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