Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Providing custom bezier control points #349

Open
krassowski opened this issue Aug 6, 2023 · 2 comments
Open

Providing custom bezier control points #349

krassowski opened this issue Aug 6, 2023 · 2 comments

Comments

@krassowski
Copy link

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:

ggraph/R/geom_edge_arc.R

Lines 176 to 178 in febab71

data2 <- data[c(FALSE, TRUE), ]
data <- data[c(TRUE, FALSE), ]
create_arc(data, data2, params)

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?

@krassowski
Copy link
Author

krassowski commented Aug 8, 2023

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, ...
      )
    )
  )
}

@thomasp85
Copy link
Owner

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants