ios 计算两个 CLLocationCoordinate2Ds 之间的方位

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3809337/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 17:48:32  来源:igfitidea点击:

Calculating bearing between two CLLocationCoordinate2Ds

iosobjective-ccoordinatescore-location

提问by James J

Very "simple" problem: given two CLLocationCoordinate2Ds, how can I get the bearing (as radians) from the first to the second? I've done a lot of research and studying on this, both the general problem and Objective-C/Cocoa Touch/iOS specifically.

非常“简单”的问题:给定两个 CLLocationCoordinate2D,如何从第一个到第二个得到方位(以弧度表示)?我对此进行了大量研究和研究,特别是一般问题和 Objective-C/Cocoa Touch/iOS。

Here's my implementation:

这是我的实现:

- (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));         
}

However, this method isn't returning consistant results for me. If the bearing is close to due north or due south, it seems to be fine, however, any other direction seems to return inconsistant data, for example:

但是,这种方法并没有为我返回一致的结果。如果方位接近正北或正南,似乎没问题,但是,任何其他方向似乎返回不一致的数据,例如:

From 50.405018, 8.437500

从 50.405018, 8.437500

To 51.339802, 12.403340

至 51.339802, 12.403340

My method returns: 5.918441 radians

我的方法返回:5.918441 弧度

Should be 1.18660576 radians

应该是 1.18660576 弧度

(see http://www.movable-type.co.uk/scripts/latlong.htmland http://www.movable-type.co.uk/scripts/latlong-map.html?lat1=50.405018&long1=8.437500&lat2=51.339802&long2=12.403340)

(参见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)

I've double and triple checked the formula is correct. I've also spot checked a bunch of values like the example above, some correct, some wrong. I've played around with various modulos or bounding of the return value, also no luck.

我已经两次和三次检查公式是否正确。我还抽查了一堆类似上面例子的值,有些是正确的,有些是错误的。我玩过各种模数或返回值的边界,也没有运气。

Any ideas? Is there an issue with my code? Maybe I've misunderstood something about how math functions work?

有任何想法吗?我的代码有问题吗?也许我误解了数学函数的工作原理?

采纳答案by Oren Trutner

Your math is correct, with the following exceptions:

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

  1. Make sure to convert fLat, fLon, tLat, and tLonto radians before applying any sin()or cos()to them. Divide by 180.0 and multiply by PI.

  2. Enter the delta between tLngand fLngas tLng-fLng, and not the other way around. Note that this difference appears twice in the expression.

  1. 在对它们应用任何sin()cos()之前,请确保将fLatfLontLattLon转换为弧度。除以 180.0 再乘以 PI。

  2. 输入tLngfLng之间的增量作为tLng-fLng,而不是相反。请注意,这种差异在表达式中出现了两次。

With those changes, I am getting 1.18660677830947 radians with double precision math and the values in the question.

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

回答by megabri

Here the code modified with the changes suggested by Oren Trutner and from myself:

这里使用 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;
    }
}

回答by Sahil Kapoor

Swift 3:

斯威夫特 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)
    }
}

回答by Trianto Kontri

you can use my code.. it's work on my project with microcontroller that use GPS for data.

你可以使用我的代码..它在我的项目上工作,微控制器使用 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;
    }                                                                 
}