USolarSystem.pas 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. //
  2. // The graphics rendering engine GLScene http://glscene.org
  3. //
  4. unit USolarSystem;
  5. (*
  6. Solar system planetary elements and positions utility unit.
  7. Based on document by Paul Schlyter (Stockholm, Sweden)
  8. http://www.stjarnhimlen.se/comp/ppcomp.html
  9. Coordinates system takes Z as "up", ie. normal to the ecliptic plane,
  10. "axis" around which the planets turn.
  11. *)
  12. interface
  13. uses
  14. System.SysUtils,
  15. System.Math,
  16. GLS.VectorGeometry;
  17. type
  18. TOrbitalElements = record
  19. N: Double; // longitude of the ascending node
  20. i: Double; // inclination to the ecliptic (plane of the Earth's orbit)
  21. w: Double; // argument of perihelion
  22. a: Double; // semi-major axis, or mean distance from Sun
  23. e: Double; // eccentricity (0=circle, 0-1=ellipse, 1=parabola)
  24. M: Double; // mean anomaly (0 at perihelion; increases uniformly with time)
  25. end;
  26. TOrbitalElementsData = record
  27. NConst, NVar: Double; // longitude of the ascending node
  28. iConst, iVar: Double;
  29. // inclination to the ecliptic (plane of the Earth's orbit)
  30. wConst, wVar: Double; // argument of perihelion
  31. aConst, aVar: Double; // semi-major axis, or mean distance from Sun
  32. eConst, eVar: Double; // eccentricity (0=circle, 0-1=ellipse, 1=parabola)
  33. MConst, MVar: Double;
  34. // mean anomaly (0 at perihelion; increases uniformly with time)
  35. end;
  36. const
  37. // geocentric sun elements (?)
  38. cSunOrbitalElements: TOrbitalElementsData = (NConst: 0.0; NVar: 0.0;
  39. iConst: 0.0; iVar: 0.0; wConst: 282.9404; wVar: 4.70935E-5;
  40. aConst: 1.000000; aVar: 0.0; // (AU)
  41. eConst: 0.016709; eVar: - 1.151E-9; MConst: 356.0470; MVar: 0.9856002585);
  42. // geocentric moon elements
  43. cMoonOrbitalElements: TOrbitalElementsData = (NConst: 125.1228;
  44. NVar: - 0.0529538083; iConst: 5.1454; iVar: 0.0; wConst: 318.0634;
  45. wVar: 0.1643573223; aConst: 60.2666; aVar: 0.0; // (Earth radii)
  46. eConst: 0.054900; eVar: 0.0; MConst: 115.3654; MVar: 13.0649929509);
  47. // heliocentric mercury elements
  48. cMercuryOrbitalElements: TOrbitalElementsData = (NConst: 48.3313;
  49. NVar: 3.24587E-5; iConst: 7.0047; iVar: 5.00E-8; wConst: 29.1241;
  50. wVar: 1.01444E-5; aConst: 0.387098; aVar: 0.0; // (AU)
  51. eConst: 0.205635; eVar: 5.59E-10; MConst: 168.6562; MVar: 4.0923344368);
  52. // heliocentric venus elements
  53. cVenusOrbitalElements: TOrbitalElementsData = (NConst: 76.6799;
  54. NVar: 2.46590E-5; iConst: 3.3946; iVar: 2.75E-8; wConst: 54.8910;
  55. wVar: 1.38374E-5; aConst: 0.723330; aVar: 0.0; // (AU)
  56. eConst: 0.006773; eVar: - 1.302E-9; MConst: 48.0052; MVar: 1.6021302244);
  57. // heliocentric mars elements
  58. cMarsOrbitalElements: TOrbitalElementsData = (NConst: 49.5574;
  59. NVar: 2.11081E-5; iConst: 1.8497; iVar: - 1.78E-8; wConst: 286.5016;
  60. wVar: 2.92961E-5; aConst: 1.523688; aVar: 0.0; // (AU)
  61. eConst: 0.093405; eVar: 2.516E-9; MConst: 18.6021; MVar: 0.5240207766);
  62. // heliocentric jupiter elements
  63. cJupiterOrbitalElements: TOrbitalElementsData = (NConst: 100.4542;
  64. NVar: 2.76854E-5; iConst: 1.3030; iVar: - 1.557E-7; wConst: 273.8777;
  65. wVar: 1.64505E-5; aConst: 5.20256; aVar: 0.0; // (AU)
  66. eConst: 0.048498; eVar: 4.469E-9; MConst: 19.8950; MVar: 0.0830853001);
  67. // heliocentric saturn elements
  68. cSaturnOrbitalElements: TOrbitalElementsData = (NConst: 113.6634;
  69. NVar: 2.38980E-5; iConst: 2.4886; iVar: - 1.081E-7; wConst: 339.3939;
  70. wVar: 2.97661E-5; aConst: 9.55475; aVar: 0.0; // (AU)
  71. eConst: 0.055546; eVar: - 9.499E-9; MConst: 316.9670; MVar: 0.0334442282);
  72. // heliocentric uranus elements
  73. cUranusOrbitalElements: TOrbitalElementsData = (NConst: 74.0005;
  74. NVar: 1.3978E-5; iConst: 0.7733; iVar: 1.9E-8; wConst: 96.6612;
  75. wVar: 3.0565E-5; aConst: 19.18171; aVar: - 1.55E-8; // (AU)
  76. eConst: 0.047318; eVar: 7.45E-9; MConst: 142.5905; MVar: 0.011725806);
  77. // heliocentric neptune elements
  78. cNeptuneOrbitalElements: TOrbitalElementsData = (NConst: 131.7806;
  79. NVar: 3.0173E-5; iConst: 1.7700; iVar: - 2.55E-7; wConst: 272.8461;
  80. wVar: - 6.027E-6; aConst: 30.05826; aVar: 3.313E-8; // (AU)
  81. eConst: 0.008606; eVar: 2.15E-9; MConst: 260.2471; MVar: 0.005995147);
  82. cAUToKilometers = 149.6E6; // astronomical units to kilometers
  83. cEarthRadius = 6400; // earth radius in kilometers
  84. // Converts a TDateTime (GMT+0) into the julian day used for computations.
  85. function GMTDateTimeToJulianDay(const dt: TDateTime): Double;
  86. // Compute orbital elements for given julian day.
  87. function ComputeOrbitalElements(const oeData: TOrbitalElementsData;
  88. const d: Double): TOrbitalElements;
  89. // Compute the planet position for given julian day (in AU).
  90. function ComputePlanetPosition(const orbitalElements: TOrbitalElements)
  91. : TAffineVector; overload;
  92. function ComputePlanetPosition(const orbitalElementsData: TOrbitalElementsData;
  93. const d: Double): TAffineVector; overload;
  94. // ------------------------------------------------------------------------------
  95. implementation
  96. // ------------------------------------------------------------------------------
  97. function GMTDateTimeToJulianDay(const dt: TDateTime): Double;
  98. begin
  99. Result := dt - EncodeDate(2000, 1, 1);
  100. end;
  101. function ComputeOrbitalElements(const oeData: TOrbitalElementsData;
  102. const d: Double): TOrbitalElements;
  103. begin
  104. with Result, oeData do
  105. begin
  106. N := NConst + NVar * d;
  107. i := iConst + iVar * d;
  108. w := wConst + wVar * d;
  109. a := aConst + aVar * d;
  110. e := eConst + eVar * d;
  111. M := MConst + MVar * d;
  112. end;
  113. end;
  114. function ComputePlanetPosition(const orbitalElements: TOrbitalElements)
  115. : TAffineVector;
  116. var
  117. eccentricAnomaly, eA0: Double;
  118. sm, cm, se, ce, si, ci, cn, sn, cvw, svw: Double;
  119. xv, yv, v, r: Double;
  120. nn: Integer; // numerical instability bailout
  121. begin
  122. with orbitalElements do
  123. begin
  124. // E = M + e*(180/pi) * sin(M) * ( 1.0 + e * cos(M) )
  125. SinCos(M * cPIdiv180, sm, cm);
  126. eccentricAnomaly := M + e * c180divPI * sm * (1.0 + e * cm);
  127. nn := 0;
  128. repeat
  129. eA0 := eccentricAnomaly;
  130. // E1 = E0 - ( E0 - e*(180/pi) * sin(E0) - M ) / ( 1 - e * cos(E0) )
  131. SinCos(eA0 * cPIdiv180, se, ce);
  132. eccentricAnomaly := eA0 - (eA0 - e * c180divPI * se - M) / (1 - e * ce);
  133. Inc(nn);
  134. until (nn > 10) or (Abs(eccentricAnomaly - eA0) < 1E-4);
  135. SinCos(eccentricAnomaly * cPIdiv180, se, ce);
  136. xv := a * (ce - e);
  137. yv := a * (Sqrt(1.0 - e * e) * se);
  138. v := ArcTan2(yv, xv) * c180divPI;
  139. r := Sqrt(xv * xv + yv * yv);
  140. SinCos(i * cPIdiv180, si, ci);
  141. SinCos(N * cPIdiv180, sn, cn);
  142. SinCos((v + w) * cPIdiv180, svw, cvw);
  143. end;
  144. // xh = r * ( cos(N) * cos(v+w) - sin(N) * sin(v+w) * cos(i) )
  145. Result.X := r * (cn * cvw - sn * svw * ci);
  146. // yh = r * ( sin(N) * cos(v+w) + cos(N) * sin(v+w) * cos(i) )
  147. Result.Y := r * (sn * cvw + cn * svw * ci);
  148. // zh = r * ( sin(v+w) * sin(i) )
  149. Result.Z := r * (svw * si);
  150. end;
  151. function ComputePlanetPosition(const orbitalElementsData: TOrbitalElementsData;
  152. const d: Double): TAffineVector;
  153. var
  154. oe: TOrbitalElements;
  155. begin
  156. oe := ComputeOrbitalElements(orbitalElementsData, d);
  157. Result := ComputePlanetPosition(oe);
  158. end;
  159. end.