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
47namespace boost { namespace geometry
48{
49
50#ifndef DOXYGEN_NO_DETAIL
51namespace detail { namespace for_each
52{
53
54
55struct 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
65struct 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
76struct 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
97template <closure_selector Closure>
98struct 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
123template <>
124struct 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
145struct 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
158struct 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
177struct 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.
198template <typename Policy>
199struct 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
217namespace dispatch
218{
219
220template
221<
222 typename Geometry,
223 typename Tag = typename tag_cast<typename tag<Geometry>::type, multi_tag>::type
224>
225struct for_each_point: not_implemented<Tag>
226{};
227
228
229template <typename Point>
230struct for_each_point<Point, point_tag>
231 : detail::for_each::fe_point_per_point
232{};
233
234
235template <typename Linestring>
236struct for_each_point<Linestring, linestring_tag>
237 : detail::for_each::fe_range_per_point
238{};
239
240
241template <typename Ring>
242struct for_each_point<Ring, ring_tag>
243 : detail::for_each::fe_range_per_point
244{};
245
246
247template <typename Polygon>
248struct for_each_point<Polygon, polygon_tag>
249 : detail::for_each::fe_polygon_per_point
250{};
251
252
253template
254<
255 typename Geometry,
256 typename Tag = typename tag_cast<typename tag<Geometry>::type, multi_tag>::type
257>
258struct for_each_segment: not_implemented<Tag>
259{};
260
261template <typename Point>
262struct for_each_segment<Point, point_tag>
263 : detail::for_each::fe_point_per_segment
264{};
265
266
267template <typename Linestring>
268struct for_each_segment<Linestring, linestring_tag>
269 : detail::for_each::fe_range_per_segment
270{};
271
272
273template <typename Ring>
274struct for_each_segment<Ring, ring_tag>
275 : detail::for_each::fe_range_per_segment
276{};
277
278
279template <typename Polygon>
280struct for_each_segment<Polygon, polygon_tag>
281 : detail::for_each::fe_polygon_per_segment
282{};
283
284
285template <typename MultiGeometry>
286struct 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
302template <typename MultiGeometry>
303struct 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*/
337template<typename Geometry, typename Functor>
338inline 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*/
360template<typename Geometry, typename Functor>
361inline 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

source code of boost/boost/geometry/algorithms/for_each.hpp