// 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 class iterator : public rtree::visitor::type { public: 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::const_reference const_reference; 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; typedef typename rtree::elements_type::type::const_iterator leaf_iterator; inline iterator() : m_values(NULL) , m_current() {} inline void operator()(internal_node const& n) { typedef typename rtree::elements_type::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 > 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