题目:Mission Impossible

题意:在天花板上有3个摄像头,下面有一个凸多面体,问摄像头观测不到的在地面上的面积是多少。

思路:先求出每个摄像头对于凸多面体在xoy平面的投影,然后求凸包,然后利用半平面交来求面积交即可,注意求投影时用到一个结论:

如果在空间有3点共线则满足:(z3-z2)/(z2-z1)=(y3-y2)/(y2-y1)=(x3-x2)/(x2-x1)

代码太乱,有时间再整理。

#include <math.h>
#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int N=105;
const double EPS=1e-8;
typedef double DIY;
DIY Area;
struct Point
{
DIY x,y;
Point() {}
Point(DIY _x,DIY _y):x(_x),y(_y){}
} p[N];
Point MakeVector(Point &P,Point &Q)
{
return Point(Q.x-P.x,Q.y-P.y);
}
DIY CrossProduct(Point P,Point Q)
{
return P.x*Q.y-P.y*Q.x;
}
Point MinA;
Point stack1[N],stack2[N],stack3[N];
int top1,top2,top3;
DIY dist(Point A,Point B)
{
return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}
DIY cross(Point A,Point B,Point C)
{
return (B.x-A.x)*(C.y-A.y)-(B.y-A.y)*(C.x-A.x);
}
bool cmp1(Point a,Point b)
{
DIY k=cross(MinA,a,b);
if(k>0) return 1;
if(k<0) return 0;
return dist(MinA,a)>dist(MinA,b);
}
void Graham1(Point *p,int n,int &top)
{
int i;
for(i=0; i<n; i++)
if(p[i].y<p[0].y||(p[i].y==p[0].y&&p[i].x<p[0].x))
swap(p[i],p[0]);
MinA=p[0];
sort(p+1,p+n,cmp1);
p[n]=p[0];
stack1[0]=p[0];
stack1[1]=p[1];
stack1[2]=p[2];
top=2;
for(i=3; i<=n; i++)
{
while(cross(stack1[top-1],stack1[top],p[i])<=0&&top>=2) --top;
stack1[++top]=p[i];
}
}
void Graham2(Point *p,int n,int &top)
{
int i;
for(i=0; i<n; i++)
if(p[i].y<p[0].y||(p[i].y==p[0].y&&p[i].x<p[0].x))
swap(p[i],p[0]);
MinA=p[0];
sort(p+1,p+n,cmp1);
p[n]=p[0];
stack2[0]=p[0];
stack2[1]=p[1];
stack2[2]=p[2];
top=2;
for(i=3; i<=n; i++)
{
while(cross(stack2[top-1],stack2[top],p[i])<=0&&top>=2) --top;
stack2[++top]=p[i];
}
}
void Graham3(Point *p,int n,int &top)
{
int i;
for(i=0; i<n; i++)
if(p[i].y<p[0].y||(p[i].y==p[0].y&&p[i].x<p[0].x))
swap(p[i],p[0]);
MinA=p[0];
sort(p+1,p+n,cmp1);
p[n]=p[0];
stack3[0]=p[0];
stack3[1]=p[1];
stack3[2]=p[2];
top=2;
for(i=3; i<=n; i++)
{
while(cross(stack3[top-1],stack3[top],p[i])<=0&&top>=2) --top;
stack3[++top]=p[i];
}
}
DIY MultiCross(Point P,Point Q,Point R)
{
return CrossProduct(MakeVector(Q,P),MakeVector(Q,R));
}
struct halfPlane
{
Point s,t;
DIY angle;
halfPlane(){}
halfPlane(Point _s,Point _t):s(_s),t(_t){}
halfPlane(DIY sx,DIY sy,DIY tx,DIY ty):s(sx,sy),t(tx,ty){}
void GetAngle()
{
angle=atan2(t.y-s.y,t.x-s.x);
}
} hp[N],q[N];
Point IntersectPoint(halfPlane P,halfPlane Q)
{
DIY a1=CrossProduct(MakeVector(P.s,Q.t),MakeVector(P.s,Q.s));
DIY a2=CrossProduct(MakeVector(P.t,Q.s),MakeVector(P.t,Q.t));
return Point((P.s.x*a2+P.t.x*a1)/(a2+a1),(P.s.y*a2+P.t.y*a1)/(a2+a1));
}
bool cmp2(halfPlane P,halfPlane Q)
{
if(fabs(P.angle-Q.angle)<EPS)
return MultiCross(P.s,P.t,Q.s)>0;
return P.angle<Q.angle;
}
bool IsParallel(halfPlane P,halfPlane Q)
{
return fabs(CrossProduct(MakeVector(P.s,P.t),MakeVector(Q.s,Q.t)))<EPS;
}
void HalfPlaneIntersect(int n,int &m)
{
sort(hp,hp+n,cmp2);
int i,l=0,r=1;
for(m=i=1; i<n; ++i)
if(hp[i].angle-hp[i-1].angle>EPS) hp[m++]=hp[i];
n=m; m=0;
q[0]=hp[0];q[1]=hp[1];
for(i=2; i<n; i++)
{
if(IsParallel(q[r],q[r-1])||IsParallel(q[l],q[l+1])) return;
while(l<r&&MultiCross(hp[i].s,hp[i].t,IntersectPoint(q[r],q[r-1]))>0) --r;
while(l<r&&MultiCross(hp[i].s,hp[i].t,IntersectPoint(q[l],q[l+1]))>0) ++l;
q[++r]=hp[i];
}
while(l<r&&MultiCross(q[l].s,q[l].t,IntersectPoint(q[r],q[r-1]))>0) --r;
while(l<r&&MultiCross(q[r].s,q[r].t,IntersectPoint(q[l],q[l+1]))>0) ++l;
q[++r]=q[l];
for(i=l; i<r; ++i)
p[m++]=IntersectPoint(q[i],q[i+1]);
}
void Solve(Point *p1,Point *p2,Point *p3,int &top1,int &top2,int &top3,int &m)
{
int i,j;
Point a,b;
Point O;
O.x=O.y=0;
int num=0;
for(i=0;i<top1;i++)
{
hp[num]=halfPlane(p1[i],p1[(i+1)%top1]);
hp[num].GetAngle();
num++;
}
for(i=0;i<top2;i++)
{
hp[num]=halfPlane(p2[i],p2[(i+1)%top2]);
hp[num].GetAngle();
num++;
}
for(i=0;i<top3;i++)
{
hp[num]=halfPlane(p3[i],p3[(i+1)%top3]);
hp[num].GetAngle();
num++;
}
HalfPlaneIntersect(num,m);
Area=0;
p[m]=p[0];
for(i=0;i<m;++i)
Area+=cross(O,p[i],p[i+1]);
if(Area<0) Area=-Area;
Area/=2.0;
}
int main()
{
int n,m,t,i,j,k;
Point p1[N],p2[N],p3[N];
top1=top2=top3=0;
Point tmp[N];
DIY x[N],y[N],z[N];
while(cin>>n)
{
for(i=0; i<n; i++)
{
cin>>x[i]>>y[i]>>z[i];
}
for(i=0;i<3;i++)
cin>>tmp[i].x>>tmp[i].y;
for(i=0;i<n;i++)
{
p1[i].y=y[i]+(0-z[i])*(y[i]-tmp[0].y)/(z[i]-100);
p1[i].x=x[i]+(0-z[i])*(x[i]-tmp[0].x)/(z[i]-100);
}
for(i=0;i<n;i++)
{
p2[i].y=y[i]+(0-z[i])*(y[i]-tmp[1].y)/(z[i]-100);
p2[i].x=x[i]+(0-z[i])*(x[i]-tmp[1].x)/(z[i]-100);
}
for(i=0;i<n;i++)
{
p3[i].y=y[i]+(0-z[i])*(y[i]-tmp[2].y)/(z[i]-100);
p3[i].x=x[i]+(0-z[i])*(x[i]-tmp[2].x)/(z[i]-100);
}
int k=0;
Graham1(p1,n,top1);
Graham2(p2,n,top2);
Graham3(p3,n,top3);
Solve(stack1,stack2,stack3,top1,top2,top3,m);
printf("%.2lf\n",Area);
}
return 0;
}

