Cone Trees: map a graph onto geometric shape
To lay out a graph on a cone, you start by laying it out in a circular way. Then you add an appropriate "z coordinate" to each node position, proportionally to its distance form the centre.
This is done using the "RadialEmbedding"
GraphLayout
.
Example:
tree = Graph@EdgeList@KaryTree[2^6 - 1, 2]
The Graph@EdgeList@
part is to change the internal representation of this graph and work around some bugs ... otherwise some of the functions below (such as the Graph3D
line) would fail.
layout = SetProperty[tree, GraphLayout -> "RadialEmbedding"]
Should you need to set the root vertex for this layout, do so using GraphLayout -> {"RadialEmbedding", "RootVertex" -> 1}
.
You can see using Show[layout, Frame -> True, FrameTicks -> True]
that {0,0}
is not in the centre. We want it in the centre. So we subtract the coordinates of the root vertex from each vertex coordinate. In this case the root vertex happens to be the first one.
coord = GraphEmbedding[layout];
coord = # - First[coord] & /@ coord;
Now we can put it in 3D on a cone:
Graph3D[tree, VertexCoordinates -> ({#1, #2, -Norm[{#1, #2}]} & @@@ coord)]
The IGraph/M package also has a similar but not fully identical layout algorithm.
<<IGraphM`
layout = IGLayoutReingoldTilfordCircular[tree, "RootVertices" -> {1}]
coord = GraphEmbedding[layout]
This function always places the root vertex at {0,0}
.
You can construct graphs using Graph3D with proper layouts:
edges = EdgeList@KaryTree[2^6 - 1, 2];
Graph3D[edges,
GraphLayout -> {"RadialEmbedding", "LayerSizeFunction" -> (-# &)}]
Graph3D[edges, GraphLayout -> "BalloonEmbedding"]