2011-11-14 122 views
13

我正在嘗試開發自己的增強現實引擎。計算兩個位置之間的軸承(lat,long)

在網上搜索,我發現這個有用的tutorial。閱讀它我發現重要的是在用戶位置,點位置和北部之間。

以下圖片來自該教程。

enter image description here

它之後,我寫了一個Objective-C的方法來獲得測試:

+ (float) calculateBetaFrom:(CLLocationCoordinate2D)user to:(CLLocationCoordinate2D)destination 
{ 
    double beta = 0; 
    double a, b = 0; 

    a = destination.latitude - user.latitude; 
    b = destination.longitude - user.longitude; 

    beta = atan2(a, b) * 180.0/M_PI; 
    if (beta < 0.0) 
     beta += 360.0; 
    else if (beta > 360.0) 
     beta -= 360; 

    return beta; 
} 

但是,當我嘗試它,它不能很好地工作。因此,我檢查了iPhone AR Toolkit,看看它是如何工作的(我一直在使用這個工具包,但它對我來說太大了)。

而且,在ARGeoCoordinate.m存在如何獲得測試另一種實現方式:這個公式(.5f M_PI *)在

float possibleAzimuth = (M_PI * .5f) - atan(latitudinalDifference/longitudinalDifference); 

爲什麼:

- (float)angleFromCoordinate:(CLLocationCoordinate2D)first toCoordinate:(CLLocationCoordinate2D)second { 

    float longitudinalDifference = second.longitude - first.longitude; 
    float latitudinalDifference  = second.latitude - first.latitude; 
    float possibleAzimuth   = (M_PI * .5f) - atan(latitudinalDifference/longitudinalDifference); 

    if (longitudinalDifference > 0) 
     return possibleAzimuth; 
    else if (longitudinalDifference < 0) 
     return possibleAzimuth + M_PI; 
    else if (latitudinalDifference < 0) 
     return M_PI; 

    return 0.0f; 
} 

它使用這個公式?我不明白。

並繼續搜索,我發現另一個page談論如何計算2個位置的距離和方位。在這個頁面還有另一個實現:

/** 
* Returns the (initial) bearing from this point to the supplied point, in degrees 
* see http://williams.best.vwh.net/avform.htm#Crs 
* 
* @param {LatLon} point: Latitude/longitude of destination point 
* @returns {Number} Initial bearing in degrees from North 
*/ 
LatLon.prototype.bearingTo = function(point) { 
    var lat1 = this._lat.toRad(), lat2 = point._lat.toRad(); 
    var dLon = (point._lon-this._lon).toRad(); 

    var y = Math.sin(dLon) * Math.cos(lat2); 
    var x = Math.cos(lat1)*Math.sin(lat2) - 
      Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon); 
    var brng = Math.atan2(y, x); 

    return (brng.toDeg()+360) % 360; 
} 

哪一個是正確的?

+0

你曾經解決過這個問題嗎?我對你使用哪種解決方案感興趣 – Craigy

+0

是的,我不得不短時間添加自己的答案。 – VansFannel

回答

14

軸承計算

//Source 
JSONObject source = step.getJSONObject("start_location"); 
double lat1 = Double.parseDouble(source.getString("lat")); 
double lng1 = Double.parseDouble(source.getString("lng")); 

// destination 
JSONObject destination = step.getJSONObject("end_location"); 
double lat2 = Double.parseDouble(destination.getString("lat")); 
double lng2 = Double.parseDouble(destination.getString("lng")); 

double dLon = (lng2-lng1); 
double y = Math.sin(dLon) * Math.cos(lat2); 
double x = Math.cos(lat1)*Math.sin(lat2) - Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon); 
double brng = Math.toDegrees((Math.atan2(y, x))); 
brng = (360 - ((brng + 360) % 360)); 

轉換成度弧度

Radians = Degrees * PI/180 

轉換成弧度度

Degrees = Radians * 180/PI 
+0

