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; }
private double GetYValue(Waypoint w) { switch (yAxisAttribute) { case WaypointAttribute.Speed: return w.Attributes[WaypointAttribute.Speed].Value; case WaypointAttribute.HeartRate: return w.Attributes[WaypointAttribute.HeartRate].GetValueOrDefault(0); case WaypointAttribute.Altitude: return w.Attributes[WaypointAttribute.Altitude].GetValueOrDefault(0); case WaypointAttribute.DirectionDeviationToNextLap: return w.Attributes[WaypointAttribute.DirectionDeviationToNextLap].Value; case WaypointAttribute.MapReadingDuration: return w.Attributes[WaypointAttribute.MapReadingDuration].GetValueOrDefault(0); case WaypointAttribute.Cadence: return w.Attributes[WaypointAttribute.Cadence].GetValueOrDefault(0); case WaypointAttribute.Power: return w.Attributes[WaypointAttribute.Power].GetValueOrDefault(0); case WaypointAttribute.Pace: default: return ConvertUtil.ToPace(w.Attributes[WaypointAttribute.Speed].Value).TotalSeconds; } }
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()); }
private KmlMarkerStyle GetMarkerStyleFromWaypoint(Waypoint waypoint, ImageExporter imageExporter, SessionSettings sessionSettings) { var attribute = imageExporter.Properties.ColorCodingAttribute; var rls = sessionSettings.RouteLineSettingsCollection[attribute]; return new KmlMarkerStyle() { Color = rls.ColorRange.GetColor(waypoint.Attributes[attribute].GetValueOrDefault(0), NoOfColorCodedSteps), Size = replayMarkerSizeFactor * ((rls.MaskVisible ? 2 * rls.MaskWidth : 0) + rls.Width) }; }
private double GetXValue(Waypoint w) { switch (xAxisAttribute) { case DomainAttribute.ElapsedTime: return w.Attributes[WaypointAttribute.ElapsedTime].Value; case DomainAttribute.Distance: return w.Attributes[WaypointAttribute.Distance].Value; case DomainAttribute.TimeOfDay: default: return (double)w.Time.ToLocalTime().Ticks / TimeSpan.TicksPerSecond; } }
private void CreateReplayPlacemark(Waypoint waypoint, KmlMarkerStyle style, XmlWriter writer, IFormatProvider formatProvider) { CreateReplayPlacemark(waypoint, style, null, null, writer, formatProvider); }
private void CreateReplayPlacemark(Waypoint waypoint, KmlMarkerStyle style, DateTime? appearTime, DateTime? disappearTime, XmlWriter writer, IFormatProvider formatProvider) { writer.WriteStartElement("Placemark"); writer.WriteElementString("styleUrl", "#" + GetMarkerStyleId(style)); if (appearTime.HasValue || disappearTime.HasValue) { writer.WriteStartElement("TimeSpan"); if (appearTime.HasValue) writer.WriteElementString("begin", FormatTime(appearTime.Value.ToUniversalTime())); if (disappearTime.HasValue) writer.WriteElementString("end", FormatTime(disappearTime.Value.ToUniversalTime())); writer.WriteEndElement(); // TimeSpan } else { writer.WriteStartElement("TimeStamp"); writer.WriteElementString("when", FormatTime(waypoint.Time.ToUniversalTime())); writer.WriteEndElement(); // TimeStamp } writer.WriteStartElement("Point"); writer.WriteElementString("coordinates", waypoint.LongLat.Longitude.ToString(formatProvider) + "," + waypoint.LongLat.Latitude.ToString(formatProvider)); writer.WriteEndElement(); // Point writer.WriteEndElement(); // Placemark }
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; }
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 Waypoint CreateWaypointFromParameterizedLocation(ParameterizedLocation parameterizedLocation) { var w = new Waypoint(); List<Waypoint> waypoints = segments[parameterizedLocation.SegmentIndex].Waypoints; var i = (int)parameterizedLocation.Floor().Value; if (i >= waypoints.Count - 1) i = waypoints.Count - 2; if (waypoints.Count < 2) return waypoints[0]; double d = parameterizedLocation.Value - i; // time DateTime dt0 = waypoints[i].Time; DateTime dt1 = waypoints[i + 1].Time; w.Time = new DateTime(dt0.Ticks + (long)(d * (dt1.Ticks - dt0.Ticks)), dt0.Kind); // location LongLat p0 = waypoints[i].LongLat; LongLat p1 = waypoints[i + 1].LongLat; w.LongLat = new LongLat(p0.Longitude + d * (p1.Longitude - p0.Longitude), p0.Latitude + d * (p1.Latitude - p0.Latitude)); // altitude if (waypoints[i].Altitude.HasValue && waypoints[i + 1].Altitude.HasValue) { w.Altitude = waypoints[i].Altitude + d * (waypoints[i + 1].Altitude - waypoints[i].Altitude); } // heart rate if (waypoints[i].HeartRate.HasValue && waypoints[i + 1].HeartRate.HasValue) { w.HeartRate = waypoints[i].HeartRate + d * (waypoints[i + 1].HeartRate - waypoints[i].HeartRate); } var attributes = new List<WaypointAttribute> { WaypointAttribute.Pace, WaypointAttribute.HeartRate, WaypointAttribute.Altitude, WaypointAttribute.Speed, WaypointAttribute.DirectionDeviationToNextLap, WaypointAttribute.ElapsedTime, WaypointAttribute.Distance, WaypointAttribute.Inclination, WaypointAttribute.Direction, WaypointAttribute.Longitude, WaypointAttribute.Latitude, WaypointAttribute.Cadence, WaypointAttribute.Power }; // map reading if(waypointAttributeExists[WaypointAttribute.MapReadingDuration]) { if(parameterizedLocation.IsNode) { w.MapReadingState = waypoints[i].MapReadingState; } else { w.MapReadingState = waypoints[i].MapReadingState == MapReadingState.NotReading || waypoints[i + 1].MapReadingState == MapReadingState.NotReading ? MapReadingState.NotReading : MapReadingState.Reading; } attributes.AddRange(new[] { WaypointAttribute.MapReadingDuration, WaypointAttribute.MapReadingState, WaypointAttribute.PreviousMapReadingEnd, WaypointAttribute.NextMapReadingStart, }); } foreach (var attribute in attributes) { w.Attributes[attribute] = GetAttributeValueBetweenWaypoints(waypoints[i], waypoints[i + 1], d, attribute); } return w; }
public Waypoint Clone() { var newWaypoint = new Waypoint(time, longLat, altitude, heartRate, mapReadingState, cadence, power); foreach (var attributeKey in Attributes.Keys) { newWaypoint.Attributes[attributeKey] = Attributes[attributeKey]; } return newWaypoint; }
// w0 and w1 are adjacent, t measured from w0 private static double? GetAttributeValueBetweenWaypoints(Waypoint w0, Waypoint w1, double t, WaypointAttribute attribute) { switch(attribute) { case WaypointAttribute.MapReadingDuration: return w0.MapReadingState == MapReadingState.StartReading || w0.MapReadingState == MapReadingState.Reading ? w0.Attributes[WaypointAttribute.MapReadingDuration] : null; case WaypointAttribute.MapReadingState: return GetAttributeValueBetweenWaypoints(w0, w1, t, WaypointAttribute.MapReadingDuration) != null ? 1 : 0; case WaypointAttribute.PreviousMapReadingEnd: return w1.Attributes[WaypointAttribute.PreviousMapReadingEnd] != null ? (double?)(w1.Attributes[WaypointAttribute.PreviousMapReadingEnd].Value - (1 - t) * (w1.Time - w0.Time).TotalSeconds) : null; case WaypointAttribute.NextMapReadingStart: return w0.Attributes[WaypointAttribute.NextMapReadingStart] != null ? (double?)(w0.Attributes[WaypointAttribute.NextMapReadingStart].Value - t * (w1.Time - w0.Time).TotalSeconds) : null; default: if (w0.Attributes.ContainsKey(attribute) && w1.Attributes.ContainsKey(attribute)) { var d0 = w0.Attributes[attribute]; var d1 = w1.Attributes[attribute]; if (d0.HasValue && d1.HasValue) return d0 + t * (d1 - d0); if (!d0.HasValue && !d1.HasValue) return null; return (t < 0.5 ? d0 : d1); } return null; } }