确定2个坐标之间的中点

时间:2012-05-11 22:02:48

标签: objective-c mapkit core-location

我正在尝试确定MKMapView中两个位置之间的中点。我遵循概述here(和here)的方法,并在Objective-C中重写,但地图正在巴芬岛东北部的某个地方居中,这两个地方附近都没有。

我的方法基于上面链接的java方法:

+(CLLocationCoordinate2D)findCenterPoint:(CLLocationCoordinate2D)_lo1 :(CLLocationCoordinate2D)_loc2 {
    CLLocationCoordinate2D center;

    double lon1 = _lo1.longitude * M_PI / 180;
    double lon2 = _loc2.longitude * M_PI / 100;

    double lat1 = _lo1.latitude * M_PI / 180;
    double lat2 = _loc2.latitude * M_PI / 100;

    double dLon = lon2 - lon1;

    double x = cos(lat2) * cos(dLon);
    double y = cos(lat2) * sin(dLon);

    double lat3 = atan2( sin(lat1) + sin(lat2), sqrt((cos(lat1) + x) * (cos(lat1) + x) + y * y) );
    double lon3 = lon1 + atan2(y, cos(lat1) + x);

    center.latitude  = lat3 * 180 / M_PI;
    center.longitude = lon3 * 180 / M_PI;

    return center;
}

2个参数包含以下数据:

_loc1:
    latitude = 45.4959839
    longitude = -73.67826455

_loc2:
    latitude = 45.482889
    longitude = -73.57522299

以上内容正确地放置在地图上(蒙特利尔及其周边地区)。我试图将地图置于2之间的中点,但我的方法返回以下内容:

latitude = 65.29055
longitude = -82.55425
在北极的某个地方,它应该在南方约500英里处。

5 个答案:

答案 0 :(得分:13)

只是预感,但我注意到您的lon2lat2变量是使用M_PI/100而非M_PI/180计算的。

double lon1 = _lo1.longitude * M_PI / 180;
double lon2 = _loc2.longitude * M_PI / 100;

double lat1 = _lo1.latitude * M_PI / 180;
double lat2 = _loc2.latitude * M_PI / 100;

将这些更改为180可能对您有所帮助。

答案 1 :(得分:13)

如果有人需要Swift中的代码,我在Swift中编写了库函数来计算MULTIPLE坐标之间的中点:

//        /** Degrees to Radian **/
class func degreeToRadian(angle:CLLocationDegrees) -> CGFloat {
    return (  (CGFloat(angle)) / 180.0 * CGFloat(M_PI)  )
}

//        /** Radians to Degrees **/
class func radianToDegree(radian:CGFloat) -> CLLocationDegrees {
    return CLLocationDegrees(  radian * CGFloat(180.0 / M_PI)  )
}

class func middlePointOfListMarkers(listCoords: [CLLocationCoordinate2D]) -> CLLocationCoordinate2D {

    var x = 0.0 as CGFloat
    var y = 0.0 as CGFloat
    var z = 0.0 as CGFloat

    for coordinate in listCoords{
        var lat:CGFloat = degreeToRadian(coordinate.latitude)
        var lon:CGFloat = degreeToRadian(coordinate.longitude)
        x = x + cos(lat) * cos(lon)
        y = y + cos(lat) * sin(lon)
        z = z + sin(lat)
    }

    x = x/CGFloat(listCoords.count)
    y = y/CGFloat(listCoords.count)
    z = z/CGFloat(listCoords.count)

    var resultLon: CGFloat = atan2(y, x)
    var resultHyp: CGFloat = sqrt(x*x+y*y)
    var resultLat:CGFloat = atan2(z, resultHyp)

    var newLat = radianToDegree(resultLat)
    var newLon = radianToDegree(resultLon)
    var result:CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: newLat, longitude: newLon)

    return result

}

可以找到详细答案here

答案 2 :(得分:7)

对于快速用户,修正后的变体为@dinjas建议

import Foundation
import MapKit
extension CLLocationCoordinate2D {
    // MARK: CLLocationCoordinate2D+MidPoint
    func middleLocationWith(location:CLLocationCoordinate2D) -> CLLocationCoordinate2D {

        let lon1 = longitude * M_PI / 180
        let lon2 = location.longitude * M_PI / 180
        let lat1 = latitude * M_PI / 180
        let lat2 = location.latitude * M_PI / 180
        let dLon = lon2 - lon1
        let x = cos(lat2) * cos(dLon)
        let y = cos(lat2) * sin(dLon)

        let lat3 = atan2( sin(lat1) + sin(lat2), sqrt((cos(lat1) + x) * (cos(lat1) + x) + y * y) )
        let lon3 = lon1 + atan2(y, cos(lat1) + x)

        let center:CLLocationCoordinate2D = CLLocationCoordinate2DMake(lat3 * 180 / M_PI, lon3 * 180 / M_PI)
        return center
    }
}

答案 3 :(得分:0)

说OP用于计算地理中点的公式基于this formula,这解释了cos / sin / sqrt计算,这很重要。

此公式将为您提供任何距离的地理中点,包括四个季度和本初子午线。

但是,如果您的计算是针对<1>公里左右的短程,则使用简单平均值将产生相同的中点结果。 即:

let firstPoint = CLLocation(....)
let secondPoint = CLLocation(....)

let midPointLat = (firstPoint.coordinate.latitude + secondPoint.coordinate.latitude) / 2
let midPointLong = (firstPoint.coordinate.longitude + secondPoint.coordinate.longitude) / 2

你实际上可以使用它10公里但是期望偏差 - 如果你只需要用快速解决方案估算短程中点就足够了。

答案 4 :(得分:-6)

我认为你有点过分思考。只是做:

float lon3 = ((lon1 + lon2) / 2)
float lat3 = ((lat1 + lat2) / 2)

lat3和lon3将成为中心点。