Chris@16
|
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
|
Chris@16
|
2
|
Chris@16
|
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
Chris@16
|
4 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
Chris@16
|
5 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
Chris@16
|
6
|
Chris@16
|
7 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
Chris@16
|
8 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
Chris@16
|
9
|
Chris@16
|
10 // Use, modification and distribution is subject to the Boost Software License,
|
Chris@16
|
11 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
12 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
13
|
Chris@16
|
14 #ifndef BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP
|
Chris@16
|
15 #define BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP
|
Chris@16
|
16
|
Chris@16
|
17 #include <cstddef>
|
Chris@16
|
18
|
Chris@16
|
19 #include <boost/numeric/conversion/cast.hpp>
|
Chris@16
|
20
|
Chris@101
|
21 #include <boost/variant/apply_visitor.hpp>
|
Chris@101
|
22 #include <boost/variant/static_visitor.hpp>
|
Chris@101
|
23 #include <boost/variant/variant_fwd.hpp>
|
Chris@16
|
24
|
Chris@16
|
25 #include <boost/geometry/algorithms/clear.hpp>
|
Chris@101
|
26 #include <boost/geometry/algorithms/envelope.hpp>
|
Chris@16
|
27 #include <boost/geometry/algorithms/not_implemented.hpp>
|
Chris@16
|
28 #include <boost/geometry/arithmetic/arithmetic.hpp>
|
Chris@16
|
29 #include <boost/geometry/geometries/concepts/check.hpp>
|
Chris@101
|
30 #include <boost/geometry/geometries/box.hpp>
|
Chris@16
|
31 #include <boost/geometry/util/math.hpp>
|
Chris@16
|
32
|
Chris@101
|
33 #include <boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp>
|
Chris@16
|
34
|
Chris@16
|
35 namespace boost { namespace geometry
|
Chris@16
|
36 {
|
Chris@16
|
37
|
Chris@16
|
38
|
Chris@16
|
39 #ifndef DOXYGEN_NO_DETAIL
|
Chris@16
|
40 namespace detail { namespace buffer
|
Chris@16
|
41 {
|
Chris@16
|
42
|
Chris@16
|
43 template <typename BoxIn, typename BoxOut, typename T, std::size_t C, std::size_t D, std::size_t N>
|
Chris@16
|
44 struct box_loop
|
Chris@16
|
45 {
|
Chris@16
|
46 typedef typename coordinate_type<BoxOut>::type coordinate_type;
|
Chris@16
|
47
|
Chris@16
|
48 static inline void apply(BoxIn const& box_in, T const& distance, BoxOut& box_out)
|
Chris@16
|
49 {
|
Chris@16
|
50 coordinate_type d = distance;
|
Chris@16
|
51 set<C, D>(box_out, get<C, D>(box_in) + d);
|
Chris@16
|
52 box_loop<BoxIn, BoxOut, T, C, D + 1, N>::apply(box_in, distance, box_out);
|
Chris@16
|
53 }
|
Chris@16
|
54 };
|
Chris@16
|
55
|
Chris@16
|
56 template <typename BoxIn, typename BoxOut, typename T, std::size_t C, std::size_t N>
|
Chris@16
|
57 struct box_loop<BoxIn, BoxOut, T, C, N, N>
|
Chris@16
|
58 {
|
Chris@16
|
59 static inline void apply(BoxIn const&, T const&, BoxOut&) {}
|
Chris@16
|
60 };
|
Chris@16
|
61
|
Chris@16
|
62 // Extends a box with the same amount in all directions
|
Chris@16
|
63 template<typename BoxIn, typename BoxOut, typename T>
|
Chris@16
|
64 inline void buffer_box(BoxIn const& box_in, T const& distance, BoxOut& box_out)
|
Chris@16
|
65 {
|
Chris@16
|
66 assert_dimension_equal<BoxIn, BoxOut>();
|
Chris@16
|
67
|
Chris@16
|
68 static const std::size_t N = dimension<BoxIn>::value;
|
Chris@16
|
69
|
Chris@16
|
70 box_loop<BoxIn, BoxOut, T, min_corner, 0, N>::apply(box_in, -distance, box_out);
|
Chris@16
|
71 box_loop<BoxIn, BoxOut, T, max_corner, 0, N>::apply(box_in, distance, box_out);
|
Chris@16
|
72 }
|
Chris@16
|
73
|
Chris@16
|
74
|
Chris@16
|
75
|
Chris@16
|
76 }} // namespace detail::buffer
|
Chris@16
|
77 #endif // DOXYGEN_NO_DETAIL
|
Chris@16
|
78
|
Chris@16
|
79 #ifndef DOXYGEN_NO_DISPATCH
|
Chris@16
|
80 namespace dispatch
|
Chris@16
|
81 {
|
Chris@16
|
82
|
Chris@16
|
83 template
|
Chris@16
|
84 <
|
Chris@16
|
85 typename Input,
|
Chris@16
|
86 typename Output,
|
Chris@16
|
87 typename TagIn = typename tag<Input>::type,
|
Chris@16
|
88 typename TagOut = typename tag<Output>::type
|
Chris@16
|
89 >
|
Chris@16
|
90 struct buffer: not_implemented<TagIn, TagOut>
|
Chris@16
|
91 {};
|
Chris@16
|
92
|
Chris@16
|
93
|
Chris@16
|
94 template <typename BoxIn, typename BoxOut>
|
Chris@16
|
95 struct buffer<BoxIn, BoxOut, box_tag, box_tag>
|
Chris@16
|
96 {
|
Chris@16
|
97 template <typename Distance>
|
Chris@16
|
98 static inline void apply(BoxIn const& box_in, Distance const& distance,
|
Chris@101
|
99 Distance const& , BoxOut& box_out)
|
Chris@16
|
100 {
|
Chris@16
|
101 detail::buffer::buffer_box(box_in, distance, box_out);
|
Chris@16
|
102 }
|
Chris@16
|
103 };
|
Chris@16
|
104
|
Chris@16
|
105 } // namespace dispatch
|
Chris@16
|
106 #endif // DOXYGEN_NO_DISPATCH
|
Chris@16
|
107
|
Chris@16
|
108
|
Chris@101
|
109 namespace resolve_variant {
|
Chris@101
|
110
|
Chris@101
|
111 template <typename Geometry>
|
Chris@101
|
112 struct buffer
|
Chris@101
|
113 {
|
Chris@101
|
114 template <typename Distance, typename GeometryOut>
|
Chris@101
|
115 static inline void apply(Geometry const& geometry,
|
Chris@101
|
116 Distance const& distance,
|
Chris@101
|
117 Distance const& chord_length,
|
Chris@101
|
118 GeometryOut& out)
|
Chris@101
|
119 {
|
Chris@101
|
120 dispatch::buffer<Geometry, GeometryOut>::apply(geometry, distance, chord_length, out);
|
Chris@101
|
121 }
|
Chris@101
|
122 };
|
Chris@101
|
123
|
Chris@101
|
124 template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
Chris@101
|
125 struct buffer<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
Chris@101
|
126 {
|
Chris@101
|
127 template <typename Distance, typename GeometryOut>
|
Chris@101
|
128 struct visitor: boost::static_visitor<void>
|
Chris@101
|
129 {
|
Chris@101
|
130 Distance const& m_distance;
|
Chris@101
|
131 Distance const& m_chord_length;
|
Chris@101
|
132 GeometryOut& m_out;
|
Chris@101
|
133
|
Chris@101
|
134 visitor(Distance const& distance,
|
Chris@101
|
135 Distance const& chord_length,
|
Chris@101
|
136 GeometryOut& out)
|
Chris@101
|
137 : m_distance(distance),
|
Chris@101
|
138 m_chord_length(chord_length),
|
Chris@101
|
139 m_out(out)
|
Chris@101
|
140 {}
|
Chris@101
|
141
|
Chris@101
|
142 template <typename Geometry>
|
Chris@101
|
143 void operator()(Geometry const& geometry) const
|
Chris@101
|
144 {
|
Chris@101
|
145 buffer<Geometry>::apply(geometry, m_distance, m_chord_length, m_out);
|
Chris@101
|
146 }
|
Chris@101
|
147 };
|
Chris@101
|
148
|
Chris@101
|
149 template <typename Distance, typename GeometryOut>
|
Chris@101
|
150 static inline void apply(
|
Chris@101
|
151 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
|
Chris@101
|
152 Distance const& distance,
|
Chris@101
|
153 Distance const& chord_length,
|
Chris@101
|
154 GeometryOut& out
|
Chris@101
|
155 )
|
Chris@101
|
156 {
|
Chris@101
|
157 boost::apply_visitor(visitor<Distance, GeometryOut>(distance, chord_length, out), geometry);
|
Chris@101
|
158 }
|
Chris@101
|
159 };
|
Chris@101
|
160
|
Chris@101
|
161 } // namespace resolve_variant
|
Chris@101
|
162
|
Chris@101
|
163
|
Chris@16
|
164 /*!
|
Chris@16
|
165 \brief \brief_calc{buffer}
|
Chris@16
|
166 \ingroup buffer
|
Chris@16
|
167 \details \details_calc{buffer, \det_buffer}.
|
Chris@16
|
168 \tparam Input \tparam_geometry
|
Chris@16
|
169 \tparam Output \tparam_geometry
|
Chris@16
|
170 \tparam Distance \tparam_numeric
|
Chris@16
|
171 \param geometry_in \param_geometry
|
Chris@16
|
172 \param geometry_out \param_geometry
|
Chris@16
|
173 \param distance The distance to be used for the buffer
|
Chris@16
|
174 \param chord_length (optional) The length of the chord's in the generated arcs around points or bends
|
Chris@16
|
175
|
Chris@16
|
176 \qbk{[include reference/algorithms/buffer.qbk]}
|
Chris@16
|
177 */
|
Chris@16
|
178 template <typename Input, typename Output, typename Distance>
|
Chris@16
|
179 inline void buffer(Input const& geometry_in, Output& geometry_out,
|
Chris@16
|
180 Distance const& distance, Distance const& chord_length = -1)
|
Chris@16
|
181 {
|
Chris@16
|
182 concept::check<Input const>();
|
Chris@16
|
183 concept::check<Output>();
|
Chris@16
|
184
|
Chris@101
|
185 resolve_variant::buffer<Input>::apply(geometry_in, distance, chord_length, geometry_out);
|
Chris@16
|
186 }
|
Chris@16
|
187
|
Chris@16
|
188 /*!
|
Chris@16
|
189 \brief \brief_calc{buffer}
|
Chris@16
|
190 \ingroup buffer
|
Chris@16
|
191 \details \details_calc{return_buffer, \det_buffer}. \details_return{buffer}.
|
Chris@16
|
192 \tparam Input \tparam_geometry
|
Chris@16
|
193 \tparam Output \tparam_geometry
|
Chris@16
|
194 \tparam Distance \tparam_numeric
|
Chris@16
|
195 \param geometry \param_geometry
|
Chris@16
|
196 \param distance The distance to be used for the buffer
|
Chris@16
|
197 \param chord_length (optional) The length of the chord's in the generated arcs
|
Chris@101
|
198 around points or bends (RESERVED, NOT YET USED)
|
Chris@16
|
199 \return \return_calc{buffer}
|
Chris@16
|
200 */
|
Chris@16
|
201 template <typename Output, typename Input, typename Distance>
|
Chris@16
|
202 Output return_buffer(Input const& geometry, Distance const& distance, Distance const& chord_length = -1)
|
Chris@16
|
203 {
|
Chris@16
|
204 concept::check<Input const>();
|
Chris@16
|
205 concept::check<Output>();
|
Chris@16
|
206
|
Chris@16
|
207 Output geometry_out;
|
Chris@16
|
208
|
Chris@101
|
209 resolve_variant::buffer<Input>::apply(geometry, distance, chord_length, geometry_out);
|
Chris@16
|
210
|
Chris@16
|
211 return geometry_out;
|
Chris@16
|
212 }
|
Chris@16
|
213
|
Chris@101
|
214 /*!
|
Chris@101
|
215 \brief \brief_calc{buffer}
|
Chris@101
|
216 \ingroup buffer
|
Chris@101
|
217 \details \details_calc{buffer, \det_buffer}.
|
Chris@101
|
218 \tparam GeometryIn \tparam_geometry
|
Chris@101
|
219 \tparam MultiPolygon \tparam_geometry{MultiPolygon}
|
Chris@101
|
220 \tparam DistanceStrategy A strategy defining distance (or radius)
|
Chris@101
|
221 \tparam SideStrategy A strategy defining creation along sides
|
Chris@101
|
222 \tparam JoinStrategy A strategy defining creation around convex corners
|
Chris@101
|
223 \tparam EndStrategy A strategy defining creation at linestring ends
|
Chris@101
|
224 \tparam PointStrategy A strategy defining creation around points
|
Chris@101
|
225 \param geometry_in \param_geometry
|
Chris@101
|
226 \param geometry_out output multi polygon (or std:: collection of polygons),
|
Chris@101
|
227 will contain a buffered version of the input geometry
|
Chris@101
|
228 \param distance_strategy The distance strategy to be used
|
Chris@101
|
229 \param side_strategy The side strategy to be used
|
Chris@101
|
230 \param join_strategy The join strategy to be used
|
Chris@101
|
231 \param end_strategy The end strategy to be used
|
Chris@101
|
232 \param point_strategy The point strategy to be used
|
Chris@101
|
233
|
Chris@101
|
234 \qbk{distinguish,with strategies}
|
Chris@101
|
235 \qbk{[include reference/algorithms/buffer_with_strategies.qbk]}
|
Chris@101
|
236 */
|
Chris@101
|
237 template
|
Chris@101
|
238 <
|
Chris@101
|
239 typename GeometryIn,
|
Chris@101
|
240 typename MultiPolygon,
|
Chris@101
|
241 typename DistanceStrategy,
|
Chris@101
|
242 typename SideStrategy,
|
Chris@101
|
243 typename JoinStrategy,
|
Chris@101
|
244 typename EndStrategy,
|
Chris@101
|
245 typename PointStrategy
|
Chris@101
|
246 >
|
Chris@101
|
247 inline void buffer(GeometryIn const& geometry_in,
|
Chris@101
|
248 MultiPolygon& geometry_out,
|
Chris@101
|
249 DistanceStrategy const& distance_strategy,
|
Chris@101
|
250 SideStrategy const& side_strategy,
|
Chris@101
|
251 JoinStrategy const& join_strategy,
|
Chris@101
|
252 EndStrategy const& end_strategy,
|
Chris@101
|
253 PointStrategy const& point_strategy)
|
Chris@101
|
254 {
|
Chris@101
|
255 typedef typename boost::range_value<MultiPolygon>::type polygon_type;
|
Chris@101
|
256 concept::check<GeometryIn const>();
|
Chris@101
|
257 concept::check<polygon_type>();
|
Chris@101
|
258
|
Chris@101
|
259 typedef typename point_type<GeometryIn>::type point_type;
|
Chris@101
|
260 typedef typename rescale_policy_type<point_type>::type rescale_policy_type;
|
Chris@101
|
261
|
Chris@101
|
262 geometry_out.clear();
|
Chris@101
|
263
|
Chris@101
|
264 model::box<point_type> box;
|
Chris@101
|
265 envelope(geometry_in, box);
|
Chris@101
|
266 buffer(box, box, distance_strategy.max_distance(join_strategy, end_strategy));
|
Chris@101
|
267
|
Chris@101
|
268 rescale_policy_type rescale_policy
|
Chris@101
|
269 = boost::geometry::get_rescale_policy<rescale_policy_type>(box);
|
Chris@101
|
270
|
Chris@101
|
271 detail::buffer::buffer_inserter<polygon_type>(geometry_in, std::back_inserter(geometry_out),
|
Chris@101
|
272 distance_strategy,
|
Chris@101
|
273 side_strategy,
|
Chris@101
|
274 join_strategy,
|
Chris@101
|
275 end_strategy,
|
Chris@101
|
276 point_strategy,
|
Chris@101
|
277 rescale_policy);
|
Chris@101
|
278 }
|
Chris@101
|
279
|
Chris@101
|
280
|
Chris@16
|
281 }} // namespace boost::geometry
|
Chris@16
|
282
|
Chris@16
|
283 #endif // BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP
|