geometry.index: added experimental spatial query iterator and rtree::qbegin() and rtree::qend() methods, added allocator_type to Allocators.

[SVN r83935]
This commit is contained in:
Adam Wulkiewicz
2013-04-16 22:08:55 +00:00
parent 2a1855795e
commit fcc99ddbcb
6 changed files with 254 additions and 60 deletions

View File

@@ -165,6 +165,7 @@ class allocators<Allocator, Value, Parameters, Box, node_d_mem_dynamic_tag>
>::other
{
public:
typedef Allocator allocator_type;
typedef typename Allocator::size_type size_type;
typedef typename Allocator::template rebind<

View File

@@ -114,6 +114,7 @@ class allocators<Allocator, Value, Parameters, Box, node_d_mem_static_tag>
>::other
{
public:
typedef Allocator allocator_type;
typedef typename Allocator::size_type size_type;
typedef typename Allocator::template rebind<

View File

@@ -97,6 +97,7 @@ class allocators<Allocator, Value, Parameters, Box, node_s_mem_dynamic_tag>
>::other
{
public:
typedef Allocator allocator_type;
typedef typename Allocator::size_type size_type;
typedef typename Allocator::template rebind<

View File

@@ -95,6 +95,7 @@ struct allocators<Allocator, Value, Parameters, Box, node_s_mem_static_tag>
>::other
{
public:
typedef Allocator allocator_type;
typedef typename Allocator::size_type size_type;
typedef typename Allocator::template rebind<

View File

@@ -75,67 +75,172 @@ struct spatial_query
size_type found_count;
};
//template <typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename Predicates, typename OutIter>
//struct spatial_query_incremental
// : 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;
// typedef typename Allocators::node_pointer node_pointer;
//
// static const unsigned predicates_len = index::detail::predicates_length<Predicates>::value;
//
// inline spatial_query_incremental(Translator const& t, Predicates const& p)
// : tr(t), pred(p)
// {}
//
// inline void operator()(internal_node const& n)
// {
// typedef typename rtree::elements_type<internal_node>::type elements_type;
// elements_type const& elements = rtree::elements(n);
//
// internal_stack.push_back(std::make_pair(elements.begin(), elements.end()));
//
// //// if node meets predicates
// //// 0 - dummy value
// //if ( index::detail::predicates_check<index::detail::bounds_tag, 0, predicates_len>(pred, 0, internal_stack.back().first->first) )
// //{
// // nodes.push_back(it->second);
// // 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);
//
// leaf_range.push_back(std::make_pair(elements.begin(), elements.end()));
//
// //// 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;
//
// typedef typename rtree::elements_type<internal_node>::type::const_iterator internal_iterator;
// typedef typename rtree::elements_type<leaf>::type::const_iterator leaf_iterator;
//
// std::vector< std::pair<internal_iterator, internal_iterator> > internal_stack;
// std::pair<leaf_iterator, leaf_iterator> leaf_range;
//};
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename Predicates>
struct spatial_query_incremental
: 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;
}}} // namespace detail::rtree::visitors
typedef typename Allocators::size_type size_type;
typedef typename Allocators::node_pointer node_pointer;
typedef typename rtree::elements_type<internal_node>::type::const_iterator internal_iterator;
typedef typename rtree::elements_type<leaf>::type leaf_elements;
static const unsigned predicates_len = index::detail::predicates_length<Predicates>::value;
inline spatial_query_incremental(Translator const& t, Predicates const& p)
: tr(t), pred(p)
, values(0), value_index(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);
internal_stack.push_back(std::make_pair(elements.begin(), elements.end()));
}
inline void operator()(leaf const& n)
{
typedef typename rtree::elements_type<leaf>::type elements_type;
elements_type const& elements = rtree::elements(n);
values = &elements;
value_index = 0;
}
Value const& dereference() const
{
BOOST_ASSERT_MSG(values, "not dereferencable");
return (*values)[value_index];
}
void increment()
{
for (;;)
{
if ( values )
{
// ERROR: infinite loop - value_index isn't incremented
for ( ;; ++value_index )
{
if ( values->size() <= value_index )
{
values = 0;
value_index = 0;
break;
}
Value const& v = (*values)[value_index];
if ( index::detail::predicates_check<index::detail::value_tag, 0, predicates_len>(pred, v, tr(v)) )
return;
}
}
// move to the next leaf if values aren't set
for ( ; !values ; ++internal_stack.back().first )
{
if ( internal_stack.empty() )
return;
if ( internal_stack.back().first == internal_stack.back().second )
{
internal_stack.pop_back();
continue;
}
if ( index::detail::predicates_check<index::detail::bounds_tag, 0, predicates_len>(pred, 0, internal_stack.back().first->first) )
rtree::apply_visitor(*this, *(internal_stack.back().first->second));
}
}
}
friend bool operator==(spatial_query_incremental const& l, spatial_query_incremental const& r)
{
return (l.values == r.values) && (l.value_index == r.value_index);
}
Translator const& tr;
Predicates pred;
boost::container::vector< std::pair<internal_iterator, internal_iterator> > internal_stack;
const leaf_elements * values;
size_type value_index;
};
} // namespace visitors
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename Predicates>
class spatial_query_iterator
{
typedef visitors::spatial_query_incremental<Value, Options, Translator, Box, Allocators, Predicates> visitor_type;
typedef typename visitor_type::node_pointer node_pointer;
// WARNING! If const Value is passed to rebind it won't compile for interprocess' allocator
typedef typename Allocators::allocator_type::template rebind<Value>::other allocator_type;
public:
typedef std::input_iterator_tag iterator_category;
typedef const Value value_type;
typedef Value const& reference;
typedef typename allocator_type::difference_type difference_type;
typedef typename allocator_type::pointer pointer;
inline spatial_query_iterator(Translator const& t, Predicates const& p)
: m_visitor(t, p)
{}
inline spatial_query_iterator(node_pointer root, Translator const& t, Predicates const& p)
: m_visitor(t, p)
{
detail::rtree::apply_visitor(m_visitor, *root);
m_visitor.increment();
}
reference operator*() const
{
return m_visitor.dereference();
}
const value_type * operator->() const
{
return boost::addressof(m_visitor.dereference());
}
spatial_query_iterator & operator++()
{
m_visitor.increment();
return *this;
}
spatial_query_iterator operator++(int)
{
spatial_query_iterator temp = *this;
this->operator++();
return temp;
}
friend bool operator==(spatial_query_iterator const& l, spatial_query_iterator const& r)
{
return l.m_visitor == r.m_visitor;
}
friend bool operator!=(spatial_query_iterator const& l, spatial_query_iterator const& r)
{
return !(l.m_visitor == r.m_visitor);
}
private:
visitor_type m_visitor;
};
}} // namespace detail::rtree
}}} // namespace boost::geometry::index

View File

@@ -719,6 +719,40 @@ public:
return query_dispatch(predicates, out_it, boost::mpl::bool_<is_nearest>());
}
#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
template <typename Predicates>
typename boost::mpl::if_c<
detail::predicates_count_nearest<Predicates>::value == 0,
detail::rtree::spatial_query_iterator<value_type, options_type, translator_type, box_type, allocators_type, Predicates>,
void
>::type
qbegin(Predicates const& predicates) const
{
static const unsigned nearest_count = detail::predicates_count_nearest<Predicates>::value;
static const bool is_nearest = 0 < nearest_count;
BOOST_MPL_ASSERT_MSG((nearest_count <= 1), PASS_ONLY_ONE_NEAREST_PREDICATE, (Predicates));
return qbegin_dispatch(predicates, boost::mpl::bool_<is_nearest>());
}
template <typename Predicates>
typename boost::mpl::if_c<
detail::predicates_count_nearest<Predicates>::value == 0,
detail::rtree::spatial_query_iterator<value_type, options_type, translator_type, box_type, allocators_type, Predicates>,
void
>::type
qend(Predicates const& predicates) const
{
static const unsigned nearest_count = detail::predicates_count_nearest<Predicates>::value;
static const bool is_nearest = 0 < nearest_count;
BOOST_MPL_ASSERT_MSG((nearest_count <= 1), PASS_ONLY_ONE_NEAREST_PREDICATE, (Predicates));
return qend_dispatch(predicates, boost::mpl::bool_<is_nearest>());
}
#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
/*!
\brief Returns the number of stored values.
@@ -1104,6 +1138,57 @@ private:
return raw_nearest_k(nearest_pred.distance_predicates, nearest_pred.count, predicates, out_it);
}
#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
template <typename Predicates>
typename
boost::mpl::if_c<
detail::predicates_count_nearest<Predicates>::value == 0,
detail::rtree::spatial_query_iterator<value_type, options_type, translator_type, box_type, allocators_type, Predicates>,
void
>::type
qbegin_dispatch(Predicates const& predicates, boost::mpl::bool_<false> const& /*is_nearest*/) const
{
typedef detail::rtree::spatial_query_iterator<
value_type, options_type, translator_type, box_type, allocators_type, Predicates
> iterator_type;
if ( !m_members.root )
return iterator_type(m_members.translator(), predicates);
return iterator_type(m_members.root, m_members.translator(), predicates);
}
template <typename Predicates>
void qbegin_dispatch(Predicates const& predicates, boost::mpl::bool_<true> const& /*is_nearest*/) const
{
BOOST_MPL_ASSERT_MSG(false, NEAREST_QUERY_ITERATOR_NOT_IMPLEMENTED_YET, (rtree));
}
template <typename Predicates>
typename
boost::mpl::if_c<
detail::predicates_count_nearest<Predicates>::value == 0,
detail::rtree::spatial_query_iterator<value_type, options_type, translator_type, box_type, allocators_type, Predicates>,
void
>::type
qend_dispatch(Predicates const& predicates, boost::mpl::bool_<false> const& /*is_nearest*/) const
{
typedef detail::rtree::spatial_query_iterator<
value_type, options_type, translator_type, box_type, allocators_type, Predicates
> iterator_type;
return iterator_type(m_members.translator(), predicates);
}
template <typename Predicates>
void qend_dispatch(Predicates const& predicates, boost::mpl::bool_<true> const& /*is_nearest*/) const
{
BOOST_MPL_ASSERT_MSG(false, NEAREST_QUERY_ITERATOR_NOT_IMPLEMENTED_YET, (rtree));
}
#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
/*!
\brief Find k values meeting distances and spatial predicates.