2010-09-28 120 views
34

非常“简单”的问题:给定两个CLLocationCoordinate2D,如何从第一个到第二个获得方位(以弧度表示)?我已经做了大量的研究和研究,包括一般问题和Objective-C/Cocoa Touch/iOS。计算两个CLLocationCoordinate2D之间的方位

这里是我的实现:

- (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

我已经双重和三重检查了公式是正确的。我也发现了一些像上面这个例子那样的值,一些是正确的,一些是错误的。我玩过各种模块或返回值的界限,也没有运气。

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

回答

30

你的数学是正确的,但下列情况除外:

  1. 确保氟利昂转换TLATtLon施加任何犯罪之前弧度()cos()给他们。除以180.0并乘以PI。

  2. 输入三角洲TLNG和FLNG为TLNG-FLNG之间,而不是周围的其他方式。请注意,这种差异在表达式中出现两次。

随着这些变化,我得到1.18660677830947弧度与双精度数学和问题中的值。

+1

我最初的反应是“转换纬度/经度弧度?这是什么样的疯狂?“然后我真的尝试了它,就像一个魅力 – 2010-09-29 05:20:53

+1

好点。地理纬度和经度度的使用是如此根深蒂固,很容易忘记他们描述球体几何中的角度地球大多数现代语言中的trig函数需要弧度,强制转换 – 2010-09-30 05:34:26

+0

你能解释2吗?如果fLng较大,会怎样? – Nick 2010-10-12 11:02:43

50

这里由奥伦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; 
    } 
} 
+0

@ 0x7fffffff但是它的工作原理和原理概述如下: – 2014-02-12 22:23:31

+4

shouldn这些是双打而不是花车..? – 2014-12-19 10:21:39

+0

什么是最后的if语句?角度如何小于0?还有什么点的其他声明,为什么角度超过360? – Supertecnoboff 2017-03-10 10:30:24

0

你可以使用我的代码..在我的项目它的工作与使用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; 
    }                 
} 
+0

为什么'22/7'而不是M_PI更精确? – Sulthan 2016-09-17 21:20:44

6

斯威夫特3:

func getBearing(toPoint point: CLLocationCoordinate2D) -> Double { 
    func degreesToRadians(degrees: Double) -> Double { return degrees * M_PI/180.0 } 
    func radiansToDegrees(radians: Double) -> Double { return radians * 180.0/M_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) 
} 
+0

谢谢你。一个更小的疑问。我的地图视图动画更新位置,如建筑物和其他图标闪烁。 – 2016-12-17 10:43:03

+0

可能是这可以帮助:http://stackoverflow.com/a/30862133/3950397 – 2016-12-17 10:46:07

+0

雅我已经做了类似的方式,但没有为我工作 – 2016-12-17 11:19:48