[R] Defining origin for rotation in RGL device
Duncan Murdoch
murdoch.duncan at gmail.com
Mon Apr 25 18:51:38 CEST 2011
On 25/04/2011 7:54 AM, Duncan Murdoch wrote:
> On 25/04/2011 5:46 AM, Mark Heckmann wrote:
> > Hi all,
> >
> > How can I tell RGL to set the center for the rotation to the origin of the coordinate system (0,0,0).
> > It seems that the default is to use the center of the display not the origin of the coordinate system.
> >
> > open3d()
> > lines3d(c(0, 1), c(0,0), c(0,0))
> > lines3d(c(0,0), c(0, 1), c(0,0))
> > lines3d(c(0,0), c(0,0), c(0, 1))
> >
>
> You can attach any transformation you like to a mouse button. See the
> "mouseCallbacks" demo for R implementations of the standard ones, and
> modify the mouseTrackball function there to choose the position of the
> origin of the coordinate system as the centre of rotation.
This was a little trickier than I was thinking because of the weird
coordinate system. You have to remember to transpose translationMatrix
when you're planning to work in the coordinates of userMatrix. Here's
a function (modified from mouseTrackball in the demo) that I think does
what you want.
Just call
mouseTrackballOrigin()
to set it up on button 1 on the current device with center of rotation
at (0,0,0).
Duncan Murdoch
mouseTrackballOrigin <- function(button = 1, dev = rgl.cur(),
origin=c(0,0,0) ) {
width <- height <- rotBase <- NULL
userMatrix <- list()
cur <- rgl.cur()
offset <- NULL
scale <- NULL
screenToVector <- function(x, y) {
radius <- max(width, height)/2
centre <- c(width, height)/2
pt <- (c(x, y) - centre)/radius
len <- vlen(pt)
if (len > 1.e-6) pt <- pt/len
maxlen <- sqrt(2)
angle <- (maxlen - len)/maxlen*pi/2
z <- sin(angle)
len <- sqrt(1 - z^2)
pt <- pt * len
return (c(pt, z))
}
trackballBegin <- function(x, y) {
vp <- par3d("viewport")
width <<- vp[3]
height <<- vp[4]
cur <<- rgl.cur()
bbox <- par3d("bbox")
center <- c(sum(bbox[1:2])/2, sum(bbox[3:4])/2, sum(bbox[5:6])/2)
scale <<- par3d("scale")
offset <<- (center - origin)*scale
for (i in dev) {
if (inherits(try(rgl.set(i, TRUE)), "try-error")) dev <<-
dev[dev != i]
else userMatrix[[i]] <<- par3d("userMatrix")
}
rgl.set(cur, TRUE)
rotBase <<- screenToVector(x, height - y)
}
trackballUpdate <- function(x,y) {
rotCurrent <- screenToVector(x, height - y)
angle <- angle(rotBase, rotCurrent)
axis <- xprod(rotBase, rotCurrent)
mouseMatrix <- rotationMatrix(angle, axis[1], axis[2], axis[3])
for (i in dev) {
if (inherits(try(rgl.set(i, TRUE)), "try-error")) dev <<-
dev[dev != i]
else par3d(userMatrix = t(translationMatrix(-offset[1],
-offset[2], -offset[3])) %*% mouseMatrix %*%
t(translationMatrix(offset[1], offset[2], offset[3])) %*%userMatrix[[i]])
}
rgl.set(cur, TRUE)
}
for (i in dev) {
rgl.set(i, TRUE)
rgl.setMouseCallbacks(button, begin = trackballBegin, update =
trackballUpdate, end = NULL)
}
rgl.set(cur, TRUE)
}
More information about the R-help
mailing list