Search code examples
rggplot2r-grid

ggplot2: return value from draw_panel


I am learning to code in ggplot2. I wish to create a new geom which makes something complex – not a simple polygon. Say, a rectangle with a point in the middle.

When I am defining my new geom object, say GeomFafik, I need to specify the function draw_panel (or draw_group, or whichever) which returns a grob. Here is how it looks now (based on the extending ggplot2 vignette:

GeomFafik <- ggproto("GeomFafik", 
               Geom, 
               required_aes=c("xmin", "ymin", "xmax", "ymax"),
               default_aes=aes(shape=19, colour="black"),
               draw_key=draw_key_blank(),
               draw_panel=function(data, panel_params, coord) {
                  coords <- coord$transform(data, panel_params)
                  # how can I combine grob1 with grob2 and 
                  # return the result?
                  grob1 <- grid::rectGrob(coords$xmin, coords$ymin,
                                          width=coords$xmax - coords$xmin, 
                                          height=coords$ymax - coords$ymin,
                                          gp=gpar(col=coord$colour))
                  grob2 <- grid::pointsGrob(x=coords$xmin + (coords$xmax - coords$xmin)/2,
                                            y=coords$ymin + (coords$ymax - coords$ymax)/2,
                                            gp=gpar(col=coord$colour))
               })

Am I right that I should build a grob using grob() or gTree() from grid? Or is there a ggplot2 way of doing that (similar to zeroGrob)? And if grid, then which of the two should I use? And where can I find examples? The manual page doesn't really say much.


Solution

  • OK, so that was easier than I thought. The solution is to use gTree as follows (thanks to this example):

    GeomFafik <- ggproto("GeomFafik",
                   Geom, 
                   required_aes=c("xmin", "ymin", "xmax", "ymax"),
                   default_aes=aes(shape=19, colour="black"),
                   draw_key=draw_key_blank(),
                   draw_panel=function(data, panel_params, coord) {
    
                      coords <- coord$transform(data, panel_params)
    
                      w <- coords$xmax - coords$xmin
                      h <- coords$ymax - coords$ymin
                      x <- coords$xmin + w/2
                      y <- coords$ymin + h/2
                      grob1 <- grid::rectGrob(x, y, width=w, height=h,
                                              gp=gpar(col=coord$colour))
                      grob2 <- grid::pointsGrob(x=x, y=y,
                                                gp=gpar(col=coord$colour))
                      grid::gTree("fafik_grob", children=grid::gList(grob1, grob2))
                   })
    
    
    geom_fafik <- function(mapping = NULL, data = NULL, stat = "identity",
                                  position = "identity", na.rm = FALSE, show.legend = NA, 
                                  inherit.aes = TRUE, ...) {
      layer(
        geom = GeomFafik, mapping = mapping,  data = data, stat = stat, 
        position = position, show.legend = show.legend, inherit.aes = inherit.aes,
        params = list(na.rm = na.rm, ...)
      )
    }
    

    Result, which is what I wanted:

    enter image description here