[geometry][index] query iterators added to the rtree official interface.

[SVN r85507]
This commit is contained in:
Adam Wulkiewicz 2013-08-29 00:33:54 +00:00
parent 190cf977c7
commit 242ef41cf1
3 changed files with 158 additions and 140 deletions

View File

@ -11,7 +11,10 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUERY_ITERATORS_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUERY_ITERATORS_HPP
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree {
//#define BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_TYPE_ERASURE
#define BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace iterators {
template <typename Value, typename Allocators>
struct end_query_iterator
@ -190,11 +193,11 @@ inline bool operator!=(L const& l, R const& r)
return !(l == r);
}
}}}}} // namespace boost::geometry::index::detail::rtree
}}}}}} // namespace boost::geometry::index::detail::rtree::iterators
#ifdef BOOST_GEOMETRY_INDEX_DETAIL_ENABLE_TYPE_ERASED_ITERATORS
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_TYPE_ERASURE
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree {
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace iterators {
template <typename Value, typename Allocators>
class query_iterator_base
@ -248,7 +251,7 @@ private:
};
template <typename Value, typename Allocators>
class query_iterator_poly
class query_iterator
{
typedef query_iterator_base<Value, Allocators> iterator_base;
typedef std::auto_ptr<iterator_base> iterator_ptr;
@ -260,42 +263,42 @@ public:
typedef typename Allocators::difference_type difference_type;
typedef typename Allocators::const_pointer pointer;
query_iterator_poly() {}
query_iterator() {}
template <typename It>
query_iterator_poly(It const& it)
query_iterator(It const& it)
: m_ptr(static_cast<iterator_base*>(
new query_iterator_wrapper<Value, Allocators, It>(it) ))
{}
query_iterator_poly(end_query_iterator<Value, Allocators> const& /*it*/)
query_iterator(end_query_iterator<Value, Allocators> const& /*it*/)
{}
query_iterator_poly(query_iterator_poly const& o)
query_iterator(query_iterator const& o)
: m_ptr(o.m_ptr.get() ? o.m_ptr->clone() : 0)
{}
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ENABLE_TYPE_ERASED_ITERATORS_MOVE
query_iterator_poly & operator=(query_iterator_poly const& o)
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE
query_iterator & operator=(query_iterator const& o)
{
m_ptr.reset(o.m_ptr.get() ? o.m_ptr->clone() : 0);
return *this;
}
#else
#else // !BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE
private:
BOOST_COPYABLE_AND_MOVABLE(query_iterator_poly)
BOOST_COPYABLE_AND_MOVABLE(query_iterator)
public:
query_iterator_poly & operator=(BOOST_COPY_ASSIGN_REF(query_iterator_poly) o)
query_iterator & operator=(BOOST_COPY_ASSIGN_REF(query_iterator) o)
{
m_ptr.reset(o.m_ptr.get() ? o.m_ptr->clone() : 0);
return *this;
}
query_iterator_poly(BOOST_RV_REF(query_iterator_poly) o)
query_iterator(BOOST_RV_REF(query_iterator) o)
: m_ptr(o.m_ptr.get())
{
o.m_ptr.release();
}
query_iterator_poly & operator=(BOOST_RV_REF(query_iterator_poly) o)
query_iterator & operator=(BOOST_RV_REF(query_iterator) o)
{
if ( this != boost::addressof(o) )
{
@ -304,7 +307,7 @@ public:
}
return *this;
}
#endif
#endif // BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE
reference operator*() const
{
@ -316,20 +319,20 @@ public:
return boost::addressof(m_ptr->dereference());
}
query_iterator_poly & operator++()
query_iterator & operator++()
{
m_ptr->increment();
return *this;
}
query_iterator_poly operator++(int)
query_iterator operator++(int)
{
query_iterator_poly temp = *this;
query_iterator temp = *this;
this->operator++();
return temp;
}
friend bool operator==(query_iterator_poly const& l, query_iterator_poly const& r)
friend bool operator==(query_iterator const& l, query_iterator const& r)
{
if ( l.m_ptr.get() )
{
@ -351,13 +354,15 @@ private:
iterator_ptr m_ptr;
};
}}}}} // namespace boost::geometry::index::detail::rtree
}}}}}} // namespace boost::geometry::index::detail::rtree::iterators
#else // BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_TYPE_ERASURE
#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/operators.hpp>
#include <boost/type_erasure/is_empty.hpp>
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree {
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace iterators {
template<typename T, typename Value, typename Allocators>
struct single_pass_iterator_concept :
@ -382,7 +387,7 @@ struct single_pass_iterator_type
> type;
};
}}}}} // namespace boost::geometry::index::detail::rtree
}}}}}} // namespace boost::geometry::index::detail::rtree::iterators
namespace boost { namespace type_erasure {
@ -395,17 +400,17 @@ struct concept_interface<
{
typedef Value value_type;
typedef typename Allocators::const_reference reference;
typedef typename Allocators::const_pointer;
typedef typename Allocators::const_pointer pointer;
typedef typename Allocators::difference_type difference_type;
typedef ::std::input_iterator_tag iterator_category;
};
}} // boost::type_erasure
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree {
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace iterators {
template <typename Value, typename Allocators>
class query_iterator_te
class query_iterator
{
public:
typedef std::input_iterator_tag iterator_category;
@ -419,33 +424,32 @@ private:
public:
query_iterator_te() {}
query_iterator() {}
template <typename It>
query_iterator_te(It const& it)
query_iterator(It const& it)
: m_iterator(it)
{}
query_iterator_te(end_query_iterator<Value, Allocators> const& /*it*/)
query_iterator(end_query_iterator<Value, Allocators> const& /*it*/)
{}
#ifdef BOOST_GEOMETRY_INDEX_DETAIL_ENABLE_TYPE_ERASED_ITERATORS_MOVE
#ifdef BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE
private:
BOOST_COPYABLE_AND_MOVABLE(query_iterator_te)
BOOST_COPYABLE_AND_MOVABLE(query_iterator)
public:
query_iterator_te(query_iterator_te const& o)
query_iterator(query_iterator const& o)
: m_iterator(o.m_iterator)
{}
query_iterator_te & operator=(BOOST_COPY_ASSIGN_REF(query_iterator_te) o)
query_iterator & operator=(BOOST_COPY_ASSIGN_REF(query_iterator) o)
{
m_iterator = o.m_iterator;
return *this;
}
query_iterator_te(BOOST_RV_REF(query_iterator_te) o)
query_iterator(BOOST_RV_REF(query_iterator) o)
: m_iterator(boost::move(o.m_iterator))
{}
query_iterator_te & operator=(BOOST_RV_REF(query_iterator_te) o)
query_iterator & operator=(BOOST_RV_REF(query_iterator) o)
{
if ( this != boost::addressof(o) )
{
@ -453,7 +457,7 @@ public:
}
return *this;
}
#endif
#endif // BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE
reference operator*() const
{
@ -465,20 +469,20 @@ public:
return boost::addressof(*m_iterator);
}
query_iterator_te & operator++()
query_iterator & operator++()
{
++m_iterator;
return *this;
}
query_iterator_te operator++(int)
query_iterator operator++(int)
{
query_iterator_te temp = *this;
query_iterator temp = *this;
++m_iterator;
return temp;
}
friend bool operator==(query_iterator_te const& l, query_iterator_te const& r)
friend bool operator==(query_iterator const& l, query_iterator const& r)
{
if ( !::boost::type_erasure::is_empty(l.m_iterator) )
{
@ -500,8 +504,8 @@ private:
iterator_type m_iterator;
};
}}}}} // namespace boost::geometry::index::detail::rtree
}}}}}} // namespace boost::geometry::index::detail::rtree::iterators
#endif // BOOST_GEOMETRY_INDEX_DETAIL_ENABLE_TYPE_ERASED_ITERATORS
#endif // BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_TYPE_ERASURE
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUERY_ITERATORS_HPP

