]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/geometry/include/boost/geometry/algorithms/detail/overlay/copy_segments.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / geometry / include / boost / geometry / algorithms / detail / overlay / copy_segments.hpp
CommitLineData
7c673cae
FG
1// Boost.Geometry (aka GGL, Generic Geometry Library)
2
3// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
4
5// This file was modified by Oracle on 2014.
6// Modifications copyright (c) 2014 Oracle and/or its affiliates.
7
8// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
9// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
10
11// Use, modification and distribution is subject to the Boost Software License,
12// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
13// http://www.boost.org/LICENSE_1_0.txt)
14
15#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENTS_HPP
16#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENTS_HPP
17
18
19#include <vector>
20
21#include <boost/array.hpp>
22#include <boost/mpl/assert.hpp>
23#include <boost/range.hpp>
24#include <boost/type_traits/integral_constant.hpp>
25
26#include <boost/geometry/core/assert.hpp>
27#include <boost/geometry/core/exterior_ring.hpp>
28#include <boost/geometry/core/interior_rings.hpp>
29#include <boost/geometry/core/ring_type.hpp>
30#include <boost/geometry/core/tags.hpp>
31#include <boost/geometry/algorithms/not_implemented.hpp>
32#include <boost/geometry/geometries/concepts/check.hpp>
33#include <boost/geometry/iterators/ever_circling_iterator.hpp>
34#include <boost/geometry/views/closeable_view.hpp>
35#include <boost/geometry/views/reversible_view.hpp>
36
37#include <boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp>
38#include <boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp>
39
40#include <boost/geometry/util/range.hpp>
41
42
43namespace boost { namespace geometry
44{
45
46
47#ifndef DOXYGEN_NO_DETAIL
48namespace detail { namespace copy_segments
49{
50
51
52template <bool Reverse>
53struct copy_segments_ring
54{
55 template
56 <
57 typename Ring,
58 typename SegmentIdentifier,
59 typename RobustPolicy,
60 typename RangeOut
61 >
62 static inline void apply(Ring const& ring,
63 SegmentIdentifier const& seg_id,
64 signed_size_type to_index,
65 RobustPolicy const& robust_policy,
66 RangeOut& current_output)
67 {
68 typedef typename closeable_view
69 <
70 Ring const,
71 closure<Ring>::value
72 >::type cview_type;
73
74 typedef typename reversible_view
75 <
76 cview_type const,
77 Reverse ? iterate_reverse : iterate_forward
78 >::type rview_type;
79
80 typedef typename boost::range_iterator<rview_type const>::type iterator;
81 typedef geometry::ever_circling_iterator<iterator> ec_iterator;
82
83
84 cview_type cview(ring);
85 rview_type view(cview);
86
87 // The problem: sometimes we want to from "3" to "2"
88 // -> end = "3" -> end == begin
89 // This is not convenient with iterators.
90
91 // So we use the ever-circling iterator and determine when to step out
92
93 signed_size_type const from_index = seg_id.segment_index + 1;
94
95 // Sanity check
96 BOOST_GEOMETRY_ASSERT(from_index < static_cast<signed_size_type>(boost::size(view)));
97
98 ec_iterator it(boost::begin(view), boost::end(view),
99 boost::begin(view) + from_index);
100
101 // [2..4] -> 4 - 2 + 1 = 3 -> {2,3,4} -> OK
102 // [4..2],size=6 -> 6 - 4 + 2 + 1 = 5 -> {4,5,0,1,2} -> OK
103 // [1..1], travel the whole ring round
104 signed_size_type const count = from_index <= to_index
105 ? to_index - from_index + 1
106 : static_cast<signed_size_type>(boost::size(view))
107 - from_index + to_index + 1;
108
109 for (signed_size_type i = 0; i < count; ++i, ++it)
110 {
111 detail::overlay::append_no_dups_or_spikes(current_output, *it, robust_policy);
112 }
113 }
114};
115
116template <bool Reverse, bool RemoveSpikes = true>
117class copy_segments_linestring
118{
119private:
120 // remove spikes
121 template <typename RangeOut, typename Point, typename RobustPolicy>
122 static inline void append_to_output(RangeOut& current_output,
123 Point const& point,
124 RobustPolicy const& robust_policy,
125 boost::true_type const&)
126 {
127 detail::overlay::append_no_dups_or_spikes(current_output, point,
128 robust_policy);
129 }
130
131 // keep spikes
132 template <typename RangeOut, typename Point, typename RobustPolicy>
133 static inline void append_to_output(RangeOut& current_output,
134 Point const& point,
135 RobustPolicy const&,
136 boost::false_type const&)
137 {
138 detail::overlay::append_no_duplicates(current_output, point);
139 }
140
141public:
142 template
143 <
144 typename LineString,
145 typename SegmentIdentifier,
146 typename RobustPolicy,
147 typename RangeOut
148 >
149 static inline void apply(LineString const& ls,
150 SegmentIdentifier const& seg_id,
151 signed_size_type to_index,
152 RobustPolicy const& robust_policy,
153 RangeOut& current_output)
154 {
155 signed_size_type const from_index = seg_id.segment_index + 1;
156
157 // Sanity check
158 if ( from_index > to_index
159 || from_index < 0
160 || to_index >= static_cast<signed_size_type>(boost::size(ls)) )
161 {
162 return;
163 }
164
165 signed_size_type const count = to_index - from_index + 1;
166
167 typename boost::range_iterator<LineString const>::type
168 it = boost::begin(ls) + from_index;
169
170 for (signed_size_type i = 0; i < count; ++i, ++it)
171 {
172 append_to_output(current_output, *it, robust_policy,
173 boost::integral_constant<bool, RemoveSpikes>());
174 }
175 }
176};
177
178template <bool Reverse>
179struct copy_segments_polygon
180{
181 template
182 <
183 typename Polygon,
184 typename SegmentIdentifier,
185 typename RobustPolicy,
186 typename RangeOut
187 >
188 static inline void apply(Polygon const& polygon,
189 SegmentIdentifier const& seg_id,
190 signed_size_type to_index,
191 RobustPolicy const& robust_policy,
192 RangeOut& current_output)
193 {
194 // Call ring-version with the right ring
195 copy_segments_ring<Reverse>::apply
196 (
197 seg_id.ring_index < 0
198 ? geometry::exterior_ring(polygon)
199 : range::at(geometry::interior_rings(polygon), seg_id.ring_index),
200 seg_id, to_index,
201 robust_policy,
202 current_output
203 );
204 }
205};
206
207
208template <bool Reverse>
209struct copy_segments_box
210{
211 template
212 <
213 typename Box,
214 typename SegmentIdentifier,
215 typename RobustPolicy,
216 typename RangeOut
217 >
218 static inline void apply(Box const& box,
219 SegmentIdentifier const& seg_id,
220 signed_size_type to_index,
221 RobustPolicy const& robust_policy,
222 RangeOut& current_output)
223 {
224 signed_size_type index = seg_id.segment_index + 1;
225 BOOST_GEOMETRY_ASSERT(index < 5);
226
227 signed_size_type const count = index <= to_index
228 ? to_index - index + 1
229 : 5 - index + to_index + 1;
230
231 // Create array of points, the fifth one closes it
232 boost::array<typename point_type<Box>::type, 5> bp;
233 assign_box_corners_oriented<Reverse>(box, bp);
234 bp[4] = bp[0];
235
236 // (possibly cyclic) copy to output
237 // (see comments in ring-version)
238 for (signed_size_type i = 0; i < count; i++, index++)
239 {
240 detail::overlay::append_no_dups_or_spikes(current_output,
241 bp[index % 5], robust_policy);
242
243 }
244 }
245};
246
247
248template<typename Policy>
249struct copy_segments_multi
250{
251 template
252 <
253 typename MultiGeometry,
254 typename SegmentIdentifier,
255 typename RobustPolicy,
256 typename RangeOut
257 >
258 static inline void apply(MultiGeometry const& multi_geometry,
259 SegmentIdentifier const& seg_id,
260 signed_size_type to_index,
261 RobustPolicy const& robust_policy,
262 RangeOut& current_output)
263 {
264
265 BOOST_GEOMETRY_ASSERT
266 (
267 seg_id.multi_index >= 0
268 && static_cast<std::size_t>(seg_id.multi_index) < boost::size(multi_geometry)
269 );
270
271 // Call the single-version
272 Policy::apply(range::at(multi_geometry, seg_id.multi_index),
273 seg_id, to_index,
274 robust_policy,
275 current_output);
276 }
277};
278
279
280}} // namespace detail::copy_segments
281#endif // DOXYGEN_NO_DETAIL
282
283
284#ifndef DOXYGEN_NO_DISPATCH
285namespace dispatch
286{
287
288template
289<
290 typename Tag,
291 bool Reverse
292>
293struct copy_segments : not_implemented<Tag>
294{};
295
296
297template <bool Reverse>
298struct copy_segments<ring_tag, Reverse>
299 : detail::copy_segments::copy_segments_ring<Reverse>
300{};
301
302
303template <bool Reverse>
304struct copy_segments<linestring_tag, Reverse>
305 : detail::copy_segments::copy_segments_linestring<Reverse>
306{};
307
308template <bool Reverse>
309struct copy_segments<polygon_tag, Reverse>
310 : detail::copy_segments::copy_segments_polygon<Reverse>
311{};
312
313
314template <bool Reverse>
315struct copy_segments<box_tag, Reverse>
316 : detail::copy_segments::copy_segments_box<Reverse>
317{};
318
319
320template<bool Reverse>
321struct copy_segments<multi_polygon_tag, Reverse>
322 : detail::copy_segments::copy_segments_multi
323 <
324 detail::copy_segments::copy_segments_polygon<Reverse>
325 >
326{};
327
328
329} // namespace dispatch
330#endif // DOXYGEN_NO_DISPATCH
331
332
333/*!
334 \brief Copy segments from a geometry, starting with the specified segment (seg_id)
335 until the specified index (to_index)
336 \ingroup overlay
337 */
338template
339<
340 bool Reverse,
341 typename Geometry,
342 typename SegmentIdentifier,
343 typename RobustPolicy,
344 typename RangeOut
345>
346inline void copy_segments(Geometry const& geometry,
347 SegmentIdentifier const& seg_id,
348 signed_size_type to_index,
349 RobustPolicy const& robust_policy,
350 RangeOut& range_out)
351{
352 concepts::check<Geometry const>();
353
354 dispatch::copy_segments
355 <
356 typename tag<Geometry>::type,
357 Reverse
358 >::apply(geometry, seg_id, to_index, robust_policy, range_out);
359}
360
361
362}} // namespace boost::geometry
363
364
365#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENTS_HPP