• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Stellarium / stellarium / 15670918640

16 Jun 2025 02:08AM UTC coverage: 11.775% (-0.2%) from 11.931%
15670918640

push

github

alex-w
Updated data

14700 of 124846 relevant lines covered (11.77%)

18324.52 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.47
/src/core/StelCore.cpp
1
/*
2
 * Copyright (C) 2003 Fabien Chereau
3
 * Copyright (C) 2012 Matthew Gates
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA  02110-1335, USA.
18
 */
19

20
#include "StelCore.hpp"
21

22
#include "StelProjector.hpp"
23
#include "StelProjectorClasses.hpp"
24
#include "StelToneReproducer.hpp"
25
#include "StelApp.hpp"
26
#include "StelUtils.hpp"
27
#include "StelGeodesicGrid.hpp"
28
#include "StelMovementMgr.hpp"
29
#include "StelModuleMgr.hpp"
30
#include "StelPainter.hpp"
31
#include "StelLocationMgr.hpp"
32
#include "StelObserver.hpp"
33
#include "StelObjectMgr.hpp"
34
#include "Planet.hpp"
35
#include "SolarSystem.hpp"
36
#include "LandscapeMgr.hpp"
37
#include "StelTranslator.hpp"
38
#include "StelActionMgr.hpp"
39
#include "StelFileMgr.hpp"
40
#include "StelMainView.hpp"
41
#include "EphemWrapper.hpp"
42
#include "NomenclatureItem.hpp"
43
#include "precession.h"
44
#include "Star.hpp"
45

46
#include <QSettings>
47
#include <QDebug>
48
#include <QGlobalStatic>
49
#include <QMetaEnum>
50
#include <QTimeZone>
51
#include <QFile>
52
#include <QDir>
53
#include <QRegularExpression>
54
#include <QOpenGLShaderProgram>
55

56
// Init static transfo matrices
57
// See vsop87.doc:
58
const Mat4d StelCore::matJ2000ToVsop87(Mat4d::xrotation(-23.4392803055555555556*M_PI_180) * Mat4d::zrotation(0.0000275*M_PI_180));
59
const Mat4d StelCore::matVsop87ToJ2000(matJ2000ToVsop87.transpose());
60
const Mat4d StelCore::matJ2000ToGalactic(-0.054875539726, 0.494109453312, -0.867666135858, 0, -0.873437108010, -0.444829589425, -0.198076386122, 0, -0.483834985808, 0.746982251810, 0.455983795705, 0, 0, 0, 0, 1);
61
const Mat4d StelCore::matGalacticToJ2000(matJ2000ToGalactic.transpose());
62
const Mat4d StelCore::matJ2000ToSupergalactic(0.37501548, -0.89832046, 0.22887497, 0, 0.34135896, -0.09572714, -0.93504565, 0, 0.86188018, 0.42878511, 0.27075058, 0, 0, 0, 0, 1);
63
const Mat4d StelCore::matSupergalacticToJ2000(matJ2000ToSupergalactic.transpose());
64
Mat4d StelCore::matJ2000ToJ1875; // gets to be initialized in constructor.
65

66
const double StelCore::JD_SECOND = 0.000011574074074074074074;        // 1/(24*60*60)=1/86400
67
const double StelCore::JD_MINUTE = 0.00069444444444444444444;        // 1/(24*60)   =1/1440
68
const double StelCore::JD_HOUR   = 0.041666666666666666666;        // 1/24
69
const double StelCore::JD_DAY    = 1.;
70
const double StelCore::ONE_OVER_JD_SECOND = 86400;                // 86400
71
const double StelCore::TZ_ERA_BEGINNING = 2395996.5;                // December 1, 1847
72

73
Vec3d StelCore::cachedParallaxDiff = Vec3d(0.,0.,0.);
74
double StelCore::cachedParallaxJD = 0.0;
75
PlanetP StelCore::cachedParallaxPlanet;
76
Vec3d StelCore::cachedAberrationVec = Vec3d(0.,0.,0.);
77
double StelCore::cachedAberrationJD = 0.0;
78
PlanetP StelCore::cachedAberrationPlanet = Q_NULLPTR;
79

80
StelCore::StelCore()
×
81
        : skyDrawer(Q_NULLPTR)
×
82
        , movementMgr(Q_NULLPTR)
×
83
        , propMgr(Q_NULLPTR)
×
84
        , geodesicGrid(Q_NULLPTR)
×
85
        , currentProjectionType(ProjectionStereographic)
×
86
        , currentDeltaTAlgorithm(EspenakMeeus)
×
87
        , position(Q_NULLPTR)
×
88
        , flagUseNutation(true)
×
89
        , flagUseAberration(true)
×
90
        , aberrationFactor(1.0)
×
91
        , flagUseParallax(true)
×
92
        , parallaxFactor(1.0)
×
93
        , flagUseTopocentricCoordinates(true)
×
94
        , timeSpeed(JD_SECOND)
×
95
        , JD(0.,0.)
×
96
        , presetSkyTime(0.)
×
97
        , milliSecondsOfLastJDUpdate(0)
×
98
        , jdOfLastJDUpdate(0.)
×
99
        , flagUseDST(true)
×
100
        , flagUseCTZ(false)
×
101
        , startupTimeStop(false)
×
102
        , deltaTCustomNDot(-26.0)
×
103
        , deltaTCustomYear(1820.0)
×
104
        , deltaTnDot(-26.0)
×
105
        , deltaTdontUseMoon(false)
×
106
        , deltaTfunc(StelUtils::getDeltaTByEspenakMeeus)
×
107
        , deltaTstart(-1999)
×
108
        , deltaTfinish(3000)
×
109
        , de430Available(false)
×
110
        , de431Available(false)
×
111
        , de430Active(false)
×
112
        , de431Active(false)
×
113
        , de440Available(false)
×
114
        , de441Available(false)
×
115
        , de440Active(false)
×
116
        , de441Active(false)
×
117
{
118
        setObjectName("StelCore");
×
119
        registerMathMetaTypes();
×
120

121
        toneReproducer = new StelToneReproducer();
×
122
        milliSecondsOfLastJDUpdate = QDateTime::currentMSecsSinceEpoch();
×
123

124
        QSettings* conf = StelApp::getInstance().getSettings();
×
125
        // Create and initialize the default projector params
126
        QString tmpstr = conf->value("projection/viewport").toString();
×
127
        currentProjectorParams.maskType = StelProjector::stringToMaskType(tmpstr);
×
128
        const int viewport_width = conf->value("projection/viewport_width", currentProjectorParams.viewportXywh[2]).toInt();
×
129
        const int viewport_height = conf->value("projection/viewport_height", currentProjectorParams.viewportXywh[3]).toInt();
×
130
        const int viewport_x = conf->value("projection/viewport_x", 0).toInt();
×
131
        const int viewport_y = conf->value("projection/viewport_y", 0).toInt();
×
132
        currentProjectorParams.viewportXywh.set(viewport_x,viewport_y,viewport_width,viewport_height);
×
133

134
        const qreal viewportCenterX = conf->value("projection/viewport_center_x",0.5*viewport_width).toDouble();
×
135
        const qreal viewportCenterY = conf->value("projection/viewport_center_y",0.5*viewport_height).toDouble();
×
136
        currentProjectorParams.viewportCenter.set(viewportCenterX, viewportCenterY);
×
137
        const qreal viewportCenterOffsetX = conf->value("projection/viewport_center_offset_x",0.).toDouble();
×
138
        const qreal viewportCenterOffsetY = conf->value("projection/viewport_center_offset_y",0.).toDouble();
×
139
        currentProjectorParams.viewportCenterOffset.set(viewportCenterOffsetX/100., viewportCenterOffsetY/100.);
×
140

141
        currentProjectorParams.viewportFovDiameter = conf->value("projection/viewport_fov_diameter", qMin(viewport_width,viewport_height)).toDouble();
×
142
        currentProjectorParams.flipHorz = conf->value("projection/flip_horz",false).toBool();
×
143
        currentProjectorParams.flipVert = conf->value("projection/flip_vert",false).toBool();
×
144

145
        currentProjectorParams.gravityLabels = conf->value("viewing/flag_gravity_labels").toBool();
×
146
        
147
        currentProjectorParams.devicePixelsPerPixel = StelApp::getInstance().getDevicePixelsPerPixel();
×
148

149
        flagUseNutation=conf->value("astro/flag_nutation", true).toBool();
×
150
        flagUseAberration=conf->value("astro/flag_aberration", true).toBool();
×
151
        aberrationFactor=conf->value("astro/aberration_factor", 1.0).toDouble();
×
152
        flagUseParallax=conf->value("astro/flag_parallax", true).toBool();
×
153
        parallaxFactor=conf->value("astro/parallax_factor", 1.0).toDouble();
×
154
        flagUseTopocentricCoordinates=conf->value("astro/flag_topocentric_coordinates", true).toBool();
×
155
        flagUseDST=conf->value("localization/flag_dst", true).toBool();
×
156

157
        // Initialize matJ2000ToJ1875 matrix
158
        double eps1875, chi1875, omega1875, psi1875;
159
        const double jdB1875 = StelUtils::getJDFromBesselianEpoch(1875.0);
×
160
        getPrecessionAnglesVondrak(jdB1875, &eps1875, &chi1875, &omega1875, &psi1875);
×
161
        matJ2000ToJ1875 = Mat4d::xrotation(84381.406*1./3600.*M_PI/180.) * Mat4d::zrotation(-psi1875) * Mat4d::xrotation(-omega1875) * Mat4d::zrotation(chi1875);
×
162
        matJ2000ToJ1875 = matJ2000ToJ1875.transpose();
×
163
}
×
164

165

166
StelCore::~StelCore()
×
167
{
168
        delete toneReproducer; toneReproducer=Q_NULLPTR;
×
169
        delete geodesicGrid; geodesicGrid=Q_NULLPTR;
×
170
        delete skyDrawer; skyDrawer=Q_NULLPTR;
×
171
        delete position; position=Q_NULLPTR;
×
172
        cachedParallaxPlanet=Q_NULLPTR;
×
173
        cachedAberrationPlanet=Q_NULLPTR;
×
174
}
×
175

176
const QMap<QString, DitheringMode>StelCore::ditheringMap={
177
        {"disabled"   , DitheringMode::Disabled},
178
        {"color565"   , DitheringMode::Color565},
179
        {"color666"   , DitheringMode::Color666},
180
        {"color888"   , DitheringMode::Color888},
181
        {"color101010", DitheringMode::Color101010}};
182

183
DitheringMode StelCore::parseDitheringMode(const QString& str)
×
184
{
185
        const auto s=str.trimmed().toLower();
×
186
        return ditheringMap.value(s, DitheringMode::Disabled);
×
187
}
×
188

189
/*************************************************************************
190
 Load core data and initialize with default values
191
*************************************************************************/
192
void StelCore::init()
×
193
{
194
        QSettings* conf = StelApp::getInstance().getSettings();
×
195

196
        const char ditheringModeKey[] = "video/dithering_mode";
×
197
        QVariant selectedDitherFormat = conf->value(ditheringModeKey);
×
198
        if(!selectedDitherFormat.isValid())
×
199
        {
200
                constexpr char defaultValue[] = "color888";
×
201
                selectedDitherFormat = defaultValue;
×
202
                conf->setValue(ditheringModeKey, defaultValue);
×
203
        }
204
        ditheringMode = parseDitheringMode(selectedDitherFormat.toString());
×
205

206
        if (conf->childGroups().contains("location_run_once"))
×
207
                defaultLocationID = "stellarium_cli";
×
208
        else
209
                defaultLocationID = conf->value("init_location/location", "auto").toString();
×
210
        bool ok;
211
        StelLocationMgr* locationMgr = &StelApp::getInstance().getLocationMgr();
×
212
        StelLocation location=locationMgr->getLastResortLocation(); // first location: Paris. Required if no IP connection on first launch!
×
213
        if (defaultLocationID == "auto")
×
214
        {
215
                locationMgr->locationFromIP();
×
216
        }
217
        else if (defaultLocationID == "stellarium_cli")
×
218
        {
219
                location = locationMgr->locationFromCLI();
×
220
        }
221
        else if (defaultLocationID.startsWith("GPS", Qt::CaseInsensitive))
×
222
        {
223
                // The location is obtained already from init_location/last_resort_location
224
                location.name = conf->value("init_location/location").toString();
×
225
        }
226
        else
227
        {
228
                location = locationMgr->locationForString(defaultLocationID);
×
229
        }
230

231
        if (!location.isValid())
×
232
        {
233
                qWarning() << "Location" << defaultLocationID << "is unknown.";
×
234
                location = locationMgr->getLastResortLocation();
×
235
        }
236
        position = new StelObserver(location);
×
237

238
        QString ctz = conf->value("localization/time_zone", "").toString();
×
239
        if (!ctz.isEmpty())
×
240
                setUseCustomTimeZone(true);
×
241
        else
242
                ctz = getCurrentLocation().ianaTimeZone;
×
243
        setCurrentTimeZone(ctz);
×
244

245
        // Delta-T stuff
246
        // Define default algorithm for time correction (Delta T)
247
        QString tmpDT = conf->value("navigation/time_correction_algorithm", "EspenakMeeusModified").toString();
×
248
        setCurrentDeltaTAlgorithmKey(tmpDT);
×
249

250
        // Define variables of custom equation for calculation of Delta T
251
        // Default: ndot = -26.0 "/cy/cy; year = 1820; DeltaT = -20 + 32*u^2, where u = (currentYear-1820)/100
252
        setDeltaTCustomYear(conf->value("custom_time_correction/year", 1820.0).toDouble());
×
253
        setDeltaTCustomNDot(conf->value("custom_time_correction/ndot", -26.0).toDouble());
×
254
        setDeltaTCustomEquationCoefficients(Vec3d(conf->value("custom_time_correction/coefficients", "-20,0,32").toString()));
×
255

256
        // Time stuff
257
        setTimeNow();
×
258

259
        // We want to be able to handle the old style preset time, recorded as a double
260
        // jday, or as a more human readable string...
261
        QString presetTimeStr = conf->value("navigation/preset_sky_time",2451545.).toString();
×
262
        presetSkyTime = presetTimeStr.toDouble(&ok);
×
263
        if (ok)
×
264
        {
265
                qInfo().noquote() << "navigation/preset_sky_time is a double - treating as jday:" << QString::number(presetSkyTime, 'f', 5);
×
266
        }
267
        else
268
        {
269
                qWarning().noquote() << "navigation/preset_sky_time was not a double, treating as string date:" << presetTimeStr;
×
270
                presetSkyTime = StelUtils::qDateTimeToJd(QDateTime::fromString(presetTimeStr));
×
271
        }
272
        setInitTodayTime(QTime::fromString(conf->value("navigation/today_time", "22:00").toString()));
×
273
        startupTimeMode = conf->value("navigation/startup_time_mode", "actual").toString().toLower();
×
274
        if (startupTimeMode=="preset")        
×
275
                setJD(presetSkyTime - static_cast<double>(getUTCOffset(presetSkyTime)) * JD_HOUR);
×
276
        else if (startupTimeMode=="today")
×
277
                setTodayTime(getInitTodayTime());
×
278
        startupTimeStop = conf->value("navigation/startup_time_stop", false).toBool();
×
279
        if (startupTimeStop)
×
280
                setZeroTimeSpeed();
×
281

282
        // Compute transform matrices between coordinates systems
283
        updateTransformMatrices();
×
284
        updateFixedEquatorialTransformMatrices();
×
285
        connect(this, SIGNAL(locationChanged(const StelLocation&)), this, SLOT(updateFixedEquatorialTransformMatrices()));
×
286

287
        movementMgr = new StelMovementMgr(this);
×
288
        movementMgr->init();
×
289
        currentProjectorParams.fov = static_cast<float>(movementMgr->getInitFov());
×
290
        StelApp::getInstance().getModuleMgr().registerModule(movementMgr);
×
291

292
        skyDrawer = new StelSkyDrawer(this);
×
293
        skyDrawer->init();
×
294

295
        propMgr = StelApp::getInstance().getStelPropertyManager();
×
296
        propMgr->registerObject(skyDrawer);
×
297
        propMgr->registerObject(this);
×
298
        propMgr->registerObject(toneReproducer);
×
299

300
        setCurrentProjectionTypeKey(getDefaultProjectionTypeKey());
×
301
        updateMaximumFov();
×
302

303
        // activate DE430/431
304
        initEphemeridesFunctions();
×
305

306
        // Register all the core actions.
307
        QString timeGroup = N_("Date and Time");
×
308
        QString movementGroup = N_("Movement and Selection");
×
309
        QString displayGroup = N_("Display Options");
×
310
        StelActionMgr* actionsMgr = StelApp::getInstance().getStelActionManager();
×
311
        actionsMgr->addAction("actionIncrease_Time_Speed", timeGroup, N_("Increase time speed"), this, "increaseTimeSpeed()", "L");
×
312
        actionsMgr->addAction("actionDecrease_Time_Speed", timeGroup, N_("Decrease time speed"), this, "decreaseTimeSpeed()", "J");
×
313
        actionsMgr->addAction("actionIncrease_Time_Speed_Less", timeGroup, N_("Increase time speed (a little)"), this, "increaseTimeSpeedLess()", "Shift+L");
×
314
        actionsMgr->addAction("actionDecrease_Time_Speed_Less", timeGroup, N_("Decrease time speed (a little)"), this, "decreaseTimeSpeedLess()", "Shift+J");
×
315
        actionsMgr->addAction("actionSet_Real_Time_Speed", timeGroup, N_("Set normal time rate"), this, "toggleRealTimeSpeed()", "K");
×
316
        actionsMgr->addAction("actionSet_Time_Rate_Zero", timeGroup, N_("Set time rate to zero"), this, "setZeroTimeSpeed()", "7");
×
317
        actionsMgr->addAction("actionSet_Time_Reverse", timeGroup, N_("Set reverse time direction"), this, "revertTimeDirection()", "0");
×
318
        actionsMgr->addAction("actionReturn_To_Current_Time", timeGroup, N_("Set time to now"), this, "setTimeNow()", "8");
×
319
        actionsMgr->addAction("actionAdd_Solar_Minute", timeGroup, N_("Add 1 solar minute"), this, "addMinute()");
×
320
        actionsMgr->addAction("actionAdd_Solar_Hour", timeGroup, N_("Add 1 solar hour"), this, "addHour()", "Ctrl+=");
×
321
        actionsMgr->addAction("actionAdd_Solar_Day", timeGroup, N_("Add 1 solar day"), this, "addDay()", "=");
×
322
        actionsMgr->addAction("actionAdd_Solar_Week", timeGroup, N_("Add 7 solar days"), this, "addWeek()", "]");
×
323
        actionsMgr->addAction("actionSubtract_Solar_Minute", timeGroup, N_("Subtract 1 solar minute"), this, "subtractMinute()");
×
324
        actionsMgr->addAction("actionSubtract_Solar_Hour", timeGroup, N_("Subtract 1 solar hour"), this, "subtractHour()", "Ctrl+-");
×
325
        actionsMgr->addAction("actionSubtract_Solar_Day", timeGroup, N_("Subtract 1 solar day"), this, "subtractDay()", "-");
×
326
        actionsMgr->addAction("actionSubtract_Solar_Week", timeGroup, N_("Subtract 7 solar days"), this, "subtractWeek()", "[");
×
327
        actionsMgr->addAction("actionAdd_Sidereal_Day", timeGroup, N_("Add 1 sidereal day"), this, "addSiderealDay()", "Alt+=");
×
328
        actionsMgr->addAction("actionAdd_Sidereal_Week", timeGroup, N_("Add 7 sidereal days"), this, "addSiderealWeek()");
×
329
        actionsMgr->addAction("actionAdd_Sidereal_Year", timeGroup, N_("Add 1 sidereal year"), this, "addSiderealYear()", "Ctrl+Alt+Shift+]");
×
330
        actionsMgr->addAction("actionAdd_Sidereal_Century", timeGroup, N_("Add 100 sidereal years"), this, "addSiderealYears()");
×
331
        actionsMgr->addAction("actionAdd_Synodic_Month", timeGroup, N_("Add 1 synodic month"), this, "addSynodicMonth()");
×
332
        actionsMgr->addAction("actionAdd_Saros", timeGroup, N_("Add 1 saros"), this, "addSaros()");
×
333
        actionsMgr->addAction("actionAdd_Draconic_Month", timeGroup, N_("Add 1 draconic month"), this, "addDraconicMonth()");
×
334
        actionsMgr->addAction("actionAdd_Draconic_Year", timeGroup, N_("Add 1 draconic year"), this, "addDraconicYear()");
×
335
        actionsMgr->addAction("actionAdd_Anomalistic_Month", timeGroup, N_("Add 1 anomalistic month"), this, "addAnomalisticMonth()");
×
336
        actionsMgr->addAction("actionAdd_Anomalistic_Year", timeGroup, N_("Add 1 anomalistic year"), this, "addAnomalisticYear()");
×
337
        actionsMgr->addAction("actionAdd_Anomalistic_Century", timeGroup, N_("Add 100 anomalistic years"), this, "addAnomalisticYears()");
×
338
        actionsMgr->addAction("actionAdd_Mean_Tropical_Month", timeGroup, N_("Add 1 mean tropical month"), this, "addMeanTropicalMonth()");
×
339
        actionsMgr->addAction("actionAdd_Mean_Tropical_Year", timeGroup, N_("Add 1 mean tropical year"), this, "addMeanTropicalYear()");
×
340
        actionsMgr->addAction("actionAdd_Mean_Tropical_Century", timeGroup, N_("Add 100 mean tropical years"), this, "addMeanTropicalYears()");
×
341
        actionsMgr->addAction("actionAdd_Tropical_Year", timeGroup, N_("Add 1 tropical year"), this, "addTropicalYear()");
×
342
        actionsMgr->addAction("actionAdd_Julian_Year", timeGroup, N_("Add 1 Julian year"), this, "addJulianYear()");
×
343
        actionsMgr->addAction("actionAdd_Julian_Century", timeGroup, N_("Add 1 Julian century"), this, "addJulianYears()");
×
344
        actionsMgr->addAction("actionAdd_Gaussian_Year", timeGroup, N_("Add 1 Gaussian year"), this, "addGaussianYear()");
×
345
        actionsMgr->addAction("actionAdd_Calendar_Month", timeGroup, N_("Add 1 calendar month"), this, "addCalendarMonth()");
×
346
        actionsMgr->addAction("actionAdd_Calendar_Year", timeGroup, N_("Add 1 calendar year"), this, "addCalendarYear()");
×
347
        actionsMgr->addAction("actionAdd_Calendar_Decade", timeGroup, N_("Add 10 calendar years"), this, "addCalendarDecade()");
×
348
        actionsMgr->addAction("actionAdd_Calendar_Century", timeGroup, N_("Add 100 calendar years"), this, "addCalendarCentury()");
×
349
        actionsMgr->addAction("actionAdd_Great_Year", timeGroup, N_("Add 1 Great year"), this, "addGreatYear()");
×
350
        actionsMgr->addAction("actionSubtract_Sidereal_Day", timeGroup, N_("Subtract 1 sidereal day"), this, "subtractSiderealDay()", "Alt+-");
×
351
        actionsMgr->addAction("actionSubtract_Sidereal_Week", timeGroup, N_("Subtract 7 sidereal days"), this, "subtractSiderealWeek()");
×
352
        actionsMgr->addAction("actionSubtract_Sidereal_Year", timeGroup, N_("Subtract 1 sidereal year"), this, "subtractSiderealYear()", "Ctrl+Alt+Shift+[");
×
353
        actionsMgr->addAction("actionSubtract_Sidereal_Century", timeGroup, N_("Subtract 100 sidereal years"), this, "subtractSiderealYears()");
×
354
        actionsMgr->addAction("actionSubtract_Synodic_Month", timeGroup, N_("Subtract 1 synodic month"), this, "subtractSynodicMonth()");
×
355
        actionsMgr->addAction("actionSubtract_Saros", timeGroup, N_("Subtract 1 saros"), this, "subtractSaros()");
×
356
        actionsMgr->addAction("actionSubtract_Draconic_Month", timeGroup, N_("Subtract 1 draconic month"), this, "subtractDraconicMonth()");
×
357
        actionsMgr->addAction("actionSubtract_Draconic_Year", timeGroup, N_("Subtract 1 draconic year"), this, "subtractDraconicYear()");
×
358
        actionsMgr->addAction("actionSubtract_Anomalistic_Month", timeGroup, N_("Subtract 1 anomalistic month"), this, "subtractAnomalisticMonth()");
×
359
        actionsMgr->addAction("actionSubtract_Anomalistic_Year", timeGroup, N_("Subtract 1 anomalistic year"), this, "subtractAnomalisticYear()");
×
360
        actionsMgr->addAction("actionSubtract_Anomalistic_Century", timeGroup, N_("Subtract 100 anomalistic years"), this, "subtractAnomalisticYears()");
×
361
        actionsMgr->addAction("actionSubtract_Mean_Tropical_Month", timeGroup, N_("Subtract 1 mean tropical month"), this, "subtractMeanTropicalMonth()");
×
362
        actionsMgr->addAction("actionSubtract_Mean_Tropical_Year", timeGroup, N_("Subtract 1 mean tropical year"), this, "subtractMeanTropicalYear()");
×
363
        actionsMgr->addAction("actionSubtract_Mean_Tropical_Century", timeGroup, N_("Subtract 100 mean tropical years"), this, "subtractMeanTropicalYears()");
×
364
        actionsMgr->addAction("actionSubtract_Tropical_Year", timeGroup, N_("Subtract 1 tropical year"), this, "subtractTropicalYear()");
×
365
        actionsMgr->addAction("actionSubtract_Julian_Year", timeGroup, N_("Subtract 1 Julian year"), this, "subtractJulianYear()");
×
366
        actionsMgr->addAction("actionSubtract_Julian_Century", timeGroup, N_("Subtract 1 Julian century"), this, "subtractJulianYears()");
×
367
        actionsMgr->addAction("actionSubtract_Gaussian_Year", timeGroup, N_("Subtract 1 Gaussian year"), this, "subtractGaussianYear()");
×
368
        actionsMgr->addAction("actionSubtract_Calendar_Month", timeGroup, N_("Subtract 1 calendar month"), this, "subtractCalendarMonth()");
×
369
        actionsMgr->addAction("actionSubtract_Calendar_Year", timeGroup, N_("Subtract 1 calendar year"), this, "subtractCalendarYear()");
×
370
        actionsMgr->addAction("actionSubtract_Calendar_Decade", timeGroup, N_("Subtract 10 calendar years"), this, "subtractCalendarDecade()");
×
371
        actionsMgr->addAction("actionSubtract_Calendar_Century", timeGroup, N_("Subtract 100 calendar years"), this, "subtractCalendarCentury()");
×
372
        actionsMgr->addAction("actionSubtract_Great_Year", timeGroup, N_("Subtract 1 Great year"), this, "subtractGreatYear()");
×
373

374
        actionsMgr->addAction("actionSet_Home_Planet_To_Selected", movementGroup, N_("Set home planet to selected planet"), this, "moveObserverToSelected()", "Ctrl+G");
×
375
        actionsMgr->addAction("actionGo_Home_Global", movementGroup, N_("Go to home"), this, "returnToHome()", "Ctrl+H");
×
376

377
        actionsMgr->addAction("actionHorizontal_Flip", displayGroup, N_("Flip scene horizontally"), this, "flipHorz", "Ctrl+Shift+H", "", true);
×
378
        actionsMgr->addAction("actionVertical_Flip", displayGroup, N_("Flip scene vertically"), this, "flipVert", "Ctrl+Shift+V", "", true);
×
379
}
×
380

