diff options
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.tex | 346 |
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 |