k-way三角集交集和三角剖分

时间:2013-01-30 21:59:33

标签: c++ performance algorithm graphics computational-geometry

如果我们有K组可能重叠的三角形,那么计算一组新的非重叠三角形的计算效率是多少?

例如,请考虑以下问题:

Tesselation

这里我们有3个三角形集A,B,C,有一些相互重叠,并希望得到非重叠集A',B',C',AB,AC,BC,ABC,例如AC中的三角形将包含A和C之间唯一重叠的表面;和A'将包含A的表面,它们不与任何其他集重叠。

5 个答案:

答案 0 :(得分:3)

我(也)建议采用两步法。

<强> 1。找到所有三角形边的交点。

正如评论中所指出的,这是一个研究得很好的问题,通常采用线扫方法。这是very nice overview,特别是Bentley-Ottmann算法。

<强> 2。使用受约束的Delaunay进行三角测量。

我认为@Claudiu建议的Polygon Triangulation无法解决您的问题,因为它无法保证包含所有原始边缘。因此,我建议你看看Constrained Delaunay triangulations。这些允许您指定必须包含在三角剖分中的边,即使它们不包含在无约束Delaunay或多边形三角剖分中。此外,还有一些实现允许您指定三角剖分的非凸边框,在该边框之外不生成三角形。在您的情况下,这似乎也是一个要求。

实施受约束的Delaunay并非易事。但是,CMU研究员(包括命令行工具)可以提供very nice C implementation。有关此特定算法的理论,请参阅here。该算法还支持边界规范。请注意,链接算法可以做的不仅仅是Constrained Delaunay(即质量网格生成),但可以配置为不添加新点,这相当于约束Delaunay。

修改查看其他实施的评论。

答案 1 :(得分:2)

如果你想要更直接的东西,更快的实现,更少的代码...我建议你做一些简单的polygon clipping,就像旧的软件渲染算法一样(特别是你自己'只处理三角形作为输入)。正如其他几个人简要提到的那样,它涉及在每个其他 与之相交的点处拆分每个三角形。

三角形很容易,因为在给定平面上分割三角形总是会产生1或2个新的(总共2或3)。如果您的数据集相当大,您可以引入四叉树或其他形式的空间组织,以便在添加新的三角形时更快地找到相交的三角形。

enter image description here

当然,这会产生比建议的Constrained Delaunay算法更多的多边形。但是这些算法中的许多算法在重叠形状方面做得并不好,并且需要你知道你的轮廓线段,所以你无论如何都会做同样的工作。

如果需要更少的结果三角形,您可以始终在最后进行合并传递(在剪切期间添加邻居信息以加快该部分的速度)。

无论如何,祝你好运!

答案 2 :(得分:1)

您的示例是计算几何学家称之为“一种安排”的特例。 CGAL Library具有广泛而有效的安排处理程序。如果选中this part of the documentation,您将看到可以声明一个空排列,然后插入三角形以将2d平面划分为不相交的面。正如其他人所说,你需要对不是三角形的面进行三角测量。令人高兴的是,CGAL还提供了执行此操作的例程。 This example of constrained Delaunay triangulation是一个很好的起点。

CGAL尝试使用可实用的最有效的算法。在这种情况下,看起来你可以实现O((n + k)log n)用于具有n个边(在你的情况下为三角形数的3倍)与k交点的布置。该算法使用称为“扫描线”的通用技术。垂直线从左到右扫描,沿途计算和处理“事件”。事件是边缘端点和交叉点。在处理每个事件时,将更新排列的单元格。

对于n个顶点,Delaunay算法通常为O(n log n)。有几种常见的算法,很容易在CGAL参考文献中查找或找到。

即使您不能在工作中使用CGAL(例如出于许可原因),文档中也充满了基础算法的来源:排列和受约束的Delaunay算法。

请注意,由于浮点错误,因此很难正确地实现安排和三角测量。强大的版本通常依赖于有理算术(CGAL中提供)。

答案 3 :(得分:0)

我可以想到两种方法。

更通用的方法是将输入视为一组行并将问题分成两部分:

  1. 多边形检测。获取初始三角形所构成的一组线,并获得一组非重叠多边形。 This paper提供O((N + M)^ 4)方法,N是线段的数量,M是交叉点的数量,不幸的是,这看起来有点慢......
  2. Polygon Triangulation。从步骤1中取出每个多边形并对其进行三角测量。这需要O(n log * n),其实际上是O(n)。
  3. 另一种方法是做自定义算法。解决交叉两个三角形的问题,将其应用于前两个输入三角形,然后对于每个新三角形,将算法应用于具有新三角形的所有当前三角形。看起来即使是两个三角形也不是那么简单,因为有几种情况(可能不是详尽无遗):

    1. 三角形的任何点都没有任何其他三角形。
      1. 没有交叉点
      2. 犹太明星
      3. 两个垂直钉鞋
    2. 另一个三角形的一个点包含在另一个
    3. 每个三角形包含另一个
    4. 的一个点
    5. 一个三角形中的两个点在另一个
    6. 一个在另一个中有三个点 - 一个是完全包含的
    7. 等等......不,这似乎不是正确的做法。无论如何都留在这里为后人。

答案 4 :(得分:0)

为了扩展Ted Hopp的评论,首先应该计算一个平面细分,其中输出的每个有界面与A',B',C',AB中的一个相关联, AC,BC,ABC或“无”。然后第二阶段对每组中的(可能是非凸的)面进行三角测量。

步骤1可以使用Bentley-Ottmann扫描线算法的变化在O((N + K)log N)时间内执行,其中当前集合被保持为算法状态的一部分。这可以从已经越过的线段及其方向确定。

一旦完成,每组的不相交多边形可以在O(N log N)时间内被分解为单调片段,而O(N log N)时间又可以在O(N)时间内进行三角测量。

如果您还没有,请拿起de Berg等人的“计算几何:算法和应用”副本。