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

Stellarium / stellarium / 15291801018

28 May 2025 04:52AM UTC coverage: 11.931% (-0.02%) from 11.951%
15291801018

push

github

alex-w
Added new set of navigational stars (XIX century)

0 of 6 new or added lines in 2 files covered. (0.0%)

14124 existing lines in 74 files now uncovered.

14635 of 122664 relevant lines covered (11.93%)

18291.42 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

UNCOV
80
StelCore::StelCore()
×
UNCOV
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");
×
UNCOV
119
        registerMathMetaTypes();
×
120

121
        toneReproducer = new StelToneReproducer();
×
UNCOV
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();
×
UNCOV
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();
×
UNCOV
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();
×
UNCOV
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();
×
UNCOV
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;
UNCOV
159
        const double jdB1875 = StelUtils::getJDFromBesselianEpoch(1875.0);
×
UNCOV
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

UNCOV
166
StelCore::~StelCore()
×
167
{
168
        delete toneReproducer; toneReproducer=Q_NULLPTR;
×
UNCOV
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

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

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

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

206
        if (conf->childGroups().contains("location_run_once"))
×
UNCOV
207
                defaultLocationID = "stellarium_cli";
×
208
        else
209
                defaultLocationID = conf->value("init_location/location", "auto").toString();
×
210
        bool ok;
211
        StelLocationMgr* locationMgr = &StelApp::getInstance().getLocationMgr();
×
UNCOV
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
UNCOV
224
                location.name = conf->value("init_location/location").toString();
×
225
        }
226
        else
227
        {
UNCOV
228
                location = locationMgr->locationForString(defaultLocationID);
×
229
        }
230

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

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

245
        // Delta-T stuff
246
        // Define default algorithm for time correction (Delta T)
UNCOV
247
        QString tmpDT = conf->value("navigation/time_correction_algorithm", "EspenakMeeusModified").toString();
×
UNCOV
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
UNCOV
252
        setDeltaTCustomYear(conf->value("custom_time_correction/year", 1820.0).toDouble());
×
UNCOV
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
UNCOV
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...
UNCOV
261
        QString presetTimeStr = conf->value("navigation/preset_sky_time",2451545.).toString();
×
UNCOV
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
        {
UNCOV
269
                qWarning().noquote() << "navigation/preset_sky_time was not a double, treating as string date:" << presetTimeStr;
×
UNCOV
270
                presetSkyTime = StelUtils::qDateTimeToJd(QDateTime::fromString(presetTimeStr));
×
271
        }
272
        setInitTodayTime(QTime::fromString(conf->value("navigation/today_time", "22:00").toString()));
×
UNCOV
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
UNCOV
283
        updateTransformMatrices();
×
UNCOV
284
        updateFixedEquatorialTransformMatrices();
×
285
        connect(this, SIGNAL(locationChanged(const StelLocation&)), this, SLOT(updateFixedEquatorialTransformMatrices()));
×
286

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

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

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

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

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

306
        // Register all the core actions.
UNCOV
307
        QString timeGroup = N_("Date and Time");
×
UNCOV
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");
×
UNCOV
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);
×
UNCOV
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();
×
UNCOV
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
UNCOV
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;
×
UNCOV
398
                geodesicGrid = new StelGeodesicGrid(maxLevel);
×
399
        }
400
        return geodesicGrid;
×
401
}
402

UNCOV
403
StelProjectorP StelCore::getProjection2d() const
×
404
{
405
        StelProjectorP prj(new StelProjector2d());
×
UNCOV
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))
×
UNCOV
413
                projType = currentProjectionType;
×
414

415
        StelProjectorP prj;
×
UNCOV
416
        switch (projType)
×
417
        {
418
                case ProjectionPerspective:
×
UNCOV
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 ProjectionCylinder:
×
434
                        prj = StelProjectorP(new StelProjectorCylinder(modelViewTransform));
×
435
                        break;
×
436
                case ProjectionCylinderFill:
×
437
                        prj = StelProjectorP(new StelProjectorCylinderFill(modelViewTransform));
×
438
                        break;
×
439
                case ProjectionMercator:
×
440
                        prj = StelProjectorP(new StelProjectorMercator(modelViewTransform));
×
441
                        break;
×
442
                case ProjectionOrthographic:
×
443
                        prj = StelProjectorP(new StelProjectorOrthographic(modelViewTransform));
×
444
                        break;
×
445
                case ProjectionSinusoidal:
×
446
                        prj = StelProjectorP(new StelProjectorSinusoidal(modelViewTransform));
×
447
                        break;
×
448
                case ProjectionMiller:
×
449
                        prj = StelProjectorP(new StelProjectorMiller(modelViewTransform));
×
450
                        break;
×
451
                default:
×
452
                        qWarning() << "Unknown projection type: " << static_cast<int>(projType) << "using ProjectionStereographic instead";
×
453
                        prj = StelProjectorP(new StelProjectorStereographic(modelViewTransform));
×
454
                        Q_ASSERT(0);
×
455
        }
456
        prj->init(currentProjectorParams);
×
UNCOV
457
        return prj;
×
458
}
×
459

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

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

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

512
        if (currentProjectionType==ProjectionType::ProjectionCylinderFill)
×
513
        {
514
                currentProjectorParams.widthStretch=0.5*width/height;
×
UNCOV
515
                currentProjectorParams.viewportFovDiameter = height;
×
516
        }
517
}
×
518

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

527
        // Transform matrices between coordinates systems
UNCOV
528
        updateTransformMatrices();
×
529

530
        // Update direction of vision/Zoom level
UNCOV
531
        movementMgr->updateMotion(deltaTime);
×
532

533
        currentProjectorParams.fov = static_cast<float>(movementMgr->getCurrentFov());
×
534

535
        skyDrawer->update(deltaTime);
×
UNCOV
536
}
×
537

538

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

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

556
        skyDrawer->preDraw();
×
UNCOV
557
}
×
558

559

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

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

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

584
                currentProjectionType=type;
×
UNCOV
585
                updateMaximumFov();
×
586
                if (currentProjectionType==ProjectionType::ProjectionCylinderFill)
×
587
                {
588
                        // 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.
589
                        // (To configure a stretch at startup, use startup.ssc script.)
UNCOV
590
                        conf->setValue("projection/width_stretch", currentProjectorParams.widthStretch);
×
UNCOV
591
                        currentProjectorParams.fov=180.f;
×
592
                        currentProjectorParams.widthStretch=0.5*currentProjectorParams.viewportXywh[2]/currentProjectorParams.viewportXywh[3];
×
593
                        currentProjectorParams.viewportFovDiameter = currentProjectorParams.viewportXywh[3];
×
594
                        Q_ASSERT(movementMgr);
×
595
                        movementMgr->setViewportVerticalOffsetTarget(0.);
×
596
                        movementMgr->zoomTo(180., 0.5);
×
597
                }
598
                else
599
                {
600
                        // reset to what is stored in config.ini
UNCOV
601
                        currentProjectorParams.widthStretch=conf->value("projection/width_stretch", 1.0).toDouble();
×
602
                }
603

UNCOV
604
                emit currentProjectionTypeChanged(type);
×
UNCOV
605
                emit currentProjectionTypeKeyChanged(getCurrentProjectionTypeKey());
×
606
                emit currentProjectionNameI18nChanged(getCurrentProjectionNameI18n());
×
607
        }
608
}
×
609

610
StelCore::ProjectionType StelCore::getCurrentProjectionType() const
×
611
{
612
        return currentProjectionType;
×
613
}
614

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

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

UNCOV
636
QString StelCore::getCurrentProjectionNameI18n() const
×
637
{
638
        return projectionTypeKeyToNameI18n(getCurrentProjectionTypeKey());
×
639
}
640

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

651
void StelCore::setMaskType(StelProjector::StelProjectorMaskType m)
×
652
{
653
        currentProjectorParams.maskType = m;
×
UNCOV
654
}
×
655

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

666
bool StelCore::getFlagGravityLabels() const
×
667
{
668
        return currentProjectorParams.gravityLabels;
×
669
}
670

UNCOV
671
void StelCore::setDefaultAngleForGravityText(float a)
×
672
{
673
        currentProjectorParams.defaultAngleForGravityText = a;
×
UNCOV
674
}
×
675

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

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

696
bool StelCore::getFlipHorz(void) const
×
697
{
698
        return currentProjectorParams.flipHorz;
×
699
}
700

UNCOV
701
bool StelCore::getFlipVert(void) const
×
702
{
703
        return currentProjectorParams.flipVert;
×
704
}
705

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

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

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

741
void StelCore::setViewportStretch(float stretch)
×
742
{
743
        currentProjectorParams.widthStretch=static_cast<qreal>(qMax(0.001f, stretch));
×
UNCOV
744
}
×
745

746
QString StelCore::getDefaultLocationID() const
×
747
{
748
        return defaultLocationID;
×
749
}
750

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

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

UNCOV
771
StelProjector::StelProjectorParams StelCore::getCurrentStelProjectorParams() const
×
772
{
773
        return currentProjectorParams;
×
774
}
775

UNCOV
776
void StelCore::setCurrentStelProjectorParams(const StelProjector::StelProjectorParams& newParams)
×
777
{
778
        currentProjectorParams=newParams;
×
UNCOV
779
}
×
780

781
void StelCore::lookAtJ2000(const Vec3d& pos, const Vec3d& aup)
×
782
{
783
        Vec3d f(j2000ToAltAz(pos, RefractionOff));
×
UNCOV
784
        Vec3d up(j2000ToAltAz(aup, RefractionOff));
×
785
        f.normalize();
×
786
        up.normalize();
×
787

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

800
//void StelCore::setMatAltAzModelView(const Mat4d& mat)
801
//{
802
//        matAltAzModelView = mat;
803
//        invertMatAltAzModelView = matAltAzModelView.inverse();
804
//}
805

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

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

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

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

UNCOV
846
Vec3d StelCore::galacticToJ2000(const Vec3d& v) const
×
847
{
848
        return matGalacticToJ2000*v;
×
849
}
850

UNCOV
851
Vec3d StelCore::supergalacticToJ2000(const Vec3d& v) const
×
852
{
853
        return matSupergalacticToJ2000*v;
×
854
}
855

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

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

UNCOV
878
Vec3d StelCore::j2000ToJ1875(const Vec3d& v) const
×
879
{
880
        return matJ2000ToJ1875*v;
×
881
}
882

UNCOV
883
Vec3d StelCore::j1875ToJ2000(const Vec3d& v) const
×
884
{
885
        return matJ2000ToJ1875.transpose()*v;
×
886
}
887

UNCOV
888
Vec3d StelCore::j2000ToGalactic(const Vec3d& v) const
×
889
{
890
        return matJ2000ToGalactic*v;
×
891
}
892

UNCOV
893
Vec3d StelCore::j2000ToSupergalactic(const Vec3d& v) const
×
894
{
895
        return matJ2000ToSupergalactic*v;
×
896
}
897

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1067
                matAltAzToHeliocentricEclipticJ2000 =  Mat4d::translation(position->getCenterVsop87Pos()) * matAltAzToVsop87 *
×
UNCOV
1068
                                Mat4d::translation(Vec3d(rho*sin(sigma), 0., rho*cos(sigma) ));
×
1069

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

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

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

1083

1084
//                matAltAzToHeliocentricEclipticJ2000 =  Mat4d::translation(position->getCenterVsop87Pos()) * tmp *
1085
//                                Mat4d::translation(Vec3d(0.,0., position->getDistanceFromCenter()));
1086

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

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

UNCOV
1109
Vec3d StelCore::getObserverHeliocentricEclipticVelocity() const
×
1110
{
1111
        if (!position) return Vec3d(0,0,0);
×
1112

1113
        const auto& planet = *position->getHomePlanet();
×
UNCOV
1114
        const Vec3d planetVelocity = planet.getHeliocentricEclipticVelocity();
×
1115
        if (!flagUseTopocentricCoordinates)
×
1116
                return planetVelocity;
×
1117

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

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

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

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

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

1171
        PlanetP p = GETSTELMODULE(SolarSystem)->searchByEnglishName(loc.planetName);
×
1172

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

1179
        GETSTELMODULE(StelObjectMgr)->unSelect();
×
1180

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

1186
double StelCore::getJDOfLastJDUpdate() const
×
1187
{
1188
        return jdOfLastJDUpdate;
×
1189
}
1190

UNCOV
1191
void StelCore::setMilliSecondsOfLastJDUpdate(qint64 millis)
×
1192
{
1193
        milliSecondsOfLastJDUpdate = millis;
×
UNCOV
1194
}
×
1195

1196
qint64 StelCore::getMilliSecondsOfLastJDUpdate() const
×
1197
{
1198
        return milliSecondsOfLastJDUpdate;
×
1199
}
1200

UNCOV
1201
void StelCore::setJD(double newJD)
×
1202
{
1203
        JD.first=newJD;
×
UNCOV
1204
        JD.second=computeDeltaT(newJD);        
×
1205
        resetSync();
×
1206
}
×
1207

1208
double StelCore::getJD() const
×
1209
{
1210
        return JD.first;
×
1211
}
1212

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

1221
double StelCore::getJDE() const
×
1222
{
1223
        return JD.first+JD.second/86400.0;
×
1224
}
1225

1226

UNCOV
1227
void StelCore::setMJDay(double MJD)
×
1228
{
1229
        setJD(MJD+2400000.5);
×
UNCOV
1230
}
×
1231

1232
double StelCore::getMJDay() const
×
1233
{
1234
        return JD.first-2400000.5;
×
1235
}
1236

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

1253
// @return whether aberration is currently used.
UNCOV
1254
bool StelCore::getUseAberration() const
×
1255
{
1256
        return flagUseAberration;
×
1257
}
1258
// 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).
UNCOV
1259
void StelCore::setUseAberration(bool use)
×
1260
{
1261
        if (flagUseAberration != use)
×
1262
        {
1263
                flagUseAberration=use;
×
UNCOV
1264
                StelApp::immediateSave("astro/flag_aberration", use);
×
1265
                emit flagUseAberrationChanged(use);
×
1266
        }
1267
}
×
1268

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

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

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

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

1331
double StelCore::getPresetSkyTime() const
×
1332
{
1333
        return presetSkyTime;
×
1334
}
1335

UNCOV
1336
void StelCore::setPresetSkyTime(double d)
×
1337
{
1338
        StelApp::immediateSave("navigation/preset_sky_time", d);
×
UNCOV
1339
        presetSkyTime=d;
×
1340
}
×
1341

1342
void StelCore::setTimeRate(double ts)
×
1343
{
1344
        timeSpeed=ts;
×
UNCOV
1345
        resetSync();
×
1346
        emit timeRateChanged(timeSpeed);
×
1347
}
×
1348

1349
double StelCore::getTimeRate() const
×
1350
{
1351
        return timeSpeed;
×
1352
}
1353

UNCOV
1354
void StelCore::revertTimeDirection(void)
×
1355
{
1356
        setTimeRate(-1*getTimeRate());
×
UNCOV
1357
}
×
1358

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

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

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

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

1407
// Get the information on the current location
UNCOV
1408
const StelLocation& StelCore::getCurrentLocation() const
×
1409
{
1410
        return position->getCurrentLocation();
×
1411
}
1412

UNCOV
1413
const QSharedPointer<Planet> StelCore::getCurrentPlanet() const
×
1414
{
1415
        return position->getHomePlanet();
×
1416
}
1417

UNCOV
1418
const StelObserver *StelCore::getCurrentObserver() const
×
1419
{
1420
        return position;
×
1421
}
1422

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

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

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

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

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

1514
        if (!tzValid && !tzSpecial)
×
UNCOV
1515
                qWarning().noquote() << "Invalid timezone: " << tzName;
×
1516

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

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

UNCOV
1588
        return shiftInSeconds / 3600.0;
×
UNCOV
1589
}
×
1590

1591
QString StelCore::getCurrentTimeZone() const
×
1592
{
1593
        return currentTimeZone;
×
1594
}
1595

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

1609
bool StelCore::getUseDST() const
×
1610
{
1611
        return flagUseDST;
×
1612
}
1613

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

1621
void StelCore::setDitheringMode(const DitheringMode newMode)
×
1622
{
1623
        if(newMode == ditheringMode)
×
UNCOV
1624
                return;
×
1625

1626
        ditheringMode = newMode;
×
UNCOV
1627
        StelApp::immediateSave("video/dithering_mode", ditheringMap.key(newMode, "disabled"));
×
1628
        emit ditheringModeChanged(newMode);
×
1629
}
1630

UNCOV
1631
void StelCore::setDitheringMode(const QString& modeName)
×
1632
{
1633
        const auto mode = parseDitheringMode(modeName);
×
UNCOV
1634
        setDitheringMode(mode);
×
1635
}
×
1636

1637
bool StelCore::getUseCustomTimeZone() const
×
1638
{
1639
        return flagUseCTZ;
×
1640
}
1641

UNCOV
1642
void StelCore::setUseCustomTimeZone(const bool b)
×
1643
{
1644
        flagUseCTZ = b;
×
UNCOV
1645
        emit useCustomTimeZoneChanged(b);
×
1646
}
×
1647

1648
bool StelCore::getStartupTimeStop() const
×
1649
{
1650
        return startupTimeStop;
×
1651
}
1652

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

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

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

1673
        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);
×
UNCOV
1674
        return E*M_180_PI*4.;
×
1675
}
1676

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

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

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

1689
        double deltaPsi, deltaEps;
UNCOV
1690
        getNutationAngles(getJDE(), &deltaPsi, &deltaEps); // these are radians!
×
UNCOV
1691
        double equation = 4*(sunMeanLongitude - 0.0057183 - alpha + deltaPsi*M_180_PI*cos(getPrecessionAngleVondrakEpsilon(getJDE())));
×
1692
        // The equation of time is always smaller 20 minutes in absolute value
1693
        if (qAbs(equation)>20)
×
1694
        {
1695
                // 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
UNCOV
1696
                if (equation>0.)
×
UNCOV
1697
                        equation -= 1440.;
×
1698
                else
1699
                        equation += 1440.;
×
1700
        }
1701

UNCOV
1702
        return equation;
×
1703
}
1704

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

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

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

UNCOV
1744
QTime StelCore::getInitTodayTime(void) const
×
1745
{
1746
        return initTodayTime;
×
1747
}
1748

UNCOV
1749
void StelCore::setInitTodayTime(const QTime& time)
×
1750
{
1751
        StelApp::immediateSave("navigation/today_time", time);
×
UNCOV
1752
        initTodayTime=time;
×
1753
}
×
1754

1755
void StelCore::setPresetSkyTime(QDateTime dateTime)
×
1756
{
1757
        setPresetSkyTime(StelUtils::qDateTimeToJd(dateTime));
×
UNCOV
1758
}
×
1759

1760
void StelCore::addMinute()
×
1761
{
1762
        addSolarDays(JD_MINUTE);
×
UNCOV
1763
}
×
1764

1765
void StelCore::addHour()
×
1766
{
1767
        addSolarDays(JD_HOUR);
×
UNCOV
1768
}
×
1769

1770
void StelCore::addDay()
×
1771
{
1772
        addSolarDays(1.0);
×
UNCOV
1773
}
×
1774

1775
void StelCore::addWeek()
×
1776
{
1777
        addSolarDays(7.0);
×
UNCOV
1778
}
×
1779

1780
void StelCore::addSiderealDay()
×
1781
{
1782
        addSiderealDays(1.0);
×
UNCOV
1783
}
×
1784

1785
void StelCore::addSiderealWeek()
×
1786
{
1787
        addSiderealDays(7.0);
×
UNCOV
1788
}
×
1789

1790
void StelCore::addSiderealYear()
×
1791
{
1792
        addSiderealYears(1.);
×
UNCOV
1793
}
×
1794

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

1803
        addSolarDays(days*n);
×
UNCOV
1804
}
×
1805

1806
void StelCore::addSynodicMonth()
×
1807
{
1808
        addSolarDays(29.530588853);
×
UNCOV
1809
}
×
1810

1811
void StelCore::addSaros()
×
1812
{
1813
        // 223 synodic months
UNCOV
1814
        addSolarDays(223*29.530588853);
×
UNCOV
1815
}
×
1816

1817
void StelCore::addDraconicMonth()
×
1818
{
1819
        addSolarDays(27.212220817);
×
UNCOV
1820
}
×
1821

1822
void StelCore::addMeanTropicalMonth()
×
1823
{
1824
        addSolarDays(27.321582241);
×
UNCOV
1825
}
×
1826

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

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

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

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

1872
void StelCore::addAnomalisticMonth()
×
1873
{
1874
        addSolarDays(27.554549878);
×
UNCOV
1875
}
×
1876

1877
void StelCore::addAnomalisticYear()
×
1878
{
1879
        addAnomalisticYears(1.);
×
UNCOV
1880
}
×
1881

1882
void StelCore::addAnomalisticYears(double n)
×
1883
{
1884
        addSolarDays(365.259636*n);
×
UNCOV
1885
}
×
1886

1887
void StelCore::addDraconicYear()
×
1888
{
1889
        addSolarDays(346.620075883);
×
UNCOV
1890
}
×
1891

1892
void StelCore::addMeanTropicalYear()
×
1893
{
1894
        addMeanTropicalYears(1.0);
×
UNCOV
1895
}
×
1896

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

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

1912
void StelCore::addJulianYear()
×
1913
{
1914
        addJulianYears(1.);
×
UNCOV
1915
}
×
1916

1917
void StelCore::addGaussianYear()
×
1918
{
1919
        addSolarDays(365.2568983);
×
UNCOV
1920
}
×
1921

1922
void StelCore::addJulianYears(double n)
×
1923
{
1924
        addSolarDays(365.25*n);
×
UNCOV
1925
}
×
1926

1927
void StelCore::addGreatYear()
×
1928
{
1929
        addSiderealYears(25800);
×
UNCOV
1930
}
×
1931

1932
void StelCore::subtractMinute()
×
1933
{
1934
        addSolarDays(-JD_MINUTE);
×
UNCOV
1935
}
×
1936

1937
void StelCore::subtractHour()
×
1938
{
1939
        addSolarDays(-JD_HOUR);
×
UNCOV
1940
}
×
1941

1942
void StelCore::subtractDay()
×
1943
{
1944
        addSolarDays(-1.0);
×
UNCOV
1945
}
×
1946

1947
void StelCore::subtractWeek()
×
1948
{
1949
        addSolarDays(-7.0);
×
UNCOV
1950
}
×
1951

1952
void StelCore::subtractSiderealDay()
×
1953
{
1954
        addSiderealDays(-1.0);
×
UNCOV
1955
}
×
1956

1957
void StelCore::subtractSiderealWeek()
×
1958
{
1959
        addSiderealDays(-7.0);
×
UNCOV
1960
}
×
1961

1962
void StelCore::subtractSiderealYear()
×
1963
{
1964
        addSiderealYears(-1.);
×
UNCOV
1965
}
×
1966

1967
void StelCore::subtractSiderealYears(double n)
×
1968
{
1969
        addSiderealYears(-n);
×
UNCOV
1970
}
×
1971

1972
void StelCore::subtractSynodicMonth()
×
1973
{
1974
        addSolarDays(-29.530588853);
×
UNCOV
1975
}
×
1976

