From fcc99ddbcb34e4d1bb31a850cced384ce62e7275 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Tue, 16 Apr 2013 22:08:55 +0000 Subject: [PATCH] geometry.index: added experimental spatial query iterator and rtree::qbegin() and rtree::qend() methods, added allocator_type to Allocators. [SVN r83935] --- .../detail/rtree/node/node_d_mem_dynamic.hpp | 1 + .../detail/rtree/node/node_d_mem_static.hpp | 1 + .../detail/rtree/node/node_s_mem_dynamic.hpp | 1 + .../detail/rtree/node/node_s_mem_static.hpp | 1 + .../detail/rtree/visitors/spatial_query.hpp | 225 +++++++++++++----- include/boost/geometry/index/rtree.hpp | 85 +++++++ 6 files changed, 254 insertions(+), 60 deletions(-) diff --git a/include/boost/geometry/index/detail/rtree/node/node_d_mem_dynamic.hpp b/include/boost/geometry/index/detail/rtree/node/node_d_mem_dynamic.hpp index 0e04c144f..ba15c0b44 100644 --- a/include/boost/geometry/index/detail/rtree/node/node_d_mem_dynamic.hpp +++ b/include/boost/geometry/index/detail/rtree/node/node_d_mem_dynamic.hpp @@ -165,6 +165,7 @@ class allocators >::other { public: + typedef Allocator allocator_type; typedef typename Allocator::size_type size_type; typedef typename Allocator::template rebind< diff --git a/include/boost/geometry/index/detail/rtree/node/node_d_mem_static.hpp b/include/boost/geometry/index/detail/rtree/node/node_d_mem_static.hpp index 8212aa605..0bf3fcc5a 100644 --- a/include/boost/geometry/index/detail/rtree/node/node_d_mem_static.hpp +++ b/include/boost/geometry/index/detail/rtree/node/node_d_mem_static.hpp @@ -114,6 +114,7 @@ class allocators >::other { public: + typedef Allocator allocator_type; typedef typename Allocator::size_type size_type; typedef typename Allocator::template rebind< diff --git a/include/boost/geometry/index/detail/rtree/node/node_s_mem_dynamic.hpp b/include/boost/geometry/index/detail/rtree/node/node_s_mem_dynamic.hpp index 8405e1bc7..f75b89921 100644 --- a/include/boost/geometry/index/detail/rtree/node/node_s_mem_dynamic.hpp +++ b/include/boost/geometry/index/detail/rtree/node/node_s_mem_dynamic.hpp @@ -97,6 +97,7 @@ class allocators >::other { public: + typedef Allocator allocator_type; typedef typename Allocator::size_type size_type; typedef typename Allocator::template rebind< diff --git a/include/boost/geometry/index/detail/rtree/node/node_s_mem_static.hpp b/include/boost/geometry/index/detail/rtree/node/node_s_mem_static.hpp index c0c7dcb10..a3e572576 100644 --- a/include/boost/geometry/index/detail/rtree/node/node_s_mem_static.hpp +++ b/include/boost/geometry/index/detail/rtree/node/node_s_mem_static.hpp @@ -95,6 +95,7 @@ struct allocators >::other { public: + typedef Allocator allocator_type; typedef typename Allocator::size_type size_type; typedef typename Allocator::template rebind< diff --git a/include/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp b/include/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp index 4a4ac8a2b..abebc1615 100644 --- a/include/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp +++ b/include/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp @@ -75,67 +75,172 @@ struct spatial_query size_type found_count; }; -//template -//struct spatial_query_incremental -// : public rtree::visitor::type -//{ -// typedef typename rtree::node::type node; -// typedef typename rtree::internal_node::type internal_node; -// typedef typename rtree::leaf::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::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::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(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::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(pred, *it, tr(*it)) ) -// //{ -// // out_iter = *it; -// // ++out_iter; -// -// // ++found_count; -// //} -// } -// -// Translator const& tr; -// Predicates pred; -// -// typedef typename rtree::elements_type::type::const_iterator internal_iterator; -// typedef typename rtree::elements_type::type::const_iterator leaf_iterator; -// -// std::vector< std::pair > internal_stack; -// std::pair leaf_range; -//}; +template +struct spatial_query_incremental + : public rtree::visitor::type +{ + typedef typename rtree::node::type node; + typedef typename rtree::internal_node::type internal_node; + typedef typename rtree::leaf::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::type::const_iterator internal_iterator; + typedef typename rtree::elements_type::type leaf_elements; + + static const unsigned predicates_len = index::detail::predicates_length::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::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::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(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(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_stack; + const leaf_elements * values; + size_type value_index; +}; + +} // namespace visitors + +template +class spatial_query_iterator +{ + typedef visitors::spatial_query_incremental 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::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 diff --git a/include/boost/geometry/index/rtree.hpp b/include/boost/geometry/index/rtree.hpp index 0b27df4e8..214c25835 100644 --- a/include/boost/geometry/index/rtree.hpp +++ b/include/boost/geometry/index/rtree.hpp @@ -719,6 +719,40 @@ public: return query_dispatch(predicates, out_it, boost::mpl::bool_()); } +#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL + + template + typename boost::mpl::if_c< + detail::predicates_count_nearest::value == 0, + detail::rtree::spatial_query_iterator, + void + >::type + qbegin(Predicates const& predicates) const + { + static const unsigned nearest_count = detail::predicates_count_nearest::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_()); + } + + template + typename boost::mpl::if_c< + detail::predicates_count_nearest::value == 0, + detail::rtree::spatial_query_iterator, + void + >::type + qend(Predicates const& predicates) const + { + static const unsigned nearest_count = detail::predicates_count_nearest::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_()); + } + +#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 + boost::mpl::if_c< + detail::predicates_count_nearest::value == 0, + detail::rtree::spatial_query_iterator, + void + >::type + qbegin_dispatch(Predicates const& predicates, boost::mpl::bool_ 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 + void qbegin_dispatch(Predicates const& predicates, boost::mpl::bool_ const& /*is_nearest*/) const + { + BOOST_MPL_ASSERT_MSG(false, NEAREST_QUERY_ITERATOR_NOT_IMPLEMENTED_YET, (rtree)); + } + + template + typename + boost::mpl::if_c< + detail::predicates_count_nearest::value == 0, + detail::rtree::spatial_query_iterator, + void + >::type + qend_dispatch(Predicates const& predicates, boost::mpl::bool_ 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 + void qend_dispatch(Predicates const& predicates, boost::mpl::bool_ 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.