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

Stellarium / stellarium / 3809845615

pending completion
3809845615

push

github

Georg Zotti
Ensured file paths are constant

2 of 2 new or added lines in 1 file covered. (100.0%)

14663 of 123658 relevant lines covered (11.86%)

25812.09 hits per line

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

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

22
#include "SolarSystem.hpp"
23
#include "StelTexture.hpp"
24
#include "EphemWrapper.hpp"
25
#include "Orbit.hpp"
26

27
#include "StelProjector.hpp"
28
#include "StelApp.hpp"
29
#include "StelCore.hpp"
30
#include "StelTextureMgr.hpp"
31
#include "StelObjectMgr.hpp"
32
#include "StelLocaleMgr.hpp"
33
#include "StelSkyCultureMgr.hpp"
34
#include "StelFileMgr.hpp"
35
#include "StelModuleMgr.hpp"
36
#include "StelIniParser.hpp"
37
#include "Planet.hpp"
38
#include "MinorPlanet.hpp"
39
#include "Comet.hpp"
40
#include "StelMainView.hpp"
41

42
#include "StelSkyDrawer.hpp"
43
#include "StelUtils.hpp"
44
#include "StelPainter.hpp"
45
#include "TrailGroup.hpp"
46

47
#include "AstroCalcDialog.hpp"
48
#include "StelObserver.hpp"
49

50
#include <algorithm>
51

52
#include <QTextStream>
53
#include <QSettings>
54
#include <QVariant>
55
#include <QString>
56
#include <QStringList>
57
#include <QMap>
58
#include <QMultiMap>
59
#include <QMapIterator>
60
#include <QDebug>
61
#include <QDir>
62
#include <QHash>
63

64
SolarSystem::SolarSystem() : StelObjectModule()
×
65
        , shadowPlanetCount(0)
×
66
        , earthShadowEnlargementDanjon(false)
×
67
        , flagMoonScale(false)
×
68
        , moonScale(1.0)
×
69
        , flagMinorBodyScale(false)
×
70
        , minorBodyScale(1.0)
×
71
        , flagPlanetScale(false)
×
72
        , planetScale(1.0)
×
73
        , flagSunScale(false)
×
74
        , sunScale(1.0)
×
75
        , labelsAmount(false)
×
76
        , flagPermanentSolarCorona(true)
×
77
        , flagOrbits(false)
×
78
        , flagLightTravelTime(true)
×
79
        , flagUseObjModels(false)
×
80
        , flagShowObjSelfShadows(true)
×
81
        , flagShow(false)
×
82
        , flagPointer(false)
×
83
        , flagNativePlanetNames(false)
×
84
        , flagIsolatedTrails(true)
×
85
        , numberIsolatedTrails(0)
×
86
        , maxTrailPoints(5000)
×
87
        , maxTrailTimeExtent(1)
×
88
        , trailsThickness(1)
×
89
        , flagIsolatedOrbits(true)
×
90
        , flagPlanetsOrbitsOnly(false)
×
91
        , ephemerisMarkersDisplayed(true)
×
92
        , ephemerisDatesDisplayed(false)
×
93
        , ephemerisMagnitudesDisplayed(false)
×
94
        , ephemerisHorizontalCoordinates(false)
×
95
        , ephemerisLineDisplayed(false)
×
96
        , ephemerisAlwaysOn(false)
×
97
        , ephemerisLineThickness(1)
×
98
        , ephemerisSkipDataDisplayed(false)
×
99
        , ephemerisSkipMarkersDisplayed(false)
×
100
        , ephemerisDataStep(1)
×
101
        , ephemerisDataLimit(1)
×
102
        , ephemerisSmartDatesDisplayed(true)
×
103
        , ephemerisScaleMarkersDisplayed(false)
×
104
        , ephemerisGenericMarkerColor(Vec3f(1.0f, 1.0f, 0.0f))
×
105
        , ephemerisSecondaryMarkerColor(Vec3f(0.7f, 0.7f, 1.0f))
×
106
        , ephemerisSelectedMarkerColor(Vec3f(1.0f, 0.7f, 0.0f))
×
107
        , ephemerisMercuryMarkerColor(Vec3f(1.0f, 1.0f, 0.0f))
×
108
        , ephemerisVenusMarkerColor(Vec3f(1.0f, 1.0f, 1.0f))
×
109
        , ephemerisMarsMarkerColor(Vec3f(1.0f, 0.0f, 0.0f))
×
110
        , ephemerisJupiterMarkerColor(Vec3f(0.3f, 1.0f, 1.0f))
×
111
        , ephemerisSaturnMarkerColor(Vec3f(0.0f, 1.0f, 0.0f))
×
112
        , allTrails(Q_NULLPTR)
×
113
        , conf(StelApp::getInstance().getSettings())
×
114
{
115
        planetNameFont.setPixelSize(StelApp::getInstance().getScreenFontSize());
×
116
        connect(&StelApp::getInstance(), SIGNAL(screenFontSizeChanged(int)), this, SLOT(setFontSize(int)));
×
117
        setObjectName("SolarSystem");
×
118
}
×
119

120
void SolarSystem::setFontSize(int newFontSize)
×
121
{
122
        planetNameFont.setPixelSize(newFontSize);
×
123
}
×
124

125
SolarSystem::~SolarSystem()
×
126
{
127
        // release selected:
128
        selected.clear();
×
129
        selectedSSO.clear();
×
130
        for (auto* orb : qAsConst(orbits))
×
131
        {
132
                delete orb;
×
133
                orb = Q_NULLPTR;
×
134
        }
135
        sun.clear();
×
136
        moon.clear();
×
137
        earth.clear();
×
138
        Planet::hintCircleTex.clear();
×
139
        Planet::texEarthShadow.clear();
×
140

141
        texEphemerisMarker.clear();
×
142
        texEphemerisCometMarker.clear();
×
143
        texPointer.clear();
×
144

145
        delete allTrails;
×
146
        allTrails = Q_NULLPTR;
×
147

148
        // Get rid of circular reference between the shared pointers which prevent proper destruction of the Planet objects.
149
        for (const auto& p : qAsConst(systemPlanets))
×
150
        {
151
                p->satellites.clear();
×
152
        }
153

154
        //delete comet textures created in loadPlanets
155
        Comet::comaTexture.clear();
×
156
        Comet::tailTexture.clear();
×
157

158
        //deinit of SolarSystem is NOT called at app end automatically
159
        SolarSystem::deinit();
×
160
}
×
161

162
/*************************************************************************
163
 Re-implementation of the getCallOrder method
164
*************************************************************************/
165
double SolarSystem::getCallOrder(StelModuleActionName actionName) const
×
166
{
167
        if (actionName==StelModule::ActionDraw)
×
168
                return StelApp::getInstance().getModuleMgr().getModule("StarMgr")->getCallOrder(actionName)+10;
×
169
        return 0;
×
170
}
171

172
// Init and load the solar system data
173
void SolarSystem::init()
×
174
{
175
        Q_ASSERT(conf);
×
176

177
        Planet::init();
×
178
        loadPlanets();        // Load planets data
×
179

180
        // Compute position and matrix of sun and all the satellites (ie planets)
181
        // for the first initialization Q_ASSERT that center is sun center (only impacts on light speed correction)        
182
        computePositions(StelApp::getInstance().getCore()->getJDE(), getSun());
×
183

184
        setSelected("");        // Fix a bug on macosX! Thanks Fumio!
×
185
        setFlagDrawMoonHalo(conf->value("viewing/flag_draw_moon_halo", true).toBool());
×
186
        setFlagDrawSunHalo(conf->value("viewing/flag_draw_sun_halo", true).toBool());
×
187
        setFlagMoonScale(conf->value("viewing/flag_moon_scaled", conf->value("viewing/flag_init_moon_scaled", false).toBool()).toBool());  // name change
×
188
        setMoonScale(conf->value("viewing/moon_scale", 4.0).toDouble());
×
189
        setMinorBodyScale(conf->value("viewing/minorbodies_scale", 10.0).toDouble());
×
190
        setFlagMinorBodyScale(conf->value("viewing/flag_minorbodies_scaled", false).toBool());
×
191
        setFlagPlanetScale(conf->value("viewing/flag_planets_scaled", false).toBool());
×
192
        setPlanetScale(conf->value("viewing/planets_scale", 150.0).toDouble());
×
193
        setFlagSunScale(conf->value("viewing/flag_sun_scaled", false).toBool());
×
194
        setSunScale(conf->value("viewing/sun_scale", 4.0).toDouble());
×
195
        setFlagPlanets(conf->value("astro/flag_planets").toBool());
×
196
        setFlagHints(conf->value("astro/flag_planets_hints").toBool());
×
197
        setFlagLabels(conf->value("astro/flag_planets_labels", true).toBool());
×
198
        setLabelsAmount(conf->value("astro/labels_amount", 3.).toDouble());
×
199
        setFlagOrbits(conf->value("astro/flag_planets_orbits").toBool());
×
200
        setFlagLightTravelTime(conf->value("astro/flag_light_travel_time", true).toBool());
×
201
        setFlagUseObjModels(conf->value("astro/flag_use_obj_models", false).toBool());
×
202
        setFlagShowObjSelfShadows(conf->value("astro/flag_show_obj_self_shadows", true).toBool());
×
203
        setFlagPointer(conf->value("astro/flag_planets_pointers", true).toBool());
×
204
        // Set the algorithm from Astronomical Almanac for computation of apparent magnitudes for
205
        // planets in case  observer on the Earth by default
206
        setApparentMagnitudeAlgorithmOnEarth(conf->value("astro/apparent_magnitude_algorithm", "Mallama2018").toString());
×
207
        setFlagNativePlanetNames(conf->value("viewing/flag_planets_native_names", true).toBool());
×
208
        // Is enabled the showing of isolated trails for selected objects only?
209
        setFlagIsolatedTrails(conf->value("viewing/flag_isolated_trails", true).toBool());
×
210
        setNumberIsolatedTrails(conf->value("viewing/number_isolated_trails", 1).toInt());
×
211
        setMaxTrailPoints(conf->value("viewing/max_trail_points", 5000).toInt());
×
212
        setMaxTrailTimeExtent(conf->value("viewing/max_trail_time_extent", 1).toInt());
×
213
        setFlagIsolatedOrbits(conf->value("viewing/flag_isolated_orbits", true).toBool());
×
214
        setFlagPlanetsOrbitsOnly(conf->value("viewing/flag_planets_orbits_only", false).toBool());
×
215
        setFlagPermanentOrbits(conf->value("astro/flag_permanent_orbits", false).toBool());
×
216
        setOrbitColorStyle(conf->value("astro/planets_orbits_color_style", "one_color").toString());
×
217

218
        // Settings for calculation of position of Great Red Spot on Jupiter
219
        setGrsLongitude(conf->value("astro/grs_longitude", 216).toInt());
×
220
        setGrsDrift(conf->value("astro/grs_drift", 15.).toDouble());
×
221
        setGrsJD(conf->value("astro/grs_jd", 2456901.5).toDouble());
×
222

223
        setFlagEarthShadowEnlargementDanjon(conf->value("astro/shadow_enlargement_danjon", false).toBool());
×
224
        setFlagPermanentSolarCorona(conf->value("viewing/flag_draw_sun_corona", true).toBool());
×
225

226
        // Load colors from config file
227
        QString defaultColor = conf->value("color/default_color").toString();
×
228
        setLabelsColor(                    Vec3f(conf->value("color/planet_names_color", defaultColor).toString()));
×
229
        setOrbitsColor(                    Vec3f(conf->value("color/sso_orbits_color", defaultColor).toString()));
×
230
        setMajorPlanetsOrbitsColor(        Vec3f(conf->value("color/major_planet_orbits_color", "0.7,0.2,0.2").toString()));
×
231
        setMoonsOrbitsColor(               Vec3f(conf->value("color/moon_orbits_color", "0.7,0.2,0.2").toString()));
×
232
        setMinorPlanetsOrbitsColor(        Vec3f(conf->value("color/minor_planet_orbits_color", "0.7,0.5,0.5").toString()));
×
233
        setDwarfPlanetsOrbitsColor(        Vec3f(conf->value("color/dwarf_planet_orbits_color", "0.7,0.5,0.5").toString()));
×
234
        setCubewanosOrbitsColor(           Vec3f(conf->value("color/cubewano_orbits_color", "0.7,0.5,0.5").toString()));
×
235
        setPlutinosOrbitsColor(            Vec3f(conf->value("color/plutino_orbits_color", "0.7,0.5,0.5").toString()));
×
236
        setScatteredDiskObjectsOrbitsColor(Vec3f(conf->value("color/sdo_orbits_color", "0.7,0.5,0.5").toString()));
×
237
        setOortCloudObjectsOrbitsColor(    Vec3f(conf->value("color/oco_orbits_color", "0.7,0.5,0.5").toString()));
×
238
        setCometsOrbitsColor(              Vec3f(conf->value("color/comet_orbits_color", "0.7,0.8,0.8").toString()));
×
239
        setSednoidsOrbitsColor(            Vec3f(conf->value("color/sednoid_orbits_color", "0.7,0.5,0.5").toString()));
×
240
        setInterstellarOrbitsColor(        Vec3f(conf->value("color/interstellar_orbits_color", "1.0,0.6,1.0").toString()));
×
241
        setMercuryOrbitColor(              Vec3f(conf->value("color/mercury_orbit_color", "0.5,0.5,0.5").toString()));
×
242
        setVenusOrbitColor(                Vec3f(conf->value("color/venus_orbit_color", "0.9,0.9,0.7").toString()));
×
243
        setEarthOrbitColor(                Vec3f(conf->value("color/earth_orbit_color", "0.0,0.0,1.0").toString()));
×
244
        setMarsOrbitColor(                 Vec3f(conf->value("color/mars_orbit_color", "0.8,0.4,0.1").toString()));
×
245
        setJupiterOrbitColor(              Vec3f(conf->value("color/jupiter_orbit_color", "1.0,0.6,0.0").toString()));
×
246
        setSaturnOrbitColor(               Vec3f(conf->value("color/saturn_orbit_color", "1.0,0.8,0.0").toString()));
×
247
        setUranusOrbitColor(               Vec3f(conf->value("color/uranus_orbit_color", "0.0,0.7,1.0").toString()));
×
248
        setNeptuneOrbitColor(              Vec3f(conf->value("color/neptune_orbit_color", "0.0,0.3,1.0").toString()));
×
249
        setTrailsColor(                    Vec3f(conf->value("color/object_trails_color", defaultColor).toString()));
×
250
        setPointerColor(                   Vec3f(conf->value("color/planet_pointers_color", "1.0,0.3,0.3").toString()));
×
251

252
        // Ephemeris stuff
253
        setFlagEphemerisMarkers(conf->value("astrocalc/flag_ephemeris_markers", true).toBool());
×
254
        setFlagEphemerisAlwaysOn(conf->value("astrocalc/flag_ephemeris_alwayson", true).toBool());
×
255
        setFlagEphemerisDates(conf->value("astrocalc/flag_ephemeris_dates", false).toBool());
×
256
        setFlagEphemerisMagnitudes(conf->value("astrocalc/flag_ephemeris_magnitudes", false).toBool());
×
257
        setFlagEphemerisHorizontalCoordinates(conf->value("astrocalc/flag_ephemeris_horizontal", false).toBool());
×
258
        setFlagEphemerisLine(conf->value("astrocalc/flag_ephemeris_line", false).toBool());
×
259
        setEphemerisLineThickness(conf->value("astrocalc/ephemeris_line_thickness", 1).toInt());
×
260
        setFlagEphemerisSkipData(conf->value("astrocalc/flag_ephemeris_skip_data", false).toBool());
×
261
        setFlagEphemerisSkipMarkers(conf->value("astrocalc/flag_ephemeris_skip_markers", false).toBool());
×
262
        setEphemerisDataStep(conf->value("astrocalc/ephemeris_data_step", 1).toInt());        
×
263
        setFlagEphemerisSmartDates(conf->value("astrocalc/flag_ephemeris_smart_dates", true).toBool());
×
264
        setFlagEphemerisScaleMarkers(conf->value("astrocalc/flag_ephemeris_scale_markers", false).toBool());
×
265
        setEphemerisGenericMarkerColor( Vec3f(conf->value("color/ephemeris_generic_marker_color", "1.0,1.0,0.0").toString()));
×
266
        setEphemerisSecondaryMarkerColor( Vec3f(conf->value("color/ephemeris_secondary_marker_color", "0.7,0.7,1.0").toString()));
×
267
        setEphemerisSelectedMarkerColor(Vec3f(conf->value("color/ephemeris_selected_marker_color", "1.0,0.7,0.0").toString()));
×
268
        setEphemerisMercuryMarkerColor( Vec3f(conf->value("color/ephemeris_mercury_marker_color", "1.0,1.0,0.0").toString()));
×
269
        setEphemerisVenusMarkerColor(   Vec3f(conf->value("color/ephemeris_venus_marker_color", "1.0,1.0,1.0").toString()));
×
270
        setEphemerisMarsMarkerColor(    Vec3f(conf->value("color/ephemeris_mars_marker_color", "1.0,0.0,0.0").toString()));
×
271
        setEphemerisJupiterMarkerColor( Vec3f(conf->value("color/ephemeris_jupiter_marker_color", "0.3,1.0,1.0").toString()));
×
272
        setEphemerisSaturnMarkerColor(  Vec3f(conf->value("color/ephemeris_saturn_marker_color", "0.0,1.0,0.0").toString()));
×
273

274
        setOrbitsThickness(conf->value("astro/object_orbits_thickness", 1).toBool());
×
275
        setTrailsThickness(conf->value("astro/object_trails_thickness", 1).toBool());
×
276
        recreateTrails();
×
277
        setFlagTrails(conf->value("astro/flag_object_trails", false).toBool());
×
278

279
        StelObjectMgr *objectManager = GETSTELMODULE(StelObjectMgr);
×
280
        objectManager->registerStelObjectMgr(this);
×
281
        connect(objectManager, SIGNAL(selectedObjectChanged(StelModule::StelModuleSelectAction)),
×
282
                this, SLOT(selectedObjectChange(StelModule::StelModuleSelectAction)));
283

284
        texPointer = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/pointeur4.png");
×
285
        texEphemerisMarker = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/disk.png");
×
286
        texEphemerisCometMarker = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/cometIcon.png");
×
287
        Planet::hintCircleTex = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/planet-indicator.png");
×
288
        
289
        StelApp *app = &StelApp::getInstance();
×
290
        connect(app, SIGNAL(languageChanged()), this, SLOT(updateI18n()));
×
291
        connect(&app->getSkyCultureMgr(), SIGNAL(currentSkyCultureChanged(QString)), this, SLOT(updateSkyCulture(QString)));
×
292
        connect(&StelMainView::getInstance(), SIGNAL(reloadShadersRequested()), this, SLOT(reloadShaders()));
×
293
        StelCore *core = app->getCore();
×
294
        connect(core, SIGNAL(locationChanged(StelLocation)), this, SLOT(recreateTrails()));
×
295
        connect(core, SIGNAL(dateChangedForTrails()), this, SLOT(recreateTrails()));
×
296

297
        QString displayGroup = N_("Display Options");
×
298
        addAction("actionShow_Planets", displayGroup, N_("Planets"), "planetsDisplayed", "P");
×
299
        addAction("actionShow_Planets_Labels", displayGroup, N_("Planet labels"), "labelsDisplayed", "Alt+P");
×
300
        addAction("actionShow_Planets_Orbits", displayGroup, N_("Planet orbits"), "flagOrbits", "O");
×
301
        addAction("actionShow_Planets_Trails", displayGroup, N_("Planet trails"), "trailsDisplayed", "Shift+T");
×
302
        addAction("actionShow_Planets_Trails_Reset", displayGroup, N_("Planet trails reset"), "recreateTrails()"); // No hotkey predefined.
×
303
        //there is a small discrepancy in the GUI: "Show planet markers" actually means show planet hints
304
        addAction("actionShow_Planets_Hints", displayGroup, N_("Planet markers"), "flagHints", "Ctrl+P");
×
305
        addAction("actionShow_Planets_Pointers", displayGroup, N_("Planet selection marker"), "flagPointer", "Ctrl+Shift+P");
×
306
        addAction("actionShow_Planets_EnlargeMoon", displayGroup, N_("Enlarge Moon"), "flagMoonScale");
×
307
        addAction("actionShow_Planets_EnlargeMinor", displayGroup, N_("Enlarge minor bodies"), "flagMinorBodyScale");
×
308
        addAction("actionShow_Planets_EnlargePlanets", displayGroup, N_("Enlarge Planets"), "flagPlanetScale");
×
309
        addAction("actionShow_Planets_EnlargeSun", displayGroup, N_("Enlarge Sun"), "flagSunScale");
×
310
        addAction("actionShow_Skyculture_NativePlanetNames", displayGroup, N_("Native planet names (from starlore)"), "flagNativePlanetNames", "Ctrl+Shift+N");
×
311

312
        connect(StelApp::getInstance().getModule("HipsMgr"), SIGNAL(gotNewSurvey(HipsSurveyP)),
×
313
                        this, SLOT(onNewSurvey(HipsSurveyP)));
314

315
        // Fill ephemeris dates
316
        connect(this, SIGNAL(requestEphemerisVisualization()), this, SLOT(fillEphemerisDates()));
×
317
        connect(this, SIGNAL(ephemerisDataStepChanged(int)), this, SLOT(fillEphemerisDates()));
×
318
        connect(this, SIGNAL(ephemerisSkipDataChanged(bool)), this, SLOT(fillEphemerisDates()));
×
319
        connect(this, SIGNAL(ephemerisSkipMarkersChanged(bool)), this, SLOT(fillEphemerisDates()));
×
320
        connect(this, SIGNAL(ephemerisSmartDatesChanged(bool)), this, SLOT(fillEphemerisDates()));
×
321
}
×
322

