`

计算几何_三维凸包(3d convex hull)

阅读更多

const double eps = 1e-8;
typedef list<int>::iterator liit;
inline int sign(double d){
	if(d < -eps) return -1;
	return (d > eps) ? 1 : 0;
}
struct point{
	double x, y, z;
	point(double _x=0, double _y=0, double _z=0):x(_x), y(_y), z(_z) {}
	void read(){ scanf("%lf%lf%lf", &x, &y, &z); }
	bool operator==(const point& tp){
		return (!sign(x-tp.x)) && (!sign(y-tp.y)) && (!sign(z-tp.z));
	}
	bool isOrg(){
		return !sign(x) && !sign(y) && !sign(z);
	}
	point operator-(point tp){
		return point(x-tp.x, y-tp.y, z-tp.z);
	}
};
struct face{
	list<int> pos;
	point v;  //法向量
	double d; //常量
};
inline bool cmp(point p1, point p2){
	return (p1.x < p2.x) || (p1.x == p2.x && p1.y < p2.y)
		|| (p1.x == p2.x && p1.y == p2.y && p1.z < p2.z);
}
//向量st-->ed1和st-->ed2的叉积
inline point xmul3d(point st, point ed1, point ed2){
	ed1 = ed1 - st;
	ed2 = ed2 - st;
	return point(ed1.y*ed2.z-ed2.y*ed1.z, ed1.z*ed2.x-ed2.z*ed1.x,
		ed1.x*ed2.y-ed2.x*ed1.y);
}
//向量(0,0)-->p1和(0,0)-->ed2的叉积
inline double dmul3d(point p1, point p2){
	return p1.x*p2.x+p1.y*p2.y+p1.z*p2.z;
}
inline double dist3d(point p1, point p2){
	return sqrt((p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y)
		+ (p1.z-p2.z)*(p1.z-p2.z));
}
//三维凸包类
struct convex3d{
	static const int N = 305;  //点的数目的最大值
	point ps[N];       //求解凸包的点集
	list<face> convex; //convex存储三维的凸包的各个面,这些面是三维空间的凸多边形
	int pn;            //点的个数
	int fsign[N][N];
	//添加由ps里的第a,b,c个点组成的面
	void addFace(int a, int b, int c){
		face tf;
		tf.pos.push_back(a);
		tf.pos.push_back(b);
		tf.pos.push_back(c);
		tf.v = xmul3d(ps[a], ps[b], ps[c]);
		tf.d = -dmul3d(ps[a], tf.v);
		convex.push_back(tf);
	}
	//插入第i个点是,对面f进行处理
	int handleFace(face f, int i){
		int s = sign(dmul3d(f.v, ps[i]) + f.d);
		liit now, nxt;
		now = f.pos.begin();
		nxt = f.pos.begin();
		nxt++;
		for(; nxt != f.pos.end(); nxt++, now++){
			fsign[*now][*nxt] = s;
		}
		fsign[*now][*f.pos.begin()] = s;
		return s;
	}
	//判断第i个点是否在f里面
	bool inFace(face f, int i){
		liit now, nxt;
		int pn, nn, s;
		now = f.pos.begin();
		nxt = f.pos.begin();
		nxt++;
		for(pn = nn = 0; nxt != f.pos.end(); nxt++, now++){
			s = sign(dmul3d(xmul3d(ps[*now], ps[*nxt], ps[i]), f.v));
			if(s == 1) pn++;
			else if(s == -1) nn++;
		}
		s = sign(dmul3d(xmul3d(ps[*now], ps[*f.pos.begin()], ps[i]), f.v));
		if(s == 1) pn++;
		else if(s == -1) nn++;
		if(pn >= 1 && nn >= 1) return false;
		return true;
	}
	//扩展面f,返回true表示需要删除当前的面
	bool extFace(face& f, int i){
		liit now, nxt;
		bool flag = false;
		now = f.pos.begin();
		nxt = f.pos.begin();
		nxt++;
		if(fsign[*now][*nxt] == 0){
			list<int> tpos;
			while(true){
				if(sign(dmul3d(xmul3d(ps[i], ps[*now], ps[*nxt]), f.v)) >= 1){
					break;
				}
				now++;
				if(now == f.pos.end()) now = f.pos.begin();
				nxt++;
				if(nxt == f.pos.end()) nxt = f.pos.begin();
			}
			tpos.push_back(*now);
			int st = *now;
			while(*nxt != st){
				if(sign(dmul3d(xmul3d(ps[*now], ps[i], ps[*nxt]), f.v)) >= 0){
					break;
				}
				tpos.push_back(*nxt);
				now++;
				if(now == f.pos.end()) now = f.pos.begin();
				nxt++;
				if(nxt == f.pos.end()) nxt = f.pos.begin();
			}
			tpos.push_back(i);
			while(true){
				now++;
				if(now == f.pos.end()) now = f.pos.begin();
				nxt++;
				if(nxt == f.pos.end()) nxt = f.pos.begin();
				if(*now == st) break;
				if(sign(dmul3d(xmul3d(ps[i], ps[*now], ps[*nxt]), f.v)) >= 1){
					tpos.push_back(*now);
				}
			}
			f.pos = tpos;

		}else if(fsign[*now][*nxt] > 0){
			for(; nxt != f.pos.end(); now++, nxt++){
				if(fsign[*nxt][*now] < 0){
					addFace(*now, *nxt, i);
				}
			}
			if(fsign[*f.pos.begin()][*now] < 0){
				addFace(*now, *f.pos.begin(), i);
			}
			flag = true;
		}
		return flag;
	}
	//对ps里的pn个点求最小包围多面体,结果放在convex中
	void initConvex(){
		sort(ps, ps+pn, cmp);
		pn = unique(ps, ps+pn) - ps;
		convex.clear();
		if(pn <= 2){
			return;
		}
		int a, b, c;
		double ab, bc, ac;
		a = 0;
		b = 1;
		for(c = 2; c < pn; c++){
			ab = dist3d(ps[a], ps[b]);
			bc = dist3d(ps[b], ps[c]);
			ac = dist3d(ps[a], ps[c]);
			if(sign(ab+bc-ac) == 0){
				b = c;
			}else if(sign(ab+ac-bc) == 0){
				a = c;
			}else if(sign(ac+bc-ab) != 0){
				break;
			}
		}
		if(c == pn){
			return;
		}
		int i, size, j;
		list<face>::iterator it;
		addFace(a, b, c);
		addFace(a, c, b);
		for(i = c+1; i < pn; i++){
			size = convex.size();
			for(it = convex.begin(), j = 0; j < size; j++, it++){
				if(handleFace(*it, i) == 0 && inFace(*it, i)){
						break;
				}
			}
			if(j < size) continue;
			for(it = convex.begin(), j = 0; j < size; j++){
				if(extFace(*it, i)){
					it = convex.erase(it);
				}else{
					it++;
				}
			}
		}
	}
};
 
0
0
分享到:
评论

相关推荐

    计算三维convex hull凸体体积和面积的程序

    在计算机图形学、几何建模以及数据可视化等领域,计算三维空间中的Convex Hull(凸包)体积和面积是一个非常重要的任务。Convex Hull是指一个包含给定点集的所有点,并且该集合中的任何两点之间的线段也完全位于该...

    Implementation of convex hull.rar_matlab 快速凸包_凸包_凸包 matlab_凸包算法

    在计算机科学和图形学中,凸包(Convex Hull)是一个重要的概念,它是包含所有点的最小凸多边形。在MATLAB中实现凸包算法,可以有效地处理一系列几何问题,如碰撞检测、图像处理和机器学习等。本教程将详细介绍如何在...

    TuBao.rar_convex hull Visual C_凸包_凸包2_快速凸包_点集凸包

    在计算机科学领域,凸包(Convex Hull)是几何计算中的一个重要概念,它是指一个包含在二维或三维空间中所有点的最小凸多边形。在这个项目“TuBao.rar”,作者实现了一个针对2维点集的凸包算法,特别强调了使用快速...

    ConvexHull:Python中的ConvexHull算法可视化

    在这个例子中,我们生成了一个随机的二维点集,然后使用`ConvexHull`函数计算了这些点的凸包。`vertices`属性则包含了构成凸包的所有顶点索引。 接下来,我们将讨论如何将这个计算过程可视化。在Python中,...

    Easy unity3d ConvexHull range detecter一个简单的unity凸/凹包范围检测

    总结来说,"Easy unity3d ConvexHull range detecter"是一个实用的工具,它结合了凸包理论和范围检测技术,使得在Unity3D中处理复杂的几何形状和交互变得更有效率。通过学习和应用这个项目,开发者可以提升自己在...

    计算凸包的graham算法.rar_C++_drinkqx7_凸包_计算凸包

    在计算机科学领域,凸包(Convex Hull)是几何学中的一个重要概念,它是指一个二维平面上一组点的最小子集,使得这个子集中任意两点的连线都包含在这组点的内部或边界上。计算凸包是许多算法的基础,如路径规划、...

    Convex_hull_problem.rar_凸包问题_凸包问题穷举

    在实际应用中,凸包问题有多种变体,如二维和三维的凸包,动态凸包(点集发生变化时更新凸包),以及最近凸包查询等。这些问题的解决方法往往需要结合数据结构,如优先队列或堆,以提高效率。 总的来说,理解和掌握...

    Convex Hull算法在c # 中实现_代码_下载

    这个多边形可以是二维平面上的点集,也可以是三维空间中的点集。在实际应用中,例如碰撞检测、路径规划、图像处理等领域,凸包算法有着广泛的应用。 在C#编程语言中,实现凸包算法可以帮助我们快速地找出一组点的...

    MATLAB工具箱大全-Qhull(二维三维三角分解、泰森图)凸包工具箱

    MATLAB工具箱大全中的Qhull是一个强大的计算几何库,主要功能是进行二维和三维的三角分解、泰森图的生成以及凸包的构建。Qhull在MATLAB中的应用,为用户提供了处理复杂几何数据集的有效手段,尤其在数据分析、计算机...

    Convex Hull Algorithms——凸壳算法

    在计算机科学领域,特别是几何计算方面,**凸壳算法**是一种重要的数据结构处理技术,用于寻找一组二维平面上点集的最小凸多边形(即凸壳)。该文探讨了几种**原地**(In-Place)算法来计算平面点集的凸壳。所谓**...

    tubao.rar_凸包算法_点集凸包

    凸包算法是计算机科学中的一种几何算法,主要应用于二维或三维空间中的点集。这个算法的目的是找到一个最小的多边形(二维中是多边形,三维中是多面体),该多边形可以完全包围给定点集,且边界上的点均在点集内或者...

    matlab凸包算法.pdf文件

    1. `k = convhull(P)`:计算矩阵`P`中点的二维或三维凸包,其中`P`的每一列代表一个点的坐标。 2. `k = convhull(x,y)`:计算列向量`x`和`y`中点的二维凸包,分别代表点的x坐标和y坐标。 3. `k = convhull(x,y,z)`:...

    3D 凸包的面积和体积:3D 凸包的体积和面积。-matlab开发

    在三维空间中,凸包(Convex Hull)是包含所有给定点的一个最小的凸多面体,它将这些点包裹在内部。对于3D凸包的研究,主要关注两个关键属性:面积和体积。这两个参数提供了关于凸包形状和大小的重要信息。在MATLAB...

    基于C++浅谈几何学与计算机的交叉应用【100011493】

    就计算机在几何学领域的应用,本文介绍了四色定理(Four Color Theorem)及其历史与机器证明,以及四色问题的求解.就几何学在计算机领域的应用,本文介绍了三维凸包(convex hull)表面积问题的求解.

    The Quickhull algorithm for convex hulls 快速凸包生成算法

    在三维甚至更高维度中,凸包的构建对于许多应用,如图形学、机器学习和数据分析,都是至关重要的。 在"The Quickhull algorithm for convex hulls"这篇文献中,作者深入探讨了算法的细节,包括算法的实现、性能分析...

    ConvexHull:返回3D空间中点的凸包

    同样地,在3D空间中,凸包是由点集构成的最小凸多面体,即能覆盖所有点的最小三维几何结构。 在C语言中实现凸包算法,通常有以下几种方法: 1. **Graham扫描算法**:这是最常用的一种算法,适用于2D空间。首先找到...

    ConvexHull:带有用 C++ 实现的凸包算法的控制台应用程序-开源

    在计算机科学领域,凸包(Convex Hull)算法是一种重要的几何计算方法,它用于找到一组点在二维或三维空间中的最小凸多边形,该多边形包含所有这些点。这个给定的开源项目名为“ConvexHull”,提供了一个用C++编写的...

    CGAL模型凸包计算-C++代码+详细说明文档

    CGAL库不仅提供了这些算法,还封装了相关的数据结构,如Point_3表示三维点,Plane_3表示三维平面,以及Convex_hull_3类用于构建和操作凸包。通过这些数据结构和算法,开发者可以轻松地实现对3D模型的凸包计算,而...

    【OpenCv基础】第三十九讲 凸包检测.zip

    在OpenCV中,实现凸包检测通常使用`cv2.convexHull()`函数。这个函数可以对输入的点集进行处理,返回这些点构成的最小凸多边形。在实际应用中,我们首先需要对图像进行预处理,比如二值化、边缘检测(如Canny算法或...

    根据已知顶点求构成凸包的顶点集合(C#)

    在计算机图形学中,凸包(Convex Hull)是包含一组点的最大凸多边形,它在二维空间中是由这些点形成的一个最小面积的封闭多边形。本篇将详细讲解如何利用C#语言来实现根据已知顶点集合求解凸包的方法,特别是采用扫描...

Global site tag (gtag.js) - Google Analytics