Imported Upstream version 1.57.0
[platform/upstream/boost.git] / boost / geometry / algorithms / for_each.hpp
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