POJ 3675 Telescope(圆和多边形面积交)

题目链接:http://poj.org/problem?id=3675

题意:一个圆心在原点(0,0)的圆,给出半径和另外一个多边形P求圆和多边形的相交面积

思路:三角剖分

 
  
 #include <iostream>
 #include <cstdio>
 #include <cmath>
 #define max(x,y) ((x)>(y)?(x):(y))
 #define min(x,y) ((x)<(y)?(x):(y))
 #define PI acos(-1.0)
 #define EPS 1e-10
 using namespace std;
 
 inline int DB(double x)
 {
     if(x<-EPS) return -1;
     if(x>EPS) return 1;
     return 0;
 }
 
 
 struct point
 {
     double x,y;
 
     point(){}
     point(double _x,double _y):x(_x),y(_y){}
 
     point operator-(point a)
     {
         return point(x-a.x,y-a.y);
     }
     point operator+(point a)
     {
         return point(x+a.x,y+a.y);
     }
     
     double operator*(point a)
     {
         return x*a.y-y*a.x;
     }
     
     point oppose()
     {
         return point(-x,-y);
     }
     
     double length()
     {
         return sqrt(x*x+y*y);
     }
     
     point adjust(double L)
     {
         L/=length();
         return point(x*L,y*L);
     }
     
     point vertical()
     {
         return point(-y,x);
     }
     
     double operator^(point a)
     {
         return x*a.x+y*a.y;
     }
 };
 
 
 struct segment
 {
     point a,b;
 
     segment(){}
     segment(point _a,point _b):a(_a),b(_b){}
 
     point intersect(segment s)
     {
         double s1=(s.a-a)*(s.b-a);
         double s2=(s.b-b)*(s.a-b);
         double t=s1+s2;
         s1/=t;s2/=t;
         return point(a.x*s2+b.x*s1,a.y*s2+b.y*s1);
     }
     point vertical(point p)
     {
         point t=(b-a).vertical();
         return intersect(segment(p,p+t));
     }
     int isonsegment(point p)
     {
         return DB(min(a.x,b.x)-p.x)<=0&&
                DB(max(a.x,b.x)-p.x)>=0&&
                DB(min(a.y,b.y)-p.y)<=0&&
                DB(max(a.y,b.y)-p.y)>=0;
     }
 };
 
 struct circle
 {
     point p;
     double R;
 };
 
 circle C;
 point p[105];
 int n;
 
 
 double cross_area(point a,point b,circle C)
 {
     point p=C.p;
     double R=C.R;
     int sgn=DB((b-p)*(a-p));
     double La=(a-p).length(),Lb=(b-p).length();
     int ra=DB(La-R),rb=DB(Lb-R);
     double ang=acos(((b-p)^(a-p))/(La*Lb));
     segment t(a,b);
     point s;
     point h,u,temp;
     double ans,L,d,ang1;
 
     if(!DB(La)||!DB(Lb)||!sgn) ans=0;
     else if(ra<=0&&rb<=0) ans=fabs((b-p)*(a-p))/2;
     else if(ra>=0&&rb>=0)
     {
         h=t.vertical(p);
         L=(h-p).length();
         if(!t.isonsegment(h)||DB(L-R)>=0) ans=R*R*(ang/2);
         else
         {
             ans=R*R*(ang/2);
             ang1=acos(L/R);
             ans-=R*R*ang1;
             ans+=R*sin(ang1)*L;
         }
     }
     else
     {
         h=t.vertical(p);
         L=(h-p).length();
         s=b-a;
         d=sqrt(R*R-L*L);
         s=s.adjust(d);
         if(t.isonsegment(h+s)) u=h+s;
         else u=h+s.oppose();
         if(ra==1) temp=a,a=b,b=temp;
         ans=fabs((a-p)*(u-p))/2;
         ang1=acos(((u-p)^(b-p))/((u-p).length()*(b-p).length()));
         ans+=R*R*(ang1/2);
     }
     return ans*sgn;
 }
 
 double cal_cross(circle C,point p[],int n)
 {
     double ans=0;
     int i;
     p[n]=p[0];
     for(i=0;i<n;i++) ans+=cross_area(p[i],p[i+1],C);
     return fabs(ans);
 }
 
 
 int main()
 {
     while(scanf("%lf%d",&C.R,&n)!=-1)
     {
         int i;
         for(i=0;i<n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
         C.p.x=C.p.y=0;
         double area=cal_cross(C,p,n);
         printf("%.2lf\n",area);
     }
     return 0;
 }
 
  

  

 
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值