29

I want to use tikz to draw a golden spiral, growing clockwise, ideally (but not necessarily) superimposed over a set of golden rectangles (you all know the image I'm talking about). A little bit of searching led me to this code, which yields a counterclockwise spiral:

\documentclass[tikz]{standalone}
\usetikzlibrary{decorations.markings,calc}
\tikzset{nctopath/.style={
     to path=(\tikztostart) ..controls ($(\tikztostart)!1cm*#1!-90:(\tikztotarget)$) and 
        ($(\tikztotarget)!($(\tikztostart)!1cm*#1!-50:(\tikztotarget)$)!70:    (\tikztostart)$).. 
    (\tikztotarget)
    },
}
\begin{document}    
\begin{tikzpicture}
\def\totx{1}
\coordinate (n-1-1) at (0,0) {};
\foreach \x[count=\xi from 2, evaluate=\x as \temptotx using int(\x+\totx)] in {1,...,9}{
\draw[decoration={
    markings,mark=between positions 0 and 1 step 0.249 with {
            \coordinate (n-\x-\pgfkeysvalueof{/pgf/decoration/mark info/sequence number})     ;
        }
   },postaction=decorate
] 
(n-\x-1) arc (\x*90+180:(\x+1)*90+180:{(\temptotx)*3mm}) 
coordinate (n-\xi-1) 
\pgfextra{\xdef\totx{\temptotx}};
}

\end{tikzpicture}
\end{document}

The thing is that I'm still new to tikz and thus not sure what code here does what. My questions are:

  1. How do I reverse the growth direction?

  2. How do I set phi as the growth factor (which I don't think it is currently, just from looking at the resulting spiral)?

  3. How cumbersome would it be to add in the golden rectangles (i.e., would I have to draw each one individually, or is there some way to define a pattern)?

3 Answers 3

61

Basically, the same approach as JLDiaz but using a recursive macro and letting tikz scopes and transformations do all the work.

\documentclass[tikz, border=0.125cm]{standalone}
\begin{document}

\def\spiral#1{%
  \pgfmathparse{int(#1)}%
  \ifnum\pgfmathresult>0
    \draw [help lines] (0,0) rectangle ++(1,1);
    \begin{scope}[shift={(1,1)}, rotate=90, scale=1/1.6180339887]
      \spiral{#1-1}
    \end{scope}
    \draw [red] (0,0) arc (270:360:1);
  \fi
}

\tikz[scale=2]{\spiral{12}}

\end{document}

enter image description here

And perhaps...

\documentclass[border=0.125cm, tikz]{standalone}

\begin{document}

\def\spiral#1#2#3{%
  \pgfmathparse{int(#1)}%
  \ifnum\pgfmathresult>0
    \draw [help lines] (0,0) rectangle ++(1,1);
    \begin{scope}[shift={(1,1)}, rotate=#2, scale=1/#3]
      \spiral{#1-1}{#2}{#3}%
    \end{scope}
    \pgfmathparse{int(\a)}%
    \ifnum\pgfmathresult=0
      \draw [red] (0,0) -- (1,1);
    \else%
      \draw [red] (0,0) arc (270+45-#2/2:360-45+#2/2:{1/sqrt(2) / sin(#2/2)});
    \fi
  \fi
}

\foreach \a in {90,85,...,-90,-85,-80,...,85}{
 \tikz[scale=2]{\spiral{12}{\a}{1.6180339887}\useasboundingbox (-0.5,-0.5) rectangle (3.5,3.5);}
}

\end{document}

enter image description here

9
  • 2
    +1 the spiral gets drawn on top of the squares, without need of layers. Smart!
    – JLDiaz
    Nov 23, 2013 at 19:06
  • 10
    What a nice animation!
    – juliohm
    Nov 23, 2013 at 23:32
  • Whoa! How did you do the animation?
    – crmdgn
    Nov 24, 2013 at 16:03
  • @crmdgn gimp is ideal for this kind of thing. Nov 24, 2013 at 18:57
  • As in gimp the photo editor? or is there a gimp TeX package?
    – crmdgn
    Nov 24, 2013 at 20:35
27

Code

Improved a little the code to make easier the explanations, and to put the "golden ratio rectangles" in a background layer. Explanations below the picture.

Updated after egreg's comments.

\documentclass{article}
\usepackage{tikz}
\begin{document}
\thispagestyle{empty}
\usetikzlibrary{calc}

\pgfdeclarelayer{background}
\pgfsetlayers{background,main}

\newcommand\GoldenRatio{1.6180339887}
\newcommand\Side{10}
\newcommand\Sqrtwo{1.4142135624}

\begin{tikzpicture}[line cap=round]
\coordinate (origin) at (0,0);
\foreach \angle in {0,90,...,1000} {
  \coordinate (corner) at ($(origin)+(45+\angle:\Side*\Sqrtwo)$);
  \begin{pgfonlayer}{background}
      \draw[help lines] (origin) rectangle (corner);
  \end{pgfonlayer}
  \draw[very thick,red] (origin) arc(\angle-90:\angle:\Side);
  \coordinate (origin) at (corner);
  \pgfmathsetmacro{\Side}{\Side/\GoldenRatio}
  \xdef\Side{\Side}
}
\end{tikzpicture}
\end{document}

Result

Result

Explanations

The picture is built recursively, from a fundamental building block, which is a square containing a red arc.

The square is defined from two points. The first one is called origin, and initially is located at (0,0), but it will move in successive iterations of the loop. The second one is called corner, and its coordinates are dependent of those of origin in the following way:

  \coordinate (corner) at ($(origin)+(45+\angle:\Side*\Sqrtwo)$);

The expression +(45+\angle:\Side*\Sqrtwo) uses polar coordinates, relative to origin. The angle is 45 plus the "current angle" (initially zero), and the distance is the diagonal of the square whose side has \Side units of length.

Once origin and corner are known, the building block is drawn as (omitted in this case the background layer for clarity):

  \draw[help lines] (origin) rectangle (corner);
  \draw[very thick,red] (origin) arc(\angle-90:\angle:\Side);

In the first iteration, since \angle=0, \Side=10, this produces the following building block, whose side has 10 units of length:

Building block

Now, the neat trick is to update all the variables which define the building block, so that the next building block has:

  • Its origin at the previous block corner
  • Its \angle increased in 90 degrees
  • Its \Side reduced in the golden ratio.

This is the role of the next lines:

  \coordinate (origin) at (corner);
  \pgfmathsetmacro{\Side}{\Side/\GoldenRatio}
  \xdef\Side{\Side}

The following figure shows the two first iterations, and thus the two first building blocks. I decided to draw also in blue the vector which places the "corner" relative to the origin, to better understand the procedure:

Two steps

And so on, at each step the building block is reduced by the golden ratio, rotated 90 degrees, and shifted to the latest "corner".

11
  • I'll be damned. That's exactly what I need. Super curious to see the explanation, whenever you have time.
    – crmdgn
    Nov 23, 2013 at 15:44
  • @crmdgn Also note that what I have drawn is an approximation of a "true" golden spiral, as noted here
    – JLDiaz
    Nov 23, 2013 at 16:18
  • Very good answer; I have two remarks, though. Don't use \def, first of all, much less redefine \Phi in the open. Then, what's the sense of giving the golden ratio with three decimal digits and the square root of 2 with nineteen?
    – egreg
    Nov 23, 2013 at 16:19
  • @egreg What's the issue with \def and with defining \Phi?
    – crmdgn
    Nov 23, 2013 at 16:27
  • 1
    @JLDiaz With \newcommand{\Phi}{1.618} you'd have been warned that \Phi is already defined.
    – egreg
    Nov 23, 2013 at 16:36
17

Just for fun with PSTricks. No recursively-invoked macro is used here. Instead, the next node is determined by the previous one in a loop.

Linear complexity

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{pst-node,multido}
\psset{dimen=monkey}

\pstVerb
{
    /R   5 def
    /P   {2 5 sqrt 1 add div} def
    /p   {1 P div} def
    /OmP {1 P sub} def
    /C   {2 sqrt mul 45 PtoC} def
}

\def\Atom#1{%
\begin{pspicture}(-4,-1)(6,6)
    \pnode(!p 1 sub R mul neg 0 ){A-1}
    \multido{\ic=0+1,\ip=-1+1}{#1}
    {%
        \nodexn{(A\ip)+(!\ic\space dup 1 sub P exch exp R mul OmP mul exch 90 mul PtoC)}{A\ic}
        \rput(A\ic){\rput{!90 \ic\space mul}(0,0){\psframe(!R P \ic\space exp mul C)}}
    }
    \pscustom[linecolor=red]{\multido{\ic=0+1}{#1}{\psarc(A\ic){!R P \ic\space exp mul}{!\ic\space 90 mul}{!\ic\space 90 mul 90 add}}}
\end{pspicture}}

\begin{document}
\multido{\i=0+1}{12}{\Atom{\i}}
\end{document}

enter image description here

Quadratic complexity

It is not recommended as creating the i-th node needs i iterations.

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{pst-node,pst-plot}
\psset{dimen=monkey}

\pstVerb
{
    /R   5 def
    /P   {2 5 sqrt 1 add div} def
    /p   {1 P div} def
    /OmP {1 P sub} def
    /C   {2 sqrt mul 45 PtoC} def
}

\def\Atom#1{%
\begin{pspicture}(-4,-1)(6,6)
    \curvepnodes[plotpoints=#1]{0}{\the\numexpr#1-1\relax}
    {
        p 1 sub R mul neg 0 
        0 1 t
        {
          dup 1 sub P exch exp R mul OmP mul exch 90 mul PtoC
            3 -1 roll add 3 1 roll add exch 
        } for 
    }{A}
    \multido{\ic=0+1}{#1}{\rput(A\ic){\rput{!90 \ic\space mul}(0,0){\psframe(!R P \ic\space exp mul C)}}}
    \pscustom[linecolor=red]{\multido{\ic=0+1}{#1}{\psarc(A\ic){!R P \ic\space exp mul}{!\ic\space 90 mul}{!\ic\space 90 mul 90 add}}}
\end{pspicture}}

\begin{document}
\multido{\i=2+1}{12}{\Atom{\i}}
\end{document}

Closed form

In progress...

1
  • I will edit this answer later as I have many things to do right now. The quadratic complexity can be converted to be linear with temporary variables as explained by Christoph in another topic on this site. Nov 26, 2013 at 22:14

You must log in to answer this question.

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