]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Boost.Geometry (aka GGL, Generic Geometry Library) |
2 | ||
3 | // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. | |
4 | ||
5 | // Use, modification and distribution is subject to the Boost Software License, | |
6 | // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
7 | // http://www.boost.org/LICENSE_1_0.txt) | |
8 | ||
9 | #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP | |
10 | #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP | |
11 | ||
12 | ||
13 | #include <boost/array.hpp> | |
14 | #include <boost/mpl/assert.hpp> | |
15 | #include <boost/range.hpp> | |
16 | ||
17 | #include <boost/geometry/core/assert.hpp> | |
18 | #include <boost/geometry/core/ring_type.hpp> | |
19 | #include <boost/geometry/core/exterior_ring.hpp> | |
20 | #include <boost/geometry/core/interior_rings.hpp> | |
21 | #include <boost/geometry/core/tags.hpp> | |
22 | #include <boost/geometry/algorithms/convert.hpp> | |
23 | #include <boost/geometry/geometries/concepts/check.hpp> | |
24 | #include <boost/geometry/util/range.hpp> | |
25 | #include <boost/geometry/iterators/ever_circling_iterator.hpp> | |
26 | #include <boost/geometry/views/closeable_view.hpp> | |
27 | #include <boost/geometry/views/reversible_view.hpp> | |
28 | ||
29 | ||
30 | namespace boost { namespace geometry | |
31 | { | |
32 | ||
33 | ||
34 | #ifndef DOXYGEN_NO_DETAIL | |
35 | namespace detail { namespace copy_segments | |
36 | { | |
37 | ||
38 | ||
39 | template <typename Range, bool Reverse, typename SegmentIdentifier, typename PointOut> | |
40 | struct copy_segment_point_range | |
41 | { | |
42 | static inline bool apply(Range const& range, | |
43 | SegmentIdentifier const& seg_id, int offset, | |
44 | PointOut& point) | |
45 | { | |
46 | typedef typename closeable_view | |
47 | < | |
48 | Range const, | |
49 | closure<Range>::value | |
50 | >::type cview_type; | |
51 | ||
52 | typedef typename reversible_view | |
53 | < | |
54 | cview_type const, | |
55 | Reverse ? iterate_reverse : iterate_forward | |
56 | >::type rview_type; | |
57 | ||
58 | cview_type cview(range); | |
59 | rview_type view(cview); | |
60 | ||
61 | typedef typename boost::range_iterator<rview_type>::type iterator; | |
62 | geometry::ever_circling_iterator<iterator> it(boost::begin(view), boost::end(view), | |
63 | boost::begin(view) + seg_id.segment_index, true); | |
64 | ||
65 | for (signed_size_type i = 0; i < offset; ++i, ++it) | |
66 | { | |
67 | } | |
68 | ||
69 | geometry::convert(*it, point); | |
70 | return true; | |
71 | } | |
72 | }; | |
73 | ||
74 | ||
75 | template <typename Polygon, bool Reverse, typename SegmentIdentifier, typename PointOut> | |
76 | struct copy_segment_point_polygon | |
77 | { | |
78 | static inline bool apply(Polygon const& polygon, | |
79 | SegmentIdentifier const& seg_id, int offset, | |
80 | PointOut& point) | |
81 | { | |
82 | // Call ring-version with the right ring | |
83 | return copy_segment_point_range | |
84 | < | |
85 | typename geometry::ring_type<Polygon>::type, | |
86 | Reverse, | |
87 | SegmentIdentifier, | |
88 | PointOut | |
89 | >::apply | |
90 | ( | |
91 | seg_id.ring_index < 0 | |
92 | ? geometry::exterior_ring(polygon) | |
93 | : range::at(geometry::interior_rings(polygon), seg_id.ring_index), | |
94 | seg_id, offset, | |
95 | point | |
96 | ); | |
97 | } | |
98 | }; | |
99 | ||
100 | ||
101 | template <typename Box, bool Reverse, typename SegmentIdentifier, typename PointOut> | |
102 | struct copy_segment_point_box | |
103 | { | |
104 | static inline bool apply(Box const& box, | |
105 | SegmentIdentifier const& seg_id, int offset, | |
106 | PointOut& point) | |
107 | { | |
108 | signed_size_type index = seg_id.segment_index; | |
109 | for (int i = 0; i < offset; i++) | |
110 | { | |
111 | index++; | |
112 | } | |
113 | ||
114 | boost::array<typename point_type<Box>::type, 4> bp; | |
115 | assign_box_corners_oriented<Reverse>(box, bp); | |
116 | point = bp[index % 4]; | |
117 | return true; | |
118 | } | |
119 | }; | |
120 | ||
121 | ||
122 | template | |
123 | < | |
124 | typename MultiGeometry, | |
125 | typename SegmentIdentifier, | |
126 | typename PointOut, | |
127 | typename Policy | |
128 | > | |
129 | struct copy_segment_point_multi | |
130 | { | |
131 | static inline bool apply(MultiGeometry const& multi, | |
132 | SegmentIdentifier const& seg_id, int offset, | |
133 | PointOut& point) | |
134 | { | |
135 | ||
136 | BOOST_GEOMETRY_ASSERT | |
137 | ( | |
138 | seg_id.multi_index >= 0 | |
139 | && seg_id.multi_index < int(boost::size(multi)) | |
140 | ); | |
141 | ||
142 | // Call the single-version | |
143 | return Policy::apply(range::at(multi, seg_id.multi_index), seg_id, offset, point); | |
144 | } | |
145 | }; | |
146 | ||
147 | ||
148 | }} // namespace detail::copy_segments | |
149 | #endif // DOXYGEN_NO_DETAIL | |
150 | ||
151 | ||
152 | #ifndef DOXYGEN_NO_DISPATCH | |
153 | namespace dispatch | |
154 | { | |
155 | ||
156 | ||
157 | template | |
158 | < | |
159 | typename Tag, | |
160 | typename GeometryIn, | |
161 | bool Reverse, | |
162 | typename SegmentIdentifier, | |
163 | typename PointOut | |
164 | > | |
165 | struct copy_segment_point | |
166 | { | |
167 | BOOST_MPL_ASSERT_MSG | |
168 | ( | |
169 | false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE | |
170 | , (types<GeometryIn>) | |
171 | ); | |
172 | }; | |
173 | ||
174 | ||
175 | template <typename LineString, bool Reverse, typename SegmentIdentifier, typename PointOut> | |
176 | struct copy_segment_point<linestring_tag, LineString, Reverse, SegmentIdentifier, PointOut> | |
177 | : detail::copy_segments::copy_segment_point_range | |
178 | < | |
179 | LineString, Reverse, SegmentIdentifier, PointOut | |
180 | > | |
181 | {}; | |
182 | ||
183 | ||
184 | template <typename Ring, bool Reverse, typename SegmentIdentifier, typename PointOut> | |
185 | struct copy_segment_point<ring_tag, Ring, Reverse, SegmentIdentifier, PointOut> | |
186 | : detail::copy_segments::copy_segment_point_range | |
187 | < | |
188 | Ring, Reverse, SegmentIdentifier, PointOut | |
189 | > | |
190 | {}; | |
191 | ||
192 | template <typename Polygon, bool Reverse, typename SegmentIdentifier, typename PointOut> | |
193 | struct copy_segment_point<polygon_tag, Polygon, Reverse, SegmentIdentifier, PointOut> | |
194 | : detail::copy_segments::copy_segment_point_polygon | |
195 | < | |
196 | Polygon, Reverse, SegmentIdentifier, PointOut | |
197 | > | |
198 | {}; | |
199 | ||
200 | ||
201 | template <typename Box, bool Reverse, typename SegmentIdentifier, typename PointOut> | |
202 | struct copy_segment_point<box_tag, Box, Reverse, SegmentIdentifier, PointOut> | |
203 | : detail::copy_segments::copy_segment_point_box | |
204 | < | |
205 | Box, Reverse, SegmentIdentifier, PointOut | |
206 | > | |
207 | {}; | |
208 | ||
209 | ||
210 | template | |
211 | < | |
212 | typename MultiGeometry, | |
213 | bool Reverse, | |
214 | typename SegmentIdentifier, | |
215 | typename PointOut | |
216 | > | |
217 | struct copy_segment_point | |
218 | < | |
219 | multi_polygon_tag, | |
220 | MultiGeometry, | |
221 | Reverse, | |
222 | SegmentIdentifier, | |
223 | PointOut | |
224 | > | |
225 | : detail::copy_segments::copy_segment_point_multi | |
226 | < | |
227 | MultiGeometry, | |
228 | SegmentIdentifier, | |
229 | PointOut, | |
230 | detail::copy_segments::copy_segment_point_polygon | |
231 | < | |
232 | typename boost::range_value<MultiGeometry>::type, | |
233 | Reverse, | |
234 | SegmentIdentifier, | |
235 | PointOut | |
236 | > | |
237 | > | |
238 | {}; | |
239 | ||
240 | template | |
241 | < | |
242 | typename MultiGeometry, | |
243 | bool Reverse, | |
244 | typename SegmentIdentifier, | |
245 | typename PointOut | |
246 | > | |
247 | struct copy_segment_point | |
248 | < | |
249 | multi_linestring_tag, | |
250 | MultiGeometry, | |
251 | Reverse, | |
252 | SegmentIdentifier, | |
253 | PointOut | |
254 | > | |
255 | : detail::copy_segments::copy_segment_point_multi | |
256 | < | |
257 | MultiGeometry, | |
258 | SegmentIdentifier, | |
259 | PointOut, | |
260 | detail::copy_segments::copy_segment_point_range | |
261 | < | |
262 | typename boost::range_value<MultiGeometry>::type, | |
263 | Reverse, | |
264 | SegmentIdentifier, | |
265 | PointOut | |
266 | > | |
267 | > | |
268 | {}; | |
269 | ||
270 | ||
271 | } // namespace dispatch | |
272 | #endif // DOXYGEN_NO_DISPATCH | |
273 | ||
274 | ||
275 | ||
276 | ||
277 | ||
278 | /*! | |
279 | \brief Helper function, copies a point from a segment | |
280 | \ingroup overlay | |
281 | */ | |
282 | template<bool Reverse, typename Geometry, typename SegmentIdentifier, typename PointOut> | |
283 | inline bool copy_segment_point(Geometry const& geometry, | |
284 | SegmentIdentifier const& seg_id, int offset, | |
285 | PointOut& point_out) | |
286 | { | |
287 | concepts::check<Geometry const>(); | |
288 | ||
289 | return dispatch::copy_segment_point | |
290 | < | |
291 | typename tag<Geometry>::type, | |
292 | Geometry, | |
293 | Reverse, | |
294 | SegmentIdentifier, | |
295 | PointOut | |
296 | >::apply(geometry, seg_id, offset, point_out); | |
297 | } | |
298 | ||
299 | ||
300 | /*! | |
301 | \brief Helper function, to avoid the same construct several times, | |
302 | copies a point, based on a source-index and two geometries | |
303 | \ingroup overlay | |
304 | */ | |
305 | template | |
306 | < | |
307 | bool Reverse1, bool Reverse2, | |
308 | typename Geometry1, typename Geometry2, | |
309 | typename SegmentIdentifier, | |
310 | typename PointOut | |
311 | > | |
312 | inline bool copy_segment_point(Geometry1 const& geometry1, Geometry2 const& geometry2, | |
313 | SegmentIdentifier const& seg_id, int offset, | |
314 | PointOut& point_out) | |
315 | { | |
316 | concepts::check<Geometry1 const>(); | |
317 | concepts::check<Geometry2 const>(); | |
318 | ||
319 | BOOST_GEOMETRY_ASSERT(seg_id.source_index == 0 || seg_id.source_index == 1); | |
320 | ||
321 | if (seg_id.source_index == 0) | |
322 | { | |
323 | return dispatch::copy_segment_point | |
324 | < | |
325 | typename tag<Geometry1>::type, | |
326 | Geometry1, | |
327 | Reverse1, | |
328 | SegmentIdentifier, | |
329 | PointOut | |
330 | >::apply(geometry1, seg_id, offset, point_out); | |
331 | } | |
332 | else if (seg_id.source_index == 1) | |
333 | { | |
334 | return dispatch::copy_segment_point | |
335 | < | |
336 | typename tag<Geometry2>::type, | |
337 | Geometry2, | |
338 | Reverse2, | |
339 | SegmentIdentifier, | |
340 | PointOut | |
341 | >::apply(geometry2, seg_id, offset, point_out); | |
342 | } | |
343 | // Exception? | |
344 | return false; | |
345 | } | |
346 | ||
347 | ||
348 | /*! | |
349 | \brief Helper function, to avoid the same construct several times, | |
350 | copies a point, based on a source-index and two geometries | |
351 | \ingroup overlay | |
352 | */ | |
353 | template | |
354 | < | |
355 | bool Reverse1, bool Reverse2, | |
356 | typename Geometry1, typename Geometry2, | |
357 | typename SegmentIdentifier, | |
358 | typename PointOut | |
359 | > | |
360 | inline bool copy_segment_points(Geometry1 const& geometry1, Geometry2 const& geometry2, | |
361 | SegmentIdentifier const& seg_id, | |
362 | PointOut& point1, PointOut& point2) | |
363 | { | |
364 | concepts::check<Geometry1 const>(); | |
365 | concepts::check<Geometry2 const>(); | |
366 | ||
367 | return copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, 0, point1) | |
368 | && copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, 1, point2); | |
369 | } | |
370 | ||
371 | /*! | |
372 | \brief Helper function, copies three points: two from the specified segment | |
373 | (from, to) and the next one | |
374 | \ingroup overlay | |
375 | */ | |
376 | template | |
377 | < | |
378 | bool Reverse1, bool Reverse2, | |
379 | typename Geometry1, typename Geometry2, | |
380 | typename SegmentIdentifier, | |
381 | typename PointOut | |
382 | > | |
383 | inline bool copy_segment_points(Geometry1 const& geometry1, Geometry2 const& geometry2, | |
384 | SegmentIdentifier const& seg_id, | |
385 | PointOut& point1, PointOut& point2, PointOut& point3) | |
386 | { | |
387 | concepts::check<Geometry1 const>(); | |
388 | concepts::check<Geometry2 const>(); | |
389 | ||
390 | return copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, 0, point1) | |
391 | && copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, 1, point2) | |
392 | && copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, 2, point3); | |
393 | } | |
394 | ||
395 | ||
396 | ||
397 | }} // namespace boost::geometry | |
398 | ||
399 | #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP |