I am somewhat surprised that this has never caught my attention (I guess I've never drawn much with round line ends until today).
When drawing a segment with round line end, this is "of course" added as additional grob element, but it's adding "value" to the graphical representation by extending beyond the given values. How could I change this?
I think one would need re-calculate the original values so that it will be reaching the correct value when adding the round end, but this would require this calculation at draw time, i.e. within the grob function. And I'm very bad with grobs. Help would be appreciated.
library(ggplot2)
df <- data.frame(x = 0, xend = 1, y = 0, yend = 0)
ggplot(df, aes(x, y)) +
geom_vline(xintercept = c(0, 1), lty = 2) +
geom_segment(aes(xend = xend, yend = yend),
linewidth = 6, alpha = .5,
lineend = "round") +
labs(title = "NOT an accurate representation of the data",
caption = "The line extends beyond the given values")
Created on 2023-11-16 with reprex v2.0.2
This is deceptively difficult. The most foolproof way of doing it is to define a new
makeContent
method for asegmentsGrob
, which in turn means defining a new grob class, which has to be called from a newGeom
class, which requires a newgeom
. The maths itself isn't too difficult, but there's a lot of boilerplate involved.First, let us define the function that actually does the maths on the modified
segmentsGrob
, which will just be asegmentsGrob
with a different S3 class name - we'll call it"roundseg"
:Now we define a new
Geom
class - we'll call itGeomRoundseg
. It's almost identical toGeomSegment
, except itsdraw_panel
member is redefined to change thesegmentsGrob
to a different class, so that the above function is called whenever the grob is drawn or the window resized:Finally, we need a
geom_roundseg
function that is almost an exact copy ofgeom_segment
, except itslineend
parameter is removed and it uses our new Geom object:Now we're done. When we call our plot, the tips of the rounded segment will be at the specified x, y co-ordinates:
If we rescale the window, the tips stay in place:
And changing the linewidth is catered for:
And this continues to work whatever the angle of our segment: