1

While writing some code that generates TikZ code for displaying an automaton, I encounter the following issue: with the same label annotation, namely 'edge[bend angle=18,bend right] node[below=0,sloped]', the position of the label depends on the fact that some source/destination state is accepting or not: on the next figure, case b is wrongly positioned: is there a way to have some uniform command for positioning the label correctly, no matter whether the source/destination states are accepting or not ? Is it possible that this is a bug in TikZ (other positioning that I tried out were not sensitive to the fact that the source/destination states were accepting or not).

\documentclass{article}
\usepackage{tikz} \usetikzlibrary{arrows,automata}

\begin{document}
\begin{tikzpicture}[->,>=stealth',shorten >=1pt,auto,semithick]

\begin{scope}
\node[state] (1a) at (1cm,1cm) {1a};
\node[state] (2a) at (1cm,3cm) {2a};
\path
(1a) edge[bend angle=18,bend right] node[below=0,sloped] {$=$} (2a);
\end{scope}

\begin{scope}[xshift=2cm]
\node[state,accepting] (1b) at (1cm,1cm) {1b};
\node[state]           (2b) at (1cm,3cm) {2b};
\path
(1b) edge[bend angle=18,bend right] node[below=0,sloped] {$=$} (2b);
\end{scope}

\begin{scope}[xshift=4cm]
\node[state]           (1c) at (1cm,1cm) {1c};
\node[state,accepting] (2c) at (1cm,3cm) {2c};
\path
(1c) edge[bend angle=18,bend right] node[below=0,sloped] {$=$} (2c);
\end{scope}

\begin{scope}[xshift=6cm]
\node[state,accepting] (1d) at (1cm,1cm) {1d};
\node[state,accepting] (2d) at (1cm,3cm) {2d};
\path
(1d) edge[bend angle=18,bend right] node[below=0,sloped] {$=$} (2d);
\end{scope}

\end{tikzpicture}

\end{document}

enter image description here

2 Answers 2

1

The reason why this happens is that for sloped paths TikZ tries to intelligently interpret keys like above and so on. To switch this off, you can use the allow upside down key.

\documentclass{article}
\usepackage{tikz} 
\usetikzlibrary{arrows,automata}

\begin{document}
\begin{tikzpicture}[->,>=stealth',shorten >=1pt,auto,semithick,
    allow upside down]

\begin{scope}
\node[state] (1a) at (1cm,1cm) {1a};
\node[state] (2a) at (1cm,3cm) {2a};
\path
(1a) edge[bend angle=18,bend right] node[below=0,sloped] {$=$} (2a);
\end{scope}

\begin{scope}[xshift=2cm]
\node[state,accepting] (1b) at (1cm,1cm) {1b};
\node[state]           (2b) at (1cm,3cm) {2b};
\path
(1b) edge[bend angle=18,bend right] node[below=0,sloped] {$=$} (2b);
\end{scope}

\begin{scope}[xshift=4cm]
\node[state]           (1c) at (1cm,1cm) {1c};
\node[state,accepting] (2c) at (1cm,3cm) {2c};
\path
(1c) edge[bend angle=18,bend right] node[below=0,sloped] {$=$} (2c);
\end{scope}

\begin{scope}[xshift=6cm]
\node[state,accepting] (1d) at (1cm,1cm) {1d};
\node[state,accepting] (2d) at (1cm,3cm) {2d};
\path
(1d) edge[bend angle=18,bend right] node[below=0,sloped] {$=$} (2d);
\end{scope}

\end{tikzpicture}

\end{document}

enter image description here

This is off-topic, but in order to shorten your code you could use a loop.

\documentclass{article}
\usepackage{tikz} 
\usetikzlibrary{arrows.meta,automata}

\begin{document}
\begin{tikzpicture}[->,>=Stealth,shorten >=1pt,auto,semithick]
\foreach \X [count=\Y] in {a,...,d}
{
 \ifodd\Y
  \path  (2*\Y,1)  node[state]  (1\X) {1\X};
 \else 
  \path  (2*\Y,1)  node[state,accepting]  (1\X) {1\X};
 \fi
 \ifnum\Y<3
  \path   (2*\Y,3) node[state](2\X) {2\X};
 \else
  \path   (2*\Y,3) node[state,accepting](2\X) {2\X};
 \fi
 \path
 (1\X) edge[bend angle=18,bend right] node[below=0,sloped,
 allow upside down] {$=$} (2\X);
}
\end{tikzpicture}
\end{document}

enter image description here

Whether or not these ways of shortening codes make sense always depends on what one ultimately has in mind.

2
  • Since my TikZ code is generated by a program the question of shortening TikZ code is not so important to me (but if an can avoid case analysis whether some states are accepting or not, this makes my code generator a bit simpler). Commented May 2, 2020 at 17:22
  • The upside down key is also dependent of whether the source/destination are accepting or not for other label annotation. Commented May 5, 2020 at 13:30
0

I don't know, why this happen, however, using quotes library, set auto=right and write edge ["$=$"] solve your problem. Of course, you need to define arrows and edges quotes accordingly (see MWE below). With using TikZ library chains make the code shorter:

    \begin{scope}[nodes={state, on chain}]
\node (s11)                 {1a};
\node (s12)                 {1b};
\node (s13) [accepting]     {1c};
\node (s14) [accepting]     {1d};
%
\node (s21) [above=of s11]  {2a};
\node (s22) [accepting]     {2b};
\node (s23)                 {1c};
\node (s24) [accepting]     {1d};
    \end{scope}
    \foreach \i in {1,...,4}
{
\path   (s1\i) edge["$=$"] (s2\i);
}
    \end{tikzpicture}
\end{document}

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .