public void Import() { importResult = new ImportResult(); if (BeginWork != null) BeginWork(this, new EventArgs()); // The trackpoints List<RouteSegment> routeSegments = new List<RouteSegment>(); bool lastTrackpointWasInvalid = false; bool thisTrackpointIsInvalid = false; RouteSegment rs = new RouteSegment(); int current = 0; int total = sessionToImport.Trackpoints.Count; foreach (D303_Trk_Point_Type tp in sessionToImport.Trackpoints) { Waypoint waypoint = new Waypoint(); waypoint.Time = tp.TimeAsDateTime; waypoint.LongLat = new LongLat(tp.Position.LongitudeAsDegrees, tp.Position.LatitudeAsDegrees); waypoint.Altitude = (double)tp.Altitude; waypoint.HeartRate = (double)tp.HeartRate; thisTrackpointIsInvalid = (tp.Position.Latitude == 2147483647 && tp.Position.Longitude == 2147483647); if (!thisTrackpointIsInvalid) rs.Waypoints.Add(waypoint); if (thisTrackpointIsInvalid && lastTrackpointWasInvalid && rs.Waypoints.Count > 0) { routeSegments.Add(rs); rs = new RouteSegment(); } lastTrackpointWasInvalid = thisTrackpointIsInvalid; current++; if (WorkProgress != null && current % 10 == 0) { WorkProgress(this, new WorkProgressEventArgs((double)current / total)); } } if (rs.Waypoints.Count > 0) { routeSegments.Add(rs); } // The laps List<double> elapsedTimes = new List<double>(); double elapsedTime = 0; DateTime startTime = DateTime.MinValue; foreach (D1001_Lap_Type xLap in sessionToImport.Laps) { if (startTime == DateTime.MinValue) startTime = xLap.StartTimeAsDateTime; elapsedTimes.Add(elapsedTime); elapsedTime += (double)xLap.TotalTime / 100; } LapCollection laps = RouteImporterUtil.CreateLapsFromElapsedTimes(startTime, elapsedTimes, routeSegments); importResult.Route = new Route(routeSegments); importResult.Laps = laps; importResult.Succeeded = true; if (EndWork != null) EndWork(this, new EventArgs()); }
/// <summary> /// Opens a document stored in the old QuickRoute XML file format. This version can't save documents in this file format. /// </summary> /// <param name="fileName">The file name of the QuickRoute 1.0 xml document.</param> /// <param name="settings">The document settings to apply.</param> /// <returns></returns> public static Document OpenFromXml(string fileName, DocumentSettings settings) { XmlTextReader reader = null; RouteSegment rs = new RouteSegment(); HandleCollection handles = new HandleCollection(); Map map; try { reader = new XmlTextReader(fileName); reader.WhitespaceHandling = WhitespaceHandling.None; reader.ReadStartElement("QuickRoute"); reader.ReadStartElement("Route"); while (reader.Read() && reader.NodeType != XmlNodeType.EndElement) { while (reader.NodeType != XmlNodeType.Element) reader.Read(); Waypoint t = new Waypoint(); t.Time = DateTime.Parse(reader.GetAttribute("time")); t.LongLat = new LongLat(); t.LongLat.Longitude = double.Parse(reader.GetAttribute("longitude")); t.LongLat.Latitude = double.Parse(reader.GetAttribute("latitude")); t.Altitude = double.Parse(reader.GetAttribute("altitude")); t.HeartRate = int.Parse(reader.GetAttribute("heartRate")); rs.Waypoints.Add(t); } reader.ReadEndElement(); reader.ReadStartElement("Markers"); while (reader.Name == "Handle") { reader.Read(); Handle h = new Handle(); h.ParameterizedLocation = new ParameterizedLocation(0, double.Parse(reader.GetAttribute("value"))); reader.Read(); double x = double.Parse(reader.GetAttribute("x")); double y = double.Parse(reader.GetAttribute("y")); h.Location = new PointD(x, y); reader.Read(); h.TransformationMatrix = new GeneralMatrix(3, 3); h.MarkerDrawer = (new ApplicationSettings()).DefaultDocumentSettings.DefaultSessionSettings.MarkerDrawers[MarkerType.Handle]; for (int row = 0; row < 3; row++) { for (int col = 0; col < 3; col++) { reader.Read(); h.TransformationMatrix.SetElement(row, col, double.Parse(reader.GetAttribute("value"))); } } reader.Read(); reader.ReadEndElement(); reader.ReadEndElement(); handles.Add(h); } reader.ReadEndElement(); map = new Map(Base64StringToBitmap(reader.ReadElementContentAsString())); } catch (Exception ex) { if (reader != null) reader.Close(); throw new Exception(ex.Message); } reader.Close(); List<RouteSegment> routeSegments = new List<RouteSegment>(); routeSegments.Add(rs); Document doc = new Document(map, new Route(routeSegments), new LapCollection(), null, settings); foreach (var h in handles) { doc.Sessions[0].AddHandle(h); } doc.FileFormat = QuickRouteFileFormat.Xml; doc.Initialize(); UpdateDocumentToCurrentVersion(doc); return doc; }
public void Import() { importResult = new ImportResult(); if (BeginWork != null) BeginWork(this, new EventArgs()); XmlTextReader reader = new XmlTextReader(FileName); XPathDocument doc = new XPathDocument(reader); XPathNavigator nav = doc.CreateNavigator(); XmlNamespaceManager nsManager = new XmlNamespaceManager(nav.NameTable); nsManager.AddNamespace("ns", "http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2"); XPathNodeIterator activities = nav.Select("//ns:Activity", nsManager); while (activities.MoveNext()) { XPathNavigator id = activities.Current.SelectSingleNode("ns:Id", nsManager); if (id != null && DateTime.Parse(id.Value).ToString("yyyy-MM-dd HH:mm:ss") == IdToImport) { // the activity was found // the laps XPathNodeIterator lapNodes = activities.Current.Select("ns:Lap", nsManager); List<RouteSegment> routeSegments = new List<RouteSegment>(); RouteSegment routeSegment = new RouteSegment(); while (lapNodes.MoveNext()) { // the tracks XPathNodeIterator trackNodes = lapNodes.Current.Select("ns:Track", nsManager); int trackCount = 0; while (trackNodes.MoveNext()) { if (trackCount > 0) { if (routeSegment.Waypoints.Count > 1) routeSegments.Add(routeSegment); routeSegment = new RouteSegment(); } XPathNodeIterator trackpointNodes = trackNodes.Current.Select("ns:Trackpoint", nsManager); DateTime lastTime = DateTime.MinValue; LongLat lastLongLat = null; int trackpointCount = 0; while (trackpointNodes.MoveNext()) { Waypoint waypoint = new Waypoint(); waypoint.Time = DateTime.Parse(trackpointNodes.Current.SelectSingleNode("ns:Time", nsManager).Value).ToUniversalTime(); XPathNavigator position = trackpointNodes.Current.SelectSingleNode("ns:Position", nsManager); if (position != null) { waypoint.LongLat = new LongLat( position.SelectSingleNode("ns:LongitudeDegrees", nsManager).ValueAsDouble, position.SelectSingleNode("ns:LatitudeDegrees", nsManager).ValueAsDouble); } if (trackpointNodes.Current.SelectSingleNode("ns:AltitudeMeters", nsManager) != null) { waypoint.Altitude = trackpointNodes.Current.SelectSingleNode("ns:AltitudeMeters", nsManager).ValueAsDouble; } if (trackpointNodes.Current.SelectSingleNode("ns:HeartRateBpm/ns:Value", nsManager) != null) { waypoint.HeartRate = trackpointNodes.Current.SelectSingleNode("ns:HeartRateBpm/ns:Value", nsManager).ValueAsDouble; } if (waypoint.HeartRate == null && routeSegment.LastWaypoint != null) { // sometimes heart rates are only present at some nodes, so use last valid heart rate waypoint.HeartRate = routeSegment.LastWaypoint.HeartRate; } // do not add waypoint if it has the same location or time as the previous one if (waypoint.LongLat != null && !waypoint.LongLat.Equals(lastLongLat) && waypoint.Time != lastTime) { // special handling for positionless trackpoint in the beginning, use its time together with next position if (trackpointCount == 1 && lastLongLat == null && routeSegment.Waypoints.Count == 0) waypoint.Time = lastTime; routeSegment.Waypoints.Add(waypoint); } lastLongLat = waypoint.LongLat; lastTime = waypoint.Time; trackpointCount++; } if (lastLongLat == null && routeSegment.Waypoints.Count > 1) { // special handling for positionless trackpoint in the end, use its time together with previous position routeSegment.Waypoints[routeSegment.Waypoints.Count - 1].Time = lastTime; } trackCount++; } } // add last route segment if (routeSegment.Waypoints.Count > 1) routeSegments.Add(routeSegment); // set position of all start and end waypoints of the route segments if they are null foreach (RouteSegment rs in routeSegments) { if (rs.FirstWaypoint.LongLat == null && rs.Waypoints.Count > 1) rs.Waypoints[1] = rs.Waypoints[1].Clone(); if (rs.LastWaypoint.LongLat == null && rs.Waypoints.Count > 1) rs.Waypoints[rs.Waypoints.Count - 1] = rs.Waypoints[rs.Waypoints.Count - 2].Clone(); } // the laps lapNodes = activities.Current.Select("ns:Lap", nsManager); // first store all elapsed times List<double> elapsedTimes = new List<double>(); LapCollection laps = new LapCollection(); if (lapNodes.MoveNext()) { DateTime startTime = DateTime.Parse(lapNodes.Current.GetAttribute("StartTime", "")).ToUniversalTime(); double elapsedTime = 0; do { elapsedTimes.Add(elapsedTime); elapsedTime += lapNodes.Current.SelectSingleNode("ns:TotalTimeSeconds", nsManager).ValueAsDouble; } while (lapNodes.MoveNext()); laps = RouteImporterUtil.CreateLapsFromElapsedTimes(startTime, elapsedTimes, routeSegments); } importResult.Route = new Route(routeSegments); importResult.Laps = laps; importResult.Succeeded = importResult.Route.Segments.Count > 0; if(importResult.Route.Segments.Count == 0) importResult.Error = ImportError.NoWaypoints; break; } } reader.Close(); if (EndWork != null) EndWork(this, new EventArgs()); }
public void Import() { ImportResult = new ImportResult(); if (BeginWork != null) BeginWork(this, new EventArgs()); try { using (var stream = new FileStream(FileName, FileMode.Open, FileAccess.Read)) { using (var reader = new BinaryReader(stream)) { var header = new Header(reader); var data = new Data(reader, header.DataSize); // route var routeSegment = new RouteSegment(); foreach(var w in data.Waypoints) { if(routeSegment.Waypoints.Count == 0 || routeSegment.LastWaypoint.Time < w.Time) { routeSegment.Waypoints.Add(new Waypoint(w.Time, new LongLat(w.Longitude, w.Latitude), w.Altitude, w.HeartRate, null, w.Cadence, w.Power)); } } ImportResult.Route = new Route(new List<RouteSegment>() { routeSegment }); // laps if (routeSegment.Waypoints.Count > 1) { ImportResult.Laps = new LapCollection(); ImportResult.Laps.Add(new Lap(routeSegment.FirstWaypoint.Time, LapType.Start)); foreach (var l in data.Laps) { if (l.Time > routeSegment.FirstWaypoint.Time && l.Time < routeSegment.LastWaypoint.Time) ImportResult.Laps.Add(new Lap(l.Time, LapType.Lap)); } ImportResult.Laps.Add(new Lap(routeSegment.LastWaypoint.Time, LapType.Stop)); } ImportResult.Succeeded = true; } } } catch (Exception ex) { ImportResult.Exception = ex; } if (EndWork != null) EndWork(this, new EventArgs()); }
private static Session ReadSession(BinaryReader reader, int length) { List<DateTime> mapReadingList = null; Route route = null; HandleCollection handles = null; LongLat projectionOrigin = null; LapCollection laps = null; var startPos = reader.BaseStream.Position; SessionInfo sessionInfo = null; DateTime lastTime; while (reader.BaseStream.Position < startPos + length) { var tag = (Tags)reader.ReadByte(); var tagLength = Convert.ToInt32(reader.ReadUInt32()); switch (tag) { case Tags.Route: var attributes = reader.ReadUInt16(); var extraWaypointAttributesLength = reader.ReadUInt16(); var routeSegments = new List<RouteSegment>(); var segmentCount = reader.ReadUInt32(); lastTime = DateTime.MinValue; for (var i = 0; i < segmentCount; i++) { var rs = new RouteSegment(); var waypointCount = reader.ReadUInt32(); for (var j = 0; j < waypointCount; j++) { var w = new Waypoint(); w.LongLat = ReadLongLat(reader); w.Time = ReadTime(lastTime, reader); lastTime = w.Time; if ((attributes & (UInt16)WaypointAttribute.HeartRate) == (UInt16)WaypointAttribute.HeartRate) { w.HeartRate = reader.ReadByte(); } if ((attributes & (UInt16)WaypointAttribute.Altitude) == (UInt16)WaypointAttribute.Altitude) { w.Altitude = reader.ReadInt16(); } reader.BaseStream.Position += extraWaypointAttributesLength; // for forward compatibility rs.Waypoints.Add(w); } routeSegments.Add(rs); } route = new Route(routeSegments); break; case Tags.Handles: handles = new HandleCollection(); var handleCount = reader.ReadUInt32(); var handleMarkerDrawer = SessionSettings.CreateDefaultMarkerDrawers()[MarkerType.Handle]; for (var i = 0; i < handleCount; i++) { var handle = new Handle(); // transformation matrix handle.TransformationMatrix = new GeneralMatrix(3, 3); for (var j = 0; j < 9; j++) { handle.TransformationMatrix.SetElement(j / 3, j % 3, reader.ReadDouble()); } // parameterized location var segmentIndex = Convert.ToInt32(reader.ReadUInt32()); var value = reader.ReadDouble(); handle.ParameterizedLocation = new ParameterizedLocation(segmentIndex, value); // pixel location handle.Location = new PointD(reader.ReadDouble(), reader.ReadDouble()); // type handle.Type = (Handle.HandleType)reader.ReadInt16(); // use default marker drawer handle.MarkerDrawer = handleMarkerDrawer; handles.Add(handle); } break; case Tags.ProjectionOrigin: projectionOrigin = ReadLongLat(reader); break; case Tags.Laps: laps = new LapCollection(); var lapCount = reader.ReadUInt32(); for (var i = 0; i < lapCount; i++) { var lap = new Lap(); lap.Time = DateTime.FromBinary(reader.ReadInt64()); lap.LapType = (LapType)reader.ReadByte(); laps.Add(lap); } break; case Tags.SessionInfo: sessionInfo = new SessionInfo(); sessionInfo.Person = new SessionPerson(); sessionInfo.Person.Name = ReadString(reader); sessionInfo.Person.Club = ReadString(reader); sessionInfo.Person.Id = reader.ReadUInt32(); sessionInfo.Description = ReadString(reader); // when more fields are added, check so that tagLength is not passed break; case Tags.MapReadingInfo: mapReadingList = new List<DateTime>(); lastTime = DateTime.MinValue; var startPosition = reader.BaseStream.Position; while (reader.BaseStream.Position - startPosition < tagLength) { var time = ReadTime(lastTime, reader); mapReadingList.Add(time); lastTime = time; } break; default: reader.BaseStream.Position += tagLength; break; } } if(mapReadingList != null && route != null) route = new Route(Route.AddMapReadingWaypoints(route.Segments, mapReadingList)); var session = new Session( route, laps, new Size(0, 0), handles != null && handles.Count > 0 ? handles[0].TransformationMatrix : null, projectionOrigin, new SessionSettings()); if (handles != null) { foreach (var h in handles) { session.AddHandle(h); } } if (sessionInfo != null) session.SessionInfo = sessionInfo; return session; }
/* private void ImportGPX10() { if (BeginWork != null) BeginWork(this, new EventArgs()); NumberFormatInfo nfi = new NumberFormatInfo(); nfi.NumberDecimalSeparator = "."; XmlTextReader sr = new XmlTextReader(fileName); XmlSerializer xSerializer = new XmlSerializer(typeof(gpx10Type)); gpx10Type gpx = (gpx10Type)xSerializer.Deserialize(sr); sr.Close(); XmlNamespaceManager nsManager = new XmlNamespaceManager(sr.NameTable); nsManager.AddNamespace("st", "urn:uuid:D0EB2ED5-49B6-44e3-B13C-CF15BE7DD7DD"); importResult = new ImportResult(); // route List<RouteSegment> routeSegments = new List<RouteSegment>(); foreach (gpxTrk trk in gpx.trk) { for (int i = trk.trkseg.GetLowerBound(0); i <= trk.trkseg.GetUpperBound(0); i++) { RouteSegment routeSegment = new RouteSegment(); for (int j = trk.trkseg.GetLowerBound(1); j <= trk.trkseg.GetUpperBound(1); j++) { gpxTrkTrksegTrkpt wpt = trk.trkseg[i][j]; double lat = (double)wpt.lat; double lon = (double)wpt.lon; DateTime time = wpt.time; double? heartRate = null; double? altitude = null; routeSegment.Waypoints.Add(new Waypoint(time, new LongLat(lon, lat), altitude, heartRate)); } routeSegments.Add(routeSegment); } } importResult.Route = new Route(routeSegments); // laps LapCollection laps = new LapCollection(); importResult.Laps = laps; if (EndWork != null) EndWork(this, new EventArgs()); } */ private void ImportGPX11() { ImportResult = new ImportResult(); var isGPX10 = (GPXUtil.GetGPXVersion(fileName) == GPXVersion.GPX10); string gpx10convertedFileName = null; string polarConvertedFileName = null; var originalFileName = fileName; if (BeginWork != null) BeginWork(this, new EventArgs()); // check if the file is in gpx 1.0 format and convert it to gpx 1.1 if necessary if (isGPX10) { gpx10convertedFileName = Path.GetTempFileName(); GPXUtil.ConvertGPX10ToGPX11(fileName, gpx10convertedFileName); fileName = gpx10convertedFileName; } // check if the file is an invalid Polar ProTrainer file and correct if necessary if (PolarProTrainerUtil.IsPolarProTrainerGPXFile(fileName)) { polarConvertedFileName = Path.GetTempFileName(); PolarProTrainerUtil.CorrectPolarProTrainerGPXFile(fileName, polarConvertedFileName); fileName = polarConvertedFileName; } var nfi = new NumberFormatInfo { NumberDecimalSeparator = "." }; var sr = new XmlTextReader(fileName); var xSerializer = new XmlSerializer(typeof(gpx11Type)); var gpx11 = (gpx11Type)xSerializer.Deserialize(sr); sr.Close(); var nsManager = new XmlNamespaceManager(sr.NameTable); // add namespace for split times and heart rates (from SportsTracks software) nsManager.AddNamespace("st", "urn:uuid:D0EB2ED5-49B6-44e3-B13C-CF15BE7DD7DD"); // add namespace for map reading information (QuickRoute native) nsManager.AddNamespace("mr", "http://www.matstroeng.se/quickroute/map-reading"); // pre-store heart rates in dictionary (if present) var heartRates = new Dictionary<DateTime, double>(); // pre-store map-readings in map reading collection (if present) var mapReadings = new List<DateTime>(); if (gpx11.extensions != null && gpx11.extensions.Any != null) { foreach (var element in gpx11.extensions.Any) { if (element.Name == "st:activity") { var nodes = element.SelectNodes("st:heartRateTrack/st:heartRate[@time and @bpm]", nsManager); if (nodes != null) { foreach (XmlNode node in nodes) { DateTime time; double bpm; if (DateTime.TryParse(node.Attributes["time"].Value, out time) && double.TryParse(node.Attributes["bpm"].Value, NumberStyles.Any, nfi, out bpm)) { time = time.ToUniversalTime(); if(!heartRates.ContainsKey(time)) heartRates.Add(time, bpm); } } } } if(element.Name == "mr:map-reading") { DateTime start, end; if (DateTime.TryParse(element.Attributes["start"].Value, out start) && DateTime.TryParse(element.Attributes["end"].Value, out end)) { mapReadings.Add(start.ToUniversalTime()); mapReadings.Add(end.ToUniversalTime()); } } } } mapReadings = FilterMapReadings(mapReadings); // QuickRoute route var noOfWaypoints = 0; var noOfWaypointsWithTimes = 0; var routeSegments = new List<RouteSegment>(); // first use GPX track if (gpx11.trk != null) { foreach (var trk in gpx11.trk) { // Garmin Training Center exports each lap as a separate trkseg with end time of trkseg n equal to start time of trkseg n+1 // handle this issue foreach (var trkseg in trk.trkseg) { var routeSegment = new RouteSegment(); wptType lastWpt = null; if (trkseg.trkpt != null) { foreach (var wpt in trkseg.trkpt) { if (lastWpt == null || wpt.time != lastWpt.time) { if (wpt.extensions != null && wpt.extensions.Any != null && wpt.extensions.Any[0].LocalName == "timerPaused") { // new route segment ahead if (routeSegment.Waypoints.Count > 0) routeSegments.Add(routeSegment); routeSegment = new RouteSegment(); } else { var lat = (double)wpt.lat; var lon = (double)wpt.lon; double? heartRate = null; double? altitude = null; // check for heartrate in SportsTracks extensions if (heartRates.ContainsKey(wpt.time)) heartRate = heartRates[wpt.time]; // check for heartrate in Garmin Trackpoint Extensions heartRate = GetGarminHeartRateFromWaypoint(wpt) ?? heartRate; if (wpt.eleSpecified) { altitude = (double?)wpt.ele; } if (wpt.timeSpecified) { routeSegment.Waypoints.Add(new Waypoint(wpt.time, new LongLat(lon, lat), altitude, heartRate, null)); noOfWaypointsWithTimes++; lastWpt = wpt; } } noOfWaypoints++; } } } if (routeSegment.Waypoints.Count > 0) routeSegments.Add(routeSegment); } } } // if no GPX track - use GPX route if (noOfWaypointsWithTimes == 0 && gpx11.rte != null) { foreach (var route in gpx11.rte) { var routeSegment = new RouteSegment(); foreach (var rtept in route.rtept) { if (rtept.extensions != null && rtept.extensions.Any != null && rtept.extensions.Any[0].LocalName == "timerPaused") { // new route segment ahead if (routeSegment.Waypoints.Count > 0) routeSegments.Add(routeSegment); routeSegment = new RouteSegment(); } else { var lat = (double) rtept.lat; var lon = (double) rtept.lon; double? heartRate = null; double? altitude = null; if (heartRates.ContainsKey(rtept.time)) heartRate = heartRates[rtept.time]; if (rtept.eleSpecified) { altitude = (double?) rtept.ele; } if (rtept.timeSpecified) { routeSegment.Waypoints.Add(new Waypoint(rtept.time, new LongLat(lon, lat), altitude, heartRate, null)); noOfWaypointsWithTimes++; } } noOfWaypoints++; } if (routeSegment.Waypoints.Count > 0) routeSegments.Add(routeSegment); } } // add map reading waypoints routeSegments = Route.AddMapReadingWaypoints(routeSegments, mapReadings); // concat route segments if they are close enough (oddly enough, Garmin Training Center v2 seems to create a trkseg for each lap) var lapsFromConcatenatedRouteSegments = new List<Lap>(); if (routeSegments.Count > 0) { var concatenatedRouteSegments = new List<RouteSegment>() { routeSegments[0] }; for (var i = 1; i < routeSegments.Count; i++) { if (concatenatedRouteSegments[concatenatedRouteSegments.Count - 1].LastWaypoint.Time.AddSeconds(10) > routeSegments[i].FirstWaypoint.Time) { lapsFromConcatenatedRouteSegments.Add(new Lap(concatenatedRouteSegments[concatenatedRouteSegments.Count - 1].LastWaypoint.Time, LapType.Lap)); concatenatedRouteSegments[concatenatedRouteSegments.Count - 1].Waypoints.AddRange(routeSegments[i].Waypoints); } } routeSegments = concatenatedRouteSegments; } importResult.Succeeded = (noOfWaypointsWithTimes > 0); if (ImportResult.Succeeded) { importResult.Route = new Route(routeSegments); // laps var laps = new LapCollection(); var startTime = ImportResult.Route.FirstWaypoint.Time; // from GPX st:split if (gpx11.extensions != null && gpx11.extensions.Any != null) { foreach (var element in gpx11.extensions.Any) { if (element.Name == "st:activity") { var nodes = element.SelectNodes("st:splits/st:split[@time]", nsManager); if (nodes != null) { foreach (XmlNode node in nodes) { var elapsedTime = double.Parse(node.Attributes["time"].Value, nfi); var lap = new Lap(startTime.AddSeconds(elapsedTime), LapType.Lap); laps.Add(lap); } } } } } // from GPX waypoints if (gpx11.wpt != null && laps.Count == 0) { foreach (var waypoint in gpx11.wpt) { if (waypoint.timeSpecified) { laps.Add(new Lap(waypoint.time, LapType.Lap)); } } } laps.AddRange(lapsFromConcatenatedRouteSegments); foreach (var rs in routeSegments) { laps.Add(new Lap(rs.FirstWaypoint.Time, LapType.Start)); laps.Add(new Lap(rs.LastWaypoint.Time, LapType.Stop)); } importResult.Laps = laps; } else { if (noOfWaypoints == 0) { importResult.Error = ImportError.NoWaypoints; } else if (noOfWaypointsWithTimes == 0) { importResult.Error = ImportError.NoWaypointTimes; } } if (gpx10convertedFileName != null) { File.Delete(gpx10convertedFileName); fileName = originalFileName; } if (polarConvertedFileName != null) { File.Delete(polarConvertedFileName); fileName = originalFileName; } // import Polar HRM file with same base file name as the gpx file, if existing var extension = new FileInfo(fileName).Extension; if(extension != "") { string hrmFileName = new FileInfo(fileName).FullName.Replace(extension, ".hrm"); if(File.Exists(hrmFileName)) { new PolarHRMImporter().AddLapsAndHRData(hrmFileName, importResult); } } if (EndWork != null) EndWork(this, new EventArgs()); }
public void Import() { importResult = new ImportResult(); if (BeginWork != null) BeginWork(this, new EventArgs()); StreamReader reader = new StreamReader(FileName); RouteSegment rs = new RouteSegment(); LapCollection laps = new LapCollection(); int i; string[] atoms; string line; for (i = 0; i < 3; i++) reader.ReadLine(); // start time atoms = reader.ReadLine().Split("\t".ToCharArray()); DateTime startTime = DateTime.MinValue; int firstColonPosition = atoms[1].IndexOf(":"); int lastColonPosition = atoms[1].LastIndexOf(":"); int length = lastColonPosition + 2 - firstColonPosition + 2 + 1; if (length > 0) { if(DateTime.TryParse(atoms[1].Substring(firstColonPosition - 2, lastColonPosition + 2 - firstColonPosition + 2 + 1), out startTime)) { startTime = startTime.ToUniversalTime(); } } // go to start of coordinates i = 0; while (i < 5 && !reader.EndOfStream) { line = reader.ReadLine(); if (line == "") i++; } reader.ReadLine(); reader.ReadLine(); // read all coordinates while (!reader.EndOfStream) { line = reader.ReadLine(); if (line == "") break; atoms = line.Split("\t".ToCharArray()); Waypoint w = new Waypoint(); w.Time = startTime.AddSeconds(Convert.ToInt32(atoms[0])); w.LongLat = new LongLat(ParseFRWDLongLatString(atoms[5]), ParseFRWDLongLatString(atoms[4])); double altitude; double.TryParse(LocalizeDecimalString(atoms[6]), out altitude); w.Altitude = altitude; double heartRate; double.TryParse(LocalizeDecimalString(atoms[9]), out heartRate); w.HeartRate = heartRate; rs.Waypoints.Add(w); if (atoms[1] != "") { // lap Lap lap = new Lap(); lap.LapType = LapType.Lap; lap.Time = w.Time; laps.Add(lap); } } if (laps.Count > 0) laps[0].LapType = LapType.Start; if (laps.Count > 1) laps[laps.Count - 1].LapType = LapType.Stop; importResult.Laps = laps; List<RouteSegment> routeSegments = new List<RouteSegment>(); if(rs.Waypoints.Count > 0) { routeSegments.Add(rs); importResult.Route = new Route(routeSegments); importResult.Succeeded = true; } else { importResult.Succeeded = false; importResult.Error = ImportError.NoWaypoints; } reader.Close(); if (EndWork != null) EndWork(this, new EventArgs()); }
public CutRouteData Cut(ParameterizedLocation parameterizedLocation, CutType cutType) { var cutRoute = new CutRouteData { CutType = cutType }; switch (cutType) { case CutType.Before: cutRoute.Segments.AddRange(segments.GetRange(0, parameterizedLocation.SegmentIndex)); if (!parameterizedLocation.IsNode) { // cut between two waypoints: create cut waypoint Waypoint cutWaypoint = CreateWaypointFromParameterizedLocation(parameterizedLocation); var rs = new RouteSegment(); segments.RemoveRange(0, parameterizedLocation.SegmentIndex); rs.Waypoints.AddRange(segments[0].Waypoints.GetRange(0, (int)parameterizedLocation.Ceiling().Value)); cutRoute.Segments.Add(rs); segments[0].Waypoints.RemoveRange(0, (int)parameterizedLocation.Ceiling().Value); segments[0].Waypoints.Insert(0, cutWaypoint); cutRoute.WaypointInsertedAtCut = cutWaypoint; } else { // cut exactly at a waypoint var rs = new RouteSegment(); segments.RemoveRange(0, parameterizedLocation.SegmentIndex); rs.Waypoints.AddRange(segments[0].Waypoints.GetRange(0, (int)parameterizedLocation.Value)); cutRoute.Segments.Add(rs); segments[0].Waypoints.RemoveRange(0, (int)parameterizedLocation.Value); } // handle map readings nicely if (waypointAttributeExists[WaypointAttribute.MapReadingDuration] && segments[0].FirstWaypoint.MapReadingState == MapReadingState.Reading) { segments[0].FirstWaypoint.MapReadingState = MapReadingState.StartReading; } break; case CutType.After: if (parameterizedLocation.SegmentIndex < segments.Count - 1) { cutRoute.Segments.AddRange(segments.GetRange(parameterizedLocation.SegmentIndex + 1, segments.Count - 1 - parameterizedLocation.SegmentIndex)); segments.RemoveRange(parameterizedLocation.SegmentIndex + 1, segments.Count - 1 - parameterizedLocation.SegmentIndex); } var i = (int)parameterizedLocation.Ceiling().Value; int count = segments[parameterizedLocation.SegmentIndex].Waypoints.Count; if (!parameterizedLocation.IsNode) { // cut between two waypoints: create cut waypoint Waypoint cutWaypoint = CreateWaypointFromParameterizedLocation(parameterizedLocation); var rs = new RouteSegment(); rs.Waypoints.AddRange(segments[parameterizedLocation.SegmentIndex].Waypoints.GetRange(i, count - i)); cutRoute.Segments.Insert(0, rs); segments[parameterizedLocation.SegmentIndex].Waypoints.RemoveRange(i, count - i); segments[parameterizedLocation.SegmentIndex].Waypoints.Insert(i, cutWaypoint); cutRoute.WaypointInsertedAtCut = cutWaypoint; } else { // cut exactly at a waypoint var rs = new RouteSegment(); rs.Waypoints.AddRange(segments[parameterizedLocation.SegmentIndex].Waypoints.GetRange(i + 1, count - 1 - i)); cutRoute.Segments.Insert(0, rs); segments[parameterizedLocation.SegmentIndex].Waypoints.RemoveRange(i + 1, count - 1 - i); } // handle map readings nicely var lastWaypoint = segments[segments.Count - 1].LastWaypoint; if (waypointAttributeExists[WaypointAttribute.MapReadingDuration] && lastWaypoint.MapReadingState == MapReadingState.Reading) { lastWaypoint.MapReadingState = MapReadingState.EndReading; } break; } return cutRoute; }
public static List<RouteSegment> AddMapReadingWaypoints(List<RouteSegment> routeSegments, List<DateTime> mapReadings) { if (mapReadings.Count == 0) return routeSegments; var newRouteSegments = new List<RouteSegment>(); foreach (var routeSegment in routeSegments) { var newRouteSegment = new RouteSegment(); var waypointCount = 0; var mapReadingIndex = -1; // just to be sure, could probably be removed foreach (var waypoint in routeSegment.Waypoints) { while (mapReadingIndex < mapReadings.Count - 1 && mapReadings[mapReadingIndex+1] <= waypoint.Time) { mapReadingIndex++; } var newWaypoint = waypoint.Clone(); if (waypoint == routeSegment.FirstWaypoint) { newWaypoint.MapReadingState = mapReadingIndex % 2 == 0 ? MapReadingState.StartReading : MapReadingState.NotReading; newRouteSegment.Waypoints.Add(newWaypoint); } else if (waypoint == routeSegment.LastWaypoint) { newWaypoint.MapReadingState = newRouteSegment.LastWaypoint.MapReadingState == MapReadingState.StartReading || newRouteSegment.LastWaypoint.MapReadingState == MapReadingState.Reading ? MapReadingState.EndReading : MapReadingState.NotReading; newRouteSegment.Waypoints.Add(newWaypoint); break; } else { if (mapReadingIndex != -1 && mapReadings[mapReadingIndex] == newWaypoint.Time) { newWaypoint.MapReadingState = mapReadingIndex % 2 == 0 ? MapReadingState.StartReading : MapReadingState.EndReading; } else { newWaypoint.MapReadingState = mapReadingIndex % 2 == 0 ? MapReadingState.Reading : MapReadingState.NotReading; } newRouteSegment.Waypoints.Add(newWaypoint); } var nextWaypoint = routeSegment.Waypoints[waypointCount + 1]; while (mapReadingIndex < mapReadings.Count - 1 && mapReadings[mapReadingIndex + 1] < nextWaypoint.Time) { var time = mapReadings[mapReadingIndex + 1]; var t = (double)(time - waypoint.Time).Ticks / (nextWaypoint.Time - waypoint.Time).Ticks; var longLat = (1 - t) * waypoint.LongLat + t * nextWaypoint.LongLat; var altitude = waypoint.Altitude.HasValue && nextWaypoint.Altitude.HasValue ? (double?)((1 - t) * waypoint.Altitude.Value + t * nextWaypoint.Altitude.Value) : null; var heartRate = waypoint.HeartRate.HasValue && nextWaypoint.HeartRate.HasValue ? (double?)((1 - t) * waypoint.HeartRate.Value + t * nextWaypoint.HeartRate.Value) : null; var mapReadingState = (mapReadingIndex + 1) % 2 == 0 ? MapReadingState.StartReading : MapReadingState.EndReading; newRouteSegment.Waypoints.Add(new Waypoint(time, longLat, altitude, heartRate, mapReadingState, null, null)); mapReadingIndex++; } waypointCount++; } newRouteSegments.Add(newRouteSegment); } return newRouteSegments; }