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'm trying to use styles to generate TikZ figures that have repeated, regularly spaced elements by looping through an array, but am perplexed by the results I'm getting.

For example, if I define the style

state/.style={circle,draw=none,inner sep=0pt,minimum size=7mm,label=center:$#1$,name=#1}

then when I try to iterate through an array as the source of the arguments to the style, as in

\def\labels{{e,a,a^2,a^3}};\def\dim{4};
\foreach \n in {0,1,2,3} {
    \node[state={\labels[\n]}]at({cos(90+\n*(360/\dim))},{sin(90+\n*(360/\dim))}){};}

I get an error: Package pgf Error: No shape named e is known.

If I change around the definition of the array and the iterator(s)a bit,

\def\nodes{0/{e},1/{a},2/{a^2},3/{a^3}};\def\dim{4};
\foreach \n\lab in \nodes{
    \node[state={\lab}]at({cos(90+\n*(360/\dim))},{sin(90+\n*(360/\dim))}){};}

I can get the result I want (see MWE), but I'd rather not do this, as it requires an array structure that's not generally useable for my purposes.

enter image description here

How can I get the first form of the iterator and array to work?


\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{positioning}
\usetikzlibrary{arrows}
\usetikzlibrary{petri}

\begin{document}

\tikzset{
    redarrow/.style={->, red, fill=none,>=stealth, thick},
    state/.style={circle,draw=gray,inner sep=0pt,minimum size=7mm,label=center:$#1$,name=#1}}

\begin{center}

\begin{tikzpicture}
% This approach results in an error
% \def\labels{{e,a,a^2,a^3}};\def\dim{4};
% \foreach \n in {0,1,2,3} {
%   \node[state={\labels[\n]}]at({cos(90+\n*(360/\dim))},{sin(90+\n*(360/\dim))}){};}
\def\nodes{0/{e},1/{a},2/{a^2},3/{a^3}};\def\dim{4};
\foreach \n\lab in \nodes{
    \node[state={\lab}]at({cos(90+\n*(360/\dim))},{sin(90+\n*(360/\dim))}){};}
\draw[redarrow](e)--(a);\draw[redarrow](a)--(a^2);\draw[redarrow](a^2)--(a^3);\draw[redarrow](a^3)--(e);
\end{tikzpicture}

\end{center}

\end{document}
share|improve this question
    
Another version of this scenario produces an odd result: if I change the order of the approaches above, I no longer get the error, but instead get a figure that "uses" the elements defined in the first figure, and gives them labels like "e,a,a^2,a^3[0]". –  raxacoricofallapatorius May 21 '12 at 20:16

1 Answer 1

up vote 4 down vote accepted

Update

Sorry I did not know that pgfmath could work with arrays. The problem is that you need to use "e", "a" etc.. because "pgfmath" replaces e by 2.71828, and says that a is not a math function.

Don't forgot the next two rules.

Each element in the array will be evaluated as it is parsed, so expressions can be used.

and

"x" (group operators) These operators are used to quote x. However, as every expression is expanded with \edef before it is parsed, macros (e.g., font commands like \tt or \Huge) may need to be “protected” from this expansion (e.g., \noexpand\Huge). Ideally, you should avoid such macros anyway. Obviously, these operators should be used with great care as further calculations are unlikely to be possible with the result.

A solution is the next code but I don't like the node's names perhaps simpler is to use \n for the names.

remark : the result of \pgfmathparse{\labels[\n]} is given by \pgfmathresult and it's possible in some cases, to store this result with another macro.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{arrows}

\begin{document}

\tikzset{
    redarrow/.style 2 args={->, red, fill=none,>=stealth, thick},
    state/.style={circle,draw=gray,inner sep=0pt,minimum size=7mm,label=center:#1}}

\begin{center}

\begin{tikzpicture}
 \def\dim{4}
\def\labels{{"e","a","a^2","a^3"}}
\foreach \n in  {0,...,3}{
\pgfmathparse{\labels[\n]} 
\node[state={$\pgfmathresult$}] (\pgfmathresult) at ({cos(90+\n*(360/\dim))},{sin(90+\n*(360/\dim))}){};
  }   

\draw[redarrow](e)--(a);\draw[redarrow](a)--(a^2);\draw[redarrow](a^2)--(a^3);\draw[redarrow](a^3)--(e);
\end{tikzpicture}

\end{center}

\end{document} 

also possible is

\tikzset{
    redarrow/.style 2 args={->, red, fill=none,>=stealth, thick},
    state/.style={circle,draw=gray,inner sep=0pt,minimum size=7mm,label=center:$#1$,name=#1}}

\begin{tikzpicture}
 \def\dim{4}
\def\labels{{"e","a","a^2","a^3"}}
\foreach \n in  {0,...,3}{
\pgfmathparse{\labels[\n]} 
\node[state={\pgfmathresult}]  at ({cos(90+\n*(360/\dim))},{sin(90+\n*(360/\dim))}){};
  }   
\draw[redarrow](e)--(a);\draw[redarrow](a)--(a^2);\draw[redarrow](a^2)--(a^3);\draw[redarrow](a^3)--(e);
\end{tikzpicture} 

enter image description here


First answer :

\documentclass{article}
\usepackage{tikz}


\begin{document}

\tikzset{state/.style={circle,
                       draw=gray,
                       inner sep=0pt,
                       minimum size=7mm,
                       label=center:$#1$,
                       name=#1}}

\begin{center}
\begin{tikzpicture}

\def\labels{e,a,a^2,a^3}\def\dim{4}
\foreach \n [count=\ni] in \labels {% 
  \node[state={\n}] at ({cos(90+\ni*(360/\dim))},{sin(90+\ni*(360/\dim))}){};}  

\end{tikzpicture}

\end{center}
\end{document} 
share|improve this answer
    
I was building from the example on the top of p.529 of the TikZ-PGF manual (v. 2.10). Where did I go wrong in adapting that? –  raxacoricofallapatorius May 21 '12 at 22:19
1  
Ha ! there is an array structure inside pgfmath. I think you need to access values of the array with pgfmathparse. I will update my answer. –  Alain Matthes May 22 '12 at 6:01
    
Thanks. And thanks for keeping the old answer too for reference. That was also quite helpful. –  raxacoricofallapatorius May 22 '12 at 13:29

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.