Last active
August 27, 2017 14:24
-
-
Save airbreather/f374f8085af45ff185e539c0ae4f0024 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Globalization; | |
| using System.Linq; | |
| using System.Xml.Linq; | |
| namespace GpxCore | |
| { | |
| public sealed class Gpx | |
| { | |
| public const string GpxNamespace = "http://www.topografix.com/GPX/1/1"; | |
| public static readonly XName GpxElementName = XName.Get("gpx", GpxNamespace); | |
| public GpxWaypoint[] Waypoints; | |
| public GpxTrack[] Tracks; | |
| public GpxRoute[] Routes; | |
| public static Gpx Load(XElement gpxElement) => | |
| new Gpx | |
| { | |
| Waypoints = gpxElement.Elements(XName.Get("wpt", GpxNamespace)).Select(GpxWaypoint.Load).ToArray(), | |
| Routes = gpxElement.Elements(XName.Get("rte", GpxNamespace)).Select(GpxRoute.Load).ToArray(), | |
| Tracks = gpxElement.Elements(XName.Get("trk", GpxNamespace)).Select(GpxTrack.Load).ToArray(), | |
| }; | |
| } | |
| public sealed class GpxWaypoint | |
| { | |
| public double Longitude; | |
| public double Latitude; | |
| public static GpxWaypoint Load(XElement wptElement) => | |
| new GpxWaypoint | |
| { | |
| Longitude = Double.Parse(wptElement.Attribute("lon").Value, NumberStyles.Float, CultureInfo.InvariantCulture), | |
| Latitude = Double.Parse(wptElement.Attribute("lat").Value, NumberStyles.Float, CultureInfo.InvariantCulture), | |
| }; | |
| } | |
| public sealed class GpxTrack | |
| { | |
| public GpxTrackSegment[] Segments; | |
| public static GpxTrack Load(XElement trkElement) => | |
| new GpxTrack | |
| { | |
| Segments = trkElement.Elements(XName.Get("trkseg", Gpx.GpxNamespace)).Select(GpxTrackSegment.Load).ToArray(), | |
| }; | |
| } | |
| public sealed class GpxTrackSegment | |
| { | |
| public GpxWaypoint[] Waypoints; | |
| public static GpxTrackSegment Load(XElement trksegElement) => | |
| new GpxTrackSegment | |
| { | |
| Waypoints = trksegElement.Elements(XName.Get("trkpt", Gpx.GpxNamespace)).Select(GpxWaypoint.Load).ToArray(), | |
| }; | |
| } | |
| public sealed class GpxRoute | |
| { | |
| public GpxWaypoint[] Waypoints; | |
| public static GpxRoute Load(XElement rteElement) => | |
| new GpxRoute | |
| { | |
| Waypoints = rteElement.Elements(XName.Get("rtept", Gpx.GpxNamespace)).Select(GpxWaypoint.Load).ToArray(), | |
| }; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections.Generic; | |
| using System.IO; | |
| using System.Linq; | |
| using System.Xml; | |
| using System.Xml.Linq; | |
| using GpxCore; | |
| namespace GpxDemo | |
| { | |
| internal static class Program | |
| { | |
| private const string GpxList = @"<?xml version=""1.0"" encoding=""utf-8""?> | |
| <myList> | |
| <gpx xmlns=""http://www.topografix.com/GPX/1/1""> | |
| <wpt lon=""-100"" lat=""42"" /> | |
| <wpt lon=""-101"" lat=""43"" /> | |
| <wpt lon=""-102"" lat=""44"" /> | |
| <wpt lon=""-103"" lat=""45"" /> | |
| <wpt lon=""-104"" lat=""46"" /> | |
| <wpt lon=""-105"" lat=""47"" /> | |
| <rte> | |
| <rtept lon=""-100.2"" lat=""42.9"" /> | |
| <rtept lon=""-100.3"" lat=""42.8"" /> | |
| <rtept lon=""-100.4"" lat=""42.7"" /> | |
| <rtept lon=""-100.5"" lat=""42.6"" /> | |
| <rtept lon=""-100.6"" lat=""42.5"" /> | |
| <rtept lon=""-100.7"" lat=""42.4"" /> | |
| </rte> | |
| <rte> | |
| <rtept lon=""-101.2"" lat=""43.9"" /> | |
| <rtept lon=""-101.3"" lat=""43.8"" /> | |
| <rtept lon=""-101.4"" lat=""43.7"" /> | |
| <rtept lon=""-101.5"" lat=""43.6"" /> | |
| <rtept lon=""-101.6"" lat=""43.5"" /> | |
| <rtept lon=""-101.7"" lat=""43.4"" /> | |
| </rte> | |
| <trk> | |
| <trkseg> | |
| <trkpt lon=""-102.2"" lat=""44.9"" /> | |
| <trkpt lon=""-102.3"" lat=""44.8"" /> | |
| <trkpt lon=""-102.4"" lat=""44.7"" /> | |
| <trkpt lon=""-102.5"" lat=""44.6"" /> | |
| <trkpt lon=""-102.6"" lat=""44.5"" /> | |
| <trkpt lon=""-102.7"" lat=""44.4"" /> | |
| </trkseg> | |
| <trkseg> | |
| <trkpt lon=""-103.2"" lat=""42.9"" /> | |
| <trkpt lon=""-103.3"" lat=""42.8"" /> | |
| <trkpt lon=""-103.4"" lat=""42.7"" /> | |
| <trkpt lon=""-103.5"" lat=""42.6"" /> | |
| <trkpt lon=""-103.6"" lat=""42.5"" /> | |
| <trkpt lon=""-103.7"" lat=""42.4"" /> | |
| </trkseg> | |
| </trk> | |
| <trk> | |
| <trkseg> | |
| <trkpt lon=""-112.2"" lat=""47.9"" /> | |
| <trkpt lon=""-112.3"" lat=""47.8"" /> | |
| <trkpt lon=""-112.4"" lat=""47.7"" /> | |
| <trkpt lon=""-112.5"" lat=""47.6"" /> | |
| <trkpt lon=""-112.6"" lat=""47.5"" /> | |
| <trkpt lon=""-112.7"" lat=""47.4"" /> | |
| </trkseg> | |
| <trkseg> | |
| <trkpt lon=""-113.2"" lat=""46.9"" /> | |
| <trkpt lon=""-113.3"" lat=""46.8"" /> | |
| <trkpt lon=""-113.4"" lat=""46.7"" /> | |
| <trkpt lon=""-113.5"" lat=""46.6"" /> | |
| <trkpt lon=""-113.6"" lat=""46.5"" /> | |
| <trkpt lon=""-113.7"" lat=""46.4"" /> | |
| </trkseg> | |
| </trk> | |
| </gpx> | |
| <gpx xmlns=""http://www.topografix.com/GPX/1/1""> | |
| <wpt lon=""-130"" lat=""52"" /> | |
| <wpt lon=""-131"" lat=""53"" /> | |
| <wpt lon=""-132"" lat=""54"" /> | |
| <wpt lon=""-133"" lat=""55"" /> | |
| <wpt lon=""-134"" lat=""56"" /> | |
| <wpt lon=""-135"" lat=""57"" /> | |
| <rte> | |
| <rtept lon=""-130.2"" lat=""52.9"" /> | |
| <rtept lon=""-130.3"" lat=""52.8"" /> | |
| <rtept lon=""-130.4"" lat=""52.7"" /> | |
| <rtept lon=""-130.5"" lat=""52.6"" /> | |
| <rtept lon=""-130.6"" lat=""52.5"" /> | |
| <rtept lon=""-130.7"" lat=""52.4"" /> | |
| </rte> | |
| <rte> | |
| <rtept lon=""-131.2"" lat=""53.9"" /> | |
| <rtept lon=""-131.3"" lat=""53.8"" /> | |
| <rtept lon=""-131.4"" lat=""53.7"" /> | |
| <rtept lon=""-131.5"" lat=""53.6"" /> | |
| <rtept lon=""-131.6"" lat=""53.5"" /> | |
| <rtept lon=""-131.7"" lat=""53.4"" /> | |
| </rte> | |
| <trk> | |
| <trkseg> | |
| <trkpt lon=""-132.2"" lat=""54.9"" /> | |
| <trkpt lon=""-132.3"" lat=""54.8"" /> | |
| <trkpt lon=""-132.4"" lat=""54.7"" /> | |
| <trkpt lon=""-132.5"" lat=""54.6"" /> | |
| <trkpt lon=""-132.6"" lat=""54.5"" /> | |
| <trkpt lon=""-132.7"" lat=""54.4"" /> | |
| </trkseg> | |
| <trkseg> | |
| <trkpt lon=""-133.2"" lat=""52.9"" /> | |
| <trkpt lon=""-133.3"" lat=""52.8"" /> | |
| <trkpt lon=""-133.4"" lat=""52.7"" /> | |
| <trkpt lon=""-133.5"" lat=""52.6"" /> | |
| <trkpt lon=""-133.6"" lat=""52.5"" /> | |
| <trkpt lon=""-133.7"" lat=""52.4"" /> | |
| </trkseg> | |
| </trk> | |
| <trk> | |
| <trkseg> | |
| <trkpt lon=""-132.2"" lat=""57.9"" /> | |
| <trkpt lon=""-132.3"" lat=""57.8"" /> | |
| <trkpt lon=""-132.4"" lat=""57.7"" /> | |
| <trkpt lon=""-132.5"" lat=""57.6"" /> | |
| <trkpt lon=""-132.6"" lat=""57.5"" /> | |
| <trkpt lon=""-132.7"" lat=""57.4"" /> | |
| </trkseg> | |
| <trkseg> | |
| <trkpt lon=""-133.2"" lat=""56.9"" /> | |
| <trkpt lon=""-133.3"" lat=""56.8"" /> | |
| <trkpt lon=""-133.4"" lat=""56.7"" /> | |
| <trkpt lon=""-133.5"" lat=""56.6"" /> | |
| <trkpt lon=""-133.6"" lat=""56.5"" /> | |
| <trkpt lon=""-133.7"" lat=""56.4"" /> | |
| </trkseg> | |
| </trk> | |
| </gpx> | |
| </myList> | |
| "; | |
| private static void Main(string[] args) | |
| { | |
| var doc = XDocument.Parse(GpxList); | |
| // get all track segments in the list | |
| var allTrackSegments = from gpxElement in doc.Descendants(Gpx.GpxElementName) | |
| let gpx = Gpx.Load(gpxElement) | |
| from track in gpx.Tracks | |
| from trackSegment in track.Segments | |
| select trackSegment; | |
| foreach (var trackSegment in allTrackSegments) | |
| { | |
| var begin = trackSegment.Waypoints[0]; | |
| var end = trackSegment.Waypoints[trackSegment.Waypoints.Length - 1]; | |
| Console.WriteLine($"track segment has {trackSegment.Waypoints.Length} waypoints and goes from (lon: {begin.Longitude}, lat: {begin.Latitude}) to (lon: {end.Longitude}, lat: {end.Latitude})"); | |
| } | |
| // get all routes that have any points west of 130 degrees west longitude. | |
| var matchingRoutes = from gpxElement in doc.Descendants(Gpx.GpxElementName) | |
| let gpx = Gpx.Load(gpxElement) | |
| from route in gpx.Routes | |
| where route.Waypoints.Any(wpt => wpt.Longitude < -130) | |
| select route; | |
| foreach (var matchingRoute in matchingRoutes) | |
| { | |
| var begin = matchingRoute.Waypoints[0]; | |
| var end = matchingRoute.Waypoints[matchingRoute.Waypoints.Length - 1]; | |
| Console.WriteLine($"route has {matchingRoute.Waypoints.Length} waypoints and goes from (lon: {begin.Longitude}, lat: {begin.Latitude}) to (lon: {end.Longitude}, lat: {end.Latitude})"); | |
| } | |
| // find the bounding box of all points. | |
| // imagine that the list was HUGE and we didn't want to fully buffer it, so this reader | |
| // would actually be reading from some remote stream instead of the string. | |
| double minlon = Double.MaxValue; | |
| double minlat = Double.MaxValue; | |
| double maxlon = Double.MinValue; | |
| double maxlat = Double.MinValue; | |
| using (var stringReader = new StringReader(GpxList)) | |
| using (var reader = XmlReader.Create(stringReader)) | |
| { | |
| foreach (var wpt in ReadAllWaypoints(reader)) | |
| { | |
| if (wpt.Longitude < minlon) | |
| { | |
| minlon = wpt.Longitude; | |
| } | |
| if (wpt.Latitude < minlat) | |
| { | |
| minlat = wpt.Latitude; | |
| } | |
| if (wpt.Longitude > maxlon) | |
| { | |
| maxlon = wpt.Longitude; | |
| } | |
| if (wpt.Latitude > maxlat) | |
| { | |
| maxlat = wpt.Latitude; | |
| } | |
| } | |
| } | |
| Console.WriteLine($"minlon: {minlon}"); | |
| Console.WriteLine($"minlat: {minlat}"); | |
| Console.WriteLine($"maxlon: {maxlon}"); | |
| Console.WriteLine($"maxlat: {maxlat}"); | |
| } | |
| private static IEnumerable<GpxWaypoint> ReadAllWaypoints(XmlReader reader) | |
| { | |
| while (reader.Read()) | |
| { | |
| if (reader.NodeType != XmlNodeType.Element || reader.NamespaceURI != Gpx.GpxNamespace) | |
| { | |
| continue; | |
| } | |
| switch (reader.Name) | |
| { | |
| case "wpt": | |
| case "trkpt": | |
| case "rtept": | |
| yield return GpxWaypoint.Load((XElement)XElement.ReadFrom(reader)); | |
| break; | |
| } | |
| } | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment