# Is there a curved EdgeShapeFunction that has arrowheads?

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"]


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

• 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. Commented May 3, 2019 at 12:06
• 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. Commented May 3, 2019 at 12:43
• TracePrint + MakeBoxes on a graph with GraphLayout -> "GravityEmbedding" shows it's using "CurvedEdge". Commented May 3, 2019 at 14:26
• @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 Commented May 3, 2019 at 16:02
• 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"]? Commented May 3, 2019 at 16:03

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"]


• For reference, this solution works only in M12.0 or later. Commented Jul 15, 2022 at 11:07