How can I combine edges in an ortho graph? - graphviz

I'm using splines=ortho and I was hoping for the edges to collapse together. To illustrate, I want to accomplish this:
I tried this:
digraph G {
splines=ortho;
edge [dir=none];
node [shape=diamond, label="", height=0.1, width=0.1];
start -> a [weight=10];
start -> b;
start -> c;
start -> d;
start -> e;
}
But it ends up looking like this:
Any clue on how I can make the edges overlap each other?

You need to create empty nodes on the same level as start and connect to them first, then draw the rest of your graph:
digraph G
{
node[ shape = point, label="", height=0, width=0 ] 01 02 03 04;
node[ shape=diamond, label="", height=0.1, width=0.1 ];
{ rank = same; start 01 02 03 04; }
edge [dir=none];
start -> 01 -> 02 -> 03 -> 04[ minlen = 2 ];
start -> a [weight=2];
01 -> b;
02 -> c;
03 -> d;
04 -> e;
}
yields

Related

Align nodes of subgraph with another subgraph nodes

How do I align nodes with each other between subgraphs?
In the example, I would like all the 0 nodes aligned vertically as well as the 1, 2, 3 and 4 nodes. It would be good if all the right edges of subgraphs were extended as necessary to align too.
digraph AlignWhenMissing {
rankdir=LR;
node [shape=box]
subgraph clusterA {label = "A Shift a4 along (no a3)";
a0 -> a1;
a1 -> a2;
a2 -> a4;
}
subgraph clusterB {label = "B Shift b2 above a2";
b0 -> b2;
b2 -> b3;
}
subgraph clusterC {label = "C Shift c3 above b3";
c0 -> c3;
}
A -> a0[lhead=clusterA];
B -> b0[lhead=clusterB];
C -> c0[lhead=clusterC];
a0 -> b0[constraint=false];
b3 -> c3[constraint=false];
a2 -> b2[constraint=false];
}
The minlen attribute (https://graphviz.org/docs/attrs/minlen/) applies to edges to lengthen them (i.e. to push them "out" by N ranks).
Then added invisible nodes and edges to increase cluster dimension.
digraph AlignWhenMissing {
rankdir=LR;
node [shape=box]
subgraph clusterA {label = "A Shift a4 along (no a3)";
a0 -> a1;
a1 -> a2;
a2 -> a4 [minlen=2];
}
subgraph clusterB {label = "B Shift b2 above a2";
b0 -> b2 [minlen=2]
b2 -> b3;
b4 [style=invis]
b3 -> b4 [style=invis]
}
subgraph clusterC {label = "C Shift c3 above b3";
c0 -> c3 [minlen=3];
c4 [style=invis]
c3 -> c4 [style=invis]
}
A -> a0[lhead=clusterA];
B -> b0[lhead=clusterB];
C -> c0[lhead=clusterC];
a0 -> b0[constraint=false];
b3 -> c3[constraint=false];
a2 -> b2[constraint=false];
}
Giving:

When rankdir is LR, why are the nodes in the same rank ordered bottom to top instead of top to bottom?

In the following example, the nodes in the subgraphs are ordered from the bottom to the top instead of from top to bottom. How can that be reversed, so that the start is top-left and the nodes in the subgraphs are ordered from top to bottom (A1-A4 and B1-B4)?
digraph ab
{
rankdir=LR
splines=ortho
ranksep=1
node[shape = record]
subgraph cluster_0
{
label="A"
{
rank = "same"
state0_anchor [label="", style=invis, width=0]
state0_step0 [label="A1"]
state0_step1 [label="A2"]
state0_step2 [label="A3"]
state0_step3 [label="A4"]
}
state0_anchor->state0_step0[style = invis]
state0_step0 -> state0_step1 -> state0_step2 -> state0_step3
}
state0_step3 -> state0_step0 [constraint=false]
state0_step3 -> state1_step0 [constraint=false]
subgraph cluster_state1
{
label="B"
{
rank = "same"
state1_anchor [label="", style=invis, width=0, height=0]
state1_step0 [label="B1"]
state1_step1 [label="B2"]
state1_step2 [label="B3"]
state1_step3 [label="B4"]
}
state1_anchor->state1_step0[style = invis]
state1_step0 -> state1_step1 -> state1_step2 -> state1_step3
}
state1_step3 -> state0_step0 [constraint=false]
state0_anchor -> state1_anchor[style = invis]
start -> state0_step0
}
In your example, when direction of the edges within the subgraphs are reversed, the nodes will be ordered the way you'd like. Something like this:
state0_step3 -> state0_step2 [dir=rev]
state0_step2 -> state0_step1 [dir=rev]
state0_step1 -> state0_step0 [dir=rev]
state0_step0 -> state0_anchor [style = invis]
The same for state1-nodes.
Details about transformations when going LR can be found in https://stackoverflow.com/a/9592856/63733

Maintain horizontal ordering of nodes in Graphviz

I have the following the dot file contents:
digraph G {
start -> {a0, b0} -> end;
start -> c0 -> c1 -> c2 -> end;
start -> d0 -> d1 -> d2 -> end;
start -> {e0, f0} -> end;
subgraph cluster_test {
{
rank = same;
a0; b0; c0; d0; e0; f0;
}
{
rank = same;
c1; d1;
}
{
rank = same;
c2; d2;
}
}
}
The resulting graph is as follows:
What I want is for the ordering of level 0 nodes to be maintained, i.e, I want a0, b0 to come before c0, d0 in the horizontal direction.
How do I achieve this?
Empty nodes, edges with weight and explicit ordering of the top row in the cluster helps. See code below with annotations:
digraph so
{
// we define all nodes in the beginning, before edges and clusters
// may not be essential but I think it's good practice
start
a0 b0 c0 d0 e0 f0
c1 d1
c2 d2
end
// we define "empty" nodes that can be used to route the edges
node[ shape = point, height = 0 ];
ax bx ex fx
subgraph cluster_test
{
// we need to keep explicit order of the top nodes in the cluster
{ rank = same; a0 -> b0 -> c0 -> d0 -> e0 -> f0[ style = invis ] }
// the original layout in the cluster, empty nodes added at the bottom
{ rank = same; c1 d1 }
{ rank = same; ax bx c2 d2 ex fx }
c0 -> c1 -> c2;
d0 -> d1 -> d2;
// routing through invisible nodes keeps the position of all other nodes
// edges with no arrowheads, strong weight to keep it vertical
edge[ dir = none, weight = 10 ]
a0 -> ax;
b0 -> bx;
e0 -> ex;
f0 -> fx;
}
// connecting to the start and end node, normal edges again
edge[ weight = 1, dir = forw ];
start -> { a0 b0 c0 d0 e0 f0 }
{ ax bx c2 d2 ex fx } -> end;
}
which gives you

How to make a subgraph visible?

In the graph below the two subgraphs are not visible, but instead all nodes seem to be placed randomly. How can I create the visible subgraphs, like one box with my PlayerChars inside, and the other with the NonPlayerChars inside?
digraph "All Characters" {
subgraph PlayerChars {
label = "Player Characters";
node [style=filled,color=yellow];
Char1 -> Char2 [ label = "is sister of" ];
Char1 -> Char2 [ label = "is brother of" ];
label = "PCs";
}
subgraph NonPlayerChars {
label = "Non-Player Characters";
Person1 -> Char2 [label="hates"];
Char2 -> Person1 [label="is indifferent"];
Person2 -> Char2 [label="stole from"];
Person1 -> Person2 [label="is father of"];
Person2 -> Person1 [label="is daughter of"];
Char1 -> Person2 [label="is in love with"];
Person2 -> Char1 [label="is annoyed by"];
}
}
What you are looking for is called a "cluster" in Graphviz. Use the special subgraph names cluster_ to draw the subgraphs in rectangular regions. E.g. from http://www.graphviz.org/Gallery/directed/cluster.html
digraph G {
subgraph cluster_0 {
style=filled;
color=lightgrey;
node [style=filled,color=white];
a0 -> a1 -> a2 -> a3;
label = "process #1";
}
subgraph cluster_1 {
node [style=filled];
b0 -> b1 -> b2 -> b3;
label = "process #2";
color=blue
}
start -> a0;
start -> b0;
a1 -> b3;
b2 -> a3;
a3 -> a0;
a3 -> end;
b3 -> end;
start [shape=Mdiamond];
end [shape=Msquare];
}

subgraph cluster ranking in dot

I'm trying to use graphviz on media wiki as a documentation tool for software.
First, I documented some class relationships which worked well. Everything was ranked vertically as expected.
But, then, some of our modules are dlls, which I wanted to seperate into a box. When I added the nodes to a cluster, they got edged, but clusters seem to have a LR ranking rule. Or being added to a cluster broke the TB ranking of the nodes as the cluster now appears on the side of the graph.
This graph represents what I am trying to do: at the moment, cluster1 and cluster2 appear to the right of cluster0.
I want/need them to appear below.
<graphviz>
digraph d {
subgraph cluster0 {
A -> {B1 B2}
B2 -> {C1 C2 C3}
C1 -> D;
}
subgraph cluster1 {
C2 -> dll1_A;
dll1_A -> B1;
}
subgraph cluster2 {
C3 -> dll2_A;
}
dll1_A -> dll2_A;
}
</graphviz>
The layout is an attempt by Dot to minimise the overall height.
One reason for the more compact than required layout is the use of the edge that goes in the reverse direction from dll1_a to B1. It tries to pull the cluster as close back to the destination node as possible. To avoid this edge affecting the graph, either relax the constraint on the upwards edges as shown, or draw the edge in the forward direction and use the dir attribute to reverse the arrow.
This will help with many layouts but it alone is not sufficient to fix the example given. To prevent Dot from maintaining the compact layout it prefers you can add a minlen attribute to edges that should remain (near) vertical. This may be difficult to calculate in general but is practical for manually tuned layouts.
digraph d {
subgraph cluster0 {
A -> {B1 B2}
B2 -> {C1 C2 C3}
C1 -> D;
}
subgraph cluster1 {
C2 -> dll1_A [minlen = 2];
dll1_A -> B1 [constraint = false];
/* B1 -> dll1_A [dir = back]; */
}
subgraph cluster2 {
C3 -> dll2_A;
}
dll1_A -> dll2_A;
}
My experience shows that constraint=false commonly gives unnecessarily convoluted edges. It seems that weight=0 gives better results:
digraph d {
subgraph cluster0 {
A -> {B1 B2}
B2 -> {C1 C2 C3}
C1 -> D;
}
subgraph cluster1 {
C2 -> dll1_A [minlen = 2];
dll1_A -> B1 [weight = 0];
/* B1 -> dll1_A [dir = back]; */
}
subgraph cluster2 {
C3 -> dll2_A;
}
dll1_A -> dll2_A;
}
This will produce the graph you are looking for:
digraph d {
subgraph cluster0 {
A -> {B1 B2}
B2 -> {C1 C2 C3}
C1 -> D;
}
subgraph {
rankdir="TB"
subgraph cluster1 {
C2 -> dll1_A;
dll1_A -> B1;
}
subgraph cluster2 {
C3 -> dll2_A;
}
}
dll1_A -> dll2_A;
}
What this does is creat a subgraph that is used only for layout purposes to provide the top to bottom ordering that you desire.

Resources