diff -dur orig_polygon/detail/minkowski.hpp polygon/detail/minkowski.hpp --- orig_polygon/detail/minkowski.hpp 2011-10-27 15:35:55.318381000 -0400 +++ polygon/detail/minkowski.hpp 2011-10-27 15:11:15.283021900 -0400 @@ -82,17 +82,18 @@ } template inline polygon_set_data& - polygon_set_data::resize(coordinate_type resizing, bool corner_fill_arc, unsigned int num_circle_segments) { + polygon_set_data::resize(coordinate_type resizing, bool corner_fill_arc, unsigned int num_circle_segments, + double minUnroundedAngleDegrees) { using namespace ::boost::polygon::operators; + if(resizing == 0) return *this; + if(empty()) return *this; if(!corner_fill_arc) { if(resizing < 0) return shrink(-resizing); - if(resizing > 0) + else return bloat(resizing); - return *this; } - if(resizing == 0) return *this; - if(empty()) return *this; + if(num_circle_segments < 3) num_circle_segments = 4; rectangle_data rect; extents(rect); @@ -100,13 +101,28 @@ ::boost::polygon::bloat(rect, 10); (*this) = rect - (*this); //invert } - //make_arc(std::vector >& return_points, - //point_data< double> start, point_data< double> end, - //point_data< double> center, double r, unsigned int num_circle_segments) + + // scale arc up so that minimum radius corresponds to 'resizing', + // for bug ticket #6063. + const double our_pi=3.1415926535897932384626433832795028841971; + double arcRadScaling = 1.0/cos(2.0*our_pi/double(num_circle_segments)/2.0); + double arcRadius = double(std::abs(resizing))*arcRadScaling; + + if(minUnroundedAngleDegrees < 180.0) + { + // Don't round corners less than given angle (in radians). + // We do this by setting the minimum radius of the 'circle' to correspond to + // the distance to the 'elbow' created by normal offset of a corner with the given angle. + // e.g. an 90-degree corner with an offset of 1 will generate an elbow at distance sqrt(2). + // This will of course offset non-corners more than the given resizing, but the extra area + // gets chopped off by the intersection with normal_offset_result, below. + double elbowDist = double(std::abs(resizing))/sin(minUnroundedAngleDegrees*our_pi/180.0/2.0); + arcRadius = elbowDist*arcRadScaling; + } + std::vector > circle; - point_data center(0.0, 0.0), start(0.0, (double)resizing); - make_arc(circle, start, start, center, std::abs((double)resizing), - num_circle_segments); + point_data center(0.0, 0.0), start(0.0, arcRadius); + make_arc(circle, start, start, center, arcRadius, num_circle_segments); polygon_data poly; set_points(poly, circle.begin(), circle.end()); polygon_set_data offset_set; @@ -114,10 +130,19 @@ polygon_set_data result; detail::minkowski_offset::convolve_two_polygon_sets (result, *this, offset_set); + + // Intersect with result of 'normal' (non-minkowski-sum) offset, + // to remove offsets larger than the given 'resizing' when not near corners. + // Also for bug ticket #6063 + polygon_set_data normal_offset_result(*this); + normal_offset_result.bloat(std::abs(resizing)); + result = result & normal_offset_result; + if(resizing < 0) { result = result & rect;//eliminate overhang result = result ^ rect;//invert } + *this = result; return *this; } diff -dur orig_polygon/polygon_set_data.hpp polygon/polygon_set_data.hpp --- orig_polygon/polygon_set_data.hpp 2011-10-27 15:35:55.347381000 -0400 +++ polygon/polygon_set_data.hpp 2011-10-27 15:38:27.231381000 -0400 @@ -359,7 +359,8 @@ } inline polygon_set_data& - resize(coordinate_type resizing, bool corner_fill_arc = false, unsigned int num_circle_segments=0); + resize(coordinate_type resizing, bool corner_fill_arc = false, unsigned int num_circle_segments=0, + double minUnroundedAngleDegrees=180.0); template inline polygon_set_data&