4

Context: I am using the TikZ library graphdrawing and it's layered layout to visualize directed acyclic graphs in an automated manner. For me it turned out that the layered drawing algorithm seemed to be the best fit for my use case. Unfortunately the algorithm does not seem to be aware of the dimensions of my nodes which carry multiple lines of text.

Question: I tried to tweak the graph layout of the example given below by applying the settings listed below but could not achieve any significant improvement. Do you see any options that can improve the layout despite increasing the generic node distance setting in PGF/TikZ manual section 27.3? To me it seems that the issue could be related to the components packing settings but I could not find out how to apply them.

  • linear optimization layer assignment (section 30.3)
  • minimum height layer assignment (section 30.3)
  • sweep crossing minimization (section 30.4)
  • linear optimization node positioning (section 30.5)
  • polyline layer edge routing (section 30.6)

Thank you very much in advance.

Current layout:

Graph layout generated from the minimal example blow

Minimal example:

\documentclass{minimal}
\usepackage{luatex85}
\usepackage{tikz}
\usetikzlibrary{graphdrawing,graphs,shapes}
\usegdlibrary{layered}
\usepackage[active,tightpage]{preview}
\PreviewEnvironment{tikzpicture}
\begin{document}
\begin{tikzpicture}[layered layout,every edge/.style={very thick, draw=blue!40!black!60, shorten >=1pt, shorten <=1pt}, every node/.style={rectangle, text ragged, inner sep=2mm, rounded corners, shade, top color=white, bottom color=blue!50!black!20, draw=blue!40!black!60, very thick, text ragged }]
\node
    [rectangle split, rectangle split parts=4]
     (nodeA)
    {
        \textbf{Memory location}
        \nodepart{two}
        0x6149e58
        \nodepart{three}
        \textit{name}
                 some\_long\_variable\_name
        \nodepart{four}
        \textit{type}
        int
    };
\node
    [rectangle split, rectangle split parts=3]
     (nodeB)
    {
        \textbf{Function invocation}
        \nodepart{two}
        0x6a4e0c0
        \nodepart{three}
        \textit{name}
        some\_function
    };
\node
    [rectangle split, rectangle split parts=4]
     (nodeC)
    {
        \textbf{Constant value}
        \nodepart{two}
        0x6444c78
        \nodepart{three}
        \textit{name}
        literal
        \nodepart{four}
        \textit{value}
        10
    };
\node
    [rectangle split, rectangle split parts=4]
     (nodeD)
    {
        \textbf{Memory location}
        \nodepart{two}
        0x59e47a8
        \nodepart{three}
        \textit{name}
        short\_name
        \nodepart{four}
        \textit{type}
        int
    };
\node
    [rectangle split, rectangle split parts=3]
     (nodeE)
    {
        \textbf{Function invocation}
        \nodepart{two}
        0x59e48a0
        \nodepart{three}
        \textit{name}
        some\_other\_function\_longer\_name
    };
\draw (nodeB) edge[->] (nodeA);
\draw (nodeE) edge[->] (nodeA);
\draw (nodeE) edge[->] (nodeC);
\draw (nodeE) edge[->] (nodeD);
\draw (nodeE) edge[->] (nodeB);
\draw (nodeB) edge[->] (nodeD);
\end{tikzpicture}
\end{document}
  • Because of the graphdrawing library the example requires LuaLaTeX. Also I find that the layout works best for single or dual line nodes but unfortunately I need more than two lines. – Christoph Oct 18 '16 at 17:08
  • Please do not use minimal for examples. It is not suitable. – cfr Oct 19 '16 at 0:08
3

Multipart nodes behave somewhat strangely. That is they have interesting features which the less charitable might be tempted to erroneously describe as 'bugs'.

You can, however, manipulate things a bit using such keys as sibling distance and minimum layers. For example,

\documentclass[border=10pt,multi,tikz]{standalone}
\usepackage{luatex85}
\usetikzlibrary{graphdrawing,graphs,shapes.multipart}
\usegdlibrary{layered}
\begin{document}
\begin{tikzpicture}
  \begin{scope}[layered layout, sibling distance=25mm, every edge/.style={very thick, draw=blue!40!black!60, shorten >=1pt, shorten <=1pt}, every node/.style={text ragged, inner sep=2mm, rounded corners, top color=white, bottom color=blue!50!black!20, draw=blue!40!black!60, very thick}]
    \node [rectangle split, rectangle split parts=4] (A)
    {%
      \textbf{Memory location}
      \nodepart{two}
      0x6149e58
      \nodepart{three}
      \textit{name}
      some\_long\_variable\_name
      \nodepart{four}
      \textit{type}
      int%
    };
    \node [rectangle split, rectangle split parts=3] (B)
    {%
      \textbf{Function invocation}
      \nodepart{two}
      0x6a4e0c0
      \nodepart{three}
      \textit{name}
      some\_function%
    };
    \node [rectangle split, rectangle split parts=4] (C)
    {%
      \textbf{Constant value}
      \nodepart{two}
      0x6444c78
      \nodepart{three}
      \textit{name}
      literal
      \nodepart{four}
      \textit{value}
      10%
    };
    \node
    [rectangle split, rectangle split parts=4] (D)
    {%
      \textbf{Memory location}
      \nodepart{two}
      0x59e47a8
      \nodepart{three}
      \textit{name}
      short\_name
      \nodepart{four}
      \textit{type}
      int
    };
    \node [rectangle split, rectangle split parts=3] (E)
    {%
      \textbf{Function invocation}
      \nodepart{two}
      0x59e48a0
      \nodepart{three}
      \textit{name}
      some\_other\_function\_longer\_name
    };
    \draw (B) edge[->, minimum layers=3] (A);
    \draw (E) edge[->] (A);
    \draw (E) edge[->, minimum layers=3] (C);
    \draw (E) edge[->] (D);
    \draw (E) edge[->, minimum layers=4] (B);
    \draw (B) edge[->, minimum layers=3] (D);
  \end{scope}
\end{tikzpicture}
\end{document}

spread out a bit

Another option would be to add in nodes purely for their spacing function; to use a different algorithm or to combine another algorithm. However, I rather doubt that fiddling with the algorithms is likely to help in this case.

What is puzzling me right now, however, is the disappearance of the arrows. I guess, but I'm not sure, that they are behind the nodes?

  • Thank you for looking into this. Unfortunately I definitely would like to/have to find some automatic solution. As such graphs are generated automatically there is no way to tweak them manually. For presentation purposes this is possible for few of them but a general solution would scale much better. When thinking again about this I wondered about heuristics that could calculate the minimum distance property in order to align all leaf childs (Memory location, Constant value) on the same level (compute longest path to all leaf childs). Which in turn is supported by TikZ by same level. – Christoph Oct 19 '16 at 20:37
  • I will try to check tomorrow or the day after tomorrow whether this solves the issue. If yes that's the answer I was looking for and accept it :-) Thank you for that hint! :-) – Christoph Oct 19 '16 at 21:02
  • The option is called same level or same rank but unfortunately does not work as shown in the manual: { [same layer] A, C, D} – Christoph Oct 20 '16 at 11:47
  • The fully calculated set of distances is: (B, A) = 3; (E, A) = 6; (E, C) = 6; (E, D) = 6; (E, B) = 3; (E, D) = 3 with 3 units per 1 distance unit in the graph. Still I wonder if this could be computed in TikZ itself? – Christoph Oct 20 '16 at 12:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.