]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / geometry / algorithms / detail / overlay / follow_linear_linear.hpp
CommitLineData
7c673cae
FG
1// Boost.Geometry (aka GGL, Generic Geometry Library)
2
b32b8144
FG
3// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
4
f67539c2 5// Copyright (c) 2014-2020, Oracle and/or its affiliates.
b32b8144
FG
6
7// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
8// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
7c673cae
FG
9
10// Licensed under the Boost Software License version 1.0.
11// http://www.boost.org/users/license.html
12
7c673cae
FG
13
14#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_LINEAR_LINEAR_HPP
15#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_LINEAR_LINEAR_HPP
16
17#include <cstddef>
18#include <algorithm>
19#include <iterator>
20
20effc67
TL
21#include <boost/range/begin.hpp>
22#include <boost/range/end.hpp>
23#include <boost/range/size.hpp>
24#include <boost/range/value_type.hpp>
b32b8144 25#include <boost/throw_exception.hpp>
7c673cae
FG
26
27#include <boost/geometry/core/assert.hpp>
28#include <boost/geometry/core/tag.hpp>
29#include <boost/geometry/core/tags.hpp>
30
31#include <boost/geometry/algorithms/detail/overlay/copy_segments.hpp>
32#include <boost/geometry/algorithms/detail/overlay/follow.hpp>
33#include <boost/geometry/algorithms/detail/overlay/inconsistent_turns_exception.hpp>
34#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
35#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
36#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
37
38#include <boost/geometry/algorithms/detail/turns/debug_turn.hpp>
39
f67539c2
TL
40#include <boost/geometry/algorithms/detail/tupled_output.hpp>
41
7c673cae
FG
42#include <boost/geometry/algorithms/convert.hpp>
43#include <boost/geometry/algorithms/not_implemented.hpp>
44
20effc67 45#include <boost/geometry/util/condition.hpp>
7c673cae
FG
46
47namespace boost { namespace geometry
48{
49
50#ifndef DOXYGEN_NO_DETAIL
51namespace detail { namespace overlay
52{
53
54namespace following { namespace linear
55{
56
57
58
59
60// follower for linear/linear geometries set operations
61
62template <typename Turn, typename Operation>
63static inline bool is_entering(Turn const& turn,
64 Operation const& operation)
65{
66 if ( turn.method != method_touch && turn.method != method_touch_interior )
67 {
68 return false;
69 }
70 return operation.operation == operation_intersection;
71}
72
73
74
75template <typename Turn, typename Operation>
76static inline bool is_staying_inside(Turn const& turn,
77 Operation const& operation,
78 bool entered)
79{
80 if ( !entered )
81 {
82 return false;
83 }
84
85 if ( turn.method != method_equal && turn.method != method_collinear )
86 {
87 return false;
88 }
89 return operation.operation == operation_continue;
90}
91
92
93
94template <typename Turn, typename Operation>
95static inline bool is_leaving(Turn const& turn,
96 Operation const& operation,
97 bool entered)
98{
99 if ( !entered )
100 {
101 return false;
102 }
103
104 if ( turn.method != method_touch
105 && turn.method != method_touch_interior
106 && turn.method != method_equal
107 && turn.method != method_collinear )
108 {
109 return false;
110 }
111
112 if ( operation.operation == operation_blocked )
113 {
114 return true;
115 }
116
117 if ( operation.operation != operation_union )
118 {
119 return false;
120 }
121
122 return operation.is_collinear;
123}
124
125
126
127template <typename Turn, typename Operation>
128static inline bool is_isolated_point(Turn const& turn,
129 Operation const& operation,
130 bool entered)
131{
132 if ( entered )
133 {
134 return false;
135 }
136
137 if ( turn.method == method_none )
138 {
139 BOOST_GEOMETRY_ASSERT( operation.operation == operation_continue );
140 return true;
141 }
142
143 if ( turn.method == method_crosses )
144 {
145 return true;
146 }
147
148 if ( turn.method != method_touch && turn.method != method_touch_interior )
149 {
150 return false;
151 }
152
153 if ( operation.operation == operation_blocked )
154 {
155 return true;
156 }
157
158 if ( operation.operation != operation_union )
159 {
160 return false;
161 }
162
163 return !operation.is_collinear;
164}
165
166
167
168
169
f67539c2 170// GeometryOut - linestring or tuple of at least point and linestring
7c673cae
FG
171template
172<
f67539c2 173 typename GeometryOut,
7c673cae
FG
174 typename Linestring,
175 typename Linear,
176 overlay_type OverlayType,
177 bool FollowIsolatedPoints,
178 bool FollowContinueTurns
179>
f67539c2 180class follow_linestring_linear
7c673cae
FG
181{
182protected:
183 // allow spikes (false indicates: do not remove spikes)
184 typedef following::action_selector<OverlayType, false> action;
185
f67539c2
TL
186 typedef geometry::detail::output_geometry_access
187 <
188 GeometryOut, linestring_tag, linestring_tag
189 > linear;
190 typedef geometry::detail::output_geometry_access
191 <
192 GeometryOut, point_tag, linestring_tag
193 > pointlike;
194
7c673cae
FG
195 template
196 <
197 typename TurnIterator,
198 typename TurnOperationIterator,
f67539c2 199 typename LinestringOut,
7c673cae 200 typename SegmentIdentifier,
b32b8144
FG
201 typename OutputIterator,
202 typename SideStrategy
7c673cae
FG
203 >
204 static inline OutputIterator
205 process_turn(TurnIterator it,
206 TurnOperationIterator op_it,
207 bool& entered,
208 std::size_t& enter_count,
209 Linestring const& linestring,
210 LinestringOut& current_piece,
211 SegmentIdentifier& current_segment_id,
b32b8144
FG
212 OutputIterator oit,
213 SideStrategy const& strategy)
7c673cae
FG
214 {
215 // We don't rescale linear/linear
216 detail::no_rescale_policy robust_policy;
217
218 if ( is_entering(*it, *op_it) )
219 {
220 detail::turns::debug_turn(*it, *op_it, "-> Entering");
221
222 entered = true;
223 if ( enter_count == 0 )
224 {
f67539c2
TL
225 action::enter(current_piece,
226 linestring,
7c673cae
FG
227 current_segment_id,
228 op_it->seg_id.segment_index,
f67539c2
TL
229 it->point, *op_it, strategy, robust_policy,
230 linear::get(oit));
7c673cae
FG
231 }
232 ++enter_count;
233 }
234 else if ( is_leaving(*it, *op_it, entered) )
235 {
236 detail::turns::debug_turn(*it, *op_it, "-> Leaving");
237
238 --enter_count;
239 if ( enter_count == 0 )
240 {
241 entered = false;
f67539c2
TL
242 action::leave(current_piece,
243 linestring,
7c673cae
FG
244 current_segment_id,
245 op_it->seg_id.segment_index,
f67539c2
TL
246 it->point, *op_it, strategy, robust_policy,
247 linear::get(oit));
7c673cae
FG
248 }
249 }
20effc67 250 else if ( BOOST_GEOMETRY_CONDITION(FollowIsolatedPoints)
7c673cae
FG
251 && is_isolated_point(*it, *op_it, entered) )
252 {
253 detail::turns::debug_turn(*it, *op_it, "-> Isolated point");
254
f67539c2
TL
255 action::template isolated_point
256 <
257 typename pointlike::type
258 >(it->point, pointlike::get(oit));
7c673cae 259 }
20effc67 260 else if ( BOOST_GEOMETRY_CONDITION(FollowContinueTurns)
7c673cae
FG
261 && is_staying_inside(*it, *op_it, entered) )
262 {
263 detail::turns::debug_turn(*it, *op_it, "-> Staying inside");
264
265 entered = true;
266 }
267 return oit;
268 }
269
270 template
271 <
272 typename SegmentIdentifier,
f67539c2 273 typename LinestringOut,
b32b8144
FG
274 typename OutputIterator,
275 typename SideStrategy
7c673cae
FG
276 >
277 static inline OutputIterator
278 process_end(bool entered,
279 Linestring const& linestring,
280 SegmentIdentifier const& current_segment_id,
281 LinestringOut& current_piece,
b32b8144
FG
282 OutputIterator oit,
283 SideStrategy const& strategy)
7c673cae
FG
284 {
285 if ( action::is_entered(entered) )
286 {
287 // We don't rescale linear/linear
288 detail::no_rescale_policy robust_policy;
289
290 detail::copy_segments::copy_segments_linestring
291 <
292 false, false // do not reverse; do not remove spikes
293 >::apply(linestring,
294 current_segment_id,
295 static_cast<signed_size_type>(boost::size(linestring) - 1),
b32b8144 296 strategy,
7c673cae
FG
297 robust_policy,
298 current_piece);
299 }
300
301 // Output the last one, if applicable
302 if (::boost::size(current_piece) > 1)
303 {
f67539c2 304 *linear::get(oit)++ = current_piece;
7c673cae
FG
305 }
306
307 return oit;
308 }
309
310public:
b32b8144 311 template <typename TurnIterator, typename OutputIterator, typename SideStrategy>
7c673cae
FG
312 static inline OutputIterator
313 apply(Linestring const& linestring, Linear const&,
314 TurnIterator first, TurnIterator beyond,
b32b8144
FG
315 OutputIterator oit,
316 SideStrategy const& strategy)
7c673cae
FG
317 {
318 // Iterate through all intersection points (they are
319 // ordered along the each line)
320
f67539c2 321 typename linear::type current_piece;
7c673cae
FG
322 geometry::segment_identifier current_segment_id(0, -1, -1, -1);
323
324 bool entered = false;
325 std::size_t enter_count = 0;
326
327 for (TurnIterator it = first; it != beyond; ++it)
328 {
329 oit = process_turn(it, boost::begin(it->operations),
330 entered, enter_count,
331 linestring,
332 current_piece, current_segment_id,
b32b8144
FG
333 oit,
334 strategy);
7c673cae
FG
335 }
336
7c673cae
FG
337 if (enter_count != 0)
338 {
1e59de90 339 return oit;
7c673cae 340 }
7c673cae
FG
341
342 return process_end(entered, linestring,
343 current_segment_id, current_piece,
b32b8144
FG
344 oit,
345 strategy);
7c673cae
FG
346 }
347};
348
349
350
351
352template
353<
354 typename LinestringOut,
355 typename MultiLinestring,
356 typename Linear,
357 overlay_type OverlayType,
358 bool FollowIsolatedPoints,
359 bool FollowContinueTurns
360>
f67539c2
TL
361class follow_multilinestring_linear
362 : follow_linestring_linear
7c673cae
FG
363 <
364 LinestringOut,
365 typename boost::range_value<MultiLinestring>::type,
366 Linear,
367 OverlayType,
368 FollowIsolatedPoints,
369 FollowContinueTurns
370 >
371{
372protected:
373 typedef typename boost::range_value<MultiLinestring>::type Linestring;
374
f67539c2 375 typedef follow_linestring_linear
7c673cae
FG
376 <
377 LinestringOut, Linestring, Linear,
378 OverlayType, FollowIsolatedPoints, FollowContinueTurns
379 > Base;
380
381 typedef following::action_selector<OverlayType> action;
382
383 typedef typename boost::range_iterator
384 <
385 MultiLinestring const
386 >::type linestring_iterator;
387
388
389 template <typename OutputIt, overlay_type OT>
390 struct copy_linestrings_in_range
391 {
392 static inline OutputIt
393 apply(linestring_iterator, linestring_iterator, OutputIt oit)
394 {
395 return oit;
396 }
397 };
398
399 template <typename OutputIt>
400 struct copy_linestrings_in_range<OutputIt, overlay_difference>
401 {
402 static inline OutputIt
403 apply(linestring_iterator first, linestring_iterator beyond,
404 OutputIt oit)
405 {
406 for (linestring_iterator ls_it = first; ls_it != beyond; ++ls_it)
407 {
408 LinestringOut line_out;
409 geometry::convert(*ls_it, line_out);
410 *oit++ = line_out;
411 }
412 return oit;
413 }
414 };
415
416 template <typename TurnIterator>
417 static inline signed_size_type get_multi_index(TurnIterator it)
418 {
419 return boost::begin(it->operations)->seg_id.multi_index;
420 }
421
422 class has_other_multi_id
423 {
424 private:
425 signed_size_type m_multi_id;
426
427 public:
428 has_other_multi_id(signed_size_type multi_id)
429 : m_multi_id(multi_id) {}
430
431 template <typename Turn>
432 bool operator()(Turn const& turn) const
433 {
434 return boost::begin(turn.operations)->seg_id.multi_index
435 != m_multi_id;
436 }
437 };
438
439public:
b32b8144 440 template <typename TurnIterator, typename OutputIterator, typename SideStrategy>
7c673cae
FG
441 static inline OutputIterator
442 apply(MultiLinestring const& multilinestring, Linear const& linear,
443 TurnIterator first, TurnIterator beyond,
b32b8144
FG
444 OutputIterator oit,
445 SideStrategy const& strategy)
7c673cae
FG
446 {
447 BOOST_GEOMETRY_ASSERT( first != beyond );
448
449 typedef copy_linestrings_in_range
450 <
451 OutputIterator, OverlayType
452 > copy_linestrings;
453
454 linestring_iterator ls_first = boost::begin(multilinestring);
455 linestring_iterator ls_beyond = boost::end(multilinestring);
456
457 // Iterate through all intersection points (they are
458 // ordered along the each linestring)
459
460 signed_size_type current_multi_id = get_multi_index(first);
461
462 oit = copy_linestrings::apply(ls_first,
463 ls_first + current_multi_id,
464 oit);
465
466 TurnIterator per_ls_next = first;
467 do {
468 TurnIterator per_ls_current = per_ls_next;
469
470 // find turn with different multi-index
471 per_ls_next = std::find_if(per_ls_current, beyond,
472 has_other_multi_id(current_multi_id));
473
474 oit = Base::apply(*(ls_first + current_multi_id),
b32b8144 475 linear, per_ls_current, per_ls_next, oit, strategy);
7c673cae
FG
476
477 signed_size_type next_multi_id = -1;
478 linestring_iterator ls_next = ls_beyond;
479 if ( per_ls_next != beyond )
480 {
481 next_multi_id = get_multi_index(per_ls_next);
482 ls_next = ls_first + next_multi_id;
483 }
484 oit = copy_linestrings::apply(ls_first + current_multi_id + 1,
485 ls_next,
486 oit);
487
488 current_multi_id = next_multi_id;
489 }
490 while ( per_ls_next != beyond );
491
492 return oit;
493 }
494};
495
496
497
498
499
500
501template
502<
503 typename LinestringOut,
504 typename Geometry1,
505 typename Geometry2,
506 overlay_type OverlayType,
507 bool FollowIsolatedPoints,
508 bool FollowContinueTurns,
7c673cae
FG
509 typename TagIn1 = typename tag<Geometry1>::type
510>
511struct follow
f67539c2 512 : not_implemented<Geometry1>
7c673cae
FG
513{};
514
515
516
517template
518<
519 typename LinestringOut,
520 typename Linestring,
521 typename Linear,
522 overlay_type OverlayType,
523 bool FollowIsolatedPoints,
524 bool FollowContinueTurns
525>
526struct follow
527 <
528 LinestringOut, Linestring, Linear,
529 OverlayType, FollowIsolatedPoints, FollowContinueTurns,
f67539c2
TL
530 linestring_tag
531 > : follow_linestring_linear
7c673cae
FG
532 <
533 LinestringOut, Linestring, Linear,
534 OverlayType, FollowIsolatedPoints, FollowContinueTurns
535 >
536{};
537
538
539template
540<
541 typename LinestringOut,
542 typename MultiLinestring,
543 typename Linear,
544 overlay_type OverlayType,
545 bool FollowIsolatedPoints,
546 bool FollowContinueTurns
547>
548struct follow
549 <
550 LinestringOut, MultiLinestring, Linear,
551 OverlayType, FollowIsolatedPoints, FollowContinueTurns,
f67539c2
TL
552 multi_linestring_tag
553 > : follow_multilinestring_linear
7c673cae
FG
554 <
555 LinestringOut, MultiLinestring, Linear,
556 OverlayType, FollowIsolatedPoints, FollowContinueTurns
557 >
558{};
559
560
561
562}} // namespace following::linear
563
564}} // namespace detail::overlay
565#endif // DOXYGEN_NO_DETAIL
566
567}} // namespace boost::geometry
568
569
570#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_LINEAR_LINEAR_HPP