diff --git a/Orthtree/include/CGAL/Orthtree.h b/Orthtree/include/CGAL/Orthtree.h index 49ab9b570ef..8baca1abc53 100644 --- a/Orthtree/include/CGAL/Orthtree.h +++ b/Orthtree/include/CGAL/Orthtree.h @@ -736,48 +736,20 @@ public: return children(m_nodes[node]); } - const Node* _next_sibling(const Node* n) const { + const boost::optional next_sibling(Node_index 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; + // Root node has no siblings + if (is_root(n)) return {}; // Find out which child this is - std::size_t local_coordinates = n->local_coordinates().to_ulong(); + std::size_t local_coordinates = m_nodes[n].local_coordinates().to_ulong(); // todo: add local_coordinates(n) helper - constexpr static int degree = Node::Degree::value; + // The last child has no more siblings + if (int(local_coordinates) == Node::Degree::value - 1) + return {}; - // Return null if this is the last child - if (int(local_coordinates) == degree - 1) - return nullptr; - - // Otherwise, return the next child - return &(children(parent(*n))[local_coordinates + 1]); - } - - const boost::optional next_sibling(Node_index n) const { - return index(_next_sibling(&m_nodes[n])); - } - - 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; + // The next sibling is the child of the parent with the following local coordinates + return index(children(parent(n))[local_coordinates + 1]); } const boost::optional next_sibling_up(Node_index n) const { @@ -796,47 +768,13 @@ public: return {}; } - 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; - } - Node_index deepest_first_child(Node_index n) const { - return index(deepest_first_child(&m_nodes[n])).get(); - } - const Node* first_child_at_depth(const Node* n, std::size_t depth) const { + auto first = n; + while (!is_leaf(first)) + first = index(children(first)[0]); - if (!n) - return nullptr; - - // todo: use Node_index instead of pointer - 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; + return first; } boost::optional first_child_at_depth(Node_index n, std::size_t d) const { @@ -859,7 +797,6 @@ public: return {}; } - /*! \brief splits the node into subnodes. @@ -869,8 +806,6 @@ public: Contents of this node are _not_ propagated automatically. It is the responsibility of the caller to redistribute the points contained by a node after splitting */ - void split(Node& node) { split(index(node)); } - void split(Node_index n) { // Make sure the node hasn't already been split @@ -898,25 +833,21 @@ public: * After un-splitting a node it will be considered a leaf node. * Idempotent, un-splitting a leaf node has no effect. */ - void unsplit(Node& node) { - node.m_children_index.reset(); - } - void unsplit(Node_index n) { - unsplit(m_nodes[n]); + m_nodes[n].m_children_index.reset(); + // todo: the child nodes should be de-allocated! } - // todo: documentation - Point barycenter(const Node& node) const { + Point barycenter(Node_index n) const { // Determine the side length of this node - FT size = m_side_per_depth[node.depth()]; + FT size = m_side_per_depth[depth(n)]; // Determine the location this node should be split Array bary; std::size_t i = 0; for (const FT& f: cartesian_range(m_bbox_min)) { - bary[i] = FT(node.global_coordinates()[i]) * size + size / FT(2) + f; + bary[i] = FT(m_nodes[n].global_coordinates()[i]) * size + size / FT(2) + f; ++i; } @@ -926,10 +857,6 @@ public: return construct_point_d_from_array(bary); } - Point barycenter(Node_index n) const { - return barycenter(m_nodes[n]); - } - // todo: this does what the documentation for operator== claims to do! static bool is_topology_equal(const Node& lhsNode, const Self& lhsTree, const Node& rhsNode, const Self& rhsTree) { diff --git a/Orthtree/include/CGAL/Orthtree/Traversals.h b/Orthtree/include/CGAL/Orthtree/Traversals.h index 7cc9dfb5349..43340498868 100644 --- a/Orthtree/include/CGAL/Orthtree/Traversals.h +++ b/Orthtree/include/CGAL/Orthtree/Traversals.h @@ -153,7 +153,7 @@ public: } typename Tree::Node_index first_index() const { - return m_orthtree.index(first()).get(); + return m_orthtree.deepest_first_child(0); } const Node* next(const Node* n) const { diff --git a/Orthtree/test/Orthtree/test_octree_refine.cpp b/Orthtree/test/Orthtree/test_octree_refine.cpp index 71f95913050..e960d6bd616 100644 --- a/Orthtree/test/Orthtree/test_octree_refine.cpp +++ b/Orthtree/test/Orthtree/test_octree_refine.cpp @@ -54,7 +54,7 @@ void test_2_points() { // The octree should have been split once Octree other(points, points.point_map()); - other.split(other.root()); + other.split(other.index(other.root())); assert(Octree::is_topology_equal(other, octree)); assert(1 == octree.depth()); } @@ -73,15 +73,15 @@ void test_4_points() { // The octree should have been split once on the first level, and twice on the second Octree other(points, points.point_map()); - other.split(other.root()); - other.split(other.children(other.root())[3]); - other.split(other.children(other.root())[7]); + other.split(other.index(other.root())); + other.split(other.index(other.children(other.root())[3])); + other.split(other.index(other.children(other.root())[7])); assert(Octree::is_topology_equal(other, octree)); assert(2 == octree.depth()); // Applying another splitting criterion shouldn't reset the tree. octree.refine(Split_nth_child_of_root(2)); - other.split(other.children(other.root())[2]); + other.split(other.index(other.children(other.root())[2])); assert(Octree::is_topology_equal(other, octree)); }