最近邻区域可视化

6
我正在编写一个使用k-d树查找二维空间中点的应用程序。在开发过程中,能够“看到”每个点周围最近邻居区域会很好。
在附加的图像中,红色点是k-d树中的点,蓝线环绕每个点,限定了最近邻搜索将返回包含点的区域。
图像是这样创建的:
for each point in the space:
  da = distance to nearest neighbor
  db = distance to second-nearest neighbor
  if absolute_value(da - db) < 4:
    draw blue pixel

这个算法有两个问题:
  • (更重要的)在我的(相对较快的Core i7)电脑上速度很慢。
  • (不太重要的)它不够精确,你可以通过蓝线的宽度变化看出来。
这种点集“可视化”叫什么?
有哪些好的算法可以创建这样的可视化效果?

partitions

4个回答

7
这被称为沃罗诺伊图,有许多优秀的算法可以高效地生成它们。我听说最常用的是福特算法,其运行时间为O(n log n),但也存在其他算法来解决此问题。
希望这能帮到你!

4

Jacob,你用一种有趣的方式生成了这个沃罗诺伊图,尽管它不太高效。

先说不那么重要的问题:你得到的可变厚度边界,也就是蝴蝶形状的区域,实际上是双曲线两个分支之间的面积。确切地说,是由方程|da - db| = 4给出的双曲线。要得到一条粗线,你必须修改此标准,并将其替换为两个最近邻居的角平分线距离;使用向量计算,|PA.AB/||AB|| - ||AB||/2 | < 4。

更重要的问题:有两种已知的有效方法可以构建一组点的沃罗诺伊图:Fortune's sweep algorithm(如templatetypedef所述)和Preparata & Shamos' Divide & Conquer solutions。两者都以O(N.Lg(N))的最优时间运行,但并不容易实现。

这些算法将构造沃罗诺伊图作为一组线段和半线段。请参阅http://en.wikipedia.org/wiki/Voronoi_diagram

本文“Primitives for the manipulation of general subdivisions and the computation of Voronoi”使用一种有点高级的框架描述了这两种算法,关注所有实现细节;该文章很难,但这些算法是可实现的。

你也可以看看“平面沃罗诺伊图的直接迭代算法”,我从未尝试过。

完全不同的方法是直接从给定点构建距离映射,例如通过Dijkstra算法:从给定点开始,你扩展每个点距离内的区域边界,当两个边界相遇时停止扩展。[需要更多解释。] 请参见http://1.bp.blogspot.com/-O6rXggLa9fE/TnAwz4f9hXI/AAAAAAAAAPk/0vrqEKRPVIw/s1600/distmap-20-seed4-fin.jpg

另一个计算距离映射的高效起点可以是“用线性时间计算距离变换的通用算法”。


2

根据个人经验:Fortune算法实现起来很麻烦。Guibas和Stolfi提出的分治算法还好;他们提供了详细的伪代码,易于转录成过程式编程语言。两者都会在使用浮点数时因输入接近退化而崩溃,但由于基元是二次的,如果您可以将坐标表示为32位整数,则可以使用64位执行行列式计算。

一旦您使其正常工作,您可能会考虑用适用于平面子区域的算法替换kd-tree算法,后者具有Theta(√n)的最坏情况。


1

谢谢提供链接。我最终使用了D3实现,效果非常好。 - Jacob Marble

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接