1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
|
\name{setAxisCallbacks}
\alias{setAxisCallbacks}
\title{
User-defined axis labelling callbacks.
}
\description{
This function sets user callbacks to construct axes in R or
\code{\link{rglwidget}} displays.
}
\usage{
setAxisCallbacks(axes, fns,
javascript = NULL,
subscene = scene$rootSubscene$id,
scene = scene3d(minimal = FALSE),
applyToScene = TRUE,
applyToDev = missing(scene))
}
\arguments{
\item{axes}{
Which axes? Specify as number in \code{1:3} or letter in
\code{c("x", "y", "z")}.
}
\item{fns}{
Function or list of functions or character vector giving
names of functions.
}
\item{javascript}{
Optional block of Javascript code to be
included (at the global level).
}
\item{subscene}{
Which subscene do these callbacks apply to?
}
\item{scene}{
Which scene?
}
\item{applyToScene}{
Should these changes apply to the scene object?
}
\item{applyToDev}{
Should these changes apply to the current device?
}
}
\details{
If \code{applyToScene} is \code{TRUE}, this function adds Javascript
callbacks to the \code{scene} object.
If \code{applyToDev} is \code{TRUE}, it adds R
callbacks to the current RGL device.
For Javascript,
the callbacks are specified as strings; these will be
evaluated within the browser in the global context to define the functions,
which will then be called with the Javascript
\code{this} object set to the current
\code{rglwidgetClass} object.
For R, they may be strings or R functions.
Both options may be \code{TRUE}, in which case the
callbacks must be specified as strings which are
both valid Javascript and valid R. The usual way to
do this is to give just a function name, with the
function defined elsewhere, as in the Example below.
The functions should have a header of the form
\code{function(margin)}. The \code{margin} argument
will be a string like \code{"x++"} indicating which margin
would be chosen by R. If RGL would not choose to draw any
axis annotations (which happens with \code{\link{rglwidget}}, though
not currently in R itself), only the letter will be passed,
e.g. \code{"x"}.
}
\value{
Invisibly returns an \code{rglScene} object. This
object will record the changes if \code{applyToScene}
is \code{TRUE}.
If \code{applyToDev} is \code{TRUE}, it will also
have the side effect of attempting to install the
callbacks.
}
\seealso{
\code{\link{setUserCallbacks}} for mouse callbacks.
}
\author{
Duncan Murdoch
}
\examples{
# Draw arrows instead of tick marks on axes
arrowAxis <- local({
ids <- c(NA, NA, NA)
bbox <- c(NA, NA, NA, NA, NA, NA)
function(margin) {
dim <- if (grepl("x", margin)) 1 else
if (grepl("y", margin)) 2 else
3
inds <- 2*dim + (-1):0
range <- par3d("bbox")[inds]
if (!identical(bbox[inds], range)) {
if (!is.na(ids[dim]))
pop3d(id = ids[dim])
bbox[inds] <<- range
center <- mean(range)
from <- mean(c(range[1], center))
to <- mean(c(center, range[2]))
# margin should agree with suggestion, so use "x++" etc.
margin <- gsub("-", "+", margin)
ids[dim] <<- arrow3d(p0 = c(from, 1, 1),
p1 = c(to, 1, 1),
n = 4,
type = "lines",
margin = margin,
floating = TRUE)
}
}
})
# Define the Javascript function with the same name to use in WebGL
# Since Javascript won't change the bounding box, this function
# doesn't need to do anything.
js <- "
window.arrowAxis = function(margin) {} ;
"
xyz <- matrix(rnorm(60), ncol = 3)
plot3d(xyz, xlab = "x", ylab = "y", zlab = "z")
setAxisCallbacks(1:3, "arrowAxis", javascript = js)
rglwidget()
}
|