4

I'm having lots of trouble when using \ifodd. I want to make a pattern of alternating thick and thin lines, I have tried several ways but none of them works.

With this structure


\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning,calc}

\begin{document}
\begin{tikzpicture}[remember picture,overlay,shorten >= -10pt]

    \coordinate (aux1) at ([xshift=-25mm, yshift=-30mm]current page.north east);
    \coordinate (aux2) at ([xshift=-25mm, yshift=30mm]current page.south east);
    \coordinate (aux3) at ([xshift=25mm, yshift=-30mm]current page.north west);
    \coordinate (aux4) at ([xshift=25mm, yshift=30mm]current page.south west);
    
    \begin{scope}[black]
        \foreach \i [evaluate =\i as \x using int(\i)] in {0, ..., 4}{
            \draw["\ifodd \x line width=1pt \else line width=2pt \fi" ]([
                    xshift=\x mm,
                    yshift=-65mm
                ]aux1)
                -- 
                ([
                    xshift=\x mm,
                    yshift=10mm]
                aux2);
        }
        
    \end{scope}
\end{tikzpicture}

\end{document}

I have tried


\foreach \x in {0, ..., 4}{
    \draw["\ifodd \x line width=1pt \else line width=2pt \fi" ]([
}
\foreach \x in {0, ..., 4}{
    \draw["\ifodd \num{\x} line width=1pt \else line width=2pt \fi" ]([
}
\foreach \x in {0, ..., 4}{
    \draw["\ifodd \value{\x} line width=1pt \else line width=2pt \fi" ]([
}
\foreach \i [evaluate =\i as \x using int(\i)] in {0, ..., 4}{
    \draw["\ifodd \x line width=1pt \else line width=2pt \fi" ]([
}

Note: I want to learn how to use \ifodd inside loops

3
  • You can use \draw[line width=\ifodd\x\space1pt\else2pt\fi] instead, but you'll get a dimension too large error from your picture anyway, not sure where exactly that comes from.
    – Skillmon
    Mar 2 at 7:59
  • @Skillmon I have wrote an answer, but incomplete (for example, I don't know why "=" must be outside of the test, or if there is a solution to "protect" it). Also, is \space better than brace around the dimensions?
    – quark67
    Mar 2 at 8:08
  • @quark67 Yes, \space will end the \ifodd without any other ill effects that {} would have. The = must be outside the \ifodd...\fi block so that pgfkeys parses \ifodd\x\space1pt\else2pt\fi as the value (which it'll then try to use as a dimension, and during that assignment, not during key-parsing, the conditional will get evaluated).
    – Skillmon
    Mar 2 at 14:08

2 Answers 2

6

There are several problems with your code. The first one is the usage of "standalone" document class with node positioned relatively to the corner of the current page (but for standalone, the dimension of the page isn't fixed). This result in a "dimension too large" error (comment the line beginning with \draw, and you obtain a very big document: 12.13 cm width and 575.84 cm height!)

So first, we replace standalone by article.

Minor problem (non-blocking), the coordinates "aux3" and "aux4" aren't used, so we wipe it.

The second problem is with the syntax in the line \draw["\ifodd \x line width=1pt \else line width=2pt \fi" ]([.

First, forget the quotes ", it's a wrong syntax.

Secondly, if you try after removing the ", \ifodd \x line width=1pt \else line width=2pt \fi still don't work.

But \ifodd \x red\else blue\fi works.

In fact, if you add braces around true code and false code, as in \ifodd \x{line width=1pt}\else{line width=2pt}\fi you obtain error messages like I do not know the key '/tikz/line width=2pt' and I am going to ignore it. So TikZ see line width=1pt as key, not as key = value.

The problem seems related to the character = but I have don't find an explanation in the TeXbook nor in TeX by Topic for "protect" them, but I have probably not searched the good word to find the explanation.

A solution is to output "=" from the conditional test.

line width=\ifodd \x {1pt} \else 2pt\fi works.

Without brace around 1pt, you have the error Package PGF Math Error: Unknown function `pt' (in 'pt').

Note: Better than use brace around 1pt, we can use \space between \ifodd \x and 1pt (thanks to Skillmon, in the comments of the question).

Edit: You can also directly use \i for the test and for the dimension of the horizontal shift (so you can suppress [evaluate =\i as \x using int(\i)] and replace xshift=\x mm, with xshift=\i mm, in the \draw command).

Corrected code (I have also modified dimensions of yshift in the draw command, so the lines are vertically centered):

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning,calc}

\begin{document}
\begin{tikzpicture}[remember picture,overlay]

    \coordinate (aux1) at ([xshift=-25mm, yshift=-30mm]current page.north east);
    \coordinate (aux2) at ([xshift=-25mm, yshift=30mm]current page.south east);
    
    \begin{scope}[black]
        \foreach \i in {0, ..., 4}{
            \draw[line width=\ifodd \i\space 1pt\else 2pt\fi]([
                    xshift=\i mm,
                    yshift=0mm
                ]aux1)
                -- 
                ([
                    xshift=\i mm,
                    yshift=0mm]
                aux2);
        }
        
    \end{scope}
\end{tikzpicture}

\end{document}

Output (left: the whole document, right: a zoom on it):

enter image description here

7

You can't have conditionals enclosing the options.

I'm not sure why you define \x that way, as \i is an integer.

It's simpler than that: use \pgfmathifthenelse.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning,calc}

\begin{document}
\begin{tikzpicture}[
%  remember picture,
%  overlay,
  shorten >= -10pt
]
  \coordinate (aux1) at ([xshift=-25mm, yshift=-30mm]current page.north east);
  \coordinate (aux2) at ([xshift=-25mm, yshift=30mm]current page.south east);
  \coordinate (aux3) at ([xshift=25mm, yshift=-30mm]current page.north west);
  \coordinate (aux4) at ([xshift=25mm, yshift=30mm]current page.south west);
    
  \begin{scope}[black]
    \foreach \i in {0, ..., 4}{
      \pgfmathifthenelse{isodd(\i)}{1}{2}
      \draw[line width=\pgfmathresult pt]
        ([xshift=\i mm,yshift=-65mm]aux1)
        -- 
        ([xshift=\i mm,yshift=10mm]aux2);
    }
  \end{scope}
\end{tikzpicture}

\end{document}

enter image description here

As noted by Qrrbrbirlbel in comments, you can more simply do

      \draw[line width=isodd(\i) ? 1pt : 2pt]

omitting the \pgfmathifhenelse line.

Or you can use expl3:

\ExplSyntaxOn
\NewExpandableDocumentCommand{\isoddTF}{mmm}
 {
  \int_if_odd:nTF { #1 } { #2 } { #3 }
 }
\ExplSyntaxOff

in the preamble and

     \draw[line width=\isoddTF{\i}{1pt}{2pt}]

in the body of the tikzpicture.

2
  • 3
    Since it's TikZ (and everything's going to be PGFMath'ed anyway), it can also be line width=isodd(\i) ? 1pt : 2pt. Mar 2 at 9:31
  • 1
    @Qrrbrbirlbel Interesting, thanks.
    – egreg
    Mar 2 at 9:32

You must log in to answer this question.

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