customrotation.cpp
上传用户:center1979
上传日期:2022-07-26
资源大小:50633k
文件大小:33k
源码类别:

OpenGL

开发平台:

Visual C++

  1. // customrotation.cpp
  2. //
  3. // Custom rotation models for Solar System bodies.
  4. //
  5. // Copyright (C) 2008, the Celestia Development Team
  6. // Initial version by Chris Laurel, claurel@gmail.com
  7. //
  8. // This program is free software; you can redistribute it and/or
  9. // modify it under the terms of the GNU General Public License
  10. // as published by the Free Software Foundation; either version 2
  11. // of the License, or (at your option) any later version.
  12. #include <map>
  13. #include <string>
  14. #include <celengine/customrotation.h>
  15. #include <celengine/rotation.h>
  16. #include <celengine/astro.h>
  17. #include <celengine/precession.h>
  18. using namespace std;
  19. static map<string, RotationModel*> CustomRotationModels;
  20. static bool CustomRotationModelsInitialized = false;
  21. // Clamp secular terms in IAU rotation models to this number of centuries
  22. // from J2000. Extrapolating much further can lead to ridiculous results,
  23. // such as planets 'tipping over' Periodic terms are not clamped; their
  24. // validity over long time ranges is questionable, but extrapolating them
  25. // doesn't produce obviously absurd results.
  26. static const double IAU_SECULAR_TERM_VALID_CENTURIES = 50.0;
  27. // The P03 long period precession theory for Earth is valid for a one
  28. // million year time span centered on J2000. For dates outside far outside
  29. // that range, the polynomial terms produce absurd results.
  30. static const double P03LP_VALID_CENTURIES = 5000.0;
  31. /*! Base class for IAU rotation models. All IAU rotation models are in the
  32.  *  J2000.0 Earth equatorial frame.
  33.  */
  34. class IAURotationModel : public CachingRotationModel
  35. {
  36. public:
  37.     IAURotationModel(double _period) :
  38.         period(_period), flipped(false)
  39.     {
  40.     }
  41.     
  42.     virtual ~IAURotationModel() {}
  43.     
  44.     bool isPeriodic() const { return true; }
  45.     double getPeriod() const { return period; }
  46.     
  47.     virtual Quatd computeSpin(double t) const
  48.     {
  49.         // Time argument of IAU rotation models is actually day since J2000.0 TT, but
  50.         // Celestia uses TDB. The difference should be so minute as to be irrelevant.
  51.         t = t - astro::J2000;
  52.         if (flipped)
  53.             return Quatd::yrotation( degToRad(180.0 + meridian(t)));
  54.         else
  55.             return Quatd::yrotation(-degToRad(180.0 + meridian(t)));
  56.     }
  57.     
  58.     virtual Quatd computeEquatorOrientation(double t) const
  59.     {
  60.         double poleRA = 0.0;
  61.         double poleDec = 0.0;
  62.         
  63.         t = t - astro::J2000;
  64.         pole(t, poleRA, poleDec);
  65.         double node = poleRA + 90.0;
  66.         double inclination = 90.0 - poleDec;
  67.         
  68.         if (flipped)
  69.             return Quatd::xrotation(PI) * Quatd::xrotation(degToRad(-inclination)) * Quatd::yrotation(degToRad(-node));
  70.         else
  71.             return Quatd::xrotation(degToRad(-inclination)) * Quatd::yrotation(degToRad(-node));
  72.     }
  73.     
  74.     // Return the RA and declination (in degrees) of the rotation axis
  75.     virtual void pole(double t, double& ra, double& dec) const = 0;
  76.     
  77.     virtual double meridian(double t) const = 0;
  78. protected:
  79.     static void clamp_centuries(double& T)
  80.     {
  81.         if (T < -IAU_SECULAR_TERM_VALID_CENTURIES)
  82.             T = -IAU_SECULAR_TERM_VALID_CENTURIES;
  83.         else if (T > IAU_SECULAR_TERM_VALID_CENTURIES)
  84.             T = IAU_SECULAR_TERM_VALID_CENTURIES;
  85.     }
  86.     void setFlipped(bool _flipped)
  87.     {
  88.         flipped = _flipped;
  89.     }
  90.     
  91. private:
  92.     double period;
  93.     bool flipped;
  94. };
  95. /******* Earth rotation model *******/
  96. class EarthRotationModel : public CachingRotationModel
  97. {
  98. public:
  99.     EarthRotationModel()
  100.     {
  101.     }
  102.     
  103.     ~EarthRotationModel()
  104.     {
  105.     }
  106.     
  107.     Quatd computeSpin(double tjd) const
  108.     {
  109.         // TODO: Use a more accurate model for sidereal time
  110.         double t = tjd - astro::J2000;
  111.         double theta = 2 * PI * (t * 24.0 / 23.9344694 - 259.853 / 360.0);
  112.         return Quatd::yrotation(-theta);
  113.     }
  114.     
  115.     Quatd computeEquatorOrientation(double tjd) const
  116.     {
  117.         double T = (tjd - astro::J2000) / 36525.0;
  118.         
  119.         // Clamp T to the valid time range of the precession theory.
  120.         if (T < -P03LP_VALID_CENTURIES)
  121.             T = -P03LP_VALID_CENTURIES;
  122.         else if (T > P03LP_VALID_CENTURIES)
  123.             T = P03LP_VALID_CENTURIES;
  124.         
  125.         astro::PrecessionAngles prec = astro::PrecObliquity_P03LP(T);
  126.         astro::EclipticPole pole = astro::EclipticPrecession_P03LP(T);
  127.         
  128.         double obliquity = degToRad(prec.epsA / 3600);
  129.         double precession = degToRad(prec.pA / 3600);
  130.         
  131.         // Calculate the angles pi and Pi from the ecliptic pole coordinates
  132.         // P and Q:
  133.         //   P = sin(pi)*sin(Pi)
  134.         //   Q = sin(pi)*cos(Pi)
  135.         double P = pole.PA * 2.0 * PI / 1296000;
  136.         double Q = pole.QA * 2.0 * PI / 1296000;
  137.         double piA = asin(sqrt(P * P + Q * Q));
  138.         double PiA = atan2(P, Q);
  139.         // Calculate the rotation from the J2000 ecliptic to the ecliptic
  140.         // of date.
  141.         Quatd RPi = Quatd::zrotation(PiA);
  142.         Quatd rpi = Quatd::xrotation(piA);
  143.         Quatd eclRotation = ~RPi * rpi * RPi;
  144.         Quatd q = Quatd::xrotation(obliquity) * Quatd::zrotation(-precession) * ~eclRotation;
  145.         
  146.         // convert to Celestia's coordinate system
  147.         return Quatd::xrotation(PI / 2.0) * q * Quatd::xrotation(-PI / 2.0);
  148.     }
  149.     
  150.     double getPeriod() const
  151.     {
  152.         return 23.9344694 / 24.0;
  153.     }
  154.     bool isPeriodic() const
  155.     {
  156.         return true;
  157.     }
  158. };
  159. /******* IAU rotation models for the planets *******/
  160. /*! IAUPrecessingRotationModel is a rotation model with uniform rotation about
  161.  *  a pole that precesses linearly in RA and declination.
  162.  */
  163. class IAUPrecessingRotationModel : public IAURotationModel
  164. {
  165. public:
  166.     
  167.     /*! rotationRate is in degrees per Julian day
  168.      *  pole precession is in degrees per Julian century
  169.      */
  170.     IAUPrecessingRotationModel(double _poleRA,
  171.                                double _poleRARate,
  172.                                double _poleDec,
  173.                                double _poleDecRate,
  174.                                double _meridianAtEpoch,
  175.                                double _rotationRate) :
  176.     IAURotationModel(std::abs(360.0 / _rotationRate)),
  177.         poleRA(_poleRA),
  178.         poleRARate(_poleRARate),
  179.         poleDec(_poleDec),
  180.         poleDecRate(_poleDecRate),
  181.         meridianAtEpoch(_meridianAtEpoch),
  182.         rotationRate(_rotationRate)
  183.     {
  184.         if (rotationRate < 0.0)
  185.             setFlipped(true);
  186.     }
  187.     
  188.     void pole(double d, double& ra, double &dec) const
  189.     {
  190.         double T = d / 36525.0;
  191.         clamp_centuries(T);
  192.         ra = poleRA + poleRARate * T;
  193.         dec = poleDec + poleDecRate * T;
  194.     }
  195.     
  196.     double meridian(double d) const
  197.     {
  198.         return meridianAtEpoch + rotationRate * d;
  199.     }
  200.     
  201. private:
  202.     double poleRA;
  203.     double poleRARate;
  204.     double poleDec;
  205.     double poleDecRate;
  206.     double meridianAtEpoch;
  207.     double rotationRate;
  208. };
  209. class IAUNeptuneRotationModel : public IAURotationModel
  210. {
  211. public:
  212.     IAUNeptuneRotationModel() : IAURotationModel(360.0 / 536.3128492) {}
  213.     
  214.     void pole(double d, double& ra, double &dec) const
  215.     {
  216.         double T = d / 36525.0;
  217.         double N = degToRad(357.85 + 52.316 * T);
  218.         ra = 299.36 + 0.70 * sin(N);
  219.         dec = 43.46 - 0.51 * cos(N);
  220.     }
  221.     
  222.     double meridian(double d) const
  223.     {
  224.         double T = d / 36525.0;
  225.         double N = degToRad(357.85 + 52.316 * T);
  226.         return 253.18 + 536.3128492 * d - 0.48 * sin(N);
  227.     }    
  228. };
  229. /*! IAU rotation model for the Moon.
  230.  *  From the IAU/IAG Working Group on Cartographic Coordinates and Rotational Elements:
  231.  *  http://astrogeology.usgs.gov/Projects/WGCCRE/constants/iau2000_table2.html
  232.  */
  233. class IAULunarRotationModel : public IAURotationModel
  234. {
  235. public:
  236.     IAULunarRotationModel() : IAURotationModel(360.0 / 13.17635815) {}
  237.     
  238.     void calcArgs(double d, double E[14]) const
  239.     {
  240.         E[1]  = degToRad(125.045 -  0.0529921 * d);
  241.         E[2]  = degToRad(250.089 -  0.1059842 * d);
  242.         E[3]  = degToRad(260.008 + 13.012009 * d);
  243.         E[4]  = degToRad(176.625 + 13.3407154 * d);
  244.         E[5]  = degToRad(357.529 +  0.9856993 * d);
  245.         E[6]  = degToRad(311.589 + 26.4057084 * d);
  246.         E[7]  = degToRad(134.963 + 13.0649930 * d);
  247.         E[8]  = degToRad(276.617 +  0.3287146 * d);
  248.         E[9]  = degToRad( 34.226 +  1.7484877 * d);
  249.         E[10] = degToRad( 15.134 -  0.1589763 * d);
  250.         E[11] = degToRad(119.743 +  0.0036096 * d);
  251.         E[12] = degToRad(239.961 +  0.1643573 * d);
  252.         E[13] = degToRad( 25.053 + 12.9590088 * d);
  253.     }
  254.     
  255.     void pole(double d, double& ra, double& dec) const
  256.     {
  257.         double T = d / 36525.0;
  258.         clamp_centuries(T);
  259.         double E[14];
  260.         calcArgs(d, E);
  261.         
  262.         ra = 269.9949
  263.             + 0.0013*T
  264.             - 3.8787 * sin(E[1])
  265.             - 0.1204 * sin(E[2])
  266.             + 0.0700 * sin(E[3])
  267.             - 0.0172 * sin(E[4])
  268.             + 0.0072 * sin(E[6])
  269.             - 0.0052 * sin(E[10])
  270.             + 0.0043 * sin(E[13]);
  271.             
  272.         dec = 66.5392
  273.             + 0.0130 * T
  274.             + 1.5419 * cos(E[1])
  275.             + 0.0239 * cos(E[2])
  276.             - 0.0278 * cos(E[3])
  277.             + 0.0068 * cos(E[4])
  278.             - 0.0029 * cos(E[6])
  279.             + 0.0009 * cos(E[7])
  280.             + 0.0008 * cos(E[10])
  281.             - 0.0009 * cos(E[13]);
  282.             
  283.             
  284.     }
  285.     
  286.     double meridian(double d) const
  287.     {
  288.         double E[14];
  289.         calcArgs(d, E);
  290.         // d^2 represents slowing of lunar rotation as the Moon recedes
  291.         // from the Earth. This may need to be clamped at some very large
  292.         // time range (1 Gy?)
  293.         return (38.3213
  294.                 + 13.17635815 * d
  295.                 - 1.4e-12 * d * d
  296.                 + 3.5610 * sin(E[1])
  297.                 + 0.1208 * sin(E[2])
  298.                 - 0.0642 * sin(E[3])
  299.                 + 0.0158 * sin(E[4])
  300.                 + 0.0252 * sin(E[5])
  301.                 - 0.0066 * sin(E[6])
  302.                 - 0.0047 * sin(E[7])
  303.                 - 0.0046 * sin(E[8])
  304.                 + 0.0028 * sin(E[9])
  305.                 + 0.0052 * sin(E[10])
  306.                 + 0.0040 * sin(E[11])
  307.                 + 0.0019 * sin(E[12])
  308.                 - 0.0044 * sin(E[13]));
  309.     }
  310. };
  311. // Rotations of Martian, Jovian, and Uranian satellites from IAU/IAG Working group 
  312. // on Cartographic Coordinates and Rotational Elements (Corrected for known errata
  313. // as of 17 Feb 2006)
  314. // See: http://astrogeology.usgs.gov/Projects/WGCCRE/constants/iau2000_table2.html
  315. class IAUPhobosRotationModel : public IAURotationModel
  316. {
  317. public:
  318.     IAUPhobosRotationModel() : IAURotationModel(360.0 / 1128.8445850) {}
  319.     
  320.     void pole(double t, double& ra, double& dec) const
  321.     {
  322.         double T = t / 36525.0;
  323.         double M1 = degToRad(169.51 - 0.04357640 * t);
  324.         clamp_centuries(T);
  325.         ra  = 317.68 - 0.108 * T + 1.79 * sin(M1);
  326.         dec =  52.90 - 0.061 * T - 1.08 * cos(M1);
  327.     }
  328.     
  329.     double meridian(double t) const
  330.     {
  331.         // Note: negative coefficient of T^2 term for meridian angle indicates faster
  332.         // rotation as Phobos's orbit evolves inward toward Mars
  333.         double T = t / 36525.0;
  334.         double M1 = degToRad(169.51 - 0.04357640 * t);
  335.         double M2 = degToRad(192.93 + 1128.4096700 * t + 8.864 * T * T);
  336.         return 35.06 + 1128.8445850 * t + 8.864 * T * T - 1.42 * sin(M1) - 0.78 * sin(M2);
  337.     }
  338. };
  339. class IAUDeimosRotationModel : public IAURotationModel
  340. {
  341. public:
  342.     IAUDeimosRotationModel() : IAURotationModel(360.0 / 285.1618970) {}
  343.     
  344.     void pole(double t, double& ra, double& dec) const
  345.     {
  346.         double T = t / 36525.0;
  347.         double M3 = degToRad(53.47 - 0.0181510 * t);
  348.         clamp_centuries(T);
  349.         ra  = 316.65 - 0.108 * T + 2.98 * sin(M3);
  350.         dec =  53.52 - 0.061 * T - 1.78 * cos(M3);
  351.     }
  352.     
  353.     double meridian(double t) const
  354.     {
  355.         // Note: positive coefficient of T^2 term for meridian angle indicates slowing
  356.         // rotation as Deimos's orbit evolves outward from Mars
  357.         double T = t / 36525.0;
  358.         double M3 = degToRad(53.47 - 0.0181510 * t);
  359.         return 79.41 + 285.1618970 * t + 0.520 * T * T - 2.58 * sin(M3) + 0.19 * cos(M3);
  360.     }
  361. };
  362. /****** Satellites of Jupiter ******/
  363.         
  364. class IAUAmaltheaRotationModel : public IAURotationModel
  365. {
  366. public:
  367.     IAUAmaltheaRotationModel() : IAURotationModel(360.0 / 722.6314560) {}
  368.     
  369.     void pole(double t, double& ra, double& dec) const
  370.     {
  371.         double T = t / 36525.0;
  372.         double J1 = degToRad(73.32 + 91472.9 * T);
  373.         clamp_centuries(T);
  374.         ra = 268.05 - 0.009 * T - 0.84 * sin(J1) + 0.01 * sin(2.0 * J1);
  375.         dec = 64.49 + 0.003 * T - 0.36 * cos(J1);
  376.     }
  377.     
  378.     double meridian(double t) const
  379.     {
  380.         double T = t / 36525.0;
  381.         double J1 = degToRad(73.32 + 91472.9 * T);
  382.         return 231.67 + 722.6314560 * t + 0.76 * sin(J1) - 0.01 * sin(2.0 * J1);
  383.     }
  384. };
  385. class IAUThebeRotationModel : public IAURotationModel
  386. {
  387. public:
  388.     IAUThebeRotationModel() : IAURotationModel(360.0 / 533.7004100) {}
  389.     
  390.     void pole(double t, double& ra, double& dec) const
  391.     {
  392.         double T = t / 36525.0;
  393.         double J2 = degToRad(24.62 + 45137.2 * T);
  394.         clamp_centuries(T);
  395.         ra = 268.05 - 0.009 * T - 2.11 * sin(J2) + 0.04 * sin(2.0 * J2);
  396.         dec = 64.49 + 0.003 * T - 0.91 * cos(J2) + 0.01 * cos(2.0 * J2);        
  397.     }
  398.     
  399.     double meridian(double t) const
  400.     {
  401.         double T = t / 36525.0;
  402.         double J2 = degToRad(24.62 + 45137.2 * T);
  403.         return 8.56 + 533.7004100 * t + 1.91 * sin(J2) - 0.04 * sin(2.0 * J2);
  404.     }    
  405. };
  406. class IAUIoRotationModel : public IAURotationModel
  407. {
  408. public:
  409.     IAUIoRotationModel() : IAURotationModel(360.0 / 203.4889538) {}
  410.     
  411.     void pole(double t, double& ra, double& dec) const
  412.     {
  413.         double T = t / 36525.0;
  414.         double J3 = degToRad(283.90 + 4850.7 * T);
  415.         double J4 = degToRad(355.80 + 1191.3 * T);
  416.         clamp_centuries(T);
  417.         ra = 268.05 - 0.009 * T + 0.094 * sin(J3) + 0.024 * sin(J4);
  418.         dec = 64.49 + 0.003 * T + 0.040 * cos(J3) + 0.011 * cos(J4);        
  419.     }
  420.     
  421.     double meridian(double t) const
  422.     {
  423.         double T = t / 36525.0;
  424.         double J3 = degToRad(283.90 + 4850.7 * T);
  425.         double J4 = degToRad(355.80 + 1191.3 * T);
  426.         return 200.39 + 203.4889538 * t - 0.085 * sin(J3) - 0.022 * sin(J4);
  427.     }    
  428. };
  429. class IAUEuropaRotationModel : public IAURotationModel
  430. {
  431. public:
  432.     IAUEuropaRotationModel() : IAURotationModel(360.0 / 101.3747235) {}
  433.     
  434.     void pole(double t, double& ra, double& dec) const
  435.     {
  436.         double T = t / 36525.0;
  437.         double J4 = degToRad(355.80 + 1191.3 * T);
  438.         double J5 = degToRad(119.90 + 262.1 * T);
  439.         double J6 = degToRad(229.80 + 64.3 * T);
  440.         double J7 = degToRad(352.35 + 2382.6 * T);
  441.         clamp_centuries(T);
  442.         ra = 268.05 - 0.009 * T + 1.086 * sin(J4) + 0.060 * sin(J5) + 0.015 * sin(J6) + 0.009 * sin(J7);
  443.         dec = 64.49 + 0.003 * T + 0.486 * cos(J4) + 0.026 * cos(J5) + 0.007 * cos(J6) + 0.002 * cos(J7);        
  444.     }
  445.     
  446.     double meridian(double t) const
  447.     {
  448.         double T = t / 36525.0;
  449.         double J4 = degToRad(355.80 + 1191.3 * T);
  450.         double J5 = degToRad(119.90 + 262.1 * T);
  451.         double J6 = degToRad(229.80 + 64.3 * T);
  452.         double J7 = degToRad(352.35 + 2382.6 * T);
  453.         return 36.022 + 101.3747235 * t - 0.980 * sin(J4) - 0.054 * sin(J5) - 0.014 * sin(J6) - 0.008 * sin(J7);
  454.     }    
  455. };
  456. class IAUGanymedeRotationModel : public IAURotationModel
  457. {
  458. public:
  459.     IAUGanymedeRotationModel() : IAURotationModel(360.0 / 50.3176081) {}
  460.     
  461.     void pole(double t, double& ra, double& dec) const
  462.     {
  463.         double T = t / 36525.0;
  464.         double J4 = degToRad(355.80 + 1191.3 * T);
  465.         double J5 = degToRad(119.90 + 262.1 * T);
  466.         double J6 = degToRad(229.80 + 64.3 * T);
  467.         clamp_centuries(T);
  468.         ra = 268.05 - 0.009 * T - 0.037 * sin(J4) + 0.431 * sin(J5) + 0.091 * sin(J6);
  469.         dec = 64.49 + 0.003 * T - 0.016 * cos(J4) + 0.186 * cos(J5) + 0.039 * cos(J6);        
  470.     }
  471.     
  472.     double meridian(double t) const
  473.     {
  474.         double T = t / 36525.0;
  475.         double J4 = degToRad(355.80 + 1191.3 * T);
  476.         double J5 = degToRad(119.90 + 262.1 * T);
  477.         double J6 = degToRad(229.80 + 64.3 * T);
  478.         return 44.064 + 50.3176081 * t + 0.033 * sin(J4) - 0.389 * sin(J5) - 0.082 * sin(J6);
  479.     }    
  480. };
  481. class IAUCallistoRotationModel : public IAURotationModel
  482. {
  483. public:
  484.     IAUCallistoRotationModel() : IAURotationModel(360.0 / 21.5710715) {}
  485.     
  486.     void pole(double t, double& ra, double& dec) const
  487.     {
  488.         double T = t / 36525.0;
  489.         double J5 = degToRad(119.90 + 262.1 * T);
  490.         double J6 = degToRad(229.80 + 64.3 * T);
  491.         double J8 = degToRad(113.35 + 6070.0 * T);
  492.         clamp_centuries(T);
  493.         ra = 268.05 - 0.009 * T - 0.068 * sin(J5) + 0.590 * sin(J6) + 0.010 * sin(J8);
  494.         dec = 64.49 + 0.003 * T - 0.029 * cos(J5) + 0.254 * cos(J6) - 0.004 * cos(J8);        
  495.     }
  496.     
  497.     double meridian(double t) const
  498.     {
  499.         double T = t / 36525.0;
  500.         double J5 = degToRad(119.90 + 262.1 * T);
  501.         double J6 = degToRad(229.80 + 64.3 * T);
  502.         double J8 = degToRad(113.35 + 6070.0 * T);
  503.         return 259.51 + 21.5710715 * t + 0.061 * sin(J5) - 0.533 * sin(J6) - 0.009 * sin(J8);
  504.     }    
  505. };
  506. /*
  507. S1 = 353.32 + 75706.7 * T
  508. S2 = 28.72 + 75706.7 * T
  509. S3 = 177.40 - 36505.5 * T
  510. S4 = 300.00 - 7225.9 * T
  511. S5 = 53.59 - 8968.6 * T
  512. S6 = 143.38 - 10553.5 * T
  513. S7 = 345.20 - 1016.3 * T
  514. S8 = 29.80 - 52.1 * T
  515. S9 = 316.45 + 506.2 * T
  516. */
  517. // Rotations of Saturnian satellites from Seidelmann, _Explanatory Supplement to the
  518. // Astronomical Almanac_ (1992).
  519. class IAUMimasRotationModel : public IAURotationModel
  520. {
  521. public:
  522.     IAUMimasRotationModel() : IAURotationModel(360.0 / 381.9945550) {}
  523.     
  524.     void pole(double t, double& ra, double& dec) const
  525.     {
  526.         double T = t / 36525.0;
  527.         double S3 = degToRad(177.40 - 36505.5 * T);
  528.         clamp_centuries(T);
  529.         ra = 40.66 - 0.036 * T + 13.56 * sin(S3);
  530.         dec = 83.52 - 0.004 * T - 1.53 * cos(S3);
  531.     }
  532.     
  533.     double meridian(double t) const
  534.     {
  535.         double T = t / 36525.0;
  536.         double S3 = degToRad(177.40 - 36505.5 * T);
  537.         double S9 = degToRad(316.45 + 506.2 * T);
  538.         return 337.46 + 381.9945550 * t - 13.48 * sin(S3) - 44.85 * sin(S9);        
  539.     }
  540. };
  541. class IAUEnceladusRotationModel : public IAURotationModel
  542. {
  543. public:
  544.     IAUEnceladusRotationModel() : IAURotationModel(360.0 / 262.7318996) {}
  545.     
  546.     void pole(double t, double& ra, double& dec) const
  547.     {
  548.         double T = t / 36525.0;
  549.         clamp_centuries(T);
  550.         ra = 40.66 - 0.036 * T;
  551.         dec = 83.52 - 0.004 * T;
  552.     }
  553.     
  554.     double meridian(double t) const
  555.     {
  556.         return 2.82 + 262.7318996 * t;
  557.     }
  558. };
  559. class IAUTethysRotationModel : public IAURotationModel
  560. {
  561. public:
  562.     IAUTethysRotationModel() : IAURotationModel(360.0 / 190.6979085) {}
  563.     
  564.     void pole(double t, double& ra, double& dec) const
  565.     {
  566.         double T = t / 36525.0;
  567.         double S4 = degToRad(300.00 - 7225.9 * T);
  568.         clamp_centuries(T);
  569.         ra = 40.66 - 0.036 * T - 9.66 * sin(S4);
  570.         dec = 83.52 - 0.004 * T - 1.09 * cos(S4);
  571.     }
  572.     
  573.     double meridian(double t) const
  574.     {
  575.         double T = t / 36525.0;
  576.         double S4 = degToRad(300.00 - 7225.9 * T);
  577.         double S9 = degToRad(316.45 + 506.2 * T);
  578.         return 10.45 + 190.6979085 * t - 9.60 * sin(S4) + 2.23 * sin(S9);        
  579.     }
  580. };
  581. class IAUTelestoRotationModel : public IAURotationModel
  582. {
  583. public:
  584.     IAUTelestoRotationModel() : IAURotationModel(360.0 / 190.6979330) {}
  585.     
  586.     void pole(double t, double& ra, double& dec) const
  587.     {
  588.         double T = t / 36525.0;
  589.         clamp_centuries(T);
  590.         ra = 50.50 - 0.036 * T;
  591.         dec = 84.06 - 0.004 * T;
  592.     }
  593.     
  594.     double meridian(double t) const
  595.     {
  596.         return 56.88 + 190.6979330 * t;
  597.     }
  598. };
  599. class IAUCalypsoRotationModel : public IAURotationModel
  600. {
  601. public:
  602.     IAUCalypsoRotationModel() : IAURotationModel(360.0 / 190.6742373) {}
  603.     
  604.     void pole(double t, double& ra, double& dec) const
  605.     {
  606.         double T = t / 36525.0;
  607.         double S5 = degToRad(53.59 - 8968.6 * T);
  608.         clamp_centuries(T);
  609.         ra = 40.58 - 0.036 * T - 13.943 * sin(S5) - 1.686 * sin(2.0 * S5);
  610.         dec = 83.43 - 0.004 * T - 1.572 * cos(S5) + 0.095 * cos(2.0 * S5);
  611.     }
  612.     
  613.     double meridian(double t) const
  614.     {
  615.         double T = t / 36525.0;
  616.         double S5 = degToRad(53.59 - 8968.6 * T);
  617.         return 149.36 + 190.6742373 * t - 13.849 * sin(S5) + 1.685 * sin(2.0 * S5);
  618.     }
  619. };
  620. class IAUDioneRotationModel : public IAURotationModel
  621. {
  622. public:
  623.     IAUDioneRotationModel() : IAURotationModel(360.0 / 131.5349316) {}
  624.     
  625.     void pole(double t, double& ra, double& dec) const
  626.     {
  627.         double T = t / 36525.0;
  628.         clamp_centuries(T);
  629.         ra = 40.66 - 0.036 * T;
  630.         dec = 83.52 - 0.004 * T;
  631.     }
  632.     
  633.     double meridian(double t) const
  634.     {
  635.         return 357.00 + 131.5349316 * t;
  636.     }
  637. };
  638. class IAUHeleneRotationModel : public IAURotationModel
  639. {
  640. public:
  641.     IAUHeleneRotationModel() : IAURotationModel(360.0 / 131.6174056) {}
  642.     
  643.     void pole(double t, double& ra, double& dec) const
  644.     {
  645.         double T = t / 36525.0;
  646.         double S6 = degToRad(143.38 - 10553.5 * T);
  647.         clamp_centuries(T);
  648.         ra = 40.58 - 0.036 * T + 1.662 * sin(S6) + 0.024 * sin(2.0 * S6);
  649.         dec = 83.52 - 0.004 * T - 0.187 * cos(S6) + 0.095 * cos(2.0 * S6);
  650.     }
  651.     
  652.     double meridian(double t) const
  653.     {
  654.         double T = t / 36525.0;
  655.         double S6 = degToRad(143.38 - 10553.5 * T);
  656.         return 245.39 + 131.6174056 * t - 1.651 * sin(S6) + 0.024 * sin(2.0 * S6);
  657.     }
  658. };
  659. class IAURheaRotationModel : public IAURotationModel
  660. {
  661. public:
  662.     IAURheaRotationModel() : IAURotationModel(360.0 / 79.6900478) {}
  663.     
  664.     void pole(double t, double& ra, double& dec) const
  665.     {
  666.         double T = t / 36525.0;
  667.         double S7 = degToRad(345.20 - 1016.3 * T);
  668.         clamp_centuries(T);
  669.         ra = 40.38 - 0.036 * T + 3.10 * sin(S7);
  670.         dec = 83.55 - 0.004 * T - 0.35 * cos(S7);
  671.     }
  672.     
  673.     double meridian(double t) const
  674.     {
  675.         double T = t / 36525.0;
  676.         double S7 = degToRad(345.20 - 1016.3 * T);
  677.         return 235.16 + 79.6900478 * t - 1.651 - 3.08 * sin(S7);
  678.     }
  679. };
  680. class IAUTitanRotationModel : public IAURotationModel
  681. {
  682. public:
  683.     IAUTitanRotationModel() : IAURotationModel(360.0 / 22.5769768) {}
  684.     
  685.     void pole(double t, double& ra, double& dec) const
  686.     {
  687.         double T = t / 36525.0;
  688.         double S8 = degToRad(29.80 - 52.1 * T);
  689.         clamp_centuries(T);
  690.         ra = 36.41 - 0.036 * T + 2.66 * sin(S8);
  691.         dec = 83.94 - 0.004 * T - 0.30 * cos(S8);
  692.     }
  693.     
  694.     double meridian(double t) const
  695.     {
  696.         double T = t / 36525.0;
  697.         double S8 = degToRad(29.80 - 52.1 * T);
  698.         return 189.64 + 22.5769768 * t - 2.64 * sin(S8);
  699.     }
  700. };
  701. class IAUIapetusRotationModel : public IAURotationModel
  702. {
  703. public:
  704.     IAUIapetusRotationModel() : IAURotationModel(360.0 / 4.5379572) {}
  705.     
  706.     void pole(double t, double& ra, double& dec) const
  707.     {
  708.         double T = t / 36525.0;
  709.         clamp_centuries(T);
  710.         ra = 318.16 - 3.949 * T;
  711.         dec = 75.03 - 1.142 * T;
  712.     }
  713.     
  714.     double meridian(double t) const
  715.     {
  716.         return 350.20 + 4.5379572 * t;
  717.     }
  718. };
  719. class IAUPhoebeRotationModel : public IAURotationModel
  720. {
  721. public:
  722.     IAUPhoebeRotationModel() : IAURotationModel(360.0 / 22.5769768) {}
  723.     
  724.     void pole(double t, double& ra, double& dec) const
  725.     {
  726.         double T = t / 36525.0;
  727.         clamp_centuries(T);
  728.         ra = 355.16;
  729.         dec = 68.70 - 1.143 * T;
  730.     }
  731.     
  732.     double meridian(double t) const
  733.     {
  734.         return 304.70 + 930.8338720 * t;
  735.     }
  736. };
  737. class IAUMirandaRotationModel : public IAURotationModel
  738. {
  739. public:
  740.     IAUMirandaRotationModel() : IAURotationModel(360.0 / 254.6906892) { setFlipped(true); }
  741.     
  742.     void pole(double t, double& ra, double& dec) const
  743.     {
  744.         double T = t / 36525.0;
  745.         double U11 = degToRad(102.23 - 2024.22 * T);
  746.         ra =  257.43 + 4.41 * sin(U11) - 0.04 * sin(2.0 * U11);
  747.         dec = -15.08 + 4.25 * cos(U11) - 0.02 * cos(2.0 * U11);
  748.     }
  749.     
  750.     double meridian(double t) const
  751.     {
  752.         double T = t / 36525.0;
  753.         double U11 = degToRad(102.23 - 2024.22 * T);
  754.         double U12 = degToRad(316.41 + 2863.96 * T);
  755.         return 30.70 - 254.6906892 * t
  756.                - 1.27 * sin(U12) + 0.15 * sin(2.0 * U12)
  757.                + 1.15 * sin(U11) - 0.09 * sin(2.0 * U11);
  758.     }
  759. };
  760. class IAUArielRotationModel : public IAURotationModel
  761. {
  762. public:
  763.     IAUArielRotationModel() : IAURotationModel(360.0 / 142.8356681) { setFlipped(true); }
  764.     
  765.     void pole(double t, double& ra, double& dec) const
  766.     {
  767.         double T = t / 36525.0;
  768.         double U13 = degToRad(304.01 - 51.94 * T);
  769.         ra =  257.43 + 0.29 * sin(U13);
  770.         dec = -15.10 + 0.28 * cos(U13);
  771.     }
  772.     
  773.     double meridian(double t) const
  774.     {
  775.         double T = t / 36525.0;
  776.         double U12 = degToRad(316.41 + 2863.96 * T);
  777.         double U13 = degToRad(304.01 - 51.94 * T);
  778.         return 156.22 - 142.8356681 * t + 0.05 * sin(U12) + 0.08 * sin(U13);
  779.     }
  780. };
  781. class IAUUmbrielRotationModel : public IAURotationModel
  782. {
  783. public:
  784.     IAUUmbrielRotationModel() : IAURotationModel(360.0 / 86.8688923) { setFlipped(true); }
  785.     
  786.     void pole(double t, double& ra, double& dec) const
  787.     {
  788.         double T = t / 36525.0;
  789.         double U14 = degToRad(308.71 - 93.17 * T);
  790.         ra =  257.43 + 0.21 * sin(U14);
  791.         dec = -15.10 + 0.20 * cos(U14);
  792.     }
  793.     
  794.     double meridian(double t) const
  795.     {
  796.         double T = t / 36525.0;
  797.         double U12 = degToRad(316.41 + 2863.96 * T);
  798.         double U14 = degToRad(308.71 - 93.17 * T);
  799.         return 108.05 - 86.8688923 * t - 0.09 * sin(U12) + 0.06 * sin(U14);
  800.     }
  801. };
  802. class IAUTitaniaRotationModel : public IAURotationModel
  803. {
  804. public:
  805.     IAUTitaniaRotationModel() : IAURotationModel(360.0 / 41.351431) { setFlipped(true); }
  806.     
  807.     void pole(double t, double& ra, double& dec) const
  808.     {
  809.         double T = t / 36525.0;
  810.         double U15 = degToRad(340.82 - 75.32 * T);
  811.         ra =  257.43 + 0.29 * sin(U15);
  812.         dec = -15.10 + 0.28 * cos(U15);
  813.     }
  814.     
  815.     double meridian(double t) const
  816.     {
  817.         double T = t / 36525.0;
  818.         double U15 = degToRad(340.82 - 75.32 * T);
  819.         return 77.74 - 41.351431 * t + 0.08 * sin(U15);
  820.     }
  821. };
  822. class IAUOberonRotationModel : public IAURotationModel
  823. {
  824. public:
  825.     IAUOberonRotationModel() : IAURotationModel(360.0 / 26.7394932) { setFlipped(true); }
  826.     
  827.     void pole(double t, double& ra, double& dec) const
  828.     {
  829.         double T = t / 36525.0;
  830.         double U16 = degToRad(259.14 - 504.81 * T);
  831.         ra =  257.43 + 0.16 * sin(U16);
  832.         dec = -15.10 + 0.16 * cos(U16);
  833.     }
  834.     
  835.     double meridian(double t) const
  836.     {
  837.         double T = t / 36525.0;
  838.         double U16 = degToRad(259.14 - 504.81 * T);
  839.         return 6.77 - 26.7394932 * t + 0.04 * sin(U16);
  840.     }
  841. };
  842. RotationModel*
  843. GetCustomRotationModel(const std::string& name)
  844. {
  845.     // Initialize the custom rotation model table.
  846.     if (!CustomRotationModelsInitialized)
  847.     {
  848.         CustomRotationModelsInitialized = true;
  849.         
  850.         CustomRotationModels["earth-p03lp"] = new EarthRotationModel();
  851.         
  852.         // IAU rotation elements for the planets
  853.         CustomRotationModels["iau-mercury"] = new IAUPrecessingRotationModel(281.01, -0.033,
  854.                                                                              61.45, -0.005,
  855.                                                                              329.548, 6.1385025);
  856.         CustomRotationModels["iau-venus"]   = new IAUPrecessingRotationModel(272.76, 0.0,
  857.                                                                              67.16, 0.0,
  858.                                                                              160.20, -1.4813688);
  859.         CustomRotationModels["iau-earth"]   = new IAUPrecessingRotationModel(0.0, -0.641,
  860.                                                                              90.0, -0.557,
  861.                                                                              190.147, 360.9856235);
  862.         CustomRotationModels["iau-mars"]    = new IAUPrecessingRotationModel(317.68143, -0.1061,
  863.                                                                              52.88650, -0.0609,
  864.                                                                              176.630, 350.89198226);
  865.         CustomRotationModels["iau-jupiter"] = new IAUPrecessingRotationModel(268.05, -0.009,
  866.                                                                              64.49, -0.003,
  867.                                                                              284.95, 870.5366420);
  868.         CustomRotationModels["iau-saturn"]  = new IAUPrecessingRotationModel(40.589, -0.036,
  869.                                                                              83.537, -0.004,
  870.                                                                              38.90, 810.7939024);
  871.         CustomRotationModels["iau-uranus"]  = new IAUPrecessingRotationModel(257.311, 0.0,
  872.                                                                              -15.175, 0.0,
  873.                                                                              203.81, -501.1600928);
  874.         CustomRotationModels["iau-neptune"] = new IAUNeptuneRotationModel();
  875.         CustomRotationModels["iau-pluto"]   = new IAUPrecessingRotationModel(313.02, 0.0,
  876.                                                                              9.09, 0.0,
  877.                                                                              236.77, -56.3623195);
  878.        
  879.         // IAU elements for satellite of Earth
  880.         CustomRotationModels["iau-moon"] = new IAULunarRotationModel();
  881.         
  882.         // IAU elements for satellites of Mars
  883.         CustomRotationModels["iau-phobos"] = new IAUPhobosRotationModel();
  884.         CustomRotationModels["iau-deimos"] = new IAUDeimosRotationModel();
  885.         
  886.         // IAU elements for satellites of Jupiter
  887.         CustomRotationModels["iau-metis"]    = new IAUPrecessingRotationModel(268.05, -0.009,
  888.                                                                               64.49, 0.003,
  889.                                                                               346.09, 1221.2547301);
  890.         CustomRotationModels["iau-adrastea"] = new IAUPrecessingRotationModel(268.05, -0.009,
  891.                                                                               64.49, 0.003,
  892.                                                                               33.29, 1206.9986602);
  893.         CustomRotationModels["iau-amalthea"] = new IAUAmaltheaRotationModel();
  894.         CustomRotationModels["iau-thebe"]    = new IAUThebeRotationModel();
  895.         CustomRotationModels["iau-io"]       = new IAUIoRotationModel();
  896.         CustomRotationModels["iau-europa"]   = new IAUEuropaRotationModel();
  897.         CustomRotationModels["iau-ganymede"] = new IAUGanymedeRotationModel();
  898.         CustomRotationModels["iau-callisto"] = new IAUCallistoRotationModel();
  899.         
  900.         // IAU elements for satellites of Saturn
  901.         CustomRotationModels["iau-pan"]        = new IAUPrecessingRotationModel(40.6, -0.036,
  902.                                                                                 83.5, -0.004,
  903.                                                                                 48.8, 626.0440000);
  904.         CustomRotationModels["iau-atlas"]      = new IAUPrecessingRotationModel(40.6, -0.036,
  905.                                                                                 83.5, -0.004,
  906.                                                                                 137.88, 598.3060000);
  907.         CustomRotationModels["iau-prometheus"] = new IAUPrecessingRotationModel(40.6, -0.036,
  908.                                                                                 83.5, -0.004,
  909.                                                                                 296.14, 587.289000);
  910.         CustomRotationModels["iau-pandora"]    = new IAUPrecessingRotationModel(40.6, -0.036,
  911.                                                                                 83.5, -0.004,
  912.                                                                                 162.92, 572.7891000);
  913.         CustomRotationModels["iau-mimas"]     = new IAUMimasRotationModel();
  914.         CustomRotationModels["iau-enceladus"] = new IAUEnceladusRotationModel();
  915.         CustomRotationModels["iau-tethys"]    = new IAUTethysRotationModel();
  916.         CustomRotationModels["iau-telesto"]   = new IAUTelestoRotationModel();
  917.         CustomRotationModels["iau-calypso"]   = new IAUCalypsoRotationModel();
  918.         CustomRotationModels["iau-dione"]     = new IAUDioneRotationModel();
  919.         CustomRotationModels["iau-helene"]    = new IAUHeleneRotationModel();
  920.         CustomRotationModels["iau-rhea"]      = new IAURheaRotationModel();
  921.         CustomRotationModels["iau-titan"]     = new IAUTitanRotationModel();
  922.         CustomRotationModels["iau-iapetus"]   = new IAUIapetusRotationModel();
  923.         CustomRotationModels["iau-phoebe"]    = new IAUPhoebeRotationModel();
  924.         
  925.         CustomRotationModels["iau-miranda"]   = new IAUMirandaRotationModel();
  926.         CustomRotationModels["iau-ariel"]     = new IAUArielRotationModel();
  927.         CustomRotationModels["iau-umbriel"]   = new IAUUmbrielRotationModel();
  928.         CustomRotationModels["iau-titania"]   = new IAUTitaniaRotationModel();
  929.         CustomRotationModels["iau-oberon"]    = new IAUOberonRotationModel();
  930.     }
  931.     if (CustomRotationModels.count(name) > 0)
  932.         return CustomRotationModels[name];
  933.     else
  934.         return NULL;
  935. }