diff options
Diffstat (limited to 'Master/texmf-dist/tex/generic/pgf/modules/pgfmodulesnakes.code.tex')
-rw-r--r-- | Master/texmf-dist/tex/generic/pgf/modules/pgfmodulesnakes.code.tex | 370 |
1 files changed, 370 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/generic/pgf/modules/pgfmodulesnakes.code.tex b/Master/texmf-dist/tex/generic/pgf/modules/pgfmodulesnakes.code.tex new file mode 100644 index 00000000000..0d3ad5dfdeb --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/modules/pgfmodulesnakes.code.tex @@ -0,0 +1,370 @@ +% 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 Public License. +% +% See the file doc/generic/pgf/licenses/LICENSE for more details. + +\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/modules/pgfmodulesnakes.code.tex,v 1.2 2008/01/17 20:09:17 tantau Exp $ + +\PackageWarning{pgf}{Snakes have been superseded by decorations. Use +the module decorations instead of snakes} + +\usepgfmodule{decorations} + +\endinput + + + +\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}% + \pgfutil@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{\pgfutil@ifnextchar[{\pgf@@snake@start#1}{\pgf@@snake@start#1[]}}%} +\def\pgf@@snake@start#1[#2]#3{% + \pgfutil@namedef{pgf@snake@@\pgf@snake@name @#1@options}{#2}% + \pgfutil@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% + % + % MW: Calculate the angle of the snake. + % + \edef\pgf@marshal{% + \noexpand\pgfmathanglebetweenpoints{\noexpand\pgfpointorigin}{% + \noexpand\pgf@x\the\pgf@x\noexpand\pgf@y\the\pgf@y}% + }% + \pgf@marshal% + \let\pgfsnakeangle\pgfmathresult% + % + % MW: Use this instead for length (?). More accurate and only a few operations slower. + % + \pgfmathveclen@{\pgfmath@tonumber{\pgf@x}}{\pgfmath@tonumber{\pgf@y}}% + \pgfsnakeremainingdistance\pgfmathresult pt\relax% + % + % 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 normalized 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% + \pgfutil@for\pgf@temp:=\pgf@list\do{% + \ifx\pgf@temp\pgfutil@empty% + \else% + \expandafter\pgf@snake@invoke\pgf@temp% + \fi% + }% + \endgroup% +} + +\def\pgf@snake@invoke#1#2{% + \pgfmathsetlength\pgf@xa{#2}% + {% + \edef\pgf@marshal{\noexpand\pgfpathsnakealongvector{#1}{\the\pgf@xa}{\noexpand\pgfqpoint{\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{% + \pgfutil@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% + \pgfmathsetlength\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 + \expandafter\expandafter\expandafter\pgf@snakes@setter + \expandafter\expandafter\expandafter{\csname pgf@snake@@\pgf@snake@name @\pgf@snake@current@state @options\endcsname}% + \ifx\pgf@snake@next\relax% + \let\pgf@snake@next=\pgf@snake@do@code% + \fi% + \pgf@snake@next% +} +\def\pgf@snakes@setter{% + \pgfqkeys{/pgf/snakes}% +} + +\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 + \pgfmathsetlength{\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% +} + +\pgfkeys{ + /pgf/snakes/width/.code=\def\pgf@snake@width{#1}\pgf@snake@switch@if#1 to final\pgf@stop,% + /pgf/snakes/switch if less than/.code=\pgf@snake@switch@if#1\pgf@stop,% + /pgf/snakes/next state/.store in=\pgf@snake@next@state% +} + +\def\pgf@snake@switch@if#1to #2\pgf@stop{% + \ifx\pgf@snake@next\relax% + \pgfmathsetlength\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{\pgfqpoint{\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{\pgfqpoint{\pgfsnakeremainingdistance}{0pt}} } +} + + + +\endinput |