Example #1
0
        // 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)
            ) ;
        }
Example #2
0
 // 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;
}
Example #4
0
        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 );
}
Example #7
0
        // 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 ;
        }