【模板】【圆和多边形面积交】三角剖分 poj 3675
题目链接:https://vjudge.net/problem/POJ-3675
原文链接:https://blog.csdn.net/pokemonn_getto_daze/article/details/52058312
还是借鉴别人的模板的。。。写的太好了。
模板:
1 /************************************************************************* 2 > File Name: poj3675.cpp 3 # File Name: poj3675.cpp 4 # Author : xiaobuxie 5 # QQ : 760427180 6 # Email:760427180@qq.com 7 # Created Time: 2019年10月16日 星期三 19时08分03秒 8 ************************************************************************/ 9 10 #include<iostream> 11 #include<cstdio> 12 #include<map> 13 #include<cmath> 14 #include<cstring> 15 #include<set> 16 #include<queue> 17 #include<vector> 18 #include<algorithm> 19 using namespace std; 20 typedef long long ll; 21 #define inf 0x3f3f3f3f 22 #define pq priority_queue<int,vector<int>,greater<int> > 23 #define eps 1e-6 24 ll gcd(ll a,ll b){ 25 if(a<b) return gcd(b,a); 26 return b==0?a:gcd(b,a%b); 27 } 28 29 const int N = 50+9; 30 int sgn(double x){ 31 if(fabs(x) < eps) return 0; 32 if( x < 0) return -1; 33 return 1; 34 } 35 struct Point{ 36 double x,y; 37 Point(){x=y=0;} 38 Point(double a,double b){ x=a,y=b;} 39 Point operator - (const Point& b)const 40 {return Point(x-b.x,y-b.y);} 41 Point operator + (const Point& b)const 42 {return Point(x+b.x,y+b.y);} 43 Point operator * (const double& b)const 44 {return Point(x*b,y*b);} 45 double dot (const Point& b)const 46 {return x*b.x + y*b.y;} 47 double cross (const Point& b ,const Point& c)const 48 {return (b.x - x)*(c.y - y) - (c.x - x)*(b.y - y);} 49 double dis(const Point& b)const 50 {return sqrt( (x-b.x)*(x-b.x) + (y-b.y)*(y-b.y));} 51 bool OnLine(const Point& st,Point& ed)const 52 {return !sgn(cross(st,ed));} 53 bool OnSeg(const Point& st,Point& ed)const 54 {return OnLine(st,ed) && (*this - ed).dot(*this - st) < eps;} 55 }p[N]; 56 int n; 57 58 //两 直线 交点 59 Point LineCross(Point a,Point b,Point c,Point d){ 60 double u = a.cross(b,c), v = b.cross(a,d); 61 return Point((c.x*v + d.x*u) / (u+v), (c.y*v + d.y*u)/(u+v)); 62 } 63 64 //a,b线段(直线)和圆的交点 p1,p2分别为靠近a,b的交点 65 //a,b在圆的同一侧也可以,只是将向量长度改变而已 66 double LineCrossCircle(Point a,Point b,Point o,double r,Point& p1,Point& p2){ 67 Point fp = LineCross(o,Point(o.x + a.y - b.y , o.y + b.x -a.x),a,b);// o 垂直到ab直线交点 68 double otol = o.dis(fp); 69 double otos = fp.OnSeg(a,b) ? otol : min(o.dis(a) , o.dis(b)); 70 double atob = a.dis(b); 71 double fptoe = sqrt( r*r - otol*otol ) / atob; 72 if( otos > r - eps) return otos; 73 //向量长度改变 74 p1 = fp + ( a - b ) * fptoe; 75 p2 = fp + ( b - a ) * fptoe; 76 return otos; 77 } 78 79 //oa,到 ob 扇形面积 80 double SectorA(Point o,Point a,Point b,double r){ //a to b 逆时针 81 double ao2 = (a.x - o.x)*(a.x - o.x) + (a.y - o.y)*(a.y - o.y); 82 double bo2 = (b.x - o.x)*(b.x - o.x) + (b.y - o.y)*(b.y - o.y); 83 double ab2 = (a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y); 84 double ang = acos(0.5*(ao2 + bo2 - ab2)/sqrt(ao2)/sqrt(bo2)); 85 return 0.5 * r * r * ang; 86 } 87 88 // 三角形oab 和圆相交的面积 89 double TICA(Point o,Point a,Point b,double r){//a to b逆时针 90 if(o.OnLine(a,b)) return 0.0; 91 double adis = o.dis(a),bdis = o.dis(b); 92 if( adis < r + eps && bdis < r + eps) return o.cross(a,b) * 0.5; 93 Point ta,tb; 94 double otos = LineCrossCircle(a,b,o,r,ta,tb); 95 if( otos > r - eps) return SectorA(o,a,b,r); 96 if( adis < r + eps) return o.cross(a,tb) * 0.5 + SectorA(o,tb,b,r); 97 if( bdis < r + eps) return o.cross(ta,b) * 0.5 + SectorA(o,a,ta,r); 98 return o.cross(ta,tb)*0.5 + SectorA(o,a,ta,r) + SectorA(o,tb,b,r); 99 } 100 101 //多边形和圆相交的面积 102 //点从 0 开始,并且为逆时针 103 double PICA(int n,Point o,double r){ 104 double res = 0; 105 for(int i =0; i<n;++i){ 106 if(o.cross(p[i],p[(i+1)%n]) > 0) res += TICA(o,p[i],p[(i+1)%n],r); 107 else res -= TICA(o,p[(i+1)%n],p[i],r); 108 } 109 return fabs(res); 110 } 111 int main(){ 112 double r; 113 while(~scanf("%lf",&r)){ 114 scanf("%d",&n); 115 for(int i = 0;i<n;++i) scanf("%lf %lf",&p[i].x,&p[i].y); 116 printf("%.2f\n",PICA(n,Point(0,0),r)); 117 } 118 return 0; 119 }