1 // Copyright (C) 2013 INRIA - Sophia Antipolis (France).
2 // Copyright (c) 2017 GeometryFactory Sarl (France).
3 //
4 // This file is part of CGAL (www.cgal.org).
5 //
6 // $URL: https://github.com/CGAL/cgal/blob/v5.3/Scale_space_reconstruction_3/include/CGAL/Scale_space_reconstruction_3/Alpha_shape_mesher.h $
7 // $Id: Alpha_shape_mesher.h e895f42 2021-01-06T14:29:37+01:00 Simon Giraudot
8 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
9 //
10 // Author(s):      Thijs van Lankveld, Simon Giraudot
11 
12 
13 #ifndef CGAL_SCALE_SPACE_RECONSTRUCTION_3_ALPHA_SHAPE_MESHER_H
14 #define CGAL_SCALE_SPACE_RECONSTRUCTION_3_ALPHA_SHAPE_MESHER_H
15 
16 #include <CGAL/license/Scale_space_reconstruction_3.h>
17 
18 #include <CGAL/Scale_space_reconstruction_3/Shape_construction_3.h>
19 
20 #include <CGAL/Union_find.h>
21 
22 namespace CGAL
23 {
24 
25 namespace Scale_space_reconstruction_3
26 {
27 
28 /** \ingroup PkgScaleSpaceReconstruction3Classes
29  *
30  *  Surface mesher for scale space reconstruction based on
31  *  `CGAL::Alpha_shape_3`.
32  *
33  *  The surface can be constructed either for a fixed neighborhood
34  *  radius, or for a dynamic radius. When constructing the surface for
35  *  exactly one neighborhood radius, it is faster to set
36  *  `FixedSurface` to `Tag_true`. If the correct neighborhood radius
37  *  should be changed or estimated multiple times, it is faster to set
38  *  `FixedSurface` to `Tag_false`.
39  *
40  *  It is undefined whether a surface with fixed radius may have its radius
41  *  changed, but if so, this will likely require more computation time than
42  *  changing the radius of a dynamic surface. In either case, it is possible to
43  *  change the point set while maintaining the same radius.
44  *
45  *  The surface can be stored either as an unordered collection of triangles,
46  *  or as a collection ordered by shells. A shell is a maximally connected
47  *  component of the surface where connected facets are locally oriented
48  *  towards the same side of the surface.
49  *
50  *  \cgalModels CGAL::Scale_space_reconstruction_3::Mesher
51  *
52  *  \tparam Geom_traits is the geometric traits class. It must be a
53  *  model of `DelaunayTriangulationTraits_3`. It must have a
54  *  `RealEmbeddable` field number type. Generally,
55  *  `Exact_predicates_inexact_constructions_kernel` is preferred.
56  *  \tparam FixedSurface determines whether the surface is expected to
57  *  be constructed for a fixed neighborhood radius. It must be a
58  *  `Boolean_tag` type. The default value is `Tag_true`. Note that the
59  *  value of this parameter does not change the result but only has an
60  *  impact on the run-time.
61  */
62 template <typename Geom_traits, typename FixedSurface = Tag_true>
63 class Alpha_shape_mesher
64 {
65 public:
66   typedef typename Geom_traits::FT FT;
67   typedef typename Geom_traits::Point_3                        Point;          ///< defines the point type.
68 
69   typedef std::array< unsigned int, 3 >       Facet;                 ///< defines a triple of point indices indicating a triangle of the surface.
70 private:
71   typedef std::list< Facet >                         Facetset;              ///< defines a collection of triples.
72   // Note that this is a list for two reasons: iterator validity for the shell iterators, and memory requirements for the expected huge collections.
73 
74 public:
75 #ifdef DOXYGEN_RUNNING
76   typedef unspecified_type                            Facet_iterator;        ///< defines an iterator over the triples.
77   typedef const unspecified_type                      Facet_const_iterator;  ///< defines a constant iterator over the triples.
78 #else // DOXYGEN_RUNNING
79   typedef Facetset::iterator                         Facet_iterator;
80   typedef Facetset::const_iterator                   Facet_const_iterator;
81 #endif // DOXYGEN_RUNNING
82 
83 private:
84   typedef std::vector< Facet_iterator >              FacetIterSet;
85 
86 private:
87 
88   // Constructing the surface.
89   typedef CGAL::Shape_construction_3<Geom_traits, FixedSurface> Shape_construction_3;
90 
91   typedef typename Shape_construction_3::Shape           Shape;
92   typedef typename Shape_construction_3::Triangulation   Triangulation;
93 
94   typedef typename Shape::Vertex_handle               Vertex_handle;
95   typedef typename Shape::Cell_handle                 Cell_handle;
96   typedef typename Shape::Facet                       SFacet;
97   typedef typename Shape::Edge                        Edge;
98   typedef std::pair<Vertex_handle, Vertex_handle>     VEdge;
99 
100   typedef typename Shape::Vertex_iterator             Vertex_iterator;
101   typedef typename Shape::Cell_iterator               Cell_iterator;
102   typedef typename Shape::Facet_iterator              SFacet_iterator;
103   typedef typename Shape::Edge_iterator               Edge_iterator;
104 
105   typedef typename Shape::Finite_cells_iterator       Finite_cells_iterator;
106   typedef typename Shape::Finite_facets_iterator      Finite_facets_iterator;
107   typedef typename Shape::Finite_edges_iterator       Finite_edges_iterator;
108   typedef typename Shape::Finite_vertices_iterator    Finite_vertices_iterator;
109 
110   typedef typename Shape::Facet_circulator            SFacet_circulator;
111 
112   typedef typename Shape::All_cells_iterator          All_cells_iterator;
113 
114   typedef typename Shape::Classification_type         Classification_type;
115 
116   typedef std::map<SFacet, unsigned int> Map_facet_to_shell;
117   typedef typename std::array<std::set<SFacet>, 2 >   Bubble;
118 
119   bool _separate_shells;
120   bool _force_manifold;
121   FT _border_angle;
122 
123   // The shape must be a pointer, because the alpha of a Fixed_alpha_shape_3
124   // can only be set at construction and its assignment operator is private.
125   // We want to be able to set the alpha after constructing the scale-space
126   // reconstructer object.
127   Shape*          _shape;
128 
129   // The surface. If the surface is collected per shell, the triples of the
130   // same shell are stored consecutively.
131   Facetset       _surface;
132 
133   // The shells can be accessed through iterators to the surface.
134   FacetIterSet   _shells;
135 
136   // If the surface is forced to be manifold, removed facets are stored
137   Facetset _garbage;
138 
139   // Map TDS facets to shells
140   Map_facet_to_shell _map_f2s;
141   unsigned int _index;
142 
143   std::vector<Bubble> _bubbles;
144   std::map<SFacet, std::size_t> _map_f2b;
145 
146   FT _squared_radius;
147 
148 public:
149 
150   /**
151    *  Constructs an alpha shape mesher.
152    *
153    *  \param squared_radius \f$\alpha\f$ parameter of the alpha shape algorithm.
154    *  \param separate_shells determines whether to collect the surface per shell.
155    *  \param force_manifold determines if the surface is forced to be 2-manifold.
156    *  \param border_angle sets the maximal angle between two facets
157    *  such that the edge is seen as a border.
158    *
159    *  If the output is forced to be 2-manifold, some almost flat
160    *  volume bubbles are detected. To do so, border edges must be
161    *  estimated.
162    *
163    *  An edge adjacent to 2 regular facets is considered as a border
164    *  if it is also adjacent to a singular facet or if the angle
165    *  between the two regular facets is lower than this parameter
166    *  (set to 45° by default).
167    *
168    *  \note `border_angle` is not used if `force_manifold` is set to false.
169    */
170   Alpha_shape_mesher (FT squared_radius,
171                       bool separate_shells = false,
172                       bool force_manifold = false,
173                       FT border_angle = 45.)
_separate_shells(separate_shells)174     : _separate_shells (separate_shells),
175       _force_manifold (force_manifold),
176       _border_angle (border_angle),
177       _shape (nullptr),
178       _squared_radius (squared_radius)
179   {
180 
181   }
182 
~Alpha_shape_mesher()183   ~Alpha_shape_mesher ()
184   {
185     clear_surface();
186   }
187 
188   /// \cond SKIP_IN_MANUAL
189   template <typename InputIterator, typename OutputIterator>
operator()190   void operator() (InputIterator begin, InputIterator end, OutputIterator output)
191   {
192     clear_surface();
193 
194     _shape = Shape_construction_3().construct (begin, end, _squared_radius);
195 
196     // If shells are not separated and no manifold constraint is given,
197     // then the quick collection of facets can be applied
198     if (!_separate_shells && !_force_manifold)
199     {
200       collect_facets_quick ();
201       _shells.push_back (_surface.begin ());
202     }
203     else
204     {
205       // Init shell index
206       _index = 0;
207 
208       // Collect all surface meshes from the alpha-shape in a fashion similar to ball-pivoting.
209       // Reset the facet handled markers.
210       for( All_cells_iterator cit = _shape->all_cells_begin(); cit != _shape->all_cells_end(); ++cit )
211         cit->info() = 0;
212 
213       if (_force_manifold)
214       {
215         // If manifold surface is wanted, small volumes (bubbles) are first detected in
216         // order to know which layer to ignore when collecting facets
217         detect_bubbles();
218       }
219 
220       collect_facets ();
221 
222       if (_force_manifold)
223       {
224         // Even when taking into account facets, some nonmanifold features might remain
225         fix_nonmanifold_edges();
226         fix_nonmanifold_vertices();
227       }
228     }
229 
230     for (Facet_iterator it = _surface.begin(); it != _surface.end(); ++ it)
231     {
232       std::array<std::size_t, 3> f = {{ std::size_t((*it)[0]), std::size_t((*it)[1]), std::size_t((*it)[2]) }};
233       *(output ++) = f;
234     }
235   }
236   /// \endcond
237 
238   /// gives the number of triangles of the surface.
number_of_triangles()239   std::size_t number_of_triangles() const { return _surface.size(); }
240 
241   /// gives an iterator to the first triple in the surface.
surface_begin()242   Facet_const_iterator surface_begin() const { return _surface.begin(); }
243   /// gives an iterator to the first triple in the surface.
244   /** \warning Changes to the surface may change its topology.
245    */
surface_begin()246   Facet_iterator surface_begin() { return _surface.begin(); }
247 
248   /// gives a past-the-end iterator of the triples in the surface.
surface_end()249   Facet_const_iterator surface_end() const { return _surface.end(); }
250   /// gives a past-the-end iterator of the triples in the surface.
251   /** \warning Changes to the surface may change its topology.
252    */
surface_end()253   Facet_iterator surface_end() { return _surface.end(); }
254 
255 
256   /// gives the number of shells of the surface.
number_of_shells()257   std::size_t number_of_shells() const {
258     return _shells.size();
259   }
260 
261   /// gives an iterator to the first triple in a given shell.
262   /** \param shell is the index of the shell to access.
263    *
264    *  \pre `shell` is in the range [ 0, `number_of_shells()` ).
265    */
shell_begin(std::size_t shell)266   Facet_const_iterator shell_begin( std::size_t shell ) const
267   {
268     CGAL_assertion( shell < _shells.size() );
269     return _shells[ shell ];
270   }
271   /// gives an iterator to the first triple in a given shell.
272   /** \param shell is the index of the shell to access.
273    *
274    *  \pre `shell` is in the range [ 0, `number_of_shells()` ).
275    *
276    *  \warning Changes to a shell may invalidate the topology of the surface.
277    */
shell_begin(std::size_t shell)278   Facet_iterator shell_begin( std::size_t shell )
279   {
280     CGAL_assertion( shell < _shells.size() );
281     return _shells[ shell ];
282   }
283 
284   /// gives a past-the-end iterator of the triples in a given shell.
285   /** \param shell is the index of the shell to access.
286    *
287    *  \pre `shell` is in the range [ 0, `number_of_shells()` ).
288    */
shell_end(std::size_t shell)289   Facet_const_iterator shell_end( std::size_t shell ) const
290   {
291     CGAL_assertion( shell < _shells.size() );
292     if( shell == _shells.size()-1 )
293       return _surface.end();
294     return _shells[ shell+1 ];
295   }
296 
297   /// gives a past-the-end iterator of the triples in a given shell.
298   /** \param shell is the index of the shell to access.
299    *
300    *  \pre `shell` is in the range [ 0, `number_of_shells()` ).
301    *
302    *  \warning Changes to a shell may invalidate the topology of the surface.
303    */
shell_end(std::size_t shell)304   Facet_iterator shell_end( std::size_t shell )
305   {
306     CGAL_assertion( shell < _shells.size() );
307     if( shell == _shells.size()-1 )
308         return _surface.end();
309     return _shells[ shell+1 ];
310   }
311 
312   /// gives an iterator to the first triple of the garbage facets
313   /// that may be discarded if 2-manifold output is required.
garbage_begin()314   Facet_const_iterator garbage_begin() const { return _garbage.begin(); }
315   /// gives an iterator to the first triple of the garbage facets
316   /// that may be discarded if 2-manifold output is required.
garbage_begin()317   Facet_iterator garbage_begin() { return _garbage.begin(); }
318 
319   /// gives a past-the-end iterator of the triples of the garbage facets
320   /// that may be discarded if 2-manifold output is required.
garbage_end()321   Facet_const_iterator garbage_end() const { return _garbage.end(); }
322   /// gives a past-the-end iterator of the triples of the garbage facets
323   /// that may be discarded if 2-manifold output is required.
garbage_end()324   Facet_iterator garbage_end() { return _garbage.end(); }
325 
326 private:
327 
deinit_shape()328   void deinit_shape()
329   {
330     if (_shape != nullptr)
331     {
332       delete _shape;
333       _shape = nullptr;
334     }
335   }
336 
clear_surface()337   void clear_surface()
338   {
339     _shells.clear();
340     _surface.clear();
341     _garbage.clear();
342     deinit_shape();
343   }
344 
collect_facets()345   void collect_facets ()
346   {
347     // We check each of the facets: if it is not handled and either regular or singular,
348     // we start collecting the next surface from here.
349     for (Finite_facets_iterator fit = _shape->finite_facets_begin(); fit != _shape->finite_facets_end(); ++fit)
350     {
351       switch(_shape->classify (*fit))
352       {
353         case Shape::REGULAR:
354           // Build a surface from the outer cell.
355           if (_shape->classify(fit->first) == Shape::EXTERIOR)
356             collect_shell (*fit);
357           else
358             collect_shell (_shape->mirror_facet (*fit));
359           break;
360         case Shape::SINGULAR:
361           // Build a surface from both incident cells.
362           collect_shell (*fit);
363           collect_shell (_shape->mirror_facet (*fit));
364           break;
365         default:
366           break;
367       }
368     }
369   }
370 
collect_facets_quick()371   void collect_facets_quick ()
372   {
373     // Collect all facets from the alpha-shape in an unordered fashion.
374     for (Finite_facets_iterator fit = _shape->finite_facets_begin(); fit != _shape->finite_facets_end(); ++fit)
375     {
376       switch (_shape->classify(*fit))
377       {
378         case Shape::REGULAR:
379           // Collect the outer cell.
380           if (_shape->classify(fit->first) == Shape::EXTERIOR)
381             _surface.push_back (ordered_facet_indices (*fit));
382           else
383             _surface.push_back (ordered_facet_indices (_shape->mirror_facet(*fit)));
384           break;
385         case Shape::SINGULAR:
386           // Collect both incident cells.
387           _surface.push_back (ordered_facet_indices (*fit));
388           _surface.push_back (ordered_facet_indices (_shape->mirror_facet (*fit)));
389           break;
390         default:
391           break;
392       }
393     }
394   }
395 
is_handled(Cell_handle c,unsigned int li)396   inline bool is_handled( Cell_handle c, unsigned int li ) const
397   {
398     switch( li ) {
399       case 0: return ( c->info()&1 ) != 0;
400       case 1: return ( c->info()&2 ) != 0;
401       case 2: return ( c->info()&4 ) != 0;
402       case 3: return ( c->info()&8 ) != 0;
403     }
404     return false;
405   }
is_handled(const SFacet & f)406   inline bool is_handled( const SFacet& f ) const { return is_handled( f.first, f.second ); }
407 
mark_handled(Cell_handle c,unsigned int li)408   inline void mark_handled( Cell_handle c, unsigned int li )
409   {
410     switch( li ) {
411       case 0: c->info() |= 1; return;
412       case 1: c->info() |= 2; return;
413       case 2: c->info() |= 4; return;
414       case 3: c->info() |= 8; return;
415     }
416   }
mark_handled(SFacet f)417   inline void mark_handled( SFacet f ) { mark_handled( f.first, f.second ); }
418 
mark_opposite_handled(SFacet f)419   inline void mark_opposite_handled( SFacet f )
420   {
421 
422     Classification_type cl = _shape->classify (f);
423 
424     // If cell is singular, simply mark mirror facet as handled
425     if (cl == Shape::SINGULAR)
426     {
427       SFacet mirror = _shape->mirror_facet (f);
428       mark_handled (mirror);
429     }
430     // If cell is regular, get corresponding bubble and mark
431     // facets of the other layer of the bubble as handled
432     else if (cl == Shape::REGULAR)
433     {
434       SFacet fac = (_shape->classify (f.first) == Shape::EXTERIOR)
435         ? f
436         : _shape->mirror_facet (f);
437 
438       typename std::map<SFacet, std::size_t>::iterator
439         search = _map_f2b.find (fac);
440 
441       if (search == _map_f2b.end ())
442         return;
443 
444       unsigned int layer = (_bubbles[search->second][0].find (fac) == _bubbles[search->second][0].end ())
445         ? 0 : 1;
446 
447       typename std::set<SFacet>::iterator it = _bubbles[search->second][layer].begin ();
448 
449       // If bubble has already been handled, no need to do it again
450       if (is_handled (*it))
451         return;
452 
453       for (;it != _bubbles[search->second][layer].end (); ++ it)
454       {
455         _garbage.push_back (ordered_facet_indices (*it));
456         mark_handled (*it);
457       }
458 
459     }
460 
461 
462   }
463 
464 
ordered_facet_indices(const SFacet & f)465   inline Facet ordered_facet_indices( const SFacet& f ) const
466   {
467     if( (f.second&1) == 0 )
468       return make_array<unsigned int>( f.first->vertex( (f.second+2)&3 )->info(),
469                                        f.first->vertex( (f.second+1)&3 )->info(),
470                                        f.first->vertex( (f.second+3)&3 )->info() );
471     else
472       return make_array<unsigned int>( f.first->vertex( (f.second+1)&3 )->info(),
473                                        f.first->vertex( (f.second+2)&3 )->info(),
474                                        f.first->vertex( (f.second+3)&3 )->info() );
475   }
476 
collect_shell(const SFacet & f)477   void collect_shell( const SFacet& f)
478   {
479     collect_shell (f.first, f.second);
480   }
collect_shell(Cell_handle c,unsigned int li)481   void collect_shell( Cell_handle c, unsigned int li)
482   {
483     // Collect one surface mesh from the alpha-shape in a fashion similar to ball-pivoting.
484     // Invariant: the facet is regular or singular.
485 
486 
487     // To stop stack overflows: use own stack.
488     std::stack<SFacet> stack;
489     stack.push( SFacet(c, li) );
490 
491     SFacet f;
492     Cell_handle n, p;
493     int ni, pi;
494     Vertex_handle a;
495     Classification_type cl;
496     bool processed = false;
497 
498     while( !stack.empty() ) {
499       f = stack.top();
500       stack.pop();
501 
502       // Check if the cell was already handled.
503       // Note that this is an extra check that in many cases is not necessary.
504       if( is_handled(f) )
505         continue;
506 
507       // The facet is part of the surface.
508       CGAL_assertion( !_shape->is_infinite(f) );
509       mark_handled(f);
510       // Output the facet as a triple of indices.
511       _surface.push_back( ordered_facet_indices(f) );
512       if( !processed ) {
513         if (_separate_shells || _shells.size () == 0)
514         {
515           _shells.push_back( --_surface.end() );
516           _index ++;
517         }
518         processed = true;
519       }
520 
521       // Save in which shell the facet is stored
522       _map_f2s[f] = _index-1;
523 
524       // If the surface is required to be manifold,
525       // the opposite layer should be ignored
526       if (_force_manifold)
527         mark_opposite_handled (f);
528 
529       // Pivot over each of the facet's edges and continue the surface at the next regular or singular facet.
530       for( int i = 0; i < 4; ++i ) {
531         // Skip the current facet.
532         if( i == f.second || is_handled(f.first, i) )
533           continue;
534 
535         // Rotate around the edge (starting from the shared facet in the current cell) until a regular or singular facet is found.
536         n = f.first;
537         ni = i;
538         a = f.first->vertex( f.second );
539         cl = _shape->classify( SFacet(n, ni) );
540 
541         while( cl != Shape::REGULAR && cl != Shape::SINGULAR ) {
542           p = n;
543           n = n->neighbor(ni);
544           ni = n->index(a);
545           pi = n->index(p);
546           a = n->vertex(pi);
547           cl = _shape->classify( SFacet(n, ni) );
548         }
549 
550         // Continue the surface at the next regular or singular facet.
551         stack.push( SFacet(n, ni) );
552       }
553 
554     }
555 
556   }
557 
detect_bubbles()558   void detect_bubbles ()
559   {
560     std::set<Cell_handle> done;
561 
562     unsigned int nb_facets_removed = 0;
563 
564     unsigned int nb_skipped = 0;
565     for (Cell_iterator cit = _shape->cells_begin (); cit != _shape->cells_end (); ++ cit)
566     {
567       if (_shape->is_infinite (cit))
568         continue;
569       if (_shape->classify (cit) != Shape::INTERIOR)
570         continue;
571       if (done.find (cit) != done.end ())
572         continue;
573 
574       std::set<VEdge> borders;
575       std::vector<Cell_handle> cells;
576       std::stack<Cell_handle> todo;
577       todo.push (cit);
578 
579       // Get all cells of volume and all borders
580       while (!(todo.empty ()))
581       {
582         Cell_handle c = todo.top ();
583         todo.pop ();
584 
585         if (!(done.insert (c).second))
586           continue;
587 
588         cells.push_back (c);
589 
590         for (unsigned int i = 0; i < 4; ++ i)
591         {
592           if (_shape->classify (c->neighbor (i)) == Shape::INTERIOR)
593             todo.push (c->neighbor (i));
594           else
595           {
596             // Test if edge is proper border
597             for (unsigned int j = 0; j < 3; ++ j)
598             {
599               unsigned int i0 = (i + j + 1)%4;
600               unsigned int i1 = (i + (j+1)%3 + 1)%4;
601               CGAL_assertion (i0 != i && i1 != i);
602               Edge edge (c, i0, i1);
603 
604               if (_shape->classify (edge) != Shape::REGULAR)
605                 continue;
606 
607               VEdge vedge = (c->vertex (i0) < c->vertex (i1))
608                 ? std::make_pair (c->vertex (i0), c->vertex (i1))
609                 : std::make_pair (c->vertex (i1), c->vertex (i0));
610 
611               if (borders.find (vedge) != borders.end ())
612                 continue;
613 
614               SFacet_circulator start = _shape->incident_facets (edge);
615               SFacet_circulator circ = start;
616               unsigned int cnt = 0;
617               do
618               {
619                 if (_shape->classify (*circ) == Shape::SINGULAR
620                     || _shape->classify (*circ) == Shape::REGULAR)
621                   ++ cnt;
622                 ++ circ;
623               }
624               while (circ != start);
625 
626               // If edge is non-manifold, use as border
627               if (cnt > 2)
628               {
629                 borders.insert (vedge);
630                 continue;
631               }
632 
633               // Else, if facets in cell are regular and angle is
634               // under _border_angle limit, use as border
635               SFacet f0 (c, i);
636               SFacet f1 (c, (i + (j+2)%3 + 1)%4);
637 
638               if (_shape->classify (f0) != Shape::REGULAR
639                   || _shape->classify (f1) != Shape::REGULAR)
640                 continue;
641 
642               double angle = Geom_traits().compute_approximate_dihedral_angle_3_object()(vedge.first->point (),
643                                                                                          vedge.second->point (),
644                                                                                          c->vertex (i)->point (),
645                                                                                          c->vertex ((i + (j+2)%3 + 1)%4)->point ());
646 
647               if (-_border_angle < angle && angle < _border_angle)
648               {
649                 borders.insert (vedge);
650               }
651             }
652 
653           }
654         }
655       }
656 
657       int layer = -1;
658 
659       // Try to generate bubble from the volume found
660       _bubbles.push_back (Bubble());
661       std::set<SFacet> done;
662       for (unsigned int c = 0; c < cells.size (); ++ c)
663       {
664         for (unsigned int ii = 0; ii < 4; ++ ii)
665         {
666           SFacet start = _shape->mirror_facet (SFacet (cells[c], ii));
667 
668           if (_shape->classify (start) != Shape::REGULAR)
669             continue;
670 
671           if (done.find (start) != done.end ())
672             continue;
673 
674           ++ layer;
675 
676           std::stack<SFacet> stack;
677           stack.push (start);
678 
679           SFacet f;
680           Cell_handle n, p;
681           int ni, pi;
682           Vertex_handle a;
683           Classification_type cl;
684 
685           // A bubble is well formed is the border contains one loop that
686           // separates two layers.
687           // If the number of layers is different than 2, the volume is completely ignored.
688           while( !stack.empty() )
689           {
690             f = stack.top();
691             stack.pop();
692 
693             if (!(done.insert (f).second))
694               continue;
695 
696             if (_shape->classify (f.first) == Shape::EXTERIOR)
697             {
698               if (layer < 2)
699               {
700                 _bubbles.back ()[layer].insert (f);
701                 _map_f2b[f] = _bubbles.size () - 1;
702               }
703               else
704               {
705                 nb_facets_removed ++;
706                 mark_handled (f);
707                 _garbage.push_back (ordered_facet_indices (f));
708               }
709             }
710             else
711             {
712               if (layer < 2)
713               {
714                 _bubbles.back ()[layer].insert (_shape->mirror_facet (f));
715                 _map_f2b[_shape->mirror_facet (f)] = _bubbles.size () - 1;
716               }
717               else
718               {
719                 nb_facets_removed ++;
720                 mark_handled (_shape->mirror_facet (f));
721                 _garbage.push_back (ordered_facet_indices (_shape->mirror_facet (f)));
722               }
723             }
724 
725 
726             for( int i = 0; i < 4; ++i )
727             {
728               // Skip the current facet.
729               if( i == f.second)
730                 continue;
731 
732               n = f.first;
733               ni = i;
734               a = f.first->vertex( f.second );
735               cl = _shape->classify( SFacet(n, ni) );
736 
737               int n0 = -1, n1 = -1;
738               bool n0found = false;
739               for (int j = 0; j < 4; ++ j)
740               {
741                 if (j != ni && j != f.second)
742                 {
743                   if (n0found)
744                   {
745                     n1 = j;
746                     break;
747                   }
748                   else
749                   {
750                     n0 = j;
751                     n0found = true;
752                   }
753                 }
754               }
755 
756               VEdge vedge = (n->vertex (n0) < n->vertex (n1))
757                 ? std::make_pair (n->vertex (n0), n->vertex (n1))
758                 : std::make_pair (n->vertex (n1), n->vertex (n0));
759 
760               // If the edge is a border, propagation stops in this direction.
761               if (borders.find (vedge) != borders.end ())
762                 continue;
763 
764               while( cl != Shape::REGULAR && cl != Shape::SINGULAR ) {
765                 p = n;
766                 n = n->neighbor(ni);
767                 ni = n->index(a);
768                 pi = n->index(p);
769                 a = n->vertex(pi);
770                 cl = _shape->classify( SFacet(n, ni) );
771               }
772 
773               stack.push (SFacet (n, ni));
774 
775             }
776 
777           }
778         }
779 
780       }
781 
782       // If number of layers is != 2, ignore volume and discard bubble
783       if (layer != 1)
784       {
785         nb_skipped ++;
786         for (unsigned int i = 0; i < 2; ++ i)
787           for (typename std::set<SFacet>::iterator fit = _bubbles.back()[i].begin ();
788                fit != _bubbles.back()[i].end (); ++ fit)
789           {
790             mark_handled (*fit);
791             _map_f2b.erase (*fit);
792             _garbage.push_back (ordered_facet_indices (*fit));
793             nb_facets_removed ++;
794           }
795         _bubbles.pop_back ();
796       }
797 
798     }
799   }
800 
801 
fix_nonmanifold_edges()802   void fix_nonmanifold_edges()
803   {
804 
805     typedef std::map<std::pair<VEdge, unsigned int>, std::set<Facet> > Edge_shell_map_triples;
806     typedef typename Edge_shell_map_triples::iterator Edge_shell_map_triples_iterator;
807 
808     unsigned int nb_facets_removed = 0;
809 
810     unsigned int nb_nm_edges = 0;
811 
812     // Store for each pair edge/shell the incident facets
813     Edge_shell_map_triples eshell_triples;
814     std::map<Facet, SFacet> map_t2f;
815 
816     for (typename Map_facet_to_shell::iterator fit = _map_f2s.begin ();
817          fit != _map_f2s.end (); ++ fit)
818     {
819       SFacet f = fit->first;
820       Facet t = ordered_facet_indices (f);
821       map_t2f[t] = f;
822 
823       for (unsigned int k = 0; k < 3; ++ k)
824       {
825         Vertex_handle v0 = f.first->vertex ((f.second + k + 1)%4);
826         Vertex_handle v1 = f.first->vertex ((f.second + (k+1)%3 + 1)%4);
827         VEdge vedge = (v0 < v1) ? std::make_pair (v0, v1) : std::make_pair (v1, v0);
828 
829         std::pair<Edge_shell_map_triples_iterator, bool>
830           search = eshell_triples.insert (std::make_pair (std::make_pair (vedge, fit->second),
831                                                           std::set<Facet>()));
832 
833         search.first->second.insert (t);
834       }
835     }
836 
837     for (Edge_shell_map_triples_iterator eit = eshell_triples.begin ();
838          eit != eshell_triples.end (); ++ eit)
839     {
840       // If an edge has more than 2 incident facets for one shell, it is non-manifold
841       if (eit->second.size () < 3)
842         continue;
843 
844       ++ nb_nm_edges;
845 
846       Facet_iterator tit = _shells[eit->first.second];
847       Facet_iterator end = (eit->first.second == _shells.size () - 1)
848         ? _surface.end () : _shells[eit->first.second + 1];
849 
850       // Remove facets until the edge is manifold in this shell
851       while (tit != end && eit->second.size () > 2)
852       {
853         Facet_iterator current = tit ++;
854 
855         typename std::set<Facet>::iterator search = eit->second.find (*current);
856 
857         if (search != eit->second.end ())
858         {
859           if (current == _shells[eit->first.second])
860             _shells[eit->first.second] = tit;
861 
862           _garbage.push_back (*current);
863           _map_f2s.erase (map_t2f[*current]);
864           _surface.erase (current);
865 
866           ++ nb_facets_removed;
867           eit->second.erase (search);
868         }
869 
870       }
871 
872     }
873   }
874 
875   template <typename T>
876   struct operator_less
877   {
operatoroperator_less878     bool operator() (const T& a, const T& b) const
879     {
880       return &*a < &*b;
881     }
882   };
883 
884 
find_two_other_vertices(const SFacet & f,Vertex_handle v,Vertex_handle & v1,Vertex_handle & v2)885   void find_two_other_vertices(const SFacet& f, Vertex_handle v,
886                                Vertex_handle& v1, Vertex_handle& v2)
887   {
888     Vertex_handle vother = f.first->vertex (f.second);
889     bool v1found = false;
890 
891     for (unsigned int i = 0; i < 4; ++ i)
892     {
893       Vertex_handle vi = f.first->vertex (i);
894       if (vi != v && vi != vother)
895       {
896         if (v1found)
897         {
898           v2 = vi;
899           return;
900         }
901         else
902         {
903           v1 = vi;
904           v1found = true;
905         }
906       }
907     }
908   }
909 
fix_nonmanifold_vertices()910   void fix_nonmanifold_vertices()
911   {
912 
913     typedef ::CGAL::Union_find<SFacet> UF;
914     typedef typename UF::handle UF_handle;
915 
916 
917     typedef std::map<std::pair<Vertex_handle, unsigned int>, std::vector<SFacet> > Vertex_shell_map_facets;
918     typedef typename Vertex_shell_map_facets::iterator Vertex_shell_map_facet_iterator;
919 
920     // For faster facet removal, we sort the triples of each shell as a preprocessing
921     for (unsigned int i = 0; i < _shells.size (); ++ i)
922     {
923       Facet_iterator begin = _shells[i];
924       Facet_iterator end = (i+1 == _shells.size ()) ? _surface.end () : _shells[i+1];
925 
926       Facetset tmp;
927       tmp.splice (tmp.end(), _surface, begin, end);
928 
929       tmp.sort();
930       _shells[i] = tmp.begin ();
931       _surface.splice(end, tmp, tmp.begin(), tmp.end());
932     }
933 
934     unsigned int nb_facets_removed = 0;
935     unsigned int nb_nm_vertices = 0;
936     // Removing facets to fix non-manifold vertices might make some other vertices
937     // become non-manifold, therefore we iterate until no facet needs to be removed.
938     do
939     {
940       nb_nm_vertices = 0;
941       nb_facets_removed = 0;
942 
943       // Store for each pair vertex/shell the incident facets
944       Vertex_shell_map_facets vshell_facets;
945 
946       for (typename Map_facet_to_shell::iterator fit = _map_f2s.begin ();
947            fit != _map_f2s.end (); ++ fit)
948       {
949         SFacet f = fit->first;
950 
951         for (unsigned int k = 0; k < 3; ++ k)
952         {
953           Vertex_handle v = f.first->vertex ((f.second+k+1)%4);
954 
955           std::pair<Vertex_shell_map_facet_iterator, bool>
956             search = vshell_facets.insert (std::make_pair (std::make_pair (v, fit->second),
957                                                            std::vector<SFacet>()));
958           search.first->second.push_back (f);
959 
960         }
961 
962       }
963 
964       for (Vertex_shell_map_facet_iterator fit = vshell_facets.begin ();
965            fit != vshell_facets.end (); ++ fit)
966       {
967         if (fit->second.size () < 2)
968           continue;
969 
970         Vertex_handle vit = fit->first.first;
971         unsigned int shell = fit->first.second;
972 
973         UF uf;
974         std::map<SFacet, UF_handle> map_f2h;
975 
976         for (unsigned int i = 0; i < fit->second.size (); ++ i)
977           map_f2h.insert (std::make_pair (fit->second[i], uf.make_set (fit->second[i])));
978 
979         std::map<Vertex_handle, SFacet> map_v2f;
980 
981         for (unsigned int i = 0; i < fit->second.size (); ++ i)
982         {
983           Vertex_handle v1, v2;
984           find_two_other_vertices (fit->second[i], vit, v1, v2);
985           std::pair<typename std::map<Vertex_handle, SFacet>::iterator, bool>
986             insertion1 = map_v2f.insert (std::make_pair (v1, fit->second[i]));
987           if (!(insertion1.second))
988             uf.unify_sets (map_f2h[fit->second[i]], map_f2h[insertion1.first->second]);
989           std::pair<typename std::map<Vertex_handle, SFacet>::iterator, bool>
990             insertion2 = map_v2f.insert (std::make_pair (v2, fit->second[i]));
991           if (!(insertion2.second))
992             uf.unify_sets (map_f2h[fit->second[i]], map_f2h[insertion2.first->second]);
993         }
994 
995         if (uf.number_of_sets () > 1)
996         {
997           ++ nb_nm_vertices;
998 
999           typedef std::map<UF_handle, std::vector<SFacet>, operator_less<UF_handle> > Map_uf_sets;
1000           Map_uf_sets map_h2f;
1001           for (unsigned int i = 0; i < fit->second.size (); ++ i)
1002           {
1003             UF_handle handle = uf.find (map_f2h[fit->second[i]]);
1004 
1005             std::pair<typename Map_uf_sets::iterator, bool>
1006               insertion = map_h2f.insert (std::make_pair (handle, std::vector<SFacet>()));
1007 
1008             insertion.first->second.push_back (fit->second[i]);
1009           }
1010 
1011           typename Map_uf_sets::iterator largest = map_h2f.end ();
1012           std::size_t nb_largest = 0;
1013           for (typename Map_uf_sets::iterator ufit = map_h2f.begin (); ufit != map_h2f.end (); ++ ufit)
1014           {
1015             std::size_t size = ufit->second.size ();
1016             if (size > nb_largest)
1017             {
1018               nb_largest = size;
1019               largest = ufit;
1020             }
1021           }
1022 
1023           std::vector<Facet> triples;
1024 
1025           for (typename Map_uf_sets::iterator ufit = map_h2f.begin (); ufit != map_h2f.end (); ++ ufit)
1026           {
1027             if (ufit == largest)
1028               continue;
1029             for (unsigned int i = 0; i < ufit->second.size (); ++ i)
1030             {
1031               _map_f2s.erase (ufit->second[i]);
1032               triples.push_back (ordered_facet_indices (ufit->second[i]));
1033             }
1034           }
1035           std::sort (triples.begin (), triples.end ());
1036 
1037           Facet_iterator tit = _shells[shell];
1038           Facet_iterator end = (shell == _shells.size () - 1)
1039             ? _surface.end () : _shells[shell + 1];
1040 
1041           unsigned int tindex = 0;
1042 
1043           while (tit != end && tindex < triples.size ())
1044           {
1045             Facet_iterator current = tit ++;
1046 
1047             if (*current == triples[tindex])
1048             {
1049               if (current == _shells[shell])
1050                 _shells[shell] = tit;
1051 
1052               _garbage.push_back (*current);
1053               _surface.erase (current);
1054 
1055               ++ nb_facets_removed;
1056               ++ tindex;
1057             }
1058 
1059           }
1060         }
1061 
1062       }
1063 
1064     }
1065     while (nb_nm_vertices != 0);
1066 
1067   }
1068 
1069 };
1070 
1071 
1072 } // namespace Scale_space_reconstruction_3
1073 
1074 } // namespace CGAL
1075 
1076 #endif // CGAL_SCALE_SPACE_RECONSTRUCTION_3_ALPHA_SHAPE_MESHER_H
1077