123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- //
- // The graphics rendering engine GLScene http://glscene.org
- //
- unit USolarSystem;
- (*
- Solar system planetary elements and positions utility unit.
- Based on document by Paul Schlyter (Stockholm, Sweden)
- http://www.stjarnhimlen.se/comp/ppcomp.html
- Coordinates system takes Z as "up", ie. normal to the ecliptic plane,
- "axis" around which the planets turn.
- *)
- interface
- uses
- System.SysUtils,
- System.Math,
- GLS.VectorGeometry;
- type
- TOrbitalElements = record
- N: Double; // longitude of the ascending node
- i: Double; // inclination to the ecliptic (plane of the Earth's orbit)
- w: Double; // argument of perihelion
- a: Double; // semi-major axis, or mean distance from Sun
- e: Double; // eccentricity (0=circle, 0-1=ellipse, 1=parabola)
- M: Double; // mean anomaly (0 at perihelion; increases uniformly with time)
- end;
- TOrbitalElementsData = record
- NConst, NVar: Double; // longitude of the ascending node
- iConst, iVar: Double;
- // inclination to the ecliptic (plane of the Earth's orbit)
- wConst, wVar: Double; // argument of perihelion
- aConst, aVar: Double; // semi-major axis, or mean distance from Sun
- eConst, eVar: Double; // eccentricity (0=circle, 0-1=ellipse, 1=parabola)
- MConst, MVar: Double;
- // mean anomaly (0 at perihelion; increases uniformly with time)
- end;
- const
- // geocentric sun elements (?)
- cSunOrbitalElements: TOrbitalElementsData = (NConst: 0.0; NVar: 0.0;
- iConst: 0.0; iVar: 0.0; wConst: 282.9404; wVar: 4.70935E-5;
- aConst: 1.000000; aVar: 0.0; // (AU)
- eConst: 0.016709; eVar: - 1.151E-9; MConst: 356.0470; MVar: 0.9856002585);
- // geocentric moon elements
- cMoonOrbitalElements: TOrbitalElementsData = (NConst: 125.1228;
- NVar: - 0.0529538083; iConst: 5.1454; iVar: 0.0; wConst: 318.0634;
- wVar: 0.1643573223; aConst: 60.2666; aVar: 0.0; // (Earth radii)
- eConst: 0.054900; eVar: 0.0; MConst: 115.3654; MVar: 13.0649929509);
- // heliocentric mercury elements
- cMercuryOrbitalElements: TOrbitalElementsData = (NConst: 48.3313;
- NVar: 3.24587E-5; iConst: 7.0047; iVar: 5.00E-8; wConst: 29.1241;
- wVar: 1.01444E-5; aConst: 0.387098; aVar: 0.0; // (AU)
- eConst: 0.205635; eVar: 5.59E-10; MConst: 168.6562; MVar: 4.0923344368);
- // heliocentric venus elements
- cVenusOrbitalElements: TOrbitalElementsData = (NConst: 76.6799;
- NVar: 2.46590E-5; iConst: 3.3946; iVar: 2.75E-8; wConst: 54.8910;
- wVar: 1.38374E-5; aConst: 0.723330; aVar: 0.0; // (AU)
- eConst: 0.006773; eVar: - 1.302E-9; MConst: 48.0052; MVar: 1.6021302244);
- // heliocentric mars elements
- cMarsOrbitalElements: TOrbitalElementsData = (NConst: 49.5574;
- NVar: 2.11081E-5; iConst: 1.8497; iVar: - 1.78E-8; wConst: 286.5016;
- wVar: 2.92961E-5; aConst: 1.523688; aVar: 0.0; // (AU)
- eConst: 0.093405; eVar: 2.516E-9; MConst: 18.6021; MVar: 0.5240207766);
- // heliocentric jupiter elements
- cJupiterOrbitalElements: TOrbitalElementsData = (NConst: 100.4542;
- NVar: 2.76854E-5; iConst: 1.3030; iVar: - 1.557E-7; wConst: 273.8777;
- wVar: 1.64505E-5; aConst: 5.20256; aVar: 0.0; // (AU)
- eConst: 0.048498; eVar: 4.469E-9; MConst: 19.8950; MVar: 0.0830853001);
- // heliocentric saturn elements
- cSaturnOrbitalElements: TOrbitalElementsData = (NConst: 113.6634;
- NVar: 2.38980E-5; iConst: 2.4886; iVar: - 1.081E-7; wConst: 339.3939;
- wVar: 2.97661E-5; aConst: 9.55475; aVar: 0.0; // (AU)
- eConst: 0.055546; eVar: - 9.499E-9; MConst: 316.9670; MVar: 0.0334442282);
- // heliocentric uranus elements
- cUranusOrbitalElements: TOrbitalElementsData = (NConst: 74.0005;
- NVar: 1.3978E-5; iConst: 0.7733; iVar: 1.9E-8; wConst: 96.6612;
- wVar: 3.0565E-5; aConst: 19.18171; aVar: - 1.55E-8; // (AU)
- eConst: 0.047318; eVar: 7.45E-9; MConst: 142.5905; MVar: 0.011725806);
- // heliocentric neptune elements
- cNeptuneOrbitalElements: TOrbitalElementsData = (NConst: 131.7806;
- NVar: 3.0173E-5; iConst: 1.7700; iVar: - 2.55E-7; wConst: 272.8461;
- wVar: - 6.027E-6; aConst: 30.05826; aVar: 3.313E-8; // (AU)
- eConst: 0.008606; eVar: 2.15E-9; MConst: 260.2471; MVar: 0.005995147);
- cAUToKilometers = 149.6E6; // astronomical units to kilometers
- cEarthRadius = 6400; // earth radius in kilometers
- // Converts a TDateTime (GMT+0) into the julian day used for computations.
- function GMTDateTimeToJulianDay(const dt: TDateTime): Double;
- // Compute orbital elements for given julian day.
- function ComputeOrbitalElements(const oeData: TOrbitalElementsData;
- const d: Double): TOrbitalElements;
- // Compute the planet position for given julian day (in AU).
- function ComputePlanetPosition(const orbitalElements: TOrbitalElements)
- : TAffineVector; overload;
- function ComputePlanetPosition(const orbitalElementsData: TOrbitalElementsData;
- const d: Double): TAffineVector; overload;
- // ------------------------------------------------------------------------------
- implementation
- // ------------------------------------------------------------------------------
- function GMTDateTimeToJulianDay(const dt: TDateTime): Double;
- begin
- Result := dt - EncodeDate(2000, 1, 1);
- end;
- function ComputeOrbitalElements(const oeData: TOrbitalElementsData;
- const d: Double): TOrbitalElements;
- begin
- with Result, oeData do
- begin
- N := NConst + NVar * d;
- i := iConst + iVar * d;
- w := wConst + wVar * d;
- a := aConst + aVar * d;
- e := eConst + eVar * d;
- M := MConst + MVar * d;
- end;
- end;
- function ComputePlanetPosition(const orbitalElements: TOrbitalElements)
- : TAffineVector;
- var
- eccentricAnomaly, eA0: Double;
- sm, cm, se, ce, si, ci, cn, sn, cvw, svw: Double;
- xv, yv, v, r: Double;
- nn: Integer; // numerical instability bailout
- begin
- with orbitalElements do
- begin
- // E = M + e*(180/pi) * sin(M) * ( 1.0 + e * cos(M) )
- SinCos(M * cPIdiv180, sm, cm);
- eccentricAnomaly := M + e * c180divPI * sm * (1.0 + e * cm);
- nn := 0;
- repeat
- eA0 := eccentricAnomaly;
- // E1 = E0 - ( E0 - e*(180/pi) * sin(E0) - M ) / ( 1 - e * cos(E0) )
- SinCos(eA0 * cPIdiv180, se, ce);
- eccentricAnomaly := eA0 - (eA0 - e * c180divPI * se - M) / (1 - e * ce);
- Inc(nn);
- until (nn > 10) or (Abs(eccentricAnomaly - eA0) < 1E-4);
- SinCos(eccentricAnomaly * cPIdiv180, se, ce);
- xv := a * (ce - e);
- yv := a * (Sqrt(1.0 - e * e) * se);
- v := ArcTan2(yv, xv) * c180divPI;
- r := Sqrt(xv * xv + yv * yv);
- SinCos(i * cPIdiv180, si, ci);
- SinCos(N * cPIdiv180, sn, cn);
- SinCos((v + w) * cPIdiv180, svw, cvw);
- end;
- // xh = r * ( cos(N) * cos(v+w) - sin(N) * sin(v+w) * cos(i) )
- Result.X := r * (cn * cvw - sn * svw * ci);
- // yh = r * ( sin(N) * cos(v+w) + cos(N) * sin(v+w) * cos(i) )
- Result.Y := r * (sn * cvw + cn * svw * ci);
- // zh = r * ( sin(v+w) * sin(i) )
- Result.Z := r * (svw * si);
- end;
- function ComputePlanetPosition(const orbitalElementsData: TOrbitalElementsData;
- const d: Double): TAffineVector;
- var
- oe: TOrbitalElements;
- begin
- oe := ComputeOrbitalElements(orbitalElementsData, d);
- Result := ComputePlanetPosition(oe);
- end;
- end.
|