2

I would like to draw some circles and some squares and I would like to put in into a loop. But that does not seem to work. Any help would be great.

\documentclass[tikz]{standalone}

\usepackage{xfp} % floating point unit f\"ur fpeval

\usepackage{tikz}
\usetikzlibrary{quotes}

\begin{document}
   \begin{tikzpicture}
      \edef\r{1.0}

         \draw circle (\r);
         \draw (-1.0*\r,\r) to (\r,\r); % oben
         \draw (-1.0*\r,-1.0*\r) to (1.0*\r,-1.0*\r); % unten
         \draw (-1.0*\r,0) to ["\fpeval{\r}"] (-1.0*\r,1.0*\r); % Mitte
         \draw (-1.0*\r,-1.0*\r) to (-1.0*\r,1.0*\r); % links
         \draw (1.0*\r,-1.0*\r) to (1.0*\r,1.0*\r); % rechts
         \pgfmathparse{sqrt(\r^2 + \r^2)}\edef\r{\pgfmathresult};

         \draw circle (\r);
         \draw (-1.0*\r,\r) to (\r,\r); % oben
         \draw (-1.0*\r,-1.0*\r) to (1.0*\r,-1.0*\r); % unten
         \draw (-1.0*\r,0) to ["\fpeval{\r}"] (-1.0*\r,1.0*\r); % Mitte
         \draw (-1.0*\r,-1.0*\r) to (-1.0*\r,1.0*\r); % links
         \draw (1.0*\r,-1.0*\r) to (1.0*\r,1.0*\r); % rechts
         \pgfmathparse{sqrt(\r^2 + \r^2)}\edef\r{\pgfmathresult};

         \draw circle (\r);
         \draw (-1.0*\r,\r) to (\r,\r); % oben
         \draw (-1.0*\r,-1.0*\r) to (1.0*\r,-1.0*\r); % unten
         \draw (-1.0*\r,0) to ["\fpeval{\r}"] (-1.0*\r,1.0*\r); % Mitte
         \draw (-1.0*\r,-1.0*\r) to (-1.0*\r,1.0*\r); % links
         \draw (1.0*\r,-1.0*\r) to (1.0*\r,1.0*\r); % rechts
         \pgfmathparse{sqrt(\r^2 + \r^2)}\edef\r{\pgfmathresult};

         \draw circle (\r);
         \draw (-1.0*\r,\r) to (\r,\r); % oben
         \draw (-1.0*\r,-1.0*\r) to (1.0*\r,-1.0*\r); % unten
         \draw (-1.0*\r,0) to ["\fpeval{\r}"] (-1.0*\r,1.0*\r); % Mitte
         \draw (-1.0*\r,-1.0*\r) to (-1.0*\r,1.0*\r); % links
         \draw (1.0*\r,-1.0*\r) to (1.0*\r,1.0*\r); % rechts
         \pgfmathparse{sqrt(\r^2 + \r^2)}\edef\r{\pgfmathresult};

         \draw circle (\r);
         \draw (-1.0*\r,\r) to (\r,\r); % oben
         \draw (-1.0*\r,-1.0*\r) to (1.0*\r,-1.0*\r); % unten
         \draw (-1.0*\r,0) to ["\fpeval{\r}"] (-1.0*\r,1.0*\r); % Mitte
         \draw (-1.0*\r,-1.0*\r) to (-1.0*\r,1.0*\r); % links
         \draw (1.0*\r,-1.0*\r) to (1.0*\r,1.0*\r); % rechts
         \pgfmathparse{sqrt(\r^2 + \r^2)}\edef\r{\pgfmathresult};

      \foreach \I in {1, ..., 5}{
         \draw circle (\r);
         \draw (-1.0*\r,\r) to (\r,\r); % oben
         \draw (-1.0*\r,-1.0*\r) to (1.0*\r,-1.0*\r); % unten
         \draw (-1.0*\r,0) to ["\fpeval{\r}"] (-1.0*\r,1.0*\r); % Mitte
         \draw (-1.0*\r,-1.0*\r) to (-1.0*\r,1.0*\r); % links
         \draw (1.0*\r,-1.0*\r) to (1.0*\r,1.0*\r); % rechts
         \pgfmathparse{sqrt(\r^2 + \r^2)}\edef\r{\pgfmathresult};
      }
   \end{tikzpicture}
\end{document}
3
  • Assignments in the body of the \foreach loop are local. You'll need \xdef (which is \global\edef) or use the evaluate and the remember option of \foreach. Aug 29, 2022 at 9:04
  • That sounds good. But to be honest, this is my first try with tikz. What do I have to do with evaluate and remember?
    – Andreas
    Aug 29, 2022 at 9:09
  • I just changed from edef to xdef. That seems to work. (Great) But does it also work with more similar figures?
    – Andreas
    Aug 29, 2022 at 9:12

2 Answers 2

4

With use of the \pgfmathsetmacro, nodes and labels above nodes (concept is quite similar to nice @Qrrbrbirlbel answer: +1):

\documentclass[margin=3mm, tikz]{standalone}

\usepackage{xfp} % floating point unit f\"ur fpeval

\usepackage{tikz}
\usetikzlibrary{quotes}
\usepackage{pgfmath}

\begin{document}
   \begin{tikzpicture}[
every label/.style = {font=\footnotesize}
                        ]
      \edef\r{1.0}
\foreach \i in {0,1,...,4}
{
   \pgfmathsetmacro{\R}{+sqrt(2)^\i*\r} %
\node[draw, minimum size=2*\R cm, label=\R] {};
\node[circle, draw, minimum size=2*\R cm] {};
}
   \end{tikzpicture}
\end{document}

enter image description here

1
  • Thanks al lot for your helpful hints.
    – Andreas
    Aug 30, 2022 at 16:12
8

Assignments in the body of a \foreach loop are local. You can use make them global by using \global\edef/\xdef

\pgfmathparse{sqrt(\r^2 + \r^2)}\xdef\r{\pgfmathresult}

however this will destroy the original definition of \r (putting a diacritic ring on a letter). Even if you don't need that, I'd advise against it.

The \foreach macro offers much better options:

In your case, you'll want something like this:

\foreach \I[
  evaluate={\nextR = \r * sqrt 2;},
  remember=\nextR as \r (initially 1)
] in {1, ..., 5}{

For every instance \foreach will evaluate \r * sqrt 2 (equivalnt to your original sqrt(\r^2+\r^2)) and store it in \nextR, as if you've done

\pgfmathsetmacro\nextR{\r * sqrt 2}

and this evaluated \nextR will be the \r of the next loop, except for the first time where \r will be 1 (declared by using (initially 1)).

I've taken the liberty to draw the square using the rectangle path operation (alternative link) and using the modern syntax for specifying the radius of a circle (radius=… instead of (…)).

Code

\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}
\foreach \i[
  evaluate={\nextR = \r * sqrt 2;},
  remember=\nextR as \r (initially 1)
] in {1,...,10} {
\draw circle[radius=\r]
  (-\r, -\r) rectangle (\r,\r)
  node[left] at (-\r,.5*\r) {\pgfmathprintnumber{\r}}
  ;
}
\end{tikzpicture}
\end{document}

Output

enter image description here

2
  • Off-topic: With the through and the fit library we can do \node[draw,circle through=(0:1)](c){};\node[draw,fit=(c),inner sep=0pt](r){};\foreach\i in{1,...,10}{\node[draw,circle through=(r.north east)](c){};\node[draw,fit=(c),inner sep=0pt](r){};} Aug 29, 2022 at 9:40
  • Thanks al lot for your helpful hints.
    – Andreas
    Aug 30, 2022 at 16:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .