Search code examples
rgraphicsr-grid

Using R 4.1.0's new `grid::pattern` function, how can I rotate a pattern


I am investigating the new pattern functionality of grid. So far, I can cross-hatch a rectangle:

library(grid)

# Note that using absolute coordinates like "cm" for
# x and y does not work
cross <- grobTree(
  linesGrob( x= unit(c(0,1),"npc"), y= unit(c(0,1),"npc")),
  linesGrob( x= unit(c(0,1),"npc"), y= unit(c(1,0),"npc")))

cpat <- pattern(cross,
  width = unit(1,"cm"),
  height = unit(1,"cm"),
  extend = "repeat")

rect <- rectGrob(
  width = unit(5, "cm"),
  height = unit(5, "cm"),
  gp= gpar(fill = cpat))

grid.newpage()
grid.draw(rect)

Cross-hatched square

But I can neither rotate my object without messing up:

grid.newpage()
grid.draw(grobTree(rect,vp=viewport(angle=20)))

rotated square, rotated pattern, but pattern repetition is not rotated

And I also cannot rotate the pattern inside the object because each time, it does not rotate the direction in which to repeat the pattern:

vp <- viewport(angle = 30)
cross <- grobTree(
  linesGrob( x= unit(c(0,1),"npc"), y= unit(c(0,1),"npc")),
  linesGrob( x= unit(c(0,1),"npc"), y= unit(c(1,0),"npc")),
  vp = vp)

cpat <- pattern(cross,
  width = unit(1,"cm"),
  height = unit(1,"cm"),
  extend = "repeat")

rect <- rectGrob(
  width = unit(5, "cm"),
  height = unit(5, "cm"),
  gp= gpar(fill = cpat))

grid.newpage()
grid.draw(rect)

square with half rotated crosses repeated without rotation

How can I rotate the direction in which the pattern is repeated?

EDIT: This is on R 4.3.1


Solution

  • This feels like a bug; the pattern should rotate with the viewport, but it seems that although each instance of the pattern is rotating, their origin relative to the viewport is not. This causes the pattern to misalign.

    A workaround is to create a large repeated pattern manually that exceeds the size of the square:

    library(grid)
    
    cross <- do.call('grobTree', c(
      lapply(seq(-5, 5, 0.1), function(x) {
        linesGrob(x = c(0, 1) + x, y = c(0, 1))
      }),
      lapply(seq(-5, 5, 0.1), function(x) {
        linesGrob(x = c(0, 1) + x, y = c(1, 0))
      })))
    
    cpat <- pattern(cross,
                    width = unit(15, "cm"),
                    height = unit(15, "cm"),
                    extend = 'none')
    
    rect <- rectGrob(
      width = unit(5, "cm"),
      height = unit(5, "cm"),
      gp = gpar(fill = cpat))
    
    grid.newpage()
    grid.draw(rect)
    

    enter image description here

    grid.newpage()
    grid.draw(grobTree(rect, vp = viewport(angle = 20)))
    

    enter image description here

    Of course, this seems to defeat the purpose of having the option of a repeated pattern. This may be a design comprimise rather than a bug per se, but perhaps worth filing a bug report.