Replication of the rgl point in the lattice

It would be convenient to interactively select a decent point of view using rgl , and then take the same orientation in the lattice 3D plot. For example, given the following graph using an uninformative point of view.

 library(lattice) wireframe(volcano, screen = list(x=0, y=0, z=0)) 

enter image description here

The same can be opened in rgl on

 library(rgl) persp3d(volcano) view3d(0, 0) 

enter image description here

Interactively easy to rotate the plot to an informative look.

enter image description here

Matrix giving current rgl viewpoint can be extracted

 p <- par3d() p$userMatrix 

How can I transform this matrix into the corresponding parameters x , y , z screen to replicate the representation in the lattice?

UPDATE 1

I tried 42 conversions below. The code shows the rgl plot and the corresponding lattice plot per line. If I executed it correctly (see the code below), there will still be a problem.

enter image description here

 # convert rgl viewpoint into lattice # screen orientation rgl_to_lattice_viewpoint <- function() { p <- par3d() rotm <- p$userMatrix B = 360*atan(rotm[1,2]/rotm[2,2])/(2*pi) P = 360*asin(-rotm[3,2])/(2*pi) H = 360*atan(rotm[3,1]/rotm[3,3])/(2*pi) list(x=-B, y=-P, z=-H) } # read and plot PNG image plot_png <- function(f) { img <- readPNG(f) rimg <- as.raster(img) # raster multilayer object plot(NULL, xlim=c(0,1), ylim=c(0,1), xlab = "", ylab = "", asp=1, frame=F, xaxt="n", yaxt="n") rasterImage(rimg, 0, 0, 1, 1) } # create rgl snapshot with random rotation and # corresponding lattice wireframe plot lattice_plus_rgl_plot <- function() { # rgl plot random rotation persp3d(volcano, col = "green3") theta <- sample(-180:180, 1) phi <- sample(-90:90, 1) view3d(theta, phi, fov=40) v <- rgl_to_lattice_viewpoint() f <- tempfile(fileext = ".png") rgl.snapshot(f) rgl.close() # lattice plot f2 <- tempfile(fileext = ".png") png(f2) print(wireframe(volcano, screen = v)) dev.off() # plot both plot_png(f) plot_png(f2) } # CREATE SOME PLOTS library(rgl) library(lattice) library(png) par(mfrow=c(3,2), mar=c(0,0,0,0)) replicate(3, lattice_plus_rgl_plot()) 
+5
source share
2 answers

I used the answer to this question to convert from a rotation matrix to angles: Converting an Euler to a matrix and a matrix to euler . I agree that I see a slightly different answer here: How to calculate the angle from a relational matrix . (My linear algebra is not good enough to determine which one is correct.)

 p <- par3d() rotm <- p$userMatrix B = 360*atan(rotm[1,2]/rotm[2,2])/(2*pi) P = 360*asin(-rotm[3,2])/(2*pi) H = 360*atan(rotm[3,1]/rotm[3,3])/(2*pi) > print(list(B,P,H)) [[1]] [1] 41.54071 [[2]] [1] 40.28412 [[3]] [1] 41.24902 

At this point, I already rotated the RGL object at about the “viewpoint” that you suggested. From experiments, I found that negative values ​​applied to the call of the frame apparently give the correct results. "Viewer rotation angle" is probably considered negative for "object rotation angles."

  png(); print(wireframe(volcano, screen = list(x=-B, y=-P, z=-H)) ); dev.off() 

enter image description here

There is a rotate.wireframe function in the TeachingDemos package, but it does not work very well while running rgl-graphs at the same time. (No plot was apparent until I closed the rgl device.) It also seemed unusable on a Mac (thick black line on the graph). It uses the X11 / XQuartz tools to control the interaction through the tk / tcl functions, and I could not reproduce the graphs from the displayed angles. Looking at the code, I cannot understand why this should be. But your mileage may change.

+1
source

This version of your function uses transforms from the orientlib package and makes the rotation matrix an argument:

 rgl_to_lattice_viewpoint <- function(rotm = par3d("userMatrix")) { e <- -orientlib::eulerzyx(orientlib::rotmatrix(rotm[1:3, 1:3]))@x*180/pi list(z = e[1], y = e[2], x = e[3]) } 

Note that the order of z, y, x is essential.

Using it instead of your function, I get this output: rgl and lattice graphics

They get the right rotation. I do not know if a coincidence of perspectives is also possible.

Edited to add: rgl version 0.95.1468, available only on R-forge, contains a version of this function and one for the base graphics.

+1
source

All Articles