﻿namespace CGAL {
/*!

\mainpage User Manual 
\anchor Chapter_Point_Set_Processing
\anchor chappoint_set_processing_3

\cgalAutoToc

\authors Pierre Alliez, Clément Jamin, Quentin Mérigot, Jocelyn Meyron, Laurent Saboret, Nader Salman, Shihao Wu

\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 alignment to produce a set of
points or points with normals (alignment is not covered in \cgal);
-# 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_3PropertyMaps Property Maps

The algorithms of this component take as input parameters iterator
ranges of 3D points, or of 3D points with normals. 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 chapterProperty_map
"CGAL and Boost Property Maps"
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}


\section Point_set_processing_3InputOutput Input/Output

\subsection Point_set_processing_3Streams Streams

We provide functions to read and write sets of points or sets of
points with normals from the following ASCII file formats: XYZ (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), OFF
(%Object File Format) \cgalCite{cgal:p-gmgv16-96} and PLY (Polygon
File Format).

- `read_xyz_points()` 
- `read_off_points()`
- `read_ply_points()` 
- `write_off_points()` 
- `write_xyz_points()`
- `write_ply_points()`

Note that `read_ply_points()` also accepts binary PLY format in
addition of ASCII.

\subsection Point_set_processing_3Example 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}

\section Point_set_processing_3Analysis Analysis

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_1 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_3OutlierRemoval Outlier Removal

Function `remove_outliers()` deletes a user-specified fraction
of outliers from an input point set. More specifically, it sorts the
input points in increasing order of average squared distances to their
`k` nearest neighbors and deletes the points with largest value.

\subsection Point_set_processing_3Example_2 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


Four 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 fast.

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 representant
one arbitrarily chosen point. This algorithm is 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}.


\subsection Point_set_processing_3Example_3 Grid Simplification Example

The following example reads a point set and simplifies it by clustering.
\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_9 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 monotoneous 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 splitted. 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_4 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="http://www.threadingbuildingblocks.org">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="http://www.threadingbuildingblocks.org/documentation">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


\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 `k` 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 `k` 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}.

\subsection Point_set_processing_3Example_5 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_6 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="http://www.threadingbuildingblocks.org">Intel TBB library</a>.
The number of threads used is controlled through the tbb::task_scheduler_init class.
See the <a href="http://www.threadingbuildingblocks.org/documentation">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 `k`
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 `k` 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}.

\section Point_set_processing_3NormalOrientation Normal Orientation

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 `k`
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

\subsection Point_set_processing_3Example_7 Example

The following example reads a point set from a file, estimates the
normals through PCA over the 6 nearest neighbors and orients the
normals:
\cgalExample{Point_set_processing_3/normals_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_8 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 neigbhorhood size estimation if this parameter value is set to default or smaller that 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_10 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_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 covarience measure of a point set,
as well as the normal and feature edge estimation functions based on it.

*/ 
} /* namespace CGAL */

