Add support for output DynamicGeometry in convex_hull().

This commit is contained in:
Adam Wulkiewicz
2021-06-28 00:29:00 +02:00
parent 26d8518048
commit 8fddb60cdc
3 changed files with 63 additions and 22 deletions

View File

@@ -152,7 +152,7 @@ struct output_geometry
template <typename OutputGeometry>
struct output_geometry<OutputGeometry, linestring_tag>
{
output_geometry(OutputGeometry & out) : m_out(out) {}
explicit output_geometry(OutputGeometry & out) : m_out(out) {}
OutputGeometry & range() { return m_out; }
template <typename Strategy>
void move_to_out(Strategy const& ) {}
@@ -163,7 +163,7 @@ private:
template <typename OutputGeometry>
struct output_geometry<OutputGeometry, ring_tag>
{
output_geometry(OutputGeometry & out) : m_out(out) {}
explicit output_geometry(OutputGeometry & out) : m_out(out) {}
OutputGeometry & range() { return m_out; }
template <typename Strategy>
void move_to_out(Strategy const& ) {}
@@ -174,7 +174,7 @@ private:
template <typename OutputGeometry>
struct output_geometry<OutputGeometry, polygon_tag>
{
output_geometry(OutputGeometry & out) : m_out(out) {}
explicit output_geometry(OutputGeometry & out) : m_out(out) {}
decltype(auto) range() { return exterior_ring(m_out); }
template <typename Strategy>
void move_to_out(Strategy const& ) {}
@@ -185,7 +185,7 @@ private:
template <typename OutputGeometry>
struct output_geometry<OutputGeometry, multi_polygon_tag>
{
output_geometry(OutputGeometry & out) : m_out(out) {}
explicit output_geometry(OutputGeometry & out) : m_out(out) {}
decltype(auto) range() { return exterior_ring(m_polygon); }
template <typename Strategy>
void move_to_out(Strategy const& )
@@ -244,8 +244,26 @@ struct output_pointlike_less
static const bool value = priority<G1>::value < priority<G2>::value;
};
template <typename OutputGeometry>
struct output_geometry<OutputGeometry, geometry_collection_tag>
struct move_emplace_back_policy
{
template <typename Geometry, typename OutputGeometry>
static inline void apply(Geometry & g, OutputGeometry & out)
{
range::emplace_back(out, std::move(g));
}
};
struct move_assign_policy
{
template <typename Geometry, typename OutputGeometry>
static inline void apply(Geometry & g, OutputGeometry & out)
{
out = std::move(g);
}
};
template <typename OutputGeometry, typename MovePolicy>
struct output_geometry_dg_or_gc
{
using polygonal_t = typename util::sequence_min_element
<
@@ -265,18 +283,18 @@ struct output_geometry<OutputGeometry, geometry_collection_tag>
// select_element may define different kind of geometry than the one that is desired
BOOST_GEOMETRY_STATIC_ASSERT(util::is_polygonal<polygonal_t>::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<linear_t>::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<pointlike_t>::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 <typename Strategy>
void move_to_out(Strategy const& strategy)
{
@@ -287,7 +305,7 @@ struct output_geometry<OutputGeometry, geometry_collection_tag>
if (size > minimum_ring_size<polygonal_t>::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<OutputGeometry, geometry_collection_tag>
{
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<polygonal_t> m_wrapper;
};
template <typename OutputGeometry>
struct output_geometry<OutputGeometry, geometry_collection_tag>
: output_geometry_dg_or_gc<OutputGeometry, move_emplace_back_policy>
{
explicit output_geometry(OutputGeometry & out)
: output_geometry_dg_or_gc<OutputGeometry, move_emplace_back_policy>(out)
{}
};
template <typename OutputGeometry>
struct output_geometry<OutputGeometry, dynamic_geometry_tag>
: output_geometry_dg_or_gc<OutputGeometry, move_assign_policy>
{
explicit output_geometry(OutputGeometry & out)
: output_geometry_dg_or_gc<OutputGeometry, move_assign_policy>(out)
{}
};
}} // namespace detail::convex_hull
#endif // DOXYGEN_NO_DETAIL

View File

@@ -31,13 +31,6 @@ struct first_geometry_type
using type = Geometry;
};
template <typename Geometry>
struct first_geometry_type<Geometry, dynamic_geometry_tag>
{
BOOST_GEOMETRY_STATIC_ASSERT_FALSE("Not implemented for this Geometry",
Geometry, dynamic_geometry_tag);
};
template <typename Geometry>
struct first_geometry_type<Geometry, geometry_collection_tag>
{
@@ -55,6 +48,11 @@ struct first_geometry_type<Geometry, geometry_collection_tag>
>::type;
};
template <typename Geometry>
struct first_geometry_type<Geometry, dynamic_geometry_tag>
: first_geometry_type<Geometry, geometry_collection_tag>
{};
template
<

View File

@@ -152,8 +152,15 @@ struct test_convex_hull
using point_t = typename bg::point_type<Hull>::type;
using var_t = boost::variant<Hull, bg::model::linestring<point_t>, point_t>;
using gc_t = bg::model::geometry_collection<var_t>;
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()))