~ubuntu-branches/debian/squeeze/stellarium/squeeze

« 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
 
using namespace std;
21
 
 
22
 
#include <algorithm>
23
 
#include <iostream>
24
 
#include <string>
25
 
#include "solarsystem.h"
26
 
#include "s_texture.h"
27
 
#include "stellplanet.h"
28
 
#include "orbit.h"
29
 
#include "stellarium.h"
30
 
#include "init_parser.h"
31
 
 
32
 
#include "draw.h"
33
 
 
34
 
SolarSystem::SolarSystem()
35
 
            :sun(NULL),moon(NULL),earth(NULL),
36
 
             moonScale(1.), planet_name_font(NULL), tex_earth_shadow(NULL),
37
 
             flagOrbits(false),flag_light_travel_time(false) {
38
 
}
39
 
 
40
 
void SolarSystem::setFont(float font_size, const string& font_name)
41
 
{
42
 
        if(planet_name_font) delete planet_name_font;
43
 
 
44
 
        planet_name_font = new s_font(font_size, font_name);
45
 
        if (!planet_name_font)
46
 
        {
47
 
                printf("Can't create planet_name_font\n");
48
 
                exit(-1);
49
 
        }
50
 
        Planet::set_font(planet_name_font);
51
 
}
52
 
 
53
 
SolarSystem::~SolarSystem()
54
 
{
55
 
        for(vector<Planet*>::iterator iter = system_planets.begin(); iter != system_planets.end(); ++iter)
56
 
        {
57
 
                if (*iter) delete *iter;
58
 
                *iter = NULL;
59
 
        }
60
 
        for(vector<EllipticalOrbit*>::iterator iter = ell_orbits.begin(); iter != ell_orbits.end(); ++iter)
61
 
        {
62
 
                if (*iter) delete *iter;
63
 
                *iter = NULL;
64
 
        }
65
 
        sun = NULL;
66
 
        moon = NULL;
67
 
        earth = NULL;
68
 
 
69
 
        if (planet_name_font) delete planet_name_font;
70
 
        if(tex_earth_shadow) delete tex_earth_shadow;
71
 
}
72
 
 
73
 
 
74
 
// Init and load the solar system data
75
 
void SolarSystem::load(const string& planetfile)
76
 
{
77
 
        cout << "Loading Solar System data...";
78
 
        InitParser pd;  // The Planet data ini file parser
79
 
        pd.load(planetfile);
80
 
 
81
 
        int nbSections = pd.get_nsec();
82
 
        for (int i = 0;i<nbSections;++i)
83
 
        {
84
 
                const string secname = pd.get_secname(i);
85
 
                const string englishName = pd.get_str(secname, "name");
86
 
 
87
 
                const string str_parent = pd.get_str(secname, "parent");
88
 
                Planet *parent = NULL;
89
 
 
90
 
                if (str_parent!="none")
91
 
                {
92
 
                        // Look in the other planets the one named with str_parent
93
 
                        vector<Planet*>::iterator iter = system_planets.begin();
94
 
                        while (iter != system_planets.end())
95
 
                        {
96
 
                                if ((*iter)->getEnglishName()==str_parent)
97
 
                                {
98
 
                                        parent = (*iter);
99
 
                                }
100
 
                                iter++;
101
 
                        }
102
 
                        if (parent == NULL)
103
 
                        {
104
 
                                cout << "ERROR : can't find parent for " << englishName << endl;
105
 
                                exit(-1);
106
 
                        }
107
 
                }
108
 
 
109
 
                const string funcname = pd.get_str(secname, "coord_func");
110
 
 
111
 
                pos_func_type posfunc;
112
 
                OsulatingFunctType *osculating_func = 0;
113
 
                EllipticalOrbit* orb = NULL;
114
 
 
115
 
                if (funcname=="ell_orbit")
116
 
                {
117
 
                        // Read the orbital elements
118
 
                        double period = pd.get_double(secname, "orbit_Period");
119
 
                        double epoch = pd.get_double(secname, "orbit_Epoch",J2000);
120
 
                        double semi_major_axis = pd.get_double(secname, "orbit_SemiMajorAxis")/AU;
121
 
                        double eccentricity = pd.get_double(secname, "orbit_Eccentricity");
122
 
                        double inclination = pd.get_double(secname, "orbit_Inclination")*M_PI/180.;
123
 
                        double ascending_node = pd.get_double(secname, "orbit_AscendingNode")*M_PI/180.;
124
 
                        double long_of_pericenter = pd.get_double(secname, "orbit_LongOfPericenter")*M_PI/180.;
125
 
                        double mean_longitude = pd.get_double(secname, "orbit_MeanLongitude")*M_PI/180.;
126
 
 
127
 
                        double arg_of_pericenter = long_of_pericenter - ascending_node;
128
 
                        double anomaly_at_epoch = mean_longitude - (arg_of_pericenter + ascending_node);
129
 
                        double pericenter_distance = semi_major_axis * (1.0 - eccentricity);
130
 
 
131
 
                          // when the parent is the sun use ecliptic rathe than sun equator:
132
 
                        const double parent_rot_obliquity = parent->get_parent()
133
 
                                                          ? parent->getRotObliquity()
134
 
                                                          : 0.0;
135
 
                        const double parent_rot_asc_node = parent->get_parent()
136
 
                                                          ? parent->getRotAscendingnode()
137
 
                                                          : 0.0;
138
 
                        // Create an elliptical orbit
139
 
                        orb = new EllipticalOrbit(pericenter_distance,
140
 
                                                  eccentricity,
141
 
                                                  inclination,
142
 
                                                  ascending_node,
143
 
                                                  arg_of_pericenter,
144
 
                                                  anomaly_at_epoch,
145
 
                                                  period,
146
 
                                                  epoch,
147
 
                                                  parent_rot_obliquity,
148
 
                                                  parent_rot_asc_node);
149
 
                        ell_orbits.push_back(orb);
150
 
 
151
 
                        posfunc = pos_func_type(orb, &EllipticalOrbit::positionAtTimevInVSOP87Coordinates);
152
 
                }
153
 
 
154
 
                if (funcname=="sun_special")
155
 
                        posfunc = pos_func_type(get_sun_helio_coordsv);
156
 
 
157
 
                if (funcname=="mercury_special") {
158
 
                        posfunc = pos_func_type(get_mercury_helio_coordsv);
159
 
                        osculating_func = &get_mercury_helio_osculating_coords;
160
 
                }
161
 
        
162
 
                if (funcname=="venus_special") {
163
 
                        posfunc = pos_func_type(get_venus_helio_coordsv);
164
 
                        osculating_func = &get_venus_helio_osculating_coords;
165
 
                }
166
 
 
167
 
                if (funcname=="earth_special") {
168
 
                        posfunc = pos_func_type(get_earth_helio_coordsv);
169
 
                        osculating_func = &get_earth_helio_osculating_coords;
170
 
                }
171
 
 
172
 
                if (funcname=="lunar_special")
173
 
                        posfunc = pos_func_type(get_lunar_parent_coordsv);
174
 
 
175
 
                if (funcname=="mars_special") {
176
 
                        posfunc = pos_func_type(get_mars_helio_coordsv);
177
 
                        osculating_func = &get_mars_helio_osculating_coords;
178
 
                }
179
 
 
180
 
                if (funcname=="phobos_special")
181
 
                        posfunc = pos_func_type(get_phobos_parent_coordsv);
182
 
 
183
 
                if (funcname=="deimos_special")
184
 
                        posfunc = pos_func_type(get_deimos_parent_coordsv);
185
 
 
186
 
                if (funcname=="jupiter_special") {
187
 
                        posfunc = pos_func_type(get_jupiter_helio_coordsv);
188
 
                        osculating_func = &get_jupiter_helio_osculating_coords;
189
 
                }
190
 
 
191
 
                if (funcname=="europa_special")
192
 
                        posfunc = pos_func_type(get_europa_parent_coordsv);
193
 
 
194
 
                if (funcname=="calisto_special")
195
 
                        posfunc = pos_func_type(get_callisto_parent_coordsv);
196
 
 
197
 
                if (funcname=="io_special")
198
 
                        posfunc = pos_func_type(get_io_parent_coordsv);
199
 
 
200
 
                if (funcname=="ganymede_special")
201
 
                        posfunc = pos_func_type(get_ganymede_parent_coordsv);
202
 
 
203
 
                if (funcname=="saturn_special") {
204
 
                        posfunc = pos_func_type(get_saturn_helio_coordsv);
205
 
                        osculating_func = &get_saturn_helio_osculating_coords;
206
 
                }
207
 
 
208
 
                if (funcname=="mimas_special")
209
 
                        posfunc = pos_func_type(get_mimas_parent_coordsv);
210
 
 
211
 
                if (funcname=="enceladus_special")
212
 
                        posfunc = pos_func_type(get_enceladus_parent_coordsv);
213
 
 
214
 
                if (funcname=="tethys_special")
215
 
                        posfunc = pos_func_type(get_tethys_parent_coordsv);
216
 
 
217
 
                if (funcname=="dione_special")
218
 
                        posfunc = pos_func_type(get_dione_parent_coordsv);
219
 
 
220
 
                if (funcname=="rhea_special")
221
 
                        posfunc = pos_func_type(get_rhea_parent_coordsv);
222
 
 
223
 
                if (funcname=="titan_special")
224
 
                        posfunc = pos_func_type(get_titan_parent_coordsv);
225
 
 
226
 
                if (funcname=="iapetus_special")
227
 
                        posfunc = pos_func_type(get_iapetus_parent_coordsv);
228
 
 
229
 
                if (funcname=="hyperion_special")
230
 
                        posfunc = pos_func_type(get_hyperion_parent_coordsv);
231
 
 
232
 
                if (funcname=="uranus_special") {
233
 
                        posfunc = pos_func_type(get_uranus_helio_coordsv);
234
 
                        osculating_func = &get_uranus_helio_osculating_coords;
235
 
                }
236
 
 
237
 
                if (funcname=="miranda_special")
238
 
                        posfunc = pos_func_type(get_miranda_parent_coordsv);
239
 
 
240
 
                if (funcname=="ariel_special")
241
 
                        posfunc = pos_func_type(get_ariel_parent_coordsv);
242
 
 
243
 
                if (funcname=="umbriel_special")
244
 
                        posfunc = pos_func_type(get_umbriel_parent_coordsv);
245
 
 
246
 
                if (funcname=="titania_special")
247
 
                        posfunc = pos_func_type(get_titania_parent_coordsv);
248
 
 
249
 
                if (funcname=="oberon_special")
250
 
                        posfunc = pos_func_type(get_oberon_parent_coordsv);
251
 
 
252
 
                if (funcname=="neptune_special") {
253
 
                        posfunc = pos_func_type(get_neptune_helio_coordsv);
254
 
                        osculating_func = &get_neptune_helio_osculating_coords;
255
 
                }
256
 
 
257
 
                if (funcname=="pluto_special")
258
 
                        posfunc = pos_func_type(get_pluto_helio_coordsv);
259
 
 
260
 
 
261
 
                if (posfunc.empty())
262
 
                {
263
 
                        cout << "ERROR : can't find posfunc " << funcname << " for " << englishName << endl;
264
 
                        exit(-1);
265
 
                }
266
 
 
267
 
                // Create the Planet and add it to the list
268
 
                Planet* p = new Planet(parent,
269
 
                               englishName,
270
 
                               pd.get_boolean(secname, "halo"),
271
 
                               pd.get_boolean(secname, "lighting"),
272
 
                               pd.get_double(secname, "radius")/AU,
273
 
                               pd.get_double(secname, "oblateness", 0.0),
274
 
                               StelUtility::str_to_vec3f(pd.get_str(secname, "color").c_str()),
275
 
                               pd.get_double(secname, "albedo"),
276
 
                               pd.get_str(secname, "tex_map"),
277
 
                               pd.get_str(secname, "tex_halo"),
278
 
                               posfunc,osculating_func,
279
 
                               pd.get_boolean(secname, "hidden", 0));
280
 
 
281
 
                if (secname=="earth") earth = p;
282
 
                if (secname=="sun") sun = p;
283
 
                if (secname=="moon") moon = p;
284
 
 
285
 
                p->set_rotation_elements(
286
 
                    pd.get_double(secname, "rot_periode", pd.get_double(secname, "orbit_Period", 24.))/24.,
287
 
                    pd.get_double(secname, "rot_rotation_offset",0.),
288
 
                    pd.get_double(secname, "rot_epoch", J2000),
289
 
                    pd.get_double(secname, "rot_obliquity",0.)*M_PI/180.,
290
 
                    pd.get_double(secname, "rot_equator_ascending_node",0.)*M_PI/180.,
291
 
                    pd.get_double(secname, "rot_precession_rate",0.)*M_PI/(180*36525),
292
 
                    pd.get_double(secname, "sidereal_period",0.) );
293
 
 
294
 
 
295
 
                if (pd.get_boolean(secname, "rings", 0)) {
296
 
                        const double r_min = pd.get_double(secname, "ring_inner_size")/AU;
297
 
                        const double r_max = pd.get_double(secname, "ring_outer_size")/AU;
298
 
                        Ring *r = new Ring(r_min,r_max,pd.get_str(secname, "tex_ring"));
299
 
                        p->set_rings(r);
300
 
                }
301
 
 
302
 
                string bighalotexfile = pd.get_str(secname, "tex_big_halo", "");
303
 
                if (!bighalotexfile.empty())
304
 
                {
305
 
                        p->set_big_halo(bighalotexfile);
306
 
                        p->set_halo_size(pd.get_double(secname, "big_halo_size", 50.f));
307
 
                }
308
 
 
309
 
                system_planets.push_back(p);
310
 
        }
311
 
 
312
 
        // special case: load earth shadow texture
313
 
        tex_earth_shadow = new s_texture("earth-shadow.png", TEX_LOAD_TYPE_PNG_ALPHA);
314
 
 
315
 
        cout << "(loaded)" << endl;
316
 
}
317
 
 
318
 
// Compute the position for every elements of the solar system.
319
 
// The order is not important since the position is computed relatively to the mother body
320
 
void SolarSystem::computePositions(double date,const Planet *home_planet) {
321
 
  if (flag_light_travel_time) {
322
 
    for (vector<Planet*>::const_iterator iter(system_planets.begin());
323
 
         iter!=system_planets.end();iter++) {
324
 
      (*iter)->computePositionWithoutOrbits(date);
325
 
    }
326
 
    const Vec3d home_pos(home_planet->get_heliocentric_ecliptic_pos());
327
 
    for (vector<Planet*>::const_iterator iter(system_planets.begin());
328
 
         iter!=system_planets.end();iter++) {
329
 
      const double light_speed_correction =
330
 
        ((*iter)->get_heliocentric_ecliptic_pos()-home_pos).length()
331
 
        * (149597870000.0 / (299792458.0 * 86400));
332
 
//cout << "SolarSystem::computePositions: " << (*iter)->getEnglishName()
333
 
//     << ": " << (86400*light_speed_correction) << endl;
334
 
      (*iter)->compute_position(date-light_speed_correction);
335
 
    }
336
 
  } else {
337
 
    for (vector<Planet*>::const_iterator iter(system_planets.begin());
338
 
         iter!=system_planets.end();iter++) {
339
 
      (*iter)->compute_position(date);
340
 
    }
341
 
  }
342
 
}
343
 
 
344
 
// Compute the transformation matrix for every elements of the solar system.
345
 
// The elements have to be ordered hierarchically, eg. it's important to compute earth before moon.
346
 
void SolarSystem::computeTransMatrices(double date,const Planet *home_planet) {
347
 
  if (flag_light_travel_time) {
348
 
    const Vec3d home_pos(home_planet->get_heliocentric_ecliptic_pos());
349
 
    for (vector<Planet*>::const_iterator iter(system_planets.begin());
350
 
         iter!=system_planets.end();iter++) {
351
 
      const double light_speed_correction =
352
 
        ((*iter)->get_heliocentric_ecliptic_pos()-home_pos).length()
353
 
        * (149597870000.0 / (299792458.0 * 86400));
354
 
      (*iter)->compute_trans_matrix(date-light_speed_correction);
355
 
    }
356
 
  } else {
357
 
    for (vector<Planet*>::const_iterator iter(system_planets.begin());
358
 
         iter!=system_planets.end();iter++) {
359
 
      (*iter)->compute_trans_matrix(date);
360
 
    }
361
 
  }
362
 
}
363
 
 
364
 
// Draw all the elements of the solar system
365
 
// We are supposed to be in heliocentric coordinate
366
 
double SolarSystem::draw(Projector * prj, const Navigator * nav, const ToneReproductor* eye, bool flag_point)
367
 
