Exemple #1
0
 private void AddEphemIfMissing(Ephemerides bodyEphemerides, string key, object value)
 {
     if (!bodyEphemerides.Select(e => e.Key).Contains(key))
     {
         bodyEphemerides.Add(new Ephemeris(key, value, Formatters.GetDefault(key)));
     }
 }
Exemple #2
0
        // TODO: add ability to specify location and preferFast flag
        public List <Ephemerides> GetEphemerides(CelestialObject body, double from, double to, double step, IEnumerable <string> categories, CancellationToken?cancelToken = null, IProgress <double> progress = null)
        {
            List <Ephemerides> all = new List <Ephemerides>();

            var config = EphemConfigs[body.GetType()];

            var itemsToBeCalled = config.Filter(categories);

            for (double jd = from; jd < to; jd += step)
            {
                if (cancelToken != null && cancelToken.Value.IsCancellationRequested)
                {
                    break;
                }
                else
                {
                    progress?.Report((jd - from) / (to - from) * 100);
                }

                var context = new SkyContext(jd, Context.GeoLocation);

                Ephemerides ephemerides = new Ephemerides(body);

                foreach (var item in itemsToBeCalled)
                {
                    ephemerides.Add(new Ephemeris(item.Category, item.Formula.DynamicInvoke(context, body), item.Formatter ?? Formatters.GetDefault(item.Category)));
                }

                all.Add(ephemerides);
            }

            return(all);
        }
Exemple #3
0
        public Ephemerides GetEphemerides(CelestialObject body, SkyContext context, IEnumerable <string> categories)
        {
            var         config          = EphemConfigs[body.GetType()];
            var         itemsToBeCalled = config.Filter(categories);
            Ephemerides ephemerides     = new Ephemerides(body);

            foreach (var item in itemsToBeCalled)
            {
                ephemerides.Add(new Ephemeris(item.Category, item.Formula.DynamicInvoke(context, body), item.Formatter ?? Formatters.GetDefault(item.Category)));
            }
            return(ephemerides);
        }
Exemple #4
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);
        }