Fix traversal concept, model and examples

This commit is contained in:
Simon Giraudot 2021-01-19 13:31:41 +01:00
parent 11aa2c24f5
commit a906b12b3c
11 changed files with 64 additions and 27 deletions

View File

@ -3,28 +3,33 @@
\ingroup PkgOrthtreeConcepts \ingroup PkgOrthtreeConcepts
\cgalConcept \cgalConcept
\brief a Traversal provides the functions needed to traverse the \brief a traversal provides the functions needed to traverse the
nodes of an Orthtree. nodes of an Orthtree.
A traversal is used to iterate on a tree with a user-selected order A traversal is used to iterate on a tree with a user-selected order
(e.g. Preorder, Postorder). (e.g. Preorder, Postorder).
Template parameters are the template parameters of the `CGAL::Orthtree`,
please refer to the documentation of this class for more
information.
\cgalHasModel `CGAL::Orthtrees::Traversal::Preorder` \cgalHasModel `CGAL::Orthtrees::Traversal::Preorder`
\cgalHasModel `CGAL::Orthtrees::Traversal::Postorder` \cgalHasModel `CGAL::Orthtrees::Traversal::Postorder`
\cgalHasModel `CGAL::Orthtrees::Traversal::Leaves` \cgalHasModel `CGAL::Orthtrees::Traversal::Leaves`
*/ */
template<typename T, typename PR, typename PM>
class Traversal { class Traversal {
public: public:
using Node = typename CGAL::Orthtree<T,PR,PM>::Node; ///< The node type
/*! /*!
\brief returns the first node to iterate to, given the root of the Orthtree. \brief returns the first node to iterate to, given the root of the Orthtree.
*/ */
template<typename Node>
Node first (Node root) const; Node first (Node root) const;
/*! /*!
\brief returns the next node to iterate to, given the previous node. \brief returns the next node to iterate to, given the previous node.
*/ */
template<typename Node>
Node next(Node n) const; Node next(Node n) const;
}; };

View File

@ -57,8 +57,8 @@
- `CGAL::Orthtrees::Split_predicate::Maximum_depth_and_maximum_number_of_inliers` - `CGAL::Orthtrees::Split_predicate::Maximum_depth_and_maximum_number_of_inliers`
\cgalCRPSection{%Traversal} \cgalCRPSection{%Traversal}
- `CGAL::Orthtrees::Traversal::Preorder` - `CGAL::Orthtrees::Traversal::Preorder<Traits, PointRange, PointMap>`
- `CGAL::Orthtrees::Traversal::Postorder` - `CGAL::Orthtrees::Traversal::Postorder<Traits, PointRange, PointMap>`
- `CGAL::Orthtrees::Traversal::Leaves` - `CGAL::Orthtrees::Traversal::Leaves<Traits, PointRange, PointMap>`
*/ */

View File

@ -13,16 +13,15 @@ typedef CGAL::Point_set_3<Point> Point_set;
typedef Point_set::Point_map Point_map; typedef Point_set::Point_map Point_map;
typedef CGAL::Octree<Kernel, Point_set, Point_map> Octree; typedef CGAL::Octree<Kernel, Point_set, Point_map> Octree;
typedef Octree::Node Node;
struct First_branch_traversal struct First_branch_traversal
{ {
template <typename Node>
Node first (Node root) const Node first (Node root) const
{ {
return root; return root;
} }
template <typename Node>
Node next (Node n) const Node next (Node n) const
{ {
if (n.is_leaf()) if (n.is_leaf())

View File

@ -13,6 +13,7 @@ typedef CGAL::Point_set_3<Point> Point_set;
typedef Point_set::Point_map Point_map; typedef Point_set::Point_map Point_map;
typedef CGAL::Octree<Kernel, Point_set, Point_map> Octree; typedef CGAL::Octree<Kernel, Point_set, Point_map> Octree;
typedef CGAL::Orthtrees::Traversal::Preorder<typename Octree::Traits, Point_set, Point_map> Preorder_traversal;
int main(int argc, char **argv) { int main(int argc, char **argv) {
@ -36,7 +37,7 @@ int main(int argc, char **argv) {
octree.refine(); octree.refine();
// Print out the octree using preorder traversal // Print out the octree using preorder traversal
for (Octree::Node node : octree.traverse<CGAL::Orthtrees::Traversal::Preorder>()) { for (Octree::Node node : octree.traverse<Preorder_traversal>()) {
std::cout << node << std::endl; std::cout << node << std::endl;
} }

View File

@ -139,6 +139,9 @@ public:
typedef typename PointRange::iterator Range_iterator; typedef typename PointRange::iterator Range_iterator;
typedef typename std::iterator_traits<Range_iterator>::value_type Range_type; typedef typename std::iterator_traits<Range_iterator>::value_type Range_type;
typedef internal::Cartesian_ranges<Traits> Cartesian_ranges; typedef internal::Cartesian_ranges<Traits> Cartesian_ranges;
typedef Orthtrees::Traversal::Leaves<Traits, PointRange, PointMap> Leaves_traversal;
typedef Orthtrees::Traversal::Preorder<Traits, PointRange, PointMap> Preorder_traversal;
/// \endcond /// \endcond
/// @} /// @}
@ -311,7 +314,7 @@ public:
// Collect all the leaf nodes // Collect all the leaf nodes
std::queue<Node> leaf_nodes; std::queue<Node> leaf_nodes;
for (Node leaf : traverse(Orthtrees::Traversal::Leaves())) { for (Node leaf : traverse(Leaves_traversal())) {
// TODO: I'd like to find a better (safer) way of doing this // TODO: I'd like to find a better (safer) way of doing this
leaf_nodes.push(leaf); leaf_nodes.push(leaf);
} }
@ -403,8 +406,7 @@ public:
Node first = traversal.first(m_root); Node first = traversal.first(m_root);
Node_traversal_method_const next = std::bind(&Traversal::template next<Node>, Node_traversal_method_const next = std::bind(&Traversal::next, traversal, _1);
traversal, _1);
return boost::make_iterator_range(Traversal_iterator<Node>(first, next), return boost::make_iterator_range(Traversal_iterator<Node>(first, next),
Traversal_iterator<Node>()); Traversal_iterator<Node>());
@ -864,7 +866,7 @@ public:
friend std::ostream& operator<< (std::ostream& os, const Self& orthtree) friend std::ostream& operator<< (std::ostream& os, const Self& orthtree)
{ {
// Create a range of nodes // Create a range of nodes
auto nodes = orthtree.traverse(CGAL::Orthtrees::Traversal::Preorder()); auto nodes = orthtree.traverse(Preorder_traversal());
// Iterate over the range // Iterate over the range
for (auto &n : nodes) { for (auto &n : nodes) {
// Show the depth // Show the depth

View File

@ -20,6 +20,12 @@
namespace CGAL { namespace CGAL {
/// \cond SKIP_IN_MANUAL
// Forward declaration
template<typename T, typename PR, typename PM>
class Orthtree;
/// \endcond
namespace Orthtrees { namespace Orthtrees {
/// \cond SKIP_IN_MANUAL /// \cond SKIP_IN_MANUAL
@ -86,16 +92,22 @@ namespace Traversal {
/*! /*!
\ingroup PkgOrthtreeTraversal \ingroup PkgOrthtreeTraversal
\brief preorder traversal, starting from the root towards the leaves. \brief preorder traversal, starting from the root towards the leaves.
Template parameters are the template parameters of the `Orthtree`,
please refer to the documentation of this class for more
information.
\cgalModels Traversal \cgalModels Traversal
*/ */
template <typename T, typename PR, typename PM>
struct Preorder { struct Preorder {
template <typename Node> using Node = typename Orthtree<T,PR,PM>::Node;
Node first(Node root) const { Node first(Node root) const {
return root; return root;
} }
template <typename Node>
Node next(Node n) const { Node next(Node n) const {
if (n.is_leaf()) { if (n.is_leaf()) {
@ -116,17 +128,23 @@ struct Preorder {
/*! /*!
\ingroup PkgOrthtreeTraversal \ingroup PkgOrthtreeTraversal
\brief preorder traversal, starting from the leaves towards the root. \brief preorder traversal, starting from the leaves towards the root.
Template parameters are the template parameters of the `Orthtree`,
please refer to the documentation of this class for more
information.
\cgalModels Traversal \cgalModels Traversal
*/ */
template <typename T, typename PR, typename PM>
struct Postorder { struct Postorder {
template <typename Node> using Node = typename Orthtree<T,PR,PM>::Node;
Node first(Node root) const { Node first(Node root) const {
return deepest_first_child(root); return deepest_first_child(root);
} }
template <typename Node>
Node next(Node n) const { Node next(Node n) const {
Node next = deepest_first_child(next_sibling(n)); Node next = deepest_first_child(next_sibling(n));
@ -141,17 +159,23 @@ struct Postorder {
/*! /*!
\ingroup PkgOrthtreeTraversal \ingroup PkgOrthtreeTraversal
\brief leaves traversal, ignoring all non-leave nodes. \brief leaves traversal, ignoring all non-leave nodes.
Template parameters are the template parameters of the `Orthtree`,
please refer to the documentation of this class for more
information.
\cgalModels Traversal \cgalModels Traversal
*/ */
template <typename T, typename PR, typename PM>
struct Leaves { struct Leaves {
template <typename Node> using Node = typename Orthtree<T,PR,PM>::Node;
Node first(Node root) const { Node first(Node root) const {
return deepest_first_child(root); return deepest_first_child(root);
} }
template <typename Node>
Node next(Node n) const { Node next(Node n) const {
Node next = deepest_first_child(next_sibling(n)); Node next = deepest_first_child(next_sibling(n));

View File

@ -12,6 +12,8 @@
#ifndef CGAL_ORTHTREE_TRAITS_3_H #ifndef CGAL_ORTHTREE_TRAITS_3_H
#define CGAL_ORTHTREE_TRAITS_3_H #define CGAL_ORTHTREE_TRAITS_3_H
#include <CGAL/license/Orthtree.h>
namespace CGAL namespace CGAL
{ {

View File

@ -12,6 +12,8 @@
#ifndef CGAL_ORTHTREE_TRAITS_3_H #ifndef CGAL_ORTHTREE_TRAITS_3_H
#define CGAL_ORTHTREE_TRAITS_3_H #define CGAL_ORTHTREE_TRAITS_3_H
#include <CGAL/license/Orthtree.h>
namespace CGAL namespace CGAL
{ {

View File

@ -12,6 +12,8 @@
#ifndef CGAL_ORTHTREE_TRAITS_D_H #ifndef CGAL_ORTHTREE_TRAITS_D_H
#define CGAL_ORTHTREE_TRAITS_D_H #define CGAL_ORTHTREE_TRAITS_D_H
#include <CGAL/license/Orthtree.h>
namespace CGAL namespace CGAL
{ {

View File

@ -14,14 +14,14 @@ typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_3 Point; typedef Kernel::Point_3 Point;
typedef Kernel::FT FT; typedef Kernel::FT FT;
typedef CGAL::Point_set_3<Point> Point_set; typedef CGAL::Point_set_3<Point> Point_set;
typedef CGAL::Octree<Kernel, Point_set, typename Point_set::Point_map> typedef CGAL::Octree<Kernel, Point_set, typename Point_set::Point_map> Octree;
Octree; typedef CGAL::Orthtrees::Traversal::Leaves<typename Octree::Traits, Point_set, typename Point_set::Point_map> Leaves_traversal;
std::size_t count_jumps(Octree &octree) { std::size_t count_jumps(Octree &octree) {
std::size_t jumps = 0; std::size_t jumps = 0;
for (auto &node : octree.traverse(CGAL::Orthtrees::Traversal::Leaves())) { for (auto &node : octree.traverse(Leaves_traversal())) {
for (int direction = 0; direction < 6; ++direction) { for (int direction = 0; direction < 6; ++direction) {

View File

@ -11,8 +11,8 @@
typedef CGAL::Simple_cartesian<double> Kernel; typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_3 Point; typedef Kernel::Point_3 Point;
typedef CGAL::Point_set_3<Point> Point_set; typedef CGAL::Point_set_3<Point> Point_set;
typedef CGAL::Octree<Kernel, Point_set, typename Point_set::Point_map> typedef CGAL::Octree<Kernel, Point_set, typename Point_set::Point_map> Octree;
Octree; typedef CGAL::Orthtrees::Traversal::Preorder<typename Octree::Traits, Point_set, typename Point_set::Point_map> Preorder_traversal;
bool test_preorder_1_node() { bool test_preorder_1_node() {
@ -25,7 +25,7 @@ bool test_preorder_1_node() {
octree.refine(10, 1); octree.refine(10, 1);
// Create the range // Create the range
auto nodes = octree.traverse<CGAL::Orthtrees::Traversal::Preorder>(); auto nodes = octree.traverse<Preorder_traversal>();
// Check each item in the range // Check each item in the range
auto iter = nodes.begin(); auto iter = nodes.begin();
@ -46,7 +46,7 @@ bool test_preorder_9_nodes() {
octree.refine(10, 1); octree.refine(10, 1);
// Create the range // Create the range
auto nodes = octree.traverse<CGAL::Orthtrees::Traversal::Preorder>(); auto nodes = octree.traverse<Preorder_traversal>();
// Check each item in the range // Check each item in the range
auto iter = nodes.begin(); auto iter = nodes.begin();
@ -73,7 +73,7 @@ bool test_preorder_25_nodes() {
octree.refine(10, 1); octree.refine(10, 1);
// Create the range // Create the range
auto nodes = octree.traverse<CGAL::Orthtrees::Traversal::Preorder>(); auto nodes = octree.traverse<Preorder_traversal>();
// Check each item in the range // Check each item in the range
auto iter = nodes.begin(); auto iter = nodes.begin();