Delaunay三角剖分

合集下载

上下扫描线的delaunay三角剖分算法

上下扫描线的delaunay三角剖分算法

上下扫描线的delaunay三角剖分算法Delaunay三角剖分是一种广泛应用于计算几何和数值分析的算法,它主要用于生成二维平面上的三角形网格。

Delaunay三角剖分具有很多优良的性质,例如空外接圆性质和最小角最大性质等。

上下扫描线的Delaunay三角剖分算法是一种高效的Delaunay三角剖分算法,其基本思想是利用扫描线从上到下或从下到上扫描整个区域,并在扫描过程中对点进行插入和删除操作,从而生成Delaunay三角剖分。

具体步骤如下:
1. 将所有点按照y坐标从大到小排序。

2. 从上到下扫描整个区域,对于每个扫描到的点,将其插入到Delaunay三角剖分中。

具体做法是:找到该点的最近点,然后删除该点,并将该点和最近点之间的线段加入到Delaunay三角剖分中。

3. 重复步骤2,直到扫描完所有点。

该算法的时间复杂度为O(nlogn),其中n为点的数量。

这是因为需要将所有点排序,并且每次插入一个点都需要在已排序的点中进行二分查找。

需要注意的是,该算法只能处理凸多边形的边界,如果存在凹多边形或自相交的情况,需要使用其他算法进行处理。

三维空间 delaunay三角剖分的分治算法

三维空间 delaunay三角剖分的分治算法

三维空间 delaunay三角剖分的分治算法
三维空间的Delaunay三角剖分可以使用分治算法来实现。


治算法是一种将问题分解成更小的子问题来解决的算法思想。

以下是三维空间Delaunay三角剖分的分治算法的基本步骤:
1. 将输入的点集P按照x坐标进行排序,得到有序点集P_x。

2. 对P_x进行分割,将点集分成两部分,左边部分为P_l,右
边部分为P_r。

3. 递归调用Delaunay三角剖分算法,分别对P_l和P_r进行处理。

这两个子问题可以分别在不同的处理器或线程上进行处理,从而加快算法的执行速度。

4. 将子问题的结果合并,得到整体的Delaunay三角剖分结果。

在递归调用Delaunay三角剖分算法时,同样的分治策略可以
应用到三维空间中。

对于每一个子问题,可以按照y坐标对点集进行排序,然后再递归地将子问题分割成更小的子问题。

当子问题中的点个数达到一个阈值时,可以使用其他的三维空间Delaunay三角剖分算法进行解决,如增量法或基于四面体的
方法。

通过使用分治算法,可以将大问题划分成许多小问题,并行地解决这些小问题,从而提高算法的执行效率。

同时,在三维空间中使用分治算法可以减少问题的复杂性,使得算法更易于实现和理解。

Delaunay三角剖分

Delaunay三角剖分
仁除了端点.平面图屮的边不包含点集屮的任何点。
2.没有相交边。(边和边没有交叉点)
3.平面图中所有的面都是三角面.且所有三介面的合集堆散点集V的凸包。
1.2 Delaunay
在实际中运用的鼓多的三角別分是Delaunay三角剖分.它绘一种待殊的三角剖分。先从Delaunay边说起:
【定义】Delaunay边:假设E中的一条边e(两个端点为a,b)> e若满足下列条件.则称Z为Delaunay边:存在一个閲
丄・CvPoint2D32f fp;//This is our point holder//;.^我心点的f•} fIRS)
2・for(i = 0; i < as_many_points_as_you_want; i++ ) {
3・//However you want to set points〃如果我们的点集不足32位的.在这里我们将其转为CvPoint2D32于・如下两种方法.
第//
5.fp=your_32f_point_list[i];
6.cvSubdiv0elaunay2DInsert( subdiv, fp )j
7・}
转换为
1)
2)
肖可以通过输入点(散点集)得到
1.cvCalcSubdivVoronoi2D( subdiv);//Fill out Voronoi data in subdiv〃在subdiv充Vornoi的数州
1.
以下是Delaunay剖分所具备的优异特性:
1x最接近:以掖接近的三点形成三角形.且各线段《三角行的边〉皆不相交。
2.唯一性:不论从区域何处开始构建.最终都将得到一致的结果。
3.眾优性:任惫两个相邻三角形构成的凸四边形的对角线如何可以互换的话.那么两个三角形六个内角屮最小角度不 会变化,

Voronoi图和Delaunay三角剖分

Voronoi图和Delaunay三角剖分

Voronoi图和Delaunay三⾓剖分刷题的时候发现了这么⼀个新的东西:Voronoi图和Delaunay三⾓剖分发现这个东西可以O(nlogn)解决平⾯图最⼩⽣成树问题感觉⾮常棒然后就去学了..看的,感谢n+e的耐⼼教导..Voronoi图是个啥Delaunay三⾓剖分最优三⾓剖分就是使每⼀个三⾓形的外接圆都不包含其他的点的三⾓剖分这个算法就是求最优三⾓剖分的简单来说就是分治合并对于点数⼩于等于3的可以直接连边合并的时候1)先找到两边最下⾯的点,这个可以⽤凸包求,然后连边2)对于现在得到的两个点p1、p2,找到⼀个点连接着p1且由这三个点的外接圆不包含别的任何点,并删除这个外接圆经过的边,p2也是如此3)看现在找出来的两个点y1、y2,找其中⼀个点使得它与p1、p2的外接圆不包含另外⼀个点,使其与对应的点连边4)重复(2)(3)直到⽆边可连对n+e代码的修改⼀开始压根不知道怎么实现这个算法的时候去看了看n+e的代码..发现他的代码中每次都要遍历p1和p2的所有边,这样的做法在特殊的图⾥⾯是O(n2)的可以说他⾃⼰出的数据偏⽔??(雾然后看了上⾯那篇详细的⽂章,发现它的边是按照顺时针或者逆时针的⽅向进⾏取边的,这样遇到的边要不删掉要不就是最优的所以我开了⼀个双向链表来储存边,使得边是按照(−π2,3π2]顺时针排列然后就会发现细节⼀⼤堆..调了我3天的东西就直接放上来好了判断⼀个点是否在某三个点的外接圆内在⾥⾯有讲,但是貌似图都爆掉了??就是把点映射到z=x2+y2的抛物⾯上,这三个点就会形成⼀个新的平⾯,然后再判断剩下的那个点和这个平⾯的关系即可下⾯放⼏张n+e给我的图⽚⽅便理解?抛物⾯z=x2+y2其实第三张图应该很清晰了吧..在圆内的点都会在平⾯下⽅,⽽在圆外的都会在平⾯上⽅这个⽤三维叉积点积判⼀下就好了Code下⾯就贴⼀下我3天的成果吧..还有什么问题请指教..bzoj4219#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <cmath>#include <vector>#define eps 1e-10using namespace std;const int Maxn = 100010;double _max(double x, double y) { return x > y ? x : y; }double _min(double x, double y) { return x < y ? x : y; }struct node {int y, nxt, frt, opp;}a[Maxn<<3]; int first[Maxn], last[Maxn], num[Maxn<<3], now;int sta[Maxn], tp;int pb(int x, int k, int y) {int u = num[now++];a[u].y = y; a[u].frt = k;if(k){a[u].nxt = a[k].nxt;if(a[k].nxt) a[a[k].nxt].frt = u;else last[x] = u;a[k].nxt = u;} else {if(first[x]) a[first[x]].frt = u;else last[x] = u;a[u].nxt = first[x]; first[x] = u;}return u;}int pf(int x, int k, int y) {int u = num[now++];a[u].y = y; a[u].nxt = k;if(k){a[u].frt = a[k].frt;if(a[k].frt) a[a[k].frt].nxt = u;else first[x] = u;a[k].frt = u;} else {if(last[x]) a[last[x]].nxt = u;else first[x] = u;a[u].frt = last[x]; last[x] = u;}return u;}void del(int x, int k) {num[--now] = k;if(a[k].nxt) a[a[k].nxt].frt = a[k].frt;else last[x] = a[k].frt;if(a[k].frt) a[a[k].frt].nxt = a[k].nxt;else first[x] = a[k].nxt;}double _abs(double x) { return x < 0 ? -x : x; }int zero(double x) { return _abs(x) < eps ? 1 : 0; }struct Point {double x, y;Point(double x = 0, double y = 0) : x(x), y(y) {}bool operator<(const Point &A) const { return zero(x-A.x) ? y < A.y : x < A.x; } Point operator-(const Point &A) const { return Point(x-A.x, y-A.y); }}list[Maxn]; int n; double X, Y;double Cross(Point A, Point B) { return A.x*B.y-B.x*A.y; }double Dot(Point A, Point B) { return A.x*B.x+A.y*B.y; }double dis(Point A) { return sqrt(Dot(A, A)); }double dis(int x, int y) { return dis(list[y]-list[x]); }struct Point3 {double x, y, z;Point3(double x = 0, double y = 0, double z = 0) : x(x), y(y), z(z) {}Point3 operator-(const Point3 &A) const { return Point3(x-A.x, y-A.y, z-A.z); } };double Dot(Point3 A, Point3 B) { return A.x*B.x+A.y*B.y+A.z*B.z; }Point3 Cross(Point3 A, Point3 B) { return Point3(A.y*B.z-A.z*B.y, A.z*B.x-A.x*B.z, A.x*B.y-A.y*B.x); } Point3 t(Point A) { return Point3(A.x, A.y, A.x*A.x+A.y*A.y); }bool incir(Point D, Point A, Point B, Point C) {if(Cross(B-A, C-A) < -eps) swap(B, C);Point3 aa = t(A), bb = t(B), cc = t(C), dd = t(D);return Dot(Cross(bb-aa, cc-aa), dd-aa) < -eps;}bool incir(int D, int A, int B, int C) { return incir(list[D], list[A], list[B], list[C]); }void divi(int L, int R) {if(L == R) return;if(L+1 == R){int k1 = pb(L, 0, R); int k2 = pf(R, 0, L);a[k1].opp = k2; a[k2].opp = k1;return;}int mid = L+R>>1, i, j, k;divi(L, mid); divi(mid+1, R);int p1 = 0, p2 = 0; tp = 0;for(i = L; i <= R; i++){while(tp > 1 && Cross(list[i]-list[sta[tp-1]], list[sta[tp]]-list[sta[tp-1]]) > eps) tp--;sta[++tp] = i;}for(i = 1; i < tp; i++) if(sta[i] <= mid && sta[i+1] > mid){ p1 = sta[i]; p2 = sta[i+1]; break; }int kp1, kp2;for(kp1 = last[p1]; kp1; kp1 = a[kp1].frt){if(Cross(list[a[kp1].y]-list[p1], list[p2]-list[p1]) < eps || Cross(list[a[kp1].y]-list[p1], Point(0,1)) < -eps) break; }int k1 = pb(p1, kp1, p2);for(kp2 = first[p2]; kp2; kp2 = a[kp2].nxt){if(Cross(list[a[kp2].y]-list[p2], list[p1]-list[p2]) > -eps || Cross(list[a[kp2].y]-list[p2], Point(0,1)) > eps) break; }int k2 = pf(p2, kp2, p1);a[k1].opp = k2; a[k2].opp = k1;while(1){int np1 = 0, np2 = 0;for(; kp1; kp1 = a[kp1].frt){if(Cross(list[a[kp1].y]-list[p1], list[p2]-list[p1]) > -eps){if(Cross(list[a[kp1].y]-list[p1], Point(0,1)) > -eps) continue;else break;}if(a[kp1].frt && incir(a[a[kp1].frt].y, p1, p2, a[kp1].y)) del(a[kp1].y, a[kp1].opp), del(p1, kp1);else { np1 = kp1; break; }}for(; kp2; kp2 = a[kp2].nxt){if(Cross(list[a[kp2].y]-list[p2], list[p1]-list[p2]) < eps){if(Cross(list[a[kp2].y]-list[p2], Point(0,1)) < -eps) continue;else break;}if(a[kp2].nxt && incir(a[a[kp2].nxt].y, p1, p2, a[kp2].y)) del(a[kp2].y, a[kp2].opp), del(p2, kp2);else { np2 = kp2; break; }}if(!np1 && !np2) break;if(!np2 || (np1 && !incir(a[kp2].y, p1, p2, a[kp1].y))){p1 = a[kp1].y;k2 = pf(p2, kp2, p1);for(kp1 = last[p1]; kp1; kp1 = a[kp1].frt){if(Cross(list[a[kp1].y]-list[p1], list[p2]-list[p1]) < eps || Cross(list[a[kp1].y]-list[p1], Point(0,1)) < -eps) break; }k1 = pb(p1, kp1, p2);a[k1].opp = k2; a[k2].opp = k1;} else {p2 = a[kp2].y;k1 = pb(p1, kp1, p2);for(kp2 = first[p2]; kp2; kp2 = a[kp2].nxt){if(Cross(list[a[kp2].y]-list[p2], list[p1]-list[p2]) > -eps || Cross(list[a[kp2].y]-list[p2], Point(0,1)) > eps) break; }k2 = pf(p2, kp2, p1);a[k1].opp = k2; a[k2].opp = k1;}}}struct enode {int x, y; double d;enode(int x = 0, int y = 0, double d = 0) : x(x), y(y), d(d) {}bool operator<(const enode &A) const { return d < A.d; }}e[Maxn<<4]; int el;int fa[Maxn];int ff(int x) { return fa[x] == x ? x : fa[x] = ff(fa[x]); }int main() {int i, j, k;scanf("%d%lf%lf", &n, &X, &Y);for(i = 1; i <= n; i++) scanf("%lf%lf", &list[i].x, &list[i].y);now = 1;for(i = 1; i <= n<<3; i++) num[i] = i;sort(list+1, list+n+1);divi(1, n);for(i = 1; i <= n; i++){e[++el] = enode(i, n+1, _min(list[i].x, Y-list[i].y));e[++el] = enode(i, n+2, _min(list[i].y, X-list[i].x));for(k = first[i]; k; k = a[k].nxt) e[++el] = enode(i, a[k].y, dis(i, a[k].y)/2.0); }sort(e+1, e+el+1);for(i = 1; i <= n+2; i++) fa[i] = i;for(i = 1; i <= el; i++){int fx = ff(e[i].x), fy = ff(e[i].y);if(fx != fy){fa[fx] = fy;if(ff(n+1) == ff(n+2)){ printf("%lf\n", e[i].d); return 0; }}}return 0;}⼩总结??虽然这次搞这个东西⽤的时间很长.. 但是收获还是很⼤的..最后差那么⼏个点wa还是很想放弃的..但是还是坚持下了来了嘛..加油啊..Processing math: 100%。

delaunay方法

delaunay方法

delaunay方法
Delaunay方法,又称为Delaunay三角剖分,是前苏联数学家Delaunay在1934年提出的一种三角剖分方法。

该方法满足所谓的“最大-最小角”优化准则,即所有最小内角之和最大,从而使得划分的三角形不会出现某个内角过小的情况。

这种方法在二维情况下可以描述为:对于给定的平面点集,只存在着唯一的一种三角剖分方法,满足Delaunay三角剖分的条件,即任意一个三角形的外接圆内不包括其他结点。

Delaunay三角剖分方法在各种二维三角剖分中具有全局和局部最优性。

它可以应用于数值模拟的网格生成,尤其在复杂外形的非结构网格生成中有广泛应用。

此外,Delaunay 三角剖分方法还可以推广至多维问题,例如在三维情况下,四面体的外接球内不包含其他节点。

在具体实施过程中,三维情况下的Delaunay三角化可以包括以下步骤:在三维空间内定义一个大的凸壳区域以覆盖所有将要插入的点;根据网格步长分布要求在凸壳区域内引入一个新点;标记将被删除的四面体(其外接球包含新点的所有四面体);建立空洞边界(由被标记的四面体组成的凸壳的外边界);在剩余四面体中查找被标记四面体的邻居以
建立有效的空间连续性;利用空洞边界上每个三角形的三个顶点与新点组成新的四面体;建立空洞外原四面体和新生成的四面体的邻居关系。

delaunay 三角剖分 步骤

delaunay 三角剖分 步骤

delaunay 三角剖分步骤1. Delaunay三角剖分是用于将点集分割成不规则三角形的方法。

The Delaunay triangulation is a method for dividing a set of points into irregular triangles.2.首先选择一个点作为起始点。

First, select a point as the starting point.3.然后选择另外两个点与起始点构成一个三角形。

Then select two other points to form a triangle with the starting point.4.接着选择一个未被包含在任何三角形内的点。

Then select a point that is not included in any triangle.5.在所有的三角形中寻找能将这个新点包含进去的三角形。

Find a triangle among all the triangles that can include this new point.6.如果找到了这样的三角形,将这个三角形和新点围成的区域删除。

If such a triangle is found, remove the area enclosed by this triangle and the new point.7.在新的边缘上寻找新的三角形。

Find new triangles on the new edges.8.重复以上步骤,直到所有的点都被包含在三角形内。

Repeat the above steps until all points are included in triangles.9. Delaunay三角剖分具有无重叠、最小化夹角和最大化最小角的性质。

Delaunay triangulation has the properties of non-overlapping, minimizing angles, and maximizing minimum angles.10.可以使用Delaunay三角剖分来进行网格生成和空间分析。

三维空间Delaunay三角剖分算法的研究及应用

三维空间Delaunay三角剖分算法的研究及应用

三维空间Delaunay三角剖分算法的研究及应用一、本文概述随着计算几何和计算机图形学的发展,三维空间Delaunay三角剖分算法已成为一种重要的空间数据处理和分析技术。

本文旨在全面深入地研究三维空间Delaunay三角剖分算法的原理、实现方法以及应用领域。

本文将对三维空间Delaunay三角剖分算法的基本概念和性质进行详细的阐述,包括其定义、性质、特点以及与其他三角剖分算法的比较。

接着,本文将重点探讨三维空间Delaunay三角剖分算法的实现方法,包括增量法、分治法和扫描转换法等,并分析它们的优缺点和适用范围。

本文还将对三维空间Delaunay三角剖分算法在各个领域的应用进行详细的介绍和分析。

这些领域包括计算机科学、地理信息系统、地质学、气象学、生物医学等。

通过具体的应用案例,本文将展示三维空间Delaunay三角剖分算法在实际问题中的应用价值和效果。

本文还将对三维空间Delaunay三角剖分算法的未来发展方向进行展望,探讨其在新技术和新领域中的应用前景和挑战。

本文旨在全面系统地研究三维空间Delaunay三角剖分算法的理论和实践,为其在实际问题中的应用提供有力的支持和指导。

二、三维空间Delaunay三角剖分算法的基本原理Delaunay三角剖分算法是一种广泛应用于二维空间的数据处理算法,它的核心目标是将一组离散的二维点集剖分为一系列互不重叠的三角形,且这些三角形满足Delaunay性质。

简单来说,Delaunay 性质要求任何一个三角形的外接圆内部不包含该三角形之外的任何数据点。

初始化:为每个点分配一个初始的三角形。

这通常是通过连接每个点与它的两个最近邻点来完成的,形成一个初始的三角形网格。

合并三角形:接下来,算法会尝试合并相邻的三角形,以形成更大的三角形。

在合并过程中,算法会检查新形成的三角形是否满足Delaunay性质。

如果满足,则合并成功;如果不满足,则放弃合并,并标记这两个三角形为“已处理”。

delaunay-三角剖分算法

delaunay-三角剖分算法

一、概述Delaunay 三角剖分算法是计算机图形学领域中常用的一种算法,它可以将给定的点集进行高效的三角剖分,用于构建网格、进行地理信息系统分析、建立三维模型等应用。

本文将对该算法的原理、实现和应用进行介绍。

二、算法原理1. 待剖分点集在进行Delaunay三角剖分之前,需要准备一个点集,这个点集是待剖分的对象。

点集的数量取决于具体的应用,可以是二维平面上的点,也可以是三维空间中的点。

2. Delaunay 三角形在进行三角剖分时,Delaunay 三角形是一种特殊的三角形,满足以下性质:a. 任意一个点要么位于Delaunay 三角形的外接圆内部,要么位于外接圆的边上;b. 任意两个Delaunay 三角形之间的外接圆不相交。

3. Delaunay 三角剖分Delaunay 三角剖分是将给定点集进行三角剖分的过程,它的目标是构建满足Delaunay 三角形性质的三角形集合。

三、算法实现1. 基于增量法的实现增量法是Delaunay 三角剖分的一种经典算法,它的基本思想是逐步增加点,并根据Delaunay 三角形的性质进行调整。

具体步骤如下: a. 初始化:选择一个超级三角形包含所有点集,作为初始三角剖分;b. 顺序插入点:逐个将待剖分点插入到当前三角剖分中,并进行调整;c. 边界检测:检测新增的边界是否需要进行修正;d. 优化处理:对新增点周围的三角形进行优化调整。

2. 时间复杂度分析增量法的时间复杂度主要取决于点集的数量和点的分布情况,一般情况下,其时间复杂度可以达到O(nlogn)。

四、算法应用1. 图形渲染在计算机图形学中,Delaunay三角剖分常用于构建网格、进行三维渲染等。

它可以有效地分割空间,使得渲染效果更加真实。

2. 地理信息系统地理信息系统中常常需要对地理数据进行空间分析,Delaunay三角剖分可以帮助构建地理网格,进行地形分析、资源评估等。

3. 三维建模在三维建模领域,Delaunay三角剖分可以用于构建复杂的三维模型,并支持模型的分析、编辑等功能。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

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); } }
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;
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[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) //{ // // // // // // // //} deltins = TinInsert(envtins, dispts);//离散点内插 return deltins; } } gra.DrawPolygon(Pens.Blue, ctin); 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.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));
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); }
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();
} 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]))
相关文档
最新文档