14
$\begingroup$

The undocumented "CurvedArc" EdgeShapeFunction draws edges as curves (instead of straight lines). However, it does not draw arrowheads for directed graphs.

Is there a built-in EdgeShapeFunction specification that draws directed edges as curved arcs, with a consistent curve direction relative to the edge direction, and visible arrowheads?

I could certainly create my own edge shape function that does this. But this is such a frequently needed edge shape function that I am hoping that it is already built in, just not documented (just like "CurvedArc").


Example of a graph where this would be useful, and CurvedArc fails.

RelationGraph[MemberQ[{1, 2, 4}, Mod[#1 - #2, 7]] &, Range[0, 6],
 EdgeShapeFunction -> "CurvedArc"]

enter image description here

Note that this is a directed graph.

Edge shape function that would work better with this graph:

rot[{x_, y_}] := {-y, x}
arc = Function[{pts, edge},
  Module[{s = First[pts], t = Last[pts]},
   {Arrowheads[{{Automatic, 2/3}}], 
    Arrow@BezierCurve[{s, s + (t - s)/2 + 1/8 rot[t - s] , t}]}
   ]
  ]

All edge shape function specs should be listed by GraphElementData["EdgeShapeFunction"] but they aren't.

$\endgroup$
6
  • $\begingroup$ In v12, GraphLayout -> "GravityEmbedding" does this (despite a layout having no business of changing edge shapes...) I just don't know which edge shape spec it uses. $\endgroup$
    – Szabolcs
    Commented May 3, 2019 at 12:06
  • 1
    $\begingroup$ I went so far as to run strings on the kernel library, but unfortunately the edge shape functions aren't clustered near each other so it's too much effort to try and come up with a real list. If it helps, CurvedArc and CurvedEdge are the only two I could find that weren't in the list. $\endgroup$
    – Carl Lange
    Commented May 3, 2019 at 12:43
  • 1
    $\begingroup$ TracePrint + MakeBoxes on a graph with GraphLayout -> "GravityEmbedding" shows it's using "CurvedEdge". $\endgroup$
    – Greg Hurst
    Commented May 3, 2019 at 14:26
  • $\begingroup$ @ChipHurst In that case, there must be a sub-option to CurvedEdge that adds the arrowheads. I know I can do Show[g] /. bc_BezierCurve :> Arrow[bc] but that is ugly and makes a Graphics not a Graph $\endgroup$
    – Szabolcs
    Commented May 3, 2019 at 16:02
  • 2
    $\begingroup$ I might not be understanding the question correctly. Can't you just do RelationGraph[MemberQ[{1, 2, 4}, Mod[#1 - #2, 7]] &, Range[0, 6], EdgeShapeFunction -> "CurvedEdge"]? $\endgroup$
    – Greg Hurst
    Commented May 3, 2019 at 16:03

1 Answer 1

15
$\begingroup$

We can check if Graph calls GraphElementData during the drawing stage:

With[{g = Graph[{1 -> 2}, GraphLayout -> "GravityEmbedding"]},
 TracePrint[MakeBoxes[g], _GraphElementData, TraceInternal -> True]
];
GraphElementData[CurvedEdge]

   GraphElementData[{CurvedEdge,0.0183437}]

And so:

RelationGraph[MemberQ[{1, 2, 4}, Mod[RandomChoice[{Abs, Identity}][#1 - #2], 7]] &, 
  Range[0, 6], EdgeShapeFunction -> "CurvedEdge"]

$\endgroup$
1
  • 2
    $\begingroup$ For reference, this solution works only in M12.0 or later. $\endgroup$
    – Szabolcs
    Commented Jul 15, 2022 at 11:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.