Search code examples
rr-grid

Is there a way to converting a function with a series of grid.* and viewport calls to a grob/gTree?


Is there a simple way of taking an arbitrary function with a series of calls to grid.* functions and viewport actions, like the first function below, and getting back a gTree/grob object like the one generated by the second function?

I ask as it's a lot easier to experiment with creating plots stepwise using the grid.* functions than it is to use the rather unwieldy syntax for creating complex gTrees. However then when you need to use your plots within larger plot elements or combined plots I tend to want them in a gTree form and not writing to the plot device on their own.

I've been struggling to grok grid for a while now and I feel like i've missed something even after delving pretty deep into the documentation, it seems like there must be an easier way to create complex gTrees?

library(grid)

plotter <- function(x){
  pushViewport(viewport(gp = gpar(fill = "white", col = "black", lwd = 2)))
  grid.rect(
    width = 0.3, height = 0.8,
    gp = gpar(fill = "red")
  )
}

grid.newpage()
plotter()


plotter2 <- function(x) {
  g <- gTree()
  g <- addGrob(
    g,
    rectGrob(
      width = 0.3, height = 0.8,
      gp = gpar(fill = "red"),
      vp = "vp"
    )
  )
  g$childrenvp <- viewport(name = "vp", gp = gpar(fill = "white", col = "black", lwd = 2))
  g
}

grid.newpage()
grid.draw(plotter2())

Solution

  • The grid.grab() function premits you to capture an existing drawing as a gTree when called after the plotting code which produced it. The grid.grabExpr() function permits the capture of a gTree without plotting it from an expression describing it as below:

    library(grid)
    
    plotter <- function(x) {
        grid.grabExpr(expr = {
            pushViewport(viewport(gp = gpar(fill = "white", col = "black", lwd = 2)))
            grid.rect(
                width = 0.3, height = 0.8,
                gp = gpar(fill = "red")
            )
        })
    }
    
    grid.newpage()
    grid.ls(plotter()) # to see the structure of the gTree
    grid.draw(plotter())