I'm exploring using fdp to do grid (rows, and columns) based diagram using fdp with forced positions. But to my surprise, the forced positions sometimes are still just suggestion, not really enforced. I wonder how I can have the positions completely enforced with graphviz, some layout engine, and some parameter combination?
Here are the illustration of my findings: (I'm using emacs/org-mode/graphviz code block to generate the diagrams)
Case 1: single column, perfect alignment:
#+begin_src dot :file ./column1.png :cmdline -Kfdp -Tpng
graph dfd {
node[shape=box]
"(0.0, 0.0)" [pos="0.0, 0.0!"]
"(0.0, 0.1)" [pos="0.0, 0.1!"]
"(0.0, 0.2)" [pos="0.0, 0.2!"]
"(0.0, 0.3)" [pos="0.0, 0.3!"]
}
#+end_src
Case 2: 2 columns: even the first column is no longer aligned
#+begin_src dot :file ./column2.png :cmdline -Kfdp -Tpng
graph dfd {
node[shape=box]
"(0.0, 0.0)" [pos="0.0, 0.0!"]; "(0.1, 0.0)" [pos="0.1, 0.0!"]
"(0.0, 0.1)" [pos="0.0, 0.1!"]; "(0.1, 0.1)" [pos="0.1, 0.1!"]
"(0.0, 0.2)" [pos="0.0, 0.2!"]; "(0.1, 0.2)" [pos="0.1, 0.2!"]
"(0.0, 0.3)" [pos="0.0, 0.3!"]; "(0.1, 0.3)" [pos="0.1, 0.3!"]
}
#+end_src
I also found that the more columns, the worse misalignment is. I found that fdp's layout algorithm is somehow elastic to avoid overlapping but I still don't understand for the first column, there should not be any overlapping yet.
Well, I'm not sure whether graphviz
is really the tool of choice for what you want to achieve. But since I don't know, here some bits to get you going:
dot
arranges the nodes you define in a hierarchical fashion that depends upon the order they are defined, upon the direction of the edges and upon a specific instruction rank = same
for nodes that are on the same hierarchical level. dot
automatically sets the width and height of the nodes according to the label, so if your labels have different length, you need to take that into consideration.
A very basic sample:
digraph so
{
// default/initial node style
node[ shape = box, width = 2, height = 1.5 ];
// default/initial edge style
edge[ style = invis ];
{rank = same; a1 -> a2 -> a3 -> a4 }
{rank = same; b1 -> b2 -> b3 -> b4 }
{rank = same; c1 -> c2 -> c3 -> c4 }
{rank = same; d1 -> d2 -> d3 -> d4 }
a1 -> b1 -> c1 -> d1;
a1[ label = "bla" ];
c1[ label = "long label\nwith new line" ];
}
which gives you
In this simple example, the rank = same
instruction is not really necessary, you would achieve the same with
a1 -> b1 -> c1 -> d1;
a2 -> b2 -> c2 -> d2;
a3 -> b3 -> c3 -> d3;
a4 -> b4 -> c4 -> d4;
but the more elaborate your structure gets, the more the explicit ranking will help.