hdu4266(三维凸包模板题)
/*给出三维空间中的n个顶点,求解由这n个顶点构成的凸包表面的多边形个数.
增量法求解:首先任选4个点形成的一个四面体,然后每次新加一个点,分两种情况:
1> 在凸包内,则可以跳过
2> 在凸包外,找到从这个点可以"看见"的面,删除这些面,
然后对于一边没有面的线段,和新加的这个点新建一个面,至于这个点可以看见的面,
就是求出这个面的方程(可以直接求法向量).
*/
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int MAXN=;
const double EPS=1e-;
struct Point
{
double x,y,z;
Point(){}
Point(double xx,double yy,double zz):x(xx),y(yy),z(zz){} Point operator -(const Point p1) //两向量之差
{
return Point(x-p1.x,y-p1.y,z-p1.z);
} Point operator *(Point p) //叉乘
{
return Point(y*p.z-z*p.y,z*p.x-x*p.z,x*p.y-y*p.x);
} double operator ^(Point p) //点乘
{
return (x*p.x+y*p.y+z*p.z);
}
void read()
{
scanf("%lf%lf%lf",&x,&y,&z);
}
};
struct CH3D
{
struct face
{
int a,b,c; //表示凸包一个面上三个点的编号
bool ok; //表示该面是否属于最终凸包中的面
}; int n; //初始顶点数
Point P[MAXN]; //初始顶点 int num; //凸包表面的三角形数
face F[*MAXN]; int g[MAXN][MAXN]; //凸包表面的三角形 double vlen(Point a) //向量长度
{
return sqrt(a.x*a.x+a.y*a.y+a.z*a.z);
} Point cross(const Point &a, const Point &b, const Point &c) //叉乘
{
return Point((b.y-a.y)*(c.z-a.z)-(b.z-a.z)*(c.y-a.y),-((b.x-a.x)*(c.z-a.z)
-(b.z-a.z)*(c.x-a.x)),(b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x));
}
double area(Point a,Point b,Point c) //三角形面积*2
{
return vlen((b-a)*(c-a));
} double volume(Point a,Point b,Point c,Point d) //四面体有向体积*6
{
return (b-a)*(c-a)^(d-a);
} double dblcmp(Point &p,face &f) //正:点在面同向
{
Point m=P[f.b]-P[f.a];
Point n=P[f.c]-P[f.a];
Point t=p-P[f.a];
return (m*n)^t;
} void deal(int p,int a,int b)
{
int f=g[a][b];
face add;
if(F[f].ok)
{
if(dblcmp(P[p],F[f])>EPS)
dfs(p,f);
else
{
add.a=b;
add.b=a;
add.c=p;
add.ok=;
g[p][b]=g[a][p]=g[b][a]=num;
F[num++]=add;
}
}
} void dfs(int p,int now)
{
F[now].ok=;
deal(p,F[now].b,F[now].a);
deal(p,F[now].c,F[now].b);
deal(p,F[now].a,F[now].c);
} bool same(int s,int t)
{
Point &a=P[F[s].a];
Point &b=P[F[s].b];
Point &c=P[F[s].c];
return fabs(volume(a,b,c,P[F[t].a]))<EPS && fabs(volume(a,b,c,P[F[t].b]))<EPS
&& fabs(volume(a,b,c,P[F[t].c]))<EPS;
} void solve() //构建三维凸包
{
int i,j,tmp;
face add;
bool flag=true;
num=;
if(n<)
return;
for(i=;i<n;i++) //此段是为了保证前四个点不共面,若以保证,则可去掉
{
if(vlen(P[]-P[i])>EPS)
{
swap(P[],P[i]);
flag=false;
break;
}
}
if(flag)
return;
flag=true;
for(i=;i<n;i++) //使前三点不共线
{
if(vlen((P[]-P[])*(P[]-P[i]))>EPS)
{
swap(P[],P[i]);
flag=false;
break;
}
}
if(flag)
return;
flag=true;
for(i=;i<n;i++) //使前四点不共面
{
if(fabs((P[]-P[])*(P[]-P[])^(P[]-P[i]))>EPS)
{
swap(P[],P[i]);
flag=false;
break;
}
}
if(flag)
return;
for(i=;i<;i++)
{
add.a=(i+)%;
add.b=(i+)%;
add.c=(i+)%;
add.ok=true;
if(dblcmp(P[i],add)>)
swap(add.b,add.c);
g[add.a][add.b]=g[add.b][add.c]=g[add.c][add.a]=num;
F[num++]=add;
}
for(i=;i<n;i++)
{
for(j=;j<num;j++)
{
if(F[j].ok && dblcmp(P[i],F[j])>EPS)
{
dfs(i,j);
break;
}
}
}
tmp=num;
for(i=num=;i<tmp;i++)
if(F[i].ok)
{
F[num++]=F[i];
}
} double area() //表面积
{
double res=0.0;
if(n==)
{
Point p=cross(P[],P[],P[]);
res=vlen(p)/2.0;
return res;
}
for(int i=;i<num;i++)
res+=area(P[F[i].a],P[F[i].b],P[F[i].c]);
return res/2.0;
} double volume() //体积
{
double res=0.0;
Point tmp(,,);
for(int i=;i<num;i++)
res+=volume(tmp,P[F[i].a],P[F[i].b],P[F[i].c]);
return fabs(res/6.0);
} int triangle() //表面三角形个数
{
return num;
} int polygon() //表面多边形个数
{
int i,j,res,flag;
for(i=res=;i<num;i++)
{
flag=;
for(j=;j<i;j++)
if(same(i,j))
{
flag=;
break;
}
res+=flag;
}
return res;
}
Point getcent()//求凸包质心
{
Point ans(,,),temp=P[F[].a];
double v = 0.0,t2;
for(int i=;i<num;i++){
if(F[i].ok == true){
Point p1=P[F[i].a],p2=P[F[i].b],p3=P[F[i].c];
t2 = volume(temp,p1,p2,p3)/6.0;//体积大于0,也就是说,点 temp 不在这个面上
if(t2>){
ans.x += (p1.x+p2.x+p3.x+temp.x)*t2;
ans.y += (p1.y+p2.y+p3.y+temp.y)*t2;
ans.z += (p1.z+p2.z+p3.z+temp.z)*t2;
v += t2;
}
}
}
ans.x /= (*v); ans.y /= (*v); ans.z /= (*v);
return ans;
}
double function(Point fuck){//点到凸包上的最近距离(枚举每个面到这个点的距离)
double min=;
for(int i=;i<num;i++){
if(F[i].ok==true){
Point p1=P[F[i].a] , p2=P[F[i].b] , p3=P[F[i].c];
double a = ( (p2.y-p1.y)*(p3.z-p1.z)-(p2.z-p1.z)*(p3.y-p1.y) );
double b = ( (p2.z-p1.z)*(p3.x-p1.x)-(p2.x-p1.x)*(p3.z-p1.z) );
double c = ( (p2.x-p1.x)*(p3.y-p1.y)-(p2.y-p1.y)*(p3.x-p1.x) );
double d = ( -(a*p1.x+b*p1.y+c*p1.z) );
double temp = fabs(a*fuck.x+b*fuck.y+c*fuck.z+d)/sqrt(a*a+b*b+c*c);
if(temp<min)min = temp;
}
}
return min;
} }; int main()
{
int n;
while(scanf("%d",&n) && n)
{
CH3D hull;
hull.n=n;
for(int i=;i<n;i++)
{
hull.P[i].read();
}
hull.solve();
int q;
scanf("%d",&q);
for(int i=;i<q;i++)
{
Point tp;
tp.read();
double ans=1e9;
ans = min(ans, hull.function(tp) );
printf("%.4lf\n",ans);
}
}
return ;
}
求点到三维凸包的最小距离,直接用模板暴力枚举即可。
hdu4266(三维凸包模板题)的更多相关文章
- POJ3528 HDU3662 三维凸包模板
POJ3528 HDU3662 第一道题 给定若干点 求凸包的表面积,第二题 给定若干点就凸包的面数. 简单说一下三维凸包的求法,首先对于4个点假设不共面,确定了唯一四面体,对于一个新的点,若它不在四 ...
- POJ 3348 Cows | 凸包模板题
题目: 给几个点,用绳子圈出最大的面积养牛,输出最大面积/50 题解: Graham凸包算法的模板题 下面给出做法 1.选出x坐标最小(相同情况y最小)的点作为极点(显然他一定在凸包上) 2.其他点进 ...
- hdu 1348 Wall(凸包模板题)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1348 Wall Time Limit: 2000/1000 MS (Java/Others) M ...
- POJ:Dungeon Master(三维bfs模板题)
Dungeon Master Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 16748 Accepted: 6522 D ...
- HDU 1392 凸包模板题,求凸包周长
1.HDU 1392 Surround the Trees 2.题意:就是求凸包周长 3.总结:第一次做计算几何,没办法,还是看了大牛的博客 #include<iostream> #inc ...
- POJ 1113 凸包模板题
上模板. #include <cstdio> #include <cstring> #include <iostream> #include <algorit ...
- bzoj1670 Usaco2006 Building the Moat护城河的挖掘 [凸包模板题]
Description 为了防止口渴的食蚁兽进入他的农场,Farmer John决定在他的农场周围挖一条护城河.农场里一共有N(8<=N<=5,000)股泉水,并且,护城河总是笔直地连接在 ...
- UVA 11769 All Souls Night 的三维凸包要求的表面面积
主题链接:option=com_onlinejudge&Itemid=8&page=show_problem&problem=2869">点击打开链接 求给定的 ...
- hdu 1348 凸包模板
http://acm.hdu.edu.cn/showproblem.php?pid=1348 造城墙问题,求出凸包加上一圈圆的周长即可 凸包模板题 #include <cstdio> #i ...
随机推荐
- ExtentReports 结合 TestNg 生成自动化 html 报告 (支持多 suite)
转载:https://testerhome.com/topics/8134 重要说明:报告监听器源码修复一些bug,不再此处更新代码,最新代码可以到github查看最新报告监听器源码 前几天分享了ht ...
- puppeteer 相关知识
page.waitForNavigation: 但我们通过代码执行到页面跳转时,我们需要等待跳转完成再作其他事情.使用page.waitForNavigation会等待跳转完成.(一般作用在点击链接或 ...
- Crontab命令--Linux
Crontab命令--定时任务 命令格式 Example:
- Gherkin关键字
Feature 功能 Background 背景 Scenario 场景 Outline Scenarios(or Examples) Given 假如.假设.假定 When 当 Then 那么 An ...
- Python MySQLdb 使用utf-8 编码插入中文数据
参考地址:http://blog.csdn.net/dkman803/article/details/1925326/ 本人在使用python,mysqldb操作数据库的时候,发现如下问题,编码如下: ...
- oracle的一些问题
好久时间没有用oracle,这次因为有个项目的需要,又重新温习了一下oracle. 我使用的oracle的版本是windows oracle 11g_R2. 首先先说一下安装.这个没有太大的问题,主要 ...
- 189. Rotate Array【easy】
189. Rotate Array[easy] Rotate an array of n elements to the right by k steps. For example, with n = ...
- 关于extern的说明
extern的作用: extern可置于变量或者函数前,以表示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义. 声明外部变量 现代编译器一般采用按文件编译的方式 ...
- App打包上架流程(iOS转)
由于苹果的机制,在非越狱机器上安装应用必须通过官方的Appstore, 开发者开发好应用后上传Appstore,也需要通过审核等环节. AppCan作为一个跨主流平台的一个开发平台,也对ipa包上传A ...
- 小米Note全网通支持7模19频:先发标准版
2015-06-26 16:42:53 17749 次阅读 9 次推荐 稿源:安卓中国 43 条评论 感谢安卓中国的投递 自古一入电信深似海,从此手机没法买.现在首台全网通小米手机即将诞生.6 月 2 ...