From e05afa847ea173bd62c21553690c39f13878d753 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Sun, 27 Mar 2011 02:21:45 +0000 Subject: [PATCH] other version of split algorithm + a lot of minor changes [SVN r70607] --- .../index/rtree/rstar/choose_next_node.hpp | 186 +++++ .../index/rtree/rstar/rtree_insert.hpp | 645 +----------------- .../extensions/index/rtree/rstar/split.hpp | 338 +++++++++ .../geometry/extensions/index/rtree/rtree.hpp | 15 +- .../extensions/index/rtree/rtree_node.hpp | 18 + .../index/rtree/visitors/gl_draw.hpp | 30 +- .../extensions/index/rtree/visitors/print.hpp | 29 +- .../rtree/visitors/rtree_are_boxes_ok.hpp | 103 +++ tests/additional_glut_vis.cpp | 27 +- tests/additional_sizes_and_times.cpp | 8 +- tests/main.cpp | 13 + tests/rtree_native.hpp | 19 +- 12 files changed, 744 insertions(+), 687 deletions(-) create mode 100644 include/boost/geometry/extensions/index/rtree/rstar/choose_next_node.hpp create mode 100644 include/boost/geometry/extensions/index/rtree/rstar/split.hpp create mode 100644 include/boost/geometry/extensions/index/rtree/visitors/rtree_are_boxes_ok.hpp diff --git a/include/boost/geometry/extensions/index/rtree/rstar/choose_next_node.hpp b/include/boost/geometry/extensions/index/rtree/rstar/choose_next_node.hpp new file mode 100644 index 000000000..20b88e08f --- /dev/null +++ b/include/boost/geometry/extensions/index/rtree/rstar/choose_next_node.hpp @@ -0,0 +1,186 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Boost.Index - R*-tree ChooseNextNode algorithm +// +// 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_CHOOSE_NEXT_NODE_HPP +#define BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_RSTAR_CHOOSE_NEXT_NODE_HPP + +#include + +#include +#include +#include + +#include +#include + +namespace boost { namespace geometry { namespace index { + +namespace visitors { + +struct rtree_rstar_chnn_min_overlap_cost {}; +struct rtree_rstar_chnn_nearly_min_overlap_cost {}; + +// TODO: awulkiew - it's possible that goodness values may be used to choose next node +// on this step some of the goodness values would be calculated (not all) +// and only for some nodes (goodness values should be calculated only if there is an overflow) + +template +class rtree_rstar_choose_next_node +{}; + +// TODO: awulkiew finish this version +// use min_element instead of searching by myself + +//template +//class rtree_rstar_choose_next_node +//{ +// typedef typename index::detail::rtree_node::type node; +// typedef typename index::detail::rtree_internal_node::type internal_node; +// typedef typename index::detail::rtree_leaf::type leaf; +// +// typedef typename internal_node::children_type children_type; +// +//public: +// template +// static inline size_t apply(internal_node & n, Indexable const& indexable) +// { +// assert(!n.children.empty()); +// +// bool has_leaves = boost::apply_visitor( +// visitors::rtree_is_leaf(), +// *n.children.front().second); +// +// if ( !has_leaves ) +// return impl(n, indexable); +// else +// return impl(n, indexable); +// } +// +//private: +// template +// static inline size_t impl(internal_node & n, Indexable const& indexable) +// { +// } +// +//}; + +// TODO: awulkiew - wrong algorithm? Should branch check be applied to Leafs? +// TODO: awulkiew - further optimization: don't calculate area with the overlap, calculate it only if +// overlap < smallest_overlap (and current area must be stored) OR +// overlap == smallest_overlap (and area must be compared) + +template +class rtree_rstar_choose_next_node +{ + typedef typename index::detail::rtree_node::type node; + typedef typename index::detail::rtree_internal_node::type internal_node; + typedef typename index::detail::rtree_leaf::type leaf; + + typedef typename internal_node::children_type children_type; + +public: + template + static inline size_t apply(internal_node & n, Indexable const& indexable) + { + assert(!n.children.empty()); + + bool has_leaves = boost::apply_visitor( + visitors::rtree_is_leaf(), + *n.children.front().second); + + if ( !has_leaves ) + return impl(n, indexable); + else + return impl(n, indexable); + } + +private: + template + static inline size_t impl(internal_node & n, Indexable const& indexable) + { + typedef typename children_type::iterator children_iterator; + + //assert(!n.children.empty()); + + children_iterator temp_it = n.children.begin(); + children_iterator child_it = temp_it; + Areas min_areas(n.children, child_it, indexable); + + for (children_iterator it = ++temp_it; + it != n.children.end(); ++it) + { + Areas areas(n.children, it, indexable); + + if ( areas < min_areas ) + { + child_it = it; + min_areas = areas; + } + } + + // TODO: awulkiew - switch to indexes in the whole class? + return child_it - n.children.begin(); + } + + struct branch_areas + { + typedef typename area_result::type area_type; + + template + inline branch_areas(children_type const& ch, typename children_type::iterator const& k_it, Indexable const& indexable) + { + overlap_area = 0; + for (typename children_type::const_iterator it = ch.begin(); it != ch.end(); ++it) + if ( it != k_it ) + overlap_area += index::overlap(k_it->first, it->first); + + area = index::area(k_it->first); + + diff_area = index::union_area(k_it->first, indexable) - area; + } + + inline bool operator<(branch_areas &a) const + { + return overlap_area < a.overlap_area || + ( overlap_area == a.overlap_area && diff_area < a.diff_area ) || + ( diff_area == a.diff_area && area < a.area ); + } + + area_type overlap_area; + area_type diff_area; + area_type area; + }; + + struct internal_node_areas + { + typedef typename area_result::type area_type; + + template + inline internal_node_areas(children_type const&, typename children_type::iterator const& k_it, Indexable const& indexable) + { + area = index::area(k_it->first); + diff_area = index::union_area(k_it->first, indexable) - area; + } + + inline bool operator<(internal_node_areas &a) const + { + return diff_area < a.diff_area || + ( diff_area == a.diff_area && area < a.area ); + } + + area_type diff_area; + area_type area; + }; +}; + +} // namespace visitors + +}}} // namespace boost::geometry::index + +#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_RSTAR_CHOOSE_NEXT_NODE_HPP diff --git a/include/boost/geometry/extensions/index/rtree/rstar/rtree_insert.hpp b/include/boost/geometry/extensions/index/rtree/rstar/rtree_insert.hpp index e4aa929ab..3e317a3f4 100644 --- a/include/boost/geometry/extensions/index/rtree/rstar/rtree_insert.hpp +++ b/include/boost/geometry/extensions/index/rtree/rstar/rtree_insert.hpp @@ -23,578 +23,13 @@ #include #include +#include +#include + namespace boost { namespace geometry { namespace index { namespace visitors { -// ----------------------------------------------------------------------------- // -// rstar/choose_next_node -// ----------------------------------------------------------------------------- // - -// TODO: awulkiew - it's possible that goodness values may be used to choose next node - -// rtree choose_next_node algorithm for rstar variant - -template -class rtree_rstar_choose_next_node -{ - typedef typename index::detail::rtree_node::type node; - typedef typename index::detail::rtree_internal_node::type internal_node; - typedef typename index::detail::rtree_leaf::type leaf; - - typedef typename internal_node::children_type children_type; - -public: - // TODO: awulkiew - alternative lower-cost version of overlap calculation may be used (branch_areas) - // TODO: awulkiew - further optimization: don't calculate area with the overlap, calculate it only if - // overlap < smallest_overlap (and current area must be stored) OR - // overlap == smallest_overlap (and area must be compared) - template - static inline size_t apply(internal_node & n, Indexable const& indexable) - { - assert(!n.children.empty()); - - bool has_leaves = boost::apply_visitor( - visitors::rtree_is_leaf(), - *n.children.front().second); - - if ( !has_leaves ) - return impl(n, indexable); - else - return impl(n, indexable); - } - -private: - template - static inline size_t impl(internal_node & n, Indexable const& indexable) - { - typedef typename children_type::iterator children_iterator; - - //assert(!n.children.empty()); - - children_iterator temp_it = n.children.begin(); - children_iterator child_it = temp_it; - Areas min_areas(n.children, child_it, indexable); - - for (children_iterator it = ++temp_it; - it != n.children.end(); ++it) - { - Areas areas(n.children, it, indexable); - - if ( areas < min_areas ) - { - child_it = it; - min_areas = areas; - } - } - - // TODO: awulkiew - switch to indexes in the whole class? - return child_it - n.children.begin(); - } - - struct branch_areas - { - typedef typename area_result::type area_type; - - template - inline branch_areas(children_type const& ch, typename children_type::iterator const& k_it, Indexable const& indexable) - { - overlap_area = 0; - for (typename children_type::const_iterator it = ch.begin(); it != ch.end(); ++it) - if ( it != k_it ) - overlap_area += index::overlap(k_it->first, it->first); - - area = index::area(k_it->first); - - diff_area = index::union_area(k_it->first, indexable) - area; - } - - inline bool operator<(branch_areas &a) const - { - return overlap_area < a.overlap_area || - ( overlap_area == a.overlap_area && diff_area < a.diff_area ) || - ( diff_area == a.diff_area && area < a.area ); - } - - area_type overlap_area; - area_type diff_area; - area_type area; - }; - - struct internal_node_areas - { - typedef typename area_result::type area_type; - - template - inline internal_node_areas(children_type const&, typename children_type::iterator const& k_it, Indexable const& indexable) - { - area = index::area(k_it->first); - diff_area = index::union_area(k_it->first, indexable) - area; - } - - inline bool operator<(internal_node_areas &a) const - { - return diff_area < a.diff_area || - ( diff_area == a.diff_area && area < a.area ); - } - - area_type diff_area; - area_type area; - }; -}; - -// ----------------------------------------------------------------------------- // -// rstar/sorts -// ----------------------------------------------------------------------------- // - -// elements ids less comparator - -template -class rtree_rstar_elements_indexes_less -{ -public: - rtree_rstar_elements_indexes_less(Elements const& elements, Translator const& tr) - : m_elements(elements), m_tr(tr) - {} - - bool operator()(size_t e1_index, size_t e2_index) - { - return - index::detail::get( - index::detail::rtree_element_indexable(m_elements[e1_index], m_tr) - ) - < - index::detail::get( - index::detail::rtree_element_indexable(m_elements[e2_index], m_tr) - ); - } - -private: - Elements const& m_elements; - Translator const& m_tr; -}; - -template -class rtree_rstar_vectors -{ -public: - inline rtree_rstar_vectors(size_t count) - : m_count(count), m_ids(Dimension * 2 * count) - {} - - template - inline typename std::vector::iterator begin() - { - BOOST_STATIC_ASSERT(AxisIndex < Dimension); - BOOST_STATIC_ASSERT(Corner < 2); - return m_ids.begin() + ( AxisIndex * 2 + Corner ) * m_count; - } - - template - inline typename std::vector::iterator end() - { - BOOST_STATIC_ASSERT(AxisIndex < Dimension); - BOOST_STATIC_ASSERT(Corner < 2); - return m_ids.begin() + ( AxisIndex * 2 + Corner + 1) * m_count; - } - - template - inline T const& get(size_t index) const - { - BOOST_STATIC_ASSERT(AxisIndex < Dimension); - BOOST_STATIC_ASSERT(Corner < 2); - assert(index < m_count); - return m_ids[( AxisIndex * 2 + Corner ) * m_count + index]; - } - - template - inline void set(size_t index, T const& v) - { - BOOST_STATIC_ASSERT(AxisIndex < Dimension); - BOOST_STATIC_ASSERT(Corner < 2); - assert(index < m_count); - m_ids[( AxisIndex * 2 + Corner ) * m_count + index] = v; - } - - inline T const& get(size_t axis, size_t corner, size_t index) const - { - assert(axis < Dimension); - assert(corner < 2); - assert(index < m_count); - return m_ids[( axis * 2 + corner ) * m_count + index]; - } - - inline size_t vector_size() const - { - return m_count; - } - -private: - size_t m_count; - std::vector m_ids; -}; - -// init indexes of elements and sort them - -template -class rtree_rstar_sorts_fill_ids -{ - BOOST_STATIC_ASSERT(0 < Dimension); - -public: - template - static inline void apply(rtree_rstar_vectors & ids, Elements const& elements, Translator const& tr) - { - rtree_rstar_sorts_fill_ids::apply(ids, elements, tr); - - fill(ids, elements, tr); - fill(ids, elements, tr); - } - -private: - template - static inline void fill(rtree_rstar_vectors & ids, Elements const& elements, Translator const& tr) - { - for ( size_t i = 0 ; i < elements.size() ; ++i ) - ids.set(i, i); - - rtree_rstar_elements_indexes_less less(elements, tr); - std::sort(ids.begin(), ids.end(), less); - } -}; - -template -class rtree_rstar_sorts_fill_ids -{ -public: - template - static inline void apply(rtree_rstar_vectors & ids, Elements const& elements, Translator const& tr) - { - fill(ids, elements, tr); - fill(ids, elements, tr); - } - -private: - template - static inline void fill(rtree_rstar_vectors & ids, Elements const& elements, Translator const& tr) - { - for ( size_t i = 0 ; i < elements.size() ; ++i ) - ids.set<0, Corner>(i, i); - - rtree_rstar_elements_indexes_less less(elements, tr); - std::sort(ids.begin<0, Corner>(), ids.end<0, Corner>(), less); - } -}; - -// sorts for each axis for min and max - -template -class rtree_rstar_sorts -{ -public: - inline rtree_rstar_sorts(Elements const& elements, Translator const& tr) - : m_elems(elements), m_tr(tr), m_ids(m_elems.size()) - { - rtree_rstar_sorts_fill_ids::apply(m_ids, elements, tr); - } - - // TODO: awulkiew - should those methods be here? Just leave get_element? - - template - inline typename index::detail::rtree_element_indexable_type::type const& - get_indexable(size_t index) const - { - size_t id = m_ids.get(index); - return index::detail::rtree_element_indexable(m_elems[id], m_tr); - } - - inline typename index::detail::rtree_element_indexable_type::type const& - get_indexable(size_t axis, size_t corner, size_t index) const - { - size_t id = m_ids.get(axis, corner, index); - return index::detail::rtree_element_indexable(m_elems[id], m_tr); - } - - template - inline typename Elements::value_type const& get_element(size_t index) const - { - size_t id = m_ids.get(index); - return m_elems[id]; - } - - inline typename Elements::value_type const& get_element(size_t axis, size_t corner, size_t index) const - { - size_t id = m_ids.get(axis, corner, index); - return m_elems[id]; - } - - inline size_t sort_size() const - { - return m_ids.vector_size(); - } - -private: - Elements const& m_elems; - Translator const& m_tr; - - rtree_rstar_vectors m_ids; -}; - -// ----------------------------------------------------------------------------- // -// rstar/goodness_values -// ----------------------------------------------------------------------------- // - -// calculate margins, areas and overlaps - -template -class rtree_rstar_calculate_goodness_values_for_axis -{ - typedef typename geometry::traits::coordinate_type< - typename geometry::traits::point_type::type - >::type coordinate_type; - - static const size_t dimension = geometry::traits::dimension< - typename geometry::traits::point_type::type - >::value; - - typedef typename area_result::type area_type; - typedef typename margin_result::type margin_type; - typedef typename overlap_result::type overlap_type; - typedef boost::tuple goodness_type; - -public: - template - static inline void apply( - rtree_rstar_vectors & goodness_vectors, - rtree_rstar_sorts const& sorts, - size_t min_elems, - size_t max_elems) - { - assert(sorts.sort_size() == max_elems + 1); - assert(goodness_vectors.vector_size() == max_elems - 2 * min_elems + 2); - - size_t median_index_last = max_elems - min_elems + 2; - size_t i = 0; - for ( size_t median_index = min_elems ; median_index < median_index_last ; ++median_index, ++i ) - { - Box left_box = calculate_box(sorts, 0, median_index); - Box right_box = calculate_box(sorts, median_index, sorts.sort_size()); - - margin_type margin = index::margin(left_box) + index::margin(right_box); - area_type area = index::area(left_box) + index::area(right_box); - overlap_type overlap = index::overlap(left_box, right_box); - - goodness_vectors.set( - i, - boost::make_tuple(left_box, right_box, margin, overlap, area)); - } - } -private: - template - static inline Box calculate_box( - rtree_rstar_sorts const& sorts, - size_t index_first, - size_t index_last) - { - assert(index_first < index_last); - - Box result; - geometry::convert(sorts.template get_indexable(index_first), result); - ++index_first; - for ( ; index_first < index_last ; ++index_first ) - geometry::expand(result, sorts.template get_indexable(index_first)); - return result; - } -}; - -// calculate goodness values for all axis - -template -struct rtree_rstar_calculate_goodness_values -{ - BOOST_STATIC_ASSERT(0 < Dimension); - - typedef typename area_result::type area_type; - typedef typename margin_result::type margin_type; - typedef typename overlap_result::type overlap_type; - typedef boost::tuple goodness_type; - - template - static inline void apply( - rtree_rstar_vectors & goodness_vectors, - rtree_rstar_sorts const& sorts, - size_t min_elems, - size_t max_elems) - { - rtree_rstar_calculate_goodness_values - ::apply(goodness_vectors, sorts, min_elems, max_elems); - - rtree_rstar_calculate_goodness_values_for_axis - ::apply(goodness_vectors, sorts, min_elems, max_elems); - rtree_rstar_calculate_goodness_values_for_axis - ::apply(goodness_vectors, sorts, min_elems, max_elems); - } -}; - -template -struct rtree_rstar_calculate_goodness_values -{ - typedef typename area_result::type area_type; - typedef typename margin_result::type margin_type; - typedef typename overlap_result::type overlap_type; - typedef boost::tuple goodness_type; - - template - static inline void apply( - rtree_rstar_vectors & goodness_vectors, - rtree_rstar_sorts const& sorts, - size_t min_elems, - size_t max_elems) - { - rtree_rstar_calculate_goodness_values_for_axis - ::apply(goodness_vectors, sorts, min_elems, max_elems); - rtree_rstar_calculate_goodness_values_for_axis - ::apply(goodness_vectors, sorts, min_elems, max_elems); - } -}; - -// goodness values - -template -class rtree_rstar_goodness_values -{ - typedef typename geometry::traits::coordinate_type< - typename geometry::traits::point_type::type - >::type coordinate_type; - - static const size_t dimension = geometry::traits::dimension< - typename geometry::traits::point_type::type - >::value; - - typedef typename area_result::type area_type; - typedef typename margin_result::type margin_type; - typedef typename overlap_result::type overlap_type; - typedef boost::tuple goodness_type; - -public: - inline rtree_rstar_goodness_values( - Elements const& elements, - Translator const& tr, - size_t min_elems, - size_t max_elems) - : m_sorts(elements, tr) - , m_goodness_vectors(max_elems - 2 * min_elems + 2) - { - rtree_rstar_calculate_goodness_values::apply( - m_goodness_vectors, m_sorts, min_elems, max_elems); - } - - inline size_t elements_size() const - { - return m_sorts.sort_size(); - } - - inline size_t goodnesses_size() const - { - return m_goodness_vectors.vector_size(); - } - - inline goodness_type const& get_goodness(size_t axis, size_t corner, size_t index) const - { - return m_goodness_vectors.get(axis, corner, index); - } - - inline typename Elements::value_type const& get_element(size_t axis, size_t corner, size_t index) const - { - return m_sorts.get_element(axis, corner, index); - } - -private: - rtree_rstar_sorts m_sorts; - rtree_rstar_vectors m_goodness_vectors; -}; - -template -class rtree_rstar_choose_split_axis -{ - typedef typename margin_result::type margin_type; -public: - static inline std::pair apply(rtree_rstar_goodness_values const& gv) - { - std::pair smallest_distr = std::make_pair(0, 0); - margin_type smallest_margins_sum = calculate_margins_sum(0, 0, gv); - - margin_type margins_sum = calculate_margins_sum(0, 1, gv); - if ( margins_sum < smallest_margins_sum ) - { - smallest_distr.second = 1; - smallest_margins_sum = margins_sum; - } - - for ( size_t a = 1 ; a < traits::dimension::value ; ++a ) - { - for ( size_t c = 0 ; c < 2 ; ++c ) - { - margins_sum = calculate_margins_sum(a, c, gv); - if ( margins_sum < smallest_margins_sum ) - { - smallest_distr.first = a; - smallest_distr.second = c; - smallest_margins_sum = margins_sum; - } - } - } - return smallest_distr; - } -private: - static inline typename margin_result::type - calculate_margins_sum(size_t axis, size_t corner, rtree_rstar_goodness_values const& gv) - { - typename margin_result::type margins_sum = 0; - for ( size_t i = 0 ; i < gv.goodnesses_size() ; ++i ) - margins_sum += boost::get<2>(gv.get_goodness(axis, corner, i)); - return margins_sum; - } -}; - -template -class rtree_rstar_choose_split_index -{ - typedef typename area_result::type area_type; - typedef typename overlap_result::type overlap_type; -public: - static inline size_t apply(rtree_rstar_goodness_values const& gv, size_t axis, size_t corner) - { - size_t smallest_index = 0; - overlap_type smallest_overlap = boost::get<3>(gv.get_goodness(axis, corner, 0)); - overlap_type smallest_area = boost::get<4>(gv.get_goodness(axis, corner, 0)); - - for ( size_t i = 1 ; i < gv.goodnesses_size() ; ++i ) - { - overlap_type overlap = boost::get<3>(gv.get_goodness(axis, corner, i)); - if ( overlap < smallest_overlap ) - { - smallest_overlap = overlap; - smallest_area = boost::get<4>(gv.get_goodness(axis, corner, i)); - smallest_index = i; - } - else if ( overlap == smallest_overlap ) - { - area_type area = boost::get<4>(gv.get_goodness(axis, corner, i)); - if ( area < smallest_area ) - { - smallest_area = area; - smallest_index = i; - } - } - } - - return smallest_index; - } -}; - -// rtree insert routine for rstar variant - template class rtree_insert : public boost::static_visitor<> { @@ -617,7 +52,9 @@ public: size_t current_child_index_bckup = m_current_child_index; // choose next node, where value insert traversing should go - m_current_child_index = rtree_rstar_choose_next_node::apply(n, m_tr(m_value)); + m_current_child_index = + rtree_rstar_choose_next_node:: + apply(n, m_tr(m_value)); // TODO: awulkiew - if reinsert is implemented this must be changed geometry::expand(n.children[m_current_child_index].first, m_tr(m_value)); @@ -631,7 +68,8 @@ public: if ( m_max_elems_per_node < n.children.size() ) { - split(n); + rtree_rstar_split:: + apply(n, m_parent, m_current_child_index, m_root_node, m_min_elems_per_node, m_max_elems_per_node, m_tr); } } @@ -641,75 +79,12 @@ public: if ( m_max_elems_per_node < n.values.size() ) { - split(n); + rtree_rstar_split:: + apply(n, m_parent, m_current_child_index, m_root_node, m_min_elems_per_node, m_max_elems_per_node, m_tr); } } private: - template - inline void split(Node & n) - { - typedef typename index::detail::rtree_elements_type::type elements_type; - typedef typename elements_type::value_type element_type; - - elements_type & elems = index::detail::get_elements(n); - - rtree_rstar_goodness_values gv(elems, m_tr, m_min_elems_per_node, m_max_elems_per_node); - - std::pair axis_and_corner = - rtree_rstar_choose_split_axis::apply(gv); - size_t axis = axis_and_corner.first; - size_t corner = axis_and_corner.second; - - size_t choosen_index = - rtree_rstar_choose_split_index::apply(gv, axis, corner); - - size_t median_index = m_min_elems_per_node + choosen_index; - assert(median_index <= m_max_elems_per_node + 1 - m_min_elems_per_node); - - // create new node - node * right_node = rtree_create_node(Node()); - elements_type & new_elems = index::detail::get_elements(boost::get(*right_node)); - - // update new node's elements - new_elems.reserve(m_max_elems_per_node + 1 - median_index); - for ( size_t i = median_index ; i < m_max_elems_per_node + 1 ; ++i) - new_elems.push_back(gv.get_element(axis, corner, i)); - - // fill temporary container with left node's elements - elements_type left_elems; - left_elems.reserve(median_index); - for ( size_t i = 0 ; i < median_index ; ++i ) - left_elems.push_back(gv.get_element(axis, corner, i)); - // update old node's elements - elems = left_elems; - - if ( m_parent != 0 ) - { - // update old node's box - m_parent->children[m_current_child_index].first = boost::get<0>(gv.get_goodness(axis, corner, choosen_index)); - // add new node to the parent's children - m_parent->children.push_back( std::make_pair( - boost::get<1>(gv.get_goodness(axis, corner, choosen_index)), right_node ) ); - } - else - { - assert(&n == boost::get(m_root_node)); - - // create new root and add nodes - node * new_root = rtree_create_node(internal_node()); - - boost::get(*new_root).children.push_back( - std::make_pair(boost::get<0>(gv.get_goodness(axis, corner, choosen_index)), m_root_node) - ); - boost::get(*new_root).children.push_back( - std::make_pair(boost::get<1>(gv.get_goodness(axis, corner, choosen_index)), right_node) - ); - - m_root_node = new_root; - } - } - Value const& m_value; Translator const& m_tr; size_t m_min_elems_per_node; diff --git a/include/boost/geometry/extensions/index/rtree/rstar/split.hpp b/include/boost/geometry/extensions/index/rtree/rstar/split.hpp new file mode 100644 index 000000000..e6d0fe3d9 --- /dev/null +++ b/include/boost/geometry/extensions/index/rtree/rstar/split.hpp @@ -0,0 +1,338 @@ +// 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 + +#include + +#include +#include +#include +#include + +#include +#include +#include + +namespace boost { namespace geometry { namespace index { + +namespace visitors { + +// elements less + +template +class rtree_rstar_elements_less +{ + typedef typename Elements::value_type element_type; +public: + inline rtree_rstar_elements_less(Translator const& tr) + : m_tr(tr) + {} + + inline bool operator()(element_type const& e1, element_type const e2) const + { + return + index::detail::get( + index::detail::rtree_element_indexable(e1, m_tr) + ) + < + index::detail::get( + index::detail::rtree_element_indexable(e2, m_tr) + ); + } + +private: + Translator const& m_tr; +}; + +// rstar split axis data + +template +struct rtree_rstar_split_axis_data +{ + typedef typename margin_result::type margin_type; + typedef typename overlap_result::type overlap_type; + typedef typename area_result::type area_type; + + inline rtree_rstar_split_axis_data() + : margins_sum(0) + , smallest_overlap(std::numeric_limits::max()) + , smallest_area(std::numeric_limits::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 +class rtree_rstar_split_update_axis_data_for_corner +{ + typedef typename rtree_rstar_split_axis_data::margin_type margin_type; + typedef typename rtree_rstar_split_axis_data::overlap_type overlap_type; + typedef typename rtree_rstar_split_axis_data::area_type area_type; + + BOOST_STATIC_ASSERT(Corner < 2); + +public: + template + static inline void apply( + rtree_rstar_split_axis_data & split_axis_data, + 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 = index::detail::elements_box(sorted_elements.begin(), sorted_elements.begin() + median_index, tr); + Box right_box = index::detail::elements_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); + + split_axis_data.update(Corner, median_index, left_box, right_box, margin, overlap, area); + } + } +}; + +// split data + +template +struct rtree_rstar_split_data +{ + typedef typename margin_result::type margin_type; + typedef typename overlap_result::type overlap_type; + typedef typename area_result::type area_type; + + inline rtree_rstar_split_data() + : smallest_margins_sum(std::numeric_limits::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 +class rtree_rstar_split_update_data_for_axis_and_corner +{ + typedef typename rtree_rstar_split_axis_data::margin_type margin_type; + typedef typename rtree_rstar_split_axis_data::overlap_type overlap_type; + typedef typename rtree_rstar_split_axis_data::area_type area_type; + +public: + template + static inline void apply( + rtree_rstar_split_data & split_data, + Elements & elements, + size_t min_elems, + size_t max_elems, + Translator const& tr) + { + rtree_rstar_split_axis_data split_axis_data; + + rtree_rstar_elements_less less_min(tr); + std::sort(elements.begin(), elements.end(), less_min); + + rtree_rstar_split_update_axis_data_for_corner:: + apply(split_axis_data, elements, min_elems, max_elems, tr); + + split_data.update( + AxisIndex, + split_axis_data.choosen_corner, + split_axis_data.choosen_median_index, + split_axis_data.choosen_left_box, + split_axis_data.choosen_right_box, + split_axis_data.margins_sum, + elements); + } +}; + +// for each dimension and corner update split data + +template +struct rtree_rstar_split_update_data +{ + BOOST_STATIC_ASSERT(0 < Dimension); + + template + static inline void apply( + rtree_rstar_split_data & split_data, + Elements & elements, + size_t min_elems, + size_t max_elems, + Translator const& tr) + { + rtree_rstar_split_update_data:: + apply(split_data, elements, min_elems, max_elems, tr); + + rtree_rstar_split_update_data_for_axis_and_corner:: + apply(split_data, elements, min_elems, max_elems, tr); + rtree_rstar_split_update_data_for_axis_and_corner:: + apply(split_data, elements, min_elems, max_elems, tr); + } +}; + +template +struct rtree_rstar_split_update_data +{ + template + static inline void apply( + rtree_rstar_split_data & split_data, + Elements & elements, + size_t min_elems, + size_t max_elems, + Translator const& tr) + { + rtree_rstar_split_update_data_for_axis_and_corner:: + apply(split_data, elements, min_elems, max_elems, tr); + rtree_rstar_split_update_data_for_axis_and_corner:: + apply(split_data, elements, min_elems, max_elems, tr); + } +}; + +// split + +template +class rtree_rstar_split +{ + typedef typename index::detail::rtree_node::type node; + typedef typename index::detail::rtree_internal_node::type internal_node; + typedef typename index::detail::rtree_leaf::type leaf; + + static const size_t dimension = index::traits::dimension::value; + +public: + template + 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 index::detail::rtree_elements_type::type elements_type; + typedef typename elements_type::value_type element_type; + + elements_type & elements = index::detail::get_elements(n); + + // get split data + rtree_rstar_split_data split_data; + rtree_rstar_split_update_data:: + apply(split_data, elements, min_elems, max_elems, tr); + + // create new node + node * right_node = rtree_create_node(Node()); + elements_type & new_elems = index::detail::get_elements(boost::get(*right_node)); + + // update new node's elements + new_elems.resize(max_elems + 1 - split_data.choosen_median_index); + std::copy( + split_data.choosen_distribution.begin() + split_data.choosen_median_index, + split_data.choosen_distribution.end(), + new_elems.begin()); + + // update elements of the current node + elements.resize(split_data.choosen_median_index); + std::copy( + split_data.choosen_distribution.begin(), + split_data.choosen_distribution.begin() + split_data.choosen_median_index, + elements.begin()); + + if ( parent != 0 ) + { + // update old node's box + parent->children[current_child_index].first = split_data.choosen_left_box; + // add new node to the parent's children + parent->children.push_back(std::make_pair(split_data.choosen_right_box, right_node)); + } + else + { + assert(&n == boost::get(root)); + + // create new root and add nodes + node * new_root = rtree_create_node(internal_node()); + + boost::get(*new_root).children.push_back(std::make_pair(split_data.choosen_left_box, root)); + boost::get(*new_root).children.push_back(std::make_pair(split_data.choosen_right_box, right_node)); + + root = new_root; + } + } +}; + +} // namespace visitors + +}}} // namespace boost::geometry::index + +#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_RSTAR_SPLIT_HPP diff --git a/include/boost/geometry/extensions/index/rtree/rtree.hpp b/include/boost/geometry/extensions/index/rtree/rtree.hpp index 8c26668dc..3827ba6b9 100644 --- a/include/boost/geometry/extensions/index/rtree/rtree.hpp +++ b/include/boost/geometry/extensions/index/rtree/rtree.hpp @@ -41,18 +41,17 @@ public: typedef typename detail::rtree_internal_node::type internal_node; typedef typename detail::rtree_leaf::type leaf; - inline explicit rtree(size_t max_elems_per_node = 4, size_t min_elems_per_node = 2, translator_type const& translator = translator_type()) + inline explicit rtree(size_t max_elems_per_node = 2, size_t min_elems_per_node = 1, translator_type const& translator = translator_type()) : m_values_count(0) , m_max_elems_per_node(max_elems_per_node) , m_min_elems_per_node(min_elems_per_node) , m_root(0) , m_translator(translator) { - if ( min_elems_per_node < 2 ) - min_elems_per_node = 2; - - // TODO: awulkiew - reconsider following assert - assert(2 * m_min_elems_per_node <= m_max_elems_per_node); + if ( m_min_elems_per_node < 1 ) + m_min_elems_per_node = 1; + if ( m_max_elems_per_node < 2 ) + m_max_elems_per_node = 2; m_root = detail::rtree_create_node(leaf()); } @@ -82,9 +81,9 @@ public: } template - void apply_visitor(Visitor & visitor) const + typename Visitor::result_type apply_visitor(Visitor & visitor) const { - boost::apply_visitor(visitor, *m_root); + return boost::apply_visitor(visitor, *m_root); } translator_type const& get_translator() const diff --git a/include/boost/geometry/extensions/index/rtree/rtree_node.hpp b/include/boost/geometry/extensions/index/rtree/rtree_node.hpp index e72baf688..f0742f987 100644 --- a/include/boost/geometry/extensions/index/rtree/rtree_node.hpp +++ b/include/boost/geometry/extensions/index/rtree/rtree_node.hpp @@ -153,6 +153,24 @@ rtree_element_indexable(Value const& el, Translator const& tr) return tr(el); }; +// elements box + +template +inline Box elements_box(FwdIter first, FwdIter last, Translator const& tr) +{ + assert(first != last); + + Box result; + + geometry::convert(index::detail::rtree_element_indexable(*first, tr), result); + ++first; + + for ( ; first != last ; ++first ) + geometry::expand(result, index::detail::rtree_element_indexable(*first, tr)); + + return result; +} + // create leaf node template diff --git a/include/boost/geometry/extensions/index/rtree/visitors/gl_draw.hpp b/include/boost/geometry/extensions/index/rtree/visitors/gl_draw.hpp index 666a48a4c..2038bec98 100644 --- a/include/boost/geometry/extensions/index/rtree/visitors/gl_draw.hpp +++ b/include/boost/geometry/extensions/index/rtree/visitors/gl_draw.hpp @@ -27,10 +27,10 @@ struct rtree_gl_draw_point template struct rtree_gl_draw_point { - static inline void apply(Point const& p) + static inline void apply(Point const& p, size_t level) { glBegin(GL_POINT); - glVertex2f(geometry::get<0>(p), geometry::get<1>(p)); + glVertex2f(geometry::get<0>(p), geometry::get<1>(p), level); glEnd(); } }; @@ -42,13 +42,13 @@ struct rtree_gl_draw_box template struct rtree_gl_draw_box { - static inline void apply(Box const& b) + static inline void apply(Box const& b, size_t level) { glBegin(GL_LINE_LOOP); - glVertex2f(geometry::get(b), geometry::get(b)); - glVertex2f(geometry::get(b), geometry::get(b)); - glVertex2f(geometry::get(b), geometry::get(b)); - glVertex2f(geometry::get(b), geometry::get(b)); + glVertex3f(geometry::get(b), geometry::get(b), level); + glVertex3f(geometry::get(b), geometry::get(b), level); + glVertex3f(geometry::get(b), geometry::get(b), level); + glVertex3f(geometry::get(b), geometry::get(b), level); glEnd(); } }; @@ -64,9 +64,9 @@ struct rtree_gl_draw_indexable typedef typename geometry::traits::point_type::type point_type; static const size_t dimension = geometry::traits::dimension::value; - static inline void apply(Indexable const& i) + static inline void apply(Indexable const& i, size_t level) { - rtree_gl_draw_box::apply(i); + rtree_gl_draw_box::apply(i, level); } }; @@ -75,9 +75,9 @@ struct rtree_gl_draw_indexable { static const size_t dimension = geometry::traits::dimension::value; - static inline void apply(std::ostream &os, Indexable const& i) + static inline void apply(Indexable const& i, size_t level) { - rtree_gl_draw_point::apply(i); + rtree_gl_draw_point::apply(i, level); } }; @@ -86,12 +86,12 @@ struct rtree_gl_draw_indexable namespace detail { template -inline void rtree_gl_draw_indexable(Indexable const& i) +inline void rtree_gl_draw_indexable(Indexable const& i, size_t level) { dispatch::rtree_gl_draw_indexable< Indexable, typename geometry::traits::tag::type - >::apply(i); + >::apply(i, level); } } // namespace detail @@ -128,7 +128,7 @@ struct rtree_gl_draw : public boost::static_visitor<> for (typename children_type::const_iterator it = n.children.begin(); it != n.children.end(); ++it) { - detail::rtree_gl_draw_indexable(it->first); + detail::rtree_gl_draw_indexable(it->first, level); } size_t level_backup = level; @@ -152,7 +152,7 @@ struct rtree_gl_draw : public boost::static_visitor<> for (typename values_type::const_iterator it = n.values.begin(); it != n.values.end(); ++it) { - detail::rtree_gl_draw_indexable(tr(*it)); + detail::rtree_gl_draw_indexable(tr(*it), level); } } diff --git a/include/boost/geometry/extensions/index/rtree/visitors/print.hpp b/include/boost/geometry/extensions/index/rtree/visitors/print.hpp index 23799f938..63910a295 100644 --- a/include/boost/geometry/extensions/index/rtree/visitors/print.hpp +++ b/include/boost/geometry/extensions/index/rtree/visitors/print.hpp @@ -128,22 +128,15 @@ struct rtree_print : public boost::static_visitor<> { typedef typename internal_node::children_type children_type; - os << " --> Node --------" << std::endl; - os << " Address: " << this << std::endl; - os << " Level: " << level << std::endl; - os << " Children: " << n.children.size() << std::endl; - os << " | "; - + spaces(level) << "INTERNAL NODE - L:" << level << " Ch:" << n.children.size() << " @:" << &n << '\n'; + for (typename children_type::const_iterator it = n.children.begin(); it != n.children.end(); ++it) { + spaces(level); detail::rtree_print_indexable(os, it->first); - os << " | "; + os << " ->" << it->second << '\n'; } - os << std::endl; - os << " --< Node --------" << std::endl; - - os << " Children: " << std::endl; size_t level_backup = level; ++level; @@ -161,17 +154,21 @@ struct rtree_print : public boost::static_visitor<> { typedef typename leaf::values_type values_type; - os << "\t" << " --> Leaf --------" << std::endl; - os << "\t" << " Values: " << n.values.size() << std::endl; + spaces(level) << "LEAF - L:" << level << " V:" << n.values.size() << " @:" << &n << '\n'; for (typename values_type::const_iterator it = n.values.begin(); it != n.values.end(); ++it) { - os << "\t" << " | "; + spaces(level); detail::rtree_print_indexable(os, tr(*it)); - os << " | " << std::endl;; + os << '\n'; } - os << "\t" << " --< Leaf --------" << std::endl; + } + inline std::ostream & spaces(size_t level) + { + for ( size_t i = 0 ; i < 2 * level ; ++i ) + os << ' '; + return os; } std::ostream & os; diff --git a/include/boost/geometry/extensions/index/rtree/visitors/rtree_are_boxes_ok.hpp b/include/boost/geometry/extensions/index/rtree/visitors/rtree_are_boxes_ok.hpp new file mode 100644 index 000000000..5d09631e0 --- /dev/null +++ b/include/boost/geometry/extensions/index/rtree/visitors/rtree_are_boxes_ok.hpp @@ -0,0 +1,103 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Boost.Index - R-tree boxes 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_RTREE_ARE_BOXES_OK_HPP +#define BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_VISITORS_RTREE_ARE_BOXES_OK_HPP + +#include +#include + +namespace boost { namespace geometry { namespace index { + +namespace visitors { + +template +class rtree_are_boxes_ok : public boost::static_visitor +{ + typedef typename index::detail::rtree_internal_node::type internal_node; + typedef typename index::detail::rtree_leaf::type leaf; + +public: + inline rtree_are_boxes_ok(Translator const& tr) + : m_tr(tr), m_is_root(true) + {} + + inline bool operator()(internal_node const& n) + { + if (n.children.empty()) + return false; + + Box box_bckup = m_box; + bool is_root_bckup = m_is_root; + + m_is_root = false; + + for ( internal_node::children_type::const_iterator it = n.children.begin(); + it != n.children.end() ; ++it) + { + m_box = it->first; + + if ( false == boost::apply_visitor(*this, *it->second) ) + return false; + } + + m_box = box_bckup; + m_is_root = is_root_bckup; + + Box result; + geometry::convert(n.children.front().first, result); + for(internal_node::children_type::const_iterator it = n.children.begin() + 1; + it != n.children.end() ; ++it) + { + geometry::expand(result, it->first); + } + + return m_is_root || geometry::equals(result, m_box); + } + + inline bool operator()(leaf const& n) + { + if (n.values.empty()) + return false; + + Box result; + geometry::convert(m_tr(n.values.front()), result); + for(leaf::values_type::const_iterator it = n.values.begin() + 1; + it != n.values.end() ; ++it) + { + geometry::expand(result, m_tr(*it)); + } + + return m_is_root || geometry::equals(result, m_box); + } + +private: + Translator const& m_tr; + Box m_box; + bool m_is_root; +}; + +} // namespace visitors + +template +bool rtree_are_boxes_ok(rtree const& tree) +{ + typedef rtree rt; + visitors::rtree_are_boxes_ok< + typename rt::value_type, + typename rt::translator_type, + typename rt::box_type, + Tag> v(tree.get_translator()); + + return tree.apply_visitor(v); +} + +}}} // namespace boost::geometry::index + +#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_VISITORS_RTREE_ARE_BOXES_OK_HPP diff --git a/tests/additional_glut_vis.cpp b/tests/additional_glut_vis.cpp index 819dba15e..4636f8820 100644 --- a/tests/additional_glut_vis.cpp +++ b/tests/additional_glut_vis.cpp @@ -4,10 +4,12 @@ #include #include +#include +#include typedef boost::geometry::model::point P; typedef boost::geometry::model::box

