Ejemplo n.º 1
0
        private ICollection <AstroEvent> FindSolarEclipses(AstroEventsContext context)
        {
            List <AstroEvent> events = new List <AstroEvent>();

            int ln = LunarEphem.Lunation(context.From, LunationSystem.Meeus);

            do
            {
                SolarEclipse eclipse = GetNearestSolarEclipse(ln, next: true, saros: false);
                double       jd      = eclipse.JulianDayMaximum;
                if (jd <= context.To)
                {
                    var pbe       = GetBesselianElements(jd);
                    var localCirc = SolarEclipses.LocalCircumstances(pbe, context.GeoLocation);

                    string type            = Text.Get($"SolarEclipse.Type.{eclipse.EclipseType}");
                    string subtype         = eclipse.IsNonCentral ? $" {Text.Get("SolarEclipse.Type.NoCentral")}" : "";
                    string phase           = eclipse.EclipseType == SolarEclipseType.Partial ? $" ({Text.Get("SolarEclipse.MaxPhase")} {Formatters.Phase.Format(eclipse.Magnitude)})" : "";
                    double jdMax           = localCirc.MaxMagnitude > 0 ? localCirc.Maximum.JulianDay : jd;
                    string localVisibility = GetLocalVisibilityString(eclipse, localCirc);

                    events.Add(new AstroEvent(jdMax, Text.Get("SolarEclipse.Event", ("type", type), ("subtype", subtype), ("phase", phase), ("localVisibility", localVisibility)), sun, moon));
                    ln = eclipse.MeeusLunationNumber + 1;
                }
                else
                {
                    break;
                }
            }while (true);
            return(events);
        }
Ejemplo n.º 2
0
 /// <inheritdoc />
 public SolarEclipse GetNearestSolarEclipse(int ln, bool next, bool saros)
 {
     do
     {
         ln += (next ? 1 : -1) * (saros ? 223 : 1);
         var eclipse = SolarEclipses.NearestEclipse(ln, next);
         if (eclipse.IsUncertain)
         {
             var  pbe     = GetBesselianElements(eclipse.JulianDayMaximum);
             var  be      = pbe.GetInstantBesselianElements(eclipse.JulianDayMaximum);
             bool isExist = Math.Sqrt(be.X * be.X + be.Y * be.Y) - be.L1 <= 0.999;
             if (isExist)
             {
                 eclipse.IsUncertain = false;
                 return(eclipse);
             }
             else
             {
                 continue;
             }
         }
         else
         {
             return(eclipse);
         }
     }while (true);
 }
Ejemplo n.º 3
0
 /// <inheritdoc/>
 public ICollection <SolarEclipseLocalCircumstances> FindLocalCircumstancesForCities(PolynomialBesselianElements be, ICollection <CrdsGeographical> cities, CancellationToken?cancelToken = null, IProgress <double> progress = null)
 {
     return(cities
            .Distinct()
            .Select(c => SolarEclipses.LocalCircumstances(be, c))
            .ToArray());
 }
Ejemplo n.º 4
0
        public void FindInstantBesselianElements()
        {
            // 11 Aug 1999, 11:00:00 TDT
            // Besselian elements are taken from
            // https://eclipse.gsfc.nasa.gov/SEsearch/SEdata.php?Ecl=+19990811
            // Sun and Moon geocentric positions are taken
            // from NASA horizons tool
            // https://ssd.jpl.nasa.gov/horizons.cgi

            var position = new SunMoonPosition()
            {
                JulianDay    = 2451401.958333333,
                Sun          = new CrdsEquatorial(new HMS("09h 23m 11.27s"), new DMS("+15* 19' 30.1''")),
                Moon         = new CrdsEquatorial(new HMS("09h 23m 30.71s"), new DMS("+15* 48' 50.3''")),
                DistanceSun  = 1.5162934697E+08 / 6371.0,
                DistanceMoon = 3.7330565613E+05 / 6371.0
            };

            var elements = SolarEclipses.BesselianElements(position);

            Assert.AreEqual(15.32734, elements.D, 1e-2);
            Assert.AreEqual(343.68741, elements.Mu, 1e-1);
            Assert.AreEqual(0.070042, elements.X, 1e-2);
            Assert.AreEqual(0.502841, elements.Y, 1e-2);
            Assert.AreEqual(0.542469, elements.L1, 1e-2);
            Assert.AreEqual(-0.003650, elements.L2, 1e-2);
        }
Ejemplo n.º 5
0
        public void FindNearestSolarEclipse()
        {
            double       jd      = new Date(1993, 5, 21).ToJulianDay();
            SolarEclipse eclipse = SolarEclipses.NearestEclipse(jd, true);

            Assert.AreEqual(2449129.0979, eclipse.JulianDayMaximum, TimeSpan.FromMinutes(0.36).TotalDays);
            Assert.AreEqual(SolarEclipseType.Partial, eclipse.EclipseType);
            Assert.AreEqual(0.740, eclipse.Magnitude, 1e-3);
        }
Ejemplo n.º 6
0
        public void ProjectionTests()
        {
            {
                double           d  = 15.32558;
                double           mu = 345.88554;
                CrdsGeographical g  = new CrdsGeographical(-26.71875, 44.66865);
                Vector           v  = SolarEclipses.ProjectOnFundamentalPlane(g, d, mu);
                CrdsGeographical g0 = SolarEclipses.ProjectOnEarth(new System.Drawing.PointF((float)v.X, (float)v.Y), d, mu);
                Assert.AreEqual(g.Latitude, g0.Latitude, 1e-5);
                Assert.AreEqual(g.Longitude, g0.Longitude, 1e-5);
            }

            {
                double           d  = -23.25608;
                double           mu = 48.57292;
                CrdsGeographical g  = new CrdsGeographical(97.20703, -28.22697);
                Vector           v  = SolarEclipses.ProjectOnFundamentalPlane(g, d, mu);
                CrdsGeographical g0 = SolarEclipses.ProjectOnEarth(new System.Drawing.PointF((float)v.X, (float)v.Y), d, mu);
                Assert.AreEqual(g.Latitude, g0.Latitude, 1e-5);
                Assert.AreEqual(g.Longitude, g0.Longitude, 1e-5);
            }
        }
Ejemplo n.º 7
0
        /// <inheritdoc/>
        public ICollection <SolarEclipseLocalCircumstances> FindCitiesOnCentralLine(PolynomialBesselianElements be, ICollection <CrdsGeographical> centralLine, CancellationToken?cancelToken = null, IProgress <double> progress = null)
        {
            var cities = new List <CrdsGeographical>();

            for (int i = 0; i < centralLine.Count - 1; i++)
            {
                // Report progess
                progress?.Report((double)(i + 1) / centralLine.Count * 100);

                // Exit loop if cancel requested
                if (cancelToken?.IsCancellationRequested == true)
                {
                    return(new SolarEclipseLocalCircumstances[0]);
                }

                // 2 successive points create a central line segment
                var g0 = centralLine.ElementAt(i);
                var g1 = centralLine.ElementAt(i + 1);

                // Segment length, distance between 2 points on central line, in kilometers
                var length = g0.DistanceTo(g1);

                // Local circumstances at point "g0"
                var local = SolarEclipses.LocalCircumstances(be, g0);

                // Lunar umbra radius, in kilometers
                float r  = (float)(local.PathWidth / 2);
                float r0 = r;
                if (r < 10)
                {
                    r = 10;
                }

                if (r > 0)
                {
                    // Count of parts the segment should be splitted
                    int parts = (int)Math.Round(length / r);

                    // If the segment should be splitted
                    if (parts > 1)
                    {
                        // Find intermediate points and add closest cities
                        for (int j = 0; j < parts; j++)
                        {
                            // Exit loop if cancel requested
                            if (cancelToken?.IsCancellationRequested == true)
                            {
                                return(new SolarEclipseLocalCircumstances[0]);
                            }

                            var g         = Angle.Intermediate(g0, g1, (float)j / parts);
                            var locations = locationsManager.Search(g, r);
                            cities.AddRange(locations.Where(loc => loc.DistanceTo(g) <= r0));
                        }
                    }
                    // The segment should not be splitted, add closest cities to the first point
                    else
                    {
                        var locations = locationsManager.Search(g0, r);
                        cities.AddRange(locations.Where(loc => loc.DistanceTo(g0) <= r0));
                    }
                }
            }

            return(FindLocalCircumstancesForCities(be, cities, cancelToken, progress));
        }
Ejemplo n.º 8
0
 /// <inheritdoc/>
 public PolynomialBesselianElements GetBesselianElements(double jdMaximum)
 {
     return(SolarEclipses.BesselianElements(jdMaximum, GetSunMoonPositions(jdMaximum, 12)));
 }