// Included by octree.h /**\typedef template \ * typedef O_ octree_iterator::octree_type; * \brief Shorthand for an octree over which this class can iterate. */ /**\typedef template \ * typedef OP_ octree_iterator::octree_pointer; * \brief Shorthand for a pointer to an octree over which this class can iterate. */ /**\typedef template \ * typedef typename O_::allocator_type octree_iterator::octree_allocator_type; * \brief Shorthand for the allocator used by the octrees over which this class iterates. */ /**\typedef template \ * typedef typename O_::octree_node_reference octree_iterator::octree_node_reference; * \brief Shorthand for a reference to a node in the octree. */ /**\typedef template \ * typedef typename O_::octree_node_pointer octree_iterator::octree_node_pointer; * \brief Shorthand for a pointer to a node in the octree. */ /**\typedef template \ * typedef std::bidirectional_iterator_tag octree_iterator::iterator_category; * \brief A tag used by the STL to determine what algorithms may be applied to the octree container. */ /**\typedef template \ * typedef octree_iterator< T_, T_&, T_*, O_, O_*, d_ > octree_iterator::iterator; * \brief Shorthand for a non-const octree iterator (regardless of whether the current iterator is const or not). */ /**\typedef template \ * typedef octree_iterator< T_, const T_&, const T_*, O_, const O_*, d_ > octree_iterator::const_iterator; * \brief Shorthand for a const octree iterator (regardless of whether the current iterator is const or not). */ /**\typedef template \ * typedef octree_iterator< T_, R_, P_, O_, OP_, d_ > octree_iterator::self_iterator; * \brief Shorthand for an iterator of the same type as the current iterator (be it const or not). */ /**\var template \ * bool octree_iterator::_M_immediate_family *\brief Iterate over all the subnodes or just the direct children? */ /**\var template \ * bool octree_iterator::_M_only_leaf_nodes *\brief Should the iterator visit all nodes or only leaf nodes? */ /**\brief Default constructor. */ template< typename T_, typename R_, typename P_, typename O_, typename OP_, int d_ > octree_iterator::octree_iterator() { this->_M_only_leaf_nodes = true; this->_M_immediate_family = false; } /**\brief Constructor for use by octree_type's begin() and end() methods. * */ template< typename T_, typename R_, typename P_, typename O_, typename OP_, int d_ > octree_iterator::octree_iterator( octree_node_pointer oroot, octree_node_pointer onode, bool only_leaves ) : octree_path( oroot ) { // WARNING: This method assumes onode is either the root node of the tree or the "tail" of the sequence. // In order to be completely general, this method would have to search the entire octree for onode and // maintain _M_indices & _M_current_index as it searched. this->_M_only_leaf_nodes = only_leaves; this->_M_immediate_family = false; this->_M_current_node = onode; if ( this->_M_only_leaf_nodes ) { while ( this->_M_current_node && this->_M_current_node->_M_children ) { this->_M_indices.push_back( 0 ); this->_M_parents.push_back( this->_M_current_node ); this->_M_current_node = this->_M_current_node->_M_children; } } } /**\brief A copy constructor. * */ template< typename T_, typename R_, typename P_, typename O_, typename OP_, int d_ > octree_iterator::octree_iterator( const const_iterator& it ) { this->_M_root = it._M_root; this->_M_immediate_family = it._M_immediate_family; this->_M_only_leaf_nodes = it._M_only_leaf_nodes; this->_M_indices = it._M_indices; this->_M_parents = it._M_parents; this->_M_current_node = it._M_current_node; } /**\brief Utility routine used to advance the iterator if possible. * */ template< typename T_, typename R_, typename P_, typename O_, typename OP_, int d_ > typename octree_iterator::octree_node_pointer octree_iterator::check_incr() { if ( ! this->_M_root ) { throw std::logic_error( "Can't increment iterator with null octree pointer." ); } // Oldtown. (We're at the end) if ( ! this->_M_current_node ) { return nullptr; } int child = 0; // Uptown. (Climb upwards to the first non-traversed, non-leaf node) if ( this->_M_immediate_family ) { if ( this->_M_indices.empty() ) { return nullptr; } this->_M_current_node = this->_M_parents.back(); child = this->_M_indices.back() + 1; this->_M_parents.pop_back(); this->_M_indices.pop_back(); if ( child >= (1<_M_current_node = nullptr; // move to the end, but don't clear out parents/indices return nullptr; } } else if ( this->_M_current_node->is_leaf_node() ) { while ( 1 ) { if ( this->_M_indices.empty() ) { return nullptr; } this->_M_current_node = this->_M_parents.back(); child = this->_M_indices.back() + 1; this->_M_parents.pop_back(); this->_M_indices.pop_back(); if ( child < (1<_M_current_node->is_leaf_node() ) { this->_M_parents.push_back( this->_M_current_node ); this->_M_indices.push_back( child ); this->_M_current_node = this->_M_current_node->_M_children + child; child = 0; if ( ! this->_M_only_leaf_nodes || this->_M_immediate_family ) break; } return this->_M_current_node; } /**\brief Utility routine used to back up the iterator if possible. * */ template< typename T_, typename R_, typename P_, typename O_, typename OP_, int d_ > typename octree_iterator::octree_node_pointer octree_iterator::check_decr() { if ( ! this->_M_root ) { throw std::logic_error( "Can't decrement iterator with null octree pointer." ); } // Oldtown. (We're at the end) if ( ! this->_M_current_node ) { // Descend to last leaf this->_M_current_node = this->_M_root; while ( this->_M_current_node && this->_M_current_node->_M_children ) { int child = (1<_M_indices.push_back( child ); this->_M_parents.push_back( this->_M_current_node ); this->_M_current_node = this->_M_current_node->_M_children + child; } return this->_M_current_node; } else if ( this->_M_current_node == this->_M_root ) { // We're at the beginning node... can't go back any more // FIXME: What do we do when traversing only leaf nodes? The root isn't the beginning any more... octree_node_pointer tmp = this->_M_current_node; //this->_M_current_node = 0; // go back to "end" after reporting the beginning node. return tmp; } int child = (1<_M_indices.empty() ) { // Last node is root node. Report it if we should. if ( ( this->_M_only_leaf_nodes && this->_M_current_node->is_leaf_node() ) || ( ! this->_M_only_leaf_nodes ) ) { return this->_M_current_node; } else { // Oops, we were already at "begin()"... go past end. octree_node_pointer tmp = this->_M_current_node; //this->_M_current_node = 0; // go back to "end" after reporting the beginning node. return tmp; } } this->_M_current_node = this->_M_parents.back(); child = this->_M_indices.back() - 1; this->_M_parents.pop_back(); this->_M_indices.pop_back(); if ( this->_M_only_leaf_nodes ) { if ( child >= 0 ) { break; } } else { if ( child >= -1 ) { break; } } } // Midtown. (Stop at non-leaf nodes if so ordered) if ( child < 0 ) { return this->_M_current_node; } // Downtown. (Climb down to the next node) while ( ! this->_M_current_node->is_leaf_node() ) { this->_M_parents.push_back( this->_M_current_node ); this->_M_indices.push_back( child ); this->_M_current_node = this->_M_current_node->_M_children + child; child = (1<_M_current_node; } /**\brief Force the iterator to traverse only siblings and not children or parent nodes. * */ template< typename T_, typename R_, typename P_, typename O_, typename OP_, int d_ > void octree_iterator::immediate_family( bool val ) { this->_M_immediate_family = val; } /**\fn template< typename T_, typename R_, typename P_, typename O_, typename OP_, int d_ > \ * bool octree_iterator::immediate_family() const *\brief Return whether the iterator is set to traverse the entire tree or just the siblings of the current node. */ /**\fn template< typename T_, typename R_, typename P_, typename O_, typename OP_, int d_ > \ * bool& octree_iterator::immediate_family() *\brief Return whether the iterator is set to traverse the entire tree or just the siblings of the current node. */ /**\fn template< typename T_, typename R_, typename P_, typename O_, typename OP_, int d_ > \ * self_iterator& octree_iterator::operator ++ () *\brief Move to the next node in the octree that satisfies the traversal criteria. */ /**\fn template< typename T_, typename R_, typename P_, typename O_, typename OP_, int d_ > \ * self_iterator octree_iterator::operator ++ ( int ) *\brief Move to the next node in the octree that satisfies the traversal criteria. */ /**\fn template< typename T_, typename R_, typename P_, typename O_, typename OP_, int d_ > \ * self_iterator& octree_iterator::operator -- () *\brief Move to the previous node in the octree that satisfied the traversal criteria. */ /**\fn template< typename T_, typename R_, typename P_, typename O_, typename OP_, int d_ > \ * self_iterator octree_iterator::operator -- ( int ) *\brief Move to the previous node in the octree that satisfied the traversal criteria. */