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