快速计算两个位置之间的距离
问题描述:
我想获得两个位置之间的距离。 我试过这段代码:快速计算两个位置之间的距离
func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {
CLGeocoder().geocodeAddressString("ADDRESS OF LOC 2") { (placemarks, error) in
guard let placemarks = placemarks, let loc2 = placemarks.first?.location
else {
return
}
let loc1 = CLLocation(latitude: userLocation.coordinate.latitude, longitude: userLocation.coordinate.longitude)
var distance = loc1.distance(from: loc2)
print((distance/1000).rounded(), " km")
}
}
我的问题是,我得到一个错误的距离。 打印结果将是“2公里”
如果我计算出“地图”在同一地点之间的距离,我得到的长度“2,7公里”和“2.9公里”
两个Route选项我错了什么?
答
此方法通过跟踪下面的地球曲率它们之间的线测量的两个位置之间的距离。由此产生的弧线是一条平滑曲线,不考虑两个位置之间的特定高度变化。
因此,您正在计算直线距离,“像乌鸦飞”,而不是跟随道路,这将导致更长的路线,就像您在地图中看到的那样。您需要像MapKit的MKDirectionsRequest
之类的内容来匹配您在地图应用中看到的路线。 Ray Wenderlich has a good tutorial.
下面是一个例子,我只是敲了在MacOS的游乐场工作:
//: Playground - noun: a place where people can play
import Cocoa
import MapKit
import CoreLocation
// As we're waiting for completion handlers, don't want the playground
// to die on us just because we reach the end of the playground.
// See https://stackoverflow.com/questions/40269573/xcode-error-domain-dvtplaygroundcommunicationerrordomain-code-1
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
let geocoder = CLGeocoder()
geocoder.geocodeAddressString("1 Pall Mall East, London SW1Y 5AU") { (placemarks: [CLPlacemark]? , error: Error?) in
if let placemarks = placemarks {
let start_placemark = placemarks[0]
geocoder.geocodeAddressString("Buckingham Palace, London SW1A 1AA", completionHandler: { (placemarks: [CLPlacemark]?, error: Error?) in
if let placemarks = placemarks {
let end_placemark = placemarks[0]
// Okay, we've geocoded two addresses as start_placemark and end_placemark.
let start = MKMapItem(placemark: MKPlacemark(coordinate: start_placemark.location!.coordinate))
let end = MKMapItem(placemark: MKPlacemark(coordinate: end_placemark.location!.coordinate))
// Now we've got start and end MKMapItems for MapKit, based on the placemarks. Build a request for
// a route by car.
let request: MKDirectionsRequest = MKDirectionsRequest()
request.source = start
request.destination = end
request.transportType = MKDirectionsTransportType.automobile
// Execute the request on an MKDirections object
let directions = MKDirections(request: request)
directions.calculate(completionHandler: { (response: MKDirectionsResponse?, error: Error?) in
// Now we should have a route.
if let routes = response?.routes {
let route = routes[0]
print(route.distance) // 2,307 metres.
}
})
}
})
}
}
答
如果你想旅行的距离,而不是“直线距离”,使用MKDirections
,如:
func routes(to item: MKMapItem, completion: @escaping ([MKRoute]?, Error?) -> Void) {
let request = MKDirectionsRequest()
request.source = MKMapItem.forCurrentLocation()
request.destination = item
request.transportType = .automobile
let directions = MKDirections(request: request)
directions.calculate { response, error in
completion(response?.routes, error)
}
}
如果您想格式化为小数点后一位,我建议您使用NumberFormatter
,因此适用于小数点分隔符不是.
的国际用户格式:
self.routes(to: item) { routes, error in
guard let routes = routes, error == nil else {
print(error?.localizedDescription ?? "Unknown error")
return
}
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.minimumFractionDigits = 1
formatter.maximumFractionDigits = 1
for route in routes {
let distance = route.distance/1000
print(formatter.string(from: NSNumber(value: distance))!, "km")
}
}
您没有发现任何问题,您只是通过使用四舍五入()方法丢弃了小数部分,即2.7公里变为2公里,因为您舍去了它! –
如果我这样做:'print(distance/1000)'结果将是:'1.74364568832' - 与2,7或2,9不一样:/ – Ghost108