예제 #1
0
        /// <summary>
        /// Calculates an intermediate point at any fraction along the great circle path
        /// between two points with geographical coordinates
        /// </summary>
        /// <param name="p1">Geographical coordinates of the first point</param>
        /// <param name="p2">Geographical 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 CrdsGeographical Intermediate(CrdsGeographical p1, CrdsGeographical 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.Latitude);
            double alt2 = ToRadians(p2.Latitude);
            double az1  = ToRadians(p1.Longitude);
            double az2  = ToRadians(p2.Longitude);

            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 lat = Math.Atan2(z, Math.Sqrt(x * x + y * y));
            double lon = Math.Atan2(y, x);

            return(new CrdsGeographical(ToDegrees(lon), ToDegrees(lat)));
        }
예제 #2
0
        /// <summary>
        /// Calculates distance in kilometers between 2 points on the Earth surface.
        /// </summary>
        /// <param name="g1">First point.</param>
        /// <param name="g2">Second point.</param>
        /// <returns>Distance in kilometers between 2 points.</returns>
        /// <remarks>
        /// The method is taken from https://www.movable-type.co.uk/scripts/latlong.html
        /// </remarks>
        public static double DistanceTo(this CrdsGeographical g1, CrdsGeographical g2)
        {
            const double R           = 6371;
            double       phi1        = Angle.ToRadians(g1.Latitude);
            double       phi2        = Angle.ToRadians(g2.Latitude);
            double       deltaPhi    = Angle.ToRadians(g2.Latitude - g1.Latitude);
            double       deltaLambda = Angle.ToRadians(g2.Longitude - g1.Longitude);
            double       a           = Math.Sin(deltaPhi / 2) * Math.Sin(deltaPhi / 2) + Math.Cos(phi1) * Math.Cos(phi2) * Math.Sin(deltaLambda / 2) * Math.Sin(deltaLambda / 2);
            double       c           = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));

            return(R * c);
        }
예제 #3
0
        /// <summary>
        /// Calculates angular separation between two points with geographical coordinates
        /// </summary>
        /// <param name="p1">Geographical coordinates of the first point</param>
        /// <param name="p2">Geographical coordinates of the second point</param>
        /// <returns>Angular separation in degrees</returns>
        public static double Separation(CrdsGeographical p1, CrdsGeographical p2)
        {
            double a1 = ToRadians(p1.Latitude);
            double a2 = ToRadians(p2.Latitude);
            double A1 = To360(p1.Longitude);
            double A2 = To360(p2.Longitude);

            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));
        }
예제 #4
0
        /// <summary>
        /// Finds horizon circle point for a given geographical longitude
        /// for an instant of lunar eclipse, where Moon has zero altitude.
        /// </summary>
        /// <param name="e">Besselian elements of the Moon for the given instant.</param>
        /// <param name="L">Geographical longitude, positive west, negative east, from -180 to +180 degrees.</param>
        /// <returns>
        /// Geographical coordinates for the point.
        /// </returns>
        /// <remarks>
        /// The method core is based on formulae from the book:
        /// Seidelmann, P. K.: Explanatory Supplement to The Astronomical Almanac,
        /// University Science Book, Mill Valley (California), 1992,
        /// Chapter 8 "Eclipses of the Sun and Moon"
        /// https://archive.org/download/131123ExplanatorySupplementAstronomicalAlmanac/131123-explanatory-supplement-astronomical-almanac.pdf
        /// </remarks>
        private static CrdsGeographical Project(InstantLunarEclipseElements e, double L)
        {
            CrdsGeographical g = null;

            // Nutation elements
            var nutation = Nutation.NutationElements(e.JulianDay);

            // True obliquity
            var epsilon = Date.TrueObliquity(e.JulianDay, nutation.deltaEpsilon);

            // Greenwich apparent sidereal time
            double siderealTime = Date.ApparentSiderealTime(e.JulianDay, nutation.deltaPsi, epsilon);

            // Geocenric distance to the Moon, in km
            double dist = 358473400.0 / (e.F3 * 3600);

            // Horizontal parallax of the Moon
            double parallax = LunarEphem.Parallax(dist);

            // Equatorial coordinates of the Moon, initial value is geocentric
            CrdsEquatorial eq = new CrdsEquatorial(e.Alpha, e.Delta);

            // two iterations:
            // 1st: find geo location needed to perform topocentric correction
            // 2nd: correct sublunar point with topocentric position and find true geoposition
            for (int i = 0; i < 2; i++)
            {
                // sublunar point latitude, preserve sign!
                double phi0 = Sign(e.Delta) * Abs(eq.Delta);

                // sublunar point longitude (formula 8.426-1)
                double lambda0 = siderealTime - eq.Alpha;

                // sublunar point latitude (formula 8.426-2)
                double tanPhi = -1.0 / Tan(ToRadians(phi0)) * Cos(ToRadians(lambda0 - L));
                double phi    = ToDegrees(Atan(tanPhi));

                g = new CrdsGeographical(L, phi);

                if (i == 0)
                {
                    // correct to topocentric
                    eq = eq.ToTopocentric(g, siderealTime, parallax);
                }
            }

            return(g);
        }
예제 #5
0
        /// <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);
        }
예제 #6
0
        /// <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);
        }
예제 #7
0
        /// <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_));
        }
예제 #8
0
 private static LunarEclipseLocalCircumstancesContactPoint GetLocalCircumstancesContactPoint(double jd, LunarEclipse eclipse, PolynomialLunarEclipseElements e, CrdsGeographical g)
 {
     if (!double.IsNaN(jd))
     {
         return(new LunarEclipseLocalCircumstancesContactPoint(e.GetInstantBesselianElements(jd), g));
     }
     else
     {
         return(null);
     }
 }
예제 #9
0
 public static LunarEclipseLocalCircumstances LocalCircumstances(LunarEclipse eclipse, PolynomialLunarEclipseElements e, CrdsGeographical g)
 {
     return(new LunarEclipseLocalCircumstances()
     {
         Location = g,
         PenumbralBegin = GetLocalCircumstancesContactPoint(eclipse.JulianDayFirstContactPenumbra, eclipse, e, g),
         PartialBegin = GetLocalCircumstancesContactPoint(eclipse.JulianDayFirstContactUmbra, eclipse, e, g),
         TotalBegin = GetLocalCircumstancesContactPoint(eclipse.JulianDayTotalBegin, eclipse, e, g),
         Maximum = GetLocalCircumstancesContactPoint(eclipse.JulianDayMaximum, eclipse, e, g),
         TotalEnd = GetLocalCircumstancesContactPoint(eclipse.JulianDayTotalEnd, eclipse, e, g),
         PartialEnd = GetLocalCircumstancesContactPoint(eclipse.JulianDayLastContactUmbra, eclipse, e, g),
         PenumbralEnd = GetLocalCircumstancesContactPoint(eclipse.JulianDayLastContactPenumbra, eclipse, e, g),
     });
 }
예제 #10
0
        /// <summary>
        /// Calculates instants of rising, transit and setting for non-stationary celestial body for the desired date.
        /// Non-stationary in this particular case means that body has fastly changing celestial coordinates during the day.
        /// </summary>
        /// <param name="eq">Array of three equatorial coordinates of the celestial body correspoding to local midnight, local noon, and local midnight of the following day after the desired date respectively.</param>
        /// <param name="location">Geographical location of the observation point.</param>
        /// <param name="theta0">Apparent sidereal time at Greenwich for local midnight of the desired date.</param>
        /// <param name="pi">Horizontal equatorial parallax of the body.</param>
        /// <param name="sd">Visible semidiameter of the body, expressed in degrees.</param>
        /// <returns>Instants of rising, transit and setting for the celestial body for the desired date.</returns>
        public static RTS RiseTransitSet(CrdsEquatorial[] eq, CrdsGeographical location, double theta0, double pi = 0, double sd = 0)
        {
            if (eq.Length != 3)
            {
                throw new ArgumentException("Number of equatorial coordinates in the array should be equal to 3.");
            }

            double[] alpha = new double[3];
            double[] delta = new double[3];
            for (int i = 0; i < 3; i++)
            {
                alpha[i] = eq[i].Alpha;
                delta[i] = eq[i].Delta;
            }

            Angle.Align(alpha);
            Angle.Align(delta);

            List <CrdsHorizontal> hor = new List <CrdsHorizontal>();

            for (int i = 0; i <= 24; i++)
            {
                double         n       = i / 24.0;
                CrdsEquatorial eq0     = InterpolateEq(alpha, delta, n);
                var            sidTime = InterpolateSiderialTime(theta0, n);
                hor.Add(eq0.ToTopocentric(location, sidTime, pi).ToHorizontal(location, sidTime));
            }

            var result = new RTS();

            for (int i = 0; i < 24; i++)
            {
                double n = (i + 0.5) / 24.0;

                CrdsEquatorial eq0 = InterpolateEq(alpha, delta, n);

                var sidTime = InterpolateSiderialTime(theta0, n);
                var hor0    = eq0.ToTopocentric(location, sidTime, pi).ToHorizontal(location, sidTime);

                if (double.IsNaN(result.Transit) && hor0.Altitude > 0)
                {
                    double r = SolveParabola(Math.Sin(Angle.ToRadians(hor[i].Azimuth)), Math.Sin(Angle.ToRadians(hor0.Azimuth)), Math.Sin(Angle.ToRadians(hor[i + 1].Azimuth)));
                    if (!double.IsNaN(r))
                    {
                        double t = (i + r) / 24.0;

                        eq0     = InterpolateEq(alpha, delta, t);
                        sidTime = InterpolateSiderialTime(theta0, t);

                        result.Transit         = t;
                        result.TransitAltitude = eq0.ToTopocentric(location, sidTime, pi).ToHorizontal(location, sidTime).Altitude;
                    }
                }

                if (double.IsNaN(result.Rise) || double.IsNaN(result.Set))
                {
                    double r = SolveParabola(hor[i].Altitude + sd, hor0.Altitude + sd, hor[i + 1].Altitude + sd);

                    if (!double.IsNaN(r))
                    {
                        double t = (i + r) / 24.0;
                        eq0     = InterpolateEq(alpha, delta, t);
                        sidTime = InterpolateSiderialTime(theta0, t);

                        if (double.IsNaN(result.Rise) && hor[i].Altitude + sd < 0 && hor[i + 1].Altitude + sd > 0)
                        {
                            result.Rise        = t;
                            result.RiseAzimuth = eq0.ToTopocentric(location, sidTime, pi).ToHorizontal(location, sidTime).Azimuth;
                        }

                        if (double.IsNaN(result.Set) && hor[i].Altitude + sd > 0 && hor[i + 1].Altitude + sd < 0)
                        {
                            result.Set        = t;
                            result.SetAzimuth = eq0.ToTopocentric(location, sidTime, pi).ToHorizontal(location, sidTime).Azimuth;
                        }

                        if (!double.IsNaN(result.Transit) && !double.IsNaN(result.Rise) && !double.IsNaN(result.Set))
                        {
                            break;
                        }
                    }
                }
            }

            return(result);
        }
예제 #11
0
        /// <summary>
        /// Calculates visibity details for the celestial body,
        /// </summary>
        /// <param name="eqBody">Mean equatorial coordinates of the body for the desired day.</param>
        /// <param name="eqSun">Mean equatorial coordinates of the Sun for the desired day.</param>
        /// <param name="minAltitude">Minimal altitude of the body, in degrees, to be considered as approproate for observations. By default it's 5 degrees for planet.</param>
        /// <returns><see cref="VisibilityDetails"/> instance describing details of visibility.</returns>
        // TODO: tests
        public static VisibilityDetails Details(CrdsEquatorial eqBody, CrdsEquatorial eqSun, CrdsGeographical location, double theta0, double minAltitude = 5)
        {
            var details = new VisibilityDetails();

            // period when the planet is above the horizon and its altitude is larger than "minAltitude"
            RTS body = RiseTransitSet(eqBody, location, theta0, minAltitude);

            // period when the Sun is above the horizon
            RTS sun = RiseTransitSet(eqSun, location, theta0);

            // body reaches minimal altitude but Sun does not rise at all (polar night)
            if (body.TransitAltitude > minAltitude && sun.TransitAltitude <= 0)
            {
                details.Period   = VisibilityPeriod.WholeNight;
                details.Duration = body.Duration * 24;
            }
            // body does not reach the minimal altitude during the day
            else if (body.TransitAltitude <= minAltitude)
            {
                details.Period   = VisibilityPeriod.Invisible;
                details.Duration = 0;
            }
            // there is a day/night change during the day and body reaches minimal altitude
            else if (body.TransitAltitude > minAltitude)
            {
                // "Sun is below horizon" time range, expressed in degrees (0 is midnight, 180 is noon)
                var r1 = new AngleRange(sun.Set * 360, (1 - sun.Duration) * 360);

                // "body is above horizon" time range, expressed in degrees (0 is midnight, 180 is noon)
                var r2 = new AngleRange(body.Rise * 360, body.Duration * 360);

                // find the intersections of two ranges
                var ranges = r1.Overlaps(r2);

                // no intersections of time ranges
                if (!ranges.Any())
                {
                    details.Period   = VisibilityPeriod.Invisible;
                    details.Duration = 0;
                    details.Begin    = double.NaN;
                    details.End      = double.NaN;
                }
                // the body is observable during the day
                else
                {
                    // duration of visibility
                    details.Duration = ranges.Sum(i => i.Range / 360 * 24);

                    // beginning of visibility
                    details.Begin = ranges.First().Start / 360;

                    // end of visibility
                    details.End = (details.Begin + details.Duration / 24) % 1;

                    // Evening time range, expressed in degrees
                    // Start is a sunset time, range is a timespan from sunset to midnight.
                    var rE = new AngleRange(sun.Set * 360, (1 - sun.Set) * 360);

                    // Night time range, expressed in degrees
                    // Start is a midnight time, range is a half of timespan from midnight to sunrise
                    var rN = new AngleRange(0, sun.Rise / 2 * 360);

                    // Morning time range, expressed in degrees
                    // Start is a half of time from midnight to sunrise, range is a time to sunrise
                    var rM = new AngleRange(sun.Rise / 2 * 360, sun.Rise / 2 * 360);

                    foreach (var r in ranges)
                    {
                        var isEvening = r.Overlaps(rE);
                        if (isEvening.Any())
                        {
                            details.Period |= VisibilityPeriod.Evening;
                        }

                        var isNight = r.Overlaps(rN);
                        if (isNight.Any())
                        {
                            details.Period |= VisibilityPeriod.Night;
                        }

                        var isMorning = r.Overlaps(rM);
                        if (isMorning.Any())
                        {
                            details.Period |= VisibilityPeriod.Morning;
                        }
                    }
                }
            }

            return(details);
        }
예제 #12
0
        /// <summary>
        /// Calculates instants of rising, transit and setting for stationary celestial body for the desired date.
        /// Stationary in this particular case means that body has unchanged (or slightly changing) celestial coordinates during the day.
        /// </summary>
        /// <param name="eq">Equatorial coordinates of the celestial body.</param>
        /// <param name="location">Geographical location of the observation point.</param>
        /// <param name="theta0">Apparent sidereal time at Greenwich for local midnight of the desired date.</param>
        /// <param name="minAltitude">Minimal altitude of the body above the horizon, in degrees, to detect rise/set. Used only for calculating visibility conditions.</param>
        /// <returns>Instants of rising, transit and setting for the celestial body for the desired date.</returns>
        public static RTS RiseTransitSet(CrdsEquatorial eq, CrdsGeographical location, double theta0, double minAltitude = 0)
        {
            List <CrdsHorizontal> hor = new List <CrdsHorizontal>();

            for (int i = 0; i <= 24; i++)
            {
                double n       = i / 24.0;
                var    sidTime = InterpolateSiderialTime(theta0, n);
                hor.Add(eq.ToHorizontal(location, sidTime));
            }

            var result = new RTS();

            for (int i = 0; i < 24; i++)
            {
                double n = (i + 0.5) / 24.0;

                var sidTime = InterpolateSiderialTime(theta0, n);
                var hor0    = eq.ToHorizontal(location, sidTime);

                if (double.IsNaN(result.Transit) && hor0.Altitude > 0)
                {
                    double r = SolveParabola(Math.Sin(Angle.ToRadians(hor[i].Azimuth)), Math.Sin(Angle.ToRadians(hor0.Azimuth)), Math.Sin(Angle.ToRadians(hor[i + 1].Azimuth)));
                    if (!double.IsNaN(r))
                    {
                        double t = (i + r) / 24.0;
                        sidTime = InterpolateSiderialTime(theta0, t);

                        result.Transit         = t;
                        result.TransitAltitude = eq.ToHorizontal(location, sidTime).Altitude;
                    }
                }

                if (double.IsNaN(result.Rise) || double.IsNaN(result.Set))
                {
                    double r = SolveParabola(hor[i].Altitude - minAltitude, hor0.Altitude - minAltitude, hor[i + 1].Altitude - minAltitude);

                    if (!double.IsNaN(r))
                    {
                        double t = (i + r) / 24.0;
                        sidTime = InterpolateSiderialTime(theta0, t);

                        if (double.IsNaN(result.Rise) && hor[i].Altitude - minAltitude < 0 && hor[i + 1].Altitude - minAltitude > 0)
                        {
                            result.Rise        = t;
                            result.RiseAzimuth = eq.ToHorizontal(location, sidTime).Azimuth;
                        }

                        if (double.IsNaN(result.Set) && hor[i].Altitude - minAltitude > 0 && hor[i + 1].Altitude - minAltitude < 0)
                        {
                            result.Set        = t;
                            result.SetAzimuth = eq.ToHorizontal(location, sidTime).Azimuth;
                        }

                        if (!double.IsNaN(result.Transit) && !double.IsNaN(result.Rise) && !double.IsNaN(result.Set))
                        {
                            break;
                        }
                    }
                }
            }

            return(result);
        }
