diff --git a/include/boost/geometry/extensions/index/rtree/node/dynamic_visitor.hpp b/include/boost/geometry/extensions/index/rtree/node/dynamic_visitor.hpp index 7058057e4..1c9962540 100644 --- a/include/boost/geometry/extensions/index/rtree/node/dynamic_visitor.hpp +++ b/include/boost/geometry/extensions/index/rtree/node/dynamic_visitor.hpp @@ -84,6 +84,7 @@ inline Derived * get(dynamic_node * n) template inline void apply_visitor(Visitor &v, Visitable & n) { + assert(&n); n.apply_visitor(v); } diff --git a/include/boost/geometry/extensions/index/rtree/rtree.hpp b/include/boost/geometry/extensions/index/rtree/rtree.hpp index 0c75c9b18..b9fa0e9a3 100644 --- a/include/boost/geometry/extensions/index/rtree/rtree.hpp +++ b/include/boost/geometry/extensions/index/rtree/rtree.hpp @@ -175,7 +175,7 @@ public: { //TODO use Boost.Container allocator_traits_type::select_on_container_copy_construction() - this->raw_copy(src, *this, m_allocators); + this->raw_copy(src, *this, false); } /*! @@ -191,7 +191,7 @@ public: , m_leafs_level(0) , m_root(0) { - this->raw_copy(src, *this, m_allocators); + this->raw_copy(src, *this, false); } /*! @@ -225,7 +225,8 @@ public: //TODO use Boost.Container allocator_traits_type::propagate_on_container_move_assignment - this->raw_copy(src, *this, m_allocators); + // It uses m_allocators + this->raw_copy(src, *this, true); return *this; } @@ -259,7 +260,8 @@ public: } else { - this->raw_copy(src, *this, m_allocators); + // It uses m_allocators + this->raw_copy(src, *this, true); } return *this; @@ -346,6 +348,9 @@ public: template inline size_type spatial_query(Predicates const& pred, OutIter out_it) const { + if ( !m_root ) + return 0; + detail::rtree::visitors::spatial_query find_v(m_translator, pred, out_it); @@ -580,7 +585,8 @@ private: template inline void apply_visitor(Visitor & visitor) const { - detail::rtree::apply_visitor(visitor, *m_root); + if ( m_root ) + detail::rtree::apply_visitor(visitor, *m_root); } /*! @@ -710,16 +716,27 @@ private: /*! Copy the R-tree i.e. whole nodes structure, values and other attributes. + It uses destination's allocators to create the new structure. \note Exception-safety: strong. \param src The source R-tree. \param dst The destination R-tree. */ - inline void raw_copy(rtree const& src, rtree & dst, allocators_type & allocators) const + inline void raw_copy(rtree const& src, rtree & dst, bool copy_all_internals) const { - detail::rtree::visitors::copy copy_v(allocators); - detail::rtree::apply_visitor(copy_v, *src.m_root); // MAY THROW (V: alloc, copy, E: alloc, N: alloc) + detail::rtree::visitors::copy copy_v(dst.m_allocators); + + if ( src.m_root ) + detail::rtree::apply_visitor(copy_v, *src.m_root); // MAY THROW (V, E: alloc, copy, N: alloc) + + if ( copy_all_internals ) + { + dst.m_translator = src.m_translator; // MAY THROW + + dst.m_parameters = src.m_parameters; + //dst.m_allocators = dst.m_allocators; + } if ( dst.m_root ) { @@ -728,11 +745,6 @@ private: dst.m_root = 0; } - dst.m_translator = src.m_translator; - - dst.m_parameters = src.m_parameters; - dst.m_allocators = allocators; - dst.m_root = copy_v.result; dst.m_values_count = src.m_values_count; dst.m_leafs_level = src.m_leafs_level; @@ -746,6 +758,9 @@ private: template inline size_type raw_nearest_one(DistancesPredicates const& dpred, Predicates const& pred, value_type & v) const { + if ( !m_root ) + return 0; + typedef typename detail::point_relation::type point_relation; typedef typename detail::relation::value_type point_type; @@ -781,6 +796,9 @@ private: template inline size_type raw_nearest_k(DistancesPredicates const& dpred, size_t k, Predicates const& pred, OutIter out_it) const { + if ( !m_root ) + return 0; + typedef typename detail::point_relation::type point_relation; typedef typename detail::relation::value_type point_type; diff --git a/test/rtree/test_rtree.hpp b/test/rtree/test_rtree.hpp index b33468cf3..a5a8e65f8 100644 --- a/test/rtree/test_rtree.hpp +++ b/test/rtree/test_rtree.hpp @@ -260,7 +260,8 @@ template void test_spatial_query(Rtree & rtree, Predicates const& pred, std::vector const& expected_output) { BOOST_CHECK( bgi::are_levels_ok(rtree) ); - BOOST_CHECK( bgi::are_boxes_ok(rtree) ); + if ( !rtree.empty() ) + BOOST_CHECK( bgi::are_boxes_ok(rtree) ); std::vector output; size_t n = rtree.spatial_query(pred, std::back_inserter(output)); @@ -481,7 +482,9 @@ void test_nearest_query_k(Rtree const& rtree, std::vector const& input, P // caluclate biggest distance std::sort(test_output.begin(), test_output.end(), TestNearestKLess()); - D biggest_d = test_output.back().first; + D biggest_d = 0; + if ( !test_output.empty() ) + biggest_d = test_output.back().first; // transform test output to vector of values std::vector expected_output(test_output.size()); @@ -534,14 +537,13 @@ void test_copy_assignment_move(bgi::rtree const& tree, Box const& q { size_t s = tree.size(); - BOOST_CHECK(s); - std::vector expected_output; tree.spatial_query(qbox, std::back_inserter(expected_output)); // copy constructor bgi::rtree t1(tree); + BOOST_CHECK(tree.empty() == t1.empty()); BOOST_CHECK(tree.size() == t1.size()); std::vector output; @@ -551,6 +553,7 @@ void test_copy_assignment_move(bgi::rtree const& tree, Box const& q // copying assignment operator t1 = tree; + BOOST_CHECK(tree.empty() == t1.empty()); BOOST_CHECK(tree.size() == t1.size()); output.clear(); @@ -609,6 +612,8 @@ void test_rtree_by_value(Parameters const& parameters) typedef bgi::rtree Tree; typedef typename Tree::box_type B; + // not empty tree test + Tree tree(parameters); std::vector input; B qbox; @@ -632,6 +637,21 @@ void test_rtree_by_value(Parameters const& parameters) test_copy_assignment_move(tree, qbox); test_remove(tree, qbox); + + // empty tree test + + Tree empty_tree(parameters); + std::vector empty_input; + + test_intersects_and_disjoint(empty_tree, empty_input, qbox); + test_covered_by(empty_tree, empty_input, qbox); + test_overlaps(empty_tree, empty_input, qbox); + //test_touches(empty_tree, empty_input, qbox); + test_within(empty_tree, empty_input, qbox); + test_nearest_query(empty_tree, empty_input, pt); + test_nearest_query_k(empty_tree, empty_input, pt, 10); + test_nearest_query_not_found(empty_tree, generate_outside_point

::apply(), 1, 3); + test_copy_assignment_move(empty_tree, qbox); } // run all tests for one Algorithm for some number of rtrees