323
void SolarSystem::deinit()
×
324
{
325
        Planet::deinitShader();
×
326
        Planet::deinitFBO();
×
327
}
×
328

329
void SolarSystem::resetTextures(const QString &planetName)
×
330
{
331
        if (planetName.isEmpty())
×
332
        {
333
                for (const auto& p : qAsConst(systemPlanets))
×
334
                {
335
                        p->resetTextures();
×
336
                }
337
        }
338
        else
339
        {
340
                PlanetP planet = searchByEnglishName(planetName);
×
341
                if (!planet.isNull())
×
342
                        planet->resetTextures();
×
343
        }
×
344
}
×
345

346
void SolarSystem::setTextureForPlanet(const QString& planetName, const QString& texName)
×
347
{
348
        PlanetP planet = searchByEnglishName(planetName);
×
349
        if (!planet.isNull())
×
350
                planet->replaceTexture(texName);
×
351
        else
352
                qWarning() << "The planet" << planetName << "was not found. Please check the name.";
×
353
}
×
354

355
void SolarSystem::recreateTrails()
×
356
{
357
        // Create a trail group containing all the planets orbiting the sun (not including satellites)
358
        if (allTrails!=Q_NULLPTR)
×
359
                delete allTrails;
×
360
        allTrails = new TrailGroup(maxTrailTimeExtent * 365.f, maxTrailPoints);
×
361

362
        unsigned long cnt = static_cast<unsigned long>(selectedSSO.size());
×
363
        if (cnt>0 && getFlagIsolatedTrails())
×
364
        {
365
                unsigned long limit = static_cast<unsigned long>(getNumberIsolatedTrails());
×
366
                if (cnt<limit)
×
367
                        limit = cnt;
×
368
                for (unsigned long i=0; i<limit; i++)
×
369
                {
370
                        if (selectedSSO[cnt - i - 1]->getPlanetType() != Planet::isObserver)
×
371
                                allTrails->addObject(static_cast<QSharedPointer<StelObject>>(selectedSSO[cnt - i - 1]), &trailsColor);
×
372
                }
373
        }
374
        else
375
        {
376
                for (const auto& p : qAsConst(getSun()->satellites))
×
377
                {
378
                        if (p->getPlanetType() != Planet::isObserver)
×
379
                                allTrails->addObject(static_cast<QSharedPointer<StelObject>>(p), &trailsColor);
×
380
                }
381
                // Add moons of current planet
382
                StelCore *core=StelApp::getInstance().getCore();
×
383
                const StelObserver *obs=core->getCurrentObserver();
×
384
                if (obs)
×
385
                {
386
                        const QSharedPointer<Planet> planet=obs->getHomePlanet();
×
387
                        for (const auto& m : qAsConst(planet->satellites))
×
388
                                if (m->getPlanetType() != Planet::isObserver)
×
389
                                        allTrails->addObject(static_cast<QSharedPointer<StelObject>>(m), &trailsColor);
×
390
                }
×
391
        }
392
}
×
393

394

395
void SolarSystem::updateSkyCulture(const QString& skyCultureDir)
×
396
{
397
        planetNativeNamesMap.clear();
×
398
        planetNativeNamesMeaningMap.clear();
×
399

400
        QString namesFile = StelFileMgr::findFile("skycultures/" + skyCultureDir + "/planet_names.fab");
×
401

402
        if (namesFile.isEmpty())
×
403
        {
404
                for (const auto& p : qAsConst(systemPlanets))
×
405
                {
406
                        if (p->getPlanetType()==Planet::isPlanet || p->getPlanetType()==Planet::isMoon || p->getPlanetType()==Planet::isStar)
×
407
                        {
408
                                p->setNativeName("");
×
409
                                p->setNativeNameMeaning("");
×
410
                        }
411
                }
412
                updateI18n();
×
413
                return;
×
414
        }
415

416
        // Open file
417
        QFile planetNamesFile(namesFile);
×
418
        if (!planetNamesFile.open(QIODevice::ReadOnly | QIODevice::Text))
×
419
        {
420
                qDebug() << " Cannot open file" << QDir::toNativeSeparators(namesFile);
×
421
                return;
×
422
        }
423

424
        // Now parse the file
425
        // lines to ignore which start with a # or are empty
426
        static const QRegularExpression commentRx("^(\\s*#.*|\\s*)$");
×
427

428
        // lines which look like records - we use the RE to extract the fields
429
        // which will be available in recRx.capturedTexts()
430
        static const QRegularExpression recRx("^\\s*(\\w+)\\s+\"(.+)\"\\s+_[(]\"(.+)\"[)]\\n");
×
431

432
        QString record, planetId, nativeName, nativeNameMeaning;
×
433

434
        // keep track of how many records we processed.
435
        int totalRecords=0;
×
436
        int readOk=0;
×
437
        int lineNumber=0;
×
438
        while (!planetNamesFile.atEnd())
×
439
        {
440
                record = QString::fromUtf8(planetNamesFile.readLine());
×
441
                lineNumber++;
×
442

443
                // Skip comments
444
                if (commentRx.match(record).hasMatch())
×
445
                        continue;
×
446

447
                totalRecords++;
×
448

449
                QRegularExpressionMatch match=recRx.match(record);
×
450
                if (!match.hasMatch())
×
451
                {
452
                        qWarning() << "ERROR - cannot parse record at line" << lineNumber << "in planet names file" << QDir::toNativeSeparators(namesFile);
×
453
                }
454
                else
455
                {
456
                        planetId          = match.captured(1).trimmed();
×
457
                        nativeName        = match.captured(2).trimmed();
×
458
                        nativeNameMeaning = match.captured(3).trimmed();
×
459
                        planetNativeNamesMap[planetId] = nativeName;
×
460
                        planetNativeNamesMeaningMap[planetId] = nativeNameMeaning;
×
461
                        readOk++;
×
462
                }
463
        }
×
464
        planetNamesFile.close();
×
465
        qDebug() << "Loaded" << readOk << "/" << totalRecords << "native names of planets";
×
466

467
        for (const auto& p : qAsConst(systemPlanets))
×
468
        {
469
                if (p->getPlanetType()==Planet::isPlanet || p->getPlanetType()==Planet::isMoon || p->getPlanetType()==Planet::isStar)
×
470
                {
471
                        p->setNativeName(planetNativeNamesMap[p->getEnglishName()]);
×
472
                        p->setNativeNameMeaning(planetNativeNamesMeaningMap[p->getEnglishName()]);
×
473
                }
474
        }
475

476
        updateI18n();
×
477
}
×
478

479
void SolarSystem::reloadShaders()
×
480
{
481
        Planet::deinitShader();
×
482
        Planet::initShader();
×
483
}
×
484

485
void SolarSystem::drawPointer(const StelCore* core)
×
486
{
487
        const StelProjectorP prj = core->getProjection(StelCore::FrameJ2000);
×
488

489
        const QList<StelObjectP> newSelected = GETSTELMODULE(StelObjectMgr)->getSelectedObject("Planet");
×
490
        if (!newSelected.empty())
×
491
        {
492
                const StelObjectP obj = newSelected[0];
×
493
                Vec3d pos=obj->getJ2000EquatorialPos(core);
×
494

495
                Vec3f screenpos;
×
496
                // Compute 2D pos and return if outside screen
497
                if (!prj->project(pos, screenpos))
×
498
                        return;
×
499

500
                StelPainter sPainter(prj);
×
501
                sPainter.setColor(getPointerColor());
×
502

503
                float screenSize = static_cast<float>(obj->getAngularRadius(core))*prj->getPixelPerRadAtCenter()*M_PI_180f*2.f;
×
504
                
505
                const float scale = static_cast<float>(prj->getDevicePixelsPerPixel())*StelApp::getInstance().getGlobalScalingRatio();
×
506
                screenSize+= scale * (45.f + 10.f*std::sin(2.f * static_cast<float>(StelApp::getInstance().getAnimationTime())));
×
507

508
                texPointer->bind();
×
509

510
                sPainter.setBlending(true);
×
511

512
                screenSize*=0.5f;
×
513
                const float angleBase = static_cast<float>(StelApp::getInstance().getAnimationTime()) * 10;
×
514
                // We draw 4 instances of the sprite at the corners of the pointer
515
                for (int i = 0; i < 4; ++i)
×
516
                {
517
                        const float angle = angleBase + i * 90;
×
518
                        const float x = screenpos[0] + screenSize * cos(angle * M_PI_180f);
×
519
                        const float y = screenpos[1] + screenSize * sin(angle * M_PI_180f);
×
520
                        sPainter.drawSprite2dMode(x, y, 10, angle);
×
521
                }
522
        }
×
523
}
×
524

525
void keplerOrbitPosFunc(double jd,double xyz[3], double xyzdot[3], void* orbitPtr)
×
526
{
527
        static_cast<KeplerOrbit*>(orbitPtr)->positionAtTimevInVSOP87Coordinates(jd, xyz);
×
528
        static_cast<KeplerOrbit*>(orbitPtr)->getVelocity(xyzdot);
×
529
}
×
530

531
void gimbalOrbitPosFunc(double jd,double xyz[3], double xyzdot[3], void* orbitPtr)
×
532
{
533
        static_cast<GimbalOrbit*>(orbitPtr)->positionAtTimevInVSOP87Coordinates(jd, xyz);
×
534
        static_cast<GimbalOrbit*>(orbitPtr)->getVelocity(xyzdot);
×
535
}
×
536

537
// Init and load the solar system data (2 files)
538
void SolarSystem::loadPlanets()
×
539
{
540
        minorBodies.clear();
×
541
        systemMinorBodies.clear();
×
542
        qDebug() << "Loading Solar System data (1: planets and moons) ...";
×
543
        QString solarSystemFile = StelFileMgr::findFile("data/ssystem_major.ini");
×
544
        if (solarSystemFile.isEmpty())
×
545
        {
546
                qWarning() << "ERROR while loading ssystem_major.ini (unable to find data/ssystem_major.ini): " << StelUtils::getEndLineChar();
×
547
                return;
×
548
        }
549

550
        if (!loadPlanets(solarSystemFile))
×
551
        {
552
                qWarning() << "ERROR while loading ssystem_major.ini: " << StelUtils::getEndLineChar();
×
553
                return;
×
554
        }
555

556
        qDebug() << "Loading Solar System data (2: minor bodies)...";
×
557
        QStringList solarSystemFiles = StelFileMgr::findFileInAllPaths("data/ssystem_minor.ini");
×
558
        if (solarSystemFiles.isEmpty())
×
559
        {
560
                qWarning() << "ERROR while loading ssystem_minor.ini (unable to find data/ssystem_minor.ini): " << StelUtils::getEndLineChar();
×
561
                return;
×
562
        }
563

564
        for (const auto& solarSystemFile : qAsConst(solarSystemFiles))
×
565
        {
566
                if (loadPlanets(solarSystemFile))
×
567
                {
568
                        qDebug() << "File ssystem_minor.ini is loaded successfully...";
×
569
                        break;
×
570
                }
571
                else
572
                {
573
//                        sun.clear();
574
//                        moon.clear();
575
//                        earth.clear();
576
                        //qCritical() << "We should not be here!";
577

578
                        qDebug() << "Removing minor bodies";
×
579
                        for (const auto& p : qAsConst(systemPlanets))
×
580
                        {
581
                                // We can only delete minor objects now!
582
                                if (p->pType >= Planet::isAsteroid)
×
583
                                {
584
                                        p->satellites.clear();
×
585
                                }
586
                        }                        
587
                        systemPlanets.clear();                        
×
588
                        //Memory leak? What's the proper way of cleaning shared pointers?
589

590
                        // TODO: 0.16pre what about the orbits list?
591

592
                        //If the file is in the user data directory, rename it:
593
                        if (solarSystemFile.contains(StelFileMgr::getUserDir()))
×
594
                        {
595
                                QString newName = QString("%1/data/ssystem_minor-%2.ini").arg(StelFileMgr::getUserDir(), QDateTime::currentDateTime().toString("yyyyMMddThhmmss"));
×
596
                                if (QFile::rename(solarSystemFile, newName))
×
597
                                        qWarning() << "Invalid Solar System file" << QDir::toNativeSeparators(solarSystemFile) << "has been renamed to" << QDir::toNativeSeparators(newName);
×
598
                                else
599
                                {
600
                                        qWarning() << "Invalid Solar System file" << QDir::toNativeSeparators(solarSystemFile) << "cannot be removed!";
×
601
                                        qWarning() << "Please either delete it, rename it or move it elsewhere.";
×
602
                                }
603
                        }
×
604
                }
605
        }
606

607
        shadowPlanetCount = 0;
×
608

609
        for (const auto& planet : qAsConst(systemPlanets))
×
610
                if(planet->parent != sun || !planet->satellites.isEmpty())
×
611
                        shadowPlanetCount++;
×
612
}
×
613

614
unsigned char SolarSystem::BvToColorIndex(double bV)
×
615
{
616
        const double dBV = qBound(-500., static_cast<double>(bV)*1000.0, 3499.);
×
617
        return static_cast<unsigned char>(floor(0.5+127.0*((500.0+dBV)/4000.0)));
×
618
}
619