381
QString StelCore::getDefaultProjectionTypeKey() const
×
382
{
383
        QSettings* conf = StelApp::getInstance().getSettings();
×
384
        return conf->value("projection/type", "ProjectionStereographic").toString();
×
385
}
386

387
// Get the shared instance of StelGeodesicGrid.
388
// The returned instance is guaranteed to allow for at least maxLevel levels
389
const StelGeodesicGrid* StelCore::getGeodesicGrid(int maxLevel) const
×
390
{
391
        if (geodesicGrid==Q_NULLPTR)
×
392
        {
393
                geodesicGrid = new StelGeodesicGrid(maxLevel);
×
394
        }
395
        else if (maxLevel>geodesicGrid->getMaxLevel())
×
396
        {
397
                delete geodesicGrid;
×
398
                geodesicGrid = new StelGeodesicGrid(maxLevel);
×
399
        }
400
        return geodesicGrid;
×
401
}
402

403
StelProjectorP StelCore::getProjection2d() const
×
404
{
405
        StelProjectorP prj(new StelProjector2d());
×
406
        prj->init(currentProjectorParams);
×
407
        return prj;
×
408
}
×
409

410
StelProjectorP StelCore::getProjection(StelProjector::ModelViewTranformP modelViewTransform, ProjectionType projType) const
×
411
{
412
        if (projType==static_cast<ProjectionType>(1000))
×
413
                projType = currentProjectionType;
×
414

415
        StelProjectorP prj;
×
416
        switch (projType)
×
417
        {
418
                case ProjectionPerspective:
×
419
                        prj = StelProjectorP(new StelProjectorPerspective(modelViewTransform));
×
420
                        break;
×
421
                case ProjectionEqualArea:
×
422
                        prj = StelProjectorP(new StelProjectorEqualArea(modelViewTransform));
×
423
                        break;
×
424
                case ProjectionStereographic:
×
425
                        prj = StelProjectorP(new StelProjectorStereographic(modelViewTransform));
×
426
                        break;
×
427
                case ProjectionFisheye:
×
428
                        prj = StelProjectorP(new StelProjectorFisheye(modelViewTransform));
×
429
                        break;
×
430
                case ProjectionHammer:
×
431
                        prj = StelProjectorP(new StelProjectorHammer(modelViewTransform));
×
432
                        break;
×
433
                case ProjectionMollweide:
×
434
                        prj = StelProjectorP(new StelProjectorMollweide(modelViewTransform));
×
435
                        break;
×
436
                case ProjectionCylinder:
×
437
                        prj = StelProjectorP(new StelProjectorCylinder(modelViewTransform));
×
438
                        break;
×
439
                case ProjectionCylinderFill:
×
440
                        prj = StelProjectorP(new StelProjectorCylinderFill(modelViewTransform));
×
441
                        break;
×
442
                case ProjectionMercator:
×
443
                        prj = StelProjectorP(new StelProjectorMercator(modelViewTransform));
×
444
                        break;
×
445
                case ProjectionOrthographic:
×
446
                        prj = StelProjectorP(new StelProjectorOrthographic(modelViewTransform));
×
447
                        break;
×
448
                case ProjectionSinusoidal:
×
449
                        prj = StelProjectorP(new StelProjectorSinusoidal(modelViewTransform));
×
450
                        break;
×
451
                case ProjectionMiller:
×
452
                        prj = StelProjectorP(new StelProjectorMiller(modelViewTransform));
×
453
                        break;
×
454
                default:
×
455
                        qWarning() << "Unknown projection type: " << static_cast<int>(projType) << "using ProjectionStereographic instead";
×
456
                        prj = StelProjectorP(new StelProjectorStereographic(modelViewTransform));
×
457
                        Q_ASSERT(0);
×
458
        }
459
        prj->init(currentProjectorParams);
×
460
        return prj;
×
461
}
×
462

463
// Get an instance of projector using the current display parameters from Navigation, StelMovementMgr
464
StelProjectorP StelCore::getProjection(FrameType frameType, RefractionMode refractionMode) const
×
465
{
466
        switch (frameType)
×
467
        {
468
                case FrameAltAz:
×
469
                        return getProjection(getAltAzModelViewTransform(refractionMode));
×
470
                case FrameHeliocentricEclipticJ2000:
×
471
                        return getProjection(getHeliocentricEclipticModelViewTransform(refractionMode));
×
472
                case FrameObservercentricEclipticJ2000:
×
473
                        return getProjection(getObservercentricEclipticJ2000ModelViewTransform(refractionMode));
×
474
                case FrameObservercentricEclipticOfDate:
×
475
                        return getProjection(getObservercentricEclipticOfDateModelViewTransform(refractionMode));
×
476
                case FrameEquinoxEqu:
×
477
                        return getProjection(getEquinoxEquModelViewTransform(refractionMode));
×
478
                case FrameFixedEquatorial:
×
479
                        return getProjection(getFixedEquatorialModelViewTransform(refractionMode));
×
480
                case FrameJ2000:
×
481
                        return getProjection(getJ2000ModelViewTransform(refractionMode));
×
482
                case FrameGalactic:
×
483
                        return getProjection(getGalacticModelViewTransform(refractionMode));
×
484
                case FrameSupergalactic:
×
485
                        return getProjection(getSupergalacticModelViewTransform(refractionMode));
×
486
                default:
×
487
                        qDebug() << "Unknown reference frame type: " << static_cast<int>(frameType) << ".";
×
488
        }
489
        Q_ASSERT(0);
×
490
        return getProjection2d();
491
}
492

493
SphericalCap StelCore::getVisibleSkyArea() const
×
494
{
495
        const LandscapeMgr* landscapeMgr = GETSTELMODULE(LandscapeMgr);
×
496
        Vec3d up(0, 0, 1);
×
497
        up = altAzToJ2000(up, RefractionOff);
×
498
        
499
        // Limit star drawing to above landscape's minimal altitude (was const=-0.035, Bug lp:1469407)
500
        if (landscapeMgr->getIsLandscapeFullyVisible())
×
501
        {
502
                return SphericalCap(up, landscapeMgr->getLandscapeSinMinAltitudeLimit());
×
503
        }
504
        return SphericalCap(up, -1.);
×
505
}
506

507
// Handle the resizing of the window
508
void StelCore::windowHasBeenResized(qreal x, qreal y, qreal width, qreal height)
×
509
{
510
        // Maximize display when resized since it invalidates previous options anyway
511
        currentProjectorParams.viewportXywh.set(qRound(x), qRound(y), qRound(width), qRound(height));
×
512
        currentProjectorParams.viewportCenter.set(x+(0.5+currentProjectorParams.viewportCenterOffset.v[0])*width, y+(0.5+currentProjectorParams.viewportCenterOffset.v[1])*height);
×
513
        currentProjectorParams.viewportFovDiameter = qMin(width,height);
×
514

515
        if (currentProjectionType==ProjectionType::ProjectionCylinderFill)
×
516
        {
517
                currentProjectorParams.widthStretch=0.5*width/height;
×
518
                currentProjectorParams.viewportFovDiameter = height;
×
519
        }
520
}
×
521

522
/*************************************************************************
523
 Update all the objects in function of the time
524
*************************************************************************/
525
void StelCore::update(double deltaTime)
×
526
{
527
        // Update the position of observation and time and recompute planet positions etc...
528
        updateTime(deltaTime);
×
529

530
        // Transform matrices between coordinates systems
531
        updateTransformMatrices();
×
532

533
        // Update direction of vision/Zoom level
534
        movementMgr->updateMotion(deltaTime);
×
535

536
        currentProjectorParams.fov = static_cast<float>(movementMgr->getCurrentFov());
×
537

538
        skyDrawer->update(deltaTime);
×
539
}
×
540

541

542
/*************************************************************************
543
 Execute all the pre-drawing functions
544
*************************************************************************/
545
void StelCore::preDraw()
×
546
{
547
        // Init openGL viewing with fov, screen size and clip planes
548
        currentProjectorParams.zNear = 0.000001;
×
549
        currentProjectorParams.zFar = 500.;
×
550

551
        // Clear the render buffer.
552
        // Here we can set a sky background color if really wanted (art
553
        // applications. Astronomical sky should be 0/0/0/0)
554
        Vec3f backColor = StelMainView::getInstance().getSkyBackgroundColor();
×
555
        QOpenGLFunctions* gl = QOpenGLContext::currentContext()->functions();
×
556
        gl->glClearColor(backColor[0], backColor[1], backColor[2], 0.f);
×
557
        gl->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
×
558

559
        skyDrawer->preDraw();
×
560
}
×
561

562

563
/*************************************************************************
564
 Update core state after drawing modules
565
*************************************************************************/
566
void StelCore::postDraw()
×
567
{
568
        StelPainter sPainter(getProjection(StelCore::FrameJ2000));
×
569
        sPainter.drawViewportShape();
×
570
}
×
571

572
void StelCore::updateMaximumFov()
×
573
{
574
        const float savedFov = currentProjectorParams.fov;
×
575
        currentProjectorParams.fov = 0.0001f;        // Avoid crash
×
576
        const float newMaxFov = getProjection(StelProjector::ModelViewTranformP(new StelProjector::Mat4dTransform(Mat4d::identity(),Mat4d::identity())))->getMaxFov();
×
577
        movementMgr->setMaxFov(static_cast<double>(newMaxFov));
×
578
        currentProjectorParams.fov = qMin(newMaxFov, savedFov);
×
579
}
×
580

581
void StelCore::setCurrentProjectionType(ProjectionType type)
×
582
{
583
        if(type!=currentProjectionType)
×
584
        {
585
                QSettings* conf = StelApp::getInstance().getSettings();
×
586

587
                currentProjectionType=type;
×
588
                updateMaximumFov();
×
589
                if (currentProjectionType==ProjectionType::ProjectionCylinderFill)
×
590
                {
591
                        // Save whatever stretch is present into config.ini. This value is saved just temporarily until switching back to another projection and will not be loaded on startup.
592
                        // (To configure a stretch at startup, use startup.ssc script.)
593
                        conf->setValue("projection/width_stretch", currentProjectorParams.widthStretch);
×
594
                        currentProjectorParams.fov=180.f;
×
595
                        currentProjectorParams.widthStretch=0.5*currentProjectorParams.viewportXywh[2]/currentProjectorParams.viewportXywh[3];
×
596
                        currentProjectorParams.viewportFovDiameter = currentProjectorParams.viewportXywh[3];
×
597
                        Q_ASSERT(movementMgr);
×
598
                        movementMgr->setViewportVerticalOffsetTarget(0.);
×
599
                        movementMgr->zoomTo(180., 0.5);
×
600
                }
601
                else
602
                {
603
                        // reset to what is stored in config.ini
604
                        currentProjectorParams.widthStretch=conf->value("projection/width_stretch", 1.0).toDouble();
×
605
                }
606

607
                emit currentProjectionTypeChanged(type);
×
608
                emit currentProjectionTypeKeyChanged(getCurrentProjectionTypeKey());
×
609
                emit currentProjectionNameI18nChanged(getCurrentProjectionNameI18n());
×
610
        }
611
}
×
612

613
StelCore::ProjectionType StelCore::getCurrentProjectionType() const
×
614
{
615
        return currentProjectionType;
×
616
}
617

618
//! Set the current projection type to use
619
void StelCore::setCurrentProjectionTypeKey(QString key)
×
620
{
621
        const QMetaEnum& en = metaObject()->enumerator(metaObject()->indexOfEnumerator("ProjectionType"));
×
622
        ProjectionType newType = static_cast<ProjectionType>(en.keyToValue(key.toLatin1().data()));
×
623
        if (newType<0)
×
624
        {
625
                qWarning() << "Unknown projection type: " << key << "setting \"ProjectionStereographic\" instead";
×
626
                key="ProjectionStereographic";
×
627
                newType = ProjectionStereographic;
×
628
        }
629
        StelApp::immediateSave("projection/type", key);
×
630
        setCurrentProjectionType(newType);
×
631
}
×
632

633
//! Get the current Mapping used by the Projection
634
QString StelCore::getCurrentProjectionTypeKey(void) const
×
635
{
636
        return metaObject()->enumerator(metaObject()->indexOfEnumerator("ProjectionType")).key(currentProjectionType);
×
637
}
638

639
QString StelCore::getCurrentProjectionNameI18n() const
×
640
{
641
        return projectionTypeKeyToNameI18n(getCurrentProjectionTypeKey());
×
642
}
643

644
//! Get the list of all the available projections
645
QStringList StelCore::getAllProjectionTypeKeys() const
×
646
{
647
        const QMetaEnum& en = metaObject()->enumerator(metaObject()->indexOfEnumerator("ProjectionType"));
×
648
        QStringList l;
×
649
        for (int i=0;i<en.keyCount();++i)
×
650
                l << en.key(i);
×
651
        return l;
×
652
}
×
653

654
void StelCore::setMaskType(StelProjector::StelProjectorMaskType m)
×
655
{
656
        currentProjectorParams.maskType = m;
×
657
}
×
658

659
void StelCore::setFlagGravityLabels(bool gravity)
×
660
{
661
        if (currentProjectorParams.gravityLabels != gravity)
×
662
        {
663
                currentProjectorParams.gravityLabels = gravity;
×
664
                StelApp::immediateSave("viewing/flag_gravity_labels", gravity);
×
665
                emit flagGravityLabelsChanged(gravity);
×
666
        }
667
}
×
668

669
bool StelCore::getFlagGravityLabels() const
×
670
{
671
        return currentProjectorParams.gravityLabels;
×
672
}
673

674
void StelCore::setDefaultAngleForGravityText(float a)
×
675
{
676
        currentProjectorParams.defaultAngleForGravityText = a;
×
677
}
×
678

679
void StelCore::setFlipHorz(bool flip)
×
680
{
681
        if (currentProjectorParams.flipHorz != flip)
×
682
        {
683
                currentProjectorParams.flipHorz = flip;
×
684
                StelApp::immediateSave("projection/flip_horz", flip);
×
685
                emit flipHorzChanged(flip);
×
686
        }
687
}
×
688

689
void StelCore::setFlipVert(bool flip)
×
690
{
691
        if (currentProjectorParams.flipVert != flip)
×
692
        {
693
                currentProjectorParams.flipVert = flip;
×
694
                StelApp::immediateSave("projection/flip_vert", flip);
×
695
                emit flipVertChanged(flip);
×
696
        }
697
}
×
698

699
bool StelCore::getFlipHorz(void) const
×
700
{
701
        return currentProjectorParams.flipHorz;
×
702
}
703

704
bool StelCore::getFlipVert(void) const
×
705
{
706
        return currentProjectorParams.flipVert;
×
707
}
708

709
// Get current value for horizontal viewport offset [-50...50]
710
double StelCore::getViewportHorizontalOffset(void) const
×
711
{
712
        return (currentProjectorParams.viewportCenterOffset[0] * 100.0);
×
713
}
714
// Set horizontal viewport offset. Argument will be clamped to be inside [-50...50]
715
void StelCore::setViewportHorizontalOffset(double newOffsetPct)
×
716
{
717
        currentProjectorParams.viewportCenterOffset[0]=0.01* qBound(-50., newOffsetPct, 50.);
×
718
        currentProjectorParams.viewportCenter.set(currentProjectorParams.viewportXywh[0]+(0.5+currentProjectorParams.viewportCenterOffset.v[0])*currentProjectorParams.viewportXywh[2],
×
719
                                                currentProjectorParams.viewportXywh[1]+(0.5+currentProjectorParams.viewportCenterOffset.v[1])*currentProjectorParams.viewportXywh[3]);
×
720
}
×
721

722
// Get current value for vertical viewport offset [-50...50]
723
double StelCore::getViewportVerticalOffset(void) const
×
724
{
725
        return (currentProjectorParams.viewportCenterOffset[1] * 100.0);
×
726
}
727
// Set vertical viewport offset. Argument will be clamped to be inside [-50...50]
728
void StelCore::setViewportVerticalOffset(double newOffsetPct)
×
729
{
730
        currentProjectorParams.viewportCenterOffset[1]=0.01* qBound(-50., newOffsetPct, 50.);
×
731
        currentProjectorParams.viewportCenter.set(currentProjectorParams.viewportXywh[0]+(0.5+currentProjectorParams.viewportCenterOffset.v[0])*currentProjectorParams.viewportXywh[2],
×
732
                                                currentProjectorParams.viewportXywh[1]+(0.5+currentProjectorParams.viewportCenterOffset.v[1])*currentProjectorParams.viewportXywh[3]);
×
733
}
×
734

735
// Set both viewport offsets. Arguments will be clamped to be inside [-50...50]. I (GZ) hope this will avoid some of the shaking.
736
void StelCore::setViewportOffset(double newHorizontalOffsetPct, double newVerticalOffsetPct)
×
737
{
738
        currentProjectorParams.viewportCenterOffset[0]=0.01* qBound(-50., newHorizontalOffsetPct, 50.);
×
739
        currentProjectorParams.viewportCenterOffset[1]=0.01* qBound(-50., newVerticalOffsetPct,   50.);
×
740
        currentProjectorParams.viewportCenter.set(currentProjectorParams.viewportXywh[0]+(0.5+currentProjectorParams.viewportCenterOffset.v[0])*currentProjectorParams.viewportXywh[2],
×
741
                                                currentProjectorParams.viewportXywh[1]+(0.5+currentProjectorParams.viewportCenterOffset.v[1])*currentProjectorParams.viewportXywh[3]);
×
742
}
×
743

744
void StelCore::setViewportStretch(float stretch)
×
745
{
746
        currentProjectorParams.widthStretch=static_cast<qreal>(qMax(0.001f, stretch));
×
747
}
×
748

749
QString StelCore::getDefaultLocationID() const
×
750
{
751
        return defaultLocationID;
×
752
}
753

754
QString StelCore::projectionTypeKeyToNameI18n(const QString& key) const
×
755
{
756
        const QMetaEnum& en = metaObject()->enumerator(metaObject()->indexOfEnumerator("ProjectionType"));
×
757
        QString s(getProjection(StelProjector::ModelViewTranformP(new StelProjector::Mat4dTransform(Mat4d::identity(),Mat4d::identity())), static_cast<ProjectionType>(en.keyToValue(key.toLatin1())))->getNameI18());
×
758
        return s;
×
759
}
760

