/// <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()); }
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); }
/// <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)); }