Box stored in the rtree.

box() returns box_type const&.
rtree adapted to Box concept.
error in remove() fixed - size change if the Value wasn't removed.
Tests added.



[SVN r82515]
This commit is contained in:
Adam Wulkiewicz
2013-01-17 03:54:52 +00:00
parent 3083a3721c
commit 28a9448da5
3 changed files with 184 additions and 65 deletions

View File

@@ -147,7 +147,9 @@ public:
, m_values_count(0)
, m_leafs_level(0)
, m_root(0)
{}
{
geometry::assign_inverse(m_box);
}
/*!
\brief The constructor.
@@ -168,7 +170,9 @@ public:
, m_values_count(0)
, m_leafs_level(0)
, m_root(0)
{}
{
geometry::assign_inverse(m_box);
}
/*!
\brief The constructor.
@@ -197,6 +201,8 @@ public:
, m_leafs_level(0)
, m_root(0)
{
geometry::assign_inverse(m_box);
try
{
this->insert(first, last);
@@ -234,6 +240,8 @@ public:
, m_leafs_level(0)
, m_root(0)
{
geometry::assign_inverse(m_box);
try
{
this->insert(rng);
@@ -276,9 +284,9 @@ public:
, m_values_count(0)
, m_leafs_level(0)
, m_root(0)
, m_box(src.m_box)
{
//TODO use Boost.Container allocator_traits_type::select_on_container_copy_construction()
this->raw_copy(src, *this, false);
}
@@ -303,6 +311,7 @@ public:
, m_values_count(0)
, m_leafs_level(0)
, m_root(0)
, m_box(src.m_box)
{
this->raw_copy(src, *this, false);
}
@@ -325,6 +334,7 @@ public:
, m_values_count(src.m_values_count)
, m_leafs_level(src.m_leafs_level)
, m_root(src.m_root)
, m_box(src.m_box)
{
src.m_values_count = 0;
src.m_leafs_level = 0;
@@ -353,6 +363,7 @@ public:
, m_values_count(0)
, m_leafs_level(0)
, m_root(0)
, m_box(src.m_box)
{
if ( src.m_allocators.allocator == allocator )
{
@@ -388,6 +399,8 @@ public:
// It uses m_allocators
this->raw_copy(src, *this, true);
m_box = src.m_box;
return *this;
}
@@ -432,6 +445,8 @@ public:
this->raw_copy(src, *this, true);
}
m_box = src.m_box;
return *this;
}
@@ -454,6 +469,7 @@ public:
boost::swap(m_values_count, other.m_values_count);
boost::swap(m_leafs_level, other.m_leafs_level);
boost::swap(m_root, other.m_root);
boost::swap(m_box, other.m_box);
}
/*!
@@ -888,6 +904,7 @@ public:
inline void clear()
{
this->raw_destroy(*this);
geometry::assign_inverse(m_box);
}
/*!
@@ -902,21 +919,9 @@ public:
\par Throws
Nothing.
*/
inline box_type box() const
inline box_type const& box() const
{
if ( this->empty() )
{
box_type result;
geometry::assign_inverse(result);
return result;
}
detail::rtree::visitors::children_box<value_type, options_type, translator_type, box_type, allocators_type>
children_box_v(m_translator);
detail::rtree::apply_visitor(children_box_v, *m_root);
return children_box_v.result;
return m_box;
}
/*!
@@ -967,7 +972,7 @@ public:
\par Throws
Nothing.
*/
inline const translator_type & translator() const
inline translator_type const& translator() const
{
return m_translator;
}
@@ -1067,6 +1072,8 @@ private:
// TODO
// If exception is thrown, m_values_count may be invalid
++m_values_count;
geometry::expand(m_box, m_translator(value));
}
/*!
@@ -1081,7 +1088,6 @@ private:
{
// TODO: awulkiew - assert for correct value (indexable) ?
BOOST_GEOMETRY_INDEX_ASSERT(m_root, "The root must exist");
BOOST_GEOMETRY_INDEX_ASSERT(0 < m_values_count, "can't remove, there are no elements in the rtree");
detail::rtree::visitors::remove<
value_type, options_type, translator_type, box_type, allocators_type
@@ -1089,15 +1095,31 @@ private:
detail::rtree::apply_visitor(remove_v, *m_root);
// TODO
// Think about this: If exception is thrown, may the root be removed?
// Or it is just cleared?
// If exception is thrown, m_values_count may be invalid
// TODO
// If exception is thrown, m_values_count may be invalid
--m_values_count;
if ( remove_v.is_value_removed() )
{
BOOST_GEOMETRY_INDEX_ASSERT(0 < m_values_count, "unexpected state");
return remove_v.is_value_removed() ? 1 : 0;
--m_values_count;
// Calculate new box
if ( m_values_count == 0 )
{
geometry::assign_inverse(m_box);
}
else
{
detail::rtree::visitors::children_box<value_type, options_type, translator_type, box_type, allocators_type>
children_box_v(m_box, m_translator);
detail::rtree::apply_visitor(children_box_v, *m_root);
}
return 1;
}
return 0;
}
/*!
@@ -1259,6 +1281,8 @@ private:
size_type m_values_count;
size_type m_leafs_level;
node * m_root;
box_type m_box;
};
/*!
@@ -1540,7 +1564,7 @@ It calls \c rtree::box().
\return The box containing all stored values or an invalid box.
*/
template <typename Value, typename Options, typename Translator, typename Allocator>
inline typename rtree<Value, Options, Translator, Allocator>::box_type
inline typename rtree<Value, Options, Translator, Allocator>::box_type const&
box(rtree<Value, Options, Translator, Allocator> const& tree)
{
return tree.box();
@@ -1548,44 +1572,73 @@ box(rtree<Value, Options, Translator, Allocator> const& tree)
}}} // namespace boost::geometry::index
#include <boost/geometry/algorithms/envelope.hpp>
// Rtree adaptation to Box concept
namespace boost { namespace geometry {
/*!
\brief Get the box containing all stored values or an invalid box if the index has no values.
It calls \c rtree::box().
\ingroup rtree_functions
\param tree The spatial index.
\param box The object to which box containing all stored values or an invalid box will be assigned.
*/
template <typename Value, typename Options, typename Translator, typename Allocator, typename Box>
void envelope(index::rtree<Value, Options, Translator, Allocator> const& tree, Box & box)
// Traits specializations for box above
#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
namespace traits
{
envelope(tree.box(), box);
}
/*!
\brief Get the box containing all stored values or an invalid box if the index has no values.
It calls \c rtree::box().
\ingroup rtree_functions
\tparam Box The type of returned Box.
\param tree The spatial index.
\return The box containing all stored values or an invalid box.
*/
template <typename Box, typename Value, typename Options, typename Translator, typename Allocator>
Box return_envelope(index::rtree<Value, Options, Translator, Allocator> const& tree)
template <typename Value, typename Parameters, typename Translator, typename Allocator>
struct tag< index::rtree<Value, Parameters, Translator, Allocator> >
{
return return_envelope(tree.box());
}
typedef box_tag type;
};
template <typename Value, typename Parameters, typename Translator, typename Allocator>
struct point_type< index::rtree<Value, Parameters, Translator, Allocator> >
{
typedef typename geometry::point_type<
typename index::rtree<Value, Parameters, Translator, Allocator>::box_type
>::type type;
};
template <typename Value, typename Parameters, typename Translator, typename Allocator, std::size_t Dimension>
struct indexed_access<index::rtree<Value, Parameters, Translator, Allocator>, min_corner, Dimension>
{
typedef typename geometry::coordinate_type<
typename geometry::point_type<
index::rtree<Value, Parameters, Translator, Allocator>
>::type
>::type coordinate_type;
static inline coordinate_type get(index::rtree<Value, Parameters, Translator, Allocator> const& tree)
{
return geometry::get<min_corner, Dimension>(tree.box());
}
static inline void set(index::rtree<Value, Parameters, Translator, Allocator> & tree,
coordinate_type const& value)
{
return geometry::set<min_corner, Dimension>(tree.box(), value);
}
};
template <typename Value, typename Parameters, typename Translator, typename Allocator, std::size_t Dimension>
struct indexed_access<index::rtree<Value, Parameters, Translator, Allocator>, max_corner, Dimension>
{
typedef typename geometry::coordinate_type<
typename geometry::point_type<
index::rtree<Value, Parameters, Translator, Allocator>
>::type
>::type coordinate_type;
static inline coordinate_type get(index::rtree<Value, Parameters, Translator, Allocator> const& tree)
{
return geometry::get<max_corner, Dimension>(tree.box());
}
static inline void set(index::rtree<Value, Parameters, Translator, Allocator> & tree,
coordinate_type const& value)
{
return geometry::set<max_corner, Dimension>(tree.box(), value);
}
};
} // namespace traits
#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
}} //namespace boost::geometry

