From 670c52d3e3754cf997f7b2aef503fc4bf3cd5333 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Mon, 13 Apr 2020 15:54:46 +0200 Subject: [PATCH] [intersection] Modify tupled-output utils and move them out from intersection code. --- .../detail/intersection/areal_areal.hpp | 7 +- .../algorithms/detail/intersection/multi.hpp | 75 ++++- .../detail/overlay/intersection_insert.hpp | 127 ++------ .../algorithms/detail/tupled_output.hpp | 291 +++++++++++++++--- 4 files changed, 348 insertions(+), 152 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/intersection/areal_areal.hpp b/include/boost/geometry/algorithms/detail/intersection/areal_areal.hpp index a9bf98fab..994c3c7da 100644 --- a/include/boost/geometry/algorithms/detail/intersection/areal_areal.hpp +++ b/include/boost/geometry/algorithms/detail/intersection/areal_areal.hpp @@ -26,7 +26,7 @@ namespace detail { namespace intersection template < typename GeometryOut, - typename OutTag = typename detail::intersection::tag + typename OutTag = typename geometry::detail::setop_insert_output_tag < typename geometry::detail::output_geometry_value < @@ -85,9 +85,10 @@ struct intersection_areal_areal_ boost::ignore_unused < - detail::intersection::expect_output_pla + geometry::detail::expect_output < - Areal1, Areal2, single_out + Areal1, Areal2, single_out, + point_tag, linestring_tag, polygon_tag > >(); diff --git a/include/boost/geometry/algorithms/detail/intersection/multi.hpp b/include/boost/geometry/algorithms/detail/intersection/multi.hpp index 6a8c1f6c6..3b2b1461c 100644 --- a/include/boost/geometry/algorithms/detail/intersection/multi.hpp +++ b/include/boost/geometry/algorithms/detail/intersection/multi.hpp @@ -432,8 +432,8 @@ struct intersection_insert TupledOut, OverlayType, ReverseMultiLinestring, ReverseRing, - multi_linestring_tag, ring_tag, detail::intersection::tupled_output_tag, - linear_tag, areal_tag, detail::intersection::tupled_output_tag + multi_linestring_tag, ring_tag, detail::tupled_output_tag, + linear_tag, areal_tag, detail::tupled_output_tag > : detail::intersection::intersection_of_multi_linestring_with_areal < ReverseRing, @@ -441,7 +441,19 @@ struct intersection_insert OverlayType, true > - , detail::intersection::expect_output_pl + , detail::expect_output + < + MultiLinestring, Ring, TupledOut, + // NOTE: points can be the result only in case of intersection. + // TODO: union should require L and A + typename boost::mpl::if_c + < + (OverlayType == overlay_intersection), + point_tag, + void + >::type, + linestring_tag + > {}; @@ -458,8 +470,8 @@ struct intersection_insert TupledOut, OverlayType, ReverseMultiLinestring, ReversePolygon, - multi_linestring_tag, polygon_tag, detail::intersection::tupled_output_tag, - linear_tag, areal_tag, detail::intersection::tupled_output_tag + multi_linestring_tag, polygon_tag, detail::tupled_output_tag, + linear_tag, areal_tag, detail::tupled_output_tag > : detail::intersection::intersection_of_multi_linestring_with_areal < ReversePolygon, @@ -467,7 +479,19 @@ struct intersection_insert OverlayType, true > - , detail::intersection::expect_output_pl + , detail::expect_output + < + MultiLinestring, Polygon, TupledOut, + // NOTE: points can be the result only in case of intersection. + // TODO: union should require L and A + typename boost::mpl::if_c + < + (OverlayType == overlay_intersection), + point_tag, + void + >::type, + linestring_tag + > {}; template @@ -483,8 +507,8 @@ struct intersection_insert TupledOut, OverlayType, ReversePolygon, ReverseMultiLinestring, - polygon_tag, multi_linestring_tag, detail::intersection::tupled_output_tag, - areal_tag, linear_tag, detail::intersection::tupled_output_tag + polygon_tag, multi_linestring_tag, detail::tupled_output_tag, + areal_tag, linear_tag, detail::tupled_output_tag > : detail::intersection::intersection_of_areal_with_multi_linestring < ReversePolygon, @@ -492,7 +516,22 @@ struct intersection_insert OverlayType, true > - , detail::intersection::expect_output_pl + , detail::expect_output + < + Polygon, MultiLinestring, TupledOut, + // NOTE: points can be the result only in case of intersection. + // TODO: union should require L and A + // TODO: in general the result of difference should depend on the first argument + // but this specialization calls L/A in reality so the first argument is linear. + // So expect only L for difference? + typename boost::mpl::if_c + < + (OverlayType == overlay_intersection), + point_tag, + void + >::type, + linestring_tag + > {}; template @@ -508,8 +547,8 @@ struct intersection_insert TupledOut, OverlayType, ReverseMultiLinestring, ReverseMultiPolygon, - multi_linestring_tag, multi_polygon_tag, detail::intersection::tupled_output_tag, - linear_tag, areal_tag, detail::intersection::tupled_output_tag + multi_linestring_tag, multi_polygon_tag, detail::tupled_output_tag, + linear_tag, areal_tag, detail::tupled_output_tag > : detail::intersection::intersection_of_multi_linestring_with_areal < ReverseMultiPolygon, @@ -517,7 +556,19 @@ struct intersection_insert OverlayType, true > - , detail::intersection::expect_output_pl + , detail::expect_output + < + MultiLinestring, MultiPolygon, TupledOut, + // NOTE: points can be the result only in case of intersection. + // TODO: union should require L and A + typename boost::mpl::if_c + < + (OverlayType == overlay_intersection), + point_tag, + void + >::type, + linestring_tag + > {}; diff --git a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp index afc1adb9d..568cc46fd 100644 --- a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp @@ -525,73 +525,6 @@ struct intersection_areal_linear_point }; -struct tupled_output_tag {}; - - -template -< - typename GeometryOut, - bool IsTupled = geometry::detail::is_tupled_range_values::value -> -struct tag - : geometry::tag -{}; - -template -struct tag -{ - typedef tupled_output_tag type; -}; - - -template -struct expect_output_p -{ - static const bool is_point_found = geometry::tuples::exists_if - < - TupledOut, geometry::detail::is_tag_same_as_pred::template pred - >::value; - - BOOST_MPL_ASSERT_MSG - ( - is_point_found, POINTLIKE_GEOMETRY_EXPECTED_IN_TUPLED_OUTPUT, - (types) - ); -}; - -template -struct expect_output_pl - : expect_output_p -{ - static const bool is_linestring_found = geometry::tuples::exists_if - < - TupledOut, geometry::detail::is_tag_same_as_pred::template pred - >::value; - - BOOST_MPL_ASSERT_MSG - ( - is_linestring_found, LINEAR_GEOMETRY_EXPECTED_IN_TUPLED_OUTPUT, - (types) - ); -}; - -template -struct expect_output_pla - : expect_output_pl -{ - static const bool is_polygon_found = geometry::tuples::exists_if - < - TupledOut, geometry::detail::is_tag_same_as_pred::template pred - >::value; - - BOOST_MPL_ASSERT_MSG - ( - is_polygon_found, AREAL_GEOMETRY_EXPECTED_IN_TUPLED_OUTPUT, - (types) - ); -}; - - }} // namespace detail::intersection #endif // DOXYGEN_NO_DETAIL @@ -614,7 +547,7 @@ template // tag dispatching: typename TagIn1 = typename geometry::tag::type, typename TagIn2 = typename geometry::tag::type, - typename TagOut = typename detail::intersection::tag::type, + typename TagOut = typename detail::setop_insert_output_tag::type, // metafunction finetuning helpers: typename CastedTagIn1 = typename geometry::tag_cast::type, typename CastedTagIn2 = typename geometry::tag_cast::type, @@ -996,13 +929,21 @@ struct intersection_insert < Linear1, Linear2, TupledOut, OverlayType, Reverse1, Reverse2, - TagIn1, TagIn2, detail::intersection::tupled_output_tag, - linear_tag, linear_tag, detail::intersection::tupled_output_tag + TagIn1, TagIn2, detail::tupled_output_tag, + linear_tag, linear_tag, detail::tupled_output_tag > - // NOTE: This is not fully correct because points can be the result only in - // case of intersection but intersection_insert is called also by difference. - // So this requirement could be relaxed in the future. - : detail::intersection::expect_output_pl + : detail::expect_output + < + Linear1, Linear2, TupledOut, + // NOTE: points can be the result only in case of intersection. + typename boost::mpl::if_c + < + (OverlayType == overlay_intersection), + point_tag, + void + >::type, + linestring_tag + > { // NOTE: The order of geometries in TupledOut tuple/pair must correspond to the order // iterators in OutputIterators tuple/pair. @@ -1113,10 +1054,10 @@ struct intersection_insert < PointLike1, PointLike2, TupledOut, OverlayType, Reverse1, Reverse2, - TagIn1, TagIn2, detail::intersection::tupled_output_tag, - pointlike_tag, pointlike_tag, detail::intersection::tupled_output_tag + TagIn1, TagIn2, detail::tupled_output_tag, + pointlike_tag, pointlike_tag, detail::tupled_output_tag > - : detail::intersection::expect_output_p + : detail::expect_output { // NOTE: The order of geometries in TupledOut tuple/pair must correspond to the order // of iterators in OutputIterators tuple/pair. @@ -1240,16 +1181,16 @@ struct intersection_insert < PointLike, Linear, TupledOut, OverlayType, Reverse1, Reverse2, - TagIn1, TagIn2, detail::intersection::tupled_output_tag, - pointlike_tag, linear_tag, detail::intersection::tupled_output_tag + TagIn1, TagIn2, detail::tupled_output_tag, + pointlike_tag, linear_tag, detail::tupled_output_tag > // Reuse the implementation for PointLike/PointLike. : intersection_insert < PointLike, Linear, TupledOut, OverlayType, Reverse1, Reverse2, - TagIn1, TagIn2, detail::intersection::tupled_output_tag, - pointlike_tag, pointlike_tag, detail::intersection::tupled_output_tag + TagIn1, TagIn2, detail::tupled_output_tag, + pointlike_tag, pointlike_tag, detail::tupled_output_tag > {}; @@ -1265,8 +1206,8 @@ struct intersection_insert < Linestring, MultiPoint, TupledOut, overlay_intersection, Reverse1, Reverse2, - linestring_tag, multi_point_tag, detail::intersection::tupled_output_tag, - linear_tag, pointlike_tag, detail::intersection::tupled_output_tag + linestring_tag, multi_point_tag, detail::tupled_output_tag, + linear_tag, pointlike_tag, detail::tupled_output_tag > { template @@ -1368,16 +1309,16 @@ struct intersection_insert < PointLike, Areal, TupledOut, OverlayType, Reverse1, Reverse2, - TagIn1, TagIn2, detail::intersection::tupled_output_tag, - pointlike_tag, areal_tag, detail::intersection::tupled_output_tag + TagIn1, TagIn2, detail::tupled_output_tag, + pointlike_tag, areal_tag, detail::tupled_output_tag > // Reuse the implementation for PointLike/PointLike. : intersection_insert < PointLike, Areal, TupledOut, OverlayType, Reverse1, Reverse2, - TagIn1, TagIn2, detail::intersection::tupled_output_tag, - pointlike_tag, pointlike_tag, detail::intersection::tupled_output_tag + TagIn1, TagIn2, detail::tupled_output_tag, + pointlike_tag, pointlike_tag, detail::tupled_output_tag > {}; @@ -1394,8 +1335,8 @@ struct intersection_insert < Areal, MultiPoint, TupledOut, overlay_intersection, Reverse1, Reverse2, - TagIn1, multi_point_tag, detail::intersection::tupled_output_tag, - areal_tag, pointlike_tag, detail::intersection::tupled_output_tag + TagIn1, multi_point_tag, detail::tupled_output_tag, + areal_tag, pointlike_tag, detail::tupled_output_tag > { template @@ -1426,8 +1367,8 @@ struct intersection_insert TupledOut, OverlayType, ReverseLinestring, ReversePolygon, - linestring_tag, polygon_tag, detail::intersection::tupled_output_tag, - linear_tag, areal_tag, detail::intersection::tupled_output_tag + linestring_tag, polygon_tag, detail::tupled_output_tag, + linear_tag, areal_tag, detail::tupled_output_tag > : detail::intersection::intersection_of_linestring_with_areal < ReversePolygon, @@ -1450,8 +1391,8 @@ struct intersection_insert TupledOut, OverlayType, ReverseLinestring, ReverseRing, - linestring_tag, ring_tag, detail::intersection::tupled_output_tag, - linear_tag, areal_tag, detail::intersection::tupled_output_tag + linestring_tag, ring_tag, detail::tupled_output_tag, + linear_tag, areal_tag, detail::tupled_output_tag > : detail::intersection::intersection_of_linestring_with_areal < ReverseRing, diff --git a/include/boost/geometry/algorithms/detail/tupled_output.hpp b/include/boost/geometry/algorithms/detail/tupled_output.hpp index 430171693..74867fb34 100644 --- a/include/boost/geometry/algorithms/detail/tupled_output.hpp +++ b/include/boost/geometry/algorithms/detail/tupled_output.hpp @@ -9,13 +9,17 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_TUPLED_OUTPUT_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_TUPLED_OUTPUT_HPP +#include #include #include +#include #include +#include #include #include #include +#include #include #include #include @@ -53,7 +57,7 @@ struct is_multi_geometry // true for point, linestring or polygon template -struct is_multi_geometry_value +struct is_multi_geometry_element : boost::integral_constant < bool, @@ -86,23 +90,6 @@ struct is_range {}; -// geometry tag of Rng value_type -template -struct range_value_tag - : geometry::tag::type> -{}; - -// true if geometry tag of Rng is the same as Tag -template -struct is_range_value_tag_same_as - : boost::is_same - < - typename range_value_tag::type, - Tag - > -{}; - - template ::value> struct is_tupled_output_element_base : boost::integral_constant @@ -114,12 +101,13 @@ struct is_tupled_output_element_base < bool, (is_multi_geometry::value - || - ((! is_geometry::value) - && - ((is_range_value_tag_same_as::value) - || (is_range_value_tag_same_as::value) - || (is_range_value_tag_same_as::value)))) + || + ((! is_geometry::value) + && + is_multi_geometry_element + < + typename boost::range_value::type + >::value)) > {}; @@ -134,7 +122,7 @@ struct is_tupled_output_element // true if Output is not a geometry (so e.g. tuple was not adapted to any // concept) and at least one of the tuple elements is a multi-geometry or -// a range of points linestrings or polygons +// a range of points, linestrings or polygons template struct is_tupled_output_check : boost::mpl::and_ @@ -146,28 +134,15 @@ struct is_tupled_output_check {}; -// true if T is a point, linestring or polygon -template -struct is_tupled_range_values_element - : boost::integral_constant - < - bool, - ((boost::is_same::type, point_tag>::value) - || (boost::is_same::type, linestring_tag>::value) - || (boost::is_same::type, polygon_tag>::value)) - > -{}; - - // true if T is not a geometry (so e.g. tuple was not adapted to any // concept) and at least one of the tuple elements is a point, linesting // or polygon template -struct is_tupled_range_values_check +struct is_tupled_single_output_check : boost::mpl::and_ < boost::is_same::type, void>, - geometry::tuples::exists_if + geometry::tuples::exists_if > {}; @@ -222,15 +197,15 @@ struct is_tupled_output // true if T is boost::tuple, boost::tuples::cons, std::pair or std::tuple -// and is_tupled_range_values_check defiend above passes +// and is_tupled_single_output_check defiend above passes template ::value> -struct is_tupled_range_values +struct is_tupled_single_output : boost::integral_constant {}; template -struct is_tupled_range_values - : is_tupled_range_values_check +struct is_tupled_single_output + : is_tupled_single_output_check {}; @@ -527,6 +502,234 @@ struct output_geometry_access }; +template +struct output_geometry_concept_check +{ + static void apply() + { + concepts::check(); + } +}; + +template +struct output_geometry_concept_check > +{ + static void apply() + { + concepts::check(); + concepts::check(); + } +}; + +template ::value> +struct output_geometry_concept_check_t +{ + static void apply() + { + concepts::check::type>(); + output_geometry_concept_check_t::apply(); + } +}; + +template +struct output_geometry_concept_check_t +{ + static void apply() + {} +}; + +template +< + class T0, class T1, class T2, class T3, class T4, + class T5, class T6, class T7, class T8, class T9 +> +struct output_geometry_concept_check > + : output_geometry_concept_check_t > +{}; + +template +struct output_geometry_concept_check > + : output_geometry_concept_check_t > +{}; + +#ifdef BOOST_GEOMETRY_CXX11_TUPLE + +template +struct output_geometry_concept_check > + : output_geometry_concept_check_t > +{}; + +#endif // BOOST_GEOMETRY_CXX11_TUPLE + + +struct tupled_output_tag {}; + + +template +struct setop_insert_output_tag + : boost::mpl::if_c + < + geometry::detail::is_tupled_single_output::value, + tupled_output_tag, + typename geometry::tag::type + > +{}; + + +template +struct expect_output_assert_base; + +template +struct expect_output_assert_base +{ + BOOST_MPL_ASSERT_MSG + ( + IsFound, POINTLIKE_GEOMETRY_EXPECTED_IN_TUPLED_OUTPUT, + (types) + ); +}; + +template +struct expect_output_assert_base +{ + BOOST_MPL_ASSERT_MSG + ( + IsFound, LINEAR_GEOMETRY_EXPECTED_IN_TUPLED_OUTPUT, + (types) + ); +}; + +template +struct expect_output_assert_base +{ + BOOST_MPL_ASSERT_MSG + ( + IsFound, AREAL_GEOMETRY_EXPECTED_IN_TUPLED_OUTPUT, + (types) + ); +}; + + +template +struct expect_output_assert + : expect_output_assert_base + < + Geometry1, Geometry2, TupledOut, + geometry::tuples::exists_if + < + TupledOut, + is_tag_same_as_pred::template pred + >::value, + typename geometry::tag_cast + < + Tag, pointlike_tag, linear_tag, areal_tag + >::type + > +{}; + +template +struct expect_output_assert +{}; + +template +< + typename Geometry1, typename Geometry2, typename TupledOut, + typename Tag1, + typename Tag2 = void, + typename Tag3 = void +> +struct expect_output + : expect_output_assert + , expect_output_assert + , expect_output_assert +{}; + +template +< + typename Geometry1, typename Geometry2, typename TupledOut, + typename Tag1, typename Tag2 +> +struct expect_output + : expect_output_assert + , expect_output_assert +{}; + +template +< + typename Geometry1, typename Geometry2, typename TupledOut, + typename Tag1 +> +struct expect_output + : expect_output_assert +{}; + + +template +struct casted_tag_to_single_tag; + +template <> +struct casted_tag_to_single_tag +{ + typedef point_tag type; +}; + +template <> +struct casted_tag_to_single_tag +{ + typedef linestring_tag type; +}; + +template <> +struct casted_tag_to_single_tag +{ + typedef polygon_tag type; +}; + + +template +< + typename Geometry, + typename SingleOut, + bool IsMulti = geometry::detail::is_multi_geometry::value +> +struct convert_to_output +{ + template + static OutputIterator apply(Geometry const& geometry, + OutputIterator oit) + { + SingleOut single_out; + geometry::convert(geometry, single_out); + *oit++ = single_out; + return oit; + } +}; + +template +< + typename Geometry, + typename SingleOut +> +struct convert_to_output +{ + template + static OutputIterator apply(Geometry const& geometry, + OutputIterator oit) + { + typedef typename boost::range_iterator::type iterator; + for (iterator it = boost::begin(geometry); it != boost::end(geometry); ++it) + { + SingleOut single_out; + geometry::convert(*it, single_out); + *oit++ = single_out; + } + return oit; + } +}; + + } // namespace detail #endif // DOXYGEN_NO_DETAIL