Example #1
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;
        }
Example #2
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);
        }
Example #3
0
        public static PolynomialLunarEclipseElements BesselianElements(double jdMaximum, SunMoonPosition[] positions)
        {
            if (positions.Length != 5)
            {
                throw new ArgumentException("Five positions are required", nameof(positions));
            }

            double step = positions[1].JulianDay - positions[0].JulianDay;

            if (!positions.Zip(positions.Skip(1),
                               (a, b) => new { a, b })
                .All(p => Abs(p.b.JulianDay - p.a.JulianDay - step) <= 1e-6))
            {
                throw new ArgumentException("Positions should be sorted ascending by JulianDay value, and have same JulianDay step.", nameof(positions));
            }

            // 5 time instants required
            InstantLunarEclipseElements[] elements = new InstantLunarEclipseElements[5];

            PointF[] points = new PointF[5];
            for (int i = 0; i < 5; i++)
            {
                elements[i] = BesselianElements(positions[i]);
                points[i].X = i - 2;
            }

            // Alpha expressed in degrees and can cross zero point (360 -> 0).
            // Values must be aligned in order to avoid crossing.
            double[] Alpha = Align(elements.Select(e => e.Alpha).ToArray());

            return(new PolynomialLunarEclipseElements()
            {
                JulianDay0 = positions[2].JulianDay,
                JulianDayMaximum = jdMaximum,
                DeltaT = Date.DeltaT(positions[2].JulianDay),
                Step = step,
                X = LeastSquares.FindCoeffs(points.Select((p, i) => new PointF(p.X, (float)elements[i].X)), 3),
                Y = LeastSquares.FindCoeffs(points.Select((p, i) => new PointF(p.X, (float)elements[i].Y)), 3),
                F1 = LeastSquares.FindCoeffs(points.Select((p, i) => new PointF(p.X, (float)elements[i].F1)), 3),
                F2 = LeastSquares.FindCoeffs(points.Select((p, i) => new PointF(p.X, (float)elements[i].F2)), 3),
                F3 = LeastSquares.FindCoeffs(points.Select((p, i) => new PointF(p.X, (float)elements[i].F3)), 3),
                Alpha = LeastSquares.FindCoeffs(points.Select((p, i) => new PointF(p.X, (float)Alpha[i])), 3),
                Delta = LeastSquares.FindCoeffs(points.Select((p, i) => new PointF(p.X, (float)elements[i].Delta)), 3),
            });
        }
Example #4
0
        private static IList <CrdsGeographical> FindCurvePoints(InstantLunarEclipseElements e)
        {
            var curve = new List <CrdsGeographical>();

            var p0 = Project(e, -180);

            curve.Add(new CrdsGeographical(p0.Longitude, -88 * Sign(e.Delta)));

            for (int i = -180; i <= 180; i++)
            {
                var p = Project(e, i);
                curve.Add(p);
            }

            var p1 = Project(e, 180);

            curve.Add(new CrdsGeographical(p1.Longitude, -88 * Sign(e.Delta)));

            return(curve);
        }