From 6f7beaf01ad4a9abaee59eed39f8a8942e6c3205 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Fri, 17 Feb 2017 05:00:57 +0100 Subject: [PATCH] [setops] Support strategies in intersection, difference, sym_difference and union_. --- .../detail/intersection/interface.hpp | 249 +++++++++++----- .../boost/geometry/algorithms/difference.hpp | 281 ++++++++++++++++-- .../geometry/algorithms/sym_difference.hpp | 274 ++++++++++++++++- include/boost/geometry/algorithms/union.hpp | 278 ++++++++++++++++- 4 files changed, 953 insertions(+), 129 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/intersection/interface.hpp b/include/boost/geometry/algorithms/detail/intersection/interface.hpp index ddf49ad03..cd806d9c7 100644 --- a/include/boost/geometry/algorithms/detail/intersection/interface.hpp +++ b/include/boost/geometry/algorithms/detail/intersection/interface.hpp @@ -15,12 +15,14 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_INTERFACE_HPP -// TODO: those headers probably may be removed -#include -#include +#include +#include +#include #include #include +#include +#include namespace boost { namespace geometry @@ -98,33 +100,46 @@ struct intersection } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH - -namespace resolve_variant -{ - -template + +namespace resolve_strategy { + struct intersection { - template - static inline bool - apply( - const Geometry1& geometry1, - const Geometry2& geometry2, - GeometryOut& geometry_out) + template + < + typename Geometry1, + typename Geometry2, + typename RobustPolicy, + typename GeometryOut, + typename Strategy + > + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + GeometryOut & geometry_out, + Strategy const& strategy) { - concepts::check(); - concepts::check(); - - typedef typename geometry::rescale_overlay_policy_type + return dispatch::intersection < Geometry1, Geometry2 - >::type rescale_policy_type; - - rescale_policy_type robust_policy - = geometry::get_rescale_policy(geometry1, - geometry2); - + >::apply(geometry1, geometry2, robust_policy, geometry_out, + strategy); + } + + template + < + typename Geometry1, + typename Geometry2, + typename RobustPolicy, + typename GeometryOut + > + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + GeometryOut & geometry_out, + default_strategy) + { typedef typename strategy::relate::services::default_strategy < Geometry1, Geometry2 @@ -139,44 +154,83 @@ struct intersection } }; +} // resolve_strategy + + +namespace resolve_variant +{ + +template +struct intersection +{ + template + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + GeometryOut& geometry_out, + Strategy const& strategy) + { + concepts::check(); + concepts::check(); + + typedef typename geometry::rescale_overlay_policy_type + < + Geometry1, + Geometry2 + >::type rescale_policy_type; + + rescale_policy_type robust_policy + = geometry::get_rescale_policy(geometry1, + geometry2); + + return resolve_strategy::intersection::apply(geometry1, + geometry2, + robust_policy, + geometry_out, + strategy); + } +}; + template struct intersection, Geometry2> { - template + template struct visitor: static_visitor { Geometry2 const& m_geometry2; GeometryOut& m_geometry_out; + Strategy const& m_strategy; visitor(Geometry2 const& geometry2, - GeometryOut& geometry_out) + GeometryOut& geometry_out, + Strategy const& strategy) : m_geometry2(geometry2) , m_geometry_out(geometry_out) + , m_strategy(strategy) {} template - result_type operator()(Geometry1 const& geometry1) const + bool operator()(Geometry1 const& geometry1) const { return intersection - < - Geometry1, - Geometry2 - >::template apply - < - GeometryOut - > - (geometry1, m_geometry2, m_geometry_out); + < + Geometry1, + Geometry2 + >::apply(geometry1, m_geometry2, m_geometry_out, m_strategy); } }; - template + template static inline bool apply(variant const& geometry1, Geometry2 const& geometry2, - GeometryOut& geometry_out) + GeometryOut& geometry_out, + Strategy const& strategy) { - return boost::apply_visitor(visitor(geometry2, geometry_out), geometry1); + return boost::apply_visitor(visitor(geometry2, + geometry_out, + strategy), + geometry1); } }; @@ -184,40 +238,43 @@ struct intersection, Geometry2> template struct intersection > { - template + template struct visitor: static_visitor { Geometry1 const& m_geometry1; GeometryOut& m_geometry_out; + Strategy const& m_strategy; visitor(Geometry1 const& geometry1, - GeometryOut& geometry_out) + GeometryOut& geometry_out, + Strategy const& strategy) : m_geometry1(geometry1) , m_geometry_out(geometry_out) + , m_strategy(strategy) {} template - result_type operator()(Geometry2 const& geometry2) const + bool operator()(Geometry2 const& geometry2) const { return intersection - < - Geometry1, - Geometry2 - >::template apply - < - GeometryOut - > - (m_geometry1, geometry2, m_geometry_out); + < + Geometry1, + Geometry2 + >::apply(m_geometry1, geometry2, m_geometry_out, m_strategy); } }; - template + template static inline bool apply(Geometry1 const& geometry1, - const variant& geometry2, - GeometryOut& geometry_out) + variant const& geometry2, + GeometryOut& geometry_out, + Strategy const& strategy) { - return boost::apply_visitor(visitor(geometry1, geometry_out), geometry2); + return boost::apply_visitor(visitor(geometry1, + geometry_out, + strategy), + geometry2); } }; @@ -225,44 +282,82 @@ struct intersection > template struct intersection, variant > { - template + template struct visitor: static_visitor { GeometryOut& m_geometry_out; + Strategy const& m_strategy; - visitor(GeometryOut& geometry_out) + visitor(GeometryOut& geometry_out, Strategy const& strategy) : m_geometry_out(geometry_out) + , m_strategy(strategy) {} template - result_type operator()(Geometry1 const& geometry1, - Geometry2 const& geometry2) const + bool operator()(Geometry1 const& geometry1, + Geometry2 const& geometry2) const { return intersection - < - Geometry1, - Geometry2 - >::template apply - < - GeometryOut - > - (geometry1, geometry2, m_geometry_out); + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, m_geometry_out, m_strategy); } }; - template + template static inline bool - apply(const variant& geometry1, - const variant& geometry2, - GeometryOut& geometry_out) + apply(variant const& geometry1, + variant const& geometry2, + GeometryOut& geometry_out, + Strategy const& strategy) { - return boost::apply_visitor(visitor(geometry_out), geometry1, geometry2); + return boost::apply_visitor(visitor(geometry_out, + strategy), + geometry1, geometry2); } }; } // namespace resolve_variant +/*! +\brief \brief_calc2{intersection} +\ingroup intersection +\details \details_calc2{intersection, spatial set theoretic intersection}. +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\tparam GeometryOut Collection of geometries (e.g. std::vector, std::deque, boost::geometry::multi*) of which + the value_type fulfills a \p_l_or_c concept, or it is the output geometry (e.g. for a box) +\tparam Strategy \tparam_strategy{Intersection} +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\param geometry_out The output geometry, either a multi_point, multi_polygon, + multi_linestring, or a box (for intersection of two boxes) +\param strategy \param_strategy{intersection} + +\qbk{[include reference/algorithms/intersection.qbk]} +*/ +template +< + typename Geometry1, + typename Geometry2, + typename GeometryOut, + typename Strategy +> +inline bool intersection(Geometry1 const& geometry1, + Geometry2 const& geometry2, + GeometryOut& geometry_out, + Strategy const& strategy) +{ + return resolve_variant::intersection + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, geometry_out, strategy); +} + + /*! \brief \brief_calc2{intersection} \ingroup intersection @@ -285,18 +380,14 @@ template typename GeometryOut > inline bool intersection(Geometry1 const& geometry1, - Geometry2 const& geometry2, - GeometryOut& geometry_out) + Geometry2 const& geometry2, + GeometryOut& geometry_out) { return resolve_variant::intersection < - Geometry1, - Geometry2 - >::template apply - < - GeometryOut - > - (geometry1, geometry2, geometry_out); + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, geometry_out, default_strategy()); } diff --git a/include/boost/geometry/algorithms/difference.hpp b/include/boost/geometry/algorithms/difference.hpp index 2d0afffe8..06c79dc15 100644 --- a/include/boost/geometry/algorithms/difference.hpp +++ b/include/boost/geometry/algorithms/difference.hpp @@ -4,6 +4,7 @@ // This file was modified by Oracle on 2017. // Modifications copyright (c) 2017, Oracle and/or its affiliates. + // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -13,10 +14,16 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DIFFERENCE_HPP #define BOOST_GEOMETRY_ALGORITHMS_DIFFERENCE_HPP -#include + +#include +#include +#include #include #include +#include +#include + namespace boost { namespace geometry { @@ -101,18 +108,14 @@ inline OutputIterator difference_insert(Geometry1 const& geometry1, RobustPolicy const& robust_policy, OutputIterator out) { - concepts::check(); - concepts::check(); - concepts::check(); - - typename strategy::relate::services::default_strategy + typedef typename strategy::relate::services::default_strategy < Geometry1, Geometry2 - >::type strategy; + >::type strategy_type; return difference_insert(geometry1, geometry2, - robust_policy, out, strategy); + robust_policy, out, strategy_type()); } @@ -120,6 +123,250 @@ inline OutputIterator difference_insert(Geometry1 const& geometry1, #endif // DOXYGEN_NO_DETAIL +namespace resolve_strategy { + +struct difference +{ + template + < + typename Geometry1, + typename Geometry2, + typename RobustPolicy, + typename Collection, + typename Strategy + > + static inline void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + Collection & output_collection, + Strategy const& strategy) + { + typedef typename boost::range_value::type geometry_out; + + detail::difference::difference_insert( + geometry1, geometry2, robust_policy, + range::back_inserter(output_collection), + strategy); + } + + template + < + typename Geometry1, + typename Geometry2, + typename RobustPolicy, + typename Collection + > + static inline void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + Collection & output_collection, + default_strategy) + { + typedef typename boost::range_value::type geometry_out; + + detail::difference::difference_insert( + geometry1, geometry2, robust_policy, + range::back_inserter(output_collection)); + } +}; + +} // resolve_strategy + + +namespace resolve_variant +{ + +template +struct difference +{ + template + static inline void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Collection& output_collection, + Strategy const& strategy) + { + typedef typename geometry::rescale_overlay_policy_type + < + Geometry1, + Geometry2 + >::type rescale_policy_type; + + rescale_policy_type robust_policy + = geometry::get_rescale_policy(geometry1, + geometry2); + + resolve_strategy::difference::apply(geometry1, geometry2, + robust_policy, + output_collection, + strategy); + } +}; + + +template +struct difference, Geometry2> +{ + template + struct visitor: static_visitor<> + { + Geometry2 const& m_geometry2; + Collection& m_output_collection; + Strategy const& m_strategy; + + visitor(Geometry2 const& geometry2, + Collection& output_collection, + Strategy const& strategy) + : m_geometry2(geometry2) + , m_output_collection(output_collection) + , m_strategy(strategy) + {} + + template + void operator()(Geometry1 const& geometry1) const + { + difference + < + Geometry1, + Geometry2 + >::apply(geometry1, m_geometry2, m_output_collection, m_strategy); + } + }; + + template + static inline void + apply(variant const& geometry1, + Geometry2 const& geometry2, + Collection& output_collection, + Strategy const& strategy) + { + boost::apply_visitor(visitor(geometry2, + output_collection, + strategy), + geometry1); + } +}; + + +template +struct difference > +{ + template + struct visitor: static_visitor<> + { + Geometry1 const& m_geometry1; + Collection& m_output_collection; + Strategy const& m_strategy; + + visitor(Geometry1 const& geometry1, + Collection& output_collection, + Strategy const& strategy) + : m_geometry1(geometry1) + , m_output_collection(output_collection) + , m_strategy(strategy) + {} + + template + void operator()(Geometry2 const& geometry2) const + { + difference + < + Geometry1, + Geometry2 + >::apply(m_geometry1, geometry2, m_output_collection, m_strategy); + } + }; + + template + static inline void + apply(Geometry1 const& geometry1, + variant const& geometry2, + Collection& output_collection, + Strategy const& strategy) + { + boost::apply_visitor(visitor(geometry1, + output_collection, + strategy), + geometry2); + } +}; + + +template +struct difference, variant > +{ + template + struct visitor: static_visitor<> + { + Collection& m_output_collection; + Strategy const& m_strategy; + + visitor(Collection& output_collection, Strategy const& strategy) + : m_output_collection(output_collection) + , m_strategy(strategy) + {} + + template + void operator()(Geometry1 const& geometry1, + Geometry2 const& geometry2) const + { + difference + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, m_output_collection, m_strategy); + } + }; + + template + static inline void + apply(variant const& geometry1, + variant const& geometry2, + Collection& output_collection, + Strategy const& strategy) + { + boost::apply_visitor(visitor(output_collection, + strategy), + geometry1, geometry2); + } +}; + +} // namespace resolve_variant + + +/*! +\brief_calc2{difference} +\ingroup difference +\details \details_calc2{difference, spatial set theoretic difference}. +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\tparam Collection \tparam_output_collection +\tparam Strategy \tparam_strategy{Difference} +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\param output_collection the output collection +\param strategy \param_strategy{difference} + +\qbk{[include reference/algorithms/difference.qbk]} +*/ +template +< + typename Geometry1, + typename Geometry2, + typename Collection, + typename Strategy +> +inline void difference(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Collection& output_collection, + Strategy const& strategy) +{ + resolve_variant::difference + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, output_collection, strategy); +} + /*! \brief_calc2{difference} @@ -144,25 +391,11 @@ inline void difference(Geometry1 const& geometry1, Geometry2 const& geometry2, Collection& output_collection) { - concepts::check(); - concepts::check(); - - typedef typename boost::range_value::type geometry_out; - concepts::check(); - - typedef typename geometry::rescale_overlay_policy_type + resolve_variant::difference < Geometry1, Geometry2 - >::type rescale_policy_type; - - rescale_policy_type robust_policy - = geometry::get_rescale_policy(geometry1, - geometry2); - - detail::difference::difference_insert( - geometry1, geometry2, robust_policy, - range::back_inserter(output_collection)); + >::apply(geometry1, geometry2, output_collection, default_strategy()); } diff --git a/include/boost/geometry/algorithms/sym_difference.hpp b/include/boost/geometry/algorithms/sym_difference.hpp index 5d5bd904b..ad5878185 100644 --- a/include/boost/geometry/algorithms/sym_difference.hpp +++ b/include/boost/geometry/algorithms/sym_difference.hpp @@ -15,13 +15,21 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_SYM_DIFFERENCE_HPP #define BOOST_GEOMETRY_ALGORITHMS_SYM_DIFFERENCE_HPP + #include #include #include +#include +#include +#include + #include #include #include +#include +#include +#include namespace boost { namespace geometry @@ -289,6 +297,252 @@ inline OutputIterator sym_difference_insert(Geometry1 const& geometry1, #endif // DOXYGEN_NO_DETAIL +namespace resolve_strategy { + +struct sym_difference +{ + template + < + typename Geometry1, + typename Geometry2, + typename RobustPolicy, + typename Collection, + typename Strategy + > + static inline void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + Collection & output_collection, + Strategy const& strategy) + { + typedef typename boost::range_value::type geometry_out; + + detail::sym_difference::sym_difference_insert( + geometry1, geometry2, robust_policy, + range::back_inserter(output_collection), + strategy); + } + + template + < + typename Geometry1, + typename Geometry2, + typename RobustPolicy, + typename Collection + > + static inline void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + Collection & output_collection, + default_strategy) + { + typedef typename boost::range_value::type geometry_out; + + detail::sym_difference::sym_difference_insert( + geometry1, geometry2, robust_policy, + range::back_inserter(output_collection)); + } +}; + +} // resolve_strategy + + +namespace resolve_variant +{ + +template +struct sym_difference +{ + template + static inline void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Collection& output_collection, + Strategy const& strategy) + { + typedef typename geometry::rescale_overlay_policy_type + < + Geometry1, + Geometry2 + >::type rescale_policy_type; + + rescale_policy_type robust_policy + = geometry::get_rescale_policy(geometry1, + geometry2); + + resolve_strategy::sym_difference::apply(geometry1, geometry2, + robust_policy, + output_collection, + strategy); + } +}; + + +template +struct sym_difference, Geometry2> +{ + template + struct visitor: static_visitor<> + { + Geometry2 const& m_geometry2; + Collection& m_output_collection; + Strategy const& m_strategy; + + visitor(Geometry2 const& geometry2, + Collection& output_collection, + Strategy const& strategy) + : m_geometry2(geometry2) + , m_output_collection(output_collection) + , m_strategy(strategy) + {} + + template + void operator()(Geometry1 const& geometry1) const + { + sym_difference + < + Geometry1, + Geometry2 + >::apply(geometry1, m_geometry2, m_output_collection, m_strategy); + } + }; + + template + static inline void + apply(variant const& geometry1, + Geometry2 const& geometry2, + Collection& output_collection, + Strategy const& strategy) + { + boost::apply_visitor(visitor(geometry2, + output_collection, + strategy), + geometry1); + } +}; + + +template +struct sym_difference > +{ + template + struct visitor: static_visitor<> + { + Geometry1 const& m_geometry1; + Collection& m_output_collection; + Strategy const& m_strategy; + + visitor(Geometry1 const& geometry1, + Collection& output_collection, + Strategy const& strategy) + : m_geometry1(geometry1) + , m_output_collection(output_collection) + , m_strategy(strategy) + {} + + template + void operator()(Geometry2 const& geometry2) const + { + sym_difference + < + Geometry1, + Geometry2 + >::apply(m_geometry1, geometry2, m_output_collection, m_strategy); + } + }; + + template + static inline void + apply(Geometry1 const& geometry1, + variant const& geometry2, + Collection& output_collection, + Strategy const& strategy) + { + boost::apply_visitor(visitor(geometry1, + output_collection, + strategy), + geometry2); + } +}; + + +template +struct sym_difference, variant > +{ + template + struct visitor: static_visitor<> + { + Collection& m_output_collection; + Strategy const& m_strategy; + + visitor(Collection& output_collection, Strategy const& strategy) + : m_output_collection(output_collection) + , m_strategy(strategy) + {} + + template + void operator()(Geometry1 const& geometry1, + Geometry2 const& geometry2) const + { + sym_difference + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, m_output_collection, m_strategy); + } + }; + + template + static inline void + apply(variant const& geometry1, + variant const& geometry2, + Collection& output_collection, + Strategy const& strategy) + { + boost::apply_visitor(visitor(output_collection, + strategy), + geometry1, geometry2); + } +}; + +} // namespace resolve_variant + + +/*! +\brief \brief_calc2{symmetric difference} +\ingroup sym_difference +\details \details_calc2{symmetric difference, spatial set theoretic symmetric difference (XOR)}. +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\tparam Collection output collection, either a multi-geometry, + or a std::vector / std::deque etc +\tparam Strategy \tparam_strategy{Sym_difference} +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\param output_collection the output collection +\param strategy \param_strategy{sym_difference} + +\qbk{[include reference/algorithms/sym_difference.qbk]} +*/ +template +< + typename Geometry1, + typename Geometry2, + typename Collection, + typename Strategy +> +inline void sym_difference(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Collection& output_collection, + Strategy const& strategy) +{ + resolve_variant::sym_difference + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, output_collection, strategy); +} + + /*! \brief \brief_calc2{symmetric difference} \ingroup sym_difference @@ -310,26 +564,14 @@ template typename Collection > inline void sym_difference(Geometry1 const& geometry1, - Geometry2 const& geometry2, Collection& output_collection) + Geometry2 const& geometry2, + Collection& output_collection) { - concepts::check(); - concepts::check(); - - typedef typename boost::range_value::type geometry_out; - concepts::check(); - - typedef typename geometry::rescale_overlay_policy_type + resolve_variant::sym_difference < Geometry1, Geometry2 - >::type rescale_policy_type; - - rescale_policy_type robust_policy - = geometry::get_rescale_policy(geometry1, geometry2); - - detail::sym_difference::sym_difference_insert( - geometry1, geometry2, robust_policy, - range::back_inserter(output_collection)); + >::apply(geometry1, geometry2, output_collection, default_strategy()); } diff --git a/include/boost/geometry/algorithms/union.hpp b/include/boost/geometry/algorithms/union.hpp index e2a7d2b96..42682fd96 100644 --- a/include/boost/geometry/algorithms/union.hpp +++ b/include/boost/geometry/algorithms/union.hpp @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include @@ -234,6 +236,265 @@ inline OutputIterator union_insert(Geometry1 const& geometry1, #endif // DOXYGEN_NO_DETAIL +namespace resolve_strategy { + +struct union_ +{ + template + < + typename Geometry1, + typename Geometry2, + typename RobustPolicy, + typename Collection, + typename Strategy + > + static inline void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + Collection & output_collection, + Strategy const& strategy) + { + typedef typename boost::range_value::type geometry_out; + + dispatch::union_insert + < + Geometry1, Geometry2, geometry_out + >::apply(geometry1, geometry2, robust_policy, + range::back_inserter(output_collection), + strategy); + } + + template + < + typename Geometry1, + typename Geometry2, + typename RobustPolicy, + typename Collection + > + static inline void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + Collection & output_collection, + default_strategy) + { + typedef typename boost::range_value::type geometry_out; + + typedef typename strategy::intersection::services::default_strategy + < + typename cs_tag::type + >::type strategy_type; + + dispatch::union_insert + < + Geometry1, Geometry2, geometry_out + >::apply(geometry1, geometry2, robust_policy, + range::back_inserter(output_collection), + strategy_type()); + } +}; + +} // resolve_strategy + + +namespace resolve_variant +{ + +template +struct union_ +{ + template + static inline void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Collection& output_collection, + Strategy const& strategy) + { + concepts::check(); + concepts::check(); + concepts::check::type>(); + + typedef typename geometry::rescale_overlay_policy_type + < + Geometry1, + Geometry2 + >::type rescale_policy_type; + + rescale_policy_type robust_policy + = geometry::get_rescale_policy(geometry1, + geometry2); + + resolve_strategy::union_::apply(geometry1, geometry2, + robust_policy, + output_collection, + strategy); + } +}; + + +template +struct union_, Geometry2> +{ + template + struct visitor: static_visitor<> + { + Geometry2 const& m_geometry2; + Collection& m_output_collection; + Strategy const& m_strategy; + + visitor(Geometry2 const& geometry2, + Collection& output_collection, + Strategy const& strategy) + : m_geometry2(geometry2) + , m_output_collection(output_collection) + , m_strategy(strategy) + {} + + template + void operator()(Geometry1 const& geometry1) const + { + union_ + < + Geometry1, + Geometry2 + >::apply(geometry1, m_geometry2, m_output_collection, m_strategy); + } + }; + + template + static inline void + apply(variant const& geometry1, + Geometry2 const& geometry2, + Collection& output_collection, + Strategy const& strategy) + { + boost::apply_visitor(visitor(geometry2, + output_collection, + strategy), + geometry1); + } +}; + + +template +struct union_ > +{ + template + struct visitor: static_visitor<> + { + Geometry1 const& m_geometry1; + Collection& m_output_collection; + Strategy const& m_strategy; + + visitor(Geometry1 const& geometry1, + Collection& output_collection, + Strategy const& strategy) + : m_geometry1(geometry1) + , m_output_collection(output_collection) + , m_strategy(strategy) + {} + + template + void operator()(Geometry2 const& geometry2) const + { + union_ + < + Geometry1, + Geometry2 + >::apply(m_geometry1, geometry2, m_output_collection, m_strategy); + } + }; + + template + static inline void + apply(Geometry1 const& geometry1, + variant const& geometry2, + Collection& output_collection, + Strategy const& strategy) + { + boost::apply_visitor(visitor(geometry1, + output_collection, + strategy), + geometry2); + } +}; + + +template +struct union_, variant > +{ + template + struct visitor: static_visitor<> + { + Collection& m_output_collection; + Strategy const& m_strategy; + + visitor(Collection& output_collection, Strategy const& strategy) + : m_output_collection(output_collection) + , m_strategy(strategy) + {} + + template + void operator()(Geometry1 const& geometry1, + Geometry2 const& geometry2) const + { + union_ + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, m_output_collection, m_strategy); + } + }; + + template + static inline void + apply(variant const& geometry1, + variant const& geometry2, + Collection& output_collection, + Strategy const& strategy) + { + boost::apply_visitor(visitor(output_collection, + strategy), + geometry1, geometry2); + } +}; + +} // namespace resolve_variant + + +/*! +\brief Combines two geometries which each other +\ingroup union +\details \details_calc2{union, spatial set theoretic union}. +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\tparam Collection output collection, either a multi-geometry, + or a std::vector / std::deque etc +\tparam Strategy \tparam_strategy{Union_} +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\param output_collection the output collection +\param strategy \param_strategy{union_} +\note Called union_ because union is a reserved word. + +\qbk{[include reference/algorithms/union.qbk]} +*/ +template +< + typename Geometry1, + typename Geometry2, + typename Collection, + typename Strategy +> +inline void union_(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Collection& output_collection, + Strategy const& strategy) +{ + resolve_variant::union_ + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, output_collection, strategy); +} /*! @@ -258,17 +519,14 @@ template typename Collection > inline void union_(Geometry1 const& geometry1, - Geometry2 const& geometry2, - Collection& output_collection) + Geometry2 const& geometry2, + Collection& output_collection) { - concepts::check(); - concepts::check(); - - typedef typename boost::range_value::type geometry_out; - concepts::check(); - - detail::union_::union_insert(geometry1, geometry2, - range::back_inserter(output_collection)); + resolve_variant::union_ + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, output_collection, default_strategy()); }