Current File : //usr/share/texlive/texmf-dist/tex/generic/pgf/modules/pgfmodulebending.code.tex |
% Copyright 2019 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{pgfmodulebending.code.tex}
%
% This file defines commands for drawing bending arrows and lines.
%
\usepgfmodule{nonlineartransformations}%
\usepgflibrary{curvilinear}%
% Configuration options for arrow tips:
\pgfkeys{
/pgf/arrow keys/flex/.code=\pgfarrowsaddtooptions{\pgf@arrows@the@rigidity#1pt\let\pgf@arrow@flex@mode\pgf@arrow@mode@is@flex},
/pgf/arrow keys/flex/.default=1,
/pgf/arrow keys/flex'/.code=\pgfarrowsaddtooptions{\pgf@arrows@the@rigidity#1pt\let\pgf@arrow@flex@mode\pgf@arrow@mode@is@flex@prime},
/pgf/arrow keys/flex'/.default=1,
/pgf/arrow
keys/bend/.code=\pgfarrowsaddtooptions{\let\pgf@arrow@flex@mode\pgf@arrow@mode@is@bend},
}%
\def\pgf@arrow@mode@is@flex{1}%
\def\pgf@arrow@mode@is@flex@prime{2}%
\def\pgf@arrow@mode@is@bend{3}%
\newdimen\pgf@arrows@the@rigidity
%
%
% Handle the end of a curve
%
%
% First, the preparation. This is, essentially, setting up the
% nonlinear transformation
\def\pgf@prep@curveend{
\pgftransformreset%
\pgfsetcurvilinearbeziercurve{\pgfpointlastonpath}{\pgfpointsecondlastonpath}{\pgfpointthirdlastonpath}{\pgfpointfourthlastonpath}
}%
% Second, the shortening.
\def\pgf@do@shorten@curvedend{%
\expandafter\expandafter\expandafter\pgf@do@shorten@curvedend@unpack\expandafter\pgfpointfourthlastonpath\pgfpointthirdlastonpath%
}%
\def\pgf@do@shorten@curvedend@unpack\pgfqpoint#1#2\pgfqpoint#3#4{%
\pgf@process{\pgfcurvilineardistancetotime{\pgf@path@shortening@distance}}%
% Compute new curve:
\pgfpointcurveattime{\pgf@x}{\pgfpointlastonpath}{\pgfpointsecondlastonpath}{\pgfpointthirdlastonpath}{\pgfpointfourthlastonpath}%
% \pgfx/y and \pgf xa/xb already correct. Need to setup remaining vector...
\pgf@xb#3%
\pgf@yb#4%
\pgf@xb\pgf@time@t\pgf@xb%
\pgf@yb\pgf@time@t\pgf@yb%
\advance\pgf@xb by\pgf@time@s\pgf@xc%
\advance\pgf@yb by\pgf@time@s\pgf@yc%
\edef\pgfprocessresultsubpathsuffix{%
\expandafter\noexpand\pgfsubpathfourthlasttoken{#1}{#2}%
\noexpand\pgfsyssoftpath@curvetosupportatoken{\the\pgf@xb}{\the\pgf@yb}%
\noexpand\pgfsyssoftpath@curvetosupportbtoken{\the\pgf@xa}{\the\pgf@ya}%
\noexpand\pgfsyssoftpath@curvetotoken{\the\pgf@x}{\the\pgf@y}}%
\expandafter\expandafter\expandafter\def%
\expandafter\expandafter\expandafter\pgfprocessresultpathsuffix%
\expandafter\expandafter\expandafter{\expandafter\pgfprocessresultsubpathprefix\pgfprocessresultsubpathsuffix}%
}%
% Third, the drawing
\def\pgf@do@draw@curvedend{%
\pgf@do@draw@curved\pgf@end@tip@sequence%
}%
\def\pgf@do@draw@curved#1{%
{%
\pgftransformreset%
\pgf@xb\pgf@arrow@tip@total@length% xb will keep track of the total length
\let\pgf@arrow@handle\pgf@draw@curved%
\let\pgf@arrow@handle@dot\relax%
#1%
}%
}%
\def\pgf@draw@curved#1#2{%
% Prepare:
{%
\pgfarrows@getid{#1}{#2}%
% Do shift:
\expandafter\expandafter\expandafter\pgf@arrow@drawer@rigid@shift\csname pgf@ar@ends@\pgf@arrow@id\endcsname%
\expandafter\let\expandafter\pgf@arrow@bending@mode\csname pgf@ar@bending@mode@#1\endcsname%
\ifx\pgf@arrow@bending@mode\pgfutil@empty\let\pgf@arrow@flex@mode\pgf@arrow@mode@is@flex\fi%
% do swap:
{%
\csname pgf@ar@saves@\pgf@arrow@id\endcsname%
\ifcase\pgf@arrow@flex@mode\relax%
\expandafter\expandafter\expandafter\pgf@arrow@drawer@rigid\csname pgf@ar@visual@\pgf@arrow@id\endcsname% like flex
\or%
\expandafter\expandafter\expandafter\pgf@arrow@drawer@rigid\csname pgf@ar@visual@\pgf@arrow@id\endcsname%
\or%
\expandafter\expandafter\expandafter\pgf@arrow@drawer@rigid\csname pgf@ar@ends@\pgf@arrow@id\endcsname%
\or%
\pgf@arrow@drawer@bend%
\fi%
% hull points inside the above
}%
\expandafter}%
% Transform to next tip:
\expandafter\pgf@xb\the\pgf@xb%
}%
\def\pgf@falsetext{false}%
\def\pgf@arrow@drawer@rigid@shift#1#2#3{% tip end, back end, line end, sep
% Let xa be the actual back end of the current arrow plus the back end:
\advance\pgf@xb by#2%
\pgf@xa\pgf@xb%
% Update the xb:
\pgf@x#1%
\advance\pgf@x by\pgfarrowsep%
\advance\pgf@xb by-\pgf@x%
}%
\def\pgf@arrow@drawer@bend{%
\pgftransformnonlinear{\pgf@arrow@bending@mode{\pgf@x}{\pgf@y}}
\pgftransformscale{-1}%
\pgftransformxshift{-\pgf@xa}%
% Do slant:
\ifdim\pgfarrows@slant pt=0pt%
\else%
\pgftransformxslant{\pgfarrows@slant}%
\fi%
\ifpgfarrowswap%
\pgftransformyscale{-1}%
\fi%
{%
\pgf@relevantforpicturesizefalse%
\pgfscope%
\pgf@arrows@color@setup%
\csname pgf@ar@inst@code@\pgf@arrow@id\endcsname%
\endpgfscope%
}%
\pgf@arrows@bending@hull%
}%
\def\pgf@arrow@drawer@rigid#1#2#3{% (rigid) start, (rigid) end, dummy
% Compute the rigid positions:
\pgf@x#1% start
\pgf@y#2% flexibility*(end-start) + start
\advance\pgf@y by-\pgf@x%
\pgf@y\pgf@sys@tonumber\pgf@arrows@the@rigidity\pgf@y%
\advance\pgf@y by\pgf@x%
% Are they equal?
\ifdim\pgf@x=\pgf@y%
% Yes, do tangent:
\pgf@bending@do@tangent%
\else%
\pgf@bending@do@flex%
\fi%
\pgf@xc#1%
\pgf@xc-\pgf@xc%
\pgftransformxshift{+\pgf@xc}%
% Do slant:
\ifdim\pgfarrows@slant pt=0pt%
\else%
\pgftransformxslant{\pgfarrows@slant}%
\fi%
% do swap:
\ifpgfarrowswap%
\pgftransformyscale{-1}%
\fi%
\pgfscope%
\pgf@arrows@color@setup%
\pgflowlevelsynccm\csname pgf@ar@cache@\pgf@arrow@id\endcsname%
\endpgfscope%
\pgf@arrows@rigid@hull%
}%
\def\pgf@bending@do@tangent{%
\pgf@xb\pgf@xa%
\advance\pgf@xb by-\pgf@x%
\pgfcurvilineardistancetotime{\pgf@xb}%
\pgf@xb\pgf@x%
% Compute points:
\ifdim\pgf@xb=0pt%
\pgf@bending@possible@degenerate%
\else%
\pgf@bending@do@tangent@normal%
\fi%
\pgf@ya-\pgf@y%
\pgfsettransformentries%
{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}%
{\pgf@sys@tonumber\pgf@ya}{\pgf@sys@tonumber\pgf@x}{\pgf@xc}{\pgf@yc}%
}%
\def\pgf@bending@do@tangent@normal{%
\pgfpointcurveattime{\pgf@xb}{\pgf@curvilinear@line@a}{\pgf@curvilinear@line@b}{\pgf@curvilinear@line@c}{\pgf@curvilinear@line@d}%
\pgf@xc\pgf@x% save
\pgf@yc\pgf@y% save
% compute normal:
\advance\pgf@xb by-\pgf@xa%
\advance\pgf@yb by-\pgf@ya%
\pgf@process{\pgfpointnormalised{\pgf@x=\pgf@xb\pgf@y=\pgf@yb}}
}%
\def\pgf@bending@possible@degenerate{%
\ifx\pgf@curvilinear@line@a\pgf@curvilinear@line@b% degenerate!
\ifx\pgf@curvilinear@line@a\pgf@curvilinear@line@c% double degenerate!
\let\pgf@ref\pgf@curvilinear@line@d%
\else
\let\pgf@ref\pgf@curvilinear@line@c%
\fi%
\pgf@process{\pgf@curvilinear@line@a}%
\pgf@xc\pgf@x% save
\pgf@yc\pgf@y% save
\pgf@process{\pgf@ref}%
\advance\pgf@x by-\pgf@xc
\advance\pgf@y by-\pgf@yc
\pgf@process{\pgfpointnormalised{}}
\pgf@x-\pgf@x
\pgf@y-\pgf@y
\else%
\pgf@bending@do@tangent@normal%
\fi%
}%
\def\pgf@bending@do@flex{
\pgf@xb\pgf@xa%
\pgf@xc\pgf@xa%
\advance\pgf@xc by-\pgf@x%
\advance\pgf@xb by-\pgf@y%
\pgfcurvilineardistancetotime{\pgf@xc}%
\pgf@xc\pgf@x%
\pgfcurvilineardistancetotime{\pgf@xb}%
\pgf@xb\pgf@x%
% Compute points:
\pgf@process{\pgfpointcurveattime{\pgf@xc}{\pgf@curvilinear@line@a}{\pgf@curvilinear@line@b}{\pgf@curvilinear@line@c}{\pgf@curvilinear@line@d}}%
\pgf@xc\pgf@x\pgf@yc\pgf@y%
\pgf@process{\pgfpointcurveattime{\pgf@xb}{\pgf@curvilinear@line@a}{\pgf@curvilinear@line@b}{\pgf@curvilinear@line@c}{\pgf@curvilinear@line@d}}%
\pgf@xb\pgf@x\pgf@yb\pgf@y%
\pgftransformarrow{\pgfqpoint{\pgf@xb}{\pgf@yb}}{\pgfqpoint{\pgf@xc}{\pgf@yc}}%
}%
% Convex hull stuff:
\def\pgf@arrows@bending@hull{%
\ifpgf@relevantforpicturesize%
% Do bb update:
\expandafter\let\expandafter\pgf@temp\csname pgf@ar@hull@\pgf@arrow@id\endcsname%
\ifx\pgf@temp\pgfutil@empty\else%
\let\pgf@arrow@hull@point\pgf@arrow@bending@hull@point@first%
\pgf@temp%
\pgf@arrow@bending@update@bb%
\fi%
\fi%
}%
\def\pgf@arrow@bending@hull@point@first#1#2{%
\pgfpointtransformednonlinear{\pgfqpoint{#1}{#2}}%
\pgf@xa\pgf@x\pgf@xb\pgf@x%
\pgf@ya\pgf@y\pgf@yb\pgf@y%
\let\pgf@arrow@hull@point\pgf@arrow@bending@hull@point@other%
}%
\def\pgf@arrow@bending@hull@point@other#1#2{%
\pgfpointtransformednonlinear{\pgfqpoint{#1}{#2}}%
\ifdim\pgf@x<\pgf@xa\pgf@xa\pgf@x\else\ifdim\pgf@x>\pgf@xb\pgf@xb\pgf@x\fi\fi%
\ifdim\pgf@y<\pgf@ya\pgf@ya\pgf@y\else\ifdim\pgf@y>\pgf@yb\pgf@yb\pgf@y\fi\fi%
}%
\def\pgf@arrow@bending@update@bb{%
\ifdim\pgf@picmaxx=-16000pt\relax%
\global\pgf@picminx\pgf@xa%
\global\pgf@picmaxx\pgf@xb%
\global\pgf@picminy\pgf@ya%
\global\pgf@picmaxy\pgf@yb%
\else%
\ifdim\pgf@xa<\pgf@picminx\global\pgf@picminx\pgf@xa\fi%
\ifdim\pgf@ya<\pgf@picminy\global\pgf@picminy\pgf@ya\fi%
\ifdim\pgf@xb>\pgf@picmaxx\global\pgf@picmaxx\pgf@xb\fi%
\ifdim\pgf@yb>\pgf@picmaxy\global\pgf@picmaxy\pgf@yb\fi%
\fi%
}%
%
%
% Handle the start of a curve
%
%
% First, the preparation.
\def\pgf@prep@curvedstart{
\pgftransformreset%
\pgfsetcurvilinearbeziercurve{\pgfpointfirstonpath}{\pgfpointsecondonpath}{\pgfpointthirdonpath}{\pgfpointfourthonpath}%
}%
% Second, the shortening.
\def\pgf@do@shorten@curvedstart{%
\expandafter\expandafter\expandafter\pgf@do@shorten@curvedstart@unpack\expandafter\pgfpointthirdonpath\pgfpointfourthonpath%
}%
\def\pgf@do@shorten@curvedstart@unpack\pgfqpoint#1#2\pgfqpoint#3#4{%
\pgf@process{\pgfcurvilineardistancetotime{\pgf@path@shortening@distance}}%
% Compute new curve:
\pgfpointcurveattime{\pgf@x}{\pgfpointfirstonpath}{\pgfpointsecondonpath}{\pgfpointthirdonpath}{\pgfpointfourthonpath}%
% \pgfx/y and \pgf xa/xb already correct. Need to setup remaining vector...
\pgf@xb#1%
\pgf@yb#2%
\pgf@xb\pgf@time@t\pgf@xb%
\pgf@yb\pgf@time@t\pgf@yb%
\advance\pgf@xb by\pgf@time@s\pgf@xc%
\advance\pgf@yb by\pgf@time@s\pgf@yc%
\edef\pgfpointfirstonpath{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}%
\edef\pgfpointsecondonpath{\noexpand\pgfqpoint{\the\pgf@xa}{\the\pgf@ya}}%
\edef\pgfprocessresultpathsuffix{%
\noexpand\pgfsyssoftpath@movetotoken{\the\pgf@x}{\the\pgf@y}%
\noexpand\pgfsyssoftpath@curvetosupportatoken{\the\pgf@xa}{\the\pgf@ya}%
\noexpand\pgfsyssoftpath@curvetosupportbtoken{\the\pgf@xb}{\the\pgf@yb}%
\noexpand\pgfsyssoftpath@curvetotoken{#3}{#4}%
}
\expandafter\expandafter\expandafter\def%
\expandafter\expandafter\expandafter\pgfprocessresultpathsuffix%
\expandafter\expandafter\expandafter{\expandafter\pgfprocessresultpathsuffix\pgfsubpathend}%
}%
% Third, the drawing
\def\pgf@do@draw@curvedstart{%
\pgf@do@draw@curved\pgf@start@tip@sequence%
}%
\endinput