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