union.hpp 30 KB

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