/// <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> /// Adds corrections to ecliptical coordinates /// </summary> public static CrdsEcliptical operator +(CrdsEcliptical lhs, CrdsEcliptical rhs) { CrdsEcliptical ecl = new CrdsEcliptical(); ecl.Lambda = Angle.To360(lhs.Lambda + rhs.Lambda); ecl.Beta = lhs.Beta + rhs.Beta; ecl.Distance = lhs.Distance; return(ecl); }
/// <summary> /// Calculates the aberration effect for a celestial body (star or planet) for given instant. /// </summary> /// <param name="ecl">Ecliptical coordinates of the body (not corrected).</param> /// <param name="ae">Aberration elements needed for calculation of aberration correction.</param> /// <returns>Returns aberration correction values for ecliptical coordinates.</returns> /// <remarks> /// AA(II), formula 23.2 /// </remarks> public static CrdsEcliptical AberrationEffect(CrdsEcliptical ecl, AberrationElements ae) { double thetaLambda = Angle.ToRadians(ae.lambda - ecl.Lambda); double piLambda = Angle.ToRadians(ae.pi - ecl.Lambda); double beta = Angle.ToRadians(ecl.Beta); double dLambda = (-k * Math.Cos(thetaLambda) + ae.e * k * Math.Cos(piLambda)) / Math.Cos(beta); double dBeta = -k *Math.Sin(beta) * (Math.Sin(thetaLambda) - ae.e * Math.Sin(piLambda)); return(new CrdsEcliptical(dLambda / 3600, dBeta / 3600)); }
/// <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 angular separation between two points with ecliptical coordinates /// </summary> /// <param name="p1">Ecliptical coordinates of the first point</param> /// <param name="p2">Ecliptical coordinates of the second point</param> /// <returns>Angular separation in degrees</returns> public static double Separation(CrdsEcliptical p1, CrdsEcliptical p2) { double a1 = ToRadians(p1.Beta); double a2 = ToRadians(p2.Beta); double A1 = p1.Lambda; double A2 = p2.Lambda; double a = Math.Acos( Math.Sin(a1) * Math.Sin(a2) + Math.Cos(a1) * Math.Cos(a2) * Math.Cos(ToRadians(A1 - A2))); return(double.IsNaN(a) ? 0 : ToDegrees(a)); }
/// <summary> /// Gets correction for ecliptical coordinates obtained by VSOP87 theory, /// needed for conversion to standard FK5 system. /// This correction should be used only for high-precision version of VSOP87. /// </summary> /// <param name="jde">Julian Ephemeris Day</param> /// <param name="ecl">Non-corrected ecliptical coordinates of the body.</param> /// <returns>Corrections values for longutude and latitude, in degrees.</returns> /// <remarks> /// AA(II), formula 32.3. /// </remarks> public static CrdsEcliptical CorrectionForFK5(double jde, CrdsEcliptical ecl) { double T = (jde - 2451545) / 36525.0; double L_ = Angle.ToRadians(ecl.Lambda - 1.397 * T - 0.00031 * T * T); double sinL_ = Math.Sin(L_); double cosL_ = Math.Cos(L_); double deltaL = -0.09033 + 0.03916 * (cosL_ + sinL_) * Math.Tan(Angle.ToRadians(ecl.Beta)); double deltaB = 0.03916 * (cosL_ - sinL_); return(new CrdsEcliptical(deltaL / 3600, deltaB / 3600)); }
/// <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 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 ecliptical coordinates to rectangular coordinates. /// </summary> /// <param name="ecl">Ecliptical coordinates</param> /// <param name="epsilon">Obliquity of the ecliptic, in degrees.</param> /// <returns>Rectangular coordinates.</returns> public static CrdsRectangular ToRectangular(this CrdsEcliptical ecl, double epsilon) { CrdsRectangular rect = new CrdsRectangular(); double beta = Angle.ToRadians(ecl.Beta); double lambda = Angle.ToRadians(ecl.Lambda); double R = ecl.Distance; epsilon = Angle.ToRadians(epsilon); double cosBeta = Math.Cos(beta); double sinBeta = Math.Sin(beta); double sinLambda = Math.Sin(lambda); double cosLambda = Math.Cos(lambda); double sinEpsilon = Math.Sin(epsilon); double cosEpsilon = Math.Cos(epsilon); rect.X = R * cosBeta * cosLambda; rect.Y = R * (cosBeta * sinLambda * cosEpsilon - sinBeta * sinEpsilon); rect.Z = R * (cosBeta * sinLambda * sinEpsilon + sinBeta * cosEpsilon); return(rect); }
/// <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> /// Gets ecliptical coordinates of the Moon for given instant. /// </summary> /// <param name="jd">Julian Day.</param> /// <returns>Geocentric ecliptical coordinates of the Moon, referred to mean equinox of the date.</returns> /// <remarks> /// This method is taked from AA(II), chapter 47, /// and based on the Charpont ELP-2000/82 lunar theory. /// Accuracy of the method is 10" in longitude and 4" in latitude. /// </remarks> public static CrdsEcliptical GetCoordinates(double jd) { Initialize(); double T = (jd - 2451545.0) / 36525.0; double T2 = T * T; double T3 = T2 * T; double T4 = T3 * T; // Moon's mean longitude double L_ = 218.3164477 + 481267.88123421 * T - 0.0015786 * T2 + T3 / 538841.0 - T4 / 65194000.0; // Preserve the L_ value in degrees double Lm = L_; // Mean elongation of the Moon double D = 297.8501921 + 445267.1114034 * T - 0.0018819 * T2 + T3 / 545868.0 - T4 / 113065000.0; // Sun's mean anomaly double M = 357.5291092 + 35999.0502909 * T - 0.0001536 * T2 + T3 / 24490000.0; // Moon's mean anomaly double M_ = 134.9633964 + 477198.8675055 * T + 0.0087414 * T2 + T3 / 69699.0 - T4 / 14712000.0; // Moon's argument of latitude (mean dinstance of the Moon from its ascending node) double F = 93.2720950 + 483202.0175233 * T - 0.0036539 * T2 - T3 / 3526000.0 + T4 / 863310000.0; // Correction arguments double A1 = 119.75 + 131.849 * T; double A2 = 53.09 + 479264.290 * T; double A3 = 313.45 + 481266.484 * T; // Multiplier related to the eccentricity of the Earth orbit double E = 1 - 0.002516 * T - 0.0000074 * T2; L_ = Angle.ToRadians(L_); D = Angle.ToRadians(D); M = Angle.ToRadians(M); M_ = Angle.ToRadians(M_); F = Angle.ToRadians(F); A1 = Angle.ToRadians(A1); A2 = Angle.ToRadians(A2); A3 = Angle.ToRadians(A3); double Sum_l = 0; double Sum_b = 0; double Sum_r = 0; double[] DMMF = new double[] { D, M, M_, F }; double[] powE = new double[3] { 1, E, E *E }; double lrArg, bArg; for (int i = 0; i < 60; i++) { lrArg = 0; bArg = 0; for (int j = 0; j < 4; j++) { lrArg += DMMF[j] * ArgsLR[i, j]; bArg += DMMF[j] * ArgsB[i, j]; } Sum_l += SinCoeffLR[i] * Math.Sin(lrArg) * powE[Math.Abs(ArgsLR[i, 1])]; Sum_r += CosCoeffLR[i] * Math.Cos(lrArg) * powE[Math.Abs(ArgsLR[i, 1])]; Sum_b += CoeffB[i] * Math.Sin(bArg) * powE[Math.Abs(ArgsB[i, 1])]; } Sum_l += 3958 * Math.Sin(A1) + 1962 * Math.Sin(L_ - F) + 318 * Math.Sin(A2); Sum_b += -2235 * Math.Sin(L_) + 382 * Math.Sin(A3) + 175 * Math.Sin(A1 - F) + 175 * Math.Sin(A1 + F) + 127 * Math.Sin(L_ - M_) - 115 * Math.Sin(L_ + M_); CrdsEcliptical ecl = new CrdsEcliptical(); ecl.Lambda = Lm + Sum_l / 1e6; ecl.Lambda = Angle.To360(ecl.Lambda); ecl.Beta = Sum_b / 1e6; ecl.Distance = 385000.56 + Sum_r / 1e3; return(ecl); }