計算兩個大圈之間的角度我希望這是簡單的,但我發現了一些奇怪的結果。如果有人能指出我做錯了什麼,我將不勝感激。球體上的
我有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,我們在距離計算乘以它,然後通過將其在角度計算劃分,所以它被取消了。
您應該'getDistance'代碼和'RADIUS_EARTH'聲明 – 2011-11-10 06:21:51
好了,一個你正在服用的一大小數,然後把它當作一個雙......你可能會失去存在的準確性添加代碼。看看http://stackoverflow.com/questions/2173512/java-bigdecimal-trigonometric-methods它指出一個數學庫,做任意精度三角學 –