HDU5130 Signal Interference
1 /* 2 HDU5130 Signal Interference 3 http://acm.hdu.edu.cn/showproblem.php?pid=5130 4 计算几何 圆与多边形面积交 5 * 6 */ 7 8 9 #include <cstdio> 10 #include <algorithm> 11 #include <cmath> 12 using namespace std; 13 const double Pi=acos(-1.0); 14 const double eps = 1e-8; 15 const int Nmax=1005; 16 double k; 17 int sgn(double x) 18 { 19 if(x<-eps) 20 return -1; 21 if(x>eps) 22 return 1; 23 return 0; 24 } 25 double Abs(double x) 26 { 27 if(sgn(x)<0) 28 x=-x; 29 else if(sgn(x)==0) 30 x=0.0; 31 return x; 32 } 33 double sqr(double x) 34 { 35 return x*x; 36 } 37 double Sqrt(double x) 38 { 39 return max(0.0,sqrt(x)); 40 } 41 struct Pt 42 { 43 double x,y; 44 Pt() { } 45 Pt(double x, double y) : x(x), y(y) { } 46 47 Pt operator - (const Pt &b) 48 { 49 return Pt(x-b.x,y-b.y); 50 } 51 Pt operator + (const Pt &b) 52 { 53 return Pt(x+b.x,y+b.y); 54 } 55 friend Pt operator * (double a,Pt p) 56 { 57 return Pt(p.x*a,p.y*a); 58 } 59 friend Pt operator * (Pt p,double a) 60 { 61 return Pt(p.x*a,p.y*a); 62 } 63 friend Pt operator / (Pt p,double a) 64 { 65 return Pt(p.x/a,p.y/a); 66 } 67 double norm() 68 { 69 return Sqrt(x*x + y*y); 70 } 71 double len() 72 { 73 return norm(); 74 } 75 void print() 76 { 77 printf("(%f, %f)\n", x, y); 78 } 79 }; 80 int n; 81 Pt pl[Nmax]; 82 Pt pr,A,B,p0,p1; 83 double dist (Pt a, Pt b) 84 { 85 return (a-b).norm(); 86 } 87 double dot(Pt a,Pt b)//点乘 88 { 89 return a.x*b.x+a.y*b.y; 90 } 91 double det(Pt a,Pt b) 92 { 93 return a.x*b.y-a.y*b.x; 94 } 95 Pt rotate(Pt p,double a)//P点绕原点逆时针旋转a弧度 96 { 97 return Pt(p.x*cos(a)-p.y*sin(a),p.x*sin(a)+p.y*cos(a)); 98 } 99 struct Sg//线段 100 { 101 Pt s, t; 102 Sg() { } 103 Sg(Pt s, Pt t) : s(s), t(t) { } 104 Sg(double a, double b, double c, double d) : s(a, b), t(c, d) { } 105 }; 106 bool PtOnSegment(Pt p, Pt a, Pt b) //p是否在线段ab上,把<=改成<就能实现不含线段端点的点在线段上的判断。 107 { 108 return !sgn(det(p-a, b-a)) && sgn(dot(p-a, p-b)) <= 0; 109 } 110 bool PtOnLine(Pt p, Pt a, Pt b) //p是否在直线ab上 111 { 112 return !sgn(det(p-a, b-a)); 113 } 114 Pt PtLineProj(Pt s, Pt t, Pt p) //p到直线st的投影 115 { 116 double r = dot(p-s, t-s) / (t - s).norm(); 117 return s + (t - s) * r; 118 } 119 bool parallel(Pt a, Pt b, Pt s, Pt t) 120 { 121 return !sgn(det(a-b, s-t)); 122 } 123 Pt triangleMassCenter(Pt a, Pt b, Pt c) 124 { 125 return (a+b+c) / 3.0; 126 } 127 double polygon_area(Pt poly[],int n) 128 { 129 double ans=0.0; 130 if(n<3) 131 return ans; 132 for(int i=1;i<=n;i++) 133 ans+=det(poly[i],poly[i%n+1]); 134 return ans*0.5; 135 } 136 137 struct Circle 138 { 139 Pt c; 140 double r; 141 Circle(Pt _c,double _r) 142 { 143 c=_c; 144 r=_r; 145 } 146 }; 147 bool PointInCircle(Circle a,Pt p) 148 { 149 Pt c=a.c; 150 return sgn( (p-c).norm()-a.r )<0; 151 } 152 153 bool PointOnCircle(Circle a,Pt p) 154 { 155 Pt c=a.c; 156 return sgn( (p-c).norm()-a.r )==0; 157 } 158 159 bool PointIOCircle(Circle a,Pt p) 160 { 161 Pt c=a.c; 162 return sgn( (p-c).norm()-a.r )<=0; 163 } 164 165 void circle_cross_line(Circle c,Pt a, Pt b, Pt ans[], int &num) 166 { 167 double x1=a.x,y1=a.y,x2=b.x,y2=b.y; 168 double dx=x2-x1,dy=y2-y1; 169 double tmpx=x1-c.c.x,tmpy=y1-c.c.y; 170 double A=dx*dx+dy*dy; 171 double B=2.0*( dx*tmpx+dy*tmpy ); 172 double C=tmpx*tmpx+tmpy*tmpy-c.r*c.r; 173 double delta=B*B-4.0*A*C; 174 num=0; 175 if(sgn(delta)<0) 176 return; 177 double t1=(-B-Sqrt(delta))/(2.0*A); 178 double t2=(-B+Sqrt(delta))/(2.0*A); 179 if(sgn(t1-1.0)<=0 && sgn(t1)>=0) 180 ans[++num]=Pt(x1+t1*dx,y1+t1*dy); 181 if(sgn(delta)==0) 182 return; 183 if(sgn(t2-1.0)<=0 && sgn(t2)>=0) 184 ans[++num]=Pt(x1+t2*dx,y1+t2*dy); 185 } 186 187 double sector_area(Circle c,Pt a,Pt b) 188 { 189 a=a-c.c,b=b-c.c; 190 double theta = atan2(a.y, a.x) - atan2(b.y, b.x); 191 while (sgn(theta) <= 0) theta += 2.0*Pi; 192 while (sgn(theta-2.0*Pi)>0) theta -= 2.0*Pi; 193 theta = min(theta, 2.0*Pi - theta); 194 return c.r*c.r*theta*0.5; 195 } 196 197 double CirclePolyArea(Circle c,Pt poly[],int n) 198 { 199 double ans=0.0; 200 Pt p[3]; 201 int num; 202 for(int i=1;i<=n;i++) 203 { 204 Pt a=poly[i],b=poly[i%n+1]; 205 int ina=PointInCircle(c,a); 206 int inb=PointInCircle(c,b); 207 Pt da=a-c.c,db=b-c.c; 208 int s=sgn(det(da,db)); 209 double part=0.0; 210 if(ina) 211 { 212 if(inb) 213 { 214 part=Abs(det(da,db))*0.5; 215 } 216 else 217 { 218 circle_cross_line(c,a,b,p,num); 219 part=sector_area(c,p[1],b)+Abs(det(da,p[1]-c.c))*0.5; 220 } 221 } 222 else 223 { 224 if(inb) 225 { 226 circle_cross_line(c,a,b,p,num); 227 part=sector_area(c,p[1],a)+Abs(det(db,p[1]-c.c))*0.5; 228 } 229 else 230 { 231 circle_cross_line(c,a,b,p,num); 232 if(num==2) 233 { 234 part=sector_area(c,a,p[1])+sector_area(c,b,p[2])+Abs(det(p[1]-c.c,p[2]-c.c))*0.5; 235 } 236 else 237 { 238 part=sector_area(c,a,b); 239 } 240 } 241 } 242 if(s!=0) 243 ans+=1.0*s*part; 244 } 245 return ans; 246 } 247 int main() 248 { 249 int t=0; 250 while(scanf("%d%lf",&n,&k)==2) 251 { 252 t++; 253 for(int i=1;i<=n;i++) 254 scanf("%lf%lf",&pl[i].x,&pl[i].y); 255 scanf("%lf%lf%lf%lf",&A.x,&A.y,&B.x,&B.y); 256 double r; 257 double E=(2.0*B.x-2.0*sqr(k)*A.x)/(1.0-sqr(k)); 258 double F=(2.0*B.y-2.0*sqr(k)*A.y)/(1.0-sqr(k)); 259 double G=(sqr(k*A.x)+sqr(k*A.y)-sqr(B.x)-sqr(B.y))/(1.0-sqr(k)); 260 pr.x=E/2.0,pr.y=F/2.0; 261 r=Sqrt(G+sqr(E)/4.0+sqr(F)/4.0); 262 Circle C(pr,r); 263 double ans=Abs( CirclePolyArea(C,pl,n) ); 264 printf("Case %d: ",t); 265 printf("%.10f\n",ans+eps); 266 } 267 return 0; 268 }