三维凸包

/*
增量法求凸包。选取一个四面体,同时把它各面的方向向量向外,增加一个点时,若该点与凸包上的某些面的方
向向量在同一侧,则去掉那些面,并使某些边与新增点一起连成新的凸包上的面。
*/ #include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath> using namespace std;
const int MAXN=550;
const double eps=1e-8;
struct point {
double x,y,z;
};
struct face {
int a,b,c;
bool ok;
};
int n; //初始点数
point p[MAXN]; //空间点
int trianglecnt; //凸包上三角形数
face tri[6*MAXN]; //凸包上被创建的三角形
int vis[MAXN][MAXN]; //点i到点j是属于哪一个三角形。此处是有方向 point operator -(const point &x, const point &y){
point ret;
ret.x=x.x-y.x; ret.y=x.y-y.y; ret.z=x.z-y.z;
return ret;
} point operator * (const point &u,const point &v){ //叉积
point ret;
ret.x=u.y*v.z-u.z*v.y;
ret.y=u.z*v.x-u.x*v.z;
ret.z=u.x*v.y-u.y*v.x;
return ret;
} double operator ^(const point &u,const point &v){
return (u.x*v.x+u.y*v.y+u.z*v.z);
} double dist(point t){
return sqrt(t.x*t.x+t.y*t.y+t.z*t.z);
} double ptoplane(point &tmp,face &f){ //若结果大于0,证明点面的同向,即法向量方向
point m=p[f.b]-p[f.a]; point n=p[f.c]-p[f.a];
point t=tmp-p[f.a];
return (m*n)^t;
} double farea(point a,point b,point c ){
point t1=a-c; point t2=b-c;
return fabs(dist(t1*t2));
}
void dfs(int pt, int ct);
void deal(int pt,int a,int b){
int f=vis[a][b]; //所属三角形,即原来的ab。
face add;
if(tri[f].ok){
if((ptoplane(p[pt],tri[f]))>eps) dfs(pt,f); //若点同样在该f三角形方向一侧,继续调整
else {
add.a=b; add.b=a; add.c=pt; add.ok=1;
vis[pt][b]=vis[a][pt]=vis[b][a]=trianglecnt;
tri[trianglecnt++]=add;
}
}
} void dfs(int pt, int ct){
tri[ct].ok=0; //去掉该面
deal(pt,tri[ct].b,tri[ct].a); //因为有向边ab所属三角形去掉,则反方向边必定属于另一个三角形.
deal(pt,tri[ct].c,tri[ct].b);
deal(pt,tri[ct].a,tri[ct].c);
} void construct (){
int i,j;
trianglecnt=0;
if(n<4) return ; //不可能构成一个多面体
bool tmp=true;
for(i=1;i<n;i++){ //不共点两点
if(dist(p[0]-p[i])>eps){
swap(p[1],p[i]); tmp=false; break;
}
}
if(tmp) return ;
tmp=true;
for(i=2;i<n;i++){ //不共线
if(dist((p[0]-p[1])*(p[1]-p[i]))>eps){
swap(p[2],p[i]); tmp=false; break;
}
}
if(tmp) return ;
tmp=true;
for(i=3;i<n;i++){ //四点不共面K
if(fabs((p[0]-p[1])*(p[1]-p[2])^(p[0]-p[i]))>eps){
swap(p[3],p[i]); tmp=false; break;
}
}
if(tmp) return ;
face 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; //等于1表示在凸包上
if(ptoplane(p[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(p[i],tri[j]))>eps){ //增加点可见该平,即在面方向一侧
dfs(i,j); break;
}
}
}
int cnt=trianglecnt;
trianglecnt=0;
for(i=0;i<cnt;i++){ //只有ok为1的才属于凸包上的三角形
if(tri[i].ok){
tri[trianglecnt++]=tri[i];
}
}
}
double area(){
double ret=0;
for(int i=0;i<trianglecnt;i++){
ret+=farea(p[tri[i].a],p[tri[i].b],p[tri[i].c]);
}
return ret/2;
} int main(){
while(scanf("%d",&n)!=EOF){
memset(vis,0,sizeof(vis));
for(int i=0;i<n;i++)
scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].z);
construct();
printf("%.3lf\n",area());
}
}

  

