// Boost.Geometry // Copyright (c) 2020-2024, Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fysikopoulos, 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_INTERSECTION_AREAL_AREAL_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_AREAL_AREAL_HPP #include #include namespace boost { namespace geometry { #ifndef DOXYGEN_NO_DETAIL namespace detail { namespace intersection { template < typename GeometryOut, typename OutTag = typename geometry::detail::setop_insert_output_tag < typename geometry::detail::output_geometry_value < GeometryOut >::type >::type > struct intersection_areal_areal_ { template < typename Areal1, typename Areal2, typename Strategy > static inline void apply(Areal1 const& areal1, Areal2 const& areal2, GeometryOut& geometry_out, Strategy const& strategy) { geometry::dispatch::intersection_insert < Areal1, Areal2, typename boost::range_value::type, overlay_intersection >::apply(areal1, areal2, geometry::range::back_inserter(geometry_out), strategy); } }; // TODO: Ideally this should be done in one call of intersection_insert // just like it's done for all other combinations template struct intersection_areal_areal_ { template < typename Areal1, typename Areal2, typename Strategy > static inline void apply(Areal1 const& areal1, Areal2 const& areal2, TupledOut& geometry_out, Strategy const& strategy) { using single_out = typename geometry::detail::output_geometry_value < TupledOut >::type; boost::ignore_unused < geometry::detail::expect_output < Areal1, Areal2, single_out, point_tag, linestring_tag, polygon_tag > >(); using areal = geometry::detail::output_geometry_access < single_out, polygon_tag, polygon_tag >; using linear = geometry::detail::output_geometry_access < single_out, linestring_tag, linestring_tag >; using pointlike = geometry::detail::output_geometry_access < single_out, point_tag, point_tag >; // A * A -> A call_intersection(areal1, areal2, areal::get(geometry_out), strategy); bool const is_areal_empty = boost::empty(areal::get(geometry_out)); TupledOut temp_out; // L * L -> (L, P) call_intersection(geometry::detail::boundary_view(areal1), geometry::detail::boundary_view(areal2), ! is_areal_empty ? temp_out : geometry_out, strategy); if (! is_areal_empty) { // NOTE: the original areal geometry could be used instead of boundary here // however this results in static assert failure related to rescale policy // After the removing of rescaling replacing boundary with areal geometry results in // some tests failing. using areal_out_type = typename geometry::tuples::element < areal::index, TupledOut >::type; using areal_out_boundary_type = geometry::detail::boundary_view < areal_out_type const >; areal_out_boundary_type areal_out_boundary(areal::get(geometry_out)); // L - L -> L call_difference(linear::get(temp_out), areal_out_boundary, linear::get(geometry_out), strategy); // P - L -> P call_difference(pointlike::get(temp_out), areal_out_boundary, pointlike::get(geometry_out), strategy); } return; } private: template < typename Geometry1, typename Geometry2, typename GeometryOut, typename Strategy > static inline void call_intersection(Geometry1 const& geometry1, Geometry2 const& geometry2, GeometryOut& geometry_out, Strategy const& strategy) { geometry::dispatch::intersection_insert < Geometry1, Geometry2, typename geometry::detail::output_geometry_value < GeometryOut >::type, overlay_intersection >::apply(geometry1, geometry2, geometry::detail::output_geometry_back_inserter(geometry_out), strategy); } template < typename Geometry1, typename Geometry2, typename GeometryOut, typename Strategy > static inline void call_difference(Geometry1 const& geometry1, Geometry2 const& geometry2, GeometryOut& geometry_out, Strategy const& strategy) { geometry::dispatch::intersection_insert < Geometry1, Geometry2, typename boost::range_value::type, overlay_difference >::apply(geometry1, geometry2, geometry::range::back_inserter(geometry_out), strategy); } }; struct intersection_areal_areal { template < typename Areal1, typename Areal2, typename GeometryOut, typename Strategy > static inline bool apply(Areal1 const& areal1, Areal2 const& areal2, GeometryOut& geometry_out, Strategy const& strategy) { intersection_areal_areal_ < GeometryOut >::apply(areal1, areal2, geometry_out, strategy); return true; } }; }} // namespace detail::intersection #endif // DOXYGEN_NO_DETAIL #ifndef DOXYGEN_NO_DISPATCH namespace dispatch { template < typename Polygon1, typename Polygon2 > struct intersection < Polygon1, Polygon2, polygon_tag, polygon_tag, false > : detail::intersection::intersection_areal_areal {}; template < typename Polygon, typename Ring > struct intersection < Polygon, Ring, polygon_tag, ring_tag, false > : detail::intersection::intersection_areal_areal {}; template < typename Ring1, typename Ring2 > struct intersection < Ring1, Ring2, ring_tag, ring_tag, false > : detail::intersection::intersection_areal_areal {}; template < typename Polygon, typename MultiPolygon > struct intersection < Polygon, MultiPolygon, polygon_tag, multi_polygon_tag, false > : detail::intersection::intersection_areal_areal {}; template < typename MultiPolygon, typename Ring > struct intersection < MultiPolygon, Ring, multi_polygon_tag, ring_tag, false > : detail::intersection::intersection_areal_areal {}; template < typename MultiPolygon1, typename MultiPolygon2 > struct intersection < MultiPolygon1, MultiPolygon2, multi_polygon_tag, multi_polygon_tag, false > : detail::intersection::intersection_areal_areal {}; } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH }} // namespace boost::geometry #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_AREAL_AREAL_HPP