620
bool SolarSystem::loadPlanets(const QString& filePath)
×
621
{
622
        StelSkyDrawer* skyDrawer = StelApp::getInstance().getCore()->getSkyDrawer();
×
623
        qDebug() << "Loading from :"  << filePath;
×
624
        QSettings pd(filePath, StelIniFormat);
×
625
        if (pd.status() != QSettings::NoError)
×
626
        {
627
                qWarning() << "ERROR while parsing" << QDir::toNativeSeparators(filePath);
×
628
                return false;
×
629
        }
630

631
        // QSettings does not allow us to say that the sections of the file
632
        // will be listed in the same order  as in the file like the old
633
        // InitParser used to so we can no longer assume that.
634
        //
635
        // This means we must first decide what order to read the sections
636
        // of the file in (each section contains one planet/moon/asteroid/comet/...) to avoid setting
637
        // the parent Planet* to one which has not yet been created.
638
        //
639
        // Stage 1: Make a map of body names back to the section names
640
        // which they come from. Also make a map of body name to parent body
641
        // name. These two maps can be made in a single pass through the
642
        // sections of the file.
643
        //
644
        // Stage 2: Make an ordered list of section names such that each
645
        // item is only ever dependent on items which appear earlier in the
646
        // list.
647
        // 2a: Make a QMultiMap relating the number of levels of dependency
648
        //     to the body name, i.e.
649
        //     0 -> Sun
650
        //     1 -> Mercury
651
        //     1 -> Venus
652
        //     1 -> Earth
653
        //     2 -> Moon
654
        //     etc.
655
        // 2b: Populate an ordered list of section names by iterating over
656
        //     the QMultiMap.  This type of container is always sorted on the
657
        //     key in ascending order, so it's easy.
658
        //     i.e. [sun, earth, moon] is fine, but not [sun, moon, earth]
659
        //
660
        // Stage 3: iterate over the ordered sections decided in stage 2,
661
        // creating the planet objects from the QSettings data.
662

663
        // Stage 1 (as described above).
664
        QMap<QString, QString> secNameMap;
×
665
        QMap<QString, QString> parentMap;
×
666
        QStringList sections = pd.childGroups();
×
667
        // qDebug() << "Stage 1: load ini file with" << sections.size() << "entries: "<< sections;
668
        for (int i=0; i<sections.size(); ++i)
×
669
        {
670
                const QString secname = sections.at(i);
×
671
                const QString englishName = pd.value(secname+"/name").toString();
×
672
                const QString strParent = pd.value(secname+"/parent", "Sun").toString();
×
673
                secNameMap[englishName] = secname;
×
674
                if (strParent!="none" && !strParent.isEmpty() && !englishName.isEmpty())
×
675
                {
676
                        parentMap[englishName] = strParent;
×
677
                        // qDebug() << "parentmap[" << englishName << "] = " << strParent;
678
                }
679
        }
×
680

681
        // Stage 2a (as described above).
682
        QMultiMap<int, QString> depLevelMap;
×
683
        for (int i=0; i<sections.size(); ++i)
×
684
        {
685
                const QString englishName = pd.value(sections.at(i)+"/name").toString();
×
686

687
                // follow dependencies, incrementing level when we have one
688
                // till we run out.
689
                QString p=englishName;
×
690
                int level = 0;
×
691
                while(parentMap.contains(p) && parentMap[p]!="none")
×
692
                {
693
                        level++;
×
694
                        p = parentMap[p];
×
695
                }
696

697
                depLevelMap.insert(level, secNameMap[englishName]);
×
698
                // qDebug() << "2a: Level" << level << "secNameMap[" << englishName << "]="<< secNameMap[englishName];
699
        }
×
700

701
        // Stage 2b (as described above).
702
        // qDebug() << "Stage 2b:";
703
        QStringList orderedSections;
×
704
#if (QT_VERSION>=QT_VERSION_CHECK(6,0,0))
705
        QMultiMapIterator<int, QString> levelMapIt(depLevelMap);
706
#else
707
        QMapIterator<int, QString> levelMapIt(depLevelMap);
×
708
#endif
709
        while(levelMapIt.hasNext())
×
710
        {
711
                levelMapIt.next();
×
712
                orderedSections << levelMapIt.value();
×
713
        }
714
        // qDebug() << orderedSections;
715

716
        // Stage 3 (as described above).
717
        int readOk=0;
×
718
        //int totalPlanets=0;
719

720
        // qDebug() << "Adding " << orderedSections.size() << "objects...";
721
        for (int i = 0;i<orderedSections.size();++i)
×
722
        {
723
                // qDebug() << "Processing entry" << orderedSections.at(i);
724

725
                //totalPlanets++;
726
                const QString secname = orderedSections.at(i);
×
727
                const QString englishName = pd.value(secname+"/name").toString().simplified();
×
728
                const QString strParent = pd.value(secname+"/parent", "Sun").toString(); // Obvious default, keep file entries simple.
×
729
                PlanetP parent;
×
730
                if (strParent!="none")
×
731
                {
732
                        // Look in the other planets the one named with strParent
733
                        for (const auto& p : qAsConst(systemPlanets))
×
734
                        {
735
                                if (p->getEnglishName()==strParent)
×
736
                                {
737
                                        parent = p;
×
738
                                        break;
×
739
                                }
740
                        }
741
                        if (parent.isNull())
×
742
                        {
743
                                qWarning() << "ERROR : can't find parent solar system body for " << englishName << ". Skipping.";
×
744
                                //abort();
745
                                continue;
×
746
                        }
747
                }
748
                Q_ASSERT(parent || englishName=="Sun");
×
749

750
                const QString coordFuncName = pd.value(secname+"/coord_func", "kepler_orbit").toString(); // 0.20: new default for all non *_special.
×
751
                // qDebug() << "englishName:" << englishName << ", parent:" << strParent <<  ", coord_func:" << coordFuncName;
752
                posFuncType posfunc=Q_NULLPTR;
×
753
                Orbit* orbitPtr=Q_NULLPTR;
×
754
                OsculatingFunctType *osculatingFunc = Q_NULLPTR;
×
755
                bool closeOrbit = true;
×
756
                double semi_major_axis=0; // used again below.
×
757
                const QString type = pd.value(secname+"/type").toString();
×
758

759

760
#ifdef USE_GIMBAL_ORBIT
761
                // undefine the flag in Orbit.h to disable and use the old, static observer solution (on an infinitely slow KeplerOrbit)
762
                // Note that for now we ignore any orbit-related config values from the ini file.
763
                if (type=="observer")
×
764
                {
765
                        // Create a pseudo orbit that allows interaction with keyboard
766
                        GimbalOrbit *orb = new GimbalOrbit(1, 0., 90.);    // [1 AU over north pole]
×
767
                        orbits.push_back(orb);
×
768

769
                        orbitPtr = orb;
×
770
                        posfunc = &gimbalOrbitPosFunc;
×
771
                }
772
                else
773
#endif
774
                if ((coordFuncName=="kepler_orbit") || (coordFuncName=="comet_orbit") || (coordFuncName=="ell_orbit")) // ell_orbit used for planet moons. TBD in V1.0: remove non-kepler_orbit!
×
775
                {
776
                        // ell_orbit was used for planet moons, comet_orbit for minor bodies. The only difference is that pericenter distance for moons is given in km, not AU.
777
                        // Read the orbital elements                        
778
                        const double eccentricity = pd.value(secname+"/orbit_Eccentricity", 0.0).toDouble();
×
779
                        if (eccentricity >= 1.0) closeOrbit = false;
×
780
                        double pericenterDistance = pd.value(secname+"/orbit_PericenterDistance",-1e100).toDouble(); // AU, or km for ell_orbit!
×
781
                        if (pericenterDistance <= 0.0) {
×
782
                                semi_major_axis = pd.value(secname+"/orbit_SemiMajorAxis",-1e100).toDouble();
×
783
                                if (semi_major_axis <= -1e100) {
×
784
                                        qDebug() << "ERROR loading " << englishName
×
785
                                                 << ": you must provide orbit_PericenterDistance or orbit_SemiMajorAxis. Skipping " << englishName;
×
786
                                        continue;
×
787
                                } else {
788
                                        Q_ASSERT(eccentricity != 1.0); // parabolic orbits have no semi_major_axis
×
789
                                        pericenterDistance = semi_major_axis * (1.0-eccentricity);
×
790
                                }
791
                        } else {
792
                                semi_major_axis = (eccentricity == 1.0)
×
793
                                                                ? 0.0 // parabolic orbits have no semi_major_axis
×
794
                                                                : pericenterDistance / (1.0-eccentricity);
×
795
                        }
796
                        if (strParent!="Sun")
×
797
                                pericenterDistance /= AU;  // Planet moons have distances given in km in the .ini file! But all further computation done in AU.
×
798

799
                        double meanMotion = pd.value(secname+"/orbit_MeanMotion",-1e100).toDouble(); // degrees/day
×
800
                        if (meanMotion <= -1e100) {
×
801
                                const double period = pd.value(secname+"/orbit_Period",-1e100).toDouble();
×
802
                                if (period <= -1e100) {
×
803
                                        if (parent->getParent()) {
×
804
                                                qWarning() << "ERROR: " << englishName
×
805
                                                           << ": when the parent body is not the sun, you must provide "
×
806
                                                           << "either orbit_MeanMotion or orbit_Period";
×
807
                                        } else {
808
                                                // in case of parent=sun: use Gaussian gravitational constant for calculating meanMotion:
809
                                                meanMotion = (eccentricity == 1.0)
×
810
                                                                        ? 0.01720209895 * (1.5/pericenterDistance) * std::sqrt(0.5/pericenterDistance)  // Heafner: Fund.Eph.Comp. W / dt
×
811
                                                                        : 0.01720209895 / (fabs(semi_major_axis)*std::sqrt(fabs(semi_major_axis)));
×
812
                                        }
813
                                } else {
814
                                        meanMotion = 2.0*M_PI/period;
×
815
                                }
816
                        } else {
817
                                meanMotion *= (M_PI/180.0);
×
818
                        }
819

820
                        const double ascending_node = pd.value(secname+"/orbit_AscendingNode", 0.0).toDouble()*(M_PI/180.0);
×
821
                        double arg_of_pericenter = pd.value(secname+"/orbit_ArgOfPericenter",-1e100).toDouble();
×
822
                        double long_of_pericenter;
823
                        if (arg_of_pericenter <= -1e100) {
×
824
                                long_of_pericenter = pd.value(secname+"/orbit_LongOfPericenter", 0.0).toDouble()*(M_PI/180.0);
×
825
                                arg_of_pericenter = long_of_pericenter - ascending_node;
×
826
                        } else {
827
                                arg_of_pericenter *= (M_PI/180.0);
×
828
                                long_of_pericenter = arg_of_pericenter + ascending_node;
×
829
                        }
830

831
                        double time_at_pericenter = pd.value(secname+"/orbit_TimeAtPericenter",-1e100).toDouble();
×
832
                        // In earlier times (up to 0.21.2) we did not care much to store orbital epoch for comets but silently assumed T for it in various places.
833
                        // However, the distinction is relevant to discern element sets for various valid ranges.
834
                        // Comet orbits epoch should default to T while planets or moons default to J2000.
835
                        const double epoch = pd.value(secname+"/orbit_Epoch", type=="comet" ? time_at_pericenter : J2000).toDouble();
×
836
                        if (time_at_pericenter <= -1e100) {
×
837
                                double mean_anomaly = pd.value(secname+"/orbit_MeanAnomaly",-1e100).toDouble()*(M_PI/180.0);
×
838
                                if (mean_anomaly <= -1e10) {
×
839
                                        double mean_longitude = pd.value(secname+"/orbit_MeanLongitude",-1e100).toDouble()*(M_PI/180.0);
×
840
                                        if (mean_longitude <= -1e10) {
×
841
                                                qWarning() << "ERROR: " << englishName
×
842
                                                           << ": when you do not provide orbit_TimeAtPericenter, you must provide orbit_Epoch"
×
843
                                                           << "and either one of orbit_MeanAnomaly or orbit_MeanLongitude. Skipping this object.";
×
844
                                                //abort();
845
                                                continue;
×
846
                                        } else {
847
                                                mean_anomaly = mean_longitude - long_of_pericenter;
×
848
                                        }
849
                                }
850
                                time_at_pericenter = epoch - mean_anomaly / meanMotion;
×
851
                        }
852

853
                        static const QMap<QString, double>massMap={ // masses from DE430/431
854
                                { "Sun",            1.0},
×
855
                                { "Mercury",  6023682.155592},
×
856
                                { "Venus",     408523.718658},
×
857
                                { "Earth",     332946.048834},
×
858
                                { "Mars",     3098703.590291},
×
859
                                { "Jupiter",     1047.348625},
×
860
                                { "Saturn",      3497.901768},
×
861
                                { "Uranus",     22902.981613},
×
862
                                { "Neptune",    19412.259776},
×
863
                                { "Pluto",  135836683.768617}};
×
864

865
                        // Construct orbital elements relative to the parent body. This will construct orbits for J2000 only.
866
                        // Some planet axes move very slowly, this effect could be modelled by replicating these lines
867
                        // after recomputing obliquity and node (below) in Planet::computeTransMatrix().
868
                        // The effect is negligible for several millennia, though.
869
                        // When the parent is the sun use ecliptic rather than sun equator:
870
                        const double parentRotObliquity  = parent->getParent() ? parent->getRotObliquity(J2000) : 0.0;
×
871
                        const double parent_rot_asc_node = parent->getParent() ? parent->getRotAscendingNode()  : 0.0;
×
872
                        double parent_rot_j2000_longitude = 0.0;
×
873
                        if (parent->getParent()) {
×
874
                                const double c_obl = cos(parentRotObliquity);
×
875
                                const double s_obl = sin(parentRotObliquity);
×
876
                                const double c_nod = cos(parent_rot_asc_node);
×
877
                                const double s_nod = sin(parent_rot_asc_node);
×
878
                                const Vec3d OrbitAxis0( c_nod,       s_nod,        0.0);
×
879
                                const Vec3d OrbitAxis1(-s_nod*c_obl, c_nod*c_obl,s_obl);
×
880
                                const Vec3d OrbitPole(  s_nod*s_obl,-c_nod*s_obl,c_obl);
×
881
                                const Vec3d J2000Pole(StelCore::matJ2000ToVsop87.multiplyWithoutTranslation(Vec3d(0,0,1)));
×
882
                                Vec3d J2000NodeOrigin(J2000Pole^OrbitPole);
×
883
                                J2000NodeOrigin.normalize();
×
884
                                parent_rot_j2000_longitude = atan2(J2000NodeOrigin*OrbitAxis1,J2000NodeOrigin*OrbitAxis0);
×
885
                        }
886

887
                        const double orbitGoodDays=pd.value(secname+"/orbit_good", parent->englishName!="Sun" ? 0. : -1.).toDouble(); // "Moons" have permanently good orbits.
×
888
                        const double inclination = pd.value(secname+"/orbit_Inclination", 0.0).toDouble()*(M_PI/180.0);
×
889

890
                        // Create a Keplerian orbit. This has been called CometOrbit before 0.20.
891
                        //qDebug() << "Creating KeplerOrbit for" << parent->englishName << "---" << englishName;
892
                        KeplerOrbit *orb = new KeplerOrbit(epoch,                  // JDE
893
                                                           pericenterDistance,     // [AU]
894
                                                           eccentricity,           // 0..>1 (>>1 for Interstellar objects)
895
                                                           inclination,            // [radians]
896
                                                           ascending_node,         // [radians]
897
                                                           arg_of_pericenter,      // [radians]
898
                                                           time_at_pericenter,     // JDE
899
                                                           orbitGoodDays,          // orbitGoodDays. 0=always good, -1=compute_half_orbit_duration
900
                                                           meanMotion,             // [radians/day]
901
                                                           parentRotObliquity,     // [radians]
902
                                                           parent_rot_asc_node,    // [radians]
903
                                                           parent_rot_j2000_longitude, // [radians]
904
                                                           1./massMap.value(parent->englishName, 1.)); // central mass [solar masses]
×
905
                        orbits.push_back(orb);
×
906

907
                        orbitPtr = orb;
×
908
                        posfunc = &keplerOrbitPosFunc;
×
909
                }
910
                else
911
                {
912
                        static const QMap<QString, posFuncType>posfuncMap={
913
                                { "sun_special",       &get_sun_helio_coordsv},
×
914
                                { "mercury_special",   &get_mercury_helio_coordsv},
×
915
                                { "venus_special",     &get_venus_helio_coordsv},
×
916
                                { "earth_special",     &get_earth_helio_coordsv},
×
917
                                { "lunar_special",     &get_lunar_parent_coordsv},
×
918
                                { "mars_special",      &get_mars_helio_coordsv},
×
919
                                { "phobos_special",    &get_phobos_parent_coordsv},
×
920
                                { "deimos_special",    &get_deimos_parent_coordsv},
×
921
                                { "jupiter_special",   &get_jupiter_helio_coordsv},
×
922
                                { "io_special",        &get_io_parent_coordsv},
×
923
                                { "europa_special",    &get_europa_parent_coordsv},
×
924
                                { "ganymede_special",  &get_ganymede_parent_coordsv},
×
925
                                { "calisto_special",   &get_callisto_parent_coordsv},
×
926
                                { "callisto_special",  &get_callisto_parent_coordsv},
×
927
                                { "saturn_special",    &get_saturn_helio_coordsv},
×
928
                                { "mimas_special",     &get_mimas_parent_coordsv},
×
929
                                { "enceladus_special", &get_enceladus_parent_coordsv},
×
930
                                { "tethys_special",    &get_tethys_parent_coordsv},
×
931
                                { "dione_special",     &get_dione_parent_coordsv},
×
932
                                { "rhea_special",      &get_rhea_parent_coordsv},
×
933
                                { "titan_special",     &get_titan_parent_coordsv},
×
934
                                { "hyperion_special",  &get_hyperion_parent_coordsv},
×
935
                                { "iapetus_special",   &get_iapetus_parent_coordsv},
×
936
                                { "helene_special",    &get_helene_parent_coordsv},
×
937
                                { "telesto_special",   &get_telesto_parent_coordsv},
×
938
                                { "calypso_special",   &get_calypso_parent_coordsv},
×
939
                                { "uranus_special",    &get_uranus_helio_coordsv},
×
940
                                { "miranda_special",   &get_miranda_parent_coordsv},
×
941
                                { "ariel_special",     &get_ariel_parent_coordsv},
×
942
                                { "umbriel_special",   &get_umbriel_parent_coordsv},
×
943
                                { "titania_special",   &get_titania_parent_coordsv},
×
944
                                { "oberon_special",    &get_oberon_parent_coordsv},
×
945
                                { "neptune_special",   &get_neptune_helio_coordsv},
×
946
                                { "pluto_special",     &get_pluto_helio_coordsv}};
×
947
                        static const QMap<QString, OsculatingFunctType*>osculatingMap={
948
                                { "mercury_special",   &get_mercury_helio_osculating_coords},
×
949
                                { "venus_special",     &get_venus_helio_osculating_coords},
×
950
                                { "earth_special",     &get_earth_helio_osculating_coords},
×
951
                                { "mars_special",      &get_mars_helio_osculating_coords},
×
952
                                { "jupiter_special",   &get_jupiter_helio_osculating_coords},
×
953
                                { "saturn_special",    &get_saturn_helio_osculating_coords},
×
954
                                { "uranus_special",    &get_uranus_helio_osculating_coords},
×
955
                                { "neptune_special",   &get_neptune_helio_osculating_coords}};
×
956
                        posfunc=posfuncMap.value(coordFuncName, Q_NULLPTR);
×
957
                        osculatingFunc=osculatingMap.value(coordFuncName, Q_NULLPTR);
×
958
                }
959
                if (posfunc==Q_NULLPTR)
×
960
                {
961
                        qCritical() << "ERROR in section " << secname << ": can't find posfunc " << coordFuncName << " for " << englishName;
×
962
                        exit(-1);
×
963
                }
964

965
                // Create the Solar System body and add it to the list
966
                //TODO: Refactor the subclass selection to reduce duplicate code mess here,
967
                // by at least using this base class pointer and using setXXX functions instead of mega-constructors
968
                // that have to pass most of it on to the Planet class
969
                PlanetP newP;
×
970

971
                // New class objects, named "plutino", "cubewano", "dwarf planet", "SDO", "OCO", has properties
972
                // similar to asteroids and we should calculate their positions like for asteroids. Dwarf planets
973
                // have one exception: Pluto - as long as we use a special function for calculation of Pluto's orbit.
974
                if ((type == "asteroid" || type == "dwarf planet" || type == "cubewano" || type=="sednoid" || type == "plutino" || type == "scattered disc object" || type == "Oort cloud object" || type == "interstellar object") && !englishName.contains("Pluto"))
×
975
                {
976
                        minorBodies << englishName;
×
977

978
                        Vec3f color = Vec3f(1.f, 1.f, 1.f);
×
979
                        const double bV = pd.value(secname+"/color_index_bv", 99.).toDouble();
×
980
                        if (bV<99.)
×
981
                                color = skyDrawer->indexToColor(BvToColorIndex(bV))*0.75f; // see ZoneArray.cpp:L490
×
982
                        else
983
                                color = Vec3f(pd.value(secname+"/color", "1.0,1.0,1.0").toString());
×
984

985
                        const bool hidden = pd.value(secname+"/hidden", false).toBool();
×
986
                        const QString normalMapName = ( hidden ? "" : englishName.toLower().append("_normals.png")); // no normal maps for invisible objects!
×
987
                        const QString horizonMapName = ( hidden ? "" : englishName.toLower().append("_normals.png")); // no normal maps for invisible objects!
×
988

989
                        newP = PlanetP(new MinorPlanet(englishName,
×
990
                                                    pd.value(secname+"/radius", 1.0).toDouble()/AU,
×
991
                                                    pd.value(secname+"/oblateness", 0.0).toDouble(),
×
992
                                                    color, // halo color
993
                                                    pd.value(secname+"/albedo", 0.25f).toFloat(),
×
994
                                                    pd.value(secname+"/roughness",0.9f).toFloat(),
×
995
                                                    pd.value(secname+"/tex_map", "nomap.png").toString(),
×
996
                                                    pd.value(secname+"/normals_map", normalMapName).toString(),
×
997
                                                    pd.value(secname+"/horizon_map", horizonMapName).toString(),
×
998
                                                    pd.value(secname+"/model").toString(),
×
999
                                                    posfunc,
1000
                                                    static_cast<KeplerOrbit*>(orbitPtr), // the KeplerOrbit object created previously
1001
                                                    osculatingFunc, // should be Q_NULLPTR
1002
                                                    closeOrbit,
1003
                                                    hidden,
1004
                                                    type));
×
1005
                        QSharedPointer<MinorPlanet> mp =  newP.dynamicCast<MinorPlanet>();
×
1006
                        //Number, Provisional designation
1007
                        mp->setMinorPlanetNumber(pd.value(secname+"/minor_planet_number", 0).toInt());
×
1008
                        mp->setProvisionalDesignation(pd.value(secname+"/provisional_designation", "").toString());
×
1009

1010
                        //H-G magnitude system
1011
                        const float magnitude = pd.value(secname+"/absolute_magnitude", -99.f).toFloat();
×
1012
                        const float slope = pd.value(secname+"/slope_parameter", 0.15f).toFloat();
×
1013
                        if (magnitude > -99.f)
×
1014
                        {
1015
                                mp->setAbsoluteMagnitudeAndSlope(magnitude, qBound(0.0f, slope, 1.0f));
×
1016
                        }
1017

1018
                        mp->setColorIndexBV(static_cast<float>(bV));
×
1019
                        mp->setSpectralType(pd.value(secname+"/spec_t", "").toString(), pd.value(secname+"/spec_b", "").toString());
×
1020
                        if (semi_major_axis>0)
×
1021
                                mp->deltaJDE = 2.0*semi_major_axis*StelCore::JD_SECOND;
×
1022
                         else if ((semi_major_axis<=0.0) && (type!="interstellar object"))
×
1023
                                qWarning() << "WARNING: Minor Body" << englishName << "has no semimajor axis!";
×
1024

1025
                        systemMinorBodies.push_back(newP);
×
1026
                }
×
1027
                else if (type == "comet")
×
1028
                {
1029
                        minorBodies << englishName;
×
1030
                        newP = PlanetP(new Comet(englishName,
×
1031
                                              pd.value(secname+"/radius", 1.0).toDouble()/AU,
×
1032
                                              pd.value(secname+"/oblateness", 0.0).toDouble(),
×
1033
                                              Vec3f(pd.value(secname+"/color", "1.0,1.0,1.0").toString()), // halo color
×
1034
                                              pd.value(secname+"/albedo", 0.075f).toFloat(), // assume very dark surface
×
1035
                                              pd.value(secname+"/roughness",0.9f).toFloat(),
×
1036
                                              pd.value(secname+"/outgas_intensity",0.1f).toFloat(),
×
1037
                                              pd.value(secname+"/outgas_falloff", 0.1f).toFloat(),
×
1038
                                              pd.value(secname+"/tex_map", "nomap.png").toString(),
×
1039
                                              pd.value(secname+"/model").toString(),
×
1040
                                              posfunc,
1041
                                              static_cast<KeplerOrbit*>(orbitPtr), // the KeplerOrbit object
1042
                                              osculatingFunc, // ALWAYS NULL for comets.
1043
                                              closeOrbit,
1044
                                              pd.value(secname+"/hidden", false).toBool(),
×
1045
                                              type,
1046
                                              pd.value(secname+"/dust_widthfactor", 1.5f).toFloat(),
×
1047
                                              pd.value(secname+"/dust_lengthfactor", 0.4f).toFloat(),
×
1048
                                              pd.value(secname+"/dust_brightnessfactor", 1.5f).toFloat()
×
1049
                                              ));
×
1050
                        QSharedPointer<Comet> mp = newP.dynamicCast<Comet>();
×
1051

1052
                        //g,k magnitude system
1053
                        const float magnitude = pd.value(secname+"/absolute_magnitude", -99).toFloat();
×
1054
                        const float slope = qBound(-5.0f, pd.value(secname+"/slope_parameter", 4.0f).toFloat(), 30.0f);
×
1055
                        if (magnitude > -99)
×
1056
                        {
1057
                                        mp->setAbsoluteMagnitudeAndSlope(magnitude, slope);
×
1058
                        }
1059

1060
                        systemMinorBodies.push_back(newP);
×
1061
                }
×
1062
                else // type==star|planet|moon|dwarf planet|observer|artificial
1063
                {
1064
                        //qDebug() << type;
1065
                        Q_ASSERT(type=="star" || type=="planet" || type=="moon" || type=="artificial" || type=="observer" || type=="dwarf planet"); // TBD: remove Pluto...
×
1066
                        // Set possible default name of the normal map for avoiding yin-yang shaped moon
1067
                        // phase when normal map key not exists. Example: moon_normals.png
1068
                        // Details: https://bugs.launchpad.net/stellarium/+bug/1335609                        
1069
                        newP = PlanetP(new Planet(englishName,
×
1070
                                               pd.value(secname+"/radius", 1.0).toDouble()/AU,
×
1071
                                               pd.value(secname+"/oblateness", 0.0).toDouble(),
×
1072
                                               Vec3f(pd.value(secname+"/color", "1.0,1.0,1.0").toString()), // halo color
×
1073
                                               pd.value(secname+"/albedo", 0.25f).toFloat(),
×
1074
                                               pd.value(secname+"/roughness",0.9f).toFloat(),
×
1075
                                               pd.value(secname+"/tex_map", "nomap.png").toString(),
×
1076
                                               pd.value(secname+"/normals_map", englishName.toLower().append("_normals.png")).toString(),
×
1077
                                               pd.value(secname+"/horizon_map", englishName.toLower().append("_horizon.png")).toString(),
×
1078
                                               pd.value(secname+"/model").toString(),
×
1079
                                               posfunc,
1080
                                               static_cast<KeplerOrbit*>(orbitPtr), // This remains Q_NULLPTR for the major planets, or has a KeplerOrbit for planet moons.
1081
                                               osculatingFunc,
1082
                                               closeOrbit,
1083
                                               pd.value(secname+"/hidden", false).toBool(),
×
1084
                                               pd.value(secname+"/atmosphere", false).toBool(),
×
1085
                                               pd.value(secname+"/halo", true).toBool(),
×
1086
                                               type));
×
1087
                        newP->absoluteMagnitude = pd.value(secname+"/absolute_magnitude", -99.f).toFloat();
×
1088

1089
                        // Moon designation (planet index + IAU moon number)
1090
                        QString moonDesignation = pd.value(secname+"/iau_moon_number", "").toString();
×
1091
                        if (!moonDesignation.isEmpty())
×
1092
                        {
1093
                                newP->setIAUMoonNumber(moonDesignation);
×
1094
                        }
1095
                }
×
1096

1097
                if (!parent.isNull())
×
1098
                {
1099
                        parent->satellites.append(newP);
×
1100
                        newP->parent = parent;
×
1101
                }
1102
                if (secname=="earth") earth = newP;
×
1103
                if (secname=="sun") sun = newP;
×
1104
                if (secname=="moon") moon = newP;
×
1105

1106
                // At this point the orbit and object type (class Planet and subclasses) have been fixed.
1107
                // For many objects we have oriented spheroids with rotational parameters.
1108

1109
                // There are two ways of defining the axis orientation:
1110
                // obliquity and ascending node, which was used by Stellarium already before 2010 (based on Celestia?).
1111
                double rotObliquity = pd.value(secname+"/rot_obliquity",0.).toDouble()*(M_PI_180);
×
1112
                double rotAscNode = pd.value(secname+"/rot_equator_ascending_node",0.).toDouble()*(M_PI_180);
×
1113
                // rot_periode given in hours (from which rotPeriod in days),
1114
                // The default is useful for many moons in bound rotation
1115
                double rotPeriod=pd.value(secname+"/rot_periode", pd.value(secname+"/orbit_Period", 1.).toDouble()*24.).toDouble()/24.;
×
1116
                double rotOffset=pd.value(secname+"/rot_rotation_offset",0.).toDouble();
×
1117

1118
                // 0.21+: Use WGCCRE planet North pole data if available
1119
                // NB: N pole for J2000 epoch as defined by IAU (NOT right hand rotation rule)
1120
                // Define only basic motion. Use special functions for more complicated axes.
1121
                const double J2000NPoleRA  = pd.value(secname+"/rot_pole_ra",  0.).toDouble()*M_PI_180;
×
1122
                const double J2000NPoleRA1 = pd.value(secname+"/rot_pole_ra1", 0.).toDouble()*M_PI_180;
×
1123
                const double J2000NPoleDE  = pd.value(secname+"/rot_pole_de",  0.).toDouble()*M_PI_180;
×
1124
                const double J2000NPoleDE1 = pd.value(secname+"/rot_pole_de1", 0.).toDouble()*M_PI_180;
×
1125
                const double J2000NPoleW0  = pd.value(secname+"/rot_pole_w0",  0.).toDouble(); // [degrees]   Basically the same idea as rot_rotation_offset, but W!=rotAngle
×
1126
                const double J2000NPoleW1  = pd.value(secname+"/rot_pole_w1",  0.).toDouble(); // [degrees/d] Basically the same idea as 360/rot_periode
×
1127
                if (fabs(J2000NPoleW1) > 0.0) // Patch possibly old period value with a more modern value.
×
1128
                {
1129
                        // this is just another expression for rotational speed.
1130
                        rotPeriod=360.0/J2000NPoleW1;
×
1131
                }
1132

1133
                // IMPORTANT: For the planet moons with orbits relative to planets' equator plane,
1134
                // re-compute the important bits from the updated axis elements.
1135
                // Reactivated to re-establish Pluto/Charon lock #153
1136
                if((J2000NPoleRA!=0.) || (J2000NPoleDE!=0.))
×
1137
                {
1138
                        // If available, recompute obliquity and AscNode from the new data.
1139
                        // Solution since 0.16: Make this once for J2000.
1140
                        // Optional (future?): Repeat this block in Planet::computeTransMatrix() for planets with moving axes and update all Moons' KeplerOrbit if required.
1141
                        Vec3d J2000NPole;
×
1142
                        StelUtils::spheToRect(J2000NPoleRA,J2000NPoleDE,J2000NPole);
×
1143

1144
                        Vec3d vsop87Pole(StelCore::matJ2000ToVsop87.multiplyWithoutTranslation(J2000NPole));
×
1145

1146
                        double lon, lat;
1147
                        StelUtils::rectToSphe(&lon, &lat, vsop87Pole);
×
1148

1149
                        rotObliquity = (M_PI_2 - lat);
×
1150
                        rotAscNode = (lon + M_PI_2);
×
1151

1152
                        //qDebug() << englishName << ": Compare these values to the older data in ssystem_major";
1153
                        //qDebug() << "\tCalculated rotational obliquity: " << rotObliquity*180./M_PI;
1154
                        //qDebug() << "\tCalculated rotational ascending node: " << rotAscNode*180./M_PI;
1155

1156
                        if (J2000NPoleW0 >0)
×
1157
                        {
1158
                                // W0 is counted from the ascending node with ICRF, but rotOffset from orbital plane.
1159
                                // Try this assumption by just counting Offset=W0+90+RA0.
1160
                                rotOffset=J2000NPoleW0 + lon*M_180_PI;
×
1161
                                //qDebug() << "\tCalculated rotational period (days // hours): " << rotPeriod << "//" << rotPeriod*24.;
1162
                                //qDebug() << "\tRotational offset (degrees): " << rotOffset;
1163
                        }
1164
                }
1165
                newP->setRotationElements(
×
1166
                        englishName,
1167
                        rotPeriod,
1168
                        rotOffset,
1169
                        pd.value(secname+"/rot_epoch", J2000).toDouble(),
×
1170
                        rotObliquity,
1171
                        rotAscNode,
1172
                        J2000NPoleRA,
1173
                        J2000NPoleRA1,
1174
                        J2000NPoleDE,
1175
                        J2000NPoleDE1,
1176
                        J2000NPoleW0,
1177
                        J2000NPoleW1);
1178
                // orbit_Period or orbit_visualization_period given in days.
1179
                // Elliptical Kepler orbits (ecc<0.9) will replace whatever is given by a value computed on the fly.
1180
                newP->setSiderealPeriod(fabs(pd.value(secname+"/orbit_Period",
×
1181
                                                      pd.value(secname+"/orbit_visualization_period" )).toDouble()));
×
1182

1183
                if (pd.contains(secname+"/tex_ring")) {
×
1184
                        const float rMin = pd.value(secname+"/ring_inner_size").toFloat()/AUf;
×
1185
                        const float rMax = pd.value(secname+"/ring_outer_size").toFloat()/AUf;
×
1186
                        Ring *r = new Ring(rMin,rMax,pd.value(secname+"/tex_ring").toString());
×
1187
                        newP->setRings(r);
×
1188
                }
1189

1190
                systemPlanets.push_back(newP);
×
1191
                readOk++;
×
1192
        }
×
1193

1194
        if (systemPlanets.isEmpty())
×
1195
        {
1196
                qWarning() << "No Solar System objects loaded from" << QDir::toNativeSeparators(filePath);
×
1197
                return false;
×
1198
        }
1199
        else qDebug() << "SolarSystem has " << systemPlanets.count() << "entries.";
×
1200

1201
        // special case: load earth shadow texture
1202
        if (!Planet::texEarthShadow)
×
1203
                Planet::texEarthShadow = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/earth-shadow.png");
×
1204

1205
        // Also comets just have static textures.
1206
        if (!Comet::comaTexture)
×
1207
                Comet::comaTexture = StelApp::getInstance().getTextureManager().createTextureThread(StelFileMgr::getInstallationDir()+"/textures/cometComa.png", StelTexture::StelTextureParams(true, GL_LINEAR, GL_CLAMP_TO_EDGE));
×
1208
        //tail textures. We use paraboloid tail bodies, textured like a fisheye sphere, i.e. center=head. The texture should be something like a mottled star to give some structure.
1209
        if (!Comet::tailTexture)
×
1210
                Comet::tailTexture = StelApp::getInstance().getTextureManager().createTextureThread(StelFileMgr::getInstallationDir()+"/textures/cometTail.png", StelTexture::StelTextureParams(true, GL_LINEAR, GL_CLAMP_TO_EDGE));
×
1211

1212
        if (readOk>0)
×
1213
                qDebug() << "Loaded" << readOk << "Solar System bodies";
×
1214

1215
        return true;
×
1216
}
×
1217

