我需要你的帮助,我正在一个应用程序上工作,我有一些针脚(位置),我想要的是获得每个和我的位置之间的距离。我的代码如下
let annotation = MKPointAnnotation()
let annotationTwo = MKPointAnnotation()
let saintPaulHospitalBC = MKPointAnnotation()
override func viewDidLoad() {
super.viewDidLoad()
mapita.showsUserLocation = true // Mapita is the name of the MapView.
annotation.coordinate = CLLocationCoordinate2D(latitude: 25.647399800, longitude: -100.334304500)
mapita.addAnnotation(annotation)
annotationTwo.coordinate = CLLocationCoordinate2D(latitude: 25.589339000, longitude: -100.257724800)
mapita.addAnnotation(annotationTwo)
saintPaulHospitalBC.coordinate = CLLocationCoordinate2D(latitude: 49.280524700, longitude: -123.128232600)
mapita.addAnnotation(SaintPaulHospitalBC)
}
当我运行代码时,地图会显示引脚,但我还能做些什么才能开始计算距离?谢谢!
答案 0 :(得分:7)
您必须将注释的坐标转换为CLLocation类型,然后获取它们之间的距离。要忽略坐标的高度,因为它们是2D,只需使用2D坐标的纬度和经度属性,如下所示:
let loc1 = CLLocation(latitude: coord1.latitude, longitude: coord1.longitude)
但是,CLLocation还有其他一些属性,例如速度和高度,所以如果你想要考虑那些因素,我必须提供更多信息。要找到两个位置之间的距离,请执行以下操作:
let distance = loc1.distance(from: loc2)
这将以米为单位给出你的答案。
答案 1 :(得分:3)
创建辅助函数来计算用户位置与给定MKPointAnnotation
引脚之间的距离:
/// Returns the distance (in meters) from the
/// user's location to the specified point.
private func userDistance(from point: MKPointAnnotation) -> Double? {
guard let userLocation = mapita.userLocation.location else {
return nil // User location unknown!
}
let pointLocation = CLLocation(
latitude: point.coordinate.latitude,
longitude: point.coordinate.longitude
)
return userLocation.distance(from: pointLocation)
}
最后,为了让用户与圣保罗医院保持距离:
if let distance = userDistance(from: saintPaulHospitalBC) {
// Use distance here...
}
地理定位跟踪延迟。但是有一个问题:由于MapKit / CoreLocation地理位置跟踪可能仍在后台运行,因此用户距离可能不会始终始终。
解决这个问题的一种方法是在最终计算距离之前符合MKMapViewDelegate
protocol并等待mapView(_:didUpdate:)
callback。
答案 2 :(得分:1)
很容易在下面尝试我的代码。
别忘了导入CoreLocation或MapKit,希望它对您有帮助
func calculateDistancefrom(sourceLocation: MKMapItem, destinationLocation: MKMapItem, doneSearching: @escaping (_ expectedTravelTim: TimeInterval) -> Void) {
let request: MKDirectionsRequest = MKDirectionsRequest()
request.source = sourceLocation
request.destination = destinationLocation
request.requestsAlternateRoutes = true
request.transportType = .automobile
let directions = MKDirections(request: request)
directions.calculate { (directions, error) in
if var routeResponse = directions?.routes {
routeResponse.sort(by: {$0.expectedTravelTime <
$1.expectedTravelTime})
let quickestRouteForSegment: MKRoute = routeResponse[0]
doneSearching(quickestRouteForSegment.distance)
}
}
}
func getDistance(lat: Double, lon: Double, completionHandler: @escaping (_ distance: Int) -> Void) {
let destinationItem = MKMapItem(placemark: MKPlacemark(coordinate: CLLocationCoordinate2DMake(lat, lon)))
guard let currentLocation = self.locationManager?.location else { return }
let sourceItem = MKMapItem(placemark: MKPlacemark(coordinate: currentLocation.coordinate))
self.calculateDistancefrom(sourceLocation: sourceItem, destinationLocation: destinationItem, doneSearching: { distance in
completionHandler(distance)
})
}
//Thereafter get the distance in meters by calling
self.getDistance(lat: yourLat, lon: YourLon) { distance in
}
//you can divide by 1000 to convert to KM... .etc
答案 3 :(得分:0)
回想一下,你需要先指定你想要的“距离”。如果您正在寻找简单的Euclidean Distance,那么任何其他答案或使用distanceFromLocation
都可以。根据Apple关于distanceFromLocation
此方法通过跟踪测量两个位置之间的距离 它们之间的一条线跟随地球的曲率。该 产生的弧线是一条平滑的曲线并没有考虑在内 两个地点之间的特定高度变化。
这意味着,使用此方法得出的距离不是两点之间的实际路线/运输距离。 如果这是你正在寻找的,那么请转到我上面链接的答案,如果没有,那么继续阅读(但不管怎样,我鼓励你阅读整个帖子:)。
如果您正在寻找位置与地图中其他注释之间的“路线”距离(可驾驶,可步行等),那么使用MKRoute
对象将需要更多工作。更具体地说,您需要先访问每个注释的MKMapItem
个对象,然后像下面的自定义方法才能获得两个{{1}之间的路由信息对象。
注意 - 如果您没有MapItem
,那么您可以使用每个注释的坐标创建它们,如此
MapItems
在您的类(或ViewController类)中全局定义MKRoute变量。此ley myCoordinates CLLocationCoordinate2D(latitude: 25.647399800, longitude: -100.334304500)
let myPlacemark = MKPlacemark(coordinate: myCoordinates)
let myMapItem = MKMapItem(placemark: myPlacemark)
将在两点之间保存计算出的路线信息。
var
然后
var route: MKRoute!
用法是
func getDistanceToDestination(srcMapItem srcmapItem: MKMapItem, destMapItem destmapItem: MKMapItem){
let request = MKDirectionsRequest() //create a direction request object
request.source = srcmapItem //this is the source location mapItem object
request.destination = destmapItem //this is the destination location mapItem object
request.transportType = MKDirectionsTransportType.automobile //define the transportation method
let directions = MKDirections(request: request) //request directions
directions.calculate { (response, error) in
guard let response = response else {
print(error.debugDescription)
return
}
self.route = response.routes[0] //get the routes, could be multiple routes in the routes[] array but usually [0] is the best route
}
}
其中self.getDistanceToDestination(srcMapItem: yourSourceMapItemObj, destMapItem: yourDestinationMapitemObj)
和yourSourceMapItemObj
是两个yourDestinationMapitemObj
个对象,即源点和目标点。
然后您可以使用MapItem
访问距离,以获得self.route.distance
返回的第一条最佳路线的距离。 MKRoute
对象MKRoute
还有很多其他属性,您可以使用这些属性来显示/计算其他内容,我建议您使用look at those too。您可以使用上面的函数绘制route
,即显示ployLine
中两个位置之间的路线,只需在上面的自定义方法的末尾添加MapView
然后使用下面的self.mapView.add(self.route.polyline)
函数渲染折线。
MKMapViewDelegate
最后,请确保您的课程(或您的课程扩展程序)符合func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let linerenderer = MKPolylineRenderer(overlay: self.route.polyline)
linerenderer.strokeColor = .blue
linerenderer.lineWidth = 3.5
return linerenderer
}
和CLLocationManagerDelegate
协议,并且mapview委托指向MKMapViewDelegate
(我假设您已经这样做)按顺序为了上述一切工作。
答案 4 :(得分:0)
使用MapKit和Swift 5
计算两个位置之间的距离
示例功能:我已经在Google Map和Apple Map中进行了测试
let startLocation : CLLocation = CLLocation.init(latitude: 23.0952779, longitude: 72.5274129)
let endLocation : CLLocation = CLLocation.init(latitude: 23.0981711, longitude: 72.5294229)
let distance = startLocation.distance(from: endLocation)
self.getDistance(departureDate: Date().adjust(hour: 8, minute: 0, second: 0, day: 0, month: 0), arrivalDate: Date().adjust(hour: 8, minute: 10, second: 0, day: 0, month: 0), startLocation: startLocation, endLocation: endLocation) { (distanceInMeters) in
print("fake distance: \(distance)")
let fakedistanceInMeter = Measurement(value: distance, unit: UnitLength.meters)
let fakedistanceInKM = fakedistanceInMeter.converted(to: UnitLength.kilometers).value
let fakedistanceInMiles = fakedistanceInMeter.converted(to: UnitLength.miles).value
print("fakedistanceInKM :\(fakedistanceInKM)")
print("fakedistanceInMiles :\(fakedistanceInMiles)")
print("actualDistance : \(distanceInMeters)")
let distanceInMeter = Measurement(value: distanceInMeters, unit: UnitLength.meters)
let distanceInKM = distanceInMeter.converted(to: UnitLength.kilometers).value
let distanceInMiles = distanceInMeter.converted(to: UnitLength.miles).value
print("distanceInKM :\(distanceInKM)")
print("distanceInMiles :\(distanceInMiles)")
}
功能使用
self.getDistance(departureDate: trip.departure.dateTime, arrivalDate: trip.arrival.dateTime, startLocation: startLocation, endLocation: endLocation) { (actualDistance) in
print("actualDistance : \(actualDistance)")
}
我对上述功能进行了改进,并在此处添加了代码,希望对您有所帮助。
func calculateDistancefrom(departureDate: Date, arrivalDate: Date, sourceLocation: MKMapItem, destinationLocation: MKMapItem, doneSearching: @escaping (_ distance: CLLocationDistance) -> Void) {
let request: MKDirections.Request = MKDirections.Request()
request.departureDate = departureDate
request.arrivalDate = arrivalDate
request.source = sourceLocation
request.destination = destinationLocation
request.requestsAlternateRoutes = true
request.transportType = .automobile
let directions = MKDirections(request: request)
directions.calculate { (directions, error) in
if var routeResponse = directions?.routes {
routeResponse.sort(by: {$0.expectedTravelTime <
$1.expectedTravelTime})
let quickestRouteForSegment: MKRoute = routeResponse[0]
doneSearching(quickestRouteForSegment.distance)
}
}
}
func getDistance(departureDate: Date, arrivalDate: Date, startLocation : CLLocation, endLocation : CLLocation, completionHandler: @escaping (_ distance: CLLocationDistance) -> Void) {
let destinationItem = MKMapItem(placemark: MKPlacemark(coordinate: startLocation.coordinate))
let sourceItem = MKMapItem(placemark: MKPlacemark(coordinate: endLocation.coordinate))
self.calculateDistancefrom(departureDate: departureDate, arrivalDate: arrivalDate, sourceLocation: sourceItem, destinationLocation: destinationItem, doneSearching: { distance in
completionHandler(distance)
})
}