]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/geometry/algorithms/sym_difference.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / geometry / algorithms / sym_difference.hpp
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2
3 // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
4
5 // This file was modified by Oracle on 2015-2021.
6 // Modifications copyright (c) 2015-2021 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_SYM_DIFFERENCE_HPP
16 #define BOOST_GEOMETRY_ALGORITHMS_SYM_DIFFERENCE_HPP
17
18
19 #include <algorithm>
20 #include <iterator>
21 #include <vector>
22
23 #include <boost/variant/apply_visitor.hpp>
24 #include <boost/variant/static_visitor.hpp>
25 #include <boost/variant/variant_fwd.hpp>
26
27 #include <boost/geometry/algorithms/intersection.hpp>
28 #include <boost/geometry/algorithms/union.hpp>
29 #include <boost/geometry/geometries/multi_polygon.hpp>
30 #include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
31 #include <boost/geometry/strategies/default_strategy.hpp>
32 #include <boost/geometry/strategies/detail.hpp>
33 #include <boost/geometry/strategies/relate/cartesian.hpp>
34 #include <boost/geometry/strategies/relate/geographic.hpp>
35 #include <boost/geometry/strategies/relate/spherical.hpp>
36 #include <boost/geometry/util/range.hpp>
37
38
39 namespace boost { namespace geometry
40 {
41
42 #ifndef DOXYGEN_NO_DETAIL
43 namespace detail { namespace sym_difference
44 {
45
46
47 template <typename GeometryOut>
48 struct compute_difference
49 {
50 template
51 <
52 typename Geometry1,
53 typename Geometry2,
54 typename RobustPolicy,
55 typename OutputIterator,
56 typename Strategy
57 >
58 static inline OutputIterator apply(Geometry1 const& geometry1,
59 Geometry2 const& geometry2,
60 RobustPolicy const& robust_policy,
61 OutputIterator out,
62 Strategy const& strategy)
63 {
64 return geometry::dispatch::intersection_insert
65 <
66 Geometry1,
67 Geometry2,
68 GeometryOut,
69 overlay_difference,
70 geometry::detail::overlay::do_reverse
71 <
72 geometry::point_order<Geometry1>::value
73 >::value,
74 geometry::detail::overlay::do_reverse
75 <
76 geometry::point_order<Geometry2>::value, true
77 >::value
78 >::apply(geometry1, geometry2, robust_policy, out, strategy);
79 }
80 };
81
82
83
84 template <typename GeometryOut, typename Geometry1, typename Geometry2>
85 struct sym_difference_generic
86 {
87 template
88 <
89 typename RobustPolicy,
90 typename OutputIterator,
91 typename Strategy
92 >
93 static inline OutputIterator apply(Geometry1 const& geometry1,
94 Geometry2 const& geometry2,
95 RobustPolicy const& robust_policy,
96 OutputIterator out,
97 Strategy const& strategy)
98 {
99 out = compute_difference
100 <
101 GeometryOut
102 >::apply(geometry1, geometry2, robust_policy, out, strategy);
103
104 return compute_difference
105 <
106 GeometryOut
107 >::apply(geometry2, geometry1, robust_policy, out, strategy);
108 }
109 };
110
111
112 template <typename GeometryOut, typename Areal1, typename Areal2>
113 struct sym_difference_areal_areal
114 {
115 template
116 <
117 typename RobustPolicy,
118 typename OutputIterator,
119 typename Strategy
120 >
121 static inline OutputIterator apply(Areal1 const& areal1,
122 Areal2 const& areal2,
123 RobustPolicy const& robust_policy,
124 OutputIterator out,
125 Strategy const& strategy)
126 {
127 typedef geometry::model::multi_polygon
128 <
129 GeometryOut
130 > helper_geometry_type;
131
132 helper_geometry_type diff12, diff21;
133
134 std::back_insert_iterator<helper_geometry_type> oit12(diff12);
135 std::back_insert_iterator<helper_geometry_type> oit21(diff21);
136
137 compute_difference
138 <
139 GeometryOut
140 >::apply(areal1, areal2, robust_policy, oit12, strategy);
141
142 compute_difference
143 <
144 GeometryOut
145 >::apply(areal2, areal1, robust_policy, oit21, strategy);
146
147 return geometry::dispatch::union_insert
148 <
149 helper_geometry_type,
150 helper_geometry_type,
151 GeometryOut
152 >::apply(diff12, diff21, robust_policy, out, strategy);
153 }
154 };
155
156
157 template
158 <
159 typename GeometryOut,
160 typename SingleTag,
161 template <typename, typename, typename> class Algorithm
162 >
163 struct sym_difference_same_inputs_tupled_output
164 {
165 template
166 <
167 typename Geometry1,
168 typename Geometry2,
169 typename RobustPolicy,
170 typename OutputIterator,
171 typename Strategy
172 >
173 static inline OutputIterator apply(Geometry1 const& geometry1,
174 Geometry2 const& geometry2,
175 RobustPolicy const& robust_policy,
176 OutputIterator out,
177 Strategy const& strategy)
178 {
179 typedef typename geometry::detail::output_geometry_access
180 <
181 GeometryOut, SingleTag, SingleTag
182 > access;
183
184 access::get(out) = Algorithm
185 <
186 typename access::type, Geometry1, Geometry2
187 >::apply(geometry1, geometry2, robust_policy, access::get(out), strategy);
188
189 return out;
190 }
191 };
192
193
194 template
195 <
196 typename GeometryOut,
197 typename SingleTag1,
198 typename SingleTag2,
199 bool Reverse = (geometry::core_dispatch::top_dim<SingleTag1>::value
200 > geometry::core_dispatch::top_dim<SingleTag2>::value)
201 >
202 struct sym_difference_different_inputs_tupled_output
203 {
204 template
205 <
206 typename Geometry1,
207 typename Geometry2,
208 typename RobustPolicy,
209 typename OutputIterator,
210 typename Strategy
211 >
212 static inline OutputIterator apply(Geometry1 const& geometry1,
213 Geometry2 const& geometry2,
214 RobustPolicy const& robust_policy,
215 OutputIterator out,
216 Strategy const& strategy)
217 {
218 return sym_difference_different_inputs_tupled_output
219 <
220 GeometryOut, SingleTag2, SingleTag1
221 >::apply(geometry2, geometry1, robust_policy, out, strategy);
222 }
223 };
224
225 template
226 <
227 typename GeometryOut,
228 typename SingleTag1,
229 typename SingleTag2
230 >
231 struct sym_difference_different_inputs_tupled_output
232 <
233 GeometryOut, SingleTag1, SingleTag2, false
234 >
235 {
236 template
237 <
238 typename Geometry1,
239 typename Geometry2,
240 typename RobustPolicy,
241 typename OutputIterator,
242 typename Strategy
243 >
244 static inline OutputIterator apply(Geometry1 const& geometry1,
245 Geometry2 const& geometry2,
246 RobustPolicy const& robust_policy,
247 OutputIterator out,
248 Strategy const& strategy)
249 {
250 typedef typename geometry::detail::output_geometry_access
251 <
252 GeometryOut, SingleTag1, SingleTag1
253 > access1;
254 typedef typename geometry::detail::output_geometry_access
255 <
256 GeometryOut, SingleTag2, SingleTag2
257 > access2;
258
259 access1::get(out) = compute_difference
260 <
261 typename access1::type
262 >::apply(geometry1, geometry2, robust_policy, access1::get(out), strategy);
263
264 access2::get(out) = geometry::detail::convert_to_output
265 <
266 Geometry2,
267 typename access2::type
268 >::apply(geometry2, access2::get(out));
269
270 return out;
271 }
272 };
273
274
275 }} // namespace detail::sym_difference
276 #endif // DOXYGEN_NO_DETAIL
277
278
279
280 #ifndef DOXYGEN_NO_DISPATCH
281 namespace dispatch
282 {
283
284
285 template
286 <
287 typename Geometry1,
288 typename Geometry2,
289 typename GeometryOut,
290 typename TagIn1 = typename geometry::tag_cast
291 <
292 typename tag<Geometry1>::type, pointlike_tag, linear_tag, areal_tag
293 >::type,
294 typename TagIn2 = typename geometry::tag_cast
295 <
296 typename tag<Geometry2>::type, pointlike_tag, linear_tag, areal_tag
297 >::type,
298 typename TagOut = typename detail::setop_insert_output_tag<GeometryOut>::type
299 >
300 struct sym_difference_insert
301 : detail::sym_difference::sym_difference_generic
302 <
303 GeometryOut, Geometry1, Geometry2
304 >
305 {};
306
307
308 template
309 <
310 typename Areal1,
311 typename Areal2,
312 typename GeometryOut,
313 typename TagOut
314 >
315 struct sym_difference_insert
316 <
317 Areal1, Areal2, GeometryOut,
318 areal_tag, areal_tag, TagOut
319 > : detail::sym_difference::sym_difference_areal_areal
320 <
321 GeometryOut, Areal1, Areal2
322 >
323 {};
324
325
326
327 template
328 <
329 typename PointLike1,
330 typename PointLike2,
331 typename GeometryOut
332 >
333 struct sym_difference_insert
334 <
335 PointLike1, PointLike2, GeometryOut,
336 pointlike_tag, pointlike_tag, detail::tupled_output_tag
337 >
338 : detail::expect_output<PointLike1, PointLike2, GeometryOut, point_tag>
339 , detail::sym_difference::sym_difference_same_inputs_tupled_output
340 <
341 GeometryOut,
342 point_tag,
343 detail::sym_difference::sym_difference_generic
344 >
345 {};
346
347 template
348 <
349 typename Linear1,
350 typename Linear2,
351 typename GeometryOut
352 >
353 struct sym_difference_insert
354 <
355 Linear1, Linear2, GeometryOut,
356 linear_tag, linear_tag, detail::tupled_output_tag
357 >
358 : detail::expect_output<Linear1, Linear2, GeometryOut, linestring_tag>
359 , detail::sym_difference::sym_difference_same_inputs_tupled_output
360 <
361 GeometryOut,
362 linestring_tag,
363 detail::sym_difference::sym_difference_generic
364 >
365 {};
366
367 template
368 <
369 typename Areal1,
370 typename Areal2,
371 typename GeometryOut
372 >
373 struct sym_difference_insert
374 <
375 Areal1, Areal2, GeometryOut,
376 areal_tag, areal_tag, detail::tupled_output_tag
377 >
378 : detail::expect_output<Areal1, Areal2, GeometryOut, polygon_tag>
379 , detail::sym_difference::sym_difference_same_inputs_tupled_output
380 <
381 GeometryOut,
382 polygon_tag,
383 detail::sym_difference::sym_difference_areal_areal
384 >
385 {};
386
387 template
388 <
389 typename Geometry1,
390 typename Geometry2,
391 typename GeometryOut,
392 typename TagIn1,
393 typename TagIn2
394 >
395 struct sym_difference_insert
396 <
397 Geometry1, Geometry2, GeometryOut,
398 TagIn1, TagIn2, detail::tupled_output_tag
399 >
400 : detail::expect_output
401 <
402 Geometry1, Geometry2, GeometryOut,
403 typename detail::single_tag_from_base_tag<TagIn1>::type,
404 typename detail::single_tag_from_base_tag<TagIn2>::type
405 >
406 , detail::sym_difference::sym_difference_different_inputs_tupled_output
407 <
408 GeometryOut,
409 typename detail::single_tag_from_base_tag<TagIn1>::type,
410 typename detail::single_tag_from_base_tag<TagIn2>::type
411 >
412 {};
413
414
415 } // namespace dispatch
416 #endif // DOXYGEN_NO_DISPATCH
417
418
419
420 #ifndef DOXYGEN_NO_DETAIL
421 namespace detail { namespace sym_difference
422 {
423
424
425
426 /*!
427 \brief \brief_calc2{symmetric difference} \brief_strategy
428 \ingroup sym_difference
429 \details \details_calc2{symmetric difference, spatial set theoretic symmetric difference (XOR)}
430 \brief_strategy. \details_insert{sym_difference}
431 \tparam GeometryOut output geometry type, must be specified
432 \tparam Geometry1 \tparam_geometry
433 \tparam Geometry2 \tparam_geometry
434 \tparam Strategy \tparam_strategy_overlay
435 \param geometry1 \param_geometry
436 \param geometry2 \param_geometry
437 \param out \param_out{difference}
438 \param strategy \param_strategy{difference}
439 \return \return_out
440
441 \qbk{distinguish,with strategy}
442 */
443 template
444 <
445 typename GeometryOut,
446 typename Geometry1,
447 typename Geometry2,
448 typename OutputIterator,
449 typename Strategy
450 >
451 inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,
452 Geometry2 const& geometry2,
453 OutputIterator out,
454 Strategy const& strategy)
455 {
456 concepts::check<Geometry1 const>();
457 concepts::check<Geometry2 const>();
458 //concepts::check<GeometryOut>();
459 geometry::detail::output_geometry_concept_check<GeometryOut>::apply();
460
461 typedef typename geometry::rescale_overlay_policy_type
462 <
463 Geometry1,
464 Geometry2,
465 typename Strategy::cs_tag
466 >::type rescale_policy_type;
467
468 rescale_policy_type robust_policy
469 = geometry::get_rescale_policy<rescale_policy_type>(
470 geometry1, geometry2, strategy);
471
472 return dispatch::sym_difference_insert
473 <
474 Geometry1, Geometry2, GeometryOut
475 >::apply(geometry1, geometry2, robust_policy, out, strategy);
476 }
477
478
479 /*!
480 \brief \brief_calc2{symmetric difference}
481 \ingroup sym_difference
482 \details \details_calc2{symmetric difference, spatial set theoretic symmetric difference (XOR)}
483 \details_insert{sym_difference}
484 \tparam GeometryOut output geometry type, must be specified
485 \tparam Geometry1 \tparam_geometry
486 \tparam Geometry2 \tparam_geometry
487 \param geometry1 \param_geometry
488 \param geometry2 \param_geometry
489 \param out \param_out{difference}
490 \return \return_out
491
492 */
493 template
494 <
495 typename GeometryOut,
496 typename Geometry1,
497 typename Geometry2,
498 typename OutputIterator
499 >
500 inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,
501 Geometry2 const& geometry2, OutputIterator out)
502 {
503 typedef typename strategies::relate::services::default_strategy
504 <
505 Geometry1, Geometry2
506 >::type strategy_type;
507
508 return sym_difference_insert<GeometryOut>(geometry1, geometry2, out, strategy_type());
509 }
510
511 }} // namespace detail::sym_difference
512 #endif // DOXYGEN_NO_DETAIL
513
514
515 namespace resolve_strategy {
516
517 template
518 <
519 typename Strategy,
520 bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
521 >
522 struct sym_difference
523 {
524 template <typename Geometry1, typename Geometry2, typename Collection>
525 static inline void apply(Geometry1 const& geometry1,
526 Geometry2 const& geometry2,
527 Collection & output_collection,
528 Strategy const& strategy)
529 {
530 typedef typename geometry::detail::output_geometry_value
531 <
532 Collection
533 >::type single_out;
534
535 detail::sym_difference::sym_difference_insert<single_out>(
536 geometry1, geometry2,
537 geometry::detail::output_geometry_back_inserter(output_collection),
538 strategy);
539 }
540 };
541
542 template <typename Strategy>
543 struct sym_difference<Strategy, false>
544 {
545 template <typename Geometry1, typename Geometry2, typename Collection>
546 static inline void apply(Geometry1 const& geometry1,
547 Geometry2 const& geometry2,
548 Collection & output_collection,
549 Strategy const& strategy)
550 {
551 using strategies::relate::services::strategy_converter;
552
553 sym_difference
554 <
555 decltype(strategy_converter<Strategy>::get(strategy))
556 >::apply(geometry1, geometry2, output_collection,
557 strategy_converter<Strategy>::get(strategy));
558 }
559 };
560
561 template <>
562 struct sym_difference<default_strategy, false>
563 {
564 template <typename Geometry1, typename Geometry2, typename Collection>
565 static inline void apply(Geometry1 const& geometry1,
566 Geometry2 const& geometry2,
567 Collection & output_collection,
568 default_strategy)
569 {
570 typedef typename strategies::relate::services::default_strategy
571 <
572 Geometry1, Geometry2
573 >::type strategy_type;
574
575 sym_difference
576 <
577 strategy_type
578 >::apply(geometry1, geometry2, output_collection, strategy_type());
579 }
580 };
581
582 } // resolve_strategy
583
584
585 namespace resolve_variant
586 {
587
588 template <typename Geometry1, typename Geometry2>
589 struct sym_difference
590 {
591 template <typename Collection, typename Strategy>
592 static inline void apply(Geometry1 const& geometry1,
593 Geometry2 const& geometry2,
594 Collection& output_collection,
595 Strategy const& strategy)
596 {
597 resolve_strategy::sym_difference
598 <
599 Strategy
600 >::apply(geometry1, geometry2, output_collection, strategy);
601 }
602 };
603
604
605 template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
606 struct sym_difference<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
607 {
608 template <typename Collection, typename Strategy>
609 struct visitor: static_visitor<>
610 {
611 Geometry2 const& m_geometry2;
612 Collection& m_output_collection;
613 Strategy const& m_strategy;
614
615 visitor(Geometry2 const& geometry2,
616 Collection& output_collection,
617 Strategy const& strategy)
618 : m_geometry2(geometry2)
619 , m_output_collection(output_collection)
620 , m_strategy(strategy)
621 {}
622
623 template <typename Geometry1>
624 void operator()(Geometry1 const& geometry1) const
625 {
626 sym_difference
627 <
628 Geometry1,
629 Geometry2
630 >::apply(geometry1, m_geometry2, m_output_collection, m_strategy);
631 }
632 };
633
634 template <typename Collection, typename Strategy>
635 static inline void
636 apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
637 Geometry2 const& geometry2,
638 Collection& output_collection,
639 Strategy const& strategy)
640 {
641 boost::apply_visitor(visitor<Collection, Strategy>(geometry2,
642 output_collection,
643 strategy),
644 geometry1);
645 }
646 };
647
648
649 template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
650 struct sym_difference<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
651 {
652 template <typename Collection, typename Strategy>
653 struct visitor: static_visitor<>
654 {
655 Geometry1 const& m_geometry1;
656 Collection& m_output_collection;
657 Strategy const& m_strategy;
658
659 visitor(Geometry1 const& geometry1,
660 Collection& output_collection,
661 Strategy const& strategy)
662 : m_geometry1(geometry1)
663 , m_output_collection(output_collection)
664 , m_strategy(strategy)
665 {}
666
667 template <typename Geometry2>
668 void operator()(Geometry2 const& geometry2) const
669 {
670 sym_difference
671 <
672 Geometry1,
673 Geometry2
674 >::apply(m_geometry1, geometry2, m_output_collection, m_strategy);
675 }
676 };
677
678 template <typename Collection, typename Strategy>
679 static inline void
680 apply(Geometry1 const& geometry1,
681 variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
682 Collection& output_collection,
683 Strategy const& strategy)
684 {
685 boost::apply_visitor(visitor<Collection, Strategy>(geometry1,
686 output_collection,
687 strategy),
688 geometry2);
689 }
690 };
691
692
693 template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
694 struct sym_difference<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
695 {
696 template <typename Collection, typename Strategy>
697 struct visitor: static_visitor<>
698 {
699 Collection& m_output_collection;
700 Strategy const& m_strategy;
701
702 visitor(Collection& output_collection, Strategy const& strategy)
703 : m_output_collection(output_collection)
704 , m_strategy(strategy)
705 {}
706
707 template <typename Geometry1, typename Geometry2>
708 void operator()(Geometry1 const& geometry1,
709 Geometry2 const& geometry2) const
710 {
711 sym_difference
712 <
713 Geometry1,
714 Geometry2
715 >::apply(geometry1, geometry2, m_output_collection, m_strategy);
716 }
717 };
718
719 template <typename Collection, typename Strategy>
720 static inline void
721 apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
722 variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
723 Collection& output_collection,
724 Strategy const& strategy)
725 {
726 boost::apply_visitor(visitor<Collection, Strategy>(output_collection,
727 strategy),
728 geometry1, geometry2);
729 }
730 };
731
732 } // namespace resolve_variant
733
734
735 /*!
736 \brief \brief_calc2{symmetric difference}
737 \ingroup sym_difference
738 \details \details_calc2{symmetric difference, spatial set theoretic symmetric difference (XOR)}.
739 \tparam Geometry1 \tparam_geometry
740 \tparam Geometry2 \tparam_geometry
741 \tparam Collection output collection, either a multi-geometry,
742 or a std::vector<Geometry> / std::deque<Geometry> etc
743 \tparam Strategy \tparam_strategy{Sym_difference}
744 \param geometry1 \param_geometry
745 \param geometry2 \param_geometry
746 \param output_collection the output collection
747 \param strategy \param_strategy{sym_difference}
748
749 \qbk{distinguish,with strategy}
750 \qbk{[include reference/algorithms/sym_difference.qbk]}
751 */
752 template
753 <
754 typename Geometry1,
755 typename Geometry2,
756 typename Collection,
757 typename Strategy
758 >
759 inline void sym_difference(Geometry1 const& geometry1,
760 Geometry2 const& geometry2,
761 Collection& output_collection,
762 Strategy const& strategy)
763 {
764 resolve_variant::sym_difference
765 <
766 Geometry1,
767 Geometry2
768 >::apply(geometry1, geometry2, output_collection, strategy);
769 }
770
771
772 /*!
773 \brief \brief_calc2{symmetric difference}
774 \ingroup sym_difference
775 \details \details_calc2{symmetric difference, spatial set theoretic symmetric difference (XOR)}.
776 \tparam Geometry1 \tparam_geometry
777 \tparam Geometry2 \tparam_geometry
778 \tparam Collection output collection, either a multi-geometry,
779 or a std::vector<Geometry> / std::deque<Geometry> etc
780 \param geometry1 \param_geometry
781 \param geometry2 \param_geometry
782 \param output_collection the output collection
783
784 \qbk{[include reference/algorithms/sym_difference.qbk]}
785 */
786 template
787 <
788 typename Geometry1,
789 typename Geometry2,
790 typename Collection
791 >
792 inline void sym_difference(Geometry1 const& geometry1,
793 Geometry2 const& geometry2,
794 Collection& output_collection)
795 {
796 resolve_variant::sym_difference
797 <
798 Geometry1,
799 Geometry2
800 >::apply(geometry1, geometry2, output_collection, default_strategy());
801 }
802
803
804 }} // namespace boost::geometry
805
806
807 #endif // BOOST_GEOMETRY_ALGORITHMS_SYM_DIFFERENCE_HPP