\documentclass[a4paper]{article}
%\VignetteIndexEntry{Locations versus Dimensions}
%\VignettePackage{grid}
\setlength{\parindent}{0in}
\setlength{\parskip}{.1in}
\setlength{\textwidth}{140mm}
\setlength{\oddsidemargin}{10mm}

\newcommand{\code}[1]{\texttt{#1}}
\newcommand{\pkg}[1]{{\normalfont\fontseries{b}\selectfont #1}}
\newcommand{\grid}{\pkg{grid}}

\title{The difference between Locations and Dimensions in \grid{}}
\author{Paul Murrell}

\begin{document}

\maketitle

<<echo=FALSE, results=hide>>=
library(grDevices)
library(grid)
ps.options(pointsize=12)
options(width=60)

@
\grid{} makes use of unit objects to express both the locations and
dimensions of graphical components.  For example, the \code{grid.rect()}
function treats its x- and y-arguments as locations within the current
viewport, and its width- and height-arguments as dimensions within the
current viewport.

These different interpretations of units are usually implicit like this;
if its an x- or y-value then its a location, if its a width- or height-value
then its a dimension.

The distinction is made at all because, in some coordinate systems, notably
\code{"native"} coordinates, the location $x$ can have a very different
meaning
from the dimension $x$ -- basically, whenever the minimum value of the
coordinate system is not zero.

In the specification of simple units, the difference between locations
and dimensions is often not noticeable.  However, there are a couple
of tricky areas:

\begin{enumerate}
\item When adding (or performing any arithmetic operation on) units,
it is important to keep in mind that locations are added like vectors
and dimensions are added like lengths.  The following
diagram demonstrates the difference:

<<fig=TRUE, echo=FALSE, results=hide>>=
diagram.locn <- function(i, n, locn) {
  x <- i/(n+1)
  grid.lines(x=unit(rep(x, 2), "npc"),
             y=unit.c(unit(0, "npc"), locn))
  grid.lines(x=unit(x, "npc") + unit(c(-2, 0, 2), "mm"),
             y=locn + unit(c(-2, 0, -2), "mm"))
  grid.text(paste(as.character(locn), "as a location"),
            x=unit(x, "npc") - unit(1, "mm"),
            y=locn - unit(3, "mm"),
            just=c("right", "bottom"),
            rot=90)
}
diagram.dimn <- function(i, n, dimn) {
  x <- i/(n+1)
  pushViewport(viewport(x=unit(x, "npc"), y=unit(0, "native"),
            h=dimn, w=unit(1, "lines"), just=c("centre", "bottom")))
  grid.rect()
  grid.text(paste(as.character(dimn), "as a dimension"),
            rot=90)
  popViewport()
}
pushViewport(viewport(w=.8, y=unit(1.7, "inches"),
                             h=unit(4, "inches"),
                             just=c("centre", "bottom"),
                             yscale=c(-0.6, 1.3)))
grid.grill(v=c(0, 1), h=seq(-.5, 1, .5), default.units="native")
grid.rect()
grid.yaxis()
n <- 10
diagram.locn(1, n, unit(1, "native"))
diagram.locn(2, n, unit(-0.4, "native"))
diagram.locn(3, n, unit(0.4, "native"))
diagram.locn(4, n, unit(1, "native") + unit(-0.4, "native"))
diagram.locn(5, n, unit(1, "native") - unit(0.4, "native"))
diagram.dimn(6, n, unit(1, "native"))
diagram.dimn(7, n, unit(-0.4, "native"))
diagram.dimn(8, n, unit(0.4, "native"))
diagram.dimn(9, n, unit(1, "native") + unit(-0.4, "native"))
diagram.dimn(10, n, unit(1, "native") - unit(0.4, "native"))

@
\item The functions \code{convertX},
\code{convertY}, \code{convertWidth}, \code{convertHeight}
  are used to convert from one coordinate system to another.
Again, it is important whether the conversion is for a location or
for a dimension.
The following code
demonstrates some results from these functions based on a similar
situation to that in the preceding diagram:

<<fig=FALSE>>=
pushViewport(viewport(yscale=c(-0.6, 1.3)))
# Unexpected results?
convertY(unit(1,'native'), "native")
convertY(unit(-.4,'native'), "native")
convertY(unit(1,'native')+unit(-.4,'native'), "native")
convertY(unit(1,'native')-unit(.4,'native'), "native")
# Expected results
convertHeight(unit(1,'native'), "native")
convertHeight(unit(-.4,'native'), "native")
convertHeight(unit(1,'native')+unit(-.4,'native'), "native")
convertHeight(unit(1,'native')-unit(.4,'native'), "native")
popViewport()

@
\end{enumerate}

% Start a new page
% Not echoed, not evaluated
% ONLY here for checkVignettes so that all output doesn't
% end up on one enormous page

<<eval=FALSE, echo=FALSE>>=
grid.newpage()

@
\end{document}
