출처: https://stackoverflow.com/a/28028023/1025379
두 좌표를 잇는 직선에서 나와 가장 가까운 좌표를 찾아야 한다. CoreLocation이나 MapKit에서는 따로 지원하지는 않는 것 같다.
출처의 코드를 플레이 그라운드에서 테스트 해봤다.
import MapKit import PlaygroundSupport func makeLocation(lat: Double, lon: Double) -> CLLocationCoordinate2D { return CLLocationCoordinate2DMake(lat, lon) } func nearestPointToPoint(_ origin: CGPoint, _ pointA: CGPoint, _ pointB: CGPoint) -> (CGPoint, Double) { let dAP = CGPoint(x: origin.x - pointA.x, y: origin.y - pointA.y) let dAB = CGPoint(x: pointB.x - pointA.x, y: pointB.y - pointA.y) let dot = dAP.x * dAB.x + dAP.y * dAB.y let squareLength = dAB.x * dAB.x + dAB.y * dAB.y let param = dot / squareLength // 경도 180도 근처에서 오류 발생 // var nearestPoint = CGPoint() // if param < 0 || (pointA.x == pointB.x && pointA.y == pointB.y) { // nearestPoint.x = pointA.x // nearestPoint.y = pointA.y // } else if param > 1 { // nearestPoint.x = pointB.x // nearestPoint.y = pointB.y // } else { // nearestPoint.x = pointA.x + param * dAB.x // nearestPoint.y = pointA.y + param * dAB.y // } let nearestPoint = CGPoint(x: pointA.x + param * dAB.x, y: pointA.y + param * dAB.y) let dx = origin.x - nearestPoint.x let dy = origin.y - nearestPoint.y let distance = sqrtf(Float(dx * dx + dy * dy)) return (nearestPoint, Double(distance)) } extension CLLocationCoordinate2D { func toCGPoint() -> CGPoint { return CGPoint(x: longitude, y: latitude) } } // Now let's create a MKMapView let mapView = MKMapView(frame: CGRect(x: 0, y: 0, width: 800, height: 800)) let location1 = makeLocation(lat: 52, lon: -2) let myLocation = makeLocation(lat: 53, lon: -1) let location2 = makeLocation(lat: 52, lon: 0) let locations = [location1, location2] // Define a region for our map view var mapRegion = MKCoordinateRegion() let mapRegionSpan = 5.0 mapRegion.center = myLocation mapRegion.span.latitudeDelta = mapRegionSpan mapRegion.span.longitudeDelta = mapRegionSpan mapView.setRegion(mapRegion, animated: true) locations.map { let pin = MKPointAnnotation() pin.title = "(\($0.latitude), \($0.longitude))" pin.coordinate = $0 return pin } .map { mapView.addAnnotation($0) } let me = MKPointAnnotation() me.coordinate = myLocation me.title = "me(\(myLocation.latitude), \(myLocation.longitude))" mapView.addAnnotation(me) let (near, distance) = nearestPointToPoint(me.coordinate.toCGPoint(), location1.toCGPoint(), location2.toCGPoint()) let nearLocation = makeLocation(lat: Double(near.y), lon: Double(near.x)) print("near: \(nearLocation), distance: \(distance)") let nearPoint = MKPointAnnotation() nearPoint.title = "near (\(nearLocation.latitude),\(nearLocation.longitude))" nearPoint.coordinate = nearLocation mapView.addAnnotation(nearPoint) // Add the created mapView to our Playground Live View PlaygroundPage.current.liveView = mapView












여기까지는 정상적으로 동작하는데, 문제는 경도 180도 근처에서 발생한다. 이건 모르겠다. 보니까 경도 180 근처에서는 나라도 없어서 그냥 써도 괜찮을 것 같다.
