我正在尝试使用 TikZ 和自动机包绘制自动机,我正在使用 overlay-beamer-styles 逐张修改该自动机。我正在更改的一件事是将哪些节点标记为接受状态。但是,更改此设置会导致所有内容略微移动,这在从一张幻灯片切换到另一张幻灯片时看起来很糟糕。我该如何解决这个问题?我希望所有边缘、节点标签等都保持在相同的位置,并且只有节点的边框发生变化,最好通过添加/删除内线来实现。
这是一个最小工作示例:
\documentclass{beamer}
\usepackage{tikz}
\usetikzlibrary{
automata,
overlay-beamer-styles}
\tikzset{
accepting on/.style={alt=#1{accepting}{}}
}
\begin{document}
\begin{frame}{}
\begin{tikzpicture}[initial text=,auto,state/.append style={minimum size=1.5cm}]
\node[state,initial,accepting on=<2>] (z0) at (0,0) {$z_0$};
\node[state,accepting on=<1>] (z1) at (2,0) {$z_1$};
\path[->] (z0) edge [loop above] node {$a$} (z0)
edge node {$b$} (z1)
(z1) edge [loop above] node {$a,b$} (z1);
\end{tikzpicture}
\end{frame}
\end{document}
输出如下:
答案1
自动机样式accepting by double
定义为
\tikzset{accepting by double/.style= {double,outer sep=.5\pgflinewidth+.3pt}} % .3pt is half double width distance
这意味着不仅增加了双线,而且由于的不同,节点的大小也会发生变化outer sep
。
outer sep
如果在不接受的覆盖上也增加,则可以避免节点在覆盖之间跳转:
\documentclass{beamer}
\usepackage{tikz}
\usetikzlibrary{
automata,
overlay-beamer-styles}
\tikzset{
accepting on/.style={alt=#1{accepting}{accepting, double=none}}
}
\begin{document}
\begin{frame}
\begin{tikzpicture}[initial text=,auto,state/.append style={minimum size=1.5cm}]
\node[state,initial,accepting on=<2>] (z0) at (0,0) {$z_0$};
\node[state,accepting on=<1>] (z1) at (2,0) {$z_1$};
\path[->] (z0) edge [loop above] node {$a$} (z0)
edge node {$b$} (z1)
(z1) edge [loop above] node {$a,b$} (z1);
\end{tikzpicture}
\end{frame}
\end{document}
答案2
ingdouble
会改变节点大小,这会导致整个 TikZ 图片有点宽和高的典型问题(跳跃的第一个实例),但在这种情况下,它也会改变循环和沿循环放置的节点(跳跃的第二个实例)。
尽管samcarter 的回答通过使不接受状态与接受状态一样大来补偿这一点(这将导致节点边界和箭头之间出现一点空白)这个答案试图通过使接受状态与不接受状态一样大来解决这个问题:
不是
double
通过路径,而是通过nfold
库来偏移它。对于圆形,这种方法非常有效。对于其他形状,这种方法可能不太有效。形状
rectangle
无法通过nfold
(然而?) 并且由于矩形是在另一个方向构建的,因此偏移量需要反转。但是我们可以添加布尔值来轻松翻转偏移量。
通过添加另一个仅绘制且没有文本的圆形节点。
如果您的所有状态都具有相同的大小和形状,这实际上是我首选的版本,否则您需要根据状态的变化情况对此进行一些调整。(不过,我们可以轻松添加一个漂亮的界面来做到这一点。)
就其当前形式而言,它非常不灵活,并且使用硬编码数字。(我们可以测量原始节点,并使标签的大小依赖于此。)
不过,当你开始使用颜色、变换或其他花哨的东西时,这可能会很容易被打破。
通过原始的
double
方式,accepting by double
但是使节点稍微小一些。这仅当节点足够大时才有效,即,不会因为文本太大而超出
minimum width
/ 。height
总的来说,我更喜欢通过 来解决nfold
,特别是如果您只使用圆圈,因为如果您自定义 s,它的干扰最小state
。
代码
\documentclass{beamer}
\usepackage{tikz}
\usetikzlibrary{automata,overlay-beamer-styles,nfold}
\makeatletter
\tikzset{offset/.code=\tikz@addmode{\pgfgetpath\tikz@temp\pgfsetpath\pgfutil@empty\pgfoffsetpath\tikz@temp{#1}}}
\makeatother
\tikzset{
accepting by offset/.style={postaction={path only, draw, offset=#1}},
accepting by label/.style={label={[circle,path only, draw, minimum size={1.5cm-(#1)}]center:}},
accepting by smaller/.style={
accepting by double,
minimum width/.expanded={\pgfkeysvalueof{/pgf/minimum width}-(\pgfkeysvalueof{/pgf/outer xsep})-.5\pgflinewidth},
minimum height/.expanded={\pgfkeysvalueof{/pgf/minimum height}-(\pgfkeysvalueof{/pgf/outer ysep})-.5\pgflinewidth}},
set accepting on/offset/.style={accepting on/.style={alt={##1{accepting by offset={#1}}{}}}},
set accepting on/label/.style={accepting on/.style={alt={##1{accepting by label={#1}}{}}}},
set accepting on/smaller/.style={accepting on/.style={alt={##1{accepting by smaller}{}}}},
set accepting on/offset=+1pt, % just a default
}
\begin{document}
\begin{frame}{Accepting by offset}
\begin{tikzpicture}[initial text=, auto, state/.append style={minimum size=1.5cm}]
\node[state,initial,accepting on=<2>] (z0) at (0,0) {$z_0$};
\node[state,accepting on=<1>] (z1) at (2,0) {$z_1$};
\path[->] (z0) edge [loop above] node {$a$} (z0)
edge node {$b$} (z1)
(z1) edge [loop above] node {$a,b$} (z1);
\end{tikzpicture}
\end{frame}
\begin{frame}{Accepting by label}
\tikzset{set accepting on/label=2pt}
\begin{tikzpicture}[initial text=, auto, state/.append style={minimum size=1.5cm}]
\node[state,initial,accepting on=<2>] (z0) at (0,0) {$z_0$};
\node[state,accepting on=<1>] (z1) at (2,0) {$z_1$};
\path[->] (z0) edge [loop above] node {$a$} (z0)
edge node {$b$} (z1)
(z1) edge [loop above] node {$a,b$} (z1);
\end{tikzpicture}
\end{frame}
\begin{frame}{Accepting by smaller}
\tikzset{set accepting on/smaller=.3pt+\pgflinewidth}
\begin{tikzpicture}[initial text=, auto, state/.append style={minimum size=1.5cm}]
\node[state,initial,accepting on=<2>] (z0) at (0,0) {$z_0$};
\node[state,accepting on=<1>] (z1) at (2,0) {$z_1$};
\path[->] (z0) edge [loop above] node {$a$} (z0)
edge node {$b$} (z1)
(z1) edge [loop above] node {$a,b$} (z1);
\end{tikzpicture}
\end{frame}
\end{document}