Chris@102
|
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
|
Chris@102
|
2
|
Chris@102
|
3 // Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
Chris@102
|
4
|
Chris@102
|
5 // Use, modification and distribution is subject to the Boost Software License,
|
Chris@102
|
6 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@102
|
7 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@102
|
8
|
Chris@102
|
9 #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_MITER_HPP
|
Chris@102
|
10 #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_MITER_HPP
|
Chris@102
|
11
|
Chris@102
|
12 #include <boost/assert.hpp>
|
Chris@102
|
13 #include <boost/geometry/core/cs.hpp>
|
Chris@102
|
14 #include <boost/geometry/policies/compare.hpp>
|
Chris@102
|
15 #include <boost/geometry/util/math.hpp>
|
Chris@102
|
16 #include <boost/geometry/util/select_most_precise.hpp>
|
Chris@102
|
17
|
Chris@102
|
18 #include <boost/geometry/strategies/buffer.hpp>
|
Chris@102
|
19
|
Chris@102
|
20
|
Chris@102
|
21 namespace boost { namespace geometry
|
Chris@102
|
22 {
|
Chris@102
|
23
|
Chris@102
|
24 namespace strategy { namespace buffer
|
Chris@102
|
25 {
|
Chris@102
|
26
|
Chris@102
|
27 /*!
|
Chris@102
|
28 \brief Let the buffer create sharp corners
|
Chris@102
|
29 \ingroup strategies
|
Chris@102
|
30 \details This strategy can be used as JoinStrategy for the buffer algorithm.
|
Chris@102
|
31 It creates a sharp corners around each convex vertex. It can be applied
|
Chris@102
|
32 for (multi)linestrings and (multi)polygons.
|
Chris@102
|
33 If corners are sharp by themselves, the miters might become very long. Therefore
|
Chris@102
|
34 there is a limit (miter_limit), in terms of the used distance, which limits
|
Chris@102
|
35 their length. The miter is not changed to a bevel form (as done in some
|
Chris@102
|
36 other software), it is just adapted to the specified miter_limit but keeps
|
Chris@102
|
37 its miter form.
|
Chris@102
|
38 If the buffer distance is 5.0, and the miter limit is 2.0, generated points
|
Chris@102
|
39 will be located at a distance of at most 10.0 (2*5) units.
|
Chris@102
|
40 This strategy is only applicable for Cartesian coordinate systems.
|
Chris@102
|
41
|
Chris@102
|
42 \qbk{
|
Chris@102
|
43 [heading Example]
|
Chris@102
|
44 [buffer_join_miter]
|
Chris@102
|
45 [heading Output]
|
Chris@102
|
46 [$img/strategies/buffer_join_miter.png]
|
Chris@102
|
47 [heading See also]
|
Chris@102
|
48 \* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]
|
Chris@102
|
49 \* [link geometry.reference.strategies.strategy_buffer_join_round join_round]
|
Chris@102
|
50 }
|
Chris@102
|
51 */
|
Chris@102
|
52 class join_miter
|
Chris@102
|
53 {
|
Chris@102
|
54 public:
|
Chris@102
|
55
|
Chris@102
|
56 //! \brief Constructs the strategy
|
Chris@102
|
57 //! \param miter_limit The miter limit, to avoid excessively long miters around sharp corners
|
Chris@102
|
58 explicit inline join_miter(double miter_limit = 5.0)
|
Chris@102
|
59 : m_miter_limit(valid_limit(miter_limit))
|
Chris@102
|
60 {}
|
Chris@102
|
61
|
Chris@102
|
62 #ifndef DOXYGEN_SHOULD_SKIP_THIS
|
Chris@102
|
63 //! Fills output_range with a sharp shape around a vertex
|
Chris@102
|
64 template <typename Point, typename DistanceType, typename RangeOut>
|
Chris@102
|
65 inline bool apply(Point const& ip, Point const& vertex,
|
Chris@102
|
66 Point const& perp1, Point const& perp2,
|
Chris@102
|
67 DistanceType const& buffer_distance,
|
Chris@102
|
68 RangeOut& range_out) const
|
Chris@102
|
69 {
|
Chris@102
|
70 geometry::equal_to<Point> equals;
|
Chris@102
|
71 if (equals(ip, vertex))
|
Chris@102
|
72 {
|
Chris@102
|
73 return false;
|
Chris@102
|
74 }
|
Chris@102
|
75 if (equals(perp1, perp2))
|
Chris@102
|
76 {
|
Chris@102
|
77 return false;
|
Chris@102
|
78 }
|
Chris@102
|
79
|
Chris@102
|
80 typedef typename coordinate_type<Point>::type coordinate_type;
|
Chris@102
|
81 typedef typename geometry::select_most_precise
|
Chris@102
|
82 <
|
Chris@102
|
83 coordinate_type,
|
Chris@102
|
84 double
|
Chris@102
|
85 >::type promoted_type;
|
Chris@102
|
86
|
Chris@102
|
87 Point p = ip;
|
Chris@102
|
88
|
Chris@102
|
89 // Check the distance ip-vertex (= miter distance)
|
Chris@102
|
90 // (We calculate it manually (not using Pythagoras strategy) to reuse
|
Chris@102
|
91 // dx and dy)
|
Chris@102
|
92 coordinate_type const dx = get<0>(p) - get<0>(vertex);
|
Chris@102
|
93 coordinate_type const dy = get<1>(p) - get<1>(vertex);
|
Chris@102
|
94
|
Chris@102
|
95 promoted_type const distance = geometry::math::sqrt(dx * dx + dy * dy);
|
Chris@102
|
96
|
Chris@102
|
97 promoted_type const max_distance
|
Chris@102
|
98 = m_miter_limit * geometry::math::abs(buffer_distance);
|
Chris@102
|
99
|
Chris@102
|
100 if (distance > max_distance)
|
Chris@102
|
101 {
|
Chris@102
|
102 BOOST_ASSERT(distance != 0.0);
|
Chris@102
|
103
|
Chris@102
|
104 promoted_type const proportion = max_distance / distance;
|
Chris@102
|
105 set<0>(p, get<0>(vertex) + dx * proportion);
|
Chris@102
|
106 set<1>(p, get<1>(vertex) + dy * proportion);
|
Chris@102
|
107 }
|
Chris@102
|
108
|
Chris@102
|
109 range_out.push_back(perp1);
|
Chris@102
|
110 range_out.push_back(p);
|
Chris@102
|
111 range_out.push_back(perp2);
|
Chris@102
|
112 return true;
|
Chris@102
|
113 }
|
Chris@102
|
114
|
Chris@102
|
115 template <typename NumericType>
|
Chris@102
|
116 inline NumericType max_distance(NumericType const& distance) const
|
Chris@102
|
117 {
|
Chris@102
|
118 return distance * m_miter_limit;
|
Chris@102
|
119 }
|
Chris@102
|
120
|
Chris@102
|
121 #endif // DOXYGEN_SHOULD_SKIP_THIS
|
Chris@102
|
122
|
Chris@102
|
123 private :
|
Chris@102
|
124 double valid_limit(double miter_limit) const
|
Chris@102
|
125 {
|
Chris@102
|
126 if (miter_limit < 1.0)
|
Chris@102
|
127 {
|
Chris@102
|
128 // It should always exceed the buffer distance
|
Chris@102
|
129 miter_limit = 1.0;
|
Chris@102
|
130 }
|
Chris@102
|
131 return miter_limit;
|
Chris@102
|
132 }
|
Chris@102
|
133
|
Chris@102
|
134 double m_miter_limit;
|
Chris@102
|
135 };
|
Chris@102
|
136
|
Chris@102
|
137 }} // namespace strategy::buffer
|
Chris@102
|
138
|
Chris@102
|
139
|
Chris@102
|
140 }} // namespace boost::geometry
|
Chris@102
|
141
|
Chris@102
|
142 #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_MITER_HPP
|