]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/geometry/include/boost/geometry/strategies/cartesian/buffer_join_round.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / geometry / include / boost / geometry / strategies / cartesian / buffer_join_round.hpp
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2
3 // Copyright (c) 2012-2015 Barend Gehrels, Amsterdam, the Netherlands.
4
5 // This file was modified by Oracle on 2015.
6 // Modifications copyright (c) 2015, Oracle and/or its affiliates.
7
8 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
9
10 // Use, modification and distribution is subject to the Boost Software License,
11 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
12 // http://www.boost.org/LICENSE_1_0.txt)
13
14 #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_HPP
15 #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_HPP
16
17 #include <algorithm>
18
19 #include <boost/geometry/core/cs.hpp>
20 #include <boost/geometry/policies/compare.hpp>
21 #include <boost/geometry/strategies/buffer.hpp>
22 #include <boost/geometry/util/math.hpp>
23 #include <boost/geometry/util/select_most_precise.hpp>
24
25 #ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN
26 #include <iostream>
27 #include <boost/geometry/io/wkt/wkt.hpp>
28 #endif
29
30
31 namespace boost { namespace geometry
32 {
33
34
35 namespace strategy { namespace buffer
36 {
37
38 /*!
39 \brief Let the buffer create rounded corners
40 \ingroup strategies
41 \details This strategy can be used as JoinStrategy for the buffer algorithm.
42 It creates a rounded corners around each convex vertex. It can be applied
43 for (multi)linestrings and (multi)polygons.
44 This strategy is only applicable for Cartesian coordinate systems.
45
46 \qbk{
47 [heading Example]
48 [buffer_join_round]
49 [heading Output]
50 [$img/strategies/buffer_join_round.png]
51 [heading See also]
52 \* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]
53 \* [link geometry.reference.strategies.strategy_buffer_join_miter join_miter]
54 }
55 */
56 class join_round
57 {
58 public :
59
60 //! \brief Constructs the strategy
61 //! \param points_per_circle points which would be used for a full circle
62 explicit inline join_round(std::size_t points_per_circle = 90)
63 : m_points_per_circle(points_per_circle)
64 {}
65
66 private :
67 template
68 <
69 typename PromotedType,
70 typename Point,
71 typename DistanceType,
72 typename RangeOut
73 >
74 inline void generate_points(Point const& vertex,
75 Point const& perp1, Point const& perp2,
76 DistanceType const& buffer_distance,
77 RangeOut& range_out) const
78 {
79 PromotedType const dx1 = get<0>(perp1) - get<0>(vertex);
80 PromotedType const dy1 = get<1>(perp1) - get<1>(vertex);
81 PromotedType const dx2 = get<0>(perp2) - get<0>(vertex);
82 PromotedType const dy2 = get<1>(perp2) - get<1>(vertex);
83
84 PromotedType const two_pi = geometry::math::two_pi<PromotedType>();
85
86 PromotedType const angle1 = atan2(dy1, dx1);
87 PromotedType angle2 = atan2(dy2, dx2);
88 while (angle2 > angle1)
89 {
90 angle2 -= two_pi;
91 }
92 PromotedType const angle_diff = angle1 - angle2;
93
94 // Divide the angle into an integer amount of steps to make it
95 // visually correct also for a low number of points / circle
96
97 // If a full circle is divided into 3 parts (e.g. angle is 125),
98 // the one point in between must still be generated
99 // The calculation below:
100 // - generates 1 point in between for an angle of 125 based on 3 points
101 // - generates 0 points in between for an angle of 90 based on 4 points
102
103 std::size_t const n = (std::max)(static_cast<std::size_t>(
104 ceil(m_points_per_circle * angle_diff / two_pi)), std::size_t(1));
105
106 PromotedType const diff = angle_diff / static_cast<PromotedType>(n);
107 PromotedType a = angle1 - diff;
108
109 // Walk to n - 1 to avoid generating the last point
110 for (std::size_t i = 0; i < n - 1; i++, a -= diff)
111 {
112 Point p;
113 set<0>(p, get<0>(vertex) + buffer_distance * cos(a));
114 set<1>(p, get<1>(vertex) + buffer_distance * sin(a));
115 range_out.push_back(p);
116 }
117 }
118
119 public :
120
121
122 #ifndef DOXYGEN_SHOULD_SKIP_THIS
123 //! Fills output_range with a rounded shape around a vertex
124 template <typename Point, typename DistanceType, typename RangeOut>
125 inline bool apply(Point const& ip, Point const& vertex,
126 Point const& perp1, Point const& perp2,
127 DistanceType const& buffer_distance,
128 RangeOut& range_out) const
129 {
130 typedef typename coordinate_type<Point>::type coordinate_type;
131 typedef typename boost::range_value<RangeOut>::type output_point_type;
132
133 typedef typename geometry::select_most_precise
134 <
135 typename geometry::select_most_precise
136 <
137 coordinate_type,
138 typename geometry::coordinate_type<output_point_type>::type
139 >::type,
140 double
141 >::type promoted_type;
142
143 geometry::equal_to<Point> equals;
144 if (equals(perp1, perp2))
145 {
146 #ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN
147 std::cout << "Corner for equal points " << geometry::wkt(ip) << " " << geometry::wkt(perp1) << std::endl;
148 #endif
149 return false;
150 }
151
152 // Generate 'vectors'
153 coordinate_type vix = (get<0>(ip) - get<0>(vertex));
154 coordinate_type viy = (get<1>(ip) - get<1>(vertex));
155
156 promoted_type length_i = geometry::math::sqrt(vix * vix + viy * viy);
157 DistanceType const bd = geometry::math::abs(buffer_distance);
158 promoted_type prop = bd / length_i;
159
160 Point bp;
161 set<0>(bp, get<0>(vertex) + vix * prop);
162 set<1>(bp, get<1>(vertex) + viy * prop);
163
164 range_out.push_back(perp1);
165 generate_points<promoted_type>(vertex, perp1, perp2, bd, range_out);
166 range_out.push_back(perp2);
167 return true;
168 }
169
170 template <typename NumericType>
171 static inline NumericType max_distance(NumericType const& distance)
172 {
173 return distance;
174 }
175
176 #endif // DOXYGEN_SHOULD_SKIP_THIS
177
178 private :
179 std::size_t m_points_per_circle;
180 };
181
182
183 }} // namespace strategy::buffer
184
185 }} // namespace boost::geometry
186
187 #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_HPP