When displaying directions on the built-in Maps.app on the iPhone you can \"select\" one of the usually 3 route alternatives that are displayed by tapping on it. I wan\'t to
The solution proposed below by Jensemann is working great. See below code adapted for Swift 2, tested successfully on IOS 8 and 9 (XCode 7.1).
func didTapMap(gestureRecognizer: UIGestureRecognizer) {
tapPoint = gestureRecognizer.locationInView(mapView)
NSLog("tapPoint = %f,%f",tapPoint.x, tapPoint.y)
//convert screen CGPoint tapPoint to CLLocationCoordinate2D...
let tapCoordinate = mapView.convertPoint(tapPoint, toCoordinateFromView: mapView)
let tapMapPoint = MKMapPointForCoordinate(tapCoordinate)
print("tap coordinates = \(tapCoordinate)")
print("tap map point = \(tapMapPoint)")
// Now we test to see if one of the overlay MKPolyline paths were tapped
var nearestDistance = Double(MAXFLOAT)
let minDistance = 2000 // in meters, adjust as needed
var nearestPoly = MKPolyline()
// arrayPolyline below is an array of MKPolyline overlaid on the mapView
for poly in arrayPolyline {
// ... get the distance ...
let distance = distanceOfPoint(tapMapPoint, poly: poly)
print("distance = \(distance)")
// ... and find the nearest one
if (distance < nearestDistance) {
nearestDistance = distance
nearestPoly = poly
}
}
if (nearestDistance <= minDistance) {
NSLog("Touched poly: %@\n distance: %f", nearestPoly, nearestDistance);
}
}
func distanceOfPoint(pt: MKMapPoint, poly: MKPolyline) -> Double {
var distance: Double = Double(MAXFLOAT)
var linePoints: [MKMapPoint] = []
var polyPoints = UnsafeMutablePointer.alloc(poly.pointCount)
for point in UnsafeBufferPointer(start: poly.points(), count: poly.pointCount) {
linePoints.append(point)
print("point: \(point.x),\(point.y)")
}
for n in 0...linePoints.count - 2 {
let ptA = linePoints[n]
let ptB = linePoints[n+1]
let xDelta = ptB.x - ptA.x
let yDelta = ptB.y - ptA.y
if (xDelta == 0.0 && yDelta == 0.0) {
// Points must not be equal
continue
}
let u: Double = ((pt.x - ptA.x) * xDelta + (pt.y - ptA.y) * yDelta) / (xDelta * xDelta + yDelta * yDelta)
var ptClosest = MKMapPoint()
if (u < 0.0) {
ptClosest = ptA
} else if (u > 1.0) {
ptClosest = ptB
} else {
ptClosest = MKMapPointMake(ptA.x + u * xDelta, ptA.y + u * yDelta);
}
distance = min(distance, MKMetersBetweenMapPoints(ptClosest, pt))
}
return distance
}