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); }
public PointD GetDirectionVectorFromParameterizedLocation(ParameterizedLocation pl) { if (pl == null) { return(null); } double wi = GetWaypointIndexFromParameterizedLocation(pl); if (wi == Math.Floor(wi)) { // exactly at a waypoint if (wi == 0) { // first waypoint AdjustedWaypoint wp0 = segments[pl.SegmentIndex].Waypoints[0]; AdjustedWaypoint wp1 = segments[pl.SegmentIndex].Waypoints[1]; return(LinearAlgebraUtil.Normalize(wp1.Location - wp0.Location)); } else if ((int)wi == segments[pl.SegmentIndex].Waypoints.Count - 1) { // last waypoint int lastWaypointIndex = segments[pl.SegmentIndex].Waypoints.Count - 1; AdjustedWaypoint wp0 = segments[pl.SegmentIndex].Waypoints[lastWaypointIndex - 1]; AdjustedWaypoint wp1 = segments[pl.SegmentIndex].Waypoints[lastWaypointIndex]; return(LinearAlgebraUtil.Normalize(wp1.Location - wp0.Location)); } else { AdjustedWaypoint wp0 = segments[pl.SegmentIndex].Waypoints[(int)wi - 1]; AdjustedWaypoint wp1 = segments[pl.SegmentIndex].Waypoints[(int)wi]; AdjustedWaypoint wp2 = segments[pl.SegmentIndex].Waypoints[(int)wi + 1]; return(LinearAlgebraUtil.Normalize( LinearAlgebraUtil.Normalize(wp2.Location - wp1.Location) + LinearAlgebraUtil.Normalize(wp1.Location - wp0.Location) )); } } else { AdjustedWaypoint wp0 = segments[pl.SegmentIndex].Waypoints[(int)Math.Floor(wi)]; AdjustedWaypoint wp1 = segments[pl.SegmentIndex].Waypoints[(int)Math.Ceiling(wi)]; return(LinearAlgebraUtil.Normalize(wp1.Location - wp0.Location)); } }
public ParameterizedLocation GetClosestParameterizedLocation(PointD location, out double distance) { if (location == null) { distance = 0; return(null); } double closestDistance = 0.0; ParameterizedLocation closestDistanceParameterizedLocation = new ParameterizedLocation(0, 0); bool closestDistanceSet = false; double limit = 2 * 32; for (int i = 0; i < segments.Count; i++) { List <AdjustedWaypoint> waypoints = segments[i].Waypoints; PointD p0 = waypoints[0].Location; for (int j = 1; j < waypoints.Count; j++) { PointD p1 = waypoints[j].Location; // long distance between p0 and p1? then we need to check more time-consuming ClosestDistancePointToLine even if p0 is far from location bool isLongLineSegment = (LinearAlgebraUtil.DistancePointToPoint(p0, p1) > limit); if (LinearAlgebraUtil.DistancePointToPoint(location, p1) < limit || isLongLineSegment) { double t; double tmpDistance = LinearAlgebraUtil.ClosestDistancePointToLine(location, p0, p1, out t); if (tmpDistance < closestDistance || !closestDistanceSet) { closestDistance = tmpDistance; closestDistanceParameterizedLocation = new ParameterizedLocation(i, waypoints[j - 1].ParameterizedLocation.Value + t * (waypoints[j].ParameterizedLocation.Value - waypoints[j - 1].ParameterizedLocation.Value)); closestDistanceSet = true; } } p0 = p1; } } distance = closestDistance; return(closestDistanceSet ? closestDistanceParameterizedLocation : null); }
public Transformation(LongLatBox longLatBox, Size imageSize) { // calculate projection origin ProjectionOrigin = new LongLat((longLatBox.East + longLatBox.West) / 2, (longLatBox.North + longLatBox.South) / 2); // get image corners from kml file var imageCornerLongLats = longLatBox.GetRotatedBoxCornerLongLats(); // project them on flat surface var projectedImageCorners = new Dictionary <Corner, PointD>(); projectedImageCorners[Corner.NorthWest] = imageCornerLongLats[Corner.NorthWest].Project(ProjectionOrigin); projectedImageCorners[Corner.SouthEast] = imageCornerLongLats[Corner.SouthEast].Project(ProjectionOrigin); // calculate transformation matrix TransformationMatrix = LinearAlgebraUtil.CalculateTransformationMatrix( projectedImageCorners[Corner.NorthWest], new PointD(0, 0), projectedImageCorners[Corner.SouthEast], new PointD(imageSize.Width - 1, imageSize.Height - 1), null, true); }
public static LongLat Deproject(PointD coordinate, LongLat projectionOrigin) { if (LinearAlgebraUtil.DistancePointToPoint(coordinate, new PointD(0, 0)) < 0.0000001) { return(new LongLat(projectionOrigin.Longitude, projectionOrigin.Latitude)); } const double r = 6378200; // earth radius in metres var longLat = new LongLat(); var rho = Math.Sqrt(coordinate.X * coordinate.X + coordinate.Y * coordinate.Y); var c = Math.Asin(rho / r); var lambda0 = projectionOrigin.Longitude * Math.PI / 180.0; var phi1 = projectionOrigin.Latitude * Math.PI / 180.0; longLat.Latitude = Math.Asin(Math.Cos(c) * Math.Sin(phi1) + (coordinate.Y * Math.Sin(c) * Math.Cos(phi1) / rho)) / Math.PI * 180.0; longLat.Longitude = (lambda0 + Math.Atan(coordinate.X * Math.Sin(c) / (rho * Math.Cos(phi1) * Math.Cos(c) - coordinate.Y * Math.Sin(phi1) * Math.Sin(c)))) / Math.PI * 180.0; return(longLat); }
public Dictionary <Corner, LongLat> GetRotatedBoxCornerLongLats() { var rotation = -Rotation; var corners = new Dictionary <Corner, LongLat>(); corners[Corner.NorthEast] = new LongLat(East, North); corners[Corner.NorthWest] = new LongLat(West, North); corners[Corner.SouthWest] = new LongLat(West, South); corners[Corner.SouthEast] = new LongLat(East, South); var projectionOrigin = new LongLat((East + West) / 2, (North + South) / 2); var projectedMapCenter = projectionOrigin.Project(projectionOrigin); var projectedCorners = new Dictionary <Corner, PointD>(); projectedCorners[Corner.NorthEast] = corners[Corner.NorthEast].Project(projectionOrigin); projectedCorners[Corner.NorthWest] = corners[Corner.NorthWest].Project(projectionOrigin); projectedCorners[Corner.SouthWest] = corners[Corner.SouthWest].Project(projectionOrigin); projectedCorners[Corner.SouthEast] = corners[Corner.SouthEast].Project(projectionOrigin); var projectedRotatedCorners = new Dictionary <Corner, PointD>(); projectedRotatedCorners[Corner.NorthEast] = LinearAlgebraUtil.Rotate(projectedCorners[Corner.NorthEast], projectedMapCenter, rotation); projectedRotatedCorners[Corner.NorthWest] = LinearAlgebraUtil.Rotate(projectedCorners[Corner.NorthWest], projectedMapCenter, rotation); projectedRotatedCorners[Corner.SouthWest] = LinearAlgebraUtil.Rotate(projectedCorners[Corner.SouthWest], projectedMapCenter, rotation); projectedRotatedCorners[Corner.SouthEast] = LinearAlgebraUtil.Rotate(projectedCorners[Corner.SouthEast], projectedMapCenter, rotation); var rotatedCorners = new Dictionary <Corner, LongLat>(); rotatedCorners[Corner.NorthWest] = LongLat.Deproject(projectedRotatedCorners[Corner.NorthWest], projectionOrigin); rotatedCorners[Corner.NorthEast] = LongLat.Deproject(projectedRotatedCorners[Corner.NorthEast], projectionOrigin); rotatedCorners[Corner.SouthWest] = LongLat.Deproject(projectedRotatedCorners[Corner.SouthWest], projectionOrigin); rotatedCorners[Corner.SouthEast] = LongLat.Deproject(projectedRotatedCorners[Corner.SouthEast], projectionOrigin); return(rotatedCorners); }
/// <summary> /// Converts a map image pixel coordinate to a longitude and latitude coordinate /// </summary> /// <param name="mapImagePosition">Map pixel coordinate, referring to unzoomed map without any borders and image header</param> /// <returns></returns> public LongLat GetLongLatForMapImagePosition(PointD mapImagePosition, GeneralMatrix averageTransformationMatrixInverse) { var projectedPosition = LinearAlgebraUtil.Transform(mapImagePosition, averageTransformationMatrixInverse); return(LongLat.Deproject(projectedPosition, ProjectionOrigin)); }