当前位置:首页 > 代码 > 正文

delaunay三角剖分算法c代码(delaunay 三角剖分)

admin 发布:2022-12-19 19:32 209


今天给各位分享delaunay三角剖分算法c代码的知识,其中也会对delaunay 三角剖分进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

本文目录一览:

区域的Delaunay三角剖分

从上文中介绍的对点集的Delaunay三角剖分方法可以知道,点集的Delaunay的三角剖分方法是最简单、最基础的,所以,可以考虑在点集的Delaunay三角剖分方法的基础上获得区域的Delaunay三角剖分,实际上,区域的Delaunay三角剖分方法正是这样做的。

为了利用点集的Delaunay三角剖分方法,首先应该将剖分对象从区域转换到点集,而为了实现上述目的,需要经过两个过程:布点、离散边界。布点即是向区域内插入一些合适的点,离散边界即是将区域边界分割成若干小线段。在进行上述处理后,就将需要剖分的对象从一个区域转变成一个点集,点集中的点为向区域内插入的点和边界离散后形成小线段的端点;然后采用点集的Delaunay三角剖分方法,如Lawson算法或Bowyer-Wat-son算法,对从区域转换过来的点集进行Delaunay三角剖分操作;最后需要删除那些在区域之外的三角形,因为对一个点集进行Delaunay三角剖分操作,最后获得的三角剖分的范围是该点集的凸壳,而点集的凸壳绝大多数情况下与需要剖分的区域不一致,通常情况下是凸壳的范围大于需要剖分的区域,因此那些属于凸壳但不属于需要剖分的区域的三角形需要删除。

区域的Delaunay三角剖分方法可以概括为3个步骤:

第一步:布点并离散边界,将剖分对象从区域转换为点集。根据剖分规模或想要得到的三角形单元的大概边长,向区域内插入一系列的内部点,并将内外边界离散成一系列的小线段。图3.14(a)为某剖分区域,图3.14(b)为向区域内布点的结果,图3.14(c)则时在布点之后进行离散边界的结果。

图3.14 二维区域布点与边界离散

第二步:对点集进行Delaunay三角剖分操作。将离散后的内外边界的端点和根据需要布设的内部点组成输入点集,采用逐点插入法(Lawson算法或Bowyer-Watson算法)将上述点集进行Delaunay三角剖分,详细步骤请参见本章中点集的Delauany三角剖分方法,最后点集的Delaunay三角剖分如图3.15所示。剖分区域之外的三角形只能是由同一条边界上线段的端点组成,不可能由内部点或不同边界(如2个顶点位于外边界,1个顶点位于内边界)上端点组成区域之外的三角形,所以,判断一个三角形是否多余,首先判断该三角形的3个点是否位于同一条边界,若是,该三角形有可能为多余三角形,但不一定,如图3.16中由点9、10和11组成的三角形位于区域内部,但由点21、22和23组成的三角形却在区域外;因此,三角形的3个顶点位于同一条边界上只是必要条件,还需要进一步判断。

图3.15 点集的Delaunay三角剖分(未进行边界处理)

第三步:边界处理。根据区域边界,删除多余的三角形,得到区域的Delaunay三角剖分。

完整的边界处理方法如下:

(1)将区域的每条边界离散后按照固定顺序排列,边界上端点的ID也依次排列。需要特别注意的是,外边界必须按照逆时针排列,外边界上的端点编号也依次由小到大排列,如图3.16所示,从点0到点36依次排列;所有内边界离散后按照顺时针排列,同样,每条内边界上端点编号依次从小到大排列。

(2)依次判断点集的Delaunay三角剖分中每个三角形的三个顶点是否位于同一边界,若某个三角形的3个顶点位于同一边界上,将3个顶点由小到大排序,并按照排序后点号组成一个新的三角形,计算该新三角形的面积,若面积>0,则表示该三角形为区域内部三角形,保留;若面积<0,则表示该三角形为区域外三角形,删除。

图3.16 边界处理

图3.17 二维区域的Delaunay三角剖分

如由点0、1和36组成的三角形,排序后依次为0、1、36,新的三角形面积>0,表示该三角形为区域内部三角形,保留;由点21、22和23组成的三角形按照逆时针规则正常时排序为23、22、21,排序后依次为21、22、23,新的三角形面积<0,表示该三角形为区域外部三角形,删除。

边界处理后,得到最终的区域的Delaunay三角剖分,如图3.17所示。

布点和离散边界的代码详见推进波前法代码中的函数CreateInnerPoint()和Create-BoundaryPoint();点集的Delauany三角剖分方法的完整代码详见Bowyer-Watson算法的代码。以下为进行边界处理的代码,函数DeletedInvalidTriangle()用于删除剖分区域之外的三角形,函数AreaOfTrgl()用于计算三角形的面积。

三维地质建模方法及程序实现

三维地质建模方法及程序实现

谁对opencv里面的delaunay三角剖分方法比较熟悉的

具体什么不太懂,不过我收藏了一个以前别人讲这方面的东西,你看看,希望对你有帮助。

Delaunay三角网是俄国数学家B.Delaunay于1934年发现的。关于Delaunay三角网构建的研究有许多,但由于本课题具有数据量大的特征,不宜直接沿用已有构建方法,笔者针对本课题数据特征,研究获得了适应本课题,速度较快的构建方法。Delaunay三角网有一个特性,每个三角网形成的外接圆都不包含其他参考点。利用这一个性质,我们可以直接构成Delaunay三角网:

一、建立第一个三角形

1、判断用来建立TIN的总脚点数,小于3则报错退出。

2、第一点的选择:

链表的第一节点,命名为Pt1;

3、第二点的选择:

A.非Pt1点; B.距Pt1最近

命名为Pt2

4、第三点的选择

A.非Pt1,Pt2点;

B.与Pt1,Pt2点组成的三角形的外接圆内无其他节点;

C.与Pt1,Pt2组成的三角形中的角Pt1Pt3Pt2最大。

命名为Pt3

5、生成三边,加入边表

6、生成第一个三角形,组建三角形表

二、扩展TIN

1、从边表头取一边,要求:该边flag标志为假(只在一个三角形中)

2、从点链表中搜索一点,要求:

A、与边中的Pixel3在边的异侧;

B、该点与边组成的三角形的外接圆内无其他点

C、满足上面两条件的点中角Pt1Pt3Pt2最大的点为Pt3。

3、判断新生成的边,如果边表中没有,则加入边表尾,设定标志flag为假,如果有,则设定该边flag为真。

4、将生成的三角形假如三角形表

5、设定选中的边的标志flag为真

6、转至1,直至边表边的标志flag全部为真。

数据结构:

struct Pixel //脚点数据

{

double x,y,z,g;

bool flag;

};

struct List //数据链表

{

Pixel *pixel;

List *next;

};

struct Line //三角形边

{

Pixel *pixel1; //三角形边一端点

Pixel *pixel2; //三角形边另一端点

Pixel *pixel3; //三角形边所对顶点

bool flag;

};

struct Linelist //三角形边表

{

Line *line;

Linelist *next;

};

struct Triangle //三角形表

{

Line *line1;

Line *line2;

Line *line3;

Triangle *next;

};

以下是我程序中关于建网的部分:

// DelaunayTIN.cpp: implementation of the CDelaunayTIN class.

//

//////////////////////////////////////////////////////////////////////

#include "stdafx.h"

#include "Reconstruction.h"

#include "DelaunayTIN.h"

#include "MyMath.h"

#include math.h

#include "ListControl.h"

#ifdef _DEBUG

#undef THIS_FILE

static char THIS_FILE[]=__FILE__;

#define new DEBUG_NEW

#endif

//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////

CDelaunayTIN::CDelaunayTIN()

{

}

CDelaunayTIN::~CDelaunayTIN()

{

}

/////////////////////////////////////////////////////////////////////////////

//函数名: CreateDelaunayTIN

//编写者: Polaris

//参考资料:

//功能: 用给定的数据链表数据,组建Delaunay不规则三角网

//输入参数:数据链表list;区域范围(XMin,YMin),(XMax,YMax)

//输出参数:不规则三角网首三角形地址

//备注:

/////////////////////////////////////////////////////////////////////////////

struct Triangle * CDelaunayTIN::CreateDelaunayTIN(List *list)

