3

I'm getting strange behavior when using TikZ's evaluate syntax.

Why is the bottom line shorter than the other three?

See how the bottom diagonal line is shorter than the other three? This is not the desired behavior. The code for the above image is here:

\documentclass{memoir}
\usepackage{tikz}
\begin{document}

\[
\begin{tikzpicture}
    \foreach \x in {0,...,4} 
        {\node (X\x) at (0,\x) {$\bullet$};
        }
    \foreach \x in {0,...,4} 
        {\node (Y\x) at (3,\x) {$\bullet$};
        }
% start weirdness
    \draw (X0) -- (Y1);
    \foreach \x [evaluate=\x as \sx using \x+1] in {1,...,3}
    {
        \draw (X\x) -- (Y\sx);
    }
% end weirdness. 
% Comment out the above weirdness and uncomment out the following:
%   \draw (X0) -- (Y0);
%   \foreach \x [evaluate=\x as \sx using \x] in {1,...,3}
%   {
%      \draw (X\x) -- (Y\sx);
%   }
\end{tikzpicture}
\]

\end{document}

If you comment out the lines between "start weirdness" and "end weirdness" and you un-comment out the last five lines, you'll see that the problem is magically fixed: all the lines look the same.

Now all the lines are the same length.

Again, in the original code---and the associated picture at the top of this post---the desired behavior is the shorter line. The other three are undesirable. Can you help me get the desired behavior?

Thanks!

2
  • 1
    You need to wrap \x+1 into int, \foreach \x [evaluate=\x as \sx using {int(\x+1)}] in {1,...,3} { \draw (X\x) -- (Y\sx); }, since otherwise you get numbers like 2.0, where .0 is interpreted as an anchor.
    – user194703
    Dec 3, 2019 at 19:03
  • wow, thanks! If you write that as an answer, I'll select it, thus giving you points. Dec 3, 2019 at 19:44

2 Answers 2

3

As written in my comment, you need to wrap \x+1 into int

\foreach \x [evaluate=\x as \sx using {int(\x+1)}] in {1,...,3}
    {
        \draw (X\x) -- (Y\sx);
    }

since otherwise you get numbers like 2.0, where .0 is interpreted as an anchor. .0 is (in this case) coincident with the east anchor, i.e. at angle 0. Your output shows lines that connect to the east anchor of the respective Y-type nodes. You may wonder why the problem does not happen in the second loop. This is because when you say

 evaluate=\x as \sx using \x

TikZ does not need to parse the expression, and does not add .0.

\documentclass{memoir}
\usepackage{tikz}
\begin{document}

\[
\begin{tikzpicture}
    \foreach \x in {0,...,4} 
        {\node (X\x) at (0,\x) {$\bullet$};
        }
    \foreach \x in {0,...,4} 
        {\node (Y\x) at (3,\x) {$\bullet$};
        }
% start weirdness
    \draw (X0) -- (Y1);
    \foreach \x [evaluate=\x as \sx using {int(\x+1)}] in {1,...,3}
    {
        \draw (X\x) -- (Y\sx);
    }
\end{tikzpicture}   
\quad\mbox{vs.}\quad
\begin{tikzpicture}
% end weirdness. 
% Comment out the above weirdness and uncomment out the following:
    \foreach \x in {0,...,4} 
        {\node (X\x) at (0,\x) {$\bullet$};
        }
    \foreach \x in {0,...,4} 
        {\node (Y\x) at (3,\x) {$\bullet$};
        }
  \draw (X0) -- (Y0);
  \foreach \x [evaluate=\x as \sx using \x] in {1,...,3}
  {
     \draw (X\x) -- (Y\sx);
  }
\end{tikzpicture}
\]

\end{document}

enter image description here

BTW, I would avoid using \x as the loop variable since it is also used by calc, i.e. you may find other "weirdness" if you use calc with \x loops. And if you want the gaps to go away, you could just draw the nodes with TikZ.

\documentclass{memoir}
\usepackage{tikz}
\begin{document}

\[
\begin{tikzpicture}[bullet/.style={circle,fill,inner sep=2pt}]
    \path foreach \Y in {0,...,4} 
        {(0,\Y) node[bullet] (X\Y){}
         (3,\Y) node[bullet] (Y\Y) {}
        };
    \foreach \X [evaluate=\X as \Y using {int(\X+1)}] in {0,...,3}
    {
        \draw (X\X) -- (Y\Y);
    }
\end{tikzpicture}   
\]
\end{document}

enter image description here

Steven B. Segelets suggests to use \the\numexpr. This works fine but then you do not need evaluate at all.

\documentclass{memoir}
\usepackage{tikz}
\begin{document}

\[
\begin{tikzpicture}[bullet/.style={circle,fill,inner sep=2pt}]
    \path foreach \Y in {0,...,4} 
        {(0,\Y) node[bullet] (X\Y){}
         (3,\Y) node[bullet] (Y\Y) {}
        };
    \foreach \X  in {0,...,3}
    {
        \draw (X\X) -- (Y\the\numexpr\X+1);
    }
\end{tikzpicture}   
\]
\end{document}
3

I'm sure there is a tikz way of doing it, but I concluded the \x+1 needed evaluation, so since it is integral, I used \numexpr.

\documentclass{memoir}
\usepackage{tikz}
\begin{document}

\[
\begin{tikzpicture}
    \foreach \x in {0,...,4} 
        {\node (X\x) at (0,\x) {$\bullet$};
        }
    \foreach \x in {0,...,4} 
        {\node (Y\x) at (3,\x) {$\bullet$};
        }
% start weirdness
    \draw (X0) -- (Y1);
    \foreach \x [evaluate=\x as \sx using \the\numexpr\x+1\relax] in {1,...,3}
    {
        \draw (X\x) -- (Y\sx);
    }
% end weirdness. 
% Comment out the above weirdness and uncomment out the following:
%   \draw (X0) -- (Y0);
%   \foreach \x [evaluate=\x as \sx using \x] in {1,...,3}
%   {
%      \draw (X\x) -- (Y\sx);
%   }
\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 .