Added thirdparty: boost library

This commit is contained in:
Viacheslav Demydiuk
2024-01-06 19:55:56 +02:00
parent bf49f439e1
commit bccd1e7051
15683 changed files with 3239840 additions and 0 deletions
@@ -0,0 +1,72 @@
// Boost.Geometry Index
//
// R-tree node children box calculating visitor implementation
//
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
//
// This file was modified by Oracle on 2019-2023.
// Modifications copyright (c) 2019-2023 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// 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_INDEX_DETAIL_RTREE_VISITORS_CHILDREN_BOX_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_CHILDREN_BOX_HPP
#include <boost/geometry/index/detail/rtree/node/node.hpp>
#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree { namespace visitors {
template <typename MembersHolder>
class children_box
: public MembersHolder::visitor_const
{
typedef typename MembersHolder::parameters_type parameters_type;
typedef typename MembersHolder::translator_type translator_type;
typedef typename MembersHolder::box_type box_type;
typedef typename MembersHolder::internal_node internal_node;
typedef typename MembersHolder::leaf leaf;
public:
inline children_box(box_type & result,
parameters_type const& parameters,
translator_type const& tr)
: m_result(result), m_parameters(parameters), m_tr(tr)
{}
inline void operator()(internal_node const& n)
{
typedef typename rtree::elements_type<internal_node>::type elements_type;
elements_type const& elements = rtree::elements(n);
m_result = rtree::elements_box<box_type>(elements.begin(), elements.end(), m_tr,
index::detail::get_strategy(m_parameters));
}
inline void operator()(leaf const& n)
{
typedef typename rtree::elements_type<leaf>::type elements_type;
elements_type const& elements = rtree::elements(n);
m_result = rtree::values_box<box_type>(elements.begin(), elements.end(), m_tr,
index::detail::get_strategy(m_parameters));
}
private:
box_type & m_result;
parameters_type const& m_parameters;
translator_type const& m_tr;
};
}}} // namespace detail::rtree::visitors
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_CHILDREN_BOX_HPP
+100
View File
@@ -0,0 +1,100 @@
// Boost.Geometry Index
//
// R-tree deep copying visitor implementation
//
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
//
// This file was modified by Oracle on 2019.
// Modifications copyright (c) 2019 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// 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_INDEX_DETAIL_RTREE_VISITORS_COPY_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_COPY_HPP
#include <boost/geometry/index/detail/rtree/node/subtree_destroyer.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree { namespace visitors {
template <typename MembersHolder>
class copy
: public MembersHolder::visitor
{
typedef typename MembersHolder::allocators_type allocators_type;
typedef typename MembersHolder::node node;
typedef typename MembersHolder::internal_node internal_node;
typedef typename MembersHolder::leaf leaf;
typedef rtree::subtree_destroyer<MembersHolder> subtree_destroyer;
typedef typename allocators_type::node_pointer node_pointer;
public:
explicit inline copy(allocators_type & allocators)
: result(0)
, m_allocators(allocators)
{}
inline void operator()(internal_node & n)
{
node_pointer raw_new_node = rtree::create_node<allocators_type, internal_node>::apply(m_allocators); // MAY THROW, STRONG (N: alloc)
subtree_destroyer new_node(raw_new_node, m_allocators);
typedef typename rtree::elements_type<internal_node>::type elements_type;
elements_type & elements = rtree::elements(n);
elements_type & elements_dst = rtree::elements(rtree::get<internal_node>(*new_node));
for (typename elements_type::iterator it = elements.begin();
it != elements.end(); ++it)
{
rtree::apply_visitor(*this, *it->second); // MAY THROW (V, E: alloc, copy, N: alloc)
// for exception safety
subtree_destroyer auto_result(result, m_allocators);
elements_dst.push_back( rtree::make_ptr_pair(it->first, result) ); // MAY THROW, STRONG (E: alloc, copy)
auto_result.release();
}
result = new_node.get();
new_node.release();
}
inline void operator()(leaf & l)
{
node_pointer raw_new_node = rtree::create_node<allocators_type, leaf>::apply(m_allocators); // MAY THROW, STRONG (N: alloc)
subtree_destroyer new_node(raw_new_node, m_allocators);
typedef typename rtree::elements_type<leaf>::type elements_type;
elements_type & elements = rtree::elements(l);
elements_type & elements_dst = rtree::elements(rtree::get<leaf>(*new_node));
for (typename elements_type::iterator it = elements.begin();
it != elements.end(); ++it)
{
elements_dst.push_back(*it); // MAY THROW, STRONG (V: alloc, copy)
}
result = new_node.get();
new_node.release();
}
node_pointer result;
private:
allocators_type & m_allocators;
};
}}} // namespace detail::rtree::visitors
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_COPY_HPP
+123
View File
@@ -0,0 +1,123 @@
// Boost.Geometry Index
//
// R-tree count visitor implementation
//
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
//
// This file was modified by Oracle on 2019-2023.
// Modifications copyright (c) 2019-2023 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// 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_INDEX_DETAIL_RTREE_VISITORS_COUNT_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_COUNT_HPP
#include <boost/geometry/index/equal_to.hpp>
#include <boost/geometry/index/detail/algorithms/bounds.hpp>
#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
#include <boost/geometry/index/detail/rtree/node/variant_visitor.hpp>
#include <boost/geometry/index/parameters.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree { namespace visitors {
template <typename Indexable, typename Value>
struct count_helper
{
template <typename Translator>
static inline typename Translator::result_type indexable(Indexable const& i, Translator const&)
{
return i;
}
template <typename Translator, typename Strategy>
static inline bool equals(Indexable const& i, Value const& v, Translator const& tr, Strategy const& s)
{
return index::detail::equals<Indexable>::apply(i, tr(v), s);
}
};
template <typename Value>
struct count_helper<Value, Value>
{
template <typename Translator>
static inline typename Translator::result_type indexable(Value const& v, Translator const& tr)
{
return tr(v);
}
template <typename Translator, typename Strategy>
static inline bool equals(Value const& v1, Value const& v2, Translator const& tr, Strategy const& s)
{
return tr.equals(v1, v2, s);
}
};
template <typename ValueOrIndexable, typename MembersHolder>
struct count
: public MembersHolder::visitor_const
{
typedef typename MembersHolder::value_type value_type;
typedef typename MembersHolder::parameters_type parameters_type;
typedef typename MembersHolder::translator_type translator_type;
typedef typename MembersHolder::node node;
typedef typename MembersHolder::internal_node internal_node;
typedef typename MembersHolder::leaf leaf;
typedef count_helper<ValueOrIndexable, value_type> count_help;
inline count(ValueOrIndexable const& vori, parameters_type const& parameters, translator_type const& t)
: value_or_indexable(vori), m_parameters(parameters), tr(t), found_count(0)
{}
inline void operator()(internal_node const& n)
{
typedef typename rtree::elements_type<internal_node>::type elements_type;
elements_type const& elements = rtree::elements(n);
// traverse nodes meeting predicates
for (typename elements_type::const_iterator it = elements.begin();
it != elements.end(); ++it)
{
if ( index::detail::covered_by_bounds(count_help::indexable(value_or_indexable, tr),
it->first,
index::detail::get_strategy(m_parameters)) )
{
rtree::apply_visitor(*this, *it->second);
}
}
}
inline void operator()(leaf const& n)
{
typedef typename rtree::elements_type<leaf>::type elements_type;
elements_type const& elements = rtree::elements(n);
// get all values meeting predicates
for (typename elements_type::const_iterator it = elements.begin();
it != elements.end(); ++it)
{
// if value meets predicates
if ( count_help::equals(value_or_indexable, *it, tr,
index::detail::get_strategy(m_parameters)) )
{
++found_count;
}
}
}
ValueOrIndexable const& value_or_indexable;
parameters_type const& m_parameters;
translator_type const& tr;
typename MembersHolder::size_type found_count;
};
}}} // namespace detail::rtree::visitors
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_COUNT_HPP
@@ -0,0 +1,87 @@
// Boost.Geometry Index
//
// R-tree destroying visitor implementation
//
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
//
// This file was modified by Oracle on 2019-2023.
// Modifications copyright (c) 2019-2023 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// 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_INDEX_DETAIL_RTREE_VISITORS_DELETE_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DELETE_HPP
#include <boost/geometry/index/detail/rtree/node/concept.hpp>
#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
#include <boost/geometry/index/detail/rtree/node/weak_visitor.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree { namespace visitors {
template <typename MembersHolder>
class destroy
: public MembersHolder::visitor
{
public:
typedef typename MembersHolder::node node;
typedef typename MembersHolder::internal_node internal_node;
typedef typename MembersHolder::leaf leaf;
typedef typename MembersHolder::allocators_type allocators_type;
typedef typename MembersHolder::node_pointer node_pointer;
inline destroy(node_pointer node, allocators_type & allocators)
: m_current_node(node)
, m_allocators(allocators)
{}
inline void operator()(internal_node & n)
{
BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<internal_node>(*m_current_node), "invalid pointers");
node_pointer node_to_destroy = m_current_node;
typedef typename rtree::elements_type<internal_node>::type elements_type;
elements_type & elements = rtree::elements(n);
for (typename elements_type::iterator it = elements.begin();
it != elements.end(); ++it)
{
m_current_node = it->second;
rtree::apply_visitor(*this, *m_current_node);
it->second = 0;
}
rtree::destroy_node<allocators_type, internal_node>::apply(m_allocators, node_to_destroy);
}
inline void operator()(leaf & l)
{
boost::ignore_unused(l);
BOOST_GEOMETRY_INDEX_ASSERT(&l == &rtree::get<leaf>(*m_current_node), "invalid pointers");
rtree::destroy_node<allocators_type, leaf>::apply(m_allocators, m_current_node);
}
static inline void apply(node_pointer node, allocators_type & allocators)
{
destroy v(node, allocators);
rtree::apply_visitor(v, *node);
}
private:
node_pointer m_current_node;
allocators_type & m_allocators;
};
}}} // namespace detail::rtree::visitors
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DELETE_HPP
@@ -0,0 +1,576 @@
// Boost.Geometry Index
//
// R-tree distance (knn, path, etc. ) query visitor implementation
//
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
//
// This file was modified by Oracle on 2019-2023.
// Modifications copyright (c) 2019-2023 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// 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_INDEX_DETAIL_RTREE_VISITORS_DISTANCE_QUERY_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DISTANCE_QUERY_HPP
#include <queue>
#include <boost/geometry/index/detail/distance_predicates.hpp>
#include <boost/geometry/index/detail/predicates.hpp>
#include <boost/geometry/index/detail/priority_dequeue.hpp>
#include <boost/geometry/index/detail/rtree/node/weak_visitor.hpp>
#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
#include <boost/geometry/index/detail/translator.hpp>
#include <boost/geometry/index/parameters.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree { namespace visitors {
struct pair_first_less
{
template <typename First, typename Second>
inline bool operator()(std::pair<First, Second> const& p1,
std::pair<First, Second> const& p2) const
{
return p1.first < p2.first;
}
};
struct pair_first_greater
{
template <typename First, typename Second>
inline bool operator()(std::pair<First, Second> const& p1,
std::pair<First, Second> const& p2) const
{
return p1.first > p2.first;
}
};
template <typename T, typename Comp>
struct priority_dequeue : index::detail::priority_dequeue<T, std::vector<T>, Comp>
{
priority_dequeue() = default;
//void reserve(typename std::vector<T>::size_type n)
//{
// this->c.reserve(n);
//}
//void clear()
//{
// this->c.clear();
//}
};
template <typename T, typename Comp>
struct priority_queue : std::priority_queue<T, std::vector<T>, Comp>
{
priority_queue() = default;
//void reserve(typename std::vector<T>::size_type n)
//{
// this->c.reserve(n);
//}
void clear()
{
this->c.clear();
}
};
struct branch_data_comp
{
template <typename BranchData>
bool operator()(BranchData const& b1, BranchData const& b2) const
{
return b1.distance > b2.distance || (b1.distance == b2.distance && b1.reverse_level > b2.reverse_level);
}
};
template <typename DistanceType, typename Value>
class distance_query_result
{
using neighbor_data = std::pair<DistanceType, const Value *>;
using neighbors_type = std::vector<neighbor_data>;
using size_type = typename neighbors_type::size_type;
public:
inline distance_query_result(size_type k)
: m_count(k)
{
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)
{
m_neighbors.push_back(std::make_pair(distance, value_ptr));
if (m_neighbors.size() == m_count)
{
std::make_heap(m_neighbors.begin(), m_neighbors.end(), pair_first_less());
}
}
else if (distance < m_neighbors.front().first)
{
std::pop_heap(m_neighbors.begin(), m_neighbors.end(), pair_first_less());
m_neighbors.back().first = distance;
m_neighbors.back().second = value_ptr;
std::push_heap(m_neighbors.begin(), m_neighbors.end(), pair_first_less());
}
}
// NOTE: Do not call if max_count() == 0
inline bool ignore_branch(DistanceType const& distance) const
{
return m_neighbors.size() == m_count
&& m_neighbors.front().first <= distance;
}
template <typename OutIt>
inline size_type finish(OutIt out_it) const
{
for (auto const& p : m_neighbors)
{
*out_it = *(p.second);
++out_it;
}
return m_neighbors.size();
}
size_type max_count() const
{
return m_count;
}
private:
size_type m_count;
neighbors_type m_neighbors;
};
template <typename MembersHolder, typename Predicates>
class distance_query
{
typedef typename MembersHolder::value_type value_type;
typedef typename MembersHolder::box_type box_type;
typedef typename MembersHolder::parameters_type parameters_type;
typedef typename MembersHolder::translator_type translator_type;
typedef typename index::detail::strategy_type<parameters_type>::type strategy_type;
typedef typename MembersHolder::node node;
typedef typename MembersHolder::internal_node internal_node;
typedef typename MembersHolder::leaf leaf;
typedef index::detail::predicates_element
<
index::detail::predicates_find_distance<Predicates>::value, Predicates
> nearest_predicate_access;
typedef typename nearest_predicate_access::type nearest_predicate_type;
typedef typename indexable_type<translator_type>::type indexable_type;
typedef index::detail::calculate_distance<nearest_predicate_type, indexable_type, strategy_type, value_tag> calculate_value_distance;
typedef index::detail::calculate_distance<nearest_predicate_type, box_type, strategy_type, bounds_tag> calculate_node_distance;
typedef typename calculate_value_distance::result_type value_distance_type;
typedef typename calculate_node_distance::result_type node_distance_type;
typedef typename MembersHolder::size_type size_type;
typedef typename MembersHolder::node_pointer node_pointer;
using neighbor_data = std::pair<value_distance_type, const value_type *>;
using neighbors_type = std::vector<neighbor_data>;
struct branch_data
{
branch_data(node_distance_type d, size_type rl, node_pointer p)
: distance(d), reverse_level(rl), ptr(p)
{}
node_distance_type distance;
size_type reverse_level;
node_pointer ptr;
};
using branches_type = priority_queue<branch_data, branch_data_comp>;
public:
distance_query(MembersHolder const& members, Predicates const& pred)
: m_tr(members.translator())
, m_strategy(index::detail::get_strategy(members.parameters()))
, m_pred(pred)
{
m_neighbors.reserve((std::min)(members.values_count, size_type(max_count())));
//m_branches.reserve(members.parameters().get_min_elements() * members.leafs_level); ?
// min, max or average?
}
template <typename OutIter>
size_type apply(MembersHolder const& members, OutIter out_it)
{
return apply(members.root, members.leafs_level, out_it);
}
private:
template <typename OutIter>
size_type apply(node_pointer ptr, size_type reverse_level, OutIter out_it)
{
namespace id = index::detail;
if (max_count() <= 0)
{
return 0;
}
for (;;)
{
if (reverse_level > 0)
{
internal_node& n = rtree::get<internal_node>(*ptr);
// fill array of nodes meeting predicates
for (auto const& p : rtree::elements(n))
{
node_distance_type node_distance; // for distance predicate
// if current node meets predicates (0 is dummy value)
if (id::predicates_check<id::bounds_tag>(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(node_distance))
{
// add current node's data into the list
m_branches.push(branch_data(node_distance, reverse_level - 1, p.second));
}
}
}
else
{
leaf& n = rtree::get<leaf>(*ptr);
// 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<id::value_tag>(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))
{
// store value
store_value(value_distance, boost::addressof(v));
}
}
}
if (m_branches.empty()
|| ignore_branch(m_branches.top().distance))
{
break;
}
ptr = m_branches.top().ptr;
reverse_level = m_branches.top().reverse_level;
m_branches.pop();
}
for (auto const& p : m_neighbors)
{
*out_it = *(p.second);
++out_it;
}
return m_neighbors.size();
}
bool ignore_branch(node_distance_type const& node_distance) const
{
return m_neighbors.size() == max_count()
&& m_neighbors.front().first <= node_distance;
}
void store_value(value_distance_type value_distance, const value_type * value_ptr)
{
if (m_neighbors.size() < max_count())
{
m_neighbors.push_back(std::make_pair(value_distance, value_ptr));
if (m_neighbors.size() == max_count())
{
std::make_heap(m_neighbors.begin(), m_neighbors.end(), pair_first_less());
}
}
else if (value_distance < m_neighbors.front().first)
{
std::pop_heap(m_neighbors.begin(), m_neighbors.end(), pair_first_less());
m_neighbors.back() = std::make_pair(value_distance, value_ptr);
std::push_heap(m_neighbors.begin(), m_neighbors.end(), pair_first_less());
}
}
std::size_t max_count() const
{
return nearest_predicate_access::get(m_pred).count;
}
nearest_predicate_type const& predicate() const
{
return nearest_predicate_access::get(m_pred);
}
translator_type const& m_tr;
strategy_type m_strategy;
Predicates const& m_pred;
branches_type m_branches;
neighbors_type m_neighbors;
};
template <typename MembersHolder, typename Predicates>
class distance_query_incremental
{
typedef typename MembersHolder::value_type value_type;
typedef typename MembersHolder::box_type box_type;
typedef typename MembersHolder::parameters_type parameters_type;
typedef typename MembersHolder::translator_type translator_type;
typedef typename MembersHolder::allocators_type allocators_type;
typedef typename index::detail::strategy_type<parameters_type>::type strategy_type;
typedef typename MembersHolder::node node;
typedef typename MembersHolder::internal_node internal_node;
typedef typename MembersHolder::leaf leaf;
typedef index::detail::predicates_element
<
index::detail::predicates_find_distance<Predicates>::value, Predicates
> nearest_predicate_access;
typedef typename nearest_predicate_access::type nearest_predicate_type;
typedef typename indexable_type<translator_type>::type indexable_type;
typedef index::detail::calculate_distance<nearest_predicate_type, indexable_type, strategy_type, value_tag> calculate_value_distance;
typedef index::detail::calculate_distance<nearest_predicate_type, box_type, strategy_type, bounds_tag> calculate_node_distance;
typedef typename calculate_value_distance::result_type value_distance_type;
typedef typename calculate_node_distance::result_type node_distance_type;
typedef typename allocators_type::size_type size_type;
typedef typename allocators_type::const_reference const_reference;
typedef typename allocators_type::node_pointer node_pointer;
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;
using neighbor_data = std::pair<value_distance_type, const value_type *>;
using neighbors_type = priority_dequeue<neighbor_data, pair_first_greater>;
struct branch_data
{
branch_data(node_distance_type d, size_type rl, node_pointer p)
: distance(d), reverse_level(rl), ptr(p)
{}
node_distance_type distance;
size_type reverse_level;
node_pointer ptr;
};
using branches_type = priority_queue<branch_data, branch_data_comp>;
public:
inline distance_query_incremental()
: m_tr(nullptr)
// , m_strategy()
// , m_pred()
, m_neighbors_count(0)
, m_neighbor_ptr(nullptr)
{}
inline distance_query_incremental(Predicates const& pred)
: m_tr(nullptr)
// , m_strategy()
, m_pred(pred)
, m_neighbors_count(0)
, m_neighbor_ptr(nullptr)
{}
inline distance_query_incremental(MembersHolder const& members, Predicates const& pred)
: m_tr(::boost::addressof(members.translator()))
, m_strategy(index::detail::get_strategy(members.parameters()))
, m_pred(pred)
, m_neighbors_count(0)
, m_neighbor_ptr(nullptr)
{}
const_reference dereference() const
{
return *m_neighbor_ptr;
}
void initialize(MembersHolder const& members)
{
if (0 < max_count())
{
apply(members.root, members.leafs_level);
increment();
}
}
void increment()
{
for (;;)
{
if (m_branches.empty())
{
// there exists a next closest neighbor so we can increment
if (! m_neighbors.empty())
{
m_neighbor_ptr = m_neighbors.top().second;
++m_neighbors_count;
m_neighbors.pop_top();
}
else
{
// there aren't any neighbors left, end
m_neighbor_ptr = nullptr;
m_neighbors_count = max_count();
}
return;
}
else
{
branch_data const& closest_branch = m_branches.top();
// if next neighbor is closer or as close as the closest branch, set next neighbor
if (! m_neighbors.empty() && m_neighbors.top().first <= closest_branch.distance )
{
m_neighbor_ptr = m_neighbors.top().second;
++m_neighbors_count;
m_neighbors.pop_top();
return;
}
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 (ignore_branch_or_value(closest_branch.distance))
{
m_branches.clear();
continue;
}
else
{
node_pointer ptr = closest_branch.ptr;
size_type reverse_level = closest_branch.reverse_level;
m_branches.pop();
apply(ptr, reverse_level);
}
}
}
}
bool is_end() const
{
return m_neighbor_ptr == nullptr;
}
friend bool operator==(distance_query_incremental const& l, distance_query_incremental const& r)
{
return l.m_neighbors_count == r.m_neighbors_count;
}
private:
void apply(node_pointer ptr, size_type reverse_level)
{
namespace id = index::detail;
// Put node's elements into the list of active branches if those elements meets predicates
// and distance predicates(currently not used)
// and aren't further than found neighbours (if there is enough neighbours)
if (reverse_level > 0)
{
internal_node& n = rtree::get<internal_node>(*ptr);
// fill active branch list array of nodes meeting predicates
for (auto const& p : rtree::elements(n))
{
node_distance_type node_distance; // for distance predicate
// if current node meets predicates (0 is dummy value)
if (id::predicates_check<id::bounds_tag>(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))
{
// add current node into the queue
m_branches.push(branch_data(node_distance, reverse_level - 1, p.second));
}
}
}
// Put values into the list of neighbours if those values meets predicates
// and distance predicates(currently not used)
// and aren't further than already found neighbours (if there is enough neighbours)
else
{
leaf& n = rtree::get<leaf>(*ptr);
// 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<id::value_tag>(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))
{
// add current value into the queue
m_neighbors.push(std::make_pair(value_distance, boost::addressof(v)));
// remove unneeded value
if (m_neighbors_count + m_neighbors.size() > max_count())
{
m_neighbors.pop_bottom();
}
}
}
}
}
template <typename Distance>
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);
}
std::size_t max_count() const
{
return nearest_predicate_access::get(m_pred).count;
}
nearest_predicate_type const& predicate() const
{
return nearest_predicate_access::get(m_pred);
}
const translator_type * m_tr;
strategy_type m_strategy;
Predicates m_pred;
branches_type m_branches;
neighbors_type m_neighbors;
size_type m_neighbors_count;
const value_type * m_neighbor_ptr;
};
}}} // namespace detail::rtree::visitors
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DISTANCE_QUERY_HPP
+636
View File
@@ -0,0 +1,636 @@
// Boost.Geometry Index
//
// R-tree inserting visitor implementation
//
// Copyright (c) 2011-2023 Adam Wulkiewicz, Lodz, Poland.
//
// This file was modified by Oracle on 2019-2023.
// Modifications copyright (c) 2019-2023 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// 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_INDEX_DETAIL_RTREE_VISITORS_INSERT_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_INSERT_HPP
#ifdef BOOST_GEOMETRY_INDEX_EXPERIMENTAL_ENLARGE_BY_EPSILON
#include <type_traits>
#endif
#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/index/detail/algorithms/bounds.hpp>
#include <boost/geometry/index/detail/algorithms/content.hpp>
#include <boost/geometry/index/detail/rtree/node/node.hpp>
#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
#include <boost/geometry/index/detail/rtree/node/subtree_destroyer.hpp>
#include <boost/geometry/index/detail/rtree/options.hpp>
#include <boost/geometry/util/condition.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree {
// Default choose_next_node
template
<
typename MembersHolder,
typename ChooseNextNodeTag = typename MembersHolder::options_type::choose_next_node_tag
>
class choose_next_node;
template <typename MembersHolder>
class choose_next_node<MembersHolder, choose_by_content_diff_tag>
{
public:
typedef typename MembersHolder::box_type box_type;
typedef typename MembersHolder::parameters_type parameters_type;
typedef typename MembersHolder::node node;
typedef typename MembersHolder::internal_node internal_node;
typedef typename MembersHolder::leaf leaf;
typedef typename rtree::elements_type<internal_node>::type children_type;
typedef typename index::detail::default_content_result<box_type>::type content_type;
template <typename Indexable>
static inline size_t apply(internal_node & n,
Indexable const& indexable,
parameters_type const& parameters,
size_t /*node_relative_level*/)
{
children_type & children = rtree::elements(n);
BOOST_GEOMETRY_INDEX_ASSERT(!children.empty(), "can't choose the next node if children are empty");
size_t children_count = children.size();
// choose index with smallest content change or smallest content
size_t choosen_index = 0;
content_type smallest_content_diff = (std::numeric_limits<content_type>::max)();
content_type smallest_content = (std::numeric_limits<content_type>::max)();
// caculate areas and areas of all nodes' boxes
for ( size_t i = 0 ; i < children_count ; ++i )
{
typedef typename children_type::value_type child_type;
child_type const& ch_i = children[i];
// expanded child node's box
box_type box_exp(ch_i.first);
index::detail::expand(box_exp, indexable,
index::detail::get_strategy(parameters));
// areas difference
content_type content = index::detail::content(box_exp);
content_type content_diff = content - index::detail::content(ch_i.first);
// update the result
if ( content_diff < smallest_content_diff ||
( content_diff == smallest_content_diff && content < smallest_content ) )
{
smallest_content_diff = content_diff;
smallest_content = content;
choosen_index = i;
}
}
return choosen_index;
}
};
// ----------------------------------------------------------------------- //
// Not implemented here
template
<
typename MembersHolder,
typename RedistributeTag = typename MembersHolder::options_type::redistribute_tag
>
struct redistribute_elements
{
BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
"Not implemented for this RedistributeTag type.",
MembersHolder, RedistributeTag);
};
// ----------------------------------------------------------------------- //
// Split algorithm
template
<
typename MembersHolder,
typename SplitTag = typename MembersHolder::options_type::split_tag
>
class split
{
BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
"Not implemented for this SplitTag type.",
MembersHolder, SplitTag);
};
// Default split algorithm
template <typename MembersHolder>
class split<MembersHolder, split_default_tag>
{
protected:
typedef typename MembersHolder::parameters_type parameters_type;
typedef typename MembersHolder::box_type box_type;
typedef typename MembersHolder::translator_type translator_type;
typedef typename MembersHolder::allocators_type allocators_type;
typedef typename MembersHolder::size_type size_type;
typedef typename MembersHolder::node node;
typedef typename MembersHolder::internal_node internal_node;
typedef typename MembersHolder::leaf leaf;
typedef typename MembersHolder::node_pointer node_pointer;
public:
typedef index::detail::varray<
typename rtree::elements_type<internal_node>::type::value_type,
1
> nodes_container_type;
template <typename Node>
static inline void apply(nodes_container_type & additional_nodes,
Node & n,
box_type & n_box,
parameters_type const& parameters,
translator_type const& translator,
allocators_type & allocators)
{
// TODO - consider creating nodes always with sufficient memory allocated
// create additional node, use auto destroyer for automatic destruction on exception
node_pointer n2_ptr = rtree::create_node<allocators_type, Node>::apply(allocators); // MAY THROW, STRONG (N: alloc)
// create reference to the newly created node
Node & n2 = rtree::get<Node>(*n2_ptr);
BOOST_TRY
{
// NOTE: thread-safety
// After throwing an exception by redistribute_elements the original node may be not changed or
// both nodes may be empty. In both cases the tree won't be valid r-tree.
// The alternative is to create 2 (or more) additional nodes here and store backup info
// in the original node, then, if exception was thrown, the node would always have more than max
// elements.
// The alternative is to use moving semantics in the implementations of redistribute_elements,
// it will be possible to throw from std::move() in the case of e.g. static size nodes.
// redistribute elements
box_type box2;
redistribute_elements<MembersHolder>
::apply(n, n2, n_box, box2, parameters, translator, allocators); // MAY THROW (V, E: alloc, copy, copy)
// check numbers of elements
BOOST_GEOMETRY_INDEX_ASSERT(parameters.get_min_elements() <= rtree::elements(n).size() &&
rtree::elements(n).size() <= parameters.get_max_elements(),
"unexpected number of elements");
BOOST_GEOMETRY_INDEX_ASSERT(parameters.get_min_elements() <= rtree::elements(n2).size() &&
rtree::elements(n2).size() <= parameters.get_max_elements(),
"unexpected number of elements");
// return the list of newly created nodes (this algorithm returns one)
additional_nodes.push_back(rtree::make_ptr_pair(box2, n2_ptr)); // MAY THROW, STRONG (alloc, copy)
}
BOOST_CATCH(...)
{
// NOTE: This code is here to prevent leaving the rtree in a state
// after an exception is thrown in which pushing new element could
// result in assert or putting it outside the memory of node elements.
typename rtree::elements_type<Node>::type & elements = rtree::elements(n);
size_type const max_size = parameters.get_max_elements();
if (elements.size() > max_size)
{
rtree::destroy_element<MembersHolder>::apply(elements[max_size], allocators);
elements.pop_back();
}
rtree::visitors::destroy<MembersHolder>::apply(n2_ptr, allocators);
BOOST_RETHROW
}
BOOST_CATCH_END
}
};
// ----------------------------------------------------------------------- //
namespace visitors { namespace detail {
template <typename InternalNode, typename InternalNodePtr, typename SizeType>
struct insert_traverse_data
{
typedef typename rtree::elements_type<InternalNode>::type elements_type;
typedef typename elements_type::value_type element_type;
typedef typename elements_type::size_type elements_size_type;
typedef SizeType size_type;
insert_traverse_data()
: parent(0), current_child_index(0), current_level(0)
{}
void move_to_next_level(InternalNodePtr new_parent,
elements_size_type new_child_index)
{
parent = new_parent;
current_child_index = new_child_index;
++current_level;
}
bool current_is_root() const
{
return 0 == parent;
}
elements_type & parent_elements() const
{
BOOST_GEOMETRY_INDEX_ASSERT(parent, "null pointer");
return rtree::elements(*parent);
}
element_type & current_element() const
{
BOOST_GEOMETRY_INDEX_ASSERT(parent, "null pointer");
return rtree::elements(*parent)[current_child_index];
}
InternalNodePtr parent;
elements_size_type current_child_index;
size_type current_level;
};
// Default insert visitor
template <typename Element, typename MembersHolder>
class insert
: public MembersHolder::visitor
{
protected:
typedef typename MembersHolder::box_type box_type;
typedef typename MembersHolder::value_type value_type;
typedef typename MembersHolder::parameters_type parameters_type;
typedef typename MembersHolder::translator_type translator_type;
typedef typename MembersHolder::allocators_type allocators_type;
typedef typename MembersHolder::node node;
typedef typename MembersHolder::internal_node internal_node;
typedef typename MembersHolder::leaf leaf;
typedef rtree::subtree_destroyer<MembersHolder> subtree_destroyer;
typedef typename allocators_type::node_pointer node_pointer;
typedef typename allocators_type::size_type size_type;
//typedef typename allocators_type::internal_node_pointer internal_node_pointer;
typedef internal_node * internal_node_pointer;
inline insert(node_pointer & root,
size_type & leafs_level,
Element const& element,
parameters_type const& parameters,
translator_type const& translator,
allocators_type & allocators,
size_type relative_level = 0
)
: m_element(element)
, m_parameters(parameters)
, m_translator(translator)
, m_relative_level(relative_level)
, m_level(leafs_level - relative_level)
, m_root_node(root)
, m_leafs_level(leafs_level)
, m_traverse_data()
, m_allocators(allocators)
{
BOOST_GEOMETRY_INDEX_ASSERT(m_relative_level <= leafs_level, "unexpected level value");
BOOST_GEOMETRY_INDEX_ASSERT(m_level <= m_leafs_level, "unexpected level value");
BOOST_GEOMETRY_INDEX_ASSERT(0 != m_root_node, "there is no root node");
// TODO
// assert - check if Box is correct
// When a value is inserted, during the tree traversal bounds of nodes
// on a path from the root to a leaf must be expanded. So prepare
// a bounding object at the beginning to not do it later for each node.
// NOTE: This is actually only needed because conditionally the bounding
// object may be expanded below. Otherwise the indexable could be
// directly used instead
index::detail::bounds(rtree::element_indexable(m_element, m_translator),
m_element_bounds,
index::detail::get_strategy(m_parameters));
#ifdef BOOST_GEOMETRY_INDEX_EXPERIMENTAL_ENLARGE_BY_EPSILON
// Enlarge it in case if it's not bounding geometry type.
// It's because Points and Segments are compared WRT machine epsilon
// This ensures that leafs bounds correspond to the stored elements
if (BOOST_GEOMETRY_CONDITION((
std::is_same<Element, value_type>::value
&& ! index::detail::is_bounding_geometry
<
typename indexable_type<translator_type>::type
>::value )) )
{
geometry::detail::expand_by_epsilon(m_element_bounds);
}
#endif
}
template <typename Visitor>
inline void traverse(Visitor & visitor, internal_node & n)
{
// choose next node
size_t choosen_node_index = rtree::choose_next_node<MembersHolder>
::apply(n, rtree::element_indexable(m_element, m_translator),
m_parameters,
m_leafs_level - m_traverse_data.current_level);
// expand the node to contain value
index::detail::expand(
rtree::elements(n)[choosen_node_index].first,
m_element_bounds,
index::detail::get_strategy(m_parameters));
// next traversing step
traverse_apply_visitor(visitor, n, choosen_node_index); // MAY THROW (V, E: alloc, copy, N:alloc)
}
// TODO: awulkiew - change post_traverse name to handle_overflow or overflow_treatment?
template <typename Node>
inline void post_traverse(Node &n)
{
BOOST_GEOMETRY_INDEX_ASSERT(m_traverse_data.current_is_root() ||
&n == &rtree::get<Node>(*m_traverse_data.current_element().second),
"if node isn't the root current_child_index should be valid");
// handle overflow
if ( m_parameters.get_max_elements() < rtree::elements(n).size() )
{
// NOTE: If the exception is thrown current node may contain more than MAX elements or be empty.
// Furthermore it may be empty root - internal node.
split(n); // MAY THROW (V, E: alloc, copy, N:alloc)
}
}
template <typename Visitor>
inline void traverse_apply_visitor(Visitor & visitor, internal_node &n, size_t choosen_node_index)
{
// save previous traverse inputs and set new ones
insert_traverse_data<internal_node, internal_node_pointer, size_type>
backup_traverse_data = m_traverse_data;
// calculate new traverse inputs
m_traverse_data.move_to_next_level(&n, choosen_node_index);
// next traversing step
rtree::apply_visitor(visitor, *rtree::elements(n)[choosen_node_index].second); // MAY THROW (V, E: alloc, copy, N:alloc)
// restore previous traverse inputs
m_traverse_data = backup_traverse_data;
}
// TODO: consider - split result returned as OutIter is faster than reference to the container. Why?
template <typename Node>
inline void split(Node & n) const
{
typedef rtree::split<MembersHolder> split_algo;
typename split_algo::nodes_container_type additional_nodes;
box_type n_box;
split_algo::apply(additional_nodes, n, n_box, m_parameters, m_translator, m_allocators); // MAY THROW (V, E: alloc, copy, N:alloc)
BOOST_GEOMETRY_INDEX_ASSERT(additional_nodes.size() == 1, "unexpected number of additional nodes");
// TODO add all additional nodes
// For kmeans algorithm:
// elements number may be greater than node max elements count
// split and reinsert must take node with some elements count
// and container of additional elements (std::pair<Box, node*>s or Values)
// and translator + allocators
// where node_elements_count + additional_elements > node_max_elements_count
// What with elements other than std::pair<Box, node*> ?
// Implement template <node_tag> struct node_element_type or something like that
// for exception safety
subtree_destroyer additional_node_ptr(additional_nodes[0].second, m_allocators);
#ifdef BOOST_GEOMETRY_INDEX_EXPERIMENTAL_ENLARGE_BY_EPSILON
// Enlarge bounds of a leaf node.
// It's because Points and Segments are compared WRT machine epsilon
// This ensures that leafs' bounds correspond to the stored elements.
if (BOOST_GEOMETRY_CONDITION((
std::is_same<Node, leaf>::value
&& ! index::detail::is_bounding_geometry
<
typename indexable_type<translator_type>::type
>::value )))
{
geometry::detail::expand_by_epsilon(n_box);
geometry::detail::expand_by_epsilon(additional_nodes[0].first);
}
#endif
// node is not the root - just add the new node
if ( !m_traverse_data.current_is_root() )
{
// update old node's box
m_traverse_data.current_element().first = n_box;
// add new node to parent's children
m_traverse_data.parent_elements().push_back(additional_nodes[0]); // MAY THROW, STRONG (V, E: alloc, copy)
}
// node is the root - add level
else
{
BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<Node>(*m_root_node), "node should be the root");
// create new root and add nodes
subtree_destroyer new_root(rtree::create_node<allocators_type, internal_node>::apply(m_allocators), m_allocators); // MAY THROW, STRONG (N:alloc)
BOOST_TRY
{
rtree::elements(rtree::get<internal_node>(*new_root)).push_back(rtree::make_ptr_pair(n_box, m_root_node)); // MAY THROW, STRONG (E:alloc, copy)
rtree::elements(rtree::get<internal_node>(*new_root)).push_back(additional_nodes[0]); // MAY THROW, STRONG (E:alloc, copy)
}
BOOST_CATCH(...)
{
// clear new root to not delete in the ~subtree_destroyer() potentially stored old root node
rtree::elements(rtree::get<internal_node>(*new_root)).clear();
BOOST_RETHROW // RETHROW
}
BOOST_CATCH_END
m_root_node = new_root.get();
++m_leafs_level;
new_root.release();
}
additional_node_ptr.release();
}
// TODO: awulkiew - implement dispatchable split::apply to enable additional nodes creation
Element const& m_element;
box_type m_element_bounds;
parameters_type const& m_parameters;
translator_type const& m_translator;
size_type const m_relative_level;
size_type const m_level;
node_pointer & m_root_node;
size_type & m_leafs_level;
// traversing input parameters
insert_traverse_data<internal_node, internal_node_pointer, size_type> m_traverse_data;
allocators_type & m_allocators;
};
} // namespace detail
// Insert visitor forward declaration
template
<
typename Element,
typename MembersHolder,
typename InsertTag = typename MembersHolder::options_type::insert_tag
>
class insert;
// Default insert visitor used for nodes elements
// After passing the Element to insert visitor the Element is managed by the tree
// I.e. one should not delete the node passed to the insert visitor after exception is thrown
// because this visitor may delete it
template <typename Element, typename MembersHolder>
class insert<Element, MembersHolder, insert_default_tag>
: public detail::insert<Element, MembersHolder>
{
public:
typedef detail::insert<Element, MembersHolder> base;
typedef typename base::parameters_type parameters_type;
typedef typename base::translator_type translator_type;
typedef typename base::allocators_type allocators_type;
typedef typename base::node node;
typedef typename base::internal_node internal_node;
typedef typename base::leaf leaf;
typedef typename base::node_pointer node_pointer;
typedef typename base::size_type size_type;
inline insert(node_pointer & root,
size_type & leafs_level,
Element const& element,
parameters_type const& parameters,
translator_type const& translator,
allocators_type & allocators,
size_type relative_level = 0
)
: base(root, leafs_level, element, parameters, translator, allocators, relative_level)
{}
inline void operator()(internal_node & n)
{
BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_leafs_level, "unexpected level");
if ( base::m_traverse_data.current_level < base::m_level )
{
// next traversing step
base::traverse(*this, n); // MAY THROW (E: alloc, copy, N: alloc)
}
else
{
BOOST_GEOMETRY_INDEX_ASSERT(base::m_level == base::m_traverse_data.current_level, "unexpected level");
BOOST_TRY
{
// push new child node
rtree::elements(n).push_back(base::m_element); // MAY THROW, STRONG (E: alloc, copy)
}
BOOST_CATCH(...)
{
// if the insert fails above, the element won't be stored in the tree
rtree::visitors::destroy<MembersHolder>::apply(base::m_element.second, base::m_allocators);
BOOST_RETHROW // RETHROW
}
BOOST_CATCH_END
}
base::post_traverse(n); // MAY THROW (E: alloc, copy, N: alloc)
}
inline void operator()(leaf &)
{
BOOST_GEOMETRY_INDEX_ASSERT(false, "this visitor can't be used for a leaf");
}
};
// Default insert visitor specialized for Values elements
template <typename MembersHolder>
class insert<typename MembersHolder::value_type, MembersHolder, insert_default_tag>
: public detail::insert<typename MembersHolder::value_type, MembersHolder>
{
public:
typedef detail::insert<typename MembersHolder::value_type, MembersHolder> base;
typedef typename base::value_type value_type;
typedef typename base::parameters_type parameters_type;
typedef typename base::translator_type translator_type;
typedef typename base::allocators_type allocators_type;
typedef typename base::node node;
typedef typename base::internal_node internal_node;
typedef typename base::leaf leaf;
typedef typename base::node_pointer node_pointer;
typedef typename base::size_type size_type;
inline insert(node_pointer & root,
size_type & leafs_level,
value_type const& value,
parameters_type const& parameters,
translator_type const& translator,
allocators_type & allocators,
size_type relative_level = 0
)
: base(root, leafs_level, value, parameters, translator, allocators, relative_level)
{}
inline void operator()(internal_node & n)
{
BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_leafs_level, "unexpected level");
BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_level, "unexpected level");
// next traversing step
base::traverse(*this, n); // MAY THROW (V, E: alloc, copy, N: alloc)
base::post_traverse(n); // MAY THROW (E: alloc, copy, N: alloc)
}
inline void operator()(leaf & n)
{
BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level == base::m_leafs_level, "unexpected level");
BOOST_GEOMETRY_INDEX_ASSERT(base::m_level == base::m_traverse_data.current_level ||
base::m_level == (std::numeric_limits<size_t>::max)(), "unexpected level");
rtree::elements(n).push_back(base::m_element); // MAY THROW, STRONG (V: alloc, copy)
base::post_traverse(n); // MAY THROW (V: alloc, copy, N: alloc)
}
};
}}} // namespace detail::rtree::visitors
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_INSERT_HPP
@@ -0,0 +1,50 @@
// Boost.Geometry Index
//
// R-tree leaf node checking visitor implementation
//
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
//
// This file was modified by Oracle on 2019.
// Modifications copyright (c) 2019 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// 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_INDEX_DETAIL_RTREE_VISITORS_IS_LEAF_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_IS_LEAF_HPP
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree { namespace visitors {
template <typename MembersHolder>
struct is_leaf
: public MembersHolder::visitor_const
{
typedef typename MembersHolder::internal_node internal_node;
typedef typename MembersHolder::leaf leaf;
is_leaf()
: result(false)
{}
inline void operator()(internal_node const&)
{
// result = false;
}
inline void operator()(leaf const&)
{
result = true;
}
bool result;
};
}}} // namespace detail::rtree::visitors
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_IS_LEAF_HPP
@@ -0,0 +1,143 @@
// Boost.Geometry Index
//
// R-tree iterator visitor implementation
//
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
//
// This file was modified by Oracle on 2021-2023.
// Modifications copyright (c) 2021-2023 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// 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_INDEX_DETAIL_RTREE_VISITORS_ITERATOR_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_ITERATOR_HPP
#include <boost/geometry/index/detail/rtree/node/concept.hpp>
#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
#include <boost/geometry/index/detail/rtree/node/variant_visitor.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree { namespace visitors {
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
class iterator
: public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
{
public:
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;
typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
typedef typename Allocators::size_type size_type;
typedef typename Allocators::const_reference const_reference;
typedef typename Allocators::node_pointer node_pointer;
typedef typename rtree::elements_type<internal_node>::type::const_iterator internal_iterator;
typedef typename rtree::elements_type<leaf>::type leaf_elements;
typedef typename rtree::elements_type<leaf>::type::const_iterator leaf_iterator;
inline iterator()
: m_values(NULL)
, m_current()
{}
inline void operator()(internal_node const& n)
{
typedef typename rtree::elements_type<internal_node>::type elements_type;
elements_type const& elements = rtree::elements(n);
m_internal_stack.push_back(std::make_pair(elements.begin(), elements.end()));
}
inline void operator()(leaf const& n)
{
m_values = ::boost::addressof(rtree::elements(n));
m_current = rtree::elements(n).begin();
}
const_reference dereference() const
{
BOOST_GEOMETRY_INDEX_ASSERT(m_values, "not dereferencable");
return *m_current;
}
void initialize(node_pointer root)
{
rtree::apply_visitor(*this, *root);
search_value();
}
void increment()
{
++m_current;
search_value();
}
void search_value()
{
for (;;)
{
// if leaf is choosen, move to the next value in leaf
if ( m_values )
{
// there are more values in the current leaf
if ( m_current != m_values->end() )
{
return;
}
// no more values, clear current leaf
else
{
m_values = 0;
}
}
// if leaf isn't choosen, move to the next leaf
else
{
// return if there is no more nodes to traverse
if ( m_internal_stack.empty() )
return;
// no more children in current node, remove it from stack
if ( m_internal_stack.back().first == m_internal_stack.back().second )
{
m_internal_stack.pop_back();
continue;
}
internal_iterator it = m_internal_stack.back().first;
++m_internal_stack.back().first;
// push the next node to the stack
rtree::apply_visitor(*this, *(it->second));
}
}
}
bool is_end() const
{
return 0 == m_values;
}
friend bool operator==(iterator const& l, iterator const& r)
{
return (l.m_values == r.m_values) && (0 == l.m_values || l.m_current == r.m_current );
}
private:
std::vector< std::pair<internal_iterator, internal_iterator> > m_internal_stack;
const leaf_elements * m_values;
leaf_iterator m_current;
};
}}} // namespace detail::rtree::visitors
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_ITERATOR_HPP
+357
View File
@@ -0,0 +1,357 @@
// Boost.Geometry Index
//
// R-tree removing visitor implementation
//
// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
//
// This file was modified by Oracle on 2019-2023.
// Modifications copyright (c) 2019-2023 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// 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_INDEX_DETAIL_RTREE_VISITORS_REMOVE_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_REMOVE_HPP
#include <boost/geometry/algorithms/detail/covered_by/interface.hpp>
#include <boost/geometry/index/parameters.hpp>
#include <boost/geometry/index/detail/algorithms/bounds.hpp>
#include <boost/geometry/index/detail/rtree/node/node.hpp>
#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
#include <boost/geometry/index/detail/rtree/node/subtree_destroyer.hpp>
#include <boost/geometry/index/detail/rtree/visitors/destroy.hpp>
#include <boost/geometry/index/detail/rtree/visitors/insert.hpp>
#include <boost/geometry/index/detail/rtree/visitors/is_leaf.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree { namespace visitors {
// Default remove algorithm
template <typename MembersHolder>
class remove
: public MembersHolder::visitor
{
typedef typename MembersHolder::box_type box_type;
typedef typename MembersHolder::value_type value_type;
typedef typename MembersHolder::parameters_type parameters_type;
typedef typename MembersHolder::translator_type translator_type;
typedef typename MembersHolder::allocators_type allocators_type;
typedef typename MembersHolder::node node;
typedef typename MembersHolder::internal_node internal_node;
typedef typename MembersHolder::leaf leaf;
typedef rtree::subtree_destroyer<MembersHolder> subtree_destroyer;
typedef typename allocators_type::node_pointer node_pointer;
typedef typename allocators_type::size_type size_type;
typedef typename rtree::elements_type<internal_node>::type::size_type internal_size_type;
//typedef typename Allocators::internal_node_pointer internal_node_pointer;
typedef internal_node * internal_node_pointer;
public:
inline remove(node_pointer & root,
size_type & leafs_level,
value_type const& value,
parameters_type const& parameters,
translator_type const& translator,
allocators_type & allocators)
: m_value(value)
, m_parameters(parameters)
, m_translator(translator)
, m_allocators(allocators)
, m_root_node(root)
, m_leafs_level(leafs_level)
, 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<internal_node>::type children_type;
children_type & children = rtree::elements(n);
// traverse children which boxes intersects value's box
internal_size_type child_node_index = 0;
for ( ; child_node_index < children.size() ; ++child_node_index )
{
if ( index::detail::covered_by_bounds(m_translator(m_value),
children[child_node_index].first,
index::detail::get_strategy(m_parameters)) )
{
// next traversing step
traverse_apply_visitor(n, child_node_index); // MAY THROW
if ( m_is_value_removed )
break;
}
}
// value was found and removed
if ( m_is_value_removed )
{
typedef typename rtree::elements_type<internal_node>::type elements_type;
typedef typename elements_type::iterator element_iterator;
elements_type & elements = rtree::elements(n);
// underflow occured - child node should be removed
if ( m_is_underflow )
{
element_iterator underfl_el_it = elements.begin() + child_node_index;
size_type relative_level = m_leafs_level - m_current_level;
// move node to the container - store node's relative level as well and return new underflow state
// NOTE: if the min elements number is 1, then after an underflow
// here the child elements count is 0, so it's not required to store this node,
// it could just be destroyed
m_is_underflow = store_underflowed_node(elements, underfl_el_it, relative_level); // MAY THROW (E: alloc, copy)
}
// n is not root - adjust aabb
if ( 0 != m_parent )
{
// underflow state should be ok here
// note that there may be less than min_elems elements in root
// so this condition should be checked only here
BOOST_GEOMETRY_INDEX_ASSERT((elements.size() < m_parameters.get_min_elements()) == m_is_underflow, "unexpected state");
rtree::elements(*m_parent)[m_current_child_index].first
= rtree::elements_box<box_type>(elements.begin(), elements.end(), m_translator,
index::detail::get_strategy(m_parameters));
}
// n is root node
else
{
BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<internal_node>(*m_root_node), "node must be the root");
// reinsert elements from removed nodes (underflows)
reinsert_removed_nodes_elements(); // MAY THROW (V, E: alloc, copy, N: alloc)
// shorten the tree
// NOTE: if the min elements number is 1, then after underflow
// here the number of elements may be equal to 0
// this can occur only for the last removed element
if ( rtree::elements(n).size() <= 1 )
{
node_pointer root_to_destroy = m_root_node;
if ( rtree::elements(n).size() == 0 )
m_root_node = 0;
else
m_root_node = rtree::elements(n)[0].second;
--m_leafs_level;
rtree::destroy_node<allocators_type, internal_node>::apply(m_allocators, root_to_destroy);
}
}
}
}
inline void operator()(leaf & n)
{
typedef typename rtree::elements_type<leaf>::type elements_type;
elements_type & elements = rtree::elements(n);
// find value and remove it
for ( typename elements_type::iterator it = elements.begin() ; it != elements.end() ; ++it )
{
if ( m_translator.equals(*it, m_value, index::detail::get_strategy(m_parameters)) )
{
rtree::move_from_back(elements, it); // MAY THROW (V: copy)
elements.pop_back();
m_is_value_removed = true;
break;
}
}
// if value was removed
if ( m_is_value_removed )
{
BOOST_GEOMETRY_INDEX_ASSERT(0 < m_parameters.get_min_elements(), "min number of elements is too small");
// calc underflow
m_is_underflow = elements.size() < m_parameters.get_min_elements();
// n is not root - adjust aabb
if ( 0 != m_parent )
{
rtree::elements(*m_parent)[m_current_child_index].first
= rtree::values_box<box_type>(elements.begin(), elements.end(), m_translator,
index::detail::get_strategy(m_parameters));
}
}
}
bool is_value_removed() const
{
return m_is_value_removed;
}
private:
typedef std::vector< std::pair<size_type, node_pointer> > underflow_nodes;
void traverse_apply_visitor(internal_node &n, internal_size_type choosen_node_index)
{
// save previous traverse inputs and set new ones
internal_node_pointer parent_bckup = m_parent;
internal_size_type current_child_index_bckup = m_current_child_index;
size_type current_level_bckup = m_current_level;
m_parent = &n;
m_current_child_index = choosen_node_index;
++m_current_level;
// next traversing step
rtree::apply_visitor(*this, *rtree::elements(n)[choosen_node_index].second); // MAY THROW (V, E: alloc, copy, N: alloc)
// restore previous traverse inputs
m_parent = parent_bckup;
m_current_child_index = current_child_index_bckup;
m_current_level = current_level_bckup;
}
bool store_underflowed_node(
typename rtree::elements_type<internal_node>::type & elements,
typename rtree::elements_type<internal_node>::type::iterator underfl_el_it,
size_type relative_level)
{
// move node to the container - store node's relative level as well
m_underflowed_nodes.push_back(std::make_pair(relative_level, underfl_el_it->second)); // MAY THROW (E: alloc, copy)
BOOST_TRY
{
// NOTE: those are elements of the internal node which means that copy/move shouldn't throw
// Though it's safer in case if the pointer type could throw in copy ctor.
// In the future this try-catch block could be removed.
rtree::move_from_back(elements, underfl_el_it); // MAY THROW (E: copy)
elements.pop_back();
}
BOOST_CATCH(...)
{
m_underflowed_nodes.pop_back();
BOOST_RETHROW // RETHROW
}
BOOST_CATCH_END
// calc underflow
return elements.size() < m_parameters.get_min_elements();
}
static inline bool is_leaf(node const& n)
{
visitors::is_leaf<MembersHolder> ilv;
rtree::apply_visitor(ilv, n);
return ilv.result;
}
void reinsert_removed_nodes_elements()
{
typename underflow_nodes::reverse_iterator it = m_underflowed_nodes.rbegin();
BOOST_TRY
{
// reinsert elements from removed nodes
// begin with levels closer to the root
for ( ; it != m_underflowed_nodes.rend() ; ++it )
{
// it->first is an index of a level of a node, not children
// counted from the leafs level
bool const node_is_leaf = it->first == 1;
BOOST_GEOMETRY_INDEX_ASSERT(node_is_leaf == is_leaf(*it->second), "unexpected condition");
if ( node_is_leaf )
{
reinsert_node_elements(rtree::get<leaf>(*it->second), it->first); // MAY THROW (V, E: alloc, copy, N: alloc)
rtree::destroy_node<allocators_type, leaf>::apply(m_allocators, it->second);
}
else
{
reinsert_node_elements(rtree::get<internal_node>(*it->second), it->first); // MAY THROW (V, E: alloc, copy, N: alloc)
rtree::destroy_node<allocators_type, internal_node>::apply(m_allocators, it->second);
}
}
//m_underflowed_nodes.clear();
}
BOOST_CATCH(...)
{
// destroy current and remaining nodes
for ( ; it != m_underflowed_nodes.rend() ; ++it )
{
rtree::visitors::destroy<MembersHolder>::apply(it->second, m_allocators);
}
//m_underflowed_nodes.clear();
BOOST_RETHROW // RETHROW
}
BOOST_CATCH_END
}
template <typename Node>
void reinsert_node_elements(Node &n, size_type node_relative_level)
{
typedef typename rtree::elements_type<Node>::type elements_type;
elements_type & elements = rtree::elements(n);
typename elements_type::iterator it = elements.begin();
BOOST_TRY
{
for ( ; it != elements.end() ; ++it )
{
visitors::insert<typename elements_type::value_type, MembersHolder>
insert_v(m_root_node, m_leafs_level, *it,
m_parameters, m_translator, m_allocators,
node_relative_level - 1);
rtree::apply_visitor(insert_v, *m_root_node); // MAY THROW (V, E: alloc, copy, N: alloc)
}
}
BOOST_CATCH(...)
{
++it;
rtree::destroy_elements<MembersHolder>::apply(it, elements.end(), m_allocators);
elements.clear();
BOOST_RETHROW // RETHROW
}
BOOST_CATCH_END
}
value_type const& m_value;
parameters_type const& m_parameters;
translator_type const& m_translator;
allocators_type & m_allocators;
node_pointer & m_root_node;
size_type & m_leafs_level;
bool m_is_value_removed;
underflow_nodes m_underflowed_nodes;
// traversing input parameters
internal_node_pointer m_parent;
internal_size_type m_current_child_index;
size_type m_current_level;
// traversing output parameters
bool m_is_underflow;
};
}}} // namespace detail::rtree::visitors
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_REMOVE_HPP
@@ -0,0 +1,275 @@
// Boost.Geometry Index
//
// R-tree spatial query visitor implementation
//
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
//
// This file was modified by Oracle on 2019-2023.
// Modifications copyright (c) 2019-2023 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// 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_INDEX_DETAIL_RTREE_VISITORS_SPATIAL_QUERY_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_SPATIAL_QUERY_HPP
#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
#include <boost/geometry/index/detail/rtree/node/weak_visitor.hpp>
#include <boost/geometry/index/detail/predicates.hpp>
#include <boost/geometry/index/parameters.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree { namespace visitors {
template <typename MembersHolder, typename Predicates, typename OutIter>
struct spatial_query
{
typedef typename MembersHolder::parameters_type parameters_type;
typedef typename MembersHolder::translator_type translator_type;
typedef typename MembersHolder::allocators_type allocators_type;
typedef typename index::detail::strategy_type<parameters_type>::type strategy_type;
typedef typename MembersHolder::node node;
typedef typename MembersHolder::internal_node internal_node;
typedef typename MembersHolder::leaf leaf;
typedef typename allocators_type::node_pointer node_pointer;
typedef typename allocators_type::size_type size_type;
spatial_query(MembersHolder const& members, Predicates const& p, OutIter out_it)
: m_tr(members.translator())
, m_strategy(index::detail::get_strategy(members.parameters()))
, m_pred(p)
, m_out_iter(out_it)
, m_found_count(0)
{}
size_type apply(node_pointer ptr, size_type reverse_level)
{
namespace id = index::detail;
if (reverse_level > 0)
{
internal_node& n = rtree::get<internal_node>(*ptr);
// traverse nodes meeting predicates
for (auto const& p : rtree::elements(n))
{
// if node meets predicates (0 is dummy value)
if (id::predicates_check<id::bounds_tag>(m_pred, 0, p.first, m_strategy))
{
apply(p.second, reverse_level - 1);
}
}
}
else
{
leaf& n = rtree::get<leaf>(*ptr);
// get all values meeting predicates
for (auto const& v : rtree::elements(n))
{
// if value meets predicates
if (id::predicates_check<id::value_tag>(m_pred, v, m_tr(v), m_strategy))
{
*m_out_iter = v;
++m_out_iter;
++m_found_count;
}
}
}
return m_found_count;
}
size_type apply(MembersHolder const& members)
{
return apply(members.root, members.leafs_level);
}
private:
translator_type const& m_tr;
strategy_type m_strategy;
Predicates const& m_pred;
OutIter m_out_iter;
size_type m_found_count;
};
template <typename MembersHolder, typename Predicates>
class spatial_query_incremental
{
typedef typename MembersHolder::value_type value_type;
typedef typename MembersHolder::parameters_type parameters_type;
typedef typename MembersHolder::translator_type translator_type;
typedef typename MembersHolder::allocators_type allocators_type;
typedef typename index::detail::strategy_type<parameters_type>::type strategy_type;
typedef typename MembersHolder::node node;
typedef typename MembersHolder::internal_node internal_node;
typedef typename MembersHolder::leaf leaf;
typedef typename allocators_type::size_type size_type;
typedef typename allocators_type::const_reference const_reference;
typedef typename allocators_type::node_pointer node_pointer;
typedef typename rtree::elements_type<internal_node>::type::const_iterator internal_iterator;
typedef typename rtree::elements_type<leaf>::type leaf_elements;
typedef typename rtree::elements_type<leaf>::type::const_iterator leaf_iterator;
struct internal_data
{
internal_data(internal_iterator f, internal_iterator l, size_type rl)
: first(f), last(l), reverse_level(rl)
{}
internal_iterator first;
internal_iterator last;
size_type reverse_level;
};
public:
spatial_query_incremental()
: m_translator(nullptr)
// , m_strategy()
// , m_pred()
, m_values(nullptr)
, m_current()
{}
spatial_query_incremental(Predicates const& p)
: m_translator(nullptr)
// , m_strategy()
, m_pred(p)
, m_values(nullptr)
, m_current()
{}
spatial_query_incremental(MembersHolder const& members, Predicates const& p)
: m_translator(::boost::addressof(members.translator()))
, m_strategy(index::detail::get_strategy(members.parameters()))
, m_pred(p)
, m_values(nullptr)
, m_current()
{}
const_reference dereference() const
{
BOOST_GEOMETRY_INDEX_ASSERT(m_values, "not dereferencable");
return *m_current;
}
void initialize(MembersHolder const& members)
{
apply(members.root, members.leafs_level);
search_value();
}
void increment()
{
++m_current;
search_value();
}
bool is_end() const
{
return 0 == m_values;
}
friend bool operator==(spatial_query_incremental const& l, spatial_query_incremental const& r)
{
return (l.m_values == r.m_values) && (0 == l.m_values || l.m_current == r.m_current);
}
private:
void apply(node_pointer ptr, size_type reverse_level)
{
namespace id = index::detail;
if (reverse_level > 0)
{
internal_node& n = rtree::get<internal_node>(*ptr);
auto const& elements = rtree::elements(n);
m_internal_stack.push_back(internal_data(elements.begin(), elements.end(), reverse_level - 1));
}
else
{
leaf& n = rtree::get<leaf>(*ptr);
m_values = ::boost::addressof(rtree::elements(n));
m_current = rtree::elements(n).begin();
}
}
void search_value()
{
namespace id = index::detail;
for (;;)
{
// if leaf is choosen, move to the next value in leaf
if ( m_values )
{
if ( m_current != m_values->end() )
{
// return if next value is found
value_type const& v = *m_current;
if (id::predicates_check<id::value_tag>(m_pred, v, (*m_translator)(v), m_strategy))
{
return;
}
++m_current;
}
// no more values, clear current leaf
else
{
m_values = 0;
}
}
// if leaf isn't choosen, move to the next leaf
else
{
// return if there is no more nodes to traverse
if (m_internal_stack.empty())
{
return;
}
internal_data& current_data = m_internal_stack.back();
// no more children in current node, remove it from stack
if (current_data.first == current_data.last)
{
m_internal_stack.pop_back();
continue;
}
internal_iterator it = current_data.first;
++current_data.first;
// next node is found, push it to the stack
if (id::predicates_check<id::bounds_tag>(m_pred, 0, it->first, m_strategy))
{
apply(it->second, current_data.reverse_level);
}
}
}
}
const translator_type * m_translator;
strategy_type m_strategy;
Predicates m_pred;
std::vector<internal_data> m_internal_stack;
const leaf_elements * m_values;
leaf_iterator m_current;
};
}}} // namespace detail::rtree::visitors
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_SPATIAL_QUERY_HPP