![如何用节点列表参数化 tikz 链图片](https://linux22.com/image/263442/%E5%A6%82%E4%BD%95%E7%94%A8%E8%8A%82%E7%82%B9%E5%88%97%E8%A1%A8%E5%8F%82%E6%95%B0%E5%8C%96%20tikz%20%E9%93%BE%E5%9B%BE%E7%89%87.png)
我想绘制几个像这样的 tikz 图片,但每行有不同数量的节点,并且不同节点之间的顶行和底行之间有箭头。
例如等等
。
我想创建一个宏,可以重复用于每次绘图。例如,该宏使用 3 个列表进行参数化,2 个列表列出顶行和底行中的节点,例如 [h_0,h_1,h_2]、[h'_0,h'_1],另一个列表是成对的列表 [(h_0,h'_0), (h_2,h'_1)] - 因此该宏将绘制两个链,然后针对每个给定对在顶行中的节点和底行中的节点之间绘制一个箭头。
我是一个 Latex 初学者,我不确定从哪里开始,或者在 Latex 中什么是合理的方法来处理这种参数化和迭代。
这是我用来绘制上图的标记:
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{arrows,chains,scopes}
\begin{document}
\begin{tikzpicture}
{[node distance=0.4cm,
start chain=going right,
every join/.style=->]
\node [on chain] (start) {$h_0$};
\node [on chain,join] {$h_1$};
\node [on chain,join] {$h_2$};
\node [on chain,join] (C1) {$h_3$};
\node [on chain, below=1cm of start] (start) {$h_0'$};
\node [on chain,join] {$h_1'$};
\node [on chain,join] {$h_2'$};
\node [on chain,join] {$h_3'$};
\node [on chain,join] (C2) {$h_4'$};
\draw[thick,<->] (C1.south east)--(C2.north west);
}
\end{tikzpicture}
\end{document}
答案1
通过三个\foreach
循环,这可以相当简单地完成。
由于该scopes
库不能很好地chain
处理在\foreach
(→ 使用 foreach 绘制带有分支的链),我使用了完整的\begin{scope}
语法。
待连接节点列表使用的语法与您的问题中要求的语法不同,即
from1/to1, from2/to2, from3/to3, …
这样做主要是因为这样更容易编写循环。不过使用嵌套列表语法也不会太难。
所有节点都有三个名称:
twoStoryChain<node content>
,例如twoStoryChainh_1
;twoStoryChain<row number>-<node content>
例如twoStoryChainI-h_1
;或twoStoryChain<row number>-<index>
,例如twoStoryChainI-0
。
如果节点是唯一的,则可以通过其内容访问节点;如果节点在行方向上是唯一的,则可以通过其行号和其内容访问节点;如果所有节点都失败(始终是唯一的),则可以通过其行号和其行索引访问节点。看看最后一张 TikZ 图片。所有解决方案都已呈现。
代码
\documentclass[tikz]{standalone}
\usetikzlibrary{arrows,chains,scopes}
\newcommand*{\twoStoryChain}[3]{% #1 = top row,
% #2 = second row,
% #3 = connected nodes
\edef\qrrRowI{#1}
\edef\qrrRowII{#2}
\edef\qrrConnectedNodes{#3}
\begin{scope}[
node distance=0.4cm,
start chain=going right,
every join/.style=->
]
\foreach \element[count=\iElement from 0] in \qrrRowI {
\ifnum\iElement=0
\node[on chain, name={twoStoryChainI-\element}, alias={twoStoryChainI-\iElement}, alias={twoStoryChain\element}] {$\element$};
\else
\node[on chain, name={twoStoryChainI-\element}, alias={twoStoryChainI-\iElement}, alias={twoStoryChain\element}, join] {$\element$};
\fi
}
%
\foreach \element[count=\iElement from 0] in \qrrRowII {
\ifnum\iElement=0
\node[on chain, name={twoStoryChainII-\element}, alias={twoStoryChainII-\iElement}, alias={twoStoryChain\element}, below=1cm of twoStoryChainI-0] {$\element$};
\else
\node[on chain, name={twoStoryChainII-\element}, alias={twoStoryChainII-\iElement}, alias={twoStoryChain\element}, join] {$\element$};
\fi
}
\end{scope}
\foreach \fromNode/\toNode in \qrrConnectedNodes {
\draw[thick, <->] (twoStoryChain\fromNode) -- (twoStoryChain\toNode);
}
}
\begin{document}
\begin{tikzpicture}
\twoStoryChain{h_0,h_1,h_2,h_3}{h_0', h_1',h_2',h_3',h_4'}{h_3/h_4'}
\end{tikzpicture}
\begin{tikzpicture}
\twoStoryChain{h_0,h_1,h_2}{h_0', h_1',h_2',h_3',h_4'}{h_1/h_2',h_2/h_4'}
\end{tikzpicture}
\begin{tikzpicture}
\twoStoryChain{h_0,h_0,h_1,h_3}{h_0,h_0,h_1,h_2,h_4}{%
h_2/h_3,% names like content
I-h_1/II-h_1,% names like content but with number of chain
I-0/II-1,% or names with an index
I-1/h_4% or mixed
}
\end{tikzpicture}
\end{document}
输出