You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

294 lines
11 KiB
Plaintext

// Included by octree.h
/**\typedef template<typename T_,typename R_,typename P_,typename O_,typename OP_,int d_> \
* typedef O_ octree_iterator<T_,R_,P_,O_,OP_,d_>::octree_type;
* \brief Shorthand for an octree over which this class can iterate.
*/
/**\typedef template<typename T_,typename R_,typename P_,typename O_,typename OP_,int d_> \
* typedef OP_ octree_iterator<T_,R_,P_,O_,OP_,d_>::octree_pointer;
* \brief Shorthand for a pointer to an octree over which this class can iterate.
*/
/**\typedef template<typename T_,typename R_,typename P_,typename O_,typename OP_,int d_> \
* typedef typename O_::allocator_type
* octree_iterator<T_,R_,P_,O_,OP_,d_>::octree_allocator_type; \brief Shorthand for the allocator
* used by the octrees over which this class iterates.
*/
/**\typedef template<typename T_,typename R_,typename P_,typename O_,typename OP_,int d_> \
* typedef typename O_::octree_node_reference
* octree_iterator<T_,R_,P_,O_,OP_,d_>::octree_node_reference; \brief Shorthand for a reference to a
* node in the octree.
*/
/**\typedef template<typename T_,typename R_,typename P_,typename O_,typename OP_,int d_> \
* typedef typename O_::octree_node_pointer
* octree_iterator<T_,R_,P_,O_,OP_,d_>::octree_node_pointer; \brief Shorthand for a pointer to a
* node in the octree.
*/
/**\typedef template<typename T_,typename R_,typename P_,typename O_,typename OP_,int d_> \
* typedef std::bidirectional_iterator_tag
* octree_iterator<T_,R_,P_,O_,OP_,d_>::iterator_category; \brief A tag used by the STL to determine
* what algorithms may be applied to the octree container.
*/
/**\typedef template<typename T_,typename R_,typename P_,typename O_,typename OP_,int d_> \
* typedef octree_iterator< T_, T_&, T_*, O_, O_*, d_ >
* octree_iterator<T_,R_,P_,O_,OP_,d_>::iterator; \brief Shorthand for a non-const octree iterator
* (regardless of whether the current iterator is const or not).
*/
/**\typedef template<typename T_,typename R_,typename P_,typename O_,typename OP_,int d_> \
* typedef octree_iterator< T_, const T_&, const T_*, O_, const O_*, d_ >
* octree_iterator<T_,R_,P_,O_,OP_,d_>::const_iterator; \brief Shorthand for a const octree iterator
* (regardless of whether the current iterator is const or not).
*/
/**\typedef template<typename T_,typename R_,typename P_,typename O_,typename OP_,int d_> \
* typedef octree_iterator< T_, R_, P_, O_, OP_, d_ >
* octree_iterator<T_,R_,P_,O_,OP_,d_>::self_iterator; \brief Shorthand for an iterator of the same
* type as the current iterator (be it const or not).
*/
/**\var template<typename T_,typename R_,typename P_,typename O_,typename OP_,int d_> \
* bool octree_iterator<T_,R_,P_,O_,OP_,d_>::_M_immediate_family
*\brief Iterate over all the subnodes or just the direct children?
*/
/**\var template<typename T_,typename R_,typename P_,typename O_,typename OP_,int d_> \
* bool octree_iterator<T_,R_,P_,O_,OP_,d_>::_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<T_, R_, P_, O_, OP_, d_>::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<T_, R_, P_, O_, OP_, d_>::octree_iterator(
octree_node_pointer oroot, octree_node_pointer onode, bool only_leaves)
: octree_path<T_, R_, P_, O_, OP_, d_>(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<T_, R_, P_, O_, OP_, d_>::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<T_, R_, P_, O_, OP_, d_>::octree_node_pointer
octree_iterator<T_, R_, P_, O_, OP_, d_>::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 << d_))
{
this->_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 << d_))
{
break;
}
}
}
// 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 = 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<T_, R_, P_, O_, OP_, d_>::octree_node_pointer
octree_iterator<T_, R_, P_, O_, OP_, d_>::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 << d_) - 1;
this->_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 << d_) - 1;
// Uptown. (Climb upwards to the first non-traversed node)
while (1)
{
if (this->_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 << d_) - 1;
}
return this->_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<T_, R_, P_, O_, OP_, d_>::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<T_,R_,P_,O_,OP_,d_>::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<T_,R_,P_,O_,OP_,d_>::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<T_,R_,P_,O_,OP_,d_>::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<T_,R_,P_,O_,OP_,d_>::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<T_,R_,P_,O_,OP_,d_>::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<T_,R_,P_,O_,OP_,d_>::operator -- ( int )
*\brief Move to the previous node in the octree that satisfied the traversal criteria.
*/