diff --git a/Orthtree/include/CGAL/Orthtree.h b/Orthtree/include/CGAL/Orthtree.h index 4b39fde2767..d908de7adf0 100644 --- a/Orthtree/include/CGAL/Orthtree.h +++ b/Orthtree/include/CGAL/Orthtree.h @@ -436,12 +436,22 @@ public: \brief provides read-write access to the root node, and by extension the rest of the tree. - todo: why wasn't this provided previously? - \return a reference to the root node of the tree. */ Node& root() { return m_nodes[0]; } + std::size_t index(const Node& node) const { + return std::distance(m_nodes.data(), &node); + } + + const Node& operator[](std::size_t index) const { + return m_nodes[index]; + } + + Node& operator[](std::size_t index) { + return m_nodes[index]; + } + /*! \brief returns the deepest level reached by a leaf node in this tree (root being level 0). */ @@ -665,6 +675,86 @@ public: return node.m_children.get(); } + const Node* next_sibling(const Node* n) const { + + // todo: maybe this should take a reference? + if (nullptr == n) + return nullptr; + + // If this node has no parent, it has no siblings + if (n->is_root()) + return nullptr; + + // Find out which child this is + std::size_t index = n->local_coordinates().to_ulong(); + + constexpr static int degree = Node::Degree::value; + + // Return null if this is the last child + if (int(index) == degree - 1) + return nullptr; + + // Otherwise, return the next child + return &(children(parent(*n))[index + 1]); + } + + const Node* next_sibling_up(const Node* n) const { + + if (!n || n->is_root()) return nullptr; + + auto up = &parent(*n); + while (nullptr != up) { + + if (nullptr != next_sibling(up)) + return next_sibling(up); + + // todo: this could be cleaned up; it's probably not necessary to involve pointers here + up = up->is_root() ? nullptr : &parent(*up); + } + + return nullptr; + } + + const Node* deepest_first_child(const Node* n) const { + + if (n == nullptr) + return nullptr; + + // Find the deepest child on the left + auto first = n; + while (!first->is_leaf()) + first = &children(*first)[0]; + return first; + } + + + const Node* first_child_at_depth(const Node* n, std::size_t depth) const { + + if (!n) + return nullptr; + + std::stack todo; + todo.push(n); + + if (n->depth() == depth) + return n; + + while (!todo.empty()) { + const Node* node = todo.top(); + todo.pop(); + + if (node->depth() == depth) + return node; + + if (!node->is_leaf()) + for (int i = 0; i < Node::Degree::value; ++i) + todo.push(&((*node)[std::size_t(Node::Degree::value - 1 - i)])); + } + + return nullptr; + } + + /*! \brief splits the node into subnodes. diff --git a/Orthtree/include/CGAL/Orthtree/Traversals.h b/Orthtree/include/CGAL/Orthtree/Traversals.h index 5f3dcc54e74..8814219305b 100644 --- a/Orthtree/include/CGAL/Orthtree/Traversals.h +++ b/Orthtree/include/CGAL/Orthtree/Traversals.h @@ -31,94 +31,6 @@ class Orthtree; namespace Orthtrees { -/// \cond SKIP_IN_MANUAL - -// todo: all of these could be members of Orthtree - -template -const typename Tree::Node* next_sibling(const Tree& orthtree, const typename Tree::Node* n) { - - // todo: maybe this should take a reference? - if (nullptr == n) - return nullptr; - - // If this node has no parent, it has no siblings - if (n->is_root()) - return nullptr; - - // Find out which child this is - std::size_t index = n->local_coordinates().to_ulong(); - - constexpr static int degree = Tree::Node::Degree::value; - // Return null if this is the last child - if (int(index) == degree - 1) - return nullptr; - - // Otherwise, return the next child - return &(orthtree.children(orthtree.parent(*n))[index + 1]); -} - -template -const typename Tree::Node* next_sibling_up(const Tree& orthtree, const typename Tree::Node* n) { - - if (!n || n->is_root()) return nullptr; - - auto up = &orthtree.parent(*n); - while (nullptr != up) { - - if (nullptr != next_sibling(orthtree, up)) - return next_sibling(orthtree, up); - - // todo: this could be cleaned up; it's probably not necessary to involve pointers here - up = up->is_root() ? nullptr : &orthtree.parent(*up); - } - - return nullptr; -} - -template -const typename Tree::Node* deepest_first_child(const Tree& orthtree, const typename Tree::Node* n) { - - if (n == nullptr) - return nullptr; - - // Find the deepest child on the left - auto first = n; - while (!first->is_leaf()) - first = &orthtree.children(*first)[0]; - return first; -} - - -template -const typename Tree::Node* first_child_at_depth(const Tree& orthtree, const typename Tree::Node* n, std::size_t depth) { - - if (!n) - return nullptr; - - std::stack todo; - todo.push(n); - - if (n->depth() == depth) - return n; - - while (!todo.empty()) { - const typename Tree::Node* node = todo.top(); - todo.pop(); - - if (node->depth() == depth) - return node; - - if (!node->is_leaf()) - for (int i = 0; i < Tree::Node::Degree::value; ++i) - todo.push(&((*node)[std::size_t(Tree::Node::Degree::value - 1 - i)])); - } - - return nullptr; -} - -/// \endcond - /*! \ingroup PkgOrthtreeTraversal \brief A class used for performing a preorder traversal. @@ -147,11 +59,11 @@ public: if (n->is_leaf()) { - auto next = next_sibling(m_orthtree, n); + auto next = m_orthtree.next_sibling(n); if (nullptr == next) { - return next_sibling_up(m_orthtree, n); + return m_orthtree.next_sibling_up(n); } return next; @@ -221,15 +133,15 @@ public: Leaves_traversal(const Tree& orthtree) : m_orthtree(orthtree) {} const Node* first() const { - return deepest_first_child(m_orthtree, &m_orthtree.root()); + return m_orthtree.deepest_first_child(&m_orthtree.root()); } const Node* next(const Node* n) const { - auto next = deepest_first_child(m_orthtree, next_sibling(m_orthtree, n)); + auto next = m_orthtree.deepest_first_child(m_orthtree.next_sibling(n)); if (!next) - next = deepest_first_child(m_orthtree, next_sibling_up(m_orthtree, n)); + next = m_orthtree.deepest_first_child(m_orthtree.next_sibling_up(n)); return next; } @@ -262,21 +174,21 @@ public: template const Node* first() const { - return first_child_at_depth(m_orthtree, m_orthtree.root(), m_depth); + return m_orthtree.first_child_at_depth(m_orthtree.root(), m_depth); } template const Node* next(const Node* n) const { - const Node* next = next_sibling(m_orthtree, n); + const Node* next = m_orthtree.next_sibling(n); if (!next) { const Node* up = n; do { - up = next_sibling_up(m_orthtree, up); + up = m_orthtree.next_sibling_up(up); if (!up) return nullptr; - next = first_child_at_depth(m_orthtree, up, m_depth); + next = m_orthtree.first_child_at_depth(up, m_depth); } while (!next); }