diff --git a/include/boost/geometry/strategies/cartesian/buffer_join_miter.hpp b/include/boost/geometry/strategies/cartesian/buffer_join_miter.hpp index 8968a6af4..06fe685cc 100644 --- a/include/boost/geometry/strategies/cartesian/buffer_join_miter.hpp +++ b/include/boost/geometry/strategies/cartesian/buffer_join_miter.hpp @@ -32,6 +32,11 @@ namespace strategy { namespace buffer \details This strategy can be used as JoinStrategy for the buffer algorithm. It creates a sharp corners around each convex vertex. It can be applied for (multi)linestrings and (multi)polygons. + If corners are sharp by themselves, the miters might become very long. Therefore + there is a limit (miter_limit), in terms of the used distance, which limits + their length. The miter is not changed to a bevel form (as done in some + other software), it is just adapted to the specified miter_limit but keeps + its miter form. This strategy is only applicable for Cartesian coordinate systems. \qbk{ @@ -47,12 +52,11 @@ namespace strategy { namespace buffer class join_miter { public: - //! Constructs the strategy - inline join_miter() - {} - //! Constructs the strategy with a (currently dummy) integer - explicit inline join_miter(int) + //! \brief Constructs the strategy + //! \param miter_limit The miter limit, to avoid excessively long miters around sharp corners + explicit inline join_miter(double miter_limit = 5.0) + : m_miter_limit(valid_limit(miter_limit)) {} #ifndef DOXYGEN_SHOULD_SKIP_THIS @@ -78,25 +82,24 @@ public: Point p = ip; - // Normalize it and give it X*dist. - coordinate_type const dx = get<0>(ip) - get<0>(vertex); - coordinate_type const dy = get<1>(ip) - get<1>(vertex); + // Check the distance ip-vertex (= miter distance) + // (We calculate it manually (not using Pythagoras strategy) to reuse + // dx and dy) + coordinate_type const dx = get<0>(p) - get<0>(vertex); + coordinate_type const dy = get<1>(p) - get<1>(vertex); - promoted_type const length = geometry::math::sqrt(dx * dx + dy * dy); + promoted_type const distance = geometry::math::sqrt(dx * dx + dy * dy); - BOOST_ASSERT(length != 0.0); // because ip/vertex are not equal + promoted_type const max_distance + = m_miter_limit * geometry::math::abs(buffer_distance); - // TODO: make max-mitre-limit flexible - promoted_type const ten = 10.0; - promoted_type const zero_seven = 0.7; - - promoted_type const max = ten * geometry::math::abs(buffer_distance); - - if (length > max) + if (distance > max_distance) { - promoted_type const prop = zero_seven * buffer_distance / length; - set<0>(p, get<0>(vertex) + dx * prop); - set<1>(p, get<1>(vertex) + dy * prop); + BOOST_ASSERT(distance != 0.0); + + promoted_type const proportion = max_distance / distance; + set<0>(p, get<0>(vertex) + dx * proportion); + set<1>(p, get<1>(vertex) + dy * proportion); } range_out.push_back(perp1); @@ -105,6 +108,19 @@ public: return true; } #endif // DOXYGEN_SHOULD_SKIP_THIS + +private : + double valid_limit(double miter_limit) const + { + if (miter_limit < 1.0) + { + // It should always exceed the buffer distance + miter_limit = 1.0; + } + return miter_limit; + } + + double m_miter_limit; }; }} // namespace strategy::buffer diff --git a/test/algorithms/buffer/polygon_buffer.cpp b/test/algorithms/buffer/polygon_buffer.cpp index 2d52e99f0..ed7389ece 100644 --- a/test/algorithms/buffer/polygon_buffer.cpp +++ b/test/algorithms/buffer/polygon_buffer.cpp @@ -87,7 +87,7 @@ void test_all() { typedef bg::model::polygon
polygon_type;
- bg::strategy::buffer::join_miter join_miter;
+ bg::strategy::buffer::join_miter join_miter(10.0);
bg::strategy::buffer::join_round join_round(100);
bg::strategy::buffer::end_flat end_flat;
bg::strategy::buffer::end_round end_round(100);
@@ -277,7 +277,7 @@ void test_all()
test_one