diff options
author | Karl Berry <karl@freefriends.org> | 2006-01-09 00:56:57 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2006-01-09 00:56:57 +0000 |
commit | f07bb53970ee2ecc53f81a206a3d3a67ef665e4a (patch) | |
tree | 6f57a1d62971db79e5ff023bdfd83b22cb971dc9 /Master/texmf-dist/doc/generic/pgf/text-en/pgfmanual-en-base-snakes.tex | |
parent | 007f67a693e4d031fd3d792df8e4d5f43e2cb2e7 (diff) |
doc 6
git-svn-id: svn://tug.org/texlive/trunk@85 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/doc/generic/pgf/text-en/pgfmanual-en-base-snakes.tex')
-rw-r--r-- | Master/texmf-dist/doc/generic/pgf/text-en/pgfmanual-en-base-snakes.tex | 391 |
1 files changed, 391 insertions, 0 deletions
diff --git a/Master/texmf-dist/doc/generic/pgf/text-en/pgfmanual-en-base-snakes.tex b/Master/texmf-dist/doc/generic/pgf/text-en/pgfmanual-en-base-snakes.tex new file mode 100644 index 00000000000..6c23140fbe7 --- /dev/null +++ b/Master/texmf-dist/doc/generic/pgf/text-en/pgfmanual-en-base-snakes.tex @@ -0,0 +1,391 @@ +% Copyright 2003 by Till Tantau <tantau@cs.tu-berlin.de>. +% +% This program can be redistributed and/or modified under the terms +% of the LaTeX Project Public License Distributed from CTAN +% archives in directory macros/latex/base/lppl.txt. + + +\section{Snakes} + +\label{section-base-snakes} + +\subsection{Overview} + +A \emph{snake} is a ``way of adding a winding line to a path.'' To be +a bit more precise, you use snakes to extend the path and the +commands for using snakes start with |\pgfpath|. However, snakes do +not necessarily extend the path using line-to and curve-to operations; +rather, they can also contain move-to operations and, thereby, cause +the path to be split into many subpaths. + +As an example, let us consider a simple snake like the |zigzag| +snake. It looks like this: + +\begin{codeexample}[] +\begin{tikzpicture} + \draw[snake=zigzag] (0,0) -- (3,0); + \draw[snake=zigzag] (0,-.5) -- (3,-1); +\end{tikzpicture} +\end{codeexample} + +The above example demonstrates the two key features of snakes: +\begin{enumerate} +\item + Snakes are made up from little segments that are repeated several + times. For the |zigzag| snake these segements look like this: + \tikz{\draw[snake=zigzag] (0,0) -- (\pgfsnakesegmentlength+0.1pt,0pt);}. +\item + Snakes ``follow along a straight to the target point.'' Thus, when + the target point is not to the right of the start point, the snake + is rotated appropriately. +\end{enumerate} + + +In order to use snakes, they first have to be \emph{declared}. This +declaration contains a detailed description of how each segement of +the snake looks like and in what ordering the different possible +segments are used. + +Once a snake has been declared, it can be used. For this you specify a +target point and a snaked line will be added from the last point +current point to the target point. + + +\subsection{Declaring a Snake} + + +\subsubsection{Segments} + +When you declare a snake, you provide a description of how the +different segments of the snake will be rendered. The description of +each segment should be given in a way as if the target of the snaked +line where at $(+\infty,0)$ and as if the segment's start where at the +origin. Thus, for example, the segment of the |zigzag| might be +defined using the following code: +\begin{codeexample}[code only] +\pgfpathlineto{\pgfpoint{5pt}{5pt}} +\pgfpathlineto{\pgfpoint{15pt}{-5pt}} +\pgfpathlineto{\pgfpoint{20pt}{0pt}} +\end{codeexample} + +\pgfname\ will ensure that an appropriate coordinate transformation +is in place when the snake segment is added to the path such that +the snake segment actually points in the right direction. Also +subsequent snake segments will be transformed such that they are +``further along the line'' toward the target. All transformations +are setup automatically. + +Note that we did not use a |\pgfpathmoveto{\pgfpointorigin}| at the +beginning of the segment code. Doing so would subdivide the path into +numerous subpath. Rather, we assume that the previous segment caused +the current point to be at the origin. + +While we can now describe segments, we still need a way to ``stop'' +the snake. Also, \pgfname\ needs to know the width of the different +snake segments such that it can translate the next segment correctly. +Even though it would be possible to compute all this information +automatically, \pgfname\ does not do so and you have to provide the +information ``by hand'' for each segment. + + +\subsubsection{Snake Automata} + +Up to now our snakes only have one segment that is repeated again and +again. However, we might also like to have \emph{different} segments +and use rules to describe which segment should be used where. For +example, we might have special segments at the start and at the end. + +For snakes we use a mechanism known in computer science as +\emph{finite automata} to describe which segment is used in each part +of the snake. The idea is the following: For the first segment we +start in a special \emph{state} called the \emph{initial state}. In +this state, and also in all other state later, \pgfname\ first +computes how much space is left on the snake. That is, \pgfname\ keeps +track of the distance to the target. Attached to each state there is a +set of rules of the following form: ``If the remaining distance is +less than $x$, switch to state~$q$.'' \pgfname\ checks for each of +these rules whether it applies and, if so, immediately switches to +state~$q$. + +Only if none of the rules tell us to switch to another +state, \pgfname\ will execute the state's code. This code will add a +segment to the path. In addition to the rules there is also width +parameter attached to each state. \pgfname\ then translates the +coordinate system by this width and reduces the remaining distance. +Then, \pgfname\ either stays in the current state or switches to +another state, depending on yet another property attached of the +state. + +The whole process stops when a special state called |final| is +reached. The segment of this state is added to the path immediately +(it is often empty, though) and the process ends. + +\subsubsection{The Snake Declaration Command} + +\begin{command}{\pgfdeclaresnake\marg{name}\marg{initial + state}\marg{states}} + This command declares a new snake called \meta{name}. The + \meta{states} argument contains a description of the snake + automaton's states and the transitions between them. The + \meta{initial state} is the state in which the automaton starts. + + The \meta{states} argument should consist of |\state| commands, one + for each state of the snake automaton. The |\state| command is + defined only when the \meta{states} argument is executed. + +\begin{codeexample}[] +\pgfdeclaresnake{example snake}{initial} +{ + \state{initial}[width=10pt] + { + \pgfpathlineto{\pgfpoint{0pt}{5pt}} + \pgfpathlineto{\pgfpoint{5pt}{5pt}} + \pgfpathlineto{\pgfpoint{5pt}{-5pt}} + \pgfpathlineto{\pgfpoint{10pt}{-5pt}} + \pgfpathlineto{\pgfpoint{10pt}{0pt}} + } + \state{final} + { + \pgfpathlineto{\pgfpoint{\pgfsnakeremainingdistance}{0pt}} + } +} +\tikz{\draw[snake=example snake] (0,0) -- (3,0); + \draw[snake=example snake] (0,-1) -- (3,-3);} +\end{codeexample} + + The |\state| command works as follows: + \begin{command}{\state\marg{name}\oarg{options}\marg{code}} + This command declares a new state inside the current snake + automaton. The state is names \meta{name}. + + When \pgfname\ is in state \meta{name}, the following things + happen: + \begin{enumerate} + \item + The \meta{options} are parsed. This may lead, see below, to a + state switch. When this happens, the following steps are not + executed. The \meta{options} are executed one after the other in + the given order. If an option causes a state switch, the switch + is immediate, even if later options might cause a different + state switch. + \item + The \meta{code} is executed. When this happens, the coordinate + transformation will be setup such that the origin is at the + start of the segment and such that the target lies in the + direction ``east.'' + \item + After the \meta{code} has been executed, the state switches to + whatever state has been specified inside the \meta{options} + using the |next state| option. If no |next state| has been + specified, the state stays the same. + \end{enumerate} + + The following options are allowed inside the \meta{options}: + \begin{itemize} + \itemoption{switch if less than}|=|\meta{dimension}| to |\meta{new state} + When this option is encountered, \pgfname\ checks whether the + remaining distance to the target is less than + \meta{dimension}. If so, an immediate state switch to \meta{new + state} occurs. + \itemoption{width}|=|\meta{dimension} + This option tells \pgfname\ the width of the segment if it is + appended to the path. The coordinate system will, afterward, be + translated by \meta{dimension} to ensure that the next segment + starts where the current one ended. + + In addition, this option will cause an immediate switch to the + state |final| if the remaining distance is less than + \meta{dimension}. The effect is the same as if you had said + |switch if less than=|\meta{dimension}| to final| just before + the |width| option. + \itemoption{next state}=\meta{new state} + After the segment has been added to the path, a state switch to + \meta{new state} is performed. If this option is not given, the + next state is the same as the current state. + \end{itemize} + + There are two dimensions that are useful inside snake automata: + \begin{command}{\pgfsnakeremainingdistance} + This \TeX\ dimension holds the remaining distance to the target. + \end{command} + \begin{command}{\pgfsnakecompleteddistance} + This \TeX\ dimension holds the distance already completed on the + snake. + \end{command} + \end{command} + + As a final example we present a more complicated snake that makes + use of the different options: +\begin{codeexample}[] +\pgfdeclaresnake{complicated example snake}{initial} +{ + \state{initial}[width=5pt,next state=up] + { \pgfpathlineto{\pgfpoint{5pt}{0pt}} } + + \state{up}[width=5pt,next state=down] + { + \ifdim\pgfsnakeremainingdistance>\pgfsnakecompleteddistance + % Growing + \pgfpathlineto{\pgfpoint{0pt}{\pgfsnakecompleteddistance}} + \pgfpathlineto{\pgfpoint{5pt}{\pgfsnakecompleteddistance}} + \pgfpathlineto{\pgfpoint{5pt}{0pt}} + \else + % Shrinking + \pgfpathlineto{\pgfpoint{0pt}{\pgfsnakeremainingdistance}} + \pgfpathlineto{\pgfpoint{5pt}{\pgfsnakeremainingdistance}} + \pgfpathlineto{\pgfpoint{5pt}{0pt}} + \fi% + } + \state{down}[width=5pt,next state=up] + { + \ifdim\pgfsnakeremainingdistance>\pgfsnakecompleteddistance + % Growing + \pgfpathlineto{\pgfpoint{0pt}{-\pgfsnakecompleteddistance}} + \pgfpathlineto{\pgfpoint{5pt}{-\pgfsnakecompleteddistance}} + \pgfpathlineto{\pgfpoint{5pt}{0pt}} + \else + % Shrinking + \pgfpathlineto{\pgfpoint{0pt}{-\pgfsnakeremainingdistance}} + \pgfpathlineto{\pgfpoint{5pt}{-\pgfsnakeremainingdistance}} + \pgfpathlineto{\pgfpoint{5pt}{0pt}} + \fi% + } + \state{final} + { + \pgfpathlineto{\pgfpoint{\pgfsnakeremainingdistance}{0pt}} + } +} +\begin{tikzpicture}[snake=complicated example snake] + \draw[snake] (0,0) -- (3,0); + \fill[red!50,snake,rounded corners=2pt] (.5,-2) -- ++(2.5,-2.5) + [snake=none] -- ++(0,-.5) -| (0,-2) -- cycle; +\end{tikzpicture} +\end{codeexample} +\end{command} + + +\subsubsection{Predefined Snakes} + +Only two very simple and basic snakes are predefined when you load +\pgfname. For more interesting snakes you can use the package +|pgflibrarysnakes|. + +\begin{snake}{lineto} + This most trivial of all snakes is simply a straight line. This + snake is typically not used in a ``stand alone'' fashion. Rather, it + is useful as a ``subsnake'' of the |\pgfsnakesto| command. +\end{snake} + +\begin{snake}{moveto} + Arguably, this snake is even simpler than the previous snake. This + snake consists of a simple move-to operation. Like the |lineto| + snake, it is useful as a ``subsnake'' of the |\pgfsnakesto| + command. +\end{snake} + + + +\subsection{Using Snakes} + +Three commands can be used to use a snake. + +\begin{command}{\pgfpathsnakealongvector\marg{snake}\marg{length}\marg{vector}} + This command will append the \meta{snake} to the current path. The + length of the snake is given by \meta{length}. The \meta{vector} + should be a normalizes vector (a vector having length |1pt|) + pointing in the direction in which the snake should grow. +\begin{codeexample}[] +\begin{tikzpicture} + \draw[help lines] (0,0) grid (3,2); + \pgfpathmoveto{\pgfpoint{1cm}{1cm}} + \pgfpathsnakealongvector{zigzag}{2cm}{\pgfpointpolar{30}{1pt}} + \pgfusepath{stroke} +\end{tikzpicture} +\end{codeexample} +\end{command} + +\begin{command}{\pgfpathsnakesto\marg{snake list}\marg{target}} + This command will append the snakes in the \meta{snake list} to the + current path such that it ends at \meta{point}. This command calls the previous + one (repeatedly, possibly) after having computed the distance from + the current point to \meta{target} and normalized the vector + connecting the current point to the target. + + The \meta{snake list} is a comma-separated list of pairs consisting + of a snake name in curly braces and a distance in curly braces. For + example, a snake list might be |{lineto}{1cm},{moveto}{2cm}|. This + is interpreted as follows: Use a |lineto| snake for the first + centimeter of the way to the \meta{target}, then use the |moveto| + snake for the next two centimeters. + + No attempt is made to check or ensure that the distances of the + ``subsnakes' add up to the distnace from the current point to the + \meta{target}. However, it is possible to refer to this distance + inside the \meta{snake list}: While the snake list is processed, the + two \TeX-dimensions |\pgfsnakeremainingdistance| and + |\pgfsnakecompleteddistance| will be set to the correct values. For + example, consider the example from a above, consisting of a |lineto| + and a |moveto| snake. Suppose the distance to \meta{target} where + 5cm. Then, when the length of the first subsnake is computed, the + remaining distance willbe set to 5cm and the completed distance to + 0cm. When the length of the second subsnake is computed, the + remaining distance wil be 4cm and the completed distance will be + 1cm. + + Here are some useful examles: |{zigzag}{\pgfsnakeremainingdistance}| + is a \meta{snake list} that consists only of a |zigzag| snake whose + length is the total distance from the current point to the + \meta{target}. Next, to get a snake that is a |zigzag| snake that is + preceeded and succeeded by 3mm of |lineto|, you can use the + following: +\begin{codeexample}[] +\begin{tikzpicture} + \draw[help lines](0,0) grid (3,2); + \pgfpathmoveto{\pgfpointorigin} + \pgfpathsnakesto{% + {lineto}{3mm},% + {zigzag}{\pgfsnakeremainingdistance-6mm},% + {lineto}{3mm}} + {\pgfpoint{3cm}{2cm}} + \pgfusepath{stroke} +\end{tikzpicture} +\end{codeexample} + + Note that the computation of the distance may be imprecise. In + general, the placement precision of the snakes will not be perfect. +\end{command} + +\begin{command}{\pgfpathsnaketo\marg{snake}\marg{target}} + This command is just a shortcut for calling |\pgfpathsnakesto| for a + single snake whose length is |\pgfsnakeremainingdistance|. +\begin{codeexample}[] +\begin{tikzpicture} + \draw[help lines] (0,0) grid (3,2); + \pgfpathmoveto{\pgfpoint{1cm}{1cm}} + \pgfpathsnaketo{zigzag}{\pgfpoint{3cm}{2cm}} + \pgfusepath{stroke} +\end{tikzpicture} +\end{codeexample} +\end{command} + +As was already mentioned, when each segment of the snake is added to +the path, an appropriate coordinate transformation will be in +force. It is sometimes useful to add an additional transformation +locally. For example, by reflecting everything around the $x$-axis +right before each segment is added, the snake will effectively be +mirrored along the path. The following command allows you to install +such a ``last minute transformation.'' + +\begin{command}{\pgfsetsnakesegmenttransformation\marg{code}} + The \meta{code} will be executed at the very beginning of each + segment. Normally, this be a transformation command that changes the + $y$-axis in some way. +\end{command} + + + + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "~/texmf/tex/generic/pgf/doc/pgf/version-for-pdftex/en/pgfmanual" +%%% End: |