1218
// Compute the position for every elements of the solar system.
1219
// The order is not important since the position is computed relatively to the mother body
1220
void SolarSystem::computePositions(double dateJDE, PlanetP observerPlanet)
×
1221
{
1222
        StelCore *core=StelApp::getInstance().getCore();
×
1223
        const bool withAberration=core->getUseAberration();
×
1224
        if (flagLightTravelTime) // switching off light time correction implies no aberration for the planets.
×
1225
        {
1226
                for (const auto& p : qAsConst(systemPlanets))
×
1227
                {
1228
                        p->computePosition(dateJDE, Vec3d(0.));
×
1229
                }
1230
                const Vec3d obsPosJDE=observerPlanet->getHeliocentricEclipticPos();
×
1231

1232
                // For higher accuracy, we now make two iterations of light time and aberration correction. In the final round, we also compute rotation data.
1233
                // May fix sub-arcsecond inaccuracies, and optionally apply aberration in the way described in Explanatory Supplement (2013), 7.55.
1234
                // For reasons unknown (See discussion in GH:#1626) we do not add anything for the Moon when observed from Earth!
1235
                // Presumably the used ephemerides already provide aberration-corrected positions for the Moon?
1236
                const Vec3d aberrationPushSpeed=observerPlanet->getHeliocentricEclipticVelocity() * core->getAberrationFactor();
×
1237
                for (const auto& p : qAsConst(systemPlanets))
×
1238
                {
1239
                        //p->setExtraInfoString(StelObject::DebugAid, "");
1240
                        const double lightTimeDays = (p->getHeliocentricEclipticPos()-obsPosJDE).norm() * (AU / (SPEED_OF_LIGHT * 86400.));
×
1241
                        Vec3d aberrationPush(0.);
×
1242
                        if (withAberration && (observerPlanet->englishName!="Earth" || p->englishName!="Moon"))
×
1243
                                aberrationPush=lightTimeDays*aberrationPushSpeed;
×
1244
                        p->computePosition(dateJDE-lightTimeDays, aberrationPush);
×
1245
                }
1246
                // Extra accuracy with another round. Not sure if useful. Maybe hide behind a new property flag?
1247
                for (const auto& p : qAsConst(systemPlanets))
×
1248
                {
1249
                        //p->setExtraInfoString(StelObject::DebugAid, "");
1250
                        const double lightTimeDays = (p->getHeliocentricEclipticPos()-obsPosJDE).norm() * (AU / (SPEED_OF_LIGHT * 86400.));
×
1251
                        Vec3d aberrationPush(0.);
×
1252
                        if (withAberration && (observerPlanet->englishName!="Earth" || p->englishName!="Moon"))
×
1253
                                aberrationPush=lightTimeDays*aberrationPushSpeed;
×
1254
                        // The next call may already do nothing if the time difference to the previous round is not large enough.
1255
                        p->computePosition(dateJDE-lightTimeDays, aberrationPush);
×
1256
//                        p->setExtraInfoString(StelObject::DebugAid, QString("LightTime %1d; obsSpeed %2/%3/%4 AU/d")
1257
//                                              .arg(QString::number(lightTimeDays, 'f', 3))
1258
//                                              .arg(QString::number(aberrationPushSpeed[0], 'f', 3))
1259
//                                              .arg(QString::number(aberrationPushSpeed[0], 'f', 3))
1260
//                                              .arg(QString::number(aberrationPushSpeed[0], 'f', 3)));
1261

1262
                        if      (p->englishName=="Moon")    RotationElements::updatePlanetCorrections(dateJDE-lightTimeDays, RotationElements::EarthMoon);
×
1263
                        else if (p->englishName=="Mars")    RotationElements::updatePlanetCorrections(dateJDE-lightTimeDays, RotationElements::Mars);
×
1264
                        else if (p->englishName=="Jupiter") RotationElements::updatePlanetCorrections(dateJDE-lightTimeDays, RotationElements::Jupiter);
×
1265
                        else if (p->englishName=="Saturn")  RotationElements::updatePlanetCorrections(dateJDE-lightTimeDays, RotationElements::Saturn);
×
1266
                        else if (p->englishName=="Uranus")  RotationElements::updatePlanetCorrections(dateJDE-lightTimeDays, RotationElements::Uranus);
×
1267
                        else if (p->englishName=="Neptune") RotationElements::updatePlanetCorrections(dateJDE-lightTimeDays, RotationElements::Neptune);
×
1268
                }
1269
        }
1270
        else
1271
        {
1272
                for (const auto& p : qAsConst(systemPlanets))
×
1273
                {
1274
                        p->setExtraInfoString(StelObject::DebugAid, "");
×
1275
                        p->computePosition(dateJDE, Vec3d(0.));
×
1276
                        if      (p->englishName=="Moon")    RotationElements::updatePlanetCorrections(dateJDE, RotationElements::EarthMoon);
×
1277
                        else if (p->englishName=="Mars")    RotationElements::updatePlanetCorrections(dateJDE, RotationElements::Mars);
×
1278
                        else if (p->englishName=="Jupiter") RotationElements::updatePlanetCorrections(dateJDE, RotationElements::Jupiter);
×
1279
                        else if (p->englishName=="Saturn")  RotationElements::updatePlanetCorrections(dateJDE, RotationElements::Saturn);
×
1280
                        else if (p->englishName=="Uranus")  RotationElements::updatePlanetCorrections(dateJDE, RotationElements::Uranus);
×
1281
                        else if (p->englishName=="Neptune") RotationElements::updatePlanetCorrections(dateJDE, RotationElements::Neptune);
×
1282
                }
1283
        }
1284
        computeTransMatrices(dateJDE, observerPlanet->getHeliocentricEclipticPos());
×
1285
}
×
1286

1287
// Compute the transformation matrix for every elements of the solar system.
1288
// The elements have to be ordered hierarchically, eg. it's important to compute earth before moon.
1289
void SolarSystem::computeTransMatrices(double dateJDE, const Vec3d& observerPos)
×
1290
{
1291
        const double dateJD=dateJDE - (StelApp::getInstance().getCore()->computeDeltaT(dateJDE))/86400.0;
×
1292

1293
        if (flagLightTravelTime)
×
1294
        {
1295
                for (const auto& p : qAsConst(systemPlanets))
×
1296
                {
1297
                        const double light_speed_correction = (p->getHeliocentricEclipticPos()-observerPos).norm() * (AU / (SPEED_OF_LIGHT * 86400));
×
1298
                        p->computeTransMatrix(dateJD-light_speed_correction, dateJDE-light_speed_correction);
×
1299
                }
1300
        }
1301
        else
1302
        {
1303
                for (const auto& p : qAsConst(systemPlanets))
×
1304
                {
1305
                        p->computeTransMatrix(dateJD, dateJDE);
×
1306
                }
1307
        }
1308
}
×
1309

1310
// And sort them from the furthest to the closest to the observer
1311
// NOTE: std::binary_function is deprecated in C++11 and removed in C++17
1312
struct biggerDistance : public StelUtils::binary_function<PlanetP, PlanetP, bool>
1313
{
1314
        bool operator()(PlanetP p1, PlanetP p2)
×
1315
        {
1316
                return p1->getDistance() > p2->getDistance();
×
1317
        }
1318
};
1319

1320
// Draw all the elements of the solar system
1321
// We are supposed to be in heliocentric coordinate
1322
void SolarSystem::draw(StelCore* core)
×
1323
{
1324
        // AstroCalcDialog
1325
        drawEphemerisItems(core);
×
1326

1327
        if (!flagShow)
×
1328
                return;
×
1329

1330
        // Compute each Planet distance to the observer
1331
        const Vec3d obsHelioPos = core->getObserverHeliocentricEclipticPos();
×
1332

1333
        for (const auto& p : qAsConst(systemPlanets))
×
1334
        {
1335
                p->computeDistance(obsHelioPos);
×
1336
        }
1337

1338
        // And sort them from the furthest to the closest
1339
        std::sort(systemPlanets.begin(),systemPlanets.end(),biggerDistance());
×
1340

1341
        if (trailFader.getInterstate()>0.0000001f)
×
1342
        {
1343
                StelPainter sPainter(core->getProjection2d());
×
1344
                const float ppx = static_cast<float>(sPainter.getProjector()->getDevicePixelsPerPixel());
×
1345
                allTrails->setOpacity(trailFader.getInterstate());
×
1346
                if (trailsThickness>1 || ppx>1.f)
×
1347
                        sPainter.setLineWidth(trailsThickness*ppx);
×
1348
                allTrails->draw(core, &sPainter);
×
1349
                if (trailsThickness>1 || ppx>1.f)
×
1350
                        sPainter.setLineWidth(1);
×
1351
        }
×
1352

1353
        // Make some voodoo to determine when labels should be displayed
1354
        const float sdLimitMag=static_cast<float>(core->getSkyDrawer()->getLimitMagnitude());
×
1355
        const float maxMagLabel = (sdLimitMag<5.f ? sdLimitMag :
×
1356
                        5.f+(sdLimitMag-5.f)*1.2f) +(static_cast<float>(labelsAmount)-3.f)*1.2f;
×
1357

1358
        // Draw the elements
1359
        for (const auto& p : qAsConst(systemPlanets))
×
1360
        {
1361
                if ( (p->getEnglishName() != "Sun") ||
×
1362
                                ((p->getEnglishName() == "Sun") && !(core->getSkyDrawer()->getFlagDrawSunAfterAtmosphere())))
×
1363
                        p->draw(core, maxMagLabel, planetNameFont);
×
1364
        }
1365

1366
        if (GETSTELMODULE(StelObjectMgr)->getFlagSelectedObjectPointer() && getFlagPointer())
×
1367
                drawPointer(core);
×
1368
}
1369

1370
void SolarSystem::drawEphemerisItems(const StelCore* core)
×
1371
{
1372
        if (flagShow || (!flagShow && getFlagEphemerisAlwaysOn()))
×
1373
        {
1374
                if (getFlagEphemerisMarkers())
×
1375
                        drawEphemerisMarkers(core);
×
1376
                if (getFlagEphemerisLine())
×
1377
                        drawEphemerisLine(core);
×
1378
        }
1379
}
×
1380

1381
Vec3f SolarSystem::getEphemerisMarkerColor(int index) const
×
1382
{
1383
        // Sync index with AstroCalcDialog::generateEphemeris(). If required, switch to using a QMap.
1384
        const QVector<Vec3f> colors={
1385
                ephemerisGenericMarkerColor,
1386
                ephemerisSecondaryMarkerColor,
1387
                ephemerisMercuryMarkerColor,
1388
                ephemerisVenusMarkerColor,
1389
                ephemerisMarsMarkerColor,
1390
                ephemerisJupiterMarkerColor,
1391
                ephemerisSaturnMarkerColor};
×
1392
        return colors.value(index, ephemerisGenericMarkerColor);
×
1393
}
×
1394

1395
void SolarSystem::drawEphemerisMarkers(const StelCore *core)
×
1396
{
1397
        const int fsize = AstroCalcDialog::EphemerisList.count();
×
1398
        if (fsize==0) return;
×
1399

1400
        StelProjectorP prj;
×
1401
        if (getFlagEphemerisHorizontalCoordinates())
×
1402
                prj = core->getProjection(StelCore::FrameAltAz, StelCore::RefractionOff);
×
1403
        else
1404
                prj = core->getProjection(StelCore::FrameJ2000);
×
1405
        StelPainter sPainter(prj);
×
1406

1407
        float size, shift, baseSize = 4.f;
×
1408
        const bool showDates = getFlagEphemerisDates();
×
1409
        const bool showMagnitudes = getFlagEphemerisMagnitudes();
×
1410
        const bool showSkippedData = getFlagEphemerisSkipData();
×
1411
        const bool skipMarkers = getFlagEphemerisSkipMarkers();
×
1412
        const int dataStep = getEphemerisDataStep();
×
1413
        const int sizeCoeff = getEphemerisLineThickness() - 1;
×
1414
        QString info = "";
×
1415
        Vec3d win;
×
1416
        Vec3f markerColor;
×
1417
        bool skipFlag = false;
×
1418

1419
        if (getFlagEphemerisLine() && getFlagEphemerisScaleMarkers())
×
1420
                baseSize = 3.f; // The line lies through center of marker
×
1421

1422
        for (int i =0; i < fsize; i++)
×
1423
        {
1424
                skipFlag = (((i + 1)%dataStep)!=1 && dataStep!=1);
×
1425

1426
                // Check visibility of pointer
1427
                if (!(sPainter.getProjector()->projectCheck(AstroCalcDialog::EphemerisList[i].coord, win)))
×
1428
                        continue;
×
1429

1430
                QString debugStr; // Used temporarily for development
×
1431
                const bool isComet=AstroCalcDialog::EphemerisList[i].isComet;
×
1432
                if (i == AstroCalcDialog::DisplayedPositionIndex)
×
1433
                {
1434
                        markerColor = getEphemerisSelectedMarkerColor();
×
1435
                        size = 6.f;
×
1436
                }
1437
                else
1438
                {
1439
                        markerColor = getEphemerisMarkerColor(AstroCalcDialog::EphemerisList[i].colorIndex);
×
1440
                        size = baseSize;
×
1441
                }
1442
                if (isComet) size += 16.f;
×
1443
                size += sizeCoeff;
×
1444
                sPainter.setColor(markerColor);
×
1445
                sPainter.setBlending(true, GL_ONE, GL_ONE);
×
1446
                if (isComet)
×
1447
                        texEphemerisCometMarker->bind();
×
1448
                else
1449
                        texEphemerisMarker->bind();
×
1450

1451
                if (skipMarkers && skipFlag)
×
1452
                        continue;
×
1453

1454
                Vec3f win;
×
1455
                float solarAngle=0.f; // Angle to possibly rotate the texture. Degrees.
×
1456
                if (prj->project(AstroCalcDialog::EphemerisList[i].coord, win))
×
1457
                {
1458
                        if (isComet)
×
1459
                        {
1460
                                // compute solarAngle in screen space.
1461
                                Vec3f sunWin;
×
1462
                                prj->project(AstroCalcDialog::EphemerisList[i].sunCoord, sunWin);
×
1463
                                // TODO: In some projections, we may need to test result and flip/mirror the angle, or deal with wrap-around effects.
1464
                                // E.g., in cylindrical mode, the comet icon will flip as soon as the corresponding sun position wraps around the screen edge.
1465
                                solarAngle=M_180_PIf*(atan2(-(win[1]-sunWin[1]), win[0]-sunWin[0]));
×
1466
                                // This will show projected positions and angles usable in labels.
1467
                                debugStr = QString("Sun: %1/%2 Obj: %3/%4 -->%5").arg(QString::number(sunWin[0]), QString::number(sunWin[1]), QString::number(win[0]), QString::number(win[1]), QString::number(solarAngle));
×
1468
                        }
1469
                        //sPainter.drawSprite2dMode(static_cast<float>(win[0]), static_cast<float>(win[1]), size, 180.f+AstroCalcDialog::EphemerisList[i].solarAngle*M_180_PIf);
1470
                        sPainter.drawSprite2dMode(static_cast<float>(win[0]), static_cast<float>(win[1]), size, 270.f-solarAngle);
×
1471
                }
1472

1473
                if (showDates || showMagnitudes)
×
1474
                {
1475
                        if (showSkippedData && skipFlag)
×
1476
                                continue;
×
1477

1478
                        shift = 3.f + size/1.6f;
×
1479
                        if (showDates && showMagnitudes)
×
1480
                                info = QString("%1 (%2)").arg(AstroCalcDialog::EphemerisList[i].objDateStr, QString::number(AstroCalcDialog::EphemerisList[i].magnitude, 'f', 2));
×
1481
                        if (showDates && !showMagnitudes)
×
1482
                                info = AstroCalcDialog::EphemerisList[i].objDateStr;
×
1483
                        if (!showDates && showMagnitudes)
×
1484
                                info = QString::number(AstroCalcDialog::EphemerisList[i].magnitude, 'f', 2);
×
1485

1486
                        // Activate for debug labels.
1487
                        //info=debugStr;
1488
                        sPainter.drawText(AstroCalcDialog::EphemerisList[i].coord, info, 0, shift, shift, false);
×
1489
                }
1490
        }
×
1491
}
×
1492

1493
void SolarSystem::drawEphemerisLine(const StelCore *core)
×
1494
{
1495
        const int size = AstroCalcDialog::EphemerisList.count();
×
1496
        if (size==0) return;
×
1497

1498
        // The array of data is not empty - good news!
1499
        StelProjectorP prj;
×
1500
        if (getFlagEphemerisHorizontalCoordinates())
×
1501
                prj = core->getProjection(StelCore::FrameAltAz, StelCore::RefractionOff);
×
1502
        else
1503
                prj = core->getProjection(StelCore::FrameJ2000);
×
1504
        StelPainter sPainter(prj);
×
1505
        const float ppx = static_cast<float>(sPainter.getProjector()->getDevicePixelsPerPixel());
×
1506

1507
        const float oldLineThickness=sPainter.getLineWidth();
×
1508
        const float lineThickness = getEphemerisLineThickness()*ppx;
×
1509
        if (!fuzzyEquals(lineThickness, oldLineThickness))
×
1510
                sPainter.setLineWidth(lineThickness);
×
1511

1512
        Vec3f color;
×
1513
        QVector<Vec3d> vertexArray;
×
1514
        QVector<Vec4f> colorArray;
×
1515
        const int limit = getEphemerisDataLimit();
×
1516
        const int nsize = static_cast<int>(size/limit);
×
1517
        vertexArray.resize(nsize);
×
1518
        colorArray.resize(nsize);
×
1519
        for (int j=0; j<limit; j++)
×
1520
        {
1521
                for (int i =0; i < nsize; i++)
×
1522
                {
1523
                        color = getEphemerisMarkerColor(AstroCalcDialog::EphemerisList[i + j*nsize].colorIndex);
×
1524
                        colorArray[i]=Vec4f(color, 1.0f);
×
1525
                        vertexArray[i]=AstroCalcDialog::EphemerisList[i + j*nsize].coord;
×
1526
                }
1527
                sPainter.drawPath(vertexArray, colorArray);
×
1528
        }
1529

1530
        if (!fuzzyEquals(lineThickness, oldLineThickness))
×
1531
                sPainter.setLineWidth(oldLineThickness); // restore line thickness
×
1532
}
×
1533

1534
void SolarSystem::fillEphemerisDates()
×
1535
{
1536
        const int fsize = AstroCalcDialog::EphemerisList.count();
×
1537
        if (fsize==0) return;
×
1538

1539
        StelLocaleMgr* localeMgr = &StelApp::getInstance().getLocaleMgr();
×
1540
        const bool showSmartDates = getFlagEphemerisSmartDates();
×
1541
        double JD = AstroCalcDialog::EphemerisList.first().objDate;
×
1542
        bool withTime = (fsize>1 && (AstroCalcDialog::EphemerisList[1].objDate-JD<1.0));
×
1543

1544
        int fYear, fMonth, fDay, sYear, sMonth, sDay, h, m, s;
1545
        QString info;
×
1546
        const double shift = StelApp::getInstance().getCore()->getUTCOffset(JD)*0.041666666666;
×
1547
        StelUtils::getDateFromJulianDay(JD+shift, &fYear, &fMonth, &fDay);
×
1548
        bool sFlag = true;
×
1549
        sYear = fYear;
×
1550
        sMonth = fMonth;
×
1551
        sDay = fDay;
×
1552
        const bool showSkippedData = getFlagEphemerisSkipData();
×
1553
        const int dataStep = getEphemerisDataStep();
×
1554

1555
        for (int i = 0; i < fsize; i++)
×
1556
        {
1557
                JD = AstroCalcDialog::EphemerisList[i].objDate;
×
1558
                StelUtils::getDateFromJulianDay(JD+shift, &fYear, &fMonth, &fDay);
×
1559

1560
                if (showSkippedData && ((i + 1)%dataStep)!=1 && dataStep!=1)
×
1561
                        continue;
×
1562

1563
                if (showSmartDates)
×
1564
                {
1565
                        if (sFlag)
×
1566
                                info = QString("%1").arg(fYear);
×
1567

1568
                        if (info.isEmpty() && !sFlag && fYear!=sYear)
×
1569
                                info = QString("%1").arg(fYear);
×
1570

1571
                        if (!info.isEmpty())
×
1572
                                info.append(QString("/%1").arg(localeMgr->romanMonthName(fMonth)));
×
1573
                        else if (fMonth!=sMonth)
×
1574
                                info = QString("%1").arg(localeMgr->romanMonthName(fMonth));
×
1575

1576
                        if (!info.isEmpty())
×
1577
                                info.append(QString("/%1").arg(fDay));
×
1578
                        else
1579
                                info = QString("%1").arg(fDay);
×
1580

1581
                        if (withTime) // very short step
×
1582
                        {
1583
                                if (fDay==sDay && !sFlag)
×
1584
                                        info.clear();
×
1585

1586
                                StelUtils::getTimeFromJulianDay(JD+shift, &h, &m, &s);
×
1587
                                if (!info.isEmpty())
×
1588
                                        info.append(QString(" %1:%2").arg(h).arg(m));
×
1589
                                else
1590
                                        info = QString("%1:%2").arg(h).arg(m);
×
1591
                        }
1592

1593
                        AstroCalcDialog::EphemerisList[i].objDateStr = info;
×
1594
                        info.clear();
×
1595
                        sYear = fYear;
×
1596
                        sMonth = fMonth;
×
1597
                        sDay = fDay;
×
1598
                        sFlag = false;
×
1599
                }
1600
                else
1601
                {
1602
                        // OK, let's use standard formats for date and time (as defined for whole planetarium)
1603
                        if (withTime)
×
1604
                                AstroCalcDialog::EphemerisList[i].objDateStr = QString("%1 %2").arg(localeMgr->getPrintableDateLocal(JD), localeMgr->getPrintableTimeLocal(JD));
×
1605
                        else
1606
                                AstroCalcDialog::EphemerisList[i].objDateStr = localeMgr->getPrintableDateLocal(JD);
×
1607
                }
1608
        }
1609
}
×
1610

1611
PlanetP SolarSystem::searchByEnglishName(QString planetEnglishName) const
×
1612
{
1613
        for (const auto& p : systemPlanets)
×
1614
        {
1615
                if (p->getEnglishName().toUpper() == planetEnglishName.toUpper() || p->getCommonEnglishName().toUpper() == planetEnglishName.toUpper())
×
1616
                        return p;
×
1617
        }
1618
        return PlanetP();
×
1619
}
1620

1621
PlanetP SolarSystem::searchMinorPlanetByEnglishName(QString planetEnglishName) const
×
1622
{
1623
        for (const auto& p : systemMinorBodies)
×
1624
        {
1625
                if (p->getCommonEnglishName().toUpper() == planetEnglishName.toUpper() || p->getEnglishName().toUpper() == planetEnglishName.toUpper())
×
1626
                        return p;
×
1627
        }
1628
        return PlanetP();
×
1629
}
1630

1631

1632
StelObjectP SolarSystem::searchByNameI18n(const QString& planetNameI18) const
×
1633
{
1634
        for (const auto& p : systemPlanets)
×
1635
        {
1636
                QString nativeName = p->getNativeNameI18n().toUpper();
×
1637
                if (p->getNameI18n().toUpper() == planetNameI18.toUpper() || (!nativeName.isEmpty() && nativeName == planetNameI18.toUpper()))
×
1638
                        return qSharedPointerCast<StelObject>(p);
×
1639
        }
×
1640
        return StelObjectP();
×
1641
}
1642

1643

1644
StelObjectP SolarSystem::searchByName(const QString& name) const
×
1645
{
1646
        for (const auto& p : systemPlanets)
×
1647
        {
1648
                QString nativeName = p->getNativeName().toUpper();
×
1649
                if (p->getEnglishName().toUpper() == name.toUpper() || (!nativeName.isEmpty() && nativeName == name.toUpper()))
×
1650
                        return qSharedPointerCast<StelObject>(p);
×
1651
        }
×
1652
        return StelObjectP();
×
1653
}
1654

1655
float SolarSystem::getPlanetVMagnitude(QString planetName, bool withExtinction) const
×
1656
{
1657
        PlanetP p = searchByEnglishName(planetName);
×
1658
        if (p.isNull()) // Possible was asked the common name of minor planet?
×
1659
                p = searchMinorPlanetByEnglishName(planetName);
×
1660
        float r = 0.f;
×
1661
        if (withExtinction)
×
1662
                r = p->getVMagnitudeWithExtinction(StelApp::getInstance().getCore());
×
1663
        else
1664
                r = p->getVMagnitude(StelApp::getInstance().getCore());
×
1665
        return r;
×
1666
}
×
1667

1668
QString SolarSystem::getPlanetType(QString planetName) const
×
1669
{
1670
        PlanetP p = searchByEnglishName(planetName);
×
1671
        if (p.isNull()) // Possible was asked the common name of minor planet?
×
1672
                p = searchMinorPlanetByEnglishName(planetName);
×
1673
        if (p.isNull())
×
1674
                return QString("UNDEFINED");
×
1675
        return p->getPlanetTypeString();
×
1676
}
×
1677

1678
double SolarSystem::getDistanceToPlanet(QString planetName) const
×
1679
{
1680
        PlanetP p = searchByEnglishName(planetName);
×
1681
        if (p.isNull()) // Possible was asked the common name of minor planet?
×
1682
                p = searchMinorPlanetByEnglishName(planetName);
×
1683
        return p->getDistance();
×
1684
}
×
1685

1686
double SolarSystem::getElongationForPlanet(QString planetName) const
×
1687
{
1688
        PlanetP p = searchByEnglishName(planetName);
×
1689
        if (p.isNull()) // Possible was asked the common name of minor planet?
×
1690
                p = searchMinorPlanetByEnglishName(planetName);
×
1691
        return p->getElongation(StelApp::getInstance().getCore()->getObserverHeliocentricEclipticPos());
×
1692
}
×
1693

1694
double SolarSystem::getPhaseAngleForPlanet(QString planetName) const
×
1695
{
1696
        PlanetP p = searchByEnglishName(planetName);
×
1697
        if (p.isNull()) // Possible was asked the common name of minor planet?
×
1698
                p = searchMinorPlanetByEnglishName(planetName);
×
1699
        return p->getPhaseAngle(StelApp::getInstance().getCore()->getObserverHeliocentricEclipticPos());
×
1700
}
×
1701

1702
float SolarSystem::getPhaseForPlanet(QString planetName) const
×
1703
{
1704
        PlanetP p = searchByEnglishName(planetName);
×
1705
        if (p.isNull()) // Possible was asked the common name of minor planet?
×
1706
                p = searchMinorPlanetByEnglishName(planetName);
×
1707
        return p->getPhase(StelApp::getInstance().getCore()->getObserverHeliocentricEclipticPos());
×
1708
}
×
1709

1710
QStringList SolarSystem::getObjectsList(QString objType) const
×
1711
{
1712
        QStringList r;
×
1713
        if (objType.toLower()=="all")
×
1714
        {
1715
                r = listAllObjects(true);
×
1716
                // Remove the Sun
1717
                r.removeOne("Sun");
×
1718
                // Remove special objects
1719
                r.removeOne("Solar System Observer");
×
1720
                r.removeOne("Earth Observer");
×
1721
                r.removeOne("Mars Observer");
×
1722
                r.removeOne("Jupiter Observer");
×
1723
                r.removeOne("Saturn Observer");
×
1724
                r.removeOne("Uranus Observer");
×
1725
                r.removeOne("Neptune Observer");
×
1726
        }
1727
        else
1728
                r = listAllObjectsByType(objType, true);
×
1729

1730
        return r;
×
1731
}
×
1732

1733
// Search if any Planet is close to position given in earth equatorial position and return the distance
1734
StelObjectP SolarSystem::search(Vec3d pos, const StelCore* core) const
×
1735
{
1736
        pos.normalize();
×
1737
        PlanetP closest;
×
1738
        double cos_angle_closest = 0.;
×
1739
        Vec3d equPos;
×
1740

1741
        for (const auto& p : systemPlanets)
×
1742
        {
1743
                equPos = p->getEquinoxEquatorialPos(core);
×
1744
                equPos.normalize();
×
1745
                double cos_ang_dist = equPos*pos;
×
1746
                if (cos_ang_dist>cos_angle_closest)
×
1747
                {
1748
                        closest = p;
×
1749
                        cos_angle_closest = cos_ang_dist;
×
1750
                }
1751
        }
1752

1753
        if (cos_angle_closest>0.999)
×
1754
        {
1755
                return qSharedPointerCast<StelObject>(closest);
×
1756
        }
1757
        else return StelObjectP();
×
1758
}
×
1759

1760
// Return a QList containing the planets located inside the limFov circle around position vv
1761
QList<StelObjectP> SolarSystem::searchAround(const Vec3d& vv, double limitFov, const StelCore* core) const
×
1762
{
1763
        QList<StelObjectP> result;
×
1764
        if (!getFlagPlanets())
×
1765
                return result;
×
1766

1767
        const bool withAberration=core->getUseAberration();
×
1768
        Vec3d v(vv);
×
1769
        v.normalize(); // TODO: start with vv already normalized?
×
1770
        if (withAberration)
×
1771
        {
1772
                Vec3d vel=core->getCurrentPlanet()->getHeliocentricEclipticVelocity();
×
1773
                StelCore::matVsop87ToJ2000.transfo(vel);
×
1774
                vel*=core->getAberrationFactor()*(AU/(86400.0*SPEED_OF_LIGHT));
×
1775
                v+=vel;
×
1776
                v.normalize();
×
1777
        }
1778

1779
        double cosLimFov = std::cos(limitFov * M_PI/180.);
×
1780
        Vec3d equPos;
×
1781
        double cosAngularSize;
1782

1783
        const QString weAreHere = core->getCurrentPlanet()->getEnglishName();
×
1784
        for (const auto& p : systemPlanets)
×
1785
        {
1786
                equPos = p->getJ2000EquatorialPos(core);
×
1787
                equPos.normalize();
×
1788

1789
                cosAngularSize = std::cos(p->getSpheroidAngularRadius(core) * M_PI/180.);
×
1790

1791
                if (equPos*v>=std::min(cosLimFov, cosAngularSize) && p->getEnglishName()!=weAreHere)
×
1792
                {
1793
                        result.append(qSharedPointerCast<StelObject>(p));
×
1794
                }
1795
        }
1796
        return result;
×
1797
}
×
1798

1799
// Update i18 names from english names according to current sky culture translator
1800
void SolarSystem::updateI18n()
×
1801
{
1802
        const StelTranslator& trans = StelApp::getInstance().getLocaleMgr().getSkyTranslator();
×
1803
        for (const auto& p : qAsConst(systemPlanets))
×
1804
                p->translateName(trans);
×
1805
}
×
1806

1807
QStringList SolarSystem::listMatchingObjects(const QString& objPrefix, int maxNbItem, bool useStartOfWords) const
×
1808
{
1809
        QStringList result;
×
1810
        if (getFlagPlanets())
×
1811
                result = StelObjectModule::listMatchingObjects(objPrefix, maxNbItem, useStartOfWords);
×
1812
        return result;
×
1813
}
×
1814

1815
void SolarSystem::setFlagTrails(bool b)
×
1816
{
1817
        if (getFlagTrails() != b)
×
1818
        {
1819
                trailFader = b;
×
1820
                if (b)
×
1821
                {
1822
                        allTrails->reset(maxTrailPoints);
×
1823
                        recreateTrails();
×
1824
                }
1825
                emit trailsDisplayedChanged(b);
×
1826
        }
1827
}
×
1828

1829
bool SolarSystem::getFlagTrails() const
×
1830
{
1831
        return static_cast<bool>(trailFader);
×
1832
}
1833

1834
void SolarSystem::setMaxTrailPoints(int max)
×
1835
{
1836
        if (maxTrailPoints != max)
×
1837
        {
1838
                maxTrailPoints = max;
×
1839
                allTrails->reset(max);
×
1840
                recreateTrails();
×
1841
                emit maxTrailPointsChanged(max);
×
1842
        }
1843
}
×
1844

1845
void SolarSystem::setMaxTrailTimeExtent(int max)
×
1846
{
1847
        if (maxTrailTimeExtent != max && maxTrailTimeExtent > 0)
×
1848
        {
1849
                maxTrailTimeExtent = max;
×
1850
                recreateTrails();
×
1851
                emit maxTrailTimeExtentChanged(max);
×
1852
        }
1853
}
×
1854

1855
void SolarSystem::setTrailsThickness(int v)
×
1856
{
1857
        if (trailsThickness != v)
×
1858
        {
1859
                trailsThickness = v;
×
1860
                emit trailsThicknessChanged(v);
×
1861
        }
1862
}
×
1863

1864
void SolarSystem::setFlagHints(bool b)
×
1865
{
1866
        if (getFlagHints() != b)
×
1867
        {
1868
                for (const auto& p : qAsConst(systemPlanets))
×
1869
                        p->setFlagHints(b);
×
1870
                emit flagHintsChanged(b);
×
1871
        }
1872
}
×
1873

1874
bool SolarSystem::getFlagHints(void) const
×
1875
{
1876
        for (const auto& p : systemPlanets)
×
1877
        {
1878
                if (p->getFlagHints())
×
1879
                        return true;
×
1880
        }
1881
        return false;
×
1882
}
1883

1884
void SolarSystem::setFlagLabels(bool b)
×
1885
{
1886
        if (getFlagLabels() != b)
×
1887
        {
1888
                for (const auto& p : qAsConst(systemPlanets))
×
1889
                        p->setFlagLabels(b);
×
1890
                emit labelsDisplayedChanged(b);
×
1891
        }
1892
}
×
1893

1894
bool SolarSystem::getFlagLabels() const
×
1895
{
1896
        for (const auto& p : systemPlanets)
×
1897
        {
1898
                if (p->getFlagLabels())
×
1899
                        return true;
×
1900
        }
1901
        return false;
×
1902
}
1903

1904
void SolarSystem::setFlagOrbits(bool b)
×
1905
{
1906
        bool old = flagOrbits;
×
1907
        flagOrbits = b;
×
1908
        bool flagPlanetsOnly = getFlagPlanetsOrbitsOnly();
×
1909
        if (!b || !selected || selected==sun)
×
1910
        {
1911
                if (flagPlanetsOnly)
×
1912
                {
1913
                        for (const auto& p : qAsConst(systemPlanets))
×
1914
                        {
1915
                                if (p->getPlanetType()==Planet::isPlanet)
×
1916
                                        p->setFlagOrbits(b);
×
1917
                                else
1918
                                        p->setFlagOrbits(false);
×
1919
                        }
1920
                }
1921
                else
1922
                {
1923
                        for (const auto& p : qAsConst(systemPlanets))
×
1924
                                p->setFlagOrbits(b);
×
1925
                }
1926
        }
1927
        else if (getFlagIsolatedOrbits()) // If a Planet is selected and orbits are on, fade out non-selected ones
×
1928
        {
1929
                if (flagPlanetsOnly)
×
1930
                {
1931
                        for (const auto& p : qAsConst(systemPlanets))
×
1932
                        {
1933
                                if (selected == p && p->getPlanetType()==Planet::isPlanet)
×
1934
                                        p->setFlagOrbits(b);
×
1935
                                else
1936
                                        p->setFlagOrbits(false);
×
1937
                        }
1938
                }
1939
                else
1940
                {
1941
                        for (const auto& p : qAsConst(systemPlanets))
×
1942
                        {
1943
                                if (selected == p)
×
1944
                                        p->setFlagOrbits(b);
×
1945
                                else
1946
                                        p->setFlagOrbits(false);
×
1947
                        }
1948
                }
1949
        }
1950
        else
1951
        {
1952
                // A planet is selected and orbits are on - draw orbits for the planet and their moons
1953
                for (const auto& p : qAsConst(systemPlanets))
×
1954
                {
1955
                        if (selected == p || selected == p->parent)
×
1956
                                p->setFlagOrbits(b);
×
1957
                        else
1958
                                p->setFlagOrbits(false);
×
1959
                }
1960
        }
1961
        if(old != flagOrbits)
×
1962
                emit flagOrbitsChanged(flagOrbits);
×
1963
}
×
1964

1965
void SolarSystem::setFlagLightTravelTime(bool b)
×
1966
{
1967
        if(b!=flagLightTravelTime)
×
1968
        {
1969
                flagLightTravelTime = b;
×
1970
                emit flagLightTravelTimeChanged(b);
×
1971
        }
1972
}
×
1973

1974
void SolarSystem::setFlagShowObjSelfShadows(bool b)
×
1975
{
1976
        if(b!=flagShowObjSelfShadows)
×
1977
        {
1978
                flagShowObjSelfShadows = b;
×
1979
                if(!b)
×
1980
                        Planet::deinitFBO();
×
1981
                emit flagShowObjSelfShadowsChanged(b);
×
1982
        }
1983
}
×
1984

1985
void SolarSystem::setSelected(PlanetP obj)
×
1986
{
1987
        if (obj && obj->getType() == "Planet")
×
1988
        {
1989
                selected = obj;
×
1990
                selectedSSO.push_back(obj);
×
1991
        }
1992
        else
1993
                selected.clear();
×
1994
        // Undraw other objects hints, orbit, trails etc..
1995
        setFlagHints(getFlagHints());
×
1996
        setFlagOrbits(getFlagOrbits());
×
1997
}
×
1998

1999

2000
void SolarSystem::update(double deltaTime)
×
2001
{
2002
        trailFader.update(static_cast<int>(deltaTime*1000));
×
2003
        if (trailFader.getInterstate()>0.f)
×
2004
        {
2005
                allTrails->update();
×
2006
        }
2007

2008
        for (const auto& p : qAsConst(systemPlanets))
×
2009
        {
2010
                p->update(static_cast<int>(deltaTime*1000));
×
2011
        }
2012
}
×
2013

2014
// is a lunar eclipse close at hand?
2015
bool SolarSystem::nearLunarEclipse() const
×
2016
{
2017
        // TODO: could replace with simpler test
2018
        // TODO Source?
2019

2020
        const Vec3d sun = getSun()->getAberrationPush();
×
2021
        const Vec3d e = getEarth()->getEclipticPos();
×
2022
        const Vec3d m = getMoon()->getEclipticPos();  // relative to earth
×
2023
        const Vec3d mh = getMoon()->getHeliocentricEclipticPos();  // relative to sun
×
2024

2025
        // shadow location at earth + moon distance along earth vector from (aberrated) sun
2026
        Vec3d en = e-sun;
×
2027
        en.normalize();
×
2028
        Vec3d shadow = en * (e.norm() + m.norm());
×
2029

2030
        // find shadow radii in AU
2031
        double r_penumbra = shadow.norm()*702378.1/AU/e.norm() - SUN_RADIUS/AU;
×
2032

2033
        // modify shadow location for scaled moon
2034
        Vec3d mdist = shadow - mh;
×
2035
        if(mdist.norm() > r_penumbra + 2000./AU) return false;   // not visible so don't bother drawing
×
2036

2037
        return true;
×
2038
}
2039

2040
QStringList SolarSystem::listAllObjects(bool inEnglish) const
×
2041
{
2042
        QStringList result;
×
2043
        if (inEnglish)
×
2044
        {
2045
                for (const auto& p : systemPlanets)
×
2046
                {
2047
                        result << p->getEnglishName();
×
2048
                }
2049
        }
2050
        else
2051
        {
2052
                for (const auto& p : systemPlanets)
×
2053
                {
2054
                        result << p->getNameI18n();
×
2055
                        if (!p->getNativeNameI18n().isEmpty())
×
2056
                                result << p->getNativeNameI18n() << p->getNativeName();
×
2057
                }
2058
        }
2059
        return result;
×
2060
}
×
2061

2062
QStringList SolarSystem::listAllObjectsByType(const QString &objType, bool inEnglish) const
×
2063
{
2064
        QStringList result;
×
2065
        if (inEnglish)
×
2066
        {
2067
                for (const auto& p : systemPlanets)
×
2068
                {
2069
                        if (p->getPlanetTypeString()==objType)
×
2070
                                result << p->getEnglishName();
×
2071
                }
2072
        }
2073
        else
2074
        {
2075
                for (const auto& p : systemPlanets)
×
2076
                {
2077
                        if (p->getPlanetTypeString()==objType)
×
2078
                                result << p->getNameI18n();
×
2079
                }
2080
        }
2081
        return result;
×
2082
}
×
2083

2084
void SolarSystem::selectedObjectChange(StelModule::StelModuleSelectAction)
×
2085
{
2086
        const QList<StelObjectP> newSelected = GETSTELMODULE(StelObjectMgr)->getSelectedObject("Planet");
×
2087
        if (!newSelected.empty())
×
2088
        {
2089
                setSelected(qSharedPointerCast<Planet>(newSelected[0]));
×
2090
                if (getFlagIsolatedTrails())
×
2091
                        recreateTrails();
×
2092
        }
2093
        else
2094
                setSelected("");
×
2095
}
×
2096

2097
// Activate/Deactivate planets display
2098
void SolarSystem::setFlagPlanets(bool b)
×
2099
{
2100
        if (b!=flagShow)
×
2101
        {
2102
                flagShow=b;
×
2103
                emit flagPlanetsDisplayedChanged(b);
×
2104
        }
2105
}
×
2106

2107
bool SolarSystem::getFlagPlanets(void) const
×
2108
{
2109
        return flagShow;
×
2110
}
2111

2112
void SolarSystem::setFlagEphemerisMarkers(bool b)
×
2113
{
2114
        if (b!=ephemerisMarkersDisplayed)
×
2115
        {
2116
                ephemerisMarkersDisplayed=b;
×
2117
                conf->setValue("astrocalc/flag_ephemeris_markers", b); // Immediate saving of state
×
2118
                emit ephemerisMarkersChanged(b);
×
2119
        }
2120
}
×
2121

2122
bool SolarSystem::getFlagEphemerisMarkers() const
×
2123
{
2124
        return ephemerisMarkersDisplayed;
×
2125
}
2126

2127
void SolarSystem::setFlagEphemerisLine(bool b)
×
2128
{
2129
        if (b!=ephemerisLineDisplayed)
×
2130
        {
2131
                ephemerisLineDisplayed=b;
×
2132
                conf->setValue("astrocalc/flag_ephemeris_line", b); // Immediate saving of state
×
2133
                emit ephemerisLineChanged(b);
×
2134
        }
2135
}
×
2136

2137
bool SolarSystem::getFlagEphemerisLine() const
×
2138
{
2139
        return ephemerisLineDisplayed;
×
2140
}
2141

2142
bool SolarSystem::getFlagEphemerisAlwaysOn() const
×
2143
{
2144
        return ephemerisAlwaysOn;
×
2145
}
2146

2147
void SolarSystem::setFlagEphemerisAlwaysOn(bool b)
×
2148
{
2149
        if (b != ephemerisAlwaysOn)
×
2150
        {
2151
                ephemerisAlwaysOn = b;
×
2152
                conf->setValue("astrocalc/flag_ephemeris_alwayson", b); // Immediate saving of state
×
2153
                emit ephemerisAlwaysOnChanged(b);
×
2154
        }
2155
}
×
2156

2157
void SolarSystem::setFlagEphemerisHorizontalCoordinates(bool b)
×
2158
{
2159
        if (b!=ephemerisHorizontalCoordinates)
×
2160
        {
2161
                ephemerisHorizontalCoordinates=b;
×
2162
                conf->setValue("astrocalc/flag_ephemeris_horizontal", b); // Immediate saving of state
×
2163
                emit ephemerisHorizontalCoordinatesChanged(b);
×
2164
        }
2165
}
×
2166

2167
bool SolarSystem::getFlagEphemerisHorizontalCoordinates() const
×
2168
{
2169
        return ephemerisHorizontalCoordinates;
×
2170
}
2171

2172
void SolarSystem::setFlagEphemerisDates(bool b)
×
2173
{
2174
        if (b!=ephemerisDatesDisplayed)
×
2175
        {
2176
                ephemerisDatesDisplayed=b;
×
2177
                conf->setValue("astrocalc/flag_ephemeris_dates", b); // Immediate saving of state
×
2178
                emit ephemerisDatesChanged(b);
×
2179
        }
2180
}
×
2181

2182
bool SolarSystem::getFlagEphemerisDates() const
×
2183
{
2184
        return ephemerisDatesDisplayed;
×
2185
}
2186

2187
void SolarSystem::setFlagEphemerisMagnitudes(bool b)
×
2188
{
2189
        if (b!=ephemerisMagnitudesDisplayed)
×
2190
        {
2191
                ephemerisMagnitudesDisplayed=b;
×
2192
                conf->setValue("astrocalc/flag_ephemeris_magnitudes", b); // Immediate saving of state
×
2193
                emit ephemerisMagnitudesChanged(b);
×
2194
        }
2195
}
×
2196

2197
bool SolarSystem::getFlagEphemerisMagnitudes() const
×
2198
{
2199
        return ephemerisMagnitudesDisplayed;
×
2200
}
2201

2202
void SolarSystem::setFlagEphemerisSkipData(bool b)
×
2203
{
2204
        if (b!=ephemerisSkipDataDisplayed)
×
2205
        {
2206
                ephemerisSkipDataDisplayed=b;
×
2207
                conf->setValue("astrocalc/flag_ephemeris_skip_data", b); // Immediate saving of state
×
2208
                emit ephemerisSkipDataChanged(b);
×
2209
        }
2210
}
×
2211

2212
bool SolarSystem::getFlagEphemerisSkipData() const
×
2213
{
2214
        return ephemerisSkipDataDisplayed;
×
2215
}
2216

2217
void SolarSystem::setFlagEphemerisSkipMarkers(bool b)
×
2218
{
2219
        if (b!=ephemerisSkipMarkersDisplayed)
×
2220
        {
2221
                ephemerisSkipMarkersDisplayed=b;
×
2222
                conf->setValue("astrocalc/flag_ephemeris_skip_markers", b); // Immediate saving of state
×
2223
                emit ephemerisSkipMarkersChanged(b);
×
2224
        }
2225
}
×
2226

2227
bool SolarSystem::getFlagEphemerisSkipMarkers() const
×
2228
{
2229
        return ephemerisSkipMarkersDisplayed;
×
2230
}
2231

2232
void SolarSystem::setFlagEphemerisSmartDates(bool b)
×
2233
{
2234
        if (b!=ephemerisSmartDatesDisplayed)
×
2235
        {
2236
                ephemerisSmartDatesDisplayed=b;
×
2237
                conf->setValue("astrocalc/flag_ephemeris_smart_dates", b); // Immediate saving of state
×
2238
                emit ephemerisSmartDatesChanged(b);
×
2239
        }
2240
}
×
2241

2242
bool SolarSystem::getFlagEphemerisSmartDates() const
×
2243
{
2244
        return ephemerisSmartDatesDisplayed;
×
2245
}
2246

2247
void SolarSystem::setFlagEphemerisScaleMarkers(bool b)
×
2248
{
2249
        if (b!=ephemerisScaleMarkersDisplayed)
×
2250
        {
2251
                ephemerisScaleMarkersDisplayed=b;
×
2252
                conf->setValue("astrocalc/flag_ephemeris_scale_markers", b); // Immediate saving of state
×
2253
                emit ephemerisScaleMarkersChanged(b);
×
2254
        }
2255
}
×
2256

2257
bool SolarSystem::getFlagEphemerisScaleMarkers() const
×
2258
{
2259
        return ephemerisScaleMarkersDisplayed;
×
2260
}
2261

2262
void SolarSystem::setEphemerisDataStep(int step)
×
2263
{
2264
        ephemerisDataStep = step;
×
2265
        // automatic saving of the setting
2266
        conf->setValue("astrocalc/ephemeris_data_step", step);
×
2267
        emit ephemerisDataStepChanged(step);
×
2268
}
×
2269

2270
int SolarSystem::getEphemerisDataStep() const
×
2271
{
2272
        return ephemerisDataStep;
×
2273
}
2274

2275
void SolarSystem::setEphemerisDataLimit(int limit)
×
2276
{
2277
        ephemerisDataLimit = limit;
×
2278
        emit ephemerisDataLimitChanged(limit);
×
2279
}
×
2280

2281
int SolarSystem::getEphemerisDataLimit() const
×
2282
{
2283
        return ephemerisDataLimit;
×
2284
}
2285

2286
void SolarSystem::setEphemerisLineThickness(int v)
×
2287
{
2288
        ephemerisLineThickness = v;
×
2289
        // automatic saving of the setting
2290
        conf->setValue("astrocalc/ephemeris_line_thickness", v);
×
2291
        emit ephemerisLineThicknessChanged(v);
×
2292
}
×
2293

2294
int SolarSystem::getEphemerisLineThickness() const
×
2295
{
2296
        return ephemerisLineThickness;
×
2297
}
2298

2299
void SolarSystem::setEphemerisGenericMarkerColor(const Vec3f& color)
×
2300
{
2301
        if (color!=ephemerisGenericMarkerColor)
×
2302
        {
2303
                ephemerisGenericMarkerColor = color;
×
2304
                emit ephemerisGenericMarkerColorChanged(color);
×
2305
        }
2306
}
×
2307

2308
Vec3f SolarSystem::getEphemerisGenericMarkerColor() const
×
2309
{
2310
        return ephemerisGenericMarkerColor;
×
2311
}
2312

2313
void SolarSystem::setEphemerisSecondaryMarkerColor(const Vec3f& color)
×
2314
{
2315
        if (color!=ephemerisSecondaryMarkerColor)
×
2316
        {
2317
                ephemerisSecondaryMarkerColor = color;
×
2318
                emit ephemerisSecondaryMarkerColorChanged(color);
×
2319
        }
2320
}
×
2321

2322
Vec3f SolarSystem::getEphemerisSecondaryMarkerColor() const
×
2323
{
2324
        return ephemerisSecondaryMarkerColor;
×
2325
}
2326

2327
void SolarSystem::setEphemerisSelectedMarkerColor(const Vec3f& color)
×
2328
{
2329
        if (color!=ephemerisSelectedMarkerColor)
×
2330
        {
2331
                ephemerisSelectedMarkerColor = color;
×
2332
                emit ephemerisSelectedMarkerColorChanged(color);
×
2333
        }
2334
}
×
2335

2336
Vec3f SolarSystem::getEphemerisSelectedMarkerColor() const
×
2337
{
2338
        return ephemerisSelectedMarkerColor;
×
2339
}
2340

2341
void SolarSystem::setEphemerisMercuryMarkerColor(const Vec3f& color)
×
2342
{
2343
        if (color!=ephemerisMercuryMarkerColor)
×
2344
        {
2345
                ephemerisMercuryMarkerColor = color;
×
2346
                emit ephemerisMercuryMarkerColorChanged(color);
×
2347
        }
2348
}
×
2349

2350
Vec3f SolarSystem::getEphemerisMercuryMarkerColor() const
×
2351
{
2352
        return ephemerisMercuryMarkerColor;
×
2353
}
2354

2355
void SolarSystem::setEphemerisVenusMarkerColor(const Vec3f& color)
×
2356
{
2357
        if (color!=ephemerisVenusMarkerColor)
×
2358
        {
2359
                ephemerisVenusMarkerColor = color;
×
2360
                emit ephemerisVenusMarkerColorChanged(color);
×
2361
        }
2362
}
×
2363

2364
Vec3f SolarSystem::getEphemerisVenusMarkerColor() const
×
2365
{
2366
        return ephemerisVenusMarkerColor;
×
2367
}
2368

2369
void SolarSystem::setEphemerisMarsMarkerColor(const Vec3f& color)
×
2370
{
2371
        if (color!=ephemerisMarsMarkerColor)
×
2372
        {
2373
                ephemerisMarsMarkerColor = color;
×
2374
                emit ephemerisMarsMarkerColorChanged(color);
×
2375
        }
2376
}
×
2377

2378
Vec3f SolarSystem::getEphemerisMarsMarkerColor() const
×
2379
{
2380
        return ephemerisMarsMarkerColor;
×
2381
}
2382

2383
void SolarSystem::setEphemerisJupiterMarkerColor(const Vec3f& color)
×
2384
{
2385
        if (color!=ephemerisJupiterMarkerColor)
×
2386
        {
2387
                ephemerisJupiterMarkerColor = color;
×
2388
                emit ephemerisJupiterMarkerColorChanged(color);
×
2389
        }
2390
}
×
2391

2392
Vec3f SolarSystem::getEphemerisJupiterMarkerColor() const
×
2393
{
2394
        return ephemerisJupiterMarkerColor;
×
2395
}
2396

2397
void SolarSystem::setEphemerisSaturnMarkerColor(const Vec3f& color)
×
2398
{
2399
        if (color!=ephemerisSaturnMarkerColor)
×
2400
        {
2401
                ephemerisSaturnMarkerColor = color;
×
2402
                emit ephemerisSaturnMarkerColorChanged(color);
×
2403
        }
2404
}
×
2405

2406
Vec3f SolarSystem::getEphemerisSaturnMarkerColor() const
×
2407
{
2408
        return ephemerisSaturnMarkerColor;
×
2409
}
2410

2411
void SolarSystem::setFlagNativePlanetNames(bool b)
×
2412
{
2413
        if (b!=flagNativePlanetNames)
×
2414
        {
2415
                flagNativePlanetNames=b;
×
2416
                for (const auto& p : qAsConst(systemPlanets))
×
2417
                {
2418
                        if (p->getPlanetType()==Planet::isPlanet || p->getPlanetType()==Planet::isMoon || p->getPlanetType()==Planet::isStar)
×
2419
                                p->setFlagNativeName(flagNativePlanetNames);
×
2420
                }
2421
                updateI18n();
×
2422
                emit flagNativePlanetNamesChanged(b);
×
2423
        }
2424
}
×
2425

2426
bool SolarSystem::getFlagNativePlanetNames() const
×
2427
{
2428
        return flagNativePlanetNames;
×
2429
}
2430

2431
void SolarSystem::setFlagIsolatedTrails(bool b)
×
2432
{
2433
        if(b!=flagIsolatedTrails)
×
2434
        {
2435
                flagIsolatedTrails = b;
×
2436
                recreateTrails();
×
2437
                emit flagIsolatedTrailsChanged(b);
×
2438
        }
2439
}
×
2440

2441
bool SolarSystem::getFlagIsolatedTrails() const
×
2442
{
2443
        return flagIsolatedTrails;
×
2444
}
2445

2446
int SolarSystem::getNumberIsolatedTrails() const
×
2447
{
2448
        return numberIsolatedTrails;
×
2449
}
2450

2451
void SolarSystem::setNumberIsolatedTrails(int n)
×
2452
{
2453
        // [1..5] - valid range for trails
2454
        numberIsolatedTrails = qBound(1, n, 5);
×
2455

2456
        if (getFlagIsolatedTrails())
×
2457
                recreateTrails();
×
2458

2459
        emit numberIsolatedTrailsChanged(numberIsolatedTrails);
×
2460
}
×
2461

2462
void SolarSystem::setFlagIsolatedOrbits(bool b)
×
2463
{
2464
        if(b!=flagIsolatedOrbits)
×
2465
        {
2466
                flagIsolatedOrbits = b;
×
2467
                emit flagIsolatedOrbitsChanged(b);
×
2468
                // Reinstall flag for orbits to renew visibility of orbits
2469
                setFlagOrbits(getFlagOrbits());
×
2470
        }
2471
}
×
2472

2473
bool SolarSystem::getFlagIsolatedOrbits() const
×
2474
{
2475
        return flagIsolatedOrbits;
×
2476
}
2477

2478
void SolarSystem::setFlagPlanetsOrbitsOnly(bool b)
×
2479
{
2480
        if(b!=flagPlanetsOrbitsOnly)
×
2481
        {
2482
                flagPlanetsOrbitsOnly = b;
×
2483
                emit flagPlanetsOrbitsOnlyChanged(b);
×
2484
                // Reinstall flag for orbits to renew visibility of orbits
2485
                setFlagOrbits(getFlagOrbits());
×
2486
        }
2487
}
×
2488

2489
bool SolarSystem::getFlagPlanetsOrbitsOnly() const
×
2490
{
2491
        return flagPlanetsOrbitsOnly;
×
2492
}
2493

2494
// Set/Get planets names color
2495
void SolarSystem::setLabelsColor(const Vec3f& c)
×
2496
{
2497
        if (c!=Planet::getLabelColor())
×
2498
        {
2499
                Planet::setLabelColor(c);
×
2500
                emit labelsColorChanged(c);
×
2501
        }
2502
}
×
2503

2504
Vec3f SolarSystem::getLabelsColor(void) const
×
2505
{
2506
        return Planet::getLabelColor();
×
2507
}
2508

2509
// Set/Get orbits lines color
2510
void SolarSystem::setOrbitsColor(const Vec3f& c)
×
2511
{
2512
        if (c!=Planet::getOrbitColor())
×
2513
        {
2514
                Planet::setOrbitColor(c);
×
2515
                emit orbitsColorChanged(c);
×
2516
        }
2517
}
×
2518

2519
Vec3f SolarSystem::getOrbitsColor(void) const
×
2520
{
2521
        return Planet::getOrbitColor();
×
2522
}
2523

2524
void SolarSystem::setMajorPlanetsOrbitsColor(const Vec3f &c)
×
2525
{
2526
        if (c!=Planet::getMajorPlanetOrbitColor())
×
2527
        {
2528
                Planet::setMajorPlanetOrbitColor(c);
×
2529
                emit majorPlanetsOrbitsColorChanged(c);
×
2530
        }
2531
}
×
2532

2533
Vec3f SolarSystem::getMajorPlanetsOrbitsColor(void) const
×
2534
{
2535
        return Planet::getMajorPlanetOrbitColor();
×
2536
}
2537

2538
void SolarSystem::setMinorPlanetsOrbitsColor(const Vec3f &c)
×
2539
{
2540
        if (c!=Planet::getMinorPlanetOrbitColor())
×
2541
        {
2542
                Planet::setMinorPlanetOrbitColor(c);
×
2543
                emit minorPlanetsOrbitsColorChanged(c);
×
2544
        }
2545
}
×
2546

2547
Vec3f SolarSystem::getMinorPlanetsOrbitsColor(void) const
×
2548
{
2549
        return Planet::getMinorPlanetOrbitColor();
×
2550
}
2551

2552
void SolarSystem::setDwarfPlanetsOrbitsColor(const Vec3f &c)
×
2553
{
2554
        if (c!=Planet::getDwarfPlanetOrbitColor())
×
2555
        {
2556
                Planet::setDwarfPlanetOrbitColor(c);
×
2557
                emit dwarfPlanetsOrbitsColorChanged(c);
×
2558
        }
2559
}
×
2560

2561
Vec3f SolarSystem::getDwarfPlanetsOrbitsColor(void) const
×
2562
{
2563
        return Planet::getDwarfPlanetOrbitColor();
×
2564
}
2565

2566
void SolarSystem::setMoonsOrbitsColor(const Vec3f &c)
×
2567
{
2568
        if (c!=Planet::getMoonOrbitColor())
×
2569
        {
2570
                Planet::setMoonOrbitColor(c);
×
2571
                emit moonsOrbitsColorChanged(c);
×
2572
        }
2573
}
×
2574

2575
Vec3f SolarSystem::getMoonsOrbitsColor(void) const
×
2576
{
2577
        return Planet::getMoonOrbitColor();
×
2578
}
2579

2580
void SolarSystem::setCubewanosOrbitsColor(const Vec3f &c)
×
2581
{
2582
        if (c!=Planet::getCubewanoOrbitColor())
×
2583
        {
2584
                Planet::setCubewanoOrbitColor(c);
×
2585
                emit cubewanosOrbitsColorChanged(c);
×
2586
        }
2587
}
×
2588

2589
Vec3f SolarSystem::getCubewanosOrbitsColor(void) const
×
2590
{
2591
        return Planet::getCubewanoOrbitColor();
×
2592
}
2593

2594
void SolarSystem::setPlutinosOrbitsColor(const Vec3f &c)
×
2595
{
2596
        if (c!=Planet::getPlutinoOrbitColor())
×
2597
        {
2598
                Planet::setPlutinoOrbitColor(c);
×
2599
                emit plutinosOrbitsColorChanged(c);
×
2600
        }
2601
}
×
2602

2603
Vec3f SolarSystem::getPlutinosOrbitsColor(void) const
×
2604
{
2605
        return Planet::getPlutinoOrbitColor();
×
2606
}
2607

2608
void SolarSystem::setScatteredDiskObjectsOrbitsColor(const Vec3f &c)
×
2609
{
2610
        if (c!=Planet::getScatteredDiscObjectOrbitColor())
×
2611
        {
2612
                Planet::setScatteredDiscObjectOrbitColor(c);
×
2613
                emit scatteredDiskObjectsOrbitsColorChanged(c);
×
2614
        }
2615
}
×
2616

2617
Vec3f SolarSystem::getScatteredDiskObjectsOrbitsColor(void) const
×
2618
{
2619
        return Planet::getScatteredDiscObjectOrbitColor();
×
2620
}
2621

2622
void SolarSystem::setOortCloudObjectsOrbitsColor(const Vec3f &c)
×
2623
{
2624
        if (c!=Planet::getOortCloudObjectOrbitColor())
×
2625
        {
2626
                Planet::setOortCloudObjectOrbitColor(c);
×
2627
                emit oortCloudObjectsOrbitsColorChanged(c);
×
2628
        }
2629
}
×
2630

2631
Vec3f SolarSystem::getOortCloudObjectsOrbitsColor(void) const
×
2632
{
2633
        return Planet::getOortCloudObjectOrbitColor();
×
2634
}
2635

2636
void SolarSystem::setCometsOrbitsColor(const Vec3f& c)
×
2637
{
2638
        if (c!=Planet::getCometOrbitColor())
×
2639
        {
2640
                Planet::setCometOrbitColor(c);
×
2641
                emit cometsOrbitsColorChanged(c);
×
2642
        }
2643
}
×
2644

2645
Vec3f SolarSystem::getCometsOrbitsColor(void) const
×
2646
{
2647
        return Planet::getCometOrbitColor();
×
2648
}
2649

2650
void SolarSystem::setSednoidsOrbitsColor(const Vec3f& c)
×
2651
{
2652
        if (c!=Planet::getSednoidOrbitColor())
×
2653
        {
2654
                Planet::setSednoidOrbitColor(c);
×
2655
                emit sednoidsOrbitsColorChanged(c);
×
2656
        }
2657
}
×
2658

2659
Vec3f SolarSystem::getSednoidsOrbitsColor(void) const
×
2660
{
2661
        return Planet::getSednoidOrbitColor();
×
2662
}
2663

2664
void SolarSystem::setInterstellarOrbitsColor(const Vec3f& c)
×
2665
{
2666
        if (c!=Planet::getInterstellarOrbitColor())
×
2667
        {
2668
                Planet::setInterstellarOrbitColor(c);
×
2669
                emit interstellarOrbitsColorChanged(c);
×
2670
        }
2671
}
×
2672

2673
Vec3f SolarSystem::getInterstellarOrbitsColor(void) const
×
2674
{
2675
        return Planet::getInterstellarOrbitColor();
×
2676
}
2677

2678
void SolarSystem::setMercuryOrbitColor(const Vec3f &c)
×
2679
{
2680
        if (c!=Planet::getMercuryOrbitColor())
×
2681
        {
2682
                Planet::setMercuryOrbitColor(c);
×
2683
                emit mercuryOrbitColorChanged(c);
×
2684
        }
2685
}
×
2686

2687
Vec3f SolarSystem::getMercuryOrbitColor(void) const
×
2688
{
2689
        return Planet::getMercuryOrbitColor();
×
2690
}
2691

2692
void SolarSystem::setVenusOrbitColor(const Vec3f &c)
×
2693
{
2694
        if (c!=Planet::getVenusOrbitColor())
×
2695
        {
2696
                Planet::setVenusOrbitColor(c);
×
2697
                emit venusOrbitColorChanged(c);
×
2698
        }
2699
}
×
2700

2701
Vec3f SolarSystem::getVenusOrbitColor(void) const
×
2702
{
2703
        return Planet::getVenusOrbitColor();
×
2704
}
2705

2706
void SolarSystem::setEarthOrbitColor(const Vec3f &c)
×
2707
{
2708
        if (c!=Planet::getEarthOrbitColor())
×
2709
        {
2710
                Planet::setEarthOrbitColor(c);
×
2711
                emit earthOrbitColorChanged(c);
×
2712
        }
2713
}
×
2714

2715
Vec3f SolarSystem::getEarthOrbitColor(void) const
×
2716
{
2717
        return Planet::getEarthOrbitColor();
×
2718
}
2719

2720
void SolarSystem::setMarsOrbitColor(const Vec3f &c)
×
2721
{
2722
        if (c!=Planet::getMarsOrbitColor())
×
2723
        {
2724
                Planet::setMarsOrbitColor(c);
×
2725
                emit marsOrbitColorChanged(c);
×
2726
        }
2727
}
×
2728

2729
Vec3f SolarSystem::getMarsOrbitColor(void) const
×
2730
{
2731
        return Planet::getMarsOrbitColor();
×
2732
}
2733

2734
void SolarSystem::setJupiterOrbitColor(const Vec3f &c)
×
2735
{
2736
        if (c!=Planet::getJupiterOrbitColor())
×
2737
        {
2738
                Planet::setJupiterOrbitColor(c);
×
2739
                emit jupiterOrbitColorChanged(c);
×
2740
        }
2741
}
×
2742

2743
Vec3f SolarSystem::getJupiterOrbitColor(void) const
×
2744
{
2745
        return Planet::getJupiterOrbitColor();
×
2746
}
2747

2748
void SolarSystem::setSaturnOrbitColor(const Vec3f &c)
×
2749
{
2750
        if (c!=Planet::getSaturnOrbitColor())
×
2751
        {
2752
                Planet::setSaturnOrbitColor(c);
×
2753
                emit saturnOrbitColorChanged(c);
×
2754
        }
2755
}
×
2756

2757
Vec3f SolarSystem::getSaturnOrbitColor(void) const
×
2758
{
2759
        return Planet::getSaturnOrbitColor();
×
2760
}
2761

2762
void SolarSystem::setUranusOrbitColor(const Vec3f &c)
×
2763
{
2764
        if (c!=Planet::getUranusOrbitColor())
×
2765
        {
2766
                Planet::setUranusOrbitColor(c);
×
2767
                emit uranusOrbitColorChanged(c);
×
2768
        }
2769
}
×
2770

2771
Vec3f SolarSystem::getUranusOrbitColor(void) const
×
2772
{
2773
        return Planet::getUranusOrbitColor();
×
2774
}
2775

2776
void SolarSystem::setNeptuneOrbitColor(const Vec3f &c)
×
2777
{
2778
        if (c!=Planet::getNeptuneOrbitColor())
×
2779
        {
2780
                Planet::setNeptuneOrbitColor(c);
×
2781
                emit neptuneOrbitColorChanged(c);
×
2782
        }
2783
}
×
2784

2785
Vec3f SolarSystem::getNeptuneOrbitColor(void) const
×
2786
{
2787
        return Planet::getNeptuneOrbitColor();
×
2788
}
2789

2790
// Set/Get if Moon display is scaled
2791
void SolarSystem::setFlagMoonScale(bool b)
×
2792
{
2793
        if(b!=flagMoonScale)
×
2794
        {
2795
                if (b) getMoon()->setSphereScale(moonScale);
×
2796
                else getMoon()->setSphereScale(1);
×
2797
                flagMoonScale = b;
×
2798
                emit flagMoonScaleChanged(b);
×
2799
        }
2800
}
×
2801

2802
// Set/Get Moon display scaling factor. This goes directly to the Moon object.
2803
void SolarSystem::setMoonScale(double f)
×
2804
{
2805
        if(!fuzzyEquals(moonScale, f))
×
2806
        {
2807
                moonScale = f;
×
2808
                if (flagMoonScale)
×
2809
                        getMoon()->setSphereScale(moonScale);
×
2810
                emit moonScaleChanged(f);
×
2811
        }
2812
}
×
2813

2814
// Set if minor body display is scaled. This flag will be queried by all Planet objects except for the Moon.
2815
void SolarSystem::setFlagMinorBodyScale(bool b)
×
2816
{
2817
        if(b!=flagMinorBodyScale)
×
2818
        {
2819
                flagMinorBodyScale = b;
×
2820

2821
                double newScale = b ? minorBodyScale : 1.0;
×
2822
                //update the bodies with the new scale
2823
                for (const auto& p : qAsConst(systemPlanets))
×
2824
                {
2825
                        if(p == moon) continue;
×
2826
                        if (p->getPlanetType()!=Planet::isPlanet && p->getPlanetType()!=Planet::isStar)
×
2827
                                p->setSphereScale(newScale);
×
2828
                }
2829
                emit flagMinorBodyScaleChanged(b);
×
2830
        }
2831
}
×
2832

2833
// Set minor body display scaling factor. This will be queried by all Planet objects except for the Moon.
2834
void SolarSystem::setMinorBodyScale(double f)
×
2835
{
2836
        if(!fuzzyEquals(minorBodyScale, f))
×
2837
        {
2838
                minorBodyScale = f;
×
2839
                if(flagMinorBodyScale) //update the bodies with the new scale
×
2840
                {
2841
                        for (const auto& p : qAsConst(systemPlanets))
×
2842
                        {
2843
                                if(p == moon) continue;
×
2844
                                if (p->getPlanetType()!=Planet::isPlanet && p->getPlanetType()!=Planet::isStar)
×
2845
                                        p->setSphereScale(minorBodyScale);
×
2846
                        }
2847
                }
2848
                emit minorBodyScaleChanged(f);
×
2849
        }
2850
}
×
2851

