user2249626
user2249626

Reputation: 453

draw cube into 3D scatterplot in RGL

I'm trying to add a smaller cube/mesh (with specified side length) to a 3D scatterplot. I'd like for the cube to be positioned at the origin. How would I go about doing that? I've played around with cube3d() but I can't seem to position the cube right nor make it a mesh (so I can see the data points it contains. Here's what I have:

library(rgl)
x <- runif(100)
y <- runif(100)
z <- runif(100)
plot3d(x,y,z, type="p", col="red", xlab="x", ylab="y", zlab="z", site=5, lwd=15)

Upvotes: 2

Views: 7743

Answers (2)

IRTFM
IRTFM

Reputation: 263342

There is a cube3d function that by default returns a list object (but does not plot it) that represents a cube spanning x:[-1,1]; y:[-1,1]; z:[-1,1]. If you apply a color to the sides, it will be solid by default. You need to make the sides transparent with 'alpha" (see ?rgl.materials). So if we start out with the plot you used:

library(rgl)
x <- runif(100)
y <- runif(100)
z <- runif(100)
plot3d(x,y,z, type="p", col="red", xlab="x", ylab="y", zlab="z", site=5, lwd=15)
c3d <- cube3d(color="red", alpha=0.1)  # nothing happens yet
c3d   # Look at structure
shade3d(c3d)   # render the object

This expands the plot to the default dimensions of the transparent red cube mentioned above. The vertices are at the xyz location in the first three rows of the $vb element:

c3b$vb
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,]   -1    1   -1    1   -1    1   -1    1
[2,]   -1   -1    1    1   -1   -1    1    1
[3,]   -1   -1   -1   -1    1    1    1    1
[4,]    1    1    1    1    1    1    1    1

Now to make another cube that has one of its vertices at the origin, the quickest way I could think of was to set all the -1's to 0:

 c3d.origin <- cube3d(color="red", alpha=0.1)
 c3d.origin$vb [c3d.origin$vb == -1] <- 0
 shade3d(c3d.origin)
 rgl.snapshot("cubes3d.png")

enter image description here

Upvotes: 3

Bryan Hanson
Bryan Hanson

Reputation: 6213

Here's something I had around for various purposes. It should get you started.

box <- data.frame(
    x = c(1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1),
    y = c(1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1),
    z = c(1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1))
segments3d(box$x, box$y, box$z, line_antialias = TRUE, col = "blue")
points3d(0,0,0, col = "red", size = 5, point_antialias = TRUE)

Upvotes: 0

Related Questions