Ticket #6063: boost_polygon_bug6063_fix2.patch

File boost_polygon_bug6063_fix2.patch, 4.2 KB (added by dbfaken@…, 11 years ago)

Second version of fix for ticket 6063. Created against boost 1.47.0.

  • detail/minkowski.hpp

    diff -dur orig_polygon/detail/minkowski.hpp polygon/detail/minkowski.hpp
    old new  
    8282}
    8383  template<typename T>
    8484  inline polygon_set_data<T>&
    85   polygon_set_data<T>::resize(coordinate_type resizing, bool corner_fill_arc, unsigned int num_circle_segments) {
     85  polygon_set_data<T>::resize(coordinate_type resizing, bool corner_fill_arc, unsigned int num_circle_segments,
     86                              double minUnroundedAngleDegrees) {
    8687    using namespace ::boost::polygon::operators;
     88    if(resizing == 0) return *this;
     89    if(empty()) return *this;
    8790    if(!corner_fill_arc) {
    8891      if(resizing < 0)
    8992        return shrink(-resizing);
    90       if(resizing > 0)
     93      else
    9194        return bloat(resizing);
    92       return *this;
    9395    }
    94     if(resizing == 0) return *this;
    95     if(empty()) return *this;
     96
    9697    if(num_circle_segments < 3) num_circle_segments = 4;
    9798    rectangle_data<coordinate_type> rect;
    9899    extents(rect);
     
    100101      ::boost::polygon::bloat(rect, 10);
    101102      (*this) = rect - (*this); //invert
    102103    }
    103     //make_arc(std::vector<point_data< T> >& return_points, 
    104     //point_data< double> start, point_data< double>  end,
    105     //point_data< double> center,  double r, unsigned int num_circle_segments)     
     104
     105    // scale arc up so that minimum radius corresponds to 'resizing',
     106    // for bug ticket #6063.
     107    const double our_pi=3.1415926535897932384626433832795028841971;
     108    double arcRadScaling = 1.0/cos(2.0*our_pi/double(num_circle_segments)/2.0);
     109    double arcRadius = double(std::abs(resizing))*arcRadScaling;
     110
     111    if(minUnroundedAngleDegrees < 180.0)
     112    {
     113        // Don't round corners less than given angle (in radians).
     114        // We do this by setting the minimum radius of the 'circle' to correspond to
     115        // the distance to the 'elbow' created by normal offset of a corner with the given angle.
     116        // e.g. an 90-degree corner with an offset of 1 will generate an elbow at distance sqrt(2).
     117        // This will of course offset non-corners more than the given resizing, but the extra area
     118        // gets chopped off by the intersection with normal_offset_result, below.
     119        double elbowDist = double(std::abs(resizing))/sin(minUnroundedAngleDegrees*our_pi/180.0/2.0);
     120        arcRadius = elbowDist*arcRadScaling;
     121    }
     122
    106123    std::vector<point_data<coordinate_type> > circle;
    107     point_data<double> center(0.0, 0.0), start(0.0, (double)resizing);
    108     make_arc(circle, start, start, center, std::abs((double)resizing),
    109              num_circle_segments);
     124    point_data<double> center(0.0, 0.0), start(0.0, arcRadius);
     125    make_arc(circle, start, start, center, arcRadius, num_circle_segments);
    110126    polygon_data<coordinate_type> poly;
    111127    set_points(poly, circle.begin(), circle.end());
    112128    polygon_set_data<coordinate_type> offset_set;
     
    114130    polygon_set_data<coordinate_type> result;
    115131    detail::minkowski_offset<coordinate_type>::convolve_two_polygon_sets
    116132      (result, *this, offset_set);
     133
     134    // Intersect with result of 'normal' (non-minkowski-sum) offset,
     135    // to remove offsets larger than the given 'resizing' when not near corners.
     136    // Also for bug ticket #6063
     137    polygon_set_data<coordinate_type> normal_offset_result(*this);
     138    normal_offset_result.bloat(std::abs(resizing));
     139    result = result & normal_offset_result;
     140
    117141    if(resizing < 0) {
    118142      result = result & rect;//eliminate overhang
    119143      result = result ^ rect;//invert
    120144    }
     145
    121146    *this = result;
    122147    return *this;
    123148  }
  • polygon_set_data.hpp

    diff -dur orig_polygon/polygon_set_data.hpp polygon/polygon_set_data.hpp
    old new  
    359359    }
    360360
    361361    inline polygon_set_data&
    362     resize(coordinate_type resizing, bool corner_fill_arc = false, unsigned int num_circle_segments=0);
     362    resize(coordinate_type resizing, bool corner_fill_arc = false, unsigned int num_circle_segments=0,
     363           double minUnroundedAngleDegrees=180.0);
    363364
    364365    template <typename transform_type>
    365366    inline polygon_set_data&