private double QueryGoogleElevation(AXPoint point) { var altitude = 0.0; var template = "http://maps.googleapis.com/maps/api/elevation/xml?locations={0},{1}&sensor=true"; var llPos = new UtmCoordinates(Datum.WGS84, Engine.Settings.UtmZone, point.Easting, point.Northing, 0).ToLatLon(Datum.WGS84); var url = string.Format(NumberFormatInfo.InvariantInfo, template, llPos.Latitude.Degrees, llPos.Longitude.Degrees); try { var wCli = new WebClient() { Encoding = Encoding.UTF8, }; var XMLstr = wCli.DownloadString(url); var xml = XElement.Parse(XMLstr); altitude = double.Parse(xml.Descendants(XName.Get("elevation")).First().Value, NumberFormatInfo.InvariantInfo); } catch { AddNote(string.Format("could not retrieve ground elevation, using 0m MSL"), true); } return(altitude); }
private double QueryEarthtoolsElevation(AXPoint point) { var altitude = 0.0; var template = "http://www.earthtools.org/height/{0}/{1}"; var llPos = new UtmCoordinates(Datum.WGS84, Engine.Settings.UtmZone, point.Easting, point.Northing, 0).ToLatLon(Datum.WGS84); var url = string.Format(NumberFormatInfo.InvariantInfo, template, llPos.Latitude.Degrees, llPos.Longitude.Degrees); try { var wCli = new WebClient() { Encoding = Encoding.UTF8, }; var XMLstr = wCli.DownloadString(url); var xml = XElement.Parse(XMLstr); altitude = double.Parse(xml.Descendants(XName.Get("meters")).First().Value, NumberFormatInfo.InvariantInfo); } catch { AddNote(string.Format("could not retrieve ground elevation, using 0m MSL"), true); } return(altitude); }
public AXPoint FindGroundContact(AXPoint reference, bool backwards) { var track = CleanTrack as IEnumerable <AXPoint>; if (backwards) { //take off can't be after first marker if (Markers.Count > 0 && Markers.First().Time < reference.Time) { reference = Markers.First(); } track = track.Reverse().Where(p => reference == null || p.Time <= reference.Time); } else { //landing can't be before last marker if (Markers.Count > 0 && Markers.Last().Time > reference.Time) { reference = Markers.Last(); } track = track.Where(p => reference == null || p.Time >= reference.Time); } AXPoint groundContact = null; AXPoint point_m1 = null; var smoothedSpeed = double.NaN; foreach (var point in track) { if (point_m1 != null) { try { if (double.IsNaN(smoothedSpeed)) { smoothedSpeed = Math.Abs(Physics.Velocity3D(point, point_m1)); } else { smoothedSpeed = (Math.Abs(Physics.Velocity3D(point, point_m1)) + smoothedSpeed * (Settings.Smoothness - 1)) / Settings.Smoothness; } if (smoothedSpeed < Settings.MinSpeed) { groundContact = point; break; } } catch (Exception ex) { Debug.WriteLine(ex); } } point_m1 = point; } return(groundContact); }
protected void Worker_RunWorkerCompleted(object s, RunWorkerCompletedEventArgs args) { if (args.Error != null) { ShowError(args.Error.Message); } else if (args.Cancelled) { ShowError("Cancelled"); } else { var result = (string)args.Result; switch (result) { case "openScript": Report = Engine.Report; TrackPointer = null; Tools.TrackPointsCount = Engine.VisibleTrack.Length; RaisePropertyChanged("Engine"); RaisePropertyChanged("Report"); Tools.SelectStatic(); break; case "openTrack": Report = Engine.Report; if (string.IsNullOrEmpty(Report.Debriefer)) { Report.Debriefer = Debriefer; } //if (Report.PilotId <= 0) //{ // ShowError("The pilot number cannot be zero"); // return; //} TrackPointer = null; Tools.TrackPointsCount = Engine.VisibleTrack.Length; RaisePropertyChanged("Report"); Tools.SelectPilotDependent(); break; case "process": Tools.SelectProcessed(); break; case "batchProcess": Engine.Reset(); Engine.Display(); Report = Engine.Report; RaisePropertyChanged("Report"); Tools.SelectStatic(); break; } } Cursor = Cursors.Arrow; }
public override ValidationResult Validate(object value, CultureInfo cultureInfo) { try { var point = AXPoint.Parse((string)value); return(new ValidationResult(true, null)); } catch { return(new ValidationResult(false, "Value is not a valid point")); } }
//constructor protected FlightReport(FlightSettings settings) { Settings = settings; SignatureStatus = SignatureStatus.NotSigned; pilotId = 0; LoggerModel = ""; LoggerSerialNumber = ""; debriefers = new List <string>(); OriginalTrack = new AXPoint[0]; Markers = new ObservableCollection <AXWaypoint>(); DeclaredGoals = new ObservableCollection <GoalDeclaration>(); Notes = new ObservableCollection <string>(); }
public override void CheckConstructorSyntax() { base.CheckConstructorSyntax(); switch (Definition.ObjectType) { default: throw new ArgumentException("Unknown map type '" + Definition.ObjectType + "'"); case "BITMAP": AssertNumberOfParametersOrDie(Definition.ObjectParameters.Length == 1); //load the georeferenced image to retrieve top-left and bottom-right corners Exception exception = null; var t = new Thread(() => { try { var map = new GeoreferencedImage(Path.Combine(Directory.GetCurrentDirectory(), Definition.ObjectParameters[0])); topLeft = new AXPoint(DateTime.Now, map.TopLeft.X, map.TopLeft.Y, 0); bottomRight = new AXPoint(DateTime.Now, map.BottomRight.X, map.BottomRight.Y, 0); } catch (Exception ex) { exception = ex; } }); // ensure we are doing this in the main thread t.SetApartmentState(ApartmentState.STA); t.Start(); t.Join(); //throw any exception if (exception != null) { throw exception; } break; case "BLANK": AssertNumberOfParametersOrDie(Definition.ObjectParameters.Length == 2); topLeft = ResolveOrDie <ScriptingPoint>(0).Point; bottomRight = ResolveOrDie <ScriptingPoint>(1).Point; break; } Engine.Settings.TopLeft = topLeft; Engine.Settings.BottomRight = bottomRight; }
//Handles all property changes from the Tools window private void Tools_PropertyChanged(Object sender, PropertyChangedEventArgs args) { if (Engine != null) { switch (args.PropertyName) { case "TrackType": Engine.VisibleTrackType = Tools.TrackType; Tools.TrackPointsCount = Engine.VisibleTrack.Length; Engine.Display(); break; case "PointerIndex": if (Report != null) { TrackPointer = Engine.VisibleTrack[Tools.PointerIndex]; Engine.TrackPointer.Position = TrackPointer.ToWindowsPoint(); if (Tools.KeepPointerCentered) { MapViewer.PanTo(Engine.TrackPointer.Position); } RaisePropertyChanged("TrackPointer"); } break; case "KeepPointerCentered": Engine.KeepPointerCentered = Tools.KeepPointerCentered; if (Tools.KeepPointerCentered) { MapViewer.PanTo(Engine.TrackPointer.Position); } break; case "LayerVisibilityMask": MapViewer.LayerVisibilityMask = Tools.LayerVisibilityMask; break; default: throw new NotImplementedException(); } } }
/* * new 2011 RPZ penalty draft * public double ScaledRPZInfringement(AXPoint point) * { * double infringement = 0; * * if (point == null) * Trace.WriteLine("Area " + ObjectName + ": the testing point is null", ObjectClass); * else * { * //if (Contains(point)) * { * switch (ObjectType) * { * case "CIRCLE": * { * var hInfringement = radius - Physics.Distance2D(center.Point, point); * var vInfringement = upperLimit - point.Altitude; * infringement = Math.Sqrt(hInfringement * hInfringement + vInfringement * vInfringement) / 8; * } * break; * * case "DOME": * infringement = radius - Physics.Distance2D(center.Point, point) / 8; * break; * * case "POLY": * { * //TODO: implement polygonal RPZ * //var hInfringement = min(distance2D(p, foreach segment in outline)); * //var vInfringement = upperLimit - point.Altitude; * //infringement = Math.Sqrt(hInfringement * hInfringement + vInfringement * vInfringement) / 8; * * * //Vector p, q; * //q = new Vector(outline[outline.Count - 1].Easting, outline[outline.Count - 1].Northing); * //for (var i = 0; i < outline.Count; i++) * //{ * // p = q; * // q = new Vector(outline[i].Easting, outline[i].Northing); * * // var pq = (q - p); * // pq = pq / Math.Sqrt(pq.X * pq.X + pq.Y * pq.Y); * //} * } * throw new NotImplementedException(); * break; * } * } * } * * return infringement; * } */ /// <summary>Check if a given point is inside the polygonal area. 2D only. /// Considers that the last point is the same as the first (ie: for a square, only 4 points are needed) /// </summary> /// <param name="point">Point to check.</param> /// <returns>True if the point is inside the area.</returns> private bool InPolygon(AXPoint testPoint) { // Checks the number of intersections for an horizontal ray passing from the exterior of the polygon to testPoint. // If it is odd then the point lies inside the polygon. bool isInside = false; AXPoint point1, point2; for (int pointIndex1 = 0, pointIndex2 = outline.Count - 1; pointIndex1 < outline.Count; pointIndex2 = pointIndex1++) { point1 = outline[pointIndex1]; point2 = outline[pointIndex2]; if ((((point1.Northing <= testPoint.Northing) && (testPoint.Northing < point2.Northing)) || ((point2.Northing <= testPoint.Northing) && (testPoint.Northing < point1.Northing))) && (testPoint.Easting - point1.Easting < (point2.Easting - point1.Easting) * (testPoint.Northing - point1.Northing) / (point2.Northing - point1.Northing))) { isInside = !isInside; } } return(isInside); }
protected void DetectTakeOffAndLanding() { // find the highest point in flight AXPoint highest = null; foreach (var point in CleanTrack) { if (highest == null || point.Altitude > highest.Altitude) { highest = point; } } if (highest == null) //highest == null is caused by empty track. Probably wrong log file date or UTM zone in settings. { Notes.Add("Empty track file! Check the flight date and time and UTM zone."); } else { // find take off point TakeOffPoint = FindGroundContact(highest, true); if (TakeOffPoint == null) { TakeOffPoint = CleanTrack.First(); TakeOffPoint.Remarks = "Take off point not found. Using first track point"; Notes.Add(TakeOffPoint.Remarks); } // find landing point LandingPoint = FindGroundContact(highest, false); if (LandingPoint == null) { LandingPoint = CleanTrack.Last(); LandingPoint.Remarks = "Landing point not found. Using last track point."; Notes.Add(LandingPoint.Remarks); } } }
private void AddDeclaredGoal_Click(object sender, RoutedEventArgs e) { GoalDeclaration declaration = null; if (sender is Button) { if (listBoxDeclaredGoals.SelectedItem != null) { declaration = (GoalDeclaration)listBoxDeclaredGoals.SelectedItem; } else { declaration = new GoalDeclaration(0, Engine.Settings.Date, "0000/0000", 0); } } else if (sender is MenuItem) { var point = new AXPoint(DateTime.Now, MapViewer.MousePointerPosition.X, MapViewer.MousePointerPosition.Y, 0); declaration = new GoalDeclaration(0, Engine.Settings.Date, point.ToString(AXPointInfo.CompetitionCoords10).Trim(), double.NaN); } if (declaration != null) { var dlg = new InputWindow(s => GoalDeclaration.Parse(s) != null) { Title = "Enter goal declaration", Text = declaration.ToString(AXPointInfo.Name | AXPointInfo.Date | AXPointInfo.Time | AXPointInfo.Declaration | AXPointInfo.Altitude) }; dlg.ShowDialog(); if (dlg.Response == System.Windows.Forms.DialogResult.OK) { Report.AddDeclaredGoal(GoalDeclaration.Parse(dlg.Text)); Engine.Display(); } } }
/// <summary>Checks if a point is inside the map boundaries /// </summary> /// <param name="p"></param> /// <returns></returns> public bool IsInside(AXPoint p) { return(p.Easting >= topLeft.Easting && p.Easting <= bottomRight.Easting && p.Northing >= bottomRight.Northing && p.Northing <= topLeft.Northing); }
public bool Contains(AXPoint point) { var isInside = false; if (point == null) { Trace.WriteLine("Area " + Definition.ObjectName + ": the testing point is null", Definition.ObjectClass); } else { switch (Definition.ObjectType) { case "CYLINDER": if (center.Point != null) { isInside = point.Altitude >= lowerLimit && point.Altitude <= upperLimit && Physics.Distance2D(center.Point, point) <= radius; } break; case "SPHERE": if (center.Point != null) { isInside = Physics.Distance3D(center.Point, point) <= radius; } break; case "PRISM": isInside = point.Altitude >= lowerLimit && point.Altitude <= upperLimit && InPolygon(point); break; case "TIME": isInside = point.Time >= lowerTime && point.Time <= upperTime; break; case "UNION": foreach (var area in areas) { isInside = area.Contains(point); if (isInside) { break; } } break; case "INTERSECTION": foreach (var area in areas) { isInside = area.Contains(point); if (!isInside) { break; } } break; case "SUBTRACTION": foreach (var area in areas) { if (area.Contains(point)) { if (isInside) { isInside = false; break; } else { isInside = true; } } } break; default: throw new ArgumentException(string.Format("Contains() not implemented for '{0}'", Definition.ObjectType)); } } return(isInside); }
protected void DoTrackCleanUp() { int nTime = 0, nDupe = 0, nSpike = 0; var validPoints = new List <AXPoint>(); var minValidTime = Date + new TimeSpan(4, 0, 0); //04:00(am) or 16:00(pm) local var maxValidTime = Date + new TimeSpan(12, 0, 0); //12:00(am) or 24:00(pm) local AXPoint point_m1 = null; AXPoint point_m2 = null; foreach (var point in OriginalTrack) { // remove points before/after valid times if (point.Time < minValidTime || point.Time > maxValidTime) { nTime++; continue; } // remove dupe if (point_m1 != null && Physics.TimeDiff(point, point_m1).TotalSeconds == 0) { nDupe++; continue; } // remove spike //TODO: consider removing spikes by change in direction if (point_m2 != null && Physics.Acceleration3D(point, point_m1, point_m2) > Settings.MaxAcceleration) { nSpike++; continue; } validPoints.Add(point); point_m2 = point_m1; point_m1 = point; } Notes.Add(string.Format("Original track has {0} points", OriginalTrack.Length)); if (nTime > 0) { Notes.Add(string.Format("{0} out-of-time points removed", nTime)); } if (nDupe > 0) { Notes.Add(string.Format("{0} duplicated points removed", nDupe)); } if (nSpike > 0) { Notes.Add(string.Format("{0} spike points removed", nSpike)); } cleanTrack = validPoints.ToArray(); if (cleanTrack.Length == 0) { Notes.Add("Empty track file! Check the flight date and time and UTM zone."); } else if (Settings.InterpolationInterval > 0) { var nBefore = cleanTrack.Length; //cleanTrack = Interpolation.Linear(cleanTrack, Settings.InterpolationInterval, Settings.InterpolationMaxGap).ToArray(); cleanTrack = Interpolation.Spline(cleanTrack, Settings.InterpolationInterval, Settings.InterpolationMaxGap).ToArray(); Notes.Add(string.Format("{0} points added by interpolation", cleanTrack.Length - nBefore)); } }
//factory public static FlightReport Load(string debriefer, string filePath, FlightSettings settings) { FlightReport report = null; var ext = Path.GetExtension(filePath).ToLower(); if (ext == SerializedFileExtension) { //deserialize report report = ObjectSerializer <FlightReport> .Load(filePath, serializationFormat); report.Debriefer = debriefer; report.DoTrackCleanUp(); } else { var logFile = LoggerFile.Load(filePath, settings.UtcOffset, settings.AltitudeCorrectionsFileName); //check pilot id var pilotId = logFile.PilotId; if (pilotId == 0) { //try to get the pilot Id from filename //The file name must contain a P or p followed with pilot number (1 to 3 digits) //examples: f001_p021_l0.trk, Flight01P001.trk, 20120530AM_p01.trk, 0530AMP02_1.trk var pattern = @"P(\d{1,3})"; var input = Path.GetFileName(filePath); var matches = Regex.Matches(input, pattern, RegexOptions.IgnoreCase); if (matches.Count == 1) { pilotId = int.Parse(matches[0].Groups[1].Value); } if (pilotId == 0) { throw new Exception( "The pilot id is not present in the track log file and it could not be inferred from the file name.\n" + "The file name must contain a P or p followed with pilot number (1 to 3 digits)\n" + "examples: f001_p021_l0.trk, Flight01P001.trk, 20120530AM_p01.trk, 0530AMP02_1.trk" ); } } //Convert geographical coordinates to AX coordinates var tracklog = logFile.GetTrackLog(); var track = new AXPoint[tracklog.Length]; Parallel.For(0, track.Length, i => { track[i] = settings.FromGeoToAXPoint(tracklog[i], logFile.IsAltitudeBarometric); }); var markers = new ObservableCollection <AXWaypoint>(); foreach (var m in logFile.GetMarkers()) { markers.Add(settings.FromGeoToAXWaypoint(m, logFile.IsAltitudeBarometric)); } var declarations = new ObservableCollection <GoalDeclaration>(); foreach (var d in logFile.GetGoalDeclarations()) { declarations.Add(d); } //Make new report report = new FlightReport(settings) { Debriefer = debriefer, IsDirty = true, LogFile = logFile, SignatureStatus = logFile.SignatureStatus, pilotId = pilotId, //don't use PilotId on constructor! LoggerModel = logFile.LoggerModel, LoggerSerialNumber = logFile.LoggerSerialNumber, OriginalTrack = track, Markers = markers, DeclaredGoals = declarations, Notes = new ObservableCollection <string>() }; switch (logFile.SignatureStatus) { case SignatureStatus.NotSigned: report.Notes.Add("The log file is not signed"); break; case SignatureStatus.Genuine: report.Notes.Add("The log file has a valid signature"); break; case SignatureStatus.Counterfeit: report.Notes.Add("*** THE LOG FILE HAS AN INVALID SIGNATURE! ***"); break; } report.DoTrackCleanUp(); report.DetectTakeOffAndLanding(); } return(report); }