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

Stellarium / stellarium / 5809629656

pending completion
5809629656

Pull #3359

github

gzotti
Fixed spelling
Pull Request #3359: Restore drawing of orbits on open KeplerOrbits.

19 of 19 new or added lines in 4 files covered. (100.0%)

14813 of 124521 relevant lines covered (11.9%)

26969.66 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 given in days.
1233
                // Elliptical Kepler orbits (ecc<0.9) will replace whatever is given by a value computed on the fly. Parabolic objects show 0.
1234
                newP->setSiderealPeriod(fabs(pd.value(secname+"/orbit_Period", 0.).toDouble()));
×
1235

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

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

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

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

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

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

1269
        return true;
×
1270
}
×
1271

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1759

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

1771

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

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

1806
        return StelObjectP();
×
1807
}
1808

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

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

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

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

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

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

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

1884
        return r;
×
1885
}
×
1886

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2092

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

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

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

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

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

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

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

2130
        return true;
×
2131
}
2132

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3155

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

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

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

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

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

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

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

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

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

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

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

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

3246
        emit solarSystemDataReloaded();
×
3247
}
×
3248

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3392
        double final_illumination = 1.0;
×
3393

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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