\documentclass{beamer} \setbeamertemplate{navigation symbols}{} % \usetheme{Copenhagen} % \usetheme{Warsaw} \usetheme{default} \useinnertheme{rounded} \useinnertheme{circles} \useoutertheme{headshadow} \usecolortheme{orchid} \usecolortheme{whale} \setbeamercolor{item}{fg=black} \usepackage{calc} \usepackage{alltt} \usepackage{Sweave} \usepackage{boxedminipage} \usepackage{ulem} \usepackage{hyperref} \usepackage{fancyvrb} \newcommand{\R}{{\sffamily R}} \DeclareFixedFont{\almosttiny}{OT1}{cmr}{m}{n}{6} \renewcommand{\emph}[1]{{\bfseries #1}} \newcommand{\pkg}[1]{{\bfseries #1}} \newcommand{\code}[1]{{\ttfamily #1}} \newcommand{\dfn}[1]{{\bfseries #1}} \definecolor{greybg}{gray}{0.9} \definecolor{grey}{gray}{.8} \definecolor{dkgrey}{gray}{0.5} \newcommand{\intpic}[3]{ \setlength{\fboxsep}{.1in} \colorbox{white}{\begin{minipage}[t]{#1} \vspace{0pt} \includegraphics[width=#1]{#2} \end{minipage}\begin{minipage}[t]{\textwidth - #1 - .2in} % .2 = 2 x .1 \vspace{0pt} \setlength{\parindent}{.1in} \narrower ~\\ #3 \newline ~ \end{minipage}}} \begin{document} <>= options(prompt=" ") options(continue=" ") @ \SweaveOpts{keep.source = true, eps = false} \title{Gore: What is it Good For?} \author{Paul Murrell} \institute{The University of Auckland} \date{July 2011} \frame{\titlepage} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Overview} \begin{itemize} \item Several \R{} graphics packages provide convenient high-level functions for producing statistical plots. \end{itemize} <>= library(ggplot2) qplot(Sepal.Length, Sepal.Width, data=iris, color=Species) @ \begin{center} \includegraphics[width=.5\textwidth]{gore-ggplot} \end{center} \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Overview} \begin{itemize} \item Several graphics packages also provide access to much lower-level graphics facilities (gory graphics details). \end{itemize} <>= library(grid) grid.lines(x, y, gp=gpar(col="grey50", lwd=40, lineend="square", linejoin="mitre")) @ <>= x <- c(.4, .6, .4) y <- c(.2, .5, .8) <> grid.points(x, y, default="npc", pch=16, gp=gpar(cex=0.5)) grid.lines(x - .3, y, gp=gpar(lwd=40, col="gray50")) # lineend="round", linejoin="round" grid.points(x - .3, y, default="npc", pch=16, gp=gpar(cex=0.5)) grid.lines(x + .3, y, gp=gpar(lwd=40, lineend="butt", linejoin="bevel", col="gray50")) grid.points(x + .3, y, default="npc", pch=16, gp=gpar(cex=0.5)) @ \begin{center} \includegraphics[width=.5\textwidth]{gore-grid} \end{center} \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Overview} \begin{itemize} \item What's the point of these gory graphical details? \begin{itemize} \item Complex paths and fill-rules \item Texture mapping \item Colour spaces \item Character encodings \item Line endings \end{itemize} \end{itemize} \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Complex paths} \begin{itemize} \item Sophisticated graphics systems allow for not just general polygonal shapes, but also for complex paths whose edges may self-intersect and/or that may consist of disjoint polygons. \end{itemize} <>= outline <- function(x, y, col="black") { n <- length(x) for (i in 1:n) { start <- i if (i == n) end <- 1 else end <- i + 1 grid.segments(x[start], y[start], x[end], y[end], default="native", arrow=arrow(angle=10, length=unit(5, "mm"), type="closed"), gp=gpar(col=col, fill=col)) } } <>= t <- seq(0, 2*pi, length=6)[-6] x <- cos(t) y <- sin(t) # grid.newpage() pushViewport(viewport(layout=grid.layout(1, 3, respect=TRUE))) pushViewport(viewport(layout.pos.col=1, xscale=c(-1, 1), yscale=c(-1, 1))) grid.polygon(x, y, default="native", gp=gpar(fill="grey")) outline(x, y) popViewport() pushViewport(viewport(layout.pos.col=2, xscale=c(-1, 1), yscale=c(-1, 1))) grid.polygon(x[c(1, 5, 2, 4, 3)], y[c(1, 5, 2, 4, 3)], default="native", gp=gpar(fill="grey")) outline(x[c(1, 5, 2, 4, 3)], y[c(1, 5, 2, 4, 3)]) popViewport() pushViewport(viewport(layout.pos.col=3, xscale=c(-1, 1), yscale=c(-1, 1))) grid.path(c(x, .5*x), c(y, .5*y), id.lengths=rep(5, 2), rule="evenodd", default="native", gp=gpar(fill="grey")) outline(x, y) outline(.5*x, .5*y) popViewport() @ \begin{center} \includegraphics[width=.8\textwidth]{gore-polygon} \end{center} \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Path fill-rules} \begin{itemize} \item When a polygon describes a complex shape, either with self-intersecting edges, or disjoint paths, there are two standard rules for determining which regions are ``inside'' the polygon: \end{itemize} <>= x <- c(0, 0, .8, .2, 1, 1) y <- c(0, 1, .5, .5, 1, 0) star <- function(lab, rule, gp=gpar(col=NA, fill="black", lwd=1)) { grid.text(lab, y=unit(1, "npc"), just="bottom") pushViewport(viewport(width=.8, height=.8)) grid.path(x, y, id.lengths=c(3, 3), default="native", gp=gp, rule=rule) popViewport() } # grid.newpage() pushViewport(viewport(layout=grid.layout(1, 3, respect=TRUE))) pushViewport(viewport(layout.pos.col=1)) star("even-odd", "evenodd") popViewport() pushViewport(viewport(layout.pos.col=2), viewport(width=.8, height=.8)) xl <- split(x, rep(1:2, each=3)) yl <- split(y, rep(1:2, each=3)) for (i in 1:2) { grid.path(xl[[i]], yl[[i]], gp=gpar(fill=rgb((1:0)[i], 0, (0:1)[i], .2))) outline(xl[[i]], yl[[i]], col=rgb((1:0)[i], 0, (0:1)[i])) } popViewport(2) pushViewport(viewport(layout.pos.col=3)) star("non-zero winding", "winding") popViewport() @ \begin{center} \includegraphics[width=.8\textwidth]{gore-fillrule} \end{center} \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Path fill-rules} \begin{itemize} \item \R{} provides support for drawing these sorts of complex paths and provides control over the fill-rule. \end{itemize} <>= library(grImport) # PostScriptTrace("GNU.eps", "GNU.xml") gnu <- readPicture("GNU.xml") # grid.newpage() pushViewport(viewport(layout=grid.layout(1, 3, respect=TRUE))) pushViewport(viewport(layout.pos.col=1)) grid.picture(gnu) grid.rect(gp=gpar(col=NA, fill="white")) downViewport("picture.scale") brokenGNU <- explodePaths(gnu[-(1:2)]) lapply(brokenGNU@paths, function(path) { grid.polygon(path@x, path@y, default="native") }) popViewport(3) pushViewport(viewport(layout.pos.col=2)) grid.picture(gnu) grid.rect(gp=gpar(col=NA, fill="white")) downViewport("picture.scale") grid.polygon(gnu@paths[[3]]@x, gnu@paths[[3]]@y, default="native", gp=gpar(fill="black")) grid.text('grid.polygon()', y=0, just="top") popViewport(3) pushViewport(viewport(layout.pos.col=3)) grid.picture(gnu) grid.text('grid.path(rule="winding")', y=0, just="top") popViewport() @ \begin{center} \includegraphics[width=.8\textwidth]{gore-gnu} \end{center} \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Path fill-rules} \begin{itemize} \item Complex paths can be useful for drawing plots. \end{itemize} <>= library(akima) library(maps) library(gpclib) library(maptools) quakes <- read.csv("quakes-mod.csv") quakes$long <- ifelse(quakes$LONG < 0, 360 + quakes$LONG, quakes$LONG) quakes <- quakes[quakes$LAT < 0 & quakes$long < 190, ] library(MASS) qd <- kde2d(quakes$long, quakes$LAT, n=100) ql <- contourLines(qd$x, qd$y, qd$z, nlevels=10) n <- length(ql) # points(quakes$long, quakes$LAT, pch=".") outline <- map("nz", plot=FALSE) xrange <- range(outline$x, na.rm=TRUE) yrange <- range(outline$y, na.rm=TRUE) xbox <- xrange + c(-2, 2) ybox <- yrange + c(-2, 2) hue <- 240 <>= par(mar=rep(2, 4)) # Plot the data map("nz") mapply(function(c, col) { polygon(c, col=col, border=adjustcolor(col, 1, .9, .9, .9)) }, ql, as.list(hcl(hue, 50, 20 + 60*n:1/(n+1)))) # grey(.7*n:1/(n+1) + .2))) polypath(c(outline$x, NA, c(xbox, rev(xbox))), c(outline$y, NA, rep(ybox, each=2)), col="white", rule="evenodd") points(quakes$long[quakes$MAG > 7], quakes$LAT[quakes$MAG > 7], pch=21, bg=hcl(hue - 180, 80, 80)) box() @ \begin{center} \includegraphics[width=.6\textwidth]{gore-nzfinal} \end{center} \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Path fill-rules} \begin{itemize} \item The plot consists of data symbols ... \end{itemize} <>= par(mar=rep(2, 4)) map("nz", col=NA) points(quakes$long[quakes$MAG > 7], quakes$LAT[quakes$MAG > 7], pch=21, bg=hcl(hue - 180, 50, 80)) box() @ \begin{minipage}{.5\textwidth} <>= points(x, y, ...) @ \end{minipage}% \begin{minipage}{.5\textwidth} \begin{center} \includegraphics[width=\textwidth]{gore-nzpoints} \end{center} \end{minipage}% \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Path fill-rules} \begin{itemize} \item ... a map outline ... \end{itemize} <>= par(mar=rep(2, 4)) # Plot the data map("nz") box() @ \begin{minipage}{.5\textwidth} <>= library(maps) map("nz") @ \end{minipage}% \begin{minipage}{.5\textwidth} \begin{center} \includegraphics[width=\textwidth]{gore-nzmap} \end{center} \end{minipage}% \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Path fill-rules} \begin{itemize} \item ... and contour lines. \end{itemize} <>= par(mar=rep(2, 4)) # Plot the data map("nz", col=NA) mapply(function(c, col) { polygon(c, col=col, border=adjustcolor(col, 1, .9, .9, .9)) }, ql, as.list(hcl(hue, 50, 20 + 60*n:1/(n+1)))) box() @ \begin{minipage}{.5\textwidth} <>= mapply(polygon, contourLines(...), col=...) @ \end{minipage}% \begin{minipage}{.5\textwidth} \begin{center} \includegraphics[width=\textwidth]{gore-nzcontour} \end{center} \end{minipage}% \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Path fill-rules} \begin{itemize} \item The map is a complex path that describes the border of New Zealand. \end{itemize} <>= par(mar=rep(2, 4)) map("nz", col="grey", fill=TRUE) @ \begin{minipage}{.5\textwidth} <>= outline <- map("nz", plot=FALSE) polypath(outline, rule="evenodd") @ \end{minipage}% \begin{minipage}{.5\textwidth} \begin{center} \includegraphics[width=\textwidth]{gore-nzmappath} \end{center} \end{minipage}% \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Path fill-rules} \begin{itemize} \item We can add points to add a bounding box to this path ... \end{itemize} <>= par(mar=rep(2, 4)) map("nz", col=NA) polypath(c(outline$x, NA, c(xbox, rev(xbox))), c(outline$y, NA, rep(ybox, each=2)), col="white", rule="evenodd") box() @ \begin{minipage}{.5\textwidth} <>= xrange <- range(outline$x) xbox <- xrange + c(-2, 2) path$x <- c(outline$x, NA, c(xbox, rev(xbox))) @ \end{minipage}% \begin{minipage}{.5\textwidth} \begin{center} \includegraphics[width=\textwidth]{gore-nzpathbox} \end{center} \end{minipage}% \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Path fill-rules} \begin{itemize} \item Filling with an ``evenodd'' rule now fills everything outside New Zealand. \end{itemize} <>= par(mar=rep(2, 4)) map("nz", col=NA) polypath(c(outline$x, NA, c(xbox, rev(xbox))), c(outline$y, NA, rep(ybox, each=2)), col="grey", rule="evenodd") box() @ \begin{minipage}{.5\textwidth} <>= polypath(path, rule="evenodd") @ \end{minipage}% \begin{minipage}{.5\textwidth} \begin{center} \includegraphics[width=\textwidth]{gore-nzpathfill} \end{center} \end{minipage}% \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Path fill-rules} \begin{itemize} \item The contours are drawn first ... \end{itemize} <>= par(mar=rep(2, 4)) # P1 map("nz", col=NA) mapply(function(c, col) { polygon(c, col=col, border=adjustcolor(col, 1, .9, .9, .9)) }, ql, as.list(hcl(hue, 50, 20 + 60*n:1/(n+1)))) box() @ \begin{minipage}{.5\textwidth} <>= mapply(polygon, contourLines(...), col=...) @ \end{minipage}% \begin{minipage}{.5\textwidth} \begin{center} \includegraphics[width=\textwidth]{gore-nzoverlaycontour} \end{center} \end{minipage}% \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Path fill-rules} \begin{itemize} \item ... then the inverted New Zealand region is filled to obscure the contours outside New Zealand ... \end{itemize} <>= par(mar=rep(2, 4)) # P1 map("nz", col=NA) mapply(function(c, col) { polygon(c, col=col, border=adjustcolor(col, 1, .9, .9, .9)) }, ql, as.list(hcl(hue, 50, 20 + 60*n:1/(n+1)))) polypath(c(outline$x, NA, c(xbox, rev(xbox))), c(outline$y, NA, rep(ybox, each=2)), col="white", rule="evenodd") box() @ \begin{minipage}{.5\textwidth} <>= mapply(polygon, contourLines(...), col=...) polypath(path, rule="evenodd") @ \end{minipage}% \begin{minipage}{.5\textwidth} \begin{center} \includegraphics[width=\textwidth]{gore-nzoverlaypath} \end{center} \end{minipage}% \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Path fill-rules} \begin{itemize} \item ... and finally the points are drawn over the top. \end{itemize} <>= par(mar=rep(2, 4)) map("nz", col=NA) mapply(function(c, col) { polygon(c, col=col, border=adjustcolor(col, 1, .9, .9, .9)) }, ql, as.list(hcl(hue, 50, 20 + 60*n:1/(n+1)))) polypath(c(outline$x, NA, c(xbox, rev(xbox))), c(outline$y, NA, rep(ybox, each=2)), col="white", rule="evenodd") points(quakes$long[quakes$MAG > 7], quakes$LAT[quakes$MAG > 7], pch=21, bg=hcl(hue - 180, 50, 80)) box() @ \begin{minipage}{.5\textwidth} <>= mapply(polygon, contourLines(...), col=...) polypath(path, rule="evenodd") points(x, y, ...) @ \end{minipage}% \begin{minipage}{.5\textwidth} \begin{center} \includegraphics[width=\textwidth]{gore-nzoverlaypoints} \end{center} \end{minipage}% \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Texture Mapping} \begin{itemize} \item When drawing a 3D image, surfaces can be ``coloured'' using an image. \end{itemize} <>= library(png) png("worldsmall.png", width=600, height=300) worldsmall <- readPNG(system.file("textures/worldsmall.png",package="rgl")) grid.raster(worldsmall) dev.off() png("worldsmall-grid.png", width=600, height=300) worldsmall <- readPNG(system.file("textures/worldsmall.png",package="rgl")) grid.raster(worldsmall) grid.rect(x=rep(0:19/20, 20), y=rep(0:19/20, each=20), width=1/20, height=1/20, just=c("left", "bottom"), gp=gpar(fill=NA)) dev.off() library(rgl) lat <- matrix(seq(90,-90, len=20)*pi/180, 20, 20, byrow=TRUE) long <- matrix(seq(-180, 180, len=20)*pi/180, 20, 20) r <- 6378.1 # radius of Earth in km x <- r*cos(lat)*cos(long) y <- r*cos(lat)*sin(long) z <- r*sin(lat) open3d(windowRect=c(0, 0, 300, 300)) clear3d("all") light3d() persp3d(x, y, z, col="white", axes=FALSE, box=FALSE, xlab="", ylab="", zlab="", normal_x=x, normal_y=y, normal_z=z) par3d(userMatrix=rotationMatrix(-pi/2, 1, 0, 0)%*% rotationMatrix(-30/180*pi, 0, 0, 1)%*% rotationMatrix(45/180*pi, 1, 0, 0), zoom=2/3) snapshot3d("sphere.png") open3d(windowRect=c(0, 0, 300, 300)) clear3d("all") material3d(shininess=100, specular="black") persp3d(x, y, z, col="black", front="line", back="culled", axes=FALSE, box=FALSE, xlab="", ylab="", zlab="", normal_x=x, normal_y=y, normal_z=z) par3d(userMatrix=rotationMatrix(-pi/2, 1, 0, 0)%*% rotationMatrix(-30/180*pi, 0, 0, 1)%*% rotationMatrix(45/180*pi, 1, 0, 0), zoom=2/3) snapshot3d("sphereWire.png") open3d(windowRect=c(0, 0, 300, 300)) clear3d("all") light3d() persp3d(x, y, z, col="white", texture=system.file("textures/worldsmall.png",package="rgl"), specular="black", axes=FALSE, box=FALSE, xlab="", ylab="", zlab="", normal_x=x, normal_y=y, normal_z=z) par3d(userMatrix=rotationMatrix(-pi/2, 1, 0, 0)%*% rotationMatrix(-30/180*pi, 0, 0, 1)%*% rotationMatrix(45/180*pi, 1, 0, 0), zoom=2/3) snapshot3d("sphereTexture.png") @ \begin{verbatim} library(rgl) \end{verbatim} \begin{center} \setlength{\fboxsep}{0in} \begin{minipage}{.6\textwidth}% \fbox{\includegraphics[width=\textwidth]{worldsmall.png}}% \begin{verbatim} "worldsmall.png" \end{verbatim} \end{minipage}% \begin{minipage}{.4\textwidth}% \includegraphics[width=\textwidth]{sphere.png}% \begin{verbatim} persp3d(x, y, z) \end{verbatim} \end{minipage}% \end{center} \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Texture Mapping} \begin{itemize} \item Points on the image are mapped to vertices on the 3D surface. \end{itemize} \begin{center} \setlength{\fboxsep}{0in} \begin{minipage}{.6\textwidth}% \fbox{\includegraphics[width=\textwidth]{worldsmall-grid.png}}% \end{minipage}% \begin{minipage}{.4\textwidth}% \includegraphics[width=\textwidth]{sphereWire.png}% \end{minipage}% \end{center} \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Texture Mapping} \begin{itemize} \item Points on the image are mapped to vertices on the 3D surface. \end{itemize} \begin{center} \setlength{\fboxsep}{0in} \begin{minipage}{.62\textwidth}% \begin{verbatim} persp3d(x, y, z, texture="worldsmall.png") \end{verbatim} \end{minipage}% \begin{minipage}{.38\textwidth}% \includegraphics[width=\textwidth]{sphereTexture.png}% \end{minipage}% \end{center} \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Texture Mapping} \begin{itemize} \item Texture mapping can be useful for drawing plots. \end{itemize} <>= load("RData_forpaul") nrz <- nrow(z) ncz <- ncol(z) color <- colorRampPalette(c("blue", "white", "red"))(16) zfacet <- 0.25*(z[-1, -1] + z[-1, -ncz] + z[-nrz, -1] + z[-nrz, -ncz]) facetcol <- cut(zfacet,breaks=c(-7,-4,seq(-3,3,by=0.5),4,7)) library(maps) customFC <- function(x, y, z, col, levels) { par(mar = rep(0, 4)) plot.new() plot.window(range(x, finite=TRUE), range(y, finite=TRUE), "", xaxs="i", yaxs="i", asp=NA) .Internal(filledcontour(as.double(x), as.double(y), z, as.double(levels), col=col)) } # Do a PNG of filled.contour with world map png("world.png", width=600, height=300) customFC(x, y, z, col=color, levels=c(-7, -4, seq(-3, 3, by=0.5), 4, 7)) map("world", add=TRUE, interior=FALSE) dev.off() xx <- matrix(x, nrow=length(x), ncol=length(y)) yy <- matrix(2*rev(y), nrow=length(x), ncol=length(y), byrow=TRUE) zz <- z[, dim(z)[2]:1] open3d(windowRect=c(0, 0, 900, 900)) clear3d("all") light3d() persp3d(x, y, z, zlim=c(-10, 10), aspect=c(1, .5, 1), col="white", specular="black", texture="world.png", texture_s=matrix(1:128/129, 128, 64), texture_t=matrix(1:64/65, 128, 64, byrow=TRUE), axes=FALSE, box=FALSE, xlab="", ylab="", zlab="") par3d(userMatrix=rotationMatrix(-pi/2, 1, 0, 0)%*% rotationMatrix(15/180*pi, 1, 0, 0)%*% rotationMatrix(50/180*pi, 0, 0, 1)%*% rotationMatrix(30/180*pi, 1, 0, 0), zoom=.75) snapshot3d("heatmapTexture.png") @ \begin{center} \includegraphics[bb=0 200 900 700, clip, width=\textwidth]{heatmapTexture.png} \end{center} \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Texture Mapping} \begin{itemize} \item The plot consists of a filled contour ... \end{itemize} <>= pdf("heatmap.pdf") customFC(x, y, z, col=color, levels=c(-7, -4, seq(-3, 3, by=0.5), 4, 7)) dev.off() pdf("worldmap.pdf", height=3.5) par(mar=rep(0, 4)) map("world", interior=FALSE) dev.off() open3d(windowRect=c(0, 0, 900, 900)) clear3d("all") light3d() persp3d(x, y, z, front="fill", back="fill", col="white", zlim=c(-10, 10), aspect=c(1, .5, 1), axes=FALSE, box=FALSE, xlab="", ylab="", zlab="") par3d(userMatrix=rotationMatrix(-pi/2, 1, 0, 0)%*% rotationMatrix(15/180*pi, 1, 0, 0)%*% rotationMatrix(50/180*pi, 0, 0, 1)%*% rotationMatrix(30/180*pi, 1, 0, 0), zoom=.75) snapshot3d("surface.png") @ \begin{minipage}{.5\textwidth}% \begin{verbatim} filled.contour(x, y, z) \end{verbatim} \end{minipage}% \begin{minipage}{.5\textwidth}% \includegraphics[width=\textwidth]{heatmap}% \end{minipage}% \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Texture Mapping} \begin{itemize} \item ... a map ... \end{itemize} \begin{minipage}{.5\textwidth}% \begin{verbatim} library(maps) map("world") \end{verbatim} \end{minipage}% \begin{minipage}{.5\textwidth}% \includegraphics[width=\textwidth]{worldmap}% \end{minipage}% \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Texture Mapping} \begin{itemize} \item ... and a 3D surface. \end{itemize} \begin{minipage}{.5\textwidth}% \begin{verbatim} library(rgl) persp3d(x, y, z) \end{verbatim} \end{minipage}% \begin{minipage}{.5\textwidth}% \includegraphics[bb=0 200 900 700, clip, width=\textwidth]{surface.png} \end{minipage}% \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Texture Mapping} \begin{itemize} \item The map and heatmap can be combined in a PNG image. \end{itemize} \begin{minipage}{.5\textwidth}% \begin{verbatim} png("world.png") filled.contour(x, y, z) map("world", add=TRUE) dev.off() \end{verbatim} \end{minipage}% \begin{minipage}{.5\textwidth}% \includegraphics[width=\textwidth]{world.png} \end{minipage}% \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Texture Mapping} \begin{itemize} \item The image is then used as a texture for the surface. \end{itemize} <>= open3d(windowRect=c(0, 0, 900, 900)) clear3d("all") light3d() persp3d(x, y, z, front="fill", back="fill", col="white", zlim=c(-10, 10), aspect=c(1, .5, 1), axes=FALSE, box=FALSE, xlab="", ylab="", zlab="") material3d(alpha=.8) surface3d(x, y, matrix(4, nrow=length(x), ncol=length(y)), col="white", specular="black", texture="world.png", texture_s=matrix(1:128/129, 128, 64), texture_t=matrix(1:64/65, 128, 64, byrow=TRUE)) par3d(userMatrix=rotationMatrix(-pi/2, 1, 0, 0)%*% rotationMatrix(15/180*pi, 1, 0, 0)%*% rotationMatrix(50/180*pi, 0, 0, 1)%*% rotationMatrix(30/180*pi, 1, 0, 0), zoom=.75) snapshot3d("combine.png") @ \begin{center} \begin{minipage}{.52\textwidth}% \begin{verbatim} persp3d(x, y, x, texture="world.png") \end{verbatim} \end{minipage}% \hfill \begin{minipage}{.48\textwidth}% \includegraphics[bb=0 200 900 800, clip, width=\textwidth]{combine.png} \includegraphics[bb=0 200 900 700, clip, width=\textwidth]{heatmapTexture.png} \end{minipage}% \end{center} \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Colour Spaces} \begin{itemize} \item The colour space that most people are familiar with is RGB (Red Green Blue). <<>>= rgb(.8, .6, .4) @ \end{itemize} \begin{itemize} \item But this is not a very convenient colour space to work in. \item For example, what colour is produced by the code above? \end{itemize} \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Colour Spaces} <>= grid.rect(gp=gpar(fill=rgb(.8, .6, .4))) @ \vspace{.2in} \begin{center} \includegraphics[width=.3\textwidth]{gore-rgb} \end{center} \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Colour Spaces} \begin{itemize} \item A much nicer colour space to work in is HCL\\ (Hue Chroma Lightness). <<>>= hcl(46, 55, 67) @ \end{itemize} \begin{itemize} \item It is actually still very difficult to intuit the hue \\ (0 yields red, 120 yields green 240 yields blue),\\ but I can at least immediately tell that this is a not very colourful and moderately light colour. \end{itemize} \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Colour Spaces} \begin{itemize} \item What I also gain is the ability to generate colour \emph{sets} in a rational manner. <>= options(width=50) <<>>= hcl(46, 55, seq(10, 90, 10)) @ \end{itemize} <>= grid.circle(x=1:9/10, r=unit(1, "cm"), gp=gpar(col=NA, fill=hcl(46, 55, seq(10, 90, 10)))) @ \begin{center} \includegraphics[width=.9\textwidth]{gore-hcl} \end{center} \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Color Spaces} \begin{itemize} \item Color spaces can be useful in plots. \end{itemize} <>= library(oz) ozLines <- ozRegion() # The sections are as # follows: 1-7, coastlines of WA(1), NT(2), QLD(3), NSW(4), # VIC(5), TAS(6) and SA(7) respectively; sections 8-16 are # internal mainland state boundaries: SA-WA(8), WA-NT(9), # NT-SA(10), NT-QLD(11), QLD-SA(12), QLD-NSW(13), NSW-SA(14), # NSW-VIC(15), VIC-SA(16). makeBdry <- function(lines, rev=NULL) { if (is.null(rev)) { list(x=unlist(lapply(lines, function(line) line$x)), y=unlist(lapply(lines, function(line) line$y))) } else { list(x=unlist(mapply(function(line, rev) { if (rev) { rev(line$x) } else { line$x } }, lines, as.list(rev))), y=unlist(mapply(function(line, rev) { if (rev) { rev(line$y) } else { line$y } }, lines, as.list(rev)))) } } WA <- makeBdry(ozLines$lines[c(1, 8, 9)]) NT <- makeBdry(ozLines$lines[c(2, 11, 10, 9)], rev=c(FALSE, TRUE, TRUE, FALSE)) QLD <- makeBdry(ozLines$lines[c(3, 13, 12, 11)], rev=c(FALSE, FALSE, TRUE, FALSE)) NSW <- makeBdry(ozLines$lines[c(4, 15, 14, 13)], rev=c(FALSE, FALSE, TRUE, TRUE)) VIC <- makeBdry(ozLines$lines[c(5, 16, 15)], rev=c(FALSE, TRUE, TRUE)) TAS <- makeBdry(ozLines$lines[6]) SA <- makeBdry(ozLines$lines[c(7, 8, 10, 12, 14, 16)]) australia <- list(states=list(WA=WA, NT=NT, QLD=QLD, NSW=NSW, VIC=VIC, TAS=TAS, SA=SA), xrange=ozLines$rangex, yrange=ozLines$rangey) centre <- function(bdry) { # c(mean(range(bdry$x)), mean(range(bdry$y))) # From 'maps' package centroid.polygon(bdry) } australia$centres <- lapply(australia$states, centre) stateInfo <- read.table("oz.txt", head=TRUE, sep="\t") pop <- as.numeric(gsub(",", "", stateInfo$Population)) area <- as.numeric(gsub(",", "", stateInfo$Area)) popDens <- pop/area names(popDens) <- gsub(" +", "", stateInfo$Postal) par(mar=rep(0, 4)) plot.new() plot.window(australia$xrange, australia$yrange) for (i in names(popDens)) { polygon(australia$states[[i]], col=hcl(46, 55, 4*popDens[i])) cntr <- australia$centres[[i]] text(cntr[1], cntr[2], round(popDens[i]), col=if (4*popDens[i] < 80) "white" else "black") } oz(coast=FALSE, state=TRUE, col="grey", add=TRUE) @ \begin{center} \includegraphics[width=.5\textwidth]{gore-oz} \end{center} \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Color Spaces} \begin{itemize} \item The plot consists of polygons describing the states of Australia ... \end{itemize} <>= library(oz) par(mar=rep(1, 4)) oz() @ \begin{center} \begin{minipage}{.4\textwidth}% <>= library(oz) oz() @ \end{minipage}% \hfill \begin{minipage}{.6\textwidth}% \includegraphics[width=\textwidth]{gore-ozregions} \end{minipage}% \end{center} \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Color Spaces} \begin{itemize} \item ... and colours representing the population density of each state. \end{itemize} <>= hcl(46, 55, 4*popDens) @ <>= grid.circle(x=1:7/8, r=unit(1, "cm"), gp=gpar(col=NA, fill=hcl(46, 55, 4*sort(popDens)))) @ \begin{center} \includegraphics[width=.8\textwidth]{gore-ozcolours} \end{center} \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Color Spaces} \begin{itemize} \item An additional detail is that the text labels in each state are calculated programmatically from the state colours. \end{itemize} <>= ifelse(4*popDens < 80, "white", "black") @ <>= grid.circle(x=1:7/8, r=unit(1, "cm"), gp=gpar(col=NA, fill=hcl(46, 55, 4*sort(popDens)))) grid.text(round(sort(popDens)), x=1:7/8, gp=gpar(col=ifelse(4*sort(popDens) < 80, "white", "black"))) @ \begin{center} \includegraphics[width=.8\textwidth]{gore-oztext} \end{center} \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Color Spaces} <>= polygon(australia$states, col=hcl(46, 55, 4*popDens)) text(cntr[1], cntr[2], round(popDens), col=ifelse(4*popDens < 80, "white", "black")) @ %$ \begin{center} \includegraphics[width=.5\textwidth]{gore-oz} \end{center} \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Character Encodings} \begin{itemize} \item A \emph{font} is a collection of named glyphs. \end{itemize} \begin{center} \begin{tabular}{r c l} \code{/a} & $\rightarrow$ & \verb|a| \\ \code{/b} & $\rightarrow$ & \verb|b| \\ \code{/c} & $\rightarrow$ & \verb|c| \\ \code{/d} & $\rightarrow$ & \verb|d| \\ \code{/zero} & $\rightarrow$ & \verb|0| \\ \code{/exclam} & $\rightarrow$ & \verb|!| \\ \code{/ampersand} & $\rightarrow$ & \verb|&| \\ \code{/plusminus} & $\rightarrow$ & $\pm$ \\ \end{tabular} \end{center} \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Character Encodings} \begin{itemize} \item An \emph{encoding} pairs a number code with each named glyph. \end{itemize} \begin{center} \begin{tabular}{l c r c l} 141 & $\rightarrow$ & \code{/a} & $\rightarrow$ & \verb|a| \\ 142 & $\rightarrow$ & \code{/b} & $\rightarrow$ & \verb|b| \\ 143 & $\rightarrow$ & \code{/c} & $\rightarrow$ & \verb|c| \\ 144 & $\rightarrow$ & \code{/d} & $\rightarrow$ & \verb|d| \\ 060 & $\rightarrow$ & \code{/zero} & $\rightarrow$ & \verb|0| \\ 041 & $\rightarrow$ & \code{/exclam} & $\rightarrow$ & \verb|!| \\ 046 & $\rightarrow$ & \code{/ampersand} & $\rightarrow$ & \verb|&| \\ 261 & $\rightarrow$ & \code{/plusminus} & $\rightarrow$ & $\pm$ \\ \end{tabular} \end{center} \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Character Encodings} \begin{itemize} \item Keystrokes are recorded as number codes. \item Special escape sequences can be used to enter number codes that have no corresponding key. \end{itemize} <>= key <- function(key, filename=key) { pdf(paste(filename, ".pdf", sep=""), width=1/4, height=1/4) grid.roundrect(width=.8, height=.8) grid.text(key) dev.off() } key("A") key("B") key("C") key("D") key("0", filename="zero") key("!", filename="exclam") key("&", filename="ampersand") key("\\", filename="slash") key("2", filename="two") key("6", filename="six") key("1", filename="one") @ \begin{center} \begin{tabular}{r c l c r c l} \includegraphics[width=.12in]{A} & $\rightarrow$ & 141 & $\rightarrow$ & \code{/a} & $\rightarrow$ & \verb|a| \\ \includegraphics[width=.12in]{B} & $\rightarrow$ & 142 & $\rightarrow$ & \code{/b} & $\rightarrow$ & \verb|b| \\ \includegraphics[width=.12in]{C} & $\rightarrow$ & 143 & $\rightarrow$ & \code{/c} & $\rightarrow$ & \verb|c| \\ \includegraphics[width=.12in]{D} & $\rightarrow$ & 144 & $\rightarrow$ & \code{/d} & $\rightarrow$ & \verb|d| \\ \includegraphics[width=.12in]{zero} & $\rightarrow$ & 060 & $\rightarrow$ & \code{/zero} & $\rightarrow$ & \verb|0| \\ \includegraphics[width=.12in]{exclam} & $\rightarrow$ & 041 & $\rightarrow$ & \code{/exclam} & $\rightarrow$ & \verb|!| \\ \includegraphics[width=.12in]{ampersand} & $\rightarrow$ & 046 & $\rightarrow$ & \code{/ampersand} & $\rightarrow$ & \verb|&| \\ \includegraphics[width=.12in]{slash}\includegraphics[width=.12in]{two}\includegraphics[width=.12in]{six}\includegraphics[width=.12in]{one} & $\rightarrow$ & 261 & $\rightarrow$ & \code{/plusminus} & $\rightarrow$ & {\bfseries $\pm$} \\ \end{tabular} \end{center} \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Character Encodings} \begin{itemize} \item Character encodings can be useful for drawing plots. \end{itemize} \begin{center} \includegraphics[width=.7\textwidth]{ellEmbedded} \end{center} \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Character Encodings} \begin{itemize} \item The plot consists of a line ... \end{itemize} <>= curve(20*(3*log(1-x) + log(x))) @ <>= par(mar=c(2, 3, 2, 2)) curve(20*(3*log(1-x) + log(x)), 0.01, .9, xlab="", ylab="", axes=FALSE) box() @ \begin{center} \includegraphics[width=.5\textwidth]{gore-curve} \end{center} \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Character Encodings} \begin{itemize} \item ... and a special script-l character. \end{itemize} <>= grid.text("\200", gp=gpar(fontfamily="special")) @ \begin{center} \includegraphics[width=.5\textwidth]{gore-scriptl} \end{center} <>= lscriptFont <- Type1Font(family="special", metrics=c("./cmmi10.afm", "Helvetica-Bold.afm", "Helvetica-Oblique.afm", "Helvetica-BoldOblique.afm"), encoding="./special") pdfFonts(special=lscriptFont) @ <>= <> Sys.setlocale("LC_CTYPE", "en_NZ.iso-8859-1") <> @ \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Character Encodings} \begin{itemize} \item The Computer Modern Math Italic font. \end{itemize} {\small \begin{verbatim} ... C 94 ; WX 1000 ; N slurbelow ; B 56 133 943 371 ; C 95 ; WX 1000 ; N slurabove ; B 56 130 943 381 ; C 96 ; WX 416.667 ; N lscript ; B 11 -12 398 705 ; C 97 ; WX 528.588 ; N a ; B 40 -11 498 442 ; C 98 ; WX 429.165 ; N b ; B 47 -11 415 694 ; ... \end{verbatim} } \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Character Encodings} \begin{itemize} \item A special encoding file. \end{itemize} {\small \begin{verbatim} ... %% 0140 /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z /braceleft /bar /braceright /asciitilde /.notdef %% 0200 /lscript /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef ... \end{verbatim} } \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Character Encodings} \begin{itemize} \item Telling \R{} about the font and the encoding. \end{itemize} <>= <> @ \end{frame} <>= mtext("\200", side=2, line=1, cex=1.5, family="special") @ <>= pdf("ell.pdf", width=5, height=4) par(mar=c(2, 3, 2, 2)) curve(20*(3*log(1-x) + log(x)), 0.01, .9, xlab="", ylab="", axes=FALSE) <> mtext(expression(italic(p)), side=1, line=1) box() dev.off() embedFonts("ell.pdf", out="ellEmbedded.pdf", fontpaths=".") @ %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Character Encodings} <>= curve(20*(3*log(1-x) + log(x)), axes=FALSE) mtext("\200", side=2, family="special") @ \begin{center} \includegraphics[width=.7\textwidth]{ellEmbedded} \end{center} \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Line Endings} \begin{itemize} \item The default line ending in \R{} graphics is ``round''. \end{itemize} <>= segments(.5, 0, .5, runif(1), lwd=10) @ <>= # From R-help 2011-06-17 from Frank Harrell set.seed(1) par(mfrow=c(2, 2), mar=rep(.5, 4), oma=rep(2, 4), yaxs="i", xpd=NA) plot.new() grid.rect(gp=gpar(col=NA, fill="grey")) rect(0, 0, 1, 1, col="white", border=NA) segments(.5, 0, .5, runif(1), lwd=10) mtext("x3", side=2, line=1) mtext("x1", side=3, line=1) plot.new() rect(0, 0, 1, 1, col="white", border=NA) segments(.5, 0, .5, runif(1), lwd=10) mtext("x3", side=4, line=1) mtext("x2", side=3, line=1) mtext("x2", side=1, line=1) plot.new() rect(0, 0, 1, 1, col="white", border=NA) segments(.5, 0, .5, runif(1), lwd=10) mtext("x2", side=2, line=1) mtext("x2", side=4, line=1) mtext("x1", side=1, line=1) library(grid) # grid.rect(width=.99, height=.99) @ \begin{center} \includegraphics[width=.5\textwidth]{gore-badend} \end{center} \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Line Endings} \begin{itemize} \item Even line endings can be useful for drawing plots. \end{itemize} <>= segments(.5, 0, .5, runif(1), lwd=10, lend="butt") @ <>= set.seed(1) par(mfrow=c(2, 2), mar=rep(.5, 4), oma=rep(2, 4), yaxs="i", xpd=NA) plot.new() library(grid) grid.rect(gp=gpar(col=NA, fill="grey")) rect(0, 0, 1, 1, col="white", border=NA) segments(.5, 0, .5, runif(1), lwd=10, lend="butt") mtext("x3", side=2, line=1) mtext("x1", side=3, line=1) plot.new() rect(0, 0, 1, 1, col="white", border=NA) segments(.5, 0, .5, runif(1), lwd=10, lend="butt") mtext("x3", side=4, line=1) mtext("x2", side=3, line=1) mtext("x2", side=1, line=1) plot.new() rect(0, 0, 1, 1, col="white", border=NA) segments(.5, 0, .5, runif(1), lwd=10, lend="butt") mtext("x2", side=2, line=1) mtext("x2", side=4, line=1) mtext("x1", side=1, line=1) # grid.rect(width=.99, height=.99) @ \begin{center} \includegraphics[width=.5\textwidth]{gore-happyend} \end{center} \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Discussion} \begin{itemize} \item As well as producing convenient high-level interfaces for statistical graphics, it is important to retain access to the low-level gory details. \end{itemize} \begin{itemize} \item Implications for software design: the \emph{user} needs access to the gory details. \end{itemize} \begin{itemize} \item Implications for teaching: should we be teaching students the gory details? \end{itemize} \end{frame} %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{Acknowledgements} \begin{itemize} \item The contour map within a map came from discussions with G. Arun Kumar. \item The New Zealand boundaries came from the \pkg{maps} package. \item The earthquake data came from the GeoNet Project\\ \url{http://www.geonet.org.nz/} \item The 3D texture mapping example came from discussion with Claudia Tebaldi. \item The 3D images were produced with the \pkg{rgl} package. \item The script-l example came from discussion with Ivo Welch. \item The Australian map boundaries came from the \pkg{oz} package. \item Australian state population and area information was obtained from Wikipedia. \item The line endings example was based on an R-help post by Frank Harrell. % The Gantt Chart data set is from the \pkg{plan} package. \end{itemize} \end{frame} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % END DOCUMENT \end{document} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%% % FRAME %%%%%%% \begin{frame}[fragile] \frametitle{} \begin{itemize} \item \end{itemize} \end{frame}