具有已知有序边界点的弱简单多边形的有效三角剖分

问题描述

我有一个点集 P,它表示平面多边形的(有序)边界点,内部没有任何点。多边形可能是凹面的,并且至少是 weakly simple。可以将所有多边形约束为简单的。我的目标是比 O(n^2) 更快地对平面多边形进行三角剖分。

集合P的大小从几百个点到1-200万不等。由于这些多边形是如何生成的特定原因,很难简单地进行下采样并获得较小的集合 P。

我使用 Python 工作——我对我使用的软件包或他们拥有的许可证没有任何限制。

我尝试过的方法

我的“稳定”软件是围绕 earclipping algorithm 构建的。这对于具有数百或数千个点的小示例非常有效,但对于大型多边形来说运行时间过长。它没有利用边界和边界排序的知识(而且很挑剔,会产生非常难看的网格)。

最近我尝试使用 Triangle,通过一些 python bindings 和受约束的 delaunay 算法。即使在提供边界边时,受约束的 delaunay 在凹形上运行也会返回多边形边界腔内的三角形。注意:我不需要(准)delaunay 三角剖分,我正在查看 Triangle,因为它紧凑、广受好评且速度快。 凹度填充的一个简单解决方案是检查生成的三角形是否在边界内(例如,计算每个三角形的质心并运行点入多边形算法)。然而,简单的点入多边形算法(例如光线投射)在 O(n^2) 时间内运行,因为对于 P 中的 n 个点,有 n 个边界边缘,必须检查 ~n 个生成的 tris。

问题的具体形式

  1. 是否有一种(不同于耳夹或受约束的 delaunay)算法可以利用我的高度特定情况,或者
  2. 是否有更有效的方法来检查生成的 tris 是否在我的边界内?

根据我在下面链接到的其他一些 SO 帖子,听起来 Triangle 满足了上述一项或两项,而我只是没有充分利用它(可能也是python 绑定?)。我有 C 的功能上不存在的知识;到目前为止,对 Triangle 代码的挖掘一直没有结果。

我看过类似的问题,但并没有完全解决我的问题:

解决方法

我对此有 2 个建议:

  • 您可以找到一种执行甜蜜三角测量的算法,但速度不会比 O(n**2)
  • 您可以更快地找到算法O(n*log(n)),但它总是(根据我的经验)以牺牲三角剖分的质量为代价

当生成连接仅来自表面轮廓的点的三角形时,通常将其命名为贪心三角剖分

1.对于最快的三角剖分

有两种算法(据我所知):

  • 直接三角测量的人
  • 那些将给定的非凸轮廓分割成较小的凸轮廓(或至少是单调的),然后才对它们进行三角剖分(这很容易,因为这是凸轮廓)

两者都基于所谓的sweepline algorithms,简而言之:

  • 选择飞机的方向(无论是什么)
  • 按照那个方向排序你的观点
  • 按照它们在排序列表中的顺序考虑匹配点

[ ] - A publication for the 1st kind

[ ] - this wikipedia page 也很有用。

2.最好的三角剖分

有多种方法,但我所知道的最好的方法是通过减少轮廓进行三角测量:

  • 选择一个点,您将放置一个与其直接相邻的三角形
  • 创建一个三角形并从轮廓中删除最新的点
  • 再做一次,直到没有轮廓
  • 有一些启发式方法可以知道每次迭代优先制作哪个三角形

这就是在madcad.triangulation中所做的,它的复杂度是O(n*k),k = 凹点数

from madcad.triangulation import *

outline = Wire([ ... your points ... ])

triangulation(outline)  # this is triangulating the outline,it even works with holes in the surface
triangulation_outline(outline)  # this function is a subpart of the latest,working only on outlines with no holes

结论

我取决于你需要什么:) 我个人在大多数用例中都放弃了最快的三角剖分,因为在平滑轮廓的情况下三角形的质量非常差。

如果您需要对生成的网格执行一些计算,非常细的三角形将导致使用浮点的精度显着下降。

,

如果你对 Triangle 不满意,也许你可以试试 CGAL python 绑定:https://github.com/CGAL/cgal-swig-bindings

它们在 test.pypi.org 上作为预编译包提供:https://test.pypi.org/project/cgal/