]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / geometry / algorithms / detail / buffer / get_piece_turns.hpp
CommitLineData
7c673cae
FG
1// Boost.Geometry (aka GGL, Generic Geometry Library)
2
3// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
b32b8144
FG
4// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
5
20effc67
TL
6// This file was modified by Oracle on 2017-2020.
7// Modifications copyright (c) 2017-2020 Oracle and/or its affiliates.
b32b8144 8// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
7c673cae
FG
9
10// Use, modification and distribution is subject to the Boost Software License,
11// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
12// http://www.boost.org/LICENSE_1_0.txt)
13
14#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_GET_PIECE_TURNS_HPP
15#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_GET_PIECE_TURNS_HPP
16
92f5a8d4 17#include <boost/core/ignore_unused.hpp>
20effc67
TL
18#include <boost/range/begin.hpp>
19#include <boost/range/end.hpp>
20#include <boost/range/value_type.hpp>
7c673cae 21
92f5a8d4 22#include <boost/geometry/core/assert.hpp>
7c673cae 23#include <boost/geometry/algorithms/equals.hpp>
7c673cae
FG
24#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
25#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
26#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
27#include <boost/geometry/algorithms/detail/sections/section_functions.hpp>
28#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp>
29
30
31namespace boost { namespace geometry
32{
33
34
35#ifndef DOXYGEN_NO_DETAIL
36namespace detail { namespace buffer
37{
38
92f5a8d4
TL
39// Implements a unique_sub_range for a buffered piece,
40// the range can return subsequent points
41// known as "i", "j" and "k" (and further), indexed as 0,1,2,3
42template <typename Ring>
43struct unique_sub_range_from_piece
7c673cae 44{
92f5a8d4
TL
45 typedef typename boost::range_iterator<Ring const>::type iterator_type;
46 typedef typename geometry::point_type<Ring const>::type point_type;
47
48 unique_sub_range_from_piece(Ring const& ring,
49 iterator_type iterator_at_i, iterator_type iterator_at_j)
50 : m_ring(ring)
51 , m_iterator_at_i(iterator_at_i)
52 , m_iterator_at_j(iterator_at_j)
53 , m_point_retrieved(false)
54 {}
55
56 static inline bool is_first_segment() { return false; }
57 static inline bool is_last_segment() { return false; }
58
59 static inline std::size_t size() { return 3u; }
60
61 inline point_type const& at(std::size_t index) const
7c673cae 62 {
92f5a8d4
TL
63 BOOST_GEOMETRY_ASSERT(index < size());
64 switch (index)
65 {
66 case 0 : return *m_iterator_at_i;
67 case 1 : return *m_iterator_at_j;
68 case 2 : return get_point_k();
69 default : return *m_iterator_at_i;
70 }
71 }
72
73private :
74
75 inline point_type const& get_point_k() const
76 {
77 if (! m_point_retrieved)
78 {
79 m_iterator_at_k = advance_one(m_iterator_at_j);
80 m_point_retrieved = true;
81 }
82 return *m_iterator_at_k;
83 }
84
85 inline void circular_advance_one(iterator_type& next) const
86 {
87 ++next;
88 if (next == boost::end(m_ring))
89 {
90 next = boost::begin(m_ring) + 1;
91 }
7c673cae
FG
92 }
93
92f5a8d4
TL
94 inline iterator_type advance_one(iterator_type it) const
95 {
96 iterator_type result = it;
97 circular_advance_one(result);
98
99 // TODO: we could also use piece-boundaries
100 // to check if the point equals the last one
101 while (geometry::equals(*it, *result))
102 {
103 circular_advance_one(result);
104 }
105 return result;
106 }
107
108 Ring const& m_ring;
109 iterator_type m_iterator_at_i;
110 iterator_type m_iterator_at_j;
111 mutable iterator_type m_iterator_at_k;
112 mutable bool m_point_retrieved;
7c673cae 113};
7c673cae
FG
114
115template
116<
117 typename Pieces,
118 typename Rings,
119 typename Turns,
1e59de90 120 typename Strategy,
7c673cae
FG
121 typename RobustPolicy
122>
123class piece_turn_visitor
124{
125 Pieces const& m_pieces;
126 Rings const& m_rings;
127 Turns& m_turns;
1e59de90 128 Strategy const& m_strategy;
7c673cae
FG
129 RobustPolicy const& m_robust_policy;
130
131 template <typename Piece>
132 inline bool is_adjacent(Piece const& piece1, Piece const& piece2) const
133 {
134 if (piece1.first_seg_id.multi_index != piece2.first_seg_id.multi_index)
135 {
136 return false;
137 }
138
139 return piece1.index == piece2.left_index
140 || piece1.index == piece2.right_index;
141 }
142
143 template <typename Piece>
144 inline bool is_on_same_convex_ring(Piece const& piece1, Piece const& piece2) const
145 {
146 if (piece1.first_seg_id.multi_index != piece2.first_seg_id.multi_index)
147 {
148 return false;
149 }
150
151 return ! m_rings[piece1.first_seg_id.multi_index].has_concave;
152 }
153
7c673cae
FG
154 template <std::size_t Dimension, typename Iterator, typename Box>
155 inline void move_begin_iterator(Iterator& it_begin, Iterator it_beyond,
b32b8144
FG
156 signed_size_type& index, int dir,
157 Box const& this_bounding_box,
158 Box const& other_bounding_box)
7c673cae
FG
159 {
160 for(; it_begin != it_beyond
161 && it_begin + 1 != it_beyond
162 && detail::section::preceding<Dimension>(dir, *(it_begin + 1),
b32b8144
FG
163 this_bounding_box,
164 other_bounding_box,
165 m_robust_policy);
7c673cae
FG
166 ++it_begin, index++)
167 {}
168 }
169
170 template <std::size_t Dimension, typename Iterator, typename Box>
171 inline void move_end_iterator(Iterator it_begin, Iterator& it_beyond,
b32b8144
FG
172 int dir, Box const& this_bounding_box,
173 Box const& other_bounding_box)
7c673cae
FG
174 {
175 while (it_beyond != it_begin
176 && it_beyond - 1 != it_begin
177 && it_beyond - 2 != it_begin)
178 {
179 if (detail::section::exceeding<Dimension>(dir, *(it_beyond - 2),
b32b8144 180 this_bounding_box, other_bounding_box, m_robust_policy))
7c673cae
FG
181 {
182 --it_beyond;
183 }
184 else
185 {
186 return;
187 }
188 }
189 }
190
191 template <typename Piece, typename Section>
192 inline void calculate_turns(Piece const& piece1, Piece const& piece2,
193 Section const& section1, Section const& section2)
194 {
195 typedef typename boost::range_value<Rings const>::type ring_type;
196 typedef typename boost::range_value<Turns const>::type turn_type;
197 typedef typename boost::range_iterator<ring_type const>::type iterator;
198
199 signed_size_type const piece1_first_index = piece1.first_seg_id.segment_index;
200 signed_size_type const piece2_first_index = piece2.first_seg_id.segment_index;
201 if (piece1_first_index < 0 || piece2_first_index < 0)
202 {
203 return;
204 }
205
206 // Get indices of part of offsetted_rings for this monotonic section:
207 signed_size_type const sec1_first_index = piece1_first_index + section1.begin_index;
208 signed_size_type const sec2_first_index = piece2_first_index + section2.begin_index;
209
210 // index of last point in section, beyond-end is one further
211 signed_size_type const sec1_last_index = piece1_first_index + section1.end_index;
212 signed_size_type const sec2_last_index = piece2_first_index + section2.end_index;
213
214 // get geometry and iterators over these sections
215 ring_type const& ring1 = m_rings[piece1.first_seg_id.multi_index];
216 iterator it1_first = boost::begin(ring1) + sec1_first_index;
217 iterator it1_beyond = boost::begin(ring1) + sec1_last_index + 1;
218
219 ring_type const& ring2 = m_rings[piece2.first_seg_id.multi_index];
220 iterator it2_first = boost::begin(ring2) + sec2_first_index;
221 iterator it2_beyond = boost::begin(ring2) + sec2_last_index + 1;
222
223 // Set begin/end of monotonic ranges, in both x/y directions
224 signed_size_type index1 = sec1_first_index;
225 move_begin_iterator<0>(it1_first, it1_beyond, index1,
b32b8144 226 section1.directions[0], section1.bounding_box, section2.bounding_box);
7c673cae 227 move_end_iterator<0>(it1_first, it1_beyond,
b32b8144 228 section1.directions[0], section1.bounding_box, section2.bounding_box);
7c673cae 229 move_begin_iterator<1>(it1_first, it1_beyond, index1,
b32b8144 230 section1.directions[1], section1.bounding_box, section2.bounding_box);
7c673cae 231 move_end_iterator<1>(it1_first, it1_beyond,
b32b8144 232 section1.directions[1], section1.bounding_box, section2.bounding_box);
7c673cae
FG
233
234 signed_size_type index2 = sec2_first_index;
235 move_begin_iterator<0>(it2_first, it2_beyond, index2,
b32b8144 236 section2.directions[0], section2.bounding_box, section1.bounding_box);
7c673cae 237 move_end_iterator<0>(it2_first, it2_beyond,
b32b8144 238 section2.directions[0], section2.bounding_box, section1.bounding_box);
7c673cae 239 move_begin_iterator<1>(it2_first, it2_beyond, index2,
b32b8144 240 section2.directions[1], section2.bounding_box, section1.bounding_box);
7c673cae 241 move_end_iterator<1>(it2_first, it2_beyond,
b32b8144 242 section2.directions[1], section2.bounding_box, section1.bounding_box);
7c673cae
FG
243
244 turn_type the_model;
245 the_model.operations[0].piece_index = piece1.index;
246 the_model.operations[0].seg_id = piece1.first_seg_id;
247 the_model.operations[0].seg_id.segment_index = index1; // override
248
249 iterator it1 = it1_first;
250 for (iterator prev1 = it1++;
251 it1 != it1_beyond;
252 prev1 = it1++, the_model.operations[0].seg_id.segment_index++)
253 {
254 the_model.operations[1].piece_index = piece2.index;
255 the_model.operations[1].seg_id = piece2.first_seg_id;
256 the_model.operations[1].seg_id.segment_index = index2; // override
257
92f5a8d4 258 unique_sub_range_from_piece<ring_type> unique_sub_range1(ring1, prev1, it1);
7c673cae
FG
259
260 iterator it2 = it2_first;
261 for (iterator prev2 = it2++;
262 it2 != it2_beyond;
263 prev2 = it2++, the_model.operations[1].seg_id.segment_index++)
264 {
92f5a8d4 265 unique_sub_range_from_piece<ring_type> unique_sub_range2(ring2, prev2, it2);
20effc67 266
7c673cae
FG
267 typedef detail::overlay::get_turn_info
268 <
20effc67 269 detail::overlay::assign_policy_only_start_turns
7c673cae
FG
270 > turn_policy;
271
92f5a8d4
TL
272 turn_policy::apply(unique_sub_range1, unique_sub_range2,
273 the_model,
1e59de90 274 m_strategy,
92f5a8d4
TL
275 m_robust_policy,
276 std::back_inserter(m_turns));
7c673cae
FG
277 }
278 }
279 }
280
281public:
282
283 piece_turn_visitor(Pieces const& pieces,
284 Rings const& ring_collection,
285 Turns& turns,
1e59de90 286 Strategy const& strategy,
7c673cae
FG
287 RobustPolicy const& robust_policy)
288 : m_pieces(pieces)
289 , m_rings(ring_collection)
290 , m_turns(turns)
1e59de90 291 , m_strategy(strategy)
7c673cae
FG
292 , m_robust_policy(robust_policy)
293 {}
294
295 template <typename Section>
b32b8144 296 inline bool apply(Section const& section1, Section const& section2,
7c673cae
FG
297 bool first = true)
298 {
92f5a8d4 299 boost::ignore_unused(first);
7c673cae
FG
300
301 typedef typename boost::range_value<Pieces const>::type piece_type;
302 piece_type const& piece1 = m_pieces[section1.ring_id.source_index];
303 piece_type const& piece2 = m_pieces[section2.ring_id.source_index];
304
305 if ( piece1.index == piece2.index
306 || is_adjacent(piece1, piece2)
307 || is_on_same_convex_ring(piece1, piece2)
308 || detail::disjoint::disjoint_box_box(section1.bounding_box,
92f5a8d4 309 section2.bounding_box,
1e59de90 310 m_strategy) )
7c673cae 311 {
b32b8144 312 return true;
7c673cae
FG
313 }
314
315 calculate_turns(piece1, piece2, section1, section2);
b32b8144
FG
316
317 return true;
7c673cae
FG
318 }
319};
320
321
322}} // namespace detail::buffer
323#endif // DOXYGEN_NO_DETAIL
324
325
326}} // namespace boost::geometry
327
328#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_GET_PIECE_TURNS_HPP