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

Stellarium / stellarium / 5770622832

pending completion
5770622832

Pull #3348

github

gzotti
Fixed a logic error introduced by previous edit.
Pull Request #3348: Fix: orbit details

58 of 58 new or added lines in 5 files covered. (100.0%)

14813 of 124420 relevant lines covered (11.91%)

27935.46 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
        , flagOrbitsWithMoons(false)
×
92
        , ephemerisMarkersDisplayed(true)
×
93
        , ephemerisDatesDisplayed(false)
×
94
        , ephemerisMagnitudesDisplayed(false)
×
95
        , ephemerisHorizontalCoordinates(false)
×
96
        , ephemerisLineDisplayed(false)
×
97
        , ephemerisAlwaysOn(false)
×
98
        , ephemerisNow(false)
×
99
        , ephemerisLineThickness(1)
×
100
        , ephemerisSkipDataDisplayed(false)
×
101
        , ephemerisSkipMarkersDisplayed(false)
×
102
        , ephemerisDataStep(1)
×
103
        , ephemerisDataLimit(1)
×
104
        , ephemerisSmartDatesDisplayed(true)
×
105
        , ephemerisScaleMarkersDisplayed(false)
×
106
        , ephemerisGenericMarkerColor(Vec3f(1.0f, 1.0f, 0.0f))
×
107
        , ephemerisSecondaryMarkerColor(Vec3f(0.7f, 0.7f, 1.0f))
×
108
        , ephemerisSelectedMarkerColor(Vec3f(1.0f, 0.7f, 0.0f))
×
109
        , ephemerisMercuryMarkerColor(Vec3f(1.0f, 1.0f, 0.0f))
×
110
        , ephemerisVenusMarkerColor(Vec3f(1.0f, 1.0f, 1.0f))
×
111
        , ephemerisMarsMarkerColor(Vec3f(1.0f, 0.0f, 0.0f))
×
112
        , ephemerisJupiterMarkerColor(Vec3f(0.3f, 1.0f, 1.0f))
×
113
        , ephemerisSaturnMarkerColor(Vec3f(0.0f, 1.0f, 0.0f))
×
114
        , allTrails(Q_NULLPTR)
×
115
        , conf(StelApp::getInstance().getSettings())
×
116
{
117
        planetNameFont.setPixelSize(StelApp::getInstance().getScreenFontSize());
×
118
        connect(&StelApp::getInstance(), SIGNAL(screenFontSizeChanged(int)), this, SLOT(setFontSize(int)));
×
119
        setObjectName("SolarSystem");
×
120
        connect(this, SIGNAL(flagOrbitsChanged(bool)),            this, SLOT(reconfigureOrbits()));
×
121
        connect(this, SIGNAL(flagPlanetsOrbitsOnlyChanged(bool)), this, SLOT(reconfigureOrbits()));
×
122
        connect(this, SIGNAL(flagIsolatedOrbitsChanged(bool)),    this, SLOT(reconfigureOrbits()));
×
123
        connect(this, SIGNAL(flagOrbitsWithMoonsChanged(bool)),   this, SLOT(reconfigureOrbits()));
×
124
}
×
125

126
void SolarSystem::setFontSize(int newFontSize)
×
127
{
128
        planetNameFont.setPixelSize(newFontSize);
×
129
}
×
130

131
SolarSystem::~SolarSystem()
×
132
{
133
        // release selected:
134
        selected.clear();
×
135
        selectedSSO.clear();
×
136
        for (auto* orb : qAsConst(orbits))
×
137
        {
138
                delete orb;
×
139
                orb = Q_NULLPTR;
×
140
        }
141
        sun.clear();
×
142
        moon.clear();
×
143
        earth.clear();
×
144
        Planet::hintCircleTex.clear();
×
145
        Planet::texEarthShadow.clear();
×
146

147
        texEphemerisMarker.clear();
×
148
        texEphemerisCometMarker.clear();
×
149
        texEphemerisNowMarker.clear();
×
150
        texPointer.clear();
×
151

152
        delete allTrails;
×
153
        allTrails = Q_NULLPTR;
×
154

155
        // Get rid of circular reference between the shared pointers which prevent proper destruction of the Planet objects.
156
        for (const auto& p : qAsConst(systemPlanets))
×
157
        {
158
                p->satellites.clear();
×
159
        }
160

161
        //delete comet textures created in loadPlanets
162
        Comet::comaTexture.clear();
×
163
        Comet::tailTexture.clear();
×
164

165
        //deinit of SolarSystem is NOT called at app end automatically
166
        SolarSystem::deinit();
×
167
}
×
168

169
/*************************************************************************
170
 Re-implementation of the getCallOrder method
171
*************************************************************************/
172
double SolarSystem::getCallOrder(StelModuleActionName actionName) const
×
173
{
174
        if (actionName==StelModule::ActionDraw)
×
175
                return StelApp::getInstance().getModuleMgr().getModule("StarMgr")->getCallOrder(actionName)+10;
×
176
        return 0;
×
177
}
178

179
// Init and load the solar system data
180
void SolarSystem::init()
×
181
{
182
        Q_ASSERT(conf);
×
183

184
        Planet::init();
×
185
        loadPlanets();        // Load planets data
×
186

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

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

226
        // Settings for calculation of position of Great Red Spot on Jupiter
227
        setGrsLongitude(conf->value("astro/grs_longitude", 216).toInt());
×
228
        setGrsDrift(conf->value("astro/grs_drift", 15.).toDouble());
×
229
        setGrsJD(conf->value("astro/grs_jd", 2456901.5).toDouble());
×
230

231
        setFlagEarthShadowEnlargementDanjon(conf->value("astro/shadow_enlargement_danjon", false).toBool());
×
232
        setFlagPermanentSolarCorona(conf->value("viewing/flag_draw_sun_corona", true).toBool());
×
233

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

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

283
        setOrbitsThickness(conf->value("astro/object_orbits_thickness", 1).toInt());
×
284
        setTrailsThickness(conf->value("astro/object_trails_thickness", 1).toInt());
×
285
        recreateTrails();
×
286
        setFlagTrails(conf->value("astro/flag_object_trails", false).toBool());
×
287

288
        StelObjectMgr *objectManager = GETSTELMODULE(StelObjectMgr);
×
289
        objectManager->registerStelObjectMgr(this);
×
290
        connect(objectManager, SIGNAL(selectedObjectChanged(StelModule::StelModuleSelectAction)),
×
291
                this, SLOT(selectedObjectChange(StelModule::StelModuleSelectAction)));
292

293
        texPointer = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/pointeur4.png");
×
294
        texEphemerisMarker = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/disk.png");
×
295
        texEphemerisNowMarker = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/gear.png");
×
296
        texEphemerisCometMarker = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/cometIcon.png");
×
297
        Planet::hintCircleTex = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/planet-indicator.png");
×
298
        
299
        StelApp *app = &StelApp::getInstance();
×
300
        connect(app, SIGNAL(languageChanged()), this, SLOT(updateI18n()));
×
301
        connect(&app->getSkyCultureMgr(), SIGNAL(currentSkyCultureChanged(QString)), this, SLOT(updateSkyCulture(QString)));
×
302
        connect(&StelMainView::getInstance(), SIGNAL(reloadShadersRequested()), this, SLOT(reloadShaders()));
×
303
        StelCore *core = app->getCore();
×
304
        connect(core, SIGNAL(locationChanged(StelLocation)), this, SLOT(recreateTrails()));
×
305
        connect(core, SIGNAL(dateChangedForTrails()), this, SLOT(recreateTrails()));
×
306

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

322
        connect(StelApp::getInstance().getModule("HipsMgr"), SIGNAL(gotNewSurvey(HipsSurveyP)),
×
323
                        this, SLOT(onNewSurvey(HipsSurveyP)));
324

325
        // Fill ephemeris dates
326
        connect(this, SIGNAL(requestEphemerisVisualization()), this, SLOT(fillEphemerisDates()));
×
327
        connect(this, SIGNAL(ephemerisDataStepChanged(int)), this, SLOT(fillEphemerisDates()));
×
328
        connect(this, SIGNAL(ephemerisSkipDataChanged(bool)), this, SLOT(fillEphemerisDates()));
×
329
        connect(this, SIGNAL(ephemerisSkipMarkersChanged(bool)), this, SLOT(fillEphemerisDates()));
×
330
        connect(this, SIGNAL(ephemerisSmartDatesChanged(bool)), this, SLOT(fillEphemerisDates()));
×
331
}
×
332

333
void SolarSystem::deinit()
×
334
{
335
        Planet::deinitShader();
×
336
        Planet::deinitFBO();
×
337
}
×
338

339
void SolarSystem::resetTextures(const QString &planetName)
×
340
{
341
        if (planetName.isEmpty())
×
342
        {
343
                for (const auto& p : qAsConst(systemPlanets))
×
344
                {
345
                        p->resetTextures();
×
346
                }
347
        }
348
        else
349
        {
350
                PlanetP planet = searchByEnglishName(planetName);
×
351
                if (!planet.isNull())
×
352
                        planet->resetTextures();
×
353
        }
×
354
}
×
355

356
void SolarSystem::setTextureForPlanet(const QString& planetName, const QString& texName)
×
357
{
358
        PlanetP planet = searchByEnglishName(planetName);
×
359
        if (!planet.isNull())
×
360
                planet->replaceTexture(texName);
×
361
        else
362
                qWarning() << "The planet" << planetName << "was not found. Please check the name.";
×
363
}
×
364

365
void SolarSystem::recreateTrails()
×
366
{
367
        // Create a trail group containing all the planets orbiting the sun (not including satellites)
368
        if (allTrails!=Q_NULLPTR)
×
369
                delete allTrails;
×
370
        allTrails = new TrailGroup(maxTrailTimeExtent * 365.f, maxTrailPoints);
×
371

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

404

405
void SolarSystem::updateSkyCulture(const QString& skyCultureDir)
×
406
{
407
        planetNativeNamesMap.clear();
×
408
        planetNativeNamesMeaningMap.clear();
×
409

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

412
        if (namesFile.isEmpty())
×
413
        {
414
                for (const auto& p : qAsConst(systemPlanets))
×
415
                {
416
                        if (p->getPlanetType()==Planet::isPlanet || p->getPlanetType()==Planet::isMoon || p->getPlanetType()==Planet::isStar)
×
417
                        {
418
                                p->setNativeName("");
×
419
                                p->setNativeNameMeaning("");
×
420
                        }
421
                }
422
                updateI18n();
×
423
                return;
×
424
        }
425

426
        // Open file
427
        QFile planetNamesFile(namesFile);
×
428
        if (!planetNamesFile.open(QIODevice::ReadOnly | QIODevice::Text))
×
429
        {
430
                qDebug() << " Cannot open file" << QDir::toNativeSeparators(namesFile);
×
431
                return;
×
432
        }
433

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

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

442
        QString record, planetId, nativeName, nativeNameMeaning;
×
443

444
        // keep track of how many records we processed.
445
        int totalRecords=0;
×
446
        int readOk=0;
×
447
        int lineNumber=0;
×
448
        while (!planetNamesFile.atEnd())
×
449
        {
450
                record = QString::fromUtf8(planetNamesFile.readLine());
×
451
                lineNumber++;
×
452

453
                // Skip comments
454
                if (commentRx.match(record).hasMatch())
×
455
                        continue;
×
456

457
                totalRecords++;
×
458

459
                QRegularExpressionMatch match=recRx.match(record);
×
460
                if (!match.hasMatch())
×
461
                {
462
                        qWarning() << "ERROR - cannot parse record at line" << lineNumber << "in planet names file" << QDir::toNativeSeparators(namesFile);
×
463
                }
464
                else
465
                {
466
                        planetId          = match.captured(1).trimmed();
×
467
                        nativeName        = match.captured(2).trimmed();
×
468
                        nativeNameMeaning = match.captured(3).trimmed();
×
469
                        planetNativeNamesMap[planetId] = nativeName;
×
470
                        planetNativeNamesMeaningMap[planetId] = nativeNameMeaning;
×
471
                        readOk++;
×
472
                }
473
        }
×
474
        planetNamesFile.close();
×
475
        qDebug() << "Loaded" << readOk << "/" << totalRecords << "native names of planets";
×
476

477
        for (const auto& p : qAsConst(systemPlanets))
×
478
        {
479
                if (p->getPlanetType()==Planet::isPlanet || p->getPlanetType()==Planet::isMoon || p->getPlanetType()==Planet::isStar)
×
480
                {
481
                        p->setNativeName(planetNativeNamesMap[p->getEnglishName()]);
×
482
                        p->setNativeNameMeaning(planetNativeNamesMeaningMap[p->getEnglishName()]);
×
483
                }
484
        }
485

486
        updateI18n();
×
487
}
×
488

489
void SolarSystem::reloadShaders()
×
490
{
491
        Planet::deinitShader();
×
492
        Planet::initShader();
×
493
}
×
494

495
void SolarSystem::drawPointer(const StelCore* core)
×
496
{
497
        const StelProjectorP prj = core->getProjection(StelCore::FrameJ2000);
×
498

499
        const QList<StelObjectP> newSelected = GETSTELMODULE(StelObjectMgr)->getSelectedObject("Planet");
×
500
        if (!newSelected.empty())
×
501
        {
502
                const StelObjectP obj = newSelected[0];
×
503
                Vec3d pos=obj->getJ2000EquatorialPos(core);
×
504

505
                Vec3f screenpos;
×
506
                // Compute 2D pos and return if outside screen
507
                if (!prj->project(pos, screenpos))
×
508
                        return;
×
509

510
                StelPainter sPainter(prj);
×
511
                sPainter.setColor(getPointerColor());
×
512

513
                float screenSize = static_cast<float>(obj->getAngularRadius(core))*prj->getPixelPerRadAtCenter()*M_PI_180f*2.f;
×
514
                
515
                const float scale = static_cast<float>(prj->getDevicePixelsPerPixel())*StelApp::getInstance().getGlobalScalingRatio();
×
516
                screenSize+= scale * (45.f + 10.f*std::sin(2.f * static_cast<float>(StelApp::getInstance().getAnimationTime())));
×
517

518
                texPointer->bind();
×
519

520
                sPainter.setBlending(true);
×
521

522
                screenSize*=0.5f;
×
523
                const float angleBase = static_cast<float>(StelApp::getInstance().getAnimationTime()) * 10;
×
524
                // We draw 4 instances of the sprite at the corners of the pointer
525
                for (int i = 0; i < 4; ++i)
×
526
                {
527
                        const float angle = angleBase + i * 90;
×
528
                        const float x = screenpos[0] + screenSize * cos(angle * M_PI_180f);
×
529
                        const float y = screenpos[1] + screenSize * sin(angle * M_PI_180f);
×
530
                        sPainter.drawSprite2dMode(x, y, 10, angle);
×
531
                }
532
        }
×
533
}
×
534

535
void keplerOrbitPosFunc(double jd,double xyz[3], double xyzdot[3], void* orbitPtr)
×
536
{
537
        static_cast<KeplerOrbit*>(orbitPtr)->positionAtTimevInVSOP87Coordinates(jd, xyz);
×
538
        static_cast<KeplerOrbit*>(orbitPtr)->getVelocity(xyzdot);
×
539
}
×
540

541
void gimbalOrbitPosFunc(double jd,double xyz[3], double xyzdot[3], void* orbitPtr)
×
542
{
543
        static_cast<GimbalOrbit*>(orbitPtr)->positionAtTimevInVSOP87Coordinates(jd, xyz);
×
544
        static_cast<GimbalOrbit*>(orbitPtr)->getVelocity(xyzdot);
×
545
}
×
546

547
// Init and load the solar system data (2 files)
548
void SolarSystem::loadPlanets()
×
549
{
550
        minorBodies.clear();
×
551
        systemMinorBodies.clear();
×
552
        qDebug() << "Loading Solar System data (1: planets and moons) ...";
×
553
        QString solarSystemFile = StelFileMgr::findFile("data/ssystem_major.ini");
×
554
        if (solarSystemFile.isEmpty())
×
555
        {
556
                qWarning() << "ERROR while loading ssystem_major.ini (unable to find data/ssystem_major.ini):" << StelUtils::getEndLineChar();
×
557
                return;
×
558
        }
559

560
        if (!loadPlanets(solarSystemFile))
×
561
        {
562
                qWarning() << "ERROR while loading ssystem_major.ini:" << StelUtils::getEndLineChar();
×
563
                return;
×
564
        }
565

566
        qDebug() << "Loading Solar System data (2: minor bodies) ...";
×
567
        QStringList solarSystemFiles = StelFileMgr::findFileInAllPaths("data/ssystem_minor.ini");
×
568
        if (solarSystemFiles.isEmpty())
×
569
        {
570
                qWarning() << "ERROR while loading ssystem_minor.ini (unable to find data/ssystem_minor.ini):" << StelUtils::getEndLineChar();
×
571
                return;
×
572
        }
573

574
        for (const auto& solarSystemFile : qAsConst(solarSystemFiles))
×
575
        {
576
                if (loadPlanets(solarSystemFile))
×
577
                {
578
                        qDebug() << "File ssystem_minor.ini is loaded successfully...";
×
579
                        break;
×
580
                }
581
                else
582
                {
583
//                        sun.clear();
584
//                        moon.clear();
585
//                        earth.clear();
586
                        //qCritical() << "We should not be here!";
587

588
                        qDebug() << "Removing minor bodies";
×
589
                        for (const auto& p : qAsConst(systemPlanets))
×
590
                        {
591
                                // We can only delete minor objects now!
592
                                if (p->pType >= Planet::isAsteroid)
×
593
                                {
594
                                        p->satellites.clear();
×
595
                                }
596
                        }                        
597
                        systemPlanets.clear();                        
×
598
                        //Memory leak? What's the proper way of cleaning shared pointers?
599

600
                        // TODO: 0.16pre what about the orbits list?
601

602
                        //If the file is in the user data directory, rename it:
603
                        if (solarSystemFile.contains(StelFileMgr::getUserDir()))
×
604
                        {
605
                                QString newName = QString("%1/data/ssystem_minor-%2.ini").arg(StelFileMgr::getUserDir(), QDateTime::currentDateTime().toString("yyyyMMddThhmmss"));
×
606
                                if (QFile::rename(solarSystemFile, newName))
×
607
                                        qWarning() << "Invalid Solar System file" << QDir::toNativeSeparators(solarSystemFile) << "has been renamed to" << QDir::toNativeSeparators(newName);
×
608
                                else
609
                                {
610
                                        qWarning() << "Invalid Solar System file" << QDir::toNativeSeparators(solarSystemFile) << "cannot be removed!";
×
611
                                        qWarning() << "Please either delete it, rename it or move it elsewhere.";
×
612
                                }
613
                        }
×
614
                }
615
        }
616

617
        shadowPlanetCount = 0;
×
618

619
        for (const auto& planet : qAsConst(systemPlanets))
×
620
                if(planet->parent != sun || !planet->satellites.isEmpty())
×
621
                        shadowPlanetCount++;
×
622
}
×
623

624
unsigned char SolarSystem::BvToColorIndex(double bV)
×
625
{
626
        const double dBV = qBound(-500., static_cast<double>(bV)*1000.0, 3499.);
×
627
        return static_cast<unsigned char>(floor(0.5+127.0*((500.0+dBV)/4000.0)));
×
628
}
629

630
bool SolarSystem::loadPlanets(const QString& filePath)
×
631
{
632
        StelSkyDrawer* skyDrawer = StelApp::getInstance().getCore()->getSkyDrawer();
×
633
        qDebug().noquote() << "Loading from:"  << filePath;
×
634
        QSettings pd(filePath, StelIniFormat);
×
635
        if (pd.status() != QSettings::NoError)
×
636
        {
637
                qWarning().noquote() << "ERROR while parsing" << QDir::toNativeSeparators(filePath);
×
638
                return false;
×
639
        }
640

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

673
        // Stage 1 (as described above).
674
        QMap<QString, QString> secNameMap;
×
675
        QMap<QString, QString> parentMap;
×
676
        QStringList sections = pd.childGroups();
×
677
        // qDebug() << "Stage 1: load ini file with" << sections.size() << "entries: "<< sections;
678
        for (int i=0; i<sections.size(); ++i)
×
679
        {
680
                const QString secname = sections.at(i);
×
681
                const QString englishName = pd.value(secname+"/name").toString();
×
682
                const QString strParent = pd.value(secname+"/parent", "Sun").toString();
×
683
                secNameMap[englishName] = secname;
×
684
                if (strParent!="none" && !strParent.isEmpty() && !englishName.isEmpty())
×
685
                {
686
                        parentMap[englishName] = strParent;
×
687
                        // qDebug() << "parentmap[" << englishName << "] = " << strParent;
688
                }
689
        }
×
690

691
        // Stage 2a (as described above).
692
        QMultiMap<int, QString> depLevelMap;
×
693
        for (int i=0; i<sections.size(); ++i)
×
694
        {
695
                const QString englishName = pd.value(sections.at(i)+"/name").toString();
×
696

697
                // follow dependencies, incrementing level when we have one
698
                // till we run out.
699
                QString p=englishName;
×
700
                int level = 0;
×
701
                while(parentMap.contains(p) && parentMap[p]!="none")
×
702
                {
703
                        level++;
×
704
                        p = parentMap[p];
×
705
                }
706

707
                depLevelMap.insert(level, secNameMap[englishName]);
×
708
                // qDebug() << "2a: Level" << level << "secNameMap[" << englishName << "]="<< secNameMap[englishName];
709
        }
×
710

711
        // Stage 2b (as described above).
712
        // qDebug() << "Stage 2b:";
713
        QStringList orderedSections;
×
714
#if (QT_VERSION>=QT_VERSION_CHECK(6,0,0))
715
        QMultiMapIterator<int, QString> levelMapIt(depLevelMap);
716
#else
717
        QMapIterator<int, QString> levelMapIt(depLevelMap);
×
718
#endif
719
        while(levelMapIt.hasNext())
×
720
        {
721
                levelMapIt.next();
×
722
                orderedSections << levelMapIt.value();
×
723
        }
724
        // qDebug() << orderedSections;
725

726
        // Stage 3 (as described above).
727
        int readOk=0;
×
728
        //int totalPlanets=0;
729

730
        // qDebug() << "Adding " << orderedSections.size() << "objects...";
731
        for (int i = 0;i<orderedSections.size();++i)
×
732
        {
733
                // qDebug() << "Processing entry" << orderedSections.at(i);
734

735
                //totalPlanets++;
736
                const QString secname = orderedSections.at(i);
×
737
                const QString englishName = pd.value(secname+"/name").toString().simplified();
×
738
                const double bV = pd.value(secname+"/color_index_bv", 99.).toDouble();
×
739
                const QString strParent = pd.value(secname+"/parent", "Sun").toString(); // Obvious default, keep file entries simple.
×
740
                PlanetP parent;
×
741
                if (strParent!="none")
×
742
                {
743
                        // Look in the other planets the one named with strParent
744
                        for (const auto& p : qAsConst(systemPlanets))
×
745
                        {
746
                                if (p->getCommonEnglishName()==strParent)
×
747
                                {
748
                                        parent = p;
×
749
                                        break;
×
750
                                }
751
                        }
752
                        if (parent.isNull())
×
753
                        {
754
                                qWarning().noquote().nospace() << "ERROR: can't find parent solar system body for " << englishName << ". Skipping.";
×
755
                                //abort();
756
                                continue;
×
757
                        }
758
                }
759
                Q_ASSERT(parent || englishName=="Sun");
×
760

761
                const QString coordFuncName = pd.value(secname+"/coord_func", "kepler_orbit").toString(); // 0.20: new default for all non *_special.
×
762
                // qDebug() << "englishName:" << englishName << ", parent:" << strParent <<  ", coord_func:" << coordFuncName;
763
                posFuncType posfunc=Q_NULLPTR;
×
764
                Orbit* orbitPtr=Q_NULLPTR;
×
765
                OsculatingFunctType *osculatingFunc = Q_NULLPTR;
×
766
                bool closeOrbit = true;
×
767
                double semi_major_axis=0; // used again below.
×
768
                const QString type = pd.value(secname+"/type").toString();
×
769

770

771
#ifdef USE_GIMBAL_ORBIT
772
                // undefine the flag in Orbit.h to disable and use the old, static observer solution (on an infinitely slow KeplerOrbit)
773
                // Note that for now we ignore any orbit-related config values except orbit_SemiMajorAxis from the ini file.
774
                if (type=="observer")
×
775
                {
776
                        double unit = 1; // AU
×
777
                        double defaultSemiMajorAxis = 1;
×
778
                        if (strParent!="Sun")
×
779
                        {
780
                                unit /= AU;  // Planet moons have distances given in km in the .ini file! But all further computation done in AU.
×
781
                                defaultSemiMajorAxis *= AU;
×
782
                        }
783
                        semi_major_axis = pd.value(secname+"/orbit_SemiMajorAxis", defaultSemiMajorAxis).toDouble() * unit;
×
784
                        // Create a pseudo orbit that allows interaction with keyboard
785
                        GimbalOrbit *orb = new GimbalOrbit(semi_major_axis, 0.*M_PI_180, 45.*M_PI_180); // [Over mid-north latitude]
×
786
                        orb->setMinDistance(parent->getEquatorialRadius()*1.5);
×
787
                        orbits.push_back(orb);
×
788

789
                        orbitPtr = orb;
×
790
                        posfunc = &gimbalOrbitPosFunc;
×
791
                }
792
                else
793
#endif
794
                if ((coordFuncName=="kepler_orbit") || (coordFuncName=="comet_orbit") || (coordFuncName=="ell_orbit")) // ell_orbit used for planet moons. TBD in V1.0: remove non-kepler_orbit!
×
795
                {
796
                        // 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.
797
                        // Read the orbital elements                        
798
                        const double eccentricity = pd.value(secname+"/orbit_Eccentricity", 0.0).toDouble();
×
799
                        if (eccentricity >= 1.0) closeOrbit = false;
×
800
                        double pericenterDistance = pd.value(secname+"/orbit_PericenterDistance",-1e100).toDouble(); // AU, or km for ell_orbit!
×
801
                        if (pericenterDistance <= 0.0) {
×
802
                                semi_major_axis = pd.value(secname+"/orbit_SemiMajorAxis",-1e100).toDouble();
×
803
                                if (semi_major_axis <= -1e100) {
×
804
                                        qDebug() << "ERROR loading " << englishName
×
805
                                                 << ": you must provide orbit_PericenterDistance or orbit_SemiMajorAxis. Skipping " << englishName;
×
806
                                        continue;
×
807
                                } else {
808
                                        Q_ASSERT(eccentricity != 1.0); // parabolic orbits have no semi_major_axis
×
809
                                        pericenterDistance = semi_major_axis * (1.0-eccentricity);
×
810
                                }
811
                        } else {
812
                                semi_major_axis = (eccentricity == 1.0)
×
813
                                                                ? 0.0 // parabolic orbits have no semi_major_axis
×
814
                                                                : pericenterDistance / (1.0-eccentricity);
×
815
                        }
816
                        if (strParent!="Sun")
×
817
                                pericenterDistance /= AU;  // Planet moons have distances given in km in the .ini file! But all further computation done in AU.
×
818

819
                        double meanMotion = pd.value(secname+"/orbit_MeanMotion",-1e100).toDouble(); // degrees/day
×
820
                        if (meanMotion <= -1e100) {
×
821
                                const double period = pd.value(secname+"/orbit_Period",-1e100).toDouble();
×
822
                                if (period <= -1e100) {
×
823
                                        if (parent->getParent()) {
×
824
                                                qWarning().noquote() << "ERROR: " << englishName
×
825
                                                           << ": when the parent body is not the sun, you must provide "
×
826
                                                           << "either orbit_MeanMotion or orbit_Period";
×
827
                                        } else {
828
                                                // in case of parent=sun: use Gaussian gravitational constant for calculating meanMotion:
829
                                                meanMotion = (eccentricity == 1.0)
×
830
                                                                        ? 0.01720209895 * (1.5/pericenterDistance) * std::sqrt(0.5/pericenterDistance)  // Heafner: Fund.Eph.Comp. W / dt
×
831
                                                                        : 0.01720209895 / (fabs(semi_major_axis)*std::sqrt(fabs(semi_major_axis)));
×
832
                                        }
833
                                } else {
834
                                        meanMotion = 2.0*M_PI/period;
×
835
                                }
836
                        } else {
837
                                meanMotion *= (M_PI/180.0);
×
838
                        }
839

840
                        const double ascending_node = pd.value(secname+"/orbit_AscendingNode", 0.0).toDouble()*(M_PI/180.0);
×
841
                        double arg_of_pericenter = pd.value(secname+"/orbit_ArgOfPericenter",-1e100).toDouble();
×
842
                        double long_of_pericenter;
843
                        if (arg_of_pericenter <= -1e100) {
×
844
                                long_of_pericenter = pd.value(secname+"/orbit_LongOfPericenter", 0.0).toDouble()*(M_PI/180.0);
×
845
                                arg_of_pericenter = long_of_pericenter - ascending_node;
×
846
                        } else {
847
                                arg_of_pericenter *= (M_PI/180.0);
×
848
                                long_of_pericenter = arg_of_pericenter + ascending_node;
×
849
                        }
850

851
                        double time_at_pericenter = pd.value(secname+"/orbit_TimeAtPericenter",-1e100).toDouble();
×
852
                        // 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.
853
                        // However, the distinction is relevant to discern element sets for various valid ranges.
854
                        // Comet orbits epoch should default to T while planets or moons default to J2000.
855
                        const double epoch = pd.value(secname+"/orbit_Epoch", type=="comet" ? time_at_pericenter : J2000).toDouble();
×
856
                        if (time_at_pericenter <= -1e100) {
×
857
                                double mean_anomaly = pd.value(secname+"/orbit_MeanAnomaly",-1e100).toDouble()*(M_PI/180.0);
×
858
                                if (mean_anomaly <= -1e10) {
×
859
                                        double mean_longitude = pd.value(secname+"/orbit_MeanLongitude",-1e100).toDouble()*(M_PI/180.0);
×
860
                                        if (mean_longitude <= -1e10) {
×
861
                                                qWarning().noquote() << "ERROR: " << englishName
×
862
                                                           << ": when you do not provide orbit_TimeAtPericenter, you must provide orbit_Epoch"
×
863
                                                           << "and either one of orbit_MeanAnomaly or orbit_MeanLongitude. Skipping this object.";
×
864
                                                //abort();
865
                                                continue;
×
866
                                        } else {
867
                                                mean_anomaly = mean_longitude - long_of_pericenter;
×
868
                                        }
869
                                }
870
                                time_at_pericenter = epoch - mean_anomaly / meanMotion;
×
871
                        }
872

873
                        static const QMap<QString, double>massMap={ // masses from DE430/431
874
                                { "Sun",            1.0},
×
875
                                { "Mercury",  6023682.155592},
×
876
                                { "Venus",     408523.718658},
×
877
                                { "Earth",     332946.048834},
×
878
                                { "Mars",     3098703.590291},
×
879
                                { "Jupiter",     1047.348625},
×
880
                                { "Saturn",      3497.901768},
×
881
                                { "Uranus",     22902.981613},
×
882
                                { "Neptune",    19412.259776},
×
883
                                { "Pluto",  135836683.768617}};
×
884

885
                        // Construct orbital elements relative to the parent body. This will construct orbits for J2000 only.
886
                        // Some planet axes move very slowly, this effect could be modelled by replicating these lines
887
                        // after recomputing obliquity and node (below) in Planet::computeTransMatrix().
888
                        // The effect is negligible for several millennia, though.
889
                        // When the parent is the sun use ecliptic rather than sun equator:
890
                        const double parentRotObliquity  = parent->getParent() ? parent->getRotObliquity(J2000) : 0.0;
×
891
                        const double parent_rot_asc_node = parent->getParent() ? parent->getRotAscendingNode()  : 0.0;
×
892
                        double parent_rot_j2000_longitude = 0.0;
×
893
                        if (parent->getParent()) {
×
894
                                const double c_obl = cos(parentRotObliquity);
×
895
                                const double s_obl = sin(parentRotObliquity);
×
896
                                const double c_nod = cos(parent_rot_asc_node);
×
897
                                const double s_nod = sin(parent_rot_asc_node);
×
898
                                const Vec3d OrbitAxis0( c_nod,       s_nod,        0.0);
×
899
                                const Vec3d OrbitAxis1(-s_nod*c_obl, c_nod*c_obl,s_obl);
×
900
                                const Vec3d OrbitPole(  s_nod*s_obl,-c_nod*s_obl,c_obl);
×
901
                                const Vec3d J2000Pole(StelCore::matJ2000ToVsop87.multiplyWithoutTranslation(Vec3d(0,0,1)));
×
902
                                Vec3d J2000NodeOrigin(J2000Pole^OrbitPole);
×
903
                                J2000NodeOrigin.normalize();
×
904
                                parent_rot_j2000_longitude = atan2(J2000NodeOrigin*OrbitAxis1,J2000NodeOrigin*OrbitAxis0);
×
905
                        }
906

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

910
                        // Create a Keplerian orbit. This has been called CometOrbit before 0.20.
911
                        //qDebug() << "Creating KeplerOrbit for" << parent->englishName << "---" << englishName;
912
                        KeplerOrbit *orb = new KeplerOrbit(epoch,                  // JDE
913
                                                           pericenterDistance,     // [AU]
914
                                                           eccentricity,           // 0..>1 (>>1 for Interstellar objects)
915
                                                           inclination,            // [radians]
916
                                                           ascending_node,         // [radians]
917
                                                           arg_of_pericenter,      // [radians]
918
                                                           time_at_pericenter,     // JDE
919
                                                           orbitGoodDays,          // orbitGoodDays. 0=always good, -1=compute_half_orbit_duration
920
                                                           meanMotion,             // [radians/day]
921
                                                           parentRotObliquity,     // [radians]
922
                                                           parent_rot_asc_node,    // [radians]
923
                                                           parent_rot_j2000_longitude, // [radians]
924
                                                           1./massMap.value(parent->englishName, 1.)); // central mass [solar masses]
×
925
                        orbits.push_back(orb);
×
926

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

985
                // Create the Solar System body and add it to the list
986
                //TODO: Refactor the subclass selection to reduce duplicate code mess here,
987
                // by at least using this base class pointer and using setXXX functions instead of mega-constructors
988
                // that have to pass most of it on to the Planet class
989
                PlanetP newP;
×
990

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

998
                        Vec3f color = Vec3f(1.f, 1.f, 1.f);
×
999
                        if (bV<99.)
×
1000
                                color = skyDrawer->indexToColor(BvToColorIndex(bV))*0.75f; // see ZoneArray.cpp:L490
×
1001
                        else
1002
                                color = Vec3f(pd.value(secname+"/color", "1.0,1.0,1.0").toString());
×
1003

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

1008
                        newP = PlanetP(new MinorPlanet(englishName,
×
1009
                                                    pd.value(secname+"/radius", 1.0).toDouble()/AU,
×
1010
                                                    pd.value(secname+"/oblateness", 0.0).toDouble(),
×
1011
                                                    color, // halo color
1012
                                                    pd.value(secname+"/albedo", 0.25f).toFloat(),
×
1013
                                                    pd.value(secname+"/roughness",0.9f).toFloat(),
×
1014
                                                    pd.value(secname+"/tex_map", "nomap.png").toString(),
×
1015
                                                    pd.value(secname+"/normals_map", normalMapName).toString(),
×
1016
                                                    pd.value(secname+"/horizon_map", horizonMapName).toString(),
×
1017
                                                    pd.value(secname+"/model").toString(),
×
1018
                                                    posfunc,
1019
                                                    static_cast<KeplerOrbit*>(orbitPtr), // the KeplerOrbit object created previously
1020
                                                    osculatingFunc, // should be Q_NULLPTR
1021
                                                    closeOrbit,
1022
                                                    hidden,
1023
                                                    type));
×
1024
                        QSharedPointer<MinorPlanet> mp =  newP.dynamicCast<MinorPlanet>();
×
1025
                        //Number, IAU provisional designation
1026
                        mp->setMinorPlanetNumber(pd.value(secname+"/minor_planet_number", 0).toInt());
×
1027
                        mp->setIAUDesignation(pd.value(secname+"/iau_designation", "").toString());
×
1028

1029
                        //H-G magnitude system
1030
                        const float magnitude = pd.value(secname+"/absolute_magnitude", -99.f).toFloat();
×
1031
                        const float slope = pd.value(secname+"/slope_parameter", 0.15f).toFloat();
×
1032
                        if (magnitude > -99.f)
×
1033
                        {
1034
                                mp->setAbsoluteMagnitudeAndSlope(magnitude, qBound(0.0f, slope, 1.0f));
×
1035
                        }
1036

1037
                        mp->setColorIndexBV(static_cast<float>(bV));
×
1038
                        mp->setSpectralType(pd.value(secname+"/spec_t", "").toString(), pd.value(secname+"/spec_b", "").toString());
×
1039

1040
                        // Discovery circumstances
1041
                        QString discovererName = pd.value(secname+"/discoverer", "").toString();
×
1042
                        QString discoveryDate = pd.value(secname+"/discovery", "").toString();
×
1043
                        if (!discoveryDate.isEmpty())
×
1044
                                mp->setDiscoveryData(discoveryDate, discovererName);
×
1045

1046
                        // order of codes: date_code [P/1982 U1] - perihelion_code [1986 III] - discovery_code [1982i]
1047
                        QStringList codes = { pd.value(secname+"/date_code", "").toString(),
×
1048
                                              pd.value(secname+"/perihelion_code", "").toString(),
×
1049
                                              pd.value(secname+"/discovery_code", "").toString() };
×
1050
                        codes.removeAll("");
×
1051
                        if (codes.count()>0)
×
1052
                                mp->setExtraDesignations(codes);
×
1053

1054
                        if (semi_major_axis>0)
×
1055
                                mp->deltaJDE = 2.0*semi_major_axis*StelCore::JD_SECOND;
×
1056
                         else if ((semi_major_axis<=0.0) && (type!="interstellar object"))
×
1057
                                qWarning().noquote() << "WARNING: Minor body" << englishName << "has no semimajor axis!";
×
1058

1059
                        systemMinorBodies.push_back(newP);
×
1060
                }
×
1061
                else if (type == "comet")
×
1062
                {
1063
                        minorBodies << englishName;
×
1064
                        newP = PlanetP(new Comet(englishName,
×
1065
                                              pd.value(secname+"/radius", 1.0).toDouble()/AU,
×
1066
                                              pd.value(secname+"/oblateness", 0.0).toDouble(),
×
1067
                                              Vec3f(pd.value(secname+"/color", "1.0,1.0,1.0").toString()), // halo color
×
1068
                                              pd.value(secname+"/albedo", 0.075f).toFloat(), // assume very dark surface
×
1069
                                              pd.value(secname+"/roughness",0.9f).toFloat(),
×
1070
                                              pd.value(secname+"/outgas_intensity",0.1f).toFloat(),
×
1071
                                              pd.value(secname+"/outgas_falloff", 0.1f).toFloat(),
×
1072
                                              pd.value(secname+"/tex_map", "nomap.png").toString(),
×
1073
                                              pd.value(secname+"/model").toString(),
×
1074
                                              posfunc,
1075
                                              static_cast<KeplerOrbit*>(orbitPtr), // the KeplerOrbit object
1076
                                              osculatingFunc, // ALWAYS NULL for comets.
1077
                                              closeOrbit,
1078
                                              pd.value(secname+"/hidden", false).toBool(),
×
1079
                                              type,
1080
                                              pd.value(secname+"/dust_widthfactor", 1.5f).toFloat(),
×
1081
                                              pd.value(secname+"/dust_lengthfactor", 0.4f).toFloat(),
×
1082
                                              pd.value(secname+"/dust_brightnessfactor", 1.5f).toFloat()
×
1083
                                              ));
×
1084
                        QSharedPointer<Comet> mp = newP.dynamicCast<Comet>();
×
1085

1086
                        //g,k magnitude system
1087
                        const float magnitude = pd.value(secname+"/absolute_magnitude", -99.f).toFloat();
×
1088
                        const float slope = qBound(-5.0f, pd.value(secname+"/slope_parameter", 4.0f).toFloat(), 30.0f);
×
1089
                        if (magnitude > -99.f)
×
1090
                                        mp->setAbsoluteMagnitudeAndSlope(magnitude, slope);
×
1091

1092
                        QString iauDesignation = pd.value(secname+"/iau_designation", "").toString();
×
1093
                        if (!iauDesignation.isEmpty())
×
1094
                                mp->setIAUDesignation(iauDesignation);
×
1095
                        // order of codes: date_code [P/1982 U1] - perihelion_code [1986 III] - discovery_code [1982i]
1096
                        QStringList codes = { pd.value(secname+"/date_code", "").toString(),
×
1097
                                              pd.value(secname+"/perihelion_code", "").toString(),
×
1098
                                              pd.value(secname+"/discovery_code", "").toString() };
×
1099
                        codes.removeAll("");
×
1100
                        if (codes.count()>0)
×
1101
                                mp->setExtraDesignations(codes);
×
1102

1103
                        // Discovery circumstances
1104
                        QString discovererName = pd.value(secname+"/discoverer", "").toString();
×
1105
                        QString discoveryDate = pd.value(secname+"/discovery", "").toString();
×
1106
                        if (!discoveryDate.isEmpty())
×
1107
                                mp->setDiscoveryData(discoveryDate, discovererName);
×
1108

1109
                        systemMinorBodies.push_back(newP);
×
1110
                }
×
1111
                else // type==star|planet|moon|dwarf planet|observer|artificial
1112
                {
1113
                        //qDebug() << type;
1114
                        Q_ASSERT(type=="star" || type=="planet" || type=="moon" || type=="artificial" || type=="observer" || type=="dwarf planet"); // TBD: remove Pluto...
×
1115
                        // Set possible default name of the normal map for avoiding yin-yang shaped moon
1116
                        // phase when normal map key not exists. Example: moon_normals.png
1117
                        // Details: https://bugs.launchpad.net/stellarium/+bug/1335609                        
1118
                        newP = PlanetP(new Planet(englishName,
×
1119
                                               pd.value(secname+"/radius", 1.0).toDouble()/AU,
×
1120
                                               pd.value(secname+"/oblateness", 0.0).toDouble(),
×
1121
                                               Vec3f(pd.value(secname+"/color", "1.0,1.0,1.0").toString()), // halo color
×
1122
                                               pd.value(secname+"/albedo", 0.25f).toFloat(),
×
1123
                                               pd.value(secname+"/roughness",0.9f).toFloat(),
×
1124
                                               pd.value(secname+"/tex_map", "nomap.png").toString(),
×
1125
                                               pd.value(secname+"/normals_map", englishName.toLower().append("_normals.png")).toString(),
×
1126
                                               pd.value(secname+"/horizon_map", englishName.toLower().append("_horizon.png")).toString(),
×
1127
                                               pd.value(secname+"/model").toString(),
×
1128
                                               posfunc,
1129
                                               static_cast<KeplerOrbit*>(orbitPtr), // This remains Q_NULLPTR for the major planets, or has a KeplerOrbit for planet moons.
1130
                                               osculatingFunc,
1131
                                               closeOrbit,
1132
                                               pd.value(secname+"/hidden", false).toBool(),
×
1133
                                               pd.value(secname+"/atmosphere", false).toBool(),
×
1134
                                               pd.value(secname+"/halo", true).toBool(),
×
1135
                                               type));
×
1136
                        newP->absoluteMagnitude = pd.value(secname+"/absolute_magnitude", -99.f).toFloat();
×
1137
                        newP->massKg = pd.value(secname+"/mass_kg", 0.).toDouble();
×
1138

1139
                        // Moon designation (planet index + IAU moon number)
1140
                        QString moonDesignation = pd.value(secname+"/iau_moon_number", "").toString();
×
1141
                        if (!moonDesignation.isEmpty())
×
1142
                                newP->setIAUMoonNumber(moonDesignation);
×
1143
                        newP->setColorIndexBV(static_cast<float>(bV));
×
1144
                        // Discovery circumstances
1145
                        QString discovererName = pd.value(secname+"/discoverer", "").toString();
×
1146
                        QString discoveryDate = pd.value(secname+"/discovery", "").toString();
×
1147
                        if (!discoveryDate.isEmpty())
×
1148
                                newP->setDiscoveryData(discoveryDate, discovererName);
×
1149
                }
×
1150

1151
                if (!parent.isNull())
×
1152
                {
1153
                        parent->satellites.append(newP);
×
1154
                        newP->parent = parent;
×
1155
                }
1156
                if (secname=="earth") earth = newP;
×
1157
                if (secname=="sun") sun = newP;
×
1158
                if (secname=="moon") moon = newP;
×
1159

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

1163
                // There are two ways of defining the axis orientation:
1164
                // obliquity and ascending node, which was used by Stellarium already before 2010 (based on Celestia?).
1165
                double rotObliquity = pd.value(secname+"/rot_obliquity",0.).toDouble()*(M_PI_180);
×
1166
                double rotAscNode = pd.value(secname+"/rot_equator_ascending_node",0.).toDouble()*(M_PI_180);
×
1167
                // rot_periode given in hours (from which rotPeriod in days),
1168
                // The default is useful for many moons in bound rotation
1169
                double rotPeriod=pd.value(secname+"/rot_periode", pd.value(secname+"/orbit_Period", 1.).toDouble()*24.).toDouble()/24.;
×
1170
                double rotOffset=pd.value(secname+"/rot_rotation_offset",0.).toDouble();
×
1171

1172
                // 0.21+: Use WGCCRE planet North pole data if available
1173
                // NB: N pole for J2000 epoch as defined by IAU (NOT right hand rotation rule)
1174
                // Define only basic motion. Use special functions for more complicated axes.
1175
                const double J2000NPoleRA  = pd.value(secname+"/rot_pole_ra",  0.).toDouble()*M_PI_180;
×
1176
                const double J2000NPoleRA1 = pd.value(secname+"/rot_pole_ra1", 0.).toDouble()*M_PI_180;
×
1177
                const double J2000NPoleDE  = pd.value(secname+"/rot_pole_de",  0.).toDouble()*M_PI_180;
×
1178
                const double J2000NPoleDE1 = pd.value(secname+"/rot_pole_de1", 0.).toDouble()*M_PI_180;
×
1179
                const double J2000NPoleW0  = pd.value(secname+"/rot_pole_w0",  0.).toDouble(); // [degrees]   Basically the same idea as rot_rotation_offset, but W!=rotAngle
×
1180
                const double J2000NPoleW1  = pd.value(secname+"/rot_pole_w1",  0.).toDouble(); // [degrees/d] Basically the same idea as 360/rot_periode
×
1181
                if (fabs(J2000NPoleW1) > 0.0) // Patch possibly old period value with a more modern value.
×
1182
                {
1183
                        // this is just another expression for rotational speed.
1184
                        rotPeriod=360.0/J2000NPoleW1;
×
1185
                }
1186

1187
                // IMPORTANT: For the planet moons with orbits relative to planets' equator plane,
1188
                // re-compute the important bits from the updated axis elements.
1189
                // Reactivated to re-establish Pluto/Charon lock #153
1190
                if((J2000NPoleRA!=0.) || (J2000NPoleDE!=0.))
×
1191
                {
1192
                        // If available, recompute obliquity and AscNode from the new data.
1193
                        // Solution since 0.16: Make this once for J2000.
1194
                        // Optional (future?): Repeat this block in Planet::computeTransMatrix() for planets with moving axes and update all Moons' KeplerOrbit if required.
1195
                        Vec3d J2000NPole;
×
1196
                        StelUtils::spheToRect(J2000NPoleRA,J2000NPoleDE,J2000NPole);
×
1197

1198
                        Vec3d vsop87Pole(StelCore::matJ2000ToVsop87.multiplyWithoutTranslation(J2000NPole));
×
1199

1200
                        double lon, lat;
1201
                        StelUtils::rectToSphe(&lon, &lat, vsop87Pole);
×
1202

1203
                        rotObliquity = (M_PI_2 - lat);
×
1204
                        rotAscNode = (lon + M_PI_2);
×
1205

1206
                        //qDebug() << englishName << ": Compare these values to the older data in ssystem_major";
1207
                        //qDebug() << "\tCalculated rotational obliquity: " << rotObliquity*180./M_PI;
1208
                        //qDebug() << "\tCalculated rotational ascending node: " << rotAscNode*180./M_PI;
1209

1210
                        if (J2000NPoleW0 >0)
×
1211
                        {
1212
                                // W0 is counted from the ascending node with ICRF, but rotOffset from orbital plane.
1213
                                // Try this assumption by just counting Offset=W0+90+RA0.
1214
                                rotOffset=J2000NPoleW0 + lon*M_180_PI;
×
1215
                                //qDebug() << "\tCalculated rotational period (days // hours): " << rotPeriod << "//" << rotPeriod*24.;
1216
                                //qDebug() << "\tRotational offset (degrees): " << rotOffset;
1217
                        }
1218
                }
1219
                newP->setRotationElements(
×
1220
                        englishName,
1221
                        rotPeriod,
1222
                        rotOffset,
1223
                        pd.value(secname+"/rot_epoch", J2000).toDouble(),
×
1224
                        rotObliquity,
1225
                        rotAscNode,
1226
                        J2000NPoleRA,
1227
                        J2000NPoleRA1,
1228
                        J2000NPoleDE,
1229
                        J2000NPoleDE1,
1230
                        J2000NPoleW0,
1231
                        J2000NPoleW1);
1232
                // orbit_Period or orbit_visualization_period given in days.
1233
                // Elliptical Kepler orbits (ecc<0.9) will replace whatever is given by a value computed on the fly.
1234
                newP->setSiderealPeriod(fabs(pd.value(secname+"/orbit_Period",
×
1235
                                                      pd.value(secname+"/orbit_visualization_period" )).toDouble()));
×
1236

1237
                if (pd.contains(secname+"/tex_ring")) {
×
1238
                        const float rMin = pd.value(secname+"/ring_inner_size").toFloat()/AUf;
×
1239
                        const float rMax = pd.value(secname+"/ring_outer_size").toFloat()/AUf;
×
1240
                        Ring *r = new Ring(rMin,rMax,pd.value(secname+"/tex_ring").toString());
×
1241
                        newP->setRings(r);
×
1242
                }
1243

1244
                systemPlanets.push_back(newP);
×
1245
                readOk++;
×
1246
        }
×
1247

1248
        if (systemPlanets.isEmpty())
×
1249
        {
1250
                qWarning().noquote() << "No Solar System objects loaded from" << QDir::toNativeSeparators(filePath);
×
1251
                return false;
×
1252
        }
1253
        else
1254
                qDebug() << "Solar System has" << systemPlanets.count() << "entries.";
×
1255

1256
        // special case: load earth shadow texture
1257
        if (!Planet::texEarthShadow)
×
1258
                Planet::texEarthShadow = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/earth-shadow.png");
×
1259

1260
        // Also comets just have static textures.
1261
        if (!Comet::comaTexture)
×
1262
                Comet::comaTexture = StelApp::getInstance().getTextureManager().createTextureThread(StelFileMgr::getInstallationDir()+"/textures/cometComa.png", StelTexture::StelTextureParams(true, GL_LINEAR, GL_CLAMP_TO_EDGE));
×
1263
        //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.
1264
        if (!Comet::tailTexture)
×
1265
                Comet::tailTexture = StelApp::getInstance().getTextureManager().createTextureThread(StelFileMgr::getInstallationDir()+"/textures/cometTail.png", StelTexture::StelTextureParams(true, GL_LINEAR, GL_CLAMP_TO_EDGE));
×
1266

1267
        if (readOk>0)
×
1268
                qDebug() << "Loaded" << readOk << "Solar System bodies";
×
1269

1270
        return true;
×
1271
}
×
1272

1273
// Compute the position for every elements of the solar system.
1274
// The order is not important since the position is computed relatively to the mother body
1275
void SolarSystem::computePositions(double dateJDE, PlanetP observerPlanet)
×
1276
{
1277
        StelCore *core=StelApp::getInstance().getCore();
×
1278
        const bool withAberration=core->getUseAberration();
×
1279
        if (flagLightTravelTime) // switching off light time correction implies no aberration for the planets.
×
1280
        {
1281
                for (const auto& p : qAsConst(systemPlanets))
×
1282
                {
1283
                        p->computePosition(dateJDE, Vec3d(0.));
×
1284
                }
1285
                const Vec3d obsPosJDE=observerPlanet->getHeliocentricEclipticPos();
×
1286

1287
                // For higher accuracy, we now make two iterations of light time and aberration correction. In the final
1288
                // round, we also compute rotation data.  May fix sub-arcsecond inaccuracies, and optionally apply
1289
                // aberration in the way described in Explanatory Supplement (2013), 7.55.  For reasons unknown (See
1290
                // discussion in GH:#1626) we do not add anything for the Moon when observed from Earth!  Presumably the
1291
                // used ephemerides already provide aberration-corrected positions for the Moon?
1292
                const Vec3d aberrationPushSpeed=observerPlanet->getHeliocentricEclipticVelocity() * core->getAberrationFactor();
×
1293
                for (const auto& p : qAsConst(systemPlanets))
×
1294
                {
1295
                        //p->setExtraInfoString(StelObject::DebugAid, "");
1296
                        const auto planetPos = p->getHeliocentricEclipticPos();
×
1297
                        const double lightTimeDays = (planetPos-obsPosJDE).norm() * (AU / (SPEED_OF_LIGHT * 86400.));
×
1298
                        Vec3d aberrationPush(0.);
×
1299
                        if (withAberration && (observerPlanet->englishName!="Earth" || p->englishName!="Moon"))
×
1300
                                aberrationPush=lightTimeDays*aberrationPushSpeed;
×
1301
                        p->computePosition(dateJDE-lightTimeDays, aberrationPush);
×
1302
                }
1303
                // Extra accuracy with another round. Not sure if useful. Maybe hide behind a new property flag?
1304
                for (const auto& p : qAsConst(systemPlanets))
×
1305
                {
1306
                        //p->setExtraInfoString(StelObject::DebugAid, "");
1307
                        const auto planetPos = p->getHeliocentricEclipticPos();
×
1308
                        const double lightTimeDays = (planetPos-obsPosJDE).norm() * (AU / (SPEED_OF_LIGHT * 86400.));
×
1309
                        Vec3d aberrationPush(0.);
×
1310
                        if (withAberration && (observerPlanet->englishName!="Earth" || p->englishName!="Moon"))
×
1311
                                aberrationPush=lightTimeDays*aberrationPushSpeed;
×
1312
                        // The next call may already do nothing if the time difference to the previous round is not large enough.
1313
                        p->computePosition(dateJDE-lightTimeDays, aberrationPush);
×
1314
//                        p->setExtraInfoString(StelObject::DebugAid, QString("LightTime %1d; obsSpeed %2/%3/%4 AU/d")
1315
//                                              .arg(QString::number(lightTimeDays, 'f', 3))
1316
//                                              .arg(QString::number(aberrationPushSpeed[0], 'f', 3))
1317
//                                              .arg(QString::number(aberrationPushSpeed[0], 'f', 3))
1318
//                                              .arg(QString::number(aberrationPushSpeed[0], 'f', 3)));
1319

1320
                        const auto update = &RotationElements::updatePlanetCorrections;
×
1321
                        if      (p->englishName=="Moon")    update(dateJDE-lightTimeDays, RotationElements::EarthMoon);
×
1322
                        else if (p->englishName=="Mars")    update(dateJDE-lightTimeDays, RotationElements::Mars);
×
1323
                        else if (p->englishName=="Jupiter") update(dateJDE-lightTimeDays, RotationElements::Jupiter);
×
1324
                        else if (p->englishName=="Saturn")  update(dateJDE-lightTimeDays, RotationElements::Saturn);
×
1325
                        else if (p->englishName=="Uranus")  update(dateJDE-lightTimeDays, RotationElements::Uranus);
×
1326
                        else if (p->englishName=="Neptune") update(dateJDE-lightTimeDays, RotationElements::Neptune);
×
1327
                }
1328
        }
1329
        else
1330
        {
1331
                for (const auto& p : qAsConst(systemPlanets))
×
1332
                {
1333
                        p->setExtraInfoString(StelObject::DebugAid, "");
×
1334
                        p->computePosition(dateJDE, Vec3d(0.));
×
1335
                        const auto update = &RotationElements::updatePlanetCorrections;
×
1336
                        if      (p->englishName=="Moon")    update(dateJDE, RotationElements::EarthMoon);
×
1337
                        else if (p->englishName=="Mars")    update(dateJDE, RotationElements::Mars);
×
1338
                        else if (p->englishName=="Jupiter") update(dateJDE, RotationElements::Jupiter);
×
1339
                        else if (p->englishName=="Saturn")  update(dateJDE, RotationElements::Saturn);
×
1340
                        else if (p->englishName=="Uranus")  update(dateJDE, RotationElements::Uranus);
×
1341
                        else if (p->englishName=="Neptune") update(dateJDE, RotationElements::Neptune);
×
1342
                }
1343
        }
1344
        computeTransMatrices(dateJDE, observerPlanet->getHeliocentricEclipticPos());
×
1345
}
×
1346

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

1353
        if (flagLightTravelTime)
×
1354
        {
1355
                for (const auto& p : qAsConst(systemPlanets))
×
1356
                {
1357
                        const double light_speed_correction = (p->getHeliocentricEclipticPos()-observerPos).norm() * (AU / (SPEED_OF_LIGHT * 86400));
×
1358
                        p->computeTransMatrix(dateJD-light_speed_correction, dateJDE-light_speed_correction);
×
1359
                }
1360
        }
1361
        else
1362
        {
1363
                for (const auto& p : qAsConst(systemPlanets))
×
1364
                {
1365
                        p->computeTransMatrix(dateJD, dateJDE);
×
1366
                }
1367
        }
1368
}
×
1369

1370
// And sort them from the furthest to the closest to the observer
1371
// NOTE: std::binary_function is deprecated in C++11 and removed in C++17
1372
struct biggerDistance : public StelUtils::binary_function<PlanetP, PlanetP, bool>
1373
{
1374
        bool operator()(PlanetP p1, PlanetP p2)
×
1375
        {
1376
                return p1->getDistance() > p2->getDistance();
×
1377
        }
1378
};
1379

1380
// Draw all the elements of the solar system
1381
// We are supposed to be in heliocentric coordinate
1382
void SolarSystem::draw(StelCore* core)
×
1383
{
1384
        // AstroCalcDialog
1385
        drawEphemerisItems(core);
×
1386

1387
        if (!flagShow)
×
1388
                return;
×
1389

1390
        // Compute each Planet distance to the observer
1391
        const Vec3d obsHelioPos = core->getObserverHeliocentricEclipticPos();
×
1392

1393
        for (const auto& p : qAsConst(systemPlanets))
×
1394
        {
1395
                p->computeDistance(obsHelioPos);
×
1396
        }
1397

1398
        // And sort them from the furthest to the closest
1399
        std::sort(systemPlanets.begin(),systemPlanets.end(),biggerDistance());
×
1400

1401
        if (trailFader.getInterstate()>0.0000001f)
×
1402
        {
1403
                StelPainter sPainter(core->getProjection2d());
×
1404
                const float ppx = static_cast<float>(sPainter.getProjector()->getDevicePixelsPerPixel());
×
1405
                allTrails->setOpacity(trailFader.getInterstate());
×
1406
                if (trailsThickness>1 || ppx>1.f)
×
1407
                        sPainter.setLineWidth(trailsThickness*ppx);
×
1408
                allTrails->draw(core, &sPainter);
×
1409
                if (trailsThickness>1 || ppx>1.f)
×
1410
                        sPainter.setLineWidth(1);
×
1411
        }
×
1412

1413
        // Make some voodoo to determine when labels should be displayed
1414
        const float sdLimitMag=static_cast<float>(core->getSkyDrawer()->getLimitMagnitude());
×
1415
        const float maxMagLabel = (sdLimitMag<5.f ? sdLimitMag :
×
1416
                        5.f+(sdLimitMag-5.f)*1.2f) +(static_cast<float>(labelsAmount)-3.f)*1.2f;
×
1417

1418
        // Draw the elements
1419
        for (const auto& p : qAsConst(systemPlanets))
×
1420
        {
1421
                if ( (p->getEnglishName() != "Sun") ||
×
1422
                                ((p->getEnglishName() == "Sun") && !(core->getSkyDrawer()->getFlagDrawSunAfterAtmosphere())))
×
1423
                        p->draw(core, maxMagLabel, planetNameFont);
×
1424
        }
1425

1426
        if (GETSTELMODULE(StelObjectMgr)->getFlagSelectedObjectPointer() && getFlagPointer())
×
1427
                drawPointer(core);
×
1428
}
1429

1430
void SolarSystem::drawEphemerisItems(const StelCore* core)
×
1431
{
1432
        if (flagShow || (!flagShow && getFlagEphemerisAlwaysOn()))
×
1433
        {
1434
                if (getFlagEphemerisMarkers())
×
1435
                        drawEphemerisMarkers(core);
×
1436
                if (getFlagEphemerisLine())
×
1437
                        drawEphemerisLine(core);
×
1438
        }
1439
}
×
1440

1441
Vec3f SolarSystem::getEphemerisMarkerColor(int index) const
×
1442
{
1443
        // Sync index with AstroCalcDialog::generateEphemeris(). If required, switch to using a QMap.
1444
        const QVector<Vec3f> colors={
1445
                ephemerisGenericMarkerColor,
1446
                ephemerisSecondaryMarkerColor,
1447
                ephemerisMercuryMarkerColor,
1448
                ephemerisVenusMarkerColor,
1449
                ephemerisMarsMarkerColor,
1450
                ephemerisJupiterMarkerColor,
1451
                ephemerisSaturnMarkerColor};
×
1452
        return colors.value(index, ephemerisGenericMarkerColor);
×
1453
}
×
1454

1455
void SolarSystem::drawEphemerisMarkers(const StelCore *core)
×
1456
{
1457
        const int fsize = AstroCalcDialog::EphemerisList.count();
×
1458
        if (fsize==0) return;
×
1459

1460
        StelProjectorP prj;
×
1461
        if (getFlagEphemerisHorizontalCoordinates())
×
1462
                prj = core->getProjection(StelCore::FrameAltAz, StelCore::RefractionOff);
×
1463
        else
1464
                prj = core->getProjection(StelCore::FrameJ2000);
×
1465
        StelPainter sPainter(prj);
×
1466

1467
        float size, shift, baseSize = 4.f;
×
1468
        const bool showDates = getFlagEphemerisDates();
×
1469
        const bool showMagnitudes = getFlagEphemerisMagnitudes();
×
1470
        const bool showSkippedData = getFlagEphemerisSkipData();
×
1471
        const bool skipMarkers = getFlagEphemerisSkipMarkers();
×
1472
        const bool isNowVisible = getFlagEphemerisNow();
×
1473
        const int dataStep = getEphemerisDataStep();
×
1474
        const int sizeCoeff = getEphemerisLineThickness() - 1;
×
1475
        QString info = "";
×
1476
        Vec3d win;
×
1477
        Vec3f markerColor;
×
1478
        bool skipFlag = false;
×
1479

1480
        if (getFlagEphemerisLine() && getFlagEphemerisScaleMarkers())
×
1481
                baseSize = 3.f; // The line lies through center of marker
×
1482

1483
        if (isNowVisible)
×
1484
        {
1485
                const int limit = getEphemerisDataLimit();
×
1486
                const int nsize = static_cast<int>(fsize/limit);
×
1487
                sPainter.setBlending(true, GL_ONE, GL_ONE);
×
1488
                texEphemerisNowMarker->bind();
×
1489
                Vec3d pos;
×
1490
                Vec3f win;
×
1491
                for (int i =0; i < limit; i++)
×
1492
                {
1493
                        sPainter.setColor(getEphemerisMarkerColor(AstroCalcDialog::EphemerisList[i*nsize].colorIndex));
×
1494
                        if (getFlagEphemerisHorizontalCoordinates())
×
1495
                                pos = AstroCalcDialog::EphemerisList[i*nsize].sso->getAltAzPosAuto(core);
×
1496
                        else
1497
                                pos = AstroCalcDialog::EphemerisList[i*nsize].sso->getJ2000EquatorialPos(core);
×
1498
                        if (prj->project(pos, win))
×
1499
                                sPainter.drawSprite2dMode(static_cast<float>(win[0]), static_cast<float>(win[1]), 6.f, 0.f);
×
1500
                }
1501
        }
1502

1503
        for (int i =0; i < fsize; i++)
×
1504
        {
1505
                skipFlag = (((i + 1)%dataStep)!=1 && dataStep!=1);
×
1506

1507
                // Check visibility of pointer
1508
                if (!(sPainter.getProjector()->projectCheck(AstroCalcDialog::EphemerisList[i].coord, win)))
×
1509
                        continue;
×
1510

1511
                QString debugStr; // Used temporarily for development
×
1512
                const bool isComet=AstroCalcDialog::EphemerisList[i].isComet;
×
1513
                if (i == AstroCalcDialog::DisplayedPositionIndex)
×
1514
                {
1515
                        markerColor = getEphemerisSelectedMarkerColor();
×
1516
                        size = 6.f;
×
1517
                }
1518
                else
1519
                {
1520
                        markerColor = getEphemerisMarkerColor(AstroCalcDialog::EphemerisList[i].colorIndex);
×
1521
                        size = baseSize;
×
1522
                }
1523
                if (isComet) size += 16.f;
×
1524
                size += sizeCoeff;
×
1525
                sPainter.setColor(markerColor);
×
1526
                sPainter.setBlending(true, GL_ONE, GL_ONE);
×
1527
                if (isComet)
×
1528
                        texEphemerisCometMarker->bind();
×
1529
                else
1530
                        texEphemerisMarker->bind();
×
1531

1532
                if (skipMarkers && skipFlag)
×
1533
                        continue;
×
1534

1535
                Vec3f win;
×
1536
                float solarAngle=0.f; // Angle to possibly rotate the texture. Degrees.
×
1537
                if (prj->project(AstroCalcDialog::EphemerisList[i].coord, win))
×
1538
                {
1539
                        if (isComet)
×
1540
                        {
1541
                                // compute solarAngle in screen space.
1542
                                Vec3f sunWin;
×
1543
                                prj->project(AstroCalcDialog::EphemerisList[i].sunCoord, sunWin);
×
1544
                                // TODO: In some projections, we may need to test result and flip/mirror the angle, or deal with wrap-around effects.
1545
                                // E.g., in cylindrical mode, the comet icon will flip as soon as the corresponding sun position wraps around the screen edge.
1546
                                solarAngle=M_180_PIf*(atan2(-(win[1]-sunWin[1]), win[0]-sunWin[0]));
×
1547
                                // This will show projected positions and angles usable in labels.
1548
                                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));
×
1549
                        }
1550
                        //sPainter.drawSprite2dMode(static_cast<float>(win[0]), static_cast<float>(win[1]), size, 180.f+AstroCalcDialog::EphemerisList[i].solarAngle*M_180_PIf);
1551
                        sPainter.drawSprite2dMode(static_cast<float>(win[0]), static_cast<float>(win[1]), size, 270.f-solarAngle);
×
1552
                }
1553

1554
                if (showDates || showMagnitudes)
×
1555
                {
1556
                        if (showSkippedData && skipFlag)
×
1557
                                continue;
×
1558

1559
                        shift = 3.f + size/1.6f;
×
1560
                        if (showDates && showMagnitudes)
×
1561
                                info = QString("%1 (%2)").arg(AstroCalcDialog::EphemerisList[i].objDateStr, QString::number(AstroCalcDialog::EphemerisList[i].magnitude, 'f', 2));
×
1562
                        if (showDates && !showMagnitudes)
×
1563
                                info = AstroCalcDialog::EphemerisList[i].objDateStr;
×
1564
                        if (!showDates && showMagnitudes)
×
1565
                                info = QString::number(AstroCalcDialog::EphemerisList[i].magnitude, 'f', 2);
×
1566

1567
                        // Activate for debug labels.
1568
                        //info=debugStr;
1569
                        sPainter.drawText(AstroCalcDialog::EphemerisList[i].coord, info, 0, shift, shift, false);
×
1570
                }
1571
        }
×
1572
}
×
1573

1574
void SolarSystem::drawEphemerisLine(const StelCore *core)
×
1575
{
1576
        const int size = AstroCalcDialog::EphemerisList.count();
×
1577
        if (size==0) return;
×
1578

1579
        // The array of data is not empty - good news!
1580
        StelProjectorP prj;
×
1581
        if (getFlagEphemerisHorizontalCoordinates())
×
1582
                prj = core->getProjection(StelCore::FrameAltAz, StelCore::RefractionOff);
×
1583
        else
1584
                prj = core->getProjection(StelCore::FrameJ2000);
×
1585
        StelPainter sPainter(prj);
×
1586
        const float ppx = static_cast<float>(sPainter.getProjector()->getDevicePixelsPerPixel());
×
1587

1588
        const float oldLineThickness=sPainter.getLineWidth();
×
1589
        const float lineThickness = getEphemerisLineThickness()*ppx;
×
1590
        if (!fuzzyEquals(lineThickness, oldLineThickness))
×
1591
                sPainter.setLineWidth(lineThickness);
×
1592

1593
        Vec3f color;
×
1594
        QVector<Vec3d> vertexArray;
×
1595
        QVector<Vec4f> colorArray;
×
1596
        const int limit = getEphemerisDataLimit();
×
1597
        const int nsize = static_cast<int>(size/limit);
×
1598
        vertexArray.resize(nsize);
×
1599
        colorArray.resize(nsize);
×
1600
        for (int j=0; j<limit; j++)
×
1601
        {
1602
                for (int i =0; i < nsize; i++)
×
1603
                {
1604
                        color = getEphemerisMarkerColor(AstroCalcDialog::EphemerisList[i + j*nsize].colorIndex);
×
1605
                        colorArray[i]=Vec4f(color, 1.0f);
×
1606
                        vertexArray[i]=AstroCalcDialog::EphemerisList[i + j*nsize].coord;
×
1607
                }
1608
                sPainter.drawPath(vertexArray, colorArray);
×
1609
        }
1610

1611
        if (!fuzzyEquals(lineThickness, oldLineThickness))
×
1612
                sPainter.setLineWidth(oldLineThickness); // restore line thickness
×
1613
}
×
1614

1615
void SolarSystem::fillEphemerisDates()
×
1616
{
1617
        const int fsize = AstroCalcDialog::EphemerisList.count();
×
1618
        if (fsize==0) return;
×
1619

1620
        StelLocaleMgr* localeMgr = &StelApp::getInstance().getLocaleMgr();
×
1621
        const bool showSmartDates = getFlagEphemerisSmartDates();
×
1622
        double JD = AstroCalcDialog::EphemerisList.first().objDate;
×
1623
        bool withTime = (fsize>1 && (AstroCalcDialog::EphemerisList[1].objDate-JD<1.0));
×
1624

1625
        int fYear, fMonth, fDay, sYear, sMonth, sDay, h, m, s;
1626
        QString info;
×
1627
        const double shift = StelApp::getInstance().getCore()->getUTCOffset(JD)*StelCore::JD_HOUR;
×
1628
        StelUtils::getDateFromJulianDay(JD+shift, &fYear, &fMonth, &fDay);
×
1629
        bool sFlag = true;
×
1630
        sYear = fYear;
×
1631
        sMonth = fMonth;
×
1632
        sDay = fDay;
×
1633
        const bool showSkippedData = getFlagEphemerisSkipData();
×
1634
        const int dataStep = getEphemerisDataStep();
×
1635

1636
        for (int i = 0; i < fsize; i++)
×
1637
        {
1638
                JD = AstroCalcDialog::EphemerisList[i].objDate;
×
1639
                StelUtils::getDateFromJulianDay(JD+shift, &fYear, &fMonth, &fDay);
×
1640

1641
                if (showSkippedData && ((i + 1)%dataStep)!=1 && dataStep!=1)
×
1642
                        continue;
×
1643

1644
                if (showSmartDates)
×
1645
                {
1646
                        if (sFlag)
×
1647
                                info = QString("%1").arg(fYear);
×
1648

1649
                        if (info.isEmpty() && !sFlag && fYear!=sYear)
×
1650
                                info = QString("%1").arg(fYear);
×
1651

1652
                        if (!info.isEmpty())
×
1653
                                info.append(QString("/%1").arg(localeMgr->romanMonthName(fMonth)));
×
1654
                        else if (fMonth!=sMonth)
×
1655
                                info = QString("%1").arg(localeMgr->romanMonthName(fMonth));
×
1656

1657
                        if (!info.isEmpty())
×
1658
                                info.append(QString("/%1").arg(fDay));
×
1659
                        else
1660
                                info = QString("%1").arg(fDay);
×
1661

1662
                        if (withTime) // very short step
×
1663
                        {
1664
                                if (fDay==sDay && !sFlag)
×
1665
                                        info.clear();
×
1666

1667
                                StelUtils::getTimeFromJulianDay(JD+shift, &h, &m, &s);
×
1668
                                QString hours = QString::number(h).rightJustified(2, '0');
×
1669
                                QString minutes = QString::number(m).rightJustified(2, '0');
×
1670
                                if (!info.isEmpty())
×
1671
                                        info.append(QString(" %1:%2").arg(hours, minutes));
×
1672
                                else
1673
                                        info = QString("%1:%2").arg(hours, minutes);
×
1674
                        }
×
1675

1676
                        AstroCalcDialog::EphemerisList[i].objDateStr = info;
×
1677
                        info.clear();
×
1678
                        sYear = fYear;
×
1679
                        sMonth = fMonth;
×
1680
                        sDay = fDay;
×
1681
                        sFlag = false;
×
1682
                }
1683
                else
1684
                {
1685
                        // OK, let's use standard formats for date and time (as defined for whole planetarium)
1686
                        if (withTime)
×
1687
                                AstroCalcDialog::EphemerisList[i].objDateStr = QString("%1 %2").arg(localeMgr->getPrintableDateLocal(JD), localeMgr->getPrintableTimeLocal(JD));
×
1688
                        else
1689
                                AstroCalcDialog::EphemerisList[i].objDateStr = localeMgr->getPrintableDateLocal(JD);
×
1690
                }
1691
        }
1692
}
×
1693

