123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444 |
- // 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 <algorithm>
- #include <vector>
- #include <boost/range/begin.hpp>
- #include <boost/range/end.hpp>
- #include <boost/range/size.hpp>
- #include <boost/range/value_type.hpp>
- #include <boost/geometry/algorithms/convert.hpp>
- #include <boost/geometry/algorithms/not_implemented.hpp>
- #include <boost/geometry/algorithms/detail/equals/point_point.hpp>
- #include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
- #include <boost/geometry/core/assert.hpp>
- #include <boost/geometry/core/point_type.hpp>
- #include <boost/geometry/core/tag.hpp>
- #include <boost/geometry/core/tags.hpp>
- #include <boost/geometry/policies/compare.hpp>
- #include <boost/geometry/util/constexpr.hpp>
- 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<GeometryIn>::type
- >
- struct copy_points
- : not_implemented<PointOut, GeometryIn>
- {};
- template <typename PointOut, typename PointIn>
- struct copy_points<PointOut, PointIn, point_tag>
- {
- template <typename OutputIterator>
- static inline void apply(PointIn const& point_in,
- OutputIterator& oit)
- {
- PointOut point_out;
- geometry::convert(point_in, point_out);
- *oit++ = point_out;
- }
- };
- template <typename PointOut, typename MultiPointIn>
- struct copy_points<PointOut, MultiPointIn, multi_point_tag>
- {
- template <typename OutputIterator>
- 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 <typename PointOut, overlay_type OverlayType>
- struct action_selector_pl
- {};
- template <typename PointOut>
- struct action_selector_pl<PointOut, overlay_intersection>
- {
- template
- <
- typename Point,
- typename OutputIterator
- >
- static inline void apply(Point const& point,
- bool is_common,
- OutputIterator& oit)
- {
- if ( is_common )
- {
- copy_points<PointOut, Point>::apply(point, oit);
- }
- }
- };
- template <typename PointOut>
- struct action_selector_pl<PointOut, overlay_difference>
- {
- template
- <
- typename Point,
- typename OutputIterator
- >
- static inline void apply(Point const& point,
- bool is_common,
- OutputIterator& oit)
- {
- if ( !is_common )
- {
- copy_points<PointOut, Point>::apply(point, oit);
- }
- }
- };
- //===========================================================================
- // difference/intersection of point-point
- template
- <
- typename Point1,
- typename Point2,
- typename PointOut,
- overlay_type OverlayType
- >
- struct point_point_point
- {
- template <typename RobustPolicy, typename OutputIterator, typename Strategy>
- 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 <typename RobustPolicy, typename OutputIterator, typename Strategy>
- 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 <typename RobustPolicy, typename OutputIterator, typename Strategy>
- static inline OutputIterator apply(Point const& point,
- MultiPoint const& multipoint,
- RobustPolicy const& ,
- OutputIterator oit,
- Strategy const& strategy)
- {
- typedef action_selector_pl<PointOut, OverlayType> 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 <typename RobustPolicy, typename OutputIterator, typename Strategy>
- static inline OutputIterator apply(MultiPoint1 const& multipoint1,
- MultiPoint2 const& multipoint2,
- RobustPolicy const& robust_policy,
- OutputIterator oit,
- Strategy const& strategy)
- {
- typedef geometry::less<void, -1, Strategy> 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<MultiPoint2>::type point2_type;
- std::vector<point2_type> 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<PointLike1, PointLike2, PointOut>
- {};
- 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 <typename RobustPolicy, typename OutputIterator, typename Strategy>
- static inline OutputIterator apply(PointLike1 const& pointlike1,
- PointLike2 const& pointlike2,
- RobustPolicy const& robust_policy,
- OutputIterator oit,
- Strategy const& strategy)
- {
- copy_points<PointOut, PointLike1>::apply(pointlike1, oit);
- return detail_dispatch::overlay::pointlike_pointlike_point
- <
- PointLike2, PointLike1, PointOut, overlay_difference,
- typename tag<PointLike2>::type,
- typename tag<PointLike1>::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
|