diff options
Diffstat (limited to 'boost/geometry/algorithms/sym_difference.hpp')
-rw-r--r-- | boost/geometry/algorithms/sym_difference.hpp | 288 |
1 files changed, 264 insertions, 24 deletions
diff --git a/boost/geometry/algorithms/sym_difference.hpp b/boost/geometry/algorithms/sym_difference.hpp index 33f94c9321..725230cd5b 100644 --- a/boost/geometry/algorithms/sym_difference.hpp +++ b/boost/geometry/algorithms/sym_difference.hpp @@ -2,10 +2,11 @@ // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2015. -// Modifications copyright (c) 2015 Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2017. +// Modifications copyright (c) 2015-2017 Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -14,13 +15,21 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_SYM_DIFFERENCE_HPP #define BOOST_GEOMETRY_ALGORITHMS_SYM_DIFFERENCE_HPP + #include <algorithm> #include <iterator> #include <vector> +#include <boost/variant/apply_visitor.hpp> +#include <boost/variant/static_visitor.hpp> +#include <boost/variant/variant_fwd.hpp> + #include <boost/geometry/algorithms/intersection.hpp> #include <boost/geometry/algorithms/union.hpp> #include <boost/geometry/geometries/multi_polygon.hpp> +#include <boost/geometry/policies/robustness/get_rescale_policy.hpp> +#include <boost/geometry/strategies/default_strategy.hpp> +#include <boost/geometry/util/range.hpp> namespace boost { namespace geometry @@ -276,14 +285,10 @@ inline OutputIterator sym_difference_insert(Geometry1 const& geometry1, concepts::check<Geometry2 const>(); concepts::check<GeometryOut>(); - typedef intersection_strategies + typedef typename strategy::intersection::services::default_strategy < - typename cs_tag<GeometryOut>::type, - Geometry1, - Geometry2, - typename geometry::point_type<GeometryOut>::type, - RobustPolicy - > strategy_type; + typename cs_tag<GeometryOut>::type + >::type strategy_type; return sym_difference_insert<GeometryOut>(geometry1, geometry2, robust_policy, out, strategy_type()); } @@ -292,6 +297,216 @@ 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<Collection>::type geometry_out; + + detail::sym_difference::sym_difference_insert<geometry_out>( + 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<Collection>::type geometry_out; + + detail::sym_difference::sym_difference_insert<geometry_out>( + geometry1, geometry2, robust_policy, + range::back_inserter(output_collection)); + } +}; + +} // resolve_strategy + + +namespace resolve_variant +{ + +template <typename Geometry1, typename Geometry2> +struct sym_difference +{ + template <typename Collection, typename Strategy> + 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<rescale_policy_type>(geometry1, + geometry2); + + resolve_strategy::sym_difference::apply(geometry1, geometry2, + robust_policy, + output_collection, + strategy); + } +}; + + +template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2> +struct sym_difference<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2> +{ + template <typename Collection, typename Strategy> + 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 <typename Geometry1> + void operator()(Geometry1 const& geometry1) const + { + sym_difference + < + Geometry1, + Geometry2 + >::apply(geometry1, m_geometry2, m_output_collection, m_strategy); + } + }; + + template <typename Collection, typename Strategy> + static inline void + apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1, + Geometry2 const& geometry2, + Collection& output_collection, + Strategy const& strategy) + { + boost::apply_visitor(visitor<Collection, Strategy>(geometry2, + output_collection, + strategy), + geometry1); + } +}; + + +template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)> +struct sym_difference<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> > +{ + template <typename Collection, typename Strategy> + 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 <typename Geometry2> + void operator()(Geometry2 const& geometry2) const + { + sym_difference + < + Geometry1, + Geometry2 + >::apply(m_geometry1, geometry2, m_output_collection, m_strategy); + } + }; + + template <typename Collection, typename Strategy> + static inline void + apply(Geometry1 const& geometry1, + variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2, + Collection& output_collection, + Strategy const& strategy) + { + boost::apply_visitor(visitor<Collection, Strategy>(geometry1, + output_collection, + strategy), + geometry2); + } +}; + + +template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)> +struct sym_difference<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> > +{ + template <typename Collection, typename Strategy> + 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 <typename Geometry1, typename Geometry2> + void operator()(Geometry1 const& geometry1, + Geometry2 const& geometry2) const + { + sym_difference + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, m_output_collection, m_strategy); + } + }; + + template <typename Collection, typename Strategy> + static inline void + apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1, + variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2, + Collection& output_collection, + Strategy const& strategy) + { + boost::apply_visitor(visitor<Collection, Strategy>(output_collection, + strategy), + geometry1, geometry2); + } +}; + +} // namespace resolve_variant + + /*! \brief \brief_calc2{symmetric difference} \ingroup sym_difference @@ -300,39 +515,64 @@ inline OutputIterator sym_difference_insert(Geometry1 const& geometry1, \tparam Geometry2 \tparam_geometry \tparam Collection output collection, either a multi-geometry, or a std::vector<Geometry> / std::deque<Geometry> 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{distinguish,with strategy} \qbk{[include reference/algorithms/sym_difference.qbk]} */ template < typename Geometry1, typename Geometry2, - typename Collection + typename Collection, + typename Strategy > inline void sym_difference(Geometry1 const& geometry1, - Geometry2 const& geometry2, Collection& output_collection) + Geometry2 const& geometry2, + Collection& output_collection, + Strategy const& strategy) { - concepts::check<Geometry1 const>(); - concepts::check<Geometry2 const>(); - - typedef typename boost::range_value<Collection>::type geometry_out; - concepts::check<geometry_out>(); - - typedef typename geometry::rescale_overlay_policy_type + resolve_variant::sym_difference < Geometry1, Geometry2 - >::type rescale_policy_type; + >::apply(geometry1, geometry2, output_collection, strategy); +} - rescale_policy_type robust_policy - = geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2); - detail::sym_difference::sym_difference_insert<geometry_out>( - geometry1, geometry2, robust_policy, - range::back_inserter(output_collection)); +/*! +\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<Geometry> / std::deque<Geometry> etc +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\param output_collection the output collection + +\qbk{[include reference/algorithms/sym_difference.qbk]} +*/ +template +< + typename Geometry1, + typename Geometry2, + typename Collection +> +inline void sym_difference(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Collection& output_collection) +{ + resolve_variant::sym_difference + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, output_collection, default_strategy()); } |