我想知道如何以最小的努力绘制这样的路径图。
答案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.3
或0.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); }
图表中最复杂的箭头是F1和F3;我们希望此箭头精确地锚定在右中部,并弯曲。我们可以通过指定“ 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 网”,如果你按照这个例子做,你就可以轻松地做这样的事情: