summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/doc/generic/pgf/text-en/pgfmanual-en-base-snakes.tex
blob: 64f70f8a6874866304fb36a4913dc469165d009d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
% Copyright 2006 by Till Tantau
%
% This file may be distributed and/or modified
%
% 1. under the LaTeX Project Public License and/or
% 2. under the GNU Free Documentation License.
%
% See the file doc/generic/pgf/licenses/LICENSE for more details.



\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: