Chris@16
|
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
|
Chris@16
|
2
|
Chris@101
|
3 // Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
Chris@101
|
4 // Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
Chris@101
|
5 // Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
Chris@101
|
6 // Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
|
Chris@101
|
7
|
Chris@101
|
8 // This file was modified by Oracle on 2014.
|
Chris@101
|
9 // Modifications copyright (c) 2014, Oracle and/or its affiliates.
|
Chris@101
|
10
|
Chris@101
|
11 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
Chris@16
|
12
|
Chris@16
|
13 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
Chris@16
|
14 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
Chris@16
|
15
|
Chris@16
|
16 // Use, modification and distribution is subject to the Boost Software License,
|
Chris@16
|
17 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
18 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
19
|
Chris@16
|
20 #ifndef BOOST_GEOMETRY_ALGORITHMS_FOR_EACH_HPP
|
Chris@16
|
21 #define BOOST_GEOMETRY_ALGORITHMS_FOR_EACH_HPP
|
Chris@16
|
22
|
Chris@16
|
23
|
Chris@16
|
24 #include <algorithm>
|
Chris@16
|
25
|
Chris@16
|
26 #include <boost/range.hpp>
|
Chris@16
|
27 #include <boost/type_traits/is_const.hpp>
|
Chris@101
|
28 #include <boost/type_traits/remove_reference.hpp>
|
Chris@16
|
29
|
Chris@101
|
30 #include <boost/geometry/algorithms/detail/interior_iterator.hpp>
|
Chris@16
|
31 #include <boost/geometry/algorithms/not_implemented.hpp>
|
Chris@101
|
32 #include <boost/geometry/core/closure.hpp>
|
Chris@16
|
33 #include <boost/geometry/core/exterior_ring.hpp>
|
Chris@16
|
34 #include <boost/geometry/core/interior_rings.hpp>
|
Chris@101
|
35 #include <boost/geometry/core/point_type.hpp>
|
Chris@16
|
36 #include <boost/geometry/core/tag_cast.hpp>
|
Chris@101
|
37 #include <boost/geometry/core/tags.hpp>
|
Chris@16
|
38
|
Chris@16
|
39 #include <boost/geometry/geometries/concepts/check.hpp>
|
Chris@16
|
40
|
Chris@16
|
41 #include <boost/geometry/geometries/segment.hpp>
|
Chris@16
|
42
|
Chris@16
|
43 #include <boost/geometry/util/add_const_if_c.hpp>
|
Chris@101
|
44 #include <boost/geometry/util/range.hpp>
|
Chris@16
|
45
|
Chris@16
|
46
|
Chris@16
|
47 namespace boost { namespace geometry
|
Chris@16
|
48 {
|
Chris@16
|
49
|
Chris@16
|
50 #ifndef DOXYGEN_NO_DETAIL
|
Chris@16
|
51 namespace detail { namespace for_each
|
Chris@16
|
52 {
|
Chris@16
|
53
|
Chris@16
|
54
|
Chris@16
|
55 struct fe_point_per_point
|
Chris@16
|
56 {
|
Chris@16
|
57 template <typename Point, typename Functor>
|
Chris@16
|
58 static inline void apply(Point& point, Functor& f)
|
Chris@16
|
59 {
|
Chris@16
|
60 f(point);
|
Chris@16
|
61 }
|
Chris@16
|
62 };
|
Chris@16
|
63
|
Chris@16
|
64
|
Chris@16
|
65 struct fe_point_per_segment
|
Chris@16
|
66 {
|
Chris@16
|
67 template <typename Point, typename Functor>
|
Chris@101
|
68 static inline void apply(Point& , Functor& /*f*/)
|
Chris@16
|
69 {
|
Chris@16
|
70 // TODO: if non-const, we should extract the points from the segment
|
Chris@16
|
71 // and call the functor on those two points
|
Chris@16
|
72 }
|
Chris@16
|
73 };
|
Chris@16
|
74
|
Chris@16
|
75
|
Chris@16
|
76 struct fe_range_per_point
|
Chris@16
|
77 {
|
Chris@16
|
78 template <typename Range, typename Functor>
|
Chris@16
|
79 static inline void apply(Range& range, Functor& f)
|
Chris@16
|
80 {
|
Chris@16
|
81 // The previous implementation called the std library:
|
Chris@16
|
82 // return (std::for_each(boost::begin(range), boost::end(range), f));
|
Chris@16
|
83 // But that is not accepted for capturing lambda's.
|
Chris@16
|
84 // It needs to do it like that to return the state of Functor f (f is passed by value in std::for_each).
|
Chris@16
|
85
|
Chris@16
|
86 // So we now loop manually.
|
Chris@16
|
87
|
Chris@101
|
88 for (typename boost::range_iterator<Range>::type
|
Chris@101
|
89 it = boost::begin(range); it != boost::end(range); ++it)
|
Chris@16
|
90 {
|
Chris@16
|
91 f(*it);
|
Chris@16
|
92 }
|
Chris@16
|
93 }
|
Chris@16
|
94 };
|
Chris@16
|
95
|
Chris@16
|
96
|
Chris@101
|
97 template <closure_selector Closure>
|
Chris@101
|
98 struct fe_range_per_segment_with_closure
|
Chris@16
|
99 {
|
Chris@16
|
100 template <typename Range, typename Functor>
|
Chris@16
|
101 static inline void apply(Range& range, Functor& f)
|
Chris@16
|
102 {
|
Chris@16
|
103 typedef typename add_const_if_c
|
Chris@16
|
104 <
|
Chris@16
|
105 is_const<Range>::value,
|
Chris@16
|
106 typename point_type<Range>::type
|
Chris@16
|
107 >::type point_type;
|
Chris@16
|
108
|
Chris@101
|
109 typedef typename boost::range_iterator<Range>::type iterator_type;
|
Chris@101
|
110
|
Chris@101
|
111 iterator_type it = boost::begin(range);
|
Chris@101
|
112 iterator_type previous = it++;
|
Chris@16
|
113 while(it != boost::end(range))
|
Chris@16
|
114 {
|
Chris@16
|
115 model::referring_segment<point_type> s(*previous, *it);
|
Chris@16
|
116 f(s);
|
Chris@16
|
117 previous = it++;
|
Chris@16
|
118 }
|
Chris@16
|
119 }
|
Chris@16
|
120 };
|
Chris@16
|
121
|
Chris@16
|
122
|
Chris@101
|
123 template <>
|
Chris@101
|
124 struct fe_range_per_segment_with_closure<open>
|
Chris@101
|
125 {
|
Chris@101
|
126 template <typename Range, typename Functor>
|
Chris@101
|
127 static inline void apply(Range& range, Functor& f)
|
Chris@101
|
128 {
|
Chris@101
|
129 fe_range_per_segment_with_closure<closed>::apply(range, f);
|
Chris@101
|
130
|
Chris@101
|
131 model::referring_segment
|
Chris@101
|
132 <
|
Chris@101
|
133 typename add_const_if_c
|
Chris@101
|
134 <
|
Chris@101
|
135 is_const<Range>::value,
|
Chris@101
|
136 typename point_type<Range>::type
|
Chris@101
|
137 >::type
|
Chris@101
|
138 > s(range::back(range), range::front(range));
|
Chris@101
|
139
|
Chris@101
|
140 f(s);
|
Chris@101
|
141 }
|
Chris@101
|
142 };
|
Chris@101
|
143
|
Chris@101
|
144
|
Chris@101
|
145 struct fe_range_per_segment
|
Chris@101
|
146 {
|
Chris@101
|
147 template <typename Range, typename Functor>
|
Chris@101
|
148 static inline void apply(Range& range, Functor& f)
|
Chris@101
|
149 {
|
Chris@101
|
150 fe_range_per_segment_with_closure
|
Chris@101
|
151 <
|
Chris@101
|
152 closure<Range>::value
|
Chris@101
|
153 >::apply(range, f);
|
Chris@101
|
154 }
|
Chris@101
|
155 };
|
Chris@101
|
156
|
Chris@101
|
157
|
Chris@16
|
158 struct fe_polygon_per_point
|
Chris@16
|
159 {
|
Chris@16
|
160 template <typename Polygon, typename Functor>
|
Chris@16
|
161 static inline void apply(Polygon& poly, Functor& f)
|
Chris@16
|
162 {
|
Chris@16
|
163 fe_range_per_point::apply(exterior_ring(poly), f);
|
Chris@16
|
164
|
Chris@101
|
165 typename interior_return_type<Polygon>::type
|
Chris@101
|
166 rings = interior_rings(poly);
|
Chris@101
|
167
|
Chris@101
|
168 for (typename detail::interior_iterator<Polygon>::type
|
Chris@101
|
169 it = boost::begin(rings); it != boost::end(rings); ++it)
|
Chris@16
|
170 {
|
Chris@16
|
171 fe_range_per_point::apply(*it, f);
|
Chris@16
|
172 }
|
Chris@16
|
173 }
|
Chris@16
|
174
|
Chris@16
|
175 };
|
Chris@16
|
176
|
Chris@16
|
177 struct fe_polygon_per_segment
|
Chris@16
|
178 {
|
Chris@16
|
179 template <typename Polygon, typename Functor>
|
Chris@16
|
180 static inline void apply(Polygon& poly, Functor& f)
|
Chris@16
|
181 {
|
Chris@16
|
182 fe_range_per_segment::apply(exterior_ring(poly), f);
|
Chris@16
|
183
|
Chris@101
|
184 typename interior_return_type<Polygon>::type
|
Chris@101
|
185 rings = interior_rings(poly);
|
Chris@101
|
186
|
Chris@101
|
187 for (typename detail::interior_iterator<Polygon>::type
|
Chris@101
|
188 it = boost::begin(rings); it != boost::end(rings); ++it)
|
Chris@16
|
189 {
|
Chris@16
|
190 fe_range_per_segment::apply(*it, f);
|
Chris@16
|
191 }
|
Chris@16
|
192 }
|
Chris@16
|
193
|
Chris@16
|
194 };
|
Chris@16
|
195
|
Chris@101
|
196 // Implementation of multi, for both point and segment,
|
Chris@101
|
197 // just calling the single version.
|
Chris@101
|
198 template <typename Policy>
|
Chris@101
|
199 struct for_each_multi
|
Chris@101
|
200 {
|
Chris@101
|
201 template <typename MultiGeometry, typename Functor>
|
Chris@101
|
202 static inline void apply(MultiGeometry& multi, Functor& f)
|
Chris@101
|
203 {
|
Chris@101
|
204 for (typename boost::range_iterator<MultiGeometry>::type
|
Chris@101
|
205 it = boost::begin(multi); it != boost::end(multi); ++it)
|
Chris@101
|
206 {
|
Chris@101
|
207 Policy::apply(*it, f);
|
Chris@101
|
208 }
|
Chris@101
|
209 }
|
Chris@101
|
210 };
|
Chris@16
|
211
|
Chris@16
|
212 }} // namespace detail::for_each
|
Chris@16
|
213 #endif // DOXYGEN_NO_DETAIL
|
Chris@16
|
214
|
Chris@16
|
215
|
Chris@16
|
216 #ifndef DOXYGEN_NO_DISPATCH
|
Chris@16
|
217 namespace dispatch
|
Chris@16
|
218 {
|
Chris@16
|
219
|
Chris@16
|
220 template
|
Chris@16
|
221 <
|
Chris@16
|
222 typename Geometry,
|
Chris@16
|
223 typename Tag = typename tag_cast<typename tag<Geometry>::type, multi_tag>::type
|
Chris@16
|
224 >
|
Chris@16
|
225 struct for_each_point: not_implemented<Tag>
|
Chris@16
|
226 {};
|
Chris@16
|
227
|
Chris@16
|
228
|
Chris@16
|
229 template <typename Point>
|
Chris@16
|
230 struct for_each_point<Point, point_tag>
|
Chris@16
|
231 : detail::for_each::fe_point_per_point
|
Chris@16
|
232 {};
|
Chris@16
|
233
|
Chris@16
|
234
|
Chris@16
|
235 template <typename Linestring>
|
Chris@16
|
236 struct for_each_point<Linestring, linestring_tag>
|
Chris@16
|
237 : detail::for_each::fe_range_per_point
|
Chris@16
|
238 {};
|
Chris@16
|
239
|
Chris@16
|
240
|
Chris@16
|
241 template <typename Ring>
|
Chris@16
|
242 struct for_each_point<Ring, ring_tag>
|
Chris@16
|
243 : detail::for_each::fe_range_per_point
|
Chris@16
|
244 {};
|
Chris@16
|
245
|
Chris@16
|
246
|
Chris@16
|
247 template <typename Polygon>
|
Chris@16
|
248 struct for_each_point<Polygon, polygon_tag>
|
Chris@16
|
249 : detail::for_each::fe_polygon_per_point
|
Chris@16
|
250 {};
|
Chris@16
|
251
|
Chris@16
|
252
|
Chris@16
|
253 template
|
Chris@16
|
254 <
|
Chris@16
|
255 typename Geometry,
|
Chris@16
|
256 typename Tag = typename tag_cast<typename tag<Geometry>::type, multi_tag>::type
|
Chris@16
|
257 >
|
Chris@16
|
258 struct for_each_segment: not_implemented<Tag>
|
Chris@16
|
259 {};
|
Chris@16
|
260
|
Chris@16
|
261 template <typename Point>
|
Chris@16
|
262 struct for_each_segment<Point, point_tag>
|
Chris@16
|
263 : detail::for_each::fe_point_per_segment
|
Chris@16
|
264 {};
|
Chris@16
|
265
|
Chris@16
|
266
|
Chris@16
|
267 template <typename Linestring>
|
Chris@16
|
268 struct for_each_segment<Linestring, linestring_tag>
|
Chris@16
|
269 : detail::for_each::fe_range_per_segment
|
Chris@16
|
270 {};
|
Chris@16
|
271
|
Chris@16
|
272
|
Chris@16
|
273 template <typename Ring>
|
Chris@16
|
274 struct for_each_segment<Ring, ring_tag>
|
Chris@16
|
275 : detail::for_each::fe_range_per_segment
|
Chris@16
|
276 {};
|
Chris@16
|
277
|
Chris@16
|
278
|
Chris@16
|
279 template <typename Polygon>
|
Chris@16
|
280 struct for_each_segment<Polygon, polygon_tag>
|
Chris@16
|
281 : detail::for_each::fe_polygon_per_segment
|
Chris@16
|
282 {};
|
Chris@16
|
283
|
Chris@16
|
284
|
Chris@101
|
285 template <typename MultiGeometry>
|
Chris@101
|
286 struct for_each_point<MultiGeometry, multi_tag>
|
Chris@101
|
287 : detail::for_each::for_each_multi
|
Chris@101
|
288 <
|
Chris@101
|
289 // Specify the dispatch of the single-version as policy
|
Chris@101
|
290 for_each_point
|
Chris@101
|
291 <
|
Chris@101
|
292 typename add_const_if_c
|
Chris@101
|
293 <
|
Chris@101
|
294 is_const<MultiGeometry>::value,
|
Chris@101
|
295 typename boost::range_value<MultiGeometry>::type
|
Chris@101
|
296 >::type
|
Chris@101
|
297 >
|
Chris@101
|
298 >
|
Chris@101
|
299 {};
|
Chris@101
|
300
|
Chris@101
|
301
|
Chris@101
|
302 template <typename MultiGeometry>
|
Chris@101
|
303 struct for_each_segment<MultiGeometry, multi_tag>
|
Chris@101
|
304 : detail::for_each::for_each_multi
|
Chris@101
|
305 <
|
Chris@101
|
306 // Specify the dispatch of the single-version as policy
|
Chris@101
|
307 for_each_segment
|
Chris@101
|
308 <
|
Chris@101
|
309 typename add_const_if_c
|
Chris@101
|
310 <
|
Chris@101
|
311 is_const<MultiGeometry>::value,
|
Chris@101
|
312 typename boost::range_value<MultiGeometry>::type
|
Chris@101
|
313 >::type
|
Chris@101
|
314 >
|
Chris@101
|
315 >
|
Chris@101
|
316 {};
|
Chris@101
|
317
|
Chris@101
|
318
|
Chris@16
|
319 } // namespace dispatch
|
Chris@16
|
320 #endif // DOXYGEN_NO_DISPATCH
|
Chris@16
|
321
|
Chris@16
|
322
|
Chris@16
|
323 /*!
|
Chris@16
|
324 \brief \brf_for_each{point}
|
Chris@16
|
325 \details \det_for_each{point}
|
Chris@16
|
326 \ingroup for_each
|
Chris@16
|
327 \param geometry \param_geometry
|
Chris@16
|
328 \param f \par_for_each_f{point}
|
Chris@16
|
329 \tparam Geometry \tparam_geometry
|
Chris@16
|
330 \tparam Functor \tparam_functor
|
Chris@16
|
331
|
Chris@16
|
332 \qbk{[include reference/algorithms/for_each_point.qbk]}
|
Chris@16
|
333 \qbk{[heading Example]}
|
Chris@16
|
334 \qbk{[for_each_point] [for_each_point_output]}
|
Chris@16
|
335 \qbk{[for_each_point_const] [for_each_point_const_output]}
|
Chris@16
|
336 */
|
Chris@16
|
337 template<typename Geometry, typename Functor>
|
Chris@16
|
338 inline Functor for_each_point(Geometry& geometry, Functor f)
|
Chris@16
|
339 {
|
Chris@16
|
340 concept::check<Geometry>();
|
Chris@16
|
341
|
Chris@16
|
342 dispatch::for_each_point<Geometry>::apply(geometry, f);
|
Chris@16
|
343 return f;
|
Chris@16
|
344 }
|
Chris@16
|
345
|
Chris@16
|
346
|
Chris@16
|
347 /*!
|
Chris@16
|
348 \brief \brf_for_each{segment}
|
Chris@16
|
349 \details \det_for_each{segment}
|
Chris@16
|
350 \ingroup for_each
|
Chris@16
|
351 \param geometry \param_geometry
|
Chris@16
|
352 \param f \par_for_each_f{segment}
|
Chris@16
|
353 \tparam Geometry \tparam_geometry
|
Chris@16
|
354 \tparam Functor \tparam_functor
|
Chris@16
|
355
|
Chris@16
|
356 \qbk{[include reference/algorithms/for_each_segment.qbk]}
|
Chris@16
|
357 \qbk{[heading Example]}
|
Chris@16
|
358 \qbk{[for_each_segment_const] [for_each_segment_const_output]}
|
Chris@16
|
359 */
|
Chris@16
|
360 template<typename Geometry, typename Functor>
|
Chris@16
|
361 inline Functor for_each_segment(Geometry& geometry, Functor f)
|
Chris@16
|
362 {
|
Chris@16
|
363 concept::check<Geometry>();
|
Chris@16
|
364
|
Chris@16
|
365 dispatch::for_each_segment<Geometry>::apply(geometry, f);
|
Chris@16
|
366 return f;
|
Chris@16
|
367 }
|
Chris@16
|
368
|
Chris@16
|
369
|
Chris@16
|
370 }} // namespace boost::geometry
|
Chris@16
|
371
|
Chris@16
|
372
|
Chris@16
|
373 #endif // BOOST_GEOMETRY_ALGORITHMS_FOR_EACH_HPP
|