5
$\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$
  • $\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 May 3 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 May 3 at 12:43
  • 1
    $\begingroup$ TracePrint + MakeBoxes on a graph with GraphLayout -> "GravityEmbedding" shows it's using "CurvedEdge". $\endgroup$ – Chip Hurst May 3 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 May 3 at 16:02
  • $\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$ – Chip Hurst May 3 at 16:03
5
$\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$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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