计算两个CLLocationCoordinate2D之间的方位

时间:2010-09-28 02:47:38

标签: ios objective-c coordinates core-location

非常“简单”的问题:给定两个CLLocationCoordinate2Ds,如何从第一个到第二个获得方位(以弧度为单位)?我已经做了很多研究和研究,包括一般问题和Objective-C / Cocoa Touch / iOS。

这是我的实施:

- (float) getHeadingForDirectionFromCoordinate:(CLLocationCoordinate2D)fromLoc toCoordinate:(CLLocationCoordinate2D)toLoc
{
    float fLat = fromLoc.latitude;
    float fLng = fromLoc.longitude;
    float tLat = toLoc.latitude;
    float tLng = toLoc.longitude;

    return atan2(sin(fLng-tLng)*cos(tLat), cos(fLat)*sin(tLat)-sin(fLat)*cos(tLat)*cos(fLng-tLng));         
}

然而,这种方法并没有为我返回一致的结果。如果轴承接近正北或正南,看起来很好,但是,任何其他方向似乎都会返回不一致的数据,例如:

从50.405018,8.437500

至51.339802,12.403340

我的方法返回:5.918441弧度

应为1.18660576弧度

(请参阅http://www.movable-type.co.uk/scripts/latlong.htmlhttp://www.movable-type.co.uk/scripts/latlong-map.html?lat1=50.405018&long1=8.437500&lat2=51.339802&long2=12.403340

我已经检查过双重和三重配方是否正确。我也发现了一些像上面的例子一样的值,有些是正确的,有些是错的。我玩过各种模数或返回值的界限,也没有运气。

有什么想法吗?我的代码有问题吗?也许我误解了数学函数是如何工作的?

4 个答案:

答案 0 :(得分:52)

这里的代码是根据Oren Trutner和我自己建议的修改而修改的:

#define degreesToRadians(x) (M_PI * x / 180.0)
#define radiansToDegrees(x) (x * 180.0 / M_PI)

- (float)getHeadingForDirectionFromCoordinate:(CLLocationCoordinate2D)fromLoc toCoordinate:(CLLocationCoordinate2D)toLoc
{
    float fLat = degreesToRadians(fromLoc.latitude);
    float fLng = degreesToRadians(fromLoc.longitude);
    float tLat = degreesToRadians(toLoc.latitude);
    float tLng = degreesToRadians(toLoc.longitude);

    float degree = radiansToDegrees(atan2(sin(tLng-fLng)*cos(tLat), cos(fLat)*sin(tLat)-sin(fLat)*cos(tLat)*cos(tLng-fLng)));

    if (degree >= 0) {
        return degree;
    } else {
        return 360+degree;
    }
}

答案 1 :(得分:31)

您的数学是正确的,但以下情况除外:

  1. 确保在应用之前将 fLat fLon tLat tLon 转换为弧度任何 sin() cos()给他们。除以180.0并乘以PI。

  2. tLng fLng 之间的差值输入为 tLng-fLng ,而不是相反。请注意,此差异在表达式中出现两次。

  3. 通过这些更改,我获得了1.18660677830947弧度,双精度数学和问题中的值。

答案 2 :(得分:10)

斯威夫特3:

extension CLLocationCoordinate2D {
    func bearing(to point: CLLocationCoordinate2D) -> Double {
        func degreesToRadians(_ degrees: Double) -> Double { return degrees * Double.pi / 180.0 }
        func radiansToDegrees(_ radians: Double) -> Double { return radians * 180.0 / Double.pi }

        let lat1 = degreesToRadians(latitude)
        let lon1 = degreesToRadians(longitude)

        let lat2 = degreesToRadians(point.latitude);
        let lon2 = degreesToRadians(point.longitude);

        let dLon = lon2 - lon1;

        let y = sin(dLon) * cos(lat2);
        let x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon);
        let radiansBearing = atan2(y, x);

        return radiansToDegrees(radiansBearing)
    }
}

答案 3 :(得分:-1)

你可以使用我的代码..它可以在我的项目中使用微控制器使用GPS进行数据处理。

#define d2r ((22/7.0)/180.0)
#define r2d (180.0/(22/7.0))

double get_heading1(double lat1, double long1, double lat2, double long2)  
{
    double diff_lat, diff_long;
    double degree;

    diff_long =(double) (((long2*1000000)-(long1*1000000))/1000000) * d2r;
    diff_lat = (double) (((lat2*1000000)-(lat1*1000000))/1000000) * d2r;     

    degree = r2d     (atan2(sin(diff_long)*cos(d2r*lat2),cos(d2r*lat1)*sin(d2r*lat2)-sin(d2r*lat1)*cos(d2r*lat2)    *cos(diff_long)));

    if (degree >= 0) {
        return degree;
    } else {
        return 360+degree;
    }                                                                 
}
相关问题