/*给出三维空间中的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(三维凸包模板题)的更多相关文章

  1. POJ3528 HDU3662 三维凸包模板

    POJ3528 HDU3662 第一道题 给定若干点 求凸包的表面积,第二题 给定若干点就凸包的面数. 简单说一下三维凸包的求法,首先对于4个点假设不共面,确定了唯一四面体,对于一个新的点,若它不在四 ...

  2. POJ 3348 Cows | 凸包模板题

    题目: 给几个点,用绳子圈出最大的面积养牛,输出最大面积/50 题解: Graham凸包算法的模板题 下面给出做法 1.选出x坐标最小(相同情况y最小)的点作为极点(显然他一定在凸包上) 2.其他点进 ...

  3. hdu 1348 Wall(凸包模板题)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1348 Wall Time Limit: 2000/1000 MS (Java/Others)    M ...

  4. POJ:Dungeon Master(三维bfs模板题)

    Dungeon Master Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 16748   Accepted: 6522 D ...

  5. HDU 1392 凸包模板题,求凸包周长

    1.HDU 1392 Surround the Trees 2.题意:就是求凸包周长 3.总结:第一次做计算几何,没办法,还是看了大牛的博客 #include<iostream> #inc ...

  6. POJ 1113 凸包模板题

    上模板. #include <cstdio> #include <cstring> #include <iostream> #include <algorit ...

  7. bzoj1670 Usaco2006 Building the Moat护城河的挖掘 [凸包模板题]

    Description 为了防止口渴的食蚁兽进入他的农场,Farmer John决定在他的农场周围挖一条护城河.农场里一共有N(8<=N<=5,000)股泉水,并且,护城河总是笔直地连接在 ...

  8. UVA 11769 All Souls Night 的三维凸包要求的表面面积

    主题链接:option=com_onlinejudge&Itemid=8&page=show_problem&problem=2869">点击打开链接 求给定的 ...

  9. hdu 1348 凸包模板

    http://acm.hdu.edu.cn/showproblem.php?pid=1348 造城墙问题,求出凸包加上一圈圆的周长即可 凸包模板题 #include <cstdio> #i ...

随机推荐

  1. $HTTP_RAW_POST_DATA 与$_POST

    出处:http://blog.163.com/gwo-cce@126/blog/static/325736492008101142422345/ 这是手册里写的 总是产生变量包含有原始的 POST 数 ...

  2. Android短信发送器(2)

    在上一篇的<Android短信发送器>当中.发送功能并不完好.当发送内容超过限定字数时,短信就会发送失败,此时就须要推断内容是否超过限制,假设不超过限制.就直接发送,反之.则对其进行处理再 ...

  3. Timus Online Judge 1057. Amount of Degrees(数位dp)

    1057. Amount of Degrees Time limit: 1.0 second Memory limit: 64 MB Create a code to determine the am ...

  4. 2D游戏平滑的迷雾战争效果

    近期刚好有做2D游戏的点光源效果,然后就扩展一下.研究了一下战争迷雾的效果.主要是想实现相似魔兽争霸那种人物走动,然后黑色的战争迷雾随着人物的移动渐渐打开的效果.使用具有渐变透明图片作为光源来使得战争 ...

  5. java之方法的重写

    方法的重写: 1.在子类中可以根据需要对从基类中继承来的方法进行重写. 2.重写的方法和被重写的方法必须具有相同方法名称.参数列表和返回类型. 3.重写方法不能使用比被重写的方法更严格的访问权限. 程 ...

  6. [1-2] 把时间当做朋友(李笑来)Chapter 2 【开启自己的心智】 摘录

    心智是可培养的.可发展的.甚至是可以重建的 早意识到,早些培养可以让自己起步更早些 审视一下我们自己,运用自己的心智,我们会知道每个人可以把自己划分为两部分:自己知道的与自己并不知道的.我们有的时候并 ...

  7. PHP-CURL在POST请求时的注意事项

    今天搞12306抢票, 在用CURL模拟POST请求校验验证码时, 无论如何12306都返回零, 正常应该返回True或者False, 最后查找原因如下 只是请求头 Content-Type 用了 a ...

  8. rational rose 2007安装破解全过程

    1:下载安装文件 下载地址: http://pan.baidu.com/s/1c0ldKEs 2:下载虚拟光驱 由于下载的文件须要光驱安装,所以须要下载一个虚拟光驱,虚拟光驱名称:daemon too ...

  9. 自己动手一步一步安装hadoop(含编译hadoop的native本地包)

    近期项目须要用到hadoop.边学习边应用,第一步无疑是安装hadoop.我安装的是hadoop-2.4.1.以下是具体步骤,做备忘以后查看 一.下载依赖软件 1.java hadoop官网说明仅仅支 ...

  10. 固态继电器SSR

    s107.  LH1521.  CPC1035N http://e22a.com/h.bXsDYw?cv=AAOzhSfJ&sm=53e30b