1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
5 // Use, modification and distribution is subject to the Boost Software License,
6 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
9 #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_MITER_HPP
10 #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_MITER_HPP
12 #include <boost/assert.hpp>
13 #include <boost/geometry/core/cs.hpp>
14 #include <boost/geometry/policies/compare.hpp>
15 #include <boost/geometry/util/math.hpp>
16 #include <boost/geometry/util/select_most_precise.hpp>
18 #include <boost/geometry/strategies/buffer.hpp>
21 namespace boost { namespace geometry
24 namespace strategy { namespace buffer
28 \brief Let the buffer create sharp corners
30 \details This strategy can be used as JoinStrategy for the buffer algorithm.
31 It creates a sharp corners around each convex vertex. It can be applied
32 for (multi)linestrings and (multi)polygons.
33 If corners are sharp by themselves, the miters might become very long. Therefore
34 there is a limit (miter_limit), in terms of the used distance, which limits
35 their length. The miter is not changed to a bevel form (as done in some
36 other software), it is just adapted to the specified miter_limit but keeps
38 This strategy is only applicable for Cartesian coordinate systems.
44 [$img/strategies/buffer_join_miter.png]
46 \* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]
47 \* [link geometry.reference.strategies.strategy_buffer_join_round join_round]
54 //! \brief Constructs the strategy
55 //! \param miter_limit The miter limit, to avoid excessively long miters around sharp corners
56 explicit inline join_miter(double miter_limit = 5.0)
57 : m_miter_limit(valid_limit(miter_limit))
60 #ifndef DOXYGEN_SHOULD_SKIP_THIS
61 //! Fills output_range with a sharp shape around a vertex
62 template <typename Point, typename DistanceType, typename RangeOut>
63 inline bool apply(Point const& ip, Point const& vertex,
64 Point const& perp1, Point const& perp2,
65 DistanceType const& buffer_distance,
66 RangeOut& range_out) const
68 geometry::equal_to<Point> equals;
69 if (equals(ip, vertex))
73 if (equals(perp1, perp2))
78 typedef typename coordinate_type<Point>::type coordinate_type;
79 typedef typename geometry::select_most_precise
83 >::type promoted_type;
87 // Check the distance ip-vertex (= miter distance)
88 // (We calculate it manually (not using Pythagoras strategy) to reuse
90 coordinate_type const dx = get<0>(p) - get<0>(vertex);
91 coordinate_type const dy = get<1>(p) - get<1>(vertex);
93 promoted_type const distance = geometry::math::sqrt(dx * dx + dy * dy);
95 promoted_type const max_distance
96 = m_miter_limit * geometry::math::abs(buffer_distance);
98 if (distance > max_distance)
100 BOOST_ASSERT(distance != 0.0);
102 promoted_type const proportion = max_distance / distance;
103 set<0>(p, get<0>(vertex) + dx * proportion);
104 set<1>(p, get<1>(vertex) + dy * proportion);
107 range_out.push_back(perp1);
108 range_out.push_back(p);
109 range_out.push_back(perp2);
113 template <typename NumericType>
114 inline NumericType max_distance(NumericType const& distance) const
116 return distance * m_miter_limit;
119 #endif // DOXYGEN_SHOULD_SKIP_THIS
122 double valid_limit(double miter_limit) const
124 if (miter_limit < 1.0)
126 // It should always exceed the buffer distance
132 double m_miter_limit;
135 }} // namespace strategy::buffer
138 }} // namespace boost::geometry
140 #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_MITER_HPP