View File

@ -1,61 +0,0 @@
// Boost.Geometry Index
//
// Type-erased iterators
//
// Copyright (c) 2011-2013 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_TYPE_ERASED_ITERATORS_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_TYPE_ERASED_ITERATORS_HPP
#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/operators.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {
template<typename T, typename ValueType, typename Reference, typename Pointer, typename DifferenceType>
struct single_pass_iterator_concept :
::boost::mpl::vector<
::boost::type_erasure::copy_constructible<T>,
::boost::type_erasure::equality_comparable<T>,
::boost::type_erasure::dereferenceable<Reference, T>,
::boost::type_erasure::assignable<T>,
::boost::type_erasure::incrementable<T>,
::boost::type_erasure::relaxed // default ctor
>
{};
template <typename ValueType, typename Reference, typename Pointer, typename DifferenceType>
struct single_pass_iterator_type
{
typedef ::boost::type_erasure::any<
single_pass_iterator_concept<
::boost::type_erasure::_self, ValueType, Reference, Pointer, DifferenceType
>
> type;
};
}}}} // namespace boost::geometry::index::detail
namespace boost { namespace type_erasure {
template<typename T, typename ValueType, typename Reference, typename Pointer, typename DifferenceType, typename Base>
struct concept_interface<
::boost::geometry::index::detail::single_pass_iterator_concept<
T, ValueType, Reference, Pointer, DifferenceType
>, Base, T>
: Base
{
typedef ValueType value_type;
typedef Reference reference;
typedef Pointer pointer;
typedef DifferenceType difference_type;
typedef ::std::input_iterator_tag iterator_category;
};
}} // namespace boost::type_erasure
#endif // BOOST_GEOMETRY_INDEX_DETAIL_TYPE_ERASED_ITERATORS_HPP

View File

@ -61,13 +61,9 @@
#include <boost/geometry/index/detail/rtree/utilities/view.hpp>
#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
// query iterators
#include <boost/geometry/index/detail/rtree/query_iterators.hpp>
#ifdef BOOST_GEOMETRY_INDEX_DETAIL_ENABLE_TYPE_ERASED_ITERATORS
// type-erased iterators
#include <boost/geometry/index/detail/type_erased_iterators.hpp>
#endif
#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
// serialization
#include <boost/geometry/index/detail/serialization.hpp>
#endif
@ -189,6 +185,9 @@ public:
/*! \brief Unsigned integral type used by the container. */
typedef typename allocators_type::size_type size_type;
/*! \brief The type-erased const query iterator. */
typedef index::detail::rtree::iterators::query_iterator<value_type, allocators_type> const_query_iterator;
public:
/*!
@ -731,6 +730,7 @@ public:
\par Throws
If Value copy constructor or copy assignment throws.
If predicates copy throws.
\warning
Only one \c nearest() perdicate may be passed to the query. Passing more of them results in compile-time error.
@ -753,34 +753,50 @@ public:
return query_dispatch(predicates, out_it, boost::mpl::bool_<is_distance_predicate>());
}
#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
/*!
\brief Returns the query iterator pointing at the begin of the query range.
#ifdef BOOST_GEOMETRY_INDEX_DETAIL_ENABLE_TYPE_ERASED_ITERATORS
This method returns the iterator which may be used to perform iterative queries. For the information
about the predicates which may be passed to this method see query().
The type of the returned iterator depends on the type of passed Predicates but the iterator of this type
may be assigned to the variable of const_query_iterator type. If you'd like to use the type of the iterator
returned by this method you may get the type e.g. by using C++11 decltype or Boost.Typeof library.
This iterator may be compared with iterators returned by both versions of qend() method.
// BEWARE!
// Don't use this type-erased iterator after assigning values returned by qbegin(Pred) and qend()
// e.g. don't pass them into the std::copy() or compare them like this:
// const_query_iterator i1 = qbegin(...);
// const_query_iterator i2 = qend();
// i1 == i2; // BAM!
// now this will cause undefined behaviour.
// using native types is ok:
// qbegin(...) == qend();
\par Example
\verbatim
// Store the result in the container using std::copy() - it requires both iterators of the same type
std::copy(tree.qbegin(bgi::intersects(box)), tree.qend(bgi::intersects(box)), std::back_inserter(result));
typedef typename index::detail::single_pass_iterator_type<
value_type, const_reference, const_pointer, difference_type
>::type const_query_iterator;
// Store the result in the container using std::copy() and type-erased iterators
Rtree::const_query_iterator first = tree.qbegin(bgi::intersects(box));
Rtree::const_query_iterator last = tree.qend();
std::copy(first, last, std::back_inserter(result));
typedef index::detail::rtree::query_iterator_poly<value_type, allocators_type> const_query_iterator_alt;
typedef index::detail::rtree::query_iterator_te<value_type, allocators_type> const_query_iterator_alt2;
// Boost.Typeof
typedef BOOST_TYPEOF(tree.qbegin(bgi::nearest(pt, 10000))) Iter;
for ( Iter it = tree.qbegin(bgi::nearest(pt, 10000)) ; it != tree.qend() ; ++it )
{
// do something with value
if ( has_enough_nearest_values() )
break;
}
\endverbatim
#endif // BOOST_GEOMETRY_INDEX_DETAIL_ENABLE_TYPE_ERASED_ITERATORS
\par Throws
If predicates copy throws.
If allocation throws.
\param predicates Predicates.
\return The iterator pointing at the begin of the query range.
*/
template <typename Predicates>
typename boost::mpl::if_c<
detail::predicates_count_distance<Predicates>::value == 0,
detail::rtree::spatial_query_iterator<value_type, options_type, translator_type, box_type, allocators_type, Predicates>,
detail::rtree::distance_query_iterator<
detail::rtree::iterators::spatial_query_iterator<value_type, options_type, translator_type, box_type, allocators_type, Predicates>,
detail::rtree::iterators::distance_query_iterator<
value_type, options_type, translator_type, box_type, allocators_type, Predicates,
detail::predicates_find_distance<Predicates>::value
>
@ -792,8 +808,8 @@ public:
typedef typename boost::mpl::if_c<
detail::predicates_count_distance<Predicates>::value == 0,
detail::rtree::spatial_query_iterator<value_type, options_type, translator_type, box_type, allocators_type, Predicates>,
detail::rtree::distance_query_iterator<
detail::rtree::iterators::spatial_query_iterator<value_type, options_type, translator_type, box_type, allocators_type, Predicates>,
detail::rtree::iterators::distance_query_iterator<
value_type, options_type, translator_type, box_type, allocators_type, Predicates,
detail::predicates_find_distance<Predicates>::value
>
@ -805,11 +821,37 @@ public:
return iterator_type(m_members.root, m_members.translator(), predicates);
}
/*!
\brief Returns the query iterator pointing at the end of the query range.
This method returns the iterator which may be used to perform iterative queries. For the information
about the predicates which may be passed to this method see query().
The type of the returned iterator depends on the type of passed Predicates but the iterator of this type
may be assigned to the variable of const_query_iterator type. If you'd like to use the type of the iterator
returned by this method you may get the type e.g. by using C++11 decltype or Boost.Typeof library.
The type of the iterator returned by this method is the same as the one returned by qbegin() to which
the same predicates were passed.
\par Example
\verbatim
// Store the result in the container using std::copy() - it requires both iterators of the same type
std::copy(tree.qbegin(bgi::intersects(box)), tree.qend(bgi::intersects(box)), std::back_inserter(result));
\endverbatim
\par Throws
If predicates copy throws.
\param predicates Predicates.
\return The iterator pointing at the end of the query range.
*/
template <typename Predicates>
typename boost::mpl::if_c<
detail::predicates_count_distance<Predicates>::value == 0,
detail::rtree::spatial_query_iterator<value_type, options_type, translator_type, box_type, allocators_type, Predicates>,
detail::rtree::distance_query_iterator<
detail::rtree::iterators::spatial_query_iterator<value_type, options_type, translator_type, box_type, allocators_type, Predicates>,
detail::rtree::iterators::distance_query_iterator<
value_type, options_type, translator_type, box_type, allocators_type, Predicates,
detail::predicates_find_distance<Predicates>::value
>
@ -821,8 +863,8 @@ public:
typedef typename boost::mpl::if_c<
detail::predicates_count_distance<Predicates>::value == 0,
detail::rtree::spatial_query_iterator<value_type, options_type, translator_type, box_type, allocators_type, Predicates>,
detail::rtree::distance_query_iterator<
detail::rtree::iterators::spatial_query_iterator<value_type, options_type, translator_type, box_type, allocators_type, Predicates>,
detail::rtree::iterators::distance_query_iterator<
value_type, options_type, translator_type, box_type, allocators_type, Predicates,
detail::predicates_find_distance<Predicates>::value
>
@ -831,14 +873,47 @@ public:
return iterator_type(m_members.translator(), predicates);
}
detail::rtree::end_query_iterator<value_type, allocators_type>
/*!
\brief Returns the query iterator pointing at the end of the query range.
This method returns the iterator which may be compared with the iterator returned by qbegin() in order to
check if the query has ended.
The type of the returned iterator is different than the type returned by qbegin() but the iterator of this type
may be assigned to the variable of const_query_iterator type. If you'd like to use the type of the iterator returned by this
method, which most certainly will be faster than the type-erased iterator, you may get the type
e.g. by using C++11 decltype or Boost.Typeof library.
The type of the iterator returned by this method is dfferent than the type returned by qbegin().
\par Example
\verbatim
// Store the result in the container using std::copy() and type-erased iterators
Rtree::const_query_iterator first = tree.qbegin(bgi::intersects(box));
Rtree::const_query_iterator last = tree.qend();
std::copy(first, last, std::back_inserter(result));
// Boost.Typeof
typedef BOOST_TYPEOF(tree.qbegin(bgi::nearest(pt, 10000))) Iter;
for ( Iter it = tree.qbegin(bgi::nearest(pt, 10000)) ; it != tree.qend() ; ++it )
{
// do something with value
if ( has_enough_nearest_values() )
break;
}
\endverbatim
\par Throws
Nothing
\return The iterator pointing at the end of the query range.
*/
detail::rtree::iterators::end_query_iterator<value_type, allocators_type>
qend() const
{
return detail::rtree::end_query_iterator<value_type, allocators_type>();
return detail::rtree::iterators::end_query_iterator<value_type, allocators_type>();
}
#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
/*!
\brief Returns the number of stored values.