31

I want to draw a graph like in the second picture of the following code:

\documentclass{article}
\usepackage{mathptmx}
\usepackage{tikz}
\usepackage{verbatim}
\usetikzlibrary{arrows,shapes,graphs,graphs.standard,quotes}
\usepackage{calc}% http://ctan.org/pkg/calc
\usepackage{ifthen}

\begin{document}

% This one works
\begin{tikzpicture}

\foreach \x in {1,...,5}
{ \node[circle,draw] (\x 1) at (0,\x) {\x};
    \node[circle,draw] (\x 2)at (2,\x) {\x};
    \ifthenelse{\NOT 4 = \x \AND \NOT 7 = \x}{\draw (\x 1) -- (\x 2);}{} % (*)
}

\end{tikzpicture}

% This one does not work with line (*)
\begin{tikzpicture}
\tikzstyle{vertex}=[circle,fill=blue!15,draw,minimum size=17pt,inner sep=0pt]

%See TikZ documentation! (Section 19, graphs)
\graph[circular placement, radius=4cm, group polar shift=(360/5:0),
         nodes={circle,draw,vertex}] {
    \foreach \x [evaluate=\x as \sx using int(\x+1)] in {0,...,4} {
      \foreach \y in {\x,...,4} {
        \x -- \y;
        %\ifthenelse{\NOT 4 = \x \AND \NOT 7 = \x}{\draw (\x 1) -- (\x 2);}{} % (*)
      };
    };
  };
\end{tikzpicture}

\end{document}

It uses the TikZ graph library. As you might guess, I want to label the edges dependent on what \x and \y are in the for loop. So I need an If-Then-Else statement and came to this answer: https://tex.stackexchange.com/a/45907/52709. I copied the code, it is the first picture and it works. But applying the same \ifthenelse-line to my code (commented out), produces an error at that line:

! Undefined control sequence.<argument> \NOT 4 = \x \AND \NOT 7 = \x }

and also

! Illegal parameter number in definition of \tikz@lib@graph@name.

at the end of the graph defintion (};).

Isn’t it possible to use something like \ifthenelse inside such a graph definition? How can I achieve what I need?

  • 2
    You have to remember that Tikz does its own parsing. Everything from \path (for example) to the terminating semicolon is parsed by Tikz. Outside these areas you can add any latex commands you want. – John Kormylo Jul 01 '14 at 16:22
  • Right, so this means I can't use \ifthenelse? Is there another way to do it? – user905686 Jul 01 '14 at 16:27
  • 1
    pgfmath contains its own ifthenelse, sort of. – John Kormylo Jul 01 '14 at 16:33
  • Evey (x,y) coordinate is passed through \pgfmathparse automatically. – John Kormylo Jul 01 '14 at 16:41
  • Since you are using tikz graphs, which require Lua, you can use lua too to evaluate your conditionals. I was trying to compose a MWE as proof of concept, but then I realized I didn't really understand the purpose of the conditions. What kind of output do you expect? Your example code compares \x with 4 an 7, but that doesn't makes much sense, and it does not use \y. – JLDiaz Jul 01 '14 at 18:11
  • Ok sorry about the confusing usage of \ifthenelse. Surely I want to use it according to my labeling problem, I just copied the working example to show what syntax I would need. – user905686 Jul 02 '14 at 11:22

2 Answers2

36

\ifthenelse is "normal" LaTeX code. Therefore you can not use this command inside a TikZ path specification. But since the node text is put in a normal TeX box you can use \ifthenelse inside the node text. So you can try

\documentclass[tikz,margin=5mm]{standalone}
\usetikzlibrary{graphs,graphs.standard,quotes}

\usepackage{ifthen}

\begin{document}
\begin{tikzpicture}[
  vertex/.style={circle,fill=blue!15,draw,minimum size=17pt,inner sep=0pt}
]
%See TikZ documentation! (Section 19, graphs)
\graph[circular placement, radius=4cm, group polar shift=(360/5:0),
         nodes={circle,draw,vertex}] {
    \foreach \x in {0,...,4} {
      \foreach \y in {\x,...,4} {
        \x --["\ifthenelse{\x=3 \OR \y=3 \OR \x=\y}{}{\x\y}",sloped] \y;
  }}};
\end{tikzpicture}
\end{document}

enter image description here

Or you can position the nodes inside the \graph and connect them outside. Then you can use \ifthenelse outside of a path specification. Note that the complete \draw paths are in the arguments of \ifthenelse.

\documentclass[tikz,margin=5mm]{standalone}
\usetikzlibrary{graphs,graphs.standard,quotes}

\usepackage{ifthen}

\begin{document}
\begin{tikzpicture}[
  vertex/.style={circle,fill=blue!15,draw,minimum size=17pt,inner sep=0pt}
]
%See TikZ documentation! (Section 19, graphs)
\graph[circular placement, radius=4cm, group polar shift=(360/5:0),
         nodes={circle,draw,vertex}] {\foreach \x in {0,...,4} \x;
};
\foreach \x in {0,...,4} {
  \foreach \y in {\x,...,4} {
    \ifthenelse{\x=3 \OR \y=3 \OR \x=\y}{\draw(\x)--(\y);}{\draw(\x)--node[auto,sloped]{\x\y}(\y);}
}}
\end{tikzpicture}
\end{document}

The result is the same as above.


In the pgfmanual you can also find \pgfextra as a possibilty to suspend temporarly the path construction and do some other things like \ifthenelse. Here is a simple example where the filling color depends on the counter:

\documentclass[tikz,margin=5mm]{standalone}
\newcommand\mycolor{blue!15}
\usepackage{ifthen}
\begin{document}
    \begin{tikzpicture}[
        vertex/.style={circle,draw,minimum size=17pt,inner sep=0pt}
      ]
  \foreach \i in {0,...,4}{
    \path(0,0)\pgfextra{\ifthenelse{\i=2}{\def\mycolor{red!15}}{}}
      (90+\i*72:1)node[vertex,fill=\mycolor]{\i};}
\end{tikzpicture}
\end{document}

This results in

enter image description here

But AFAIK this does not work inside a \graph command.


Update:

Solutions without package \ifthen based on a suggestion of @marmot in a comment:

\documentclass[tikz,margin=5mm]{standalone}
\usetikzlibrary{graphs,graphs.standard,quotes}

\begin{document}
\begin{tikzpicture}[
  vertex/.style={circle,fill=blue!15,draw,minimum size=17pt,inner sep=0pt}
]
%See TikZ documentation! (Section 19, graphs)
\graph[circular placement, radius=4cm, group polar shift=(360/5:0),
         nodes={circle,draw,vertex}] {
    \foreach \x in {0,...,4} {
      \foreach \y 
        [evaluate=\y as \z using {int(ifthenelse(\x==3 || \y==3 || \x==\y,1,0))}]
        in {\x,...,4} {
        \x --["\ifnum \z=0 {\x\y}\fi",sloped] \y;
  }}};
\end{tikzpicture}
\end{document}

or

\documentclass[tikz,margin=5mm]{standalone}
\usetikzlibrary{graphs,graphs.standard,quotes}

\begin{document}
\begin{tikzpicture}[
  vertex/.style={circle,fill=blue!15,draw,minimum size=17pt,inner sep=0pt}
]
%See TikZ documentation! (Section 19, graphs)
\graph[circular placement, radius=4cm, group polar shift=(360/5:0),
         nodes={circle,draw,vertex}] {\foreach \x in {0,...,4} \x;
};
\foreach \x in {0,...,4} {
  \foreach \y 
    [evaluate=\y as \z using {int(ifthenelse(\x==3 || \y==3 || \x==\y,1,0))}]
    in {\x,...,4} {
      \ifnum \z=1
        \draw(\x)--(\y);
      \else 
        \draw(\x)--node[auto,sloped]{\x\y}(\y);
      \fi
}}
\end{tikzpicture}
\end{document}

The result is the same as in the first picture.

esdd
  • 85,675
  • This is exactly what I need! Can you please add an explanation why this works and where you can use \ifthenelse and where not? Thanks! – user905686 Jul 02 '14 at 11:40
  • I have edited my answer. – esdd Jul 02 '14 at 20:35
  • 2
    Maybe add \foreach \x in {0,...,4} { \foreach \y [evaluate=\y as \z using {int(ifthenelse(\x==3 || \y==3 || \x==\y,1,0))}] in {\x,...,4} { \ifnum\z=1 \draw(\x)--(\y); \else \draw(\x)--node[auto]{\x\y}(\y); \fi }} to the list of possibilities. It does not require the ifthenelse package. –  Jun 21 '19 at 01:05
8

You can pre-compute an array of points using \ifthenelse, then use them in the \foreach. I have no idea what you are trying to accomplish with the second example.

\documentclass{article}
\usepackage{mathptmx}
\usepackage{tikz}
\usepackage{verbatim}
\usetikzlibrary{arrows,shapes,graphs,graphs.standard,quotes}
\usepackage{calc}% http://ctan.org/pkg/calc
\usepackage{ifthen}

\begin{document}
\begin{tikzpicture}

\def\xset{1,2,3,5}% sort of obvious

\def\xset{\strut}% doing it the hard way
\foreach \x in {1,...,5}
  {\ifthenelse{\NOT 4 = \x \AND \NOT 7 = \x}
  {\if\xset\strut\relax\global\edef\xset{\x}\else\global\edef\xset{\xset,\x}\fi}
  {}};

\foreach \x in {1,...,5}
{ \node[circle,draw] (\x 1) at (0,\x) {\x };
    \node[circle,draw] (\x 2) at (2,\x) {\x };
}
\foreach \x in \xset {\draw (\x 1) -- (\x 2);};

\end{tikzpicture}
\end{document}
John Kormylo
  • 79,712
  • 3
  • 50
  • 120