The writeWebGL function from the {rgl} package can be used to export interactive 3D plots to HTML (see example below).
require(rgl)
jet.colors <-colorRampPalette(c("#00007F", "blue", "#007FFF", "cyan",
"#7FFF7F", "yellow", "#FF7F00", "red", "#7F0000"))
colorzjet <- jet.colors(100)
data(volcano)
z <- 5 * volcano # Exaggerate the relief
x <- 10 * (1:nrow(z)) # 10 meter spacing (S to N)
y <- 10 * (1:ncol(z))
open3d()
bg3d("white")
material3d(col="black")
persp3d(x, y, z, col = colorzjet[ findInterval(z, seq(min(z), max(z), length=100))], aspect="iso",axes = TRUE, box = FALSE, smooth=FALSE,lit=FALSE,front="fill")
surface3d(x, y, z, front = "lines",col="black", lit=FALSE)
browseURL(paste("file://", writeWebGL(dir=file.path("C:/", "webGL"), width=700), sep=""))
It does not, however, currently support wireframe or point rendering, meaning that 3D surfaces will be exported as polygons without visible edges.
Does anyone know a way around that? I'd like my HTML file to show the edges of each facet on the 3D surface.
You'll need to draw the points or edges using low level functions. It's fairly easy to do points:
id <- surface3d(x, y, z, front = "lines",col="black", lit=FALSE)
vertices <- rgl.attrib(id, "vertices")
points3d(vertices)
Doing the wireframe is more complicated, because you need to join the right vertices. Here are a couple of functions that can do it.
surfaceData <- function(id) {
vertices <- rgl.attrib(id, "vertices")
dim <- rgl.attrib(id, "dim")
array(vertices, c(dim, 3))
}
surface2lines <- function(data, ...) {
vertices <- NULL
for (i in seq_len(dim(data)[1]))
vertices <- rbind(vertices, data[i,,], c(NA, NA, NA))
for (j in seq_len(dim(data)[2]))
vertices <- rbind(vertices, data[,j,], c(NA, NA, NA))
lines3d(vertices, ...)
}
You call surfaceData(id)
to extract the vertices of a surface, then surface2lines()
on that array to plot the lines. For example,
id <- surface3d(x, y, z, front = "lines",col="black", lit=FALSE)
d <- surfaceData(id)
open3d()
surface2lines(d)
which gives this image from your data:
You could overplot this on the surface; you'll likely need to play with
the depth_test
property to get it to show up on top of the surface.