下面是针对“Python根据经纬度计算距离”的完整攻略。
1. 确定坐标系
在进行经纬度计算时,首先需要确定所使用的坐标系。通常使用的是WGS-84坐标系,它是GPS使用的坐标系,也是Google Maps和其他在线地图平台的标准坐标系。
2. 计算距离
计算距离的方法有很多种,以下是其中比较常用的两种方法。
方法一:Haversine公式
Haversine公式是根据经纬度计算两点间最短距离的常见算法之一,它的基本思路是将地球看成一颗球体,根据两个点的经纬度计算出它们在球面上对应点的夹角,然后将夹角转换成弧长即距离。下面是使用Haversine公式计算距离的示例代码:
from math import radians, sin, cos, sqrt, atan2
def haversine(lat1, lon1, lat2, lon2):
R = 6371 # 地球平均半径,单位为公里
lat1, lon1, lat2, lon2 = map(radians, [lat1, lon1, lat2, lon2])
dlon = lon2 - lon1
dlat = lat2 - lat1
a = sin(dlat / 2) ** 2 + cos(lat1) * cos(lat2) * sin(dlon / 2) ** 2
c = 2 * atan2(sqrt(a), sqrt(1 - a))
distance = R * c
return distance
该函数接受四个参数,分别为两个点的经度和纬度,返回值为两点之间的距离,单位为千米。
方法二:Vincenty公式
Vincenty公式是Haversine公式的改进版,它同样也是根据经纬度计算两点之间距离的方法,但是它考虑了地球不是完全的球形,而是一个椭球体的事实。下面是使用Vincenty公式计算距离的示例代码:
from math import sin, cos, atan2, sqrt, pi
def vincenty(lat1, lon1, lat2, lon2):
a = 6378137 # 赤道半径,单位为米
b = 6356752.314245 # 极半径,单位为米
f = 1 / 298.257223563 # 扁率
L = radians(lon2 - lon1)
U1 = atan2((1 - f) * sin(radians(lat1)), cos(radians(lat1)))
U2 = atan2((1 - f) * sin(radians(lat2)), cos(radians(lat2)))
sinU1, cosU1 = sin(U1), cos(U1)
sinU2, cosU2 = sin(U2), cos(U2)
lam = L
i = 0
while True:
sinLam, cosLam = sin(lam), cos(lam)
sinSigma = sqrt((cosU2 * sinLam) ** 2 + (cosU1 * sinU2 - sinU1 * cosU2 * cosLam) ** 2)
if sinSigma == 0:
return 0 # 两点重合
cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLam
sigma = atan2(sinSigma, cosSigma)
sinAlpha = cosU1 * cosU2 * sinLam / sinSigma
cosSqAlpha = 1 - sinAlpha ** 2
if cosSqAlpha == 0:
cos2SigmaM = 0 # 两点在赤道上
else:
cos2SigmaM = cosSigma - 2 * sinU1 * sinU2 / cosSqAlpha
C = f / 16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha))
newLam = L + (1 - C) * f * sinAlpha * (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM ** 2)))
if abs(newLam - lam) < 1e-12:
break
lam = newLam
i += 1
if i == 1000:
return None # 失败,迭代次数太多
uSq = cosSqAlpha * (a ** 2 - b ** 2) / b ** 2
A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)))
B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)))
deltaSigma = B * sinSigma * (cos2SigmaM + 1 / 4 * B * (cosSigma * (-1 + 2 * cos2SigmaM ** 2) - 1 / 6 * B * cos2SigmaM * (-3 + 4 * sinSigma ** 2) * (-3 + 4 * cos2SigmaM ** 2)))
s = b * A * (sigma - deltaSigma)
return s / 1000 # 返回值单位为千米
与Haversine相比,Vincenty需要进行更多的计算,但精度更高。
3. 示例
下面是两个示例,一个使用Haversine公式计算距离,一个使用Vincenty公式计算距离。
示例一:Haversine公式
lat1 = 31.281334
lon1 = 121.500464
lat2 = 31.230416
lon2 = 121.473701
distance = haversine(lat1, lon1, lat2, lon2)
print(f"两地之间的距离为{distance:.2f}千米")
以上代码使用Haversine公式,计算了上海市区浦东机场与虹桥机场之间的距离,输出结果为:
两地之间的距离为33.70千米
示例二:Vincenty公式
lat1 = 31.281334
lon1 = 121.500464
lat2 = 31.230416
lon2 = 121.473701
distance = vincenty(lat1, lon1, lat2, lon2)
print(f"两地之间的距离为{distance:.2f}千米")
以上代码使用Vincenty公式,计算了上海市区浦东机场与虹桥机场之间的距离,输出结果为:
两地之间的距离为32.61千米
以上就是根据经纬度计算距离的Python攻略。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:python根据经纬度计算距离示例 - Python技术站