File indexing completed on 2025-01-18 09:35:20
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef BOOST_GEOMETRY_ALGORITHMS_DIFFERENCE_HPP
0015 #define BOOST_GEOMETRY_ALGORITHMS_DIFFERENCE_HPP
0016
0017
0018 #include <boost/geometry/algorithms/detail/gc_make_rtree.hpp>
0019 #include <boost/geometry/algorithms/detail/intersection/gc.hpp>
0020 #include <boost/geometry/algorithms/detail/intersection/multi.hpp>
0021 #include <boost/geometry/algorithms/detail/overlay/intersection_insert.hpp>
0022 #include <boost/geometry/algorithms/detail/visit.hpp>
0023 #include <boost/geometry/core/geometry_types.hpp>
0024 #include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
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 #include <boost/geometry/util/sequence.hpp>
0032 #include <boost/geometry/views/detail/geometry_collection_view.hpp>
0033
0034
0035 namespace boost { namespace geometry
0036 {
0037
0038 #ifndef DOXYGEN_NO_DETAIL
0039 namespace detail { namespace difference
0040 {
0041
0042
0043
0044 template <typename Geometry1, typename Geometry2>
0045 using is_subtractable_t = util::bool_constant
0046 <
0047 (geometry::topological_dimension<Geometry1>::value
0048 <= geometry::topological_dimension<Geometry2>::value)
0049 >;
0050
0051
0052 template
0053 <
0054 typename Geometry1,
0055 typename Geometry2,
0056 typename SingleOut,
0057 typename OutTag = typename detail::setop_insert_output_tag<SingleOut>::type,
0058 bool ReturnGeometry1 = (! is_subtractable_t<Geometry1, Geometry2>::value)
0059 >
0060 struct call_intersection_insert
0061 {
0062 template
0063 <
0064 typename OutputIterator,
0065 typename RobustPolicy,
0066 typename Strategy
0067 >
0068 static inline OutputIterator apply(Geometry1 const& geometry1,
0069 Geometry2 const& geometry2,
0070 RobustPolicy const& robust_policy,
0071 OutputIterator out,
0072 Strategy const& strategy)
0073 {
0074 return geometry::dispatch::intersection_insert
0075 <
0076 Geometry1, Geometry2,
0077 SingleOut,
0078 overlay_difference,
0079 geometry::detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
0080 geometry::detail::overlay::do_reverse<geometry::point_order<Geometry2>::value, true>::value
0081 >::apply(geometry1, geometry2, robust_policy, out, strategy);
0082 }
0083 };
0084
0085
0086 template <typename Geometry1, typename Geometry2, typename SingleOut, typename OutTag>
0087 struct call_intersection_insert<Geometry1, Geometry2, SingleOut, OutTag, true>
0088 {
0089 template <typename OutputIterator, typename RobustPolicy, typename Strategy>
0090 static inline OutputIterator apply(Geometry1 const& geometry1,
0091 Geometry2 const& ,
0092 RobustPolicy const& ,
0093 OutputIterator out,
0094 Strategy const& )
0095 {
0096 return geometry::detail::convert_to_output
0097 <
0098 Geometry1,
0099 SingleOut
0100 >::apply(geometry1, out);
0101 }
0102 };
0103
0104
0105 template
0106 <
0107 typename Geometry1,
0108 typename Geometry2,
0109 typename SingleOut
0110 >
0111 struct call_intersection_insert_tupled_base
0112 {
0113 typedef typename geometry::detail::single_tag_from_base_tag
0114 <
0115 typename geometry::tag_cast
0116 <
0117 typename geometry::tag<Geometry1>::type,
0118 pointlike_tag, linear_tag, areal_tag
0119 >::type
0120 >::type single_tag;
0121
0122 typedef detail::expect_output
0123 <
0124 Geometry1, Geometry2, SingleOut, single_tag
0125 > expect_check;
0126
0127 typedef typename geometry::detail::output_geometry_access
0128 <
0129 SingleOut, single_tag, single_tag
0130 > access;
0131 };
0132
0133 template
0134 <
0135 typename Geometry1,
0136 typename Geometry2,
0137 typename SingleOut
0138 >
0139 struct call_intersection_insert
0140 <
0141 Geometry1, Geometry2, SingleOut,
0142 detail::tupled_output_tag,
0143 false
0144 >
0145 : call_intersection_insert_tupled_base<Geometry1, Geometry2, SingleOut>
0146 {
0147 typedef call_intersection_insert_tupled_base<Geometry1, Geometry2, SingleOut> base_t;
0148
0149 template
0150 <
0151 typename OutputIterator,
0152 typename RobustPolicy,
0153 typename Strategy
0154 >
0155 static inline OutputIterator apply(Geometry1 const& geometry1,
0156 Geometry2 const& geometry2,
0157 RobustPolicy const& robust_policy,
0158 OutputIterator out,
0159 Strategy const& strategy)
0160 {
0161 base_t::access::get(out) = call_intersection_insert
0162 <
0163 Geometry1, Geometry2,
0164 typename base_t::access::type
0165 >::apply(geometry1, geometry2, robust_policy,
0166 base_t::access::get(out), strategy);
0167
0168 return out;
0169 }
0170 };
0171
0172 template
0173 <
0174 typename Geometry1,
0175 typename Geometry2,
0176 typename SingleOut
0177 >
0178 struct call_intersection_insert
0179 <
0180 Geometry1, Geometry2, SingleOut,
0181 detail::tupled_output_tag,
0182 true
0183 >
0184 : call_intersection_insert_tupled_base<Geometry1, Geometry2, SingleOut>
0185 {
0186 typedef call_intersection_insert_tupled_base<Geometry1, Geometry2, SingleOut> base_t;
0187
0188 template
0189 <
0190 typename OutputIterator,
0191 typename RobustPolicy,
0192 typename Strategy
0193 >
0194 static inline OutputIterator apply(Geometry1 const& geometry1,
0195 Geometry2 const& ,
0196 RobustPolicy const& ,
0197 OutputIterator out,
0198 Strategy const& )
0199 {
0200 base_t::access::get(out) = geometry::detail::convert_to_output
0201 <
0202 Geometry1,
0203 typename base_t::access::type
0204 >::apply(geometry1, base_t::access::get(out));
0205
0206 return out;
0207 }
0208 };
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229 template
0230 <
0231 typename GeometryOut,
0232 typename Geometry1,
0233 typename Geometry2,
0234 typename OutputIterator,
0235 typename Strategy
0236 >
0237 inline OutputIterator difference_insert(Geometry1 const& geometry1,
0238 Geometry2 const& geometry2,
0239 OutputIterator out,
0240 Strategy const& strategy)
0241 {
0242 concepts::check<Geometry1 const>();
0243 concepts::check<Geometry2 const>();
0244
0245 geometry::detail::output_geometry_concept_check<GeometryOut>::apply();
0246
0247 typedef typename geometry::rescale_overlay_policy_type
0248 <
0249 Geometry1,
0250 Geometry2,
0251 typename Strategy::cs_tag
0252 >::type rescale_policy_type;
0253
0254 rescale_policy_type robust_policy
0255 = geometry::get_rescale_policy<rescale_policy_type>(
0256 geometry1, geometry2, strategy);
0257
0258 return geometry::detail::difference::call_intersection_insert
0259 <
0260 Geometry1, Geometry2, GeometryOut
0261 >::apply(geometry1, geometry2, robust_policy, out, strategy);
0262 }
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280 template
0281 <
0282 typename GeometryOut,
0283 typename Geometry1,
0284 typename Geometry2,
0285 typename OutputIterator
0286 >
0287 inline OutputIterator difference_insert(Geometry1 const& geometry1,
0288 Geometry2 const& geometry2,
0289 OutputIterator out)
0290 {
0291 typedef typename strategies::relate::services::default_strategy
0292 <
0293 Geometry1,
0294 Geometry2
0295 >::type strategy_type;
0296
0297 return difference_insert<GeometryOut>(geometry1, geometry2, out,
0298 strategy_type());
0299 }
0300
0301
0302 template
0303 <
0304 typename Geometry, typename Collection,
0305 typename CastedTag = typename geometry::tag_cast
0306 <
0307 typename geometry::tag<Geometry>::type,
0308 pointlike_tag, linear_tag, areal_tag
0309 >::type
0310 >
0311 struct multi_output_type
0312 {
0313 BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
0314 "Not implemented this Geometry type.",
0315 Geometry, CastedTag);
0316 };
0317
0318 template <typename Geometry, typename Collection>
0319 struct multi_output_type<Geometry, Collection, pointlike_tag>
0320 {
0321 using type = typename util::sequence_find_if
0322 <
0323 typename traits::geometry_types<Collection>::type,
0324 util::is_multi_point
0325 >::type;
0326 };
0327
0328 template <typename Geometry, typename Collection>
0329 struct multi_output_type<Geometry, Collection, linear_tag>
0330 {
0331 using type = typename util::sequence_find_if
0332 <
0333 typename traits::geometry_types<Collection>::type,
0334 util::is_multi_linestring
0335 >::type;
0336 };
0337
0338 template <typename Geometry, typename Collection>
0339 struct multi_output_type<Geometry, Collection, areal_tag>
0340 {
0341 using type = typename util::sequence_find_if
0342 <
0343 typename traits::geometry_types<Collection>::type,
0344 util::is_multi_polygon
0345 >::type;
0346 };
0347
0348
0349 }}
0350 #endif
0351
0352
0353 namespace resolve_collection
0354 {
0355
0356
0357 template
0358 <
0359 typename Geometry1, typename Geometry2, typename Collection,
0360 typename Tag1 = typename geometry::tag<Geometry1>::type,
0361 typename Tag2 = typename geometry::tag<Geometry2>::type,
0362 typename CollectionTag = typename geometry::tag<Collection>::type
0363 >
0364 struct difference
0365 {
0366 template <typename Strategy>
0367 static void apply(Geometry1 const& geometry1,
0368 Geometry2 const& geometry2,
0369 Collection & output_collection,
0370 Strategy const& strategy)
0371 {
0372 using single_out = typename geometry::detail::output_geometry_value
0373 <
0374 Collection
0375 >::type;
0376
0377 detail::difference::difference_insert<single_out>(
0378 geometry1, geometry2,
0379 geometry::detail::output_geometry_back_inserter(output_collection),
0380 strategy);
0381 }
0382 };
0383
0384 template <typename Geometry1, typename Geometry2, typename Collection>
0385 struct difference
0386 <
0387 Geometry1, Geometry2, Collection,
0388 geometry_collection_tag, geometry_collection_tag, geometry_collection_tag
0389 >
0390 {
0391 template <typename Strategy>
0392 static void apply(Geometry1 const& geometry1,
0393 Geometry2 const& geometry2,
0394 Collection& output_collection,
0395 Strategy const& strategy)
0396 {
0397 auto const rtree2 = detail::gc_make_rtree_iterators(geometry2, strategy);
0398 detail::visit_breadth_first([&](auto const& g1)
0399 {
0400
0401 typename detail::difference::multi_output_type
0402 <
0403 util::remove_cref_t<decltype(g1)>, Collection
0404 >::type out;
0405
0406 g1_minus_gc2(g1, rtree2, out, strategy);
0407
0408 detail::intersection::gc_move_multi_back(output_collection, out);
0409
0410 return true;
0411 }, geometry1);
0412 }
0413
0414 private:
0415
0416 template <typename G1, typename Rtree2, typename MultiOut, typename Strategy>
0417 static void g1_minus_gc2(G1 const& g1, Rtree2 const& rtree2, MultiOut& out, Strategy const& strategy)
0418 {
0419 {
0420 using single_out_t = typename geometry::detail::output_geometry_value<MultiOut>::type;
0421 auto out_it = geometry::detail::output_geometry_back_inserter(out);
0422 geometry::detail::convert_to_output<G1, single_out_t>::apply(g1, out_it);
0423 }
0424
0425 using box1_t = detail::gc_make_rtree_box_t<G1>;
0426 box1_t b1 = geometry::return_envelope<box1_t>(g1, strategy);
0427 detail::expand_by_epsilon(b1);
0428
0429 for (auto qit = rtree2.qbegin(index::intersects(b1)); qit != rtree2.qend(); ++qit)
0430 {
0431 traits::iter_visit<Geometry2>::apply([&](auto const& g2)
0432 {
0433 multi_out_minus_g2(out, g2, strategy);
0434 }, qit->second);
0435
0436 if (boost::empty(out))
0437 {
0438 return;
0439 }
0440 }
0441 }
0442
0443 template
0444 <
0445 typename MultiOut, typename G2, typename Strategy,
0446 std::enable_if_t<detail::difference::is_subtractable_t<MultiOut, G2>::value, int> = 0
0447 >
0448 static void multi_out_minus_g2(MultiOut& out, G2 const& g2, Strategy const& strategy)
0449 {
0450 MultiOut result;
0451 difference<MultiOut, G2, MultiOut>::apply(out, g2, result, strategy);
0452 out = std::move(result);
0453 }
0454
0455 template
0456 <
0457 typename MultiOut, typename G2, typename Strategy,
0458 std::enable_if_t<(! detail::difference::is_subtractable_t<MultiOut, G2>::value), int> = 0
0459 >
0460 static void multi_out_minus_g2(MultiOut& , G2 const& , Strategy const& )
0461 {}
0462 };
0463
0464
0465 template <typename Geometry1, typename Geometry2, typename Collection, typename Tag1>
0466 struct difference
0467 <
0468 Geometry1, Geometry2, Collection,
0469 Tag1, geometry_collection_tag, geometry_collection_tag
0470 >
0471 {
0472 template <typename Strategy>
0473 static void apply(Geometry1 const& geometry1,
0474 Geometry2 const& geometry2,
0475 Collection & output_collection,
0476 Strategy const& strategy)
0477 {
0478 using gc_view_t = geometry::detail::geometry_collection_view<Geometry1>;
0479 difference
0480 <
0481 gc_view_t, Geometry2, Collection
0482 >::apply(gc_view_t(geometry1), geometry2, output_collection, strategy);
0483 }
0484 };
0485
0486 template <typename Geometry1, typename Geometry2, typename Collection, typename Tag2>
0487 struct difference
0488 <
0489 Geometry1, Geometry2, Collection,
0490 geometry_collection_tag, Tag2, geometry_collection_tag
0491 >
0492 {
0493 template <typename Strategy>
0494 static void apply(Geometry1 const& geometry1,
0495 Geometry2 const& geometry2,
0496 Collection & output_collection,
0497 Strategy const& strategy)
0498 {
0499 using gc_view_t = geometry::detail::geometry_collection_view<Geometry2>;
0500 difference
0501 <
0502 Geometry1, gc_view_t, Collection
0503 >::apply(geometry1, gc_view_t(geometry2), output_collection, strategy);
0504 }
0505 };
0506
0507 template <typename Geometry1, typename Geometry2, typename Collection, typename Tag1, typename Tag2>
0508 struct difference
0509 <
0510 Geometry1, Geometry2, Collection,
0511 Tag1, Tag2, geometry_collection_tag
0512 >
0513 {
0514 template <typename Strategy>
0515 static void apply(Geometry1 const& geometry1,
0516 Geometry2 const& geometry2,
0517 Collection & output_collection,
0518 Strategy const& strategy)
0519 {
0520 using gc1_view_t = geometry::detail::geometry_collection_view<Geometry1>;
0521 using gc2_view_t = geometry::detail::geometry_collection_view<Geometry2>;
0522 difference
0523 <
0524 gc1_view_t, gc2_view_t, Collection
0525 >::apply(gc1_view_t(geometry1), gc2_view_t(geometry2), output_collection, strategy);
0526 }
0527 };
0528
0529
0530 }
0531
0532
0533 namespace resolve_strategy {
0534
0535 template
0536 <
0537 typename Strategy,
0538 bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
0539 >
0540 struct difference
0541 {
0542 template <typename Geometry1, typename Geometry2, typename Collection>
0543 static inline void apply(Geometry1 const& geometry1,
0544 Geometry2 const& geometry2,
0545 Collection & output_collection,
0546 Strategy const& strategy)
0547 {
0548 resolve_collection::difference
0549 <
0550 Geometry1, Geometry2, Collection
0551 >::apply(geometry1, geometry2, output_collection, strategy);
0552 }
0553 };
0554
0555 template <typename Strategy>
0556 struct difference<Strategy, false>
0557 {
0558 template <typename Geometry1, typename Geometry2, typename Collection>
0559 static inline void apply(Geometry1 const& geometry1,
0560 Geometry2 const& geometry2,
0561 Collection & output_collection,
0562 Strategy const& strategy)
0563 {
0564 using strategies::relate::services::strategy_converter;
0565
0566 difference
0567 <
0568 decltype(strategy_converter<Strategy>::get(strategy))
0569 >::apply(geometry1, geometry2, output_collection,
0570 strategy_converter<Strategy>::get(strategy));
0571 }
0572 };
0573
0574 template <>
0575 struct difference<default_strategy, false>
0576 {
0577 template <typename Geometry1, typename Geometry2, typename Collection>
0578 static inline void apply(Geometry1 const& geometry1,
0579 Geometry2 const& geometry2,
0580 Collection & output_collection,
0581 default_strategy)
0582 {
0583 typedef typename strategies::relate::services::default_strategy
0584 <
0585 Geometry1,
0586 Geometry2
0587 >::type strategy_type;
0588
0589 difference
0590 <
0591 strategy_type
0592 >::apply(geometry1, geometry2, output_collection, strategy_type());
0593 }
0594 };
0595
0596 }
0597
0598
0599 namespace resolve_dynamic
0600 {
0601
0602 template
0603 <
0604 typename Geometry1, typename Geometry2,
0605 typename Tag1 = typename geometry::tag<Geometry1>::type,
0606 typename Tag2 = typename geometry::tag<Geometry2>::type
0607 >
0608 struct difference
0609 {
0610 template <typename Collection, typename Strategy>
0611 static void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
0612 Collection& output_collection, Strategy const& strategy)
0613 {
0614 resolve_strategy::difference
0615 <
0616 Strategy
0617 >::apply(geometry1, geometry2, output_collection, strategy);
0618 }
0619 };
0620
0621 template <typename DynamicGeometry1, typename Geometry2, typename Tag2>
0622 struct difference<DynamicGeometry1, Geometry2, dynamic_geometry_tag, Tag2>
0623 {
0624 template <typename Collection, typename Strategy>
0625 static void apply(DynamicGeometry1 const& geometry1, Geometry2 const& geometry2,
0626 Collection& output_collection, Strategy const& strategy)
0627 {
0628 traits::visit<DynamicGeometry1>::apply([&](auto const& g1)
0629 {
0630 resolve_strategy::difference
0631 <
0632 Strategy
0633 >::apply(g1, geometry2, output_collection, strategy);
0634 }, geometry1);
0635 }
0636 };
0637
0638 template <typename Geometry1, typename DynamicGeometry2, typename Tag1>
0639 struct difference<Geometry1, DynamicGeometry2, Tag1, dynamic_geometry_tag>
0640 {
0641 template <typename Collection, typename Strategy>
0642 static void apply(Geometry1 const& geometry1, DynamicGeometry2 const& geometry2,
0643 Collection& output_collection, Strategy const& strategy)
0644 {
0645 traits::visit<DynamicGeometry2>::apply([&](auto const& g2)
0646 {
0647 resolve_strategy::difference
0648 <
0649 Strategy
0650 >::apply(geometry1, g2, output_collection, strategy);
0651 }, geometry2);
0652 }
0653 };
0654
0655 template <typename DynamicGeometry1, typename DynamicGeometry2>
0656 struct difference<DynamicGeometry1, DynamicGeometry2, dynamic_geometry_tag, dynamic_geometry_tag>
0657 {
0658 template <typename Collection, typename Strategy>
0659 static void apply(DynamicGeometry1 const& geometry1, DynamicGeometry2 const& geometry2,
0660 Collection& output_collection, Strategy const& strategy)
0661 {
0662 traits::visit<DynamicGeometry1, DynamicGeometry2>::apply([&](auto const& g1, auto const& g2)
0663 {
0664 resolve_strategy::difference
0665 <
0666 Strategy
0667 >::apply(g1, g2, output_collection, strategy);
0668 }, geometry1, geometry2);
0669 }
0670 };
0671
0672 }
0673
0674
0675
0676
0677
0678
0679
0680
0681
0682
0683
0684
0685
0686
0687
0688
0689
0690
0691 template
0692 <
0693 typename Geometry1,
0694 typename Geometry2,
0695 typename Collection,
0696 typename Strategy
0697 >
0698 inline void difference(Geometry1 const& geometry1,
0699 Geometry2 const& geometry2,
0700 Collection& output_collection,
0701 Strategy const& strategy)
0702 {
0703 resolve_dynamic::difference
0704 <
0705 Geometry1,
0706 Geometry2
0707 >::apply(geometry1, geometry2, output_collection, strategy);
0708 }
0709
0710
0711
0712
0713
0714
0715
0716
0717
0718
0719
0720
0721
0722
0723
0724 template
0725 <
0726 typename Geometry1,
0727 typename Geometry2,
0728 typename Collection
0729 >
0730 inline void difference(Geometry1 const& geometry1,
0731 Geometry2 const& geometry2,
0732 Collection& output_collection)
0733 {
0734 resolve_dynamic::difference
0735 <
0736 Geometry1,
0737 Geometry2
0738 >::apply(geometry1, geometry2, output_collection, default_strategy());
0739 }
0740
0741
0742 }}
0743
0744
0745 #endif