3
* Copyright (C) 2002 Fabien Chereau
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.
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.
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.
25
#include "solarsystem.h"
26
#include "s_texture.h"
27
#include "stellplanet.h"
29
#include "stellarium.h"
30
#include "init_parser.h"
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) {
40
void SolarSystem::setFont(float font_size, const string& font_name)
42
if(planet_name_font) delete planet_name_font;
44
planet_name_font = new s_font(font_size, font_name);
45
if (!planet_name_font)
47
printf("Can't create planet_name_font\n");
50
Planet::set_font(planet_name_font);
53
SolarSystem::~SolarSystem()
55
for(vector<Planet*>::iterator iter = system_planets.begin(); iter != system_planets.end(); ++iter)
57
if (*iter) delete *iter;
60
for(vector<EllipticalOrbit*>::iterator iter = ell_orbits.begin(); iter != ell_orbits.end(); ++iter)
62
if (*iter) delete *iter;
69
if (planet_name_font) delete planet_name_font;
70
if(tex_earth_shadow) delete tex_earth_shadow;
74
// Init and load the solar system data
75
void SolarSystem::load(const string& planetfile)
77
cout << "Loading Solar System data...";
78
InitParser pd; // The Planet data ini file parser
81
int nbSections = pd.get_nsec();
82
for (int i = 0;i<nbSections;++i)
84
const string secname = pd.get_secname(i);
85
const string englishName = pd.get_str(secname, "name");
87
const string str_parent = pd.get_str(secname, "parent");
88
Planet *parent = NULL;
90
if (str_parent!="none")
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())
96
if ((*iter)->getEnglishName()==str_parent)
104
cout << "ERROR : can't find parent for " << englishName << endl;
109
const string funcname = pd.get_str(secname, "coord_func");
111
pos_func_type posfunc;
112
OsulatingFunctType *osculating_func = 0;
113
EllipticalOrbit* orb = NULL;
115
if (funcname=="ell_orbit")
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.;
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);
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()
135
const double parent_rot_asc_node = parent->get_parent()
136
? parent->getRotAscendingnode()
138
// Create an elliptical orbit
139
orb = new EllipticalOrbit(pericenter_distance,
147
parent_rot_obliquity,
148
parent_rot_asc_node);
149
ell_orbits.push_back(orb);
151
posfunc = pos_func_type(orb, &EllipticalOrbit::positionAtTimevInVSOP87Coordinates);
154
if (funcname=="sun_special")
155
posfunc = pos_func_type(get_sun_helio_coordsv);
157
if (funcname=="mercury_special") {
158
posfunc = pos_func_type(get_mercury_helio_coordsv);
159
osculating_func = &get_mercury_helio_osculating_coords;
162
if (funcname=="venus_special") {
163
posfunc = pos_func_type(get_venus_helio_coordsv);
164
osculating_func = &get_venus_helio_osculating_coords;
167
if (funcname=="earth_special") {
168
posfunc = pos_func_type(get_earth_helio_coordsv);
169
osculating_func = &get_earth_helio_osculating_coords;
172
if (funcname=="lunar_special")
173
posfunc = pos_func_type(get_lunar_parent_coordsv);
175
if (funcname=="mars_special") {
176
posfunc = pos_func_type(get_mars_helio_coordsv);
177
osculating_func = &get_mars_helio_osculating_coords;
180
if (funcname=="phobos_special")
181
posfunc = pos_func_type(get_phobos_parent_coordsv);
183
if (funcname=="deimos_special")
184
posfunc = pos_func_type(get_deimos_parent_coordsv);
186
if (funcname=="jupiter_special") {
187
posfunc = pos_func_type(get_jupiter_helio_coordsv);
188
osculating_func = &get_jupiter_helio_osculating_coords;
191
if (funcname=="europa_special")
192
posfunc = pos_func_type(get_europa_parent_coordsv);
194
if (funcname=="calisto_special")
195
posfunc = pos_func_type(get_callisto_parent_coordsv);
197
if (funcname=="io_special")
198
posfunc = pos_func_type(get_io_parent_coordsv);
200
if (funcname=="ganymede_special")
201
posfunc = pos_func_type(get_ganymede_parent_coordsv);
203
if (funcname=="saturn_special") {
204
posfunc = pos_func_type(get_saturn_helio_coordsv);
205
osculating_func = &get_saturn_helio_osculating_coords;
208
if (funcname=="mimas_special")
209
posfunc = pos_func_type(get_mimas_parent_coordsv);
211
if (funcname=="enceladus_special")
212
posfunc = pos_func_type(get_enceladus_parent_coordsv);
214
if (funcname=="tethys_special")
215
posfunc = pos_func_type(get_tethys_parent_coordsv);
217
if (funcname=="dione_special")
218
posfunc = pos_func_type(get_dione_parent_coordsv);
220
if (funcname=="rhea_special")
221
posfunc = pos_func_type(get_rhea_parent_coordsv);
223
if (funcname=="titan_special")
224
posfunc = pos_func_type(get_titan_parent_coordsv);
226
if (funcname=="iapetus_special")
227
posfunc = pos_func_type(get_iapetus_parent_coordsv);
229
if (funcname=="hyperion_special")
230
posfunc = pos_func_type(get_hyperion_parent_coordsv);
232
if (funcname=="uranus_special") {
233
posfunc = pos_func_type(get_uranus_helio_coordsv);
234
osculating_func = &get_uranus_helio_osculating_coords;
237
if (funcname=="miranda_special")
238
posfunc = pos_func_type(get_miranda_parent_coordsv);
240
if (funcname=="ariel_special")
241
posfunc = pos_func_type(get_ariel_parent_coordsv);
243
if (funcname=="umbriel_special")
244
posfunc = pos_func_type(get_umbriel_parent_coordsv);
246
if (funcname=="titania_special")
247
posfunc = pos_func_type(get_titania_parent_coordsv);
249
if (funcname=="oberon_special")
250
posfunc = pos_func_type(get_oberon_parent_coordsv);
252
if (funcname=="neptune_special") {
253
posfunc = pos_func_type(get_neptune_helio_coordsv);
254
osculating_func = &get_neptune_helio_osculating_coords;
257
if (funcname=="pluto_special")
258
posfunc = pos_func_type(get_pluto_helio_coordsv);
263
cout << "ERROR : can't find posfunc " << funcname << " for " << englishName << endl;
267
// Create the Planet and add it to the list
268
Planet* p = new Planet(parent,
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));
281
if (secname=="earth") earth = p;
282
if (secname=="sun") sun = p;
283
if (secname=="moon") moon = p;
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.) );
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"));
302
string bighalotexfile = pd.get_str(secname, "tex_big_halo", "");
303
if (!bighalotexfile.empty())
305
p->set_big_halo(bighalotexfile);
306
p->set_halo_size(pd.get_double(secname, "big_halo_size", 50.f));
309
system_planets.push_back(p);
312
// special case: load earth shadow texture
313
tex_earth_shadow = new s_texture("earth-shadow.png", TEX_LOAD_TYPE_PNG_ALPHA);
315
cout << "(loaded)" << endl;
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);
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);
337
for (vector<Planet*>::const_iterator iter(system_planets.begin());
338
iter!=system_planets.end();iter++) {
339
(*iter)->compute_position(date);
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);
357
for (vector<Planet*>::const_iterator iter(system_planets.begin());
358
iter!=system_planets.end();iter++) {
359
(*iter)->compute_trans_matrix(date);
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)
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);
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);
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));
387
// Compute each Planet distance to the observer
388
Vec3d obs_helio_pos = nav->get_observer_helio_pos();
390
vector<Planet*>::iterator iter;
391
iter = system_planets.begin();
392
while (iter != system_planets.end())
394
(*iter)->compute_distance(obs_helio_pos);
398
// And sort them from the furthest to the closest
399
sort(system_planets.begin(),system_planets.end(),bigger_distance());
402
double maxSquaredDistance = 0;
403
iter = system_planets.begin();
404
while (iter != system_planets.end())
406
double squaredDistance = 0;
407
if(*iter==moon && near_lunar_eclipse(nav, prj))
410
// TODO: moon magnitude label during eclipse isn't accurate...
412
// special case to update stencil buffer for drawing lunar eclipses
413
glClear(GL_STENCIL_BUFFER_BIT);
416
glStencilFunc(GL_ALWAYS, 0x1, 0x1);
417
glStencilOp(GL_ZERO, GL_REPLACE, GL_REPLACE);
419
squaredDistance = (*iter)->draw(prj, nav, eye, flag_point, 1);
424
squaredDistance = (*iter)->draw(prj, nav, eye, flag_point, 0);
426
if (squaredDistance > maxSquaredDistance)
427
maxSquaredDistance = squaredDistance;
432
glDisable(GL_LIGHT0);
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);
441
return maxSquaredDistance;
444
Planet* SolarSystem::searchByEnglishName(string planetEnglishName) const
446
//printf("SolarSystem::searchByEnglishName(\"%s\"): start\n",
447
// planetEnglishName.c_str());
448
// side effect - bad?
449
// transform(planetEnglishName.begin(), planetEnglishName.end(), planetEnglishName.begin(), ::tolower);
451
vector<Planet*>::const_iterator iter = system_planets.begin();
452
while (iter != system_planets.end())
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
460
//printf("SolarSystem::searchByEnglishName(\"%s\"): not found\n",
461
// planetEnglishName.c_str());
465
Planet* SolarSystem::searchByNamesI18(wstring planetNameI18) const
468
// side effect - bad?
469
// transform(planetNameI18.begin(), planetNameI18.end(), planetNameI18.begin(), ::tolower);
471
vector<Planet*>::const_iterator iter = system_planets.begin();
472
while (iter != system_planets.end())
475
if( (*iter)->getNameI18() == planetNameI18 ) return (*iter); // also check standard ini file names
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
486
Planet * closest = NULL;
487
double cos_angle_closest = 0.;
490
vector<Planet*>::const_iterator iter = system_planets.begin();
491
while (iter != system_planets.end())
493
equPos = (*iter)->get_earth_equ_pos(nav);
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)
499
cos_angle_closest = cos_ang_dist;
505
if (cos_angle_closest>0.999)
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,
515
const Navigator * nav,
516
const Projector * prj) const
518
vector<StelObject*> result;
520
double cos_lim_fov = cos(lim_fov * M_PI/180.);
523
vector<Planet*>::const_iterator iter = system_planets.begin();
524
while (iter != system_planets.end())
526
equPos = (*iter)->get_earth_equ_pos(nav);
528
if (equPos[0]*v[0] + equPos[1]*v[1] + equPos[2]*v[2]>=cos_lim_fov)
530
result.push_back(*iter);
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)
541
vector<Planet*>::iterator iter;
542
for( iter = system_planets.begin(); iter < system_planets.end(); iter++ )
544
(*iter)->translateName(trans);
548
vector<wstring> SolarSystem::getNamesI18(void)
550
vector<wstring> names;
551
vector < Planet * >::iterator iter;
553
for (iter = system_planets.begin(); iter != system_planets.end(); ++iter)
554
names.push_back((*iter)->getNameI18());
559
// returns a newline delimited hash of localized:standard planet names for tui
560
wstring SolarSystem::getPlanetHashString(void)
563
vector < Planet * >::iterator iter;
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";
570
// wcout << oss.str();
577
void SolarSystem::updateTrails(const Navigator* nav)
579
vector<Planet*>::iterator iter;
580
for( iter = system_planets.begin(); iter < system_planets.end(); iter++ )
582
(*iter)->update_trail(nav);
586
void SolarSystem::startTrails(bool b)
588
vector<Planet*>::iterator iter;
589
for( iter = system_planets.begin(); iter < system_planets.end(); iter++ )
591
(*iter)->startTrail(b);
595
void SolarSystem::setFlagTrails(bool b)
597
vector<Planet*>::iterator iter;
598
for( iter = system_planets.begin(); iter < system_planets.end(); iter++ )
600
(*iter)->setFlagTrail(b);
604
bool SolarSystem::getFlagTrails(void) const
606
for (vector<Planet*>::const_iterator iter = system_planets.begin();
607
iter != system_planets.end(); iter++ ) {
608
if ((*iter)->getFlagTrail()) return true;
613
void SolarSystem::setFlagHints(bool b)
615
vector<Planet*>::iterator iter;
616
for( iter = system_planets.begin(); iter < system_planets.end(); iter++ )
618
(*iter)->setFlagHints(b);
622
bool SolarSystem::getFlagHints(void) const
624
for (vector<Planet*>::const_iterator iter = system_planets.begin();
625
iter != system_planets.end(); iter++ ) {
626
if ((*iter)->getFlagHints()) return true;
631
void SolarSystem::setFlagOrbits(bool b)
634
if (!b || selected == NULL || selected->getEnglishName() == "Sun")
636
vector<Planet*>::iterator iter;
637
for( iter = system_planets.begin(); iter < system_planets.end(); iter++ )
639
(*iter)->setFlagOrbits(b);
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++ )
648
if((*iter)!=selected) (*iter)->setFlagOrbits(false);
649
else (*iter)->setFlagOrbits(b);
655
void SolarSystem::setSelected(Planet * p)
658
// Undraw other objects hints, orbit, trails etc..
659
setFlagHints(getFlagHints());
660
setFlagOrbits(getFlagOrbits());
661
setFlagTrails(getFlagTrails());
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)
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();
674
// shadow location at earth + moon distance along earth vector from sun
677
Vec3d shadow = en * (e.length() + m.length());
680
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
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());
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);
691
Vec3d upt = rpt*r_umbra*mscale*1.02; // point on umbra edge
692
rpt *= r_penumbra*mscale; // point on penumbra edge
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
698
shadow = mh + mdist*mscale;
699
r_penumbra *= mscale;
701
nav->switch_to_heliocentric();
702
glEnable(GL_STENCIL_TEST);
703
glStencilFunc(GL_EQUAL, 0x1, 0x1);
704
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
706
Mat4d mat = nav->get_helio_to_eye_mat();
708
// shadow radial texture
709
glBindTexture(GL_TEXTURE_2D, tex_earth_shadow->getID());
714
glBegin(GL_TRIANGLE_FAN);
716
prj->sVertex3( shadow[0],shadow[1], shadow[2], mat);
718
for (int i=0; i<=100; i++)
720
r = Mat4d::rotation(shadow, 2*M_PI*i/100.) * upt;
723
glTexCoord2f(0.6,0); // position in texture of umbra edge
724
prj->sVertex3( s[0],s[1], s[2], mat);
731
glBegin(GL_TRIANGLE_STRIP);
732
for (int i=0; i<=100; i++)
734
r = Mat4d::rotation(shadow, 2*M_PI*i/100.) * rpt;
735
u = Mat4d::rotation(shadow, 2*M_PI*i/100.) * upt;
740
prj->sVertex3( sp[0],sp[1], sp[2], mat);
742
glTexCoord2f(1.,0); // position in texture of umbra edge
743
prj->sVertex3( s[0],s[1], s[2], mat);
747
glDisable(GL_STENCIL_TEST);
752
void SolarSystem::update(int delta_time, Navigator* nav)
754
vector<Planet*>::iterator iter = system_planets.begin();
755
while (iter != system_planets.end())
757
(*iter)->update_trail(nav);
758
(*iter)->update(delta_time);
766
// is a lunar eclipse close at hand?
767
bool SolarSystem::near_lunar_eclipse(const Navigator * nav, Projector *prj)
769
// TODO: could replace with simpler test
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
775
// shadow location at earth + moon distance along earth vector from sun
778
Vec3d shadow = en * (e.length() + m.length());
780
// find shadow radii in AU
781
double r_penumbra = shadow.length()*702378.1/AU/e.length() - 696000/AU;
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
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
793
vector<wstring> result;
794
if (maxNbItem==0) return result;
796
wstring objw = objPrefix;
797
transform(objw.begin(), objw.end(), objw.begin(), ::toupper);
799
vector < Planet * >::const_iterator iter;
800
for (iter = system_planets.begin(); iter != system_planets.end(); ++iter)
802
wstring constw = (*iter)->getNameI18().substr(0, objw.size());
803
transform(constw.begin(), constw.end(), constw.begin(), ::toupper);
806
result.push_back((*iter)->getNameI18());
807
if (result.size()==maxNbItem)