15#ifndef dealii_cgal_triangulation_h
16#define dealii_cgal_triangulation_h
27#ifdef DEAL_II_WITH_CGAL
29# include <boost/hana.hpp>
31# include <CGAL/Complex_2_in_triangulation_3.h>
32# include <CGAL/IO/facets_in_complex_2_to_triangle_mesh.h>
33# include <CGAL/Implicit_surface_3.h>
34# include <CGAL/Labeled_mesh_domain_3.h>
35# include <CGAL/Mesh_complex_3_in_triangulation_3.h>
36# include <CGAL/Mesh_criteria_3.h>
37# include <CGAL/Mesh_triangulation_3.h>
38# include <CGAL/Polyhedron_3.h>
39# include <CGAL/Surface_mesh.h>
40# include <CGAL/Surface_mesh_default_triangulation_3.h>
41# include <CGAL/Triangulation_2.h>
42# include <CGAL/Triangulation_3.h>
43# include <CGAL/make_mesh_3.h>
44# include <CGAL/make_surface_mesh.h>
81 template <
int spacedim,
typename CGALTriangulation>
83 add_points_to_cgal_triangulation(
const std::vector<
Point<spacedim>> &points,
117 template <
typename CGALTriangulation,
int dim,
int spacedim>
119 cgal_triangulation_to_dealii_triangulation(
120 const CGALTriangulation &cgal_triangulation,
146 template <
typename CGALTriangulationType,
147 typename CornerIndexType,
148 typename CurveIndexType>
150 cgal_triangulation_to_dealii_triangulation(
151 const CGAL::Mesh_complex_3_in_triangulation_3<CGALTriangulationType,
178 template <
typename CGAL_MeshType>
180 cgal_surface_mesh_to_dealii_triangulation(
const CGAL_MeshType &cgal_mesh,
187 template <
int spacedim,
typename CGALTriangulation>
189 add_points_to_cgal_triangulation(
const std::vector<
Point<spacedim>> &points,
194 "The triangulation you pass to this function should be a valid "
195 "CGAL triangulation."));
197 std::vector<typename CGALTriangulation::Point> cgal_points(points.size());
198 std::transform(points.begin(),
202 return CGALWrappers::dealii_point_to_cgal_point<
203 typename CGALTriangulation::Point>(p);
206 triangulation.insert(cgal_points.begin(), cgal_points.end());
209 "The Triangulation is no longer valid after inserting the points. "
215 template <
typename CGALTriangulationType,
216 typename CornerIndexType,
217 typename CurveIndexType>
219 cgal_triangulation_to_dealii_triangulation(
220 const CGAL::Mesh_complex_3_in_triangulation_3<CGALTriangulationType,
226 using C3T3 = CGAL::Mesh_complex_3_in_triangulation_3<CGALTriangulationType,
231 std::vector<Point<3>> dealii_vertices;
232 std::map<typename C3T3::Vertex_handle, unsigned int>
233 cgal_to_dealii_vertex_map;
235 std::size_t inum = 0;
236 for (
auto vit = cgal_triangulation.triangulation().finite_vertices_begin();
237 vit != cgal_triangulation.triangulation().finite_vertices_end();
240 if (vit->in_dimension() <= -1)
242 cgal_to_dealii_vertex_map[vit] = inum++;
243 dealii_vertices.emplace_back(
244 CGALWrappers::cgal_point_to_dealii_point<3>(vit->point()));
248 std::vector<CellData<3>> cells;
249 for (
auto cgal_cell = cgal_triangulation.cells_in_complex_begin();
250 cgal_cell != cgal_triangulation.cells_in_complex_end();
254 for (
unsigned int i = 0; i < 4; ++i)
255 cell.vertices[i] = cgal_to_dealii_vertex_map[cgal_cell->vertex(i)];
256 cell.manifold_id = cgal_triangulation.subdomain_index(cgal_cell);
257 cells.push_back(cell);
262 if constexpr (std::is_integral_v<typename C3T3::Surface_patch_index>)
264 for (
auto face = cgal_triangulation.facets_in_complex_begin();
265 face != cgal_triangulation.facets_in_complex_end();
268 const auto &[cgal_cell, cgal_vertex_face_index] = *face;
274 for (
int i = 0; i < 4; ++i)
275 if (i != cgal_vertex_face_index)
276 dealii_face.vertices[j++] =
277 cgal_to_dealii_vertex_map[cgal_cell->vertex(i)];
278 dealii_face.manifold_id =
279 cgal_triangulation.surface_patch_index(cgal_cell,
280 cgal_vertex_face_index);
285 if constexpr (std::is_integral_v<typename C3T3::Curve_index>)
287 for (
auto edge = cgal_triangulation.edges_in_complex_begin();
288 edge != cgal_triangulation.edges_in_complex_end();
291 const auto &[cgal_cell,
v1, v2] = *edge;
293 dealii_edge.vertices[0] =
294 cgal_to_dealii_vertex_map[cgal_cell->vertex(
v1)];
295 dealii_edge.vertices[1] =
296 cgal_to_dealii_vertex_map[cgal_cell->vertex(v2)];
297 dealii_edge.manifold_id =
298 cgal_triangulation.curve_index(cgal_cell->vertex(
v1),
299 cgal_cell->vertex(v2));
311 template <
typename CGALTriangulation,
int dim,
int spacedim>
313 cgal_triangulation_to_dealii_triangulation(
314 const CGALTriangulation &cgal_triangulation,
318 ExcMessage(
"The dimension of the input CGAL triangulation (" +
319 std::to_string(cgal_triangulation.dimension()) +
320 ") does not match the dimension of the output "
321 "deal.II triangulation (" +
322 std::to_string(dim) +
")."));
325 ExcMessage(
"The output triangulation object needs to be empty."));
328 std::vector<Point<spacedim>> vertices(
329 cgal_triangulation.number_of_vertices());
330 std::vector<CellData<dim>> cells;
334 std::map<typename CGALTriangulation::Vertex_handle, unsigned int>
338 for (
const auto &v : cgal_triangulation.finite_vertex_handles())
341 CGALWrappers::cgal_point_to_dealii_point<spacedim>(v->point());
346 const auto has_faces = boost::hana::is_valid(
347 [](
auto &&obj) ->
decltype(obj.finite_face_handles()) {});
349 const auto has_cells = boost::hana::is_valid(
350 [](
auto &&obj) ->
decltype(obj.finite_cell_handles()) {});
353 if constexpr (
decltype(has_faces(cgal_triangulation)){})
356 if (cgal_triangulation.dimension() == 2)
357 for (
const auto &f : cgal_triangulation.finite_face_handles())
360 for (
unsigned int i = 0;
363 cell.vertices[i] = vertex_map[f->vertex(i)];
364 cells.push_back(cell);
366 else if (cgal_triangulation.dimension() == 1)
368 for (
const auto &e : cgal_triangulation.finite_edges())
372 const auto &f =
e.first;
373 const auto &i =
e.second;
381 for (
unsigned int j = 0;
385 cell.vertices[
id++] = vertex_map[f->vertex(j)];
386 cells.push_back(cell);
393 else if constexpr (
decltype(has_cells(cgal_triangulation)){})
396 if (cgal_triangulation.dimension() == 3)
397 for (
const auto &c : cgal_triangulation.finite_cell_handles())
400 for (
unsigned int i = 0;
403 cell.vertices[i] = vertex_map[c->vertex(i)];
404 cells.push_back(cell);
406 else if (cgal_triangulation.dimension() == 2)
408 for (
const auto &facet : cgal_triangulation.finite_facets())
412 const auto &c = facet.first;
413 const auto &i = facet.second;
421 for (
unsigned int j = 0;
425 cell.vertices[
id++] = vertex_map[c->vertex(j)];
426 cells.push_back(cell);
428 else if (cgal_triangulation.dimension() == 1)
430 for (
const auto &edge : cgal_triangulation.finite_edges())
433 const auto &[c, i, j] = edge;
435 cell.vertices[0] = vertex_map[c->vertex(i)];
436 cell.vertices[1] = vertex_map[c->vertex(j)];
437 cells.push_back(cell);
449 template <
typename CGAL_MeshType>
451 cgal_surface_mesh_to_dealii_triangulation(
const CGAL_MeshType &cgal_mesh,
456 "Triangulation must be empty upon calling this function."));
458 const auto is_surface_mesh =
459 boost::hana::is_valid([](
auto &&obj) ->
decltype(obj.faces()) {});
461 const auto is_polyhedral =
462 boost::hana::is_valid([](
auto &&obj) ->
decltype(obj.facets_begin()) {});
465 std::vector<::Point<3>> vertices;
466 std::vector<CellData<2>> cells;
470 if constexpr (
decltype(is_surface_mesh(cgal_mesh)){})
474 vertices.reserve(cgal_mesh.num_vertices());
475 std::map<typename CGAL_MeshType::Vertex_index, unsigned int> vertex_map;
478 for (
const auto &v : cgal_mesh.vertices())
480 vertices.emplace_back(CGALWrappers::cgal_point_to_dealii_point<3>(
481 cgal_mesh.point(v)));
487 for (
const auto &face : cgal_mesh.faces())
489 const auto face_vertices =
490 CGAL::vertices_around_face(cgal_mesh.halfedge(face), cgal_mesh);
492 AssertThrow(face_vertices.size() == 3 || face_vertices.size() == 4,
493 ExcMessage(
"Only triangle or quadrilateral surface "
494 "meshes are supported in deal.II"));
497 auto it_vertex = c.vertices.begin();
498 for (
const auto &v : face_vertices)
499 *(it_vertex++) = vertex_map[v];
502 if (face_vertices.size() == 4)
503 std::swap(c.vertices[3], c.vertices[2]);
505 cells.emplace_back(c);
508 else if constexpr (
decltype(is_polyhedral(cgal_mesh)){})
512 vertices.reserve(cgal_mesh.size_of_vertices());
513 std::map<
decltype(cgal_mesh.vertices_begin()),
unsigned int> vertex_map;
516 for (
auto it = cgal_mesh.vertices_begin();
517 it != cgal_mesh.vertices_end();
520 vertices.emplace_back(
521 CGALWrappers::cgal_point_to_dealii_point<3>(it->point()));
522 vertex_map[it] = i++;
527 for (
auto face = cgal_mesh.facets_begin();
528 face != cgal_mesh.facets_end();
531 auto j = face->facet_begin();
532 const unsigned int vertices_per_face = CGAL::circulator_size(j);
533 AssertThrow(vertices_per_face == 3 || vertices_per_face == 4,
534 ExcMessage(
"Only triangle or quadrilateral surface "
535 "meshes are supported in deal.II. You "
536 "tried to read a mesh where a face has " +
537 std::to_string(vertices_per_face) +
538 " vertices per face."));
541 auto it = c.vertices.begin();
542 for (
unsigned int i = 0; i < vertices_per_face; ++i)
544 *(it++) = vertex_map[j->vertex()];
548 if (vertices_per_face == 4)
549 std::swap(c.vertices[3], c.vertices[2]);
551 cells.emplace_back(c);
558 "Unsupported CGAL surface triangulation type."));
560 triangulation.create_triangulation(vertices, cells, subcell_data);
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)
#define DEAL_II_ASSERT_UNREACHABLE()
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