1694
PlanetP SolarSystem::searchByEnglishName(QString planetEnglishName) const
×
1695
{
1696
        for (const auto& p : systemPlanets)
×
1697
        {
1698
                if (p->getEnglishName().toUpper() == planetEnglishName.toUpper() || p->getCommonEnglishName().toUpper() == planetEnglishName.toUpper())
×
1699
                        return p;
×
1700

1701
                // IAU designation?
1702
                QString iau = p->getIAUDesignation();
×
1703
                if (!iau.isEmpty() && iau.toUpper()==planetEnglishName.toUpper())
×
1704
                        return p;
×
1705
        }
×
1706
        for (const auto& p : systemMinorBodies)
×
1707
        {
1708
                QStringList c;
×
1709
                // other comet designations?
1710
                if (p->getPlanetType()==Planet::isComet)
×
1711
                {
1712
                        QSharedPointer<Comet> mp = p.dynamicCast<Comet>();
×
1713
                        c = mp->getExtraDesignations();
×
1714
                } else {
×
1715
                        QSharedPointer<MinorPlanet> mp = p.dynamicCast<MinorPlanet>();
×
1716
                        c = mp->getExtraDesignations();
×
1717
                }
×
1718
                for (const auto& d : c)
×
1719
                {
1720
                        if (d.toUpper()==planetEnglishName.toUpper())
×
1721
                                return p;
×
1722
                }
1723
        }
×
1724
        return PlanetP();
×
1725
}
1726

1727
PlanetP SolarSystem::searchMinorPlanetByEnglishName(QString planetEnglishName) const
×
1728
{
1729
        for (const auto& p : systemMinorBodies)
×
1730
        {
1731
                if (p->getCommonEnglishName().toUpper() == planetEnglishName.toUpper() || p->getEnglishName().toUpper() == planetEnglishName.toUpper())
×
1732
                        return p;
×
1733

1734
                // IAU designation?
1735
                QString iau = p->getIAUDesignation();
×
1736
                if (!iau.isEmpty() && iau.toUpper()==planetEnglishName.toUpper())
×
1737
                        return p;
×
1738

1739
                QStringList c;
×
1740
                // other comet designations?
1741
                if (p->getPlanetType()==Planet::isComet)
×
1742
                {
1743
                        QSharedPointer<Comet> mp = p.dynamicCast<Comet>();
×
1744
                        c = mp->getExtraDesignations();
×
1745
                }
×
1746
                else
1747
                {
1748
                        QSharedPointer<MinorPlanet> mp = p.dynamicCast<MinorPlanet>();
×
1749
                        c = mp->getExtraDesignations();
×
1750
                }
×
1751
                for (const auto& d : c)
×
1752
                {
1753
                        if (d.toUpper()==planetEnglishName.toUpper())
×
1754
                                return p;
×
1755
                }
1756
        }
×
1757
        return PlanetP();
×
1758
}
1759

1760

1761
StelObjectP SolarSystem::searchByNameI18n(const QString& planetNameI18) const
×
1762
{
1763
        for (const auto& p : systemPlanets)
×
1764
        {
1765
                QString nativeName = p->getNativeNameI18n().toUpper();
×
1766
                if (p->getNameI18n().toUpper() == planetNameI18.toUpper() || (!nativeName.isEmpty() && nativeName == planetNameI18.toUpper()))
×
1767
                        return qSharedPointerCast<StelObject>(p);
×
1768
        }
×
1769
        return StelObjectP();
×
1770
}
1771

1772

1773
StelObjectP SolarSystem::searchByName(const QString& name) const
×
1774
{
1775
        for (const auto& p : systemPlanets)
×
1776
        {
1777
                QString nativeName = p->getNativeName().toUpper();
×
1778
                if (p->getEnglishName().toUpper() == name.toUpper() || (!nativeName.isEmpty() && nativeName == name.toUpper()))
×
1779
                        return qSharedPointerCast<StelObject>(p);
×
1780

1781
                // IAU designation?
1782
                QString iau = p->getIAUDesignation();
×
1783
                if (!iau.isEmpty() && iau.toUpper()==name.toUpper())
×
1784
                        return qSharedPointerCast<StelObject>(p);
×
1785
        }
×
1786
        for (const auto& p : systemMinorBodies)
×
1787
        {
1788
                QStringList c;
×
1789
                // other comet designations?
1790
                if (p->getPlanetType()==Planet::isComet)
×
1791
                {
1792
                        QSharedPointer<Comet> mp = p.dynamicCast<Comet>();
×
1793
                        c = mp->getExtraDesignations();
×
1794
                }
×
1795
                else
1796
                {
1797
                        QSharedPointer<MinorPlanet> mp = p.dynamicCast<MinorPlanet>();
×
1798
                        c = mp->getExtraDesignations();
×
1799
                }
×
1800
                for (const auto& d : c)
×
1801
                {
1802
                        if (d.toUpper()==name.toUpper())
×
1803
                                return qSharedPointerCast<StelObject>(p);
×
1804
                }
1805
        }
×
1806

1807
        return StelObjectP();
×
1808
}
1809

1810
float SolarSystem::getPlanetVMagnitude(QString planetName, bool withExtinction) const
×
1811
{
1812
        PlanetP p = searchByEnglishName(planetName);
×
1813
        if (p.isNull()) // Possible was asked the common name of minor planet?
×
1814
                p = searchMinorPlanetByEnglishName(planetName);
×
1815
        float r = 0.f;
×
1816
        if (withExtinction)
×
1817
                r = p->getVMagnitudeWithExtinction(StelApp::getInstance().getCore());
×
1818
        else
1819
                r = p->getVMagnitude(StelApp::getInstance().getCore());
×
1820
        return r;
×
1821
}
×
1822

1823
QString SolarSystem::getPlanetType(QString planetName) const
×
1824
{
1825
        PlanetP p = searchByEnglishName(planetName);
×
1826
        if (p.isNull()) // Possible was asked the common name of minor planet?
×
1827
                p = searchMinorPlanetByEnglishName(planetName);
×
1828
        if (p.isNull())
×
1829
                return QString("UNDEFINED");
×
1830
        return p->getObjectType();
×
1831
}
×
1832

1833
double SolarSystem::getDistanceToPlanet(QString planetName) const
×
1834
{
1835
        PlanetP p = searchByEnglishName(planetName);
×
1836
        if (p.isNull()) // Possible was asked the common name of minor planet?
×
1837
                p = searchMinorPlanetByEnglishName(planetName);
×
1838
        return p->getDistance();
×
1839
}
×
1840

1841
double SolarSystem::getElongationForPlanet(QString planetName) const
×
1842
{
1843
        PlanetP p = searchByEnglishName(planetName);
×
1844
        if (p.isNull()) // Possible was asked the common name of minor planet?
×
1845
                p = searchMinorPlanetByEnglishName(planetName);
×
1846
        return p->getElongation(StelApp::getInstance().getCore()->getObserverHeliocentricEclipticPos());
×
1847
}
×
1848

1849
double SolarSystem::getPhaseAngleForPlanet(QString planetName) const
×
1850
{
1851
        PlanetP p = searchByEnglishName(planetName);
×
1852
        if (p.isNull()) // Possible was asked the common name of minor planet?
×
1853
                p = searchMinorPlanetByEnglishName(planetName);
×
1854
        return p->getPhaseAngle(StelApp::getInstance().getCore()->getObserverHeliocentricEclipticPos());
×
1855
}
×
1856

1857
float SolarSystem::getPhaseForPlanet(QString planetName) const
×
1858
{
1859
        PlanetP p = searchByEnglishName(planetName);
×
1860
        if (p.isNull()) // Possible was asked the common name of minor planet?
×
1861
                p = searchMinorPlanetByEnglishName(planetName);
×
1862
        return p->getPhase(StelApp::getInstance().getCore()->getObserverHeliocentricEclipticPos());
×
1863
}
×
1864

1865
QStringList SolarSystem::getObjectsList(QString objType) const
×
1866
{
1867
        QStringList r;
×
1868
        if (objType.toLower()=="all")
×
1869
        {
1870
                r = listAllObjects(true);
×
1871
                // Remove the Sun
1872
                r.removeOne("Sun");
×
1873
                // Remove special objects
1874
                r.removeOne("Solar System Observer");
×
1875
                r.removeOne("Earth Observer");
×
1876
                r.removeOne("Mars Observer");
×
1877
                r.removeOne("Jupiter Observer");
×
1878
                r.removeOne("Saturn Observer");
×
1879
                r.removeOne("Uranus Observer");
×
1880
                r.removeOne("Neptune Observer");
×
1881
        }
1882
        else
1883
                r = listAllObjectsByType(objType, true);
×
1884

1885
        return r;
×
1886
}
×
1887

1888
// Search if any Planet is close to position given in earth equatorial position and return the distance
1889
StelObjectP SolarSystem::search(Vec3d pos, const StelCore* core) const
×
1890
{
1891
        pos.normalize();
×
1892
        PlanetP closest;
×
1893
        double cos_angle_closest = 0.;
×
1894
        Vec3d equPos;
×
1895

1896
        for (const auto& p : systemPlanets)
×
1897
        {
1898
                equPos = p->getEquinoxEquatorialPos(core);
×
1899
                equPos.normalize();
×
1900
                double cos_ang_dist = equPos*pos;
×
1901
                if (cos_ang_dist>cos_angle_closest)
×
1902
                {
1903
                        closest = p;
×
1904
                        cos_angle_closest = cos_ang_dist;
×
1905
                }
1906
        }
1907

1908
        if (cos_angle_closest>0.999)
×
1909
        {
1910
                return qSharedPointerCast<StelObject>(closest);
×
1911
        }
1912
        else return StelObjectP();
×
1913
}
×
1914

1915
// Return a QList containing the planets located inside the limFov circle around position vv
1916
QList<StelObjectP> SolarSystem::searchAround(const Vec3d& vv, double limitFov, const StelCore* core) const
×
1917
{
1918
        QList<StelObjectP> result;
×
1919
        if (!getFlagPlanets())
×
1920
                return result;
×
1921

1922
        const bool withAberration=core->getUseAberration();
×
1923
        Vec3d v(vv);
×
1924
        v.normalize(); // TODO: start with vv already normalized?
×
1925
        if (withAberration)
×
1926
        {
1927
                Vec3d vel=core->getCurrentPlanet()->getHeliocentricEclipticVelocity();
×
1928
                StelCore::matVsop87ToJ2000.transfo(vel);
×
1929
                vel*=core->getAberrationFactor()*(AU/(86400.0*SPEED_OF_LIGHT));
×
1930
                v+=vel;
×
1931
                v.normalize();
×
1932
        }
1933

1934
        double cosLimFov = std::cos(limitFov * M_PI/180.);
×
1935
        Vec3d equPos;
×
1936
        double cosAngularSize;
1937

1938
        const QString weAreHere = core->getCurrentPlanet()->getEnglishName();
×
1939
        for (const auto& p : systemPlanets)
×
1940
        {
1941
                equPos = p->getJ2000EquatorialPos(core);
×
1942
                equPos.normalize();
×
1943

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

1946
                if (equPos*v>=std::min(cosLimFov, cosAngularSize) && p->getEnglishName()!=weAreHere)
×
1947
                {
1948
                        result.append(qSharedPointerCast<StelObject>(p));
×
1949
                }
1950
        }
1951
        return result;
×
1952
}
×
1953

1954
// Update i18 names from english names according to current sky culture translator
1955
void SolarSystem::updateI18n()
×
1956
{
1957
        const StelTranslator& trans = StelApp::getInstance().getLocaleMgr().getSkyTranslator();
×
1958
        for (const auto& p : qAsConst(systemPlanets))
×
1959
                p->translateName(trans);
×
1960
}
×
1961

1962
QStringList SolarSystem::listMatchingObjects(const QString& objPrefix, int maxNbItem, bool useStartOfWords) const
×
1963
{
1964
        QStringList result;
×
1965
        if (getFlagPlanets())
×
1966
                result = StelObjectModule::listMatchingObjects(objPrefix, maxNbItem, useStartOfWords);
×
1967
        return result;
×
1968
}
×
1969

1970
void SolarSystem::setFlagTrails(bool b)
×
1971
{
1972
        if (getFlagTrails() != b)
×
1973
        {
1974
                trailFader = b;
×
1975
                if (b)
×
1976
                {
1977
                        allTrails->reset(maxTrailPoints);
×
1978
                        recreateTrails();
×
1979
                }
1980
                emit trailsDisplayedChanged(b);
×
1981
        }
1982
}
×
1983

1984
bool SolarSystem::getFlagTrails() const
×
1985
{
1986
        return static_cast<bool>(trailFader);
×
1987
}
1988

1989
void SolarSystem::setMaxTrailPoints(int max)
×
1990
{
1991
        if (maxTrailPoints != max)
×
1992
        {
1993
                maxTrailPoints = max;
×
1994
                allTrails->reset(max);
×
1995
                recreateTrails();
×
1996
                emit maxTrailPointsChanged(max);
×
1997
        }
1998
}
×
1999

2000
void SolarSystem::setMaxTrailTimeExtent(int max)
×
2001
{
2002
        if (maxTrailTimeExtent != max && maxTrailTimeExtent > 0)
×
2003
        {
2004
                maxTrailTimeExtent = max;
×
2005
                recreateTrails();
×
2006
                emit maxTrailTimeExtentChanged(max);
×
2007
        }
2008
}
×
2009

2010
void SolarSystem::setTrailsThickness(int v)
×
2011
{
2012
        if (trailsThickness != v)
×
2013
        {
2014
                trailsThickness = v;
×
2015
                emit trailsThicknessChanged(v);
×
2016
        }
2017
}
×
2018

2019
void SolarSystem::setFlagHints(bool b)
×
2020
{
2021
        if (getFlagHints() != b)
×
2022
        {
2023
                for (const auto& p : qAsConst(systemPlanets))
×
2024
                        p->setFlagHints(b);
×
2025
                emit flagHintsChanged(b);
×
2026
        }
2027
}
×
2028

2029
bool SolarSystem::getFlagHints(void) const
×
2030
{
2031
        for (const auto& p : systemPlanets)
×
2032
        {
2033
                if (p->getFlagHints())
×
2034
                        return true;
×
2035
        }
2036
        return false;
×
2037
}
2038

2039
void SolarSystem::setFlagLabels(bool b)
×
2040
{
2041
        if (getFlagLabels() != b)
×
2042
        {
2043
                for (const auto& p : qAsConst(systemPlanets))
×
2044
                        p->setFlagLabels(b);
×
2045
                emit labelsDisplayedChanged(b);
×
2046
        }
2047
}
×
2048

2049
bool SolarSystem::getFlagLabels() const
×
2050
{
2051
        for (const auto& p : systemPlanets)
×
2052
        {
2053
                if (p->getFlagLabels())
×
2054
                        return true;
×
2055
        }
2056
        return false;
×
2057
}
2058

2059
void SolarSystem::setFlagLightTravelTime(bool b)
×
2060
{
2061
        if(b!=flagLightTravelTime)
×
2062
        {
2063
                flagLightTravelTime = b;
×
2064
                emit flagLightTravelTimeChanged(b);
×
2065
        }
2066
}
×
2067

2068
void SolarSystem::setFlagShowObjSelfShadows(bool b)
×
2069
{
2070
        if(b!=flagShowObjSelfShadows)
×
2071
        {
2072
                flagShowObjSelfShadows = b;
×
2073
                if(!b)
×
2074
                        Planet::deinitFBO();
×
2075
                emit flagShowObjSelfShadowsChanged(b);
×
2076
        }
2077
}
×
2078

2079
void SolarSystem::setSelected(PlanetP obj)
×
2080
{
2081
        if (obj && obj->getType() == "Planet")
×
2082
        {
2083
                selected = obj;
×
2084
                selectedSSO.push_back(obj);
×
2085
        }
2086
        else
2087
                selected.clear();
×
2088
        // Undraw other objects hints, orbit, trails etc..
2089
        setFlagHints(getFlagHints());
×
2090
        reconfigureOrbits();
×
2091
}
×
2092

2093

2094
void SolarSystem::update(double deltaTime)
×
2095
{
2096
        trailFader.update(static_cast<int>(deltaTime*1000));
×
2097
        if (trailFader.getInterstate()>0.f)
×
2098
        {
2099
                allTrails->update();
×
2100
        }
2101

2102
        for (const auto& p : qAsConst(systemPlanets))
×
2103
        {
2104
                p->update(static_cast<int>(deltaTime*1000));
×
2105
        }
2106
}
×
2107

2108
// is a lunar eclipse close at hand?
2109
bool SolarSystem::nearLunarEclipse() const
×
2110
{
2111
        // TODO: could replace with simpler test
2112
        // TODO Source?
2113

2114
        const Vec3d sun = getSun()->getAberrationPush();
×
2115
        const Vec3d e = getEarth()->getEclipticPos();
×
2116
        const Vec3d m = getMoon()->getEclipticPos();  // relative to earth
×
2117
        const Vec3d mh = getMoon()->getHeliocentricEclipticPos();  // relative to sun
×
2118

2119
        // shadow location at earth + moon distance along earth vector from (aberrated) sun
2120
        Vec3d en = e-sun;
×
2121
        en.normalize();
×
2122
        Vec3d shadow = en * (e.norm() + m.norm());
×
2123

2124
        // find shadow radii in AU
2125
        double r_penumbra = shadow.norm()*702378.1/AU/e.norm() - SUN_RADIUS/AU;
×
2126

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

2131
        return true;
×
2132
}
2133

2134
QStringList SolarSystem::listAllObjects(bool inEnglish) const
×
2135
{
2136
        QStringList result;
×
2137
        if (inEnglish)
×
2138
        {
2139
                for (const auto& p : systemPlanets)
×
2140
                {
2141
                        result << p->getEnglishName();
×
2142
                        if (!p->getIAUDesignation().isEmpty())
×
2143
                                result << p->getIAUDesignation();
×
2144
                }
2145
        }
2146
        else
2147
        {
2148
                for (const auto& p : systemPlanets)
×
2149
                {
2150
                        result << p->getNameI18n();
×
2151
                        if (!p->getNativeNameI18n().isEmpty())
×
2152
                                result << p->getNativeNameI18n() << p->getNativeName();
×
2153
                        if (!p->getIAUDesignation().isEmpty())
×
2154
                                result << p->getIAUDesignation();
×
2155
                }
2156
        }
2157
        for (const auto& p : systemMinorBodies)
×
2158
        {
2159
                QStringList c;
×
2160
                // other comet designations?
2161
                if (p->getPlanetType()==Planet::isComet)
×
2162
                {
2163
                        QSharedPointer<Comet> mp = p.dynamicCast<Comet>();
×
2164
                        c = mp->getExtraDesignations();
×
2165
                } else {
×
2166
                        QSharedPointer<MinorPlanet> mp = p.dynamicCast<MinorPlanet>();
×
2167
                        c = mp->getExtraDesignations();
×
2168
                }
×
2169
                if (c.count()>0)
×
2170
                        result << c;
×
2171
        }
×
2172
        return result;
×
2173
}
×
2174

2175
QStringList SolarSystem::listAllObjectsByType(const QString &objType, bool inEnglish) const
×
2176
{
2177
        QStringList result;
×
2178
        if (inEnglish)
×
2179
        {
2180
                for (const auto& p : systemPlanets)
×
2181
                {
2182
                        if (p->getObjectType()==objType)
×
2183
                        {
2184
                                result << p->getEnglishName();
×
2185
                                if (!p->getIAUDesignation().isEmpty())
×
2186
                                        result << p->getIAUDesignation();
×
2187
                        }
2188
                }
2189
        }
2190
        else
2191
        {
2192
                for (const auto& p : systemPlanets)
×
2193
                {
2194
                        if (p->getObjectType()==objType)
×
2195
                        {
2196
                                result << p->getNameI18n();
×
2197
                                if (!p->getIAUDesignation().isEmpty())
×
2198
                                        result << p->getIAUDesignation();
×
2199
                        }
2200
                }
2201
        }
2202
        for (const auto& p : systemMinorBodies)
×
2203
        {
2204
                if (p->getObjectType()==objType)
×
2205
                {
2206
                        QStringList c;
×
2207
                        // other comet designations?
2208
                        if (p->getPlanetType()==Planet::isComet)
×
2209
                        {
2210
                                QSharedPointer<Comet> mp = p.dynamicCast<Comet>();
×
2211
                                c = mp->getExtraDesignations();
×
2212
                        } else {
×
2213
                                QSharedPointer<MinorPlanet> mp = p.dynamicCast<MinorPlanet>();
×
2214
                                c = mp->getExtraDesignations();
×
2215
                        }
×
2216
                        if (c.count()>0)
×
2217
                                result << c;
×
2218
                }
×
2219
        }
2220
        return result;
×
2221
}
×
2222

2223
void SolarSystem::selectedObjectChange(StelModule::StelModuleSelectAction)
×
2224
{
2225
        const QList<StelObjectP> newSelected = GETSTELMODULE(StelObjectMgr)->getSelectedObject("Planet");
×
2226
        if (!newSelected.empty())
×
2227
        {
2228
                setSelected(qSharedPointerCast<Planet>(newSelected[0]));
×
2229
                if (getFlagIsolatedTrails())
×
2230
                        recreateTrails();
×
2231
        }
2232
        else
2233
                setSelected("");
×
2234
}
×
2235

2236
// Activate/Deactivate planets display
2237
void SolarSystem::setFlagPlanets(bool b)
×
2238
{
2239
        if (b!=flagShow)
×
2240
        {
2241
                flagShow=b;
×
2242
                emit flagPlanetsDisplayedChanged(b);
×
2243
        }
2244
}
×
2245

2246
bool SolarSystem::getFlagPlanets(void) const
×
2247
{
2248
        return flagShow;
×
2249
}
2250

2251
void SolarSystem::setFlagEphemerisMarkers(bool b)
×
2252
{
2253
        if (b!=ephemerisMarkersDisplayed)
×
2254
        {
2255
                ephemerisMarkersDisplayed=b;
×
2256
                conf->setValue("astrocalc/flag_ephemeris_markers", b); // Immediate saving of state
×
2257
                emit ephemerisMarkersChanged(b);
×
2258
        }
2259
}
×
2260

2261
bool SolarSystem::getFlagEphemerisMarkers() const
×
2262
{
2263
        return ephemerisMarkersDisplayed;
×
2264
}
2265

2266
void SolarSystem::setFlagEphemerisLine(bool b)
×
2267
{
2268
        if (b!=ephemerisLineDisplayed)
×
2269
        {
2270
                ephemerisLineDisplayed=b;
×
2271
                conf->setValue("astrocalc/flag_ephemeris_line", b); // Immediate saving of state
×
2272
                emit ephemerisLineChanged(b);
×
2273
        }
2274
}
×
2275

2276
bool SolarSystem::getFlagEphemerisLine() const
×
2277
{
2278
        return ephemerisLineDisplayed;
×
2279
}
2280

2281
bool SolarSystem::getFlagEphemerisAlwaysOn() const
×
2282
{
2283
        return ephemerisAlwaysOn;
×
2284
}
2285

2286
void SolarSystem::setFlagEphemerisAlwaysOn(bool b)
×
2287
{
2288
        if (b != ephemerisAlwaysOn)
×
2289
        {
2290
                ephemerisAlwaysOn = b;
×
2291
                conf->setValue("astrocalc/flag_ephemeris_alwayson", b); // Immediate saving of state
×
2292
                emit ephemerisAlwaysOnChanged(b);
×
2293
        }
2294
}
×
2295

2296
bool SolarSystem::getFlagEphemerisNow() const
×
2297
{
2298
        return ephemerisNow;
×
2299
}
2300

2301
void SolarSystem::setFlagEphemerisNow(bool b)
×
2302
{
2303
        if (b != ephemerisNow)
×
2304
        {
2305
                ephemerisNow = b;
×
2306
                conf->setValue("astrocalc/flag_ephemeris_now", b); // Immediate saving of state
×
2307
                emit ephemerisNowChanged(b);
×
2308
        }
2309
}
×
2310

2311
void SolarSystem::setFlagEphemerisHorizontalCoordinates(bool b)
×
2312
{
2313
        if (b!=ephemerisHorizontalCoordinates)
×
2314
        {
2315
                ephemerisHorizontalCoordinates=b;
×
2316
                conf->setValue("astrocalc/flag_ephemeris_horizontal", b); // Immediate saving of state
×
2317
                emit ephemerisHorizontalCoordinatesChanged(b);
×
2318
        }
2319
}
×
2320

2321
bool SolarSystem::getFlagEphemerisHorizontalCoordinates() const
×
2322
{
2323
        return ephemerisHorizontalCoordinates;
×
2324
}
2325

2326
void SolarSystem::setFlagEphemerisDates(bool b)
×
2327
{
2328
        if (b!=ephemerisDatesDisplayed)
×
2329
        {
2330
                ephemerisDatesDisplayed=b;
×
2331
                conf->setValue("astrocalc/flag_ephemeris_dates", b); // Immediate saving of state
×
2332
                emit ephemerisDatesChanged(b);
×
2333
        }
2334
}
×
2335

2336
bool SolarSystem::getFlagEphemerisDates() const
×
2337
{
2338
        return ephemerisDatesDisplayed;
×
2339
}
2340

2341
void SolarSystem::setFlagEphemerisMagnitudes(bool b)
×
2342
{
2343
        if (b!=ephemerisMagnitudesDisplayed)
×
2344
        {
2345
                ephemerisMagnitudesDisplayed=b;
×
2346
                conf->setValue("astrocalc/flag_ephemeris_magnitudes", b); // Immediate saving of state
×
2347
                emit ephemerisMagnitudesChanged(b);
×
2348
        }
2349
}
×
2350

2351
bool SolarSystem::getFlagEphemerisMagnitudes() const
×
2352
{
2353
        return ephemerisMagnitudesDisplayed;
×
2354
}
2355

2356
void SolarSystem::setFlagEphemerisSkipData(bool b)
×
2357
{
2358
        if (b!=ephemerisSkipDataDisplayed)
×
2359
        {
2360
                ephemerisSkipDataDisplayed=b;
×
2361
                conf->setValue("astrocalc/flag_ephemeris_skip_data", b); // Immediate saving of state
×
2362
                emit ephemerisSkipDataChanged(b);
×
2363
        }
2364
}
×
2365

2366
bool SolarSystem::getFlagEphemerisSkipData() const
×
2367
{
2368
        return ephemerisSkipDataDisplayed;
×
2369
}
2370

2371
void SolarSystem::setFlagEphemerisSkipMarkers(bool b)
×
2372
{
2373
        if (b!=ephemerisSkipMarkersDisplayed)
×
2374
        {
2375
                ephemerisSkipMarkersDisplayed=b;
×
2376
                conf->setValue("astrocalc/flag_ephemeris_skip_markers", b); // Immediate saving of state
×
2377
                emit ephemerisSkipMarkersChanged(b);
×
2378
        }
2379
}
×
2380

2381
bool SolarSystem::getFlagEphemerisSkipMarkers() const
×
2382
{
2383
        return ephemerisSkipMarkersDisplayed;
×
2384
}
2385

2386
void SolarSystem::setFlagEphemerisSmartDates(bool b)
×
2387
{
2388
        if (b!=ephemerisSmartDatesDisplayed)
×
2389
        {
2390
                ephemerisSmartDatesDisplayed=b;
×
2391
                conf->setValue("astrocalc/flag_ephemeris_smart_dates", b); // Immediate saving of state
×
2392
                emit ephemerisSmartDatesChanged(b);
×
2393
        }
2394
}
×
2395

2396
bool SolarSystem::getFlagEphemerisSmartDates() const
×
2397
{
2398
        return ephemerisSmartDatesDisplayed;
×
2399
}
2400

2401
void SolarSystem::setFlagEphemerisScaleMarkers(bool b)
×
2402
{
2403
        if (b!=ephemerisScaleMarkersDisplayed)
×
2404
        {
2405
                ephemerisScaleMarkersDisplayed=b;
×
2406
                conf->setValue("astrocalc/flag_ephemeris_scale_markers", b); // Immediate saving of state
×
2407
                emit ephemerisScaleMarkersChanged(b);
×
2408
        }
2409
}
×
2410

2411
bool SolarSystem::getFlagEphemerisScaleMarkers() const
×
2412
{
2413
        return ephemerisScaleMarkersDisplayed;
×
2414
}
2415

2416
void SolarSystem::setEphemerisDataStep(int step)
×
2417
{
2418
        ephemerisDataStep = step;
×
2419
        // automatic saving of the setting
2420
        conf->setValue("astrocalc/ephemeris_data_step", step);
×
2421
        emit ephemerisDataStepChanged(step);
×
2422
}
×
2423

2424
int SolarSystem::getEphemerisDataStep() const
×
2425
{
2426
        return ephemerisDataStep;
×
2427
}
2428

2429
void SolarSystem::setEphemerisDataLimit(int limit)
×
2430
{
2431
        ephemerisDataLimit = limit;
×
2432
        emit ephemerisDataLimitChanged(limit);
×
2433
}
×
2434

2435
int SolarSystem::getEphemerisDataLimit() const
×
2436
{
2437
        return ephemerisDataLimit;
×
2438
}
2439

2440
void SolarSystem::setEphemerisLineThickness(int v)
×
2441
{
2442
        ephemerisLineThickness = v;
×
2443
        // automatic saving of the setting
2444
        conf->setValue("astrocalc/ephemeris_line_thickness", v);
×
2445
        emit ephemerisLineThicknessChanged(v);
×
2446
}
×
2447

2448
int SolarSystem::getEphemerisLineThickness() const
×
2449
{
2450
        return ephemerisLineThickness;
×
2451
}
2452

2453
void SolarSystem::setEphemerisGenericMarkerColor(const Vec3f& color)
×
2454
{
2455
        if (color!=ephemerisGenericMarkerColor)
×
2456
        {
2457
                ephemerisGenericMarkerColor = color;
×
2458
                emit ephemerisGenericMarkerColorChanged(color);
×
2459
        }
2460
}
×
2461

2462
Vec3f SolarSystem::getEphemerisGenericMarkerColor() const
×
2463
{
2464
        return ephemerisGenericMarkerColor;
×
2465
}
2466

2467
void SolarSystem::setEphemerisSecondaryMarkerColor(const Vec3f& color)
×
2468
{
2469
        if (color!=ephemerisSecondaryMarkerColor)
×
2470
        {
2471
                ephemerisSecondaryMarkerColor = color;
×
2472
                emit ephemerisSecondaryMarkerColorChanged(color);
×
2473
        }
2474
}
×
2475

2476
Vec3f SolarSystem::getEphemerisSecondaryMarkerColor() const
×
2477
{
2478
        return ephemerisSecondaryMarkerColor;
×
2479
}
2480

2481
void SolarSystem::setEphemerisSelectedMarkerColor(const Vec3f& color)
×
2482
{
2483
        if (color!=ephemerisSelectedMarkerColor)
×
2484
        {
2485
                ephemerisSelectedMarkerColor = color;
×
2486
                emit ephemerisSelectedMarkerColorChanged(color);
×
2487
        }
2488
}
×
2489

2490
Vec3f SolarSystem::getEphemerisSelectedMarkerColor() const
×
2491
{
2492
        return ephemerisSelectedMarkerColor;
×
2493
}
2494

2495
void SolarSystem::setEphemerisMercuryMarkerColor(const Vec3f& color)
×
2496
{
2497
        if (color!=ephemerisMercuryMarkerColor)
×
2498
        {
2499
                ephemerisMercuryMarkerColor = color;
×
2500
                emit ephemerisMercuryMarkerColorChanged(color);
×
2501
        }
2502
}
×
2503

2504
Vec3f SolarSystem::getEphemerisMercuryMarkerColor() const
×
2505
{
2506
        return ephemerisMercuryMarkerColor;
×
2507
}
2508

2509
void SolarSystem::setEphemerisVenusMarkerColor(const Vec3f& color)
×
2510
{
2511
        if (color!=ephemerisVenusMarkerColor)
×
2512
        {
2513
                ephemerisVenusMarkerColor = color;
×
2514
                emit ephemerisVenusMarkerColorChanged(color);
×
2515
        }
2516
}
×
2517

2518
Vec3f SolarSystem::getEphemerisVenusMarkerColor() const
×
2519
{
2520
        return ephemerisVenusMarkerColor;
×
2521
}
2522

2523
void SolarSystem::setEphemerisMarsMarkerColor(const Vec3f& color)
×
2524
{
2525
        if (color!=ephemerisMarsMarkerColor)
×
2526
        {
2527
                ephemerisMarsMarkerColor = color;
×
2528
                emit ephemerisMarsMarkerColorChanged(color);
×
2529
        }
2530
}
×
2531

2532
Vec3f SolarSystem::getEphemerisMarsMarkerColor() const
×
2533
{
2534
        return ephemerisMarsMarkerColor;
×
2535
}
2536

2537
void SolarSystem::setEphemerisJupiterMarkerColor(const Vec3f& color)
×
2538
{
2539
        if (color!=ephemerisJupiterMarkerColor)
×
2540
        {
2541
                ephemerisJupiterMarkerColor = color;
×
2542
                emit ephemerisJupiterMarkerColorChanged(color);
×
2543
        }
2544
}
×
2545

2546
Vec3f SolarSystem::getEphemerisJupiterMarkerColor() const
×
2547
{
2548
        return ephemerisJupiterMarkerColor;
×
2549
}
2550

2551
void SolarSystem::setEphemerisSaturnMarkerColor(const Vec3f& color)
×
2552
{
2553
        if (color!=ephemerisSaturnMarkerColor)
×
2554
        {
2555
                ephemerisSaturnMarkerColor = color;
×
2556
                emit ephemerisSaturnMarkerColorChanged(color);
×
2557
        }
2558
}
×
2559

2560
Vec3f SolarSystem::getEphemerisSaturnMarkerColor() const
×
2561
{
2562
        return ephemerisSaturnMarkerColor;
×
2563
}
2564

2565
void SolarSystem::setFlagNativePlanetNames(bool b)
×
2566
{
2567
        if (b!=flagNativePlanetNames)
×
2568
        {
2569
                flagNativePlanetNames=b;
×
2570
                for (const auto& p : qAsConst(systemPlanets))
×
2571
                {
2572
                        if (p->getPlanetType()==Planet::isPlanet || p->getPlanetType()==Planet::isMoon || p->getPlanetType()==Planet::isStar)
×
2573
                                p->setFlagNativeName(flagNativePlanetNames);
×
2574
                }
2575
                updateI18n();
×
2576
                emit flagNativePlanetNamesChanged(b);
×
2577
        }
2578
}
×
2579

2580
bool SolarSystem::getFlagNativePlanetNames() const
×
2581
{
2582
        return flagNativePlanetNames;
×
2583
}
2584

2585
void SolarSystem::setFlagIsolatedTrails(bool b)
×
2586
{
2587
        if(b!=flagIsolatedTrails)
×
2588
        {
2589
                flagIsolatedTrails = b;
×
2590
                recreateTrails();
×
2591
                emit flagIsolatedTrailsChanged(b);
×
2592
        }
2593
}
×
2594

2595
bool SolarSystem::getFlagIsolatedTrails() const
×
2596
{
2597
        return flagIsolatedTrails;
×
2598
}
2599

2600
int SolarSystem::getNumberIsolatedTrails() const
×
2601
{
2602
        return numberIsolatedTrails;
×
2603
}
2604

2605
void SolarSystem::setNumberIsolatedTrails(int n)
×
2606
{
2607
        // [1..5] - valid range for trails
2608
        numberIsolatedTrails = qBound(1, n, 5);
×
2609

2610
        if (getFlagIsolatedTrails())
×
2611
                recreateTrails();
×
2612

2613
        emit numberIsolatedTrailsChanged(numberIsolatedTrails);
×
2614
}
×
2615

2616
void SolarSystem::setFlagOrbits(bool b)
×
2617
{
2618
        if(b!=getFlagOrbits())
×
2619
        {
2620
                flagOrbits = b;
×
2621
                emit flagOrbitsChanged(b);
×
2622
        }
2623
}
×
2624

