Support for pattern fills was added to the R graphics engine in R version 4.1.0, with an R interface via the ‘grid’ package.
library(grid)
For example, the following code defines a linear gradient that varies horizontally from red to white and a tiling pattern that is based on a repeating red circle.
gradcol <- c(palette()[2], "white")
grad <- linearGradient(gradcol, y1=.5, y2=.5)
patcol <- 2
pat <- pattern(circleGrob(r=unit(2, "mm"), gp=gpar(col=patcol, fill=patcol)),
width=unit(5, "mm"), height=unit(5, "mm"),
extend="repeat")
The next code calls grid.rect()
twice, once to fill a
rectangle with the linear gradient and a second time to fill
another rectangle with the tiling pattern.
grid.rect(1/3, width=1/4, height=1/2,
gp=gpar(fill=grad))
grid.rect(2/3, width=1/4, height=1/2,
gp=gpar(fill=pat))
The following code draws the two rectangles with a single call
to grid.rect()
and fills them both using the linear gradient.
The result is that both rectangles are filled with the same
gradient from red to white, with the gradient relative to
a bounding box around both rectangles (we start with red at
the left edge of the rectangle on the left and end with white at the
right edge of the rectangle on the right).
grid.rect(1:2/3, width=1/4, height=1/2,
gp=gpar(fill=grad))
From R 4.2.0, we can produce a different result because the
linearGradient()
function has gained a group
argument.
If we set this to FALSE
, then we can fill both rectangles
with the “same” gradient fill, but the gradient fill is relative
to individual rectangles, as shown below.
grad2 <- linearGradient(gradcol, y1=.5, y2=.5,
group=FALSE)
grid.rect(1:2/3, width=1/4, height=1/2,
gp=gpar(fill=grad2))
Another change in R 4.2.0 is that we can specify more than one pattern fill.
For example, the following code draws the two rectangles in a single
grid.rect()
call and provides a list of pattern fills:
the original linear gradient and the tiling pattern.
The result is that the first rectangle is filled with the linear
gradient and the second rectangle is filled with the tiling pattern.
grid.rect(1:2/3, width=1/4, height=1/2,
gp=gpar(fill=list(grad, pat)))
The result is different from the very first example because
both the linear gradient and the tiling pattern are relative to
a bounding box around both rectangles. The following code
uses the new group
argument to fill each rectangle with a different
pattern fill and have the pattern fills relative to the individual
rectangles.
pat2 <- pattern(circleGrob(r=unit(2, "mm"), gp=gpar(col=patcol, fill=patcol)),
width=unit(5, "mm"), height=unit(5, "mm"),
extend="repeat",
group=FALSE)
grid.rect(1:2/3, width=1/4, height=1/2,
gp=gpar(fill=list(grad2, pat2)))
A further addition in R 4.2.0 is the ability to use pattern fills
on “points” (data symbols). Combining that with pattern lists
and group=FALSE
, we can, for example,
apply pattern fills to individual points on a scatterplot,
as shown below. For this example,
the pattern fill is a radial gradient from white to red.
library(gggrid)
grad3 <- radialGradient(rev(gradcol),
cx2=.8, cy2=.8, group=FALSE)
filledPoints <- function(data, coords) {
pointsGrob(coords$x, coords$y, pch=21,
gp=gpar(col=patcol, fill=grad3))
}
ggplot(mtcars) +
grid_panel(filledPoints,
mapping=aes(x=disp, y=mpg))
Further discussion and more detail about these new facilities
can be found in the
technical report
“Vectorised Pattern Fills in R Graphics”. The technical report
“Constructive Geometry for Complex Grobs”
describes related changes to the grobCoords()
function that is
used in the resolution of pattern fills.