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

OpenGL

开发平台:

Visual C++

  1. // nutation.cpp
  2. //
  3. // Calculate nutation 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 "nutation.h"
  16. using namespace std;
  17. struct NutationTableEntry
  18. {
  19.     // Multiples of arguments
  20.     int lMult;
  21.     int l_Mult;
  22.     int FMult;
  23.     int DMult;
  24.     int OmMult;
  25.     double l1; // longitude, sin
  26.     double l2; // longitude, t*sin
  27.     double o1; // obliquity, cos
  28.     double o2; // obliquity, t*cos
  29.     double l3; // longitude, cos
  30.     double o3; // obliquity, sin
  31. };
  32. // Luni-Solar nutation coefficients, units 0.1 microarcsec:
  33. // longitude (sin, t*sin, cos), obliquity (cos, t*cos, sin)
  34. static const NutationTableEntry IAU2000BNutationTable[] =
  35. {
  36.  { 0,   0,   0,   0,   1,-172064161, -174666, 92052331,  9086, 33386, 15377 },
  37.  { 0,   0,   2,  -2,   2, -13170906,   -1675,  5730336, -3015,-13696, -4587 },
  38.  { 0,   0,   2,   0,   2,  -2276413,    -234,   978459,  -485,  2796,  1374 },
  39.  { 0,   0,   0,   0,   2,   2074554,     207,  -897492,   470,  -698,  -291 },
  40.  { 0,   1,   0,   0,   0,   1475877,   -3633,    73871,  -184, 11817, -1924 },
  41.  { 0,   1,   2,  -2,   2,   -516821,    1226,   224386,  -677,  -524,  -174 },
  42.  { 1,   0,   0,   0,   0,    711159,      73,    -6750,     0,  -872,   358 },
  43.  { 0,   0,   2,   0,   1,   -387298,    -367,   200728,    18,   380,   318 },
  44.  { 1,   0,   2,   0,   2,   -301461,     -36,   129025,   -63,   816,   367 },
  45.  { 0,  -1,   2,  -2,   2,    215829,    -494,   -95929,   299,   111,   132 },
  46.  { 0,   0,   2,  -2,   1,    128227,     137,   -68982,    -9,   181,    39 },
  47.  {-1,   0,   2,   0,   2,    123457,      11,   -53311,    32,    19,    -4 },
  48.  {-1,   0,   0,   2,   0,    156994,      10,    -1235,     0,  -168,    82 },
  49.  { 1,   0,   0,   0,   1,     63110,      63,   -33228,     0,    27,    -9 },
  50.  {-1,   0,   0,   0,   1,    -57976,     -63,    31429,     0,  -189,   -75 },
  51.  {-1,   0,   2,   2,   2,    -59641,     -11,    25543,   -11,   149,    66 },
  52.  { 1,   0,   2,   0,   1,    -51613,     -42,    26366,     0,   129,    78 },
  53.  {-2,   0,   2,   0,   1,     45893,      50,   -24236,   -10,    31,    20 },
  54.  { 0,   0,   0,   2,   0,     63384,      11,    -1220,     0,  -150,    29 },
  55.  { 0,   0,   2,   2,   2,    -38571,      -1,    16452,   -11,   158,    68 },
  56.  {-2,   0,   0,   2,   0,    -47722,       0,      477,     0,   -18,   -25 },
  57.  { 2,   0,   2,   0,   2,    -31046,      -1,    13238,   -11,   131,    59 },
  58.  { 1,   0,   2,  -2,   2,     28593,       0,   -12338,    10,    -1,    -3 },
  59.  {-1,   0,   2,   0,   1,     20441,      21,   -10758,     0,    10,    -3 },
  60.  { 2,   0,   0,   0,   0,     29243,       0,     -609,     0,   -74,    13 },
  61.  { 0,   0,   2,   0,   0,     25887,       0,     -550,     0,   -66,    11 },
  62.  { 0,   1,   0,   0,   1,    -14053,     -25,     8551,    -2,    79,   -45 },
  63.  {-1,   0,   0,   2,   1,     15164,      10,    -8001,     0,    11,    -1 },
  64.  { 0,   2,   2,  -2,   2,    -15794,      72,     6850,   -42,   -16,    -5 },
  65.  { 0,   0,  -2,   2,   0,     21783,       0,     -167,     0,    13,    13 },
  66.  { 1,   0,   0,  -2,   1,    -12873,     -10,     6953,     0,   -37,   -14 },
  67.  { 0,  -1,   0,   0,   1,    -12654,      11,     6415,     0,    63,    26 },
  68.  {-1,   0,   2,   2,   1,    -10204,       0,     5222,     0,    25,    15 },
  69.  { 0,   2,   0,   0,   0,     16707,     -85,      168,    -1,   -10,    10 },
  70.  { 1,   0,   2,   2,   2,     -7691,       0,     3268,     0,    44,    19 },
  71.  {-2,   0,   2,   0,   0,    -11024,       0,      104,     0,   -14,     2 },
  72.  { 0,   1,   2,   0,   2,      7566,     -21,    -3250,     0,   -11,    -5 },
  73.  { 0,   0,   2,   2,   1,     -6637,     -11,     3353,     0,    25,    14 },
  74.  { 0,  -1,   2,   0,   2,     -7141,      21,     3070,     0,     8,     4 },
  75.  { 0,   0,   0,   2,   1,     -6302,     -11,     3272,     0,     2,     4 },
  76.  { 1,   0,   2,  -2,   1,      5800,      10,    -3045,     0,     2,    -1 },
  77.  { 2,   0,   2,  -2,   2,      6443,       0,    -2768,     0,    -7,    -4 },
  78.  {-2,   0,   0,   2,   1,     -5774,     -11,     3041,     0,   -15,    -5 },
  79.  { 2,   0,   2,   0,   1,     -5350,       0,     2695,     0,    21,    12 },
  80.  { 0,  -1,   2,  -2,   1,     -4752,     -11,     2719,     0,    -3,    -3 },
  81.  { 0,   0,   0,  -2,   1,     -4940,     -11,     2720,     0,   -21,    -9 },
  82.  {-1,  -1,   0,   2,   0,      7350,       0,      -51,     0,    -8,     4 },
  83.  { 2,   0,   0,  -2,   1,      4065,       0,    -2206,     0,     6,     1 },
  84.  { 1,   0,   0,   2,   0,      6579,       0,     -199,     0,   -24,     2 },
  85.  { 0,   1,   2,  -2,   1,      3579,       0,    -1900,     0,     5,     1 },
  86.  { 1,  -1,   0,   0,   0,      4725,       0,      -41,     0,    -6,     3 },
  87.  {-2,   0,   2,   0,   2,     -3075,       0,     1313,     0,    -2,    -1 },
  88.  { 3,   0,   2,   0,   2,     -2904,       0,     1233,     0,    15,     7 },
  89.  { 0,  -1,   0,   2,   0,      4348,       0,      -81,     0,   -10,     2 },
  90.  { 1,  -1,   2,   0,   2,     -2878,       0,     1232,     0,     8,     4 },
  91.  { 0,   0,   0,   1,   0,     -4230,       0,      -20,     0,     5,    -2 },
  92.  {-1,  -1,   2,   2,   2,     -2819,       0,     1207,     0,     7,     3 },
  93.  {-1,   0,   2,   0,   0,     -4056,       0,       40,     0,     5,    -2 },
  94.  { 0,  -1,   2,   2,   2,     -2647,       0,     1129,     0,    11,     5 },
  95.  {-2,   0,   0,   0,   1,     -2294,       0,     1266,     0,   -10,    -4 },
  96.  { 1,   1,   2,   0,   2,      2481,       0,    -1062,     0,    -7,    -3 },
  97.  { 2,   0,   0,   0,   1,      2179,       0,    -1129,     0,    -2,    -2 },
  98.  {-1,   1,   0,   1,   0,      3276,       0,       -9,     0,     1,     0 },
  99.  { 1,   1,   0,   0,   0,     -3389,       0,       35,     0,     5,    -2 },
  100.  { 1,   0,   2,   0,   0,      3339,       0,     -107,     0,   -13,     1 },
  101.  {-1,   0,   2,  -2,   1,     -1987,       0,     1073,     0,    -6,    -2 },
  102.  { 1,   0,   0,   0,   2,     -1981,       0,      854,     0,     0,     0 },
  103.  {-1,   0,   0,   1,   0,      4026,       0,     -553,     0,  -353,  -139 },
  104.  { 0,   0,   2,   1,   2,      1660,       0,     -710,     0,    -5,    -2 },
  105.  {-1,   0,   2,   4,   2,     -1521,       0,      647,     0,     9,     4 },
  106.  {-1,   1,   0,   1,   1,      1314,       0,     -700,     0,     0,     0 },
  107.  { 0,  -2,   2,  -2,   1,     -1283,       0,      672,     0,     0,     0 },
  108.  { 1,   0,   2,   2,   1,     -1331,       0,      663,     0,     8,     4 },
  109.  {-2,   0,   2,   2,   2,      1383,       0,     -594,     0,    -2,    -2 },
  110.  {-1,   0,   0,   0,   2,      1405,       0,     -610,     0,     4,     2 },
  111.  { 1,   1,   2,  -2,   2,      1290,       0,     -556,     0,     0,     0 },
  112.  {-2,   0,   2,   4,   2,     -1214,       0,      518,     0,     5,     2 },
  113.  {-1,   0,   4,   0,   2,      1146,       0,     -490,     0,    -3,    -1 },
  114. };
  115. double arcsecToRad(double as)
  116. {
  117.     return degToRad(as / 3600.0);
  118. }
  119. double milliarcsecToRad(double as)
  120. {
  121.     return degToRad(as / 3600000.0);
  122. }
  123. double microarcsecToRad(double as)
  124. {
  125.     return degToRad(as / 3600000000.0);
  126. }
  127. /*! Calculate nutation angles using the IAU2000B model. This model is a
  128.  *  truncated version of the IAU2000A model. It uses 77 terms for lunisolar
  129.  *  nutation and just a single constant term for planetary precession.
  130.  *
  131.  *  T is a time in Julian centuries (day number / 36525) from J2000 TT. The
  132.  *  angles returned are in radians. Note the use of Terrestrial Time instead
  133.  *  of TDB: this will not result in any meaningful discrepancy.
  134.  *
  135.  *  For further information, see IERS Technical Note 32:
  136.  *  http://www.iers.org/documents/publications/tn/tn32/tn32_033.pdf
  137.  */
  138. astro::NutationAngles
  139. astro::Nutation_IAU2000B(double T)
  140. {
  141.     double T2 = T * T;
  142.     double T3 = T2 * T;
  143.     double T4 = T3 * T;
  144.     // Mean anomaly of the Moon
  145.     double l  = arcsecToRad(134.96340251
  146.                             + 1717915923.2178 * T
  147.                             + 31.8792         * T2
  148.                             + 0.051635        * T3
  149.                             - 0.00024470      * T4);
  150.     // Mean anomaly of the Sun.
  151.     double l_ = arcsecToRad(357.52910918
  152.                             + 129596581.0481  * T
  153.                             - 0.5532          * T2
  154.                             + 0.000136        * T3
  155.                             - 0.00001149      * T4);
  156.     // Mean longitude of the Moon minus the mean longitude of the Moon's
  157.     // node.
  158.     double F  = arcsecToRad(93.27209062
  159.                             + 1739527262.8478 * T
  160.                             - 12.7512         * T2
  161.                             - 0.001037        * T3 
  162.                             + 0.00000417      * T4);
  163.     // Mean elongation of the Moon from the Sun
  164.     double D  = arcsecToRad(29.785019547
  165.                             + 1602961601.2090 * T
  166.                             - 6.3706          * T2
  167.                             + 0.006593        * T3
  168.                             - 0.00003169      * T4);
  169.     // Longitude of the ascending node of the Moon's orbit on the ecliptic
  170.     // measured from the mean equinox of date.
  171.     double Om = arcsecToRad(125.04455501
  172.                             - 6962890.5431    * T
  173.                             + 7.4722          * T2
  174.                             + 0.007702        * T3
  175.                             - 0.00005939      * T4);
  176.     double obliquity = 0.0;
  177.     double longitude = 0.0;
  178.     unsigned int nEntries = sizeof(IAU2000BNutationTable) /
  179.                             sizeof(IAU2000BNutationTable[0]);
  180.     for (unsigned int i = 0; i < nEntries; i++)
  181.     {
  182.         const NutationTableEntry& ent = IAU2000BNutationTable[i];
  183.         double arg = (l  * ent.lMult   +
  184.                       l_ * ent.l_Mult  +
  185.                       F  * ent.FMult   +
  186.                       D  * ent.DMult   +
  187.                       Om * ent.OmMult);
  188.         double S = sin(arg);
  189.         double C = cos(arg);
  190.         longitude += (ent.l1 + ent.l2 * T) * S + ent.l3 * C;
  191.         obliquity += (ent.o1 + ent.o2 * T) * C + ent.o3 * S;
  192.     }
  193.     // These constant terms account for the missing long-period planetary
  194.     // terms in the truncated nutation model.
  195.     double oblPlanetary  = milliarcsecToRad(-0.135);
  196.     double longPlanetary = milliarcsecToRad(+0.388);
  197.     NutationAngles nutation;
  198.     // Convert to radians from units of 0.1 microarcsec
  199.     nutation.obliquity = microarcsecToRad(obliquity * 0.1);
  200.     nutation.longitude = microarcsecToRad(longitude * 0.1);
  201.     // Add planetary nutation
  202.     nutation.obliquity += oblPlanetary;
  203.     nutation.longitude += longPlanetary;
  204.     return nutation;
  205. }
  206. #if TEST
  207. using namespace astro;
  208. int main()
  209. {
  210.     for (int i = -50; i < 50; i++)
  211.     {
  212.         NutationAngles nutation = Nutation_IAU2000B((double) i / 100.0);
  213.         cout << radToDeg(nutation.longitude) * 3600.0 << ", "
  214.              << radToDeg(nutation.obliquity) * 3600.0 << endl;
  215.     }
  216. }
  217. #endif