diff options
Diffstat (limited to 'boost/geometry/algorithms/equals.hpp')
-rw-r--r-- | boost/geometry/algorithms/equals.hpp | 645 |
1 files changed, 2 insertions, 643 deletions
diff --git a/boost/geometry/algorithms/equals.hpp b/boost/geometry/algorithms/equals.hpp index 1479ea66fa..77b8977d22 100644 --- a/boost/geometry/algorithms/equals.hpp +++ b/boost/geometry/algorithms/equals.hpp @@ -22,649 +22,8 @@ #define BOOST_GEOMETRY_ALGORITHMS_EQUALS_HPP -#include <cstddef> -#include <vector> - -#include <boost/range.hpp> -#include <boost/type_traits/is_base_of.hpp> - -#include <boost/variant/apply_visitor.hpp> -#include <boost/variant/static_visitor.hpp> -#include <boost/variant/variant_fwd.hpp> - -#include <boost/geometry/core/access.hpp> -#include <boost/geometry/core/coordinate_dimension.hpp> -#include <boost/geometry/core/geometry_id.hpp> -#include <boost/geometry/core/reverse_dispatch.hpp> -#include <boost/geometry/core/tags.hpp> - -#include <boost/geometry/geometries/concepts/check.hpp> - -#include <boost/geometry/algorithms/detail/equals/point_point.hpp> -#include <boost/geometry/algorithms/not_implemented.hpp> - -// For trivial checks -#include <boost/geometry/algorithms/area.hpp> -#include <boost/geometry/algorithms/length.hpp> -#include <boost/geometry/util/math.hpp> -#include <boost/geometry/util/select_coordinate_type.hpp> -#include <boost/geometry/util/select_most_precise.hpp> - -#include <boost/geometry/algorithms/detail/equals/collect_vectors.hpp> -#include <boost/geometry/algorithms/relate.hpp> -#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp> - -#include <boost/geometry/views/detail/indexed_point_view.hpp> - - -namespace boost { namespace geometry -{ - -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace equals -{ - - -template -< - std::size_t Dimension, - std::size_t DimensionCount -> -struct point_point -{ - template <typename Point1, typename Point2, typename Strategy> - static inline bool apply(Point1 const& point1, Point2 const& point2, Strategy const& strategy) - { - return ! detail::disjoint::point_point - < - Point1, Point2, - Dimension, DimensionCount - >::apply(point1, point2, strategy); - } -}; - - -template -< - std::size_t Dimension, - std::size_t DimensionCount -> -struct box_box -{ - template <typename Box1, typename Box2, typename Strategy> - static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy) - { - if (!geometry::math::equals(get<min_corner, Dimension>(box1), get<min_corner, Dimension>(box2)) - || !geometry::math::equals(get<max_corner, Dimension>(box1), get<max_corner, Dimension>(box2))) - { - return false; - } - return box_box<Dimension + 1, DimensionCount>::apply(box1, box2, strategy); - } -}; - -template <std::size_t DimensionCount> -struct box_box<DimensionCount, DimensionCount> -{ - template <typename Box1, typename Box2, typename Strategy> - static inline bool apply(Box1 const& , Box2 const& , Strategy const& ) - { - return true; - } -}; - - -struct segment_segment -{ - template <typename Segment1, typename Segment2, typename Strategy> - static inline bool apply(Segment1 const& segment1, Segment2 const& segment2, Strategy const& ) - { - return equals::equals_point_point( - indexed_point_view<Segment1 const, 0>(segment1), - indexed_point_view<Segment2 const, 0>(segment2) ) - ? equals::equals_point_point( - indexed_point_view<Segment1 const, 1>(segment1), - indexed_point_view<Segment2 const, 1>(segment2) ) - : ( equals::equals_point_point( - indexed_point_view<Segment1 const, 0>(segment1), - indexed_point_view<Segment2 const, 1>(segment2) ) - && equals::equals_point_point( - indexed_point_view<Segment1 const, 1>(segment1), - indexed_point_view<Segment2 const, 0>(segment2) ) - ); - } -}; - - -struct area_check -{ - template <typename Geometry1, typename Geometry2, typename Strategy> - static inline bool apply(Geometry1 const& geometry1, - Geometry2 const& geometry2, - Strategy const& strategy) - { - return geometry::math::equals( - geometry::area(geometry1, - strategy.template get_area_strategy<Geometry1>()), - geometry::area(geometry2, - strategy.template get_area_strategy<Geometry2>())); - } -}; - - -struct length_check -{ - template <typename Geometry1, typename Geometry2, typename Strategy> - static inline bool apply(Geometry1 const& geometry1, - Geometry2 const& geometry2, - Strategy const& strategy) - { - return geometry::math::equals( - geometry::length(geometry1, - strategy.template get_distance_strategy<Geometry1>()), - geometry::length(geometry2, - strategy.template get_distance_strategy<Geometry2>())); - } -}; - - -template <typename Geometry1, typename Geometry2, typename IntersectionStrategy> -struct collected_vector -{ - typedef typename geometry::select_most_precise - < - typename select_coordinate_type - < - Geometry1, Geometry2 - >::type, - double - >::type calculation_type; - - typedef geometry::collected_vector - < - calculation_type, - Geometry1, - typename IntersectionStrategy::side_strategy_type - > type; -}; - -template <typename TrivialCheck> -struct equals_by_collection -{ - template <typename Geometry1, typename Geometry2, typename Strategy> - static inline bool apply(Geometry1 const& geometry1, - Geometry2 const& geometry2, - Strategy const& strategy) - { - if (! TrivialCheck::apply(geometry1, geometry2, strategy)) - { - return false; - } - - typedef typename collected_vector - < - Geometry1, Geometry2, Strategy - >::type collected_vector_type; - - std::vector<collected_vector_type> c1, c2; - - geometry::collect_vectors(c1, geometry1); - geometry::collect_vectors(c2, geometry2); - - if (boost::size(c1) != boost::size(c2)) - { - return false; - } - - std::sort(c1.begin(), c1.end()); - std::sort(c2.begin(), c2.end()); - - // Just check if these vectors are equal. - return std::equal(c1.begin(), c1.end(), c2.begin()); - } -}; - -template<typename Geometry1, typename Geometry2> -struct equals_by_relate - : detail::relate::relate_impl - < - detail::de9im::static_mask_equals_type, - Geometry1, - Geometry2 - > -{}; - -// If collect_vectors which is a SideStrategy-dispatched optimization -// is implemented in a way consistent with the Intersection/Side Strategy -// then collect_vectors is used, otherwise relate is used. -// NOTE: the result could be coneptually different for invalid -// geometries in different coordinate systems because collect_vectors -// and relate treat invalid geometries differently. -template<typename TrivialCheck> -struct equals_by_collection_or_relate -{ - template <typename Geometry1, typename Geometry2, typename Strategy> - static inline bool apply(Geometry1 const& geometry1, - Geometry2 const& geometry2, - Strategy const& strategy) - { - typedef typename boost::is_base_of - < - nyi::not_implemented_tag, - typename collected_vector - < - Geometry1, Geometry2, Strategy - >::type - >::type enable_relate_type; - - return apply(geometry1, geometry2, strategy, enable_relate_type()); - } - -private: - template <typename Geometry1, typename Geometry2, typename Strategy> - static inline bool apply(Geometry1 const& geometry1, - Geometry2 const& geometry2, - Strategy const& strategy, - boost::false_type /*enable_relate*/) - { - return equals_by_collection<TrivialCheck>::apply(geometry1, geometry2, strategy); - } - - template <typename Geometry1, typename Geometry2, typename Strategy> - static inline bool apply(Geometry1 const& geometry1, - Geometry2 const& geometry2, - Strategy const& strategy, - boost::true_type /*enable_relate*/) - { - return equals_by_relate<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy); - } -}; - - -}} // namespace detail::equals -#endif // DOXYGEN_NO_DETAIL - - -#ifndef DOXYGEN_NO_DISPATCH -namespace dispatch -{ - -template -< - typename Geometry1, - typename Geometry2, - typename Tag1 = typename tag<Geometry1>::type, - typename Tag2 = typename tag<Geometry2>::type, - std::size_t DimensionCount = dimension<Geometry1>::type::value, - bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value -> -struct equals: not_implemented<Tag1, Tag2> -{}; - - -// If reversal is needed, perform it -template -< - typename Geometry1, typename Geometry2, - typename Tag1, typename Tag2, - std::size_t DimensionCount -> -struct equals<Geometry1, Geometry2, Tag1, Tag2, DimensionCount, true> - : equals<Geometry2, Geometry1, Tag2, Tag1, DimensionCount, false> -{ - template <typename Strategy> - static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy) - { - return equals - < - Geometry2, Geometry1, - Tag2, Tag1, - DimensionCount, - false - >::apply(g2, g1, strategy); - } -}; - - -template <typename P1, typename P2, std::size_t DimensionCount, bool Reverse> -struct equals<P1, P2, point_tag, point_tag, DimensionCount, Reverse> - : detail::equals::point_point<0, DimensionCount> -{}; - -template <typename MultiPoint1, typename MultiPoint2, std::size_t DimensionCount, bool Reverse> -struct equals<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag, DimensionCount, Reverse> - : detail::equals::equals_by_relate<MultiPoint1, MultiPoint2> -{}; - -template <typename MultiPoint, typename Point, std::size_t DimensionCount, bool Reverse> -struct equals<MultiPoint, Point, multi_point_tag, point_tag, DimensionCount, Reverse> - : detail::equals::equals_by_relate<MultiPoint, Point> -{}; - -template <typename MultiPoint, typename Point, std::size_t DimensionCount, bool Reverse> -struct equals<Point, MultiPoint, point_tag, multi_point_tag, DimensionCount, Reverse> - : detail::equals::equals_by_relate<Point, MultiPoint> -{}; - -template <typename Box1, typename Box2, std::size_t DimensionCount, bool Reverse> -struct equals<Box1, Box2, box_tag, box_tag, DimensionCount, Reverse> - : detail::equals::box_box<0, DimensionCount> -{}; - - -template <typename Ring1, typename Ring2, bool Reverse> -struct equals<Ring1, Ring2, ring_tag, ring_tag, 2, Reverse> - : detail::equals::equals_by_collection_or_relate<detail::equals::area_check> -{}; - - -template <typename Polygon1, typename Polygon2, bool Reverse> -struct equals<Polygon1, Polygon2, polygon_tag, polygon_tag, 2, Reverse> - : detail::equals::equals_by_collection_or_relate<detail::equals::area_check> -{}; - - -template <typename Polygon, typename Ring, bool Reverse> -struct equals<Polygon, Ring, polygon_tag, ring_tag, 2, Reverse> - : detail::equals::equals_by_collection_or_relate<detail::equals::area_check> -{}; - - -template <typename Ring, typename Box, bool Reverse> -struct equals<Ring, Box, ring_tag, box_tag, 2, Reverse> - : detail::equals::equals_by_collection<detail::equals::area_check> -{}; - - -template <typename Polygon, typename Box, bool Reverse> -struct equals<Polygon, Box, polygon_tag, box_tag, 2, Reverse> - : detail::equals::equals_by_collection<detail::equals::area_check> -{}; - -template <typename Segment1, typename Segment2, std::size_t DimensionCount, bool Reverse> -struct equals<Segment1, Segment2, segment_tag, segment_tag, DimensionCount, Reverse> - : detail::equals::segment_segment -{}; - -template <typename LineString1, typename LineString2, bool Reverse> -struct equals<LineString1, LineString2, linestring_tag, linestring_tag, 2, Reverse> - : detail::equals::equals_by_relate<LineString1, LineString2> -{}; - -template <typename LineString, typename MultiLineString, bool Reverse> -struct equals<LineString, MultiLineString, linestring_tag, multi_linestring_tag, 2, Reverse> - : detail::equals::equals_by_relate<LineString, MultiLineString> -{}; - -template <typename MultiLineString1, typename MultiLineString2, bool Reverse> -struct equals<MultiLineString1, MultiLineString2, multi_linestring_tag, multi_linestring_tag, 2, Reverse> - : detail::equals::equals_by_relate<MultiLineString1, MultiLineString2> -{}; - - -template <typename MultiPolygon1, typename MultiPolygon2, bool Reverse> -struct equals - < - MultiPolygon1, MultiPolygon2, - multi_polygon_tag, multi_polygon_tag, - 2, - Reverse - > - : detail::equals::equals_by_collection_or_relate<detail::equals::area_check> -{}; - - -template <typename Polygon, typename MultiPolygon, bool Reverse> -struct equals - < - Polygon, MultiPolygon, - polygon_tag, multi_polygon_tag, - 2, - Reverse - > - : detail::equals::equals_by_collection_or_relate<detail::equals::area_check> -{}; - -template <typename MultiPolygon, typename Ring, bool Reverse> -struct equals - < - MultiPolygon, Ring, - multi_polygon_tag, ring_tag, - 2, - Reverse - > - : detail::equals::equals_by_collection_or_relate<detail::equals::area_check> -{}; - - -} // namespace dispatch -#endif // DOXYGEN_NO_DISPATCH - - -namespace resolve_strategy -{ - -struct equals -{ - template <typename Geometry1, typename Geometry2, typename Strategy> - static inline bool apply(Geometry1 const& geometry1, - Geometry2 const& geometry2, - Strategy const& strategy) - { - return dispatch::equals - < - Geometry1, Geometry2 - >::apply(geometry1, geometry2, strategy); - } - - template <typename Geometry1, typename Geometry2> - static inline bool apply(Geometry1 const& geometry1, - Geometry2 const& geometry2, - default_strategy) - { - typedef typename strategy::relate::services::default_strategy - < - Geometry1, - Geometry2 - >::type strategy_type; - - return dispatch::equals - < - Geometry1, Geometry2 - >::apply(geometry1, geometry2, strategy_type()); - } -}; - -} // namespace resolve_strategy - - -namespace resolve_variant { - -template <typename Geometry1, typename Geometry2> -struct equals -{ - template <typename Strategy> - static inline bool apply(Geometry1 const& geometry1, - Geometry2 const& geometry2, - Strategy const& strategy) - { - concepts::check_concepts_and_equal_dimensions - < - Geometry1 const, - Geometry2 const - >(); - - return resolve_strategy::equals - ::apply(geometry1, geometry2, strategy); - } -}; - -template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2> -struct equals<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2> -{ - template <typename Strategy> - struct visitor: static_visitor<bool> - { - Geometry2 const& m_geometry2; - Strategy const& m_strategy; - - visitor(Geometry2 const& geometry2, Strategy const& strategy) - : m_geometry2(geometry2) - , m_strategy(strategy) - {} - - template <typename Geometry1> - inline bool operator()(Geometry1 const& geometry1) const - { - return equals<Geometry1, Geometry2> - ::apply(geometry1, m_geometry2, m_strategy); - } - - }; - - template <typename Strategy> - static inline bool apply( - boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1, - Geometry2 const& geometry2, - Strategy const& strategy - ) - { - return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1); - } -}; - -template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)> -struct equals<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > -{ - template <typename Strategy> - struct visitor: static_visitor<bool> - { - Geometry1 const& m_geometry1; - Strategy const& m_strategy; - - visitor(Geometry1 const& geometry1, Strategy const& strategy) - : m_geometry1(geometry1) - , m_strategy(strategy) - {} - - template <typename Geometry2> - inline bool operator()(Geometry2 const& geometry2) const - { - return equals<Geometry1, Geometry2> - ::apply(m_geometry1, geometry2, m_strategy); - } - - }; - - template <typename Strategy> - static inline bool apply( - Geometry1 const& geometry1, - boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2, - Strategy const& strategy - ) - { - return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2); - } -}; - -template < - BOOST_VARIANT_ENUM_PARAMS(typename T1), - BOOST_VARIANT_ENUM_PARAMS(typename T2) -> -struct equals< - boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, - boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> -> -{ - template <typename Strategy> - struct visitor: static_visitor<bool> - { - Strategy const& m_strategy; - - visitor(Strategy const& strategy) - : m_strategy(strategy) - {} - - template <typename Geometry1, typename Geometry2> - inline bool operator()(Geometry1 const& geometry1, - Geometry2 const& geometry2) const - { - return equals<Geometry1, Geometry2> - ::apply(geometry1, geometry2, m_strategy); - } - - }; - - template <typename Strategy> - static inline bool apply( - boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1, - boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2, - Strategy const& strategy - ) - { - return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2); - } -}; - -} // namespace resolve_variant - - -/*! -\brief \brief_check{are spatially equal} -\details \details_check12{equals, is spatially equal}. Spatially equal means - that the same point set is included. A box can therefore be spatially equal - to a ring or a polygon, or a linestring can be spatially equal to a - multi-linestring or a segment. This only works theoretically, not all - combinations are implemented yet. -\ingroup equals -\tparam Geometry1 \tparam_geometry -\tparam Geometry2 \tparam_geometry -\tparam Strategy \tparam_strategy{Equals} -\param geometry1 \param_geometry -\param geometry2 \param_geometry -\param strategy \param_strategy{equals} -\return \return_check2{are spatially equal} - -\qbk{distinguish,with strategy} -\qbk{[include reference/algorithms/equals.qbk]} - */ -template <typename Geometry1, typename Geometry2, typename Strategy> -inline bool equals(Geometry1 const& geometry1, - Geometry2 const& geometry2, - Strategy const& strategy) -{ - return resolve_variant::equals - < - Geometry1, Geometry2 - >::apply(geometry1, geometry2, strategy); -} - - -/*! -\brief \brief_check{are spatially equal} -\details \details_check12{equals, is spatially equal}. Spatially equal means - that the same point set is included. A box can therefore be spatially equal - to a ring or a polygon, or a linestring can be spatially equal to a - multi-linestring or a segment. This only works theoretically, not all - combinations are implemented yet. -\ingroup equals -\tparam Geometry1 \tparam_geometry -\tparam Geometry2 \tparam_geometry -\param geometry1 \param_geometry -\param geometry2 \param_geometry -\return \return_check2{are spatially equal} - -\qbk{[include reference/algorithms/equals.qbk]} - */ -template <typename Geometry1, typename Geometry2> -inline bool equals(Geometry1 const& geometry1, Geometry2 const& geometry2) -{ - return resolve_variant::equals<Geometry1, Geometry2> - ::apply(geometry1, geometry2, default_strategy()); -} - - -}} // namespace boost::geometry +#include <boost/geometry/algorithms/detail/equals/interface.hpp> +#include <boost/geometry/algorithms/detail/equals/implementation.hpp> #endif // BOOST_GEOMETRY_ALGORITHMS_EQUALS_HPP |