File indexing completed on 2025-01-05 03:58:43
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 }