I inherited a function written either for an older version of R or SPlus
to draw a brace, "{", in a graph. It uses par("uin") to
determine the
scaling of the
quarter circles that make up segments of the brace, but that setting
doesn't
exist in current R.
I'm guessing that, in the function below, ux, uy can be defined from
par("usr") and par("pin"), but maybe someone remembers what
par("uin")
was supposed to refer to.
brace <- function (x1 = 0, y1 = 0, x2 = 0, y2 = 1, right = TRUE, rad = 0.2)
{
uin <- par("uin")
ux <- uin[1]
uy <- uin[2]
dx <- x2 - x1
dy <- y2 - y1
alpha <- atan(ux * dx, uy * dy)
scale <- sqrt((ux * dx)^2 + (uy * dy)^2)
if (scale > 5 * rad)
rad <- rad/scale
qcirc <- cbind(cos((0:10) * pi/20), sin((0:10) * pi/20))
qcircr <- cbind(cos((10:0) * pi/20), sin((10:0) * pi/20))
rot <- function(theta) t(cbind(c(cos(theta), sin(theta)),
c(-sin(theta), cos(theta))))
seg1 <- t(t(rad * qcirc %*% rot(-pi/2)) + c(0, rad))
seg4 <- t(t(rad * qcirc) + c(0, 1 - rad))
seg3 <- t(t((rad * qcircr) %*% rot(pi)) + c(2 * rad, 0.5 +
rad))
seg2 <- t(t((rad * qcircr) %*% rot(pi/2)) + c(2 * rad, 0.5 -
rad))
bra <- rbind(seg1, seg2, seg3, seg4)
if (!right)
bra <- bra %*% diag(c(-1, 1))
bra <- scale * bra %*% rot(-alpha)
bra <- bra %*% diag(c(1/ux, 1/uy))
bra <- t(t(bra) + c(x1, y1))
bra
}
--
Michael Friendly Email: friendly AT yorku DOT ca
Professor, Psychology Dept.
York University Voice: 416 736-5115 x66249 Fax: 416 736-5814
4700 Keele Street Web: http://www.datavis.ca
Toronto, ONT M3J 1P3 CANADA
http://tinyurl.com/34fhcvg Am 19.07.2010 17:20, schrieb Michael Friendly:> I inherited a function written either for an older version of R or SPlus > to draw a brace, "{", in a graph. It uses par("uin") to determine the > scaling of the > quarter circles that make up segments of the brace, but that setting > doesn't > exist in current R. > I'm guessing that, in the function below, ux, uy can be defined from > par("usr") and par("pin"), but maybe someone remembers what par("uin") > was supposed to refer to. > > brace <- function (x1 = 0, y1 = 0, x2 = 0, y2 = 1, right = TRUE, rad > 0.2) > { > uin <- par("uin") > ux <- uin[1] > uy <- uin[2] > dx <- x2 - x1 > dy <- y2 - y1 > alpha <- atan(ux * dx, uy * dy) > scale <- sqrt((ux * dx)^2 + (uy * dy)^2) > if (scale > 5 * rad) > rad <- rad/scale > qcirc <- cbind(cos((0:10) * pi/20), sin((0:10) * pi/20)) > qcircr <- cbind(cos((10:0) * pi/20), sin((10:0) * pi/20)) > rot <- function(theta) t(cbind(c(cos(theta), sin(theta)), > c(-sin(theta), cos(theta)))) > seg1 <- t(t(rad * qcirc %*% rot(-pi/2)) + c(0, rad)) > seg4 <- t(t(rad * qcirc) + c(0, 1 - rad)) > seg3 <- t(t((rad * qcircr) %*% rot(pi)) + c(2 * rad, 0.5 + > rad)) > seg2 <- t(t((rad * qcircr) %*% rot(pi/2)) + c(2 * rad, 0.5 - > rad)) > bra <- rbind(seg1, seg2, seg3, seg4) > if (!right) > bra <- bra %*% diag(c(-1, 1)) > bra <- scale * bra %*% rot(-alpha) > bra <- bra %*% diag(c(1/ux, 1/uy)) > bra <- t(t(bra) + c(x1, y1)) > bra > }
My question is probably stupid but why don't you use the text() function?
plot(1:10,type="n")
text(4,4,"{")
text(6,6,"{",cex=3) # if you want it bigger
Alain
On 19-Jul-10 17:20, Michael Friendly wrote:> I inherited a function written either for an older version of R or SPlus
> to draw a brace, "{", in a graph. It uses par("uin")
to determine the
> scaling of the
> quarter circles that make up segments of the brace, but that setting
> doesn't
> exist in current R.
> I'm guessing that, in the function below, ux, uy can be defined from
> par("usr") and par("pin"), but maybe someone remembers
what par("uin")
> was supposed to refer to.
>
> brace <- function (x1 = 0, y1 = 0, x2 = 0, y2 = 1, right = TRUE, rad =
> 0.2)
> {
> uin <- par("uin")
> ux <- uin[1]
> uy <- uin[2]
> dx <- x2 - x1
> dy <- y2 - y1
> alpha <- atan(ux * dx, uy * dy)
> scale <- sqrt((ux * dx)^2 + (uy * dy)^2)
> if (scale > 5 * rad)
> rad <- rad/scale
> qcirc <- cbind(cos((0:10) * pi/20), sin((0:10) * pi/20))
> qcircr <- cbind(cos((10:0) * pi/20), sin((10:0) * pi/20))
> rot <- function(theta) t(cbind(c(cos(theta), sin(theta)),
> c(-sin(theta), cos(theta))))
> seg1 <- t(t(rad * qcirc %*% rot(-pi/2)) + c(0, rad))
> seg4 <- t(t(rad * qcirc) + c(0, 1 - rad))
> seg3 <- t(t((rad * qcircr) %*% rot(pi)) + c(2 * rad, 0.5 +
> rad))
> seg2 <- t(t((rad * qcircr) %*% rot(pi/2)) + c(2 * rad, 0.5 -
> rad))
> bra <- rbind(seg1, seg2, seg3, seg4)
> if (!right)
> bra <- bra %*% diag(c(-1, 1))
> bra <- scale * bra %*% rot(-alpha)
> bra <- bra %*% diag(c(1/ux, 1/uy))
> bra <- t(t(bra) + c(x1, y1))
> bra
> }
>
--
Alain Guillet
Statistician and Computer Scientist
SMCS - IMMAQ - Universit? catholique de Louvain
Bureau c.316
Voie du Roman Pays, 20
B-1348 Louvain-la-Neuve
Belgium
tel: +32 10 47 30 50
>From the S+8.1 documentation graphics.pdf* uin *information numeric inches per *usr *unit *c(0.73, 0.05) * [[alternative HTML version deleted]]
Michael,
I have a very old version of some brace functions somewhere.
I never did combine them into a single function, so there's
one each for left/right/up/down braces. (I used them in
teaching regression to show resids and formulae.)
If you're interested, I'll dig 'em up and send them.
Otherwise, I think you can make your inherited code work
with something like
Usr <- par('usr')
Pin <- par('pin')
dux <- Usr[2] - Usr[1]
duy <- Usr[4] - Usr[3]
uin <- c(dux,duy)/Pin
to replace
uin <- par("uin")
But you'll also have to fiddle with atan()
-Peter Ehlers
On 2010-07-19 9:20, Michael Friendly wrote:> I inherited a function written either for an older version of R or SPlus
> to draw a brace, "{", in a graph. It uses par("uin") to
determine the
> scaling of the
> quarter circles that make up segments of the brace, but that setting
> doesn't
> exist in current R.
> I'm guessing that, in the function below, ux, uy can be defined from
> par("usr") and par("pin"), but maybe someone remembers
what par("uin")
> was supposed to refer to.
>
> brace <- function (x1 = 0, y1 = 0, x2 = 0, y2 = 1, right = TRUE, rad =
0.2)
> {
> uin <- par("uin")
> ux <- uin[1]
> uy <- uin[2]
> dx <- x2 - x1
> dy <- y2 - y1
> alpha <- atan(ux * dx, uy * dy)
> scale <- sqrt((ux * dx)^2 + (uy * dy)^2)
> if (scale > 5 * rad)
> rad <- rad/scale
> qcirc <- cbind(cos((0:10) * pi/20), sin((0:10) * pi/20))
> qcircr <- cbind(cos((10:0) * pi/20), sin((10:0) * pi/20))
> rot <- function(theta) t(cbind(c(cos(theta), sin(theta)),
> c(-sin(theta), cos(theta))))
> seg1 <- t(t(rad * qcirc %*% rot(-pi/2)) + c(0, rad))
> seg4 <- t(t(rad * qcirc) + c(0, 1 - rad))
> seg3 <- t(t((rad * qcircr) %*% rot(pi)) + c(2 * rad, 0.5 +
> rad))
> seg2 <- t(t((rad * qcircr) %*% rot(pi/2)) + c(2 * rad, 0.5 -
> rad))
> bra <- rbind(seg1, seg2, seg3, seg4)
> if (!right)
> bra <- bra %*% diag(c(-1, 1))
> bra <- scale * bra %*% rot(-alpha)
> bra <- bra %*% diag(c(1/ux, 1/uy))
> bra <- t(t(bra) + c(x1, y1))
> bra
> }
>
Thanks, Peter This more or less corresponds to the solution I came to, modulo xyinch() and atan2(x,y) = atan(x/y). It is mostly intended as a replacement for arrows() in statistical diagrams/plots where you want to show a given range in a plot precisely without additional boundary lines. It works reasonably well for horizontal and vertical braces, but in other cases depends on the aspect ratio of the plot. The internal calculation of scale is a kludge to try to adjust for that. -Michael Peter Ehlers wrote:> The following works for me: > > brace <- function (x1 = 0, y1 = 0, x2 = 0, y2 = 1, right = TRUE, rad = > 0.2) > { > uin<-xyinch() # thanks to Paul's comment; I had forgotten xinch() > ux <- uin[1] > uy <- uin[2] > dx <- x2 - x1 > dy <- y2 - y1 > alpha <- atan2(ux * dx, uy * dy) # in R, we need atan2() > scale <- sqrt((ux * dx)^2 + (uy * dy)^2) > if (scale > 5 * rad) > rad <- rad/scale > qcirc <- cbind(cos((0:10) * pi/20), sin((0:10) * pi/20)) > qcircr <- cbind(cos((10:0) * pi/20), sin((10:0) * pi/20)) > rot <- function(theta) t(cbind(c(cos(theta), sin(theta)), > c(-sin(theta), cos(theta)))) > seg1 <- t(t(rad * qcirc %*% rot(-pi/2)) + c(0, rad)) > seg4 <- t(t(rad * qcirc) + c(0, 1 - rad)) > seg3 <- t(t((rad * qcircr) %*% rot(pi)) + c(2 * rad, 0.5 + > rad)) > seg2 <- t(t((rad * qcircr) %*% rot(pi/2)) + c(2 * rad, 0.5 - > rad)) > bra <- rbind(seg1, seg2, seg3, seg4) > if (!right) > bra <- bra %*% diag(c(-1, 1)) > bra <- scale * bra %*% rot(-alpha) > bra <- bra %*% diag(c(1/ux, 1/uy)) > bra <- t(t(bra) + c(x1, y1)) > bra > } > > plot(...) > lines(brace(...)) > > For non-vertical/horizontal braces, the arcs at the ends > don't seem quite right to me. Also, it would seem useful > to be able to just define the cusp and the width of a > brace. I might have a look at that over the weekend. > > -Peter Ehlers > > > On 2010-07-19 9:20, Michael Friendly wrote: >> I inherited a function written either for an older version of R or SPlus >> to draw a brace, "{", in a graph. It uses par("uin") to determine the >> scaling of the >> quarter circles that make up segments of the brace, but that setting >> doesn't >> exist in current R. >> I'm guessing that, in the function below, ux, uy can be defined from >> par("usr") and par("pin"), but maybe someone remembers what par("uin") >> was supposed to refer to. >> >> brace <- function (x1 = 0, y1 = 0, x2 = 0, y2 = 1, right = TRUE, rad >> = 0.2) >> { >> > [....]-- Michael Friendly Email: friendly AT yorku DOT ca Professor, Psychology Dept. York University Voice: 416 736-5115 x66249 Fax: 416 736-5814 4700 Keele Street Web: http://www.datavis.ca Toronto, ONT M3J 1P3 CANADA