Applies smoothing algorithms on a triangular mesh. Vertices that belong to no face carry no connectivity, so they are excluded from the computation and returned at their input positions with zero normal vectors; the remaining vertices are unaffected by their presence.
vcg_smooth_implicit solves, separately for each coordinate, the
sparse linear system
\((M + \lambda L^k) x = M v\), where \(v\)
holds the input positions, \(M\) the per-vertex areas scaled to a
maximum of one, \(L\) the 'Laplacian' and
\(k = 2^{degree - 1}\). Degrees 1 and 2 are solved
iteratively (conjugate gradients), with memory growing linearly with the
mesh; higher degrees are solved by a sparse factorization. The memory the
solve needs is estimated before anything large is allocated, and the
function stops with an explanation when it exceeds max_memory; very
large meshes can be simplified first with vcg_decimate.
Usage
vcg_smooth_implicit(
mesh,
lambda = 0.2,
use_mass_matrix = TRUE,
fix_border = FALSE,
use_cot_weight = FALSE,
degree = 1L,
laplacian_weight = 1,
max_memory = 2
)
vcg_smooth_explicit(
mesh,
type = c("taubin", "laplace", "HClaplace", "fujiLaplace", "angWeight",
"surfPreserveLaplace"),
iteration = 10,
lambda = 0.5,
mu = -0.53,
delta = 0.1
)Arguments
- mesh
triangular mesh stored as object of class 'mesh3d'.
- lambda
In
vcg_smooth_implicit, the amount of smoothness, which has no effect whenuse_mass_matrixisFALSE; default is0.2. Invcg_smooth_explicit, parameter for'taubin'smoothing.- use_mass_matrix
logical: whether to keep the mesh close to its input position with an area-weighted (mass matrix) term; default is
TRUE. WithFALSEthere is no such term and the fixed border vertices alone determine the result, the smoothest surface spanning the border; this needsfix_border = TRUEand a border in every connected part of the mesh, andlambdathen has no effect- fix_border
logical: whether border vertices (vertices on an edge that belongs to exactly one face) keep exactly their input positions; default is
FALSE. Closed meshes have no border- use_cot_weight
logical: whether to use cotangent weight; default is
FALSE(using uniform 'Laplacian')- degree
integer: degree of the 'Laplacian' operator; the system uses \(L^k\) with \(k = 2^{degree - 1}\) (the 'Laplacian' squared
degree - 1times), sodegree = 2uses \(L^2\) anddegree = 3uses \(L^4\); default is1- laplacian_weight
numeric: weight when
use_cot_weightisFALSE; default is1.0- max_memory
maximum memory in
GiBthatvcg_smooth_implicitmay use for the solve; default is2. The need is estimated from the mesh before any large allocation, and exceeding it raises an error that suggests alternatives- type
method name of explicit smooth, choices are
'taubin','laplace','HClaplace','fujiLaplace','angWeight','surfPreserveLaplace'.- iteration
number of iterations
- mu
parameter for
'taubin'explicit smoothing.- delta
parameter for scale-dependent 'Laplacian' smoothing or maximum allowed angle (in 'Radian') for deviation between surface preserving 'Laplacian'.
Value
An object of class "mesh3d" with:
vbvertex coordinates
normalsvertex normal vectors
ittriangular face index
Coercing Surface Inputs
The surface objects are converted to 'mesh3d' object before
applying further calculations.
When surface is a surface ieegio object, the returned
mesh3d$vb contains vertices that have been left-multiplied by
surface$geometry$transforms[[1]] (the first transform stored in the
geometry, typically the ScannerAnat or voxel-to-world transform).
Breaking change: Earlier versions (before 0.2.6) of ravetools
returned the raw surface$geometry$vertices without applying any
transform, so downstream code often multiplied by
surface$geometry$transforms[[1]] (or an equivalent) manually before
working in world space. Such code will now double
apply the transform and produce incorrect coordinates. If you previously
applied a transform from surface$geometry$transforms by hand after
calling a ravetools mesh function on an 'ieegio_surface',
remove that manual step.
Surfaces with an empty or missing geometry$transforms list (for
example, surfaces produced by ieegio's volume_to_surface,
which stores an identity transform) are unaffected.
If geometry$transforms contains multiple transforms targeting
different coordinate spaces, only the first one is used. Callers that need
a specific target space should select and apply that transform themselves
before calling ravetools mesh functions.
Examples
if(is_not_cran()) {
# Prepare mesh with no normals
data("left_hippocampus_mask")
# Grow 2mm on each direction to fill holes
volume <- grow_volume(left_hippocampus_mask, 2)
# Initial mesh
mesh <- vcg_isosurface(volume)
# Start: examples
rgl_view({
rgl_call("mfrow3d", 2, 4)
rgl_call("title3d", "Naive ISOSurface")
rgl_call("shade3d", mesh, col = 2)
rgl_call("next3d")
rgl_call("title3d", "Implicit Smooth")
rgl_call("shade3d", col = 2,
x = vcg_smooth_implicit(mesh, degree = 2))
rgl_call("next3d")
rgl_call("title3d", "Explicit Smooth - taubin")
rgl_call("shade3d", col = 2,
x = vcg_smooth_explicit(mesh, "taubin"))
rgl_call("next3d")
rgl_call("title3d", "Explicit Smooth - laplace")
rgl_call("shade3d", col = 2,
x = vcg_smooth_explicit(mesh, "laplace"))
rgl_call("next3d")
rgl_call("title3d", "Explicit Smooth - angWeight")
rgl_call("shade3d", col = 2,
x = vcg_smooth_explicit(mesh, "angWeight"))
rgl_call("next3d")
rgl_call("title3d", "Explicit Smooth - HClaplace")
rgl_call("shade3d", col = 2,
x = vcg_smooth_explicit(mesh, "HClaplace"))
rgl_call("next3d")
rgl_call("title3d", "Explicit Smooth - fujiLaplace")
rgl_call("shade3d", col = 2,
x = vcg_smooth_explicit(mesh, "fujiLaplace"))
rgl_call("next3d")
rgl_call("title3d", "Explicit Smooth - surfPreserveLaplace")
rgl_call("shade3d", col = 2,
x = vcg_smooth_explicit(mesh, "surfPreserveLaplace"))
})
}
#> Package `rgl` is not installed. Please install `rgl` to use this function.
#> Error in loadNamespace(name): there is no package called ‘rgl’