difference.hpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
  3. // This file was modified by Oracle on 2017-2023.
  4. // Modifications copyright (c) 2017-2023, Oracle and/or its affiliates.
  5. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
  6. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  7. // Use, modification and distribution is subject to the Boost Software License,
  8. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. #ifndef BOOST_GEOMETRY_ALGORITHMS_DIFFERENCE_HPP
  11. #define BOOST_GEOMETRY_ALGORITHMS_DIFFERENCE_HPP
  12. #include <boost/geometry/algorithms/detail/gc_make_rtree.hpp>
  13. #include <boost/geometry/algorithms/detail/intersection/gc.hpp>
  14. #include <boost/geometry/algorithms/detail/intersection/multi.hpp>
  15. #include <boost/geometry/algorithms/detail/overlay/intersection_insert.hpp>
  16. #include <boost/geometry/algorithms/detail/visit.hpp>
  17. #include <boost/geometry/core/geometry_types.hpp>
  18. #include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
  19. #include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
  20. #include <boost/geometry/strategies/default_strategy.hpp>
  21. #include <boost/geometry/strategies/detail.hpp>
  22. #include <boost/geometry/strategies/relate/cartesian.hpp>
  23. #include <boost/geometry/strategies/relate/geographic.hpp>
  24. #include <boost/geometry/strategies/relate/spherical.hpp>
  25. #include <boost/geometry/util/sequence.hpp>
  26. #include <boost/geometry/views/detail/geometry_collection_view.hpp>
  27. namespace boost { namespace geometry
  28. {
  29. #ifndef DOXYGEN_NO_DETAIL
  30. namespace detail { namespace difference
  31. {
  32. // True if the result of difference can be different than Geometry1
  33. template <typename Geometry1, typename Geometry2>
  34. using is_subtractable_t = util::bool_constant
  35. <
  36. (geometry::topological_dimension<Geometry1>::value
  37. <= geometry::topological_dimension<Geometry2>::value)
  38. >;
  39. template
  40. <
  41. typename Geometry1,
  42. typename Geometry2,
  43. typename SingleOut,
  44. typename OutTag = typename detail::setop_insert_output_tag<SingleOut>::type,
  45. bool ReturnGeometry1 = (! is_subtractable_t<Geometry1, Geometry2>::value)
  46. >
  47. struct call_intersection_insert
  48. {
  49. template
  50. <
  51. typename OutputIterator,
  52. typename RobustPolicy,
  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, Geometry2,
  64. SingleOut,
  65. overlay_difference,
  66. geometry::detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
  67. geometry::detail::overlay::do_reverse<geometry::point_order<Geometry2>::value, true>::value
  68. >::apply(geometry1, geometry2, robust_policy, out, strategy);
  69. }
  70. };
  71. template <typename Geometry1, typename Geometry2, typename SingleOut, typename OutTag>
  72. struct call_intersection_insert<Geometry1, Geometry2, SingleOut, OutTag, true>
  73. {
  74. template <typename OutputIterator, typename RobustPolicy, typename Strategy>
  75. static inline OutputIterator apply(Geometry1 const& geometry1,
  76. Geometry2 const& ,
  77. RobustPolicy const& ,
  78. OutputIterator out,
  79. Strategy const& )
  80. {
  81. return geometry::detail::convert_to_output
  82. <
  83. Geometry1,
  84. SingleOut
  85. >::apply(geometry1, out);
  86. }
  87. };
  88. template
  89. <
  90. typename Geometry1,
  91. typename Geometry2,
  92. typename SingleOut
  93. >
  94. struct call_intersection_insert_tupled_base
  95. {
  96. typedef typename geometry::detail::single_tag_from_base_tag
  97. <
  98. typename geometry::tag_cast
  99. <
  100. typename geometry::tag<Geometry1>::type,
  101. pointlike_tag, linear_tag, areal_tag
  102. >::type
  103. >::type single_tag;
  104. typedef detail::expect_output
  105. <
  106. Geometry1, Geometry2, SingleOut, single_tag
  107. > expect_check;
  108. typedef typename geometry::detail::output_geometry_access
  109. <
  110. SingleOut, single_tag, single_tag
  111. > access;
  112. };
  113. template
  114. <
  115. typename Geometry1,
  116. typename Geometry2,
  117. typename SingleOut
  118. >
  119. struct call_intersection_insert
  120. <
  121. Geometry1, Geometry2, SingleOut,
  122. detail::tupled_output_tag,
  123. false
  124. >
  125. : call_intersection_insert_tupled_base<Geometry1, Geometry2, SingleOut>
  126. {
  127. typedef call_intersection_insert_tupled_base<Geometry1, Geometry2, SingleOut> base_t;
  128. template
  129. <
  130. typename OutputIterator,
  131. typename RobustPolicy,
  132. typename Strategy
  133. >
  134. static inline OutputIterator apply(Geometry1 const& geometry1,
  135. Geometry2 const& geometry2,
  136. RobustPolicy const& robust_policy,
  137. OutputIterator out,
  138. Strategy const& strategy)
  139. {
  140. base_t::access::get(out) = call_intersection_insert
  141. <
  142. Geometry1, Geometry2,
  143. typename base_t::access::type
  144. >::apply(geometry1, geometry2, robust_policy,
  145. base_t::access::get(out), strategy);
  146. return out;
  147. }
  148. };
  149. template
  150. <
  151. typename Geometry1,
  152. typename Geometry2,
  153. typename SingleOut
  154. >
  155. struct call_intersection_insert
  156. <
  157. Geometry1, Geometry2, SingleOut,
  158. detail::tupled_output_tag,
  159. true
  160. >
  161. : call_intersection_insert_tupled_base<Geometry1, Geometry2, SingleOut>
  162. {
  163. typedef call_intersection_insert_tupled_base<Geometry1, Geometry2, SingleOut> base_t;
  164. template
  165. <
  166. typename OutputIterator,
  167. typename RobustPolicy,
  168. typename Strategy
  169. >
  170. static inline OutputIterator apply(Geometry1 const& geometry1,
  171. Geometry2 const& ,
  172. RobustPolicy const& ,
  173. OutputIterator out,
  174. Strategy const& )
  175. {
  176. base_t::access::get(out) = geometry::detail::convert_to_output
  177. <
  178. Geometry1,
  179. typename base_t::access::type
  180. >::apply(geometry1, base_t::access::get(out));
  181. return out;
  182. }
  183. };
  184. /*!
  185. \brief_calc2{difference} \brief_strategy
  186. \ingroup difference
  187. \details \details_calc2{difference_insert, spatial set theoretic difference}
  188. \brief_strategy. \details_inserter{difference}
  189. \tparam GeometryOut output geometry type, must be specified
  190. \tparam Geometry1 \tparam_geometry
  191. \tparam Geometry2 \tparam_geometry
  192. \tparam OutputIterator output iterator
  193. \tparam Strategy \tparam_strategy_overlay
  194. \param geometry1 \param_geometry
  195. \param geometry2 \param_geometry
  196. \param out \param_out{difference}
  197. \param strategy \param_strategy{difference}
  198. \return \return_out
  199. \qbk{distinguish,with strategy}
  200. */
  201. template
  202. <
  203. typename GeometryOut,
  204. typename Geometry1,
  205. typename Geometry2,
  206. typename OutputIterator,
  207. typename Strategy
  208. >
  209. inline OutputIterator difference_insert(Geometry1 const& geometry1,
  210. Geometry2 const& geometry2,
  211. OutputIterator out,
  212. Strategy const& strategy)
  213. {
  214. concepts::check<Geometry1 const>();
  215. concepts::check<Geometry2 const>();
  216. //concepts::check<GeometryOut>();
  217. geometry::detail::output_geometry_concept_check<GeometryOut>::apply();
  218. typedef typename geometry::rescale_overlay_policy_type
  219. <
  220. Geometry1,
  221. Geometry2,
  222. typename Strategy::cs_tag
  223. >::type rescale_policy_type;
  224. rescale_policy_type robust_policy
  225. = geometry::get_rescale_policy<rescale_policy_type>(
  226. geometry1, geometry2, strategy);
  227. return geometry::detail::difference::call_intersection_insert
  228. <
  229. Geometry1, Geometry2, GeometryOut
  230. >::apply(geometry1, geometry2, robust_policy, out, strategy);
  231. }
  232. /*!
  233. \brief_calc2{difference}
  234. \ingroup difference
  235. \details \details_calc2{difference_insert, spatial set theoretic difference}.
  236. \details_insert{difference}
  237. \tparam GeometryOut output geometry type, must be specified
  238. \tparam Geometry1 \tparam_geometry
  239. \tparam Geometry2 \tparam_geometry
  240. \tparam OutputIterator output iterator
  241. \param geometry1 \param_geometry
  242. \param geometry2 \param_geometry
  243. \param out \param_out{difference}
  244. \return \return_out
  245. \qbk{[include reference/algorithms/difference_insert.qbk]}
  246. */
  247. template
  248. <
  249. typename GeometryOut,
  250. typename Geometry1,
  251. typename Geometry2,
  252. typename OutputIterator
  253. >
  254. inline OutputIterator difference_insert(Geometry1 const& geometry1,
  255. Geometry2 const& geometry2,
  256. OutputIterator out)
  257. {
  258. typedef typename strategies::relate::services::default_strategy
  259. <
  260. Geometry1,
  261. Geometry2
  262. >::type strategy_type;
  263. return difference_insert<GeometryOut>(geometry1, geometry2, out,
  264. strategy_type());
  265. }
  266. template
  267. <
  268. typename Geometry, typename Collection,
  269. typename CastedTag = typename geometry::tag_cast
  270. <
  271. typename geometry::tag<Geometry>::type,
  272. pointlike_tag, linear_tag, areal_tag
  273. >::type
  274. >
  275. struct multi_output_type
  276. {
  277. BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
  278. "Not implemented this Geometry type.",
  279. Geometry, CastedTag);
  280. };
  281. template <typename Geometry, typename Collection>
  282. struct multi_output_type<Geometry, Collection, pointlike_tag>
  283. {
  284. using type = typename util::sequence_find_if
  285. <
  286. typename traits::geometry_types<Collection>::type,
  287. util::is_multi_point
  288. >::type;
  289. };
  290. template <typename Geometry, typename Collection>
  291. struct multi_output_type<Geometry, Collection, linear_tag>
  292. {
  293. using type = typename util::sequence_find_if
  294. <
  295. typename traits::geometry_types<Collection>::type,
  296. util::is_multi_linestring
  297. >::type;
  298. };
  299. template <typename Geometry, typename Collection>
  300. struct multi_output_type<Geometry, Collection, areal_tag>
  301. {
  302. using type = typename util::sequence_find_if
  303. <
  304. typename traits::geometry_types<Collection>::type,
  305. util::is_multi_polygon
  306. >::type;
  307. };
  308. }} // namespace detail::difference
  309. #endif // DOXYGEN_NO_DETAIL
  310. namespace resolve_collection
  311. {
  312. template
  313. <
  314. typename Geometry1, typename Geometry2, typename Collection,
  315. typename Tag1 = typename geometry::tag<Geometry1>::type,
  316. typename Tag2 = typename geometry::tag<Geometry2>::type,
  317. typename CollectionTag = typename geometry::tag<Collection>::type
  318. >
  319. struct difference
  320. {
  321. template <typename Strategy>
  322. static void apply(Geometry1 const& geometry1,
  323. Geometry2 const& geometry2,
  324. Collection & output_collection,
  325. Strategy const& strategy)
  326. {
  327. using single_out = typename geometry::detail::output_geometry_value
  328. <
  329. Collection
  330. >::type;
  331. detail::difference::difference_insert<single_out>(
  332. geometry1, geometry2,
  333. geometry::detail::output_geometry_back_inserter(output_collection),
  334. strategy);
  335. }
  336. };
  337. template <typename Geometry1, typename Geometry2, typename Collection>
  338. struct difference
  339. <
  340. Geometry1, Geometry2, Collection,
  341. geometry_collection_tag, geometry_collection_tag, geometry_collection_tag
  342. >
  343. {
  344. template <typename Strategy>
  345. static void apply(Geometry1 const& geometry1,
  346. Geometry2 const& geometry2,
  347. Collection& output_collection,
  348. Strategy const& strategy)
  349. {
  350. auto const rtree2 = detail::gc_make_rtree_iterators(geometry2, strategy);
  351. detail::visit_breadth_first([&](auto const& g1)
  352. {
  353. // multi-point, multi-linestring or multi_polygon
  354. typename detail::difference::multi_output_type
  355. <
  356. util::remove_cref_t<decltype(g1)>, Collection
  357. >::type out;
  358. g1_minus_gc2(g1, rtree2, out, strategy);
  359. detail::intersection::gc_move_multi_back(output_collection, out);
  360. return true;
  361. }, geometry1);
  362. }
  363. private:
  364. // Implemented as separate function because msvc is unable to do nested lambda capture
  365. template <typename G1, typename Rtree2, typename MultiOut, typename Strategy>
  366. static void g1_minus_gc2(G1 const& g1, Rtree2 const& rtree2, MultiOut& out, Strategy const& strategy)
  367. {
  368. {
  369. using single_out_t = typename geometry::detail::output_geometry_value<MultiOut>::type;
  370. auto out_it = geometry::detail::output_geometry_back_inserter(out);
  371. geometry::detail::convert_to_output<G1, single_out_t>::apply(g1, out_it);
  372. }
  373. using box1_t = detail::gc_make_rtree_box_t<G1>;
  374. box1_t b1 = geometry::return_envelope<box1_t>(g1, strategy);
  375. detail::expand_by_epsilon(b1);
  376. for (auto qit = rtree2.qbegin(index::intersects(b1)); qit != rtree2.qend(); ++qit)
  377. {
  378. traits::iter_visit<Geometry2>::apply([&](auto const& g2)
  379. {
  380. multi_out_minus_g2(out, g2, strategy);
  381. }, qit->second);
  382. if (boost::empty(out))
  383. {
  384. return;
  385. }
  386. }
  387. }
  388. template
  389. <
  390. typename MultiOut, typename G2, typename Strategy,
  391. std::enable_if_t<detail::difference::is_subtractable_t<MultiOut, G2>::value, int> = 0
  392. >
  393. static void multi_out_minus_g2(MultiOut& out, G2 const& g2, Strategy const& strategy)
  394. {
  395. MultiOut result;
  396. difference<MultiOut, G2, MultiOut>::apply(out, g2, result, strategy);
  397. out = std::move(result);
  398. }
  399. template
  400. <
  401. typename MultiOut, typename G2, typename Strategy,
  402. std::enable_if_t<(! detail::difference::is_subtractable_t<MultiOut, G2>::value), int> = 0
  403. >
  404. static void multi_out_minus_g2(MultiOut& , G2 const& , Strategy const& )
  405. {}
  406. };
  407. template <typename Geometry1, typename Geometry2, typename Collection, typename Tag1>
  408. struct difference
  409. <
  410. Geometry1, Geometry2, Collection,
  411. Tag1, geometry_collection_tag, geometry_collection_tag
  412. >
  413. {
  414. template <typename Strategy>
  415. static void apply(Geometry1 const& geometry1,
  416. Geometry2 const& geometry2,
  417. Collection & output_collection,
  418. Strategy const& strategy)
  419. {
  420. using gc_view_t = geometry::detail::geometry_collection_view<Geometry1>;
  421. difference
  422. <
  423. gc_view_t, Geometry2, Collection
  424. >::apply(gc_view_t(geometry1), geometry2, output_collection, strategy);
  425. }
  426. };
  427. template <typename Geometry1, typename Geometry2, typename Collection, typename Tag2>
  428. struct difference
  429. <
  430. Geometry1, Geometry2, Collection,
  431. geometry_collection_tag, Tag2, geometry_collection_tag
  432. >
  433. {
  434. template <typename Strategy>
  435. static void apply(Geometry1 const& geometry1,
  436. Geometry2 const& geometry2,
  437. Collection & output_collection,
  438. Strategy const& strategy)
  439. {
  440. using gc_view_t = geometry::detail::geometry_collection_view<Geometry2>;
  441. difference
  442. <
  443. Geometry1, gc_view_t, Collection
  444. >::apply(geometry1, gc_view_t(geometry2), output_collection, strategy);
  445. }
  446. };
  447. template <typename Geometry1, typename Geometry2, typename Collection, typename Tag1, typename Tag2>
  448. struct difference
  449. <
  450. Geometry1, Geometry2, Collection,
  451. Tag1, Tag2, geometry_collection_tag
  452. >
  453. {
  454. template <typename Strategy>
  455. static void apply(Geometry1 const& geometry1,
  456. Geometry2 const& geometry2,
  457. Collection & output_collection,
  458. Strategy const& strategy)
  459. {
  460. using gc1_view_t = geometry::detail::geometry_collection_view<Geometry1>;
  461. using gc2_view_t = geometry::detail::geometry_collection_view<Geometry2>;
  462. difference
  463. <
  464. gc1_view_t, gc2_view_t, Collection
  465. >::apply(gc1_view_t(geometry1), gc2_view_t(geometry2), output_collection, strategy);
  466. }
  467. };
  468. } // namespace resolve_collection
  469. namespace resolve_strategy {
  470. template
  471. <
  472. typename Strategy,
  473. bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
  474. >
  475. struct difference
  476. {
  477. template <typename Geometry1, typename Geometry2, typename Collection>
  478. static inline void apply(Geometry1 const& geometry1,
  479. Geometry2 const& geometry2,
  480. Collection & output_collection,
  481. Strategy const& strategy)
  482. {
  483. resolve_collection::difference
  484. <
  485. Geometry1, Geometry2, Collection
  486. >::apply(geometry1, geometry2, output_collection, strategy);
  487. }
  488. };
  489. template <typename Strategy>
  490. struct difference<Strategy, false>
  491. {
  492. template <typename Geometry1, typename Geometry2, typename Collection>
  493. static inline void apply(Geometry1 const& geometry1,
  494. Geometry2 const& geometry2,
  495. Collection & output_collection,
  496. Strategy const& strategy)
  497. {
  498. using strategies::relate::services::strategy_converter;
  499. difference
  500. <
  501. decltype(strategy_converter<Strategy>::get(strategy))
  502. >::apply(geometry1, geometry2, output_collection,
  503. strategy_converter<Strategy>::get(strategy));
  504. }
  505. };
  506. template <>
  507. struct difference<default_strategy, false>
  508. {
  509. template <typename Geometry1, typename Geometry2, typename Collection>
  510. static inline void apply(Geometry1 const& geometry1,
  511. Geometry2 const& geometry2,
  512. Collection & output_collection,
  513. default_strategy)
  514. {
  515. typedef typename strategies::relate::services::default_strategy
  516. <
  517. Geometry1,
  518. Geometry2
  519. >::type strategy_type;
  520. difference
  521. <
  522. strategy_type
  523. >::apply(geometry1, geometry2, output_collection, strategy_type());
  524. }
  525. };
  526. } // resolve_strategy
  527. namespace resolve_dynamic
  528. {
  529. template
  530. <
  531. typename Geometry1, typename Geometry2,
  532. typename Tag1 = typename geometry::tag<Geometry1>::type,
  533. typename Tag2 = typename geometry::tag<Geometry2>::type
  534. >
  535. struct difference
  536. {
  537. template <typename Collection, typename Strategy>
  538. static void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
  539. Collection& output_collection, Strategy const& strategy)
  540. {
  541. resolve_strategy::difference
  542. <
  543. Strategy
  544. >::apply(geometry1, geometry2, output_collection, strategy);
  545. }
  546. };
  547. template <typename DynamicGeometry1, typename Geometry2, typename Tag2>
  548. struct difference<DynamicGeometry1, Geometry2, dynamic_geometry_tag, Tag2>
  549. {
  550. template <typename Collection, typename Strategy>
  551. static void apply(DynamicGeometry1 const& geometry1, Geometry2 const& geometry2,
  552. Collection& output_collection, Strategy const& strategy)
  553. {
  554. traits::visit<DynamicGeometry1>::apply([&](auto const& g1)
  555. {
  556. resolve_strategy::difference
  557. <
  558. Strategy
  559. >::apply(g1, geometry2, output_collection, strategy);
  560. }, geometry1);
  561. }
  562. };
  563. template <typename Geometry1, typename DynamicGeometry2, typename Tag1>
  564. struct difference<Geometry1, DynamicGeometry2, Tag1, dynamic_geometry_tag>
  565. {
  566. template <typename Collection, typename Strategy>
  567. static void apply(Geometry1 const& geometry1, DynamicGeometry2 const& geometry2,
  568. Collection& output_collection, Strategy const& strategy)
  569. {
  570. traits::visit<DynamicGeometry2>::apply([&](auto const& g2)
  571. {
  572. resolve_strategy::difference
  573. <
  574. Strategy
  575. >::apply(geometry1, g2, output_collection, strategy);
  576. }, geometry2);
  577. }
  578. };
  579. template <typename DynamicGeometry1, typename DynamicGeometry2>
  580. struct difference<DynamicGeometry1, DynamicGeometry2, dynamic_geometry_tag, dynamic_geometry_tag>
  581. {
  582. template <typename Collection, typename Strategy>
  583. static void apply(DynamicGeometry1 const& geometry1, DynamicGeometry2 const& geometry2,
  584. Collection& output_collection, Strategy const& strategy)
  585. {
  586. traits::visit<DynamicGeometry1, DynamicGeometry2>::apply([&](auto const& g1, auto const& g2)
  587. {
  588. resolve_strategy::difference
  589. <
  590. Strategy
  591. >::apply(g1, g2, output_collection, strategy);
  592. }, geometry1, geometry2);
  593. }
  594. };
  595. } // namespace resolve_dynamic
  596. /*!
  597. \brief_calc2{difference}
  598. \ingroup difference
  599. \details \details_calc2{difference, spatial set theoretic difference}.
  600. \tparam Geometry1 \tparam_geometry
  601. \tparam Geometry2 \tparam_geometry
  602. \tparam Collection \tparam_output_collection
  603. \tparam Strategy \tparam_strategy{Difference}
  604. \param geometry1 \param_geometry
  605. \param geometry2 \param_geometry
  606. \param output_collection the output collection
  607. \param strategy \param_strategy{difference}
  608. \qbk{distinguish,with strategy}
  609. \qbk{[include reference/algorithms/difference.qbk]}
  610. */
  611. template
  612. <
  613. typename Geometry1,
  614. typename Geometry2,
  615. typename Collection,
  616. typename Strategy
  617. >
  618. inline void difference(Geometry1 const& geometry1,
  619. Geometry2 const& geometry2,
  620. Collection& output_collection,
  621. Strategy const& strategy)
  622. {
  623. resolve_dynamic::difference
  624. <
  625. Geometry1,
  626. Geometry2
  627. >::apply(geometry1, geometry2, output_collection, strategy);
  628. }
  629. /*!
  630. \brief_calc2{difference}
  631. \ingroup difference
  632. \details \details_calc2{difference, spatial set theoretic difference}.
  633. \tparam Geometry1 \tparam_geometry
  634. \tparam Geometry2 \tparam_geometry
  635. \tparam Collection \tparam_output_collection
  636. \param geometry1 \param_geometry
  637. \param geometry2 \param_geometry
  638. \param output_collection the output collection
  639. \qbk{[include reference/algorithms/difference.qbk]}
  640. */
  641. template
  642. <
  643. typename Geometry1,
  644. typename Geometry2,
  645. typename Collection
  646. >
  647. inline void difference(Geometry1 const& geometry1,
  648. Geometry2 const& geometry2,
  649. Collection& output_collection)
  650. {
  651. resolve_dynamic::difference
  652. <
  653. Geometry1,
  654. Geometry2
  655. >::apply(geometry1, geometry2, output_collection, default_strategy());
  656. }
  657. }} // namespace boost::geometry
  658. #endif // BOOST_GEOMETRY_ALGORITHMS_DIFFERENCE_HPP