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