Change distance between edges in dot - graphviz

Is there a way to control the spacing between edges in dot, similar to the nodesep attribute in the other graphviz layout engines? I would like to keep using dot as the layout engine.
By edges I mean either multi-edges or multi-coloured edges, like in the following example. I would like to decrease the space between the a->b edges or increase the space between the c->d edges.
digraph G {
nodesep = "0.15"
a -> b [dir=none color="red"]
a -> b [dir=none color="blue"]
a -> b [dir=none color="green"]
c -> d [dir=none color="green:red:blue"]
}
In dot, the nodesep attribute does not have the desired effect.

Assuming a white background, add white (invisible) lines to change the apparent spacing:
digraph G {
nodesep = "0.15"
c -> d [dir=none color="green:white:white:white:red:white:white:white:blue"]
}
Giving:

There seems to be a bug in that code, only one leg is thicker (penwidth).
So, this solution used ports:
digraph G {
// nodesep = "0.15"
splines=false
edge[penwidth=7]
a:sw -> b:nw [dir=none color="red"]
a -> b [dir=none color="blue"]
a:se -> b:ne [dir=none color="green"]
c -> d [dir=none color="green:white:white:white:red:white:white:white:blue"]
}
Giving:

The best solution I've found is to add transparent edges. That way, this solution works regardless of background colour. Since the edges are transparent, overlap is not a problem and all the coloured edges have the same width.
digraph G {
c -> d [
dir=none
penwidth=5
color="red:transparent:transparent:green:transparent:transparent:blue"
]
}
Produces:
This works for an arbitrary number of edges, and the spacing can be controlled by changing the number of transparent edges between each coloured edge.

Related

How to have multiple label one above and one below the edges in graphviz?

I've the following output currently I want to place a label below the edge between p and z in the figure.Is it possible to do in graphviz I've tried using xlabels but it doesn't work.
Current Code:
digraph GPG{
node [shape=box];
subgraph cluster0{
node[shape=circle];
0[label=0,style=invis];
}
subgraph cluster1{
node[shape=circle];
1[label=1,style=invis];
p->z [label="2 | 1",minlen=1];
{
rank = same;
p;z;
}
}
subgraph cluster2{
node[shape=circle];
2[label=2,style=invis];
}
0->1
1->2
}
I want a label below edge p->z as well above the edge.Is it possible in graphviz?
Kind of ugly, but:
digraph overunder{
splines=false
{ rank=same
a -> b [label=" over " ]
a -> b [label="under" penwidth=0.0 dir=none]
}
}
Produces:
You may have to add the non-breaking space characters (see above) because Graphviz seems to position labels based on the length of the text - longer labels are placed above shorter labels.

Graphviz (dot) control edge routing

In this graph the bottom edge is not drawn symmetrical to the top edge:
digraph G {
A:ne -> A:nw;
A:sw -> A:se;
}
I want it to look more like a "fat snowman" with the edge A:sw -> A:se; looping below the node. Is there a way?
Short answer no - or not easily.
Loops seem to be placed from the rankdir direction. If rankdir is TB (down), loops seem to be placed "up".
It you're willing to work at it, you can run your graph twice, once with rankdir=TB, once with rankdir=BT - both times with -Tdot. Then you'd have to replace the offending edge with the equivalent edge from the other graph. [I hope this makes some sense]
Here is a tweaked version of your graph run with different values of rankdir:
digraph G {
A:ne -> A:nw;
A:sw -> A:se;
dummy [style=invis]
dummy -> A [style=invis]
}

Graphviz: How to place nodes only in lower semi-circle using circo layout?

In the attached figure, the nodes are arranged in a circle around the node. Is there a (possibly generic) way to arrange the nodes only in the lower semi-circle, without having to provide fixed coordinates for the nodes?
Edit: Would like to achieve something like shown in the image attached below. As one can see - all the nodes are arranged in the lower semi-circular region (this figure was made using CMap Tools).
The code is trivial, but pasting it anyway.
digraph semicircle {
rankdir="TD"
graph [nodesep="0.1", ranksep="0.3", center=true]
mindist="0.4"
S [label="Root", style="filled", fillcolor="greenyellow", shape="box"]
subgraph cluster1 {
rank="same"
A; B; C; D;
S -> {A, B, C, D};
} }
using dot/circo : graphviz version 2.40.1
I noted that circo placed nodes counter-clockwise, starting at 3 o'clock.
I added enough invisible nodes to fill the 2 through 10 o'clock positions.
To make the inter-nodal distances even more uniform I added:
node [shape=square style=rounded]
The result I got is this:
Try this:
digraph semicircle {
rankdir="TD"
graph [nodesep="0.1", ranksep="0.3", center=true, root=S]
mindist="0.4"
S [label="Root", style="filled", fillcolor="greenyellow", shape="box"]
subgraph cluster1 {
rank="same"
A
z1[style=invis label=""]
z2[style=invis label=""]
B; C; D;
S -> A
S -> z1,z2 [style=invis]
S -> { B, C, D};
}
}

How do I vertically align a node with the center of a cluster?

I am looking for a way to align individual nodes in graphviz with an entire subgraph/cluster.
I am currently teaching a small team of analysts to use rmarkdown and I want to allow them to include simple graphs and flowcharts in their documents. I therefore use DiagrammeR (and viz.js) to render charts written in dot. To increase user adoption, I want to minimize complexity and avoid HTML and use raw dot.
Our problem is that we frequently try to align nodes with subgraphs/clusters containing multiple nodes, but we cannot align the entire subgraph with the node. Alignment only works with the constituent nodes within the subgraph/cluster. (see nodes C,D,E and G,T below)
I have tried to create a record node using GT [shape = record label="{G | T}"] but that does not allow individual styling of the two nodes.
I have also tried creating an HTML record node which allows individual styling but increases complexity too much and requires users to know HTML.
Finally, I have tried to insert an invisible node inside the clusters to "simulate" the center and then use the invisible node for alignment. This unfortunately pushes G and T to far apart and doesn't achieve the intended effect.
digraph G {
graph [splines = false, ranksep = 0.2]
edge [style = "invis"]
node [shape = box, width = 7.5]
A B H
node [shape = circle, width = 1.5]
subgraph cluster_2 {
rank = same
C D E
}
subgraph cluster_1 {
G [shape = box]
T [shape = box]
}
A -> B
G -> T
B -> {C D E G}
{C D E T} -> H
}
The following gives the output:
In the picture above, the subgraph containing G and T is not aligned with the subgraph containing C,D,E.
Is there a way to vertically align the centers of the two subgraphs?
The problem is that GraphViz only align node rows and {C D E} is one row where as {G->T} is two rows so {C D E} can only be align with either G or T
You can however align {C D E} with the space between G and T though that is probably not what you want. E.g. like this:
digraph G {
graph [splines = false, ranksep = 0.2]
//edge [style = "invis"]
node [shape = box, width = 7.5]
A B H
node [shape = circle, width = 1.5]
subgraph cluster_2 {
rank = same
C D E
}
subgraph cluster_1 {
G [shape = box]
T [shape = box]
}
A -> B
G -> T[minlen=2]
B -> G
B -> {C D E} -> H [minlen=2]
T -> H
}
Resulting in:

How to prevent edge labels from messing up the layout in graphviz?

I have a simple vertical graph that looks nice and symmetrical without any labels using the following code:
digraph test_alignment
{
{rank=same; a -> b;}
a -> c;
b -> c;
c -> d;
d -> e;
d -> f;
{rank=same; e -> f;}
}
I'd like to label the edge between A and B as well as the one between E and F, using the same string for each label. I'm expecting the same output, except with longer A->B and E->F edges bearing the same label.
Unfortunately, as soon as I add a label to one of these edges, the general layout looks slightly askew (the result is similar if I add a label to the E->F edge):
digraph test_alignment
{
{rank=same; a -> b [label="Label"];}
a -> c;
b -> c;
c -> d;
d -> e;
d -> f;
{rank=same; e -> f;}
}
I'm very new to graphviz and, following many questions on Stack Overflow, I have been experimenting with different combinations of rank and constraint, I tried using clusters to see if it would keep the top and bottom part properly aligned independently, and tried using a mix of dot, ccomp, gvpack and neato that produced similar results.
It always seems to boil down to the fact adding a label to the edge between nodes with the same rank affects how these nodes are positioned in a way I don't yet understand.
Am I missing something trivial, or am I attempting something I shouldn't instead of letting dot do its thing?
I'm using dot - graphviz version 2.36.0 (20140111.2315) and the linked pictures were produced with dot only (though I obtained similar results when using :
dot test_alignment.dot -Tpng -O
You may try to use the xlabel attribute, together with forcelabels if necessary. From the description:
... For edges, the label will be placed near the center of the edge. This
can be useful in dot to avoid the occasional problem when the use of
edge labels distorts the layout. ...

Resources