TransWikia.com

On a conditional command: more powerful than ifnum

TeX - LaTeX Asked on December 21, 2020

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?

4 Answers

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} {
    defrotation{-45}
    ifnumy=1
      ifnumx=1 defrotation{0} fi
      ifnumx=2 defrotation{0} fi
    fi
    fill[red!50] (x,y) ellipse [x radius=3pt, y radius=6pt, rotate=rotation];
    ifnum x<y unlessifnum x<1 breakforeach fifi
  }
}
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)}{defrotation{0}}{defrotation{-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})}
      {defrotation{0}}
      {defrotation{-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}

Correct answer by egreg on December 21, 2020

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
fifi

Answered by Donald Arseneau on December 21, 2020

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

Answered by Aria on December 21, 2020

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

Answered by vi pa on December 21, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP