我们使用标准容器和算法讨论Voronoi图的简单变体,这些容器和算法提供的性能比暴力法更好。
布局
介绍
基于边界的Voronoi图
点位置查询
简单变体的想法
蛮力法
网格法
倒排列表
计算复杂度
更新操作
Voronoi图的更高级的变体
C ++实现
Voronoi图的可视化和距离变换
性能测试
使用C ++代码
与C#实现的比较
德劳内三角剖分
参考文献
介绍
Voronoi图(参见图1)是具有许多应用程序的基本几何结构。有关更详细的描述,请参见Wikipedia [1]中的文章及其参考。
图1:平面中一组点的Voronoi图。
不幸的是,Voronoi图的有效编程表示需要相当复杂的数据结构。开发和维护这些数据结构的高成本是在实践中充分利用这一强大的数学概念的严重障碍。
在这里,我们讨论使用可互换STL容器的可负担且有效的Voronoi图。这种方法的主要优点是表示简单,开发和维护成本低以及对各种用户算法的适应性。好处是以性能为代价的,但是,它比暴力方法要好得多。Voronoi图的建议变体对于快速开发需要Voronoi图功能的算法,以及开发Voronoi图的高级和高效表示形式应该是有用的。
基于边界的Voronoi图
根据定义,Voronoi图表示将二维空间细分为由一组输入点诱导的区域,这些点在传统术语中称为站点。每个区域都有一个多边形边界,其中包含最接近该区域站点的平面的所有点。这些区域也称为Voronoi细胞。
图2: Voronoi图的基于边界的表示图。两个相邻单元格的公共边界元素用红色绘制。
Voronoi图的广泛使用的基于边界的表示形式,如图2所示,存储了位置,单元,边缘和顶点的集合。这些表示的复杂性不仅与数据集相关,而且与支持不同类型表示形式的元素之间的邻接关系的需求有关。例如,边缘必须链接到单元格边界中的上一条和下一条边缘,此外,该边缘必须存储到该边界所包围的单元格的至少一个链接。这些表示形式对于有效遍历Voronoi图和计算Voronoi单元的参数(例如面积和周长)很有用。
点位置查询
应用程序中所需的Voronoi图的主要功能之一是平面点定位算法,该算法针对给定的查询点查找包含该点的像元。点位置问题非常重要。在实践中出现的许多类型的特定问题可以简化为点位置问题。一个典型的示例是涉及计算居住在购物中心区域内的客户数量的任务。
尽管有丰富的数据集,但是基于边界的表示方法没有提供比具有线性运行时间的搜索更好的功能。一种方法是将多边形中的测试点应用于Voronoi单元。另一种方法是通过计算从查询点到每个站点的距离来找到最近的站点。为了使用对数运行时间进行有效的搜索操作,Voronoi图的表示应使用基于R树或有向无环图(DAG)的空间索引。另一个高级数据结构的开发和集成使有效的Voronoi图的实现和维护变得颇具挑战性,并且成本很高。
简单变体的想法
Voronoi图的实际变体的想法是通过存储和使用尽可能少的数据集来降低表示的复杂性。在建议的最小变体中,Voronoi图仅由一组站点表示。该表示的第二个元素是最近邻居搜索的算法。该算法旨在支持Voronoi图的功能:点位置,查找站点的邻居以及构建单元格边界。如果最近邻居搜索的实现简单,则此方法可提供这种Voronoi图表示的主要优点-降低开发和维护成本。该变体的另一个好处是最小的空间需求。
蛮力法
在开发的早期阶段,考虑并实施Voronoi图的蛮力变体是合理的。它基于简单的算法,该算法计算查询点与每个Voronoi站点之间的距离,并找到具有第一个最小距离的站点。实施蛮力变体的简便性以牺牲用户算法所需的操作效率为代价。该方法具有线性运行时间。对于大型数据集来说太慢了。
Voronoi图的简单表示的主要问题是,是否有可能在不开发点位置查询所需的复杂空间数据结构的情况下提高最近邻居搜索的效率。
网格法
蛮力方法的低效率可以通过流行的网格方法解决。此方法的最简单变体是构建大小相等的方形单元。每个网格单元均存储其包含的点的列表。
图3:网格方法的图示。最近邻居搜索算法计算查询点(红色)和灰色单元中的点之间的距离。
搜索从包含查询点的单元格开始,然后在与访问的单元格相邻的单元格中继续进行搜索(参见图3)。当查询点与最接近的未访问单元格之间的距离大于查询点与已处理数据子集中的点之间的最小距离时,搜索将停止。
网格方法比基于空间数据结构的方法简单得多,但是它并不完全琐碎,并且有许多限制。当空间数据的分布均匀时,此方法可提供最佳性能。像元的最佳大小取决于数据的密度。当网格中有太多的空单元格或一个