【问题标题】:Given generating points of a voronoi diagram; compute the vertices of it给定 voronoi 图的生成点;计算它的顶点
【发布时间】:2021-02-15 11:38:55
【问题描述】:

令 $p_i$ 为二维空间中的第 i 个点,生成 voronoi 图。这意味着,Voronoi 区域 $V_i$ 中的每个点 $x$ 都满足

$|x-p_i|

和 $|x-p_i|=|x-p_j|,i \neq j$ 在它的边界上。边界是一个有顶点和边的图。现在我对跨越 Voronoi 图的边界(边)的顶点的位置感兴趣。

当我选择 $p_i$ 时,有哪些算法可用于计算 Voronoi 图的顶点位置?

我知道我可以搜索 $p_i$ 的最近邻生成器,​​然后使用外接圆属性;但是我怎样才能尽可能高效地找到最近邻居的位置(这意味着我找到了 Delaunay 三角剖分)?

请注意,我很感兴趣如何找到位于分隔 Voronoi 区域的边界上的顶点(边界的三个边相交处)的坐标向量 $(r_x,r_y)$。有什么提示吗?

【问题讨论】:

  • 您将不得不创建某种数据结构来支持有效的点查询。为什么不将该数据结构设为 Delaunay 三角剖分?
  • @YvesDaoust OP 想要选择一个输入点,而不是任意点。但要回答您的问题,是的,您只需使用 K-D 树、R-树或类似树找到最近的点,然后检查三角形及其 Delaunay 邻居。
  • @YvesDaoust 在 Delaunay 三角剖分中定位点的一种非常有效的方法是使用“walk”算法,例如 Lawson 的 Stochastic Walk。一个好的 Delaunay 库将包括一个。网上有很多关于 Delaunay walk 算法的论文。我在gwlucastrig.github.io/Tinfour/doc/… 的第 28 页上写了一个(我希望)非常简单的解释(参见 2.2.8.4 顶点位置)
  • @YvesDaoust:你的记忆是正确的......在一般情况下,步行的时间复杂度是 O(√n)。从实际的角度来看,如果您的代码以常规模式执行大量行走(例如生成网格),则它可以从完成前一次行走的地方开始每次行走。在那种特殊(虽然很常见)的情况下,相邻点靠近前一个查询,步行时间很短,平均情况是 O(k)。

标签: algorithm graphics computational-geometry voronoi


【解决方案1】:

不幸的是,最优解很复杂。

您可以使用 Fortune 或 Guibas & Stolfi 的算法构建图表,这需要 O(N Log N) 时间和 O(N) 空间。 (由于 Voronoi 图和 Delaunay 三角剖分互为对偶,因此您可以交替构建一个或另一个。)

但是 Voronoi 图的表示不适合任意点的有效定位。因此,您必须将其转换为诸如梯形地图之类的结构,这样可以在 O(Log N) 时间内进行高效的点位置查询。不幸的是,我从未见过在 Voronoi 图的框架中执行这种转换的显式算法。

【讨论】:

    【解决方案2】:

    计算平面中的 Voronoi 区域相当于计算 n 半平面的交点 - 由点 p_i 和每隔一个点 p_j 之间的平分线定义的半平面。 然而,这个问题等价于(通过对偶)计算平面中n 点的凸包(参见《离散与计算几何手册》中的Chapter 30.5 on Arrangements)。 计算平面has a known lower bound of \Omega(n log n) 中一组点的凸包。

    计算 Delaunay 三角剖分只需要 O(n log n) 时间。 因此,正如 @matt-timmermans 和 @yves-daoust 所建议的,将输入预处理为 Delaunay 三角剖分并没有真正的开销,并且可能是大多数应用程序的最佳选择。

    一旦计算了 Delaunay 三角剖分,每个查询(区域边界的构建) 只需要O(1 + k) 时间,其中k 是输出大小,即Voronoi 区域边界上的顶点/边数。 请注意,k 本身可以是\Omega(n),例如,如果n-1 点或多或少地放置在一个圆上并且p_i 靠近其中心。

    虽然最坏情况的算法是\Omega(n log n),因此并不比计算 Delaunay 三角剖分更好, 还有一个输出敏感算法的选项,它采用O(n*k)(取决于输出 Voronoi 区域的大小)。

    在 Voronoi 区域的边界上找到单个顶点等价于线性规划问题的结果 (见Computational Geometry: Algorithms and Applications第4章)。

    特别是,Megiddo 的算法或其随机版本(上述书籍的第 4.4 章)在O(n) 线性时间运行。 一旦找到第一个顶点及其两条生成线,就可以通过将剩余线与生成线相交来找到下一个顶点。 最近的交点是下一个 Voronoi 顶点,然后最近的相交线成为下一条相交的线。 当再次到达第一个顶点时,该过程终止。 总而言之,每次迭代需要O(n),还有k迭代,所以这个算法一共需要O(n*k)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-04
      • 1970-01-01
      相关资源
      最近更新 更多