Chris@102
|
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
|
Chris@102
|
2
|
Chris@102
|
3 // Copyright (c) 2014, Oracle and/or its affiliates.
|
Chris@102
|
4
|
Chris@102
|
5 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
Chris@102
|
6
|
Chris@102
|
7 // Licensed under the Boost Software License version 1.0.
|
Chris@102
|
8 // http://www.boost.org/users/license.html
|
Chris@102
|
9
|
Chris@102
|
10 #ifndef BOOST_GEOMETRY_ITERATORS_SEGMENT_ITERATOR_HPP
|
Chris@102
|
11 #define BOOST_GEOMETRY_ITERATORS_SEGMENT_ITERATOR_HPP
|
Chris@102
|
12
|
Chris@102
|
13 #include <boost/mpl/assert.hpp>
|
Chris@102
|
14 #include <boost/type_traits/is_convertible.hpp>
|
Chris@102
|
15 #include <boost/range.hpp>
|
Chris@102
|
16
|
Chris@102
|
17 #include <boost/geometry/core/exterior_ring.hpp>
|
Chris@102
|
18 #include <boost/geometry/core/interior_rings.hpp>
|
Chris@102
|
19 #include <boost/geometry/core/tags.hpp>
|
Chris@102
|
20
|
Chris@102
|
21 #include <boost/geometry/iterators/detail/point_iterator/inner_range_type.hpp>
|
Chris@102
|
22 #include <boost/geometry/iterators/detail/segment_iterator/iterator_type.hpp>
|
Chris@102
|
23
|
Chris@102
|
24 #include <boost/geometry/iterators/dispatch/segment_iterator.hpp>
|
Chris@102
|
25
|
Chris@102
|
26
|
Chris@102
|
27 namespace boost { namespace geometry
|
Chris@102
|
28 {
|
Chris@102
|
29
|
Chris@102
|
30
|
Chris@102
|
31 #ifndef DOXYGEN_NO_DISPATCH
|
Chris@102
|
32 namespace dispatch
|
Chris@102
|
33 {
|
Chris@102
|
34
|
Chris@102
|
35
|
Chris@102
|
36 // specializations for segments_begin
|
Chris@102
|
37
|
Chris@102
|
38
|
Chris@102
|
39 template <typename Linestring>
|
Chris@102
|
40 struct segments_begin<Linestring, linestring_tag>
|
Chris@102
|
41 {
|
Chris@102
|
42 typedef typename detail::segment_iterator::iterator_type
|
Chris@102
|
43 <
|
Chris@102
|
44 Linestring
|
Chris@102
|
45 >::type return_type;
|
Chris@102
|
46
|
Chris@102
|
47 static inline return_type apply(Linestring& linestring)
|
Chris@102
|
48 {
|
Chris@102
|
49 return return_type(linestring);
|
Chris@102
|
50 }
|
Chris@102
|
51 };
|
Chris@102
|
52
|
Chris@102
|
53
|
Chris@102
|
54 template <typename Ring>
|
Chris@102
|
55 struct segments_begin<Ring, ring_tag>
|
Chris@102
|
56 {
|
Chris@102
|
57 typedef typename detail::segment_iterator::iterator_type
|
Chris@102
|
58 <
|
Chris@102
|
59 Ring
|
Chris@102
|
60 >::type return_type;
|
Chris@102
|
61
|
Chris@102
|
62 static inline return_type apply(Ring& ring)
|
Chris@102
|
63 {
|
Chris@102
|
64 return return_type(ring);
|
Chris@102
|
65 }
|
Chris@102
|
66 };
|
Chris@102
|
67
|
Chris@102
|
68
|
Chris@102
|
69 template <typename Polygon>
|
Chris@102
|
70 struct segments_begin<Polygon, polygon_tag>
|
Chris@102
|
71 {
|
Chris@102
|
72 typedef typename detail::point_iterator::inner_range_type
|
Chris@102
|
73 <
|
Chris@102
|
74 Polygon
|
Chris@102
|
75 >::type inner_range;
|
Chris@102
|
76
|
Chris@102
|
77 typedef typename detail::segment_iterator::iterator_type
|
Chris@102
|
78 <
|
Chris@102
|
79 Polygon
|
Chris@102
|
80 >::type return_type;
|
Chris@102
|
81
|
Chris@102
|
82 static inline return_type apply(Polygon& polygon)
|
Chris@102
|
83 {
|
Chris@102
|
84 typedef typename return_type::second_iterator_type flatten_iterator;
|
Chris@102
|
85
|
Chris@102
|
86 return return_type
|
Chris@102
|
87 (segments_begin
|
Chris@102
|
88 <
|
Chris@102
|
89 inner_range
|
Chris@102
|
90 >::apply(geometry::exterior_ring(polygon)),
|
Chris@102
|
91 segments_end
|
Chris@102
|
92 <
|
Chris@102
|
93 inner_range
|
Chris@102
|
94 >::apply(geometry::exterior_ring(polygon)),
|
Chris@102
|
95 flatten_iterator(boost::begin(geometry::interior_rings(polygon)),
|
Chris@102
|
96 boost::end(geometry::interior_rings(polygon))
|
Chris@102
|
97 ),
|
Chris@102
|
98 flatten_iterator(boost::begin(geometry::interior_rings(polygon)),
|
Chris@102
|
99 boost::end(geometry::interior_rings(polygon))
|
Chris@102
|
100 )
|
Chris@102
|
101 );
|
Chris@102
|
102 }
|
Chris@102
|
103 };
|
Chris@102
|
104
|
Chris@102
|
105
|
Chris@102
|
106 template <typename MultiLinestring>
|
Chris@102
|
107 struct segments_begin<MultiLinestring, multi_linestring_tag>
|
Chris@102
|
108 {
|
Chris@102
|
109 typedef typename detail::segment_iterator::iterator_type
|
Chris@102
|
110 <
|
Chris@102
|
111 MultiLinestring
|
Chris@102
|
112 >::type return_type;
|
Chris@102
|
113
|
Chris@102
|
114 static inline return_type apply(MultiLinestring& multilinestring)
|
Chris@102
|
115 {
|
Chris@102
|
116 return return_type(boost::begin(multilinestring),
|
Chris@102
|
117 boost::end(multilinestring));
|
Chris@102
|
118 }
|
Chris@102
|
119 };
|
Chris@102
|
120
|
Chris@102
|
121
|
Chris@102
|
122 template <typename MultiPolygon>
|
Chris@102
|
123 struct segments_begin<MultiPolygon, multi_polygon_tag>
|
Chris@102
|
124 {
|
Chris@102
|
125 typedef typename detail::segment_iterator::iterator_type
|
Chris@102
|
126 <
|
Chris@102
|
127 MultiPolygon
|
Chris@102
|
128 >::type return_type;
|
Chris@102
|
129
|
Chris@102
|
130 static inline return_type apply(MultiPolygon& multipolygon)
|
Chris@102
|
131 {
|
Chris@102
|
132 return return_type(boost::begin(multipolygon),
|
Chris@102
|
133 boost::end(multipolygon));
|
Chris@102
|
134 }
|
Chris@102
|
135 };
|
Chris@102
|
136
|
Chris@102
|
137
|
Chris@102
|
138 } // namespace dispatch
|
Chris@102
|
139 #endif // DOXYGEN_NO_DISPATCH
|
Chris@102
|
140
|
Chris@102
|
141
|
Chris@102
|
142
|
Chris@102
|
143
|
Chris@102
|
144
|
Chris@102
|
145 #ifndef DOXYGEN_NO_DISPATCH
|
Chris@102
|
146 namespace dispatch
|
Chris@102
|
147 {
|
Chris@102
|
148
|
Chris@102
|
149
|
Chris@102
|
150 // specializations for segments_end
|
Chris@102
|
151
|
Chris@102
|
152
|
Chris@102
|
153 template <typename Linestring>
|
Chris@102
|
154 struct segments_end<Linestring, linestring_tag>
|
Chris@102
|
155 {
|
Chris@102
|
156 typedef typename detail::segment_iterator::iterator_type
|
Chris@102
|
157 <
|
Chris@102
|
158 Linestring
|
Chris@102
|
159 >::type return_type;
|
Chris@102
|
160
|
Chris@102
|
161 static inline return_type apply(Linestring& linestring)
|
Chris@102
|
162 {
|
Chris@102
|
163 return return_type(linestring, true);
|
Chris@102
|
164 }
|
Chris@102
|
165 };
|
Chris@102
|
166
|
Chris@102
|
167
|
Chris@102
|
168 template <typename Ring>
|
Chris@102
|
169 struct segments_end<Ring, ring_tag>
|
Chris@102
|
170 {
|
Chris@102
|
171 typedef typename detail::segment_iterator::iterator_type
|
Chris@102
|
172 <
|
Chris@102
|
173 Ring
|
Chris@102
|
174 >::type return_type;
|
Chris@102
|
175
|
Chris@102
|
176 static inline return_type apply(Ring& ring)
|
Chris@102
|
177 {
|
Chris@102
|
178 return return_type(ring, true);
|
Chris@102
|
179 }
|
Chris@102
|
180 };
|
Chris@102
|
181
|
Chris@102
|
182
|
Chris@102
|
183 template <typename Polygon>
|
Chris@102
|
184 struct segments_end<Polygon, polygon_tag>
|
Chris@102
|
185 {
|
Chris@102
|
186 typedef typename detail::point_iterator::inner_range_type
|
Chris@102
|
187 <
|
Chris@102
|
188 Polygon
|
Chris@102
|
189 >::type inner_range;
|
Chris@102
|
190
|
Chris@102
|
191 typedef typename detail::segment_iterator::iterator_type
|
Chris@102
|
192 <
|
Chris@102
|
193 Polygon
|
Chris@102
|
194 >::type return_type;
|
Chris@102
|
195
|
Chris@102
|
196 static inline return_type apply(Polygon& polygon)
|
Chris@102
|
197 {
|
Chris@102
|
198 typedef typename return_type::second_iterator_type flatten_iterator;
|
Chris@102
|
199
|
Chris@102
|
200 return return_type
|
Chris@102
|
201 (segments_end
|
Chris@102
|
202 <
|
Chris@102
|
203 inner_range
|
Chris@102
|
204 >::apply(geometry::exterior_ring(polygon)),
|
Chris@102
|
205 flatten_iterator(boost::begin(geometry::interior_rings(polygon)),
|
Chris@102
|
206 boost::end(geometry::interior_rings(polygon))
|
Chris@102
|
207 ),
|
Chris@102
|
208 flatten_iterator( boost::end(geometry::interior_rings(polygon)) )
|
Chris@102
|
209 );
|
Chris@102
|
210 }
|
Chris@102
|
211 };
|
Chris@102
|
212
|
Chris@102
|
213
|
Chris@102
|
214 template <typename MultiLinestring>
|
Chris@102
|
215 struct segments_end<MultiLinestring, multi_linestring_tag>
|
Chris@102
|
216 {
|
Chris@102
|
217 typedef typename detail::segment_iterator::iterator_type
|
Chris@102
|
218 <
|
Chris@102
|
219 MultiLinestring
|
Chris@102
|
220 >::type return_type;
|
Chris@102
|
221
|
Chris@102
|
222 static inline return_type apply(MultiLinestring& multilinestring)
|
Chris@102
|
223 {
|
Chris@102
|
224 return return_type(boost::end(multilinestring));
|
Chris@102
|
225 }
|
Chris@102
|
226 };
|
Chris@102
|
227
|
Chris@102
|
228
|
Chris@102
|
229 template <typename MultiPolygon>
|
Chris@102
|
230 struct segments_end<MultiPolygon, multi_polygon_tag>
|
Chris@102
|
231 {
|
Chris@102
|
232 typedef typename detail::segment_iterator::iterator_type
|
Chris@102
|
233 <
|
Chris@102
|
234 MultiPolygon
|
Chris@102
|
235 >::type return_type;
|
Chris@102
|
236
|
Chris@102
|
237 static inline return_type apply(MultiPolygon& multipolygon)
|
Chris@102
|
238 {
|
Chris@102
|
239 return return_type(boost::end(multipolygon));
|
Chris@102
|
240 }
|
Chris@102
|
241 };
|
Chris@102
|
242
|
Chris@102
|
243
|
Chris@102
|
244 } // namespace dispatch
|
Chris@102
|
245 #endif // DOXYGEN_NO_DISPATCH
|
Chris@102
|
246
|
Chris@102
|
247
|
Chris@102
|
248 // MK:: need to add doc here
|
Chris@102
|
249 template <typename Geometry>
|
Chris@102
|
250 class segment_iterator
|
Chris@102
|
251 : public detail::segment_iterator::iterator_type<Geometry>::type
|
Chris@102
|
252 {
|
Chris@102
|
253 private:
|
Chris@102
|
254 typedef typename detail::segment_iterator::iterator_type
|
Chris@102
|
255 <
|
Chris@102
|
256 Geometry
|
Chris@102
|
257 >::type base;
|
Chris@102
|
258
|
Chris@102
|
259 inline base const* base_ptr() const
|
Chris@102
|
260 {
|
Chris@102
|
261 return this;
|
Chris@102
|
262 }
|
Chris@102
|
263
|
Chris@102
|
264 template <typename OtherGeometry> friend class segment_iterator;
|
Chris@102
|
265
|
Chris@102
|
266 template <typename G>
|
Chris@102
|
267 friend inline segment_iterator<G const> segments_begin(G const&);
|
Chris@102
|
268
|
Chris@102
|
269 template <typename G>
|
Chris@102
|
270 friend inline segment_iterator<G const> segments_end(G const&);
|
Chris@102
|
271
|
Chris@102
|
272 inline segment_iterator(base const& base_it) : base(base_it) {}
|
Chris@102
|
273
|
Chris@102
|
274 public:
|
Chris@102
|
275 // The following typedef is needed for this iterator to be
|
Chris@102
|
276 // bidirectional.
|
Chris@102
|
277 // Normally we would not have to define this. However, due to the
|
Chris@102
|
278 // fact that the value type of the iterator is not a reference,
|
Chris@102
|
279 // the iterator_facade framework (used to define the base class of
|
Chris@102
|
280 // this iterator) degrades automatically the iterator's category
|
Chris@102
|
281 // to input iterator. With the following typedef we recover the
|
Chris@102
|
282 // correct iterator category.
|
Chris@102
|
283 typedef std::bidirectional_iterator_tag iterator_category;
|
Chris@102
|
284
|
Chris@102
|
285 inline segment_iterator() {}
|
Chris@102
|
286
|
Chris@102
|
287 template <typename OtherGeometry>
|
Chris@102
|
288 inline segment_iterator(segment_iterator<OtherGeometry> const& other)
|
Chris@102
|
289 : base(*other.base_ptr())
|
Chris@102
|
290 {
|
Chris@102
|
291 static const bool is_conv
|
Chris@102
|
292 = boost::is_convertible<
|
Chris@102
|
293 typename detail::segment_iterator::iterator_type
|
Chris@102
|
294 <
|
Chris@102
|
295 OtherGeometry
|
Chris@102
|
296 >::type,
|
Chris@102
|
297 typename detail::segment_iterator::iterator_type<Geometry>::type
|
Chris@102
|
298 >::value;
|
Chris@102
|
299
|
Chris@102
|
300 BOOST_MPL_ASSERT_MSG((is_conv),
|
Chris@102
|
301 NOT_CONVERTIBLE,
|
Chris@102
|
302 (segment_iterator<OtherGeometry>));
|
Chris@102
|
303 }
|
Chris@102
|
304
|
Chris@102
|
305 inline segment_iterator& operator++() // prefix
|
Chris@102
|
306 {
|
Chris@102
|
307 base::operator++();
|
Chris@102
|
308 return *this;
|
Chris@102
|
309 }
|
Chris@102
|
310
|
Chris@102
|
311 inline segment_iterator& operator--() // prefix
|
Chris@102
|
312 {
|
Chris@102
|
313 base::operator--();
|
Chris@102
|
314 return *this;
|
Chris@102
|
315 }
|
Chris@102
|
316
|
Chris@102
|
317 inline segment_iterator operator++(int) // postfix
|
Chris@102
|
318 {
|
Chris@102
|
319 segment_iterator copy(*this);
|
Chris@102
|
320 base::operator++();
|
Chris@102
|
321 return copy;
|
Chris@102
|
322 }
|
Chris@102
|
323
|
Chris@102
|
324 inline segment_iterator operator--(int) // postfix
|
Chris@102
|
325 {
|
Chris@102
|
326 segment_iterator copy(*this);
|
Chris@102
|
327 base::operator--();
|
Chris@102
|
328 return copy;
|
Chris@102
|
329 }
|
Chris@102
|
330 };
|
Chris@102
|
331
|
Chris@102
|
332
|
Chris@102
|
333 // MK:: need to add doc here
|
Chris@102
|
334 template <typename Geometry>
|
Chris@102
|
335 inline segment_iterator<Geometry const>
|
Chris@102
|
336 segments_begin(Geometry const& geometry)
|
Chris@102
|
337 {
|
Chris@102
|
338 return dispatch::segments_begin<Geometry const>::apply(geometry);
|
Chris@102
|
339 }
|
Chris@102
|
340
|
Chris@102
|
341
|
Chris@102
|
342 // MK:: need to add doc here
|
Chris@102
|
343 template <typename Geometry>
|
Chris@102
|
344 inline segment_iterator<Geometry const>
|
Chris@102
|
345 segments_end(Geometry const& geometry)
|
Chris@102
|
346 {
|
Chris@102
|
347 return dispatch::segments_end<Geometry const>::apply(geometry);
|
Chris@102
|
348 }
|
Chris@102
|
349
|
Chris@102
|
350
|
Chris@102
|
351 }} // namespace boost::geometry
|
Chris@102
|
352
|
Chris@102
|
353 #endif // BOOST_GEOMETRY_ITERATORS_SEGMENT_ITERATOR_HPP
|