traversals are now templated by OrthtreeTraits

This commit is contained in:
Sven Oesau 2024-02-02 09:32:29 +01:00
parent 834b405a09
commit 3c55548967
4 changed files with 52 additions and 59 deletions

View File

@ -15,7 +15,7 @@ using Octree = CGAL::Orthtree<OTraits>;
void dump_as_polylines(const Octree& ot) void dump_as_polylines(const Octree& ot)
{ {
std::ofstream out("octree.polylines.txt"); std::ofstream out("octree.polylines.txt");
for (Octree::Node_index node : ot.traverse(CGAL::Orthtrees::Leaves_traversal<Octree>(ot))) for (Octree::Node_index node : ot.traverse(CGAL::Orthtrees::Leaves_traversal<OTraits>(ot)))
{ {
if (!ot.is_leaf(node)) if (!ot.is_leaf(node))
continue; continue;

View File

@ -12,7 +12,7 @@ using Point = Kernel::Point_3;
using Point_set = CGAL::Point_set_3<Point>; using Point_set = CGAL::Point_set_3<Point>;
using Point_map = Point_set::Point_map; using Point_map = Point_set::Point_map;
using Octree = CGAL::Octree<Kernel, Point_set, Point_map>; using Octree = CGAL::Octree<Kernel, Point_set, Point_map>;
using Preorder_traversal = CGAL::Orthtrees::Preorder_traversal<Octree>; using Preorder_traversal = CGAL::Orthtrees::Preorder_traversal<typename Octree::Traits>;
int main(int argc, char **argv) { int main(int argc, char **argv) {

View File

@ -333,7 +333,7 @@ public:
// Collect all the leaf nodes // Collect all the leaf nodes
std::queue<Node_index> leaf_nodes; std::queue<Node_index> leaf_nodes;
for (Node_index leaf: traverse(Orthtrees::Leaves_traversal<Self>(*this))) { for (Node_index leaf: traverse(Orthtrees::Leaves_traversal<Traits>(*this))) {
leaf_nodes.push(leaf); leaf_nodes.push(leaf);
} }
@ -390,16 +390,11 @@ public:
/*! /*!
* \brief provides direct read-only access to the tree traits. * \brief provides direct read-only access to the tree traits.
*
* @return a const reference to the traits instantiation.
*/ */
const Traits& traits() const { return m_traits; } const Traits& traits() const { return m_traits; }
/*! /*!
\brief provides access to the root node, and by \brief provides access to the root node, and by extension the rest of the tree.
extension the rest of the tree.
\return Node_index of the root node.
*/ */
Node_index root() const { return 0; } Node_index root() const { return 0; }
@ -448,35 +443,6 @@ public:
return traverse(Traversal{*this, std::forward<Args>(args)...}); return traverse(Traversal{*this, std::forward<Args>(args)...});
} }
// TODO shall we document it?
FT
compute_cartesian_coordinate(std::uint32_t gc, std::size_t depth, int ci) const
{
CGAL_assertion(depth <= m_side_per_depth.size());
// an odd coordinate will be first compute at the current depth,
// while an even coordinate has already been computed at a previous depth.
// So while the coordinate is even, we decrease the depth to end up of the first
// non-even coordinate to compute it (with particular case for bbox limits).
// Note that is depth becomes too large, we might end up with incorrect coordinates
// due to rounding errors.
if (gc == (1u << depth)) return (m_bbox.max)()[ci]; // gc == 2^node_depth
if (gc == 0) return (m_bbox.min)()[ci];
if (gc % 2 !=0)
{
FT size = depth < m_side_per_depth.size()
? m_side_per_depth[depth][ci]
: m_side_per_depth[depth-1][ci]/FT(2);
return (m_bbox.min)()[ci] + int(gc) * size;
}
std::size_t nd = depth;
do{
--nd;
gc = gc >> 1;
}
while((gc&1)==0); // while even, shift
return (m_bbox.min)()[ci] + int(gc) * m_side_per_depth[nd][ci];
}
/*! /*!
\brief constructs the bounding box of a node. \brief constructs the bounding box of a node.
@ -1143,6 +1109,33 @@ public:
private: // functions : private: // functions :
FT compute_cartesian_coordinate(std::uint32_t gc, std::size_t depth, int ci) const
{
CGAL_assertion(depth <= m_side_per_depth.size());
// an odd coordinate will be first compute at the current depth,
// while an even coordinate has already been computed at a previous depth.
// So while the coordinate is even, we decrease the depth to end up of the first
// non-even coordinate to compute it (with particular case for bbox limits).
// Note that is depth becomes too large, we might end up with incorrect coordinates
// due to rounding errors.
if (gc == (1u << depth)) return (m_bbox.max)()[ci]; // gc == 2^node_depth
if (gc == 0) return (m_bbox.min)()[ci];
if (gc % 2 != 0)
{
FT size = depth < m_side_per_depth.size()
? m_side_per_depth[depth][ci]
: m_side_per_depth[depth - 1][ci] / FT(2);
return (m_bbox.min)()[ci] + int(gc) * size;
}
std::size_t nd = depth;
do {
--nd;
gc = gc >> 1;
} while ((gc & 1) == 0); // while even, shift
return (m_bbox.min)()[ci] + int(gc) * m_side_per_depth[nd][ci];
}
Node_index recursive_descendant(Node_index node, std::size_t i) { return child(node, i); } Node_index recursive_descendant(Node_index node, std::size_t i) { return child(node, i); }
template <typename... Indices> template <typename... Indices>
@ -1241,7 +1234,7 @@ public:
friend std::ostream& operator<<(std::ostream& os, const Self& orthtree) { friend std::ostream& operator<<(std::ostream& os, const Self& orthtree) {
// Iterate over all nodes // Iterate over all nodes
for (auto n: orthtree.traverse(Orthtrees::Preorder_traversal<Self>(orthtree))) { for (auto n: orthtree.traverse(Orthtrees::Preorder_traversal<Traits>(orthtree))) {
// Show the depth // Show the depth
for (std::size_t i = 0; i < orthtree.depth(n); ++i) for (std::size_t i = 0; i < orthtree.depth(n); ++i)
os << ". "; os << ". ";

View File

@ -28,23 +28,23 @@ namespace Orthtrees {
\ingroup PkgOrthtreeTraversal \ingroup PkgOrthtreeTraversal
\brief A class used for performing a preorder traversal. \brief A class used for performing a preorder traversal.
\tparam Tree an instance of `Orthtree` \tparam GeomTraits must be a model of `OrthtreeTraits`
A preorder traversal starts from the root towards the leaves. A preorder traversal starts from the root towards the leaves.
\cgalModels{OrthtreeTraversal} \cgalModels{OrthtreeTraversal}
*/ */
template <typename Tree> template <typename GeomTraits>
struct Preorder_traversal { struct Preorder_traversal {
private: private:
const Tree& m_orthtree; const Orthtree<GeomTraits>& m_orthtree;
public: public:
using Node_index = typename Tree::Node_index; using Node_index = typename Orthtree<GeomTraits>::Node_index;
Preorder_traversal(const Tree& orthtree) : m_orthtree(orthtree) {} Preorder_traversal(const Orthtree<GeomTraits>& orthtree) : m_orthtree(orthtree) {}
Node_index first_index() const { Node_index first_index() const {
return m_orthtree.root(); return m_orthtree.root();
@ -72,23 +72,23 @@ public:
\ingroup PkgOrthtreeTraversal \ingroup PkgOrthtreeTraversal
\brief A class used for performing a postorder traversal. \brief A class used for performing a postorder traversal.
\tparam Tree an instance of `Orthtree` \tparam GeomTraits must be a model of `OrthtreeTraits`
A postorder traversal starts from the leaves towards the root. A postorder traversal starts from the leaves towards the root.
\cgalModels{OrthtreeTraversal} \cgalModels{OrthtreeTraversal}
*/ */
template <typename Tree> template <typename GeomTraits>
struct Postorder_traversal { struct Postorder_traversal {
private: private:
const Tree& m_orthtree; const Orthtree<GeomTraits>& m_orthtree;
public: public:
using Node_index = typename Tree::Node_index; using Node_index = typename Orthtree<GeomTraits>::Node_index;
Postorder_traversal(const Tree& orthtree) : m_orthtree(orthtree) {} Postorder_traversal(const Orthtree<GeomTraits>& orthtree) : m_orthtree(orthtree) {}
Node_index first_index() const { Node_index first_index() const {
return m_orthtree.deepest_first_child(m_orthtree.root()); return m_orthtree.deepest_first_child(m_orthtree.root());
@ -103,23 +103,23 @@ public:
\ingroup PkgOrthtreeTraversal \ingroup PkgOrthtreeTraversal
\brief A class used for performing a traversal on leaves only. \brief A class used for performing a traversal on leaves only.
\tparam Tree an instance of `Orthtree` \tparam GeomTraits must be a model of `OrthtreeTraits`
All non-leaf nodes are ignored. All non-leaf nodes are ignored.
\cgalModels{OrthtreeTraversal} \cgalModels{OrthtreeTraversal}
*/ */
template <typename Tree> template <typename GeomTraits>
struct Leaves_traversal { struct Leaves_traversal {
private: private:
const Tree& m_orthtree; const Orthtree<GeomTraits>& m_orthtree;
public: public:
using Node_index = typename Tree::Node_index; using Node_index = typename Orthtree<GeomTraits>::Node_index;
Leaves_traversal(const Tree& orthtree) : m_orthtree(orthtree) {} Leaves_traversal(const Orthtree<GeomTraits>& orthtree) : m_orthtree(orthtree) {}
Node_index first_index() const { Node_index first_index() const {
return m_orthtree.deepest_first_child(m_orthtree.root()); return m_orthtree.deepest_first_child(m_orthtree.root());
@ -141,7 +141,7 @@ public:
\ingroup PkgOrthtreeTraversal \ingroup PkgOrthtreeTraversal
\brief A class used for performing a traversal of a specific depth level. \brief A class used for performing a traversal of a specific depth level.
\tparam Tree an instance of `Orthtree` \tparam GeomTraits must be a model of `OrthtreeTraits`
All tree nodes at another depth are ignored. If the selected depth is All tree nodes at another depth are ignored. If the selected depth is
All tree nodes at another depth are ignored. If the selected depth is All tree nodes at another depth are ignored. If the selected depth is
@ -149,21 +149,21 @@ public:
\cgalModels{OrthtreeTraversal} \cgalModels{OrthtreeTraversal}
*/ */
template <typename Tree> template <typename GeomTraits>
struct Level_traversal { struct Level_traversal {
private: private:
const Tree& m_orthtree; const Orthtree<GeomTraits>& m_orthtree;
const std::size_t m_depth; const std::size_t m_depth;
public: public:
using Node_index = typename Tree::Node_index; using Node_index = typename Orthtree<GeomTraits>::Node_index;
/*! /*!
constructs a `depth`-level traversal. constructs a `depth`-level traversal.
*/ */
Level_traversal(const Tree& orthtree, std::size_t depth) : m_orthtree(orthtree), m_depth(depth) {} Level_traversal(const Orthtree<GeomTraits>& orthtree, std::size_t depth) : m_orthtree(orthtree), m_depth(depth) {}
Node_index first_index() const { Node_index first_index() const {
// assumes the tree has at least one child at m_depth // assumes the tree has at least one child at m_depth