union.hpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  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-2020.
  4. // Modifications copyright (c) 2014-2020 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/not_implemented.hpp>
  14. #include <boost/geometry/algorithms/detail/overlay/overlay.hpp>
  15. #include <boost/geometry/core/point_order.hpp>
  16. #include <boost/geometry/core/reverse_dispatch.hpp>
  17. #include <boost/geometry/geometries/concepts/check.hpp>
  18. #include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
  19. #include <boost/geometry/strategies/default_strategy.hpp>
  20. #include <boost/geometry/strategies/detail.hpp>
  21. #include <boost/geometry/strategies/relate/services.hpp>
  22. #include <boost/geometry/util/range.hpp>
  23. #include <boost/geometry/algorithms/detail/intersection/multi.hpp>
  24. #include <boost/geometry/algorithms/detail/overlay/intersection_insert.hpp>
  25. #include <boost/geometry/algorithms/detail/overlay/linear_linear.hpp>
  26. #include <boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp>
  27. namespace boost { namespace geometry
  28. {
  29. #ifndef DOXYGEN_NO_DISPATCH
  30. namespace dispatch
  31. {
  32. template
  33. <
  34. typename Geometry1, typename Geometry2, typename GeometryOut,
  35. typename TagIn1 = typename tag<Geometry1>::type,
  36. typename TagIn2 = typename tag<Geometry2>::type,
  37. typename TagOut = typename detail::setop_insert_output_tag<GeometryOut>::type,
  38. typename CastedTagIn1 = typename geometry::tag_cast<TagIn1, areal_tag, linear_tag, pointlike_tag>::type,
  39. typename CastedTagIn2 = typename geometry::tag_cast<TagIn2, areal_tag, linear_tag, pointlike_tag>::type,
  40. typename CastedTagOut = typename geometry::tag_cast<TagOut, areal_tag, linear_tag, pointlike_tag>::type,
  41. bool Reverse = geometry::reverse_dispatch<Geometry1, Geometry2>::type::value
  42. >
  43. struct union_insert: not_implemented<TagIn1, TagIn2, TagOut>
  44. {};
  45. // If reversal is needed, perform it first
  46. template
  47. <
  48. typename Geometry1, typename Geometry2, typename GeometryOut,
  49. typename TagIn1, typename TagIn2, typename TagOut,
  50. typename CastedTagIn1, typename CastedTagIn2, typename CastedTagOut
  51. >
  52. struct union_insert
  53. <
  54. Geometry1, Geometry2, GeometryOut,
  55. TagIn1, TagIn2, TagOut,
  56. CastedTagIn1, CastedTagIn2, CastedTagOut,
  57. true
  58. >
  59. {
  60. template <typename RobustPolicy, typename OutputIterator, typename Strategy>
  61. static inline OutputIterator apply(Geometry1 const& g1,
  62. Geometry2 const& g2,
  63. RobustPolicy const& robust_policy,
  64. OutputIterator out,
  65. Strategy const& strategy)
  66. {
  67. return union_insert
  68. <
  69. Geometry2, Geometry1, GeometryOut
  70. >::apply(g2, g1, robust_policy, out, strategy);
  71. }
  72. };
  73. template
  74. <
  75. typename Geometry1, typename Geometry2, typename GeometryOut,
  76. typename TagIn1, typename TagIn2, typename TagOut
  77. >
  78. struct union_insert
  79. <
  80. Geometry1, Geometry2, GeometryOut,
  81. TagIn1, TagIn2, TagOut,
  82. areal_tag, areal_tag, areal_tag,
  83. false
  84. > : detail::overlay::overlay
  85. <
  86. Geometry1, Geometry2,
  87. detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
  88. detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,
  89. detail::overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value,
  90. GeometryOut,
  91. overlay_union
  92. >
  93. {};
  94. // dispatch for union of linear geometries
  95. template
  96. <
  97. typename Linear1, typename Linear2, typename LineStringOut,
  98. typename TagIn1, typename TagIn2
  99. >
  100. struct union_insert
  101. <
  102. Linear1, Linear2, LineStringOut,
  103. TagIn1, TagIn2, linestring_tag,
  104. linear_tag, linear_tag, linear_tag,
  105. false
  106. > : detail::overlay::linear_linear_linestring
  107. <
  108. Linear1, Linear2, LineStringOut, overlay_union
  109. >
  110. {};
  111. // dispatch for point-like geometries
  112. template
  113. <
  114. typename PointLike1, typename PointLike2, typename PointOut,
  115. typename TagIn1, typename TagIn2
  116. >
  117. struct union_insert
  118. <
  119. PointLike1, PointLike2, PointOut,
  120. TagIn1, TagIn2, point_tag,
  121. pointlike_tag, pointlike_tag, pointlike_tag,
  122. false
  123. > : detail::overlay::union_pointlike_pointlike_point
  124. <
  125. PointLike1, PointLike2, PointOut
  126. >
  127. {};
  128. template
  129. <
  130. typename Geometry1, typename Geometry2, typename SingleTupledOut,
  131. typename TagIn1, typename TagIn2,
  132. typename CastedTagIn
  133. >
  134. struct union_insert
  135. <
  136. Geometry1, Geometry2, SingleTupledOut,
  137. TagIn1, TagIn2, detail::tupled_output_tag,
  138. CastedTagIn, CastedTagIn, detail::tupled_output_tag,
  139. false
  140. >
  141. {
  142. typedef typename geometry::detail::single_tag_from_base_tag
  143. <
  144. CastedTagIn
  145. >::type single_tag;
  146. typedef detail::expect_output
  147. <
  148. Geometry1, Geometry2, SingleTupledOut, single_tag
  149. > expect_check;
  150. typedef typename geometry::detail::output_geometry_access
  151. <
  152. SingleTupledOut, single_tag, single_tag
  153. > access;
  154. template <typename RobustPolicy, typename OutputIterator, typename Strategy>
  155. static inline OutputIterator apply(Geometry1 const& g1,
  156. Geometry2 const& g2,
  157. RobustPolicy const& robust_policy,
  158. OutputIterator out,
  159. Strategy const& strategy)
  160. {
  161. access::get(out) = union_insert
  162. <
  163. Geometry2, Geometry1, typename access::type
  164. >::apply(g2, g1, robust_policy, access::get(out), strategy);
  165. return out;
  166. }
  167. };
  168. template
  169. <
  170. typename Geometry1, typename Geometry2, typename SingleTupledOut,
  171. typename SingleTag1, typename SingleTag2,
  172. bool Geometry1LesserTopoDim = (topological_dimension<Geometry1>::value
  173. < topological_dimension<Geometry2>::value)
  174. >
  175. struct union_insert_tupled_different
  176. {
  177. typedef typename geometry::detail::output_geometry_access
  178. <
  179. SingleTupledOut, SingleTag1, SingleTag1
  180. > access1;
  181. typedef typename geometry::detail::output_geometry_access
  182. <
  183. SingleTupledOut, SingleTag2, SingleTag2
  184. > access2;
  185. template <typename RobustPolicy, typename OutputIterator, typename Strategy>
  186. static inline OutputIterator apply(Geometry1 const& g1,
  187. Geometry2 const& g2,
  188. RobustPolicy const& robust_policy,
  189. OutputIterator out,
  190. Strategy const& strategy)
  191. {
  192. access1::get(out) = geometry::dispatch::intersection_insert
  193. <
  194. Geometry1, Geometry2,
  195. typename access1::type,
  196. overlay_difference,
  197. geometry::detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
  198. geometry::detail::overlay::do_reverse<geometry::point_order<Geometry2>::value, true>::value
  199. >::apply(g1, g2, robust_policy, access1::get(out), strategy);
  200. access2::get(out) = geometry::detail::convert_to_output
  201. <
  202. Geometry2,
  203. typename access2::type
  204. >::apply(g2, access2::get(out));
  205. return out;
  206. }
  207. };
  208. template
  209. <
  210. typename Geometry1, typename Geometry2, typename SingleTupledOut,
  211. typename SingleTag1, typename SingleTag2
  212. >
  213. struct union_insert_tupled_different
  214. <
  215. Geometry1, Geometry2, SingleTupledOut, SingleTag1, SingleTag2, false
  216. >
  217. {
  218. template <typename RobustPolicy, typename OutputIterator, typename Strategy>
  219. static inline OutputIterator apply(Geometry1 const& g1,
  220. Geometry2 const& g2,
  221. RobustPolicy const& robust_policy,
  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, robust_policy, 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. typedef typename geometry::detail::single_tag_from_base_tag
  246. <
  247. CastedTagIn1
  248. >::type single_tag1;
  249. typedef detail::expect_output
  250. <
  251. Geometry1, Geometry2, SingleTupledOut, single_tag1
  252. > expect_check1;
  253. typedef typename geometry::detail::single_tag_from_base_tag
  254. <
  255. CastedTagIn2
  256. >::type single_tag2;
  257. typedef detail::expect_output
  258. <
  259. Geometry1, Geometry2, SingleTupledOut, single_tag2
  260. > expect_check2;
  261. template <typename RobustPolicy, typename OutputIterator, typename Strategy>
  262. static inline OutputIterator apply(Geometry1 const& g1,
  263. Geometry2 const& g2,
  264. RobustPolicy const& robust_policy,
  265. OutputIterator out,
  266. Strategy const& strategy)
  267. {
  268. return union_insert_tupled_different
  269. <
  270. Geometry1, Geometry2, SingleTupledOut, single_tag1, single_tag2
  271. >::apply(g1, g2, robust_policy, out, strategy);
  272. }
  273. };
  274. } // namespace dispatch
  275. #endif // DOXYGEN_NO_DISPATCH
  276. #ifndef DOXYGEN_NO_DETAIL
  277. namespace detail { namespace union_
  278. {
  279. /*!
  280. \brief_calc2{union}
  281. \ingroup union
  282. \details \details_calc2{union_insert, spatial set theoretic union}.
  283. \details_insert{union}
  284. \tparam GeometryOut output geometry type, must be specified
  285. \tparam Geometry1 \tparam_geometry
  286. \tparam Geometry2 \tparam_geometry
  287. \tparam OutputIterator output iterator
  288. \param geometry1 \param_geometry
  289. \param geometry2 \param_geometry
  290. \param out \param_out{union}
  291. \return \return_out
  292. */
  293. template
  294. <
  295. typename GeometryOut,
  296. typename Geometry1,
  297. typename Geometry2,
  298. typename OutputIterator
  299. >
  300. inline OutputIterator union_insert(Geometry1 const& geometry1,
  301. Geometry2 const& geometry2,
  302. OutputIterator out)
  303. {
  304. concepts::check<Geometry1 const>();
  305. concepts::check<Geometry2 const>();
  306. geometry::detail::output_geometry_concept_check<GeometryOut>::apply();
  307. typename strategies::relate::services::default_strategy
  308. <
  309. Geometry1, Geometry2
  310. >::type strategy;
  311. typedef typename geometry::rescale_overlay_policy_type
  312. <
  313. Geometry1,
  314. Geometry2
  315. >::type rescale_policy_type;
  316. rescale_policy_type robust_policy
  317. = geometry::get_rescale_policy<rescale_policy_type>(
  318. geometry1, geometry2, strategy);
  319. return dispatch::union_insert
  320. <
  321. Geometry1, Geometry2, GeometryOut
  322. >::apply(geometry1, geometry2, robust_policy, out, strategy);
  323. }
  324. }} // namespace detail::union_
  325. #endif // DOXYGEN_NO_DETAIL
  326. namespace resolve_strategy {
  327. template
  328. <
  329. typename Strategy,
  330. bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
  331. >
  332. struct union_
  333. {
  334. template <typename Geometry1, typename Geometry2, typename Collection>
  335. static inline void apply(Geometry1 const& geometry1,
  336. Geometry2 const& geometry2,
  337. Collection & output_collection,
  338. Strategy const& strategy)
  339. {
  340. typedef typename geometry::detail::output_geometry_value
  341. <
  342. Collection
  343. >::type single_out;
  344. typedef typename geometry::rescale_overlay_policy_type
  345. <
  346. Geometry1,
  347. Geometry2,
  348. typename Strategy::cs_tag
  349. >::type rescale_policy_type;
  350. rescale_policy_type robust_policy
  351. = geometry::get_rescale_policy<rescale_policy_type>(
  352. geometry1, geometry2, strategy);
  353. dispatch::union_insert
  354. <
  355. Geometry1, Geometry2, single_out
  356. >::apply(geometry1, geometry2, robust_policy,
  357. geometry::detail::output_geometry_back_inserter(output_collection),
  358. strategy);
  359. }
  360. };
  361. template <typename Strategy>
  362. struct union_<Strategy, false>
  363. {
  364. template <typename Geometry1, typename Geometry2, typename Collection>
  365. static inline void apply(Geometry1 const& geometry1,
  366. Geometry2 const& geometry2,
  367. Collection & output_collection,
  368. Strategy const& strategy)
  369. {
  370. using strategies::relate::services::strategy_converter;
  371. union_
  372. <
  373. decltype(strategy_converter<Strategy>::get(strategy))
  374. >::apply(geometry1, geometry2, output_collection,
  375. strategy_converter<Strategy>::get(strategy));
  376. }
  377. };
  378. template <>
  379. struct union_<default_strategy, false>
  380. {
  381. template <typename Geometry1, typename Geometry2, typename Collection>
  382. static inline void apply(Geometry1 const& geometry1,
  383. Geometry2 const& geometry2,
  384. Collection & output_collection,
  385. default_strategy)
  386. {
  387. typedef typename strategies::relate::services::default_strategy
  388. <
  389. Geometry1,
  390. Geometry2
  391. >::type strategy_type;
  392. union_
  393. <
  394. strategy_type
  395. >::apply(geometry1, geometry2, output_collection, strategy_type());
  396. }
  397. };
  398. } // resolve_strategy
  399. namespace resolve_variant
  400. {
  401. template <typename Geometry1, typename Geometry2>
  402. struct union_
  403. {
  404. template <typename Collection, typename Strategy>
  405. static inline void apply(Geometry1 const& geometry1,
  406. Geometry2 const& geometry2,
  407. Collection& output_collection,
  408. Strategy const& strategy)
  409. {
  410. concepts::check<Geometry1 const>();
  411. concepts::check<Geometry2 const>();
  412. //concepts::check<typename boost::range_value<Collection>::type>();
  413. geometry::detail::output_geometry_concept_check
  414. <
  415. typename geometry::detail::output_geometry_value
  416. <
  417. Collection
  418. >::type
  419. >::apply();
  420. resolve_strategy::union_
  421. <
  422. Strategy
  423. >::apply(geometry1, geometry2, output_collection, strategy);
  424. }
  425. };
  426. template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
  427. struct union_<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
  428. {
  429. template <typename Collection, typename Strategy>
  430. struct visitor: static_visitor<>
  431. {
  432. Geometry2 const& m_geometry2;
  433. Collection& m_output_collection;
  434. Strategy const& m_strategy;
  435. visitor(Geometry2 const& geometry2,
  436. Collection& output_collection,
  437. Strategy const& strategy)
  438. : m_geometry2(geometry2)
  439. , m_output_collection(output_collection)
  440. , m_strategy(strategy)
  441. {}
  442. template <typename Geometry1>
  443. void operator()(Geometry1 const& geometry1) const
  444. {
  445. union_
  446. <
  447. Geometry1,
  448. Geometry2
  449. >::apply(geometry1, m_geometry2, m_output_collection, m_strategy);
  450. }
  451. };
  452. template <typename Collection, typename Strategy>
  453. static inline void
  454. apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
  455. Geometry2 const& geometry2,
  456. Collection& output_collection,
  457. Strategy const& strategy)
  458. {
  459. boost::apply_visitor(visitor<Collection, Strategy>(geometry2,
  460. output_collection,
  461. strategy),
  462. geometry1);
  463. }
  464. };
  465. template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
  466. struct union_<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
  467. {
  468. template <typename Collection, typename Strategy>
  469. struct visitor: static_visitor<>
  470. {
  471. Geometry1 const& m_geometry1;
  472. Collection& m_output_collection;
  473. Strategy const& m_strategy;
  474. visitor(Geometry1 const& geometry1,
  475. Collection& output_collection,
  476. Strategy const& strategy)
  477. : m_geometry1(geometry1)
  478. , m_output_collection(output_collection)
  479. , m_strategy(strategy)
  480. {}
  481. template <typename Geometry2>
  482. void operator()(Geometry2 const& geometry2) const
  483. {
  484. union_
  485. <
  486. Geometry1,
  487. Geometry2
  488. >::apply(m_geometry1, geometry2, m_output_collection, m_strategy);
  489. }
  490. };
  491. template <typename Collection, typename Strategy>
  492. static inline void
  493. apply(Geometry1 const& geometry1,
  494. variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
  495. Collection& output_collection,
  496. Strategy const& strategy)
  497. {
  498. boost::apply_visitor(visitor<Collection, Strategy>(geometry1,
  499. output_collection,
  500. strategy),
  501. geometry2);
  502. }
  503. };
  504. template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
  505. struct union_<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
  506. {
  507. template <typename Collection, typename Strategy>
  508. struct visitor: static_visitor<>
  509. {
  510. Collection& m_output_collection;
  511. Strategy const& m_strategy;
  512. visitor(Collection& output_collection, Strategy const& strategy)
  513. : m_output_collection(output_collection)
  514. , m_strategy(strategy)
  515. {}
  516. template <typename Geometry1, typename Geometry2>
  517. void operator()(Geometry1 const& geometry1,
  518. Geometry2 const& geometry2) const
  519. {
  520. union_
  521. <
  522. Geometry1,
  523. Geometry2
  524. >::apply(geometry1, geometry2, m_output_collection, m_strategy);
  525. }
  526. };
  527. template <typename Collection, typename Strategy>
  528. static inline void
  529. apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
  530. variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
  531. Collection& output_collection,
  532. Strategy const& strategy)
  533. {
  534. boost::apply_visitor(visitor<Collection, Strategy>(output_collection,
  535. strategy),
  536. geometry1, geometry2);
  537. }
  538. };
  539. } // namespace resolve_variant
  540. /*!
  541. \brief Combines two geometries which each other
  542. \ingroup union
  543. \details \details_calc2{union, spatial set theoretic union}.
  544. \tparam Geometry1 \tparam_geometry
  545. \tparam Geometry2 \tparam_geometry
  546. \tparam Collection output collection, either a multi-geometry,
  547. or a std::vector<Geometry> / std::deque<Geometry> etc
  548. \tparam Strategy \tparam_strategy{Union_}
  549. \param geometry1 \param_geometry
  550. \param geometry2 \param_geometry
  551. \param output_collection the output collection
  552. \param strategy \param_strategy{union_}
  553. \note Called union_ because union is a reserved word.
  554. \qbk{distinguish,with strategy}
  555. \qbk{[include reference/algorithms/union.qbk]}
  556. */
  557. template
  558. <
  559. typename Geometry1,
  560. typename Geometry2,
  561. typename Collection,
  562. typename Strategy
  563. >
  564. inline void union_(Geometry1 const& geometry1,
  565. Geometry2 const& geometry2,
  566. Collection& output_collection,
  567. Strategy const& strategy)
  568. {
  569. resolve_variant::union_
  570. <
  571. Geometry1,
  572. Geometry2
  573. >::apply(geometry1, geometry2, output_collection, strategy);
  574. }
  575. /*!
  576. \brief Combines two geometries which each other
  577. \ingroup union
  578. \details \details_calc2{union, spatial set theoretic union}.
  579. \tparam Geometry1 \tparam_geometry
  580. \tparam Geometry2 \tparam_geometry
  581. \tparam Collection output collection, either a multi-geometry,
  582. or a std::vector<Geometry> / std::deque<Geometry> etc
  583. \param geometry1 \param_geometry
  584. \param geometry2 \param_geometry
  585. \param output_collection the output collection
  586. \note Called union_ because union is a reserved word.
  587. \qbk{[include reference/algorithms/union.qbk]}
  588. */
  589. template
  590. <
  591. typename Geometry1,
  592. typename Geometry2,
  593. typename Collection
  594. >
  595. inline void union_(Geometry1 const& geometry1,
  596. Geometry2 const& geometry2,
  597. Collection& output_collection)
  598. {
  599. resolve_variant::union_
  600. <
  601. Geometry1,
  602. Geometry2
  603. >::apply(geometry1, geometry2, output_collection, default_strategy());
  604. }
  605. }} // namespace boost::geometry
  606. #endif // BOOST_GEOMETRY_ALGORITHMS_UNION_HPP