一、概述
隨著全球經濟的發展和交通出行的便捷,我們需要對兩點之間的距離進行準確的計算,而經緯度距離計算就是最常見的一種計算方法。在Java中,我們可以使用不同的方法來實現經緯度距離計算,本文將針對這一問題,介紹一些經典的演算法和代碼實現。
二、常見的經緯度距離計算方法
在實現經緯度距離計算時,常用的有以下三種方法:
1、球面餘弦定理:該方法適用於計算地球上兩點之間的距離,需要使用球面三角形的餘弦定理。
2、Vincenty公式:該方法是基於橢球體上的測地線距離計算的,是計算地球上兩點之間距離的精確方法。
3、Haversine公式:該方法是一種簡單的計算地球上兩點之間距離的方法,適用於全球各地的距離計算。
三、球面餘弦定理計算代碼示例:
public static final double EARTH_RADIUS = 6371.393; //地球半徑,單位千米
public static double getDistance(double long1, double lat1, double long2, double lat2){
long1 = Math.toRadians(long1);
long2 = Math.toRadians(long2);
lat1 = Math.toRadians(lat1);
lat2 = Math.toRadians(lat2);
double cos = Math.cos(lat1) * Math.cos(lat2) * Math.cos(long1 - long2) + Math.sin(lat1) * Math.sin(lat2);
double distance = EARTH_RADIUS * Math.acos(cos);
return distance;
}
以上代碼是基於球面餘弦定理實現的經緯度距離計算,通過該方法我們可以計算出兩點之間的準確距離。需要注意的是,計算的結果是千米,如果需要轉換為其他單位,需要自行進行轉換計算。
四、Vincenty公式計算代碼示例:
public static final double EARTH_RADIUS = 6378137; //地球半徑,單位米
public static double getDistance(double long1, double lat1, double long2, double lat2){
double a = EARTH_RADIUS;
double b = a - 21.385 * (1 - Math.sin(Math.toRadians(lat1))) / 180;
double f = (a - b) / a;
double L = Math.toRadians(long2 - long1);
double U1 = Math.atan((1 - f) * Math.tan(Math.toRadians(lat1)));
double U2 = Math.atan((1 - f) * Math.tan(Math.toRadians(lat2)));
double sinU1 = Math.sin(U1);
double cosU1 = Math.cos(U1);
double sinU2 = Math.sin(U2);
double cosU2 = Math.cos(U2);
double lambda = L;
double sinLambda = Math.sin(lambda);
double cosLambda = Math.cos(lambda);
double sinSigma = 0;
double cosSigma = 0;
double sigma = 0;
double sinAlpha = 0;
double cosSqAlpha = 0;
double cos2SigmaM = 0;
double C = 0;
double deltaLambda = 0;
double tempLambda = 0;
for (int i = 0; i < 100; i++) {
tempLambda = lambda;
sinLambda = Math.sin(tempLambda);
cosLambda = Math.cos(tempLambda);
sinSigma = Math.sqrt((cosU2 * sinLambda) * (cosU2 * sinLambda) + (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda) * (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda));
cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda;
sigma = Math.atan2(sinSigma, cosSigma);
sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma;
cosSqAlpha = 1 - sinAlpha * sinAlpha;
cos2SigmaM = cosSigma - 2 * sinU1 * sinU2 / cosSqAlpha;
if (Double.isNaN(cos2SigmaM)) {
cos2SigmaM = 0;
}
C = f / 16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha));
deltaLambda = L + (1 - C) * f * sinAlpha * (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)));
if (Math.abs(deltaLambda - lambda) < 0.0001) {
break;
} else {
lambda = deltaLambda;
}
}
double distance = b * cosU2 * (deltaLambda - L);
return distance;
}
以上代碼是基於Vincenty公式實現的距離計算,這個演算法可以提供更高的計算精度,但計算量相對較大。
五、Haversine公式計算代碼示例:
public static final double EARTH_RADIUS = 6371.393; //地球半徑,單位千米
public static double getDistance(double long1, double lat1, double long2, double lat2){
double radLat1 = Math.toRadians(lat1);
double radLat2 = Math.toRadians(lat2);
double a = radLat1 - radLat2;
double b = Math.toRadians(long1) - Math.toRadians(long2);
double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
s = s * EARTH_RADIUS;
return s;
}
以上代碼是基於Haversine公式實現的經緯度距離計算,演算法簡單而效率高,早在18世紀時就被廣泛應用于海洋導航。
六、總結
在本文中,我們介紹了三種不同的方法實現經緯度距離計算,分別是球面餘弦定理、Vincenty公式和Haversine公式。在實際應用中,我們需要根據具體情況選擇不同的方法。球面餘弦定理適用於需要快速計算近似距離的場景,Haversine公式可用於快速計算全球各地的距離,Vincenty公式則可提供更高的計算精度。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/181973.html
微信掃一掃
支付寶掃一掃