// Boost.Geometry (aka GGL, Generic Geometry Library) // Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland. // Copyright (c) 2014-2023, Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_POINTLIKE_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_POINTLIKE_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace geometry { #ifndef DOXYGEN_NO_DETAIL namespace detail { namespace overlay { // struct for copying points of the pointlike geometries to output template < typename PointOut, typename GeometryIn, typename TagIn = typename tag::type > struct copy_points : not_implemented {}; template struct copy_points { template static inline void apply(PointIn const& point_in, OutputIterator& oit) { PointOut point_out; geometry::convert(point_in, point_out); *oit++ = point_out; } }; template struct copy_points { template static inline void apply(MultiPointIn const& multi_point_in, OutputIterator& oit) { for (auto it = boost::begin(multi_point_in); it != boost::end(multi_point_in); ++it) { PointOut point_out; geometry::convert(*it, point_out); *oit++ = point_out; } } }; // action struct for difference/intersection template struct action_selector_pl {}; template struct action_selector_pl { template < typename Point, typename OutputIterator > static inline void apply(Point const& point, bool is_common, OutputIterator& oit) { if ( is_common ) { copy_points::apply(point, oit); } } }; template struct action_selector_pl { template < typename Point, typename OutputIterator > static inline void apply(Point const& point, bool is_common, OutputIterator& oit) { if ( !is_common ) { copy_points::apply(point, oit); } } }; //=========================================================================== // difference/intersection of point-point template < typename Point1, typename Point2, typename PointOut, overlay_type OverlayType > struct point_point_point { template static inline OutputIterator apply(Point1 const& point1, Point2 const& point2, RobustPolicy const& , OutputIterator oit, Strategy const& strategy) { action_selector_pl < PointOut, OverlayType >::apply(point1, detail::equals::equals_point_point(point1, point2, strategy), oit); return oit; } }; // difference of multipoint-point // // the apply method in the following struct is called only for // difference; for intersection the reversal will // always call the point-multipoint version template < typename MultiPoint, typename Point, typename PointOut, overlay_type OverlayType > struct multipoint_point_point { template static inline OutputIterator apply(MultiPoint const& multipoint, Point const& point, RobustPolicy const& , OutputIterator oit, Strategy const& strategy) { BOOST_GEOMETRY_ASSERT( OverlayType == overlay_difference ); for (auto it = boost::begin(multipoint); it != boost::end(multipoint); ++it) { action_selector_pl < PointOut, OverlayType >::apply(*it, detail::equals::equals_point_point(*it, point, strategy), oit); } return oit; } }; // difference/intersection of point-multipoint template < typename Point, typename MultiPoint, typename PointOut, overlay_type OverlayType > struct point_multipoint_point { template static inline OutputIterator apply(Point const& point, MultiPoint const& multipoint, RobustPolicy const& , OutputIterator oit, Strategy const& strategy) { typedef action_selector_pl action; for (auto it = boost::begin(multipoint); it != boost::end(multipoint); ++it) { if ( detail::equals::equals_point_point(*it, point, strategy) ) { action::apply(point, true, oit); return oit; } } action::apply(point, false, oit); return oit; } }; // difference/intersection of multipoint-multipoint template < typename MultiPoint1, typename MultiPoint2, typename PointOut, overlay_type OverlayType > struct multipoint_multipoint_point { template static inline OutputIterator apply(MultiPoint1 const& multipoint1, MultiPoint2 const& multipoint2, RobustPolicy const& robust_policy, OutputIterator oit, Strategy const& strategy) { typedef geometry::less less_type; if BOOST_GEOMETRY_CONSTEXPR (OverlayType != overlay_difference) { if (boost::size(multipoint1) > boost::size(multipoint2)) { return multipoint_multipoint_point < MultiPoint2, MultiPoint1, PointOut, OverlayType >::apply(multipoint2, multipoint1, robust_policy, oit, strategy); } } typedef typename boost::range_value::type point2_type; std::vector points2(boost::begin(multipoint2), boost::end(multipoint2)); less_type const less = less_type(); std::sort(points2.begin(), points2.end(), less); for (auto it1 = boost::begin(multipoint1); it1 != boost::end(multipoint1); ++it1) { bool found = std::binary_search(points2.begin(), points2.end(), *it1, less); action_selector_pl < PointOut, OverlayType >::apply(*it1, found, oit); } return oit; } }; }} // namespace detail::overlay #endif // DOXYGEN_NO_DETAIL //=========================================================================== #ifndef DOXYGEN_NO_DISPATCH namespace detail_dispatch { namespace overlay { // dispatch struct for pointlike-pointlike difference/intersection // computation template < typename PointLike1, typename PointLike2, typename PointOut, overlay_type OverlayType, typename Tag1, typename Tag2 > struct pointlike_pointlike_point : not_implemented {}; template < typename Point1, typename Point2, typename PointOut, overlay_type OverlayType > struct pointlike_pointlike_point < Point1, Point2, PointOut, OverlayType, point_tag, point_tag > : detail::overlay::point_point_point < Point1, Point2, PointOut, OverlayType > {}; template < typename Point, typename MultiPoint, typename PointOut, overlay_type OverlayType > struct pointlike_pointlike_point < Point, MultiPoint, PointOut, OverlayType, point_tag, multi_point_tag > : detail::overlay::point_multipoint_point < Point, MultiPoint, PointOut, OverlayType > {}; template < typename MultiPoint, typename Point, typename PointOut, overlay_type OverlayType > struct pointlike_pointlike_point < MultiPoint, Point, PointOut, OverlayType, multi_point_tag, point_tag > : detail::overlay::multipoint_point_point < MultiPoint, Point, PointOut, OverlayType > {}; template < typename MultiPoint1, typename MultiPoint2, typename PointOut, overlay_type OverlayType > struct pointlike_pointlike_point < MultiPoint1, MultiPoint2, PointOut, OverlayType, multi_point_tag, multi_point_tag > : detail::overlay::multipoint_multipoint_point < MultiPoint1, MultiPoint2, PointOut, OverlayType > {}; }} // namespace detail_dispatch::overlay #endif // DOXYGEN_NO_DISPATCH //=========================================================================== #ifndef DOXYGEN_NO_DETAIL namespace detail { namespace overlay { // generic pointlike-pointlike union implementation template < typename PointLike1, typename PointLike2, typename PointOut > struct union_pointlike_pointlike_point { template static inline OutputIterator apply(PointLike1 const& pointlike1, PointLike2 const& pointlike2, RobustPolicy const& robust_policy, OutputIterator oit, Strategy const& strategy) { copy_points::apply(pointlike1, oit); return detail_dispatch::overlay::pointlike_pointlike_point < PointLike2, PointLike1, PointOut, overlay_difference, typename tag::type, typename tag::type >::apply(pointlike2, pointlike1, robust_policy, oit, strategy); } }; }} // namespace detail::overlay #endif // DOXYGEN_NO_DETAIL }} // namespace boost::geometry #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_POINTLIKE_HPP