﻿namespace CGAL {
/*!

\mainpage User Manual
\anchor Chapter_Point_Set_Processing
\anchor chappoint_set_processing_3

\cgalAutoToc

\authors Pierre Alliez, Simon Giraudot, Clément Jamin, Florent Lafarge, Quentin Mérigot, Jocelyn Meyron, Laurent Saboret, Nader Salman, Shihao Wu, Necip Fazil Yildiran

\section Point_set_processing_3Introduction Introduction

This \cgal component implements methods to analyze and process 3D point sets. The input is an unorganized 3D point set, possibly with normal attributes (unoriented or oriented). The input point set can be analyzed to measure geometric properties such as average
spacing between the points and their `k` nearest neighbors. It
can be processed with functions devoted to the simplification, regularization, upsampling, outlier removal, smoothing, normal estimation and normal orientation. The processing of point sets is often needed in applications dealing with measurement data, such as surface reconstruction from laser scanned data (see \cgalFigureRef{Point_set_processing_3figintroduction}).

\cgalFigureBegin{Point_set_processing_3figintroduction,introduction.jpg}
Point set processing. Left: 275K points sampled on the statue of an elephant with a Minolta laser scanner. Right: point set after outlier removal, denoising and simplification to 17K points.
\cgalFigureEnd

In the context of surface reconstruction we can position the elements
of this component along the common surface reconstruction pipeline
(\cgalFigureRef{Point_set_processing_3figpipeline}) which involves the
following steps:
-# Scanning and scan registration to produce a set of
points or points with normals;
-# Outlier removal;
-# Simplification to reduce the number of input points;
-# Smoothing to reduce noise in the input data;
-# Normal estimation and orientation when the normals are not already provided
by the acquisition device; and
-# Surface reconstruction. Chapter \ref Chapter_Poisson_Surface_Reconstruction "Poisson Surface Reconstruction"
deals with surface reconstruction from point sets with normal attributes.

\cgalFigureBegin{Point_set_processing_3figpipeline,pipeline.jpg}
Point set processing pipeline for surface reconstruction. The algorithms listed in gray are available from other CGAL components (bounding volumes and principal component analysis).
\cgalFigureEnd


\section Point_set_processing_3API API

The algorithms of this component take as input parameters ranges of 3D
points, or of 3D points with normals. They can be
adapted to the user's data structures and make extensive use of
\ref Point_set_processing_3NamedParameters "named parameters" and of
\ref Point_set_processing_3PropertyMaps "property maps":

\code
std::vector<PointVectorPair> points;
typedef CGAL::First_of_pair_property_map<PointVectorPair> Point_map;
typedef CGAL::Second_of_pair_property_map<PointVectorPair> Vector_map;

CGAL::jet_estimate_normals
<CGAL::Parallel_tag>           // concurrency tag
  (points,                     // input range of points
   12,                         // parameter: number of neighbors
   CGAL::parameters::          // named parameters:
   point_map (Point_map()).    //  * point map
   normal_map (Vector_map())); //  * normal map
\endcode

This API was introduced in \cgal 4.12. Please refer to the
\ref Point_set_processing_3Outdated "dedicated section"
on how to upgrade from the outdated API.

\subsection Point_set_processing_3NamedParameters Named Parameters

Named parameters are used to deal with optional parameters. The page
\ref BGLNamedParameters explains the rationale and API in general.
The page \ref bgl_namedparameters describes their usage.

\subsection Point_set_processing_3PropertyMaps Property Maps

The property maps are used to access the point or normal information
from the input data, so as to let the user decide upon the
implementation of a point with normal. The latter can be represented
as, e.g., a class derived from the \cgal 3D point, or as a
`std::pair<Point_3<K>, Vector_3<K>>`, or as a
`boost::tuple<..,Point_3<K>, ..., Vector_3<K> >`.

The following classes described in Chapter \ref PkgPropertyMap
provide property maps for the implementations of points with normals
listed above:

- `Identity_property_map<T>`
- `First_of_pair_property_map<Pair>` and `Second_of_pair_property_map<Pair>`
- `Nth_of_tuple_property_map<N, Tuple>`

`Identity_property_map<Point_3>` is the default value of the
position property map expected by all functions in this component.

See below examples using pair and tuple property maps.

Users of this package may use other types to represent positions and
normals if they implement the corresponding property maps.

Points and normals can even be stored in separate containers
and accessed by their index, as any built-in vector is also
a property map.

\cgalExample{Point_set_processing_3/grid_simplify_indices.cpp}

\subsection Point_set_processing_3Outdated Upgrading from pre-CGAL 4.12 API

The current API based on ranges and named parameters was introduced in
\cgal 4.12. The old API that used pairs of iterators along with usual
\cpp parameters (with some default values and overloads to handle
optional parameters) has been removed in \cgal 5.0.

Translating your pre-\cgal 4.12 code using Point Set Processing to the
current API is easy. For example, consider this code using the old API:

\code
std::vector<PointVectorPair> points;

// Old pre-CGAL 4.12 API
CGAL::jet_estimate_normals<Concurrency_tag>
  (points.begin(), points.end(),
   CGAL::First_of_pair_property_map<PointVectorPair>(),
   CGAL::Second_of_pair_property_map<PointVectorPair>(),
   12); // Number of neighbors
\endcode

The pair of iterators is replaced by a range and the optional
parameters (than can be deduced automatically in simple cases) are
moved to the end of the function in a single named parameter object
(see \ref BGLNamedParameters). The code translated to the current API
becomes:

\code
std::vector<PointVectorPair> points;

// New API
CGAL::jet_estimate_normals<Concurrency_tag>
  (points,
   12, // Number of neighbors
   CGAL::parameters::point_map (CGAL::First_of_pair_property_map<PointVectorPair>()).
   normal_map (CGAL::Second_of_pair_property_map<PointVectorPair>()));
\endcode

Please refer to the @ref PkgPointSetProcessing3Ref for
the detailed API of the Point Set Processing functions.


\section Point_set_processing_3InputOutput Input/Output

\subsection Point_set_processing_3Points_io Points And Normals

\cgal provides functions to read and write sets of points (possibly with normals)
from the following file formats:

- \link IOStreamXYZ XYZ \endlink (\ascii file three point coordinates `x y z` per line or three
point coordinates and three normal vector coordinates `x y z nx ny nz`
per line)
- \link IOStreamOFF OFF (%Object File Format) \endlink -- \cgalCite{cgal:p-gmgv16-96}
- \link IOStreamPLY PLY (Polygon File Format) \endlink -- \cgalCite{cgal:b-ply-11}
- \link IOStreamLAS LAS (Lidar Format) \endlink -- \cgalCite{cgal:asprs-lasf-13} This format does
not handle normals and requires the \ref thirdpartyLASlib library.

All of the functions in \ref PkgPointSetProcessing3IO (with the exception of the LAS format)
can read and write either points alone or points with normals (depending on
whether the `normal_map` named parameter is used by the user or not).
Note that the %PLY format handles both \ascii and binary formats. In
addition, %PLY and %LAS are extensible formats that can embed additional
properties. These can also be read by \cgal (see Section \ref
Point_set_processing_3Properties_io).

\subsubsection Point_set_processing_3Example_io Example

The following example reads a point set from an input file and writes
it to a file, both in the XYZ format. Positions and normals are stored
in pairs and accessed through property maps.
\cgalExample{Point_set_processing_3/read_write_xyz_point_set_example.cpp}

\subsection Point_set_processing_3Properties_io Points With Properties

%PLY files are designed to embed an arbitrary number of additional
attributes. More specifically, point sets may contain visibility
vectors, RGB colors, intensity, etc. As it is not possible to provide
dedicated functions to every possible combination of %PLY properties,
\cgal provides a simple way to read %PLY properties and store them in
any structure the user needs. Handling of %LAS files works similarly
with the difference that the property names and types are fixed and
defined by the %LAS standard.

Functions `read_PLY_with_properties()` and
`read_LAS_with_properties()` allow the user to read any
property needed. The user must provide a set of property handlers that
are used to instantiate number types and complex objects from %PLY/%LAS
properties. This handlers are either:

- a pair consisting of a property map and of a single %PLY/%LAS property
descriptor

- a tuple consisting of a property map, a functor to construct the
objects wanted and multiple %PLY/%LAS property descriptors

Output functions `write_PLY_with_properties()` and
`write_LAS_with_properties()` work similarly.

\subsubsection Point_set_processing_3Example_ply_write PLY Writing Example

The following example shows how to call
`write_PLY_with_properties()` to write a point set with points,
RGB colors and intensity. Notice that in order to write a complex
object, users need to provide an overload of `CGAL::Output_rep`.

\cgalExample{Point_set_processing_3/write_ply_points_example.cpp}

\subsubsection Point_set_processing_3Example_ply_read PLY Reading Example

The following example shows how to call
`read_PLY_with_properties()` to read a point set with points,
normals, RGB colors and intensity and stores these attributes in a
user-defined container.

\cgalExample{Point_set_processing_3/read_ply_points_with_colors_example.cpp}

\subsubsection Point_set_processing_3Example_las_read LAS Reading Example

The following example shows how to call
`read_LAS_with_properties()` to read a point set with points
and RGBI colors and stores these attributes in a user-defined
container.

\cgalExample{Point_set_processing_3/read_las_example.cpp}

\sa \ref IOstreamPointSetIO

\section Point_set_processing_3Spacing Average Spacing

Function `compute_average_spacing()` computes the average
spacing of all input points to their `k` nearest neighbor points,
`k` being specified by the user. As it provides an order of a
point set density, this function is used downstream the surface
reconstruction pipeline to automatically determine some parameters
such as output mesh sizing for surface reconstruction.

\subsection Point_set_processing_3Example_average_spacing Example

The following example reads a point set in the `xyz` format and
computes the average spacing. Index, position and color are stored in
a tuple and accessed through property maps.
\cgalExample{Point_set_processing_3/average_spacing_example.cpp}

Note that other functions such as centroid or bounding volumes are
found in other \cgal components:

- `centroid()`
- `bounding_box()`
- `Min_sphere_of_spheres_d<Traits>`

\section Point_set_processing_3Scale Automatic Scale Estimation

Point sets are often used to sample objects with a higher dimension,
typically a curve in 2D or a surface in 3D. In such cases, finding the
scale of the object is crucial, that is to say finding the minimal
number of points (or the minimal local range) such that the subset of
points has the appearance of a curve in 2D or a surface in 3D
\cgalCite{cgal:gcsa-nasr-13}.

\cgal provides two functions that automatically estimate the scale of a
2D point set sampling a curve or a 3D point set sampling a surface:

- `estimate_global_k_neighbor_scale()`
- `estimate_global_range_scale()`

Functions such as `grid_simplify_point_set()` require a range scale
while `jet_estimate_normals()`, `remove_outliers()` or
`vcm_estimate_normals()` are examples of functions that accepts both a
K neighbor scale or a range scale.

In some specific cases, the scale of a point set might not be
homogeneous (for example if the point set contains variable
noise). \cgal also provides two functions that automatically estimate
the scales of a point set at a set of user-defined query points:

- `estimate_local_k_neighbor_scales()`
- `estimate_local_range_scales()`

The 4 functions presented here work both with 2D points and 3D points
and they shouldn't be used if the point sets do not sample a curve in
2D or a surface in 3D.

\subsection Point_set_processing_3Example_scale_estimation_global Global Scale Example

The following example reads a 3D point set in the `xyz` format and:

- Estimates the K neighbor global scale
- Uses it to smooth the point set
- Estimates the range global scale
- Uses it to simplify the point set

\cgalExample{Point_set_processing_3/scale_estimation_example.cpp}

\subsection Point_set_processing_3Example_scale_estimation_local Local Scales Example

This second example generates a 2D point set sampling a circle with
variable noise. It then estimates the scale at 3 different query
points in the domain.

\cgalExample{Point_set_processing_3/scale_estimation_2d_example.cpp}

\section Point_set_processing_3Registration Registration

\cgal provides two functions as wrapper for the \ref thirdpartyOpenGR library
\cgalCite{cgal:m-ogr-17}, and two functions as wrapper for the \ref thirdpartylibpointmatcher
library :

- `CGAL::OpenGR::compute_registration_transformation()` computes the
registration of one point set w.r.t. another in the form of a
`CGAL::Aff_transformation_3` object, using the Super4PCS algorithm
\cgalCite{cgal:mam-sffgp-14};

- `CGAL::OpenGR::register_point_sets()` computes the registration of
one point set w.r.t. another and directly aligns it to it;

- `CGAL::pointmatcher::compute_registration_transformation()` computes the
registration of one point set w.r.t. another in the form of a
`CGAL::Aff_transformation_3` object, using the ICP (Iterative Closest Point)
algorithm;

- `CGAL::pointmatcher::register_point_sets()` computes the registration of
one point set w.r.t. another and directly aligns it to it.

\subsection Point_set_processing_3Examples_registration_OpenGR OpenGR Example

The following example reads two point sets and aligns them using the
\ref thirdpartyOpenGR library, using the Super4PCS algorithm:
\cgalExample{Point_set_processing_3/registration_with_OpenGR.cpp}

\cgalFigureRef{Point_set_processing_3tableRegistrationRegistration_visualization_table} demonstrates
visualization of a scan data before and after different registration methods are applied,
including the %OpenGR registration method. To obtain the results for %OpenGR registration
in the visualization table, above-mentioned example was used.

\subsubsection Point_set_processing_3Examples_registration_OpenGR_parameter_number_of_samples Parameter: number_of_samples

Input clouds are sub-sampled prior exploration, to ensure fast computations.
Super4PCS has a linear complexity w.r.t. the number of input samples, allowing
to use larger values than 4PCS.
Simple geometry with large overlap can be matched with only 200 samples.
However, with Super4PCS, smaller details can be used during the process by using
up to thousands of points. There is no theoretical limit to this parameter;
however, using too large values leads to very a large congruent set,
which requires more time and memory to be explored.

Using a large number of samples is recommended when:

- geometrical details are required to perform the matching, for instance to disambiguate
between several similar configurations,

- the clouds have a very low overlap: using a too sparse sampling can result in
an empty overlapping area, causing the algorithm to fail,

- the clouds are very noisy, and require a dense sampling.

Note that Super4PCS is a global registration algorithm, which finds a good approximate
of the rigid transformation aligning two clouds. Increasing the number of samples
in order to get a fine registration is not optimal: it is usually faster to use
fewer samples, and refine the transformation using a local algorithm, like the ICP,
or its variant SparseICP.

\subsubsection Point_set_processing_3Examples_registration_OpenGR_parameter_accuracy Parameter: accuracy

This parameter controls the registration accuracy: setting a small value means that
the two clouds need to be very close to be considered as well aligned. It is expressed in scene units.

A simple way to understand its impact is to consider the computation of the Largest Common Pointset (LCP),
the metric used to verify how aligned the clouds are. For each transformation matrix produced
by Super4PCS, OpenGR computes the LCP measure by considering a shell around the reference cloud, and
count the percentage of points of the target cloud lying in the shell. The thickness of the shell is
defined by the parameter delta (accuracy).

Using too wide values will slow down the algorithm by increasing the size of the congruent set,
while using to small values prevents to find a solution. This parameter impacts other steps of
the algorithm, see the paper \cgalCite{cgal:mam-sffgp-14} for more details.

\subsubsection Point_set_processing_3Examples_registration_OpenGR_parameter_normal Parameter: maximum normal deviation

This parameter sets an angle threshold above which two pairs of points are discarded as candidates
for matching. It is expressed in degrees.

The default value is 90° (no filtering). Decreasing this value allows to decrease the computation
time by being more selective on candidates. Using too small values might result in ignoring
candidates that should indeed have been matched and may thus result in a quality decrease.

\subsubsection Point_set_processing_3Examples_registration_OpenGR_parameter_overlap Parameter: overlap

Ratio of expected overlap between the two point sets: it is ranging between 0 (no overlap) to 1 (100% overlap).

The overlap parameter controls the size of the basis used for registration, as shown below:

\cgalFigureBegin{Point_set_processing_3figOpenGR_parameter_overlap,super4PCS_overlap.png}
The effect of varying overlap parameter on the size of the basis used for registration. The overlap is smaller for left (a) than right (b).
\cgalFigureEnd

Usually, the larger the overlap, the faster the algorithm.
When the overlap is unknown, a simple way to set this parameter is to start from
100% overlap, and decrease the value until obtaining a good result.
Using too small values will slow down the algorithm, and
reduce the accuracy of the result.

\subsubsection Point_set_processing_3Examples_registration_OpenGR_parameter_maximum_running_time Parameter: maximum_running_time

Maximum number of seconds after which the algorithm stops. Super4PCS explores the
transformation space to align the two input clouds. Since the exploration is performed
randomly, it is recommended to use a large time value to explore the whole space.

\subsection Point_set_processing_3Examples_registration_PointMatcher PointMatcher Example

The following example reads two point sets and aligns them using the
\ref thirdpartylibpointmatcher library, using the ICP algorithm. It also shows how
to customize ICP algorithm by using possible configurations:
\cgalExample{Point_set_processing_3/registration_with_pointmatcher.cpp}

\cgalFigureRef{Point_set_processing_3tableRegistrationRegistration_visualization_table} demonstrates
visualization of a scan data before and after different registration methods are applied,
including the PointMatcher registration method. To obtain the results for PointMatcher registration
in the visualization table, above-mentioned example was used.

\subsubsection Point_set_processing_3Examples_registration_PointMatcher_parameter_point_set_filters Parameter: point_set_filters

The chain of filters to be applied to the point cloud. The
point cloud is processed into an intermediate point cloud with the given chain
of filters to be used in the alignment procedure. The chain is organized with
the forward traversal order of the point set filters range.

The chain of point set filters are applied only once at the beginning of the
ICP procedure, i.e., before the first iteration of the ICP algorithm.

The filters can have several purposes, including but not limited to:

- removal of noisy points which render alignment of point clouds difficult,

- removal of redundant points so as to speed up alignment,

- addition of descriptive information to the points such as a surface normal vector or the direction from the point to the sensor.

In registration, there are two point clouds in consideration, one of which is the reference point
cloud while the other one is the point cloud to register. The point set filters corresponds to `readingDataPointsFilters` configuration module of \ref thirdpartylibpointmatcher
library while it corresponds to the `referenceDataPointsFilters` for the other point cloud.
The filters should be chosen and set from possible components of those configuration modules.

\subsubsection Point_set_processing_3Examples_registration_PointMatcher_parameter_matcher Parameter: matcher

The method used for matching (linking) the points from to the points in the reference cloud.

Corresponds to `matcher` configuration module of \ref thirdpartylibpointmatcher
library. The matcher should be chosen and set from possible components of
the `matcher` configuration module.
See <a href="https://libpointmatcher.readthedocs.io/en/latest/Configuration/#configuration-of-an-icp-chain">libpointmatcher documentation</a>
for possible configurations.

\subsubsection Point_set_processing_3Examples_registration_PointMatcher_parameter_outlier_filters Parameter: outlier_filters

The chain of filters to be applied to the matched (linked) point clouds after
each processing iteration of the ICP algorithm to remove the links which do not
correspond to true point correspondences. The outliers are rejected. Points
with no link are ignored in the subsequent error minimization step.
The chain is organized with the forward traversal order of the outlier filters
range.

Corresponds to `outlierFilters` configuration module of \ref thirdpartylibpointmatcher
library. The filters should be chosen and set from possible components of
the `outlierFilters` configuration module.
See <a href="https://libpointmatcher.readthedocs.io/en/latest/Configuration/#configuration-of-an-icp-chain">libpointmatcher documentation</a>
for possible configurations.

\subsubsection Point_set_processing_3Examples_registration_PointMatcher_parameter_error_minimizer Parameter: error_minimizer

The error minimizer that computes a transformation matrix such as to minimize
the error between the point sets.

Corresponds to `errorMinimizer` configuration module of \ref thirdpartylibpointmatcher
library. The error minimizer should be chosen and set from possible components of
the `errorMinimizer` configuration module.
See <a href="https://libpointmatcher.readthedocs.io/en/latest/Configuration/#configuration-of-an-icp-chain">libpointmatcher documentation</a>
for possible configurations.

\subsubsection Point_set_processing_3Examples_registration_PointMatcher_parameter_inspector Parameter: inspector

The inspector allows to log data at different steps for analysis. Inspectors
typically provide deeper scrutiny than the logger.

Corresponds to `inspector` configuration module of \ref thirdpartylibpointmatcher
library. The inspector should be chosen and set from possible components of
the `inspector` configuration module.
See <a href="https://libpointmatcher.readthedocs.io/en/latest/Configuration/#configuration-of-an-icp-chain">libpointmatcher documentation</a>
for possible configurations.

\subsubsection Point_set_processing_3Examples_registration_PointMatcher_parameter_logger Parameter: logger

The method for logging information regarding the registration process outputted
by \ref thirdpartylibpointmatcher library. The logs generated by CGAL library
does not get effected by this configuration.

Corresponds to `logger` configuration module of \ref thirdpartylibpointmatcher
library. The logger should be chosen and set from possible components of
the `logger` configuration module.
See <a href="https://libpointmatcher.readthedocs.io/en/latest/Configuration/#configuration-of-an-icp-chain">libpointmatcher documentation</a>
for possible configurations.

\subsubsection Point_set_processing_3Examples_registration_PointMatcher_parameter_transformation Parameter: transformation

The affine transformation that is used as the initial transformation for the reference point cloud.

\subsection Point_set_processing_3Examples_registration_OpenGR_PointMatcher_Pipeline OpenGR/PointMatcher Pipeline Example

The following example reads two point sets and aligns them by using both
\ref thirdpartyOpenGR and \ref thirdpartylibpointmatcher libraries, respectively.
It depicts a use case where a coarse estimation of a registration transformation
is done using the Super4PCS algorithm. Then, a fine registration from this coarse
registration using the ICP algorithm.
\cgalExample{Point_set_processing_3/registration_with_opengr_pointmatcher_pipeline.cpp}

\cgalFigureRef{Point_set_processing_3tableRegistrationRegistration_visualization_table} demonstrates
visualization of a scan data before and after different registration methods are applied,
including the pipeline of %OpenGR and PointMatcher registration methods. To obtain the results
for the pipeline of %OpenGR and PointMatcher registration methods in the visualization table,
above-mentioned example was used.

\cgalFigureAnchor{Point_set_processing_3tableRegistrationRegistration_visualization_table}
<table>
<tr>
  <th>       </th>
  <th>Scan 1 </th>
  <th>Scan 1 (possibly transformed, green) and Scan 2 (the reference, red)</th>
</tr>
<tr>
  <th>Unregistered</th>
  <td>
    \cgalFigureBegin{Point_set_processing_3figRegistrationUnregistered_hippo2_view1, registration_view1_hippo2_unregistered.png}
    \cgalFigureEnd
  </td>
  <td>
    \cgalFigureBegin{Point_set_processing_3figRegistrationUnregistered_hippo1_hippo2_view1, registration_view1_hippo1_hippo2_unregistered.png}
    \cgalFigureEnd
  </td>
</tr>
<tr>
  <th>
    Registered
    using
    %OpenGR
  </th>
  <td>
    \cgalFigureBegin{Point_set_processing_3figRegistrationOpenGR_hippo2_view1, registration_view1_hippo2_opengr.png}
    \cgalFigureEnd
  </td>
  <td>
    \cgalFigureBegin{Point_set_processing_3figRegistrationOpenGR_hippo1_hippo2_view1, registration_view1_hippo1_hippo2_opengr.png}
    \cgalFigureEnd
  </td>
</tr>
<tr>
  <th>
    Registered
    using
    PointMatcher
  </th>
  <td>
    \cgalFigureBegin{Point_set_processing_3figRegistrationPointMatcher_hippo2_view1, registration_view1_hippo2_pointmatcher.png}
    \cgalFigureEnd
  </td>
  <td>
    \cgalFigureBegin{Point_set_processing_3figRegistrationPointMatcher_hippo1_hippo2_view1, registration_view1_hippo1_hippo2_pointmatcher.png}
    \cgalFigureEnd
  </td>
</tr>
<tr>
  <th>
    Registered
    using
    OpenGR+PointMatcher
    Pipeline
  </th>
  <td>
    \cgalFigureBegin{Point_set_processing_3figRegistrationPipeline_hippo2_view1, registration_view1_hippo2_opengr_pointmatcher_pipeline.png}
    \cgalFigureEnd
  </td>
  <td>
    \cgalFigureBegin{Point_set_processing_3figRegistrationPipeline_hippo1_hippo2_view1, registration_view1_hippo1_hippo2_opengr_pointmatcher_pipeline.png}
    \cgalFigureEnd
  </td>
</tr>
</table>
\cgalFigureCaptionBegin{Point_set_processing_3tableRegistrationRegistration_visualization_table}
Visualization of registered hippo scans with different registration methods.
Two scans are used: red as the reference, green as the one for which the transformation
is computed and applied. To obtain the results, the example code given in
\ref Point_set_processing_3Examples_registration_OpenGR ,
\ref Point_set_processing_3Examples_registration_PointMatcher ,
\ref Point_set_processing_3Examples_registration_OpenGR_PointMatcher_Pipeline
were applied, respectively. The parameters of the algorithms used to obtain those
results are not optimized for the shown scans; therefore, better parameter choice
might result in better results in terms of registration accuracy for each algorithm
individually.
\cgalFigureCaptionEnd


\section Point_set_processing_3Clustering Clustering

If an input point set represents several objects which are spatially
separated, a clustering algorithm can be applied to identify connected
components on a nearest neighbor graph built using a query sphere of
fixed radius centered on each point.

The clustering is stored in a cluster map which associates each input
point with the index of the cluster it belongs to: users can then use
this map however they find it relevant to their use case, for example
segmenting the input point set into one point set per
cluster. \cgalFigureRef{Point_set_processing_3figclustering} shows
different clustering outputs.

\cgalFigureBegin{Point_set_processing_3figclustering,clustering.png}
Point Set Clustering outputs (one color per cluster). Top: input point
set and clustering using a neighbor radius of 1.5 (147 clusters
extracted). Bottom: clustering with neighbor radius 3.0 (37 clusters
extracted), and with neighbor radius 6.0 (5 clusters extracted).
\cgalFigureEnd


\subsection Point_set_processing_3Example_clustering Example

In the following example, clusters (and adjacencies between them) are
computed and stored as colors in a PLY file:

\cgalExample{Point_set_processing_3/clustering_example.cpp}

\section Point_set_processing_3OutlierRemoval Outlier Removal

Function `remove_outliers()` deletes a user-specified fraction of
outliers from an input point set. More specifically, it partitions the
input points with respect to the average squared distances to their
nearest neighbors and deletes the points with largest value, either
partitioning with a threshold or removing a fixed percentage. The
user can either specify a fixed number of nearest neighbors or a fixed
spherical neighborhood radius.

\subsection Point_set_processing_3Example_outlier_removal Example

The following example reads a point set and removes 5% of the
points. It uses the `Identity_property_map<Point_3>` property
map (optional as it is the default position property map of all
functions in this component.)
\cgalExample{Point_set_processing_3/remove_outliers_example.cpp}

\section Point_set_processing_3Simplification Simplification


Five simplification functions are devised to reduce an input point set.

Function `random_simplify_point_set()` randomly deletes a
user-specified fraction of points from the input point set. This
algorithm is the fastest.

Function `grid_simplify_point_set()` considers a regular grid covering
the bounding box of the input point set, and clusters all points
sharing the same cell of the grid by picking as representative one
arbitrarily chosen point: representatives may only be retained in cells
that have more than a user-defined minimum number of points in order
to also filter out low density areas and outliers. This algorithm is
still fast, although slower than `random_simplify_point_set()`.

Function `hierarchy_simplify_point_set()` provides an adaptive
simplification of the point set through local clusters
\cgalCite{cgal:pgk-esops-02}. The size of the clusters is either
directly selected by the user or it automatically adapts to the local
variation of the point set.

Function `wlop_simplify_and_regularize_point_set()` not only simplifies,
but also regularizes downsampled points. This is an implementation of
the Weighted Locally Optimal Projection (WLOP) algorithm \cgalCite{wlop-2009}.

Function `poisson_eliminate()` is a greedy down sampling method that generates
a subset of the input points with Poisson disk property. This is an implementation of the
<em>Sample Elimination for Generating Poisson Disk Sample Sets</em> method \cgalCite{cgal:y-sefpdss}.


\subsection Point_set_processing_3Example_grid_simplification Grid Simplification Example

The following example reads a point set and simplifies it by
clustering. To filter out outliers, at least 3 points must lie in a
cell so that a point from this cell is kept.
\cgalExample{Point_set_processing_3/grid_simplification_example.cpp}

\cgalFigureBegin{Point_set_processing_3figgrid_simplification,grid_simplification.jpg}
Point set simplification through grid-based clustering. Removed points are depicted in red. Notice how low-density areas (in green) are not simplified.
\cgalFigureEnd

\subsection Point_set_processing_3Example_hierarchy_simplication Hierarchy Simplification Example
The following example reads a point set and produces a set of clusters.

\cgalExample{Point_set_processing_3/hierarchy_simplification_example.cpp}

\subsubsection Point_set_processing_3Hierarchy_simplification_parameter_size Parameter: size
The hierarchy simplification algorithm recursively split the point set
in two until each cluster's size is less than the parameter `size`.

\cgalFigureBegin{Point_set_processing_3figHierarchy_simplification_size, hierarchical_clustering_size.jpg}
Input point set and hierarchy simplification with different `size`
parameter: \f$10\f$, \f$100\f$ and \f$1000\f$. In the 3 cases,
`var_max`\f$=1/3\f$.  \cgalFigureEnd


\subsubsection Point_set_processing_3Hierarchy_simplification_parameter_var_max Parameter: var_max
In addition to the size parameter, a variation parameter allows to
increase simplification in monotonous regions. For each cluster, a
surface variation measure is computed using the sorted eigenvalues of
the covariance matrix: \f[ \sigma(p) = \frac{\lambda_0}{\lambda_0 +
    \lambda_1 + \lambda_2}. \f]

This function goes from \f$0\f$ if the cluster is coplanar to
\f$1/3\f$ if it is fully isotropic. If a cluster's variation is above
`var_max`, it is split. If `var_max` is equal to \f$1/3\f$, this
parameter has no effect and the clustering is regular on the whole
point set.

\cgalFigureBegin{Point_set_processing_3figHierarchical_clustering_var_max, hierarchical_clustering_var_max.jpg}
Input point set and hierarchy simplification with different `var_max`
parameter: \f$0.00001\f$, \f$0.001\f$ and \f$0.1\f$. In the 3 cases,
`size`\f$=1000\f$.  \cgalFigureEnd


\subsection Point_set_processing_3Example_wlop WLOP Simplification Example
The following example reads a point set, simplifies and regularizes it by WLOP.

\cgalExample{Point_set_processing_3/wlop_simplify_and_regularize_point_set_example.cpp}

\cgalFigureBegin{Point_set_processing_3figsimplification_comparison, simplification_comparison.jpg}
Comparison for three simplification methods: Left: Random simplification result. Middle: Grid simplification result. Right: WLOP simplification result.
\cgalFigureEnd

\subsubsection Point_set_processing_3WLOP_Parameter Parameter: require_uniform_sampling
Computing density weights for each point is an optional preprocessing. For example, as shown in the following figure, when require_uniform_sampling is set to false, WLOP preserves the intrinsic non-uniform sampling of the original points; if require_uniform_sampling is set to true, WLOP is resilient to non-uniform sampling and generates sample points with more uniform distribution, at the expense of computational time.


\cgalFigureBegin{Point_set_processing_3figWLOP_parameter_density, WLOP_parameter_density.jpg}
Comparison between with and without density: Left: input. Middle: `require_uniform_sampling = false`. Right: `require_uniform_sampling=true`.
\cgalFigureEnd

\subsubsection Point_set_processing_3WLOP_parameter_neighborhood_size Parameter: neighbor_radius
Usually, the neighborhood of sample points should include at least two rings of neighboring sample points. Using a small neighborhood size may not be able to generate regularized result, while using big neighborhood size will make the sample points shrink into the interior of the local surface (under-fitting). The function will use a neighborhood size estimation if this parameter value is set to default or smaller that zero.

\cgalFigureBegin{Point_set_processing_3figWLOP_parameter_neighborhood_size, WLOP_parameter_neighborhood_size.jpg}
Comparison between different sizes of neighbor radius.
\cgalFigureEnd

\subsubsection Point_set_processing_3WLOP_parallel_performance Parallel Performance
A parallel version of WLOP is provided and requires the executable to be linked against the
<a href="https://github.com/oneapi-src/oneTBB">Intel TBB library</a>.
To control the number of threads used, the user may use the tbb::task_scheduler_init class.
See the <a href="https://software.intel.com/content/www/us/en/develop/documentation/onetbb-documentation/top.html">TBB documentation</a>
for more details. We provide below a speed-up chart generated using the parallel version of the WLOP algorithm. The machine used is a PC running Windows 7 64-bits with a 4-core i7-4700HQ\@2.40GHz CPU with 8GB of RAM.

\cgalFigureBegin{Point_set_processing_3figWLOP_parallel_performance, parallel_WLOP_performance.jpg}
Parallel WLOP speed-up, compared to the sequential version of the algorithm.
\cgalFigureEnd

\subsection Point_set_processing_3PoissonElimination Poisson Sample Elimination
The Poisson sample elimination is a greedy downsampling method that calculates a weight for each input point based on the density of its local neighborhood. Subsequently, the point with the highest weight is removed and the weights of the remaining points around it are updated until the target size is reached. A custom function to calculate the weight of a point can be provided.

The Poisson sample elimination has the following parameters:
- *dimension*: The dimension of the sampling domain of the point cloud, e.g., 2 if the point cloud is sampled from a surface, while the ambient dimension is typically 3. The default value is 2.
- *weight_function*: A custom function can be provided to calculate the weight between two points. The type of the functor is as follows:
\code{.cpp}
double(*func)(const Point &p, const Point &n, double squared_distance, double r_max)
\endcode
The default weight is \f$\left(1 - \frac{d_{p,n}}{2r_{max}}\right)^8\f$ with \f$d_{p,n}\f$ being the distance between the point p and its neighbor n.
- \f$r_{max}\f$: The \f$r_{max}\f$ parameter specifies the radius of the neighborhood, i.e., the neighboring points that are used to calculate the weight of a point. \f$r_{max}\f$ has to be provided if a custom *weight_function* is used. Only points within a distance of \f$r_{max}\f$ are used to calculate the weight of a point. A large value can thus cause a large running time. The default is calculated based in the bounding volume \f$V\f$ of the input points, the *dimension* parameter and the number of input points \f$N\f$:

\f$\mathrm{dimension} = 2:\qquad\f$ \f$r_{max} = \sqrt{\frac{V}{2\sqrt{3}N}}\f$

\f$\mathrm{dimension} = 3:\qquad\f$ \f$r_{max} = \sqrt{\frac{V}{4\sqrt{2}N}}\f$

- *progressive*: The output points of the function can be reordered to be progressive. A progressive ordering will increase the running time by a factor of at most 2 as the function is internally applied several times on increasingly smaller subsets. The default value is false.

\cgalFigureAnchor{Point_set_processing_3figPoisson_elimination}
<center>
<img src="poisson_elimination.png" style="max-width:80%;"/>
</center>
\cgalFigureCaptionBegin{Point_set_processing_3figPoisson_elimination}
Poisson elimination on point cloud randomly sampled from a mesh with 20k points showing results with \f$\frac{1}{2}\f$, \f$\frac{1}{4}\f$ and \f$\frac{1}{8}\f$ of the input size.
\cgalFigureCaptionEnd

\subsubsection Point_set_processing_3Example_poisson_elimination Poisson Sample Elimination Example

The following example reads a point cloud, applies Poisson elimination to reduce the point cloud to \f$\frac{1}{5}\f$ of its size and saves it into a file.

\cgalExample{Point_set_processing_3/poisson_eliminate_example.cpp}

\subsubsection Point_set_processing_3Example_poisson_elimination_on_mesh Poisson Sample Elimination from Mesh Example

The following example first samples a point cloud from a surface mesh and then uses Poisson elimination to provide an evenly sampled point cloud.

\cgalExample{Point_set_processing_3/poisson_eliminate_from_mesh_example.cpp}

\section Point_set_processing_3Smoothing Smoothing

Two smoothing functions are devised to smooth an input point set.

Function `jet_smooth_point_set()` smooths the input point set by
projecting each point onto a smooth parametric surface patch
(so-called jet surface) fitted over its nearest neighbors.

Function `bilateral_smooth_point_set()` smooths the input point set by
iteratively projecting each point onto the implicit surface patch fitted over its nearest neighbors.
Bilateral projection preserves sharp features according to the normal (gradient) information.
Normals are thus required as input. For more details, see section 4 of \cgalCite{ear-2013}.

For both functions, the user can either specify a fixed number of
nearest neighbors or a fixed spherical neighborhood radius.

\subsection Point_set_processing_3Example_jet_smoothing Jet Smoothing Example

The following example generates a set of 9 points close to the `xy`
plane and smooths them using 8 nearest neighbors:
\cgalExample{Point_set_processing_3/jet_smoothing_example.cpp}

\subsection Point_set_processing_3Example_bilateral_smoothing Bilateral Smoothing Example

The following example reads a set of points with normals and smooths them via bilateral smoothing:
\cgalExample{Point_set_processing_3/bilateral_smooth_point_set_example.cpp}

\cgalFigureBegin{Point_set_processing_3figsmoothing_comparison, smoothing_comparison.jpg}
Comparison for two smoothing methods: Left: Input, 250K points, normal-color mapping. Middle: Jet smoothing result, 197 seconds. Right: Bilateral smoothing result, 110 seconds.
\cgalFigureEnd

\subsubsection Point_set_processing_3Bilateral_smoothing_parallel_performance Parallel Performance

A parallel version of bilateral smoothing is provided and requires the executable to be linked against the
<a href="https://github.com/oneapi-src/oneTBB">Intel TBB library</a>.
The number of threads used is controlled through the tbb::task_scheduler_init class.
See the <a href="https://software.intel.com/content/www/us/en/develop/documentation/onetbb-documentation/top.html">TBB documentation</a> for more details.
We provide below a speed-up chart generated using the parallel version of the bilateral smoothing algorithm.
The machine used is a PC running Windows 7 64-bits with a 4-core i7-4700HQ\@2.40GHz CPU with 8GB of RAM.

\cgalFigureBegin{Point_set_processing_3Bilateral_smoothing_parallel_performance, parallel_bilateral_smooth_point_set_performance.jpg}
Parallel bilateral smoothing speed-up, compared to the sequential version of the algorithm.
\cgalFigureEnd

\section Point_set_processing_3NormalEstimation Normal Estimation

Assuming a point set sampled over an inferred surface \b S, two
functions provide an estimate of the normal to \b S at each
point. The result is an unoriented normal vector for each input point.

Function `jet_estimate_normals()` estimates the normal direction
at each point from the input set by fitting a jet surface over its
nearest neighbors. The default jet is a quadric surface. This
algorithm is well suited to point sets scattered over curved surfaces.

Function `pca_estimate_normals()` estimates the normal direction
at each point from the set by linear least squares fitting of a plane
over its nearest neighbors. This algorithm is simpler and
faster than `jet_estimate_normals()`.

Function `vcm_estimate_normals()` estimates the normal direction
at each point from the set by using the Voronoi Covariance Measure
of the point set. This algorithm is more complex and slower than
the previous algorithms. It is based on the
article \cgalCite{cgal:mog-vbcfe-11}.

For these three functions, the user can either specify a fixed number
of nearest neighbors or a fixed spherical neighborhood radius.

\section Point_set_processing_3NormalOrientation Normal Orientation

\subsection Point_set_processing_3Mst_orient_normals Minimum Spanning Tree

Function `mst_orient_normals()` orients the normals of a set of
points with unoriented normals using the method described by Hoppe et
al. in <I>Surface reconstruction from unorganized points</I> \cgalCite{cgal:hddms-srup-92}.
More specifically, this method constructs a
Riemannian graph over the input points (the graph of the
nearest neighbor points) and propagates a seed normal orientation
within a minimum spanning tree computed over this graph. The result is
an oriented normal vector for each input unoriented normal, except for
the normals which cannot be successfully oriented.

\cgalFigureBegin{Point_set_processing_3figmst_orient_normals,mst_orient_normals.jpg}
Normal orientation of a sampled cube surface. Left: unoriented normals. Right: orientation of right face normals is propagated to bottom face.
\cgalFigureEnd

\subsubsection Point_set_processing_3Example_normals Example

The following example reads a point set from a file, estimates the
normals through PCA (either over the 18 nearest neighbors or using a
spherical neighborhood radius of twice the average spacing) and
orients the normals:
\cgalExample{Point_set_processing_3/normals_example.cpp}

\subsection Point_set_processing_3Scanline_orient_normals Scanline

The minimum spanning tree results can give suboptimal results on point
clouds with many sharp features and occlusions, which typically
happens on airborne acquired urban datasets.

`scanline_orient_normals()` is an alternative method specialized for
point sets which are ordered in scanline aligned on the XY-plane. It
can take advantage of LAS properties provided by some LIDAR scanner
and is the best choice of normal orientation when dealing with 2.5D
urban scenes.

\cgalFigureBegin{Point_set_processing_3figmst_scanline_orient_normals,scanline_orient_normals.png}
Normal orientation of a LIDAR scanline. The point cloud is a typical
airborne LIDAR input, sampling a building without normal information
and with many occlusions (especially on vertical walls).
\cgalFigureEnd

\subsubsection Point_set_processing_3Example_scanline_normals Example

The following example reads a point set from a LAS file, estimates the
normals through Jet Fitting and outputs in PLY format the orientation
results of all the variants of `scanline_orient_normals()`:

\cgalExample{Point_set_processing_3/orient_scanlines_example.cpp}

\section Point_set_processing_3Upsampling Upsampling

The function `edge_aware_upsample_point_set()` generates a denser point set from an input point set. This has applications in point-based rendering, hole filling, and sparse surface reconstruction.
The algorithm can progressively upsample the point set while approaching the edge singularities. See \cgalCite{ear-2013} for more details.

\subsection Point_set_processing_3Example_upsampling Example

The following example reads a point set from a file, upsamples it to get a denser result.

\cgalExample{Point_set_processing_3/edge_aware_upsample_point_set_example.cpp}

\subsubsection Point_set_processing_3Upsample_Parameter1 Parameter: edge_sensitivity
This parameter controls where the new points are inserted. Larger values of edge-sensitivity give higher priority to inserting points along the sharp features.
For example, as shown in the following figure, high value is preferable when one wants to insert more points on sharp features, where the local gradient is high, e.g., darts, cusps, creases and corners. In contrast, points are evenly inserted when edge_sensitivity is set to 0. The range of possible value is [0, 1].


\cgalFigureBegin{Point_set_processing_3figUpsample_edge_sensitivity, upsample_edge_sensitivity.jpg}
Upsampling for different edge-sensitivity parameter values. The input containing 850 points is upsampled to 1,500 points in all cases depicted.
\cgalFigureEnd

\subsubsection Point_set_processing_3Upsample_Parameter2 Parameter: sharpness_angle
This parameter controls the preservation of sharp features.

\cgalFigureBegin{Point_set_processing_3figUpsample_sharpness_angle, upsample_sharpness_angle.jpg}
Upsampling for different sharpness_angle parameter values. The input containing 850 points is upsampled to 425K points in all cases depicted.
\cgalFigureEnd

\subsubsection Point_set_processing_3upsample_neighborhood_size Parameter: neighbor_radius
Usually, the neighborhood of sample points should include at least one ring of neighboring sample points. Using small neighborhood size may not be able to insert new points. Using big neighborhood size can fill small holes, but points inserted on the edges could be irregular. The function will use a neighborhood size estimation if this parameter value is set to default or smaller than zero.

\cgalFigureBegin{Point_set_processing_3figupsample_neighborhood_size, upsample_neighborhood_size.jpg}
Comparison between different sizes of neighbor radius.
\cgalFigureEnd

\section Point_set_processing_3FeaturesEstimation Feature Edges Estimation

Function `vcm_is_on_feature_edge()` indicates if a points belong to a feature edges of the
point set using its Voronoi Covariance Measure.
It is based on the article \cgalCite{cgal:mog-vbcfe-11}.

It first computes the VCM of the points set using `compute_vcm()`. Then, it estimates
which points belong to a sharp edge by testing if a ratio of eigenvalues
is greater than a given threshold.

\subsection Point_set_processing_3Example_sharp_edges Example

The following example reads a point set from a file, estimates the
points that are on sharp edges:
\cgalExample{Point_set_processing_3/edges_example.cpp}


\section Point_set_processing_3Structuring Structuring

The function `structure_point_set()` generates a structured version of
the input point set assigned to a set of planes. Such an input can be
produced by a shape detection algorithm (see its \ref PkgShapeDetectionRef).
Point set structuring is based on the article \cgalCite{cgal:la-srpss-13}.

- __Planes__: inliers of each detected plane are replaced by sets of
noise-free points sampled at the vertices of a regular grid: this is
achieved by filling an occupancy grid aligned on the principal
components of the inlier sets with a spacing lower than \f$\sqrt{2}\f$
times the user-defined tolerance.

- __Creases__: adjacencies between 2 planes are detected and regularly
resampled on an occupancy array along the edge with a spacing equal to
twice the user-defined tolerance.

- __Corners__: 3-cycles are detected from the primitive adjacency
graph and sampled using the exact intersection point of the 3 planes
(provided it exists and remains in the given tolerance). These corners
are also locally clustered to former corners of degree higher than 3.

This algorithm is well suited to point sets sampled on surfaces with
planar sections and sharp edges.

\cgalFigureBegin{Point_set_processing_3figstructuring,structuring.png}
Point set structuring. Left: input raw point set. Right: structured point set.
\cgalFigureEnd

Structure information of points can be used to perform feature
preserving reconstruction (see
\ref AFSR_Example_sharp_features "Advancing Front Surface Reconstruction"
for example). More specifically, the class storing a point set with
structure provides the user with a method
`Point_set_with_structure::facet_coherence()` that estimates if a
triplet of points form a coherent facet.

\cgalFigureBegin{Point_set_processing_3figstructuring_coherence, structuring_coherence.png}
(a) Input point set (and structured output); (b) output with many
incoherent facets; (c) output with all facets coherent. i, j and k
each corresponds to a primitive index.
\cgalFigureEnd



\subsection Point_set_processing_3Example_9 Example

The following example applies shape detection followed by structuring to a
point set:
\cgalExample{Point_set_processing_3/structuring_example.cpp}


\section Point_set_processing_3Callbacks Callbacks

Several functions of this package provide a callback mechanism that enables the user to track the progress of the algorithms and to interrupt them if needed. A callback, in this package, is an instance of `std::function<bool(double)>` that takes the advancement as a parameter (between 0. when the algorithm begins to 1. when the algorithm is completed) and that returns `true` if the algorithm should carry on, `false` otherwise. It is passed as a named parameter with an empty function as default.

Algorithms that support this mechanism are detailed in the @ref PkgPointSetProcessing3Ref, along with the effect that an early interruption has on the output.

\subsection Point_set_processing_3Example_callbacks Example

The following example defines a callback that displays the name of the current algorithm along with the progress (as a percentage) updated every \f$1/10th\f$ of a second. While the algorithm is running, the console output will typically look like this:

\code{.sh}
Computing average spacing: 100%
Grid simplification: 100%
Jet smoothing: 54%
\endcode

Thanks to the carriage return character `\r`, the lines are overwritten and the user sees the percentage increasing on each line.

\cgalExample{Point_set_processing_3/callback_example.cpp}


\section Point_set_processing_3ImplementationHistory Implementation History

Pierre Alliez and Laurent Saboret contributed the initial component. Nader Salman contributed the grid simplification.
Started from GSoC'2013, three new algorithms were implemented by Shihao Wu and Clément Jamin: WLOP, bilateral smoothing and upsampling.
Started from GSoC'2014, Jocelyn Meyron with the help of Quentin Mérigot introduced the computation of the Voronoi covariance measure of a point set,
as well as the normal and feature edge estimation functions based on it.
Florent Lafarge with the help of Simon Giraudot contributed the point set structuring algorithm.
Started from GSoC'2019, Necip Fazil Yildiran with the help of Nicolas Mellado and Simon Giraudot introduced the wrappers for OpenGR and PointMatcher
libraries that perform registration on two point sets.
Poisson sample elimination is a reimplementation by Sven Oesau based on \cgalCite{cgal:y-sefpdss}. The original source code <a href="https://github.com/cemyuksel/cyCodeBase/">cyCodeBase</a> was used as a reference.

*/
} /* namespace CGAL */
