2010-09-28 98 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

相關問題