[Tex/LaTex] Drawing a collaboration graph or tree with TikZ

data structuresdot2texdot2texigraphstikz-pgf

I'm trying to draw a collaboration graph for C data structures. originally I got dot files from Doxygen which I tried to convert using dot2tex with varying degrees of success, though none produced decent output (ie. no alignment, none of the typical "proper" look of well made TikZ diagrams). This kind of graph is similar to a dependency graph, except it contains references for each data structure link to the linked struct (in other words, an edge/path is connected between the pointer/reference field to the struct it references).

I would like to know if tikz-qtree could work for this purpose, since I want to optimize space usage and dot/graphvix/dot2tex (and manually tweaking the output) is suboptimal

Example of collaboration diagram:

enter image description here

The original dot syntax:

digraph G
{
  edge [fontname="Helvetica",fontsize="10",labelfontname="Helvetica",labelfontsize="10"];
  node [fontname="Helvetica",fontsize="10",shape=record];
  Node1 [label="faultstate",height=0.2,width=0.4,color="black", fillcolor="grey75", style="filled" fontcolor="black"];
  Node2 -> Node1 [dir="back",color="darkorchid3",fontsize="10",style="dashed",label=" entry" ,fontname="Helvetica"];
  Node2 [label="vm_map_entry",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$structvm__map__entry.html"];
  Node2 -> Node2 [dir="back",color="darkorchid3",fontsize="10",style="dashed",label=" prev\nnext\nright\nleft" ,fontname="Helvetica"];
  Node3 -> Node2 [dir="back",color="darkorchid3",fontsize="10",style="dashed",label=" object" ,fontname="Helvetica"];
  Node3 [label="vm_map_object",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$unionvm__map__object.html"];
  Node4 -> Node3 [dir="back",color="darkorchid3",fontsize="10",style="dashed",label=" sub_map" ,fontname="Helvetica"];
  Node4 [label="vm_map",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$structvm__map.html"];
  Node2 -> Node4 [dir="back",color="darkorchid3",fontsize="10",style="dashed",label=" root\nheader" ,fontname="Helvetica"];
  Node5 -> Node3 [dir="back",color="darkorchid3",fontsize="10",style="dashed",label=" vm_object" ,fontname="Helvetica"];
  Node5 [label="vm_object",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$structvm__object.html"];
  Node5 -> Node5 [dir="back",color="darkorchid3",fontsize="10",style="dashed",label=" backing_object" ,fontname="Helvetica"];
  Node4 -> Node1 [dir="back",color="darkorchid3",fontsize="10",style="dashed",label=" map" ,fontname="Helvetica"];
  Node5 -> Node1 [dir="back",color="darkorchid3",fontsize="10",style="dashed",label=" first_object\nobject" ,fontname="Helvetica"];
}

The converted TeX syntax (after dot to xdot intermediate conversion via graphviz's dot) from dot2tex (TikZ mode):

\documentclass{article}
\usepackage[x11names, rgb]{xcolor}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usetikzlibrary{snakes,arrows,shapes}
\usepackage{amsmath}

\begin{document}
\pagestyle{empty}

\enlargethispage{100cm}
\begin{tikzpicture}[>=latex',line join=bevel,]
\node (Node1) at (28bp,10bp) [draw=black,fill=grey75,record] {faultstate};
  \node (Node3) at (213bp,10bp) [draw=black,fill=white,record] {vm\_map\_object};
  \node (Node2) at (65bp,178bp) [draw=black,fill=white,record] {vm\_map\_entry};
  \node (Node5) at (140bp,88bp) [draw=black,fill=white,record] {vm\_object};
  \node (Node4) at (65bp,88bp) [draw=black,fill=white,record] {vm\_map};
  \draw [darkorchid3,<-,dashed] (Node3) ..controls (247.46bp,28.666bp) and (252.35bp,32.972bp)  .. (256bp,38bp) .. controls (258.83bp,41.907bp) and (274.89bp,84.957bp)  .. (266bp,98bp) .. controls (230bp,150.83bp) and (152.79bp,168.33bp)  .. (Node2);
  \definecolor{strokecol}{rgb}{0.0,0.0,0.0};
  \pgfsetstrokecolor{strokecol}
  \draw (284bp,88bp) node { object};
  \draw [darkorchid3,<-,dashed] (Node2) ..controls (120bp,183.99bp) and (123bp,181.48bp)  .. (123bp,178bp) .. controls (123bp,172.43bp) and (115.33bp,169.35bp)  .. (Node2);
  \draw (134bp,190bp) node { prev};
  \draw (134bp,179bp) node {next};
  \draw (134bp,168bp) node {right};
  \draw (134bp,157bp) node {left};
  \draw [darkorchid3,<-,dashed] (Node2) ..controls (32.825bp,146.58bp) and (12.591bp,123.18bp)  .. (4bp,98bp) .. controls (-5.6625bp,69.676bp) and (12.453bp,35.188bp)  .. (Node1);
  \draw (16.5bp,88bp) node { entry};
  \draw [darkorchid3,<-,dashed] (Node5) ..controls (185.12bp,92.844bp) and (188bp,90.849bp)  .. (188bp,88bp) .. controls (188bp,83.324bp) and (180.25bp,80.95bp)  .. (Node5);
  \draw (222.5bp,88bp) node { backing\_object};
  \draw [darkorchid3,<-,dashed] (Node4) ..controls (35.128bp,68.878bp) and (31.433bp,64.745bp)  .. (29bp,60bp) .. controls (22.399bp,47.129bp) and (24.124bp,29.744bp)  .. (Node1);
  \draw (40bp,49bp) node { map};
  \draw [darkorchid3,<-,dashed] (Node5) ..controls (179.37bp,70.063bp) and (185.87bp,65.478bp)  .. (191bp,60bp) .. controls (201.97bp,48.297bp) and (208.13bp,30.2bp)  .. (Node3);
  \draw (228.5bp,49bp) node { vm\_object};
  \draw [darkorchid3,<-,dashed] (Node5) ..controls (131.95bp,58.339bp) and (126.18bp,45.94bp)  .. (117bp,38bp) .. controls (100.03bp,23.315bp) and (75.247bp,16.617bp)  .. (Node1);
  \draw (158bp,50bp) node { first\_object};
  \draw (158bp,39bp) node {object};
  \draw [darkorchid3,<-,dashed] (Node4) ..controls (61.38bp,57.989bp) and (62.694bp,45.955bp)  .. (70bp,38bp) .. controls (83.331bp,23.486bp) and (133.52bp,16.635bp)  .. (Node3);
  \draw (91.5bp,49bp) node { sub\_map};
  \draw [darkorchid3,<-,dashed] (Node2) ..controls (65bp,139.31bp) and (65bp,111.67bp)  .. (Node4);
  \draw (80bp,128bp) node { root};
  \draw (80bp,117bp) node {header};
\end{tikzpicture}
\end{document}

Output obtained:

Note: this is without --tikzedgelabels. Using the option yields a broken diagram. dot2tex likes straight edges only, so bent curves/edges connecting nodes don't play along.

Output wanted:

  • No hideous \draw -(coordinate) constructs. I want TikZ-style edge labels and no fixed drawing points. I want the layout to be fluid and have optimal distribution of the diagram nodes in the canvas.

  • --tikzedgelabels won't cut it. just a FYI, i can see it coming in the comments.

Best Answer

Only an answer based on percusse's fine solution but with some modifications for the styles. I try to get a lighter code. I added a scope to use options for the labels. I removed pos=.5 because it's the value by default. I remove the style myline and I placed the options in the scope. I used the possibility to draw several edges from the same vertex with one path.

\documentclass{article}
\usepackage{tikz}
\begin{document}

\begin{tikzpicture}[ %some style declarations  
                    mynode/.style = {draw,inner sep=2mm},
                    scale=1.5]

% Placing the nodes: you have to place them, no way to know beforehand
\node[fill=red,
      mynode] (n0) at (0,0)   {faultstate};
\node[mynode] (n1) at (1,2)   {vm\_map};
\node[mynode] (n2) at (1,5)   {vm\_map\_entry};
\node[mynode] (n3) at (3.5,2) {vm\_object};
\node[mynode] (n4) at (5,0)   {vm\_map\_object};

%Now the edges and labels 
\begin{scope}[> = stealth,  ->,blue,thick,
              every node/.style = {black,right,align=center}]
  \draw (n1) edge              node                 {root\\header}            (n2);
  \draw (n0) edge [bend left]  node                 {entry}                   (n2) 
             edge [bend left]  node                 {map}                     (n1)
             edge [bend right] node [pos=0.8,
                                     below right]   {first\_object \\object}  (n3);
  \draw (n4) edge [bend left]  node [pos=0.8]       {sub\_map}                (n1) 
             edge [bend right] node                 {vm\_object}              (n3);
  \draw (n3) edge [loop right] node                 {backing\_object}         (n3);
  \draw (n2) edge [loop right,
                   min distance =1 cm,
                   out=10,
                   in=-10]       node               {prev\\next\\right\\left} (n2) 
             edge [looseness=1.8,
                   out=30,
                   in=20]      node  [below left]   {object}                  (n4) ;  
\end{scope}
\end{tikzpicture}
\end{document}   

enter image description here

Related Question