Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r84730 - trunk/boost/geometry/index/detail/rtree
From: adam.wulkiewicz_at_[hidden]
Date: 2013-06-10 11:55:45


Author: awulkiew
Date: 2013-06-10 11:55:45 EDT (Mon, 10 Jun 2013)
New Revision: 84730
URL: http://svn.boost.org/trac/boost/changeset/84730

Log:
geometry.index: packer replaced by pack, various tweaks added.

Text files modified:
   trunk/boost/geometry/index/detail/rtree/pack_create.hpp | 124 +++++++++++++++++++++++----------------
   1 files changed, 73 insertions(+), 51 deletions(-)

Modified: trunk/boost/geometry/index/detail/rtree/pack_create.hpp
==============================================================================
--- trunk/boost/geometry/index/detail/rtree/pack_create.hpp Mon Jun 10 11:32:34 2013 (r84729)
+++ trunk/boost/geometry/index/detail/rtree/pack_create.hpp 2013-06-10 11:55:45 EDT (Mon, 10 Jun 2013) (r84730)
@@ -105,9 +105,17 @@
 // it is more similar to the top-down recursive kd-tree creation algorithm
 // using object median split and split axis of greatest BB edge
 // BB is only used as a hint (assuming objects are distributed uniformly)
+//
+// Implemented algorithm guarantees that the number of elements in nodes will be between Min and Max
+// and that nodes are packed as tightly as possible
+// e.g. for 177 values Max = 5 and Min = 2 it will construct the following tree:
+// ROOT 177
+// L1 125 52
+// L2 25 25 25 25 25 25 17 10
+// L3 5x5 5x5 5x5 5x5 5x5 5x5 3x5+2 2x5
 
 template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
-class packer
+class pack
 {
     typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
     typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
@@ -130,34 +138,37 @@
     typedef typename internal_elements::value_type internal_element;
 
 public:
- packer(parameters_type const& p, Translator const& tr, Allocators & al) : m_parameters(p), m_translator(tr), m_allocators(al) {}
-
     // Arbitrary iterators
- template <typename InIt>
- node_pointer pack(InIt first, InIt last)
+ template <typename InIt> inline static
+ node_pointer apply(InIt first, InIt last,
+ parameters_type const& parameters, Translator const& translator, Allocators & allocators)
     {
+ typedef typename std::iterator_traits<InIt>::difference_type diff_type;
+
+ diff_type diff = std::distance(first, last);
+ if ( diff <= 0 )
+ return node_pointer(0);
+
         typedef std::pair<point_type, InIt> entry_type;
         std::vector<entry_type> entries;
 
- // TODO if RandomAccess
- // count = distance(first, last);
- // reserve(count);
-
+ std::size_t values_count = static_cast<std::size_t>(diff);
+ entries.reserve(values_count);
+
         Box hint_box;
         geometry::assign_inverse(hint_box);
-
- std::size_t count = 0;
- for ( ; first != last ; ++first, ++count )
+ for ( ; first != last ; ++first )
         {
- geometry::expand(hint_box, m_translator(*first));
+ geometry::expand(hint_box, translator(*first));
 
             point_type pt;
- geometry::centroid(m_translator(*first), pt);
+ geometry::centroid(translator(*first), pt);
             entries.push_back(std::make_pair(pt, first));
         }
 
- subtree_elements_counts subtree_counts = calculate_subtree_elements_counts(count);
- internal_element el = per_level(entries.begin(), entries.end(), hint_box, count, subtree_counts);
+ subtree_elements_counts subtree_counts = calculate_subtree_elements_counts(values_count, parameters);
+ internal_element el = per_level(entries.begin(), entries.end(), hint_box, values_count, subtree_counts,
+ parameters, translator, allocators);
         return el.second;
     }
 
@@ -169,80 +180,84 @@
         std::size_t minc;
     };
 
- template <typename EIt>
- internal_element per_level(EIt first, EIt last, Box const& hint_box, std::size_t count, subtree_elements_counts const& subtree_counts)
+ template <typename EIt> inline static
+ internal_element per_level(EIt first, EIt last, Box const& hint_box, std::size_t values_count, subtree_elements_counts const& subtree_counts,
+ parameters_type const& parameters, Translator const& translator, Allocators & allocators)
     {
- // remove it later
- BOOST_ASSERT(first <= last); BOOST_ASSERT(last - first == typename std::iterator_traits<EIt>::difference_type(count));
+ BOOST_ASSERT(first < last);
+ BOOST_ASSERT(last - first == values_count);
 
         if ( subtree_counts.maxc <= 1 )
         {
             // ROOT or LEAF
- BOOST_ASSERT(count <= m_parameters.get_max_elements());
+ BOOST_ASSERT(values_count <= parameters.get_max_elements());
             // if !root check m_parameters.get_min_elements() <= count
 
             // create new leaf node
- node_pointer n = rtree::create_node<Allocators, leaf>::apply(m_allocators); // MAY THROW (A)
+ node_pointer n = rtree::create_node<Allocators, leaf>::apply(allocators); // MAY THROW (A)
             leaf & l = rtree::get<leaf>(*n);
             // reserve space for values
- rtree::elements(l).reserve(count); // MAY THROW (A)
+ rtree::elements(l).reserve(values_count); // MAY THROW (A)
             // calculate values box and copy values
             Box elements_box;
             geometry::assign_inverse(elements_box);
             for ( ; first != last ; ++first )
             {
                 rtree::elements(l).push_back(*(first->second)); // MAY THROW (C)
- geometry::expand(elements_box, m_translator(*(first->second)));
+ geometry::expand(elements_box, translator(*(first->second)));
             }
             return internal_element(elements_box, n);
         }
 
         // calculate next max and min subtree counts
         subtree_elements_counts next_subtree_counts = subtree_counts;
- next_subtree_counts.maxc /= m_parameters.get_max_elements();
- next_subtree_counts.minc /= m_parameters.get_max_elements();
+ next_subtree_counts.maxc /= parameters.get_max_elements();
+ next_subtree_counts.minc /= parameters.get_max_elements();
 
         // create new internal node
- node_pointer n = rtree::create_node<Allocators, internal_node>::apply(m_allocators); // MAY THROW (A)
+ node_pointer n = rtree::create_node<Allocators, internal_node>::apply(allocators); // MAY THROW (A)
         internal_node & in = rtree::get<internal_node>(*n);
         // reserve space for values
- rtree::elements(in).reserve(calculate_nodes_count(count, subtree_counts)); // MAY THROW (A)
+ std::size_t nodes_count = calculate_nodes_count(values_count, subtree_counts);
+ rtree::elements(in).reserve(nodes_count); // MAY THROW (A)
         // calculate values box and copy values
         Box elements_box;
         geometry::assign_inverse(elements_box);
 
- per_level_packets(first, last,
- hint_box,
- subtree_counts,
- next_subtree_counts,
- rtree::elements(in), elements_box);
+ per_level_packets(first, last, hint_box, values_count, subtree_counts, next_subtree_counts,
+ rtree::elements(in), elements_box,
+ parameters, translator, allocators);
 
         return internal_element(elements_box, n);
     }
 
- template <typename EIt>
- void per_level_packets(EIt first, EIt last,
- Box const& hint_box,
+ template <typename EIt> inline static
+ void per_level_packets(EIt first, EIt last, Box const& hint_box,
+ std::size_t values_count,
                            subtree_elements_counts const& subtree_counts,
                            subtree_elements_counts const& next_subtree_counts,
- internal_elements & elements, Box & elements_box)
+ internal_elements & elements, Box & elements_box,
+ parameters_type const& parameters, Translator const& translator, Allocators & allocators)
     {
- std::size_t values_count = last - first;
+ BOOST_ASSERT(first < last);
+ BOOST_ASSERT(last - first == values_count);
 
- BOOST_ASSERT_MSG( subtree_counts.minc <= values_count, "invalid min counter" );
+ BOOST_ASSERT_MSG( subtree_counts.minc <= values_count, "too small number of elements");
 
         // only one packet
         if ( values_count <= subtree_counts.maxc )
         {
             // the end, move to the next level
- internal_element el = per_level(first, last, hint_box, values_count, next_subtree_counts);
+ internal_element el = per_level(first, last, hint_box, values_count, next_subtree_counts,
+ parameters, translator, allocators);
             // this container should have memory allocated, reserve() called outside
             elements.push_back(el); // SHOULDN'T THROW (C)
             geometry::expand(elements_box, el.first);
             return;
         }
         
- EIt median = first + calculate_median_count(values_count, subtree_counts);
+ std::size_t median_count = calculate_median_count(values_count, subtree_counts);
+ EIt median = first + median_count;
 
         coordinate_type greatest_length;
         std::size_t greatest_dim_index = 0;
@@ -251,23 +266,33 @@
         pack_utils::partial_sort_and_half_boxes<0, dimension>
             ::apply(first, median, last, hint_box, left, right, greatest_dim_index);
         
- per_level_packets(first, median, left, subtree_counts, next_subtree_counts, elements, elements_box);
- per_level_packets(median, last, right, subtree_counts, next_subtree_counts, elements, elements_box);
+ per_level_packets(first, median, left,
+ median_count, subtree_counts, next_subtree_counts,
+ elements, elements_box,
+ parameters, translator, allocators);
+ per_level_packets(median, last, right,
+ values_count - median_count, subtree_counts, next_subtree_counts,
+ elements, elements_box,
+ parameters, translator, allocators);
     }
 
- subtree_elements_counts calculate_subtree_elements_counts(std::size_t elements_count)
+ inline static
+ subtree_elements_counts calculate_subtree_elements_counts(std::size_t elements_count, parameters_type const& parameters)
     {
+ (void)parameters;
+
         subtree_elements_counts res(1, 1);
 
- std::size_t smax = m_parameters.get_max_elements();
- for ( ; smax < elements_count ; smax *= m_parameters.get_max_elements() )
+ std::size_t smax = parameters.get_max_elements();
+ for ( ; smax < elements_count ; smax *= parameters.get_max_elements() )
             res.maxc = smax;
 
- res.minc = m_parameters.get_min_elements() * (res.maxc / m_parameters.get_max_elements());
+ res.minc = parameters.get_min_elements() * (res.maxc / parameters.get_max_elements());
 
         return res;
     }
 
+ inline static
     std::size_t calculate_nodes_count(std::size_t count,
                                       subtree_elements_counts const& subtree_counts)
     {
@@ -288,6 +313,7 @@
         return n;
     }
 
+ inline static
     std::size_t calculate_median_count(std::size_t count,
                                        subtree_elements_counts const& subtree_counts)
     {
@@ -327,10 +353,6 @@
 
         return median_count;
     }
-
- parameters_type const& m_parameters;
- Translator const& m_translator;
- Allocators & m_allocators;
 };
 
 }}}}} // namespace boost::geometry::index::detail::rtree


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk