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); } }
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); } }
private void BuildCategoriesTree() { Nodes.Clear(); if (SelectedBody != null) { var categories = sky.GetEphemerisCategories(SelectedBody); var groups = categories.GroupBy(cat => cat.Split('.').First()); Node root = new Node(Text.Get("EphemeridesSettingsWindow.Ephemerides.All")); root.CheckedChanged += Root_CheckedChanged; string selectedBodyTypeName = SelectedBody.GetType().Name; foreach (var group in groups) { Node node = new Node(Text.Get($"{selectedBodyTypeName}.{group.Key}"), group.Key); if (group.Count() > 1) { foreach (var item in group) { node.Children.Add(new Node(Text.Get($"{selectedBodyTypeName}.{item}"), item)); } } root.Children.Add(node); } Nodes.Add(root); root.IsChecked = true; } }
private void MapRightClick(PointF point) { map.SelectedObject = map.FindObject(point); map.Invalidate(); ContextMenuItems.Clear(); ContextMenuItems.Add(new MenuItemVM() { Header = "Info", Command = MapDoubleClickCommand, CommandParameter = point, IsEnabled = map.SelectedObject != null }); ContextMenuItems.Add(null); ContextMenuItems.Add(new MenuItemVM() { Header = "Center", Command = CenterOnPointCommand, CommandParameter = point }); ContextMenuItems.Add(new MenuItemVM() { Header = "Search object...", Command = SearchObjectCommand }); ContextMenuItems.Add(new MenuItemVM() { Header = "Go to point..." }); ContextMenuItems.Add(null); ContextMenuItems.Add(new MenuItemVM() { Header = "Ephemerides", IsEnabled = map.SelectedObject != null && sky.GetEphemerisCategories(map.SelectedObject).Any(), Command = GetObjectEphemerisCommand, CommandParameter = map.SelectedObject }); // dynamic menu items from plugins foreach (var configItem in contextMenuItemsConfig) { ContextMenuItems.Add(new MenuItemVM() { Header = configItem.Text, IsEnabled = configItem.EnabledCondition(), IsCheckable = configItem.CheckedCondition != null, IsChecked = configItem.CheckedCondition != null ? configItem.CheckedCondition() : false, Command = new Command(configItem.Action) }); } ContextMenuItems.Add(null); ContextMenuItems.Add(new MenuItemVM() { Header = map.LockedObject != null ? (map.SelectedObject != null && map.SelectedObject != map.LockedObject ? "Lock" : "Unlock") : "Lock", IsEnabled = map.LockedObject != null || map.SelectedObject != null, Command = LockOnObjectCommand, CommandParameter = map.SelectedObject }); NotifyPropertyChanged(nameof(ContextMenuItems)); }
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); }