Drawing the dragon curve
A solution using Plain TeX macros and LaTeX's picture environment (enhanced by pict2e package).
Update adds variant with rounded corners (see end of answer).
and this time starting rightwards (animation updated):
Variant with rounded corners at bottom.
\documentclass[multi=picture,ignorerest=false]{standalone}
% convert -density 150 -verbose -delay 40 -dispose None DG/dragoncurve.* -delay 200 DG/dragoncurve.13.png -loop 0 dragoncurve.gif
\usepackage{pict2e}
\usepackage{color}
\usepackage{picture}
\newcount\X % integer horizontal coordinate
\newcount\Y % integer vertical coordinate
\newdimen\E % initial scale
\E 4cm
\newcount\Iter % iteration level, for displaying
\Iter = 1
\newcount\DeltaX
\newcount\DeltaY
% initial direction for first drawn Dragon curve (has two segments)
\DeltaX = -1
\DeltaY = 1
\let\LL\relax
\let\RR\relax
\def\Dragon {\L}
\def\IterateDragon {\advance\Iter 1
% adjust initial direction, rotating 45 degrees clockwise
\count255 = \DeltaX
\advance\DeltaX by \DeltaY
\advance\DeltaY by -\count255
% adjust scale
\E = 0.5\E
% apply rules
\def\L{\noexpand\L\LL\noexpand\R}%
\def\R{\noexpand\L\RR\noexpand\R}%
\edef\Dragon{\Dragon}%
}
% draw one segment in given direction and with current scale
\def\DrawSegment {\advance\X\DeltaX
\advance\Y\DeltaY
\lineto(\X,\Y)}
\def\DrawDragon {%
\setlength{\unitlength}{\E}%
\begin{picture}(13cm,9cm)(-9.5cm,-3cm)
\linethickness{1.5pt}%
\def\L {\count255 = \DeltaX
\DeltaX = -\DeltaY
\DeltaY = \count255
\DrawSegment }%
\def\R {\count255 = \DeltaX
\DeltaX = \DeltaY
\DeltaY = -\count255
\DrawSegment }%
\let\LL\L
\let\RR\R
\X = 0
\Y = 0
\put(0,0){\textcolor{blue}{\phantom{x}\the\Iter}}
\moveto(0,0)
\DrawSegment
\Dragon
\strokepath
\end{picture}}
\begin{document}
\ttfamily
\DrawDragon
\IterateDragon
\DrawDragon
\IterateDragon
\DrawDragon
\IterateDragon
\DrawDragon
\IterateDragon
\DrawDragon
\IterateDragon
\DrawDragon
\IterateDragon
\DrawDragon
\IterateDragon
\DrawDragon
\IterateDragon
\DrawDragon
\IterateDragon
\DrawDragon
\IterateDragon
\DrawDragon
% twelfth .. slow
\IterateDragon
\DrawDragon
% thirteenth .... sloooww
\IterateDragon
\DrawDragon
\end{document}
Code variant for rounded corners:
\documentclass[multi=picture,ignorerest=false]{standalone}
% convert -density 75 -verbose -dispose none -delay 100 -- DG3/dragoncurve3.* -delay 200 DG3/dragoncurve3.12.png -loop 0 dragoncurve3.gif
\usepackage{pict2e}
\usepackage{color}
\usepackage{picture}
\newcount\X % integer horizontal coordinate
\newcount\Y % integer vertical coordinate
% for convenience another pair
\newcount\x
\newcount\y
\newdimen\E % initial scale
\E 1cm
\newcount\Iter % iteration level, for displaying
\Iter = 1
\newcount\DeltaX
\newcount\DeltaY
% initial direction for first drawn Dragon curve (has two segments)
% this version goes rightward
\DeltaX = 1
\DeltaY = -1
% for convenience another pair
\newcount\deltax
\newcount\deltay
% (the first iterate goes down then up, thus turning left).
\def\Dragon {\L}
\def\IterMode {%
\let\LL\relax
\let\RR\relax
%
\def\L{\noexpand\L\LL\noexpand\R}%
\def\R{\noexpand\L\RR\noexpand\R}%
}
\def\DrawMode {%
\def\L {\deltax = -\DeltaY
\deltay = \DeltaX
\DrawArc
}%
\def\R {\deltax = \DeltaY
\deltay = -\DeltaX
\DrawArc
}%
\let\LL\L
\let\RR\R
}
\def\DrawArc {%
\x\numexpr \X + 2*\DeltaX + 2*\deltax\relax
\y\numexpr \Y + 2*\DeltaY + 2*\deltay\relax
\curveto
(\numexpr\X+\DeltaX\relax,\numexpr\Y+\DeltaY\relax)%
(\numexpr\x-\deltax\relax,\numexpr\y-\deltay\relax)%
(\x,\y)%
\X\x
\Y\y
\DeltaX\deltax
\DeltaY\deltay
}%
\def\IterateDragon {%
\global\advance\Iter 1
% adjust initial direction, rotating 45 degrees clockwise
\count255 = \DeltaX
\global\advance\DeltaX by \DeltaY
\global\advance\DeltaY by -\count255
% adjust scale
\global\E = 0.5\E
% apply rules and modify \Dragon globally
\IterMode
\xdef\Dragon{\Dragon}%
}
\def\DrawDragonPath #1{%
\linethickness{#1}%
\ifodd\Iter\color{red}\else\color{blue}\fi
\moveto(0,0)
\X\numexpr2*\DeltaX\relax
\Y\numexpr2*\DeltaY\relax
\lineto(\X,\Y)
\DrawMode
\Dragon
\X\numexpr\X+2*\DeltaX\relax
\Y\numexpr\Y+2*\DeltaY\relax
\lineto(\X,\Y)
\strokepath
}%
\def\DrawOneDragon #1{%
\setlength{\unitlength}{\E}%
\begin{picture}(12.35cm,8.6cm)(-2.85cm,-5.6cm)
\DrawDragonPath {#1}%
\put(0,0){\llap{\the\Iter\phantom{x}}}%
\end{picture}%
}
\def\DrawTwoDragons {% draws AND iterates once to get next curve too.
\setlength{\unitlength}{\E}%
\begin{picture}(12.35cm,8.6cm)(-2.85cm,-5.6cm)
% je fais ça vite fait, car avec convert je n'ai pas vu comment avoir deux
% rémanences, donc on fait deux dessins ici.
% we store initial direction:
\count2=\DeltaX
\count4=\DeltaY
\DrawDragonPath {1pt}%
% restore initial direction (which will be rotated 45° by \IterateDragon)
\DeltaX \count2
\DeltaY \count4
\IterateDragon % does \IterMode, makes global changes to \Dragon etc...
% compensate (only in this picture) for scale being left the same.
\divide\DeltaX by 2
\divide\DeltaY by 2
\DrawDragonPath {1.5pt}%
\put(0,0){\llap{\the\Iter\phantom{x}}}%
\end{picture}%
}
\begin{document}
\ttfamily
\DrawOneDragon {1.5pt}%1
\DrawTwoDragons %2
\DrawTwoDragons %3
\DrawTwoDragons %4
\DrawTwoDragons %5
\DrawTwoDragons %6
\DrawTwoDragons %7
\DrawTwoDragons %8
\DrawTwoDragons %9
\DrawTwoDragons %10
\DrawTwoDragons %11
\DrawOneDragon {1pt}%
\end{document}
As a Lindenmayer system, the dragon curve can be presented by
angle 90°
initial string FX
string rewriting rules
X ↦ X+YF+
Y ↦ −FX−Y.
so we have a simple TikZ solution using lindenmayersystems
library:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{lindenmayersystems}
\begin{document}
\fbox{%
\tikz[rotate=65]
\draw[green!60!black]
l-system
[l-system={
rule set={X -> X+YF+,Y->-FX-Y},
axiom=FX,
angle=90,
order=12,
step=5pt
}
];
}
\end{document}
Changing to order=14
and reducing the step to 2pt
gives:
And my computer reports pretty decent times:
real 0m48.379s
user 0m46.404s
sys 0m0.120s
However, order=15
already produces the dreadful TeX capacity exceeded!
error.
A little beamer
animation up to order 12:
\documentclass{beamer}
\usepackage{tikz}
\usetikzlibrary{lindenmayersystems}
\begin{document}
\begin{frame}
\centering
\tikz
\foreach \Valor in {1,2,...,12}
\draw<\Valor>[green!60!black]
l-system
[l-system={
rule set={X -> X+YF+,Y->-FX-Y},
axiom=FX,
angle=90,
order=\Valor,
step=3pt
}
];
\end{frame}
\end{document}
Rounded version
The rounded version is obtained simply by adding rounded corners=<length>
to the options for the \draw
; a little example of order 11:
\documentclass[border=3pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{lindenmayersystems}
\begin{document}
\tikz
\draw[green!60!black,rounded corners=4pt]
l-system
[l-system={
rule set={X -> X+YF+,Y->-FX-Y},
axiom=FX,
angle=90,
order=11,
step=10pt
}
];
\end{document}
The result:
Twindragon
The Davis-Knuth dragon can also be easily obtained:
\documentclass[tikz,border=3pt]{standalone}
\usetikzlibrary{lindenmayersystems}
\begin{document}
\tikz\draw[line width=1pt,green!60!black,rounded corners]
l-system
[l-system={
rule set={X -> X+YF,Y->FX-Y},
axiom=FX+FX+,
angle=90,
order=12,
step=10pt
}
];
\end{document}
Here is one implementation, using PSTricks.
The sequence is generated via repetitive string replacements using xstring
's \StrSubstitute
:
\documentclass{article}
\usepackage[paper=a3paper,landscape,margin=0pt]{geometry}
\usepackage{etoolbox,pstricks,xstring,multido}
\pagestyle{empty}
\begin{document}
\begin{pspicture}(-25cm,-10cm)(10cm,7cm)
\psset{unit=5mm}
\SpecialCoor
\def\dragoncurve{L,1R}% Starting fold
\multido{\i=0+1}{10}{% Add 10 more folds
% Add fold
\StrSubstitute{\dragoncurve}{L}{L,1P}[\dragoncurve]% L -> L1P
\StrSubstitute{\dragoncurve}{R}{L,0R}[\dragoncurve]% R -> L0R
\StrSubstitute{\dragoncurve}{P}{R}[\dragoncurve]% P -> R
\xdef\dragoncurve{\dragoncurve}% Make definition global
}
\StrSubstitute{\dragoncurve}{L}{}[\dragoncurve]% Drop L
\StrSubstitute{\dragoncurve}{R}{}[\dragoncurve]% Drop R
\StrSubstitute[1]{\dragoncurve}{,}{}[\dragoncurve]% Drop first ,
\def\nextangle{0}% Starting angle
\pscustom[linewidth=.1pt]{
\psline(0,0)% Initial node
\renewcommand{\do}[1]{
\rlineto(1;\nextangle)% Draw next line
\xdef\nextangle{\number\numexpr\nextangle+\ifnum#1=1 (-90)\else (90)\fi}
}%
\expandafter\docsvlist\expandafter{\dragoncurve}% Process dragon curve
\rlineto(1;\nextangle)% Draw final line
}
\end{pspicture}
\end{document}
The production is only limited by TeX's memory. With the default settings, perhaps 12 folds can be made (compiling for a very long time, and having to use a very large paper size or adjustments to the unit
and/or runit
).