union.hpp 28 KB

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