|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r82515 - in sandbox-branches/geometry/index: boost/geometry/extensions/index/rtree boost/geometry/extensions/index/rtree/visitors test/rtree
From: adam.wulkiewicz_at_[hidden]
Date: 2013-01-16 22:54:53
Author: awulkiew
Date: 2013-01-16 22:54:52 EST (Wed, 16 Jan 2013)
New Revision: 82515
URL: http://svn.boost.org/trac/boost/changeset/82515
Log:
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.
Text files modified:
sandbox-branches/geometry/index/boost/geometry/extensions/index/rtree/rtree.hpp | 157 ++++++++++++++++++++++++++-------------
sandbox-branches/geometry/index/boost/geometry/extensions/index/rtree/visitors/children_box.hpp | 11 +-
sandbox-branches/geometry/index/test/rtree/test_rtree.hpp | 67 +++++++++++++++++
3 files changed, 177 insertions(+), 58 deletions(-)
Modified: sandbox-branches/geometry/index/boost/geometry/extensions/index/rtree/rtree.hpp
==============================================================================
--- sandbox-branches/geometry/index/boost/geometry/extensions/index/rtree/rtree.hpp (original)
+++ sandbox-branches/geometry/index/boost/geometry/extensions/index/rtree/rtree.hpp 2013-01-16 22:54:52 EST (Wed, 16 Jan 2013)
@@ -147,7 +147,9 @@
, m_values_count(0)
, m_leafs_level(0)
, m_root(0)
- {}
+ {
+ geometry::assign_inverse(m_box);
+ }
/*!
\brief The constructor.
@@ -168,7 +170,9 @@
, m_values_count(0)
, m_leafs_level(0)
, m_root(0)
- {}
+ {
+ geometry::assign_inverse(m_box);
+ }
/*!
\brief The constructor.
@@ -197,6 +201,8 @@
, m_leafs_level(0)
, m_root(0)
{
+ geometry::assign_inverse(m_box);
+
try
{
this->insert(first, last);
@@ -234,6 +240,8 @@
, m_leafs_level(0)
, m_root(0)
{
+ geometry::assign_inverse(m_box);
+
try
{
this->insert(rng);
@@ -276,9 +284,9 @@
, 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 @@
, 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 @@
, 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 @@
, 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 @@
// It uses m_allocators
this->raw_copy(src, *this, true);
+ m_box = src.m_box;
+
return *this;
}
@@ -432,6 +445,8 @@
this->raw_copy(src, *this, true);
}
+ m_box = src.m_box;
+
return *this;
}
@@ -454,6 +469,7 @@
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 @@
inline void clear()
{
this->raw_destroy(*this);
+ geometry::assign_inverse(m_box);
}
/*!
@@ -902,21 +919,9 @@
\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 @@
\par Throws
Nothing.
*/
- inline const translator_type & translator() const
+ inline translator_type const& translator() const
{
return m_translator;
}
@@ -1067,6 +1072,8 @@
// 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 @@
{
// 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 @@
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");
+
+ --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);
- return remove_v.is_value_removed() ? 1 : 0;
+ detail::rtree::apply_visitor(children_box_v, *m_root);
+ }
+
+ return 1;
+ }
+
+ return 0;
}
/*!
@@ -1259,6 +1281,8 @@
size_type m_values_count;
size_type m_leafs_level;
node * m_root;
+
+ box_type m_box;
};
/*!
@@ -1540,7 +1564,7 @@
\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 @@
}}} // 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.
+// Traits specializations for box above
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
-It calls \c rtree::box().
+template <typename Value, typename Parameters, typename Translator, typename Allocator>
+struct tag< index::rtree<Value, Parameters, Translator, Allocator> >
+{
+ typedef box_tag type;
+};
-\ingroup rtree_functions
+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;
+};
-\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)
+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>
{
- envelope(tree.box(), box);
-}
+ typedef typename geometry::coordinate_type<
+ typename geometry::point_type<
+ index::rtree<Value, Parameters, Translator, Allocator>
+ >::type
+ >::type coordinate_type;
-/*!
-\brief Get the box containing all stored values or an invalid box if the index has no values.
+ static inline coordinate_type get(index::rtree<Value, Parameters, Translator, Allocator> const& tree)
+ {
+ return geometry::get<min_corner, Dimension>(tree.box());
+ }
-It calls \c rtree::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);
+ }
+};
-\ingroup rtree_functions
+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;
-\tparam Box The type of returned Box.
+ static inline coordinate_type get(index::rtree<Value, Parameters, Translator, Allocator> const& tree)
+ {
+ return geometry::get<max_corner, Dimension>(tree.box());
+ }
-\param tree The spatial index.
+ static inline void set(index::rtree<Value, Parameters, Translator, Allocator> & tree,
+ coordinate_type const& value)
+ {
+ return geometry::set<max_corner, Dimension>(tree.box(), value);
+ }
+};
-\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)
-{
- return return_envelope(tree.box());
-}
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
}} //namespace boost::geometry
Modified: sandbox-branches/geometry/index/boost/geometry/extensions/index/rtree/visitors/children_box.hpp
==============================================================================
--- sandbox-branches/geometry/index/boost/geometry/extensions/index/rtree/visitors/children_box.hpp (original)
+++ sandbox-branches/geometry/index/boost/geometry/extensions/index/rtree/visitors/children_box.hpp 2013-01-16 22:54:52 EST (Wed, 16 Jan 2013)
@@ -26,8 +26,8 @@
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 @@
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 @@
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;
};
Modified: sandbox-branches/geometry/index/test/rtree/test_rtree.hpp
==============================================================================
--- sandbox-branches/geometry/index/test/rtree/test_rtree.hpp (original)
+++ sandbox-branches/geometry/index/test/rtree/test_rtree.hpp 2013-01-16 22:54:52 EST (Wed, 16 Jan 2013)
@@ -1049,6 +1049,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
test_count_rtree_values<Box>(parameters);
test_rtree_count<Box>(parameters);
+ test_rtree_box<Box>(parameters);
}
#endif
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk