并行流程图:连接节点、箭头路由和对齐

并行流程图:连接节点、箭头路由和对齐

从 GraphViz 过渡到 TikZ 让我很头疼......

我的任务是生成以下各种流程图:

图像

具体来说,我需要一种方法来定位共享边界的节点(最好与它们的宽度和高度无关),同时遵循网格。解释如何绘制表示节点分组的括号,以及如何绘制端点不重合(最好不指定精确坐标或角度)或与特定列对齐的正交箭头(如箭头)可获得额外加分load -> add

答案1

主要请求有三点:

  1. 一种定位共享边界的节点的方法。这里的一种可能性是使用键node distancepositioning库。例如:

    \documentclass{standalone}
    \usepackage{tikz}
    \usetikzlibrary{positioning}
    
    \begin{document}
    
    \begin{tikzpicture}[every node/.style={draw}]
    \node (a) {A};
    \node[right=of a] (b) {B};
    \node[right=of b] (c) {C};
    \begin{scope}[yshift=-1cm,node distance=-\pgflinewidth,every node/.append style={fill=blue!20}]
    \node (a) {A};
    \node[right=of a] (b) {B};
    \node[right=of b] (c) {C};
    \end{scope}
    \end{tikzpicture}
    
    \end{document}
    

    在此处输入图片描述

  2. 如何绘制端点不重合(最好不指定精确的坐标或角度)或与特定列对齐的正交箭头。这里的主要工具是垂直坐标系的隐式语法。表达式( p |- q )( q -| p )。例如,(0,1 |- 2,3)(2,3 -| 0,1)都产生与 相同的结果(0,3);以下示例展示了此语法的实际应用:

    \documentclass{standalone}
    \usepackage{tikz}
    
    \begin{document}
    
    \begin{tikzpicture}
    \node at (0,0) (a) {A};
    \node at (2,2) (b) {B};
    \node at (4,-1) (c) {C};
    \node at (4,-2) (d) {D};
    
    \draw[red] (a) |- (b);
    \draw[blue] (a) -| (b);
    \draw[green] (c) -- (a|-c) -- (a|-d) -- (d);
    \end{tikzpicture}
    
    \end{document}
    

    在此处输入图片描述

  3. 如何绘制表示节点分组的括号。这里的想法是使用装饰;特别是库brace提供的装饰decorations.pathreplacing。一个小例子:

    \documentclass{standalone}
    \usepackage{tikz}
    \usetikzlibrary{decorations.pathreplacing}
    
    \begin{document}
    
    \begin{tikzpicture}
    \node (a) {A};
    \node at (2,2) (b) {B};
    \node at (4,0) (c) {C};
    \draw[decorate,decoration=brace] (a) -- (b);
    \draw[decorate,decoration=brace] (b) -- (c);
    \draw[decorate,decoration={brace,mirror}] (a) -- (c);
    \end{tikzpicture}
    
    \end{document}
    

    在此处输入图片描述

结合这些想法,再定义一些节点的样式,就可以生成原始图表了。完整代码:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{calc,positioning,arrows,decorations.pathreplacing}

\definecolor{myblue}{RGB}{170,223,249}
\begin{document}

\begin{tikzpicture}[
  >={stealth'},
  every node/.style={node distance=-\pgflinewidth},
  exx/.style={rectangle,draw,fill=gray!30,text width=0.9cm,align=center,font=\ttfamily},
  sblue/.style={rectangle,rounded corners,draw,fill=myblue,text width=1.25cm,
    align=center,text height=9pt,text depth=3pt,font=\sffamily},
  mtext/.style={text width=4cm,align=left,text height=9pt,text depth=3pt,font=\ttfamily}
]

% the upper eax,..., edx nodes
\node[exx] (eax) {\%eax};
\node[exx,right= of eax] (ebx) {\%ebx};
\node[exx,right= of ebx] (ecx) {\%ecx};
\node[exx,right= of ecx] (edx) {\%edx};

% the vertical blue nodes
\node[sblue,below right = 10pt of edx] (sadd) {s\_addr};
\node[sblue,below = of sadd] (sdata) {s\_data};
\node[sblue,below = of sdata] (load) {load};
\node[sblue,below = of load] (add) {add};
\node[sblue,below = of add] (sub) {sub};
\node[sblue,below = of sub] (jne) {jne};

% some vertical nodes to place text to the right of the blue nodes
\node[mtext,right = 20pt of sadd] (tsadd) {};
\node[mtext,below = of tsadd] (tsdata) {};
\node[mtext,below = -9pt of tsadd] {movl \%eax,(\%ecx)};
\node[mtext,right = 20pt of load] (tload) {movl (\%ebx),\%eax};
\node[mtext,below = of tload] (tadd) {addl \$1,\%eax};
\node[mtext,below = of tadd] (tsub) {subl \$1,\%edx};
\node[mtext,below = of tsub] (tjne) {jne loop};

% the lower eax,..., edx nodes
\node[exx,below left = 10pt of jne] (edx1) {\%edx};
\node[exx,left= of edx1] (ecx1) {\%ecx};
\node[exx,left= of ecx1] (ebx1) {\%ebx};
\node[exx,left= of ebx1] (eax1) {\%eax};

% the straight lines with arrow tips
\draw[->] (eax) |- (sdata);
\draw[->] (ebx) -- (ebx1);
\draw[->] (ecx) -- (ecx1);
\draw[->] (edx) |- (sub.170);
\draw[->] (sub.190) -| (edx1);
\draw[*->] (ecx|-sadd) |- (sadd);
\draw[*->] (ebx|-load.170) |- (load.170);
\draw[->] (load.190) -- (eax|-load.190) -- (eax|-add.170) -- (add.170);
\draw[->] (add.190) -| (eax1);

% the curved arrows
\draw[->] (sadd.355) to[out=-30,in=30] (sdata.5);
\draw[->] (sadd.0) to[out=-30,in=30] (load.350);
\draw[->,dashed] (sdata.355) to[out=-30,in=30] (load.5);
\draw[->] (sub.0) to[out=-30,in=30] (jne.0);

% the brace
\draw[decorate,decoration=brace] ( $(sadd.north)!.35!(tsadd.north) $ ) -- ( $(sdata.south)!.35!(tsdata.south) $ );

\end{tikzpicture}

\end{document}

在此处输入图片描述

相关内容