6

I want to draw something in tikz where the range of an inner loop depends on an outer loop (by construction of the math involved). I need to differentiate between even and odd number in the inner loop, and so my first approach was to define the range \foreach \ell in {[begin],[begin+2],...,[end]} and then deal with \ell and \ell+1 separately in the loop (this code with square brackets cannot run, for the actual example see MWE below).

The problem is that - contrary to my expectation - for the the smallest range that occurs, tikz evaluates \foreach \ell in {-1,1,...,-1} as \ell in {-1,1}). The documentation (p.910) says (square bracket and emphasis mine):

In this situation, the part of the list reading x,y,...,z is replaced by x,x+d,x+2d,...,x+md, where [d=y-x and] the last dots are semantic dots, not syntactic dots. The value m is the largest number such that x+md<=z if d is positive or such that x+md>=z if d is negative.

My interpretation would be that m should be 0 in my case, but maybe that's hard to actually implement - or the behaviour could even be intentional.

In any case, I'd like to avoid having to split the loops and would like to find a way around it. I guess it would be possible to build an if-clause depending on the parity of \ell (to distinguish between even and odd, and just avoid specifying the second value of the list), this is just not that elegant either IMHO. But maybe there's no way around that as things stand...

As a brief sketch how I'd like my code to look like, here's an MWE (the desired result should just be one node at (1,1) with label "1"):

\documentclass{article}
\usepackage[english]{babel}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
\foreach \j in {1} % scale (normally more!)
{
    % do something per scale here
    \pgfmathsetmacro{\z}{2^(\j-1)}
    \pgfmathsetmacro\istart{-\z}
    \pgfmathsetmacro\isecond{\istart+2}
    \pgfmathsetmacro\iend{\z-2}
    \foreach \ell in {\istart,\isecond,...,\iend}
    {
        % do something for \ell here
        \node at (\ell,\ell) {\ell}; % just for illustration
        % do something for \ell+1 here
    }
}
\end{tikzpicture}
\end{document}
  • pgffor always evaluates at least 2 values, the first one, and the second one. Only then it cares about the upper bound. It should have been stated in the manual. However, I'm sure that this has been asked before here :) I just can't find it now... – yo' Oct 7 '14 at 9:54
  • @tohecz: Is this intentional or would it just be too hard to discard the second value afterwards? I find the behaviour stated in the documentation to be very intuitive, and IMHO that's how it should work also for m=0. – Axel Oct 7 '14 at 9:59
10

TikZ doesn't solve x+md<z equation to come up with the proper m or d for that matter. It starts adding \isecond - \istart amount in this case 2 after(!) evaluating the loop at \istart and \isecond because those points are given. Then checks whether 1+2 < -1 no then quits with I'm done.

You can use \ifodd, \ifeven if clauses if you want to branch off inside foreach. Or you can use \pgfmathiseven{<number>} and check the value of \pgfmathresult

\documentclass{article}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
\foreach \j in {1,...,4}
{
\ifodd\j\relax
\node at (0,\j) {odd};
\else
\node at (\j,0) {even};
\fi
}
\end{tikzpicture}
\end{document}

enter image description here

  • Thanks for the \ifodd-trick, that at least is not as verbose as the \pgfmathiseven{...}-\pgfmathresult combination. I've therefore accepted the answer. Just out of curiosity, is there a TeX/PGF/performance-reason why the second value cannot be discarded in this case? I find the behaviour as stated in the documentation to be very intuitive and IMHO it should extend to m=0. (Ps. I made a similar comment to @tohecz after OP - sorry for the redundancy, I wanted to answer you both.) – Axel Oct 7 '14 at 10:03
  • @Axel Functionally, we can consider this usage as abuse of arrays because what you do is to first signal TikZ to expect an monotone array with ... but then render the resulting array via using an endpoint that doesn't result with an array and moreover rendering ... useless. The reason for not extending this to the cases you mentioned is because TeX floating point math is not precise. Hence given a d, computing m precisely is problematic in some cases. This implementation in that sense is a choice. I can see why you want to overload its definition but it would lead to extensive checks. – percusse Oct 7 '14 at 10:10
  • And from a coding perspective if you don't have an array you shouldn't utilize array tools for special case handling. – percusse Oct 7 '14 at 10:12
  • 1
    Ok, thanks, I can now at least understand the design decision better. On a different note, replacing \ifodd with \ifeven crashes for me - could it be that only the former is defined (together with the \else-clause this certainly covers all cases...)? – Axel Oct 7 '14 at 10:14
  • 1
    No problem! The crash also happens without the \else-clause, though (on my machine)... – Axel Oct 7 '14 at 10:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.