force_manifold and separate_shells attributes replaced by parameters for clearer interface

This commit is contained in:
Simon Giraudot 2015-08-24 17:23:16 +02:00
parent fb7b5d7884
commit 644df25e9e
3 changed files with 63 additions and 110 deletions

View File

@ -37,11 +37,13 @@ int main(int argc, char* argv[]) {
Timer t; Timer t;
t.start(); t.start();
// Construct the mesh in a scale space. // Construct the mesh in a scale space.
Reconstruction reconstruct( 10, 200, Reconstruction reconstruct( 10, 200 );
false, // Do not separate shells
true // Force manifold output reconstruct.reconstruct_surface( points.begin(), points.end(), 4,
); false, // Do not separate shells
reconstruct.reconstruct_surface( points.begin(), points.end(), 4 ); true // Force manifold output
);
std::cerr << "Reconstruction done in " << t.time() << " sec." << std::endl; std::cerr << "Reconstruction done in " << t.time() << " sec." << std::endl;
t.reset(); t.reset();
std::ofstream out ("out.off"); std::ofstream out ("out.off");

View File

@ -201,17 +201,13 @@ public:
template < class Gt, class FS, class wA, class Ct > template < class Gt, class FS, class wA, class Ct >
Scale_space_surface_reconstruction_3<Gt,FS,wA,Ct>:: Scale_space_surface_reconstruction_3<Gt,FS,wA,Ct>::
Scale_space_surface_reconstruction_3( unsigned int neighbors, unsigned int samples, Scale_space_surface_reconstruction_3( unsigned int neighbors, unsigned int samples)
bool separate_shells, bool force_manifold) : _generator (0),_mean_neighbors(neighbors), _samples(samples), _squared_radius(-1), _shape(0) {}
: _generator (0),_mean_neighbors(neighbors), _samples(samples), _squared_radius(-1),
_separate_shells (separate_shells), _force_manifold (force_manifold),
_border_angle (45.), _shape(0) {}
template < class Gt, class FS, class wA, class Ct > template < class Gt, class FS, class wA, class Ct >
Scale_space_surface_reconstruction_3<Gt,FS,wA,Ct>:: Scale_space_surface_reconstruction_3<Gt,FS,wA,Ct>::
Scale_space_surface_reconstruction_3( FT sq_radius ) Scale_space_surface_reconstruction_3( FT sq_radius )
: _mean_neighbors(0), _samples(0), _squared_radius(sq_radius), : _mean_neighbors(0), _samples(0), _squared_radius(sq_radius),_shape(0) {
_separate_shells (true), _force_manifold (false), _border_angle (45.), _shape(0) {
CGAL_precondition( sq_radius >= 0 ); CGAL_precondition( sq_radius >= 0 );
} }
@ -305,7 +301,7 @@ ordered_facet_indices( const Facet& f ) const {
template < class Gt, class FS, class wA, class Ct > template < class Gt, class FS, class wA, class Ct >
void void
Scale_space_surface_reconstruction_3<Gt,FS,wA,Ct>:: Scale_space_surface_reconstruction_3<Gt,FS,wA,Ct>::
collect_shell( Cell_handle c, unsigned int li ) { collect_shell( Cell_handle c, unsigned int li, bool separate_shells, bool force_manifold ) {
// Collect one surface mesh from the alpha-shape in a fashion similar to ball-pivoting. // Collect one surface mesh from the alpha-shape in a fashion similar to ball-pivoting.
// Invariant: the facet is regular or singular. // Invariant: the facet is regular or singular.
@ -336,7 +332,7 @@ collect_shell( Cell_handle c, unsigned int li ) {
// Output the facet as a triple of indices. // Output the facet as a triple of indices.
_surface.push_back( ordered_facet_indices(f) ); _surface.push_back( ordered_facet_indices(f) );
if( !processed ) { if( !processed ) {
if (_separate_shells || _shells.size () == 0) if (separate_shells || _shells.size () == 0)
{ {
_shells.push_back( --_surface.end() ); _shells.push_back( --_surface.end() );
_index ++; _index ++;
@ -349,7 +345,7 @@ collect_shell( Cell_handle c, unsigned int li ) {
// If the surface is required to be manifold, // If the surface is required to be manifold,
// the opposite layer should be ignored // the opposite layer should be ignored
if (_force_manifold) if (force_manifold)
mark_opposite_handled (f); mark_opposite_handled (f);
// Pivot over each of the facet's edges and continue the surface at the next regular or singular facet. // Pivot over each of the facet's edges and continue the surface at the next regular or singular facet.
@ -384,7 +380,7 @@ collect_shell( Cell_handle c, unsigned int li ) {
template < class Gt, class FS, class wA, class Ct > template < class Gt, class FS, class wA, class Ct >
void void
Scale_space_surface_reconstruction_3<Gt,FS,wA,Ct>:: Scale_space_surface_reconstruction_3<Gt,FS,wA,Ct>::
collect_facets( ) { collect_facets (bool separate_shells, bool force_manifold) {
// We check each of the facets: if it is not handled and either regular or singular, // We check each of the facets: if it is not handled and either regular or singular,
@ -394,14 +390,14 @@ collect_facets( ) {
case Shape::REGULAR: case Shape::REGULAR:
// Build a surface from the outer cell. // Build a surface from the outer cell.
if( _shape->classify(fit->first) == Shape::EXTERIOR ) if( _shape->classify(fit->first) == Shape::EXTERIOR )
collect_shell( *fit ); collect_shell( *fit, separate_shells, force_manifold );
else else
collect_shell( _shape->mirror_facet( *fit ) ); collect_shell( _shape->mirror_facet( *fit ), separate_shells, force_manifold );
break; break;
case Shape::SINGULAR: case Shape::SINGULAR:
// Build a surface from both incident cells. // Build a surface from both incident cells.
collect_shell( *fit ); collect_shell( *fit, separate_shells, force_manifold );
collect_shell( _shape->mirror_facet( *fit ) ); collect_shell( _shape->mirror_facet( *fit ), separate_shells, force_manifold );
break; break;
default: default:
break; break;
@ -557,7 +553,7 @@ construct_shape( InputIterator begin, InputIterator end,
template < class Gt, class FS, class wA, class Ct > template < class Gt, class FS, class wA, class Ct >
void void
Scale_space_surface_reconstruction_3<Gt,FS,wA,Ct>:: Scale_space_surface_reconstruction_3<Gt,FS,wA,Ct>::
collect_surface( ) { collect_surface (bool separate_shells, bool force_manifold, FT border_angle) {
clear_surface(); clear_surface();
if( !has_shape() ) if( !has_shape() )
@ -568,7 +564,7 @@ collect_surface( ) {
// If shells are not separated and no manifold constraint is given, // If shells are not separated and no manifold constraint is given,
// then the quick collection of facets can be applied // then the quick collection of facets can be applied
if (!_separate_shells && !_force_manifold) if (!separate_shells && !force_manifold)
{ {
collect_facets_quick (); collect_facets_quick ();
_shells.push_back (_surface.begin ()); _shells.push_back (_surface.begin ());
@ -583,16 +579,16 @@ collect_surface( ) {
for( All_cells_iterator cit = _shape->all_cells_begin(); cit != _shape->all_cells_end(); ++cit ) for( All_cells_iterator cit = _shape->all_cells_begin(); cit != _shape->all_cells_end(); ++cit )
cit->info() = 0; cit->info() = 0;
if (_force_manifold) if (force_manifold)
{ {
// If manifold surface is wanted, small volumes (bubbles) are first detected in // If manifold surface is wanted, small volumes (bubbles) are first detected in
// order to know which layer to ignore when collecting facets // order to know which layer to ignore when collecting facets
detect_bubbles(); detect_bubbles(border_angle);
} }
collect_facets (); collect_facets (separate_shells, force_manifold);
if (_force_manifold) if (force_manifold)
{ {
// Even when taking into account facets, some nonmanifold features might remain // Even when taking into account facets, some nonmanifold features might remain
fix_nonmanifold_edges(); fix_nonmanifold_edges();
@ -634,7 +630,7 @@ find_two_other_vertices(const Facet& f, Vertex_handle v,
template < class Gt, class FS, class wA, class Ct > template < class Gt, class FS, class wA, class Ct >
void void
Scale_space_surface_reconstruction_3<Gt,FS,wA,Ct>:: Scale_space_surface_reconstruction_3<Gt,FS,wA,Ct>::
detect_bubbles() { detect_bubbles(FT border_angle) {
std::set<Cell_handle> done; std::set<Cell_handle> done;
@ -723,7 +719,7 @@ detect_bubbles() {
c->vertex (i)->point (), c->vertex (i)->point (),
c->vertex ((i + (j+2)%3 + 1)%4)->point ()); c->vertex ((i + (j+2)%3 + 1)%4)->point ());
if (-_border_angle < angle && angle < _border_angle) if (-border_angle < angle && angle < border_angle)
{ {
borders.insert (vedge); borders.insert (vedge);
} }
@ -1125,13 +1121,14 @@ fix_nonmanifold_vertices() {
template < class Gt, class FS, class wA, class Ct > template < class Gt, class FS, class wA, class Ct >
void void
Scale_space_surface_reconstruction_3<Gt,FS,wA,Ct>:: Scale_space_surface_reconstruction_3<Gt,FS,wA,Ct>::
reconstruct_surface( unsigned int iterations ) { reconstruct_surface( unsigned int iterations, bool separate_shells,
bool force_manifold, FT border_angle) {
// Smooth the scale space. // Smooth the scale space.
increase_scale( iterations ); increase_scale( iterations );
// Mesh the perturbed points. // Mesh the perturbed points.
collect_surface (); collect_surface (separate_shells, force_manifold, border_angle);
} }
@ -1141,19 +1138,14 @@ template < class InputIterator >
void void
Scale_space_surface_reconstruction_3<Gt,FS,wA,Ct>:: Scale_space_surface_reconstruction_3<Gt,FS,wA,Ct>::
reconstruct_surface( InputIterator begin, InputIterator end, unsigned int iterations, reconstruct_surface( InputIterator begin, InputIterator end, unsigned int iterations,
bool separate_shells, bool force_manifold, bool separate_shells, bool force_manifold, FT border_angle,
typename boost::enable_if< CGAL::is_iterator<InputIterator> >::type*) { typename boost::enable_if< CGAL::is_iterator<InputIterator> >::type*) {
// Compute the radius for which the mean ball would contain the required number of neighbors. // Compute the radius for which the mean ball would contain the required number of neighbors.
clear(); clear();
insert( begin, end ); insert( begin, end );
_separate_shells = separate_shells; reconstruct_surface (iterations, separate_shells, force_manifold, border_angle);
_force_manifold = force_manifold;
reconstruct_surface (iterations);
} }
/// \endcond /// \endcond

View File

@ -226,10 +226,6 @@ private:
FT _squared_radius; // The squared neighborhood radius. FT _squared_radius; // The squared neighborhood radius.
bool _separate_shells;
bool _force_manifold;
FT _border_angle;
// The shape must be a pointer, because the alpha of a Fixed_alpha_shape_3 // The shape must be a pointer, because the alpha of a Fixed_alpha_shape_3
// can only be set at construction and its assignment operator is private. // can only be set at construction and its assignment operator is private.
// We want to be able to set the alpha after constructing the scale-space // We want to be able to set the alpha after constructing the scale-space
@ -268,8 +264,7 @@ public:
* \param separate_shells determines whether to collect the surface per shell. * \param separate_shells determines whether to collect the surface per shell.
* \param force_manifold determines if the surface is forced to be 2-manifold. * \param force_manifold determines if the surface is forced to be 2-manifold.
*/ */
Scale_space_surface_reconstruction_3( unsigned int neighbors, unsigned int samples, Scale_space_surface_reconstruction_3( unsigned int neighbors, unsigned int samples);
bool separate_shells = true, bool force_manifold = false );
/// constructs a surface reconstructor with a given neighborhood radius. /// constructs a surface reconstructor with a given neighborhood radius.
/** \param sq_radius is the squared radius of the neighborhood. /** \param sq_radius is the squared radius of the neighborhood.
@ -300,15 +295,15 @@ private:
Triple ordered_facet_indices( const Facet& f ) const; Triple ordered_facet_indices( const Facet& f ) const;
// Collect the triangles of one shell of the surface. // Collect the triangles of one shell of the surface.
void collect_shell( Cell_handle c, unsigned int li ); void collect_shell( Cell_handle c, unsigned int li, bool separate_shells, bool force_manifold);
// Collect the triangles of one shell of the surface. // Collect the triangles of one shell of the surface.
void collect_shell( const Facet& f ) { void collect_shell( const Facet& f, bool separate_shells, bool force_manifold) {
collect_shell( f.first, f.second ); collect_shell( f.first, f.second, separate_shells, force_manifold );
} }
// Collect the triangles of the complete surface. // Collect the triangles of the complete surface.
void collect_facets( ); void collect_facets( bool separate_shells, bool force_manifold );
void collect_facets_quick( ); void collect_facets_quick( );
@ -657,60 +652,6 @@ public:
void set_neighborhood_sample_size( unsigned int samples ) { _samples = samples; } void set_neighborhood_sample_size( unsigned int samples ) { _samples = samples; }
/// \} /// \}
/// \name Output Options Parameters
/// \{
/// determines whether to collect the surface per shell.
/** If set to false, the output surface is stored in a single shell.
*
* \note Setting this parameter to false when 2-manifoldness is
* not required allows for a quicker computation of the
* reconstruction.
*
* \sa `shell_begin(std::size_t shell)`
* \sa `shell_end(std::size_t shell)`
*/
void set_separate_shells( bool separate_shells ) { _separate_shells = separate_shells; }
/// determines if the surface is forced to be 2-manifold.
/** If set to true, some facets of the reconstruction are
* willingly discarded so that every facet, edge and vertex are
* manifold. The discarded facets are accessible by iterating on
* the garbage container.
*
* \note Setting this parameter to false when separate shells are
* not required allows for a quicker computation of the
* reconstruction.
*
* \note This function has no effect on an already reconstructed
* surface. For the change of requirement (manifold or not) to be
* applied, the `reconstruct_surface()` function must be called
* again.
*
* \sa `garbage_begin()`
* \sa `garbage_end()`
*/
void set_force_manifold( bool force_manifold ) { _force_manifold = force_manifold; }
/// sets the maximal angle between two facets such that the edge
/// is seen as a border.
/** If the output is forced to be 2-manifold, some almost flat
* volume bubbles are detected. To do so, border edges must be
* estimated.
*
* An edge adjacent to 2 regular facets is considered as a border
* if it is also adjacent to a singular facet or if the angle
* between the two regular facets is lower than this parameter
* (set to 45° by default).
*
* \param border_angle is the maximal angle between two facets
* such that their common edge is considered as a border.
*
* \note This parameter is only used if the output is forced to
* be 2-manifold
*
*/
void set_border_angle( FT border_angle) { _border_angle = border_angle; }
/// \}
/// \name Scale-Space Manipulation /// \name Scale-Space Manipulation
/// \{ /// \{
@ -839,12 +780,12 @@ private:
// collects the surface mesh from the shape. // collects the surface mesh from the shape.
// If the sahep does not yet exist, it is constructed. // If the sahep does not yet exist, it is constructed.
void collect_surface ( ); void collect_surface (bool separate_shells, bool force_manifold, FT border_angle );
// detects the non-manifold features of the shape // detects the non-manifold features of the shape
void find_two_other_vertices(const Facet& f, Vertex_handle v, void find_two_other_vertices(const Facet& f, Vertex_handle v,
Vertex_handle& v1, Vertex_handle& v2); Vertex_handle& v1, Vertex_handle& v2);
void detect_bubbles(); void detect_bubbles( FT border_angle );
void fix_nonmanifold_edges(); void fix_nonmanifold_edges();
void fix_nonmanifold_vertices(); void fix_nonmanifold_vertices();
@ -865,16 +806,33 @@ public:
* If the neighborhood radius has not been set before, it is automatically * If the neighborhood radius has not been set before, it is automatically
* estimated using `estimate_neighborhood_squared_radius()`. * estimated using `estimate_neighborhood_squared_radius()`.
* *
* \param separate_shells determines whether to collect the surface per shell.
* \param force_manifold determines if the surface is forced to be 2-manifold.
* \param border_angle sets the maximal angle between two facets
* such that the edge is seen as a border.
*
* If the output is forced to be 2-manifold, some almost flat
* volume bubbles are detected. To do so, border edges must be
* estimated.
*
* An edge adjacent to 2 regular facets is considered as a border
* if it is also adjacent to a singular facet or if the angle
* between the two regular facets is lower than this parameter
* (set to 45° by default).
*
* \note This method processes the point set at the current scale. The * \note This method processes the point set at the current scale. The
* points can be set with <code>[insert(begin, end)](\ref insert)</code>. * points can be set with <code>[insert(begin, end)](\ref insert)</code>.
* \note `border_angle` is not used if `force_manifold` is set to false.
* *
* \sa `estimate_neighborhood_squared_radius()`. * \sa `estimate_neighborhood_squared_radius()`.
* \sa `increase_scale(unsigned int iterations)`. * \sa `increase_scale(unsigned int iterations)`.
*/ */
void reconstruct_surface() void reconstruct_surface(bool separate_shells = true,
{ bool force_manifold = false,
reconstruct_surface(0); FT border_angle = 45)
} {
reconstruct_surface(0, separate_shells, force_manifold, border_angle);
}
/// gives the number of triangles of the surface. /// gives the number of triangles of the surface.
std::size_t number_of_triangles() const { return _surface.size(); } std::size_t number_of_triangles() const { return _surface.size(); }
@ -889,7 +847,8 @@ public:
} }
/// \cond internal_doc /// \cond internal_doc
void reconstruct_surface( unsigned int iterations); void reconstruct_surface( unsigned int iterations, bool separate_shells = true,
bool force_manifold = false, FT border_angle = 45);
/// \endcond /// \endcond
/// \cond internal_doc /// \cond internal_doc
@ -921,10 +880,10 @@ public:
#ifdef DOXYGEN_RUNNING #ifdef DOXYGEN_RUNNING
void reconstruct_surface( InputIterator begin, InputIterator end, void reconstruct_surface( InputIterator begin, InputIterator end,
unsigned int iterations = 0, bool separate_shells = true, unsigned int iterations = 0, bool separate_shells = true,
bool force_manifold = false); bool force_manifold = false, FT border_angle = 45);
#else // DOXYGEN_RUNNING #else // DOXYGEN_RUNNING
void reconstruct_surface( InputIterator begin, InputIterator end, unsigned int iterations = 0, void reconstruct_surface( InputIterator begin, InputIterator end, unsigned int iterations = 0,
bool shells = true, bool force_manifold = false, bool separate_shells = true, bool force_manifold = false, FT border_angle = 45,
typename boost::enable_if< CGAL::is_iterator<InputIterator> >::type* = NULL ); typename boost::enable_if< CGAL::is_iterator<InputIterator> >::type* = NULL );
#endif // DOXYGEN_RUNNING #endif // DOXYGEN_RUNNING
/// \endcond /// \endcond