sym_difference.hpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
  3. // This file was modified by Oracle on 2015-2023.
  4. // Modifications copyright (c) 2015-2023 Oracle and/or its affiliates.
  5. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
  6. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
  7. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  8. // Use, modification and distribution is subject to the Boost Software License,
  9. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  10. // http://www.boost.org/LICENSE_1_0.txt)
  11. #ifndef BOOST_GEOMETRY_ALGORITHMS_SYM_DIFFERENCE_HPP
  12. #define BOOST_GEOMETRY_ALGORITHMS_SYM_DIFFERENCE_HPP
  13. #include <iterator>
  14. #include <boost/geometry/algorithms/difference.hpp>
  15. #include <boost/geometry/algorithms/union.hpp>
  16. #include <boost/geometry/geometries/adapted/boost_variant.hpp>
  17. #include <boost/geometry/geometries/multi_polygon.hpp>
  18. #include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
  19. #include <boost/geometry/strategies/default_strategy.hpp>
  20. #include <boost/geometry/strategies/detail.hpp>
  21. #include <boost/geometry/strategies/relate/cartesian.hpp>
  22. #include <boost/geometry/strategies/relate/geographic.hpp>
  23. #include <boost/geometry/strategies/relate/spherical.hpp>
  24. namespace boost { namespace geometry
  25. {
  26. #ifndef DOXYGEN_NO_DETAIL
  27. namespace detail { namespace sym_difference
  28. {
  29. template <typename GeometryOut>
  30. struct compute_difference
  31. {
  32. template
  33. <
  34. typename Geometry1,
  35. typename Geometry2,
  36. typename RobustPolicy,
  37. typename OutputIterator,
  38. typename Strategy
  39. >
  40. static inline OutputIterator apply(Geometry1 const& geometry1,
  41. Geometry2 const& geometry2,
  42. RobustPolicy const& robust_policy,
  43. OutputIterator out,
  44. Strategy const& strategy)
  45. {
  46. return geometry::dispatch::intersection_insert
  47. <
  48. Geometry1,
  49. Geometry2,
  50. GeometryOut,
  51. overlay_difference,
  52. geometry::detail::overlay::do_reverse
  53. <
  54. geometry::point_order<Geometry1>::value
  55. >::value,
  56. geometry::detail::overlay::do_reverse
  57. <
  58. geometry::point_order<Geometry2>::value, true
  59. >::value
  60. >::apply(geometry1, geometry2, robust_policy, out, strategy);
  61. }
  62. };
  63. template <typename GeometryOut, typename Geometry1, typename Geometry2>
  64. struct sym_difference_generic
  65. {
  66. template
  67. <
  68. typename RobustPolicy,
  69. typename OutputIterator,
  70. typename Strategy
  71. >
  72. static inline OutputIterator apply(Geometry1 const& geometry1,
  73. Geometry2 const& geometry2,
  74. RobustPolicy const& robust_policy,
  75. OutputIterator out,
  76. Strategy const& strategy)
  77. {
  78. out = compute_difference
  79. <
  80. GeometryOut
  81. >::apply(geometry1, geometry2, robust_policy, out, strategy);
  82. return compute_difference
  83. <
  84. GeometryOut
  85. >::apply(geometry2, geometry1, robust_policy, out, strategy);
  86. }
  87. };
  88. template <typename GeometryOut, typename Areal1, typename Areal2>
  89. struct sym_difference_areal_areal
  90. {
  91. template
  92. <
  93. typename RobustPolicy,
  94. typename OutputIterator,
  95. typename Strategy
  96. >
  97. static inline OutputIterator apply(Areal1 const& areal1,
  98. Areal2 const& areal2,
  99. RobustPolicy const& robust_policy,
  100. OutputIterator out,
  101. Strategy const& strategy)
  102. {
  103. typedef geometry::model::multi_polygon
  104. <
  105. GeometryOut
  106. > helper_geometry_type;
  107. helper_geometry_type diff12, diff21;
  108. std::back_insert_iterator<helper_geometry_type> oit12(diff12);
  109. std::back_insert_iterator<helper_geometry_type> oit21(diff21);
  110. compute_difference
  111. <
  112. GeometryOut
  113. >::apply(areal1, areal2, robust_policy, oit12, strategy);
  114. compute_difference
  115. <
  116. GeometryOut
  117. >::apply(areal2, areal1, robust_policy, oit21, strategy);
  118. return geometry::dispatch::union_insert
  119. <
  120. helper_geometry_type,
  121. helper_geometry_type,
  122. GeometryOut
  123. >::apply(diff12, diff21, robust_policy, out, strategy);
  124. }
  125. };
  126. template
  127. <
  128. typename GeometryOut,
  129. typename SingleTag,
  130. template <typename, typename, typename> class Algorithm
  131. >
  132. struct sym_difference_same_inputs_tupled_output
  133. {
  134. template
  135. <
  136. typename Geometry1,
  137. typename Geometry2,
  138. typename RobustPolicy,
  139. typename OutputIterator,
  140. typename Strategy
  141. >
  142. static inline OutputIterator apply(Geometry1 const& geometry1,
  143. Geometry2 const& geometry2,
  144. RobustPolicy const& robust_policy,
  145. OutputIterator out,
  146. Strategy const& strategy)
  147. {
  148. typedef typename geometry::detail::output_geometry_access
  149. <
  150. GeometryOut, SingleTag, SingleTag
  151. > access;
  152. access::get(out) = Algorithm
  153. <
  154. typename access::type, Geometry1, Geometry2
  155. >::apply(geometry1, geometry2, robust_policy, access::get(out), strategy);
  156. return out;
  157. }
  158. };
  159. template
  160. <
  161. typename GeometryOut,
  162. typename SingleTag1,
  163. typename SingleTag2,
  164. bool Reverse = (geometry::core_dispatch::top_dim<SingleTag1>::value
  165. > geometry::core_dispatch::top_dim<SingleTag2>::value)
  166. >
  167. struct sym_difference_different_inputs_tupled_output
  168. {
  169. template
  170. <
  171. typename Geometry1,
  172. typename Geometry2,
  173. typename RobustPolicy,
  174. typename OutputIterator,
  175. typename Strategy
  176. >
  177. static inline OutputIterator apply(Geometry1 const& geometry1,
  178. Geometry2 const& geometry2,
  179. RobustPolicy const& robust_policy,
  180. OutputIterator out,
  181. Strategy const& strategy)
  182. {
  183. return sym_difference_different_inputs_tupled_output
  184. <
  185. GeometryOut, SingleTag2, SingleTag1
  186. >::apply(geometry2, geometry1, robust_policy, out, strategy);
  187. }
  188. };
  189. template
  190. <
  191. typename GeometryOut,
  192. typename SingleTag1,
  193. typename SingleTag2
  194. >
  195. struct sym_difference_different_inputs_tupled_output
  196. <
  197. GeometryOut, SingleTag1, SingleTag2, false
  198. >
  199. {
  200. template
  201. <
  202. typename Geometry1,
  203. typename Geometry2,
  204. typename RobustPolicy,
  205. typename OutputIterator,
  206. typename Strategy
  207. >
  208. static inline OutputIterator apply(Geometry1 const& geometry1,
  209. Geometry2 const& geometry2,
  210. RobustPolicy const& robust_policy,
  211. OutputIterator out,
  212. Strategy const& strategy)
  213. {
  214. typedef typename geometry::detail::output_geometry_access
  215. <
  216. GeometryOut, SingleTag1, SingleTag1
  217. > access1;
  218. typedef typename geometry::detail::output_geometry_access
  219. <
  220. GeometryOut, SingleTag2, SingleTag2
  221. > access2;
  222. access1::get(out) = compute_difference
  223. <
  224. typename access1::type
  225. >::apply(geometry1, geometry2, robust_policy, access1::get(out), strategy);
  226. access2::get(out) = geometry::detail::convert_to_output
  227. <
  228. Geometry2,
  229. typename access2::type
  230. >::apply(geometry2, access2::get(out));
  231. return out;
  232. }
  233. };
  234. }} // namespace detail::sym_difference
  235. #endif // DOXYGEN_NO_DETAIL
  236. #ifndef DOXYGEN_NO_DISPATCH
  237. namespace dispatch
  238. {
  239. template
  240. <
  241. typename Geometry1,
  242. typename Geometry2,
  243. typename GeometryOut,
  244. typename TagIn1 = typename geometry::tag_cast
  245. <
  246. typename tag<Geometry1>::type, pointlike_tag, linear_tag, areal_tag
  247. >::type,
  248. typename TagIn2 = typename geometry::tag_cast
  249. <
  250. typename tag<Geometry2>::type, pointlike_tag, linear_tag, areal_tag
  251. >::type,
  252. typename TagOut = typename detail::setop_insert_output_tag<GeometryOut>::type
  253. >
  254. struct sym_difference_insert
  255. : detail::sym_difference::sym_difference_generic
  256. <
  257. GeometryOut, Geometry1, Geometry2
  258. >
  259. {};
  260. template
  261. <
  262. typename Areal1,
  263. typename Areal2,
  264. typename GeometryOut,
  265. typename TagOut
  266. >
  267. struct sym_difference_insert
  268. <
  269. Areal1, Areal2, GeometryOut,
  270. areal_tag, areal_tag, TagOut
  271. > : detail::sym_difference::sym_difference_areal_areal
  272. <
  273. GeometryOut, Areal1, Areal2
  274. >
  275. {};
  276. template
  277. <
  278. typename PointLike1,
  279. typename PointLike2,
  280. typename GeometryOut
  281. >
  282. struct sym_difference_insert
  283. <
  284. PointLike1, PointLike2, GeometryOut,
  285. pointlike_tag, pointlike_tag, detail::tupled_output_tag
  286. >
  287. : detail::expect_output<PointLike1, PointLike2, GeometryOut, point_tag>
  288. , detail::sym_difference::sym_difference_same_inputs_tupled_output
  289. <
  290. GeometryOut,
  291. point_tag,
  292. detail::sym_difference::sym_difference_generic
  293. >
  294. {};
  295. template
  296. <
  297. typename Linear1,
  298. typename Linear2,
  299. typename GeometryOut
  300. >
  301. struct sym_difference_insert
  302. <
  303. Linear1, Linear2, GeometryOut,
  304. linear_tag, linear_tag, detail::tupled_output_tag
  305. >
  306. : detail::expect_output<Linear1, Linear2, GeometryOut, linestring_tag>
  307. , detail::sym_difference::sym_difference_same_inputs_tupled_output
  308. <
  309. GeometryOut,
  310. linestring_tag,
  311. detail::sym_difference::sym_difference_generic
  312. >
  313. {};
  314. template
  315. <
  316. typename Areal1,
  317. typename Areal2,
  318. typename GeometryOut
  319. >
  320. struct sym_difference_insert
  321. <
  322. Areal1, Areal2, GeometryOut,
  323. areal_tag, areal_tag, detail::tupled_output_tag
  324. >
  325. : detail::expect_output<Areal1, Areal2, GeometryOut, polygon_tag>
  326. , detail::sym_difference::sym_difference_same_inputs_tupled_output
  327. <
  328. GeometryOut,
  329. polygon_tag,
  330. detail::sym_difference::sym_difference_areal_areal
  331. >
  332. {};
  333. template
  334. <
  335. typename Geometry1,
  336. typename Geometry2,
  337. typename GeometryOut,
  338. typename TagIn1,
  339. typename TagIn2
  340. >
  341. struct sym_difference_insert
  342. <
  343. Geometry1, Geometry2, GeometryOut,
  344. TagIn1, TagIn2, detail::tupled_output_tag
  345. >
  346. : detail::expect_output
  347. <
  348. Geometry1, Geometry2, GeometryOut,
  349. typename detail::single_tag_from_base_tag<TagIn1>::type,
  350. typename detail::single_tag_from_base_tag<TagIn2>::type
  351. >
  352. , detail::sym_difference::sym_difference_different_inputs_tupled_output
  353. <
  354. GeometryOut,
  355. typename detail::single_tag_from_base_tag<TagIn1>::type,
  356. typename detail::single_tag_from_base_tag<TagIn2>::type
  357. >
  358. {};
  359. } // namespace dispatch
  360. #endif // DOXYGEN_NO_DISPATCH
  361. #ifndef DOXYGEN_NO_DETAIL
  362. namespace detail { namespace sym_difference
  363. {
  364. /*!
  365. \brief \brief_calc2{symmetric difference} \brief_strategy
  366. \ingroup sym_difference
  367. \details \details_calc2{symmetric difference, spatial set theoretic symmetric difference (XOR)}
  368. \brief_strategy. \details_insert{sym_difference}
  369. \tparam GeometryOut output geometry type, must be specified
  370. \tparam Geometry1 \tparam_geometry
  371. \tparam Geometry2 \tparam_geometry
  372. \tparam Strategy \tparam_strategy_overlay
  373. \param geometry1 \param_geometry
  374. \param geometry2 \param_geometry
  375. \param out \param_out{difference}
  376. \param strategy \param_strategy{difference}
  377. \return \return_out
  378. \qbk{distinguish,with strategy}
  379. */
  380. template
  381. <
  382. typename GeometryOut,
  383. typename Geometry1,
  384. typename Geometry2,
  385. typename OutputIterator,
  386. typename Strategy
  387. >
  388. inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,
  389. Geometry2 const& geometry2,
  390. OutputIterator out,
  391. Strategy const& strategy)
  392. {
  393. concepts::check<Geometry1 const>();
  394. concepts::check<Geometry2 const>();
  395. //concepts::check<GeometryOut>();
  396. geometry::detail::output_geometry_concept_check<GeometryOut>::apply();
  397. typedef typename geometry::rescale_overlay_policy_type
  398. <
  399. Geometry1,
  400. Geometry2,
  401. typename Strategy::cs_tag
  402. >::type rescale_policy_type;
  403. rescale_policy_type robust_policy
  404. = geometry::get_rescale_policy<rescale_policy_type>(
  405. geometry1, geometry2, strategy);
  406. return dispatch::sym_difference_insert
  407. <
  408. Geometry1, Geometry2, GeometryOut
  409. >::apply(geometry1, geometry2, robust_policy, out, strategy);
  410. }
  411. /*!
  412. \brief \brief_calc2{symmetric difference}
  413. \ingroup sym_difference
  414. \details \details_calc2{symmetric difference, spatial set theoretic symmetric difference (XOR)}
  415. \details_insert{sym_difference}
  416. \tparam GeometryOut output geometry type, must be specified
  417. \tparam Geometry1 \tparam_geometry
  418. \tparam Geometry2 \tparam_geometry
  419. \param geometry1 \param_geometry
  420. \param geometry2 \param_geometry
  421. \param out \param_out{difference}
  422. \return \return_out
  423. */
  424. template
  425. <
  426. typename GeometryOut,
  427. typename Geometry1,
  428. typename Geometry2,
  429. typename OutputIterator
  430. >
  431. inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,
  432. Geometry2 const& geometry2, OutputIterator out)
  433. {
  434. typedef typename strategies::relate::services::default_strategy
  435. <
  436. Geometry1, Geometry2
  437. >::type strategy_type;
  438. return sym_difference_insert<GeometryOut>(geometry1, geometry2, out, strategy_type());
  439. }
  440. }} // namespace detail::sym_difference
  441. #endif // DOXYGEN_NO_DETAIL
  442. namespace resolve_collection
  443. {
  444. template
  445. <
  446. typename Geometry1, typename Geometry2, typename Collection,
  447. typename Tag1 = typename geometry::tag<Geometry1>::type,
  448. typename Tag2 = typename geometry::tag<Geometry2>::type,
  449. typename CollectionTag = typename geometry::tag<Collection>::type
  450. >
  451. struct sym_difference
  452. {
  453. template <typename Strategy>
  454. static void apply(Geometry1 const& geometry1,
  455. Geometry2 const& geometry2,
  456. Collection & output_collection,
  457. Strategy const& strategy)
  458. {
  459. typedef typename geometry::detail::output_geometry_value
  460. <
  461. Collection
  462. >::type single_out;
  463. detail::sym_difference::sym_difference_insert<single_out>(
  464. geometry1, geometry2,
  465. geometry::detail::output_geometry_back_inserter(output_collection),
  466. strategy);
  467. }
  468. };
  469. template <typename Geometry1, typename Geometry2, typename Collection>
  470. struct sym_difference
  471. <
  472. Geometry1, Geometry2, Collection,
  473. geometry_collection_tag, geometry_collection_tag, geometry_collection_tag
  474. >
  475. {
  476. template <typename Strategy>
  477. static void apply(Geometry1 const& geometry1,
  478. Geometry2 const& geometry2,
  479. Collection& output_collection,
  480. Strategy const& strategy)
  481. {
  482. Collection temp1, temp2;
  483. resolve_collection::difference
  484. <
  485. Geometry1, Geometry2, Collection
  486. >::apply(geometry1, geometry2, temp1, strategy);
  487. resolve_collection::difference
  488. <
  489. Geometry2, Geometry1, Collection
  490. >::apply(geometry2, geometry1, temp2, strategy);
  491. resolve_collection::union_
  492. <
  493. Collection, Collection, Collection
  494. >::apply(temp1, temp2, output_collection, strategy);
  495. }
  496. };
  497. template <typename Geometry1, typename Geometry2, typename Collection, typename Tag1>
  498. struct sym_difference
  499. <
  500. Geometry1, Geometry2, Collection,
  501. Tag1, geometry_collection_tag, geometry_collection_tag
  502. >
  503. {
  504. template <typename Strategy>
  505. static void apply(Geometry1 const& geometry1,
  506. Geometry2 const& geometry2,
  507. Collection & output_collection,
  508. Strategy const& strategy)
  509. {
  510. using gc_view_t = geometry::detail::geometry_collection_view<Geometry1>;
  511. sym_difference
  512. <
  513. gc_view_t, Geometry2, Collection
  514. >::apply(gc_view_t(geometry1), geometry2, output_collection, strategy);
  515. }
  516. };
  517. template <typename Geometry1, typename Geometry2, typename Collection, typename Tag2>
  518. struct sym_difference
  519. <
  520. Geometry1, Geometry2, Collection,
  521. geometry_collection_tag, Tag2, geometry_collection_tag
  522. >
  523. {
  524. template <typename Strategy>
  525. static void apply(Geometry1 const& geometry1,
  526. Geometry2 const& geometry2,
  527. Collection & output_collection,
  528. Strategy const& strategy)
  529. {
  530. using gc_view_t = geometry::detail::geometry_collection_view<Geometry2>;
  531. sym_difference
  532. <
  533. Geometry1, gc_view_t, Collection
  534. >::apply(geometry1, gc_view_t(geometry2), output_collection, strategy);
  535. }
  536. };
  537. template <typename Geometry1, typename Geometry2, typename Collection, typename Tag1, typename Tag2>
  538. struct sym_difference
  539. <
  540. Geometry1, Geometry2, Collection,
  541. Tag1, Tag2, geometry_collection_tag
  542. >
  543. {
  544. template <typename Strategy>
  545. static void apply(Geometry1 const& geometry1,
  546. Geometry2 const& geometry2,
  547. Collection & output_collection,
  548. Strategy const& strategy)
  549. {
  550. using gc1_view_t = geometry::detail::geometry_collection_view<Geometry1>;
  551. using gc2_view_t = geometry::detail::geometry_collection_view<Geometry2>;
  552. sym_difference
  553. <
  554. gc1_view_t, gc2_view_t, Collection
  555. >::apply(gc1_view_t(geometry1), gc2_view_t(geometry2), output_collection, strategy);
  556. }
  557. };
  558. } // namespace resolve_collection
  559. namespace resolve_strategy
  560. {
  561. template
  562. <
  563. typename Strategy,
  564. bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
  565. >
  566. struct sym_difference
  567. {
  568. template <typename Geometry1, typename Geometry2, typename Collection>
  569. static inline void apply(Geometry1 const& geometry1,
  570. Geometry2 const& geometry2,
  571. Collection & output_collection,
  572. Strategy const& strategy)
  573. {
  574. resolve_collection::sym_difference
  575. <
  576. Geometry1, Geometry2, Collection
  577. >::apply(geometry1, geometry2, output_collection, strategy);
  578. }
  579. };
  580. template <typename Strategy>
  581. struct sym_difference<Strategy, false>
  582. {
  583. template <typename Geometry1, typename Geometry2, typename Collection>
  584. static inline void apply(Geometry1 const& geometry1,
  585. Geometry2 const& geometry2,
  586. Collection & output_collection,
  587. Strategy const& strategy)
  588. {
  589. using strategies::relate::services::strategy_converter;
  590. sym_difference
  591. <
  592. decltype(strategy_converter<Strategy>::get(strategy))
  593. >::apply(geometry1, geometry2, output_collection,
  594. strategy_converter<Strategy>::get(strategy));
  595. }
  596. };
  597. template <>
  598. struct sym_difference<default_strategy, false>
  599. {
  600. template <typename Geometry1, typename Geometry2, typename Collection>
  601. static inline void apply(Geometry1 const& geometry1,
  602. Geometry2 const& geometry2,
  603. Collection & output_collection,
  604. default_strategy)
  605. {
  606. typedef typename strategies::relate::services::default_strategy
  607. <
  608. Geometry1, Geometry2
  609. >::type strategy_type;
  610. sym_difference
  611. <
  612. strategy_type
  613. >::apply(geometry1, geometry2, output_collection, strategy_type());
  614. }
  615. };
  616. } // resolve_strategy
  617. namespace resolve_dynamic
  618. {
  619. template
  620. <
  621. typename Geometry1, typename Geometry2,
  622. typename Tag1 = typename geometry::tag<Geometry1>::type,
  623. typename Tag2 = typename geometry::tag<Geometry2>::type
  624. >
  625. struct sym_difference
  626. {
  627. template <typename Collection, typename Strategy>
  628. static inline void apply(Geometry1 const& geometry1,
  629. Geometry2 const& geometry2,
  630. Collection& output_collection,
  631. Strategy const& strategy)
  632. {
  633. resolve_strategy::sym_difference
  634. <
  635. Strategy
  636. >::apply(geometry1, geometry2, output_collection, strategy);
  637. }
  638. };
  639. template <typename DynamicGeometry1, typename Geometry2, typename Tag2>
  640. struct sym_difference<DynamicGeometry1, Geometry2, dynamic_geometry_tag, Tag2>
  641. {
  642. template <typename Collection, typename Strategy>
  643. static void apply(DynamicGeometry1 const& geometry1, Geometry2 const& geometry2,
  644. Collection& output_collection, Strategy const& strategy)
  645. {
  646. traits::visit<DynamicGeometry1>::apply([&](auto const& g1)
  647. {
  648. resolve_strategy::sym_difference
  649. <
  650. Strategy
  651. >::apply(g1, geometry2, output_collection, strategy);
  652. }, geometry1);
  653. }
  654. };
  655. template <typename Geometry1, typename DynamicGeometry2, typename Tag1>
  656. struct sym_difference<Geometry1, DynamicGeometry2, Tag1, dynamic_geometry_tag>
  657. {
  658. template <typename Collection, typename Strategy>
  659. static void apply(Geometry1 const& geometry1, DynamicGeometry2 const& geometry2,
  660. Collection& output_collection, Strategy const& strategy)
  661. {
  662. traits::visit<DynamicGeometry2>::apply([&](auto const& g2)
  663. {
  664. resolve_strategy::sym_difference
  665. <
  666. Strategy
  667. >::apply(geometry1, g2, output_collection, strategy);
  668. }, geometry2);
  669. }
  670. };
  671. template <typename DynamicGeometry1, typename DynamicGeometry2>
  672. struct sym_difference<DynamicGeometry1, DynamicGeometry2, dynamic_geometry_tag, dynamic_geometry_tag>
  673. {
  674. template <typename Collection, typename Strategy>
  675. static void apply(DynamicGeometry1 const& geometry1, DynamicGeometry2 const& geometry2,
  676. Collection& output_collection, Strategy const& strategy)
  677. {
  678. traits::visit<DynamicGeometry1, DynamicGeometry2>::apply([&](auto const& g1, auto const& g2)
  679. {
  680. resolve_strategy::sym_difference
  681. <
  682. Strategy
  683. >::apply(g1, g2, output_collection, strategy);
  684. }, geometry1, geometry2);
  685. }
  686. };
  687. } // namespace resolve_dynamic
  688. /*!
  689. \brief \brief_calc2{symmetric difference}
  690. \ingroup sym_difference
  691. \details \details_calc2{symmetric difference, spatial set theoretic symmetric difference (XOR)}.
  692. \tparam Geometry1 \tparam_geometry
  693. \tparam Geometry2 \tparam_geometry
  694. \tparam Collection output collection, either a multi-geometry,
  695. or a std::vector<Geometry> / std::deque<Geometry> etc
  696. \tparam Strategy \tparam_strategy{Sym_difference}
  697. \param geometry1 \param_geometry
  698. \param geometry2 \param_geometry
  699. \param output_collection the output collection
  700. \param strategy \param_strategy{sym_difference}
  701. \qbk{distinguish,with strategy}
  702. \qbk{[include reference/algorithms/sym_difference.qbk]}
  703. */
  704. template
  705. <
  706. typename Geometry1,
  707. typename Geometry2,
  708. typename Collection,
  709. typename Strategy
  710. >
  711. inline void sym_difference(Geometry1 const& geometry1,
  712. Geometry2 const& geometry2,
  713. Collection& output_collection,
  714. Strategy const& strategy)
  715. {
  716. resolve_dynamic::sym_difference
  717. <
  718. Geometry1,
  719. Geometry2
  720. >::apply(geometry1, geometry2, output_collection, strategy);
  721. }
  722. /*!
  723. \brief \brief_calc2{symmetric difference}
  724. \ingroup sym_difference
  725. \details \details_calc2{symmetric difference, spatial set theoretic symmetric difference (XOR)}.
  726. \tparam Geometry1 \tparam_geometry
  727. \tparam Geometry2 \tparam_geometry
  728. \tparam Collection output collection, either a multi-geometry,
  729. or a std::vector<Geometry> / std::deque<Geometry> etc
  730. \param geometry1 \param_geometry
  731. \param geometry2 \param_geometry
  732. \param output_collection the output collection
  733. \qbk{[include reference/algorithms/sym_difference.qbk]}
  734. */
  735. template
  736. <
  737. typename Geometry1,
  738. typename Geometry2,
  739. typename Collection
  740. >
  741. inline void sym_difference(Geometry1 const& geometry1,
  742. Geometry2 const& geometry2,
  743. Collection& output_collection)
  744. {
  745. resolve_dynamic::sym_difference
  746. <
  747. Geometry1,
  748. Geometry2
  749. >::apply(geometry1, geometry2, output_collection, default_strategy());
  750. }
  751. }} // namespace boost::geometry
  752. #endif // BOOST_GEOMETRY_ALGORITHMS_SYM_DIFFERENCE_HPP