1977
void StelCore::subtractSaros()
×
1978
{
1979
        // 223 synodic months
UNCOV
1980
        addSolarDays(-223*29.530588853);
×
UNCOV
1981
}
×
1982

1983
void StelCore::subtractDraconicMonth()
×
1984
{
1985
        addSolarDays(-27.212220817);
×
UNCOV
1986
}
×
1987

1988
void StelCore::subtractMeanTropicalMonth()
×
1989
{
1990
        addSolarDays(-27.321582241);
×
UNCOV
1991
}
×
1992

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

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

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

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

2038
void StelCore::subtractGreatYear()
×
2039
{
2040
        subtractSiderealYears(25800);
×
UNCOV
2041
}
×
2042

2043
void StelCore::subtractAnomalisticMonth()
×
2044
{
2045
        addSolarDays(-27.554549878);
×
UNCOV
2046
}
×
2047

2048
void StelCore::subtractAnomalisticYear()
×
2049
{
2050
        subtractAnomalisticYears(1.);
×
UNCOV
2051
}
×
2052

2053
void StelCore::subtractAnomalisticYears(double n)
×
2054
{
2055
        addSolarDays(-365.259636*n);
×
UNCOV
2056
}
×
2057

2058
void StelCore::subtractDraconicYear()
×
2059
{
2060
        addSolarDays(-346.620075883);
×
UNCOV
2061
}
×
2062

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

2070
void StelCore::subtractMeanTropicalYear()
×
2071
{
2072
        addMeanTropicalYears(-1.0);
×
UNCOV
2073
}
×
2074

2075
void StelCore::subtractMeanTropicalYears(double n)
×
2076
{
2077
        addMeanTropicalYears(-1.0*n);
×
UNCOV
2078
}
×
2079

2080
void StelCore::subtractJulianYear()
×
2081
{
2082
        addSolarDays(-365.25);
×
UNCOV
2083
}
×
2084

2085
void StelCore::subtractGaussianYear()
×
2086
{
2087
        addSolarDays(-365.2568983);
×
UNCOV
2088
}
×
2089

2090
void StelCore::subtractJulianYears(double n)
×
2091
{
2092
        addSolarDays(-365.25*n);
×
UNCOV
2093
}
×
2094

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

2102
        setJD(getJD() + d);
×
2103

2104
        if (qAbs(d)>0.99) // WTF: qAbs(d)>=1.0 not working here!
×
UNCOV
2105
                emit dateChanged();
×
2106
}
×
2107

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

2115
        setJD(getJD() + d);
×
UNCOV
2116
}
×
2117

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

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

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

UNCOV
2137
QString StelCore::getStartupTimeMode() const
×
2138
{
2139
        return startupTimeMode;
×
2140
}
2141

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

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

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

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

2184
void StelCore::setZeroTimeSpeed()
×
2185
{
2186
        setTimeRate(0);
×
UNCOV
2187
}
×
2188

2189
void StelCore::setRealTimeSpeed()
×
2190
{
2191
        setTimeRate(JD_SECOND);
×
UNCOV
2192
}
×
2193

2194
void StelCore::toggleRealTimeSpeed()
×
2195
{
2196
        (!getRealTimeSpeed()) ? setRealTimeSpeed() : setZeroTimeSpeed();
×
UNCOV
2197
}
×
2198

2199
bool StelCore::getRealTimeSpeed() const
×
2200
{
2201
        return (fabs(timeSpeed-JD_SECOND)<0.0000001);
×
2202
}
2203

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

2217
        // Fix time limits to -100000 to +100000 to prevent bugs
UNCOV
2218
        if (JD.first>38245309.499988) JD.first = 38245309.499988;
×
UNCOV
2219
        if (JD.first<-34803211.500012) JD.first = -34803211.500012;
×
2220
        JD.second=computeDeltaT(JD.first);
×
2221

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

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

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

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

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

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

2318
void StelCore::setStartupTimeMode(const QString& s)
×
2319
{
2320
        StelApp::immediateSave("navigation/startup_time_mode", s);
×
UNCOV
2321
        startupTimeMode = s;
×
2322
}
×
2323

2324
// return precomputed DeltaT in seconds. Public.
UNCOV
2325
double StelCore::getDeltaT() const
×
2326
{
2327
        return JD.second;
×
2328
}
2329

2330

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

2345
        else
2346
        {
UNCOV
2347
                Q_ASSERT(deltaTfunc);
×
UNCOV
2348
                DeltaT=deltaTfunc(JD);
×
2349
        }
2350

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

2357
        return DeltaT;
×
2358
}
2359

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

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

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

2655
//! Get description of the current algorithm for time correction
UNCOV
2656
QString StelCore::getCurrentDeltaTAlgorithmDescription(void) const
×
2657
{
2658
        // 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.
UNCOV
2659
        QString description;
×
UNCOV
2660
        double jd = 0;
×
2661
        QString marker;
×
2662
        switch (getCurrentDeltaTAlgorithm())
×
2663
        {
2664
                case WithoutCorrection:
×
UNCOV
2665
                        description = q_("Correction is disabled. Use only if you know what you are doing!");
×
2666
                        break;
×
2667
                case Schoch: // historical value.
×
2668
                        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));
×
2669
                        break;
×
2670
                case Clemence: // historical value.
×
2671
                        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));
×
2672
                        break;
×
2673
                case IAU: // historical value.
×
2674
                        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));
×
2675
                        // find year of publication of AFFC
2676
                        break;
×
UNCOV
2677
                case AstronomicalEphemeris: // historical value.
×
2678
                        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));
×
2679
                        // TODO: expand the sentence: ... adopted ... from 19xx-19yy?
2680
                        break;
×
UNCOV
2681
                case TuckermanGoldstine: // historical value.
×
2682
                        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));
×
2683
                        // TODO: These tables are sometimes found cited, but I have no details. Maybe add "based on ... " ?
2684
                        break;
×
UNCOV
2685
                case MullerStephenson:
×
2686
                        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));
×
2687
                        break;
×
2688
                case Stephenson1978:
×
2689
                        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));
×
2690
                        break;
×
2691
                case SchmadelZech1979: // outdated data fit, historical value?
×
2692
                        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));
×
2693
                        break;
×
2694
                case MorrisonStephenson1982:
×
2695
                        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));
×
2696
                        break;
×
2697
                case StephensonMorrison1984: // PRIMARY SOURCE
×
2698
                        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));
×
2699
                        break;
×
2700
                case StephensonHoulden:
×
2701
                        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));
×
2702
                        break;
×
2703
                case Espenak: // limited range, but wide availability?
×
2704
                        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));
×
2705
                        break;
×
2706
                case Borkowski: // Linked to ELP2000-85, so it's important...
×
2707
                        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));
×
2708
                        break;
×
2709
                case SchmadelZech1988: // data fit through Stephenson&Morrison1984, which itself is important. Unclear who uses this version?
×
2710
                        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));
×
2711
                        break;
×
2712
                case ChaprontTouze:
×
2713
                        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));
×
2714
                        break;
×
2715
                case StephensonMorrison1995:
×
2716
                        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));
×
2717
                        break;
×
2718
                case Stephenson1997:
×
2719
                        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));
×
2720
                        break;
×
2721
                case ChaprontMeeus:
×
2722
                        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));
×
2723
                        break;
×
2724
                case JPLHorizons:
×
2725
                        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));
×
2726
                        break;
×
2727
                case MeeusSimons:
×
2728
                        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));
×
2729
                        break;
×
2730
                case MontenbruckPfleger: // uninspired
×
2731
                        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));
×
2732
                        break;
×
2733
                case ReingoldDershowitz: //
×
2734
                        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));
×
2735
                        break;
×
2736
                case MorrisonStephenson2004: // PRIMARY SOURCE
×
2737
                        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));
×
2738
                        break;
×
2739
                case Reijs:
×
2740
                        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));
×
2741
                        break;
×
2742
                case EspenakMeeus: // GENERAL SOLUTION
×
2743
                        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));
×
2744
                        break;
×
2745
                case EspenakMeeusModified: // MODIFIED SOLUTION
×
2746
                        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>");
×
2747
                        break;
×
2748
                case EspenakMeeusZeroMoonAccel: // PATCHED SOLUTION. Experimental, it may not make sense to keep it in V1.0.
×
2749
                        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));
×
2750
                        break;
×
2751
                case Banjevic:
×
2752
                        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));
×
2753
                        break;
×
2754
                case IslamSadiqQureshi:
×
2755
                        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));
×
2756
                        break;
×
2757
                case KhalidSultanaZaidi:
×
2758
                        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));
×
2759
                        break;
×
2760
                case StephensonMorrisonHohenkerk2016: // PRIMARY SOURCE, SEEMS VERY IMPORTANT
×
2761
                        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));
×
2762
                        break;
×
2763
                case Henriksson2017:
×
2764
                        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));
×
2765
                        break;
×
2766
                case Custom:
×
2767
                        description = q_("This is a quadratic formula for calculation of %1T with coefficients defined by the user.").arg(QChar(0x0394));
×
2768
                        break;
×
2769
                default:
×
2770
                        description = q_("Error");
×
2771
        }
2772

2773
        // Put n-dot value info
UNCOV
2774
        if (getCurrentDeltaTAlgorithm()!=WithoutCorrection)
×
2775
        {
2776
                QString accel = QString("%1\"/cy<sup>2</sup>").arg(QString::number(getDeltaTnDot(), 'f', 4));
×
UNCOV
2777
                QString ndot  = QString("&#x1E45;");
×
2778
                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));
×
2779
        }
×
2780

2781
        return description;
×
UNCOV
2782
}
×
2783

2784
QString StelCore::getCurrentDeltaTAlgorithmValidRangeDescription(const double JD, QString *marker) const
×
2785
{
2786
        QString validRange = "";
×
UNCOV
2787
        QString validRangeAppendix = "";
×
2788
        *marker = "";
×
2789
        int year, month, day;
2790

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

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

2854
        return QString(" %1").arg(validRange);
×
UNCOV
2855
}
×
2856

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

2872
        // immediately decide upon sky background brightness...
UNCOV
2873
        return (GETSTELMODULE(LandscapeMgr)->getAtmosphereAverageLuminance() > static_cast<float>(getSkyDrawer()->getDaylightLabelThreshold()));
×
2874
}
2875

UNCOV
2876
double StelCore::getCurrentEpoch() const
×
2877
{
2878
        return 2000.0 + (getJD() - 2451545.0)/365.25;
×
2879
}
2880

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

UNCOV
2885
bool StelCore::de430IsAvailable()
×
2886
{
2887
        return de430Available;
×
2888
}
2889

UNCOV
2890
bool StelCore::de431IsAvailable()
×
2891
{
2892
        return de431Available;
×
2893
}
2894

UNCOV
2895
bool StelCore::de430IsActive()
×
2896
{
2897
        return de430Active;
×
2898
}
2899

UNCOV
2900
bool StelCore::de431IsActive()
×
2901
{
2902
        return de431Active;
×
2903
}
2904

UNCOV
2905
void StelCore::setDe430Active(bool status)
×
2906
{
2907
        de430Active = de430Available && status;
×
UNCOV
2908
}
×
2909

2910
void StelCore::setDe431Active(bool status)
×
2911
{
2912
        de431Active = de431Available && status;
×
UNCOV
2913
}
×
2914

2915

UNCOV
2916
bool StelCore::de440IsAvailable()
×
2917
{
2918
        return de440Available;
×
2919
}
2920

UNCOV
2921
bool StelCore::de441IsAvailable()
×
2922
{
2923
        return de441Available;
×
2924
}
2925

UNCOV
2926
bool StelCore::de440IsActive()
×
2927
{
2928
        return de440Active;
×
2929
}
2930

UNCOV
2931
bool StelCore::de441IsActive()
×
2932
{
2933
        return de441Active;
×
2934
}
2935

UNCOV
2936
void StelCore::setDe440Active(bool status)
×
2937
{
2938
        de440Active = de440Available && status;
×
UNCOV
2939
}
×
2940

2941
void StelCore::setDe441Active(bool status)
×
2942
{
2943
        de441Active = de441Available && status;
×
UNCOV
2944
}
×
2945

2946
void StelCore::initEphemeridesFunctions()
×
2947
{
2948
        QSettings* conf = StelApp::getInstance().getSettings();
×
2949

2950
        QString de430ConfigPath = conf->value("astro/de430_path").toString();
×
UNCOV
2951
        QString de431ConfigPath = conf->value("astro/de431_path").toString();
×
2952
        QString de440ConfigPath = conf->value("astro/de440_path").toString();
×
2953
        QString de441ConfigPath = conf->value("astro/de441_path").toString();
×
2954

2955
        QString de430FilePath;
×
UNCOV
2956
        QString de431FilePath;
×
2957
        QString de440FilePath;
×
2958
        QString de441FilePath;
×
2959

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

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

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

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

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

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

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

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

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

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

UNCOV
3031
Q_GLOBAL_STATIC(QVector<iau_constelspan>, iau_constlineVec);
×
3032
static bool iau_constlineVecInitialized=false;
3033

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

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

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

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

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

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

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

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

UNCOV
3177
Vec3d StelCore::getMouseJ2000Pos() const
×
3178
{
3179
        const StelProjectorP prj = getProjection(StelCore::FrameJ2000, StelCore::RefractionAuto);
×
UNCOV
3180
        float ppx = static_cast<float>(getCurrentStelProjectorParams().devicePixelsPerPixel);
×
3181

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

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

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

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

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

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

UNCOV
3275
void StelCore::setAberrationUniforms(QOpenGLShaderProgram& program) const
×
3276
{
3277
        Vec3d velocity(0.);
×
UNCOV
3278
        if(getUseAberration())
×
3279
        {
3280
                velocity = getAberrationFactor() * cachedAberrationVec;
×
3281
        }
3282
        program.setUniformValue("STELCORE_currentPlanetBarycentricEclipticVelocity", velocity.toQVector());
×
UNCOV
3283
}
×
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