union.hpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
  3. // This file was modified by Oracle on 2014-2023.
  4. // Modifications copyright (c) 2014-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_UNION_HPP
  12. #define BOOST_GEOMETRY_ALGORITHMS_UNION_HPP
  13. #include <boost/geometry/algorithms/detail/gc_group_elements.hpp>
  14. #include <boost/geometry/algorithms/detail/intersection/gc.hpp>
  15. #include <boost/geometry/algorithms/detail/overlay/intersection_insert.hpp>
  16. #include <boost/geometry/algorithms/detail/overlay/linear_linear.hpp>
  17. #include <boost/geometry/algorithms/detail/overlay/overlay.hpp>
  18. #include <boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp>
  19. #include <boost/geometry/algorithms/not_implemented.hpp>
  20. #include <boost/geometry/core/point_order.hpp>
  21. #include <boost/geometry/core/reverse_dispatch.hpp>
  22. #include <boost/geometry/geometries/adapted/boost_variant.hpp>
  23. #include <boost/geometry/geometries/concepts/check.hpp>
  24. #include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
  25. #include <boost/geometry/strategies/default_strategy.hpp>
  26. #include <boost/geometry/strategies/detail.hpp>
  27. #include <boost/geometry/strategies/relate/cartesian.hpp>
  28. #include <boost/geometry/strategies/relate/geographic.hpp>
  29. #include <boost/geometry/strategies/relate/spherical.hpp>
  30. #include <boost/geometry/util/type_traits_std.hpp>
  31. #include <boost/geometry/views/detail/geometry_collection_view.hpp>
  32. #include <boost/geometry/views/detail/random_access_view.hpp>
  33. namespace boost { namespace geometry
  34. {
  35. #ifndef DOXYGEN_NO_DISPATCH
  36. namespace dispatch
  37. {
  38. template
  39. <
  40. typename Geometry1, typename Geometry2, typename GeometryOut,
  41. typename TagIn1 = typename tag<Geometry1>::type,
  42. typename TagIn2 = typename tag<Geometry2>::type,
  43. typename TagOut = typename detail::setop_insert_output_tag<GeometryOut>::type,
  44. typename CastedTagIn1 = typename geometry::tag_cast<TagIn1, areal_tag, linear_tag, pointlike_tag>::type,
  45. typename CastedTagIn2 = typename geometry::tag_cast<TagIn2, areal_tag, linear_tag, pointlike_tag>::type,
  46. typename CastedTagOut = typename geometry::tag_cast<TagOut, areal_tag, linear_tag, pointlike_tag>::type,
  47. bool Reverse = geometry::reverse_dispatch<Geometry1, Geometry2>::type::value
  48. >
  49. struct union_insert: not_implemented<TagIn1, TagIn2, TagOut>
  50. {};
  51. // If reversal is needed, perform it first
  52. template
  53. <
  54. typename Geometry1, typename Geometry2, typename GeometryOut,
  55. typename TagIn1, typename TagIn2, typename TagOut,
  56. typename CastedTagIn1, typename CastedTagIn2, typename CastedTagOut
  57. >
  58. struct union_insert
  59. <
  60. Geometry1, Geometry2, GeometryOut,
  61. TagIn1, TagIn2, TagOut,
  62. CastedTagIn1, CastedTagIn2, CastedTagOut,
  63. true
  64. >
  65. {
  66. template <typename RobustPolicy, typename OutputIterator, typename Strategy>
  67. static inline OutputIterator apply(Geometry1 const& g1,
  68. Geometry2 const& g2,
  69. RobustPolicy const& robust_policy,
  70. OutputIterator out,
  71. Strategy const& strategy)
  72. {
  73. return union_insert
  74. <
  75. Geometry2, Geometry1, GeometryOut
  76. >::apply(g2, g1, robust_policy, out, strategy);
  77. }
  78. };
  79. template
  80. <
  81. typename Geometry1, typename Geometry2, typename GeometryOut,
  82. typename TagIn1, typename TagIn2, typename TagOut
  83. >
  84. struct union_insert
  85. <
  86. Geometry1, Geometry2, GeometryOut,
  87. TagIn1, TagIn2, TagOut,
  88. areal_tag, areal_tag, areal_tag,
  89. false
  90. > : detail::overlay::overlay
  91. <
  92. Geometry1, Geometry2,
  93. detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
  94. detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,
  95. detail::overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value,
  96. GeometryOut,
  97. overlay_union
  98. >
  99. {};
  100. // dispatch for union of linear geometries
  101. template
  102. <
  103. typename Linear1, typename Linear2, typename LineStringOut,
  104. typename TagIn1, typename TagIn2
  105. >
  106. struct union_insert
  107. <
  108. Linear1, Linear2, LineStringOut,
  109. TagIn1, TagIn2, linestring_tag,
  110. linear_tag, linear_tag, linear_tag,
  111. false
  112. > : detail::overlay::linear_linear_linestring
  113. <
  114. Linear1, Linear2, LineStringOut, overlay_union
  115. >
  116. {};
  117. // dispatch for point-like geometries
  118. template
  119. <
  120. typename PointLike1, typename PointLike2, typename PointOut,
  121. typename TagIn1, typename TagIn2
  122. >
  123. struct union_insert
  124. <
  125. PointLike1, PointLike2, PointOut,
  126. TagIn1, TagIn2, point_tag,
  127. pointlike_tag, pointlike_tag, pointlike_tag,
  128. false
  129. > : detail::overlay::union_pointlike_pointlike_point
  130. <
  131. PointLike1, PointLike2, PointOut
  132. >
  133. {};
  134. template
  135. <
  136. typename Geometry1, typename Geometry2, typename SingleTupledOut,
  137. typename TagIn1, typename TagIn2,
  138. typename CastedTagIn
  139. >
  140. struct union_insert
  141. <
  142. Geometry1, Geometry2, SingleTupledOut,
  143. TagIn1, TagIn2, detail::tupled_output_tag,
  144. CastedTagIn, CastedTagIn, detail::tupled_output_tag,
  145. false
  146. >
  147. {
  148. using single_tag = typename geometry::detail::single_tag_from_base_tag
  149. <
  150. CastedTagIn
  151. >::type;
  152. using expect_check = detail::expect_output
  153. <
  154. Geometry1, Geometry2, SingleTupledOut, single_tag
  155. >;
  156. using access = typename geometry::detail::output_geometry_access
  157. <
  158. SingleTupledOut, single_tag, single_tag
  159. >;
  160. template <typename RobustPolicy, typename OutputIterator, typename Strategy>
  161. static inline OutputIterator apply(Geometry1 const& g1,
  162. Geometry2 const& g2,
  163. RobustPolicy const& robust_policy,
  164. OutputIterator out,
  165. Strategy const& strategy)
  166. {
  167. access::get(out) = union_insert
  168. <
  169. Geometry2, Geometry1, typename access::type
  170. >::apply(g2, g1, robust_policy, access::get(out), strategy);
  171. return out;
  172. }
  173. };
  174. template
  175. <
  176. typename Geometry1, typename Geometry2, typename SingleTupledOut,
  177. typename SingleTag1, typename SingleTag2,
  178. bool Geometry1LesserTopoDim = (topological_dimension<Geometry1>::value
  179. < topological_dimension<Geometry2>::value)
  180. >
  181. struct union_insert_tupled_different
  182. {
  183. using access1 = typename geometry::detail::output_geometry_access
  184. <
  185. SingleTupledOut, SingleTag1, SingleTag1
  186. >;
  187. using access2 = typename geometry::detail::output_geometry_access
  188. <
  189. SingleTupledOut, SingleTag2, SingleTag2
  190. >;
  191. template <typename RobustPolicy, typename OutputIterator, typename Strategy>
  192. static inline OutputIterator apply(Geometry1 const& g1,
  193. Geometry2 const& g2,
  194. RobustPolicy const& robust_policy,
  195. OutputIterator out,
  196. Strategy const& strategy)
  197. {
  198. access1::get(out) = geometry::dispatch::intersection_insert
  199. <
  200. Geometry1, Geometry2,
  201. typename access1::type,
  202. overlay_difference,
  203. geometry::detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
  204. geometry::detail::overlay::do_reverse<geometry::point_order<Geometry2>::value, true>::value
  205. >::apply(g1, g2, robust_policy, access1::get(out), strategy);
  206. access2::get(out) = geometry::detail::convert_to_output
  207. <
  208. Geometry2,
  209. typename access2::type
  210. >::apply(g2, access2::get(out));
  211. return out;
  212. }
  213. };
  214. template
  215. <
  216. typename Geometry1, typename Geometry2, typename SingleTupledOut,
  217. typename SingleTag1, typename SingleTag2
  218. >
  219. struct union_insert_tupled_different
  220. <
  221. Geometry1, Geometry2, SingleTupledOut, SingleTag1, SingleTag2, false
  222. >
  223. {
  224. template <typename RobustPolicy, typename OutputIterator, typename Strategy>
  225. static inline OutputIterator apply(Geometry1 const& g1,
  226. Geometry2 const& g2,
  227. RobustPolicy const& robust_policy,
  228. OutputIterator out,
  229. Strategy const& strategy)
  230. {
  231. return union_insert_tupled_different
  232. <
  233. Geometry2, Geometry1, SingleTupledOut, SingleTag2, SingleTag1, true
  234. >::apply(g2, g1, robust_policy, out, strategy);
  235. }
  236. };
  237. template
  238. <
  239. typename Geometry1, typename Geometry2, typename SingleTupledOut,
  240. typename TagIn1, typename TagIn2,
  241. typename CastedTagIn1, typename CastedTagIn2
  242. >
  243. struct union_insert
  244. <
  245. Geometry1, Geometry2, SingleTupledOut,
  246. TagIn1, TagIn2, detail::tupled_output_tag,
  247. CastedTagIn1, CastedTagIn2, detail::tupled_output_tag,
  248. false
  249. >
  250. {
  251. using single_tag1 = typename geometry::detail::single_tag_from_base_tag
  252. <
  253. CastedTagIn1
  254. >::type;
  255. using expect_check1 = detail::expect_output
  256. <
  257. Geometry1, Geometry2, SingleTupledOut, single_tag1
  258. >;
  259. using single_tag2 = typename geometry::detail::single_tag_from_base_tag
  260. <
  261. CastedTagIn2
  262. >::type;
  263. using expect_check2 = detail::expect_output
  264. <
  265. Geometry1, Geometry2, SingleTupledOut, single_tag2
  266. >;
  267. template <typename RobustPolicy, typename OutputIterator, typename Strategy>
  268. static inline OutputIterator apply(Geometry1 const& g1,
  269. Geometry2 const& g2,
  270. RobustPolicy const& robust_policy,
  271. OutputIterator out,
  272. Strategy const& strategy)
  273. {
  274. return union_insert_tupled_different
  275. <
  276. Geometry1, Geometry2, SingleTupledOut, single_tag1, single_tag2
  277. >::apply(g1, g2, robust_policy, out, strategy);
  278. }
  279. };
  280. } // namespace dispatch
  281. #endif // DOXYGEN_NO_DISPATCH
  282. #ifndef DOXYGEN_NO_DETAIL
  283. namespace detail { namespace union_
  284. {
  285. /*!
  286. \brief_calc2{union}
  287. \ingroup union
  288. \details \details_calc2{union_insert, spatial set theoretic union}.
  289. \details_insert{union}
  290. \tparam GeometryOut output geometry type, must be specified
  291. \tparam Geometry1 \tparam_geometry
  292. \tparam Geometry2 \tparam_geometry
  293. \tparam OutputIterator output iterator
  294. \param geometry1 \param_geometry
  295. \param geometry2 \param_geometry
  296. \param out \param_out{union}
  297. \return \return_out
  298. */
  299. template
  300. <
  301. typename GeometryOut,
  302. typename Geometry1,
  303. typename Geometry2,
  304. typename OutputIterator
  305. >
  306. inline OutputIterator union_insert(Geometry1 const& geometry1,
  307. Geometry2 const& geometry2,
  308. OutputIterator out)
  309. {
  310. concepts::check<Geometry1 const>();
  311. concepts::check<Geometry2 const>();
  312. geometry::detail::output_geometry_concept_check<GeometryOut>::apply();
  313. typename strategies::relate::services::default_strategy
  314. <
  315. Geometry1, Geometry2
  316. >::type strategy;
  317. using rescale_policy_type = typename geometry::rescale_overlay_policy_type
  318. <
  319. Geometry1,
  320. Geometry2
  321. >::type;
  322. rescale_policy_type robust_policy
  323. = geometry::get_rescale_policy<rescale_policy_type>(
  324. geometry1, geometry2, strategy);
  325. return dispatch::union_insert
  326. <
  327. Geometry1, Geometry2, GeometryOut
  328. >::apply(geometry1, geometry2, robust_policy, out, strategy);
  329. }
  330. }} // namespace detail::union_
  331. #endif // DOXYGEN_NO_DETAIL
  332. namespace resolve_collection
  333. {
  334. template
  335. <
  336. typename Geometry1, typename Geometry2, typename GeometryOut,
  337. typename Tag1 = typename geometry::tag<Geometry1>::type,
  338. typename Tag2 = typename geometry::tag<Geometry2>::type,
  339. typename TagOut = typename geometry::tag<GeometryOut>::type
  340. >
  341. struct union_
  342. {
  343. template <typename Strategy>
  344. static void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
  345. GeometryOut & geometry_out, Strategy const& strategy)
  346. {
  347. using single_out = typename geometry::detail::output_geometry_value
  348. <
  349. GeometryOut
  350. >::type;
  351. using rescale_policy_type = typename geometry::rescale_overlay_policy_type
  352. <
  353. Geometry1,
  354. Geometry2,
  355. typename Strategy::cs_tag
  356. >::type;
  357. rescale_policy_type robust_policy
  358. = geometry::get_rescale_policy<rescale_policy_type>(
  359. geometry1, geometry2, strategy);
  360. dispatch::union_insert
  361. <
  362. Geometry1, Geometry2, single_out
  363. >::apply(geometry1, geometry2, robust_policy,
  364. geometry::detail::output_geometry_back_inserter(geometry_out),
  365. strategy);
  366. }
  367. };
  368. template
  369. <
  370. typename Geometry1, typename Geometry2, typename GeometryOut
  371. >
  372. struct union_
  373. <
  374. Geometry1, Geometry2, GeometryOut,
  375. geometry_collection_tag, geometry_collection_tag, geometry_collection_tag
  376. >
  377. {
  378. // NOTE: for now require all of the possible output types
  379. // technically only a subset could be needed.
  380. using multi_point_t = typename util::sequence_find_if
  381. <
  382. typename traits::geometry_types<GeometryOut>::type,
  383. util::is_multi_point
  384. >::type;
  385. using multi_linestring_t = typename util::sequence_find_if
  386. <
  387. typename traits::geometry_types<GeometryOut>::type,
  388. util::is_multi_linestring
  389. >::type;
  390. using multi_polygon_t = typename util::sequence_find_if
  391. <
  392. typename traits::geometry_types<GeometryOut>::type,
  393. util::is_multi_polygon
  394. >::type;
  395. using tuple_out_t = boost::tuple<multi_point_t, multi_linestring_t, multi_polygon_t>;
  396. template <typename Strategy>
  397. static inline void apply(Geometry1 const& geometry1,
  398. Geometry2 const& geometry2,
  399. GeometryOut& geometry_out,
  400. Strategy const& strategy)
  401. {
  402. detail::random_access_view<Geometry1 const> gc1_view(geometry1);
  403. detail::random_access_view<Geometry2 const> gc2_view(geometry2);
  404. detail::gc_group_elements(gc1_view, gc2_view, strategy,
  405. [&](auto const& inters_group)
  406. {
  407. tuple_out_t out;
  408. merge_group(gc1_view, gc2_view, strategy, inters_group, out);
  409. detail::intersection::gc_move_multi_back(geometry_out, boost::get<0>(out));
  410. detail::intersection::gc_move_multi_back(geometry_out, boost::get<1>(out));
  411. detail::intersection::gc_move_multi_back(geometry_out, boost::get<2>(out));
  412. return true;
  413. },
  414. [&](auto const& disjoint_group)
  415. {
  416. copy_disjoint(gc1_view, gc2_view, disjoint_group, geometry_out);
  417. });
  418. }
  419. private:
  420. template <typename GC1View, typename GC2View, typename Strategy, typename Group>
  421. static inline void merge_group(GC1View const& gc1_view, GC2View const& gc2_view,
  422. Strategy const& strategy, Group const& inters_group,
  423. tuple_out_t& out)
  424. {
  425. for (auto const& id : inters_group)
  426. {
  427. if (id.source_id == 0)
  428. {
  429. traits::iter_visit<GC1View>::apply([&](auto const& g1)
  430. {
  431. merge_one(out, g1, strategy);
  432. }, boost::begin(gc1_view) + id.gc_id);
  433. }
  434. else
  435. {
  436. traits::iter_visit<GC2View>::apply([&](auto const& g2)
  437. {
  438. merge_one(out, g2, strategy);
  439. }, boost::begin(gc2_view) + id.gc_id);
  440. }
  441. }
  442. /*
  443. // L = L \ A
  444. {
  445. multi_linestring_t l;
  446. subtract_greater_topodim(boost::get<1>(out), boost::get<2>(out), l, strategy);
  447. boost::get<1>(out) = std::move(l);
  448. }
  449. // P = P \ A
  450. {
  451. multi_point_t p;
  452. subtract_greater_topodim(boost::get<0>(out), boost::get<2>(out), p, strategy);
  453. boost::get<0>(out) = std::move(p);
  454. }
  455. // P = P \ L
  456. {
  457. multi_point_t p;
  458. subtract_greater_topodim(boost::get<0>(out), boost::get<1>(out), p, strategy);
  459. boost::get<0>(out) = std::move(p);
  460. }
  461. */
  462. }
  463. template <typename G, typename Strategy, std::enable_if_t<util::is_pointlike<G>::value, int> = 0>
  464. static inline void merge_one(tuple_out_t& out, G const& g, Strategy const& strategy)
  465. {
  466. multi_point_t p;
  467. union_<multi_point_t, G, multi_point_t>::apply(boost::get<0>(out), g, p, strategy);
  468. boost::get<0>(out) = std::move(p);
  469. }
  470. template <typename G, typename Strategy, std::enable_if_t<util::is_linear<G>::value, int> = 0>
  471. static inline void merge_one(tuple_out_t& out, G const& g, Strategy const& strategy)
  472. {
  473. multi_linestring_t l;
  474. union_<multi_linestring_t, G, multi_linestring_t>::apply(boost::get<1>(out), g, l, strategy);
  475. boost::get<1>(out) = std::move(l);
  476. }
  477. template <typename G, typename Strategy, std::enable_if_t<util::is_areal<G>::value, int> = 0>
  478. static inline void merge_one(tuple_out_t& out, G const& g, Strategy const& strategy)
  479. {
  480. multi_polygon_t a;
  481. union_<multi_polygon_t, G, multi_polygon_t>::apply(boost::get<2>(out), g, a, strategy);
  482. boost::get<2>(out) = std::move(a);
  483. }
  484. template <typename GC1View, typename GC2View, typename Group>
  485. static inline void copy_disjoint(GC1View const& gc1_view, GC2View const& gc2_view,
  486. Group const& disjoint_group, GeometryOut& geometry_out)
  487. {
  488. for (auto const& id : disjoint_group)
  489. {
  490. if (id.source_id == 0)
  491. {
  492. traits::iter_visit<GC1View>::apply([&](auto const& g1)
  493. {
  494. copy_one(g1, geometry_out);
  495. }, boost::begin(gc1_view) + id.gc_id);
  496. }
  497. else
  498. {
  499. traits::iter_visit<GC2View>::apply([&](auto const& g2)
  500. {
  501. copy_one(g2, geometry_out);
  502. }, boost::begin(gc2_view) + id.gc_id);
  503. }
  504. }
  505. }
  506. template <typename G, std::enable_if_t<util::is_pointlike<G>::value, int> = 0>
  507. static inline void copy_one(G const& g, GeometryOut& geometry_out)
  508. {
  509. multi_point_t p;
  510. geometry::convert(g, p);
  511. detail::intersection::gc_move_multi_back(geometry_out, p);
  512. }
  513. template <typename G, std::enable_if_t<util::is_linear<G>::value, int> = 0>
  514. static inline void copy_one(G const& g, GeometryOut& geometry_out)
  515. {
  516. multi_linestring_t l;
  517. geometry::convert(g, l);
  518. detail::intersection::gc_move_multi_back(geometry_out, l);
  519. }
  520. template <typename G, std::enable_if_t<util::is_areal<G>::value, int> = 0>
  521. static inline void copy_one(G const& g, GeometryOut& geometry_out)
  522. {
  523. multi_polygon_t a;
  524. geometry::convert(g, a);
  525. detail::intersection::gc_move_multi_back(geometry_out, a);
  526. }
  527. /*
  528. template <typename Multi1, typename Multi2, typename Strategy>
  529. static inline void subtract_greater_topodim(Multi1 const& multi1, Multi2 const& multi2, Multi1& multi_out, Strategy const& strategy)
  530. {
  531. using rescale_policy_type = typename geometry::rescale_overlay_policy_type
  532. <
  533. Multi1, Multi2
  534. >::type;
  535. rescale_policy_type robust_policy
  536. = geometry::get_rescale_policy<rescale_policy_type>(
  537. multi1, multi2, strategy);
  538. geometry::dispatch::intersection_insert
  539. <
  540. Multi1, Multi2,
  541. typename boost::range_value<Multi1>::type,
  542. overlay_difference,
  543. geometry::detail::overlay::do_reverse<geometry::point_order<Multi1>::value>::value,
  544. geometry::detail::overlay::do_reverse<geometry::point_order<Multi2>::value, true>::value
  545. >::apply(multi1, multi2, robust_policy, range::back_inserter(multi_out), strategy);
  546. }
  547. */
  548. };
  549. template
  550. <
  551. typename Geometry1, typename Geometry2, typename GeometryOut, typename Tag1
  552. >
  553. struct union_
  554. <
  555. Geometry1, Geometry2, GeometryOut,
  556. Tag1, geometry_collection_tag, geometry_collection_tag
  557. >
  558. {
  559. template <typename Strategy>
  560. static inline void apply(Geometry1 const& geometry1,
  561. Geometry2 const& geometry2,
  562. GeometryOut& geometry_out,
  563. Strategy const& strategy)
  564. {
  565. using gc_view_t = geometry::detail::geometry_collection_view<Geometry1>;
  566. union_
  567. <
  568. gc_view_t, Geometry2, GeometryOut
  569. >::apply(gc_view_t(geometry1), geometry2, geometry_out, strategy);
  570. }
  571. };
  572. template
  573. <
  574. typename Geometry1, typename Geometry2, typename GeometryOut, typename Tag2
  575. >
  576. struct union_
  577. <
  578. Geometry1, Geometry2, GeometryOut,
  579. geometry_collection_tag, Tag2, geometry_collection_tag
  580. >
  581. {
  582. template <typename Strategy>
  583. static inline void apply(Geometry1 const& geometry1,
  584. Geometry2 const& geometry2,
  585. GeometryOut& geometry_out,
  586. Strategy const& strategy)
  587. {
  588. using gc_view_t = geometry::detail::geometry_collection_view<Geometry2>;
  589. union_
  590. <
  591. Geometry1, gc_view_t, GeometryOut
  592. >::apply(geometry1, gc_view_t(geometry2), geometry_out, strategy);
  593. }
  594. };
  595. template
  596. <
  597. typename Geometry1, typename Geometry2, typename GeometryOut, typename Tag1, typename Tag2
  598. >
  599. struct union_
  600. <
  601. Geometry1, Geometry2, GeometryOut,
  602. Tag1, Tag2, geometry_collection_tag
  603. >
  604. {
  605. template <typename Strategy>
  606. static inline void apply(Geometry1 const& geometry1,
  607. Geometry2 const& geometry2,
  608. GeometryOut& geometry_out,
  609. Strategy const& strategy)
  610. {
  611. using gc1_view_t = geometry::detail::geometry_collection_view<Geometry1>;
  612. using gc2_view_t = geometry::detail::geometry_collection_view<Geometry2>;
  613. union_
  614. <
  615. gc1_view_t, gc2_view_t, GeometryOut
  616. >::apply(gc1_view_t(geometry1), gc2_view_t(geometry2), geometry_out, strategy);
  617. }
  618. };
  619. } // namespace resolve_collection
  620. namespace resolve_strategy {
  621. template
  622. <
  623. typename Strategy,
  624. bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
  625. >
  626. struct union_
  627. {
  628. template <typename Geometry1, typename Geometry2, typename Collection>
  629. static inline void apply(Geometry1 const& geometry1,
  630. Geometry2 const& geometry2,
  631. Collection & output_collection,
  632. Strategy const& strategy)
  633. {
  634. resolve_collection::union_
  635. <
  636. Geometry1, Geometry2, Collection
  637. >::apply(geometry1, geometry2, output_collection, strategy);
  638. }
  639. };
  640. template <typename Strategy>
  641. struct union_<Strategy, false>
  642. {
  643. template <typename Geometry1, typename Geometry2, typename Collection>
  644. static inline void apply(Geometry1 const& geometry1,
  645. Geometry2 const& geometry2,
  646. Collection & output_collection,
  647. Strategy const& strategy)
  648. {
  649. using strategies::relate::services::strategy_converter;
  650. union_
  651. <
  652. decltype(strategy_converter<Strategy>::get(strategy))
  653. >::apply(geometry1, geometry2, output_collection,
  654. strategy_converter<Strategy>::get(strategy));
  655. }
  656. };
  657. template <>
  658. struct union_<default_strategy, false>
  659. {
  660. template <typename Geometry1, typename Geometry2, typename Collection>
  661. static inline void apply(Geometry1 const& geometry1,
  662. Geometry2 const& geometry2,
  663. Collection & output_collection,
  664. default_strategy)
  665. {
  666. using strategy_type = typename strategies::relate::services::default_strategy
  667. <
  668. Geometry1,
  669. Geometry2
  670. >::type;
  671. union_
  672. <
  673. strategy_type
  674. >::apply(geometry1, geometry2, output_collection, strategy_type());
  675. }
  676. };
  677. } // resolve_strategy
  678. namespace resolve_dynamic
  679. {
  680. template
  681. <
  682. typename Geometry1, typename Geometry2,
  683. typename Tag1 = typename geometry::tag<Geometry1>::type,
  684. typename Tag2 = typename geometry::tag<Geometry2>::type
  685. >
  686. struct union_
  687. {
  688. template <typename Collection, typename Strategy>
  689. static inline void apply(Geometry1 const& geometry1,
  690. Geometry2 const& geometry2,
  691. Collection& output_collection,
  692. Strategy const& strategy)
  693. {
  694. concepts::check<Geometry1 const>();
  695. concepts::check<Geometry2 const>();
  696. //concepts::check<typename boost::range_value<Collection>::type>();
  697. geometry::detail::output_geometry_concept_check
  698. <
  699. typename geometry::detail::output_geometry_value
  700. <
  701. Collection
  702. >::type
  703. >::apply();
  704. resolve_strategy::union_
  705. <
  706. Strategy
  707. >::apply(geometry1, geometry2, output_collection, strategy);
  708. }
  709. };
  710. template <typename DynamicGeometry1, typename Geometry2, typename Tag2>
  711. struct union_<DynamicGeometry1, Geometry2, dynamic_geometry_tag, Tag2>
  712. {
  713. template <typename Collection, typename Strategy>
  714. static inline void apply(DynamicGeometry1 const& geometry1, Geometry2 const& geometry2,
  715. Collection& output_collection, Strategy const& strategy)
  716. {
  717. traits::visit<DynamicGeometry1>::apply([&](auto const& g1)
  718. {
  719. union_
  720. <
  721. util::remove_cref_t<decltype(g1)>,
  722. Geometry2
  723. >::apply(g1, geometry2, output_collection, strategy);
  724. }, geometry1);
  725. }
  726. };
  727. template <typename Geometry1, typename DynamicGeometry2, typename Tag1>
  728. struct union_<Geometry1, DynamicGeometry2, Tag1, dynamic_geometry_tag>
  729. {
  730. template <typename Collection, typename Strategy>
  731. static inline void apply(Geometry1 const& geometry1, DynamicGeometry2 const& geometry2,
  732. Collection& output_collection, Strategy const& strategy)
  733. {
  734. traits::visit<DynamicGeometry2>::apply([&](auto const& g2)
  735. {
  736. union_
  737. <
  738. Geometry1,
  739. util::remove_cref_t<decltype(g2)>
  740. >::apply(geometry1, g2, output_collection, strategy);
  741. }, geometry2);
  742. }
  743. };
  744. template <typename DynamicGeometry1, typename DynamicGeometry2>
  745. struct union_<DynamicGeometry1, DynamicGeometry2, dynamic_geometry_tag, dynamic_geometry_tag>
  746. {
  747. template <typename Collection, typename Strategy>
  748. static inline void apply(DynamicGeometry1 const& geometry1, DynamicGeometry2 const& geometry2,
  749. Collection& output_collection, Strategy const& strategy)
  750. {
  751. traits::visit<DynamicGeometry1, DynamicGeometry2>::apply([&](auto const& g1, auto const& g2)
  752. {
  753. union_
  754. <
  755. util::remove_cref_t<decltype(g1)>,
  756. util::remove_cref_t<decltype(g2)>
  757. >::apply(g1, g2, output_collection, strategy);
  758. }, geometry1, geometry2);
  759. }
  760. };
  761. } // namespace resolve_dynamic
  762. /*!
  763. \brief Combines two geometries which each other
  764. \ingroup union
  765. \details \details_calc2{union, spatial set theoretic union}.
  766. \tparam Geometry1 \tparam_geometry
  767. \tparam Geometry2 \tparam_geometry
  768. \tparam Collection output collection, either a multi-geometry,
  769. or a std::vector<Geometry> / std::deque<Geometry> etc
  770. \tparam Strategy \tparam_strategy{Union_}
  771. \param geometry1 \param_geometry
  772. \param geometry2 \param_geometry
  773. \param output_collection the output collection
  774. \param strategy \param_strategy{union_}
  775. \note Called union_ because union is a reserved word.
  776. \qbk{distinguish,with strategy}
  777. \qbk{[include reference/algorithms/union.qbk]}
  778. */
  779. template
  780. <
  781. typename Geometry1,
  782. typename Geometry2,
  783. typename Collection,
  784. typename Strategy
  785. >
  786. inline void union_(Geometry1 const& geometry1,
  787. Geometry2 const& geometry2,
  788. Collection& output_collection,
  789. Strategy const& strategy)
  790. {
  791. resolve_dynamic::union_
  792. <
  793. Geometry1,
  794. Geometry2
  795. >::apply(geometry1, geometry2, output_collection, strategy);
  796. }
  797. /*!
  798. \brief Combines two geometries which each other
  799. \ingroup union
  800. \details \details_calc2{union, spatial set theoretic union}.
  801. \tparam Geometry1 \tparam_geometry
  802. \tparam Geometry2 \tparam_geometry
  803. \tparam Collection output collection, either a multi-geometry,
  804. or a std::vector<Geometry> / std::deque<Geometry> etc
  805. \param geometry1 \param_geometry
  806. \param geometry2 \param_geometry
  807. \param output_collection the output collection
  808. \note Called union_ because union is a reserved word.
  809. \qbk{[include reference/algorithms/union.qbk]}
  810. */
  811. template
  812. <
  813. typename Geometry1,
  814. typename Geometry2,
  815. typename Collection
  816. >
  817. inline void union_(Geometry1 const& geometry1,
  818. Geometry2 const& geometry2,
  819. Collection& output_collection)
  820. {
  821. resolve_dynamic::union_
  822. <
  823. Geometry1,
  824. Geometry2
  825. >::apply(geometry1, geometry2, output_collection, default_strategy());
  826. }
  827. }} // namespace boost::geometry
  828. #endif // BOOST_GEOMETRY_ALGORITHMS_UNION_HPP