// http://astronomy.swin.edu.au/~pbourke/geometry/polyarea/ vec2 barycenter(const Polygon2d& P) { gx_assert(P.size() > 0) ; double A = signed_area(P) ; if(::fabs(A) < 1e-30) { return P[0] ; } double x = 0.0 ; double y = 0.0 ; for(unsigned int i=0; i<P.size(); i++) { unsigned int j = (i+1) % P.size() ; const vec2& t1 = P[i] ; const vec2& t2 = P[j] ; double d = (t1.x * t2.y - t2.x * t1.y) ; x += (t1.x + t2.x) * d ; y += (t1.y + t2.y) * d ; } return vec2( x / (6.0 * A), y / (6.0 * A) ) ; }
// Clipping with convex window using Sutherland-Hogdman reentrant clipping void convex_clip_polygon( const Polygon2d& P, const Polygon2d& clip, Polygon2d& result ) { gx_parano_assert(polygon_is_convex(clip)) ; Polygon2d tmp1 = P ; bool invert = (signed_area(tmp1) != signed_area(clip)) ; Polygon2d tmp2 ; Polygon2d* src = &tmp1 ; Polygon2d* dst = &tmp2 ; for(unsigned int i=0; i<clip.size(); i++) { unsigned int j = ((i+1) % clip.size()) ; const vec2& p1 = clip[i] ; const vec2& p2 = clip[j] ; clip_polygon_by_half_plane(*src, p1, p2, *dst, invert) ; gx_swap(src, dst) ; } result = *src ; }
Point2 Exact_adaptive_kernel::circumcenter( Point2 const& a, Point2 const& b, Point2 const& c ) { Point2 ba = b - a; Point2 ca = c - a; double bal = distance_squared( a, b ); double cal = distance_squared( a, c ); double denominator = 0.25 / signed_area( b, c, a ); Point2 d( ( ca( 1 ) * bal - ba( 1 ) * cal ) * denominator, ( ba( 0 ) * cal - ca( 0 ) * bal ) * denominator ); return a + d; }
void convex_clip_segment( Segment2d& S, const Polygon2d& window ) { gx_parano_assert(polygon_is_convex(window)) ; bool invert = (signed_area(window) < 0) ; for(unsigned int i=0; i<window.size(); i++) { unsigned int j = ((i+1) % window.size()) ; clip_segment_by_half_plane(S, window[i], window[j], invert) ; } }
Point2 Exact_adaptive_kernel::circumcenter(Point2 const& p1, Point2 const& p2, Point2 const& p3) { Point2 p2p1(p2.x()-p1.x(), p2.y()-p1.y()); Point2 p3p1(p3.x()-p1.x(), p3.y()-p1.y()); Point2 p2p3(p2.x()-p3.x(), p2.y()-p3.y()); double p2p1dist = p2p1.x()*p2p1.x() + p2p1.y()*p2p1.y(); double p3p1dist = p3p1.x()*p3p1.x() + p3p1.y()*p3p1.y(); double denominator = 0.5/(2.0*signed_area(p1, p2, p3)); BOOST_ASSERT(denominator > 0.0); double dx = (p3p1.y() * p2p1dist - p2p1.y() * p3p1dist) * denominator; double dy = (p2p1.x() * p3p1dist - p3p1.x() * p2p1dist) * denominator; return Point2(p1.x()+dx, p1.y()+dy); }
Point2 Exact_adaptive_kernel::offcenter( Point2 const& a, Point2 const& b, Point2 const& c, double offconstant ) { Point2 ba = b - a; Point2 ca = c - a; Point2 bc = b - c; double abdist = distance_squared( a, b ); double acdist = distance_squared( a, c ); double bcdist = distance_squared( b, c ); double denominator = 0.25 / signed_area( b, c, a ); BOOST_ASSERT( denominator > 0.0 ); double dx = ( ca(1) * abdist - ba(1) * acdist ) * denominator; double dy = ( ba(0) * acdist - ca(0) * abdist ) * denominator; double dxoff, dyoff; if ( ( abdist < acdist ) && ( abdist < bcdist ) ) { dxoff = 0.5 * ba(0) - offconstant * ba(1); dyoff = 0.5 * ba(1) + offconstant * ba(0); if ( dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy ) { dx = dxoff; dy = dyoff; } } else if ( acdist < bcdist ) { dxoff = 0.5 * ca(0) + offconstant * ca(1); dyoff = 0.5 * ca(1) - offconstant * ca(0); if ( dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy ) { dx = dxoff; dy = dyoff; } } else { dxoff = 0.5 * bc(0) - offconstant * bc(1); dyoff = 0.5 * bc(1) + offconstant * bc(0); if ( dxoff * dxoff + dyoff * dyoff < ( dx - ba(0) ) * ( dx - ba(0) ) + ( dy - ba(1) ) * ( dy - ba(1) ) ) { dx = ba(0) + dxoff; dy = ba(1) + dyoff; } } return Point2( a(0) + dx, a(1) + dy ); }
// Compute the kernel using Sutherland-Hogdman reentrant clipping // The kernel is obtained by clipping the polygon with each // half-plane yielded by its sides. void kernel(const Polygon2d& P, Polygon2d& result) { Array1d<Sign> sign(P.size()) ; for(unsigned int i=0; i<P.size(); i++) { unsigned int j = ((i+1) % P.size()) ; unsigned int k = ((j+1) % P.size()) ; sign(j) = orient(P[i],P[j],P[k]) ; } bool invert = (signed_area(P) < 0) ; Polygon2d tmp1 = P ; Polygon2d tmp2 ; Polygon2d* src = &tmp1 ; Polygon2d* dst = &tmp2 ; for(unsigned int i=0; i<P.size(); i++) { unsigned int j = ((i+1) % P.size()) ; const vec2& p1 = P[i] ; const vec2& p2 = P[j] ; if((p2-p1).length() == 0) { std::cerr << "null edge in poly" << std::endl ; continue ; } // Optimization: do not clip by convex-convex edges // (Thanks to Rodrigo Toledo for the tip !) if(!invert && sign(i) != NEGATIVE && sign(j) != NEGATIVE) { continue ; } if(invert && sign(i) != POSITIVE && sign(j) != POSITIVE) { continue ; } clip_polygon_by_half_plane(*src, p1, p2, *dst, invert) ; gx_swap(src, dst) ; } result = *src ; }