|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r84029 - trunk/boost/geometry/index/detail/rtree/visitors
From: adam.wulkiewicz_at_[hidden]
Date: 2013-04-24 07:22:37
Author: awulkiew
Date: 2013-04-24 07:22:36 EDT (Wed, 24 Apr 2013)
New Revision: 84029
URL: http://svn.boost.org/trac/boost/changeset/84029
Log:
geometry.index: experimental nearest iterative visitor optimized (different data structures, less complex algorithm).
Text files modified:
trunk/boost/geometry/index/detail/rtree/visitors/nearest_query.hpp | 96 ++++++++++++++++++++++++++++-----------
1 files changed, 69 insertions(+), 27 deletions(-)
Modified: trunk/boost/geometry/index/detail/rtree/visitors/nearest_query.hpp
==============================================================================
--- trunk/boost/geometry/index/detail/rtree/visitors/nearest_query.hpp (original)
+++ trunk/boost/geometry/index/detail/rtree/visitors/nearest_query.hpp 2013-04-24 07:22:36 EDT (Wed, 24 Apr 2013)
@@ -353,6 +353,7 @@
typedef index::detail::distances_calc<distance_predicates_type, Box, index::detail::bounds_tag> node_distances_calc;
typedef typename node_distances_calc::result_type node_distances_type;
typedef index::detail::distances_predicates_check<distance_predicates_type, Box, index::detail::bounds_tag> node_distances_predicates_check;
+ typedef typename index::detail::cdist_value<node_distances_type>::type node_distance_type;
typedef index::detail::distances_calc<
distance_predicates_type,
@@ -369,15 +370,26 @@
typedef typename Allocators::size_type size_type;
typedef typename Allocators::node_pointer node_pointer;
- typedef typename rtree::elements_type<internal_node>::type::const_iterator internal_iterator;
+ static const unsigned predicates_len = index::detail::predicates_length<Predicates>::value;
+
+ typedef typename rtree::elements_type<internal_node>::type internal_elements;
+ typedef typename internal_elements::const_iterator internal_iterator;
typedef typename rtree::elements_type<leaf>::type leaf_elements;
- static const unsigned predicates_len = index::detail::predicates_length<Predicates>::value;
+ typedef std::pair<node_distances_type, node_pointer> branch_data;
+ typedef typename index::detail::rtree::container_from_elements_type<
+ internal_elements, branch_data
+ >::type active_branch_list_type;
+ typedef std::vector<
+ std::pair<active_branch_list_type, typename active_branch_list_type::size_type>
+ > internal_stack_type;
inline nearest_query_incremental(Translator const& translator, Predicates const& pred)
: m_translator(translator)
, m_pred(pred)
, current_neighbor(std::numeric_limits<size_type>::max())
+
+ , next_closest_node_distance(std::numeric_limits<node_distance_type>::max())
{
BOOST_ASSERT_MSG(0 < max_count(), "k must be greather than 0");
}
@@ -393,7 +405,7 @@
{
size_type new_neighbor = current_neighbor == std::numeric_limits<size_type>::max() ? 0 : current_neighbor + 1;
- if ( active_branch_list.empty() )
+ if ( internal_stack.empty() )
{
if ( new_neighbor < neighbors.size() )
current_neighbor = new_neighbor;
@@ -408,28 +420,41 @@
}
else
{
+ active_branch_list_type & branches = internal_stack.back().first;
+ typename active_branch_list_type::size_type & current_branch = internal_stack.back().second;
+
+ if ( branches.size() <= current_branch )
+ {
+ internal_stack.pop_back();
+ continue;
+ }
+
// if there are no nodes which can have closer values, set new value
if ( new_neighbor < neighbors.size() &&
- is_node_further(neighbors[new_neighbor].first, active_branch_list.front().first) )
+ // here must be < because otherwise neighbours may be sorted in different order
+ // if there is another value with equal distance
+ neighbors[new_neighbor].first < next_closest_node_distance )
{
current_neighbor = new_neighbor;
return;
}
- std::pair<node_distances_type, node_pointer> active_branch = active_branch_list.front();
- active_branch_list.pop_front();
- rtree::apply_visitor(*this, *(active_branch.second));
-
- // remove nodes further than the furthest neighbour - not really needed
+ // if node is further than the furthest neighbour, following nodes also will be further
BOOST_ASSERT_MSG(neighbors.size() <= max_count(), "unexpected neighbours count");
- if ( max_count() <= neighbors.size() )
+ if ( max_count() <= neighbors.size() &&
+ is_node_prunable(neighbors.back().first, branches[current_branch].first) )
{
- // prune nodes which mindists are further than furthest value's dist
- while ( !active_branch_list.empty() &&
- is_node_prunable(neighbors.back().first, active_branch_list.back().first) )
- {
- active_branch_list.pop_back();
- }
+ // stop traversing current level
+ internal_stack.pop_back();
+ continue;
+ }
+ else
+ {
+ // new level - must increment current_branch before traversing of another level (mem reallocation)
+ ++current_branch;
+ rtree::apply_visitor(*this, *(branches[current_branch - 1].second));
+
+ next_closest_node_distance = calc_closest_node_distance(internal_stack.begin(), internal_stack.end());
}
}
}
@@ -452,6 +477,8 @@
typedef typename rtree::elements_type<internal_node>::type elements_type;
elements_type const& elements = rtree::elements(n);
+ internal_stack.push_back(std::make_pair(active_branch_list_type(), 0));
+
// fill active branch list array of nodes meeting predicates
for ( typename elements_type::const_iterator it = elements.begin() ; it != elements.end() ; ++it )
{
@@ -473,13 +500,16 @@
if ( node_distances_predicates_check::apply(dist_pred(), node_dist_data) )
{
// add current node's data into the list
- active_branch_list.push_front( std::make_pair(node_dist_data, it->second) );
+ internal_stack.back().first.push_back( std::make_pair(node_dist_data, it->second) );
}
}
}
- // sort array
- std::sort(active_branch_list.begin(), active_branch_list.end(), abl_less);
+ if ( internal_stack.back().first.empty() )
+ internal_stack.pop_back();
+ else
+ // sort array
+ std::sort(internal_stack.back().first.begin(), internal_stack.back().first.end(), abl_less);
}
// Put values into the list of neighbours if those values meets predicates
@@ -543,18 +573,29 @@
return p1.first < p2.first;
}
- template <typename Distance>
- static inline bool is_node_prunable(Distance const& greatest_dist, node_distances_type const& d)
+ node_distance_type
+ calc_closest_node_distance(typename internal_stack_type::const_iterator first,
+ typename internal_stack_type::const_iterator last)
{
- return greatest_dist <= index::detail::cdist_value<node_distances_type>
- ::template get<index::detail::to_nearest_tag>(d);
+ node_distance_type result = std::numeric_limits<node_distance_type>::max();
+ for ( ; first != last ; ++first )
+ {
+ if ( first->first.size() <= first->second )
+ continue;
+
+ node_distance_type curr_dist = index::detail::cdist_value<node_distances_type>
+ ::template get<index::detail::to_nearest_tag>(first->first[first->second].first);
+ if ( curr_dist < result )
+ result = curr_dist;
+ }
+ return result;
}
template <typename Distance>
- static inline bool is_node_further(Distance const& dist, node_distances_type const& d)
+ static inline bool is_node_prunable(Distance const& greatest_dist, node_distances_type const& d)
{
- return dist <= index::detail::cdist_value<node_distances_type>
- ::template get<index::detail::to_nearest_tag>(d);
+ return greatest_dist <= index::detail::cdist_value<node_distances_type>
+ ::template get<index::detail::to_nearest_tag>(d);
}
inline distance_predicates_type const& dist_pred() const
@@ -571,9 +612,10 @@
Predicates m_pred;
- std::deque< std::pair<node_distances_type, node_pointer> > active_branch_list;
+ internal_stack_type internal_stack;
std::vector< std::pair<value_distance_type, const Value *> > neighbors;
size_type current_neighbor;
+ node_distance_type next_closest_node_distance;
};
} // namespace visitors
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