From d70a1756f92b2e39ee54e6dcc2d507baafe972e9 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Sat, 16 Jul 2011 22:00:42 +0000 Subject: [PATCH] node split algorithm separated from insert visitor, it's now tag-dispatchable. [SVN r73157] --- .../extensions/index/rtree/options.hpp | 22 ++-- .../index/rtree/visitors/insert.hpp | 118 +++++++++++------- 2 files changed, 84 insertions(+), 56 deletions(-) diff --git a/include/boost/geometry/extensions/index/rtree/options.hpp b/include/boost/geometry/extensions/index/rtree/options.hpp index 85cc4eb2d..45fddc2de 100644 --- a/include/boost/geometry/extensions/index/rtree/options.hpp +++ b/include/boost/geometry/extensions/index/rtree/options.hpp @@ -20,6 +20,9 @@ struct insert_reinsert_tag {}; struct choose_by_content_diff_tag {}; struct choose_by_overlap_diff_tag {}; +// SplitTag +struct split_default_tag {}; + // RedistributeTag struct linear_tag {}; struct quadratic_tag {}; @@ -75,12 +78,13 @@ struct rstar namespace options { -template +template struct rtree { typedef Parameters parameters_type; typedef InsertTag insert_tag; typedef ChooseNextNodeTag choose_next_node_tag; + typedef SplitTag split_tag; typedef RedistributeTag redistribute_tag; typedef NodeTag node_tag; }; @@ -95,19 +99,6 @@ struct options_type // TODO: awulkiew - use static assert }; -// default options -//template -//struct options_type< options::rtree > -//{ -// typedef options::rtree< -// Parameters, -// InsertTag, -// ChooseNextNodeTag, -// RedistributeTag, -// NodeTag -// > type; -//}; - template struct options_type< linear > { @@ -115,6 +106,7 @@ struct options_type< linear > linear, insert_default_tag, choose_by_content_diff_tag, + split_default_tag, linear_tag, node_default_static_tag > type; @@ -127,6 +119,7 @@ struct options_type< quadratic > quadratic, insert_default_tag, choose_by_content_diff_tag, + split_default_tag, quadratic_tag, node_default_static_tag > type; @@ -139,6 +132,7 @@ struct options_type< rstar, insert_reinsert_tag, choose_by_overlap_diff_tag, + split_default_tag, rstar_tag, node_default_static_tag > type; diff --git a/include/boost/geometry/extensions/index/rtree/visitors/insert.hpp b/include/boost/geometry/extensions/index/rtree/visitors/insert.hpp index cf2832809..0521ff1c6 100644 --- a/include/boost/geometry/extensions/index/rtree/visitors/insert.hpp +++ b/include/boost/geometry/extensions/index/rtree/visitors/insert.hpp @@ -77,10 +77,82 @@ struct choose_next_node } }; +// ----------------------------------------------------------------------- // + // Not implemented here template struct redistribute_elements; +// ----------------------------------------------------------------------- // + +// Split algorithm +template +class split; + +// Default split algorithm +template +class split +{ +protected: + typedef typename rtree::node::type node; + typedef typename rtree::internal_node::type internal_node; + typedef typename rtree::leaf::type leaf; + + typedef typename Options::parameters_type parameters_type; + +public: + template + static inline void apply(node* & root_node, + size_t & leafs_level, + Node & n, + internal_node *parent_node, + size_t current_child_index, + Translator const& tr) + { + // create additional node + node * second_node = rtree::create_node(Node()); + Node & n2 = rtree::get(*second_node); + + // redistribute elements + Box box1, box2; + redistribute_elements:: + apply(n, n2, box1, box2, tr); + + // check numbers of elements + BOOST_GEOMETRY_INDEX_ASSERT(parameters_type::min_elements <= rtree::elements(n).size() && + rtree::elements(n).size() <= parameters_type::max_elements, + "unexpected number of elements"); + BOOST_GEOMETRY_INDEX_ASSERT(parameters_type::min_elements <= rtree::elements(n2).size() && + rtree::elements(n2).size() <= parameters_type::max_elements, + "unexpected number of elements"); + + // node is not the root - just add the new node + if ( parent_node != 0 ) + { + // update old node's box + rtree::elements(*parent_node)[current_child_index].first = box1; + // add new node to the parent's children + rtree::elements(*parent_node).push_back(std::make_pair(box2, second_node)); + } + // node is the root - add level + else + { + BOOST_GEOMETRY_INDEX_ASSERT(&n == rtree::get(root_node), "node should be the root"); + + // create new root and add nodes + node * new_root = rtree::create_node(internal_node()); + + rtree::elements(rtree::get(*new_root)).push_back(std::make_pair(box1, root_node)); + rtree::elements(rtree::get(*new_root)).push_back(std::make_pair(box2, second_node)); + + root_node = new_root; + ++leafs_level; + } + } +}; + +// ----------------------------------------------------------------------- // + // Default insert visitor template class insert @@ -169,52 +241,14 @@ protected: m_current_level = current_level_bckup; } - // TODO: awulkiew - implement dispatchable split::apply to enable additional nodes creation - template - inline void split(Node &n) const + inline void split(Node & n) const { - // create additional node - node * second_node = rtree::create_node(Node()); - Node & n2 = rtree::get(*second_node); - - // redistribute elements - Box box1, box2; - redistribute_elements:: - apply(n, n2, box1, box2, m_tr); - - // check numbers of elements - BOOST_GEOMETRY_INDEX_ASSERT(parameters_type::min_elements <= rtree::elements(n).size() && - rtree::elements(n).size() <= parameters_type::max_elements, - "unexpected number of elements"); - BOOST_GEOMETRY_INDEX_ASSERT(parameters_type::min_elements <= rtree::elements(n2).size() && - rtree::elements(n2).size() <= parameters_type::max_elements, - "unexpected number of elements"); - - // node is not the root - just add the new node - if ( m_parent != 0 ) - { - // update old node's box - rtree::elements(*m_parent)[m_current_child_index].first = box1; - // add new node to the parent's children - rtree::elements(*m_parent).push_back(std::make_pair(box2, second_node)); - } - // node is the root - add level - else - { - BOOST_GEOMETRY_INDEX_ASSERT(&n == rtree::get(m_root_node), "node should be the root"); - - // create new root and add nodes - node * new_root = rtree::create_node(internal_node()); - - rtree::elements(rtree::get(*new_root)).push_back(std::make_pair(box1, m_root_node)); - rtree::elements(rtree::get(*new_root)).push_back(std::make_pair(box2, second_node)); - - m_root_node = new_root; - ++m_leafs_level; - } + detail::split::apply(m_root_node, m_leafs_level, n, m_parent, m_current_child_index, m_tr); } + // TODO: awulkiew - implement dispatchable split::apply to enable additional nodes creation + Element const& m_element; Translator const& m_tr; const size_t m_relative_level;