5

According to the TEX in a Nutshell, Petr Olšák, page 16/29, we get:

\ifnum ⟨number 1⟩ ⟨relation⟩ ⟨number 2⟩ . The ⟨relation⟩ could be < or = or >. It returns true if the comparison of the two numbers is true.

I am looking for a more powerful conditional command to include (~=) (not equal to) relation.

  • Do we have such a conditional command?

The reason I asked is related to page 1005/1318 TikZ manual. Which I modified the code a little bit to generate an array of elliptical objects as below:

enter image description here

I rotated all ellipses 45 degree clockwise. What I want to do is not to rotate the highlighted ellipses in yellow so the rot=0 for them.

  • How to do it with a conditional command?

Below is my code:

 \documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
 \foreach \x in {1,...,4}
\foreach \y in {1,...,4}

{
\fill[red!50] (\x,\y) ellipse [x radius=3pt, y radius=6pt, rotate=-45];
\ifnum {\x<\y} & {\x>1}
\breakforeach
\fi
}
\draw [|-|] (.895,1) -- ++(0.211,0);
\end{tikzpicture}
\end{document}

It seems ifthen package is the answer. I used the code below using \ifthenelse, but got an error:

\documentclass{standalone}
\usepackage{tikz,ifthen}
\begin{document}
\ifthenelse{1>2 \AND 3=3}{yes}{no}
\begin{tikzpicture}
\foreach \x in {1,...,4}
\foreach \y in {1,...,4}
{
\newcommand{\first}{\(\x=1 \and \y=1\)}
\newcommand{\second}{\(\x=2 \and \y=1\) }
\ifthenelse{\(\first\) \or \(\second\)}
 {\fill[red!50] (\x,\y) ellipse [x radius=3pt , y radius= 6pt, rotate=0];}
{\fill[red!50] (\x,\y) ellipse [x radius=3pt , y radius= 6pt, rotate=-45];}
\ifnum \x<\y
\breakforeach
\fi
}
\draw [|-|] (.895,1) -- ++(0.211,0);
\end{tikzpicture}
\end{document}

Error: ! Extra \or. ...=1) } \ifthenelse {(\first ) \or (\second )} {\fill [red!... Do you know how to debug this code to make it work?

0

4 Answers 4

8

In order to reproduce the picture, the test should be 1 ≤ x < y.

You can parametrize the rotation angle and test for the two special cases.

\documentclass{standalone}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
\foreach \x in {1,...,4} {
  \foreach \y in {1,...,4} {
    \def\rotation{-45}
    \ifnum\y=1
      \ifnum\x=1 \def\rotation{0} \fi
      \ifnum\x=2 \def\rotation{0} \fi
    \fi
    \fill[red!50] (\x,\y) ellipse [x radius=3pt, y radius=6pt, rotate=\rotation];
    \ifnum \x<\y \unless\ifnum \x<1 \breakforeach \fi\fi
  }
}
\draw [|-|] (.895,1) -- ++(0.211,0);
\end{tikzpicture}
\end{document}

enter image description here

You can also use \ifthenelse, of course.

\documentclass{standalone}
\usepackage{tikz}
\usepackage{xifthen}

\begin{document}
\begin{tikzpicture}
\foreach \x in {1,...,4} {
  \foreach \y in {1,...,4} {
    \ifthenelse{\y=1 \AND \(\x=1 \OR \x=2\)}{\def\rotation{0}}{\def\rotation{-45}}
    \fill[red!50] (\x,\y) ellipse [x radius=3pt, y radius=6pt, rotate=\rotation];
    \ifthenelse{ \x<\y \AND \NOT\(\x<1\) }{\breakforeach}{}
  }
}
\draw [|-|] (.895,1) -- ++(0.211,0);
\end{tikzpicture}
\end{document}

With a somewhat easier syntax, see https://tex.stackexchange.com/a/467527/4427

\documentclass[border=4]{standalone}
\usepackage{tikz}
\usepackage{xparse}

\ExplSyntaxOn
\NewExpandableDocumentCommand{\xifthenelse}{mmm}
 {
  \bool_if:nTF { #1 } { #2 } { #3 }
 }

\cs_new_eq:NN \numtest     \int_compare_p:n
\cs_new_eq:NN \oddtest     \int_if_odd_p:n
\cs_new_eq:NN \fptest      \fp_compare_p:n
\cs_new_eq:NN \dimtest     \dim_compare_p:n
\cs_new_eq:NN \deftest     \cs_if_exist_p:N
\cs_new_eq:NN \namedeftest \cs_if_exist_p:c
\cs_new_eq:NN \eqdeftest   \token_if_eq_meaning_p:NN
\cs_new_eq:NN \streqtest   \str_if_eq_p:ee
\cs_new_eq:NN \emptytest   \tl_if_blank_p:n
\prg_new_conditional:Nnn \xxifthen_legacy_conditional:n { p,T,F,TF }
 {
  \use:c { if#1 } \prg_return_true: \else: \prg_return_false: \fi:
 }
\cs_new_eq:NN \boolean \xxifthen_legacy_conditional_p:n
\ExplSyntaxOff

\begin{document}
\begin{tikzpicture}
\foreach \x in {1,...,4} {
  \foreach \y in {1,...,4} {
    \xifthenelse{\numtest{\y=1} && (\numtest{\x=1} || \numtest{\x=2})}
      {\def\rotation{0}}
      {\def\rotation{-45}}
    \fill[red!50] (\x,\y) ellipse [x radius=3pt, y radius=6pt, rotate=\rotation];
    \xifthenelse{ \numtest{1<=\x<\y} }{\breakforeach}{}
  }
}
\draw [|-|] (.895,1) -- ++(0.211,0);
\end{tikzpicture}
\end{document}
3
  • Can we do it with ifthenelse?
    – Aria
    Aug 5, 2020 at 9:00
  • @Aria Is there any reason to? Anyway, I added it.
    – egreg
    Aug 5, 2020 at 9:17
  • I thought if then else might be shorter.
    – Aria
    Aug 5, 2020 at 17:04
6

LaTeX's ifthen package has some facility for combining conditionals with \and and \or, \not and parentheses. But your case is easy to do with \ifnum:

\ifnum \x<\y \ifnum \x>1
  \breakforeach
\fi\fi
5
  • Can we get parentheses in \ifthenelse{(\x=1 \and \y=1) \or (\x=2 \and \y=1)}{<task1>}{<task2>}?
    – Aria
    Aug 5, 2020 at 5:32
  • Do texdoc ifthen. The introduction is all the documentation you need to read. Parentheses need to be \( and \). Aug 5, 2020 at 6:50
  • Got error for: \newcommand{\first}{(\x=1 \and \y=1)} \newcommand{\second}{(\x=2 \and \y=1) } \ifthenelse{\first \or \second } {\fill[red!50] (\x,\y) ellipse [x radius=3pt , y radius= 6pt, rotate=0];} {\fill[red!50] (\x,\y) ellipse [x radius=3pt , y radius= 6pt, rotate=-45];}
    – Aria
    Aug 5, 2020 at 6:59
  • I need to have a condition like (p and q) or (p and r), do you know how to define?
    – Aria
    Aug 5, 2020 at 7:02
  • You can't hide the syntax in macros. You still have the wrong parentheses. My answer was for \ifnum anyway, rather than \ifthenelse. There may be other options with "expl" syntax. Aug 5, 2020 at 9:37
1
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{math}
\begin{document}
\begin{tikzpicture}
\foreach \x in {1,...,4} {
\tikzmath {\xEnd=\x+1;}
\foreach \y in {1,...,\xEnd} {
\fill[red!50] (\x,\y) 
ellipse [x radius=3pt, y radius=6pt, rotate={ifthenelse(\x==1 || \x==2 && \y==1,0,-45)}];
}}
\draw [|-|] (.895,1) -- ++(0.211,0);
\end{tikzpicture}
\end{document}

enter image description here

0

Found a much simpler solution. Below are the key ideas:

  • \ifthenelse from ifthen package in CTAN is that powerful conditional command.

  • \ifthenelse{<test>}{<then clause>}{<else clause>}is the command format wherein <test> is a boolean expression using the infix connectives, \and, \or, the unary \not and parentheses \( \).

  • Also \OR and \AND are safer to be used with \ifthenelse rather than using \or and \andsince it can’t be misinterpreted when appearing inside a TEX-conditional in which \or has a different meaning. So here is the code:

    \documentclass{standalone}
    \usepackage{tikz,ifthen}
    \begin{document}
    \begin{tikzpicture}
    \foreach \x in {1,...,4}
    \foreach \y in {1,...,4}
    {
    \ifthenelse{\(\x=1 \AND \y=1\) \OR \(\x=2 \AND \y=1\) }
    {\fill[red!50] (\x,\y) ellipse [x radius=3pt , y radius= 6pt, rotate=0];}
    {\fill[red!50] (\x,\y) ellipse [x radius=3pt , y radius= 6pt, rotate=-45];}
    \ifnum \x<\y
    \breakforeach
    \fi
    }
     \draw [|-|] (.895,1) -- ++(0.211,0);
    \end{tikzpicture}
    \end{document}
    

enter image description here

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.