File indexing completed on 2024-04-28 11:29:48

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2015 Gerhard Holtkamp
0004 //
0005 
0006 /***************************************************************************
0007 * Calculate positions and physical ephemerides of Solar System bodies.     * *                                                                          *
0008 * The algorithm for the Modified Julian Date are based on                  *
0009 * O.Montebruck and T.Pfleger, "Astronomy with a PC",                       *
0010 * Springer Verlag, Berlin, Heidelberg, New York, 1989                      *
0011 * 
0012 * The calculations of the positions and physical ephemerides of the        *
0013 * various solar system bodies are based on                                 *
0014 * O.Montebruck, "Astronomie mit dem Personal Computer",                    *
0015 * Springer Verlag, Berlin, Heidelberg, 1989;                               *
0016 * O.Montebruck, "Practical Ephemeris Calculations",                        *
0017 * Springer Verlag, Berlin, Heidelberg, New York, 1989                      *
0018 * and on the                                                               *
0019 * "Explanatory Supplement to the Astronomical Almanac"                     *
0020 * University Science Books, Mill Valley, CA, 1992                          *
0021 *                                                                          *
0022 * Open Source Code. License: GNU LGPL Version 2+                           *
0023 *                                                                          *
0024 * Author: Gerhard HOLTKAMP,        09-JAN-2015                             *
0025 ***************************************************************************/
0026 
0027 /*------------ include files and definitions -----------------------------*/
0028 #include "solarsystem.h"
0029 #include <cstdio>
0030 #include <cstdlib>
0031 #include <cstring>
0032 #include <cmath>
0033 #include <ctime>
0034 using namespace std;
0035 
0036 #include "astrolib.h"
0037 #include "astr2lib.h"
0038 
0039 const double degrad = M_PI / 180.0;
0040 
0041 // ################ Solar Eclipse Class ####################
0042 
0043 SolarSystem::SolarSystem()
0044 {
0045  ssinit();
0046 }
0047 
0048 SolarSystem::~SolarSystem()
0049 {
0050 
0051 }
0052 
0053 double SolarSystem::atan23 (double y, double x)
0054  {
0055   /* redefine atan2 so that it doesn't crash when both x and y are 0 */
0056   double result;
0057 
0058   if ((x == 0) && (y == 0)) result = 0;
0059   else result = atan2 (y, x);
0060 
0061   return result;
0062  }
0063 
0064 double SolarSystem::DegFDms (double h)
0065  {
0066   /* convert degrees from d.fff -> d.mmsss where .mm are the minutes
0067      and sss are seconds (and fractions of seconds).
0068   */
0069   int mm, deg;
0070   double hh, t, sec;
0071 
0072   hh = fabs(h);
0073   dms (hh,deg,mm,sec);
0074   if (sec>=59.5)
0075    {
0076     mm++;
0077     sec = 0;
0078    };
0079   if (mm>59)
0080    {
0081     deg++;
0082     mm=0;
0083    };
0084   hh = double(deg);
0085   t = double(mm)/100.0;
0086   hh += t;
0087   t = sec/10000.0;
0088   hh += t;
0089   if (h < 0) hh = -hh;
0090 
0091   return hh;
0092  }
0093 
0094 double SolarSystem::DmsDegF (double h)
0095  {
0096   /* convert degrees from d.mmsss -> d.fff where .mm are the minutes
0097      and sss are seconds (and fractions of seconds).
0098      Returned is the angle in decimal degrees.
0099   */
0100   int mm, deg;
0101   double hh, t, sec, dlt;
0102 
0103   hh = fabs(h);
0104   dlt = hh*3.33e-16;
0105   hh += dlt;
0106   deg = int(hh);
0107   t = fmod(hh,1.0)*100.0;
0108   mm = int(t + 0.1e-12);
0109   sec = fmod(hh*100.0,1.0)*100.0;
0110   hh = ddd(deg,mm,sec);
0111   if (h < 0) hh = -hh;
0112 
0113   return hh;
0114  }
0115 
0116 void SolarSystem::ssinit()
0117 {
0118  // initialize solar system data
0119   ss_update_called = false;
0120   ss_moon_called = false;
0121   ss_nutation = false;
0122   ss_planmat_called = false;
0123   ss_kepler_stored = false;
0124   ss_kepler_called = false;
0125   ss_user_stored= false;
0126   ss_user_active = false;
0127 
0128   ss_day = 1;
0129   ss_month = 1;
0130   ss_year = 2012;
0131   ss_hour = 0;
0132   ss_minute = 0;
0133   ss_second = 0;
0134   ss_tzone = 0;
0135   ss_del_auto = 1;
0136   ss_del_tdut = DefTdUt(ss_year);
0137   ss_RT = true;
0138   ss_epoch = 51544.5;  // J2000.0
0139   ss_central_body = 4;  
0140   setCurrentMJD();
0141   ss_planmat = mxidn();
0142   getConstEarth();
0143 
0144   // just to have some data there in case
0145   ss_user_J2 = 1.08263e-3;
0146   ss_user_R0 = 6378.140;
0147   ss_user_flat = 0.00335364;
0148   ss_user_axl0 = 0.0;
0149   ss_user_axl1 = 0.0;
0150   ss_user_axb0 = 90.0;
0151   ss_user_axb1 = 0.0;   
0152   ss_user_W = 0;
0153   ss_user_Wd = 359.017045833334;
0154   ss_user_GM = 3.986005e+14;  
0155 
0156 }
0157 
0158 void SolarSystem::DefTime ()  // Get System Time and Date
0159  {
0160   time_t tt;
0161   int hh, mm, ss;
0162   double jd, hr;
0163 
0164   tt = time(NULL);
0165   jd = 40587.0 + tt/86400.0; // seconds since 1-JAN-1970
0166 
0167   caldat(jd, hh, mm, ss, hr);
0168   ss_year = ss;
0169   ss_month = mm;
0170   ss_day = hh;
0171 
0172   dms(hr, hh, mm, jd);
0173   ss_hour = hh;
0174   ss_minute = mm;
0175   ss_second = int(jd);
0176   if (ss_del_auto) ss_del_tdut = DefTdUt(ss_year);
0177   };
0178 
0179 void SolarSystem::setTimezone(double d)
0180 {
0181   // set the timezone to d (hours difference from UTC) for I/O
0182   ss_tzone = d;
0183 }
0184 
0185 void SolarSystem::setDeltaTAI_UTC(double d)
0186 {
0187   // c is the difference between TAI and UTC according to the IERS
0188   // we have to add 32.184 sec to get to the difference TT - UT
0189   // which is used in the calculations here
0190 
0191   ss_del_tdut = d + 32.184;
0192   ss_del_auto = 0;
0193 }
0194 
0195 void SolarSystem::setAutoTAI_UTC()
0196 {
0197   // set the difference between TAI and UTC according to the IERS
0198   ss_del_auto = true;
0199   ss_del_tdut = DefTdUt(ss_year);
0200 }
0201 
0202 void SolarSystem::setCurrentMJD(int year, int month, int day, int hour, int min, double sec)
0203 {
0204     // set the (MJD-) time currently used for calculations to year, month, day, hour, min, sec
0205     // corrected for timezone
0206 
0207     double jd;
0208 
0209     jd = ddd(hour, min, sec) - ss_tzone;
0210     jd = mjd(day, month, year, jd);
0211 
0212     ss_time = jd;
0213     ss_update_called = false;
0214     ss_moon_called = false;
0215     ss_planmat_called = false;
0216     ss_kepler_called = false;
0217 
0218 }
0219 
0220 void SolarSystem::setCurrentMJD()
0221 {
0222   // set the (MJD-) time currently used for calculations to Real Time
0223 
0224     double jd, sec;
0225 
0226     DefTime();
0227     sec = double(ss_second);
0228     jd = ddd(ss_hour, ss_minute, sec);
0229     jd = mjd(ss_day, ss_month, ss_year, jd);
0230 
0231     ss_time = jd;
0232     ss_update_called = false;
0233     ss_moon_called = false;
0234     ss_planmat_called = false;
0235     ss_kepler_called = false;
0236 
0237 }
0238 
0239 double SolarSystem::getMJD(int year, int month, int day, int hour, int min, double sec)
0240 {
0241     // return the (MJD-) time corresponding to year, month, day, hour, min, sec
0242     // corrected for timezone
0243 
0244     double jd;
0245 
0246     jd = ddd(hour, min, sec) - ss_tzone;
0247     jd = mjd(day, month, year, jd);
0248 
0249     return jd;
0250 }
0251 
0252 void SolarSystem::getDatefromMJD(double mjd, int &year, int &month, int &day, int &hour, int &min, double &sec)
0253 {
0254     // convert times given in Modified Julian Date (MJD) into conventional date and time
0255     // correct for timezone
0256 
0257     double magn;
0258 
0259     caldat((mjd + ss_tzone/24.0), day, month, year, magn);
0260     dms (magn,hour,min,sec);
0261     if (sec>30.0) min++;
0262     if (min>59)
0263      {
0264       hour++;
0265       min=0;
0266      };
0267 }
0268 
0269 void SolarSystem::setEpoch (double yr)
0270 {
0271  int day, month, year;
0272  double b;
0273 
0274  if (yr == 0) ss_epoch = 0;  // Mean of Date
0275  else
0276   {
0277    year = int(yr);
0278    b = 12.0 * (yr - double(year));
0279    month = int(b) + 1;
0280    day = 1;
0281 
0282    b = 0;
0283    ss_epoch = mjd(day, month, year, b); 
0284   }
0285   ss_update_called = false;
0286   ss_moon_called = false;
0287   ss_planmat_called = false;
0288   ss_kepler_called = false;
0289 
0290 }
0291 
0292 void SolarSystem::setNutation (bool nut)
0293 {
0294   ss_nutation = nut;
0295   ss_update_called = false;
0296   ss_moon_called = false;
0297   ss_planmat_called = false;
0298   ss_kepler_called = false;
0299 
0300 }
0301 
0302 void SolarSystem::setCentralBody(char* pname)
0303 {
0304   ss_central_body = 4;  // default Earth
0305   getConstEarth();
0306   if (strncmp("Sun", pname, 3) == 0)
0307    {
0308     ss_central_body = 0;
0309     getConstSun();
0310    };
0311   if (strncmp("Moon", pname, 4) == 0)
0312    {
0313     ss_central_body = 1;
0314     getConstMoon();
0315    };
0316   if (strncmp("Mercury", pname, 7) == 0)
0317    {
0318     ss_central_body = 2;
0319     getConstMercury();
0320    };
0321   if (strncmp("Venus", pname, 5) == 0)
0322    {
0323     ss_central_body = 3;
0324     getConstVenus();
0325    };
0326   if (strncmp("Mars", pname, 4) == 0)
0327    {
0328     ss_central_body = 5;
0329     getConstMars();
0330    };
0331   if (strncmp("Jupiter", pname, 7) == 0)
0332    {
0333     ss_central_body = 6;
0334     getConstJupiter();
0335    };
0336   if (strncmp("Saturn", pname, 6) == 0)
0337    {
0338     ss_central_body = 7;
0339     getConstSaturn();
0340    };
0341   if (strncmp("Uranus", pname, 6) == 0)
0342    {
0343     ss_central_body = 8;
0344     getConstUranus();
0345    };
0346   if (strncmp("Neptune", pname, 7) == 0)
0347    {
0348     ss_central_body = 9;
0349     getConstNeptune();
0350    };
0351   if (strncmp("Io", pname, 2) == 0)
0352    {
0353     ss_central_body = 10;
0354     getConstIo();
0355    };
0356   if (strncmp("Europa", pname, 6) == 0)
0357    {
0358     ss_central_body = 11;
0359     getConstEuropa();
0360    };
0361   if (strncmp("Ganymede", pname, 8) == 0)
0362    {
0363     ss_central_body = 12;
0364     getConstGanymede();
0365    };
0366   if (strncmp("Callisto", pname, 8) == 0)
0367    {
0368     ss_central_body = 13;
0369     getConstCallisto();
0370    };
0371   if (strncmp("Rhea", pname, 4) == 0)
0372    {
0373     ss_central_body = 14;
0374     getConstRhea();
0375    };
0376   if (strncmp("Titan", pname, 5) == 0)
0377    {
0378     ss_central_body = 15;
0379     getConstTitan();
0380    };
0381   if (strncmp("Mimas", pname, 5) == 0)
0382    {
0383     ss_central_body = 16;
0384     getConstMimas();
0385    };
0386   if (strncmp("Enceladus", pname, 9) == 0)
0387    {
0388     ss_central_body = 17;
0389     getConstEnceladus();
0390    };
0391   if (strncmp("Dione", pname, 5) == 0)
0392    {
0393     ss_central_body = 18;
0394     getConstDione();
0395    };
0396 
0397   if (strncmp("User", pname, 4) == 0)
0398    {
0399     if (ss_user_active)
0400      {
0401       ss_central_body = -1;
0402       getConstUser();
0403      };
0404    };
0405 
0406   ss_update_called = false;
0407   ss_moon_called = false;
0408   ss_planmat_called = false;
0409   ss_kepler_called = false;
0410 
0411 }
0412 
0413 void SolarSystem::includeUser(bool uact)
0414 {
0415  // set user defined object active if possible
0416  if(ss_user_stored) ss_user_active = uact;
0417 
0418  ss_update_called = false; 
0419 
0420 }
0421 
0422 void SolarSystem::updateSolar()
0423 {
0424   // calculate all positions in mean ecliptic of epoch
0425 
0426   const double ae = 23454.77992; // 149597870.0/6378.14 =  1AE -> Earth Radii
0427   double dt, eps2;
0428   Sun200 sun;
0429   Moon200 moon;
0430   Plan200 pln;
0431   Vec3 coff, r1, v1;
0432   Mat3 pmx;
0433 
0434   ss_update_called = true;
0435 
0436   // get positions in ecliptic coordinates of date
0437   dt = ss_time + ss_del_tdut/86400.0;
0438   dt = julcent (dt);
0439   ss_rs = sun.position(dt);
0440   ss_rm = moon.position(dt)/ae;
0441   ss_pmer = pln.Mercury(dt);
0442   ss_pven = pln.Venus(dt);
0443   ss_pearth[0] = -ss_rs[0];
0444   ss_pearth[1] = -ss_rs[1];
0445   ss_pearth[2] = -ss_rs[2];
0446   ss_pmars = pln.Mars(dt);
0447   ss_pjup = pln.Jupiter(dt);
0448   ss_psat = pln.Saturn(dt);
0449   ss_pura = pln.Uranus(dt);
0450   ss_pnept = pln.Neptune(dt);
0451   ss_pio = PosJIo(dt) + ss_pjup;
0452   ss_peuropa = PosEuropa(dt) + ss_pjup;
0453   ss_pganymede = PosGanymede(dt) + ss_pjup;
0454   ss_pcallisto = PosCallisto(dt) + ss_pjup;
0455   SatRhea (dt, r1, v1);
0456   ss_prhea = r1 + ss_psat;
0457   SatTitan (dt, r1, v1);
0458   ss_ptitan = r1 + ss_psat;
0459   ss_pmimas = PosSMimas(dt) + ss_psat;
0460   ss_penceladus = PosSEnceladus(dt) + ss_psat;
0461   ss_pdione = PosSDione(dt) + ss_psat;
0462   if (ss_user_active) ss_user = PosUser(dt);
0463 
0464   // refer to selected central body
0465   coff[0] = 0;
0466   coff[1] = 0;
0467   coff[2] = 0;
0468 
0469   if (ss_central_body == 2) coff -= ss_pmer; 
0470   if (ss_central_body == 3) coff -= ss_pven; 
0471   if (ss_central_body == 4) coff -= ss_pearth;
0472   if (ss_central_body == 5) coff -= ss_pmars; 
0473   if (ss_central_body == 6) coff -= ss_pjup; 
0474   if (ss_central_body == 7) coff -= ss_psat; 
0475   if (ss_central_body == 8) coff -= ss_pura; 
0476   if (ss_central_body == 9) coff -= ss_pnept; 
0477   if (ss_central_body == 10) coff -= ss_pio; 
0478   if (ss_central_body == 11) coff -= ss_peuropa; 
0479   if (ss_central_body == 12) coff -= ss_pganymede; 
0480   if (ss_central_body == 13) coff -= ss_pcallisto; 
0481   if (ss_central_body == 14) coff -= ss_prhea; 
0482   if (ss_central_body == 15) coff -= ss_ptitan; 
0483   if (ss_central_body == 16) coff -= ss_pmimas; 
0484   if (ss_central_body == 17) coff -= ss_penceladus; 
0485   if (ss_central_body == 18) coff -= ss_pdione;
0486   if (ss_central_body == -1) coff -= ss_user; 
0487   if (ss_central_body == 1) coff = coff + ss_rs - ss_rm; 
0488 
0489   ss_pmer += coff;
0490   ss_pven += coff;
0491   ss_pearth += coff;
0492   ss_pmars += coff;
0493   ss_pjup += coff;
0494   ss_psat += coff;
0495   ss_pura += coff;
0496   ss_pnept += coff;
0497   ss_pio += coff;
0498   ss_peuropa += coff;
0499   ss_pganymede += coff;
0500   ss_pcallisto += coff;
0501   ss_prhea += coff;
0502   ss_ptitan += coff;
0503   ss_pmimas += coff;
0504   ss_penceladus += coff;
0505   ss_pdione += coff;
0506   if (ss_user_active) ss_user += coff;
0507 
0508   ss_rs[0] = coff[0];
0509   ss_rs[1] = coff[1];
0510   ss_rs[2] = coff[2];
0511 
0512   // convert into equatorial
0513   ss_rs = eclequ(dt, ss_rs);
0514   ss_rm = eclequ(dt, ss_rm);
0515   ss_pmer = eclequ(dt, ss_pmer);
0516   ss_pven = eclequ(dt, ss_pven);
0517   ss_pearth = eclequ(dt, ss_pearth);
0518   ss_pmars = eclequ(dt, ss_pmars);
0519   ss_pjup = eclequ(dt, ss_pjup);
0520   ss_psat = eclequ(dt, ss_psat);
0521   ss_pura = eclequ(dt, ss_pura);
0522   ss_pnept = eclequ(dt, ss_pnept);
0523   ss_pio = eclequ(dt, ss_pio);
0524   ss_peuropa = eclequ(dt, ss_peuropa);
0525   ss_pganymede = eclequ(dt, ss_pganymede);
0526   ss_pcallisto = eclequ(dt, ss_pcallisto);
0527   ss_prhea = eclequ(dt, ss_prhea);
0528   ss_ptitan = eclequ(dt, ss_ptitan);
0529   ss_pmimas = eclequ(dt, ss_pmimas);
0530   ss_penceladus = eclequ(dt, ss_penceladus);
0531   ss_pdione = eclequ(dt, ss_pdione);
0532   if (ss_user_active) ss_user = eclequ(dt, ss_user);
0533 
0534   // correct for precession
0535   if (ss_epoch != 0)
0536    {
0537     eps2 = julcent(ss_epoch);
0538     pmx = pmatequ(dt, eps2);
0539     ss_rs = mxvct(pmx,ss_rs);
0540     ss_rm = mxvct(pmx,ss_rm);
0541     ss_pmer = mxvct(pmx,ss_pmer);
0542     ss_pven = mxvct(pmx,ss_pven);
0543     ss_pearth = mxvct(pmx,ss_pearth);
0544     ss_pmars = mxvct(pmx,ss_pmars);
0545     ss_pjup = mxvct(pmx,ss_pjup);
0546     ss_psat = mxvct(pmx,ss_psat);
0547     ss_pura = mxvct(pmx,ss_pura);
0548     ss_pnept = mxvct(pmx,ss_pnept);
0549     ss_pio = mxvct(pmx,ss_pio);
0550     ss_peuropa = mxvct(pmx,ss_peuropa);
0551     ss_pganymede = mxvct(pmx,ss_pganymede);
0552     ss_pcallisto = mxvct(pmx,ss_pcallisto);
0553     ss_prhea = mxvct(pmx,ss_prhea);
0554     ss_ptitan = mxvct(pmx,ss_ptitan);
0555     ss_pmimas = mxvct(pmx,ss_pmimas);
0556     ss_penceladus = mxvct(pmx,ss_penceladus);
0557     ss_pdione = mxvct(pmx,ss_pdione);
0558     if (ss_user_active) ss_user = mxvct(pmx, ss_user);
0559    };
0560 
0561   // correct for nutation
0562   if (ss_nutation)
0563    {
0564     pmx = nutmat(dt, eps2, false);
0565     ss_rs = mxvct(pmx,ss_rs);
0566     ss_rm = mxvct(pmx,ss_rm);
0567     ss_pmer = mxvct(pmx,ss_pmer);
0568     ss_pven = mxvct(pmx,ss_pven);
0569     ss_pearth = mxvct(pmx,ss_pearth);
0570     ss_pmars = mxvct(pmx,ss_pmars);
0571     ss_pjup = mxvct(pmx,ss_pjup);
0572     ss_psat = mxvct(pmx,ss_psat);
0573     ss_pura = mxvct(pmx,ss_pura);
0574     ss_pnept = mxvct(pmx,ss_pnept);
0575     ss_pio = mxvct(pmx,ss_pio);
0576     ss_peuropa = mxvct(pmx,ss_peuropa);
0577     ss_pganymede = mxvct(pmx,ss_pganymede);
0578     ss_pcallisto = mxvct(pmx,ss_pcallisto);
0579     ss_prhea = mxvct(pmx,ss_prhea);
0580     ss_ptitan = mxvct(pmx,ss_ptitan);
0581     ss_pmimas = mxvct(pmx,ss_pmimas);
0582     ss_penceladus = mxvct(pmx,ss_penceladus);
0583     ss_pdione = mxvct(pmx,ss_pdione);
0584     if (ss_user_active) ss_user = mxvct(pmx, ss_user);
0585    };
0586 }
0587 
0588 void SolarSystem::getRaDec(const Vec3& r1, double& ra, double& decl)
0589 {
0590   // convert equatorial vector r1 into RA and DEC (in HH.MMSS and DD.MMSS)
0591 
0592   double const degrad = M_PI / 180.0;
0593   Vec3 r2;
0594 
0595   r2 = carpol(r1);
0596   decl = r2[2] / degrad;
0597   ra = r2[1] / degrad;
0598   ra /= 15.0;
0599   if (ra < 0) ra += 24.0;
0600   
0601   decl = DegFDms(decl);
0602   ra = DegFDms(ra);
0603 
0604 }
0605 
0606 void SolarSystem::getSun (double& ra, double& decl)  // RA and Dec for the Sun
0607 {
0608   if (!ss_update_called) updateSolar();
0609   if (ss_central_body == 0)
0610    {
0611     ra = -100.0;
0612     decl = 0;
0613    }
0614   else getRaDec (ss_rs, ra, decl);
0615 } 
0616 
0617 void SolarSystem::getMoon (double& ra, double& decl)  // RA and Dec for the Moon
0618 {
0619   if (!ss_update_called) updateSolar();
0620   if (ss_central_body != 4)
0621    {
0622     ra = -100.0;
0623     decl = 0;
0624    }
0625   else getRaDec (ss_rm, ra, decl);
0626 } 
0627 
0628 void SolarSystem::getMercury (double& ra, double& decl)  // RA and Dec for Mercury
0629 {
0630   if (!ss_update_called) updateSolar();
0631   if (ss_central_body == 2)
0632    {
0633     ra = -100.0;
0634     decl = 0;
0635    }
0636   else getRaDec (ss_pmer, ra, decl);
0637 } 
0638 
0639 void SolarSystem::getVenus (double& ra, double& decl)  // RA and Dec for Venus
0640 {
0641   if (!ss_update_called) updateSolar();
0642   if (ss_central_body == 3)
0643    {
0644     ra = -100.0;
0645     decl = 0;
0646    }
0647   else getRaDec (ss_pven, ra, decl);
0648 } 
0649 
0650 void SolarSystem::getEarth (double& ra, double& decl)  // RA and Dec for Earth
0651 {
0652   if (!ss_update_called) updateSolar();
0653   if (ss_central_body == 4)
0654    {
0655     ra = -100.0;
0656     decl = 0;
0657    }
0658   else getRaDec (ss_pearth, ra, decl);
0659 } 
0660 
0661 void SolarSystem::getMars (double& ra, double& decl)  // RA and Dec for Mars
0662 {
0663   if (!ss_update_called) updateSolar();
0664   if (ss_central_body == 5)
0665    {
0666     ra = -100.0;
0667     decl = 0;
0668    }
0669   else getRaDec (ss_pmars, ra, decl);
0670 } 
0671 
0672 void SolarSystem::getJupiter (double& ra, double& decl)  // RA and Dec for Jupiter
0673 {
0674   if (!ss_update_called) updateSolar();
0675   if (ss_central_body == 6)
0676    {
0677     ra = -100.0;
0678     decl = 0;
0679    }
0680   else getRaDec (ss_pjup, ra, decl);
0681 } 
0682 
0683 void SolarSystem::getSaturn (double& ra, double& decl)  // RA and Dec for Saturn
0684 {
0685   if (!ss_update_called) updateSolar();
0686   if (ss_central_body == 7)
0687    {
0688     ra = -100.0;
0689     decl = 0;
0690    }
0691   else getRaDec (ss_psat, ra, decl);
0692 } 
0693 
0694 void SolarSystem::getUranus (double& ra, double& decl)  // RA and Dec for Uranus
0695 {
0696   if (!ss_update_called) updateSolar();
0697   if (ss_central_body == 8)
0698    {
0699     ra = -100.0;
0700     decl = 0;
0701    }
0702   else getRaDec (ss_pura, ra, decl);
0703 } 
0704 
0705 void SolarSystem::getNeptune (double& ra, double& decl)  // RA and Dec for Neptune
0706 {
0707   if (!ss_update_called) updateSolar();
0708   if (ss_central_body == 9)
0709    {
0710     ra = -100.0;
0711     decl = 0;
0712    }
0713   else getRaDec (ss_pnept, ra, decl);
0714 } 
0715 
0716 void SolarSystem::getIo (double& ra, double& decl)  // RA and Dec for Io
0717 {
0718   if (!ss_update_called) updateSolar();
0719   if (ss_central_body == 10)
0720    {
0721     ra = -100.0;
0722     decl = 0;
0723    }
0724   else getRaDec (ss_pio, ra, decl);
0725 } 
0726 
0727 void SolarSystem::getEuropa (double& ra, double& decl)  // RA and Dec for Europa
0728 {
0729   if (!ss_update_called) updateSolar();
0730   if (ss_central_body == 11)
0731    {
0732     ra = -100.0;
0733     decl = 0;
0734    }
0735   else getRaDec (ss_peuropa, ra, decl);
0736 } 
0737 
0738 void SolarSystem::getGanymede (double& ra, double& decl)  // RA and Dec for Ganymede
0739 {
0740   if (!ss_update_called) updateSolar();
0741   if (ss_central_body == 12)
0742    {
0743     ra = -100.0;
0744     decl = 0;
0745    }
0746   else getRaDec (ss_pganymede, ra, decl);
0747 } 
0748 
0749 void SolarSystem::getCallisto (double& ra, double& decl)  // RA and Dec for Callisto
0750 {
0751   if (!ss_update_called) updateSolar();
0752   if (ss_central_body == 13)
0753    {
0754     ra = -100.0;
0755     decl = 0;
0756    }
0757   else getRaDec (ss_pcallisto, ra, decl);
0758 } 
0759 
0760 void SolarSystem::getRhea (double& ra, double& decl)  // RA and Dec for Rhea
0761 {
0762   if (!ss_update_called) updateSolar();
0763   if (ss_central_body == 14)
0764    {
0765     ra = -100.0;
0766     decl = 0;
0767    }
0768   else getRaDec (ss_prhea, ra, decl);
0769 } 
0770 
0771 void SolarSystem::getTitan (double& ra, double& decl)  // RA and Dec for Titan
0772 {
0773   if (!ss_update_called) updateSolar();
0774   if (ss_central_body == 15)
0775    {
0776     ra = -100.0;
0777     decl = 0;
0778    }
0779   else getRaDec (ss_ptitan, ra, decl);
0780 } 
0781 
0782 void SolarSystem::getMimas (double& ra, double& decl)  // RA and Dec for Mimas
0783 {
0784   if (!ss_update_called) updateSolar();
0785   if (ss_central_body == 16)
0786    {
0787     ra = -100.0;
0788     decl = 0;
0789    }
0790   else getRaDec (ss_pmimas, ra, decl);
0791 } 
0792 
0793 void SolarSystem::getEnceladus (double& ra, double& decl)  // RA and Dec for Enceladus
0794 {
0795   if (!ss_update_called) updateSolar();
0796   if (ss_central_body == 17)
0797    {
0798     ra = -100.0;
0799     decl = 0;
0800    }
0801   else getRaDec (ss_penceladus, ra, decl);
0802 } 
0803 
0804 void SolarSystem::getDione (double& ra, double& decl)  // RA and Dec for Dione
0805 {
0806   if (!ss_update_called) updateSolar();
0807   if (ss_central_body == 18)
0808    {
0809     ra = -100.0;
0810     decl = 0;
0811    }
0812   else getRaDec (ss_pdione, ra, decl);
0813 } 
0814 
0815 void SolarSystem::getUser (double& ra, double& decl)  // RA and Dec for User
0816 {
0817   if (!ss_update_called) updateSolar();
0818   if (ss_central_body == -1)
0819    {
0820     ra = -100.0;
0821     decl = 0;
0822    }
0823   else getRaDec (ss_user, ra, decl);
0824 
0825 }
0826 
0827 void SolarSystem::getPhysSun (double &pdiam, double &pmag)
0828 {
0829  // Apparent diameter for the Sun in radians
0830 
0831   if (ss_central_body == 0)
0832    {
0833     pdiam = 0;
0834     pmag = 0;
0835 
0836     return;
0837    }; 
0838   if (!ss_update_called) updateSolar();
0839 
0840   pdiam = 0.00930495 / abs(ss_rs);
0841   pmag = -26.7 + 5.0 * log10(abs(ss_rs));
0842 } 
0843  
0844 void SolarSystem::getPhysMercury(double &pdiam, double &pmag, double &pphase)
0845 {
0846  // Physical elements Mercury 
0847 
0848  double ia, cp, cs, ps;
0849 
0850  if (ss_central_body == 2)
0851   {
0852    pdiam = 0;
0853    pmag = 0;
0854    pphase = 0;
0855 
0856    return;
0857   }; 
0858 
0859  if (!ss_update_called) updateSolar();
0860 
0861  cp = abs(ss_pmer);
0862  cs = abs(ss_rs);
0863  ps = abs(ss_rs - ss_pmer);
0864 
0865  pdiam = 3.24831e-05 / cp; // apparent diameter in radians
0866 
0867  ia = 2.0 * cp * ps;
0868  if (ia == 0) ia = 1.0; // this should never happen
0869 
0870  ia = (cp*cp + ps*ps - cs*cs) / ia;  // cos of phase angle
0871 
0872  pphase = 0.5 * (1.0 + ia);
0873 
0874  ia = acos(ia) / degrad;
0875  ia /= 100.0;
0876  pmag = -0.36 + 3.80*ia - 2.73*ia*ia + 2.00*ia*ia*ia;
0877  pmag = pmag + 5.0 * log10(ps * cp);
0878 }
0879 
0880 void SolarSystem::getPhysVenus(double &pdiam, double &pmag, double &pphase)
0881 {
0882  // Physical elements Venus 
0883 
0884  double ia, cp, cs, ps;
0885 
0886  if (ss_central_body == 3) 
0887   {
0888    pdiam = 0;
0889    pmag = 0;
0890    pphase = 0;
0891 
0892    return;
0893   }; 
0894 
0895  if (!ss_update_called) updateSolar();
0896 
0897  cp = abs(ss_pven);
0898  cs = abs(ss_rs);
0899  ps = abs(ss_rs - ss_pven);
0900 
0901  pdiam = 8.09089e-05 / cp; // apparent diameter in radians
0902 
0903  ia = 2.0 * cp * ps;
0904  if (ia == 0) ia = 1.0; // this should never happen
0905 
0906  ia = (cp*cp + ps*ps - cs*cs) / ia;  // cos of phase angle
0907 
0908  pphase = 0.5 * (1.0 + ia);
0909 
0910  ia = acos(ia) / degrad;
0911  ia /= 100.0;
0912  pmag = -4.29 + 0.09*ia + 2.39*ia*ia - 0.65*ia*ia*ia;
0913  pmag = pmag + 5.0 * log10(ps * cp);
0914 }
0915 
0916 void SolarSystem::getPhysEarth(double &pdiam, double &pmag, double &pphase)
0917 {
0918  // Physical elements Earth 
0919 
0920  double ia, cp, cs, ps;
0921 
0922  if (ss_central_body == 4) 
0923   {
0924    pdiam = 0;
0925    pmag = 0;
0926    pphase = 0;
0927 
0928    return;
0929   }; 
0930 
0931  if (!ss_update_called) updateSolar();
0932 
0933  cp = abs(ss_pearth);
0934  cs = abs(ss_rs);
0935  ps = abs(ss_rs - ss_pearth);
0936 
0937  pdiam = 8.52705e-05 / cp; // apparent diameter in radians
0938 
0939  ia = 2.0 * cp * ps;
0940  if (ia == 0) ia = 1.0; // this should never happen
0941 
0942  ia = (cp*cp + ps*ps - cs*cs) / ia;  // cos of phase angle
0943 
0944  pphase = 0.5 * (1.0 + ia);
0945 
0946  ia = acos(ia) / degrad;
0947  ia /= 100.0;
0948  pmag = -4.0 + 0.09*ia + 2.39*ia*ia - 0.65*ia*ia*ia;
0949  pmag = pmag + 5.0 * log10(ps * cp);
0950 }
0951 
0952 void SolarSystem::getPhysMars(double &pdiam, double &pmag, double &pphase)
0953 {
0954  // Physical elements Mars 
0955 
0956  double ia, cp, cs, ps;
0957 
0958  if (ss_central_body == 5) 
0959   {
0960    pdiam = 0;
0961    pmag = 0;
0962    pphase = 0;
0963 
0964    return;
0965   }; 
0966 
0967  if (!ss_update_called) updateSolar();
0968 
0969  cp = abs(ss_pmars);
0970  cs = abs(ss_rs);
0971  ps = abs(ss_rs - ss_pmars);
0972 
0973  pdiam = 4.54178e-05 / cp;  // apparent diameter in radians
0974 
0975  ia = 2.0 * cp * ps;
0976  if (ia == 0) ia = 1.0; // this should never happen
0977 
0978  ia = (cp*cp + ps*ps - cs*cs) / ia;  // cos of phase angle
0979 
0980  pphase = 0.5 * (1.0 + ia);
0981 
0982  ia = acos(ia) / degrad;
0983  if (ia > 39.0) ia = 39.0;  // limit to max angle for Mars from Earth
0984  pmag = -1.52 + 0.016*ia;
0985  pmag = pmag + 5.0 * log10(ps * cp);
0986 }
0987 
0988 void SolarSystem::getPhysJupiter(double &pdiam, double &pmag, double &pphase)
0989 {
0990  // Physical elements Jupiter 
0991 
0992  double ia, cp, cs, ps;
0993 
0994  if (ss_central_body == 6) 
0995   {
0996    pdiam = 0;
0997    pmag = 0;
0998    pphase = 0;
0999 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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  
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 
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 
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 
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 
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 
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 
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 
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 }