Hi,
A small update on the Grid aspect: I played a little with the idea of
tiling a raster motif and clipping it to a rectangle. The idea is as
follows: 1) create a motif and rasterize it with grid.cap; 2) make the
drawDetails method of the new grob to calculate how many repeats of
the motif are needed for a particular outline size; 3) clip the tiled
motif to the rectangular outline. This setup ensures that the user is
in control of the size of the motif and that this size is maintained
for different rectangle sizes (also works with dynamic resizing).
The code below works with R devel, though I ran into some weird
device-dependent problems (posted to R-dev). The working output is
attached.
Best,
baptiste
library(grid)
dots <- function(..., width=0.5, height=0.5){
x11(width=width, height=height)
grid.points(x=unit(0.5, "npc"), y=unit(0.5, "npc"), ...)
m <- grid.cap()
dev.off()
invisible(m)
}
.dots <- dots()
grid.raster(.dots)
plus <- function(..., width=0.5, height=0.5){
x11(width=width, height=height)
grid.points(x=unit(0.5, "npc"), y=unit(0.5, "npc"), pch="+",
gp=gpar(cex=3), ...)
m <- grid.cap()
dev.off()
invisible(m)
}
.plus <- plus()
grid.raster(.plus)
slash45 <- function(..., width=0.5, height=0.5){
x11(width=width, height=height)
grid.segments(...)
m <- grid.cap()
dev.off()
invisible(m)
}
.slash45 <- slash45()
grid.raster(.slash45)
bslash45 <- function(..., width=0.5, height=0.5){
x11(width=width, height=height)
grid.segments(0, 1, 1, 0, ...)
m <- grid.cap()
dev.off()
invisible(m)
}
.bslash45 <- bslash45()
grid.raster(.bslash45)
grid45 <- function(..., width=0.5, height=0.5){
x11(width=width, height=height)
grid.polygon(...)
m <- grid.cap()
dev.off()
invisible(m)
}
.grid45 <- grid45()
## grid.raster(.grid45)
tile.motif <- function(m, nx=10, ny=nx){
cols <- matrix(rep(m, nx), ncol=ncol(m)*nx, byrow=F)
matrix(rep(t(cols), ny), nrow=nrow(cols)*ny, byrow=T)
}
## quartz()
## grid.raster(tile.motif(.dots, 2, 3))
## grid.raster(tile.motif(.grid45, 2, 3))
## grid.raster(tile.motif(.slash45, 2, 3))
## grid.raster(tile.motif(.bslash45, 2, 3))
patternGrob <- function(x=unit(0.5, "npc"), y=unit(0.5, "npc"),
width=unit(1, "npc"), height=unit(1, "npc"),
motif=matrix("white"), AR=1,
motif.width=unit(5, "mm"),
motif.height=AR*motif.width,
pattern.offset=c(0, 0), # unimplemented
default.units="npc",
clip=TRUE, gp=gpar(fill=NA), ...)
{
grob(x=x, y=y, width=width, height=height,
motif=motif, motif.width=motif.width,
motif.height=motif.height, clip=clip, gp=gp, ..., cl="pattern")
}
widthDetails.pattern <- function(x) x$width
heightDetails.pattern <- function(x) x$height
drawDetails.pattern <- function(x, recording=TRUE){
## calculate the number of tiles
nx <- ceiling(convertUnit(x$width, "in", value=TRUE) /
convertUnit(x$motif.width, "in", value=TRUE)) + 1
ny <- ceiling(convertUnit(x$height, "in", axisFrom = "y", value=TRUE) /
convertUnit(x$motif.height, "in", axisFrom = "y",
value=TRUE)) + 1
width <- convertUnit(x$width, "in")
height <- convertUnit(x$height, "in", axisFrom = "y")
## clip the raster
pushViewport(viewport(x=x$x, y=x$y,
width=x$width, height=x$height, clip=x$clip))
grid.raster(tile.motif(x$motif, nx, ny), width=nx*x$motif.width,
height=ny*x$motif.height)
upViewport()
## overlay the rectangle
grid.rect(x=x$x, y=x$y,
width=x$width, height=x$height,
just="center", gp=x$gp)
}
g1 <- patternGrob(x=0.2, y=0.1, width=unit(0.2, "npc"),
height=unit(0.1, "npc"),
clip=TRUE, motif=.dots)
g2 <- patternGrob(x=0.7, width=unit(3.7, "cm"),
height=unit(5.2, "cm"),
clip=TRUE, motif=.grid45)
g3 <- patternGrob(x=0.2, width=unit(0.2, "npc"),
height=unit(2.3, "cm"),
clip=TRUE, motif=.slash45)
g4 <- patternGrob(x=0.7, y=0.1, width=unit(2, "in"),
gp=gpar(fill=NA, col="blue", lwd=2),
height=unit(0.1, "npc"), AR=3,
clip=TRUE, motif=.bslash45)
g5 <- patternGrob(x=0.5, y=0.8, width=unit(1, "npc"),
gp=gpar(fill=NA, col="blue", lwd=2),
height=unit(0.1, "npc"),
clip=TRUE, motif=.plus)
quartz()
grid.newpage()
lapply(ls(pattern="g[[:digit:]]"), function(g) grid.draw(get(g)))