Providing custom bezier control points
krassowski opened this issue · comments
The documentation suggests that geom_edge_*2
functions allow customisation of the control points:
The version postfixed with a "2" uses the "long" edge format (see get_edges()) and makes it possible to interpolate node parameter between the start and end node along the edge.
It wasted a bit too much of my time to understand that in fact it does not allow to specify the control points manually but barely computes them arbitrarily. The documentation is of course technically right - this is what interpolation means (kind of because technically bezier curve is an interpolation too), but this was quite surprising.
So currently get_edges()
always returns 2 rows per edge, white StatEdgeArc2
and remove_loop2
assume that two rows are present, in particular by selecting every other row as from/to vertices and using them to compute the arcs:
Lines 176 to 178 in febab71
If I wanted to have the full control I could switch to ggforce::geom_bezier2
but this means loosing out on all the goodies that GeomEdgePath
provides. I wish I could just specify stat=ggforce::StatBezier2
but it seems unsupported in geom_edge_*2
.
Any thoughts about this?
For anyone interested, geom_edge_manual_arc
defined as below works well, but it's a lot of boilerplate for everyday use!
geom_edge_manual_arc <- function(
mapping = NULL, data = get_edges('long'), # you probably do not want get_edges here (pass your data with control points instead)
position = 'identity', arrow = NULL,
n = 100, fold = FALSE, lineend = 'butt',
linejoin = 'round', linemitre = 1,
label_colour = 'black', label_alpha = 1,
label_parse = FALSE, check_overlap = FALSE,
angle_calc = 'rot', force_flip = TRUE,
label_dodge = NULL, label_push = NULL,
show.legend = NA, ...
) {
mapping <- ggraph:::complete_edge_aes(mapping)
mapping <- ggraph:::aes_intersect(mapping, aes(
x = x, y = y, group = edge.id,
circular = circular
))
layer(
data = data, mapping = mapping, stat = ggforce::StatBezier2,
geom = ggraph::GeomEdgePath, position = position, show.legend = show.legend,
inherit.aes = FALSE,
params = ggraph:::expand_edge_aes(
list(
arrow = arrow, lineend = lineend, linejoin = linejoin,
linemitre = linemitre, na.rm = FALSE, n = n,
interpolate = TRUE, fold = fold,
label_colour = label_colour, label_alpha = label_alpha,
label_parse = label_parse, check_overlap = check_overlap,
angle_calc = angle_calc, force_flip = force_flip,
label_dodge = label_dodge, label_push = label_push, ...
)
)
)
}
yeah, you'd need a whole new edge geom for this. Arc was never intended as a general bezier geom for edges (in the same way that diagonal is a "fixed" bezier geom)
Such a geom would be quite niche so I'm afraid I can't prioritise that at the moment