From 5ceb8a3b2e43eb9749d709b5a918d433edcd2802 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Thu, 22 Jul 2021 22:29:02 +0200 Subject: [PATCH] [index] Rewrite predicate checks in query visitors. --- .../detail/rtree/visitors/distance_query.hpp | 165 ++++++++---------- .../detail/rtree/visitors/spatial_query.hpp | 28 ++- 2 files changed, 81 insertions(+), 112 deletions(-) diff --git a/include/boost/geometry/index/detail/rtree/visitors/distance_query.hpp b/include/boost/geometry/index/detail/rtree/visitors/distance_query.hpp index b7d119f10..43a943e20 100644 --- a/include/boost/geometry/index/detail/rtree/visitors/distance_query.hpp +++ b/include/boost/geometry/index/detail/rtree/visitors/distance_query.hpp @@ -84,11 +84,10 @@ public: inline distance_query_result(size_type k) : m_count(k) { - BOOST_GEOMETRY_INDEX_ASSERT(0 < m_count, "Number of neighbors should be greater than 0"); - m_neighbors.reserve(m_count); } + // NOTE: Do not call if max_count() == 0 inline void store(DistanceType const& distance, const Value * value_ptr) { if (m_neighbors.size() < m_count) @@ -109,6 +108,7 @@ public: } } + // NOTE: Do not call if max_count() == 0 inline bool ignore_branch(DistanceType const& distance) const { return m_neighbors.size() == m_count @@ -127,6 +127,11 @@ public: return m_neighbors.size(); } + size_type max_count() const + { + return m_count; + } + private: size_type m_count; neighbors_type m_neighbors; @@ -184,28 +189,29 @@ public: }; inline distance_query(parameters_type const& parameters, translator_type const& translator, Predicates const& pred) - : m_parameters(parameters), m_translator(translator) + : m_tr(translator) , m_pred(pred) , m_result(nearest_predicate_access::get(m_pred).count) , m_strategy(index::detail::get_strategy(parameters)) { - //m_branches.reserve(m_parameters.get_max_elements() * levels_count); ? + //m_branches.reserve(parameters.get_max_elements() * levels_count); ? } template size_type apply(node_pointer root, OutIter out_it) { + if (m_result.max_count() <= 0) + { + return 0; + } + m_level = 1; rtree::apply_visitor(*this, *root); for (;;) { - if (m_branches.empty()) - { - break; - } - - if (m_result.ignore_branch(m_branches.top().distance)) + if (m_branches.empty() + || m_result.ignore_branch(m_branches.top().distance)) { break; } @@ -226,30 +232,18 @@ public: // fill array of nodes meeting predicates for (auto const& p : rtree::elements(n)) { - // if current node meets predicates - // 0 - dummy value - if (! id::predicates_check(m_pred, 0, p.first, m_strategy)) - { - continue; - } + node_distance_type node_distance; // for distance predicate - // calculate node's distance(s) for distance predicate - node_distance_type node_distance; - // if distance isn't ok - move to the next node - if (! calculate_node_distance::apply(predicate(), p.first, - m_strategy, node_distance)) + // if current node meets predicates (0 is dummy value) + if (id::predicates_check(m_pred, 0, p.first, m_strategy) + // and if distance is ok + && calculate_node_distance::apply(predicate(), p.first, m_strategy, node_distance) + // and if current node is closer than the furthest neighbor + && ! m_result.ignore_branch(node_distance)) { - continue; + // add current node's data into the list + m_branches.push(branch_data(node_distance, m_level, p.second)); } - - // if current node is further than found neighbors - don't analyze it - if (m_result.ignore_branch(node_distance)) - { - continue; - } - - // add current node's data into the list - m_branches.push(branch_data(node_distance, m_level, p.second)); } } @@ -260,23 +254,16 @@ public: // search leaf for closest value meeting predicates for (auto const& v : rtree::elements(n)) { + value_distance_type value_distance; // for distance predicate + // if value meets predicates - if (! id::predicates_check(m_pred, v, m_translator(v), m_strategy)) + if (id::predicates_check(m_pred, v, m_tr(v), m_strategy) + // and if distance is ok + && calculate_value_distance::apply(predicate(), m_tr(v), m_strategy, value_distance)) { - continue; + // store value + m_result.store(value_distance, boost::addressof(v)); } - - // calculate values distance for distance predicate - value_distance_type value_distance; - // if distance is ok - if (! calculate_value_distance::apply(predicate(), m_translator(v), - m_strategy, value_distance)) - { - continue; - } - - // store value - m_result.store(value_distance, boost::addressof(v)); } } @@ -286,10 +273,10 @@ private: return nearest_predicate_access::get(m_pred); } - parameters_type const& m_parameters; - translator_type const& m_translator; + translator_type const& m_tr; Predicates m_pred; + distance_query_result m_result; priority_queue m_branches; size_type m_level; @@ -340,7 +327,7 @@ public: using neighbors_type = priority_dequeue; inline distance_query_incremental() - : m_translator(nullptr) + : m_tr(nullptr) // , m_pred() , m_neighbors_count(0) , m_neighbor_ptr(nullptr) @@ -348,7 +335,7 @@ public: {} inline distance_query_incremental(parameters_type const& params, translator_type const& translator, Predicates const& pred) - : m_translator(::boost::addressof(translator)) + : m_tr(::boost::addressof(translator)) , m_pred(pred) , m_neighbors_count(0) , m_neighbor_ptr(nullptr) @@ -407,8 +394,7 @@ public: BOOST_GEOMETRY_INDEX_ASSERT(m_neighbors_count + m_neighbors.size() <= max_count(), "unexpected neighbors count"); // if there is enough neighbors and there is no closer branch - if (m_neighbors_count + m_neighbors.size() == max_count() - && (m_neighbors.empty() || m_neighbors.bottom().first <= closest_branch.first)) + if (ignore_branch_or_value(closest_branch.first)) { m_branches.clear(); continue; @@ -444,30 +430,18 @@ public: // fill active branch list array of nodes meeting predicates for (auto const& p : rtree::elements(n)) { - // if current node doesn't meet predicates - // 0 - dummy value - if (! id::predicates_check(m_pred, 0, p.first, m_strategy)) - { - continue; - } + node_distance_type node_distance; // for distance predicate - // calculate node's distance(s) for distance predicate - node_distance_type node_distance; - // if distance isn't ok - if (! calculate_node_distance::apply(predicate(), p.first, m_strategy, node_distance)) + // if current node meets predicates (0 is dummy value) + if (id::predicates_check(m_pred, 0, p.first, m_strategy) + // and if distance is ok + && calculate_node_distance::apply(predicate(), p.first, m_strategy, node_distance) + // and if current node is closer than the furthest neighbor + && ! ignore_branch_or_value(node_distance)) { - continue; + // add current node into the queue + m_branches.push(std::make_pair(node_distance, p.second)); } - - // if there is enough neighbors and there is no closer branch - if (m_neighbors_count + m_neighbors.size() == max_count() - && (m_neighbors.empty() || m_neighbors.bottom().first <= node_distance)) - { - continue; - } - - // add current node into the queue - m_branches.push(std::make_pair(node_distance, p.second)); } } @@ -481,38 +455,35 @@ public: // search leaf for closest value meeting predicates for (auto const& v : rtree::elements(n)) { - // if value doesn't meet predicates - if (! id::predicates_check(m_pred, v, (*m_translator)(v), m_strategy)) - { - continue; - } - - // calculate values distance for distance predicate - value_distance_type value_distance; - // if distance isn't ok - if (! calculate_value_distance::apply(predicate(), (*m_translator)(v), - m_strategy, value_distance)) - { - continue; - } + value_distance_type value_distance; // for distance predicate - // if there is enough neighbors and there is no closer neighbor - if (m_neighbors_count + m_neighbors.size() == max_count() - && (m_neighbors.empty() || m_neighbors.bottom().first <= value_distance)) + // if value meets predicates + if (id::predicates_check(m_pred, v, (*m_tr)(v), m_strategy) + // and if distance is ok + && calculate_value_distance::apply(predicate(), (*m_tr)(v), m_strategy, value_distance) + // and if current value is closer than the furthest neighbor + && ! ignore_branch_or_value(value_distance)) { - continue; - } + // add current value into the queue + m_neighbors.push(std::make_pair(value_distance, boost::addressof(v))); - // add current value into the queue - m_neighbors.push(std::make_pair(value_distance, boost::addressof(v))); - if (m_neighbors_count + m_neighbors.size() > max_count()) - { - m_neighbors.pop_bottom(); + // remove unneeded value + if (m_neighbors_count + m_neighbors.size() > max_count()) + { + m_neighbors.pop_bottom(); + } } } } private: + template + inline bool ignore_branch_or_value(Distance const& distance) + { + return m_neighbors_count + m_neighbors.size() == max_count() + && (m_neighbors.empty() || m_neighbors.bottom().first <= distance); + } + inline std::size_t max_count() const { return nearest_predicate_access::get(m_pred).count; @@ -523,7 +494,7 @@ private: return nearest_predicate_access::get(m_pred); } - const translator_type * m_translator; + const translator_type * m_tr; Predicates m_pred; diff --git a/include/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp b/include/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp index 77ce05ce9..64d7585bf 100644 --- a/include/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp +++ b/include/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp @@ -39,7 +39,7 @@ struct spatial_query typedef typename allocators_type::size_type size_type; inline spatial_query(parameters_type const& par, translator_type const& t, Predicates const& p, OutIter out_it) - : tr(t), pred(p), out_iter(out_it), found_count(0), strategy(index::detail::get_strategy(par)) + : m_tr(t), m_pred(p), m_out_iter(out_it), m_found_count(0), m_strategy(index::detail::get_strategy(par)) {} size_type apply(node_pointer root) @@ -58,7 +58,7 @@ struct spatial_query rtree::apply_visitor(*this, *ptr); } - return found_count; + return m_found_count; } inline void operator()(internal_node const& n) @@ -68,9 +68,8 @@ struct spatial_query // traverse nodes meeting predicates for (auto const& p : rtree::elements(n)) { - // if node meets predicates - // 0 - dummy value - if (id::predicates_check(pred, 0, p.first, strategy)) + // if node meets predicates (0 is dummy value) + if (id::predicates_check(m_pred, 0, p.first, m_strategy)) { m_internal_stack.push_back(p.second); } @@ -85,27 +84,26 @@ struct spatial_query for (auto const& v : rtree::elements(n)) { // if value meets predicates - if (id::predicates_check(pred, v, tr(v), strategy)) + if (id::predicates_check(m_pred, v, m_tr(v), m_strategy)) { - *out_iter = v; - ++out_iter; - - ++found_count; + *m_out_iter = v; + ++m_out_iter; + ++m_found_count; } } } private: - translator_type const& tr; + translator_type const& m_tr; - Predicates pred; + Predicates m_pred; std::vector m_internal_stack; - OutIter out_iter; - size_type found_count; + OutIter m_out_iter; + size_type m_found_count; - strategy_type strategy; + strategy_type m_strategy; }; template