1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2015 Gerhard Holtkamp
4 //
5
6 /***************************************************************************
7 * Calculate positions and physical ephemerides of Solar System bodies. * * *
8 * The algorithm for the Modified Julian Date are based on *
9 * O.Montebruck and T.Pfleger, "Astronomy with a PC", *
10 * Springer Verlag, Berlin, Heidelberg, New York, 1989 *
11 *
12 * The calculations of the positions and physical ephemerides of the *
13 * various solar system bodies are based on *
14 * O.Montebruck, "Astronomie mit dem Personal Computer", *
15 * Springer Verlag, Berlin, Heidelberg, 1989; *
16 * O.Montebruck, "Practical Ephemeris Calculations", *
17 * Springer Verlag, Berlin, Heidelberg, New York, 1989 *
18 * and on the *
19 * "Explanatory Supplement to the Astronomical Almanac" *
20 * University Science Books, Mill Valley, CA, 1992 *
21 * *
22 * Open Source Code. License: GNU LGPL Version 2+ *
23 * *
24 * Author: Gerhard HOLTKAMP, 09-JAN-2015 *
25 ***************************************************************************/
26
27 /*------------ include files and definitions -----------------------------*/
28 #include "solarsystem.h"
29 #include <cstdio>
30 #include <cstdlib>
31 #include <cstring>
32 #include <cmath>
33 #include <ctime>
34 using namespace std;
35
36 #include "astrolib.h"
37 #include "astr2lib.h"
38
39 const double degrad = M_PI / 180.0;
40
41 // ################ Solar Eclipse Class ####################
42
SolarSystem()43 SolarSystem::SolarSystem()
44 {
45 ssinit();
46 }
47
~SolarSystem()48 SolarSystem::~SolarSystem()
49 {
50
51 }
52
atan23(double y,double x)53 double SolarSystem::atan23 (double y, double x)
54 {
55 /* redefine atan2 so that it doesn't crash when both x and y are 0 */
56 double result;
57
58 if ((x == 0) && (y == 0)) result = 0;
59 else result = atan2 (y, x);
60
61 return result;
62 }
63
DegFDms(double h)64 double SolarSystem::DegFDms (double h)
65 {
66 /* convert degrees from d.fff -> d.mmsss where .mm are the minutes
67 and sss are seconds (and fractions of seconds).
68 */
69 int mm, deg;
70 double hh, t, sec;
71
72 hh = fabs(h);
73 dms (hh,deg,mm,sec);
74 if (sec>=59.5)
75 {
76 mm++;
77 sec = 0;
78 };
79 if (mm>59)
80 {
81 deg++;
82 mm=0;
83 };
84 hh = double(deg);
85 t = double(mm)/100.0;
86 hh += t;
87 t = sec/10000.0;
88 hh += t;
89 if (h < 0) hh = -hh;
90
91 return hh;
92 }
93
DmsDegF(double h)94 double SolarSystem::DmsDegF (double h)
95 {
96 /* convert degrees from d.mmsss -> d.fff where .mm are the minutes
97 and sss are seconds (and fractions of seconds).
98 Returned is the angle in decimal degrees.
99 */
100 int mm, deg;
101 double hh, t, sec, dlt;
102
103 hh = fabs(h);
104 dlt = hh*3.33e-16;
105 hh += dlt;
106 deg = int(hh);
107 t = fmod(hh,1.0)*100.0;
108 mm = int(t + 0.1e-12);
109 sec = fmod(hh*100.0,1.0)*100.0;
110 hh = ddd(deg,mm,sec);
111 if (h < 0) hh = -hh;
112
113 return hh;
114 }
115
ssinit()116 void SolarSystem::ssinit()
117 {
118 // initialize solar system data
119 ss_update_called = false;
120 ss_moon_called = false;
121 ss_nutation = false;
122 ss_planmat_called = false;
123 ss_kepler_stored = false;
124 ss_kepler_called = false;
125 ss_user_stored= false;
126 ss_user_active = false;
127
128 ss_day = 1;
129 ss_month = 1;
130 ss_year = 2012;
131 ss_hour = 0;
132 ss_minute = 0;
133 ss_second = 0;
134 ss_tzone = 0;
135 ss_del_auto = 1;
136 ss_del_tdut = DefTdUt(ss_year);
137 ss_RT = true;
138 ss_epoch = 51544.5; // J2000.0
139 ss_central_body = 4;
140 setCurrentMJD();
141 ss_planmat = mxidn();
142 getConstEarth();
143
144 // just to have some data there in case
145 ss_user_J2 = 1.08263e-3;
146 ss_user_R0 = 6378.140;
147 ss_user_flat = 0.00335364;
148 ss_user_axl0 = 0.0;
149 ss_user_axl1 = 0.0;
150 ss_user_axb0 = 90.0;
151 ss_user_axb1 = 0.0;
152 ss_user_W = 0;
153 ss_user_Wd = 359.017045833334;
154 ss_user_GM = 3.986005e+14;
155
156 }
157
DefTime()158 void SolarSystem::DefTime () // Get System Time and Date
159 {
160 time_t tt;
161 int hh, mm, ss;
162 double jd, hr;
163
164 tt = time(NULL);
165 jd = 40587.0 + tt/86400.0; // seconds since 1-JAN-1970
166
167 caldat(jd, hh, mm, ss, hr);
168 ss_year = ss;
169 ss_month = mm;
170 ss_day = hh;
171
172 dms(hr, hh, mm, jd);
173 ss_hour = hh;
174 ss_minute = mm;
175 ss_second = int(jd);
176 if (ss_del_auto) ss_del_tdut = DefTdUt(ss_year);
177 };
178
setTimezone(double d)179 void SolarSystem::setTimezone(double d)
180 {
181 // set the timezone to d (hours difference from UTC) for I/O
182 ss_tzone = d;
183 }
184
setDeltaTAI_UTC(double d)185 void SolarSystem::setDeltaTAI_UTC(double d)
186 {
187 // c is the difference between TAI and UTC according to the IERS
188 // we have to add 32.184 sec to get to the difference TT - UT
189 // which is used in the calculations here
190
191 ss_del_tdut = d + 32.184;
192 ss_del_auto = 0;
193 }
194
setAutoTAI_UTC()195 void SolarSystem::setAutoTAI_UTC()
196 {
197 // set the difference between TAI and UTC according to the IERS
198 ss_del_auto = true;
199 ss_del_tdut = DefTdUt(ss_year);
200 }
201
setCurrentMJD(int year,int month,int day,int hour,int min,double sec)202 void SolarSystem::setCurrentMJD(int year, int month, int day, int hour, int min, double sec)
203 {
204 // set the (MJD-) time currently used for calculations to year, month, day, hour, min, sec
205 // corrected for timezone
206
207 double jd;
208
209 jd = ddd(hour, min, sec) - ss_tzone;
210 jd = mjd(day, month, year, jd);
211
212 ss_time = jd;
213 ss_update_called = false;
214 ss_moon_called = false;
215 ss_planmat_called = false;
216 ss_kepler_called = false;
217
218 }
219
setCurrentMJD()220 void SolarSystem::setCurrentMJD()
221 {
222 // set the (MJD-) time currently used for calculations to Real Time
223
224 double jd, sec;
225
226 DefTime();
227 sec = double(ss_second);
228 jd = ddd(ss_hour, ss_minute, sec);
229 jd = mjd(ss_day, ss_month, ss_year, jd);
230
231 ss_time = jd;
232 ss_update_called = false;
233 ss_moon_called = false;
234 ss_planmat_called = false;
235 ss_kepler_called = false;
236
237 }
238
getMJD(int year,int month,int day,int hour,int min,double sec)239 double SolarSystem::getMJD(int year, int month, int day, int hour, int min, double sec)
240 {
241 // return the (MJD-) time corresponding to year, month, day, hour, min, sec
242 // corrected for timezone
243
244 double jd;
245
246 jd = ddd(hour, min, sec) - ss_tzone;
247 jd = mjd(day, month, year, jd);
248
249 return jd;
250 }
251
getDatefromMJD(double mjd,int & year,int & month,int & day,int & hour,int & min,double & sec)252 void SolarSystem::getDatefromMJD(double mjd, int &year, int &month, int &day, int &hour, int &min, double &sec)
253 {
254 // convert times given in Modified Julian Date (MJD) into conventional date and time
255 // correct for timezone
256
257 double magn;
258
259 caldat((mjd + ss_tzone/24.0), day, month, year, magn);
260 dms (magn,hour,min,sec);
261 if (sec>30.0) min++;
262 if (min>59)
263 {
264 hour++;
265 min=0;
266 };
267 }
268
setEpoch(double yr)269 void SolarSystem::setEpoch (double yr)
270 {
271 int day, month, year;
272 double b;
273
274 if (yr == 0) ss_epoch = 0; // Mean of Date
275 else
276 {
277 year = int(yr);
278 b = 12.0 * (yr - double(year));
279 month = int(b) + 1;
280 day = 1;
281
282 b = 0;
283 ss_epoch = mjd(day, month, year, b);
284 }
285 ss_update_called = false;
286 ss_moon_called = false;
287 ss_planmat_called = false;
288 ss_kepler_called = false;
289
290 }
291
setNutation(bool nut)292 void SolarSystem::setNutation (bool nut)
293 {
294 ss_nutation = nut;
295 ss_update_called = false;
296 ss_moon_called = false;
297 ss_planmat_called = false;
298 ss_kepler_called = false;
299
300 }
301
setCentralBody(char * pname)302 void SolarSystem::setCentralBody(char* pname)
303 {
304 ss_central_body = 4; // default Earth
305 getConstEarth();
306 if (strncmp("Sun", pname, 3) == 0)
307 {
308 ss_central_body = 0;
309 getConstSun();
310 };
311 if (strncmp("Moon", pname, 4) == 0)
312 {
313 ss_central_body = 1;
314 getConstMoon();
315 };
316 if (strncmp("Mercury", pname, 7) == 0)
317 {
318 ss_central_body = 2;
319 getConstMercury();
320 };
321 if (strncmp("Venus", pname, 5) == 0)
322 {
323 ss_central_body = 3;
324 getConstVenus();
325 };
326 if (strncmp("Mars", pname, 4) == 0)
327 {
328 ss_central_body = 5;
329 getConstMars();
330 };
331 if (strncmp("Jupiter", pname, 7) == 0)
332 {
333 ss_central_body = 6;
334 getConstJupiter();
335 };
336 if (strncmp("Saturn", pname, 6) == 0)
337 {
338 ss_central_body = 7;
339 getConstSaturn();
340 };
341 if (strncmp("Uranus", pname, 6) == 0)
342 {
343 ss_central_body = 8;
344 getConstUranus();
345 };
346 if (strncmp("Neptune", pname, 7) == 0)
347 {
348 ss_central_body = 9;
349 getConstNeptune();
350 };
351 if (strncmp("Io", pname, 2) == 0)
352 {
353 ss_central_body = 10;
354 getConstIo();
355 };
356 if (strncmp("Europa", pname, 6) == 0)
357 {
358 ss_central_body = 11;
359 getConstEuropa();
360 };
361 if (strncmp("Ganymede", pname, 8) == 0)
362 {
363 ss_central_body = 12;
364 getConstGanymede();
365 };
366 if (strncmp("Callisto", pname, 8) == 0)
367 {
368 ss_central_body = 13;
369 getConstCallisto();
370 };
371 if (strncmp("Rhea", pname, 4) == 0)
372 {
373 ss_central_body = 14;
374 getConstRhea();
375 };
376 if (strncmp("Titan", pname, 5) == 0)
377 {
378 ss_central_body = 15;
379 getConstTitan();
380 };
381 if (strncmp("Mimas", pname, 5) == 0)
382 {
383 ss_central_body = 16;
384 getConstMimas();
385 };
386 if (strncmp("Enceladus", pname, 9) == 0)
387 {
388 ss_central_body = 17;
389 getConstEnceladus();
390 };
391 if (strncmp("Dione", pname, 5) == 0)
392 {
393 ss_central_body = 18;
394 getConstDione();
395 };
396
397 if (strncmp("User", pname, 4) == 0)
398 {
399 if (ss_user_active)
400 {
401 ss_central_body = -1;
402 getConstUser();
403 };
404 };
405
406 ss_update_called = false;
407 ss_moon_called = false;
408 ss_planmat_called = false;
409 ss_kepler_called = false;
410
411 }
412
includeUser(bool uact)413 void SolarSystem::includeUser(bool uact)
414 {
415 // set user defined object active if possible
416 if(ss_user_stored) ss_user_active = uact;
417
418 ss_update_called = false;
419
420 }
421
updateSolar()422 void SolarSystem::updateSolar()
423 {
424 // calculate all positions in mean ecliptic of epoch
425
426 const double ae = 23454.77992; // 149597870.0/6378.14 = 1AE -> Earth Radii
427 double dt, eps2;
428 Sun200 sun;
429 Moon200 moon;
430 Plan200 pln;
431 Vec3 coff, r1, v1;
432 Mat3 pmx;
433
434 ss_update_called = true;
435
436 // get positions in ecliptic coordinates of date
437 dt = ss_time + ss_del_tdut/86400.0;
438 dt = julcent (dt);
439 ss_rs = sun.position(dt);
440 ss_rm = moon.position(dt)/ae;
441 ss_pmer = pln.Mercury(dt);
442 ss_pven = pln.Venus(dt);
443 ss_pearth[0] = -ss_rs[0];
444 ss_pearth[1] = -ss_rs[1];
445 ss_pearth[2] = -ss_rs[2];
446 ss_pmars = pln.Mars(dt);
447 ss_pjup = pln.Jupiter(dt);
448 ss_psat = pln.Saturn(dt);
449 ss_pura = pln.Uranus(dt);
450 ss_pnept = pln.Neptune(dt);
451 ss_pio = PosJIo(dt) + ss_pjup;
452 ss_peuropa = PosEuropa(dt) + ss_pjup;
453 ss_pganymede = PosGanymede(dt) + ss_pjup;
454 ss_pcallisto = PosCallisto(dt) + ss_pjup;
455 SatRhea (dt, r1, v1);
456 ss_prhea = r1 + ss_psat;
457 SatTitan (dt, r1, v1);
458 ss_ptitan = r1 + ss_psat;
459 ss_pmimas = PosSMimas(dt) + ss_psat;
460 ss_penceladus = PosSEnceladus(dt) + ss_psat;
461 ss_pdione = PosSDione(dt) + ss_psat;
462 if (ss_user_active) ss_user = PosUser(dt);
463
464 // refer to selected central body
465 coff[0] = 0;
466 coff[1] = 0;
467 coff[2] = 0;
468
469 if (ss_central_body == 2) coff -= ss_pmer;
470 if (ss_central_body == 3) coff -= ss_pven;
471 if (ss_central_body == 4) coff -= ss_pearth;
472 if (ss_central_body == 5) coff -= ss_pmars;
473 if (ss_central_body == 6) coff -= ss_pjup;
474 if (ss_central_body == 7) coff -= ss_psat;
475 if (ss_central_body == 8) coff -= ss_pura;
476 if (ss_central_body == 9) coff -= ss_pnept;
477 if (ss_central_body == 10) coff -= ss_pio;
478 if (ss_central_body == 11) coff -= ss_peuropa;
479 if (ss_central_body == 12) coff -= ss_pganymede;
480 if (ss_central_body == 13) coff -= ss_pcallisto;
481 if (ss_central_body == 14) coff -= ss_prhea;
482 if (ss_central_body == 15) coff -= ss_ptitan;
483 if (ss_central_body == 16) coff -= ss_pmimas;
484 if (ss_central_body == 17) coff -= ss_penceladus;
485 if (ss_central_body == 18) coff -= ss_pdione;
486 if (ss_central_body == -1) coff -= ss_user;
487 if (ss_central_body == 1) coff = coff + ss_rs - ss_rm;
488
489 ss_pmer += coff;
490 ss_pven += coff;
491 ss_pearth += coff;
492 ss_pmars += coff;
493 ss_pjup += coff;
494 ss_psat += coff;
495 ss_pura += coff;
496 ss_pnept += coff;
497 ss_pio += coff;
498 ss_peuropa += coff;
499 ss_pganymede += coff;
500 ss_pcallisto += coff;
501 ss_prhea += coff;
502 ss_ptitan += coff;
503 ss_pmimas += coff;
504 ss_penceladus += coff;
505 ss_pdione += coff;
506 if (ss_user_active) ss_user += coff;
507
508 ss_rs[0] = coff[0];
509 ss_rs[1] = coff[1];
510 ss_rs[2] = coff[2];
511
512 // convert into equatorial
513 ss_rs = eclequ(dt, ss_rs);
514 ss_rm = eclequ(dt, ss_rm);
515 ss_pmer = eclequ(dt, ss_pmer);
516 ss_pven = eclequ(dt, ss_pven);
517 ss_pearth = eclequ(dt, ss_pearth);
518 ss_pmars = eclequ(dt, ss_pmars);
519 ss_pjup = eclequ(dt, ss_pjup);
520 ss_psat = eclequ(dt, ss_psat);
521 ss_pura = eclequ(dt, ss_pura);
522 ss_pnept = eclequ(dt, ss_pnept);
523 ss_pio = eclequ(dt, ss_pio);
524 ss_peuropa = eclequ(dt, ss_peuropa);
525 ss_pganymede = eclequ(dt, ss_pganymede);
526 ss_pcallisto = eclequ(dt, ss_pcallisto);
527 ss_prhea = eclequ(dt, ss_prhea);
528 ss_ptitan = eclequ(dt, ss_ptitan);
529 ss_pmimas = eclequ(dt, ss_pmimas);
530 ss_penceladus = eclequ(dt, ss_penceladus);
531 ss_pdione = eclequ(dt, ss_pdione);
532 if (ss_user_active) ss_user = eclequ(dt, ss_user);
533
534 // correct for precession
535 if (ss_epoch != 0)
536 {
537 eps2 = julcent(ss_epoch);
538 pmx = pmatequ(dt, eps2);
539 ss_rs = mxvct(pmx,ss_rs);
540 ss_rm = mxvct(pmx,ss_rm);
541 ss_pmer = mxvct(pmx,ss_pmer);
542 ss_pven = mxvct(pmx,ss_pven);
543 ss_pearth = mxvct(pmx,ss_pearth);
544 ss_pmars = mxvct(pmx,ss_pmars);
545 ss_pjup = mxvct(pmx,ss_pjup);
546 ss_psat = mxvct(pmx,ss_psat);
547 ss_pura = mxvct(pmx,ss_pura);
548 ss_pnept = mxvct(pmx,ss_pnept);
549 ss_pio = mxvct(pmx,ss_pio);
550 ss_peuropa = mxvct(pmx,ss_peuropa);
551 ss_pganymede = mxvct(pmx,ss_pganymede);
552 ss_pcallisto = mxvct(pmx,ss_pcallisto);
553 ss_prhea = mxvct(pmx,ss_prhea);
554 ss_ptitan = mxvct(pmx,ss_ptitan);
555 ss_pmimas = mxvct(pmx,ss_pmimas);
556 ss_penceladus = mxvct(pmx,ss_penceladus);
557 ss_pdione = mxvct(pmx,ss_pdione);
558 if (ss_user_active) ss_user = mxvct(pmx, ss_user);
559 };
560
561 // correct for nutation
562 if (ss_nutation)
563 {
564 pmx = nutmat(dt, eps2, false);
565 ss_rs = mxvct(pmx,ss_rs);
566 ss_rm = mxvct(pmx,ss_rm);
567 ss_pmer = mxvct(pmx,ss_pmer);
568 ss_pven = mxvct(pmx,ss_pven);
569 ss_pearth = mxvct(pmx,ss_pearth);
570 ss_pmars = mxvct(pmx,ss_pmars);
571 ss_pjup = mxvct(pmx,ss_pjup);
572 ss_psat = mxvct(pmx,ss_psat);
573 ss_pura = mxvct(pmx,ss_pura);
574 ss_pnept = mxvct(pmx,ss_pnept);
575 ss_pio = mxvct(pmx,ss_pio);
576 ss_peuropa = mxvct(pmx,ss_peuropa);
577 ss_pganymede = mxvct(pmx,ss_pganymede);
578 ss_pcallisto = mxvct(pmx,ss_pcallisto);
579 ss_prhea = mxvct(pmx,ss_prhea);
580 ss_ptitan = mxvct(pmx,ss_ptitan);
581 ss_pmimas = mxvct(pmx,ss_pmimas);
582 ss_penceladus = mxvct(pmx,ss_penceladus);
583 ss_pdione = mxvct(pmx,ss_pdione);
584 if (ss_user_active) ss_user = mxvct(pmx, ss_user);
585 };
586 }
587
getRaDec(const Vec3 & r1,double & ra,double & decl)588 void SolarSystem::getRaDec(const Vec3& r1, double& ra, double& decl)
589 {
590 // convert equatorial vector r1 into RA and DEC (in HH.MMSS and DD.MMSS)
591
592 double const degrad = M_PI / 180.0;
593 Vec3 r2;
594
595 r2 = carpol(r1);
596 decl = r2[2] / degrad;
597 ra = r2[1] / degrad;
598 ra /= 15.0;
599 if (ra < 0) ra += 24.0;
600
601 decl = DegFDms(decl);
602 ra = DegFDms(ra);
603
604 }
605
getSun(double & ra,double & decl)606 void SolarSystem::getSun (double& ra, double& decl) // RA and Dec for the Sun
607 {
608 if (!ss_update_called) updateSolar();
609 if (ss_central_body == 0)
610 {
611 ra = -100.0;
612 decl = 0;
613 }
614 else getRaDec (ss_rs, ra, decl);
615 }
616
getMoon(double & ra,double & decl)617 void SolarSystem::getMoon (double& ra, double& decl) // RA and Dec for the Moon
618 {
619 if (!ss_update_called) updateSolar();
620 if (ss_central_body != 4)
621 {
622 ra = -100.0;
623 decl = 0;
624 }
625 else getRaDec (ss_rm, ra, decl);
626 }
627
getMercury(double & ra,double & decl)628 void SolarSystem::getMercury (double& ra, double& decl) // RA and Dec for Mercury
629 {
630 if (!ss_update_called) updateSolar();
631 if (ss_central_body == 2)
632 {
633 ra = -100.0;
634 decl = 0;
635 }
636 else getRaDec (ss_pmer, ra, decl);
637 }
638
getVenus(double & ra,double & decl)639 void SolarSystem::getVenus (double& ra, double& decl) // RA and Dec for Venus
640 {
641 if (!ss_update_called) updateSolar();
642 if (ss_central_body == 3)
643 {
644 ra = -100.0;
645 decl = 0;
646 }
647 else getRaDec (ss_pven, ra, decl);
648 }
649
getEarth(double & ra,double & decl)650 void SolarSystem::getEarth (double& ra, double& decl) // RA and Dec for Earth
651 {
652 if (!ss_update_called) updateSolar();
653 if (ss_central_body == 4)
654 {
655 ra = -100.0;
656 decl = 0;
657 }
658 else getRaDec (ss_pearth, ra, decl);
659 }
660
getMars(double & ra,double & decl)661 void SolarSystem::getMars (double& ra, double& decl) // RA and Dec for Mars
662 {
663 if (!ss_update_called) updateSolar();
664 if (ss_central_body == 5)
665 {
666 ra = -100.0;
667 decl = 0;
668 }
669 else getRaDec (ss_pmars, ra, decl);
670 }
671
getJupiter(double & ra,double & decl)672 void SolarSystem::getJupiter (double& ra, double& decl) // RA and Dec for Jupiter
673 {
674 if (!ss_update_called) updateSolar();
675 if (ss_central_body == 6)
676 {
677 ra = -100.0;
678 decl = 0;
679 }
680 else getRaDec (ss_pjup, ra, decl);
681 }
682
getSaturn(double & ra,double & decl)683 void SolarSystem::getSaturn (double& ra, double& decl) // RA and Dec for Saturn
684 {
685 if (!ss_update_called) updateSolar();
686 if (ss_central_body == 7)
687 {
688 ra = -100.0;
689 decl = 0;
690 }
691 else getRaDec (ss_psat, ra, decl);
692 }
693
getUranus(double & ra,double & decl)694 void SolarSystem::getUranus (double& ra, double& decl) // RA and Dec for Uranus
695 {
696 if (!ss_update_called) updateSolar();
697 if (ss_central_body == 8)
698 {
699 ra = -100.0;
700 decl = 0;
701 }
702 else getRaDec (ss_pura, ra, decl);
703 }
704
getNeptune(double & ra,double & decl)705 void SolarSystem::getNeptune (double& ra, double& decl) // RA and Dec for Neptune
706 {
707 if (!ss_update_called) updateSolar();
708 if (ss_central_body == 9)
709 {
710 ra = -100.0;
711 decl = 0;
712 }
713 else getRaDec (ss_pnept, ra, decl);
714 }
715
getIo(double & ra,double & decl)716 void SolarSystem::getIo (double& ra, double& decl) // RA and Dec for Io
717 {
718 if (!ss_update_called) updateSolar();
719 if (ss_central_body == 10)
720 {
721 ra = -100.0;
722 decl = 0;
723 }
724 else getRaDec (ss_pio, ra, decl);
725 }
726
getEuropa(double & ra,double & decl)727 void SolarSystem::getEuropa (double& ra, double& decl) // RA and Dec for Europa
728 {
729 if (!ss_update_called) updateSolar();
730 if (ss_central_body == 11)
731 {
732 ra = -100.0;
733 decl = 0;
734 }
735 else getRaDec (ss_peuropa, ra, decl);
736 }
737
getGanymede(double & ra,double & decl)738 void SolarSystem::getGanymede (double& ra, double& decl) // RA and Dec for Ganymede
739 {
740 if (!ss_update_called) updateSolar();
741 if (ss_central_body == 12)
742 {
743 ra = -100.0;
744 decl = 0;
745 }
746 else getRaDec (ss_pganymede, ra, decl);
747 }
748
getCallisto(double & ra,double & decl)749 void SolarSystem::getCallisto (double& ra, double& decl) // RA and Dec for Callisto
750 {
751 if (!ss_update_called) updateSolar();
752 if (ss_central_body == 13)
753 {
754 ra = -100.0;
755 decl = 0;
756 }
757 else getRaDec (ss_pcallisto, ra, decl);
758 }
759
getRhea(double & ra,double & decl)760 void SolarSystem::getRhea (double& ra, double& decl) // RA and Dec for Rhea
761 {
762 if (!ss_update_called) updateSolar();
763 if (ss_central_body == 14)
764 {
765 ra = -100.0;
766 decl = 0;
767 }
768 else getRaDec (ss_prhea, ra, decl);
769 }
770
getTitan(double & ra,double & decl)771 void SolarSystem::getTitan (double& ra, double& decl) // RA and Dec for Titan
772 {
773 if (!ss_update_called) updateSolar();
774 if (ss_central_body == 15)
775 {
776 ra = -100.0;
777 decl = 0;
778 }
779 else getRaDec (ss_ptitan, ra, decl);
780 }
781
getMimas(double & ra,double & decl)782 void SolarSystem::getMimas (double& ra, double& decl) // RA and Dec for Mimas
783 {
784 if (!ss_update_called) updateSolar();
785 if (ss_central_body == 16)
786 {
787 ra = -100.0;
788 decl = 0;
789 }
790 else getRaDec (ss_pmimas, ra, decl);
791 }
792
getEnceladus(double & ra,double & decl)793 void SolarSystem::getEnceladus (double& ra, double& decl) // RA and Dec for Enceladus
794 {
795 if (!ss_update_called) updateSolar();
796 if (ss_central_body == 17)
797 {
798 ra = -100.0;
799 decl = 0;
800 }
801 else getRaDec (ss_penceladus, ra, decl);
802 }
803
getDione(double & ra,double & decl)804 void SolarSystem::getDione (double& ra, double& decl) // RA and Dec for Dione
805 {
806 if (!ss_update_called) updateSolar();
807 if (ss_central_body == 18)
808 {
809 ra = -100.0;
810 decl = 0;
811 }
812 else getRaDec (ss_pdione, ra, decl);
813 }
814
getUser(double & ra,double & decl)815 void SolarSystem::getUser (double& ra, double& decl) // RA and Dec for User
816 {
817 if (!ss_update_called) updateSolar();
818 if (ss_central_body == -1)
819 {
820 ra = -100.0;
821 decl = 0;
822 }
823 else getRaDec (ss_user, ra, decl);
824
825 }
826
getPhysSun(double & pdiam,double & pmag)827 void SolarSystem::getPhysSun (double &pdiam, double &pmag)
828 {
829 // Apparent diameter for the Sun in radians
830
831 if (ss_central_body == 0)
832 {
833 pdiam = 0;
834 pmag = 0;
835
836 return;
837 };
838 if (!ss_update_called) updateSolar();
839
840 pdiam = 0.00930495 / abs(ss_rs);
841 pmag = -26.7 + 5.0 * log10(abs(ss_rs));
842 }
843
getPhysMercury(double & pdiam,double & pmag,double & pphase)844 void SolarSystem::getPhysMercury(double &pdiam, double &pmag, double &pphase)
845 {
846 // Physical elements Mercury
847
848 double ia, cp, cs, ps;
849
850 if (ss_central_body == 2)
851 {
852 pdiam = 0;
853 pmag = 0;
854 pphase = 0;
855
856 return;
857 };
858
859 if (!ss_update_called) updateSolar();
860
861 cp = abs(ss_pmer);
862 cs = abs(ss_rs);
863 ps = abs(ss_rs - ss_pmer);
864
865 pdiam = 3.24831e-05 / cp; // apparent diameter in radians
866
867 ia = 2.0 * cp * ps;
868 if (ia == 0) ia = 1.0; // this should never happen
869
870 ia = (cp*cp + ps*ps - cs*cs) / ia; // cos of phase angle
871
872 pphase = 0.5 * (1.0 + ia);
873
874 ia = acos(ia) / degrad;
875 ia /= 100.0;
876 pmag = -0.36 + 3.80*ia - 2.73*ia*ia + 2.00*ia*ia*ia;
877 pmag = pmag + 5.0 * log10(ps * cp);
878 }
879
getPhysVenus(double & pdiam,double & pmag,double & pphase)880 void SolarSystem::getPhysVenus(double &pdiam, double &pmag, double &pphase)
881 {
882 // Physical elements Venus
883
884 double ia, cp, cs, ps;
885
886 if (ss_central_body == 3)
887 {
888 pdiam = 0;
889 pmag = 0;
890 pphase = 0;
891
892 return;
893 };
894
895 if (!ss_update_called) updateSolar();
896
897 cp = abs(ss_pven);
898 cs = abs(ss_rs);
899 ps = abs(ss_rs - ss_pven);
900
901 pdiam = 8.09089e-05 / cp; // apparent diameter in radians
902
903 ia = 2.0 * cp * ps;
904 if (ia == 0) ia = 1.0; // this should never happen
905
906 ia = (cp*cp + ps*ps - cs*cs) / ia; // cos of phase angle
907
908 pphase = 0.5 * (1.0 + ia);
909
910 ia = acos(ia) / degrad;
911 ia /= 100.0;
912 pmag = -4.29 + 0.09*ia + 2.39*ia*ia - 0.65*ia*ia*ia;
913 pmag = pmag + 5.0 * log10(ps * cp);
914 }
915
getPhysEarth(double & pdiam,double & pmag,double & pphase)916 void SolarSystem::getPhysEarth(double &pdiam, double &pmag, double &pphase)
917 {
918 // Physical elements Earth
919
920 double ia, cp, cs, ps;
921
922 if (ss_central_body == 4)
923 {
924 pdiam = 0;
925 pmag = 0;
926 pphase = 0;
927
928 return;
929 };
930
931 if (!ss_update_called) updateSolar();
932
933 cp = abs(ss_pearth);
934 cs = abs(ss_rs);
935 ps = abs(ss_rs - ss_pearth);
936
937 pdiam = 8.52705e-05 / cp; // apparent diameter in radians
938
939 ia = 2.0 * cp * ps;
940 if (ia == 0) ia = 1.0; // this should never happen
941
942 ia = (cp*cp + ps*ps - cs*cs) / ia; // cos of phase angle
943
944 pphase = 0.5 * (1.0 + ia);
945
946 ia = acos(ia) / degrad;
947 ia /= 100.0;
948 pmag = -4.0 + 0.09*ia + 2.39*ia*ia - 0.65*ia*ia*ia;
949 pmag = pmag + 5.0 * log10(ps * cp);
950 }
951
getPhysMars(double & pdiam,double & pmag,double & pphase)952 void SolarSystem::getPhysMars(double &pdiam, double &pmag, double &pphase)
953 {
954 // Physical elements Mars
955
956 double ia, cp, cs, ps;
957
958 if (ss_central_body == 5)
959 {
960 pdiam = 0;
961 pmag = 0;
962 pphase = 0;
963
964 return;
965 };
966
967 if (!ss_update_called) updateSolar();
968
969 cp = abs(ss_pmars);
970 cs = abs(ss_rs);
971 ps = abs(ss_rs - ss_pmars);
972
973 pdiam = 4.54178e-05 / cp; // apparent diameter in radians
974
975 ia = 2.0 * cp * ps;
976 if (ia == 0) ia = 1.0; // this should never happen
977
978 ia = (cp*cp + ps*ps - cs*cs) / ia; // cos of phase angle
979
980 pphase = 0.5 * (1.0 + ia);
981
982 ia = acos(ia) / degrad;
983 if (ia > 39.0) ia = 39.0; // limit to max angle for Mars from Earth
984 pmag = -1.52 + 0.016*ia;
985 pmag = pmag + 5.0 * log10(ps * cp);
986 }
987
getPhysJupiter(double & pdiam,double & pmag,double & pphase)988 void SolarSystem::getPhysJupiter(double &pdiam, double &pmag, double &pphase)
989 {
990 // Physical elements Jupiter
991
992 double ia, cp, cs, ps;
993
994 if (ss_central_body == 6)
995 {
996 pdiam = 0;
997 pmag = 0;
998 pphase = 0;
999
1000 return;
1001 };
1002
1003 if (!ss_update_called) updateSolar();
1004
1005 cp = abs(ss_pjup);
1006 cs = abs(ss_rs);
1007 ps = abs(ss_rs - ss_pjup);
1008
1009 pdiam = 0.000955789 / cp; // apparent diameter in radians
1010
1011 ia = 2.0 * cp * ps;
1012 if (ia == 0) ia = 1.0; // this should never happen
1013
1014 ia = (cp*cp + ps*ps - cs*cs) / ia; // cos of phase angle
1015
1016 pphase = 0.5 * (1.0 + ia);
1017
1018 ia = acos(ia) / degrad;
1019 if (ia > 11.3) ia = 11.3; // limit to max angle for Jupiter from Earth
1020 pmag = -9.25 + 0.005*ia;
1021 pmag = pmag + 5.0 * log10(ps * cp);
1022 }
1023
getPhysSaturn(double & pdiam,double & pmag,double & pphase)1024 void SolarSystem::getPhysSaturn(double &pdiam, double &pmag, double &pphase)
1025 {
1026 // Physical elements Saturn
1027
1028 double ia, cp, cs, ps;
1029
1030 if (ss_central_body == 7)
1031 {
1032 pdiam = 0;
1033 pmag = 0;
1034 pphase = 0;
1035
1036 return;
1037 };
1038
1039 if (!ss_update_called) updateSolar();
1040
1041 cp = abs(ss_psat);
1042 cs = abs(ss_rs);
1043 ps = abs(ss_rs - ss_psat);
1044
1045 pdiam = 0.000805733 / cp; // apparent diameter in radians
1046
1047 ia = 2.0 * cp * ps;
1048 if (ia == 0) ia = 1.0; // this should never happen
1049
1050 ia = (cp*cp + ps*ps - cs*cs) / ia; // cos of phase angle
1051
1052 pphase = 0.5 * (1.0 + ia);
1053
1054 // ia = acos(ia) / degrad;
1055 // pmag = -7.19 + 0.044*ia;
1056 pmag = -10.0;
1057 pmag = pmag + 5.0 * log10(ps * cp);
1058 }
1059
getPhysUranus(double & pdiam,double & pmag,double & pphase)1060 void SolarSystem::getPhysUranus(double &pdiam, double &pmag, double &pphase)
1061 {
1062 // Physical elements Uranus
1063
1064 double ia, cp, cs, ps;
1065
1066 if (ss_central_body == 8)
1067 {
1068 pdiam = 0;
1069 pmag = 0;
1070 pphase = 0;
1071
1072 return;
1073 };
1074
1075 if (!ss_update_called) updateSolar();
1076
1077 cp = abs(ss_pura);
1078 cs = abs(ss_rs);
1079 ps = abs(ss_rs - ss_pura);
1080
1081 pdiam = 0.000341703 / cp; // apparent diameter in radians
1082
1083 ia = 2.0 * cp * ps;
1084 if (ia == 0) ia = 1.0; // this should never happen
1085
1086 ia = (cp*cp + ps*ps - cs*cs) / ia; // cos of phase angle
1087
1088 pphase = 0.5 * (1.0 + ia);
1089
1090 ia = acos(ia) / degrad;
1091 if (ia > 3.0) ia = 3.0; // limit to max angle for Uranus from Earth
1092 pmag = -7.19 + 0.0228*ia;
1093 pmag = pmag + 5.0 * log10(ps * cp);
1094 }
1095
getPhysNeptune(double & pdiam,double & pmag,double & pphase)1096 void SolarSystem::getPhysNeptune(double &pdiam, double &pmag, double &pphase)
1097 {
1098 // Physical elements Neptune
1099
1100 double ia, cp, cs, ps;
1101
1102 if (ss_central_body == 9)
1103 {
1104 pdiam = 0;
1105 pmag = 0;
1106 pphase = 0;
1107
1108 return;
1109 };
1110
1111 if (!ss_update_called) updateSolar();
1112
1113 cp = abs(ss_pnept);
1114 cs = abs(ss_rs);
1115 ps = abs(ss_rs - ss_pnept);
1116
1117 pdiam = 0.000331074 / cp; // apparent diameter in radians
1118
1119 ia = 2.0 * cp * ps;
1120 if (ia == 0) ia = 1.0; // this should never happen
1121
1122 ia = (cp*cp + ps*ps - cs*cs) / ia; // cos of phase angle
1123
1124 pphase = 0.5 * (1.0 + ia);
1125
1126 pmag = -6.87;
1127 pmag = pmag + 5.0 * log10(ps * cp);
1128 }
1129
getPhysIo(double & pdiam,double & pmag,double & pphase)1130 void SolarSystem::getPhysIo(double &pdiam, double &pmag, double &pphase)
1131 {
1132 // Physical elements Io
1133
1134 double ia, cp, cs, ps;
1135
1136 if (ss_central_body == 10)
1137 {
1138 pdiam = 0;
1139 pmag = 0;
1140 pphase = 0;
1141
1142 return;
1143 };
1144
1145 if (!ss_update_called) updateSolar();
1146
1147 cp = abs(ss_pio);
1148 cs = abs(ss_rs);
1149 ps = abs(ss_rs - ss_pio);
1150
1151 pdiam = 2.42651e-05 / cp; // apparent diameter in radians
1152
1153 ia = 2.0 * cp * ps;
1154 if (ia == 0) ia = 1.0; // this should never happen
1155
1156 ia = (cp*cp + ps*ps - cs*cs) / ia; // cos of phase angle
1157
1158 pphase = 0.5 * (1.0 + ia);
1159
1160 ia = acos(ia) / degrad;
1161 if (ia > 11.3) ia = 11.3; // limit to max angle for Jupiter from Earth
1162 pmag = -1.68 + 0.046*ia - 0.0010*ia*ia;
1163 pmag = pmag + 5.0 * log10(ps * cp);
1164 }
1165
getPhysEuropa(double & pdiam,double & pmag,double & pphase)1166 void SolarSystem::getPhysEuropa(double &pdiam, double &pmag, double &pphase)
1167 {
1168 // Physical elements Europa
1169
1170 double ia, cp, cs, ps;
1171
1172 if (ss_central_body == 11)
1173 {
1174 pdiam = 0;
1175 pmag = 0;
1176 pphase = 0;
1177
1178 return;
1179 };
1180
1181 if (!ss_update_called) updateSolar();
1182
1183 cp = abs(ss_peuropa);
1184 cs = abs(ss_rs);
1185 ps = abs(ss_rs - ss_peuropa);
1186
1187 pdiam = 2.09762e-05 / cp; // apparent diameter in radians
1188
1189 ia = 2.0 * cp * ps;
1190 if (ia == 0) ia = 1.0; // this should never happen
1191
1192 ia = (cp*cp + ps*ps - cs*cs) / ia; // cos of phase angle
1193
1194 pphase = 0.5 * (1.0 + ia);
1195
1196 ia = acos(ia) / degrad;
1197 if (ia > 11.3) ia = 11.3; // limit to max angle for Jupiter from Earth
1198 pmag = -1.41 + 0.0312*ia - 0.00125*ia*ia;
1199 pmag = pmag + 5.0 * log10(ps * cp);
1200 }
1201
getPhysGanymede(double & pdiam,double & pmag,double & pphase)1202 void SolarSystem::getPhysGanymede(double &pdiam, double &pmag, double &pphase)
1203 {
1204 // Physical elements Ganymede
1205
1206 double ia, cp, cs, ps;
1207
1208 if (ss_central_body == 12)
1209 {
1210 pdiam = 0;
1211 pmag = 0;
1212 pphase = 0;
1213
1214 return;
1215 };
1216
1217 if (!ss_update_called) updateSolar();
1218
1219 cp = abs(ss_pganymede);
1220 cs = abs(ss_rs);
1221 ps = abs(ss_rs - ss_pganymede);
1222
1223 pdiam = 3.51743e-05 / cp; // apparent diameter in radians
1224
1225 ia = 2.0 * cp * ps;
1226 if (ia == 0) ia = 1.0; // this should never happen
1227
1228 ia = (cp*cp + ps*ps - cs*cs) / ia; // cos of phase angle
1229
1230 pphase = 0.5 * (1.0 + ia);
1231
1232 ia = acos(ia) / degrad;
1233 if (ia > 11.3) ia = 11.3; // limit to max angle for Jupiter from Earth
1234 pmag = -2.09 + 0.0323*ia - 0.00066*ia*ia;
1235 pmag = pmag + 5.0 * log10(ps * cp);
1236 }
1237
getPhysCallisto(double & pdiam,double & pmag,double & pphase)1238 void SolarSystem::getPhysCallisto(double &pdiam, double &pmag, double &pphase)
1239 {
1240 // Physical elements Callisto
1241
1242 double ia, cp, cs, ps;
1243
1244 if (ss_central_body == 13)
1245 {
1246 pdiam = 0;
1247 pmag = 0;
1248 pphase = 0;
1249
1250 return;
1251 };
1252
1253 if (!ss_update_called) updateSolar();
1254
1255 cp = abs(ss_pcallisto);
1256 cs = abs(ss_rs);
1257 ps = abs(ss_rs - ss_pcallisto);
1258
1259 pdiam = 3.2086e-05 / cp; // apparent diameter in radians
1260
1261 ia = 2.0 * cp * ps;
1262 if (ia == 0) ia = 1.0; // this should never happen
1263
1264 ia = (cp*cp + ps*ps - cs*cs) / ia; // cos of phase angle
1265
1266 pphase = 0.5 * (1.0 + ia);
1267
1268 ia = acos(ia) / degrad;
1269 if (ia > 11.3) ia = 11.3; // limit to max angle for Jupiter from Earth
1270 pmag = -1.05 + 0.078*ia - 0.00274*ia*ia;
1271 pmag = pmag + 5.0 * log10(ps * cp);
1272 }
1273
getPhysRhea(double & pdiam,double & pmag,double & pphase)1274 void SolarSystem::getPhysRhea(double &pdiam, double &pmag, double &pphase)
1275 {
1276 // Physical elements Rhea
1277
1278 double ia, cp, cs, ps;
1279
1280 if (ss_central_body == 14)
1281 {
1282 pdiam = 0;
1283 pmag = 0;
1284 pphase = 0;
1285
1286 return;
1287 };
1288
1289 if (!ss_update_called) updateSolar();
1290
1291 cp = abs(ss_prhea);
1292 cs = abs(ss_rs);
1293 ps = abs(ss_rs - ss_prhea);
1294
1295 pdiam = 1.02274e-05 / cp; // apparent diameter in radians
1296
1297 ia = 2.0 * cp * ps;
1298 if (ia == 0) ia = 1.0; // this should never happen
1299
1300 ia = (cp*cp + ps*ps - cs*cs) / ia; // cos of phase angle
1301
1302 pphase = 0.5 * (1.0 + ia);
1303
1304 pmag = 0.1;
1305 pmag = pmag + 5.0 * log10(ps * cp);
1306 }
1307
getPhysTitan(double & pdiam,double & pmag,double & pphase)1308 void SolarSystem::getPhysTitan(double &pdiam, double &pmag, double &pphase)
1309 {
1310 // Physical elements Titan
1311
1312 double ia, cp, cs, ps;
1313
1314 if (ss_central_body == 15)
1315 {
1316 pdiam = 0;
1317 pmag = 0;
1318 pphase = 0;
1319
1320 return;
1321 };
1322
1323 if (!ss_update_called) updateSolar();
1324
1325 cp = abs(ss_ptitan);
1326 cs = abs(ss_rs);
1327 ps = abs(ss_rs - ss_ptitan);
1328
1329 pdiam = 3.44256e-05 / cp; // apparent diameter in radians
1330
1331 ia = 2.0 * cp * ps;
1332 if (ia == 0) ia = 1.0; // this should never happen
1333
1334 ia = (cp*cp + ps*ps - cs*cs) / ia; // cos of phase angle
1335
1336 pphase = 0.5 * (1.0 + ia);
1337
1338 pmag = -1.28;
1339 pmag = pmag + 5.0 * log10(ps * cp);
1340 }
1341
getPhysMimas(double & pdiam,double & pmag,double & pphase)1342 void SolarSystem::getPhysMimas(double &pdiam, double &pmag, double &pphase)
1343 {
1344 // Physical elements Mimas
1345
1346 double ia, cp, cs, ps;
1347
1348 if (ss_central_body == 16)
1349 {
1350 pdiam = 0;
1351 pmag = 0;
1352 pphase = 0;
1353
1354 return;
1355 };
1356
1357 if (!ss_update_called) updateSolar();
1358
1359 cp = abs(ss_pmimas);
1360 cs = abs(ss_rs);
1361 ps = abs(ss_rs - ss_pmimas);
1362
1363 pdiam = 2.62036e-06 / cp; // apparent diameter in radians
1364
1365 ia = 2.0 * cp * ps;
1366 if (ia == 0) ia = 1.0; // this should never happen
1367
1368 ia = (cp*cp + ps*ps - cs*cs) / ia; // cos of phase angle
1369
1370 pphase = 0.5 * (1.0 + ia);
1371
1372 pmag = 3.3;
1373 pmag = pmag + 5.0 * log10(ps * cp);
1374 }
1375
getPhysEnceladus(double & pdiam,double & pmag,double & pphase)1376 void SolarSystem::getPhysEnceladus(double &pdiam, double &pmag, double &pphase)
1377 {
1378 // Physical elements Enceladus
1379
1380 double ia, cp, cs, ps;
1381
1382 if (ss_central_body == 17)
1383 {
1384 pdiam = 0;
1385 pmag = 0;
1386 pphase = 0;
1387
1388 return;
1389 };
1390
1391 if (!ss_update_called) updateSolar();
1392
1393 cp = abs(ss_penceladus);
1394 cs = abs(ss_rs);
1395 ps = abs(ss_rs - ss_penceladus);
1396
1397 pdiam = 3.34229e-06 / cp; // apparent diameter in radians
1398
1399 ia = 2.0 * cp * ps;
1400 if (ia == 0) ia = 1.0; // this should never happen
1401
1402 ia = (cp*cp + ps*ps - cs*cs) / ia; // cos of phase angle
1403
1404 pphase = 0.5 * (1.0 + ia);
1405
1406 pmag = 2.1;
1407 pmag = pmag + 5.0 * log10(ps * cp);
1408 }
1409
getPhysDione(double & pdiam,double & pmag,double & pphase)1410 void SolarSystem::getPhysDione(double &pdiam, double &pmag, double &pphase)
1411 {
1412 // Physical elements Dione
1413
1414 double ia, cp, cs, ps;
1415
1416 if (ss_central_body == 18)
1417 {
1418 pdiam = 0;
1419 pmag = 0;
1420 pphase = 0;
1421
1422 return;
1423 };
1424
1425 if (!ss_update_called) updateSolar();
1426
1427 cp = abs(ss_pdione);
1428 cs = abs(ss_rs);
1429 ps = abs(ss_rs - ss_pdione);
1430
1431 pdiam = 7.48674e-06 / cp; // apparent diameter in radians
1432
1433 ia = 2.0 * cp * ps;
1434 if (ia == 0) ia = 1.0; // this should never happen
1435
1436 ia = (cp*cp + ps*ps - cs*cs) / ia; // cos of phase angle
1437
1438 pphase = 0.5 * (1.0 + ia);
1439
1440 pmag = 0.8;
1441 pmag = pmag + 5.0 * log10(ps * cp);
1442 }
1443
getPhysUser(double & pdiam,double & pmag,double & pphase)1444 void SolarSystem::getPhysUser(double &pdiam, double &pmag, double &pphase)
1445 {
1446 // Physical elements user defined object
1447
1448 double ia, cp, cs, ps;
1449
1450 pdiam = 0;
1451 pmag = 0;
1452 pphase = 0;
1453
1454 if (!ss_user_active) return;
1455 if (ss_central_body == -1) return;
1456
1457 if (!ss_update_called) updateSolar();
1458
1459 cp = abs(ss_user);
1460 cs = abs(ss_rs);
1461 ps = abs(ss_rs - ss_user);
1462
1463 pdiam = 6.684587153547e-09 * ss_R0 / cp; // apparent diameter in radians
1464
1465 ia = 2.0 * cp * ps;
1466 if (ia == 0) ia = 1.0; // this should never happen
1467
1468 ia = (cp*cp + ps*ps - cs*cs) / ia; // cos of phase angle
1469
1470 pphase = 0.5 * (1.0 + ia);
1471
1472 pmag = getCometMag(6.0,4.0); // Just to have a value. This will usually be wrong!
1473 // pmag = pmag + 5.0 * log10(ps * cp);
1474
1475 }
1476
getDiamMoon()1477 double SolarSystem::getDiamMoon ()
1478 {
1479 // Apparent diameter for the Moon
1480
1481 if (ss_central_body == 1) return 0;
1482 if (!ss_update_called) updateSolar();
1483
1484 return 2.32356e-05 / abs(ss_rm);
1485 }
1486
getLunarLibration(double & lblon,double & lblat,double & termt)1487 void SolarSystem::getLunarLibration (double &lblon, double &lblat, double &termt)
1488 {
1489 // librations of the Moon and terminator position
1490 if (!ss_moon_called) MoonDetails();
1491
1492 lblon = ss_moon_lblon;
1493 lblat = ss_moon_lblat;
1494 termt = ss_moon_term;
1495 }
1496
getLunarPhase(double & phase,double & ildisk,double & amag)1497 void SolarSystem::getLunarPhase (double &phase, double &ildisk, double &amag)
1498 {
1499 // phase and mag of Moon
1500 if (!ss_moon_called) MoonDetails();
1501
1502 phase = ss_moon_phase;
1503 ildisk = ss_moon_ildisk;
1504 amag = ss_moon_mag;
1505 }
1506
SnPos(double & ep2,double & els)1507 Vec3 SolarSystem::SnPos (double &ep2, double &els)
1508 {
1509 // return the apparent position of the Sun
1510 // and the Nutation ep2 value and the ecliptic longitude of the Sun els
1511
1512 Sun200 sun;
1513 Mat3 mx;
1514 Vec3 rs, s;
1515 double t;
1516
1517 t = ss_time + ss_del_tdut/86400.0;
1518 t = julcent (t);
1519
1520 rs = sun.position(t);
1521 s = carpol(rs);
1522 els = s[1];
1523
1524 rs = eclequ(t,rs);
1525 mx = nutmat(t,ep2); // nutation
1526 rs = mxvct(mx,rs); // apparent coordinates
1527 rs = aberrat(t,rs);
1528
1529 return rs;
1530 }
1531
MnPos(double & ep2,double & elm)1532 Vec3 SolarSystem::MnPos (double &ep2, double &elm)
1533 {
1534 // return the apparent position of the Moon
1535 // and the Nutation ep2 value and the ecliptic longitude of the Moon elm
1536
1537 Moon200 moon;
1538 Mat3 mx;
1539 Vec3 rm, s;
1540 double t;
1541
1542 t = ss_time + ss_del_tdut/86400.0;
1543 t = julcent (t);
1544
1545 rm = moon.position(t);
1546 s = carpol(rm);
1547 elm = s[1];
1548
1549 rm = eclequ(t,rm);
1550 mx = nutmat(t,ep2); // nutation
1551 rm = mxvct(mx,rm);
1552
1553 return rm;
1554 }
1555
PosUser(double t)1556 Vec3 SolarSystem::PosUser (double t)
1557 {
1558 /* Ecliptic coordinates (in A.U.) of User defined object
1559 for Equinox of Date.
1560 t is the time in Julian centuries since J2000.
1561 ===================================================================*/
1562 // get the position of the object for which the Kepler elements had been stored
1563
1564 const double gs = 2.959122083e-4; // gravitation constant of the Sun in AU and d
1565 double dt;
1566 int day, month, year;
1567 double b, yr;
1568 Mat3 pmx;
1569 Vec3 r1, v1;
1570
1571 // calculate Kepler orbit
1572
1573 dt = ss_time + ss_del_tdut/86400.0;
1574
1575 kepler (gs, ss_user_t0, dt, ss_user_m0, ss_user_a, ss_user_ecc, ss_user_ran, ss_user_aper, ss_user_inc, r1, v1);
1576
1577 // correct for precession (into Mean of Date)
1578 yr = ss_user_eclep;
1579 if (yr != 0)
1580 {
1581 year = int(yr);
1582 b = 12.0 * (yr - double(year));
1583 month = int(b) + 1;
1584 day = 1;
1585
1586 b = mjd(day, month, year, 0);
1587 b = julcent(b);
1588
1589 pmx = pmatecl(b, t);
1590 r1 = mxvct(pmx,r1);
1591 };
1592
1593 return r1;
1594 }
1595
MoonLibr(double jd,Vec3 rm,Vec3 sn,double & lblon,double & lblat,double & termt)1596 void SolarSystem::MoonLibr (double jd, Vec3 rm, Vec3 sn,
1597 double &lblon, double &lblat, double &termt)
1598 {
1599 /* Calculate the librations angles lblon (longitude) and
1600 lblat (latitude) for the moon at position rs and time jd.
1601 Also calculate the selenographic longitude of the terminator.
1602 rm is the position of the Moon from Earth, sn the position
1603 of the Sun (also with respect to Earth).
1604 */
1605 double t, gam, gmp, l, omg, mln;
1606 double a, b, c, ic, gn, gp, omp;
1607 double const degrad = M_PI / 180.0;
1608 Vec3 v1;
1609 Mat3 m1, m2;
1610
1611 t = (jd - 15019.5) / 36525.0;
1612 gam = 281.2208333 + ((0.33333333e-5*t + 0.45277778e-3)*t + 1.7191750)*t;
1613 gmp = 334.3295556 + ((-0.125e-4*t - 0.10325e-1)*t + 4069.0340333)*t;
1614 l = 279.6966778 + (0.3025e-3*t + 36000.768925)*t;
1615 omg = 259.1832750 + ((0.22222222e-5*t + 0.20777778e-2)*t - 1934.1420083)*t;
1616 b = 23.45229444 + ((0.50277778e-6*t -0.16388889e-5)*t - 0.130125e-1)*t;
1617 mln = 270.4341639 + ((0.1888889e-5*t -0.11333e-2)*t + 481267.8831417)*t;
1618 ic = 1.535*degrad;
1619 gn = (l - gam)*degrad;
1620 gp = (mln - gmp)*degrad;
1621 omp = (gmp - omg)*degrad;
1622 a = -107.0*cos(gp) + 37.0*cos(gp+2.0*omp) -11.0*cos(2.0*(gp+omp));
1623 a = a*0.000277778*degrad + ic;
1624 c = (-109.0*sin(gp) + 37.0*sin(gp+2.0*omp) - 11.0*sin(2.0*(gp+omp)))/sin(ic);
1625 c = (c*0.000277778 + omg)*degrad;
1626 gn = -12.0*sin(gp) + 59.0*sin(gn) + 18.0*sin(2.0*omp);
1627 gn = gn*0.000277778*degrad; // tau
1628
1629 b *= degrad;
1630 gam = cos(a)*cos(b) + sin(a)*sin(b)*cos(c);
1631 gmp = gam*gam;
1632 if(gmp > 1.0) gmp = 0;
1633 else gmp = sqrt(1.0 - gmp);
1634 gam = atan23(gmp,gam); // theta
1635 t = cos(a)*sin(b) - sin(a)*sin(b)*cos(c);
1636 l = -sin(a)*sin(c);
1637
1638 gmp = atan23(l,t); // phi
1639 t = sin(a)*cos(b) - cos(a)*sin(b)*cos(c);
1640 l = -sin(b)*sin(c);
1641 a = atan23(l,t); // delta
1642 c = a + mln*degrad + gn - c; // psi
1643
1644 // libration rotation matrix from Mean equator to true selenographic
1645 m1 = zrot(gmp);
1646 m2 = xrot(gam);
1647 m1 = m2 * m1;
1648 m2 = zrot(c);
1649 m1 = m2 * m1;
1650
1651 // Earth coordinates
1652 v1[0] = -rm[0];
1653 v1[1] = -rm[1];
1654 v1[2] = -rm[2];
1655
1656 v1 = mxvct(m1,v1);
1657 v1 = carpol(v1);
1658 lblat = v1[2] / degrad;
1659 lblon = v1[1] / degrad;
1660 if (lblon > 180.0) lblon = lblon - 360.0;
1661
1662 // terminator
1663 v1 = mxvct(m1,sn);
1664 v1 = carpol(v1);
1665 termt = v1[1] / degrad;
1666 if (termt > 180.0) termt = termt - 360.0;
1667 termt -= 90.0;
1668 a = 90.0 + lblon;
1669 b = lblon - 90;
1670 if (termt > a) termt -= 180.0;
1671 else
1672 {
1673 if (termt < b) termt += 180;
1674 };
1675 }
1676
MoonDetails()1677 void SolarSystem::MoonDetails ()
1678 {
1679 // Calculate specific details about the Moon
1680 // Libration, Terminator position, Phase and Magnitude
1681
1682 double jd, t, lblon, lblat, termt, mnmag;
1683 double dist, ps;
1684 static double els, elm;
1685 double const degrad = M_PI / 180.0;
1686 double ae = 23454.77992; // 149597870.0/6378.14 = 1AE -> Earth Radii
1687 static Vec3 snc, mnc; // position of the Sun and the Moon
1688 Vec3 s, rm, rs, s3;
1689 double ep2; // correction for Apparent Sideral Time
1690
1691 if (ss_central_body != 4) // calculate only for the Earth as reference
1692 {
1693 ss_moon_ildisk = 0;
1694 ss_moon_phase = 0;
1695 ss_moon_lblon = 0;
1696 ss_moon_lblat = 0;
1697 ss_moon_mag = 0;
1698 ss_moon_term = 0;
1699
1700 return;
1701 };
1702
1703 if (!ss_update_called) updateSolar();
1704 ss_moon_called = true;
1705
1706 jd = ss_time;
1707
1708 rs = SnPos (ep2, els);
1709 rs *= ae;
1710 snc = rs;
1711
1712 rm = MnPos (ep2, elm);
1713 mnc = rm;
1714 s = snc - rm;
1715 MoonLibr(jd, rm, s, lblon, lblat, termt); // librations and terminator
1716
1717 // calculate apparent magnitude of the Moon
1718 mnmag = abs(rm) / 23454.77992; // distance moon-observer in AU
1719 s = vnorm(s);
1720 s[0] = -s[0];
1721 s[1] = -s[1];
1722 s[2] = -s[2];
1723 s3 = vnorm(rm);
1724
1725 dist = dot(s, s3); // cos of phase angle Sun-Moon-Observer
1726 if (fabs(dist) <= 1.0) dist = acos(dist) / degrad;
1727 else dist = 180.0;
1728 if (dist <= 61.0) dist = -3.475256769e-2 + 2.75256769e-2*dist;
1729 else
1730 {
1731 if (dist < 115.0) dist = 0.6962632 * exp(1.48709985e-2*dist);
1732 else
1733 {
1734 if (dist < 155.0) dist = 0.6531068 * exp(1.49213e-2*dist);
1735 else dist = 1.00779e-9 * pow (dist, 4.486359);
1736 };
1737 };
1738 if (mnmag <= 0) mnmag = 1e-30; // should never happen.
1739 mnmag = 0.23 + 5.0*log10(mnmag) + dist; // moon's mag
1740
1741 // illuminated fraction
1742 rs = snc - mnc;
1743 rs = vnorm(rs);
1744 rm = vnorm(mnc);
1745 t = (1.0 - dot(rs,rm)) * 0.5;
1746 ps = elm - els;
1747 if (ps < 0) ps += 2*M_PI;
1748 ps = ps / (2.0*M_PI);
1749
1750 ss_moon_ildisk = t;
1751 ss_moon_phase = ps;
1752 ss_moon_lblon = lblon;
1753 ss_moon_lblat = lblat;
1754 ss_moon_mag = mnmag;
1755 ss_moon_term = termt;
1756 }
1757
getConstSun()1758 void SolarSystem::getConstSun() // Sun constants
1759 {
1760 ss_J2 = 0;
1761 ss_R0 = 696000.0;
1762 ss_flat = 0.0;
1763 ss_axl0 = 286.13;
1764 ss_axl1 = 0.0;
1765 ss_axb0 = 63.87;
1766 ss_axb1 = 0.0;
1767 ss_W = 84.10;
1768 ss_Wd = 14.1844000;
1769 ss_GM = 1.32712438e+20;
1770 }
1771
getConstMoon()1772 void SolarSystem::getConstMoon() // Moon planetary constants
1773 {
1774 ss_J2 = 0.2027e-3;
1775 ss_R0 = 1738.0;
1776 ss_flat = 0.0;
1777 ss_axl0 = 0.0;
1778 ss_axl1 = 0.0;
1779 ss_axb0 = 90.0;
1780 ss_axb1 = 0.0;
1781 ss_W = 0.0;
1782 ss_Wd = 13.17635898;
1783 ss_GM = 4.90279412e+12;
1784 }
1785
getConstMercury()1786 void SolarSystem::getConstMercury() // Mercury planetary constants
1787 {
1788 ss_J2 = 0.0;
1789 ss_R0 = 2439.7;
1790 ss_flat = 0.0;
1791 ss_axl0 = 281.0097;
1792 ss_axl1 = -0.0328;
1793 ss_axb0 = 61.4143;
1794 ss_axb1 = -0.0049;
1795 ss_W = 329.5469;
1796 ss_Wd = 6.1385025;
1797 ss_GM = 2.20320802e+13;
1798 }
1799
getConstVenus()1800 void SolarSystem::getConstVenus() // Venus planetary constants
1801 {
1802 ss_J2 = 0.027e-3;
1803 ss_R0 = 6051.9;
1804 ss_flat = 0.0;
1805 ss_axl0 = 272.72;
1806 ss_axl1 = 0.0;
1807 ss_axb0 = 67.16;
1808 ss_axb1 = 0.0;
1809 ss_W = 160.20;
1810 ss_Wd = -1.4813688;
1811 ss_GM = 3.24858761e+14;
1812 }
1813
getConstEarth()1814 void SolarSystem::getConstEarth() // Earth planetary constants
1815 {
1816 ss_J2 = 1.08263e-3;
1817 ss_R0 = 6378.140;
1818 ss_flat = 0.00335364;
1819 ss_axl0 = 0.0;
1820 ss_axl1 = 0.0;
1821 ss_axb0 = 90.0;
1822 ss_axb1 = 0.0;
1823 ss_W = 0;
1824 ss_Wd = 359.017045833334;
1825 ss_GM = 3.986005e+14;
1826 }
1827
getConstMars()1828 void SolarSystem::getConstMars() // Mars planetary constants
1829 {
1830 ss_J2 = 1.964e-3;
1831 ss_R0 = 3397.2;
1832 ss_flat = 0.00647630;
1833 ss_axl0 = 317.68143;
1834 ss_axl1 = -0.1061;
1835 ss_axb0 = 52.88650;
1836 ss_axb1 = -0.0609;
1837 ss_W = 176.630; // 176.655;
1838 ss_Wd = 350.89198226;
1839 ss_GM = 4.282828596416e+13; // 4.282837405582e+13
1840 }
1841
getConstJupiter()1842 void SolarSystem::getConstJupiter() // Jupiter planetary constants
1843 {
1844 ss_J2 = 0.01475;
1845 ss_R0 = 71492.0;
1846 ss_flat = 0.06487;
1847 ss_axl0 = 268.056595;
1848 ss_axl1 = -0.009;
1849 ss_axb0 = 64.495303;
1850 ss_axb1 = 0.003;
1851 ss_W = 43.3;
1852 ss_Wd = 870.270;
1853 ss_GM = 1.2671199164e+17;
1854 }
1855
getConstSaturn()1856 void SolarSystem::getConstSaturn() // Saturn planetary constants
1857 {
1858 ss_J2 = 0.01645;
1859 ss_R0 = 60268.0;
1860 ss_flat = 0.09796;
1861 ss_axl0 = 40.589;
1862 ss_axl1 = -0.036;
1863 ss_axb0 = 83.537;
1864 ss_axb1 = -0.004;
1865 ss_W = 38.90;
1866 ss_Wd = 810.7939024;
1867 ss_GM = 3.7934096899e+16;
1868 }
1869
getConstUranus()1870 void SolarSystem::getConstUranus() // Uranus planetary constants
1871 {
1872 ss_J2 = 0.012;
1873 ss_R0 = 25559.0;
1874 ss_flat = 0.02293;
1875 ss_axl0 = 257.311;
1876 ss_axl1 = 0;
1877 ss_axb0 = -15.175;
1878 ss_axb1 = 0;
1879 ss_W = 203.18;
1880 ss_Wd = -501.1600928;
1881 ss_GM = 5.8031587739e+15;
1882 }
1883
getConstNeptune()1884 void SolarSystem::getConstNeptune() // Neptune planetary constants
1885 {
1886 ss_J2 = 0.004;
1887 ss_R0 = 24764.0;
1888 ss_flat = 0.0171;
1889 ss_axl0 = 299.36;
1890 ss_axl1 = 0;
1891 ss_axb0 = 43.46;
1892 ss_axb1 = 0;
1893 ss_W = 253.18;
1894 ss_Wd = 536.3128492;
1895 ss_GM = 6.8713077560e+15;
1896 }
1897
getConstIo()1898 void SolarSystem::getConstIo() // Io planetary constants
1899 {
1900 ss_J2 = 0;
1901 ss_R0 = 1815.0;
1902 ss_flat = 0;
1903 ss_axl0 = 268.05;
1904 ss_axl1 = -0.009;
1905 ss_axb0 = 64.49;
1906 ss_axb1 = 0.003;
1907 ss_W = 200.39;
1908 ss_Wd = 203.4889538;
1909 ss_GM = 5.930121208752e+12;
1910 }
1911
getConstEuropa()1912 void SolarSystem::getConstEuropa() // Europa planetary constants
1913 {
1914 double j4, dt;
1915 dt = ss_time + ss_del_tdut/86400.0;
1916 dt = julcent (dt);
1917 j4 = 355.8 + 1191.3*dt;
1918 j4 *= degrad;
1919
1920 ss_J2 = 0;
1921 ss_R0 = 1569.0;
1922 ss_flat = 0;
1923 ss_axl0 = 268.08 + 1.086*sin(j4);
1924 ss_axl1 = -0.009;
1925 ss_axb0 = 64.51 + 0.468*cos(j4);
1926 ss_axb1 = 0.003;
1927 ss_W = 36.022 - 0.980*sin(j4);
1928 ss_Wd = 101.3747235;
1929 ss_GM = 3.193142189328e+12;
1930 }
1931
getConstGanymede()1932 void SolarSystem::getConstGanymede() // Ganymede planetary constants
1933 {
1934 double j5, dt;
1935 dt = ss_time + ss_del_tdut/86400.0;
1936 dt = julcent (dt);
1937 j5 = 119.9 + 262.1*dt;
1938 j5 *= degrad;
1939
1940 ss_J2 = 0;
1941 ss_R0 = 2631.0;
1942 ss_flat = 0;
1943 ss_axl0 = 268.20 + 0.431*sin(j5);
1944 ss_axl1 = -0.009;
1945 ss_axb0 = 64.57 + 0.186*cos(j5);
1946 ss_axb1 = 0.003;
1947 ss_W = 44.064 - 0.186*sin(j5);
1948 ss_Wd = 50.3176081;
1949 ss_GM = 9.883535347920e+12;
1950 }
1951
getConstCallisto()1952 void SolarSystem::getConstCallisto() // Callisto planetary constants
1953 {
1954 double j6, dt;
1955 dt = ss_time + ss_del_tdut/86400.0;
1956 dt = julcent (dt);
1957 j6 = 229.8 + 64.3*dt;
1958 j6 *= degrad;
1959
1960 ss_J2 = 0;
1961 ss_R0 = 2400.0;
1962 ss_flat = 0;
1963 ss_axl0 = 268.72 + 0.590*sin(j6);
1964 ss_axl1 = -0.009;
1965 ss_axb0 = 64.83 + 0.254*cos(j6);
1966 ss_axb1 = 0.003;
1967 ss_W = 259.51 - 0.254*sin(j6);
1968 ss_Wd = 21.5710715;
1969 ss_GM = 7.171898726824e+12;
1970 }
1971
getConstRhea()1972 void SolarSystem::getConstRhea() // Rhea planetary constants
1973 {
1974 double s7, dt;
1975 dt = ss_time + ss_del_tdut/86400.0;
1976 dt = julcent (dt);
1977 s7 = 345.2 - 1016.3*dt;
1978 s7 *= degrad;
1979
1980 ss_J2 = 0;
1981 ss_R0 = 765.0;
1982 ss_flat = 0;
1983 ss_axl0 = 40.38 + 3.10*sin(s7);
1984 ss_axl1 = -0.036;
1985 ss_axb0 = 83.55 - 0.35*cos(s7);
1986 ss_axb1 = -0.004;
1987 ss_W = 235.16 - 3.08*sin(s7);
1988 ss_Wd = 79.6900478;
1989 ss_GM = 1.669100263556e+11;
1990 }
1991
getConstTitan()1992 void SolarSystem::getConstTitan() // Titan planetary constants
1993 {
1994 double s8, dt;
1995 dt = ss_time + ss_del_tdut/86400.0;
1996 dt = julcent (dt);
1997 s8 = 29.8 - 52.1*dt;
1998 s8 *= degrad;
1999
2000 ss_J2 = 0;
2001 ss_R0 = 2575.0;
2002 ss_flat = 0;
2003 ss_axl0 = 39.4827 + 2.66*sin(s8);
2004 ss_axl1 = -0.036;
2005 ss_axb0 = 83.4279 - 0.33*cos(s8);
2006 ss_axb1 = -0.004;
2007 ss_W = 186.5855 - 2.64*sin(s8);
2008 ss_Wd = 22.5769768;
2009 ss_GM = 9.028315061962e+12;
2010 }
2011
getConstMimas()2012 void SolarSystem::getConstMimas() // Mimas planetary constants
2013 {
2014 double s3, s9, dt;
2015 dt = ss_time + ss_del_tdut/86400.0;
2016 dt = julcent (dt);
2017 s3 = 117.40 - 36505.5*dt;
2018 s3 *= degrad;
2019 s9 = 316.45 + 506.2*dt;
2020 s9 *= degrad;
2021
2022 ss_J2 = 0;
2023 ss_R0 = 196.0;
2024 ss_flat = 0;
2025 ss_axl0 = 40.66 + 13.56*sin(s3);
2026 ss_axl1 = -0.036;
2027 ss_axb0 = 83.52 - 1.53*cos(s3);
2028 ss_axb1 = -0.004;
2029 ss_W = 333.46 - 13.48*sin(s3) - 44.85*sin(s9);
2030 ss_Wd = 381.9945550;
2031 ss_GM = 3.034727751920e+09;
2032 }
2033
getConstEnceladus()2034 void SolarSystem::getConstEnceladus() // Enceladus planetary constants
2035 {
2036 ss_J2 = 0;
2037 ss_R0 = 250.0;
2038 ss_flat = 0;
2039 ss_axl0 = 40.66;
2040 ss_axl1 = -0.036;
2041 ss_axb0 = 83.52;
2042 ss_axb1 = -0.004;
2043 ss_W = 6.32;
2044 ss_Wd = 262.7318996;
2045 ss_GM = 4.931432596870e+09;
2046 }
2047
getConstDione()2048 void SolarSystem::getConstDione() // Dione planetary constants
2049 {
2050 ss_J2 = 0;
2051 ss_R0 = 560.0;
2052 ss_flat = 0;
2053 ss_axl0 = 40.66;
2054 ss_axl1 = -0.036;
2055 ss_axb0 = 83.52;
2056 ss_axb1 = -0.004;
2057 ss_W = 357.00;
2058 ss_Wd = 131.5349316;
2059 ss_GM = 7.017807926315e+10;
2060 }
2061
getConstUser()2062 void SolarSystem::getConstUser() // User planetary constants
2063 {
2064 ss_J2 = ss_user_J2;
2065 ss_R0 = ss_user_R0;
2066 ss_flat = ss_user_flat;
2067 ss_axl0 = ss_user_axl0;
2068 ss_axl1 = ss_user_axl1;
2069 ss_axb0 = ss_user_axb0;
2070 ss_axb1 = ss_user_axb1;
2071 ss_W = ss_user_W;
2072 ss_Wd = ss_user_Wd;
2073 ss_GM = ss_user_GM;
2074 }
2075
putConstUser(double j2,double r0,double flat,double axl0,double axl1,double axb0,double axb1,double w,double wd,double gm)2076 void SolarSystem::putConstUser(double j2, double r0, double flat, double axl0, double axl1, double axb0, double axb1, double w, double wd, double gm)
2077 {
2078 // store physical user constants
2079 ss_user_J2 = j2;
2080 ss_user_R0 = r0;
2081 ss_user_flat = flat;
2082 ss_user_axl0 = axl0;
2083 ss_user_axl1 = axl1;
2084 ss_user_axb0 = axb0;
2085 ss_user_axb1 = axb1;
2086 ss_user_W = w;
2087 ss_user_Wd = wd;
2088 ss_user_GM = gm;
2089 }
2090
getSelenographic()2091 Mat3 SolarSystem::getSelenographic ()
2092 {
2093 // Calculate the Matrix to transform from Mean of J2000 into selenographic
2094 // coordinates at MJD time ss_time.
2095
2096 double t, gam, gmp, l, omg, mln;
2097 double a, b, c, ic, gn, gp, omp;
2098 double const degrad = M_PI / 180.0;
2099 Vec3 v1;
2100 Mat3 m1, m2;
2101
2102 t = (ss_time - 15019.5) / 36525.0;
2103 gam = 281.2208333 + ((0.33333333e-5*t + 0.45277778e-3)*t + 1.7191750)*t;
2104 gmp = 334.3295556 + ((-0.125e-4*t - 0.10325e-1)*t + 4069.0340333)*t;
2105 l = 279.6966778 + (0.3025e-3*t + 36000.768925)*t;
2106 omg = 259.1832750 + ((0.22222222e-5*t + 0.20777778e-2)*t - 1934.1420083)*t;
2107 b = 23.45229444 + ((0.50277778e-6*t -0.16388889e-5)*t - 0.130125e-1)*t;
2108 mln = 270.4341639 + ((0.1888889e-5*t -0.11333e-2)*t + 481267.8831417)*t;
2109 ic = 1.535*degrad;
2110 gn = (l - gam)*degrad;
2111 gp = (mln - gmp)*degrad;
2112 omp = (gmp - omg)*degrad;
2113 a = -107.0*cos(gp) + 37.0*cos(gp+2.0*omp) -11.0*cos(2.0*(gp+omp));
2114 a = a*0.000277778*degrad + ic;
2115 c = (-109.0*sin(gp) + 37.0*sin(gp+2.0*omp) - 11.0*sin(2.0*(gp+omp)))/sin(ic);
2116 c = (c*0.000277778 + omg)*degrad;
2117 gn = -12.0*sin(gp) + 59.0*sin(gn) + 18.0*sin(2.0*omp);
2118 gn = gn*0.000277778*degrad; // tau
2119
2120 b *= degrad;
2121 gam = cos(a)*cos(b) + sin(a)*sin(b)*cos(c);
2122 gmp = gam*gam;
2123 if(gmp > 1.0) gmp = 0;
2124 else gmp = sqrt(1.0 - gmp);
2125 gam = atan23(gmp,gam); // theta
2126 t = cos(a)*sin(b) - sin(a)*sin(b)*cos(c);
2127 l = -sin(a)*sin(c);
2128
2129 gmp = atan23(l,t); // phi
2130 t = sin(a)*cos(b) - cos(a)*sin(b)*cos(c);
2131 l = -sin(b)*sin(c);
2132 a = atan23(l,t); // delta
2133 c = a + mln*degrad + gn - c; // psi
2134
2135 // libration rotation matrix from Mean equator to true selenographic
2136 m1 = zrot(gmp);
2137 m2 = xrot(gam);
2138 m1 = m2 * m1;
2139 m2 = zrot(c);
2140 m1 = m2 * m1;
2141
2142 t = julcent(ss_time + ss_del_tdut/86400.0);
2143 m2 = pmatequ(0,t); // convert from mean of J2000 to mean of epoch
2144 m1 = m1 * m2;
2145
2146 return m1;
2147 }
2148
getPlanMat()2149 void SolarSystem::getPlanMat()
2150 {
2151 // get Matrix to convert from Equatorial into planetary coordinates
2152
2153 double ag, dt;
2154 Mat3 mx, m1;
2155
2156 ss_planmat_called = true;
2157
2158 dt = ss_time + ss_del_tdut/86400.0;
2159 dt = julcent (dt);
2160 if (ss_central_body == 1) ss_planmat = getSelenographic();
2161 else
2162 {
2163 if (ss_central_body == 4) // Earth
2164 {
2165 mx = pmatequ(0, dt);
2166 m1 = nutmat(dt, ag, false);
2167 mx = m1 * mx;
2168 m1 = zrot(lsidtim(ss_time, 0, ag)*M_PI/12.0);
2169 }
2170 else // other planets
2171 {
2172 ag = (ss_axl0 + ss_axl1 * dt) * M_PI / 180.0;
2173 mx = zrot(ag + M_PI / 2.0);
2174 ag = (ss_axb0 + ss_axb1 * dt) * M_PI / 180.0;
2175 m1 = xrot(M_PI / 2.0 - ag);
2176 mx = m1 * mx;
2177 m1 = zrot((ss_W + ss_Wd*(ss_time+ss_del_tdut/86400.0-51544.5))*(M_PI/180.0));
2178 };
2179 ss_planmat = m1 * mx;
2180 };
2181
2182 if (ss_epoch != 51544.5) // correct for precession
2183 {
2184 if (ss_epoch == 0) ag = dt;
2185 else ag = julcent(ss_epoch);
2186 mx = pmatequ(ag, 0);
2187 ss_planmat = ss_planmat * mx;
2188 };
2189
2190 }
2191
getPlanetocentric(double ra,double decl)2192 Vec3 SolarSystem::getPlanetocentric (double ra, double decl)
2193 {
2194 // return unity vector which corresponds to planetocentric position of
2195 // sky point at R.A ra (in HH.MMSS) and Declination decl (in DDD.MMSS)
2196
2197 double dra, ddec;
2198 Vec3 ru;
2199
2200 if (!ss_update_called) updateSolar();
2201 if (!ss_planmat_called) getPlanMat();
2202
2203 dra = 15.0*DmsDegF(ra)*degrad;
2204 ddec = DmsDegF(decl)*degrad;
2205
2206 ru[0] = 1.0;
2207 ru[1] = dra;
2208 ru[2] = ddec;
2209 ru = polcar(ru);
2210
2211 ru = mxvct (ss_planmat, ru);
2212
2213 return ru;
2214 }
2215
getPlanetographic(double ra,double decl,double & lng,double & lat)2216 void SolarSystem::getPlanetographic (double ra, double decl, double &lng, double &lat)
2217 {
2218 // get planetogrphic longitude long and latitude lat (in decimal degrees) where
2219 // sky point at R.A ra (in HH.MMSS) and Declination decl (in DDD.MMSS) is at zenith.
2220
2221 int j;
2222 double f, re, b1, b2, b3, c, sh, s, mp2;
2223 Vec3 ru, s2;
2224
2225 ru = getPlanetocentric (ra, decl);
2226
2227 mp2 = 2.0 * M_PI;
2228 re = ss_R0;
2229 ru *= re;
2230 f = ss_flat;
2231
2232 s2 = carpol(ru);
2233 ss_lat = s2[2]; // just preliminary
2234 ss_lng = s2[1]; // measured with the motion of rotation!
2235 if (ss_lng > mp2) ss_lng -= mp2;
2236 if (ss_lng < -M_PI) ss_lng += mp2;
2237 if (ss_lng > M_PI) ss_lng -= mp2;
2238
2239 // get height above ellipsoid and geodetic latitude
2240 if (abs(ru) > 0.1)
2241 {
2242 if (f == 0)
2243 {
2244 ss_height = abs(ru) - re;
2245 }
2246 else
2247 {
2248 c = f*(2.0 - f);
2249 s = ru[0]*ru[0] + ru[1]*ru[1];
2250 sh = c*ru[2];
2251
2252 for (j=0; j<4; j++)
2253 {
2254 b1 = ru[2] + sh;
2255 b3 = sqrt(s+b1*b1);
2256 if (b3 < 1e-5) b3 = sin(ss_lat); // just in case
2257 else b3 = b1 / b3;
2258 b2 = re / sqrt(1.0 - c*b3*b3);
2259 sh = b2 * c * b3;
2260 };
2261
2262 sh = ru[2] + sh;
2263 ss_lat = atan23(sh,sqrt(s));
2264 sh = sqrt(s+sh*sh) - b2;
2265 ss_height = sh;
2266 };
2267 }
2268 else ss_height = 0; // this should never happen
2269
2270 ss_lat = ss_lat * 180.0 / M_PI;
2271 ss_lng = ss_lng * 180.0 / M_PI;
2272
2273 lat = ss_lat;
2274 lng = ss_lng;
2275
2276 }
2277
getSkyRotAngles(double & raz1,double & rax,double & raz2)2278 void SolarSystem::getSkyRotAngles (double &raz1, double &rax, double &raz2)
2279 {
2280 // get rotation angles to transform from the Equatorial System into the
2281 // Planetocentric System (angles in radians)
2282 // first rotate around z-axis with raz1, then around the x-axis with rax
2283 // and finally around the new z-axis with raz2
2284
2285 double rz1, rx1, rz2;
2286 Vec3 rpole, rnull, rtmp;
2287 Mat3 pmheq;
2288
2289 if (!ss_update_called) updateSolar();
2290 if (!ss_planmat_called) getPlanMat();
2291
2292 pmheq = mxtrn ( ss_planmat); // from planetary into J2000
2293 rtmp[0] = 0;
2294 rtmp[1] = 0;
2295 rtmp[2] = 1.0;
2296 rpole = mxvct (pmheq, rtmp);
2297
2298 rtmp[0] = 1.0;
2299 rtmp[2] = 0;
2300 rnull = mxvct (pmheq, rtmp);
2301
2302 rtmp = carpol (rpole);
2303 rz1 = rtmp[1]; // Right Ascension of North Pole direction
2304 rx1 = rtmp[2]; // Declination
2305
2306 pmheq = zrot(rz1 + M_PI*0.5);
2307 pmheq = xrot(M_PI*0.5 - rx1) * pmheq;
2308 rtmp = mxvct (pmheq, rnull);
2309 rnull = carpol (rtmp);
2310 rz2 = rnull[1]; // angle W
2311
2312 raz1 = rz1 + M_PI*0.5;
2313 if (raz1 > 2.0*M_PI) raz1 -= 2.0*M_PI;
2314 rax = M_PI*0.5 - rx1;
2315 raz2 = rz2;
2316
2317 }
2318
putOrbitElements(double t0,double pdist,double ecc,double ran,double aper,double inc,double eclep)2319 void SolarSystem::putOrbitElements (double t0, double pdist, double ecc, double ran, double aper, double inc, double eclep)
2320 {
2321 // store orbit elements for a hyperbolic, parabolic or highly elliptic heliocentric orbit
2322
2323 ss_kepler_stored = true;
2324 ss_kepler_called = false;
2325
2326 ss_t0 = t0;
2327 ss_m0 = -1.0;
2328 ss_a = pdist;
2329 ss_ecc = ecc;
2330 ss_ran = ran;
2331 ss_aper = aper;
2332 ss_inc = inc;
2333 ss_eclep = eclep;
2334 }
2335
putEllipticElements(double t0,double a,double m0,double ecc,double ran,double aper,double inc,double eclep)2336 void SolarSystem::putEllipticElements (double t0, double a, double m0, double ecc, double ran, double aper, double inc, double eclep)
2337 {
2338 // store orbit elements for an elliptic heliocentric orbit
2339
2340 ss_kepler_stored = true;
2341 ss_kepler_called = false;
2342
2343 ss_t0 = t0;
2344 ss_m0 = m0;
2345 ss_a = a;
2346 ss_ecc = ecc;
2347 ss_ran = ran;
2348 ss_aper = aper;
2349 ss_inc = inc;
2350 ss_eclep = eclep;
2351 }
2352
putOrbitUser(double t0,double pdist,double ecc,double ran,double aper,double inc,double eclep)2353 void SolarSystem::putOrbitUser (double t0, double pdist, double ecc, double ran, double aper, double inc, double eclep)
2354 {
2355 // store orbit elements for a hyperbolic, parabolic or highly elliptic heliocentric orbit for the user defined body
2356
2357 ss_user_stored = true;
2358 ss_user_active = true;
2359 ss_update_called = false;
2360
2361 ss_user_t0 = t0;
2362 ss_user_m0 = -1.0;
2363 ss_user_a = pdist;
2364 ss_user_ecc = ecc;
2365 ss_user_ran = ran;
2366 ss_user_aper = aper;
2367 ss_user_inc = inc;
2368 ss_user_eclep = eclep;
2369 }
2370
putEllipticUser(double t0,double a,double m0,double ecc,double ran,double aper,double inc,double eclep)2371 void SolarSystem::putEllipticUser (double t0, double a, double m0, double ecc, double ran, double aper, double inc, double eclep)
2372 {
2373 // store orbit elements for an elliptic heliocentric orbit for the user object
2374
2375 ss_user_stored = true;
2376 ss_user_active = true;
2377 ss_update_called = false;
2378
2379 ss_user_t0 = t0;
2380 ss_user_m0 = m0;
2381 ss_user_a = a;
2382 ss_user_ecc = ecc;
2383 ss_user_ran = ran;
2384 ss_user_aper = aper;
2385 ss_user_inc = inc;
2386 ss_user_eclep = eclep;
2387 }
2388
getOrbitPosition(double & ra,double & decl)2389 void SolarSystem::getOrbitPosition (double& ra, double& decl)
2390 {
2391 // get the position of the object for which the Kepler elements had been stored
2392
2393 const double gs = 2.959122083e-4; // gravitation constant of the Sun in AU and d
2394 double dt;
2395 int day, month, year;
2396 double b, eps2, yr;
2397 Mat3 pmx;
2398
2399 Vec3 r1, v1;
2400
2401 if (!ss_kepler_stored)
2402 {
2403 ra = -100.0;
2404 decl = 0;
2405
2406 return;
2407 };
2408
2409 if (!ss_update_called) updateSolar();
2410
2411 ss_kepler_called = true;
2412
2413 // calculate Kepler orbit
2414
2415 dt = ss_time + ss_del_tdut/86400.0;
2416
2417 kepler (gs, ss_t0, dt, ss_m0, ss_a, ss_ecc, ss_ran, ss_aper, ss_inc, r1, v1);
2418
2419 // correct for precession
2420 if (ss_epoch != 0) eps2 = julcent(ss_epoch);
2421 else eps2 = julcent(dt);
2422
2423 yr = ss_eclep;
2424 if (yr == 0) b = eps2; // Mean of Date
2425 else
2426 {
2427 year = int(yr);
2428 b = 12.0 * (yr - double(year));
2429 month = int(b) + 1;
2430 day = 1;
2431
2432 b = mjd(day, month, year, 0);
2433 b = julcent(b);
2434 };
2435
2436 pmx = pmatecl(b, eps2);
2437 ss_comet = mxvct(pmx,r1);
2438
2439 // convert into equatorial
2440 ss_comet = eclequ(eps2, ss_comet);
2441
2442 // correct for nutation
2443 if (ss_nutation)
2444 {
2445 dt = julcent(dt);
2446 pmx = nutmat(dt, eps2, false);
2447 ss_comet = mxvct(pmx,ss_comet);
2448 };
2449
2450 // refer to selected central body
2451 ss_comet = ss_comet + ss_rs;
2452
2453 getRaDec (ss_comet, ra, decl);
2454 }
2455
getDistance()2456 double SolarSystem::getDistance()
2457 {
2458 // distance in AU of Kepler object
2459
2460 double ra, decl;
2461
2462 if (!ss_kepler_stored) return 0;
2463
2464 if (!ss_kepler_called) getOrbitPosition (ra, decl);
2465
2466 return abs(ss_comet);
2467 }
2468
getCometMag(double g,double k)2469 double SolarSystem::getCometMag(double g, double k)
2470 {
2471 // apparent magnitude of comet. g = absolute magnitude, k = comet function
2472
2473 double ra, decl;
2474
2475 if (!ss_kepler_stored) return 0;
2476
2477 if (!ss_kepler_called) getOrbitPosition (ra, decl);
2478
2479 return g + 5.0 * log10(abs(ss_comet)) + k * log10(abs(ss_comet - ss_rs));
2480
2481 }
2482
getAsteroidMag(double h,double g)2483 double SolarSystem::getAsteroidMag(double h, double g)
2484 {
2485 // apparent magnitude of asteroid. h = absolute magnitude, g = slope parameter
2486
2487 double ra, decl, s, t;
2488
2489 if (!ss_kepler_stored) return 0;
2490
2491 if (!ss_kepler_called) getOrbitPosition (ra, decl);
2492
2493 ra = abs(ss_comet);
2494 decl = abs(ss_comet - ss_rs);
2495 t = 2.0 * ra * decl;
2496 s = abs(ss_rs);
2497
2498 if (t > 0) t = (ra*ra + decl*decl - s*s) / t;
2499 else t = 0; // just in case
2500
2501 t = acos(t) / degrad;
2502 t /= 10.0;
2503
2504 ra = h + 5.0 * log10(ra*decl) + g * t;
2505
2506 return ra;
2507
2508 }
2509