Modifies a mesh3d object so that values of a function are bounded.
clipMesh3d(mesh, fn, bound = 0, greater = TRUE, minVertices = 0, plot = FALSE, keepValues = FALSE, keepTags = FALSE) clipObj3d(ids = tagged3d(tags), fn, bound = 0, greater = TRUE, minVertices = 0, replace = TRUE, tags)
A function used to determine clipping, or a vector of values from such a function, with one value per vertex.
The value(s) of
fn on the clipping boundary.
Logical; whether to keep
fn >= bound or not.
See Details below.
Logical; whether or not to plot the mesh.
Logical; whether to save the function values at
each vertex when
plot = FALSE.
Whether to keep the
of the result; see details below.
The RGL id value(s) of objects to clip.
Object tags; an alternate way to specify
ids. Ignored if
ids objects be deleted after the clipped
ones are drawn?
These functions transform a mesh3d object or other
RGL objects by removing parts where
fn argument can be any
of the following:
a character vector naming a function (with special
to functions returning those coordinates)
a numeric vector with one value per vertex
NULL, indicating that the numeric values
are saved in
clipObj3d any of the above except
may be used.
is a numeric vector, with one value per vertex, those values will be
used in the test.
If it is a function with formal arguments
z, it will receive the coordinates of
vertices in those arguments, otherwise it will receive
the coordinates in a single n x 3 matrix. The function
should be vectorized and return one value per vertex,
to check against the bound.
These operations are performed on the mesh:
First, all quads are converted to triangles.
Next, each vertex is checked against the condition.
Modifications to triangles depend
on how many of the vertices satisfy the condition
fn >= bound or
fn <= bound, depending on
If no vertices in a triangle satisfy the condition, the triangle is omitted.
If one vertex satisfies the condition, the other two vertices
in that triangle are shrunk towards it by assuming
is locally linear.
If two vertices satisfy the condition, the third vertex is shrunk along each edge towards each other vertex, forming a quadrilateral made of two new triangles.
If all vertices satisfy the condition, they are included with no modifications.
Modifications to line segments are similar: the segment will be shortened if it crosses the boundary, or omitted if it is entirely out of bounds. Points, spheres, text and sprites will just be kept or rejected.
minVertices argument is used to improve the
approximation to the boundary when
fn is a non-linear
function. In that case, the interpolation described above
can be inaccurate. If
minVertices is set to a
10000), then each object is modified
by subdivision to have at least that number of vertices,
so that pieces are smaller and the linear interpolation
is more accurate. In the
minVertices can be a vector, with entries corresponding
to each of the entries in
plot = FALSE,
clipMesh3d returns new mesh3d object in which all vertices (approximately) satisfy the
clipping condition. Note that the order of vertices will likely
differ from the original order, and new vertices will be added near
the boundary (and if
minVertices > 0, in the
interior). If in addition
keepValues = TRUE,
a component named
"values" will be added to the
mesh containing the values for each vertex.
keepTags = TRUE, the
described below will be added to the output mesh.
plot = TRUE, the result will be
shade3d and its result returned.
clipObj3d is called for the side effect of modifying
the scene. It returns a list of new RGL id values
corresponding to the
ids passed as arguments.
See https://stackoverflow.com/q/56242470/2554330 and https://laustep.github.io/stlahblog/posts/MeshClipping.html for a motivating example.
filledContour3d for ways to display function
values without clipping.
# Show the problem that minVertices solves: cube <- cube3d(col = palette.colors(6, "Accent"), meshColor = "faces") # This function only has one argument, so it will # be passed x, y and z in columns of a matrix vecnorm <- function(vals) apply(vals, 1, function(row) sqrt(sum(row^2))) open3d() mfrow3d(2, 2, sharedMouse = TRUE) id1 <- shade3d(cube) # All vertices have norm sqrt(3), so this clips nothing: clipObj3d(id1, fn = vecnorm, bound = sqrt(2)) next3d() id2 <- wire3d(cube, lit = FALSE) clipObj3d(id2, fn = vecnorm, bound = sqrt(2)) # This subdivides the cube, and does proper clipping: next3d() id3 <- shade3d(cube) clipObj3d(id3, fn = vecnorm, bound = sqrt(2), minVertices = 200) next3d() id4 <- wire3d(cube, lit = FALSE) clipObj3d(id4, fn = vecnorm, bound = sqrt(2), minVertices = 200)