POJ 3528的更多相关文章

  1. poj 3528 Ultimate Weapon (3D Convex Hull)

    3528 -- Ultimate Weapon 一道三维凸包的题目,题目要求求出三维凸包的表面积.看懂了网上的三维凸包的代码以后,自己写的代码,跟网上的模板有所不同.调了一个晚上,结果发现错的只是数组 ...

  2. POJ 3528 求三维凸包表面积

    也是用模板直接套的题目诶 //#pragma comment(linker, "/STACK:16777216") //for c++ Compiler #include < ...

  3. ACM计算几何题目推荐

    //第一期 计算几何题的特点与做题要领: 1.大部分不会很难,少部分题目思路很巧妙 2.做计算几何题目,模板很重要,模板必须高度可靠. 3.要注意代码的组织,因为计算几何的题目很容易上两百行代码,里面 ...

  4. POJ 3579

    Median Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3528   Accepted: 1001 Descriptio ...

  5. POJ 3370. Halloween treats 抽屉原理 / 鸽巢原理

    Halloween treats Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 7644   Accepted: 2798 ...

  6. POJ 2356. Find a multiple 抽屉原理 / 鸽巢原理

    Find a multiple Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7192   Accepted: 3138   ...

  7. POJ 2965. The Pilots Brothers' refrigerator 枚举or爆搜or分治

    The Pilots Brothers' refrigerator Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 22286 ...

  8. POJ 1753. Flip Game 枚举or爆搜+位压缩,或者高斯消元法

    Flip Game Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 37427   Accepted: 16288 Descr ...

  9. POJ 3254. Corn Fields 状态压缩DP (入门级)

    Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9806   Accepted: 5185 Descr ...

随机推荐

  1. golang——(strings包)常用字符串操作函数

    (1)func HasPrefix(s, prefix string) bool 判断字符串s是否有前缀字符串prefix: (2)func HasSuffix(s, suffix string) b ...

  2. Too Many open files 问题排查

    问题描述:使用netty做性能测试时,并发过大造成Too Many open files问题 该类错误是因为linux系统对socket连接时需要打开的文件句柄数有限制可以通过ulimit -a 查看 ...

  3. 【DP、线段树优化】琪露诺

    跟去年(2017)PJ第四题几乎是一样的?/吐血 DP方程可以很简单的推出来,f[i]=max{f[k]}+a[i] 然而这样做是O(n^2)的 看一下数据,200000的话要不nlogn 要不n 由 ...

  4. NPM 国内镜像使用方法

    npm官方站点: http://www.npmjs.org/ 本文使用国内镜像地址: http://www.cnpmjs.org/ 搜索镜像:https://npm.taobao.org/ 具体方法: ...

  5. UOJ 129/BZOJ 4197 寿司晚宴 状压DP

    //By SiriusRen #include <cstdio> #include <algorithm> using namespace std; ; struct Node ...

  6. BZOJ 1583

    思路: 维护两个指针pointer_1和pointer_2 代表用算法一走到的位置 和算法2走到的位置 若 算法一<算法2 数组后面就插入算法一的解  pointer_1++ (记得判重) (这 ...

  7. CSS的常用属性(一)

    文本属性 font-size: 16px 文字大小 font-weight: 700 文字粗细 值从100-900 (值为700看上去加粗了) 不推荐使用font-weight: bold font- ...

  8. 溢出文本省略号的js实现

    function ellipsis(element) { var limitWidth = element.clientWidth; var temp = element.cloneNode(true ...

  9. JSON与List之间的转换

    jsonString转换为list: JSONArray jsonArray=JSONArray.fromObject(result); List<RentCar> books=(List ...

  10. 苹果双系统win8.1遇到的一些问题

    MacBook air是一款不错的电脑,详细没研究就不叙述好与坏了.只此记录自己使用这款笔记本遇到的问题. 一.安装双系统win8.1 1.下载镜像文件—>拷贝到ios内存中,一个8GU盘.ht ...