问题描述
我需要快速找到3个(或更多个)维度中距平面(或超平面)最近的k个点。是否存在使用某种聪明的数据结构(类似于kd-tree对k个最近邻居的工作方式)执行该搜索的快速方法?
我知道我可以旋转平面和所有点,以使平面正交于其中一个轴,然后仅通过使用该轴上的坐标来测量每个点到平面的距离。但是,这种蛮力方法的时间复杂度是O(N),其中(N)是点数。由于我必须找到大量平面和大量点的k个最近邻居,因此,如果可能,我需要找到一种更快的算法。
解决方法
通过使用具有超平面法线的点积来测量距离...所以让:
n
-是超平面法线单位向量
p0
-是超平面上的任意点
p[i]
-是您的Pointcloud i={ 0,1,2...n-1 }
的第i点
那么到超平面的距离是:
d = |dot( p[i] - p0,n )|
,如您所见,无需任何昂贵的操作就无需变换/对齐任何内容及其O(1)
。我希望在大多数情况下,任何预先排序的点或使用巧妙的结构都比这要慢...
现在您有2个选择,要么为每个点计算d
,然后进行快速排序,这将导致O(n.log(n))
时间和O(n)
空间复杂度。
或者记住跑步中k
个最接近的点,这些时间导致O(k*n)
个时间和O(k)
个空间。
因此,如果k
很小(k < log(n))
,或者您没有足够的内存来备用,请使用第二种方法,否则请使用第一种方法。
我认为您可以简单地使用任何支持自定义距离功能的空间数据结构(kd-tree,R-tree等)。您应该能够定义一个距离函数,该函数仅使用到平面的距离而不是到中心点的距离。
@Spektre描述了如何计算此距离。
我不知道它如何扩展,因为它可能取决于实现所使用的kNN搜索算法。 但是,我相信标准算法(Hjaltason和Samet:“在空间数据库中进行距离浏览”。)至少应优于O(n)。
如果您使用的是Java,我的TinSpin库中的R-Tree,Quadtree和PH-Tree索引都使用此算法。