void clip_polygon_by_half_plane( const Polygon2d& P, const vec2& q1, const vec2& q2, Polygon2d& result, bool invert ) { result.clear() ; if(P.size() == 0) { return ; } if(P.size() == 1) { if(point_is_in_half_plane(P[0], q1, q2, invert)) { result.push_back(P[0]) ; } return ; } vec2 prev_p = P[P.size() - 1] ; Sign prev_status = point_is_in_half_plane( prev_p, q1, q2, invert ) ; for(unsigned int i=0; i<P.size(); i++) { vec2 p = P[i] ; Sign status = point_is_in_half_plane( p, q1, q2, invert ) ; if( status != prev_status && status != ZERO && prev_status != ZERO ) { vec2 intersect ; if(intersect_segments(prev_p, p, q1, q2, intersect)) { result.push_back(intersect) ; } else { } } switch(status) { case NEGATIVE: break ; case ZERO: result.push_back(p) ; break ; case POSITIVE: result.push_back(p) ; break ; } prev_p = p ; prev_status = status ; } }
void minimum_area_enclosing_rectangle( const Polygon2d& PP, vec2& S, vec2& T ) { // Note: this implementation has O(n2) complexity :-( // (where n is the number of vertices in the convex hull) // If this appears to be a bottleneck, use a smarter // implementation with better complexity. Polygon2d P ; convex_hull(PP, P) ; int N = P.size() ; // Add the first vertex at the end of P P.push_back(P[0]) ; double min_area = Numeric::big_double ; for(int i=1; i<=N; i++) { vec2 Si = P[i] - P[i-1] ; if( ( Si.length2() ) < 1e-20) { continue ; } vec2 Ti(-Si.y, Si.x) ; normalize(Si) ; normalize(Ti) ; double s0 = Numeric::big_double ; double s1 = -Numeric::big_double ; double t0 = Numeric::big_double ; double t1 = -Numeric::big_double ; for(int j=1; j<N; j++) { vec2 D = P[j] - P[0] ; double s = dot(Si, D) ; s0 = gx_min(s0, s) ; s1 = gx_max(s1, s) ; double t = dot(Ti, D) ; t0 = gx_min(t0, t) ; t1 = gx_max(t1, t) ; } double area = (s1 - s0) * (t1 - t0) ; if(area < min_area) { min_area = area ; if((s1 - s0) < (t1 - t0)) { S = Si ; T = Ti ; } else { S = Ti ; T = Si ; } } } }
void convex_hull(const Polygon2d& PP, Polygon2d& result) { result.clear() ; int n = PP.size() ; vec2* P = new vec2[n+1] ; { for(int i=0; i<n; i++) { P[i] = PP[i] ; }} int u = make_chain(P, n, cmpl); P[n] = P[0]; int ch = u+make_chain(P+u, n-u+1, cmph); {for(int i=0; i<ch; i++) { result.push_back(P[i]) ; }} delete[] P ; }