问题
想象一下,我站在机场。给定地理坐标对,如何有效地确定我所在的机场?
输入
(x,y)
。[(a1,b1), (a2,b2)...]
,其中每个坐标对代表一个机场。所需输出
来自机场坐标对的坐标对(a,b)
,代表距离(x,y)
最近的机场。
效率低下的解决方案
这是我解决这个问题的低效尝试。它在机场的长度上显然是线性的。
shortest_distance = None
shortest_distance_coordinates = None
point = (50.776435, -0.146834)
for airport in airports:
distance = compute_distance(point, airport)
if distance < shortest_distance or shortest_distance is None:
shortest_distance = distance
shortest_distance_coordinates = airport
问题
如何改进此解决方案?这可能涉及根据我们当前所处位置的坐标预先过滤机场列表的某种方式,或事先按特定顺序对它们进行排序。
答案 0 :(得分:13)
使用k维树:
>>> from scipy import spatial
>>> airports = [(10,10),(20,20),(30,30),(40,40)]
>>> tree = spatial.KDTree(airports)
>>> tree.query([(21,21)])
(array([ 1.41421356]), array([1]))
1.41421356是查询点与最近邻居之间的距离,1是邻居的索引。
答案 1 :(得分:2)
从此SO question:
import numpy as np
def closest_node(node, nodes):
nodes = np.asarray(nodes)
deltas = nodes - node
dist_2 = np.einsum('ij,ij->i', deltas, deltas)
return np.argmin(dist_2)
其中node
是具有两个值(x,y)的元组,而nodes
是具有两个值([(x_1, y_1), (x_2, y_2),]
)的元组数组
答案 2 :(得分:2)
如果您的坐标未分类,只有在(latitude,longitude)
通过先对纬度进行过滤而不是地球时,您的搜索才会略有改进
球体上的1度纬度为111.2 km或69英里
但这不会带来巨大的加速。
如果您先按纬度对机场进行排序,那么您可以使用二进制搜索来查找可能匹配的第一个机场(airport_lat >= point_lat-tolerance
),然后仅比较最后一个机场可以匹配(airport_lat <= point_lat+tolerance
) - 但要照顾0度等于360.虽然你不能直接使用那个库,bisect的来源是实现二进制文件的良好开端搜索范围。
虽然从技术上讲这种方式搜索仍然是O(n),但实际距离计算(取决于公差)和纬度比较很少。所以你将获得巨大的加速。