mirror of
https://github.com/vdemydiuk/mtapi.git
synced 2026-08-18 13:18:12 +00:00
Added thirdparty: boost library
This commit is contained in:
+72
@@ -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
@@ -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
@@ -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
|
||||
+87
@@ -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
|
||||
Vendored
Executable
+576
@@ -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
@@ -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
|
||||
+50
@@ -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
|
||||
+143
@@ -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
@@ -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
|
||||
+275
@@ -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
|
||||
Reference in New Issue
Block a user