1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
5 // This file was modified by Oracle on 2014, 2017.
6 // Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
8 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
9 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
11 // Use, modification and distribution is subject to the Boost Software License,
12 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
13 // http://www.boost.org/LICENSE_1_0.txt)
15 #ifndef BOOST_GEOMETRY_ALGORITHMS_UNION_HPP
16 #define BOOST_GEOMETRY_ALGORITHMS_UNION_HPP
19 #include <boost/range/metafunctions.hpp>
21 #include <boost/geometry/core/is_areal.hpp>
22 #include <boost/geometry/core/point_order.hpp>
23 #include <boost/geometry/core/reverse_dispatch.hpp>
24 #include <boost/geometry/geometries/concepts/check.hpp>
25 #include <boost/geometry/algorithms/not_implemented.hpp>
26 #include <boost/geometry/algorithms/detail/overlay/overlay.hpp>
27 #include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
28 #include <boost/geometry/strategies/default_strategy.hpp>
29 #include <boost/geometry/util/range.hpp>
31 #include <boost/geometry/algorithms/detail/overlay/linear_linear.hpp>
32 #include <boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp>
35 namespace boost { namespace geometry
38 #ifndef DOXYGEN_NO_DISPATCH
44 typename Geometry1, typename Geometry2, typename GeometryOut,
45 typename TagIn1 = typename tag<Geometry1>::type,
46 typename TagIn2 = typename tag<Geometry2>::type,
47 typename TagOut = typename tag<GeometryOut>::type,
48 bool Areal1 = geometry::is_areal<Geometry1>::value,
49 bool Areal2 = geometry::is_areal<Geometry2>::value,
50 bool ArealOut = geometry::is_areal<GeometryOut>::value,
51 bool Reverse1 = detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
52 bool Reverse2 = detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,
53 bool ReverseOut = detail::overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value,
54 bool Reverse = geometry::reverse_dispatch<Geometry1, Geometry2>::type::value
56 struct union_insert: not_implemented<TagIn1, TagIn2, TagOut>
60 // If reversal is needed, perform it first
64 typename Geometry1, typename Geometry2, typename GeometryOut,
65 typename TagIn1, typename TagIn2, typename TagOut,
66 bool Areal1, bool Areal2, bool ArealOut,
67 bool Reverse1, bool Reverse2, bool ReverseOut
71 Geometry1, Geometry2, GeometryOut,
72 TagIn1, TagIn2, TagOut,
73 Areal1, Areal2, ArealOut,
74 Reverse1, Reverse2, ReverseOut,
76 >: union_insert<Geometry2, Geometry1, GeometryOut>
78 template <typename RobustPolicy, typename OutputIterator, typename Strategy>
79 static inline OutputIterator apply(Geometry1 const& g1,
81 RobustPolicy const& robust_policy,
83 Strategy const& strategy)
87 Geometry2, Geometry1, GeometryOut
88 >::apply(g2, g1, robust_policy, out, strategy);
95 typename Geometry1, typename Geometry2, typename GeometryOut,
96 typename TagIn1, typename TagIn2, typename TagOut,
97 bool Reverse1, bool Reverse2, bool ReverseOut
101 Geometry1, Geometry2, GeometryOut,
102 TagIn1, TagIn2, TagOut,
104 Reverse1, Reverse2, ReverseOut,
106 > : detail::overlay::overlay
107 <Geometry1, Geometry2, Reverse1, Reverse2, ReverseOut, GeometryOut, overlay_union>
111 // dispatch for union of non-areal geometries
114 typename Geometry1, typename Geometry2, typename GeometryOut,
115 typename TagIn1, typename TagIn2, typename TagOut,
116 bool Reverse1, bool Reverse2, bool ReverseOut
120 Geometry1, Geometry2, GeometryOut,
121 TagIn1, TagIn2, TagOut,
123 Reverse1, Reverse2, ReverseOut,
127 Geometry1, Geometry2, GeometryOut,
128 typename tag_cast<TagIn1, pointlike_tag, linear_tag>::type,
129 typename tag_cast<TagIn2, pointlike_tag, linear_tag>::type,
132 Reverse1, Reverse2, ReverseOut,
138 // dispatch for union of linear geometries
141 typename Linear1, typename Linear2, typename LineStringOut,
142 bool Reverse1, bool Reverse2, bool ReverseOut
146 Linear1, Linear2, LineStringOut,
147 linear_tag, linear_tag, linestring_tag,
149 Reverse1, Reverse2, ReverseOut,
151 > : detail::overlay::linear_linear_linestring
153 Linear1, Linear2, LineStringOut, overlay_union
158 // dispatch for point-like geometries
161 typename PointLike1, typename PointLike2, typename PointOut,
162 bool Reverse1, bool Reverse2, bool ReverseOut
166 PointLike1, PointLike2, PointOut,
167 pointlike_tag, pointlike_tag, point_tag,
169 Reverse1, Reverse2, ReverseOut,
171 > : detail::overlay::union_pointlike_pointlike_point
173 PointLike1, PointLike2, PointOut
178 } // namespace dispatch
179 #endif // DOXYGEN_NO_DISPATCH
181 #ifndef DOXYGEN_NO_DETAIL
182 namespace detail { namespace union_
188 \details \details_calc2{union_insert, spatial set theoretic union}.
189 \details_insert{union}
190 \tparam GeometryOut output geometry type, must be specified
191 \tparam Geometry1 \tparam_geometry
192 \tparam Geometry2 \tparam_geometry
193 \tparam OutputIterator output iterator
194 \param geometry1 \param_geometry
195 \param geometry2 \param_geometry
196 \param out \param_out{union}
201 typename GeometryOut,
204 typename OutputIterator
206 inline OutputIterator union_insert(Geometry1 const& geometry1,
207 Geometry2 const& geometry2,
210 concepts::check<Geometry1 const>();
211 concepts::check<Geometry2 const>();
212 concepts::check<GeometryOut>();
214 typedef typename geometry::rescale_overlay_policy_type
218 >::type rescale_policy_type;
220 typename strategy::intersection::services::default_strategy
222 typename cs_tag<GeometryOut>::type
225 rescale_policy_type robust_policy
226 = geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2);
228 return dispatch::union_insert
230 Geometry1, Geometry2, GeometryOut
231 >::apply(geometry1, geometry2, robust_policy, out, strategy);
235 }} // namespace detail::union_
236 #endif // DOXYGEN_NO_DETAIL
239 namespace resolve_strategy {
247 typename RobustPolicy,
251 static inline void apply(Geometry1 const& geometry1,
252 Geometry2 const& geometry2,
253 RobustPolicy const& robust_policy,
254 Collection & output_collection,
255 Strategy const& strategy)
257 typedef typename boost::range_value<Collection>::type geometry_out;
259 dispatch::union_insert
261 Geometry1, Geometry2, geometry_out
262 >::apply(geometry1, geometry2, robust_policy,
263 range::back_inserter(output_collection),
271 typename RobustPolicy,
274 static inline void apply(Geometry1 const& geometry1,
275 Geometry2 const& geometry2,
276 RobustPolicy const& robust_policy,
277 Collection & output_collection,
280 typedef typename boost::range_value<Collection>::type geometry_out;
282 typedef typename strategy::intersection::services::default_strategy
284 typename cs_tag<geometry_out>::type
285 >::type strategy_type;
287 dispatch::union_insert
289 Geometry1, Geometry2, geometry_out
290 >::apply(geometry1, geometry2, robust_policy,
291 range::back_inserter(output_collection),
296 } // resolve_strategy
299 namespace resolve_variant
302 template <typename Geometry1, typename Geometry2>
305 template <typename Collection, typename Strategy>
306 static inline void apply(Geometry1 const& geometry1,
307 Geometry2 const& geometry2,
308 Collection& output_collection,
309 Strategy const& strategy)
311 concepts::check<Geometry1 const>();
312 concepts::check<Geometry2 const>();
313 concepts::check<typename boost::range_value<Collection>::type>();
315 typedef typename geometry::rescale_overlay_policy_type
319 >::type rescale_policy_type;
321 rescale_policy_type robust_policy
322 = geometry::get_rescale_policy<rescale_policy_type>(geometry1,
325 resolve_strategy::union_::apply(geometry1, geometry2,
333 template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
334 struct union_<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
336 template <typename Collection, typename Strategy>
337 struct visitor: static_visitor<>
339 Geometry2 const& m_geometry2;
340 Collection& m_output_collection;
341 Strategy const& m_strategy;
343 visitor(Geometry2 const& geometry2,
344 Collection& output_collection,
345 Strategy const& strategy)
346 : m_geometry2(geometry2)
347 , m_output_collection(output_collection)
348 , m_strategy(strategy)
351 template <typename Geometry1>
352 void operator()(Geometry1 const& geometry1) const
358 >::apply(geometry1, m_geometry2, m_output_collection, m_strategy);
362 template <typename Collection, typename Strategy>
364 apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
365 Geometry2 const& geometry2,
366 Collection& output_collection,
367 Strategy const& strategy)
369 boost::apply_visitor(visitor<Collection, Strategy>(geometry2,
377 template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
378 struct union_<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
380 template <typename Collection, typename Strategy>
381 struct visitor: static_visitor<>
383 Geometry1 const& m_geometry1;
384 Collection& m_output_collection;
385 Strategy const& m_strategy;
387 visitor(Geometry1 const& geometry1,
388 Collection& output_collection,
389 Strategy const& strategy)
390 : m_geometry1(geometry1)
391 , m_output_collection(output_collection)
392 , m_strategy(strategy)
395 template <typename Geometry2>
396 void operator()(Geometry2 const& geometry2) const
402 >::apply(m_geometry1, geometry2, m_output_collection, m_strategy);
406 template <typename Collection, typename Strategy>
408 apply(Geometry1 const& geometry1,
409 variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
410 Collection& output_collection,
411 Strategy const& strategy)
413 boost::apply_visitor(visitor<Collection, Strategy>(geometry1,
421 template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
422 struct union_<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
424 template <typename Collection, typename Strategy>
425 struct visitor: static_visitor<>
427 Collection& m_output_collection;
428 Strategy const& m_strategy;
430 visitor(Collection& output_collection, Strategy const& strategy)
431 : m_output_collection(output_collection)
432 , m_strategy(strategy)
435 template <typename Geometry1, typename Geometry2>
436 void operator()(Geometry1 const& geometry1,
437 Geometry2 const& geometry2) const
443 >::apply(geometry1, geometry2, m_output_collection, m_strategy);
447 template <typename Collection, typename Strategy>
449 apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
450 variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
451 Collection& output_collection,
452 Strategy const& strategy)
454 boost::apply_visitor(visitor<Collection, Strategy>(output_collection,
456 geometry1, geometry2);
460 } // namespace resolve_variant
464 \brief Combines two geometries which each other
466 \details \details_calc2{union, spatial set theoretic union}.
467 \tparam Geometry1 \tparam_geometry
468 \tparam Geometry2 \tparam_geometry
469 \tparam Collection output collection, either a multi-geometry,
470 or a std::vector<Geometry> / std::deque<Geometry> etc
471 \tparam Strategy \tparam_strategy{Union_}
472 \param geometry1 \param_geometry
473 \param geometry2 \param_geometry
474 \param output_collection the output collection
475 \param strategy \param_strategy{union_}
476 \note Called union_ because union is a reserved word.
478 \qbk{distinguish,with strategy}
479 \qbk{[include reference/algorithms/union.qbk]}
488 inline void union_(Geometry1 const& geometry1,
489 Geometry2 const& geometry2,
490 Collection& output_collection,
491 Strategy const& strategy)
493 resolve_variant::union_
497 >::apply(geometry1, geometry2, output_collection, strategy);
502 \brief Combines two geometries which each other
504 \details \details_calc2{union, spatial set theoretic union}.
505 \tparam Geometry1 \tparam_geometry
506 \tparam Geometry2 \tparam_geometry
507 \tparam Collection output collection, either a multi-geometry,
508 or a std::vector<Geometry> / std::deque<Geometry> etc
509 \param geometry1 \param_geometry
510 \param geometry2 \param_geometry
511 \param output_collection the output collection
512 \note Called union_ because union is a reserved word.
514 \qbk{[include reference/algorithms/union.qbk]}
522 inline void union_(Geometry1 const& geometry1,
523 Geometry2 const& geometry2,
524 Collection& output_collection)
526 resolve_variant::union_
530 >::apply(geometry1, geometry2, output_collection, default_strategy());
534 }} // namespace boost::geometry
537 #endif // BOOST_GEOMETRY_ALGORITHMS_UNION_HPP