/// <summary> /// Calculates the closest point on the route relative to the given coordinate. /// </summary> /// <returns></returns> public bool ProjectOn(GeoCoordinate coordinates, out GeoCoordinate projectedCoordinates, out int entryIndex, out Meter distanceFromStart, out Second timeFromStart) { double distance = double.MaxValue; distanceFromStart = 0; timeFromStart = 0; double currentDistanceFromStart = 0; projectedCoordinates = null; entryIndex = -1; // loop over all points and try to project onto the line segments. GeoCoordinate projected; double currentDistance; var points = this.GetPoints(); for (int idx = 0; idx < points.Count - 1; idx++) { var line = new GeoCoordinateLine(points[idx], points[idx + 1], true, true); var projectedPoint = line.ProjectOn(coordinates); if (projectedPoint != null) { // there was a projected point. projected = new GeoCoordinate(projectedPoint[1], projectedPoint[0]); currentDistance = coordinates.Distance(projected); if (currentDistance < distance) { // this point is closer. projectedCoordinates = projected; entryIndex = idx; distance = currentDistance; // calculate distance/time. double localDistance = projected.DistanceReal(points[idx]).Value; distanceFromStart = currentDistanceFromStart + localDistance; if(this.HasTimes && idx > 0) { // there should be proper timing information. double timeToSegment = this.Segments[idx].Time; double timeToNextSegment = this.Segments[idx + 1].Time; timeFromStart = timeToSegment + ((timeToNextSegment - timeToSegment) * (localDistance / line.LengthReal.Value)); } } } // check first point. projected = points[idx]; currentDistance = coordinates.Distance(projected); if (currentDistance < distance) { // this point is closer. projectedCoordinates = projected; entryIndex = idx; distance = currentDistance; distanceFromStart = currentDistanceFromStart; if (this.HasTimes) { // there should be proper timing information. timeFromStart = this.Segments[idx].Time; } } // update distance from start. currentDistanceFromStart = currentDistanceFromStart + points[idx].DistanceReal(points[idx + 1]).Value; } // check last point. projected = points[points.Count - 1]; currentDistance = coordinates.Distance(projected); if (currentDistance < distance) { // this point is closer. projectedCoordinates = projected; entryIndex = points.Count - 1; distance = currentDistance; distanceFromStart = currentDistanceFromStart; if (this.HasTimes) { // there should be proper timing information. timeFromStart = this.Segments[points.Count - 1].Time; } } return true; }
/// <summary> /// Project on route and return the next entry index and coordinate. /// </summary> /// <param name="route"></param> /// <param name="coordinates"></param> /// <returns></returns> private KeyValuePair<int, GeoCoordinate> ProjectOn(Route route, GeoCoordinate coordinates) { double distance = double.MaxValue; GeoCoordinate closest = null; int closestIdx = -1; List<GeoCoordinate> points = route.GetPoints(); for (int idx = 0; idx < points.Count - 1; idx++) { GeoCoordinateLine line = new GeoCoordinateLine(points[idx], points[idx + 1], true, true); PointF2D projectedPoint = line.ProjectOn(coordinates); GeoCoordinate projected; double currentDistance; if (projectedPoint != null) { projected = new GeoCoordinate(projectedPoint[1], projectedPoint[0]); currentDistance = coordinates.Distance(projected); if (currentDistance < distance) { closest = projected; closestIdx = idx + 1; distance = currentDistance; } } projected = points[idx]; currentDistance = coordinates.Distance(projected); if (currentDistance < distance) { closest = projected; closestIdx = idx; distance = currentDistance; } } return new KeyValuePair<int,GeoCoordinate>(closestIdx, closest); }
/// <summary> /// Calculates the closest point on the route. /// </summary> /// <param name="coordinates"></param> /// <returns></returns> public GeoCoordinate ProjectOn(GeoCoordinate coordinates) { double distance = double.MaxValue; GeoCoordinate closests = null; List<GeoCoordinate> points = this.GetPoints(); for (int idx = 0; idx < points.Count - 1; idx++) { GeoCoordinateLine line = new GeoCoordinateLine(points[idx], points[idx + 1]); PointF2D projectedPoint = line.ProjectOn(coordinates); GeoCoordinate projected = new GeoCoordinate(projectedPoint[1], projectedPoint[0]); double currentDistance = coordinates.Distance(projected); if (currentDistance < distance) { closests = projected; distance = currentDistance; } } return closests; }