Increase curvature of connecting arcs - graphviz

Consider:
digraph D {
0[pos="0,0!"]
1[pos="0,5!"]
0 -> 1[label=0.25]
1 -> 0[label=0.50]
}
Rendered under neato engine, this gives:
Is there a way to increase/control the curvature of the connecting arcs so that the rendering is something like the hand-drawn annotations below:
Edited to add: While I don't have to stick with neato, it is important in my application that the node pos coordinate values be upheld.

[there may be better ways, but edges are pretty hard to wrangle]
This solution requires neato -n (see https://graphviz.org/faq/#FaqDotWithNodeCoords) and (https://graphviz.org/docs/attrs/pos/)
Different versions of neato seem to produce different results when previous answer is input. This input file should work with older & newer versions of neato.
digraph D {
// next lines from the Graphviz FAQ
overlap=false
splines=true
0[pos="0,0!"]
1[pos="0,5!"]
// stick an invisible node in the middle, to force the edges out
half [pos="0,2.5!" width=1.1 height=1 style=invis]
0:nw -> 1:sw [label=0.25]
1:se -> 0:ne [label=0.50]
}
Giving:

Related

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]
}

In GraphViz, make node positions within a subgraph independent from nodes in other subgraphs?

Using dot, the basic layout puts nodes into layers. If you create subgraphs, it groups related nodes inside of rectangles, but the nodes are still in layers, and those layers are influenced by the nodes outside of the subgraph.
Sometimes, this is great. But sometimes, when a subgraph is an independent visual entity, it might be nice to be able to lay out its content without respect to the layers of the other parts of the graph. Take for example the following:
digraph x {
subgraph one {
a [ label="a\nvery\nlong\nlabel" ]
b [ label="another\nvery\nlong\nlabel" ]
c [ label="still\nmore\nlong\nlabels" ]
a -> b - > c
}
subgraph two {
w -> x -> y -> z
}
}
Because of the long labels, the nodes in subgraph one will take up a lot of space. But because of the layer-based layout, the nodes in subgraph two will be vertically aligned with the corresponding nodes from subgraph one.
Is there a way to make it layout subgraph two as if subgraph one did not exist?
Not directly with dot. Dot does rank alignment across the entire graph. However here are two ways to get close to what you want:
use neato -Goverlap=false -Gmode=hier to approximate a dot layout:
or split the various parts into separate graphs, use dot -Tdot to layout each, then use gvpack (https://graphviz.org/pdf/gvpack.1.pdf) to combine the parts into a single output. Like so:
dot -Tdot ComboGraph1a.gv >ComboGraph1a.dot
dot -Tdot ComboGraph1b.gv >ComboGraph1b.dot
gvpack -array_ib2 ComboGraph1?.dot |neato -Tpng -n2 >oooo.png
Giving:

Add extra edges to a digraph in Graphviz

I have a .dot digraph which shows a graph as I want (depicting relationship between some tables). I want to add redundant edges to the graph (to represent redundant relationships in the database which exist only to write queries less effortly). These redundat edges, which will be written in a "dotted" style, must not change the deployment of nodes in the graph.
In other words, there's edges which must affect the node positions to print the graph pretty, and other edges which must to be added after the node positions are already computed (which will be styled differently --light gray, dotted, etc; to show that they're not main edges).
Is there options in Graphviz to specify "extra" edges?
Use constraint=false and color=gray on those additional edges.
digraph G {
a -> b -> c -> d;
d -> a [constraint=false,color=gray]
a -> z -> x -> d;
}
Play with that on http://graphviz.it/#/rhlWBZsz

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. ...

How to specify the length of an edge in graphviz?

In a directed graph, if there is a cycle, the graphviz makes that edge really short.
Is there a parameter that would let me change the length of the cyclic edge, so that
the graph looks a bit uniform.
digraph ER {
rankdir="LR";
//orientation=landscape;
node [shape=ellipse, fontsize=30];
{node [label="Original"] old;}
{node [label="Final"] new;}
{node [label="Intermediate"] ir;}
old -> ir [label="suggest", fontsize=30];
ir -> ir [label="validate", fontsize=30, len=f];
ir -> new [label = "finalize", fontsize=30];
}
Edit: Sorry, my answer will make edges longer, but not the self referencing edges you need.
len doesn't work in dot, but minlen does.
https://www.graphviz.org/doc/info/attrs.html#d:minlen
x->y
[minlen=5]
len doesn't works in dot, but you can try this trick:
digraph G {
rankdir=LR
a->b[dir=both]
b->c[dir=both,label=" "]// Just use the space to increase the edge length
}
If rankdir=TB, use label="\n" (repeat the \n as necessary) to increase the length.
I found that the following attribute nodesep worked to solve this problem with sfdp.
From nodesep | Graphviz:
For layouts other than dot
nodesep affects the spacing between loops on a single node, or multiedges between a pair of nodes.
Note that this is a graph attribute, so the value is the same for all edges in the graph.
From dot(1):
len=f sets the optimal length of an edge. The default is 1.0.
You can make the cyclic edge longer by adding a bunch of invisible cyclic edges before your visible one, like this:
digraph ER {
rankdir="LR";
//orientation=landscape;
node [shape=ellipse, fontsize=30];
{node [label="Original"] old;}
{node [label="Final"] new;}
{node [label="Intermediate"] ir;}
old -> ir [label="suggest", fontsize=30];
ir -> ir [style="invis"]
ir -> ir [style="invis"]
ir -> ir [style="invis"]
ir -> ir [style="invis"]
ir -> ir [label="validate", fontsize=30, len=f];
ir -> new [label = "finalize", fontsize=30];
}
In .dot language, the edge connects two notes with different ranks.
The length of edge is equal to (difference in ranks)*ranksep
default ranksep (in graph attribute) is 0.75 inch, so edge of adjacent nodes will be 0.75 inch.
To reduce the edge length, you set ranksep into a smaller value in graph atrribute
There's another approach that I now use for this:
I use graphviz to output the file in dot format
dot -T dot -Kneato -o ./positioned.dot ./input.dot
This file will contain the Bezier curve definitions for every edge.
I manually change the points to curve the way I want it to draw.
This may look a little daunting at first but once you figure out, how they work this isn't hard, I'm inching towards a script that will do this for me automatically
then re-run dot with your edited positioned file as the input
dot -T png -Kneato -O ./positioned.dot
With this approach I've pretty much turned dot into my text based visio replacement

Resources