【问题标题】:Efficient triangulation of weakly simple polygon with known, ordered boundary points具有已知有序边界点的弱简单多边形的有效三角剖分
【发布时间】:2021-08-23 13:02:20
【问题描述】:

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

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

我在 Python 中工作——对于我使用哪些软件包或它们拥有什么许可证,我真的没有任何限制。

我尝试过的方法

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

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

问题的具体形式

  1. 是否有利用我高度具体的案例的算法(不同于耳夹或约束 delaunay),或者
  2. 有没有更有效的方法来检查生成的 tris 是否在我的边界内?

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

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

【问题讨论】:

    标签: python triangulation


    【解决方案1】:

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

    它们在 test.pypi.org 上以预编译包的形式提供:https://test.pypi.org/project/cgal/

    【讨论】:

    • 我在 Triangle 之前看过 CGAL,现在正在回头看。这么大的一个包,要花点时间。您是否知道它是否具有删除不需要的 tris 的实现?
    • 没有什么可以从数据结构中删除三角形,但是您可以在每个三角形上附加一个布尔数据,说明是否必须过滤掉三角形。
    • 如果我明白你在说什么,我仍然需要“如何为每个唯一的 tri 生成布尔标志,以确定是否必须过滤 tri”。这似乎重述了我的未决问题,不是吗?
    • 一旦多边形的所有线段都作为约束处于受约束的 Delaunay 三角剖分中,您就可以从无限面开始泛洪三角剖分。在泛洪期间,每次遍历约束时翻转标记。
    【解决方案2】:

    对此我有 2 条建议:

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

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

    1。对于最快的三角测量

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

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

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

    • 在你的飞机上选择一个方向(不管它是什么)
    • 根据该方向对您的点进行排序
    • 按照它们来自该排序列表的顺序考虑匹配点

    [ ] - 一个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
    

    结论

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

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

    【讨论】:

    • 这太好了,谢谢。我将研究贪婪和扫描线三角剖分。我对“丑陋的网格”的评论可能被夸大了。这些网格被导入到 3D 图形程序中——细三角形可能会弄乱法线和平滑过程,但在 3D 软件中进行一些后期编辑,任何非自相交都可以。
    猜你喜欢
    • 1970-01-01
    • 2017-04-09
    • 2013-10-04
    • 2014-11-01
    • 2011-07-12
    • 1970-01-01
    • 2014-05-29
    • 2012-09-28
    • 2015-03-19
    相关资源
    最近更新 更多