summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/generic/pgf/basiclayer/pgfbasesnakes.code.tex
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/generic/pgf/basiclayer/pgfbasesnakes.code.tex')
-rw-r--r--Master/texmf-dist/tex/generic/pgf/basiclayer/pgfbasesnakes.code.tex346
1 files changed, 346 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/generic/pgf/basiclayer/pgfbasesnakes.code.tex b/Master/texmf-dist/tex/generic/pgf/basiclayer/pgfbasesnakes.code.tex
new file mode 100644
index 00000000000..7403f2a7b8e
--- /dev/null
+++ b/Master/texmf-dist/tex/generic/pgf/basiclayer/pgfbasesnakes.code.tex
@@ -0,0 +1,346 @@
+\ProvidesPackageRCS[v\pgfversion] $Header: /cvsroot/pgf/pgf/generic/pgf/basiclayer/pgfbasesnakes.code.tex,v 1.5 2005/10/10 08:38:29 tantau Exp $
+
+% Copyright 2005 by Till Tantau <tantau@cs.tu-berlin.de>.
+%
+% This program can be redistributed and/or modified under the terms
+% of the GNU Public License, version 2.
+
+
+\newdimen\pgfsnakeremainingdistance
+\newdimen\pgfsnakecompleteddistance
+
+
+% Creates a new pgf snake
+%
+% #1 = snake name
+% #1 = initial state
+% #3= states of the snake
+%
+%
+% This command declares a new snake for later use. The second
+% parameter specifies the states of the snake, see also the
+% description of pgfpathsnake.
+%
+% Inside the code of #3 the command \state may be used. This command
+% will only be defined while #3 is executed.
+%
+% Example:
+%
+% \pgfdeclaresnake{zig zag}{one zig zag}
+% {
+% \state{one zig zag}[width=10pt]
+% {
+% \pgfpathlineto{\pgfpoint{2.5pt}{2.5pt}}
+% \pgfpathlineto{\pgfpoint{7.5pt}{-2.5pt}}
+% \pgfpathlineto{\pgfpoint{10pt}{0pt}}
+% }
+% \state{final}
+% {
+% \pgfpathlineto{\pgfpoint{\pgfsnakeremainingdistance}{0pt}}
+% }
+% }
+
+\long\def\pgfdeclaresnake#1#2#3{%
+ \def\pgf@snake@name{#1}%
+ \@namedef{pgf@snake@@#1@initial}{#2}%
+ \let\pgf@orig@state=\state%
+ \let\state=\pgf@snake@state
+ #3
+ \let\state=\pgf@orig@state%
+}
+
+
+% Sets the additional transformation applied to every segment of a snake
+%
+% #1 = transformation
+%
+% Example:
+%
+% \pgfsetsnakesegmenttransformation{\pgftransformyshift{5pt}}
+
+\def\pgfsetsnakesegmenttransformation#1{\def\pgf@snakeadditionaltransform{#1}}
+\pgfsetsnakesegmenttransformation{}
+
+
+% Declares a new state
+%
+% #1 = state name
+% #2 = options
+% #3 = path element
+%
+% Description:
+%
+% When a snake is drawn and the current state is #1, the following
+% happens. First, the options are executed, which will possible change
+% the state. If that does not happen, the path element is added to the
+% path and the coordinate system is translated by the path element's
+% width (which is specified using the width option).
+%
+% Example:
+%
+% \state{initial}[width=10pt]
+% {
+% \pgfpathlineto{\pgfpoint{2.5pt}{2.5pt}}
+% \pgfpathlineto{\pgfpoint{7.5pt}{-2.5pt}}
+% \pgfpathlineto{\pgfpoint{10pt}{0pt}}
+% }
+
+\def\pgf@snake@state#1{\@ifnextchar[{\pgf@@snake@start#1}{\pgf@@snake@start#1[]}}%}
+\def\pgf@@snake@start#1[#2]#3{%
+ \@namedef{pgf@snake@@\pgf@snake@name @#1@options}{#2}%
+ \@namedef{pgf@snake@@\pgf@snake@name @#1@code}{#3}%
+}
+
+
+
+% Use multiple snakes
+%
+% #1 = list of snake names/length pairs
+% #2 = point to which the snake leads
+%
+% This operation uses the snakes in parameter #1 to get to the point
+% #4. The parameter #1 should contain pairs consisting of a snake name
+% and a length for which this snake should be used. When the length is
+% computed, the dimensions \pgfsnakeremainingdistance and
+% \pgfsnakecompleteddistance will have been set to the length of the
+% total distance to #2 that has already been covered/that still needs
+% to be covered.
+%
+% Example:
+%
+% \pgfpathsnakesto{{lineto}{1cm},{zig zag}{\pgfsnakeremainingdistance}}{\pgfpoint{2cm}{3cm}}
+
+\def\pgfpathsnakesto#1#2{%
+ \begingroup%
+ % compute target vector
+ \pgfpointtransformed{#2}%
+ \advance\pgf@x by-\pgf@path@lastx%
+ \advance\pgf@y by-\pgf@path@lasty%
+ % Ok, now normalize the vector...
+ \pgf@xa=\pgf@x%
+ \pgf@ya=\pgf@y%
+ \pgf@process{\pgfpointnormalised{}}%
+ % ok, now computer length (arghh...)
+ % In theory that's easy: divide the larger of the values x or y by
+ % the normalizes x or y. Well...
+ %
+ % First, make xa and ya positive:
+ \ifdim\pgf@xa<0pt%
+ \pgf@xa=-\pgf@xa%
+ \fi%
+ \ifdim\pgf@ya<0pt%
+ \pgf@ya=-\pgf@ya%
+ \fi%
+ % Now do division:
+ \ifdim\pgf@xa>\pgf@ya%
+ \c@pgf@counta=\pgf@x%
+ \ifnum\c@pgf@counta=0\relax%
+ \else%
+ \divide\c@pgf@counta by 255\relax%
+ \pgf@xa=16\pgf@xa\relax%
+ \divide\pgf@xa by\c@pgf@counta%
+ \pgf@xa=16\pgf@xa\relax%
+ \fi%
+ \else%
+ \c@pgf@counta=\pgf@y%
+ \ifnum\c@pgf@counta=0\relax%
+ \else%
+ \divide\c@pgf@counta by 255\relax%
+ \pgf@ya=16\pgf@ya\relax%
+ \divide\pgf@ya by\c@pgf@counta%
+ \pgf@xa=16\pgf@ya\relax%
+ \fi%
+ \fi%
+ % Make positive:
+ \ifdim\pgf@xa<0pt%
+ \pgf@xa=-\pgf@xa%
+ \fi%
+ % Ok, now we draw things...
+ \edef\pgf@list{#1}%
+ \pgfsnakeremainingdistance=\pgf@xa%
+ \pgfsnakecompleteddistance=0pt%
+ \pgf@xb=\pgf@x%
+ \pgf@yb=\pgf@y%
+ \@for\pgf@temp:=\pgf@list\do{%
+ \ifx\pgf@temp\@empty%
+ \else%
+ \expandafter\pgf@snake@invoke\pgf@temp%
+ \fi%
+ }%
+ \endgroup%
+}
+
+\def\pgf@snake@invoke#1#2{%
+ \setlength\pgf@xa{#2}%
+ {%
+ \edef\pgf@marshal{\noexpand\pgfpathsnakealongvector{#1}{\the\pgf@xa}{\noexpand\pgfpoint{\the\pgf@xb}{\the\pgf@yb}}}%
+ \pgf@marshal%
+ }%
+ \advance\pgfsnakecompleteddistance by\pgf@xa%
+ \advance\pgfsnakeremainingdistance by-\pgf@xa%
+}
+
+% Use a snake
+%
+% #1 = snake name
+% #2 = point to which the snake leads
+%
+% This operation mainly computes \pgfpathsnakealongvector for a vector
+% appropriately choosen. See \pgfpathsnakealongvector for details.
+%
+% Example:
+%
+% \pgfpathsnaketo{zig zag}{\pgfpoint{2cm}{3cm}}
+
+\def\pgfpathsnaketo#1#2{\pgfpathsnakesto{{#1}{\pgfsnakeremainingdistance}}{#2}}
+
+
+
+% Use a snake
+%
+% #1 = snake name
+% #2 = length of the snake
+% #3 = vector along which the snake grows, should have unit length.
+%
+% This command draws a snake (more precisely, it adds a snake to the
+% path). This works as follows:
+%
+% First, the coordinate system is transformed such that the vector #3
+% points to the right.
+%
+% Next, the state `initial' of the snake is entered. Unless the
+% options of this state cause it to switch to another state, the path
+% element is added to the path. Then, the coordinate system is
+% translated by the width of the path element as specified in the
+% width option of the path element. The dimensions
+% \pgfsnakeremainingdistance and \pgfsnakecompleteddistance are
+% updated.
+%
+% The process ends when the state `final' is entered. The code of the
+% final state is executed and the process stops.
+%
+% Example:
+%
+% \pgfpathsnakealongvector{zig zag}{100pt}{\pgfpolar{30}{1pt}}
+
+\def\pgfpathsnakealongvector#1#2#3{%
+ \@ifundefined{pgf@snake@@#1@initial}{\PackageError{pgf}{Undefined snake ``#1''}{}}
+ {
+ \begingroup% keep things local
+ \pgftransformreset%
+ \pgf@pt@x=\pgf@path@lastx% evil trickery to transform to the last point
+ \pgf@pt@y=\pgf@path@lasty%
+ \pgf@process{#3}%
+ \pgf@xa=\pgf@x%
+ \pgf@ya=\pgf@y%
+ \pgf@xb=-\pgf@y%
+ \pgf@yb=\pgf@x%
+ \pgftransformcm
+ {\pgf@sys@tonumber{\pgf@xa}}{\pgf@sys@tonumber{\pgf@ya}}
+ {\pgf@sys@tonumber{\pgf@xb}}{\pgf@sys@tonumber{\pgf@yb}}
+ {\pgfpointorigin}%
+ % Now, setup the automaton
+ \expandafter\let\expandafter\pgf@snake@current@state\expandafter=\csname pgf@snake@@#1@initial\endcsname%
+ \def\pgf@snake@name{#1}%
+ \pgfsnakecompleteddistance=0pt%
+ \setlength\pgfsnakeremainingdistance{#2}%
+ \pgf@snake@run%
+ % Last step:
+ {%
+ \pgftransformxshift{\pgfsnakecompleteddistance}%
+ \pgf@snakeadditionaltransform%
+ \csname pgf@snake@@#1@final@code\endcsname%
+ }%
+ \endgroup%
+ }%
+}
+
+\def\pgf@final@text{final}
+
+\def\pgf@snake@run{%
+ \let\pgf@snake@next=\pgf@snake@do@state%
+ \ifx\pgf@snake@current@state\pgf@final@text%
+ \let\pgf@snake@next=\relax%
+ \fi%
+ \pgf@snake@next%
+}
+
+\def\pgf@snake@do@state{%
+ \let\pgf@snake@next=\relax%
+ \let\pgf@snake@next@state=\pgf@snake@current@state%
+ % execute options
+ \def\pgf@marshal{\setkeys{pgfsnake}}%
+ \expandafter\expandafter\expandafter\pgf@marshal
+ \expandafter\expandafter\expandafter{\csname pgf@snake@@\pgf@snake@name @\pgf@snake@current@state @options\endcsname}%
+ \ifx\pgf@snake@next\relax%
+ \pgf@snake@next=\pgf@snake@do@code%
+ \fi%
+ \pgf@snake@next%
+}
+
+\def\pgf@snake@do@code{%
+ % Ok, execute code:
+ {%
+ \pgftransformxshift{\pgfsnakecompleteddistance}%
+ \pgf@snakeadditionaltransform%
+ \csname pgf@snake@@\pgf@snake@name @\pgf@snake@current@state @code\endcsname%
+ }%
+ % next, do transformation and update
+ \setlength{\pgf@xa}{\pgf@snake@width}%
+ \advance\pgfsnakeremainingdistance by-\pgf@xa%
+ \advance\pgfsnakecompleteddistance by\pgf@xa%
+ % Next iteration:
+ \let\pgf@snake@current@state=\pgf@snake@next@state%
+ \pgf@snake@run
+}
+
+\define@key{pgfsnake}{width}{%
+ \def\pgf@snake@width{#1}%
+ \pgf@snake@switch@if#1 to final\pgf@stop%
+}
+\define@key{pgfsnake}{switch if less than}{%
+ \pgf@snake@switch@if#1\pgf@stop%
+}
+\define@key{pgfsnake}{next state}{%
+ \def\pgf@snake@next@state{#1}%
+}
+
+\def\pgf@snake@switch@if#1to #2\pgf@stop{%
+ \ifx\pgf@snake@next\relax%
+ \setlength\pgf@x{#1}%
+ \ifdim\pgfsnakeremainingdistance<\pgf@x%
+ \def\pgf@snake@current@state{#2}%
+ \let\pgf@snake@next=\pgf@snake@run%
+ \fi%
+ \fi%
+}
+
+
+
+% lineto snake
+%
+% This snake simply adds a straight line. This snake is mainly useful
+% in conjunction with other snakes.
+
+\pgfdeclaresnake{lineto}{final}
+{
+ \state{final}
+ { \pgfpathlineto{\pgfpoint{\pgfsnakeremainingdistance}{0pt}} }
+}
+
+
+
+% moveto snake
+%
+% This snake simply jumps to the end. This snake, too, is mainly
+% useful in conjunction with other snakes.
+
+\pgfdeclaresnake{moveto}{final}
+{
+ \state{final}
+ { \pgfpathmoveto{\pgfpoint{\pgfsnakeremainingdistance}{0pt}} }
+}
+
+
+
+\endinput