diff options
Diffstat (limited to 'Master/texmf-dist/tex/generic/pgf/modules/pgfmodulenonlineartransformations.code.tex')
-rw-r--r-- | Master/texmf-dist/tex/generic/pgf/modules/pgfmodulenonlineartransformations.code.tex | 342 |
1 files changed, 342 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/generic/pgf/modules/pgfmodulenonlineartransformations.code.tex b/Master/texmf-dist/tex/generic/pgf/modules/pgfmodulenonlineartransformations.code.tex new file mode 100644 index 00000000000..913f2edff9d --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/modules/pgfmodulenonlineartransformations.code.tex @@ -0,0 +1,342 @@ +% Copyright 2013 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[v\pgfversion] $Header: /cvsroot/pgf/pgf/generic/pgf/modules/pgfmodulenonlineartransformations.code.tex,v 1.4 2013/10/09 18:30:27 tantau Exp $ + + +% +% This file defines commands for nonlinear coordinate systems. This is +% needed, for instance, for bend arrow heads. +% +% +% Non-linear coordinate systems transform coordinates, in addition to +% the normal linear transformations, in a, well, non-linear way. An +% example are polar coordinates. +% +% Like the linear transformations, non-linear transformations are +% applied on a low level and they are integrated into the whole path +% construction mechanism. So, while \pgfpointpolar also "does +% something nonlinear", it just provides a way of computing a +% coordinate. In contrast, installing a polar transformation will +% transform everything being drawn using the \pgfpath... commands an +% will even turn a straight line into a circle. +% +% Since computing non-linear transformations is expensive, they are +% only applied "if really necessary". + + + + +% Return a transformed point +% +% #1 = a point +% +% Description: +% +% Applies the current transformation and the current nonlinear +% transformation to the given point and returns the result in \pgf@x/y. + +\def\pgfpointtransformednonlinear#1{% + \pgf@process{% + #1% + \pgf@pos@transform{\pgf@x}{\pgf@y}% + \pgf@nlt@list% + } +} + + + + +% Approximate the nonlinear translation locally +% +% Description: +% +% Does a "local syncronization" of the nonlinear transformation with +% the linear transformation regarding the translation part of the +% current nonlinear transformatoin. The *linear* transformation will be +% updated so that it translates things to the point to which the +% nonlinear transformation transforms the origin. The nonlinear +% transformation will be reset. +% +% The net effect is that you can now draw things near the origin as +% before, but with just a linear transformation in force. Note that +% the coordinate system will not be rotated, only a shift is done (use +% the "real" local sync for a full sync). + +\def\pgfapproximatenonlineartranslation{% + \ifx\pgf@nlt@list\pgfutil@empty% + \else% + \pgfpointtransformednonlinear{\pgfpointorigin}% + \pgf@pt@x=\pgf@x% + \pgf@pt@y=\pgf@y% + \let\pgf@nlt@list\pgfutil@empty% + \let\pgf@nlt@moveto\pgf@lt@moveto% + \let\pgf@nlt@lineto\pgf@lt@lineto% + \let\pgf@nlt@curveto\pgf@lt@curveto% + \let\pgf@nlt@closepath\pgf@lt@closepath% + \fi% +} + + + +% Local sync translation +% +% Description: +% +% Does a "complete local syncronization" of the nonlinear +% transformation with the linear transformation. The *linear* +% transformation will be updated so that it transforms things to the +% point to which the nonlinear transformation transforms the +% origin. The nonlinear transformation will be reset. +% +% The net effect is that you can now draw things near the origin as +% before, but with just a linear transformation in force. + +\def\pgfapproximatenonlineartransformation{% + \ifx\pgf@nlt@list\pgfutil@empty% + \else% + \pgfpointtransformednonlinear{\pgfpoint{1pt}{0pt}}% + \pgf@xa\pgf@x + \pgf@ya\pgf@y + \pgfpointtransformednonlinear{\pgfpoint{0pt}{1pt}}% + \pgf@xb\pgf@x + \pgf@yb\pgf@y + \pgfpointtransformednonlinear{\pgfpointorigin}% + \advance\pgf@xa by-\pgf@x + \advance\pgf@xb by-\pgf@x + \advance\pgf@ya by-\pgf@y + \advance\pgf@yb by-\pgf@y + \pgfsettransformentries{\pgf@sys@tonumber\pgf@xa}{\pgf@sys@tonumber\pgf@ya}{\pgf@sys@tonumber\pgf@xb}{\pgf@sys@tonumber\pgf@yb}{\pgf@x}{\pgf@y}% + \let\pgf@nlt@list\pgfutil@empty% + \let\pgf@nlt@moveto\pgf@lt@moveto% + \let\pgf@nlt@lineto\pgf@lt@lineto% + \let\pgf@nlt@curveto\pgf@lt@curveto% + \let\pgf@nlt@closepath\pgf@lt@closepath% + \fi% +} + + + +% Adds a non-linear transformation to the current list of +% transformations. +% +% #1 = code +% +% Description: +% +% When the code #1 is called, \pgf@x and \pgf@y will be set to some +% values, let us call this the point p. The nonlinear transformation +% will now map this point to a new point f(p). The coordinates of this +% point shoudl be returned in \pgf@x and \pgf@y. Furthermore, consider +% the two "unit tangents" (going in $x$-direction and in +% $y$-direction) at point p. The nonlinear transformaiton will map +% these to new tangents, t_x and t_y. The (not necessarily normalized) +% vectors t_x and t_y should be returned in pgf@xa and -ya and pgf@xb +% and pgf@yb. The macro should not do any global assignments except to +% \pgf@x and \pgf@y, but may do arbitrary local assignments. +% +% The effect of installing a new transformation is the following: As +% long as there is at least one nonlinear transformation installed, +% whenever the path construction commands add a curve or line to the +% softpath, the line or curve will be "bend" by applying all of the +% nonlinear transformation installed. In particular, straight lines +% will be replaced by curves. +% +% Note that the normal linear transformation are always applied before +% any nonlinear transformations are applied. + +\def\pgftransformnonlinear#1{% + \expandafter\def\expandafter\pgf@nlt@list\expandafter{\pgf@nlt@list#1}% + \let\pgf@nlt@moveto\pgf@nlt@moveto@nlt + \let\pgf@nlt@lineto\pgf@nlt@lineto@nlt + \let\pgf@nlt@curveto\pgf@nlt@curveto@nlt + \let\pgf@nlt@closepath\pgf@nlt@closepath@nlt +} + +\def\pgf@nlt@moveto@nlt#1#2{% + {% + \pgfutil@tempdima#1% + \pgfutil@tempdimb#2% + \pgf@x\pgfutil@tempdima% + \pgf@y\pgfutil@tempdimb% + \xdef\pgf@nlt@last@moveto@orig{{\the\pgf@x}{\the\pgf@y}}% + \pgf@nlt@list% + \xdef\pgf@nlt@last@moveto@trans{{\the\pgf@x}{\the\pgf@y}}% + \xdef\pgf@nlt@last@moveto@xaxis{{\the\pgf@xa}{\the\pgf@ya}}% + \xdef\pgf@nlt@last@moveto@yaxis{{\the\pgf@xb}{\the\pgf@yb}}% + \pgf@protocolsizes{\pgf@x}{\pgf@y}% + \pgfsyssoftpath@moveto{\the\pgf@x}{\the\pgf@y}% + \global\let\pgf@nlt@last@coord@orig\pgf@nlt@last@moveto@orig% + \global\let\pgf@nlt@last@coord@trans\pgf@nlt@last@moveto@trans% + \global\let\pgf@nlt@last@coord@xaxis\pgf@nlt@last@moveto@xaxis% + \global\let\pgf@nlt@last@coord@yaxis\pgf@nlt@last@moveto@yaxis% + }% +} + + +\def\pgf@nlt@lineto@nlt#1#2{% + {% + \edef\pgf@temp{\pgf@xc\the#1\pgf@yc\the#2}% + \pgf@temp% + \expandafter\pgfqpoint\pgf@nlt@last@coord@orig% + \expandafter\pgf@nlt@set@temps\pgf@nlt@last@coord@trans% + % Test, whether the points are quite near: + \pgf@xa\pgf@x\advance\pgf@xa by-\pgf@xc% + \pgf@ya\pgf@y\advance\pgf@ya by-\pgf@yc% + \pgfutil@tempswafalse% + \ifdim\pgf@xa<0.1pt\relax\ifdim\pgf@xa>-0.1pt\relax\ifdim\pgf@ya<0.1pt\relax\ifdim\pgf@ya>-0.1pt\relax\pgfutil@tempswatrue\fi\fi\fi\fi% + \ifpgfutil@tempswa% + \pgf@x\pgf@xc\pgf@y\pgf@yc% + \xdef\pgf@nlt@last@coord@orig{{\the\pgf@x}{\the\pgf@y}}% + \pgf@process{\pgf@nlt@list}% + \xdef\pgf@nlt@last@coord@trans{{\the\pgf@x}{\the\pgf@y}}% + \xdef\pgf@nlt@last@coord@xaxis{{\the\pgf@xa}{\the\pgf@ya}}% + \xdef\pgf@nlt@last@coord@yaxis{{\the\pgf@xb}{\the\pgf@yb}}% + \pgf@protocolsizes{\pgf@x}{\pgf@y}% + \pgfsyssoftpath@lineto{\the\pgf@x}{\the\pgf@y}% + \else% + % Compute support points + \pgf@xb=.333333\pgf@x% + \advance\pgf@xb by.666666\pgf@xc% + \pgf@yb=.333333\pgf@y% + \advance\pgf@yb by.666666\pgf@yc% + \pgf@xa=.333333\pgf@xc% + \advance\pgf@xa by.666666\pgf@x% + \pgf@ya=.333333\pgf@yc% + \advance\pgf@ya by.666666\pgf@y% + \pgf@nlt@inner@curve% + \fi% + }% +} + +\def\pgf@nlt@set@temps#1#2{% + \pgfutil@tempdima#1\pgfutil@tempdimb#2% +} + +\def\pgf@nlt@curveto@nlt#1#2#3#4#5#6{% + {% + \edef\pgf@temp{\pgf@xa\the#1\pgf@ya\the#2\pgf@xb\the#3\pgf@yb\the#4\pgf@xc\the#5\pgf@yc\the#6}% + \pgf@temp% + \pgf@nlt@inner@curve% + }% +} + +\newdimen\pgftransformnonlinearflatness +\pgftransformnonlinearflatness=5pt +\def\pgfsettransformnonlinearflatness#1{\pgfmathsetlength\pgftransformnonlinearflatness{#1}} + + + +% Compute a curve from \pgf@nlt@last@coord@orig to \pgf@xc/\pgf@yc via the +% controls \pgf@xa/\pgf@ya and \pgf@xb/\pgf@yb. +\def\pgf@nlt@inner@curve{% + \expandafter\pgfqpoint\pgf@nlt@last@coord@orig% + % Save delta of supports: + \pgfutil@tempdima\pgf@xa\advance\pgfutil@tempdima by-\pgf@xb + \pgfutil@tempdimb\pgf@ya\advance\pgfutil@tempdimb by-\pgf@yb + \begingroup + % Replace supports by relative supports + \advance\pgf@xa by-\pgf@x% + \advance\pgf@ya by-\pgf@y% + \advance\pgf@xb by-\pgf@xc% + \advance\pgf@yb by-\pgf@yc% + % + % Now, test whether the flatness is satisfied: + % + \pgfutil@tempswafalse + \ifdim\pgfutil@tempdima>\pgftransformnonlinearflatness\pgfutil@tempswatrue\fi% + \ifdim\pgfutil@tempdima<-\pgftransformnonlinearflatness\pgfutil@tempswatrue\fi% + \ifdim\pgfutil@tempdimb>\pgftransformnonlinearflatness\pgfutil@tempswatrue\fi% + \ifdim\pgfutil@tempdimb<-\pgftransformnonlinearflatness\pgfutil@tempswatrue\fi% + \ifdim\pgf@xa>\pgftransformnonlinearflatness\pgfutil@tempswatrue\fi% + \ifdim\pgf@xa<-\pgftransformnonlinearflatness\pgfutil@tempswatrue\fi% + \ifdim\pgf@ya>\pgftransformnonlinearflatness\pgfutil@tempswatrue\fi% + \ifdim\pgf@ya<-\pgftransformnonlinearflatness\pgfutil@tempswatrue\fi% + \ifdim\pgf@xb>\pgftransformnonlinearflatness\pgfutil@tempswatrue\fi% + \ifdim\pgf@xb<-\pgftransformnonlinearflatness\pgfutil@tempswatrue\fi% + \ifdim\pgf@yb>\pgftransformnonlinearflatness\pgfutil@tempswatrue\fi% + \ifdim\pgf@yb<-\pgftransformnonlinearflatness\pgfutil@tempswatrue\fi% + \ifpgfutil@tempswa% + \endgroup% Undo the adjustmenst... + {% + \edef\pgf@orig@xya{\pgf@xa\the\pgf@xa\pgf@ya\the\pgf@ya} + \edef\pgf@orig@xyb{\pgf@xb\the\pgf@xb\pgf@yb\the\pgf@yb} + \edef\pgf@orig@xyc{\pgf@xc\the\pgf@xc\pgf@yc\the\pgf@yc} + \pgfpointcurveattime{.5}% + {\expandafter\pgfqpoint\pgf@nlt@last@coord@orig}% + {\pgf@x\pgf@xa\pgf@y\pgf@ya}% + {\pgf@x\pgf@xb\pgf@y\pgf@yb}% + {\pgf@x\pgf@xc\pgf@y\pgf@yc}% + % First new curve: + % Start is at last@coord@orig, + % first support is at last@coord@orig*t + s*(original xa/ya) + % second support is at xb/yb + % target is at x/y + {% + % Target: + \pgf@xc\pgf@x\pgf@yc\pgf@y + % First support: + \expandafter\pgfqpoint\pgf@nlt@last@coord@orig% + \pgf@orig@xya% + \pgf@xa\pgf@time@s\pgf@xa\advance\pgf@xa by\pgf@time@t\pgf@x% + \pgf@ya\pgf@time@s\pgf@ya\advance\pgf@ya by\pgf@time@t\pgf@y% + \pgf@nlt@inner@curve% + }% + % Second new curve: + % Start is at (new) last@coord@orig + % first support is at xa/ya + % second support is at t*(original xb/yb) + s*(original xc/yc) + % target is at original xc/yc + {% + \pgf@orig@xyb% + \pgf@orig@xyc% + \pgf@xb\pgf@time@t\pgf@xb\advance\pgf@xb by\pgf@time@s\pgf@xc% + \pgf@yb\pgf@time@t\pgf@yb\advance\pgf@yb by\pgf@time@s\pgf@yc% + \pgf@nlt@inner@curve% + }% + }% + \else% + \endgroup% Snap back... + \pgf@nlt@do@inner@curve% + \fi% +} + +\def\pgf@nlt@do@inner@curve{% + \pgf@process{\pgf@x\pgf@xa\pgf@y\pgf@ya\pgf@nlt@list}% + \pgf@xa\pgf@x\pgf@ya\pgf@y% + \pgf@process{\pgf@x\pgf@xb\pgf@y\pgf@yb\pgf@nlt@list}% + \pgf@xb\pgf@x\pgf@yb\pgf@y% + \xdef\pgf@nlt@last@coord@orig{{\the\pgf@xc}{\the\pgf@yc}}% + \pgf@process{\pgf@x\pgf@xc\pgf@y\pgf@yc\pgf@nlt@list}% + \pgf@xc\pgf@x\pgf@yc\pgf@y% + \xdef\pgf@nlt@last@coord@trans{{\the\pgf@xc}{\the\pgf@yc}}% + \pgf@protocolsizes{\pgf@xa}{\pgf@ya}% + \pgf@protocolsizes{\pgf@xb}{\pgf@yb}% + \pgf@protocolsizes{\pgf@xc}{\pgf@yc}% + \pgfsyssoftpath@curveto{\the\pgf@xa}{\the\pgf@ya}{\the\pgf@xb}{\the\pgf@yb}{\the\pgf@xc}{\the\pgf@yc}% +} + + +\def\pgf@nlt@closepath@nlt{% + {% + \expandafter\pgfqpoint\pgf@nlt@last@moveto@orig% + \expandafter\pgf@nlt@set@temps\pgf@nlt@last@coord@orig% + \advance\pgfutil@tempdima by-\pgf@x% + \advance\pgfutil@tempdimb by-\pgf@y% + \pgfutil@tempswatrue% + \ifdim\pgfutil@tempdima<0.01pt\relax\ifdim\pgfutil@tempdima>-0.01pt\relax\ifdim\pgfutil@tempdimb<0.01pt\relax\ifdim\pgfutil@tempdimb>-0.01pt\relax\pgfutil@tempswafalse\fi\fi\fi\fi% + \ifpgfutil@tempswa% + \pgf@nlt@lineto@nlt{\pgf@x}{\pgf@y}% + \fi% + \pgfsyssoftpath@closepath% + }% +} + + +\endinput |