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@101
|
6 // Copyright (c) 2014 Samuel Debionne, Grenoble, France.
|
Chris@16
|
7
|
Chris@16
|
8 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
Chris@16
|
9 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
Chris@16
|
10
|
Chris@16
|
11 // Use, modification and distribution is subject to the Boost Software License,
|
Chris@16
|
12 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
13 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
14
|
Chris@16
|
15 #ifndef BOOST_GEOMETRY_ALGORITHMS_EXPAND_HPP
|
Chris@16
|
16 #define BOOST_GEOMETRY_ALGORITHMS_EXPAND_HPP
|
Chris@16
|
17
|
Chris@16
|
18
|
Chris@16
|
19 #include <cstddef>
|
Chris@16
|
20
|
Chris@16
|
21 #include <boost/numeric/conversion/cast.hpp>
|
Chris@16
|
22
|
Chris@101
|
23 #include <boost/variant/apply_visitor.hpp>
|
Chris@101
|
24 #include <boost/variant/static_visitor.hpp>
|
Chris@101
|
25 #include <boost/variant/variant_fwd.hpp>
|
Chris@101
|
26
|
Chris@16
|
27 #include <boost/geometry/algorithms/not_implemented.hpp>
|
Chris@16
|
28 #include <boost/geometry/core/coordinate_dimension.hpp>
|
Chris@16
|
29 #include <boost/geometry/geometries/concepts/check.hpp>
|
Chris@16
|
30
|
Chris@16
|
31 #include <boost/geometry/util/select_coordinate_type.hpp>
|
Chris@16
|
32
|
Chris@16
|
33 #include <boost/geometry/strategies/compare.hpp>
|
Chris@16
|
34 #include <boost/geometry/policies/compare.hpp>
|
Chris@16
|
35
|
Chris@16
|
36
|
Chris@16
|
37 namespace boost { namespace geometry
|
Chris@16
|
38 {
|
Chris@16
|
39
|
Chris@16
|
40 #ifndef DOXYGEN_NO_DETAIL
|
Chris@16
|
41 namespace detail { namespace expand
|
Chris@16
|
42 {
|
Chris@16
|
43
|
Chris@16
|
44
|
Chris@16
|
45 template
|
Chris@16
|
46 <
|
Chris@16
|
47 typename StrategyLess, typename StrategyGreater,
|
Chris@16
|
48 std::size_t Dimension, std::size_t DimensionCount
|
Chris@16
|
49 >
|
Chris@16
|
50 struct point_loop
|
Chris@16
|
51 {
|
Chris@16
|
52 template <typename Box, typename Point>
|
Chris@16
|
53 static inline void apply(Box& box, Point const& source)
|
Chris@16
|
54 {
|
Chris@16
|
55 typedef typename strategy::compare::detail::select_strategy
|
Chris@16
|
56 <
|
Chris@16
|
57 StrategyLess, 1, Point, Dimension
|
Chris@16
|
58 >::type less_type;
|
Chris@16
|
59
|
Chris@16
|
60 typedef typename strategy::compare::detail::select_strategy
|
Chris@16
|
61 <
|
Chris@16
|
62 StrategyGreater, -1, Point, Dimension
|
Chris@16
|
63 >::type greater_type;
|
Chris@16
|
64
|
Chris@16
|
65 typedef typename select_coordinate_type<Point, Box>::type coordinate_type;
|
Chris@16
|
66
|
Chris@16
|
67 less_type less;
|
Chris@16
|
68 greater_type greater;
|
Chris@16
|
69
|
Chris@16
|
70 coordinate_type const coord = get<Dimension>(source);
|
Chris@16
|
71
|
Chris@16
|
72 if (less(coord, get<min_corner, Dimension>(box)))
|
Chris@16
|
73 {
|
Chris@16
|
74 set<min_corner, Dimension>(box, coord);
|
Chris@16
|
75 }
|
Chris@16
|
76
|
Chris@16
|
77 if (greater(coord, get<max_corner, Dimension>(box)))
|
Chris@16
|
78 {
|
Chris@16
|
79 set<max_corner, Dimension>(box, coord);
|
Chris@16
|
80 }
|
Chris@16
|
81
|
Chris@16
|
82 point_loop
|
Chris@16
|
83 <
|
Chris@16
|
84 StrategyLess, StrategyGreater,
|
Chris@16
|
85 Dimension + 1, DimensionCount
|
Chris@16
|
86 >::apply(box, source);
|
Chris@16
|
87 }
|
Chris@16
|
88 };
|
Chris@16
|
89
|
Chris@16
|
90
|
Chris@16
|
91 template
|
Chris@16
|
92 <
|
Chris@16
|
93 typename StrategyLess, typename StrategyGreater,
|
Chris@16
|
94 std::size_t DimensionCount
|
Chris@16
|
95 >
|
Chris@16
|
96 struct point_loop
|
Chris@16
|
97 <
|
Chris@16
|
98 StrategyLess, StrategyGreater,
|
Chris@16
|
99 DimensionCount, DimensionCount
|
Chris@16
|
100 >
|
Chris@16
|
101 {
|
Chris@16
|
102 template <typename Box, typename Point>
|
Chris@16
|
103 static inline void apply(Box&, Point const&) {}
|
Chris@16
|
104 };
|
Chris@16
|
105
|
Chris@16
|
106
|
Chris@16
|
107 template
|
Chris@16
|
108 <
|
Chris@16
|
109 typename StrategyLess, typename StrategyGreater,
|
Chris@16
|
110 std::size_t Index,
|
Chris@16
|
111 std::size_t Dimension, std::size_t DimensionCount
|
Chris@16
|
112 >
|
Chris@16
|
113 struct indexed_loop
|
Chris@16
|
114 {
|
Chris@16
|
115 template <typename Box, typename Geometry>
|
Chris@16
|
116 static inline void apply(Box& box, Geometry const& source)
|
Chris@16
|
117 {
|
Chris@16
|
118 typedef typename strategy::compare::detail::select_strategy
|
Chris@16
|
119 <
|
Chris@16
|
120 StrategyLess, 1, Box, Dimension
|
Chris@16
|
121 >::type less_type;
|
Chris@16
|
122
|
Chris@16
|
123 typedef typename strategy::compare::detail::select_strategy
|
Chris@16
|
124 <
|
Chris@16
|
125 StrategyGreater, -1, Box, Dimension
|
Chris@16
|
126 >::type greater_type;
|
Chris@16
|
127
|
Chris@16
|
128 typedef typename select_coordinate_type
|
Chris@16
|
129 <
|
Chris@16
|
130 Box,
|
Chris@16
|
131 Geometry
|
Chris@16
|
132 >::type coordinate_type;
|
Chris@16
|
133
|
Chris@16
|
134 less_type less;
|
Chris@16
|
135 greater_type greater;
|
Chris@16
|
136
|
Chris@16
|
137 coordinate_type const coord = get<Index, Dimension>(source);
|
Chris@16
|
138
|
Chris@16
|
139 if (less(coord, get<min_corner, Dimension>(box)))
|
Chris@16
|
140 {
|
Chris@16
|
141 set<min_corner, Dimension>(box, coord);
|
Chris@16
|
142 }
|
Chris@16
|
143
|
Chris@16
|
144 if (greater(coord, get<max_corner, Dimension>(box)))
|
Chris@16
|
145 {
|
Chris@16
|
146 set<max_corner, Dimension>(box, coord);
|
Chris@16
|
147 }
|
Chris@16
|
148
|
Chris@16
|
149 indexed_loop
|
Chris@16
|
150 <
|
Chris@16
|
151 StrategyLess, StrategyGreater,
|
Chris@16
|
152 Index, Dimension + 1, DimensionCount
|
Chris@16
|
153 >::apply(box, source);
|
Chris@16
|
154 }
|
Chris@16
|
155 };
|
Chris@16
|
156
|
Chris@16
|
157
|
Chris@16
|
158 template
|
Chris@16
|
159 <
|
Chris@16
|
160 typename StrategyLess, typename StrategyGreater,
|
Chris@16
|
161 std::size_t Index, std::size_t DimensionCount
|
Chris@16
|
162 >
|
Chris@16
|
163 struct indexed_loop
|
Chris@16
|
164 <
|
Chris@16
|
165 StrategyLess, StrategyGreater,
|
Chris@16
|
166 Index, DimensionCount, DimensionCount
|
Chris@16
|
167 >
|
Chris@16
|
168 {
|
Chris@16
|
169 template <typename Box, typename Geometry>
|
Chris@16
|
170 static inline void apply(Box&, Geometry const&) {}
|
Chris@16
|
171 };
|
Chris@16
|
172
|
Chris@16
|
173
|
Chris@16
|
174
|
Chris@16
|
175 // Changes a box such that the other box is also contained by the box
|
Chris@16
|
176 template
|
Chris@16
|
177 <
|
Chris@16
|
178 typename StrategyLess, typename StrategyGreater
|
Chris@16
|
179 >
|
Chris@16
|
180 struct expand_indexed
|
Chris@16
|
181 {
|
Chris@16
|
182 template <typename Box, typename Geometry>
|
Chris@16
|
183 static inline void apply(Box& box, Geometry const& geometry)
|
Chris@16
|
184 {
|
Chris@16
|
185 indexed_loop
|
Chris@16
|
186 <
|
Chris@16
|
187 StrategyLess, StrategyGreater,
|
Chris@16
|
188 0, 0, dimension<Geometry>::type::value
|
Chris@16
|
189 >::apply(box, geometry);
|
Chris@16
|
190
|
Chris@16
|
191 indexed_loop
|
Chris@16
|
192 <
|
Chris@16
|
193 StrategyLess, StrategyGreater,
|
Chris@16
|
194 1, 0, dimension<Geometry>::type::value
|
Chris@16
|
195 >::apply(box, geometry);
|
Chris@16
|
196 }
|
Chris@16
|
197 };
|
Chris@16
|
198
|
Chris@16
|
199 }} // namespace detail::expand
|
Chris@16
|
200 #endif // DOXYGEN_NO_DETAIL
|
Chris@16
|
201
|
Chris@16
|
202 #ifndef DOXYGEN_NO_DISPATCH
|
Chris@16
|
203 namespace dispatch
|
Chris@16
|
204 {
|
Chris@16
|
205
|
Chris@16
|
206 template
|
Chris@16
|
207 <
|
Chris@16
|
208 typename GeometryOut, typename Geometry,
|
Chris@16
|
209 typename StrategyLess = strategy::compare::default_strategy,
|
Chris@16
|
210 typename StrategyGreater = strategy::compare::default_strategy,
|
Chris@16
|
211 typename TagOut = typename tag<GeometryOut>::type,
|
Chris@16
|
212 typename Tag = typename tag<Geometry>::type
|
Chris@16
|
213 >
|
Chris@16
|
214 struct expand: not_implemented<TagOut, Tag>
|
Chris@16
|
215 {};
|
Chris@16
|
216
|
Chris@16
|
217
|
Chris@16
|
218 // Box + point -> new box containing also point
|
Chris@16
|
219 template
|
Chris@16
|
220 <
|
Chris@16
|
221 typename BoxOut, typename Point,
|
Chris@16
|
222 typename StrategyLess, typename StrategyGreater
|
Chris@16
|
223 >
|
Chris@16
|
224 struct expand<BoxOut, Point, StrategyLess, StrategyGreater, box_tag, point_tag>
|
Chris@16
|
225 : detail::expand::point_loop
|
Chris@16
|
226 <
|
Chris@16
|
227 StrategyLess, StrategyGreater,
|
Chris@16
|
228 0, dimension<Point>::type::value
|
Chris@16
|
229 >
|
Chris@16
|
230 {};
|
Chris@16
|
231
|
Chris@16
|
232
|
Chris@16
|
233 // Box + box -> new box containing two input boxes
|
Chris@16
|
234 template
|
Chris@16
|
235 <
|
Chris@16
|
236 typename BoxOut, typename BoxIn,
|
Chris@16
|
237 typename StrategyLess, typename StrategyGreater
|
Chris@16
|
238 >
|
Chris@16
|
239 struct expand<BoxOut, BoxIn, StrategyLess, StrategyGreater, box_tag, box_tag>
|
Chris@16
|
240 : detail::expand::expand_indexed<StrategyLess, StrategyGreater>
|
Chris@16
|
241 {};
|
Chris@16
|
242
|
Chris@16
|
243 template
|
Chris@16
|
244 <
|
Chris@16
|
245 typename Box, typename Segment,
|
Chris@16
|
246 typename StrategyLess, typename StrategyGreater
|
Chris@16
|
247 >
|
Chris@16
|
248 struct expand<Box, Segment, StrategyLess, StrategyGreater, box_tag, segment_tag>
|
Chris@16
|
249 : detail::expand::expand_indexed<StrategyLess, StrategyGreater>
|
Chris@16
|
250 {};
|
Chris@16
|
251
|
Chris@16
|
252
|
Chris@16
|
253 } // namespace dispatch
|
Chris@16
|
254 #endif // DOXYGEN_NO_DISPATCH
|
Chris@16
|
255
|
Chris@16
|
256
|
Chris@101
|
257 namespace resolve_variant {
|
Chris@101
|
258
|
Chris@101
|
259 template <typename Geometry>
|
Chris@101
|
260 struct expand
|
Chris@101
|
261 {
|
Chris@101
|
262 template <typename Box>
|
Chris@101
|
263 static inline void apply(Box& box, Geometry const& geometry)
|
Chris@101
|
264 {
|
Chris@101
|
265 concept::check<Box>();
|
Chris@101
|
266 concept::check<Geometry const>();
|
Chris@101
|
267 concept::check_concepts_and_equal_dimensions<Box, Geometry const>();
|
Chris@101
|
268
|
Chris@101
|
269 dispatch::expand<Box, Geometry>::apply(box, geometry);
|
Chris@101
|
270 }
|
Chris@101
|
271 };
|
Chris@101
|
272
|
Chris@101
|
273 template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
Chris@101
|
274 struct expand<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
Chris@101
|
275 {
|
Chris@101
|
276 template <typename Box>
|
Chris@101
|
277 struct visitor: boost::static_visitor<void>
|
Chris@101
|
278 {
|
Chris@101
|
279 Box& m_box;
|
Chris@101
|
280
|
Chris@101
|
281 visitor(Box& box) : m_box(box) {}
|
Chris@101
|
282
|
Chris@101
|
283 template <typename Geometry>
|
Chris@101
|
284 void operator()(Geometry const& geometry) const
|
Chris@101
|
285 {
|
Chris@101
|
286 return expand<Geometry>::apply(m_box, geometry);
|
Chris@101
|
287 }
|
Chris@101
|
288 };
|
Chris@101
|
289
|
Chris@101
|
290 template <class Box>
|
Chris@101
|
291 static inline void
|
Chris@101
|
292 apply(Box& box,
|
Chris@101
|
293 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry)
|
Chris@101
|
294 {
|
Chris@101
|
295 return boost::apply_visitor(visitor<Box>(box), geometry);
|
Chris@101
|
296 }
|
Chris@101
|
297 };
|
Chris@101
|
298
|
Chris@101
|
299 } // namespace resolve_variant
|
Chris@101
|
300
|
Chris@101
|
301
|
Chris@16
|
302 /***
|
Chris@16
|
303 *!
|
Chris@16
|
304 \brief Expands a box using the extend (envelope) of another geometry (box, point)
|
Chris@16
|
305 \ingroup expand
|
Chris@16
|
306 \tparam Box type of the box
|
Chris@16
|
307 \tparam Geometry of second geometry, to be expanded with the box
|
Chris@16
|
308 \param box box to expand another geometry with, might be changed
|
Chris@16
|
309 \param geometry other geometry
|
Chris@16
|
310 \param strategy_less
|
Chris@16
|
311 \param strategy_greater
|
Chris@16
|
312 \note Strategy is currently ignored
|
Chris@16
|
313 *
|
Chris@16
|
314 template
|
Chris@16
|
315 <
|
Chris@16
|
316 typename Box, typename Geometry,
|
Chris@16
|
317 typename StrategyLess, typename StrategyGreater
|
Chris@16
|
318 >
|
Chris@16
|
319 inline void expand(Box& box, Geometry const& geometry,
|
Chris@16
|
320 StrategyLess const& strategy_less,
|
Chris@16
|
321 StrategyGreater const& strategy_greater)
|
Chris@16
|
322 {
|
Chris@16
|
323 concept::check_concepts_and_equal_dimensions<Box, Geometry const>();
|
Chris@16
|
324
|
Chris@16
|
325 dispatch::expand<Box, Geometry>::apply(box, geometry);
|
Chris@16
|
326 }
|
Chris@16
|
327 ***/
|
Chris@16
|
328
|
Chris@16
|
329
|
Chris@16
|
330 /*!
|
Chris@16
|
331 \brief Expands a box using the bounding box (envelope) of another geometry (box, point)
|
Chris@16
|
332 \ingroup expand
|
Chris@16
|
333 \tparam Box type of the box
|
Chris@16
|
334 \tparam Geometry \tparam_geometry
|
Chris@16
|
335 \param box box to be expanded using another geometry, mutable
|
Chris@16
|
336 \param geometry \param_geometry geometry which envelope (bounding box) will be added to the box
|
Chris@16
|
337
|
Chris@16
|
338 \qbk{[include reference/algorithms/expand.qbk]}
|
Chris@16
|
339 */
|
Chris@16
|
340 template <typename Box, typename Geometry>
|
Chris@16
|
341 inline void expand(Box& box, Geometry const& geometry)
|
Chris@16
|
342 {
|
Chris@101
|
343 resolve_variant::expand<Geometry>::apply(box, geometry);
|
Chris@16
|
344 }
|
Chris@16
|
345
|
Chris@16
|
346 }} // namespace boost::geometry
|
Chris@16
|
347
|
Chris@16
|
348 #endif // BOOST_GEOMETRY_ALGORITHMS_EXPAND_HPP
|