首页 > 代码库 > [转]计算几何模板
[转]计算几何模板
Repost
1.
1 #include<vector> 2 #include<list> 3 #include<map> 4 #include<set> 5 #include<deque> 6 #include<queue> 7 #include<stack> 8 #include<bitset> 9 #include<algorithm> 10 #include<functional> 11 #include<numeric> 12 #include<utility> 13 #include<iostream> 14 #include<sstream> 15 #include<iomanip> 16 #include<cstdio> 17 #include<cmath> 18 #include<cstdlib> 19 #include<cctype> 20 #include<string> 21 #include<cstring> 22 #include<cstdio> 23 #include<cmath> 24 #include<cstdlib> 25 #include<ctime> 26 #include<climits> 27 #include<complex> 28 #define mp make_pair 29 #define pb push_back 30 using namespace std; 31 const double eps=1e-8; 32 const double pi=acos(-1.0); 33 const double inf=1e20; 34 const int maxp=1111; 35 int dblcmp(double d) 36 { 37 if (fabs(d)<eps)return 0; 38 return d>eps?1:-1; 39 } 40 inline double sqr(double x){return x*x;} 41 struct point 42 { 43 double x,y; 44 point(){} 45 point(double _x,double _y): 46 x(_x),y(_y){}; 47 void input() 48 { 49 scanf("%lf%lf",&x,&y); 50 } 51 void output() 52 { 53 printf("%.2f %.2f\n",x,y); 54 } 55 bool operator==(point a)const 56 { 57 return dblcmp(a.x-x)==0&&dblcmp(a.y-y)==0; 58 } 59 bool operator<(point a)const 60 { 61 return dblcmp(a.x-x)==0?dblcmp(y-a.y)<0:x<a.x; 62 } 63 double len() 64 { 65 return hypot(x,y); 66 } 67 double len2() 68 { 69 return x*x+y*y; 70 } 71 double distance(point p) 72 { 73 return hypot(x-p.x,y-p.y); 74 } 75 point add(point p) 76 { 77 return point(x+p.x,y+p.y); 78 } 79 point sub(point p) 80 { 81 return point(x-p.x,y-p.y); 82 } 83 point mul(double b) 84 { 85 return point(x*b,y*b); 86 } 87 point div(double b) 88 { 89 return point(x/b,y/b); 90 } 91 double dot(point p) 92 { 93 return x*p.x+y*p.y; 94 } 95 double det(point p) 96 { 97 return x*p.y-y*p.x; 98 } 99 double rad(point a,point b) 100 { 101 point p=*this; 102 return fabs(atan2(fabs(a.sub(p).det(b.sub(p))),a.sub(p).dot(b.sub(p)))); 103 } 104 point trunc(double r) 105 { 106 double l=len(); 107 if (!dblcmp(l))return *this; 108 r/=l; 109 return point(x*r,y*r); 110 } 111 point rotleft() 112 { 113 return point(-y,x); 114 } 115 point rotright() 116 { 117 return point(y,-x); 118 } 119 point rotate(point p,double angle)//绕点p逆时针旋转angle角度 120 { 121 point v=this->sub(p); 122 double c=cos(angle),s=sin(angle); 123 return point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c); 124 } 125 }; 126 struct line 127 { 128 point a,b; 129 line(){} 130 line(point _a,point _b) 131 { 132 a=_a; 133 b=_b; 134 } 135 bool operator==(line v) 136 { 137 return (a==v.a)&&(b==v.b); 138 } 139 //倾斜角angle 140 line(point p,double angle) 141 { 142 a=p; 143 if (dblcmp(angle-pi/2)==0) 144 { 145 b=a.add(point(0,1)); 146 } 147 else 148 { 149 b=a.add(point(1,tan(angle))); 150 } 151 } 152 //ax+by+c=0 153 line(double _a,double _b,double _c) 154 { 155 if (dblcmp(_a)==0) 156 { 157 a=point(0,-_c/_b); 158 b=point(1,-_c/_b); 159 } 160 else if (dblcmp(_b)==0) 161 { 162 a=point(-_c/_a,0); 163 b=point(-_c/_a,1); 164 } 165 else 166 { 167 a=point(0,-_c/_b); 168 b=point(1,(-_c-_a)/_b); 169 } 170 } 171 void input() 172 { 173 a.input(); 174 b.input(); 175 } 176 void adjust() 177 { 178 if (b<a)swap(a,b); 179 } 180 double length() 181 { 182 return a.distance(b); 183 } 184 double angle()//直线倾斜角 0<=angle<180 185 { 186 double k=atan2(b.y-a.y,b.x-a.x); 187 if (dblcmp(k)<0)k+=pi; 188 if (dblcmp(k-pi)==0)k-=pi; 189 return k; 190 } 191 //点和线段关系 192 //1 在逆时针 193 //2 在顺时针 194 //3 平行 195 int relation(point p) 196 { 197 int c=dblcmp(p.sub(a).det(b.sub(a))); 198 if (c<0)return 1; 199 if (c>0)return 2; 200 return 3; 201 } 202 bool pointonseg(point p) 203 { 204 return dblcmp(p.sub(a).det(b.sub(a)))==0&&dblcmp(p.sub(a).dot(p.sub(b)))<=0; 205 } 206 bool parallel(line v) 207 { 208 return dblcmp(b.sub(a).det(v.b.sub(v.a)))==0; 209 } 210 //2 规范相交 211 //1 非规范相交 212 //0 不相交 213 int segcrossseg(line v) 214 { 215 int d1=dblcmp(b.sub(a).det(v.a.sub(a))); 216 int d2=dblcmp(b.sub(a).det(v.b.sub(a))); 217 int d3=dblcmp(v.b.sub(v.a).det(a.sub(v.a))); 218 int d4=dblcmp(v.b.sub(v.a).det(b.sub(v.a))); 219 if ((d1^d2)==-2&&(d3^d4)==-2)return 2; 220 return (d1==0&&dblcmp(v.a.sub(a).dot(v.a.sub(b)))<=0|| 221 d2==0&&dblcmp(v.b.sub(a).dot(v.b.sub(b)))<=0|| 222 d3==0&&dblcmp(a.sub(v.a).dot(a.sub(v.b)))<=0|| 223 d4==0&&dblcmp(b.sub(v.a).dot(b.sub(v.b)))<=0); 224 } 225 int linecrossseg(line v)//*this seg v line 226 { 227 int d1=dblcmp(b.sub(a).det(v.a.sub(a))); 228 int d2=dblcmp(b.sub(a).det(v.b.sub(a))); 229 if ((d1^d2)==-2)return 2; 230 return (d1==0||d2==0); 231 } 232 //0 平行 233 //1 重合 234 //2 相交 235 int linecrossline(line v) 236 { 237 if ((*this).parallel(v)) 238 { 239 return v.relation(a)==3; 240 } 241 return 2; 242 } 243 point crosspoint(line v) 244 { 245 double a1=v.b.sub(v.a).det(a.sub(v.a)); 246 double a2=v.b.sub(v.a).det(b.sub(v.a)); 247 return point((a.x*a2-b.x*a1)/(a2-a1),(a.y*a2-b.y*a1)/(a2-a1)); 248 } 249 double dispointtoline(point p) 250 { 251 return fabs(p.sub(a).det(b.sub(a)))/length(); 252 } 253 double dispointtoseg(point p) 254 { 255 if (dblcmp(p.sub(b).dot(a.sub(b)))<0||dblcmp(p.sub(a).dot(b.sub(a)))<0) 256 { 257 return min(p.distance(a),p.distance(b)); 258 } 259 return dispointtoline(p); 260 } 261 point lineprog(point p) 262 { 263 return a.add(b.sub(a).mul(b.sub(a).dot(p.sub(a))/b.sub(a).len2())); 264 } 265 point symmetrypoint(point p) 266 { 267 point q=lineprog(p); 268 return point(2*q.x-p.x,2*q.y-p.y); 269 } 270 }; 271 struct circle 272 { 273 point p; 274 double r; 275 circle(){} 276 circle(point _p,double _r): 277 p(_p),r(_r){}; 278 circle(double x,double y,double _r): 279 p(point(x,y)),r(_r){}; 280 circle(point a,point b,point c)//三角形的外接圆 281 { 282 p=line(a.add(b).div(2),a.add(b).div(2).add(b.sub(a).rotleft())).crosspoint(line(c.add(b).div(2),c.add(b).div(2).add(b.sub(c).rotleft()))); 283 r=p.distance(a); 284 } 285 circle(point a,point b,point c,bool t)//三角形的内切圆 286 { 287 line u,v; 288 double m=atan2(b.y-a.y,b.x-a.x),n=atan2(c.y-a.y,c.x-a.x); 289 u.a=a; 290 u.b=u.a.add(point(cos((n+m)/2),sin((n+m)/2))); 291 v.a=b; 292 m=atan2(a.y-b.y,a.x-b.x),n=atan2(c.y-b.y,c.x-b.x); 293 v.b=v.a.add(point(cos((n+m)/2),sin((n+m)/2))); 294 p=u.crosspoint(v); 295 r=line(a,b).dispointtoseg(p); 296 } 297 void input() 298 { 299 p.input(); 300 scanf("%lf",&r); 301 } 302 void output() 303 { 304 printf("%.2lf %.2lf %.2lf\n",p.x,p.y,r); 305 } 306 bool operator==(circle v) 307 { 308 return ((p==v.p)&&dblcmp(r-v.r)==0); 309 } 310 bool operator<(circle v)const 311 { 312 return ((p<v.p)||(p==v.p)&&dblcmp(r-v.r)<0); 313 } 314 double area() 315 { 316 return pi*sqr(r); 317 } 318 double circumference() 319 { 320 return 2*pi*r; 321 } 322 //0 圆外 323 //1 圆上 324 //2 圆内 325 int relation(point b) 326 { 327 double dst=b.distance(p); 328 if (dblcmp(dst-r)<0)return 2; 329 if (dblcmp(dst-r)==0)return 1; 330 return 0; 331 } 332 int relationseg(line v) 333 { 334 double dst=v.dispointtoseg(p); 335 if (dblcmp(dst-r)<0)return 2; 336 if (dblcmp(dst-r)==0)return 1; 337 return 0; 338 } 339 int relationline(line v) 340 { 341 double dst=v.dispointtoline(p); 342 if (dblcmp(dst-r)<0)return 2; 343 if (dblcmp(dst-r)==0)return 1; 344 return 0; 345 } 346 //过a b两点 半径r的两个圆 347 int getcircle(point a,point b,double r,circle&c1,circle&c2) 348 { 349 circle x(a,r),y(b,r); 350 int t=x.pointcrosscircle(y,c1.p,c2.p); 351 if (!t)return 0; 352 c1.r=c2.r=r; 353 return t; 354 } 355 //与直线u相切 过点q 半径r1的圆 356 int getcircle(line u,point q,double r1,circle &c1,circle &c2) 357 { 358 double dis=u.dispointtoline(q); 359 if (dblcmp(dis-r1*2)>0)return 0; 360 if (dblcmp(dis)==0) 361 { 362 c1.p=q.add(u.b.sub(u.a).rotleft().trunc(r1)); 363 c2.p=q.add(u.b.sub(u.a).rotright().trunc(r1)); 364 c1.r=c2.r=r1; 365 return 2; 366 } 367 line u1=line(u.a.add(u.b.sub(u.a).rotleft().trunc(r1)),u.b.add(u.b.sub(u.a).rotleft().trunc(r1))); 368 line u2=line(u.a.add(u.b.sub(u.a).rotright().trunc(r1)),u.b.add(u.b.sub(u.a).rotright().trunc(r1))); 369 circle cc=circle(q,r1); 370 point p1,p2; 371 if (!cc.pointcrossline(u1,p1,p2))cc.pointcrossline(u2,p1,p2); 372 c1=circle(p1,r1); 373 if (p1==p2) 374 { 375 c2=c1;return 1; 376 } 377 c2=circle(p2,r1); 378 return 2; 379 } 380 //同时与直线u,v相切 半径r1的圆 381 int getcircle(line u,line v,double r1,circle &c1,circle &c2,circle &c3,circle &c4) 382 { 383 if (u.parallel(v))return 0; 384 line u1=line(u.a.add(u.b.sub(u.a).rotleft().trunc(r1)),u.b.add(u.b.sub(u.a).rotleft().trunc(r1))); 385 line u2=line(u.a.add(u.b.sub(u.a).rotright().trunc(r1)),u.b.add(u.b.sub(u.a).rotright().trunc(r1))); 386 line v1=line(v.a.add(v.b.sub(v.a).rotleft().trunc(r1)),v.b.add(v.b.sub(v.a).rotleft().trunc(r1))); 387 line v2=line(v.a.add(v.b.sub(v.a).rotright().trunc(r1)),v.b.add(v.b.sub(v.a).rotright().trunc(r1))); 388 c1.r=c2.r=c3.r=c4.r=r1; 389 c1.p=u1.crosspoint(v1); 390 c2.p=u1.crosspoint(v2); 391 c3.p=u2.crosspoint(v1); 392 c4.p=u2.crosspoint(v2); 393 return 4; 394 } 395 //同时与不相交圆cx,cy相切 半径为r1的圆 396 int getcircle(circle cx,circle cy,double r1,circle&c1,circle&c2) 397 { 398 circle x(cx.p,r1+cx.r),y(cy.p,r1+cy.r); 399 int t=x.pointcrosscircle(y,c1.p,c2.p); 400 if (!t)return 0; 401 c1.r=c2.r=r1; 402 return t; 403 } 404 int pointcrossline(line v,point &p1,point &p2)//求与线段交要先判断relationseg 405 { 406 if (!(*this).relationline(v))return 0; 407 point a=v.lineprog(p); 408 double d=v.dispointtoline(p); 409 d=sqrt(r*r-d*d); 410 if (dblcmp(d)==0) 411 { 412 p1=a; 413 p2=a; 414 return 1; 415 } 416 p1=a.sub(v.b.sub(v.a).trunc(d)); 417 p2=a.add(v.b.sub(v.a).trunc(d)); 418 return 2; 419 } 420 //5 相离 421 //4 外切 422 //3 相交 423 //2 内切 424 //1 内含 425 int relationcircle(circle v) 426 { 427 double d=p.distance(v.p); 428 if (dblcmp(d-r-v.r)>0)return 5; 429 if (dblcmp(d-r-v.r)==0)return 4; 430 double l=fabs(r-v.r); 431 if (dblcmp(d-r-v.r)<0&&dblcmp(d-l)>0)return 3; 432 if (dblcmp(d-l)==0)return 2; 433 if (dblcmp(d-l)<0)return 1; 434 } 435 int pointcrosscircle(circle v,point &p1,point &p2) 436 { 437 int rel=relationcircle(v); 438 if (rel==1||rel==5)return 0; 439 double d=p.distance(v.p); 440 double l=(d+(sqr(r)-sqr(v.r))/d)/2; 441 double h=sqrt(sqr(r)-sqr(l)); 442 p1=p.add(v.p.sub(p).trunc(l).add(v.p.sub(p).rotleft().trunc(h))); 443 p2=p.add(v.p.sub(p).trunc(l).add(v.p.sub(p).rotright().trunc(h))); 444 if (rel==2||rel==4) 445 { 446 return 1; 447 } 448 return 2; 449 } 450 //过一点做圆的切线 (先判断点和圆关系) 451 int tangentline(point q,line &u,line &v) 452 { 453 int x=relation(q); 454 if (x==2)return 0; 455 if (x==1) 456 { 457 u=line(q,q.add(q.sub(p).rotleft())); 458 v=u; 459 return 1; 460 } 461 double d=p.distance(q); 462 double l=sqr(r)/d; 463 double h=sqrt(sqr(r)-sqr(l)); 464 u=line(q,p.add(q.sub(p).trunc(l).add(q.sub(p).rotleft().trunc(h)))); 465 v=line(q,p.add(q.sub(p).trunc(l).add(q.sub(p).rotright().trunc(h)))); 466 return 2; 467 } 468 double areacircle(circle v) 469 { 470 int rel=relationcircle(v); 471 if (rel>=4)return 0.0; 472 if (rel<=2)return min(area(),v.area()); 473 double d=p.distance(v.p); 474 double hf=(r+v.r+d)/2.0; 475 double ss=2*sqrt(hf*(hf-r)*(hf-v.r)*(hf-d)); 476 double a1=acos((r*r+d*d-v.r*v.r)/(2.0*r*d)); 477 a1=a1*r*r; 478 double a2=acos((v.r*v.r+d*d-r*r)/(2.0*v.r*d)); 479 a2=a2*v.r*v.r; 480 return a1+a2-ss; 481 } 482 double areatriangle(point a,point b) 483 { 484 if (dblcmp(p.sub(a).det(p.sub(b))==0))return 0.0; 485 point q[5]; 486 int len=0; 487 q[len++]=a; 488 line l(a,b); 489 point p1,p2; 490 if (pointcrossline(l,q[1],q[2])==2) 491 { 492 if (dblcmp(a.sub(q[1]).dot(b.sub(q[1])))<0)q[len++]=q[1]; 493 if (dblcmp(a.sub(q[2]).dot(b.sub(q[2])))<0)q[len++]=q[2]; 494 } 495 q[len++]=b; 496 if (len==4&&(dblcmp(q[0].sub(q[1]).dot(q[2].sub(q[1])))>0))swap(q[1],q[2]); 497 double res=0; 498 int i; 499 for (i=0;i<len-1;i++) 500 { 501 if (relation(q[i])==0||relation(q[i+1])==0) 502 { 503 double arg=p.rad(q[i],q[i+1]); 504 res+=r*r*arg/2.0; 505 } 506 else 507 { 508 res+=fabs(q[i].sub(p).det(q[i+1].sub(p))/2.0); 509 } 510 } 511 return res; 512 } 513 }; 514 struct polygon 515 { 516 int n; 517 point p[maxp]; 518 line l[maxp]; 519 void input() 520 { 521 n=4; 522 for (int i=0;i<n;i++) 523 { 524 p[i].input(); 525 } 526 } 527 void add(point q) 528 { 529 p[n++]=q; 530 } 531 void getline() 532 { 533 for (int i=0;i<n;i++) 534 { 535 l[i]=line(p[i],p[(i+1)%n]); 536 } 537 } 538 struct cmp 539 { 540 point p; 541 cmp(const point &p0){p=p0;} 542 bool operator()(const point &aa,const point &bb) 543 { 544 point a=aa,b=bb; 545 int d=dblcmp(a.sub(p).det(b.sub(p))); 546 if (d==0) 547 { 548 return dblcmp(a.distance(p)-b.distance(p))<0; 549 } 550 return d>0; 551 } 552 }; 553 void norm() 554 { 555 point mi=p[0]; 556 for (int i=1;i<n;i++)mi=min(mi,p[i]); 557 sort(p,p+n,cmp(mi)); 558 } 559 void getconvex(polygon &convex) 560 { 561 int i,j,k; 562 sort(p,p+n); 563 convex.n=n; 564 for (i=0;i<min(n,2);i++) 565 { 566 convex.p[i]=p[i]; 567 } 568 if (n<=2)return; 569 int &top=convex.n; 570 top=1; 571 for (i=2;i<n;i++) 572 { 573 while (top&&convex.p[top].sub(p[i]).det(convex.p[top-1].sub(p[i]))<=0) 574 top--; 575 convex.p[++top]=p[i]; 576 } 577 int temp=top; 578 convex.p[++top]=p[n-2]; 579 for (i=n-3;i>=0;i--) 580 { 581 while (top!=temp&&convex.p[top].sub(p[i]).det(convex.p[top-1].sub(p[i]))<=0) 582 top--; 583 convex.p[++top]=p[i]; 584 } 585 } 586 bool isconvex() 587 { 588 bool s[3]; 589 memset(s,0,sizeof(s)); 590 int i,j,k; 591 for (i=0;i<n;i++) 592 { 593 j=(i+1)%n; 594 k=(j+1)%n; 595 s[dblcmp(p[j].sub(p[i]).det(p[k].sub(p[i])))+1]=1; 596 if (s[0]&&s[2])return 0; 597 } 598 return 1; 599 } 600 //3 点上 601 //2 边上 602 //1 内部 603 //0 外部 604 int relationpoint(point q) 605 { 606 int i,j; 607 for (i=0;i<n;i++) 608 { 609 if (p[i]==q)return 3; 610 } 611 getline(); 612 for (i=0;i<n;i++) 613 { 614 if (l[i].pointonseg(q))return 2; 615 } 616 int cnt=0; 617 for (i=0;i<n;i++) 618 { 619 j=(i+1)%n; 620 int k=dblcmp(q.sub(p[j]).det(p[i].sub(p[j]))); 621 int u=dblcmp(p[i].y-q.y); 622 int v=dblcmp(p[j].y-q.y); 623 if (k>0&&u<0&&v>=0)cnt++; 624 if (k<0&&v<0&&u>=0)cnt--; 625 } 626 return cnt!=0; 627 } 628 //1 在多边形内长度为正 629 //2 相交或与边平行 630 //0 无任何交点 631 int relationline(line u) 632 { 633 int i,j,k=0; 634 getline(); 635 for (i=0;i<n;i++) 636 { 637 if (l[i].segcrossseg(u)==2)return 1; 638 if (l[i].segcrossseg(u)==1)k=1; 639 } 640 if (!k)return 0; 641 vector<point>vp; 642 for (i=0;i<n;i++) 643 { 644 if (l[i].segcrossseg(u)) 645 { 646 if (l[i].parallel(u)) 647 { 648 vp.pb(u.a); 649 vp.pb(u.b); 650 vp.pb(l[i].a); 651 vp.pb(l[i].b); 652 continue; 653 } 654 vp.pb(l[i].crosspoint(u)); 655 } 656 } 657 sort(vp.begin(),vp.end()); 658 int sz=vp.size(); 659 for (i=0;i<sz-1;i++) 660 { 661 point mid=vp[i].add(vp[i+1]).div(2); 662 if (relationpoint(mid)==1)return 1; 663 } 664 return 2; 665 } 666 //直线u切割凸多边形左侧 667 //注意直线方向 668 void convexcut(line u,polygon &po) 669 { 670 int i,j,k; 671 int &top=po.n; 672 top=0; 673 for (i=0;i<n;i++) 674 { 675 int d1=dblcmp(p[i].sub(u.a).det(u.b.sub(u.a))); 676 int d2=dblcmp(p[(i+1)%n].sub(u.a).det(u.b.sub(u.a))); 677 if (d1>=0)po.p[top++]=p[i]; 678 if (d1*d2<0)po.p[top++]=u.crosspoint(line(p[i],p[(i+1)%n])); 679 } 680 } 681 double getcircumference() 682 { 683 double sum=0; 684 int i; 685 for (i=0;i<n;i++) 686 { 687 sum+=p[i].distance(p[(i+1)%n]); 688 } 689 return sum; 690 } 691 double getarea() 692 { 693 double sum=0; 694 int i; 695 for (i=0;i<n;i++) 696 { 697 sum+=p[i].det(p[(i+1)%n]); 698 } 699 return fabs(sum)/2; 700 } 701 bool getdir()//1代表逆时针 0代表顺时针 702 { 703 double sum=0; 704 int i; 705 for (i=0;i<n;i++) 706 { 707 sum+=p[i].det(p[(i+1)%n]); 708 } 709 if (dblcmp(sum)>0)return 1; 710 return 0; 711 } 712 point getbarycentre() 713 { 714 point ret(0,0); 715 double area=0; 716 int i; 717 for (i=1;i<n-1;i++) 718 { 719 double tmp=p[i].sub(p[0]).det(p[i+1].sub(p[0])); 720 if (dblcmp(tmp)==0)continue; 721 area+=tmp; 722 ret.x+=(p[0].x+p[i].x+p[i+1].x)/3*tmp; 723 ret.y+=(p[0].y+p[i].y+p[i+1].y)/3*tmp; 724 } 725 if (dblcmp(area))ret=ret.div(area); 726 return ret; 727 } 728 double areaintersection(polygon po) 729 { 730 } 731 double areaunion(polygon po) 732 { 733 return getarea()+po.getarea()-areaintersection(po); 734 } 735 double areacircle(circle c) 736 { 737 int i,j,k,l,m; 738 double ans=0; 739 for (i=0;i<n;i++) 740 { 741 int j=(i+1)%n; 742 if (dblcmp(p[j].sub(c.p).det(p[i].sub(c.p)))>=0) 743 { 744 ans+=c.areatriangle(p[i],p[j]); 745 } 746 else 747 { 748 ans-=c.areatriangle(p[i],p[j]); 749 } 750 } 751 return fabs(ans); 752 } 753 //多边形和圆关系 754 //0 一部分在圆外 755 //1 与圆某条边相切 756 //2 完全在圆内 757 int relationcircle(circle c) 758 { 759 getline(); 760 int i,x=2; 761 if (relationpoint(c.p)!=1)return 0; 762 for (i=0;i<n;i++) 763 { 764 if (c.relationseg(l[i])==2)return 0; 765 if (c.relationseg(l[i])==1)x=1; 766 } 767 return x; 768 } 769 void find(int st,point tri[],circle &c) 770 { 771 if (!st) 772 { 773 c=circle(point(0,0),-2); 774 } 775 if (st==1) 776 { 777 c=circle(tri[0],0); 778 } 779 if (st==2) 780 { 781 c=circle(tri[0].add(tri[1]).div(2),tri[0].distance(tri[1])/2.0); 782 } 783 if (st==3) 784 { 785 c=circle(tri[0],tri[1],tri[2]); 786 } 787 } 788 void solve(int cur,int st,point tri[],circle &c) 789 { 790 find(st,tri,c); 791 if (st==3)return; 792 int i; 793 for (i=0;i<cur;i++) 794 { 795 if (dblcmp(p[i].distance(c.p)-c.r)>0) 796 { 797 tri[st]=p[i]; 798 solve(i,st+1,tri,c); 799 } 800 } 801 } 802 circle mincircle()//点集最小圆覆盖 803 { 804 random_shuffle(p,p+n); 805 point tri[4]; 806 circle c; 807 solve(n,0,tri,c); 808 return c; 809 } 810 int circlecover(double r)//单位圆覆盖 811 { 812 int ans=0,i,j; 813 vector<pair<double,int> >v; 814 for (i=0;i<n;i++) 815 { 816 v.clear(); 817 for (j=0;j<n;j++)if (i!=j) 818 { 819 point q=p[i].sub(p[j]); 820 double d=q.len(); 821 if (dblcmp(d-2*r)<=0) 822 { 823 double arg=atan2(q.y,q.x); 824 if (dblcmp(arg)<0)arg+=2*pi; 825 double t=acos(d/(2*r)); 826 v.push_back(make_pair(arg-t+2*pi,-1)); 827 v.push_back(make_pair(arg+t+2*pi,1)); 828 } 829 } 830 sort(v.begin(),v.end()); 831 int cur=0; 832 for (j=0;j<v.size();j++) 833 { 834 if (v[j].second==-1)++cur; 835 else --cur; 836 ans=max(ans,cur); 837 } 838 } 839 return ans+1; 840 } 841 int pointinpolygon(point q)//点在凸多边形内部的判定 842 { 843 if (getdir())reverse(p,p+n); 844 if (dblcmp(q.sub(p[0]).det(p[n-1].sub(p[0])))==0) 845 { 846 if (line(p[n-1],p[0]).pointonseg(q))return n-1; 847 return -1; 848 } 849 int low=1,high=n-2,mid; 850 while (low<=high) 851 { 852 mid=(low+high)>>1; 853 if (dblcmp(q.sub(p[0]).det(p[mid].sub(p[0])))>=0&&dblcmp(q.sub(p[0]).det(p[mid+1].sub(p[0])))<0) 854 { 855 polygon c; 856 c.p[0]=p[mid]; 857 c.p[1]=p[mid+1]; 858 c.p[2]=p[0]; 859 c.n=3; 860 if (c.relationpoint(q))return mid; 861 return -1; 862 } 863 if (dblcmp(q.sub(p[0]).det(p[mid].sub(p[0])))>0) 864 { 865 low=mid+1; 866 } 867 else 868 { 869 high=mid-1; 870 } 871 } 872 return -1; 873 } 874 }; 875 struct polygons 876 { 877 vector<polygon>p; 878 polygons() 879 { 880 p.clear(); 881 } 882 void clear() 883 { 884 p.clear(); 885 } 886 void push(polygon q) 887 { 888 if (dblcmp(q.getarea()))p.pb(q); 889 } 890 vector<pair<double,int> >e; 891 void ins(point s,point t,point X,int i) 892 { 893 double r=fabs(t.x-s.x)>eps?(X.x-s.x)/(t.x-s.x):(X.y-s.y)/(t.y-s.y); 894 r=min(r,1.0);r=max(r,0.0); 895 e.pb(mp(r,i)); 896 } 897 double polyareaunion() 898 { 899 double ans=0.0; 900 int c0,c1,c2,i,j,k,w; 901 for (i=0;i<p.size();i++) 902 { 903 if (p[i].getdir()==0)reverse(p[i].p,p[i].p+p[i].n); 904 } 905 for (i=0;i<p.size();i++) 906 { 907 for (k=0;k<p[i].n;k++) 908 { 909 point &s=p[i].p[k],&t=p[i].p[(k+1)%p[i].n]; 910 if (!dblcmp(s.det(t)))continue; 911 e.clear(); 912 e.pb(mp(0.0,1)); 913 e.pb(mp(1.0,-1)); 914 for (j=0;j<p.size();j++)if (i!=j) 915 { 916 for (w=0;w<p[j].n;w++) 917 { 918 point a=p[j].p[w],b=p[j].p[(w+1)%p[j].n],c=p[j].p[(w-1+p[j].n)%p[j].n]; 919 c0=dblcmp(t.sub(s).det(c.sub(s))); 920 c1=dblcmp(t.sub(s).det(a.sub(s))); 921 c2=dblcmp(t.sub(s).det(b.sub(s))); 922 if (c1*c2<0)ins(s,t,line(s,t).crosspoint(line(a,b)),-c2); 923 else if (!c1&&c0*c2<0)ins(s,t,a,-c2); 924 else if (!c1&&!c2) 925 { 926 int c3=dblcmp(t.sub(s).det(p[j].p[(w+2)%p[j].n].sub(s))); 927 int dp=dblcmp(t.sub(s).dot(b.sub(a))); 928 if (dp&&c0)ins(s,t,a,dp>0?c0*((j>i)^(c0<0)):-(c0<0)); 929 if (dp&&c3)ins(s,t,b,dp>0?-c3*((j>i)^(c3<0)):c3<0); 930 } 931 } 932 } 933 sort(e.begin(),e.end()); 934 int ct=0; 935 double tot=0.0,last; 936 for (j=0;j<e.size();j++) 937 { 938 if (ct==2)tot+=e[j].first-last; 939 ct+=e[j].second; 940 last=e[j].first; 941 } 942 ans+=s.det(t)*tot; 943 } 944 } 945 return fabs(ans)*0.5; 946 } 947 }; 948 const int maxn=500; 949 struct circles 950 { 951 circle c[maxn]; 952 double ans[maxn];//ans[i]表示被覆盖了i次的面积 953 double pre[maxn]; 954 int n; 955 circles(){} 956 void add(circle cc) 957 { 958 c[n++]=cc; 959 } 960 bool inner(circle x,circle y) 961 { 962 if (x.relationcircle(y)!=1)return 0; 963 return dblcmp(x.r-y.r)<=0?1:0; 964 } 965 void init_or()//圆的面积并去掉内含的圆 966 { 967 int i,j,k=0; 968 bool mark[maxn]={0}; 969 for (i=0;i<n;i++) 970 { 971 for (j=0;j<n;j++)if (i!=j&&!mark[j]) 972 { 973 if ((c[i]==c[j])||inner(c[i],c[j]))break; 974 } 975 if (j<n)mark[i]=1; 976 } 977 for (i=0;i<n;i++)if (!mark[i])c[k++]=c[i]; 978 n=k; 979 } 980 void init_and()//圆的面积交去掉内含的圆 981 { 982 int i,j,k=0; 983 bool mark[maxn]={0}; 984 for (i=0;i<n;i++) 985 { 986 for (j=0;j<n;j++)if (i!=j&&!mark[j]) 987 { 988 if ((c[i]==c[j])||inner(c[j],c[i]))break; 989 } 990 if (j<n)mark[i]=1; 991 } 992 for (i=0;i<n;i++)if (!mark[i])c[k++]=c[i]; 993 n=k; 994 } 995 double areaarc(double th,double r) 996 { 997 return 0.5*sqr(r)*(th-sin(th)); 998 } 999 void getarea()1000 {1001 int i,j,k;1002 memset(ans,0,sizeof(ans));1003 vector<pair<double,int> >v;1004 for (i=0;i<n;i++)1005 {1006 v.clear();1007 v.push_back(make_pair(-pi,1));1008 v.push_back(make_pair(pi,-1));1009 for (j=0;j<n;j++)if (i!=j)1010 {1011 point q=c[j].p.sub(c[i].p);1012 double ab=q.len(),ac=c[i].r,bc=c[j].r;1013 if (dblcmp(ab+ac-bc)<=0)1014 {1015 v.push_back(make_pair(-pi,1));1016 v.push_back(make_pair(pi,-1));1017 continue;1018 }1019 if (dblcmp(ab+bc-ac)<=0)continue;1020 if (dblcmp(ab-ac-bc)>0) continue;1021 double th=atan2(q.y,q.x),fai=acos((ac*ac+ab*ab-bc*bc)/(2.0*ac*ab));1022 double a0=th-fai;1023 if (dblcmp(a0+pi)<0)a0+=2*pi;1024 double a1=th+fai;1025 if (dblcmp(a1-pi)>0)a1-=2*pi;1026 if (dblcmp(a0-a1)>0)1027 {1028 v.push_back(make_pair(a0,1));1029 v.push_back(make_pair(pi,-1));1030 v.push_back(make_pair(-pi,1));1031 v.push_back(make_pair(a1,-1));1032 }1033 else1034 {1035 v.push_back(make_pair(a0,1));1036 v.push_back(make_pair(a1,-1));1037 }1038 }1039 sort(v.begin(),v.end());1040 int cur=0;1041 for (j=0;j<v.size();j++)1042 {1043 if (cur&&dblcmp(v[j].first-pre[cur]))1044 {1045 ans[cur]+=areaarc(v[j].first-pre[cur],c[i].r);1046 ans[cur]+=0.5*point(c[i].p.x+c[i].r*cos(pre[cur]),c[i].p.y+c[i].r*sin(pre[cur])).det(point(c[i].p.x+c[i].r*cos(v[j].first),c[i].p.y+c[i].r*sin(v[j].first)));1047 }1048 cur+=v[j].second;1049 pre[cur]=v[j].first;1050 }1051 }1052 for (i=1;i<=n;i++)1053 {1054 ans[i]-=ans[i+1];1055 }1056 }1057 };1058 struct halfplane:public line1059 {1060 double angle;1061 halfplane(){}1062 //表示向量 a->b逆时针(左侧)的半平面1063 halfplane(point _a,point _b)1064 {1065 a=_a;1066 b=_b;1067 }1068 halfplane(line v)1069 {1070 a=v.a;1071 b=v.b;1072 }1073 void calcangle()1074 {1075 angle=atan2(b.y-a.y,b.x-a.x);1076 }1077 bool operator<(const halfplane &b)const1078 {1079 return angle<b.angle;1080 }1081 };1082 struct halfplanes1083 {1084 int n;1085 halfplane hp[maxp];1086 point p[maxp];1087 int que[maxp];1088 int st,ed;1089 void push(halfplane tmp)1090 {1091 hp[n++]=tmp;1092 }1093 void unique()1094 {1095 int m=1,i;1096 for (i=1;i<n;i++)1097 {1098 if (dblcmp(hp[i].angle-hp[i-1].angle))hp[m++]=hp[i];1099 else if (dblcmp(hp[m-1].b.sub(hp[m-1].a).det(hp[i].a.sub(hp[m-1].a))>0))hp[m-1]=hp[i];1100 }1101 n=m;1102 }1103 bool halfplaneinsert()1104 {1105 int i;1106 for (i=0;i<n;i++)hp[i].calcangle();1107 sort(hp,hp+n);1108 unique();1109 que[st=0]=0;1110 que[ed=1]=1;1111 p[1]=hp[0].crosspoint(hp[1]);1112 for (i=2;i<n;i++)1113 {1114 while (st<ed&&dblcmp((hp[i].b.sub(hp[i].a).det(p[ed].sub(hp[i].a))))<0)ed--;1115 while (st<ed&&dblcmp((hp[i].b.sub(hp[i].a).det(p[st+1].sub(hp[i].a))))<0)st++;1116 que[++ed]=i;1117 if (hp[i].parallel(hp[que[ed-1]]))return false;1118 p[ed]=hp[i].crosspoint(hp[que[ed-1]]);1119 }1120 while (st<ed&&dblcmp(hp[que[st]].b.sub(hp[que[st]].a).det(p[ed].sub(hp[que[st]].a)))<0)ed--;1121 while (st<ed&&dblcmp(hp[que[ed]].b.sub(hp[que[ed]].a).det(p[st+1].sub(hp[que[ed]].a)))<0)st++;1122 if (st+1>=ed)return false;1123 return true;1124 }1125 void getconvex(polygon &con)1126 {1127 p[st]=hp[que[st]].crosspoint(hp[que[ed]]);1128 con.n=ed-st+1;1129 int j=st,i=0;1130 for (;j<=ed;i++,j++)1131 {1132 con.p[i]=p[j];1133 }1134 }1135 };1136 struct point31137 {1138 double x,y,z;1139 point3(){}1140 point3(double _x,double _y,double _z):1141 x(_x),y(_y),z(_z){};1142 void input()1143 {1144 scanf("%lf%lf%lf",&x,&y,&z);1145 }1146 void output()1147 {1148 printf("%.2lf %.2lf %.2lf\n",x,y,z);1149 }1150 bool operator==(point3 a)1151 {1152 return dblcmp(a.x-x)==0&&dblcmp(a.y-y)==0&&dblcmp(a.z-z)==0;1153 }1154 bool operator<(point3 a)const1155 {1156 return dblcmp(a.x-x)==0?dblcmp(y-a.y)==0?dblcmp(z-a.z)<0:y<a.y:x<a.x;1157 }1158 double len()1159 {1160 return sqrt(len2());1161 }1162 double len2()1163 {1164 return x*x+y*y+z*z;1165 }1166 double distance(point3 p)1167 {1168 return sqrt((p.x-x)*(p.x-x)+(p.y-y)*(p.y-y)+(p.z-z)*(p.z-z));1169 }1170 point3 add(point3 p)1171 {1172 return point3(x+p.x,y+p.y,z+p.z);1173 }1174 point3 sub(point3 p)1175 {1176 return point3(x-p.x,y-p.y,z-p.z);1177 }1178 point3 mul(double d)1179 {1180 return point3(x*d,y*d,z*d);1181 }1182 point3 div(double d)1183 {1184 return point3(x/d,y/d,z/d);1185 }1186 double dot(point3 p)1187 {1188 return x*p.x+y*p.y+z*p.z;1189 }1190 point3 det(point3 p)1191 {1192 return point3(y*p.z-p.y*z,p.x*z-x*p.z,x*p.y-p.x*y);1193 }1194 double rad(point3 a,point3 b)1195 {1196 point3 p=(*this);1197 return acos(a.sub(p).dot(b.sub(p))/(a.distance(p)*b.distance(p)));1198 }1199 point3 trunc(double r)1200 {1201 r/=len();1202 return point3(x*r,y*r,z*r);1203 }1204 point3 rotate(point3 o,double r)1205 {1206 }1207 };1208 struct line31209 {1210 point3 a,b;1211 line3(){}1212 line3(point3 _a,point3 _b)1213 {1214 a=_a;1215 b=_b;1216 }1217 bool operator==(line3 v)1218 {1219 return (a==v.a)&&(b==v.b);1220 }1221 void input()1222 {1223 a.input();1224 b.input();1225 }1226 double length()1227 {1228 return a.distance(b);1229 }1230 bool pointonseg(point3 p)1231 {1232 return dblcmp(p.sub(a).det(p.sub(b)).len())==0&&dblcmp(a.sub(p).dot(b.sub(p)))<=0;1233 }1234 double dispointtoline(point3 p)1235 {1236 return b.sub(a).det(p.sub(a)).len()/a.distance(b);1237 }1238 double dispointtoseg(point3 p)1239 {1240 if (dblcmp(p.sub(b).dot(a.sub(b)))<0||dblcmp(p.sub(a).dot(b.sub(a)))<0)1241 {1242 return min(p.distance(a),p.distance(b));1243 }1244 return dispointtoline(p);1245 }1246 point3 lineprog(point3 p)1247 {1248 return a.add(b.sub(a).trunc(b.sub(a).dot(p.sub(a))/b.distance(a)));1249 }1250 point3 rotate(point3 p,double ang)//p绕此向量逆时针arg角度1251 {1252 if (dblcmp((p.sub(a).det(p.sub(b)).len()))==0)return p;1253 point3 f1=b.sub(a).det(p.sub(a));1254 point3 f2=b.sub(a).det(f1);1255 double len=fabs(a.sub(p).det(b.sub(p)).len()/a.distance(b));1256 f1=f1.trunc(len);f2=f2.trunc(len);1257 point3 h=p.add(f2);1258 point3 pp=h.add(f1);1259 return h.add((p.sub(h)).mul(cos(ang*1.0))).add((pp.sub(h)).mul(sin(ang*1.0)));1260 }1261 };1262 struct plane1263 {1264 point3 a,b,c,o;1265 plane(){}1266 plane(point3 _a,point3 _b,point3 _c)1267 {1268 a=_a;1269 b=_b;1270 c=_c;1271 o=pvec();1272 }1273 plane(double _a,double _b,double _c,double _d)1274 {1275 //ax+by+cz+d=01276 o=point3(_a,_b,_c);1277 if (dblcmp(_a)!=0)1278 {1279 a=point3((-_d-_c-_b)/_a,1,1);1280 }1281 else if (dblcmp(_b)!=0)1282 {1283 a=point3(1,(-_d-_c-_a)/_b,1);1284 }1285 else if (dblcmp(_c)!=0)1286 {1287 a=point3(1,1,(-_d-_a-_b)/_c);1288 }1289 }1290 void input()1291 {1292 a.input();1293 b.input();1294 c.input();1295 o=pvec();1296 }1297 point3 pvec()1298 {1299 return b.sub(a).det(c.sub(a));1300 }1301 bool pointonplane(point3 p)//点是否在平面上1302 {1303 return dblcmp(p.sub(a).dot(o))==0;1304 }1305 //0 不在1306 //1 在边界上1307 //2 在内部1308 int pointontriangle(point3 p)//点是否在空间三角形abc上1309 {1310 if (!pointonplane(p))return 0;1311 double s=a.sub(b).det(c.sub(b)).len();1312 double s1=p.sub(a).det(p.sub(b)).len();1313 double s2=p.sub(a).det(p.sub(c)).len();1314 double s3=p.sub(b).det(p.sub(c)).len();1315 if (dblcmp(s-s1-s2-s3))return 0;1316 if (dblcmp(s1)&&dblcmp(s2)&&dblcmp(s3))return 2;1317 return 1;1318 }1319 //判断两平面关系1320 //0 相交1321 //1 平行但不重合1322 //2 重合1323 bool relationplane(plane f)1324 {1325 if (dblcmp(o.det(f.o).len()))return 0;1326 if (pointonplane(f.a))return 2;1327 return 1;1328 }1329 double angleplane(plane f)//两平面夹角1330 {1331 return acos(o.dot(f.o)/(o.len()*f.o.len()));1332 }1333 double dispoint(point3 p)//点到平面距离1334 {1335 return fabs(p.sub(a).dot(o)/o.len());1336 }1337 point3 pttoplane(point3 p)//点到平面最近点1338 {1339 line3 u=line3(p,p.add(o));1340 crossline(u,p);1341 return p;1342 }1343 int crossline(line3 u,point3 &p)//平面和直线的交点1344 {1345 double x=o.dot(u.b.sub(a));1346 double y=o.dot(u.a.sub(a));1347 double d=x-y;1348 if (dblcmp(fabs(d))==0)return 0;1349 p=u.a.mul(x).sub(u.b.mul(y)).div(d);1350 return 1;1351 }1352 int crossplane(plane f,line3 &u)//平面和平面的交线1353 {1354 point3 oo=o.det(f.o);1355 point3 v=o.det(oo);1356 double d=fabs(f.o.dot(v));1357 if (dblcmp(d)==0)return 0;1358 point3 q=a.add(v.mul(f.o.dot(f.a.sub(a))/d));1359 u=line3(q,q.add(oo));1360 return 1;1361 }1362 };
2.
1 #include<vector> 2 #include<list> 3 #include<map> 4 #include<set> 5 #include<deque> 6 #include<queue> 7 #include<stack> 8 #include<bitset> 9 #include<algorithm> 10 #include<functional> 11 #include<numeric> 12 #include<utility> 13 #include<iostream> 14 #include<sstream> 15 #include<iomanip> 16 #include<cstdio> 17 #include<cmath> 18 #include<cstdlib> 19 #include<cctype> 20 #include<string> 21 #include<cstring> 22 #include<cstdio> 23 #include<cmath> 24 #include<cstdlib> 25 #include<ctime> 26 #include<climits> 27 #include<complex> 28 #define mp make_pair 29 #define pb push_back 30 using namespace std; 31 const double eps=1e-8;//精度 32 const double pi=acos(-1.0);//π 33 const double inf=1e20;//无穷大 34 const int maxp=1111;//最大点数 35 /* 36 判断d是否在精度内等于0 37 */ 38 int dblcmp(double d) 39 { 40 if (fabs(d)<eps)return 0; 41 return d>eps?1:-1; 42 } 43 /* 44 求x的平方 45 */ 46 inline double sqr(double x){return x*x;} 47 /* 48 点/向量 49 */ 50 struct point 51 { 52 double x,y; 53 point(){} 54 point(double _x,double _y):x(_x),y(_y){}; 55 //读入一个点 56 void input() 57 { 58 scanf("%lf%lf",&x,&y); 59 } 60 //输出一个点 61 void output() 62 { 63 printf("%.2f %.2f\n",x,y); 64 } 65 //判断两点是否相等 66 bool operator==(point a)const 67 { 68 return dblcmp(a.x-x)==0&&dblcmp(a.y-y)==0; 69 } 70 //判断两点大小 71 bool operator<(point a)const 72 { 73 return dblcmp(a.x-x)==0?dblcmp(y-a.y)<0:x<a.x; 74 } 75 //点到源点的距离/向量的长度 76 double len() 77 { 78 return hypot(x,y); 79 } 80 //点到源点距离的平方 81 double len2() 82 { 83 return x*x+y*y; 84 } 85 //两点间的距离 86 double distance(point p) 87 { 88 return hypot(x-p.x,y-p.y); 89 } 90 //向量加 91 point add(point p) 92 { 93 return point(x+p.x,y+p.y); 94 } 95 //向量减 96 point sub(point p) 97 { 98 return point(x-p.x,y-p.y); 99 }100 //向量乘101 point mul(double b)102 {103 return point(x*b,y*b);104 }105 //向量除106 point div(double b)107 {108 return point(x/b,y/b);109 }110 //点乘111 double dot(point p)112 {113 return x*p.x+y*p.y;114 }115 //叉乘116 double det(point p)117 {118 return x*p.y-y*p.x;119 }120 //XXXXXXX121 double rad(point a,point b)122 {123 point p=*this;124 return fabs(atan2(fabs(a.sub(p).det(b.sub(p))),a.sub(p).dot(b.sub(p))));125 }126 //截取长度r127 point trunc(double r)128 {129 double l=len();130 if (!dblcmp(l))return *this;131 r/=l;132 return point(x*r,y*r);133 }134 //左转90度135 point rotleft()136 {137 return point(-y,x);138 }139 //右转90度140 point rotright()141 {142 return point(y,-x);143 }144 //绕点p逆时针旋转angle角度145 point rotate(point p,double angle)146 {147 point v=this->sub(p);148 double c=cos(angle),s=sin(angle);149 return point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c);150 }151 };152 /*153 线段/直线154 */155 struct line156 {157 point a,b;158 line(){}159 line(point _a,point _b)160 {161 a=_a;162 b=_b;163 }164 //判断线段相等165 bool operator==(line v)166 {167 return (a==v.a)&&(b==v.b);168 }169 //点p做倾斜角为angle的射线170 line(point p,double angle)171 {172 a=p;173 if (dblcmp(angle-pi/2)==0)174 {175 b=a.add(point(0,1));176 }177 else178 {179 b=a.add(point(1,tan(angle)));180 }181 }182 //直线一般式ax+by+c=0183 line(double _a,double _b,double _c)184 {185 if (dblcmp(_a)==0)186 {187 a=point(0,-_c/_b);188 b=point(1,-_c/_b);189 }190 else if (dblcmp(_b)==0)191 {192 a=point(-_c/_a,0);193 b=point(-_c/_a,1);194 }195 else196 {197 a=point(0,-_c/_b);198 b=point(1,(-_c-_a)/_b);199 }200 }201 //读入一个线段202 void input()203 {204 a.input();205 b.input();206 }207 //校准线段两点208 void adjust()209 {210 if (b<a)swap(a,b);211 }212 //线段长度213 double length()214 {215 return a.distance(b);216 }217 //直线倾斜角 0<=angle<180218 double angle()219 {220 double k=atan2(b.y-a.y,b.x-a.x);221 if (dblcmp(k)<0)k+=pi;222 if (dblcmp(k-pi)==0)k-=pi;223 return k;224 }225 //点和线段关系226 //1 在逆时针227 //2 在顺时针228 //3 平行229 int relation(point p)230 {231 int c=dblcmp(p.sub(a).det(b.sub(a)));232 if (c<0)return 1;233 if (c>0)return 2;234 return 3;235 }236 //点是否在线段上237 bool pointonseg(point p)238 {239 return dblcmp(p.sub(a).det(b.sub(a)))==0&&dblcmp(p.sub(a).dot(p.sub(b)))<=0;240 }241 //两线是否平行242 bool parallel(line v)243 {244 return dblcmp(b.sub(a).det(v.b.sub(v.a)))==0;245 }246 //线段和线段关系247 //0 不相交248 //1 非规范相交249 //2 规范相交250 int segcrossseg(line v)251 {252 int d1=dblcmp(b.sub(a).det(v.a.sub(a)));253 int d2=dblcmp(b.sub(a).det(v.b.sub(a)));254 int d3=dblcmp(v.b.sub(v.a).det(a.sub(v.a)));255 int d4=dblcmp(v.b.sub(v.a).det(b.sub(v.a)));256 if ((d1^d2)==-2&&(d3^d4)==-2)return 2;257 return (d1==0&&dblcmp(v.a.sub(a).dot(v.a.sub(b)))<=0||258 d2==0&&dblcmp(v.b.sub(a).dot(v.b.sub(b)))<=0||259 d3==0&&dblcmp(a.sub(v.a).dot(a.sub(v.b)))<=0||260 d4==0&&dblcmp(b.sub(v.a).dot(b.sub(v.b)))<=0);261 }262 //线段和直线v关系263 int linecrossseg(line v)//*this seg v line264 {265 int d1=dblcmp(b.sub(a).det(v.a.sub(a)));266 int d2=dblcmp(b.sub(a).det(v.b.sub(a)));267 if ((d1^d2)==-2)return 2;268 return (d1==0||d2==0);269 }270 //直线和直线关系271 //0 平行272 //1 重合273 //2 相交274 int linecrossline(line v)275 {276 if ((*this).parallel(v))277 {278 return v.relation(a)==3;279 }280 return 2;281 }282 //求两线交点283 point crosspoint(line v)284 {285 double a1=v.b.sub(v.a).det(a.sub(v.a));286 double a2=v.b.sub(v.a).det(b.sub(v.a));287 return point((a.x*a2-b.x*a1)/(a2-a1),(a.y*a2-b.y*a1)/(a2-a1));288 }289 //点p到直线的距离290 double dispointtoline(point p)291 {292 return fabs(p.sub(a).det(b.sub(a)))/length();293 }294 //点p到线段的距离295 double dispointtoseg(point p)296 {297 if (dblcmp(p.sub(b).dot(a.sub(b)))<0||dblcmp(p.sub(a).dot(b.sub(a)))<0)298 {299 return min(p.distance(a),p.distance(b));300 }301 return dispointtoline(p);302 }303 //XXXXXXXX304 point lineprog(point p)305 {306 return a.add(b.sub(a).mul(b.sub(a).dot(p.sub(a))/b.sub(a).len2()));307 }308 //点p关于直线的对称点309 point symmetrypoint(point p)310 {311 point q=lineprog(p);312 return point(2*q.x-p.x,2*q.y-p.y);313 }314 };315 316 /*317 多边形318 */319 struct polygon320 {321 int n;//点个数322 point p[maxp];//顶点323 line l[maxp];//边324 //读入一个多边形325 void input(int n=4)326 {327 for (int i=0;i<n;i++)328 {329 p[i].input();330 }331 }332 //添加一个点333 void add(point q)334 {335 p[n++]=q;336 }337 //取得边338 void getline()339 {340 for (int i=0;i<n;i++)341 {342 l[i]=line(p[i],p[(i+1)%n]);343 }344 }345 struct cmp346 {347 point p;348 cmp(const point &p0){p=p0;}349 bool operator()(const point &aa,const point &bb)350 {351 point a=aa,b=bb;352 int d=dblcmp(a.sub(p).det(b.sub(p)));353 if (d==0)354 {355 return dblcmp(a.distance(p)-b.distance(p))<0;356 }357 return d>0;358 }359 };360 void norm()361 {362 point mi=p[0];363 for (int i=1;i<n;i++)mi=min(mi,p[i]);364 sort(p,p+n,cmp(mi));365 }366 //求凸包存入多边形convex367 void getconvex(polygon &convex)368 {369 int i,j,k;370 sort(p,p+n);371 convex.n=n;372 for (i=0;i<min(n,2);i++)373 {374 convex.p[i]=p[i];375 }376 if (n<=2)return;377 int &top=convex.n;378 top=1;379 for (i=2;i<n;i++)380 {381 while (top&&convex.p[top].sub(p[i]).det(convex.p[top-1].sub(p[i]))<=0)382 top--;383 convex.p[++top]=p[i];384 }385 int temp=top;386 convex.p[++top]=p[n-2];387 for (i=n-3;i>=0;i--)388 {389 while (top!=temp&&convex.p[top].sub(p[i]).det(convex.p[top-1].sub(p[i]))<=0)390 top--;391 convex.p[++top]=p[i];392 }393 }394 //判断是否凸多边形395 bool isconvex()396 {397 bool s[3];398 memset(s,0,sizeof(s));399 int i,j,k;400 for (i=0;i<n;i++)401 {402 j=(i+1)%n;403 k=(j+1)%n;404 s[dblcmp(p[j].sub(p[i]).det(p[k].sub(p[i])))+1]=1;405 if (s[0]&&s[2])return 0;406 }407 return 1;408 }409 //点与多边形关系410 //0 外部411 //1 内部412 //2 边上413 //3 点上414 int relationpoint(point q)415 {416 int i,j;417 for (i=0;i<n;i++)418 {419 if (p[i]==q)return 3;420 }421 getline();422 for (i=0;i<n;i++)423 {424 if (l[i].pointonseg(q))return 2;425 }426 int cnt=0;427 for (i=0;i<n;i++)428 {429 j=(i+1)%n;430 int k=dblcmp(q.sub(p[j]).det(p[i].sub(p[j])));431 int u=dblcmp(p[i].y-q.y);432 int v=dblcmp(p[j].y-q.y);433 if (k>0&&u<0&&v>=0)cnt++;434 if (k<0&&v<0&&u>=0)cnt--;435 }436 return cnt!=0;437 }438 //线段与多边形关系439 //0 无任何交点440 //1 在多边形内长度为正441 //2 相交或与边平行442 int relationline(line u)443 {444 int i,j,k=0;445 getline();446 for (i=0;i<n;i++)447 {448 if (l[i].segcrossseg(u)==2)return 1;449 if (l[i].segcrossseg(u)==1)k=1;450 }451 if (!k)return 0;452 vector<point>vp;453 for (i=0;i<n;i++)454 {455 if (l[i].segcrossseg(u))456 {457 if (l[i].parallel(u))458 {459 vp.pb(u.a);460 vp.pb(u.b);461 vp.pb(l[i].a);462 vp.pb(l[i].b);463 continue;464 }465 vp.pb(l[i].crosspoint(u));466 }467 }468 sort(vp.begin(),vp.end());469 int sz=vp.size();470 for (i=0;i<sz-1;i++)471 {472 point mid=vp[i].add(vp[i+1]).div(2);473 if (relationpoint(mid)==1)return 1;474 }475 return 2;476 }477 //直线u切割凸多边形左侧478 //注意直线方向479 void convexcut(line u,polygon &po)480 {481 int i,j,k;482 int &top=po.n;483 top=0;484 for (i=0;i<n;i++)485 {486 int d1=dblcmp(p[i].sub(u.a).det(u.b.sub(u.a)));487 int d2=dblcmp(p[(i+1)%n].sub(u.a).det(u.b.sub(u.a)));488 if (d1>=0)po.p[top++]=p[i];489 if (d1*d2<0)po.p[top++]=u.crosspoint(line(p[i],p[(i+1)%n]));490 }491 }492 //取得周长493 double getcircumference()494 {495 double sum=0;496 int i;497 for (i=0;i<n;i++)498 {499 sum+=p[i].distance(p[(i+1)%n]);500 }501 return sum;502 }503 //取得面积504 double getarea()505 {506 double sum=0;507 int i;508 for (i=0;i<n;i++)509 {510 sum+=p[i].det(p[(i+1)%n]);511 }512 return fabs(sum)/2;513 }514 bool getdir()//1代表逆时针 0代表顺时针515 {516 double sum=0;517 int i;518 for (i=0;i<n;i++)519 {520 sum+=p[i].det(p[(i+1)%n]);521 }522 if (dblcmp(sum)>0)return 1;523 return 0;524 }525 //取得重心526 point getbarycentre()527 {528 point ret(0,0);529 double area=0;530 int i;531 for (i=1;i<n-1;i++)532 {533 double tmp=p[i].sub(p[0]).det(p[i+1].sub(p[0]));534 if (dblcmp(tmp)==0)continue;535 area+=tmp;536 ret.x+=(p[0].x+p[i].x+p[i+1].x)/3*tmp;537 ret.y+=(p[0].y+p[i].y+p[i+1].y)/3*tmp;538 }539 if (dblcmp(area))ret=ret.div(area);540 return ret;541 }542 //点在凸多边形内部的判定543 int pointinpolygon(point q)544 {545 if (getdir())reverse(p,p+n);546 if (dblcmp(q.sub(p[0]).det(p[n-1].sub(p[0])))==0)547 {548 if (line(p[n-1],p[0]).pointonseg(q))return n-1;549 return -1;550 }551 int low=1,high=n-2,mid;552 while (low<=high)553 {554 mid=(low+high)>>1;555 if (dblcmp(q.sub(p[0]).det(p[mid].sub(p[0])))>=0&&dblcmp(q.sub(p[0]).det(p[mid+1].sub(p[0])))<0)556 {557 polygon c;558 c.p[0]=p[mid];559 c.p[1]=p[mid+1];560 c.p[2]=p[0];561 c.n=3;562 if (c.relationpoint(q))return mid;563 return -1;564 }565 if (dblcmp(q.sub(p[0]).det(p[mid].sub(p[0])))>0)566 {567 low=mid+1;568 }569 else570 {571 high=mid-1;572 }573 }574 return -1;575 }576 };
[转]计算几何模板
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。