Delaunay三角剖分学习笔记

  最近计算几何课程要求交一个结课论文,借这个机会,我就认真地学习了下Delaunay三角剖分。
  Delaunay三角剖分其实并不是一种算法,它只是给出了一个“好的”三角网格的定义,它的优秀特性是空圆特性和最大化最小角特性,这两个特性避免了狭长三角形的产生,也使得Delaunay三角剖分应用广泛。
  空圆特性其实就是对于两个共边的三角形,任意一个三角形的外接圆中都不能包含有另一个三角形的顶点,这种形式的剖分产生的最小角最大。


不满足空圆特性

  假如以AC来剖分四边形ABCD,这里B点在三角形ACD的外接圆内,D点在三角形ABC的外接圆内,所以不具有空圆特性


满足空圆特性

  以BD来剖分四边形ABCD,C点不在三角形ABD的外接圆内,A点也不在三角形BCD的外接圆内,具有空圆特性,而且它的最小角要比不满足空圆特性的最小角大。

问题描述

  现在给定了平面上的一个点集V,求出它的Delaunay三角剖分


点集

Delaunay三角剖分

Bowyer逐点插入法

  Bowyer逐点插入法是一个很经典的实现方法,网上的资料大多数都是采用的这种算法。这里使用的算法是按照 Paul Bourke在论文中提供的伪代码实现的,这个伪代码也写的很好,非常容易懂

以下摘自他的论文

subroutine triangulate
input : vertex list   输入:顶点链表
output : triangle list  输出:三角形链表
initialize the triangle list  初始化三角形链表
determine the supertriangle  确定超级三角形
add supertriangle vertices to the end of the vertex list   将超级三角形的顶点加入到顶点链表中
add the supertriangle to the triangle list  将超级三角形加入到三角形链表中
for each sample point in the vertex list  对顶点链表中的每一个点
initialize the edge buffer  初始化边数组
for each triangle currently in the triangle list  对于三角形链表中的每一个三角形
calculate the triangle circumcircle center and radius  计算出外接圆圆心和半径
if the point lies in the triangle circumcircle then  如果这个点在三角形的外接圆内
add the three triangle edges to the edge buffer  把这个三角形的三条边加入到边数组中
remove the triangle from the triangle list  从三角形链表中将这个三角形删除
endif
endfor
delete all doubly specified edges from the edge buffer  把边数组中所有重复的边都删除,注意这里是把所有的重复边都删除,比如有边e1,e2,e2,e3,删除后应该只剩e1和e3
this leaves the edges of the enclosing polygon only  这步会得到一个闭合的多边形
add to the triangle list all triangles formed between the point 用这个点和边数组中的每一条边都组合成一个三角形,加入到三角形链表中
and the edges of the enclosing polygon
endfor
remove any triangles from the triangle list that use the supertriangle vertices从三角形链表中删除使用超级三角形顶点的三角形
remove the supertriangle vertices from the vertex list将超级三角形的顶点从顶点链表中删除
end

  在使用过程中,发现“把超级三角形的顶点加入到顶点链表中”似乎没什么必要,另外,顶点用数组存好一点,因为不需要添加和删除。

  以四个点A、B、C、D举例,首先建立一个超级三角形PQR,这个三角形要把所有点都包含进去。


建立超级三角形

  接着分析A点,因为A点在三角形PQR的外接圆内部,所以利用A点将三角形PQR分拆成三个子三角形。


A点

  再考虑B点,它只在三角形AQR的内部,再将三角形AQR分拆成三个子三角形。


B点

  接着是C点,这时我们有5个三角形,对这5个三角形每一个检查C点在不在它的外接圆内。经过检测,发现它在三角形APR和三角形ABR的外接圆内。


C点

  删除三角形APR和三角形ABR的公共边AR,得到四边形ABPR,并将C点与每一个边组成一个三角形。


删除公共边

  最后对D点进行分析,它在三角形ABC和三角形BCR的外接圆内,所以应删除公共边BC,再用D点与这两个三角形的其他边形成子三角形。


D点

删除公共边

  最后把含有超级三角形的顶点的三角形全部删除,就得到这四个点的三角剖分


删除超级三角形

  我编写程序的时候使用三个点进行测试,有时候结果出不来,是因为在最后一步删除超级三角形的时候是这样的

然后删除超级三角形相关顶点就把所有三角形都删掉了。刚开始的时候我以为是和超级三角形的选取有关,纸异兽的文章中也没有详细分析,只提供了一个生成超级三角形的方案。我很好奇这个超级三角形只要包含所有点就可以吗,后来发现当遇到只有三个点的情况就直接相连就可以了,四个点以后就不会出现这种情况。

  另外关于这个方法,我在Github上看到了一个实现,作者是jeanbroid,用openGL做显示,里面用了很多C++标准库的东西,让我大开眼界,非常感谢他,不过他用到了双缓存,需要把demo.cpp中的GLUT_SINGLE改成GLUT_DOUBLE才能运行。

分治法

  分治法是我在查看维基百科的时候看到的,据维基百科说分治法是效率最高的一种方法。在维基百科的引用中发现了一个介绍delaunay三角剖分的分治法的一个非常好的网站,网站作者是Samuel Peterson,这个网站主要介绍了在给定条件下的Delaunay三角剖分。

  分治法进行三角剖分需要对点集中所有点按照x坐标的升序进行排序,x坐标相同时,按照y坐标进行排序,接着将整个点集递归地划分数量相近的两个子集,直到子集中点的数目小于等于3。


点集的分割

  先给出一个定义方便后面叙述。对于一条边,如果它的两个端点都在分割线的左边,称它为LL边,一端在左边一端在右边称为LR边,两个端点都在右边称为RR边。

  分治法的重点在于如何递归地合并三角网格。
  首先是确定一条LR基线,这条线位于最下方,且不与其他边相交,如27边


确定基线

  接着,确定下一条LR边。以右侧三角网为例,按照顺时针方向,计算出∠672,∠872,∠1072,∠972的值,并根据角度大小对顶点进行排序,角度最小的点为第一候选点,以此类推,这里第一候选点为6,第二候选点为8。


候选点的选取

  作三角形276的外接圆,发现第二候选点8不在该外接圆内,且∠672小于180°,故右侧的候选点为6。候选点的要求是以候选点与该侧基线端点形成的角小于180°,且不包含下一候选点。若大于180°,则该侧无候选点,若包含下一候选点,则考虑下一候选点是否满足该条件。按照这种方法对左侧三角网格进行分析,可得到左侧候选点为点3。
LR边的选择

  当左右两侧都存在候选点时,如当前情况,这时需要考虑下一条LR边是37还是26。作三角形237的外接圆,可发现右侧候选点6在此外接圆外,而左侧候选点在三角形276外接圆内,故下一条LR边为边37。

  当只有一侧存在候选点时,将此候选点与基线另一侧的端点连线作为下一条LR边。

  将边37作为下一条基线重复该过程,直到两边都不存在候选点,程序结束。

附一张Bowyer算法最后的显示效果


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335

推荐阅读更多精彩内容

  • 我亦举家清 爱见澄清晨 黄金答母恩 玮勤玮名姓 玮别五秋萤
    黑色玫瑰d阅读 437评论 3 7
  • 2018班车已经到站,这一年收获满满,登山、跑马、写字、绘画、读书,当然也有失落、气愤、伤心难过。 现在重整行装迈...
    凌玉_cc23阅读 234评论 0 1
  • ❤如何拥有人脉 人脉=诚实+终身成长+对家人朋友好 ❤人脉是你赢得的,不是你要来的 不要去追一匹马,用追马的时间种...
    孤独中的喧嚣阅读 187评论 0 0
  • 一 那年夏天雨水特别多,6月只有四天没下雨,我掩好宿舍门,带走了一台电脑、一皮箱书还有一编织袋的衣物,胡乱又仓促地...
    李布波阅读 448评论 5 6
  • 湖正中,飘着一叶扁舟,在这一叶扁舟之上,仰面朝天躺着一个头发略微有些卷曲的男人,男人的一只手搭在船舷外,小拇指和无...
    13号的小猫阅读 426评论 0 2