First updates based on the second review round.

This commit is contained in:
Thijs van Lankveld 2014-09-02 17:53:07 +02:00
parent d7d5c1afa3
commit 6eb9d75dc9
5 changed files with 150 additions and 91 deletions

View File

@ -17,7 +17,7 @@
// Author(s): Thijs van Lankveld
/// projects a point orthogonally onto a weighted least-squares planar approximation of a point set.
/// A concept for projecting a point orthogonally onto a weighted least-squares planar approximation of a point set.
/** \ingroup PkgScaleSpaceReconstruction3Concepts
* \cgalConcept
*

View File

@ -24,11 +24,11 @@ The problem of surface reconstruction from a point sample is ill-defined. Becaus
Given real-world data sets we also have to contend with noise and outliers, small errors in the point location and points that do not sample the surface respectively. These are generally caused by faults in the measurement procedure. Unless we actually know the surface sampled, we cannot determine whether a distinctive point is an outlier, is caused by noise, or samples a detail of the surface.
To overcome these obstacles, we use a scale-space \cgalCite{cgal:dmsl-ssmrp-11}, which models geometry at different scales. For this purpose, a \em scale is an abstraction level of the geometry. At a smaller, finer scale the geometry contains more details. Conversely at a larger, coarser scale the geometry contains less details. The \em scale-space is a model of the geometry at a dynamic scale. We refer to changing to a coarser scale as <em>advancing the scale-space</em>. In case of a point set, less detailed geometry means the points are closer to a smooth surface or this surface is closer to planar.
To overcome these obstacles, we use a scale-space \cgalCite{cgal:dmsl-ssmrp-11}, which models geometry at different scales. The geometry we model specifically are points and surfaces. For our purpose, a \em scale is an abstraction level of the geometry. At a smaller, finer scale the geometry contains more details. Conversely at a larger, coarser scale the geometry contains less details. The \em scale-space is a model of the geometry at a dynamic scale. We refer to changing to a coarser scale as <em>advancing the scale-space</em>. In case of a point set, less detailed geometry means the points are closer to a smooth surface or this surface is closer to planar.
The scale-space surface reconstruction method is twofold. Firstly, a scale-space of the point set is constructed. Then, a triangulated surface mesh of the points in the scale-space is computed. Neighboring triangles in the mesh have consistent orientation, as expressed using the '<em>right-hand rule</em>' on the ordered vertices of the triangle.
The points maintain their original order in the scale-space. This means it is straightforward to revert the scale-space on the triangulated surface mesh. In essence, the method can reconstruct a smooted surface or a surface interpolating the original points. The only change is whether to apply the index triples to the scale-space or to the original point set.
The points maintain their original order in the scale-space. This means it is straightforward to revert the scale-space on the triangulated surface mesh. In essence, the method can reconstruct a smoothed surface or a surface interpolating the original points. The only change is whether to apply the index triples to the scale-space or to the original point set.
When applied to the scale-space, the surface mesh is non-self-intersecting. The interior of the triangles cannot pairwise intersect in a line segment. However, the surface does not need to be manifold. An edge may be incident to more than two triangles and triangles may overlap exactly if the regions on both sides of the triangle are not part of the object. Note that we count overlapping triangles with opposite orientations as separate triangles. In many cases where the points sample the surface of an object, the computed surface will contain both an '<em>outward-facing</em>' and a similar '<em>inward-facing</em>' surface, with a thin volume between them.
@ -54,7 +54,7 @@ The method provides access to intermediate results and the user can adjust these
\subsection ScaleSpaceReconstruction3secParam Parameter Settings
The scale-space surface reconstruction method has two main global parameters: the radius of the neighborhood ball and the number of scale-space advancement iterations. If no appropriate neighborhood radius is known, this can be estimated using two more parameters: the mean number of neighbors and the number of samples. We have empirically determined values for each of these parameters that work well on a broad spectrum of data sets. However, we advise to carefully fine-tune these parameters for each new data sets.
The scale-space surface reconstruction method has two main global parameters: the radius of the neighborhood ball and the number of scale-space advancement iterations. If no appropriate neighborhood radius is known, this can be estimated using two more parameters: the mean number of neighbors and the number of samples. We have empirically determined values for each of these parameters that work well on a broad spectrum of data sets. However, we advise to carefully fine-tune these parameters for each new data set.
The scale-space reconstruction operates locally. Points within a local neighborhood influence each other when advancing the scale-space. Similarly, points near each other in space are more likely to be near each other on the reconstructed surface. Therefore, it is important to have a good indication of which points are near each other. This proximity is expressed in the neighborhood ball radius parameter.
@ -75,7 +75,7 @@ The main class `Scale_space_surface_reconstruction_3` contains all the functiona
The neighborhood size is estimated using Orthogonal_k_neighbor_search. The point set is generally stored in a Orthogonal_k_neighbor_search::Tree. When the neighborhood size is estimated, this tree is searched for nearest neighbors.
The scale-space is computed using a weighted PCA procedure. For this procedure, we use the efficient \ref thirdpartyEigen libraries. Because this procedure is performed locally per point, it is performed with parallel computing when openMP is enabled.
The scale-space is computed using a weighted PCA procedure. For this procedure, we use the efficient \ref thirdpartyEigen libraries. Because this procedure is performed locally per point, it is performed with parallel computing when Intel TBB is linked.
The mesh reconstruction of the scale-space is performed by filtering an Alpha_shape_3 or Fixed_alpha_shape_3. Which of these is used is captured in the Fixed_scale template parameter of Scale_space_surface_reconstruction_3.
@ -178,7 +178,7 @@ Settings used when running the scale-space method on several data sets. Data set
\cgalFigureRef{chapterScaleSpaceReconstruction3figBenchmarks} shows the number of triangles of the surfaces constructed and the running time for doing so. Half of the data sets are synthetic, the others are constructed by image-based dense reconstruction. The data sets are ordered by size, the synthetic sets mainly making up the smaller ones.
The times were measured on a 64-bit Windows 7 system with 8 2.5GHz Intel processors and 16GB RAM. The scale-space constructions employ parallel computing using openMP. The smaller data sets use roughly 0.1GB of memory, but the largest data sets have a peak usage of 10.5GB during the meshing step. For this benchmark we used the Exact_predicates_inexact_constructions_kernel kernel, Fixed_scale enabled, and Shells disabled.14
The times were measured on a 64-bit Windows 7 system with 8 2.5GHz Intel processors and 16GB RAM. The scale-space constructions employ parallel computing using Intel TBB. The smaller data sets use roughly 0.1GB of memory, but the largest data sets have a peak usage of 10.5GB during the meshing step. For this benchmark we used the Exact_predicates_inexact_constructions_kernel kernel, Fixed_scale enabled, and Shells disabled.14
\cgalFigureAnchor{chapterScaleSpaceReconstruction3figBenchmarks}
<center>
@ -220,7 +220,7 @@ This first example shows how to read a point set from a file, reconstruct the su
\cgalExample{Scale_space_reconstruction_3/scale_space.cpp}
The next example shows how to perform the reconstruction step-by-step and how to change the parameters between steps.
The next example shows how to perform the reconstruction step-by-step and how to change the parameters between steps. Each parameter can be changed between steps by calling the specific *set_* method. An example of this is given by the call to <code>set_neighborhood_squared_radius( 0.05 )</code>. Alternatively, they can be adjusted before performing a method by calling the method with parameters. An example is given by the call to <code>estimate_neighborhood_radius( 10, 100 )</code>.
\cgalExample{Scale_space_reconstruction_3/scale_space_incremental.cpp}

View File

@ -28,7 +28,8 @@ int main(void) {
std::cout << "done: " << points.size() << " points." << std::endl;
// Construct the reconstruction to estimate the neighborhood radius.
Reconstruction reconstruct( 10, 100 );
// The -1 indicates the neighborhood radius is not yet set.
Reconstruction reconstruct( -1 );
// Add the points.
reconstruct.add_points( points.begin(), points.end() );
@ -38,7 +39,7 @@ int main(void) {
reconstruct.advance_scale_space( 2 );
// Re-estimate the neighborhood radius.
reconstruct.estimate_neighborhood_radius();
reconstruct.estimate_neighborhood_radius( 10, 100 );
// Advance the scale-space further.
reconstruct.advance_scale_space( 2 );

View File

@ -36,6 +36,10 @@
#include <CGAL/Scale_space_reconstruction_3/internal/check3264.h>
#include <CGAL/Scale_space_reconstruction_3/Shape_construction_3.h>
#include <CGAL/Scale_space_reconstruction_3/Weighted_PCA_projection_3.h>
#include <boost/mpl/and.hpp>
namespace CGAL {
/// computes a triangulated surface mesh interpolating a point set.
@ -51,9 +55,9 @@ namespace CGAL {
*
* The points maintain their original order in the scale-space. This means it
* is straightforward to revert the scale-space on the triangulated surface
* mesh. In essence, the method can reconstruct a smooted surface or a surface
* interpolating the original points. The only change is whether to apply the
* index triples to the scale-space or to the original point set.
* mesh. In essence, the method can reconstruct a smoothed surface or a
* surface interpolating the original points. The only change is whether to
* apply the index triples to the scale-space or to the original point set.
*
* When applied to the scale-space, the surface mesh is non-self-intersecting.
* The interior of the triangles cannot pairwise intersect in a line segment.
@ -101,7 +105,6 @@ namespace CGAL {
* smaller than the neighborhood size, the scale is coarse enough for mesh
* reconstruction after a few iterations of advancing the scale-space.
*
* For the PCA procedure, we use a `Weighted_PCA_projection_3<GeomTraits>`.
* The mesh reconstruction of the scale-space is performed by filtering a 3D
* \f$ \alpha \f$-shape. The result is returned as a collection of triples on
* the indices of the points of the surface triangles. Recall that this
@ -152,22 +155,22 @@ namespace CGAL {
* surface where connected facets are locally oriented towards the same side
* of the surface.
*
* \tparam GeomTraits is the geometric traits class. It must be a model of
* `DelaunayTriangulationTraits_3`. Generally,
* `Exact_predicates_inexact_constructions_kernel` is preferred.
* \tparam DelaunayTriangulationTraits_3 is the geometric traits class.
* Generally, `Exact_predicates_inexact_constructions_kernel` is preferred.
* \tparam FixedScale determines whether the shape is constructed at a fixed
* scale. It must be a `Boolean_tag` type. The default value is `Tag_true`.
* \tparam OrderShells determines whether to collect the surface per shell. It must
* be a `Boolean_tag` type. The default value is `Tag_true`.
* \tparam OrderShells determines whether to collect the surface per shell. It
* must be a `Boolean_tag` type. The default value is `Tag_true`.
* \tparam WeightedPCAProjection_3 is the type of weighted PCA to use. The
* default value is `Weighted_PCA_projection_3<DelaunayTriangulationTraits_3>`.
*/
#ifdef DOXYGEN_RUNNING
template < class GeomTraits, class FixedScale, class OrderShells >
template < class DelaunayTriangulationTraits_3, class FixedScale, class OrderShells, class WeightedPCAProjection_3 >
#else
template < class Gt, class FS = Tag_true, class OS = Tag_true, class Ct = Parallel_tag >
template < class Gt, class FS = Tag_true, class OS = Tag_true, class Ct = Parallel_tag, class WPCA = Weighted_PCA_projection_3< Gt > >
#endif
class Scale_space_surface_reconstruction_3 {
public:
typedef Gt GeomTraits;
typedef FS FixedScale;
typedef OS OrderShells;
typedef Ct Concurrency_tag;
@ -208,15 +211,20 @@ private:
public:
/// \name Types
/// \{
typedef typename Gt::FT FT; ///< defines the number field type.
typedef typename Gt::Point_3 Point; ///< defines the point type.
typedef typename Gt::Triangle_3 Triangle; ///< defines the triangle type.
#ifdef DOXYGEN_RUNNING
typedef typename DelaunayTriangulationTraits_3::FT FT; ///< defines the number field type.
typedef typename DelaunayTriangulationTraits_3::Point_3 Point; ///< defines the point type.
typedef typename DelaunayTriangulationTraits_3::Triangle_3 Triangle; ///< defines the triangle type.
typedef unspecified_type Point_iterator; ///< defines an iterator over the points.
typedef const unspecified_type Const_point_iterator; ///< defines a constant iterator over the points.
#else // DOXYGEN_RUNNING
typedef typename Gt::FT FT;
typedef typename Gt::Point_3 Point;
typedef typename Gt::Triangle_3 Triangle;
typedef typename Search_tree::iterator Point_iterator;
typedef typename Search_tree::const_iterator Const_point_iterator;
#endif // DOXYGEN_RUNNING
@ -381,7 +389,14 @@ public:
* \sa `reconstruct_surface(InputIterator begin, InputIterator end, unsigned int iterations)`.
*/
template < class InputIterator >
#ifdef DOXYGEN_RUNNING
void add_points( InputIterator begin, InputIterator end ) {
#else // DOXYGEN_RUNNING
void add_points( InputIterator begin, InputIterator end,
typename boost::enable_if<
boost::is_convertible< typename std::iterator_traits<InputIterator>::value_type,
Point > >::type* = NULL ) {
#endif // DOXYGEN_RUNNING
_tree.insert( begin, end );
}
@ -622,7 +637,14 @@ public:
* \sa `reconstruct_surface(InputIterator begin, InputIterator end, unsigned int iterations)`.
*/
template < class InputIterator >
#ifdef DOXYGEN_RUNNING
FT estimate_neighborhood_radius( InputIterator begin, InputIterator end ) {
#else // DOXYGEN_RUNNING
FT estimate_neighborhood_radius( InputIterator begin, InputIterator end,
typename boost::enable_if<
boost::is_convertible< typename std::iterator_traits<InputIterator>::value_type,
Point > >::type* = NULL ) {
#endif // DOXYGEN_RUNNING
return estimate_neighborhood_radius( begin, end, mean_number_of_neighbors(), neighborhood_sample_size() );
}
@ -654,7 +676,14 @@ public:
* \sa `estimate_neighborhood_radius(unsigned int neighbors, unsigned int samples)`.
*/
template < class InputIterator >
#ifdef DOXYGEN_RUNNING
FT estimate_neighborhood_radius( InputIterator begin, InputIterator end, unsigned int neighbors, unsigned int samples );
#else // DOXYGEN_RUNNING
FT estimate_neighborhood_radius( InputIterator begin, InputIterator end, unsigned int neighbors, unsigned int samples,
typename boost::enable_if<
boost::is_convertible< typename std::iterator_traits<InputIterator>::value_type,
Point > >::type* = NULL );
#endif // DOXYGEN_RUNNING
/// \}
@ -710,7 +739,14 @@ public:
* \sa `reconstruct_surface(InputIterator begin, InputIterator end, unsigned int iterations)`.
*/
template < class InputIterator >
#ifdef DOXYGEN_RUNNING
void construct_scale_space( InputIterator begin, InputIterator end, unsigned int iterations = 1 ) {
#else // DOXYGEN_RUNNING
void construct_scale_space( InputIterator begin, InputIterator end, unsigned int iterations = 1,
typename boost::enable_if<
boost::is_convertible< typename std::iterator_traits<InputIterator>::value_type,
Point > >::type* = NULL ) {
#endif // DOXYGEN_RUNNING
clear();
add_points( begin, end );
advance_scale_space( iterations );
@ -779,7 +815,14 @@ private:
* \sa `is_constructed()`.
*/
template < class InputIterator >
#ifdef DOXYGEN_RUNNING
void construct_shape( InputIterator begin, InputIterator end );
#else // DOXYGEN_RUNNING
void construct_shape( InputIterator begin, InputIterator end,
typename boost::enable_if<
boost::is_convertible< typename std::iterator_traits<InputIterator>::value_type,
Point > >::type* = NULL );
#endif // DOXYGEN_RUNNING
// collects the surface mesh from the shape.
// If the sahep does not yet exist, it is constructed.
@ -846,7 +889,14 @@ public:
* \sa `construct_scale_space(InputIterator begin, InputIterator end, unsigned int iterations)`.
*/
template < class InputIterator >
#ifdef DOXYGEN_RUNNING
void reconstruct_surface( InputIterator begin, InputIterator end, unsigned int iterations = 0 );
#else // DOXYGEN_RUNNING
void reconstruct_surface( InputIterator begin, InputIterator end, unsigned int iterations = 0,
typename boost::enable_if<
boost::is_convertible< typename std::iterator_traits<InputIterator>::value_type,
Point > >::type* = NULL );
#endif // DOXYGEN_RUNNING
/// \}

View File

@ -29,9 +29,9 @@
namespace CGAL {
template < class Gt, class FS, class OS, class Ct >
template < class Gt, class FS, class OS, class Ct, class WPCA >
class
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::
Finite_point_iterator: public Finite_vertices_iterator {
typedef Finite_vertices_iterator Base;
typedef Finite_point_iterator Self;
@ -44,9 +44,9 @@ public:
}; // class Finite_point_iterator
template < class Gt, class FS, class OS, class Ct >
template < class Gt, class FS, class OS, class Ct, class WPCA >
class
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::
In_surface_tester {
const Shape* _s;
@ -75,9 +75,9 @@ public:
// Compute the number of neighbors of a point that lie within a fixed radius.
template < class Gt, class FS, class OS, class Ct >
template < class Gt, class FS, class OS, class Ct, class WPCA >
class
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::
ComputeNN {
public:
typedef std::vector< Point > Pointset;
@ -114,15 +114,14 @@ public:
// Advance a point to a coarser scale.
template < class Gt, class FS, class OS, class Ct >
template < class Gt, class FS, class OS, class Ct, class WPCA >
class
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::
AdvanceSS {
public:
typedef std::vector< Point > Pointset;
typedef std::vector< unsigned int > CountVec;
typedef std::map< Point, size_t > PIMap;
typedef Weighted_PCA_projection_3< Gt > WPCAP;
private:
const Search_tree& _tree;
@ -148,7 +147,7 @@ public:
// Collect the vertices within the ball and their weights.
Dynamic_search search( _tree, _pts[i] );
WPCAP pca( _nn[i] );
WPCA pca( _nn[i] );
unsigned int column = 0;
for( typename Dynamic_search::iterator nit = search.begin();
nit != search.end() && column < _nn[i];
@ -168,19 +167,19 @@ public:
}; // class AdvanceSS
template < class Gt, class FS, class OS, class Ct >
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::
template < class Gt, class FS, class OS, class Ct, class WPCA >
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::
Scale_space_surface_reconstruction_3( unsigned int neighbors, unsigned int samples )
: _mean_neighbors(neighbors), _samples(samples), _squared_radius(-1), _shape(0) {}
template < class Gt, class FS, class OS, class Ct >
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::
template < class Gt, class FS, class OS, class Ct, class WPCA >
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::
Scale_space_surface_reconstruction_3( FT sq_radius )
: _mean_neighbors(30), _samples(200), _squared_radius(sq_radius), _shape(0) {}
template < class Gt, class FS, class OS, class Ct >
template < class Gt, class FS, class OS, class Ct, class WPCA >
inline bool
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::
is_handled( Cell_handle c, unsigned int li ) const {
switch( li ) {
case 0: return ( c->info()&1 ) != 0;
@ -191,9 +190,9 @@ is_handled( Cell_handle c, unsigned int li ) const {
return false;
}
template < class Gt, class FS, class OS, class Ct >
template < class Gt, class FS, class OS, class Ct, class WPCA >
inline void
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::
mark_handled( Cell_handle c, unsigned int li ) {
switch( li ) {
case 0: c->info() |= 1; return;
@ -203,9 +202,9 @@ mark_handled( Cell_handle c, unsigned int li ) {
}
}
template < class Gt, class FS, class OS, class Ct >
inline typename Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::Triple
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::
template < class Gt, class FS, class OS, class Ct, class WPCA >
inline typename Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::Triple
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::
ordered_facet_indices( const Facet& f ) const {
if( (f.second&1) == 0 )
return make_array<unsigned int>( f.first->vertex( (f.second+2)&3 )->info(),
@ -217,9 +216,9 @@ ordered_facet_indices( const Facet& f ) const {
f.first->vertex( (f.second+3)&3 )->info() );
}
template < class Gt, class FS, class OS, class Ct >
template < class Gt, class FS, class OS, class Ct, class WPCA >
void
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::
collect_shell( Cell_handle c, unsigned int li ) {
// Collect one surface mesh from the alpha-shape in a fashion similar to ball-pivoting.
// Invariant: the facet is regular or singular.
@ -280,9 +279,9 @@ collect_shell( Cell_handle c, unsigned int li ) {
}
}
template < class Gt, class FS, class OS, class Ct >
template < class Gt, class FS, class OS, class Ct, class WPCA >
void
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::
collect_facets( Tag_true ) {
// Collect all surface meshes from the alpha-shape in a fashion similar to ball-pivoting.
// Reset the facet handled markers.
@ -311,9 +310,9 @@ collect_facets( Tag_true ) {
}
}
template < class Gt, class FS, class OS, class Ct >
template < class Gt, class FS, class OS, class Ct, class WPCA >
void
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::
collect_facets( Tag_false ) {
// Collect all facets from the alpha-shape in an unordered fashion.
for( Finite_facets_iterator fit = _shape->finite_facets_begin(); fit != _shape->finite_facets_end(); ++fit ) {
@ -336,18 +335,18 @@ collect_facets( Tag_false ) {
}
}
template < class Gt, class FS, class OS, class Ct >
const typename Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::Shape&
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::
template < class Gt, class FS, class OS, class Ct, class WPCA >
const typename Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::Shape&
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::
shape() const {
if( !has_shape() )
_shape = Shape_construction_3().construct( _shape, _squared_radius );
return *_shape;
}
template < class Gt, class FS, class OS, class Ct >
typename Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::FT
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::
template < class Gt, class FS, class OS, class Ct, class WPCA >
typename Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::FT
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::
estimate_neighborhood_radius( unsigned int neighbors, unsigned int samples ) {
typename Gt::Compute_squared_distance_3 squared_distance = Gt().compute_squared_distance_3_object();
@ -377,20 +376,23 @@ estimate_neighborhood_radius( unsigned int neighbors, unsigned int samples ) {
// Doxygen has a bug where it cannot link the declaration and implementation
// of methods with a templated parameter.
#ifndef DOXYGEN_RUNNING
template < class Gt, class FS, class OS, class Ct >
template < class Gt, class FS, class OS, class Ct, class WPCA >
template < class InputIterator >
typename Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::FT
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::
estimate_neighborhood_radius( InputIterator begin, InputIterator end, unsigned int neighbors, unsigned int samples ) {
typename Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::FT
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::
estimate_neighborhood_radius( InputIterator begin, InputIterator end, unsigned int neighbors, unsigned int samples,
typename boost::enable_if<
boost::is_convertible< typename std::iterator_traits<InputIterator>::value_type,
Point > >::type* ) {
clear();
add_points( begin, end );
return estimate_neighborhood_radius( neighbors, samples );
}
#endif // DOXYGEN_RUNNING
template < class Gt, class FS, class OS, class Ct >
template < class Gt, class FS, class OS, class Ct, class WPCA >
void
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::
advance_scale_space( unsigned int iterations ) {
typedef std::vector< unsigned int > CountVec;
typedef std::map<Point, size_t> PIMap;
@ -434,18 +436,18 @@ advance_scale_space( unsigned int iterations ) {
}
}
template < class Gt, class FS, class OS, class Ct >
template < class Gt, class FS, class OS, class Ct, class WPCA >
template< class F >
void
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::
try_parallel( const F& func, size_t begin, size_t end, Sequential_tag ) const {
for( std::size_t i = begin; i < end; ++i ) func( i );
}
template < class Gt, class FS, class OS, class Ct >
template < class Gt, class FS, class OS, class Ct, class WPCA >
template< class F >
void
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::
try_parallel( const F& func, size_t begin, size_t end, Parallel_tag ) const {
#ifdef CGAL_LINKED_WITH_TBB
tbb::parallel_for( tbb::blocked_range< std::size_t >( begin, end ), func );
@ -454,20 +456,23 @@ try_parallel( const F& func, size_t begin, size_t end, Parallel_tag ) const {
#endif // CGAL_LINKED_WITH_TBB
}
template < class Gt, class FS, class OS, class Ct >
template < class Gt, class FS, class OS, class Ct, class WPCA >
template < class InputIterator >
void
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::
construct_shape( InputIterator begin, InputIterator end ) {
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::
construct_shape( InputIterator begin, InputIterator end,
typename boost::enable_if<
boost::is_convertible< typename std::iterator_traits<InputIterator>::value_type,
Point > >::type* ) {
deinit_shape();
if( !has_neighborhood_radius() )
estimate_neighborhood_radius();
_shape = Shape_construction_3().construct( begin, end, _squared_radius );
}
template < class Gt, class FS, class OS, class Ct >
template < class Gt, class FS, class OS, class Ct, class WPCA >
void
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::
collect_surface() {
_surface.clear();
if( !has_shape() )
@ -475,9 +480,9 @@ collect_surface() {
collect_facets();
}
template < class Gt, class FS, class OS, class Ct >
template < class Gt, class FS, class OS, class Ct, class WPCA >
void
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::
reconstruct_surface( unsigned int iterations ) {
// Smooth the scale space.
advance_scale_space( iterations );
@ -486,11 +491,14 @@ reconstruct_surface( unsigned int iterations ) {
collect_surface();
}
template < class Gt, class FS, class OS, class Ct >
template < class Gt, class FS, class OS, class Ct, class WPCA >
template < class InputIterator >
void
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::
reconstruct_surface( InputIterator begin, InputIterator end, unsigned int iterations ) {
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::
reconstruct_surface( InputIterator begin, InputIterator end, unsigned int iterations,
typename boost::enable_if<
boost::is_convertible< typename std::iterator_traits<InputIterator>::value_type,
Point > >::type* = NULL ) {
// Compute the radius for which the mean ball would contain the required number of neighbors.
clear();
add_points( begin, end );
@ -502,25 +510,25 @@ reconstruct_surface( InputIterator begin, InputIterator end, unsigned int iterat
collect_surface();
}
template < class Gt, class FS, class OS, class Ct >
typename Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::Const_triple_iterator
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::shell_begin( std::size_t shell ) const {
template < class Gt, class FS, class OS, class Ct, class WPCA >
typename Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::Const_triple_iterator
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::shell_begin( std::size_t shell ) const {
CGAL_assertion( OS::value == true );
CGAL_assertion( shell >= 0 && shell < _shells.size() );
return _shells[ shell ];
}
template < class Gt, class FS, class OS, class Ct >
typename Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::Triple_iterator
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::shell_begin( std::size_t shell ) {
template < class Gt, class FS, class OS, class Ct, class WPCA >
typename Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::Triple_iterator
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::shell_begin( std::size_t shell ) {
CGAL_assertion( OS::value == true );
CGAL_assertion( shell >= 0 && shell < _shells.size() );
return _shells[ shell ];
}
template < class Gt, class FS, class OS, class Ct >
typename Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::Const_triple_iterator
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::shell_end( std::size_t shell ) const {
template < class Gt, class FS, class OS, class Ct, class WPCA >
typename Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::Const_triple_iterator
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::shell_end( std::size_t shell ) const {
CGAL_assertion( OS::value == true );
CGAL_assertion( shell >= 0 && shell < _shells.size() );
if( shell == _shells.size()-1 )
@ -528,9 +536,9 @@ Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::shell_end( std::size_t shell
return _shells[ shell+1 ];
}
template < class Gt, class FS, class OS, class Ct >
typename Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::Triple_iterator
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct>::shell_end( std::size_t shell ) {
template < class Gt, class FS, class OS, class Ct, class WPCA >
typename Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::Triple_iterator
Scale_space_surface_reconstruction_3<Gt,FS,OS,Ct,WPCA>::shell_end( std::size_t shell ) {
CGAL_assertion( OS::value == true );
CGAL_assertion( shell >= 0 && shell < _shells.size() );
if( shell == _shells.size()-1 )