difference.hpp 22 KB

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