diff --git a/Orthtree/doc/Orthtree/Orthtree.txt b/Orthtree/doc/Orthtree/Orthtree.txt index 2c7394316fe..4584cff09cb 100644 --- a/Orthtree/doc/Orthtree/Orthtree.txt +++ b/Orthtree/doc/Orthtree/Orthtree.txt @@ -5,128 +5,151 @@ namespace CGAL { \anchor Chapter_Orthtree \cgalAutoToc -\author Jackson Campolattaro, Simon Giraudot, Cédric Portaneri, Tong Zhao, Pierre Alliez +\authors Jackson Campolattaro, Simon Giraudot, Cédric Portaneri, Tong Zhao, Pierre Alliez -\section Section_Octree_Introduction Introduction +\section Section_Orthtree_Introduction Introduction -An octree is a commonly used data structure that subdivides 3d space. -The Octree package provides the Octree and Node classes. +Quadtrees are tree data structures in which each node encloses a +square section of space, and each internal node has exactly 4 +children. Octrees are a similar data structure in 3D in which each +node encloses a cubic section of space, and each internal node has +exactly 8 children. -Note that the octree will often be outperformed by Spacial_searching's kD-tree. -Octrees are most useful when implementing algorithms that require nodes without high aspect-ratios. -Intersection and nearest-neighbor algorithms should be expected to perform worse than the kD-tree -but they can be useful if the octree has already been constructed. +We call the generalization of such data structure "Orthtrees", as +orthants are generalizations of a quadrants and octants. The term +_Hyperoctree_ can also be found in litterature to name such data +structures in dimensions 4 and higher. -\section Section_Octree_Building Building an Octree +This package provides a general data structure `Orthtree` along with +aliases for `Quadtree` and `Octree`. These trees can be constructed +with custom point ranges and split predicates, and iterated on with +various traversal methods. -Before an octree can be used for anything, the tree itself must be created. -By default, the constructor returns a tree with a single (root) node that contains all the points. -We can use the `refine` method to subdivide space further. +\cgalFigureBegin{Orthtree_fig, orthtree.png} +Building an %Orthtree in 3D (%Octree) from a point cloud. +\cgalFigureEnd -\subsection Section_Octree_Point_Vector Building an Octree from a Vector of Points -The simplest way to create an octree is using a vector of points. -The constructor generally expects a separate point-range and map, -but the point-map defaults to CGAL's `Identity_property_map` if none is provided. -That enables using a range that contains the points directly, because it's mapped directly to itself. +\section Section_Orthtree_Building Building -\b Example +An %Orthtree is created using a set of points. The constructor returns +a tree with a single (root) node that contains all the points. -This example illustrates how to create an octree from a `std::vector`. +The method [refine()](@ref CGAL::Orthtree::refine) must be called to +subdividce space further. This method uses a split predicate which +takes a node as input and returns `true` is this node should be +splitted, `false` otherwise: this allows users to choose on what +criterion should the %Orthtree be refined. Predefined predicates are +provided such as [Max_depth](@ref CGAL::Orthtrees::Split_predicate::Max_depth) or [Bucket_size](@ref CGAL::Orthtrees::Split_predicate::Bucket_size). -An `std::vector` is manually filled with points. +\subsection Section_Orthtree_Orthtree_Point_Vector Building an Orthtree + +The simplest way to create an %Orthtree is using a vector of points. +The constructor generally expects a separate point range and map, +but the point map defaults to `Identity_property_map` if none is provided. + +The following example shows how to build an %Orthtree in dimension 4. +An `std::vector` is manually filled with points. The vector is used as the point set, -a `CGAL::Identity_property_map` is automatically set as the octree's map type, so a map doesn't need to be provided. +a `CGAL::Identity_property_map` is automatically set as the %Orthtree's map type, so a map doesn't need to be provided. + +\cgalExample{Orthtree/Orthtree_build.cpp} + +\subsection Section_Orthtree_Quadtree Building a Quadtree + +The `Orthtree` class may be templated with `Orthtree_traits_2` and thus +behave as a %Quadtree. For convenience, an alias `Quadtree` is provided. + +The following example shows how to create a %Quadtree from a vector of +`Point_2` objects: + +\cgalExample{Orthtree/Quadtree_build_from_Point_vector.cpp} + +\subsection Section_Orthtree_Point_Vector Building an Octree + +The `Orthtree` class may be templated with `Orthtree_traits_3` and thus +behave as an %Octree. For convenience, an alias `Octree` is provided. + +The following example shows how to create an %Octree from a vector of +`Point_3` objects: \cgalExample{Orthtree/Octree_build_from_Point_vector.cpp} -\subsection Section_Octree_Point_Set Building an Octree from a Point_set_3 +\subsection Section_Orthtree_Point_Set Building an Octree from a Point_set_3 -Using a `Point_set_3` is slightly more complicated, but it comes with a number of advantages. -CGAL's Point set class has many useful features. -Here we take advantage of its ability to save and load from files easily. -The independent point-range and map may also come with a performance benefit. - -\b Example - -This example illustrates how to create an octree from a `Point_set_3` loaded from a file. -It also shows a more explicit way of setting the split criteria when refining the tree. +Some data structures such as `Point_set_3` require a non-default point +map type and object. This example illustrates how to create an %Octree from a `Point_set_3` loaded from a file. +It also shows a more explicit way of setting the split predicate when refining the tree. An octree is constructed from the point set and its map. -The tree is refined with a max-depth (deepest node allowed) of 10, +The tree is refined with a max depth (deepest node allowed) of 10, and a bucket size (maximum number of points contained by a single node) of 20. The tree is then printed to the standard output. -The split criterion is manually constructed and passed to the refine method. +The split predicate is manually constructed and passed to the refine method. \cgalExample{Orthtree/Octree_build_from_Point_set.cpp} -\subsection Section_Octree_Custom_Split_Criterion Building an Octree with a Custom Split Criterion +\subsection Section_Orthtree_Custom_Split_Precicate Building an Octree with a Custom Split Predicate -It's very easy to create your own criterion if the existing ones don't match your needs. -For example, you might design a criterion which only splits nodes that contain exactly 4 points. -\todo Link to SplitCriterion concept +The split predicate is a user-defined functor that determine whether a +node needs to be split. Custom predicates can easily be defined if the +existing ones do not match users' needs. -\b Example - -This example illustrates how to refine an octree using a split criterion that isn't provided by default. - -The criterion is a functor created by the user to determine whether a node needs to be split. -This particular criterion sets a node's bucket size as a ratio of its depth. -For example, for a ratio of 2, a node at depth 2 can hold 4 points, a node at depth 7 can hold 14. +The following example illustrates how to refine an %Octree using a +split predicate that isn't provided by default. This particular +predicate sets a node's bucket size as a ratio of its depth. For +example, for a ratio of 2, a node at depth 2 can hold 4 points, a node +at depth 7 can hold 14. \cgalExample{Orthtree/Octree_build_with_custom_split.cpp} -\section Section_Octree_Traversal Traversal over an Octree +\section Section_Orthtree_Traversal Traversal -Traversal is the act of navigating among the nodes of the tree. -The Octree and Node classes provide a number of different solutions for traversing the tree. +\note For simplicity, the rest of the user manual will only use +Octrees, but all the presented features also apply to Quadtrees and +higher dimension Orthtrees. -\subsection Section_Octree_Manual_Traveral Manual Traversal +%Traversal is the act of navigating among the nodes of the tree. +The Orthtree and [Node](@ref CGAL::Orthtree::Node) classes provide a +number of different solutions for traversing the tree. -Because our octree is a form of connected acyclic undirected graph, it's possible to navigate between any two nodes. -What that means in practice, is that given a pointer or reference to one node on the tree, it's possible to +\subsection Section_Orthtree_Manual_Traveral Manual Traversal + +Because our %Orthtree is a form of connected acyclic undirected graph, it's possible to navigate between any two nodes. +What that means in practice, is that given a node on the tree, it's possible to access any other node using the right set of operations. -The node has functions that allow the user to access each of its children, as well as its parent (if it exists). +The `Node` class provides functions that allows the user to access each of its children, as well as its parent (if it exists). -\b Example +The following example demonstrates ways of accessing different nodes of a tree, given a reference to one. -This example demonstrates ways of accessing different nodes of a tree, given a reference to one. +From the root node, children can be accessed using [the subscript operator (`[]`)](@ref CGAL::Orthtree::Node::operator[]). +For an %Octree, values from 0-7 provide access to the different children. -If you have the root node, it's possible to get to its children using the subscript operator (`[]`). -Values from 0-7 provide access to the different children. -Using the operator on a leaf node is considered undefined behavior. +For non-root nodes, it's possible to access parent nodes using the [parent()](@ref CGAL::Orthtree::Node::parent) accessor. -For non-root nodes, it's possible to access parent nodes using the `parent` accessor. -Note that the accessor returns a pointer and not a reference, -calling the root node's parent accessor will return null. - -These accessors and operators can be chained to access any node in the tree in a single line of code. +These accessors and operators can be chained to access any node in the tree in a single line of code, as shown in the following example: \cgalExample{Orthtree/Octree_traversal_manual.cpp} -\subsection Section_Octree_Preorder_Traversal Preorder Traversal +\subsection Section_Orthtree_Preorder_Traversal Preorder Traversal It's often useful to be able to iterate over the nodes of the tree in a particular order. For example, the stream operator `<<` uses a traversal to print out each node. -A few traversals are provided, among them "Preorder" and "Postorder". +A few traversals are provided, among them [Preorder](@ref CGAL::Orthtrees::Traversal::Preorder) and [Postorder](@ref CGAL::Orthtrees::Traversal::Postorder). To traverse a tree in preorder is to visit each parent immediately followed by its children, where in posterder traversal the children are visited first. -\todo This could use a bit more detail - -\b Example - -This example illustrates how to use the provided traversals. +The following example illustrates how to use the provided traversals. A tree is constructed, and a traversal is used to create a range that can be iterated over using a for-each loop. -The default output operator for the octree uses the preorder traversal to do a pretty-print of the tree structure. +The default output operator for the %Orthtree uses the preorder traversal to do a pretty-print of the tree structure. In this case, we print out the nodes of the tree without indentation instead. \cgalExample{Orthtree/Octree_traversal_preorder.cpp} -\section Section_Octree_Acceleration Acceleration of Common Tasks +\section Section_Orthtree_Acceleration Acceleration of Common Tasks -Once an octree is built, its structure can be used to accelerate different tasks. +Once an %Orthtree is built, its structure can be used to accelerate different tasks. -\subsection Section_Octree_Nearest_Neighbor Finding the Nearest Neighbor of a Point +\subsection Section_Orthtree_Nearest_Neighbor Finding the Nearest Neighbor of a Point The naive way of finding the nearest neighbor of a point requires finding the distance of every other point. -An octree can be used to perform the same task in significantly less time. +An %Orthtree can be used to perform the same task in significantly less time. For large numbers of points, this can be a large enough difference to outweigh the time spent building the tree. -Note that a kD-tree is expected to outperform the Octree for this task, -it should be preferred unless features specific to the Octree are needed. +Note that a kD-tree is expected to outperform the %Orthtree for this task, +it should be preferred unless features specific to the %Orthtree are needed. -\b Example +The following example illustrates how to use an %Octree to accelerate the search for points close to a location. -This example illustrates how to use an octree to accelerate the search for points close to a location. - -Points are loaded from a file and an octree is built. +Points are loaded from a file and an %Octree is built. The nearest neighbor method is invoked for several input points. A k value of 1 is used to find the single closest point. Results are put in a vector, and then printed. \cgalExample{Orthtree/Octree_find_nearest_neighbor.cpp} -\subsection Section_Octree_Grade Grading an octree +\subsection Section_Orthtree_Grade Grading -\b Example +An %Orthtree is graded if the difference of depth between two adjacent +leaves is at most 1 for every pair of leaves. -This example demonstrates how to use the grade method to eliminate large jumps in depth within the octree. +\cgalFigureBegin{Orthtree_quadree_graded_fig, quadtree_graded.png} +%Quadtree before and after being graded. +\cgalFigureEnd + +The following example demonstrates how to use the grade method to eliminate large jumps in depth within the %Orthtree. A tree is created such that one node is split many more times than those it borders. -`grade()` splits the octree's nodes so that adjacent nodes never have a difference in depth greater than one. +[grade()](@ref CGAL::Orthtree::grade) splits the %Octree's nodes so that adjacent nodes never have a difference in depth greater than one. The tree is printed before and after grading, so that the differences are visible. \cgalExample{Orthtree/Octree_grade.cpp} -\section Section_Octree_Quadtree Quadtree +\section Section_Orthtree_Performance Performance -If the Octree class is templated with a point range whose `value_type` -is a `Point_2` object, it will behave as a Quadtree: all the features -of the package remain valid, using a dimension of 2 instead of 3 and a -degree (number of children of a node) of 4 instead of 8. +\subsection Section_Orthtree_Performance_Comparison Comparison with kD Tree -\b Example +\todo -The following example shows how to create a Quadtree from a vector of -`Point_2` objects: - -\cgalExample{Orthtree/Quadtree_build_from_Point_vector.cpp} - -\section Section_Octree_Performance Performance - -\subsection Section_Octree_Performance_Comparison Comparison with kD Tree - -e.g. When is an octree the right choice? - -\section Section_Octree_Software_Design Software Design - -\subsection Subsection_Octree_Design_Octree Octree -\subsection Subsection_Octree_Design_Walker_Rules Walker Rules -\subsection Subsection_Octree_Design_Splitting_Rules Splitting Rules -\subsection Subsection_Octree_Design_Walker_Rules Walker Rules - -\section Section_Octree_History History +\section Section_Orthtree_History History This package was developed by Jackson Campolatarro as part of the Google Summer of Code 2020, based on a prototype code by Tong Zhao and Cédric Portaneri, diff --git a/Orthtree/doc/Orthtree/dependencies b/Orthtree/doc/Orthtree/dependencies index e69de29bb2d..1e72914f700 100644 --- a/Orthtree/doc/Orthtree/dependencies +++ b/Orthtree/doc/Orthtree/dependencies @@ -0,0 +1,10 @@ +Circulator +Manual +Kernel_23 +Kernel_d +Number_types +Point_set_3 +Property_map +STL_Extension +Spatial_searching +Stream_support diff --git a/Orthtree/examples/Orthtree/Octree_build_from_Point_set.cpp b/Orthtree/examples/Orthtree/Octree_build_from_Point_set.cpp index 4b9c85ff969..db632d646f3 100644 --- a/Orthtree/examples/Orthtree/Octree_build_from_Point_set.cpp +++ b/Orthtree/examples/Orthtree/Octree_build_from_Point_set.cpp @@ -33,7 +33,7 @@ int main(int argc, char **argv) { Octree octree(points, points.point_map()); // Build the octree with a small bucket size, using a more verbose method - octree.refine(CGAL::Orthtrees::Split_predicate::Max_depth_or_bucket_size(5, 10)); + octree.refine(CGAL::Orthtrees::Split_predicate::Max_depth_or_bucket_size(4, 10)); // Print out the tree std::cout << octree; diff --git a/Orthtree/examples/Orthtree/Orthtree_build.cpp b/Orthtree/examples/Orthtree/Orthtree_build.cpp index 14eb18157a7..02ce0f672cb 100644 --- a/Orthtree/examples/Orthtree/Orthtree_build.cpp +++ b/Orthtree/examples/Orthtree/Orthtree_build.cpp @@ -30,7 +30,6 @@ int main() Orthtree orthtree(points_dd); orthtree.refine(10, 5); - orthtree.grade(); return EXIT_SUCCESS; } diff --git a/Orthtree/examples/Orthtree/Quadtree_build_from_Point_vector.cpp b/Orthtree/examples/Orthtree/Quadtree_build_from_Point_vector.cpp index 45575aec6cf..162d30f37da 100644 --- a/Orthtree/examples/Orthtree/Quadtree_build_from_Point_vector.cpp +++ b/Orthtree/examples/Orthtree/Quadtree_build_from_Point_vector.cpp @@ -12,14 +12,25 @@ typedef std::vector Point_vector; typedef CGAL::Quadtree Quadtree; -int main() +int main(int argc, char** argv) { - CGAL::Random r; - Point_vector points_2d; - for (std::size_t i = 0; i < 5; ++ i) - points_2d.emplace_back(r.get_double(-1., 1.), - r.get_double(-1., 1.)); + if (argc == 1) + { + CGAL::Random r; + + for (std::size_t i = 0; i < 5; ++ i) + points_2d.emplace_back(r.get_double(-1., 1.), + r.get_double(-1., 1.)); + } + else + { + std::ifstream ifs (argv[1]); + Point_2 point; + unsigned int nb = 0; + while (ifs >> point) + points_2d.emplace_back(point); + } Quadtree quadtree(points_2d); quadtree.refine(10, 5); diff --git a/Orthtree/include/CGAL/Orthtree.h b/Orthtree/include/CGAL/Orthtree.h index 086820b1f11..f91593f40aa 100644 --- a/Orthtree/include/CGAL/Orthtree.h +++ b/Orthtree/include/CGAL/Orthtree.h @@ -20,8 +20,6 @@ #include #include -#include - #include #include #include @@ -194,6 +192,7 @@ public: { bbox_min[i] = (std::min)(x, bbox_min[i]); bbox_max[i] = (std::max)(x, bbox_max[i]); + ++ i; } } diff --git a/Orthtree/package_info/Orthtree/dependencies b/Orthtree/package_info/Orthtree/dependencies index dfa1e5af518..575ce6e504a 100644 --- a/Orthtree/package_info/Orthtree/dependencies +++ b/Orthtree/package_info/Orthtree/dependencies @@ -7,12 +7,9 @@ Intersections_2 Intersections_3 Interval_support Kernel_23 -Modular_arithmetic Number_types -Octree -Principal_component_analysis_LGPL +Orthtree Profiling_tools Property_map STL_Extension -Spatial_searching Stream_support