TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I am a fan of \foreach loops in tikz, but often find myself in a situation where I want to make an exception for a single iteration of the loop. For example,

  \documentclass{article}
  \usepackage{tikz}
  \begin{document}

  \begin{tikzpicture}[every node/.style={draw, circle}]
  \node[label=above:a] (a) at (3,1) {};
  \node[label=below:b] (b) at (3,-1) {};

  \foreach \i in {0,1,2,3,4,5,6} {
    \node[label=above:\i] (x\i) at (\i, 0) {};
    \draw (x\i)--(b);
  }
  \draw (a)--(x3);
  \end{tikzpicture}

  \end{document}

I would like to have label=right:\i for node 3 since otherwise it intersects the edge to a. I can think of some ugly solutions (e.g., taking this case out of the loop and copying the code with the difference for it alone), but do you have any nicer way to achieve this?

share|improve this question
up vote 3 down vote accepted

You are looking for the \ifnum<condition> \else \fi construct. See the code below.

Note that by \ifnum you can only compare integers. More complex conditions can be done using e.g. \pgfmathparse.

\documentclass{article}
\usepackage{tikz}
\begin{document}

\begin{tikzpicture}[every node/.style={draw, circle}]
\node[label=above:a] (a) at (3,1) {};
\node[label=below:b] (b) at (3,-1) {};

\foreach \i in {0,...,6} {
    \ifnum\i=3
        \node[label=right:\i] (x\i) at (\i, 0) {};
    \else
        \node[label=above:\i] (x\i) at (\i, 0) {};
    \fi
    \draw (x\i)--(b);
}
\draw (a)--(x3);
\end{tikzpicture}

\end{document}

Edit: To avoid copying a possibly extensive code within the \ifnum \else \fi construct, you can do for example this. I'm not 100% sure this is robust but here it works.

\documentclass{article}
\usepackage{tikz}
\begin{document}

\begin{tikzpicture}[every node/.style={draw, circle}]
\node[label=above:a] (a) at (3,1) {};
\node[label=below:b] (b) at (3,-1) {};

\foreach \i in {0,...,6} {      
    \ifnum\i=3 \def\location{right} \else \def\location{above} \fi  % change here
    \node [label=\location:\i] (x\i) at (\i, 0) {};                 % and here
    \draw (x\i)--(b);
}
\draw (a)--(x3);
\end{tikzpicture}

\end{document}
share|improve this answer
    
Nice! Is there a way to make this inline? I've just tried \node[\ifnum\i=3 label=right:\i \else label=above:\i\fi] (x\i) at (\i, 0) {};, without success. – tarulen Feb 22 at 15:18
    
Not quite as far as I know, but there are other options. I'll edit the answer. – Ondrian Feb 22 at 15:24

You can define your label option like this:

[label={\ifnum\i\equals3 right\else above\fi :\i}]

with the command \newcommand\equals{=} added to the preamble. Because this = is what cases a parse error for tikz when it tries to split the input at = to recognize key/value pairs. This idea was borrowed from a comment by @egreg on a similar question.

\documentclass[border=5pt,tikz]{standalone}
\newcommand\equals{=}
\begin{document}

  \begin{tikzpicture}[every node/.style={draw, circle}]
  \node[label=above:a] (a) at (3,1) {};
  \node[label=below:b] (b) at (3,-1) {};

  \foreach \i in {0,...,6} {
    \node [label={\ifnum\i\equals3 right\else above\fi :\i}] (x\i) at (\i, 0) {};
    \draw (x\i)--(b);
  }
  \draw (a)--(x3);
\end{tikzpicture}

\end{document}

enter image description here

share|improve this answer
    
That's a cool hack :) – Ondrian Feb 22 at 17:20
    
Thank you, you've provided a nice solution too. – AboAmmar Feb 22 at 21:07

First solution (remove exception case from \foreach list):

\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[every node/.style={draw, circle}]
  \node[label=above:a] (a) at (3,1) {};
  \node[label=below:b] (b) at (3,-1) {};

  \foreach \i in {0,1,2,4,5,6} {
    \node[label=above:\i] (x\i) at (\i, 0) {};
    \draw (x\i)--(b);
  }
  % exception
  \node[label=right:3] (x3) at (3, 0) {};
  \draw (x3)--(b);

  \draw (a)--(x3);
\end{tikzpicture}
\end{document}

Second solution (no exception using two variables in \foreach):

\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[every node/.style={draw, circle}]
  \node[label=above:a] (a) at (3,1) {};
  \node[label=below:b] (b) at (3,-1) {};

  \foreach \i/\mypos in {0/above,1/above,2/above,3/right,4/above,5/above,6/above} {
    \node[label=\mypos:\i] (x\i) at (\i, 0) {};
    \draw (x\i)--(b);
  }

  \draw (a)--(x3);
\end{tikzpicture}
\end{document}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.