cgal/Mesh_3/doc/Mesh_3/Mesh_3.txt

1429 lines
59 KiB
Plaintext
Executable File

namespace CGAL {
/*!
\mainpage User Manual
\anchor Chapter_3D_Mesh_Generation
\anchor userchaptermesh3
\authors Pierre Alliez, Clément Jamin, Laurent Rineau, Stéphane Tayeb, Jane Tournois, Mariette Yvinec
\cgalAutoToc
\cgalFigureBegin{figuremultilabel_mesher,multilabel_mesher.jpg}
Cut-view of a multi-domain 3D mesh generated from a segmented image.
\cgalFigureEnd
\section Mesh_3_section_intro Introduction
This package is devoted to the generation of isotropic simplicial
meshes discretizing 3D domains.
The domain to be meshed is a subset of 3D space, required to be bounded.
The domain may be connected or composed of multiple components
and/or subdivided in several subdomains.
Boundary and subdivision surfaces are either
smooth or piecewise smooth surfaces, formed with planar or curved surface patches.
Surfaces may exhibit 1-dimensional features (e.g. crease edges)
and 0-dimensional features (e.g. singular points as corners
tips, cusps or darts), that have to be fairly
approximated in the mesh.
The output mesh is a 3-dimensional triangulation,
including subcomplexes that approximate each input domain feature: subdomain,
boundary surface patch or input domain feature with dimension 0 or 1.
Thus, the output mesh includes a 3D submesh covering each subdomain,
a surface mesh approximating each boundary or subdividing
surface patch, a polyline approximation for each
1-dimensional feature and
of course a vertex on each corner.
The main entry points of the package are
two global functions that respectively generate
and refine such meshes.
The mesh generator is customized to output a mesh
that fits as much as possible the user needs,
for instance in terms of sizing field
or with respect to some user customized quality criteria.
The meshing engine used in this mesh generator
is based on Delaunay refinement \cgalCite{c-gqmgc-93}, \cgalCite{r-draq2d-95}, \cgalCite{s-tmgdr-98}.
It uses the notion of restricted Delaunay triangulation
to approximate 1-dimensional curves and surface patches \cgalCite{cgal:bo-pgsms-05}.
Before the refinement, a mechanism of protecting balls is set up on 1-dimensional features, if any,
to ensure a fair representation
of those features in the mesh, and also to guarantee the termination of the refinement process,
whatever may be the input geometry, in particular whatever small angles
the boundary and subdivision surface patches may form \cgalCite{cgal:cdl-pdma-07}, \cgalCite{cgal:cdr-drpsc-07}.
The Delaunay refinement is followed by a mesh optimization phase
to remove slivers and provide a good quality mesh.
Optionally, the meshing and optimization algorithms support multi-core shared-memory
architectures to take advantage of available parallelism.
\subsection Mesh_3InputDomain Input Domain
The domain to be meshed is assumed to be bounded
and representable as a pure
3D complex. A 3D complex is a set of faces with dimension 0,
1, 2, and 3 such that
all faces are pairwise interior disjoint
and the boundary of each face of the complex is the union of lower-dimensional faces
of the complex.
The 3D complex is pure, meaning that each face is included in a face of dimension 3,
so that the complex is entirely described by the set of its 3D faces and their subfaces.
However the 3D complex needs not be connected.
The set of faces with dimension lower or equal than 2 forms a 2D
subcomplex which needs not be manifold, neither pure, nor connected:
some 3D faces may have dangling 2D or 1D faces in their boundary faces.
In the rest of the documentation, we will refer to the
input 3D complex as the input domain. The faces of the input domain
with dimension 0, 1, 2, and 3 are called respectively
<I>corners</I>, <I>curves</I>, <I>surface patches</I>, and <I>subdomains</I>
to clearly distinguish them from the faces of the mesh
that are called vertices, edges, facets, and cells.
Note that the input complex faces are not required to be linear nor smooth.
Surface patches, for instance, may be smooth surface patches
or portions of surface meshes with boundaries.
Curves may be for instance straight segments, parameterized curves
or polylines. Each of those features will be accurately represented in the final mesh.
The 0 and 1-dimensional features of the input domain are usually singular points
of the subdomain boundaries, however this is not required. Furthermore, those features
are not required to cover all the subdomains boundaries singularities
but only those that need to be accurately represented in the final mesh.
In the following, we say that a domain has <I>features</I> when it has 0 and
1-dimensional features that need to be accurately represented in the mesh,
and we call those features <I>exposed features</I>.
Therefore, a domain may be without features either because all boundary surface patches
are smooth closed surfaces, or simply because the curves joining different surface patches
and the singularities of those patches need not be accurately approximated
in the final mesh.
Note also that input complex faces are not required to be connected.
Faces of the input domain are identified by indices.
If a subdomain is not connected, its different components receive the same index.
Likewise different surface patches, curves, or corners may share the same index.
Each connected component of a feature will be accurately represented
in the final mesh.
Note however that the occurrence of multiply connected faces in the
input complex may affect the relevance of internal topological checks
performed by the mesh generator.
The domain is passed to the mesh generation function
as a domain class, often called the oracle,
that provides predicates and constructors related to the domain,
the subdomains, the boundary surface patches,
and also the 0 and 1-dimensional exposed features, if any.
Mainly, the oracle provides a predicate to test
if a given query point belongs
to the domain or not
and to find in which subdomain it lies in, in the affirmative case.
The domain class also provides predicates and constructors to test the intersection of a query line segment
with the boundary surface patches and to construct intersection points, if any.
Lastly, if the input domain includes 1-dimensional exposed features, the domain class
provides a way to construct sample points on these features.
The current implementation provides classes to represent
domains bounded by isosurfaces of implicit functions, polyhedral domains,
and domains defined through 3D labeled images.
Currently, 1-dimensional features may be defined as segments and polyline segments.
\subsection Mesh_3OutputMesh Output Mesh
The resulting mesh is output as a subcomplex of a
\ref CGAL::Regular_triangulation_3 "weighted Delaunay 3D triangulation",
in a class providing various iterators
on mesh elements.
The 3D triangulation provides approximations of the
subdomains, surface patches, curves,
and corners according to the restricted
Delaunay triangulation paradigm. This means that each subdomain
is approximated by the union of the tetrahedral cells
whose circumcenters are located inside the domain
(or subdomain).
Each surface patch is approximated
by the union of the Delaunay mesh facets whose dual Voronoi edges intersect the surface patch.
Such mesh facets are called <I>surface facets</I> in the following.
The 1-dimensional exposed features are approximated by sequences of mesh edges
and the 0-dimensional exposed features are represented by mesh vertices.
It is possible to extract the facets of the complex
as a `FaceGraph`, using the function `facets_in_complex_3_to_triangle_mesh()`.
\subsection Mesh_3DelaunayRefinement Delaunay Refinement
\anchor introsecparam
The mesh generation algorithm is mainly a Delaunay refinement process.
The Delaunay refinement is
preceded by a protecting phase to ensure an accurate representation
of 1-dimensional features, if any,
and followed by an optimization phase to achieve a good quality mesh.
The Delaunay refinement process is driven by criteria
concerning either the size and shape of mesh cells
and surface facets.
The refinement process terminates when there are
no more mesh cells or surface facets violating the criteria.
The criteria are designed to achieve a nice spread of the mesh vertices
while ensuring the termination of the refinement process.
Those criteria may be somehow tuned to the user needs
to achieve for instance the respect of a sizing field by mesh elements,
some topological conditions on the representation of boundary surfaces in the mesh,
and/or some error bound for the approximation of boundary surfaces.
To some extent, the user may tune the Delaunay refinement
to a prescribed trade-off
between mesh quality and mesh density.
The mesh density refers to the number of mesh vertices and cells,
i.e.\ to the complexity of the mesh.
The mesh quality referred to here is measured by the radius edge
ratio of surface facets end mesh cells, where the radius edge ratio of
a simplex (triangle or tetrahedron) is the ratio between its circumradius
and its shortest edge length.
\subsection Mesh_3Protectionof0and1dimensionalExposed Protection of 0 and 1-dimensional Exposed Features
If the domain description includes 0 dimensional features,
the corresponding points are inserted into the Delaunay triangulation
from the start.
If the domain has 1-dimensional exposed features,
the method of protecting balls \cgalCite{cgal:cdl-pdma-07}, \cgalCite{cgal:cdr-drpsc-07}
is used to achieve an accurate representation of those features in the mesh
and to guarantee that the refinement process terminates
whatever may be the dihedral angles formed by input surface patches incident to a
given 1-feature or the angles formed by two 1-features incident to a 0-feature.
According to this method, the 1-dimensional features are
sampled with points and covered by protecting balls centered on the sample points,
in such a way that:
- no three balls intersect;
- no pair of balls centered on different 1-features intersect.
The triangulation embedding the mesh is in fact
a weighted Delaunay triangulation, and the triangulation
is initialized by the insertion of all the protecting
balls, regarded as weighted points.
The Delaunay refinement process
is then launched as before except that refinement points
are no longer circumcenters but are
weighted circumcenters.
All Steiner vertices inserted by the refinement process are given a zero weight.
The method guarantees:
- that each segment joining
two successive centers on a 1-dimensional feature will stay in the triangulation,
thus ensuring an accurate approximation of the 1-dimensional features;
- that the refinement process will never try to insert a refinement point in the union of the
protecting balls, which ensures the termination of the refinement process.
\subsection Mesh_3OptimizationPhase Optimization Phase
Any tetrahedron that is quasi degenerate has a big radius edge ratio, except
those belonging to the family of slivers. A sliver is easily obtained
as the convex hull of 4 points close to the equatorial circle of a 3D
ball and roughly equally spread along this circle.
The Delaunay refinement tracks tetrahedra with big radius edge ratio
and therefore eliminates all kinds of
badly shaped tetrahedra except slivers.
Therefore, some sliver-shaped tetrahedra may still be present in the mesh
at the end of the refinement process.
The optimization phase aims to eliminate these slivers.
The optimization phase is a sequence of optimization processes,
amongst the following available optimizers: an ODT-smoother,
a Lloyd-smoother, a sliver perturber, and a sliver exuder.
The Lloyd and ODT-smoother are global optimizers
moving the mesh vertices to minimize
a mesh energy. Those optimizers are described respectively in
\cgalCite{cgal:dfg-cvtaa-99t}, \cgalCite{cgal:dw-tmgob-02} and in \cgalCite{cgal::c-mssbo-04}, \cgalCite{cgal:acyd-vtm-05}.
In both cases the mesh energy
is the `L1` error resulting from the interpolation
of the function \f$ f(x) =x^2\f$ by a piecewise linear function.
In the case of the Lloyd smoother,
the interpolation is linear in each Voronoi cell of the set of mesh vertices.
In the case of the ODT-smoother, the interpolation is linear in each cell
of the Delaunay triangulation of the mesh vertices,
hence the name `ODT` which is an abbreviation for *Optimal Delaunay Triangulation*.
\cgalFigureBegin{mesh_3paraboloid,paraboloid.jpg}
The one dimensional illustration of the mesh energy minimized by ODT (left) and Lloyd (right) smoothers.
\cgalFigureEnd
The Lloyd optimizer is known to be blind to the occurrence of slivers in the mesh
while the ODT-smoother tends to chase them out.
Both of them are global optimizers,
meaning that they try to improve
the whole mesh rather than focusing on the worst elements. However, both are empirically known
to be very efficient as a preliminary step of optimization as they tend to enhance the
efficiency of the perturber and/or the exuder applied afterwards, see \cgalFigureRef{figureoptimization}
The perturber and the exuder focus on improving the worst mesh elements.
The perturber \cgalCite{cgal:tsa-ps3dd-09} improves the meshes by local changes
in the vertices positions
aiming to make slivers disappear. The exuder \cgalCite{cgal:cdeft-slive-00}
chases the remaining slivers by
re-weighting mesh vertices with optimal weights.
Each optimization process can be activated or not, and tuned
according to the user requirements and the available time.
By default, only the perturber and the exuder are activated.
Optimization processes are designed to improve mesh quality. However, beware that such an improvement
is obtained by perturbing mesh vertices and modifying the mesh connectivity which has an impact
on the strict compliance to the refinement criteria. Though a strict compliance to mesh criteria
is granted at the end of the Delaunay refinement, this may no longer be true after
some optimization processes. Also beware that the default behavior does involve some
optimization processes.
\cgalFigureBegin{figureoptimization,optimization.jpg}
Compared effect of a global optimizer and the perturber. The left part shows the distribution of dihedral angles of mesh cells, right after Delaunay refinement (top), after some ODT smoothing (middle) and after perturbation (bottom). The numbers under the histograms give the measure in degrees of the smallest and biggest dihedral angles in the mesh.
\cgalFigureEnd
\subsection Mesh_3PostProcessing Post-processing
The tetrahedral mesh generation algorithm by Delaunay refinement provided by this package
does not guarantee that all the vertices of the output mesh are actually present in the final mesh.
In most cases, all points are used, but if the geometry of the object
has small features, compared to the size of the simplices (triangles and tetrahedra),
it might be that the Delaunay facets that are selected in the restricted Delaunay
triangulation miss some vertices of the triangulation.
The concurrent version of the tetrahedral mesh generation algorithm
also inserts a small set of auxiliary vertices that belong to the triangulation
but are isolated from the complex at the end of the meshing process.
These so-called \em isolated vertices belong to the triangulation but not to any cell
of the `C3T3`. They can be removed using the function `remove_isolated_vertices()` of `CGAL::Mesh_complex_3_in_triangulation_3`.
\section Mesh_3_section_interface Interface
As of \cgal 5.6, this package uses \ref bgl_namedparameters to set parameters. More details are provided in \ref FromBoostNPtoCGALNP.
\subsection Mesh_3TheGlobalFunctions The Global Functions
A 3D mesh generation process is launched through a call
to one of the two following functions:
\code{.cpp}
template <class C3T3, class MeshDomain, class MeshCriteria, class NamedParameters>
C3T3 make_mesh_3(const MeshDomain& domain,
const MeshCriteria& criteria,
const NamedParameters& np);
template <class C3T3, class MeshDomain, class MeshCriteria, class NamedParameters>
void refine_mesh_3(C3T3& c3t3,
const MeshDomain& domain,
const MeshCriteria& criteria,
const NamedParameters& np);
\endcode
The function `make_mesh_3()` generates from scratch a mesh
of the input domain, while the function `refine_mesh_3()` refines
an existing mesh of the input domain. Note that as the protection
of 0 and 1-dimensional features does not rely on Delaunay
refinement, the function `refine_mesh_3()` has no parameter
to preserve features.
The following sections describe the different template parameters
(and their requirements) of these two global functions.
\subsection Mesh_3TheDataStructure The Data Structure
The template parameter `C3T3` is required to be a model of
the concept
`MeshComplex_3InTriangulation_3`, a data structure devised to
represent a three dimensional complex embedded in a 3D
triangulation. In both functions, an instance of type `C3T3` is used to maintain the current
approximating simplicial mesh
and to represent the final 3D mesh at the end
of the procedure.
The embedding 3D triangulation is required to be the nested type
`CGAL::Mesh_triangulation_3::type`, provided by the class template
`CGAL::Mesh_triangulation_3`. The type for this triangulation is a
wrapper around the class `CGAL::Regular_triangulation_3` whose vertex and cell base classes
are respectively models of the concepts `MeshVertexBase_3` and
`MeshCellBase_3`.
\subsection Mesh_3TheDomainOracleandtheFeaturesParameter The Domain Oracle and the Features Parameter
The template parameter `MeshDomain` is required to be a model of
the concept `MeshDomain_3`. The argument `domain` of type
`MeshDomain`
is the sole link through which the domain
to be discretized is known by the mesh generation algorithm.
This concept provides, among others,
member functions to test whether or not
a query segment intersects boundary surfaces,
and to compute an intersection point in the affirmative.
The `MeshDomain_3` concept adds member functions
which given a query point tell whether the point lies
inside or outside the domain and in which subdomain the point lies,
if inside.
If the domain description includes 0 and 1-dimensional features
that have to be accurately represented in the final mesh,
the template parameter `MeshDomain` is required to be
of a model of the concept
`MeshDomainWithFeatures_3`. The concept `MeshDomainWithFeatures_3` mainly
provides the incidence
graph of 0, 1 and 2-dimensional features,
and a member function to construct
sample points on curves.
Users whose domain is a model of `MeshDomainWithFeatures_3`
can choose to have the corners and curves of the domain
represented in the mesh or not, using the following parameters:
<UL>
<LI>\link parameters::features() `parameters::features(domain)` \endlink
sets features according to the domain,
i.e.\ 0 and 1-dimensional features are taken into account if `domain` is a
`MeshDomainWithFeatures_3`.
<LI>`parameters::no_features()` prevents the representation
of 0 and 1-dimensional features in the mesh. This is useful to get a smooth and rough approximation
of a domain with features.
</UL>
\subsection Mesh_3TheMeshingCriteria The Meshing Criteria
The template parameter `MeshCriteria` must be a model of the concept
`MeshCriteria_3`, or a model of the refined concept `MeshCriteriaWithFeatures_3`
if the domain has exposed features.
The argument of type `MeshCriteria` passed to the mesh generator specifies the
size and shape requirements for the tetrahedra in the mesh
and for the triangles in the boundary surface mesh. These criteria
condition the rules that drive the refinement process. At the end
of the refinement process, mesh elements satisfy the criteria.
Note that this may not be strictly true anymore after the optimization phase, but this
last phase is devised to only improve the mesh quality.
The criteria for surface facets are governed by the four following
parameters:
<UL>
<LI><I>`facet_angle`.</I> This parameter controls the shape of
surface facets. Specifically, it is a lower bound for the angle (in degrees) of
surface facets. When boundary surfaces are smooth, the termination of the meshing process is
guaranteed if this angular bound is at most 30 degrees \cgalCite{c-gqmgc-93}.
<LI><I>`facet_size`.</I> This parameter controls the size of surface facets.
Each surface facet has
a surface Delaunay ball which is a ball circumscribing the surface facet and
centered on the surface patch. The parameter `facet_size` is
either a constant or a spatially variable scalar field, providing an
upper bound for the radii of surface Delaunay balls.
<LI><I>`facet_distance`.</I> This parameter controls the approximation error of boundary and subdivision surfaces.
Specifically, it is
either a constant or a spatially variable scalar field. It
provides an upper bound for the distance between the circumcenter
of a surface facet and the center of a surface Delaunay ball of this facet.
<LI><I>`facet_topology`.</I> This parameter controls the set of topological constraints
which have to be verified by each surface facet. By default, each vertex of a surface
facet has to be located on a surface patch, on a curve, or on a corner. It can
also be set to check whether the three vertices of a surface facet belongs to the same
surface patch. This has to be done cautiously, as such a criterion needs that each
intersection of input surface patches is an input 1-dimensional feature.
</UL>
The criteria for mesh cells are governed by two parameters:
<UL>
<LI><I>`cell_radius_edge_ratio`.</I> This parameter controls the
shape of mesh cells (but can't filter slivers, as we discussed earlier).
It is an upper bound for the ratio
between the circumradius of a
mesh tetrahedron and its shortest edge.
There is a theoretical bound for this parameter:
the Delaunay refinement process is guaranteed to terminate
for values of `cell_radius_edge_ratio` bigger than 2.
<LI><I>`cell_size`.</I>
This parameter controls the size of mesh tetrahedra.
It is either a scalar or a spatially variable scalar field.
It provides an upper bound on the circumradii of the
mesh tetrahedra.
</UL>
\cgalFigureRef{figureparameters} shows how the mesh generation process
behaves with respect to these parameters.
\cgalFigureAnchor{figureparameters}
<CENTER>
<TABLE BORDER=0>
<TR>
<TD> </TD>
<TD><IMG border="0" height="250px" src="./implicit_domain.jpg"> </TD>
<TD> </TD>
</TR>
<TR>
<TD><IMG border="0" height="250px" src="./implicit_domain_3.jpg"></TD>
<TD><IMG border="0" height="250px" src="./implicit_domain_4.jpg"></TD>
<TD><IMG border="0" height="250px" src="./implicit_domain_5.jpg"></TD>
</TR>
</TABLE>
</CENTER>
\cgalFigureCaptionBegin{figureparameters}
Top: the mesh is obtained using the parameters \f$ (25,0.15,0.05)\f$
for the angular bound, radius bound and distance bound of surface
facets and \f$ (4,0.2) \f$ for the radius-edge bound and radius bound
of mesh cells. The result is a uniform mesh which contains tetrahedra
of about the same size. Bottom left : the mesh is obtained by relaxing
the <I> size bound</I> of tetrahedra and facets. The result is a small
coarse mesh. Bottom middle : the mesh is obtained from the previous
one by tightening the <I>distance bound</I> of surface facets to \f$
0.01\f$. The result is then a graded 3D mesh with a dense surface mesh
achieving a precise approximation. Bottom right : the mesh is obtained
from the previous one by fixing <I>radius bound</I> of surface facets
to \f$ 0.01\f$. The surface mesh is then denser to achieve the size
bound.
\cgalFigureCaptionEnd
If the domain has 1-dimensional exposed features, the `criteria` includes
a sizing field to guide
the sampling of 1-dimensional features with protecting balls centers.
<UL>
<LI><I>`edge_size`</I>. This constant or variable scalar field is used as an upper bound for the distance between two
protecting ball centers that are consecutive on a 1-feature. This parameter has to be set to a positive value when
1-dimensional features protection is used.
</UL>
\subsection Mesh_3TheOptimizationParameters The Optimization Parameters
The four additional parameters are optimization parameters.
They control which optimization processes are performed
and enable the user to tune the parameters of the activated optimization processes.
These parameters have internal types which are not described
but the library provides global functions to generate
appropriate values of these types:
<UL>
<LI>`parameters::lloyd()` and `parameters::no_lloyd()` activate and deactivate the Lloyd smoother.
<LI>`parameters::odt()` and `parameters::no_odt()` activate and deactivate the ODT-smoother.
<LI>`parameters::perturb()` and `parameters::no_perturb()` activate and deactivate the perturber.
<LI>`parameters::exude()` and `parameters::no_exude()` activate and deactivate the exuder.
</UL>
These parameters are optional and can be passed in any order.
If one parameter is not passed the default value is used. By default,
only the perturber and the exuder are activated.
Note that whatever may be the optimization processes activated by `make_mesh_3()`
or `refine_mesh_3()`,
they are always launched in the order that is a suborder
of the following: *ODT-smoother*, *Lloyd-smoother*, *perturber*, and *exuder*.
The package also provides four global functions to launch
each optimization process independently. These functions are useful for advanced experimentation
on the efficiency of each optimization method.
Note however that the exuder adds on mesh vertices weights that are conditioned by vertices
positions.
Therefore an exudation process should never be run before
a smoother or a perturber.
For a maximum efficiency, whatever may be the optimization processes activated,
they should be launched in the order that is a suborder
of the following: *ODT-smoother*, *Lloyd-smoother*, *perturber*, and *exuder*.
\code{.cpp}
template< class C3T3, class MeshDomain >
Mesh_optimization_return_code lloyd_optimize_mesh_3(C3T3& c3t3, const MeshDomain& domain);
template< class C3T3, class MeshDomain >
Mesh_optimization_return_code odt_optimize_mesh_3(C3T3& c3t3, const MeshDomain& domain);
template< class C3T3, class MeshDomain >
Mesh_optimization_return_code perturb_mesh_3(C3T3& c3t3, const MeshDomain& domain);
template< class C3T3 >
Mesh_optimization_return_code exude_mesh_3(C3T3& c3t3);
\endcode
Note that the global functions activating the optimization processes or launching
those processes have themselves parameters (see details in reference pages) to tune the optimization process.
\subsection Mesh_3ParallelAlgorithms Parallel Algorithms
Enabling parallel meshing and optimization algorithms is achieved through
setting the third template parameter of the `Mesh_triangulation_3` class
to `Parallel_tag`, when defining the triangulation type.
Note that when the user provides his/her own vertex and
cell base classes, the `MeshVertexBase_3` and
`MeshCellBase_3` concepts impose additional requirements.
Parallel algorithms require the executable to be linked against the
<a href="https://github.com/oneapi-src/oneTBB">Intel TBB library</a>.
To control the number of threads used, the user may use the tbb::task_scheduler_init class.
See the <a href="https://software.intel.com/content/www/us/en/develop/documentation/onetbb-documentation/top.html">TBB documentation</a>
for more details.
\section Mesh_3_section_io Input/Output
Several file formats are supported for writing a mesh:
- \ref IOStreamMedit, using \link CGAL::IO::write_MEDIT() `CGAL::IO::write_MEDIT()`\endlink
- \ref IOStreamVTK, using \link CGAL::IO::output_to_vtu() `CGAL::IO::output_to_vtu()`\endlink
- \ref IOStreamAvizo, using \link CGAL::IO::output_to_avizo `CGAL::IO::output_to_avizo()`\endlink
- \ref IOStreamTetgen, using \link CGAL::IO::output_to_tetgen `CGAL::IO::output_to_tetgen()`\endlink
\section Mesh_3_section_examples Examples
\subsection Mesh_33DDomainsBoundedbyIsosurfaces 3D Domains Bounded by Isosurfaces
\subsubsection Mesh_33DDomainsImplicitIsosurfaces 3D Domains Bounded by Implicit Isosurfaces
The following code produces a 3D mesh for a domain whose boundary surface
is an isosurface defined by an implicit
function. \cgalFigureRef{figureimplicit_domain} shows a cut view of the
resulting mesh.
Note the use of named parameters in the
constructor of the `Mesh_criteria` instance.
\cgalExample{Mesh_3/mesh_implicit_sphere.cpp}
\cgalFigureBegin{figureimplicit_domain,implicit_domain.jpg}
Cut view of a 3D mesh produced from an implicit domain
\cgalFigureEnd
\subsection Mesh_3MeshingMultipleDomains Meshing Multiple Domains
\anchor Mesh_3_subsection_examples_multi_domain
\subsubsection Mesh_3MeshingMultipleDomains_1 Construction from a Vector of Implicit Functions
The following code produces a 3D mesh for a domain consisting of several subdomains.
It uses `Implicit_multi_domain_to_labeling_function_wrapper` as model of `ImplicitFunction` which is required by `Labeled_mesh_domain_3`.
\cgalFigureRef{figuremulti_domain} shows a view and a cut view of the
resulting mesh.
\cgalExample{Mesh_3/mesh_implicit_domains.cpp}
\cgalFigureBegin{figuremulti_domain,multi_domain.jpg,multi_domain_cut.jpg}
View (left) and cut view (right) of a 3D mesh of a torus intersecting sphere.
\cgalFigureEnd
\subsubsection Mesh_3MeshingMultipleDomains_2 Construction from a Vector of Implicit Functions and a Vector of Strings
The following code produces a 3D mesh for a domain consisting of several subdomains too.
Here, the set of subdomains is given by a vector of vector of signs, whereas the set was built automatically in the previous example.
Each subdomain corresponds to a sign vector [s1, s2, ..., sn] where si is the sign of the function fi(p) at a point p of the subdomain.
\cgalFigureRef{figuremulti_domain2} shows a view of the
resulting mesh.
\cgalExample{Mesh_3/mesh_implicit_domains_2.cpp}
\cgalFigureBegin{figuremulti_domain2,multi_domain_2.jpg}
View of a 3D mesh of the relative complement of a torus in a sphere.
\cgalFigureEnd
\subsubsection Mesh_3MeshingMultipleDomains_3 Construction of a Hybrid Domain : From an Implicit and a Polyhedral Domain
The example code of \ref Mesh_3/mesh_hybrid_mesh_domain.cpp produces a 3D mesh for a domain consisting of several subdomains too.
Here, the set of subdomains is given by two subdomains of different types : a domain defined by an implicit sphere,
and a domain defined by the triangulated surface of a cube.
\cgalFigureRef{mesh3HybridDomainExample} shows the results with or without the
protection of the 1D-features.
\cgalFigureAnchor{mesh3HybridDomainExample}
<center>
<table border=0>
<tr>
<td><img border="0" src="./hybrid_domain.jpg"></td>
<td><img border="0" src="./hybrid_domain_mesh_no_protection.jpg"></td>
<td><img border="0" src="./hybrid_domain_mesh_protection.jpg"></td>
</tr>
</table>
</center>
\cgalFigureCaptionBegin{mesh3HybridDomainExample}
Left: the input hybrid domain.
Middle : the output mesh without any call to `%add_features()`.
Right : the output mesh with added 1D-features at the intersection of subdomains.
\cgalFigureCaptionEnd
\subsection Mesh_3PolyhedralDomains Polyhedral Domains
\anchor Mesh_3_subsection_examples_polyhedral
\subsubsection Mesh_33DPolyhedralDomains 3D Polyhedral Domains
The following code produces a 3D mesh for a domain
defined by a polyhedral surface. \cgalFigureRef{figurepolyhedral_domain}
shows the resulting mesh.
\cgalExample{Mesh_3/mesh_polyhedral_domain.cpp}
\cgalFigureBegin{figurepolyhedral_domain,polyhedral_domain.jpg,polyhedral_domain_2.jpg}
View of 3D meshes produced from a polyhedral domain. (i) is a view of file out_1.mesh and (ii) is a view of file out_2.mesh. Code from subsection \ref Mesh_3_subsection_examples_polyhedral generates these files.
\cgalFigureEnd
\subsubsection Mesh_33DSurfaceInsidePolyhedralDomain Remeshing a Polyhedral Domain with Surfaces
In the following example we have a "bounding polyhedron" which defines the meshing domain and two surfaces inside this domain.
The surfaces inside the domain may be closed surfaces as well as surfaces with boundaries. In the case of a closed surface
the volume delimited by this surface is also considered as inside the domain.
\cgalExample{Mesh_3/mesh_polyhedral_domain_with_surface_inside.cpp}
\cgalFigureBegin{figurepolyhedral_domain_with_surface,polyhedral_domain_with_surface.jpg}
View of 3D meshes produced from a polyhedral domain with a nested surface.
\cgalFigureEnd
\subsubsection Mesh_3RemeshingPolyhedralSurface Remeshing a Polyhedral Surface
The following code creates a polyhedral domain, with only one polyhedron,
and no "bounding polyhedron". The volumetric part of the domain may be empty
and should not be meshed.
In this case, it is recommended to use the `CGAL::parameters::surface_only()` parameter
to speedup the meshing of the surface only.
This enables to remesh a surface, and is equivalent to the function `make_surface_mesh()`.
\cgalExample{Mesh_3/remesh_polyhedral_surface.cpp}
\cgalFigureBegin{figureremeshing,remeshing.jpg}
View of a remeshed surface. (Left) input mesh (Right) output mesh. Code from subsection \ref Mesh_3RemeshingPolyhedralSurface generates the file.
\cgalFigureEnd
\subsection Mesh_3DomainsFrom3DImages Domains From 3D Images
\subsubsection Mesh_33DDomainsGrayImageIsosurfaces 3D Domains Bounded by Isosurfaces in 3D Gray-Level Images
The following example produces a 3D mesh for a domain whose boundary surface
is the isosurface associated to an isovalue inside the input gray-level
3D image. In the distribution you can also find the example \ref Mesh_3/mesh_3D_gray_vtk_image.cpp which can deal with `*.nii` as well as `DICOM` files as input.
\cgalExample{Mesh_3/mesh_3D_gray_image.cpp}
\subsubsection Mesh_3DomainsFromSegmented3DImages Domains From Segmented 3D Images
\anchor Mesh_3_subsection_examples_3d_image
The following code produces a 3D mesh from
a 3D image. The image is a segmented medical image in which each
voxel is associated a label in accordance with
the tissue the voxel belongs to.
The domain is therefore a multi-domain
where each subdomain corresponds to a specific tissue.
In the following example, the image is read from the file
`liver.inr.gz` which is encoded in the format of the library Inrimage
`https://www-pequan.lip6.fr/~bereziat/inrimage/`.
The resulting mesh is shown in \cgalFigureRef{figureliver_3d_image_mesh}.
\cgalExample{Mesh_3/mesh_3D_image.cpp}
\cgalFigureBegin{figureliver_3d_image_mesh,liver.jpg}
Cut view of a 3D mesh produced from a segmented liver image. Code from subsection \ref Mesh_3_subsection_examples_3d_image generates this file.
\cgalFigureEnd
\subsubsection Mesh_3DomainsFrom3DImagesWithWeights Domains From Segmented 3D Images, with Weights
When a segmented image is given as input, the generated mesh surface sometimes sticks too closely
to the voxels surface, causing an aliasing effect.
A solution to generate a smooth and accurate output surface was described by Stalling et al in
\cgalCite{stalling1998weighted}. It consists in generating a second input image, made
of integer coefficients called *weights*, and use those weights to define smoother domain boundaries.
The 3D image of weights can be generated using `CGAL::Mesh_3::generate_label_weights()` as shown in
the following example.
\cgalExample{Mesh_3/mesh_3D_weighted_image.cpp}
\cgalFigureBegin{figure_weightedImage, weighted_images.jpg}
Surface of the output mesh generated with a very small `facet_distance`
without the weights (left, 25563 vertices) and with the weights (right, 19936 vertices).
\cgalFigureEnd
\subsubsection Mesh_3DomainsFrom3DImagesWithCustomInitialization Domains From 3D Images, with a Custom Initialization
The example \ref Mesh_3/mesh_3D_image_with_image_initialization.cpp is a modification
of \ref Mesh_3/mesh_3D_image.cpp. The goal of that example is to show how
the default initialization of the triangulation, using random rays, can be
replaced by a new implementation. In this case, the initialization detects
all connected components in the 3D segmented image, and inserts points in
the triangulation for each connected component.
\snippet Mesh_3/mesh_3D_image_with_image_initialization.cpp Meshing
The parameter `CGAL::parameters::initial_points_generator` is used.
It expects a functor that returns a set of points for the mesh
initialization (following the concept `InitialPointsGenerator_3`). The functor
`Construct_initial_points_labeled_image` is used in this example.
It constructs points using the API of the mesh domain, as follows.
First, the functor `construct_intersection` is created:
\snippet CGAL/Mesh_3/Construct_initial_points_labeled_image.h construct intersection
then the `%Mesh_domain::Intersection` object (a `%tuple` with three
elements) is constructed using a call to the functor `construct_intersection`
\snippet CGAL/Mesh_3/Construct_initial_points_labeled_image.h use construct intersection
and eventually `%intersect_index` is the element \#1 of `%intersect`.
\snippet CGAL/Mesh_3/Construct_initial_points_labeled_image.h get construct intersection
The dimension of the underlying simplex is stored as the element \#2 of `%intersect``.
The result of the custom initialization can be seen in
\cgalFigureRef{mesh3custominitimage3D}. The generated 3D image contains a
big sphere at the center, and 50 smaller spheres, generated
randomly. Without the custom initialization, only the biggest component
(the sphere at the center) was initialized and meshed. With the custom
initialization, the initial `%c3t3` object contains points on all connected
components, and all spheres are meshed.
\cgalFigureAnchor{mesh3custominitimage3D}
<center>
<table border=0>
<tr>
<td><img border="0" src="./no-custom-init.png"></td>
<td><img border="0" src="./with-custom-init.png"></td>
</tr>
</table>
</center>
\cgalFigureCaptionBegin{mesh3custominitimage3D}
Left: the mesh without the custom initialization, only the big sphere at
the center is meshed
Right: the mesh generated after the initialization of all connected components
\cgalFigureCaptionEnd
Note that the example \ref
Mesh_3/mesh_3D_image_with_image_initialization.cpp also shows how to
create a 3D image using the undocumented API of CGAL_ImageIO.
\snippet Mesh_3/mesh_3D_image_with_image_initialization.cpp Create_the_image
The code of the function `%random_labeled_image()` is in the header file \ref
Mesh_3/random_labeled_image.h.
The example \ref Mesh_3/mesh_3D_image_with_custom_initialization.cpp features
a custom functor that initializes the triangulation.
A struct `Custom_Initial_points_generator` that places 1D-feature points
alongside a line is created.
Finally, the example \ref Mesh_3/mesh_3D_image_with_initial_points.cpp features
a point container that initializes the triangulation using the meshing parameter
`parameters::initial_points()`.
\subsection Mesh_3UsingVariableSizingField Using Variable Sizing Field
\subsubsection Mesh_3SizingFieldasanAnalyticalFunction Sizing Field as an Analytical Function
\anchor Mesh_3_subsubsection_examples_sphere_variable
The following example shows how to use an analytical function as sizing field.
\cgalExample{Mesh_3/mesh_implicit_sphere_variable_size.cpp}
\cgalFigureBegin{figuresphere_variable_mesh,sphere_variable.jpg}
Cut view of a 3D mesh produced from an implicit sphere with non-constant sizing field. Code from subsection \ref Mesh_3_subsubsection_examples_sphere_variable generates this file.
\cgalFigureEnd
\subsubsection Mesh_3DifferentSizingFieldforDifferentSubdomains Different Sizing Field for Different Subdomains
\anchor Mesh_3_subsubsection_examples_3d_image_variable
The following example shows how to use different size for different organs in
a 3D medical image.
\cgalExample{Mesh_3/mesh_3D_image_variable_size.cpp}
\cgalFigureBegin{figureliver_variable_mesh,liver_variable.jpg}
View of a 3D mesh produced from a 3D image with different size for different organs. Code from subsection \ref Mesh_3_subsubsection_examples_3d_image_variable generates this file.
\cgalFigureEnd
\subsubsection Mesh_3LipschitzSizingField Lipschitz Sizing Field
\anchor Mesh_3_subsubsection_examples_3d_image_lip_sizing
The following example shows how to use another custom sizing function, that is
`k`-Lipschitz. For each subdomain, the user provides the parameter `k`,
a minimal size and maximal size for cells.
\cgalExample{Mesh_3/mesh_polyhedral_domain_with_lipschitz_sizing.cpp}
\cgalFigureBegin{figurefandisk_lip_sizing,fandisk_lip.jpg}
View of a 3D mesh produced with a Lipschitz sizing field,
for a single subdomain. Code from subsection \ref Mesh_3_subsubsection_examples_3d_image_lip_sizing generates this mesh.
\cgalFigureEnd
\subsection Mesh_3MeshingDomainswithSharpFeatures Meshing Domains with Sharp Features
\anchor Mesh_3_subsection_example_polyhedral_with_edges
\subsubsection Mesh_33DPolyhedralDomainwithEdges 3D Polyhedral Domain with Edges
The following example shows how to generate a mesh from a polyhedral
surface. The output mesh conforms to the sharp features of the input surface.
\cgalExample{Mesh_3/mesh_polyhedral_domain_with_features.cpp}
\cgalFigureBegin{figurefandisk_mesh,fandisk.jpg}
View of a 3D mesh with sharp features. Code from subsection \ref Mesh_3_subsection_example_polyhedral_with_edges generates this mesh.
\cgalFigureEnd
\subsubsection Mesh_3ImplicitDomainWith1DFeatures Implicit Domain With 1D Features
The following example shows how to generate a mesh from an implicit
domain. We add by hand the intersection of the spheres as a sharp feature.
\cgalExample{Mesh_3/mesh_two_implicit_spheres_with_balls.cpp}
\cgalFigureBegin{figuretwo_spheres_mesh,twospheres.jpg}
View of a 3D mesh with sharp features generated from two intersected implicit spheres. On the left, one can see the mesh without feature preservation, and on the right the mesh with feature preservation.
\cgalFigureEnd
\subsubsection Mesh_3DomainsFromSegmented3DImagesWithFeatures Domains from Segmented 3D Images, with 1D Features
The example \ref Mesh_3/mesh_3D_image_with_features.cpp is a modification
of \ref Mesh_3/mesh_3D_image.cpp. That example shows how to generate a mesh
from a 3D labeled image (also known as "a segmented image"), that has 2D
surfaces that intersect the box corresponding to the boundary of the
image. The intersection of the 2D surface with the bounding box of the
image is composed of 1D curves, and must be defined as 1D-features in the
domain.
The first modification is the type of the mesh domain. Instead of being
`Labeled_mesh_domain_3`, it is a
`Mesh_domain_with_polyline_features_3` templated by a
`Labeled_mesh_domain_3`.
\snippet Mesh_3/mesh_3D_image_with_features.cpp Domain definition
In the %main() function, the domain is created with an additional argument - a
dedicated functor that computes the one-dimensional features, which are then
added to the domain.
\snippet Mesh_3/mesh_3D_image_with_detection_of_features.cpp Domain creation
The `CGAL::Mesh_3::Detect_features_in_image` functor is defined in its own
header file. It computes the one-dimensional features that correspond to the
intersections of the bounding box of the image with the surfaces defined by the
image, as well as polylines that lie at the intersection of three or more
subdomains (including the outside). It then constructs a graph of these polyline
features. The named constructor adds this feature graph to the domain for later
feature protection. The original feature detection algorithm was described in
\cgalCite{cgal:hssz-gmcabonbc-97}, which provides a list of possible voxel
configurations. The feature detection implemented in \cgal generalizes this
description.
The example \ref Mesh_3/mesh_3D_image_with_features.cpp shows how
user-specified input polylines can further be added as 1D features to the mesh domain.
\snippet Mesh_3/mesh_3D_image_with_features.cpp Domain creation
In the meshing criteria, if 1D features are added to the domain, the user
can define the parameter `edge_size` of the criteria class
`Mesh_criteria_3`, as follows, to set up an upper bound on the length of
the edges of the 1D-mesh corresponding to the 1D-features.
\snippet Mesh_3/mesh_3D_image_with_features.cpp Mesh criteria
The rest of the example is similar to \ref Mesh_3/mesh_3D_image.cpp.
\cgalFigureRef{mesh3protectionimage3D} shows the results without or with the
protection of the 1D-features.
\cgalFigureAnchor{mesh3protectionimage3D}
<center>
<table border=0>
<tr>
<td><img border="0" src="./no-protection.png"></td>
<td><img border="0" src="./protection-box.png"></td>
<td><img border="0" src="./protection-all.png"></td>
</tr>
</table>
</center>
\cgalFigureCaptionBegin{mesh3protectionimage3D}
Left: the mesh without any call to `%add_features()`.
Middle: the mesh with only the 1D-features computed by
`CGAL::Mesh_3::Detect_features_on_image_bbox()`.
Right: the mesh with added 1D-features in the interior of the bounding box
of the image.
\cgalFigureCaptionEnd
\subsubsection Mesh_3PolyhedralComplex Polyhedral Complex
The following example shows how to generate a mesh from a polyhedral complex
that forms a bounded domain.
The domain is defined by a group of polyhedral surfaces that are conformal.
For each facet of the input polyhedral surfaces,
the ids of incident subdomains are known.
The input surfaces intersect along polylines that are considered as sharp features,
and protected as for all domain types in this Section.
\cgalExample{Mesh_3/mesh_polyhedral_complex.cpp}
\cgalFigureRef{mesh3protectionComplex} shows the results without or with the
protection of the 1D-features.
\cgalFigureAnchor{mesh3protectionComplex}
<center>
<table border=0>
<tr>
<td><img border="0" src="./no-protection-complex.png"></td>
<td><img border="0" src="./protection-complex.png"></td>
</tr>
</table>
</center>
\cgalFigureCaptionBegin{mesh3protectionComplex}
Left: the mesh without any call to `%detect_features()`.
The mesh is overrefined next to sharp features, because the mesher tries to
reach the target `facet_distance`, by inserting centers of surface Delaunay
balls, that are not likely to be on sharp edges.
Right: the mesh with added 1D-features along sharp edges and edges shared
by at least two of the input polyhedral surfaces forming the complex.
\cgalFigureCaptionEnd
\subsubsection Mesh_3EdgesSizingField Sizing Field for Feature Edges
The following example shows how to generate a mesh from a polyhedral complex
or a polyhedral surface with polyline features.
Polyline features are covered by a set of so-called "protecting balls" which
sizes are highly related to the edge length, and
are driven by the size component of `Mesh_edge_criteria_3`
(see Section \ref Mesh_3Protectionof0and1dimensionalExposed).
The ideal size can be computed using
`Sizing_field_with_aabb_tree` that helps start the feature protection
and one-dimensional meshing process with a good initial guess.
To fit the protecting balls requirements,
no protecting ball can have its radius
larger than half of the distance from the corresponding vertex (its center),
to surface patches the
current polyline feature does not belong to.
\cgalExample{Mesh_3/mesh_polyhedral_domain_with_features_sizing.cpp}
\subsubsection Mesh_WithEdgeDistanceCriterion Approximation Criterion for Feature Edges
The following example shows how to generate a mesh with an approximation error criterion.
Polyline features are covered by a set of so-called "protecting balls" which
sizes are highly related to the `edge_size` and `edge_distance` criteria.
This edge distance is driven by the distance component of `Mesh_edge_criteria_3`
(see Section \ref Mesh_3Protectionof0and1dimensionalExposed).
The parameter `edge_distance` enables the subdivision of edges that are too far away from the
corresponding input sharp features. It may result in an output mesh with shorter edges along the
input polyline features.
\cgalExample{Mesh_3/mesh_polyhedral_domain_with_edge_distance.cpp}
\cgalFigureAnchor{mesh3edge_distance}
<center>
<table border=0>
<tr>
<td><img border="0" src="./u_arch_no_edge_distance.png" alt="u_arch mesh without edge_distance criterion"></td>
<td><img border="0" src="./u_arch_with_edge_distance.png" alt="u_arch mesh with edge_distance criterion"></td>
</tr>
</table>
</center>
\cgalFigureCaptionBegin{mesh3edge_distance}
Left: the mesh without the `%edge_distance` criterion.
Right: the mesh with the `%edge_distance` criterion set to the same value as `%facet_distance`.
\cgalFigureCaptionEnd
\subsection Mesh_3TuningMeshOptimization Tuning Mesh Optimization
\anchor Mesh_3_subsection_examples_optimization
In the previous examples, the mesh generation is launched through a call
`make_mesh_3()` with a minimal number of parameters. In such cases,
the default optimization strategy is applied: after the Delaunay refinement process
two optimization steps are performed, a perturbation and a sliver exudation.
The following examples show how to disable default optimization steps
and how to tune the parameters of optimization steps.
\subsubsection Mesh_3DisablingExudationandTuningPerturbation Disabling Exudation and Tuning Perturbation
In this first example, we show how to disable the exudation step.
The optimization phase after the refinement includes only
a perturbation phase which is launched with no time bound
and an objective of 10 degrees for the minimum dihedral angle
of the mesh.
The example shows two ways of achieving the same result. The first way
issues a single call to `make_mesh_3()` with the required optimization
process activated and tuned. In the second way, `make_mesh_3()` is first called
without any optimization process and the resulting mesh is next optimized
through a call to `perturb_mesh_3()` with tuned parameters.
\cgalExample{Mesh_3/mesh_optimization_example.cpp}
\subsubsection Mesh_3UsingLloydGlobalOptimization Using Lloyd Global Optimization
In this second example, we show how to call the Lloyd optimization on the
mesh, followed by a call to exudation. We set a time bound of 30s for the Lloyd optimization.
We set a time bound of 10s and a sliver bound of 10 degrees for the exuder.
\cgalExample{Mesh_3/mesh_optimization_lloyd_example.cpp}
\section Mesh_3Performances Performance
We provide here some benchmarks of the performance of the mesh generation algorithms.
\subsection Mesh_3DelaunayRefinement_1 Delaunay Refinement
The computer used for benchmarking is a PC running Linux64 with two Intel Xeon CPU X5450 clocked at 3.00 GHz
with 32GB of RAM. The program has been compiled with g++ v4.3.2 with the -O3 option.
These benchmarks have been done using \cgal v3.8.
Note that these benchmarks were obtained with the sequential version of the algorithm,
which does not take advantage of multi-core architectures. See the next
section for performance of parallel algorithms.
We study the refinement part of the mesh generation engine in this section. We
give the CPU time (measured by `Timer`) using the 3 provided oracles. In all experiments, we produce well
shaped elements: we set the facet angle bound and the radius edge bound to their
theoretical limit (resp. 30 degrees and 2). We also use the same uniform sizing field for facets
and cells.
\subsubsection Mesh_3ImplicitFunction Implicit Function
We mesh an analytical sphere of radius 1.
<CENTER>
<TABLE CELLSPACING=5 >
<TR><TD ALIGN=LEFT NOWRAP COLSPAN=6><HR>
<TR>
<TD ALIGN=LEFT NOWRAP>
Size bound
<TD ALIGN=LEFT NOWRAP>
vertices nb
<TD ALIGN=LEFT NOWRAP>
facets nb
<TD ALIGN=LEFT NOWRAP>
tetrahedra nb
<TD ALIGN=CENTER NOWRAP>
CPU Time (s)
<TD ALIGN=CENTER NOWRAP>
vertices/second
<TR><TD ALIGN=LEFT NOWRAP COLSPAN=6><HR>
<TR>
<TD ALIGN=LEFT NOWRAP>
0.2
<TD ALIGN=LEFT NOWRAP>
499
<TD ALIGN=LEFT NOWRAP>
488
<TD ALIGN=LEFT NOWRAP>
2,299
<TD ALIGN=CENTER NOWRAP>
0.0240
<TD ALIGN=CENTER NOWRAP>
20,800
<TR>
<TD ALIGN=LEFT NOWRAP>
0.1
<TD ALIGN=LEFT NOWRAP>
3,480
<TD ALIGN=LEFT NOWRAP>
2,046
<TD ALIGN=LEFT NOWRAP>
18,756
<TD ALIGN=CENTER NOWRAP>
0.146
<TD ALIGN=CENTER NOWRAP>
23,800
<TR>
<TD ALIGN=LEFT NOWRAP>
0.05
<TD ALIGN=LEFT NOWRAP>
25,556
<TD ALIGN=LEFT NOWRAP>
8,274
<TD ALIGN=LEFT NOWRAP>
149,703
<TD ALIGN=CENTER NOWRAP>
1.50
<TD ALIGN=CENTER NOWRAP>
17,000
<TR>
<TD ALIGN=LEFT NOWRAP>
0.025
<TD ALIGN=LEFT NOWRAP>
195,506
<TD ALIGN=LEFT NOWRAP>
33,212
<TD ALIGN=LEFT NOWRAP>
1,194,727
<TD ALIGN=CENTER NOWRAP>
17.4
<TD ALIGN=CENTER NOWRAP>
11,200
<TR>
<TD ALIGN=LEFT NOWRAP>
0.0125
<TD ALIGN=LEFT NOWRAP>
1,528,636
<TD ALIGN=LEFT NOWRAP>
134,810
<TD ALIGN=LEFT NOWRAP>
9,547,772
<TD ALIGN=CENTER NOWRAP>
179
<TD ALIGN=CENTER NOWRAP>
8,530
<TR><TD ALIGN=LEFT NOWRAP COLSPAN=6><HR>
</TABLE>
</CENTER>
\subsubsection Mesh_3PolyhedralDomain Polyhedral Domain
\cgalFigureBegin{figuremesh_3_benchmark_polyhedral,bench_polyhedral.jpg}
View of polyhedral mesh generation result (size = 0.005).
\cgalFigureEnd
We mesh a volume bounded by a closed triangulated surface made of about 50,000 vertices and 100,000 triangles.
\cgalFigureRef{figuremesh_3_benchmark_polyhedral} shows the mesh obtained when
size is set to 0.005.
<CENTER>
<TABLE CELLSPACING=5 >
<TR><TD ALIGN=LEFT NOWRAP COLSPAN=6><HR>
<TR>
<TD ALIGN=LEFT NOWRAP>
Size bound
<TD ALIGN=LEFT NOWRAP>
vertices nb
<TD ALIGN=LEFT NOWRAP>
facets nb
<TD ALIGN=LEFT NOWRAP>
tetrahedra nb
<TD ALIGN=CENTER NOWRAP>
CPU Time (s)
<TD ALIGN=CENTER NOWRAP>
vertices/second
<TR><TD ALIGN=LEFT NOWRAP COLSPAN=6><HR>
<TR>
<TD ALIGN=LEFT NOWRAP>
0.04
<TD ALIGN=LEFT NOWRAP>
423
<TD ALIGN=LEFT NOWRAP>
717
<TD ALIGN=LEFT NOWRAP>
1,332
<TD ALIGN=CENTER NOWRAP>
0.488
<TD ALIGN=CENTER NOWRAP>
866
<TR>
<TD ALIGN=LEFT NOWRAP>
0.02
<TD ALIGN=LEFT NOWRAP>
2,638
<TD ALIGN=LEFT NOWRAP>
3,414
<TD ALIGN=LEFT NOWRAP>
10,957
<TD ALIGN=CENTER NOWRAP>
2.64
<TD ALIGN=CENTER NOWRAP>
998
<TR>
<TD ALIGN=LEFT NOWRAP>
0.01
<TD ALIGN=LEFT NOWRAP>
18,168
<TD ALIGN=LEFT NOWRAP>
15,576
<TD ALIGN=LEFT NOWRAP>
90,338
<TD ALIGN=CENTER NOWRAP>
13.9
<TD ALIGN=CENTER NOWRAP>
1,310
<TR>
<TD ALIGN=LEFT NOWRAP>
0.005
<TD ALIGN=LEFT NOWRAP>
129,442
<TD ALIGN=LEFT NOWRAP>
64,645
<TD ALIGN=LEFT NOWRAP>
722,018
<TD ALIGN=CENTER NOWRAP>
66.7
<TD ALIGN=CENTER NOWRAP>
1,940
<TR>
<TD ALIGN=LEFT NOWRAP>
0.0025
<TD ALIGN=LEFT NOWRAP>
967,402
<TD ALIGN=LEFT NOWRAP>
263,720
<TD ALIGN=LEFT NOWRAP>
5,756,491
<TD ALIGN=CENTER NOWRAP>
348
<TD ALIGN=CENTER NOWRAP>
2,780
<TR><TD ALIGN=LEFT NOWRAP COLSPAN=6><HR>
</TABLE>
</CENTER>
\subsubsection Mesh_33DImage 3D Image
\cgalFigureBegin{figuremesh_3_benchmark_3d_image,bench_3d.jpg}
View of 3d image mesh generation result (size = 4).
\cgalFigureEnd
We mesh image number 2 from the 3D-IRCADb-01 (available at <A href="https://www.ircad.fr/research/data-sets/liver-segmentation-3d-ircadb-01/">https://www.ircad.fr/research/data-sets/liver-segmentation-3d-ircadb-01/</A>) public database.
The size of this image is 512x512x172 voxels (about 45M voxels). The size of the voxels
is 0.78mm x 0.78mm x 1.6mm. \cgalFigureRef{figuremesh_3_benchmark_3d_image}
shows the mesh obtained for size set to 4.
<CENTER>
<TABLE CELLSPACING=5 >
<TR><TD ALIGN=LEFT NOWRAP COLSPAN=6><HR>
<TR>
<TD ALIGN=LEFT NOWRAP>
Size bound (mm)
<TD ALIGN=LEFT NOWRAP>
vertices nb
<TD ALIGN=LEFT NOWRAP>
facets nb
<TD ALIGN=LEFT NOWRAP>
tetrahedra nb
<TD ALIGN=CENTER NOWRAP>
CPU Time (s)
<TD ALIGN=CENTER NOWRAP>
vertices/second
<TR><TD ALIGN=LEFT NOWRAP COLSPAN=6><HR>
<TR>
<TD ALIGN=LEFT NOWRAP>
16
<TD ALIGN=LEFT NOWRAP>
3,898
<TD ALIGN=LEFT NOWRAP>
4,099
<TD ALIGN=LEFT NOWRAP>
20,692
<TD ALIGN=CENTER NOWRAP>
0.344
<TD ALIGN=CENTER NOWRAP>
11,300
<TR>
<TD ALIGN=LEFT NOWRAP>
8
<TD ALIGN=LEFT NOWRAP>
34,117
<TD ALIGN=LEFT NOWRAP>
27,792
<TD ALIGN=LEFT NOWRAP>
199,864
<TD ALIGN=CENTER NOWRAP>
3.09
<TD ALIGN=CENTER NOWRAP>
11,000
<TR>
<TD ALIGN=LEFT NOWRAP>
4
<TD ALIGN=LEFT NOWRAP>
206,566
<TD ALIGN=LEFT NOWRAP>
86,180
<TD ALIGN=LEFT NOWRAP>
1,253,694
<TD ALIGN=CENTER NOWRAP>
22.4
<TD ALIGN=CENTER NOWRAP>
9,230
<TR>
<TD ALIGN=LEFT NOWRAP>
2
<TD ALIGN=LEFT NOWRAP>
1,546,196
<TD ALIGN=LEFT NOWRAP>
329,758
<TD ALIGN=LEFT NOWRAP>
9,617,278
<TD ALIGN=CENTER NOWRAP>
199
<TD ALIGN=CENTER NOWRAP>
7,780
<TR><TD ALIGN=LEFT NOWRAP COLSPAN=6><HR>
</TABLE>
</CENTER>
\subsection Mesh_3Parallel_performance_1 Parallel Performance
We provide below speed-up charts generated using the parallel version of the meshing algorithms of \cgal 4.5.
The machine used is a PC running Windows 7 64-bits with two 6-core Intel Xeon CPU X5660 clocked at 2.80 GHz
with 32GB of RAM. The program has been compiled with Microsoft Visual C++ 2012 in Release mode.
\cgalFigureRef{figure_refinement_speedup} shows mesh refinement speed-up, and \cgalFigureRef{figure_lloyd_speedup}
shows Lloyd optimization speed-up. ODT optimization exhibits similar speed-up.
\cgalFigureBegin{figure_refinement_speedup,refinement_speedup.png}
Facet refinement speed-up (left) and cell refinement speed-up (right), compared to the sequential version of the algorithm.
\cgalFigureEnd
\cgalFigureBegin{figure_lloyd_speedup,lloyd_speedup.png}
Lloyd optimization speed-up, compared to the sequential version of the algorithm. Parallel ODT exhibits similar performance.
\cgalFigureEnd
\section Mesh_3DesignAndImpl Design and Implementation History
\subsection Mesh_3TheoreticalFoundations Theoretical Foundations
The \cgal mesh generation package implements a meshing engine based
on the method of Delaunay refinement introduced by Chew \cgalCite{c-gqmgc-93} and Ruppert \cgalCite{r-draq2d-95}
and pioneered in 3D by Shewchuk \cgalCite{s-tmgdr-98}.
It uses the notion of restricted Delaunay triangulation
to approximate 1-dimensional curved features and curved surface patches
and rely on the work of Boissonnat and Oudot \cgalCite{cgal:bo-pgsms-05}
and Oudot et al. \cgalCite{cgal:ory-mvbss-05}
to achieve accurate representation of boundary and subdividing surfaces in the mesh.
The mechanism of protecting balls, used to ensure a fair representation
of 1-dimensional features, if any, and the termination of the refinement process
whatever may be the input geometry, in particular whatever small dihedral angles may form
the boundary and subdivision surface patches,
was pioneered by Cheng et al. \cgalCite{cgal:cdr-drpsc-07} and further experimented by Dey, Levine et al.
\cgalCite{cgal:cdl-pdma-07}.
The optimization phase involves global optimization processes, a perturbation process
and a sliver exudation process. The global optimizers are based on Lloyd smoothing \cgalCite{cgal:dfg-cvtaa-99t}, \cgalCite{cgal:dw-tmgob-02}
and odt smoothing \cgalCite{cgal::c-mssbo-04}, \cgalCite{cgal:acyd-vtm-05}, where odt means
<I>optimal Delaunay triangulation</I>. The perturbation process
is mainly based on the work of Tournois \cgalCite{cgal:t-om-09}
and Tournois et al. \cgalCite{cgal:twad-iropitmg-09},
while the exudation process is, the now famous, optimization by weighting described
in Edelsbrunner et al. \cgalCite{cgal:cdeft-slive-00}.
\subsection Mesh_3ImplementationHistory Implementation History
Work on the package `Mesh_3` started during the PhD thesis of Laurent Rineau
advised by Mariette Yvinec. A code prototype, together
with a first version of design and specifications \cgalCite{cgal:ry-gsddrm-06}
came out of their collaboration.
From the beginning of 2009, most of the work has been performed by Stéphane
Tayeb, in collaboration with Mariette Yvinec, Laurent Rineau, Pierre Alliez and Jane Tournois.
First, Stéphane released the first public version of the package, implementing the specifications
written by Laurent and Mariette.
The optimization processes are
heavily based on the work of Jane Tournois and Pierre Alliez
during the PhD of Jane advised by Pierre. The optimization phase was imported
in the mesh generation package by Stéphane Tayeb
and appeared first in release 3.6 of \cgal.
In collaboration with Laurent Rineau, Stéphane also added demos and examples.
After some experiments on medical imaging data performed by
Dobrina Boltcheva et al. \cgalCite{cgal:byb-mgmmi-09}, \cgalCite{cgal:-byb-fpdmgmmi-09}, the handling
of 1-dimensional features was worked out by Laurent Rineau, Stéphane Tayeb
and Mariette Yvinec. It appeared first in the release 3.8 of \cgal.
In 2013, Clément Jamin made the meshing and optimization algorithms parallel
on multi-core shared-memory architectures.
*/
} /* namespace CGAL */