From 8fddb60cdc39686357ad5560b9738f2f795d76ee Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Mon, 28 Jun 2021 00:29:00 +0200 Subject: [PATCH] Add support for output DynamicGeometry in convex_hull(). --- .../detail/convex_hull/interface.hpp | 66 ++++++++++++++----- .../detail/select_geometry_type.hpp | 12 ++-- .../convex_hull/test_convex_hull.hpp | 7 ++ 3 files changed, 63 insertions(+), 22 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/convex_hull/interface.hpp b/include/boost/geometry/algorithms/detail/convex_hull/interface.hpp index 0e483e0f0..c7d169242 100644 --- a/include/boost/geometry/algorithms/detail/convex_hull/interface.hpp +++ b/include/boost/geometry/algorithms/detail/convex_hull/interface.hpp @@ -152,7 +152,7 @@ struct output_geometry template struct output_geometry { - output_geometry(OutputGeometry & out) : m_out(out) {} + explicit output_geometry(OutputGeometry & out) : m_out(out) {} OutputGeometry & range() { return m_out; } template void move_to_out(Strategy const& ) {} @@ -163,7 +163,7 @@ private: template struct output_geometry { - output_geometry(OutputGeometry & out) : m_out(out) {} + explicit output_geometry(OutputGeometry & out) : m_out(out) {} OutputGeometry & range() { return m_out; } template void move_to_out(Strategy const& ) {} @@ -174,7 +174,7 @@ private: template struct output_geometry { - output_geometry(OutputGeometry & out) : m_out(out) {} + explicit output_geometry(OutputGeometry & out) : m_out(out) {} decltype(auto) range() { return exterior_ring(m_out); } template void move_to_out(Strategy const& ) {} @@ -185,7 +185,7 @@ private: template struct output_geometry { - output_geometry(OutputGeometry & out) : m_out(out) {} + explicit output_geometry(OutputGeometry & out) : m_out(out) {} decltype(auto) range() { return exterior_ring(m_polygon); } template void move_to_out(Strategy const& ) @@ -244,8 +244,26 @@ struct output_pointlike_less static const bool value = priority::value < priority::value; }; -template -struct output_geometry +struct move_emplace_back_policy +{ + template + static inline void apply(Geometry & g, OutputGeometry & out) + { + range::emplace_back(out, std::move(g)); + } +}; + +struct move_assign_policy +{ + template + static inline void apply(Geometry & g, OutputGeometry & out) + { + out = std::move(g); + } +}; + +template +struct output_geometry_dg_or_gc { using polygonal_t = typename util::sequence_min_element < @@ -265,18 +283,18 @@ struct output_geometry // select_element may define different kind of geometry than the one that is desired BOOST_GEOMETRY_STATIC_ASSERT(util::is_polygonal::value, - "It must be possible to store polygonal geometry in GeometryCollection.", polygonal_t); + "It must be possible to store polygonal geometry in OutputGeometry.", polygonal_t); BOOST_GEOMETRY_STATIC_ASSERT(util::is_linear::value, - "It must be possible to store linear geometry in GeometryCollection.", linear_t); + "It must be possible to store linear geometry in OutputGeometry.", linear_t); BOOST_GEOMETRY_STATIC_ASSERT(util::is_pointlike::value, - "It must be possible to store pointlike geometry in GeometryCollection.", pointlike_t); + "It must be possible to store pointlike geometry in OutputGeometry.", pointlike_t); - output_geometry(OutputGeometry & out) + explicit output_geometry_dg_or_gc(OutputGeometry & out) : m_out(out), m_wrapper(m_polygonal) {} decltype(auto) range() { return m_wrapper.range(); } - + template void move_to_out(Strategy const& strategy) { @@ -287,7 +305,7 @@ struct output_geometry if (size > minimum_ring_size::value) { m_wrapper.move_to_out(strategy); - range::emplace_back(m_out, std::move(m_polygonal)); + MovePolicy::apply(m_polygonal, m_out); } else // size == 3 || size == 4 { @@ -295,18 +313,18 @@ struct output_geometry { pointlike_t pointlike; move_to_pointlike(out_range, pointlike); - range::emplace_back(m_out, std::move(pointlike)); + MovePolicy::apply(pointlike, m_out); } else if (detail::equals::equals_point_point(range::front(out_range), range::at(out_range, 2), strategy)) { linear_t linear; move_to_linear(out_range, linear); - range::emplace_back(m_out, std::move(linear)); + MovePolicy::apply(linear, m_out); } else { m_wrapper.move_to_out(strategy); - range::emplace_back(m_out, std::move(m_polygonal)); + MovePolicy::apply(m_polygonal, m_out); } } } @@ -348,6 +366,24 @@ private: output_geometry m_wrapper; }; +template +struct output_geometry + : output_geometry_dg_or_gc +{ + explicit output_geometry(OutputGeometry & out) + : output_geometry_dg_or_gc(out) + {} +}; + +template +struct output_geometry + : output_geometry_dg_or_gc +{ + explicit output_geometry(OutputGeometry & out) + : output_geometry_dg_or_gc(out) + {} +}; + }} // namespace detail::convex_hull #endif // DOXYGEN_NO_DETAIL diff --git a/include/boost/geometry/algorithms/detail/select_geometry_type.hpp b/include/boost/geometry/algorithms/detail/select_geometry_type.hpp index 58ec63507..5592fa5c4 100644 --- a/include/boost/geometry/algorithms/detail/select_geometry_type.hpp +++ b/include/boost/geometry/algorithms/detail/select_geometry_type.hpp @@ -31,13 +31,6 @@ struct first_geometry_type using type = Geometry; }; -template -struct first_geometry_type -{ - BOOST_GEOMETRY_STATIC_ASSERT_FALSE("Not implemented for this Geometry", - Geometry, dynamic_geometry_tag); -}; - template struct first_geometry_type { @@ -55,6 +48,11 @@ struct first_geometry_type >::type; }; +template +struct first_geometry_type + : first_geometry_type +{}; + template < diff --git a/test/algorithms/convex_hull/test_convex_hull.hpp b/test/algorithms/convex_hull/test_convex_hull.hpp index e77584072..34720a27e 100644 --- a/test/algorithms/convex_hull/test_convex_hull.hpp +++ b/test/algorithms/convex_hull/test_convex_hull.hpp @@ -152,8 +152,15 @@ struct test_convex_hull using point_t = typename bg::point_type::type; using var_t = boost::variant, point_t>; using gc_t = bg::model::geometry_collection; + + var_t var; + bg::convex_hull(geometry, var, Strategy()); + gc_t gc; bg::convex_hull(geometry, gc, Strategy()); + + BOOST_CHECK(var.which() == gc[0].which()); + if (bg::detail::equals::equals_point_point(hull.outer()[0], hull.outer()[1], Strategy())) BOOST_CHECK(gc[0].which() == 2); // GC stores point else if (bg::detail::equals::equals_point_point(hull.outer()[0], hull.outer()[2], Strategy()))