#line 1 "verify/geometry/voronoi_diagram.test.cpp"
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/problems/2160"
#define ERROR "1e-4"
#line 1 "geometry/voronoi_diagram.hpp"
#include<algorithm>
#include<array>
#include<cassert>
#include<cmath>
#include<concepts>
#include<cstddef>
#include<limits>
#include<numeric>
#include<utility>
#include<vector>#line 1 "geometry/euclidean_mst.hpp"
#line 10 "geometry/euclidean_mst.hpp"
#include<tuple>
#line 13 "geometry/euclidean_mst.hpp"
#line 1 "ds/dsu/dsu.hpp"
#line 8 "ds/dsu/dsu.hpp"
namespacem1une{namespaceds{structDsu{private:int_n;// parent_or_size[i] is the parent of i if it's >= 0.// If it's < 0, then i is a root and -parent_or_size[i] is the size of the group.std::vector<int>parent_or_size;// Returns {new leader, absorbed leader}. The absorbed leader is -1 when// both vertices already belong to the same component.std::pair<int,int>merge_leaders(inta,intb){intx=leader(a),y=leader(b);if(x==y)return{x,-1};if(-parent_or_size[x]<-parent_or_size[y])std::swap(x,y);parent_or_size[x]+=parent_or_size[y];parent_or_size[y]=x;return{x,y};}public:Dsu():_n(0){}explicitDsu(intn):_n(n),parent_or_size(n,-1){}// Merges the group containing 'a' with the group containing 'b'.// Returns the leader of the merged group.intmerge(inta,intb){returnmerge_leaders(a,b).first;}// Invokes callback(new_leader, absorbed_leader) after an actual merge.// Returns the leader of the merged group.template<classCallback>intmerge(inta,intb,Callback&&callback){std::pair<int,int>merged=merge_leaders(a,b);if(merged.second!=-1)callback(merged.first,merged.second);returnmerged.first;}// Returns true if 'a' and 'b' belong to the same group.boolsame(inta,intb){returnleader(a)==leader(b);}// Returns the leader (representative) of the group containing 'a'.intleader(inta){if(parent_or_size[a]<0)returna;// Path compressionreturnparent_or_size[a]=leader(parent_or_size[a]);}// Returns the size of the group containing 'a'.intsize(inta){return-parent_or_size[leader(a)];}// Returns a list of all groups, where each group is a vector of its elements.std::vector<std::vector<int>>groups(){std::vector<int>leader_buf(_n),group_size(_n);for(inti=0;i<_n;i++){leader_buf[i]=leader(i);group_size[leader_buf[i]]++;}std::vector<std::vector<int>>result(_n);for(inti=0;i<_n;i++){result[i].reserve(group_size[i]);}for(inti=0;i<_n;i++){result[leader_buf[i]].push_back(i);}result.erase(std::remove_if(result.begin(),result.end(),[&](conststd::vector<int>&v){returnv.empty();}),result.end());returnresult;}};}// namespace ds}// namespace m1une#line 1 "geometry/point.hpp"
#line 7 "geometry/point.hpp"
#include<type_traits>#line 1 "geometry/detail/floating_predicate.hpp"
namespacem1une{namespacegeometry{namespacepredicate_detail{template<typenameT>constexprTabsolute(Tvalue){returnvalue<T(0)?-value:value;}template<typenameT>constexprTmax_value(Tfirst,Tsecond){returnfirst<second?second:first;}template<typenameT>constexprTvector_scale(Tx,Ty){returnmax_value(absolute(x),absolute(y));}template<boolExact,typenameT>constexprintscaled_sign(Tvalue,Tscale,longdoubleeps){ifconstexpr(Exact){return(value>T(0))-(value<T(0));}else{constTtolerance=T(eps)*scale;return(value>tolerance)-(value<-tolerance);}}template<boolExact,typenameT>constexprTdeterminant_scale(Tax,Tay,Tbx,Tby){ifconstexpr(Exact){returnT(0);}else{returnvector_scale(ax,ay)*vector_scale(bx,by);}}template<boolExact,typenameT>constexprintdeterminant_sign(Tax,Tay,Tbx,Tby,longdoubleeps){constTdeterminant=ax*by-ay*bx;returnscaled_sign<Exact>(determinant,determinant_scale<Exact>(ax,ay,bx,by),eps);}template<boolExact,typenameT>constexprintorientation_sign(Tdirection_x,Tdirection_y,Toffset_x,Toffset_y,longdoubleeps){constTdeterminant=direction_x*offset_y-direction_y*offset_x;Tscale=T(0);ifconstexpr(!Exact){constTdirection_scale=vector_scale(direction_x,direction_y);scale=direction_scale*max_value(direction_scale,vector_scale(offset_x,offset_y));}returnscaled_sign<Exact>(determinant,scale,eps);}template<boolExact,typenameT>constexprintdot_sign(Tax,Tay,Tbx,Tby,longdoubleeps){constTvalue=ax*bx+ay*by;Tscale=T(0);ifconstexpr(!Exact){scale=vector_scale(ax,ay)*vector_scale(bx,by);}returnscaled_sign<Exact>(value,scale,eps);}}// namespace predicate_detail}// namespace geometry}// namespace m1une#line 10 "geometry/point.hpp"
namespacem1une{namespacegeometry{template<typenameT>conceptCoordinate=!std::same_as<std::remove_cv_t<T>,bool>&&(std::is_arithmetic_v<T>||(std::copyable<T>&&std::totally_ordered<T>&&requires(Ta,Tb){T(0);T(1);static_cast<longdouble>(a);{+a}->std::same_as<T>;{-a}->std::same_as<T>;{a+b}->std::same_as<T>;{a-b}->std::same_as<T>;{a*b}->std::same_as<T>;{a/b}->std::same_as<T>;{a+=b}->std::same_as<T&>;{a-=b}->std::same_as<T&>;}));// Custom coordinate types keep their own exact arithmetic.template<typenameT>conceptExactCoordinate=Coordinate<T>&&!std::floating_point<T>;template<CoordinateT>usingwide_type=std::conditional_t<std::integral<T>,__int128_t,std::conditional_t<std::floating_point<T>,longdouble,T>>;template<CoordinateT>structPoint{Tx;Ty;constexprPoint():x(0),y(0){}constexprPoint(Tx_value,Ty_value):x(x_value),y(y_value){}template<CoordinateU>explicitconstexprPoint(constPoint<U>&other):x(static_cast<T>(other.x)),y(static_cast<T>(other.y)){}constexprPoint&operator+=(constPoint&other){x+=other.x;y+=other.y;return*this;}constexprPoint&operator-=(constPoint&other){x-=other.x;y-=other.y;return*this;}constexprPointoperator+()const{return*this;}constexprPointoperator-()const{returnPoint(-x,-y);}friendconstexprPointoperator+(Pointleft,constPoint&right){returnleft+=right;}friendconstexprPointoperator-(Pointleft,constPoint&right){returnleft-=right;}friendconstexprbooloperator==(constPoint&,constPoint&)=default;friendconstexprbooloperator<(constPoint&left,constPoint&right){if(left.x!=right.x)returnleft.x<right.x;returnleft.y<right.y;}};template<CoordinateT>constexprPoint<longdouble>centroid(constPoint<T>&point){returnPoint<longdouble>(point);}template<CoordinateT,typenameScalar>requires(std::is_arithmetic_v<Scalar>||Coordinate<Scalar>)constexprautooperator*(constPoint<T>&point,Scalarscalar){usingResult=std::common_type_t<T,Scalar>;returnPoint<Result>(Result(point.x)*Result(scalar),Result(point.y)*Result(scalar));}template<typenameScalar,CoordinateT>requires(std::is_arithmetic_v<Scalar>||Coordinate<Scalar>)constexprautooperator*(Scalarscalar,constPoint<T>&point){returnpoint*scalar;}template<CoordinateT,typenameScalar>requires(std::is_arithmetic_v<Scalar>||Coordinate<Scalar>)constexprautooperator/(constPoint<T>&point,Scalarscalar){usingResult=std::common_type_t<T,Scalar>;returnPoint<Result>(Result(point.x)/Result(scalar),Result(point.y)/Result(scalar));}template<CoordinateT>constexprwide_type<T>dot(constPoint<T>&a,constPoint<T>&b){usingW=wide_type<T>;returnW(a.x)*W(b.x)+W(a.y)*W(b.y);}template<CoordinateT>constexprwide_type<T>cross(constPoint<T>&a,constPoint<T>&b){usingW=wide_type<T>;returnW(a.x)*W(b.y)-W(a.y)*W(b.x);}template<CoordinateT>constexprwide_type<T>cross(constPoint<T>&origin,constPoint<T>&a,constPoint<T>&b){usingW=wide_type<T>;Wax=W(a.x)-W(origin.x);Way=W(a.y)-W(origin.y);Wbx=W(b.x)-W(origin.x);Wby=W(b.y)-W(origin.y);returnax*by-ay*bx;}template<CoordinateT>constexprwide_type<T>norm2(constPoint<T>&point){returndot(point,point);}template<CoordinateT>constexprwide_type<T>distance2(constPoint<T>&a,constPoint<T>&b){usingW=wide_type<T>;Wdx=W(a.x)-W(b.x);Wdy=W(a.y)-W(b.y);returndx*dx+dy*dy;}template<CoordinateT>longdoublenorm(constPoint<T>&point){returnstd::hypot(static_cast<longdouble>(point.x),static_cast<longdouble>(point.y));}template<CoordinateT>longdoubledistance(constPoint<T>&a,constPoint<T>&b){returnstd::hypot(static_cast<longdouble>(a.x)-static_cast<longdouble>(b.x),static_cast<longdouble>(a.y)-static_cast<longdouble>(b.y));}template<CoordinateT,typenameM,typenameN>requires(std::is_arithmetic_v<M>||Coordinate<M>)&&(std::is_arithmetic_v<N>||Coordinate<N>)constexprPoint<longdouble>internal_division_point(constPoint<T>&a,constPoint<T>&b,Mm,Nn){longdoublefirst_ratio=static_cast<longdouble>(m);longdoublesecond_ratio=static_cast<longdouble>(n);longdoubledenominator=first_ratio+second_ratio;assert(denominator!=0);Point<longdouble>first(a);Point<longdouble>direction=Point<longdouble>(b)-first;returnfirst+direction*(first_ratio/denominator);}template<CoordinateT,typenameM,typenameN>requires(std::is_arithmetic_v<M>||Coordinate<M>)&&(std::is_arithmetic_v<N>||Coordinate<N>)constexprPoint<longdouble>external_division_point(constPoint<T>&a,constPoint<T>&b,Mm,Nn){longdoublefirst_ratio=static_cast<longdouble>(m);longdoublesecond_ratio=static_cast<longdouble>(n);longdoubledenominator=first_ratio-second_ratio;assert(denominator!=0);Point<longdouble>first(a);Point<longdouble>direction=Point<longdouble>(b)-first;returnfirst+direction*(first_ratio/denominator);}template<CoordinateT>constexprintsign(wide_type<T>value,longdoubleeps=1e-12L){returnpredicate_detail::scaled_sign<ExactCoordinate<T>>(value,wide_type<T>(1),eps);}template<CoordinateT>constexprintorientation(constPoint<T>&a,constPoint<T>&b,constPoint<T>&c,longdoubleeps=1e-12L){usingW=wide_type<T>;constWfirst_x=W(b.x)-W(a.x);constWfirst_y=W(b.y)-W(a.y);constWsecond_x=W(c.x)-W(a.x);constWsecond_y=W(c.y)-W(a.y);returnpredicate_detail::orientation_sign<ExactCoordinate<T>>(first_x,first_y,second_x,second_y,eps);}template<CoordinateT>constexprboolcollinear(constPoint<T>&a,constPoint<T>&b,constPoint<T>&c,longdoubleeps=1e-12L){returnorientation(a,b,c,eps)==0;}template<CoordinateT>Point<longdouble>rotate(constPoint<T>&point,longdoubleangle){longdoublecosine=std::cos(angle);longdoublesine=std::sin(angle);returnPoint<longdouble>(static_cast<longdouble>(point.x)*cosine-static_cast<longdouble>(point.y)*sine,static_cast<longdouble>(point.x)*sine+static_cast<longdouble>(point.y)*cosine);}template<CoordinateT>Point<longdouble>normalized(constPoint<T>&point){longdoublelength=norm(point);assert(length!=0);returnPoint<longdouble>(static_cast<longdouble>(point.x)/length,static_cast<longdouble>(point.y)/length);}}// namespace geometry}// namespace m1une#line 16 "geometry/euclidean_mst.hpp"
namespacem1une{namespacegeometry{template<classT>structEuclideanMstEdge{intfrom;intto;Tsquared_distance;};template<classT>structEuclideanMst{longdoublecost;std::vector<EuclideanMstEdge<T>>edges;};namespacedetail{template<ExactCoordinateT>classEuclideanDelaunay{private:usingW=wide_type<T>;structInternalPoint{Wx;Wy;friendbooloperator==(constInternalPoint&,constInternalPoint&)=default;};structEdge{intto;intccw;intcw;intreverse;boolenabled=false;};std::vector<int>open_addresses;std::vector<InternalPoint>points;std::vector<Edge>edges;std::vector<int>duplicate_representative;staticInternalPointsubtract(constInternalPoint&a,constInternalPoint&b){returnInternalPoint{a.x-b.x,a.y-b.y};}staticWcross_product(constInternalPoint&a,constInternalPoint&b){returna.x*b.y-a.y*b.x;}staticWsquared_norm(constInternalPoint&point){returnpoint.x*point.x+point.y*point.y;}staticboolinside_circumcircle(InternalPointa,InternalPointb,InternalPointc,constInternalPoint&d){a=subtract(a,d);b=subtract(b,d);c=subtract(c,d);Wdeterminant=cross_product(b,c)*squared_norm(a)+cross_product(c,a)*squared_norm(b)+cross_product(a,b)*squared_norm(c);returndeterminant>0;}intget_open_address(){if(open_addresses.empty()){edges.push_back(Edge());returnint(edges.size())-1;}intresult=open_addresses.back();open_addresses.pop_back();returnresult;}std::pair<int,int>add_edge(intfrom,intto){intforward=get_open_address();intbackward=get_open_address();edges[forward].to=to;edges[forward].ccw=forward;edges[forward].cw=forward;edges[forward].reverse=backward;edges[forward].enabled=true;edges[backward].to=from;edges[backward].ccw=backward;edges[backward].cw=backward;edges[backward].reverse=forward;edges[backward].enabled=true;return{forward,backward};}voiderase_directed_edge(intedge){intccw=edges[edge].ccw;intcw=edges[edge].cw;edges[ccw].cw=cw;edges[cw].ccw=ccw;edges[edge].enabled=false;}voiderase_edge(intedge){intreverse=edges[edge].reverse;erase_directed_edge(edge);erase_directed_edge(reverse);open_addresses.push_back(edge);open_addresses.push_back(reverse);}voidinsert_ccw_after(intedge,intposition){intnext=edges[position].ccw;edges[edge].ccw=next;edges[next].cw=edge;edges[edge].cw=position;edges[position].ccw=edge;}voidinsert_cw_after(intedge,intposition){intnext=edges[position].cw;edges[edge].cw=next;edges[next].ccw=edge;edges[edge].ccw=position;edges[position].cw=edge;}intorientation(inta,intb,intc)const{InternalPointab=subtract(points[b],points[a]);InternalPointac=subtract(points[c],points[a]);Wvalue=cross_product(ab,ac);return(value>0)-(value<0);}std::pair<int,int>go_next(intedge)const{intvertex=edges[edge].to;intnext_edge=edges[edges[edge].reverse].ccw;return{vertex,next_edge};}std::pair<int,int>go_previous(intedge)const{intvertex=edges[edges[edge].cw].to;intnext_edge=edges[edges[edge].cw].reverse;return{vertex,next_edge};}std::tuple<int,int,int,int>lower_tangent(intleft_vertex,intleft_edge,intright_vertex,intright_edge)const{while(true){auto[next_left_vertex,next_left_edge]=go_previous(left_edge);if(orientation(right_vertex,left_vertex,next_left_vertex)>0){left_vertex=next_left_vertex;left_edge=next_left_edge;continue;}auto[next_right_vertex,next_right_edge]=go_next(right_edge);if(orientation(left_vertex,right_vertex,next_right_vertex)<0){right_vertex=next_right_vertex;right_edge=next_right_edge;continue;}break;}return{left_vertex,left_edge,right_vertex,right_edge};}std::pair<int,int>extreme_vertex(intvertex,intedge,boolminimum)const{std::pair<int,int>result={vertex,edge};intcurrent_vertex=vertex;intcurrent_edge=edge;do{std::tie(current_vertex,current_edge)=go_next(current_edge);std::pair<int,int>candidate={current_vertex,current_edge};if((minimum&&candidate<result)||(!minimum&&result<candidate)){result=candidate;}}while(current_edge!=edge);returnresult;}boolinside_circumcircle(inta,intb,intc,intd)const{returninside_circumcircle(points[a],points[b],points[c],points[d]);}std::pair<int,int>merge_triangulations(intleft_vertex,intleft_edge,intright_vertex,intright_edge){std::tie(left_vertex,left_edge)=extreme_vertex(left_vertex,left_edge,false);std::tie(right_vertex,right_edge)=extreme_vertex(right_vertex,right_edge,true);auto[lower_left,lower_left_edge,lower_right,lower_right_edge]=lower_tangent(left_vertex,left_edge,right_vertex,right_edge);auto[upper_right,upper_right_edge,upper_left,upper_left_edge]=lower_tangent(right_vertex,right_edge,left_vertex,left_edge);lower_right_edge=edges[lower_right_edge].cw;upper_right_edge=edges[upper_right_edge].cw;auto[base,reverse_base]=add_edge(lower_left,lower_right);insert_cw_after(base,lower_left_edge);insert_ccw_after(reverse_base,lower_right_edge);if(lower_left==upper_left)upper_left_edge=base;if(lower_right==upper_right)upper_right_edge=reverse_base;intleft=lower_left;intleft_candidate=lower_left_edge;intright=lower_right;intright_candidate=lower_right_edge;while(left!=upper_left||right!=upper_right){intnext_left=edges[left_candidate].to;intnext_right=edges[right_candidate].to;intnext_left_candidate=edges[left_candidate].ccw;intnext_right_candidate=edges[right_candidate].cw;if(left_candidate!=upper_left_edge&&next_left_candidate!=base){intsecond_left=edges[next_left_candidate].to;if(inside_circumcircle(left,right,next_left,second_left)){erase_edge(left_candidate);left_candidate=next_left_candidate;continue;}}if(right_candidate!=upper_right_edge&&next_right_candidate!=reverse_base){intsecond_right=edges[next_right_candidate].to;if(inside_circumcircle(next_right,left,right,second_right)){erase_edge(right_candidate);right_candidate=next_right_candidate;continue;}}boolchoose_left=right_candidate==upper_right_edge;if(left_candidate!=upper_left_edge&&right_candidate!=upper_right_edge){if(orientation(left,right,next_right)<0){choose_left=true;}elseif(orientation(next_left,left,right)<0){choose_left=false;}else{choose_left=inside_circumcircle(left,right,next_right,next_left);}}if(choose_left){next_left_candidate=edges[edges[left_candidate].reverse].ccw;auto[new_base,new_reverse_base]=add_edge(next_left,right);insert_cw_after(new_base,next_left_candidate);insert_ccw_after(new_reverse_base,right_candidate);left_candidate=next_left_candidate;left=next_left;}else{next_right_candidate=edges[edges[right_candidate].reverse].cw;auto[new_reverse_base,new_base]=add_edge(next_right,left);insert_ccw_after(new_reverse_base,next_right_candidate);insert_cw_after(new_base,left_candidate);right_candidate=next_right_candidate;right=next_right;}}return{lower_left,base};}std::pair<int,int>solve_range(intleft,intright){if(right-left==2){auto[forward,backward]=add_edge(left,left+1);(void)backward;return{left,forward};}if(right-left==3){intmiddle=left+1;intlast=left+2;auto[first_middle,middle_first]=add_edge(left,middle);auto[middle_last,last_middle]=add_edge(middle,last);intdirection=orientation(left,middle,last);if(direction==0){insert_ccw_after(middle_first,middle_last);return{left,first_middle};}auto[first_last,last_first]=add_edge(left,last);if(direction>0){insert_cw_after(first_middle,first_last);insert_cw_after(middle_last,middle_first);insert_cw_after(last_first,last_middle);return{left,first_middle};}insert_ccw_after(first_middle,first_last);insert_ccw_after(middle_last,middle_first);insert_ccw_after(last_first,last_middle);return{middle,middle_first};}intmiddle=(left+right)/2;auto[left_vertex,left_edge]=solve_range(left,middle);auto[right_vertex,right_edge]=solve_range(middle,right);returnmerge_triangulations(left_vertex,left_edge,right_vertex,right_edge);}voidsolve(){intsize=int(points.size());if(size<=1)return;std::vector<int>order(size);for(inti=0;i<size;i++)order[i]=i;std::stable_sort(order.begin(),order.end(),[&](intleft,intright){if(points[left].x!=points[right].x){returnpoints[left].x<points[right].x;}returnpoints[left].y<points[right].y;});std::vector<InternalPoint>original_points=points;duplicate_representative.assign(size,0);intunique_size=0;for(inti=0;i<size;i++){intvertex=order[i];if(i==0||!(original_points[order[unique_size-1]]==original_points[vertex])){order[unique_size]=vertex;points[unique_size]=original_points[vertex];unique_size++;duplicate_representative[vertex]=vertex;}else{duplicate_representative[vertex]=order[unique_size-1];}}if(unique_size>=2)solve_range(0,unique_size);points.swap(original_points);for(auto&edge:edges)edge.to=order[edge.to];}public:explicitEuclideanDelaunay(conststd::vector<Point<T>>&input_points){assert(input_points.size()<=std::size_t(std::numeric_limits<int>::max()));points.reserve(input_points.size());edges.reserve(std::size_t(6)*input_points.size());for(constauto&point:input_points){points.push_back(InternalPoint{W(point.x),W(point.y)});}solve();}boolhas_duplicates()const{for(intvertex=0;vertex<int(duplicate_representative.size());++vertex){if(duplicate_representative[vertex]!=vertex)returntrue;}returnfalse;}std::vector<std::pair<int,int>>get_edges()const{std::vector<std::pair<int,int>>result;result.reserve(edges.size()/2+duplicate_representative.size());for(intedge=0;edge<int(edges.size());edge++){if(!edges[edge].enabled)continue;intreverse=edges[edge].reverse;if(edge<reverse)continue;result.emplace_back(edges[edge].to,edges[reverse].to);}for(intvertex=0;vertex<int(duplicate_representative.size());vertex++){if(duplicate_representative[vertex]!=vertex){result.emplace_back(vertex,duplicate_representative[vertex]);}}returnresult;}};}// namespace detail// Returns O(n) Delaunay edges containing a Euclidean minimum spanning tree.template<ExactCoordinateT>std::vector<EuclideanMstEdge<wide_type<T>>>euclidean_mst_edges(conststd::vector<Point<T>>&points){usingW=wide_type<T>;autodelaunay_edges=detail::EuclideanDelaunay<T>(points).get_edges();std::vector<EuclideanMstEdge<W>>result;result.reserve(delaunay_edges.size());for(auto[from,to]:delaunay_edges){result.push_back(EuclideanMstEdge<W>{from,to,distance2(points[from],points[to])});}returnresult;}// Returns a Euclidean minimum spanning tree.template<ExactCoordinateT>EuclideanMst<wide_type<T>>euclidean_mst(conststd::vector<Point<T>>&points){usingW=wide_type<T>;autocandidates=euclidean_mst_edges(points);std::sort(candidates.begin(),candidates.end(),[](constauto&left,constauto&right){if(left.squared_distance!=right.squared_distance){returnleft.squared_distance<right.squared_distance;}if(left.from!=right.from)returnleft.from<right.from;returnleft.to<right.to;});m1une::ds::Dsudsu(int(points.size()));EuclideanMst<W>result;result.cost=0;result.edges.reserve(points.empty()?0:points.size()-1);for(constauto&edge:candidates){if(dsu.same(edge.from,edge.to))continue;dsu.merge(edge.from,edge.to);result.cost+=std::sqrt(static_cast<longdouble>(edge.squared_distance));result.edges.push_back(edge);if(result.edges.size()+1==points.size())break;}assert(points.empty()||result.edges.size()+1==points.size());returnresult;}}// namespace geometry}// namespace m1une#line 16 "geometry/voronoi_diagram.hpp"
namespacem1une{namespacegeometry{enumclassVoronoiEdgeKind{Segment,Ray,Line,};structVoronoiEdge{VoronoiEdgeKindkind;intfirst_site;intsecond_site;intfirst_vertex;intsecond_vertex;Point<longdouble>point;Point<longdouble>direction;};structVoronoiDiagram{std::vector<Point<longdouble>>vertices;std::vector<VoronoiEdge>edges;std::vector<std::vector<int>>cell_edges;};namespacevoronoi_diagram_detail{template<ExactCoordinateT>intdirection_half(constPoint<T>&origin,constPoint<T>&destination){usingW=wide_type<T>;Wx=W(destination.x)-W(origin.x);Wy=W(destination.y)-W(origin.y);returny>0||(y==0&&x>=0)?0:1;}template<ExactCoordinateT>booldirection_less(conststd::vector<Point<T>>&sites,intorigin,intfirst,intsecond){intfirst_half=direction_half(sites[origin],sites[first]);intsecond_half=direction_half(sites[origin],sites[second]);if(first_half!=second_half)returnfirst_half<second_half;usingW=wide_type<T>;Wfirst_x=W(sites[first].x)-W(sites[origin].x);Wfirst_y=W(sites[first].y)-W(sites[origin].y);Wsecond_x=W(sites[second].x)-W(sites[origin].x);Wsecond_y=W(sites[second].y)-W(sites[origin].y);Wproduct=first_x*second_y-first_y*second_x;if(product!=0)returnproduct>0;Wfirst_norm=first_x*first_x+first_y*first_y;Wsecond_norm=second_x*second_x+second_y*second_y;if(first_norm!=second_norm)returnfirst_norm<second_norm;returnfirst<second;}template<ExactCoordinateT>boolcocircular(constPoint<T>&first,constPoint<T>&second,constPoint<T>&third,constPoint<T>&fourth){usingW=wide_type<T>;Wax=W(first.x)-W(fourth.x);Way=W(first.y)-W(fourth.y);Wbx=W(second.x)-W(fourth.x);Wby=W(second.y)-W(fourth.y);Wcx=W(third.x)-W(fourth.x);Wcy=W(third.y)-W(fourth.y);Wa_norm=ax*ax+ay*ay;Wb_norm=bx*bx+by*by;Wc_norm=cx*cx+cy*cy;Wdeterminant=(bx*cy-by*cx)*a_norm+(cx*ay-cy*ax)*b_norm+(ax*by-ay*bx)*c_norm;returndeterminant==0;}template<ExactCoordinateT>Point<longdouble>circumcenter(constPoint<T>&first,constPoint<T>&second,constPoint<T>&third){longdoubleax=static_cast<longdouble>(first.x);longdoubleay=static_cast<longdouble>(first.y);longdoublebx=static_cast<longdouble>(second.x);longdoubleby=static_cast<longdouble>(second.y);longdoublecx=static_cast<longdouble>(third.x);longdoublecy=static_cast<longdouble>(third.y);longdoubledenominator=2*(ax*(by-cy)+bx*(cy-ay)+cx*(ay-by));assert(denominator!=0);longdoublefirst_norm=ax*ax+ay*ay;longdoublesecond_norm=bx*bx+by*by;longdoublethird_norm=cx*cx+cy*cy;returnPoint<longdouble>((first_norm*(by-cy)+second_norm*(cy-ay)+third_norm*(ay-by))/denominator,(first_norm*(cx-bx)+second_norm*(ax-cx)+third_norm*(bx-ax))/denominator);}inlinePoint<longdouble>unit(Point<longdouble>direction){longdoublelength=norm(direction);assert(length!=0);returndirection/length;}inlineintother_site(constVoronoiEdge&edge,intsite){assert(edge.first_site==site||edge.second_site==site);returnedge.first_site==site?edge.second_site:edge.first_site;}}// namespace voronoi_diagram_detail// Constructs the ordinary Euclidean Voronoi diagram of distinct exact-coordinate sites.template<ExactCoordinateT>VoronoiDiagramvoronoi_diagram(conststd::vector<Point<T>>&sites){namespacedetail=voronoi_diagram_detail;assert(sites.size()<=std::size_t(std::numeric_limits<int>::max()));constintsize=int(sites.size());std::vector<int>site_order(size);std::iota(site_order.begin(),site_order.end(),0);std::sort(site_order.begin(),site_order.end(),[&](intfirst,intsecond){returnsites[first]<sites[second];});for(intindex=1;index<size;++index){assert(sites[site_order[index-1]]!=sites[site_order[index]]);}std::vector<std::pair<int,int>>delaunay_edges=geometry::detail::EuclideanDelaunay<T>(sites).get_edges();for(auto&[first,second]:delaunay_edges){if(first>second)std::swap(first,second);}std::sort(delaunay_edges.begin(),delaunay_edges.end());delaunay_edges.erase(std::unique(delaunay_edges.begin(),delaunay_edges.end()),delaunay_edges.end());autofind_edge_index=[&](intfirst,intsecond){if(first>second)std::swap(first,second);autoiterator=std::lower_bound(delaunay_edges.begin(),delaunay_edges.end(),std::pair(first,second));if(iterator==delaunay_edges.end()||*iterator!=std::pair(first,second)){return-1;}returnint(iterator-delaunay_edges.begin());};std::vector<std::vector<int>>neighbors(size);for(intindex=0;index<int(delaunay_edges.size());++index){auto[first,second]=delaunay_edges[index];neighbors[first].push_back(second);neighbors[second].push_back(first);}for(intsite=0;site<size;++site){std::sort(neighbors[site].begin(),neighbors[site].end(),[&](intfirst,intsecond){returndetail::direction_less(sites,site,first,second);});}std::vector<std::array<int,3>>triangles;for(intsite=0;site<size;++site){intdegree=int(neighbors[site].size());for(intindex=0;index<degree;++index){intfirst=neighbors[site][index];intsecond=neighbors[site][(index+1)%degree];if(orientation(sites[site],sites[first],sites[second])<=0){continue;}if(find_edge_index(first,second)==-1)continue;std::array<int,3>triangle{site,first,second};std::sort(triangle.begin(),triangle.end());triangles.push_back(triangle);}}std::sort(triangles.begin(),triangles.end());triangles.erase(std::unique(triangles.begin(),triangles.end()),triangles.end());for(auto&triangle:triangles){if(orientation(sites[triangle[0]],sites[triangle[1]],sites[triangle[2]])<0){std::swap(triangle[1],triangle[2]);}}std::vector<std::array<int,2>>incident_triangles(delaunay_edges.size(),std::array<int,2>{-1,-1});std::vector<int>incident_count(delaunay_edges.size(),0);for(inttriangle=0;triangle<int(triangles.size());++triangle){for(intside=0;side<3;++side){intfirst=triangles[triangle][side];intsecond=triangles[triangle][(side+1)%3];intedge=find_edge_index(first,second);assert(edge!=-1);assert(incident_count[edge]<2);incident_triangles[edge][incident_count[edge]++]=triangle;}}std::vector<int>parent(triangles.size());std::vector<int>component_size(triangles.size(),1);std::iota(parent.begin(),parent.end(),0);autofind_root=[&](auto&&self,intvertex)->int{if(parent[vertex]==vertex)returnvertex;returnparent[vertex]=self(self,parent[vertex]);};automerge=[&](intfirst,intsecond){first=find_root(find_root,first);second=find_root(find_root,second);if(first==second)return;if(component_size[first]<component_size[second]){std::swap(first,second);}parent[second]=first;component_size[first]+=component_size[second];};for(intedge=0;edge<int(delaunay_edges.size());++edge){if(incident_count[edge]!=2)continue;intfirst_triangle=incident_triangles[edge][0];intsecond_triangle=incident_triangles[edge][1];constauto&first=triangles[first_triangle];constauto&second=triangles[second_triangle];intfourth=second[0];if(fourth==first[0]||fourth==first[1]||fourth==first[2]){fourth=second[1];}if(fourth==first[0]||fourth==first[1]||fourth==first[2]){fourth=second[2];}assert(fourth!=first[0]&&fourth!=first[1]&&fourth!=first[2]);if(detail::cocircular(sites[first[0]],sites[first[1]],sites[first[2]],sites[fourth])){merge(first_triangle,second_triangle);}}VoronoiDiagramresult;result.cell_edges.resize(size);std::vector<int>root_vertex(triangles.size(),-1);std::vector<int>triangle_vertex(triangles.size(),-1);for(inttriangle=0;triangle<int(triangles.size());++triangle){introot=find_root(find_root,triangle);if(root_vertex[root]==-1){constauto&sites_on_circle=triangles[triangle];root_vertex[root]=int(result.vertices.size());result.vertices.push_back(detail::circumcenter(sites[sites_on_circle[0]],sites[sites_on_circle[1]],sites[sites_on_circle[2]]));}triangle_vertex[triangle]=root_vertex[root];}result.edges.reserve(delaunay_edges.size());for(intedge=0;edge<int(delaunay_edges.size());++edge){auto[first_site,second_site]=delaunay_edges[edge];VoronoiEdgevoronoi_edge;voronoi_edge.first_site=first_site;voronoi_edge.second_site=second_site;voronoi_edge.first_vertex=-1;voronoi_edge.second_vertex=-1;if(incident_count[edge]==2){intfirst_vertex=triangle_vertex[incident_triangles[edge][0]];intsecond_vertex=triangle_vertex[incident_triangles[edge][1]];if(first_vertex==second_vertex)continue;if(first_vertex>second_vertex){std::swap(first_vertex,second_vertex);}voronoi_edge.kind=VoronoiEdgeKind::Segment;voronoi_edge.first_vertex=first_vertex;voronoi_edge.second_vertex=second_vertex;voronoi_edge.point=result.vertices[first_vertex];voronoi_edge.direction=result.vertices[second_vertex]-result.vertices[first_vertex];}elseif(incident_count[edge]==1){inttriangle=incident_triangles[edge][0];intthird_site=triangles[triangle][0];if(third_site==first_site||third_site==second_site){third_site=triangles[triangle][1];}if(third_site==first_site||third_site==second_site){third_site=triangles[triangle][2];}assert(third_site!=first_site&&third_site!=second_site);Point<longdouble>first(sites[first_site]);Point<longdouble>second(sites[second_site]);Point<longdouble>edge_direction=second-first;Point<longdouble>outward;if(orientation(sites[first_site],sites[second_site],sites[third_site])>0){outward=Point<longdouble>(edge_direction.y,-edge_direction.x);}else{outward=Point<longdouble>(-edge_direction.y,edge_direction.x);}voronoi_edge.kind=VoronoiEdgeKind::Ray;voronoi_edge.first_vertex=triangle_vertex[triangle];voronoi_edge.point=result.vertices[voronoi_edge.first_vertex];voronoi_edge.direction=detail::unit(outward);}else{assert(incident_count[edge]==0);Point<longdouble>first(sites[first_site]);Point<longdouble>second(sites[second_site]);Point<longdouble>edge_direction=second-first;voronoi_edge.kind=VoronoiEdgeKind::Line;voronoi_edge.point=(first+second)/2.0L;voronoi_edge.direction=detail::unit(Point<longdouble>(edge_direction.y,-edge_direction.x));}intvoronoi_edge_index=int(result.edges.size());result.edges.push_back(voronoi_edge);result.cell_edges[first_site].push_back(voronoi_edge_index);result.cell_edges[second_site].push_back(voronoi_edge_index);}for(intsite=0;site<size;++site){std::sort(result.cell_edges[site].begin(),result.cell_edges[site].end(),[&](intfirst_edge,intsecond_edge){intfirst_other=detail::other_site(result.edges[first_edge],site);intsecond_other=detail::other_site(result.edges[second_edge],site);returndetail::direction_less(sites,site,first_other,second_other);});}returnresult;}}// namespace geometry}// namespace m1une#line 1 "geometry/half_plane_intersection.hpp"
#line 8 "geometry/half_plane_intersection.hpp"
#include<deque>
#line 10 "geometry/half_plane_intersection.hpp"
#include<numbers>
#include<optional>
#include<random>
#line 15 "geometry/half_plane_intersection.hpp"
#line 1 "geometry/linear.hpp"
#line 7 "geometry/linear.hpp"
#line 9 "geometry/linear.hpp"
namespacem1une{namespacegeometry{template<CoordinateT>structLine{Point<T>a;Point<T>b;};template<CoordinateT>structSegment{Point<T>a;Point<T>b;};template<CoordinateT>structRay{Point<T>origin;Point<T>through;};enumclassLinearIntersectionKind{Empty,Point,Segment,Ray,Line,};structLinearIntersection{LinearIntersectionKindkind;Point<longdouble>first;Point<longdouble>second;};structClosestPoints{Point<longdouble>first;Point<longdouble>second;};namespacelinear_intersection_detail{inlineLinearIntersectionmake_empty(){constPoint<longdouble>zero;returnLinearIntersection{LinearIntersectionKind::Empty,zero,zero,};}template<CoordinateT>LinearIntersectionmake_point(constPoint<T>&point){constPoint<longdouble>converted(point);returnLinearIntersection{LinearIntersectionKind::Point,converted,converted,};}template<CoordinateT>LinearIntersectionmake_object(LinearIntersectionKindkind,constPoint<T>&first,constPoint<T>&second){returnLinearIntersection{kind,Point<longdouble>(first),Point<longdouble>(second),};}}// namespace linear_intersection_detailtemplate<CoordinateT>constexprPoint<longdouble>centroid(constSegment<T>&segment){returnPoint<longdouble>((static_cast<longdouble>(segment.a.x)+static_cast<longdouble>(segment.b.x))/2,(static_cast<longdouble>(segment.a.y)+static_cast<longdouble>(segment.b.y))/2);}template<CoordinateT>boolon_line(constLine<T>&line,constPoint<T>&point,longdoubleeps=1e-12L){assert(line.a!=line.b);returnorientation(line.a,line.b,point,eps)==0;}template<CoordinateT>boolparallel(constLine<T>&first,constLine<T>&second,longdoubleeps=1e-12L){usingW=wide_type<T>;Wfirst_x=W(first.b.x)-W(first.a.x);Wfirst_y=W(first.b.y)-W(first.a.y);Wsecond_x=W(second.b.x)-W(second.a.x);Wsecond_y=W(second.b.y)-W(second.a.y);returnpredicate_detail::determinant_sign<ExactCoordinate<T>>(first_x,first_y,second_x,second_y,eps)==0;}template<CoordinateT>boolorthogonal(constLine<T>&first,constLine<T>&second,longdoubleeps=1e-12L){usingW=wide_type<T>;Wfirst_x=W(first.b.x)-W(first.a.x);Wfirst_y=W(first.b.y)-W(first.a.y);Wsecond_x=W(second.b.x)-W(second.a.x);Wsecond_y=W(second.b.y)-W(second.a.y);returnpredicate_detail::dot_sign<ExactCoordinate<T>>(first_x,first_y,second_x,second_y,eps)==0;}template<CoordinateT>Point<longdouble>projection(constLine<T>&line,constPoint<T>&point){assert(line.a!=line.b);Point<longdouble>a(line.a);Point<longdouble>direction(static_cast<longdouble>(line.b.x)-static_cast<longdouble>(line.a.x),static_cast<longdouble>(line.b.y)-static_cast<longdouble>(line.a.y));Point<longdouble>offset(static_cast<longdouble>(point.x)-a.x,static_cast<longdouble>(point.y)-a.y);longdoubleratio=dot(offset,direction)/dot(direction,direction);returna+direction*ratio;}template<CoordinateT>Point<longdouble>reflection(constLine<T>&line,constPoint<T>&point){Point<longdouble>projected=projection(line,point);returnprojected*2.0L-Point<longdouble>(point);}template<CoordinateT>boolintersects(constLine<T>&first,constLine<T>&second,longdoubleeps=1e-12L){return!parallel(first,second,eps)||on_line(first,second.a,eps);}template<CoordinateT>boolon_segment(constSegment<T>&segment,constPoint<T>&point,longdoubleeps=1e-12L){if(orientation(segment.a,segment.b,point,eps)!=0)returnfalse;usingW=wide_type<T>;constWdirection_x=W(segment.b.x)-W(segment.a.x);constWdirection_y=W(segment.b.y)-W(segment.a.y);if(direction_x==W(0)&&direction_y==W(0)){ifconstexpr(ExactCoordinate<T>){returnpoint==segment.a;}else{returnpredicate_detail::absolute(W(point.x)-W(segment.a.x))<=eps&&predicate_detail::absolute(W(point.y)-W(segment.a.y))<=eps;}}constWoffset_x=W(point.x)-W(segment.a.x);constWoffset_y=W(point.y)-W(segment.a.y);constWprojection=offset_x*direction_x+offset_y*direction_y;constWlength_squared=direction_x*direction_x+direction_y*direction_y;returnpredicate_detail::scaled_sign<ExactCoordinate<T>>(projection,length_squared,eps)>=0&&predicate_detail::scaled_sign<ExactCoordinate<T>>(projection-length_squared,length_squared,eps)<=0;}template<CoordinateT>Point<longdouble>projection(constSegment<T>&segment,constPoint<T>&point){constPoint<longdouble>first(segment.a);constPoint<longdouble>direction=Point<longdouble>(segment.b)-first;constlongdoublelength_squared=dot(direction,direction);if(length_squared==0)returnfirst;constlongdoubleratio=std::clamp(dot(Point<longdouble>(point)-first,direction)/length_squared,0.0L,1.0L);returnfirst+direction*ratio;}template<CoordinateT>boolintersects(constSegment<T>&first,constSegment<T>&second,longdoubleeps=1e-12L){intabc=orientation(first.a,first.b,second.a,eps);intabd=orientation(first.a,first.b,second.b,eps);intcda=orientation(second.a,second.b,first.a,eps);intcdb=orientation(second.a,second.b,first.b,eps);if(abc==0&&on_segment(first,second.a,eps))returntrue;if(abd==0&&on_segment(first,second.b,eps))returntrue;if(cda==0&&on_segment(second,first.a,eps))returntrue;if(cdb==0&&on_segment(second,first.b,eps))returntrue;returnabc*abd<0&&cda*cdb<0;}template<CoordinateT>boolintersects(constLine<T>&line,constSegment<T>&segment,longdoubleeps=1e-12L){intfirst_side=orientation(line.a,line.b,segment.a,eps);intsecond_side=orientation(line.a,line.b,segment.b,eps);returnfirst_side==0||second_side==0||first_side!=second_side;}template<CoordinateT>boolintersects(constSegment<T>&segment,constLine<T>&line,longdoubleeps=1e-12L){returnintersects(line,segment,eps);}namespacelinear_parameter_detail{template<CoordinateT>structParameters{wide_type<T>denominator;wide_type<T>denominator_scale;wide_type<T>first_numerator;wide_type<T>second_numerator;};template<CoordinateT>Parameters<T>parameters(constPoint<T>&first_origin,constPoint<T>&first_through,constPoint<T>&second_origin,constPoint<T>&second_through){usingW=wide_type<T>;Wfirst_x=W(first_through.x)-W(first_origin.x);Wfirst_y=W(first_through.y)-W(first_origin.y);Wsecond_x=W(second_through.x)-W(second_origin.x);Wsecond_y=W(second_through.y)-W(second_origin.y);Woffset_x=W(second_origin.x)-W(first_origin.x);Woffset_y=W(second_origin.y)-W(first_origin.y);returnParameters<T>{first_x*second_y-first_y*second_x,predicate_detail::determinant_scale<ExactCoordinate<T>>(first_x,first_y,second_x,second_y),offset_x*second_y-offset_y*second_x,offset_x*first_y-offset_y*first_x};}template<CoordinateT>intdenominator_sign(constParameters<T>&values,longdoubleeps){returnpredicate_detail::scaled_sign<ExactCoordinate<T>>(values.denominator,values.denominator_scale,eps);}template<CoordinateT>boolratio_nonnegative(wide_type<T>numerator,wide_type<T>denominator,longdoubleeps){constintnumerator_sign=predicate_detail::scaled_sign<ExactCoordinate<T>>(numerator,predicate_detail::absolute(denominator),eps);constintdenominator_direction=(denominator>0)-(denominator<0);returnnumerator_sign==0||numerator_sign==denominator_direction;}template<CoordinateT>boolratio_in_unit_interval(wide_type<T>numerator,wide_type<T>denominator,longdoubleeps){constautoscale=predicate_detail::absolute(denominator);constintstart_sign=predicate_detail::scaled_sign<ExactCoordinate<T>>(numerator,scale,eps);constintfinish_sign=predicate_detail::scaled_sign<ExactCoordinate<T>>(numerator-denominator,scale,eps);if(denominator>0){returnstart_sign>=0&&finish_sign<=0;}returnstart_sign<=0&&finish_sign>=0;}}// namespace linear_parameter_detailtemplate<CoordinateT>boolon_ray(constRay<T>&ray,constPoint<T>&point,longdoubleeps=1e-12L){assert(ray.origin!=ray.through);if(orientation(ray.origin,ray.through,point,eps)!=0)returnfalse;usingW=wide_type<T>;Wdirection_x=W(ray.through.x)-W(ray.origin.x);Wdirection_y=W(ray.through.y)-W(ray.origin.y);Woffset_x=W(point.x)-W(ray.origin.x);Woffset_y=W(point.y)-W(ray.origin.y);constWprojection=direction_x*offset_x+direction_y*offset_y;constWlength_squared=direction_x*direction_x+direction_y*direction_y;returnpredicate_detail::scaled_sign<ExactCoordinate<T>>(projection,length_squared,eps)>=0;}template<CoordinateT>Point<longdouble>projection(constRay<T>&ray,constPoint<T>&point){assert(ray.origin!=ray.through);Point<longdouble>origin(ray.origin);Point<longdouble>direction=Point<longdouble>(ray.through)-origin;Point<longdouble>offset=Point<longdouble>(point)-origin;longdoubleratio=dot(offset,direction)/dot(direction,direction);if(ratio<0)ratio=0;returnorigin+direction*ratio;}template<CoordinateT>Ray<longdouble>reflection(constLine<T>&line,constRay<T>&ray){assert(ray.origin!=ray.through);returnRay<longdouble>{reflection(line,ray.origin),reflection(line,ray.through)};}template<CoordinateT>Ray<longdouble>reflected_ray(constRay<T>&incoming,constPoint<T>&hit,constLine<T>&mirror,longdoubleeps=1e-12L){assert(incoming.origin!=incoming.through);assert(on_line(mirror,hit,eps));Point<T>translated=hit+(incoming.through-incoming.origin);returnRay<longdouble>{Point<longdouble>(hit),reflection(mirror,translated)};}template<CoordinateT>boolintersects(constRay<T>&ray,constLine<T>&line,longdoubleeps=1e-12L){assert(ray.origin!=ray.through);assert(line.a!=line.b);linear_parameter_detail::Parameters<T>values=linear_parameter_detail::parameters(ray.origin,ray.through,line.a,line.b);if(linear_parameter_detail::denominator_sign(values,eps)==0){returnon_line(line,ray.origin,eps);}returnlinear_parameter_detail::ratio_nonnegative<T>(values.first_numerator,values.denominator,eps);}template<CoordinateT>boolintersects(constLine<T>&line,constRay<T>&ray,longdoubleeps=1e-12L){returnintersects(ray,line,eps);}template<CoordinateT>boolintersects(constRay<T>&ray,constSegment<T>&segment,longdoubleeps=1e-12L){assert(ray.origin!=ray.through);if(segment.a==segment.b)returnon_ray(ray,segment.a,eps);linear_parameter_detail::Parameters<T>values=linear_parameter_detail::parameters(ray.origin,ray.through,segment.a,segment.b);if(linear_parameter_detail::denominator_sign(values,eps)==0){if(orientation(ray.origin,ray.through,segment.a,eps)!=0){returnfalse;}returnon_ray(ray,segment.a,eps)||on_ray(ray,segment.b,eps)||on_segment(segment,ray.origin,eps);}returnlinear_parameter_detail::ratio_nonnegative<T>(values.first_numerator,values.denominator,eps)&&linear_parameter_detail::ratio_in_unit_interval<T>(values.second_numerator,values.denominator,eps);}template<CoordinateT>boolintersects(constSegment<T>&segment,constRay<T>&ray,longdoubleeps=1e-12L){returnintersects(ray,segment,eps);}template<CoordinateT>boolintersects(constRay<T>&first,constRay<T>&second,longdoubleeps=1e-12L){assert(first.origin!=first.through);assert(second.origin!=second.through);linear_parameter_detail::Parameters<T>values=linear_parameter_detail::parameters(first.origin,first.through,second.origin,second.through);if(linear_parameter_detail::denominator_sign(values,eps)==0){if(orientation(first.origin,first.through,second.origin,eps)!=0){returnfalse;}returnon_ray(first,second.origin,eps)||on_ray(second,first.origin,eps);}returnlinear_parameter_detail::ratio_nonnegative<T>(values.first_numerator,values.denominator,eps)&&linear_parameter_detail::ratio_nonnegative<T>(values.second_numerator,values.denominator,eps);}namespacelinear_intersection_detail{enumclassDomain{Line,Segment,Ray,};template<CoordinateT>structParametricObject{Point<T>origin;Point<T>through;Domaindomain;};template<CoordinateT>ParametricObject<T>parametric_object(constLine<T>&line){assert(line.a!=line.b);returnParametricObject<T>{line.a,line.b,Domain::Line};}template<CoordinateT>ParametricObject<T>parametric_object(constSegment<T>&segment){returnParametricObject<T>{segment.a,segment.b,Domain::Segment};}template<CoordinateT>ParametricObject<T>parametric_object(constRay<T>&ray){assert(ray.origin!=ray.through);returnParametricObject<T>{ray.origin,ray.through,Domain::Ray};}template<CoordinateT>boolcontains(constParametricObject<T>&object,constPoint<T>&point,longdoubleeps){if(object.domain==Domain::Line){returnon_line(Line<T>{object.origin,object.through},point,eps);}if(object.domain==Domain::Segment){returnon_segment(Segment<T>{object.origin,object.through},point,eps);}returnon_ray(Ray<T>{object.origin,object.through},point,eps);}template<CoordinateT>boolaccepts_parameter(Domaindomain,wide_type<T>numerator,wide_type<T>denominator,longdoubleeps){if(domain==Domain::Line)returntrue;if(domain==Domain::Ray){returnlinear_parameter_detail::ratio_nonnegative<T>(numerator,denominator,eps);}returnlinear_parameter_detail::ratio_in_unit_interval<T>(numerator,denominator,eps);}template<CoordinateT>Point<longdouble>point_at_ratio(constParametricObject<T>&object,wide_type<T>numerator,wide_type<T>denominator){constlongdoubleratio=static_cast<longdouble>(numerator)/static_cast<longdouble>(denominator);constPoint<longdouble>origin(object.origin);constPoint<longdouble>direction=Point<longdouble>(object.through)-origin;returnorigin+direction*ratio;}template<CoordinateT>structAxisProjection{booluse_x;boolnegate;wide_type<T>operator()(constPoint<T>&point)const{constwide_type<T>value=use_x?wide_type<T>(point.x):wide_type<T>(point.y);returnnegate?-value:value;}};template<CoordinateT>AxisProjection<T>axis_projection(constParametricObject<T>&object){usingW=wide_type<T>;constWdirection_x=W(object.through.x)-W(object.origin.x);constWdirection_y=W(object.through.y)-W(object.origin.y);constbooluse_x=predicate_detail::absolute(direction_x)>=predicate_detail::absolute(direction_y);constWcomponent=use_x?direction_x:direction_y;assert(component!=W(0));returnAxisProjection<T>{use_x,component<W(0)};}template<CoordinateT>structParameterInterval{boolhas_lower;boolhas_upper;wide_type<T>lower;wide_type<T>upper;};template<CoordinateT>ParameterInterval<T>parameter_interval(constParametricObject<T>&object,constAxisProjection<T>&projection){usingW=wide_type<T>;constWorigin=projection(object.origin);constWthrough=projection(object.through);if(object.domain==Domain::Line){returnParameterInterval<T>{false,false,W(0),W(0)};}if(object.domain==Domain::Segment){returnParameterInterval<T>{true,true,std::min(origin,through),std::max(origin,through),};}if(origin<through){returnParameterInterval<T>{true,false,origin,W(0)};}returnParameterInterval<T>{false,true,W(0),origin};}template<CoordinateT>ParameterInterval<T>intersect_intervals(ParameterInterval<T>first,constParameterInterval<T>&second){if(second.has_lower&&(!first.has_lower||first.lower<second.lower)){first.has_lower=true;first.lower=second.lower;}if(second.has_upper&&(!first.has_upper||second.upper<first.upper)){first.has_upper=true;first.upper=second.upper;}returnfirst;}template<CoordinateT>Point<longdouble>point_at_projection(constParametricObject<T>&object,constAxisProjection<T>&projection,longdoubletarget){constlongdoubleorigin=static_cast<longdouble>(projection(object.origin));constlongdoublethrough=static_cast<longdouble>(projection(object.through));constlongdoubleratio=(target-origin)/(through-origin);constPoint<longdouble>point(object.origin);constPoint<longdouble>direction=Point<longdouble>(object.through)-point;returnpoint+direction*ratio;}template<CoordinateT>LinearIntersectioncollinear_intersection(constParametricObject<T>&first,constParametricObject<T>&second,longdoubleeps){usingW=wide_type<T>;constAxisProjection<T>projection=axis_projection(first);constParameterInterval<T>first_interval=parameter_interval(first,projection);constParameterInterval<T>second_interval=parameter_interval(second,projection);constParameterInterval<T>common=intersect_intervals(first_interval,second_interval);Wscale=predicate_detail::absolute(projection(first.through)-projection(first.origin));scale=std::max(scale,predicate_detail::absolute(projection(second.through)-projection(second.origin)));if(common.has_lower&&common.has_upper){constintorder=predicate_detail::scaled_sign<ExactCoordinate<T>>(common.lower-common.upper,scale,eps);if(order>0)returnmake_empty();if(order==0){constlongdoublecoordinate=(static_cast<longdouble>(common.lower)+static_cast<longdouble>(common.upper))/2.0L;returnmake_point(point_at_projection(first,projection,coordinate));}returnmake_object(LinearIntersectionKind::Segment,point_at_projection(first,projection,static_cast<longdouble>(common.lower)),point_at_projection(first,projection,static_cast<longdouble>(common.upper)));}constPoint<longdouble>direction=Point<longdouble>(first.through)-Point<longdouble>(first.origin);if(common.has_lower){constPoint<longdouble>origin=point_at_projection(first,projection,static_cast<longdouble>(common.lower));returnmake_object(LinearIntersectionKind::Ray,origin,origin+direction);}if(common.has_upper){constPoint<longdouble>origin=point_at_projection(first,projection,static_cast<longdouble>(common.upper));returnmake_object(LinearIntersectionKind::Ray,origin,origin-direction);}returnmake_object(LinearIntersectionKind::Line,first.origin,first.through);}template<CoordinateT>LinearIntersectionintersect(constParametricObject<T>&first,constParametricObject<T>&second,longdoubleeps){constboolfirst_degenerate=first.origin==first.through;constboolsecond_degenerate=second.origin==second.through;if(first_degenerate){assert(first.domain==Domain::Segment);if(contains(second,first.origin,eps)){returnmake_point(first.origin);}returnmake_empty();}if(second_degenerate){assert(second.domain==Domain::Segment);if(contains(first,second.origin,eps)){returnmake_point(second.origin);}returnmake_empty();}constlinear_parameter_detail::Parameters<T>values=linear_parameter_detail::parameters(first.origin,first.through,second.origin,second.through);if(linear_parameter_detail::denominator_sign(values,eps)!=0){if(!accepts_parameter<T>(first.domain,values.first_numerator,values.denominator,eps)||!accepts_parameter<T>(second.domain,values.second_numerator,values.denominator,eps)){returnmake_empty();}returnmake_point(point_at_ratio(first,values.first_numerator,values.denominator));}if(orientation(first.origin,first.through,second.origin,eps)!=0){returnmake_empty();}returncollinear_intersection(first,second,eps);}}// namespace linear_intersection_detailtemplate<CoordinateT>LinearIntersectionlinear_intersection(constLine<T>&first,constLine<T>&second,longdoubleeps=1e-12L){returnlinear_intersection_detail::intersect(linear_intersection_detail::parametric_object(first),linear_intersection_detail::parametric_object(second),eps);}template<CoordinateT>LinearIntersectionlinear_intersection(constLine<T>&line,constSegment<T>&segment,longdoubleeps=1e-12L){returnlinear_intersection_detail::intersect(linear_intersection_detail::parametric_object(line),linear_intersection_detail::parametric_object(segment),eps);}template<CoordinateT>LinearIntersectionlinear_intersection(constSegment<T>&segment,constLine<T>&line,longdoubleeps=1e-12L){returnlinear_intersection_detail::intersect(linear_intersection_detail::parametric_object(segment),linear_intersection_detail::parametric_object(line),eps);}template<CoordinateT>LinearIntersectionlinear_intersection(constSegment<T>&first,constSegment<T>&second,longdoubleeps=1e-12L){returnlinear_intersection_detail::intersect(linear_intersection_detail::parametric_object(first),linear_intersection_detail::parametric_object(second),eps);}template<CoordinateT>LinearIntersectionlinear_intersection(constRay<T>&ray,constLine<T>&line,longdoubleeps=1e-12L){returnlinear_intersection_detail::intersect(linear_intersection_detail::parametric_object(ray),linear_intersection_detail::parametric_object(line),eps);}template<CoordinateT>LinearIntersectionlinear_intersection(constLine<T>&line,constRay<T>&ray,longdoubleeps=1e-12L){returnlinear_intersection_detail::intersect(linear_intersection_detail::parametric_object(line),linear_intersection_detail::parametric_object(ray),eps);}template<CoordinateT>LinearIntersectionlinear_intersection(constRay<T>&ray,constSegment<T>&segment,longdoubleeps=1e-12L){returnlinear_intersection_detail::intersect(linear_intersection_detail::parametric_object(ray),linear_intersection_detail::parametric_object(segment),eps);}template<CoordinateT>LinearIntersectionlinear_intersection(constSegment<T>&segment,constRay<T>&ray,longdoubleeps=1e-12L){returnlinear_intersection_detail::intersect(linear_intersection_detail::parametric_object(segment),linear_intersection_detail::parametric_object(ray),eps);}template<CoordinateT>LinearIntersectionlinear_intersection(constRay<T>&first,constRay<T>&second,longdoubleeps=1e-12L){returnlinear_intersection_detail::intersect(linear_intersection_detail::parametric_object(first),linear_intersection_detail::parametric_object(second),eps);}namespaceclosest_points_detail{inlineClosestPointsreversed(constClosestPoints&result){returnClosestPoints{result.second,result.first};}inlineboolpoint_less(constPoint<longdouble>&first,constPoint<longdouble>&second){if(first.x!=second.x)returnfirst.x<second.x;returnfirst.y<second.y;}inlineClosestPointscommon_point(constLinearIntersection&intersection){assert(intersection.kind!=LinearIntersectionKind::Empty);Point<longdouble>point=intersection.first;if(intersection.kind==LinearIntersectionKind::Segment){if(point_less(intersection.second,point)){point=intersection.second;}}elseif(intersection.kind==LinearIntersectionKind::Line){constLine<longdouble>line{intersection.first,intersection.second};point=projection(line,Point<longdouble>(0,0));}returnClosestPoints{point,point};}inlinelongdoubleseparation2(constClosestPoints&result){returndistance2(result.first,result.second);}inlineboolcanonical_less(constClosestPoints&first,constClosestPoints&second){Point<longdouble>first_start=first.first;Point<longdouble>first_finish=first.second;if(point_less(first_finish,first_start)){std::swap(first_start,first_finish);}Point<longdouble>second_start=second.first;Point<longdouble>second_finish=second.second;if(point_less(second_finish,second_start)){std::swap(second_start,second_finish);}if(point_less(first_start,second_start))returntrue;if(point_less(second_start,first_start))returnfalse;returnpoint_less(first_finish,second_finish);}inlinevoidconsider(ClosestPoints&best,constClosestPoints&candidate){constlongdoublebest_distance=separation2(best);constlongdoublecandidate_distance=separation2(candidate);if(candidate_distance<best_distance||(candidate_distance==best_distance&&canonical_less(candidate,best))){best=candidate;}}}// namespace closest_points_detailtemplate<CoordinateT>ClosestPointsclosest_points(constPoint<T>&first,constPoint<T>&second){returnClosestPoints{Point<longdouble>(first),Point<longdouble>(second),};}template<CoordinateT>ClosestPointsclosest_points(constLine<T>&line,constPoint<T>&point){returnClosestPoints{projection(line,point),Point<longdouble>(point),};}template<CoordinateT>ClosestPointsclosest_points(constPoint<T>&point,constLine<T>&line){returnclosest_points_detail::reversed(closest_points(line,point));}template<CoordinateT>ClosestPointsclosest_points(constSegment<T>&segment,constPoint<T>&point){returnClosestPoints{projection(segment,point),Point<longdouble>(point),};}template<CoordinateT>ClosestPointsclosest_points(constPoint<T>&point,constSegment<T>&segment){returnclosest_points_detail::reversed(closest_points(segment,point));}template<CoordinateT>ClosestPointsclosest_points(constRay<T>&ray,constPoint<T>&point){returnClosestPoints{projection(ray,point),Point<longdouble>(point),};}template<CoordinateT>ClosestPointsclosest_points(constPoint<T>&point,constRay<T>&ray){returnclosest_points_detail::reversed(closest_points(ray,point));}template<CoordinateT>ClosestPointsclosest_points(constLine<T>&first,constLine<T>&second,longdoubleeps=1e-12L){constLinearIntersectionintersection=linear_intersection(first,second,eps);if(intersection.kind!=LinearIntersectionKind::Empty){returnclosest_points_detail::common_point(intersection);}ClosestPointsresult=closest_points(first,second.a);closest_points_detail::consider(result,closest_points(first.a,second));returnresult;}template<CoordinateT>ClosestPointsclosest_points(constLine<T>&line,constSegment<T>&segment,longdoubleeps=1e-12L){constLinearIntersectionintersection=linear_intersection(line,segment,eps);if(intersection.kind!=LinearIntersectionKind::Empty){returnclosest_points_detail::common_point(intersection);}ClosestPointsresult=closest_points(line,segment.a);closest_points_detail::consider(result,closest_points(line,segment.b));returnresult;}template<CoordinateT>ClosestPointsclosest_points(constSegment<T>&segment,constLine<T>&line,longdoubleeps=1e-12L){returnclosest_points_detail::reversed(closest_points(line,segment,eps));}template<CoordinateT>ClosestPointsclosest_points(constSegment<T>&first,constSegment<T>&second,longdoubleeps=1e-12L){constLinearIntersectionintersection=linear_intersection(first,second,eps);if(intersection.kind!=LinearIntersectionKind::Empty){returnclosest_points_detail::common_point(intersection);}ClosestPointsresult=closest_points(first,second.a);closest_points_detail::consider(result,closest_points(first,second.b));closest_points_detail::consider(result,closest_points(first.a,second));closest_points_detail::consider(result,closest_points(first.b,second));returnresult;}template<CoordinateT>ClosestPointsclosest_points(constLine<T>&line,constRay<T>&ray,longdoubleeps=1e-12L){constLinearIntersectionintersection=linear_intersection(line,ray,eps);if(intersection.kind!=LinearIntersectionKind::Empty){returnclosest_points_detail::common_point(intersection);}returnclosest_points(line,ray.origin);}template<CoordinateT>ClosestPointsclosest_points(constRay<T>&ray,constLine<T>&line,longdoubleeps=1e-12L){returnclosest_points_detail::reversed(closest_points(line,ray,eps));}template<CoordinateT>ClosestPointsclosest_points(constRay<T>&ray,constSegment<T>&segment,longdoubleeps=1e-12L){constLinearIntersectionintersection=linear_intersection(ray,segment,eps);if(intersection.kind!=LinearIntersectionKind::Empty){returnclosest_points_detail::common_point(intersection);}ClosestPointsresult=closest_points(ray,segment.a);closest_points_detail::consider(result,closest_points(ray,segment.b));closest_points_detail::consider(result,closest_points(ray.origin,segment));returnresult;}template<CoordinateT>ClosestPointsclosest_points(constSegment<T>&segment,constRay<T>&ray,longdoubleeps=1e-12L){returnclosest_points_detail::reversed(closest_points(ray,segment,eps));}template<CoordinateT>ClosestPointsclosest_points(constRay<T>&first,constRay<T>&second,longdoubleeps=1e-12L){constLinearIntersectionintersection=linear_intersection(first,second,eps);if(intersection.kind!=LinearIntersectionKind::Empty){returnclosest_points_detail::common_point(intersection);}ClosestPointsresult=closest_points(first,second.origin);closest_points_detail::consider(result,closest_points(first.origin,second));returnresult;}template<CoordinateT>longdoubledistance(constLine<T>&line,constPoint<T>&point){constClosestPointsresult=closest_points(line,point);returngeometry::distance(result.first,result.second);}template<CoordinateT>longdoubledistance(constPoint<T>&point,constLine<T>&line){returndistance(line,point);}template<CoordinateT>longdoubledistance(constSegment<T>&segment,constPoint<T>&point){constClosestPointsresult=closest_points(segment,point);returngeometry::distance(result.first,result.second);}template<CoordinateT>longdoubledistance(constPoint<T>&point,constSegment<T>&segment){returndistance(segment,point);}template<CoordinateT>longdoubledistance(constRay<T>&ray,constPoint<T>&point){constClosestPointsresult=closest_points(ray,point);returngeometry::distance(result.first,result.second);}template<CoordinateT>longdoubledistance(constPoint<T>&point,constRay<T>&ray){returndistance(ray,point);}template<CoordinateT>longdoubledistance(constLine<T>&first,constLine<T>&second){constClosestPointsresult=closest_points(first,second);returngeometry::distance(result.first,result.second);}template<CoordinateT>longdoubledistance(constLine<T>&line,constSegment<T>&segment){constClosestPointsresult=closest_points(line,segment);returngeometry::distance(result.first,result.second);}template<CoordinateT>longdoubledistance(constSegment<T>&segment,constLine<T>&line){returndistance(line,segment);}template<CoordinateT>longdoubledistance(constSegment<T>&first,constSegment<T>&second){constClosestPointsresult=closest_points(first,second);returngeometry::distance(result.first,result.second);}template<CoordinateT>longdoubledistance(constLine<T>&line,constRay<T>&ray){constClosestPointsresult=closest_points(line,ray);returngeometry::distance(result.first,result.second);}template<CoordinateT>longdoubledistance(constRay<T>&ray,constLine<T>&line){returndistance(line,ray);}template<CoordinateT>longdoubledistance(constRay<T>&ray,constSegment<T>&segment){constClosestPointsresult=closest_points(ray,segment);returngeometry::distance(result.first,result.second);}template<CoordinateT>longdoubledistance(constSegment<T>&segment,constRay<T>&ray){returndistance(ray,segment);}template<CoordinateT>longdoubledistance(constRay<T>&first,constRay<T>&second){constClosestPointsresult=closest_points(first,second);returngeometry::distance(result.first,result.second);}}// namespace geometry}// namespace m1une#line 17 "geometry/half_plane_intersection.hpp"
namespacem1une{namespacegeometry{enumclassHalfPlaneIntersectionStatus{Empty,Unbounded,Degenerate,Bounded,};structHalfPlaneIntersectionResult{HalfPlaneIntersectionStatusstatus;std::vector<Point<longdouble>>polygon;};namespacehalf_plane_intersection_detail{structHalfPlane{Point<longdouble>point;Point<longdouble>direction;longdoubleangle;HalfPlane(constPoint<longdouble>&point_value,constPoint<longdouble>&direction_value):point(point_value),direction(direction_value){angle=std::atan2(direction.y,direction.x);if(angle<0)angle+=2*std::numbers::pi_v<longdouble>;}};inlinebooldirection_less(constHalfPlane&first,constHalfPlane&second){returnfirst.angle<second.angle;}inlineboolparallel(constHalfPlane&first,constHalfPlane&second,longdoubleeps){returnstd::fabs(cross(first.direction,second.direction))<=eps;}inlineboolsame_direction(constHalfPlane&first,constHalfPlane&second,longdoubleeps){returnparallel(first,second,eps)&&dot(first.direction,second.direction)>0;}inlinebooloutside(constHalfPlane&half_plane,constPoint<longdouble>&point,longdoubleeps){returncross(half_plane.direction,point-half_plane.point)<-eps;}inlineboolmore_restrictive(constHalfPlane&candidate,constHalfPlane¤t,longdoubleeps){returncross(current.direction,candidate.point-current.point)>eps;}inlinestd::optional<Point<longdouble>>intersection(constHalfPlane&first,constHalfPlane&second,longdoubleeps){longdoubledenominator=cross(first.direction,second.direction);if(std::fabs(denominator)<=eps)returnstd::nullopt;longdoubleratio=cross(second.point-first.point,second.direction)/denominator;returnfirst.point+first.direction*ratio;}inlinevoidmerge_same_direction(std::vector<HalfPlane>&half_planes,constHalfPlane&half_plane,longdoubleeps){if(half_planes.empty()||!same_direction(half_planes.back(),half_plane,eps)){half_planes.push_back(half_plane);return;}if(more_restrictive(half_plane,half_planes.back(),eps)){half_planes.back()=half_plane;}}inlinevoidmerge_cyclic_ends(std::vector<HalfPlane>&half_planes,longdoubleeps){if(half_planes.size()<2||!same_direction(half_planes.front(),half_planes.back(),eps)){return;}if(more_restrictive(half_planes.back(),half_planes.front(),eps)){half_planes.front()=half_planes.back();}half_planes.pop_back();}inlineboolhas_feasible_point(std::vector<HalfPlane>half_planes,longdoubleeps){std::mt19937_64generator(0x6a09e667f3bcc909ULL);std::shuffle(half_planes.begin(),half_planes.end(),generator);Point<longdouble>feasible(0,0);for(std::size_tindex=0;index<half_planes.size();++index){constHalfPlane¤t=half_planes[index];if(!outside(current,feasible,eps))continue;Point<longdouble>normal(-current.direction.y,current.direction.x);Point<longdouble>base=normal*dot(normal,current.point);longdoublelower=-std::numeric_limits<longdouble>::infinity();longdoubleupper=std::numeric_limits<longdouble>::infinity();for(std::size_tprevious_index=0;previous_index<index;++previous_index){constHalfPlane&previous=half_planes[previous_index];longdoublecoefficient=cross(previous.direction,current.direction);longdoubleconstant=cross(previous.direction,base-previous.point);if(std::fabs(coefficient)<=eps){if(constant<-eps)returnfalse;continue;}longdoublebound=(-eps-constant)/coefficient;if(coefficient>0){lower=std::max(lower,bound);}else{upper=std::min(upper,bound);}if(lower>upper)returnfalse;}longdoubleparameter=0;if(parameter<lower)parameter=lower;if(parameter>upper)parameter=upper;feasible=base+current.direction*parameter;}returntrue;}inlineboolhas_bounded_recession_cone(conststd::vector<HalfPlane>&half_planes,longdoubleeps){if(half_planes.empty())returnfalse;constexprlongdoublepi=std::numbers::pi_v<longdouble>;longdoublemaximum_gap=half_planes.front().angle+2*pi-half_planes.back().angle;for(std::size_tindex=1;index<half_planes.size();++index){maximum_gap=std::max(maximum_gap,half_planes[index].angle-half_planes[index-1].angle);}returnmaximum_gap<pi-eps;}}// namespace half_plane_intersection_detail// Each directed line keeps its closed left half-plane. Returns the vertices of// a bounded intersection with positive area in counterclockwise order. Empty,// unbounded, and bounded zero-area intersections have distinct statuses.template<CoordinateT>HalfPlaneIntersectionResulthalf_plane_intersection(conststd::vector<Line<T>>&half_planes,longdoubleeps=1e-12L){usinghalf_plane_intersection_detail::HalfPlane;namespacedetail=half_plane_intersection_detail;assert(eps>=0);std::vector<HalfPlane>sorted;sorted.reserve(half_planes.size());for(constLine<T>&line:half_planes){assert(line.a!=line.b);Point<longdouble>point(line.a);Point<longdouble>direction=Point<longdouble>(line.b)-point;longdoublelength=norm(direction);direction=direction/length;sorted.push_back(HalfPlane{point,direction});}if(!detail::has_feasible_point(sorted,eps)){returnHalfPlaneIntersectionResult{HalfPlaneIntersectionStatus::Empty,{},};}std::sort(sorted.begin(),sorted.end(),detail::direction_less);if(!detail::has_bounded_recession_cone(sorted,eps)){returnHalfPlaneIntersectionResult{HalfPlaneIntersectionStatus::Unbounded,{},};}if(sorted.size()<3){returnHalfPlaneIntersectionResult{HalfPlaneIntersectionStatus::Degenerate,{},};}std::vector<HalfPlane>unique;unique.reserve(sorted.size());for(constHalfPlane&half_plane:sorted){detail::merge_same_direction(unique,half_plane,eps);}detail::merge_cyclic_ends(unique,eps);if(unique.size()<3){returnHalfPlaneIntersectionResult{HalfPlaneIntersectionStatus::Degenerate,{},};}std::deque<HalfPlane>deque;for(constHalfPlane&half_plane:unique){while(deque.size()>=2){autopoint=detail::intersection(deque[deque.size()-2],deque.back(),eps);if(!point.has_value()){returnHalfPlaneIntersectionResult{HalfPlaneIntersectionStatus::Degenerate,{},};}if(!detail::outside(half_plane,*point,eps))break;deque.pop_back();}while(deque.size()>=2){autopoint=detail::intersection(deque[0],deque[1],eps);if(!point.has_value()){returnHalfPlaneIntersectionResult{HalfPlaneIntersectionStatus::Degenerate,{},};}if(!detail::outside(half_plane,*point,eps))break;deque.pop_front();}deque.push_back(half_plane);}while(deque.size()>=3){autopoint=detail::intersection(deque[deque.size()-2],deque.back(),eps);if(!point.has_value()){returnHalfPlaneIntersectionResult{HalfPlaneIntersectionStatus::Degenerate,{},};}if(!detail::outside(deque.front(),*point,eps))break;deque.pop_back();}while(deque.size()>=3){autopoint=detail::intersection(deque[0],deque[1],eps);if(!point.has_value()){returnHalfPlaneIntersectionResult{HalfPlaneIntersectionStatus::Degenerate,{},};}if(!detail::outside(deque.back(),*point,eps))break;deque.pop_front();}if(deque.size()<3){returnHalfPlaneIntersectionResult{HalfPlaneIntersectionStatus::Degenerate,{},};}std::vector<Point<longdouble>>polygon;polygon.reserve(deque.size());for(std::size_tindex=0;index<deque.size();++index){autopoint=detail::intersection(deque[index],deque[(index+1)%deque.size()],eps);if(!point.has_value()){returnHalfPlaneIntersectionResult{HalfPlaneIntersectionStatus::Degenerate,{},};}if(polygon.empty()||distance(polygon.back(),*point)>eps){polygon.push_back(*point);}}if(polygon.size()>=2&&distance(polygon.front(),polygon.back())<=eps){polygon.pop_back();}if(polygon.size()<3){returnHalfPlaneIntersectionResult{HalfPlaneIntersectionStatus::Degenerate,{},};}longdoublesigned_area2=0;Point<longdouble>origin=polygon.front();for(std::size_tindex=1;index+1<polygon.size();++index){signed_area2+=cross(polygon[index]-origin,polygon[index+1]-origin);}if(signed_area2<=eps){returnHalfPlaneIntersectionResult{HalfPlaneIntersectionStatus::Degenerate,{},};}autofirst=std::min_element(polygon.begin(),polygon.end());std::rotate(polygon.begin(),first,polygon.end());returnHalfPlaneIntersectionResult{HalfPlaneIntersectionStatus::Bounded,std::move(polygon),};}}// namespace geometry}// namespace m1une#line 6 "verify/geometry/voronoi_diagram.test.cpp"
#line 11 "verify/geometry/voronoi_diagram.test.cpp"
#include<cstdint>
#include<iomanip>
#include<iostream>
#line 15 "verify/geometry/voronoi_diagram.test.cpp"
#include<set>
#line 18 "verify/geometry/voronoi_diagram.test.cpp"
namespace{usingm1une::geometry::Point;usingm1une::geometry::VoronoiDiagram;usingm1une::geometry::VoronoiEdge;usingm1une::geometry::VoronoiEdgeKind;usingSite=Point<longlong>;usingRealPoint=Point<longdouble>;longdoublesquared_distance(constRealPoint&first,constRealPoint&second){longdoublex=first.x-second.x;longdoubley=first.y-second.y;returnx*x+y*y;}boolclose(longdoublefirst,longdoublesecond,longdoubleeps=1e-8L){returnstd::fabs(first-second)<=eps*std::max(1.0L,std::max(std::fabs(first),std::fabs(second)));}voidcheck_boundary_point(conststd::vector<Site>&sites,constVoronoiEdge&edge,constRealPoint&point){RealPointfirst(sites[edge.first_site]);RealPointsecond(sites[edge.second_site]);longdoublefirst_distance=squared_distance(point,first);longdoublesecond_distance=squared_distance(point,second);assert(close(first_distance,second_distance,1e-7L));for(constSite&site:sites){longdoublecandidate=squared_distance(point,RealPoint(site));longdoubletolerance=1e-7L*std::max(1.0L,std::max(first_distance,candidate));assert(first_distance<=candidate+tolerance);}}boolnaive_has_voronoi_edge(conststd::vector<Site>&sites,intfirst_site,intsecond_site){RealPointfirst(sites[first_site]);RealPointsecond(sites[second_site]);RealPointmidpoint=(first+second)/2.0L;RealPointdifference=second-first;RealPointdirection(difference.y,-difference.x);longdoublelower=-std::numeric_limits<longdouble>::infinity();longdoubleupper=std::numeric_limits<longdouble>::infinity();for(constSite&integer_site:sites){RealPointsite(integer_site);longdoubleconstant=squared_distance(midpoint,first)-squared_distance(midpoint,site);RealPointshifted=midpoint+direction;longdoublecoefficient=squared_distance(shifted,first)-squared_distance(shifted,site)-constant;if(std::fabs(coefficient)<=1e-14L){if(constant>1e-12L)returnfalse;}else{longdoublebound=-constant/coefficient;if(coefficient>0){upper=std::min(upper,bound);}else{lower=std::max(lower,bound);}}}returnlower+1e-10L<upper;}voidcheck_diagram(conststd::vector<Site>&sites){VoronoiDiagramdiagram=m1une::geometry::voronoi_diagram(sites);assert(diagram.cell_edges.size()==sites.size());std::set<std::pair<int,int>>actual_pairs;std::vector<int>cell_occurrences(diagram.edges.size(),0);for(intsite=0;site<int(sites.size());++site){for(intedge_index:diagram.cell_edges[site]){assert(0<=edge_index&&edge_index<int(diagram.edges.size()));constVoronoiEdge&edge=diagram.edges[edge_index];assert(edge.first_site==site||edge.second_site==site);++cell_occurrences[edge_index];}}for(intedge_index=0;edge_index<int(diagram.edges.size());++edge_index){constVoronoiEdge&edge=diagram.edges[edge_index];assert(cell_occurrences[edge_index]==2);assert(0<=edge.first_site&&edge.first_site<int(sites.size()));assert(0<=edge.second_site&&edge.second_site<int(sites.size()));assert(edge.first_site<edge.second_site);assert(actual_pairs.emplace(edge.first_site,edge.second_site).second);if(edge.kind==VoronoiEdgeKind::Segment){assert(0<=edge.first_vertex);assert(edge.first_vertex<int(diagram.vertices.size()));assert(0<=edge.second_vertex);assert(edge.second_vertex<int(diagram.vertices.size()));assert(edge.first_vertex<edge.second_vertex);assert(close(edge.point.x,diagram.vertices[edge.first_vertex].x));assert(close(edge.point.y,diagram.vertices[edge.first_vertex].y));RealPointexpected_direction=diagram.vertices[edge.second_vertex]-diagram.vertices[edge.first_vertex];assert(close(edge.direction.x,expected_direction.x));assert(close(edge.direction.y,expected_direction.y));for(longdoubleparameter:std::array<longdouble,3>{0,0.5L,1}){check_boundary_point(sites,edge,edge.point+edge.direction*parameter);}}elseif(edge.kind==VoronoiEdgeKind::Ray){assert(0<=edge.first_vertex);assert(edge.first_vertex<int(diagram.vertices.size()));assert(edge.second_vertex==-1);assert(close(edge.point.x,diagram.vertices[edge.first_vertex].x));assert(close(edge.point.y,diagram.vertices[edge.first_vertex].y));assert(close(m1une::geometry::norm(edge.direction),1));for(longdoubleparameter:std::array<longdouble,3>{0,1,100}){check_boundary_point(sites,edge,edge.point+edge.direction*parameter);}}else{assert(edge.kind==VoronoiEdgeKind::Line);assert(edge.first_vertex==-1);assert(edge.second_vertex==-1);assert(close(m1une::geometry::norm(edge.direction),1));for(longdoubleparameter:std::array<longdouble,3>{-100,0,100}){check_boundary_point(sites,edge,edge.point+edge.direction*parameter);}}}for(intfirst=0;first<int(sites.size());++first){for(intsecond=first+1;second<int(sites.size());++second){boolactual=actual_pairs.contains(std::pair(first,second));boolexpected=naive_has_voronoi_edge(sites,first,second);assert(actual==expected);}}}intcount_kind(constVoronoiDiagram&diagram,VoronoiEdgeKindkind){returnint(std::count_if(diagram.edges.begin(),diagram.edges.end(),[&](constVoronoiEdge&edge){returnedge.kind==kind;}));}voidtest_fixed(){check_diagram({});check_diagram(std::vector<Site>{Site(4,-2)});std::vector<Site>two_sites{Site(0,0),Site(4,0)};check_diagram(two_sites);VoronoiDiagramtwo=m1une::geometry::voronoi_diagram(two_sites);assert(two.vertices.empty());assert(two.edges.size()==1);assert(two.edges[0].kind==VoronoiEdgeKind::Line);assert(close(two.edges[0].point.x,2));assert(close(two.edges[0].point.y,0));std::vector<Site>triangle{Site(0,0),Site(6,0),Site(0,8),};check_diagram(triangle);VoronoiDiagramthree=m1une::geometry::voronoi_diagram(triangle);assert(three.vertices.size()==1);assert(three.edges.size()==3);assert(count_kind(three,VoronoiEdgeKind::Ray)==3);assert(close(three.vertices[0].x,3));assert(close(three.vertices[0].y,4));std::vector<Site>square{Site(0,0),Site(2,0),Site(2,2),Site(0,2),};check_diagram(square);VoronoiDiagramfour=m1une::geometry::voronoi_diagram(square);assert(four.vertices.size()==1);assert(four.edges.size()==4);assert(count_kind(four,VoronoiEdgeKind::Ray)==4);std::vector<Site>cocircular{Site(5,0),Site(3,4),Site(0,5),Site(-3,4),Site(-5,0),Site(-3,-4),Site(0,-5),Site(3,-4),};check_diagram(cocircular);VoronoiDiagrameight=m1une::geometry::voronoi_diagram(cocircular);assert(eight.vertices.size()==1);assert(eight.edges.size()==8);assert(count_kind(eight,VoronoiEdgeKind::Ray)==8);std::vector<Site>square_with_center=square;square_with_center.emplace_back(1,1);check_diagram(square_with_center);VoronoiDiagramfive=m1une::geometry::voronoi_diagram(square_with_center);assert(five.vertices.size()==4);assert(five.edges.size()==8);assert(count_kind(five,VoronoiEdgeKind::Segment)==4);assert(count_kind(five,VoronoiEdgeKind::Ray)==4);std::vector<Site>collinear{Site(-5,3),Site(-1,3),Site(2,3),Site(9,3),};check_diagram(collinear);VoronoiDiagramline=m1une::geometry::voronoi_diagram(collinear);assert(line.vertices.empty());assert(line.edges.size()==3);assert(count_kind(line,VoronoiEdgeKind::Line)==3);}voidtest_randomized(){std::uint64_tstate=0x243f6a8885a308d3ULL;autorandom=[&state](){state^=state<<7;state^=state>>9;returnstate;};for(inttrial=0;trial<1500;++trial){intsize=int(random()%11);std::set<std::pair<longlong,longlong>>used;std::vector<Site>sites;sites.reserve(size);while(int(sites.size())<size){longlongx=static_cast<longlong>(random()%21)-10;longlongy=static_cast<longlong>(random()%21)-10;if(used.emplace(x,y).second)sites.emplace_back(x,y);}check_diagram(sites);}}longdoublepolygon_area(conststd::vector<RealPoint>&polygon){longdoubletwice_area=0;for(intindex=0;index<int(polygon.size());++index){twice_area+=m1une::geometry::cross(polygon[index],polygon[(index+1)%polygon.size()]);}returnstd::fabs(twice_area)/2;}}// namespaceintmain(){test_fixed();test_randomized();std::cout<<std::fixed<<std::setprecision(10);while(true){intisland_size,site_count;std::cin>>island_size>>site_count;if(island_size==0&&site_count==0)break;std::vector<Site>island(island_size);for(Site&point:island)std::cin>>point.x>>point.y;std::vector<Site>sites(site_count);for(Site&point:sites)std::cin>>point.x>>point.y;VoronoiDiagramdiagram=m1une::geometry::voronoi_diagram(sites);for(intsite=0;site<site_count;++site){std::vector<m1une::geometry::Line<longdouble>>half_planes;half_planes.reserve(island_size+diagram.cell_edges[site].size());for(intindex=0;index<island_size;++index){half_planes.push_back(m1une::geometry::Line<longdouble>{RealPoint(island[index]),RealPoint(island[(index+1)%island_size]),});}for(intedge_index:diagram.cell_edges[site]){constVoronoiEdge&edge=diagram.edges[edge_index];intother=edge.first_site==site?edge.second_site:edge.first_site;RealPointfirst(sites[site]);RealPointsecond(sites[other]);RealPointmidpoint=(first+second)/2.0L;RealPointdifference=second-first;RealPointdirection(-difference.y,difference.x);half_planes.push_back(m1une::geometry::Line<longdouble>{midpoint,midpoint+direction,});}autointersection=m1une::geometry::half_plane_intersection(half_planes);longdoublearea=0;if(intersection.status==m1une::geometry::HalfPlaneIntersectionStatus::Bounded){area=polygon_area(intersection.polygon);}std::cout<<area<<'\n';}}}