16#ifndef dealii_cgal_triangulation_h
17#define dealii_cgal_triangulation_h
28#ifdef DEAL_II_WITH_CGAL
30# include <boost/hana.hpp>
32# include <CGAL/Complex_2_in_triangulation_3.h>
33# include <CGAL/IO/facets_in_complex_2_to_triangle_mesh.h>
34# include <CGAL/Implicit_surface_3.h>
35# include <CGAL/Labeled_mesh_domain_3.h>
36# include <CGAL/Mesh_complex_3_in_triangulation_3.h>
37# include <CGAL/Mesh_criteria_3.h>
38# include <CGAL/Mesh_triangulation_3.h>
39# include <CGAL/Polyhedron_3.h>
40# include <CGAL/Surface_mesh.h>
41# include <CGAL/Surface_mesh_default_triangulation_3.h>
42# include <CGAL/Triangulation_2.h>
43# include <CGAL/Triangulation_3.h>
44# include <CGAL/make_mesh_3.h>
45# include <CGAL/make_surface_mesh.h>
82 template <
int spacedim,
typename CGALTriangulation>
84 add_points_to_cgal_triangulation(
const std::vector<
Point<spacedim>> &points,
118 template <
typename CGALTriangulation,
int dim,
int spacedim>
120 cgal_triangulation_to_dealii_triangulation(
121 const CGALTriangulation & cgal_triangulation,
147 template <
typename CGALTriangulationType,
148 typename CornerIndexType,
149 typename CurveIndexType>
151 cgal_triangulation_to_dealii_triangulation(
152 const CGAL::Mesh_complex_3_in_triangulation_3<CGALTriangulationType,
155 & cgal_triangulation,
179 template <
typename CGAL_MeshType>
181 cgal_surface_mesh_to_dealii_triangulation(
const CGAL_MeshType &cgal_mesh,
188 template <
int spacedim,
typename CGALTriangulation>
190 add_points_to_cgal_triangulation(
const std::vector<
Point<spacedim>> &points,
195 "The triangulation you pass to this function should be a valid "
196 "CGAL triangulation."));
198 std::vector<typename CGALTriangulation::Point> cgal_points(points.size());
199 std::transform(points.begin(),
203 return CGALWrappers::dealii_point_to_cgal_point<
204 typename CGALTriangulation::Point>(p);
207 triangulation.insert(cgal_points.begin(), cgal_points.end());
210 "The Triangulation is no longer valid after inserting the points. "
216 template <
typename CGALTriangulationType,
217 typename CornerIndexType,
218 typename CurveIndexType>
220 cgal_triangulation_to_dealii_triangulation(
221 const CGAL::Mesh_complex_3_in_triangulation_3<CGALTriangulationType,
224 & cgal_triangulation,
227 using C3T3 = CGAL::Mesh_complex_3_in_triangulation_3<CGALTriangulationType,
232 std::vector<Point<3>> dealii_vertices;
233 std::map<typename C3T3::Vertex_handle, unsigned int>
234 cgal_to_dealii_vertex_map;
236 std::size_t inum = 0;
237 for (
auto vit = cgal_triangulation.triangulation().finite_vertices_begin();
238 vit != cgal_triangulation.triangulation().finite_vertices_end();
241 if (vit->in_dimension() <= -1)
243 cgal_to_dealii_vertex_map[vit] = inum++;
244 dealii_vertices.emplace_back(
245 CGALWrappers::cgal_point_to_dealii_point<3>(vit->point()));
249 std::vector<CellData<3>> cells;
250 for (
auto cgal_cell = cgal_triangulation.cells_in_complex_begin();
251 cgal_cell != cgal_triangulation.cells_in_complex_end();
255 for (
unsigned int i = 0; i < 4; ++i)
256 cell.vertices[i] = cgal_to_dealii_vertex_map[cgal_cell->vertex(i)];
257 cell.manifold_id = cgal_triangulation.subdomain_index(cgal_cell);
258 cells.push_back(cell);
263 if constexpr (std::is_integral<typename C3T3::Surface_patch_index>::value)
265 for (
auto face = cgal_triangulation.facets_in_complex_begin();
266 face != cgal_triangulation.facets_in_complex_end();
269 const auto &[cgal_cell, cgal_vertex_face_index] = *face;
275 for (
int i = 0; i < 4; ++i)
276 if (i != cgal_vertex_face_index)
277 dealii_face.vertices[j++] =
278 cgal_to_dealii_vertex_map[cgal_cell->vertex(i)];
279 dealii_face.manifold_id =
280 cgal_triangulation.surface_patch_index(cgal_cell,
281 cgal_vertex_face_index);
286 if constexpr (std::is_integral<typename C3T3::Curve_index>::value)
288 for (
auto edge = cgal_triangulation.edges_in_complex_begin();
289 edge != cgal_triangulation.edges_in_complex_end();
292 const auto &[cgal_cell,
v1, v2] = *edge;
294 dealii_edge.vertices[0] =
295 cgal_to_dealii_vertex_map[cgal_cell->vertex(
v1)];
296 dealii_edge.vertices[1] =
297 cgal_to_dealii_vertex_map[cgal_cell->vertex(v2)];
298 dealii_edge.manifold_id =
299 cgal_triangulation.curve_index(cgal_cell->vertex(
v1),
300 cgal_cell->vertex(v2));
312 template <
typename CGALTriangulation,
int dim,
int spacedim>
314 cgal_triangulation_to_dealii_triangulation(
315 const CGALTriangulation & cgal_triangulation,
319 ExcMessage(
"The dimension of the input CGAL triangulation (" +
320 std::to_string(cgal_triangulation.dimension()) +
321 ") does not match the dimension of the output "
322 "deal.II triangulation (" +
323 std::to_string(dim) +
")."));
326 ExcMessage(
"The output triangulation object needs to be empty."));
329 std::vector<Point<spacedim>>
vertices(
330 cgal_triangulation.number_of_vertices());
331 std::vector<CellData<dim>> cells;
335 std::map<typename CGALTriangulation::Vertex_handle, unsigned int>
339 for (
const auto &v : cgal_triangulation.finite_vertex_handles())
342 CGALWrappers::cgal_point_to_dealii_point<spacedim>(v->point());
347 const auto has_faces = boost::hana::is_valid(
348 [](
auto &&obj) ->
decltype(obj.finite_face_handles()) {});
350 const auto has_cells = boost::hana::is_valid(
351 [](
auto &&obj) ->
decltype(obj.finite_cell_handles()) {});
354 if constexpr (
decltype(has_faces(cgal_triangulation)){})
357 if (cgal_triangulation.dimension() == 2)
358 for (
const auto &f : cgal_triangulation.finite_face_handles())
361 for (
unsigned int i = 0;
364 cell.vertices[i] = vertex_map[f->vertex(i)];
365 cells.push_back(cell);
367 else if (cgal_triangulation.dimension() == 1)
369 for (
const auto &e : cgal_triangulation.finite_edges())
373 const auto & f =
e.first;
374 const auto & i =
e.second;
382 for (
unsigned int j = 0;
386 cell.vertices[
id++] = vertex_map[f->vertex(j)];
387 cells.push_back(cell);
394 else if constexpr (
decltype(has_cells(cgal_triangulation)){})
397 if (cgal_triangulation.dimension() == 3)
398 for (
const auto &c : cgal_triangulation.finite_cell_handles())
401 for (
unsigned int i = 0;
404 cell.vertices[i] = vertex_map[c->vertex(i)];
405 cells.push_back(cell);
407 else if (cgal_triangulation.dimension() == 2)
409 for (
const auto &facet : cgal_triangulation.finite_facets())
413 const auto & c = facet.first;
414 const auto & i = facet.second;
422 for (
unsigned int j = 0;
426 cell.vertices[
id++] = vertex_map[c->vertex(j)];
427 cells.push_back(cell);
429 else if (cgal_triangulation.dimension() == 1)
431 for (
const auto &edge : cgal_triangulation.finite_edges())
434 const auto &[c, i, j] = edge;
436 cell.vertices[0] = vertex_map[c->vertex(i)];
437 cell.vertices[1] = vertex_map[c->vertex(j)];
438 cells.push_back(cell);
450 template <
typename CGAL_MeshType>
452 cgal_surface_mesh_to_dealii_triangulation(
const CGAL_MeshType &cgal_mesh,
457 "Triangulation must be empty upon calling this function."));
459 const auto is_surface_mesh =
460 boost::hana::is_valid([](
auto &&obj) ->
decltype(obj.faces()) {});
462 const auto is_polyhedral =
463 boost::hana::is_valid([](
auto &&obj) ->
decltype(obj.facets_begin()) {});
467 std::vector<CellData<2>> cells;
471 if constexpr (
decltype(is_surface_mesh(cgal_mesh)){})
475 vertices.reserve(cgal_mesh.num_vertices());
476 std::map<typename CGAL_MeshType::Vertex_index, unsigned int> vertex_map;
479 for (
const auto &v : cgal_mesh.vertices())
481 vertices.emplace_back(CGALWrappers::cgal_point_to_dealii_point<3>(
482 cgal_mesh.point(v)));
488 for (
const auto &face : cgal_mesh.faces())
490 const auto face_vertices =
491 CGAL::vertices_around_face(cgal_mesh.halfedge(face), cgal_mesh);
493 AssertThrow(face_vertices.size() == 3 || face_vertices.size() == 4,
494 ExcMessage(
"Only triangle or quadrilateral surface "
495 "meshes are supported in deal.II"));
498 auto it_vertex = c.vertices.begin();
499 for (
const auto &v : face_vertices)
500 *(it_vertex++) = vertex_map[v];
503 if (face_vertices.size() == 4)
504 std::swap(c.vertices[3], c.vertices[2]);
506 cells.emplace_back(c);
509 else if constexpr (
decltype(is_polyhedral(cgal_mesh)){})
513 vertices.reserve(cgal_mesh.size_of_vertices());
514 std::map<
decltype(cgal_mesh.vertices_begin()),
unsigned int> vertex_map;
517 for (
auto it = cgal_mesh.vertices_begin();
518 it != cgal_mesh.vertices_end();
522 CGALWrappers::cgal_point_to_dealii_point<3>(it->point()));
523 vertex_map[it] = i++;
528 for (
auto face = cgal_mesh.facets_begin();
529 face != cgal_mesh.facets_end();
532 auto j = face->facet_begin();
533 const unsigned int vertices_per_face = CGAL::circulator_size(j);
534 AssertThrow(vertices_per_face == 3 || vertices_per_face == 4,
535 ExcMessage(
"Only triangle or quadrilateral surface "
536 "meshes are supported in deal.II. You "
537 "tried to read a mesh where a face has " +
538 std::to_string(vertices_per_face) +
539 " vertices per face."));
542 auto it = c.vertices.begin();
543 for (
unsigned int i = 0; i < vertices_per_face; ++i)
545 *(it++) = vertex_map[j->vertex()];
549 if (vertices_per_face == 4)
550 std::swap(c.vertices[3], c.vertices[2]);
552 cells.emplace_back(c);
559 "Unsupported CGAL surface triangulation type."));
unsigned int n_vertices() const
virtual void create_triangulation(const std::vector< Point< spacedim > > &vertices, const std::vector< CellData< dim > > &cells, const SubCellData &subcelldata)
unsigned int n_cells() const
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
#define Assert(cond, exc)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
constexpr const ReferenceCell Tetrahedron
constexpr const ReferenceCell Triangle
constexpr const ReferenceCell Line
const ::parallel::distributed::Triangulation< dim, spacedim > * triangulation
std::vector< CellData< 2 > > boundary_quads
std::vector< CellData< 1 > > boundary_lines