File indexing completed on 2025-09-15 08:35:18
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef BOOST_GEOMETRY_ALGORITHMS_SYM_DIFFERENCE_HPP
0016 #define BOOST_GEOMETRY_ALGORITHMS_SYM_DIFFERENCE_HPP
0017
0018
0019 #include <iterator>
0020
0021 #include <boost/geometry/core/primary_single_tag.hpp>
0022 #include <boost/geometry/core/tag_cast.hpp>
0023 #include <boost/geometry/algorithms/difference.hpp>
0024 #include <boost/geometry/algorithms/union.hpp>
0025 #include <boost/geometry/geometries/adapted/boost_variant.hpp>
0026 #include <boost/geometry/geometries/multi_polygon.hpp>
0027 #include <boost/geometry/strategies/default_strategy.hpp>
0028 #include <boost/geometry/strategies/detail.hpp>
0029 #include <boost/geometry/strategies/relate/cartesian.hpp>
0030 #include <boost/geometry/strategies/relate/geographic.hpp>
0031 #include <boost/geometry/strategies/relate/spherical.hpp>
0032
0033
0034 namespace boost { namespace geometry
0035 {
0036
0037 #ifndef DOXYGEN_NO_DETAIL
0038 namespace detail { namespace sym_difference
0039 {
0040
0041
0042 template <typename GeometryOut>
0043 struct compute_difference
0044 {
0045 template
0046 <
0047 typename Geometry1,
0048 typename Geometry2,
0049 typename OutputIterator,
0050 typename Strategy
0051 >
0052 static inline OutputIterator apply(Geometry1 const& geometry1,
0053 Geometry2 const& geometry2,
0054 OutputIterator out,
0055 Strategy const& strategy)
0056 {
0057 return geometry::dispatch::intersection_insert
0058 <
0059 Geometry1,
0060 Geometry2,
0061 GeometryOut,
0062 overlay_difference,
0063 geometry::detail::overlay::do_reverse
0064 <
0065 geometry::point_order<Geometry1>::value
0066 >::value,
0067 geometry::detail::overlay::do_reverse
0068 <
0069 geometry::point_order<Geometry2>::value, true
0070 >::value
0071 >::apply(geometry1, geometry2, out, strategy);
0072 }
0073 };
0074
0075
0076
0077 template <typename GeometryOut, typename Geometry1, typename Geometry2>
0078 struct sym_difference_generic
0079 {
0080 template
0081 <
0082 typename OutputIterator,
0083 typename Strategy
0084 >
0085 static inline OutputIterator apply(Geometry1 const& geometry1,
0086 Geometry2 const& geometry2,
0087 OutputIterator out,
0088 Strategy const& strategy)
0089 {
0090 out = compute_difference
0091 <
0092 GeometryOut
0093 >::apply(geometry1, geometry2, out, strategy);
0094
0095 return compute_difference
0096 <
0097 GeometryOut
0098 >::apply(geometry2, geometry1, out, strategy);
0099 }
0100 };
0101
0102
0103 template <typename GeometryOut, typename Areal1, typename Areal2>
0104 struct sym_difference_areal_areal
0105 {
0106 template
0107 <
0108 typename OutputIterator,
0109 typename Strategy
0110 >
0111 static inline OutputIterator apply(Areal1 const& areal1,
0112 Areal2 const& areal2,
0113 OutputIterator out,
0114 Strategy const& strategy)
0115 {
0116 typedef geometry::model::multi_polygon
0117 <
0118 GeometryOut
0119 > helper_geometry_type;
0120
0121 helper_geometry_type diff12, diff21;
0122
0123 std::back_insert_iterator<helper_geometry_type> oit12(diff12);
0124 std::back_insert_iterator<helper_geometry_type> oit21(diff21);
0125
0126 compute_difference
0127 <
0128 GeometryOut
0129 >::apply(areal1, areal2, oit12, strategy);
0130
0131 compute_difference
0132 <
0133 GeometryOut
0134 >::apply(areal2, areal1, oit21, strategy);
0135
0136 return geometry::dispatch::union_insert
0137 <
0138 helper_geometry_type,
0139 helper_geometry_type,
0140 GeometryOut
0141 >::apply(diff12, diff21, out, strategy);
0142 }
0143 };
0144
0145
0146 template
0147 <
0148 typename GeometryOut,
0149 typename SingleTag,
0150 template <typename, typename, typename> class Algorithm
0151 >
0152 struct sym_difference_same_inputs_tupled_output
0153 {
0154 template
0155 <
0156 typename Geometry1,
0157 typename Geometry2,
0158 typename OutputIterator,
0159 typename Strategy
0160 >
0161 static inline OutputIterator apply(Geometry1 const& geometry1,
0162 Geometry2 const& geometry2,
0163 OutputIterator out,
0164 Strategy const& strategy)
0165 {
0166 typedef typename geometry::detail::output_geometry_access
0167 <
0168 GeometryOut, SingleTag, SingleTag
0169 > access;
0170
0171 access::get(out) = Algorithm
0172 <
0173 typename access::type, Geometry1, Geometry2
0174 >::apply(geometry1, geometry2, access::get(out), strategy);
0175
0176 return out;
0177 }
0178 };
0179
0180
0181 template
0182 <
0183 typename GeometryOut,
0184 typename SingleTag1,
0185 typename SingleTag2,
0186 bool Reverse = (geometry::core_dispatch::top_dim<SingleTag1>::value
0187 > geometry::core_dispatch::top_dim<SingleTag2>::value)
0188 >
0189 struct sym_difference_different_inputs_tupled_output
0190 {
0191 template
0192 <
0193 typename Geometry1,
0194 typename Geometry2,
0195 typename OutputIterator,
0196 typename Strategy
0197 >
0198 static inline OutputIterator apply(Geometry1 const& geometry1,
0199 Geometry2 const& geometry2,
0200 OutputIterator out,
0201 Strategy const& strategy)
0202 {
0203 return sym_difference_different_inputs_tupled_output
0204 <
0205 GeometryOut, SingleTag2, SingleTag1
0206 >::apply(geometry2, geometry1, out, strategy);
0207 }
0208 };
0209
0210 template
0211 <
0212 typename GeometryOut,
0213 typename SingleTag1,
0214 typename SingleTag2
0215 >
0216 struct sym_difference_different_inputs_tupled_output
0217 <
0218 GeometryOut, SingleTag1, SingleTag2, false
0219 >
0220 {
0221 template
0222 <
0223 typename Geometry1,
0224 typename Geometry2,
0225 typename OutputIterator,
0226 typename Strategy
0227 >
0228 static inline OutputIterator apply(Geometry1 const& geometry1,
0229 Geometry2 const& geometry2,
0230 OutputIterator out,
0231 Strategy const& strategy)
0232 {
0233 typedef typename geometry::detail::output_geometry_access
0234 <
0235 GeometryOut, SingleTag1, SingleTag1
0236 > access1;
0237 typedef typename geometry::detail::output_geometry_access
0238 <
0239 GeometryOut, SingleTag2, SingleTag2
0240 > access2;
0241
0242 access1::get(out) = compute_difference
0243 <
0244 typename access1::type
0245 >::apply(geometry1, geometry2, access1::get(out), strategy);
0246
0247 access2::get(out) = geometry::detail::convert_to_output
0248 <
0249 Geometry2,
0250 typename access2::type
0251 >::apply(geometry2, access2::get(out));
0252
0253 return out;
0254 }
0255 };
0256
0257
0258 }}
0259 #endif
0260
0261
0262
0263 #ifndef DOXYGEN_NO_DISPATCH
0264 namespace dispatch
0265 {
0266
0267
0268 template
0269 <
0270 typename Geometry1,
0271 typename Geometry2,
0272 typename GeometryOut,
0273 typename TagIn1 = tag_cast_t
0274 <
0275 tag_t<Geometry1>, pointlike_tag, linear_tag, areal_tag
0276 >,
0277 typename TagIn2 = tag_cast_t
0278 <
0279 tag_t<Geometry2>, pointlike_tag, linear_tag, areal_tag
0280 >,
0281 typename TagOut = typename detail::setop_insert_output_tag<GeometryOut>::type
0282 >
0283 struct sym_difference_insert
0284 : detail::sym_difference::sym_difference_generic
0285 <
0286 GeometryOut, Geometry1, Geometry2
0287 >
0288 {};
0289
0290
0291 template
0292 <
0293 typename Areal1,
0294 typename Areal2,
0295 typename GeometryOut,
0296 typename TagOut
0297 >
0298 struct sym_difference_insert
0299 <
0300 Areal1, Areal2, GeometryOut,
0301 areal_tag, areal_tag, TagOut
0302 > : detail::sym_difference::sym_difference_areal_areal
0303 <
0304 GeometryOut, Areal1, Areal2
0305 >
0306 {};
0307
0308
0309
0310 template
0311 <
0312 typename PointLike1,
0313 typename PointLike2,
0314 typename GeometryOut
0315 >
0316 struct sym_difference_insert
0317 <
0318 PointLike1, PointLike2, GeometryOut,
0319 pointlike_tag, pointlike_tag, detail::tupled_output_tag
0320 >
0321 : detail::expect_output<PointLike1, PointLike2, GeometryOut, point_tag>
0322 , detail::sym_difference::sym_difference_same_inputs_tupled_output
0323 <
0324 GeometryOut,
0325 point_tag,
0326 detail::sym_difference::sym_difference_generic
0327 >
0328 {};
0329
0330 template
0331 <
0332 typename Linear1,
0333 typename Linear2,
0334 typename GeometryOut
0335 >
0336 struct sym_difference_insert
0337 <
0338 Linear1, Linear2, GeometryOut,
0339 linear_tag, linear_tag, detail::tupled_output_tag
0340 >
0341 : detail::expect_output<Linear1, Linear2, GeometryOut, linestring_tag>
0342 , detail::sym_difference::sym_difference_same_inputs_tupled_output
0343 <
0344 GeometryOut,
0345 linestring_tag,
0346 detail::sym_difference::sym_difference_generic
0347 >
0348 {};
0349
0350 template
0351 <
0352 typename Areal1,
0353 typename Areal2,
0354 typename GeometryOut
0355 >
0356 struct sym_difference_insert
0357 <
0358 Areal1, Areal2, GeometryOut,
0359 areal_tag, areal_tag, detail::tupled_output_tag
0360 >
0361 : detail::expect_output<Areal1, Areal2, GeometryOut, polygon_tag>
0362 , detail::sym_difference::sym_difference_same_inputs_tupled_output
0363 <
0364 GeometryOut,
0365 polygon_tag,
0366 detail::sym_difference::sym_difference_areal_areal
0367 >
0368 {};
0369
0370 template
0371 <
0372 typename Geometry1,
0373 typename Geometry2,
0374 typename GeometryOut,
0375 typename TagIn1,
0376 typename TagIn2
0377 >
0378 struct sym_difference_insert
0379 <
0380 Geometry1, Geometry2, GeometryOut,
0381 TagIn1, TagIn2, detail::tupled_output_tag
0382 >
0383 : detail::expect_output
0384 <
0385 Geometry1, Geometry2, GeometryOut, primary_single_tag_t<TagIn1>, primary_single_tag_t<TagIn2>
0386 >
0387 , detail::sym_difference::sym_difference_different_inputs_tupled_output
0388 <
0389 GeometryOut, primary_single_tag_t<TagIn1>, primary_single_tag_t<TagIn2>
0390 >
0391 {};
0392
0393
0394 }
0395 #endif
0396
0397
0398
0399 #ifndef DOXYGEN_NO_DETAIL
0400 namespace detail { namespace sym_difference
0401 {
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422 template
0423 <
0424 typename GeometryOut,
0425 typename Geometry1,
0426 typename Geometry2,
0427 typename OutputIterator,
0428 typename Strategy
0429 >
0430 inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,
0431 Geometry2 const& geometry2,
0432 OutputIterator out,
0433 Strategy const& strategy)
0434 {
0435 concepts::check<Geometry1 const>();
0436 concepts::check<Geometry2 const>();
0437
0438 geometry::detail::output_geometry_concept_check<GeometryOut>::apply();
0439
0440 return dispatch::sym_difference_insert
0441 <
0442 Geometry1, Geometry2, GeometryOut
0443 >::apply(geometry1, geometry2, out, strategy);
0444 }
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461 template
0462 <
0463 typename GeometryOut,
0464 typename Geometry1,
0465 typename Geometry2,
0466 typename OutputIterator
0467 >
0468 inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,
0469 Geometry2 const& geometry2, OutputIterator out)
0470 {
0471 typedef typename strategies::relate::services::default_strategy
0472 <
0473 Geometry1, Geometry2
0474 >::type strategy_type;
0475
0476 return sym_difference_insert<GeometryOut>(geometry1, geometry2, out, strategy_type());
0477 }
0478
0479 }}
0480 #endif
0481
0482
0483 namespace resolve_collection
0484 {
0485
0486 template
0487 <
0488 typename Geometry1, typename Geometry2, typename Collection,
0489 typename Tag1 = geometry::tag_t<Geometry1>,
0490 typename Tag2 = geometry::tag_t<Geometry2>,
0491 typename CollectionTag = geometry::tag_t<Collection>
0492 >
0493 struct sym_difference
0494 {
0495 template <typename Strategy>
0496 static void apply(Geometry1 const& geometry1,
0497 Geometry2 const& geometry2,
0498 Collection & output_collection,
0499 Strategy const& strategy)
0500 {
0501 typedef typename geometry::detail::output_geometry_value
0502 <
0503 Collection
0504 >::type single_out;
0505
0506 detail::sym_difference::sym_difference_insert<single_out>(
0507 geometry1, geometry2,
0508 geometry::detail::output_geometry_back_inserter(output_collection),
0509 strategy);
0510 }
0511 };
0512
0513
0514 template <typename Geometry1, typename Geometry2, typename Collection>
0515 struct sym_difference
0516 <
0517 Geometry1, Geometry2, Collection,
0518 geometry_collection_tag, geometry_collection_tag, geometry_collection_tag
0519 >
0520 {
0521 template <typename Strategy>
0522 static void apply(Geometry1 const& geometry1,
0523 Geometry2 const& geometry2,
0524 Collection& output_collection,
0525 Strategy const& strategy)
0526 {
0527 Collection temp1, temp2;
0528 resolve_collection::difference
0529 <
0530 Geometry1, Geometry2, Collection
0531 >::apply(geometry1, geometry2, temp1, strategy);
0532 resolve_collection::difference
0533 <
0534 Geometry2, Geometry1, Collection
0535 >::apply(geometry2, geometry1, temp2, strategy);
0536 resolve_collection::union_
0537 <
0538 Collection, Collection, Collection
0539 >::apply(temp1, temp2, output_collection, strategy);
0540 }
0541 };
0542
0543 template <typename Geometry1, typename Geometry2, typename Collection, typename Tag1>
0544 struct sym_difference
0545 <
0546 Geometry1, Geometry2, Collection,
0547 Tag1, geometry_collection_tag, geometry_collection_tag
0548 >
0549 {
0550 template <typename Strategy>
0551 static void apply(Geometry1 const& geometry1,
0552 Geometry2 const& geometry2,
0553 Collection & output_collection,
0554 Strategy const& strategy)
0555 {
0556 using gc_view_t = geometry::detail::geometry_collection_view<Geometry1>;
0557 sym_difference
0558 <
0559 gc_view_t, Geometry2, Collection
0560 >::apply(gc_view_t(geometry1), geometry2, output_collection, strategy);
0561 }
0562 };
0563
0564 template <typename Geometry1, typename Geometry2, typename Collection, typename Tag2>
0565 struct sym_difference
0566 <
0567 Geometry1, Geometry2, Collection,
0568 geometry_collection_tag, Tag2, geometry_collection_tag
0569 >
0570 {
0571 template <typename Strategy>
0572 static void apply(Geometry1 const& geometry1,
0573 Geometry2 const& geometry2,
0574 Collection & output_collection,
0575 Strategy const& strategy)
0576 {
0577 using gc_view_t = geometry::detail::geometry_collection_view<Geometry2>;
0578 sym_difference
0579 <
0580 Geometry1, gc_view_t, Collection
0581 >::apply(geometry1, gc_view_t(geometry2), output_collection, strategy);
0582 }
0583 };
0584
0585 template <typename Geometry1, typename Geometry2, typename Collection, typename Tag1, typename Tag2>
0586 struct sym_difference
0587 <
0588 Geometry1, Geometry2, Collection,
0589 Tag1, Tag2, geometry_collection_tag
0590 >
0591 {
0592 template <typename Strategy>
0593 static void apply(Geometry1 const& geometry1,
0594 Geometry2 const& geometry2,
0595 Collection & output_collection,
0596 Strategy const& strategy)
0597 {
0598 using gc1_view_t = geometry::detail::geometry_collection_view<Geometry1>;
0599 using gc2_view_t = geometry::detail::geometry_collection_view<Geometry2>;
0600 sym_difference
0601 <
0602 gc1_view_t, gc2_view_t, Collection
0603 >::apply(gc1_view_t(geometry1), gc2_view_t(geometry2), output_collection, strategy);
0604 }
0605 };
0606
0607
0608 }
0609
0610
0611 namespace resolve_strategy
0612 {
0613
0614 template
0615 <
0616 typename Strategy,
0617 bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
0618 >
0619 struct sym_difference
0620 {
0621 template <typename Geometry1, typename Geometry2, typename Collection>
0622 static inline void apply(Geometry1 const& geometry1,
0623 Geometry2 const& geometry2,
0624 Collection & output_collection,
0625 Strategy const& strategy)
0626 {
0627 resolve_collection::sym_difference
0628 <
0629 Geometry1, Geometry2, Collection
0630 >::apply(geometry1, geometry2, output_collection, strategy);
0631 }
0632 };
0633
0634 template <typename Strategy>
0635 struct sym_difference<Strategy, false>
0636 {
0637 template <typename Geometry1, typename Geometry2, typename Collection>
0638 static inline void apply(Geometry1 const& geometry1,
0639 Geometry2 const& geometry2,
0640 Collection & output_collection,
0641 Strategy const& strategy)
0642 {
0643 using strategies::relate::services::strategy_converter;
0644
0645 sym_difference
0646 <
0647 decltype(strategy_converter<Strategy>::get(strategy))
0648 >::apply(geometry1, geometry2, output_collection,
0649 strategy_converter<Strategy>::get(strategy));
0650 }
0651 };
0652
0653 template <>
0654 struct sym_difference<default_strategy, false>
0655 {
0656 template <typename Geometry1, typename Geometry2, typename Collection>
0657 static inline void apply(Geometry1 const& geometry1,
0658 Geometry2 const& geometry2,
0659 Collection & output_collection,
0660 default_strategy)
0661 {
0662 typedef typename strategies::relate::services::default_strategy
0663 <
0664 Geometry1, Geometry2
0665 >::type strategy_type;
0666
0667 sym_difference
0668 <
0669 strategy_type
0670 >::apply(geometry1, geometry2, output_collection, strategy_type());
0671 }
0672 };
0673
0674 }
0675
0676
0677 namespace resolve_dynamic
0678 {
0679
0680 template
0681 <
0682 typename Geometry1, typename Geometry2,
0683 typename Tag1 = geometry::tag_t<Geometry1>,
0684 typename Tag2 = geometry::tag_t<Geometry2>
0685 >
0686 struct sym_difference
0687 {
0688 template <typename Collection, typename Strategy>
0689 static inline void apply(Geometry1 const& geometry1,
0690 Geometry2 const& geometry2,
0691 Collection& output_collection,
0692 Strategy const& strategy)
0693 {
0694 resolve_strategy::sym_difference
0695 <
0696 Strategy
0697 >::apply(geometry1, geometry2, output_collection, strategy);
0698 }
0699 };
0700
0701
0702 template <typename DynamicGeometry1, typename Geometry2, typename Tag2>
0703 struct sym_difference<DynamicGeometry1, Geometry2, dynamic_geometry_tag, Tag2>
0704 {
0705 template <typename Collection, typename Strategy>
0706 static void apply(DynamicGeometry1 const& geometry1, Geometry2 const& geometry2,
0707 Collection& output_collection, Strategy const& strategy)
0708 {
0709 traits::visit<DynamicGeometry1>::apply([&](auto const& g1)
0710 {
0711 resolve_strategy::sym_difference
0712 <
0713 Strategy
0714 >::apply(g1, geometry2, output_collection, strategy);
0715 }, geometry1);
0716 }
0717 };
0718
0719
0720 template <typename Geometry1, typename DynamicGeometry2, typename Tag1>
0721 struct sym_difference<Geometry1, DynamicGeometry2, Tag1, dynamic_geometry_tag>
0722 {
0723 template <typename Collection, typename Strategy>
0724 static void apply(Geometry1 const& geometry1, DynamicGeometry2 const& geometry2,
0725 Collection& output_collection, Strategy const& strategy)
0726 {
0727 traits::visit<DynamicGeometry2>::apply([&](auto const& g2)
0728 {
0729 resolve_strategy::sym_difference
0730 <
0731 Strategy
0732 >::apply(geometry1, g2, output_collection, strategy);
0733 }, geometry2);
0734 }
0735 };
0736
0737
0738 template <typename DynamicGeometry1, typename DynamicGeometry2>
0739 struct sym_difference<DynamicGeometry1, DynamicGeometry2, dynamic_geometry_tag, dynamic_geometry_tag>
0740 {
0741 template <typename Collection, typename Strategy>
0742 static void apply(DynamicGeometry1 const& geometry1, DynamicGeometry2 const& geometry2,
0743 Collection& output_collection, Strategy const& strategy)
0744 {
0745 traits::visit<DynamicGeometry1, DynamicGeometry2>::apply([&](auto const& g1, auto const& g2)
0746 {
0747 resolve_strategy::sym_difference
0748 <
0749 Strategy
0750 >::apply(g1, g2, output_collection, strategy);
0751 }, geometry1, geometry2);
0752 }
0753 };
0754
0755 }
0756
0757
0758
0759
0760
0761
0762
0763
0764
0765
0766
0767
0768
0769
0770
0771
0772
0773
0774
0775 template
0776 <
0777 typename Geometry1,
0778 typename Geometry2,
0779 typename Collection,
0780 typename Strategy
0781 >
0782 inline void sym_difference(Geometry1 const& geometry1,
0783 Geometry2 const& geometry2,
0784 Collection& output_collection,
0785 Strategy const& strategy)
0786 {
0787 resolve_dynamic::sym_difference
0788 <
0789 Geometry1,
0790 Geometry2
0791 >::apply(geometry1, geometry2, output_collection, strategy);
0792 }
0793
0794
0795
0796
0797
0798
0799
0800
0801
0802
0803
0804
0805
0806
0807
0808
0809 template
0810 <
0811 typename Geometry1,
0812 typename Geometry2,
0813 typename Collection
0814 >
0815 inline void sym_difference(Geometry1 const& geometry1,
0816 Geometry2 const& geometry2,
0817 Collection& output_collection)
0818 {
0819 resolve_dynamic::sym_difference
0820 <
0821 Geometry1,
0822 Geometry2
0823 >::apply(geometry1, geometry2, output_collection, default_strategy());
0824 }
0825
0826
0827 }}
0828
0829
0830 #endif