grid Graphics
from Top to Bottom

How do we draw this in R?

Drawing text in grid

library(grid)
grid.text("CPI data")

Drawing text in grid

grid.text(c("CPI data", "code", "???"),
          x=c(2/4, 1/4, 3/4), y=c(2/3, 1/3, 1/3))

Drawing a shape in grid

grid.circle(x=c(2/4, 1/4, 3/4), y=c(2/3, 1/3, 1/3),
            r=.1)

Drawing a shape in grid

ellipse <- function(a, b) {
    angle <- seq(0, 2*pi, length=101)
    grid.polygon(.5 + a*cos(angle),
                 .5 + b*sin(angle))
}
grid.text("CPI data")
ellipse(.3, .1)

Drawing a shape the wrong size

Drawing in a viewport

ellipse <- function(a, b) {
    pushViewport(viewport(width=2*a, height=2*b,
                          name="vp"))
    angle <- seq(0, 2*pi, length=101)
    grid.polygon(.5 + .5*cos(angle),
                 .5 + .5*sin(angle))
    upViewport()
}

Drawing in a viewport

grid.text("CPI data")
ellipse(.3, .1)

Drawing with units

grid.text("CPI data")
ellipse(unit(.3, "npc"), unit(.1, "npc"))

Drawing with units

grid.text("CPI data")
ellipse(unit(2, "in"), unit(1, "in"))

Drawing a shape a fixed size

Drawing a shape the correct size

grid.text("CPI data")
ellipse(stringWidth("CPI data"), unit(1, "in"))

Drawing a shape the correct size

ellipse <- function(x, y, a, b) {
    pushViewport(viewport(x, y,
                          width=2*a, height=2*b))
    angle <- seq(0, 2*pi, length=101)
    grid.polygon(.5 + .5*cos(angle),
                 .5 + .5*sin(angle))
    popViewport()
}
node <- function(x, y, label) {
    grid.text(label, x, y)
    ellipse(x, y, stringWidth(label),
            unit(1, "lines"))
}

Drawing a shape the correct size

node(2/4, 2/3, "CPI data")
node(1/4, 1/3, "code")
node(3/4, 1/3, "???")

How do we draw this in R?

Drawing a raster

library(png)
img <- readPNG("pk.png")
grid.raster(img)

Drawing a raster wherever we like

grid.raster(img, .1, .1, width=.5,
            just=c("left", "bottom"))
pushViewport(viewport(.75, .75, .25, .25,
                      angle=45))
grid.raster(img)
popViewport()

How do we draw this in R?

Drawing a line

grid.segments(.2, .2, .8, .2)
grid.lines(c(.2, .5, .8), c(.4, .5, .4))
grid.xspline(c(.2, .5, .8), c(.6, .9, .6),
             shape=1)

Drawing a grey dotted line

grid.segments(.2, .2, .8, .2)
grid.lines(c(.2, .5, .8), c(.4, .5, .4),
           gp=gpar(lty="dotted"))
grid.xspline(c(.2, .5, .8), c(.6, .9, .6),
             shape=1,
             gp=gpar(lty="dotted", col="grey"))

Drawing a line with an arrow

arrow <- arrow(angle=20, length=unit(.1, "in"),
               type="closed")
grid.segments(.2, .2, .8, .2, arrow=arrow)
grid.lines(c(.2, .5, .8), c(.4, .5, .4),
           arrow=arrow)
grid.xspline(c(.2, .5, .8), c(.6, .9, .6),
             shape=1, arrow=arrow)

How do we draw this in R?

Drawing a grob

ellipseGrob <- function(x=.5, y=.5, a, b) {
    vp <- viewport(x, y, width=2*a, height=2*b)
    angle <- seq(0, 2*pi, length=101)
    polygonGrob(.5 + .5*cos(angle), .5 + .5*sin(angle),
                vp=vp)
}
eg <- ellipseGrob(a=.3, b=.1)

Drawing a grob

grid.draw(eg)

Drawing on the edge (of a grob)

for (i in seq(0, 360, length.out=9)) {
    grid.circle(x=grobX(eg, i), y=grobY(eg, i),
                r=unit(1, "mm"),
                gp=gpar(fill=bg))
}

Drawing a named grob

ellipseGrob <- function(x=.5, y=.5, a, b, name) {
    vp <- viewport(x, y, width=2*a, height=2*b)
    angle <- seq(0, 2*pi, length=101)
    polygonGrob(.5 + .5*cos(angle), .5 + .5*sin(angle),
                vp=vp, name=name)
}
eg <- ellipseGrob(a=.3, b=.1, name="el")

Drawing a named grob

grid.draw(eg)

Drawing on the edge (of a named grob)

for (i in seq(0, 360, length.out=9)) {
    grid.circle(x=grobX("el", i), y=grobY("el", i),
                r=unit(1, "mm"),
                gp=gpar(fill=bg))
}

How do we draw this in R?

Drawing a graph

library(graph)
gnel <- new("graphNEL",
            nodes=c("CPI", "code", "data"),
            edgeL=list(CPI=list(
                         edges=c("code", "data")),
                       code=list(),
                       data=list()),
            edgemode="directed")

Drawing a graph

library(Rgraphviz)
plot(gnel)

Drawing a better graph

library(gridGraphviz)
rag <- agopenTrue(gnel, "",
                  attrs=list(node=
                    list(shape="ellipse")))

Drawing a better graph

grid.graph(rag)

Drawing a better graph

grid.ls(rag)
edge-CPI~code
  curve-CPI~code-1
  arrowhead-CPI~code
edge-CPI~data
  curve-CPI~data-1
  arrowhead-CPI~data
CPI
  box-CPI
  label-CPI
code
  box-code
  label-code
data
  box-data
  label-data

Drawing a better graph

grid.ls(grobs=FALSE, viewports=TRUE)
ROOT
  graphSizeVP
    graphScaleVP
      2

Drawing a better graph

showViewport()

Adding to a graph

downViewport("graphScaleVP")
grid.raster(img, 1, 1, width=.4, just="bottom",
            name="img")
grid.segments(grobX("img", "west"),
              grobY("img", "west"),
              grobX(grid.get("box-CPI"), 45),
              grobY(grid.get("box-CPI"), 45),
              gp=gpar(lty="dotted"))

How do we draw this in R?

Drawing a named grob

eg <- ellipseGrob(a=.3, b=.1, name="el")
grid.draw(eg)

Exporting to SVG

svg("ellipse-svg.svg")
grid.draw(eg)
dev.off()
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlin ...
<g id="surface129">
<rect x="0" y="0" width="504" height="504" style=" ...
<path style="fill-rule:nonzero;fill:rgb(100%,100%, ...
</g>
</svg>

Exporting to SVG

library(gridSVG)
gridsvg("ellipse-gridsvg.svg")
grid.draw(eg)
dev.off()
<?xml version="1.0" encoding="ASCII"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlin ...
  <g transform="translate(0, 504) scale(1, -1)">
    <g id="gridSVG" fill="none" stroke="rgb(0,0,0) ...
      <g id="GRID.VP.32.1">
        <g id="el.1">
          <polygon id="el.1.1" points="403.2,252 4 ...
        </g>
      </g>
    </g>
  </g>
</svg>

Drawing a drop shadow

blurAlpha <- feGaussianBlur(input="SourceAlpha",
                            sd=3, result="blur")
offset <- feOffset(input="blur",
                   unit(3, "mm"), unit(-3, "mm"),
                   result="drop")
composite <- feComposite(input1="SourceGraphic",
                         input2="drop")
drop <- filterEffect(list(blurAlpha,
                          offset,
                          composite))

Drawing a drop shadow

gridsvg("ellipse-drop.svg")
grid.draw(eg)
grid.filter("el", drop)
dev.off()

Drawing a better graph

grid.graph(rag)

Drawing a better graph

grid.ls(rag)
edge-CPI~code
  curve-CPI~code-1
  arrowhead-CPI~code
edge-CPI~data
  curve-CPI~data-1
  arrowhead-CPI~data
CPI
  box-CPI
  label-CPI
code
  box-code
  label-code
data
  box-data
  label-data

Accessing grobs

grid.get("box", grep=TRUE, global=TRUE)
(polygon[box-CPI], polygon[box-code], polygon[box-data]) 

Editing grobs

grid.edit("box", grep=TRUE, global=TRUE,
          gp=gpar(fill="white"))

Drawing a graph with drop shadows

grid.filter("box", grep=TRUE, global=TRUE,
            drop)

That is how we draw this in R

Acknowledgements