1 // Copyright (c) 2014 GeometryFactory (France). All rights reserved.
2 // All rights reserved.
3 //
4 // This file is part of CGAL (www.cgal.org)
5 //
6 // $URL: https://github.com/CGAL/cgal/blob/v5.3/BGL/include/CGAL/boost/graph/helpers.h $
7 // $Id: helpers.h 5bd28b4 2020-07-29T10:24:02+02:00 Mael Rouxel-Labbé
8 // SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
9 //
10 // Author(s) : Andreas Fabri
11 
12 #ifndef CGAL_BOOST_GRAPH_HELPERS_H
13 #define CGAL_BOOST_GRAPH_HELPERS_H
14 
15 #include <CGAL/boost/graph/iterator.h>
16 #include <CGAL/boost/graph/properties.h>
17 #include <CGAL/boost/graph/internal/Has_member_clear.h>
18 #include <CGAL/function_objects.h>
19 #include <CGAL/IO/Verbose_ostream.h>
20 
21 #include <boost/range/empty.hpp>
22 
23 namespace CGAL {
24 
25 /*!
26    \ingroup PkgBGLHelperFct
27     returns `true` if the halfedge `hd` is on a border.
28   */
29 template <typename FaceGraph>
is_border(typename boost::graph_traits<FaceGraph>::halfedge_descriptor hd,const FaceGraph & g)30 bool is_border(typename boost::graph_traits<FaceGraph>::halfedge_descriptor hd, const FaceGraph& g)
31 {
32   return face(hd,g) == boost::graph_traits<FaceGraph>::null_face();
33 }
34 
35  /*!
36    \ingroup PkgBGLHelperFct
37     returns `true` if the halfedge `hd` or the opposite halfedge is on a border.
38   */
39 template <typename FaceGraph>
is_border_edge(typename boost::graph_traits<FaceGraph>::halfedge_descriptor hd,const FaceGraph & g)40 bool is_border_edge(typename boost::graph_traits<FaceGraph>::halfedge_descriptor hd, const FaceGraph& g)
41 {
42   return is_border(hd, g) || is_border(opposite(hd,g), g);
43 }
44 
45  /*!
46    \ingroup PkgBGLHelperFct
47     returns `true` if the edge `e` is on a border.
48   */
49 template <typename FaceGraph>
is_border(typename boost::graph_traits<FaceGraph>::edge_descriptor ed,const FaceGraph & g)50 bool is_border(typename boost::graph_traits<FaceGraph>::edge_descriptor ed, const FaceGraph& g)
51 {
52   return is_border_edge(halfedge(ed,g), g);
53 }
54 
55  /*!
56    \ingroup PkgBGLHelperFct
57     returns a halfedge which is on a border and whose target vertex is `vd`, if such a halfedge exists.
58   */
59 template <typename FaceGraph>
60 boost::optional<typename boost::graph_traits<FaceGraph>::halfedge_descriptor>
is_border(typename boost::graph_traits<FaceGraph>::vertex_descriptor vd,const FaceGraph & g)61 is_border(typename boost::graph_traits<FaceGraph>::vertex_descriptor vd,
62           const FaceGraph& g)
63 {
64   CGAL::Halfedge_around_target_iterator<FaceGraph> havib, havie;
65   for(boost::tie(havib, havie) = halfedges_around_target(halfedge(vd, g), g); havib != havie; ++havib) {
66     if(is_border(*havib,g)) {
67       typename boost::graph_traits<FaceGraph>::halfedge_descriptor h = *havib;
68       return h;
69     }
70   }
71   // empty
72   return boost::optional<typename boost::graph_traits<FaceGraph>::halfedge_descriptor>();
73 }
74 
75 
76  /*!
77    \ingroup PkgBGLHelperFct
78     returns `true` if there are no border edges.
79   */
80 template <typename FaceGraph>
is_closed(const FaceGraph & g)81 bool is_closed(const FaceGraph& g)
82 {
83   typedef typename boost::graph_traits<FaceGraph>::halfedge_descriptor halfedge_descriptor;
84   for(halfedge_descriptor hd : halfedges(g)){
85     if(is_border(hd,g)){
86       return false;
87     }
88   }
89   return true;
90 }
91 
92   /*!
93    \ingroup PkgBGLHelperFct
94     returns `true` if the target of `hd` has exactly two incident edges.
95   */
96 template <typename FaceGraph>
is_bivalent(typename boost::graph_traits<FaceGraph>::halfedge_descriptor hd,const FaceGraph & g)97 bool is_bivalent(typename boost::graph_traits<FaceGraph>::halfedge_descriptor hd, const FaceGraph& g)
98 {
99   return hd == opposite(next(opposite(next(hd,g),g),g),g);
100 }
101 
102   /*!
103    \ingroup PkgBGLHelperFct
104     returns `true` if all vertices have exactly two incident edges.
105   */
106 template <typename FaceGraph>
is_bivalent_mesh(const FaceGraph & g)107   bool is_bivalent_mesh(const FaceGraph& g)
108 {
109   typedef typename boost::graph_traits<FaceGraph>::vertex_descriptor vertex_descriptor;
110   typedef typename boost::graph_traits<FaceGraph>::halfedge_descriptor halfedge_descriptor;
111   for(vertex_descriptor vd : vertices(g)){
112     halfedge_descriptor hd = halfedge(vd,g);
113     if((hd == boost::graph_traits<FaceGraph>::null_halfedge()) ||
114        (! is_bivalent(hd,g))){
115       return false;
116     }
117   }
118   return true;
119 }
120 
121   /*!
122    \ingroup PkgBGLHelperFct
123     returns `true` if the target of `hd` has exactly three incident edges.
124   */
125 template <typename FaceGraph>
is_trivalent(typename boost::graph_traits<FaceGraph>::halfedge_descriptor hd,const FaceGraph & g)126 bool is_trivalent(typename boost::graph_traits<FaceGraph>::halfedge_descriptor hd, const FaceGraph& g)
127 {
128   return hd == opposite(next(opposite(next(opposite(next(hd,g),g),g),g),g),g);
129 }
130 
131   /*!
132    \ingroup PkgBGLHelperFct
133     returns `true` if all
134     vertices have exactly three incident edges.
135   */
136 template <typename FaceGraph>
is_trivalent_mesh(const FaceGraph & g)137   bool is_trivalent_mesh(const FaceGraph& g)
138 {
139   typedef typename boost::graph_traits<FaceGraph>::vertex_descriptor vertex_descriptor;
140   typedef typename boost::graph_traits<FaceGraph>::halfedge_descriptor halfedge_descriptor;
141   for(vertex_descriptor vd : vertices(g)){
142     halfedge_descriptor hd = halfedge(vd,g);
143     if((hd == boost::graph_traits<FaceGraph>::null_halfedge()) ||
144        (! is_trivalent(halfedge(hd,g),g))){
145       return false;
146     }
147   }
148   return true;
149 }
150 
151  /*!
152    \ingroup PkgBGLHelperFct
153     returns `true` iff the connected component denoted by `hd` is a triangle.
154     \pre `g` must be valid.
155   */
156 template <typename FaceGraph>
is_isolated_triangle(typename boost::graph_traits<FaceGraph>::halfedge_descriptor hd,const FaceGraph & g)157   bool is_isolated_triangle(typename boost::graph_traits<FaceGraph>::halfedge_descriptor hd, const FaceGraph& g)
158 {
159   typedef typename boost::graph_traits<FaceGraph>::halfedge_descriptor halfedge_descriptor;
160   halfedge_descriptor beg = hd;
161   if(is_border(hd,g)) return false;
162   for(int i=0; i<3;i++){
163     if(! is_border(opposite(hd,g),g)) return false;
164     hd = next(hd,g);
165   }
166   return hd == beg;
167 }
168 
169  /*!
170    \ingroup PkgBGLHelperFct
171     returns `true` iff the face denoted by `hd` is a triangle, that is it has three incident halfedges.
172  */
173 template <typename FaceGraph>
is_triangle(typename boost::graph_traits<FaceGraph>::halfedge_descriptor hd,const FaceGraph & g)174 bool is_triangle(typename boost::graph_traits<FaceGraph>::halfedge_descriptor hd, const FaceGraph& g)
175 {
176   return hd == next(next(next(hd,g),g),g);
177 }
178 
179   /*!
180    \ingroup PkgBGLHelperFct
181     returns `true` if all faces are triangles.
182   */
183 template <typename FaceGraph>
is_triangle_mesh(const FaceGraph & g)184   bool is_triangle_mesh(const FaceGraph& g)
185 {
186   typedef typename boost::graph_traits<FaceGraph>::face_descriptor face_descriptor;
187   for(face_descriptor fd : faces(g)){
188     if(! is_triangle(halfedge(fd,g),g)){
189       return false;
190     }
191   }
192   return true;
193 }
194 
195 /*!
196    \ingroup PkgBGLHelperFct
197     returns `true` iff the connected component denoted by `hd` is a quadrilateral.
198   */
199 template <typename FaceGraph>
is_isolated_quad(typename boost::graph_traits<FaceGraph>::halfedge_descriptor hd,const FaceGraph & g)200 bool is_isolated_quad(typename boost::graph_traits<FaceGraph>::halfedge_descriptor hd, const FaceGraph& g)
201 {
202  typedef typename boost::graph_traits<FaceGraph>::halfedge_descriptor halfedge_descriptor;
203   halfedge_descriptor beg = hd;
204   if(is_border(hd,g)) return false;
205   for(int i=0; i<4;i++){
206     if(! is_border(opposite(hd,g),g)) return false;
207     hd = next(hd,g);
208   }
209   return hd == beg;
210 }
211 
212 
213  /*!
214    \ingroup PkgBGLHelperFct
215     returns `true` iff the face denoted by `hd` is a quad, that is it has four incident halfedges.
216  */
217 template <typename FaceGraph>
is_quad(typename boost::graph_traits<FaceGraph>::halfedge_descriptor hd,const FaceGraph & g)218 bool is_quad(typename boost::graph_traits<FaceGraph>::halfedge_descriptor hd, const FaceGraph& g)
219 {
220   return hd == next(next(next(next(hd,g),g),g),g);
221 }
222 
223   /*!
224    \ingroup PkgBGLHelperFct
225     returns `true` if all faces are quadrilaterals.
226   */
227 template <typename FaceGraph>
is_quad_mesh(const FaceGraph & g)228   bool is_quad_mesh(const FaceGraph& g)
229 {
230     typedef typename boost::graph_traits<FaceGraph>::face_descriptor face_descriptor;
231   for(face_descriptor fd : faces(g)){
232     if(! is_quad(halfedge(fd,g),g)){
233       return false;
234     }
235   }
236   return true;
237 }
238 
239   /*!
240    \ingroup PkgBGLHelperFct
241     returns `true` iff the connected component denoted by `hd` is a tetrahedron.
242   */
243 template <typename FaceGraph>
is_tetrahedron(typename boost::graph_traits<FaceGraph>::halfedge_descriptor hd,const FaceGraph & g)244 bool is_tetrahedron( typename boost::graph_traits<FaceGraph>::halfedge_descriptor hd, const FaceGraph& g)
245 {
246   typedef typename boost::graph_traits<FaceGraph>::halfedge_descriptor halfedge_descriptor;
247 
248   halfedge_descriptor h1 = hd;
249   if(is_border(h1,g)) return false;
250   typedef typename boost::graph_traits<FaceGraph>::halfedge_descriptor halfedge_descriptor;
251   halfedge_descriptor h2 = next(h1,g);
252   halfedge_descriptor h3 = next(h2,g);
253   halfedge_descriptor h4 = next(opposite(h1,g),g );
254   halfedge_descriptor h5 = next(opposite(h2,g),g );
255   halfedge_descriptor h6 = next(opposite(h3,g),g );
256   // check halfedge combinatorics.
257   // at least three edges at vertices 1, 2, 3.
258   if ( h4 == opposite(h3,g) ) return false;
259   if ( h5 == opposite(h1,g) ) return false;
260   if ( h6 == opposite(h2,g) ) return false;
261   // exact three edges at vertices 1, 2, 3.
262   if ( next(opposite(h4,g),g) != opposite(h3,g) ) return false;
263   if ( next(opposite(h5,g),g) != opposite(h1,g) ) return false;
264   if ( next(opposite(h6,g),g) != opposite(h2,g) ) return false;
265   // three edges at v4.
266   if ( opposite(next(h4,g),g) != h5 ) return false;
267   if ( opposite(next(h5,g),g) != h6 ) return false;
268   if ( opposite(next(h6,g),g) != h4 ) return false;
269   // All facets are triangles.
270   if ( next(next(next(h1,g),g),g) != h1 ) return false;
271   if ( next(next(next(h4,g),g),g) != h4 ) return false;
272   if ( next(next(next(h5,g),g),g) != h5 ) return false;
273   if ( next(next(next(h6,g),g),g) != h6 ) return false;
274   // all edges are non-border edges.
275   if ( is_border(h1,g) ) return false;  // implies h2 and h3
276   if ( is_border(h4,g) ) return false;
277   if ( is_border(h5,g) ) return false;
278   if ( is_border(h6,g) ) return false;
279   return true;
280   }
281 
282 template <typename FaceGraph>
is_valid_halfedge_descriptor(typename boost::graph_traits<FaceGraph>::halfedge_descriptor h,const FaceGraph & g)283 bool is_valid_halfedge_descriptor( typename boost::graph_traits<FaceGraph>::halfedge_descriptor h, const FaceGraph& g)
284 {
285   typedef typename boost::graph_traits<FaceGraph>::halfedge_descriptor halfedge_descriptor;
286   typedef typename boost::graph_traits<FaceGraph>::face_descriptor face_descriptor;
287   face_descriptor f = face(h,g);
288   halfedge_descriptor done(h);
289   do{
290     if(face(h,g) != f){
291       std::cerr << "halfedge " << h << " is invalid\n";
292       return false;
293     }
294     halfedge_descriptor hn = h;
295     hn = next(h,g);
296     if(prev(hn,g) != h){
297       std::cerr << "halfedge " << h << " is invalid\n";
298       return false;
299     }
300     h = hn;
301   } while(h != done);
302   return true;
303 }
304 
305 template <typename FaceGraph>
is_valid_vertex_descriptor(typename boost::graph_traits<FaceGraph>::vertex_descriptor v,const FaceGraph & g)306 bool is_valid_vertex_descriptor( typename boost::graph_traits<FaceGraph>::vertex_descriptor v, const FaceGraph& g)
307 {
308   typedef typename boost::graph_traits<FaceGraph>::halfedge_descriptor halfedge_descriptor;
309   halfedge_descriptor h = halfedge(v,g), done(h);
310   if(h == boost::graph_traits<FaceGraph>::null_halfedge()){
311     return true;
312   }
313   do{
314     if(target(h,g) != v){
315       std::cerr << "vertex " << v << " is invalid\n";
316       return false;
317     }
318     h = opposite(next(h,g),g);
319   }while(h != done);
320   return true;
321 }
322 
323 template <typename FaceGraph>
is_valid_face_descriptor(typename boost::graph_traits<FaceGraph>::face_descriptor f,const FaceGraph & g)324 bool is_valid_face_descriptor( typename boost::graph_traits<FaceGraph>::face_descriptor f, const FaceGraph& g)
325 {
326   typedef typename boost::graph_traits<FaceGraph>::halfedge_descriptor halfedge_descriptor;
327 
328   halfedge_descriptor h = halfedge(f,g);
329   if(face(h,g) != f){
330     std::cerr << "face " << f << " is invalid\n";
331     return false;
332   }
333   return true;
334 }
335 
336 /*!
337   \ingroup PkgBGLHelperFct
338  * \brief checks the integrity of `g`.
339  *
340  * `g` is valid if it follows the rules of the `HalfedgeListGraph` concept,
341  * and all of its associations are reciprocal.
342  * For example, `prev(next(h, g), g)` must be `h`,
343  * and `next(prev(h, g), g)` must be `h`.
344  *
345  * \param g the `Graph` to test.
346  * \param verb if `true`, the details of the check will be written in the standard output.
347  *
348  * \tparam Graph a model of `HalfedgeListGraph`
349  *
350  * \return `true` if `g` is valid, `false` otherwise.
351  *
352  */
353 template<typename Graph>
354 bool is_valid_halfedge_graph(const Graph& g, bool verb = false)
355 {
356   typedef typename boost::graph_traits<Graph>::vertex_descriptor     vertex_descriptor;
357   typedef typename boost::graph_traits<Graph>::vertices_size_type    vertex_size_type;
358   typedef typename boost::graph_traits<Graph>::halfedge_descriptor   halfedge_descriptor;
359   typedef typename boost::graph_traits<Graph>::halfedges_size_type   halfedges_size_type;
360 
361   Verbose_ostream verr(verb);
362   std::size_t num_v(std::distance(boost::begin(vertices(g)), boost::end(vertices(g)))),
363               num_e(std::distance(boost::begin(edges(g)), boost::end(edges(g)))),
364               num_h(std::distance(boost::begin(halfedges(g)), boost::end(halfedges(g))));
365 
366   bool valid = (1 != (num_h&1) && (2*num_e == num_h));
367   if(!valid)
368   {
369     verr << "number of halfedges is odd." << std::endl;
370     verr << "Halfedge Graph Structure is NOT VALID." << std::endl;
371     return false;
372   }
373 
374   // All halfedges.
375   halfedges_size_type n = 0;
376   for(halfedge_descriptor begin : halfedges(g))
377   {
378     // Pointer integrity.
379     valid = (next(begin, g) != boost::graph_traits<Graph>::null_halfedge());
380     valid = valid && (opposite(begin, g) != boost::graph_traits<Graph>::null_halfedge());
381     if(!valid)
382     {
383       verr << "halfedge " << n << " next / opposite halfedges are null." << std::endl;
384       verr << "Halfedge Graph Structure is NOT VALID." << std::endl;
385       return false;
386     }
387 
388     // edge integrity
389     valid = (halfedge(edge(begin, g), g) == begin);
390 
391     // opposite integrity.
392     valid = valid && (opposite(begin, g) != begin);
393     valid = valid && (opposite(opposite(begin, g), g) == begin);
394     if(!valid)
395     {
396       verr << "halfedge " << n << " invalid halfedge opposite()." << std::endl;
397       verr << "Halfedge Graph Structure is NOT VALID." << std::endl;
398       return false;
399     }
400 
401     // previous integrity.
402     valid = (prev(next(begin, g), g) == begin);
403     valid = valid && (next(prev(begin, g), g) == begin);
404     if(!valid)
405     {
406       verr << "halfedge " << n << " prev(next(hd)) != hd OR next(prev(hd)) != hd" << std::endl;
407       verr << "Halfedge Graph Structure is NOT VALID." << std::endl;
408       return false;
409     }
410 
411     // vertex integrity.
412     valid = (target(begin, g) != boost::graph_traits<Graph>::null_vertex());
413     if(!valid)
414     {
415       verr << "halfedge " << n << " target of halfedge is the null vertex." << std::endl;
416       verr << "Halfedge Graph Structure is NOT VALID." << std::endl;
417       return false;
418     }
419 
420     valid = (target(begin, g) == target(opposite(next(begin, g), g), g));
421     if(!valid)
422     {
423       verr << "halfedge " << n << " target(hd) != source(next(hd))." << std::endl;
424       verr << "Halfedge Graph Structure is NOT VALID." << std::endl;
425       return false;
426     }
427 
428     ++n;
429   }
430 
431   valid = (n == num_h);
432   if(!valid)
433   {
434     verr << "counting halfedges failed." << std::endl;
435     verr << "Halfedge Graph Structure is NOT VALID." << std::endl;
436     return false;
437   }
438 
439   // All vertices.
440   vertex_size_type v = 0;
441   n = 0;
442   for(vertex_descriptor vbegin : vertices(g))
443   {
444     // Pointer integrity.
445     if(halfedge(vbegin, g) != boost::graph_traits<Graph>::null_halfedge())
446       valid = (target(halfedge(vbegin, g), g) == vbegin);
447     else
448       valid = false;
449 
450     if(!valid)
451     {
452       verr << "vertex " << v << " halfedge incident to vertex is the null halfedge." << std::endl;
453       verr << "Halfedge Graph Structure is NOT VALID." << std::endl;
454       return false;
455     }
456 
457     // cycle-around-vertex test.
458     halfedge_descriptor h = halfedge(vbegin, g);
459     if(h != boost::graph_traits<Graph>::null_halfedge())
460     {
461       halfedge_descriptor ge = h;
462       do
463       {
464         ++n;
465         h = opposite(next(h, g), g);
466         valid = (n <= num_h && n != 0);
467         if(!valid)
468         {
469           verr << "vertex " << v << " too many halfedges around vertex." << std::endl;
470           verr << "Halfedge Graph Structure is NOT VALID." << std::endl;
471           return false;
472         }
473       }
474       while(h != ge);
475     }
476 
477     ++v;
478   }
479 
480   valid = (v == num_v);
481   if(!valid)
482   {
483     verr << "counting vertices failed." << std::endl;
484     verr << "Halfedge Graph Structure is NOT VALID." << std::endl;
485     return false;
486   }
487 
488   valid = (n == num_h);
489   if(!valid)
490   {
491     verr << "counting halfedges via vertices failed." << std::endl;
492     verr << "Halfedge Graph Structure is NOT VALID." << std::endl;
493     return false;
494   }
495 
496   // All halfedges.
497   n = 0;
498   for(halfedge_descriptor i : halfedges(g))
499   {
500     // At least triangular facets and distinct geometry.
501     valid = (next(i, g) != i) && (target(i, g) != target(opposite(i, g), g));
502     if(!valid)
503     {
504       verr << "halfedge " << n << " pointer validity corrupted." << std::endl;
505       verr << "Halfedge Graph Structure is NOT VALID." << std::endl;
506       return false;
507     }
508 
509     ++n;
510   }
511 
512   valid = (n == num_h);
513   if(!valid)
514     verr << "counting halfedges failed." << std::endl;
515 
516   verr << "Halfedge Graph Structure is " << (valid ? "valid." : "NOT VALID.") << std::endl;
517 
518   return valid;
519 }
520 
521 /*!
522   \ingroup PkgBGLHelperFct
523  * \brief checks the integrity of `g`.
524  *
525  * `g` is valid if it is a valid `HalfedgeListGraph`, if it follows the rules
526  * of the `FaceListGraph` concept, and all of its associations are reciprocal.
527  * For example, `face(halfedge(f,g),g)` must be `f`.
528  * calls `is_valid_halfedge_graph()`
529  *
530  * \param g the `Graph` to test.
531  * \param verb if `true`, the details of the check will be written in the standard output.
532  *
533  * \tparam Graph a model of `FaceListGraph`
534  *
535  * \return `true` if `g` is valid, `false` otherwise.
536  *
537  * \see `is_valid_halfedge_graph()`
538  */
539 template<typename Graph>
540 bool is_valid_face_graph(const Graph& g, bool verb = false)
541 {
542   typedef typename boost::graph_traits<Graph>::halfedge_descriptor   halfedge_descriptor;
543   typedef typename boost::graph_traits<Graph>::halfedges_size_type   halfedges_size_type;
544   typedef typename boost::graph_traits<Graph>::face_descriptor       face_descriptor;
545   typedef typename boost::graph_traits<Graph>::faces_size_type       faces_size_type;
546 
547   Verbose_ostream verr(verb);
548 
549   std::size_t num_f(std::distance(boost::begin(faces(g)), boost::end(faces(g)))),
550               num_h(std::distance(boost::begin(halfedges(g)), boost::end(halfedges(g))));
551 
552   faces_size_type f = 0;
553   std::size_t n = 0;
554   std::size_t hn = 0;
555   halfedges_size_type nb = 0;
556 
557   //is valid halfedge_graph ?
558   bool valid = is_valid_halfedge_graph(g, verb);
559   if(!valid)
560     return false;
561 
562   // All faces.
563   for(face_descriptor fbegin : faces(g))
564   {
565     // Pointer integrity.
566     if(halfedge(fbegin, g) != boost::graph_traits<Graph>::null_halfedge())
567       valid = (face(halfedge(fbegin, g), g) == fbegin);
568     else
569       valid = false;
570 
571     if(!valid)
572     {
573       verr << "face " << f << " halfedge incident to face is the null halfedge." << std::endl;
574       verr << "Face Graph Structure is NOT VALID." << std::endl;
575       return false;
576     }
577 
578     // cycle-around-face test.
579     halfedge_descriptor h = halfedge( fbegin, g);
580     if(h != boost::graph_traits<Graph>::null_halfedge())
581     {
582       halfedge_descriptor ge = h;
583       do
584       {
585         ++n;
586         h = next(h, g);
587         valid = (n <= num_h && n != 0);
588         if(!valid)
589         {
590           verr << "face " << f << " too many halfedges around face." << std::endl;
591           verr << "Face Graph Structure is NOT VALID." << std::endl;
592           return false;
593         }
594       }
595       while(h != ge);
596     }
597 
598     ++f;
599   }
600 
601   valid = (f == num_f);
602   if(!valid)
603   {
604     verr << "counting faces failed." << std::endl;
605     verr << "Face Graph Structure is NOT VALID." << std::endl;
606     return false;
607   }
608 
609   for(halfedge_descriptor i : halfedges(g))
610   {
611     ++hn;
612 
613     //counting borders
614     if(is_border(i, g))
615       ++nb;
616 
617     // face integrity.
618     valid = (face(i, g) == face(next(i, g), g));
619     if(!valid)
620     {
621       verr << "halfedge " << hn << " face(hd) != face(next(hd))." << std::endl;
622       verr << "Face Graph Structure is NOT VALID." << std::endl;
623       return false;
624     }
625   }
626 
627   valid = (n + nb == num_h);
628   if(!valid)
629   {
630     verr << "sum border halfedges (2*nb) = " << 2 * nb << std::endl;
631     verr << "counting halfedges via faces failed." << std::endl;
632     verr << "Face Graph Structure is NOT VALID." << std::endl;
633     return false;
634   }
635 
636   valid = (f == num_f);
637   if(!valid)
638     verr << "counting faces failed." << std::endl;
639 
640   verr << "Face Graph Structure is " << (valid ? "valid." : "NOT VALID.") << std::endl;
641 
642   return valid;
643 }
644 
645 /*!
646   \ingroup PkgBGLHelperFct
647  * \brief checks the integrity of `g`.
648  *
649  * `g` is valid if it is a valid `FaceListGraph` and it has distinct faces on each side of an edge.
650  * calls `is_valid_face_graph()`.
651  *
652  * \param g the `Mesh` to test.
653  * \param verb : if `true`, the details of the check will be written in the standard output.
654  *
655  * \tparam Mesh a model of `FaceListGraph` and `HalfedgeListGraph`, and follows
656  * the definition of a \ref PMPDef "PolygonMesh"
657  * \return `true` if `g` is valid, `false` otherwise.
658  *
659  * \see `is_valid_face_graph()`
660  * \see `is_valid_halfedge_graph()`
661  *
662  */
663 template <typename Mesh>
664 bool is_valid_polygon_mesh(const Mesh& g, bool verb = false)
665 {
666   typedef typename boost::graph_traits<Mesh>::halfedge_descriptor   halfedge_descriptor;
667 
668   Verbose_ostream verr(verb);
669   bool valid = is_valid_face_graph(g, verb);
670   if(!valid)
671     return false;
672 
673   // test for 2-manifoldness
674   // Distinct facets on each side of an halfedge.
675   for(halfedge_descriptor i : halfedges(g))
676   {
677     valid = (face(i, g) != face(opposite(i, g), g));
678     if(!valid)
679     {
680       verr << "both incident facets are equal." << std::endl;
681       verr << "Polygon Mesh Structure is NOT VALID." << std::endl;
682       return false;
683     }
684 
685     valid = (next(next(i, g), g) != i);
686     valid = valid && (target(i, g) != target(next(i, g), g));
687     valid = valid && (target(i, g) != target(next(next(i, g), g), g));
688     if(!valid)
689     {
690       verr << "incident facet is not at least a triangle." << std::endl;
691       verr << "Polygon Mesh Structure is NOT VALID." << std::endl;
692       return false;
693     }
694   }
695 
696   verr << "Polygon Mesh Structure is valid." << std::endl;
697   return true;
698 }
699 
700   /*!
701    \ingroup PkgBGLHelperFct
702     returns `true` iff the connected component denoted by `hd` is a hexahedron.
703   */
704 template <typename FaceGraph>
is_hexahedron(typename boost::graph_traits<FaceGraph>::halfedge_descriptor hd,const FaceGraph & g)705 bool is_hexahedron( typename boost::graph_traits<FaceGraph>::halfedge_descriptor hd, const FaceGraph& g)
706 {
707   typedef typename boost::graph_traits<FaceGraph>::halfedge_descriptor halfedge_descriptor;
708 
709   halfedge_descriptor h1 = hd;
710   if(is_border(h1,g)) return false;
711   typedef typename boost::graph_traits<FaceGraph>::halfedge_descriptor halfedge_descriptor;
712   halfedge_descriptor h2 = next(h1,g);
713   halfedge_descriptor h3 = next(h2,g);
714   halfedge_descriptor h4 = next(h3,g);
715   halfedge_descriptor h1o = opposite(h1,g);
716   halfedge_descriptor h2o = opposite(h2,g);
717   halfedge_descriptor h3o = opposite(h3,g);
718   halfedge_descriptor h4o = opposite(h4,g);
719   if(opposite(next(h2o,g),g) != prev(h1o,g)) return false;
720   if(opposite(next(h3o,g),g) != prev(h2o,g)) return false;
721   if(opposite(next(h4o,g),g) != prev(h3o,g)) return false;
722   if(opposite(next(h1o,g),g) != prev(h4o,g)) return false;
723   if(! is_quad(h1,g)) return false;
724   if(! is_quad(h1o,g)) return false;
725   if(! is_quad(h2o,g)) return false;
726   if(! is_quad(h3o,g)) return false;
727   if(! is_quad(h4o,g)) return false;
728   h1o =next(next(h1o,g),g);
729   h2o =next(next(h2o,g),g);
730   h3o =next(next(h3o,g),g);
731   h4o =next(next(h4o,g),g);
732   if(next(opposite(h2o,g),g) != opposite(h1o,g)) return false;
733   if(next(opposite(h3o,g),g) != opposite(h2o,g)) return false;
734   if(next(opposite(h4o,g),g) != opposite(h3o,g)) return false;
735   if(next(opposite(h1o,g),g) != opposite(h4o,g)) return false;
736 
737   if(! is_quad(opposite(h4o,g),g)) return false;
738   return true;
739 }
740 
741 namespace internal {
742 
743 template<typename FaceGraph>
744 inline
745 typename boost::enable_if<Has_member_clear<FaceGraph>, void>::type
clear_impl(FaceGraph & g)746 clear_impl(FaceGraph& g)
747 { g.clear(); }
748 
749 template<typename FaceGraph>
750 inline
751 typename boost::disable_if<Has_member_clear<FaceGraph>, void>::type
clear_impl(FaceGraph & g)752 clear_impl(FaceGraph& g)
753 {
754   while(boost::begin(edges(g))!=boost::end(edges(g)))
755     remove_edge(*boost::begin(edges(g)), g);
756   while(boost::begin(faces(g))!=boost::end(faces(g)))
757     remove_face(*boost::begin(faces(g)), g);
758   while(boost::begin(vertices(g))!=boost::end(vertices(g)))
759     remove_vertex(*boost::begin(vertices(g)), g);
760 }
761 
762 template <class FaceGraph>
swap_vertices(typename boost::graph_traits<FaceGraph>::vertex_descriptor & p,typename boost::graph_traits<FaceGraph>::vertex_descriptor & q,FaceGraph & g)763 void swap_vertices(
764   typename boost::graph_traits<FaceGraph>::vertex_descriptor& p,
765   typename boost::graph_traits<FaceGraph>::vertex_descriptor& q,
766   FaceGraph& g)
767 {
768  typedef typename boost::graph_traits<FaceGraph>::halfedge_descriptor halfedge_descriptor;
769 
770   halfedge_descriptor hq=halfedge(q, g);
771   halfedge_descriptor hp=halfedge(p, g);
772   for(halfedge_descriptor h : halfedges_around_target(hq, g))
773     set_target(h, p, g);
774   for(halfedge_descriptor h : halfedges_around_target(hp, g))
775     set_target(h, q, g);
776   set_halfedge(p, hq, g);
777   set_halfedge(q, hp, g);
778 }
779 
780 template <class FaceGraph>
swap_edges(const typename boost::graph_traits<FaceGraph>::halfedge_descriptor & h1,const typename boost::graph_traits<FaceGraph>::halfedge_descriptor & h2,FaceGraph & g)781 void swap_edges(
782   const typename boost::graph_traits<FaceGraph>::halfedge_descriptor& h1,
783   const typename boost::graph_traits<FaceGraph>::halfedge_descriptor& h2,
784   FaceGraph& g)
785 {
786   typedef typename boost::graph_traits<FaceGraph>::halfedge_descriptor halfedge_descriptor;
787   typedef typename boost::graph_traits<FaceGraph>::face_descriptor face_descriptor;
788   typedef typename boost::graph_traits<FaceGraph>::vertex_descriptor vertex_descriptor;
789   const halfedge_descriptor oh1 = opposite(h1, g), oh2 = opposite(h2, g);
790 
791   // backup vertex pointers
792   vertex_descriptor s1 = target(oh1, g), s2 = target(oh2, g);
793   vertex_descriptor t1 = target(h1, g), t2 = target(h2, g);
794 
795   // backup face pointers
796   face_descriptor f1 = face(h1, g), f2 = face(h2, g);
797   face_descriptor fo1 = face(oh1, g), fo2 = face(oh2, g);
798 
799   // backup next prev pointers
800   halfedge_descriptor nh1 = next(h1, g), nh2 = next(h2, g);
801   halfedge_descriptor ph1 = prev(h1, g), ph2 = prev(h2, g);
802   halfedge_descriptor noh1 = next(oh1, g), noh2 = next(oh2, g);
803   halfedge_descriptor poh1 = prev(oh1, g), poh2 = prev(oh2, g);
804 
805   // handle particular cases where next/prev are halfedges to be swapt
806   if (nh1 == oh2) nh1 = oh1;
807   if (nh1 == h2) nh1 = h1;
808   if (nh2 == oh1) nh2 = oh2;
809   if (nh2 == h1) nh2 = h2;
810   if (ph1 == oh2) ph1 = oh1;
811   if (ph1 == h2) ph1 = h1;
812   if (ph2 == oh1) ph2 = oh2;
813   if (ph2 == h1) ph2 = h2;
814   if (noh1 == oh2) noh1 = oh1;
815   if (noh1 == h2) noh1 = h1;
816   if (noh2 == oh1) noh2 = oh2;
817   if (noh2 == h1) noh2 = h2;
818   if (poh1 == oh2) poh1 = oh1;
819   if (poh1 == h2) poh1 = h1;
820   if (poh2 == oh1) poh2 = oh2;
821   if (poh2 == h1) poh2 = h2;
822 
823   // (1) exchange next pointers
824   set_next(h1, nh2, g);
825   set_next(h2, nh1, g);
826   set_next(ph1, h2, g);
827   set_next(ph2, h1, g);
828   set_next(oh1, noh2, g);
829   set_next(oh2, noh1, g);
830   set_next(poh1, oh2, g);
831   set_next(poh2, oh1, g);
832 
833   // (2) exchange vertex-halfedge pointers
834   set_target(h1, t2, g);
835   set_target(h2, t1, g);
836   set_target(oh1, s2, g);
837   set_target(oh2, s1, g);
838   if (halfedge(t1, g)==h1) set_halfedge(t1, h2, g);
839   if (halfedge(t2, g)==h2) set_halfedge(t2, h1, g);
840   if (halfedge(s1, g)==oh1) set_halfedge(s1, oh2, g);
841   if (halfedge(s2, g)==oh2) set_halfedge(s2, oh1, g);
842 
843   // (3) exchange face-halfedge pointers
844   set_face(h1, f2, g);
845   set_face(h2, f1, g);
846   set_face(oh1, fo2, g);
847   set_face(oh2, fo1, g);
848 
849   face_descriptor nf = boost::graph_traits<FaceGraph>::null_face();
850   if (f1 != nf && halfedge(f1, g)==h1) set_halfedge(f1, h2, g);
851   if (f2 != nf && halfedge(f2, g)==h2) set_halfedge(f2, h1, g);
852   if (fo1 != nf && halfedge(fo1, g)==oh1) set_halfedge(fo1, oh2, g);
853   if (fo2 != nf && halfedge(fo2, g)==oh2) set_halfedge(fo2, oh1, g);
854 }
855 
856 
857 } //end of internal namespace
858 
859 /**
860  * \ingroup PkgBGLHelperFct
861  *
862  * removes all vertices, faces and halfedges from a graph. Calls
863  * `remove_edge()`, `remove_vertex()`, and `remove_face()` for each
864  * edge, vertex or face.
865  *
866  * If the graph has a member function `clear()`, it will be called
867  * instead.
868  *
869  * @tparam FaceGraph model of `MutableHalfedgeGraph` and `MutableFaceGraph`
870  *
871  * @param g the graph to clear
872  *
873  **/
874 template<typename FaceGraph>
clear(FaceGraph & g)875 void clear(FaceGraph& g)
876 {
877   internal::clear_impl(g);
878   CGAL_postcondition(std::distance(boost::begin(edges(g)),boost::end(edges(g))) == 0);
879   CGAL_postcondition(std::distance(boost::begin(vertices(g)),boost::end(vertices(g))) == 0);
880   CGAL_postcondition(std::distance(boost::begin(faces(g)),boost::end(faces(g))) == 0);
881 }
882 
883 /**
884 * \ingroup PkgBGLHelperFct
885 *
886 * checks whether the graph is empty, by checking that it does not contain any vertex.
887 *
888 * @tparam FaceGraph model of `FaceGraph`
889 *
890 * @param g the graph to test
891 *
892 **/
893 template<typename FaceGraph>
is_empty(const FaceGraph & g)894 bool is_empty(const FaceGraph& g)
895 {
896   return boost::empty(vertices(g));
897 }
898 
899 /// \ingroup PkgBGLHelperFct
900 ///
901 /// \brief returns the number of calls to `next()` one has to apply to the halfedge `hd`
902 ///        for `source(hd, mesh) == vd` to be true, starting from `hd = halfedge(fd, tm)`.
903 ///
904 /// \tparam Graph a model of `FaceGraph`
905 ///
906 /// \param vd a vertex of `g` whose index is sought
907 /// \param fd a face of `g` in which the index of `vd` is sought
908 /// \param g a mesh of type `Graph`
909 ///
910 /// \pre `vd` is a vertex of `fd`.
911 template <typename Graph>
vertex_index_in_face(const typename boost::graph_traits<Graph>::vertex_descriptor vd,const typename boost::graph_traits<Graph>::face_descriptor fd,const Graph & g)912 int vertex_index_in_face(const typename boost::graph_traits<Graph>::vertex_descriptor vd,
913                          const typename boost::graph_traits<Graph>::face_descriptor fd,
914                          const Graph& g)
915 {
916   typedef typename boost::graph_traits<Graph>::halfedge_descriptor halfedge_descriptor;
917 
918   halfedge_descriptor start = halfedge(fd, g);
919   halfedge_descriptor current = start;
920   int counter = 0;
921 
922   do
923   {
924     if(source(current, g) == vd)
925       break;
926 
927     ++counter;
928     current = next(current, g);
929   }
930   while(current != start);
931 
932   if(counter != 0 && current == start)
933   {
934     CGAL_assertion_msg(false, "Could not find vertex in face");
935     return -1;
936   }
937 
938   return counter;
939 }
940 
941 /// \ingroup PkgBGLHelperFct
942 ///
943 /// \brief returns the number of calls to `next(hd, tm)` one has to apply to `hd` for `hd == he`
944 ///        to be true, starting from `hd = halfedge(face(he, tm), tm)`.
945 ///
946 /// \tparam Graph a model of `FaceGraph`.
947 ///
948 /// \param he a halfedge of `g` whose index in `face(he, tm)` is sought
949 /// \param g an object of type `Graph`
950 ///
951 template <typename Graph>
halfedge_index_in_face(typename boost::graph_traits<Graph>::halfedge_descriptor he,const Graph & g)952 int halfedge_index_in_face(typename boost::graph_traits<Graph>::halfedge_descriptor he,
953                            const Graph& g)
954 {
955   typedef typename boost::graph_traits<Graph>::halfedge_descriptor halfedge_descriptor;
956   typedef typename boost::graph_traits<Graph>::face_descriptor     face_descriptor;
957 
958   CGAL_precondition(he != boost::graph_traits<Graph>::null_halfedge());
959   CGAL_precondition(!is_border(he, g));
960 
961   face_descriptor f = face(he, g);
962   halfedge_descriptor start = halfedge(f, g);
963   halfedge_descriptor current = start;
964   int count = 0;
965 
966   while(current != he)
967   {
968     current = next(current, g);
969     ++count;
970   }
971 
972   return count;
973 }
974 
975 } // namespace CGAL
976 
977 // Here at the bottom because helpers.h must include generators (for backward compatibility reasons),
978 // and Euler_operations.h needs helpers.h
979 #include <CGAL/boost/graph/generators.h>
980 
981 #endif // CGAL_BOOST_GRAPH_HELPERS_H
982