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 def7bb102..bdaf2804f 100644 --- a/include/boost/geometry/extensions/index/rtree/linear/redistribute_elements.hpp +++ b/include/boost/geometry/extensions/index/rtree/linear/redistribute_elements.hpp @@ -193,8 +193,6 @@ struct redistribute_elements typedef typename rtree::element_indexable_type::type indexable_type; typedef typename index::traits::coordinate_type::type coordinate_type; typedef typename index::default_area_result::type area_type; - - static const size_t dimension = index::traits::dimension::value; // copy original elements elements_type elements_copy = rtree::elements_get(n); @@ -233,27 +231,21 @@ struct redistribute_elements { element_type const& elem = elements_copy[i]; indexable_type const& indexable = rtree::element_indexable(elem, tr); + bool insert_into_group1 = false; // 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 ) + if ( elements1.size() + remaining <= min_elems ) { - elements1.push_back(elem); - geometry::expand(box1, indexable); - area1 = index::area(box1); + insert_into_group1 = true; } - else 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); + insert_into_group1 = false; } // choose better node and insert element else { - assert(0 < remaining); - remaining--; - // calculate enlarged boxes and areas Box enlarged_box1(box1); Box enlarged_box2(box2); @@ -262,57 +254,42 @@ struct redistribute_elements 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; + area_type area_increase1 = enlarged_area1 - area1; + area_type area_increase2 = enlarged_area2 - area2; - // choose group which box area have to be enlarged least - if ( areas_diff1 < areas_diff2 ) + // choose group which box area have to be enlarged least or has smaller area or has fewer elements + if ( area_increase1 < area_increase2 || + ( area_increase1 == area_increase2 && area1 < area2 ) || + ( area1 == area2 && elements1.size() <= elements2.size() ) ) { - 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; + insert_into_group1 = true; } else { - // choose group which box has smaller area - if ( area1 < area2 ) - { - elements1.push_back(elem); - box1 = enlarged_box1; - area1 = enlarged_area1; - } - 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; - } - } + insert_into_group1 = false; } } + + if ( insert_into_group1 ) + { + elements1.push_back(elem); + geometry::expand(box1, indexable); + area1 = index::area(box1); + } + else + { + elements2.push_back(elem); + geometry::expand(box2, indexable); + area2 = index::area(box2); + } + + assert(0 < remaining); + --remaining; } } + + assert(min_elems <= elements1.size() && elements1.size() <= max_elems); + assert(min_elems <= elements2.size() && elements2.size() <= max_elems); } }; diff --git a/include/boost/geometry/extensions/index/rtree/quadratic/redistribute_elements.hpp b/include/boost/geometry/extensions/index/rtree/quadratic/redistribute_elements.hpp index 4babab5d1..3f594e55f 100644 --- a/include/boost/geometry/extensions/index/rtree/quadratic/redistribute_elements.hpp +++ b/include/boost/geometry/extensions/index/rtree/quadratic/redistribute_elements.hpp @@ -54,11 +54,11 @@ struct pick_seeds { 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); + indexable_type const& ind1 = rtree::element_indexable(elements[i], tr); + indexable_type const& ind2 = rtree::element_indexable(elements[j], tr); box_type enlarged_box; - geometry::convert(ind1); + geometry::convert(ind1, enlarged_box); geometry::expand(enlarged_box, ind2); area_type free_area = index::area(enlarged_box) - index::area(ind1) - index::area(ind2); @@ -76,7 +76,183 @@ struct pick_seeds } // namespace quadratic -// TODO: awulkiew - redistribute +template +struct redistribute_elements +{ + typedef typename rtree::node::type node; + typedef typename rtree::internal_node::type internal_node; + typedef typename rtree::leaf::type leaf; + + typedef typename index::default_area_result::type area_type; + + template + static inline void apply(Node & n, + Node & second_node, + Box & box1, + Box & box2, + size_t min_elems, + size_t max_elems, + Translator const& tr) + { + typedef typename rtree::elements_type::type elements_type; + typedef typename elements_type::value_type element_type; + typedef typename rtree::element_indexable_type::type indexable_type; + typedef typename index::traits::coordinate_type::type coordinate_type; + + // copy original elements + elements_type elements_copy = rtree::elements_get(n); + + // calculate initial seeds + size_t seed1 = 0; + size_t seed2 = 0; + quadratic::pick_seeds::apply(elements_copy, tr, seed1, seed2); + + // prepare nodes' elements containers + elements_type & elements1 = rtree::elements_get(n); + elements_type & elements2 = rtree::elements_get(second_node); + elements1.clear(); + assert(elements2.empty()); + + // add seeds + elements1.push_back(elements_copy[seed1]); + elements2.push_back(elements_copy[seed2]); + + // calculate boxes + geometry::convert(rtree::element_indexable(elements_copy[seed1], tr), box1); + geometry::convert(rtree::element_indexable(elements_copy[seed2], tr), box2); + + // remove seeds + if (seed1 < seed2) + { + elements_copy.erase(elements_copy.begin() + seed2); + elements_copy.erase(elements_copy.begin() + seed1); + } + else + { + elements_copy.erase(elements_copy.begin() + seed1); + elements_copy.erase(elements_copy.begin() + seed2); + } + + // initialize areas + area_type area1 = index::area(box1); + area_type area2 = index::area(box2); + + size_t remaining = elements_copy.size(); + + // redistribute the rest of the elements + while ( !elements_copy.empty() ) + { + elements_type::reverse_iterator el_it = elements_copy.rbegin(); + bool insert_into_group1 = false; + + size_t elements1_count = elements1.size(); + size_t elements2_count = elements2.size(); + + // 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_count + remaining <= min_elems ) + { + insert_into_group1 = true; + } + else if ( elements2_count + remaining <= min_elems ) + { + insert_into_group1 = false; + } + // insert the best element + else + { + // find element with minimum groups areas increses differences + area_type area_increase1 = 0; + area_type area_increase2 = 0; + pick_next(elements_copy.rbegin(), elements_copy.rend(), + box1, box2, area1, area2, tr, + el_it, area_increase1, area_increase2); + + if ( area_increase1 < area_increase2 || + ( area_increase1 == area_increase2 && area1 < area2 ) || + ( area1 == area2 && elements1_count <= elements2_count ) ) + { + insert_into_group1 = true; + } + else + { + insert_into_group1 = false; + } + } + + // move element to the choosen group + element_type const& elem = *el_it; + indexable_type const& indexable = rtree::element_indexable(elem, tr); + + if ( insert_into_group1 ) + { + elements1.push_back(elem); + geometry::expand(box1, indexable); + area1 = index::area(box1); + } + else + { + elements2.push_back(elem); + geometry::expand(box2, indexable); + area2 = index::area(box2); + } + + assert(!elements_copy.empty()); + elements_copy.erase(elements_copy.begin() + elements_copy.size() - 1); + + assert(0 < remaining); + --remaining; + } + + assert(min_elems <= elements1.size() && elements1.size() <= max_elems); + assert(min_elems <= elements2.size() && elements2.size() <= max_elems); + } + + template + static inline void pick_next(It first, It last, + Box const& box1, Box const& box2, + area_type const& area1, area_type const& area2, + Translator const& tr, + It out_it, area_type & out_area_increase1, area_type & out_area_increase2) + { + typedef typename boost::iterator_value::type element_type; + typedef typename rtree::element_indexable_type::type indexable_type; + + area_type greatest_area_incrase_diff = 0; + out_it = first; + out_area_increase1 = 0; + out_area_increase2 = 0; + + for ( It el_it = first ; el_it != last ; ++el_it ) + { + indexable_type const& indexable = rtree::element_indexable(*el_it, tr); + + // 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 area_incrase1 = (enlarged_area1 - area1); + area_type area_incrase2 = (enlarged_area2 - area2); + + area_type area_incrase_diff = area_incrase1 < area_incrase2 ? + area_incrase2 - area_incrase1 : area_incrase1 - area_incrase2; + + if ( greatest_area_incrase_diff < area_incrase_diff ) + { + greatest_area_incrase_diff = area_incrase_diff; + out_it = el_it; + out_area_increase1 = area_incrase1; + out_area_increase2 = area_incrase2; + } + + break; + } + } +}; } // namespace detail diff --git a/include/boost/geometry/extensions/index/rtree/rtree.hpp b/include/boost/geometry/extensions/index/rtree/rtree.hpp index 48bb46488..decfe5f48 100644 --- a/include/boost/geometry/extensions/index/rtree/rtree.hpp +++ b/include/boost/geometry/extensions/index/rtree/rtree.hpp @@ -22,8 +22,9 @@ #include +#include + // TODO: awulkiew - correct implementation -//#include //#include namespace boost { namespace geometry { namespace index { diff --git a/include/boost/geometry/extensions/index/rtree/visitors/insert.hpp b/include/boost/geometry/extensions/index/rtree/visitors/insert.hpp index a962d7c34..b0a358d17 100644 --- a/include/boost/geometry/extensions/index/rtree/visitors/insert.hpp +++ b/include/boost/geometry/extensions/index/rtree/visitors/insert.hpp @@ -211,7 +211,7 @@ protected: traverse_apply_visitor(visitor, n, choosen_node_index); } - // TODO: awulkiew - change name to handle_overflow or overflow_treatment? + // TODO: awulkiew - change post_traverse name to handle_overflow or overflow_treatment? template inline void post_traverse(Node &n) diff --git a/include/boost/geometry/extensions/index/rtree/visitors/remove.hpp b/include/boost/geometry/extensions/index/rtree/visitors/remove.hpp index 1f6b0b472..875896ffb 100644 --- a/include/boost/geometry/extensions/index/rtree/visitors/remove.hpp +++ b/include/boost/geometry/extensions/index/rtree/visitors/remove.hpp @@ -48,9 +48,12 @@ public: typedef typename rtree::elements_type::type children_type; children_type & children = rtree::elements_get(n); + // traverse children which boxes intersects value's box size_t child_node_index = 0; for ( ; child_node_index < children.size() ; ++child_node_index ) { + // TODO: awulkiew - change intersects to within + if ( geometry::intersects(children[child_node_index].first, m_tr(m_value)) ) { // next traversing step diff --git a/tests/additional_glut_vis.cpp b/tests/additional_glut_vis.cpp index 1e8cf323d..8e68e8da2 100644 --- a/tests/additional_glut_vis.cpp +++ b/tests/additional_glut_vis.cpp @@ -9,7 +9,7 @@ typedef boost::geometry::model::point P; typedef boost::geometry::model::box

B; //boost::geometry::index::rtree t(2, 1); -boost::geometry::index::rtree t(4, 2); +boost::geometry::index::rtree t(4, 2); std::vector vect; void render_scene(void) diff --git a/tests/additional_sizes_and_times.cpp b/tests/additional_sizes_and_times.cpp index 5174149cd..cdcab5eed 100644 --- a/tests/additional_sizes_and_times.cpp +++ b/tests/additional_sizes_and_times.cpp @@ -17,7 +17,8 @@ int main() typedef bg::model::point P; typedef bg::model::box

B; - typedef bgi::rtree, bgi::default_parameter, bgi::linear_tag> RT; + //typedef bgi::rtree, bgi::default_parameter, bgi::linear_tag> RT; + typedef bgi::rtree, bgi::default_parameter, bgi::quadratic_tag> RT; std::ifstream file_cfg("config.txt"); size_t max_elems = 4;