/// <summary> /// Performs reduction of equatorial coordinates from one epoch to another /// with using of precessional elements. /// </summary> /// <param name="eq0">Equatorial coordinates for initial epoch.</param> /// <param name="p">Precessional elements for reduction from initial epoch to target (final) epoch.</param> /// <returns>Equatorial coordinates for target (final) epoch.</returns> /// <remarks> /// This method is taken from AA(I), formula 20.4. /// </remarks> public static CrdsEquatorial GetEquatorialCoordinates(CrdsEquatorial eq0, PrecessionalElements p) { CrdsEquatorial eq = new CrdsEquatorial(); double sinDelta0 = Math.Sin(Angle.ToRadians(eq0.Delta)); double cosDelta0 = Math.Cos(Angle.ToRadians(eq0.Delta)); double sinTheta = Math.Sin(Angle.ToRadians(p.theta)); double cosTheta = Math.Cos(Angle.ToRadians(p.theta)); double sinAlpha0Zeta = Math.Sin(Angle.ToRadians(eq0.Alpha + p.zeta)); double cosAlpha0Zeta = Math.Cos(Angle.ToRadians(eq0.Alpha + p.zeta)); double A = cosDelta0 * sinAlpha0Zeta; double B = cosTheta * cosDelta0 * cosAlpha0Zeta - sinTheta * sinDelta0; double C = sinTheta * cosDelta0 * cosAlpha0Zeta + cosTheta * sinDelta0; eq.Alpha = Angle.ToDegrees(Math.Atan2(A, B)) + p.z; eq.Alpha = Angle.To360(eq.Alpha); if (Math.Abs(C) == 1) { eq.Delta = Angle.ToDegrees(Math.Acos(A * A + B * B)); } else { eq.Delta = Angle.ToDegrees(Math.Asin(C)); } return(eq); }
/// <summary> /// Gets geocentric elongation angle of the Moon from Sun /// </summary> /// <param name="sun">Ecliptical geocentrical coordinates of the Sun</param> /// <param name="moon">Ecliptical geocentrical coordinates of the Moon</param> /// <returns>Geocentric elongation angle, in degrees, from 0 to 180.</returns> /// <remarks> /// AA(II), formula 48.2 /// </remarks> public static double Elongation(CrdsEcliptical sun, CrdsEcliptical moon) { double beta = Angle.ToRadians(moon.Beta); double lambda = Angle.ToRadians(moon.Lambda); double lambda0 = Angle.ToRadians(sun.Lambda); return(Angle.ToDegrees(Math.Acos(Math.Cos(beta) * Math.Cos(lambda - lambda0)))); }
/// <summary> /// Converts rectangular topocentric coordinates of a planet to topocentrical ecliptical coordinates /// </summary> /// <param name="rect">Rectangular topocentric coordinates of a planet</param> /// <returns>Topocentrical ecliptical coordinates of a planet</returns> public static CrdsEcliptical ToEcliptical(this CrdsRectangular rect) { double lambda = Angle.To360(Angle.ToDegrees(Math.Atan2(rect.Y, rect.X))); double beta = Angle.ToDegrees(Math.Atan(rect.Z / Math.Sqrt(rect.X * rect.X + rect.Y * rect.Y))); double distance = Math.Sqrt(rect.X * rect.X + rect.Y * rect.Y + rect.Z * rect.Z); return(new CrdsEcliptical(lambda, beta, distance)); }
/// <summary> /// Calculates phase angle of the Moon /// </summary> /// <param name="psi">Geocentric elongation of the Moon.</param> /// <param name="R">Distance Earth-Sun, in kilometers</param> /// <param name="Delta">Distance Earth-Moon, in kilometers</param> /// <returns>Phase angle, in degrees, from 0 to 180</returns> /// <remarks> /// AA(II), formula 48.3. /// </remarks> public static double PhaseAngle(double psi, double R, double Delta) { psi = Angle.ToRadians(Math.Abs(psi)); double phaseAngle = Angle.ToDegrees(Math.Atan(R * Math.Sin(psi) / (Delta - R * Math.Cos(psi)))); if (phaseAngle < 0) { phaseAngle += 180; } return(phaseAngle); }
/// <summary> /// Calculates appearance of Saturn rings /// </summary> /// <param name="jd">Julian date to calculate for</param> /// <param name="saturn">Heliocentric coordinates of Saturn.</param> /// <param name="earth">Heliocentric coordinates of Earth.</param> /// <param name="epsilon">True obliquity of ecliptic.</param> /// <returns> /// Appearance data for Saturn rings. /// </returns> /// <remarks> /// Method is taken from AA(II), chapter 45. /// </remarks> public static RingsAppearance SaturnRings(double jd, CrdsHeliocentrical saturn, CrdsHeliocentrical earth, double epsilon) { RingsAppearance rings = new RingsAppearance(); double T = (jd - 2451545.0) / 36525.0; double T2 = T * T; double i = 28.075216 - 0.012998 * T + 0.000004 * T2; double Omega = 169.508470 + 1.394681 * T + 0.000412 * T2; double lambda0 = Omega - 90; double beta0 = 90 - i; i = Angle.ToRadians(i); Omega = Angle.ToRadians(Omega); CrdsEcliptical ecl = saturn.ToRectangular(earth).ToEcliptical(); double beta = Angle.ToRadians(ecl.Beta); double lambda = Angle.ToRadians(ecl.Lambda); rings.B = Angle.ToDegrees(Math.Asin(Math.Sin(i) * Math.Cos(beta) * Math.Sin(lambda - Omega) - Math.Cos(i) * Math.Sin(beta))); rings.a = 375.35 / ecl.Distance; rings.b = rings.a * Math.Sin(Math.Abs(Angle.ToRadians(rings.B))); double N = 113.6655 + 0.8771 * T; double l_ = Angle.ToRadians(saturn.L - 0.01759 / saturn.R); double b_ = Angle.ToRadians(saturn.B - 0.000764 * Math.Cos(Angle.ToRadians(saturn.L - N)) / saturn.R); double U1 = Angle.ToDegrees(Math.Atan((Math.Sin(i) * Math.Sin(b_) + Math.Cos(i) * Math.Cos(b_) * Math.Sin(l_ - Omega)) / (Math.Cos(b_) * Math.Cos(l_ - Omega)))); double U2 = Angle.ToDegrees(Math.Atan((Math.Sin(i) * Math.Sin(beta) + Math.Cos(i) * Math.Cos(beta) * Math.Sin(lambda - Omega)) / (Math.Cos(beta) * Math.Cos(lambda - Omega)))); rings.DeltaU = Math.Abs(U1 - U2); CrdsEcliptical eclPole = new CrdsEcliptical(); eclPole.Set(lambda0, beta0); CrdsEquatorial eq = ecl.ToEquatorial(epsilon); CrdsEquatorial eqPole = eclPole.ToEquatorial(epsilon); double alpha = Angle.ToRadians(eq.Alpha); double delta = Angle.ToRadians(eq.Delta); double alpha0 = Angle.ToRadians(eqPole.Alpha); double delta0 = Angle.ToRadians(eqPole.Delta); double y = Math.Cos(delta0) * Math.Sin(alpha0 - alpha); double x = Math.Sin(delta0) * Math.Cos(delta) - Math.Cos(delta0) * Math.Sin(delta) * Math.Cos(alpha0 - alpha); rings.P = Angle.ToDegrees(Math.Atan2(y, x)); return(rings); }
/// <summary> /// Calculates visible appearance of planet for given date. /// </summary> /// <param name="jd">Julian day</param> /// <param name="planet">Planet number to calculate appearance, 1 = Mercury, 2 = Venus and etc.</param> /// <param name="eq">Equatorial coordinates of the planet</param> /// <param name="distance">Distance from the planet to the Earth</param> /// <returns>Appearance parameters of the planet</returns> /// <remarks> /// This method is based on book "Practical Ephemeris Calculations", Montenbruck. /// See topic 6.4, pp. 88-92. /// </remarks> public static PlanetAppearance PlanetAppearance(double jd, int planet, CrdsEquatorial eq, double distance) { PlanetAppearance a = new PlanetAppearance(); double d = jd - 2451545.0; double T = d / 36525.0; // coordinates of the point to which the north pole of the planet is pointing. CrdsEquatorial eq0 = new CrdsEquatorial(); eq0.Alpha = Angle.To360(cAlpha0[planet - 1][0] + cAlpha0[planet - 1][1] * T + cAlpha0[planet - 1][2] * T); eq0.Delta = cDelta0[planet - 1][0] + cDelta0[planet - 1][1] * T + cDelta0[planet - 1][2] * T; // take light time effect into account d -= PlanetPositions.LightTimeEffect(distance); T = d / 36525.0; // position of null meridian double W = Angle.To360(cW[planet - 1][0] + cW[planet - 1][1] * d + cW[planet - 1][2] * T); double delta = Angle.ToRadians(eq.Delta); double alpha = Angle.ToRadians(eq.Alpha); double delta0 = Angle.ToRadians(eq0.Delta); double dAlpha0 = Angle.ToRadians(eq0.Alpha - eq.Alpha); double sinD = -Math.Sin(delta0) * Math.Sin(delta) - Math.Cos(delta0) * Math.Cos(delta) * Math.Cos(dAlpha0); // planetographic latitude of the Earth a.D = Angle.ToDegrees(Math.Asin(sinD)); double cosD = Math.Cos(Angle.ToRadians(a.D)); double sinP = Math.Cos(delta0) * Math.Sin(dAlpha0) / cosD; double cosP = (Math.Sin(delta0) * Math.Cos(delta) - Math.Cos(delta0) * Math.Sin(delta) * Math.Cos(dAlpha0)) / cosD; // position angle of the axis a.P = Angle.To360(Angle.ToDegrees(Math.Atan2(sinP, cosP))); double sinK = (-Math.Cos(delta0) * Math.Sin(delta) + Math.Sin(delta0) * Math.Cos(delta) * Math.Cos(dAlpha0)) / cosD; double cosK = Math.Cos(delta) * Math.Sin(dAlpha0) / cosD; double K = Angle.ToDegrees(Math.Atan2(sinK, cosK)); // planetographic longitude of the central meridian a.CM = planet == 5 ? JupiterCM2(jd) : Angle.To360(Math.Sign(W) * (W - K)); return(a); }
/// <summary> /// Converts ecliptical coordinates to equatorial. /// </summary> /// <param name="ecl">Pair of ecliptical cooordinates.</param> /// <param name="epsilon">Obliquity of the ecliptic, in degrees.</param> /// <returns>Pair of equatorial coordinates.</returns> public static CrdsEquatorial ToEquatorial(this CrdsEcliptical ecl, double epsilon) { CrdsEquatorial eq = new CrdsEquatorial(); epsilon = Angle.ToRadians(epsilon); double lambda = Angle.ToRadians(ecl.Lambda); double beta = Angle.ToRadians(ecl.Beta); double Y = Math.Sin(lambda) * Math.Cos(epsilon) - Math.Tan(beta) * Math.Sin(epsilon); double X = Math.Cos(lambda); eq.Alpha = Angle.To360(Angle.ToDegrees(Math.Atan2(Y, X))); eq.Delta = Angle.ToDegrees(Math.Asin(Math.Sin(beta) * Math.Cos(epsilon) + Math.Cos(beta) * Math.Sin(epsilon) * Math.Sin(lambda))); return(eq); }
/// <summary> /// Converts galactical coodinates to equatorial, for equinox B1950.0. /// </summary> /// <param name="gal">Galactical coodinates.</param> /// <returns>Equatorial coodinates, for equinox B1950.0.</returns> public static CrdsEquatorial ToEquatorial(this CrdsGalactical gal) { CrdsEquatorial eq = new CrdsEquatorial(); double l_l0 = Angle.ToRadians(gal.l - 123.0); double delta0 = Angle.ToRadians(27.4); double b = Angle.ToRadians(gal.b); double Y = Math.Sin(l_l0); double X = Math.Cos(l_l0) * Math.Sin(delta0) - Math.Tan(b) * Math.Cos(delta0); double sinDelta = Math.Sin(b) * Math.Sin(delta0) + Math.Cos(b) * Math.Cos(delta0) * Math.Cos(l_l0); eq.Alpha = Angle.To360(Angle.ToDegrees(Math.Atan2(Y, X)) + 12.25); eq.Delta = Angle.ToDegrees(Math.Asin(sinDelta)); return(eq); }
/// <summary> /// Converts equatorial coordinates (for equinox B1950.0) to galactical coordinates. /// </summary> /// <param name="eq">Equatorial coordinates for equinox B1950.0</param> /// <returns>Galactical coordinates.</returns> public static CrdsGalactical ToGalactical(this CrdsEquatorial eq) { CrdsGalactical gal = new CrdsGalactical(); double alpha0_alpha = Angle.ToRadians(192.25 - eq.Alpha); double delta = Angle.ToRadians(eq.Delta); double delta0 = Angle.ToRadians(27.4); double Y = Math.Sin(alpha0_alpha); double X = Math.Cos(alpha0_alpha) * Math.Sin(delta0) - Math.Tan(delta) * Math.Cos(delta0); double sinb = Math.Sin(delta) * Math.Sin(delta0) + Math.Cos(delta) * Math.Cos(delta0) * Math.Cos(alpha0_alpha); gal.l = Angle.To360(303 - Angle.ToDegrees(Math.Atan2(Y, X))); gal.b = Angle.ToDegrees(Math.Asin(sinb)); return(gal); }
/// <summary> /// Converts equatorial coordinates to ecliptical coordinates. /// </summary> /// <param name="eq">Pair of equatorial coordinates.</param> /// <param name="epsilon">Obliquity of the ecliptic, in degrees.</param> /// <returns></returns> public static CrdsEcliptical ToEcliptical(this CrdsEquatorial eq, double epsilon) { CrdsEcliptical ecl = new CrdsEcliptical(); epsilon = Angle.ToRadians(epsilon); double alpha = Angle.ToRadians(eq.Alpha); double delta = Angle.ToRadians(eq.Delta); double Y = Math.Sin(alpha) * Math.Cos(epsilon) + Math.Tan(delta) * Math.Sin(epsilon); double X = Math.Cos(alpha); ecl.Lambda = Angle.ToDegrees(Math.Atan2(Y, X)); ecl.Beta = Angle.ToDegrees(Math.Asin(Math.Sin(delta) * Math.Cos(epsilon) - Math.Cos(delta) * Math.Sin(epsilon) * Math.Sin(alpha))); return(ecl); }
/// <summary> /// Converts local horizontal coordinates to equatorial coordinates. /// </summary> /// <param name="hor">Pair of local horizontal coordinates.</param> /// <param name="geo">Geographical of the observer</param> /// <param name="theta0">Local sidereal time.</param> /// <returns>Pair of equatorial coordinates</returns> public static CrdsEquatorial ToEquatorial(this CrdsHorizontal hor, CrdsGeographical geo, double theta0) { CrdsEquatorial eq = new CrdsEquatorial(); double A = Angle.ToRadians(hor.Azimuth); double h = Angle.ToRadians(hor.Altitude); double phi = Angle.ToRadians(geo.Latitude); double Y = Math.Sin(A); double X = Math.Cos(A) * Math.Sin(phi) + Math.Tan(h) * Math.Cos(phi); double H = Angle.ToDegrees(Math.Atan2(Y, X)); eq.Alpha = Angle.To360(theta0 - geo.Longitude - H); eq.Delta = Angle.ToDegrees(Math.Asin(Math.Sin(phi) * Math.Sin(h) - Math.Cos(phi) * Math.Cos(h) * Math.Cos(A))); return(eq); }
/// <summary> /// Converts equatorial coodinates to local horizontal /// </summary> /// <param name="eq">Pair of equatorial coodinates</param> /// <param name="geo">Geographical coordinates of the observer</param> /// <param name="theta0">Local sidereal time</param> /// <remarks> /// Implementation is taken from AA(I), formulae 12.5, 12.6. /// </remarks> public static CrdsHorizontal ToHorizontal(this CrdsEquatorial eq, CrdsGeographical geo, double theta0) { double H = Angle.ToRadians(HourAngle(theta0, geo.Longitude, eq.Alpha)); double phi = Angle.ToRadians(geo.Latitude); double delta = Angle.ToRadians(eq.Delta); CrdsHorizontal hor = new CrdsHorizontal(); double Y = Math.Sin(H); double X = Math.Cos(H) * Math.Sin(phi) - Math.Tan(delta) * Math.Cos(phi); hor.Altitude = Angle.ToDegrees(Math.Asin(Math.Sin(phi) * Math.Sin(delta) + Math.Cos(phi) * Math.Cos(delta) * Math.Cos(H))); hor.Azimuth = Angle.ToDegrees(Math.Atan2(Y, X)); hor.Azimuth = Angle.To360(hor.Azimuth); return(hor); }
/// <summary> /// Calculates topocentric equatorial coordinates of celestial body /// with taking into account correction for parallax. /// </summary> /// <param name="eq">Geocentric equatorial coordinates of the body</param> /// <param name="geo">Geographical coordinates of the body</param> /// <param name="theta0">Apparent sidereal time at Greenwich</param> /// <param name="pi">Parallax of a body</param> /// <returns>Topocentric equatorial coordinates of the celestial body</returns> /// <remarks> /// Method is taken from AA(II), formulae 40.6-40.7. /// </remarks> public static CrdsEquatorial ToTopocentric(this CrdsEquatorial eq, CrdsGeographical geo, double theta0, double pi) { double H = Angle.ToRadians(HourAngle(theta0, geo.Longitude, eq.Alpha)); double delta = Angle.ToRadians(eq.Delta); double sinPi = Math.Sin(Angle.ToRadians(pi)); double A = Math.Cos(delta) * Math.Sin(H); double B = Math.Cos(delta) * Math.Cos(H) - geo.RhoCosPhi * sinPi; double C = Math.Sin(delta) - geo.RhoSinPhi * sinPi; double q = Math.Sqrt(A * A + B * B + C * C); double H_ = Angle.ToDegrees(Math.Atan2(A, B)); double alpha_ = Angle.To360(theta0 - geo.Longitude - H_); double delta_ = Angle.ToDegrees(Math.Asin(C / q)); return(new CrdsEquatorial(alpha_, delta_)); }
public static CrdsEquatorial ToEquatorial(this CrdsRectangular m, CrdsEquatorial planet, double P, double semidiameter) { // convert to polar coordinates // radius-vector of moon, in planet's equatorial radii double r = Math.Sqrt(m.X * m.X + m.Y * m.Y); // rotation angle double theta = Angle.ToDegrees(Math.Atan2(m.Y, m.X)); // rotate with position angle of the planet theta += P; // convert back to rectangular coordinates, but rotated with P angle: double x = r * Math.Cos(Angle.ToRadians(theta)); double y = r * Math.Sin(Angle.ToRadians(theta)); double dAlpha = (1 / Math.Cos(Angle.ToRadians(planet.Delta))) * x * semidiameter / 3600; double dDelta = y * semidiameter / 3600; return(new CrdsEquatorial(planet.Alpha - dAlpha, planet.Delta + dDelta)); }
/// <summary> /// Gets geocentric elongation angle of the celestial body /// </summary> /// <param name="sun">Ecliptical geocentrical coordinates of the Sun</param> /// <param name="body">Ecliptical geocentrical coordinates of the body</param> /// <returns>Geocentric elongation angle, in degrees, from -180 to 180. /// Negative sign means western elongation, positive eastern. /// </returns> /// <remarks> /// AA(II), formula 48.2 /// </remarks> // TODO: tests public static double Elongation(CrdsEcliptical sun, CrdsEcliptical body) { double beta = Angle.ToRadians(body.Beta); double lambda = Angle.ToRadians(body.Lambda); double lambda0 = Angle.ToRadians(sun.Lambda); double s = sun.Lambda; double b = body.Lambda; if (Math.Abs(s - b) > 180) { if (s < b) { s += 360; } else { b += 360; } } return(Math.Sign(b - s) * Angle.ToDegrees(Math.Acos(Math.Cos(beta) * Math.Cos(lambda - lambda0)))); }
/// <summary> /// Calculates heliocentrical coordinates of the planet using VSOP87 motion theory. /// </summary> /// <param name="planet">Planet serial number - from 1 (Mercury) to 8 (Neptune) to calculate heliocentrical coordinates.</param> /// <param name="jde">Julian Ephemeris Day</param> /// <returns>Returns heliocentric coordinates of the planet for given date.</returns> public static CrdsHeliocentrical GetPlanetCoordinates(int planet, double jde, bool highPrecision = true, bool epochOfDate = true) { Initialize(); const int L = 0; const int B = 1; const int R = 2; int p = planet - 1; int e = epochOfDate ? 1 : 0; double t = (jde - 2451545.0) / 365250.0; double t2 = t * t; double t3 = t * t2; double t4 = t * t3; double t5 = t * t4; double[] l = new double[6]; double[] b = new double[6]; double[] r = new double[6]; for (int j = 0; j < 6; j++) { l[j] = 0; for (int i = 0; i < Terms[e, p, L, j]?.Count; i++) { if (!highPrecision && i > LPTermsCount[e, p, L, j]) { break; } l[j] += Terms[e, p, L, j][i].A * Math.Cos(Terms[e, p, L, j][i].B + Terms[e, p, L, j][i].C * t); } b[j] = 0; for (int i = 0; i < Terms[e, p, B, j]?.Count; i++) { if (!highPrecision && i > LPTermsCount[e, p, B, j]) { break; } b[j] += Terms[e, p, B, j][i].A * Math.Cos(Terms[e, p, B, j][i].B + Terms[e, p, B, j][i].C * t); } r[j] = 0; for (int i = 0; i < Terms[e, p, R, j]?.Count; i++) { if (!highPrecision && i > LPTermsCount[e, p, R, j]) { break; } r[j] += Terms[e, p, R, j][i].A * Math.Cos(Terms[e, p, R, j][i].B + Terms[e, p, R, j][i].C * t); } } CrdsHeliocentrical result = new CrdsHeliocentrical(); result.L = l[0] + l[1] * t + l[2] * t2 + l[3] * t3 + l[4] * t4 + l[5] * t5; result.L = Angle.ToDegrees(result.L); result.L = Angle.To360(result.L); result.B = b[0] + b[1] * t + b[2] * t2 + b[3] * t3 + b[4] * t4 + b[5] * t5; result.B = Angle.ToDegrees(result.B); result.R = r[0] + r[1] * t + r[2] * t2 + r[3] * t3 + r[4] * t4 + r[5] * t5; return(result); }
/// <summary> /// Loads VSOP terms from file if not loaded yet /// </summary> private static void Initialize() { // high precision if (Terms == null) { Terms = new List <Term> [EPOCHS_COUNT, PLANETS_COUNT, SERIES_COUNT, POWERS_COUNT]; LPTermsCount = new int[EPOCHS_COUNT, PLANETS_COUNT, SERIES_COUNT, POWERS_COUNT]; } // already initialized else { return; } for (int e = 0; e < 2; e++) { using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream($"ADK.Data.VSOP87{(e == 0 ? "B" : "D")}.bin")) using (var reader = new BinaryReader(stream)) { while (reader.BaseStream.Position != reader.BaseStream.Length) { int p = reader.ReadInt32(); int t = reader.ReadInt32(); int power = reader.ReadInt32(); int count = reader.ReadInt32(); double A, B, C; Terms[e, p, t, power] = new List <Term>(); for (int i = 0; i < count; i++) { A = reader.ReadDouble(); B = reader.ReadDouble(); C = reader.ReadDouble(); Terms[e, p, t, power].Add(new Term(A, B, C)); } // sort terms by A coefficient descending Terms[e, p, t, power].Sort((x, y) => Math.Sign(y.A - x.A)); LPTermsCount[e, p, t, power] = count; for (int i = 0; i < count; i++) { // L, B if (t < 2) { // maximal error in seconds of arc // calculated by rule descibed in AA(II), p. 220 (Accuracy of the results) double err = Angle.ToDegrees(2 * Math.Sqrt(i + 1) * Terms[e, p, t, power][i].A) * 3600; if (err < 1) { LPTermsCount[e, p, t, power] = i; break; } } // R else { // maximal error in AU // calculated by rule descibed in AA(II), p. 220 (Accuracy of the results) double err = 2 * Math.Sqrt(i + 1) * Terms[e, p, t, power][i].A; if (err < 1e-8) { LPTermsCount[e, p, t, power] = i; break; } } } } } } }
/// <summary> /// Calculates heliocentrical coordinates of the planet using VSOP87 motion theory. /// </summary> /// <param name="planet"><see cref="Planet"/> to calculate heliocentrical coordinates.</param> /// <param name="jde">Julian Ephemeris Day</param> /// <returns>Returns heliocentric coordinates of the planet for given date.</returns> public static CrdsHeliocentrical GetPlanetCoordinates(Planet planet, double jde, bool highPrecision = true) { Initialize(highPrecision); const int L = 0; const int B = 1; const int R = 2; int p = (int)planet - 1; double t = (jde - 2451545.0) / 365250.0; double t2 = t * t; double t3 = t * t2; double t4 = t * t3; double t5 = t * t4; double[] l = new double[6]; double[] b = new double[6]; double[] r = new double[6]; List <Term>[,,] terms = highPrecision ? TermsHP : TermsLP; for (int j = 0; j < 6; j++) { l[j] = 0; for (int i = 0; i < terms[p, L, j]?.Count; i++) { l[j] += terms[p, L, j][i].A * Math.Cos(terms[p, L, j][i].B + terms[p, L, j][i].C * t); } b[j] = 0; for (int i = 0; i < terms[p, B, j]?.Count; i++) { b[j] += terms[p, B, j][i].A * Math.Cos(terms[p, B, j][i].B + terms[p, B, j][i].C * t); } r[j] = 0; for (int i = 0; i < terms[p, R, j]?.Count; i++) { r[j] += terms[p, R, j][i].A * Math.Cos(terms[p, R, j][i].B + terms[p, R, j][i].C * t); } } // Dimension coefficient. // Should be applied for the shortened VSOP87 formulae listed in AA book // because "A" coefficient expressed in 1e-8 radian for longitude and latitude and in 1e-8 AU for radius vector // Original (high-precision) version of VSOP has "A" expressed in radians and AU respectively. double d = highPrecision ? 1 : 1e-8; CrdsHeliocentrical result = new CrdsHeliocentrical(); result.L = (l[0] + l[1] * t + l[2] * t2 + l[3] * t3 + l[4] * t4 + l[5] * t5) * d; result.L = Angle.ToDegrees(result.L); result.L = Angle.To360(result.L); result.B = (b[0] + b[1] * t + b[2] * t2 + b[3] * t3 + b[4] * t4 + b[5] * t5) * d; result.B = Angle.ToDegrees(result.B); result.R = (r[0] + r[1] * t + r[2] * t2 + r[3] * t3 + r[4] * t4 + r[5] * t5) * d; return(result); }