> I'm wondering whether it wouldn't be fairly doable to create a new
> geom to mimic the type='b' of base graphics. As far as I understand
> from main/plot.c it's only a matter of chopping up the segments to
> make an exclusion zone around the points.
Here's a start:
barbedGrob <- function(x = stats::runif(10), y = stats::runif(10),
size=1, shape=1,
colour="red", fill="blue", alpha=0.8,
linetype=1, lex=1){
start <- 1
end <- length(x)
grob.lines <- segmentsGrob(
x[-end], y[-end], x[-start], y[-start],
default.units="native",
gp = gpar(
col = alpha(colour, alpha),
lex = lex, lty = linetype, lineend = "butt"
)
)
grob.points <- pointsGrob(x, y, pch=shape, size=size*unit(1, "char"),
gp = gpar(
col = alpha(colour, alpha),
fill = alpha(fill, alpha),
lex = lex, linejoin = "mitre"
)
)
gTree(children = gList(grob.lines,grob.points))
}
g <- barbedGrob(shape=21, size=3, fill="blue", lex=2)
pushViewport(vp=viewport(width=1, height=1))
grid.draw(g)
Now, the fun part will be to chop the segments...
x <- c(-0.2, 0.8) # only dealing with one segment so far
y <- c(0.2, 0.5) # (Any takers to adapt the code for any number of points?)
pushViewport(vp=viewport(width=1, height=1,
xscale = c(-1, 1), yscale = c(-1, 1)))
grid.points(x = x,
y = y,
pch = 21, size = unit(1, "char"),
default.units = "native", name = NULL,
gp = gpar(col="red", fill=alpha("green", 0.5)), draw = TRUE)
dx <- diff(x)
dy <- diff(y)
length <- sqrt(dx^2 + dy^2)
exclusion <- convertX(unit(1.5, "char"), "npc", TRUE) # in real world,
needs to be a vector for each point can have a different size
scaling <- exclusion / length
# left and right don't mean much but, hey, one needs directions
x.left <- scaling * dx + x[1]
y.left <- scaling * dy + y[1]
x.right <- x[2] - scaling * dx
y.right <- y[2] - scaling * dy
grid.segments(x0 = x.left, y0 = y.left,
x1 = x.right, y1=y.right,
default.units = "native", name = NULL,
gp = gpar(col="blue", lex=4), draw = TRUE)
Let me know what you think,
baptiste
--
As for your request of setting the linewidth, I've tested a minor
change to geom_point() that I renamed geom_point2. The only change is
the addition of the gpar argument lex. Seems to work for me. (this
one, you'll need the svn version as I just uploaded it).

Best,
baptiste
barbedGrob <- function(x = stats::runif(10),
y = stats::runif(10),
size=abs(rnorm(10, mean=1)), shape=21,
colour="red", fill="blue", alpha=0.8,
linetype=1, lex=2){
dx <- diff(x)
dy <- diff(y)
new.x <- rep(x, each=2)[-c(1, 2*length(x))]
new.y <- rep(y, each=2)[-c(1, 2*length(y))]
new.size <- rep(size, each=2)[-c(1, 2*length(size))]
length <- sqrt(dx^2 + dy^2)
exclusion <- 0.5*convertX(unit(new.size, "char"), "npc", TRUE)
scaling <- exclusion / rep(length, each=2)
start <- seq(1, by=2, length(new.x))
end <- seq(2, by=2, length(new.x))
x.start <- scaling[start] * dx[(start+1)/2] + new.x[start]
y.start <- scaling[start] * dy[(start+1)/2] + new.y[start]
x.end <- new.x[end] - scaling[end] * dx[end/2]
y.end <- new.y[end] - scaling[end] * dy[end/2]
grob.lines <- segmentsGrob(
x0 = x.start, y0 = y.start,
x1 = x.end, y1=y.end,
default.units="native",
gp = gpar(
col = alpha(colour, alpha),
lex = lex, lty = linetype, lineend = "butt"
)
)
grob.points <- pointsGrob(x, y, pch=shape, size=unit(size, "char"),
gp = gpar(
col = alpha(colour, alpha),
fill = alpha(fill, alpha),
lex = lex, linejoin = "mitre"
)
)
gTree(children = gList(grob.lines,grob.points))
}
barbedGrob() -> g
pushViewport(vp=viewport(width=1, height=1))
grid.draw(g)
On Thu, Jun 4, 2009 at 12:03 AM, Winston Chang <win...@stdout.org> wrote:
> Thanks for adding this! 'lex' works well. Comments:
> - Legends don't draw with the new linewidth.
I noticed this too, but I couldn't pinpoint the origin of this issue.
I'm afraid that's as far as my little experiments have taught me about
ggplot2.
> - It appears to use different units than 'size' does for line
thickness and
> point diameter. For example, a line with size=2 looks about the same as a
> point with lex=5. In my opinion, it would be good to use the same units,
> even if that means that the default for lex will be a small
non-integer. If
> they're in the same units, then it will be simpler to make graphs with
> consistent line and point outline widths.
agreed -- but units are a somewhat iffy business for me. I think I've
got it sorted now but I'll have to check.
> - Perhaps lex isn't the best name? The other aesthetic names in
ggplot2 use
> normal language.
>
I agree, but I have a problem with the name 'size' when used for the
line thickness of some geoms. I'm still not sure adding a scale for this
parameter made much sense in the first place.
>
> A final suggestion for Hadley - it would be great if this (and some of
> Baptiste's other additions) could be added to ggplot2 proper at some
point.
>
well, I won't reply for Hadley but IMHO any such experimental feature
should probably be considered a bit like community packages vs. base R:
any proposed 'improvement' should first meet strong criteria before
being added to the main package,
- high standards (aesthetics, conformity with other pieces of code,
legibility, examples, doc, efficiency, ... ), and reliability
- thorough testing (hence a necessary delay before adding new features)
- clear usefulness / improvement
None of the current code of ggextra meets any of these points when
checked against the standards of ggplot2. That situation will hopefully
improve with time (and contributors, should more people join in).
What's more, ggplot2 seems quite a big piece of code already (to me
anyway), so it's probably best not to add too many features too soon
(again, imho). That's part of the idea behind my placing this
'experimental add-ons' package on r-forge: make it as easy to test new
ideas as loading a small package.
It's very clear that Hadley listens to everybody's suggestions on this
list, so 'm sure he'll pick up any ideas worth exploring further.
Cheers,
baptiste
I think segments are fine. But it currently resembles more of a
ggplot2 function than a grid function:
* you should probably use pch, cex, etc, and use gpar
* you should be able to specify units for x and y (and have a
default.units parameter)
Hadley
The default R units are in points - multiply your unit in millimeters
by ggplot2:::.pt to convert to points.
> > - Perhaps lex isn't the best name? The other aesthetic names in
> ggplot2 use
> > normal language.
> >
>
> I agree, but I have a problem with the name 'size' when used for the
> line thickness of some geoms. I'm still not sure adding a scale for this
> parameter made much sense in the first place.
Size is currently used for line thickness of any thing with a fill,
and the size of points. One possibility would be to switch to using
linewidth for all line widths. Another would be to have size2 (for
secondary size) which for points would control the line width. Scales
do start to get complicated though, as you'll need to have a different
scale for the line thickness of the point and the size of the point.
Personally, I still prefer the technique of drawing two points in
different colours.
> > A final suggestion for Hadley - it would be great if this (and some of
> > Baptiste's other additions) could be added to ggplot2 proper at some
> point.
> >
>
> well, I won't reply for Hadley but IMHO any such experimental feature
> should probably be considered a bit like community packages vs. base R:
> any proposed 'improvement' should first meet strong criteria before
> being added to the main package,
I agree :) I definitely do pick up smaller features and include them,
but larger experimental features like this need more thought.
> What's more, ggplot2 seems quite a big piece of code already (to me
> anyway), so it's probably best not to add too many features too soon
> (again, imho). That's part of the idea behind my placing this
> 'experimental add-ons' package on r-forge: make it as easy to test new
> ideas as loading a small package.
This seems like the right model to me too.
Hadley
http://econum.umh.ac.be/rwiki/doku.php?id=tips:graphics-grid:linesandpointsgrob
I'm not clear why some gpar() such as pch and size are outside the gp
argument of pointsGrob(), while others are inside. Let me know if you
see some inconsistency in my new version.
Also, as far as a ggplot geom is concerned, it might be that the points
should remain a separate geom (another layer). That way, one can control
the appearance of lines and points separately (further, one could use
different geoms such as error bars, stars, ellipses, ...). I've added a
switch only.lines=TRUE for this purpose, which draws only the portions
of segments.
Best,
baptiste
Personally, I'd go for the first option --- linewidth for all line
widths. But that's not something I could do in this add-ons package as
it's a global change throughout ggplot2's code.
> Personally, I still prefer the technique of drawing two points in
> different colours.
>
I think a real type = 'b' geom has its value, especially when the data
is quite dense: you don't want the large white points to mask
surrounding lines or other layers unnecessarily. (not that I've ever
used type= 'b' myself, but I can see situations where it might be good).
Perhaps the new argument only.lines=TRUE could provide a better compromise.
Best,
baptiste
--
baptiste Auguié