diff --git a/Scale_space_reconstruction_3/examples/Scale_space_reconstruction_3/scale_space_manifold.cpp b/Scale_space_reconstruction_3/examples/Scale_space_reconstruction_3/scale_space_manifold.cpp index 6e9b373bebb..3b9a2dbf47f 100644 --- a/Scale_space_reconstruction_3/examples/Scale_space_reconstruction_3/scale_space_manifold.cpp +++ b/Scale_space_reconstruction_3/examples/Scale_space_reconstruction_3/scale_space_manifold.cpp @@ -37,11 +37,13 @@ int main(int argc, char* argv[]) { Timer t; t.start(); // Construct the mesh in a scale space. - Reconstruction reconstruct( 10, 200, - false, // Do not separate shells - true // Force manifold output - ); - reconstruct.reconstruct_surface( points.begin(), points.end(), 4 ); + Reconstruction reconstruct( 10, 200 ); + + reconstruct.reconstruct_surface( points.begin(), points.end(), 4, + false, // Do not separate shells + true // Force manifold output + ); + std::cerr << "Reconstruction done in " << t.time() << " sec." << std::endl; t.reset(); std::ofstream out ("out.off"); diff --git a/Scale_space_reconstruction_3/include/CGAL/Scale_space_reconstruction_3/Scale_space_surface_reconstruction_3_impl.h b/Scale_space_reconstruction_3/include/CGAL/Scale_space_reconstruction_3/Scale_space_surface_reconstruction_3_impl.h index c2087716930..063ea9c488c 100644 --- a/Scale_space_reconstruction_3/include/CGAL/Scale_space_reconstruction_3/Scale_space_surface_reconstruction_3_impl.h +++ b/Scale_space_reconstruction_3/include/CGAL/Scale_space_reconstruction_3/Scale_space_surface_reconstruction_3_impl.h @@ -201,17 +201,13 @@ public: template < class Gt, class FS, class wA, class Ct > Scale_space_surface_reconstruction_3:: -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), - _separate_shells (separate_shells), _force_manifold (force_manifold), - _border_angle (45.), _shape(0) {} +Scale_space_surface_reconstruction_3( unsigned int neighbors, unsigned int samples) + : _generator (0),_mean_neighbors(neighbors), _samples(samples), _squared_radius(-1), _shape(0) {} template < class Gt, class FS, class wA, class Ct > Scale_space_surface_reconstruction_3:: Scale_space_surface_reconstruction_3( FT sq_radius ) -: _mean_neighbors(0), _samples(0), _squared_radius(sq_radius), - _separate_shells (true), _force_manifold (false), _border_angle (45.), _shape(0) { +: _mean_neighbors(0), _samples(0), _squared_radius(sq_radius),_shape(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 > void Scale_space_surface_reconstruction_3:: -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. // 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. _surface.push_back( ordered_facet_indices(f) ); if( !processed ) { - if (_separate_shells || _shells.size () == 0) + if (separate_shells || _shells.size () == 0) { _shells.push_back( --_surface.end() ); _index ++; @@ -349,7 +345,7 @@ collect_shell( Cell_handle c, unsigned int li ) { // If the surface is required to be manifold, // the opposite layer should be ignored - if (_force_manifold) + if (force_manifold) mark_opposite_handled (f); // 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 > void Scale_space_surface_reconstruction_3:: -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, @@ -394,14 +390,14 @@ collect_facets( ) { case Shape::REGULAR: // Build a surface from the outer cell. if( _shape->classify(fit->first) == Shape::EXTERIOR ) - collect_shell( *fit ); + collect_shell( *fit, separate_shells, force_manifold ); else - collect_shell( _shape->mirror_facet( *fit ) ); + collect_shell( _shape->mirror_facet( *fit ), separate_shells, force_manifold ); break; case Shape::SINGULAR: // Build a surface from both incident cells. - collect_shell( *fit ); - collect_shell( _shape->mirror_facet( *fit ) ); + collect_shell( *fit, separate_shells, force_manifold ); + collect_shell( _shape->mirror_facet( *fit ), separate_shells, force_manifold ); break; default: break; @@ -557,7 +553,7 @@ construct_shape( InputIterator begin, InputIterator end, template < class Gt, class FS, class wA, class Ct > void Scale_space_surface_reconstruction_3:: -collect_surface( ) { +collect_surface (bool separate_shells, bool force_manifold, FT border_angle) { clear_surface(); if( !has_shape() ) @@ -568,7 +564,7 @@ collect_surface( ) { // If shells are not separated and no manifold constraint is given, // then the quick collection of facets can be applied - if (!_separate_shells && !_force_manifold) + if (!separate_shells && !force_manifold) { collect_facets_quick (); _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 ) cit->info() = 0; - if (_force_manifold) + if (force_manifold) { // If manifold surface is wanted, small volumes (bubbles) are first detected in // 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 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 > void Scale_space_surface_reconstruction_3:: -detect_bubbles() { +detect_bubbles(FT border_angle) { std::set done; @@ -723,7 +719,7 @@ detect_bubbles() { c->vertex (i)->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); } @@ -1125,13 +1121,14 @@ fix_nonmanifold_vertices() { template < class Gt, class FS, class wA, class Ct > void Scale_space_surface_reconstruction_3:: - reconstruct_surface( unsigned int iterations ) { + reconstruct_surface( unsigned int iterations, bool separate_shells, + bool force_manifold, FT border_angle) { // Smooth the scale space. increase_scale( iterations ); // Mesh the perturbed points. - collect_surface (); + collect_surface (separate_shells, force_manifold, border_angle); } @@ -1141,19 +1138,14 @@ template < class InputIterator > void Scale_space_surface_reconstruction_3:: 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 >::type*) { // Compute the radius for which the mean ball would contain the required number of neighbors. clear(); insert( begin, end ); - _separate_shells = separate_shells; - _force_manifold = force_manifold; - - reconstruct_surface (iterations); - - + reconstruct_surface (iterations, separate_shells, force_manifold, border_angle); } /// \endcond diff --git a/Scale_space_reconstruction_3/include/CGAL/Scale_space_surface_reconstruction_3.h b/Scale_space_reconstruction_3/include/CGAL/Scale_space_surface_reconstruction_3.h index bc7d6835a20..d1bc1fcec53 100644 --- a/Scale_space_reconstruction_3/include/CGAL/Scale_space_surface_reconstruction_3.h +++ b/Scale_space_reconstruction_3/include/CGAL/Scale_space_surface_reconstruction_3.h @@ -226,10 +226,6 @@ private: 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 // 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 @@ -268,8 +264,7 @@ public: * \param separate_shells determines whether to collect the surface per shell. * \param force_manifold determines if the surface is forced to be 2-manifold. */ - Scale_space_surface_reconstruction_3( unsigned int neighbors, unsigned int samples, - bool separate_shells = true, bool force_manifold = false ); + Scale_space_surface_reconstruction_3( unsigned int neighbors, unsigned int samples); /// constructs a surface reconstructor with a given neighborhood radius. /** \param sq_radius is the squared radius of the neighborhood. @@ -300,15 +295,15 @@ private: Triple ordered_facet_indices( const Facet& f ) const; // 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. - void collect_shell( const Facet& f ) { - collect_shell( f.first, f.second ); + void collect_shell( const Facet& f, bool separate_shells, bool force_manifold) { + collect_shell( f.first, f.second, separate_shells, force_manifold ); } // Collect the triangles of the complete surface. - void collect_facets( ); + void collect_facets( bool separate_shells, bool force_manifold ); void collect_facets_quick( ); @@ -657,60 +652,6 @@ public: 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 /// \{ @@ -839,12 +780,12 @@ private: // collects the surface mesh from the shape. // 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 void find_two_other_vertices(const Facet& f, Vertex_handle v, Vertex_handle& v1, Vertex_handle& v2); - void detect_bubbles(); + void detect_bubbles( FT border_angle ); void fix_nonmanifold_edges(); void fix_nonmanifold_vertices(); @@ -865,16 +806,33 @@ public: * If the neighborhood radius has not been set before, it is automatically * 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 * points can be set with [insert(begin, end)](\ref insert). + * \note `border_angle` is not used if `force_manifold` is set to false. * * \sa `estimate_neighborhood_squared_radius()`. * \sa `increase_scale(unsigned int iterations)`. */ - void reconstruct_surface() - { - reconstruct_surface(0); - } + void reconstruct_surface(bool separate_shells = true, + bool force_manifold = false, + FT border_angle = 45) + { + reconstruct_surface(0, separate_shells, force_manifold, border_angle); + } /// gives the number of triangles of the surface. std::size_t number_of_triangles() const { return _surface.size(); } @@ -889,7 +847,8 @@ public: } /// \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 /// \cond internal_doc @@ -921,10 +880,10 @@ public: #ifdef DOXYGEN_RUNNING void reconstruct_surface( InputIterator begin, InputIterator end, unsigned int iterations = 0, bool separate_shells = true, - bool force_manifold = false); + bool force_manifold = false, FT border_angle = 45); #else // DOXYGEN_RUNNING 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 >::type* = NULL ); #endif // DOXYGEN_RUNNING /// \endcond