add boost on mac
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree node children box calculating visitor implementation
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// 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
|
||||
|
||||
namespace boost { namespace geometry { namespace index {
|
||||
|
||||
namespace detail { namespace rtree { namespace visitors {
|
||||
|
||||
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
|
||||
class children_box
|
||||
: public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
|
||||
{
|
||||
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;
|
||||
|
||||
public:
|
||||
inline children_box(Box & result, Translator const& tr)
|
||||
: m_result(result), 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>(elements.begin(), elements.end(), m_tr);
|
||||
}
|
||||
|
||||
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>(elements.begin(), elements.end(), m_tr);
|
||||
}
|
||||
|
||||
private:
|
||||
Box & m_result;
|
||||
Translator const& m_tr;
|
||||
};
|
||||
|
||||
}}} // namespace detail::rtree::visitors
|
||||
|
||||
}}} // namespace boost::geometry::index
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_CHILDREN_BOX_HPP
|
||||
@@ -0,0 +1,92 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree deep copying visitor implementation
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// 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
|
||||
|
||||
namespace boost { namespace geometry { namespace index {
|
||||
|
||||
namespace detail { namespace rtree { namespace visitors {
|
||||
|
||||
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
|
||||
class copy
|
||||
: public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, false>::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 rtree::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer;
|
||||
typedef typename Allocators::node_pointer node_pointer;
|
||||
|
||||
explicit inline copy(Allocators & allocators)
|
||||
: result(0)
|
||||
, m_allocators(allocators)
|
||||
{}
|
||||
|
||||
inline void operator()(internal_node & n)
|
||||
{
|
||||
node_pointer raw_new_node = rtree::create_node<Allocators, 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, 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 & m_allocators;
|
||||
};
|
||||
|
||||
}}} // namespace detail::rtree::visitors
|
||||
|
||||
}}} // namespace boost::geometry::index
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_COPY_HPP
|
||||
@@ -0,0 +1,107 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree count visitor implementation
|
||||
//
|
||||
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// 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
|
||||
|
||||
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>
|
||||
static inline bool equals(Indexable const& i, Value const& v, Translator const& tr)
|
||||
{
|
||||
return geometry::equals(i, tr(v));
|
||||
}
|
||||
};
|
||||
|
||||
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>
|
||||
static inline bool equals(Value const& v1, Value const& v2, Translator const& tr)
|
||||
{
|
||||
return tr.equals(v1, v2);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ValueOrIndexable, typename Value, typename Options, typename Translator, typename Box, typename Allocators>
|
||||
struct count
|
||||
: public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
|
||||
{
|
||||
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 count_helper<ValueOrIndexable, Value> count_help;
|
||||
|
||||
inline count(ValueOrIndexable const& vori, Translator const& t)
|
||||
: value_or_indexable(vori), 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 ( geometry::covered_by(
|
||||
return_ref_or_bounds(
|
||||
count_help::indexable(value_or_indexable, tr)),
|
||||
it->first) )
|
||||
{
|
||||
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) )
|
||||
{
|
||||
++found_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ValueOrIndexable const& value_or_indexable;
|
||||
Translator const& tr;
|
||||
typename Allocators::size_type found_count;
|
||||
};
|
||||
|
||||
}}} // namespace detail::rtree::visitors
|
||||
|
||||
}}} // namespace boost::geometry::index
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_COUNT_HPP
|
||||
@@ -0,0 +1,71 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree destroying visitor implementation
|
||||
//
|
||||
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// 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
|
||||
|
||||
namespace boost { namespace geometry { namespace index {
|
||||
|
||||
namespace detail { namespace rtree { namespace visitors {
|
||||
|
||||
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
|
||||
class destroy
|
||||
: public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, false>::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::node_pointer node_pointer;
|
||||
|
||||
inline destroy(node_pointer root_node, Allocators & allocators)
|
||||
: m_current_node(root_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, 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, leaf>::apply(m_allocators, m_current_node);
|
||||
}
|
||||
|
||||
private:
|
||||
node_pointer m_current_node;
|
||||
Allocators & m_allocators;
|
||||
};
|
||||
|
||||
}}} // namespace detail::rtree::visitors
|
||||
|
||||
}}} // namespace boost::geometry::index
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DELETE_HPP
|
||||
@@ -0,0 +1,588 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree distance (knn, path, etc. ) query visitor implementation
|
||||
//
|
||||
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// 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
|
||||
|
||||
namespace boost { namespace geometry { namespace index {
|
||||
|
||||
namespace detail { namespace rtree { namespace visitors {
|
||||
|
||||
template <typename Value, typename Translator, typename DistanceType, typename OutIt>
|
||||
class distance_query_result
|
||||
{
|
||||
public:
|
||||
typedef DistanceType distance_type;
|
||||
|
||||
inline explicit distance_query_result(size_t k, OutIt out_it)
|
||||
: m_count(k), m_out_it(out_it)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(0 < m_count, "Number of neighbors should be greater than 0");
|
||||
|
||||
m_neighbors.reserve(m_count);
|
||||
}
|
||||
|
||||
inline void store(Value const& val, distance_type const& curr_comp_dist)
|
||||
{
|
||||
if ( m_neighbors.size() < m_count )
|
||||
{
|
||||
m_neighbors.push_back(std::make_pair(curr_comp_dist, val));
|
||||
|
||||
if ( m_neighbors.size() == m_count )
|
||||
std::make_heap(m_neighbors.begin(), m_neighbors.end(), neighbors_less);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( curr_comp_dist < m_neighbors.front().first )
|
||||
{
|
||||
std::pop_heap(m_neighbors.begin(), m_neighbors.end(), neighbors_less);
|
||||
m_neighbors.back().first = curr_comp_dist;
|
||||
m_neighbors.back().second = val;
|
||||
std::push_heap(m_neighbors.begin(), m_neighbors.end(), neighbors_less);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline bool has_enough_neighbors() const
|
||||
{
|
||||
return m_count <= m_neighbors.size();
|
||||
}
|
||||
|
||||
inline distance_type greatest_comparable_distance() const
|
||||
{
|
||||
// greatest distance is in the first neighbor only
|
||||
// if there is at least m_count values found
|
||||
// this is just for safety reasons since is_comparable_distance_valid() is checked earlier
|
||||
// TODO - may be replaced by ASSERT
|
||||
return m_neighbors.size() < m_count
|
||||
? (std::numeric_limits<distance_type>::max)()
|
||||
: m_neighbors.front().first;
|
||||
}
|
||||
|
||||
inline size_t finish()
|
||||
{
|
||||
typedef typename std::vector< std::pair<distance_type, Value> >::const_iterator neighbors_iterator;
|
||||
for ( neighbors_iterator it = m_neighbors.begin() ; it != m_neighbors.end() ; ++it, ++m_out_it )
|
||||
*m_out_it = it->second;
|
||||
|
||||
return m_neighbors.size();
|
||||
}
|
||||
|
||||
private:
|
||||
inline static bool neighbors_less(
|
||||
std::pair<distance_type, Value> const& p1,
|
||||
std::pair<distance_type, Value> const& p2)
|
||||
{
|
||||
return p1.first < p2.first;
|
||||
}
|
||||
|
||||
size_t m_count;
|
||||
OutIt m_out_it;
|
||||
|
||||
std::vector< std::pair<distance_type, Value> > m_neighbors;
|
||||
};
|
||||
|
||||
template <
|
||||
typename Value,
|
||||
typename Options,
|
||||
typename Translator,
|
||||
typename Box,
|
||||
typename Allocators,
|
||||
typename Predicates,
|
||||
unsigned DistancePredicateIndex,
|
||||
typename OutIter
|
||||
>
|
||||
class distance_query
|
||||
: public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
|
||||
{
|
||||
public:
|
||||
typedef typename Options::parameters_type parameters_type;
|
||||
|
||||
typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;
|
||||
typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
|
||||
typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
|
||||
|
||||
typedef index::detail::predicates_element<DistancePredicateIndex, Predicates> nearest_predicate_access;
|
||||
typedef typename nearest_predicate_access::type nearest_predicate_type;
|
||||
typedef typename indexable_type<Translator>::type indexable_type;
|
||||
|
||||
typedef index::detail::calculate_distance<nearest_predicate_type, indexable_type, value_tag> calculate_value_distance;
|
||||
typedef index::detail::calculate_distance<nearest_predicate_type, Box, 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;
|
||||
|
||||
static const unsigned predicates_len = index::detail::predicates_length<Predicates>::value;
|
||||
|
||||
inline distance_query(parameters_type const& parameters, Translator const& translator, Predicates const& pred, OutIter out_it)
|
||||
: m_parameters(parameters), m_translator(translator)
|
||||
, m_pred(pred)
|
||||
, m_result(nearest_predicate_access::get(m_pred).count, out_it)
|
||||
{}
|
||||
|
||||
inline void operator()(internal_node const& n)
|
||||
{
|
||||
typedef typename rtree::elements_type<internal_node>::type elements_type;
|
||||
|
||||
// array of active nodes
|
||||
typedef typename index::detail::rtree::container_from_elements_type<
|
||||
elements_type,
|
||||
std::pair<node_distance_type, typename Allocators::node_pointer>
|
||||
>::type active_branch_list_type;
|
||||
|
||||
active_branch_list_type active_branch_list;
|
||||
active_branch_list.reserve(m_parameters.get_max_elements());
|
||||
|
||||
elements_type const& elements = rtree::elements(n);
|
||||
|
||||
// fill array of nodes meeting predicates
|
||||
for (typename elements_type::const_iterator it = elements.begin();
|
||||
it != elements.end(); ++it)
|
||||
{
|
||||
// if current node meets predicates
|
||||
// 0 - dummy value
|
||||
if ( index::detail::predicates_check<index::detail::bounds_tag, 0, predicates_len>(m_pred, 0, it->first) )
|
||||
{
|
||||
// calculate node's distance(s) for distance predicate
|
||||
node_distance_type node_distance;
|
||||
// if distance isn't ok - move to the next node
|
||||
if ( !calculate_node_distance::apply(predicate(), it->first, node_distance) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// if current node is further than found neighbors - don't analyze it
|
||||
if ( m_result.has_enough_neighbors() &&
|
||||
is_node_prunable(m_result.greatest_comparable_distance(), node_distance) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// add current node's data into the list
|
||||
active_branch_list.push_back( std::make_pair(node_distance, it->second) );
|
||||
}
|
||||
}
|
||||
|
||||
// if there aren't any nodes in ABL - return
|
||||
if ( active_branch_list.empty() )
|
||||
return;
|
||||
|
||||
// sort array
|
||||
std::sort(active_branch_list.begin(), active_branch_list.end(), abl_less);
|
||||
|
||||
// recursively visit nodes
|
||||
for ( typename active_branch_list_type::const_iterator it = active_branch_list.begin();
|
||||
it != active_branch_list.end() ; ++it )
|
||||
{
|
||||
// if current node is further than furthest neighbor, the rest of nodes also will be further
|
||||
if ( m_result.has_enough_neighbors() &&
|
||||
is_node_prunable(m_result.greatest_comparable_distance(), it->first) )
|
||||
break;
|
||||
|
||||
rtree::apply_visitor(*this, *(it->second));
|
||||
}
|
||||
|
||||
// ALTERNATIVE VERSION - use heap instead of sorted container
|
||||
// It seems to be faster for greater MaxElements and slower otherwise
|
||||
// CONSIDER: using one global container/heap for active branches
|
||||
// instead of a sorted container per level
|
||||
// This would also change the way how branches are traversed!
|
||||
// The same may be applied to the iterative version which btw suffers
|
||||
// from the copying of the whole containers on resize of the ABLs container
|
||||
|
||||
//// make a heap
|
||||
//std::make_heap(active_branch_list.begin(), active_branch_list.end(), abl_greater);
|
||||
|
||||
//// recursively visit nodes
|
||||
//while ( !active_branch_list.empty() )
|
||||
//{
|
||||
// //if current node is further than furthest neighbor, the rest of nodes also will be further
|
||||
// if ( m_result.has_enough_neighbors()
|
||||
// && is_node_prunable(m_result.greatest_comparable_distance(), active_branch_list.front().first) )
|
||||
// {
|
||||
// break;
|
||||
// }
|
||||
|
||||
// rtree::apply_visitor(*this, *(active_branch_list.front().second));
|
||||
|
||||
// std::pop_heap(active_branch_list.begin(), active_branch_list.end(), abl_greater);
|
||||
// active_branch_list.pop_back();
|
||||
//}
|
||||
}
|
||||
|
||||
inline void operator()(leaf const& n)
|
||||
{
|
||||
typedef typename rtree::elements_type<leaf>::type elements_type;
|
||||
elements_type const& elements = rtree::elements(n);
|
||||
|
||||
// search leaf for closest value meeting predicates
|
||||
for (typename elements_type::const_iterator it = elements.begin();
|
||||
it != elements.end(); ++it)
|
||||
{
|
||||
// if value meets predicates
|
||||
if ( index::detail::predicates_check<index::detail::value_tag, 0, predicates_len>(m_pred, *it, m_translator(*it)) )
|
||||
{
|
||||
// calculate values distance for distance predicate
|
||||
value_distance_type value_distance;
|
||||
// if distance is ok
|
||||
if ( calculate_value_distance::apply(predicate(), m_translator(*it), value_distance) )
|
||||
{
|
||||
// store value
|
||||
m_result.store(*it, value_distance);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline size_t finish()
|
||||
{
|
||||
return m_result.finish();
|
||||
}
|
||||
|
||||
private:
|
||||
static inline bool abl_less(
|
||||
std::pair<node_distance_type, typename Allocators::node_pointer> const& p1,
|
||||
std::pair<node_distance_type, typename Allocators::node_pointer> const& p2)
|
||||
{
|
||||
return p1.first < p2.first;
|
||||
}
|
||||
|
||||
//static inline bool abl_greater(
|
||||
// std::pair<node_distance_type, typename Allocators::node_pointer> const& p1,
|
||||
// std::pair<node_distance_type, typename Allocators::node_pointer> const& p2)
|
||||
//{
|
||||
// return p1.first > p2.first;
|
||||
//}
|
||||
|
||||
template <typename Distance>
|
||||
static inline bool is_node_prunable(Distance const& greatest_dist, node_distance_type const& d)
|
||||
{
|
||||
return greatest_dist <= d;
|
||||
}
|
||||
|
||||
nearest_predicate_type const& predicate() const
|
||||
{
|
||||
return nearest_predicate_access::get(m_pred);
|
||||
}
|
||||
|
||||
parameters_type const& m_parameters;
|
||||
Translator const& m_translator;
|
||||
|
||||
Predicates m_pred;
|
||||
distance_query_result<Value, Translator, value_distance_type, OutIter> m_result;
|
||||
};
|
||||
|
||||
template <
|
||||
typename Value,
|
||||
typename Options,
|
||||
typename Translator,
|
||||
typename Box,
|
||||
typename Allocators,
|
||||
typename Predicates,
|
||||
unsigned DistancePredicateIndex
|
||||
>
|
||||
class distance_query_incremental
|
||||
: public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
|
||||
{
|
||||
public:
|
||||
typedef typename Options::parameters_type parameters_type;
|
||||
|
||||
typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;
|
||||
typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
|
||||
typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
|
||||
|
||||
typedef index::detail::predicates_element<DistancePredicateIndex, Predicates> nearest_predicate_access;
|
||||
typedef typename nearest_predicate_access::type nearest_predicate_type;
|
||||
typedef typename indexable_type<Translator>::type indexable_type;
|
||||
|
||||
typedef index::detail::calculate_distance<nearest_predicate_type, indexable_type, value_tag> calculate_value_distance;
|
||||
typedef index::detail::calculate_distance<nearest_predicate_type, Box, 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::size_type size_type;
|
||||
typedef typename Allocators::const_reference const_reference;
|
||||
typedef typename Allocators::node_pointer node_pointer;
|
||||
|
||||
static const unsigned predicates_len = index::detail::predicates_length<Predicates>::value;
|
||||
|
||||
typedef typename rtree::elements_type<internal_node>::type internal_elements;
|
||||
typedef typename internal_elements::const_iterator internal_iterator;
|
||||
typedef typename rtree::elements_type<leaf>::type leaf_elements;
|
||||
|
||||
typedef std::pair<node_distance_type, node_pointer> branch_data;
|
||||
typedef typename index::detail::rtree::container_from_elements_type<
|
||||
internal_elements, branch_data
|
||||
>::type active_branch_list_type;
|
||||
struct internal_stack_element
|
||||
{
|
||||
internal_stack_element() : current_branch(0) {}
|
||||
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
// Required in c++03 for containers using Boost.Move
|
||||
internal_stack_element & operator=(internal_stack_element const& o)
|
||||
{
|
||||
branches = o.branches;
|
||||
current_branch = o.current_branch;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
active_branch_list_type branches;
|
||||
typename active_branch_list_type::size_type current_branch;
|
||||
};
|
||||
typedef std::vector<internal_stack_element> internal_stack_type;
|
||||
|
||||
inline distance_query_incremental()
|
||||
: m_translator(NULL)
|
||||
// , m_pred()
|
||||
, current_neighbor((std::numeric_limits<size_type>::max)())
|
||||
// , next_closest_node_distance((std::numeric_limits<node_distance_type>::max)())
|
||||
{}
|
||||
|
||||
inline distance_query_incremental(Translator const& translator, Predicates const& pred)
|
||||
: m_translator(::boost::addressof(translator))
|
||||
, m_pred(pred)
|
||||
, current_neighbor((std::numeric_limits<size_type>::max)())
|
||||
|
||||
, next_closest_node_distance((std::numeric_limits<node_distance_type>::max)())
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(0 < max_count(), "k must be greather than 0");
|
||||
}
|
||||
|
||||
const_reference dereference() const
|
||||
{
|
||||
return *(neighbors[current_neighbor].second);
|
||||
}
|
||||
|
||||
void initialize(node_pointer root)
|
||||
{
|
||||
rtree::apply_visitor(*this, *root);
|
||||
increment();
|
||||
}
|
||||
|
||||
void increment()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
size_type new_neighbor = current_neighbor == (std::numeric_limits<size_type>::max)() ? 0 : current_neighbor + 1;
|
||||
|
||||
if ( internal_stack.empty() )
|
||||
{
|
||||
if ( new_neighbor < neighbors.size() )
|
||||
current_neighbor = new_neighbor;
|
||||
else
|
||||
{
|
||||
current_neighbor = (std::numeric_limits<size_type>::max)();
|
||||
// clear() is used to disable the condition above
|
||||
neighbors.clear();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
active_branch_list_type & branches = internal_stack.back().branches;
|
||||
typename active_branch_list_type::size_type & current_branch = internal_stack.back().current_branch;
|
||||
|
||||
if ( branches.size() <= current_branch )
|
||||
{
|
||||
internal_stack.pop_back();
|
||||
continue;
|
||||
}
|
||||
|
||||
// if there are no nodes which can have closer values, set new value
|
||||
if ( new_neighbor < neighbors.size() &&
|
||||
// here must be < because otherwise neighbours may be sorted in different order
|
||||
// if there is another value with equal distance
|
||||
neighbors[new_neighbor].first < next_closest_node_distance )
|
||||
{
|
||||
current_neighbor = new_neighbor;
|
||||
return;
|
||||
}
|
||||
|
||||
// if node is further than the furthest neighbour, following nodes also will be further
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(neighbors.size() <= max_count(), "unexpected neighbours count");
|
||||
if ( max_count() <= neighbors.size() &&
|
||||
is_node_prunable(neighbors.back().first, branches[current_branch].first) )
|
||||
{
|
||||
// stop traversing current level
|
||||
internal_stack.pop_back();
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// new level - must increment current_branch before traversing of another level (mem reallocation)
|
||||
++current_branch;
|
||||
rtree::apply_visitor(*this, *(branches[current_branch - 1].second));
|
||||
|
||||
next_closest_node_distance = calc_closest_node_distance(internal_stack.begin(), internal_stack.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool is_end() const
|
||||
{
|
||||
return (std::numeric_limits<size_type>::max)() == current_neighbor;
|
||||
}
|
||||
|
||||
friend bool operator==(distance_query_incremental const& l, distance_query_incremental const& r)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(l.current_neighbor != r.current_neighbor ||
|
||||
(std::numeric_limits<size_type>::max)() == l.current_neighbor ||
|
||||
(std::numeric_limits<size_type>::max)() == r.current_neighbor ||
|
||||
l.neighbors[l.current_neighbor].second == r.neighbors[r.current_neighbor].second,
|
||||
"not corresponding iterators");
|
||||
return l.current_neighbor == r.current_neighbor;
|
||||
}
|
||||
|
||||
// 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)
|
||||
inline void operator()(internal_node const& n)
|
||||
{
|
||||
typedef typename rtree::elements_type<internal_node>::type elements_type;
|
||||
elements_type const& elements = rtree::elements(n);
|
||||
|
||||
// add new element
|
||||
internal_stack.resize(internal_stack.size()+1);
|
||||
|
||||
// fill active branch list array of nodes meeting predicates
|
||||
for ( typename elements_type::const_iterator it = elements.begin() ; it != elements.end() ; ++it )
|
||||
{
|
||||
// if current node meets predicates
|
||||
// 0 - dummy value
|
||||
if ( index::detail::predicates_check<index::detail::bounds_tag, 0, predicates_len>(m_pred, 0, it->first) )
|
||||
{
|
||||
// calculate node's distance(s) for distance predicate
|
||||
node_distance_type node_distance;
|
||||
// if distance isn't ok - move to the next node
|
||||
if ( !calculate_node_distance::apply(predicate(), it->first, node_distance) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// if current node is further than found neighbors - don't analyze it
|
||||
if ( max_count() <= neighbors.size() &&
|
||||
is_node_prunable(neighbors.back().first, node_distance) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// add current node's data into the list
|
||||
internal_stack.back().branches.push_back( std::make_pair(node_distance, it->second) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( internal_stack.back().branches.empty() )
|
||||
internal_stack.pop_back();
|
||||
else
|
||||
// sort array
|
||||
std::sort(internal_stack.back().branches.begin(), internal_stack.back().branches.end(), abl_less);
|
||||
}
|
||||
|
||||
// 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)
|
||||
inline void operator()(leaf const& n)
|
||||
{
|
||||
typedef typename rtree::elements_type<leaf>::type elements_type;
|
||||
elements_type const& elements = rtree::elements(n);
|
||||
|
||||
// store distance to the furthest neighbour
|
||||
bool not_enough_neighbors = neighbors.size() < max_count();
|
||||
value_distance_type greatest_distance = !not_enough_neighbors ? neighbors.back().first : (std::numeric_limits<value_distance_type>::max)();
|
||||
|
||||
// search leaf for closest value meeting predicates
|
||||
for ( typename elements_type::const_iterator it = elements.begin() ; it != elements.end() ; ++it)
|
||||
{
|
||||
// if value meets predicates
|
||||
if ( index::detail::predicates_check<index::detail::value_tag, 0, predicates_len>(m_pred, *it, (*m_translator)(*it)) )
|
||||
{
|
||||
// calculate values distance for distance predicate
|
||||
value_distance_type value_distance;
|
||||
// if distance is ok
|
||||
if ( calculate_value_distance::apply(predicate(), (*m_translator)(*it), value_distance) )
|
||||
{
|
||||
// if there is not enough values or current value is closer than furthest neighbour
|
||||
if ( not_enough_neighbors || value_distance < greatest_distance )
|
||||
{
|
||||
neighbors.push_back(std::make_pair(value_distance, boost::addressof(*it)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sort array
|
||||
std::sort(neighbors.begin(), neighbors.end(), neighbors_less);
|
||||
// remove furthest values
|
||||
if ( max_count() < neighbors.size() )
|
||||
neighbors.resize(max_count());
|
||||
}
|
||||
|
||||
private:
|
||||
static inline bool abl_less(std::pair<node_distance_type, typename Allocators::node_pointer> const& p1,
|
||||
std::pair<node_distance_type, typename Allocators::node_pointer> const& p2)
|
||||
{
|
||||
return p1.first < p2.first;
|
||||
}
|
||||
|
||||
static inline bool neighbors_less(std::pair<value_distance_type, const Value *> const& p1,
|
||||
std::pair<value_distance_type, const Value *> const& p2)
|
||||
{
|
||||
return p1.first < p2.first;
|
||||
}
|
||||
|
||||
node_distance_type
|
||||
calc_closest_node_distance(typename internal_stack_type::const_iterator first,
|
||||
typename internal_stack_type::const_iterator last)
|
||||
{
|
||||
node_distance_type result = (std::numeric_limits<node_distance_type>::max)();
|
||||
for ( ; first != last ; ++first )
|
||||
{
|
||||
if ( first->branches.size() <= first->current_branch )
|
||||
continue;
|
||||
|
||||
node_distance_type curr_dist = first->branches[first->current_branch].first;
|
||||
if ( curr_dist < result )
|
||||
result = curr_dist;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Distance>
|
||||
static inline bool is_node_prunable(Distance const& greatest_dist, node_distance_type const& d)
|
||||
{
|
||||
return greatest_dist <= d;
|
||||
}
|
||||
|
||||
inline unsigned 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 * m_translator;
|
||||
|
||||
Predicates m_pred;
|
||||
|
||||
internal_stack_type internal_stack;
|
||||
std::vector< std::pair<value_distance_type, const Value *> > neighbors;
|
||||
size_type current_neighbor;
|
||||
node_distance_type next_closest_node_distance;
|
||||
};
|
||||
|
||||
}}} // namespace detail::rtree::visitors
|
||||
|
||||
}}} // namespace boost::geometry::index
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DISTANCE_QUERY_HPP
|
||||
@@ -0,0 +1,573 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree inserting visitor implementation
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// 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
|
||||
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
|
||||
#include <boost/geometry/util/condition.hpp>
|
||||
|
||||
#include <boost/geometry/index/detail/algorithms/content.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace index {
|
||||
|
||||
namespace detail { namespace rtree {
|
||||
|
||||
// Default choose_next_node
|
||||
template <typename Value, typename Options, typename Box, typename Allocators, typename ChooseNextNodeTag>
|
||||
class choose_next_node;
|
||||
|
||||
template <typename Value, typename Options, typename Box, typename Allocators>
|
||||
class choose_next_node<Value, Options, Box, Allocators, choose_by_content_diff_tag>
|
||||
{
|
||||
public:
|
||||
typedef typename Options::parameters_type parameters_type;
|
||||
|
||||
typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;
|
||||
typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
|
||||
typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
|
||||
|
||||
typedef typename rtree::elements_type<internal_node>::type children_type;
|
||||
|
||||
typedef typename index::detail::default_content_result<Box>::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 box_exp(ch_i.first);
|
||||
geometry::expand(box_exp, indexable);
|
||||
|
||||
// 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 Value, typename Options, typename Translator, typename Box, typename Allocators, typename RedistributeTag>
|
||||
struct redistribute_elements
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG(
|
||||
(false),
|
||||
NOT_IMPLEMENTED_FOR_THIS_REDISTRIBUTE_TAG_TYPE,
|
||||
(redistribute_elements));
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
// Split algorithm
|
||||
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename SplitTag>
|
||||
class split
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG(
|
||||
(false),
|
||||
NOT_IMPLEMENTED_FOR_THIS_SPLIT_TAG_TYPE,
|
||||
(split));
|
||||
};
|
||||
|
||||
// Default split algorithm
|
||||
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
|
||||
class split<Value, Options, Translator, Box, Allocators, split_default_tag>
|
||||
{
|
||||
protected:
|
||||
typedef typename Options::parameters_type parameters_type;
|
||||
|
||||
typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;
|
||||
typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
|
||||
typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
|
||||
|
||||
typedef rtree::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer;
|
||||
|
||||
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 & n_box,
|
||||
parameters_type const& parameters,
|
||||
Translator const& translator,
|
||||
Allocators & allocators)
|
||||
{
|
||||
// TODO - consider creating nodes always with sufficient memory allocated
|
||||
|
||||
// create additional node, use auto destroyer for automatic destruction on exception
|
||||
subtree_destroyer second_node(rtree::create_node<Allocators, Node>::apply(allocators), allocators); // MAY THROW, STRONG (N: alloc)
|
||||
// create reference to the newly created node
|
||||
Node & n2 = rtree::get<Node>(*second_node);
|
||||
|
||||
// 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 boost::move() in the case of e.g. static size nodes.
|
||||
|
||||
// redistribute elements
|
||||
Box box2;
|
||||
redistribute_elements<
|
||||
Value,
|
||||
Options,
|
||||
Translator,
|
||||
Box,
|
||||
Allocators,
|
||||
typename Options::redistribute_tag
|
||||
>::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, second_node.get())); // MAY THROW, STRONG (alloc, copy)
|
||||
|
||||
// release the ptr
|
||||
second_node.release();
|
||||
}
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
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 Value, typename Options, typename Translator, typename Box, typename Allocators>
|
||||
class insert
|
||||
: public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, false>::type
|
||||
{
|
||||
protected:
|
||||
typedef typename Options::parameters_type parameters_type;
|
||||
|
||||
typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;
|
||||
typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
|
||||
typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
|
||||
|
||||
typedef rtree::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer;
|
||||
typedef typename Allocators::node_pointer node_pointer;
|
||||
typedef typename Allocators::size_type size_type;
|
||||
|
||||
//typedef typename Allocators::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 const& translator,
|
||||
Allocators & 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);
|
||||
|
||||
#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((
|
||||
boost::is_same<Element, Value>::value
|
||||
&& ! index::detail::is_bounding_geometry
|
||||
<
|
||||
typename indexable_type<Translator>::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<Value, Options, Box, Allocators, typename Options::choose_next_node_tag>::
|
||||
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
|
||||
geometry::expand(
|
||||
rtree::elements(n)[choosen_node_index].first,
|
||||
m_element_bounds
|
||||
/*rtree::element_indexable(m_element, m_translator)*/);
|
||||
|
||||
// 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<Value, Options, Translator, Box, Allocators, typename Options::split_tag> split_algo;
|
||||
|
||||
typename split_algo::nodes_container_type additional_nodes;
|
||||
Box 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((
|
||||
boost::is_same<Node, leaf>::value
|
||||
&& ! index::detail::is_bounding_geometry
|
||||
<
|
||||
typename indexable_type<Translator>::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, 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 m_element_bounds;
|
||||
parameters_type const& m_parameters;
|
||||
Translator 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 & m_allocators;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// Insert visitor forward declaration
|
||||
template <typename Element, typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename InsertTag>
|
||||
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 Value, typename Options, typename Translator, typename Box, typename Allocators>
|
||||
class insert<Element, Value, Options, Translator, Box, Allocators, insert_default_tag>
|
||||
: public detail::insert<Element, Value, Options, Translator, Box, Allocators>
|
||||
{
|
||||
public:
|
||||
typedef detail::insert<Element, Value, Options, Translator, Box, Allocators> base;
|
||||
typedef typename base::node node;
|
||||
typedef typename base::internal_node internal_node;
|
||||
typedef typename base::leaf leaf;
|
||||
|
||||
typedef typename Options::parameters_type parameters_type;
|
||||
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 const& translator,
|
||||
Allocators & 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<Value, Options, Translator, Box, Allocators> del_v(base::m_element.second, base::m_allocators);
|
||||
rtree::apply_visitor(del_v, *base::m_element.second);
|
||||
|
||||
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 Value, typename Options, typename Translator, typename Box, typename Allocators>
|
||||
class insert<Value, Value, Options, Translator, Box, Allocators, insert_default_tag>
|
||||
: public detail::insert<Value, Value, Options, Translator, Box, Allocators>
|
||||
{
|
||||
public:
|
||||
typedef detail::insert<Value, Value, Options, Translator, Box, Allocators> base;
|
||||
typedef typename base::node node;
|
||||
typedef typename base::internal_node internal_node;
|
||||
typedef typename base::leaf leaf;
|
||||
|
||||
typedef typename Options::parameters_type parameters_type;
|
||||
typedef typename base::node_pointer node_pointer;
|
||||
typedef typename base::size_type size_type;
|
||||
|
||||
inline insert(node_pointer & root,
|
||||
size_type & leafs_level,
|
||||
Value const& value,
|
||||
parameters_type const& parameters,
|
||||
Translator const& translator,
|
||||
Allocators & 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,45 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree leaf node checking visitor implementation
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// 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 Value, typename Options, typename Box, typename Allocators>
|
||||
struct is_leaf : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
|
||||
{
|
||||
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;
|
||||
|
||||
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,134 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree iterator visitor implementation
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// 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
|
||||
|
||||
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
|
||||
@@ -0,0 +1,344 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree removing visitor implementation
|
||||
//
|
||||
// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// 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/index/detail/rtree/visitors/is_leaf.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/covered_by/interface.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace index {
|
||||
|
||||
namespace detail { namespace rtree { namespace visitors {
|
||||
|
||||
// Default remove algorithm
|
||||
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
|
||||
class remove
|
||||
: public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, false>::type
|
||||
{
|
||||
typedef typename Options::parameters_type parameters_type;
|
||||
|
||||
typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;
|
||||
typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
|
||||
typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
|
||||
|
||||
typedef rtree::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer;
|
||||
typedef typename Allocators::node_pointer node_pointer;
|
||||
typedef typename Allocators::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 const& value,
|
||||
parameters_type const& parameters,
|
||||
Translator const& translator,
|
||||
Allocators & 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 ( geometry::covered_by(
|
||||
return_ref_or_bounds(m_translator(m_value)),
|
||||
children[child_node_index].first) )
|
||||
{
|
||||
// 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>(elements.begin(), elements.end(), m_translator);
|
||||
}
|
||||
// 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, 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) )
|
||||
{
|
||||
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>(elements.begin(), elements.end(), m_translator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool is_value_removed() const
|
||||
{
|
||||
return m_is_value_removed;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
typedef std::vector< std::pair<size_type, node_pointer> > UnderflowNodes;
|
||||
|
||||
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<Value, Options, Box, Allocators> ilv;
|
||||
rtree::apply_visitor(ilv, n);
|
||||
return ilv.result;
|
||||
}
|
||||
|
||||
void reinsert_removed_nodes_elements()
|
||||
{
|
||||
typename UnderflowNodes::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, 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, 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 )
|
||||
{
|
||||
subtree_destroyer dummy(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,
|
||||
Value, Options, Translator, Box, Allocators,
|
||||
typename Options::insert_tag
|
||||
> 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<Value, Options, Translator, Box, Allocators>
|
||||
::apply(it, elements.end(), m_allocators);
|
||||
elements.clear();
|
||||
BOOST_RETHROW // RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
|
||||
Value const& m_value;
|
||||
parameters_type const& m_parameters;
|
||||
Translator const& m_translator;
|
||||
Allocators & m_allocators;
|
||||
|
||||
node_pointer & m_root_node;
|
||||
size_type & m_leafs_level;
|
||||
|
||||
bool m_is_value_removed;
|
||||
UnderflowNodes 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,214 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// R-tree spatial query visitor implementation
|
||||
//
|
||||
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// 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
|
||||
|
||||
namespace boost { namespace geometry { namespace index {
|
||||
|
||||
namespace detail { namespace rtree { namespace visitors {
|
||||
|
||||
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename Predicates, typename OutIter>
|
||||
struct spatial_query
|
||||
: public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
|
||||
{
|
||||
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;
|
||||
|
||||
static const unsigned predicates_len = index::detail::predicates_length<Predicates>::value;
|
||||
|
||||
inline spatial_query(Translator const& t, Predicates const& p, OutIter out_it)
|
||||
: tr(t), pred(p), out_iter(out_it), 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 node meets predicates
|
||||
// 0 - dummy value
|
||||
if ( index::detail::predicates_check<index::detail::bounds_tag, 0, predicates_len>(pred, 0, it->first) )
|
||||
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 ( index::detail::predicates_check<index::detail::value_tag, 0, predicates_len>(pred, *it, tr(*it)) )
|
||||
{
|
||||
*out_iter = *it;
|
||||
++out_iter;
|
||||
|
||||
++found_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Translator const& tr;
|
||||
|
||||
Predicates pred;
|
||||
|
||||
OutIter out_iter;
|
||||
size_type found_count;
|
||||
};
|
||||
|
||||
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename Predicates>
|
||||
class spatial_query_incremental
|
||||
: 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;
|
||||
|
||||
static const unsigned predicates_len = index::detail::predicates_length<Predicates>::value;
|
||||
|
||||
inline spatial_query_incremental()
|
||||
: m_translator(NULL)
|
||||
// , m_pred()
|
||||
, m_values(NULL)
|
||||
, m_current()
|
||||
{}
|
||||
|
||||
inline spatial_query_incremental(Translator const& t, Predicates const& p)
|
||||
: m_translator(::boost::addressof(t))
|
||||
, m_pred(p)
|
||||
, 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 )
|
||||
{
|
||||
if ( m_current != m_values->end() )
|
||||
{
|
||||
// return if next value is found
|
||||
Value const& v = *m_current;
|
||||
if ( index::detail::predicates_check<index::detail::value_tag, 0, predicates_len>(m_pred, v, (*m_translator)(v)) )
|
||||
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;
|
||||
|
||||
// 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;
|
||||
|
||||
// next node is found, push it to the stack
|
||||
if ( index::detail::predicates_check<index::detail::bounds_tag, 0, predicates_len>(m_pred, 0, it->first) )
|
||||
rtree::apply_visitor(*this, *(it->second));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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:
|
||||
|
||||
const Translator * m_translator;
|
||||
|
||||
Predicates m_pred;
|
||||
|
||||
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_SPATIAL_QUERY_HPP
|
||||
Reference in New Issue
Block a user