UVA 11769 All Souls Night 三维凸包求表面积

题目链接:点击打开链接

求给定的3维坐标的凸包的表面积

三维凸包裸题。。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
#define PR 1e-8
#define N 510
struct TPoint{
	double x, y, z;
	TPoint(){}
	TPoint(double _x, double _y, double _z):x(_x), y(_y), z(_z){}
	TPoint operator-(const TPoint p){return TPoint(x-p.x, y-p.y, z-p.z);}
	TPoint operator*(const TPoint p){return TPoint(y*p.z-z*p.y, z*p.x-x*p.z, x*p.y-y*p.x);}
	double operator^(const TPoint p){return x*p.x+y*p.y+z*p.z;}
};
struct fac{
	int a, b, c;
	bool ok;
};
struct T3dhull{
	int n;
	TPoint ply[N];
	int trianglecnt;
	fac tri[N];
	int vis[N][N];
	double dist(TPoint a){return sqrt(a.x*a.x+a.y*a.y+a.z*a.z);}
	double area(TPoint a, TPoint b, TPoint c)
	{ return dist((b-a)*(c-a));}
	double volume(TPoint a, TPoint b, TPoint c, TPoint d)
	{ return (b-a)*(c-a)^(d-a);}
	double ptoplane(TPoint &p, fac &f)
	{
		TPoint m = ply[f.b] - ply[f.a], n = ply[f.c]-ply[f.a], t = p-ply[f.a];
		return (m*n)^t;
	}
	void deal(int p, int a, int b){
		int f = vis[a][b];
		fac add;
		if(tri[f].ok)
		{
			if((ptoplane(ply[p], tri[f])) > PR)
				dfs(p, f);
			else
			{
				add.a = b, add.b = a, add.c = p, add.ok = 1;
				vis[p][b] = vis[a][p] = vis[b][a] = trianglecnt;
				tri[trianglecnt++] = add;
			}
		}
	}
	void dfs(int p, int cnt) {
		tri[cnt].ok = 0;
		deal(p, tri[cnt].b, tri[cnt].a);
		deal(p, tri[cnt].c, tri[cnt].b);
		deal(p, tri[cnt].a, tri[cnt].c);
	}
	bool same(int s, int e) {
		TPoint a = ply[tri[s].a], b = ply[tri[s].b], c = ply[tri[s].c];
		return fabs(volume(a,b,c,ply[tri[e].a])) < PR
			&& fabs(volume(a,b,c,ply[tri[e].b])) < PR
			&& fabs(volume(a,b,c,ply[tri[e].c])) < PR;
	}
	void construct()
	{
		int i, j;
		trianglecnt = 0;
		if(n<4) return ;
		bool tmp = true;
		for(i = 1; i < n; i++)
		{
			if((dist(ply[0]-ply[i])) > PR)
			{
				swap(ply[1], ply[i]);
				tmp = false;
				break;
			}
		}
		if(tmp)return ;
		tmp = true;
		for(i = 2; i < n; i++)
		{
			if((dist((ply[0]-ply[1])*(ply[1]-ply[i]))) > PR)
			{
				swap(ply[2], ply[i]);
				tmp = false;
				break;
			}
		}
		if(tmp) return ;
		tmp = true;
		for(i = 3; i < n; i++)
		{
			if(fabs((ply[0]-ply[1])*(ply[1]-ply[2])^(ply[0]-ply[i]))>PR)
			{
				swap(ply[3], ply[i]);
				tmp =false;
				break;
			}
		}
		if(tmp)return ;
		fac add;
		for(i = 0; i < 4; i++)
		{
			add.a = (i+1)%4, add.b = (i+2)%4, add.c = (i+3)%4, add.ok = 1;
			if((ptoplane(ply[i], add))>0)
				swap(add.b, add.c);
			vis[add.a][add.b] = vis[add.b][add.c] = vis[add.c][add.a] = trianglecnt;
			tri[trianglecnt++] = add;
		}
		for(i = 4; i < n; i++)
		{
			for(j = 0; j < trianglecnt; j++)
			{
				if(tri[j].ok && (ptoplane(ply[i], tri[j])) > PR)
				{
					dfs(i, j); break;
				}
			}
		}
		int cnt = trianglecnt;
		trianglecnt = 0;
		for(i = 0; i < cnt; i++)
		{
			if(tri[i].ok)
				tri[trianglecnt++] = tri[i];
		}
	}
	double area()
	{
		double ret = 0;
		for(int i = 0; i < trianglecnt; i++)
			ret += area(ply[tri[i].a], ply[tri[i].b], ply[tri[i].c]);
		return ret/2.0;
	}
	double volume()
	{
		TPoint p(0,0,0);
		double ret = 0;
		for(int i = 0; i < trianglecnt; i++)
			ret += volume(p, ply[tri[i].a], ply[tri[i].b], ply[tri[i].c]);
		return fabs(ret/6);
	}
}hull;

