# fields, Tools for spatial data # Copyright 2004-2011, Institute for Mathematics Applied Geosciences # University Corporation for Atmospheric Research # Licensed under the GPL -- www.gpl.org/licenses/gpl.html "image.plot" <- function(..., add = FALSE, nlevel = 64, horizontal = FALSE, legend.shrink = 0.9, legend.width = 1.2, legend.mar = ifelse(horizontal, 3.1, 5.1), legend.lab = NULL, graphics.reset = FALSE, bigplot = NULL, smallplot = NULL, legend.only = FALSE, col = tim.colors(nlevel), lab.breaks = NULL, axis.args = NULL, legend.args = NULL, midpoint = FALSE, border=NA, lwd.poly=1.0) { # Thanks to S. Koehler and S. Woodhead # for comments on making this a better function # # save current graphics settings old.par <- par(no.readonly = TRUE) # figure out zlim from passed arguments info <- image.plot.info(...) if (add) { big.plot <- old.par$plt } if (legend.only) { graphics.reset <- TRUE } if (is.null(legend.mar)) { legend.mar <- ifelse(horizontal, 3.1, 5.1) } # # figure out how to divide up the plotting real estate. # temp <- image.plot.plt(add = add, legend.shrink = legend.shrink, legend.width = legend.width, legend.mar = legend.mar, horizontal = horizontal, bigplot = bigplot, smallplot = smallplot) # # bigplot are plotting region coordinates for image # smallplot are plotting coordinates for legend smallplot <- temp$smallplot bigplot <- temp$bigplot # # draw the image in bigplot, just call the R base function # or poly.image for polygonal cells note logical switch # for poly.grid parsed out of call from image.plot.info if (!legend.only) { if (!add) { par(plt = bigplot) } if (!info$poly.grid) { image(..., add = add, col = col) } else { poly.image(..., add = add, col = col, midpoint = midpoint, border=border, lwd.poly=lwd.poly) } big.par <- par(no.readonly = TRUE) } ## ## check dimensions of smallplot if ((smallplot[2] < smallplot[1]) | (smallplot[4] < smallplot[3])) { par(old.par) stop("plot region too small to add legend\n") } # Following code draws the legend using the image function # and a one column image. # calculate locations for colors on legend strip ix <- 1 minz <- info$zlim[1] maxz <- info$zlim[2] binwidth <- (maxz - minz)/nlevel midpoints <- seq(minz + binwidth/2, maxz - binwidth/2, by = binwidth) iy <- midpoints iz <- matrix(iy, nrow = 1, ncol = length(iy)) # extract the breaks from the ... arguments # note the breaks delineate intervals of common color breaks <- list(...)$breaks # draw either horizontal or vertical legends. # using either suggested breaks or not -- a total of four cases. # # next par call sets up a new plotting region just for the legend strip # at the smallplot coordinates par(new = TRUE, pty = "m", plt = smallplot, err = -1) # create the argument list to draw the axis # this avoids 4 separate calls to axis and allows passing extra # arguments. # then add axis with specified lab.breaks at specified breaks if (!is.null(breaks) & !is.null(lab.breaks)) { # axis with labels at break points axis.args <- c(list(side = ifelse(horizontal, 1, 4), mgp = c(3, 1, 0), las = ifelse(horizontal, 0, 2), at = breaks, labels = lab.breaks), axis.args) } else { # If lab.breaks is not specified, with or without breaks, pretty # tick mark locations and labels are computed internally, # or as specified in axis.args at the function call axis.args <- c(list(side = ifelse(horizontal, 1, 4), mgp = c(3, 1, 0), las = ifelse(horizontal, 0, 2)), axis.args) } # # draw color scales the four cases are horizontal/vertical breaks/no breaks # add a label if this is passed. if (!horizontal) { if (is.null(breaks)) { image(ix, iy, iz, xaxt = "n", yaxt = "n", xlab = "", ylab = "", col = col) } else { image(ix, iy, iz, xaxt = "n", yaxt = "n", xlab = "", ylab = "", col = col, breaks = breaks) } } else { if (is.null(breaks)) { image(iy, ix, t(iz), xaxt = "n", yaxt = "n", xlab = "", ylab = "", col = col) } else { image(iy, ix, t(iz), xaxt = "n", yaxt = "n", xlab = "", ylab = "", col = col, breaks = breaks) } } # # # now add the axis to the legend strip. # notice how all the information is in the list axis.args # do.call("axis", axis.args) # add a box around legend strip box() # # add a label to the axis if information has been supplied # using the mtext function. The arguments to mtext are # passed as a list like the drill for axis (see above) # if (!is.null(legend.lab)) { legend.args <- list(text = legend.lab, side = ifelse(horizontal, 1, 4), line = legend.mar - 2) # just guessing at a good default for line argument! } # # add the label using mtext function if (!is.null(legend.args)) { do.call(mtext, legend.args) } # # # clean up graphics device settings # reset to larger plot region with right user coordinates. mfg.save <- par()$mfg if (graphics.reset | add) { par(old.par) par(mfg = mfg.save, new = FALSE) invisible() } else { par(big.par) par(plt = big.par$plt, xpd = FALSE) par(mfg = mfg.save, new = FALSE) invisible() } }