20
votes

While the view3d(theta, phi,...) function can be used to rotate the viewing point to a suitable location while taking snapshot of 3d charts/objects, it's quite hard to guess which theta and phi values are good.

Once the plot is shown, we can interactively rotate it. But is there anyway to find out the theta and phi parameters of the plot after manual rotation, such that we can use it programmatically (i.e. when creating many plots that should be of the same viewpoint)?

2
See 2nd comment in accepted answer stackoverflow.com/questions/7977313/… - Julián Urbano
@JoshO'Brien Still calculating theta and phi from the matrix is not straightforward. I am preparing a complete answer for this question - Ali
Ali -- Great! I've retracted my close vote, and look forward to seeing how you extract phi and theta from that projection matrix. - Josh O'Brien
@JoshO'Brien Yes it changes. Every manual rotation can not be reconstructed by changing viewpoint, since it takes only two parameters (theta, phi), while 3 are needed - Ali

2 Answers

13
votes

I've been trying to work this out myself and I think I have the answer for maintaining the perspective of a user modified interactive plot. view3d only affects the perspective within an already open window, the key is to use open3d to set-up your window and perspectives before you actually generate the plot.

In other words, we don't actually need to use the phi and theta angle information (directly). Once you have generated an interactive plot and got the perspective you like (you'll probably want to resize the window or the image grab will be too small), something like the following will extract the required information:

zoom<-par3d()$zoom
userMatrix<-par3d()$userMatrix
windowRect<-par3d()$windowRect

Then the following will open a window at the desired size and perspective (and zoom), generate the plot, and then grab the image.

open3d(zoom = zoom, userMatrix = userMatrix, windowRect=windowRect)
perps3d(x=x,y=y,z=z) # plus whatever arguments you need, but ignoring all perspective arguments
rgl.snapshot( filename, fmt="png", top=TRUE)

That's the basic idea and can be used to automatically generate graphs of the same perspective. You can also mess around with the scale or fov arguments from par3d as you see fit, with the same sort of idea to extract and use the information. I think these are what will be required for Ali above.

It's a little inelegant to call persp3d when automatically generating multiple plots, because that function is really designed for interactive plots. I suspect you can use the information userMatrix, zoom, fov, scale etc from par3d, and some maths (such as Ali's) to determine phi, theta, r and d, and put these into persp directly - rather than dealing with persp3d for every plot, but I haven't tested that.

4
votes

There is no need to extract the viewing angles. You can extract userMatrix

um <- par3d()$userMatrix

and then use

view3d(userMatrix = um)

The viewing angles will be restored.