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