Here is a reproducible example of the problem. I want to create side by side plot3d
in rgl with shared mouse.
#use an example from rgl's manual
set.seed(1234)
x <- sort(rnorm(100))
y <- rnorm(100)
z <- rnorm(100) + atan2(x, y)
#create side by side plot
open3d()
mfrow3d(1, 2, sharedMouse=TRUE)
plot3d(x, y, z, col=rainbow(100))
arrow3d(c(0, 0, 0), c(2, 2, 2), type="lines")
next3d()
plot3d(x, y, z, col=rainbow(100))
All good so far.
Now overlay the arrow3d to the plot on the right side
arrow3d(c(0, 0, 0), c(2, 2, 2), type="lines")
and the axes change with the arrow not placed correctly
Can't figure out what is happening. If I plot each of these two plots with arrow3d()
in separate open3d()
calls they look identical. I tried other approaches such as combineWidgets
in the manipulateWidget package, which works correctly but I can't figure out how to share the mouse across subscenes. plotly will be too tricky because my application require many 3d arrows along a path to create a trajectory and 3d arrows apparently are not easy to implement in plotly outside of annotations.
Running rgl 1.1.3 on R 4.2.2 on a mac (x86_64-apple-darwin17.0).
This is a bug in the rgl.window2user()
function that is used by arrow3d()
. It has been fixed in rgl
1.1.10, but that's only available on Github, and installing rgl
from source isn't always easy. Here's a bit of a hack to install just the bug fix in the CRAN version 1.1.3:
# This is the fixed version of rgl.window2user:
rgl.window2user <- function( x, y = NULL, z = 0, projection = rgl.projection()) {
xyz <- xyz.coords(x,y,z,recycle=TRUE)
viewport <- projection$view
normalized <- rbind( 2*(xyz$x - viewport[1]/viewport[3]) - 1,
2*(xyz$y - viewport[2]/viewport[4]) - 1,
2*xyz$z - 1,
1 )
asEuclidean(with(projection, t(solve(proj %*% model, normalized))))
}
environment(rgl.window2user) <- environment(rgl::rgl.window2user)
assignInNamespace("rgl.window2user", rgl.window2user, "rgl")
Code like this is not accepted by CRAN in a package, but for your own use it should be okay. The change it makes will only last for the current R session.