[index][strategies] Pass strategy to centroid() in the rtree.

Implement spherical and geographic strategies in order to maintain
backward compatibility. Even though dummy legacy strategy is returned.

Add centroid tests for undefined CS.
This commit is contained in:
Adam Wulkiewicz 2021-03-10 17:03:03 +01:00
parent bb758ac749
commit edc2aa5051
5 changed files with 61 additions and 30 deletions

View File

@ -196,8 +196,10 @@ public:
values_count = static_cast<size_type>(diff);
entries.reserve(values_count);
auto const& strategy = index::detail::get_strategy(parameters);
expandable_box<box_type, strategy_type> hint_box(detail::get_strategy(parameters));
expandable_box<box_type, strategy_type> hint_box(strategy);
for ( ; first != last ; ++first )
{
// NOTE: support for iterators not returning true references adapted
@ -214,7 +216,7 @@ public:
hint_box.expand(indexable);
point_type pt;
geometry::centroid(indexable, pt);
geometry::centroid(indexable, pt, strategy);
entries.push_back(std::make_pair(pt, first));
}

View File

@ -101,9 +101,12 @@ public:
BOOST_GEOMETRY_INDEX_ASSERT(elements.size() == elements_count, "unexpected elements number");
BOOST_GEOMETRY_INDEX_ASSERT(0 < reinserted_elements_count, "wrong value of elements to reinsert");
auto const& strategy = index::detail::get_strategy(parameters);
// calculate current node's center
point_type node_center;
geometry::centroid(rtree::elements(*parent)[current_child_index].first, node_center);
geometry::centroid(rtree::elements(*parent)[current_child_index].first, node_center,
strategy);
// fill the container of centers' distances of children from current node's center
typedef typename index::detail::rtree::container_from_elements_type<
@ -115,13 +118,12 @@ public:
// If constructor is used instead of resize() MS implementation leaks here
sorted_elements.reserve(elements_count); // MAY THROW, STRONG (V, E: alloc, copy)
auto const& strategy = index::detail::get_strategy(parameters);
for ( typename elements_type::const_iterator it = elements.begin() ;
it != elements.end() ; ++it )
{
point_type element_center;
geometry::centroid( rtree::element_indexable(*it, translator), element_center);
geometry::centroid(rtree::element_indexable(*it, translator), element_center,
strategy);
sorted_elements.push_back(std::make_pair(
comparable_distance_pp::call(node_center, element_center, strategy),
*it)); // MAY THROW (V, E: copy)

View File

@ -12,13 +12,8 @@
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/length/services.hpp>
#include <boost/geometry/strategies/geographic/distance.hpp>
// TODO - for backwards compatibility, remove?
#include <boost/geometry/strategies/geographic/distance_andoyer.hpp>
#include <boost/geometry/strategies/geographic/distance_thomas.hpp>
#include <boost/geometry/strategies/geographic/distance_vincenty.hpp>
#include <boost/geometry/strategies/centroid.hpp>
#include <boost/geometry/strategies/centroid/services.hpp>
namespace boost { namespace geometry
@ -27,7 +22,6 @@ namespace boost { namespace geometry
namespace strategies { namespace centroid
{
/*
template
<
typename FormulaPolicy = strategy::andoyer,
@ -45,12 +39,29 @@ public:
explicit geographic(Spheroid const& spheroid)
: base_t(spheroid)
{}
// TODO: Box and Segment should have proper strategies.
template <typename Geometry, typename Point>
static auto centroid(Geometry const&, Point const&,
std::enable_if_t
<
util::is_segment<Geometry>::value
|| util::is_box<Geometry>::value
> * = nullptr)
{
return strategy::centroid::not_applicable_strategy();
}
};
*/
namespace services
{
template <typename Geometry>
struct default_strategy<Geometry, geographic_tag>
{
using type = strategies::centroid::geographic<>;
};
} // namespace services
}} // namespace strategies::centroid

View File

@ -12,9 +12,8 @@
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/length/services.hpp>
#include <boost/geometry/strategies/spherical/distance_haversine.hpp>
#include <boost/geometry/strategies/centroid.hpp>
#include <boost/geometry/strategies/centroid/services.hpp>
namespace boost { namespace geometry
@ -23,30 +22,41 @@ namespace boost { namespace geometry
namespace strategies { namespace centroid
{
/*
template
<
typename RadiusTypeOrSphere = double,
typename CalculationType = void
>
class spherical
: public strategies::detail::spherical_base<RadiusTypeOrSphere>
: public strategies::detail::spherical_base<void>
{
using base_t = strategies::detail::spherical_base<RadiusTypeOrSphere>;
using base_t = strategies::detail::spherical_base<void>;
public:
spherical() = default;
template <typename RadiusOrSphere>
explicit spherical(RadiusOrSphere const& radius_or_sphere)
: base_t(radius_or_sphere)
{}
// TODO: Box and Segment should have proper strategies.
template <typename Geometry, typename Point>
static auto centroid(Geometry const&, Point const&,
std::enable_if_t
<
util::is_segment<Geometry>::value
|| util::is_box<Geometry>::value
> * = nullptr)
{
return strategy::centroid::not_applicable_strategy();
}
};
*/
namespace services
{
template <typename Geometry>
struct default_strategy<Geometry, spherical_equatorial_tag>
{
using type = strategies::centroid::spherical<>;
};
} // namespace services
}} // namespace strategies::centroid

View File

@ -24,13 +24,19 @@ inline void simplify(G const& g1, G & g2)
bg::simplify(g1, g2, 1, bg::strategies::simplify::geographic<>());
}
template <typename G, typename P>
inline void centroid(G const& g, P & p)
{
bg::centroid(g, p, bg::strategies::centroid::cartesian<>());
bg::centroid(g, p, bg::strategies::centroid::spherical<>());
bg::centroid(g, p, bg::strategies::centroid::geographic<>());
}
int test_main(int, char*[])
{
geom g, o;
// this compiles but it shouldn't!
// internally default_strategy is defined as not_applicable_strategy for box
bg::centroid(g.b, o.pt);
::centroid(g.b, o.pt);
::simplify(g.pt, o.pt);
::simplify(g.ls, o.ls);