How to force neato engine to reverse node order? - graphviz

I'm trying to draw a graph where the shorter word "Myth" is in the top right, however the neato engine is recalcitrant and refuses to accept pos inputs (with or without !) and rank inputs. When appending ! to my pos inputs, it will just stretch the graph out really far, and keep "Hominids" in the top row, while putting "Myth" in the bottom.
digraph G {
layout="neato";
center="true";
fontpath="C:\Windows\Fonts";
node [fontsize="14"];
node [fontname="Abode Jenson Pro"];
graph [size="10,10!"];
rankdir=LR;
meme [shape=ellipse,label="Myth",rank="min",pos="3,0!"];
gene [shape=ellipse,label="Hominids",rank="max",pos="7,10!"];
meme -> gene [arrowsize="0.5",label="increases \n survival of",fontsize="8",constraint="true"];
gene -> meme [arrowsize="0.5",label=" generate \n venerate",fontsize="8",constraint="false"];
}

Graphviz counts coordinates as on the orthogonal graph with 0 being at the bottom left corner. So in pos attribute first coordinate is distance from left side to right →, and the second one — from bottom to top ↑.
Look at you current coordinate values:
So it's logical that your nodes appear as on the picture: you've forced their positions to be so! If you inverse the pos values you will get the result you need:
digraph G {
layout="neato";
center="true";
fontpath="C:\Windows\Fonts";
node [fontsize="14"];
node [fontname="Abode Jenson Pro"];
graph [size="10,10!"];
meme [shape=ellipse,label="Myth",rank="min",pos="7,10"];
gene [shape=ellipse,label="Hominids",rank="max",pos="3,0"];
meme -> gene [arrowsize="0.5",label="increases \n survival of",fontsize="8",constraint="true"];
gene -> meme [arrowsize="0.5",label=" generate \n venerate",fontsize="8",constraint="false"];
}
Also note that rankdir attribute you used, won't have any effect in neato. As stated in the documentation it only works with dot layout.

Related

GraphViz DOT output: What are the 4-6 "pos" coordinates for an "edge"

I just started to experiment with GraphViz's "neato" command for
Kamada-Kawai graph visualization (solved using stress majorization).
I am particularly interested in extracting the laid out node
coordinates for external processing.
I was looking at this
question
to figure out the "pos" attribute for graph edges in the output DOT
file. The attribute consists of 4 coordinate points. One helpful
answer says that the
series of coordinats (not necessarily 4) are the control points of a
spline, likely a Bezier
spline.
The answerer is "compound eye", who I'll refer to as "CE". Here is
the example given:
// digrfG.dot
//-----------
digraph G {
A [label = "A" xlabel="a" pos="0,100" ]
B [label = "B" xlabel="b" pos="100,0"]
A -> B [label = "A->B www" xlabel="a->b"]
[pos="0,100 0,0 0,0 100,0"]
}
In Bash, it is processed by GraphViz using:
# Make image:
#------------
dot -Kneato -n2 -Tpng digrfG.dot >| digrfG.png
# Make output DOT file:
#----------------------
dot -Kneato -n2 digrfG.dot >| digrfG_out.dot
The output is:
# digrfG_out.dot
#---------------
digraph G {
graph [bb="-7,0,154,151"];
node [label="\N"];
A [height=0.5, label=A, pos="27,118",
width=0.75, xlabel=a, xlp="-3.5,143.5"];
B [height=0.5, label=B, pos="127,18",
width=0.75, xlabel=b, xlp="96,43.5"];
A -> B [label="A->B www", lp="42.5,75.5",
pos="27,118 27,18 27,18 127,18",
xlabel="a->b", xlp="63.5,60.5"];
}
My edge coordinates do not match
CE's, neither in the
numerical quantities nor in the number of coordinates. While I have 4
coordinates, CE has 6, including 2 coordinates at the start of the
series prefixed by "s," and "e,". The Bezier curve
page
cited by CE gives the impression that typical Bezier splines have 4
control points, including start and end points, though the math
allows for more. This Micrsoft
page
reinforces this impression of a 4-point default.
This GraphViz
page shows that
an edge's "pos" attribute contains a spline, starting with start and
end points, prefixed with "s," and "e," as per CE's output, but the
syntax is puzzling. If it is regular expression syntax, then there
are 4 or more coordinates following optional start and end points.
That might explain why I have no coordinates prefixed with "s," or
"e,", but I have 4 coordinates.
In digrfG_out.dot above, if I compare the 4 coordinates with the
node coordinates, it is clear that the first and last of the 4
coordinates match the node coordinates. It seems that CE's GraphViz
defaults to 6 control points and explicitly designates start and end
points at the head of the list of coordinates, whereas my GraphViz
defaults to 4, without special treatment of the start and end
points. Since GraphViz's spline
page is so
ambiguous, I was wondering if this interpretation can be confirmed.
Thanks.
I would suggest skipping CE's explanation (not necessarily wrong, but maybe ambiguous) and go to the sources on the Graphviz website.
Yes, Bezier curves require 4 points per "segment" (my term) but the last point in a segment is also used as the first in the next segment. Graphviz's arrowheads use separate points - for one end of the arrowhead.
The optional s (start) and e (end) points are for optional arrowheads. Then 4 required points and then optional sets of 3 points.
See p.36 https://www.graphviz.org/pdf/dotguide.pdf, https://forum.graphviz.org/t/how-to-control-the-points-of-splines/1087, and https://forum.graphviz.org/t/fun-with-edges/888 - in addition to the (yes, regular expression) http://www.graphviz.org/docs/attr-types/splineType/
I hope this helps.
Any edge can have arrowheads, even in a non-directed graph. Digraph just sets the default (arrowhead or no arrowhead). The dir attribute (https://graphviz.org/docs/attrs/dir/) explicitly sets arrowheads.
Finally, arrowhead shape (https://graphviz.org/doc/info/arrows.html) can be "none".
graph {
A--B [dir=forward]
C--D [dir=back]
E--F [dir=both]
G--H [dir=none]
}
Dot produces this:

How to draw a spline curve between 2 points with a control points with graphviz?

I would like to create a spline curve between the blue point and the green point with the red point as a control point.
Graphviz documentation says :
splines attribute, of type bool or string, is valid on Graphs
splineType with the pattern : spline ( ';' spline )* is a valid type for pos attribute
pos attribute is valid on Edges and Nodes
I Tried this graph
graph G{
layout ="neato" outputorder="edgesfirst" splines="true"
a[shape="point" pos="0,0!" color="blue"]
b[shape="point" pos="1,0!" color="green"]
c[shape="point" pos=" 0.5,0.5!" color="red"]
a -- b [pos="e,1,0 s,0,0 0.5,0.5!"]
}
then on Windows 10 PowerShell :
neato.exe -Tsvg .\spline.dot > .\spline.svg
with
neato - graphviz version 2.49.3 (20211023.0002)
result
What is the proper way of achieving this?
Thanks.
Close, but ...
! notation seems to only apply to nodes (not edges) (poorly documented, but see: https://graphviz.org/docs/attr-types/point/ and https://graphviz.org/docs/attrs/pin/)
by default, pos value units are points (inch/72). Your values are ~ too small
neato -n2 will use node & edge values you provide (https://graphviz.org/faq/#FaqDotWithCoords)
all edges (not just curves) are defined as cubic B-splines and are defined by 1 + n*3 points (n is integer >=1) (https://graphviz.org/docs/attr-types/splineType/) (i.e. 4 or 7 or 11 or ...)
So:
graph G{
// default units for pos values are in points (72/inch)
// multiplied by 100 out of laziness
// ! only applies to nodes, not edges
layout ="neato"
outputorder="edgesfirst" // why???
splines="true"
a[shape="point" pos="0,0!" color="blue"]
b[shape="point" pos="100,0!" color="green"]
c[shape="point" pos="50,50!" color="red"]
// "s" arrowhead must preceed "e" arrowhead, so swaped them
// BUT, "--" says non-directed graph, NO arrowheads, so they are deleted
// also need 4, 7, 11, ... points NOT including arrowhead points
// so added points (just guesses)
a -- b [pos="0,0 30,66 70,66 100,0"]
}
Gives:
Whew

Can you join edges when they go to the same node?

See the line on the leftmost side of this image.
This isn't a perfect example because the lines don't end on a node, but imagine that there is a node on the bottom left corner of the image. Normally in graphviz if I have a graph like this:
digraph G {
a->c
b->c
}
Then I get two separate lines going into c. Is it possible to have these two lines join before they reach c?
Yes, it is possible to have two lines join before they reach c but, as far as I can see, it requires inserting an invisible node to do it. e.g.:
digraph G {
x [style=invis, height=0, label=""]
a->x [dir=none]
b->x [dir=none]
x->c
}
... which gives:

edge-layout in graphviz for fixed node positions

I was trying to write my own little algorithm for graph layout that only creates a node layout but does not define edge routes. When I use Graphviz to turn the resulting dot file into a graph, the edges are straight lines that cross the nodes and even overlap each other. Is there a way to use Graphviz to layout the edges as nicely as the dot algorithm does, but have the nodes in predetermined fixed positions?
You can see the effect for instance on the following graph:
digraph test {
"a" [pos="0.0,0.0"];
"b" [pos="50.0,50.0"];
"c" [pos="100.0,100.0"];
"a" -> "b";
"a" -> "c";
"b" -> "c";
}
When drawn with dot -Knop -Tpng -otest.png test.dotty the line between a and c crosses b. What I want is that all nodes keep their positions, but the line between a and c goes around b.
Just add:
splines=true;
to your graph - result is:

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