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

OpenGL

开发平台:

Visual C++

  1. // precession.cpp
  2. //
  3. // Calculate precession angles for Earth.
  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 <cmath>
  13. #include <iostream>
  14. #include <celmath/mathlib.h>
  15. #include <celmath/vecmath.h>
  16. #include "precession.h"
  17. using namespace std;
  18. // Periodic term for the long-period extension of the P03 precession
  19. // model.
  20. struct EclipticPrecessionTerm
  21. {
  22.     double Pc;
  23.     double Qc;
  24.     double Ps;
  25.     double Qs;
  26.     double period;
  27. };
  28. static EclipticPrecessionTerm EclipticPrecessionTerms[] =
  29. {
  30.     {   486.230527, 2559.065245, -2578.462809,   485.116645, 2308.98 },
  31.     {  -963.825784,  247.582718,  -237.405076,  -971.375498, 1831.25 },
  32.     { -1868.737098, -957.399054,  1007.593090, -1930.464338,  687.52 },
  33.     { -1589.172175,  493.021354,  -423.035168, -1634.905683,  729.97 },
  34.     {   429.442489, -328.301413,   337.266785,   429.594383,  492.21 },
  35.     { -2244.742029, -339.969833,   221.240093, -2131.745072,  708.13 },
  36. };
  37. // Periodic term for the long-period extension of the P03 precession
  38. // model.
  39. struct PrecessionTerm
  40. {
  41.     double pc;
  42.     double epsc;
  43.     double ps;
  44.     double epss;
  45.     double period;
  46. };
  47. static PrecessionTerm PrecessionTerms[] =
  48. {
  49.     { -6180.062400,   807.904635, -2434.845716, -2056.455197,  409.90 },
  50.     { -2721.869299,  -177.959383,   538.034071,  -912.727303,  396.15 },
  51.     {  1460.746498,   371.942696, -1245.689351,   447.710000,  536.91 },
  52.     { -1838.488899,  -176.029134,   529.220775,  -611.297411,  402.90 },
  53.     {   949.518077,   -89.154030,   277.195375,   315.900626,  417.15 },
  54.     {    32.701460,  -336.048179,   945.979710,    12.390157,  288.92 },
  55.     {   598.054819,   -17.415730,  -955.163661,   -15.922155, 4042.97 },
  56.     {  -293.145284,   -28.084479,    93.894079,  -102.870153,  304.90 },
  57.     {    66.354942,    21.456146,     0.671968,    24.123484,  281.46 },
  58.     {    18.894136,    30.917011,  -184.663935,     2.512708,  204.38 },
  59. };
  60. /*! Compute the precession of the ecliptic, based on a long-period
  61.  *  extension of the the P03 model, presented in "Long-periodic Precession
  62.  *  Parameters", J. Vondrak (2006)
  63.  *  http://www.astronomy2006.com/files/vondrak.pdf
  64.  *  For an explanation of the angles used in the P03 model, see
  65.  *  "Expressions for IAU2000 precession quantities", N. Capitaine et al,
  66.  *  Astronomy & Astrophysics, v.412, p.567-586 (2003).
  67.  *
  68.  *  Also: "Expressions for the Precession Quantities", J. H. Lieske et al,
  69.  *  Astronomy & Astrophysics, v.58, p. 1-16 (1977).
  70.  *
  71.  *  6 long-periodic terms, plus a cubic polynomial for longer terms.
  72.  *  The terms are fitted to the P03 model withing 1000 years of J2000.
  73.  *
  74.  *  T is the time in centuries since J2000. The angles returned are
  75.  *  in arcseconds.
  76.  */
  77. astro::EclipticPole
  78. astro::EclipticPrecession_P03LP(double T)
  79. {
  80.     EclipticPole pole;
  81.     double T2 = T * T;
  82.     double T3 = T2 * T;
  83.     pole.PA = (5750.804069
  84.                +  0.1948311 * T
  85.                -  0.00016739 * T2
  86.                -  4.8e-8 * T3);
  87.     pole.QA = (-1673.999018
  88.                +   0.3474459 * T
  89.                +   0.00011243 * T2
  90.                -   6.4e-8 * T3);
  91.     unsigned int nTerms = sizeof(EclipticPrecessionTerms) / sizeof(EclipticPrecessionTerms[0]);
  92.     for (unsigned int i = 0; i < nTerms; i++)
  93.     {
  94.         const EclipticPrecessionTerm& p = EclipticPrecessionTerms[i];
  95.         double theta = 2.0 * PI * T / p.period;
  96.         double s = sin(theta);
  97.         double c = cos(theta);
  98.         pole.PA += p.Pc * c + p.Ps * s;
  99.         pole.QA += p.Qc * c + p.Qs * s;
  100.     }
  101.     return pole;
  102. }
  103. /*! Compute the general precession and obliquity, based on the model
  104.  *  presented in "Long-periodic Precession Parameters", J. Vondrak, 2006
  105.  *  http://www.astronomy2006.com/files/vondrak.pdf
  106.  *
  107.  *  T is the time in centuries since J2000. The angles returned are
  108.  *  in arcseconds.
  109.  */
  110. astro::PrecessionAngles
  111. astro::PrecObliquity_P03LP(double T)
  112. {
  113.     PrecessionAngles angles;
  114.     double T2 = T * T;
  115.     double T3 = T2 * T;
  116.     angles.pA   = (  7907.295950
  117.                    + 5044.374034 * T
  118.                    -    0.00713473 * T2
  119.                    +    6e-9 * T3);
  120.     angles.epsA = (  83973.876448
  121.                    -     0.0425899 * T
  122.                    -     0.00000113 * T2);
  123.     unsigned int nTerms = sizeof(PrecessionTerms) / sizeof(PrecessionTerms[0]);
  124.     for (unsigned int i = 0; i < nTerms; i++)
  125.     {
  126.         const PrecessionTerm& p = PrecessionTerms[i];
  127.         double theta = 2.0 * PI * T / p.period;
  128.         double s = sin(theta);
  129.         double c = cos(theta);
  130.         angles.pA   += p.pc * c   + p.ps * s;
  131.         angles.epsA += p.epsc * c + p.epss * s;
  132.     }
  133.     return angles;
  134. }
  135. /*! Compute equatorial precession angles z, zeta, and theta using the P03
  136.  *  precession model.
  137.  */
  138. astro::EquatorialPrecessionAngles
  139. astro::EquatorialPrecessionAngles_P03(double T)
  140. {
  141.     EquatorialPrecessionAngles prec;
  142.     double T2 = T * T;
  143.     double T3 = T2 * T;
  144.     double T4 = T3 * T;
  145.     double T5 = T4 * T;
  146.     
  147.     prec.zetaA =  (     2.650545
  148.                    + 2306.083227 * T
  149.                    +    0.2988499 * T2
  150.                    +    0.01801828 * T3
  151.                    -    0.000005971 * T4
  152.                    -    0.0000003173 * T5);
  153.     prec.zA =     ( -    2.650545 
  154.                     + 2306.077181 * T
  155.                     +    1.0927348 * T2
  156.                     +    0.01826837 * T3
  157.                     -    0.000028596 * T4
  158.                     -    0.0000002904 * T5);
  159.     prec.thetaA = (   2004.191903 * T
  160.                    -     0.4294934 * T2
  161.                    -     0.04182264 * T3
  162.                    -     0.000007089 * T4
  163.                    -     0.0000001274 * T5);
  164.     
  165.     return prec;
  166. }
  167. /*! Compute the ecliptic pole coordinates PA and QA using the P03 precession
  168.  *  model. The quantities PA and QA are coordinates, but they are given in
  169.  *  units of arcseconds in P03. They should be divided by 1296000/2pi.
  170.  */
  171. astro::EclipticPole
  172. astro::EclipticPrecession_P03(double T)
  173. {
  174.     astro::EclipticPole pole;
  175.     double T2 = T * T;
  176.     double T3 = T2 * T;
  177.     double T4 = T3 * T;
  178.     double T5 = T4 * T;
  179.     
  180.     pole.PA = (  4.199094 * T
  181.               + 0.1939873 * T2
  182.               - 0.00022466 * T3
  183.               - 0.000000912 * T4
  184.               + 0.0000000120 * T5);
  185.     pole.QA = (-46.811015 * T
  186.               + 0.0510283 * T2
  187.               + 0.00052413 * T3
  188.               - 0.00000646 * T4
  189.               - 0.0000000172 * T5);
  190.     
  191.     return pole;
  192. }
  193. /*! Calculate the angles of the ecliptic of date with respect to
  194.  *  the J2000 ecliptic using the P03 precession model.
  195.  */
  196. astro::EclipticAngles
  197. astro::EclipticPrecessionAngles_P03(double T)
  198. {
  199.     astro::EclipticAngles ecl;
  200.     double T2 = T * T;
  201.     double T3 = T2 * T;
  202.     double T4 = T3 * T;
  203.     double T5 = T4 * T;
  204.     
  205.     ecl.piA = ( 46.998973 * T
  206.                - 0.0334926 * T2
  207.                - 0.00012559 * T3
  208.                + 0.000000113 * T4
  209.                - 0.0000000022 * T5);
  210.     ecl.PiA = (629546.7936
  211.                 - 867.95758 * T
  212.                 +   0.157992 * T2
  213.                 -   0.0005371 * T3
  214.                 -   0.00004797 * T4
  215.                 +   0.000000072 * T5);
  216.     
  217.     return ecl;
  218. }
  219. // DE405 obliquity of the ecliptic
  220. static const double eps0 = 84381.40889;
  221. /*! Compute the general precession and obliquity using the P03
  222.  *  precession model. See PrecObliquity_P03LP for more details.
  223.  */
  224. astro::PrecessionAngles
  225. astro::PrecObliquity_P03(double T)
  226. {
  227.     astro::PrecessionAngles prec;
  228.     double T2 = T * T;
  229.     double T3 = T2 * T;
  230.     double T4 = T3 * T;
  231.     double T5 = T4 * T;
  232.     
  233.     prec.epsA = (eps0
  234.                 - 46.836769 * T
  235.                 -  0.0001831 * T2
  236.                 +  0.00200340 * T3
  237.                 -  0.000000576 * T4
  238.                 -  0.0000000434 * T5);
  239.     prec.pA   = ( 5028.796195 * T
  240.                 +   1.1054348 * T2
  241.                 +   0.00007964 * T3
  242.                 -   0.000023857 * T4
  243.                 -   0.0000000383 * T5);
  244. #if 0
  245.     prec.chiA = (  10.556403 * T
  246.                 -  2.3814292 * T2
  247.                 -  0.00121197 * T3
  248.                 +  0.000170663 * T4
  249.                 -  0.0000000560 * T5);
  250. #endif
  251.     
  252.     return prec;
  253. }
  254. #define TEST 0
  255. #if TEST
  256. #include <celmath/quaternion.h>
  257. int main(int argc, char* argv[])
  258. {
  259.     double step = 10.0;
  260.     
  261.     for (int i = -100; i <= 100; i++)
  262.     {
  263.         // Get time in Julian centuries from J2000
  264.         double T = (double) i * step / 100;
  265.         
  266.         astro::EclipticPole ecl = astro::EclipticPrecession_P03LP(T);
  267.         astro::EclipticPole eclP03 = astro::EclipticPrecession_P03(T);
  268.         astro::EclipticAngles eclAnglesP03 = astro::EclipticPrecessionAngles_P03(T);
  269.         
  270.         //clog << ecl.PA - eclP03.PA << ", " << ecl.QA - eclP03.QA << endl;
  271.         ecl = eclP03;
  272.         Vec3d v(0.0, 0.0, 0.0);
  273.         v.x =  ecl.PA * 2.0 * PI / 1296000;
  274.         v.y = -ecl.QA * 2.0 * PI / 1296000;
  275.         v.z = sqrt(1.0 - v.x * v.x - v.y * v.y);
  276.         
  277.         Quatd eclRotation = Quatd::vecToVecRotation(Vec3d(0.0, 0.0, 1.0), v);
  278.         Quatd eclRotation2 = Quatd::zrotation(-degToRad(eclAnglesP03.PiA / 3600.0)) *
  279.                              Quatd::xrotation(degToRad(eclAnglesP03.piA / 3600.0)) *
  280.                              Quatd::zrotation(degToRad(eclAnglesP03.PiA / 3600.0));
  281.         Quatd eclRotation3;
  282.         {
  283.             // Calculate the angles pi and Pi from the ecliptic pole coordinates
  284.             // P and Q:
  285.             //   P = sin(pi)*sin(Pi)
  286.             //   Q = sin(pi)*cos(Pi)
  287.             double P = eclP03.PA * 2.0 * PI / 1296000;
  288.             double Q = eclP03.QA * 2.0 * PI / 1296000;
  289.             double piA = asin(sqrt(P * P + Q * Q));
  290.             double PiA = atan2(P, Q);
  291.             
  292.             // Calculate the rotation from the J2000 ecliptic to the ecliptic
  293.             // of date.
  294.             eclRotation3 = Quatd::zrotation(-PiA) *
  295.                            Quatd::xrotation(piA) *
  296.                            Quatd::zrotation(PiA);
  297.             
  298.             piA = radToDeg(piA) * 3600;
  299.             PiA = radToDeg(PiA) * 3600;
  300.             clog << "Pi: " << PiA << ", " << eclAnglesP03.PiA << endl;
  301.             clog << "pi: " << piA << ", " << eclAnglesP03.piA << endl;
  302.         }
  303.         
  304.         astro::PrecessionAngles prec = astro::PrecObliquity_P03LP(T);
  305.         Quatd p03lpRot = Quatd::xrotation(degToRad(prec.epsA / 3600.0)) *
  306.                          Quatd::zrotation(-degToRad(prec.pA / 3600.0));
  307.         p03lpRot = p03lpRot * ~eclRotation3;
  308.                 
  309.         astro::PrecessionAngles prec2 = astro::PrecObliquity_P03(T);
  310.         //clog << prec.epsA - prec2.epsA << ", " << prec.pA - prec2.pA << endl;
  311.         
  312.         astro::EquatorialPrecessionAngles precP03 = astro::EquatorialPrecessionAngles_P03(T);
  313.         Quatd p03Rot = Quatd::zrotation(-degToRad(precP03.zA / 3600.0)) *
  314.                        Quatd::yrotation( degToRad(precP03.thetaA / 3600.0)) *
  315.                        Quatd::zrotation(-degToRad(precP03.zetaA / 3600.0));
  316.         p03Rot = p03Rot * Quatd::xrotation(degToRad(eps0 / 3600.0));
  317.         
  318.         Vec3d xaxis(0, 0, 1);
  319.         Vec3d v0 = xaxis * p03lpRot.toMatrix3();
  320.         Vec3d v1 = xaxis * p03Rot.toMatrix3();
  321.         
  322.         // Show the angle between the J2000 ecliptic pole and the ecliptic
  323.         // pole at T centuries from J2000
  324.         double theta0 = acos(xaxis * v0);
  325.         double theta1 = acos(xaxis * v1);
  326.         
  327.         clog << T * 100 << ": " 
  328.             << radToDeg(acos(v0 * v1)) * 3600 << ", "
  329.             << radToDeg(theta0) << ", "
  330.             << radToDeg(theta1) << ", "
  331.             << radToDeg(theta1 - theta0) * 3600
  332.             << endl;
  333.     }
  334.     return 0;
  335. }
  336. #endif // TEST