Пример #1
0
        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);
        }
Пример #2
0
        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);
        }
Пример #3
0
        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);
        }
Пример #4
0
        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;
        }
Пример #5
0
 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"));
     }
 }
Пример #6
0
 //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>();
 }
Пример #7
0
        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;
        }
Пример #8
0
        //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();
                }
            }
        }
Пример #9
0
        /*
         * 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);
        }
Пример #10
0
        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);
                }
            }
        }
Пример #11
0
        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();
                }
            }
        }
Пример #12
0
 /// <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);
 }
Пример #13
0
        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);
        }
Пример #14
0
        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));
            }
        }
Пример #15
0
        //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);
        }