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