您將該值轉換爲度數,但不是以度數爲單位的緯度和經度?你不應該先把它們轉換成弧度嗎? – ravemir

+0

我不轉換半徑的緯度和經度。我不認爲它有什麼區別 –

+0

你是否嘗試過在線軸承匹配測試?爲前。通過這個鏈接進行測試。 http://www.sunearthtools.com/tools/distance.php –

4

在式

float possibleAzimuth = (M_PI * .5f) - atan(latitudinalDifference/longitudinalDifference);

術語(M_PI * .5f)裝置π/2,其是90°。這意味着它與您剛纔陳述的公式相同,因爲關於上面的數字,它擁有

β = arctan(a/b)= 90° - arctan(b/a)。

因此,如果a指的是經度差和b緯度差,那麼兩個公式都是相似的。最後一個公式使用我的方程的第一部分再次計算相同。

+0

你可以把'a'作爲lat和'b'的差異來表示長度差異。請參閱我的回答,瞭解「a」實際上應該是長期差異還是「b」差異。編輯答案與圖表保持一致可能會有所幫助,所以我們不會混淆未來的讀者。 – Dolbz

+0

謝謝Dolbz,你是對的,a和b應該改變。我編輯了我的主要答案,以便擁有一個正確的答案。 :) – Palund

2

a在圖中是經度差,因此b是緯度差,因此在你寫的方法中你有錯誤的方法。

a = destination.latitude - user.latitude; // should be b 
b = destination.longitude - user.longitude; // should be a 

嘗試切換它們,看看會發生什麼。

請參閱Palund對您其餘問題的回答。

+0

謝謝,你是對的:我與a和b犯了一個錯誤。我已經改變了他們,我得到了β= 9度。但是,如果我使用LatLon.prototype.bearingTo,使用相同的位置,我會得到beta = 7度。我認爲第二個更準確,但我不明白它沒有在iPhone AR Toolkit中實現。再次感謝。 – VansFannel

+0

這解決了這個問題。只需使用arctan(b,a)而不是(a,b)。 –

0

如果你想看看mixare增強現實引擎中使用的代碼,它在github上,還有一個iPhone版本:github。COM/mixare

+0

謝謝。我現在看到你已經使用這個ar瀏覽器。你能幫我找到包含軸承計算的類嗎? – VansFannel

+1

嗨,我不是iPhone版的開發人員,但根據以下網址上提供的類文檔:http://code.google.com/p/mixare/wiki/FileResponsibility,它應該是類AugmentedViewController。來源是:https://github.com/mixare/mixare-iphone/blob/master/Classes/gui/tabbarControllers/augmentedView/AugmentedViewController.m – Daniele

7

我知道這個問題是舊的,但這裏是一個更容易的解決方案:

float bearing = loc1.bearingTo(loc2);

1

嘗試此準確的結果:

private static double degreeToRadians(double latLong) { 
    return (Math.PI * latLong/180.0); 
} 

private static double radiansToDegree(double latLong) { 
    return (latLong * 180.0/Math.PI); 
} 

public static double getBearing() { 

//Source 
JSONObject source = step.getJSONObject("start_location"); 
double lat1 = Double.parseDouble(source.getString("lat")); 
double lng1 = Double.parseDouble(source.getString("lng")); 

// destination 
JSONObject destination = step.getJSONObject("end_location"); 
double lat2 = Double.parseDouble(destination.getString("lat")); 
double lng2 = Double.parseDouble(destination.getString("lng")); 

    double fLat = degreeToRadians(lat1); 
    double fLong = degreeToRadians(lng1); 
    double tLat = degreeToRadians(lat2); 
    double tLong = degreeToRadians(lng2); 

    double dLon = (tLong - fLong); 

    double degree = radiansToDegree(Math.atan2(sin(dLon) * cos(tLat), 
      cos(fLat) * sin(tLat) - sin(fLat) * cos(tLat) * cos(dLon))); 

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

您可以測試http://www.sunearthtools.com/tools/distance.php方位結果。

相關問題