|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r72531 - in sandbox-branches/geometry/index_080_new: boost/geometry/extensions/index/algorithms boost/geometry/extensions/index/rtree boost/geometry/extensions/index/rtree/rstar boost/geometry/extensions/index/rtree/visitors tests
From: adam.wulkiewicz_at_[hidden]
Date: 2011-06-09 19:56:00
Author: awulkiew
Date: 2011-06-09 19:55:58 EDT (Thu, 09 Jun 2011)
New Revision: 72531
URL: http://svn.boost.org/trac/boost/changeset/72531
Log:
reinserting insert visitor corrected, insert visitors now relies on relative level, levels check added, boxes check corrected.
Added:
sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/algorithms/distance_sqr.hpp (contents, props changed)
sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/visitors/are_levels_ok.hpp (contents, props changed)
Removed:
sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/rstar/split.hpp
Text files modified:
sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/algorithms/within.hpp | 4
sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/rstar/insert.hpp | 736 +++++++++++++++++++++++++++------------
sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/rstar/redistribute_elements.hpp | 5
sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/rstar/rstar.hpp | 1
sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/rtree.hpp | 6
sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/visitors/are_boxes_ok.hpp | 34 +
sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/visitors/insert.hpp | 62 +-
sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/visitors/remove.hpp | 22
sandbox-branches/geometry/index_080_new/tests/additional_glut_vis.cpp | 21
sandbox-branches/geometry/index_080_new/tests/additional_sizes_and_times.cpp | 60 ++
10 files changed, 642 insertions(+), 309 deletions(-)
Added: sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/algorithms/distance_sqr.hpp
==============================================================================
--- (empty file)
+++ sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/algorithms/distance_sqr.hpp 2011-06-09 19:55:58 EDT (Thu, 09 Jun 2011)
@@ -0,0 +1,78 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Boost.SpatialIndex - n-dimensional distance_sqr between points
+//
+// Copyright 2011 Adam Wulkiewicz.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_ALGORITHMS_DISTANCE_SQR_HPP
+#define BOOST_GEOMETRY_EXTENSIONS_INDEX_ALGORITHMS_DISTANCE_SQR_HPP
+
+namespace boost { namespace geometry { namespace index {
+
+template <typename Point1, typename Point2>
+class default_distance_sqr_result
+{
+ typedef typename select_most_precise<
+ typename traits::coordinate_type<Point1>::type,
+ long double
+ >::type intermediate_type;
+
+public:
+ typedef typename select_most_precise<
+ typename traits::coordinate_type<Point2>::type,
+ intermediate_type
+ >::type type;
+};
+
+namespace detail {
+
+template <typename Point1, typename Point2, size_t CurrentDimension>
+struct distance_sqr_for_each_dimension
+{
+ BOOST_STATIC_ASSERT(0 < CurrentDimension);
+ BOOST_STATIC_ASSERT(CurrentDimension <= traits::dimension<Point1>::value);
+
+ typedef typename default_distance_sqr_result<Point1, Point2>::type result_type;
+
+ static inline result_type apply(Point1 const& p1, Point2 const& p2)
+ {
+ result_type temp = geometry::get<CurrentDimension - 1>(p1) - geometry::get<CurrentDimension - 1>(p2);
+ return distance_sqr_for_each_dimension<Point1, Point2, CurrentDimension - 1>::apply(p1, p2) +
+ temp * temp;
+ }
+};
+
+template <typename Point1, typename Point2>
+struct distance_sqr_for_each_dimension<Point1, Point2, 1>
+{
+ BOOST_STATIC_ASSERT(1 <= traits::dimension<Point1>::value);
+
+ typedef typename default_distance_sqr_result<Point1, Point2>::type result_type;
+
+ static inline result_type apply(Point1 const& p1, Point2 const& p2)
+ {
+ result_type temp = geometry::get<0>(p1) - geometry::get<0>(p2);
+ return temp * temp;
+ }
+};
+
+} // namespace detail
+
+template <typename Point1, typename Point2>
+typename default_distance_sqr_result<Point1, Point2>::type distance_sqr(Point1 const& p1, Point2 const& p2)
+{
+ BOOST_STATIC_ASSERT(traits::dimension<Point1>::value == traits::dimension<Point2>::value);
+
+ return detail::distance_sqr_for_each_dimension<
+ Point1,
+ Point2,
+ index::traits::dimension<Point1>::value
+ >::apply(p1, p2);
+}
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_ALGORITHMS_DISTANCE_SQR_HPP
Modified: sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/algorithms/within.hpp
==============================================================================
--- sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/algorithms/within.hpp (original)
+++ sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/algorithms/within.hpp 2011-06-09 19:55:58 EDT (Thu, 09 Jun 2011)
@@ -46,7 +46,7 @@
template <typename Box>
static inline bool apply(Box const& b, Indexable const& p)
{
- return index::get<min_corner, DimensionIndex>(b) <= index::get<DimensionIndex>(p);
+ return index::get<min_corner, DimensionIndex>(b) <= geometry::get<DimensionIndex>(p);
}
};
@@ -56,7 +56,7 @@
template <typename Box>
static inline bool apply(Box const& b, Indexable const& p)
{
- return index::get<DimensionIndex>(p) <= index::get<max_corner, DimensionIndex>(b);
+ return geometry::get<DimensionIndex>(p) <= index::get<max_corner, DimensionIndex>(b);
}
};
Modified: sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/rstar/insert.hpp
==============================================================================
--- sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/rstar/insert.hpp (original)
+++ sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/rstar/insert.hpp 2011-06-09 19:55:58 EDT (Thu, 09 Jun 2011)
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
//
-// Boost.Index - R*-tree insert algorithm implementation
+// Boost.Index - R*-tree insert
//
// Copyright 2011 Adam Wulkiewicz.
// Use, modification and distribution is subject to the Boost Software License,
@@ -10,27 +10,12 @@
#ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_RSTAR_INSERT_HPP
#define BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_RSTAR_INSERT_HPP
-#include <algorithm>
-
-#include <boost/geometry/strategies/strategies.hpp>
#include <boost/geometry/algorithms/centroid.hpp>
-#include <boost/geometry/algorithms/distance.hpp>
#include <boost/geometry/extensions/index/algorithms/area.hpp>
-#include <boost/geometry/extensions/index/algorithms/margin.hpp>
-#include <boost/geometry/extensions/index/algorithms/overlap.hpp>
-#include <boost/geometry/extensions/index/algorithms/union_area.hpp>
+#include <boost/geometry/extensions/index/algorithms/distance_sqr.hpp>
#include <boost/geometry/extensions/index/rtree/node.hpp>
-#include <boost/geometry/extensions/index/rtree/visitors/insert.hpp>
-#include <boost/geometry/extensions/index/rtree/visitors/is_leaf.hpp>
-
-#include <boost/geometry/extensions/index/rtree/rstar/choose_next_node.hpp>
-#include <boost/geometry/extensions/index/rtree/rstar/split.hpp>
-
-//TEST
-#include <boost/geometry/extensions/index/rtree/visitors/print.hpp>
-#include <boost/geometry/extensions/index/rtree/visitors/are_boxes_ok.hpp>
namespace boost { namespace geometry { namespace index {
@@ -38,222 +23,513 @@
namespace detail {
-//template <typename Element, typename Value, typename Translator, typename Box>
-//class insert<Element, Value, Translator, Box, rstar_tag> : public boost::static_visitor<>
-//{
-//protected:
-// typedef typename rtree::node<Value, Box, rstar_tag>::type node;
-// typedef typename rtree::internal_node<Value, Box, rstar_tag>::type internal_node;
-// typedef typename rtree::leaf<Value, Box, rstar_tag>::type leaf;
-//
-// inline insert(node* & root,
-// Element const& el,
-// size_t min_elements,
-// size_t max_elements,
-// Translator const& tr,
-// size_t level = std::numeric_limits<size_t>::max()
-// )
-// : m_element(el)
-// , m_tr(tr)
-// , m_min_elems_per_node(min_elements)
-// , m_max_elems_per_node(max_elements)
-// , m_reinserted_elements_count(size_t(max_elements * 0.3f))
-// , m_level(level)
-// , m_root_node(root)
-// , m_parent(0), m_current_child_index(0), m_current_level(0)
-// {}
-//
-// template <typename Derived>
-// inline void traverse(Derived & d, internal_node & n)
-// {
-// // choose next node, where value insert traversing should go
-// size_t choosen_node_index = rstar::choose_next_node<Value, Box>::
-// apply(n, rtree::element_indexable(m_element, m_tr));
-//
-// //TEST
-// /*{
-// std::ofstream log("log.txt", std::ofstream::trunc);
-// log << std::fixed << "internal node " << m_current_level << " " << m_level << '\n';
-// boost::geometry::index::detail::rtree::visitors::detail::print_indexable(log, rtree::element_indexable(m_element, m_tr));
-// log << '\n' << "choosen node: " << choosen_node_index << "\n";
-// log << "before: ";
-// boost::geometry::index::detail::rtree::visitors::detail::print_indexable(log, n.children[choosen_node_index].first);
-// log << "\n";
-// }*/
-//
-// // expand the node to contain value
-// geometry::expand(
-// n.children[choosen_node_index].first,
-// rtree::element_indexable(m_element, m_tr));
-//
-// //TEST
-// /*{
-// std::ofstream log("log.txt", std::ofstream::app);
-// log << std::fixed << choosen_node_index << "after: ";
-// boost::geometry::index::detail::rtree::visitors::detail::print_indexable(log, n.children[choosen_node_index].first);
-// log << '\n';
-// boost::geometry::index::detail::rtree::visitors::print<Value, Translator, Box, rstar_tag> print_v(log, m_tr);
-// boost::apply_visitor(print_v, *m_root_node);
-// }*/
-//
-// // apply traversing visitor
-// traverse_apply_visitor(d, n, choosen_node_index);
-// }
-//
-// template <typename Node>
-// inline void post_traverse_handle_oveflow(Node &n)
-// {
-// // handle overflow
-// if ( m_max_elems_per_node < rtree::elements_get(n).size() )
-// {
-// detail::overflow_treatment<Value, Translator, Box, Tag>::
-// apply(n, m_parent, m_current_child_index, m_root_node, m_min_elems_per_node, m_max_elems_per_node, m_tr);
-// }
-// }
-//
-// template <typename Derived>
-// inline void traverse_apply_visitor(Derived & d, internal_node &n, size_t choosen_node_index)
-// {
-// // save previous traverse inputs and set new ones
-// internal_node * parent_bckup = m_parent;
-// size_t current_child_index_bckup = m_current_child_index;
-// size_t current_level_bckup = m_current_level;
-//
-// m_parent = &n;
-// m_current_child_index = choosen_node_index;
-// ++m_current_level;
-//
-// // next traversing step
-// boost::apply_visitor(d, *n.children[choosen_node_index].second);
-//
-// // restore previous traverse inputs
-// m_parent = parent_bckup;
-// m_current_child_index = current_child_index_bckup;
-// m_current_level = current_level_bckup;
-// }
-//
-// // before calling overflow_treatment all nodes have aabbs expanded
-// // and the number of elements in the current node is max + 1
-// template <typename Node>
-// inline void overflow_treatment(Node & n)
-// {
-// // TODO: awulkiew - replace this condition with tag dispatched template
-//
-// // first time insert
-// /*if ( m_parent != 0 &&
-// m_level == std::numeric_limits<size_t>::max() &&
-// 0 < m_reinserted_elements_count )
-// {
-// reinsert(n);
-// }
-// // second time insert
-// else
-// {*/
-// rstar::split<Value, Translator, Box>::
-// apply(n, m_parent, m_current_child_index, m_root_node, m_min_elems_per_node, m_max_elems_per_node, m_tr);
-// //}
-// }
-//
-// template <typename Distance, typename El>
-// static inline bool distances_asc(
-// std::pair<Distance, El> const& d1,
-// std::pair<Distance, El> const& d2)
-// {
-// return d1.first < d2.first;
-// }
-//
-// template <typename Distance, typename El>
-// static inline bool distances_dsc(
-// std::pair<Distance, El> const& d1,
-// std::pair<Distance, El> const& d2)
-// {
-// return d1.first > d2.first;
-// }
-//
-// template <typename Node>
-// inline void reinsert(Node & n)
-// {
-// typedef typename index::detail::rtree::elements_type<Node>::type elements_type;
-// typedef typename index::detail::rtree::element_type<Node>::type element_type;
-// typedef typename geometry::point_type<Box>::type point_type;
-// // TODO: awulkiew - use distance_result
-// typedef typename index::traits::coordinate_type<point_type>::type distance_type;
-//
-// assert(m_parent != 0);
-// assert(0 < m_reinserted_elements_count);
-//
-// point_type node_center;
-// geometry::centroid(m_parent->children[m_current_child_index].first, node_center);
-//
-// elements_type & elements = index::detail::rtree::elements_get(n);
-//
-// size_t elements_count = elements.size();
-// std::vector< std::pair<distance_type, element_type> > distances(elements_count);
-// for ( size_t i = 0 ; i < elements_count ; ++i )
-// {
-// // TODO: awulkiew - use distance_sqr
-// // (use select_calculation_type if distance_sqr must be implemented in geometry::index)
-// // change point type for this geometry
-// point_type element_center;
-// geometry::centroid( index::detail::rtree::element_indexable(
-// elements[i],
-// m_tr
-// ), element_center);
-//
-// distances[i].first = geometry::distance(node_center, element_center);
-// distances[i].second = elements[i];
-// }
-//
-// // sort elements by distances from center
-// std::partial_sort(
-// distances.begin(),
-// distances.begin() + m_reinserted_elements_count,
-// distances.end(),
-// distances_dsc<distance_type, element_type>);
-//
-// // copy elements which will be reinserted
-// elements_type elements_to_reinsert(m_reinserted_elements_count);
-// for ( size_t i = 0 ; i < m_reinserted_elements_count ; ++i )
-// elements_to_reinsert[i] = distances[i].second;
-//
-// // copy elements to the current node
-// elements.resize(elements_count - m_reinserted_elements_count);
-// for ( size_t i = m_reinserted_elements_count ; i < elements_count ; ++i )
-// elements[i - m_reinserted_elements_count] = distances[i].second;
-//
-// // calulate node's new box
-// m_parent->children[m_current_child_index].first =
-// elements_box<Box>(elements.begin(), elements.end(), m_tr);
-//
-// // reinsert children starting from the minimum distance
-// for ( size_t i = m_reinserted_elements_count ; 0 < i ; --i )
-// {
-// insert_impl<Value, Translator, Box, element_type> insert_v(
-// m_root_node, elements_to_reinsert[i - 1],
-// m_min_elems_per_node, m_max_elems_per_node,
-// m_tr, m_current_level);
-// boost::apply_visitor(insert_v, *m_root_node);
-// }
-// }
-//
-// Element const& m_element;
-// Translator const& m_tr;
-// const size_t m_min_elems_per_node;
-// const size_t m_max_elems_per_node;
-// const size_t m_reinserted_elements_count;
-//
-// const size_t m_level;
-//
-// node* & m_root_node;
-//
-// // traversing input parameters
-// internal_node *m_parent;
-// size_t m_current_child_index;
-// size_t m_current_level;
-//};
+namespace rstar {
+
+template <typename Value, typename Translator, typename Box>
+class remove_elements_to_reinsert
+{
+public:
+ typedef typename rtree::node<Value, Box, rstar_tag>::type node;
+ typedef typename rtree::internal_node<Value, Box, rstar_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, Box, rstar_tag>::type leaf;
+
+ template <typename Node>
+ static inline void apply(
+ typename rtree::elements_type<Node>::type & result_elements,
+ Node & n,
+ internal_node *parent,
+ size_t current_child_index,
+ size_t min_elems,
+ size_t max_elems,
+ Translator const& tr)
+ {
+ typedef typename rtree::elements_type<Node>::type elements_type;
+ typedef typename elements_type::value_type element_type;
+ typedef typename geometry::point_type<Box>::type point_type;
+ // TODO: awulkiew - change second point_type to the point type of the Indexable?
+ typedef typename index::default_distance_sqr_result<point_type, point_type>::type distance_sqr_type;
+
+ assert(parent != 0);
+
+ const size_t reinserted_elements_count = static_cast<size_t>(max_elems * 0.3f);
+ assert(0 < reinserted_elements_count);
+
+ // calculate current node's center
+ point_type node_center;
+ geometry::centroid(rtree::elements(*parent)[current_child_index].first, node_center);
+
+ // fill the container of centers' distances of children from current node's center
+ elements_type & elements = rtree::elements(n);
+ size_t elements_count = elements.size();
+ std::vector< std::pair<distance_sqr_type, element_type> > sorted_elements(elements_count);
+ for ( size_t i = 0 ; i < elements_count ; ++i )
+ {
+ point_type element_center;
+ geometry::centroid( rtree::element_indexable(elements[i], tr),
+ element_center);
+ sorted_elements[i].first = index::distance_sqr(node_center, element_center);
+ sorted_elements[i].second = elements[i];
+ }
+
+ // sort elements by distances from center
+ std::partial_sort(
+ sorted_elements.begin(),
+ sorted_elements.begin() + reinserted_elements_count,
+ sorted_elements.end(),
+ distances_dsc<distance_sqr_type, element_type>);
+
+ // copy elements which will be reinserted
+ result_elements.resize(reinserted_elements_count);
+ for ( size_t i = 0 ; i < reinserted_elements_count ; ++i )
+ result_elements[i] = sorted_elements[i].second;
+
+ // copy remaining elements to the current node
+ elements.resize(elements_count - reinserted_elements_count);
+ for ( size_t i = reinserted_elements_count ; i < elements_count ; ++i )
+ elements[i - reinserted_elements_count] = sorted_elements[i].second;
+ }
+
+private:
+ template <typename Distance, typename El>
+ static inline bool distances_asc(
+ std::pair<Distance, El> const& d1,
+ std::pair<Distance, El> const& d2)
+ {
+ return d1.first < d2.first;
+ }
+
+ template <typename Distance, typename El>
+ static inline bool distances_dsc(
+ std::pair<Distance, El> const& d1,
+ std::pair<Distance, El> const& d2)
+ {
+ return d1.first > d2.first;
+ }
+};
+
+template <typename Value, typename Translator, typename Box>
+struct reinsert_or_split_root
+{
+ typedef typename rtree::node<Value, Box, rstar_tag>::type node;
+ typedef typename rtree::internal_node<Value, Box, rstar_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, Box, rstar_tag>::type leaf;
+
+ template <typename Node>
+ static inline void apply(
+ typename rtree::elements_type<Node>::type & result_elements,
+ Node & n,
+ internal_node *parent,
+ size_t current_child_index,
+ node* & root_node,
+ size_t & leafs_level,
+ size_t min_elems,
+ size_t max_elems,
+ Translator const& tr)
+ {
+ // node isn't root node
+ if ( parent )
+ {
+ rstar::remove_elements_to_reinsert<Value, Translator, Box>::apply(
+ result_elements, n,
+ parent, current_child_index,
+ min_elems, max_elems, tr);
+ }
+ // node is root node
+ else
+ {
+ // it's really the root node
+ assert(&rtree::get<Node>(n) == root_node);
+
+ detail::split<Value, Translator, Box, rstar_tag>::apply(
+ n,
+ parent, current_child_index,
+ root_node, leafs_level,
+ min_elems, max_elems, tr);
+ }
+ }
+};
+
+template <size_t InsertIndex, typename Element, typename Value, typename Translator, typename Box>
+struct level_insert
+ : public detail::insert<Element, Value, Translator, Box, rstar_tag>
+{
+ typedef detail::insert<Element, Value, Translator, Box, rstar_tag> base;
+ typedef typename base::node node;
+ typedef typename base::internal_node internal_node;
+ typedef typename base::leaf leaf;
+
+ typedef typename rtree::elements_type<internal_node>::type result_type;
+
+ inline level_insert(node* & root,
+ size_t & leafs_level,
+ Element const& element,
+ size_t min_elements,
+ size_t max_elements,
+ Translator const& tr,
+ size_t relative_level)
+ : base(root, leafs_level, element, min_elements, max_elements, tr, relative_level)
+ , result_relative_level(0)
+ {}
+
+ inline void operator()(internal_node & n)
+ {
+ assert(base::m_current_level < base::m_leafs_level);
+
+ if ( base::m_current_level < base::m_level )
+ {
+ // next traversing step
+ base::traverse(*this, n);
+
+ // further insert
+ if ( 0 < InsertIndex )
+ {
+ assert(0 < base::m_level);
+
+ if ( base::m_current_level == base::m_level - 1 )
+ {
+ result_relative_level = base::m_leafs_level - base::m_current_level;
+
+ // overflow
+ if ( base::m_max_elems_per_node < rtree::elements(n).size() )
+ {
+ rstar::reinsert_or_split_root<Value, Translator, Box>::apply(
+ result_elements, n,
+ base::m_parent, base::m_current_child_index,
+ base::m_root_node, base::m_leafs_level,
+ base::m_min_elems_per_node, base::m_max_elems_per_node, base::m_tr);
+ }
+ }
+ }
+ }
+ else
+ {
+ assert( base::m_level == base::m_current_level );
+
+ // push new child node
+ rtree::elements(n).push_back(base::m_element);
+
+ // first insert
+ if ( 0 == InsertIndex )
+ {
+ result_relative_level = base::m_leafs_level - base::m_current_level;
+
+ // overflow
+ if ( base::m_max_elems_per_node < rtree::elements(n).size() )
+ {
+ rstar::reinsert_or_split_root<Value, Translator, Box>::apply(
+ result_elements, n,
+ base::m_parent, base::m_current_child_index,
+ base::m_root_node, base::m_leafs_level,
+ base::m_min_elems_per_node, base::m_max_elems_per_node, base::m_tr);
+ }
+ }
+ // not the first insert
+ else
+ {
+ // overflow
+ if ( base::m_max_elems_per_node < rtree::elements(n).size() )
+ {
+ detail::split<Value, Translator, Box, rstar_tag>::apply(
+ n,
+ base::m_parent, base::m_current_child_index,
+ base::m_root_node, base::m_leafs_level,
+ base::m_min_elems_per_node, base::m_max_elems_per_node, base::m_tr);
+ }
+ }
+ }
+
+ if ( !result_elements.empty() && base::m_parent )
+ {
+ // calulate node's new box
+ rtree::elements(*base::m_parent)[base::m_current_child_index].first =
+ elements_box<Box>(rtree::elements(n).begin(), rtree::elements(n).end(), base::m_tr);
+ }
+ }
+
+ inline void operator()(leaf &)
+ {
+ assert(false);
+ }
+
+ size_t result_relative_level;
+ result_type result_elements;
+};
+
+template <size_t InsertIndex, typename Value, typename Translator, typename Box>
+struct level_insert<InsertIndex, Value, Value, Translator, Box>
+ : public detail::insert<Value, Value, Translator, Box, rstar_tag>
+{
+ typedef detail::insert<Value, Value, Translator, Box, rstar_tag> base;
+ typedef typename base::node node;
+ typedef typename base::internal_node internal_node;
+ typedef typename base::leaf leaf;
+
+ typedef typename rtree::elements_type<internal_node>::type result_type;
+
+ inline level_insert(node* & root,
+ size_t & leafs_level,
+ Value const& v,
+ size_t min_elements,
+ size_t max_elements,
+ Translator const& t,
+ size_t relative_level)
+ : base(root, leafs_level, v, min_elements, max_elements, t, relative_level)
+ , result_relative_level(0)
+ {}
+
+ inline void operator()(internal_node & n)
+ {
+ assert(base::m_current_level < base::m_leafs_level);
+ assert(base::m_current_level < base::m_level);
+
+ // next traversing step
+ base::traverse(*this, n);
+
+ assert(0 < base::m_level);
+
+ if ( base::m_current_level == base::m_level - 1 )
+ {
+ result_relative_level = base::m_leafs_level - base::m_current_level;
+
+ // overflow
+ if ( base::m_max_elems_per_node < rtree::elements(n).size() )
+ {
+ rstar::reinsert_or_split_root<Value, Translator, Box>::apply(
+ result_elements, n,
+ base::m_parent, base::m_current_child_index,
+ base::m_root_node, base::m_leafs_level,
+ base::m_min_elems_per_node, base::m_max_elems_per_node, base::m_tr);
+ }
+ }
+
+ if ( !result_elements.empty() && base::m_parent )
+ {
+ // calulate node's new box
+ rtree::elements(*base::m_parent)[base::m_current_child_index].first =
+ elements_box<Box>(rtree::elements(n).begin(), rtree::elements(n).end(), base::m_tr);
+ }
+ }
+
+ inline void operator()(leaf & n)
+ {
+ assert(base::m_current_level == base::m_leafs_level);
+ assert(base::m_level == base::m_current_level ||
+ base::m_level == std::numeric_limits<size_t>::max());
+
+ rtree::elements(n).push_back(base::m_element);
+
+ if ( base::m_max_elems_per_node < rtree::elements(n).size() )
+ {
+ detail::split<Value, Translator, Box, rstar_tag>::apply(
+ n,
+ base::m_parent, base::m_current_child_index,
+ base::m_root_node, base::m_leafs_level,
+ base::m_min_elems_per_node, base::m_max_elems_per_node, base::m_tr);
+ }
+ }
+
+ size_t result_relative_level;
+ result_type result_elements;
+};
+
+template <typename Value, typename Translator, typename Box>
+struct level_insert<0, Value, Value, Translator, Box>
+ : public detail::insert<Value, Value, Translator, Box, rstar_tag>
+{
+ typedef detail::insert<Value, Value, Translator, Box, rstar_tag> base;
+ typedef typename base::node node;
+ typedef typename base::internal_node internal_node;
+ typedef typename base::leaf leaf;
+
+ typedef typename rtree::elements_type<leaf>::type result_type;
+
+ inline level_insert(node* & root,
+ size_t & leafs_level,
+ Value const& v,
+ size_t min_elements,
+ size_t max_elements,
+ Translator const& t,
+ size_t relative_level)
+ : base(root, leafs_level, v, min_elements, max_elements, t, relative_level)
+ , result_relative_level(0)
+ {}
+
+ inline void operator()(internal_node & n)
+ {
+ assert(base::m_current_level < base::m_leafs_level);
+ assert(base::m_current_level < base::m_level);
+
+ // next traversing step
+ base::traverse(*this, n);
+
+ if ( !result_elements.empty() && base::m_parent )
+ {
+ // calulate node's new box
+ rtree::elements(*base::m_parent)[base::m_current_child_index].first =
+ elements_box<Box>(rtree::elements(n).begin(), rtree::elements(n).end(), base::m_tr);
+ }
+ }
+
+ inline void operator()(leaf & n)
+ {
+ assert(base::m_current_level == base::m_leafs_level);
+ assert(base::m_level == base::m_current_level ||
+ base::m_level == std::numeric_limits<size_t>::max());
+
+ rtree::elements(n).push_back(base::m_element);
+
+ result_relative_level = base::m_leafs_level - base::m_current_level;
+
+ if ( base::m_max_elems_per_node < rtree::elements(n).size() )
+ {
+ rstar::reinsert_or_split_root<Value, Translator, Box>::apply(
+ result_elements, n,
+ base::m_parent, base::m_current_child_index,
+ base::m_root_node, base::m_leafs_level,
+ base::m_min_elems_per_node, base::m_max_elems_per_node, base::m_tr);
+ }
+
+ if ( !result_elements.empty() && base::m_parent )
+ {
+ // calulate node's new box
+ rtree::elements(*base::m_parent)[base::m_current_child_index].first =
+ elements_box<Box>(rtree::elements(n).begin(), rtree::elements(n).end(), base::m_tr);
+ }
+ }
+
+ size_t result_relative_level;
+ result_type result_elements;
+};
+
+// R*-tree insert visitor
+template <typename Element, typename Value, typename Translator, typename Box>
+class insert : public rtree::visitor<Value, Box, rstar_tag, false>::type
+{
+protected:
+ typedef typename rtree::node<Value, Box, rstar_tag>::type node;
+ typedef typename rtree::internal_node<Value, Box, rstar_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, Box, rstar_tag>::type leaf;
+
+public:
+ inline insert(node* & root,
+ size_t & leafs_level,
+ Element const& element,
+ size_t min_elements,
+ size_t max_elements,
+ Translator const& tr,
+ size_t relative_level = 0
+ )
+ : m_root(root), m_leafs_level(leafs_level), m_element(element)
+ , m_min_elements(min_elements), m_max_elements(max_elements)
+ , m_tr(tr), m_relative_level(relative_level)
+ {}
+
+ inline void operator()(internal_node & n)
+ {
+ typedef typename elements_type<internal_node>::type elements_type;
+
+ rstar::level_insert<0, Element, Value, Translator, Box> lins_v(
+ m_root, m_leafs_level, m_element, m_min_elements, m_max_elements, m_tr, m_relative_level);
+
+ rtree::apply_visitor(lins_v, n);
+
+ if ( !lins_v.result_elements.empty() )
+ {
+ recursive_reinsert(lins_v.result_elements, lins_v.result_relative_level);
+ }
+ }
+
+ inline void operator()(leaf & n)
+ {
+ rstar::level_insert<0, Element, Value, Translator, Box> lins_v(
+ m_root, m_leafs_level, m_element, m_min_elements, m_max_elements, m_tr, m_relative_level);
+
+ rtree::apply_visitor(lins_v, n);
+
+ // we're in the root, so root should be split and there should be no elements to reinsert
+ assert(lins_v.result_elements.empty());
+ }
+
+protected:
+ template <typename Elements>
+ inline void recursive_reinsert(Elements const& elements, size_t relative_level)
+ {
+ typedef typename Elements::value_type element_type;
+
+ // reinsert children starting from the minimum distance
+ for ( typename Elements::const_reverse_iterator it = elements.rbegin();
+ it != elements.rend(); ++it)
+ {
+ rstar::level_insert<1, element_type, Value, Translator, Box> lins_v(
+ m_root, m_leafs_level, *it, m_min_elements, m_max_elements, m_tr, relative_level);
+
+ rtree::apply_visitor(lins_v, *m_root);
+
+ assert(relative_level + 1 == lins_v.result_relative_level);
+
+ // non-root relative level
+ if ( lins_v.result_relative_level < m_leafs_level && !lins_v.result_elements.empty())
+ {
+ recursive_reinsert(lins_v.result_elements, lins_v.result_relative_level);
+ }
+ }
+ }
+
+ node* & m_root;
+ size_t & m_leafs_level;
+ Element const& m_element;
+ size_t m_min_elements;
+ size_t m_max_elements;
+ Translator const& m_tr;
+ size_t m_relative_level;
+};
+
+} // namespace rstar
} // namespace detail
+// R*-tree insert visitor
+template <typename Element, typename Value, typename Translator, typename Box>
+class insert<Element, Value, Translator, Box, rstar_tag>
+ : public detail::rstar::insert<Element, Value, Translator, Box>
+{
+ typedef detail::rstar::insert<Element, Value, Translator, Box> base;
+ typedef typename base::node node;
+
+public:
+ inline insert(node* & root,
+ size_t & leafs_level,
+ Element const& element,
+ size_t min_elements,
+ size_t max_elements,
+ Translator const& tr,
+ size_t relative_level = 0
+ )
+ : base(root, leafs_level, element, min_elements, max_elements, tr, relative_level)
+ {}
+};
+
+// R*-tree insert visitor
+template <typename Value, typename Translator, typename Box>
+class insert<Value, Value, Translator, Box, rstar_tag>
+ : public detail::rstar::insert<Value, Value, Translator, Box>
+{
+ typedef detail::rstar::insert<Value, Value, Translator, Box> base;
+ typedef typename base::node node;
+
+public:
+ inline insert(node* & root,
+ size_t & leafs_level,
+ Value const& element,
+ size_t min_elements,
+ size_t max_elements,
+ Translator const& tr,
+ size_t relative_level = 0
+ )
+ : base(root, leafs_level, element, min_elements, max_elements, tr, relative_level)
+ {}
+};
+
}}} // namespace detail::rtree::visitors
}}} // namespace boost::geometry::index
Modified: sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/rstar/redistribute_elements.hpp
==============================================================================
--- sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/rstar/redistribute_elements.hpp (original)
+++ sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/rstar/redistribute_elements.hpp 2011-06-09 19:55:58 EDT (Thu, 09 Jun 2011)
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
//
-// Boost.Index - R-tree quadratic split algorithm implementation
+// Boost.Index - R*-tree split algorithm implementation
//
// Copyright 2011 Adam Wulkiewicz.
// Use, modification and distribution is subject to the Boost Software License,
@@ -35,7 +35,8 @@
typedef typename index::default_area_result<Box>::type area_type;
template <typename Node>
- static inline void apply(Node & n,
+ static inline void apply(
+ Node & n,
Node & second_node,
Box & box1,
Box & box2,
Modified: sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/rstar/rstar.hpp
==============================================================================
--- sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/rstar/rstar.hpp (original)
+++ sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/rstar/rstar.hpp 2011-06-09 19:55:58 EDT (Thu, 09 Jun 2011)
@@ -16,6 +16,7 @@
}}} // namespace boost::geometry::index
+#include <boost/geometry/extensions/index/rtree/rstar/insert.hpp>
#include <boost/geometry/extensions/index/rtree/rstar/choose_next_node.hpp>
#include <boost/geometry/extensions/index/rtree/rstar/redistribute_elements.hpp>
Deleted: sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/rstar/split.hpp
==============================================================================
--- sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/rstar/split.hpp 2011-06-09 19:55:58 EDT (Thu, 09 Jun 2011)
+++ (empty file)
@@ -1,345 +0,0 @@
-// Boost.Geometry (aka GGL, Generic Geometry Library)
-//
-// Boost.Index - R*-tree split algorithm implementation
-//
-// Copyright 2011 Adam Wulkiewicz.
-// Use, modification and distribution is subject to the Boost Software License,
-// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_RSTAR_SPLIT_HPP
-#define BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_RSTAR_SPLIT_HPP
-
-#include <algorithm>
-
-#include <boost/tuple/tuple.hpp>
-
-#include <boost/geometry/extensions/index/algorithms/area.hpp>
-#include <boost/geometry/extensions/index/algorithms/margin.hpp>
-#include <boost/geometry/extensions/index/algorithms/overlap.hpp>
-#include <boost/geometry/extensions/index/algorithms/union_area.hpp>
-
-#include <boost/geometry/extensions/index/rtree/node.hpp>
-#include <boost/geometry/extensions/index/rtree/visitors/insert.hpp>
-#include <boost/geometry/extensions/index/rtree/visitors/is_leaf.hpp>
-
-namespace boost { namespace geometry { namespace index {
-
-namespace detail { namespace rtree { namespace rstar {
-
-// elements less
-
-template <typename Elements, typename Translator, size_t AxisIndex, size_t Corner>
-class elements_less
-{
- typedef typename Elements::value_type element_type;
-public:
- inline elements_less(Translator const& tr)
- : m_tr(tr)
- {}
-
- inline bool operator()(element_type const& e1, element_type const e2) const
- {
- return
- index::get<Corner, AxisIndex>(
- rtree::element_indexable(e1, m_tr)
- )
- <
- index::get<Corner, AxisIndex>(
- rtree::element_indexable(e2, m_tr)
- );
- }
-
-private:
- Translator const& m_tr;
-};
-
-// rstar split axis data
-
-template <typename Box>
-struct split_axis_data
-{
- typedef typename default_margin_result<Box>::type margin_type;
- typedef typename default_overlap_result<Box>::type overlap_type;
- typedef typename default_area_result<Box>::type area_type;
-
- inline split_axis_data()
- : margins_sum(0)
- , smallest_overlap(std::numeric_limits<overlap_type>::max())
- , smallest_area(std::numeric_limits<area_type>::max())
- {}
-
- inline void update(
- size_t corner,
- size_t median_index,
- Box const& left_box,
- Box const& right_box,
- margin_type const& margin,
- overlap_type const& overlap,
- area_type const& area)
- {
- margins_sum += margin;
-
- if ( overlap < smallest_overlap ||
- ( overlap == smallest_overlap && area < smallest_area ) )
- {
- choosen_corner = corner;
- choosen_median_index = median_index;
- choosen_left_box = left_box;
- choosen_right_box = right_box;
- smallest_overlap = overlap;
- smallest_area = area;
- }
- }
-
- size_t choosen_corner;
- size_t choosen_median_index;
- Box choosen_left_box;
- Box choosen_right_box;
- margin_type margins_sum;
- overlap_type smallest_overlap;
- area_type smallest_area;
-};
-
-// update axis data for given axis and corner
-
-template <typename Value, typename Translator, typename Box, size_t Corner>
-class split_update_axis_data_for_corner
-{
- typedef typename split_axis_data<Box>::margin_type margin_type;
- typedef typename split_axis_data<Box>::overlap_type overlap_type;
- typedef typename split_axis_data<Box>::area_type area_type;
-
- BOOST_STATIC_ASSERT(Corner < 2);
-
-public:
- template <typename Elements>
- static inline void apply(
- split_axis_data<Box> & sad,
- Elements const& sorted_elements,
- size_t min_elems,
- size_t max_elems,
- Translator const& tr)
- {
- size_t median_index_last = max_elems - min_elems + 2;
- for ( size_t median_index = min_elems ; median_index < median_index_last ; ++median_index )
- {
- Box left_box = rtree::elements_box<Box>(sorted_elements.begin(), sorted_elements.begin() + median_index, tr);
- Box right_box = rtree::elements_box<Box>(sorted_elements.begin() + median_index, sorted_elements.end(), tr);
-
- margin_type margin = index::margin(left_box) + index::margin(right_box);
- overlap_type overlap = index::overlap(left_box, right_box);
- area_type area = index::area(left_box) + index::area(right_box);
-
- sad.update(Corner, median_index, left_box, right_box, margin, overlap, area);
- }
- }
-};
-
-// split data
-
-template <typename Elements, typename Box>
-struct split_data
-{
- typedef typename default_margin_result<Box>::type margin_type;
- typedef typename default_overlap_result<Box>::type overlap_type;
- typedef typename default_area_result<Box>::type area_type;
-
- inline split_data()
- : smallest_margins_sum(std::numeric_limits<margin_type>::max())
- {}
-
- inline void update(
- size_t axis,
- size_t corner,
- size_t median_index,
- Box const& left_box,
- Box const& right_box,
- margin_type const& margins_sum,
- Elements const& distribution)
- {
- if ( margins_sum < smallest_margins_sum )
- {
- choosen_axis = axis;
- choosen_corner = corner;
- choosen_median_index = median_index;
- choosen_left_box = left_box;
- choosen_right_box = right_box;
- smallest_margins_sum = margins_sum;
- choosen_distribution = distribution;
- }
- }
-
- size_t choosen_axis;
- size_t choosen_corner;
- size_t choosen_median_index;
- Box choosen_left_box;
- Box choosen_right_box;
- margin_type smallest_margins_sum;
- Elements choosen_distribution;
-};
-
-// update split data for given axis and corner
-
-template <typename Value, typename Translator, typename Box, size_t AxisIndex, size_t Corner>
-class split_update_data_for_axis_and_corner
-{
- typedef typename split_axis_data<Box>::margin_type margin_type;
- typedef typename split_axis_data<Box>::overlap_type overlap_type;
- typedef typename split_axis_data<Box>::area_type area_type;
-
-public:
- template <typename Elements>
- static inline void apply(
- split_data<Elements, Box> & split_data,
- Elements & elements,
- size_t min_elems,
- size_t max_elems,
- Translator const& tr)
- {
- split_axis_data<Box> sad;
-
- elements_less<Elements, Translator, AxisIndex, Corner> less_min(tr);
- std::sort(elements.begin(), elements.end(), less_min);
-
- split_update_axis_data_for_corner<Value, Translator, Box, Corner>::
- apply(sad, elements, min_elems, max_elems, tr);
-
- split_data.update(
- AxisIndex,
- sad.choosen_corner,
- sad.choosen_median_index,
- sad.choosen_left_box,
- sad.choosen_right_box,
- sad.margins_sum,
- elements);
- }
-};
-
-// for each dimension and corner update split data
-
-template <typename Value, typename Translator, typename Box, size_t Dimension>
-struct split_update_data
-{
- BOOST_STATIC_ASSERT(0 < Dimension);
-
- template <typename Elements>
- static inline void apply(
- split_data<Elements, Box> & sd,
- Elements & elements,
- size_t min_elems,
- size_t max_elems,
- Translator const& tr)
- {
- split_update_data<Value, Translator, Box, Dimension - 1>::
- apply(sd, elements, min_elems, max_elems, tr);
-
- split_update_data_for_axis_and_corner<Value, Translator, Box, Dimension - 1, min_corner>::
- apply(sd, elements, min_elems, max_elems, tr);
- split_update_data_for_axis_and_corner<Value, Translator, Box, Dimension - 1, max_corner>::
- apply(sd, elements, min_elems, max_elems, tr);
- }
-};
-
-template <typename Value, typename Translator, typename Box>
-struct split_update_data<Value, Translator, Box, 1>
-{
- template <typename Elements>
- static inline void apply(
- split_data<Elements, Box> & sd,
- Elements & elements,
- size_t min_elems,
- size_t max_elems,
- Translator const& tr)
- {
- split_update_data_for_axis_and_corner<Value, Translator, Box, 0, min_corner>::
- apply(sd, elements, min_elems, max_elems, tr);
- split_update_data_for_axis_and_corner<Value, Translator, Box, 0, max_corner>::
- apply(sd, elements, min_elems, max_elems, tr);
- }
-};
-
-// split
-
-template <typename Value, typename Translator, typename Box>
-class split
-{
- typedef typename rtree::node<Value, Box, rstar_tag>::type node;
- typedef typename rtree::internal_node<Value, Box, rstar_tag>::type internal_node;
- typedef typename rtree::leaf<Value, Box, rstar_tag>::type leaf;
-
- static const size_t dimension = index::traits::dimension<Box>::value;
-
-public:
- template <typename Node>
- static inline void apply(
- Node & n,
- internal_node *parent,
- size_t current_child_index,
- node *& root,
- size_t min_elems,
- size_t max_elems,
- Translator const& tr)
- {
- typedef typename rtree::elements_type<Node>::type elements_type;
- typedef typename elements_type::value_type element_type;
-
- elements_type & elements = rtree::elements_get(n);
-
- assert(elements.size() == max_elems + 1);
-
- // get split data
- split_data<elements_type, Box> sd;
- split_update_data<Value, Translator, Box, dimension>::
- apply(sd, elements, min_elems, max_elems, tr);
-
- assert(min_elems <= sd.choosen_median_index);
- assert(sd.choosen_median_index <= max_elems + 1 - min_elems);
-
- // create new node
- node * right_node = rtree::create_node(Node());
- elements_type & new_elems = rtree::elements_get(boost::get<Node>(*right_node));
-
- // update new node's elements
- new_elems.resize(max_elems + 1 - sd.choosen_median_index);
- std::copy(
- sd.choosen_distribution.begin() + sd.choosen_median_index,
- sd.choosen_distribution.end(),
- new_elems.begin());
-
- // update elements of the current node
- elements.resize(sd.choosen_median_index);
- std::copy(
- sd.choosen_distribution.begin(),
- sd.choosen_distribution.begin() + sd.choosen_median_index,
- elements.begin());
-
- // node is not the root
- if ( parent != 0 )
- {
- // update old node's box
- parent->children[current_child_index].first = sd.choosen_left_box;
- // add new node to the parent's children
- parent->children.push_back(std::make_pair(sd.choosen_right_box, right_node));
- }
- // node is the root
- else
- {
- assert(&n == boost::get<Node>(root));
-
- // create new root and add nodes
- node * new_root = rtree::create_node(internal_node());
-
- boost::get<internal_node>(*new_root).children.push_back(std::make_pair(sd.choosen_left_box, root));
- boost::get<internal_node>(*new_root).children.push_back(std::make_pair(sd.choosen_right_box, right_node));
-
- root = new_root;
- }
- }
-};
-
-}}} // namespace detail::rtree:rstar
-
-}}} // namespace boost::geometry::index
-
-#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_RSTAR_SPLIT_HPP
Modified: sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/rtree.hpp
==============================================================================
--- sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/rtree.hpp (original)
+++ sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/rtree.hpp 2011-06-09 19:55:58 EDT (Thu, 09 Jun 2011)
@@ -54,6 +54,7 @@
, m_max_elems_per_node(max_elems_per_node)
, m_min_elems_per_node(min_elems_per_node)
, m_root(0)
+ , m_leafs_level(0)
, m_translator(translator)
{
if ( m_min_elems_per_node < 1 )
@@ -86,7 +87,7 @@
// TODO: awulkiew - assert for correct value
detail::rtree::visitors::insert<value_type, value_type, translator_type, box_type, tag_type>
- insert_v(m_root, value, m_min_elems_per_node, m_max_elems_per_node, m_translator);
+ insert_v(m_root, m_leafs_level, value, m_min_elems_per_node, m_max_elems_per_node, m_translator);
detail::rtree::apply_visitor(insert_v, *m_root);
@@ -99,7 +100,7 @@
assert(0 < m_values_count);
detail::rtree::visitors::remove<value_type, translator_type, box_type, tag_type>
- remove_v(m_root, value, m_min_elems_per_node, m_max_elems_per_node, m_translator);
+ remove_v(m_root, m_leafs_level, value, m_min_elems_per_node, m_max_elems_per_node, m_translator);
detail::rtree::apply_visitor(remove_v, *m_root);
@@ -144,6 +145,7 @@
size_t m_max_elems_per_node;
size_t m_min_elems_per_node;
node *m_root;
+ size_t m_leafs_level;
translator_type m_translator;
};
Modified: sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/visitors/are_boxes_ok.hpp
==============================================================================
--- sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/visitors/are_boxes_ok.hpp (original)
+++ sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/visitors/are_boxes_ok.hpp 2011-06-09 19:55:58 EDT (Thu, 09 Jun 2011)
@@ -74,21 +74,27 @@
typedef typename rtree::elements_type<leaf>::type elements_type;
elements_type const& elements = rtree::elements(n);
- if (elements.empty())
+ // non-root node
+ if (!m_is_root)
{
- result = false;
- return;
- }
-
- Box box_exp;
- geometry::convert(m_tr(elements.front()), box_exp);
- for(typename elements_type::const_iterator it = elements.begin() + 1;
- it != elements.end() ; ++it)
- {
- geometry::expand(box_exp, m_tr(*it));
- }
-
- result = m_is_root || geometry::equals(box_exp, m_box);
+ if ( elements.empty() )
+ {
+ result = false;
+ return;
+ }
+
+ Box box_exp;
+ geometry::convert(m_tr(elements.front()), box_exp);
+ for(typename elements_type::const_iterator it = elements.begin() + 1;
+ it != elements.end() ; ++it)
+ {
+ geometry::expand(box_exp, m_tr(*it));
+ }
+
+ result = geometry::equals(box_exp, m_box);
+ }
+ else
+ result = true;
}
bool result;
Added: sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/visitors/are_levels_ok.hpp
==============================================================================
--- (empty file)
+++ sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/visitors/are_levels_ok.hpp 2011-06-09 19:55:58 EDT (Thu, 09 Jun 2011)
@@ -0,0 +1,105 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Boost.Index - R-tree levels checking visitor
+//
+// Copyright 2011 Adam Wulkiewicz.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_VISITORS_ARE_LEVELS_OK_HPP
+#define BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_VISITORS_ARE_LEVELS_OK_HPP
+
+#include <boost/geometry/extensions/index/rtree/node.hpp>
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree { namespace visitors {
+
+template <typename Value, typename Translator, typename Box, typename Tag>
+class are_levels_ok : public rtree::visitor<Value, Box, Tag, true>::type
+{
+ typedef typename rtree::internal_node<Value, Box, Tag>::type internal_node;
+ typedef typename rtree::leaf<Value, Box, Tag>::type leaf;
+
+public:
+ inline are_levels_ok(Translator const& tr)
+ : result(true), m_tr(tr), m_leafs_level(std::numeric_limits<size_t>::max()), m_current_level(0)
+ {}
+
+ inline void operator()(internal_node const& n)
+ {
+ typedef typename rtree::elements_type<internal_node>::type elements_type;
+ elements_type const& elements = rtree::elements(n);
+
+ if (elements.empty())
+ {
+ result = false;
+ return;
+ }
+
+ size_t current_level_backup = m_current_level;
+ ++m_current_level;
+
+ for ( typename elements_type::const_iterator it = elements.begin();
+ it != elements.end() ; ++it)
+ {
+ rtree::apply_visitor(*this, *it->second);
+
+ if ( result == false )
+ return;
+ }
+
+ m_current_level = current_level_backup;
+ }
+
+ inline void operator()(leaf const& n)
+ {
+ typedef typename rtree::elements_type<leaf>::type elements_type;
+ elements_type const& elements = rtree::elements(n);
+
+ // empty leaf in non-root node
+ if (0 < m_current_level && elements.empty())
+ {
+ result = false;
+ return;
+ }
+
+ if ( m_leafs_level == std::numeric_limits<size_t>::max() )
+ {
+ m_leafs_level = m_current_level;
+ }
+ else if ( m_leafs_level != m_current_level )
+ {
+ result = false;
+ }
+ }
+
+ bool result;
+
+private:
+ Translator const& m_tr;
+ size_t m_leafs_level;
+ size_t m_current_level;
+};
+
+}}} // namespace detail::rtree::visitors
+
+template <typename Value, typename Translator, typename Tag>
+bool are_levels_ok(rtree<Value, Translator, Tag> const& tree)
+{
+ typedef rtree<Value, Translator, Tag> rt;
+ detail::rtree::visitors::are_levels_ok<
+ typename rt::value_type,
+ typename rt::translator_type,
+ typename rt::box_type,
+ typename rt::tag_type> v(tree.get_translator());
+
+ tree.apply_visitor(v);
+
+ return v.result;
+}
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_VISITORS_ARE_LEVELS_OK_HPP
Modified: sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/visitors/insert.hpp
==============================================================================
--- sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/visitors/insert.hpp (original)
+++ sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/visitors/insert.hpp 2011-06-09 19:55:58 EDT (Thu, 09 Jun 2011)
@@ -94,6 +94,7 @@
internal_node *parent,
size_t current_child_index,
node *& root,
+ size_t & leafs_level,
size_t min_elems,
size_t max_elems,
Translator const& tr)
@@ -111,7 +112,7 @@
assert(min_elems <= rtree::elements(n).size() && rtree::elements(n).size() <= max_elems);
assert(min_elems <= rtree::elements(n2).size() && rtree::elements(n2).size() <= max_elems);
- // node is not the root
+ // node is not the root - just add the new node
if ( parent != 0 )
{
// update old node's box
@@ -119,7 +120,7 @@
// add new node to the parent's children
rtree::elements(*parent).push_back(std::make_pair(box2, second_node));
}
- // node is the root
+ // node is the root - add level
else
{
assert(&n == rtree::get<Node>(root));
@@ -131,32 +132,11 @@
rtree::elements(rtree::get<internal_node>(*new_root)).push_back(std::make_pair(box2, second_node));
root = new_root;
+ ++leafs_level;
}
}
};
-// Default overflow treatment algorithm
-template <typename Value, typename Translator, typename Box, typename Tag>
-struct overflow_treatment
-{
- typedef typename rtree::node<Value, Box, Tag>::type node;
- typedef typename rtree::internal_node<Value, Box, Tag>::type internal_node;
- typedef typename rtree::leaf<Value, Box, Tag>::type leaf;
-
- template <typename Node>
- static inline void apply(
- Node & n,
- internal_node *parent,
- size_t current_child_index,
- node *& root,
- size_t min_elems,
- size_t max_elems,
- Translator const& tr)
- {
- split<Value, Translator, Box, Tag>::apply(n, parent, current_child_index, root, min_elems, max_elems, tr);
- }
-};
-
// Default insert visitor
template <typename Element, typename Value, typename Translator, typename Box, typename Tag>
class insert : public rtree::visitor<Value, Box, Tag, false>::type
@@ -167,22 +147,27 @@
typedef typename rtree::leaf<Value, Box, Tag>::type leaf;
inline insert(node* & root,
+ size_t & leafs_level,
Element const& element,
size_t min_elements,
size_t max_elements,
Translator const& t,
- size_t level = std::numeric_limits<size_t>::max()
+ size_t relative_level = 0
)
: m_element(element)
, m_tr(t)
, m_min_elems_per_node(min_elements)
, m_max_elems_per_node(max_elements)
- , m_level(level)
+ , m_relative_level(relative_level)
+ , m_level(leafs_level - relative_level)
, m_root_node(root)
+ , m_leafs_level(leafs_level)
, m_parent(0)
, m_current_child_index(0)
, m_current_level(0)
{
+ assert(m_relative_level <= leafs_level);
+ assert(m_level <= m_leafs_level);
// TODO
// assert - check if Box is correct
}
@@ -209,11 +194,16 @@
template <typename Node>
inline void post_traverse(Node &n)
{
+ // if node isn't a root check if parent and current_child_index isn't corrupted
+ assert(0 == m_parent || &n == rtree::get<Node>(rtree::elements(*m_parent)[m_current_child_index].second));
+
// handle overflow
if ( m_max_elems_per_node < rtree::elements(n).size() )
{
- detail::overflow_treatment<Value, Translator, Box, Tag>::
- apply(n, m_parent, m_current_child_index, m_root_node, m_min_elems_per_node, m_max_elems_per_node, m_tr);
+ split<Value, Translator, Box, Tag>::apply(
+ n, m_parent, m_current_child_index,
+ m_root_node, m_leafs_level,
+ m_min_elems_per_node, m_max_elems_per_node, m_tr);
}
}
@@ -243,9 +233,11 @@
Translator const& m_tr;
const size_t m_min_elems_per_node;
const size_t m_max_elems_per_node;
+ const size_t m_relative_level;
const size_t m_level;
node* & m_root_node;
+ size_t & m_leafs_level;
// traversing input parameters
internal_node *m_parent;
@@ -265,17 +257,20 @@
typedef typename base::leaf leaf;
inline insert(node* & root,
+ size_t & leafs_level,
Element const& element,
size_t min_elements,
size_t max_elements,
Translator const& tr,
- size_t level = std::numeric_limits<size_t>::max()
+ size_t relative_level = 0
)
- : base(root, element, min_elements, max_elements, tr, level)
+ : base(root, leafs_level, element, min_elements, max_elements, tr, relative_level)
{}
inline void operator()(internal_node & n)
{
+ assert(base::m_current_level < base::m_leafs_level);
+
if ( base::m_current_level < base::m_level )
{
// next traversing step
@@ -308,17 +303,19 @@
typedef typename base::leaf leaf;
inline insert(node* & root,
+ size_t & leafs_level,
Value const& v,
size_t min_elements,
size_t max_elements,
Translator const& t,
- size_t level = std::numeric_limits<size_t>::max()
+ size_t relative_level = 0
)
- : base(root, v, min_elements, max_elements, t, level)
+ : base(root, leafs_level, v, min_elements, max_elements, t, relative_level)
{}
inline void operator()(internal_node & n)
{
+ assert(base::m_current_level < base::m_leafs_level);
assert(base::m_current_level < base::m_level);
// next traversing step
@@ -329,6 +326,7 @@
inline void operator()(leaf & n)
{
+ assert(base::m_current_level == base::m_leafs_level);
assert( base::m_level == base::m_current_level ||
base::m_level == std::numeric_limits<size_t>::max() );
Modified: sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/visitors/remove.hpp
==============================================================================
--- sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/visitors/remove.hpp (original)
+++ sandbox-branches/geometry/index_080_new/boost/geometry/extensions/index/rtree/visitors/remove.hpp 2011-06-09 19:55:58 EDT (Thu, 09 Jun 2011)
@@ -29,12 +29,18 @@
typedef typename rtree::leaf<Value, Box, Tag>::type leaf;
public:
- inline explicit remove(node* & root, Value const& v, size_t min_elements, size_t max_elements, Translator const& t)
+ inline remove(node* & root,
+ size_t & leafs_level,
+ Value const& v,
+ size_t min_elements,
+ size_t max_elements,
+ Translator const& t)
: m_value(v)
, m_tr(t)
, m_min_elems_per_node(min_elements)
, m_max_elems_per_node(max_elements)
, m_root_node(root)
+ , m_leafs_level(leafs_level)
, m_is_value_removed(false)
, m_parent(0)
, m_current_child_index(0)
@@ -76,8 +82,8 @@
{
element_iterator underfl_el_it = elements.begin() + child_node_index;
- // move node to the container
- m_underflowed_nodes.push_back(std::make_pair(m_current_level + 1, underfl_el_it->second));
+ // move node to the container - store node's relative level as well
+ m_underflowed_nodes.push_back(std::make_pair(m_leafs_level - m_current_level, underfl_el_it->second));
elements.erase(underfl_el_it);
// calc underflow
@@ -87,8 +93,9 @@
// n is not root - adjust aabb
if ( 0 != m_parent )
{
- // test underflow state should be ok here
+ // underflow state should be ok here
// note that there may be less than min_elems elements in root
+ // so this condition should be checked only here
assert((elements.size() < m_min_elems_per_node) == m_is_underflow);
rtree::elements(*m_parent)[m_current_child_index].first
@@ -120,6 +127,7 @@
if ( rtree::elements(n).size() == 1 )
{
m_root_node = rtree::elements(n)[0].second;
+ --m_leafs_level;
}
}
}
@@ -178,7 +186,7 @@
}
template <typename Node>
- void reinsert_elements(Node &n, size_t level)
+ void reinsert_elements(Node &n, size_t node_relative_level)
{
typedef typename rtree::elements_type<Node>::type elements_type;
elements_type & elements = rtree::elements(n);
@@ -187,11 +195,12 @@
{
visitors::insert<typename elements_type::value_type, Value, Translator, Box, Tag> insert_v(
m_root_node,
+ m_leafs_level,
*it,
m_min_elems_per_node,
m_max_elems_per_node,
m_tr,
- level);
+ node_relative_level - 1);
rtree::apply_visitor(insert_v, *m_root_node);
}
@@ -203,6 +212,7 @@
const size_t m_max_elems_per_node;
node* & m_root_node;
+ size_t & m_leafs_level;
bool m_is_value_removed;
std::vector< std::pair<size_t, node*> > m_underflowed_nodes;
Modified: sandbox-branches/geometry/index_080_new/tests/additional_glut_vis.cpp
==============================================================================
--- sandbox-branches/geometry/index_080_new/tests/additional_glut_vis.cpp (original)
+++ sandbox-branches/geometry/index_080_new/tests/additional_glut_vis.cpp 2011-06-09 19:55:58 EDT (Thu, 09 Jun 2011)
@@ -9,16 +9,21 @@
#include <gl/glut.h>
+//#define BOOST_GEOMETRY_INDEX_USE_VARIANT_NODES
#include <boost/geometry/extensions/index/rtree/rtree.hpp>
#include <boost/geometry/extensions/index/rtree/visitors/gl_draw.hpp>
#include <boost/geometry/extensions/index/rtree/visitors/print.hpp>
#include <boost/geometry/extensions/index/rtree/visitors/are_boxes_ok.hpp>
+#include <boost/geometry/extensions/index/rtree/visitors/are_levels_ok.hpp>
typedef boost::geometry::model::point<float, 2, boost::geometry::cs::cartesian> P;
typedef boost::geometry::model::box<P> B;
//boost::geometry::index::rtree<B> t(2, 1);
-boost::geometry::index::rtree<B, boost::geometry::index::default_parameter, boost::geometry::index::quadratic_tag> t(4, 2);
+boost::geometry::index::rtree<
+ B,
+ boost::geometry::index::default_parameter,
+ boost::geometry::index::rstar_tag> t(4, 2);
std::vector<B> vect;
void render_scene(void)
@@ -61,13 +66,14 @@
boost::geometry::index::insert(t, b);
vect.push_back(b);
- /*std::cout << t << "\n\n";
+ std::cout << t << "\n\n";
std::cout << "inserted: ";
boost::geometry::index::detail::rtree::visitors::detail::print_indexable(std::cout, b);
std::cout << '\n';
- std::cout << ( boost::geometry::index::are_boxes_ok(t) ? "boxes OK" : "WRONG BOXES!" );
- std::cout << "\n\n\n";*/
+ std::cout << ( boost::geometry::index::are_boxes_ok(t) ? "boxes OK\n" : "WRONG BOXES!\n" );
+ std::cout << ( boost::geometry::index::are_levels_ok(t) ? "levels OK\n" : "WRONG LEVELS!\n" );
+ std::cout << "\n\n";
glutPostRedisplay();
}
@@ -82,12 +88,13 @@
boost::geometry::index::remove(t, b);
vect.erase(vect.begin() + i);
- /*std::cout << '\n' << t << "\n\n";
+ std::cout << '\n' << t << "\n\n";
std::cout << "removed: ";
boost::geometry::index::detail::rtree::visitors::detail::print_indexable(std::cout, b);
std::cout << '\n';
- std::cout << ( boost::geometry::index::are_boxes_ok(t) ? "boxes OK" : "WRONG BOXES!" );
- std::cout << "\n\n\n";*/
+ std::cout << ( boost::geometry::index::are_boxes_ok(t) ? "boxes OK\n" : "WRONG BOXES!\n" );
+ std::cout << ( boost::geometry::index::are_levels_ok(t) ? "levels OK\n" : "WRONG LEVELS!\n" );
+ std::cout << "\n\n";
glutPostRedisplay();
}
Modified: sandbox-branches/geometry/index_080_new/tests/additional_sizes_and_times.cpp
==============================================================================
--- sandbox-branches/geometry/index_080_new/tests/additional_sizes_and_times.cpp (original)
+++ sandbox-branches/geometry/index_080_new/tests/additional_sizes_and_times.cpp 2011-06-09 19:55:58 EDT (Thu, 09 Jun 2011)
@@ -11,6 +11,7 @@
#include <boost/geometry/extensions/index/rtree/rtree.hpp>
#include <boost/geometry/extensions/index/rtree/visitors/are_boxes_ok.hpp>
+#include <boost/geometry/extensions/index/rtree/visitors/are_levels_ok.hpp>
#include <iostream>
#include <fstream>
@@ -28,9 +29,9 @@
typedef bg::model::point<float, 2, bg::cs::cartesian> P;
typedef bg::model::box<P> B;
- typedef bgi::rtree<std::pair<B, size_t>, bgi::default_parameter, bgi::linear_tag> RT;
+ //typedef bgi::rtree<std::pair<B, size_t>, bgi::default_parameter, bgi::linear_tag> RT;
//typedef bgi::rtree<std::pair<B, size_t>, bgi::default_parameter, bgi::quadratic_tag> RT;
- //typedef bgi::rtree<std::pair<B, size_t>, bgi::default_parameter, bgi::rstar_tag> RT;
+ typedef bgi::rtree<std::pair<B, size_t>, bgi::default_parameter, bgi::rstar_tag> RT;
// load config file
std::ifstream file_cfg("config.txt");
@@ -89,7 +90,7 @@
else
{
boost::mt19937 rng;
- float max_val = values_count / 2;
+ float max_val = static_cast<float>(values_count / 2);
boost::uniform_real<float> range(-max_val, max_val);
boost::variate_generator<boost::mt19937&, boost::uniform_real<float> > rnd(rng, range);
@@ -114,6 +115,25 @@
float y = coords[i].second;
B b(P(x - 0.5f, y - 0.5f), P(x + 0.5f, y + 0.5f));
+ //if ( 341700 <= i )
+ // std::cout << i << "\n";
+
+ // Czy mozliwe, ze w czasie powtornego reinserta
+ // nagle drzewo sie powieksza o jeden poziom?
+ // Tak, drzewo sie rozrasta, powinno sie wstawiac w poziomie liczac od lisci
+ // TODO: relative_level zamiast level
+
+ // TODO: asserty w operator(leaf)
+ // current_level == leaf_level
+
+ // Swoja droga to dziwne ze przy drzewie 4,2
+ // dzieje sie to samo dopiero dla obiektow o indeksie 300k a nie wczesniej
+ // Dlaczego?
+ // Przy 32 obiektach powtornie wstawianych jest 9 a przy 4 tylko 1
+
+ // TODO: Zrobic kolejnego visitora sprawdzajacego czy odpowiednie wezly zostaly wstawione w dobrym miejscu
+ // Np sprawdzajacego czy wszystkie liscie sa na tym samym poziomie
+
t.insert(std::make_pair(b, i));
}
std::cout << "time: " << tim.elapsed() << "s\n";
@@ -124,6 +144,10 @@
std::cout << "BOXES OK\n";
else
std::cout << "WRONG BOXES\n";
+ if ( bgi::are_levels_ok(t) )
+ std::cout << "LEVELS OK\n";
+ else
+ std::cout << "WRONG LEVELS\n";
// searching test
{
@@ -157,11 +181,15 @@
std::cout << "time: " << tim.elapsed() << "s\n";
}
- // check
- if ( bgi::are_boxes_ok(t) )
- std::cout << "BOXES OK\n";
- else
- std::cout << "WRONG BOXES\n";
+ // check
+ if ( bgi::are_boxes_ok(t) )
+ std::cout << "BOXES OK\n";
+ else
+ std::cout << "WRONG BOXES\n";
+ if ( bgi::are_levels_ok(t) )
+ std::cout << "LEVELS OK\n";
+ else
+ std::cout << "WRONG LEVELS\n";
// searching test
{
@@ -184,7 +212,7 @@
{
std::cout << "inserting time test...\n";
tim.restart();
- for (size_t i = 0 ; i < values_count / 2 ; ++i )
+ for (size_t i = 0 ; i < remove_count ; ++i )
{
float x = coords[i].first;
float y = coords[i].second;
@@ -195,11 +223,15 @@
std::cout << "time: " << tim.elapsed() << "s\n";
}
- // test
- if ( bgi::are_boxes_ok(t) )
- std::cout << "BOXES OK\n";
- else
- std::cout << "WRONG BOXES\n";
+ // check
+ if ( bgi::are_boxes_ok(t) )
+ std::cout << "BOXES OK\n";
+ else
+ std::cout << "WRONG BOXES\n";
+ if ( bgi::are_levels_ok(t) )
+ std::cout << "LEVELS OK\n";
+ else
+ std::cout << "WRONG LEVELS\n";
// searching test
{
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