Java計(jì)算經(jīng)緯度距離的示例代碼
在 Java 中計(jì)算兩個(gè)經(jīng)緯度之間的距離,可以使用以下多種方法(代碼示例均返回米為單位):
1. Haversine公式(中等精度,推薦通用場(chǎng)景)
public class GeoDistanceCalculator {
public static double haversineDistance(double lat1, double lon1, double lat2, double lon2) {
final int EARTH_RADIUS_METERS = 6371000;
double dLat = Math.toRadians(lat2 - lat1);
double dLon = Math.toRadians(lon2 - lon1);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(Math.toRadians(lat1)) *
Math.cos(Math.toRadians(lat2)) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return EARTH_RADIUS_METERS * c;
}
public static void main(String[] args) {
double distance = haversineDistance(40.7128, -74.0060, 34.0522, -118.2437);
System.out.println("距離:" + distance + " 米"); // 輸出約 3933476 米
}
}2. 球面余弦定理(簡(jiǎn)單但精度較低)
public static double sphericalCosineLaw(double lat1, double lon1, double lat2, double lon2) {
final int EARTH_RADIUS_METERS = 6371000;
double lat1Rad = Math.toRadians(lat1);
double lat2Rad = Math.toRadians(lat2);
double dLon = Math.toRadians(lon2 - lon1);
double distance = Math.acos(
Math.sin(lat1Rad) * Math.sin(lat2Rad) +
Math.cos(lat1Rad) * Math.cos(lat2Rad) * Math.cos(dLon)
) * EARTH_RADIUS_METERS;
return distance;
}
3. Vincenty公式(高精度,適用于復(fù)雜模型)
public static double vincentyDistance(double lat1, double lon1, double lat2, double lon2) {
final double a = 6378137.0; // 赤道半徑(米)
final double b = 6356752.314245; // 極半徑(米)
final double f = 1 / 298.257223563; // 扁率
double L = Math.toRadians(lon2 - lon1);
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), cosU1 = Math.cos(U1);
double sinU2 = Math.sin(U2), cosU2 = Math.cos(U2);
double lambda = L, lambdaPrev;
double sinSigma, cosSigma, sigma, sinAlpha, cosSqAlpha, C;
int maxIterations = 200;
do {
double sinLambda = Math.sin(lambda), cosLambda = Math.cos(lambda);
sinSigma = Math.sqrt(
(cosU2 * sinLambda) * (cosU2 * sinLambda) +
(cosU1 * sinU2 - sinU1 * cosU2 * cosLambda) *
(cosU1 * sinU2 - sinU1 * cosU2 * cosLambda)
);
if (sinSigma == 0) return 0; // 重合點(diǎn)
cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda;
sigma = Math.atan2(sinSigma, cosSigma);
sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma;
cosSqAlpha = 1 - sinAlpha * sinAlpha;
C = f / 16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha));
lambdaPrev = lambda;
lambda = L + (1 - C) * f * sinAlpha *
(sigma + C * sinSigma * (cosSigma + C * cosSigma * (-1 + 2 * C * cosSigma * cosSigma)));
} while (Math.abs(lambda - lambdaPrev) > 1e-12 && --maxIterations > 0);
double uSq = cosSqAlpha * (a * a - b * b) / (b * b);
double A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));
double B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));
double deltaSigma = B * sinSigma * (cosSigma + B / 4 *
(cosSigma * (-1 + 2 * B * cosSigma * cosSigma) -
B / 6 * cosSigma * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cosSigma * cosSigma)));
return b * A * (sigma - deltaSigma);
}4. Android內(nèi)置方法(僅限Android開(kāi)發(fā))
import android.location.Location;
public static float androidLocationDistance(double lat1, double lon1, double lat2, double lon2) {
Location location1 = new Location("point1");
location1.setLatitude(lat1);
location1.setLongitude(lon1);
Location location2 = new Location("point2");
location2.setLatitude(lat2);
location2.setLongitude(lon2);
return location1.distanceTo(location2); // 返回米
}
5. 極地坐標(biāo)系近似法(快速但低精度)
public static double polarApproximation(double lat1, double lon1, double lat2, double lon2) {
final int EARTH_RADIUS_METERS = 6371000;
double dLat = Math.toRadians(lat2 - lat1);
double dLon = Math.toRadians(lon2 - lon1);
double avgLat = Math.toRadians((lat1 + lat2) / 2);
double x = dLon * Math.cos(avgLat);
double y = dLat;
return Math.sqrt(x * x + y * y) * EARTH_RADIUS_METERS;
}6.方法對(duì)比
| 方法 | 精度 | 速度 | 適用場(chǎng)景 |
|---|---|---|---|
| Haversine公式 | 中等(~0.5%) | 快 | 通用場(chǎng)景(導(dǎo)航、LBS服務(wù)) |
| Vincenty公式 | 高(~0.5mm) | 慢 | 高精度需求(測(cè)繪、科學(xué)研究) |
| 球面余弦定理 | 低 | 快 | 快速估算(非關(guān)鍵場(chǎng)景) |
| Android Location | 中等 | 中等 | Android應(yīng)用開(kāi)發(fā) |
| 極地近似法 | 低 | 極快 | 快速篩選大量坐標(biāo)點(diǎn) |
7.選擇建議
推薦使用 Haversine 公式:適用于大多數(shù)應(yīng)用(如計(jì)算兩個(gè)城市間的距離)。
需要高精度時(shí)選擇 Vincenty 公式:例如地質(zhì)勘測(cè)或?qū)Ш较到y(tǒng)。
Android 開(kāi)發(fā)直接使用 Location.distanceTo():無(wú)需手動(dòng)實(shí)現(xiàn)算法。
快速篩選坐標(biāo)點(diǎn)用極地近似法:例如在數(shù)據(jù)庫(kù)中篩選附近地點(diǎn)。
8.知識(shí)延展
Python計(jì)算經(jīng)緯度兩點(diǎn)之間距離方法
在Python中計(jì)算兩個(gè)經(jīng)緯度之間的距離有多種方法,常用的包括Haversine公式和Vincenty公式。下面是這兩種方法的實(shí)現(xiàn)示例。
1. Haversine公式
Haversine公式是一種簡(jiǎn)單且常用的計(jì)算地球表面兩點(diǎn)之間最短距離(大圓距離)的方法。
import math
def haversine_distance(lat1, lon1, lat2, lon2):
# 地球半徑,單位:公里
R = 6371.0
# 將經(jīng)緯度轉(zhuǎn)換為弧度
lat1_rad = math.radians(lat1)
lon1_rad = math.radians(lon1)
lat2_rad = math.radians(lat2)
lon2_rad = math.radians(lon2)
# 計(jì)算差值
dlat = lat2_rad - lat1_rad
dlon = lon2_rad - lon1_rad
# Haversine公式
a = math.sin(dlat / 2)**2 + math.cos(lat1_rad) * math.cos(lat2_rad) * math.sin(dlon / 2)**2
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
distance = R * c
return distance
# 示例使用
lat1, lon1 = 34.052235, -118.243683 # 洛杉磯的經(jīng)緯度
lat2, lon2 = 40.712776, -74.005974 # 紐約的經(jīng)緯度
distance = haversine_distance(lat1, lon1, lat2, lon2)
print(f"Distance using Haversine formula: {distance} km")2. Vincenty公式
Vincenty公式提供了更高的精度,適用于需要精確測(cè)量的情況。
第一種使用geographiclib庫(kù)
pip install geographiclib
from geographiclib.geodesic import Geodesic
def vincenty_distance(lat1, lon1, lat2, lon2):
geod = Geodesic.WGS84 # 使用WGS84橢球體模型
result = geod.Inverse(lat1, lon1, lat2, lon2)
distance = result['s12'] / 1000.0 # 距離單位:公里
return distance
# 示例使用
lat1, lon1 = 34.052235, -118.243683 # 洛杉磯的經(jīng)緯度
lat2, lon2 = 40.712776, -74.005974 # 紐約的經(jīng)緯度
distance = vincenty_distance(lat1, lon1, lat2, lon2)
print(f"Distance using Vincenty formula: {distance} km")
第二種使用geopy庫(kù)
pip install geopy
from geopy.distance import geodesic
def calculate_distance_with_geopy(lat1, lon1, lat2, lon2):
# 定義兩個(gè)點(diǎn)
point1 = (lat1, lon1)
point2 = (lat2, lon2)
# 計(jì)算兩點(diǎn)之間的距離
distance = geodesic(point1, point2).kilometers
return distance
# 示例使用
lat1, lon1 = 34.052235, -118.243683 # 洛杉磯的經(jīng)緯度
lat2, lon2 = 40.712776, -74.005974 # 紐約的經(jīng)緯度
distance = calculate_distance_with_geopy(lat1, lon1, lat2, lon2)
print(f"Distance using Vincenty formula: {distance} km")Haversine公式:簡(jiǎn)單易用,適合大多數(shù)情況。
Vincenty公式:更高精度,適用于需要精確測(cè)量的情況。
到此這篇關(guān)于Java計(jì)算經(jīng)緯度距離的示例代碼的文章就介紹到這了,更多相關(guān)Java計(jì)算經(jīng)緯度距離內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Java根據(jù)坐標(biāo)經(jīng)緯度計(jì)算兩點(diǎn)距離5種方法及校驗(yàn)經(jīng)緯度是否在圓/多邊形區(qū)域內(nèi)的算法推薦
- Java中如何使用Redis GEO測(cè)算經(jīng)緯度距離
- Java通過(guò)經(jīng)緯度坐標(biāo)獲取兩個(gè)點(diǎn)之間的直線距離的示例
- Java編程獲取經(jīng)緯度之間距離的方法
- java計(jì)算兩點(diǎn)間的距離方法總結(jié)
- Java實(shí)現(xiàn)的計(jì)算最大下標(biāo)距離算法示例
- java實(shí)現(xiàn)計(jì)算地理坐標(biāo)之間的距離
相關(guān)文章
Spring Data JPA 語(yǔ)法詳解與使用案例詳解
Spring Data JPA 通過(guò)接口繼承和方法名解析,大幅簡(jiǎn)化了數(shù)據(jù)庫(kù)操作,開(kāi)發(fā)者可以專注于業(yè)務(wù)邏輯而無(wú)需編寫(xiě)大量重復(fù)代碼,本文通過(guò)實(shí)例代碼給大家介紹Spring Data JPA 語(yǔ)法詳解與使用案例,感興趣的朋友跟隨小編一起看看吧2025-09-09
Java的validation參數(shù)校驗(yàn)代碼實(shí)例
這篇文章主要介紹了Java的validation參數(shù)校驗(yàn)代碼實(shí)例,Validation參數(shù)校驗(yàn)是指在程序運(yùn)行中對(duì)傳進(jìn)來(lái)的參數(shù)進(jìn)行合法性檢查,以保證程序的正確性和安全性,需要的朋友可以參考下2023-10-10
Spring入門配置和DL依賴注入實(shí)現(xiàn)圖解
這篇文章主要介紹了Spring入門配置和DL依賴注入實(shí)現(xiàn)圖解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10
Springboot接收?Form?表單數(shù)據(jù)的示例詳解
這篇文章主要介紹了Springboot接收?Form?表單數(shù)據(jù)的實(shí)例代碼,本文通過(guò)圖文實(shí)例代碼相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08
使用自定義注解進(jìn)行restful請(qǐng)求參數(shù)的校驗(yàn)方式
這篇文章主要介紹了使用自定義注解進(jìn)行restful請(qǐng)求參數(shù)的校驗(yàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10
Spring Boot 防止接口惡意刷新和暴力請(qǐng)求的實(shí)現(xiàn)
本文主要介紹了Spring Boot 防止接口惡意刷新和暴力請(qǐng)求的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06
SpringBoot默認(rèn)日志logback輸出格式配置
Springboot內(nèi)置使用了commons-logging日志門面,并內(nèi)置一個(gè)logback日志實(shí)現(xiàn),默認(rèn)輸出INFO級(jí)別,可以在application配置文件中修改logback的默認(rèn)配置,下面就來(lái)介紹一下,感興趣的可以了解一下2025-09-09

