Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I apologise if I'm using and searching with incorrect terminology. This seems an obvious question (to me) so I'm surprised I've not found anything (and so assume I'm missing something).

In metapost, I can use the following to define a loop:

for i=some-value step 0.05 until some-other-value:
    fill fullcircle scaled so-and-so withcolor i*white;
    so-and-so := so-and-so - something;
    something-else := i;
endfor;

This means that I can define how large the increments should be without needing to know the initial and final value of i.

Is something similar possible in tikz?

I can achieve the same effect in a more roundabout fashion by calculating the second value for the loop from the first value plus the value of the step. However, I wonder if there is not some simpler method.

That is, the following code works:

\documentclass[border=5pt,tikz]{standalone}

\begin{document}
  \tikzset{
    /mytree/key1/.initial={-10},
    /mytree/key2/.initial={10},
    /mytree/step1/.initial={2},
  }
  \begin{tikzpicture}
    \pgfmathsetmacro{\myfirststep}{\pgfkeysvalueof{/mytree/key1} + \pgfkeysvalueof{/mytree/step1}}%
    \foreach \i in {\pgfkeysvalueof{/mytree/key1},\myfirststep,...,\pgfkeysvalueof{/mytree/key2}}
      \node at (\i,0) {\i};
  \end{tikzpicture}
\end{document}

but I wonder is it possible to replace the lines

    \pgfmathsetmacro{\myfirststep}{\pgfkeysvalueof{/mytree/key1} + \pgfkeysvalueof{/mytree/step1}}%
    \foreach \i in {\pgfkeysvalueof{/mytree/key1},\myfirststep,...,\pgfkeysvalueof{/mytree/key2}}

with something more elegant such as

    \foreach \i [step=\pgfkeysvalueof{/mytree/step1}] in {\pgfkeysvalueof{/mytree/key1},...,\pgfkeysvalueof{/mytree/key2}}

which would be analogous to the usage of step in metapost?

share|improve this question
    
You can embed your customization into a style and use it repeatedly, would that be elegant enough? :P –  percusse Jul 17 '14 at 8:30
    
@percusse I was hoping for just a step= type option. But if I haven't missed something, then, yes, that would be elegant enough ;). Do you mean literally using .../.style... rather than .../.code...? I'm still somewhat at sea with keys in pgf/tikz! –  cfr Jul 17 '14 at 9:16
3  
Put \pgfkeys{/pgf/foreach/custom step/.code={your first line here doing the computation}} and then use it with \foreach \i[custom step] in {\pgfstuff,\myfirststep,...,\pgfmorestuff}{...} that's what I meant. –  percusse Jul 17 '14 at 9:18
    
@percusse Aha! I see. I will definitely try this shortly. That does, indeed, look very neat ;). Thanks! –  cfr Jul 17 '14 at 9:23
    
@percusse Maybe you could turn your comments into an answer such that this question is no longer shown as unanswered. –  cryingshadow Dec 28 '14 at 11:34

3 Answers 3

An implementation with expl3; the complete list is generated, so relieving PGF from the burden of doing the work by itself.

\documentclass{article}
\usepackage{xparse,tikz}

\ExplSyntaxOn
\NewDocumentCommand{\mpfor}{mm}
 {% #1 = variable, #2 = keys
  \cfr_mpfor:nn { #1 } { #2 }
 }

\keys_define:nn { cfr/mpfor }
 {
  start .fp_set:N = \l_cfr_mpfor_start_fp,
  start .value_required:,
  end   .fp_set:N = \l_cfr_mpfor_end_fp,
  end   .value_required:,
  step  .fp_set:N = \l_cfr_mpfor_step_fp,
 }

\clist_new:N \l_cfr_mpfor_values_clist

\cs_new_protected:Npn \cfr_mpfor:nn #1 #2
 {
  \keys_set:nn { cfr/mpfor } { step = 1 , #2 } % default step 1
  \bool_do_while:nn
   {
    (% if the step is positive, continue until <= holds
     \fp_compare_p:n { \l_cfr_mpfor_step_fp > \c_zero_fp }
     &&
     \fp_compare_p:n { \l_cfr_mpfor_start_fp <= \l_cfr_mpfor_end_fp }
    )
    ||
    (% if the step is negative, continue until >= holds
     \fp_compare_p:n { \l_cfr_mpfor_step_fp < \c_zero_fp }
     &&
     \fp_compare_p:n { \l_cfr_mpfor_start_fp >= \l_cfr_mpfor_end_fp }
    )
   }
   {
    \clist_put_right:Nx \l_cfr_mpfor_values_clist { \fp_eval:n { \l_cfr_mpfor_start_fp } }
    \fp_add:Nn \l_cfr_mpfor_start_fp { \l_cfr_mpfor_step_fp }
   }
  \cfr_mpfor_foreach:Vn \l_cfr_mpfor_values_clist { #1 }
 }

\cs_new_protected:Npn \cfr_mpfor_foreach:nn #1 #2
 {
  \foreach #2 in ~ { #1 }
 }
\cs_generate_variant:Nn \cfr_mpfor_foreach:nn { V }

\ExplSyntaxOff

\begin{document}

\begin{tikzpicture}
\mpfor{\i}{start=-4,step=2,end=8}{\node at (\i,0) {$\i$};}
\end{tikzpicture}

\begin{tikzpicture}
\mpfor{\i}{start=8,step=-2,end=-4}{\node at (\i,0) {$\i$};}
\end{tikzpicture}

\end{document}

Note that no check is performed to see whether the loop ends (it might be added). If the step is zero, only the start point is used.

Any value can be used, so long as it fits in the values accepted by the fp module.

enter image description here

share|improve this answer

This is not really simple method, and not really elegant, but ... is one possibility. This is a TikZ only solution. And it can be adapted to add other keys (like second, random step, exclusive start, exclusive end, ...).

\documentclass[border=5pt,tikz]{standalone}

\pgfkeys{
  /stepfor/.cd,
  start/.store in={\startvalue},
  step/.store in={\stepvalue},
  end/.store in={\endvalue}
}
\def\for[#1]#2{
  \pgfkeys{/stepfor/.cd,#1}
  \pgfmathsetmacro{\secondvalue}{int(\startvalue+\stepvalue)}
  \foreach \i in {\startvalue,\secondvalue,...,\endvalue}{#2}
}

\begin{document}
  \begin{tikzpicture}
    \for[start=-4,step=2,end=8]{\node at (\i,0) {\i};}
  \end{tikzpicture}
\end{document}

enter image description here

Note: I have put int in the evaluation of \secondvalue just to make the output nicer ;) But for working with reals it should be deleted, of course.

share|improve this answer

If you accept to use a library outside of TikZ, and you want to loop over integers only, you can take for example xinttools.

Method 1: using xint only.

\documentclass[tikz,border=5pt]{standalone}
\usepackage{xinttools}

\begin{document}
  \begin{tikzpicture}
    \xintFor* #1 in {\xintSeq[2]{-4}{8}} \do {
      \node at (#1,0) {#1};
    }
  \end{tikzpicture}
\end{document}

enter image description here

Method 2: using xint and \foreach.

\documentclass[tikz,border=5pt]{standalone}
\usepackage{xinttools}

\begin{document}
  \begin{tikzpicture}
    \edef\interval{\xintListWithSep{,}{\xintSeq[2]{-4}{8}}}
    \foreach \i in \interval 
      \node at (\i,0) {\i};
  \end{tikzpicture}
\end{document}

Method 2+: using xint, \foreach and styling.

\documentclass[border=5pt]{standalone}
\usepackage{tikz}
\usepackage{xinttools}
\tikzset{
  /pgf/foreach/interval/.code args={from #1 to #2 by #3}{
    \edef\interval{\xintListWithSep{,}{\xintSeq[#3]{#1}{#2}}}
  }
}
\begin{document}
  \begin{tikzpicture}
    \foreach[interval=from -4 to 8 by 2] \i in \interval
      \node at (\i,0) {\i};
  \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.