Is something like the below diagram possible with Graphviz?
In particular, I’ve been unable to figure out how to:
- Place node labels outside of the node itself
- Connect node centers
- Display nodes as graphics (e.g. with center pin)
Thank you.
Is something like the below diagram possible with Graphviz?
In particular, I’ve been unable to figure out how to:
Thank you.
On a bet, I suppose it could be done, but no guarantees. (The edge routing is probably the hardest part):
neato -n
(pos | Graphviz) to have neato just route edges. (use splines=ortho
and edge [dir=both arrowhead=none arrowtail=none headclip=false tailclip=false]
to go center-to-center)splines=ortho
provides “nice” edge routing. (splines=ortho
can be disappointing)Before doing the above, look at the PIC language (PIC (markup language) - Wikipedia). I like the pikchr & dpic variants.
I came up with the diagram below that meets some of your requirements, using HTML-like labels and basic DOT processing.
A cluster is used to depict each Instrument.
Inside each cluster is a single node using the "plaintext"
shape. The label of the shape uses HTML-like labels to create a two-row table.
<td>
element (e.g. <td port="out2"
>) and uses a single character to depict the circle-enclosed dot, using the “Wingdings” font (on Windows) with a 30px pixel size.Now you can add edges which connect via the ports using a statement such as:
a:out1 -- c:a;
I was not able to replicate everything in your example. Unfortunately splines="ortho"
routing scrambles the result, and the HTML-like labels don’t support the headclip
, headport
, tailclip
, or tailport
attributes you would normally use to bring an edge to the center of a node.
That said, I hope this gets you closer to what you are trying to accomplish.
Here is the DOT source code used to create the graph above:
strict graph "main"
{
layout="dot";
rankdir="LR";
graph[ fontname="Arial Bold" labeljust="l" ];
node[ fontname="Wingdings" ];
subgraph "cluster_1" { label="Instrument A"
"a"[ shape="plaintext" label=<<table border="0" cellborder="0" cellspacing="0"><tr><td fixedsize="true" width="50">Out 1</td><td fixedsize="true" width="50">Out 2</td><td fixedsize="true" width="50">In 1</td></tr><tr><td port="out1"><font point-size="30">⦿</font></td><td port="out2"><font point-size="30">⦿</font></td><td port="in"><font point-size="30">⦿</font></td></tr></table>> ];
}
subgraph "cluster_2" { label="Instrument B"
"b"[ shape="plaintext" label=<<table border="0" cellborder="0" cellspacing="0"><tr><td fixedsize="true" width="50">Out 1</td><td fixedsize="true" width="50">Out 2</td><td fixedsize="true" width="50">In 1</td></tr><tr><td port="out1"><font point-size="30">⦿</font></td><td port="out2"><font point-size="30">⦿</font></td><td port="in"><font point-size="30">⦿</font></td></tr></table>> ];
}
subgraph "cluster_3" { label="Instrument C"
"c"[ shape="plaintext" label=<<table border="0" cellborder="0" cellspacing="0"><tr><td fixedsize="true" width="50">A</td><td fixedsize="true" width="50">B</td><td fixedsize="true" width="50">C</td><td fixedsize="true" width="50">D</td></tr><tr><td port="a"><font point-size="30">⦿</font></td><td port="b"><font point-size="30">⦿</font></td><td port="c"><font point-size="30">⦿</font></td><td port="d"><font point-size="30">⦿</font></td></tr></table>> ];
}
"a":"out1" -- "c":"a";
"b":"out1" -- "c":"b";
}
Another thing I just thought of is to use the ranksep
and nodesep
attributes to increase the spacing between the nodes.
The revised DOT source is as follows:
strict graph "main"
{
layout="dot";
rankdir="LR";
graph[ fontname="Arial Bold" labeljust="l" ];
node[ fontname="Wingdings" ];
nodesep="2" ranksep="2"
subgraph "cluster_1" { label="Instrument A"
"a"[ shape="plaintext" label=<<table border="0" cellborder="0" cellspacing="0"><tr><td fixedsize="true" width="50">Out 1</td><td fixedsize="true" width="50">Out 2</td><td fixedsize="true" width="50">In 1</td></tr><tr><td port="out1"><font point-size="30">⦿</font></td><td port="out2"><font point-size="30">⦿</font></td><td port="in"><font point-size="30">⦿</font></td></tr></table>> ];
}
subgraph "cluster_2" { label="Instrument B"
"b"[ shape="plaintext" label=<<table border="0" cellborder="0" cellspacing="0"><tr><td fixedsize="true" width="50">Out 1</td><td fixedsize="true" width="50">Out 2</td><td fixedsize="true" width="50">In 1</td></tr><tr><td port="out1"><font point-size="30">⦿</font></td><td port="out2"><font point-size="30">⦿</font></td><td port="in"><font point-size="30">⦿</font></td></tr></table>> ];
}
subgraph "cluster_3" { label="Instrument C"
"c"[ shape="plaintext" label=<<table border="0" cellborder="0" cellspacing="0"><tr><td fixedsize="true" width="50">A</td><td fixedsize="true" width="50">B</td><td fixedsize="true" width="50">C</td><td fixedsize="true" width="50">D</td></tr><tr><td port="a"><font point-size="30">⦿</font></td><td port="b"><font point-size="30">⦿</font></td><td port="c"><font point-size="30">⦿</font></td><td port="d"><font point-size="30">⦿</font></td></tr></table>> ];
}
"a":"out1" -- "c":"a";
"b":"out1" -- "c":"b";
}
Another variation, using Top to Bottom (instead of Left to Right) layout:
Source:
strict graph "main"
{
layout="dot";
rankdir="TB";
graph[ fontname="Arial Bold" labeljust="l" ];
node[ fontname="Wingdings" ];
nodesep="1.5" ranksep="1.5"
subgraph "cluster_1" { label="Instrument A"
"a"[ shape="plaintext" label=<<table border="0" cellborder="0" cellspacing="0"><tr><td fixedsize="true" width="50">Out 1</td><td fixedsize="true" width="50">Out 2</td><td fixedsize="true" width="50">In 1</td></tr><tr><td port="out1"><font point-size="30">⦿</font></td><td port="out2"><font point-size="30">⦿</font></td><td port="in"><font point-size="30">⦿</font></td></tr></table>> ];
}
subgraph "cluster_2" { label="Instrument B"
"b"[ shape="plaintext" label=<<table border="0" cellborder="0" cellspacing="0"><tr><td fixedsize="true" width="50">Out 1</td><td fixedsize="true" width="50">Out 2</td><td fixedsize="true" width="50">In 1</td></tr><tr><td port="out1"><font point-size="30">⦿</font></td><td port="out2"><font point-size="30">⦿</font></td><td port="in"><font point-size="30">⦿</font></td></tr></table>> ];
}
subgraph "cluster_3" { label="Instrument C"
"c"[ shape="plaintext" label=<<table border="0" cellborder="0" cellspacing="0"><tr><td fixedsize="true" width="50">A</td><td fixedsize="true" width="50">B</td><td fixedsize="true" width="50">C</td><td fixedsize="true" width="50">D</td></tr><tr><td port="a"><font point-size="30">⦿</font></td><td port="b"><font point-size="30">⦿</font></td><td port="c"><font point-size="30">⦿</font></td><td port="d"><font point-size="30">⦿</font></td></tr></table>> ];
}
"a":"out1" -- "c":"a";
"c":"b" -- "b":"out1";
}