凸包

凸包
凸包

实验报告

姓名:张晖

班级:地信1002

学号:201001136 指导:刘少华老师

2013.4.17

基于凸包的三角网算法

一,实验背景

数字地形模型是针对地形地貌的一种数字建模,这种建模的结

果通常就是一个数字高程模型(DEM)。不规则三角网(TIN)

模型是DEM中存储和表示非规则数据的理想模型,它既减少

规则网格方法造成的数据冗余,同时在计算效率方面又优于

纯粹基于等高线的方法,所以寻求一种好的TIN算法更能快

速逼真的显示与模拟出地貌三维信息。在所有可能的三角网

中,Delaunay三角网在地形拟合方面表现最为出色,因此常

常用于TIN的生成。

二,实验目的

1,了解TIN的算法种类及各算法特点,尤其是对三角网生长

算法的了解与掌握

2,根据基于凸包的三角网算法,应用C#编写一个自动生成三

角网的程序。

3,学生熟练掌握C#的使用。

三,实验内容

1. 查找关于三角网生成算法的论文,了解与掌握其要义。

2. 分析与研究三角网生成算法

3. 选择一种算法实现三角网的生成(三角网生长算法)

4. 选择一种语言编写三角网的生成代码(C#)

四,算法简介

(1)凸包生成。①求出点集中满足min(x-y)、min(x+y)、max(x-y)、max(x+y)的四个点,并按照逆时针方向组成一个链表。这四个点是离

散点中与包含离散点的外接矩形的四个角点最接近的点,这四个点构成

的多边形作为初始凸包。

②对于每个凸包上的点I,设它的后续点为J,计算矢量线段IJ右侧的所有

点到IJ的距离,求出距离最大的点K。

③将K插入I、J之间,并将K赋给J。

④重复②、③步,直到点集中没有在线段IJ右侧的点为止。

⑤将J赋给I,J取其后续点,重复②、③、④步。

⑥当凸包中任意相邻两点连线的右侧不存在离散点时,结束点集凸包求取

过程。

完成这一步后,形成了包含所有离散点的多边形(凸包)。

(2)环切边界法凸包三角剖分。在凸包链表中每次寻找一个由相邻两条凸包边组成的三角形,在该三角形的内部和边界上都不包含凸包上的任何

其他点。将这个点去掉后得到新的凸包链表。重复这个过程,直到凸包

链表中只剩下三个离散点为止。将凸包链表中的最后三个离散点构成一

个三角形,结束凸包三角剖分过程。

完成这一步后,将凸包中的点构成了若干Delaunay三角形。

(3)离散点内插。在对凸包进行三角剖分之后,不在凸包上的其余离散点,可采用逐点内插的方法进行剖分。其基本过程为:

①找出外接圆包含待插入点的所有三角形,构成插入区域。

②删除插入区域内的三角形公共边,形成由三角形顶点构成的多边形。

③将插入点与多边形所有顶点相连,构成新的Delaunay三角形。

④重复①、②、③,直到所有非凸壳离散点都插入为止。

完成这一步,就完成了Delaunay三角网的构建。

五,源代码

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Drawing;

namespace TINProject

{

class CPoint

{

public int id;

public float x, y;

public CPoint()

{ id = 0; }

}

class CEdge

{

public int id;

public int[] pid;

public int[] tid;

public CEdge()

{

id = 0;

pid = new int[2];

tid = new int[2];

}

}

class CTriangle

{

public int id;

public int[] pid;

public int[] eid;

public CTriangle()

{

id = 0;

pid = new int[3];

eid = new int[2];

}

}

class CTin

{

public List _PntsAry;

public List _EdgesAry;

public List _TrianlgesAry;

public List _TuBaoAry;

public CTin()

{

_PntsAry = new List();

_EdgesAry = new List();

_TrianlgesAry = new List();

_TuBaoAry = new List();

}

public bool IsRightInLine(CPoint p1, CPoint p2, CPoint p)

{

double dx, dy;

dx = p2.x - p1.x;

dy = p2.y - p1.y;

double d = dy * (p.x - p1.x) + dx * (p1.y - p.y);

if (d < 0)

return true;

return false;

}

public double distance(CPoint a, CPoint b

{

double dis;

dis = Math.Sqrt((b.y - a.y) * (b.y - a.y) + (b.x - a.x) * (b.x - a.x));

return dis;

}

public double GetThreePointsCosAngle(CPoint a, CPoint b, CPoint c)

{

double distance1, distance2, distance3;

double cos;

distance1 = Math.Pow((b.x - a.x), 2) + Math.Pow((b.y - a.y), 2);

distance2 = Math.Pow((c.x - a.x), 2) + Math.Pow((c.y - a.y), 2);

distance3 = Math.Pow((b.x - c.x), 2) + Math.Pow((b.y - c.y), 2);

cos = (double)(distance3 + distance2 - distance1) * 1.000000 / (2 * Math.Sqrt(distance3) * Math.Sqrt(distance2));

return cos;

}

public int GetMaxCosAngle(CPoint p1, CPoint p2)

{

double minCos = 1;

int targetIndex = -1;

foreach (CPoint p in_PntsAry)

{

if (IsRightInLine(p1, p2, p))

{

double cosangle = GetThreePointsCosAngle(p1, p2, p);

if (cosangle < minCos)

{

minCos = cosangle;

targetIndex = p.id;

}

}

}

return targetIndex;

}

public int get_leftpoint_cos_index(CPoint p1, CPoint p2)

{

double minCos = 1;

int Index = -1;

foreach (CPoint p in_PntsAry)

{

if (!IsRightInLine(p1, p2, p))

{

double cosangle = GetThreePointsCosAngle(p1, p2, p);

if (cosangle < minCos)

{

minCos = cosangle;

Index = p.id;

}

}

}

return Index;

}

private Pen pen = new Pen(Color.Blue, 5);

private Brush brush = Brushes.Blue;

float r = 10;

public void draw(Graphics g)

{

foreach (CPoint p in_PntsAry)

{

g.FillEllipse(brush, p.x - r / 2, p.y - r / 2, r, r);

}

for (int i = 0; i <= _EdgesAry.Count - 1; i++)

{

g.DrawLine(new Pen(Color.Black), _PntsAry[_EdgesAry[i].pid[0]].x, _PntsAry[_EdgesAry[i].pid[0]].y, _PntsAry[_EdgesAry[i].pid[1]].x,

_PntsAry[_EdgesAry[i].pid[1]].y);

}

for(int j=0;j<_TuBaoAry.Count-1 ;j++)

{

g.DrawLine(new Pen(Color.Red), _TuBaoAry[j].x, _TuBaoAry[j].y, _TuBaoAry[j + 1].x, _TuBaoAry[j + 1].y);

}

}

public void tubao_construct() //建立凸包

{

_TuBaoAry.Clear();

int i, min_index = -1, index = -1;

double min_y, maxangle = -1, angle = -1;

CPoint z=new CPoint();

CPoint p1 = new CPoint();

z = _PntsAry[0];

min_y = z.y;

for (i = 0; i < _PntsAry.Count; i++)

{

if (min_y >= _PntsAry[i].y)

{

min_y = _PntsAry[i].y;

min_index = i;

}

}

p1 = _PntsAry[min_index];

_TuBaoAry.Add(p1);

CPoint p = new CPoint();

p.id = -1;

p.x = p1.x + 200;

for (int j = 0; j < _PntsAry.Count; j++)

{

if (p1.id != _PntsAry[j].id)

{

angle = GetThreePointsCosAngle( p, _PntsAry[j],p1);

if (angle > maxangle)

{

maxangle = angle;

index = j;

}

}

}

if (index >= 0)

{

_TuBaoAry.Add(_PntsAry[index]);

}

int count = _TuBaoAry.Count - 1;

CPoint p0 = _TuBaoAry[count];

while (p0.id != p1.id)

{

count = _TuBaoAry.Count - 1;

CPoint p2 = _TuBaoAry[count - 1];

CPoint temp_point = new CPoint();

temp_point.id =p2.id;

temp_point.x = 2 *p0.x -p2.x;

temp_point.y = 2 *p0.y - p2.y;

maxangle = -1;

index = -1;

for (int j = 0; j < _PntsAry.Count; j++)

{

if (p0.id != _PntsAry[j].id)

{

angle = GetThreePointsCosAngle( temp_point, _PntsAry[j],p0);

if (angle > maxangle)

{

maxangle = angle;

index = j;

}

}

}

if (index >=0)

{

_TuBaoAry.Add(_PntsAry[index]);

count++;

p0 = _TuBaoAry[count];

}

}

}

public void construct_tin()

{

_EdgesAry.Clear();

if (_PntsAry.Count < 3)

int use_point_cout = 0;

int i, count = -1;

CEdge edg = new CEdge();

CEdge one = new CEdge();

CEdge other = new CEdge();

int firstpoint = 0;

double mixdistance = 10000000, dis1;

for (i = 1; i < _PntsAry.Count; i++)

{

dis1 = distance(_PntsAry.ElementAt(firstpoint), _PntsAry.ElementAt(i));

if (mixdistance > dis1)

{

mixdistance = dis1;

count = i;

}

}

if (count < 0) return;

edg.id = 0;

edg.pid[0] = firstpoint;

edg.pid[1] = count;

_EdgesAry.Add(edg);

CPoint p2 = _PntsAry[count];

int k = GetMaxCosAngle(_PntsAry[firstpoint], p2);

if (k >= 0)

{

one.id = 1;

one.pid[0] = firstpoint;

one.pid[1] = k;

_EdgesAry.Add(one);

other.id = 2;

other.pid[0] = k;

other.pid[1] = count;

_EdgesAry.Add(other);

}

int f;

int currentid = 1;

while (currentid <= _EdgesAry.Count - 1)

{

int c, b;

f =

GetMaxCosAngle(_PntsAry.ElementAt(_EdgesAry.ElementAt(currentid).pid[0]),

_PntsAry.ElementAt(_EdgesAry.ElementAt(currentid).pid[1]));

if (f > 0)

{

c = _PntsAry.ElementAt(_EdgesAry.ElementAt(currentid).pid[0]).id;

b = f;

if (!IsExistCedg(c, b))

{

CEdge edg2 = new CEdge();

edg2.id = _EdgesAry.Count;

edg2.pid[0] = c;

edg2.pid[1] = b;

_EdgesAry.Add(edg2);

}

c = f;

b = _PntsAry.ElementAt(_EdgesAry.ElementAt(currentid).pid[1]).id;

if (!IsExistCedg(c, b))

{

CEdge edg1 = new CEdge();

edg1.id = _EdgesAry.Count;

edg1.pid[0] = c;

edg1.pid[1] = b;

_EdgesAry.Add(edg1);

}

}

use_point_cout = (_EdgesAry.Count + 3) / 2;

currentid++;

}

}

public bool IsExistCedg(int i, int j)

{

foreach (CEdge t in_EdgesAry)

{

if (t.pid[0] == i && t.pid[1] == j)

return true;

else if (t.pid[1] == i && t.pid[0] == j)

return true;

}

return false;

}

public void drawline(Graphics g)

{

CPoint p1 = new CPoint();

CPoint p2 = new CPoint();

foreach (CEdge edg in_EdgesAry)

{

for (int i = 0; i < _EdgesAry.Count - 1; i++)

{

for (int j = 0; j < _PntsAry.Count - 1; j++)

{

if (_PntsAry[j].id == _EdgesAry.ElementAt(i).pid[0] &&

_PntsAry[j].id == _EdgesAry.ElementAt(i).pid[1])

{

p1.x = _PntsAry[_EdgesAry.ElementAt(i).pid[0]].x;

p1.y = _PntsAry[_EdgesAry.ElementAt(i).pid[0]].y;

p2.x = _PntsAry[_EdgesAry.ElementAt(i).pid[1]].x;

p2.y = _PntsAry[_EdgesAry.ElementAt(i).pid[1]].y;

g.DrawLine(new Pen(Color.Black), p1.x, p1.y, p2.x, p2.y);

}

}

}

} }}

(1)自己取点

(2)随机取点

在刘老师的指导下,通过一段时间的学习,我对数字高程模型有了一定的了解。TIN(Triangulated Irregular Network)即不规则三角网,Delaunay三角网是其中的一种表现形式,也是一种主要的DTM 的表示法。老师针对几种算法中的生成算法进行了重点讲解和实际操作指导。清楚明白的了解到TIN即不规则三角网的生成原理和过程Delaunay三角网生成算法经过多年的发展已经相当成熟,它在生活、军事、工业等领域都得到了广泛地应用,Delaunay三角网生成算法具有非常重要的意义。

第65讲 凸集与凸包(原)

第65讲凸集与凸包 本节主要内容是:凸集、凸包的概念以及用凸集凸包来解有关的题.凸集:平面上的点集,如果任何两点在这个点集内,则连这两点的线段上的所有的点也在此点集内,就说该点集是一个凸集. 线段、射线、直线、圆及带形、整个平面等都是凸集. 两个凸集的交集还是凸集;任意多个凸集的交集也仍是凸集. 凸包:每个平面点集都可用凸集去盖住它,所有盖住某个平面点集的凸集的交集就是这个平面点集的凸包. 或者可以形象地说:如果把平面上的点集的每个点都插上一根针,然后用一根橡皮筋套在这些针外,当橡皮筋收紧时橡皮筋围出的图形就是这个点集的凸包. 平面点集的直径平面点集中的任意两点距离的最大值称为这个平面点集的直径. 例如,圆的直径就是其直径,有无数条;线段的直径就是其本身;正三角形的三个顶点组成的点集的直径就是其边长,有三条;平行四边形的直径是其较长的对角线;…. A类例题 例1定理任何一个平面点集的凸包是存在且唯一的. 分析存在惟一性的证明,即证明满足某条件的集A存在且惟一存在.通常先证明存在性,即证明有满足条件的集合A.再用反证法证明惟一性,即若满足条件的集A不惟一,或说明会引出矛盾,或得出其余集均必需与A相等的结论. 证明由于全平面是一个凸集,故任何平面点集都可用全平面盖住,即能被凸集盖住,从而盖住该凸集的所有凸集的交集存在,即凸包存在.而如果某个凸集A有两个凸包M1与M2,则M1∩M2也能盖住凸集A,且M1∩M2?M1,但M1是A的凸包,故M1?M1∩M2,故M1∩M2=M1.同理M1∩M2=M2.即M1=M2.

例2 定理 如果一个点集M 是由有限个点组成,且其中至少有三个点不共线,则M 的凸包是一个凸多边形. 分析 可以构造一个寻找凸包的方法,来说明命题的正确性. 证明 由于M 为有限点集,故存在一条直线l ,使M 中的一个或几个点在l 上,其余的点 都在l 同旁(这只要任画一条直线,如果点集M 中的点在直线l 的两旁,则让直线按与此直线垂直的方向平移,即可得到满足要求的直线). 取l 上的两个方向中的一个方向为正向,此时,按此正向,不妨设M 中不在l 上的点都 在l 的左边.在l 上沿其正向找出M 中的最后一个点A 1,把l 绕A 1逆时针旋转,直到遇到M 中的另外的点,又找出此时l 上的M 中的最后一个点A 2,此时再让l 绕A 2逆时针旋转,依此类推,直到最后绕A k 旋转又遇到A 1为止(由于M 是有限点集,故这样的旋转不可能一起下去).这时,凸多边形A 1A 2…A k 即为M 的凸包. 情景再现 1.证明圆面(圆及圆内所有的点组成的集合)是凸集. 2.平面上任意给定5个点,其中任三点不共线,则可选出4个点,这四点能构成一个凸四边形的四个顶点. B 类例题 例3 海莱定理: 定理(海莱定理) 对于若干个(个数n ≥3)凸集,如果任意三个凸集都有一个公共点,那么存在一个点同时属于每个凸集. 分析 先证明简单情况,再用数学归纳法证明本定理. 证明 对于n =3,显然成立. 当n >3时,先取4个这样的凸集.F 1,F 2,F 3,F 4. A A A A 123k l l 1

把点集凸包化Granham-Scan算法(使用水平序)概要

把点集凸包化Granham-Scan算法(使用水平序) #include #include #include #include using nameaace std; const int M=100000+5; struct Point { double x,y; } p[M]; double dis(Point A,Point B) { return sqrt((B.x-A.x)*(B.x-A.x)+(B.y-A.y)*(B.y-A.y)); } bool cmp(Point a,Point b) { if (a.xb.x) return false; if (a.y1 && p[i].x==p[i-1].x && p[i].y==p[i-1].y) continue; p[++t]=p[i]; } n=t; t=0; memset(bo+1,true,n*sizeof(bo[0])); if (n>0){ stack[++t]=1; bo[stack[t]]=false;

求凸包算法详解

概念 凸包(Convex Hull)是一个计算几何(图形学)中的概念。用不严谨的话来讲,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边型,它能包含点集中所有点的。严谨的定义和相关概念参见维基百科:凸包。 这个算法是由数学大师葛立恒(Graham)发明的,他曾经是美国数学学会(AMS)主席、AT&T首席科学家以及国际杂技师协会(IJA)主席。(太汗了,这位大牛还会玩杂技~) 问题 给定平面上的二维点集,求解其凸包。 过程 1. 在所有点中选取y坐标最小的一点H,当作基点。如果存在多个点的y坐标都为最小值,则选取x坐标最小的一点。坐标相同的点应排除。然后按照其它各点p和基点构成的向量与x轴的夹角进行排序,夹角由大至小进行顺时针扫描,反之则进行逆时针扫描。实现中无需求得夹角,只需根据向量的内积公式求出向量的模即可。以下图为例,基点为H,根据夹角由小至大排序后依次为H,K,C,D,L,F,G,E,I,B,A,J。下面进行逆时针扫描。 2. 线段一定在凸包上,接着加入C。假设线段也在凸包上,因为就H,K,C 三点而言,它们的凸包就是由此三点所组成。但是接下来加入D时会发现,线段才会在凸包上,所以将线段排除,C点不可能是凸包。 3. 即当加入一点时,必须考虑到前面的线段是否会出现在凸包上。从基点开始,凸包上每条相临的线段的旋转方向应该一致,并与扫描的方向相反。如果发现新加的点使得新线段与上线段的旋转方向发生变化,则可判定上一点必然不在凸包上。实现时可用向量叉积进行判断,设新加入的点为p n + 1,上一点为p n,再上一点为p n - 1。顺时针扫描时,如果向量

Graham算法求凸包完整程序代码

#include #include #include using namespace std; /* PointSet[]:输入的点集 ch[]:输出的凸包上的点集,按照逆时针方向排列 n:PointSet中的点的数目 len:输出的凸包上的点的个数 */ struct Point { float x,y; }; //小于,说明向量p0p1的极角大于p0p2的极角 float multiply(Point p1,Point p2,Point p0) { return((p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y)); } float dis(Point p1,Point p2) { return(sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y))); } void Graham_scan(Point PointSet[],Point ch[],int n,int &len) { int i,j,k=0,top=2; Point tmp; //找到最下且偏左的那个点 for(i=1;i0) ||((multiply(PointSet[j],PointSet[k],PointSet[0])==0)

打凸包

凸包成形 (1)高凸包成形方法: 在MB板等产品上经常可以看到一些高度较高的凸包,如图(A)所示。 (2). 成形方法 产品的凸包高度(H)比较高,在一次抽凸成形时容易拉破。为了避免发生拉破现象 保证产品成形以后的形状尺寸,一般要分两步成形。 第一步:抽弧形。如上图(B),注意以下几个重点: A. 产品抽弧成形后的c和d两点间的周长L1(由三段弧长相加)应稍大于产品要求的 断面中a和b两点间的周长L2(a和b参见图A),一般L1=L2+(0.2~0.8)mm. B. 下模入子c和d两点间的直线距离等于产品要求的断面中a和b两点间的直线距离D5。 C. 闭模时保证图中半径为r1的圆弧与下模最小间隙为产品材料厚度的百分之六十(T*60%)。 第二步:整形。 有两种不同的整形方法。如图(C)和图(D),一般用图(C)方法,凸包外形要求不高 时用图(D) 方法 (3). 确定抽弧形时冲子尺寸的步骤和方法: A. 根据产品要求的形状和尺寸确定下模入子内孔的形状尺寸。如图(E) 注意:a.C和d点间的直线距离等于产品要求的断面中a和b两点的直线距离D5。 b.入子内孔中圆弧半径r1的大小一般在1~3mm之间(含1和3mm),以0.5mm 为一阶。初步确定取r1等于产品断面中相应处的半径r.

B. 初步产品抽弧形时的外形尺寸: a. 如图(f)所示,以3点(下与下模入子内孔两r1圆弧的切点及抽凸底部的中点(g)作圆。

b. 经过修剪如图(g)所示,测出点c和点d间三段圆弧的总长度L1。 c. 如果此三段弧总长L1小于产品要求的断面中a和b两点间的周长L2,则通过把抽凸底部中点g向下移动一段距离h(h可以0.5mm为一阶)后得出点h,重新过三点作圆,如图(h)所示。 d. 重复步骤3.2.2.2和步骤3.2.2.3,直到满足L1=L2+(0.2~0.8)mm。通过此方法求出产品抽弧形时的外形尺寸 C. 确定抽弧形冲子端部球体半径的方法: a. 以第3.3.2步确定的产品抽弧形时的外形尺寸偏移一个材料厚度。如图(I) b. 以下模入子内孔中半径为r1的两圆弧偏移T*0.6%。如图(I) c. 用三点作圆的方法画出与步骤3.3.3.1和步骤3.3.3.2中确定的三段弧相切的 圆,此圆的半径R就是抽弧形冲子端部球体的半径R(取小数点后一位小数,但标注尺寸时精确到小数点后两位)。如图(J) D. 确定抽弧形冲子身部直径 a. 如果(B)确定的圆球心在产品材料上表面(即上脱板与材料接触面)以上时,圆球与产品材料上平面相交,就得出抽弧形部子身部的断面。如图(K)所示,D9 就是所求的抽弧形冲子身部的直径。 b.如果(B)确定的圆球圆心在产品材料上表面(即上脱板与材料接触面)与下表面 之间,就取抽弧形冲子的身段直径D9等于圆球的直径(即D9=2*R),抽弧形 冲子的端部形状就是一半球体。如图(I) c. 如果(B)确定的圆球圆心在产品材料下表面(即下模板与材料接触面)以下时,必须请主管决定。

凸包问题

凸包问题 摘要:凸包问题是计算机几何中的一个经典问题,它要求将平面内的点集用最少的凸点将所有的顶点封闭。凸包问题的应用十分广泛,很多最优化问题经过抽象后可以发现它最终是凸包问题模型;它还可以用于人际关系网络的最小化搜索,通过人际关系,可以合理推断出某人的身份,职位等个人特征。目前求取凸包的常用算法有:穷举法,格雷厄姆扫描法(Graham),分治法,蛮力法和Jarris 步进法。其中穷举法与蛮力法都是建立在穷举的算法思想上,它们的时间复杂度比较大,格雷厄姆扫描法采用几何方面的知识,降低了求解过程的时间复杂度。关键词:凸包问题;计算机几何;格雷厄姆扫描法 一、引言 凸包问题的完整描述:令S 是平面上的一个点集,封闭S 中所有顶点的最小凸多边形,称为S 的凸包,表示为CH(S)。如下图一所示,由红色线段表示的多边形就是点集Q={p0,p1,...p12}的凸包。 图一 凸包问题是计算机几何的一个经典问题,它可以解决很多优化模型,目前目前求取凸包的常用算法有:穷举法,格雷厄姆扫描法(Graham),分治法,蛮力法和Jarris步进法。本文主要讨论穷举法,蛮力法,以及格雷厄姆扫描法,通过算法思想的描述,计算出相应的时间复杂度,比较这几种算法的优劣。

二、穷举法 穷举法的思想很简单直接,它利用凸包性质—如果点集中的两个点的连线属于凸多边形的边,当且仅当点集中其余的点都在这两个点连线的同一侧。 假设点集合S 中有n 个顶点,则这n 个顶点共可以构成(1) 2n n -条边,对于任何一条边来讲,检查其余的n-2 个点的相对于该直线段的正负性。如果它们有相同的正负性,说明该边是凸多边形的边,反之就不属于凸多边形,继续检查。算法流程图如下: 不相同 相同 N Y 图二:算法流程图 上述算法(穷举法)需要执行n(n-1)/2 次,再次检查n-2 个点的正负性,故算法 时间复杂性为2(1)2 n n -∑=3()o n 。显然这并非一个高效的算法凸包问题有许多更加有效的算法可以达到log n n 的渐近时间复杂度。 三、蛮力法 开始 从点集S 中取出两个顶 点u ,v 判断其余的n-2 个点的相对于该直线段的正负性 判断执行次数是否 大于(1)2n n - 把u ,v 加入凸包 结束

计算几何之凸包(一) {卷包裹算法}

计算几何之凸包(一) {卷包裹算法} { 半个寒假都在写凸包 这几篇文章整理一下 主要介绍二维凸包的求解算法 以及一个简单的应用 } ================================================== ================== 一.凸集&凸包 (下文中所有的集合若不作特殊说明都是指欧氏空间上的集合) 凸集(Convex Set):任意两点的连线都在这个集合内的集合就是一个凸集. A set in Euclidean space is convex set if it contains all the line segm ents connecting any pair of its points. https://www.360docs.net/doc/6b17740004.html,/Convex.html 凸包(Convex Hull):包含集合S的所有凸集的交集就是集合S的凸包. The convex hull of a set of points S in N dimensions is the intersection of all convex sets containing S.

我们经常关注一个点集的凸包这也是计算几何学的一个基本问题 我们现在已经有成熟的算法可以求出平面点集的凸包和空间点集的凸包 甚至有的算法可以方便的求出任意维度欧氏空间内的一个点集的凸包 凸包有着优美而实用的性质我们可以利用凸包把一个杂乱的点集所包含的信息进行有效的概括梳理 ================================================== ================== 二.平面点集的凸包的算法 (下文中所有凸包若不作特殊说明都是指平面点集的凸包) 有两种直观的理解凸包的方式 在木板上钉钉子用一个有弹性的橡皮筋去框住所有钉子 橡皮筋形成的图形就是这个钉子所构成的点集的凸包

凸包

算法分析与设计 课程设计 题目:凸包问题 所属专业:信息与计算科学 年级:1121102 学生姓名:江浩2011213361 学生姓名:张鸿2011213363 学生姓名:杨永涛2011213374 指导教师:于洪 评定成绩:

关于凸包问题的分析与求解 摘要 本文针对凸包问题进行分析和讨论,首先对凸包进行定义性描述并对其做具体分析,它要求将平面内的点集用最少的凸点来封闭,然后给出其具体模型,并对模型进行分析和求解,最后我们讨论几种求解算法(包括穷举法,蛮力法和分治法)的优劣性并给出问题的算法代码。 关键词:凸包问题穷举法分治法 一.引言 凸包(Convex Hull)是一个计算几何(图形学)中的概念。用不严谨的话来讲,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的多边形,它能包含点集中的所有点。 凸包问题的完整描述如下: 令S 是平面上的一个点集,封闭S 中所有顶点的最小凸多边形,称为S 的凸包,表示为CH(S)。如下图一所示,由红色线段表示的多边形就是点集Q={p0,p1,...p12}的凸包。

图一 凸包问题是计算机几何的一个经典问题,它可以解决很多优化模型,目前目前求取凸包的常用算法有:穷举法,格雷厄姆扫描法(Graham),分治法,蛮力法和Jarris步进法。本文主要讨论穷举法,蛮力法,以及格雷厄姆扫描法。 二.问题分析 根据前面的描述我们先分析以下几种算法的特点: 1.穷举法 穷举法的思想很简单直接,它利用凸包性质—如果点集中的两个点的连线属于凸多边形的边,当且仅当点集中其余的点都在这两个点连线的同一侧。 假设点集合S中有n个顶点,则这n个顶点共可以构成 (1) 2 n n- 条边,对于任何一条边来讲, 检查其余的n-2 个点的相对于该直线段的正负性。如果它们有相同的正负性,说明该边是凸多边形的边,反之就不属于凸多边形,继续检查。穷举法需要执行n(n-1)/2次,再次检查n-2 个点的正负性,故算法时间复杂性为 2(1) 2 n n- ∑=3() o n。显然这并非一个高效的算法凸包 问题有许多更加有效的算法可以达到log n n的渐近时间复杂度。 算法流程图如下:

动态凸包最优算法实现及 程序演示

动态凸包最优算法实现及 程序演示 计算几何大作业 2015-6-14 计研142班范典2014210896 计算机系高性能所杨珂2014310561 计算机系高性能所曾开胜2014210957

1.程序演示说明 程序设计思路 希望实现一个带界面交互的REALTIME CONVEX HULL算法演示程序,由用户输入待求凸包的点集,分别采用OPTIMAL及DYNAMIC算法计算凸包,并将运算的实时结果与运算过程中维护的平衡树在窗口中显示。 演示程序由前端和后端两个部分组成,前端采集用户的输入信息,通过接口调用后端程序得到反馈,并将运算过程中的每个步骤按照一定的顺序呈现在界面中。后端算法接受前端界面的调用,通过两种算法实时计算当前点集对应凸包并将重点步骤以SNAPSHOT的形式储存。 程序界面概览 图 1 一组点集及其对应凸包与当前平衡树

图 2 另一组点集及其对应凸包与当前平衡树 图 3 右键菜单支持功能概览 程序功能说明 前端分为左右两个部分,左半部分为用户输入区域,可以通过鼠标点击指定下一个顶点的位置。右半部分为平衡树显示区域,显示当前凸包上各顶点在平衡树上的位置。 程序提供了三种显示模式,REALTIME模式直接显示新生成的凸包及平衡树的形状,DYNAMIC模式和OPTIMAL模式逐步显示搜索过程中每个时刻的变化,三种模式可以在过程中随时相互切换。

程序还提供了一些附加功能,比如速度调节,可以更清晰的观察到搜索的具体步骤,还支持单步的重放以及整体的重绘,功能比较完整且鲁棒,可以用于凸包算法的教学演示。 特别地,演示程序实现了输入点集与平衡树显示的互不干扰。每个步骤中被检查的关键顶点予以高亮显示。每个点的颜色不同,边界点与内部点的形状不同,以此进行区分。平衡树高度可以自适应调整等。 程序后端实现了两种不同复杂度的动态凸包算法,具体内容将在第二节中进行详细的描述。 编程环境说明 演示程序使用C++编程。大部分后端程序在Linux环境调试,前端显示部分在WINDOWS下使用VS2012平台配合OPENGL3.7完成。 2.算法原理 静态二维凸包算法 凸包(Convex Hull)是一个计算几何(图形学)中的概念。一组平面上的点,求一个包含所有点的最小的凸多边形,这就是凸包问题了。这可以形象地想成这样:在地上放置一些不可移动的木桩,用一根绳子把他们尽量紧地圈起来,并且为凸边形,这就是凸包了。在二维欧几里得空间中,凸包可想象为一条刚好包著所有点的橡皮圈。用不严谨的话来讲,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边型,它能包含点集中所有点的(具体的例子如图一所示)。

三维凸包算法的实现及其动画演示

计算几何 大作业 三维凸包算法的实现及其动画演示 实验报告 小组成员: 软件学院 2014213460 孙聪 软件学院 2014213517 高莹

目录 1 程序演示说明 (1) 1.1网页服务器配置及项目运行说明 (1) 1.2 项目使用操作说明 (2) 1.3 动画说明 (7) 2算法与数据结构 (13) 2.1 储存网格模型的数据结构 (13) 2.2 朴素的增量法构造凸包 (15) 2.3 礼品包装法构造凸包 (17) 2.4 冲突图法构造凸包 (19) 2.5 分治法构造凸包 (20) 3性能测试 (24) 4参考文献 (25)

1 程序演示说明 本次实验采用js和html编写。除了打开保存文件功能(需配置服务器方能正常执行)之外,其余功能均可通过直接使用浏览器打开convex_demo.html文件得以体现。 注:因使用webgl技术,所以请使用各主流浏览器的较新版本的浏览器浏览。否则,可能出现无法正常显示与执行的情况。经测试,在较新版本的IE及Chrome浏览器下表现正常。 无论实在透视投影还是正交投影下,鼠标左键拖动为旋转几何体;右键拖动为移动几何体;鼠标滚轮控制视点的远近。 1.1网页服务器配置及项目运行说明 本项目在不同操作系统下,只需正确安装启动及设置Web服务器后,所有功能均可正常运行。 1.软件安装 1)软件下载地址https://www.360docs.net/doc/6b17740004.html,/ 2)服务器启动问题说明:安装完成后,打开xampp控制面板,启动Apache。

①若因端口80占用启动失败,则点击Config,选择Apache(httpd.conf)打开,修改端口。 修改“Listen 80”为“Listen 8081”; 修改“ServerName localhost:80”为“ServerName localhost:8081”; ②若因端口443占用启动失败,在Apache配置文件httpd.conf中,去掉“Include "conf/extra/httpd-ssl.conf"” 或者将占用相应端口的进程杀死,则不用修改相应的配置文件。 2.项目运行说明 1)将工程目录放在xampp安装目录/htdocs中 2)启动Apache服务器。 3)打开较新版本的IE及Chrome浏览器浏览器 输入localhost:80/ConvexHull/src/convex_demo.html 注:若前面修改过服务器端口,则需将80替换为修改的端口号 1.2 项目使用操作说明 1.点集操作 点集控制部分可以初始化需要生成凸包的点。

凸包成形冲模设计

凸包成形冲模设计https://www.360docs.net/doc/6b17740004.html,/Sheetmatal/Article60603_2.htm l 产品形状 在钣金产品上经常可以看到一些高度较高的凸包,如图1所示。 2 成形方法 产品的凸包高度H比较高,在一次抽凸成形时容易拉破。为了避免发生拉破现象,保证产品成形以后的形状尺寸,一般要分两步成形。 第1步:抽弧形。如图2所示,注意以下几个重点。 (1)产品抽弧成形后的c和d两点间的周长L1。(由3段弧长相加)应稍大于产品要求的断面中a和b两点间的周长L2(a和b参见图1),一般L1=L2+(0.2—0.8)mm。 (2)下模镶块c和d两点间的直线距离等于产品要求的断面中a和b两点间的直线距离 D5。 (3)闭模时保证图2中半径为r1的圆弧与下模最小间隙为产品材料厚度的60%(Tx60%)。 第2步:整形。

有两种不同的整形方法。如图3和图4,一般用图3方法,凸包外形要求不高时用图4方法。 3 确定抽弧形时凸模尺寸的步骤和方法 (1)根据产品要求的形状和尺寸确定下模镶块内孔的形状尺寸,如图5所示。 注意:①c和d点间的直线距离等于产品要求的断面中a和b两点的直线距离D5; ②镶块内孔中圆弧半径rl的大小一般在1~3mm之间(含1mm和3mm,以0.5mm为一阶)。初步确定取r1等于产品断面中相应处的半径。 (2)初步产品抽弧形时的外形尺寸: ①如图6所示,以3点(下与下模镶块内孔两r1圆弧的切点及抽凸底部的中点g作圆; ②经过修剪如图7所示,测出点c和点d间3段圆弧的总长度L1; ③如果此3段弧总长L1小于产品要求的断面中a和b两点间的周长L2,则通过把抽凸底部中点g向下移动一段距离h(h可以0.5mm为一阶)后得出点H,重新过3点作圆,如图8所示; ④重复以上两个步骤画弧,直到弧长满足Ll=L2+(0.2-0.8)mm。如此即可求出产品抽弧形时的外形尺寸。

相关文档
最新文档