[英]How can I quickly estimate the distance between two (latitude, longitude) points?
我希望能够估计两个(纬度,经度)点之间的距离。 我想低于,因为这将用于 A* 图形搜索,并且我希望它很快。 这些点最多相距 800 公里。
Python 中Haversine 公式的答案(两个 GPS 点之间的轴承和距离)提供了 Python 实现来回答您的问题。
使用下面的实现,我在较旧的笔记本电脑上在不到 1 秒的时间内执行了 100,000 次迭代。 我认为就您的目的而言,这应该足够了。 但是,在优化性能之前,您应该分析任何内容。
from math import radians, cos, sin, asin, sqrt
def haversine(lon1, lat1, lon2, lat2):
"""
Calculate the great circle distance between two points
on the earth (specified in decimal degrees)
"""
# convert decimal degrees to radians
lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
# haversine formula
dlon = lon2 - lon1
dlat = lat2 - lat1
a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
c = 2 * asin(sqrt(a))
# Radius of earth in kilometers is 6371
km = 6371* c
return km
低估haversine(lat1, long1, lat2, long2) * 0.90
或您想要的任何因素。 我不明白在你的低估中引入错误有什么用。
由于距离相对较小,您可以使用等距柱状距离近似值。 这种近似比使用Haversine 公式更快。 因此,要获得从参考点 (lat1/lon1) 到您要测试的点 (lat2/lon2) 的距离,请使用以下公式。 重要提示:您需要将所有经纬度点转换为弧度:
R = 6371 // radius of the earth in km
x = (lon2 - lon1) * cos( 0.5*(lat2+lat1) )
y = lat2 - lat1
d = R * sqrt( x*x + y*y )
由于“R”以公里为单位,因此距离“d”将以公里为单位。
速度的一种想法是将经纬度坐标转换为 3D (x,y,z) 坐标。 对点进行预处理后,使用点之间的欧几里得距离作为实际距离的快速计算下冲。
如果点之间的距离相对较小(几米到几公里的范围),那么快速方法之一可能是
from math import cos, sqrt
def qick_distance(Lat1, Long1, Lat2, Long2):
x = Lat2 - Lat1
y = (Long2 - Long1) * cos((Lat2 + Lat1)*0.00872664626)
return 111.319 * sqrt(x*x + y*y)
Lat, Long 以弧度为单位,距离以公里为单位。
与 Haversine 距离的偏差约为 1%,而速度增益超过 ~10 倍。
0.00872664626 = 0.5 * pi/180,
111.319 - 是对应于赤道 1 度的距离,你可以用你的中值替换它,就像这里https://www.cartographyunchained.com/cgsta1/或用一个简单的查找表替换它。
您可以使用cdist
空间距离类中的scipy
:
例如:
from scipy.spatial.distance import cdist
df1_latlon = df1[['lat','lon']]
df2_latlon = df2[['lat', 'lon']]
distanceCalc = cdist(df1_latlon, df2_latlon, metric=haversine)
要计算两点之间的半正弦距离,您可以简单地使用mpu.haversine_distance()库,如下所示:
>>> import mpu
>>> munich = (48.1372, 11.5756)
>>> berlin = (52.5186, 13.4083)
>>> round(mpu.haversine_distance(munich, berlin), 1)
>>> 504.2
请使用以下代码。
def distance(lat1, lng1, lat2, lng2):
#return distance as meter if you want km distance, remove "* 1000"
radius = 6371 * 1000
dLat = (lat2-lat1) * math.pi / 180
dLng = (lng2-lng1) * math.pi / 180
lat1 = lat1 * math.pi / 180
lat2 = lat2 * math.pi / 180
val = sin(dLat/2) * sin(dLat/2) + sin(dLng/2) * sin(dLng/2) * cos(lat1) * cos(lat2)
ang = 2 * atan2(sqrt(val), sqrt(1-val))
return radius * ang
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.