[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); values_count = static_cast<size_type>(diff);
entries.reserve(values_count); 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 ) for ( ; first != last ; ++first )
{ {
// NOTE: support for iterators not returning true references adapted // NOTE: support for iterators not returning true references adapted
@ -214,7 +216,7 @@ public:
hint_box.expand(indexable); hint_box.expand(indexable);
point_type pt; point_type pt;
geometry::centroid(indexable, pt); geometry::centroid(indexable, pt, strategy);
entries.push_back(std::make_pair(pt, first)); 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(elements.size() == elements_count, "unexpected elements number");
BOOST_GEOMETRY_INDEX_ASSERT(0 < reinserted_elements_count, "wrong value of elements to reinsert"); 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 // calculate current node's center
point_type node_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 // fill the container of centers' distances of children from current node's center
typedef typename index::detail::rtree::container_from_elements_type< 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 // If constructor is used instead of resize() MS implementation leaks here
sorted_elements.reserve(elements_count); // MAY THROW, STRONG (V, E: alloc, copy) 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() ; for ( typename elements_type::const_iterator it = elements.begin() ;
it != elements.end() ; ++it ) it != elements.end() ; ++it )
{ {
point_type element_center; 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( sorted_elements.push_back(std::make_pair(
comparable_distance_pp::call(node_center, element_center, strategy), comparable_distance_pp::call(node_center, element_center, strategy),
*it)); // MAY THROW (V, E: copy) *it)); // MAY THROW (V, E: copy)

View File

@ -12,13 +12,8 @@
#include <boost/geometry/strategies/detail.hpp> #include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/length/services.hpp> #include <boost/geometry/strategies/centroid.hpp>
#include <boost/geometry/strategies/centroid/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>
namespace boost { namespace geometry namespace boost { namespace geometry
@ -27,7 +22,6 @@ namespace boost { namespace geometry
namespace strategies { namespace centroid namespace strategies { namespace centroid
{ {
/*
template template
< <
typename FormulaPolicy = strategy::andoyer, typename FormulaPolicy = strategy::andoyer,
@ -45,12 +39,29 @@ public:
explicit geographic(Spheroid const& spheroid) explicit geographic(Spheroid const& spheroid)
: base_t(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 namespace services
{ {
template <typename Geometry>
struct default_strategy<Geometry, geographic_tag>
{
using type = strategies::centroid::geographic<>;
};
} // namespace services } // namespace services
}} // namespace strategies::centroid }} // namespace strategies::centroid

View File

@ -12,9 +12,8 @@
#include <boost/geometry/strategies/detail.hpp> #include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/length/services.hpp> #include <boost/geometry/strategies/centroid.hpp>
#include <boost/geometry/strategies/centroid/services.hpp>
#include <boost/geometry/strategies/spherical/distance_haversine.hpp>
namespace boost { namespace geometry namespace boost { namespace geometry
@ -23,30 +22,41 @@ namespace boost { namespace geometry
namespace strategies { namespace centroid namespace strategies { namespace centroid
{ {
/*
template template
< <
typename RadiusTypeOrSphere = double,
typename CalculationType = void typename CalculationType = void
> >
class spherical 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: public:
spherical() = default; spherical() = default;
template <typename RadiusOrSphere> // TODO: Box and Segment should have proper strategies.
explicit spherical(RadiusOrSphere const& radius_or_sphere) template <typename Geometry, typename Point>
: base_t(radius_or_sphere) 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 namespace services
{ {
template <typename Geometry>
struct default_strategy<Geometry, spherical_equatorial_tag>
{
using type = strategies::centroid::spherical<>;
};
} // namespace services } // namespace services
}} // namespace strategies::centroid }} // 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<>()); 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*[]) int test_main(int, char*[])
{ {
geom g, o; geom g, o;
// this compiles but it shouldn't! ::centroid(g.b, o.pt);
// internally default_strategy is defined as not_applicable_strategy for box
bg::centroid(g.b, o.pt);
::simplify(g.pt, o.pt); ::simplify(g.pt, o.pt);
::simplify(g.ls, o.ls); ::simplify(g.ls, o.ls);