正如@Davis Herring 在 cmets 中提到的,一个有效的选择是 k-d 树。
k-d 树是一种避免蛮力方法并允许有效距离计算的算法*(背景见答案底部)。
这有几个 Python 实现,其中之一是通过SciPy:
SciPy k-d tree in Cython(使用 C/Cython 更快)
SciPy k-d tree in pure Python
您可以通过首先为您的 xyz 数据构建一个 k-d 树来使用它:
import numpy as np #for later code
from scipy.spatial import cKDTree
kdtree = cKDTree(xyzData)
然后,您必须使用点 point 查询 k-d 树,以计算 point 与其最近邻居之间的距离。此查询的输出是point 与其最近邻居之间的距离NN_dist 以及该邻居的索引NN_idx。要计算所有点的值,我们需要一个 for 循环,但考虑到 k-d 树算法,这比蛮力计算要快得多:
NN_dists = np.zeros(numPoints) #pre-allocate an array to store distances
for i in range(numPoints):
point = xyzData[i]
NN_dist, NN_idx = kdtree.query(point,k=[1])
#Note: 'k' specifies the kth neighbor distance to compute,
#so set k=2 if you end up finding the point as its own "neighbor":
if NN_dist == 0:
NN_dist, NN_idx = targetTree.query(curCoord,k=[2])
NN_dists[i] = NN_dist
(详情请参阅k-d tree query)。
然后,要查找低于某个阈值的距离,您可以在使用比较运算符时使用 NumPy 数组的内置实用程序(如 <):
distanceThres = 10
goodIdx = NN_dists < distanceThres
goodPoints = xyzData[goodIdx]
这将为您提供位于指定距离阈值distanceThres 内的索引goodIdx 和点goodPoints(尽管您可能必须根据xyz 坐标数据的形状/格式更改此代码)。
*k-d 树上的浅色背景(对细节进行修饰——更多信息请参阅参考资料):k-d 树方法以避免计算每个点之间的距离的方式对数据集进行分区(即蛮力方法) )。它通过将数据集划分为二进制空间分区来构建 k-d 树来做到这一点。这些分区使得距离计算(例如,最近邻搜索)可以忽略远处分区中的数据点。此外,每个点都会重复使用相同的 k-d 树。
网上有很多关于 k-d 树的资源。当我学习这个算法时,我发现这些参考资料最有帮助:Stanford k-d trees 或 Princeton k-d trees。
如果您有任何问题,请告诉我——我自己在一个天文学项目中遇到了这个确切的问题,所以我可以提供更多帮助。