用最少的努力绘制路径图?

用最少的努力绘制路径图?

我想知道如何以最小的努力绘制这样的路径图。

在此处输入图片描述

答案1

这是另一个使用 的解决方案TiKZ,但不对网格进行操作。[根据评论,对其进行了一些编辑以简化代码。]

TiKZ 是一款非常棒的图表制作软件包。由于您是通过编程而不是交互方式进行操作的,因此您可以非常精确地制作图像,并包含更高级别的概念;但如果您想快速完成,则需要一些预先考虑。我将描述工作流程,以便不仅描述什么代码可以生成此图像,但要表明你可以如何设计生成该图像的代码

强制性序言

在文档的开头使用类似的内容。

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc,shapes}

\begin{document}

该命令\usetikzlibrary应始终伴随\usepackage{tikz},因为总会有一些库需要使用。在我们的例子中,我们想要calc计算相对位置,并shapes获取例如 椭圆形节点。出色的TiKZ 和 PGF 的文档将始终让您知道需要哪些库来将东西放入图片中。

定义样式

你的照片有好几张节点(方框、椭圆)具有共同的特征。我们定义了不同样式的节点,这些节点或多或少地重复了它们。你应该比我更聪明地命名它们。所有这些都是描述它们应该如何显示的设置。(“”inner sep参数定义了边框与文本之间的距离,与默认值不同;所有值都是通过反复试验获得的。)

\tikzstyle{input}=[font=\scriptsize\sffamily\bfseries]
\tikzstyle{yelbox}=[rectangle,draw=black,fill=yellow,
                    font=\scriptsize\sffamily\bfseries,inner sep=6pt]
\tikzstyle{yelball}=[ellipse,draw=black,fill=yellow,
                     font=\scriptsize\sffamily\bfseries,inner sep=-1pt]
\tikzstyle{whiteball}=[ellipse,draw=black,fill=white,
                       font=\scriptsize\sffamily\bfseries,inner sep=-1pt]

还有不同类型的重复箭头:我们也为它们定义了样式。(这里,“ latex”只是三角箭头的名称;我stealth自己更喜欢使用“ ”,但在这种情况下我复制了您的图像。)

\tikzstyle{arr}=[-latex,black,line width=1pt]
\tikzstyle{doublearr}=[latex-latex,black,line width=1pt]
\tikzstyle{bluearr}=[-latex,blue,line width=1pt]

临时命令

您的某些节点具有标签多行等功能。我们将制作一个宏来完美地生成这些标签。默认宽度是3em通过反复试验获得的。

\newcommand\nodelabel[3][3em]{\parbox{#1}{\centering #2 \\ #3 }}

为了更快地制作图像原型,我希望快速控制垂直方向上节点的间距,这是变化最大(也是最不均匀)的地方。我将定义一个可以调整的缩放因子(设置为负数,以更改正常惯例,TiKZ使较大的数字对应较大的向下距离)。

\newcommand\vertspacing{-1.5}

构建图片

开始了:

\begin{tikzpicture}[scale=0.8]

通过反复试验,我们找到了适合一页的缩放比例。您也可以独立控制 x 缩放和 y 缩放,但我没有这样做,因为无论如何我都想反转坐标的方向,并且可以用另一种方式进行缩放。(您可以使用负 y 缩放来做到这一点,但它会弄乱节点的角,例如我将在下面使用的.north和。).south

在构建此程序时,您应该一直重新编译以查明放置是否工作正常,并调整节点的样式以使其外观更好。但不要花太多时间让一切都完美;先让事情几乎正确,然后在最后让它们完美。

构建 E 节点

这些是具有左侧和右侧的标签。我们将为它们命名,以便在绘制箭头时可以引用节点。

我目测了节点的相对垂直间距;当间隙较大时,我确定增量间距为0.30.4。水平位置也目测(并略微调整),使用负/正值以确保对称性。

\foreach \label/\row in
    {E16/1, E17/2.3, E14/3.3, E15/4.7, E18/5.7, E19/7} 
        \node [input] (\label) at ($(-7.5,\vertspacing*\row)$) {\label};

\foreach \label/\row in
    {E10/1, E11/2.3, E8/3.3, E9/4.7, E12/5.7, E13/7}
        \node [input] (\label) at ($(7.5,\vertspacing*\row)$) {\label};

分配(\label)我们稍后将使用的节点的名称;告诉{\label}应该用什么标签打印节点。

构建 V 节点

这些是具有标签,即节点的名称。它们也有单独的标题,分别是Axxx#样式部分是它们打印的标签。它们具有与输入节点类似的垂直定位。我们使用\nodelabel之前定义的宏来生成它们的标签。

\foreach \title/\label/\row in
    {GSSC1/V16/1, GSCR1/V17/2.3, ASCC1/V14/3.3, ASCB1/V15/4.7, AAET1/V18/5.7, AAMA1/V19/7}
        \node [yelbox] (\label) at ($(-5,\vertspacing*\row)$) {\nodelabel{\title}{\label}};

\foreach \title/\label/\row in
    {GSSC2/V10/1, GSCR2/V11/2.3, ASCC2/V8/3.3, ASCB2/V9/4.7, AAET2/V12/5.7, AAMA2/V13/7}
        \node [yelbox] (\label) at ($(5,\vertspacing*\row)$) {\nodelabel{\title}{\label}};

我们使用标签的一部分来命名节点,因为它更短,并且它们与相邻节点的名称相匹配节点;这以后会很方便。

构建 F 节点

这些是椭圆形节点,F标签。这又类似于节点。它们的垂直定位基本上是在节点;这是手工计算的,不过如果你更聪明一点,也可以TiKZ自己计算。宽度的3.5em选择是为了使椭圆具有与原始图表大致相同的形状。

\foreach \title/\label/\row in
    {GSC/F1/1.65/4, ASC/F2/4/4, AA/F3/6.35/4}
        \node [whiteball] (\label) at ($(-2,\vertspacing*\row)$) 
                          {\nodelabel[3.5em]{\title \\ I}{\label}};

\foreach \title/\label/\row in
    {GSC/F4/1.65, ASC/F5/4, AA/F6/6.35}
        \node [yelball] (\label) at ($(2,\vertspacing*\row)$) 
                          {\nodelabel[3.5em]{\title \\ II}{\label}};

构建 D 节点

对于每一个F右侧的节点上有一个节点上方和右侧。我们放置一个每个节点相对于相应的节点处于固定位置F节点。

\foreach \label/\parent/\row in
    {D4/F4/.7, D5/F5/3, D6/F6/5.4}
        \node [input] (\label) at ($(\parent) + (0.5,-1*\vertspacing)$) {\label};

如果你在这里添加来结束图片\end{tikzpicture}\end{document},它将看起来像这样:

部分完成的图表

箭头绘制

在这里,我们利用节点的标签方案。在这种情况下,由于整个图中的标签相当统一,我们基本上只需要说“连接每个节点与适当的节点“,同样地,对于节点到F节点(具有适当样式的箭头)。

\foreach \j in {16, 17, 14, 15, 18, 19, 10, 11, 8, 9, 12, 13}
    \draw [bluearr] (E\j) to (V\j);

\foreach \j in {4, 5, 6}
    \draw [bluearr] (D\j) to (F\j);

F节点没有这样简单的命名方案,但没关系;我们只需指定完整的节点名称。此外,我们希望箭头精确地终止于框垂直边的中间;我们通过根据需要为这些节点指定“ east”或“ west”锚点来实现这一点。

\foreach \F/\Va/\Vb in  {F1/V16/V17, F2/V14/V15, F3/V18/V19}
        { \draw [arr] (\F) to (\Va.east); \draw [arr] (\F) to (\Vb.east); }

\foreach \F/\Va/\Vb in  {F4/V10/V11, F5/V8/V9, F6/V12/V13}
        { \draw [arr] (\F) to (\Va.west); \draw [arr] (\F) to (\Vb.west); }

图表中最复杂的箭头是F1F3;我们希望此箭头精确地锚定在右中部,并弯曲。我们可以通过指定“ east”锚点,并指定箭头应弯曲的角度(相对于正东)来实现这一点。这些角度是通过目测选择的。

\draw [doublearr, out=-60, in=60] (F1.east) to (F3.east);

其他箭头相当简单,并使用迄今为止描述的技术。

\draw [doublearr] (F1) to (F2);
\draw [doublearr] (F2) to (F3);
\draw [arr]       (F1) to (F5.north);
\draw [arr]       (F1) to (F6.north);
\draw [arr]       (F2) to (F4.west);
\draw [arr]       (F2) to (F6.west);
\draw [arr]       (F3) to (F4.south);
\draw [arr]       (F3) to (F5.south);

整理起来

就是这样!

\end{tikzpicture}
\end{document}

得到的图为:

完整图表

这是对原作相当忠实的再现,如果我可以这么说的话;而且我花了一个小时的时间从原作开始制作它 — — 其中一部分时间是花在查找我制作过程中被遗忘的 TiKZ 片段上!

答案2

看着那(这TikZ 手册中的第二个教程:它的标题是“哈根的 Petri 网”,如果你按照这个例子做,你就可以轻松地做这样的事情:

在此处输入图片描述

相关内容