{

//组建第一个三角形

CMyMath MyMath;

CListControl ListControl;

struct List *node;

struct Pixel *pt1,*pt2,*pt3;

bool flag;

struct Triangle *TIN;

pt1=list-pixel;

pt2=list-next-pixel;

node=list-next-next;

while(node!=NULL)

{

if(MyMath.Calculate2PtDistanceIn3D

(pt1-x,pt1-y,pt1-z,node-pixel-x,node-pixel-y,node-pixel-z)

MyMath.Calculate2PtDistanceIn3D

(pt1-x,pt1-y,pt1-z,pt2-x,pt2-y,pt2-z))

{

pt2=node-pixel;

}

node=node-next;

}

node=list-next;

pt3=NULL;

while(node!=NULL)

{

if(node-pixel==pt1 || node-pixel==pt2)

{

node=node-next;

continue;

}

if(pt3==NULL)

{

pt3=node-pixel;

}

else

{

if((pow(MyMath.Calculate2PtDistanceIn2D(pt1-x,pt1-y,node-pixel-x,node-pixel-y),2)+pow(MyMath.Calculate2PtDistanceIn2D(pt2-x,pt2-y,node-pixel-x,node-pixel-y),2)-pow(MyMath.Calculate2PtDistanceIn2D(pt1-x,pt1-y,pt2-x,pt2-y),2))/(2*MyMath.Calculate2PtDistanceIn2D(pt1-x,pt1-y,node-pixel-x,node-pixel-y)*MyMath.Calculate2PtDistanceIn2D(pt2-x,pt2-y,node-pixel-x,node-pixel-y))

(pow(MyMath.Calculate2PtDistanceIn2D(pt1-x,pt1-y,pt3-x,pt3-y),2)+pow(MyMath.Calculate2PtDistanceIn2D(pt2-x,pt2-y,pt3-x,pt3-y),2)-pow(MyMath.Calculate2PtDistanceIn2D(pt1-x,pt1-y,pt2-x,pt2-y),2))/(2*MyMath.Calculate2PtDistanceIn2D(pt1-x,pt1-y,pt3-x,pt3-y)*MyMath.Calculate2PtDistanceIn2D(pt2-x,pt2-y,pt3-x,pt3-y)))

{

pt3=node-pixel;

}

}

node=node-next;

}

//LineList

Linelist *linehead,*linenode,*linelast;

Line *ln1,*ln2,*ln3;

linenode=new Linelist;

linenode-line=new Line;

linenode-line-pixel1=pt1;

求一个用C++写的Delaunay三角剖分间接实现Voronoi图的代码。最好有算法说明谢谢!! 急用!!

#includeiostream

#includecmath

using namespace std;

#define N 30

typedef struct //定义点的结构体

{

int x,y;

}Point;

class point

{

private:

Point *v;

public:

int distance(Point i,Point j); //计算两点的距离

int w(Point i,Point j,Point k); //计算三条边的长度之和

void minWeightTriangulation(int n,int t[][N],int s[][N]); //用动态规划计算最优值

void print(int s[][N],int i,int j); //输出

};

int point::distance(Point i,Point j)

{

int s=(i.x-j.x)*(i.x-j.x)+(i.y-i.y)*(i.y-i.y);

return sqrt(s);

}

int point::w(Point i,Point j,Point k)

{

return distance(i,j)+distance(j,k)+distance(i,k);

}

void point::minWeightTriangulation(int n,int t[][N],int s[][N]) //用动态规划计算最优值

{

int i=0;

int r=0;

int k=0;

for(i=1;i=n;i++) t[i][i]=0;

for(r=2;r=n;r++)

for(i=1;i=n-r+1;i++)

{

int j=i+r-1;

t[i][j]=t[i+1][j]+w(v[i-1],v[i],v[j]);

s[i][j]=i;

for(k=i+1;kj;k++)

{

int u=t[i][k]+t[k+1][j]+w(v[i-1],v[k],v[j]);

if(ut[i][j])

{

t[i][j]=u;

s[i][j]=k;

}

}

}

}

void point::print(int s[][N],int i,int j)

{

if(i==j)

return;

print(s,i,s[i][j]);

print(s,s[i][j]+1,j);

cout"三角行:v"i-1"v"s[i][j]"v"jendl;

}

int main()

{

int n,i;

Point v[N]={0,0};

point triangle;

int t[N][N],s[N][N];

cout"输入多边形的顶点数:";

cinn;

for(i=0;in;i++)

{

cout"输入第"i+1"点的坐标:";

cinv[i].xv[i].y;

}

triangle.minWeightTriangulation(n,t,s);

triangle.print(s,1,n);

return 0;

}

点集的Delaunay三角剖分方法

3.2.1.1 基本理论

B.Delaunay于1934年提出了Delaunay三角网格的概念,它是Voronoi图(简称V图)的几何对偶图,具有严格的数学定义和完备的理论基础。

图3.1 Voronoi图(虚线)及对应的Delaunay三角剖分(实线)

3.2.1.1.1 Voronoi图

假设V={v1,v2,…,vN},N≥3是欧几里得平面上的一个点集,并且这些点不共线,四点不共圆。用d(vi,vj)表示点vi与vj间的欧几里得距离。

设x为平面上的点,则:

区域V(i)={x∈E2d(x,vi)≤d(x,vj),j=1,2,…,N,j≠i}称为Voronoi多边形,也称为该点的邻域。点集中所有点的Voronoi多边形组成Voronoi图,如图3.1所示。

平面上的Voronoi图可以看做是点集V中的每个点作为生长核,以相同的速率向外扩张,直到彼此相遇为止而在平面上形成的图形。除最外层的点形成开放的区域外,其余每个点都形成一个凸多边形。

3.2.1.1.2 Delaunay三角剖分

Delaunay三角形网格为V图的几何对偶图。在二维平面中,点集中若无四点共圆,则该点集V图中每个顶点恰好是3个边的公共顶点,并且是3个Voronoi多边形的公共顶点;上述3个Voronoi多边形所对应的点集中的点连成的三角形称为与该Voronoi顶点对应的Delaunay三角形,如图3.1所示。如果一个二维点集中有四点共圆的情况,此时,这些点对应的Voronoi多边形共用一个Voronoi顶点,这个公共的Voronoi顶点对应多于3个Voronoi多边形,也就是对应于点集中多于3个的点;这些点可以连成多于一个的三角形。此时,可以任意将上述几个点形成的凸包划分为若干三角形,这些三角形也称为和这个Voronoi顶点对应的Delaunay三角形。

所有与Voronoi顶点对应的Delaunay三角形就构成了Delaunay三角剖分。当无退化情况(四点共圆)出现时,点集的Delaunay三角剖分是唯一的。

3.2.1.1.3 Delaunay三角剖分的特性

Delaunay三角剖分具有两个重要特性:

(1)最小角最大化特性:即要求三角形的最小内角尽量最大,具体地说是指在两个相邻的三角形构成凸四边形的对角线,在相互交换后,6个内角的最小角不再增大,并且使三角形尽量接近等边。

(2)空外接圆特性:即三角形的外接圆中不包含其他三角形的顶点(任意四点不能共圆),该特性保证了最邻近的点构成三角形,使三角形的边长之和尽量最小。

3.2.1.2 常用算法

Delaunay三角剖分方法是目前最流行的通用的全自动网格生成方法之一。比较有效的Delaunay三角剖分算法有分治算法、逐点插入法和三角网生长法等(Tsai,1993),其中逐点插入法由于其算法的简洁性且易于实现,因而获得广泛的应用。其主要思路是先构建一个包含点集或区域的初始网格,再依次向初始网格中插入点,最后形成Delaunay三角剖分。

采用逐点插入法建立Delaunay三角网的算法思想最初是由Lawson于1977年提出的(Lawson,1977),Bowyer和Watson等先后对该算法进行了发展和完善(Bowyer,1981;Watson,1981)。目前涌现出的大量逐点插入法中,主要为以Lawson算法代表的对角线交换算法和以Bowyer-Watson算法代表的空外接圆法。

3.2.1.2.1 Lawson算法

Lawson算法的主要思想是将要插入的数据点逐一插入到一个已存在的Delaunay三角网内,然后再用局部优化算法(Local Optimization Procedure,LOP)优化使其满足Delau-nay三角网的要求,其主要步骤如下:

图3.2 包含点集的三角形

第一步:构建一个三角形或多个三角形(通常情况下为一个三角形,该三角形也称超级三角形),使点集中所有点都落在该三角形内,如图3.2所示。另外,也可以用一个矩形包围所有点,再将矩形对角线相连生成一对三角形作为初始网格。

第二步:将包含点集的三角形作为第一个三角形单元加入初始三角形网格中。

第三步:依次插入一个点P,并在三角网中找出包含P的三角形T,此时存在3种情况:

(1)P在三角形T内部,即P不落在三角形T的边或顶点上,把P与T的3个顶点相连,生成3个新的三角形,将新生成的三角形加入三角网,删除三角形T,如图3.3(a)所示。

(2)P在三角形T的一条边上,但不在顶点上,把P与T的3个顶点中与P相对的顶点相连,生成两个新的三角形,将新生成的三角形加入三角网,删除三角形T,如图3.4(b)所示。

(3)P在三角形T顶点上,不需处理,进行下一步操作。实际上,若点集中不存在相互重合的点,则P落在三角形T顶点上这种情况不会发生。

图3.3 向三角形网格中插入点P

上一步处理中,直接将三角形的顶点与P相连生成新的三角形单元不一定满足Delau-nay三角剖分的要求,因此,需要采用LOP算法对局部三角形进行优化。该算法的主要操作是进行边交换使新生成的三角形单元及其相邻的单元满足空外接圆特性。这样一个重要的过程其实非常简单,它就是运用Delaunay三角剖分的空外接圆特性对由两个有共用边的三角形组成的四边形进行判断,如果其中一个三角形的外接圆包含第四个顶点,则将这个四边形的对角线交换,如图3.4所示,在交换对角线后两个新三角形都满足空外接圆特性。

当两个有共用边的三角形具有相同的外接圆时,即存在四点共圆情况,此时,按照空外接圆特性,可以交换对角线也可以不交换对角线,那么这时候就要按照最小角最大化特性进行处理。具体做法是,先计算不进行边交换前三角形对中的6个内角的最小值,再计算进行边交换后6个内角的最小值,判断边交换前、后最小角是否变大,若是,交换,否则,不交换。上述操作就是为了尽量满足最小角最大化特性。

图3.4 四点不共圆时的边交换

图3.5 点集的Delaunay三角网格

第四步:在所有点被插入之后,从网格中删除多余的三角形单元,最后得到的网格就是点集的Delaunay三角网格,如图3.5所示。

按照上述算法,编程环境为VC++,Lawson算法的代码如下,其中参数CSurf*surf表示网格平面,网格结点和单元分别存储在成员pNodes和pTrgls中。函数IsPointInTrian-gle(x,y,tx[0],ty[0],tx[1],ty[1],tx[2],ty[2])用于判断点(x,y)是否落在由三点(tx[0],ty[0])、(tx[1],ty[1])和(tx[2],ty[2])组成的三角形中;函数LOP(CTrgl*ta,CTrgl*tb)采用LOP方法优化三角形对ta和tb。

三维地质建模方法及程序实现

三维地质建模方法及程序实现

三维地质建模方法及程序实现

3.2.1.2.2 Bowyer-Watson算法

Bowyer-Watson算法也是一种先形成初始网格,再逐步插入数据点进行细化的算法。与Lawson算法不同的是,Bowyer-Watson算法插入点时需要判断网格中三角形单元的外接圆是否包含该结点,而不是判断该三角形单元本身是否包含该结点;另外一个区别是Bowyer-Watson算法在每次插入一个点之后不需要像Lawson算法那样用LOP算法优化三角网。

Bowyer-Watson算法的主要步骤如下:

第一步:建立一个包含整个点集的初始网格。通常情况下初始网格为一个三角形或由一个矩形连接对角线得到的一对三角形。

第二步:依次将数据点插入到最近更新后得到的网格中,形成新的网格并更新,分为三小步:

(1)插入一个新点 P 到现有的 Delaunay 三角网格中,如图 3.6(a)所示。

(2)寻找并删除所有外接圆包含 P 点的三角单元,形成一个 Delaunay 空腔。图3.6(a)中的阴影三角形为外接圆包含 P 点的三角单元; 图 3.6(b)所示为形成的一个Delaunay 空腔。

(3)连接 P 点和 Delaunay 空腔边界上所有各点,形成新的 Delaunay 三角网格,如图3.6(c)所示。

图3.6 向三角形网格中插入点

第三步:删除多余的三角形,即如果某个三角形中的某个结点不属于原始的点集,则删除该三角形;最后结果即为点集的Delaunay三角剖分网格。

按照上述算法,编程环境为VC++,Bowyer-Watson算法的完整代码如下,其中参数CSurf*surf表示网格平面,网格结点和单元分别存储在成员pNodes和pTrgls中。函数TriangleInCircle()的作用是判断点(xp,yp)是否落在由三点(x1,y1)、(x2,y2)和(x3,y3)组成的三角形的外接圆内。

三维地质建模方法及程序实现

三维地质建模方法及程序实现

三维地质建模方法及程序实现

三维地质建模方法及程序实现

采用上述算法和代码,对一个包含46个点的点集进行Delaunay剖分,图3.7(a)所示为输入的点集,得到拥有74个三角形单元的网格,如图3.7(b)所示。

图3.7 Bowyer-Watson算法剖分实例

delaunay三角剖分算法c代码的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于delaunay 三角剖分、delaunay三角剖分算法c代码的信息别忘了在本站进行查找喔。

版权说明:如非注明,本站文章均为 AH站长 原创,转载请注明出处和附带本文链接;

本文地址:http://ahzz.com.cn/post/20628.html


取消回复欢迎 发表评论:

分享到

温馨提示

下载成功了么?或者链接失效了?

联系我们反馈

立即下载