The as.mesh3d() generic function converts various objects to mesh3d objects. Methods are added to support a variety of spatial formats, which will include triangles or quads according to their inherent form. For quad-types the argument triangles can be specified to generate triangles from quads. The majority of conversions are done by model functions in the silicate package, and anglr adds models DEL(), DEL0(), and QUAD().

The mesh3d format is the rgl workhorse behind plot3d(), wire3d(), persp3d() and dot3d().'

A method for a numeric matrix is included, as are methods for sf, sp, raster, RTriangle, and silicate types. and for a matrix.

# S3 method for TRI
as.mesh3d(
  x,
  z,
  smooth = FALSE,
  normals = NULL,
  texcoords = NULL,
  ...,
  keep_all = TRUE,
  image_texture = NULL,
  meshColor = "faces"
)

# S3 method for TRI0
as.mesh3d(
  x,
  z,
  smooth = FALSE,
  normals = NULL,
  texcoords = NULL,
  ...,
  keep_all = TRUE,
  image_texture = NULL,
  meshColor = "faces"
)

# S3 method for ARC
as.mesh3d(
  x,
  triangles = TRUE,
  smooth = FALSE,
  normals = NULL,
  texcoords = NULL,
  ...,
  keep_all = TRUE,
  image_texture = NULL,
  meshColor = "faces"
)

# S3 method for BasicRaster
as.mesh3d(
  x,
  triangles = TRUE,
  smooth = FALSE,
  normals = NULL,
  texcoords = NULL,
  ...,
  keep_all = TRUE,
  image_texture = NULL,
  meshColor = "faces",
  max_triangles = NULL
)

# S3 method for QUAD
as.mesh3d(
  x,
  triangles = FALSE,
  smooth = FALSE,
  normals = NULL,
  texcoords = NULL,
  ...,
  keep_all = TRUE,
  image_texture = NULL,
  meshColor = "faces"
)

# S3 method for triangulation
as.mesh3d(x, ...)

# S3 method for sfc
as.mesh3d(
  x,
  triangles = FALSE,
  smooth = FALSE,
  normals = NULL,
  texcoords = NULL,
  ...,
  keep_all = TRUE,
  image_texture = NULL,
  meshColor = "faces"
)

# S3 method for sf
as.mesh3d(
  x,
  triangles = FALSE,
  smooth = FALSE,
  normals = NULL,
  texcoords = NULL,
  ...,
  keep_all = TRUE,
  image_texture = NULL,
  meshColor = "faces"
)

# S3 method for Spatial
as.mesh3d(
  x,
  triangles = FALSE,
  smooth = FALSE,
  normals = NULL,
  texcoords = NULL,
  ...,
  keep_all = TRUE,
  image_texture = NULL,
  meshColor = "faces"
)

# S3 method for matrix
as.mesh3d(
  x,
  triangles = FALSE,
  smooth = FALSE,
  normals = NULL,
  texcoords = NULL,
  ...,
  keep_all = TRUE,
  image_texture = NULL,
  meshColor = "faces"
)

# S3 method for sc
as.mesh3d(x, ...)

Arguments

x

a surface-alike, a matrix, or spatial object from raster, sp, sf, trip, or silicate

z

numeric vector or raster object (see details)

smooth

Whether to average normals at vertices for a smooth appearance.

normals

User-specified normals at each vertex. Requires smooth = FALSE.

texcoords

Texture coordinates at each vertex.

...

arguments collected and passed to rgl::tmesh3d() as the material argument

keep_all

whether to keep non-visible triangles

image_texture

an rgb object to texture the surface

meshColor

how should colours be interpreted? 'vertices' or 'faces', for more details see rgl::tmesh3d.

triangles

for quad input types, the quads may optionally be split into triangles

max_triangles

limit on triangles to create, passed to terrainmeshr

Value

a mesh3d object

Details

When converting a matrix to mesh3d it is considered to be quad-based (area interpretation) within xmin = 0, xmax = nrow(x), ymin = 0, ymax = ncol(x). Note that this differs from the [0, 1, 0, 1] interpretation of image(), but shares its orientation. Raster-types from the raster package are interpreted in the t(ranspose), y-flip orientation used by plot(raster::raster(matrix)).

The conversion function anglr::as.mesh3d() consolidates code from quadmesh and angstroms packages where the basic facilities were developed. The function as.mesh3d() is imported from rgl and re-exported, and understands all of the surface types from sf, sp, raster, and silicate, and can accept a raw matrix as input.

When creating a surface mesh there is an optional z argument to extract elevation values from a raster, and/or an image_texture argument to drape an image from a raster RGB object onto the surface. Map projections are automatically resolved to the coordinate system of the x argument.

Implicit versus explicit topology

We support conversion to mesh for strictly linear types such as sf 'POLYGON', 'MULTIPOLYGON', 'MULTILINESTRING', 'LINESTRING' and their sp counterparts 'SpatialPolygons' and 'SpatialLines'. Even polygons are only implicit surfaces and so conversion and plotting functions try to reflect this inherent nature as much as possible. A mesh is inherently a surface, and so the method for polygons or lines will first call a surface-generating function, silicate::TRI0() or DEL0() in order to created the required primitives, while plot3d() will not do this. The key goal is flexibility, and so we can call a meshing function as.mesh3d() (does conversion) or persp3d() (a plot function, but requires conversion to surface) and they will choose an interpretation. An non-formal guideline is to use the cheapest method possible, i.e. silicate::TRI0().

Much of the above is open for discussion, so please get in touch! Use the issues tab or ping me on twitter to clarify or discuss anything.

Elevation values with z

The 'z' argument can be a constant value or a vector of values to be used for each vertex. Alternatively, it may be a spatial raster object from which 'z' values are derived. If not set, the vertex 'z_' value from TRI/TRI0 is used, otherwise z = 0' is assumed.

Textures

Please see the documentation for rgl textures in vignette("rgl", package = "rgl"). The most important detail is that the $material$color property of a mesh3d not be set to "black" ("#000000" or equivalent), or it will not be visible at all. The only way to add a texture in mesh3d is as a PNG file on-disk, so anglr functions take an in-memory object and create the file if needed.

See also

Examples

sf <- silicate::minimal_mesh #sf <- silicate::inlandwaters x <- silicate::TRI(sf) library(rgl) clear3d(); plot3d(x); view3d(phi = -10) ## simple convention to carry feature colours sf$color_ <- c("firebrick", "dodgerblue") clear3d(); plot3d(silicate::TRI(sf)); view3d(phi = -10) # material properties for $material are collected in ... # and will override the 'color_' mech x$object$color_ <- "black" clear3d(); plot3d(as.mesh3d(x, color = rainbow(14))) ## we cannot assume TRI triangles relate to features simply ## but sometimes it does (always does for TRI0) cols <- c("black", "grey")[c(rep(1, 12), c(2, 2))] clear3d(); plot3d(as.mesh3d(x, color = cols)) ## smear by vertices meshColor cols <- c("black", "grey") clear3d(); plot3d(as.mesh3d(x, color = cols), meshColor = "vertices") ## other material properties clear3d() plot3d(as.mesh3d(x, color = cols, specular = "black"), meshColor = "vertices") clear3d() plot3d(as.mesh3d(x, color = cols, front = "lines", lwd = 5), meshColor = "vertices") clear3d() plot3d(as.mesh3d(x, color = viridis::viridis(20), alpha = 0.3), meshColor = "faces") clear3d() plot3d(as.mesh3d(x, color = viridis::viridis(5), alpha = 0.3), meshColor = "vertices") # TRI0 - index is stored structurally, not relations x0 <- silicate::TRI0(sf) clear3d(); plot3d(x0); view3d(phi = -10) # (TRI0 - it *is* guaranteed that triangle order is native) clear3d(); plot3d(as.mesh3d(x0, color = rainbow(14))) ## arbitrarily drape polygons over raster r <- raster::setExtent(raster::raster(volcano), raster::extent(-0.1, 1.1, -0.1, 1.1)) clear3d();shade3d(as.mesh3d(DEL(silicate::minimal_mesh, max_area = 0.001), z =r)) aspect3d(1, 1, 0.5) # \donttest{ library(rgl) ## get sf extent ext <- sf_extent(silicate::inlandwaters) r1 <- raster::setExtent(raster::raster(volcano), ext) clear3d();shade3d(as.mesh3d(DEL(silicate::inlandwaters, max_area = 1e9), z =r1)) aspect3d(1, 1, .2) ## fake news rgl::wire3d(as.mesh3d(r1)) # }