761
QString StelCore::projectionNameI18nToTypeKey(const QString& nameI18n) const
×
762
{
763
        const QMetaEnum& en = metaObject()->enumerator(metaObject()->indexOfEnumerator("ProjectionType"));
×
764
        for (int i=0;i<en.keyCount();++i)
×
765
        {
766
                if (getProjection(StelProjector::ModelViewTranformP(new StelProjector::Mat4dTransform(Mat4d::identity(),Mat4d::identity())), static_cast<ProjectionType>(i))->getNameI18()==nameI18n)
×
767
                        return en.valueToKey(i);
×
768
        }
769
        // Unknown translated name
770
        Q_ASSERT(0);
×
771
        return en.valueToKey(ProjectionStereographic);
772
}
773

774
StelProjector::StelProjectorParams StelCore::getCurrentStelProjectorParams() const
×
775
{
776
        return currentProjectorParams;
×
777
}
778

779
void StelCore::setCurrentStelProjectorParams(const StelProjector::StelProjectorParams& newParams)
×
780
{
781
        currentProjectorParams=newParams;
×
782
}
×
783

784
void StelCore::lookAtJ2000(const Vec3d& pos, const Vec3d& aup)
×
785
{
786
        Vec3d f(j2000ToAltAz(pos, RefractionOff));
×
787
        Vec3d up(j2000ToAltAz(aup, RefractionOff));
×
788
        f.normalize();
×
789
        up.normalize();
×
790

791
        // Update the model view matrix
792
        Vec3d s(f^up);        // y vector
×
793
        s.normalize();
×
794
        Vec3d u(s^f);        // Up vector in AltAz coordinates
×
795
        u.normalize();
×
796
        matAltAzModelView.set(s[0],u[0],-f[0],0.,
×
797
                              s[1],u[1],-f[1],0.,
×
798
                              s[2],u[2],-f[2],0.,
×
799
                              0.,0.,0.,1.);
800
        invertMatAltAzModelView = matAltAzModelView.inverse();
×
801
}
×
802

803
//void StelCore::setMatAltAzModelView(const Mat4d& mat)
804
//{
805
//        matAltAzModelView = mat;
806
//        invertMatAltAzModelView = matAltAzModelView.inverse();
807
//}
808

809
Vec3d StelCore::altAzToEquinoxEqu(const Vec3d& v, RefractionMode refMode) const
×
810
{
811
        if (refMode==RefractionOff || skyDrawer==Q_NULLPTR || (refMode==RefractionAuto && skyDrawer->getFlagHasAtmosphere()==false))
×
812
                return matAltAzToEquinoxEqu*v;
×
813
        Vec3d r(v);
×
814
        skyDrawer->getRefraction().backward(r);
×
815
        r.transfo4d(matAltAzToEquinoxEqu);
×
816
        return r;
×
817
}
818

819
Vec3d StelCore::equinoxEquToAltAz(const Vec3d& v, RefractionMode refMode) const
×
820
{
821
        if (refMode==RefractionOff || skyDrawer==Q_NULLPTR || (refMode==RefractionAuto && skyDrawer->getFlagHasAtmosphere()==false))
×
822
                return matEquinoxEquToAltAz*v;
×
823
        Vec3d r(v);
×
824
        r.transfo4d(matEquinoxEquToAltAz);
×
825
        skyDrawer->getRefraction().forward(r);
×
826
        return r;
×
827
}
828

829
Vec3d StelCore::altAzToJ2000(const Vec3d& v, RefractionMode refMode) const
×
830
{
831
        if (refMode==RefractionOff || skyDrawer==Q_NULLPTR || (refMode==RefractionAuto && skyDrawer->getFlagHasAtmosphere()==false))
×
832
                return matEquinoxEquDateToJ2000*matAltAzToEquinoxEqu*v;
×
833
        Vec3d r(v);
×
834
        skyDrawer->getRefraction().backward(r);
×
835
        r.transfo4d(matEquinoxEquDateToJ2000*matAltAzToEquinoxEqu);
×
836
        return r;
×
837
}
838

839
Vec3d StelCore::j2000ToAltAz(const Vec3d& v, RefractionMode refMode) const
×
840
{
841
        if (refMode==RefractionOff || skyDrawer==Q_NULLPTR || (refMode==RefractionAuto && skyDrawer->getFlagHasAtmosphere()==false))
×
842
                return matJ2000ToAltAz*v;
×
843
        Vec3d r(v);
×
844
        r.transfo4d(matJ2000ToAltAz);
×
845
        skyDrawer->getRefraction().forward(r);
×
846
        return r;
×
847
}
848

849
Vec3d StelCore::galacticToJ2000(const Vec3d& v) const
×
850
{
851
        return matGalacticToJ2000*v;
×
852
}
853

854
Vec3d StelCore::supergalacticToJ2000(const Vec3d& v) const
×
855
{
856
        return matSupergalacticToJ2000*v;
×
857
}
858

859
Vec3d StelCore::equinoxEquToJ2000(const Vec3d& v, RefractionMode refMode) const
×
860
{
861
        if (refMode==RefractionOff || skyDrawer==Q_NULLPTR || (refMode==RefractionAuto && skyDrawer->getFlagHasAtmosphere()==false))
×
862
                return matEquinoxEquDateToJ2000*v;
×
863
        Vec3d r(v);
×
864
        r.transfo4d(matEquinoxEquToAltAz);
×
865
        skyDrawer->getRefraction().backward(r);
×
866
        r.transfo4d(matAltAzToJ2000);
×
867
        return r;
×
868
}
869

870
Vec3d StelCore::j2000ToEquinoxEqu(const Vec3d& v, RefractionMode refMode) const
×
871
{
872
        if (refMode==RefractionOff || skyDrawer==Q_NULLPTR || (refMode==RefractionAuto && skyDrawer->getFlagHasAtmosphere()==false))
×
873
                return matJ2000ToEquinoxEqu*v;
×
874
        Vec3d r(v);
×
875
        r.transfo4d(matJ2000ToAltAz);
×
876
        skyDrawer->getRefraction().forward(r);
×
877
        r.transfo4d(matAltAzToEquinoxEqu);
×
878
        return r;
×
879
}
880

881
Vec3d StelCore::j2000ToJ1875(const Vec3d& v) const
×
882
{
883
        return matJ2000ToJ1875*v;
×
884
}
885

886
Vec3d StelCore::j1875ToJ2000(const Vec3d& v) const
×
887
{
888
        return matJ2000ToJ1875.transpose()*v;
×
889
}
890

891
Vec3d StelCore::j2000ToGalactic(const Vec3d& v) const
×
892
{
893
        return matJ2000ToGalactic*v;
×
894
}
895

896
Vec3d StelCore::j2000ToSupergalactic(const Vec3d& v) const
×
897
{
898
        return matJ2000ToSupergalactic*v;
×
899
}
900

901
//! Transform vector from heliocentric ecliptic coordinate to altazimuthal
902
Vec3d StelCore::heliocentricEclipticToAltAz(const Vec3d& v, RefractionMode refMode) const
×
903
{
904
        if (refMode==RefractionOff || skyDrawer==Q_NULLPTR || (refMode==RefractionAuto && skyDrawer->getFlagHasAtmosphere()==false))
×
905
                return matHeliocentricEclipticJ2000ToAltAz*v;
×
906
        Vec3d r(v);
×
907
        r.transfo4d(matHeliocentricEclipticJ2000ToAltAz);
×
908
        skyDrawer->getRefraction().forward(r);
×
909
        return r;
×
910
}
911

912
//! Transform from heliocentric coordinate to equatorial at current equinox (for the planet where the observer stands)
913
Vec3d StelCore::heliocentricEclipticToEquinoxEqu(const Vec3d& v) const
×
914
{
915
        return matHeliocentricEclipticToEquinoxEqu*v;
×
916
}
917

918
/*
919
//! Transform vector from heliocentric coordinate to false equatorial : equatorial
920
//! coordinate but centered on the observer position (useful for objects close to earth)
921
//! Unused as of V0.13
922
Vec3d StelCore::heliocentricEclipticToEarthPosEquinoxEqu(const Vec3d& v) const
923
{
924
        return matAltAzToEquinoxEqu*matHeliocentricEclipticToAltAz*v;
925
}
926
*/
927

928
StelProjector::ModelViewTranformP StelCore::getHeliocentricEclipticModelViewTransform(RefractionMode refMode) const
×
929
{
930
        if (refMode==RefractionOff || skyDrawer==Q_NULLPTR || (refMode==RefractionAuto && skyDrawer->getFlagHasAtmosphere()==false))
×
931
                return StelProjector::ModelViewTranformP(new StelProjector::Mat4dTransform(matAltAzModelView,matHeliocentricEclipticJ2000ToAltAz));
×
932
        Refraction* refr = new Refraction(skyDrawer->getRefraction());
×
933
        // The pretransform matrix will convert from input coordinates to AltAz needed by the refraction function.
934
        refr->setPreTransfoMat(matHeliocentricEclipticJ2000ToAltAz);
×
935
        refr->setPostTransfoMat(matAltAzModelView);
×
936
        return StelProjector::ModelViewTranformP(refr);
×
937
}
938

939
//! Get the modelview matrix for observer-centric ecliptic J2000 (Vsop87A) drawing
940
StelProjector::ModelViewTranformP StelCore::getObservercentricEclipticJ2000ModelViewTransform(RefractionMode refMode) const
×
941
{
942
        if (refMode==RefractionOff || skyDrawer==Q_NULLPTR || (refMode==RefractionAuto && skyDrawer->getFlagHasAtmosphere()==false))
×
943
                return StelProjector::ModelViewTranformP(new StelProjector::Mat4dTransform(matAltAzModelView,matJ2000ToAltAz*matVsop87ToJ2000));
×
944
        Refraction* refr = new Refraction(skyDrawer->getRefraction());
×
945
        // The pretransform matrix will convert from input coordinates to AltAz needed by the refraction function.
946
        refr->setPreTransfoMat(matJ2000ToAltAz*matVsop87ToJ2000);
×
947
        refr->setPostTransfoMat(matAltAzModelView);
×
948
        return StelProjector::ModelViewTranformP(refr);
×
949
}
950

951
//! Get the modelview matrix for observer-centric ecliptic-of-date drawing
952
StelProjector::ModelViewTranformP StelCore::getObservercentricEclipticOfDateModelViewTransform(RefractionMode refMode) const
×
953
{
954
        double eps_A=getPrecessionAngleVondrakCurrentEpsilonA();
×
955
        if (refMode==RefractionOff || skyDrawer==Q_NULLPTR || (refMode==RefractionAuto && skyDrawer->getFlagHasAtmosphere()==false))
×
956
                return StelProjector::ModelViewTranformP(new StelProjector::Mat4dTransform(matAltAzModelView,matEquinoxEquToAltAz* Mat4d::xrotation(eps_A)));
×
957
        Refraction* refr = new Refraction(skyDrawer->getRefraction());
×
958
        // The pretransform matrix will convert from input coordinates to AltAz needed by the refraction function.
959
        refr->setPreTransfoMat(matEquinoxEquToAltAz* Mat4d::xrotation(eps_A));
×
960
        refr->setPostTransfoMat(matAltAzModelView);
×
961
        return StelProjector::ModelViewTranformP(refr);
×
962
}
963

964
//! Get the modelview matrix for observer-centric equatorial at equinox drawing
965
StelProjector::ModelViewTranformP StelCore::getEquinoxEquModelViewTransform(RefractionMode refMode) const
×
966
{
967
        if (refMode==RefractionOff || skyDrawer==Q_NULLPTR || (refMode==RefractionAuto && skyDrawer->getFlagHasAtmosphere()==false))
×
968
                return StelProjector::ModelViewTranformP(new StelProjector::Mat4dTransform(matAltAzModelView,matEquinoxEquToAltAz));
×
969
        Refraction* refr = new Refraction(skyDrawer->getRefraction());
×
970
        // The pretransform matrix will convert from input coordinates to AltAz needed by the refraction function.
971
        refr->setPreTransfoMat(matEquinoxEquToAltAz);
×
972
        refr->setPostTransfoMat(matAltAzModelView);
×
973
        return StelProjector::ModelViewTranformP(refr);
×
974
}
975

976
//! Get the modelview matrix for observer-centric fixed equatorial drawing
977
StelProjector::ModelViewTranformP StelCore::getFixedEquatorialModelViewTransform(RefractionMode refMode) const
×
978
{
979
        if (refMode==RefractionOff || skyDrawer==Q_NULLPTR || (refMode==RefractionAuto && skyDrawer->getFlagHasAtmosphere()==false))
×
980
                return StelProjector::ModelViewTranformP(new StelProjector::Mat4dTransform(matAltAzModelView,matFixedEquatorialToAltAz));
×
981
        Refraction* refr = new Refraction(skyDrawer->getRefraction());
×
982
        // The pretransform matrix will convert from input coordinates to AltAz needed by the refraction function.
983
        refr->setPreTransfoMat(matFixedEquatorialToAltAz);
×
984
        refr->setPostTransfoMat(matAltAzModelView);
×
985
        return StelProjector::ModelViewTranformP(refr);
×
986
}
987

988
//! Get the modelview matrix for observer-centric altazimuthal drawing
989
StelProjector::ModelViewTranformP StelCore::getAltAzModelViewTransform(RefractionMode refMode) const
×
990
{
991
        if (refMode==RefractionOff || skyDrawer==Q_NULLPTR || (refMode==RefractionAuto && skyDrawer->getFlagHasAtmosphere()==false))
×
992
        {
993
                // Catch problem with improperly initialized matAltAzModelView
994
                Q_ASSERT(matAltAzModelView[0]==matAltAzModelView[0]);
×
995
                return StelProjector::ModelViewTranformP(new StelProjector::Mat4dTransform(matAltAzModelView,Mat4d::identity()));
×
996
        }
997
        Refraction* refr = new Refraction(skyDrawer->getRefraction());
×
998
        // The pretransform matrix will convert from input coordinates to AltAz needed by the refraction function.
999
        refr->setPostTransfoMat(matAltAzModelView);
×
1000
        return StelProjector::ModelViewTranformP(refr);
×
1001
}
1002

1003
//! Get the modelview matrix for observer-centric J2000 equatorial drawing
1004
StelProjector::ModelViewTranformP StelCore::getJ2000ModelViewTransform(RefractionMode refMode) const
×
1005
{
1006
        if (refMode==RefractionOff || skyDrawer==Q_NULLPTR || (refMode==RefractionAuto && skyDrawer->getFlagHasAtmosphere()==false))
×
1007
                return StelProjector::ModelViewTranformP(new StelProjector::Mat4dTransform(matAltAzModelView,matEquinoxEquToAltAz*matJ2000ToEquinoxEqu));
×
1008
        Refraction* refr = new Refraction(skyDrawer->getRefraction());
×
1009
        // The pretransform matrix will convert from input coordinates to AltAz needed by the refraction function.
1010
        refr->setPreTransfoMat(matEquinoxEquToAltAz*matJ2000ToEquinoxEqu);
×
1011
        refr->setPostTransfoMat(matAltAzModelView);
×
1012
        return StelProjector::ModelViewTranformP(refr);
×
1013
}
1014

1015
//! Get the modelview matrix for observer-centric Galactic equatorial drawing
1016
StelProjector::ModelViewTranformP StelCore::getGalacticModelViewTransform(RefractionMode refMode) const
×
1017
{
1018
        if (refMode==RefractionOff || skyDrawer==Q_NULLPTR || (refMode==RefractionAuto && skyDrawer->getFlagHasAtmosphere()==false))
×
1019
                return StelProjector::ModelViewTranformP(new StelProjector::Mat4dTransform(matAltAzModelView,matEquinoxEquToAltAz*matJ2000ToEquinoxEqu*matGalacticToJ2000));
×
1020
        Refraction* refr = new Refraction(skyDrawer->getRefraction());
×
1021
        // The pretransform matrix will convert from input coordinates to AltAz needed by the refraction function.
1022
        refr->setPreTransfoMat(matEquinoxEquToAltAz*matJ2000ToEquinoxEqu*matGalacticToJ2000);
×
1023
        refr->setPostTransfoMat(matAltAzModelView);
×
1024
        return StelProjector::ModelViewTranformP(refr);
×
1025
}
1026

1027
//! Get the modelview matrix for observer-centric Supergalactic equatorial drawing
1028
StelProjector::ModelViewTranformP StelCore::getSupergalacticModelViewTransform(RefractionMode refMode) const
×
1029
{
1030
        if (refMode==RefractionOff || skyDrawer==Q_NULLPTR || (refMode==RefractionAuto && skyDrawer->getFlagHasAtmosphere()==false))
×
1031
                return StelProjector::ModelViewTranformP(new StelProjector::Mat4dTransform(matAltAzModelView,matEquinoxEquToAltAz*matJ2000ToEquinoxEqu*matSupergalacticToJ2000));
×
1032
        Refraction* refr = new Refraction(skyDrawer->getRefraction());
×
1033
        // The pretransform matrix will convert from input coordinates to AltAz needed by the refraction function.
1034
        refr->setPreTransfoMat(matEquinoxEquToAltAz*matJ2000ToEquinoxEqu*matSupergalacticToJ2000);
×
1035
        refr->setPostTransfoMat(matAltAzModelView);
×
1036
        return StelProjector::ModelViewTranformP(refr);
×
1037
}
1038

1039
// GZ: One of the most important functions, totally void of doc. :-(
1040
// called in update() (for every frame)
1041
void StelCore::updateTransformMatrices()
×
1042
{
1043
        matAltAzToEquinoxEqu = position->getRotAltAzToEquatorial(getJD(), getJDE());
×
1044
        matEquinoxEquToAltAz = matAltAzToEquinoxEqu.transpose();
×
1045

1046
        // multiply static J2000 earth axis tilt (eclipticalJ2000<->equatorialJ2000)
1047
        // in effect, this matrix transforms from VSOP87 ecliptical J2000 to planet-based equatorial coordinates.
1048
        // For earth, matJ2000ToEquinoxEqu is the precession matrix.        
1049
        matEquinoxEquDateToJ2000 = matVsop87ToJ2000 * position->getRotEquatorialToVsop87();
×
1050
        matJ2000ToEquinoxEqu = matEquinoxEquDateToJ2000.transpose();
×
1051
        matJ2000ToAltAz = matEquinoxEquToAltAz*matJ2000ToEquinoxEqu;
×
1052
        matAltAzToJ2000 = matJ2000ToAltAz.transpose();
×
1053

1054
        matHeliocentricEclipticToEquinoxEqu = matJ2000ToEquinoxEqu * matVsop87ToJ2000 * Mat4d::translation(-position->getCenterVsop87Pos());
×
1055

1056
        // These two next have to take into account the position of the observer on the earth/planet of observation.        
1057
        Mat4d matAltAzToVsop87 = matJ2000ToVsop87 * matEquinoxEquDateToJ2000 * matAltAzToEquinoxEqu;
×
1058
        //Mat4d tmp1 = matJ2000ToVsop87 * matEquinoxEquDateToJ2000;
1059

1060
        // Before 0.14 getDistanceFromCenter assumed spherical planets. Now uses rectangular coordinates for observer!
1061
        // In series 0.14 and 0.15, this was erroneous: offset by distance rho, but in the wrong direction.
1062
        // Attempt to fix LP:1275092. This improves the situation, but is still not perfect.
1063
        // Please keep the commented stuff until situation is really solved.
1064
        if (flagUseTopocentricCoordinates)
×
1065
        {
1066
                const Vec4d offset=position->getTopographicOffsetFromCenter(); // [rho cosPhi', rho sinPhi', phi'_rad, rho]
×
1067
                const double sigma=static_cast<double>(position->getCurrentLocation().getLatitude())*M_PI/180.0 - offset.v[2];
×
1068
                const double rho=offset.v[3];
×
1069

1070
                matAltAzToHeliocentricEclipticJ2000 =  Mat4d::translation(position->getCenterVsop87Pos()) * matAltAzToVsop87 *
×
1071
                                Mat4d::translation(Vec3d(rho*sin(sigma), 0., rho*cos(sigma) ));
×
1072

1073
                matHeliocentricEclipticJ2000ToAltAz =
1074
                                Mat4d::translation(Vec3d(-rho*sin(sigma), 0., -rho*cos(sigma))) * matAltAzToVsop87.transpose() *
×
1075
                                Mat4d::translation(-position->getCenterVsop87Pos());
×
1076

1077
                // Here I tried to split tmp matrix. This does not work:
1078
//                matAltAzToHeliocentricEclipticJ2000 =  Mat4d::translation(position->getCenterVsop87Pos()) * tmp1 *
1079
//                                Mat4d::translation(Vec3d(rho*sin(sigma), 0., rho*cos(sigma) )) * matAltAzToEquinoxEqu;
1080

1081
//                matHeliocentricEclipticJ2000ToAltAz =
1082
//                                matEquinoxEquToAltAz *
1083
//                                Mat4d::translation(Vec3d(-rho*sin(sigma), 0., -rho*cos(sigma))) * tmp1.transpose() *
1084
//                                Mat4d::translation(-position->getCenterVsop87Pos());
1085

1086

1087
//                matAltAzToHeliocentricEclipticJ2000 =  Mat4d::translation(position->getCenterVsop87Pos()) * tmp *
1088
//                                Mat4d::translation(Vec3d(0.,0., position->getDistanceFromCenter()));
1089

1090
//                matHeliocentricEclipticJ2000ToAltAz =  Mat4d::translation(Vec3d(0.,0.,-position->getDistanceFromCenter())) * tmp.transpose() *
1091
//                                Mat4d::translation(-position->getCenterVsop87Pos());
1092
        }
1093
        else
1094
        {
1095
                matAltAzToHeliocentricEclipticJ2000 =  Mat4d::translation(position->getCenterVsop87Pos()) * matAltAzToVsop87;
×
1096
                matHeliocentricEclipticJ2000ToAltAz =  matAltAzToVsop87.transpose() * Mat4d::translation(-position->getCenterVsop87Pos());
×
1097
        }
1098
}
×
1099

1100
// This avoids calling a costly operation every frame.
1101
void StelCore::updateFixedEquatorialTransformMatrices()
×
1102
{
1103
        matAltAzToFixedEquatorial = Mat4d::yrotation(M_PI_2-static_cast<double>(getCurrentLocation().getLatitude())*M_PI_180);
×
1104
        matFixedEquatorialToAltAz = matAltAzToFixedEquatorial.transpose();
×
1105
}
×
1106
// Return the observer heliocentric position
1107
Vec3d StelCore::getObserverHeliocentricEclipticPos() const
×
1108
{
1109
        return Vec3d(matAltAzToHeliocentricEclipticJ2000[12], matAltAzToHeliocentricEclipticJ2000[13], matAltAzToHeliocentricEclipticJ2000[14]);
×
1110
}
1111

1112
Vec3d StelCore::getObserverHeliocentricEclipticVelocity() const
×
1113
{
1114
        if (!position) return Vec3d(0,0,0);
×
1115

1116
        const auto& planet = *position->getHomePlanet();
×
1117
        const Vec3d planetVelocity = planet.getHeliocentricEclipticVelocity();
×
1118
        if (!flagUseTopocentricCoordinates)
×
1119
                return planetVelocity;
×
1120

1121
        const auto off = position->getTopographicOffsetFromCenter();
×
1122
        const auto rotRadius = off.v[0];
×
1123
        const auto rotPeriod = planet.getSiderealDay();
×
1124
        const auto linearSpeed = 2 * M_PI * rotRadius / rotPeriod; // AU/day
×
1125
        const auto toJ2000 = matAltAzToHeliocentricEclipticJ2000.upper3x3();
×
1126
        const auto eastwardVelocity = Vec3d(0,linearSpeed,0);
×
1127
        const auto velocity = toJ2000 * eastwardVelocity;
×
1128
        return planetVelocity + velocity;
×
1129
}
1130

1131
// Set the location to use by default at startup
1132
void StelCore::setDefaultLocationID(const QString& id)
×
1133
{
1134
        StelLocation location = StelApp::getInstance().getLocationMgr().locationForString(id);
×
1135
        if (!location.isValid())
×
1136
        {
1137
                qWarning() << "Trying to set an invalid location" << id;
×
1138
                return;
×
1139
        }
1140
        defaultLocationID = id;
×
1141
        QSettings* conf = StelApp::getInstance().getSettings();
×
1142
        Q_ASSERT(conf);
×
1143
        conf->setValue("init_location/location", id);
×
1144
}
×
1145

1146
void StelCore::returnToDefaultLocation()
×
1147
{
1148
        StelLocationMgr& locationMgr = StelApp::getInstance().getLocationMgr();
×
1149
        StelLocation loc = locationMgr.locationForString(defaultLocationID);
×
1150
        if (loc.isValid())
×
1151
                moveObserverTo(loc, 1., 2.);
×
1152
        else
1153
                qDebug() << "StelCore::returnToDefaultLocation: Location " << loc.serializeToLine().replace('\t', '|') << "is invalid. Store an entry from the locations list as default location.";
×
1154
}
×
1155

1156
void StelCore::returnToHome()
×
1157
{
1158
        // Using returnToDefaultLocation() and getCurrentLocation() introduce issue, because for flying
1159
        // between planets using SpaceShip and second method give does not exist data
1160
        StelLocationMgr& locationMgr = StelApp::getInstance().getLocationMgr();
×
1161
        StelLocation loc;
×
1162
        QSettings* conf = StelApp::getInstance().getSettings();
×
1163
        if (defaultLocationID == "auto")
×
1164
        {
1165
                locationMgr.locationFromIP();
×
1166
                loc = locationMgr.getLastResortLocation();
×
1167
        }
1168
        else
1169
                loc = locationMgr.locationForString(defaultLocationID);
×
1170

1171
        if (loc.isValid())
×
1172
                moveObserverTo(loc, conf->value("navigation/return_home_duration", 0.).toDouble()); // ability set a duration of movement (for a demo)
×
1173

1174
        PlanetP p = GETSTELMODULE(SolarSystem)->searchByEnglishName(loc.planetName);
×
1175

1176
        LandscapeMgr* landscapeMgr = GETSTELMODULE(LandscapeMgr);
×
1177
        landscapeMgr->setCurrentLandscapeID(landscapeMgr->getDefaultLandscapeID());
×
1178
        landscapeMgr->setFlagAtmosphere(p->hasAtmosphere() && conf->value("landscape/flag_atmosphere", true).toBool());
×
1179
        landscapeMgr->setFlagFog(p->hasAtmosphere() && conf->value("landscape/flag_fog", true).toBool());
×
1180
        landscapeMgr->setFlagLandscape(!p->getEnglishName().contains("observer", Qt::CaseInsensitive) && conf->value("landscape/flag_landscape", true).toBool());
×
1181

1182
        GETSTELMODULE(StelObjectMgr)->unSelect();
×
1183

1184
        StelMovementMgr* smmgr = getMovementMgr();
×
1185
        smmgr->setViewDirectionJ2000(altAzToJ2000(smmgr->getInitViewingDirection(), StelCore::RefractionOff));
×
1186
        smmgr->zoomTo(smmgr->getInitFov(), conf->value("navigation/return_fov_duration", 1.).toDouble()); // ability set a duration of zooming (for a demo)
×
1187
}
×
1188

1189
double StelCore::getJDOfLastJDUpdate() const
×
1190
{
1191
        return jdOfLastJDUpdate;
×
1192
}
1193

1194
void StelCore::setMilliSecondsOfLastJDUpdate(qint64 millis)
×
1195
{
1196
        milliSecondsOfLastJDUpdate = millis;
×
1197
}
×
1198

1199
qint64 StelCore::getMilliSecondsOfLastJDUpdate() const
×
1200
{
1201
        return milliSecondsOfLastJDUpdate;
×
1202
}
1203

1204
void StelCore::setJD(double newJD)
×
1205
{
1206
        JD.first=newJD;
×
1207
        JD.second=computeDeltaT(newJD);        
×
1208
        resetSync();
×
1209
}
×
1210

1211
double StelCore::getJD() const
×
1212
{
1213
        return JD.first;
×
1214
}
1215

1216
void StelCore::setJDE(double newJDE)
×
1217
{
1218
        // nitpickerish this is not exact, but as good as it gets...
1219
        JD.second=computeDeltaT(newJDE);
×
1220
        JD.first=newJDE-JD.second/86400.0;
×
1221
        resetSync();
×
1222
}
×
1223

1224
double StelCore::getJDE() const
×
1225
{
1226
        return JD.first+JD.second/86400.0;
×
1227
}
1228

1229

1230
void StelCore::setMJDay(double MJD)
×
1231
{
1232
        setJD(MJD+2400000.5);
×
1233
}
×
1234

1235
double StelCore::getMJDay() const
×
1236
{
1237
        return JD.first-2400000.5;
×
1238
}
1239

1240
// @return whether nutation is currently used.
1241
bool StelCore::getUseNutation() const
×
1242
{
1243
        return flagUseNutation;
×
1244
}
1245
// Set whether you want computation and simulation of nutation (a slight wobble of Earth's axis, just a few arcseconds).
1246
void StelCore::setUseNutation(bool use)
×
1247
{
1248
        if (flagUseNutation != use)
×
1249
        {
1250
                flagUseNutation=use;
×
1251
                StelApp::immediateSave("astro/flag_nutation", use);
×
1252
                emit flagUseNutationChanged(use);
×
1253
        }
1254
}
×
1255

1256
// @return whether aberration is currently used.
1257
bool StelCore::getUseAberration() const
×
1258
{
1259
        return flagUseAberration;
×
1260
}
1261
// Set whether you want computation and simulation of aberration (a slight wobble of stellar positions due to finite speed of light, about 20 arcseconds when observing from earth).
1262
void StelCore::setUseAberration(bool use)
×
1263
{
1264
        if (flagUseAberration != use)
×
1265
        {
1266
                flagUseAberration=use;
×
1267
                StelApp::immediateSave("astro/flag_aberration", use);
×
1268
                emit flagUseAberrationChanged(use);
×
1269
        }
1270
}
×
1271

1272
// @return aberration factor. 1 is realistic simulation, but higher values may be useful for didactic purposes.
1273
double StelCore::getAberrationFactor() const
×
1274
{
1275
        return aberrationFactor;
×
1276
}
1277
// Set aberration factor. Values are clamped to 0...5. (Values above 5 cause graphical problems.)
1278
void StelCore::setAberrationFactor(double factor)
×
1279
{
1280
        if (!fuzzyEquals(aberrationFactor, factor))
×
1281
        {
1282
                aberrationFactor=qBound(0.,factor, 5.);
×
1283
                StelApp::immediateSave("astro/aberration_factor", aberrationFactor);
×
1284
                emit aberrationFactorChanged(factor);
×
1285
        }
1286
}
×
1287

1288
// @return whether parallax effect is currently used.
1289
bool StelCore::getUseParallax() const
×
1290
{
1291
        return flagUseParallax;
×
1292
}
1293
// Set whether you want computation and simulation of parallax effect.
1294
void StelCore::setUseParallax(bool use)
×
1295
{
1296
        if (flagUseParallax != use)
×
1297
        {
1298
                flagUseParallax=use;
×
1299
                StelApp::immediateSave("astro/flag_parallax", use);
×
1300
                emit flagUseParallaxChanged(use);
×
1301
        }
1302
}
×
1303

1304
// @return parallax factor. 1 is realistic simulation, but higher values may be useful for didactic purposes.
1305
double StelCore::getParallaxFactor() const {return parallaxFactor;}
×
1306
// Set aberration factor. Values are clamped to 0...5. (Values above 5 cause graphical problems.)
1307
void StelCore::setParallaxFactor(double factor)
×
1308
{
1309
        if (!fuzzyEquals(parallaxFactor, factor))
×
1310
        {
1311
                parallaxFactor=qBound(0.,factor, 100000.);
×
1312
                StelApp::immediateSave("astro/parallax_factor", parallaxFactor);
×
1313
                emit parallaxFactorChanged(factor);
×
1314
        }
1315
}
×
1316

1317
// @return whether topocentric coordinates are currently used.
1318
bool StelCore::getUseTopocentricCoordinates() const
×
1319
{
1320
        return flagUseTopocentricCoordinates;
×
1321
}
1322
// Set whether you want topocentric or planetocentric data
1323
void StelCore::setUseTopocentricCoordinates(bool use)
×
1324
{
1325
        if (flagUseTopocentricCoordinates!= use)
×
1326
        {
1327
                flagUseTopocentricCoordinates=use;
×
1328
                // DO NOT IMMEDIATE-SAVE! -- This flag is switched too often. GH #4112
1329
                // Add a store button elsewhere when needed.
1330
                emit flagUseTopocentricCoordinatesChanged(use);
×
1331
        }
1332
}
×
1333

1334
double StelCore::getPresetSkyTime() const
×
1335
{
1336
        return presetSkyTime;
×
1337
}
1338

1339
void StelCore::setPresetSkyTime(double d)
×
1340
{
1341
        StelApp::immediateSave("navigation/preset_sky_time", d);
×
1342
        presetSkyTime=d;
×
1343
}
×
1344

1345
void StelCore::setTimeRate(double ts)
×
1346
{
1347
        timeSpeed=ts;
×
1348
        resetSync();
×
1349
        emit timeRateChanged(timeSpeed);
×
1350
}
×
1351

1352
double StelCore::getTimeRate() const
×
1353
{
1354
        return timeSpeed;
×
1355
}
1356

1357
void StelCore::revertTimeDirection(void)
×
1358
{
1359
        setTimeRate(-1*getTimeRate());
×
1360
}
×
1361

1362
void StelCore::moveObserverToSelected()
×
1363
{
1364
        StelObjectMgr* objmgr = GETSTELMODULE(StelObjectMgr);
×
1365
        Q_ASSERT(objmgr);
×
1366
        if (objmgr->getWasSelected())
×
1367
        {
1368
                Planet* pl = dynamic_cast<Planet*>(objmgr->getSelectedObject()[0].data());
×
1369
                if (pl)
×
1370
                {
1371
                        // We need to move to the selected planet. Try to generate a location from the current one
1372
                        StelLocation loc = getCurrentLocation();
×
1373
                        if (loc.planetName != pl->getEnglishName())
×
1374
                        {
1375
                                loc.planetName = pl->getEnglishName();                                
×
1376
                                loc.name = "landing site";
×
1377
                                loc.state = "";
×
1378
                                if (pl->getPlanetType()==Planet::isObserver)
×
1379
                                        loc.role=QChar('o');
×
1380
                                else
1381
                                        loc.role=QChar('X');
×
1382

1383
                                // Let's try guess name of location...
1384
                                LocationMap results = StelApp::getInstance().getLocationMgr().pickLocationsNearby(loc.planetName, loc.getLongitude(), loc.getLatitude(), 1.0f);
×
1385
                                if (!results.isEmpty())
×
1386
                                        loc = results.value(results.firstKey()); // ...and use it!
×
1387

1388
                                moveObserverTo(loc, 1, 1, pl->getEnglishName());
×
1389
                        }
×
1390
                }
×
1391
                else
1392
                {
1393
                        NomenclatureItem* ni = dynamic_cast<NomenclatureItem*>(objmgr->getSelectedObject()[0].data());
×
1394
                        if (ni)
×
1395
                        {
1396
                                // We need to move to the nomenclature item's host planet.
1397
                                StelLocation loc(ni->getEnglishName(), "", "", ni->getPlanet()->getEnglishName(), ni->getLongitude(), ni->getLatitude(), 0, 0, getCurrentTimeZone(), 1, 'X', ni->getPlanet()->getEnglishName());
×
1398
                                loc.lightPollutionLuminance = 0; // be dead sure it's zero!
×
1399

1400
                                moveObserverTo(loc, 1, 1, ni->getPlanet()->getEnglishName());
×
1401
                                objmgr->unSelect(); // no use to keep it: Marker will flicker around the screen.
×
1402
                        }
×
1403
                }
1404
        }
1405
        StelMovementMgr* mmgr = GETSTELMODULE(StelMovementMgr);
×
1406
        Q_ASSERT(mmgr);
×
1407
        mmgr->setFlagTracking(false);
×
1408
}
×
1409

1410
// Get the information on the current location
1411
const StelLocation& StelCore::getCurrentLocation() const
×
1412
{
1413
        return position->getCurrentLocation();
×
1414
}
1415

1416
const QSharedPointer<Planet> StelCore::getCurrentPlanet() const
×
1417
{
1418
        return position->getHomePlanet();
×
1419
}
1420

1421
const StelObserver *StelCore::getCurrentObserver() const
×
1422
{
1423
        return position;
×
1424
}
1425

1426
void StelCore::setObserver(StelObserver *obs)
×
1427
{
1428
        delete position;
×
1429
        position = obs;
×
1430
        if (!getUseCustomTimeZone() && !obs->getCurrentLocation().ianaTimeZone.isEmpty())
×
1431
                setCurrentTimeZone(obs->getCurrentLocation().ianaTimeZone);
×
1432
}
×
1433

1434
// Smoothly move the observer to the given location
1435
void StelCore::moveObserverTo(const StelLocation& target, double duration, double durationIfPlanetChange, const QString &landscapeID)
×
1436
{
1437
        const double d = (getCurrentLocation().planetName==target.planetName) ? duration : durationIfPlanetChange;
×
1438
        //qDebug() << "StelCore::moveObserverTo" << target.name << "in" << d << "seconds with Landscape" << landscapeID ;
1439
        if (d>0.)
×
1440
        {
1441
                StelLocation curLoc = getCurrentLocation();
×
1442
                if (position->isTraveling())
×
1443
                {
1444
                        // Avoid using a temporary location name to create another temporary one (otherwise it looks like loc1 -> loc2 -> loc3 etc..)
1445
                        curLoc.name = ".";
×
1446
                }
1447
                SpaceShipObserver* newObs = new SpaceShipObserver(curLoc, target, d);                
×
1448
                setObserver(newObs);
×
1449
                newObs->update(0);
×
1450
        }
×
1451
        else
1452
        {
1453
                setObserver(new StelObserver(target));
×
1454
        }
1455

1456
        // Auto-select observed planet for observer locations
1457
        if (target.role==QChar('o'))
×
1458
        {
1459
                // If we change to an Observer "planet", auto-select and focus on the observed object.
1460
                SolarSystem *ss=GETSTELMODULE(SolarSystem);
×
1461
                PlanetP planet=nullptr;
×
1462
                if (ss)
×
1463
                        planet=GETSTELMODULE(SolarSystem)->searchByEnglishName(target.planetName);
×
1464
                if (planet && planet->getPlanetType()==Planet::isObserver)
×
1465
                {
1466
                        StelObjectMgr *soMgr=GETSTELMODULE(StelObjectMgr);
×
1467
                        if (soMgr)
×
1468
                        {
1469
                                soMgr->findAndSelect(planet->getParent()->getEnglishName());
×
1470
                                GETSTELMODULE(StelMovementMgr)->setFlagTracking(true);
×
1471
                        }
1472
                }
1473
        }
×
1474
        emit targetLocationChanged(target, landscapeID); // inform others about our next location. E.g., let LandscapeMgr load a new landscape.
×
1475
        emit locationChanged(getCurrentLocation());
×
1476
}
×
1477

1478
double StelCore::getUTCOffset(const double JD) const
×
1479
{
1480
        int year, month, day, hour, minute, second;
1481
        StelUtils::getDateTimeFromJulianDay(JD, &year, &month, &day, &hour, &minute, &second);
×
1482
        // as analogous to second statement in getJDFromDate, nkerr
1483
        if ( year <= 0 )
×
1484
        {
1485
                year = year - 1;
×
1486
        }
1487
        //getTime/DateFromJulianDay returns UTC time, not local time
1488
        QDateTime universal(QDate(year, month, day), QTime(hour, minute, second), Qt::UTC);
×
1489
        if (!universal.isValid())
×
1490
        {
1491
                //qWarning() << "JD " << QString("%1").arg(JD) << " out of bounds of QT help with GMT shift, using current datetime";
1492
                // Assumes the GMT shift was always the same before year -4710
1493
                // NOTE: QDateTime has no year 0, and therefore likely different leap year rules.
1494
                // Under which circumstances do we get invalid universal?
1495
                universal = QDateTime(QDate(-4710, month, day), QTime(hour, minute, second), Qt::UTC);
×
1496
        }
1497

1498
#if defined(Q_OS_WIN)
1499
        if (abs(year)<3)
1500
        {
1501
                // Mitigate a QTBUG on Windows (GH #594).
1502
                // This bug causes offset to be MIN_INT in January to March, 1AD.
1503
                // We assume a constant offset in this remote history,
1504
                // so we construct yet another date to get a valid offset.
1505
                // Application of the named time zones is inappropriate in any case.
1506
                universal = QDateTime(QDate(3, month, day), QTime(hour, minute, second), Qt::UTC);
1507
        }
1508
#endif
1509
        StelLocation loc = getCurrentLocation();
×
1510
        QString tzName = getCurrentTimeZone();
×
1511
        bool tzSpecial = QString("LMST LTST system_default").contains(tzName);
×
1512
        QTimeZone tz(tzName.toUtf8());
×
1513
        // We must fight a bug in Qt6.2 on Linux. For some reason tz.isValid() is true even for our self-named zones LMST,LTST,system_default.
1514
        // We must use an intermediate Boolean which we set to false where needed.
1515
        bool tzValid = tzSpecial ? false : tz.isValid();
×
1516

1517
        if (!tzValid && !tzSpecial)
×
1518
                qWarning().noquote() << "Invalid timezone: " << tzName;
×
1519

1520
        qint64 shiftInSeconds = 0;
×
1521
        if (tzName=="system_default" || (loc.planetName=="Earth" && !tzValid && !QString("LMST LTST").contains(tzName)))
×
1522
        {
1523
                QDateTime local = universal.toLocalTime();
×
1524
                //Both timezones should be interpreted as UTC because secsTo() converts both
1525
                //times to UTC if their zones have different daylight saving time rules.
1526
                local.setTimeSpec(Qt::UTC);
×
1527
                shiftInSeconds = universal.secsTo(local);
×
1528
                if (abs(shiftInSeconds)>50000 || shiftInSeconds==INT_MIN)
×
1529
                {
1530
                        qDebug() << "TZ system_default or invalid, At JD" << QString::number(JD, 'g', 11) << ", shift:" << shiftInSeconds;
×
1531
                }
1532
        }
×
1533
        else
1534
        {
1535
                // The first adoption of a standard time was on December 1, 1847 in Great Britain
1536
                if (tzValid && loc.planetName=="Earth" && (JD>=StelCore::TZ_ERA_BEGINNING || getUseCustomTimeZone()))
×
1537
                {
1538
                        if (getUseDST())
×
1539
                                shiftInSeconds = tz.offsetFromUtc(universal);
×
1540
                        else
1541
                                shiftInSeconds = tz.standardTimeOffset(universal);
×
1542
                        if (abs(shiftInSeconds)>500000 || shiftInSeconds==INT_MIN)
×
1543
                        {
1544
                                // Something very strange has happened. The Windows-only clause above already mitigated GH #594.
1545
                                // Trigger this with a named custom TZ like Europe/Stockholm.
1546
                                // Then try to wheel back some date in January-March from year 10 to 0. Instead of year 1, it jumps to 70,
1547
                                // an offset of INT_MIN
1548
                                qWarning() << "ERROR TRAPPED! --- Please submit a bug report with this logfile attached.";
×
1549
                                qWarning() << "TZ" << tz << "valid, but at JD" << QString::number(JD, 'g', 11) << ", shift:" << shiftInSeconds;
×
1550
                                qWarning() << "Universal reference date: " << universal.toString();
×
1551
                        }
1552
                }
1553
                else
1554
                {
1555
                        shiftInSeconds = qRound((loc.getLongitude()/15.f)*3600.f); // Local Mean Solar Time
×
1556
                }
1557
                if (tzName=="LTST")
×
1558
                        shiftInSeconds += qRound(getSolutionEquationOfTime()*60);
×
1559
        }
1560
        //qDebug() << "ShiftInSeconds:" << shiftInSeconds;
1561

1562
        // Extraterrestrial: Either use the configured Terrestrial timezone, or even a pseudo-LMST based on planet's rotation speed?
1563
        if (loc.planetName!="Earth")
×
1564
        {
1565
                if (tzValid && (JD>=StelCore::TZ_ERA_BEGINNING || getUseCustomTimeZone()))
×
1566
                {
1567
                        if (getUseDST())
×
1568
                                shiftInSeconds = tz.offsetFromUtc(universal);
×
1569
                        else
1570
                                shiftInSeconds = tz.standardTimeOffset(universal);
×
1571
                        if (shiftInSeconds==INT_MIN) // triggered error
×
1572
                        {
1573
                                // Something very strange has happened. The Windows-only clause above already mitigated GH #594.
1574
                                // Trigger this with a named custom TZ like Europe/Stockholm.
1575
                                // Then try to wheel back some date in January-March from year 10 to 0. Instead of year 1, it jumps to 70,
1576
                                // an offset of INT_MIN
1577
                                qWarning() << "ERROR TRAPPED! --- Please submit a bug report with this logfile attached.";
×
1578
                                qWarning() << "TZ" << tz << "valid, but at JD" << QString::number(JD, 'g', 11) << ", shift:" << shiftInSeconds;
×
1579
                                qWarning() << "Universal reference date: " << universal.toString();
×
1580
                        }
1581
                }
1582
                else
1583
                {
1584
                        // TODO: This should give "mean solar time" for any planet.
1585
                        // Combine rotation and orbit, or (for moons) rotation and orbit of parent planet.
1586
                        // LTST is even worse, needs equation of time for other planets.
1587
                        shiftInSeconds = 0; // For now, give UT
×
1588
                }
1589
        }
1590

1591
        return shiftInSeconds / 3600.0;
×
1592
}
×
1593

1594
QString StelCore::getCurrentTimeZone() const
×
1595
{
1596
        return currentTimeZone;
×
1597
}
1598

1599
void StelCore::setCurrentTimeZone(const QString& tz)
×
1600
{
1601
        if (StelApp::getInstance().getLocationMgr().getAllTimezoneNames().contains(tz))
×
1602
        {
1603
                currentTimeZone = tz;
×
1604
                emit currentTimeZoneChanged(tz);
×
1605
        }
1606
        else
1607
        {
1608
                qWarning() << "StelCore: Invalid timezone name:" << tz << " -- not setting timezone.";
×
1609
        }
1610
}
×
1611

1612
bool StelCore::getUseDST() const
×
1613
{
1614
        return flagUseDST;
×
1615
}
1616

1617
void StelCore::setUseDST(const bool b)
×
1618
{
1619
        flagUseDST = b;
×
1620
        StelApp::getInstance().getSettings()->setValue("localization/flag_dst", b);
×
1621
        emit flagUseDSTChanged(b);
×
1622
}
×
1623

1624
void StelCore::setDitheringMode(const DitheringMode newMode)
×
1625
{
1626
        if(newMode == ditheringMode)
×
1627
                return;
×
1628

1629
        ditheringMode = newMode;
×
1630
        StelApp::immediateSave("video/dithering_mode", ditheringMap.key(newMode, "disabled"));
×
1631
        emit ditheringModeChanged(newMode);
×
1632
}
1633

1634
void StelCore::setDitheringMode(const QString& modeName)
×
1635
{
1636
        const auto mode = parseDitheringMode(modeName);
×
1637
        setDitheringMode(mode);
×
1638
}
×
1639

1640
bool StelCore::getUseCustomTimeZone() const
×
1641
{
1642
        return flagUseCTZ;
×
1643
}
1644

1645
void StelCore::setUseCustomTimeZone(const bool b)
×
1646
{
1647
        flagUseCTZ = b;
×
1648
        emit useCustomTimeZoneChanged(b);
×
1649
}
×
1650

1651
bool StelCore::getStartupTimeStop() const
×
1652
{
1653
        return startupTimeStop;
×
1654
}
1655

1656
void StelCore::setStartupTimeStop(const bool b)
×
1657
{
1658
        startupTimeStop = b;
×
1659
        StelApp::immediateSave("navigation/startup_time_stop", b);
×
1660
        emit startupTimeStopChanged(b);
×
1661
}
×
1662

1663
double StelCore::getSolutionEquationOfTime(const double JDE) const
×
1664
{
1665
        // The full solution to the equation of time requires lots of computation. We go the fast way from Meeus, AA2, 28.3.
1666

1667
        const double T=(JDE-2451545.0)/36525.;
×
1668
        const double tau = T*0.1;
×
1669
        const double epsRad=getPrecessionAngleVondrakEpsilon(JDE);
×
1670
        const double e = (-0.0000001267*T-0.000042037)*T+0.016708634;
×
1671
        const double M = ((-0.0001537*T+35999.05029)*T+357.52911)*M_PI_180;
×
1672
        double Lo = StelUtils::fmodpos(280.4664567 + tau*(360007.6982779 + tau*(0.03032028 + tau*(1./49931. + tau*(-1./15300. - tau/2000000.)))), 360.);
×
1673
        Lo *= M_PI_180;
×
1674
        double y=tan(epsRad*0.5); y*=y;
×
1675

1676
        double E=y*sin(2.*Lo)+2.*e*sin(M)*(2.*y*cos(2.*Lo)-1.)-0.5*y*y*sin(4.*Lo)-1.25*e*e*sin(2.*M);
×
1677
        return E*M_180_PI*4.;
×
1678
}
1679

1680
double StelCore::getSolutionEquationOfTime() const
×
1681
{
1682
        const double tau = (getJDE() - 2451545.0)/365250.0;
×
1683
        const double sunMeanLongitude = StelUtils::fmodpos(280.4664567 + tau*(360007.6982779 + tau*(0.03032028 + tau*(1./49931. + tau*(-1./15300. - tau/2000000.)))), 360.);
×
1684

1685
        Vec3d pos = GETSTELMODULE(StelObjectMgr)->searchByName("Sun")->getEquinoxEquatorialPos(this);
×
1686
        double ra, dec;
1687
        StelUtils::rectToSphe(&ra, &dec, pos);
×
1688

1689
        // convert radians to degrees and reduce the angle, so that 0 <= angle < 360
1690
        const double alpha = StelUtils::fmodpos(ra*M_180_PI, 360.);
×
1691

1692
        double deltaPsi, deltaEps;
1693
        getNutationAngles(getJDE(), &deltaPsi, &deltaEps); // these are radians!
×
1694
        double equation = 4*(sunMeanLongitude - 0.0057183 - alpha + deltaPsi*M_180_PI*cos(getPrecessionAngleVondrakEpsilon(getJDE())));
×
1695
        // The equation of time is always smaller 20 minutes in absolute value
1696
        if (qAbs(equation)>20)
×
1697
        {
1698
                // If absolute value of the equation of time appears to be too large, add 24 hours (1440 minutes) to or subtract it from our result
1699
                if (equation>0.)
×
1700
                        equation -= 1440.;
×
1701
                else
1702
                        equation += 1440.;
×
1703
        }
1704

1705
        return equation;
×
1706
}
1707

1708
//! Set stellarium time to current real world time
1709
void StelCore::setTimeNow()
×
1710
{
1711
        setJD(StelUtils::getJDFromSystem());
×
1712
        // Force emit dateChanged
1713
        emit dateChanged();
×
1714
}
×
1715

1716
void StelCore::setTodayTime(const QTime& target)
×
1717
{
1718
        QDateTime dt = QDateTime::currentDateTime();
×
1719
        if (target.isValid())
×
1720
        {
1721
                dt.setTime(target);
×
1722
                // don't forget to adjust for timezone / daylight savings.
1723
                double JD = StelUtils::qDateTimeToJd(dt)-(static_cast<double>(getUTCOffset(StelUtils::getJDFromSystem())) * JD_HOUR);
×
1724
                setJD(JD);
×
1725
        }
1726
        else
1727
        {
1728
                qWarning().noquote() << "Time passed to StelCore::setTodayTime is not valid. The system time will be used." << target;
×
1729
                setTimeNow();
×
1730
        }
1731
}
×
1732

1733
//! Get whether the current stellarium time is the real world time
1734
bool StelCore::getIsTimeNow(void) const
×
1735
{
1736
        // cache last time to prevent to much slow system call
1737
        static double lastJD = getJD();
×
1738
        static bool previousResult = (fabs(getJD()-(StelUtils::getJDFromSystem()))<JD_SECOND);
×
1739
        if (fabs(lastJD-getJD())>JD_SECOND/4)
×
1740
        {
1741
                lastJD = getJD();
×
1742
                previousResult = (fabs(getJD()-(StelUtils::getJDFromSystem()))<JD_SECOND);
×
1743
        }
1744
        return previousResult;
×
1745
}
1746

1747
QTime StelCore::getInitTodayTime(void) const
×
1748
{
1749
        return initTodayTime;
×
1750
}
1751

1752
void StelCore::setInitTodayTime(const QTime& time)
×
1753
{
1754
        StelApp::immediateSave("navigation/today_time", time);
×
1755
        initTodayTime=time;
×
1756
}
×
1757

1758
void StelCore::setPresetSkyTime(QDateTime dateTime)
×
1759
{
1760
        setPresetSkyTime(StelUtils::qDateTimeToJd(dateTime));
×
1761
}
×
1762

1763
void StelCore::addMinute()
×
1764
{
1765
        addSolarDays(JD_MINUTE);
×
1766
}
×
1767

1768
void StelCore::addHour()
×
1769
{
1770
        addSolarDays(JD_HOUR);
×
1771
}
×
1772

1773
void StelCore::addDay()
×
1774
{
1775
        addSolarDays(1.0);
×
1776
}
×
1777

1778
void StelCore::addWeek()
×
1779
{
1780
        addSolarDays(7.0);
×
1781
}
×
1782

1783
void StelCore::addSiderealDay()
×
1784
{
1785
        addSiderealDays(1.0);
×
1786
}
×
1787

1788
void StelCore::addSiderealWeek()
×
1789
{
1790
        addSiderealDays(7.0);
×
1791
}
×
1792

1793
void StelCore::addSiderealYear()
×
1794
{
1795
        addSiderealYears(1.);
×
1796
}
×
1797

1798
void StelCore::addSiderealYears(double n)
×
1799
{
1800
        double days = 365.256363004;
×
1801
        double sidereal = getLocalSiderealYearLength();
×
1802
        Planet::PlanetType ptype = getCurrentPlanet()->getPlanetType();
×
1803
        if (ptype!=Planet::isObserver && ptype!=Planet::isArtificial && sidereal>0.)
×
1804
                days = sidereal;
×
1805

1806
        addSolarDays(days*n);
×
1807
}
×
1808

1809
void StelCore::addSynodicMonth()
×
1810
{
1811
        addSolarDays(29.530588853);
×
1812
}
×
1813

1814
void StelCore::addSaros()
×
1815
{
1816
        // 223 synodic months
1817
        addSolarDays(223*29.530588853);
×
1818
}
×
1819

1820
void StelCore::addDraconicMonth()
×
1821
{
1822
        addSolarDays(27.212220817);
×
1823
}
×
1824

1825
void StelCore::addMeanTropicalMonth()
×
1826
{
1827
        addSolarDays(27.321582241);
×
1828
}
×
1829

1830
void StelCore::addCalendarMonth()
×
1831
{
1832
        double cjd = getJD();
×
1833
        int year, month, day, hour, minute, second;
1834
        StelUtils::getDateTimeFromJulianDay(cjd, &year, &month, &day, &hour, &minute, &second);
×
1835
        month++;
×
1836
        if (month>12)
×
1837
        {
1838
                month = 1;
×
1839
                year++;
×
1840
        }
1841
        StelUtils::getJDFromDate(&cjd, year, month, day, hour, minute, static_cast<float>(second));
×
1842
        setJD(cjd);
×
1843
}
×
1844

1845
void StelCore::addCalendarYear()
×
1846
{
1847
        double cjd = getJD();
×
1848
        int year, month, day, hour, minute, second;
1849
        StelUtils::getDateTimeFromJulianDay(cjd, &year, &month, &day, &hour, &minute, &second);
×
1850
        year++;
×
1851
        StelUtils::getJDFromDate(&cjd, year, month, day, hour, minute, static_cast<float>(second));
×
1852
        setJD(cjd);
×
1853
}
×
1854

1855
void StelCore::addCalendarDecade()
×
1856
{
1857
        double cjd = getJD();
×
1858
        int year, month, day, hour, minute, second;
1859
        StelUtils::getDateTimeFromJulianDay(cjd, &year, &month, &day, &hour, &minute, &second);
×
1860
        year+=10;
×
1861
        StelUtils::getJDFromDate(&cjd, year, month, day, hour, minute, static_cast<float>(second));
×
1862
        setJD(cjd);
×
1863
}
×
1864

1865
void StelCore::addCalendarCentury()
×
1866
{
1867
        double cjd = getJD();
×
1868
        int year, month, day, hour, minute, second;
1869
        StelUtils::getDateTimeFromJulianDay(cjd, &year, &month, &day, &hour, &minute, &second);
×
1870
        year+=100;
×
1871
        StelUtils::getJDFromDate(&cjd, year, month, day, hour, minute, static_cast<float>(second));
×
1872
        setJD(cjd);
×
1873
}
×
1874

1875
void StelCore::addAnomalisticMonth()
×
1876
{
1877
        addSolarDays(27.554549878);
×
1878
}
×
1879

1880
void StelCore::addAnomalisticYear()
×
1881
{
1882
        addAnomalisticYears(1.);
×
1883
}
×
1884

1885
void StelCore::addAnomalisticYears(double n)
×
1886
{
1887
        addSolarDays(365.259636*n);
×
1888
}
×
1889

1890
void StelCore::addDraconicYear()
×
1891
{
1892
        addSolarDays(346.620075883);
×
1893
}
×
1894

1895
void StelCore::addMeanTropicalYear()
×
1896
{
1897
        addMeanTropicalYears(1.0);
×
1898
}
×
1899

1900
void StelCore::addTropicalYear()
×
1901
{
1902
        // Source: J. Meeus. More Mathematical Astronomy Morsels. 2002, p. 358.
1903
        // Meeus, J. & Savoie, D. The history of the tropical year. Journal of the British Astronomical Association, vol.102, no.1, p.40-42
1904
        // http://articles.adsabs.harvard.edu//full/1992JBAA..102...40M
1905
        const double T = (getJD()-2451545.0)/365250.0;
×
1906
        addSolarDays(365.242189623 - T*(0.000061522 - T*(0.0000000609 + T*0.00000026525)));
×
1907
}
×
1908

1909
void StelCore::addMeanTropicalYears(double n)
×
1910
{        
1911
        // Source: https://en.wikipedia.org/wiki/Tropical_year#Mean_tropical_year_current_value
1912
        addSolarDays(365.2421897*n); // The mean tropical year on January 1, 2000
×
1913
}
×
1914

1915
void StelCore::addJulianYear()
×
1916
{
1917
        addJulianYears(1.);
×
1918
}
×
1919

1920
void StelCore::addGaussianYear()
×
1921
{
1922
        addSolarDays(365.2568983);
×
1923
}
×
1924

1925
void StelCore::addJulianYears(double n)
×
1926
{
1927
        addSolarDays(365.25*n);
×
1928
}
×
1929

1930
void StelCore::addGreatYear()
×
1931
{
1932
        addSiderealYears(25800);
×
1933
}
×
1934

1935
void StelCore::subtractMinute()
×
1936
{
1937
        addSolarDays(-JD_MINUTE);
×
1938
}
×
1939

1940
void StelCore::subtractHour()
×
1941
{
1942
        addSolarDays(-JD_HOUR);
×
1943
}
×
1944

1945
void StelCore::subtractDay()
×
1946
{
1947
        addSolarDays(-1.0);
×
1948
}
×
1949

1950
void StelCore::subtractWeek()
×
1951
{
1952
        addSolarDays(-7.0);
×
1953
}
×
1954

1955
void StelCore::subtractSiderealDay()
×
1956
{
1957
        addSiderealDays(-1.0);
×
1958
}
×
1959

1960
void StelCore::subtractSiderealWeek()
×
1961
{
1962
        addSiderealDays(-7.0);
×
1963
}
×
1964

1965
void StelCore::subtractSiderealYear()
×
1966
{
1967
        addSiderealYears(-1.);
×
1968
}
×
1969

1970
void StelCore::subtractSiderealYears(double n)
×
1971
{
1972
        addSiderealYears(-n);
×
1973
}
×
1974

1975
void StelCore::subtractSynodicMonth()
×
1976
{
1977
        addSolarDays(-29.530588853);
×
1978
}
×
1979

1980
void StelCore::subtractSaros()
×
1981
{
1982
        // 223 synodic months
1983
        addSolarDays(-223*29.530588853);
×
1984
}
×
1985

1986
void StelCore::subtractDraconicMonth()
×
1987
{
1988
        addSolarDays(-27.212220817);
×
1989
}
×
1990

1991
void StelCore::subtractMeanTropicalMonth()
×
1992
{
1993
        addSolarDays(-27.321582241);
×
1994
}
×
1995

1996
void StelCore::subtractCalendarMonth()
×
1997
{
1998
        double cjd = getJD();
×
1999
        int year, month, day, hour, minute, second;
2000
        StelUtils::getDateTimeFromJulianDay(cjd, &year, &month, &day, &hour, &minute, &second);
×
2001
        month--;
×
2002
        if (month<1)
×
2003
        {
2004
                month = 12;
×
2005
                year--;
×
2006
        }
2007
        StelUtils::getJDFromDate(&cjd, year, month, day, hour, minute, static_cast<float>(second));
×
2008
        setJD(cjd);
×
2009
}
×
2010

2011
void StelCore::subtractCalendarYear()
×
2012
{
2013
        double cjd = getJD();
×
2014
        int year, month, day, hour, minute, second;
2015
        StelUtils::getDateTimeFromJulianDay(cjd, &year, &month, &day, &hour, &minute, &second);
×
2016
        year--;
×
2017
        StelUtils::getJDFromDate(&cjd, year, month, day, hour, minute, static_cast<float>(second));
×
2018
        setJD(cjd);
×
2019
}
×
2020

2021
void StelCore::subtractCalendarDecade()
×
2022
{
2023
        double cjd = getJD();
×
2024
        int year, month, day, hour, minute, second;
2025
        StelUtils::getDateTimeFromJulianDay(cjd, &year, &month, &day, &hour, &minute, &second);
×
2026
        year-=10;
×
2027
        StelUtils::getJDFromDate(&cjd, year, month, day, hour, minute, static_cast<float>(second));
×
2028
        setJD(cjd);
×
2029
}
×
2030

2031
void StelCore::subtractCalendarCentury()
×
2032
{
2033
        double cjd = getJD();
×
2034
        int year, month, day, hour, minute, second;
2035
        StelUtils::getDateTimeFromJulianDay(cjd, &year, &month, &day, &hour, &minute, &second);
×
2036
        year-=100;
×
2037
        StelUtils::getJDFromDate(&cjd, year, month, day, hour, minute, static_cast<float>(second));
×
2038
        setJD(cjd);
×
2039
}
×
2040

2041
void StelCore::subtractGreatYear()
×
2042
{
2043
        subtractSiderealYears(25800);
×
2044
}
×
2045

2046
void StelCore::subtractAnomalisticMonth()
×
2047
{
2048
        addSolarDays(-27.554549878);
×
2049
}
×
2050

2051
void StelCore::subtractAnomalisticYear()
×
2052
{
2053
        subtractAnomalisticYears(1.);
×
2054
}
×
2055

2056
void StelCore::subtractAnomalisticYears(double n)
×
2057
{
2058
        addSolarDays(-365.259636*n);
×
2059
}
×
2060

2061
void StelCore::subtractDraconicYear()
×
2062
{
2063
        addSolarDays(-346.620075883);
×
2064
}
×
2065

2066
void StelCore::subtractTropicalYear()
×
2067
{
2068
        // Source: J. Meeus. More Mathematical Astronomy Morsels. 2002, p. 358.
2069
        double T = (getJD()-2451545.0)/365250.0;
×
2070
        addSolarDays(-(365.242189623 - T*(0.000061522 - T*(0.0000000609 + T*0.00000026525))));
×
2071
}
×
2072

2073
void StelCore::subtractMeanTropicalYear()
×
2074
{
2075
        addMeanTropicalYears(-1.0);
×
2076
}
×
2077

2078
void StelCore::subtractMeanTropicalYears(double n)
×
2079
{
2080
        addMeanTropicalYears(-1.0*n);
×
2081
}
×
2082

2083
void StelCore::subtractJulianYear()
×
2084
{
2085
        addSolarDays(-365.25);
×
2086
}
×
2087

2088
void StelCore::subtractGaussianYear()
×
2089
{
2090
        addSolarDays(-365.2568983);
×
2091
}
×
2092

2093
void StelCore::subtractJulianYears(double n)
×
2094
{
2095
        addSolarDays(-365.25*n);
×
2096
}
×
2097

2098
void StelCore::addSolarDays(double d)
×
2099
{
2100
        const PlanetP& home = getCurrentPlanet();
×
2101
        Planet::PlanetType ptype = home->getPlanetType();
×
2102
        if (ptype!=Planet::isArtificial && ptype!=Planet::isObserver)
×
2103
                d *= home->getMeanSolarDay();
×
2104

2105
        setJD(getJD() + d);
×
2106

2107
        if (qAbs(d)>0.99) // WTF: qAbs(d)>=1.0 not working here!
×
2108
                emit dateChanged();
×
2109
}
×
2110

2111
void StelCore::addSiderealDays(double d)
×
2112
{
2113
        const PlanetP& home = getCurrentPlanet();
×
2114
        Planet::PlanetType ptype = home->getPlanetType();
×
2115
        if (ptype!=Planet::isArtificial && ptype!=Planet::isObserver)
×
2116
                d *= home->getSiderealDay();
×
2117

2118
        setJD(getJD() + d);
×
2119
}
×
2120

2121
// Get the sidereal time of the prime meridian (i.e. Rotation Angle) shifted by the observer longitude
2122
double StelCore::getLocalSiderealTime() const
×
2123
{
2124
        // On Earth, this requires UT deliberately with all its faults, on other planets we use the more regular TT.
2125
        return (getCurrentPlanet()->getSiderealTime(getJD(), getJDE())+static_cast<double>(position->getCurrentLocation().getLongitude()))*M_PI/180.;
×
2126
}
2127

2128
//! Get the duration of a sidereal day for the current observer in day.
2129
double StelCore::getLocalSiderealDayLength() const
×
2130
{
2131
        return getCurrentPlanet()->getSiderealDay();
×
2132
}
2133

2134
//! Get the duration of a sidereal year for the current observer in days.
2135
double StelCore::getLocalSiderealYearLength() const
×
2136
{
2137
        return getCurrentPlanet()->getSiderealPeriod();
×
2138
}
2139

2140
QString StelCore::getStartupTimeMode() const
×
2141
{
2142
        return startupTimeMode;
×
2143
}
2144

2145
//! Increase the time speed
2146
void StelCore::increaseTimeSpeed()
×
2147
{
2148
        double s = getTimeRate();
×
2149
        if (s>=JD_SECOND) s*=10.;
×
2150
        else if (s<-JD_SECOND) s/=10.;
×
2151
        else if (s>=0.) s=JD_SECOND;
×
2152
        else s=0.;
×
2153
        setTimeRate(s);
×
2154
}
×
2155

2156
//! Decrease the time speed
2157
void StelCore::decreaseTimeSpeed()
×
2158
{
2159
        double s = getTimeRate();
×
2160
        if (s>JD_SECOND) s/=10.;
×
2161
        else if (s<=-JD_SECOND) s*=10.;
×
2162
        else if (s<=0.) s=-JD_SECOND;
×
2163
        else s=0.;
×
2164
        setTimeRate(s);
×
2165
}
×
2166

2167
void StelCore::increaseTimeSpeedLess()
×
2168
{
2169
        double s = getTimeRate();
×
2170
        if (s>=JD_SECOND) s*=2.;
×
2171
        else if (s<-JD_SECOND) s/=2.;
×
2172
        else if (s>=0.) s=JD_SECOND;
×
2173
        else s=0.;
×
2174
        setTimeRate(s);
×
2175
}
×
2176

2177
void StelCore::decreaseTimeSpeedLess()
×
2178
{
2179
        double s = getTimeRate();
×
2180
        if (s>JD_SECOND) s/=2.;
×
2181
        else if (s<=-JD_SECOND) s*=2.;
×
2182
        else if (s<=0.) s=-JD_SECOND;
×
2183
        else s=0.;
×
2184
        setTimeRate(s);
×
2185
}
×
2186

2187
void StelCore::setZeroTimeSpeed()
×
2188
{
2189
        setTimeRate(0);
×
2190
}
×
2191

2192
void StelCore::setRealTimeSpeed()
×
2193
{
2194
        setTimeRate(JD_SECOND);
×
2195
}
×
2196

2197
void StelCore::toggleRealTimeSpeed()
×
2198
{
2199
        (!getRealTimeSpeed()) ? setRealTimeSpeed() : setZeroTimeSpeed();
×
2200
}
×
2201

2202
bool StelCore::getRealTimeSpeed() const
×
2203
{
2204
        return (fabs(timeSpeed-JD_SECOND)<0.0000001);
×
2205
}
2206

2207
////////////////////////////////////////////////////////////////////////////////
2208
// Increment time
2209
void StelCore::updateTime(double deltaTime)
×
2210
{
2211
        if (getRealTimeSpeed())
×
2212
        {
2213
                JD.first = jdOfLastJDUpdate + (QDateTime::currentMSecsSinceEpoch() - milliSecondsOfLastJDUpdate) / 1000.0 * JD_SECOND;
×
2214
        }
2215
        else
2216
        {
2217
                JD.first = jdOfLastJDUpdate + (QDateTime::currentMSecsSinceEpoch() - milliSecondsOfLastJDUpdate) / 1000.0 * timeSpeed;
×
2218
        }
2219

2220
        // Fix time limits to -100000 to +100000 to prevent bugs
2221
        if (JD.first>38245309.499988) JD.first = 38245309.499988;
×
2222
        if (JD.first<-34803211.500012) JD.first = -34803211.500012;
×
2223
        JD.second=computeDeltaT(JD.first);
×
2224

2225
        if (position->isObserverLifeOver())
×
2226
        {
2227
                // Unselect if the new home planet is the previously selected object
2228
                StelObjectMgr* objmgr = GETSTELMODULE(StelObjectMgr);
×
2229
                Q_ASSERT(objmgr);
×
2230
                if (objmgr->getWasSelected() && objmgr->getSelectedObject()[0].data()==getCurrentPlanet())
×
2231
                {
2232
                        objmgr->unSelect();
×
2233
                }
2234
                StelObserver* newObs = position->getNextObserver();
×
2235
                delete position;
×
2236
                position = newObs;
×
2237
        }
2238
        if (position && position->update(deltaTime))
×
2239
        {
2240
                emit locationChanged(getCurrentLocation());
×
2241
        }
2242

2243
        // Position of sun and all the satellites (ie planets)
2244
        // GZ maybe setting this static can speedup a bit?
2245
        static SolarSystem* solsystem = static_cast<SolarSystem*>(StelApp::getInstance().getModuleMgr().getModule("SolarSystem"));
×
2246
        // Likely the most important location where we need JDE:
2247
        solsystem->computePositions(this, getJDE(), getCurrentPlanet());
×
2248
}
×
2249

2250
void StelCore::resetSync()
×
2251
{
2252
        jdOfLastJDUpdate = getJD();
×
2253
        //use currentMsecsSinceEpoch directly instead of StelApp::getTotalRuntime,
2254
        //because the StelApp::startMSecs gets subtracted anyways in update()
2255
        //also changed to qint64 to increase precision
2256
        milliSecondsOfLastJDUpdate = QDateTime::currentMSecsSinceEpoch();
×
2257
        emit timeSyncOccurred(jdOfLastJDUpdate);
×
2258
}
×
2259

2260
void StelCore::registerMathMetaTypes()
×
2261
{
2262
        //enables use of these types in QVariant, StelProperty, signals and slots
2263
        qRegisterMetaType<Vec2d>();
×
2264
        qRegisterMetaType<Vec2f>();
×
2265
        qRegisterMetaType<Vec2i>();
×
2266
        qRegisterMetaType<Vec3d>();
×
2267
        qRegisterMetaType<Vec3f>();
×
2268
        qRegisterMetaType<Vec3i>();
×
2269
        qRegisterMetaType<Vec4d>();
×
2270
        qRegisterMetaType<Vec4f>();
×
2271
        qRegisterMetaType<Vec4i>();
×
2272
        qRegisterMetaType<Mat4d>();
×
2273
        qRegisterMetaType<Mat4f>();
×
2274
        qRegisterMetaType<Mat3d>();
×
2275
        qRegisterMetaType<Mat3f>();
×
2276
        qRegisterMetaType<DitheringMode>();
×
2277

2278
#if (QT_VERSION<QT_VERSION_CHECK(6,0,0))
2279
        //registers the QDataStream operators, so that QVariants with these types can be saved
2280
        qRegisterMetaTypeStreamOperators<Vec2d>();
2281
        qRegisterMetaTypeStreamOperators<Vec2f>();
2282
        qRegisterMetaTypeStreamOperators<Vec2i>();
2283
        qRegisterMetaTypeStreamOperators<Vec3d>();
2284
        qRegisterMetaTypeStreamOperators<Vec3f>();
2285
        qRegisterMetaTypeStreamOperators<Vec3i>();
2286
        qRegisterMetaTypeStreamOperators<Vec4d>();
2287
        qRegisterMetaTypeStreamOperators<Vec4f>();
2288
        qRegisterMetaTypeStreamOperators<Vec4i>();
2289
        qRegisterMetaTypeStreamOperators<Mat4d>();
2290
        qRegisterMetaTypeStreamOperators<Mat4f>();
2291
        qRegisterMetaTypeStreamOperators<Mat3d>();
2292
        qRegisterMetaTypeStreamOperators<Mat3f>();
2293
        qRegisterMetaTypeStreamOperators<DitheringMode>();
2294
#endif
2295
        //for debugging QVariants with these types, it helps if we register the string converters
2296
        // This is also required for QJSEngine.
2297
        QMetaType::registerConverter(&Vec2d::toString);
×
2298
        QMetaType::registerConverter(&Vec2f::toString);
×
2299
        QMetaType::registerConverter(&Vec2i::toString);
×
2300
        QMetaType::registerConverter(&Vec3d::toString);
×
2301
        QMetaType::registerConverter(&Vec3f::toString);
×
2302
        QMetaType::registerConverter(&Vec3i::toString);
×
2303
        QMetaType::registerConverter(&Vec4d::toString);
×
2304
        QMetaType::registerConverter(&Vec4f::toString);
×
2305
        QMetaType::registerConverter(&Vec4i::toString);
×
2306

2307
        //Hopefully this works to convert types in scripts when given as String "[...]"
2308
        // Maybe even make brackets optional!
2309
        // Nope, does not work for QJSEngine.
2310
//        QMetaType::registerConverter<QString, Vec2d>(&Vec2d::fromBracketedString);
2311
//        QMetaType::registerConverter<QString, Vec2f>(&Vec2f::fromBracketedString);
2312
//        QMetaType::registerConverter<QString, Vec2i>(&Vec2i::fromBracketedString);
2313
//        QMetaType::registerConverter<QString, Vec3d>(&Vec3d::fromBracketedString);
2314
//        QMetaType::registerConverter<QString, Vec3f>(&Vec3f::fromBracketedString);
2315
//        QMetaType::registerConverter<QString, Vec3i>(&Vec3i::fromBracketedString);
2316
//        QMetaType::registerConverter<QString, Vec4d>(&Vec4d::fromBracketedString);
2317
//        QMetaType::registerConverter<QString, Vec4f>(&Vec4f::fromBracketedString);
2318
//        QMetaType::registerConverter<QString, Vec4i>(&Vec4i::fromBracketedString);
2319
}
×
2320

2321
void StelCore::setStartupTimeMode(const QString& s)
×
2322
{
2323
        StelApp::immediateSave("navigation/startup_time_mode", s);
×
2324
        startupTimeMode = s;
×
2325
}
×
2326

2327
// return precomputed DeltaT in seconds. Public.
2328
double StelCore::getDeltaT() const
×
2329
{
2330
        return JD.second;
×
2331
}
2332

2333

2334
// compute and return DeltaT in seconds. Try not to call it directly, current DeltaT, JD, and JDE are available.
2335
double StelCore::computeDeltaT(const double JD)
×
2336
{
2337
        double DeltaT = 0.;
×
2338
        if (currentDeltaTAlgorithm==Custom)
×
2339
        {
2340
                // User defined coefficients for quadratic equation for DeltaT may change frequently.
2341
                deltaTnDot = deltaTCustomNDot; // n.dot = custom value "/cy/cy
×
2342
                int year, month, day;
2343
                StelUtils::getDateFromJulianDay(JD, &year, &month, &day);
×
2344
                double u = (StelUtils::yearFraction(year,month,day)-getDeltaTCustomYear())/100.;
×
2345
                DeltaT = deltaTCustomEquationCoeff[0] + u*(deltaTCustomEquationCoeff[1] + u*deltaTCustomEquationCoeff[2]);
×
2346
        }
2347

2348
        else
2349
        {
2350
                Q_ASSERT(deltaTfunc);
×
2351
                DeltaT=deltaTfunc(JD);
×
2352
        }
2353

2354
        if (!deltaTdontUseMoon)
×
2355
                DeltaT += StelUtils::getMoonSecularAcceleration(JD, deltaTnDot, ((de440Active&&EphemWrapper::jd_fits_de440(JD)) ||
×
2356
                                                                                 (de441Active&&EphemWrapper::jd_fits_de441(JD)) ||
×
2357
                                                                                 (de430Active&&EphemWrapper::jd_fits_de430(JD)) ||
×
2358
                                                                                 (de431Active&&EphemWrapper::jd_fits_de431(JD))));
×
2359

2360
        return DeltaT;
×
2361
}
2362

2363
// set a function pointer here. This should make the actual computation simpler by just calling the function.
2364
void StelCore::setCurrentDeltaTAlgorithm(DeltaTAlgorithm algorithm)
×
2365
{
2366
        currentDeltaTAlgorithm=algorithm;
×
2367
        deltaTdontUseMoon = false; // most algorithms will use it!
×
2368
        switch (currentDeltaTAlgorithm)
×
2369
        {
2370
                case WithoutCorrection:
×
2371
                        // Without correction, DeltaT is disabled
2372
                        deltaTfunc = StelUtils::getDeltaTwithoutCorrection;
×
2373
                        deltaTnDot = -26.; // n.dot = -26.0"/cy/cy OR WHAT SHALL WE DO HERE?
×
2374
                        deltaTdontUseMoon = true;
×
2375
                        deltaTstart        = INT_MIN;
×
2376
                        deltaTfinish        = INT_MAX;
×
2377
                        break;
×
2378
                case Schoch:
×
2379
                        // Schoch (1931) algorithm for DeltaT
2380
                        deltaTnDot = -29.68; // n.dot = -29.68"/cy/cy
×
2381
                        deltaTfunc = StelUtils::getDeltaTBySchoch;
×
2382
                        deltaTstart        = -300;
×
2383
                        deltaTfinish        = 1980;
×
2384
                        break;
×
2385
                case Clemence:
×
2386
                        // Clemence (1948) algorithm for DeltaT
2387
                        deltaTnDot = -22.44; // n.dot = -22.44 "/cy/cy
×
2388
                        deltaTfunc = StelUtils::getDeltaTByClemence;
×
2389
                        deltaTstart        = 1681;
×
2390
                        deltaTfinish        = 1900;
×
2391
                        break;
×
2392
                case IAU:
×
2393
                        // IAU (1952) algorithm for DeltaT, based on observations by Spencer Jones (1939)
2394
                        deltaTnDot = -22.44; // n.dot = -22.44 "/cy/cy
×
2395
                        deltaTfunc = StelUtils::getDeltaTByIAU;
×
2396
                        deltaTstart        = 1681;
×
2397
                        deltaTfinish        = 1936; // Details in http://adsabs.harvard.edu/abs/1939MNRAS..99..541S
×
2398
                        break;
×
2399
                case AstronomicalEphemeris:
×
2400
                        // Astronomical Ephemeris (1960) algorithm for DeltaT
2401
                        deltaTnDot = -22.44; // n.dot = -22.44 "/cy/cy
×
2402
                        deltaTfunc = StelUtils::getDeltaTByAstronomicalEphemeris;
×
2403
                        // GZ: What is the source of "1681..1900"? Expl.Suppl.AE 1961-p87 says "...over periods extending back to ancient times"
2404
                        // I changed to what I estimate.
2405
                        deltaTstart        = -500; // 1681;
×
2406
                        deltaTfinish        =  2000; // 1900;
×
2407
                        break;
×
2408
                case TuckermanGoldstine:
×
2409
                        // Tuckerman (1962, 1964) & Goldstine (1973) algorithm for DeltaT
2410
                        //FIXME: n.dot
2411
                        deltaTnDot = -22.44; // n.dot = -22.44 "/cy/cy ???
×
2412
                        deltaTfunc = StelUtils::getDeltaTByTuckermanGoldstine;
×
2413
                        deltaTstart        = -600;
×
2414
                        deltaTfinish        = 1649;
×
2415
                        break;
×
2416
                case MullerStephenson:
×
2417
                        // Muller & Stephenson (1975) algorithm for DeltaT
2418
                        deltaTnDot = -37.5; // n.dot = -37.5 "/cy/cy
×
2419
                        deltaTfunc = StelUtils::getDeltaTByMullerStephenson;
×
2420
                        deltaTstart        = -1375;
×
2421
                        deltaTfinish        = 1975;
×
2422
                        break;
×
2423
                case Stephenson1978:
×
2424
                        // Stephenson (1978) algorithm for DeltaT
2425
                        deltaTnDot = -30.0; // n.dot = -30.0 "/cy/cy
×
2426
                        deltaTfunc = StelUtils::getDeltaTByStephenson1978;
×
2427
                        deltaTstart        = INT_MIN; // Range unknown!
×
2428
                        deltaTfinish        = INT_MAX;
×
2429
                        break;
×
2430
                case SchmadelZech1979:
×
2431
                        // Schmadel & Zech (1979) algorithm for DeltaT
2432
                        deltaTnDot = -23.8946; // n.dot = -23.8946 "/cy/cy
×
2433
                        deltaTfunc = StelUtils::getDeltaTBySchmadelZech1979;
×
2434
                        deltaTstart        = 1800;
×
2435
                        deltaTfinish        = 1975;
×
2436
                        break;
×
2437
                case MorrisonStephenson1982:
×
2438
                        // Morrison & Stephenson (1982) algorithm for DeltaT (used by RedShift)
2439
                        deltaTnDot = -26.0; // n.dot = -26.0 "/cy/cy
×
2440
                        deltaTfunc = StelUtils::getDeltaTByMorrisonStephenson1982;
×
2441
                        // FIXME: Is it valid range?
2442
                        deltaTstart        = -4000;
×
2443
                        deltaTfinish        = 2800;
×
2444
                        break;
×
2445
                case StephensonMorrison1984:
×
2446
                        // Stephenson & Morrison (1984) algorithm for DeltaT
2447
                        deltaTnDot = -26.0; // n.dot = -26.0 "/cy/cy
×
2448
                        deltaTfunc = StelUtils::getDeltaTByStephensonMorrison1984;
×
2449
                        deltaTstart        = -391;
×
2450
                        deltaTfinish        = 1600; // TODO: 1630..1980 are tabulated values
×
2451
                        break;
×
2452
                case StephensonHoulden:
×
2453
                        // Stephenson & Houlden (1986) algorithm for DeltaT.
2454
                        deltaTnDot = -26.0; // n.dot = -26.0 "/cy/cy
×
2455
                        deltaTfunc = StelUtils::getDeltaTByStephensonHoulden;
×
2456
                        deltaTstart        = -1500;
×
2457
                        deltaTfinish        = 1600; // TODO: 1630..1980 are tabulated values from Stephenson & Morrison (1984)
×
2458
                        break;
×
2459
                case Espenak:
×
2460
                        // Espenak (1987, 1989) algorithm for DeltaT
2461
                        //FIXME: n.dot
2462
                        deltaTnDot = -23.8946; // n.dot = -23.8946 "/cy/cy ???
×
2463
                        deltaTfunc = StelUtils::getDeltaTByEspenak;
×
2464
                        deltaTstart        = 1950;
×
2465
                        deltaTfinish        = 2100;
×
2466
                        break;
×
2467
                case Borkowski:
×
2468
                        // Borkowski (1988) algorithm for DeltaT, relates to ELP2000-85!
2469
                        deltaTnDot = -23.895; // GZ: I see -23.895 in the paper, not -23.859; (?) // n.dot = -23.859 "/cy/cy
×
2470
                        deltaTfunc = StelUtils::getDeltaTByBorkowski;
×
2471
                        deltaTstart        = -2136;
×
2472
                        deltaTfinish        = 1715;
×
2473
                        break;
×
2474
                case SchmadelZech1988:
×
2475
                        // Schmadel & Zech (1988) algorithm for DeltaT
2476
                        //FIXME: n.dot
2477
                        deltaTnDot = -26.0; // n.dot = -26.0 "/cy/cy ???
×
2478
                        deltaTfunc = StelUtils::getDeltaTBySchmadelZech1988;
×
2479
                        deltaTstart        = 1800;
×
2480
                        deltaTfinish        = 1988;
×
2481
                        break;
×
2482
                case ChaprontTouze:
×
2483
                        // Chapront-Touzé & Chapront (1991) algorithm for DeltaT
2484
                        deltaTnDot = -23.8946; // n.dot = -23.8946 "/cy/cy
×
2485
                        deltaTfunc = StelUtils::getDeltaTByChaprontTouze;
×
2486
                        // FIXME: Is it valid range?
2487
                        deltaTstart        = -4000;
×
2488
                        deltaTfinish        = 8000;
×
2489
                        break;
×
2490
                case StephensonMorrison1995:
×
2491
                        // Stephenson & Morrison (1995) algorithm for DeltaT
2492
                        deltaTnDot = -26.0; // n.dot = -26.0 "/cy/cy
×
2493
                        deltaTfunc = StelUtils::getDeltaTByStephensonMorrison1995;
×
2494
                        deltaTstart        = -700;
×
2495
                        deltaTfinish        = 1600;
×
2496
                        break;
×
2497
                case Stephenson1997:
×
2498
                        // Stephenson (1997) algorithm for DeltaT
2499
                        deltaTnDot = -26.0; // n.dot = -26.0 "/cy/cy
×
2500
                        deltaTfunc = StelUtils::getDeltaTByStephenson1997;
×
2501
                        deltaTstart        = -500;
×
2502
                        deltaTfinish        = 1600;
×
2503
                        break;
×
2504
                case ChaprontMeeus:
×
2505
                        // Chapront, Chapront-Touze & Francou (1997) & Meeus (1998) algorithm for DeltaT
2506
                        deltaTnDot = -25.7376; // n.dot = -25.7376 "/cy/cy
×
2507
                        deltaTfunc = StelUtils::getDeltaTByChaprontMeeus;
×
2508
                        deltaTstart        = -400; // 1800; // not explicitly given, but guess based on his using ChaprontFrancou which is cited elsewhere in a similar term with -391.
×
2509
                        deltaTfinish        =  2150; // 1997;
×
2510
                        break;
×
2511
                case JPLHorizons:
×
2512
                        // JPL Horizons algorithm for DeltaT
2513
                        deltaTnDot = -25.7376; // n.dot = -25.7376 "/cy/cy
×
2514
                        deltaTfunc = StelUtils::getDeltaTByJPLHorizons;
×
2515
                        deltaTstart        = -2999;
×
2516
                        deltaTfinish        = 1620;
×
2517
                        break;
×
2518
                case MeeusSimons:
×
2519
                        // Meeus & Simons (2000) algorithm for DeltaT
2520
                        deltaTnDot = -25.7376; // n.dot = -25.7376 "/cy/cy
×
2521
                        deltaTfunc = StelUtils::getDeltaTByMeeusSimons;
×
2522
                        deltaTstart        = 1620;
×
2523
                        deltaTfinish        = 2000;
×
2524
                        break;
×
2525
                case ReingoldDershowitz:
×
2526
                        // Reingold & Dershowitz (2002, 2007, 2018) algorithm for DeltaT
2527
                        // FIXME: n.dot
2528
                        deltaTnDot = -26.0; // n.dot = -26.0 "/cy/cy ???
×
2529
                        deltaTfunc = StelUtils::getDeltaTByReingoldDershowitz;
×
2530
                        // GZ: while not original work, it's based on Meeus and therefore the full implementation covers likewise approximately:
2531
                        // AW: limits from 4th edition:
2532
                        deltaTstart        = -500; //1620;
×
2533
                        deltaTfinish        = 2150; //2019;
×
2534
                        break;
×
2535
                case MontenbruckPfleger:
×
2536
                        // Montenbruck & Pfleger (2000) algorithm for DeltaT
2537
                        // NOTE: book does not contain n.dot value
2538
                        // FIXME: n.dot
2539
                        deltaTnDot = -26.0; // n.dot = -26.0 "/cy/cy ???
×
2540
                        deltaTfunc = StelUtils::getDeltaTByMontenbruckPfleger;
×
2541
                        deltaTstart        = 1825;
×
2542
                        deltaTfinish        = 2005;
×
2543
                        break;
×
2544
                case MorrisonStephenson2004:
×
2545
                        // Morrison & Stephenson (2004, 2005) algorithm for DeltaT
2546
                        deltaTnDot = -26.0; // n.dot = -26.0 "/cy/cy
×
2547
                        deltaTfunc = StelUtils::getDeltaTByMorrisonStephenson2004;
×
2548
                        deltaTstart        = -1000;
×
2549
                        deltaTfinish        = 2000;
×
2550
                        break;
×
2551
                case Reijs:
×
2552
                        // Reijs (2006) algorithm for DeltaT
2553
                        deltaTnDot = -26.0; // n.dot = -26.0 "/cy/cy
×
2554
                        deltaTfunc = StelUtils::getDeltaTByReijs;
×
2555
                        deltaTstart        = -1500; // -500; // GZ: It models long-term variability, so we should reflect this. Not sure on the begin, though.
×
2556
                        deltaTfinish        = 1100; // not 1620; // GZ: Not applicable for telescopic era, and better not after 1100 (pers.comm.)
×
2557
                        break;
×
2558
                case EspenakMeeus:
×
2559
                        // Espenak & Meeus (2006, 2014) algorithm for DeltaT
2560
                        deltaTnDot = -25.858; // n.dot = -25.858 "/cy/cy
×
2561
                        deltaTfunc = StelUtils::getDeltaTByEspenakMeeus;
×
2562
                        deltaTstart        = -1999;
×
2563
                        deltaTfinish        = 3000;
×
2564
                        break;
×
2565
                case EspenakMeeusModified:
×
2566
                        // Espenak & Meeus (2006, 2014) algorithm (with modified formulae) for DeltaT
2567
                        deltaTnDot = -25.858; // n.dot = -25.858 "/cy/cy
×
2568
                        deltaTfunc = StelUtils::getDeltaTByEspenakMeeusModified;
×
2569
                        deltaTstart        = -1999;
×
2570
                        deltaTfinish        = 3000;
×
2571
                        break;
×
2572
                case EspenakMeeusZeroMoonAccel:
×
2573
                        // This is a trying area. Something is wrong with DeltaT, maybe ndot is still not applied correctly.
2574
                        // Espenak & Meeus (2006, 2014) algorithm for DeltaT
2575
                        deltaTnDot = -25.858; // n.dot = -25.858 "/cy/cy
×
2576
                        deltaTdontUseMoon = true;
×
2577
                        deltaTfunc = StelUtils::getDeltaTByEspenakMeeus;
×
2578
                        deltaTstart        = -1999;
×
2579
                        deltaTfinish        = 3000;
×
2580
                        break;
×
2581
                case Banjevic:
×
2582
                        // Banjevic (2006) algorithm for DeltaT
2583
                        deltaTnDot = -26.0; // n.dot = -26.0 "/cy/cy
×
2584
                        deltaTfunc = StelUtils::getDeltaTByBanjevic;
×
2585
                        deltaTstart        = -2020;
×
2586
                        deltaTfinish        = 1620;
×
2587
                        break;
×
2588
                case IslamSadiqQureshi:
×
2589
                        // Islam, Sadiq & Qureshi (2008 + revisited 2013) algorithm for DeltaT (6 polynomials)
2590
                        deltaTnDot = -26.0; // n.dot = -26.0 "/cy/cy
×
2591
                        deltaTfunc = StelUtils::getDeltaTByIslamSadiqQureshi;
×
2592
                        deltaTdontUseMoon = true; // Seems this solutions doesn't use value of secular acceleration of the Moon
×
2593
                        deltaTstart        = 1620;
×
2594
                        deltaTfinish        = 2007;
×
2595
                        break;
×
2596
                case KhalidSultanaZaidi:
×
2597
                        // M. Khalid, Mariam Sultana and Faheem Zaidi polynomial approximation of time period 1620-2013 (2014)
2598
                        deltaTnDot = -26.0; // n.dot = -26.0 "/cy/cy
×
2599
                        deltaTfunc = StelUtils::getDeltaTByKhalidSultanaZaidi;
×
2600
                        deltaTdontUseMoon = true; // Seems this solutions doesn't use value of secular acceleration of the Moon
×
2601
                        deltaTstart        = 1620;
×
2602
                        deltaTfinish        = 2013;
×
2603
                        break;
×
2604
                case StephensonMorrisonHohenkerk2016:
×
2605
                        deltaTnDot = -25.82; // n.dot = -25.82 "/cy/cy
×
2606
                        deltaTfunc=StelUtils::getDeltaTByStephensonMorrisonHohenkerk2016;
×
2607
                        deltaTstart        = -720;
×
2608
                        deltaTfinish        = 2019;
×
2609
                        break;
×
2610
                case Henriksson2017:
×
2611
                        // Henriksson solution (2017) for Schoch formula for DeltaT (1931)
2612
                        // Source: The Acceleration of the Moon and the Universe – the Mass of the Graviton.
2613
                        // Henriksson, G.
2614
                        // Advances in Astrophysics, Vol. 2, No. 3, August 2017
2615
                        // https://doi.org/10.22606/adap.2017.23004
2616
                        deltaTnDot = -30.128; // n.dot = -30.128"/cy/cy
×
2617
                        deltaTfunc = StelUtils::getDeltaTBySchoch;
×
2618
                        deltaTstart        = -4000;
×
2619
                        deltaTfinish        = 2000;
×
2620
                        break;
×
2621
                case Custom:
×
2622
                        // User defined coefficients for quadratic equation for DeltaT. These can change, and we don't use the function pointer here.
2623
                        deltaTnDot = deltaTCustomNDot; // n.dot = custom value "/cy/cy
×
2624
                        deltaTfunc=Q_NULLPTR;
×
2625
                        deltaTstart        = INT_MIN; // Range unknown!
×
2626
                        deltaTfinish        = INT_MAX;
×
2627
                        break;
×
2628
                default:
×
2629
                        deltaTnDot = -26.0; // n.dot = -26.0 "/cy/cy
×
2630
                        deltaTfunc=Q_NULLPTR;
×
2631
                        deltaTstart        = INT_MIN; // Range unknown!
×
2632
                        deltaTfinish        = INT_MAX;
×
2633
                        qCritical() << "StelCore: unknown DeltaT algorithm selected (" << currentDeltaTAlgorithm << ")! (setting nDot=-26., but no function!!)";
×
2634
        }
2635
        Q_ASSERT((currentDeltaTAlgorithm==Custom) || (deltaTfunc!=Q_NULLPTR));
×
2636
}
×
2637

2638
//! Set the current algorithm for time correction to use
2639
void StelCore::setCurrentDeltaTAlgorithmKey(QString key)
×
2640
{
2641
        const QMetaEnum& en = metaObject()->enumerator(metaObject()->indexOfEnumerator("DeltaTAlgorithm"));
×
2642
        DeltaTAlgorithm algo = static_cast<DeltaTAlgorithm>(en.keyToValue(key.toLatin1().data()));
×
2643
        if (algo<0)
×
2644
        {
2645
                qWarning() << "Unknown DeltaT algorithm: " << key << "setting \"WithoutCorrection\" instead";
×
2646
                algo = WithoutCorrection;
×
2647
        }
2648
        StelApp::immediateSave("navigation/time_correction_algorithm", key);
×
2649
        setCurrentDeltaTAlgorithm(algo);
×
2650
}
×
2651

2652
//! Get the current algorithm used by the DeltaT
2653
QString StelCore::getCurrentDeltaTAlgorithmKey(void) const
×
2654
{
2655
        return metaObject()->enumerator(metaObject()->indexOfEnumerator("DeltaTAlgorithm")).key(currentDeltaTAlgorithm);
×
2656
}
2657

2658
//! Get description of the current algorithm for time correction
2659
QString StelCore::getCurrentDeltaTAlgorithmDescription(void) const
×
2660
{
2661
        // GZ remarked where more info would be desirable. Generally, a full citation and the math. term would be nice to have displayed if it's just one formula, and the range of valid dates.
2662
        QString description;
×
2663
        double jd = 0;
×
2664
        QString marker;
×
2665
        switch (getCurrentDeltaTAlgorithm())
×
2666
        {
2667
                case WithoutCorrection:
×
2668
                        description = q_("Correction is disabled. Use only if you know what you are doing!");
×
2669
                        break;
×
2670
                case Schoch: // historical value.
×
2671
                        description = q_("This historical formula was obtained by C. Schoch in 1931 and was used by G. Henriksson in his article <em>Einstein's Theory of Relativity Confirmed by Ancient Solar Eclipses</em> (%1). See for more info %2here%3.").arg("2009", "<a href='http://journalofcosmology.com/AncientAstronomy123.html'>", "</a>").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2672
                        break;
×
2673
                case Clemence: // historical value.
×
2674
                        description = q_("This empirical equation was published by G. M. Clemence in the article <em>On the system of astronomical constants</em> (%1).").arg("<a href='http://adsabs.harvard.edu/abs/1948AJ.....53..169C'>1948</a>").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2675
                        break;
×
2676
                case IAU: // historical value.
×
2677
                        description = q_("This formula is based on a study of post-1650 observations of the Sun, the Moon and the planets by Spencer Jones (%1) and used by Jean Meeus in his <em>Astronomical Formulae for Calculators</em>. It was also adopted in the PC program SunTracker Pro.").arg("<a href='http://adsabs.harvard.edu/abs/1939MNRAS..99..541S'>1939</a>").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2678
                        // find year of publication of AFFC
2679
                        break;
×
2680
                case AstronomicalEphemeris: // historical value.
×
2681
                        description = q_("This is a slightly modified version of the IAU (1952) formula which was adopted in the <em>Astronomical Ephemeris</em> and in the <em>Canon of Solar Eclipses</em> by Mucke & Meeus (1983).").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2682
                        // TODO: expand the sentence: ... adopted ... from 19xx-19yy?
2683
                        break;
×
2684
                case TuckermanGoldstine: // historical value.
×
2685
                        description = q_("The tables of Tuckerman (1962, 1964) list the positions of the Sun, the Moon and the planets at 5- and 10-day intervals from 601 BCE to 1649 CE. The same relation was also implicitly adopted in the syzygy tables of Goldstine (1973).").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2686
                        // TODO: These tables are sometimes found cited, but I have no details. Maybe add "based on ... " ?
2687
                        break;
×
2688
                case MullerStephenson:
×
2689
                        description = q_("This equation was published by P. M. Muller and F. R. Stephenson in the article <em>The accelerations of the earth and moon from early astronomical observations</em> (%1).").arg("<a href='http://adsabs.harvard.edu/abs/1975grhe.conf..459M'>1975</a>").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2690
                        break;
×
2691
                case Stephenson1978:
×
2692
                        description = q_("This equation was published by F. R. Stephenson in the article <em>Pre-Telescopic Astronomical Observations</em> (%1).").arg("<a href='http://adsabs.harvard.edu/abs/1978tfer.conf....5S'>1978</a>").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2693
                        break;
×
2694
                case SchmadelZech1979: // outdated data fit, historical value?
×
2695
                        description = q_("This 12th-order polynomial equation (outdated and superseded by Schmadel & Zech (1988)) was published by L. D. Schmadel and G. Zech in the article <em>Polynomial approximations for the correction delta T E.T.-U.T. in the period 1800-1975</em> (%1) as fit through data published by Brouwer (1952).").arg("<a href='http://adsabs.harvard.edu/abs/1979AcA....29..101S'>1979</a>").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2696
                        break;
×
2697
                case MorrisonStephenson1982:
×
2698
                        description = q_("This algorithm was adopted in P. Bretagnon & L. Simon's <em>Planetary Programs and Tables from -4000 to +2800</em> (1986) and in the PC planetarium program RedShift.").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2699
                        break;
×
2700
                case StephensonMorrison1984: // PRIMARY SOURCE
×
2701
                        description = q_("This formula was published by F. R. Stephenson and L. V. Morrison in the article <em>Long-term changes in the rotation of the earth - 700 B.C. to A.D. 1980</em> (%1).").arg("<a href='http://adsabs.harvard.edu/abs/1984RSPTA.313...47S'>1984</a>").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2702
                        break;
×
2703
                case StephensonHoulden:
×
2704
                        description = q_("This algorithm was published by F. R. Stephenson and M. A. Houlden in the book <em>Atlas of Historical Eclipse Maps</em> (%1). This algorithm is used in the PC planetarium program Guide 7.").arg("<a href='https://assets.cambridge.org/97805212/67236/frontmatter/9780521267236_frontmatter.pdf'>1986</a>").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2705
                        break;
×
2706
                case Espenak: // limited range, but wide availability?
×
2707
                        description = q_("This algorithm was given by F. Espenak in his <em>Fifty Year Canon of Solar Eclipses: 1986-2035</em> (1987) and in his <em>Fifty Year Canon of Lunar Eclipses: 1986-2035</em> (1989).").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2708
                        break;
×
2709
                case Borkowski: // Linked to ELP2000-85, so it's important...
×
2710
                        description = q_("This formula was obtained by K.M. Borkowski (%1) from an analysis of 31 solar eclipse records dating between 2137 BCE and 1715 CE.").arg("<a href='http://adsabs.harvard.edu/abs/1988A&A...205L...8B'>1988</a>").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2711
                        break;
×
2712
                case SchmadelZech1988: // data fit through Stephenson&Morrison1984, which itself is important. Unclear who uses this version?
×
2713
                        description = q_("This 12th-order polynomial equation was published by L. D. Schmadel and G. Zech in the article <em>Empirical Transformations from U.T. to E.T. for the Period 1800-1988</em> (%1) as data fit through values given by Stephenson & Morrison (1984).").arg("<a href='http://adsabs.harvard.edu/abs/1988AN....309..219S'>1988</a>").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2714
                        break;
×
2715
                case ChaprontTouze:
×
2716
                        description = q_("This formula was adopted by M. Chapront-Touze & J. Chapront in the shortened version of the ELP 2000-85 lunar theory in their <em>Lunar Tables and Programs from 4000 B.C. to A.D. 8000</em> (1991).").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2717
                        break;
×
2718
                case StephensonMorrison1995:
×
2719
                        description = q_("This equation was published by F. R. Stephenson and L. V. Morrison in the article <em>Long-Term Fluctuations in the Earth's Rotation: 700 BC to AD 1990</em> (%1).").arg("<a href='http://adsabs.harvard.edu/abs/1995RSPTA.351..165S'>1995</a>").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2720
                        break;
×
2721
                case Stephenson1997:
×
2722
                        description = q_("F. R. Stephenson published this formula in his book <em>Historical Eclipses and Earth's Rotation</em> (%1).").arg("<a href='http://ebooks.cambridge.org/ebook.jsf?bid=CBO9780511525186'>1997</a>").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2723
                        break;
×
2724
                case ChaprontMeeus:
×
2725
                        description = q_("From J. Meeus, <em>Astronomical Algorithms</em> (2nd ed., 1998), and widely used. Table for 1620..2000, and includes a variant of Chapront, Chapront-Touze & Francou (1997) for dates outside 1620..2000.").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2726
                        break;
×
2727
                case JPLHorizons:
×
2728
                        description = q_("The JPL Solar System Dynamics Group of the NASA Jet Propulsion Laboratory use this formula in their interactive website %1JPL Horizons%2.").arg("<a href='http://ssd.jpl.nasa.gov/?horizons'>", "</a>").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2729
                        break;
×
2730
                case MeeusSimons:
×
2731
                        description = q_("This polynome was published by J. Meeus and L. Simons in article <em>Polynomial approximations to Delta T, 1620-2000 AD</em> (%1).").arg("<a href='http://adsabs.harvard.edu/abs/2000JBAA..110..323M'>2000</a>").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2732
                        break;
×
2733
                case MontenbruckPfleger: // uninspired
×
2734
                        description = q_("The fourth edition of O. Montenbruck & T. Pfleger's <em>Astronomy on the Personal Computer</em> (2000) provides simple 3rd-order polynomial data fits for the recent past.").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2735
                        break;
×
2736
                case ReingoldDershowitz: //
×
2737
                        description = q_("E. M. Reingold & N. Dershowitz present this polynomial data fit in <em>Calendrical Calculations</em> (4th ed. 2018) and in their <em>Calendrical Tabulations</em> (2002). It is based on Jean Meeus' <em>Astronomical Algorithms</em> (1991).").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2738
                        break;
×
2739
                case MorrisonStephenson2004: // PRIMARY SOURCE
×
2740
                        description = q_("This important solution was published by L. V. Morrison and F. R. Stephenson in article <em>Historical values of the Earth's clock error %1T and the calculation of eclipses</em> (%2) with addendum in (%3).").arg(QChar(0x0394)).arg("<a href='http://adsabs.harvard.edu/abs/2004JHA....35..327M'>2004</a>", "<a href='http://adsabs.harvard.edu/abs/2005JHA....36..339M'>2005</a>").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2741
                        break;
×
2742
                case Reijs:
×
2743
                        description = q_("From the Length of Day (LOD; as determined by Stephenson & Morrison (%2)), Victor Reijs derived a %1T formula by using a Simplex optimisation with a cosine and square function. This is based on a possible periodicy described by Stephenson (%2). See for more info %3here%4.").arg(QChar(0x0394)).arg("<a href='http://adsabs.harvard.edu/abs/2004JHA....35..327M'>2004</a>", "<a href='http://www.iol.ie/~geniet/eng/DeltaTeval.htm'>", "</a>").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2744
                        break;
×
2745
                case EspenakMeeus: // GENERAL SOLUTION
×
2746
                        description = q_("This solution by F. Espenak and J. Meeus, based on Morrison & Stephenson (2004) and a polynomial fit through tabulated values for 1600-2000, is used for the %1NASA Eclipse Web Site%2, in their <em>Five Millennium Canon of Solar Eclipses: -1900 to +3000</em> (2006) and <em>Thousand Year Canon of Solar Eclipses 1501 to 2500</em> (2014). This formula is also used in the solar, lunar and planetary ephemeris program SOLEX.").arg("<a href='http://eclipse.gsfc.nasa.gov/eclipse.html'>", "</a>").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2747
                        break;
×
2748
                case EspenakMeeusModified: // MODIFIED SOLUTION
×
2749
                        description = q_("This solution is modified from F. Espenak and J. Meeus, based on Morrison & Stephenson (2004) and a polynomial fit through tabulated values for 1600-2000. Values for 2015-2033 are interpolated from observations and predictions by IERS Rapid Service/Prediction Center.").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker)).append(" <em>").append(q_("Used by default.")).append("</em>");
×
2750
                        break;
×
2751
                case EspenakMeeusZeroMoonAccel: // PATCHED SOLUTION. Experimental, it may not make sense to keep it in V1.0.
×
2752
                        description = QString("%1 %2").arg(q_("PATCHED VERSION WITHOUT ADDITIONAL LUNAR ACCELERATION."), q_("This solution by F. Espenak and J. Meeus, based on Morrison & Stephenson (2004) and a polynomial fit through tabulated values for 1600-2000.")).append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2753
                        break;
×
2754
                case Banjevic:
×
2755
                        description = q_("This solution by B. Banjevic, based on Stephenson & Morrison (1984), was published in article <em>Ancient eclipses and dating the fall of Babylon</em> (%1).").arg("<a href='http://adsabs.harvard.edu/abs/2006POBeo..80..251B'>2006</a>").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2756
                        break;
×
2757
                case IslamSadiqQureshi:
×
2758
                        description = q_("This solution by S. Islam, M. Sadiq and M. S. Qureshi, based on Meeus & Simons (2000), was published in article <em>Error Minimization of Polynomial Approximation of DeltaT</em> (%1) and revisited by Sana Islam in 2013.").arg("<a href='http://www.ias.ac.in/article/fulltext/joaa/029/03-04/0363-0366'>2008</a>").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2759
                        break;
×
2760
                case KhalidSultanaZaidi:
×
2761
                        description = q_("This polynomial approximation with 0.6 seconds of accuracy by M. Khalid, Mariam Sultana and Faheem Zaidi was published in <em>Delta T: Polynomial Approximation of Time Period 1620-2013</em> (%1).").arg("<a href='https://doi.org/10.1155/2014/480964'>2014</a>").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2762
                        break;
×
2763
                case StephensonMorrisonHohenkerk2016: // PRIMARY SOURCE, SEEMS VERY IMPORTANT
×
2764
                        description = q_("This solution by F. R. Stephenson, L. V. Morrison and C. Y. Hohenkerk (2016) was published in <em>Measurement of the Earth’s rotation: 720 BC to AD 2015</em> (%1) and updated in <em>Addendum 2020 to 'Measurement of the Earth's Rotation: 720 BC to AD 2015'</em> (Morrison, L. V., Stephenson, F.R., Hohenkerk, C.Y. and Zawilski, M.; %2). Outside of the named range (modelled with a spline fit) it provides values from an approximate parabola.").arg("<a href='https://doi.org/10.1098/rspa.2016.0404'>2016</a>", "<a href='https://doi.org/10.1098/rspa.2020.0776'>2021</a>").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2765
                        break;
×
2766
                case Henriksson2017:
×
2767
                        description = q_("This solution by G. Henriksson was published in the article <em>The Acceleration of the Moon and the Universe - the Mass of the Graviton</em> (%1) and based on C. Schoch's formula (1931).").arg("<a href='https://doi.org/10.22606/adap.2017.23004'>2017</a>").append(getCurrentDeltaTAlgorithmValidRangeDescription(jd, &marker));
×
2768
                        break;
×
2769
                case Custom:
×
2770
                        description = q_("This is a quadratic formula for calculation of %1T with coefficients defined by the user.").arg(QChar(0x0394));
×
2771
                        break;
×
2772
                default:
×
2773
                        description = q_("Error");
×
2774
        }
2775

2776
        // Put n-dot value info
2777
        if (getCurrentDeltaTAlgorithm()!=WithoutCorrection)
×
2778
        {
2779
                QString accel = QString("%1\"/cy<sup>2</sup>").arg(QString::number(getDeltaTnDot(), 'f', 4));
×
2780
                QString ndot  = QString("&#x1E45;");
×
2781
                description.append(" " + q_("The solution's value of %1 for %2 (secular acceleration of the Moon) requires an adaptation, see Guide for details.").arg(accel, ndot));
×
2782
        }
×
2783

2784
        return description;
×
2785
}
×
2786

2787
QString StelCore::getCurrentDeltaTAlgorithmValidRangeDescription(const double JD, QString *marker) const
×
2788
{
2789
        QString validRange = "";
×
2790
        QString validRangeAppendix = "";
×
2791
        *marker = "";
×
2792
        int year, month, day;
2793

2794
        StelUtils::getDateFromJulianDay(JD, &year, &month, &day);
×
2795
        switch (currentDeltaTAlgorithm)
×
2796
        {
2797
                // These models provide extrapolated values outside their specified/recommended range.
2798
                case WithoutCorrection:      // and
×
2799
                case Schoch:                 // and
2800
                case Clemence:               // and
2801
                case IAU:                    // and
2802
                case AstronomicalEphemeris:  // and
2803
                case TuckermanGoldstine:     // and
2804
                case StephensonHoulden:      // and
2805
                case MullerStephenson:       // and
2806
                case Stephenson1978:         // and
2807
                case MorrisonStephenson1982: // and
2808
                case StephensonMorrison1984: // and
2809
                case Espenak:                // and
2810
                case Borkowski:              // and
2811
                case StephensonMorrison1995: // and
2812
                case Stephenson1997:         // and
2813
                case ChaprontMeeus:          // and
2814
                case ReingoldDershowitz:     // and
2815
                case MorrisonStephenson2004: // and
2816
                case Reijs:                  // and
2817
                case EspenakMeeus:           // range stated in the Canon, p. 14.  ... and
2818
                case EspenakMeeusModified:   // the default, range stated in the Canon, p. 14.  ... and
2819
                case EspenakMeeusZeroMoonAccel: // and
2820
                case StephensonMorrisonHohenkerk2016: // and
2821
                case Henriksson2017:
2822
                        break;
×
2823
                case JPLHorizons: // and
×
2824
                case MeeusSimons:
2825
                        validRangeAppendix = q_("with zero values outside this range");
×
2826
                        break;
×
2827
                case MontenbruckPfleger:
×
2828
                        validRangeAppendix = q_("with a typical 1-second accuracy and zero values outside this range");
×
2829
                        break;
×
2830
                case SchmadelZech1988:
×
2831
                        validRangeAppendix = q_("with a mean error of less than one second, max. error 1.9s, and values for the limit years outside this range");
×
2832
                        break;
×
2833
                case SchmadelZech1979:  // and
×
2834
                case ChaprontTouze:     // and
2835
                case Banjevic:          // and
2836
                case IslamSadiqQureshi: // and
2837
                case KhalidSultanaZaidi:
2838
                        validRangeAppendix = q_("with values for the limit years outside this range");
×
2839
                        break;
×
2840
                case Custom:
×
2841
                        // Valid range unknown
2842
                        break;
×
2843
        }
2844

2845
        if (deltaTstart > INT_MIN) // limits declared?
×
2846
        {
2847
                if (validRangeAppendix!="")
×
2848
                        validRange = q_("Valid range of usage: between years %1 and %2, %3.").arg(deltaTstart).arg(deltaTfinish).arg(validRangeAppendix);
×
2849
                else
2850
                        validRange = q_("Valid range of usage: between years %1 and %2.").arg(deltaTstart).arg(deltaTfinish);
×
2851
                if ((year < deltaTstart) || (deltaTfinish < year))
×
2852
                        *marker = "*"; // mark "outside designed range, possibly wrong"
×
2853
        }
2854
        else
2855
                *marker = "?"; // mark "no range given"
×
2856

2857
        return QString(" %1").arg(validRange);
×
2858
}
×
2859

