1

I noticed that arrows in the below MWE point to the wrong side of the nodes if I draw them with a foreach statement, but not if I write the same drawing command manually. What is wrong?

\documentclass{beamer}
\usepackage{tikz}

\begin{document}
\begin{frame}
\begin{tikzpicture}[scale=1.4]
\node[draw, thick, circle, minimum size=7mm] (xA0) at (0, 0) {};
\foreach \i in {1, ..., 3}{
  \node[draw, thick, circle, minimum size=7mm] (xA\i) at (\i, 0) {};
  \node[draw, thick, circle, minimum size=7mm] (xB\i) at (\i, -1) {};
}
\node[draw, thick, circle, minimum size=7mm] (xB4) at (4, -1) {};
\foreach \i in {0, ..., 3}{
  \pgfmathsetmacro\iplusone{\i+1};
  \draw[thick, -latex] (xA\i) -- (xB\iplusone);
  \ifnum\i<3
    \draw[thick, -latex] (xA\i) -- (xA\iplusone);
  \fi
  \ifnum\i>0
    \draw[thick, -latex] (xB\i) -- (xB\iplusone);
  \fi
}
\draw[thick, -latex, red] (xA0) -- (xB1);
\end{tikzpicture}
\end{frame}
\end{document}

The goal is that the arrows point to closest end of the node without any manual computation where that point would be; just like the red arrow.

enter image description here

3
  • 1
    The reason is \pgfmathsetmacro\iplusone{\i+1}, which produces macros like 2.0, where .0 is interpreted as node anchor (the east anchor in this case). Instead of e.g. \draw[thick, -latex] (xA\i) -- (xB\iplusone); you can write \draw[thick, -latex] (xA\i) -- (xB\the\numexpr\i+1); or you could use \pgfmathtruncatemacro\iplusone{\i+1}.
    – user194703
    Apr 29, 2020 at 6:37
  • Thank you. Very insightful. Apr 29, 2020 at 8:27
  • Well, I tried to give a detailed answer in which things get explained and the red arrow stays red.
    – user194703
    Apr 29, 2020 at 8:44

2 Answers 2

1

By defining additional counter in the loops: [count=\j from 2] you can omit calculation of node positions with \pgfmathsetmacro:

\documentclass{beamer}
\usepackage{tikz}

\begin{document}
\begin{frame}
    \begin{tikzpicture}[scale=1.4,
  C/.style = {draw, thick, circle, minimum size=7mm},
arr/.style = {thick, -latex}
                        ]
]
\foreach \i [count=\j from 2] in {1,...,4}
{
  \node[C] (xA\i) at (\i, 0) {};
  \node[C] (xB\i) at (\j, -1) {};
\draw[arr] (xA\i) -- (xB\i);
}
\foreach  \i [count=\j from 2] in {1,2,3}
{
\draw[arr] (xA\i) -- (xA\j);
\draw[arr] (xB\i) -- (xB\j);
}
\end{tikzpicture}
\end{frame}
\end{document}

enter image description here

3

Welcome! The reason is \pgfmathsetmacro\iplusone{\i+1}, which produces macros like 2.0, where .0 is interpreted as node anchor (the east anchor in this case). There are many ways to fix this, either adding int to \pgfmathsetmacro, or to use \pgfmathtruncatemacro, or with \the\numexpr as e.g. in

 \draw[thick, -latex] (xA\i) -- (xB\the\numexpr\i+1);

or with the evaluate key using int. This loop avoids overpainting one arrow. Here is a code that illustrates this, a much shorter and more ergonomic code can be found below:

\documentclass{beamer}
\usepackage{tikz}

\begin{document}
\begin{frame}
\frametitle{Some foreach loop}
\begin{tikzpicture}[scale=1.4]
\node[draw, thick, circle, minimum size=7mm] (xA0) at (0, 0) {};
\foreach \i in {1, ..., 3}{
  \node[draw, thick, circle, minimum size=7mm] (xA\i) at (\i, 0) {};
  \node[draw, thick, circle, minimum size=7mm] (xB\i) at (\i, -1) {};
}
\node[draw, thick, circle, minimum size=7mm] (xB4) at (4, -1) {};
\foreach \i [evaluate=\i as \j using {int(\i+1)}]in {0,...,3}{
  \ifnum\i<3
    \draw[thick, -latex] (xA\i) -- (xA\j);
  \fi
  \ifnum\i>0
    \draw[thick, -latex] (xB\i) -- (xB\j);
    \draw[thick, -latex] (xA\i) -- (xB\j);
  \else 
    \draw[thick, -latex, red] (xA0) -- (xB1);
  \fi
}

\end{tikzpicture}
\end{frame}
\end{document}

enter image description here

The above is to explain why things happen. You do not need any of this to draw the diagram, one single loop is enough.

\documentclass{beamer}
\usepackage{tikz}
\begin{document}
\begin{frame}
\begin{tikzpicture}[scale=1.4]
\path[nodes={draw, thick, circle, minimum size=7mm},
    every edge/.append style={thick, -latex}] 
 foreach \i in {0, ..., 3}{
  (\i, 0) node[] (xA\i)  {}
  (\i+1, -1) node[] (xB\i)   {}
  \ifnum\i>0
   (xA\i) edge (xB\i)
  \else
   (xA\i) edge[red] (xB\i)
  \fi
  \ifnum\i>0
   (xA\the\numexpr\i-1) edge (xA\i)
   (xB\the\numexpr\i-1) edge (xB\i)
  \fi};
\end{tikzpicture}
\end{frame}
\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 .