2011-11-10 41 views
2

計算兩個大圈之間的角度我希望這是簡單的,但我發現了一些奇怪的結果。如果有人能指出我做錯了什麼,我將不勝感激。球體上的

我有3個點(A,B,C)定義在地球表面(假定是一個球體)與每個點的座標爲[lat, long]。我需要計算由AC和AB組成的兩個Great Arcs之間的角度。

我已經有一個計算大圓距離(GCD)的函數,所以我決定通過獲取AC,AB和CA的GCD來解決這個問題,將它們減少到單位球體,然後應用球形定律餘弦得到角度BAC。

這似乎工作,給我合理的角度。然而,我然後試圖將所有三點都放在同一個大圓圈上,並且發生了一件奇怪的事情。如果B和C在1度以內,結果是合理的,但是當我開始將B和C沿着同一個大圓環進一步分開時,角度開始增長!

例如:

A = 49, 1 
B = 49, 10  => Angle: 0.0378 
C = 49, 10.1 

A = 49, 1 
B = 49, 10  => Angle: 0.2270 
C = 49, 10.6 

A = 49, 1 
B = 49, 10  => Angle: 3.7988 
C = 49, 20 

A = 49, 1 
B = 49, 10  => Angle: 99.1027 
C = 49, 200 

這是某種形式的精度誤差的,或者是我的公式錯了嗎?

下面是代碼(getDistance()是衆所周知的工作):

public static BigDecimal getAngle(
     final BigDecimal commonLat, final BigDecimal commonLong, 
     final BigDecimal p1Lat, final BigDecimal p1Long, 
     final BigDecimal p2Lat, final BigDecimal p2Long) { 

    // Convert real distances to unit sphere distances 
    // 
    double a = getDistance(p1Lat, p1Long, commonLat, commonLong).doubleValue()/RADIUS_EARTH; 
    double b = getDistance(p2Lat, p2Long, commonLat, commonLong).doubleValue()/RADIUS_EARTH; 
    double c = getDistance(p1Lat, p1Long, p2Lat, p2Long).doubleValue()/RADIUS_EARTH; 

    // Use the Spherical law of cosines to get at the angle between a and b 
    // 
    double numerator = Math.cos(c) - Math.cos(a) * Math.cos(b); 
    double denominator = Math.sin(a) * Math.sin(b); 
    double theta = Math.acos(numerator/denominator); 

    // Back to degrees 
    // 
    double angleInDegrees = Math.toDegrees(theta); 

    return new BigDecimal(angleInDegrees); 
    } 

不幸的是我,我的應用程序往往有將近上線的點,所以精度在這種情況下是非常重要的。這裏出了什麼問題?

編輯:按照要求,這裏是getDistance()的代碼:

public static BigDecimal getDistance(final BigDecimal endLat, final BigDecimal endLong, 
    final BigDecimal startLat, final BigDecimal startLong) { 

    final double latDiff = Math.toRadians(endLat.doubleValue() - startLat.doubleValue()); 
    final double longDiff = Math.toRadians(endLong.doubleValue() - startLong.doubleValue()); 

    final double lat1 = Math.toRadians(startLat.doubleValue()); 
    final double lat2 = Math.toRadians(endLat.doubleValue()); 

    double a = 
     Math.sin(latDiff/2) * Math.sin(latDiff/2) + 
     Math.sin(longDiff/2) * Math.sin(longDiff/2) * Math.cos(lat1) * Math.cos(lat2); 
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); 
    double d = RADIUS_EARTH * c; 

    return new BigDecimal(d); 
} 

RADIUS_EARTH聲明是無關緊要的,B/C,我們在距離計算乘以它,然後通過將其在角度計算劃分,所以它被取消了。

+0

您應該'getDistance'代碼和'RADIUS_EARTH'聲明 – 2011-11-10 06:21:51

+0

好了,一個你正在服用的一大小數,然後把它當作一個雙......你可能會失去存在的準確性添加代碼。看看http://stackoverflow.com/questions/2173512/java-bigdecimal-trigonometric-methods它指出一個數學庫,做任意精度三角學 –

回答

1

就讓我們來看看你的座標說,那緯度IST同一經度變化。但緯度(赤道除外)的所有圈子都不是大圓圈。如果經度不變,緯度不一,您是否嘗試過您的計劃?

+0

謝謝,Mnementh。我不能相信我錯過了:)。 –