B; -boost::geometry::index::rtree t; +boost::geometry::index::rtree t(2, 1); void render_scene(void) { @@ -30,8 +32,8 @@ void resize(int w, int h) glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt( - 5.0f, 5.0f, 15.0f, - 5.0f, 5.0f, -1.0f, + 150.0f, 150.0f, 150.0f, + 50.0f, 50.0f, -1.0f, 0.0f, 1.0f, 0.0f); } @@ -39,12 +41,21 @@ void mouse(int button, int state, int x, int y) { if ( state == GLUT_DOWN ) { - float x = ( rand() % 10000 ) / 1000.0f; - float y = ( rand() % 10000 ) / 1000.0f; - float w = ( rand() % 10000 ) / 100000.0f; - float h = ( rand() % 10000 ) / 100000.0f; + float x = ( rand() % 100 ); + float y = ( rand() % 100 ); + float w = ( rand() % 2 ) + 1; + float h = ( rand() % 2 ) + 1; - boost::geometry::index::insert(t, B(P(x - w, y - h),P(x + w, y + h))); + B b(P(x - w, y - h),P(x + w, y + h)); + + boost::geometry::index::insert(t, b); + + std::cout << "\n\n\n" << t << "\n\n"; + + std::cout << "inserted: "; + boost::geometry::index::visitors::detail::rtree_print_indexable(std::cout, b); + std::cout << '\n'; + std::cout << ( boost::geometry::index::rtree_are_boxes_ok(t) ? "boxes OK" : "WRONG BOXES!" ); glutPostRedisplay(); } diff --git a/tests/additional_sizes_and_times.cpp b/tests/additional_sizes_and_times.cpp index c3ce00515..53154fc06 100644 --- a/tests/additional_sizes_and_times.cpp +++ b/tests/additional_sizes_and_times.cpp @@ -29,10 +29,10 @@ int main() std::vector v(n); for ( size_t i = 0 ; i < n ; ++i ) { - float x = ( rand() % 10000 ) / 1000.0f; - float y = ( rand() % 10000 ) / 1000.0f; - float w = ( rand() % 10000 ) / 100000.0f; - float h = ( rand() % 10000 ) / 100000.0f; + float x = float( rand() % 1000 ); + float y = float( rand() % 1000 ); + float w = float( rand() % 10 ) / 10.0f; + float h = float( rand() % 10 ) / 10.0f; v[i] = B(P(x - w, y - h),P(x + w, y + h)); } diff --git a/tests/main.cpp b/tests/main.cpp index 93fc439de..fce78a685 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -8,6 +8,19 @@ int main() tests_rtree_native_hpp(); tests_rtree_filters_hpp(); + /*namespace g = boost::geometry; + typedef g::model::point P; + typedef g::model::box

B; + + g::index::rtree tree(4, 2); + g::index::insert(tree, B(P(1, 6),P(6, 19))); + g::index::insert(tree, B(P(10, 1),P(18, 18))); + g::index::insert(tree, B(P(22, 6),P(27, 20))); + g::index::insert(tree, B(P(29, 2),P(34, 18))); + g::index::insert(tree, B(P(35, 3),P(39, 19))); + + std::cout << tree;*/ + #ifdef _MSC_VER std::cin.get(); #endif diff --git a/tests/rtree_native.hpp b/tests/rtree_native.hpp index 430c68bcd..c05dd7566 100644 --- a/tests/rtree_native.hpp +++ b/tests/rtree_native.hpp @@ -17,7 +17,24 @@ void tests_rtree_native_hpp() { std::cout << "tests/rtree_native.hpp\n"; - std::cout << "Boxes\n"; + std::cout << "Boxes3d\n"; + { + typedef boost::geometry::model::point P; + typedef boost::geometry::model::box

B; + + boost::geometry::index::rtree t(4, 2); + boost::geometry::index::insert(t, B(P(0, 0, 0), P(1, 1, 1))); + boost::geometry::index::insert(t, B(P(2, 2, 2), P(3, 3, 3))); + boost::geometry::index::insert(t, B(P(4, 4, 4), P(5, 5, 5))); + boost::geometry::index::insert(t, B(P(6, 6, 6), P(7, 7, 7))); + boost::geometry::index::insert(t, B(P(8, 8, 8), P(9, 9, 9))); + std::cerr << t; + } + + std::cout << "-------------------------------------------------\n"; + std::cout << "-------------------------------------------------\n"; + + std::cout << "Boxes2d\n"; { typedef boost::geometry::model::point P; typedef boost::geometry::model::box

B;