CGAL 4.6.1 - dD Triangulations
|
This package proposes data structures and algorithms to compute triangulations of points in any dimensions. The Triangulation_data_structure
handles the combinatorial aspect of triangulations while the geometric classes Triangulation
and Delaunay_triangulation
allows to compute and maintain triangulations and Delaunay triangulations of sets of points.
A finite abstract simplicial complex is built on a finite set of vertices \( V\) and consists of a collection \( S\) of subsets of \( V\) such that
The sets in \( S\) (which are subsets of \( V\)) are called faces or simplices (the singular of which is simplex). A simplex \( s\in S\) is maximal if it is not a proper subset of some other set in \( S\). A simplex having \( d+1 \) vertices is said of dimension \( d \). The simplicial complex is pure if all the maximal simplices have the same dimension.
In the sequel, we will call these maximal simplices full cells. A face of a simplex is a subset of this simplex. A proper face of a simplex is a strict subset of this simplex.
A complex has no boundaries if any proper face of a simplex is also a proper face of another simplex.
If the vertices are embedded into Euclidean space \( \mathbb{R}^d\), we deal with finite simplicial complexes which have slightly different simplices and additional requirements:
See the wikipedia entry for more about simplicial complexes.
This CGAL package provides three main classes for creating and manipulating triangulations.
The class CGAL::Triangulation_data_structure<Dimensionality, TriangulationDSVertex, TriangulationDSFullCell>
models an abstract triangulation: vertices in this class are not embedded in Euclidean space but are only of combinatorial nature. It deals with simplicial complexes which are pure, connected and without boundaries nor singularities.
The class CGAL::Triangulation<TriangulationTraits, TriangulationDataStructure>
describes an embedded triangulation that has as vertices a given set of points. Methods are provided for the insertion of points in the triangulation, the traversal of various elements of the triangulation, as well as the localization of a query point inside the triangulation. The triangulation covers the convex hull of the set of points.
The class CGAL::Delaunay_triangulation<DelaunayTriangulationTraits, TriangulationDataStructure>
builds the Delaunay triangulation of a set of points. In a Delaunay triangulation, each face has the so-called Delaunay or empty-ball property: there exists a circumscribing ball whose interior does not contain any vertex of the triangulation.
An \( i\)-face denotes an \( i\)-dimensional simplex, or a simplex with \( i+1\) vertices. When these vertices are embedded in Euclidean space, they must be affinely independent.
If the maximal dimension of a simplex in the triangulation is \( d\), we use the following terminology:
Two faces \( \sigma\) and \( \sigma'\) are incident if and only if \( \sigma'\) is a proper sub-face of \( \sigma\) or vice versa.
In this section, we describe the concept TriangulationDataStructure
for which CGAL provides one model class: CGAL::Triangulation_data_structure<Dimensionality, TriangulationDSVertex, TriangulationDSFullCell>
.
A TriangulationDataStructure
can represent an abstract pure complex such that any facet is incident to exactly two full cells.
A TriangulationDataStructure
has a maximal dimension which is a positive integer equal to the maximum dimension a full cell can have. This maximal dimension can be chosen by the user at the creation of a TriangulationDataStructureand can then be queried using the method
tds.maximal_dimension(). A
TriangulationDataStructurealso knows the <I>current dimension</I> of its full cells, which can be queried with
tds.current_dimension()`. In the sequel, let us denote the maximal dimension with \( D \) and the current dimension with \( d \). The inequalities \( -2 \leq d \leq D\) and \( 0 \le D\) always hold. The special meaning of negative values for \(d\) is explained below.
The set of faces of a TriangulationDataStructure
with current dimension \( d \) forms a triangulation of the topological sphere \( \mathbb{S}^d\).
Two full cells \( \sigma\) and \( \sigma'\) sharing a facet are called neighbors. A full cell has always exactly \( d+1\) neighbors.
Possible values of \(d\) (the current dimension of the triangulation) include
- \(d=-2\)
- This corresponds to an empty
TriangulationDataStructure
.- \(d=-1\)
This corresponds to an abstract simplicial complex reduced to a single vertex.
- \(d=0\)
This corresponds to an abstract simplicial complex including two vertices, each corresponding to a full cell; the two full cells being neighbors of each other. This is the unique triangulation of the \( 0\)-sphere.
- \( 0< d \le D\)
- This corresponds to a triangulation of the sphere \( \mathbb{S}^d\).
Triangulation_data_structure
ClassWe give here some details about the class Triangulation_data_structure<Dimensionality, TriangulationDSVertex, TriangulationDSFullCell>
implementing the concept TriangulationDataStructure
.
A TriangulationDataStructure
explicitly stores its vertices and full cells.
Each vertex stores a reference to one of its incident full cells.
Each full cell stores references to its \( d+1\) vertices and neighbors. Its vertices and neighbors are indexed from \( 0\) to \( d \). The indices of its neighbors have the following meaning: the \( i\)-th neighbor of \( \sigma\) is the unique neighbor of \( \sigma\) that does not contain the \( i\)-th vertex of \( \sigma\); in other words, it is the neighbor of \( \sigma\) opposite to the \( i\)-th vertex of \( \sigma\) (Figure Figure 42.1).
The vertices and full cells of the triangulations are accessed through handles
and iterators
. A handle is a model of the Handle
concept, and supports the two dereference operators and operator->
.
Faces of dimension between 0 and \( d-1 \) can be accessed as subfaces of a full cell, through the nested type Face
. The Face
instance corresponding to a face \( f \) stores a reference to a full cell c
containing \( f \), and the indices of the vertices of c
that belong to \( f \).
The Triangulation_data_structure<Dimensionality, TriangulationDSVertex, TriangulationDSFullCell>
class is designed in such a way that its user can choose
Dimensionality
template parameter, TriangulationDSVertex
template parameter and TriangulationDSFullCell
template parameter. The last two parameters have default values and are thus not necessary, unless the user needs custom types (see the reference manual page for this class template). The first template parameter, Dimensionality
, must be one of the following:
Dimension_tag<D>
for some integer \( D \). This indicates that the triangulation can store full cells of dimension at most \( D \). The maximum dimension \( D \) is known by the compiler, which triggers some optimizations. Dynamic_dimension_tag
. In this case, the maximum dimension of the full cells must be passed as an integer argument to an instance constructor (see TriangulationDataStructure
). The TriangulationDSVertex
and TriangulationDSFullCell
parameters to the class template must be models of the concepts TriangulationDSVertex
and TriangulationDSFullCell
respectively. CGAL provides models for these concepts: Triangulation_ds_vertex<TriangulationDataStructure>
and Triangulation_ds_full_cell<TriangulationDataStructure, TriangulationDSFullCellStoragePolicy>
, which, as one can see, take the TriangulationDataStructure
as a template parameter in order to get access to some nested types in TriangulationDataStructure
.
The default values are CGAL::Triangulation_ds_vertex<TDS>
and CGAL::Triangulation_ds_full_cell<TDS>
where TDS
is the current class Triangulation_data_structure<Dimensionality, TriangulationDSVertex, TriangulationDSFullCell>
This creates a circular dependency, which we resolve in the same way as in the CGAL Triangulation_2
and Triangulation_3
packages (see Chapters Chapter_2D_Triangulation_Data_Structure, Chapter_2D_Triangulations, Chapter_3D_Triangulation_Data_Structure, and Chapter_3D_Triangulations). In particular, models of the concepts TriangulationDSVertex
and TriangulationDSFullCell
must provide a nested template Rebind_TDS
which is documented in those two concept's reference manual pages. This mechanism can be used to provide a custom vertex or full cell class. The user is encouraged to read the documentation of the CGAL Triangulation_2
or Triangulation_3
package.
The following examples shows how to construct a triangulation data structure by inserting vertices. Its main interest is that it demonstrates most of the API to insert new vertices into the triangulation.
File triangulation_data_structure_static.cpp
In the previous example, the maximal dimension is fixed at compile time. It is also possible to fix it at run time, as in the next example.
File triangulation_data_structure_dynamic.cpp
This example provides a function for computing the barycentric subdivision of a single full cell c
in a triangulation data structure. The other full cells adjacent to c
are automatically subdivided to match the subdivision of the full cell c
. The barycentric subdivision of c
is obtained by enumerating all the faces of c
in order of decreasing dimension, from the dimension of c
to dimension 1, and inserting a new vertex in each face. For the enumeration, we use a combination enumerator, which is not documented, but provided in CGAL.
File barycentric_subdivision.cpp
The class CGAL::Triangulation<TriangulationTraits, TriangulationDataStructure>
maintains a triangulation embedded in Euclidean space. The triangulation covers the convex hull of the input points (the embedded vertices of the triangulation).
To store this triangulation in a triangulation data structure, we turn the set of its faces into a topological sphere by adding a fictitious vertex, called the infinite vertex, as well as infinite simplices incident to boundary faces of the convex hull. Each infinite \( i\)-simplex is incident to the infinite vertex and to an \( (i-1)\)-simplex of the convex hull boundary.
See Chapters 2D Triangulations and 3D Triangulations for more details about infinite vertices and cells.
Methods are provided for the insertion of points in the triangulation, the contraction of faces, the traversal of various elements of the triangulation as well as the localization of a query point inside the triangulation.
The ordering of the vertices of a full cell defines an orientation of that full cell. As long as no advanced class method is called, it is guaranteed that all finite full cells have positive orientation. The infinite full cells are oriented as if the infinite vertex was on the other side of the hyperplane supported by the convex hull facets that the other points.
The class CGAL::Triangulation<TriangulationTraits, TriangulationDataStructure>
stores a model of the concept TriangulationDataStructure
which is instantiated with a vertex type that stores a point.
The template parameter TriangulationTraits
must be a model of the concept TriangulationTraits
which provides the Point
type as well as various geometric predicates used by the Triangulation
class.
The TriangulationTraits
concept includes a nested type TriangulationTraits::Dimension
which is the dimension of the predicates. This dimension governs the number of points given as arguments to the predicates. This type is either CGAL::Dimension_tag<D>
or CGAL::Dynamic_dimension_tag
. In any case, the dimension of the traits must match the maximal dimension of the TriangulationDataStructure
.
The template parameter TriangulationDataStructure
must be a model of the concept TriangulationDataStructure
which provides the triangulation data structure as described in the previous section.
The following example shows how to construct a triangulation in which we insert random points. In STEP 1
, we generate one hundred random points in \( \mathbb{R}^5\), which we then insert into a triangulation. In STEP 2
, we ask the triangulation to construct the set of edges ( \( 1\) dimensional faces) incident to the vertex at infinity. It is easy to see that these edges are in bijection with the vertices on the convex hull of the points. This gives us a handy way to count the convex hull vertices (include files triangulation1.cpp
and triangulation2.cpp
are given and commented below).
File triangulation.cpp
Remember that a triangulation covers the convex hull of its vertices. Each facet of the convex hull is incident to one finite full cell and one infinite full cell. In fact there is a bijection between the infinite full cells and the facets of the convex hull. If vertices are not in general position, convex hull faces that are not simplices are triangulated. In order to traverse the convex hull facets, there are (at least) two possibilities:
The first is to iterate over the full cells of the triangulation and check if they are infinite or not:
File triangulation1.cpp
A second possibility is to ask the triangulation to gather all the full cells incident to the infinite vertex: they form precisely the set of infinite full cells:
File triangulation2.cpp
One important difference between the two examples above is that the first uses little memory but traverses all the full cells, while the second visits only the infinite full cells but stores handles to them into the potentially big array infinite_full_cells
.
The class CGAL::Delaunay_triangulation<DelaunayTriangulationTraits, TriangulationDataStructure>
derives from CGAL::Triangulation<DelaunayTriangulationTraits, TriangulationDataStructure>
and represent Delaunay triangulations.
A circumscribing ball of a simplex is a ball having all vertices of the simplex on its boundary. In a Delaunay triangulation, each face has the so-called Delaunay or empty-ball property: there exists a circumscribing ball whose interior does not contain any vertex of the triangulation.
In case of degeneracies (co-spherical points) the triangulation is not uniquely defined. Note however that the CGAL implementation computes a unique triangulation even in these cases.
When a new point p
is inserted into a Delaunay triangulation, the full cells whose circumscribing ball contains p
are said to be in conflict with point p
. Note that the circumscribing ball of an infinite full cell is the empty half-space bounded by the affine hull of the finite facet of this cell. The set of full cells that are in conflict with p
form the conflict zone. The full cells in the conflict zone are removed, leaving a hole that contains p
. That hole is ``star shaped'' around p
and thus is re-triangulated using p
as a center vertex.
Delaunay triangulations also support vertex removal.
The class CGAL::Delaunay_triangulation<DelaunayTriangulationTraits, TriangulationDataStructure>
derives from CGAL::Triangulation<DelaunayTriangulationTraits, TriangulationDataStructure>
. It thus stores a model of the concept TriangulationDataStructure
which is instantiated with a vertex type that stores a geometric point and allows its retrieval.
The template parameter DelaunayTriangulationTraits
must be a model of the concept DelaunayTriangulationTraits
which provides the geometric Point
type as well as various geometric predicates used by the Delaunay_triangulation
class. The concept DelaunayTriangulationTraits
refines the concept TriangulationTraits
by requiring a few other geometric predicates, necessary for the computation of Delaunay triangulations.
When using a full cell type containing additional custom information, it may be useful to get an efficient access to the full cells that are going to be erased upon the insertion of a new point in the Delaunay triangulation, and to the newly created full cells. The second part of code example below shows how one can have efficient access to both the conflict zone and the created full cells, while still retaining an efficient update of the Delaunay triangulation.
File delaunay_triangulation.cpp
The current implementation locates points by walking in the triangulation, and sorts the points with spatial sort to insert a set of points. Thus the theoretical complexity are \( O(n\log n)\) for inserting \( n\) random points and \( O(n^{\frac{1}{d}})\) for inserting one point in a triangulation of \( n\) random points. In the worst case, the expected complexity is \( O(n^{\lceil\frac{d}{2}\rceil}+n\log n)\).
We provide below (Figure Figure 42.3) the performance of the Delaunay triangulation on randomly distributed points. The machine used is a PC running Windows 7 64-bits with an Intel Xeon CPU clocked at 2.80 GHz with 32GB of RAM. The program has been compiled with Microsoft Visual C++ 2012 in Release mode.
Dimension | 2 | 3 | 4 | 5 | 6 | 7 | 8 | |
---|---|---|---|---|---|---|---|---|
Inserting 100 points | 0.003 | 0.007 | 0.03 | 0.14 | 0.56 | 2.7 | 11.3 | |
Inserting 1000 points | 0.015 | 0.056 | 0.52 | 3.5 | 26.2 | 185 | 1385 | |
This package is heavily inspired by the works of Monique Teillaud and Sylvain Pion (Triangulation_3
) and Mariette Yvinec (Triangulation_2
). The first version was written by Samuel Hornus. The final version is a joint work by Samuel Hornus, Olivier Devillers and Clément Jamin.
Starting with the version 2.3 of CGAL, a package written by Susan Hert and Michael Seel was the first able to deal with triangulation and convex hulls in arbitrary dimension. It is deprecated since the version 4.6 of CGAL and this package should be used instead.