int main(){
	int Cas = 1;
	while(scanf("%d",&hull.n), hull.n){
		int i ;
		for(i = 0; i < hull.n; i++)
			scanf("%lf %lf %lf",&hull.ply[i].x, &hull.ply[i].y, &hull.ply[i].z);
		hull.construct();
		printf("Case %d: %.2lf\n", Cas++, hull.area());
	}
	return 0;
}

UVA 11769 All Souls Night 三维凸包求表面积

时间: 2024-08-04 12:53:17

UVA 11769 All Souls Night 三维凸包求表面积的相关文章

POJ 2225 / ZOJ 1438 / UVA 1438 Asteroids --三维凸包,求多面体重心

题意: 两个凸多面体,可以任意摆放,最多贴着,问他们重心的最短距离. 解法: 由于给出的是凸多面体,先构出两个三维凸包,再求其重心,求重心仿照求三角形重心的方式,然后再求两个多面体的重心到每个多面体的各个面的最短距离,然后最短距离相加即为答案,因为显然贴着最优. 求三角形重心见此: http://www.cnblogs.com/whatbeg/p/4234518.html 代码:(模板借鉴网上模板) #include <iostream> #include <cstdio> #in

uva 10065 (凸包+求面积)

链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=&problem=1006 Problem A Useless Tile Packers Input: standard input Output: standard output Yes, as you have apprehended the Useless Tile Pac

UVA 152-Tree&#39;s a Crowd(暴力求解三维坐标求最短距离)

Tree's a Crowd Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Description  Tree's a Crowd  Dr William Larch, noted plant psychologist and inventor of the phrase ``Think like a tree--Think Fig'' has invented a new

POJ 3528 求三维凸包表面积

也是用模板直接套的题目诶 //#pragma comment(linker, "/STACK:16777216") //for c++ Compiler #include <stdio.h> #include <iostream> #include <cstring> #include <cmath> #include <stack> #include <queue> #include <vector>

POJ3528 HDU3662 三维凸包模板

POJ3528 HDU3662 第一道题 给定若干点 求凸包的表面积,第二题 给定若干点就凸包的面数. 简单说一下三维凸包的求法,首先对于4个点假设不共面,确定了唯一四面体,对于一个新的点,若它不在四面体内,为了让它进入凸包, 则对于所有凸包上的边,若边的一面是该点可以看到的而另一面看不到,则该点与该边构成的面要加入凸包. 模板代码非常清晰, #include<stdio.h> #include<algorithm> #include<string.h> #includ

hdu4266(三维凸包模板题)

/*给出三维空间中的n个顶点,求解由这n个顶点构成的凸包表面的多边形个数. 增量法求解:首先任选4个点形成的一个四面体,然后每次新加一个点,分两种情况: 1> 在凸包内,则可以跳过 2> 在凸包外,找到从这个点可以"看见"的面,删除这些面, 然后对于一边没有面的线段,和新加的这个点新建一个面,至于这个点可以看见的面, 就是求出这个面的方程(可以直接求法向量). */ #include<iostream> #include<cmath> #includ

hdu4449Building Design(三维凸包+平面旋转)

链接 看了几小时也没看懂代码表示的何意..无奈下来问问考研舍友. 还是考研舍友比较靠谱,分分钟解决了我的疑问. 可能三维的东西在纸面上真的不好表示,网上没有形象的题解,只有简单"明了"的讲解. 这题说起来很简单,求下三维凸包,枚举每一个面,进行坐标旋转,使得当前面作为xoy面时的其他坐标,然后求下投影面的凸包的面积. 为什么要旋转面而不直接算点到面的距离,是因为投影的面积没有办法算. 面旋转时是怎么旋转的,首先求得当前面的法向量p1,再求得它与向量e(0,0,1)的法向量pp,所有的点

sgu290:Defend the Milky Way(三维凸包)

题目大意: 给出空间中 n(1≤n≤100) 个点,求出其凸包.如果有点在凸包的面或棱上,也要将其算进凸包中,将答案按字典序输出. 分析: 首先我就不吐槽 sgu 坑爹的输入了... 主要就是求解三维凸包,至于凸包面或棱上的点可以在求出凸包后再加进去.凸包上每个面都是三角形,如果在平面中就类似三角剖分一般. 这里采用的是O(n2)的增量法,主要算法流程就是: (1) 初始化一个未退化的四面体: (2) 如果新点在凸包内或凸包上,忽视掉: (3) 如果新点在凸包外,删去它可以看到的面,并将其并入整

hdu 4273 2012长春赛区网络赛 三维凸包中心到最近面距离 ***

新模板 1 /* 2 HDU 4273 Rescue 3 给一个三维凸包,求重心到表面的最短距离 4 模板题:三维凸包+多边形重心+点面距离 5 */ 6 7 #include<stdio.h> 8 #include<algorithm> 9 #include<string.h> 10 #include<math.h> 11 #include<stdlib.h> 12 using namespace std; 13 const int MAXN=