1#include"../../kyopro_library/template.hpp"
5 using Real=
long double;
41 Real
arg()
const{
return atan2(
y,
x);}
54 Line(
const Real&A,
const Real&B,
const Real&C){
119 return"COUNTER_CLOCKWISE";
125 return"ONLINE_FRONT";
171 return lessThanOrEqual(min(s
.a.x,s
.b.x),p
.x)&&
199 Real d1=abs(cross(base,s1
.a-s2
.a));
200 Real d2=abs(cross(base,s1
.b-s2
.a));
224 for(
int i=0;i<n;++i){
226 area+=points[i].x*points[j].y;
227 area-=points[i].y*points[j].x;
229 return abs(area)/2.0;
233 bool has_positive=
false,has_negative=
false;
234 for(
int i=0;i<n;++i){
237 Point a=points[j]-points[i];
238 Point b=points[k]-points[j];
243 return!(has_positive&&has_negative);
246 int n=polygon.size();
247 for(
int i=0;i<n;++i){
249 Point b=polygon[(i+1)%n];
256 int n=polygon.size();
257 bool inPolygon=
false;
258 for(
int i=0;i<n;++i){
260 Point b=polygon[(i+1)%n];
271 if(n<=1)
return points;
272 sort(points.begin(),points.end(),[](
const Point&l,
const Point&r)->
bool{
276 if(n==2)
return points;
277 vector<Point>upper={points[0],points[1]},lower={points[0],points[1]};
278 for(
int i=2;i<n;++i){
279 while((
int)upper.size()>=2&&ccw(upper.end()[-2],upper.end()[-1],points[i])!=
CLOCKWISE){
280 if(ccw(upper.end()[-2],upper.end()[-1],points[i])==
ONLINE_FRONT&&include_collinear)
break;
283 upper.push_back(points[i]);
284 while((
int)lower.size()>=2&&ccw(lower.end()[-2],lower.end()[-1],points[i])!=COUNTER_CLOCKWISE){
285 if(ccw(lower.end()[-2],lower.end()[-1],points[i])==ONLINE_FRONT&&include_collinear)
break;
288 lower.push_back(points[i]);
290 reverse(upper.begin(),upper.end());
293 lower.insert(lower.end(),upper.begin(),upper.end());
301 for(
int i=0;i<n;++i){
304 Point dist1=hull[i]-hull[j],dist2=hull[i]-hull[k];
305 max_dist=max(max_dist,dist1
.abs());
306 max_dist=max(max_dist,dist2
.abs());
313 Point dist=hull[i]-hull[k];
314 max_dist=max(max_dist,dist
.abs());
320 vector<Point>newPolygon;
322 for(
int i=0;i<n;++i){
323 const Point&cur=g[i];
324 const Point&next=g[(i+1)%n];
325 if(isLeft(l
.a,l
.b,cur))newPolygon.push_back(cur);
326 if((isLeft(l
.a,l
.b,cur)&&!isLeft(l
.a,l
.b,next))||(!isLeft(l
.a,l
.b,cur)&&isLeft(l
.a,l
.b,next))){
330 newPolygon.push_back(intersection);
339 if(r-l<=1)
return numeric_limits<Real>::max();
341 Real x=points[mid].x;
342 Real d=min(closestPair(points,l,mid),closestPair(points,mid,r));
343 auto iti=points.begin(),itl=iti+l,itm=iti+mid,itr=iti+r;
344 inplace_merge(itl,itm,itr,[](
const Point&lhs,
const Point&rhs)->
bool{
347 vector<Point>nearLine;
348 for(
int i=l;i<r;++i){
349 if(greaterThanOrEqual(fabs(points[i].x-x),d))
continue;
350 int sz=nearLine.size();
351 for(
int j=sz-1;j>=0;--j){
352 Point dv=points[i]-nearLine[j];
356 nearLine.push_back(points[i]);
368 Event(Real x,
int type,Real y1,Real y2):x(x),type(type),y1(y1),y2(y2){}
369 bool operator<(
const Event&other)
const{
370 if(x==other.x)
return type<other.type;
375 sort(segments.begin(),segments.end(),[](
const Segment&lhs,
const Segment&rhs)->
bool{
378 for(
const auto&seg:segments){
379 if(seg.a.y==seg.b.y){
382 Real x1=min(seg.a.x,seg.b.x);
383 Real x2=max(seg.a.x,seg.b.x);
384 events.emplace_back(x1,0,y,y);
385 events.emplace_back(x2,2,y,y);
389 Real y1=min(seg.a.y,seg.b.y);
390 Real y2=max(seg.a.y,seg.b.y);
391 events.emplace_back(x,1,y1,y2);
394 sort(events.begin(),events.end());
395 set<Real>activeSegments;
396 int intersectionCount=0;
397 for(
const auto&event:events){
400 activeSegments.insert(event.y1);
401 }
else if(event.type==2){
403 activeSegments.erase(event.y1);
404 }
else if(event.type==1){
406 auto lower=activeSegments.lower_bound(event.y1);
407 auto upper=activeSegments.upper_bound(event.y2);
408 intersectionCount+=distance(lower,upper);
411 return intersectionCount;
419 Real r1=c1
.r,r2=c2
.r;
424 }
else if(greaterThan(d,fabs(r1-r2))){
426 }
else if(almostEqual(d,fabs(r1-r2))){
437 Real area=sqrt(s*(s-a)*(s-b)*(s-c));
439 Real cx=(a*A
.x+b*B
.x+c*C
.x)/(a+b+c);
440 Real cy=(a*A
.y+b*B
.y+c*C
.y)/(a+b+c);
456 Real b=2*(dx*(p1
.x-cx)+dy*(p1
.y-cy));
457 Real c_const=(p1
.x-cx)*(p1
.x-cx)+(p1
.y-cy)*(p1
.y-cy)-r*r;
458 Real discriminant=b*b-4*a*c_const;
459 vector<Point>intersections;
464 intersections.emplace_back(ix,iy);
465 intersections.emplace_back(ix,iy);
466 }
else if(discriminant>0){
467 Real sqrt_discriminant=sqrt(discriminant);
468 Real t1=(-b+sqrt_discriminant)/(2*a);
469 Real t2=(-b-sqrt_discriminant)/(2*a);
474 intersections.emplace_back(ix1,iy1);
475 intersections.emplace_back(ix2,iy2);
477 if(almostEqual(intersections[0].x,intersections[1].x)){
478 if(greaterThan(intersections[0].y,intersections[1].y))swap(intersections[0],intersections[1]);
479 }
else if(greaterThan(intersections[0].x,intersections[1].x)){
480 swap(intersections[0],intersections[1]);
482 return intersections;
487 Real d=sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
488 if(d>r1+r2||d<abs(r1-r2))
return{};
489 Real a=(r1*r1-r2*r2+d*d)/(2*d);
490 Real h=sqrt(r1*r1-a*a);
491 Real x0=x1+a*(x2-x1)/d;
492 Real y0=y1+a*(y2-y1)/d;
493 Real rx=-(y2-y1)*(h/d);
494 Real ry=(x2-x1)*(h/d);
497 vector<Point>intersections;
498 intersections.push_back(p1);
499 intersections.push_back(p2);
500 if(almostEqual(intersections[0].x,intersections[1].x)){
501 if(greaterThan(intersections[0].y,intersections[1].y))swap(intersections[0],intersections[1]);
502 }
else if(greaterThan(intersections[0].x,intersections[1].x)){
503 swap(intersections[0],intersections[1]);
505 return intersections;
519 Real h=sqrt(r*r-a*a);
522 vector<Point>tangents;
523 tangents.emplace_back(cx1+h*dy/d,cy1-h*dx/d);
524 tangents.emplace_back(cx1-h*dy/d,cy1+h*dx/d);
525 if(almostEqual(tangents[0].x,tangents[1].x)){
526 if(greaterThan(tangents[0].y,tangents[1].y))swap(tangents[0],tangents[1]);
527 }
else if(greaterThan(tangents[0].x,tangents[1].x)){
528 swap(tangents[0],tangents[1]);
537 Real d=sqrt(dx*dx+dy*dy);
538 vector<Segment>tangents;
544 for(
int sign:{-1,1}){
545 Real theta=acos((r1+r2)/d);
546 Real cx1=x1+r1*cos(a+sign*theta);
547 Real cy1=y1+r1*sin(a+sign*theta);
548 Real cx2=x2+r2*cos(a+sign*theta);
549 Real cy2=y2+r2*sin(a+sign*theta);
550 tangents.emplace_back(Segment{Point(cx1,cy1),Point(cx2,cy2)});
551 if(almostEqual(d,r1+r2))
break;
555 if(greaterThanOrEqual(d,fabs(r1-r2))){
557 for(
int sign:{-1,1}){
558 Real theta=acos((r1-r2)/d);
559 Real cx1=x1+r1*cos(a+sign*theta);
560 Real cy1=y1+r1*sin(a+sign*theta);
561 Real cx2=x2-r2*cos(a+sign*theta);
562 Real cy2=y2-r2*sin(a+sign*theta);
563 tangents.emplace_back(Segment{Point(cx1,cy1),Point(cx2,cy2)});
564 if(almostEqual(d,fabs(r1-r2)))
568 sort(tangents.begin(),tangents.end(),[&](
const Segment&s1,
const Segment&s2){
bool isOrthogonal(const Segment &l1, const Line &l2)
bool isParallel(const Segment &l1, const Line &l2)
int countCirclesIntersection(const Circle &c1, const Circle &c2)
bool isOrthogonal(const Line &l1, const Segment &l2)
vector< Point > cutPolygon(const vector< Point > &g, const Line &l)
bool isParallel(const Line &l1, const Segment &l2)
Real distanceSegmentToSegment(const Segment &s1, const Segment &s2)
int countIntersections(vector< Segment >segments)
Point projection(const Point &p1, const Point &p2, const Point &p)
ベクトル p の直線 p1, p2 への正射影ベクトルを返す
Point reflection(const Line &l, const Point &p)
ベクトル p の直線 l に対する鏡像ベクトルを返す
Point reflection(const Point &p1, const Point &p2, const Point &p)
ベクトル p の直線 p1, p2 に対する鏡像ベクトルを返す
bool greaterThanOrEqual(Real a, Real b)
bool isPointInsidePolygon(const vector< Point > &polygon, const Point &p)
Real distancePointToSegment(const Point &p, const Segment &s)
bool isOrthogonal(const Segment &l1, const Segment &l2)
bool isParallel(const Line &l1, const Line &l2)
Real closestPair(vector< Point > &points, int l, int r)
Circle getCircumCircle(const Point &A, const Point &B, const Point &C)
vector< Segment > getCommonTangentsLine(const Circle &c1, const Circle &c2)
Point projection(const Line &l, const Point &p)
ベクトル p の直線 l への正射影ベクトルを返す
Orientation ccw(const Point &p0, const Point &p1, const Point &p2)
3点 p0, p1, p2 の進行方向を返す
Circle getInCircle(const Point &A, const Point &B, const Point &C)
Real convexHullDiameter(const vector< Point > &hull)
Point getIntersection(const Segment &s1, const Segment &s2)
bool greaterThan(Real a, Real b)
bool isPointOnLine(const Point &p, const Line &l)
bool almostEqual(Real a, Real b)
string orientationToString(Orientation o)
Real getPolygonArea(const vector< Point > &points)
bool lessThanOrEqual(Real a, Real b)
bool isParallel(const Segment &l1, const Segment &l2)
bool isConvex(const vector< Point > &points)
bool isPointOnSegment(const Point &p, const Segment &s)
bool isOrthogonal(const Line &l1, const Line &l2)
bool lessThan(Real a, Real b)
bool isPointOnPolygon(const vector< Point > &polygon, const Point &p)
vector< Point > getCircleLineIntersection(const Circle &c, Point p1, Point p2)
vector< Point > convexHull(vector< Point > &points, bool include_collinear=false)
vector< Point > getCirclesIntersect(const Circle &c1, const Circle &c2)
bool isIntersecting(const Segment &s1, const Segment &s2)
vector< Point > getTangentLinesFromPoint(const Circle &c, const Point &p)
Circle(Real x, Real y, Real r)
bool operator==(const Circle &C) const
friend istream & operator>>(istream &is, Circle &C)
Circle(Point _center, Real r)
friend istream & operator>>(istream &is, Line &l)
Line(const Real &A, const Real &B, const Real &C)
直線 Ax+By=C を定義する
Line(const Point &_a, const Point &_b)
bool operator==(const Line &l) const
Real cross(const Point &p) const
p との外積を返す
Point operator/(Real k) const
friend istream & operator>>(istream &is, Point &p)
Point operator*(Real k) const
Real norm() const
2乗ノルムを返す
Real abs() const
ユークリッドノルムを返す
Real dot(const Point &p) const
p との内積を返す
bool operator==(const Point &p) const
Point operator+(const Point &p) const
Point operator-(const Point &p) const
Real cross(const Point &p1, const Point &p2) const
p1 と p2 を端点とするベクトルとの外積を返す