我正在尝试绘制一个 FSM,其中一些状态节点包含树。为了实现这一点,我使用了范围,正如我的问题的答案中所建议的那样最后一个问题。
我想将状态节点相对于彼此定位,以期获得清晰对齐的图像,如下所示:
但是,如果我将状态节点彼此相对定位,则在它们适合包含树的范围之后,该范围的内容不会随周围的状态节点移动。
我尝试像这样定位范围本身:\begin{scope}[-, right of=q1, local bounding box=tree2]
,但它似乎不起作用,只会导致节点转移到奇数位置。
在我当前的解决方法中(代码粘贴在下面),我将状态节点内的每个小树中的根节点相对于另一个状态节点进行定位,但结果却是扭曲和丑陋的:
实现对齐的正确/最漂亮的方法是什么?
我的完整代码:
\documentclass{scrartcl}
\usepackage{tikz}
\usetikzlibrary{automata, positioning, arrows, fit}
\pgfdeclarelayer{background}
\pgfdeclarelayer{foreground}
\pgfsetlayers{background, main, foreground}
\tikzset{
->, % makes the edges directed
>=stealth', % makes the arrow heads bold
node distance=3cm, % specifies the minimum distance between two nodes. Change if necessary.
every state/.style={thick, fill=gray!10, inner sep=0}, % sets the properties for each 'state' node
every scope/.style={level distance = 0.8 cm},
initial text=$ $, % sets the text that appears on the start arrow
}
\begin{document}
% The problematic figure
\begin{figure}
\begin{tikzpicture}
\node[state, initial] (q1) {$ \{ q_I \} $};
\begin{scope}[-, local bounding box=tree2]
\begin{pgfonlayer}{foreground}
\small
\node[right of=q1] {$ \{ q_I, f \} $}
child {node {$ \{ q_I \} $}};
\end{pgfonlayer}
\end{scope}
\node[state, fit=(tree2)] (q2) {};
\node[state, right of=q2] (q3) {$ \{ f \} $!};
\begin{scope}[-, local bounding box=tree4]
\begin{pgfonlayer}{foreground}
\small
\node[below of=q3] {$ \{ q_I, f, g, h, i \} $}
child {node {$ \{ q_I \} $}}
child {node {$ \{ f, g, h \} $}
child {node {$ \{ g \} $}}
child {node {$ \{ h \} $}}
};
\end{pgfonlayer}
\end{scope}
\node[state, fit=(tree4)] (q4) {};
\node[state, accepting, left of=q4] (q5) {$q_5$};
\draw (q1) edge[loop above] node{0} (q1)
(q1) edge[above] node{1} (q2)
(q2) edge[loop above] node{1} (q2)
(q2) edge[bend left, above] node{0} (q3)
(q3) edge[bend left, below] node{0,1} (q2)
(q3) edge[bend left, right] node{1} (q4)
(q4) edge[above] node{0} (q5);
\end{tikzpicture}
\end{figure}
% How it should look like with "ordinary" state nodes
\begin{figure}
\begin{tikzpicture}
\node[state, initial] (q1) {$ \{ q_I \} $};
\node[state, right of=q1] (q2) {$q_2$};
\node[state, right of=q2] (q3) {$ \{ f \} $!};
\node[state, below of=q3] (q4) {$q_4$};
\node[state, accepting, left of=q4] (q5) {$q_5$};
\draw (q1) edge[loop above] node{0} (q1)
(q1) edge[above] node{1} (q2)
(q2) edge[loop above] node{1} (q2)
(q2) edge[bend left, above] node{0} (q3)
(q3) edge[bend left, below] node{0,1} (q2)
(q3) edge[right] node{1} (q4)
(q4) edge[above] node{0} (q5);
\end{tikzpicture}
\end{figure}
\end{document}
答案1
代码中的所有内容都按预期运行,但并非如您所愿。当您说
\node[right of=q1] {$ \{ q_I, f \} $}
child {node {$ \{ q_I \} $}};
这将使父母节点右侧的节点q1
,以及不是完整的树。如果您想将完整的树放在 的右侧q1
,您可以例如将其存储在\savebox
这样就可以安全地嵌套。
\documentclass{scrartcl}
\usepackage{tikz}
\usetikzlibrary{automata, positioning, arrows, fit}
\pgfdeclarelayer{background}
\pgfdeclarelayer{foreground}
\pgfsetlayers{background, main, foreground}
\tikzset{
->, % makes the edges directed
>=stealth', % makes the arrow heads bold
node distance=3cm, % specifies the minimum distance between two nodes. Change if necessary.
every state/.style={thick, fill=gray!10, inner sep=0}, % sets the properties for each 'state' node
every scope/.style={level distance = 0.8 cm},
initial text=$ $, % sets the text that appears on the start arrow
}
\newsavebox\TreeOne
\newsavebox\TreeTwo
\begin{document}
\savebox{\TreeOne}{\tikz[font=\small,-]{\node {$ \{ q_I, f \} $}
child {node {$ \{ q_I \} $}};}}
\savebox{\TreeTwo}{\tikz[font=\small,-]{\node {$ \{ q_I, f, g, h, i \} $}
child {node {$ \{ q_I \} $}}
child {node {$ \{ f, g, h \} $}
child {node {$ \{ g \} $}}
child {node {$ \{ h \} $}}
};}}
% The problematic figure
\begin{figure}
\begin{tikzpicture}
\node[state, initial] (q1) {$ \{ q_I \} $};
\node[state,right of=q1] (q2) {\usebox\TreeOne};
\node[state, right of=q2] (q3) {$ \{ f \} $!};
\node[state,below of=q3] (q4) {\usebox\TreeTwo};
\node[state, accepting, left of=q4] (q5) {$q_5$};
\draw (q1) edge[loop above] node{0} (q1)
(q1) edge[above] node{1} (q2)
(q2) edge[loop above] node{1} (q2)
(q2) edge[bend left, above] node{0} (q3)
(q3) edge[bend left, below] node{0,1} (q2)
(q3) edge[bend left, right] node{1} (q4)
(q4) edge[above] node{0} (q5);
\end{tikzpicture}
\end{figure}
% How it should look like with "ordinary" state nodes
\begin{figure}
\begin{tikzpicture}
\node[state, initial] (q1) {$ \{ q_I \} $};
\node[state, right of=q1] (q2) {$q_2$};
\node[state, right of=q2] (q3) {$ \{ f \} $!};
\node[state, below of=q3] (q4) {$q_4$};
\node[state, accepting, left of=q4] (q5) {$q_5$};
\draw (q1) edge[loop above] node{0} (q1)
(q1) edge[above] node{1} (q2)
(q2) edge[loop above] node{1} (q2)
(q2) edge[bend left, above] node{0} (q3)
(q3) edge[bend left, below] node{0,1} (q2)
(q3) edge[right] node{1} (q4)
(q4) edge[above] node{0} (q5);
\end{tikzpicture}
\end{figure}
\end{document}