计算两个CLLocationCoordinate2D之间的方位
非常“简单”的问题:给定两个CLLocationCoordinate2D,我怎么能从第一个到第二个获得方位(弧度)? 我已经做了大量的研究和研究,包括一般问题和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.html和http://www.movable-type.co.uk/scripts/latlong-map.html?lat1=50.405018&long1=8.437500 &lat2 = 51.339802&long2 = 12.403340 )
我已经双重和三重检查公式是正确的。 我也发现了一堆像上面这个例子那样的值,有些是正确的,有些是错误的。 我玩过各种模块或者返回值的边界,也没有运气。
有任何想法吗? 我的代码有问题吗? 也许我误解了math函数的工作原理?
你的math是正确的,但有以下例外:
-
确保在将sin()或cos()应用于它们之前,将fLat , fLon , tLat和tLon转换为弧度。 除以180.0并乘以PI。
-
inputtLng和fLng之间的差值为tLng-fLng ,而不是相反。 请注意,这种差异在expression式中出现两次。
随着这些变化,我得到1.18660677830947弧度双精度math和值的问题。
这里的代码修改了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; } }
Swift 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) }
你可以使用我的代码..这是我的项目与微控制器使用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; } }