您可以使用曼哈顿距离(按纬度缩放)获得一个非常快速上界估计距离,这应该足以拒绝 99.9% 的候选人(如果他们不接近)(编辑:从那以后你告诉我们他们很接近。在这种情况下,你的度量应该是距离平方,根据 Lars H 的评论)。
考虑这相当于拒绝球形矩形边界框之外的任何东西(作为圆形边界框的近似值)。
我不做 Ruby,所以这里是带有伪代码的算法:
让你的参考点P(pa,po)和其他点X(xa,xo)的纬度、经度。
预计算ka,纵向距离的纬度比例因子:ka (= cos(pa in°))。 (严格来说,ka = 常数是 P 附近的线性化近似值。)
那么距离估计为:D(X,P) = ka*|xa-pa| + |xo-po| = ka*da + do
在哪里 |z|表示绝对(z)。在最坏的情况下,这会高估真实距离 √2 倍(当 da==do 时),因此我们允许如下:
进行一次连续搜索并保持 Dmin,这是按比例计算的第五小曼哈顿距离估计值。
因此,您可以预先拒绝所有 D(X,P) > √2 * Dmin 的点(因为它们必须至少比 √((ka*da)² + do²)更远 - 那应消除 99.9% 的点)。
保留所有剩余候选点的列表,其中 D(X,P) 如果您找到新的第五小 D. 优先级队列,则更新 Dmin,否则为(coord,D) 是很好的数据结构。
请注意,我们从未计算欧几里得距离,我们只使用浮点乘法和加法。
(考虑这类似于四叉树,除了过滤掉除我们感兴趣的区域之外的所有内容,因此无需预先计算准确的距离或构建数据结构。)
如果您告诉我们预期的纬度、经度分布(度、分还是什么)会有所帮助?如果所有点都接近,则此估计器中的 √2 因子将过于保守,并将每个点都标记为候选;最好使用基于查找表的距离估计器。)
伪代码:
initialize Dmin with the fifth-smallest D from the first five points in list
for point X in list:
if D(X,P) <= √2 * Dmin:
insert the tuple (X,D) in the priority-queue of candidates
if (Dmin>D): Dmin = D
# after first pass, reject candidates with D > √2 * Dmin (use the final value of Dmin)
# ...
# then a second pass on candidates to find lowest 5 exact distances