LaTeX 中传统流程图的绘制方法

发布于 2022-09-27 18:32:42

由于工作需要,经常需要在各类文档中绘制传统程序流程图。流程图当然可以在 Visio、亿图等工具进行绘制,截图(位图,不推荐)或是导出为 PDF (矢量图,推荐)后,再通过graphicx 宏包的\includegraphics命令插入到 LaTeX 实现排版。这是一种简单直接的方法,但这种方法会存在如下问题

  • 需要额外的软件支持,降低了文档的独立性。
  • 字体、字号无法与正文匹配,整体效果不协调。
  • 缩放时字号会产生变化,无法满足字号比正文小1号的常规要求。
  • 不便后期修改、编辑和维护。

因此,在 LaTeX 中直接使用 TikZ 工具绘制流程图,是一个相对较好的选择。

直接绘制

流程图的基本形状有矩形、菱形、平行四边形、圆角矩形等。可以使用TikZ的\node命令布置这些形状结点,然后绘制对应流程线就可以实现流程图的绘制。

为绘制不同形状的结点,可以为\node命令的可选参数中设置rectanglediamondtrapeziumrounded corners等绘制属性。

显然,直接用 TikZ 代码进行流程图绘制是一个比较烦琐的过程,并且不符合 LaTeX 内容与格式分离的基本思想。同时,当有多个流程图需要绘制时,代码过于冗余,不便维护,代码的复用性也较差,不同流程图也容易产生不一致现象。

使用flowchart宏包绘制

为简化流程图的绘制代码,可以引入合适的 LaTeX 宏包进行流程图绘制。一个比较方便的宏包是flowchart宏包,它提供了如下基本的流程图形状:

image.png

显然,该宏包提供的基本流程图形状不能完全符合我国的绘制习惯。关于该宏包的使用细节,请在命令行用命令查阅其使用说明书。

设置node样式绘制

当然,可以将\node命令的可选参数中的rectanglediamondtrapeziumrounded corners等绘制属性用tikzset命令定义为绘图样式,以实现代码的简化和代码的复用。在 Brent Longborough [1] 中,给出了使用这一方式的绘制样例和实现代码。

自定义宏包绘制

根据LaTeX内容与格式分离的基本思想,显然将\tikzset样式定义及其它的设置封装为宏包,使用起来则更为方便。在完成这一封装之前,笔者刚好阅读了tikz-imagelabels 宏包的源代码,发现其key-value实现思路非常值得借鉴。因此,基于 Brent Longborough [1] 的代码,结合 tikz-imagelabels 宏包的key-value思路,笔者设计与制作了tikz-flowchart 宏包,以便在 LaTeX 中用 TikZ 实现流程图绘制,详见 [2]。

tikzpicture环境中,使用该宏包绘制流程图的基本过程是:

  1. \flowchartset命令设置全局(导言区)或局部绘制参数。
  2. 使用类似\node proc, join {$k -= 1$};命令采用proctestioterm各个node样式参数分别布置需要的流程框结点。
  3. 使用类似\node coord, right=0.8 of t1 {}; cmark{1}命令采用coord样式布置其它需要的坐标点(用于流程线的转接)。
  4. 使用类似\path (t1.south) to node [near start, xshift=1em] {$y$} (p2);命令进行流程线条件标注。
  5. 使用类似\draw norm -- (p2);命令绘制流程线。

个人建议在绘制流程前最好先用纸和笔绘制一个草图,然后再用tikz-flowchart宏包进行绘制,如下图是一个素数判断的流程图草图:

image.png

根据该草图可以使用 LaTeX 代码绘制如下流程图:

\documentclass[margin=10pt]{standalone}
% 支持中文
\usepackage{ctex}
% 流程图绘制宏包
\usepackage{tikz-flowchart}

\begin{document} %在document环境中撰写文档

% 可以局部更改各参数
\flowchartset{
  proc fill color = orange!10, % 顺序处理框填充颜色(默认取白色)
  test fill color = green!30, % 判断框填充颜色(默认取白色)
  io fill color = blue!30, % 输入/输出框填充颜色(默认取白色)
  term fill color = red!30, % 开始/结束框填充颜色(默认取白色)
  proc text width = 6em, % 顺序处理框宽度(默认取8em)
}

\begin{tikzpicture}
  % 布置结点单元
  \node [term] (st) {开始};
 \node [proc, join] (p1) {\verb|int divisor|};
  \node [test, join] (t1) {\verb|n <= 1|};
  \node [proc, ] (p2) {\verb|divisor = 2|};
  % 可以根据需要指定结点当前属性(如文字宽度)
  \node [test, text width = 10em, join] (t2) {\\verb|divisor * divisor <= n|};
  \node [test, text width = 8em] (t3) {\verb|n % divisor == 0|};
  \node [proc, text width = 6em] (p3) {\verb|divisor++|};
  \node [term, below = 1.6 of p3] (end) {结束};
  \node [proc, left = 4.8 of t2] (p4) {\verb|return 0|};
  \node [proc, right = 3.5 of p3] (p5) {\verb|return 0|};
  \node [proc, right = 5.8 of t3] (p6) {\verb|return 1|};

  % 布置用于连接的坐标结点,同时为其布置调试标记点。
  \node [coord] (c1) at ($(p2.south)!0.5!(t2.north)$)  {}; \cmark{1}
  \node [coord, below = 0.25 of p3] (c2)  {}; \cmark{2}
  \node [coord, above = 0.5 of end] (c3) {};  \cmark{3}
  \node [coord, left = 0.5 of t2] (ct) {};  \cmark{t}
  \node [coord] (c4) at (c3 -| p5)  {}; \cmark{4}
  \node [coord] (c5) at (c2 -| ct)  {}; \cmark{5}

  % 判断框连线,每次绘制时,先绘制一个带有一个固定
  % 位置标注的路径(path),然后再绘制箭头本身(arrow)。
  \path (t1.south) -- node [near start, right] {$N$} (p2.north);
  \draw [norm] (t1.south) -- (p2.north);
  \path (t1.west) -| node [near start, above] {$Y$} (p4.north);
  \draw [norm] (t1.west) -| (p4.north);

  \path (t2.south) -- node [near start, right] {$Y$} (t3.north);
  \draw [norm] (t2.south) -- (t3.north);
  \path (t2.east) -| node [near start, above] {$N$} (p6.north);
  \draw [norm] (t2.east) -| (p6.north);

  \path (t3.south) -- node [near start, right] {$N$} (p3.north);
  \draw [norm] (t3.south) -- (p3.north);
  \path (t3.east) -| node [near start, above] {$Y$} (p5.north);
  \draw [norm] (t3.east) -| (p5.north);

  % 其它连线
  \draw [norm](p3.south) |- (c5) |- (c1);
  \draw [norm](p4.south) |- (c3);
  \draw [norm](p4.south) |- (c3) -- (end);
  \draw [norm](p5.south) -- (c4);
  \draw [norm](p6.south) |- (c3);
  \draw [norm](p6.south) |- (c3) -- (end);
\end{tikzpicture}

\end{document}

image.png

关于tikz-flowchart宏包的使用细节,请参阅中的相关文档说明及使用 LaTeX 样例代码。

更多精品图在这里:https://www.latexstudio.net/index/details/index/mid/356.html

Happy TikZing!

参考链接
[1] http://www.texample.net/tikz/examples/author/brent-longborough/
[2] https://github.com/registor/tikz-flowchart/

2 条评论

发布
问题