Exemple #1
0
        private async void GetObjectEphemeris(CelestialObject body)
        {
            var es = ViewManager.CreateViewModel <EphemerisSettingsVM>();

            es.SelectedBody  = body;
            es.JulianDayFrom = sky.Context.JulianDay;
            es.JulianDayTo   = sky.Context.JulianDay + 30;
            if (ViewManager.ShowDialog(es) ?? false)
            {
                var tokenSource = new CancellationTokenSource();
                var progress    = new Progress <double>();

                ViewManager.ShowProgress("Please wait", "Calculating ephemerides...", tokenSource, progress);

                var ephem = await Task.Run(() => sky.GetEphemerides(
                                               es.SelectedBody,
                                               es.JulianDayFrom,
                                               es.JulianDayTo,
                                               es.Step.TotalDays,
                                               es.Categories,
                                               tokenSource.Token,
                                               progress
                                               ));

                if (!tokenSource.IsCancellationRequested)
                {
                    tokenSource.Cancel();
                    var vm = ViewManager.CreateViewModel <EphemerisVM>();
                    vm.SetData(es.SelectedBody, es.JulianDayFrom, es.JulianDayTo, es.Step, ephem);
                    ViewManager.ShowWindow(vm);
                }
            }
        }
Exemple #2
0
        private void AddOrEditTrack(Track track)
        {
            var categories = sky.GetEphemerisCategories(track.Body);

            if (!(categories.Contains("Equatorial.Alpha") && categories.Contains("Equatorial.Delta")))
            {
                throw new Exception($"Ephemeris provider for type {track.Body.GetType().Name} does not provide \"Equatorial.Alpha\" and \"Equatorial.Delta\" ephemeris.");
            }

            var positions = sky.GetEphemerides(track.Body, track.From, track.To, track.Step, new[] { "Equatorial.Alpha", "Equatorial.Delta" });

            foreach (var eq in positions)
            {
                track.Points.Add(new CelestialPoint()
                {
                    Equatorial0 = new CrdsEquatorial((double)eq[0].Value, (double)eq[1].Value)
                });
            }

            int index = tracksProvider.Tracks.FindIndex(t => t.Id == track.Id);

            if (index > -1)
            {
                tracksProvider.Tracks[index] = track;
            }
            else
            {
                tracksProvider.Tracks.Add(track);
            }
        }
Exemple #3
0
        private void AddOrEditTrack(Track track)
        {
            var categories = sky.GetEphemerisCategories(track.Body);

            if (!(categories.Contains("Equatorial.Alpha") && categories.Contains("Equatorial.Delta")))
            {
                throw new Exception($"Ephemeris provider for type {track.Body.GetType().Name} does not provide \"Equatorial.Alpha\" and \"Equatorial.Delta\" ephemeris.");
            }

            var positions = sky.GetEphemerides(track.Body, track.From, track.To + track.Step, track.Step, new[] { "Equatorial.Alpha", "Equatorial.Delta" });

            foreach (var eq in positions)
            {
                track.Points.Add(new CelestialPoint()
                {
                    Equatorial0 = new CrdsEquatorial(eq.GetValue <double>("Equatorial.Alpha"), eq.GetValue <double>("Equatorial.Delta"))
                });
            }

            Track existing = trackCalc.Tracks.FirstOrDefault(t => t.Id == track.Id);

            if (existing != null)
            {
                int index = trackCalc.Tracks.IndexOf(existing);
                trackCalc.Tracks[index] = track;
            }
            else
            {
                trackCalc.Tracks.Add(track);
            }
        }
        /// <summary>
        /// Calculates solar and lunar positions at five uniformly spaced times
        /// over a specified period centered at t0, where t0 is an integer hour of day
        /// nearest to the specified time instant of eclipse maximum.
        /// </summary>
        /// <param name="jdMaximum">Instant of eclipse maximum.</param>
        /// <param name="period">Period, in hours.</param>
        /// <returns></returns>
        private SunMoonPosition[] GetSunMoonPositions(double jdMaximum, double period)
        {
            // found t0 (nearest integer hour closest to the eclipse maximum)
            double t0;
            Date   d = new Date(jdMaximum);

            if (d.Minute < 30)
            {
                t0 = jdMaximum - new TimeSpan(0, d.Minute, d.Second).TotalDays;
            }
            else
            {
                t0 = jdMaximum - new TimeSpan(0, d.Minute, d.Second).TotalDays + TimeSpan.FromHours(1).TotalDays;
            }

            // The Besselian elements are derived from a least-squares fit to elements
            // calculated at five uniformly spaced times over a period centered at t0.
            SunMoonPosition[] pos = new SunMoonPosition[5];

            double dt   = TimeSpan.FromHours(period / 2).TotalDays;
            double step = TimeSpan.FromHours(period / 4).TotalDays;

            string[] ephemerides = new[] { "Equatorial0.Alpha", "Equatorial0.Delta", "Distance" };

            var sunEphem  = sky.GetEphemerides(sun, t0 - dt, t0 + dt + 1e-6, step, ephemerides);
            var moonEphem = sky.GetEphemerides(moon, t0 - dt, t0 + dt + 1e-6, step, ephemerides);

            // astronomical unit, in km
            const double AU = 149597870;

            // earth radius, in km
            const double EARTH_RADIUS = 6371;

            for (int i = 0; i < 5; i++)
            {
                pos[i] = new SunMoonPosition()
                {
                    JulianDay    = t0 + step * (i - 2),
                    Sun          = new CrdsEquatorial(sunEphem[i].GetValue <double>("Equatorial0.Alpha"), sunEphem[i].GetValue <double>("Equatorial0.Delta")),
                    Moon         = new CrdsEquatorial(moonEphem[i].GetValue <double>("Equatorial0.Alpha"), moonEphem[i].GetValue <double>("Equatorial0.Delta")),
                    DistanceSun  = sunEphem[i].GetValue <double>("Distance") * AU / EARTH_RADIUS,
                    DistanceMoon = moonEphem[i].GetValue <double>("Distance") / EARTH_RADIUS
                };
            }

            return(pos);
        }
Exemple #5
0
 public double LunarPhaseAtMax(SkyContext ctx, Meteor m)
 {
     if (Moon == null)
     {
         Moon = sky.Search("Moon");
     }
     return(Moon != null ? (double)sky.GetEphemerides(Moon, ctx, new[] { "Phase" }).First().Value : 0);
 }
Exemple #6
0
        private Ephemerides GetObservationDetails(PlanningFilter filter, SkyContext context, CelestialObject body, bool force = false)
        {
            float? magLimit      = filter.MagLimit;
            double timeFrom      = filter.TimeFrom / 24.0;
            double timeTo        = filter.TimeTo / 24.0;
            double obsDuration   = timeTo < timeFrom ? timeTo - timeFrom + 1 : timeTo - timeFrom;
            double?durationLimit = filter.DurationLimit != null ? filter.DurationLimit / 60.0 : null;

            // Planned observation range, expressed as circular sector (angles)
            // It represents a timeframe to be compared with each celestial body visibility conditions.
            AngleRange obsRange = new AngleRange(timeFrom * 360, obsDuration * 360);

            // Ephemerides for particular celestial body
            Ephemerides bodyEphemerides = new Ephemerides(body);

            // Ephemerides available for the body
            var categories = sky.GetEphemerisCategories(body);

            var visibilityEphems = sky.GetEphemerides(body, context, new[] {
                "Visibility.Begin",
                "Visibility.End",
                "Visibility.Duration",
                "RTS.Rise",
                "RTS.Transit",
                "RTS.Set",
                "RTS.RiseAzimuth",
                "RTS.TransitAltitude",
                "RTS.SetAzimuth",
                "Magnitude"
            });

            bodyEphemerides.AddRange(visibilityEphems);

            // Body does not have magnitude
            if (!categories.Contains("Magnitude"))
            {
                if (!force && filter.SkipUnknownMagnitude)
                {
                    return(null);
                }
                // Apply "skip unknown mag" filter
                bodyEphemerides.Add(new Ephemeris("Magnitude", null, Formatters.Magnitude));
            }

            if (!force && filter.MagLimit != null)
            {
                float?mag = bodyEphemerides.GetValue <float?>("Magnitude");
                // Apply magnitude filter
                if (mag > magLimit)
                {
                    return(null);
                }
            }

            // If body has visibility ephemerides, it can be planned.
            if (categories.Contains("Visibility.Duration"))
            {
                double visDuration = visibilityEphems.GetValue <double>("Visibility.Duration");
                if (visDuration > 0)
                {
                    Date visBegin = visibilityEphems.GetValue <Date>("Visibility.Begin");

                    AngleRange visRange = new AngleRange(visBegin.Time * 360, visDuration / 24 * 360);

                    var ranges = visRange.Overlaps(obsRange);

                    if (ranges.Any())
                    {
                        double beginTime = ranges.First().Start / 360;

                        if (beginTime < timeFrom)
                        {
                            beginTime += 1;
                        }

                        double endTime = beginTime + ranges.First().Range / 360;

                        // Begin of body observation, limited by desired observation begin and end time,
                        // and expressed in Date
                        Date bodyObsBegin = new Date(context.JulianDayMidnight + beginTime, context.GeoLocation.UtcOffset);

                        // Real duration of body observation, limited by desired observation begin and end time,
                        // and expressed in hours (convert from angle range expressed in degrees):
                        double bodyObsDuration = ranges.First().Range / 360 * 24;

                        // Apply duration filter
                        if (!force && durationLimit > bodyObsDuration)
                        {
                            return(null);
                        }

                        // End of body observation, limited by desired observation begin and end time,
                        // and expressed in Date
                        Date bodyObsEnd = new Date(context.JulianDayMidnight + endTime, context.GeoLocation.UtcOffset);

                        bodyEphemerides.Add(new Ephemeris("Observation.Begin", bodyObsBegin, Formatters.Time));
                        bodyEphemerides.Add(new Ephemeris("Observation.Duration", bodyObsDuration, Formatters.VisibilityDuration));
                        bodyEphemerides.Add(new Ephemeris("Observation.End", bodyObsEnd, Formatters.Time));

                        // best time of observation (in the expected time range)
                        {
                            var transit    = visibilityEphems.GetValue <Date>("RTS.Transit");
                            var transitAlt = visibilityEphems.GetValue <double>("RTS.TransitAltitude");

                            AngleRange bodyObsRange = new AngleRange(bodyObsBegin.Time * 360, bodyObsDuration / 24 * 360);
                            AngleRange tranRange    = new AngleRange(transit.Time * 360, 1e-6);

                            if (bodyObsRange.Overlaps(tranRange).Any())
                            {
                                bodyEphemerides.Add(new Ephemeris("Observation.Best", transit, Formatters.Time));
                                bodyEphemerides.Add(new Ephemeris("Observation.BestAltitude", transitAlt, Formatters.Altitude));
                                bodyEphemerides.Add(new Ephemeris("Observation.BestAzimuth", 0.0, Formatters.Azimuth));

                                var ctxBest         = new SkyContext(transit.ToJulianEphemerisDay(), context.GeoLocation, preferFast: true);
                                var bestEphemerides = sky.GetEphemerides(body, ctxBest, new[] { "Equatorial.Alpha", "Equatorial.Delta", "Constellation" });
                                bodyEphemerides.AddRange(bestEphemerides);
                            }
                            else
                            {
                                var    ctxBegin         = new SkyContext(bodyObsBegin.ToJulianEphemerisDay(), context.GeoLocation, preferFast: true);
                                var    beginEphemerides = sky.GetEphemerides(body, ctxBegin, new[] { "Horizontal.Altitude", "Horizontal.Azimuth", "Equatorial.Alpha", "Equatorial.Delta", "Constellation" });
                                double altBegin         = beginEphemerides.GetValue <double>("Horizontal.Altitude");
                                double aziBegin         = beginEphemerides.GetValue <double>("Horizontal.Azimuth");

                                var    ctxEnd         = new SkyContext(bodyObsEnd.ToJulianEphemerisDay(), context.GeoLocation, preferFast: true);
                                var    endEphemerides = sky.GetEphemerides(body, ctxEnd, new[] { "Horizontal.Altitude", "Horizontal.Azimuth", "Equatorial.Alpha", "Equatorial.Delta", "Constellation" });
                                double altEnd         = endEphemerides.GetValue <double>("Horizontal.Altitude");
                                double aziEnd         = endEphemerides.GetValue <double>("Horizontal.Azimuth");

                                if (altBegin >= altEnd)
                                {
                                    bodyEphemerides.Add(new Ephemeris("Observation.Best", bodyObsBegin, Formatters.Time));
                                    bodyEphemerides.Add(new Ephemeris("Observation.BestAltitude", altBegin, Formatters.Altitude));
                                    bodyEphemerides.Add(new Ephemeris("Observation.BestAzimuth", aziBegin, Formatters.Azimuth));
                                    bodyEphemerides.AddRange(beginEphemerides);
                                }
                                else
                                {
                                    bodyEphemerides.Add(new Ephemeris("Observation.Best", bodyObsEnd, Formatters.Time));
                                    bodyEphemerides.Add(new Ephemeris("Observation.BestAltitude", altEnd, Formatters.Altitude));
                                    bodyEphemerides.Add(new Ephemeris("Observation.BestAzimuth", aziEnd, Formatters.Azimuth));
                                    bodyEphemerides.AddRange(endEphemerides);
                                }
                            }
                        }

                        return(bodyEphemerides);
                    }
                }
            }

            // body observation duration does not match with desired time
            // or body does not observable at all,
            // or no info provided about observation
            if (force)
            {
                bodyEphemerides.Add(new Ephemeris("Observation.Begin", new Date(double.NaN), Formatters.Time));
                bodyEphemerides.Add(new Ephemeris("Observation.Duration", double.NaN, Formatters.VisibilityDuration));
                bodyEphemerides.Add(new Ephemeris("Observation.End", new Date(double.NaN), Formatters.Time));
                bodyEphemerides.Add(new Ephemeris("Observation.Best", new Date(double.NaN), Formatters.Time));
                bodyEphemerides.Add(new Ephemeris("Observation.BestAltitude", double.NaN, Formatters.Altitude));
                bodyEphemerides.Add(new Ephemeris("Observation.BestAzimuth", double.NaN, Formatters.Azimuth));
                bodyEphemerides.AddRange(visibilityEphems);
                var ctx = new SkyContext(filter.JulianDayMidnight, filter.ObserverLocation, preferFast: true);
                bodyEphemerides.AddRange(sky.GetEphemerides(body, ctx, new[] { "Horizontal.Altitude", "Horizontal.Azimuth", "Equatorial.Alpha", "Equatorial.Delta", "Constellation" }));

                // final check: add fictive/empty ephemerides as it needed by planner
                AddEphemIfMissing(bodyEphemerides, "Constellation", null);
                AddEphemIfMissing(bodyEphemerides, "Equatorial.Alpha", double.NaN);
                AddEphemIfMissing(bodyEphemerides, "Equatorial.Delta", double.NaN);
                AddEphemIfMissing(bodyEphemerides, "Horizontal.Altitude", double.NaN);
                AddEphemIfMissing(bodyEphemerides, "Horizontal.Azimuth", double.NaN);
                AddEphemIfMissing(bodyEphemerides, "Constellation", null);
                AddEphemIfMissing(bodyEphemerides, "RTS.RiseAzimuth", double.NaN);
                AddEphemIfMissing(bodyEphemerides, "RTS.SetAzimuth", double.NaN);
                AddEphemIfMissing(bodyEphemerides, "RTS.TransitAltitude", double.NaN);

                return(bodyEphemerides);
            }

            return(null);
        }