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?

Aria
  • 1,523

4 Answers4

9

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}

egreg
  • 1,121,712
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
  • Can we get parentheses in \ifthenelse{(\x=1 \and \y=1) \or (\x=2 \and \y=1)}{}{}? – Aria Aug 05 '20 at 05:32
  • Do texdoc ifthen. The introduction is all the documentation you need to read. Parentheses need to be \( and \). – Donald Arseneau Aug 05 '20 at 06: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 05 '20 at 06:59
  • I need to have a condition like (p and q) or (p and r), do you know how to define? – Aria Aug 05 '20 at 07: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. – Donald Arseneau Aug 05 '20 at 09: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

vi pa
  • 3,394
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

Aria
  • 1,523