From 919c6286b8cfeb4a028dff27c0f0720fdede9363 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Wed, 4 May 2011 21:33:15 +0000 Subject: [PATCH] remove algorithm added + some other changes [SVN r71726] --- .../extensions/index/algorithms/area.hpp | 42 ++- .../rtree/linear/redistribute_elements.hpp | 112 +++--- .../index/rtree/quadratic/quadratic.hpp | 21 ++ .../rtree/quadratic/redistribute_elements.hpp | 87 +++++ .../index/rtree/rstar/choose_next_node.hpp | 10 +- .../extensions/index/rtree/rstar/insert.hpp | 258 +++++++++++-- .../index/rtree/rstar/insert_impl.hpp | 338 ------------------ .../extensions/index/rtree/rstar/rstar.hpp | 2 + .../geometry/extensions/index/rtree/rtree.hpp | 47 ++- .../index/rtree/visitors/insert.hpp | 183 ++++++++-- .../index/rtree/visitors/remove.hpp | 191 +++++++++- .../extensions/index/translator/def.hpp | 16 +- .../extensions/index/translator/helpers.hpp | 104 +++--- .../extensions/index/translator/index.hpp | 6 +- tests/additional_glut_vis.cpp | 27 +- tests/additional_sizes_and_times.cpp | 122 +++++-- tests/main.cpp | 37 +- 17 files changed, 1013 insertions(+), 590 deletions(-) create mode 100644 include/boost/geometry/extensions/index/rtree/quadratic/quadratic.hpp create mode 100644 include/boost/geometry/extensions/index/rtree/quadratic/redistribute_elements.hpp delete mode 100644 include/boost/geometry/extensions/index/rtree/rstar/insert_impl.hpp diff --git a/include/boost/geometry/extensions/index/algorithms/area.hpp b/include/boost/geometry/extensions/index/algorithms/area.hpp index dbfe23376..8d49a4e0e 100644 --- a/include/boost/geometry/extensions/index/algorithms/area.hpp +++ b/include/boost/geometry/extensions/index/algorithms/area.hpp @@ -12,11 +12,11 @@ namespace boost { namespace geometry { namespace index { -template +template struct default_area_result { typedef typename select_most_precise< - typename coordinate_type::type, + typename traits::coordinate_type::type, long double >::type type; }; @@ -32,7 +32,7 @@ struct area_for_each_dimension static inline typename default_area_result::type apply(Box const& b) { return area_for_each_dimension::apply(b) * - ( geometry::get(b) - geometry::get(b) ); + ( index::get(b) - index::get(b) ); } }; @@ -41,16 +41,44 @@ struct area_for_each_dimension { static inline typename default_area_result::type apply(Box const& b) { - return geometry::get(b) - geometry::get(b); + return index::get(b) - index::get(b); } }; } // namespace detail -template -typename default_area_result::type area(Box const& b) +namespace dispatch { + +template +struct area { - return detail::area_for_each_dimension::value>::apply(b); + // TODO: awulkiew - static assert? +}; + +template +struct area +{ + static typename default_area_result::type apply(Indexable const&) + { + return 0; + } +}; + +template +struct area +{ + static typename default_area_result::type apply(Indexable const& b) + { + return detail::area_for_each_dimension::value>::apply(b); + } +}; + +} // namespace dispatch + +template +typename default_area_result::type area(Indexable const& b) +{ + return dispatch::area::type>::apply(b); } }}} // namespace boost::geometry::index diff --git a/include/boost/geometry/extensions/index/rtree/linear/redistribute_elements.hpp b/include/boost/geometry/extensions/index/rtree/linear/redistribute_elements.hpp index de53a04f7..def7bb102 100644 --- a/include/boost/geometry/extensions/index/rtree/linear/redistribute_elements.hpp +++ b/include/boost/geometry/extensions/index/rtree/linear/redistribute_elements.hpp @@ -30,6 +30,10 @@ namespace detail { namespace linear { +// TODO: awulkiew - there are loops inside find_greatest_normalized_separation::apply() +// iteration is done for each DimensionIndex. +// Separations and seeds for all DimensionIndex(es) could be calculated at once, stored, then the greatest would be choosen. + // from void find_normalized_separations(std::vector const& boxes, T& separation, unsigned int& first, unsigned int& second) const template @@ -96,7 +100,7 @@ struct find_greatest_normalized_separation }; template -struct choose_axis_impl +struct pick_seeds_impl { BOOST_STATIC_ASSERT(0 < DimensionIndex); @@ -106,30 +110,28 @@ struct choose_axis_impl static inline void apply(Elements const& elements, Translator const& tr, - size_t & axis, coordinate_type & separation, size_t & seed1, size_t & seed2) { - choose_axis_impl::apply(elements, tr, axis, separation, seed1, seed2); + pick_seeds_impl::apply(elements, tr, separation, seed1, seed2); coordinate_type current_separation; size_t s1, s2; find_greatest_normalized_separation::apply(elements, tr, current_separation, s1, s2); - // in the old implementation different operator was used: <= + // in the old implementation different operator was used: <= (y axis prefered) if ( separation < current_separation ) { separation = current_separation; seed1 = s1; seed2 = s2; - axis = DimensionIndex - 1; } } }; template -struct choose_axis_impl +struct pick_seeds_impl { typedef typename Elements::value_type element_type; typedef typename rtree::element_indexable_type::type indexable_type; @@ -137,36 +139,32 @@ struct choose_axis_impl static inline void apply(Elements const& elements, Translator const& tr, - size_t & axis, coordinate_type & separation, size_t & seed1, size_t & seed2) { find_greatest_normalized_separation::apply(elements, tr, separation, seed1, seed2); - axis = 0; } }; // from void linear_pick_seeds(node_pointer const& n, unsigned int &seed1, unsigned int &seed2) const template -struct choose_axis +struct pick_seeds { typedef typename Elements::value_type element_type; typedef typename rtree::element_indexable_type::type indexable_type; typedef typename index::traits::coordinate_type::type coordinate_type; - + static const size_t dimension = index::traits::dimension::value; - static inline size_t apply(Elements const& elements, - Translator const& tr, - size_t & seed1, - size_t & seed2) + static inline void apply(Elements const& elements, + Translator const& tr, + size_t & seed1, + size_t & seed2) { - size_t axis = 0; coordinate_type separation = 0; - choose_axis_impl::apply(elements, tr, axis, separation, seed1, seed2); - return axis; + pick_seeds_impl::apply(elements, tr, separation, seed1, seed2); } }; @@ -205,7 +203,7 @@ struct redistribute_elements // calculate initial seeds size_t seed1 = 0; size_t seed2 = 0; - linear::choose_axis::apply(elements_copy, tr, seed1, seed2); + linear::pick_seeds::apply(elements_copy, tr, seed1, seed2); // prepare nodes' elements containers elements_type & elements1 = rtree::elements_get(n); @@ -236,59 +234,45 @@ struct redistribute_elements element_type const& elem = elements_copy[i]; indexable_type const& indexable = rtree::element_indexable(elem, tr); - // TODO: awulkiew - is this needed? + // if there is small number of elements left and the number of elements in node is lesser than min_elems + // just insert them to this node if ( elements1.size() + remaining == min_elems ) { elements1.push_back(elem); geometry::expand(box1, indexable); area1 = index::area(box1); - continue; } - if ( elements2.size() + remaining == min_elems ) + else if ( elements2.size() + remaining == min_elems ) { elements2.push_back(elem); geometry::expand(box2, indexable); area2 = index::area(box2); - continue; - } - - assert(0 < remaining); - remaining--; - - // calculate enlarged boxes and areas - Box enlarged_box1(box1); - Box enlarged_box2(box2); - geometry::expand(enlarged_box1, indexable); - geometry::expand(enlarged_box2, indexable); - area_type enlarged_area1 = index::area(enlarged_box1); - area_type enlarged_area2 = index::area(enlarged_box2); - - area_type areas_diff1 = enlarged_area1 - area1; - area_type areas_diff2 = enlarged_area2 - area2; - - // choose group which box area have to be enlarged least - if ( areas_diff1 < areas_diff2 ) - { - elements1.push_back(elem); - box1 = enlarged_box1; - area1 = enlarged_area1; - } - else if ( areas_diff2 < areas_diff1 ) - { - elements2.push_back(elem); - box2 = enlarged_box2; - area2 = enlarged_area2; } + // choose better node and insert element else { - // choose group which box has smaller area - if ( area1 < area2 ) + assert(0 < remaining); + remaining--; + + // calculate enlarged boxes and areas + Box enlarged_box1(box1); + Box enlarged_box2(box2); + geometry::expand(enlarged_box1, indexable); + geometry::expand(enlarged_box2, indexable); + area_type enlarged_area1 = index::area(enlarged_box1); + area_type enlarged_area2 = index::area(enlarged_box2); + + area_type areas_diff1 = enlarged_area1 - area1; + area_type areas_diff2 = enlarged_area2 - area2; + + // choose group which box area have to be enlarged least + if ( areas_diff1 < areas_diff2 ) { elements1.push_back(elem); box1 = enlarged_box1; area1 = enlarged_area1; } - else if ( area2 < area1 ) + else if ( areas_diff2 < areas_diff1 ) { elements2.push_back(elem); box2 = enlarged_box2; @@ -296,19 +280,35 @@ struct redistribute_elements } else { - // choose group with fewer elements - if ( elements1.size() <= elements2.size() ) + // choose group which box has smaller area + if ( area1 < area2 ) { elements1.push_back(elem); box1 = enlarged_box1; area1 = enlarged_area1; } - else + else if ( area2 < area1 ) { elements2.push_back(elem); box2 = enlarged_box2; area2 = enlarged_area2; } + else + { + // choose group with fewer elements + if ( elements1.size() <= elements2.size() ) + { + elements1.push_back(elem); + box1 = enlarged_box1; + area1 = enlarged_area1; + } + else + { + elements2.push_back(elem); + box2 = enlarged_box2; + area2 = enlarged_area2; + } + } } } } diff --git a/include/boost/geometry/extensions/index/rtree/quadratic/quadratic.hpp b/include/boost/geometry/extensions/index/rtree/quadratic/quadratic.hpp new file mode 100644 index 000000000..fed52522e --- /dev/null +++ b/include/boost/geometry/extensions/index/rtree/quadratic/quadratic.hpp @@ -0,0 +1,21 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Boost.Index - R-tree +// +// 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_QUADRATIC_QUADRATIC_HPP +#define BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_QUADRATIC_QUADRATIC_HPP + +namespace boost { namespace geometry { namespace index { + +struct quadratic_tag {}; + +}}} // namespace boost::geometry::index + +#include + +#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_QUADRATIC_QUADRATIC_HPP diff --git a/include/boost/geometry/extensions/index/rtree/quadratic/redistribute_elements.hpp b/include/boost/geometry/extensions/index/rtree/quadratic/redistribute_elements.hpp new file mode 100644 index 000000000..4babab5d1 --- /dev/null +++ b/include/boost/geometry/extensions/index/rtree/quadratic/redistribute_elements.hpp @@ -0,0 +1,87 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Boost.Index - R-tree quadratic 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_QUADRATIC_REDISTRIBUTE_ELEMENTS_HPP +#define BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_QUADRATIC_REDISTRIBUTE_ELEMENTS_HPP + +#include + +#include + +#include +#include + +#include +#include +#include + +namespace boost { namespace geometry { namespace index { + +namespace detail { namespace rtree { namespace visitors { + +namespace detail { + +namespace quadratic { + +template +struct pick_seeds +{ + typedef typename Elements::value_type element_type; + typedef typename rtree::element_indexable_type::type indexable_type; + typedef typename index::traits::coordinate_type::type coordinate_type; + typedef Box box_type; + typedef typename index::default_area_result::type area_type; + + static inline void apply(Elements const& elements, + Translator const& tr, + size_t & seed1, + size_t & seed2) + { + size_t elements_count = elements.size(); + + assert(2 <= elements_count); + + seed1 = 0; + seed2 = 1; + area_type greatest_free_area = 0; + for ( size_t i = 0 ; i < elements_count ; ++i ) + { + for ( size_t j = i + 1 ; j < elements_count ; ++j ) + { + indexable_type & ind1 = rtree::element_indexable(elements[i], tr); + indexable_type & ind2 = rtree::element_indexable(elements[j], tr); + + box_type enlarged_box; + geometry::convert(ind1); + geometry::expand(enlarged_box, ind2); + + area_type free_area = index::area(enlarged_box) - index::area(ind1) - index::area(ind2); + + if ( greatest_free_area < free_area ) + { + greatest_free_area = free_area; + seed1 = i; + seed2 = j; + } + } + } + } +}; + +} // namespace quadratic + +// TODO: awulkiew - redistribute + +} // namespace detail + +}}} // namespace detail::rtree::visitors + +}}} // namespace boost::geometry::index + +#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_QUADRATIC_REDISTRIBUTE_ELEMENTS_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 index 785b7f24f..eb1302ca4 100644 --- a/include/boost/geometry/extensions/index/rtree/rstar/choose_next_node.hpp +++ b/include/boost/geometry/extensions/index/rtree/rstar/choose_next_node.hpp @@ -23,10 +23,12 @@ namespace boost { namespace geometry { namespace index { -namespace detail { namespace rtree { namespace rstar { +namespace detail { namespace rtree { namespace visitors { + +namespace detail { template -class choose_next_node +class choose_next_node { typedef typename rtree::node::type node; typedef typename rtree::internal_node::type internal_node; @@ -235,7 +237,9 @@ private: //}; }; -}}} // namespace detail::rtree:rstar +} // namespace detail + +}}} // namespace detail::rtree::visitors }}} // namespace boost::geometry::index diff --git a/include/boost/geometry/extensions/index/rtree/rstar/insert.hpp b/include/boost/geometry/extensions/index/rtree/rstar/insert.hpp index dfd204540..451054c04 100644 --- a/include/boost/geometry/extensions/index/rtree/rstar/insert.hpp +++ b/include/boost/geometry/extensions/index/rtree/rstar/insert.hpp @@ -10,6 +10,12 @@ #ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_RSTAR_INSERT_HPP #define BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_RSTAR_INSERT_HPP +#include + +#include +#include +#include + #include #include #include @@ -19,44 +25,234 @@ #include #include -#include +#include +#include + +//TEST +#include +#include namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace visitors { -template -class insert : public boost::static_visitor<> -{ - typedef typename rtree::node::type node; - typedef typename rtree::internal_node::type internal_node; - typedef typename rtree::leaf::type leaf; +namespace detail { -public: - inline explicit insert(node* & root, Value const& v, size_t min_elements, size_t max_elements, Translator const& t) - : m_root(root) - , m_impl(root, v, min_elements, max_elements, t) - { - // TODO - // assert - check if Box is correct - } +//template +//class insert : public boost::static_visitor<> +//{ +//protected: +// typedef typename rtree::node::type node; +// typedef typename rtree::internal_node::type internal_node; +// typedef typename rtree::leaf::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::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 +// 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:: +// 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 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 +// inline void post_traverse_handle_oveflow(Node &n) +// { +// // handle overflow +// if ( m_max_elems_per_node < rtree::elements_get(n).size() ) +// { +// detail::overflow_treatment:: +// apply(n, m_parent, m_current_child_index, m_root_node, m_min_elems_per_node, m_max_elems_per_node, m_tr); +// } +// } +// +// template +// 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 +// 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::max() && +// 0 < m_reinserted_elements_count ) +// { +// reinsert(n); +// } +// // second time insert +// else +// {*/ +// 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); +// //} +// } +// +// template +// static inline bool distances_asc( +// std::pair const& d1, +// std::pair const& d2) +// { +// return d1.first < d2.first; +// } +// +// template +// static inline bool distances_dsc( +// std::pair const& d1, +// std::pair const& d2) +// { +// return d1.first > d2.first; +// } +// +// template +// inline void reinsert(Node & n) +// { +// typedef typename index::detail::rtree::elements_type::type elements_type; +// typedef typename index::detail::rtree::element_type::type element_type; +// typedef typename geometry::point_type::type point_type; +// // TODO: awulkiew - use distance_result +// typedef typename index::traits::coordinate_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 > 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); +// +// // 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(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 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; +//}; - inline void operator()(internal_node & n) - { - assert(&n == &boost::get(*m_root)); - boost::apply_visitor(m_impl, *m_root); - } - - inline void operator()(leaf & n) - { - assert(&n == &boost::get(*m_root)); - boost::apply_visitor(m_impl, *m_root); - } - -private: - node* & m_root; - index::detail::rtree::rstar::insert_impl m_impl; -}; +} // namespace detail }}} // namespace detail::rtree::visitors diff --git a/include/boost/geometry/extensions/index/rtree/rstar/insert_impl.hpp b/include/boost/geometry/extensions/index/rtree/rstar/insert_impl.hpp deleted file mode 100644 index 90e163d34..000000000 --- a/include/boost/geometry/extensions/index/rtree/rstar/insert_impl.hpp +++ /dev/null @@ -1,338 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) -// -// Boost.Index - R*-tree reinsert 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_INSERT_IMPL_HPP -#define BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_RSTAR_INSERT_IMPL_HPP - -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -//TEST -#include -#include - -namespace boost { namespace geometry { namespace index { - -namespace detail { namespace rtree { namespace rstar { - -template -class insert_base; - -template -class insert_impl : public insert_base -{ - typedef insert_base base; - typedef typename base::node node; - typedef typename base::internal_node internal_node; - typedef typename base::leaf leaf; - -public: - inline insert_impl( - node* & root, - Element const& el, - size_t min_elements, - size_t max_elements, - Translator const& t, - size_t level = std::numeric_limits::max() - ) - : base(root, el, min_elements, max_elements, t, level) - {} - - inline void operator()(internal_node & n) - { - if ( base::m_current_level < base::m_level ) - { - // next traversing step - base::traverse(*this, n); - } - else - { - assert( base::m_level == base::m_current_level ); - - // push new child node - n.children.push_back(base::m_element); - } - - if ( base::m_max_elems_per_node < n.children.size() ) - base::overflow_treatment(n); - } - - inline void operator()(leaf & n) - { - assert(false); - } -}; - -template -class insert_impl : public insert_base -{ - typedef insert_base base; - typedef typename base::node node; - typedef typename base::internal_node internal_node; - typedef typename base::leaf leaf; - -public: - inline insert_impl( - node* & root, - Value const& v, - size_t min_elements, - size_t max_elements, - Translator const& t, - size_t level = std::numeric_limits::max() - ) - : base(root, v, min_elements, max_elements, t, level) - {} - - inline void operator()(internal_node & n) - { - assert(base::m_current_level < base::m_level); - - // next traversing step - base::traverse(*this, n); - - if ( base::m_max_elems_per_node < n.children.size() ) - base::overflow_treatment(n); - } - - inline void operator()(leaf & n) - { - assert( base::m_level == base::m_current_level || - base::m_level == std::numeric_limits::max() ); - - n.values.push_back(base::m_element); - - if ( base::m_max_elems_per_node < n.values.size() ) - base::overflow_treatment(n); - } -}; - -template -class insert_base : public boost::static_visitor<> -{ -protected: - typedef typename rtree::node::type node; - typedef typename rtree::internal_node::type internal_node; - typedef typename rtree::leaf::type leaf; - - inline insert_base( - node* & root, - Element const& el, - size_t min_elements, - size_t max_elements, - Translator const& t, - size_t level = std::numeric_limits::max() - ) - : m_element(el) - , m_tr(t) - , 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 - 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:: - 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 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 - 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 - 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::max() && - 0 < m_reinserted_elements_count ) - { - reinsert(n); - } - // second time insert - else - {*/ - 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); - //} - } - - template - static inline bool distances_asc( - std::pair const& d1, - std::pair const& d2) - { - return d1.first < d2.first; - } - - template - static inline bool distances_dsc( - std::pair const& d1, - std::pair const& d2) - { - return d1.first > d2.first; - } - - template - inline void reinsert(Node & n) - { - typedef typename index::detail::rtree::elements_type::type elements_type; - typedef typename index::detail::rtree::element_type::type element_type; - typedef typename geometry::point_type::type point_type; - // TODO: awulkiew - use distance_result - typedef typename index::traits::coordinate_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 > 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); - - // 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(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 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 detail::rtree::rstar - -}}} // namespace boost::geometry::index - -#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_RSTAR_INSERT_IMPL_HPP diff --git a/include/boost/geometry/extensions/index/rtree/rstar/rstar.hpp b/include/boost/geometry/extensions/index/rtree/rstar/rstar.hpp index 53b901ba1..972f570e5 100644 --- a/include/boost/geometry/extensions/index/rtree/rstar/rstar.hpp +++ b/include/boost/geometry/extensions/index/rtree/rstar/rstar.hpp @@ -16,6 +16,8 @@ struct rstar_tag {}; }}} // namespace boost::geometry::index +#include + #include #endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_RSTAR_RSTAR_HPP diff --git a/include/boost/geometry/extensions/index/rtree/rtree.hpp b/include/boost/geometry/extensions/index/rtree/rtree.hpp index 77428920f..48bb46488 100644 --- a/include/boost/geometry/extensions/index/rtree/rtree.hpp +++ b/include/boost/geometry/extensions/index/rtree/rtree.hpp @@ -17,9 +17,14 @@ #include #include +#include +#include #include -#include + +// TODO: awulkiew - correct implementation +//#include +//#include namespace boost { namespace geometry { namespace index { @@ -80,7 +85,9 @@ public: void insert(value_type const& value) { - detail::rtree::visitors::insert + // TODO: awulkiew - assert for correct value + + detail::rtree::visitors::insert insert_v(m_root, value, m_min_elems_per_node, m_max_elems_per_node, m_translator); boost::apply_visitor(insert_v, *m_root); @@ -88,6 +95,36 @@ public: ++m_values_count; } + void remove(value_type const& value) + { + // TODO: awulkiew - assert for correct value + assert(0 < m_values_count); + + detail::rtree::visitors::remove + remove_v(m_root, value, m_min_elems_per_node, m_max_elems_per_node, m_translator); + + boost::apply_visitor(remove_v, *m_root); + + --m_values_count; + } + + size_t size() const + { + return m_values_count; + } + + bool empty() const + { + // TODO: awulkiew - take root into consideration + return 0 == m_values_count; + } + + void clear() + { + // TODO: awulkiew - implement + assert(false); + } + template typename Visitor::result_type apply_visitor(Visitor & visitor) const { @@ -118,6 +155,12 @@ void insert(rtree & tree, Value const& v) tree.insert(v); } +template +void remove(rtree & tree, Value const& v) +{ + tree.remove(v); +} + }}} // namespace boost::geometry::index #endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_RSTREE_RSTREE_HPP diff --git a/include/boost/geometry/extensions/index/rtree/visitors/insert.hpp b/include/boost/geometry/extensions/index/rtree/visitors/insert.hpp index 9362f2a1b..a962d7c34 100644 --- a/include/boost/geometry/extensions/index/rtree/visitors/insert.hpp +++ b/include/boost/geometry/extensions/index/rtree/visitors/insert.hpp @@ -10,6 +10,8 @@ #ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_VISITORS_INSERT_HPP #define BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_VISITORS_INSERT_HPP +#include + #include namespace boost { namespace geometry { namespace index { @@ -26,16 +28,18 @@ struct choose_next_node typedef typename rtree::internal_node::type internal_node; typedef typename rtree::leaf::type leaf; - typedef typename internal_node::children_type children_type; + typedef typename rtree::elements_type::type children_type; typedef typename index::default_area_result::type area_type; template static inline size_t apply(internal_node & n, Indexable const& indexable) { - assert(!n.children.empty()); + children_type & children = rtree::elements_get(n); - size_t children_count = n.children.size(); + assert(!children.empty()); + + size_t children_count = children.size(); // choose index with smallest area change or smallest area size_t choosen_index = 0; @@ -46,7 +50,7 @@ struct choose_next_node for ( size_t i = 0 ; i < children_count ; ++i ) { typedef typename children_type::value_type child_type; - child_type const& ch_i = n.children[i]; + child_type const& ch_i = children[i]; Box box_exp(ch_i.first); geometry::expand(box_exp, indexable); @@ -73,7 +77,7 @@ struct redistribute_elements; // Default split algorithm template -class split +struct split { typedef typename rtree::node::type node; typedef typename rtree::internal_node::type internal_node; @@ -81,7 +85,6 @@ class split static const size_t dimension = index::traits::dimension::value; -public: template static inline void apply( Node & n, @@ -131,7 +134,6 @@ struct overflow_treatment typedef typename rtree::internal_node::type internal_node; typedef typename rtree::leaf::type leaf; -public: template static inline void apply( Node & n, @@ -146,21 +148,31 @@ public: } }; -} // namespace detail - -// Default insert algorithm -template +// Default insert visitor +template class insert : public boost::static_visitor<> { +public: typedef typename rtree::node::type node; typedef typename rtree::internal_node::type internal_node; typedef typename rtree::leaf::type leaf; -public: - inline explicit insert(node* & root, 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) + inline insert(node* & root, + Element const& element, + size_t min_elements, + size_t max_elements, + Translator const& t, + size_t level = std::numeric_limits::max() + ) + : m_element(element) + , m_tr(t) + , m_min_elems_per_node(min_elements) + , m_max_elems_per_node(max_elements) + , m_level(level) , m_root_node(root) - , m_parent(0), m_current_child_index(0), m_current_level(0) + , m_parent(0) + , m_current_child_index(0) + , m_current_level(0) { // TODO // assert - check if Box is correct @@ -168,39 +180,52 @@ public: inline void operator()(internal_node & n) { - // choose next node - size_t choosen_node_index = detail::choose_next_node:: - apply(n, rtree::element_indexable(m_value, m_tr)); + // traverse + traverse(*this, n); - // expand the node to contain value - geometry::expand(n.children[choosen_node_index].first, m_tr(m_value)); - - // next traversing step - traverse_apply_visitor(n, choosen_node_index); - - // handle overflow - if ( m_max_elems_per_node < n.children.size() ) - { - detail::overflow_treatment:: - apply(n, m_parent, m_current_child_index, m_root_node, m_min_elems_per_node, m_max_elems_per_node, m_tr); - } + post_traverse(n); } inline void operator()(leaf & n) { // push value - n.values.push_back(m_value); + rtree::elements_get(n).push_back(m_element); + post_traverse(n); + } + +protected: + template + inline void traverse(Visitor & visitor, internal_node & n) + { + // choose next node + size_t choosen_node_index = detail::choose_next_node:: + apply(n, rtree::element_indexable(m_element, m_tr)); + + // expand the node to contain value + geometry::expand( + n.children[choosen_node_index].first, + rtree::element_indexable(m_element, m_tr)); + + // next traversing step + traverse_apply_visitor(visitor, n, choosen_node_index); + } + + // TODO: awulkiew - change name to handle_overflow or overflow_treatment? + + template + inline void post_traverse(Node &n) + { // handle overflow - if ( m_max_elems_per_node < n.values.size() ) + if ( m_max_elems_per_node < rtree::elements_get(n).size() ) { detail::overflow_treatment:: apply(n, m_parent, m_current_child_index, m_root_node, m_min_elems_per_node, m_max_elems_per_node, m_tr); } } -private: - inline void traverse_apply_visitor(internal_node &n, size_t choosen_node_index) + template + inline void traverse_apply_visitor(Visitor & visitor, internal_node &n, size_t choosen_node_index) { // save previous traverse inputs and set new ones internal_node * parent_bckup = m_parent; @@ -212,7 +237,7 @@ private: ++m_current_level; // next traversing step - boost::apply_visitor(*this, *n.children[choosen_node_index].second); + boost::apply_visitor(visitor, *rtree::elements_get(n)[choosen_node_index].second); // restore previous traverse inputs m_parent = parent_bckup; @@ -220,10 +245,11 @@ private: m_current_level = current_level_bckup; } - Value const& m_value; + 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_level; node* & m_root_node; @@ -233,6 +259,91 @@ private: size_t m_current_level; }; +} // namespace detail + +// Default insert visitor +template +struct insert : public detail::insert +{ + typedef detail::insert base; + typedef typename base::node node; + typedef typename base::internal_node internal_node; + typedef typename base::leaf leaf; + + inline insert(node* & root, + Element const& element, + size_t min_elements, + size_t max_elements, + Translator const& tr, + size_t level = std::numeric_limits::max() + ) + : base(root, element, min_elements, max_elements, tr, level) + {} + + inline void operator()(internal_node & n) + { + if ( base::m_current_level < base::m_level ) + { + // next traversing step + base::traverse(*this, n); + } + else + { + assert( base::m_level == base::m_current_level ); + + // push new child node + rtree::elements_get(n).push_back(base::m_element); + } + + base::post_traverse(n); + } + + inline void operator()(leaf & n) + { + assert(false); + } +}; + +// Default insert visitor specialized for Values elements +template +struct insert : public detail::insert +{ + typedef detail::insert base; + typedef typename base::node node; + typedef typename base::internal_node internal_node; + typedef typename base::leaf leaf; + + inline insert(node* & root, + Value const& v, + size_t min_elements, + size_t max_elements, + Translator const& t, + size_t level = std::numeric_limits::max() + ) + : base(root, v, min_elements, max_elements, t, level) + {} + + inline void operator()(internal_node & n) + { + assert(base::m_current_level < base::m_level); + + // next traversing step + base::traverse(*this, n); + + base::post_traverse(n); + } + + inline void operator()(leaf & n) + { + assert( base::m_level == base::m_current_level || + base::m_level == std::numeric_limits::max() ); + + rtree::elements_get(n).push_back(base::m_element); + + base::post_traverse(n); + } +}; + }}} // namespace detail::rtree::visitors }}} // namespace boost::geometry::index diff --git a/include/boost/geometry/extensions/index/rtree/visitors/remove.hpp b/include/boost/geometry/extensions/index/rtree/visitors/remove.hpp index d5e9a07a4..1f6b0b472 100644 --- a/include/boost/geometry/extensions/index/rtree/visitors/remove.hpp +++ b/include/boost/geometry/extensions/index/rtree/visitors/remove.hpp @@ -12,14 +12,201 @@ #include +#include + namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace visitors { +// Default remove algorithm template -struct rtree_remove +class remove : public boost::static_visitor<> { - // not implemented here + typedef typename rtree::node::type node; + typedef typename rtree::internal_node::type internal_node; + typedef typename rtree::leaf::type leaf; + +public: + inline explicit remove(node* & root, 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_is_value_removed(false) + , m_parent(0) + , m_current_child_index(0) + , m_current_level(0) + , m_is_underflow(false) + { + // TODO + // assert - check if Value/Box is correct + } + + inline void operator()(internal_node & n) + { + typedef typename rtree::elements_type::type children_type; + children_type & children = rtree::elements_get(n); + + size_t child_node_index = 0; + for ( ; child_node_index < children.size() ; ++child_node_index ) + { + if ( geometry::intersects(children[child_node_index].first, m_tr(m_value)) ) + { + // next traversing step + traverse_apply_visitor(n, child_node_index); + + if ( m_is_value_removed ) + break; + } + } + + // value was found and removed + if ( m_is_value_removed ) + { + typedef typename rtree::elements_type::type elements_type; + typedef typename elements_type::iterator element_iterator; + elements_type & elements = rtree::elements_get(n); + + // underflow occured - child node should be removed + if ( m_is_underflow ) + { + 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)); + elements.erase(underfl_el_it); + + // calc underflow + m_is_underflow = elements.size() < m_min_elems_per_node; + } + + // test - underflow state should be ok here + assert(elements.size() < m_min_elems_per_node == m_is_underflow); + + // n is not root - adjust aabb + if ( 0 != m_parent ) + { + rtree::elements_get(*m_parent)[m_current_child_index].first + = rtree::elements_box(elements.begin(), elements.end(), m_tr); + } + // n is root node + else + { + // current node must be a root + assert(&n == boost::get(m_root_node)); + + // value not found + assert(m_is_value_removed); + + // reinsert elements from removed nodes + // begin with levels closer to the root + for ( std::vector< std::pair >::reverse_iterator it = m_underflowed_nodes.rbegin(); + it != m_underflowed_nodes.rend() ; ++it ) + { + if ( boost::apply_visitor(is_leaf(), *it->second) ) + reinsert_elements(boost::get(*it->second), it->first); + else + reinsert_elements(boost::get(*it->second), it->first); + } + + // shorten the tree + if ( rtree::elements_get(n).size() == 1 ) + { + m_root_node = rtree::elements_get(n)[0].second; + } + } + } + } + + inline void operator()(leaf & n) + { + typedef typename rtree::elements_type::type elements_type; + elements_type & elements = rtree::elements_get(n); + + // find value and remove it + for ( elements_type::iterator it = elements.begin() ; it != elements.end() ; ++it ) + { + if ( m_tr.equals(*it, m_value) ) + { + elements.erase(it); + m_is_value_removed = true; + break; + } + } + + // if value was removed + if ( m_is_value_removed ) + { + // calc underflow + m_is_underflow = elements.size() < m_min_elems_per_node; + + // n is not root - adjust aabb + if ( 0 != m_parent ) + { + rtree::elements_get(*m_parent)[m_current_child_index].first + = rtree::elements_box(elements.begin(), elements.end(), m_tr); + } + } + } + +private: + inline void traverse_apply_visitor(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(*this, *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; + } + + template + void reinsert_elements(Node &n, size_t level) + { + typedef typename rtree::elements_type::type elements_type; + elements_type & elements = rtree::elements_get(n); + for ( typename elements_type::iterator it = elements.begin(); + it != elements.end() ; ++it ) + { + visitors::insert insert_v( + m_root_node, + *it, + m_min_elems_per_node, + m_max_elems_per_node, + m_tr, + level); + + boost::apply_visitor(insert_v, *m_root_node); + } + } + + Value const& m_value; + Translator const& m_tr; + const size_t m_min_elems_per_node; + const size_t m_max_elems_per_node; + + node* & m_root_node; + bool m_is_value_removed; + std::vector< std::pair > m_underflowed_nodes; + + // traversing input parameters + internal_node *m_parent; + size_t m_current_child_index; + size_t m_current_level; + + // traversing output parameters + bool m_is_underflow; }; }}} // namespace detail::rtree::visitors diff --git a/include/boost/geometry/extensions/index/translator/def.hpp b/include/boost/geometry/extensions/index/translator/def.hpp index 4780d45be..e3c9cfcae 100644 --- a/include/boost/geometry/extensions/index/translator/def.hpp +++ b/include/boost/geometry/extensions/index/translator/def.hpp @@ -29,10 +29,10 @@ struct def return detail::extract_indexable::get(v); } - /*bool equals(Value const& v1, Value const& v2) const + bool equals(Value const& v1, Value const& v2) const { return detail::equals::apply(v1, v2); - }*/ + } }; // Iterator @@ -46,10 +46,10 @@ struct def return detail::extract_indexable::get(*v); } - /*bool equals(Value const& v1, Value const& v2) const + bool equals(Value const& v1, Value const& v2) const { return v1 == v2; - }*/ + } }; // SmartPtr @@ -63,10 +63,10 @@ struct def return detail::extract_indexable::get(*v); } - /*bool equals(Value const& v1, Value const& v2) const + bool equals(Value const& v1, Value const& v2) const { return v1 == v2; - }*/ + } }; } // namespace dispatch @@ -92,10 +92,10 @@ struct def return detail::extract_indexable::get(*v); } - /*bool equals(const Value* v1, const Value* v2) const + bool equals(const Value* v1, const Value* v2) const { return v1 == v2; - }*/ + } }; }}}} // namespace boost::geometry::index::translator diff --git a/include/boost/geometry/extensions/index/translator/helpers.hpp b/include/boost/geometry/extensions/index/translator/helpers.hpp index b68ab9fd9..44b364650 100644 --- a/include/boost/geometry/extensions/index/translator/helpers.hpp +++ b/include/boost/geometry/extensions/index/translator/helpers.hpp @@ -17,6 +17,8 @@ #include #include +#include + #include namespace boost { namespace geometry { namespace index { namespace translator { @@ -132,60 +134,58 @@ struct is_smart_ptr } // namespace detail -//namespace dispatch { -// -//template -//struct equals -//{ -// static bool apply(Geometry const& g1, Geometry const& g2) -// { -// return geometry::equals(g1, g2); -// } -//}; -// -//template -//struct equals -//{ -// static bool apply(T const& v1, T const& v2) -// { -// return v1 == v2; -// } -//}; -// -//} // namespace dispatch -// -//namespace detail { -// -//template -//struct equals -//{ -// static bool apply(Geometry const& g1, Geometry const& g2) -// { -// return geometry::equals(g1, g2); -// } -//}; -// -//template -//struct equals< std::pair > -//{ -// static bool apply(std::pair const& p1, std::pair const& p2) -// { -// return -// dispatch::equals< -// First, -// typename traits::tag::type -// >::apply(p1.first, p2.first) -// && -// dispatch::equals< -// Second, -// typename traits::tag::type -// >::apply(p1.second, p2.second); -// } -//}; -// -//} // namespace detail +namespace dispatch { +template +struct equals +{ + static bool apply(Geometry const& g1, Geometry const& g2) + { + return geometry::equals(g1, g2); + } +}; +template +struct equals +{ + static bool apply(T const& v1, T const& v2) + { + return v1 == v2; + } +}; + +} // namespace dispatch + +namespace detail { + +template +struct equals +{ + static bool apply(Geometry const& g1, Geometry const& g2) + { + return geometry::equals(g1, g2); + } +}; + +template +struct equals< std::pair > +{ + static bool apply(std::pair const& p1, std::pair const& p2) + { + return + dispatch::equals< + First, + typename traits::tag::type + >::apply(p1.first, p2.first) + && + dispatch::equals< + Second, + typename traits::tag::type + >::apply(p1.second, p2.second); + } +}; + +} // namespace detail }}}} // namespace boost::geometry::index::translator diff --git a/include/boost/geometry/extensions/index/translator/index.hpp b/include/boost/geometry/extensions/index/translator/index.hpp index b0759393d..f96d0d433 100644 --- a/include/boost/geometry/extensions/index/translator/index.hpp +++ b/include/boost/geometry/extensions/index/translator/index.hpp @@ -29,10 +29,10 @@ public: ::get(m_c[i]); } - /*bool equals(size_t i1, size_t i2) const + bool equals(size_t i1, size_t i2) const { - return i1 == i2; - }*/ + return i1 == i2; + } private: Container const& m_c; diff --git a/tests/additional_glut_vis.cpp b/tests/additional_glut_vis.cpp index db01250fc..1e8cf323d 100644 --- a/tests/additional_glut_vis.cpp +++ b/tests/additional_glut_vis.cpp @@ -10,6 +10,7 @@ typedef boost::geometry::model::point typedef boost::geometry::model::box

B; //boost::geometry::index::rtree t(2, 1); boost::geometry::index::rtree t(4, 2); +std::vector vect; void render_scene(void) { @@ -39,7 +40,7 @@ void resize(int w, int h) void mouse(int button, int state, int x, int y) { - if ( state == GLUT_DOWN ) + if ( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN ) { float x = ( rand() % 100 ); float y = ( rand() % 100 ); @@ -49,13 +50,35 @@ void mouse(int button, int state, int x, int y) B b(P(x - w, y - h),P(x + w, y + h)); boost::geometry::index::insert(t, b); + vect.push_back(b); - std::cout << "\n\n\n" << 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";*/ + + glutPostRedisplay(); + } + else if ( button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN ) + { + if ( vect.empty() ) + return; + + size_t i = rand() % vect.size(); + B b = vect[i]; + + boost::geometry::index::remove(t, b); + vect.erase(vect.begin() + i); + + /*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";*/ glutPostRedisplay(); } diff --git a/tests/additional_sizes_and_times.cpp b/tests/additional_sizes_and_times.cpp index 3398d8d71..5174149cd 100644 --- a/tests/additional_sizes_and_times.cpp +++ b/tests/additional_sizes_and_times.cpp @@ -43,39 +43,21 @@ int main() } std::cout << "loaded\n"; - std::cout << "inserting time test...\n"; - tim.restart(); RT t(max_elems, min_elems); - for (size_t i = 0 ; i < values_count ; ++i ) + { - float x = coords[i].first; - float y = coords[i].second; - B b(P(x - 0.5f, y - 0.5f), P(x + 0.5f, y + 0.5f)); - - // Zle wyswietla dane, obcina czesc ulamkowa - // Zle buduje drzewo dla i == 228 - - //TEST - /*if ( i == 228 ) + std::cout << "inserting time test...\n"; + tim.restart(); + for (size_t i = 0 ; i < values_count ; ++i ) { - std::cout << std::fixed << x << ", " << y << "\n"; - boost::geometry::index::detail::rtree::visitors::detail::print_indexable(std::cout, b); - }*/ + float x = coords[i].first; + float y = coords[i].second; + B b(P(x - 0.5f, y - 0.5f), P(x + 0.5f, y + 0.5f)); - t.insert(std::make_pair(b, i)); - - //TEST - /*if ( !boost::geometry::index::are_boxes_ok(t) ) - { - std::ofstream log("log1.txt", std::ofstream::trunc); - log << std::fixed << i << " - " << x << ", " << y << " - inserted: "; - boost::geometry::index::detail::rtree::visitors::detail::print_indexable(log, b); - log << '\n'; - log << ( boost::geometry::index::are_boxes_ok(t) ? "boxes OK" : "WRONG BOXES!" ); - log << '\n' << t; - }*/ + t.insert(std::make_pair(b, i)); + } + std::cout << "time: " << tim.elapsed() << "s\n"; } - std::cout << "time: " << tim.elapsed() << "s\n"; if ( save_ch == 's' ) { @@ -92,19 +74,81 @@ int main() std::cout << "saved...\n"; } - std::cout << "searching time test...\n"; - tim.restart(); - size_t temp = 0; - for (size_t i = 0 ; i < queries_count ; ++i ) { - float x = coords[i].first; - float y = coords[i].second; - std::deque< std::pair > result; - t.find(B(P(x - 10, y - 10), P(x + 10, y + 10)), std::back_inserter(result)); - temp += result.size(); + std::cout << "searching time test...\n"; + tim.restart(); + size_t temp = 0; + for (size_t i = 0 ; i < queries_count ; ++i ) + { + float x = coords[i].first; + float y = coords[i].second; + std::deque< std::pair > result; + t.find(B(P(x - 10, y - 10), P(x + 10, y + 10)), std::back_inserter(result)); + temp += result.size(); + } + std::cout << "time: " << tim.elapsed() << "s\n"; + std::cout << temp << "\n"; + } + + { + std::cout << "removing time test...\n"; + tim.restart(); + for (size_t i = 0 ; i < values_count / 2 ; ++i ) + { + float x = coords[i].first; + float y = coords[i].second; + B b(P(x - 0.5f, y - 0.5f), P(x + 0.5f, y + 0.5f)); + + t.remove(std::make_pair(b, i)); + } + std::cout << "time: " << tim.elapsed() << "s\n"; + } + + { + std::cout << "searching time test...\n"; + tim.restart(); + size_t temp = 0; + for (size_t i = 0 ; i < queries_count ; ++i ) + { + float x = coords[i].first; + float y = coords[i].second; + std::deque< std::pair > result; + t.find(B(P(x - 10, y - 10), P(x + 10, y + 10)), std::back_inserter(result)); + temp += result.size(); + } + std::cout << "time: " << tim.elapsed() << "s\n"; + std::cout << temp << "\n"; + } + + { + std::cout << "inserting time test...\n"; + tim.restart(); + for (size_t i = 0 ; i < values_count / 2 ; ++i ) + { + float x = coords[i].first; + float y = coords[i].second; + B b(P(x - 0.5f, y - 0.5f), P(x + 0.5f, y + 0.5f)); + + t.insert(std::make_pair(b, i)); + } + std::cout << "time: " << tim.elapsed() << "s\n"; + } + + { + std::cout << "searching time test...\n"; + tim.restart(); + size_t temp = 0; + for (size_t i = 0 ; i < queries_count ; ++i ) + { + float x = coords[i].first; + float y = coords[i].second; + std::deque< std::pair > result; + t.find(B(P(x - 10, y - 10), P(x + 10, y + 10)), std::back_inserter(result)); + temp += result.size(); + } + std::cout << "time: " << tim.elapsed() << "s\n"; + std::cout << temp << "\n"; } - std::cout << "time: " << tim.elapsed() << "s\n"; - std::cout << temp << "\n"; std::cin.get(); diff --git a/tests/main.cpp b/tests/main.cpp index 4a7e696dd..3966633e3 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -2,25 +2,40 @@ #include #include +#include + int main() { tests_translators_hpp(); tests_rtree_native_hpp(); - tests_rtree_native_hpp(); + //tests_rtree_native_hpp(); tests_rtree_filters_hpp(); - /*namespace g = boost::geometry; - typedef g::model::point P; - typedef g::model::box

B; + { + namespace bg = boost::geometry; + namespace bgi = boost::geometry::index; + typedef bg::model::point P; + typedef bg::model::box

B; + typedef std::pair V; - 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))); + bgi::rtree t(4, 2); + const int m = 15; + for ( int i = 0 ; i < m ; ++i ) + { + bgi::insert(t, V(B(P(i*2, i*2), P(i*2+1, i*2+1)), i)); + } + std::cout << t << "\n------------------------------------\n"; + std::cin.get(); - std::cout << tree;*/ + for ( int i = 0 ; i < m ; ++i ) + { + bgi::remove(t, V(B(P(i*2, i*2), P(i*2+1, i*2+1)), i)); + std::cout << t << '\n'; + std::cout << ( boost::geometry::index::are_boxes_ok(t) ? "boxes OK" : "WRONG BOXES!" ); + std::cout << "\n------------------------------------\n"; + std::cin.get(); + } + } #ifdef _MSC_VER std::cin.get();