2852
// Set if Planet display is scaled
2853
void SolarSystem::setFlagPlanetScale(bool b)
×
2854
{
2855
        if(b!=flagPlanetScale)
×
2856
        {
2857
                double scale=(b ? planetScale : 1.);
×
2858
                for (auto& p : systemPlanets)
×
2859
                {
2860
                        if (p->pType==Planet::isPlanet)
×
2861
                                p->setSphereScale(scale);
×
2862
                }
2863
                flagPlanetScale = b;
×
2864
                emit flagPlanetScaleChanged(b);
×
2865
        }
2866
}
×
2867

2868
// Set Moon display scaling factor.
2869
void SolarSystem::setPlanetScale(double f)
×
2870
{
2871
        if(!fuzzyEquals(planetScale, f))
×
2872
        {
2873
                planetScale = f;
×
2874
                if (flagPlanetScale)
×
2875
                        for (auto& p : systemPlanets)
×
2876
                        {
2877
                                if (p->pType==Planet::isPlanet)
×
2878
                                        p->setSphereScale(planetScale);
×
2879
                        }
2880
                emit planetScaleChanged(f);
×
2881
        }
2882
}
×
2883

2884
// Set if Sun display is scaled
2885
void SolarSystem::setFlagSunScale(bool b)
×
2886
{
2887
        if(b!=flagSunScale)
×
2888
        {
2889
                if (b) getSun()->setSphereScale(sunScale);
×
2890
                else getSun()->setSphereScale(1);
×
2891
                flagSunScale = b;
×
2892
                emit flagSunScaleChanged(b);
×
2893
        }
2894
}
×
2895

2896
// Set Sun display scaling factor. This goes directly to the Sun object.
2897
void SolarSystem::setSunScale(double f)
×
2898
{
2899
        if(!fuzzyEquals(sunScale, f))
×
2900
        {
2901
                sunScale = f;
×
2902
                if (flagSunScale)
×
2903
                        getSun()->setSphereScale(sunScale);
×
2904
                emit sunScaleChanged(f);
×
2905
        }
2906
}
×
2907

2908
// Set selected planets by englishName
2909
void SolarSystem::setSelected(const QString& englishName)
×
2910
{
2911
        setSelected(searchByEnglishName(englishName));
×
2912
}
×
2913

2914
// Get the list of all the planet english names
2915
QStringList SolarSystem::getAllPlanetEnglishNames() const
×
2916
{
2917
        QStringList res;
×
2918
        for (const auto& p : systemPlanets)
×
2919
                res.append(p->getEnglishName());
×
2920
        return res;
×
2921
}
×
2922

2923
QStringList SolarSystem::getAllPlanetLocalizedNames() const
×
2924
{
2925
        QStringList res;
×
2926
        for (const auto& p : systemPlanets)
×
2927
                res.append(p->getNameI18n());
×
2928
        return res;
×
2929
}
×
2930

2931
QStringList SolarSystem::getAllMinorPlanetCommonEnglishNames() const
×
2932
{
2933
        QStringList res;
×
2934
        for (const auto& p : systemMinorBodies)
×
2935
                res.append(p->getCommonEnglishName());
×
2936
        return res;
×
2937
}
×
2938

2939

2940
// GZ TODO: This could be modified to only delete&reload the minor objects. For now, we really load both parts again like in the 0.10?-0.15 series.
2941
void SolarSystem::reloadPlanets()
×
2942
{
2943
        // Save flag states
2944
        const bool flagScaleMoon = getFlagMoonScale();
×
2945
        const double moonScale = getMoonScale();
×
2946
        const bool flagScaleMinorBodies=getFlagMinorBodyScale();
×
2947
        const double minorScale= getMinorBodyScale();
×
2948
        const bool flagPlanets = getFlagPlanets();
×
2949
        const bool flagHints = getFlagHints();
×
2950
        const bool flagLabels = getFlagLabels();
×
2951
        const bool flagOrbits = getFlagOrbits();
×
2952
        const bool flagNative = getFlagNativePlanetNames();
×
2953
        bool hasSelection = false;
×
2954

2955
        // Save observer location (fix for LP bug # 969211)
2956
        // TODO: This can probably be done better with a better understanding of StelObserver --BM
2957
        StelCore* core = StelApp::getInstance().getCore();
×
2958
        const StelLocation loc = core->getCurrentLocation();
×
2959
        StelObjectMgr* objMgr = GETSTELMODULE(StelObjectMgr);
×
2960

2961
        // Whether any planet are selected? Save the current selection...
2962
        const QList<StelObjectP> selectedObject = objMgr->getSelectedObject("Planet");
×
2963
        if (!selectedObject.isEmpty())
×
2964
        {
2965
                // ... unselect current planet.
2966
                hasSelection = true;
×
2967
                objMgr->unSelect();
×
2968
        }
2969
        // Unload all Solar System objects
2970
        selected.clear();//Release the selected one
×
2971

2972
        // GZ TODO in case this methods gets converted to only reload minor bodies: Only delete Orbits which are not referenced by some Planet.
2973
        for (auto* orb : qAsConst(orbits))
×
2974
        {
2975
                delete orb;
×
2976
        }
2977
        orbits.clear();
×
2978

2979
        sun.clear();
×
2980
        moon.clear();
×
2981
        earth.clear();
×
2982
        Planet::texEarthShadow.clear(); //Loaded in loadPlanets()
×
2983

2984
        delete allTrails;
×
2985
        allTrails = Q_NULLPTR;
×
2986

2987
        for (const auto& p : qAsConst(systemPlanets))
×
2988
        {
2989
                p->satellites.clear();
×
2990
        }
2991
        systemPlanets.clear();
×
2992
        systemMinorBodies.clear();
×
2993
        // Memory leak? What's the proper way of cleaning shared pointers?
2994

2995
        // Also delete Comet textures (loaded in loadPlanets()
2996
        Comet::tailTexture.clear();
×
2997
        Comet::comaTexture.clear();
×
2998

2999
        // Re-load the ssystem_major.ini and ssystem_minor.ini file
3000
        loadPlanets();        
×
3001
        computePositions(core->getJDE(), getSun());
×
3002
        setSelected("");
×
3003
        recreateTrails();
×
3004
        
3005
        // Restore observer location
3006
        core->moveObserverTo(loc, 0., 0.);
×
3007

3008
        // Restore flag states
3009
        setFlagMoonScale(flagScaleMoon);
×
3010
        setMoonScale(moonScale);
×
3011
        setFlagMinorBodyScale(flagScaleMinorBodies);
×
3012
        setMinorBodyScale(1.0); // force-reset first to really reach the objects in the next call.
×
3013
        setMinorBodyScale(minorScale);
×
3014
        setFlagPlanets(flagPlanets);
×
3015
        setFlagHints(flagHints);
×
3016
        setFlagLabels(flagLabels);
×
3017
        setFlagOrbits(flagOrbits);
×
3018
        setFlagNativePlanetNames(flagNative);
×
3019

3020
        // Restore translations
3021
        updateI18n();
×
3022

3023
        if (hasSelection)
×
3024
        {
3025
                // Restore selection...
3026
                StelObjectP obj = selectedObject[0];
×
3027
                objMgr->findAndSelect(obj->getEnglishName(), obj->getType());
×
3028
        }
×
3029

3030
        emit solarSystemDataReloaded();
×
3031
}
×
3032

3033
// Set the algorithm for computation of apparent magnitudes for planets in case  observer on the Earth
3034
void SolarSystem::setApparentMagnitudeAlgorithmOnEarth(QString algorithm)
×
3035
{
3036
        Planet::setApparentMagnitudeAlgorithm(algorithm);
×
3037
        emit apparentMagnitudeAlgorithmOnEarthChanged(algorithm);
×
3038
}
×
3039

3040
// Get the algorithm used for computation of apparent magnitudes for planets in case  observer on the Earth
3041
QString SolarSystem::getApparentMagnitudeAlgorithmOnEarth() const
×
3042
{
3043
        return Planet::getApparentMagnitudeAlgorithmString();
×
3044
}
3045

3046
void SolarSystem::setFlagDrawMoonHalo(bool b)
×
3047
{
3048
        Planet::drawMoonHalo=b;
×
3049
        emit flagDrawMoonHaloChanged(b);
×
3050
}
×
3051

3052
bool SolarSystem::getFlagDrawMoonHalo() const
×
3053
{
3054
        return Planet::drawMoonHalo;
×
3055
}
3056

3057
void SolarSystem::setFlagDrawSunHalo(bool b)
×
3058
{
3059
        Planet::drawSunHalo=b;
×
3060
        emit flagDrawSunHaloChanged(b);
×
3061
}
×
3062

3063
bool SolarSystem::getFlagDrawSunHalo() const
×
3064
{
3065
        return Planet::drawSunHalo;
×
3066
}
3067

3068
void SolarSystem::setFlagPermanentOrbits(bool b)
×
3069
{
3070
        Planet::permanentDrawingOrbits=b;
×
3071
        emit flagPermanentOrbitsChanged(b);
×
3072
}
×
3073

3074
bool SolarSystem::getFlagPermanentOrbits() const
×
3075
{
3076
        return Planet::permanentDrawingOrbits;
×
3077
}
3078

3079
void SolarSystem::setOrbitsThickness(int v)
×
3080
{
3081
        Planet::orbitsThickness=v;
×
3082
        emit orbitsThicknessChanged(v);
×
3083
}
×
3084

3085
int SolarSystem::getOrbitsThickness() const
×
3086
{
3087
        return Planet::orbitsThickness;
×
3088
}
3089

3090
void SolarSystem::setGrsLongitude(int longitude)
×
3091
{
3092
        RotationElements::grsLongitude = longitude;
×
3093
        // automatic saving of the setting
3094
        conf->setValue("astro/grs_longitude", longitude);
×
3095
        emit grsLongitudeChanged(longitude);
×
3096
}
×
3097

3098
int SolarSystem::getGrsLongitude() const
×
3099
{
3100
        return static_cast<int>(RotationElements::grsLongitude);
×
3101
}
3102

3103
void SolarSystem::setGrsDrift(double drift)
×
3104
{
3105
        RotationElements::grsDrift = drift;
×
3106
        // automatic saving of the setting
3107
        conf->setValue("astro/grs_drift", drift);
×
3108
        emit grsDriftChanged(drift);
×
3109
}
×
3110

3111
double SolarSystem::getGrsDrift() const
×
3112
{
3113
        return RotationElements::grsDrift;
×
3114
}
3115

3116
void SolarSystem::setGrsJD(double JD)
×
3117
{
3118
        RotationElements::grsJD = JD;
×
3119
        // automatic saving of the setting
3120
        conf->setValue("astro/grs_jd", JD);
×
3121
        emit grsJDChanged(JD);
×
3122
}
×
3123

3124
double SolarSystem::getGrsJD()
×
3125
{
3126
        return RotationElements::grsJD;
×
3127
}
3128

3129
void SolarSystem::setFlagEarthShadowEnlargementDanjon(bool b)
×
3130
{
3131
        earthShadowEnlargementDanjon=b;
×
3132
        emit earthShadowEnlargementDanjonChanged(b);
×
3133
}
×
3134

3135
bool SolarSystem::getFlagEarthShadowEnlargementDanjon() const
×
3136
{
3137
        return earthShadowEnlargementDanjon;
×
3138
}
3139

3140
void SolarSystem::setOrbitColorStyle(QString style)
×
3141
{
3142
        if (style.toLower()=="groups")
×
3143
                Planet::orbitColorStyle = Planet::ocsGroups;
×
3144
        else if (style.toLower()=="major_planets")
×
3145
                Planet::orbitColorStyle = Planet::ocsMajorPlanets;
×
3146
        else
3147
                Planet::orbitColorStyle = Planet::ocsOneColor;
×
3148
}
×
3149

3150
QString SolarSystem::getOrbitColorStyle() const
×
3151
{
3152
        QString r = "one_color";
×
3153
        switch (Planet::orbitColorStyle)
×
3154
        {
3155
                case Planet::ocsOneColor:
×
3156
                        r = "one_color";
×
3157
                        break;
×
3158
                case Planet::ocsGroups:
×
3159
                        r = "groups";
×
3160
                        break;
×
3161
                case Planet::ocsMajorPlanets:
×
3162
                        r = "major_planets";
×
3163
                        break;
×
3164
        }
3165
        return r;
×
3166
}
×
3167

3168
// TODO: To make the code better understandable, get rid of planet->computeModelMatrix(trans, true) here.
3169
QPair<double, PlanetP> SolarSystem::getSolarEclipseFactor(const StelCore* core) const
×
3170
{
3171
        PlanetP p;
×
3172
        const Vec3d Lp = sun->getEclipticPos() + sun->getAberrationPush();
×
3173
        const Vec3d P3 = core->getObserverHeliocentricEclipticPos();
×
3174
        const double RS = sun->getEquatorialRadius();
×
3175

3176
        double final_illumination = 1.0;
×
3177

3178
        for (const auto& planet : systemPlanets)
×
3179
        {
3180
                if(planet == sun || planet == core->getCurrentPlanet())
×
3181
                        continue;
×
3182

3183
                Mat4d trans;
×
3184
                planet->computeModelMatrix(trans, true);
×
3185

3186
                const Vec3d C = trans * Vec3d(0., 0., 0.);
×
3187
                const double radius = planet->getEquatorialRadius();
×
3188

3189
                Vec3d v1 = Lp - P3;
×
3190
                Vec3d v2 = C - P3;
×
3191
                const double L = v1.norm();
×
3192
                const double l = v2.norm();
×
3193
                v1 /= L;
×
3194
                v2 /= l;
×
3195

3196
                const double R = RS / L;
×
3197
                const double r = radius / l;
×
3198
                const double d = ( v1 - v2 ).norm();
×
3199
                double illumination;
3200

3201
                if(d >= R + r) // distance too far
×
3202
                {
3203
                        illumination = 1.0;
×
3204
                }
3205
                else if(d <= r - R) // umbra
×
3206
                {
3207
                        illumination = 0.0;
×
3208
                }
3209
                else if(d <= R - r) // penumbra completely inside
×
3210
                {
3211
                        illumination = 1.0 - r * r / (R * R);
×
3212
                }
3213
                else // penumbra partially inside
3214
                {
3215
                        const double x = (R * R + d * d - r * r) / (2.0 * d);
×
3216

3217
                        const double alpha = std::acos(x / R);
×
3218
                        const double beta = std::acos((d - x) / r);
×
3219

3220
                        const double AR = R * R * (alpha - 0.5 * std::sin(2.0 * alpha));
×
3221
                        const double Ar = r * r * (beta - 0.5 * std::sin(2.0 * beta));
×
3222
                        const double AS = R * R * 2.0 * std::asin(1.0);
×
3223

3224
                        illumination = 1.0 - (AR + Ar) / AS;
×
3225
                }
3226

3227
                if(illumination < final_illumination)
×
3228
                {
3229
                        final_illumination = illumination;
×
3230
                        p = planet;
×
3231
                }
3232
        }
3233

3234
        return QPair<double, PlanetP>(final_illumination, p);
×
3235
}
×
3236

3237
// Retrieve Radius of Umbra and Penumbra at the distance of the Moon.
3238
// Returns a pair (umbra, penumbra) in (geocentric_arcseconds, AU, geometric_AU).
3239
// * sizes in arcseconds are the usual result found as Bessel element in eclipse literature.
3240
//   It includes scaling for effects of atmosphere either after Chauvenet (2%) or after Danjon. (see Espenak: 5000 Years Canon of Lunar Eclipses.)
3241
// * sizes in AU are the same, converted back to AU in Lunar distance.
3242
// * sizes in geometric_AU derived from pure geometrical evaluations without scalings applied.
3243
QPair<Vec3d,Vec3d> SolarSystem::getEarthShadowRadiiAtLunarDistance() const
×
3244
{
3245
        // Note: The application of this shadow enlargement is not according to the books, but looks close enough for now.
3246
        static const double sun2earth=sun->getEquatorialRadius() / earth->getEquatorialRadius();
×
3247
        PlanetP sun=getSun();
×
3248
        PlanetP moon=getMoon();
×
3249
        PlanetP earth=getEarth();
×
3250
        const double lunarDistance=moon->getEclipticPos().norm(); // Lunar distance [AU]
×
3251
        const double earthDistance=earth->getHeliocentricEclipticPos().norm(); // Earth distance [AU]
×
3252
        const double sunHP =asin(earth->getEquatorialRadius()/earthDistance) * M_180_PI*3600.; // arcsec.
×
3253
        const double moonHP=asin(earth->getEquatorialRadius()/lunarDistance) * M_180_PI*3600.; // arcsec.
×
3254
        const double sunSD  =atan(sun->getEquatorialRadius()/earthDistance)  * M_180_PI*3600.; // arcsec.
×
3255

3256
        // Compute umbra radius at lunar distance.
3257
        const double lUmbra=earthDistance/(sun2earth-1.); // length of earth umbra [AU]
×
3258
        const double rUmbraAU=earth->getEquatorialRadius()*(lUmbra-lunarDistance)/lUmbra; // radius of earth shadow at lunar distance [AU]
×
3259
        // Penumbra:
3260
        const double lPenumbra=earthDistance/(sun2earth + 1.); // distance between earth and point between sun and earth where penumbral border rays intersect
×
3261
        const double rPenumbraAU=earth->getEquatorialRadius()*(lPenumbra+lunarDistance)/lPenumbra; // radius of penumbra at Lunar distance [AU]
×
3262

3263
        //Classical Bessel elements instead
3264
        double f1, f2;
3265
        if (earthShadowEnlargementDanjon)
×
3266
        {
3267
                static const double danjonScale=1+1./85.-1./594.; // ~1.01, shadow magnification factor (see Espenak 5000 years Canon)
3268
                f1=danjonScale*moonHP + sunHP + sunSD; // penumbra radius, arcsec
×
3269
                f2=danjonScale*moonHP + sunHP - sunSD; // umbra radius, arcsec
×
3270
        }
3271
        else
3272
        {
3273
                const double mHP1=0.998340*moonHP;
×
3274
                f1=1.02*(mHP1 + sunHP + sunSD); // penumbra radius, arcsec
×
3275
                f2=1.02*(mHP1 + sunHP - sunSD); // umbra radius, arcsec
×
3276
        }
3277
        const double f1_AU=tan(f1/3600.*M_PI_180)*lunarDistance;
×
3278
        const double f2_AU=tan(f2/3600.*M_PI_180)*lunarDistance;
×
3279
        return QPair<Vec3d,Vec3d>(Vec3d(f2, f2_AU, rUmbraAU), Vec3d(f1, f1_AU, rPenumbraAU));
×
3280
}
×
3281

3282
bool SolarSystem::removeMinorPlanet(QString name)
×
3283
{
3284
        PlanetP candidate = searchMinorPlanetByEnglishName(name);
×
3285
        if (!candidate)
×
3286
        {
3287
                qWarning() << "Cannot remove planet " << name << ": Not found.";
×
3288
                return false;
×
3289
        }
3290
        Orbit* orbPtr=static_cast<Orbit*>(candidate->orbitPtr);
×
3291
        if (orbPtr)
×
3292
                orbits.removeOne(orbPtr);
×
3293
        systemPlanets.removeOne(candidate);
×
3294
        systemMinorBodies.removeOne(candidate);
×
3295
        candidate.clear();
×
3296
        return true;
×
3297
}
×
3298

3299
void SolarSystem::onNewSurvey(HipsSurveyP survey)
×
3300
{
3301
        // For the moment we only consider the survey url to decide if we
3302
        // assign it to a planet.  It would be better to use some property
3303
        // for that.
3304
        QString planetName = QUrl(survey->getUrl()).fileName();
×
3305
        PlanetP pl = searchByEnglishName(planetName);
×
3306
        if (!pl || pl->survey)
×
3307
                return;
×
3308
        pl->survey = survey;
×
3309
        survey->setProperty("planet", pl->getCommonEnglishName());
×
3310
        // Not visible by default for the moment.
3311
        survey->setProperty("visible", false);
×
3312
}
×
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