예제 #13
0
        /// <summary>
        /// Creates new instance
        /// </summary>
        public LunarEclipseLocalCircumstancesContactPoint(InstantLunarEclipseElements e, CrdsGeographical g)
        {
            CrdsEquatorial eq = new CrdsEquatorial(e.Alpha, e.Delta);

            // Nutation elements
            var nutation = Nutation.NutationElements(e.JulianDay);

            // True obliquity
            var epsilon = Date.TrueObliquity(e.JulianDay, nutation.deltaEpsilon);

            // Greenwich apparent sidereal time
            double siderealTime = Date.ApparentSiderealTime(e.JulianDay, nutation.deltaPsi, epsilon);

            // Geocenric distance to the Moon, in km
            double dist = 358473400.0 / (e.F3 * 3600);

            // Horizontal parallax of the Moon
            double parallax = LunarEphem.Parallax(dist);

            // Topocentrical equatorial coordinates
            var eqTopo = eq.ToTopocentric(g, siderealTime, parallax);

            // Horizontal coordinates
            var h = eqTopo.ToHorizontal(g, siderealTime);

            // Hour angle
            double H = Coordinates.HourAngle(siderealTime, g.Longitude, eqTopo.Alpha);

            // Position angles

            // Parallactic angle - AA(II), p.98, formula 14.1
            double qAngle = ToDegrees(Atan2(Sin(ToRadians(H)), Tan(ToRadians(g.Latitude)) * Cos(ToRadians(eqTopo.Delta)) - Sin(ToRadians(eqTopo.Delta)) * Cos(ToRadians(H))));

            // Position angle, measured from North to East (CCW)
            double pAngle = To360(ToDegrees(Atan2(e.X, e.Y)));

            // Position angle, measured from Zenith CCW
            double zAngle = To360(pAngle - qAngle);

            JulianDay     = e.JulianDay;
            LunarAltitude = h.Altitude;
            QAngle        = qAngle;
            PAngle        = pAngle;
            ZAngle        = zAngle;
            X             = e.X;
            Y             = e.Y;
            F1            = e.F1;
            F2            = e.F2;
            F3            = e.F3;
        }
예제 #14
0
 public CrdsGeographical(CrdsGeographical other)
     : this(other.Longitude, other.Latitude, other.UtcOffset, other.Elevation, other.TimeZoneId, other.LocationName)
 {
 }
예제 #15
0
 /// <summary>
 /// Creates new point with Julian Day value and coordinates
 /// </summary>
 /// <param name="jd">Julian Day value</param>
 /// <param name="c">Coordinates of the point</param>
 public SolarEclipsePoint(double jd, CrdsGeographical c)
 {
     JulianDay   = jd;
     Coordinates = c;
 }