【问题标题】:Algorithm to convert a collection of edges into collection of triangles将边集合转换为三角形集合的算法
【发布时间】:2019-07-08 17:12:28
【问题描述】:

我在我的程序中实现了一个多边形三角剖分算法。该算法首先采用simple polygon,描述为二维点/顶点,并将其拆分为y-monotone pieces。 完成此操作后,该算法将获取每个单调多边形片段并将其拆分为三角形片段。

我需要帮助的算法的输入是一个顶点数组,它以顺时针或逆时针的顺序勾勒出一个 y 单调多边形。输出是所有边的集合,既来自原始多边形,也来自三角剖分算法添加的新边,以便将此 y 单调部分拆分为三角形部分。如果我只想绘制结果,这很有效,因为可以只绘制每个边缘。

但是,这个边的集合没有特定的顺序,我需要输出是 triangle strip 类型的数组一个数组,其中每个三角形都由它的 3 个顶点简单地描述(例如:[a1,a2,a3,b1,b2,b3],因为我们有三角形 a 和三角形 b)。

是否有任何常规算法或任何其他方式可以帮助我解决这个问题?速度不是很重要,但我更喜欢快速的解决方案。

这是一个用于更好地理解我的问题的程序的伪代码示例:

class Vertex {
 var point;
 var index;
 init(x,y,index){
   point = (x,y)
   self.index = index
 }
}

class Edge {
 var from; // of type Vertex
 var to; // of type Vertex
 init(from, to){
  self.from = from
  self.to = to
 }
}

对函数 getMonotonePiecesOfPolygon(polygon) 的调用可以生成具有这些顶点和边的许多单调多边形片段之一:

var vertex0 = Vertex(x0,y0,0)
var vertex1 = Vertex(x1,y1,1)
var vertex2 = Vertex(x2,y2,2)
var vertex3 = Vertex(x3,y3,3)

var edge0 = Edge(vertex0, vertex1)
var edge1 = Edge(vertex1, vertex2)
var edge2 = Edge(vertex2, vertex3)
var edge3 = Edge(vertex3, vertex4)

这可能对应于这样的矩形:

         edge0
       0------1
       |      |
 edge3 |      | edge1
       |      |
       3------2 
         edge2

然后,我们可以在数组中提供这些边,并使用三角剖分方法“makeMonotonePolygonIntoTrianglePieces()”将多边形划分为三角形

var edgesArray = [edge0,edge1,edge2,edge3]  
var edgesArray = makePolygonIntoTrianglePieces(edgesArray)

现在edgesArray 可能如下所示:

edgesArray == [edge0,edge1,edge2,edge3,newEdge1]

在哪里

newEdge1.from == vertex0
newEdge1.to == vertex2

如果我们要绘制每条边,这将对应于这样的多边形:

         edge0
       0------1
       |\     |
 edge3 |  \   | edge1
       |    \ |
       3------2 
         edge2

现在这是我的问题要解决的部分问题。我需要一个如下所示的数组:

var triangles = [
                 vertex0,vertex3,vertex2, 
                 vertex0,vertex2,vertex1
                ]

或使用三角形带(每个三角形由一个新顶点和前一个三角形的两个顶点描述):

var triangles = [
                 vertex3, vertex2, vertex0,
                 vertex1
                ]  

【问题讨论】:

  • 我不明白你在哪里卡住了。你知道你添加了哪些边。通过构造,这些边中的每一个都恰好为两个三角形所共有。您寻找连接到该边的 both 端的一个或两个顶点。更好的是,在添加边时保留您构造的三角形的列表。然后,您可以根据需要对它们进行排序。如果你想要一个三角形带,那么从你的排序列表中删除多余的元素。
  • 也许我只是想累了,但我没有遵循你的意思,我正在“寻找连接到该边缘两端的一两个顶点”。添加每个构造的三角形的解决方案似乎可行,我明天会试试看:)谢谢
  • 好的,试试一个具体的例子。在您发布的正方形中,您添加了边 [0, 2]。你知道这个添加的边形成了两个三角形。因此,您寻找连接到 both 02 的顶点。这为您提供了您在数组中显示的两个三角形。如果您从任一孤立顶点开始——仅在一个三角形中(它将恰好有两条边——1 和 3 是那些孤立的顶点),你可以沿着三角形带“走”自己的路。
  • @Prune:我认为该算法不仅限于由 4 条边构成的多边形。一旦你有更多,我想它会有点复杂,因为你必须知道你可以连接所有“相邻”边中的哪一条边来获得一个位于多边形内部的三角形.当然,对于所有这些,您将构建一个三角形(尽管可能是退化的),但其中一些可能位于外部(想想一个形成星状形状的多边形)。顺便提一句。你甚至可以用 4 条边产生这样的情况。
  • OP 已经完成了生成边的算法。那么问题是如何产生最终的输出组织。您从一个孤立的顶点及其两条边开始,形成输出的第一个三角形。现在,为了使这更容易可视化;从图中删除该三角形。重复剩余的数字。在许多情况下(以及所有带有三角形带的情况),该三角形的一个或两个顶点将被隔离。

标签: algorithm graphics polygon computational-geometry mesh


【解决方案1】:

在您提到的其中一个 cmets 中的本书的第 2 章中,它们提出了一种称为双连接边列表 (DCEL) 的数据结构。 DCEL:s 用于存储平面细分,例如三角剖分。从您写的内容来看,我认为这可能是您正在寻找的内容。

https://en.wikipedia.org/wiki/Doubly_connected_edge_list

【讨论】:

  • 我已经实现了一个常规的双链表来存储我的边并表示多边形。当从算法中添加新边时,我不确定如何使用这样的数据结构来存储细分。在原始多边形中,每个顶点都有一个前一个顶点和一个在前的顶点。最终算法发现应该在两个顶点之间添加一条边,这将创建一个三角形。然而,这也意味着新边包含的顶点现在有 3 个包含它们的边。如何存储这个细分?
  • 好吧,我仍然认为 DCEL 是您应该考虑的。但是,如果您使用列表,则每个顶点 v 可以有一个节点,然后在每个节点中,有一个子列表,其中包含指向所有其他顶点 u 的指针,这样 v 和 u 之间就有一条边(请记住将边存储在v 和 u 的节点)。您可能还想存储子列表的指针,因为边是围绕顶点排序的,这当然取决于您最终喜欢对三角剖分做什么以及效率的重要性。
  • 啊,好吧,我只是不明白将边存储在常规双链表中和使用 DCEL 有什么区别?
  • DCEL 包含更多信息,例如,存在哪些面孔以及它们彼此相邻的位置。三角剖分是一种有点简单的细分,因此可能不需要 DCEL,但无论如何,您需要在细分的各个部分(顶点、边和面)之间维护指针链,而这正是 DCEL 所保留的由组成。表示数据的方式取决于您喜欢如何使用它。
  • 我建议的替代方案,在列表中使用列表,可能在大多数小规模情况下都可以正常工作。请注意并保持顺序,例如顶点周围边缘的角度顺序。例如,使用列表应该很容易添加一条新边(= 顶点之间的指针,边界存储在顶点的子列表中的边),尽管不一定非常有效。
猜你喜欢
  • 2013-07-21
  • 1970-01-01
  • 2011-04-01
  • 2017-04-09
  • 2010-10-15
  • 2011-11-11
  • 1970-01-01
  • 2014-11-02
  • 2013-12-16
相关资源
最近更新 更多