View File

@@ -26,8 +26,8 @@ class children_box
typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
public:
inline children_box(Translator const& tr)
: m_tr(tr)
inline children_box(Box & result, Translator const& tr)
: m_result(result), m_tr(tr)
{}
inline void operator()(internal_node const& n)
@@ -35,7 +35,7 @@ public:
typedef typename rtree::elements_type<internal_node>::type elements_type;
elements_type const& elements = rtree::elements(n);
result = rtree::elements_box<Box>(elements.begin(), elements.end(), m_tr);
m_result = rtree::elements_box<Box>(elements.begin(), elements.end(), m_tr);
}
inline void operator()(leaf const& n)
@@ -43,12 +43,11 @@ public:
typedef typename rtree::elements_type<leaf>::type elements_type;
elements_type const& elements = rtree::elements(n);
result = rtree::elements_box<Box>(elements.begin(), elements.end(), m_tr);
m_result = rtree::elements_box<Box>(elements.begin(), elements.end(), m_tr);
}
Box result;
private:
Box & m_result;
Translator const& m_tr;
};

View File

@@ -1049,6 +1049,7 @@ void test_remove(bgi::rtree<Value, Algo> & tree, Box const& qbox)
std::vector<Value> expected_output;
tree.spatial_query(bgi::disjoint(qbox), std::back_inserter(expected_output));
size_t expected_removed_count = values_to_remove.size();
size_t expected_size_after_remove = tree.size() - values_to_remove.size();
// Add value which is not stored in the Rtree
Value outsider = generate_value_outside<T>();
@@ -1062,6 +1063,7 @@ void test_remove(bgi::rtree<Value, Algo> & tree, Box const& qbox)
BOOST_CHECK( r == expected_removed_count );
std::vector<Value> output;
t.spatial_query(bgi::disjoint(qbox), std::back_inserter(output));
BOOST_CHECK( t.size() == expected_size_after_remove );
BOOST_CHECK( output.size() == tree.size() - expected_removed_count );
test_compare_outputs(t, output, expected_output);
}
@@ -1071,6 +1073,7 @@ void test_remove(bgi::rtree<Value, Algo> & tree, Box const& qbox)
BOOST_CHECK( r == expected_removed_count );
std::vector<Value> output;
t.spatial_query(bgi::disjoint(qbox), std::back_inserter(output));
BOOST_CHECK( t.size() == expected_size_after_remove );
BOOST_CHECK( output.size() == tree.size() - expected_removed_count );
test_compare_outputs(t, output, expected_output);
}
@@ -1080,6 +1083,7 @@ void test_remove(bgi::rtree<Value, Algo> & tree, Box const& qbox)
BOOST_CHECK( r == expected_removed_count );
std::vector<Value> output;
t.spatial_query(bgi::disjoint(qbox), std::back_inserter(output));
BOOST_CHECK( t.size() == expected_size_after_remove );
BOOST_CHECK( output.size() == tree.size() - expected_removed_count );
test_compare_outputs(t, output, expected_output);
}
@@ -1092,6 +1096,7 @@ void test_remove(bgi::rtree<Value, Algo> & tree, Box const& qbox)
BOOST_CHECK( r == expected_removed_count );
std::vector<Value> output;
bgi::spatial_query(t, bgi::disjoint(qbox), std::back_inserter(output));
BOOST_CHECK( t.size() == expected_size_after_remove );
BOOST_CHECK( output.size() == tree.size() - expected_removed_count );
test_compare_outputs(t, output, expected_output);
}
@@ -1101,6 +1106,7 @@ void test_remove(bgi::rtree<Value, Algo> & tree, Box const& qbox)
BOOST_CHECK( r == expected_removed_count );
std::vector<Value> output;
bgi::spatial_query(t, bgi::disjoint(qbox), std::back_inserter(output));
BOOST_CHECK( t.size() == expected_size_after_remove );
BOOST_CHECK( output.size() == tree.size() - expected_removed_count );
test_compare_outputs(t, output, expected_output);
}
@@ -1110,6 +1116,7 @@ void test_remove(bgi::rtree<Value, Algo> & tree, Box const& qbox)
BOOST_CHECK( r == expected_removed_count );
std::vector<Value> output;
bgi::spatial_query(t, bgi::disjoint(qbox), std::back_inserter(output));
BOOST_CHECK( t.size() == expected_size_after_remove );
BOOST_CHECK( output.size() == tree.size() - expected_removed_count );
test_compare_outputs(t, output, expected_output);
}
@@ -1265,6 +1272,64 @@ void test_rtree_count(Parameters const& parameters)
BOOST_CHECK(t.count(input[0].first) == 3);
}
// test rtree box
template <typename Value, typename Parameters>
void test_rtree_box(Parameters const& parameters)
{
typedef bgi::rtree<Value, Parameters> Tree;
typedef typename Tree::box_type B;
typedef typename bg::traits::point_type<B>::type P;
B b;
bg::assign_inverse(b);
Tree t(parameters);
std::vector<Value> input;
B qbox;
BOOST_CHECK(bg::equals(t.box(), b));
generate_rtree(t, input, qbox);
BOOST_FOREACH(Value const& v, input)
bg::expand(b, t.translator()(v));
BOOST_CHECK(bg::equals(t.box(), b));
//BOOST_CHECK(bg::equals(bg::return_envelope<B>(t), b));
//BOOST_CHECK(bg::area(t) == bg::area(b));
//BOOST_CHECK(bg::perimeter(t) == bg::perimeter(b));
//BOOST_CHECK(bg::equals(bg::return_centroid<P>(t), bg::return_centroid<P>(b)));
size_t s = input.size();
while ( s/2 < input.size() && !input.empty() )
{
t.remove(input.back());
input.pop_back();
}
bg::assign_inverse(b);
BOOST_FOREACH(Value const& v, input)
bg::expand(b, t.translator()(v));
BOOST_CHECK(bg::equals(t.box(), b));
Tree t2(t);
BOOST_CHECK(bg::equals(t2.box(), b));
t2.clear();
t2 = t;
BOOST_CHECK(bg::equals(t2.box(), b));
t2.clear();
t2 = boost::move(t);
BOOST_CHECK(bg::equals(t2.box(), b));
t.clear();
bg::assign_inverse(b);
BOOST_CHECK(bg::equals(t.box(), b));
}
// run all tests for one Algorithm for some number of rtrees
// defined by some number of Values constructed from given Point
@@ -1286,6 +1351,7 @@ void test_rtree_for_point(Parameters const& parameters = Parameters())
test_count_rtree_values<Point>(parameters);
test_rtree_count<Point>(parameters);
test_rtree_box<Point>(parameters);
}
template<typename Point, typename Parameters>
@@ -1305,6 +1371,7 @@ void test_rtree_for_box(Parameters const& parameters = Parameters())
test_count_rtree_values<Box>(parameters);
test_rtree_count<Box>(parameters);
test_rtree_box<Box>(parameters);
}
#endif