使用 TikZ 绘制协作图或树

使用 TikZ 绘制协作图或树

我正在尝试绘制 C 数据结构的协作图。最初,我从 Doxygen 获得了 dot 文件,并尝试使用 dot2tex 进行转换,取得了不同程度的成功,但没有一个产生像样的输出(即没有对齐,没有典型的“正确”外观,制作精良的 TikZ 图)。这种图类似于依赖图,只是它包含指向链接结构的每个数据结构链接的引用(换句话说,指针/引用字段与其引用的结构之间有一条边/路径连接)。

我想知道是否tikz-qtree可以用于此目的,因为我想优化空间使用,而 dot/graphvix/dot2tex(并手动调整输出)不是最优的

协作图示例:

在此处输入图片描述

原始点语法:

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

转换后的 TeX 语法(通过 graphviz 的 dot 进行 dot 到 xdot 中间转换之后)来自 dot2tex(TikZ 模式):

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

获得的输出:

注意:这是没有的--tikzedgelabels。使用该选项会产生损坏的图表。dot2tex 只喜欢直边,因此连接节点的弯曲曲线/边不会起作用。

所需输出:

  • 不要丑陋的\draw -(coordinate)结构。我想要 TikZ 风格的边缘标签,不要固定的绘图点。我希望布局流畅,并在画布中实现图表节点的最佳分布。

  • --tikzedgelabels不行。仅供参考,我可以在评论中看到它。

答案1

仅基于 percusse 的优秀解决方案的答案,但对样式进行了一些修改。我尝试获取更轻量的代码。我添加了一个scope用于标签的选项。我删除了它,pos=.5因为它是默认值。我删除了样式myline,并将选项放在了范围内。我利用了从同一顶点用一条路径绘制多条边的可能性。

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

在此处输入图片描述

答案2

这里有很多不同的选项。然后,您可以选择一些更专门针对树和图的库,但我建议在尝试之前先熟悉 TikZ 语言。

\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[>=stealth,%some style declarations
    myline/.style={->,blue,thick,dashed},
    mynode/.style={draw,inner sep=2mm},scale=1.5]
% Placing the nodes: you have to place them, no way to know beforehand
\node[mynode,fill=red] (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
\draw[myline] (n0) edge[bend left] node[pos=0.5,black,right] {entry} (n2) ;
\draw[myline] (n0) edge[bend left] node[pos=0.5,black,right] {map} (n1);
\draw[myline] (n0) edge[bend right] node[pos=0.8,black,below right,align=center] {first\_object \\object} (n3);
\draw[myline] (n4) edge[bend left] node[pos=0.8,black,right] {sub\_map}(n1);
\draw[myline] (n4) edge[bend right] node[pos=0.5,black,right] {vm\_object} (n3) ;
\draw[myline] (n3) edge[loop right] node[pos=0.5,black,right] {backing\_object} () ;
\draw[myline] (n1) edge node[pos=0.5,black,right,align=center] {root\\header} (n2);
\draw[myline] (n2) edge[loop right,min distance =1 cm,out=10,in=-10] node[pos=0.5,black,right,align=center] {prev\\next\\right\\left} (n2) ;
\draw[myline] (n2) edge[out=30,in=20,looseness=1.8] node[pos=0.5,black,right] {object} (n4) ;
\end{tikzpicture}
\end{document}

绘制完成后,我使用了 1.5 的缩放比例使其更开放一些,虽然这不是必需的,但在我看来看起来更好。

在此处输入图片描述

答案3

我的回答试图解释为什么@soze 得到那么奇怪的结果。

首先,当您在 dot 中定义颜色时,您必须使用与 xcolor 相同的语法,因此:

fillcolor="grey75" 错误 => fillcolor="gray!75"

color="darkorchid3" 又错了 => color="DarkOrchid3"

另一件事:record形状给我每个节点的错误,而使用形状时rectangle不会出现任何问题。

我调用graph.dot@soze 文件进行了修改:

digraph G
{
  edge [fontname="Helvetica",fontsize="10",labelfontname="Helvetica",labelfontsize="10"];
  node [fontname="Helvetica",fontsize="10",shape=rectangle];
  Node1 [label="faultstate",height=0.2,width=0.4,color="black", fillcolor="gray!75", 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"];
}

使用以下方法编译:

dot2tex -ftikz -tverbatim graph.dot > graph.tex
pdflatex graph.tex

我得到(没有错误):

在此处输入图片描述

相关内容