Delaunay triangulation (or tessellation) of a set of points.
Usage
delaunay(
points,
atinfinity = FALSE,
degenerate = FALSE,
exteriorEdges = FALSE,
elevation = FALSE
)
Arguments
- points
the points given as a matrix, one point per row
- atinfinity
Boolean, whether to include a point at infinity
- degenerate
Boolean, whether to include degenerate tiles
- exteriorEdges
Boolean, for dimension 3 only, whether to return the exterior edges (see below)
- elevation
Boolean, only for three-dimensional points; if
TRUE
, the function performs an elevated Delaunay triangulation (also called 2.5D Delaunay triangulation), using the third coordinate of a point as its elevation; see the example
Value
If the function performs an elevated Delaunay tessellation, then
the returned value is a list with four fields: mesh
, edges
,
volume
, and surface
. The mesh
field is an object of
class mesh3d
, ready for plotting with the rgl package. The
edges
field is an integer matrix which provides the indices of the
vertices of the edges, and an indicator of whether an edge is a border
edge; this matrix is obtained with vcgGetEdge
.
The volume
field provides the sum of the
volumes under the Delaunay triangles, that is to say the total volume
under the triangulated surface. Finally, the surface
field provides
the sum of the areas of the Delaunay triangles, thus this is an approximate
value of the area of the surface that is triangulated.
The elevated Delaunay tessellation is built with the help of the
interp package.
Otherwise, the function returns the Delaunay tessellation with many details,
in a list. This list contains five fields:
- vertices
the vertices (or sites) of the tessellation; these are the points passed to the function
- tiles
the tiles of the tessellation (triangles in dimension 2, tetrahedra in dimension 3)
- tilefacets
the facets of the tiles of the tessellation
- mesh
a 'rgl' mesh (
mesh3d
object)- edges
a two-columns integer matrix representing the edges, each row represents an edge; the two integers of a row are the indices of the two points which form the edge.
In dimension 3, the list contains an additional field exteriorEdges if you set exteriorEdges = TRUE
. This is the list of the exterior
edges, represented as Edge3
objects. This field is involved
in the function plotDelaunay3D
.
The vertices field is a list with the following fields:
- id
the id of the vertex; this is nothing but the index of the corresponding point passed to the function
- neighvertices
the ids of the vertices of the tessellation connected to this vertex by an edge
- neightilefacets
the ids of the tile facets this vertex belongs to
- neightiles
the ids of the tiles this vertex belongs to
The tiles field is a list with the following fields:
- id
the id of the tile
- simplex
a list describing the simplex (that is, the tile); this list contains four fields: vertices, a
hash
giving the simplex vertices and their id, circumcenter, the circumcenter of the simplex, circumradius, the circumradius of the simplex, and volume, the volume of the simplex- facets
the ids of the facets of this tile
- neighbors
the ids of the tiles adjacent to this tile
- family
two tiles have the same family if they share the same circumcenter; in this case the family is an integer, and the family is
NA
for tiles which do not share their circumcenter with any other tile- orientation
1
or-1
, an indicator of the orientation of the tile
The tilefacets field is a list with the following fields:
- id
the id of this tile facet
- subsimplex
a list describing the subsimplex (that is, the tile facet); this list is similar to the simplex list of tiles
- facetOf
one or two ids, the id(s) of the tile this facet belongs to
- normal
a vector, the normal of the tile facet
- offset
a number, the offset of the tile facet
Note
The package provides the functions plotDelaunay2D
to
plot a 2D Delaunay tessellation and plotDelaunay3D
to
plot a 3D Delaunay tessellation. But there is no function to plot an
elevated Delaunay tessellation; the examples show how to plot such a
Delaunay tessellation.
Examples
library(tessellation)
points <- rbind(
c(0.5,0.5,0.5),
c(0,0,0),
c(0,0,1),
c(0,1,0),
c(0,1,1),
c(1,0,0),
c(1,0,1),
c(1,1,0),
c(1,1,1)
)
del <- delaunay(points)
del$vertices[[1]]
#> $id
#> [1] 1
#>
#> $point
#> [1] 0.5 0.5 0.5
#>
#> $neighvertices
#> [1] 2 3 4 5 6 7 8 9
#>
#> $neightilefacets
#> [1] 1 3 4 5 7 9 10 11 13 15 16 17 20 21 23 25 26 29
#>
#> $neightiles
#> [1] 1 2 3 4 5 6 7 8 9 10 11 12
#>
del$tiles[[1]]
#> $vertices
#> [1] 8 1 6 2
#>
#> $id
#> [1] 1
#>
#> $simplex
#> $simplex$vertices
#> <hash> containing 4 key-value pair(s).
#> 1 : 0.5 0.5 0.5
#> 2 : 0 0 0
#> 6 : 1 0 0
#> 8 : 1 1 0
#>
#> $simplex$circumcenter
#> [1] 0.50 0.50 -0.25
#>
#> $simplex$circumradius
#> [1] 0.75
#>
#> $simplex$volume
#> [1] 0.08333333
#>
#>
#> $facets
#> [1] 1 2 3 4
#>
#> $neighbors
#> [1] 3 2 5
#>
#> $family
#> [1] 0
#>
#> $orientation
#> [1] -1
#>
del$tilefacets[[1]]
#> $id
#> [1] 1
#>
#> $subsimplex
#> $subsimplex$vertices
#> <hash> containing 3 key-value pair(s).
#> 1 : 0.5 0.5 0.5
#> 2 : 0 0 0
#> 6 : 1 0 0
#>
#> $subsimplex$circumcenter
#> [1] 0.500 0.125 0.125
#>
#> $subsimplex$circumradius
#> [1] 0.5303301
#>
#> $subsimplex$volume
#> [1] 0.3535534
#>
#>
#> $facetOf
#> [1] 1 3
#>
#> $normal
#> [1] 0.0000000 0.7071068 -0.7071068
#>
#> $offset
#> [1] 0
#>
# an elevated Delaunay tessellation ####
f <- function(x, y){
dnorm(x) * dnorm(y)
}
x <- y <- seq(-5, 5, length.out = 50)
grd <- expand.grid(x = x, y = y) # grid on the xy-plane
points <- as.matrix(transform( # data (x_i, y_i, z_i)
grd, z = f(x, y)
))
del <- delaunay(points, elevation = TRUE)
del[["volume"]] # close to 1, as expected
#> [1] 0.9999988
# plotting
library(rgl)
mesh <- del[["mesh"]]
open3d(windowRect = c(100, 100, 612, 356), zoom = 0.6)
aspect3d(1, 1, 20)
shade3d(mesh, color = "limegreen")
wire3d(mesh)
# another elevated Delaunay triangulation, to check the correctness of
# the calculated surface ####
library(Rvcg)
library(rgl)
cap <- vcgSphericalCap(angleRad = pi/2, subdivision = 3)
open3d(windowRect = c(100, 100, 612, 356), zoom = 0.6)
shade3d(cap, color = "lawngreen")
wire3d(cap)
# exact value of the surface of the spherical cap:
R <- 1
h <- R * (1 - sin(pi/2/2))
2 * pi * R * h
#> [1] 1.840302
# our approximation:
points <- t(cap$vb[-4, ]) # the points on the spherical cap
del <- delaunay(points, elevation = TRUE)
del[["surface"]]
#> [1] 1.832746
# try to increase `subdivision` in `vcgSphericalCap` to get a
# better approximation of the true value
# note that 'Rvcg' returns the same result as ours:
vcgArea(cap)
#> [1] 1.832746
# let's check the volume as well:
pi * h^2 * (R - h/3) # true value
#> [1] 0.2431939
del[["volume"]]
#> [1] 0.2405314
# there's a warning with 'Rvcg':
tryCatch(vcgVolume(cap), warning = function(w) message(w))
#> Warning: Mesh is not watertight! USE RESULT WITH CARE!
#> Error in invokeRestart("muffleWarning"): no 'restart' 'muffleWarning' found
suppressWarnings({vcgVolume(cap)})
#> [1] 0.2405313