要解决这个问题,首先得熟悉一下Haversine公式。
Haversine 公式是一种用于计算球面上两个点之间最短距离(大圆距离)的数学公式。这个公式通常用于地球表面的距离计算,特别是在导航和地理信息系统 (GIS) 中。
两点间的大圆距离可以通过球面三角形的边和角来计算。在 Haversine 公式中,给定两个点的纬度和经度,可以使用以下公式计算它们之间的距离:
a = sin²(Δlat/2) + cos(lat1) · cos(lat2) · sin²(Δlon/2)
c = 2 · atan2(√a,√(1−a))
distance = radius · c
其中:
- lat1 和 lon1 是第一个点的纬度和经度,lat2 和 lon2 是第二个点的纬度和经度。
- Δlat = lat2 − lat1,Δlon = lon2 − lon1。
- sin 和 cos 是正弦和余弦函数。
- atan2 是反正切函数,它返回给定两个参数的反正切值。
- a 是球面三角形的一边,c 是球面上的弧长,distance 是两点之间的球面距离。
- radius 是球体的半径,通常取地球的平均Haversine 公式的优点在于它适用于小距离的球面距离计算,并且不涉及复杂的三角函数。在实际应用中,这个公式通常被用于计算地球上两个地点之间的距离。
知晓了原理,就可以开始行动了,下面是java代码实现:
/**
* 地球半径
*/
private static final double EARTH_RADIUS_KM = 6371.0;
/**
* Haversine公式计算距离
*
* @param lat1 纬度1
* @param lon1 经度1
* @param lat2 纬度2
* @param lon2 经度2
* @return 两点之间的距离(km)
*/
public static double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
//将经纬度转换为弧度
double lat1Rad = Math.toRadians(lat1);
double lon1Rad = Math.toRadians(lon1);
double lat2Rad = Math.toRadians(lat2);
double lon2Rad = Math.toRadians(lon2);
//计算经纬度的差值
double deltaLat = lat2Rad - lat1Rad;
double deltaLon = lon2Rad - lon1Rad;
//用Haversine公式计算
double a = Math.pow(Math.sin(deltaLat / 2), 2)
+ Math.cos(lat1Rad)
* Math.cos(lat2Rad)
* Math.pow(Math.sin(deltaLon / 2), 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double distance = EARTH_RADIUS_KM * c;
//四舍五入取小数点后两位
return CurrencyUtil.roundToTwoDecimalPlaces(distance);
}