13#ifndef dealii_cgal_triangulation_h
14#define dealii_cgal_triangulation_h
26#ifdef DEAL_II_WITH_CGAL
29# include <boost/hana.hpp>
31# include <CGAL/version.h>
32# if CGAL_VERSION_MAJOR >= 6
33# include <CGAL/Installation/internal/disable_deprecation_warnings_and_errors.h>
35# include <CGAL/Complex_2_in_triangulation_3.h>
36# include <CGAL/IO/facets_in_complex_2_to_triangle_mesh.h>
37# include <CGAL/Implicit_surface_3.h>
38# include <CGAL/Labeled_mesh_domain_3.h>
39# include <CGAL/Mesh_complex_3_in_triangulation_3.h>
40# include <CGAL/Mesh_criteria_3.h>
41# include <CGAL/Mesh_triangulation_3.h>
42# include <CGAL/Polyhedron_3.h>
43# include <CGAL/Surface_mesh.h>
44# include <CGAL/Surface_mesh_default_triangulation_3.h>
45# include <CGAL/Triangulation_2.h>
46# include <CGAL/Triangulation_3.h>
47# include <CGAL/make_mesh_3.h>
48# include <CGAL/make_surface_mesh.h>
54#ifdef DEAL_II_WITH_CGAL
87 template <
int spacedim,
typename CGALTriangulation>
89 add_points_to_cgal_triangulation(
const std::vector<
Point<spacedim>> &points,
90 CGALTriangulation &triangulation);
123 template <
typename CGALTriangulation,
int dim,
int spacedim>
125 cgal_triangulation_to_dealii_triangulation(
126 const CGALTriangulation &cgal_triangulation,
152 template <
typename CGALTriangulationType,
153 typename CornerIndexType,
154 typename CurveIndexType>
156 cgal_triangulation_to_dealii_triangulation(
157 const CGAL::Mesh_complex_3_in_triangulation_3<CGALTriangulationType,
184 template <
typename CGAL_MeshType>
186 cgal_surface_mesh_to_dealii_triangulation(
const CGAL_MeshType &cgal_mesh,
193 template <
int spacedim,
typename CGALTriangulation>
195 add_points_to_cgal_triangulation(
const std::vector<
Point<spacedim>> &points,
196 CGALTriangulation &triangulation)
198 Assert(triangulation.is_valid(),
200 "The triangulation you pass to this function should be a valid "
201 "CGAL triangulation."));
203 std::vector<typename CGALTriangulation::Point> cgal_points(points.size());
204 std::transform(points.begin(),
208 return CGALWrappers::dealii_point_to_cgal_point<
209 typename CGALTriangulation::Point>(p);
212 triangulation.insert(cgal_points.begin(), cgal_points.end());
213 Assert(triangulation.is_valid(),
215 "The Triangulation is no longer valid after inserting the points. "
221 template <
typename CGALTriangulationType,
222 typename CornerIndexType,
223 typename CurveIndexType>
225 cgal_triangulation_to_dealii_triangulation(
226 const CGAL::Mesh_complex_3_in_triangulation_3<CGALTriangulationType,
232 using C3T3 = CGAL::Mesh_complex_3_in_triangulation_3<CGALTriangulationType,
237 std::vector<Point<3>> dealii_vertices;
238 std::map<typename C3T3::Vertex_handle, unsigned int>
239 cgal_to_dealii_vertex_map;
241 std::size_t inum = 0;
242 for (
auto vit = cgal_triangulation.triangulation().finite_vertices_begin();
243 vit != cgal_triangulation.triangulation().finite_vertices_end();
246 if (vit->in_dimension() <= -1)
248 cgal_to_dealii_vertex_map[vit] = inum++;
249 dealii_vertices.emplace_back(
250 CGALWrappers::cgal_point_to_dealii_point<3>(vit->point()));
254 std::vector<CellData<3>> cells;
255 for (
auto cgal_cell = cgal_triangulation.cells_in_complex_begin();
256 cgal_cell != cgal_triangulation.cells_in_complex_end();
260 for (
unsigned int i = 0; i < 4; ++i)
261 cell.vertices[i] = cgal_to_dealii_vertex_map[cgal_cell->vertex(i)];
262 cell.manifold_id = cgal_triangulation.subdomain_index(cgal_cell);
263 cells.push_back(cell);
268 if constexpr (std::is_integral_v<typename C3T3::Surface_patch_index>)
270 for (
auto face = cgal_triangulation.facets_in_complex_begin();
271 face != cgal_triangulation.facets_in_complex_end();
274 const auto &[cgal_cell, cgal_vertex_face_index] = *face;
280 for (
int i = 0; i < 4; ++i)
281 if (i != cgal_vertex_face_index)
282 dealii_face.vertices[j++] =
283 cgal_to_dealii_vertex_map[cgal_cell->vertex(i)];
284 dealii_face.manifold_id =
285 cgal_triangulation.surface_patch_index(cgal_cell,
286 cgal_vertex_face_index);
291 if constexpr (std::is_integral_v<typename C3T3::Curve_index>)
293 for (
auto edge = cgal_triangulation.edges_in_complex_begin();
294 edge != cgal_triangulation.edges_in_complex_end();
297 const auto &[cgal_cell,
v1, v2] = *edge;
299 dealii_edge.vertices[0] =
300 cgal_to_dealii_vertex_map[cgal_cell->vertex(
v1)];
301 dealii_edge.vertices[1] =
302 cgal_to_dealii_vertex_map[cgal_cell->vertex(v2)];
303 dealii_edge.manifold_id =
304 cgal_triangulation.curve_index(cgal_cell->vertex(
v1),
305 cgal_cell->vertex(v2));
317 template <
typename CGALTriangulation,
int dim,
int spacedim>
319 cgal_triangulation_to_dealii_triangulation(
320 const CGALTriangulation &cgal_triangulation,
324 ExcMessage(
"The dimension of the input CGAL triangulation (" +
325 std::to_string(cgal_triangulation.dimension()) +
326 ") does not match the dimension of the output "
327 "deal.II triangulation (" +
328 std::to_string(dim) +
")."));
331 ExcMessage(
"The output triangulation object needs to be empty."));
334 std::vector<Point<spacedim>> vertices(
335 cgal_triangulation.number_of_vertices());
336 std::vector<CellData<dim>> cells;
340 std::map<typename CGALTriangulation::Vertex_handle, unsigned int>
344 for (
const auto &v : cgal_triangulation.finite_vertex_handles())
347 CGALWrappers::cgal_point_to_dealii_point<spacedim>(v->point());
352 const auto has_faces = boost::hana::is_valid(
353 [](
auto &&obj) ->
decltype(obj.finite_face_handles()) {});
355 const auto has_cells = boost::hana::is_valid(
356 [](
auto &&obj) ->
decltype(obj.finite_cell_handles()) {});
359 if constexpr (
decltype(has_faces(cgal_triangulation)){})
362 if (cgal_triangulation.dimension() == 2)
363 for (
const auto &f : cgal_triangulation.finite_face_handles())
366 for (
unsigned int i = 0;
369 cell.vertices[i] = vertex_map[f->vertex(i)];
370 cells.push_back(cell);
372 else if (cgal_triangulation.dimension() == 1)
374 for (
const auto &e : cgal_triangulation.finite_edges())
378 const auto &f =
e.first;
379 const auto &i =
e.second;
387 for (
unsigned int j = 0;
391 cell.vertices[
id++] = vertex_map[f->vertex(j)];
392 cells.push_back(cell);
399 else if constexpr (
decltype(has_cells(cgal_triangulation)){})
402 if (cgal_triangulation.dimension() == 3)
403 for (
const auto &c : cgal_triangulation.finite_cell_handles())
406 for (
unsigned int i = 0;
409 cell.vertices[i] = vertex_map[c->vertex(i)];
410 cells.push_back(cell);
412 else if (cgal_triangulation.dimension() == 2)
414 for (
const auto &facet : cgal_triangulation.finite_facets())
418 const auto &c = facet.first;
419 const auto &i = facet.second;
427 for (
unsigned int j = 0;
431 cell.vertices[
id++] = vertex_map[c->vertex(j)];
432 cells.push_back(cell);
434 else if (cgal_triangulation.dimension() == 1)
436 for (
const auto &edge : cgal_triangulation.finite_edges())
439 const auto &[c, i, j] = edge;
441 cell.vertices[0] = vertex_map[c->vertex(i)];
442 cell.vertices[1] = vertex_map[c->vertex(j)];
443 cells.push_back(cell);
455 template <
typename CGAL_MeshType>
457 cgal_surface_mesh_to_dealii_triangulation(
const CGAL_MeshType &cgal_mesh,
462 "Triangulation must be empty upon calling this function."));
464 const auto is_surface_mesh =
465 boost::hana::is_valid([](
auto &&obj) ->
decltype(obj.faces()) {});
467 const auto is_polyhedral =
468 boost::hana::is_valid([](
auto &&obj) ->
decltype(obj.facets_begin()) {});
471 std::vector<::Point<3>> vertices;
472 std::vector<CellData<2>> cells;
476 if constexpr (
decltype(is_surface_mesh(cgal_mesh)){})
480 vertices.reserve(cgal_mesh.num_vertices());
481 std::map<typename CGAL_MeshType::Vertex_index, unsigned int> vertex_map;
484 for (
const auto &v : cgal_mesh.vertices())
486 vertices.emplace_back(CGALWrappers::cgal_point_to_dealii_point<3>(
487 cgal_mesh.point(v)));
493 for (
const auto &face : cgal_mesh.faces())
495 const auto face_vertices =
496 CGAL::vertices_around_face(cgal_mesh.halfedge(face), cgal_mesh);
498 AssertThrow(face_vertices.size() == 3 || face_vertices.size() == 4,
499 ExcMessage(
"Only triangle or quadrilateral surface "
500 "meshes are supported in deal.II"));
503 unsigned int vertex_no = 0;
504 for (
const auto &v : face_vertices)
505 c.vertices[vertex_no++] = vertex_map[v];
508 if (face_vertices.size() == 4)
509 std::swap(c.vertices[3], c.vertices[2]);
511 cells.emplace_back(c);
514 else if constexpr (
decltype(is_polyhedral(cgal_mesh)){})
518 vertices.reserve(cgal_mesh.size_of_vertices());
519 std::map<
decltype(cgal_mesh.vertices_begin()),
unsigned int> vertex_map;
522 for (
auto it = cgal_mesh.vertices_begin();
523 it != cgal_mesh.vertices_end();
526 vertices.emplace_back(
527 CGALWrappers::cgal_point_to_dealii_point<3>(it->point()));
528 vertex_map[it] = i++;
533 for (
auto face = cgal_mesh.facets_begin();
534 face != cgal_mesh.facets_end();
537 auto j = face->facet_begin();
538 const unsigned int vertices_per_face = CGAL::circulator_size(j);
539 AssertThrow(vertices_per_face == 3 || vertices_per_face == 4,
540 ExcMessage(
"Only triangle or quadrilateral surface "
541 "meshes are supported in deal.II. You "
542 "tried to read a mesh where a face has " +
543 std::to_string(vertices_per_face) +
544 " vertices per face."));
547 for (
unsigned int vertex_no = 0; vertex_no < vertices_per_face;
550 c.vertices[vertex_no] = vertex_map[j->vertex()];
554 if (vertices_per_face == 4)
555 std::swap(c.vertices[3], c.vertices[2]);
557 cells.emplace_back(c);
564 "Unsupported CGAL surface triangulation type."));
constexpr 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 DEAL_II_ASSERT_UNREACHABLE()
#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 ReferenceCell< 1 > Line
constexpr ReferenceCell< 2 > Triangle
constexpr ReferenceCell< 3 > Tetrahedron
std::vector< CellData< 2 > > boundary_quads
std::vector< CellData< 1 > > boundary_lines