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

Stellarium / stellarium / 3996069357

pending completion
3996069357

push

github

Ruslan Kabatsayev
Shorten some lines

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

14663 of 124076 relevant lines covered (11.82%)

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

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

760

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

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

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

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

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

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

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

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

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

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

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

972
                // New class objects, named "plutino", "cubewano", "dwarf planet", "SDO", "OCO", has properties
973
                // similar to asteroids and we should calculate their positions like for asteroids. Dwarf planets
974
                // have one exception: Pluto - as long as we use a special function for calculation of Pluto's orbit.
975
                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"))
×
976
                {
977
                        minorBodies << englishName;
×
978

979
                        Vec3f color = Vec3f(1.f, 1.f, 1.f);
×
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
                        newP->setColorIndexBV(static_cast<float>(bV));
×
1096
                }
×
1097

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1206
        // Also comets just have static textures.
1207
        if (!Comet::comaTexture)
×
1208
                Comet::comaTexture = StelApp::getInstance().getTextureManager().createTextureThread(StelFileMgr::getInstallationDir()+"/textures/cometComa.png", StelTexture::StelTextureParams(true, GL_LINEAR, GL_CLAMP_TO_EDGE));
×
1209
        //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.
1210
        if (!Comet::tailTexture)
×
1211
                Comet::tailTexture = StelApp::getInstance().getTextureManager().createTextureThread(StelFileMgr::getInstallationDir()+"/textures/cometTail.png", StelTexture::StelTextureParams(true, GL_LINEAR, GL_CLAMP_TO_EDGE));
×
1212

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

1216
        return true;
×
1217
}
×
1218

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1587
                                StelUtils::getTimeFromJulianDay(JD+shift, &h, &m, &s);
×
1588
                                QString hours = QString::number(h).rightJustified(2, '0');
×
1589
                                QString minutes = QString::number(m).rightJustified(2, '0');
×
1590
                                if (!info.isEmpty())
×
1591
                                        info.append(QString(" %1:%2").arg(hours, minutes));
×
1592
                                else
1593
                                        info = QString("%1:%2").arg(hours, minutes);
×
1594
                        }
×
1595

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

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

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

1634

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

1646

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

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

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

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

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

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

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

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

1733
        return r;
×
1734
}
×
1735

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

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

1756
        if (cos_angle_closest>0.999)
×
1757
        {
1758
                return qSharedPointerCast<StelObject>(closest);
×
1759
        }
1760
        else return StelObjectP();
×
1761
}
×
1762

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

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

1782
        double cosLimFov = std::cos(limitFov * M_PI/180.);
×
1783
        Vec3d equPos;
×
1784
        double cosAngularSize;
1785

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

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

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

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

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

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

1832
bool SolarSystem::getFlagTrails() const
×
1833
{
1834
        return static_cast<bool>(trailFader);
×
1835
}
1836

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

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

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

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

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

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

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

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

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

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

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

2002

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

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

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

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

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

2033
        // find shadow radii in AU
2034
        double r_penumbra = shadow.norm()*702378.1/AU/e.norm() - SUN_RADIUS/AU;
×
2035

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

2040
        return true;
×
2041
}
2042

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

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

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

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

2110
bool SolarSystem::getFlagPlanets(void) const
×
2111
{
2112
        return flagShow;
×
2113
}
2114

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

2125
bool SolarSystem::getFlagEphemerisMarkers() const
×
2126
{
2127
        return ephemerisMarkersDisplayed;
×
2128
}
2129

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

2140
bool SolarSystem::getFlagEphemerisLine() const
×
2141
{
2142
        return ephemerisLineDisplayed;
×
2143
}
2144

2145
bool SolarSystem::getFlagEphemerisAlwaysOn() const
×
2146
{
2147
        return ephemerisAlwaysOn;
×
2148
}
2149

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

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

2170
bool SolarSystem::getFlagEphemerisHorizontalCoordinates() const
×
2171
{
2172
        return ephemerisHorizontalCoordinates;
×
2173
}
2174

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

2185
bool SolarSystem::getFlagEphemerisDates() const
×
2186
{
2187
        return ephemerisDatesDisplayed;
×
2188
}
2189

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

2200
bool SolarSystem::getFlagEphemerisMagnitudes() const
×
2201
{
2202
        return ephemerisMagnitudesDisplayed;
×
2203
}
2204

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

2215
bool SolarSystem::getFlagEphemerisSkipData() const
×
2216
{
2217
        return ephemerisSkipDataDisplayed;
×
2218
}
2219

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

2230
bool SolarSystem::getFlagEphemerisSkipMarkers() const
×
2231
{
2232
        return ephemerisSkipMarkersDisplayed;
×
2233
}
2234

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

2245
bool SolarSystem::getFlagEphemerisSmartDates() const
×
2246
{
2247
        return ephemerisSmartDatesDisplayed;
×
2248
}
2249

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

2260
bool SolarSystem::getFlagEphemerisScaleMarkers() const
×
2261
{
2262
        return ephemerisScaleMarkersDisplayed;
×
2263
}
2264

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

2273
int SolarSystem::getEphemerisDataStep() const
×
2274
{
2275
        return ephemerisDataStep;
×
2276
}
2277

2278
void SolarSystem::setEphemerisDataLimit(int limit)
×
2279
{
2280
        ephemerisDataLimit = limit;
×
2281
        emit ephemerisDataLimitChanged(limit);
×
2282
}
×
2283

2284
int SolarSystem::getEphemerisDataLimit() const
×
2285
{
2286
        return ephemerisDataLimit;
×
2287
}
2288

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

2297
int SolarSystem::getEphemerisLineThickness() const
×
2298
{
2299
        return ephemerisLineThickness;
×
2300
}
2301

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

2311
Vec3f SolarSystem::getEphemerisGenericMarkerColor() const
×
2312
{
2313
        return ephemerisGenericMarkerColor;
×
2314
}
2315

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

2325
Vec3f SolarSystem::getEphemerisSecondaryMarkerColor() const
×
2326
{
2327
        return ephemerisSecondaryMarkerColor;
×
2328
}
2329

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

2339
Vec3f SolarSystem::getEphemerisSelectedMarkerColor() const
×
2340
{
2341
        return ephemerisSelectedMarkerColor;
×
2342
}
2343

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

2353
Vec3f SolarSystem::getEphemerisMercuryMarkerColor() const
×
2354
{
2355
        return ephemerisMercuryMarkerColor;
×
2356
}
2357

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

2367
Vec3f SolarSystem::getEphemerisVenusMarkerColor() const
×
2368
{
2369
        return ephemerisVenusMarkerColor;
×
2370
}
2371

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

2381
Vec3f SolarSystem::getEphemerisMarsMarkerColor() const
×
2382
{
2383
        return ephemerisMarsMarkerColor;
×
2384
}
2385

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

2395
Vec3f SolarSystem::getEphemerisJupiterMarkerColor() const
×
2396
{
2397
        return ephemerisJupiterMarkerColor;
×
2398
}
2399

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

2409
Vec3f SolarSystem::getEphemerisSaturnMarkerColor() const
×
2410
{
2411
        return ephemerisSaturnMarkerColor;
×
2412
}
2413

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

2429
bool SolarSystem::getFlagNativePlanetNames() const
×
2430
{
2431
        return flagNativePlanetNames;
×
2432
}
2433

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

2444
bool SolarSystem::getFlagIsolatedTrails() const
×
2445
{
2446
        return flagIsolatedTrails;
×
2447
}
2448

2449
int SolarSystem::getNumberIsolatedTrails() const
×
2450
{
2451
        return numberIsolatedTrails;
×
2452
}
2453

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

2459
        if (getFlagIsolatedTrails())
×
2460
                recreateTrails();
×
2461

2462
        emit numberIsolatedTrailsChanged(numberIsolatedTrails);
×
2463
}
×
2464

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

2476
bool SolarSystem::getFlagIsolatedOrbits() const
×
2477
{
2478
        return flagIsolatedOrbits;
×
2479
}
2480

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

2492
bool SolarSystem::getFlagPlanetsOrbitsOnly() const
×
2493
{
2494
        return flagPlanetsOrbitsOnly;
×
2495
}
2496

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

2507
Vec3f SolarSystem::getLabelsColor(void) const
×
2508
{
2509
        return Planet::getLabelColor();
×
2510
}
2511

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

2522
Vec3f SolarSystem::getOrbitsColor(void) const
×
2523
{
2524
        return Planet::getOrbitColor();
×
2525
}
2526

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

2536
Vec3f SolarSystem::getMajorPlanetsOrbitsColor(void) const
×
2537
{
2538
        return Planet::getMajorPlanetOrbitColor();
×
2539
}
2540

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

2550
Vec3f SolarSystem::getMinorPlanetsOrbitsColor(void) const
×
2551
{
2552
        return Planet::getMinorPlanetOrbitColor();
×
2553
}
2554

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

2564
Vec3f SolarSystem::getDwarfPlanetsOrbitsColor(void) const
×
2565
{
2566
        return Planet::getDwarfPlanetOrbitColor();
×
2567
}
2568

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

2578
Vec3f SolarSystem::getMoonsOrbitsColor(void) const
×
2579
{
2580
        return Planet::getMoonOrbitColor();
×
2581
}
2582

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

2592
Vec3f SolarSystem::getCubewanosOrbitsColor(void) const
×
2593
{
2594
        return Planet::getCubewanoOrbitColor();
×
2595
}
2596

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

2606
Vec3f SolarSystem::getPlutinosOrbitsColor(void) const
×
2607
{
2608
        return Planet::getPlutinoOrbitColor();
×
2609
}
2610

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

2620
Vec3f SolarSystem::getScatteredDiskObjectsOrbitsColor(void) const
×
2621
{
2622
        return Planet::getScatteredDiscObjectOrbitColor();
×
2623
}
2624

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

2634
Vec3f SolarSystem::getOortCloudObjectsOrbitsColor(void) const
×
2635
{
2636
        return Planet::getOortCloudObjectOrbitColor();
×
2637
}
2638

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

2648
Vec3f SolarSystem::getCometsOrbitsColor(void) const
×
2649
{
2650
        return Planet::getCometOrbitColor();
×
2651
}
2652

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

2662
Vec3f SolarSystem::getSednoidsOrbitsColor(void) const
×
2663
{
2664
        return Planet::getSednoidOrbitColor();
×
2665
}
2666

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

2676
Vec3f SolarSystem::getInterstellarOrbitsColor(void) const
×
2677
{
2678
        return Planet::getInterstellarOrbitColor();
×
2679
}
2680

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

2690
Vec3f SolarSystem::getMercuryOrbitColor(void) const
×
2691
{
2692
        return Planet::getMercuryOrbitColor();
×
2693
}
2694

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

2704
Vec3f SolarSystem::getVenusOrbitColor(void) const
×
2705
{
2706
        return Planet::getVenusOrbitColor();
×
2707
}
2708

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

2718
Vec3f SolarSystem::getEarthOrbitColor(void) const
×
2719
{
2720
        return Planet::getEarthOrbitColor();
×
2721
}
2722

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

2732
Vec3f SolarSystem::getMarsOrbitColor(void) const
×
2733
{
2734
        return Planet::getMarsOrbitColor();
×
2735
}
2736

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

2746
Vec3f SolarSystem::getJupiterOrbitColor(void) const
×
2747
{
2748
        return Planet::getJupiterOrbitColor();
×
2749
}
2750

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

2760
Vec3f SolarSystem::getSaturnOrbitColor(void) const
×
2761
{
2762
        return Planet::getSaturnOrbitColor();
×
2763
}
2764

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

2774
Vec3f SolarSystem::getUranusOrbitColor(void) const
×
2775
{
2776
        return Planet::getUranusOrbitColor();
×
2777
}
2778

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

2788
Vec3f SolarSystem::getNeptuneOrbitColor(void) const
×
2789
{
2790
        return Planet::getNeptuneOrbitColor();
×
2791
}
2792

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

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

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

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

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

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

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

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

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

2911
// Set selected planets by englishName
2912
void SolarSystem::setSelected(const QString& englishName)
×
2913
{
2914
        setSelected(searchByEnglishName(englishName));
×
2915
}
×
2916

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

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

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

2942

2943
// 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.
2944
void SolarSystem::reloadPlanets()
×
2945
{
2946
        // Save flag states
2947
        const bool flagScaleMoon = getFlagMoonScale();
×
2948
        const double moonScale = getMoonScale();
×
2949
        const bool flagScaleMinorBodies=getFlagMinorBodyScale();
×
2950
        const double minorScale= getMinorBodyScale();
×
2951
        const bool flagPlanets = getFlagPlanets();
×
2952
        const bool flagHints = getFlagHints();
×
2953
        const bool flagLabels = getFlagLabels();
×
2954
        const bool flagOrbits = getFlagOrbits();
×
2955
        const bool flagNative = getFlagNativePlanetNames();
×
2956
        bool hasSelection = false;
×
2957

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

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

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

2982
        sun.clear();
×
2983
        moon.clear();
×
2984
        earth.clear();
×
2985
        Planet::texEarthShadow.clear(); //Loaded in loadPlanets()
×
2986

2987
        delete allTrails;
×
2988
        allTrails = Q_NULLPTR;
×
2989

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

2998
        // Also delete Comet textures (loaded in loadPlanets()
2999
        Comet::tailTexture.clear();
×
3000
        Comet::comaTexture.clear();
×
3001

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

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

3023
        // Restore translations
3024
        updateI18n();
×
3025

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

3033
        emit solarSystemDataReloaded();
×
3034
}
×
3035

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

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

3049
void SolarSystem::setFlagDrawMoonHalo(bool b)
×
3050
{
3051
        Planet::drawMoonHalo=b;
×
3052
        emit flagDrawMoonHaloChanged(b);
×
3053
}
×
3054

3055
bool SolarSystem::getFlagDrawMoonHalo() const
×
3056
{
3057
        return Planet::drawMoonHalo;
×
3058
}
3059

3060
void SolarSystem::setFlagDrawSunHalo(bool b)
×
3061
{
3062
        Planet::drawSunHalo=b;
×
3063
        emit flagDrawSunHaloChanged(b);
×
3064
}
×
3065

3066
bool SolarSystem::getFlagDrawSunHalo() const
×
3067
{
3068
        return Planet::drawSunHalo;
×
3069
}
3070

3071
void SolarSystem::setFlagPermanentOrbits(bool b)
×
3072
{
3073
        Planet::permanentDrawingOrbits=b;
×
3074
        emit flagPermanentOrbitsChanged(b);
×
3075
}
×
3076

3077
bool SolarSystem::getFlagPermanentOrbits() const
×
3078
{
3079
        return Planet::permanentDrawingOrbits;
×
3080
}
3081

3082
void SolarSystem::setOrbitsThickness(int v)
×
3083
{
3084
        Planet::orbitsThickness=v;
×
3085
        emit orbitsThicknessChanged(v);
×
3086
}
×
3087

3088
int SolarSystem::getOrbitsThickness() const
×
3089
{
3090
        return Planet::orbitsThickness;
×
3091
}
3092

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

3101
int SolarSystem::getGrsLongitude() const
×
3102
{
3103
        return static_cast<int>(RotationElements::grsLongitude);
×
3104
}
3105

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

3114
double SolarSystem::getGrsDrift() const
×
3115
{
3116
        return RotationElements::grsDrift;
×
3117
}
3118

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

3127
double SolarSystem::getGrsJD()
×
3128
{
3129
        return RotationElements::grsJD;
×
3130
}
3131

3132
void SolarSystem::setFlagEarthShadowEnlargementDanjon(bool b)
×
3133
{
3134
        earthShadowEnlargementDanjon=b;
×
3135
        emit earthShadowEnlargementDanjonChanged(b);
×
3136
}
×
3137

3138
bool SolarSystem::getFlagEarthShadowEnlargementDanjon() const
×
3139
{
3140
        return earthShadowEnlargementDanjon;
×
3141
}
3142

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

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

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

3179
        double final_illumination = 1.0;
×
3180

3181
        for (const auto& planet : systemPlanets)
×
3182
        {
3183
                if(planet == sun || planet == core->getCurrentPlanet())
×
3184
                        continue;
×
3185

3186
                Mat4d trans;
×
3187
                planet->computeModelMatrix(trans, true);
×
3188

3189
                const Vec3d C = trans * Vec3d(0., 0., 0.);
×
3190
                const double radius = planet->getEquatorialRadius();
×
3191

3192
                Vec3d v1 = Lp - P3;
×
3193
                Vec3d v2 = C - P3;
×
3194
                const double L = v1.norm();
×
3195
                const double l = v2.norm();
×
3196
                v1 /= L;
×
3197
                v2 /= l;
×
3198

3199
                const double R = RS / L;
×
3200
                const double r = radius / l;
×
3201
                const double d = ( v1 - v2 ).norm();
×
3202
                double illumination;
3203

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

3220
                        const double alpha = std::acos(x / R);
×
3221
                        const double beta = std::acos((d - x) / r);
×
3222

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

3227
                        illumination = 1.0 - (AR + Ar) / AS;
×
3228
                }
3229

3230
                if(illumination < final_illumination)
×
3231
                {
3232
                        final_illumination = illumination;
×
3233
                        p = planet;
×
3234
                }
3235
        }
3236

3237
        return QPair<double, PlanetP>(final_illumination, p);
×
3238
}
×
3239

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

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

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

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

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