/// <summary> /// Creating a new document using the specified map, route, laps, initial transformation matrix, projection origin and document settings, and adding one new session with the specified route and laps. /// </summary> /// <param name="map"></param> /// <param name="route"></param> /// <param name="laps"></param> /// <param name="initialTransformationMatrix"></param> /// <param name="projectionOrigin"></param> /// <param name="settings"></param> public Document(Map map, Route route, LapCollection laps, GeneralMatrix initialTransformationMatrix, LongLat projectionOrigin, DocumentSettings settings) { Map = map; sessions.Add(new Session(route, laps, map.Image.Size, initialTransformationMatrix, projectionOrigin, settings.DefaultSessionSettings)); this.settings = settings; UpdateDocumentToCurrentVersion(this); }
public static GeneralMatrix CreateInitialTransformationMatrix(Route route, Size mapSize, LongLat projectionOrigin) { // create initial adjustment: route should fit in the 75% inner rectangle of the map RectangleD routeRectangle = route.BoundingProjectedRectangle(projectionOrigin); RectangleD mapRectangle = new RectangleD(1.0 / 8.0 * mapSize.Width, 1.0 / 8.0 * mapSize.Height, 3.0 / 4.0 * mapSize.Width, 3.0 / 4.0 * mapSize.Height); // check width/height ratio for each of the rectangles, and adjust the map rectangle to have the same ratio as the route rectangle double routeRatio = routeRectangle.Width / routeRectangle.Height; double mapRatio = mapRectangle.Width / mapRectangle.Height; if (mapRatio < routeRatio) { // too narrow mapRectangle = new RectangleD(mapRectangle.Left, mapRectangle.Center.Y - mapRectangle.Width / routeRatio / 2.0, mapRectangle.Width, mapRectangle.Width / routeRatio); } else { // too wide mapRectangle = new RectangleD(mapRectangle.Center.X - mapRectangle.Height * routeRatio / 2.0, mapRectangle.Top, mapRectangle.Height * routeRatio, mapRectangle.Height); } GeneralMatrix t = LinearAlgebraUtil.CalculateTransformationMatrix(routeRectangle.LowerLeft, mapRectangle.UpperLeft, routeRectangle.UpperRight, mapRectangle.LowerRight, null, false); return t; }
/// <summary> /// Creating a new document using the specified map, route, laps, initial transformation matrix and document settings, and adding one new session with the specified route and laps. /// </summary> /// <param name="map"></param> /// <param name="route"></param> /// <param name="laps"></param> /// <param name="initialTransformationMatrix"></param> /// <param name="settings"></param> public Document(Map map, Route route, LapCollection laps, GeneralMatrix initialTransformationMatrix, DocumentSettings settings) : this(map, route, laps, initialTransformationMatrix, null, settings) { }
/// <summary> /// Creating a new document using the specified map, route, laps, and document settings, and adding one new session with the specified route and laps. /// </summary> /// <param name="map"></param> /// <param name="route"></param> /// <param name="laps"></param> /// <param name="settings"></param> public Document(Map map, Route route, LapCollection laps, DocumentSettings settings) : this(map, route, laps, null, settings) { }
private static Bitmap CreateRouteThumbnail(Route route, Size thumbnailSize, Color routeLineColor, double routeLineWidth) { var bitmap = new Bitmap(thumbnailSize.Width, thumbnailSize.Width); var projectionOrigin = route.CenterLongLat(); // get coordinates of lines double minX = 0, maxX = 0, minY = 0, maxY = 0; var lines = new List<List<PointD>>(); foreach (var segment in route.Segments) { var vertices = new List<PointD>(); foreach (var waypoint in segment.Waypoints) { var vertex = waypoint.LongLat.Project(projectionOrigin); vertices.Add(vertex); // calculate bounds if (lines.Count == 0 && vertices.Count == 0) { minX = vertex.X; minY = vertex.Y; maxX = vertex.X; maxY = vertex.Y; } else { minX = Math.Min(minX, vertex.X); minY = Math.Min(minY, vertex.Y); maxX = Math.Max(maxX, vertex.X); maxY = Math.Max(maxY, vertex.Y); } } lines.Add(vertices); } var scale = Math.Min((thumbnailSize.Width - 1) / (maxX == minX ? 0 : maxX - minX), (thumbnailSize.Height - 1) / (maxY == minY ? 0 : maxY - minY)); var offsetX = (thumbnailSize.Width - (maxX - minX) * scale) / 2; var offsetY = (thumbnailSize.Height - (maxY - minY) * scale) / 2; // map coordinates onto thumbnail var mappedLines = new List<List<PointF>>(); foreach (var line in lines) { var mappedVertices = new List<PointF>(); foreach (var vertex in line) { mappedVertices.Add((PointF)new PointD( offsetX + scale * (vertex.X - minX), (thumbnailSize.Height - 1) - (offsetY + scale * (vertex.Y - minY)))); } mappedLines.Add(mappedVertices); } using (var g = Graphics.FromImage(bitmap)) { g.SmoothingMode = SmoothingMode.AntiAlias; foreach (var mappedLine in mappedLines) { if(mappedLine.Count > 1) g.DrawLines(new Pen(routeLineColor, (float)routeLineWidth), mappedLine.ToArray()); } } return bitmap; }
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; }