/// <summary> /// Calculates an intermediate point at any fraction along the great circle path /// between two points with horizontal coordinates /// </summary> /// <param name="p1">Horizontal coordinates of the first point</param> /// <param name="p2">Horizontal coordinates of the second point</param> /// <param name="fraction">Fraction along great circle route (f=0 is point 1, f=1 is point 2).</param> /// <returns> /// The intermediate point at specified fraction /// </returns> /// <remarks> /// Formula is taken from <see href="http://www.movable-type.co.uk/scripts/latlong.html"/> /// that is originally based on <see cref="http://www.edwilliams.org/avform.htm#Intermediate"/>. /// </remarks> public static CrdsHorizontal Intermediate(CrdsHorizontal p1, CrdsHorizontal p2, double fraction) { if (fraction < 0 || fraction > 1) { throw new ArgumentException("Fraction value should be in range [0, 1]", nameof(fraction)); } double d = ToRadians(Separation(p1, p2)); double a, b; if (d <= 1e-6) { a = 1 - fraction; b = fraction; } else { a = Math.Sin((1 - fraction) * d) / Math.Sin(d); b = Math.Sin(fraction * d) / Math.Sin(d); } double alt1 = ToRadians(p1.Altitude); double alt2 = ToRadians(p2.Altitude); double az1 = ToRadians(p1.Azimuth); double az2 = ToRadians(p2.Azimuth); double x = a * Math.Cos(alt1) * Math.Cos(az1) + b * Math.Cos(alt2) * Math.Cos(az2); double y = a * Math.Cos(alt1) * Math.Sin(az1) + b * Math.Cos(alt2) * Math.Sin(az2); double z = a * Math.Sin(alt1) + b * Math.Sin(alt2); double alt = Math.Atan2(z, Math.Sqrt(x * x + y * y)); double az = Math.Atan2(y, x); return(new CrdsHorizontal(ToDegrees(az), ToDegrees(alt))); }
public static CrdsHorizontal WithRefraction(this CrdsHorizontal h0) { //if (h0.Altitude < 0) return h0; double R = 1.02 / Math.Tan(Angle.ToRadians(h0.Altitude + 10.3 / (h0.Altitude + 5.11))); return(new CrdsHorizontal(h0.Azimuth, h0.Altitude + R / 60)); }
/// <summary> /// Calculates angular separation between two points with horizontal coordinates /// </summary> /// <param name="p1">Horizontal coordinates of the first point</param> /// <param name="p2">Horizontal coordinates of the second point</param> /// <returns>Angular separation in degrees</returns> public static double Separation(CrdsHorizontal p1, CrdsHorizontal p2) { double a1 = ToRadians(p1.Altitude); double a2 = ToRadians(p2.Altitude); double A1 = p1.Azimuth; double A2 = p2.Azimuth; 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> /// 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> /// Sets horizontal coordinates values. /// </summary> /// <param name="other">Instance of coordinates to be copied.</param> public void Set(CrdsHorizontal other) { Azimuth = other.Azimuth; Altitude = other.Altitude; }
/// <summary> /// Creates a pair of horizontal coordinates by copying from other instance. /// </summary> /// <param name="other">Instance of coordinates to be copied.</param> public CrdsHorizontal(CrdsHorizontal other) { Azimuth = other.Azimuth; Altitude = other.Altitude; }