DELAUNAY三角网的算法
- 格式:ppt
- 大小:1.46 MB
- 文档页数:10
Delaunay 三角网是Voronoi(或称thiessen多边形,V 图)图的伴生图形◆Delaunay 三角网的定义:由一系列相连的但不重叠的三角形的集合, 而且这些三角形的外接圆不包含这个面域的其他任何点。
◆Voronoi图的定义:Voronoi图把平面分成N 个区,每一个区包括一个点,该点所在的区域是距离该点最近的点的集合。
◆Delaunay三角网的特性:◆不存在四点共圆;◆每个三角形对应于一个Voronoi图顶点;◆每个三角形边对应于一个Voronoi图边;◆每个结点对应于一个Voronoi图区域;◆Delaunay图的边界是一个凸壳;◆三角网中三角形的最小角最大。
空外接圆准则最大最小角准则最短距离和准则在TIN中,过每个三角形的外接圆均不包含点集的其余任何点在TIN中的两相邻三角形形成的凸四边形中,这两三角形中的最小内角一定大于交换凸四边形对角线后所形成的两三角形的最小内角一点到基边的两端的距离和为最小Delaunay三角剖分的重要的准则张角最大准则面积比准则对角线准则一点到基边的张角为最大三角形内切圆面积与三角形面积或三角形面积与周长平方之比最小两三角形组成的凸四边形的两条对角线之比。
这一准则的比值限定值,须给定,即当计算值超过限定值才进行优化Delaunay三角剖分的重要的准则不规则三角网(TIN)的建立●三角网生长算法就是从一个“源”开始,逐步形成覆盖整个数据区域的三角网。
●从生长过程角度,三角网生长算法分为收缩生长算法和扩张生长算法两类。
方法说明方法实例收缩生长算法先形成整个数据域的数据边界(凸壳),并以此作为源头,逐步缩小以形成整个三角网分割合并算法逐点插入算法扩张生长算法从一个三角形开始向外层层扩展,形成覆盖整个区域的三角网递归生长算法逐点插入算法分割合并算法12121212递归生长算法333TIN 建立过程中的几个问题:◆邵春丽.DELAUNAY 三角网的算法详述及其应用发展前景◆鲍蕊娜,等:基于凸壳技术的Delaunay 三角网生成算法研究◆于杰等:Delaunay 三角网构建方法比较研究周围点的提取 点在三角形中的查找 空外接圆判断准则 线段求交问题。
基于三角网生长法的Delaunay三角网生成算法***************【摘要】论文简要介绍了Delaunay三角网的性质以及基本生成算法,并重点介绍了三角网生长法的基本原理和算法步骤,并通过设计合理的数据结构,对算法进行实现。
对算法进行分析并提出通过构建格网索引,进一步提高三角网生成效率。
【关键词】三角网生长法扩展TIN 格网索引1.引言数字地形模型DTM(Digital Terrain Model)是指对地形表面形态属性信息的数字表达,是带有空间位置特征和地形属性特征的数字描述[1]。
DTM是GIS的基础数据来源,可用于土地利用现状的分析、合理规划及洪水险情预报等。
DTM地形属性为高程时称为数字高程模型(DEM)。
DEM主要的三种表示模型为规则格网模型、等高线模型、不规则三角网模型(Triangular Irregular Network 简称TIN)。
数字化等高线模型不适合计算坡度或制作地貌渲染图等地形分析,规则格网数据结构简单,计算方便;但存在数据冗余,数据采集较麻烦,难以表达复杂地形等缺陷。
TIN即能够避免平坦地形时数据冗余,也能表达复杂地形,可以根据任意地形特征点表示DEM,因此被广泛应用。
Delaunay三角剖分能最大程度的接近等边三角形,避免狭长三角形,并且能保持三角网的唯一性,使其成为生成TIN的最佳选择。
本论文将简要介绍和比较几种常用的Delaunay三角网生成算法(逐点插入法,三角网生长法,分割合并算法等),并且对三角网生长法算法原理进行研究分析和程序实现。
2.Delaunay三角网的性质Delaunay三角网中的三角形必须满足以下几个性质:(1)空圆特性每一个Delaunay三角形的外接圆不包括Delaunay三角网中的任何其他点。
(2)最大最小角特性在三角剖分中,Delaunay三角网的所有三角形的最小角之和最大。
即使得Delaunay三角形最大程度接近等边三角形。
浅谈Delaunay 三角网的并行构建和更新随着测量技术的发展和新型测量设备的出现,空间数据的获取变得更加容易和快捷,与此同时,数据量也呈爆炸性的增长。
如何利用这些海量的空间数据实现数字地面模型DTM 的高效构建是当前空间分析及应用领域亟需解决的问题之一。
Delaunay 三角网以其唯一性、空圆性、能以不同分辨率表达地形、适合各种分布的数据等诸多优点而被广泛地应用于DTM 建模中。
长久以来,国内外学者对Delaunay 三角网的构建提出了多种算法。
这些算法按实现过程大致可以分为三类:逐点插入法、分治法和扫描线法。
陈楚江等提出了实现三角网局部更新的方法。
陈少勤等提出利用多源数据实现不规则三角网的动态更新。
但这些算法都是基于串行程序实现,不支持点并行的插入和删除。
随着多核计算机的普及,并行为解决大数据量的不规则三角网(TIN)构建和更新提供了新的思路。
不少学者也对此做了研究,李坚等提出将分治算法与流数据处理方法相结合,利用多核处理器平台进行并行运算。
张真[7]提出一种适用于并行计算的归并构网方法。
这些算法满足于Delaunay 三角网的并行构建,但不适用于三角网的并行动态更新。
因为在这些算法在开始之前,点集必须是确定的,而三角网更新时,被插入(删除)点是不确定的。
文章提出一种单机多核环境下Delaunay 三角网并行构建算法,该算法将数据进行格网划分,每一个数据块作为一个工作单元。
同时为解决内存共享带来的问题,可以为各工作单元分配独立的内存空间,工作单元之间相对独立,因此可以很好的实现三角网的并行构建和更新。
并行算法采用数据分块[8]的思想,首先将点数据按给定阈值(实验中发现阈值选择受实验环境影响)进行格网划分,每一个数据块形成一个独立的工作单元。
每一个工作单元只负责所属区域内三角网的构建更新。
利用计算机单机多核的优势,可以同时将多个工作单元分配给计算机进行处理。
最后将相邻的区域进行合并,最终完成三角网的构建。
约束条件下不规则delaunay三角网构建方法
不规则Delaunay三角网构建是一种在约束条件下构建三角网的方法,它可以有效地构建出满足约束条件的三角网。
首先,需要确定约束条件,即确定三角网中的节点和边的位置。
然后,根据约束条件,使用Delaunay三角剖分算法构建三角网。
Delaunay三角剖分算法是一种基于三角形的空间划分算法,它可以将空间划分为一系列的三角形,使得每个三角形的外接圆内没有其他节点。
这样,就可以构建出满足约束条件的三角网。
最后,需要对构建的三角网进行优化,以满足约束条件。
优化的方法有很多,比如调整节点位置、添加新的节点、删除多余的节点等。
这些优化操作可以使得构建的三角网更加符合约束条件,从而提高三角网的质量。
总之,不规则Delaunay三角网构建是一种在约束条件下构建三角网的有效方法,它可以有效地构建出满足约束条件的三角网,并且可以通过优化操作来提高三角网的质量。
2D-Delaunay三角网格的数据结构与遍历高晓沨1,黄懿2(1.清华大学数学系,北京 100080;南开大学数学科学学院,天津 300071) 摘要:本文总结了二维Delaunay三角网格的Bowyer-Watson自动生成算法及其实现步骤,提出了一种类的结构、函数范例(采用Visual C++ 6.0编写程序),并讨论了遍历三角网格各种方法的优劣性,给出实验数据对比;最后得出结论,用广度优先的遍历方法创建网格是生成三角网格一种相对便利有效率的方法;另外,讨论了初始点加入顺序对程序运行时间的影响。
关键词:Delaunay三角网格 类结构 自动生成 广度优先遍历Data Structure and Traverse of 2D-Delaunay TriangulationGao Xiaofeng1, Huang Yi2(Department of Mathematics ,Tsinghua University; Beijing,100080College of Mathematics, Nankai University, Tianjin, 300071) Abstruct: The article summarized the realization of 2D-Delaunay triangulation, thesteps of creating Bowyer-Watson automatic mesh generator, and then constructed a kindof Class structure as well as functions of this algorithm (using Visual C++ 6.0), andfinally discussed the advantage and disadvantage of different methods to traverse thetriangle mesh, using data examination as contrast. Lastly, the author got theconclusion that Width First Traversal method is more effective and convenient. Besides,we discussed the effect between the order of original point set and running time ofthe program.Key Word: Delaunay Triangulation, Class Structure,automatic generation, Width FirstTraversal1.引言近年来,平面任意点集的三角网格化(triangulation)问题一直是人们密切关注的问题。
Delauney三角网剖分算法原理:分为三步:一、凸包生成:1)求出如下四点:min(x-y)、min(x+y)、max(x-y)、max(x+y)并顺次放入一个数组,组成初始凸包;2)对于凸包上的点I,设它的后续点为J,计算矢量线段IJ右侧的所有点到IJ的距离,求出距离最大的点K;3)将K插入I,J之间,并将K赋给J;4)重复2,3步,直到点集中没有在IJ右侧的点为止;5)将J赋给I,J取其后续点,重复2,3,4步,当遍历了一次凸包后,凸包生成完成。
二、环切边界法凸包三角剖分:在凸包数组中,每次寻找一个由相邻两条凸包边组成的三角形,在该三角形的内部和边界上都不包含凸包上的任何其他点,然后去掉该点得到新的凸包链表,重复这个过程,最终对凸包数组中的点进行三角剖分成功。
三、离散的内插:1)建立三角形的外接圆,找出外接圆包含待插入点的所有三角形,构成插入区域;2)删除插入区域内的三角形公共边,形成由影响三角形顶点构成的多边形;3)将插入点与多边形所有顶点相连,构成新的Delaunay三角形;4)重复1,2,3,直到所有非凸包上的离散点都插入完为止。
功能实现流程:1. 在绘图菜单栏下添加一个子菜单项为Delauney,并且在工具栏上添加一个工具项。
设置text为Delaunay三角剖分,name为delaunay等属性,添加单击事件,并为单击事件代码2.为事件函数添加如下代码Graphics gra = panel1.CreateGraphics();List<Point_T> pts = new List<Point_T>();foreach (Geometry_T geo in choosegeos.Geofeatures){if (geo.GetType() == typeof(Point_T)){Point_T pt = (Point_T)geo;pts.Add(pt);}}List<Tin> deltins = DelauneyTin(pts);//根据多点构建delauney三角网foreach (Tin tin in deltins){Point[] ctin = new Point[3];for (int i = 0; i < 3; i++){cp = new Point((int)tin.Pthree[i].X, (int)tin.Pthree[i].Y); ctin[i] = cp;}gra.DrawPolygon(Pens.Red, ctin);}3.三角形TIN的数据结构public class Tin{Point_T[] pthree = new Point_T[3];Line_T[] lthree = new Line_T[3];public Line_T[] Lthree{get { return lthree; }set { lthree = value; }}public Point_T[] Pthree{get { return pthree; }set { pthree = value; }}public Tin(){ }public Tin(Point_T p1, Point_T p2, Point_T p3){pthree[0] = p1;pthree[1] = p2;pthree[2] = p3;lthree[0] = new Line_T(p1, p2);lthree[1] = new Line_T(p2, p3);lthree[2] = new Line_T(p3, p1);}}4.圆的数据结构public class Circle_T:Geometry_T{private Point_T cpt;public Point_T Cpt{get { return cpt; }set { cpt = value; }}double radius;public double Radius{get { return radius; }set { radius = value; }}public Circle_T(){ }public Circle_T(Point_T pt, double r){cpt = pt;radius = r;}}5.实现Delaunay三角剖分算法1)public List<Tin> DelauneyTin(List<Point_T> pts)//根据多点构建delauney三角网;分三步:构建凸包;凸包剖分;离散点内插{Graphics gra = panel1.CreateGraphics();List<Tin> deltins = new List<Tin>();List<Point_T> envpts = EnvelopeTin(pts);//构建凸包//for (int i = 0; i < envpts.Count - 1; i++)//{// gra.DrawLine(Pens.Black, new Point((int)envpts[i].X,(int)envpts[i].Y), new Point((int)envpts[i + 1].X, (int)envpts[i + 1].Y));//}//gra.DrawLine(Pens.Black, new Point((int)envpts[0].X, (int)envpts[0].Y), new Point((int)envpts[envpts.Count - 1].X, (int)envpts[envpts.Count - 1].Y));List<Point_T> dispts = new List<Point_T>();//非凸包上的离散点foreach (Point_T pt in pts){if (!envpts.Contains(pt)){dispts.Add(pt);}}List<Tin> envtins = EnvelopeDivision(envpts);//凸包剖分//foreach (Tin tin in envtins)//{// Point[] ctin = new Point[3];// for (int i = 0; i < 3; i++)// {// cp = new Point((int)tin.Pthree[i].X, (int)tin.Pthree[i].Y);// ctin[i] = cp;// }// gra.DrawPolygon(Pens.Blue, ctin);//}deltins = TinInsert(envtins, dispts);//离散点内插return deltins;}2)public List<Point_T> EnvelopeTin(List<Point_T> pts)//构建凸包{List<Point_T> envpts = new List<Point_T>();List<Point_T> othpts = new List<Point_T>();foreach (Point_T pt in pts){othpts.Add(pt);}//构建以x-y,x+y最大最小值组成的初始矩形框CompareXaddY comxandy = new CompareXaddY();CompareXsubY comxsuby = new CompareXsubY();pts.Sort(comxsuby);envpts.Add(pts[0]);envpts.Add(pts[pts.Count - 1]);othpts.Remove(pts[0]);othpts.Remove(pts[pts.Count-1]);pts.Sort(comxandy);if(!envpts.Contains(pts[0])){envpts.Insert(1, pts[0]);}if (!envpts.Contains(pts[pts.Count - 1])){envpts.Add(pts[pts.Count - 1]);}othpts.Remove(pts[0]);othpts.Remove(pts[pts.Count-1]);//构建以x-y,x+y最大最小值组成的初始矩形框int i = 0;int tag = 0;bool over = true;while(i<envpts.Count){Line_T cline;if (i==envpts.Count-1){cline = new Line_T(envpts[i], envpts[0]);}else{cline = new Line_T(envpts[i], envpts[i + 1]);}double dismax=0;for (int j = 0; j < othpts.Count ;j++ ){if (IsLeftPoint(othpts[j], cline)){double distance = PointToLine(othpts[j], cline);if (distance > dismax){dismax = distance;tag = j;over = false;}}}if (over){i++;}else{//envpts.RemoveAt(i);envpts.Insert(i+1, othpts[tag]);over = true;}}return envpts;}public List<Tin> EnvelopeDivision(List<Point_T> pts)//凸包剖分{List<Tin> envtins = new List<Tin>();List<Point_T> cpts = new List<Point_T>();foreach (Point_T pt in pts){cpts.Add(pt);}while (cpts.Count > 2){int tag = 0;double minangle = 120;for (int i = 0; i < cpts.Count; i++){double angle;if (i == 0){angle = CalcuAngle(cpts[cpts.Count - 1], cpts[i], cpts[i + 1]);}else if (i == cpts.Count - 1){angle = CalcuAngle(cpts[i-1], cpts[i], cpts[0]);}else{angle = CalcuAngle(cpts[i-1], cpts[i], cpts[i + 1]);}if ((angle - 60) < minangle){minangle = angle - 60;tag = i;}}int btag=tag-1;int atag=tag+1;if (tag == 0){btag = cpts.Count - 1;}else if (tag == cpts.Count - 1){atag = 0;}Tin ctin = new Tin(cpts[btag], cpts[tag], cpts[atag]);envtins.Add(ctin);cpts.RemoveAt(tag);}return envtins;}public List<Tin> TinInsert(List<Tin> tins, List<Point_T> pts)//离散点内插 {List<Tin> deltins = new List<Tin>();List<Tin> ctins = new List<Tin>();//临时凸包foreach (Tin tin in tins){ctins.Add(tin);}foreach (Point_T pt in pts)//对离散点遍历,内插{List<Point_T> cpts = new List<Point_T>();//临时点集foreach (Tin tin in ctins)//找到外接圆包含离散点的三角形{Circle_T ccir = DelauneyCicle(tin);//构造外接圆if (IsPointInCircle(pt, ccir))//点是否包含在圆内{//for (int i = 0; i < 3; i++)//{// if (!cpts.Contains(tin.Pthree[i]))// {// cpts.Add(tin.Pthree[i]);//记录当前点// }//}deltins.Add(tin); //记录保存当前三角形}}//List<Point_T> ecpts = EnvelopeTin(cpts);//求点集(外接圆包含离散的三角形)的凸包?,接下来,插入点,构建新三角网//for (int j = 0; j < ecpts.Count;j++ )//{// Tin tin;// if (j == ecpts.Count-1)// {// tin = new Tin(ecpts[j], ecpts[0], pt);// }// else// {// tin=new Tin(ecpts[j],ecpts[j+1],pt);// }// ctins.Add(tin);//}List<Line_T> eli = BorderTin(deltins);foreach (Line_T line in eli){Tin tin = new Tin(line.Frompt, line.Topt, pt);ctins.Add(tin);}foreach (Tin tin in deltins)//改变临时三角网(删除deltins保存的三角网){ctins.Remove(tin);}deltins.Clear();}return ctins;}3)public bool IsLeftPoint(Point_T pt, Line_T line)//点在线的左边;叉积大于{bool yes = false;if ((pt.X - line.Frompt.X) * line.ParaA + (pt.Y - line.Frompt.Y) * line.ParaB > 0){yes = true;}return yes;}public double CalcuAngle(Point_T fp, Point_T mp, Point_T tp)//首,中,尾三点构成的夹角{double angle = 0;Point_T vector1 = new Point_T(fp.X - mp.X, fp.Y - mp.Y);Point_T vector2 = new Point_T(tp.X - mp.X, tp.Y - mp.Y);angle = Math.Acos((vector1.X * vector2.X + vector1.Y * vector2.Y) /(Math.Sqrt(vector1.X * vector1.X + vector1.Y * vector1.Y) *Math.Sqrt(vector2.X * vector2.X + vector2.Y * vector2.Y)));return angle;}public Circle_T DelauneyCicle(Tin tin)//构建三角形的外接圆{double x1 = tin.Pthree[0].X;double x2 = tin.Pthree[1].X;double x3 = tin.Pthree[2].X;double y1 = tin.Pthree[0].Y;double y2 = tin.Pthree[1].Y;double y3 = tin.Pthree[2].Y;double x = ((y2 - y1) * (y3 * y3 - y1 * y1 + x3 * x3 - x1 * x1) - (y3 - y1) * (y2 * y2 - y1 * y1 + x2 * x2 - x1 * x1))/ (2 * (x3 - x1) * (y2 - y1) - 2 * ((x2 - x1) * (y3 - y1)));double y = ((x2 - x1) * (x3 * x3 - x1 * x1 + y3 * y3 - y1 * y1) - (x3 - x1) * (x2 * x2 - x1 * x1 + y2 * y2 - y1 * y1))/ (2 * (y3 - y1) * (x2 - x1) - 2 * ((y2 - y1) * (x3 - x1)));Point_T cpt = new Point_T(x, y);double radius=Math.Sqrt(Math.Pow((x1-x),2)+Math.Pow((y1-y),2));Circle_T cir = new Circle_T(cpt,radius);return cir;}public bool IsPointInCircle(Point_T pt, Circle_T cir){if(Math.Sqrt(Math.Pow((pt.X-cir.Cpt.X),2)+Math.Pow((pt.Y-cir.Cpt.Y),2))<cir.Radius) {return true;}elsereturn false;}public List<Line_T> BorderTin(List<Tin> tins){List<Line_T> borli = new List<Line_T>();for (int i = 0; i < tins.Count; i++){for (int t = 0; t < 3; t++){bool tag = false;Line_T cl = tins[i].Lthree[t];for (int j = 0; j < tins.Count; j++){if (j!=i&&IsContainByTin(cl, tins[j])){tag = true;}}if (!tag)borli.Add(cl);}}return borli;}public bool IsContainByTin(Line_T li, Tin tin){for (int i = 0; i < 3; i++){if ((li.Frompt == tin.Lthree[i].Frompt || li.Frompt ==tin.Lthree[i].Topt) && (li.Topt == tin.Lthree[i].Topt || li.Topt ==tin.Lthree[i].Frompt)){return true;}}return false;}6.实现两个排序类CompareXsubY(x-y排序)和CompareXaddY(x+y 排序),仿照CompareX写功能操作步骤:先在面板上绘制多个点;框选部分点;按下实现Delaunay三角网剖分工具,Delaunay三角网剖分成功。