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