NJUST4316(立体几何投影的面积交)相关推荐

  1. 题目 1471:【蓝桥杯】【入门题】【基础练习VIP】矩形面积交

    题目 1471:矩形面积交 蓝桥杯刷题群已成立,微信后台回复[蓝桥杯],即可进入. 如果加入了之前的社群不需要重复加入. 时间限制: 1Sec 内存限制: 128MB 1. 题目描述 平面上有两个矩形 ...

  2. python【蓝桥杯vip练习题库】BASIC-18 矩形面积交(线段交)

    试题 基础练习 矩形面积交 资源限制 时间限制:1.0s 内存限制:512.0MB 问题描述 平面上有两个矩形,它们的边平行于直角坐标系的X轴或Y轴.对于每个矩形,我们给出它的一对相对顶点的坐标,请你 ...

  3. hdu1255 覆盖的面积(线段树面积交)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1255 面积交与面积并相似相比回了面积并,面积交一定会有思路,当然就是cover标记大于等于两次时. 但 ...

  4. HDU - 1255 覆盖的面积(线段树求矩形面积交 扫描线+离散化)

    链接:线段树求矩形面积并 扫描线+离散化 1.给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. 2.看完线段树求矩形面积并 的方法后,再看这题,求的是矩形面积交,类同. 求面积时,用被覆 ...

  5. 矩形面积交(蓝桥杯)

    矩形面积交 问题描述 平面上有两个矩形,它们的边平行于直角坐标系的X轴或Y轴.对于每个矩形,我们给出它的一对相对顶点的坐标,请你编程算出两个矩形的交的面积. 输入格式 输入仅包含两行,每行描述一个矩形 ...

  6. 蓝桥杯试题 基础练习 矩形面积交 BASIC-18 JAVA

    目录 前言 试题 基础练习 矩形面积交 本题试题 前言 最近一直搞面试,很多写好的代码都懒得去发博客,现在补上,但是注释可能比较少,大家如果有问题请联系我 试题 基础练习 矩形面积交 资源限制 时间限 ...

  7. matlab 3维投影,matlab - 如何计算3维投影的面积? - 堆栈内存溢出

    第一步将使用convhull (如yar所建议 )来获取每个投影多边形区域的轮廓. 应该注意的是,这里要使用凸包,因为您要处理的是长方体,即长方体. 我认为您的第二个长方体(位于A(9:16, :) ...

  8. 扫描线面积并、面积交模板

    面积并 本质上是维护每个时间段里面数轴上有多少个点被赋值了 当题目数据到1e9 就需要离散化操作 统计数组上零的个数 维护最小值和最小值出现个数 然后判断下最小值是不是0 #pragma commen ...

  9. java蓝桥杯——矩形面积交

    蓝桥杯--矩形面积交(java) 大致思路: 获取矩形的四边在x轴和y轴上的位置,分别用八个变量获取.取得矩形的上边和下边,左边和右边,分别存储.如果两矩形相交,则有一矩形的一点在另一矩形的内部,如下 ...

最新文章

  1. C语言基础(12)-输入和输出
  2. 写给我的2015—开启工作新旅程
  3. 看了一个月c能学java_学过一点C语言的可以自学java吗?应该怎样开始?
  4. 丹麦奥尔堡大学计算机系博士,丹麦奥尔堡大学招收计算机全奖PHD
  5. PRML-系列一之1.5.1~1.5.3
  6. php输出mysql查询结果_PHP简单获取数据库查询结果并返回JSON
  7. Unable to convert MySQL date/time value to System.DateTime
  8. Android 系统(151)----添加开关机铃声
  9. 学习单片机c语言必备的两个软件,单片机C语言应用100例(第2版)
  10. 网页鼠标指针样式(cursor属性)
  11. 概述无线传感网的MAC协议
  12. Mybatis:高级知识1- resultMap实现一对一、一对多、多对多
  13. 查看linux磁盘信息,linux下查看硬盘型号等信息
  14. 每日一练——回文链表
  15. Linux 监控工具之Cacti使用详解(一)
  16. 实验6   实现数据完整性
  17. ​互联网的厕所,兵家的必争之地
  18. 【转载】别让自己“墙”了自己
  19. c 语言整人代码大全,C 语言整人代码大全.doc
  20. 数据结构与算法之一(书籍篇)

热门文章

  1. Elastic-Job中的SimpleJob
  2. es6语法-箭头函数
  3. Date类的构造方法和成员方法
  4. Disruptor并发框架-1
  5. OAuth2(二)——实现
  6. php十万篇文章,10万+的标题套路,就这9个
  7. python集合属性方法运算_python对象及运算 序列小结 集合
  8. ubuntu中用apt命令卸载软件
  9. Handler 源码解析(Java 层)
  10. vue.js的一些小语法v-bind,v-if,v-show,v-else