diff --git a/Advancing_front_surface_reconstruction/doc/Advancing_front_surface_reconstruction/Advancing_front_surface_reconstruction.txt b/Advancing_front_surface_reconstruction/doc/Advancing_front_surface_reconstruction/Advancing_front_surface_reconstruction.txt
index 5d996b0ceed..90502e1bdf6 100644
--- a/Advancing_front_surface_reconstruction/doc/Advancing_front_surface_reconstruction/Advancing_front_surface_reconstruction.txt
+++ b/Advancing_front_surface_reconstruction/doc/Advancing_front_surface_reconstruction/Advancing_front_surface_reconstruction.txt
@@ -47,6 +47,9 @@ not provide any guarantee on the topology of the surface.
We describe next the algorithm and provide examples.
+\note A \ref tuto_reconstruction "detailed tutorial on surface reconstruction"
+is provided with a guide to choose the most appropriate method along
+with pre- and post-processing.
\section AFSR_Definitions Definitions and the Algorithm
diff --git a/Documentation/doc/Documentation/Doxyfile.in b/Documentation/doc/Documentation/Doxyfile.in
index c4efea1bc5e..e90d8b66149 100644
--- a/Documentation/doc/Documentation/Doxyfile.in
+++ b/Documentation/doc/Documentation/Doxyfile.in
@@ -11,7 +11,8 @@ HTML_HEADER = ${CGAL_DOC_HEADER}
LAYOUT_FILE = ${CGAL_DOC_RESOURCE_DIR}/DoxygenLayout.xml
GENERATE_TAGFILE = ${CGAL_DOC_TAG_GEN_DIR}/Manual.tag
EXAMPLE_PATH = ${CGAL_Convex_hull_2_EXAMPLE_DIR} \
- ${CGAL_Kernel_23_EXAMPLE_DIR}
+ ${CGAL_Kernel_23_EXAMPLE_DIR} \
+ ${CGAL_Poisson_surface_reconstruction_3_EXAMPLE_DIR}
FILTER_PATTERNS = *.txt=${CMAKE_BINARY_DIR}/pkglist_filter
HTML_EXTRA_FILES += ${CGAL_DOC_RESOURCE_DIR}/hacks.js \
diff --git a/Documentation/doc/Documentation/Tutorials/Tutorial_reconstruction.txt b/Documentation/doc/Documentation/Tutorials/Tutorial_reconstruction.txt
new file mode 100644
index 00000000000..fb60465bbc0
--- /dev/null
+++ b/Documentation/doc/Documentation/Tutorials/Tutorial_reconstruction.txt
@@ -0,0 +1,295 @@
+namespace CGAL {
+/*!
+\example Poisson_surface_reconstruction_3/tutorial_example.cpp
+*/
+
+/*!
+
+\page tuto_reconstruction Surface Reconstruction from Point Clouds
+\cgalAutoToc
+
+\author Simon Giraudot
+
+Surface reconstruction from point clouds is a core topic in geometry
+processing \cgalCite{cgal:btsag-asosr-16}. It is an ill-posed problem:
+there is an infinite number of surfaces that approximate a single
+point cloud and a point cloud does not define a surface in
+itself. Thus additional assumptions and constraints must be defined by
+the user and reconstruction can be achieved in many different
+ways. This tutorial provides guidance on how to use the different
+algorithms of \cgal to effectively perform surface reconstruction.
+
+\section TutorialsReconstruction_algorithms Which algorithm should I use?
+
+\cgal offers three different algorithms for surface reconstruction:
+
+- \ref Chapter_Poisson_Surface_Reconstruction "Poisson Surface Reconstruction"
+- \ref Chapter_Advancing_Front_Surface_Reconstruction "Advancing Front Surface Reconstruction"
+- \ref Chapter_Scale_space_reconstruction "Scale Space Surface Reconstruction"
+
+
+Because reconstruction is an ill-posed problem, it must be regularized
+via prior knowledge. Differences in prior lead to different
+algorithms, and choosing one or the other of these methods is
+dependent on these priors. For example, Poisson always generates
+closed shapes (bounding a volume) and requires normals but does not
+interpolate input points (the output surface does not pass exactly
+through the input points). The following table lists different
+properties of the input and output to help the user choose the method
+best suited to each problem:
+
+
+| | Poisson | Advancing front | Scale space |
+|------------------------------------------|:-------:|:----------------:|:----------------:|
+| Are normals required? | Yes | No | No |
+| Is noise handled? | Yes | By preprocessing | Yes |
+| Is variable sampling handled? | Yes | Yes | By preprocessing |
+| Are input points exactly on the surface? | No | Yes | Yes |
+| Is the output always closed? | Yes | No | No |
+| Is the output always smooth? | Yes | No | No |
+| Is the output always manifold? | Yes | Yes | Optional |
+| Is the output always orientable? | Yes | Yes | Optional |
+
+
+\cgalFigureBegin{TutorialsReconstructionFigComparisons, compare_reconstructions.png}
+Comparison of reconstruction methods applied to the same input (full shape and close-up). From left to right: original point cloud; Poisson; advancing front; scale space.
+\cgalFigureEnd
+
+More information on these different methods can be found on their
+respective manual pages and in Section \ref TutorialsReconstruction_reconstruction.
+
+\section TutorialsReconstruction_overview Pipeline Overview
+
+This tutorial aims at providing a more comprehensive view of the
+possibilities offered by \cgal for dealing with point clouds, for
+surface reconstruction purposes. The following diagram shows an
+overview (not exhaustive) of common reconstruction steps using \cgal
+tools.
+
+\cgalFigureBegin{TutorialsReconstructionFigPipeline, reconstruction.svg}
+Pipeline Overview
+\cgalFigureEnd
+
+We now review some of these steps in more detail.
+
+
+\section TutorialsReconstruction_input Reading Input
+
+The reconstruction algorithms in \cgal take a range of iterators on a
+container as input and use property maps to access the points (and the
+normals when they are required). Points are typically stored in plain
+text format (denoted as 'XYZ' format) where each point is separated by
+a newline character and each coordinate separated by a white
+space. Other formats available are 'OFF', 'PLY' and 'LAS'. \cgal
+provides functions to read such formats:
+
+- `read_xyz_points()`
+- `read_off_points()`
+- `read_ply_points()`
+- `read_ply_points_with_properties()` to read additional PLY properties
+- `read_las_points()`
+- `read_las_points_with_properties()` to read additional LAS properties
+
+\cgal also provides a dedicated container `CGAL::Point_set_3` to
+handle point sets with additional properties such as normal
+vectors. In this case, property maps are easily handled as shown in
+the following sections. This structure also handles the stream
+operator to read point sets in any of the formats previously
+described. Using this method yields substantially shorter code, as can
+be seen on the following example:
+
+\snippet Poisson_surface_reconstruction_3/tutorial_example.cpp Reading input
+
+\section TutorialsReconstruction_preprocessing Preprocessing
+
+Because reconstruction algorithms have some specific requirements that
+point clouds do not always meet, some preprocessing might be necessary
+to yield the best results.
+
+Note that this _preprocessing_ step is optional: when the input point
+cloud has no imperfections, reconstruction can be applied to it
+without any preprocessing.
+
+
+\cgalFigureBegin{TutorialsReconstructionFigPreprocessing, reconstruction_preproc.png}
+Comparison of advancing front reconstruction output using different
+preprocessing on the same input. The smooth point cloud was generated
+using _jet smoothing_; the simplified point cloud was generated using
+_grid simplification_.
+\cgalFigureEnd
+
+
+\subsection TutorialsReconstruction_preprocessing_outliers Outlier removal
+
+Some acquisition techniques generate points which are far away from
+the surface. These points, commonly referred to as "outliers", have no
+relevance for reconstruction. Using the \cgal reconstruction
+algorithms on outlier-ridden point clouds produce overly distorted
+output, it is therefore strongly advised to filter these outliers
+_before_ performing reconstruction.
+
+\snippet Poisson_surface_reconstruction_3/tutorial_example.cpp Outlier removal
+
+\subsection TutorialsReconstruction_preprocessing_simplification Simplification
+
+Some laser scanners generate points with widely variable
+sampling. Typically, lines of scan are very densely sampled but the
+gap between two lines of scan is much larger, leading to an overly
+massive point cloud with large variations of sampling density. This
+type of input point cloud might generate imperfect output using
+algorithms which, in general, only handle small variations of sampling
+density.
+
+\cgal provides several simplification algorithms. In addition to
+reducing the size of the input point cloud and therefore decreasing
+computation time, some of them can help making the input more
+uniform. This is the case of the function `grid_simplify_point_set()`
+which defines a grid of a user-specified size and keeps one point per
+occupied cell.
+
+\snippet Poisson_surface_reconstruction_3/tutorial_example.cpp Simplification
+
+
+\subsection TutorialsReconstruction_preprocessing_smoothing Smoothing
+
+Although reconstructions via 'Poisson' or 'Scale space' handle noise
+internally, one may want to get tighter control over the smoothing
+step. For example, a slightly noisy point cloud can benefit from some
+reliable smoothing algorithms and be reconstructed via 'Advancing
+front' which provides relevant properties (oriented mesh with
+boundaries).
+
+Two functions are provided to smooth a noisy point cloud with a good
+approximation (i.e. without degrading curvature, for example):
+
+- `jet_smooth_point_set()`
+- `bilateral_smooth_point_set()`
+
+These functions directly modify the container:
+
+\snippet Poisson_surface_reconstruction_3/tutorial_example.cpp Smoothing
+
+
+\subsection TutorialsReconstruction_preprocessing_normal Normal Estimation and Orientation
+
+\ref Chapter_Poisson_Surface_Reconstruction "Poisson Surface Reconstruction"
+requires points with oriented normal vectors. To apply the algorithm
+to a raw point cloud, normals must be estimated first, for example
+with one of these two functions:
+
+- `pca_estimate_normals()`
+- `jet_estimate_normals()`
+
+PCA is faster but jet is more accurate in the presence of high
+curvatures. These function only estimates the _direction_ of the
+normals, not their orientation (the orientation of the vectors might
+not be locally consistent). To properly orient the normals, the
+function `mst_orient_normals()` can be used. Notice that it can also
+be used directly on input normals if their orientation is not
+consistent.
+
+\snippet Poisson_surface_reconstruction_3/tutorial_example.cpp Normal estimation
+
+\section TutorialsReconstruction_reconstruction Reconstruction
+
+\subsection TutorialsReconstruction_reconstruction_poisson Poisson
+
+Poisson reconstruction consists in computing an implicit function
+whose gradient matches the input normal vector field: this indicator
+function has opposite signs inside and outside of the inferred shape
+(hence the need for closed shapes). This method thus requires normals
+and produces smooth closed surfaces. It is not appropriate if the
+surface is expected to interpolate the input points. On the contrary,
+it performs well if the aim is to approximate a noisy point cloud with
+a smooth surface.
+
+\snippet Poisson_surface_reconstruction_3/tutorial_example.cpp Poisson reconstruction
+
+\subsection TutorialsReconstruction_reconstruction_advancing Advancing Front
+
+Advancing front is a Delaunay-based approach which interpolates a
+subset of the input points. It generates triples of point indices
+which describe the triangular facets of the reconstruction: it uses a
+priority queue to sequentially pick the Delaunay facet the most likely
+to be part of the surface, based on a size criterion (to favor the
+small facets) and an angle criterion (to favor smoothness). Its main
+virtue is to generate oriented manifold surfaces with boundaries:
+contrary to Poisson, it does not require normals and is not bound to
+reconstruct closed shapes. However, it requires preprocessing if the
+point cloud is noisy.
+
+The \ref Chapter_Advancing_Front_Surface_Reconstruction "Advancing Front"
+package provides several ways of constructing the function. Here is
+a simple example:
+
+\snippet Poisson_surface_reconstruction_3/tutorial_example.cpp Advancing front reconstruction
+
+\subsection TutorialsReconstruction_reconstruction_scale_space Scale Space
+
+Scale space reconstruction aims at producing a surface which
+interpolates the input points (interpolant) while offering some
+robustness to noise. More specifically, it first applies several times
+a smoothing filter (such as Jet Smoothing) to the input point set to
+produce a scale space; then, the smoothest scale is meshed (using for
+example the Advancing Front mesher); finally, the resulting
+connectivity between smoothed points is propagated to the original raw
+input point set. This method is the right choice if the input point
+cloud is noisy but the user still wants the surface to pass exactly
+through the points.
+
+\snippet Poisson_surface_reconstruction_3/tutorial_example.cpp Scale space reconstruction
+
+\section TutorialsReconstruction_postprocessing Output and Postprocessing
+
+Each of these methods produce a triangle mesh stored in different
+ways. If this output mesh is hampered by defects such as holes or
+self-intersections, \cgal provide several algorithms to post-process
+it (hole filling, remeshing, etc.) in the package \ref
+Chapter_PolygonMeshProcessing "Polygon Mesh Processing".
+
+We do not discuss these functions here as there are many
+postprocessing possibilities whose relevance strongly depends on the
+user's expectations on the output mesh.
+
+The mesh (postprocessed or not) can easily be saved in the PLY format
+(here, using the binary variant):
+
+\snippet Poisson_surface_reconstruction_3/tutorial_example.cpp Output poisson
+
+A polygon soup can also be saved in the OFF format by iterating on the
+points and faces:
+
+\snippet Poisson_surface_reconstruction_3/tutorial_example.cpp Output scale space
+
+Finally, if the polygon soup can be converted into a polygon mesh, it
+can also be saved directly in the OFF format using the stream
+operator:
+
+\snippet Poisson_surface_reconstruction_3/tutorial_example.cpp Output advancing front
+
+\section TutorialsReconstruction_recap Full Code Example
+
+All the code snippets used in this tutorial can be assembled to create
+a full algorithm pipeline (provided the correct _includes_ are
+used). We give a full code example which achieves all the steps
+described in this tutorial. The reconstruction method can be selected
+by the user at runtime with the second argument.
+
+\include Poisson_surface_reconstruction_3/tutorial_example.cpp
+
+\section TutorialsReconstruction_pipeline Full Pipeline Images
+
+The following figure an example of a full reconstruction pipeline
+applied to a bear statue (courtesy _EPFL Computer Graphics and
+Geometry Laboratory_ \cgalCite{cgal:e-esmr}). Two mesh processing
+algorithms (hole filling and isotropic remeshing) are also applied
+(refer to the chapter \ref Chapter_PolygonMeshProcessing "Polygon Mesh Processing"
+for more information).
+
+\cgalFigureBegin{TutorialsReconstructionFigFull, reconstruction_pipeline.png}
+Full reconstruction pipeline (with close-ups).
+\cgalFigureEnd
+
+
+*/
+}
diff --git a/Documentation/doc/Documentation/Tutorials/Tutorials.txt b/Documentation/doc/Documentation/Tutorials/Tutorials.txt
index aab618e954f..76aa5daf111 100644
--- a/Documentation/doc/Documentation/Tutorials/Tutorials.txt
+++ b/Documentation/doc/Documentation/Tutorials/Tutorials.txt
@@ -16,6 +16,8 @@ User Manual.
geometric primitives, the notion of traits classes which
define what primitives are used by a geometric algorithm, the
notions of \em concept and \em model.
+- \subpage tuto_reconstruction
+
\section tuto_examples Package Examples
diff --git a/Documentation/doc/Documentation/fig/compare_reconstructions.png b/Documentation/doc/Documentation/fig/compare_reconstructions.png
new file mode 100644
index 00000000000..5c9a41f0169
Binary files /dev/null and b/Documentation/doc/Documentation/fig/compare_reconstructions.png differ
diff --git a/Documentation/doc/Documentation/fig/reconstruction.svg b/Documentation/doc/Documentation/fig/reconstruction.svg
new file mode 100644
index 00000000000..d32ecdb5c75
--- /dev/null
+++ b/Documentation/doc/Documentation/fig/reconstruction.svg
@@ -0,0 +1,1447 @@
+
+
diff --git a/Documentation/doc/Documentation/fig/reconstruction_pipeline.png b/Documentation/doc/Documentation/fig/reconstruction_pipeline.png
new file mode 100644
index 00000000000..ce240b9fad8
Binary files /dev/null and b/Documentation/doc/Documentation/fig/reconstruction_pipeline.png differ
diff --git a/Documentation/doc/Documentation/fig/reconstruction_preproc.png b/Documentation/doc/Documentation/fig/reconstruction_preproc.png
new file mode 100644
index 00000000000..ddcab5a9e0b
Binary files /dev/null and b/Documentation/doc/Documentation/fig/reconstruction_preproc.png differ
diff --git a/Documentation/doc/biblio/cgal_manual.bib b/Documentation/doc/biblio/cgal_manual.bib
index 41fe234c9dc..785b25e2e36 100644
--- a/Documentation/doc/biblio/cgal_manual.bib
+++ b/Documentation/doc/biblio/cgal_manual.bib
@@ -708,6 +708,12 @@ Teillaud"
, year = 1999
}
+@Misc{ cgal:e-esmr,
+ title = {{EPFL} statue model repository},
+ howpublished = {{EPFL} Computer Graphics and Geometry Laboratory},
+ url = {http://lgg.epfl.ch/statues_dataset.php}
+}
+
@inproceedings{ cgal:eddhls-maam-95
,author = {Matthias Eck and Tony DeRose and Tom Duchamp and
Hugues Hoppe and Michael Lounsbery and Werner Stuetzle}
@@ -1771,6 +1777,21 @@ ABSTRACT = {We present the first complete, exact and efficient C++ implementatio
pages=""
}
+@article{cgal:btsag-asosr-16,
+ TITLE = {{A Survey of Surface Reconstruction from Point Clouds}},
+ AUTHOR = {Berger, Matthew and Tagliasacchi, Andrea and Seversky, Lee and Alliez, Pierre and Guennebaud, Gael and Levine, Joshua and Sharf, Andrei and Silva, Claudio},
+ URL = {https://hal.inria.fr/hal-01348404},
+ JOURNAL = {{Computer Graphics Forum}},
+ PUBLISHER = {{Wiley}},
+ PAGES = {27},
+ YEAR = {2016},
+ DOI = {10.1111/cgf.12802},
+ PDF = {https://hal.inria.fr/hal-01348404/file/survey-author.pdf},
+ HAL_ID = {hal-01348404},
+ HAL_VERSION = {v2}
+}
+
+
@TechReport{ cgal:pabl-cco-07,
author = {Poudret, M. and Arnould, A. and Bertrand, Y. and Lienhardt, P.},
title = {Cartes Combinatoires Ouvertes.},
diff --git a/Poisson_surface_reconstruction_3/doc/Poisson_surface_reconstruction_3/Poisson_surface_reconstruction_3.txt b/Poisson_surface_reconstruction_3/doc/Poisson_surface_reconstruction_3/Poisson_surface_reconstruction_3.txt
index 137fa4194b1..f76f4ad34e8 100644
--- a/Poisson_surface_reconstruction_3/doc/Poisson_surface_reconstruction_3/Poisson_surface_reconstruction_3.txt
+++ b/Poisson_surface_reconstruction_3/doc/Poisson_surface_reconstruction_3/Poisson_surface_reconstruction_3.txt
@@ -28,6 +28,11 @@ function of the inferred solid (Poisson Surface Reconstruction -
referred to as Poisson). Poisson is a two steps process: it requires
solving for the implicit function before function evaluation.
+\note A \ref tuto_reconstruction "detailed tutorial on surface reconstruction"
+is provided with a guide to choose the most appropriate method along
+with pre- and post-processing.
+
+
\section Poisson_surface_reconstruction_3Common Common Reconstruction Pipeline
Surface reconstruction from point sets is often a sequential process
diff --git a/Poisson_surface_reconstruction_3/examples/Poisson_surface_reconstruction_3/CMakeLists.txt b/Poisson_surface_reconstruction_3/examples/Poisson_surface_reconstruction_3/CMakeLists.txt
index 85259f8bd2f..a7eb729ec77 100644
--- a/Poisson_surface_reconstruction_3/examples/Poisson_surface_reconstruction_3/CMakeLists.txt
+++ b/Poisson_surface_reconstruction_3/examples/Poisson_surface_reconstruction_3/CMakeLists.txt
@@ -31,6 +31,8 @@ if ( CGAL_FOUND )
CGAL_target_use_Eigen(poisson_reconstruction)
create_single_source_cgal_program( "poisson_reconstruction_function.cpp" )
CGAL_target_use_Eigen(poisson_reconstruction_function)
+ create_single_source_cgal_program( "tutorial_example.cpp" )
+ CGAL_target_use_Eigen(tutorial_example)
else()
message(STATUS "NOTICE: The examples need Eigen 3.1 (or greater) will not be compiled.")
endif()
diff --git a/Poisson_surface_reconstruction_3/examples/Poisson_surface_reconstruction_3/tutorial_example.cmd b/Poisson_surface_reconstruction_3/examples/Poisson_surface_reconstruction_3/tutorial_example.cmd
new file mode 100644
index 00000000000..12b759aa160
--- /dev/null
+++ b/Poisson_surface_reconstruction_3/examples/Poisson_surface_reconstruction_3/tutorial_example.cmd
@@ -0,0 +1,3 @@
+data/kitten.xyz
+data/kitten.xyz 1
+data/kitten.xyz 2
diff --git a/Poisson_surface_reconstruction_3/examples/Poisson_surface_reconstruction_3/tutorial_example.cpp b/Poisson_surface_reconstruction_3/examples/Poisson_surface_reconstruction_3/tutorial_example.cpp
new file mode 100644
index 00000000000..ff58e34ed31
--- /dev/null
+++ b/Poisson_surface_reconstruction_3/examples/Poisson_surface_reconstruction_3/tutorial_example.cpp
@@ -0,0 +1,223 @@
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+
+// types
+typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
+typedef Kernel::FT FT;
+typedef Kernel::Point_3 Point_3;
+typedef Kernel::Vector_3 Vector_3;
+typedef Kernel::Sphere_3 Sphere_3;
+typedef CGAL::Point_set_3 Point_set;
+
+int main(int argc, char*argv[])
+{
+ ///////////////////////////////////////////////////////////////////
+ //! [Reading input]
+
+ Point_set points;
+
+ if (argc < 2)
+ {
+ std::cerr << "Usage: " << argv[0] << " [input.xyz/off/ply/las]" << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ const char* input_file = argv[1];
+ std::ifstream stream (input_file, std::ios_base::binary);
+ if (!stream)
+ {
+ std::cerr << "Error: cannot read file " << input_file << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ stream >> points;
+
+ std::cout << "Read " << points.size () << " point(s)" << std::endl;
+ if (points.empty())
+ return EXIT_FAILURE;
+
+ //! [Reading input]
+ ///////////////////////////////////////////////////////////////////
+
+ ///////////////////////////////////////////////////////////////////
+ //! [Outlier removal]
+
+ CGAL::remove_outliers (points,
+ 24, // Number of neighbors considered for evaluation
+ points.parameters().threshold_percent (5.0)); // Percentage of points to remove
+
+ std::cout << points.number_of_removed_points()
+ << " point(s) are outliers." << std::endl;
+
+ // Applying point set processing algorithm to a CGAL::Point_set_3
+ // object does not erase the points from memory but place them in
+ // the garbage of the object: memory can be freeed by the user.
+ points.collect_garbage();
+
+ //! [Outlier removal]
+ ///////////////////////////////////////////////////////////////////
+
+ ///////////////////////////////////////////////////////////////////
+ //! [Simplification]
+
+ // Compute average spacing using neighborhood of 6 points
+ double spacing = CGAL::compute_average_spacing (points, 6);
+
+ // Simplify using a grid of size 2 * average spacing
+ CGAL::grid_simplify_point_set (points, 2. * spacing);
+
+ std::cout << points.number_of_removed_points()
+ << " point(s) removed after simplification." << std::endl;
+
+ points.collect_garbage();
+
+ //! [Simplification]
+ ///////////////////////////////////////////////////////////////////
+
+ ///////////////////////////////////////////////////////////////////
+ //! [Smoothing]
+
+ CGAL::jet_smooth_point_set (points, 24);
+
+ //! [Smoothing]
+ ///////////////////////////////////////////////////////////////////
+
+ unsigned int reconstruction_choice
+ = (argc < 3 ? 0 : atoi(argv[2]));
+
+ if (reconstruction_choice == 0) // Poisson
+ {
+ ///////////////////////////////////////////////////////////////////
+ //! [Normal estimation]
+
+ CGAL::jet_estimate_normals
+ (points, 24); // Use 24 neighbors
+
+ // Orientation of normals, returns iterator to first unoriented point
+ typename Point_set::iterator unoriented_points_begin =
+ CGAL::mst_orient_normals(points, 24); // Use 24 neighbors
+
+ points.remove (unoriented_points_begin, points.end());
+
+ //! [Normal estimation]
+ ///////////////////////////////////////////////////////////////////
+
+ ///////////////////////////////////////////////////////////////////
+ //! [Poisson reconstruction]
+
+ CGAL::Surface_mesh output_mesh;
+ CGAL::poisson_surface_reconstruction_delaunay
+ (points.begin(), points.end(),
+ points.point_map(), points.normal_map(),
+ output_mesh, spacing);
+
+ //! [Poisson reconstruction]
+ ///////////////////////////////////////////////////////////////////
+
+ ///////////////////////////////////////////////////////////////////
+ //! [Output poisson]
+
+ std::ofstream f ("out.ply", std::ios_base::binary);
+ CGAL::set_binary_mode (f);
+ CGAL::write_ply (f, output_mesh);
+ f.close ();
+
+ //! [Output poisson]
+ ///////////////////////////////////////////////////////////////////
+ }
+ else if (reconstruction_choice == 1) // Advancing front
+ {
+ ///////////////////////////////////////////////////////////////////
+ //! [Advancing front reconstruction]
+
+ typedef std::array Facet; // Triple of indices
+
+ std::vector facets;
+
+ // The function is called using directly the points raw iterators
+ CGAL::advancing_front_surface_reconstruction(points.points().begin(),
+ points.points().end(),
+ std::back_inserter(facets));
+ std::cout << facets.size ()
+ << " facet(s) generated by reconstruction." << std::endl;
+
+ //! [Advancing front reconstruction]
+ ///////////////////////////////////////////////////////////////////
+
+ ///////////////////////////////////////////////////////////////////
+ //! [Output advancing front]
+
+ // copy points for random access
+ std::vector vertices;
+ vertices.reserve (points.size());
+ std::copy (points.points().begin(), points.points().end(), std::back_inserter (vertices));
+
+ CGAL::Surface_mesh output_mesh;
+ CGAL::Polygon_mesh_processing::polygon_soup_to_polygon_mesh (vertices, facets, output_mesh);
+ std::ofstream f ("out.off");
+ f << output_mesh;
+ f.close ();
+
+ //! [Output advancing front]
+ ///////////////////////////////////////////////////////////////////
+ }
+ else if (reconstruction_choice == 2) // Scale space
+ {
+ ///////////////////////////////////////////////////////////////////
+ //! [Scale space reconstruction]
+
+ CGAL::Scale_space_surface_reconstruction_3 reconstruct
+ (points.points().begin(), points.points().end());
+
+ // Smooth using 4 iterations of Jet Smoothing
+ reconstruct.increase_scale (4, CGAL::Scale_space_reconstruction_3::Jet_smoother());
+ // Mesh with the Advancing Front mesher with a maximum facet length of 0.5
+ reconstruct.reconstruct_surface (CGAL::Scale_space_reconstruction_3::Advancing_front_mesher(0.5));
+
+ //! [Scale space reconstruction]
+ ///////////////////////////////////////////////////////////////////
+
+ ///////////////////////////////////////////////////////////////////
+ //! [Output scale space]
+
+ std::ofstream f ("out.off");
+ f << "OFF" << std::endl << points.size () << " "
+ << reconstruct.number_of_facets() << " 0" << std::endl;
+ for (Point_set::Index idx : points)
+ f << points.point (idx) << std::endl;
+ for (const auto& facet : CGAL::make_range (reconstruct.facets_begin(), reconstruct.facets_end()))
+ f << "3 "<< facet << std::endl;
+ f.close ();
+
+ //! [Output scale space]
+ ///////////////////////////////////////////////////////////////////
+ }
+ else // Handle error
+ {
+ std::cerr << "Error: invalid reconstruction id: " << reconstruction_choice << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/Scale_space_reconstruction_3/doc/Scale_space_reconstruction_3/Scale_space_reconstruction_3.txt b/Scale_space_reconstruction_3/doc/Scale_space_reconstruction_3/Scale_space_reconstruction_3.txt
index db6d7281b90..333c6ef1d1a 100644
--- a/Scale_space_reconstruction_3/doc/Scale_space_reconstruction_3/Scale_space_reconstruction_3.txt
+++ b/Scale_space_reconstruction_3/doc/Scale_space_reconstruction_3/Scale_space_reconstruction_3.txt
@@ -17,6 +17,10 @@ Left: 5760 points on a synthetic knot data set. Right: reconstructed surface mes
A triangulated surface mesh is generated by first computing the point set at a coarse scale, then constructing a mesh of the point set at this scale, and finally reverting the points of the mesh back to their original scale.
+\note A \ref tuto_reconstruction "detailed tutorial on surface reconstruction"
+is provided with a guide to choose the most appropriate method along
+with pre- and post-processing.
+
\section ScaleSpaceReconstruction3secMethod Scale-Space