1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 
3 // Copyright (c) 2014, Oracle and/or its affiliates.
4 
5 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
6 
7 // Licensed under the Boost Software License version 1.0.
8 // http://www.boost.org/users/license.html
9 
10 #ifndef BOOST_GEOMETRY_ITERATORS_POINT_ITERATOR_HPP
11 #define BOOST_GEOMETRY_ITERATORS_POINT_ITERATOR_HPP
12 
13 #include <boost/iterator/iterator_adaptor.hpp>
14 #include <boost/mpl/assert.hpp>
15 #include <boost/type_traits/is_convertible.hpp>
16 #include <boost/range.hpp>
17 
18 #include <boost/geometry/core/exterior_ring.hpp>
19 #include <boost/geometry/core/interior_rings.hpp>
20 #include <boost/geometry/core/tags.hpp>
21 
22 #include <boost/geometry/iterators/dispatch/point_iterator.hpp>
23 #include <boost/geometry/iterators/detail/point_iterator/iterator_type.hpp>
24 
25 
26 namespace boost { namespace geometry
27 {
28 
29 
30 #ifndef DOXYGEN_NO_DISPATCH
31 namespace dispatch
32 {
33 
34 
35 // specializations for points_begin
36 
37 
38 template <typename Linestring>
39 struct points_begin<Linestring, linestring_tag>
40 {
41     static inline typename detail::point_iterator::iterator_type
42         <
43             Linestring
44         >::type
applyboost::geometry::dispatch::points_begin45     apply(Linestring& linestring)
46     {
47         return boost::begin(linestring);
48     }
49 };
50 
51 
52 template <typename Ring>
53 struct points_begin<Ring, ring_tag>
54 {
55     static inline typename detail::point_iterator::iterator_type<Ring>::type
applyboost::geometry::dispatch::points_begin56     apply(Ring& ring)
57     {
58         return boost::begin(ring);
59     }
60 };
61 
62 
63 template <typename Polygon>
64 struct points_begin<Polygon, polygon_tag>
65 {
66     typedef typename detail::point_iterator::iterator_type
67         <
68             Polygon
69         >::type return_type;
70 
applyboost::geometry::dispatch::points_begin71     static inline return_type apply(Polygon& polygon)
72     {
73         typedef typename return_type::second_iterator_type flatten_iterator;
74 
75         return return_type
76             (boost::begin(geometry::exterior_ring(polygon)),
77              boost::end(geometry::exterior_ring(polygon)),
78              flatten_iterator(boost::begin(geometry::interior_rings(polygon)),
79                               boost::end(geometry::interior_rings(polygon))
80                               ),
81              flatten_iterator(boost::begin(geometry::interior_rings(polygon)),
82                               boost::end(geometry::interior_rings(polygon))
83                               )
84              );
85     }
86 };
87 
88 
89 template <typename MultiPoint>
90 struct points_begin<MultiPoint, multi_point_tag>
91 {
92     static inline typename detail::point_iterator::iterator_type
93         <
94             MultiPoint
95         >::type
applyboost::geometry::dispatch::points_begin96     apply(MultiPoint& multipoint)
97     {
98         return boost::begin(multipoint);
99     }
100 };
101 
102 
103 template <typename MultiLinestring>
104 struct points_begin<MultiLinestring, multi_linestring_tag>
105 {
106     typedef typename detail::point_iterator::iterator_type
107         <
108             MultiLinestring
109         >::type return_type;
110 
applyboost::geometry::dispatch::points_begin111     static inline return_type apply(MultiLinestring& multilinestring)
112     {
113         return return_type(boost::begin(multilinestring),
114                            boost::end(multilinestring));
115     }
116 };
117 
118 
119 template <typename MultiPolygon>
120 struct points_begin<MultiPolygon, multi_polygon_tag>
121 {
122     typedef typename detail::point_iterator::iterator_type
123         <
124             MultiPolygon
125         >::type return_type;
126 
applyboost::geometry::dispatch::points_begin127     static inline return_type apply(MultiPolygon& multipolygon)
128     {
129         return return_type(boost::begin(multipolygon),
130                            boost::end(multipolygon));
131     }
132 };
133 
134 } // namespace dispatch
135 #endif // DOXYGEN_NO_DISPATCH
136 
137 
138 
139 
140 
141 #ifndef DOXYGEN_NO_DISPATCH
142 namespace dispatch
143 {
144 
145 
146 // specializations for points_end
147 
148 
149 template <typename Linestring>
150 struct points_end<Linestring, linestring_tag>
151 {
152     static inline typename detail::point_iterator::iterator_type
153         <
154             Linestring
155         >::type
applyboost::geometry::dispatch::points_end156     apply(Linestring& linestring)
157     {
158         return boost::end(linestring);
159     }
160 };
161 
162 
163 template <typename Ring>
164 struct points_end<Ring, ring_tag>
165 {
166     static inline typename detail::point_iterator::iterator_type<Ring>::type
applyboost::geometry::dispatch::points_end167     apply(Ring& ring)
168     {
169         return boost::end(ring);
170     }
171 };
172 
173 
174 template <typename Polygon>
175 struct points_end<Polygon, polygon_tag>
176 {
177     typedef typename detail::point_iterator::iterator_type
178         <
179             Polygon
180         >::type return_type;
181 
applyboost::geometry::dispatch::points_end182     static inline return_type apply(Polygon& polygon)
183     {
184         typedef typename return_type::second_iterator_type flatten_iterator;
185 
186         return return_type
187             (boost::end(geometry::exterior_ring(polygon)),
188              flatten_iterator(boost::begin(geometry::interior_rings(polygon)),
189                               boost::end(geometry::interior_rings(polygon))
190                               ),
191              flatten_iterator( boost::end(geometry::interior_rings(polygon)) )
192              );
193     }
194 };
195 
196 
197 template <typename MultiPoint>
198 struct points_end<MultiPoint, multi_point_tag>
199 {
200     static inline typename detail::point_iterator::iterator_type
201         <
202             MultiPoint
203         >::type
applyboost::geometry::dispatch::points_end204     apply(MultiPoint& multipoint)
205     {
206         return boost::end(multipoint);
207     }
208 };
209 
210 
211 template <typename MultiLinestring>
212 struct points_end<MultiLinestring, multi_linestring_tag>
213 {
214     typedef typename detail::point_iterator::iterator_type
215         <
216             MultiLinestring
217         >::type return_type;
218 
applyboost::geometry::dispatch::points_end219     static inline return_type apply(MultiLinestring& multilinestring)
220     {
221         return return_type(boost::end(multilinestring));
222     }
223 };
224 
225 
226 template <typename MultiPolygon>
227 struct points_end<MultiPolygon, multi_polygon_tag>
228 {
229     typedef typename detail::point_iterator::iterator_type
230         <
231             MultiPolygon
232         >::type return_type;
233 
applyboost::geometry::dispatch::points_end234     static inline return_type apply(MultiPolygon& multipolygon)
235     {
236         return return_type(boost::end(multipolygon));
237     }
238 };
239 
240 
241 } // namespace dispatch
242 #endif // DOXYGEN_NO_DISPATCH
243 
244 
245 // MK:: need to add doc here
246 template <typename Geometry>
247 class point_iterator
248     : public boost::iterator_adaptor
249         <
250             point_iterator<Geometry>,
251             typename detail::point_iterator::iterator_type<Geometry>::type
252         >
253 {
254 private:
255     template <typename OtherGeometry> friend class point_iterator;
256     template <typename G> friend inline point_iterator<G> points_begin(G&);
257     template <typename G> friend inline point_iterator<G> points_end(G&);
258 
point_iterator(typename point_iterator::base_type const & base_it)259     inline point_iterator(typename point_iterator::base_type const& base_it)
260         : point_iterator::iterator_adaptor_(base_it) {}
261 
262 public:
point_iterator()263     inline point_iterator() {}
264 
265     template <typename OtherGeometry>
point_iterator(point_iterator<OtherGeometry> const & other)266     inline point_iterator(point_iterator<OtherGeometry> const& other)
267         : point_iterator::iterator_adaptor_(other.base())
268     {
269         static const bool is_conv
270             = boost::is_convertible<
271                 typename detail::point_iterator::iterator_type
272                     <
273                         OtherGeometry
274                     >::type,
275                 typename detail::point_iterator::iterator_type
276                     <
277                         Geometry
278                     >::type
279             >::value;
280 
281         BOOST_MPL_ASSERT_MSG((is_conv),
282                              NOT_CONVERTIBLE,
283                              (point_iterator<OtherGeometry>));
284     }
285 };
286 
287 
288 // MK:: need to add doc here
289 template <typename Geometry>
290 inline point_iterator<Geometry>
points_begin(Geometry & geometry)291 points_begin(Geometry& geometry)
292 {
293     return dispatch::points_begin<Geometry>::apply(geometry);
294 }
295 
296 
297 // MK:: need to add doc here
298 template <typename Geometry>
299 inline point_iterator<Geometry>
points_end(Geometry & geometry)300 points_end(Geometry& geometry)
301 {
302     return dispatch::points_end<Geometry>::apply(geometry);
303 }
304 
305 
306 }} // namespace boost::geometry
307 
308 #endif // BOOST_GEOMETRY_ITERATORS_POINT_ITERATOR_HPP
309