2625
// Connect this to all signals when orbit selection or selected object has changed.
2626
// This method goes through all planets and sets orbit drawing as configured by several flags
2627
void SolarSystem::reconfigureOrbits()
×
2628
{
2629
        // we have: flagOrbits O, flagIsolatedOrbits I, flagPlanetsOrbitsOnly P, flagOrbitsWithMoons M, flagPermanentOrbits and a possibly selected planet S
2630
        // permanentOrbits only influences local drawing of a single planet and can be ignored here.
2631
        // O S I P M
2632
        // 0 X X X X  NONE
2633
        // 1 0 1 X X  NONE
2634
        // 1 X 0 0 X  ALL
2635
        // 1 X 0 1 0  all planets only
2636
        // 1 X 0 1 1  all planets with their moons only
2637

2638
        // 1 1 1 0 0  only selected SSO
2639
        // 1 1 1 0 1  only selected SSO and orbits of its moon system
2640
        // 1 1 1 1 0  only selected SSO if it is a major planet
2641
        // 1 1 1 1 1  only selected SSO if it is a major planet, plus its system of moons
2642

2643
        if (!flagOrbits || (flagIsolatedOrbits && (!selected || selected==sun)))
×
2644
        {
2645
                for (const auto& p : qAsConst(systemPlanets))
×
2646
                        p->setFlagOrbits(false);
×
2647
                return;
×
2648
        }
2649
        // from here, flagOrbits is certainly on
2650
        if (!flagIsolatedOrbits)
×
2651
        {
2652
                for (const auto& p : qAsConst(systemPlanets))
×
2653
                        p->setFlagOrbits(!flagPlanetsOrbitsOnly || (p->getPlanetType()==Planet::isPlanet || (flagOrbitsWithMoons && p->parent && p->parent->getPlanetType()==Planet::isPlanet) ));
×
2654
                return;
×
2655
        }
2656
        else // flagIsolatedOrbits && selected
2657
        {
2658
                // Display only orbit for selected planet and, if requested, its moons.
2659
                for (const auto& p : qAsConst(systemPlanets))
×
2660
                        p->setFlagOrbits(   (p==selected && (  !flagPlanetsOrbitsOnly ||  p->getPlanetType()==Planet::isPlanet ) )
×
2661
                                         || (flagOrbitsWithMoons && p->getPlanetType()==Planet::isMoon && p->parent==selected ) );
×
2662
                return;
×
2663
        }
2664
}
2665

2666
void SolarSystem::setFlagIsolatedOrbits(bool b)
×
2667
{
2668
        if(b!=flagIsolatedOrbits)
×
2669
        {
2670
                flagIsolatedOrbits = b;
×
2671
                StelApp::immediateSave("viewing/flag_isolated_orbits", b);
×
2672
                emit flagIsolatedOrbitsChanged(b);
×
2673
        }
2674
}
×
2675

2676
bool SolarSystem::getFlagIsolatedOrbits() const
×
2677
{
2678
        return flagIsolatedOrbits;
×
2679
}
2680

2681
void SolarSystem::setFlagPlanetsOrbitsOnly(bool b)
×
2682
{
2683
        if(b!=flagPlanetsOrbitsOnly)
×
2684
        {
2685
                flagPlanetsOrbitsOnly = b;
×
2686
                StelApp::immediateSave("viewing/flag_planets_orbits_only", b);
×
2687
                emit flagPlanetsOrbitsOnlyChanged(b);
×
2688
        }
2689
}
×
2690

2691
bool SolarSystem::getFlagPlanetsOrbitsOnly() const
×
2692
{
2693
        return flagPlanetsOrbitsOnly;
×
2694
}
2695

2696
void SolarSystem::setFlagOrbitsWithMoons(bool b)
×
2697
{
2698
        if(b!=flagOrbitsWithMoons)
×
2699
        {
2700
                flagOrbitsWithMoons = b;
×
2701
                StelApp::immediateSave("viewing/flag_orbits_with_moons", b);
×
2702
                emit flagOrbitsWithMoonsChanged(b);
×
2703
        }
2704
}
×
2705

2706
bool SolarSystem::getFlagOrbitsWithMoons() const
×
2707
{
2708
        return flagOrbitsWithMoons;
×
2709
}
2710

2711
// Set/Get planets names color
2712
void SolarSystem::setLabelsColor(const Vec3f& c)
×
2713
{
2714
        if (c!=Planet::getLabelColor())
×
2715
        {
2716
                Planet::setLabelColor(c);
×
2717
                emit labelsColorChanged(c);
×
2718
        }
2719
}
×
2720

2721
Vec3f SolarSystem::getLabelsColor(void) const
×
2722
{
2723
        return Planet::getLabelColor();
×
2724
}
2725

2726
// Set/Get orbits lines color
2727
void SolarSystem::setOrbitsColor(const Vec3f& c)
×
2728
{
2729
        if (c!=Planet::getOrbitColor())
×
2730
        {
2731
                Planet::setOrbitColor(c);
×
2732
                emit orbitsColorChanged(c);
×
2733
        }
2734
}
×
2735

2736
Vec3f SolarSystem::getOrbitsColor(void) const
×
2737
{
2738
        return Planet::getOrbitColor();
×
2739
}
2740

2741
void SolarSystem::setMajorPlanetsOrbitsColor(const Vec3f &c)
×
2742
{
2743
        if (c!=Planet::getMajorPlanetOrbitColor())
×
2744
        {
2745
                Planet::setMajorPlanetOrbitColor(c);
×
2746
                emit majorPlanetsOrbitsColorChanged(c);
×
2747
        }
2748
}
×
2749

2750
Vec3f SolarSystem::getMajorPlanetsOrbitsColor(void) const
×
2751
{
2752
        return Planet::getMajorPlanetOrbitColor();
×
2753
}
2754

2755
void SolarSystem::setMinorPlanetsOrbitsColor(const Vec3f &c)
×
2756
{
2757
        if (c!=Planet::getMinorPlanetOrbitColor())
×
2758
        {
2759
                Planet::setMinorPlanetOrbitColor(c);
×
2760
                emit minorPlanetsOrbitsColorChanged(c);
×
2761
        }
2762
}
×
2763

2764
Vec3f SolarSystem::getMinorPlanetsOrbitsColor(void) const
×
2765
{
2766
        return Planet::getMinorPlanetOrbitColor();
×
2767
}
2768

2769
void SolarSystem::setDwarfPlanetsOrbitsColor(const Vec3f &c)
×
2770
{
2771
        if (c!=Planet::getDwarfPlanetOrbitColor())
×
2772
        {
2773
                Planet::setDwarfPlanetOrbitColor(c);
×
2774
                emit dwarfPlanetsOrbitsColorChanged(c);
×
2775
        }
2776
}
×
2777

2778
Vec3f SolarSystem::getDwarfPlanetsOrbitsColor(void) const
×
2779
{
2780
        return Planet::getDwarfPlanetOrbitColor();
×
2781
}
2782

2783
void SolarSystem::setMoonsOrbitsColor(const Vec3f &c)
×
2784
{
2785
        if (c!=Planet::getMoonOrbitColor())
×
2786
        {
2787
                Planet::setMoonOrbitColor(c);
×
2788
                emit moonsOrbitsColorChanged(c);
×
2789
        }
2790
}
×
2791

2792
Vec3f SolarSystem::getMoonsOrbitsColor(void) const
×
2793
{
2794
        return Planet::getMoonOrbitColor();
×
2795
}
2796

2797
void SolarSystem::setCubewanosOrbitsColor(const Vec3f &c)
×
2798
{
2799
        if (c!=Planet::getCubewanoOrbitColor())
×
2800
        {
2801
                Planet::setCubewanoOrbitColor(c);
×
2802
                emit cubewanosOrbitsColorChanged(c);
×
2803
        }
2804
}
×
2805

2806
Vec3f SolarSystem::getCubewanosOrbitsColor(void) const
×
2807
{
2808
        return Planet::getCubewanoOrbitColor();
×
2809
}
2810

2811
void SolarSystem::setPlutinosOrbitsColor(const Vec3f &c)
×
2812
{
2813
        if (c!=Planet::getPlutinoOrbitColor())
×
2814
        {
2815
                Planet::setPlutinoOrbitColor(c);
×
2816
                emit plutinosOrbitsColorChanged(c);
×
2817
        }
2818
}
×
2819

2820
Vec3f SolarSystem::getPlutinosOrbitsColor(void) const
×
2821
{
2822
        return Planet::getPlutinoOrbitColor();
×
2823
}
2824

2825
void SolarSystem::setScatteredDiskObjectsOrbitsColor(const Vec3f &c)
×
2826
{
2827
        if (c!=Planet::getScatteredDiscObjectOrbitColor())
×
2828
        {
2829
                Planet::setScatteredDiscObjectOrbitColor(c);
×
2830
                emit scatteredDiskObjectsOrbitsColorChanged(c);
×
2831
        }
2832
}
×
2833

2834
Vec3f SolarSystem::getScatteredDiskObjectsOrbitsColor(void) const
×
2835
{
2836
        return Planet::getScatteredDiscObjectOrbitColor();
×
2837
}
2838

2839
void SolarSystem::setOortCloudObjectsOrbitsColor(const Vec3f &c)
×
2840
{
2841
        if (c!=Planet::getOortCloudObjectOrbitColor())
×
2842
        {
2843
                Planet::setOortCloudObjectOrbitColor(c);
×
2844
                emit oortCloudObjectsOrbitsColorChanged(c);
×
2845
        }
2846
}
×
2847

2848
Vec3f SolarSystem::getOortCloudObjectsOrbitsColor(void) const
×
2849
{
2850
        return Planet::getOortCloudObjectOrbitColor();
×
2851
}
2852

2853
void SolarSystem::setCometsOrbitsColor(const Vec3f& c)
×
2854
{
2855
        if (c!=Planet::getCometOrbitColor())
×
2856
        {
2857
                Planet::setCometOrbitColor(c);
×
2858
                emit cometsOrbitsColorChanged(c);
×
2859
        }
2860
}
×
2861

2862
Vec3f SolarSystem::getCometsOrbitsColor(void) const
×
2863
{
2864
        return Planet::getCometOrbitColor();
×
2865
}
2866

2867
void SolarSystem::setSednoidsOrbitsColor(const Vec3f& c)
×
2868
{
2869
        if (c!=Planet::getSednoidOrbitColor())
×
2870
        {
2871
                Planet::setSednoidOrbitColor(c);
×
2872
                emit sednoidsOrbitsColorChanged(c);
×
2873
        }
2874
}
×
2875

2876
Vec3f SolarSystem::getSednoidsOrbitsColor(void) const
×
2877
{
2878
        return Planet::getSednoidOrbitColor();
×
2879
}
2880

2881
void SolarSystem::setInterstellarOrbitsColor(const Vec3f& c)
×
2882
{
2883
        if (c!=Planet::getInterstellarOrbitColor())
×
2884
        {
2885
                Planet::setInterstellarOrbitColor(c);
×
2886
                emit interstellarOrbitsColorChanged(c);
×
2887
        }
2888
}
×
2889

2890
Vec3f SolarSystem::getInterstellarOrbitsColor(void) const
×
2891
{
2892
        return Planet::getInterstellarOrbitColor();
×
2893
}
2894

2895
void SolarSystem::setMercuryOrbitColor(const Vec3f &c)
×
2896
{
2897
        if (c!=Planet::getMercuryOrbitColor())
×
2898
        {
2899
                Planet::setMercuryOrbitColor(c);
×
2900
                emit mercuryOrbitColorChanged(c);
×
2901
        }
2902
}
×
2903

2904
Vec3f SolarSystem::getMercuryOrbitColor(void) const
×
2905
{
2906
        return Planet::getMercuryOrbitColor();
×
2907
}
2908

2909
void SolarSystem::setVenusOrbitColor(const Vec3f &c)
×
2910
{
2911
        if (c!=Planet::getVenusOrbitColor())
×
2912
        {
2913
                Planet::setVenusOrbitColor(c);
×
2914
                emit venusOrbitColorChanged(c);
×
2915
        }
2916
}
×
2917

2918
Vec3f SolarSystem::getVenusOrbitColor(void) const
×
2919
{
2920
        return Planet::getVenusOrbitColor();
×
2921
}
2922

2923
void SolarSystem::setEarthOrbitColor(const Vec3f &c)
×
2924
{
2925
        if (c!=Planet::getEarthOrbitColor())
×
2926
        {
2927
                Planet::setEarthOrbitColor(c);
×
2928
                emit earthOrbitColorChanged(c);
×
2929
        }
2930
}
×
2931

2932
Vec3f SolarSystem::getEarthOrbitColor(void) const
×
2933
{
2934
        return Planet::getEarthOrbitColor();
×
2935
}
2936

2937
void SolarSystem::setMarsOrbitColor(const Vec3f &c)
×
2938
{
2939
        if (c!=Planet::getMarsOrbitColor())
×
2940
        {
2941
                Planet::setMarsOrbitColor(c);
×
2942
                emit marsOrbitColorChanged(c);
×
2943
        }
2944
}
×
2945

2946
Vec3f SolarSystem::getMarsOrbitColor(void) const
×
2947
{
2948
        return Planet::getMarsOrbitColor();
×
2949
}
2950

2951
void SolarSystem::setJupiterOrbitColor(const Vec3f &c)
×
2952
{
2953
        if (c!=Planet::getJupiterOrbitColor())
×
2954
        {
2955
                Planet::setJupiterOrbitColor(c);
×
2956
                emit jupiterOrbitColorChanged(c);
×
2957
        }
2958
}
×
2959

2960
Vec3f SolarSystem::getJupiterOrbitColor(void) const
×
2961
{
2962
        return Planet::getJupiterOrbitColor();
×
2963
}
2964

2965
void SolarSystem::setSaturnOrbitColor(const Vec3f &c)
×
2966
{
2967
        if (c!=Planet::getSaturnOrbitColor())
×
2968
        {
2969
                Planet::setSaturnOrbitColor(c);
×
2970
                emit saturnOrbitColorChanged(c);
×
2971
        }
2972
}
×
2973

2974
Vec3f SolarSystem::getSaturnOrbitColor(void) const
×
2975
{
2976
        return Planet::getSaturnOrbitColor();
×
2977
}
2978

2979
void SolarSystem::setUranusOrbitColor(const Vec3f &c)
×
2980
{
2981
        if (c!=Planet::getUranusOrbitColor())
×
2982
        {
2983
                Planet::setUranusOrbitColor(c);
×
2984
                emit uranusOrbitColorChanged(c);
×
2985
        }
2986
}
×
2987

2988
Vec3f SolarSystem::getUranusOrbitColor(void) const
×
2989
{
2990
        return Planet::getUranusOrbitColor();
×
2991
}
2992

2993
void SolarSystem::setNeptuneOrbitColor(const Vec3f &c)
×
2994
{
2995
        if (c!=Planet::getNeptuneOrbitColor())
×
2996
        {
2997
                Planet::setNeptuneOrbitColor(c);
×
2998
                emit neptuneOrbitColorChanged(c);
×
2999
        }
3000
}
×
3001

3002
Vec3f SolarSystem::getNeptuneOrbitColor(void) const
×
3003
{
3004
        return Planet::getNeptuneOrbitColor();
×
3005
}
3006

3007
// Set/Get if Moon display is scaled
3008
void SolarSystem::setFlagMoonScale(bool b)
×
3009
{
3010
        if(b!=flagMoonScale)
×
3011
        {
3012
                if (b) getMoon()->setSphereScale(moonScale);
×
3013
                else getMoon()->setSphereScale(1);
×
3014
                flagMoonScale = b;
×
3015
                emit flagMoonScaleChanged(b);
×
3016
        }
3017
}
×
3018

3019
// Set/Get Moon display scaling factor. This goes directly to the Moon object.
3020
void SolarSystem::setMoonScale(double f)
×
3021
{
3022
        if(!fuzzyEquals(moonScale, f))
×
3023
        {
3024
                moonScale = f;
×
3025
                if (flagMoonScale)
×
3026
                        getMoon()->setSphereScale(moonScale);
×
3027
                emit moonScaleChanged(f);
×
3028
        }
3029
}
×
3030

3031
// Set if minor body display is scaled. This flag will be queried by all Planet objects except for the Moon.
3032
void SolarSystem::setFlagMinorBodyScale(bool b)
×
3033
{
3034
        if(b!=flagMinorBodyScale)
×
3035
        {
3036
                flagMinorBodyScale = b;
×
3037

3038
                double newScale = b ? minorBodyScale : 1.0;
×
3039
                //update the bodies with the new scale
3040
                for (const auto& p : qAsConst(systemPlanets))
×
3041
                {
3042
                        if(p == moon) continue;
×
3043
                        if (p->getPlanetType()!=Planet::isPlanet && p->getPlanetType()!=Planet::isStar)
×
3044
                                p->setSphereScale(newScale);
×
3045
                }
3046
                emit flagMinorBodyScaleChanged(b);
×
3047
        }
3048
}
×
3049

3050
// Set minor body display scaling factor. This will be queried by all Planet objects except for the Moon.
3051
void SolarSystem::setMinorBodyScale(double f)
×
3052
{
3053
        if(!fuzzyEquals(minorBodyScale, f))
×
3054
        {
3055
                minorBodyScale = f;
×
3056
                if(flagMinorBodyScale) //update the bodies with the new scale
×
3057
                {
3058
                        for (const auto& p : qAsConst(systemPlanets))
×
3059
                        {
3060
                                if(p == moon) continue;
×
3061
                                if (p->getPlanetType()!=Planet::isPlanet && p->getPlanetType()!=Planet::isStar)
×
3062
                                        p->setSphereScale(minorBodyScale);
×
3063
                        }
3064
                }
3065
                emit minorBodyScaleChanged(f);
×
3066
        }
3067
}
×
3068

3069
// Set if Planet display is scaled
3070
void SolarSystem::setFlagPlanetScale(bool b)
×
3071
{
3072
        if(b!=flagPlanetScale)
×
3073
        {
3074
                double scale=(b ? planetScale : 1.);
×
3075
                for (auto& p : systemPlanets)
×
3076
                {
3077
                        if (p->pType==Planet::isPlanet)
×
3078
                                p->setSphereScale(scale);
×
3079
                }
3080
                flagPlanetScale = b;
×
3081
                emit flagPlanetScaleChanged(b);
×
3082
        }
3083
}
×
3084

3085
// Set Moon display scaling factor.
3086
void SolarSystem::setPlanetScale(double f)
×
3087
{
3088
        if(!fuzzyEquals(planetScale, f))
×
3089
        {
3090
                planetScale = f;
×
3091
                if (flagPlanetScale)
×
3092
                        for (auto& p : systemPlanets)
×
3093
                        {
3094
                                if (p->pType==Planet::isPlanet)
×
3095
                                        p->setSphereScale(planetScale);
×
3096
                        }
3097
                emit planetScaleChanged(f);
×
3098
        }
3099
}
×
3100

3101
// Set if Sun display is scaled
3102
void SolarSystem::setFlagSunScale(bool b)
×
3103
{
3104
        if(b!=flagSunScale)
×
3105
        {
3106
                if (b) getSun()->setSphereScale(sunScale);
×
3107
                else getSun()->setSphereScale(1);
×
3108
                flagSunScale = b;
×
3109
                emit flagSunScaleChanged(b);
×
3110
        }
3111
}
×
3112

3113
// Set Sun display scaling factor. This goes directly to the Sun object.
3114
void SolarSystem::setSunScale(double f)
×
3115
{
3116
        if(!fuzzyEquals(sunScale, f))
×
3117
        {
3118
                sunScale = f;
×
3119
                if (flagSunScale)
×
3120
                        getSun()->setSphereScale(sunScale);
×
3121
                emit sunScaleChanged(f);
×
3122
        }
3123
}
×
3124

3125
// Set selected planets by englishName
3126
void SolarSystem::setSelected(const QString& englishName)
×
3127
{
3128
        setSelected(searchByEnglishName(englishName));
×
3129
}
×
3130

3131
// Get the list of all the planet english names
3132
QStringList SolarSystem::getAllPlanetEnglishNames() const
×
3133
{
3134
        QStringList res;
×
3135
        for (const auto& p : systemPlanets)
×
3136
                res.append(p->getEnglishName());
×
3137
        return res;
×
3138
}
×
3139

3140
QStringList SolarSystem::getAllPlanetLocalizedNames() const
×
3141
{
3142
        QStringList res;
×
3143
        for (const auto& p : systemPlanets)
×
3144
                res.append(p->getNameI18n());
×
3145
        return res;
×
3146
}
×
3147

3148
QStringList SolarSystem::getAllMinorPlanetCommonEnglishNames() const
×
3149
{
3150
        QStringList res;
×
3151
        for (const auto& p : systemMinorBodies)
×
3152
                res.append(p->getCommonEnglishName());
×
3153
        return res;
×
3154
}
×
3155

3156

3157
// 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.
3158
void SolarSystem::reloadPlanets()
×
3159
{
3160
        // Save flag states
3161
        const bool flagScaleMoon = getFlagMoonScale();
×
3162
        const double moonScale = getMoonScale();
×
3163
        const bool flagScaleMinorBodies=getFlagMinorBodyScale();
×
3164
        const double minorScale= getMinorBodyScale();
×
3165
        const bool flagPlanets = getFlagPlanets();
×
3166
        const bool flagHints = getFlagHints();
×
3167
        const bool flagLabels = getFlagLabels();
×
3168
        const bool flagOrbits = getFlagOrbits();
×
3169
        const bool flagNative = getFlagNativePlanetNames();
×
3170
        bool hasSelection = false;
×
3171

3172
        // Save observer location (fix for LP bug # 969211)
3173
        // TODO: This can probably be done better with a better understanding of StelObserver --BM
3174
        StelCore* core = StelApp::getInstance().getCore();
×
3175
        const StelLocation loc = core->getCurrentLocation();
×
3176
        StelObjectMgr* objMgr = GETSTELMODULE(StelObjectMgr);
×
3177

3178
        // Whether any planet are selected? Save the current selection...
3179
        const QList<StelObjectP> selectedObject = objMgr->getSelectedObject("Planet");
×
3180
        if (!selectedObject.isEmpty())
×
3181
        {
3182
                // ... unselect current planet.
3183
                hasSelection = true;
×
3184
                objMgr->unSelect();
×
3185
        }
3186
        // Unload all Solar System objects
3187
        selected.clear();//Release the selected one
×
3188

3189
        // GZ TODO in case this methods gets converted to only reload minor bodies: Only delete Orbits which are not referenced by some Planet.
3190
        for (auto* orb : qAsConst(orbits))
×
3191
        {
3192
                delete orb;
×
3193
        }
3194
        orbits.clear();
×
3195

3196
        sun.clear();
×
3197
        moon.clear();
×
3198
        earth.clear();
×
3199
        Planet::texEarthShadow.clear(); //Loaded in loadPlanets()
×
3200

3201
        delete allTrails;
×
3202
        allTrails = Q_NULLPTR;
×
3203

3204
        for (const auto& p : qAsConst(systemPlanets))
×
3205
        {
3206
                p->satellites.clear();
×
3207
        }
3208
        systemPlanets.clear();
×
3209
        systemMinorBodies.clear();
×
3210
        // Memory leak? What's the proper way of cleaning shared pointers?
3211

3212
        // Also delete Comet textures (loaded in loadPlanets()
3213
        Comet::tailTexture.clear();
×
3214
        Comet::comaTexture.clear();
×
3215

3216
        // Re-load the ssystem_major.ini and ssystem_minor.ini file
3217
        loadPlanets();        
×
3218
        computePositions(core->getJDE(), getSun());
×
3219
        setSelected("");
×
3220
        recreateTrails();
×
3221
        
3222
        // Restore observer location
3223
        core->moveObserverTo(loc, 0., 0.);
×
3224

3225
        // Restore flag states
3226
        setFlagMoonScale(flagScaleMoon);
×
3227
        setMoonScale(moonScale);
×
3228
        setFlagMinorBodyScale(flagScaleMinorBodies);
×
3229
        setMinorBodyScale(1.0); // force-reset first to really reach the objects in the next call.
×
3230
        setMinorBodyScale(minorScale);
×
3231
        setFlagPlanets(flagPlanets);
×
3232
        setFlagHints(flagHints);
×
3233
        setFlagLabels(flagLabels);
×
3234
        setFlagOrbits(flagOrbits);
×
3235
        setFlagNativePlanetNames(flagNative);
×
3236

3237
        // Restore translations
3238
        updateI18n();
×
3239

3240
        if (hasSelection)
×
3241
        {
3242
                // Restore selection...
3243
                StelObjectP obj = selectedObject[0];
×
3244
                objMgr->findAndSelect(obj->getEnglishName(), obj->getType());
×
3245
        }
×
3246

3247
        emit solarSystemDataReloaded();
×
3248
}
×
3249

3250
// Set the algorithm for computation of apparent magnitudes for planets in case  observer on the Earth
3251
void SolarSystem::setApparentMagnitudeAlgorithmOnEarth(QString algorithm)
×
3252
{
3253
        Planet::setApparentMagnitudeAlgorithm(algorithm);
×
3254
        emit apparentMagnitudeAlgorithmOnEarthChanged(algorithm);
×
3255
}
×
3256

3257
// Get the algorithm used for computation of apparent magnitudes for planets in case  observer on the Earth
3258
QString SolarSystem::getApparentMagnitudeAlgorithmOnEarth() const
×
3259
{
3260
        return Planet::getApparentMagnitudeAlgorithmString();
×
3261
}
3262

3263
void SolarSystem::setFlagDrawMoonHalo(bool b)
×
3264
{
3265
        Planet::drawMoonHalo=b;
×
3266
        emit flagDrawMoonHaloChanged(b);
×
3267
}
×
3268

3269
bool SolarSystem::getFlagDrawMoonHalo() const
×
3270
{
3271
        return Planet::drawMoonHalo;
×
3272
}
3273

3274
void SolarSystem::setFlagDrawSunHalo(bool b)
×
3275
{
3276
        Planet::drawSunHalo=b;
×
3277
        emit flagDrawSunHaloChanged(b);
×
3278
}
×
3279

3280
bool SolarSystem::getFlagDrawSunHalo() const
×
3281
{
3282
        return Planet::drawSunHalo;
×
3283
}
3284

3285
void SolarSystem::setFlagPermanentOrbits(bool b)
×
3286
{
3287
        if (Planet::permanentDrawingOrbits!=b)
×
3288
        {
3289
                Planet::permanentDrawingOrbits=b;
×
3290
                StelApp::immediateSave("astro/flag_permanent_orbits", b);
×
3291
                emit flagPermanentOrbitsChanged(b);
×
3292
        }
3293
}
×
3294

3295
bool SolarSystem::getFlagPermanentOrbits() const
×
3296
{
3297
        return Planet::permanentDrawingOrbits;
×
3298
}
3299

3300
void SolarSystem::setOrbitsThickness(int v)
×
3301
{
3302
        if (v!=Planet::orbitsThickness)
×
3303
        {
3304
                Planet::orbitsThickness=v;
×
3305
                StelApp::immediateSave("astro/object_orbits_thickness", v);
×
3306
                emit orbitsThicknessChanged(v);
×
3307
        }
3308
}
×
3309

3310
int SolarSystem::getOrbitsThickness() const
×
3311
{
3312
        return Planet::orbitsThickness;
×
3313
}
3314

3315
void SolarSystem::setGrsLongitude(int longitude)
×
3316
{
3317
        RotationElements::grsLongitude = longitude;
×
3318
        // automatic saving of the setting
3319
        conf->setValue("astro/grs_longitude", longitude);
×
3320
        emit grsLongitudeChanged(longitude);
×
3321
}
×
3322

3323
int SolarSystem::getGrsLongitude() const
×
3324
{
3325
        return static_cast<int>(RotationElements::grsLongitude);
×
3326
}
3327

3328
void SolarSystem::setGrsDrift(double drift)
×
3329
{
3330
        RotationElements::grsDrift = drift;
×
3331
        // automatic saving of the setting
3332
        conf->setValue("astro/grs_drift", drift);
×
3333
        emit grsDriftChanged(drift);
×
3334
}
×
3335

3336
double SolarSystem::getGrsDrift() const
×
3337
{
3338
        return RotationElements::grsDrift;
×
3339
}
3340

3341
void SolarSystem::setGrsJD(double JD)
×
3342
{
3343
        RotationElements::grsJD = JD;
×
3344
        // automatic saving of the setting
3345
        conf->setValue("astro/grs_jd", JD);
×
3346
        emit grsJDChanged(JD);
×
3347
}
×
3348

3349
double SolarSystem::getGrsJD()
×
3350
{
3351
        return RotationElements::grsJD;
×
3352
}
3353

3354
void SolarSystem::setFlagEarthShadowEnlargementDanjon(bool b)
×
3355
{
3356
        earthShadowEnlargementDanjon=b;
×
3357
        emit earthShadowEnlargementDanjonChanged(b);
×
3358
}
×
3359

3360
bool SolarSystem::getFlagEarthShadowEnlargementDanjon() const
×
3361
{
3362
        return earthShadowEnlargementDanjon;
×
3363
}
3364

3365
void SolarSystem::setOrbitColorStyle(QString style)
×
3366
{
3367
        if (style.toLower()=="groups")
×
3368
                Planet::orbitColorStyle = Planet::ocsGroups;
×
3369
        else if (style.toLower()=="major_planets")
×
3370
                Planet::orbitColorStyle = Planet::ocsMajorPlanets;
×
3371
        else
3372
                Planet::orbitColorStyle = Planet::ocsOneColor;
×
3373
}
×
3374

3375
QString SolarSystem::getOrbitColorStyle() const
×
3376
{
3377
        static const QMap<Planet::PlanetOrbitColorStyle, QString>map={
3378
                { Planet::ocsOneColor,     "one_color"},
×
3379
                { Planet::ocsGroups,       "groups"},
×
3380
                { Planet::ocsMajorPlanets, "major_planets"}
×
3381
        };
×
3382
        return map.value(Planet::orbitColorStyle, "one_color");
×
3383
}
3384

3385
// TODO: To make the code better understandable, get rid of planet->computeModelMatrix(trans, true) here.
3386
QPair<double, PlanetP> SolarSystem::getSolarEclipseFactor(const StelCore* core) const
×
3387
{
3388
        PlanetP p;
×
3389
        const Vec3d Lp = sun->getEclipticPos() + sun->getAberrationPush();
×
3390
        const Vec3d P3 = core->getObserverHeliocentricEclipticPos();
×
3391
        const double RS = sun->getEquatorialRadius();
×
3392

3393
        double final_illumination = 1.0;
×
3394

3395
        for (const auto& planet : systemPlanets)
×
3396
        {
3397
                if(planet == sun || planet == core->getCurrentPlanet())
×
3398
                        continue;
×
3399

3400
                Mat4d trans;
×
3401
                planet->computeModelMatrix(trans, true);
×
3402

3403
                const Vec3d C = trans * Vec3d(0., 0., 0.);
×
3404
                const double radius = planet->getEquatorialRadius();
×
3405

3406
                Vec3d v1 = Lp - P3;
×
3407
                Vec3d v2 = C - P3;
×
3408
                const double L = v1.norm();
×
3409
                const double l = v2.norm();
×
3410
                v1 /= L;
×
3411
                v2 /= l;
×
3412

3413
                const double R = RS / L;
×
3414
                const double r = radius / l;
×
3415
                const double d = ( v1 - v2 ).norm();
×
3416
                double illumination;
3417

3418
                if(d >= R + r) // distance too far
×
3419
                {
3420
                        illumination = 1.0;
×
3421
                }
3422
                else if(d <= r - R) // umbra
×
3423
                {
3424
                        illumination = 0.0;
×
3425
                }
3426
                else if(d <= R - r) // penumbra completely inside
×
3427
                {
3428
                        illumination = 1.0 - r * r / (R * R);
×
3429
                }
3430
                else // penumbra partially inside
3431
                {
3432
                        const double x = (R * R + d * d - r * r) / (2.0 * d);
×
3433

3434
                        const double alpha = std::acos(x / R);
×
3435
                        const double beta = std::acos((d - x) / r);
×
3436

3437
                        const double AR = R * R * (alpha - 0.5 * std::sin(2.0 * alpha));
×
3438
                        const double Ar = r * r * (beta - 0.5 * std::sin(2.0 * beta));
×
3439
                        const double AS = R * R * 2.0 * std::asin(1.0);
×
3440

3441
                        illumination = 1.0 - (AR + Ar) / AS;
×
3442
                }
3443

3444
                if(illumination < final_illumination)
×
3445
                {
3446
                        final_illumination = illumination;
×
3447
                        p = planet;
×
3448
                }
3449
        }
3450

3451
        return QPair<double, PlanetP>(final_illumination, p);
×
3452
}
×
3453

3454
// Retrieve Radius of Umbra and Penumbra at the distance of the Moon.
3455
// Returns a pair (umbra, penumbra) in (geocentric_arcseconds, AU, geometric_AU).
3456
// * sizes in arcseconds are the usual result found as Bessel element in eclipse literature.
3457
//   It includes scaling for effects of atmosphere either after Chauvenet (2%) or after Danjon. (see Espenak: 5000 Years Canon of Lunar Eclipses.)
3458
// * sizes in AU are the same, converted back to AU in Lunar distance.
3459
// * sizes in geometric_AU derived from pure geometrical evaluations without scalings applied.
3460
QPair<Vec3d,Vec3d> SolarSystem::getEarthShadowRadiiAtLunarDistance() const
×
3461
{
3462
        // Note: The application of this shadow enlargement is not according to the books, but looks close enough for now.
3463
        static const double sun2earth=sun->getEquatorialRadius() / earth->getEquatorialRadius();
×
3464
        PlanetP sun=getSun();
×
3465
        PlanetP moon=getMoon();
×
3466
        PlanetP earth=getEarth();
×
3467
        const double lunarDistance=moon->getEclipticPos().norm(); // Lunar distance [AU]
×
3468
        const double earthDistance=earth->getHeliocentricEclipticPos().norm(); // Earth distance [AU]
×
3469
        const double sunHP =asin(earth->getEquatorialRadius()/earthDistance) * M_180_PI*3600.; // arcsec.
×
3470
        const double moonHP=asin(earth->getEquatorialRadius()/lunarDistance) * M_180_PI*3600.; // arcsec.
×
3471
        const double sunSD  =atan(sun->getEquatorialRadius()/earthDistance)  * M_180_PI*3600.; // arcsec.
×
3472

3473
        // Compute umbra radius at lunar distance.
3474
        const double lUmbra=earthDistance/(sun2earth-1.); // length of earth umbra [AU]
×
3475
        const double rUmbraAU=earth->getEquatorialRadius()*(lUmbra-lunarDistance)/lUmbra; // radius of earth shadow at lunar distance [AU]
×
3476
        // Penumbra:
3477
        const double lPenumbra=earthDistance/(sun2earth + 1.); // distance between earth and point between sun and earth where penumbral border rays intersect
×
3478
        const double rPenumbraAU=earth->getEquatorialRadius()*(lPenumbra+lunarDistance)/lPenumbra; // radius of penumbra at Lunar distance [AU]
×
3479

3480
        //Classical Bessel elements instead
3481
        double f1, f2;
3482
        if (earthShadowEnlargementDanjon)
×
3483
        {
3484
                static const double danjonScale=1+1./85.-1./594.; // ~1.01, shadow magnification factor (see Espenak 5000 years Canon)
3485
                f1=danjonScale*moonHP + sunHP + sunSD; // penumbra radius, arcsec
×
3486
                f2=danjonScale*moonHP + sunHP - sunSD; // umbra radius, arcsec
×
3487
        }
3488
        else
3489
        {
3490
                const double mHP1=0.998340*moonHP;
×
3491
                f1=1.02*(mHP1 + sunHP + sunSD); // penumbra radius, arcsec
×
3492
                f2=1.02*(mHP1 + sunHP - sunSD); // umbra radius, arcsec
×
3493
        }
3494
        const double f1_AU=tan(f1/3600.*M_PI_180)*lunarDistance;
×
3495
        const double f2_AU=tan(f2/3600.*M_PI_180)*lunarDistance;
×
3496
        return QPair<Vec3d,Vec3d>(Vec3d(f2, f2_AU, rUmbraAU), Vec3d(f1, f1_AU, rPenumbraAU));
×
3497
}
×
3498

3499
bool SolarSystem::removeMinorPlanet(QString name)
×
3500
{
3501
        PlanetP candidate = searchMinorPlanetByEnglishName(name);
×
3502
        if (!candidate)
×
3503
        {
3504
                qWarning() << "Cannot remove planet " << name << ": Not found.";
×
3505
                return false;
×
3506
        }
3507
        Orbit* orbPtr=static_cast<Orbit*>(candidate->orbitPtr);
×
3508
        if (orbPtr)
×
3509
                orbits.removeOne(orbPtr);
×
3510
        systemPlanets.removeOne(candidate);
×
3511
        systemMinorBodies.removeOne(candidate);
×
3512
        candidate.clear();
×
3513
        return true;
×
3514
}
×
3515

3516
void SolarSystem::onNewSurvey(HipsSurveyP survey)
×
3517
{
3518
        // For the moment we only consider the survey url to decide if we
3519
        // assign it to a planet.  It would be better to use some property
3520
        // for that.
3521
        QString planetName = QUrl(survey->getUrl()).fileName();
×
3522
        PlanetP pl = searchByEnglishName(planetName);
×
3523
        if (!pl || pl->survey)
×
3524
                return;
×
3525
        pl->survey = survey;
×
3526
        survey->setProperty("planet", pl->getCommonEnglishName());
×
3527
        // Not visible by default for the moment.
3528
        survey->setProperty("visible", false);
×
3529
}
×
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