1 // Copyright (c) 2010-2011  GeometryFactory Sarl (France).
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/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/triangulate_faces.h $
7 // $Id: triangulate_faces.h bfd4e99 2020-09-15T15:42:24+02:00 Jane Tournois
8 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
9 //
10 //
11 // Author(s)     : Laurent Rineau
12 
13 #ifndef CGAL_POLYGON_MESH_PROCESSING_TRIANGULATE_FACES_H
14 #define CGAL_POLYGON_MESH_PROCESSING_TRIANGULATE_FACES_H
15 
16 #include <CGAL/license/Polygon_mesh_processing/meshing_hole_filling.h>
17 
18 #include <CGAL/disable_warnings.h>
19 
20 #include <CGAL/boost/graph/helpers.h>
21 #include <CGAL/boost/graph/Euler_operations.h>
22 
23 #ifndef CGAL_TRIANGULATE_FACES_DO_NOT_USE_CDT2
24 #include <CGAL/Triangulation_vertex_base_with_info_2.h>
25 #include <CGAL/Triangulation_face_base_with_info_2.h>
26 #include <CGAL/Constrained_Delaunay_triangulation_2.h>
27 #include <CGAL/Triangulation_2_projection_traits_3.h>
28 #else
29 #include <CGAL/use.h>
30 #endif
31 
32 #include <CGAL/Polygon_mesh_processing/triangulate_hole.h>
33 #include <CGAL/Polygon_mesh_processing/compute_normal.h>
34 #include <CGAL/Polygon_mesh_processing/internal/named_function_params.h>
35 #include <CGAL/Polygon_mesh_processing/internal/named_params_helper.h>
36 
37 #include <boost/range/size.hpp>
38 
39 #include <queue>
40 #include <vector>
41 #include <utility>
42 #include <CGAL/array.h>
43 
44 namespace CGAL {
45 
46 namespace Polygon_mesh_processing {
47 
48 namespace Triangulate_faces
49 {
50 /** \ingroup PMP_meshing_grp
51 *   %Default new face visitor model of `PMPTriangulateFaceVisitor`.
52 *   All its functions have an empty body. This class can be used as a
53 *   base class if only some of the functions of the concept require to be
54 *   overriden.
55 */
56 template<class PolygonMesh>
57 struct Default_visitor {
58   typedef boost::graph_traits<PolygonMesh> GT;
59   typedef typename GT::face_descriptor face_descriptor;
60 
before_subface_creationsDefault_visitor61   void before_subface_creations(face_descriptor /*f_old*/) {}
after_subface_creationsDefault_visitor62   void after_subface_creations() {}
after_subface_createdDefault_visitor63   void after_subface_created(face_descriptor /*f_new*/) {}
64 };
65 
66 } //end namespace Triangulate_faces
67 
68 namespace internal {
69 
70 template <class PM
71           , typename VertexPointMap
72           , typename Kernel
73           , typename Visitor>
74 class Triangulate_modifier
75 {
76   typedef Kernel Traits;
77 
78   typedef typename boost::graph_traits<PM>::vertex_descriptor vertex_descriptor;
79   typedef typename boost::graph_traits<PM>::halfedge_descriptor halfedge_descriptor;
80   typedef typename boost::graph_traits<PM>::face_descriptor face_descriptor;
81   typedef typename boost::graph_traits<PM>::edge_descriptor edge_descriptor;
82   typedef typename Kernel::Point_3 Point;
83 
84   struct Face_info {
85     typename boost::graph_traits<PM>::halfedge_descriptor e[3];
86     bool is_external;
87   };
88 
89   typedef typename boost::property_traits<VertexPointMap>::reference Point_ref;
90   VertexPointMap _vpmap;
91   Traits _traits;
92 
93 public:
94   Triangulate_modifier(VertexPointMap vpmap, const Traits& traits = Traits())
_vpmap(vpmap)95     : _vpmap(vpmap), _traits(traits)
96   {
97   }
98 
99   template <class Face_handle>
is_external(Face_handle fh)100   bool is_external(Face_handle fh) const {
101     return fh->info().is_external;
102   }
103 
triangulate_face(face_descriptor f,PM & pmesh,bool use_cdt,Visitor visitor)104   bool triangulate_face(face_descriptor f, PM& pmesh, bool use_cdt, Visitor visitor)
105   {
106     typedef typename Traits::FT FT;
107 
108     typename Traits::Vector_3 normal =
109       Polygon_mesh_processing::compute_face_normal(
110         f, pmesh, CGAL::Polygon_mesh_processing::parameters::geom_traits(_traits)
111                                                             .vertex_point_map(_vpmap));
112 
113     if(normal == typename Traits::Vector_3(0,0,0))
114       return false;
115 
116     std::size_t original_size = CGAL::halfedges_around_face(halfedge(f, pmesh), pmesh).size();
117     if(original_size == 4)
118     {
119       halfedge_descriptor v0, v1, v2, v3;
120       v0 = halfedge(f, pmesh);
121       Point_ref p0 = get(_vpmap, target(v0, pmesh));
122       v1 = next(v0, pmesh);
123       Point_ref p1 = get(_vpmap, target(v1, pmesh));
124       v2 = next(v1, pmesh);
125       Point_ref p2 = get(_vpmap, target(v2, pmesh));
126       v3 = next(v2, pmesh);
127       Point_ref p3 = get(_vpmap, target(v3, pmesh));
128 
129       /* Chooses the diagonal that will split the quad in two triangles that maximize
130        * the scalar product of of the un-normalized normals of the two triangles.
131        * The lengths of the un-normalized normals (computed using cross-products of two vectors)
132        *  are proportional to the area of the triangles.
133        * Maximize the scalar product of the two normals will avoid skinny triangles,
134        * and will also taken into account the cosine of the angle between the two normals.
135        * In particular, if the two triangles are oriented in different directions,
136        * the scalar product will be negative.
137        */
138       FT p1p3 = CGAL::cross_product(p2-p1,p3-p2) * CGAL::cross_product(p0-p3,p1-p0);
139       FT p0p2 = CGAL::cross_product(p1-p0,p1-p2) * CGAL::cross_product(p3-p2,p3-p0);
140       visitor.before_subface_creations(f);
141       halfedge_descriptor res = (p0p2>p1p3)
142                               ?  CGAL::Euler::split_face(v0, v2, pmesh)
143                               :  CGAL::Euler::split_face(v1, v3, pmesh);
144 
145       visitor.after_subface_created(face(res,pmesh));
146       visitor.after_subface_created(face(opposite(res,pmesh),pmesh));
147 
148       visitor.after_subface_creations();
149     }
150     else
151     {
152 #ifndef CGAL_TRIANGULATE_FACES_DO_NOT_USE_CDT2
153       if (use_cdt)
154       {
155         typedef CGAL::Triangulation_2_projection_traits_3<Traits>   P_traits;
156         typedef CGAL::Triangulation_vertex_base_with_info_2<halfedge_descriptor,
157                                                             P_traits>        Vb;
158         typedef CGAL::Triangulation_face_base_with_info_2<Face_info,
159                                                           P_traits>          Fb1;
160         typedef CGAL::Constrained_triangulation_face_base_2<P_traits, Fb1>   Fb;
161         typedef CGAL::Triangulation_data_structure_2<Vb,Fb>                  TDS;
162         typedef CGAL::Exact_intersections_tag                                Itag;
163         typedef CGAL::Constrained_Delaunay_triangulation_2<P_traits,
164                                                            TDS,
165                                                            Itag>             CDT;
166         P_traits cdt_traits(normal);
167         CDT cdt(cdt_traits);
168         return triangulate_face_with_CDT(f, pmesh, cdt, visitor);
169       }
170 #else
171       CGAL_USE(use_cdt);
172 #endif
173       return triangulate_face_with_hole_filling(f, pmesh, visitor);
174     }
175     return true;
176   }
177 
178   template<class CDT>
triangulate_face_with_CDT(face_descriptor f,PM & pmesh,CDT & cdt,Visitor visitor)179   bool triangulate_face_with_CDT(face_descriptor f, PM& pmesh, CDT& cdt, Visitor visitor)
180   {
181     std::size_t original_size = CGAL::halfedges_around_face(halfedge(f, pmesh), pmesh).size();
182 
183     // Halfedge_around_facet_circulator
184     typedef typename CDT::Vertex_handle Tr_Vertex_handle;
185     halfedge_descriptor start = halfedge(f, pmesh);
186     halfedge_descriptor h = start;
187     Tr_Vertex_handle previous, first;
188     do
189     {
190       Tr_Vertex_handle vh = cdt.insert(get(_vpmap, target(h, pmesh)));
191       if (first == Tr_Vertex_handle()) {
192         first = vh;
193       }
194       vh->info() = h;
195       if(previous != Tr_Vertex_handle() && previous != vh) {
196         cdt.insert_constraint(previous, vh);
197       }
198       previous = vh;
199       h = next(h, pmesh);
200 
201     } while( h != start );
202     cdt.insert_constraint(previous, first);
203 
204     // sets mark is_external
205     for(typename CDT::All_faces_iterator fit = cdt.all_faces_begin(),
206           end = cdt.all_faces_end();
207         fit != end; ++fit)
208     {
209       fit->info().is_external = false;
210     }
211     std::queue<typename CDT::Face_handle> face_queue;
212     face_queue.push(cdt.infinite_vertex()->face());
213     while(! face_queue.empty() )
214     {
215       typename CDT::Face_handle fh = face_queue.front();
216       face_queue.pop();
217 
218       if(fh->info().is_external)
219         continue;
220 
221       fh->info().is_external = true;
222       for(int i = 0; i <3; ++i)
223       {
224         if(!cdt.is_constrained(typename CDT::Edge(fh, i)))
225         {
226           face_queue.push(fh->neighbor(i));
227         }
228       }
229     }
230 
231     if(cdt.dimension() != 2 ||
232        cdt.number_of_vertices() != original_size)
233       return false;
234 
235 
236     // then modify the polyhedron
237     visitor.before_subface_creations(f);
238     // make_hole. (see comment in function body)
239     this->make_hole(halfedge(f, pmesh), pmesh);
240 
241     for(typename CDT::Finite_edges_iterator eit = cdt.finite_edges_begin(),
242           end = cdt.finite_edges_end();
243         eit != end; ++eit)
244     {
245       typename CDT::Face_handle fh = eit->first;
246       const int index = eit->second;
247       typename CDT::Face_handle opposite_fh = fh->neighbor(eit->second);
248       const int opposite_index = opposite_fh->index(fh);
249 
250       const Tr_Vertex_handle va = fh->vertex(cdt. cw(index));
251       const Tr_Vertex_handle vb = fh->vertex(cdt.ccw(index));
252 
253       if( ! (is_external(fh) && is_external(opposite_fh))//not both fh are external
254           && ! cdt.is_constrained(*eit) )                  //and edge is not constrained
255       {
256         // strictly internal edge
257         halfedge_descriptor hnew = halfedge(add_edge(pmesh), pmesh),
258           hnewopp = opposite(hnew, pmesh);
259 
260         fh->info().e[index] = hnew;
261         opposite_fh->info().e[opposite_index] = hnewopp;
262 
263         set_target(hnew,    target(va->info(), pmesh), pmesh);
264         set_target(hnewopp, target(vb->info(), pmesh), pmesh);
265       }
266       if( cdt.is_constrained(*eit) ) //edge is constrained
267       {
268         if(!is_external(fh)) {
269           fh->info().e[index] = va->info();
270         }
271         if(!is_external(opposite_fh)) {
272           opposite_fh->info().e[opposite_index] = vb->info();
273         }
274       }
275     }
276     for(typename CDT::Finite_faces_iterator fit = cdt.finite_faces_begin(),
277           end = cdt.finite_faces_end();
278         fit != end; ++fit)
279     {
280       if(!is_external(fit))
281       {
282         halfedge_descriptor h0 = fit->info().e[0];
283         halfedge_descriptor h1 = fit->info().e[1];
284         halfedge_descriptor h2 = fit->info().e[2];
285         CGAL_assertion(h0 != halfedge_descriptor());
286         CGAL_assertion(h1 != halfedge_descriptor());
287         CGAL_assertion(h2 != halfedge_descriptor());
288 
289         set_next(h0, h1, pmesh);
290         set_next(h1, h2, pmesh);
291         set_next(h2, h0, pmesh);
292 
293         Euler::fill_hole(h0, pmesh);
294         visitor.after_subface_created(face(h0, pmesh));
295       }
296     }
297     visitor.after_subface_creations();
298     return true;
299   }
300 
triangulate_face_with_hole_filling(face_descriptor f,PM & pmesh,Visitor visitor)301   bool triangulate_face_with_hole_filling(face_descriptor f, PM& pmesh, Visitor visitor)
302   {
303     namespace PMP = CGAL::Polygon_mesh_processing;
304 
305     // gather halfedges around the face
306     std::vector<Point> hole_points;
307     std::vector<vertex_descriptor> border_vertices;
308     CGAL_assertion(CGAL::halfedges_around_face(halfedge(f, pmesh), pmesh).size() > 0);
309     for(halfedge_descriptor h : CGAL::halfedges_around_face(halfedge(f, pmesh), pmesh))
310     {
311       vertex_descriptor v = source(h, pmesh);
312       hole_points.push_back( get(_vpmap, v) );
313       border_vertices.push_back(v);
314     }
315 
316     // use hole filling
317     typedef CGAL::Triple<int, int, int> Face_indices;
318     std::vector<Face_indices> patch;
319     PMP::triangulate_hole_polyline(hole_points, std::back_inserter(patch),
320                                    PMP::parameters::geom_traits(_traits));
321 
322     if(patch.empty())
323       return false;
324 
325     // triangulate the hole
326     std::map< std::pair<int, int> , halfedge_descriptor > halfedge_map;
327     int i=0;
328     for(halfedge_descriptor h : CGAL::halfedges_around_face(halfedge(f, pmesh), pmesh))
329     {
330       int j = std::size_t(i+1) == hole_points.size() ? 0 : i+1;
331       halfedge_map[ std::make_pair(i, j) ] = h;
332       ++i;
333     }
334 
335     visitor.before_subface_creations(f);
336     bool first = true;
337     std::vector<halfedge_descriptor> hedges;
338     hedges.reserve(4);
339     for(const Face_indices& triangle : patch)
340     {
341       if (first)
342         first=false;
343       else
344         f=add_face(pmesh);
345       visitor.after_subface_created(f);
346 
347       std::array<int, 4> indices =
348         make_array( triangle.first,
349                     triangle.second,
350                     triangle.third,
351                     triangle.first );
352       for (int i=0; i<3; ++i)
353       {
354         typename std::map< std::pair<int, int> , halfedge_descriptor >::iterator insert_res =
355           halfedge_map.insert(
356             std::make_pair( std::make_pair(indices[i], indices[i+1]),
357                             boost::graph_traits<PM>::null_halfedge() ) ).first;
358         if (insert_res->second == boost::graph_traits<PM>::null_halfedge())
359         {
360           halfedge_descriptor nh = halfedge(add_edge(pmesh), pmesh);
361           insert_res->second=nh;
362           halfedge_map[std::make_pair(indices[i+1], indices[i])]=opposite(nh, pmesh);
363         }
364         hedges.push_back(insert_res->second);
365       }
366       hedges.push_back(hedges.front());
367       for(int i=0; i<3;++i)
368       {
369         set_next(hedges[i], hedges[i+1], pmesh);
370         set_face(hedges[i], f, pmesh);
371         set_target(hedges[i], border_vertices[indices[i+1]], pmesh);
372       }
373       set_halfedge(f, hedges[0], pmesh);
374       hedges.clear();
375     }
376     visitor.after_subface_creations();
377     return true;
378   }
379 
380   template<typename FaceRange>
operator()381   bool operator()(FaceRange face_range, PM& pmesh, bool use_cdt, Visitor visitor)
382   {
383    bool result = true;
384     // One need to store facet handles into a vector, because the list of
385     // facets of the polyhedron will be modified during the loop, and
386     // that invalidates the range [facets_begin(), facets_end()[.
387     std::vector<face_descriptor> facets;
388     facets.reserve(std::distance(boost::begin(face_range), boost::end(face_range)));
389 
390     //only consider non-triangular faces
391     for(face_descriptor fit : face_range)
392       if ( next( next( halfedge(fit, pmesh), pmesh), pmesh)
393         !=       prev( halfedge(fit, pmesh), pmesh) )
394         facets.push_back(fit);
395 
396     // Iterates on the vector of face descriptors
397     for(face_descriptor f : facets)
398     {
399       if(!this->triangulate_face(f, pmesh, use_cdt, visitor))
400        result = false;
401     }
402     return result;
403   }
404 
make_hole(halfedge_descriptor h,PM & pmesh)405   void make_hole(halfedge_descriptor h, PM& pmesh)
406   {
407     //we are not using Euler::make_hole because it has a precondition
408     //that the hole is not made on the boundary of the mesh
409     //here we allow making a hole on the boundary, and the pair(s) of
410     //halfedges that become border-border are fixed by the connectivity
411     //setting made in operator()
412     CGAL_assertion(!is_border(h, pmesh));
413     face_descriptor fd = face(h, pmesh);
414 
415     for(halfedge_descriptor hd : halfedges_around_face(h, pmesh))
416     {
417       CGAL::internal::set_border(hd, pmesh);
418     }
419     remove_face(fd, pmesh);
420   }
421 
422 
423 }; // end class Triangulate_modifier
424 
425 }//end namespace internal
426 
427 /**
428 * \ingroup PMP_meshing_grp
429 * triangulates a single face of a polygon mesh. This function depends on the package \ref PkgTriangulation2
430 * @tparam PolygonMesh a model of `FaceListGraph` and `MutableFaceGraph`
431 * @tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters"
432 *
433 * @param f face to be triangulated
434 * @param pmesh the polygon mesh to which the face to be triangulated belongs
435 * @param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below
436 *
437 * \cgalNamedParamsBegin
438 *   \cgalParamNBegin{vertex_point_map}
439 *     \cgalParamDescription{a property map associating points to the vertices of `pmesh`}
440 *     \cgalParamType{a class model of `ReadWritePropertyMap` with `boost::graph_traits<PolygonMesh>::%vertex_descriptor`
441 *                    as key type and `%Point_3` as value type}
442 *     \cgalParamDefault{`boost::get(CGAL::vertex_point, pmesh)`}
443 *     \cgalParamExtra{If this parameter is omitted, an internal property map for `CGAL::vertex_point_t`
444 *                     must be available in `PolygonMesh`.}
445 *   \cgalParamNEnd
446 *
447 *   \cgalParamNBegin{geom_traits}
448 *     \cgalParamDescription{an instance of a geometric traits class}
449 *     \cgalParamType{a class model of `Kernel`}
450 *     \cgalParamDefault{a \cgal Kernel deduced from the point type, using `CGAL::Kernel_traits`}
451 *     \cgalParamExtra{The geometric traits class must be compatible with the vertex point type.}
452 *   \cgalParamNEnd
453 *
454 *   \cgalParamNBegin{visitor}
455 *     \cgalParamDescription{a visitor that enables to track how faces are triangulated into subfaces}
456 *     \cgalParamType{a class model of `PMPTriangulateFaceVisitor`}
457 *     \cgalParamDefault{`Triangulate_faces::Default_visitor<PolygonMesh>`}
458 *     \cgalParamExtra{Note that the visitor will be copied, so
459 *                     it must not have any data member that does not have a reference-like type.}
460 *   \cgalParamNEnd
461 * \cgalNamedParamsEnd
462 *
463 * @return `true` if the face has been triangulated.
464 */
465 template<typename PolygonMesh, typename NamedParameters>
triangulate_face(typename boost::graph_traits<PolygonMesh>::face_descriptor f,PolygonMesh & pmesh,const NamedParameters & np)466 bool triangulate_face(typename boost::graph_traits<PolygonMesh>::face_descriptor f,
467                       PolygonMesh& pmesh,
468                       const NamedParameters& np)
469 {
470   using parameters::choose_parameter;
471   using parameters::get_parameter;
472 
473   //VertexPointMap
474   typedef typename GetVertexPointMap<PolygonMesh, NamedParameters>::type VPMap;
475   VPMap vpmap = choose_parameter(get_parameter(np, internal_np::vertex_point),
476                              get_property_map(vertex_point, pmesh));
477 
478   //Kernel
479   typedef typename GetGeomTraits<PolygonMesh, NamedParameters>::type Kernel;
480   Kernel traits = choose_parameter<Kernel>(get_parameter(np, internal_np::geom_traits));
481 
482   //Option
483   bool use_cdt = choose_parameter(get_parameter(np, internal_np::use_delaunay_triangulation), true);
484 
485   typedef typename internal_np::Lookup_named_param_def<
486     internal_np::visitor_t,
487     NamedParameters,
488     Triangulate_faces::Default_visitor<PolygonMesh>//default
489   >::type Visitor;
490   Visitor visitor = choose_parameter<Visitor>(
491                              get_parameter(np, internal_np::visitor),
492                              Triangulate_faces::Default_visitor<PolygonMesh>());
493 
494   internal::Triangulate_modifier<PolygonMesh, VPMap, Kernel, Visitor> modifier(vpmap, traits);
495   return modifier.triangulate_face(f, pmesh, use_cdt, visitor);
496 }
497 
498 template<typename PolygonMesh>
triangulate_face(typename boost::graph_traits<PolygonMesh>::face_descriptor f,PolygonMesh & pmesh)499 bool triangulate_face(typename boost::graph_traits<PolygonMesh>::face_descriptor f,
500                       PolygonMesh& pmesh)
501 {
502   return triangulate_face(f, pmesh, CGAL::Polygon_mesh_processing::parameters::all_default());
503 }
504 
505 /**
506 * \ingroup PMP_meshing_grp
507 * triangulates given faces of a polygon mesh. This function depends on the package \ref PkgTriangulation2
508 *
509 * @tparam FaceRange range of `boost::graph_traits<PolygonMesh>::%face_descriptor`,
510           model of `Range`.
511           Its iterator type is `InputIterator`.
512 * @tparam PolygonMesh a model of `FaceListGraph` and `MutableFaceGraph`
513 * @tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters"
514 *
515 * @param face_range the range of faces to be triangulated
516 * @param pmesh the polygon mesh to be triangulated
517 * @param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below
518 *
519 * \cgalNamedParamsBegin
520 *   \cgalParamNBegin{vertex_point_map}
521 *     \cgalParamDescription{a property map associating points to the vertices of `pmesh`}
522 *     \cgalParamType{a class model of `ReadWritePropertyMap` with `boost::graph_traits<PolygonMesh>::%vertex_descriptor`
523 *                    as key type and `%Point_3` as value type}
524 *     \cgalParamDefault{`boost::get(CGAL::vertex_point, pmesh)`}
525 *     \cgalParamExtra{If this parameter is omitted, an internal property map for `CGAL::vertex_point_t`
526 *                     must be available in `PolygonMesh`.}
527 *   \cgalParamNEnd
528 *
529 *   \cgalParamNBegin{geom_traits}
530 *     \cgalParamDescription{an instance of a geometric traits class}
531 *     \cgalParamType{a class model of `Kernel`}
532 *     \cgalParamDefault{a \cgal Kernel deduced from the point type, using `CGAL::Kernel_traits`}
533 *     \cgalParamExtra{The geometric traits class must be compatible with the vertex point type.}
534 *   \cgalParamNEnd
535 *
536 *   \cgalParamNBegin{visitor}
537 *     \cgalParamDescription{a visitor that enables to track how faces are triangulated into subfaces}
538 *     \cgalParamType{a class model of `PMPTriangulateFaceVisitor`}
539 *     \cgalParamDefault{`Triangulate_faces::Default_visitor<PolygonMesh>`}
540 *     \cgalParamExtra{Note that the visitor will be copied, so
541 *                     it must not have any data member that does not have a reference-like type.}
542 *  `\cgalParamNEnd
543 * \cgalNamedParamsEnd
544 *
545 * @return `true` if all the faces have been triangulated.
546 *
547 * @see triangulate_face()
548 */
549 template <typename FaceRange, typename PolygonMesh, typename NamedParameters>
triangulate_faces(FaceRange face_range,PolygonMesh & pmesh,const NamedParameters & np)550 bool triangulate_faces(FaceRange face_range,
551                        PolygonMesh& pmesh,
552                        const NamedParameters& np)
553 {
554   using parameters::choose_parameter;
555   using parameters::get_parameter;
556 
557   //VertexPointMap
558   typedef typename GetVertexPointMap<PolygonMesh, NamedParameters>::type VPMap;
559   VPMap vpmap = choose_parameter(get_parameter(np, internal_np::vertex_point),
560                              get_property_map(vertex_point, pmesh));
561 
562   //Kernel
563   typedef typename GetGeomTraits<PolygonMesh, NamedParameters>::type Kernel;
564   Kernel traits = choose_parameter<Kernel>(get_parameter(np, internal_np::geom_traits));
565 
566   //Option
567   bool use_cdt = choose_parameter(get_parameter(np, internal_np::use_delaunay_triangulation), true);
568 
569   typedef typename internal_np::Lookup_named_param_def<
570     internal_np::visitor_t,
571     NamedParameters,
572     Triangulate_faces::Default_visitor<PolygonMesh>//default
573   >::type Visitor;
574   Visitor visitor = choose_parameter<Visitor>(
575                                   get_parameter(np, internal_np::visitor),
576                                   Triangulate_faces::Default_visitor<PolygonMesh>());
577 
578   internal::Triangulate_modifier<PolygonMesh, VPMap, Kernel, Visitor> modifier(vpmap, traits);
579   return modifier(face_range, pmesh, use_cdt, visitor);
580 }
581 
582 template <typename FaceRange, typename PolygonMesh>
triangulate_faces(FaceRange face_range,PolygonMesh & pmesh)583 bool triangulate_faces(FaceRange face_range, PolygonMesh& pmesh)
584 {
585   return triangulate_faces(face_range, pmesh, CGAL::Polygon_mesh_processing::parameters::all_default());
586 }
587 
588 /**
589 * \ingroup PMP_meshing_grp
590 * triangulates all faces of a polygon mesh. This function depends on the package \ref PkgTriangulation2
591 * @tparam PolygonMesh a model of `FaceListGraph` and `MutableFaceGraph`
592 * @tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters"
593 *
594 * @param pmesh the polygon mesh to be triangulated
595 * @param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below
596 *
597 * \cgalNamedParamsBegin
598 *   \cgalParamNBegin{vertex_point_map}
599 *     \cgalParamDescription{a property map associating points to the vertices of `pmesh`}
600 *     \cgalParamType{a class model of `ReadWritePropertyMap` with `boost::graph_traits<PolygonMesh>::%vertex_descriptor`
601 *                    as key type and `%Point_3` as value type}
602 *     \cgalParamDefault{`boost::get(CGAL::vertex_point, pmesh)`}
603 *     \cgalParamExtra{If this parameter is omitted, an internal property map for `CGAL::vertex_point_t`
604 *                     must be available in `PolygonMesh`.}
605 *   \cgalParamNEnd
606 *
607 *   \cgalParamNBegin{geom_traits}
608 *     \cgalParamDescription{an instance of a geometric traits class}
609 *     \cgalParamType{a class model of `Kernel`}
610 *     \cgalParamDefault{a \cgal Kernel deduced from the point type, using `CGAL::Kernel_traits`}
611 *     \cgalParamExtra{The geometric traits class must be compatible with the vertex point type.}
612 *   \cgalParamNEnd
613 *
614 *   \cgalParamNBegin{visitor}
615 *     \cgalParamDescription{a visitor that enables to track how faces are triangulated into subfaces}
616 *     \cgalParamType{a class model of `PMPTriangulateFaceVisitor`}
617 *     \cgalParamDefault{`Triangulate_faces::Default_visitor<PolygonMesh>`}
618 *     \cgalParamExtra{Note that the visitor will be copied, so
619 *                     it must not have any data member that does not have a reference-like type.}
620 *   \cgalParamNEnd
621 * \cgalNamedParamsEnd
622 *
623 * @return `true` if all the faces have been triangulated.
624 *
625 * @see triangulate_face()
626 */
627 template <typename PolygonMesh, typename NamedParameters>
triangulate_faces(PolygonMesh & pmesh,const NamedParameters & np)628 bool triangulate_faces(PolygonMesh& pmesh,
629                        const NamedParameters& np)
630 {
631   return triangulate_faces(faces(pmesh), pmesh, np);
632 }
633 
634 template <typename PolygonMesh>
triangulate_faces(PolygonMesh & pmesh)635 bool triangulate_faces(PolygonMesh& pmesh)
636 {
637   return triangulate_faces(faces(pmesh), pmesh, CGAL::Polygon_mesh_processing::parameters::all_default());
638 }
639 
640 } // end namespace Polygon_mesh_processing
641 
642 } // end namespace CGAL
643 
644 #include <CGAL/enable_warnings.h>
645 
646 #endif // CGAL_POLYGON_MESH_PROCESSING_TRIANGULATE_FACES_H
647