#pragma once
#include"geometry-base.hpp"usingPolygon=vector<Point>;// 多角形の内部に点があるか?// OUT : 0, ON : 1, IN : 2intcontains_polygon(constPolygon&Q,constPoint&p){boolin=false;for(inti=0;i<(int)Q.size();i++){Pointa=Q[i]-p,b=Q[(i+1)%Q.size()]-p;if(imag(a)>imag(b))swap(a,b);if(sign(imag(a))<=0&&0<sign(imag(b))&&sign(cross(a,b))<0)in=!in;if(equals(cross(a,b),0)&&sign(dot(a,b))<=0)return1;}returnin?2:0;}// 多角形の面積Realarea(constPolygon&p){RealA=0;for(inti=0;i<(int)p.size();++i){A+=cross(p[i],p[(i+1)%p.size()]);}returnA*0.5;}// 頂点集合から凸包を生成// boundary : 周上の点も列挙する場合 truetemplate<boolboundary=false>Polygonconvex_hull(vector<Point>ps){sort(begin(ps),end(ps));ps.erase(unique(begin(ps),end(ps)),end(ps));intn=ps.size(),k=0;if(n<=2)returnps;vector<Point>ch(2*n);// 反時計周りRealth=boundary?-EPS:+EPS;for(inti=0;i<n;ch[k++]=ps[i++]){while(k>=2&&cross(ch[k-1]-ch[k-2],ps[i]-ch[k-1])<th)--k;}for(inti=n-2,t=k+1;i>=0;ch[k++]=ps[i--]){while(k>=t&&cross(ch[k-1]-ch[k-2],ps[i]-ch[k-1])<th)--k;}ch.resize(k-1);returnch;}// 凸包の内部に点があるか?// OUT : 0, ON : 1, IN : 2intcontains_convex(constPolygon&C,constPoint&p){intN=C.size();autob1=cross(C[1]-C[0],p-C[0]);autob2=cross(C[N-1]-C[0],p-C[0]);if(b1<-EPSorb2>EPS)return0;intL=1,R=N-1;while(L+1<R){intM=(L+R)/2;(cross(p-C[0],C[M]-C[0])>=0?R:L)=M;}autov=cross(C[L]-p,C[R]-p);if(equals(v,0)){return1;}elseif(v>0){returnequals(b1,0)orequals(b2,0)?1:2;}else{return0;}}// 凸包が与えられるので最遠点対を返す// 返り値:頂点番号のペアpair<int,int>convex_polygon_diameter(constPolygon&p){intN=(int)p.size();intis=0,js=0;for(inti=1;i<N;i++){if(imag(p[i])>imag(p[is]))is=i;if(imag(p[i])<imag(p[js]))js=i;}Realmaxdis=norm(p[is]-p[js]);intmaxi,maxj,i,j;i=maxi=is;j=maxj=js;do{if(cross(p[(i+1)%N]-p[i],p[(j+1)%N]-p[j])>=0){j=(j+1)%N;}else{i=(i+1)%N;}if(norm(p[i]-p[j])>maxdis){maxdis=norm(p[i]-p[j]);maxi=i;maxj=j;}}while(i!=is||j!=js);returnminmax(maxi,maxj);}
#line 2 "geometry/polygon.hpp"
#line 2 "geometry/geometry-base.hpp"
#include<algorithm>
#include<cassert>
#include<cmath>
#include<complex>
#include<iostream>
#include<vector>usingnamespacestd;usingReal=longdouble;constexprRealEPS=1e-10;constexprRealpi=3.141592653589793238462643383279L;boolequals(Reala,Realb){returnfabs(b-a)<EPS;}intsign(Reala){returnequals(a,0)?0:a>0?1:-1;}template<typenameR>structPointBase{usingP=PointBase;Rx,y;PointBase():x(0),y(0){}PointBase(R_x,R_y):x(_x),y(_y){}template<typenameT,typenameU>PointBase(constpair<T,U>&p):x(p.first),y(p.second){}Poperator+(constP&r)const{return{x+r.x,y+r.y};}Poperator-(constP&r)const{return{x-r.x,y-r.y};}Poperator*(Rr)const{return{x*r,y*r};}Poperator/(Rr)const{return{x/r,y/r};}P&operator+=(constP&r){return(*this)=(*this)+r;}P&operator-=(constP&r){return(*this)=(*this)-r;}P&operator*=(Rr){return(*this)=(*this)*r;}P&operator/=(Rr){return(*this)=(*this)/r;}booloperator<(constP&r)const{returnx!=r.x?x<r.x:y<r.y;}booloperator==(constP&r)const{returnx==r.xandy==r.y;}booloperator!=(constP&r)const{return!((*this)==r);}Protate(Rrad)const{return{x*cos(rad)-y*sin(rad),x*sin(rad)+y*cos(rad)};}Rreal()const{returnx;}Rimag()const{returny;}friendRreal(constP&p){returnp.x;}friendRimag(constP&p){returnp.y;}friendRdot(constP&l,constP&r){returnl.x*r.x+l.y*r.y;}friendRcross(constP&l,constP&r){returnl.x*r.y-l.y*r.x;}friendRabs(constP&p){returnsqrt(p.x*p.x+p.y*p.y);}friendRnorm(constP&p){returnp.x*p.x+p.y*p.y;}friendRarg(constP&p){returnatan2(p.y,p.x);}friendistream&operator>>(istream&is,P&p){Ra,b;is>>a>>b;p=P{a,b};returnis;}friendostream&operator<<(ostream&os,constP&p){returnos<<p.x<<" "<<p.y;}};usingPoint=PointBase<Real>;usingPoints=vector<Point>;// ccw, 点の進行方向intccw(constPoint&a,constPoint&b,constPoint&c){Pointx=b-a,y=c-a;if(cross(x,y)>EPS)return+1;// 反時計回りif(cross(x,y)<-EPS)return-1;// 時計回りif(min(norm(x),norm(y))<EPS*EPS)return0;// c=a または c=bif(dot(x,y)<EPS)return+2;// c-a-b の順で一直線if(norm(x)<norm(y))return-2;// a-b-c の順で一直線return0;// a-c-b の順で一直線}#line 4 "geometry/polygon.hpp"
usingPolygon=vector<Point>;// 多角形の内部に点があるか?// OUT : 0, ON : 1, IN : 2intcontains_polygon(constPolygon&Q,constPoint&p){boolin=false;for(inti=0;i<(int)Q.size();i++){Pointa=Q[i]-p,b=Q[(i+1)%Q.size()]-p;if(imag(a)>imag(b))swap(a,b);if(sign(imag(a))<=0&&0<sign(imag(b))&&sign(cross(a,b))<0)in=!in;if(equals(cross(a,b),0)&&sign(dot(a,b))<=0)return1;}returnin?2:0;}// 多角形の面積Realarea(constPolygon&p){RealA=0;for(inti=0;i<(int)p.size();++i){A+=cross(p[i],p[(i+1)%p.size()]);}returnA*0.5;}// 頂点集合から凸包を生成// boundary : 周上の点も列挙する場合 truetemplate<boolboundary=false>Polygonconvex_hull(vector<Point>ps){sort(begin(ps),end(ps));ps.erase(unique(begin(ps),end(ps)),end(ps));intn=ps.size(),k=0;if(n<=2)returnps;vector<Point>ch(2*n);// 反時計周りRealth=boundary?-EPS:+EPS;for(inti=0;i<n;ch[k++]=ps[i++]){while(k>=2&&cross(ch[k-1]-ch[k-2],ps[i]-ch[k-1])<th)--k;}for(inti=n-2,t=k+1;i>=0;ch[k++]=ps[i--]){while(k>=t&&cross(ch[k-1]-ch[k-2],ps[i]-ch[k-1])<th)--k;}ch.resize(k-1);returnch;}// 凸包の内部に点があるか?// OUT : 0, ON : 1, IN : 2intcontains_convex(constPolygon&C,constPoint&p){intN=C.size();autob1=cross(C[1]-C[0],p-C[0]);autob2=cross(C[N-1]-C[0],p-C[0]);if(b1<-EPSorb2>EPS)return0;intL=1,R=N-1;while(L+1<R){intM=(L+R)/2;(cross(p-C[0],C[M]-C[0])>=0?R:L)=M;}autov=cross(C[L]-p,C[R]-p);if(equals(v,0)){return1;}elseif(v>0){returnequals(b1,0)orequals(b2,0)?1:2;}else{return0;}}// 凸包が与えられるので最遠点対を返す// 返り値:頂点番号のペアpair<int,int>convex_polygon_diameter(constPolygon&p){intN=(int)p.size();intis=0,js=0;for(inti=1;i<N;i++){if(imag(p[i])>imag(p[is]))is=i;if(imag(p[i])<imag(p[js]))js=i;}Realmaxdis=norm(p[is]-p[js]);intmaxi,maxj,i,j;i=maxi=is;j=maxj=js;do{if(cross(p[(i+1)%N]-p[i],p[(j+1)%N]-p[j])>=0){j=(j+1)%N;}else{i=(i+1)%N;}if(norm(p[i]-p[j])>maxdis){maxdis=norm(p[i]-p[j]);maxi=i;maxj=j;}}while(i!=is||j!=js);returnminmax(maxi,maxj);}