2860
// return if sky plus atmosphere is bright enough from sunlight so that e.g. screen labels should be rendered dark.
2861
// DONE: Simply ask the atmosphere for its surrounding brightness
2862
// TODO2: This could be moved to the SkyDrawer or even some GUI class, as it is used to decide a GUI thing.
2863
bool StelCore::isBrightDaylight() const
×
2864
{
2865
        if (propMgr->getStelPropertyValue("Oculars.ocularDisplayed", true).toBool())
×
2866
                return false;
×
2867
        SolarSystem* ssys = GETSTELMODULE(SolarSystem);
×
2868
        if (!ssys->getFlagPlanets())
×
2869
                return false;
×
2870
        if (!getSkyDrawer()->getFlagHasAtmosphere())
×
2871
                return false;
×
2872
        if (ssys->getSolarEclipseFactor(this).first<=0.01) // Total solar eclipse
×
2873
                return false;
×
2874

2875
        // immediately decide upon sky background brightness...
2876
        return (GETSTELMODULE(LandscapeMgr)->getAtmosphereAverageLuminance() > static_cast<float>(getSkyDrawer()->getDaylightLabelThreshold()));
×
2877
}
2878

2879
double StelCore::getCurrentEpoch() const
×
2880
{
2881
        return 2000.0 + (getJD() - 2451545.0)/365.25;
×
2882
}
2883

2884
// DE430/DE431 handling.
2885
// NOTE: When DE431 is not available, DE430 installed, but date outside, de430IsActive() may be true but computations still go back to VSOP!
2886
// To test whether DE43x is really currently in use, test (EphemWrapper::use_de430(jd) || EphemWrapper::use_de431(jd))
2887

2888
bool StelCore::de430IsAvailable()
×
2889
{
2890
        return de430Available;
×
2891
}
2892

2893
bool StelCore::de431IsAvailable()
×
2894
{
2895
        return de431Available;
×
2896
}
2897

2898
bool StelCore::de430IsActive()
×
2899
{
2900
        return de430Active;
×
2901
}
2902

2903
bool StelCore::de431IsActive()
×
2904
{
2905
        return de431Active;
×
2906
}
2907

2908
void StelCore::setDe430Active(bool status)
×
2909
{
2910
        de430Active = de430Available && status;
×
2911
}
×
2912

2913
void StelCore::setDe431Active(bool status)
×
2914
{
2915
        de431Active = de431Available && status;
×
2916
}
×
2917

2918

2919
bool StelCore::de440IsAvailable()
×
2920
{
2921
        return de440Available;
×
2922
}
2923

2924
bool StelCore::de441IsAvailable()
×
2925
{
2926
        return de441Available;
×
2927
}
2928

2929
bool StelCore::de440IsActive()
×
2930
{
2931
        return de440Active;
×
2932
}
2933

2934
bool StelCore::de441IsActive()
×
2935
{
2936
        return de441Active;
×
2937
}
2938

2939
void StelCore::setDe440Active(bool status)
×
2940
{
2941
        de440Active = de440Available && status;
×
2942
}
×
2943

2944
void StelCore::setDe441Active(bool status)
×
2945
{
2946
        de441Active = de441Available && status;
×
2947
}
×
2948

2949
void StelCore::initEphemeridesFunctions()
×
2950
{
2951
        QSettings* conf = StelApp::getInstance().getSettings();
×
2952

2953
        QString de430ConfigPath = conf->value("astro/de430_path").toString();
×
2954
        QString de431ConfigPath = conf->value("astro/de431_path").toString();
×
2955
        QString de440ConfigPath = conf->value("astro/de440_path").toString();
×
2956
        QString de441ConfigPath = conf->value("astro/de441_path").toString();
×
2957

2958
        QString de430FilePath;
×
2959
        QString de431FilePath;
×
2960
        QString de440FilePath;
×
2961
        QString de441FilePath;
×
2962

2963
        //<-- DE430 -->
2964
        if(de430ConfigPath.remove(QChar('"')).isEmpty())
×
2965
                de430FilePath = StelFileMgr::findFile("ephem/" + QString(DE430_FILENAME), StelFileMgr::File);
×
2966
        else
2967
                de430FilePath = StelFileMgr::findFile(de430ConfigPath, StelFileMgr::File);
×
2968

2969
        de430Available=!de430FilePath.isEmpty();
×
2970
        if(de430Available)
×
2971
        {
2972
                qInfo().noquote() << "DE430 at:" << de430FilePath;
×
2973
                EphemWrapper::init_de430(de430FilePath.toStdString().c_str());
×
2974
        }
2975
        setDe430Active(de430Available && conf->value("astro/flag_use_de430", false).toBool());
×
2976

2977
        //<-- DE431 -->
2978
        if(de431ConfigPath.remove(QChar('"')).isEmpty())
×
2979
                de431FilePath = StelFileMgr::findFile("ephem/" + QString(DE431_FILENAME), StelFileMgr::File);
×
2980
        else
2981
                de431FilePath = StelFileMgr::findFile(de431ConfigPath, StelFileMgr::File);
×
2982

2983
        de431Available=!de431FilePath.isEmpty();
×
2984
        if(de431Available)
×
2985
        {
2986
                qInfo().noquote() << "DE431 at:" << de431FilePath;
×
2987
                EphemWrapper::init_de431(de431FilePath.toStdString().c_str());
×
2988
        }
2989
        setDe431Active(de431Available && conf->value("astro/flag_use_de431", false).toBool());
×
2990

2991
        //<-- DE440 -->
2992
        if(de440ConfigPath.remove(QChar('"')).isEmpty())
×
2993
                de440FilePath = StelFileMgr::findFile("ephem/" + QString(DE440_FILENAME), StelFileMgr::File);
×
2994
        else
2995
                de440FilePath = StelFileMgr::findFile(de440ConfigPath, StelFileMgr::File);
×
2996

2997
        de440Available=!de440FilePath.isEmpty();
×
2998
        if(de440Available)
×
2999
        {
3000
                qInfo().noquote() << "DE440 at:" << de440FilePath;
×
3001
                EphemWrapper::init_de440(de440FilePath.toStdString().c_str());
×
3002
        }
3003
        setDe440Active(de440Available && conf->value("astro/flag_use_de440", false).toBool());
×
3004

3005
        //<-- DE441 -->
3006
        if(de441ConfigPath.remove(QChar('"')).isEmpty())
×
3007
                de441FilePath = StelFileMgr::findFile("ephem/" + QString(DE441_FILENAME), StelFileMgr::File);
×
3008
        else
3009
                de441FilePath = StelFileMgr::findFile(de441ConfigPath, StelFileMgr::File);
×
3010

3011
        de441Available=!de441FilePath.isEmpty();
×
3012
        if(de441Available)
×
3013
        {
3014
                qInfo().noquote() << "DE441 at:" << de441FilePath;
×
3015
                EphemWrapper::init_de441(de441FilePath.toStdString().c_str());
×
3016
        }
3017
        setDe441Active(de441Available && conf->value("astro/flag_use_de441", false).toBool());
×
3018

3019
        minMaxEphemRange = qMakePair(-4000, 8000); // VSOP87
×
3020
        if (de430Active || de440Active)
×
3021
                minMaxEphemRange = qMakePair(1550, 2650);
×
3022
        if (de431Active || de441Active)
×
3023
                minMaxEphemRange = qMakePair(-13000, 17000);
×
3024
}
×
3025

3026
// Methods for finding constellation from J2000 position.
3027
typedef struct iau_constline{
3028
        double RAlow;  // low value of 1875.0 right ascension segment, HH.dddd
3029
        double RAhigh; // high value of 1875.0 right ascension segment, HH.dddd
3030
        double decLow; // declination 1875.0 of southern border, DD.dddd
3031
        QString constellation; // 3-letter code of constellation
3032
} iau_constelspan;
3033

3034
Q_GLOBAL_STATIC(QVector<iau_constelspan>, iau_constlineVec);
×
3035
static bool iau_constlineVecInitialized=false;
3036

3037
// File iau_constellations_spans.dat is converted from file data.dat from ADC catalog VI/42.
3038
// We converted back to HH:MM:SS format to avoid the inherent rounding errors present in that file (Bug LP:#1690615).
3039
QString StelCore::getIAUConstellation(const Vec3d &positionEqJnow) const
×
3040
{
3041
        Q_ASSERT(positionEqJnow.norm()>0); // Just make sure it looks like a valid posititon.
×
3042
        // Precess positionJ2000 to 1875.0
3043
        const Vec3d pos1875=j2000ToJ1875(equinoxEquToJ2000(positionEqJnow, RefractionOff));
×
3044
        double RA1875;
3045
        double dec1875;
3046
        StelUtils::rectToSphe(&RA1875, &dec1875, pos1875);
×
3047
        RA1875 *= 12./M_PI; // hours
×
3048
        if (RA1875 <0.) RA1875+=24.;
×
3049
        dec1875 *= M_180_PI; // degrees
×
3050
        Q_ASSERT(RA1875>=0.0);
×
3051
        Q_ASSERT(RA1875<=24.0);
×
3052
        Q_ASSERT(dec1875<=90.0);
×
3053
        Q_ASSERT(dec1875>=-90.0);
×
3054

3055
        // read file into structure.
3056
        if (!iau_constlineVecInitialized)
×
3057
        {
3058
                //struct iau_constline line;
3059
                QFile file(StelFileMgr::findFile("data/constellations_spans.dat"));
×
3060

3061
                if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
×
3062
                {
3063
                        qWarning() << "IAU constellation line data file data/constellations_spans.dat not found.";
×
3064
                        return "err";
×
3065
                }
3066
                iau_constelspan span;
×
3067
                static const QRegularExpression emptyLine("^\\s*$");
×
3068
                static const QRegularExpression spaceRe("\\s+");
×
3069
                QTextStream in(&file);
×
3070
                while (!in.atEnd())
×
3071
                {
3072
                        // Build list of entries. The checks can certainly become more robust. Actually the file must have 4-part lines.
3073
                        QString line = in.readLine();
×
3074
                        if (line.length()==0) continue;
×
3075
                        if (emptyLine.match(line).hasMatch()) continue;
×
3076
                        if (line.at(0)=='#') continue; // skip comment lines.
×
3077
                        //QStringList list = line.split(QRegularExpression("\\b\\s+\\b"));
3078
                        QStringList list = line.trimmed().split(spaceRe);
×
3079
                        if (list.count() != 4)
×
3080
                        {
3081
                                qWarning() << "IAU constellation file constellations_spans.dat has bad line:" << line << "with" << list.count() << "elements";
×
3082
                                continue;
×
3083
                        }
3084
                        //qDebug() << "Creating span for decl=" << list.at(2) << " from RA=" << list.at(0) << "to" << list.at(1) << ": " << list.at(3);
3085
                        QStringList numList=list.at(0).split(QString(":"));
×
3086
                        span.RAlow= atof(numList.at(0).toLatin1()) + atof(numList.at(1).toLatin1())/60. + atof(numList.at(2).toLatin1())/3600.;
×
3087
                        numList=list.at(1).split(QString(":"));
×
3088
                        span.RAhigh=atof(numList.at(0).toLatin1()) + atof(numList.at(1).toLatin1())/60. + atof(numList.at(2).toLatin1())/3600.;
×
3089
                        numList=list.at(2).split(QString(":"));
×
3090
                        span.decLow=atof(numList.at(0).toLatin1());
×
3091
                        if (span.decLow<0.0)
×
3092
                                span.decLow -= atof(numList.at(1).toLatin1())/60.;
×
3093
                        else
3094
                                span.decLow += atof(numList.at(1).toLatin1())/60.;
×
3095
                        span.constellation=list.at(3);
×
3096
                        iau_constlineVec->append(span);
×
3097
                }
×
3098
                file.close();
×
3099
                iau_constlineVecInitialized=true;
×
3100
        }
×
3101

3102
        // iterate through vector, find entry where declination is lower.
3103
        int entry=0;
×
3104
        while (iau_constlineVec->at(entry).decLow > dec1875)
×
3105
                entry++;
×
3106
        while (entry<iau_constlineVec->size())
×
3107
        {
3108
                while (iau_constlineVec->at(entry).RAhigh <= RA1875)
×
3109
                        entry++;
×
3110
                while (iau_constlineVec->at(entry).RAlow >= RA1875)
×
3111
                        entry++;
×
3112
                if (iau_constlineVec->at(entry).RAhigh > RA1875)
×
3113
                        return iau_constlineVec->at(entry).constellation;
×
3114
                else
3115
                        entry++;
×
3116
        }
3117
        qWarning() << "getIAUconstellation error: Cannot determine, algorithm failed.";
×
3118
        return "(?)";
×
3119
}
3120

3121
// NELM = naked-eye limiting magnitude
3122
int StelCore::nelmToBortleScaleIndex(const float nelm)
×
3123
{
3124
        // Ref: Bortle, John E. (February 2001). "Gauging Light Pollution: The Bortle Dark-Sky Scale".
3125
        //  Sky & Telescope. Sky Publishing Corporation.
3126
        // https://skyandtelescope.org/astronomy-resources/light-pollution-and-astronomy-the-bortle-dark-sky-scale/
3127
        if(nelm < 4.0) return 9;
×
3128
        if(nelm < 4.5) return 8;
×
3129
        if(nelm < 5.0) return 7;
×
3130
        if(nelm < 5.5) return 6;
×
3131
        if(nelm < 6.0) return 5;
×
3132
        if(nelm < 6.5) return 4;
×
3133
        if(nelm < 7.0) return 3;
×
3134
        if(nelm < 7.5) return 2;
×
3135
        return 1;
×
3136
}
3137

3138
float StelCore::bortleScaleIndexToNELM(const int index)
247✔
3139
{
3140
        // This is kind of inverse of nelmToBortleScaleIndex(), where the "representative NELM" is chosen to be
3141
        // the middle of the interval of the NELM values for the inner indices (2-8), and the same distance from
3142
        // the boundary for outer indices (1 and 9).
3143
        switch(index)
247✔
3144
        {
3145
        case 1: return 7.75;
×
3146
        case 2: return 7.25;
19✔
3147
        case 3: return 6.75;
×
3148
        case 4: return 6.25;
×
3149
        case 5: return 5.75;
×
3150
        case 6: return 5.25;
38✔
3151
        case 7: return 4.75;
95✔
3152
        case 8: return 4.25;
×
3153
        case 9: return 3.75;
95✔
3154
        default:
×
3155
                        qWarning().nospace() << "Bortle scale index " << index << " out of range";
×
3156
                        return 0; // Let the problem be visible
×
3157
        }
3158
}
3159

3160
float StelCore::luminanceToNELM(const float luminance)
×
3161
{
3162
        // Ref: Schaefer, B. E.. "Telescopic limiting magnitudes". Astronomical Society of the Pacific,
3163
        //  Publications (ISSN 0004-6280), vol. 102, Feb. 1990, p. 212-229.
3164
        // http://adsbit.harvard.edu/cgi-bin/nph-iarticle_query?bibcode=1990PASP..102..212S
3165
        //
3166
        // Using formula (18), assuming observer's acuity Fₛ=1 (as suggested in the text as "typical observer"),
3167
        // absorption term kᵥ=0.3 (as suggested for "typical weather"), coefficient for Bₛ is adjusted to take
3168
        // the value in cd/m².
3169
        //
3170
        return 8.32f - 2.17147240951626f*std::log(1 + 88.5588612190873f*std::sqrt(luminance));
×
3171
}
3172

3173
float StelCore::nelmToLuminance(const float nelm)
247✔
3174
{
3175
        // This is just the inverse of luminanceToNELM()
3176
        const auto toSquare = std::exp(3.8315015947420905f-0.46051701859880895f*nelm) - 1;
247✔
3177
        return toSquare*toSquare*0.0001275075653676456f;
247✔
3178
}
3179

3180
Vec3d StelCore::getMouseJ2000Pos() const
×
3181
{
3182
        const StelProjectorP prj = getProjection(StelCore::FrameJ2000, StelCore::RefractionAuto);
×
3183
        float ppx = static_cast<float>(getCurrentStelProjectorParams().devicePixelsPerPixel);
×
3184

3185
        QPoint p = StelMainView::getInstance().getMousePos(); // get screen coordinates of mouse cursor
×
3186
        Vec3d mousePosition;
×
3187
        const float wh = prj->getViewportWidth()*0.5f; // get half of width of the screen
×
3188
        const float hh = prj->getViewportHeight()*0.5f; // get half of height of the screen
×
3189
        const float mx = p.x()*ppx-wh; // point 0 in center of the screen, axis X directed to right
×
3190
        const float my = p.y()*ppx-hh; // point 0 in center of the screen, axis Y directed to bottom
×
3191
        // calculate position of mouse cursor via position of center of the screen (and invert axis Y)
3192
        // If coordinates are invalid, don't draw them.
3193
        bool coordsValid = prj->unProject(static_cast<double>(prj->getViewportPosX()+wh+mx), static_cast<double>(prj->getViewportPosY()+hh+1-my), mousePosition);
×
3194
        if (coordsValid)
×
3195
        { // Nick Fedoseev patch
3196
                Vec3d win;
×
3197
                prj->project(mousePosition,win);
×
3198
                float dx = prj->getViewportPosX()+wh+mx - static_cast<float>(win.v[0]);
×
3199
                float dy = prj->getViewportPosY()+hh+1-my - static_cast<float>(win.v[1]);
×
3200
                prj->unProject(static_cast<double>(prj->getViewportPosX()+wh+mx+dx), static_cast<double>(prj->getViewportPosY()+hh+1-my+dy), mousePosition);
×
3201
        }
3202
//        if (getUseAberration() && getCurrentPlanet())
3203
//        {
3204
//                Vec3d vel=getCurrentPlanet()->getHeliocentricEclipticVelocity();
3205
//                vel=StelCore::matVsop87ToJ2000*vel * getAberrationFactor()*(AU/(86400.0*SPEED_OF_LIGHT));
3206
//                mousePosition-=vel;
3207
//                mousePosition.normalize();
3208
//        }
3209
        return mousePosition;
×
3210
}
×
3211

3212
Vec3d StelCore::calculateParallaxDiff(double JD) const {
×
3213
        // ICRS coordinates are barycentric (Gaia gives barycentric RA/DEC coordinates)
3214
        // diff between solar system bayrcentric location at STAR_CATALOG_JDEPOCH and current solar system bayrcentric location
3215
        Vec3d PosNow = getCurrentPlanet()->getBarycentricEclipticPos(JD);
×
3216
        // Transform from heliocentric ecliptic to equatorial coordinates
3217
        PosNow = matVsop87ToJ2000.upper3x3() * -1. * PosNow;  // need to times -1 because technically it is doing (0,0,0) - PosNow
×
3218
        return PosNow;
×
3219
}
3220

3221
Vec3d StelCore::getParallaxDiff(double JD) const {
×
3222
        // if isArtificial meaning transitioning between planets, use cache and don't recalculate because it will crash
3223
        if ((fuzzyEquals(JD, cachedParallaxJD, JD_SECOND) && (getCurrentPlanet() == cachedParallaxPlanet)) || (getCurrentPlanet()->getPlanetType() == Planet::isArtificial))
×
3224
        {
3225
                return cachedParallaxDiff;
×
3226
        }
3227
        cachedParallaxDiff = calculateParallaxDiff(JD); // set the cache to the new value
×
3228
        cachedParallaxJD = JD; // set the cache to the new value
×
3229
        cachedParallaxPlanet = getCurrentPlanet(); 
×
3230
    return cachedParallaxDiff;
×
3231
}
3232

3233
Vec3d StelCore::calculateAberrationVec(double JD) const {
×
3234
        // Solar system barycentric velocity
3235
        Q_UNUSED(JD);
3236
        Vec3d vel = getCurrentPlanet()->getBarycentricEclipticVelocity(JD);
×
3237
        vel = StelCore::matVsop87ToJ2000 * vel * (AU/(86400.0*SPEED_OF_LIGHT));
×
3238
        return vel;
×
3239
}
3240

3241
Vec3d StelCore::getAberrationVec(double JD) const {
×
3242
        // need to recompute the aberration vector if the JD has changed or the planet has changed
3243
        if (fuzzyEquals(JD, cachedAberrationJD, JD_SECOND) && (getCurrentPlanet() == cachedAberrationPlanet))
×
3244
        {
3245
                return getAberrationFactor() * cachedAberrationVec;
×
3246
        }
3247
        cachedAberrationVec = StelCore::calculateAberrationVec(JD); // set the cache to the new value
×
3248
        cachedAberrationJD = JD; // set the cache to the new value
×
3249
        cachedAberrationPlanet = getCurrentPlanet();
×
3250
        return getAberrationFactor() * cachedAberrationVec;
×
3251
}
3252

3253
QByteArray StelCore::getAberrationShader() const
×
3254
{
3255
        return 1+R"(
×
3256
uniform vec3 STELCORE_currentPlanetBarycentricEclipticVelocity;
3257
// objectDir points to the object as viewed from its comoving frame.
3258
// Return value represents the apparent direction to this object from a frame
3259
// that moves with respect to the object at slightly relativistic speeds (v<0.1c).
3260
// Relative error in aberration angle is about 0.5v/c.
3261
vec3 applyAberrationToObject(vec3 objectDir)
3262
{
3263
        vec3 velocity = STELCORE_currentPlanetBarycentricEclipticVelocity;
3264
        return normalize(objectDir + velocity);
3265
}
3266
// viewDir is the direction where the object appears to be when viewed from a
3267
// frame that moves with respect to it at slightly relativistic speeds (v<0.1c).
3268
// Return value represents the direction to the object as viewed from its comoving frame.
3269
// Relative error in aberration angle is about 0.5v/c.
3270
vec3 applyAberrationToViewDir(vec3 viewDir)
3271
{
3272
        vec3 velocity = STELCORE_currentPlanetBarycentricEclipticVelocity;
3273
        return normalize(viewDir - velocity);
3274
}
3275
)";
3276
}
3277

3278
void StelCore::setAberrationUniforms(QOpenGLShaderProgram& program) const
×
3279
{
3280
        Vec3d velocity(0.);
×
3281
        if(getUseAberration())
×
3282
        {
3283
                velocity = getAberrationFactor() * cachedAberrationVec;
×
3284
        }
3285
        program.setUniformValue("STELCORE_currentPlanetBarycentricEclipticVelocity", velocity.toQVector());
×
3286
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc