summaryrefslogtreecommitdiff
path: root/graphics/pgf/base/doc/pgfmanual-en-library-lsystems.tex
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/pgf/base/doc/pgfmanual-en-library-lsystems.tex')
-rw-r--r--graphics/pgf/base/doc/pgfmanual-en-library-lsystems.tex390
1 files changed, 390 insertions, 0 deletions
diff --git a/graphics/pgf/base/doc/pgfmanual-en-library-lsystems.tex b/graphics/pgf/base/doc/pgfmanual-en-library-lsystems.tex
new file mode 100644
index 0000000000..4623eef5c2
--- /dev/null
+++ b/graphics/pgf/base/doc/pgfmanual-en-library-lsystems.tex
@@ -0,0 +1,390 @@
+% Copyright 2019 by Mark Wibrow
+%
+% This file may be distributed and/or modified
+%
+% 1. under the LaTeX Project Public License and/or
+% 2. under the GNU Public License.
+%
+% See the file doc/generic/pgf/licenses/LICENSE for more details.
+
+
+\section{Lindenmayer System Drawing Library}
+
+\subsection{Overview}
+
+Lindenmayer systems (also commonly known as ``L-systems''), were originally
+developed by Aristid Lindenmayer as a theory of algae growth patterns and then
+subsequently used to model branching patterns in plants and produce fractal
+patterns. Typically, an L-system consists of a set of symbols, each of which is
+associated with some graphical action (such as ``turn left'' or ``move
+forward'') and a set of rules (``production'' or ``rewrite'' rules). Given a
+string of symbols, the rewrite rules are applied several times and when the
+resulting string is processed the action associated with each symbol is
+executed.
+
+In \pgfname, L-systems can be used to create simple 2-dimensional fractal
+patterns\ldots
+%
+\begin{codeexample}[
+ preamble={\usetikzlibrary{lindenmayersystems}},
+ pre={\expandafter\let\csname pgf@lsystem@Koch curve\endcsname=\relax},
+]
+\begin{tikzpicture}
+\pgfdeclarelindenmayersystem{Koch curve}{
+ \rule{F -> F-F++F-F}
+}
+
+\shadedraw [top color=white, bottom color=blue!50, draw=blue!50!black]
+ [l-system={Koch curve, step=2pt, angle=60, axiom=F++F++F, order=3}]
+ lindenmayer system -- cycle;
+\end{tikzpicture}
+\end{codeexample}
+%
+\noindent\ldots and ``plant like'' patterns\ldots
+%
+\begin{codeexample}[preamble={\usetikzlibrary{lindenmayersystems}}]
+\begin{tikzpicture}
+\draw [green!50!black, rotate=90]
+ [l-system={rule set={F -> FF-[-F+F]+[+F-F]}, axiom=F, order=4, step=2pt,
+ randomize step percent=25, angle=30, randomize angle percent=5}]
+ lindenmayer system;
+\end{tikzpicture}
+\end{codeexample}
+%
+\noindent \ldots but it is important to bear in mind that even moderately
+complex L-systems can exceed the available memory of \TeX, and can be very
+slow. If possible, you are advised to increase the main memory and save stack
+to their maximum possible values for your particular \TeX{} distribution.
+However, even by doing this you may find you still run out of memory quite
+quickly.
+
+For an excellent introduction to L-systems (containing some ``really cool''
+pictures -- many of which are sadly not possible in \pgfname) see \emph{The
+Algorithmic Beauty of Plants} by Przemyslaw Prusinkiewicz and Aristid
+Lindenmayer (which is freely available via the internet).
+
+\begin{pgflibrary}{lindenmayersystems}
+ This \pgfname-library provides basic commands for defining and using simple
+ L-systems. The \tikzname-library provides, furthermore, a front end for
+ using L-systems in \tikzname.
+\end{pgflibrary}
+
+
+\subsubsection{Declaring L-systems}
+
+Before an L-system can be used, it must be declared using the following
+command:
+
+\begin{command}{\pgfdeclarelindenmayersystem\marg{name}\marg{specification}}
+ This command declares a Lindenmayer system called \meta{name}. The
+ \meta{specification} argument contains a description of the L-system's
+ symbols and rules. Two commands |\symbol| and |\rule| are only defined when
+ the \meta{specification} argument is executed.
+
+ \begin{command}{\symbol\marg{name}\marg{code}}
+ This defines a symbol called \meta{name} for a specific L-system,
+ and associates it with \meta{code}.
+
+ A symbol should consist of a single alpha-numeric character (i.e.,
+ |A|-|Z|, |a|-|z| or |0|-|9|). The symbols |F|, |f|, |+|, |-|, |[| and
+ |]| are available by default so do not need to be defined for each
+ L-system. However, if you are feeling adventurous, they can be
+ redefined for specific L-systems if required. The L-system treats the
+ default symbols as follows (the commands they execute are described
+ below):
+ %
+ \begin{itemize}
+ \item |F| move forward a certain distance, drawing a line. Uses
+ |\pgflsystemdrawforward|.
+ \item |f| move forward a certain distance, without drawing a line.
+ Uses |\pgflsystemmoveforward|.
+ \item |+| turn left by some angle. Uses |\pgflsystemturnleft|.
+ \item |-| turn right by some angle. Uses |\pgflsystemturnright|.
+ \item |[| save the current state (i.e., the position and
+ direction). Uses |\pgflsystemsavestate|.
+ \item |]| restore the last saved state. Uses
+ |\pgflsystemrestorestate|.
+ \end{itemize}
+
+ The symbols |[| and |]| act like a stack: |[| pushes the state of the
+ L-system on to the stack, and |]| pops a state off the stack.
+
+ When \meta{code} is executed, the transformation matrix is set up so
+ that the origin is at the current position and the positive x-axis
+ ``points forward'', so |\pgfpathlineto{\pgfpoint{1cm}{0cm}}| draws a
+ line 1cm forward.
+
+ The following keys can alter the production of an L-system. However,
+ they do not store values in themselves.
+
+ \begin{key}{/pgf/lindenmayer system/step=\meta{length} (initially 5pt)}
+ How far the L-system moves forward if required. This key sets the
+ \TeX{} dimension |\pgflsystemstep|.
+ \end{key}
+
+ \begin{key}{/pgf/lindenmayer system/randomize step percent=\meta{percentage} (initially 0)}
+ If the step is to be randomized, this key specifies by how much.
+ The value is stored in the \TeX{} macro
+ |\pgflsystemrandomizesteppercent|.
+ \end{key}
+
+ \begin{key}{/pgf/lindenmayer system/left angle=\meta{angle} (initially 90)}
+ This key sets the angle through which the L-system turns when it
+ turns left. The value is stored in the \TeX{} macro
+ |\pgflsystemrleftangle|.
+ \end{key}
+
+ \begin{key}{/pgf/lindenmayer system/right angle=\meta{angle} (initially 90)}
+ This key sets the angle through which the L-system turns when it
+ turns right. The value is stored in the \TeX{} macro
+ |\pgflsystemrrightangle|.
+ \end{key}
+
+ \begin{key}{/pgf/lindenmayer system/randomize angle percent=\meta{percentage} (initially 0)}
+ If the angles are to be randomized, this key specifies by how much.
+ The value is stored in the \TeX{} macro
+ |\pgflsystemrandomizeanglepercent|.
+ \end{key}
+
+ For speed and convenience, when the code for a symbol is executed, the
+ following commands are available.
+
+ \begin{command}{\pgflsystemcurrentstep}
+ The current ``step'' of the L-system (i.e., how far the system
+ will move forward if required). This is initially set to the
+ value in the \TeX-dimensions |\pgflsystemstep|, but the actual
+ value may be changed if |\pgflsystemrandomizestep| is used
+ (see below).
+ \end{command}
+
+ \begin{command}{\pgflsystemcurrentleftangle}
+ The angle the L-system will turn when it turns left.
+ The value stored in this macro may be changed if
+ |\pgflsystemrandomizeleftangle| is used.
+ \end{command}
+
+ \begin{command}{\pgflsystemcurrentrightangle}
+ The angle the L-system will turn when it turns right.
+ The value stored in this macro may be changed if
+ |\pgflsystemrandomizerightangle| is used.
+ \end{command}
+
+ The following commands may be useful if you wish to define your own
+ symbols.
+
+ \begin{command}{\pgflsystemrandomizestep}
+ Randomizes the value in |\pgflsystemcurrentstep| according to the
+ current value of the key |randomize step percent|.
+ \end{command}
+
+ \begin{command}{\pgflsystemrandomizeleftangle}
+ Randomizes the value in |\pgflsystemcurrentleftangle| according to
+ the value of the |randomize angle percent| key.
+ \end{command}
+
+ \begin{command}{\pgflsystemrandomizerightangle}
+ Randomizes the value in |\pgflsystemcurrentrightangle| according
+ to the value of the |randomize angle| key.
+ \end{command}
+
+ \begin{command}{\pgflsystemdrawforward}
+ Move forward in the current direction, by |\pgflsystemcurrentstep|,
+ drawing a line in the process. This macro calls
+ |\pgflsystemrandomizestep|. Internally, \pgfname{} simply shifts
+ the transformation matrix in the positive direction of the current
+ (transformed) x-axis by |\pgflsystemstep| and then executes a
+ line-to to the (newly transformed) origin.
+ \end{command}
+
+ \begin{command}{\pgflsystemmoveforward}
+ Move forward in the current direction, by |\pgflsystemcurrentstep|,
+ without drawing a line. This macro calls
+ |\pgflsystemrandomizestep|. \pgfname{} executes a transformation as
+ above, but executes a move-to to the (newly transformed) origin.
+ \end{command}
+
+ \begin{command}{\pgflsystemturnleft}
+ Turn left by |\pgflsystemcurrentleftangle|. Internally, \pgfname{}
+ simply rotates the transformation matrix. This macro calls
+ |\pgflsystemrandomizeleftangle|.
+ \end{command}
+
+ \begin{command}{\pgflsystemturnright}
+ Turn right by |\pgflsystemcurrentrightangle|. Internally,
+ \pgfname{} simply rotates the transformation matrix. This macro
+ calls |\pgflsystemrandomizerightangle|.
+ \end{command}
+
+ \begin{command}{\pgflsystemsavestate}
+ Save the current position and orientation. Internally, \pgfname{}
+ simply starts a new \TeX-group.
+ \end{command}
+
+ \begin{command}{\pgflsystemrestorestate}
+ Restore the last saved position and orientation. Internally,
+ \pgfname{} closes a \TeX-group, restoring the transformation matrix
+ of the outer scope, and a move-to command is executed to the
+ (transformed) origin.
+ \end{command}
+ \end{command}
+
+ \begin{command}{\rule{\ttfamily\char`\{}\meta{head}{\ttfamily->}\meta{body}{\ttfamily\char`\}}}
+ Declare a rule. \meta{head} should consist of a single symbol, which
+ need not have been declared using |\symbol| or exist as a default
+ symbol (in fact, the more interesting L-systems depend on using symbols
+ with no corresponding code, to control the ``growth'' of the system).
+ \meta{body} consists of a string of symbols, which again need not
+ necessarily have any code associated with them.
+ \end{command}
+
+ As an example, the following shows an L-system that uses some of these
+ commands. This example illustrates the point that some symbols, in this
+ case |A| and |B|, do not have to have code associated with them. They
+ simply control the growth of the system.
+ %
+\begin{codeexample}[
+ preamble={\usetikzlibrary{lindenmayersystems}},
+ pre={\nullfont\expandafter\let\csname pgf@lsystem@Hilbert curve\endcsname=\relax},
+]
+\pgfdeclarelindenmayersystem{Hilbert curve}{
+ \symbol{X}{\pgflsystemdrawforward}
+ \symbol{+}{\pgflsystemturnright} % Explicitly define + and - symbols.
+ \symbol{-}{\pgflsystemturnleft}
+ \rule{A -> +BX-AXA-XB+}
+ \rule{B -> -AX+BXB+XA-}
+}
+\tikz\draw[lindenmayer system={Hilbert curve, axiom=A, order=4, angle=90}]
+ lindenmayer system;
+\end{codeexample}
+ %
+\end{command}
+
+
+\subsection{Using Lindenmayer Systems}
+
+\subsubsection{Using L-Systems in PGF}
+
+The following command is used to run an L-system in \pgfname:
+%
+\begin{command}{\pgflindenmayersystem\marg{name}\marg{axiom}\marg{order}}
+ Runs the L-system called \meta{name} using the input string \meta{axiom}
+ for \meta{order} iterations. In general, prior to calling this command, the
+ transformation matrix should be set appropriately for shifting and
+ rotating, and a move-to to the (transformed) origin should be executed.
+ This origin will be where the L-system starts. In addition, the relevant
+ keys should be set appropriately.
+ %
+\begin{codeexample}[preamble={\usetikzlibrary{lindenmayersystems}}]
+\begin{tikzpicture}
+ \draw [help lines] grid (3,2);
+ \pgfset{lindenmayer system/.cd, angle=60, step=2pt}
+ \foreach \x/\y in {0cm/1cm, 1.5cm/1.5cm, 2.5cm/0.5cm, 1cm/0cm}{
+ \pgftransformshift{\pgfqpoint{\x}{\y}}
+ \pgfpathmoveto{\pgfpointorigin}
+ \pgflindenmayersystem{Koch curve}{F++F++F}{2}
+ \pgfusepath{stroke}
+ }
+\end{tikzpicture}
+\end{codeexample}
+
+ Note that it is perfectly feasible for an L-system to define special
+ symbols which perform the move-to and use-path operations.
+ %
+\end{command}
+
+
+\subsubsection{Using L-Systems in Ti\emph{k}Z}
+
+In \tikzname, an L-system is created using a path operation. However,
+\tikzname{} is more flexible regarding the positioning of the L-system and also
+provides keys to create L-systems ``on-line''.
+
+\begin{pathoperation}{lindenmayer system}{ \opt{|[|\meta{keys}|]|}}
+ This will run an L-system according to the parameters specified in
+ \meta{keys} (which can also contain normal \tikz{} keys such as |draw| or
+ |thin|). The syntax is flexible regarding the L-system parameters and the
+ following all do the same thing:
+ %
+\begin{codeexample}[code only]
+\draw lindenmayer system [lindenmayer system={Hilbert curve, axiom=4, order=3}];
+\end{codeexample}
+
+\begin{codeexample}[code only]
+\draw [lindenmayer system={Hilbert curve, axiom=4, order=3}] lindenmayer system;
+\end{codeexample}
+
+\begin{codeexample}[code only]
+\tikzset{lindenmayer system={Hilbert curve, axiom=4, order=3}}
+\draw lindenmayer system;
+\end{codeexample}
+ %
+\end{pathoperation}
+
+\begin{pathoperation}{l-system}{ \opt{|[|\meta{keys}|]|}}
+ A more compact version of the |lindenmayer system| path command.
+\end{pathoperation}
+
+This library adds some additional keys for specifying L-systems. These keys
+only work in \tikzname{} and all have the same path, namely, |/pgf/lindenmayer|
+|system|, but the following keys are provided for convenience, so that you do
+not have to keep repeating this path:
+
+\begin{stylekey}{/pgf/lindenmayer system=\marg{keys}}
+\keyalias{tikz}
+ This key changes the key path to |/pgf/lindenmayer systems| and executes
+ \meta{keys}.
+\end{stylekey}
+
+\begin{stylekey}{/pgf/l-system=\marg{keys}}
+\keyalias{tikz}
+ A more compact version of the previous key.
+\end{stylekey}
+
+\begin{key}{/pgf/lindenmayer system/name=\marg{name}}
+ Sets the name for the L-system.
+\end{key}
+
+\begin{key}{/pgf/lindenmayer system/axiom=\marg{string}}
+ Sets the axiom (or input string) for the L-system.
+\end{key}
+
+\begin{key}{/pgf/lindenmayer system/order=\marg{integer}}
+ Sets the number of iterations the L-system will perform.
+\end{key}
+
+\begin{key}{/pgf/lindenmayer system/rule set=\marg{list}}
+ This key allows an (anonymous) L-system to be declared ``on-line''. There
+ is, however, a restriction that only the default symbols can be used for
+ drawing (empty symbols can still be used to control the growth of the
+ system). The rules in \meta{list} should be separated by commas.
+ %
+\begin{codeexample}[preamble={\usetikzlibrary{lindenmayersystems}}]
+\tikz[rotate=65]\draw [green!60!black] l-system
+ [l-system={rule set={F -> F[+F]F[-F]}, axiom=F, order=4, angle=25,step=3pt}];
+\end{codeexample}
+ %
+\end{key}
+
+\begin{key}{/pgf/lindenmayer system/anchor=\meta{anchor}}
+ Be default, when this key is not used, the L-system will start from the
+ last specified coordinate. By using this key, the L-system will be placed
+ inside a special (rectangle) node which can be positioned using
+ \meta{anchor}.
+ %
+\begin{codeexample}[preamble={\usetikzlibrary{lindenmayersystems}}]
+\begin{tikzpicture}[l-system={step=1.75pt, order=5, angle=60}]
+ \pgfdeclarelindenmayersystem{Sierpinski triangle}{
+ \symbol{X}{\pgflsystemdrawforward}
+ \symbol{Y}{\pgflsystemdrawforward}
+ \rule{X -> Y-X-Y}
+ \rule{Y -> X+Y+X}
+ }
+ \draw [help lines] grid (3,2);
+ \draw [red] (0,0) l-system
+ [l-system={Sierpinski triangle, axiom=+++X, anchor=south west}];
+ \draw [blue] (3,2) l-system
+ [l-system={Sierpinski triangle, axiom=X, anchor=north east}];
+\end{tikzpicture}
+\end{codeexample}
+ %
+\end{key}