{
368
 
        // Set the light parameters taking sun as the light source
369
 
        const float zero[4] = {0,0,0,0};
370
 
        const float ambient[4] = {0.03,0.03,0.03,0.03};
371
 
        const float diffuse[4] = {1,1,1,1};
372
 
        glLightfv(GL_LIGHT0,GL_AMBIENT, ambient);
373
 
        glLightfv(GL_LIGHT0,GL_DIFFUSE, diffuse);
374
 
        glLightfv(GL_LIGHT0,GL_SPECULAR,zero);
375
 
 
376
 
        glMaterialfv(GL_FRONT,GL_AMBIENT,  ambient);
377
 
        glMaterialfv(GL_FRONT,GL_DIFFUSE,  diffuse);
378
 
        glMaterialfv(GL_FRONT,GL_EMISSION, zero);
379
 
        glMaterialfv(GL_FRONT,GL_SHININESS,zero);
380
 
        glMaterialfv(GL_FRONT,GL_SPECULAR, zero);
381
 
 
382
 
        // Light pos in zero (sun)
383
 
        nav->switch_to_heliocentric();
384
 
        glLightfv(GL_LIGHT0,GL_POSITION,Vec4f(0.f,0.f,0.f,1.f));
385
 
        glEnable(GL_LIGHT0);
386
 
 
387
 
        // Compute each Planet distance to the observer
388
 
        Vec3d obs_helio_pos = nav->get_observer_helio_pos();
389
 
        
390
 
        vector<Planet*>::iterator iter;
391
 
        iter = system_planets.begin();
392
 
        while (iter != system_planets.end())
393
 
        {
394
 
                (*iter)->compute_distance(obs_helio_pos);
395
 
                ++iter;
396
 
        }
397
 
 
398
 
        // And sort them from the furthest to the closest
399
 
        sort(system_planets.begin(),system_planets.end(),bigger_distance());
400
 
 
401
 
        // Draw the elements
402
 
        double maxSquaredDistance = 0;
403
 
        iter = system_planets.begin();
404
 
        while (iter != system_planets.end())
405
 
        {
406
 
                double squaredDistance = 0;
407
 
                if(*iter==moon && near_lunar_eclipse(nav, prj))
408
 
                {
409
 
 
410
 
                        // TODO: moon magnitude label during eclipse isn't accurate...
411
 
 
412
 
                        // special case to update stencil buffer for drawing lunar eclipses
413
 
                        glClear(GL_STENCIL_BUFFER_BIT);
414
 
                        glClearStencil(0x0);
415
 
 
416
 
                        glStencilFunc(GL_ALWAYS, 0x1, 0x1);
417
 
                        glStencilOp(GL_ZERO, GL_REPLACE, GL_REPLACE);
418
 
 
419
 
                        squaredDistance = (*iter)->draw(prj, nav, eye, flag_point, 1);
420
 
 
421
 
                }
422
 
                else
423
 
                {
424
 
                        squaredDistance = (*iter)->draw(prj, nav, eye, flag_point, 0);
425
 
                }
426
 
                if (squaredDistance > maxSquaredDistance)
427
 
                        maxSquaredDistance = squaredDistance;
428
 
 
429
 
                ++iter;
430
 
        }
431
 
 
432
 
        glDisable(GL_LIGHT0);
433
 
 
434
 
 
435
 
        // special case: draw earth shadow over moon if appropriate
436
 
        // stencil buffer is set up in moon drawing above
437
 
        // This effect curently only looks right from earth viewpoint
438
 
        if(nav->getHomePlanet()->getEnglishName() == "Earth") 
439
 
                draw_earth_shadow(nav, prj);
440
 
 
441
 
        return maxSquaredDistance;
442
 
}
443
 
 
444
 
Planet* SolarSystem::searchByEnglishName(string planetEnglishName) const
445
 
{
446
 
//printf("SolarSystem::searchByEnglishName(\"%s\"): start\n",
447
 
//       planetEnglishName.c_str());
448
 
        // side effect - bad?
449
 
//      transform(planetEnglishName.begin(), planetEnglishName.end(), planetEnglishName.begin(), ::tolower);
450
 
 
451
 
        vector<Planet*>::const_iterator iter = system_planets.begin();
452
 
        while (iter != system_planets.end())
453
 
        {
454
 
//printf("SolarSystem::searchByEnglishName(\"%s\"): %s\n",
455
 
//       planetEnglishName.c_str(),
456
 
//       (*iter)->getEnglishName().c_str());
457
 
                if( (*iter)->getEnglishName() == planetEnglishName ) return (*iter);  // also check standard ini file names
458
 
                ++iter;
459
 
        }
460
 
//printf("SolarSystem::searchByEnglishName(\"%s\"): not found\n",
461
 
//       planetEnglishName.c_str());
462
 
        return NULL;
463
 
}
464
 
 
465
 
Planet* SolarSystem::searchByNamesI18(wstring planetNameI18) const
466
 
{
467
 
 
468
 
        // side effect - bad?
469
 
//      transform(planetNameI18.begin(), planetNameI18.end(), planetNameI18.begin(), ::tolower);
470
 
 
471
 
        vector<Planet*>::const_iterator iter = system_planets.begin();
472
 
        while (iter != system_planets.end())
473
 
        {
474
 
 
475
 
                if( (*iter)->getNameI18() == planetNameI18 ) return (*iter);  // also check standard ini file names
476
 
                ++iter;
477
 
        }
478
 
        return NULL;
479
 
}
480
 
 
481
 
// Search if any Planet is close to position given in earth equatorial position and return the distance
482
 
Planet* SolarSystem::search(Vec3d pos, const Navigator * nav,
483
 
                            const Projector * prj) const
484
 
{
485
 
        pos.normalize();
486
 
        Planet * closest = NULL;
487
 
        double cos_angle_closest = 0.;
488
 
        static Vec3d equPos;
489
 
 
490
 
        vector<Planet*>::const_iterator iter = system_planets.begin();
491
 
        while (iter != system_planets.end())
492
 
        {
493
 
                equPos = (*iter)->get_earth_equ_pos(nav);
494
 
                equPos.normalize();
495
 
                double cos_ang_dist = equPos[0]*pos[0] + equPos[1]*pos[1] + equPos[2]*pos[2];
496
 
                if (cos_ang_dist>cos_angle_closest)
497
 
                {
498
 
                        closest = *iter;
499
 
                        cos_angle_closest = cos_ang_dist;
500
 
                }
501
 
 
502
 
                iter++;
503
 
        }
504
 
 
505
 
        if (cos_angle_closest>0.999)
506
 
        {
507
 
                return closest;
508
 
        }
509
 
        else return NULL;
510
 
}
511
 
 
512
 
// Return a stl vector containing the planets located inside the lim_fov circle around position v
513
 
vector<StelObject*> SolarSystem::search_around(Vec3d v,
514
 
                                               double lim_fov,
515
 
                                               const Navigator * nav,
516
 
                                               const Projector * prj) const
517
 
{
518
 
        vector<StelObject*> result;
519
 
        v.normalize();
520
 
        double cos_lim_fov = cos(lim_fov * M_PI/180.);
521
 
        static Vec3d equPos;
522
 
 
523
 
        vector<Planet*>::const_iterator iter = system_planets.begin();
524
 
        while (iter != system_planets.end())
525
 
        {
526
 
                equPos = (*iter)->get_earth_equ_pos(nav);
527
 
                equPos.normalize();
528
 
                if (equPos[0]*v[0] + equPos[1]*v[1] + equPos[2]*v[2]>=cos_lim_fov)
529
 
                {
530
 
                        result.push_back(*iter);
531
 
                }
532
 
                iter++;
533
 
        }
534
 
        return result;
535
 
}
536
 
 
537
 
//! @brief Update i18 names from english names according to passed translator
538
 
//! The translation is done using gettext with translated strings defined in translations.h
539
 
void SolarSystem::translateNames(Translator& trans)
540
 
{
541
 
        vector<Planet*>::iterator iter;
542
 
        for( iter = system_planets.begin(); iter < system_planets.end(); iter++ )
543
 
        {
544
 
                (*iter)->translateName(trans);
545
 
        }
546
 
}
547
 
 
548
 
vector<wstring> SolarSystem::getNamesI18(void)
549
 
{
550
 
        vector<wstring> names;
551
 
        vector < Planet * >::iterator iter;
552
 
 
553
 
        for (iter = system_planets.begin(); iter != system_planets.end(); ++iter)
554
 
                names.push_back((*iter)->getNameI18());
555
 
        return names;
556
 
}
557
 
 
558
 
 
559
 
// returns a newline delimited hash of localized:standard planet names for tui
560
 
wstring SolarSystem::getPlanetHashString(void)
561
 
{
562
 
        wostringstream oss;
563
 
        vector < Planet * >::iterator iter;
564
 
 
565
 
        for (iter = system_planets.begin(); iter != system_planets.end(); ++iter) {
566
 
                oss << Translator::globalTranslator.translate((*iter)->getEnglishName()) << "\n";
567
 
                oss << StelUtility::stringToWstring((*iter)->getEnglishName()) << "\n";
568
 
        }
569
 
 
570
 
        // wcout <<  oss.str();
571
 
 
572
 
        return oss.str();
573
 
 
574
 
}
575
 
 
576
 
 
577
 
void SolarSystem::updateTrails(const Navigator* nav)
578
 
{
579
 
        vector<Planet*>::iterator iter;
580
 
        for( iter = system_planets.begin(); iter < system_planets.end(); iter++ )
581
 
        {
582
 
                (*iter)->update_trail(nav);
583
 
        }
584
 
}
585
 
 
586
 
void SolarSystem::startTrails(bool b)
587
 
{
588
 
        vector<Planet*>::iterator iter;
589
 
        for( iter = system_planets.begin(); iter < system_planets.end(); iter++ )
590
 
        {
591
 
                (*iter)->startTrail(b);
592
 
        }
593
 
}
594
 
 
595
 
void SolarSystem::setFlagTrails(bool b)
596
 
{
597
 
        vector<Planet*>::iterator iter;
598
 
        for( iter = system_planets.begin(); iter < system_planets.end(); iter++ )
599
 
        {
600
 
                (*iter)->setFlagTrail(b);
601
 
        }
602
 
}
603
 
 
604
 
bool SolarSystem::getFlagTrails(void) const
605
 
{
606
 
        for (vector<Planet*>::const_iterator iter = system_planets.begin();
607
 
             iter != system_planets.end(); iter++ ) {
608
 
                if ((*iter)->getFlagTrail()) return true;
609
 
        }
610
 
        return false;
611
 
}
612
 
 
613
 
void SolarSystem::setFlagHints(bool b)
614
 
{
615
 
        vector<Planet*>::iterator iter;
616
 
        for( iter = system_planets.begin(); iter < system_planets.end(); iter++ )
617
 
        {
618
 
                (*iter)->setFlagHints(b);
619
 
        }
620
 
}
621
 
 
622
 
bool SolarSystem::getFlagHints(void) const
623
 
{
624
 
        for (vector<Planet*>::const_iterator iter = system_planets.begin();
625
 
        iter != system_planets.end(); iter++ ) {
626
 
                if ((*iter)->getFlagHints()) return true;
627
 
        }
628
 
        return false;
629
 
}
630
 
 
631
 
void SolarSystem::setFlagOrbits(bool b)
632
 
{
633
 
        flagOrbits = b;
634
 
        if (!b || selected == NULL || selected->getEnglishName() == "Sun")
635
 
        {
636
 
                vector<Planet*>::iterator iter;
637
 
                for( iter = system_planets.begin(); iter < system_planets.end(); iter++ )
638
 
                {
639
 
                        (*iter)->setFlagOrbits(b);
640
 
                }
641
 
        }
642
 
        else
643
 
        {
644
 
                // if a Planet is selected and orbits are on, fade out non-selected ones
645
 
                vector<Planet*>::iterator iter;
646
 
                for( iter = system_planets.begin(); iter < system_planets.end(); iter++ )
647
 
                {
648
 
                        if((*iter)!=selected) (*iter)->setFlagOrbits(false);
649
 
                        else (*iter)->setFlagOrbits(b);
650
 
                }               
651
 
        }
652
 
}
653
 
 
654
 
 
655
 
void SolarSystem::setSelected(Planet * p)
656
 
{
657
 
        selected = p;
658
 
        // Undraw other objects hints, orbit, trails etc..
659
 
        setFlagHints(getFlagHints());
660
 
        setFlagOrbits(getFlagOrbits());
661
 
        setFlagTrails(getFlagTrails());
662
 
}
663
 
 
664
 
// draws earth shadow overlapping the moon using stencil buffer
665
 
// umbra and penumbra are sized separately for accuracy
666
 
void SolarSystem::draw_earth_shadow(const Navigator * nav, Projector * prj)
667
 
{
668
 
 
669
 
        Vec3d e = getEarth()->get_ecliptic_pos();
670
 
        Vec3d m = getMoon()->get_ecliptic_pos();  // relative to earth
671
 
        Vec3d mh = getMoon()->get_heliocentric_ecliptic_pos();  // relative to sun
672
 
        float mscale = getMoon()->get_sphere_scale();
673
 
 
674
 
        // shadow location at earth + moon distance along earth vector from sun
675
 
        Vec3d en = e;
676
 
        en.normalize();
677
 
        Vec3d shadow = en * (e.length() + m.length());
678
 
 
679
 
        glEnable(GL_BLEND);
680
 
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
681
 
        glColor3f(1,1,1);
682
 
 
683
 
        // find shadow radii in AU
684
 
        double r_penumbra = shadow.length()*702378.1/AU/e.length() - 696000/AU;
685
 
        double r_umbra = 6378.1/AU - m.length()*(689621.9/AU/e.length());
686
 
 
687
 
        // find vector orthogonal to sun-earth vector using cross product with
688
 
        // a non-parallel vector
689
 
        Vec3d rpt = shadow^Vec3d(0,0,1);
690
 
        rpt.normalize();
691
 
        Vec3d upt = rpt*r_umbra*mscale*1.02;  // point on umbra edge
692
 
        rpt *= r_penumbra*mscale;  // point on penumbra edge
693
 
 
694
 
        // modify shadow location for scaled moon
695
 
        Vec3d mdist = shadow - mh;
696
 
        if(mdist.length() > r_penumbra + 2000/AU) return;   // not visible so don't bother drawing
697
 
 
698
 
        shadow = mh + mdist*mscale;
699
 
        r_penumbra *= mscale;
700
 
 
701
 
        nav->switch_to_heliocentric();
702
 
        glEnable(GL_STENCIL_TEST);
703
 
        glStencilFunc(GL_EQUAL, 0x1, 0x1);
704
 
        glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
705
 
 
706
 
        Mat4d mat = nav->get_helio_to_eye_mat();
707
 
 
708
 
        // shadow radial texture
709
 
        glBindTexture(GL_TEXTURE_2D, tex_earth_shadow->getID());
710
 
 
711
 
        Vec3d r, s;
712
 
 
713
 
        // umbra first
714
 
        glBegin(GL_TRIANGLE_FAN);
715
 
        glTexCoord2f(0,0);
716
 
        prj->sVertex3( shadow[0],shadow[1], shadow[2], mat);
717
 
 
718
 
        for (int i=0; i<=100; i++)
719
 
        {
720
 
                r = Mat4d::rotation(shadow, 2*M_PI*i/100.) * upt;
721
 
                s = shadow + r;
722
 
 
723
 
                glTexCoord2f(0.6,0);  // position in texture of umbra edge
724
 
                prj->sVertex3( s[0],s[1], s[2], mat);
725
 
        }
726
 
        glEnd();
727
 
 
728
 
 
729
 
        // now penumbra
730
 
        Vec3d u, sp;
731
 
        glBegin(GL_TRIANGLE_STRIP);
732
 
        for (int i=0; i<=100; i++)
733
 
        {
734
 
                r = Mat4d::rotation(shadow, 2*M_PI*i/100.) * rpt;
735
 
                u = Mat4d::rotation(shadow, 2*M_PI*i/100.) * upt;
736
 
                s = shadow + r;
737
 
                sp = shadow + u;
738
 
 
739
 
                glTexCoord2f(0.6,0);
740
 
                prj->sVertex3( sp[0],sp[1], sp[2], mat);
741
 
 
742
 
                glTexCoord2f(1.,0);  // position in texture of umbra edge
743
 
                prj->sVertex3( s[0],s[1], s[2], mat);
744
 
        }
745
 
        glEnd();
746
 
 
747
 
        glDisable(GL_STENCIL_TEST);
748
 
 
749
 
}
750
 
 
751
 
 
752
 
void SolarSystem::update(int delta_time, Navigator* nav)
753
 
{
754
 
        vector<Planet*>::iterator iter = system_planets.begin();
755
 
        while (iter != system_planets.end())
756
 
        {
757
 
                (*iter)->update_trail(nav);
758
 
                (*iter)->update(delta_time);
759
 
                iter++;
760
 
        }
761
 
 
762
 
 
763
 
}
764
 
 
765
 
 
766
 
// is a lunar eclipse close at hand?
767
 
bool SolarSystem::near_lunar_eclipse(const Navigator * nav, Projector *prj)
768
 
{
769
 
        // TODO: could replace with simpler test
770
 
 
771
 
        Vec3d e = getEarth()->get_ecliptic_pos();
772
 
        Vec3d m = getMoon()->get_ecliptic_pos();  // relative to earth
773
 
        Vec3d mh = getMoon()->get_heliocentric_ecliptic_pos();  // relative to sun
774
 
 
775
 
        // shadow location at earth + moon distance along earth vector from sun
776
 
        Vec3d en = e;
777
 
        en.normalize();
778
 
        Vec3d shadow = en * (e.length() + m.length());
779
 
 
780
 
        // find shadow radii in AU
781
 
        double r_penumbra = shadow.length()*702378.1/AU/e.length() - 696000/AU;
782
 
 
783
 
        // modify shadow location for scaled moon
784
 
        Vec3d mdist = shadow - mh;
785
 
        if(mdist.length() > r_penumbra + 2000/AU) return 0;   // not visible so don't bother drawing
786
 
 
787
 
        return 1;
788
 
}
789
 
 
790
 
//! Find and return the list of at most maxNbItem objects auto-completing the passed object I18n name
791
 
vector<wstring> SolarSystem::listMatchingObjectsI18n(const wstring& objPrefix, unsigned int maxNbItem) const
792
 
{
793
 
        vector<wstring> result;
794
 
        if (maxNbItem==0) return result;
795
 
        
796
 
        wstring objw = objPrefix;
797
 
        transform(objw.begin(), objw.end(), objw.begin(), ::toupper);
798
 
        
799
 
        vector < Planet * >::const_iterator iter;
800
 
        for (iter = system_planets.begin(); iter != system_planets.end(); ++iter)
801
 
        {
802
 
                wstring constw = (*iter)->getNameI18().substr(0, objw.size());
803
 
                transform(constw.begin(), constw.end(), constw.begin(), ::toupper);
804
 
                if (constw==objw)
805
 
                {
806
 
                        result.push_back((*iter)->getNameI18());
807
 
                        if (result.size()==maxNbItem)
808
 
                                return result;
809
 
                }
810
 
        }
811
 
        return result;
812
 
}