~ubuntu-branches/ubuntu/precise/stellarium/precise

« back to all changes in this revision

Viewing changes to src/SolarSystem.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Cédric Delfosse
  • Date: 2008-05-19 21:28:23 UTC
  • mfrom: (3.1.5 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080519212823-m5nfiuntxstxzxj7
Tags: 0.9.1-4
Add libxcursor-dev, libxfixes-dev, libxinerama-dev, libqt4-opengl-dev to
build-deps (Closes: #479906)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Stellarium
 
3
 * Copyright (C) 2002 Fabien Chereau
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU General Public License
 
7
 * as published by the Free Software Foundation; either version 2
 
8
 * of the License, or (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program; if not, write to the Free Software
 
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
18
 */
 
19
 
 
20
 
 
21
#include <algorithm>
 
22
#include <iostream>
 
23
#include <string>
 
24
#include "SolarSystem.hpp"
 
25
#include "STexture.hpp"
 
26
#include "stellplanet.h"
 
27
#include "orbit.h"
 
28
#include "InitParser.hpp"
 
29
#include "Navigator.hpp"
 
30
#include "Projector.hpp"
 
31
#include "StelApp.hpp"
 
32
#include "StelCore.hpp"
 
33
#include "StelTextureMgr.hpp"
 
34
#include "StelObjectMgr.hpp"
 
35
#include "StelFontMgr.hpp"
 
36
#include "StelLocaleMgr.hpp"
 
37
#include "StelSkyCultureMgr.hpp"
 
38
#include "StelFileMgr.hpp"
 
39
#include "StelModuleMgr.hpp"
 
40
#include "Planet.hpp"
 
41
#include <QTextStream>
 
42
 
 
43
using namespace std;
 
44
 
 
45
SolarSystem::SolarSystem()
 
46
        :sun(NULL),moon(NULL),earth(NULL),selected(NULL),
 
47
        moonScale(1.), fontSize(14.),
 
48
        planet_name_font(StelApp::getInstance().getFontManager().getStandardFont(StelApp::getInstance().getLocaleMgr().getAppLanguage(), fontSize)),
 
49
        flagOrbits(false),flag_light_travel_time(false), lastHomePlanet(NULL)
 
50
{
 
51
        setObjectName("SolarSystem");
 
52
}
 
53
 
 
54
void SolarSystem::setFontSize(float newFontSize)
 
55
{
 
56
        planet_name_font = StelApp::getInstance().getFontManager().getStandardFont(StelApp::getInstance().getLocaleMgr().getSkyLanguage(), fontSize);
 
57
}
 
58
 
 
59
SolarSystem::~SolarSystem()
 
60
{
 
61
          // release selected:
 
62
        selected = NULL;
 
63
        for(vector<Planet*>::iterator iter = system_planets.begin(); iter != system_planets.end(); ++iter)
 
64
        {
 
65
                if (*iter) delete *iter;
 
66
                *iter = NULL;
 
67
        }
 
68
        for(vector<Orbit*>::iterator iter = orbits.begin(); iter != orbits.end(); ++iter)
 
69
        {
 
70
                if (*iter) delete *iter;
 
71
                *iter = NULL;
 
72
        }
 
73
        sun = NULL;
 
74
        moon = NULL;
 
75
        earth = NULL;
 
76
}
 
77
 
 
78
/*************************************************************************
 
79
 Reimplementation of the getCallOrder method
 
80
*************************************************************************/
 
81
double SolarSystem::getCallOrder(StelModuleActionName actionName) const
 
82
{
 
83
        if (actionName==StelModule::ACTION_DRAW)
 
84
                return StelApp::getInstance().getModuleMgr().getModule("StarMgr")->getCallOrder(actionName)+10;
 
85
        return 0;
 
86
}
 
87
 
 
88
// Init and load the solar system data
 
89
void SolarSystem::init(const InitParser& conf)
 
90
{
 
91
        loadPlanets();  // Load planets data
 
92
 
 
93
        // Compute position and matrix of sun and all the satellites (ie planets)
 
94
        // for the first initialization assert that center is sun center (only impacts on light speed correction)
 
95
        computePositions(StelUtils::getJDFromSystem());
 
96
        setSelected("");        // Fix a bug on macosX! Thanks Fumio!
 
97
        setScale(conf.get_double ("stars:star_scale"));  // if reload config
 
98
        setFlagMoonScale(conf.get_boolean("viewing", "flag_moon_scaled", conf.get_boolean("viewing", "flag_init_moon_scaled", false)));  // name change
 
99
        setMoonScale(conf.get_double ("viewing","moon_scale",5.));
 
100
        setFlagPlanets(conf.get_boolean("astro:flag_planets"));
 
101
        setFlagHints(conf.get_boolean("astro:flag_planets_hints"));
 
102
        setFlagOrbits(conf.get_boolean("astro:flag_planets_orbits"));
 
103
        setFlagLightTravelTime(conf.get_boolean("astro:flag_light_travel_time"));
 
104
        setFlagTrails(conf.get_boolean("astro", "flag_object_trails", false));
 
105
        startTrails(conf.get_boolean("astro", "flag_object_trails", false));    
 
106
        
 
107
        StelApp::getInstance().getStelObjectMgr().registerStelObjectMgr(this);
 
108
        texPointer = StelApp::getInstance().getTextureManager().createTexture("pointeur4.png");
 
109
}
 
110
 
 
111
void SolarSystem::drawPointer(const Projector* prj, const Navigator * nav)
 
112
{
 
113
        const std::vector<StelObjectP> newSelected = StelApp::getInstance().getStelObjectMgr().getSelectedObject("Planet");
 
114
        if (!newSelected.empty())
 
115
        {
 
116
                const StelObjectP obj = newSelected[0];
 
117
                Vec3d pos=obj->getObsJ2000Pos(nav);
 
118
                Vec3d screenpos;
 
119
                prj->setCurrentFrame(Projector::FRAME_J2000);
 
120
                // Compute 2D pos and return if outside screen
 
121
                if (!prj->project(pos, screenpos)) return;
 
122
        
 
123
                glColor3f(1.0f,0.3f,0.3f);
 
124
        
 
125
                float size = obj->getOnScreenSize(prj, nav);
 
126
                size+=26.f + 10.f*std::sin(2.f * StelApp::getInstance().getTotalRunTime());
 
127
 
 
128
                texPointer->bind();
 
129
 
 
130
        glEnable(GL_TEXTURE_2D);
 
131
        glEnable(GL_BLEND);
 
132
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Normal transparency mode
 
133
        
 
134
        glPushMatrix();
 
135
        glTranslatef(screenpos[0], screenpos[1], 0.0f);
 
136
        glRotatef(StelApp::getInstance().getTotalRunTime()*10.,0,0,-1);
 
137
 
 
138
        glTranslatef(-size/2, -size/2,0.0f);
 
139
        glRotatef(90,0,0,1);
 
140
        glBegin(GL_QUADS );
 
141
            glTexCoord2f(0.0f,0.0f);    glVertex3f(-10,-10,0);      //Bas Gauche
 
142
            glTexCoord2f(1.0f,0.0f);    glVertex3f(10,-10,0);       //Bas Droite
 
143
            glTexCoord2f(1.0f,1.0f);    glVertex3f(10,10,0);        //Haut Droit
 
144
            glTexCoord2f(0.0f,1.0f);    glVertex3f(-10,10,0);       //Haut Gauche
 
145
        glEnd ();
 
146
 
 
147
        glRotatef(-90,0,0,1);
 
148
        glTranslatef(0,size,0.0f);
 
149
        glBegin(GL_QUADS );
 
150
            glTexCoord2f(0.0f,0.0f);    glVertex3f(-10,-10,0);      //Bas Gauche
 
151
            glTexCoord2f(1.0f,0.0f);    glVertex3f(10,-10,0);       //Bas Droite
 
152
            glTexCoord2f(1.0f,1.0f);    glVertex3f(10,10,0);        //Haut Droit
 
153
            glTexCoord2f(0.0f,1.0f);    glVertex3f(-10,10,0);       //Haut Gauche
 
154
        glEnd ();
 
155
 
 
156
        glRotatef(-90,0,0,1);
 
157
        glTranslatef(0, size,0.0f);
 
158
        glBegin(GL_QUADS );
 
159
            glTexCoord2f(0.0f,0.0f);    glVertex3f(-10,-10,0);      //Bas Gauche
 
160
            glTexCoord2f(1.0f,0.0f);    glVertex3f(10,-10,0);       //Bas Droite
 
161
            glTexCoord2f(1.0f,1.0f);    glVertex3f(10,10,0);        //Haut Droit
 
162
            glTexCoord2f(0.0f,1.0f);    glVertex3f(-10,10,0);       //Haut Gauche
 
163
        glEnd ();
 
164
 
 
165
        glRotatef(-90,0,0,1);
 
166
        glTranslatef(0,size,0);
 
167
        glBegin(GL_QUADS );
 
168
            glTexCoord2f(0.0f,0.0f);    glVertex3f(-10,-10,0);      //Bas Gauche
 
169
            glTexCoord2f(1.0f,0.0f);    glVertex3f(10,-10,0);       //Bas Droite
 
170
            glTexCoord2f(1.0f,1.0f);    glVertex3f(10,10,0);        //Haut Droit
 
171
            glTexCoord2f(0.0f,1.0f);    glVertex3f(-10,10,0);       //Haut Gauche
 
172
        glEnd ();
 
173
                glPopMatrix();
 
174
        }
 
175
}
 
176
 
 
177
// Init and load the solar system data
 
178
void SolarSystem::loadPlanets()
 
179
{
 
180
        cout << "Loading Solar System data...";
 
181
        InitParser pd;  // The Planet data ini file parser
 
182
        try
 
183
        {
 
184
                pd.load(StelApp::getInstance().getFileMgr().findFile("data/ssystem.ini"));
 
185
        }
 
186
        catch(exception& e)
 
187
        {
 
188
                cerr << "ERROR while loading ssysyem.ini: " << e.what() << endl;
 
189
                return;
 
190
        }
 
191
 
 
192
        int nbSections = pd.get_nsec();
 
193
        for (int i = 0;i<nbSections;++i)
 
194
        {
 
195
                const string secname = pd.get_secname(i);
 
196
                const string englishName = pd.get_str(secname, "name");
 
197
 
 
198
                const string str_parent = pd.get_str(secname, "parent");
 
199
                Planet *parent = NULL;
 
200
 
 
201
                if (str_parent!="none")
 
202
                {
 
203
                        // Look in the other planets the one named with str_parent
 
204
                        vector<Planet*>::iterator iter = system_planets.begin();
 
205
                        while (iter != system_planets.end())
 
206
                        {
 
207
                                if ((*iter)->getEnglishName()==str_parent)
 
208
                                {
 
209
                                        parent = (*iter);
 
210
                                }
 
211
                                iter++;
 
212
                        }
 
213
                        if (parent == NULL)
 
214
                        {
 
215
                                cout << "ERROR : can't find parent for " << englishName << endl;
 
216
                                assert(0);
 
217
                        }
 
218
                }
 
219
 
 
220
                const string funcname = pd.get_str(secname, "coord_func");
 
221
                pos_func_type posfunc;
 
222
                OsulatingFunctType *osculating_func = 0;
 
223
                bool close_orbit = pd.get_boolean(secname, "close_orbit", 1);
 
224
 
 
225
                if (funcname=="ell_orbit")
 
226
                {
 
227
                        // Read the orbital elements
 
228
                        const double epoch = pd.get_double(secname, "orbit_Epoch",J2000);
 
229
                        const double eccentricity = pd.get_double(secname, "orbit_Eccentricity");
 
230
                        if (eccentricity >= 1.0) close_orbit = false;
 
231
                        double pericenter_distance = pd.get_double(secname,"orbit_PericenterDistance",-1e100);
 
232
                        double semi_major_axis;
 
233
                        if (pericenter_distance <= 0.0) {
 
234
                                semi_major_axis = pd.get_double(secname,"orbit_SemiMajorAxis",-1e100);
 
235
                                if (semi_major_axis <= -1e100) {
 
236
                                        cerr << "ERROR: " << englishName
 
237
                                             << ": you must provide orbit_PericenterDistance or orbit_SemiMajorAxis"
 
238
                                             << endl;
 
239
                                        assert(0);
 
240
                                } else {
 
241
                                        semi_major_axis /= AU;
 
242
                                        assert(eccentricity != 1.0); // parabolic orbits have no semi_major_axis
 
243
                                        pericenter_distance = semi_major_axis * (1.0-eccentricity);
 
244
                                }
 
245
                        } else {
 
246
                                pericenter_distance /= AU;
 
247
                                semi_major_axis = (eccentricity == 1.0)
 
248
                                                ? 0.0 // parabolic orbits have no semi_major_axis
 
249
                                                : pericenter_distance / (1.0-eccentricity);
 
250
                        }
 
251
                        double mean_motion = pd.get_double(secname,"orbit_MeanMotion",-1e100);
 
252
                        double period;
 
253
                        if (mean_motion <= -1e100) {
 
254
                                period = pd.get_double(secname,"orbit_Period",-1e100);
 
255
                                if (period <= -1e100) {
 
256
                                        mean_motion = (eccentricity == 1.0)
 
257
                                                    ? 0.01720209895 * (1.5/pericenter_distance)
 
258
                                                                    * sqrt(0.5/pericenter_distance)
 
259
                                                    : (semi_major_axis > 0.0)
 
260
                                                    ? 0.01720209895 / (semi_major_axis*sqrt(semi_major_axis))
 
261
                                                    : 0.01720209895 / (-semi_major_axis*sqrt(-semi_major_axis));
 
262
                                        period = 2.0*M_PI/mean_motion;
 
263
                                } else {
 
264
                                        mean_motion = 2.0*M_PI/period;
 
265
                                }
 
266
                        } else {
 
267
                                period = 2.0*M_PI/mean_motion;
 
268
                        }
 
269
                        const double inclination = pd.get_double(secname, "orbit_Inclination")*(M_PI/180.0);
 
270
                        const double ascending_node = pd.get_double(secname, "orbit_AscendingNode")*(M_PI/180.0);
 
271
                        double arg_of_pericenter = pd.get_double(secname,"orbit_ArgOfPericenter",-1e100);
 
272
                        double long_of_pericenter;
 
273
                        if (arg_of_pericenter <= -1e100) {
 
274
                                long_of_pericenter = pd.get_double(secname,"orbit_LongOfPericenter")*(M_PI/180.0);
 
275
                                arg_of_pericenter = long_of_pericenter - ascending_node;
 
276
                        } else {
 
277
                arg_of_pericenter *= (M_PI/180.0);
 
278
                                long_of_pericenter = arg_of_pericenter + ascending_node;
 
279
                        }
 
280
                        double mean_anomaly = pd.get_double(secname,"orbit_MeanAnomaly",-1e100);
 
281
            double mean_longitude;
 
282
                        if (mean_anomaly <= -1e100) {
 
283
                                mean_longitude = pd.get_double(secname, "orbit_MeanLongitude")*(M_PI/180.0);
 
284
                                mean_anomaly = mean_longitude - long_of_pericenter;
 
285
                        } else {
 
286
                mean_anomaly *= (M_PI/180.0);
 
287
                                mean_longitude = mean_anomaly + long_of_pericenter;
 
288
                        }
 
289
 
 
290
                          // when the parent is the sun use ecliptic rathe than sun equator:
 
291
                        const double parent_rot_obliquity = parent->get_parent()
 
292
                                                          ? parent->getRotObliquity()
 
293
                                                          : 0.0;
 
294
                        const double parent_rot_asc_node = parent->get_parent()
 
295
                                                          ? parent->getRotAscendingnode()
 
296
                                                          : 0.0;
 
297
                        // Create an elliptical orbit
 
298
                        EllipticalOrbit *orb = new EllipticalOrbit(pericenter_distance,
 
299
                                                                   eccentricity,
 
300
                                                                   inclination,
 
301
                                                                   ascending_node,
 
302
                                                                   arg_of_pericenter,
 
303
                                                                   mean_anomaly,
 
304
                                                                   period,
 
305
                                                                   epoch,
 
306
                                                                   parent_rot_obliquity,
 
307
                                                                   parent_rot_asc_node);
 
308
                        orbits.push_back(orb);
 
309
 
 
310
                        posfunc = pos_func_type(orb, &EllipticalOrbit::positionAtTimevInVSOP87Coordinates);
 
311
                } else
 
312
                if (funcname=="comet_orbit")
 
313
                {
 
314
                        // Read the orbital elements
 
315
                        const double eccentricity = pd.get_double(secname,"orbit_Eccentricity",0.0);
 
316
                        if (eccentricity >= 1.0) close_orbit = false;
 
317
                        double pericenter_distance = pd.get_double(secname,"orbit_PericenterDistance",-1e100);
 
318
                        double semi_major_axis;
 
319
                        if (pericenter_distance <= 0.0) {
 
320
                                semi_major_axis = pd.get_double(secname,"orbit_SemiMajorAxis",-1e100);
 
321
                                if (semi_major_axis <= -1e100) {
 
322
                                        cerr << "ERROR: " << englishName
 
323
                                             << ": you must provide orbit_PericenterDistance or orbit_SemiMajorAxis"
 
324
                                             << endl;
 
325
                                        assert(0);
 
326
                                } else {
 
327
                                        assert(eccentricity != 1.0); // parabolic orbits have no semi_major_axis
 
328
                                        pericenter_distance = semi_major_axis * (1.0-eccentricity);
 
329
                                }
 
330
                        } else {
 
331
                                semi_major_axis = (eccentricity == 1.0)
 
332
                                                ? 0.0 // parabolic orbits have no semi_major_axis
 
333
                                                : pericenter_distance / (1.0-eccentricity);
 
334
                        }
 
335
                        double mean_motion = pd.get_double(secname,"orbit_MeanMotion",-1e100);
 
336
                        double period;
 
337
                        if (mean_motion <= -1e100) {
 
338
                                period = pd.get_double(secname,"orbit_Period",-1e100);
 
339
                                if (period <= -1e100) {
 
340
                                        mean_motion = (eccentricity == 1.0)
 
341
                                                    ? 0.01720209895 * (1.5/pericenter_distance)
 
342
                                                                    * sqrt(0.5/pericenter_distance)
 
343
                                                    : (semi_major_axis > 0.0)
 
344
                                                    ? 0.01720209895 / (semi_major_axis*sqrt(semi_major_axis))
 
345
                                                    : 0.01720209895 / (-semi_major_axis*sqrt(-semi_major_axis));
 
346
                                        period = 2.0*M_PI/mean_motion;
 
347
                                } else {
 
348
                                        mean_motion = 2.0*M_PI/period;
 
349
                                }
 
350
                        } else {
 
351
                                period = 2.0*M_PI/mean_motion;
 
352
                        }
 
353
                        double time_at_pericenter = pd.get_double(secname,"orbit_TimeAtPericenter",-1e100);
 
354
                        if (time_at_pericenter <= -1e100) {
 
355
                                const double epoch = pd.get_double(secname,"orbit_Epoch",-1e100);
 
356
                                double mean_anomaly = pd.get_double(secname,"orbit_MeanAnomaly",-1e100);
 
357
                                if (epoch <= -1e100 || mean_anomaly <= -1e100) {
 
358
                                        cerr << "ERROR: " << englishName
 
359
                                             << ": when you do not provide orbit_TimeAtPericenter, you must provide both "
 
360
                                                "orbit_Epoch and orbit_MeanAnomaly"
 
361
                                             << endl;
 
362
                                        assert(0);
 
363
                                } else {
 
364
                                        mean_anomaly *= (M_PI/180.0);
 
365
                                        const double mean_motion = 0.01720209895 / (semi_major_axis*sqrt(semi_major_axis));
 
366
                                        time_at_pericenter = epoch - mean_anomaly / mean_motion;
 
367
                                }
 
368
                        }
 
369
                        const double inclination = pd.get_double(secname,"orbit_Inclination")*(M_PI/180.0);
 
370
                        const double ascending_node = pd.get_double(secname,"orbit_AscendingNode")*(M_PI/180.0);
 
371
                        const double arg_of_pericenter = pd.get_double(secname,"orbit_ArgOfPericenter")*(M_PI/180.0);
 
372
                        CometOrbit *orb = new CometOrbit(pericenter_distance,
 
373
                                                         eccentricity,
 
374
                                                         inclination,
 
375
                                                         ascending_node,
 
376
                                                         arg_of_pericenter,
 
377
                                                         time_at_pericenter,
 
378
                                                         mean_motion);
 
379
                        orbits.push_back(orb);
 
380
 
 
381
                        posfunc = pos_func_type(orb,&CometOrbit::positionAtTimevInVSOP87Coordinates);
 
382
                }
 
383
 
 
384
                if (funcname=="sun_special")
 
385
                        posfunc = pos_func_type(get_sun_helio_coordsv);
 
386
 
 
387
                if (funcname=="mercury_special") {
 
388
                        posfunc = pos_func_type(get_mercury_helio_coordsv);
 
389
                        osculating_func = &get_mercury_helio_osculating_coords;
 
390
                }
 
391
        
 
392
                if (funcname=="venus_special") {
 
393
                        posfunc = pos_func_type(get_venus_helio_coordsv);
 
394
                        osculating_func = &get_venus_helio_osculating_coords;
 
395
                }
 
396
 
 
397
                if (funcname=="earth_special") {
 
398
                        posfunc = pos_func_type(get_earth_helio_coordsv);
 
399
                        osculating_func = &get_earth_helio_osculating_coords;
 
400
                }
 
401
 
 
402
                if (funcname=="lunar_special")
 
403
                        posfunc = pos_func_type(get_lunar_parent_coordsv);
 
404
 
 
405
                if (funcname=="mars_special") {
 
406
                        posfunc = pos_func_type(get_mars_helio_coordsv);
 
407
                        osculating_func = &get_mars_helio_osculating_coords;
 
408
                }
 
409
 
 
410
                if (funcname=="phobos_special")
 
411
                        posfunc = pos_func_type(get_phobos_parent_coordsv);
 
412
 
 
413
                if (funcname=="deimos_special")
 
414
                        posfunc = pos_func_type(get_deimos_parent_coordsv);
 
415
 
 
416
                if (funcname=="jupiter_special") {
 
417
                        posfunc = pos_func_type(get_jupiter_helio_coordsv);
 
418
                        osculating_func = &get_jupiter_helio_osculating_coords;
 
419
                }
 
420
 
 
421
                if (funcname=="europa_special")
 
422
                        posfunc = pos_func_type(get_europa_parent_coordsv);
 
423
 
 
424
                if (funcname=="calisto_special")
 
425
                        posfunc = pos_func_type(get_callisto_parent_coordsv);
 
426
 
 
427
                if (funcname=="io_special")
 
428
                        posfunc = pos_func_type(get_io_parent_coordsv);
 
429
 
 
430
                if (funcname=="ganymede_special")
 
431
                        posfunc = pos_func_type(get_ganymede_parent_coordsv);
 
432
 
 
433
                if (funcname=="saturn_special") {
 
434
                        posfunc = pos_func_type(get_saturn_helio_coordsv);
 
435
                        osculating_func = &get_saturn_helio_osculating_coords;
 
436
                }
 
437
 
 
438
                if (funcname=="mimas_special")
 
439
                        posfunc = pos_func_type(get_mimas_parent_coordsv);
 
440
 
 
441
                if (funcname=="enceladus_special")
 
442
                        posfunc = pos_func_type(get_enceladus_parent_coordsv);
 
443
 
 
444
                if (funcname=="tethys_special")
 
445
                        posfunc = pos_func_type(get_tethys_parent_coordsv);
 
446
 
 
447
                if (funcname=="dione_special")
 
448
                        posfunc = pos_func_type(get_dione_parent_coordsv);
 
449
 
 
450
                if (funcname=="rhea_special")
 
451
                        posfunc = pos_func_type(get_rhea_parent_coordsv);
 
452
 
 
453
                if (funcname=="titan_special")
 
454
                        posfunc = pos_func_type(get_titan_parent_coordsv);
 
455
 
 
456
                if (funcname=="iapetus_special")
 
457
                        posfunc = pos_func_type(get_iapetus_parent_coordsv);
 
458
 
 
459
                if (funcname=="hyperion_special")
 
460
                        posfunc = pos_func_type(get_hyperion_parent_coordsv);
 
461
 
 
462
                if (funcname=="uranus_special") {
 
463
                        posfunc = pos_func_type(get_uranus_helio_coordsv);
 
464
                        osculating_func = &get_uranus_helio_osculating_coords;
 
465
                }
 
466
 
 
467
                if (funcname=="miranda_special")
 
468
                        posfunc = pos_func_type(get_miranda_parent_coordsv);
 
469
 
 
470
                if (funcname=="ariel_special")
 
471
                        posfunc = pos_func_type(get_ariel_parent_coordsv);
 
472
 
 
473
                if (funcname=="umbriel_special")
 
474
                        posfunc = pos_func_type(get_umbriel_parent_coordsv);
 
475
 
 
476
                if (funcname=="titania_special")
 
477
                        posfunc = pos_func_type(get_titania_parent_coordsv);
 
478
 
 
479
                if (funcname=="oberon_special")
 
480
                        posfunc = pos_func_type(get_oberon_parent_coordsv);
 
481
 
 
482
                if (funcname=="neptune_special") {
 
483
                        posfunc = pos_func_type(get_neptune_helio_coordsv);
 
484
                        osculating_func = &get_neptune_helio_osculating_coords;
 
485
                }
 
486
 
 
487
                if (funcname=="pluto_special")
 
488
                        posfunc = pos_func_type(get_pluto_helio_coordsv);
 
489
 
 
490
 
 
491
                if (posfunc.empty())
 
492
                {
 
493
                        cout << "ERROR : can't find posfunc " << funcname << " for " << englishName << endl;
 
494
                        exit(-1);
 
495
                }
 
496
 
 
497
                // Create the Planet and add it to the list
 
498
                Planet* p = new Planet(parent,
 
499
                               englishName,
 
500
                               pd.get_boolean(secname, "halo"),
 
501
                               pd.get_boolean(secname, "lighting"),
 
502
                               pd.get_double(secname, "radius")/AU,
 
503
                               pd.get_double(secname, "oblateness", 0.0),
 
504
                               StelUtils::str_to_vec3f(pd.get_str(secname, "color").c_str()),
 
505
                               pd.get_double(secname, "albedo"),
 
506
                               pd.get_str(secname, "tex_map").c_str(),
 
507
                               pd.get_str(secname, "tex_halo").c_str(),
 
508
                               posfunc,osculating_func,
 
509
                               close_orbit,
 
510
                               pd.get_boolean(secname, "hidden", 0));
 
511
 
 
512
                if (secname=="earth") earth = p;
 
513
                if (secname=="sun") sun = p;
 
514
                if (secname=="moon") moon = p;
 
515
 
 
516
                p->set_rotation_elements(
 
517
                    pd.get_double(secname, "rot_periode", pd.get_double(secname, "orbit_Period", 24.))/24.,
 
518
                    pd.get_double(secname, "rot_rotation_offset",0.),
 
519
                    pd.get_double(secname, "rot_epoch", J2000),
 
520
                    pd.get_double(secname, "rot_obliquity",0.)*(M_PI/180.0),
 
521
                    pd.get_double(secname, "rot_equator_ascending_node",0.)*(M_PI/180.0),
 
522
                    pd.get_double(secname, "rot_precession_rate",0.)*M_PI/(180*36525),
 
523
                    pd.get_double(secname, "sidereal_period",0.) );
 
524
 
 
525
 
 
526
                if (pd.get_boolean(secname, "rings", 0)) {
 
527
                        const double r_min = pd.get_double(secname, "ring_inner_size")/AU;
 
528
                        const double r_max = pd.get_double(secname, "ring_outer_size")/AU;
 
529
                        Ring *r = new Ring(r_min,r_max,pd.get_str(secname, "tex_ring").c_str());
 
530
                        p->set_rings(r);
 
531
                }
 
532
 
 
533
                QString bighalotexfile = pd.get_str(secname, "tex_big_halo", "").c_str();
 
534
                if (!bighalotexfile.isEmpty())
 
535
                {
 
536
                        p->set_big_halo(bighalotexfile);
 
537
                        p->set_halo_size(pd.get_double(secname, "big_halo_size", 50.f));
 
538
                }
 
539
 
 
540
                system_planets.push_back(p);
 
541
        }
 
542
 
 
543
        // special case: load earth shadow texture
 
544
        StelApp::getInstance().getTextureManager().setDefaultParams();
 
545
        tex_earth_shadow = StelApp::getInstance().getTextureManager().createTexture("earth-shadow.png");
 
546
        
 
547
        cout << "(loaded)" << endl;
 
548
}
 
549
 
 
550
// Compute the position for every elements of the solar system.
 
551
// The order is not important since the position is computed relatively to the mother body
 
552
void SolarSystem::computePositions(double date, const Vec3d& observerPos) {
 
553
  if (flag_light_travel_time) {
 
554
    for (vector<Planet*>::const_iterator iter(system_planets.begin());
 
555
         iter!=system_planets.end();iter++) {
 
556
      (*iter)->computePositionWithoutOrbits(date);
 
557
    }
 
558
    for (vector<Planet*>::const_iterator iter(system_planets.begin());
 
559
         iter!=system_planets.end();iter++) {
 
560
      const double light_speed_correction =
 
561
        ((*iter)->get_heliocentric_ecliptic_pos()-observerPos).length()
 
562
        * (AU / (SPEED_OF_LIGHT * 86400));
 
563
      (*iter)->compute_position(date-light_speed_correction);
 
564
    }
 
565
  } else {
 
566
    for (vector<Planet*>::const_iterator iter(system_planets.begin());
 
567
         iter!=system_planets.end();iter++) {
 
568
      (*iter)->compute_position(date);
 
569
    }
 
570
  }
 
571
  
 
572
  computeTransMatrices(date, observerPos);
 
573
}
 
574
 
 
575
// Compute the transformation matrix for every elements of the solar system.
 
576
// The elements have to be ordered hierarchically, eg. it's important to compute earth before moon.
 
577
void SolarSystem::computeTransMatrices(double date, const Vec3d& observerPos) {
 
578
  if (flag_light_travel_time) {
 
579
    for (vector<Planet*>::const_iterator iter(system_planets.begin());
 
580
         iter!=system_planets.end();iter++) {
 
581
      const double light_speed_correction =
 
582
        ((*iter)->get_heliocentric_ecliptic_pos()-observerPos).length()
 
583
        * (AU / (SPEED_OF_LIGHT * 86400));
 
584
      (*iter)->compute_trans_matrix(date-light_speed_correction);
 
585
    }
 
586
  } else {
 
587
    for (vector<Planet*>::const_iterator iter(system_planets.begin());
 
588
         iter!=system_planets.end();iter++) {
 
589
      (*iter)->compute_trans_matrix(date);
 
590
    }
 
591
  }
 
592
}
 
593
 
 
594
// Draw all the elements of the solar system
 
595
// We are supposed to be in heliocentric coordinate
 
596
double SolarSystem::draw(StelCore* core)
 
597
{
 
598
        if(!Planet::getflagShow())
 
599
                return 0.0;
 
600
        
 
601
        Navigator* nav = core->getNavigation();
 
602
        Projector* prj = core->getProjection();
 
603
        ToneReproducer* eye = core->getToneReproducer();
 
604
        
 
605
        Planet::set_font(&planet_name_font);
 
606
        
 
607
        // Set the light parameters taking sun as the light source
 
608
        const float zero[4] = {0,0,0,0};
 
609
        const float ambient[4] = {0.02,0.02,0.02,0.02};
 
610
        const float diffuse[4] = {1,1,1,1};
 
611
        glLightfv(GL_LIGHT0,GL_AMBIENT, ambient);
 
612
        glLightfv(GL_LIGHT0,GL_DIFFUSE, diffuse);
 
613
        glLightfv(GL_LIGHT0,GL_SPECULAR,zero);
 
614
 
 
615
        glMaterialfv(GL_FRONT,GL_AMBIENT,  ambient);
 
616
        glMaterialfv(GL_FRONT,GL_DIFFUSE,  diffuse);
 
617
        glMaterialfv(GL_FRONT,GL_EMISSION, zero);
 
618
        glMaterialfv(GL_FRONT,GL_SHININESS,zero);
 
619
        glMaterialfv(GL_FRONT,GL_SPECULAR, zero);
 
620
 
 
621
        // Light pos in zero (sun)
 
622
        //nav->switchToHeliocentric();
 
623
        glLightfv(GL_LIGHT0,GL_POSITION,Vec4f(0.f,0.f,0.f,1.f));
 
624
        glEnable(GL_LIGHT0);
 
625
 
 
626
        // Compute each Planet distance to the observer
 
627
        Vec3d obs_helio_pos = nav->getObserverHelioPos();
 
628
        
 
629
        vector<Planet*>::iterator iter;
 
630
        iter = system_planets.begin();
 
631
        while (iter != system_planets.end())
 
632
        {
 
633
                (*iter)->compute_distance(obs_helio_pos);
 
634
                ++iter;
 
635
        }
 
636
 
 
637
        // And sort them from the furthest to the closest
 
638
        sort(system_planets.begin(),system_planets.end(),bigger_distance());
 
639
 
 
640
        // Draw the elements
 
641
        double maxSquaredDistance = 0;
 
642
        iter = system_planets.begin();
 
643
        while (iter != system_planets.end())
 
644
        {
 
645
                double squaredDistance = 0;
 
646
                if(*iter==moon && near_lunar_eclipse(nav, prj))
 
647
                {
 
648
                        // TODO: moon magnitude label during eclipse isn't accurate...
 
649
 
 
650
                        // special case to update stencil buffer for drawing lunar eclipses
 
651
                        glClear(GL_STENCIL_BUFFER_BIT);
 
652
                        glClearStencil(0x0);
 
653
 
 
654
                        glStencilFunc(GL_ALWAYS, 0x1, 0x1);
 
655
                        glStencilOp(GL_ZERO, GL_REPLACE, GL_REPLACE);
 
656
 
 
657
                        squaredDistance = (*iter)->draw(prj, nav, eye, 1);
 
658
                }
 
659
                else
 
660
                {
 
661
                        squaredDistance = (*iter)->draw(prj, nav, eye, 0);
 
662
                }
 
663
                if (squaredDistance > maxSquaredDistance)
 
664
                        maxSquaredDistance = squaredDistance;
 
665
 
 
666
                ++iter;
 
667
        }
 
668
 
 
669
        glDisable(GL_LIGHT0);
 
670
 
 
671
 
 
672
        // special case: draw earth shadow over moon if appropriate
 
673
        // stencil buffer is set up in moon drawing above
 
674
        // This effect curently only looks right from earth viewpoint
 
675
        if(nav->getHomePlanet()->getEnglishName() == "Earth") 
 
676
                draw_earth_shadow(nav, prj);
 
677
 
 
678
        drawPointer(prj, nav);
 
679
        
 
680
        return maxSquaredDistance;
 
681
}
 
682
 
 
683
void SolarSystem::setColorScheme(const InitParser& conf, const QString& section)
 
684
{
 
685
        // Load colors from config file
 
686
        string defaultColor = conf.get_str(section.toStdString(),"default_color");
 
687
        setNamesColor(StelUtils::str_to_vec3f(conf.get_str(section.toStdString(),"planet_names_color", defaultColor)));
 
688
        setOrbitsColor(StelUtils::str_to_vec3f(conf.get_str(section.toStdString(),"planet_orbits_color", defaultColor)));
 
689
        setTrailsColor(StelUtils::str_to_vec3f(conf.get_str(section.toStdString(),"object_trails_color", defaultColor)));
 
690
}
 
691
 
 
692
Planet* SolarSystem::searchByEnglishName(string planetEnglishName) const
 
693
{
 
694
//printf("SolarSystem::searchByEnglishName(\"%s\"): start\n",
 
695
//       planetEnglishName.c_str());
 
696
        // side effect - bad?
 
697
//      transform(planetEnglishName.begin(), planetEnglishName.end(), planetEnglishName.begin(), ::tolower);
 
698
 
 
699
        vector<Planet*>::const_iterator iter = system_planets.begin();
 
700
        while (iter != system_planets.end())
 
701
        {
 
702
//printf("SolarSystem::searchByEnglishName(\"%s\"): %s\n",
 
703
//       planetEnglishName.c_str(),
 
704
//       (*iter)->getEnglishName().c_str());
 
705
                if( (*iter)->getEnglishName() == planetEnglishName ) return (*iter);  // also check standard ini file names
 
706
                ++iter;
 
707
        }
 
708
//printf("SolarSystem::searchByEnglishName(\"%s\"): not found\n",
 
709
//       planetEnglishName.c_str());
 
710
        return NULL;
 
711
}
 
712
 
 
713
StelObjectP SolarSystem::searchByNameI18n(const wstring& planetNameI18) const
 
714
{
 
715
        vector<Planet*>::const_iterator iter = system_planets.begin();
 
716
        while (iter != system_planets.end())
 
717
        {
 
718
                if( (*iter)->getNameI18n() == planetNameI18 ) return (*iter);  // also check standard ini file names
 
719
                ++iter;
 
720
        }
 
721
        return NULL;
 
722
}
 
723
 
 
724
 
 
725
StelObjectP SolarSystem::searchByName(const string& name) const
 
726
{
 
727
        vector<Planet*>::const_iterator iter = system_planets.begin();
 
728
        while (iter != system_planets.end())
 
729
        {
 
730
                if( (*iter)->getEnglishName() == name ) return (*iter); 
 
731
                ++iter;
 
732
        }
 
733
        return NULL;
 
734
}
 
735
 
 
736
// Search if any Planet is close to position given in earth equatorial position and return the distance
 
737
StelObject* SolarSystem::search(Vec3d pos, const StelCore* core) const
 
738
{
 
739
        pos.normalize();
 
740
        Planet * closest = NULL;
 
741
        double cos_angle_closest = 0.;
 
742
        static Vec3d equPos;
 
743
 
 
744
        vector<Planet*>::const_iterator iter = system_planets.begin();
 
745
        while (iter != system_planets.end())
 
746
        {
 
747
                equPos = (*iter)->getEarthEquatorialPos(core->getNavigation());
 
748
                equPos.normalize();
 
749
                double cos_ang_dist = equPos[0]*pos[0] + equPos[1]*pos[1] + equPos[2]*pos[2];
 
750
                if (cos_ang_dist>cos_angle_closest)
 
751
                {
 
752
                        closest = *iter;
 
753
                        cos_angle_closest = cos_ang_dist;
 
754
                }
 
755
                iter++;
 
756
        }
 
757
 
 
758
        if (cos_angle_closest>0.999)
 
759
        {
 
760
                return closest;
 
761
        }
 
762
        else return NULL;
 
763
}
 
764
 
 
765
// Return a stl vector containing the planets located inside the lim_fov circle around position v
 
766
vector<StelObjectP> SolarSystem::searchAround(const Vec3d& vv, double limitFov, const StelCore* core) const
 
767
{
 
768
        vector<StelObjectP> result;
 
769
        if (!getFlagPlanets())
 
770
                return result;
 
771
                
 
772
        Vec3d v = core->getNavigation()->j2000_to_earth_equ(vv);
 
773
        v.normalize();
 
774
        double cos_lim_fov = cos(limitFov * M_PI/180.);
 
775
        static Vec3d equPos;
 
776
 
 
777
        vector<Planet*>::const_iterator iter = system_planets.begin();
 
778
        while (iter != system_planets.end())
 
779
        {
 
780
                equPos = (*iter)->getEarthEquatorialPos(core->getNavigation());
 
781
                equPos.normalize();
 
782
                if (equPos[0]*v[0] + equPos[1]*v[1] + equPos[2]*v[2]>=cos_lim_fov)
 
783
                {
 
784
                        result.push_back(*iter);
 
785
                }
 
786
                iter++;
 
787
        }
 
788
        return result;
 
789
}
 
790
 
 
791
// Update i18 names from english names according to passed translator
 
792
void SolarSystem::updateI18n()
 
793
{
 
794
        Translator& trans = StelApp::getInstance().getLocaleMgr().getSkyTranslator();
 
795
        vector<Planet*>::iterator iter;
 
796
        for( iter = system_planets.begin(); iter < system_planets.end(); iter++ )
 
797
        {
 
798
                (*iter)->translateName(trans);
 
799
        }
 
800
        planet_name_font = StelApp::getInstance().getFontManager().getStandardFont(trans.getTrueLocaleName(), fontSize);
 
801
}
 
802
 
 
803
vector<wstring> SolarSystem::getNamesI18(void)
 
804
{
 
805
        vector<wstring> names;
 
806
        vector < Planet * >::iterator iter;
 
807
 
 
808
        for (iter = system_planets.begin(); iter != system_planets.end(); ++iter)
 
809
                names.push_back((*iter)->getNameI18n());
 
810
        return names;
 
811
}
 
812
 
 
813
wstring SolarSystem::getPlanetHashString(void)
 
814
{
 
815
        QString str;
 
816
        QTextStream oss(&str);
 
817
        
 
818
        vector <Planet *>::iterator iter;
 
819
        for (iter = system_planets.begin(); iter != system_planets.end(); ++iter)
 
820
        {
 
821
                if((*iter)->get_parent() != NULL && (*iter)->get_parent()->getEnglishName() != "Sun")
 
822
                {
 
823
                        oss << q_((*iter)->get_parent()->getEnglishName().c_str()) << " : ";
 
824
                }
 
825
                
 
826
                oss << q_((*iter)->getEnglishName().c_str()) << endl;
 
827
                oss << (*iter)->getEnglishName().c_str() << endl;
 
828
        }
 
829
        return str.toStdWString();
 
830
}
 
831
 
 
832
void SolarSystem::startTrails(bool b)
 
833
{
 
834
        vector<Planet*>::iterator iter;
 
835
        for( iter = system_planets.begin(); iter < system_planets.end(); iter++ )
 
836
        {
 
837
                (*iter)->startTrail(b);
 
838
        }
 
839
}
 
840
 
 
841
void SolarSystem::setFlagTrails(bool b)
 
842
{
 
843
        vector<Planet*>::iterator iter;
 
844
        for( iter = system_planets.begin(); iter < system_planets.end(); iter++ )
 
845
        {
 
846
                (*iter)->setFlagTrail(b);
 
847
        }
 
848
}
 
849
 
 
850
bool SolarSystem::getFlagTrails(void) const
 
851
{
 
852
        for (vector<Planet*>::const_iterator iter = system_planets.begin();
 
853
             iter != system_planets.end(); iter++ ) {
 
854
                if ((*iter)->getFlagTrail()) return true;
 
855
        }
 
856
        return false;
 
857
}
 
858
 
 
859
void SolarSystem::setFlagHints(bool b)
 
860
{
 
861
        vector<Planet*>::iterator iter;
 
862
        for( iter = system_planets.begin(); iter < system_planets.end(); iter++ )
 
863
        {
 
864
                (*iter)->setFlagHints(b);
 
865
        }
 
866
}
 
867
 
 
868
bool SolarSystem::getFlagHints(void) const
 
869
{
 
870
        for (vector<Planet*>::const_iterator iter = system_planets.begin();
 
871
        iter != system_planets.end(); iter++ ) {
 
872
                if ((*iter)->getFlagHints()) return true;
 
873
        }
 
874
        return false;
 
875
}
 
876
 
 
877
void SolarSystem::setFlagOrbits(bool b)
 
878
{
 
879
        flagOrbits = b;
 
880
        if (!b || !selected || selected == sun)
 
881
        {
 
882
                vector<Planet*>::iterator iter;
 
883
                for( iter = system_planets.begin(); iter < system_planets.end(); iter++ )
 
884
                {
 
885
                        (*iter)->setFlagOrbits(b);
 
886
                }
 
887
        }
 
888
        else
 
889
        {
 
890
                // if a Planet is selected and orbits are on,
 
891
        // fade out non-selected ones
 
892
                vector<Planet*>::iterator iter;
 
893
                for (iter = system_planets.begin();
 
894
             iter != system_planets.end(); iter++ )
 
895
                {
 
896
            if (selected == (*iter)) (*iter)->setFlagOrbits(b);
 
897
            else (*iter)->setFlagOrbits(false);
 
898
                }               
 
899
        }
 
900
}
 
901
 
 
902
 
 
903
void SolarSystem::setSelected(StelObject* obj)
 
904
{
 
905
    if (obj && obj->getType() == "Planet")
 
906
        selected = obj;
 
907
    else
 
908
        selected = NULL;
 
909
        // Undraw other objects hints, orbit, trails etc..
 
910
        setFlagHints(getFlagHints());
 
911
        setFlagOrbits(getFlagOrbits());
 
912
        setFlagTrails(getFlagTrails());
 
913
}
 
914
 
 
915
// draws earth shadow overlapping the moon using stencil buffer
 
916
// umbra and penumbra are sized separately for accuracy
 
917
void SolarSystem::draw_earth_shadow(const Navigator * nav, Projector * prj)
 
918
{
 
919
 
 
920
        Vec3d e = getEarth()->get_ecliptic_pos();
 
921
        Vec3d m = getMoon()->get_ecliptic_pos();  // relative to earth
 
922
        Vec3d mh = getMoon()->get_heliocentric_ecliptic_pos();  // relative to sun
 
923
        float mscale = getMoon()->get_sphere_scale();
 
924
 
 
925
        // shadow location at earth + moon distance along earth vector from sun
 
926
        Vec3d en = e;
 
927
        en.normalize();
 
928
        Vec3d shadow = en * (e.length() + m.length());
 
929
 
 
930
        glEnable(GL_BLEND);
 
931
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
932
        glColor3f(1,1,1);
 
933
 
 
934
        // find shadow radii in AU
 
935
        double r_penumbra = shadow.length()*702378.1/AU/e.length() - 696000/AU;
 
936
        double r_umbra = 6378.1/AU - m.length()*(689621.9/AU/e.length());
 
937
 
 
938
        // find vector orthogonal to sun-earth vector using cross product with
 
939
        // a non-parallel vector
 
940
        Vec3d rpt = shadow^Vec3d(0,0,1);
 
941
        rpt.normalize();
 
942
        Vec3d upt = rpt*r_umbra*mscale*1.02;  // point on umbra edge
 
943
        rpt *= r_penumbra*mscale;  // point on penumbra edge
 
944
 
 
945
        // modify shadow location for scaled moon
 
946
        Vec3d mdist = shadow - mh;
 
947
        if(mdist.length() > r_penumbra + 2000/AU) return;   // not visible so don't bother drawing
 
948
 
 
949
        shadow = mh + mdist*mscale;
 
950
        r_penumbra *= mscale;
 
951
 
 
952
        //nav->switchToHeliocentric();
 
953
        glEnable(GL_STENCIL_TEST);
 
954
        glStencilFunc(GL_EQUAL, 0x1, 0x1);
 
955
        glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
 
956
 
 
957
        prj->setCurrentFrame(Projector::FRAME_HELIO);
 
958
        // shadow radial texture
 
959
        tex_earth_shadow->bind();
 
960
 
 
961
        Vec3d r, s;
 
962
 
 
963
        // umbra first
 
964
        glBegin(GL_TRIANGLE_FAN);
 
965
      // johannes: work-around for nasty ATI rendering bug:
 
966
      // use y-texture coordinate of 0.5 instead of 0.0
 
967
        glTexCoord2f(0.f,0.5f);
 
968
        prj->drawVertex3v(shadow);
 
969
 
 
970
        for (int i=0; i<=100; i++)
 
971
        {
 
972
                r = Mat4d::rotation(shadow, 2*M_PI*i/100.) * upt;
 
973
                s = shadow + r;
 
974
 
 
975
                glTexCoord2f(0.6f,0.5f);  // position in texture of umbra edge
 
976
                prj->drawVertex3v(s);
 
977
        }
 
978
        glEnd();
 
979
 
 
980
 
 
981
        // now penumbra
 
982
        Vec3d u, sp;
 
983
        glBegin(GL_TRIANGLE_STRIP);
 
984
        for (int i=0; i<=100; i++)
 
985
        {
 
986
                r = Mat4d::rotation(shadow, 2*M_PI*i/100.) * rpt;
 
987
                u = Mat4d::rotation(shadow, 2*M_PI*i/100.) * upt;
 
988
                s = shadow + r;
 
989
                sp = shadow + u;
 
990
 
 
991
                glTexCoord2f(0.6f,0.5f);
 
992
                prj->drawVertex3v(sp);
 
993
 
 
994
                glTexCoord2f(1.f,0.5f);  // position in texture of umbra edge
 
995
                prj->drawVertex3v(s);
 
996
        }
 
997
        glEnd();
 
998
 
 
999
        glDisable(GL_STENCIL_TEST);
 
1000
 
 
1001
}
 
1002
 
 
1003
 
 
1004
void SolarSystem::update(double delta_time)
 
1005
{
 
1006
        bool restartTrails = false;
 
1007
        Navigator* nav = StelApp::getInstance().getCore()->getNavigation();
 
1008
 
 
1009
        // Determine if home planet has changed, and restart planet trails
 
1010
        // since the data is no longer useful
 
1011
        if(nav->getHomePlanet() != lastHomePlanet) {
 
1012
                lastHomePlanet = nav->getHomePlanet();
 
1013
                restartTrails = true;
 
1014
        }
 
1015
 
 
1016
        vector<Planet*>::iterator iter = system_planets.begin();
 
1017
        while (iter != system_planets.end())
 
1018
        {
 
1019
                if(restartTrails) (*iter)->startTrail(true);
 
1020
                (*iter)->update_trail(nav);
 
1021
                (*iter)->update((int)(delta_time*1000));
 
1022
                iter++;
 
1023
        }
 
1024
}
 
1025
 
 
1026
 
 
1027
// is a lunar eclipse close at hand?
 
1028
bool SolarSystem::near_lunar_eclipse(const Navigator * nav, Projector *prj)
 
1029
{
 
1030
        // TODO: could replace with simpler test
 
1031
 
 
1032
        Vec3d e = getEarth()->get_ecliptic_pos();
 
1033
        Vec3d m = getMoon()->get_ecliptic_pos();  // relative to earth
 
1034
        Vec3d mh = getMoon()->get_heliocentric_ecliptic_pos();  // relative to sun
 
1035
 
 
1036
        // shadow location at earth + moon distance along earth vector from sun
 
1037
        Vec3d en = e;
 
1038
        en.normalize();
 
1039
        Vec3d shadow = en * (e.length() + m.length());
 
1040
 
 
1041
        // find shadow radii in AU
 
1042
        double r_penumbra = shadow.length()*702378.1/AU/e.length() - 696000/AU;
 
1043
 
 
1044
        // modify shadow location for scaled moon
 
1045
        Vec3d mdist = shadow - mh;
 
1046
        if(mdist.length() > r_penumbra + 2000/AU) return 0;   // not visible so don't bother drawing
 
1047
 
 
1048
        return 1;
 
1049
}
 
1050
 
 
1051
//! Find and return the list of at most maxNbItem objects auto-completing the passed object I18n name
 
1052
vector<wstring> SolarSystem::listMatchingObjectsI18n(const wstring& objPrefix, unsigned int maxNbItem) const
 
1053
{
 
1054
        vector<wstring> result;
 
1055
        if (maxNbItem==0) return result;
 
1056
        
 
1057
        wstring objw = objPrefix;
 
1058
        transform(objw.begin(), objw.end(), objw.begin(), ::toupper);
 
1059
        
 
1060
        vector < Planet * >::const_iterator iter;
 
1061
        for (iter = system_planets.begin(); iter != system_planets.end(); ++iter)
 
1062
        {
 
1063
                wstring constw = (*iter)->getNameI18n().substr(0, objw.size());
 
1064
                transform(constw.begin(), constw.end(), constw.begin(), ::toupper);
 
1065
                if (constw==objw)
 
1066
                {
 
1067
                        result.push_back((*iter)->getNameI18n());
 
1068
                        if (result.size()==maxNbItem)
 
1069
                                return result;
 
1070
                }
 
1071
        }
 
1072
        return result;
 
1073
}
 
1074
 
 
1075
void SolarSystem::selectedObjectChangeCallBack(StelModuleSelectAction action)
 
1076
{
 
1077
        const std::vector<StelObjectP> newSelected = StelApp::getInstance().getStelObjectMgr().getSelectedObject("Planet");
 
1078
        if (!newSelected.empty())
 
1079
                setSelected(newSelected[0].get());
 
1080
//              // potentially record this action
 
1081
//              if (!recordActionCallback.empty())
 
1082
//                      recordActionCallback("select planet " + selected_object.getEnglishName());
 
1083
}
 
1084
 
 
1085
// Activate/Deactivate planets display
 
1086
void SolarSystem::setFlagPlanets(bool b) {Planet::setflagShow(b);}
 
1087
bool SolarSystem::getFlagPlanets(void) const {return Planet::getflagShow();}
 
1088
 
 
1089
// Set/Get planets names color
 
1090
void SolarSystem::setNamesColor(const Vec3f& c) {Planet::set_label_color(c);}
 
1091
const Vec3f& SolarSystem::getNamesColor(void) const {return Planet::getLabelColor();}
 
1092
 
 
1093
// Set/Get orbits lines color
 
1094
void SolarSystem::setOrbitsColor(const Vec3f& c) {Planet::set_orbit_color(c);}
 
1095
Vec3f SolarSystem::getOrbitsColor(void) const {return Planet::getOrbitColor();}
 
1096
 
 
1097
// Set/Get planets trails color
 
1098
void SolarSystem::setTrailsColor(const Vec3f& c)  {Planet::set_trail_color(c);}
 
1099
Vec3f SolarSystem::getTrailsColor(void) const {return Planet::getTrailColor();}
 
1100
 
 
1101
// Set/Get base planets display scaling factor 
 
1102
void SolarSystem::setScale(float scale) {Planet::setScale(scale);}
 
1103
float SolarSystem::getScale(void) const {return Planet::getScale();}
 
1104
 
 
1105
// Set/Get if Moon display is scaled
 
1106
void SolarSystem::setFlagMoonScale(bool b)
 
1107
{
 
1108
        if (!b) getMoon()->set_sphere_scale(1);
 
1109
        else getMoon()->set_sphere_scale(moonScale);
 
1110
        flagMoonScale = b;
 
1111
}
 
1112
 
 
1113
// Set/Get Moon display scaling factor 
 
1114
void SolarSystem::setMoonScale(float f)
 
1115
{
 
1116
        moonScale = f;
 
1117
        if (flagMoonScale)
 
1118
                getMoon()->set_sphere_scale(moonScale);
 
1119
}
 
1120
 
 
1121
// Set selected planets by englishName
 
1122
void SolarSystem::setSelected(const string& englishName)
 
1123
{
 
1124
        setSelected(searchByEnglishName(englishName));
 
1125
}
 
1126
 
 
1127
bool SolarSystem::bigger_distance::operator()(Planet* p1, Planet* p2)
 
1128
{
 
1129
        return p1->get_distance() > p2->get_distance();
 
1130
}