mirror of https://github.com/CGAL/cgal
Update branch from master after trailing whitespaces and tabs removal
This commit is contained in:
commit
2fa1f56ea1
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,294 @@
|
|||
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 tutorials provides guidances 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 leads 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:
|
||||
|
||||
<center>
|
||||
| | 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 |
|
||||
</center>
|
||||
|
||||
\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 details.
|
||||
|
||||
|
||||
\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. Smooth point cloud was generated
|
||||
using _jet smoothing_; 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
|
||||
|
||||
|
||||
*/
|
||||
}
|
||||
|
|
@ -16,6 +16,8 @@ User Manual.
|
|||
geometric primitives, the notion of <em>traits classes</em> 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
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 120 KiB |
File diff suppressed because it is too large
Load Diff
|
After Width: | Height: | Size: 46 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 508 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 303 KiB |
|
|
@ -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.},
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
namespace CGAL {
|
||||
/*!
|
||||
|
||||
\mainpage User Manual
|
||||
\mainpage User Manual
|
||||
\anchor Chapter_Poisson_Surface_Reconstruction
|
||||
\cgalAutoToc
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -38,7 +43,7 @@ reduce noise in the input data; 5) Normal estimation and orientation
|
|||
when the normals are not already provided by the acquisition device;
|
||||
and 6) Surface reconstruction.
|
||||
|
||||
\cgal provides algorithms for all steps listed above except alignment.
|
||||
\cgal provides algorithms for all steps listed above except alignment.
|
||||
|
||||
Chapter \ref chappoint_set_processing_3 "Point Set Processing"
|
||||
describes algorithms to pre-process the point set before
|
||||
|
|
@ -115,12 +120,12 @@ The following example reads a point set, creates a Poisson implicit function and
|
|||
|
||||
|
||||
The computed implicit functions can be iso-contoured to reconstruct a
|
||||
surface by using the \cgal surface mesh generator
|
||||
surface by using the \cgal surface mesh generator
|
||||
\cgalCite{cgal:ry-gsddrm-06} \cgalCite{cgal:bo-pgsms-05} :
|
||||
|
||||
`make_surface_mesh()`
|
||||
`make_surface_mesh()`
|
||||
|
||||
The parameter `Tag` affects the behavior of `make_surface_mesh()`:
|
||||
The parameter `Tag` affects the behavior of `make_surface_mesh()`:
|
||||
- `Manifold_tag`: the output mesh is guaranteed to be a manifold surface without boundary.
|
||||
- `Manifold_with_boundary_tag`: the output mesh is guaranteed to be manifold and may have boundaries.
|
||||
- `Non_manifold_tag`: the output mesh has no guarantee and hence is outputted as a polygon soup.
|
||||
|
|
@ -137,8 +142,8 @@ a three dimensional triangulation.
|
|||
Other \cgal components provide functions to write the reconstructed
|
||||
surface mesh to the %Object File Format (OFF) \cgalCite{cgal:p-gmgv16-96}
|
||||
and to convert it to a polyhedron (when it is manifold):
|
||||
- `output_surface_facets_to_off()`
|
||||
- `output_surface_facets_to_polyhedron()`
|
||||
- `output_surface_facets_to_off()`
|
||||
- `output_surface_facets_to_polyhedron()`
|
||||
|
||||
See \ref Poisson_surface_reconstruction_3/poisson_reconstruction_example.cpp "poisson_reconstruction_example.cpp" example above.
|
||||
|
||||
|
|
@ -166,7 +171,7 @@ reconstruction method expects a dense 3D oriented point set (typically
|
|||
matching the epsilon-sampling condition \cgalCite{cgal:bo-pgsms-05}) and
|
||||
sampled over a closed, smooth surface. Oriented herein means that all
|
||||
3D points must come with consistently oriented normals to the inferred
|
||||
surface. \cgalFigureRef{Poisson_surface_reconstruction_3figbimba} and \cgalFigureRef{Poisson_surface_reconstruction_3figeros}
|
||||
surface. \cgalFigureRef{Poisson_surface_reconstruction_3figbimba} and \cgalFigureRef{Poisson_surface_reconstruction_3figeros}
|
||||
illustrate cases where these ideal conditions are met.
|
||||
|
||||
\cgalFigureBegin{Poisson_surface_reconstruction_3figbimba,bimba.jpg}
|
||||
|
|
@ -343,7 +348,7 @@ with the 03 option which maximizes speed. All measurements were done using the
|
|||
|
||||
The point set chosen for benchmarking the Poisson implicit function is the Bimba con Nastrino point set
|
||||
(1.6 million points) depicted by \cgalFigureRef{Poisson_surface_reconstruction_3-fig-contouring_bench}.
|
||||
We measure the Poisson implicit function computation (i.e., the call to
|
||||
We measure the Poisson implicit function computation (i.e., the call to
|
||||
`Poisson_reconstruction_function::compute_implicit_function()` denoted by Poisson solve hereafter)
|
||||
for this point set as well as for simplified versions obtained through random simplification.
|
||||
The following table provides Poisson solve computation times in seconds for an increasing number of points.
|
||||
|
|
@ -353,9 +358,9 @@ The following table provides Poisson solve computation times in seconds for an i
|
|||
<TR>
|
||||
<TD class="math" ALIGN=CENTER NOWRAP>
|
||||
|
||||
Number of points (x1000)
|
||||
Number of points (x1000)
|
||||
<TD class="math" ALIGN=CENTER NOWRAP>
|
||||
Poisson solve duration (in s)
|
||||
Poisson solve duration (in s)
|
||||
<TR><TD ALIGN=LEFT NOWRAP COLSPAN=2><HR>
|
||||
<TR>
|
||||
<TD class="math" ALIGN=CENTER NOWRAP>
|
||||
|
|
@ -405,16 +410,16 @@ in mm (the Bimba con Nastrino statue is 324 mm tall).
|
|||
<TR><TD ALIGN=LEFT NOWRAP COLSPAN=3><HR>
|
||||
<TR>
|
||||
<TD class="math" ALIGN=CENTER NOWRAP>
|
||||
Approx. distance (*average spacing)
|
||||
Approx. distance (*average spacing)
|
||||
<TD class="math" ALIGN=CENTER NOWRAP>
|
||||
Contouring duration (in s)
|
||||
Contouring duration (in s)
|
||||
<TD class="math" ALIGN=CENTER NOWRAP>
|
||||
Reconstruction error (mm)
|
||||
Reconstruction error (mm)
|
||||
<TR><TD ALIGN=LEFT NOWRAP COLSPAN=3><HR>
|
||||
<TR>
|
||||
|
||||
<TD class="math" ALIGN=CENTER NOWRAP>
|
||||
0.1
|
||||
0.1
|
||||
<TD class="math" ALIGN=CENTER NOWRAP>
|
||||
19.2
|
||||
<TD class="math" ALIGN=CENTER NOWRAP>
|
||||
|
|
@ -442,7 +447,7 @@ Reconstruction error (mm)
|
|||
0.36
|
||||
<TR>
|
||||
<TD class="math" ALIGN=CENTER NOWRAP>
|
||||
2
|
||||
2
|
||||
<TD class="math" ALIGN=CENTER NOWRAP>
|
||||
0.8
|
||||
<TD class="math" ALIGN=CENTER NOWRAP>
|
||||
|
|
@ -461,16 +466,16 @@ for the Bimba con Nastrino point set simplified to 100k points.
|
|||
|
||||
We measure the memory occupancy for the reconstruction of the full Bimba con Nastrino point
|
||||
set (1.8 millions points) as well as for simplified versions.\n
|
||||
The Poisson implicit function computation has a memory peak when solving the Poisson linear
|
||||
The Poisson implicit function computation has a memory peak when solving the Poisson linear
|
||||
system using the sparse linear solver.
|
||||
|
||||
<TABLE CELLSPACING=5 >
|
||||
<TR><TD ALIGN=LEFT NOWRAP COLSPAN=2><HR>
|
||||
<TR>
|
||||
<TD class="math" ALIGN=CENTER NOWRAP>
|
||||
Number of points (x1000)
|
||||
Number of points (x1000)
|
||||
<TD class="math" ALIGN=CENTER NOWRAP>
|
||||
Memory occupancy (MBytes)
|
||||
Memory occupancy (MBytes)
|
||||
<TR><TD ALIGN=LEFT NOWRAP COLSPAN=2><HR>
|
||||
<TR>
|
||||
<TD class="math" ALIGN=CENTER NOWRAP>
|
||||
|
|
@ -509,19 +514,19 @@ Memory occupancy (MBytes)
|
|||
\subsection SurfReconstPerfPSS Point Set Simplification
|
||||
|
||||
Due to the memory limitations described above, we recommend to simplify the point sets captured by laser scanners.\n
|
||||
We measure the reconstruction error for the Bimba con Nastrino point set (1.6M points) as well as for
|
||||
simplified versions. All reconstructions use the recommended contouring parameter
|
||||
We measure the reconstruction error for the Bimba con Nastrino point set (1.6M points) as well as for
|
||||
simplified versions. All reconstructions use the recommended contouring parameter
|
||||
`approximation distance = 0.25 * the input point` set's average spacing.
|
||||
The reconstruction error is expressed as the average distance from input points to the reconstructed surface in mm
|
||||
The reconstruction error is expressed as the average distance from input points to the reconstructed surface in mm
|
||||
(the Bimba con Nastrino statue is 324 mm tall).
|
||||
|
||||
<TABLE CELLSPACING=5 >
|
||||
<TR><TD ALIGN=LEFT NOWRAP COLSPAN=2><HR>
|
||||
<TR>
|
||||
<TD class="math" ALIGN=CENTER NOWRAP>
|
||||
Number of points (x1000)
|
||||
Number of points (x1000)
|
||||
<TD class="math" ALIGN=CENTER NOWRAP>
|
||||
Reconstruction error (mm)
|
||||
Reconstruction error (mm)
|
||||
<TR><TD ALIGN=LEFT NOWRAP COLSPAN=2><HR>
|
||||
<TR>
|
||||
<TD class="math" ALIGN=CENTER NOWRAP>
|
||||
|
|
@ -530,7 +535,7 @@ Reconstruction error (mm)
|
|||
0.27
|
||||
<TR>
|
||||
<TD class="math" ALIGN=CENTER NOWRAP>
|
||||
120
|
||||
120
|
||||
<TD class="math" ALIGN=CENTER NOWRAP>
|
||||
0.15
|
||||
<TR>
|
||||
|
|
@ -570,10 +575,10 @@ as well as for simplified versions.
|
|||
|
||||
\section SurfReconstDesignHistory Design and Implementation History
|
||||
|
||||
The initial implementation was essentially done by Laurent Saboret, guided by Pierre Alliez and Ga\"el Guennebaud.
|
||||
The initial implementation was essentially done by Laurent Saboret, guided by Pierre Alliez and Ga\"el Guennebaud.
|
||||
For later releases of the package Andreas Fabri worked on performance improvements, and Laurent Rineau added the
|
||||
two passes for dealing with holes.
|
||||
|
||||
|
||||
*/
|
||||
*/
|
||||
} /* namespace CGAL */
|
||||
|
|
|
|||
|
|
@ -31,11 +31,13 @@ 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()
|
||||
|
||||
|
||||
|
||||
else()
|
||||
|
||||
message(STATUS "NOTICE: This program requires the CGAL library, and will not be compiled.")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
data/kitten.xyz
|
||||
data/kitten.xyz 1
|
||||
data/kitten.xyz 2
|
||||
|
|
@ -0,0 +1,223 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
|
||||
#include <CGAL/Point_set_3.h>
|
||||
#include <CGAL/Point_set_3/IO.h>
|
||||
|
||||
#include <CGAL/remove_outliers.h>
|
||||
#include <CGAL/grid_simplify_point_set.h>
|
||||
#include <CGAL/jet_smooth_point_set.h>
|
||||
#include <CGAL/jet_estimate_normals.h>
|
||||
#include <CGAL/mst_orient_normals.h>
|
||||
|
||||
#include <CGAL/poisson_surface_reconstruction.h>
|
||||
#include <CGAL/Advancing_front_surface_reconstruction.h>
|
||||
#include <CGAL/Scale_space_surface_reconstruction_3.h>
|
||||
#include <CGAL/Scale_space_reconstruction_3/Jet_smoother.h>
|
||||
#include <CGAL/Scale_space_reconstruction_3/Advancing_front_mesher.h>
|
||||
|
||||
#include <CGAL/Surface_mesh.h>
|
||||
#include <CGAL/Polygon_mesh_processing/polygon_soup_to_polygon_mesh.h>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
|
||||
// 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_3, Vector_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<CGAL::Sequential_tag> (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<CGAL::Sequential_tag> (points, 24);
|
||||
|
||||
//! [Smoothing]
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
unsigned int reconstruction_choice
|
||||
= (argc < 3 ? 0 : atoi(argv[2]));
|
||||
|
||||
if (reconstruction_choice == 0) // Poisson
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//! [Normal estimation]
|
||||
|
||||
CGAL::jet_estimate_normals<CGAL::Sequential_tag>
|
||||
(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<Point_3> 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<std::size_t, 3> Facet; // Triple of indices
|
||||
|
||||
std::vector<Facet> 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<Point_3> vertices;
|
||||
vertices.reserve (points.size());
|
||||
std::copy (points.points().begin(), points.points().end(), std::back_inserter (vertices));
|
||||
|
||||
CGAL::Surface_mesh<Point_3> 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<Kernel> 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<Kernel>());
|
||||
// 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<Kernel>(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;
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
namespace CGAL {
|
||||
/*!
|
||||
|
||||
\mainpage User Manual
|
||||
\mainpage User Manual
|
||||
\anchor Chapter_Scale_space_reconstruction
|
||||
\anchor chapterScaleSpaceReconstruction3
|
||||
\cgalAutoToc
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -174,7 +178,7 @@ We have evaluated the scale-space surface reconstruction method on several data
|
|||
|
||||
\cgalFigureAnchor{chapterScaleSpaceReconstruction3figSettings}
|
||||
<center>
|
||||
| Data set | Neighbors | Samples | Iterations |
|
||||
| Data set | Neighbors | Samples | Iterations |
|
||||
| ----: | ----: | ----: | ----: |
|
||||
Mushroom (s) | 10 | 200 | 2 |
|
||||
Elephant (s) | 15 | 200 | 1 |
|
||||
|
|
@ -269,6 +273,6 @@ This last example shows how to use the alternative operators [Jet_smoother](@ref
|
|||
|
||||
This method was developed by Julie Digne <i>et al.</i> in 2011 \cgalCite{cgal:dmsl-ssmrp-11} and implemented by Thijs van Lankveld at Inria - Sophia Antipolis in 2014.
|
||||
|
||||
*/
|
||||
*/
|
||||
} /* namespace CGAL */
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue