Delaunay三角剖分算法

一、相关定义

【定义】三角剖分:假设V是二维实数域上的有限点集,边e是由点集中的点作为端点构成的封闭线段, E为e的集合。那么该点集V的一个三角剖分T=(V,E)是一个平面图G,该平面图满足条件: 1.除了端点,平面图中的边不包含点集中的任何点。 2.没有相交边。 3.平面图中所有的面都是三角面,且所有三角面的合集是散点集V的凸包。 在实际中运用的最多的三角剖分是Delaunay三角剖分,它是一种特殊的三角剖分。先从Delaunay边说起: 【定义】Delaunay边:假设E中的一条边e(两个端点为a,b),e若满足下列条件,则称之为Delaunay边:存在一个圆经过a,b两点,圆内(注意是圆内,圆上最多三点共圆)不含点集V中任何其他的点,这一特性又称空圆特性。 【定义】Delaunay三角剖分:如果点集V的一个三角剖分T只包含Delaunay边,那么该三角剖分称为Delaunay三角剖分。
【定义】假设T为V的任一三角剖分,则T是V的一个Delaunay三角剖分,当前仅当T中的每个三角形的外接圆的内部不包含V中任何的点。

二、逐点插入算法

input: 顶点列表(vertices)                       //vertices为外部生成的随机或乱序顶点列表
output:已确定的三角形列表(triangles)
    初始化顶点列表
    创建索引列表(indices = new Array(vertices.length))    //indices数组中的值为0,1,2,3,......,vertices.length-1
    基于vertices中的顶点x座标对indices进行sort           //sort后的indices值顺序为顶点座标x从小到大排序(也可对y座标,本例中针对x座标)
    确定超级三角形
    将超级三角形保存至未确定三角形列表(temp triangles)
    将超级三角形push到triangles列表
    遍历基于indices顺序的vertices中每一个点            //基于indices后,则顶点则是由x从小到大出现
      初始化边缓存数组(edge buffer)
      遍历temp triangles中的每一个三角形
        计算该三角形的圆心和半径
        如果该点在外接圆的右侧           则该三角形为Delaunay三角形,保存到triangles           并在temp里去除掉           跳过         如果该点在外接圆外(即也不是外接圆右侧)
          则该三角形为不确定               //后面会在问题中讨论
          跳过         如果该点在外接圆内           则该三角形不为Delaunay三角形           将三边保存至edge buffer           在temp中去除掉该三角形
      对edge buffer进行去重
      将edge buffer中的边与当前的点进行组合成若干三角形并保存至temp triangles中
    将triangles与temp triangles进行合并
    除去与超级三角形有关的三角形
end

用三点来做实例:

 《Delaunay三角剖分算法》

如图,随机的三个点

 

《Delaunay三角剖分算法》

根据离散点的最大分布来求得随机一个超级三角形(超级三角形意味着该三角形包含了点集中所有的点

我的方法是根据相似三角形定理求得与矩形一半的小矩形的对角三角形,扩大一倍后则扩大后的直角三角形斜边经过点(Xmax,Ymin)

但是为了将所有的点包含在超级三角形内,在右下角对该三角形的顶点进行了横和高的扩展,并要保证这个扩展三角形底大于高,才能实现包含

这样求得的超级三角形不会特别大使得计算复杂,而且过程也简单,并将超级三角形放入temp triangles中

《Delaunay三角剖分算法》

接下来就像是伪代码中描述的那样,对temp triangle中的的三角形遍历画外接圆,这时先对左边的第一个点进行判断,其在圆内

所以该三角形不为Delaunay三角形,将其三边保存至edge buffer中,temp triangle中删除该三角形

《Delaunay三角剖分算法》

将该点与edge buffer中的每一个边相连,组成三个三角形,加入到temp triangles中

《Delaunay三角剖分算法》

再将重复对temp triangles的遍历并画外接圆,这时使用的是第二个点来进行判断

  1. 该点在三角形1外接圆右侧,则表示左侧三角形为Delaunay三角形,将该三角形保存至triangles中
  2. 该点在三角形2外接圆外侧,为不确定三角形,所以跳过(后面会讲到为什么要跳过该三角形),但并不在temp triangles中删除
  3. 该点在三角形3外接圆内侧,则这时向清空后的edge buffer加入该三角形的三条边,并用该点写edge buffer中的三角边进行组合,组合成了三个三角形并加入到temp triangles中

《Delaunay三角剖分算法》

再次对temp triangles进行遍历,这里该数组里则含有四个三角形,一个是上次检查跳过的含有第一个点的三角形和新根据第二个点生成的三个三角形

  1. 该点在三角形1外接圆右侧,则该三角形为Delaunay三角形,保存至triangles中,并在temp triangles中删除
  2. 该点在三角形2外接圆外侧,跳过
  3. 该点在三角形3外接圆内侧,将该三边保存至temp buffer中,并在temp triangles中删除
  4. 该点在三角形4外接圆内侧,将该三边保存至temp buffer中,并在temp triangles中删除

这时,temp buffer 中有六条边,triangles中有两个三角形,temp triangles中有1个三角形

对temp buffer中的六条边进行去重,得到五条边,将该点与这五条边组合成五个三角形并加入到temp triagnles 中,这时temp triangles中有6个三角形

《Delaunay三角剖分算法》

由于三个点已经遍历结束,到了不会再对第三个点形成的三角形做外接圆,这时则将triangles与temp trianlges合并,合并后的数组表示包含已经确定的Delaunay三角形和剩下的三角形

这时除去合并后数组中的和超级三角形三个点有关的所有三角形,即进行数组座标的限定,则得到了最后的结果:

《Delaunay三角剖分算法》      这是用最少的三个点来做讲解,点数越多的话计算量会越大,但是都是在上面步骤下进行的。

点赞