三角剖分算法(delaunay)
开篇

在做一个Low Poly的课题,而这种低多边形的成像效果在现在设计中越来越被喜欢,其中的低多边形都是由三角形组成的。
而如何自动生成这些看起来很特殊的三角形,就是本章要讨论的内容。
项目地址: https://github.com/zhiyishou/polyer
Demo:https://zhiyishou.github.io/Polyer
选择
其是最先是由很多离散的点组成,基于这个确定的点集,将点集连接成一定大小的三角形,且分配要相对合理,才能呈现出漂亮的三角化。
这时则要求使用三角剖分算法(Delaunay),引于百度百科《Delaunay三角剖分算法》对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中任何的点。
算法
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
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
其方法虽然可实现三角化,但是效率还是不太高
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
大多数同学看过伪代码后还是一头雾水,所以用图来解释这个过程,我们先用三点来做实例:

如图,随机的三个点
根据离散点的最大分布来求得随机一个超级三角形(超级三角形意味着该三角形包含了点集中所有的点)
我的方法是根据相似三角形定理求得与矩形一半的小矩形的对角三角形,扩大一倍后则扩大后的直角三角形斜边经过点(Xmax,Ymin)
但是为了将所有的点包含在超级三角形内,在右下角对该三角形的顶点进行了横和高的扩展,并要保证这个扩展三角形底大于高,才能实现包含
这样求得的超级三角形不会特别大使得计算复杂,而且过程也简单,并将超级三角形放入temp triangles中

接下来就像是伪代码中描述的那样,对temp triangle中的的三角形遍历画外接圆,这时先对左边的第一个点进行判断,其在圆内
所以该三角形不为Delaunay三角形,将其三边保存至edge buffer中,temp triangle中删除该三角形

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

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

再次对temp triangles进行遍历,这里该数组里则含有四个三角形,一个是上次检查跳过的含有第一个点的三角形和新根据第二个点生成的三个三角形
- 该点在三角形1外接圆右侧,则该三角形为Delaunay三角形,保存至triangles中,并在temp triangles中删除
- 该点在三角形2外接圆外侧,跳过
- 该点在三角形3外接圆内侧,将该三边保存至temp buffer中,并在temp triangles中删除
- 该点在三角形4外接圆内侧,将该三边保存至temp buffer中,并在temp triangles中删除
这时,temp buffer 中有六条边,triangles中有两个三角形,temp triangles中有1个三角形
对temp buffer中的六条边进行去重,得到五条边,将该点与这五条边组合成五个三角形并加入到temp triagnles 中,这时temp triangles中有6个三角形

由于三个点已经遍历结束,到了不会再对第三个点形成的三角形做外接圆,这时则将triangles与temp trianlges合并,合并后的数组表示包含已经确定的Delaunay三角形和剩下的三角形
这时除去合并后数组中的和超级三角形三个点有关的所有三角形,即进行数组坐标的限定,则得到了最后的结果:
问题
在用点对三角形外接圆位置关系进行判断的时候,为什么点在外接圆的右侧的话可以确定该三角形是Delaunay三角形
而当点外接圆的外侧且非右侧时,为什么要路过三角形,不把该三角形确定为Delaunay三角形呢?
首先,我们在开始的时候对原始方法进行优化时,我们增加了一个indices数组来操作vertices,并对indices依据vertices的x坐标进行了从小到大的排序
则我们在后面遍历点时是从点集的最左侧开始的,如图:



三角剖分算法(delaunay)的更多相关文章
- Delaunay三角剖分算法
在图像处理中,经常会使用到三角剖分算法: 具体定义及其算法可以参考:http://baike.so.com/doc/5447649.html 下面放出来代码: Delaunay接口为存C: 测试是使用 ...
- paper 153:Delaunay三角剖分算法--get 这个小技术吧!
直接摘自百度百科,希望大家能根据下面的介绍稍微理顺思路,按需使用,加油! 解释一下:点集的三角剖分(Triangulation),对数值分析(比如有限元分析)以及图形学来说,都是极为重要的一项预处理技 ...
- c#之GDI简单实现代码及其实例
作业:文档形式 3到5页理解 1.理解 2.源代码解释(1到2页) 3.实现效果 项目地址: https://github.com/zhiyishou/polyer Demo:https://zhiy ...
- Delaunay三角剖分及MATLAB实例
https://blog.csdn.net/piaoxuezhong/article/details/68065170 一.原理部分 点集的三角剖分(Triangulation),对数值分析(如有限元 ...
- Delaunay Triangulation in OpenCascade
Delaunay Triangulation in OpenCascade eryar@163.com 摘要:本文简要介绍了Delaunay三角剖分的基础理论,并使用OpenCascade的三角剖分算 ...
- Triangle - Delaunay Triangulator
Triangle - Delaunay Triangulator eryar@163.com Abstract. Triangle is a 2D quality mesh generator an ...
- OpenCV——Delaunay三角 [转载]
从这个博客转载 http://blog.csdn.net/raby_gyl/article/details/17409717 请其它同学转载时注明原始文章的出处! Delaunay三角剖分是1934年 ...
- Delaunay和Voronoi
什么是Delaunay三角剖分? 图1:Delaunay三角剖分偏爱小角度 给定平面中的一组点,三角剖分指的是将平面细分为三角形,这些点为顶点.在图1中,我们在左侧图像上看到了一组地标,在中间图像上看 ...
- 通过CGAL将一个多边形剖分成Delaunay三角网
目录 1. 概述 2. 实现 3. 结果 4. 参考 1. 概述 对于平面上的点集,通过Delaunay三角剖分算法能够构建一个具有空圆特性和最大化最小角特性的三角网.空圆特性其实就是对于两个共边的三 ...
随机推荐
- PHP-数据库长连接mysql_pconnect的细节
PHP的MySQL持久化连接,美好的目标,却拥有糟糕的口碑,往往令人敬而远之.这到底是为啥么.近距离观察后发现,这家伙也不容易啊,要看Apache的脸色,还得听MySQL指挥. 对于作为Apache模 ...
- PHP-Windows下搭建Nginx+PHP环境
项目中光用Nginx了, 由于有运维人员, 很少搭建Nginx服务器, 开发也就用用Apache, 搭过几次Nginx也忘的快, 每次都去翻别人博客, 今天重搭特此记录, 装前最好了解下FastCGI ...
- 字符编解码的故事(ASCII,GBK,Unicode,Utf-8区别)
很久很久以前,有一群人,他们决定用8个可以开合的晶体管来组合成不同的状态,以表示世界上的万物.他们认为8个开关状态作为原子单位很好,于是他们把这称为"字节". 再后来,他们又做了一 ...
- Mybatis自动生成的配置实例
一.目录 按照图片准备下面的东西吧,基础jar,数据链接库的jar. 二.generatorConfig.xml <?xml version="1.0" encoding=& ...
- c#取得post和get的数据和模拟发送
可以放在控制器的入口函数中,这样载入就会被调用 asp.net mvc,get+post: public ActionResult Index() { ) { foreach (var item in ...
- atitit.手动配置列表文件的选择and 数据的层次结构 attilax总结最佳实践--yaml
atitit.手动配置列表文件的选择and 数据的层次结构 attilax总结最佳实践--yaml 1. yaml是个好的选择.. 1 2. 数据的层次结构--结构:hash,list,和block ...
- 【C语言】19-static和extern关键字1-对函数的作用
一.extern与函数 在前面我提到过一句话:如果一个程序中有多个源文件(.c),编译成功会生成对应的多个目标文件(.obj),这些目标文件还不能单独运行,因为这些目标文件之间可能会有关联,比如a.o ...
- A+P+M+W
安装之前先做个目录的安排, D盘根目录建立”Dev”文件夹,在文件夹下建立: Php Apache Mysql 三个文件夹 所需软件: 0. 安装Apache的前必须安装VC11 vcredis ...
- 新建一个用户,让他只能看到某一个视图(View),如何设置
新建一个用户,让他只能看到某一个视图(View),怎么设置? 新建一个用户,让他只能看到某一个视图(View),怎么设置? 如果做不到“只能看到指定视图”,最好能做到“对指定表或视图只有查询的权限”. ...
- TIM—基本定时器
本章参考资料:< STM32F4xx 参考手册>.< STM32F4xx 规格书>.库帮助文档< stm32f4xx_dsp_stdperiph_lib_um.chm&g ...
