diff options
Diffstat (limited to 'Master/texmf-dist/tex/generic')
96 files changed, 7674 insertions, 1923 deletions
diff --git a/Master/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.code.tex b/Master/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.code.tex index d0fdab957aa..887e86e00e7 100644 --- a/Master/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.code.tex @@ -7,7 +7,7 @@ % % See the file doc/generic/pgf/licenses/LICENSE for more details. -\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/basiclayer/pgfcorearrows.code.tex,v 1.40 2013/11/07 15:45:46 tantau Exp $ +\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/basiclayer/pgfcorearrows.code.tex,v 1.43 2015/05/14 14:43:05 cfeuersaenger Exp $ @@ -575,8 +575,9 @@ } \def\pgfarrows@angle@setup@prime#1{% - \pgf@yc#1 pt% - \pgfmathtan@{.5\pgf@yc}% + \pgf@yc#1 pt % + \pgf@yc=0.5\pgf@yc + \pgfmathtan@{\pgf@sys@tonumber\pgf@yc}% \pgfarrowwidth\pgfmathresult\pgfarrowlength% \pgfarrowwidth2\pgfarrowwidth% } @@ -871,15 +872,26 @@ \expandafter\pgftransformxshift\expandafter{\the\pgf@xc}% } +\def\pgf@arrows@color@setup@restore@std@colors{% + % we want to allow 'arrows={fill=pgffillcolor}'. To this end, we have to ensure that \string\color@pgffillcolor is known. + % we can safely keep the macro in the current TeX group since it has global character anyway. + % + % Note that declaring \string\color@pgfstrokecolor as \global macro causes save stack issues and should be avoided. + \pgfutil@namelet{\string\color@pgfstrokecolor}{pgf@strokecolor@global}% + \pgfutil@namelet{\string\color@pgffillcolor}{pgf@fillcolor@global}% + % +}% + \def\pgf@arrows@color@setup{% \ifx\pgf@arrows@stroke@color\pgfutil@empty\else\pgfsetstrokecolor{\pgf@arrows@stroke@color}\fi% \ifx\pgf@arrows@fill@color\pgfutil@empty% - \expandafter\expandafter\expandafter\ifx% - \expandafter\csname\expandafter\string\expandafter\color@pgfstrokecolor\expandafter\endcsname\csname\string\color@pgffillcolor\endcsname% + \ifx\pgf@strokecolor@global\pgf@fillcolor@global \else + \pgf@arrows@color@setup@restore@std@colors \pgfsetfillcolor{pgfstrokecolor}% \fi% \else% + \pgf@arrows@color@setup@restore@std@colors \pgfsetfillcolor{\pgf@arrows@fill@color}% \fi% } diff --git a/Master/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal.code.tex b/Master/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal.code.tex index 75789f2d16c..31fa80f3635 100644 --- a/Master/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal.code.tex @@ -7,7 +7,7 @@ % % See the file doc/generic/pgf/licenses/LICENSE for more details. -\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/basiclayer/pgfcoreexternal.code.tex,v 1.20 2013/07/15 12:05:31 tantau Exp $ +\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/basiclayer/pgfcoreexternal.code.tex,v 1.21 2014/07/09 14:01:22 cfeuersaenger Exp $ @@ -492,7 +492,7 @@ \immediate\closeout\pgf@plotwrite \fi \fi - \pgfsys@papersize{\the\wd\pgfpic}{\the\dimen0}% + \pgfsys@prepare@papersize{\the\wd\pgfpic}{\the\dimen0}% % \setbox0=\vbox{% % I admit that I don't know why there is this kerning: diff --git a/Master/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicstate.code.tex b/Master/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicstate.code.tex index 81b39f34659..a0a7ac9651e 100644 --- a/Master/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicstate.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicstate.code.tex @@ -7,7 +7,7 @@ % % See the file doc/generic/pgf/licenses/LICENSE for more details. -\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/basiclayer/pgfcoregraphicstate.code.tex,v 1.11 2013/09/19 22:34:34 tantau Exp $ +\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/basiclayer/pgfcoregraphicstate.code.tex,v 1.12 2014/11/02 21:38:01 cfeuersaenger Exp $ % Globals @@ -125,9 +125,10 @@ \def\pgfsetstrokecolor#1{% \pgfutil@colorlet{pgfstrokecolor}{#1}% \pgfutil@ifundefined{applycolormixins}{}{\applycolormixins{pgfstrokecolor}}% - \expandafter\expandafter\expandafter\global% - \expandafter\expandafter\expandafter\let\expandafter\csname\expandafter\string\expandafter\color@pgfstrokecolor\expandafter\endcsname\csname\string\color@pgfstrokecolor\endcsname% - \expandafter\expandafter\expandafter\pgf@setstrokecolor\csname\string\color@pgfstrokecolor\endcsname% + \expandafter\let\expandafter\pgf@temp\csname\string\color@pgfstrokecolor\endcsname + % for arrow tips: + \global\let\pgf@strokecolor@global=\pgf@temp + \expandafter\pgf@setstrokecolor\pgf@temp% } \def\pgf@setstrokecolor#1#2#3#4#5{% \expandafter\ifx\csname pgfsys@color@#4@stroke\endcsname\relax% @@ -159,9 +160,10 @@ \def\pgfsetfillcolor#1{% \pgfutil@colorlet{pgffillcolor}{#1}% \pgfutil@ifundefined{applycolormixins}{}{\applycolormixins{pgffillcolor}}% - \expandafter\expandafter\expandafter\global% - \expandafter\expandafter\expandafter\let\expandafter\csname\expandafter\string\expandafter\color@pgffillcolor\expandafter\endcsname\csname\string\color@pgffillcolor\endcsname% - \expandafter\expandafter\expandafter\pgf@setfillcolor\csname\string\color@pgffillcolor\endcsname% + \expandafter\let\expandafter\pgf@temp\csname\string\color@pgffillcolor\endcsname + % for arrow tips: + \global\let\pgf@fillcolor@global=\pgf@temp + \expandafter\pgf@setfillcolor\pgf@temp } \def\pgf@setfillcolor#1#2#3#4#5{% \expandafter\ifx\csname pgfsys@color@#4@fill\endcsname\relax% @@ -183,11 +185,11 @@ \def\pgfsetcolor#1{% \pgfutil@colorlet{pgfstrokecolor}{#1}% \pgfutil@ifundefined{applycolormixins}{}{\applycolormixins{pgfstrokecolor}}% - \expandafter\expandafter\expandafter\global% - \expandafter\expandafter\expandafter\let\expandafter\csname\expandafter\string\expandafter\color@pgfstrokecolor\expandafter\endcsname\csname\string\color@pgfstrokecolor\endcsname% - \expandafter\expandafter\expandafter\global% - \expandafter\expandafter\expandafter\let\expandafter\csname\expandafter\string\expandafter\color@pgffillcolor\expandafter\endcsname\csname\string\color@pgfstrokecolor\endcsname% - \expandafter\expandafter\expandafter\pgf@setcolor\csname\string\color@pgfstrokecolor\endcsname% + \expandafter\let\expandafter\pgf@temp\csname\string\color@pgfstrokecolor\endcsname + % for arrow tips: + \global\let\pgf@strokecolor@global=\pgf@temp + \global\let\pgf@fillcolor@global=\pgf@temp + \expandafter\pgf@setcolor\pgf@temp% } \def\pgf@setcolor#1#2#3#4#5{% \expandafter\ifx\csname pgfsys@color@#4\endcsname\relax% diff --git a/Master/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage.code.tex b/Master/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage.code.tex index e60f66cce2f..0c36d3c1a4f 100644 --- a/Master/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage.code.tex @@ -7,7 +7,7 @@ % % See the file doc/generic/pgf/licenses/LICENSE for more details. -\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/basiclayer/pgfcorepathusage.code.tex,v 1.23 2013/12/13 15:11:58 tantau Exp $ +\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/basiclayer/pgfcorepathusage.code.tex,v 1.24 2014/11/02 21:38:01 cfeuersaenger Exp $ % Stroke/fill/clip/etc. the current path. Depending on the options, @@ -236,7 +236,7 @@ \def\pgf@stroke@inner@line@if@needed{% \ifdim\pgfinnerlinewidth>0pt\relax% - \expandafter\let\expandafter\pgf@temp@save\csname\string\color@pgfstrokecolor\endcsname% + \let\pgf@temp@save=\pgf@strokecolor@global \pgfsys@beginscope% {% \pgfsys@setlinewidth{\pgfinnerlinewidth}% @@ -245,7 +245,7 @@ \pgfsys@stroke% }% \pgfsys@endscope% - \expandafter\global\expandafter\let\csname\string\color@pgfstrokecolor\endcsname\pgf@temp@save% + \global\let\pgf@strokecolor@global=\pgf@temp@save \fi% } diff --git a/Master/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.code.tex b/Master/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.code.tex index 406d52e3a22..02687fc29c3 100644 --- a/Master/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.code.tex @@ -7,7 +7,7 @@ % % See the file doc/generic/pgf/licenses/LICENSE for more details. -\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/basiclayer/pgfcorescopes.code.tex,v 1.44 2013/10/09 18:30:27 tantau Exp $ +\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/basiclayer/pgfcorescopes.code.tex,v 1.46 2015/05/08 10:23:50 tantau Exp $ % Globals @@ -50,14 +50,14 @@ \pgfsys@beginscope% \pgf@resetpathsizes% \edef\pgfscope@linewidth{\the\pgflinewidth}% - \expandafter\let\expandafter\pgfscope@stroke@color\csname\string\color@pgfstrokecolor\endcsname% - \expandafter\let\expandafter\pgfscope@fill@color\csname\string\color@pgffillcolor\endcsname% + \let\pgfscope@stroke@color=\pgf@strokecolor@global% + \let\pgfscope@fill@color=\pgf@fillcolor@global% \begingroup} \def\endpgfscope{% \endgroup% \global\pgflinewidth=\pgfscope@linewidth% - \expandafter\global\expandafter\let\csname\string\color@pgfstrokecolor\endcsname\pgfscope@stroke@color% - \expandafter\global\expandafter\let\csname\string\color@pgffillcolor\endcsname\pgfscope@fill@color% + \global\let\pgf@strokecolor@global=\pgfscope@stroke@color% + \global\let\pgf@fillcolor@global=\pgfscope@fill@color% \pgfsys@endscope} diff --git a/Master/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransformations.code.tex b/Master/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransformations.code.tex index 83f89b1fa2d..5e13c6cb660 100644 --- a/Master/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransformations.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransformations.code.tex @@ -7,7 +7,7 @@ % % See the file doc/generic/pgf/licenses/LICENSE for more details. -\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/basiclayer/pgfcoretransformations.code.tex,v 1.17 2013/10/10 08:53:09 tantau Exp $ +\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/basiclayer/pgfcoretransformations.code.tex,v 1.20 2015/08/07 10:17:34 cfeuersaenger Exp $ % Position transformations @@ -58,8 +58,8 @@ % \pgfsettransformentries\aa\ab\ba\bb\shiftx\shifty \def\pgfgettransformentries#1#2#3#4#5#6{% \edef#1{\pgf@pt@aa}% - \edef#2{\pgf@pt@ab}% - \edef#3{\pgf@pt@ba}% + \edef#2{\pgf@pt@ab}% attention: this is (1,0), i.e. the point which is usually labelled 'ba'! + \edef#3{\pgf@pt@ba}% attention: this is (0,1), i.e. the point which is usually labelled 'ab'! \edef#4{\pgf@pt@bb}% \edef#5{\the\pgf@pt@x}% \edef#6{\the\pgf@pt@y}% @@ -97,6 +97,8 @@ \def\pgf@idmatrixtext{1.0,0.0,0.0,1.0} \def\pgf@zerozerotext{0.0,0.0} +\def\pgf@one@text{1.0} +\def\pgf@zero@text{0.0} % Transformation command % @@ -317,10 +319,10 @@ \def\pgftransformreset{% \pgf@pt@x=0pt% \pgf@pt@y=0pt% - \def\pgf@pt@aa{1.0}% - \def\pgf@pt@ba{0.0}% - \def\pgf@pt@ab{0.0}% - \def\pgf@pt@bb{1.0}% + \let\pgf@pt@aa\pgf@one@text% + \let\pgf@pt@ba\pgf@zero@text% + \let\pgf@pt@ab\pgf@zero@text% + \let\pgf@pt@bb\pgf@one@text% \pgf@pt@identitytrue% } @@ -332,10 +334,10 @@ % \pgftansformreset \def\pgftransformresetnontranslations{% - \def\pgf@pt@aa{1.0}% - \def\pgf@pt@ba{0.0}% - \def\pgf@pt@ab{0.0}% - \def\pgf@pt@bb{1.0}% + \let\pgf@pt@aa\pgf@one@text% + \let\pgf@pt@ba\pgf@zero@text% + \let\pgf@pt@ab\pgf@zero@text% + \let\pgf@pt@bb\pgf@one@text% \pgf@pt@identitytrue% } @@ -608,6 +610,62 @@ + +% Computes transformations adjustments for the current transformation +% matrix +% +% Description: +% +% This command is used when you install a transformation matrix that +% scales everything by a certain factor, but you still wish to draw +% something with "an absolute size". Suppose for instance that you +% install a transformation matrix that scales everything by a factor +% of 4 and you now wish to draw a horizontal line of length 1cm. Then, +% if you do not reset the transformation matrix, you can draw a line +% of logical length 2.5mm, which will then get scaled to a line of +% 1cm. +% +% Things get more difficult in case you scale things only, say, +% vertically. In this case, the adjustement necessary for horizontal +% lines is different from the one needed for vertical lines. +% +% This function computes the necessary scaling factors and puts them +% in the macros \pgfhorizontaltransformationadjustment and +% \pgfverticaltransformationadjustment. +% +% Note that the "right" way to draw a line of absolute length 1cm in a +% transformed coordinate system is to first compute the start point +% and to then reset the transformation matrix. The transofmration +% adjustments computed here are important only in situations where you +% cannot do this, for instance when an "outer xsep" must be set. + +\def\pgftransformationadjustments{% + \ifpgf@pt@identity% + \let\pgfhorizontaltransformationadjustment\pgf@one@text% + \let\pgfverticaltransformationadjustment\pgf@one@text% + \else% + {% + \pgf@pt@x0pt% + \pgf@pt@y0pt% + \pgfpointtransformed{\pgfqpoint{1pt}{0pt}}% + \pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}% + \pgfmathreciprocal@{\pgfmathresult}% + \global\let\pgf@temp@hori\pgfmathresult + \pgfpointtransformed{\pgfqpoint{0pt}{1pt}}% + \pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}% + \pgfmathreciprocal@{\pgfmathresult}% + \global\let\pgf@temp@vert\pgfmathresult + \xdef\pgf@marshal@b{\def\noexpand\pgfverticaltransformationadjustment{\pgfmathresult}} + }% + \let\pgfhorizontaltransformationadjustment\pgf@temp@hori% + \let\pgfverticaltransformationadjustment\pgf@temp@vert% + \fi% +} + +\let\pgfhorizontaltransformationadjustment\pgf@one@text +\let\pgfverticaltransformationadjustment\pgf@one@text + + % Low-level transformations % Causes the current high-level transformation command to be applied @@ -675,7 +733,7 @@ \let\pgfapproximatenonlineartranslation\relax \let\pgfapproximatenonlineartransformation\relax \def\pgftransformnonlinear#1{\pgferror{You need to say - \string\usepgfmodule{nonlineartransformation} to use nonlinear transformations}} + \string\usepgfmodule{nonlineartransformations} to use nonlinear transformations}} \endinput diff --git a/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/datavisualization/tikzlibrarydatavisualization.code.tex b/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/datavisualization/tikzlibrarydatavisualization.code.tex index e181c3b97ab..ba79c22b33f 100644 --- a/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/datavisualization/tikzlibrarydatavisualization.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/datavisualization/tikzlibrarydatavisualization.code.tex @@ -7,7 +7,7 @@ % % See the file doc/generic/pgf/licenses/LICENSE for more details. -\ProvidesFileRCS[v\pgfversion] $Header: /cvsroot/pgf/pgf/generic/pgf/frontendlayer/tikz/libraries/datavisualization/tikzlibrarydatavisualization.code.tex,v 1.44 2013/07/19 13:16:48 tantau Exp $ +\ProvidesFileRCS[v\pgfversion] $Header: /cvsroot/pgf/pgf/generic/pgf/frontendlayer/tikz/libraries/datavisualization/tikzlibrarydatavisualization.code.tex,v 1.48 2015/05/18 17:01:16 tantau Exp $ \usepgfmodule{datavisualization} \usetikzlibrary{backgrounds} @@ -19,7 +19,8 @@ \pgfkeys{/tikz/\tikz@dv@key/.try={#1}}% \ifpgfkeyssuccess% \else% - \pgfkeys{/errors/unknown key={/tikz/data visualization/\tikz@dv@key}{#1}}% + \edef\pgf@temp{/errors/unknown key={/tikz/data visualization/\tikz@dv@key}}% + \expandafter\pgfkeys\expandafter{\pgf@temp{#1}}% \fi% }, /tikz/data visualization/data/.unknown/.code={% @@ -28,7 +29,8 @@ \pgfkeys{/pgf/data/\tikz@dv@key/.try={#1}}% \ifpgfkeyssuccess% \else% - \pgfkeys{/errors/unknown key={/pgf/data/\tikz@dv@key}{#1}}% + \edef\pgf@temp{/errors/unknown key={/pgf/data/\tikz@dv@key}}% + \expandafter\pgfkeys\expandafter{\pgf@temp{#1}}% \fi% } } @@ -775,7 +777,7 @@ \def\tikz@lib@dv@show@axis#1#2{% \scope[data visualization/axis layer,/tikz/data visualization/.cd,low=min,high=max,every axis/.try,#2] - \pgfkeysgetvalue{#1/scaling mapper}\tikz@dv@axis@mapper + \pgfkeysgetvalue{#1/scaling mapper}\tikz@dv@axis@mapper% % Ok, calculate direction vector: \tikzpointandanchordirection{\tikz@dv@axis@mapper.set in to(min)}{\tikz@dv@axis@mapper.set in to(max)} \xdef\tikz@dv@axis@dir{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}} @@ -1178,48 +1180,53 @@ \pgfkeysgetvalue{/tikz/data visualization/phase}\tikz@temp \pgfdvmathenter{\tikz@dv@lib@phase}{\tikz@temp} \pgfdvmathenter{\tikz@dv@lib@step}{\tikz@lib@dv@step} - % Compute start: - \pgfdvmathsub{\tikz@dv@lib@temp}{\pgfdvmin}{\tikz@dv@lib@phase}% temp = dvmin - phase - \pgfdvmathdiv{\tikz@dv@lib@temp}{\tikz@dv@lib@temp}{\tikz@dv@lib@step}% temp = temp/step - \pgfdvmathfloor{\tikz@dv@lib@temp}{\tikz@dv@lib@temp}% temp = floor(temp) - \pgfdvmathmul{\tikz@lib@dv@current}{\tikz@dv@lib@temp}{\tikz@dv@lib@step}% current = temp*step ... - \pgfdvmathadd{\tikz@lib@dv@current}{\tikz@lib@dv@current}{\tikz@dv@lib@phase}% + phase - \let\tikz@lib@dv@ats\pgfutil@empty% - \let\tikz@lib@dv@minor@ats\pgfutil@empty% - \tikz@lib@dv@mapper.get function(\tikz@temp)% - \ifx\tikz@temp\pgfutil@empty% - \pgfdvmathenter{\tikz@one@hundreth}{0.001}% - \pgfdvmathsub{\tikz@lib@temp}{\pgfdvmax}{\pgfdvmin}% - \pgfdvmathmul{\tikz@lib@dv@epsilon}{\tikz@lib@temp}{\tikz@one@hundreth}% epsilon = (max - min)/1000 - \else - \let\tikz@lib@dv@epsilon\pgfdvmathalwayszero - \fi - \pgfdvmathsub{\tikz@lib@dv@min@minus@epsilon}{\pgfdvmin}{\tikz@lib@dv@epsilon}% - \pgfdvmathadd{\tikz@lib@dv@max@plus@epsilon}{\pgfdvmax}{\tikz@lib@dv@epsilon}% - \pgfkeysgetvalue{/tikz/data visualization/minor steps between steps}\tikz@lib@dv@substeps% - \ifx\tikz@lib@dv@substeps\pgfutil@empty - \else - \pgfmathsetmacro\tikz@temp{\tikz@lib@dv@substeps+1}% - \pgfdvmathenter{\tikz@dv@lib@substeps}{\tikz@temp}% - \pgfdvmathdiv{\tikz@lib@dv@substep}{\tikz@dv@lib@step}{\tikz@dv@lib@substeps}% - \fi - \loop% - \ifx\tikz@lib@dv@substeps\pgfutil@empty% - \else% - \let\tikz@lib@dv@subcurrent=\tikz@lib@dv@current% - \pgfmathsetcount{\c@pgf@counta}{\tikz@lib@dv@substeps}% - \let\tikz@lib@dv@next=\tikz@lib@dv@subloop% - \tikz@lib@dv@subloop - \fi% - \pgfdvmathifless{\tikz@lib@dv@current}{\tikz@lib@dv@min@minus@epsilon}{}{% - \pgfdvmathexitbyserializing{\tikz@temp}{\tikz@lib@dv@current}% - \edef\tikz@lib@dv@ats{\tikz@lib@dv@ats,\tikz@temp}% - } - \pgfdvmathadd{\tikz@lib@dv@current}{\tikz@lib@dv@current}{\tikz@dv@lib@step}% - \pgfdvmathifless{\tikz@lib@dv@current}{\tikz@lib@dv@max@plus@epsilon}{\tikz@lib@dv@continuetrue}{\tikz@lib@dv@continuefalse}% - \iftikz@lib@dv@continue% - \repeat% - \tikzdatavisualizationset{major/.expanded={at={\tikz@lib@dv@ats}},minor/.expanded={at={\tikz@lib@dv@minor@ats}}}% + \pgfdvmathifless{\pgfdvmathalwayszero}{\tikz@dv@lib@step}{% + % Compute start: + \pgfdvmathsub{\tikz@dv@lib@temp}{\pgfdvmin}{\tikz@dv@lib@phase}% temp = dvmin - phase + \pgfdvmathdiv{\tikz@dv@lib@temp}{\tikz@dv@lib@temp}{\tikz@dv@lib@step}% temp = temp/step + \pgfdvmathfloor{\tikz@dv@lib@temp}{\tikz@dv@lib@temp}% temp = floor(temp) + \pgfdvmathmul{\tikz@lib@dv@current}{\tikz@dv@lib@temp}{\tikz@dv@lib@step}% current = temp*step ... + \pgfdvmathadd{\tikz@lib@dv@current}{\tikz@lib@dv@current}{\tikz@dv@lib@phase}% + phase + \let\tikz@lib@dv@ats\pgfutil@empty% + \let\tikz@lib@dv@minor@ats\pgfutil@empty% + \tikz@lib@dv@mapper.get function(\tikz@temp)% + \ifx\tikz@temp\pgfutil@empty% + \pgfdvmathenter{\tikz@one@hundreth}{0.001}% + \pgfdvmathsub{\tikz@lib@temp}{\pgfdvmax}{\pgfdvmin}% + \pgfdvmathmul{\tikz@lib@dv@epsilon}{\tikz@lib@temp}{\tikz@one@hundreth}% epsilon = (max - min)/1000 + \else + \let\tikz@lib@dv@epsilon\pgfdvmathalwayszero + \fi + \pgfdvmathsub{\tikz@lib@dv@min@minus@epsilon}{\pgfdvmin}{\tikz@lib@dv@epsilon}% + \pgfdvmathadd{\tikz@lib@dv@max@plus@epsilon}{\pgfdvmax}{\tikz@lib@dv@epsilon}% + \pgfkeysgetvalue{/tikz/data visualization/minor steps between steps}\tikz@lib@dv@substeps% + \ifx\tikz@lib@dv@substeps\pgfutil@empty + \else + \pgfmathsetmacro\tikz@temp{\tikz@lib@dv@substeps+1}% + \pgfdvmathenter{\tikz@dv@lib@substeps}{\tikz@temp}% + \pgfdvmathdiv{\tikz@lib@dv@substep}{\tikz@dv@lib@step}{\tikz@dv@lib@substeps}% + \fi + \loop% + \ifx\tikz@lib@dv@substeps\pgfutil@empty% + \else% + \let\tikz@lib@dv@subcurrent=\tikz@lib@dv@current% + \pgfmathsetcount{\c@pgf@counta}{\tikz@lib@dv@substeps}% + \let\tikz@lib@dv@next=\tikz@lib@dv@subloop% + \tikz@lib@dv@subloop + \fi% + \pgfdvmathifless{\tikz@lib@dv@current}{\tikz@lib@dv@min@minus@epsilon}{}{% + \pgfdvmathexitbyserializing{\tikz@temp}{\tikz@lib@dv@current}% + \edef\tikz@lib@dv@ats{\tikz@lib@dv@ats,\tikz@temp}% + } + \pgfdvmathadd{\tikz@lib@dv@current}{\tikz@lib@dv@current}{\tikz@dv@lib@step}% + \pgfdvmathifless{\tikz@lib@dv@current}{\tikz@lib@dv@max@plus@epsilon}{\tikz@lib@dv@continuetrue}{\tikz@lib@dv@continuefalse}% + \iftikz@lib@dv@continue% + \repeat% + \tikzdatavisualizationset{major/.expanded={at={\tikz@lib@dv@ats}},minor/.expanded={at={\tikz@lib@dv@minor@ats}}}% + }{% + \pgfdvmathexitbyserializing{\tikz@temp}{\pgfdvmin}% + \tikzdatavisualizationset{major/.expanded={at={\tikz@temp}}}% + }% \fi% } \newif\iftikz@lib@dv@continue @@ -1267,8 +1274,8 @@ \pgfdvmathenter{\tikz@lib@dv@about@val}{#1}% \pgfdvmathdiv{\tikz@lib@dv@around}{\tikz@lib@dv@diff}{\tikz@lib@dv@about@val}% % Make mantisse sensible - \pgfmathfloattomacro{\tikz@lib@dv@around}{\tikz@lib@dv@flags}{\tikz@lib@dv@mant}{\tikz@lib@dv@exp} - \pgf@xc=\tikz@lib@dv@mant pt% + \pgfmathfloattomacro{\tikz@lib@dv@around}{\tikz@lib@dv@flags}{\tikz@lib@dv@mant}{\tikz@lib@dv@exp}% + \pgf@xc=\tikz@lib@dv@mant pt % \pgfkeysgetvalue{/tikz/data visualization/about strategy}\tikz@lib@dv@strat \foreach \tikz@lib@dv@threshold/\tikz@lib@replace in \tikz@lib@dv@strat { @@ -1276,15 +1283,20 @@ \global\pgf@xc=\tikz@lib@replace pt% \breakforeach \fi - } + }% \ifdim\pgf@xc<10pt% - \pgfmathfloatcreate{\tikz@lib@dv@flags}{\pgf@sys@tonumber{\pgf@xc}}{\tikz@lib@dv@exp} + \pgfmathfloatcreate{\tikz@lib@dv@flags}{\pgf@sys@tonumber{\pgf@xc}}{\tikz@lib@dv@exp}% \else - \pgfmathsetmacro\tikz@lib@dv@exp{\tikz@lib@dv@exp+1} + \begingroup + \c@pgf@countd=\tikz@lib@dv@exp + \advance\c@pgf@countd by1 + \edef\tikz@lib@dv@exp{\the\c@pgf@countd}% + \pgfmath@smuggleone\tikz@lib@dv@exp + \endgroup \divide\pgf@xc by 10\relax - \pgfmathfloatcreate{\tikz@lib@dv@flags}{\pgf@sys@tonumber{\pgf@xc}}{\tikz@lib@dv@exp} + \pgfmathfloatcreate{\tikz@lib@dv@flags}{\pgf@sys@tonumber{\pgf@xc}}{\tikz@lib@dv@exp}% \fi - \pgfmathfloattofixed{\pgfmathresult} + \pgfmathfloattofixed{\pgfmathresult}% \let\tikz@lib@dv@step=\pgfmathresult } @@ -1441,7 +1453,7 @@ \tikz@dv@parse@unit@length@#1per1units\pgf@stop% \fi% } -\def\tikz@dv@parse@unit@length@#1per#2units{ +\def\tikz@dv@parse@unit@length@#1per#2units\pgf@stop{ \pgfkeysalso{\tikz@dv@axis/scaling=0 at 0 and #2 at #1} } diff --git a/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/graphs/tikzlibrarygraphs.code.tex b/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/graphs/tikzlibrarygraphs.code.tex index c82c98c7db7..3f17447fdda 100644 --- a/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/graphs/tikzlibrarygraphs.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/graphs/tikzlibrarygraphs.code.tex @@ -8,7 +8,7 @@ % % See the file doc/generic/pgf/licenses/LICENSE for more details. -\ProvidesFileRCS[v\pgfversion] $Header: /cvsroot/pgf/pgf/generic/pgf/frontendlayer/tikz/libraries/graphs/tikzlibrarygraphs.code.tex,v 1.43 2013/10/10 09:08:58 tantau Exp $ +\ProvidesFileRCS[v\pgfversion] $Header: /cvsroot/pgf/pgf/generic/pgf/frontendlayer/tikz/libraries/graphs/tikzlibrarygraphs.code.tex,v 1.44 2015/06/05 12:41:59 tantau Exp $ % @@ -856,6 +856,16 @@ \fi% } +\newif\iftikzgraphsautonumbernodes +\newcount\tikz@lib@auto@number + +\def\tikz@lib@do@autonumber{% + \ifx\tikz@lib@graph@name@only\pgfutil@empty% + \else% + \edef\tikz@lib@graph@name@only{\tikz@lib@graph@name@only\tikz@lib@auto@sep\the\tikz@lib@auto@number}% + \global\advance\tikz@lib@auto@number by1\relax% + \fi% +} % % Parse the normal part of a node (name and, possibly, text after slash) @@ -928,6 +938,9 @@ % \def\tikz@lib@graph@handle@node@cont{% + \iftikzgraphsautonumbernodes% + \tikz@lib@do@autonumber% + \fi% \iftikz@lib@graph@fresh@node% \tikz@lg@if@local@node{\tikz@lib@graph@name}{\tikz@lg@find@fresh@name}{}% \fi% @@ -1257,6 +1270,13 @@ \newif\iftikz@lib@graph@fresh@node \tikzgraphsset{fresh nodes/.is if=tikz@lib@graph@fresh@node} +\tikzgraphsset{number nodes/.code=% + \pgfmathsetcount\tikz@lib@auto@number{#1}% + \tikzgraphsautonumbernodestrue,% + number nodes/.default=1,% + number nodes sep/.code=\def\tikz@lib@auto@sep{#1} +} +\def\tikz@lib@auto@sep{\space} \newif\iftikz@lib@graph@node@created @@ -2530,16 +2550,17 @@ \def\tikz@lib@graphs@quick@node#1"{% \def\tikzgraphnodename{#1}% - \pgfutil@ifnextchar/\tikz@lib@graphs@quick@text\tikz@lib@graphs@quick@notext% + \let\tikzgraphnodetext\tikzgraphnodename% + \iftikzgraphsautonumbernodes + \edef\tikzgraphnodename{\tikzgraphnodename\tikz@lib@auto@sep\the\tikz@lib@auto@number}% + \global\advance\tikz@lib@auto@number by1\relax% + \fi + \pgfutil@ifnextchar/\tikz@lib@graphs@quick@text\tikz@lib@graphs@quick@opt% } \def\tikz@lib@graphs@quick@text/"#1"{% \def\tikzgraphnodetext{#1}% \tikz@lib@graphs@quick@opt% } -\def\tikz@lib@graphs@quick@notext{% - \let\tikzgraphnodetext\tikzgraphnodename% - \tikz@lib@graphs@quick@opt% -} \def\tikz@lib@graphs@quick@opt{% \pgfutil@ifnextchar[\tikz@lib@graphs@quick@withopt{\tikz@lib@graphs@quick@withopt[]}%] } diff --git a/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzexternalshared.code.tex b/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzexternalshared.code.tex index fc01637466b..50829d90f46 100644 --- a/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzexternalshared.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzexternalshared.code.tex @@ -98,15 +98,22 @@ }% -\pgfutil@ifundefined{pdfshellescape}{% - \def\tikzexternalcheckshellescape{}% +\pgfutil@IfUndefined{pdfshellescape}{% + % let's hope that \usepackage{pdftexcmds} has been used... + \pgfutil@IfUndefined{pdf@shellescape}{% + \def\tikzexternalcheckshellescape{0}% + }{% + \let\tikzexternalcheckshellescape=\pdf@shellescape + }% }{% - \ifnum\pdfshellescape=1 - \def\tikzexternalcheckshellescape{\pgfkeysvalueof{/tikz/external/shell escape}\space}% - \else - \def\tikzexternalcheckshellescape{}% - \fi + \let\tikzexternalcheckshellescape=\pdfshellescape }% +\ifnum\tikzexternalcheckshellescape=1 + \def\tikzexternalcheckshellescape{\pgfkeysvalueof{/tikz/external/shell escape}\space}% +\else + \def\tikzexternalcheckshellescape{}% +\fi + \newif\iftikzexternal@auto@detect@jobname \pgfqkeys{/tikz/external}{ @@ -138,8 +145,6 @@ \pgfkeysalso{/tikz/external/figure list=true,/pgf/images/aux in dpth=true}% }, mode=convert with system call, - system call/.initial={pdflatex \tikzexternalcheckshellescape -halt-on-error -interaction=batchmode -jobname "\image" "\texsource"}, -% system call/.initial={pdflatex -interaction=batchmode -jobname '\image' '\texsource'; pdftops -eps \image.pdf}, force remake/.is if=tikzexternal@force@remake, force remake/.default=true, failed ref warnings for/.initial={\ref,\cite,\pageref}, @@ -234,6 +239,7 @@ \fi }, optimize command away=\includegraphics, + optimize command away=\pgfincludeexternalgraphics, % EXPERIMENTAL (UNTESTED): optimize latex env away/.code={% \expandafter\let\expandafter\pgf@tempa\csname #1\endcsname @@ -262,6 +268,46 @@ up to date check=md5, } +\expandafter\def\csname tikzexternal@driver@pgfsys-pdftex.def\endcsname{% + \pgfutil@IfUndefined{directlua}{% + \pgfkeyssetvalue{/tikz/external/system call}{% + pdflatex \tikzexternalcheckshellescape -halt-on-error -interaction=batchmode -jobname "\image" "\texsource"% + }% + }{% + \pgfkeyssetvalue{/tikz/external/system call}{% + lualatex \tikzexternalcheckshellescape -halt-on-error -interaction=batchmode -jobname "\image" "\texsource"% + }% + }% +}% +%-------------------------------------------------- +% \expandafter\def\csname tikzexternal@driver@pgfsys-dvipdfm.def\endcsname{% +% \pgfkeyssetvalue{/tikz/external/system call}{% +% latex \tikzexternalcheckshellescape -halt-on-error -interaction=batchmode -jobname "\image" "\texsource"% +% && dvipdfm "\image".dvi % +% }% +% }% +%-------------------------------------------------- +\expandafter\def\csname tikzexternal@driver@pgfsys-xetex.def\endcsname{% + \pgfkeyssetvalue{/tikz/external/system call}{% + xelatex \tikzexternalcheckshellescape -halt-on-error -interaction=batchmode -jobname "\image" "\texsource"% + }% +}% +\expandafter\def\csname tikzexternal@driver@pgfsys-dvips.def\endcsname{% + \pgfkeyssetvalue{/tikz/external/system call}{% + latex \tikzexternalcheckshellescape -halt-on-error -interaction=batchmode -jobname "\image" "\texsource" % + && dvips -o "\image".ps "\image".dvi % + }% +}% + +% Auto-select a suitable default value fo 'system call': +\pgfutil@ifundefined{tikzexternal@driver@\pgfsysdriver}{% + % fallback. We do not know the driver here. + \csname tikzexternal@driver@pgfsys-pdftex.def\endcsname +}{% + \csname tikzexternal@driver@\pgfsysdriver\endcsname +}% + + \def\tikzsetfigurename#1{\pgfkeyssetvalue{/tikz/external/figure name}{#1}}% \def\tikzappendtofigurename#1{\pgfkeys{/tikz/external/figure name/.add={}{#1}}} @@ -446,6 +492,9 @@ % '\ref,\pageref,\cite'. % % For use in the aux lock handling only. +% +% ATTENTION: this is used if and only if *all* references are broken +% (because the .aux file is NOT read at all)! \def\tikzexternalauxlock@handleref{% \let\pgf@external@grab@refundefinedtrue=\pgf@external@grab@refundefinedtrue@orig % @@ -472,11 +521,18 @@ \fi \fi }% -\def\tikzexternalauxlock@handleref@repl#1{\pgfutil@ifnextchar[{\tikzexternalauxlock@handleref@repl@{#1}}{\tikzexternalauxlock@handleref@repl@{#1}[]}}% -\def\tikzexternalauxlock@handleref@repl@#1[#2]#3{% +\def\tikzexternalauxlock@handleref@repl#1{% + \pgfutil@ifnextchar[{\tikzexternalauxlock@handleref@gobble@opt{#1}}{\tikzexternalauxlock@handleref@repl@{#1}}% +}% +% silently discard the options. We merely need to generate a warning. +\def\tikzexternalauxlock@handleref@gobble@opt#1[#2]{% + % there may be more than one set of options (biblatex's \cite): + \pgfutil@ifnextchar[{\tikzexternalauxlock@handleref@gobble@opt{#1}}{\tikzexternalauxlock@handleref@repl@{#1}}% +}% +\def\tikzexternalauxlock@handleref@repl@#1#2{% \tikzifexternalizingcurrent{% % note that '#1' is NO control sequence! it is a protected string - \csname tikzexternalauxlock@handleref@orig@#1\endcsname{#3}% + \csname tikzexternalauxlock@handleref@orig@#1\endcsname{#2}% \begingroup \def\n{\pgfexternal@hat\pgfexternal@hat J}% \tikzexternal@assemble@systemcall{\pgfactualjobname}{\pgf@tempa}% @@ -484,7 +540,7 @@ \pgfexternalstorecommand{% \noexpand\begingroup \noexpand\toks0={\pgf@tempa}% - \noexpand\immediate\noexpand\write16{\tikzexternalauxlock@handleref@warning{#3}{\noexpand\the\noexpand\toks0}}% + \noexpand\immediate\noexpand\write16{\tikzexternalauxlock@handleref@warning{#2}{\noexpand\the\noexpand\toks0}}% \noexpand\G@refundefinedtrue \noexpand\endgroup }% @@ -888,8 +944,8 @@ \def\tikzexternalmakefiledefaultdeprule{% \immediate\write\tikzexternal@outmakefile{\tikzexternal@PERCENTchar.\tikzexternaldepext:}% - \immediate\write\tikzexternal@outmakefile{\tikzexternal@TABchar mkdir -p $(dir $@)}% - \immediate\write\tikzexternal@outmakefile{\tikzexternal@TABchar touch $@ \tikzexternal@HASHchar\space will be filled later.}% + \immediate\write\tikzexternal@outmakefile{\tikzexternal@TABchar mkdir -p \tikzexternal@normal@dq $(dir $@)\tikzexternal@normal@dq}% + \immediate\write\tikzexternal@outmakefile{\tikzexternal@TABchar touch \tikzexternal@normal@dq $@\tikzexternal@normal@dq\space \tikzexternal@HASHchar\space will be filled later.}% }% % Invokes '#1' if a makefile is to be written and '#2' if not. @@ -1222,7 +1278,9 @@ }% \fi \expandafter\pgfincludeexternalgraphics\expandafter{\tikzexternal@curfilename}% - \global\let\G@refundefinedtrue=\tikz@refundefinedtrue@@ + \if5\tikzexternal@opmode + \global\let\G@refundefinedtrue=\tikz@refundefinedtrue@@ + \fi \tikzexternal@closeenvironments } diff --git a/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryfolding.code.tex b/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryfolding.code.tex index 1c45b6eac4d..8cd08fc5cd0 100644 --- a/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryfolding.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryfolding.code.tex @@ -8,7 +8,7 @@ % % See the file doc/generic/pgf/licenses/LICENSE for more details. -\ProvidesFileRCS[v\pgfversion] $Header: /cvsroot/pgf/pgf/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryfolding.code.tex,v 1.3 2013/08/28 11:00:54 tantau Exp $ +\ProvidesFileRCS[v\pgfversion] $Header: /cvsroot/pgf/pgf/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryfolding.code.tex,v 1.5 2015/08/03 08:39:35 cfeuersaenger Exp $ % @@ -23,140 +23,140 @@ % ----- \def\tikz@lib@fold@triangle#1#2#3#4{% - \begin{scope}[xshift=.5\tikz@lib@fold@length,yshift=.28868\tikz@lib@fold@length] + \scope[xshift=.5\tikz@lib@fold@length,yshift=.28868\tikz@lib@fold@length] #1 - \end{scope} - \begin{scope}[shift={(60:\tikz@lib@fold@length)},rotate=-60] + \endscope + \scope[shift={(60:\tikz@lib@fold@length)},rotate=-60] #2 - \end{scope} - \begin{scope}[xshift=\tikz@lib@fold@length,rotate=180] + \endscope + \scope[xshift=\tikz@lib@fold@length,rotate=180] #3 - \end{scope} - \begin{scope}[rotate=60] + \endscope + \scope[rotate=60] #4 - \end{scope} + \endscope } \def\tikz@lib@fold@square#1#2#3#4#5{% - \begin{scope}[xshift=.5\tikz@lib@fold@length,yshift=.5\tikz@lib@fold@length] + \scope[xshift=.5\tikz@lib@fold@length,yshift=.5\tikz@lib@fold@length] #1 - \end{scope} - \begin{scope}[yshift=\tikz@lib@fold@length] + \endscope + \scope[yshift=\tikz@lib@fold@length] #2 - \end{scope} - \begin{scope}[xshift=\tikz@lib@fold@length,yshift=\tikz@lib@fold@length,rotate=-90] + \endscope + \scope[xshift=\tikz@lib@fold@length,yshift=\tikz@lib@fold@length,rotate=-90] #3 - \end{scope} - \begin{scope}[xshift=\tikz@lib@fold@length,rotate=180] + \endscope + \scope[xshift=\tikz@lib@fold@length,rotate=180] #4 - \end{scope} - \begin{scope}[rotate=90] + \endscope + \scope[rotate=90] #5 - \end{scope} + \endscope } \def\tikz@lib@fold@pentagon#1#2#3#4#5#6{% - \begin{scope}[xshift=.5\tikz@lib@fold@length,yshift=0.68819\tikz@lib@fold@length] + \scope[xshift=.5\tikz@lib@fold@length,yshift=0.68819\tikz@lib@fold@length] #1 - \end{scope} - \begin{scope}[shift={(108:\tikz@lib@fold@length)},shift={(36:\tikz@lib@fold@length)},rotate=-36] + \endscope + \scope[shift={(108:\tikz@lib@fold@length)},shift={(36:\tikz@lib@fold@length)},rotate=-36] #2 - \end{scope} - \begin{scope}[xshift=\tikz@lib@fold@length,shift={(72:\tikz@lib@fold@length)},rotate=-108] + \endscope + \scope[xshift=\tikz@lib@fold@length,shift={(72:\tikz@lib@fold@length)},rotate=-108] #3 - \end{scope} - \begin{scope}[xshift=\tikz@lib@fold@length,rotate=180] + \endscope + \scope[xshift=\tikz@lib@fold@length,rotate=180] #4 - \end{scope} - \begin{scope}[rotate=108] + \endscope + \scope[rotate=108] #5 - \end{scope} - \begin{scope}[shift={(108:\tikz@lib@fold@length)},rotate=36] + \endscope + \scope[shift={(108:\tikz@lib@fold@length)},rotate=36] #6 - \end{scope} + \endscope } \def\tikz@lib@fold@hexagon#1#2#3#4#5#6#7{% - \begin{scope} + \scope [shift={(60:\tikz@lib@fold@length)}] #1 - \end{scope} - \begin{scope} + \endscope + \scope [shift={(120:\tikz@lib@fold@length)}, shift={(60:\tikz@lib@fold@length)}] #2 - \end{scope} - \begin{scope} + \endscope + \scope [shift={(120:\tikz@lib@fold@length)}, shift={(60:\tikz@lib@fold@length)}, xshift=\tikz@lib@fold@length, rotate=-60] #3 - \end{scope} - \begin{scope} + \endscope + \scope [xshift=\tikz@lib@fold@length, shift={(60:\tikz@lib@fold@length)}, rotate=-120] #4 - \end{scope} - \begin{scope} + \endscope + \scope [xshift=\tikz@lib@fold@length, rotate=180] #5 - \end{scope} - \begin{scope} + \endscope + \scope [rotate=120] #6 - \end{scope} - \begin{scope} + \endscope + \scope [shift={(120:\tikz@lib@fold@length)}, rotate=60] #7 - \end{scope} + \endscope } \def\tikz@lib@fold@octagon#1#2#3#4#5#6#7#8#9{% - \begin{scope}[xshift=.5\tikz@lib@fold@length,yshift=1.20711\tikz@lib@fold@length] + \scope[xshift=.5\tikz@lib@fold@length,yshift=1.20711\tikz@lib@fold@length] #1 - \end{scope} - \begin{scope}[yshift=2.41421\tikz@lib@fold@length] + \endscope + \scope[yshift=2.41421\tikz@lib@fold@length] #2 - \end{scope} - \begin{scope}[xshift=\tikz@lib@fold@length,yshift=2.41421\tikz@lib@fold@length,rotate=-45] + \endscope + \scope[xshift=\tikz@lib@fold@length,yshift=2.41421\tikz@lib@fold@length,rotate=-45] #3 - \end{scope} - \begin{scope}[xshift=1.70711\tikz@lib@fold@length,yshift=1.70711\tikz@lib@fold@length,rotate=-90] + \endscope + \scope[xshift=1.70711\tikz@lib@fold@length,yshift=1.70711\tikz@lib@fold@length,rotate=-90] #4 - \end{scope} - \begin{scope}[xshift=1.70711\tikz@lib@fold@length,yshift=.70711\tikz@lib@fold@length,rotate=-135] + \endscope + \scope[xshift=1.70711\tikz@lib@fold@length,yshift=.70711\tikz@lib@fold@length,rotate=-135] #5 - \end{scope} - \begin{scope}[xshift=\tikz@lib@fold@length,rotate=180] + \endscope + \scope[xshift=\tikz@lib@fold@length,rotate=180] #6 - \end{scope} - \begin{scope}[rotate=135] + \endscope + \scope[rotate=135] #7 - \end{scope} - \begin{scope}[xshift=-.70711\tikz@lib@fold@length,yshift=.70711\tikz@lib@fold@length,rotate=90] + \endscope + \scope[xshift=-.70711\tikz@lib@fold@length,yshift=.70711\tikz@lib@fold@length,rotate=90] #8 - \end{scope} - \begin{scope}[xshift=-.70711\tikz@lib@fold@length,yshift=1.70711\tikz@lib@fold@length,rotate=45] + \endscope + \scope[xshift=-.70711\tikz@lib@fold@length,yshift=1.70711\tikz@lib@fold@length,rotate=45] #9 - \end{scope} + \endscope } \def\tikz@lib@fold@decagon#1#2#3#4#5#6#7{% - \begin{scope}[shift={(72:1.61803\tikz@lib@fold@length)}] %decagon inside a circle with radius the golden ratio has side length 1 + \scope[shift={(72:1.61803\tikz@lib@fold@length)}] %decagon inside a circle with radius the golden ratio has side length 1 #1 - \end{scope} - \begin{scope} + \endscope + \scope [shift={(36:\tikz@lib@fold@length)}, shift={(72:\tikz@lib@fold@length)}, shift={(108:\tikz@lib@fold@length)}, shift={(144:\tikz@lib@fold@length)}] #2 - \end{scope} - \begin{scope} + \endscope + \scope [xshift=\tikz@lib@fold@length, shift={(36:\tikz@lib@fold@length)}, shift={(72:\tikz@lib@fold@length)}, @@ -164,59 +164,59 @@ shift={(144:\tikz@lib@fold@length)}, rotate=-36] #3 - \end{scope} - \begin{scope} + \endscope + \scope [xshift=\tikz@lib@fold@length, shift={(36:\tikz@lib@fold@length)}, shift={(72:\tikz@lib@fold@length)}, shift={(108:\tikz@lib@fold@length)}, rotate=-72] #4 - \end{scope} - \begin{scope} + \endscope + \scope [xshift=\tikz@lib@fold@length, shift={(36:\tikz@lib@fold@length)}, shift={(72:\tikz@lib@fold@length)}, rotate=-108] #5 - \end{scope} - \begin{scope} + \endscope + \scope [xshift=\tikz@lib@fold@length, shift={(36:\tikz@lib@fold@length)}, rotate=-144] #6 - \end{scope} - \begin{scope} + \endscope + \scope [xshift=\tikz@lib@fold@length, rotate=180] #7 - \end{scope} + \endscope \tikz@lib@fold@decagonbis } \def\tikz@lib@fold@decagonbis#1#2#3#4{% - \begin{scope} + \scope [rotate=144] #1 - \end{scope} - \begin{scope} + \endscope + \scope [shift={(144:\tikz@lib@fold@length)}, rotate=108] #2 - \end{scope} - \begin{scope} + \endscope + \scope [shift={(144:\tikz@lib@fold@length)}, shift={(108:\tikz@lib@fold@length)}, rotate=72] #3 - \end{scope} - \begin{scope} + \endscope + \scope [shift={(144:\tikz@lib@fold@length)}, shift={(108:\tikz@lib@fold@length)}, shift={(72:\tikz@lib@fold@length)}, rotate=36] #4 - \end{scope} + \endscope } \def\tikz@lib@fold@path{\draw[every fold](0,0) -- (\tikz@lib@fold@length,0pt);} @@ -532,12 +532,12 @@ pics/octahedron truncated folding/.style = {code=\tikzfoldingtruncatedoctahedron[];}, pics/dodecahedron folding/.style = {code=\tikzfoldingdodecahedron[];}, pics/dodecahedron' folding/.style = {code=\tikzfoldingalternatedodecahedron[];}, - pics/cuboctahedron folding/.style = {code=\tikzfoldingoctahedron[];}, - pics/cuboctahedron truncated folding/.style = {code=\tikzfoldingtruncatedoctahedron[];}, + pics/cuboctahedron folding/.style = {code=\tikzfoldingcuboctahedron[];}, + pics/cuboctahedron truncated folding/.style = {code=\tikzfoldingtruncatedcuboctahedron[];}, pics/icosahedron folding/.style = {code=\tikzfoldingicosahedron[];}, pics/rhombicuboctahedron folding/.style = {code=\tikzfoldingrhombicuboctahedron[];}, pics/snub cube folding/.style = {code=\tikzfoldingsnubcube[];}, - pics/icosidodecahedron folding/.style = {code=\tikzfoldingicosahedron[];} + pics/icosidodecahedron folding/.style = {code=\tikzfoldingicosidodecahedron[];} } diff --git a/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryintersections.code.tex b/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryintersections.code.tex index e35633fc20d..361d961339b 100644 --- a/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryintersections.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryintersections.code.tex @@ -9,6 +9,9 @@ \usepgflibrary{intersections} +% FIXME : the 'name path global' is not reset properly - and some +% following 'name path' will append to it rather that reset it. + \pgfkeys{% /tikz/name path global/.code={% % reset any "old" variables inheritted from some other path @@ -36,13 +39,6 @@ \ifx\tikz@intersect@namedpaths\pgfutil@empty% \else% \tikz@intersect@namedpaths% - \pgfutil@ifundefined{tikz@intersect@path@name@#1}{}% - {% - \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\tikz@intersect@@temppath% - \expandafter\expandafter\expandafter{\csname tikz@intersect@path@name@#1\endcsname}% - \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\tikz@intersect@temppath% - \expandafter\expandafter\expandafter{\expandafter\tikz@intersect@temppath\tikz@intersect@temppath}% - }% \fi% \tikz@intersect@addto@path@names{#1}{#2}% }% @@ -60,16 +56,20 @@ \let\tikz@finish@orig=\tikz@finish \def\tikz@finish{% - \tikz@finish@orig% - \tikz@intersect@finish% + \tikz@finish@orig% + \tikz@intersect@finish% } \def\tikz@intersect@finish{% - \ifx\tikz@intersect@namedpaths\pgfutil@empty% - \else% - \tikz@intersect@namedpaths% - \let\tikz@intersect@namedpaths=\pgfutil@empty% - \fi% + \ifx\tikz@intersect@namedpaths\pgfutil@empty% + \else% + \tikz@intersect@namedpaths% + % FIXME : it is reasonable to reset this globally as it is global + % in its nature. But the reset instruction should be moved to + % \endscope or something related. Resetting it here breaks the + % manual + \let\tikz@intersect@namedpaths=\pgfutil@empty% + \fi% } \let\tikz@intersect@namedpaths=\pgfutil@empty diff --git a/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarypatterns.meta.code.tex b/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarypatterns.meta.code.tex new file mode 100644 index 00000000000..6f8ec32f888 --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarypatterns.meta.code.tex @@ -0,0 +1,98 @@ +% Copyright 2015 by Mark Wibrow +% +% 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. + +\usepgflibrary{patterns.meta} + +\tikzset{% + pattern color/.code=\edef\tikz@pattern@color{#1}, + pattern/.code={% + \edef\tikz@temp{#1}% + \ifx\tikz@temp\tikz@nonetext% + \tikz@addmode{\tikz@mode@fillfalse}% + \else% + \ifx\tikz@temp\pgfutil@empty% + \else% + \tikz@addoption{\pgfsetfillpattern{#1}{\tikz@pattern@color}}% + \def\tikz@pattern{#1}% + \fi% + \tikz@addmode{\tikz@mode@filltrue}% + \fi% + } +} + +\def\tikz@pattern@color{black} +\def\tikz@pattern{} + +\tikzset{patterns/.cd, + .unknown/.code={% + \let\tikz@pat@key=\pgfkeyscurrentname% + \pgfkeys{/pgf/patterns/\tikz@pat@key/.try={#1}}% + }, + bottom left/.style={/pgf/patterns/bottom left={\tikz@scan@one@point\pgf@pat@process#1}}, + top right/.style={/pgf/patterns/top right={\tikz@scan@one@point\pgf@pat@process#1}}, + bounding box/.style args={#1(#2)#3and#4(#5)#6}{% + /tikz/patterns/bottom left={(#2)}, + /tikz/patterns/top right={#4(#5)}, + }, + tile size/.style={/pgf/patterns/tile size={\tikz@scan@one@point\pgf@pat@process#1}}, + tile transformation/.style={/pgf/patterns/tile transformation={% + \let\tikz@transform=\relax\pgfkeys{/tikz/.cd,#1}}% + }, + infer tile bounding box/.code={ + \def\pgf@pat@codeafterhook{% + \xdef\tikz@pat@installbb{% + \noexpand\pgfkeys{/tikz/patterns/bounding box={% + (\the\pgf@picminx-#1,\the\pgf@picminy-#1) and + (\the\pgf@picmaxx+#1,\the\pgf@picmaxy+#1) + }, + /tikz/patterns/tile size={% + (\the\pgf@picmaxx-\the\pgf@picminx, + \the\pgf@picmaxy-\the\pgf@picminy)}}}% + }% + \let\pgf@pat@declarepost=\tikz@pat@installbb% + }, + infer tile bounding box/.default=0pt, +} + +\def\tikzdeclarepattern#1{% + \begingroup% + \def\pgf@pat@codebeforehook{% + \let\tikz@transform=\relax% + \pgftransformreset% <- Hmm? + \tikz@declarepattern@install% + \ifnum\pgf@pat@type=0\relax% + \let\pgfsetstrokecolor=\tikz@pat@gobbleone% + \let\pgfsetfillcolor=\tikz@pat@gobbleone% + \fi% + \def\tikz@fig{% + \tikzerror{You cannot use nodes inside a pattern}% + }% + \tikzset{pattern/.code={\tikzerror{You cannot nest patterns}}, + pattern color/.style={pattern}}% + }% + \pgfdeclarepattern{/tikz/patterns/.cd, #1}% + \endgroup% + } + +\def\tikz@declarepattern@install{% + \let\tikz@compat@color@set=\tikz@compat@color@set@insidepatttern% + \tikz@installcommands% +} + +\let\tikz@compat@color@set@orig=\tikz@compat@color@set +\def\tikz@compat@color@set@insidepatttern#1{% + \tikz@compat@color@set@orig{#1}% + \pgfsetfillcolor{#1}\pgfsetstrokecolor{#1}% +} + + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: t +%%% End: diff --git a/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryquotes.code.tex b/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryquotes.code.tex index 4369b7e2dc2..cab6be1f07b 100644 --- a/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryquotes.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryquotes.code.tex @@ -7,7 +7,7 @@ % % See the file doc/generic/pgf/licenses/LICENSE for more details. -\ProvidesFileRCS[v\pgfversion] $Header: /cvsroot/pgf/pgf/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryquotes.code.tex,v 1.3 2013/08/28 15:24:27 tantau Exp $ +\ProvidesFileRCS[v\pgfversion] $Header: /cvsroot/pgf/pgf/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryquotes.code.tex,v 1.4 2014/03/21 19:52:38 tantau Exp $ \def\tikz@quote@parser#1{\tikz@quote@@parser#1\pgf@stop} \def\tikz@quote@@parser"#1"{% @@ -63,6 +63,7 @@ pic quotes mean={pic text={#1},pic text options={every pic quotes/.try,#2}}, every edge quotes/.style={auto}, direction shorthands/.code={% + \pgfkeyslet{/tikz/centered/.@cmd}\tikz@label@@centered \pgfkeyslet{/tikz/above/.@cmd}\tikz@label@@above \pgfkeyslet{/tikz/below/.@cmd}\tikz@label@@below \pgfkeyslet{/tikz/left/.@cmd}\tikz@label@@left @@ -74,6 +75,7 @@ } } +\def\tikz@label@@centered#1\pgfeov{\pgfkeysalso{label position=center,pin position=center}} \def\tikz@label@@above#1\pgfeov{\pgfkeysalso{label position=90,pin position=90}} \def\tikz@label@@below#1\pgfeov{\pgfkeysalso{label position=-90,pin position=-90}} \def\tikz@label@@left#1\pgfeov{\pgfkeysalso{label position=180,pin position=180}} diff --git a/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.code.tex b/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.code.tex index f8c1e8792f4..09d9a2fa122 100644 --- a/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.code.tex @@ -7,7 +7,7 @@ % % See the file doc/generic/pgf/licenses/LICENSE for more details. -\ProvidesPackageRCS[v\pgfversion] $Header: /cvsroot/pgf/pgf/generic/pgf/frontendlayer/tikz/tikz.code.tex,v 1.142 2013/12/13 15:11:58 tantau Exp $ +\ProvidesPackageRCS[v\pgfversion] $Header: /cvsroot/pgf/pgf/generic/pgf/frontendlayer/tikz/tikz.code.tex,v 1.151 2015/08/07 10:17:34 cfeuersaenger Exp $ \def\tikzerror#1{\pgfutil@packageerror{tikz}{#1}{}} @@ -375,25 +375,28 @@ \tikzset{rotate around x/.code={% \tikz@xyz@rotate@let% - \tikz@xyz@rotate@xyz@xaxis{0pt}{1pt}{0pt}{#1}% + \pgfmathparse{#1}\let\tikz@xyz@angle=\pgfmathresult% + \tikz@xyz@rotate@xyz@xaxis{0pt}{1pt}{0pt}{\tikz@xyz@angle}% \pgfextract@process\tikz@xyz@rotate@yvec{\pgfpointxyz{\pgf@sys@tonumber{\pgf@x}}{\pgf@sys@tonumber{\pgf@y}}{\pgf@sys@tonumber{\pgf@z}}}% - \tikz@xyz@rotate@xyz@xaxis{0pt}{0pt}{1pt}{#1}% + \tikz@xyz@rotate@xyz@xaxis{0pt}{0pt}{1pt}{\tikz@xyz@angle}% \pgfsetzvec{\pgfpointxyz{\pgf@sys@tonumber{\pgf@x}}{\pgf@sys@tonumber{\pgf@y}}{\pgf@sys@tonumber{\pgf@z}}}% \pgfsetyvec{\tikz@xyz@rotate@yvec}% }, rotate around y/.code={% \tikz@xyz@rotate@let% - \tikz@xyz@rotate@xyz@yaxis{1pt}{0pt}{0pt}{#1}% + \pgfmathparse{#1}\let\tikz@xyz@angle=\pgfmathresult% + \tikz@xyz@rotate@xyz@yaxis{1pt}{0pt}{0pt}{\tikz@xyz@angle}% \pgfextract@process\tikz@xyz@rotate@xvec{\pgfpointxyz{\pgf@sys@tonumber{\pgf@x}}{\pgf@sys@tonumber{\pgf@y}}{\pgf@sys@tonumber{\pgf@z}}}% - \tikz@xyz@rotate@xyz@yaxis{0pt}{0pt}{1pt}{#1}% + \tikz@xyz@rotate@xyz@yaxis{0pt}{0pt}{1pt}{\tikz@xyz@angle}% \pgfsetzvec{\pgfpointxyz{\pgf@sys@tonumber{\pgf@x}}{\pgf@sys@tonumber{\pgf@y}}{\pgf@sys@tonumber{\pgf@z}}}% \pgfsetxvec{\tikz@xyz@rotate@xvec}% }, rotate around z/.code={% \tikz@xyz@rotate@let% - \tikz@xyz@rotate@xyz@zaxis{1pt}{0pt}{0pt}{#1}% + \pgfmathparse{#1}\let\tikz@xyz@angle=\pgfmathresult% + \tikz@xyz@rotate@xyz@zaxis{1pt}{0pt}{0pt}{\tikz@xyz@angle}% \pgfextract@process\tikz@xyz@rotate@xvec{\pgfpointxyz{\pgf@sys@tonumber{\pgf@x}}{\pgf@sys@tonumber{\pgf@y}}{\pgf@sys@tonumber{\pgf@z}}}% - \tikz@xyz@rotate@xyz@zaxis{0pt}{1pt}{0pt}{#1}% + \tikz@xyz@rotate@xyz@zaxis{0pt}{1pt}{0pt}{\tikz@xyz@angle}% \pgfsetyvec{\pgfpointxyz{\pgf@sys@tonumber{\pgf@x}}{\pgf@sys@tonumber{\pgf@y}}{\pgf@sys@tonumber{\pgf@z}}}% \pgfsetxvec{\tikz@xyz@rotate@xvec}% } @@ -641,6 +644,7 @@ \pgfextra{\let\tikz@save@last@node=\tikzlastnode\tikz@node@is@a@labelfalse}% node [every pin, tikz@label@angle = #2, + anchor=@auto, #1, append after command = {% (\tikz@save@last@node) @@ -670,6 +674,7 @@ \pgfextra{\let\tikz@save@last@node=\tikzlastnode\tikz@node@is@a@labelfalse}% node [every pin, tikz@label@angle = #2, + anchor=@auto, #1, append after command = {% (\tikz@save@last@node) @@ -697,6 +702,7 @@ \tikzset{tikz@label@post/.code 2 args={ \edef\tikz@label@angle{\tikz@label@angle}% + \expandafter\pgfkeys@spdef\expandafter\tikz@label@angle\expandafter{\tikz@label@angle}% \csname tikz@label@angle@is@\tikz@label@angle\endcsname \ifx\tikz@label@angle\tikz@on@text% \def\tikz@node@at{\pgfpointanchor{\tikzlastnode}{center}}% @@ -742,7 +748,9 @@ \pgf@yc=\pgf@y% \pgf@x=\pgf@yc% \pgf@y=-\pgf@xc% - \tikz@auto@anchor% + \ifx\tikz@anchor\tikz@auto@text% + \tikz@auto@anchor% + \fi% \fi% \fi% \fi} @@ -797,6 +805,7 @@ \pgfextra{\let\tikz@save@last@fig@name=\tikz@last@fig@name\tikz@node@is@a@labelfalse} node [every label, tikz@label@angle = #2, + anchor=@auto, #1, tikz@label@post = \tikz@label@distance] {\iftikz@handle@active@nodes\expandafter\scantokens\else\expandafter\pgfutil@firstofone\fi{#3}} \pgfextra{\global\let\tikz@last@fig@name=\tikz@save@last@fig@name} @@ -826,6 +835,7 @@ \pgfextra{\let\tikz@save@last@fig@name=\tikz@last@fig@name\tikz@node@is@a@labelfalse} node [every label, tikz@label@angle = #2, + anchor=@auto, #1, tikz@label@post = \tikz@label@distance] {\iftikz@handle@active@nodes\expandafter\scantokens\else\expandafter\pgfutil@firstofone\fi{#3}} \pgfextra{\global\let\tikz@last@fig@name=\tikz@save@last@fig@name} @@ -841,6 +851,7 @@ \expandafter\def\csname tikz@label@angle@is@below right\endcsname{\def\tikz@label@angle{315}} \def\tikz@compute@direction#1{% + \ifx\tikz@anchor\tikz@auto@text% \let\tikz@do@auto@anchor=\relax \pgfmathsetcount{\c@pgf@counta}{#1}% \ifnum\c@pgf@counta<0\relax @@ -868,8 +879,9 @@ \else% \def\tikz@anchor{west}% \fi\fi\fi\fi\fi\fi\fi\fi% + \fi% } - +\def\tikz@auto@text{@auto} % General node options \tikzset{ @@ -898,7 +910,18 @@ \tikzoption{nodes}{\tikzstyle{every node}+=[#1]} -\tikzset{alias/.code={\tikz@fig@mustbenamed\expandafter\def\expandafter\tikz@alias\expandafter{\tikz@alias\pgfnodealias{#1}{\tikz@fig@name}}}} +\tikzset{alias/.code={% + \tikz@fig@mustbenamed + \begingroup + \toks0=\expandafter{\tikz@alias}% + \edef\pgf@temp{\noexpand\pgfnodealias{\tikz@pp@name{#1}}{\noexpand\tikz@fig@name}}% + \toks1=\expandafter{\pgf@temp}% + \xdef\pgf@marshal{% + \noexpand\def\noexpand\tikz@alias{\the\toks0 \the\toks1 }% + }% + \endgroup + \pgf@marshal +}} % deprecated: \def\tikzaddafternodepathoption#1{#1\tikzset{prefix after command={\pgfextra{#1}}}} @@ -933,7 +956,8 @@ \tikzoption{below right}[]% {\def\tikz@anchor{north west}% \tikz@possibly@transform{x}{}{#1}\tikz@possibly@transform{y}{-}{#1}} - +\tikzset{centered/.code=\def\tikz@anchor{center}} + \tikzoption{node distance}{\def\tikz@node@distance{#1}} \def\tikz@node@distance{1cm} @@ -996,7 +1020,12 @@ % Inter-picture options \tikzoption{remember picture}[true]{\csname pgfrememberpicturepositiononpage#1\endcsname} -\tikzoption{overlay}[]{\pgf@relevantforpicturesizefalse} +\tikzset{ + overlay/.is choice, + overlay/true/.code={\pgf@relevantforpicturesizefalse}, + overlay/false/.code={\pgf@relevantforpicturesizetrue}, + overlay/.default=true +} @@ -1577,10 +1606,10 @@ } \def\tikz@compat@color@set#1{% \pgfutil@color{#1}\pgfutil@colorlet{pgffillcolor}{#1}% - \expandafter\expandafter\expandafter\global% - \expandafter\expandafter\expandafter\let\expandafter\csname\expandafter\string\expandafter\color@pgffillcolor\expandafter\endcsname\csname\string\color@pgffillcolor\endcsname% - \expandafter\expandafter\expandafter\global% - \expandafter\expandafter\expandafter\let\expandafter\csname\expandafter\string\expandafter\color@pgfstrokecolor\expandafter\endcsname\csname\string\color@pgffillcolor\endcsname% + \expandafter\let\expandafter\pgf@temp\csname\string\color@pgffillcolor\endcsname + % for arrow tips: + \global\let\pgf@strokecolor@global=\pgf@temp + \global\let\pgf@fillcolor@global=\pgf@temp } \def\tikz@startup@env{% @@ -2214,8 +2243,10 @@ \ifx\tikz@options\pgfutil@empty% \else% \pgfsys@beginscope% + \let\pgfscope@stroke@color=\pgf@strokecolor@global% + \let\pgfscope@fill@color=\pgf@fillcolor@global% \begingroup% - \tikz@options% + \tikz@options% \fi% % % Step 6: Do a fill if shade or a path picture follows. @@ -2323,6 +2354,8 @@ \ifx\tikz@options\pgfutil@empty% \else% \endgroup% + \global\let\pgf@strokecolor@global=\pgfscope@stroke@color% + \global\let\pgf@fillcolor@global=\pgfscope@fill@color% \pgfsys@endscope% \iftikz@mode@clip% \tikzerror{Extra options not allowed for clipping path command.}% @@ -2341,6 +2374,18 @@ \let\tikz@lib@scope@check\pgfutil@empty% this is a hook for the scopes library \def\tikz@path@do@at@end{\tikz@lib@scope@check} +\def\pgf@outer@auto@adjust@hook{% + {% + \tikz@mode@drawfalse% + \tikz@mode% + \expandafter% + }% + \iftikz@mode@draw\else%xxx + \pgfkeyslet{/pgf/outer xsep}\pgf@zero@text + \pgfkeyslet{/pgf/outer ysep}\pgf@zero@text + \fi% +} + % Extra actions \def\tikz@extra@preaction#1{% @@ -3497,17 +3542,17 @@ \def\tikz@do@arc#1#2#3#4{% \let\tikz@tangent\tikz@tangent@lookup% \edef\tikz@timer@start{\noexpand\pgfqpoint{\the\tikz@lastx}{\the\tikz@lasty}}% - \edef\tikz@timer@start@angle{#1}% - \edef\tikz@timer@end@angle{#2}% + \pgfmathsetmacro\tikz@timer@start@angle{#1}% + \pgfmathsetmacro\tikz@timer@end@angle{#2}% \pgfmathparse{#3}% \let\tikz@arc@x=\pgfmathresult% \ifpgfmathunitsdeclared% \pgfmathparse{#4}% \let\tikz@arc@y=\pgfmathresult% \ifpgfmathunitsdeclared% - \tikz@@@arcfinal{\pgfpatharc{#1}{#2}{\tikz@arc@x pt and \tikz@arc@y pt}} - {\pgfpointpolar{#1}{\tikz@arc@x pt and \tikz@arc@y pt}} - {\pgfpointpolar{#2}{\tikz@arc@x pt and \tikz@arc@y pt}}% + \tikz@@@arcfinal{\pgfpatharc{\tikz@timer@start@angle}{\tikz@timer@end@angle}{\tikz@arc@x pt and \tikz@arc@y pt}} + {\pgfpointpolar{\tikz@timer@start@angle}{\tikz@arc@x pt and \tikz@arc@y pt}} + {\pgfpointpolar{\tikz@timer@end@angle}{\tikz@arc@x pt and \tikz@arc@y pt}}% \edef\tikz@timer@zero@axis{\noexpand\pgfqpoint{\tikz@arc@x pt}{0pt}} \edef\tikz@timer@ninety@axis{\noexpand\pgfqpoint{0pt}{\tikz@arc@y pt}} \else% @@ -3519,8 +3564,8 @@ \ifpgfmathunitsdeclared% \tikzerror{You cannot mix dimensions and dimensionless values in an arc}% \else% - \tikz@@@arcfinal{\pgfpatharcaxes{#1}{#2}{\pgfpointxy{\tikz@arc@x}{0}}{\pgfpointxy{0}{\tikz@arc@y}}} - {\pgfpointpolarxy{#1}{\tikz@arc@x and \tikz@arc@y}}{\pgfpointpolarxy{#2}{\tikz@arc@x and \tikz@arc@y}}% + \tikz@@@arcfinal{\pgfpatharcaxes{\tikz@timer@start@angle}{\tikz@timer@end@angle}{\pgfpointxy{\tikz@arc@x}{0}}{\pgfpointxy{0}{\tikz@arc@y}}} + {\pgfpointpolarxy{\tikz@timer@start@angle}{\tikz@arc@x and \tikz@arc@y}}{\pgfpointpolarxy{\tikz@timer@end@angle}{\tikz@arc@x and \tikz@arc@y}}% \pgf@process{\pgfpointxy{\tikz@arc@x}{0}} \edef\tikz@timer@zero@axis{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}} \pgf@process{\pgfpointxy{0}{\tikz@arc@y}} @@ -3912,6 +3957,7 @@ \setbox\tikz@figbox@bg=\box\tikz@tempbox@bg% \global\pgflinewidth=\tikz@save@line@width% \tikz@do@after@path@smuggle% + \tikz@node@is@picfalse \tikz@do@after@node% } \let\tikz@fig@continue@orig=\tikz@fig@continue diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/bindings/BindingToPGF.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/bindings/BindingToPGF.lua index 5a1337a1327..0ad475fbf3e 100644 --- a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/bindings/BindingToPGF.lua +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/bindings/BindingToPGF.lua @@ -7,7 +7,7 @@ -- -- See the file doc/generic/pgf/licenses/LICENSE for more information --- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/bindings/BindingToPGF.lua,v 1.10 2013/12/20 14:44:46 tantau Exp $ +-- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/bindings/BindingToPGF.lua,v 1.11 2015/06/08 21:58:24 tantau Exp $ @@ -75,7 +75,7 @@ local table_in_pgf_syntax function BindingToPGF:resumeGraphDrawingCoroutine(text) tex.print(text) - tex.print("\\directlua{pgf.gd.interface.InterfaceToDisplay.resumeGraphDrawingCoroutine()}") + tex.print("\\pgfgdresumecoroutinetrue") end diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/circular/Tantau2012.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/circular/Tantau2012.lua index 774bdc907be..1966a3066c5 100644 --- a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/circular/Tantau2012.lua +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/circular/Tantau2012.lua @@ -7,12 +7,14 @@ -- -- See the file doc/generic/pgf/licenses/LICENSE for more information --- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/circular/Tantau2012.lua,v 1.7 2013/05/23 20:01:25 tantau Exp $ +-- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/circular/Tantau2012.lua,v 1.9 2014/03/19 09:20:57 tantau Exp $ -- Imports local declare = require("pgf.gd.interface.InterfaceToAlgorithms").declare +local routing = require("pgf.gd.routing") + -- The algorithm class local Tantau2012 = {} @@ -25,7 +27,7 @@ declare { upward_oriented = true }, - documentation_in = "pgf.gd.doc.circular.Tantau2012" + documentation_in = "pgf.gd.circular.doc" } @@ -33,14 +35,17 @@ declare { -- Imports local Coordinate = require "pgf.gd.model.Coordinate" +local Hints = require "pgf.gd.routing.Hints" + +local lib = require "pgf.gd.lib" + -local lib = require "pgf.gd.lib" -- The implementation function Tantau2012:run() - local g = self.digraph + local g = self.ugraph local vertices = g.vertices local n = #vertices @@ -75,6 +80,10 @@ function Tantau2012:run() vertex.pos.x = radius * math.cos(2 * math.pi * (positions[i] / length + 1/4)) vertex.pos.y = -radius * math.sin(2 * math.pi * (positions[i] / length + 1/4)) end + + -- Add routing infos + local necklace = lib.icopy({g.vertices[1]}, lib.icopy(g.vertices)) + Hints.addNecklaceCircleHint(g, necklace, nil, true) end diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/doc/circular/Tantau2012.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/circular/doc.lua index e40a0bbdb1f..d3c267394c4 100644 --- a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/doc/circular/Tantau2012.lua +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/circular/doc.lua @@ -7,7 +7,7 @@ -- -- See the file doc/generic/pgf/licenses/LICENSE for more information --- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/doc/circular/Tantau2012.lua,v 1.1 2013/03/05 23:44:30 tantau Exp $ +-- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/circular/doc.lua,v 1.1 2014/03/19 09:20:57 tantau Exp $ local key = require 'pgf.gd.doc'.key local documentation = require 'pgf.gd.doc'.documentation diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/control/Anchoring.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/control/Anchoring.lua index e4364d695cd..a3f5de83194 100644 --- a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/control/Anchoring.lua +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/control/Anchoring.lua @@ -7,7 +7,7 @@ -- -- See the file doc/generic/pgf/licenses/LICENSE for more information --- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/control/Anchoring.lua,v 1.6 2013/05/23 20:01:25 tantau Exp $ +-- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/control/Anchoring.lua,v 1.7 2014/03/19 09:20:58 tantau Exp $ @@ -68,14 +68,14 @@ local declare = require "pgf.gd.interface.InterfaceToAlgorithms".declare declare { key = "desired at", type = "coordinate", - documentation_in = "pgf.gd.doc.control.Anchoring" + documentation_in = "pgf.gd.control.doc" } --- declare { key = "anchor node", type = "string", - documentation_in = "pgf.gd.doc.control.Anchoring" + documentation_in = "pgf.gd.control.doc" } @@ -84,7 +84,7 @@ declare { key = "anchor at", type = "canvas coordinate", initial = "(0pt,0pt)", - documentation_in = "pgf.gd.doc.control.Anchoring" + documentation_in = "pgf.gd.control.doc" } @@ -92,7 +92,7 @@ declare { declare { key = "anchor here", type = "boolean", - documentation_in = "pgf.gd.doc.control.Anchoring" + documentation_in = "pgf.gd.control.doc" } diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/control/LayoutPipeline.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/control/LayoutPipeline.lua index c32f9d084f6..7a6a910dfa0 100644 --- a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/control/LayoutPipeline.lua +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/control/LayoutPipeline.lua @@ -7,7 +7,7 @@ -- -- See the file doc/generic/pgf/licenses/LICENSE for more information --- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/control/LayoutPipeline.lua,v 1.11 2013/10/09 19:46:59 tantau Exp $ +-- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/control/LayoutPipeline.lua,v 1.13 2014/03/19 09:20:58 tantau Exp $ --- @@ -65,6 +65,33 @@ -- ``ideally'' rotated the graph, set this postcondition. -- \end{itemize} -- +-- +-- In addition to the above-described always-present and automatic +-- transformations, users may also specify additional pre- and +-- posttransformations. This happens when users install additional +-- algorithms in appropriate phases. In detail, the following happens +-- in order: +-- +-- \begin{enumerate} +-- \item If specified, the graph is decomposed into connected +-- components and the following steps are applied to each component +-- individually. +-- \item All algorithms in the phase stack for the phase +-- |preprocessing| are applied to the component. These algorithms are +-- run one after the other in the order they appear in the phase +-- stack. +-- \item If necessary, the spanning tree is now computed and +-- rotational information is gathered. +-- \item The single algorithm in phase |main| is called. +-- \item All algorithms in the phase stack for the phase +-- |edge routing| are run. +-- \item All algorithms in the phase stack for phase |postprocessing| +-- are run. +-- \item Edge syncing, orientation, and anchoring are applied. +-- \end{enumerate} +-- +-- If sublayouts are used, all of the above (except for anchoring) +-- happens for each sublayout. local LayoutPipeline = {} @@ -130,7 +157,7 @@ function LayoutPipeline.run(scope) -- Step 4: Apply regardless transforms Sublayouts.regardless(scope.syntactic_digraph) - + -- Step 5: Cut edges LayoutPipeline.cutEdges(scope.syntactic_digraph) @@ -162,7 +189,7 @@ function LayoutPipeline.runOnLayout(scope, algorithm_class, layout_graph, layout local new_a = layout_copy:connect(a.tail,a.head) new_a.syntactic_edges = a.syntactic_edges end - + -- Step 1: Decompose the graph into connected components, if necessary: local syntactic_components if algorithm_class.preconditions.tree or algorithm_class.preconditions.connected or layout_graph.options.componentwise then @@ -191,6 +218,18 @@ function LayoutPipeline.runOnLayout(scope, algorithm_class, layout_graph, layout -- Step 2.4: Precompute the underlying undirected graph local ugraph = Direct.ugraphFromDigraph(digraph) + + -- Step 2.4a: Run preprocessor + for _,class in ipairs(layout_graph.options.algorithm_phases["preprocessing stack"]) do + class.new{ + digraph = digraph, + ugraph = ugraph, + scope = scope, + layout = layout, + layout_graph = layout_graph, + syntactic_component = syntactic_component, + }:run() + end -- Step 2.5: Create an algorithm object local algorithm = algorithm_class.new{ @@ -228,6 +267,30 @@ function LayoutPipeline.runOnLayout(scope, algorithm_class, layout_graph, layout end end + -- Step 2.9a: Run edge routers + for _,class in ipairs(layout_graph.options.algorithm_phases["edge routing stack"]) do + class.new{ + digraph = digraph, + ugraph = ugraph, + scope = scope, + layout = layout, + layout_graph = layout_graph, + syntactic_component = syntactic_component, + }:run() + end + + -- Step 2.9b: Run postprocessor + for _,class in ipairs(layout_graph.options.algorithm_phases["postprocessing stack"]) do + class.new{ + digraph = digraph, + ugraph = ugraph, + scope = scope, + layout = layout, + layout_graph = layout_graph, + syntactic_component = syntactic_component, + }:run() + end + -- Step 2.10: Sync the graphs digraph:sync() ugraph:sync() @@ -241,6 +304,7 @@ function LayoutPipeline.runOnLayout(scope, algorithm_class, layout_graph, layout -- Step 3: Packing: LayoutPipeline.packComponents(layout_graph, syntactic_components) + end diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/doc/control/Anchoring.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/control/doc.lua index 0a80baf0ca5..ac2b186f5d5 100644 --- a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/doc/control/Anchoring.lua +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/control/doc.lua @@ -7,7 +7,7 @@ -- -- See the file doc/generic/pgf/licenses/LICENSE for more information --- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/doc/control/Anchoring.lua,v 1.1 2013/03/05 23:44:30 tantau Exp $ +-- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/control/doc.lua,v 1.1 2014/03/19 09:20:58 tantau Exp $ local key = require 'pgf.gd.doc'.key local documentation = require 'pgf.gd.doc'.documentation diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/algorithms/FruchtermanReingold.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/algorithms/FruchtermanReingold.lua new file mode 100644 index 00000000000..6c9677aeabb --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/algorithms/FruchtermanReingold.lua @@ -0,0 +1,118 @@ +-- Copyright 2014 by Ida Bruhns +-- +-- 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 information + +local SpringElectricNoCoarsenClass = {} + +-- Imports +local declare = require "pgf.gd.interface.InterfaceToAlgorithms".declare +local ForceController = require "pgf.gd.force.jedi.base.ForceController" +local ForceCanvasDistance = require "pgf.gd.force.jedi.forcetypes.ForceCanvasDistance" +local ForceGraphDistance = require "pgf.gd.force.jedi.forcetypes.ForceGraphDistance" +local Storage = require "pgf.gd.lib.Storage" + +--- +declare { + key = "spring electric no coarsen layout", + algorithm = SpringElectricNoCoarsenClass, + preconditions = { connected = true }, + postconditions = {fixed = true}, + + summary = [[This layout uses the algorithm proposed by Fruchterman and Reingold to draw graphs."]], + + documentation = + [[The Fruchterman-Reingold algorithm is one if the oldest methods + for force-based graph drawing. It is described in: + \begin{itemize} + \item + Thomas M.~J.~ Fruchterman and Edward M.~ Reingold, + \newblock Graph Drawing by Force-directed Placement, + \newblock \emph{Software -- practice and experience,} + 21(1 1), 1129-1164, 1991. + \end{itemize} + Fruchterman and Reingold had to principles in graph drawing: + \begin{enumerate} + \item Vertices connected by an edge should be drawn close toa another and + \item in general, vertices should not be drawn too close to each other. + \end{itemize} + The spring electric no coarsen layout uses spring forces as attractive + forces influecing vertex pairs connected by an edge and electric forces + as repulsive forces between all vertex pairs. The original algorithm + also contained a frame that stopped the vertices from drifting too far + apart, but this concept was not implemented. This algorithm will not be affected + by coarsening. This layout was implemented + by using the Jedi framework. + ]], + + example = + [[ + \tikz + \graph[spring electric no coarsen layout, speed = 0.35, node distance = 2.5cm, nodes={as=,circle, draw, inner sep=3pt,outer sep=0pt}, coarsen = true, maximum step = 1]{ + a -- {b, c, d, e, f, g, h, i, j}, + b -- {c, d, e, f, g, h, i, j}, + c -- {d, e, f, g, h, i, j}, + d -- {e, f, g, h, i, j}, + e -- {f, g, h, i, j}, + f -- {g, h, i, j}, + g -- {h, i, j}, + h -- {i, j}, + i -- j + }; + ]], + + example = + [[ + \graph[spring electric no coarsen layout, speed = 0.25, node distance = 0.25cm, horizontal = c to l, nodes={as=,circle, draw, inner sep=3pt,outer sep=0pt}, coarsen = false, maximum step = 1]{ + a -> b -> c -> {d1 -> e -> f -> g -> h -> i -> {j1 -> e, j2 -> l}, d2 -> l -> m}, m -> a + }; + ]] +} + + + + +-- Implementation starts here + +--define a local time function +local time_fun_1 +function time_fun_1 (t_total, t_now) + if t_now/t_total <= 0.5 then + return 0.5 + else + return 2 + end +end + +-- define storage table to add attributes if wanted +local fw_attributes = Storage.newTableStorage() + +function SpringElectricNoCoarsenClass:run() + -- add options to storage table + fw_attributes.options = self.ugraph.options + + --Generate new force class + local spring_electric_no_coarsen = ForceController.new(self.ugraph) + + spring_electric_no_coarsen:addForce{ + force_type = ForceCanvasDistance, + fun_u = function (data) return data.k*data.k/(data.d) end, + time_fun = time_fun_1, + epoch = {"after expand"} + } + spring_electric_no_coarsen:addForce{ + force_type = ForceGraphDistance, + fun_u = function (data) return -data.d*data.d/(data.k) end, + n = 1, + epoch = {"after expand"} + } + + -- run algorithm + spring_electric_no_coarsen:run() +end + +return SpringElectricNoCoarsenClass
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/algorithms/HuSpringElectricalFW.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/algorithms/HuSpringElectricalFW.lua new file mode 100644 index 00000000000..08ccad1308f --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/algorithms/HuSpringElectricalFW.lua @@ -0,0 +1,93 @@ +-- Copyright 2014 by Ida Bruhns +-- +-- 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 information + +local HuClass = {} + +-- Imports +local declare = require "pgf.gd.interface.InterfaceToAlgorithms".declare +local ForceController = require "pgf.gd.force.jedi.base.ForceController" +local ForceCanvasDistance = require "pgf.gd.force.jedi.forcetypes.ForceCanvasDistance" +local ForceGraphDistance = require "pgf.gd.force.jedi.forcetypes.ForceGraphDistance" + +--- +declare { + key = "jedi spring electric layout", + algorithm = HuClass, + documentation_in = "documentation_hu_layout", + preconditions = { connected = true }, + postconditions = {fixed = true}, + + summary = "This layout uses the spring electric algorithm proposed by Hu to draw graphs.", + + documentation = + [[The spring electric algorithm by Hu uses two kinds of forces and coarsening. + It is described in: + \begin{itemize} + \item + Yifan Hu, + \newblock Efficient, high quality force-directed graph drawing, + \newblock \emph{The Mathematica Journal,} + 10(1), 37-71, 2006. + \end{itemize} + This algorithm uses spring forces as attractive forces between vertices + connected by an edge and electric forces as repulsive forces between + all vertex pairs. Hu introduces coarsening, a procedure which repeatedly + merges vertices in order to obtain a smaller version of the graph, to + overcome local minima. He also uses the Barnes-Hut algorithm to enhance + the runtime of his algorithms. This algorithm is not used in this + implementation. This layout was implemented by using the Jedi framework. + ]], + + example = + [[ + \tikz + \graph[spring electric fw layout, speed = 0.35, node distance = 5cm, nodes={as=,circle, draw, inner sep=3pt,outer sep=0pt}, maximum displacement per step = 10]{ + a -- {b, c, d, e}, + b -- {c, d, e}, + c -- {d, e}, + d --e + }; + ]], + + example = + [[ + \tikz + \graph[spring electric fw layout, speed = 0.35, node distance = 1cm, horizontal = c to l, nodes={as=,circle, draw, inner sep=3pt,outer sep=0pt}, maximum displacement per step = 10]{ + a -> b -> c -> {d1 -> e -> f -> g -> h -> i -> {j1 -> e, j2 -> l}, d2 -> l -> m}, m -> a + }; + ]] +} + + + + +-- Implementation starts here: + +function HuClass:run() + -- Generate new force class + local hu = ForceController.new(self.ugraph) + + -- add all required forces + hu:addForce{ + force_type = ForceCanvasDistance, + fun_u = function (data) return (data.k*data.k)/data.d end, + epoch = {"during expand", "after expand"} + } + hu:addForce{ + force_type = ForceGraphDistance, + fun_u = function (data) return -(data.d*data.d)/data.k end, + n = 1, + epoch = {"during expand", "after expand"} + } + + -- run algorithm + hu:run() +end + +return HuClass
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/algorithms/SimpleSpring.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/algorithms/SimpleSpring.lua new file mode 100644 index 00000000000..20a1be5de0e --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/algorithms/SimpleSpring.lua @@ -0,0 +1,75 @@ +-- Copyright 2014 by Ida Bruhns +-- +-- 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 information + +local SimpleSpringClass = {} + +-- Imports +local declare = require "pgf.gd.interface.InterfaceToAlgorithms".declare +local ForceController = require 'pgf.gd.force.jedi.base.ForceController' +local ForceGraphDistance = require "pgf.gd.force.jedi.forcetypes.ForceGraphDistance" + +--- +declare { + key = "trivial spring layout", + algorithm = SimpleSpringClass, + documentation_in = "pgf.gd.doc.jedi.algorithms.SimpleSpringLayout", + preconditions = { connected = true }, + postconditions = {fixed = true}, + + summary = "This layout uses only spring forces to draw graphs.", + + documentation = + [[The simple spring algorithm only uses one force kind: A spring force + that serves as both attracitve and repuslive force. The edges are modeled as + springs and act according to Hoke's law: They have an ideal length and will + expand if they are contracted below this length, pushing the adjacent + vertices away from each other, and contract if it is stretched, pulling the + adjacent vertices towards each other. This ideal length is given by the + parameter |node distance|. There is no force repelling vertices that are not + connected to each other, which can lead to vertices being placed at the same + point. It is not a very powerfull layout and will probably fail with large + graphs, especially if they have few edges. It can however be used to + demonstrate the effect of spring forces. This layout was implemented by using + the Jedi framework. + ]], + + example = + [[ + \tikz + \graph[simple spring layout, node distance = 3cm, speed = 2, nodes={as=,circle, draw, inner sep=3pt,outer sep=0pt}, coarsen = true, maximum step = 1]{ + a -- {b, c, d, e}, + b -- {c, d, e}, + c -- {d, e}, + d --e + }; + ]] +} + + + + +-- Implementation starts here: + +function SimpleSpringClass:run() + --Generate new force class + simple_spring = ForceController.new(self.ugraph) + + --add all required forces + simple_spring:addForce{ + force_type = ForceGraphDistance, + fun_u = function (data) return data.k*(data.k-data.d) end, + n = 1, + epoch = {"after expand", "during expand"} + } + + -- run algorithm + simple_spring:run() +end + +return SimpleSpringClass
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/algorithms/SocialGravityCloseness.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/algorithms/SocialGravityCloseness.lua new file mode 100644 index 00000000000..12e6c02e4bf --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/algorithms/SocialGravityCloseness.lua @@ -0,0 +1,128 @@ +-- Copyright 2014 by Ida Bruhns +-- +-- 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 information + +local SocialClass = {} + +--Imports +local declare = require "pgf.gd.interface.InterfaceToAlgorithms".declare +local ForceController = require 'pgf.gd.force.jedi.base.ForceController' +local ForceCanvasDistance = require "pgf.gd.force.jedi.forcetypes.ForceCanvasDistance" +local ForceCanvasPosition = require "pgf.gd.force.jedi.forcetypes.ForceCanvasPosition" +local ForceGraphDistance = require "pgf.gd.force.jedi.forcetypes.ForceGraphDistance" +local PathLengthsFW = require "pgf.gd.force.jedi.base.PathLengthsFW" +local Storage = require "pgf.gd.lib.Storage" + +--- +declare { + key = "social closeness layout", + algorithm = SocialClass, + postconditions = {fixed = true}, + + summary = [[This layout uses the social gravity algorithm proposed by Bannister + with closeness mass to draw graphs.]], + + documentation = + [[Bannister et all described a social gravity algorithm that can be + implemented with different kinds of gravity. + It is described in: + \begin{itemize} + \item + Michael J.~ Bannister and David Eppstein and Michael T~. Goodrich and + Lowell Trott, + \newblock Force-Directed Graph Drawing Using Social Gravity and Scaling, + \newblock \emph{CoRR,} + abs/1209.0748, 2012. + \end{itemize} + This implementation uses the closeness mass to determine the gravity of each + vertex. There are three forces in this algorithm: A spring force as + attractive force between vertices connected by an edge, an electric force as + repulsive force between all vertex pairs, and a gravitational force pulling + all vertices closer to their midpoint. The gravitational force depends on + the social mass of a vertex, which can be determined in different ways. This + algorithm uses the closeness mass. The closeness of a vertex $u$ is the + reciprocal of the sum of the shortest path from $u$ to every other vertex + $v$. The gravitational force leads to more "important" vertices ending up + closer to the middle of the drawing, since the social mass of a vertex is + proportinal to its importance. The social layouts work especially well on + unconnected graphs like forests. This layout was implemented by using the + Jedi framework. + ]], + + example = + [[ + \tikz + \graph[social closeness layout, speed = 0.9, gravity = 0.2, node distance = 0.65cm, nodes={as=,circle, draw, inner sep=3pt,outer sep=0pt}, find equilibrium = true, maximum step = 5]{ + a -- a1 -- a2 -- a, + b -- b1 -- b2 -- b, + c -- c1 -- c2 -- c, + d -- d1 -- d2 -- d, + e -- e1 -- e2 -- e, + f -- f1 -- f2 -- f, + g -- g1 -- g2 -- g, + h -- h1 -- h2 -- h, + i -- i1 -- i2 -- i, + j -- j1 -- j2 -- j, + a -- b -- c -- d -- e -- f -- g -- h -- i -- j -- a + }; + ]], + + example = + [[ + \tikz + \graph[social closeness layout, speed = 0.35, node distance = 0.7cm, maximum step = 5, nodes={as=,circle, draw, inner sep=3pt,outer sep=0pt}, radius = 1cm, gravity = 2]{ + a -- {a1 -- a2, a3}, + b -- {b1, b2 -- b3 -- b4 --{b5, b6}}, + c -- {c1--c2}, + d -- {d1, d2, d3 -- {d4, d5}, d6 --{d7, d8}} + }; + ]] +} + +local fw_attributes = Storage.newTableStorage() + +function SocialClass:run() + local dist = PathLengthsFW:breadthFirstSearch(self.ugraph) + local tmp + for vertex, n in pairs(dist) do + tmp = fw_attributes[vertex] + local sum = 0 + for i, w in pairs(n) do + sum = sum + w + end + sum = sum / # self.ugraph.vertices + tmp.mass = 1/sum + end + + fw_attributes.options = self.ugraph.options + + --Generate new force class + social_gravity = ForceController.new(self.ugraph, fw_attributes) + + --add all required forces + social_gravity:addForce{ + force_type = ForceCanvasDistance, + fun_u = function (data) return data.k/(data.d*data.d) end, + epoch = {"after expand", "during expand"} + } + social_gravity:addForce{ + force_type = ForceCanvasPosition, + fun_u = function (data) return data.attributes[data.u].mass*data.attributes.options.gravity end, + epoch = {"after expand", "during expand"} + } + social_gravity:addForce{ + force_type = ForceGraphDistance, + fun_u = function (data) return -data.d/(data.k*data.k) end, + n = 1, + epoch = {"after expand", "during expand"} + } + + social_gravity:run() +end + +return SocialClass
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/algorithms/SocialGravityDegree.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/algorithms/SocialGravityDegree.lua new file mode 100644 index 00000000000..8e94a561871 --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/algorithms/SocialGravityDegree.lua @@ -0,0 +1,180 @@ +-- Copyright 2014 by Ida Bruhns +-- +-- 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 information + + +local declare = require "pgf.gd.interface.InterfaceToAlgorithms".declare +local ForceController = require 'pgf.gd.force.jedi.base.ForceController' +local ForceCanvasDistance = require "pgf.gd.force.jedi.forcetypes.ForceCanvasDistance" +local ForceCanvasPosition = require "pgf.gd.force.jedi.forcetypes.ForceCanvasPosition" +local ForceGraphDistance = require "pgf.gd.force.jedi.forcetypes.ForceGraphDistance" +local Storage = require "pgf.gd.lib.Storage" + +local SocialClass = {} + +--- +declare { + key = "social degree layout", + algorithm = SocialClass, + postconditions = {fixed = true}, + + summary = [[This layout uses the social gravity algorithm proposed by Bannister + with closeness mass to draw graphs.]], + + documentation = + [[Bannister et all described a social gravity algorithm that can be + implemented with different kinds of gravity. + It is described in: + \begin{itemize} + \item + Michael J.~ Bannister and David Eppstein and Michael T~. Goodrich and + Lowell Trott, + \newblock Force-Directed Graph Drawing Using Social Gravity and Scaling, + \newblock \emph{CoRR,} + abs/1209.0748, 2012. + \end{itemize} + This implementation uses the degree mass to determine the gravity of each + vertex. There are three forces in this algorithm: A spring force as + attractive force between vertices connected by an edge, an electric force as + repulsive force between all vertex pairs, and a gravitational force pulling + all vertices closer to their midpoint. The gravitational force depends on + the social mass of a vertex, which can be determined in different ways. This + algorithm uses the degree of each vertex as its mass. The gravitational + force leads to more "important" vertices ending up closer to the middle of + the drawing, since the social mass of a vertex is proportinal to its + importance. The social layouts work especially well on unconnected graphs + like forests. This layout was implemented by using the Jedi framework. + ]], + + example = + [[ + \graph[social degree layout, speed = 0.9, gravity = 0.2, node distance = 0.65cm, nodes={as=,circle, draw, inner sep=3pt,outer sep=0pt}, find equilibrium = true, maximum step = 5]{ + a -- a1 -- a2 -- a, + b -- b1 -- b2 -- b, + c -- c1 -- c2 -- c, + d -- d1 -- d2 -- d, + e -- e1 -- e2 -- e, + f -- f1 -- f2 -- f, + g -- g1 -- g2 -- g, + h -- h1 -- h2 -- h, + i -- i1 -- i2 -- i, + j -- j1 -- j2 -- j, + a -- b -- c -- d -- e -- f -- g -- h -- i -- j -- a + }; + ]], + + example = + [[ + \tikz + \graph[social degree layout, speed = 0.35, node distance = 0.7cm, maximum step = 15, nodes={as=,circle, draw, inner sep=3pt,outer sep=0pt}, radius = 1cm, gravity = 0.2]{ + a -- {a1 -- a2, a3}, + b -- {b1, b2 -- b3 -- b4 --{b5, b6}}, + c -- {c1--c2}, + d -- {d1, d2, d3 -- {d4, d5}, d6 --{d7, d8}} + }; + ]] +} + +--- +declare { + key = "gravity", + type = "number", + initial = 0.2, + + summary = "The gravity key describes the magnitude of the gravitational force.", + + documentation = + [[ + This parameter currently only affects the \lstinline{social degree layout} + and the \lstinline{social closeness layout}. The gravity key determines the + strength used to pull the vertices to the center of the canvas. + ]], + + example = + [[ + \graph[social degree layout, iterations = 100, maximum time = 100, maximum step = 10]{ + a1[weight = 2] -- {a2, a3, a4, a5}, + b1 -- {b2 -- {b3, b4}, b5} + }; + ]], + + example = + [[ + \graph[social degree layout, iterations = 100, maximum time = 100, gravity = 0.5, maximum step = 10]{ + a1 -- {a2 [mass = 2], a3, a4, a5}, + b1 -- {b2 -- {b3, b4}, b5} + }; + ]] +} + + + + +-- Implementation starts here: + +-- define time functions +local time_fun_1, time_fun_2, time_fun_3 + +function time_fun_1 (t_total, t_now) + if t_now > 3*t_total/4 then + return t_now/t_total + end + return 0 +end + +function time_fun_3 (t_total, t_now) + if t_now >= t_total/2 then + return 2 + else + return 1 + end +end + +-- define table to store variables if needed +local fw_attributes = Storage.newTableStorage() + +function SocialClass:run() + --initialize masses + local tmp + for _, vertex in ipairs(self.ugraph.vertices) do + tmp = fw_attributes[vertex] + tmp.social_mass = #self.ugraph:incoming(vertex) + end + + -- add options to storage table + fw_attributes.options = self.ugraph.options + + -- generate new force class + local social_gravity = ForceController.new(self.ugraph, fw_attributes) + + -- add all required forces + social_gravity:addForce{ + force_type = ForceCanvasDistance, + fun_u = function (data) return 4*data.k/(data.d*data.d) end, + time_fun = time_fun_2, + epoch = {"after expand", "during expand"} + } + social_gravity:addForce{ + force_type = ForceCanvasPosition, + fun_u = function (data) return data.attributes[data.u].social_mass*data.attributes.options.gravity end, + time_fun = time_fun_1, + epoch = {"after expand", "during expand"} + } + social_gravity:addForce{ + force_type = ForceGraphDistance, + fun_u = function (data) return -data.d/(data.k*data.k) end, + n = 1, + time_fun = time_fun_3, + epoch = {"after expand", "during expand"} + } + + -- run algorithm + social_gravity:run() +end + +return SocialClass
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/base/CoarseGraphFW.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/base/CoarseGraphFW.lua new file mode 100644 index 00000000000..f33d44e6ae1 --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/base/CoarseGraphFW.lua @@ -0,0 +1,264 @@ +-- Copyright 2014 by Ida Bruhns +-- +-- 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 information + + +--- A class for creating and handling "coarse" versions of a graph. Such versions contain +-- less nodes and edges than the original graph while retaining the overall +-- structure. This class offers functions to create coarse graphs and to expand them +-- to regain their original size. + +-- Imports +local Digraph = require "pgf.gd.model.Digraph" +local Vertex = require "pgf.gd.model.Vertex" +local Arc = require "pgf.gd.model.Arc" + +local lib = require "pgf.gd.lib" + +local CoarseGraph = Digraph.new() +CoarseGraph.__index = CoarseGraph + +--- Creates a new coarse graph derived from an existing graph. +-- +-- Generates a coarse graph for the input |Digraph|. +-- +-- Coarsening describes the process of reducing the amount of vertices in a graph +-- by merging vertices into pseudo-vertices. There are different strategies, +-- to decide which vertices should be merged, like merging vertices that belong to edges in a +-- maximal independent edge set or by creating pseudo-verties based on a maximal +-- independent node set. Those strategies are called +-- schemes. +-- +-- Coarsening is not performed automatically. The function |CoarseGraph:coarsen| +-- can be used to further coarsen the graph, or the function |CoarseGraph:uncoarsen| +-- can be used to restore the previous state. +-- +-- Note, however, that the input \meta{graph} is always modified in-place, so +-- if the original version of \meta{graph} is needed in parallel to its +-- coarse representations, a deep copy of \meta{grpah} needs to be passed over +-- to |CoarseGraph.new|. +-- +-- @param graph An existing graph that needs to be coarsened. +-- @param fw_attributes The user defined attributes, possibly attached to vertices. + +function CoarseGraph.new(ugraph, fw_attributes) + local coarse_graph = { + ugraph = ugraph, + level = 0, + scheme = CoarseGraph.coarsen_independent_edges, + ratio = 0, + fw_attributes = fw_attributes, + collapsed_vertices = {} + } + setmetatable(coarse_graph, CoarseGraph) + return coarse_graph +end + +-- locals for performance +local find_maximal_matching, arc_function + +-- This function performs one coarsening step: It finds all independent vertex +-- set according to |scheme|, coarsens them and adds the newly created +-- vertices to the collapsed_vertices table, associating them with the current +-- level. +function CoarseGraph:coarsen() + -- update the level + self.level = self.level + 1 + + local vertices = self.ugraph.vertices + local old_graph_size = #vertices + local c = {} + local fw_attributes = self.fw_attributes + local ugraph = self.ugraph + + if self.scheme == CoarseGraph.coarsen_independent_edges then + local matching = find_matching(ugraph) + local collapse_vertex + + for _,arc in ipairs(matching) do + -- get the two nodes of the edge that we are about to collapse + local a_h = arc.head + local a_t = arc.tail + local collapse_vertices = {a_h, a_t} + collapse_vertex = Vertex.new {weight = 0, mass = 0} + + ugraph:collapse(collapse_vertices, + collapse_vertex, + function (a,b) + a.weight = a.weight + b.weight + a.mass = a.mass + b.mass + if fw_attributes then + for key,value in pairs(fw_attributes[b]) do + if fw_attributes.functions[key] then + fw_attributes.functions[key](a,b) + elseif type(value) == "number" then + local tmp = fw_attributes[a] + if not tmp[key] then + tmp[key] = 0 + end + tmp[key] = tmp[key] + value + end + end + end + end, + function (a,b) + if a.weight == nil then + a.weight = b.weight + else + a.weight = a.weight + b.weight + end + end) + + local c_v_p = collapse_vertex.pos + local a_h_p = a_h.pos + local a_t_p = a_t.pos + c_v_p.x = (a_h_p.x + a_t_p.x)/2 + c_v_p.y = (a_h_p.y + a_t_p.y)/2 + + c[#c+1] = collapse_vertex + ugraph:remove{a_h, a_t} + end + + -- Enter all collapsed vertices into a table to uncoarsen one level at a time + self.collapsed_vertices[self.level] = c + else + assert(false, 'schemes other than CoarseGraph.coarsen_independent_edges are not implemented yet') + end + -- calculate the number of nodes ratio compared to the previous graph + self.ratio = #vertices / old_graph_size +end + +-- This function expands all vertices assoicated with the current level, then +-- updates the level. +function CoarseGraph:uncoarsen() + local a = self.collapsed_vertices[self.level] + local ugraph = self.ugraph + local random = math.random + local randomseed = math.randomseed + + for j=#a,1,-1 do + randomseed(42) + local to_expand = a[j] + + ugraph:expand(to_expand, function(a,b) + b.pos.x = a.pos.x + random()*10 + b.pos.y = a.pos.y + random()*10 + end) + ugraph:remove{to_expand} + ugraph:sync() + end + + self.level = self.level - 1 +end + +-- Getters +function CoarseGraph:getSize() + return #self.ugraph.vertices +end + + +function CoarseGraph:getRatio() + return self.ratio +end + + +function CoarseGraph:getLevel() + return self.level +end + + +function CoarseGraph:getGraph() + return self.ugraph +end + +-- Private helper function to determine whether the second vertex in the +-- current arc has been matched already +-- +-- @param arc The arc in question +-- @param vertex One of the arc's endpoints, either head or tail +-- @param matched_vertices The table holding all matched vertices +-- +-- @return The arc if the other endpoint has not been matched yet +function arc_function (arc, vertex, matched_vertices) + local x + if arc.head ~= vertex then + x = arc.head + else + x = arc.tail + end + if not matched_vertices[x] then + return arc + end +end + +-- The function finding a maximum matching of independent arcs. +-- +-- @param ugraph The current graph +-- +-- @return A table of arcs wich are in the matching +function find_matching(ugraph) + local matching = {} + local matched_vertices = {} + local unmatched_vertices = {} + local vertices = ugraph.vertices + + -- iterate over nodes in random order + for _,j in ipairs(lib.random_permutation(#vertices)) do + local vertex = vertices[j] + -- ignore nodes that have already been matched + if not matched_vertices[vertex] then + local arcs = {} + local all_arcs = {} + for _,v in pairs(ugraph:incoming(vertex)) do all_arcs[#all_arcs+1] = v end + for _,v in pairs(ugraph:outgoing(vertex)) do all_arcs[#all_arcs+1] = v end + -- mark the node as matched + matched_vertices[vertex] = true + + for _, a in ipairs(all_arcs) do + arcs[#arcs +1] = arc_function(a, vertex, matched_vertices) + end + + if #arcs > 0 then + -- sort edges by the weights of the adjacent vertices + table.sort(arcs, function (a, b) + local x, y + if a.head == vertex then + x = a.tail + else + x = a.head + end + if b.head == vertex then + y = b.tail + else + y = b.head + end + return x.weight < y.weight + end) + + -- match the node against the neighbour with minimum weight + matched_vertices[arcs[1].head] = true + matched_vertices[arcs[1].tail] = true + table.insert(matching, arcs[1]) + end + end + end + + -- generate a list of nodes that were not matched at all + for _,j in ipairs(lib.random_permutation(#vertices)) do + local vertex = vertices[j] + if not matched_vertices[vertex] then + table.insert(unmatched_vertices, vertex) + end + end + return matching +end + + +-- done + +return CoarseGraph
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/base/ForceController.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/base/ForceController.lua new file mode 100644 index 00000000000..1762fcf07eb --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/base/ForceController.lua @@ -0,0 +1,488 @@ +-- Copyright 2014 by Ida Bruhns +-- +-- 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 information + + +--- This class is the most basic class for the Jedi framework. It manages the +-- forces, epochs, options and streamlines the graph drawing process. +-- In detail, the force template will do the following: +-- \begin{itemize} +-- \item Hold the table with all epochs currently defined, and provide +-- a function to add new ones +-- \item Hold the table associating forces with the epochs, and provide a +-- function to add new ones +-- \item Define all the non-algorithm-specific options provided by Jedi +-- \item Assert user options to catch exceptions +-- \item Save user options and library functions to local variables to enchance +-- runtime. +-- \item Add any forces that are indicated by set options +-- \item Find and call the initial positioning algorithm requested +-- \item Determine if coarsening is enabled, and manage coarsening process if so +-- \item Call the proprocesing function of each force to obtain a vertex list the +-- force will be applied to +-- \item Calculate the forces affecting each vertex. +-- \item Move the vertices, check for equilibria/used up iterations, update +-- virtual time +-- \end{itemize} + +local ForceController = {} +ForceController.__index = ForceController + +-- Imports +local declare = require "pgf.gd.interface.InterfaceToAlgorithms".declare +local Coordinate = require "pgf.gd.model.Coordinate" +local CoarseGraph = require 'pgf.gd.force.jedi.base.CoarseGraphFW' +local PriorityQueue = require "pgf.gd.lib.PriorityQueue" +local ForcePullToPoint = require "pgf.gd.force.jedi.forcetypes.ForcePullToPoint" +local ForcePullToGrid = require "pgf.gd.force.jedi.forcetypes.ForcePullToGrid" + +local epochs = { + [1] = "preprocessing", + [2] = "initial layout", + [3] = "start coarsening process", + [4] = "before coarsen", + [5] = "start coarsen", + [6] = "during coarsen", + [7] = "end coarsen", + [8] = "before expand", + [9] = "start expand", + [10] = "during expand", + [11] = "end expand", + [12] = "end coarsening process", + [13] = "after expand", + [14] = "postprocessing" +} + +-- Automatic parameter generation for epoch-variables +for _,e in ipairs(epochs) do + --- + declare { + key = "iterations " .. e, + type = "number" + } + + --- + declare { + key = "maximum displacement per step " .. e, + type = "number" + } + + --- + declare { + key = "global speed factor " .. e, + type = "length" + } + + --- + declare { + key = "maximum time " .. e, + type = "number" + } + + --- + declare { + key = "find equilibrium ".. e, + type = "boolean" + } + + --- + declare { + key = "equilibrium threshold ".. e, + type = "number" + } +end + +-- Implementation starts here + +--- Function allowing user to add an at the specified position +-- +-- @params epoch A string that names the epoch +-- @params position The position in the epoch array at which the epoch should be inserted + +function ForceController:addEpoch(epoch, position) + table.insert(epochs, position, epoch) +end + +--- Function allowing the user to find an epoch's position in the epoch table +-- +-- @params epoch The epoch who's position we are trying to find +-- +-- @return An integer value matching the epch's index, or $-1$ if epoch was not found + +function ForceController:findEpoch(epoch) + for j, e in ipairs(epochs) do + if e == epoch then + return j + end + end + return -1 +end + + +-- locals for performance +local net_forces = {} +local sqrt = math.sqrt +local abs = math.abs +local sum_up, options, move_vertices, get_net_force, preprocessing, epoch_forces + +--- Creating a new force algorithm +-- @params ugraph The ugraph object the graph drawing algorithm will run on +-- @params fw_attributes The storage object holding the additional attributes defined by +-- the engineer +-- +-- @returns A new instance of force template +function ForceController.new(ugraph, fw_attributes) + return setmetatable( + {epoch_forces = {}, + ugraph = ugraph, + fw_attributes = fw_attributes, + pull_to_point = false, + }, ForceController) +end + +--- Running the force algorithm + +function ForceController:run() + -- locals for performance + local ugraph = self.ugraph + local coarse_graph = CoarseGraph.new(ugraph, self.fw_attributes) + local vertices_initalized = false + options = ugraph.options + epoch_forces = self.epoch_forces + local minimum_graph_size = options["minimum coarsening size"] + local vertices = ugraph.vertices + local arcs = ugraph.arcs + local downsize_ratio = options["downsize ratio"] + local natural_spring_length = options["node distance"] + local snap_to_grid = options["snap to grid"] + local coarsen = options["coarsen"] + + -- Assert user input + assert(minimum_graph_size >= 2, 'the minimum coarsening size of coarse graphs (value: ' .. minimum_graph_size .. ') needs to be greater than or equal to 2') + assert(downsize_ratio >= 0 and downsize_ratio <=1, 'the downsize ratio of the coarse graphs (value: ' .. downsize_ratio .. ') needs to be greater than or equal to 0 and smaller than or equal to 1') + assert(natural_spring_length >= 0, 'the node distance (value: ' .. natural_spring_length .. ') needs to be greater than or equal to 0') + + -- initialize vertex and arc weights + for _,vertex in ipairs(vertices) do + vertex.weight = vertex.options["coarsening weight"] + vertex.mass = vertex.options.mass + end + + for _,arc in ipairs(arcs) do + arc.weight = 1 + end + + -- Initialize epoch_forces table entries as empty tables + for _, e in ipairs(epochs) do + if not self.epoch_forces[e] then + self.epoch_forces[e] = {} + end + end + + -- Find inital positioning algorithm + local initial_positioning_class = options.algorithm_phases['initial positioning force framework'] -- initial_types[self.initial_layout] + + -- If snap to grid option is set and no force was added yet, add an extra + -- force to post-processing + if snap_to_grid then + self:addForce{ + force_type = ForcePullToGrid, + cap = 1, + time_fun = function() return 40 end, + epoch = {"postprocessing"} + } + options["iterations postprocessing"] = options["iterations postprocessing"] or 200 + options["maximum time postprocessing"] = options["maximum time postprocessing"] or 200 + options["find equilibrium postprocessing"] = options["find equilibrium postprocessing"] or true + options["equilibrium threshold postprocessing"] = options["equilibrium threshold postprocessing"] or 1 + options["maximum displacement per step postprocessing"] = options["maximum displacement per step postprocessing"] or 1 + options["global speed factor postprocessing"] = options["global speed factor postprocessing"] or 1 + end + + -- Find marker epochs + local start_coarsening = self:findEpoch("start coarsening process") + local end_coarsening = self:findEpoch("end coarsening process") + local start_coarsen = self:findEpoch("start coarsen") + local end_coarsen = self:findEpoch("end coarsen") + local start_expand = self:findEpoch("start expand") + local end_expand = self:findEpoch("end expand") + + + -- iterate over epoch table + local i = 1 + while i <= #epochs do + local e = epochs[i] + + local iterations = options["iterations "..e] or options["iterations"] + -- assert input + assert(iterations >= 0, 'iterations (value: ' .. iterations .. ') needs to be greater than 0') + + -- Check for desired vertices and collect them in a table if any are found + local desired = false + local desired_vertices = {} + -- initialize node weights + for _,vertex in ipairs(vertices) do + if vertex.options then + if vertex.options["desired at"] then + desired = true + desired_vertices[vertex] = vertex.options["desired at"] + end + end + end + + -- Add pull to point force if desired vertices were found and engineer did not add + -- this force + if desired and not self.pull_to_point then + self:addForce{ + force_type = ForcePullToPoint, + time_fun = function(t_now, t_max) return 5 end + } + end + + -- initialize the coarse graph data structure. + if coarsen then + -- vertices = coarse_graph.ugraph.vertices + -- arcs = coarse_graph.ugraph.arcs + if i >= start_coarsening and i < end_coarsening then + -- coarsen the graph repeatedly until only minimum_graph_size nodes + -- are left or until the size of the coarse graph was not reduced by + -- at least the downsize ratio configured by the user + if i >= start_coarsen and i < start_expand then + if coarse_graph:getSize() > minimum_graph_size and coarse_graph:getRatio() <= (1 - downsize_ratio) then + if i == start_coarsen then + coarse_graph:coarsen() + elseif i < end_coarsen then + preprocessing(coarse_graph.ugraph.vertices, coarse_graph.ugraph.arcs, e, coarse_graph.ugraph) + move_vertices(coarse_graph.ugraph.vertices, e) + else + i = start_coarsen - 1 + end + end + end + + -- between coarsening and expanding + if (i > end_coarsen) and (i < start_expand) then + -- use the natural spring length as the initial natural spring length + local spring_length = natural_spring_length + + if not vertices_initalized then + initial_positioning_class.new { vertices = coarse_graph.ugraph.vertices, + options = options, + desired_vertices = desired_vertices + }:run() + vertices_initalized = true + end + + preprocessing(coarse_graph.ugraph.vertices, coarse_graph.ugraph.arcs, e, coarse_graph.ugraph) + + -- set the spring length to the average arc length of the initial layout + local spring_length = 0 + for _,arc in ipairs(arcs) do + local x = abs(arc.head.pos.x - arc.tail.pos.x) + local y = abs(arc.head.pos.y - arc.tail.pos.y) + spring_length = spring_length + sqrt(x * x + y * y) + end + spring_length = spring_length / #arcs + + -- additionally improve the layout with the force-based algorithm + -- if there are more than two nodes in the coarsest graph + if coarse_graph:getSize() > 2 and end_coarsen and not start_expand then + move_vertices(coarse_graph.ugraph.vertices, e) + end + end + + -- undo coarsening step by step, applying the force-based sub-algorithm + -- to every intermediate coarse graph as well as the original graph + if i >= start_expand then + if coarse_graph:getLevel() > 0 then + if i == start_expand then + coarse_graph:uncoarsen() + elseif i < end_expand then + preprocessing(coarse_graph.ugraph.vertices, coarse_graph.ugraph.arcs, e, coarse_graph.ugraph) + move_vertices(coarse_graph.ugraph.vertices, e) + else + i = start_expand - 1 + end + else + preprocessing(coarse_graph.ugraph.vertices, coarse_graph.ugraph.arcs, e, coarse_graph.ugraph) + move_vertices(coarse_graph.ugraph.vertices, e) + end + end + -- Before and after the coarsening process + elseif i < start_coarsening or i > end_coarsening then + if not vertices_initalized then + initial_positioning_class.new { + vertices = coarse_graph.ugraph.vertices, + options = options, + desired_vertices = desired_vertices }:run() + vertices_initalized = true + end + preprocessing(coarse_graph.ugraph.vertices, coarse_graph.ugraph.arcs, e, coarse_graph.ugraph) + move_vertices(coarse_graph.ugraph.vertices, e) + end + else + -- Same without coarsen + if i < start_coarsening or i > end_coarsening then + if not vertices_initalized then + initial_positioning_class.new { + vertices = vertices, + options = options, + desired_vertices = desired_vertices }:run() + vertices_initalized = true + end + preprocessing(vertices, arcs, e, ugraph) + move_vertices(vertices, e, self.ugraph) + end + end + i = i + 1 + end +end + + +--- Preprocessing for all force types in force configuration +-- +-- @params v The vertices of the current graph +-- @params a The arcs of the current graph +-- @params epoch The preprocessing algorithm will only be applied to the forces +-- associated with this epoch. +-- @params ugraph The current graph object + +function preprocessing(v, a, epoch, ugraph) + for _, fc in ipairs(epoch_forces[epoch]) do + fc:preprocess(v, a, ugraph) + end +end + + +--- Adding forces to the algorithm. +-- +-- @params force_data A table containing force type, time function, force function, +-- capping thresholds and the epochs in which this force will be active + +function ForceController:addForce(force_data) + local t = force_data.force_type + if t == ForcePullToPoint then + self.pull_to_point = true + end + + local f = t.new {force = force_data, options = self.ugraph.options, fw_attributes = self.fw_attributes or {}} + if force_data.epoch == nil then + force_data.epoch = {} + end + for _,e in ipairs(force_data.epoch) do + local tab = self.epoch_forces[e] + if not tab then + tab = {} + end + tab[#tab +1] = f + self.epoch_forces[e] = tab + end +end + + +--- Moving vertices according to force functions until the maximum number of +-- iterations is reached +-- +-- @params vertices The vertices in the current graph +-- @params epoch The current epoch, to find the forces that are active + +function move_vertices(vertices, epoch, g) + if #epoch_forces[epoch] == 0 then + return + end + local iterations = options["iterations ".. epoch] or options["iterations"] + local find_equilibrium = options["find equilibrium ".. epoch] or options["find equilibrium"] + local epsilon = options["equilibrium threshold ".. epoch] or options["equilibrium threshold"] + local speed = options["global speed factor ".. epoch] or options["global speed factor"] + local max_step = options["maximum displacement per step ".. epoch] or options["maximum displacement per step"] + + assert(epsilon >= 0, 'the threshold for finding an equilibirum (equilibrium threshold) (value: ' .. epsilon .. ') needs to be greater than or equal to 0') + assert(speed > 0, 'the speed at which the vertices move (value: ' .. speed .. ') needs to be greater than 0') + assert(max_step > 0, 'the maximum displacement per step each vertex can move per iteration (value: ' .. max_step .. ') needs to be greater than 0') + + local max_time = options["maximum time ".. epoch] or options["maximum time"] + local d_t = max_time/iterations + local t_now = 0 + local random = math.random + local randomseed = math.randomseed + + for j = 1 , iterations do + t_now = t_now + d_t + net_forces = get_net_force(vertices, j, t_now, epoch) + + -- normalize the force vector if necessary + for v, c in pairs(net_forces) do + local n = sqrt(c.x*c.x+c.y*c.y) + if n > max_step then + local factor = max_step/n + c.x = c.x*factor + c.y = c.y*factor + end + end + + -- if not in equilibrium yet, apply forces + if not find_equilibrium or sum_up(net_forces)*d_t > epsilon then + local cool_down_dt = d_t + if cool_down_dt > 1 then + cool_down_dt = 1 + 1/d_t + end + for _, v in ipairs(vertices) do + local factor = 1/(v.mass or 1) + local c1 = net_forces[v] + local x = speed * cool_down_dt * c1.x * factor + local y = speed * cool_down_dt * c1.y * factor + local p = v.pos + p.x = p.x + x + p.y = p.y + y + end + else + break + end + end +end + + +-- calculate the net force for each vertex in one iteration +-- +-- @params vertices the vertices of the current graph +-- @params j The current iteration +-- @params t_now The current virtual time +-- @params epoch The current epoch +-- +-- @return A table of coordinate-objects associated with vertices. The +-- coordinate object hold the calculated net displacement for +-- the $x$ and $y$ coordinate. +function get_net_force(vertices, j, t_now, epoch) + local net_forces = {} + local natural_spring_length = options["node distance"] + + for _,v in ipairs(vertices) do + net_forces[v] = Coordinate.new(0,0) + end + + for _,force_class in ipairs(epoch_forces[epoch]) do + force_class:applyTo{net_forces = net_forces, options = options, j = j, t_now = t_now, k = natural_spring_length} + end + + return net_forces +end + +-- Helper function to sum up all calculated forces +-- +-- @params tab A table holding coordinate objects as values +-- +-- @returns The sum of the absolute $x$ and $y$ values in this table +function sum_up(tab) + local sum = 0 + for v, c in pairs(tab) do + sum = sum + abs(c.x) + abs(c.y) + end + return sum +end + +return ForceController
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/base/ForceTemplate.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/base/ForceTemplate.lua new file mode 100644 index 00000000000..06b61870ff4 --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/base/ForceTemplate.lua @@ -0,0 +1,44 @@ +-- Copyright 2014 by Ida Bruhns +-- +-- 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 information + + +--- This is the parent class for forces. It provides a constructor and methods +-- stubs to be overwritten in the subclasses. + +-- Imports +local lib = require "pgf.gd.lib" + +local ForceTemplate = lib.class {} + +-- constructor +function ForceTemplate:constructor() + self.force = self.force + self.fw_attributes = self.fw_attributes + if not self.force.time_fun then + self.force.time_fun = function() return 1 end + end +end + +-- Method stub for preprocessing +-- +-- @param v The vertices the list will be build on + +function ForceTemplate:preprocess(v) +end + +-- Method stub for applying the forces +-- +-- @param data A table holding data like the table the forces are collected +-- in, the current iteration, the current time stamp, some options +-- or the natural spring length + +function ForceTemplate:applyTo(data) +end + +return ForceTemplate
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/base/InitialTemplate.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/base/InitialTemplate.lua new file mode 100644 index 00000000000..ad315e7a660 --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/base/InitialTemplate.lua @@ -0,0 +1,64 @@ +-- Copyright 2014 by Ida Bruhns +-- +-- 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 information + + +--- This is the parent class for initial layout algorithms. It provides a +-- constructor and methods stubs to be overwritten in the subclasses as well +-- as placing vertices which are |desired at| a certain point. + +-- Imports +local lib = require "pgf.gd.lib" + +local InitialTemplate = lib.class {} + +-- constructor +function InitialTemplate:constructor() + self.vertices = self.vertices + self.options = self.options + self.desired_vertices = self.desired_vertices +end + +-- Method placing |desired at| vertices at the point they are desired +-- +-- @params desired_vertices A table containing all the vertices where the +-- |desired at| option is set. +-- +-- @return |placed| A boolean array stating if vertices have been placed yet +-- @return |centroid_x| The x-coordinate of the midpoint of all placed vertices +-- @return |centroid_y| The y-coordinate of the midpoint of all placed vertices + +function InitialTemplate:desired(desired_vertices) + local placed = {} + + local centroid_x, centroid_y = 0, 0 + + local size = 0 + for v, da in pairs(desired_vertices) do + local p = v.pos + local x, y = da.x, da.y + p.x = x or 0 + p.y = y or 0 + centroid_x = centroid_x + x + centroid_y = centroid_y + y + placed[v] = true + size = size +1 + end + if size>0 then + centroid_x = centroid_x / size + centroid_y = centroid_y / size + end + + return placed, centroid_x, centroid_y +end + +-- Method stub for running the layout algorithm +function InitialTemplate:run() +end + +return InitialTemplate
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/base/PathLengthsFW.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/base/PathLengthsFW.lua new file mode 100644 index 00000000000..cf7cbddc20f --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/base/PathLengthsFW.lua @@ -0,0 +1,174 @@ +-- Copyright 2014 by Ida Bruhns +-- +-- 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 information + +--- This is a helper class providing different functions that deal with graph +-- distances. This class can be used by engineers and implementers if they +-- need to calculate anything regarding graph distances. + +local PathLengths = {} + +-- Imports +local PriorityQueue = require "pgf.gd.lib.PriorityQueue" +local Preprocessing = require "pgf.gd.force.jedi.base.Preprocessing" + +-- This algorithm conducts a breadth first search on the graph it is given. +-- +-- @param ugraph The graph on which the search should be conducted +-- +-- @return A table holding every vertex $v$ as key and a table as value. The +-- value table holds all other vertices $u$ as keys and their shortest +-- distance to $v$ as value + +function PathLengths:breadthFirstSearch(ugraph) + local distances = {} + local vertices = ugraph.vertices + local arcs = ugraph.arcs + + for _,v in ipairs(vertices) do + distances[v] = {} + local dist = distances[v] + for _,w in ipairs(vertices) do + dist[w] = #vertices +1 + end + dist[v] = 0 + end + local n = 1 + local p = Preprocessing.overExactlyNPairs(vertices, arcs, n) + while (#p > 0) do + for _, v in ipairs(p) do + local tab = distances[v.tail] + tab[v.head] = n + end + n = n + 1 + p = Preprocessing.overExactlyNPairs(vertices, arcs, n) + end + return(distances) +end + + +-- This function performs Dijkstra's algorithm on the graph. +-- +-- @param ugraph The graph where the paths should be found +-- @param source The source vertex +-- +-- @return |distance| A table holding every vertex $v$ as key and a table as +-- value. The value table holds all other vertices $u$ as +-- keys and their shortest distance to $v$ as value +-- @return |levels| A table holding the levels of the graph as keys and a +-- table holding the vertices found on that level as values +-- @return |parent| A tbale holding each vertex as key and it's parent vertex +-- as value + +function PathLengths:dijkstra(ugraph, source) + local distance = {} + local levels = {} + local parent = {} + + local queue = PriorityQueue.new() + + -- reset the distance of all nodes and insert them into the priority queue + for _,v in ipairs(ugraph.vertices) do + if v == source then + distance[v] = 0 + parent[v] = nil + queue:enqueue(v, distance[v]) + else + distance[v] = #ugraph.vertices + 1 -- this is about infinity ;) + queue:enqueue(v, distance[v]) + end + end + + while not queue:isEmpty() do + local u = queue:dequeue() + + assert(distance[u] < #ugraph.vertices + 1, 'the graph is not connected, Dijkstra will not work') + + if distance[u] > 0 then + levels[distance[u]] = levels[distance[u]] or {} + table.insert(levels[distance[u]], u) + end + + + + for _,edge in ipairs(ugraph:outgoing(u)) do + local v = edge.head + local alternative = distance[u] + 1 + if alternative < distance[v] then + distance[v] = alternative + + parent[v] = u + + -- update the priority of v + queue:updatePriority(v, distance[v]) + end + end + end + + return distance, levels, parent +end + +-- This function finds the pseudo diameter of the graph, which is the longest +-- shortest path in the graph +-- +-- @param ugraph The graph who's pseudo diameter is wanted +-- +-- @ return |diameter| The pseudo diameter of the graph +-- @ return |start_node| The start node of the longest shortest path in the +-- graph +-- @ return |end_node| The end node of the longest shortest path in the graph + +function PathLengths:pseudoDiameter(ugraph) + + -- find a node with minimum degree + local start_node = ugraph.vertices[1] + for _,v in ipairs(ugraph.vertices) do + if #ugraph:incoming(v) + #ugraph:outgoing(v) < #ugraph:incoming(start_node) + #ugraph:outgoing(start_node) then + start_node = v + end + end + + assert(start_node) + + local old_diameter = 0 + local diameter = 0 + local end_node = nil + + while true do + local distance, levels = self:dijkstra(ugraph, start_node) + + -- the number of levels is the same as the distance of the nodes + -- in the last level to the start node + old_diameter = diameter + diameter = #levels + + -- abort if the diameter could not be improved + if diameter == old_diameter then + end_node = levels[#levels][1] + break + end + + -- select the node with the smallest degree from the last level as + -- the start node for the next iteration + start_node = levels[#levels][1] + for _,node in ipairs(levels[#levels]) do + if #ugraph:incoming(node)+#ugraph:outgoing(node) < #ugraph:incoming(start_node) + #ugraph:outgoing(start_node) then + start_node = node + end + end + + assert(start_node) + end + + assert(start_node) + assert(end_node) + + return diameter, start_node, end_node +end + +return PathLengths
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/base/Preprocessing.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/base/Preprocessing.lua new file mode 100644 index 00000000000..182a1e4fa79 --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/base/Preprocessing.lua @@ -0,0 +1,122 @@ +-- Copyright 2014 by Ida Bruhns +-- +-- This file may be distributed an/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 information + + +--- This file holds functions to create lists of vertex pairs. All +-- functions return a Graph object containing the vertices of the +-- original graph and an edge between the vertices forming a pair +-- under the specified conditions. The lists can be precomouted to +-- enhance performance. + +local PreprocessClass = {} + +-- Imports +local declare = require "pgf.gd.interface.InterfaceToAlgorithms".declare +local Digraph = require "pgf.gd.model.Digraph" + + +-- Creates a graph object with an arc between all pairwise disjoint vertex +-- pairs and returns the arc table +-- +-- @param vertices The vertices of the original graph +-- +-- @return An arc table + +function PreprocessClass.allPairs(vertices) + local aP = Digraph.new{} + for _, vertex in ipairs(vertices) do + for _, vertex2 in ipairs(vertices) do + if vertex ~= vertex2 then + if not aP:contains(vertex) then + aP:add {vertex} + end + if not aP:contains(vertex2) then + aP:add {vertex2} + end + if not aP:arc(vertex, vertex2) and not aP:arc(vertex2, vertex) then + aP:connect(vertex, vertex2) + end + end + end + end + return aP.arcs +end + + +-- Creates a graph object with an arc between all pairwise disjoint vertex +-- pairs that are connected by a shortest path of length n in the original +-- graph and returns the arc table +-- +-- @param vertices The vertices of the original graph +-- @param arcs The arcs of the original graph +-- @param n The length of the shortest path we are looking for +-- +-- @return An arc table + +function PreprocessClass.overExactlyNPairs(vertices, arcs, n) + local waste, p_full = PreprocessClass.overMaxNPairs(vertices, arcs, n) + local waste, p_small = PreprocessClass.overMaxNPairs(vertices, arcs, n-1) + for _, paar in ipairs(p_full.arcs) do + if p_small:arc(paar.head, paar.tail) ~= nil or p_small:arc(paar.tail, paar.head) ~= nil then + p_full:disconnect(paar.head, paar.tail) + p_full:disconnect(paar.tail, paar.head) + end + end + return p_full.arcs +end + + +-- Creates a graph object with an arc between all pairwise disjoint vertex +-- pairs that are connected by a shortest path of length n or shorter in the +-- original graph and returns the arc table +-- +-- @param vertices The vertices of the original graph +-- @param arcs The arcs of the original graph +-- @param n The length of the shortest path we are looking for +-- +-- @return An arc table + +function PreprocessClass.overMaxNPairs(vertices, arcs, n) + assert(n >= 0, 'n (value: ' .. n.. ') needs to be greater or equal 0') + local p = Digraph.new{} + local oneHop = Digraph.new{} + if n> 0 then + for _, arc in ipairs(arcs) do + local vertex = arc.head + local vertex2 = arc.tail + if not p:contains(vertex) then + p:add {vertex} + oneHop:add {vertex} + end + if not p:contains(vertex2) then + p:add {vertex2} + oneHop:add {vertex2} + end + if p:arc(vertex, vertex2) == nil and p:arc(vertex2, vertex) == nil then + p:connect(vertex, vertex2) + oneHop:connect(vertex, vertex2) + end + end + end + + n = n-1 + while n > 0 do + for _, paar in ipairs(p.arcs) do + for _, vertex in ipairs(vertices) do + if paar.head ~= vertex and p:arc(paar.head, vertex) == nil and p:arc(vertex, paar.head) == nil and (oneHop:arc(paar.tail, vertex) ~= nil or oneHop:arc(vertex, paar.tail) ~= nil) then + p:connect(paar.head, vertex) + end + end + end + n = n-1 + end + return p.arcs, p +end + +return PreprocessClass
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/doc.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/doc.lua new file mode 100644 index 00000000000..620c035d523 --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/doc.lua @@ -0,0 +1,363 @@ +-- Copyright 2014 by Ida Bruhns and 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 information + +-- Imports +local key = require 'pgf.gd.doc'.key +local documentation = require 'pgf.gd.doc'.documentation +local summary = require 'pgf.gd.doc'.summary +local example = require 'pgf.gd.doc'.example + + +-------------------------------------------------------------------- +key "maximum step" + +summary +[[ +This option determines the maximum ditance every vertex is allowed to travel +in one iteration. +]] + +documentation +[[ +No matter how large the forces influencing a vertex, the effect +on the drawing should be limited to avoid vertices "jumping" from one side of +the canvas to each other due to a strong force pulling them further than their +ideal destination. The amount of space a vertex is allowed to travel in one +iteration is limited by the \lstinline{maximum step} parameter. It is $5000$ +by default. That means by default, this parameter should not get in your way. +]] + + +example +[[ +\tikz + \graph[social degree layout, iterations = 2, maximum time = 2, maximum step = 6pt, coarsen = false]{ + a1 -- {a2, a3, a4, a5}, + b1 -- {b2 -- {b3, b4}, b5} + }; +]] + +example +[[ +\tikz + \graph[social degree layout, iterations = 2, maximum time = 2, maximum step = 12pt, coarsen = false]{ + a1 -- {a2, a3, a4, a5}, + b1 -- {b2 -- {b3, b4}, b5} + }; +]] +-------------------------------------------------------------------- + + + + + +-------------------------------------------------------------------- +key "speed" + +summary +[[ This is a factor every calculated step is multiplied by.]] + +documentation +[[ +The speed is the distance a vertex travels if it is influenced by a force of +$1$N$\cdot\gamma$. The speed is only a factor that will influence the total +amount every vertex can move: Half the speed makes half the movement, twice +the speed doubles the distance traveled. +]] + +example +[[ +\tikz + \graph[social degree layout, iterations = 1, maximum time = 1, maximum step = 100, speed = 0.2, coarsen = false]{ + a1 -- {a2, a3, a4, a5}, + b1 -- {b2 -- {b3, b4}, b5} + }; +]] + +example +[[ +\tikz + \graph[social degree layout, iterations = 1, maximum time= 1, maximum step = 100, speed = 0.4, coarsen = false]{ + a1 -- {a2, a3, a4, a5}, + b1 -- {b2 -- {b3, b4}, b5} + }; +]] +-------------------------------------------------------------------- + + + +-------------------------------------------------------------------- +key "maximum time" + +summary +[[ The highest amount of virtual time the algorithm is allowed to take.]] + +documentation +[[ +This option is part of the virtual time construct of Jedi. The virtual time +concept allows graph drawing algorithm engineers to switch forces on and of +after a relative or absolute amount of time has elapsed. If the iterations +stay the same, doubling the maximum time has the same effect as doubling the +speed: Vertices move faster, but it is possible they miss their intended +destination. Also increasing the iterations changes the "resolution" of the +graph drawing algorithm: More steps are simulated in the same time. +]] + +example +[[ +\tikz + \graph[social degree layout, iterations = 20, maximum time = 100, coarsen = false, maximum step = 0.5, gravity = 2]{ + a1 -- {a2, a3, a4, a5}, + b1 -- {b2 -- {b3, b4}, b5} + }; +]] + +example +[[ +\tikz + \graph[social degree layout, iterations = 20, maximum time = 200, coarsen = false, maximum step = 0.5, gravity = 2]{ + a1 -- {a2, a3, a4, a5}, + b1 -- {b2 -- {b3, b4}, b5} + }; +]] +-------------------------------------------------------------------- + + + +-------------------------------------------------------------------- +key "find equilibrium" + +summary +[[ If this option is |true|, the framework checks the vertex movment to detect +low movement near the equilibrium and stop the algorithm]] + +documentation +[[ +Since we often do not know how many iterations are enough, the framework will +detect when the vertices (almost) stop moving and stop the algorithm. After +each iteration, the framework adds up the net force influencing all the +vertices. If it falls below the threshold |epsilon|, the algorithm +will ignore the left over iterations and terminate. You can disable this +behavior by setting this parameter to |false|. Allowing the framework to find +the equilibrium usually saves you time, while allowing more iterations (or a + lower threshold) generates higher quality drawings. +]] + +example +[[ +\tikz + \graph[social degree layout, iterations = 300, maximum time = 300, coarsen = false, maximum step = 10, epsilon = 10]{ + a1 -- {a2, a3, a4, a5}, + b1 -- {b2 -- {b3, b4}, b5} + }; +]] + +example +[[ +\tikz + \graph[social degree layout, iterations = 300, maximum time = 300, maximum step = 10, find equilibrium = false]{ + a1 -- {a2, a3, a4, a5}, + b1 -- {b2 -- {b3, b4}, b5} + }; +]] +-------------------------------------------------------------------- + + + +-------------------------------------------------------------------- +key "epsilon" + +summary +[[ The threshold for the |find equilibrium| option.]] + +documentation +[[ +This key specifies the threshold for the |find equilibrium| option. The lower +epsilon, the longer the graph drawing algorithm will take, but the closer the +resulting drawing will be to the true energy minimum. +]] + +example +[[ +\tikz + \graph[social degree layout, iterations = 200, maximum time = 200, maximum step = 10, coarsen = false, epsilon = 2]{ + a1 -- {a2, a3, a4, a5}, + b1 -- {b2 -- {b3, b4}, b5} + }; +]] + +example +[[ +\tikz + \graph[social degree layout, iterations = 200, maximum time = 200, maximum step = 10, epsilon = 12, coarsen = false]{ + a1 -- {a2, a3, a4, a5}, + b1 -- {b2 -- {b3, b4}, b5} + }; +]] +-------------------------------------------------------------------- + + + +-------------------------------------------------------------------- +key "snap to grid" + +summary +[[ This option enables the post-processing step |snap to grid|.]] + +documentation +[[ +This key is the on/off-switch for the grid forces. The |snap to grid| option +triggers a form of post-processing were all vertices are pulled to the closest +point on a virtual grid. Please note that there is no repulsive force between +the vertices, so it is possible that two vertices are pulled to the same grid +point. The grid size is determined by the parameters |grid x length| and +|grid y length|. +]] + +example +[[ +\tikz + \graph[social degree layout, iterations = 100, maximum time = 100, maximum step = 10]{ + a1 -- {a2, a3, a4, a5}, + b1 -- {b2 -- {b3, b4}, b5} + }; +]] + +example +[[ +\tikz{ + \graph[social degree layout, iterations = 100, maximum time = 100, snap to grid =true, grid x length = 5mm, grid y length = 5mm, maximum step = 10]{ + a1 -- {a2, a3, a4, a5}, + b1 -- {b2 -- {b3, b4}, b5} + }; +]] +-------------------------------------------------------------------- + + + +-------------------------------------------------------------------- +key "grid x length" + +summary +[[ This option determines the cell size in $x$ direction for the |snap to grid| +option.]] + +documentation +[[ +The size of the cells of the virtual grid can be configured by the user. This +key allows a configuration of the horizontal cell width. +]] + +example +[[ +\tikz + \graph[social degree layout, iterations = 100, maximum time = 100, snap to grid =true, grid x length = 5mm, grid y length = 5mm, maximum step = 10]{ + a1 -- {a2, a3, a4, a5}, + b1 -- {b2 -- {b3, b4}, b5} + }; +]] + +example +[[ +\tikz + \graph[social degree layout, iterations = 100, maximum time = 100, snap to grid =true, grid x length = 9mm, grid y length = 5mm, maximum step = 10]{ + a1 -- {a2, a3, a4, a5}, + b1 -- {b2 -- {b3, b4}, b5} + }; +]] +-------------------------------------------------------------------- + + + +-------------------------------------------------------------------- +key "grid y length" + +summary +[[ This option determines the cell size in $x$ direction for the |snap to grid| +option.]] + +documentation +[[ +Same as |grid x length|, but in vertical direction (height of the cells). +]] + +example +[[ +\tikz + \graph[social degree layout, iterations = 100, maximum time = 100, snap to grid =true, grid x length = 5mm, grid y length = 5mm, maximum step = 10]{ + a1 -- {a2, a3, a4, a5}, + b1 -- {b2 -- {b3, b4}, b5} + }; +]] + +example +[[ +\tikz + \graph[social degree layout, iterations = 100, maximum time = 100, snap to grid =true, grid x length = 5mm, grid y length = 9mm, maximum step = 10]{ + a1 -- {a2, a3, a4, a5}, + b1 -- {b2 -- {b3, b4}, b5} + }; +]] +-------------------------------------------------------------------- + + +-------------------------------------------------------------------- +key "mass" + +summary +[[ + The mass of a vertex determines how fast it can move. Vertices + with higher mass move slower. +]] + +documentation +[[ + The mass of a vertex determines how fast this vertex + moves. Mass is directly inverse proportional to the distance the vertex + moves. In contrast to the global speed factor, mass usually only affects a + single vertex. A vertex with a higher mass will move slower if affected by + the same mass than a vertex with a lower mass. By default, each vertex has a + mass of $1$. +]] + +example +[[ + \tikz + \graph[social degree layout, iterations = 100, maximum time = 100, maximum displacement per step = 10]{ + a1 -- {a2, a3, a4, a5}, + b1 -- {b2 -- {b3, b4}, b5} + }; +]] + +example +[[ + \tikz + \graph[social degree layout, iterations = 100, maximum time = 100, maximum displacement per step = 10]{ + a1 -- {a2, a3, a4, a5}, + b1[mass = 4] -- {b2 -- {b3, b4}, b5} + }; +]] +-------------------------------------------------------------------- + + +-------------------------------------------------------------------- +key "coarsening weight" + +summary +[[ + The coarsening weight of a vertex determines when it will be + coarsened. +]] + +documentation +[[ + Vertices with higher coarsening weight are considered more important and + will be coarsened later, or not at all. +]] +-------------------------------------------------------------------- diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/forcetypes/ForceAbsoluteValue.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/forcetypes/ForceAbsoluteValue.lua new file mode 100644 index 00000000000..774743e52e6 --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/forcetypes/ForceAbsoluteValue.lua @@ -0,0 +1,94 @@ +-- Copyright 2014 by Ida Bruhns +-- +-- 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 information + +--- This is a subclass of ForceTemplate, which is used to implement forces +-- that work on individual vertices. Forces of this kind simply add an +-- absolute value set in the force data to each vertex' $x$ and $y$ coodinate + +-- Imports +local ForceTemplate = require "pgf.gd.force.jedi.base.ForceTemplate" +local lib = require "pgf.gd.lib" +local Preprocessing = require "pgf.gd.force.jedi.base.Preprocessing" + +-- Localize math functions +local max = math.max +local sqrt = math.sqrt +local min = math.min + +-- Implementation starts here: + +local ForceAbsoluteValue = lib.class { base_class = ForceTemplate } + +function ForceAbsoluteValue:constructor () + ForceTemplate.constructor(self) + self.p = {} +end + + +-- This force class works on a vertex array that is part of the force data +-- defined when adding the force. This array is copied into p. All vertices of +-- the graph are saved in the local variable |ver|. +-- +-- @param v The vertices of the graph we are trying to find a layout for. + +function ForceAbsoluteValue:preprocess(v) + self.ver = v + self.p = self.force.vertices +end + + +-- Applying the force to the vertices and adding the effect to the passed net +-- force array +-- +-- @param data The parameters needed to aplly the force: The options table, +-- the current time stamp, an array containing the summed up net +-- forces + +function ForceAbsoluteValue:applyTo(data) + -- locals for speed + local cap = self.force.cap + local value = self.force.value + local net_forces = data.net_forces + local t_max = self.options["maximum time"] + local t_now = data.t_now + local p = self.p + local time_fun = self.force.time_fun + + -- Evaluate time function + local time_factor = time_fun(t_max, t_now) + if time_factor == 0 then + return + end + + for _,v in ipairs(self.ver) do + for _, i in ipairs (self.p) do + -- Is the vertex in the list? + if v.name == i then + + local f = value * time_factor + + -- cap effect if necessary + if cap then + if f <= 0 then + x = max(-cap, f) + else + x = min(cap, f) + end + end + + -- add calculated effect to net forces + local c1 = net_forces[v] + c1.x = c1.x + f + c1.y = c1.y + f + end + end + end +end + +return ForceAbsoluteValue
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/forcetypes/ForceCanvasDistance.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/forcetypes/ForceCanvasDistance.lua new file mode 100644 index 00000000000..6d9e69745ed --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/forcetypes/ForceCanvasDistance.lua @@ -0,0 +1,201 @@ +-- Copyright 2014 by Ida Bruhns +-- +-- 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 information + + +--- This is a subclass of ForceTemplate, which is used to implement forces between +-- vertex pairs. The forces depend on the canvas distance of the vertices in +-- the pair. This class is e.~g.~ used for electric forces. + +-- Imports +local ForceTemplate = require "pgf.gd.force.jedi.base.ForceTemplate" +local lib = require "pgf.gd.lib" +local Preprocessing = require "pgf.gd.force.jedi.base.Preprocessing" + +-- Localize math functions +local max = math.max +local sqrt = math.sqrt +local min = math.min + +-- Implementation starts here: +local ForceCanvasDistance = lib.class { base_class = ForceTemplate } + +function ForceCanvasDistance:constructor () + ForceTemplate.constructor(self) + self.p = {} +end + + +-- This force class works on all pairwise disjoint vertex pairs. This +-- function generates a new graph object containing all vertices from the +-- original graph and arcs between all pairwise disjoint vertex pairs. The +-- arcs-table of this new object will be saved in the variable |p|. +-- +-- @param v The vertices of the graph we are trying to find a layout for. + +function ForceCanvasDistance:preprocess(v) + self.p = Preprocessing.allPairs(v) +end + + +-- Applying the force to the vertices and adding the effect to the passed net +-- force array +-- +-- @param data The parameters needed to aplly the force: The options table, +-- the current time stamp, an array containing the summed up net +-- forces + +function ForceCanvasDistance:applyTo(data) + -- locals for speed + local cap = self.force.cap + local fun_u = self.force.fun_u + local fun_v = self.force.fun_v + local net_forces = data.net_forces + local t_max = self.options["maximum time"] + local t_now = data.t_now + local k = data.k + local p = self.p + local time_fun = self.force.time_fun + local fw_attributes = self.fw_attributes + + -- Evaluate time function + local time_factor = time_fun(t_max, t_now) + if time_factor == 0 then + return + end + + if not fun_v then + local data = { k = k, attributes = fw_attributes } + for _, i in ipairs(p) do + -- dereference + local p2 = i.head + local p1 = i.tail + local p2_pos = p2.pos + local p1_pos = p1.pos + + -- calculate distance between two points + local x = p2_pos.x - p1_pos.x + local y = p2_pos.y - p1_pos.y + local d = max(sqrt(x*x+y*y),0.1) + + -- apply force function + data.u = p2 + data.v = p1 + data.d = d + local e = fun_u(data) + + -- Include time function + local f = e * time_factor / d + + -- calculate effect on x/y + local g = x * f + local h = y * f + + -- cap effect if necessary + if cap then + if g <= 0 then + x = max(-cap, g) + else + x = min(cap, g) + end + + if h <= 0 then + y = max(-cap, h) + else + y = min(cap, h) + end + else + x = g + y = h + end + + -- add calculated effect to net forces + local c1 = net_forces[p1] + c1.x = c1.x - x + c1.y = c1.y - y + local c2 = net_forces[p2] + c2.x = c2.x + x + c2.y = c2.y + y + end + else + -- There are different functions for head and tail vertex + local data = { k = k, attributes = fw_attributes } + for _, i in ipairs(p) do + -- dereference + local p2 = i.head + local p1 = i.tail + local p2_pos = p2.pos + local p1_pos = p1.pos + + -- calculate distance between two points + local x = p2_pos.x - p1_pos.x + local y = p2_pos.y - p1_pos.y + local d = max(sqrt(x*x+y*y),0.1) + + -- apply force function to distance and k (natural spring length + data.u = p2 + data.v = p1 + data.d = d + local e_head = fun_u(data) + local e_tail = fun_v(data) + + -- Include time function + local f_head = time_factor * e_head / d + local f_tail = time_factor * e_tail / d + + -- calculate effect on x/y + local g_head = x * f_head + local g_tail = x * f_tail + local h_head = y * f_head + local h_tail = y * f_tail + + -- cap effect if necessary + local x_head, x_tail, y_head, y_tail + if cap then + if g_head <= 0 then + x_head = max(-cap, g_head) + else + x_head = min(cap, g_head) + end + + if g_tail <= 0 then + x_tail = max(-cap, g_tail) + else + x_tail = min(cap, g_tail) + end + + if h_head <= 0 then + y_head = max(-cap, h_head) + else + y_head = min(cap, h_head) + end + + if h_tail <= 0 then + y_tail = max(-cap, h_tail) + else + y_tail = min(cap, h_tail) + end + else + x_head = g_head + x_tail = g_tail + y_head = h_head + y_tail = h_tail + end + + -- add calculated effect to net forces + local c1 = net_forces[p1] + c1.x = c1.x - x_tail + c1.y = c1.y - y_tail + local c2 = net_forces[p2] + c2.x = c2.x + x_head + c2.y = c2.y + y_head + end + end +end + +return ForceCanvasDistance
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/forcetypes/ForceCanvasPosition.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/forcetypes/ForceCanvasPosition.lua new file mode 100644 index 00000000000..377ab22c348 --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/forcetypes/ForceCanvasPosition.lua @@ -0,0 +1,117 @@ +-- Copyright 2014 by Ida Bruhns +-- +-- 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 information + + +--- This is a subclass of ForceTemplate, which is used to implement forces +-- that work on individual vertices. The forces depend on the canvas position +-- of the vertices. This class is e.~g.~ used for gravitational forces. + +local ForceTemplate = require "pgf.gd.force.jedi.base.ForceTemplate" +local lib = require "pgf.gd.lib" + +local ForceCanvasPosition = lib.class { base_class = ForceTemplate } + +-- Localize math functions +local max = math.max +local sqrt = math.sqrt +local min = math.min + +-- Implementation starts here: + +function ForceCanvasPosition:constructor () + ForceTemplate.constructor(self) + self.p = {} +end + + +-- This force class works on individual vertices and only depends on their +-- current position. Thus the vertex table of the current graph is simply +-- copied to the variable |p|. +-- +-- @param v The vertices of the graph we are trying to find a layout for. + +function ForceCanvasPosition:preprocess(v) + self.p = v +end + + +-- Applying the force to the vertices and adding the effect to the passed net +-- force array +-- +-- @param data The parameters needed to aplly the force: The options table, +-- the current time stamp, an array containing the summed up net +-- forces + +function ForceCanvasPosition:applyTo(data) + --localize + local cap = self.force.cap + local fun_u = self.force.fun_u + local net_forces = data.net_forces + local t_max = self.options["maximum time"] + local t_now = data.t_now + local p = self.p + local time_fun = self.force.time_fun + local initial_gravity = self.options["gravity"] + local fw_attributes = self.fw_attributes + + -- evaluate time function + local time_factor = time_fun(t_max, t_now) + if time_factor == 0 then + return + end + + -- Find midpoint of all vertices since they will be attracted to this point + local centroid_x, centroid_y = 0,0 + for _, v in ipairs(p) do + local pos = v.pos + centroid_x = centroid_x + pos.x + centroid_y = centroid_y + pos.y + end + centroid_x = centroid_x/#p + centroid_y = centroid_y/#p + + -- Iterate over the precomputed vertex list + for _, v in ipairs(p) do + -- localize + local p1 = v.pos + + -- apply force function + local factor = fun_u{attributes = fw_attributes, u = v} + + -- calculate distance between vertex and centroid + local x = centroid_x - p1.x + local y = centroid_y - p1.y + + -- calculate effect on x/y + local h = factor * time_factor + x = x * h + y = y * h + + -- cap effect if necessary + if cap then + if x <= 0 then + x = max(-cap, x) + else + x = min(cap, x) + end + if y <= 0 then + y = max(-cap, y) + else + y = min(cap, y) + end + end + + -- add calculated effect to net forces + local c = net_forces[v] + c.x = c.x + x + c.y = c.y + y + end +end + +return ForceCanvasPosition
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/forcetypes/ForceGraphDistance.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/forcetypes/ForceGraphDistance.lua new file mode 100644 index 00000000000..628f1192ac0 --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/forcetypes/ForceGraphDistance.lua @@ -0,0 +1,205 @@ +-- Copyright 2014 by Ida Bruhns +-- +-- 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 information + + +--- This is a subclass of ForceTemplate, which is used to implement forces between +-- vertex pairs. The forces depend on the graph distance of the vertices in +-- the pair. This class is e.~g.~ used for spring forces. + + +local ForceTemplate = require "pgf.gd.force.jedi.base.ForceTemplate" +local lib = require "pgf.gd.lib" +local Preprocessing = require "pgf.gd.force.jedi.base.Preprocessing" + +-- Localize math functions +local max = math.max +local sqrt = math.sqrt +local min = math.min + +-- Implementation starts here: + +local ForceGraphDistance = lib.class { base_class = ForceTemplate } + +function ForceGraphDistance:constructor () + ForceTemplate.constructor(self) + self.p = {} +end + + +-- This force class works on all pairwise disjoint vertex pairs connected by +-- a path of length maximum $n$. The parameter $n$ is given by the engineer in +-- the force declaration. This function generates a new graph object +-- containing all vertices from the original graph and arcs between all +-- pairwise disjoint vertex pairs. The arcs-table of this new object will be +-- saved in the variable |p|. +-- +-- @param v The vertices of the graph we are trying to find a layout for. + +function ForceGraphDistance:preprocess(v, a) + self.p = Preprocessing.overExactlyNPairs(v, a, self.force.n) +end + + +-- Applying the force to the vertices andadding the effect to the passed net +-- force array +-- +-- @param data The parameters needed to aplly the force: The options table, +-- the current time stamp, an array containing the summed up net +-- forces + +function ForceGraphDistance:applyTo(data) + -- locals for speed + local cap = self.force.cap + local fun_u = self.force.fun_u + local fun_v = self.force.fun_v + local net_forces = data.net_forces + local t_max = self.options["maximum time"] + local t_now = data.t_now + local k = data.k + local p = self.p + local time_fun = self.force.time_fun + local fw_attributes = self.fw_attributes + + -- Evaluate time function + local time_factor = time_fun(t_max, t_now) + if time_factor == 0 then + return + end + + if not fun_v then + local data = { k = k, attributes = fw_attributes } + for _, i in ipairs(p) do + -- dereference + local p2 = i.head + local p1 = i.tail + local p2_pos = p2.pos + local p1_pos = p1.pos + + -- calculate distance between two points + local x = p2_pos.x - p1_pos.x + local y = p2_pos.y - p1_pos.y + local d = max(sqrt(x*x+y*y),0.1) + + -- apply force function to distance and k (natural spring length) + data.u = p2 + data.v = p1 + data.d = d + local e = fun_u(data) + + -- Include time function + local f = e * time_factor / d + + -- calculate effect on x/y + local g = x * f + local h = y * f + + -- cap effect if necessary + if cap then + if g <= 0 then + x = max(-cap, g) + else + x = min(cap, g) + end + + if g <= 0 then + y = max(-cap, h) + else + y = min(cap, h) + end + else + x = g + y = h + end + + -- add calculated effect to net forces + local c1 = net_forces[p1] + c1.x = c1.x - x + c1.y = c1.y - y + local c2 = net_forces[p2] + c2.x = c2.x + x + c2.y = c2.y + y + end + else + -- There are different functions for head and tail vertex + local data = { k = k, attributes = fw_attributes } + for _, i in ipairs(p) do + -- dereference + local p2 = i.head + local p1 = i.tail + local p2_pos = p2.pos + local p1_pos = p1.pos + + -- calculate distance between two points + local x = p2_pos.x - p1_pos.x + local y = p2_pos.y - p1_pos.y + + local d = max(sqrt(x*x+y*y),0.1) + + -- apply force function to distance and k (natural spring length + data.u = p2 + data.v = p1 + data.d = d + local e_head = fun_u(data) + local e_tail = fun_v(data) + + -- Include time function + local f_head = time_factor * e_head / d + local f_tail = time_factor * e_tail / d + + -- calculate effect on x/y + local g_head = x * f_head + local g_tail = x * f_tail + local h_head = y * f_head + local h_tail = y * f_tail + + -- cap effect if necessary + local x_head, x_tail, y_head, y_tail + if cap then + if g_head <= 0 then + x_head = max(-cap, g_head) + else + x_head = min(cap, g_head) + end + + if g_tail <= 0 then + x_tail = max(-cap, g_tail) + else + x_tail = min(cap, g_tail) + end + + if h_head <= 0 then + y_head = max(-cap, h_head) + else + y_head = min(cap, h_head) + end + + if h_tail <= 0 then + y_tail = max(-cap, h_tail) + else + y_tail = min(cap, h_tail) + end + else + x_head = g_head + x_tail = g_tail + y_head = h_head + y_tail = h_tail + end + + -- add calculated effect to net forces + local c1 = net_forces[p1] + c1.x = c1.x - x_tail + c1.y = c1.y - y_tail + local c2 = net_forces[p2] + c2.x = c2.x + x_head + c2.y = c2.y + y_head + end + end +end + +return ForceGraphDistance
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/forcetypes/ForcePullToGrid.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/forcetypes/ForcePullToGrid.lua new file mode 100644 index 00000000000..b196a8a6a95 --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/forcetypes/ForcePullToGrid.lua @@ -0,0 +1,123 @@ +-- Copyright 2014 by Ida Bruhns +-- +-- 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 information + + +--- This is a subclass of ForceTemplate, which is used to implement forces +-- that work on individual vertices and pulls them to a virtual grid with +-- cells of the size determined by the user options |grid x length| and +-- |grid y length|. The forces depend on the canvas position +-- of the vertices relative to th next grid point. This class is e.~g.~ used +-- for the post-processing technique |snap to grid|. + + +-- Imports +local ForceTemplate = require "pgf.gd.force.jedi.base.ForceTemplate" +local lib = require "pgf.gd.lib" +local Preprocessing = require "pgf.gd.force.jedi.base.Preprocessing" + +-- Localize math functions +local max = math.max +local sqrt = math.sqrt +local min = math.min +local floor = math.floor +local round +function round(number) + return floor((number * 10 + 0.5) / 10) +end + +-- Implementation starts here: + +local ForcePullToGrid = lib.class { base_class = ForceTemplate } + +function ForcePullToGrid:constructor () + ForceTemplate.constructor(self) + self.p = {} +end + +-- This force class works on individual vertices and only depends on their +-- current position. Thus the vertex table of the current graph is simply +-- copied to the variable |p|. +-- +-- @param v The vertices of the graph we are trying to find a layout for. + +function ForcePullToGrid:preprocess(v) + self.p = v +end + + +-- Applying the force to the vertices andadding the effect to the passed net +-- force array +-- +-- @param data The parameters needed to aplly the force: The options table, +-- the current time stamp, an array containing the summed up net +-- forces + +function ForcePullToGrid:applyTo(data) + -- locals for speed + local cap = self.force.cap + local net_forces = data.net_forces + local t_max = self.options["maximum time"] + local grid_x_distance = self.options["grid x length"] + local grid_y_distance = self.options["grid y length"] + local t_now = data.t_now + local p = self.p + local time_fun = self.force.time_fun + local length = 5--self.options["node distance"] + + -- Evaluate time function + local time_factor = time_fun(t_max, t_now) + if time_factor == 0 then + return + end + + for _, v in ipairs(p) do + -- dereference + local p1 = v.pos + local p2_x = round(p1.x/grid_x_distance)*grid_x_distance + local p2_y = round(p1.y/grid_y_distance)*grid_y_distance + + -- calculate distance between vertex and grid point + local x = p1.x - p2_x + local y = p1.y - p2_y + local d = max(sqrt(x*x+y*y),0.1) + local l = -d/(length*length) + + -- Include time function + local h = l * time_factor + + -- scale effect according to direction + local f = x * h + local g = y * h + + -- cap effect if necessary + if cap then + if f <= 0 then + x = max(-cap, f) + else + x = min(cap, f) + end + + if g <= 0 then + y = max(-cap, g) + else + y = min(cap, g) + end + else + x = f + y = g + end + + -- add calculated effect to net forces + local c1 = net_forces[v] + c1.x = c1.x - x + c1.y = c1.y - y + end +end + +return ForcePullToGrid
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/forcetypes/ForcePullToPoint.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/forcetypes/ForcePullToPoint.lua new file mode 100644 index 00000000000..908fdcf6b2e --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/forcetypes/ForcePullToPoint.lua @@ -0,0 +1,119 @@ +-- Copyright 2014 by Ida Bruhns +-- +-- 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 information + +--- This is a subclass of ForceTemplate, which is used to implement forces +-- that work on individual vertices and pulls them to a specific point on the +-- canvas. This point is given by the |desired at| option. The forces depend +-- on the canvas position of the vertices relative to the canvas point it is +-- pulled to. + + +-- Imports +local ForceTemplate = require "pgf.gd.force.jedi.base.ForceTemplate" +local lib = require "pgf.gd.lib" +local Preprocessing = require "pgf.gd.force.jedi.base.Preprocessing" + +-- Localize math functions +local max = math.max +local sqrt = math.sqrt +local min = math.min + +-- Implementation starts here: + +local ForcePullToPoint = lib.class { base_class = ForceTemplate } + +function ForcePullToPoint:constructor () + ForceTemplate.constructor(self) + self.p = {} +end + +-- This force class works on individual vertices and depends on their +-- current position as well as the point it is desired at. Thus all vertices +-- where the |desired at| option is set are added to the table |p| together +-- with the point where they are wanted. +-- +-- @param v The vertices of the graph we are trying to find a layout for. + +function ForcePullToPoint:preprocess(v) + for _,vertex in ipairs(v) do + if vertex.options then + local da = vertex.options["desired at"] + if da then + self.p[vertex]= {da} + end + end + end +end + + +-- Applying the force to the vertices andadding the effect to the passed net +-- force array +-- +-- @param data The parameters needed to aplly the force: The options table, +-- the current time stamp, an array containing the summed up net +-- forces + +function ForcePullToPoint:applyTo(data) + -- locals for speed + local cap = self.force.cap + local net_forces = data.net_forces + local t_max = self.options["maximum time"] + local t_now = data.t_now + local p = self.p + local time_fun = self.force.time_fun + + -- Evaluate time function + local time_factor = time_fun(t_max, t_now) + if time_factor == 0 then + return + end + + for v, point in pairs(p) do + -- dereference + local p1 = v.pos + local p2 = point[1] + + -- calculate distance between vertex and centroid + local x = p1.x - p2.x + local y = p1.y - p2.y + local d = max(sqrt(x*x+y*y),0.1) + + -- Include time function + local h = d * time_factor + + -- scale effect according to direction + local f = x * h + local g = y * h + + -- cap effect if necessary + if cap then + if f <= 0 then + x = max(-cap, f) + else + x = min(cap, f) + end + + if g <= 0 then + y = max(-cap, g) + else + y = min(cap, g) + end + else + x = f + y = g + end + + -- add calculated effect to net forces + local c1 = net_forces[v] + c1.x = c1.x - x + c1.y = c1.y - y + end +end + +return ForcePullToPoint
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/initialpositioning/CircularInitialPositioning.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/initialpositioning/CircularInitialPositioning.lua new file mode 100644 index 00000000000..1ed35653c93 --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/initialpositioning/CircularInitialPositioning.lua @@ -0,0 +1,60 @@ +-- Copyright 2014 by Ida Bruhns +-- +-- 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 information + +--- This class implements an inital position algorithm for graph drawing, placing the vertices on +-- a circle with th radius given by the |radius| key +local declare = require "pgf.gd.interface.InterfaceToAlgorithms".declare +local InitialTemplate = require "pgf.gd.force.jedi.base.InitialTemplate" +local lib = require "pgf.gd.lib" + +local CircularInitialPositioning = lib.class { base_class = InitialTemplate } + + +--- +declare { + key = "circular initial position", + algorithm = CircularInitialPositioning, + phase = "initial positioning force framework", + phase_default = true +} + +-- Implementation starts here: + +function CircularInitialPositioning:constructor () + InitialTemplate.constructor(self) +end + +function CircularInitialPositioning:run() + -- locals for speed + local vertices = self.vertices + local tmp = (self.options["node pre sep"] + self.options["node post sep"]) + + (self.options["sibling pre sep"] + self.options["sibling post sep"]) + local min_radius = tmp * #self.vertices/2/math.pi + local radius = math.max(self.options.radius, min_radius) + local desired_vertices = self.desired_vertices + -- place vertices where the |desired at | option has been set first + local placed, centroid_x, centroid_y = InitialTemplate:desired(desired_vertices) + local angle = 2*math.pi / #vertices + local a = angle + local sin = math.sin + local cos = math.cos + + for _, vertex in ipairs(vertices) do + -- place all other vertices with respect to the one already placed + if placed[vertex] == nil then + local p = vertex.pos + p.x = sin(a) * radius + centroid_x + p.y = cos(a) * radius + centroid_y + a = a + angle + end + end +end + + +return CircularInitialPositioning
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/initialpositioning/GridInitialPositioning.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/initialpositioning/GridInitialPositioning.lua new file mode 100644 index 00000000000..cb710b35d60 --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/initialpositioning/GridInitialPositioning.lua @@ -0,0 +1,60 @@ +-- Copyright 2014 by Ida Bruhns +-- +-- 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 information + +--- This class implements an inital position algorithm for graph drawing, placing the vertices on +-- a grid with square cells with width |node distance| +local declare = require "pgf.gd.interface.InterfaceToAlgorithms".declare +local InitialTemplate = require "pgf.gd.force.jedi.base.InitialTemplate" +local lib = require "pgf.gd.lib" + +local GridInitialPositioning = lib.class { base_class = InitialTemplate } + + +--- +declare { + key = "grid initial position", + algorithm = GridInitialPositioning, + phase = "initial positioning force framework", +} + +-- Implementation starts here: + +function GridInitialPositioning:constructor () + InitialTemplate.constructor(self) +end + +function GridInitialPositioning:run() + -- locals for speed + local vertices = self.vertices + local dist = self.options["node distance"] + local desired_vertices = self.desired_vertices + -- place vertices where the |desired at | option has been set first + local placed, centroid_x, centroid_y = InitialTemplate:desired(desired_vertices) + local n = math.ceil(math.sqrt(#vertices)) + local x = -dist + local y = 0 + + for i, vertex in ipairs(vertices) do + -- place all other vertices with respect to the one already placed + if placed[vertex] == nil then + if i <= (y/dist+1)*n then + x = x + dist + else + x = 0 + y = y + dist + end + local p = vertex.pos + p.x = x + centroid_x + p.y = y + centroid_y + end + end +end + + +return GridInitialPositioning
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/initialpositioning/RandomInitialPositioning.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/initialpositioning/RandomInitialPositioning.lua new file mode 100644 index 00000000000..39a58b9e2bd --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/initialpositioning/RandomInitialPositioning.lua @@ -0,0 +1,49 @@ +-- Copyright 2014 by Ida Bruhns +-- +-- 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 information + +--- This class implements an inital position algorithm for graph drawing, placing the vertices at +-- random positions. +local declare = require "pgf.gd.interface.InterfaceToAlgorithms".declare +local InitialTemplate = require "pgf.gd.force.jedi.base.InitialTemplate" +local lib = require "pgf.gd.lib" + +local RandomInitialPositioning = lib.class { base_class = InitialTemplate } + +--- +declare { + key = "random initial position", + algorithm = RandomInitialPositioning, + phase = "initial positioning force framework" +} + +-- Implementation starts here: + +function RandomInitialPositioning:constructor () + InitialTemplate.constructor(self) +end + +function RandomInitialPositioning:run() + -- locals for speed + local random = math.random + local vertices = self.vertices + local desired_vertices = self.desired_vertices + -- place vertices where the |desired at | option has been set first + local placed, centroid_x, centroid_y = InitialTemplate:desired(desired_vertices) + + for _, vertex in ipairs(vertices) do + -- place all other vertices with respect to the one already placed + if placed[vertex] == nil then + p = vertex.pos + p.x = 100 * random() + centroid_x + p.y = 100 * random() + centroid_y + end + end +end + +return RandomInitialPositioning
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/library.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/library.lua new file mode 100644 index 00000000000..4cc7128b16a --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/force/jedi/library.lua @@ -0,0 +1,115 @@ +-- Copyright 2014 by Ida Bruhns +-- +-- 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 information + + +--- The library providing the graph drawing framework Jedi +-- This labrary requires all graph drawing algorithms and inital +-- positioning algorithms provided with the first release of Jedi. +-- It also defines the mass key attached to all vertices. + +-- Library name +local jedi + +-- require inital positioning algorithms +require "pgf.gd.force.jedi.initialpositioning.CircularInitialPositioning" +require "pgf.gd.force.jedi.initialpositioning.RandomInitialPositioning" +require "pgf.gd.force.jedi.initialpositioning.GridInitialPositioning" + +-- require graph drawing algorithms +require "pgf.gd.force.jedi.algorithms.FruchtermanReingold" +require "pgf.gd.force.jedi.algorithms.HuSpringElectricalFW" +require "pgf.gd.force.jedi.algorithms.SimpleSpring" +require "pgf.gd.force.jedi.algorithms.SocialGravityCloseness" +require "pgf.gd.force.jedi.algorithms.SocialGravityDegree" + + +-- define parameter +local declare = require "pgf.gd.interface.InterfaceToAlgorithms".declare + +--- +declare { + key = "maximum displacement per step", + type = "length", + initial = "100", + documentation_in = "pgf.gd.force.jedi.doc" +} + +--- +declare { + key = "global speed factor", + type = "length", + initial = "1", + documentation_in = "pgf.gd.force.jedi.doc" +} + +--- +declare { + key = "maximum time", + type = "number", + initial = "50", + documentation_in = "pgf.gd.force.jedi.doc" +} + +--- +declare { + key = "find equilibrium", + type = "boolean", + initial = true, + documentation_in = "pgf.gd.force.jedi.doc" +} + +--- +declare { + key = "equilibrium threshold", + type = "number", + initial = "3", + documentation_in = "pgf.gd.force.jedi.doc" +} + +--- +declare { + key = "grid x length", + type = "length", + initial = "10pt", + documentation_in = "pgf.gd.force.jedi.doc" +} + +--- +declare { + key = "grid y length", + type = "length", + initial = "10pt", + documentation_in = "pgf.gd.force.jedi.doc" +} + +--- +declare { + key = "snap to grid", + type = "boolean", + initial = false, + documentation_in = "pgf.gd.force.jedi.doc" +} + +--- +declare { + key = "mass", + type = "number", + initial = "1", + + documentation_in = "pgf.gd.force.jedi.doc" +} + +--- +declare { + key = "coarsening weight", + type = "number", + initial = "1", + + documentation_in = "pgf.gd.force.jedi.doc" +} diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/interface/InterfaceCore.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/interface/InterfaceCore.lua index 3e5d947c736..8de6d96d48d 100644 --- a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/interface/InterfaceCore.lua +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/interface/InterfaceCore.lua @@ -7,7 +7,7 @@ -- -- See the file doc/generic/pgf/licenses/LICENSE for more information --- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/interface/InterfaceCore.lua,v 1.5 2013/03/07 18:17:14 tantau Exp $ +-- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/interface/InterfaceCore.lua,v 1.6 2014/02/24 10:40:32 tantau Exp $ @@ -57,14 +57,21 @@ local InterfaceCore = { -- The declared keys keys = {}, + -- The phase kinds + phase_kinds = {}, + -- Internals for handling the options stack option_stack = {}, option_cache_height = nil, option_initial = { - algorithm_phases = {} + algorithm_phases = { + ["preprocessing stack"] = {}, + ["edge routing stack"] = {}, + ["postprocessing stack"] = {}, + } }, option_aliases = { - [{}] = true -- dummy entry to make sure table is not empty + [{}] = true -- Remove, once Lua Link Bug is fixed }, -- Constant strings for special collection kinds. diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/interface/InterfaceToAlgorithms.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/interface/InterfaceToAlgorithms.lua index 586efa12067..0ea7bacf96a 100644 --- a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/interface/InterfaceToAlgorithms.lua +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/interface/InterfaceToAlgorithms.lua @@ -7,7 +7,7 @@ -- -- See the file doc/generic/pgf/licenses/LICENSE for more information --- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/interface/InterfaceToAlgorithms.lua,v 1.17 2013/12/20 14:44:46 tantau Exp $ +-- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/interface/InterfaceToAlgorithms.lua,v 1.18 2014/02/24 10:40:32 tantau Exp $ @@ -433,7 +433,14 @@ end --- -- This function is called by |declare| for ``algorithm --- keys.'' They are detected by the presence of the field |algorithm| +-- keys.'' These keys are normally used without a value as in just +-- |\graph[tree layout]|, but you can optionally pass a value to +-- them. In this case, this value must be the name of a \emph{phase} +-- and the algorithm of this phase will be set (and not the +-- default phase of the key), see the description of phases below for +-- details. +-- +-- Algorithm keys are detected by the presence of the field |algorithm| -- in the table |t| passed to |declare|. Here is an example of how it -- is used: --\begin{codeexample}[code only, tikz syntax=false] @@ -488,23 +495,28 @@ end -- drawing engine which ``phase'' of the graph drawing process your -- option applies to. Each time you select an algorithm later on -- through use of the algorithm's key, the algorithm for this phase --- will be set; algorithms of other phases will not be changed. So, --- for instance, when an algorithm is part of the spanning tree +-- will be set; algorithms of other phases will not be changed. +-- For instance, when an algorithm is part of the spanning tree -- computation, its phase will be |"spanning tree computation"| and -- using its key does not change the main algorithm, but only the -- algorithm used during the computation of a spanning tree for the -- current graph (in case this is needed by the main algorithm). In -- case the |phase| field is missing, the phase |main| is used. Thus, -- when no phase field is given, the key will change the main --- algorithm used to draw the graph. +-- algorithm used to draw the graph. -- -- Later on, the algorithm set for the current phase can be accessed -- through the special |algorithm_phases| field of |options| --- tables. The |algorithm_phases| table will contain a field for each --- phase for which some algorithm has been set. +-- tables. The |algorithm_phases| table will contain two fields for each +-- phase for which some algorithm has been set: One field is the name +-- of the phase and its value will be the most recently set algorithm +-- (class) set for this phase. The other field is the name of the +-- phase followed by |" stack"|. It will contain an array of all +-- algorithm classes that have been set for this key with the most +-- recently at the end. -- -- The following example shows the declaration of an algorithm that is --- the default for the phase |spanning tree computation|: +-- the default for the phase |"spanning tree computation"|: -- --\begin{codeexample}[code only, tikz syntax=false] -- --- @@ -525,7 +537,6 @@ end -- The algorithm is called as follows during a run of the main -- algorithms: -- --- --\begin{codeexample}[code only, tikz syntax=false] -- local graph = ... -- the graph object -- local spanning_algorithm_class = graph.options.algorithm_phases["spanning tree computation"] @@ -541,7 +552,10 @@ end -- be installed as the default algorithm for the phase. This can be -- done only once per phase. Furthermore, for such a default algorithm -- the |algorithm| key must be table, it may not be a string (in other --- words, all default algorithms are loaded immediately). +-- words, all default algorithms are loaded immediately). Accessing +-- the |algorithm_phases| table for a phase for which no algorithm has +-- been set will result in the default algorithm and the phase stack +-- will also contain this algorithm; otherwise the phase stack will be empty. -- -- (You cannot call this function directly, it is included for -- documentation purposes only.) @@ -587,6 +601,9 @@ local function declare_algorithm (t) -- Save in the algorithm_classes table: InterfaceCore.algorithm_classes[t.key] = store_me + assert(t.type == nil, "type may not be set for an algorithm key") + t.type = "string" + -- Install! InterfaceCore.binding:declareCallback(t) @@ -596,6 +613,11 @@ local function declare_algorithm (t) assert (type(store_me) == "table", "default algorithms must be loaded immediately") InterfaceCore.option_initial.algorithm_phases[t.phase] = store_me + InterfaceCore.option_initial.algorithm_phases[t.phase .. " stack"] = { store_me } + else + InterfaceCore.option_initial.algorithm_phases[t.phase .. " stack"] = { + dummy = true -- Remove once Lua Link Bug is fixed + } end return true diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/interface/InterfaceToC.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/interface/InterfaceToC.lua index 5b220f318bc..37db0b3d91e 100644 --- a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/interface/InterfaceToC.lua +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/interface/InterfaceToC.lua @@ -7,7 +7,7 @@ -- -- See the file doc/generic/pgf/licenses/LICENSE for more information --- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/interface/InterfaceToC.lua,v 1.6 2013/05/23 20:01:27 tantau Exp $ +-- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/interface/InterfaceToC.lua,v 1.7 2014/02/24 10:40:32 tantau Exp $ --- @@ -63,9 +63,9 @@ function InterfaceToC.declare_algorithm_written_in_c (t) for i=1,#edges do edges[edges[i]] = i end - collectgarbage("stop") -- BUG! Remove this when everything is linked against a SINGLE Lua lib at runtime + collectgarbage("stop") -- Remove once Lua Link Bug is fixed t.algorithm_written_in_c (self.digraph, back_table, edges, self) - collectgarbage("restart") -- Remove also! + collectgarbage("restart") -- Remove once Lua Link Bug is fixed end } end diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/interface/InterfaceToDisplay.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/interface/InterfaceToDisplay.lua index cc72dc5910a..a636e79b8ea 100644 --- a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/interface/InterfaceToDisplay.lua +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/interface/InterfaceToDisplay.lua @@ -7,7 +7,7 @@ -- -- See the file doc/generic/pgf/licenses/LICENSE for more information --- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/interface/InterfaceToDisplay.lua,v 1.12 2013/12/20 14:44:46 tantau Exp $ +-- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/interface/InterfaceToDisplay.lua,v 1.14 2014/03/19 09:20:59 tantau Exp $ @@ -183,7 +183,7 @@ function InterfaceToDisplay.runGraphDrawingAlgorithm() -- End timing: local stop = os.clock() - + return stop - start end @@ -577,7 +577,7 @@ function InterfaceToDisplay.pushOption(key, value, height) assert (algorithm, "algorithm class not found") push_on_option_stack(phase_unique, - { phase = key_record.phase, algorithm = algorithm }, + { phase = value or key_record.phase, algorithm = algorithm }, height) if key_record.phase == "main" then @@ -943,6 +943,15 @@ function get_current_options_table (height, table) local function handle (k, v) if k == phase_unique then algorithm_phases[v.phase] = v.algorithm + local phase_stack = v.phase .. " stack" + local t = rawget(algorithm_phases, phase_stack) + if not t then + t = algorithm_phases[phase_stack] + assert(type(t) == "table", "unknown phase") + t = lib.copy(t) + algorithm_phases[phase_stack] = t + end + t[#t + 1] = v.algorithm elseif k == collections_unique then LookupTable.addOne(collections, v) else diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/lib.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/lib.lua index dcfb468d063..aaa7f648a51 100644 --- a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/lib.lua +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/lib.lua @@ -7,7 +7,7 @@ -- -- See the file doc/generic/pgf/licenses/LICENSE for more information --- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/lib.lua,v 1.5 2013/04/04 20:43:45 tantau Exp $ +-- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/lib.lua,v 1.6 2014/02/24 10:40:32 tantau Exp $ @@ -351,6 +351,49 @@ function lib.class(t) end + +--- +-- Returns a method that is loaded only on demand for a class. +-- +-- The idea behind this function is that you may have a class (or just +-- a table) for which some methods are needed only seldomly. In this +-- case, you can put these methods in a separate file and then use +-- |ondemand| to indicate that the methods are found in a +-- another file. +-- +--\begin{codeexample}[code only] +-- -- File Foo.lua +-- local Foo = {} +-- function Foo.bar () ... end +-- function Foo.bar2 () ... end +-- Foo.bar3 = lib.ondemand("Foo_extra", Foo, "bar3") +-- Foo.bar4 = lib.ondemand("Foo_extra", Foo, "bar4") +-- +-- return Foo +-- +-- -- Foo_extra.lua +-- local Foo = require "Foo" +-- function Foo.bar3 () ... end +-- function Foo.bar4 () ... end +--\end{codeexample} +-- +-- @param filename The name of the file when extra methods are +-- located. +-- @param table The table for which the missing functions should be +-- loaded when they are accessed. +-- @param method The name of the method. +-- +-- @return A function that, when called, loads the filename using +-- |require| and, then, forwards the call to the method. + +function lib.ondemand(filename, table, name) + return function(...) + require (filename) + return table[name] (...) + end +end + + -- Done return lib
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/lib/Transform.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/lib/Transform.lua index 88ffd6446a4..d477c682f60 100644 --- a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/lib/Transform.lua +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/lib/Transform.lua @@ -7,7 +7,7 @@ -- -- See the file doc/generic/pgf/licenses/LICENSE for more information --- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/lib/Transform.lua,v 1.1 2012/11/27 17:24:26 tantau Exp $ +-- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/lib/Transform.lua,v 1.2 2014/02/24 10:40:32 tantau Exp $ --- @@ -99,6 +99,22 @@ function Transform.concat(a,b) end + +--- +-- Inverts a transformation matrix. +-- +-- @param t The transformation. +-- +-- @return The inverted transformation +-- +function Transform.invert(t) + local t1, t2, t3, t4 = t[1], t[2], t[3], t[4] + local idet = 1/(t1*t4 - t2*t3) + + return { t4*idet, -t2*idet, -t3*idet, t1*idet, -t[5], -t[6] } +end + + -- Done return Transform
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/model/Arc.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/model/Arc.lua index ff08573cbbd..5c2f10cd383 100644 --- a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/model/Arc.lua +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/model/Arc.lua @@ -7,7 +7,7 @@ -- -- See the file doc/generic/pgf/licenses/LICENSE for more information --- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/model/Arc.lua,v 1.6 2013/12/20 14:44:46 tantau Exp $ +-- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/model/Arc.lua,v 1.7 2015/04/21 14:10:00 tantau Exp $ --- @@ -30,14 +30,21 @@ -- |optionsXxxx| functions, that will search for options in all of the -- synactic edges that ``belong'' to an edge. -- --- Similarly, even though an arc has a |path| field, setting this --- field does not immediately set the paths of the syntactic --- edges. Indeed, you will normally want to setup and modify the --- |path| field of an arc during your algorithm and only at the very --- end, ``write it back'' to the multiple syntactic edges underlying --- the graph. For this purpose, the method |sync| is used, which is --- called automatically for the |ugraph| and |digraph| of a scope as --- well as for spanning trees. +-- In order to \emph{set} options of the edges, you can set the +-- |generate_options| field of an arc (which is |nil| by default), see +-- the |declare_parameter_sequence| function for the syntax. Similar +-- to the |path| field below, the options set in this table are +-- written back to the syntactic edges during a sync. +-- +-- In detail, the following happens: Even though an arc has a |path| +-- field and a |generated_options| field, setting these fields does +-- not immediately set the paths of the syntactic edges nor does it +-- generate options. Indeed, you will normally want to setup and +-- modify the |path| field of an arc during your algorithm and only at +-- the very end, ``write it back'' to the multiple syntactic edges +-- underlying the graph. For this purpose, the method |sync| is used, +-- which is called automatically for the |ugraph| and |digraph| of a +-- scope as well as for spanning trees. -- -- The bottom line concerning the |path| field is the following: If -- you just want a straight line along an arc, just leave the field as @@ -56,9 +63,12 @@ -- in case of a loop. -- @field path If non-nil, the path of the arc. See the description -- above. --- @field syntactic_edges This field is an array containing syntactic --- edges (``real'' edges in the syntactic digraph) that underly this --- arc. +-- @field generated_options If non-nil, some options to be passed back +-- to the original syntactic edges, see the description above. +-- @field syntactic_edges In case this arc is an arc in the syntatic +-- digraph (and only then), this field contains an array containing +-- syntactic edges (``real'' edges in the syntactic digraph) that +-- underly this arc. Otherwise, the field will be empty or |nil|. -- local Arc = {} Arc.__index = Arc @@ -434,13 +444,14 @@ end --- --- Sync an |Arc| with its syntactic edges. This causes the following: +-- Sync an |Arc| with its syntactic edges with respect to the path and +-- generated options. It causes the following to happen: -- If the |path| field of the arc is |nil|, nothing --- happens. Otherwise, a copy of the |path| is created. However, for --- every path element that is a function, this function is invoked --- with the syntactic edge as its parameter. The result of this call --- should now be a |Coordinate|, which will replace the function in --- the |Path|. +-- happens with respect to the path. Otherwise, a copy of the |path| +-- is created. However, for every path element that is a function, +-- this function is invoked with the syntactic edge as its +-- parameter. The result of this call should now be a |Coordinate|, +-- which will replace the function in the |Path|. -- -- You use this method like this: --\begin{codeexample}[code only, tikz syntax=false] @@ -451,6 +462,10 @@ end --arc:sync() --\end{codeexample} -- +-- Next, similar to the path, the field |generated_options| is +-- considered. If it is not |nil|, then all options listed in this +-- field are appended to all syntactic edges underlying the arc. +-- -- Note that this function will automatically be called for all arcs -- of the |ugraph|, the |digraph|, and the |spanning_tree| of an -- algorithm by the rendering pipeline. @@ -493,6 +508,26 @@ function Arc:sync() end end end + if self.generated_options then + local head = self.head + local tail = self.tail + local a = self.syntactic_digraph:arc(tail,head) + if a and #a.syntactic_edges>0 then + for _,e in ipairs(a.syntactic_edges) do + for _,o in ipairs(self.generated_options) do + e.generated_options[#e.generated_options+1] = o + end + end + end + local a = head ~= tail and self.syntactic_digraph:arc(head,tail) + if a and #a.syntactic_edges>0 then + for _,e in ipairs(a.syntactic_edges) do + for _,o in ipairs(self.generated_options) do + e.generated_options[#e.generated_options+1] = o + end + end + end + end end diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/model/Coordinate.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/model/Coordinate.lua index a3b0a7c20bf..8d11fe89d8f 100644 --- a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/model/Coordinate.lua +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/model/Coordinate.lua @@ -7,7 +7,7 @@ -- -- See the file doc/generic/pgf/licenses/LICENSE for more information --- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/model/Coordinate.lua,v 1.3 2013/05/23 20:01:27 tantau Exp $ +-- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/model/Coordinate.lua,v 1.4 2014/02/24 10:40:32 tantau Exp $ --- @@ -18,7 +18,9 @@ -- right and the $y$-axis goes up. -- -- @field x --- @field y +-- @field y +-- +-- There is also a static field called |origin| that is always equal to the origin. local Coordinate = {} Coordinate.__index = Coordinate @@ -43,6 +45,9 @@ function Coordinate.new(x,y) end +Coordinate.origin = Coordinate.new(0,0) + + --- Creates a new coordinate that is a copy of an existing one. -- -- @return A new coordinate at the same location as |self| @@ -56,7 +61,7 @@ end --- Apply a transformation matrix to a coordinate, -- see |pgf.gd.lib.Transform| for details. -- --- @param t A tansformation +-- @param t A tansformation. function Coordinate:apply(t) local x = self.x diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/model/Path.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/model/Path.lua index 03a7e7c695c..07cd78d34e1 100644 --- a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/model/Path.lua +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/model/Path.lua @@ -7,7 +7,7 @@ -- -- See the file doc/generic/pgf/licenses/LICENSE for more information --- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/model/Path.lua,v 1.2 2013/09/23 20:04:26 tantau Exp $ +-- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/model/Path.lua,v 1.3 2014/02/24 10:40:32 tantau Exp $ --- @@ -58,10 +58,12 @@ require("pgf.gd.model").Path = Path local Coordinate = require "pgf.gd.model.Coordinate" local Bezier = require "pgf.gd.lib.Bezier" +local lib = require "pgf.gd.lib" +-- Private function -local function rigid (x) +function Path.rigid (x) if type(x) == "function" then return x() else @@ -69,6 +71,7 @@ local function rigid (x) end end +local rigid = Path.rigid --- @@ -346,7 +349,7 @@ end -- Appends a |curveto| to the path. There can be either three -- coordinates (or functions) as parameters (the two support points -- and the target) or six numbers, where two consecutive numbers form a --- Coordinate. Which case is meant is detected by the presence of a +-- |Coordinate|. Which case is meant is detected by the presence of a -- sixth non-nil parameter. function Path:appendCurveto(a,b,c,d,e,f) @@ -363,6 +366,10 @@ function Path:appendCurveto(a,b,c,d,e,f) end + + + + --- -- Makes a path ``rigid,'' meaning that all coordinates that are only -- given as functions are replaced by the values these functions @@ -1183,7 +1190,53 @@ function Path:pad(padding) end - + +--- +-- Appends an arc (as in the sense of ``a part of the circumference of +-- a circle'') to the path. You may optionally provide a +-- transformation matrix, which will be applied to the arc. In detail, +-- the following happens: We first invert the transformation +-- and apply it to the start point. Then we compute the arc +-- ``normally'', as if no transformation matrix were present. Then we +-- apply the transformation matrix to all computed points. +-- +-- @function Path:appendArc(start_angle,end_angle,radius,trans) +-- +-- @param start_angle The start angle of the arc. Must be specified in +-- degrees. +-- @param end_angle the end angle of the arc. +-- @param radius The radius of the circle on which this arc lies. +-- @param trans A transformation matrix. If |nil|, the identity +-- matrix will be assumed. + +Path.appendArc = lib.ondemand("Path_arced", Path, "appendArc") + + + +--- +-- Appends a clockwise arc (as in the sense of ``a part of the circumference of +-- a circle'') to the path such that it ends at a given point. If a +-- transformation matrix is given, both start and end point are first +-- transformed according to the inverted transformation, then the arc +-- is computed and then transformed back. +-- +-- @function Path:appendArcTo(target,radius_or_center,clockwise,trans) +-- +-- @param target The point where the arc should end. +-- @param radius_or_center If a number, it is the radius of the circle +-- on which this arc lies. If it is a |Coordinate|, this is the center +-- of the circle. +-- @param clockwise If true, the arc will be clockwise. Otherwise (the +-- default, if nothing or |nil| is given), the arc will be counter +-- clockise. +-- @param trans A transformation matrix. If missing, +-- the identity matrix is assumed. + +Path.appendArcTo = lib.ondemand("Path_arced", Path, "appendArcTo") + + + + -- -- @return The Path as string. -- diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/model/Path_arced.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/model/Path_arced.lua new file mode 100644 index 00000000000..ace3825e350 --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/model/Path_arced.lua @@ -0,0 +1,316 @@ +-- Copyright 2014 by Till Tantau +-- +-- This file may be distributed an/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 information + +-- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/model/Path_arced.lua,v 1.2 2015/05/08 10:23:50 tantau Exp $ + + +local Path = require 'pgf.gd.model.Path' + +-- Imports + +local Coordinate = require "pgf.gd.model.Coordinate" +local Transform = require "pgf.gd.lib.Transform" + + + +-- Locals + +local rigid = Path.rigid + +local tan = math.tan +local sin = math.sin +local cos = math.cos +local sqrt = math.sqrt +local atan2 = math.atan2 +local abs = math.abs + +local to_rad = math.pi/180 +local to_deg = 180/math.pi +local pi_half = math.pi/2 + +local function sin_quarter(x) + x = x % 360 + if x == 0 then + return 0 + elseif x == 90 then + return 1 + elseif x == 180 then + return 0 + else + return -1 + end +end + +local function cos_quarter(x) + x = x % 360 + if x == 0 then + return 1 + elseif x == 90 then + return 0 + elseif x == 180 then + return -1 + else + return 0 + end +end + +local function atan2deg(y,x) + + -- Works like atan2, but returns the angle in degrees and, returns + -- exactly a multiple of 90 if x or y are zero + + if x == 0 then + if y < 0 then + return -90 + else + return 90 + end + elseif y == 0 then + if x < 0 then + return 180 + else + return 0 + end + else + return atan2(y,x) * to_deg + end + +end + +local function subarc (path, startx, starty, start_angle, delta, radius, trans, center_x, center_y) + + local end_angle = start_angle + delta + local factor = tan (delta*to_rad/4) * 1.333333333333333333333 * radius + + local s1, c1, s190, c190, s2, c2, s290, c290 + + if start_angle % 90 == 0 then + s1, c1, s190, c190 = sin_quarter(start_angle), cos_quarter(start_angle), sin_quarter(start_angle+90), cos_quarter(start_angle+90) + else + local a1 = start_angle*to_rad + s1, c1, s190, c190 = sin(a1), cos(a1), sin(a1+pi_half), cos(a1+pi_half) + end + + if end_angle % 90 == 0 then + s2, c2, s290, c290 = sin_quarter(end_angle), cos_quarter(end_angle), sin_quarter(end_angle-90), cos_quarter(end_angle-90) + else + local a2 = end_angle * to_rad + s2, c2, s290, c290 = sin(a2), cos(a2), sin(a2-pi_half), cos(a2-pi_half) + end + + local lastx, lasty = center_x + c2*radius, center_y + s2*radius + + path[#path + 1] = "curveto" + path[#path + 1] = Coordinate.new (startx + c190*factor, starty + s190*factor) + path[#path + 1] = Coordinate.new (lastx + c290*factor, lasty + s290*factor) + path[#path + 1] = Coordinate.new (lastx, lasty) + + if trans then + path[#path-2]:apply(trans) + path[#path-1]:apply(trans) + path[#path ]:apply(trans) + end + + return lastx, lasty, end_angle +end + + + +local function arc (path, start, start_angle, end_angle, radius, trans, centerx, centery) + + -- @param path is the path object + -- @param start is the start coordinate + -- @param start_angle is given in degrees + -- @param end_angle is given in degrees + -- @param radius is the radius + -- @param trans is an optional transformation matrix that gets applied to all computed points + -- @param centerx optionally: x-part of the center of the circle + -- @param centery optionally: y-part of the center of the circle + + local startx, starty = start.x, start.y + + -- Compute center: + centerx = centerx or startx - cos(start_angle*to_rad)*radius + centery = centery or starty - sin(start_angle*to_rad)*radius + + if start_angle < end_angle then + -- First, ensure that the angles are in a reasonable range: + start_angle = start_angle % 360 + end_angle = end_angle % 360 + + if end_angle <= start_angle then + -- In case the modulo has inadvertedly moved the end angle + -- before the start angle: + end_angle = end_angle + 360 + end + + -- Ok, now create a series of arcs that are at most quarter-cycles: + while start_angle < end_angle do + if start_angle + 179 < end_angle then + -- Add a quarter cycle: + startx, starty, start_angle = subarc(path, startx, starty, start_angle, 90, radius, trans, centerx, centery) + elseif start_angle + 90 < end_angle then + -- Add 60 degrees to ensure that there are no small segments + -- at the end + startx, starty, start_angle = subarc(path, startx, starty, start_angle, (end_angle-start_angle)/2, radius, trans, centerx, centery) + else + subarc(path, startx, starty, start_angle, end_angle - start_angle, radius, trans, centerx, centery) + break + end + end + + elseif start_angle > end_angle then + -- First, ensure that the angles are in a reasonable range: + start_angle = start_angle % 360 + end_angle = end_angle % 360 + + if end_angle >= start_angle then + -- In case the modulo has inadvertedly moved the end angle + -- before the start angle: + end_angle = end_angle - 360 + end + + -- Ok, now create a series of arcs that are at most quarter-cycles: + while start_angle > end_angle do + if start_angle - 179 > end_angle then + -- Add a quarter cycle: + startx, starty, start_angle = subarc(path, startx, starty, start_angle, -90, radius, trans, centerx, centery) + elseif start_angle - 90 > end_angle then + -- Add 60 degrees to ensure that there are no small segments + -- at the end + startx, starty, start_angle = subarc(path, startx, starty, start_angle, (end_angle-start_angle)/2, radius, trans, centerx, centery) + else + subarc(path, startx, starty, start_angle, end_angle - start_angle, radius, trans, centerx, centery) + break + end + end + + -- else, do nothing + end +end + + +-- Doc see Path.lua + +function Path:appendArc(start_angle,end_angle,radius, trans) + + local start = rigid(self[#self]) + assert(type(start) == "table", "trying to append an arc to a path that does not end with a coordinate") + + if trans then + start = start:clone() + start:apply(Transform.invert(trans)) + end + + arc (self, start, start_angle, end_angle, radius, trans) +end + + + + +-- Doc see Path.lua + +function Path:appendArcTo (target, radius_or_center, clockwise, trans) + + local start = rigid(self[#self]) + assert(type(start) == "table", "trying to append an arc to a path that does not end with a coordinate") + + local trans_target = target + local centerx, centery, radius + + if type(radius_or_center) == "number" then + radius = radius_or_center + else + centerx, centery = radius_or_center.x, radius_or_center.y + end + + if trans then + start = start:clone() + trans_target = target:clone() + local itrans = Transform.invert(trans) + start:apply(itrans) + trans_target:apply(itrans) + if centerx then + local t = radius_or_center:clone() + t:apply(itrans) + centerx, centery = t.x, t.y + end + end + + if not centerx then + -- Compute center + local dx, dy = target.x - start.x, target.y - start.y + + if abs(dx) == abs(dy) and abs(dx) == radius then + if (dx < 0 and dy < 0) or (dx > 0 and dy > 0) then + centerx = start.x + centery = trans_target.y + else + centerx = trans_target.x + centery = start.y + end + else + local l_sq = dx*dx + dy*dy + if l_sq >= radius*radius*4*0.999999 then + centerx = (start.x+trans_target.x) / 2 + centery = (start.y+trans_target.y) / 2 + assert(l_sq <= radius*radius*4/0.999999, "radius too small for arc") + else + -- Normalize + local l = sqrt(l_sq) + local nx = dx / l + local ny = dy / l + + local e = sqrt(radius*radius - 0.25*l_sq) + + centerx = start.x + 0.5*dx - ny*e + centery = start.y + 0.5*dy + nx*e + end + end + end + + local start_dx, start_dy, target_dx, target_dy = + start.x - centerx, start.y - centery, + trans_target.x - centerx, trans_target.y - centery + + if not radius then + -- Center is given, compute radius: + radius_sq = start_dx^2 + start_dy^2 + + -- Ensure that the circle is, indeed, centered: + assert (abs(target_dx^2 + target_dy^2 - radius_sq)/radius_sq < 1e-5, "attempting to add an arc with incorrect center") + + radius = sqrt(radius_sq) + end + + -- Compute start and end angle: + local start_angle = atan2deg(start_dy, start_dx) + local end_angle = atan2deg(target_dy, target_dx) + + if clockwise then + if end_angle > start_angle then + end_angle = end_angle - 360 + end + else + if end_angle < start_angle then + end_angle = end_angle + 360 + end + end + + arc (self, start, start_angle, end_angle, radius, trans, centerx, centery) + + -- Patch last point to avoid rounding problems: + self[#self] = target +end + + + +-- Done + +return true
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/pedigrees.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/pedigrees.lua new file mode 100644 index 00000000000..72bb3e904ee --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/pedigrees.lua @@ -0,0 +1,21 @@ +-- Copyright 2015 by Till Tantau +-- +-- This file may be distributed an/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 information + +--- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/pedigrees.lua,v 1.1 2015/03/12 15:58:20 tantau Exp $ + + +local pedigrees = {} + +-- Declare namespace +require("pgf.gd").pedigrees = tree + + +-- Done + +return pedigrees
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/pedigrees/Koerner2015.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/pedigrees/Koerner2015.lua new file mode 100644 index 00000000000..460aaaed905 --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/pedigrees/Koerner2015.lua @@ -0,0 +1,162 @@ +-- Copyright 2015 by Till Tantau +-- +-- This file may be distributed an/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 information + +-- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/pedigrees/Koerner2015.lua,v 1.1 2015/03/12 15:58:23 tantau Exp $ + + +local Koerner2015 = {} + + +-- Namespace +require("pgf.gd.pedigrees").Koerner2015 = Koerner2015 + +-- Imports +local InterfaceToAlgorithms = require "pgf.gd.interface.InterfaceToAlgorithms" +local Storage = require "pgf.gd.lib.Storage" +local Direct = require "pgf.gd.lib.Direct" + +-- Shorthand: +local declare = InterfaceToAlgorithms.declare + + +--- +declare { + key = "mate", + type = "boolean", + + summary = [[" + Edges of type |mate| join mates. + "]], +} + + +--- +declare { + key = "child", + type = "boolean", + + summary = [[" + Edges of type |child| join a parent to a child. The parent is the tail of the edge, the child is the head. + "]], +} + +--- +declare { + key = "sibling", + type = "boolean", + + summary = [[" + Edges of type |sibling| join a siblings (persons with identical parents). + "]], +} + + +--- +declare { + key = "simple pedigree layout", + algorithm = Koerner2015, + + postconditions = { + upward_oriented = true + }, + + summary = [[" + A simple algorithm for drawing a pedigree. + "]], + documentation = [[" + ... + "]], + examples = [[" + \tikz \graph [simple pedigree layout, default edge operator=complete bipartite] + { + Eve -- [mate] Felix; + { Eve, Felix } -> [child] { George, Hank }; + + Alice -- [mate] Bob; + { Alice, Bob } -> [child] { Charly, Dave, Eve }; + }; + "]] +} + + +function Koerner2015:run() + + local g = self.digraph + + -- Compute ranks: + + local visited = {} + local ranks = {} + + local queue = { { g.vertices[1], 1 } } + + local queue_start = 1 + local queue_end = 1 + + local function put(v, r) + queue_end = queue_end + 1 + queue [queue_end] = { v, r } + end + + local function get() + local v = queue[queue_start][1] + local r = queue[queue_start][2] + queue_start = queue_start + 1 + return v,r + end + + while queue_start <= queue_end do + + -- Pop + local v, rank = get() + ranks[v] = rank + + visited [v] = true + + -- Follow mates: + for _,a in ipairs(g:outgoing(v)) do + if a:options("sibling") then + if not visited[a.head] then + put(a.head, rank) + end + end + end + for _,a in ipairs(g:incoming(v)) do + if a:options("child") then + if not visited[a.tail] then + put(a.tail, rank-1) + end + end + end + for _,a in ipairs(g:outgoing(v)) do + if a:options("child") then + if not visited[a.head] then + put(a.head, rank+1) + end + end + end + for _,a in ipairs(g:outgoing(v)) do + if a:options("mate") then + if not visited[a.head] then + put(a.head, rank) + end + end + end + end + + for i,v in ipairs(g.vertices) do + v.pos.x = i*50 + v.pos.y = ranks[v] * 50 + end + +end + +return Koerner2015 + + diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/pedigrees/library.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/pedigrees/library.lua new file mode 100644 index 00000000000..4e6000d038f --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/pedigrees/library.lua @@ -0,0 +1,21 @@ +-- Copyright 2015 by Till Tantau +-- +-- This file may be distributed an/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 information + +-- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/pedigrees/library.lua,v 1.1 2015/03/12 15:58:23 tantau Exp $ + + + +--- +-- A pedigree depicts parent--mate--sibling relationships between individuals. +-- +-- @library + +local pedigrees -- Library name + +require "pgf.gd.pedigrees.Koerner2015" diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/routing.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/routing.lua new file mode 100644 index 00000000000..0dd9659852e --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/routing.lua @@ -0,0 +1,22 @@ +-- Copyright 2012 by Till Tantau +-- +-- This file may be distributed an/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 information + +--- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/routing.lua,v 1.1 2014/02/24 10:40:32 tantau Exp $ + + + +local routing = {} + +-- Declare namespace +require("pgf.gd").routing = routing + + +-- Done + +return routing
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/routing/Hints.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/routing/Hints.lua new file mode 100644 index 00000000000..46c337090f4 --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/routing/Hints.lua @@ -0,0 +1,100 @@ +-- Copyright 2014 by Till Tantau +-- +-- This file may be distributed an/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 information + +-- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/routing/Hints.lua,v 1.2 2015/05/18 17:01:16 tantau Exp $ + + +--- +-- The |Hints| class provides a way for graph drawing algorithms to +-- communicate certain possibilities concerning the routing of edges +-- to edge routing algorithms. This partly decouples the choice of the +-- vertex positioning algorithms from the choice of edge routing +-- algorithm. For instance, for a simple necklace routing, it is +-- unclear whether the edges on the necklace should be routing ``along +-- the necklace'' or not. Thus, necklace routing algoirthms will +-- ``hint'' that a necklace is present and only when the +-- |necklace routing| algorithm is selected will these hints lead to +-- actual bending of edges. +-- +-- For each kind of hint, there are methods in this class for creating +-- the hints and other methods for reading them. Hints are always +-- local to the ugraph. + +local Hints = {} + +-- Namespace +require("pgf.gd.routing").Hints = Hints + +-- Imports +local Storage = require("pgf.gd.lib.Storage") +local Coordinate = require("pgf.gd.model.Coordinate") + + + + +-- The necklace storage + +local necklaces = Storage.new() + + +--- +-- Adds a necklace hint. In this case, the hint indicates that the +-- given sequence of vertices lie on a circle. +-- +-- The idea is that an algorithm may specify that in a +-- given graph certain sequences of nodes form a ``necklace,'' which +-- is typically a circle. There may be more than one necklace inside a +-- given graph. For each necklace, +-- whenever an arc connects subsequent nodes on the necklace, they get +-- bend in such a way that they lie follow the path of the +-- necklace. If an arc lies on more than one necklace, the ``last one +-- wins.'' +-- +-- @param ugraph The ugraph to which this hint is added +-- @param necklace The sequence of vertices that form the necklace. If +-- the necklace is closed, the last vertex must equal the first one. +-- @param center If provided, must be |Coordinate| that specifies the +-- center of the circle on which the vertices lie. If not provided, +-- the origin is assumed. +-- @param clockwise If |true|, the vertices are in clockwise order, +-- otherwise in counter-clockwise order. + +function Hints.addNecklaceCircleHint(ugraph, necklace, center, clockwise) + local a = necklaces[ugraph] or {} + necklaces[ugraph] = a + + a[#a+1] = { + necklace = necklace, + center = center or Coordinate.origin, + clockwise = clockwise + } +end + + +--- +-- Gets the necklace hints. +-- +-- This function will return an array whose entries are necklace +-- hints. Each entry in the array has a |necklace| field, which is the +-- field passed to the |addNecklaceXxxx| methods. For a circle +-- necklace, the |center| and |clockwise| fields will be set. (Other +-- necklaces are not yet implemented.) +-- +-- @param ugraph The ugraph for which the necklace hints are +-- requested. +-- @return The array of necklaces as described above. + +function Hints.getNecklaceHints(ugraph) + return necklaces[ugraph] or {} +end + +-- done + +return Hints + diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/routing/NecklaceRouting.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/routing/NecklaceRouting.lua new file mode 100644 index 00000000000..23a9d265923 --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/routing/NecklaceRouting.lua @@ -0,0 +1,90 @@ +-- Copyright 2014 by Till Tantau +-- +-- This file may be distributed an/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 information + +-- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/routing/NecklaceRouting.lua,v 1.1 2014/04/28 12:28:46 tantau Exp $ + + +-- The class; it processes necklace hints. + +local NecklaceRouting = {} + + +-- Namespace +require("pgf.gd.routing").NecklaceRouting = NecklaceRouting + +-- Imports +local declare = require("pgf.gd.interface.InterfaceToAlgorithms").declare + +local Hints = require "pgf.gd.routing.Hints" +local Path = require "pgf.gd.model.Path" + + +--- +declare { + key = "necklace routing", + algorithm = NecklaceRouting, + + phase = "edge routing", + + summary = "Bends all edges of a graph that lie on ``necklaces'' along these necklaces.", + + documentation = [[" + Some graph drawing algorithms lay out some or all nodes along a + path, which is then called a \emph{necklace.} For instance, the + |simple necklace layout| places all nodes on a circle and that + circle is the ``necklace.'' When the |necklace rounting| edge + routing algorithm is selected, all edges that connect subsequent + nodes on such a necklace are bend in such a way that the + ``follow the necklace path.'' In the example case, this will + cause all edges that connect adjacent nodes to become arcs on + of the circle on which the nodes lie. + + Note that local edge routing options for an edge may overrule + the edge routing computed by the algorithm as in the edge from 6 + to 7 in the example. + "]], + + examples = [[" + \tikz \graph [simple necklace layout, node distance=1.5cm, + necklace routing, + nodes={draw,circle}, edges={>={Stealth[round,sep,bend]}}] + { 1 -> 2 [minimum size=30pt] <- 3 <-> 4 -- + 5 -- 6 -- [bend left] 7 -- 1 -- 4 }; + "]] +} + + + +-- The implementation + +function NecklaceRouting:run() + local ugraph = self.ugraph + + for _,entry in ipairs(Hints.getNecklaceHints(ugraph)) do + assert (entry.center) -- no other necklace types, yet + local prev + for _,vertex in ipairs(entry.necklace) do + if prev then + local a = ugraph:arc(prev, vertex) + if a then + local p = Path.new() + p:appendMoveto(a.tail.pos:clone()) + p:appendArcTo(a.head.pos:clone(), entry.center, entry.clockwise) + a.path = p + end + end + prev = vertex + end + end +end + + +-- done + +return NecklaceRouting
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/routing/library.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/routing/library.lua new file mode 100644 index 00000000000..80364d11a39 --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/routing/library.lua @@ -0,0 +1,29 @@ +-- Copyright 2012 by Till Tantau +-- +-- This file may be distributed an/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 information + +-- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/routing/library.lua,v 1.1 2014/02/24 10:40:33 tantau Exp $ + + +-- Imports +local declare = require "pgf.gd.interface.InterfaceToAlgorithms".declare + +--- +-- This library contains algorithms for routing edges through a graph. +-- +-- @library + +local routing -- Library name + +-- Load declarations from: + +-- Load algorithms from: +require "pgf.gd.routing.NecklaceRouting" + + +-- General declarations diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/trees/ReingoldTilford1981.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/trees/ReingoldTilford1981.lua index 2bcade8b967..c808607385b 100644 --- a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/trees/ReingoldTilford1981.lua +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/trees/ReingoldTilford1981.lua @@ -7,7 +7,7 @@ -- -- See the file doc/generic/pgf/licenses/LICENSE for more information --- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/trees/ReingoldTilford1981.lua,v 1.10 2013/05/23 20:01:29 tantau Exp $ +-- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/trees/ReingoldTilford1981.lua,v 1.11 2014/03/19 09:20:59 tantau Exp $ @@ -37,7 +37,7 @@ declare { upward_oriented = true }, - documentation_in = "pgf.gd.doc.trees.ReingoldTilford1981" + documentation_in = "pgf.gd.trees.doc" } @@ -45,7 +45,7 @@ declare { declare { key = "missing nodes get space", type = "boolean", - documentation_in = "pgf.gd.doc.trees.ReingoldTilford1981" + documentation_in = "pgf.gd.trees.doc" } @@ -55,7 +55,7 @@ declare { key = "significant sep", type = "length", initial = "0", - documentation_in = "pgf.gd.doc.trees.ReingoldTilford1981" + documentation_in = "pgf.gd.trees.doc" } @@ -67,7 +67,7 @@ declare { { key = "minimum number of children" , value=2 }, { key = "significant sep", value = 10 }, }, - documentation_in = "pgf.gd.doc.trees.ReingoldTilford1981" + documentation_in = "pgf.gd.trees.doc" } --- @@ -79,7 +79,7 @@ declare { { key = "missing nodes get space" }, { key = "significant sep", value = 0 }, }, - documentation_in = "pgf.gd.doc.trees.ReingoldTilford1981" + documentation_in = "pgf.gd.trees.doc" } diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/doc/trees/ReingoldTilford1981.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/trees/doc.lua index 794214c5f74..09c35611723 100644 --- a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/doc/trees/ReingoldTilford1981.lua +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/trees/doc.lua @@ -7,7 +7,7 @@ -- -- See the file doc/generic/pgf/licenses/LICENSE for more information --- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/doc/trees/ReingoldTilford1981.lua,v 1.1 2013/03/05 23:44:30 tantau Exp $ +-- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/trees/doc.lua,v 1.1 2014/03/19 09:20:59 tantau Exp $ local key = require 'pgf.gd.doc'.key diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/tex/pgflibrarygraphdrawing.code.tex b/Master/texmf-dist/tex/generic/pgf/graphdrawing/tex/pgflibrarygraphdrawing.code.tex index 02d4d8ffa30..ad648c29402 100644 --- a/Master/texmf-dist/tex/generic/pgf/graphdrawing/tex/pgflibrarygraphdrawing.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/tex/pgflibrarygraphdrawing.code.tex @@ -8,7 +8,7 @@ % % See the file doc/generic/pgf/licenses/LICENSE for more details. -\ProvidesFileRCS[v\pgfversion] $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/tex/pgflibrarygraphdrawing.code.tex,v 1.38 2013/08/28 11:47:35 tantau Exp $ +\ProvidesFileRCS[v\pgfversion] $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/tex/pgflibrarygraphdrawing.code.tex,v 1.39 2015/06/08 21:58:24 tantau Exp $ @@ -978,6 +978,14 @@ } + +% The following is used to ensure that if we need to resume the graph +% drawing (through co-routines), we pass control back to TeX +% first. Otherwise, new text input levels are created and there may be +% only 15 of these... +\newif\ifpgfgdresumecoroutine + + % Ends a graph drawing scope % % Description: @@ -988,14 +996,22 @@ % See \pgfgdbeginscope \def\pgfgdendscope{% + \pgfgdresumecoroutinefalse% \directlua{ pgf.gd.interface.InterfaceToDisplay.runGraphDrawingAlgorithm() - } - \endgroup + }% + \pgfutil@loop% + \ifpgfgdresumecoroutine% + \pgfgdresumecoroutinefalse% + \directlua{ + pgf.gd.interface.InterfaceToDisplay.resumeGraphDrawingCoroutine() + }% + \pgfutil@repeat% + \endgroup% % Late positioning has ended - \directlua{pgf.gd.interface.InterfaceToDisplay.renderGraph()} - \directlua{pgf.gd.interface.InterfaceToDisplay.endGraphDrawingScope()} - \endgroup + \directlua{pgf.gd.interface.InterfaceToDisplay.renderGraph()}% + \directlua{pgf.gd.interface.InterfaceToDisplay.endGraphDrawingScope()}% + \endgroup% } diff --git a/Master/texmf-dist/tex/generic/pgf/libraries/luamath/pgf/luamath/functions.lua b/Master/texmf-dist/tex/generic/pgf/libraries/luamath/pgf/luamath/functions.lua new file mode 100644 index 00000000000..8fc963d8b9e --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/libraries/luamath/pgf/luamath/functions.lua @@ -0,0 +1,626 @@ +-- Copyright 2011 by Christophe Jorssen +-- +-- 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. +-- +-- $Id: functions.lua,v 1.3 2015/05/10 20:34:13 cfeuersaenger Exp $ +-- + +local pgfluamathfunctions = pgfluamathfunctions or {} + +-- Maps function names to their function. +-- +-- Note that this allows to register functions which are not in pgfluamathfunctions. +-- +-- Note that the string keys are not necessarily the same as the function +-- names. In particular, the math expression "not(1,1)" will execute notPGF(1,1) +-- +-- Note that each function which is added to pgfluamathfunctions will _automatically_ be inserted into this map, see __newindex. +-- (I fear it will not be erased directly...) +pgfluamathfunctions.stringToFunctionMap = {} + +local newFunctionAllocatedCallback = function(table,key,value) + local keyName = tostring(key):gsub("PGF","") + if not value then + stringToFunctionMap[keyName] = nil + elseif type(value) == 'function' then + -- remember it, and strip PGF suffix (i.e. remember 'not' instead of 'notPGF') + pgfluamathfunctions.stringToFunctionMap[keyName] = value + end + rawset(table,key,value) +end + +setmetatable(pgfluamathfunctions, { __newindex = newFunctionAllocatedCallback }) + +local mathabs, mathacos, mathasin = math.abs, math.acos, math.asin +local mathatan, mathceil = math.atan, math.ceil +local mathcos, mathdeg = math.cos, math.deg +local mathexp, mathfloor, mathfmod = math.exp, math.floor, math.fmod +local mathlog, mathmax = math.log, math.max +local mathmin, mathpi = math.min, math.pi +local mathrad, mathrandom = math.rad, math.random +local mathrandomseed, mathsin = math.randomseed, math.sin +local mathsqrt = math.sqrt +local mathtan = math.tan + +local trigFormatToRadians = mathrad + +local radiansToTrigFormat = mathdeg + +pgfluamathfunctions.TrigFormat = { 'deg', 'rad' } +pgfluamathfunctions.stringToFunctionMap["TrigFormat"] = nil + +-- choice is one of the valid choices in TrigFormat. +function pgfluamathfunctions.setTrigFormat(choice) + if choice == 'deg' then + trigFormatToRadians = mathrad + radiansToTrigFormat = mathdeg + elseif choice == 'rad' then + local identity = function(x) return x end + trigFormatToRadians = identity + radiansToTrigFormat = identity + else + error("The argument '" .. tostring(choice) .. "' is no valid choice for setTrigFormat.") + end +end +pgfluamathfunctions.stringToFunctionMap["setTrigFormat"] = nil + +pgfluamathfunctions.setRandomSeed = mathrandomseed +pgfluamathfunctions.stringToFunctionMap["setRandomSeed"] = nil + +------------------------------------------- + +function pgfluamathfunctions.add(x,y) + return x+y +end + +function pgfluamathfunctions.subtract(x,y) + return x-y +end + +function pgfluamathfunctions.neg(x) + return -x +end + +function pgfluamathfunctions.multiply(x,y) + return x*y +end + +function pgfluamathfunctions.veclen(x,y) + return mathsqrt(x*x+y*y) +end + +function pgfluamathfunctions.divide(x,y) + return x/y +end + +function pgfluamathfunctions.div(x,y) + return mathfloor(x/y) +end + +function pgfluamathfunctions.pow(x,y) + -- do not use math.pow -- it is deprecated as of LUA 5.3 + return x^y +end + +function pgfluamathfunctions.factorial(x) +-- TODO: x must be an integer + if x == 0 then + return 1 + else + return x * pgfluamathfunctions.factorial(x-1) + end +end + +function pgfluamathfunctions.ifthenelse(x,y,z) + if x~= 0 then + return y + else + return z + end +end + +function pgfluamathfunctions.equal(x,y) + if x == y then + return 1 + else + return 0 + end +end + +function pgfluamathfunctions.greater(x,y) + if x > y then + return 1 + else + return 0 + end +end + +function pgfluamathfunctions.less(x,y) + if x < y then + return 1 + else + return 0 + end +end + +function pgfluamathfunctions.min(x,y) + return mathmin(x,y) +end + +function pgfluamathfunctions.max(x,y) + return mathmax(x,y) +end + +function pgfluamathfunctions.notequal(x,y) + if x ~= y then + return 1 + else + return 0 + end +end + +function pgfluamathfunctions.notless(x,y) + if x >= y then + return 1 + else + return 0 + end +end + +function pgfluamathfunctions.notgreater(x,y) + if x <= y then + return 1 + else + return 0 + end +end + +function pgfluamathfunctions.andPGF(x,y) + if (x ~= 0) and (y ~= 0) then + return 1 + else + return 0 + end +end + +function pgfluamathfunctions.orPGF(x,y) + if (x ~= 0) or (y ~= 0) then + return 1 + else + return 0 + end +end + +function pgfluamathfunctions.notPGF(x) + if x == 0 then + return 1 + else + return 0 + end +end + +function pgfluamathfunctions.pi() + return mathpi +end + +function pgfluamathfunctions.e() + return mathexp(1) +end + +function pgfluamathfunctions.abs(x) + return mathabs(x) +end + +function pgfluamathfunctions.floor(x) + return mathfloor(x) +end + +function pgfluamathfunctions.ceil(x) + return mathceil(x) +end + +function pgfluamathfunctions.exp(x) + return mathexp(x) +end + +function pgfluamathfunctions.ln(x) + return mathlog(x) +end + +local logOf10 = mathlog(10) +function pgfluamathfunctions.log10(x) + return mathlog(x) / logOf10 +end + +local logOf2 = mathlog(2) +function pgfluamathfunctions.log2(x) + return mathlog(x) / logOf2 +end + +function pgfluamathfunctions.sqrt(x) + return mathsqrt(x) +end + +function pgfluamathfunctions.sign(x) + if x < 0 then + return -1.0 + elseif x == 0 then + return 0.0 + else + return 1.0 + end +end +function pgfluamathfunctions.real(x) + -- "ensure that x contains a decimal point" is kind of a no-op here, isn't it!? + return x +end + +function pgfluamathfunctions.rnd() + return mathrandom() +end + +function pgfluamathfunctions.rand() + return -1 + mathrandom() *2 +end + +function pgfluamathfunctions.random(x,y) + if x == nil and y == nil then + return mathrandom() + elseif y == nil then + return mathrandom(x) + else + return mathrandom(x,y) + end +end + +function pgfluamathfunctions.deg(x) + return mathdeg(x) +end + +function pgfluamathfunctions.rad(x) + return mathrad(x) +end + +function pgfluamathfunctions.round(x) + if x<0 then + return -mathfloor(mathabs(x)+0.5) + else + return mathfloor(x + 0.5) + end +end + +function pgfluamathfunctions.gcd(a, b) + if b == 0 then + return a + else + return pgfluamathfunctions.gcd(b, a%b) + end +end + +function pgfluamathfunctions.isprime(a) + local ifisprime = true + if a == 1 then + ifisprime = false + elseif a == 2 then + ifisprime = true +-- if a > 2 then + else + local i, imax = 2, mathceil(mathsqrt(a)) + 1 + while ifisprime and (i < imax) do + if pgfluamathfunctions.gcd(a,i) ~= 1 then + ifisprime = false + end + i = i + 1 + end + end + if ifisprime then + return 1 + else + return 0 + end +end + + +function pgfluamathfunctions.split_braces_to_explist(s) + -- (Thanks to mpg and zappathustra from fctt) + -- Make unpack available whatever lua version is used + -- (unpack in lua 5.1 table.unpack in lua 5.2) + local unpack = table.unpack or unpack + local t = {} + for i in s:gmatch('%b{}') do + table.insert(t, tonumber(i:sub(2, -2))) + end + return unpack(t) +end + +function pgfluamathfunctions.split_braces_to_table(s) + local t = {} + for i in s:gmatch('%b{}') do + table.insert(t, tonumber(i:sub(2, -2))) + end + return t +end + +function pgfluamathfunctions.mathtrue() + return 1.0 +end +pgfluamathfunctions.stringToFunctionMap["true"] = pgfluamathfunctions.mathtrue + +function pgfluamathfunctions.mathfalse() + return 0.0 +end +pgfluamathfunctions.stringToFunctionMap["false"] = pgfluamathfunctions.mathfalse + +function pgfluamathfunctions.frac(a) + -- should be positive, apparently + return mathabs(a - pgfluamathfunctions.int(a)) +end + +function pgfluamathfunctions.int(a) + if a < 0 then + return -mathfloor(mathabs(a)) + else + return mathfloor(a) + end +end + +function pgfluamathfunctions.iseven(a) + if (a % 2) == 0 then + return 1.0 + else + return 0.0 + end +end + +function pgfluamathfunctions.isodd(a) + if (a % 2) == 0 then + return 0.0 + else + return 1.0 + end +end + +function pgfluamathfunctions.mod(x,y) + if x/y < 0 then + return -(mathabs(x)%mathabs(y)) + else + return mathabs(x)%mathabs(y) + end +end + +function pgfluamathfunctions.Mod(x,y) + local tmp = pgfluamathfunctions.mod(x,y) + if tmp < 0 then + tmp = tmp + y + end + return tmp +end + +function pgfluamathfunctions.Sin(x) + return mathsin(trigFormatToRadians(x)) +end +pgfluamathfunctions.sin=pgfluamathfunctions.Sin + + +function pgfluamathfunctions.cosh(x) + -- math.cosh is deprecated as of LUA 5.3 . reimplement it: + return 0.5* (mathexp(x) + mathexp(-x)) +end +function pgfluamathfunctions.sinh(x) + -- math.sinh is deprecated as of LUA 5.3 . reimplement it: + return 0.5* (mathexp(x) - mathexp(-x)) +end + +local sinh = pgfluamathfunctions.sinh +local cosh = pgfluamathfunctions.cosh +function pgfluamathfunctions.tanh(x) + -- math.tanh is deprecated as of LUA 5.3 . reimplement it: + return sinh(x)/cosh(x) +end + +function pgfluamathfunctions.Cos(x) + return mathcos(trigFormatToRadians(x)) +end +pgfluamathfunctions.cos=pgfluamathfunctions.Cos + +function pgfluamathfunctions.Tan(x) + return mathtan(trigFormatToRadians(x)) +end +pgfluamathfunctions.tan=pgfluamathfunctions.Tan + +function pgfluamathfunctions.aSin(x) + return radiansToTrigFormat(mathasin(x)) +end +pgfluamathfunctions.asin=pgfluamathfunctions.aSin + +function pgfluamathfunctions.aCos(x) + return radiansToTrigFormat(mathacos(x)) +end +pgfluamathfunctions.acos=pgfluamathfunctions.aCos + +function pgfluamathfunctions.aTan(x) + return radiansToTrigFormat(mathatan(x)) +end +pgfluamathfunctions.atan=pgfluamathfunctions.aTan + +local mathatan2 +if math.atan2 == nil then + -- math.atan2 has been deprecated since LUA 5.3 + mathatan2 = function (y,x) return mathatan(y,x) end +else + mathatan2 = math.atan2 +end + +function pgfluamathfunctions.aTan2(y,x) + return radiansToTrigFormat(mathatan2(y,x)) +end +pgfluamathfunctions.atan2=pgfluamathfunctions.aTan2 +pgfluamathfunctions.atantwo=pgfluamathfunctions.aTan2 + +function pgfluamathfunctions.cot(x) + return pgfluamathfunctions.cos(x) / pgfluamathfunctions.sin(x) +end +function pgfluamathfunctions.sec(x) + return 1 / pgfluamathfunctions.cos(x) +end +function pgfluamathfunctions.cosec(x) + return 1 / pgfluamathfunctions.sin(x) +end + +function pgfluamathfunctions.pointnormalised (pgfx, pgfy) + local pgfx_normalised, pgfy_normalised + if pgfx == 0. and pgfy == 0. then + -- Orginal pgf macro gives this result + tex.dimen['pgf@x'] = "0pt" + tex.dimen['pgf@y'] = "1pt" + else + pgfx_normalised = pgfx/math.sqrt(pgfx^2 + pgfy^2) + pgfx_normalised = pgfx_normalised - pgfx_normalised%0.00001 + pgfy_normalised = pgfy/math.sqrt(pgfx^2 + pgfy^2) + pgfy_normalised = pgfy_normalised - pgfy_normalised%0.00001 + tex.dimen['pgf@x'] = tostring(pgfx_normalised) .. "pt" + tex.dimen['pgf@y'] = tostring(pgfy_normalised) .. "pt" + end + return nil +end + +local isnan = function(x) + return x ~= x +end + +pgfluamathfunctions.isnan = isnan + +local infty = 1/0 +pgfluamathfunctions.infty = infty + +local nan = math.sqrt(-1) +pgfluamathfunctions.nan = nan + +local stringlen = string.len +local globaltonumber = tonumber +local stringsub=string.sub +local stringformat = string.format +local stringsub = string.sub + +-- like tonumber(x), but it also accepts nan, inf, infty, and the TeX FPU format +function pgfluamathfunctions.tonumber(x) + if type(x) == 'number' then return x end + if not x then return x end + + local len = stringlen(x) + local result = globaltonumber(x) + if not result then + if len >2 and stringsub(x,2,2) == 'Y' and stringsub(x,len,len) == ']' then + -- Ah - some TeX FPU input of the form 1Y1.0e3] . OK. transform it + local flag = stringsub(x,1,1) + if flag == '0' then + -- ah, 0.0 + result = 0.0 + elseif flag == '1' then + result = globaltonumber(stringsub(x,3, len-1)) + elseif flag == '2' then + result = globaltonumber("-" .. stringsub(x,3, len-1)) + elseif flag == '3' then + result = nan + elseif flag == '4' then + result = infty + elseif flag == '5' then + result = -infty + end + else + local lower = x:lower() + if lower == 'nan' then + result = nan + elseif lower == "-nan" then + result = nan + elseif lower == 'inf' or lower == 'infty' then + result = infty + elseif lower == '-inf' or lower == '-infty' then + result = -infty + end + end + end + + return result +end + +local stringlen = string.len +local globaltonumber = tonumber +local stringformat = string.format +local stringsub = string.sub +local stringfind = string.find +local stringbyte = string.byte +local NULL_CHAR = string.byte("0",1) + +local function discardTrailingZeros(x) + local result = x + -- printf is too stupid: I would like to have + -- 1. a fast method + -- 2. a reliable method + -- 3. full precision of x + -- 4. a fixed point representation + -- the 'f' modifier has trailing zeros (stupid!) + -- the 'g' modified can switch to scientific notation (no-go!) + local periodOff = stringfind(result, '.',1,true) + if periodOff ~= nil then + -- strip trailing zeros + local chars = { stringbyte(result,1,#result) }; + local lastNonZero = #chars + for i = #chars, periodOff, -1 do + if chars[i] ~= NULL_CHAR then lastNonZero=i; break; end + end + if lastNonZero ~= #chars then + -- Ah: we had at least one trailing zero. + -- discard all but the last. + lastNonZero = mathmax(periodOff+1,lastNonZero) + end + result = stringsub(result, 1, lastNonZero) + end + return result; +end + +local function discardTrailingZerosFromMantissa(x) + local mantissaStart = stringfind(x, "e") + + local mantissa = stringsub(x,1,mantissaStart-1) + local exponent = stringsub(x,mantissaStart) + + return discardTrailingZeros(mantissa) .. exponent +end + + +-- a helper function which has no catcode issues when communicating with TeX: +function pgfluamathfunctions.tostringfixed(x) + if x == nil then + return "" + end + + return discardTrailingZeros(stringformat("%f", x)) +end + +-- converts an input number to a string which is accepted by the TeX FPU +function pgfluamathfunctions.toTeXstring(x) + local result = "" + if x ~= nil then + if x == infty then result = "4Y0.0e0]" + elseif x == -infty then result = "5Y0.0e0]" + elseif isnan(x) then result = "3Y0.0e0]" + elseif x == 0 then result = "0Y0.0e0]" + else + result = discardTrailingZerosFromMantissa(stringformat("%.10e", x)) + if x > 0 then + result = "1Y" .. result .. "]" + else + result = "2Y" .. stringsub(result,2) .. "]" + end + end + end + return result +end + +return pgfluamathfunctions diff --git a/Master/texmf-dist/tex/generic/pgf/libraries/luamath/pgf/luamath/parser.lua b/Master/texmf-dist/tex/generic/pgf/libraries/luamath/pgf/luamath/parser.lua new file mode 100644 index 00000000000..55066b45aad --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/libraries/luamath/pgf/luamath/parser.lua @@ -0,0 +1,470 @@ +-- Copyright 2011 by Christophe Jorssen and Mark Wibrow +-- Copyright 2014 by Christian Feuersaenger +-- +-- 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. +-- +-- $Id: parser.lua,v 1.1 2014/12/27 14:11:49 cfeuersaenger Exp $ +-- +-- usage: +-- +-- pgfluamathparser = require("pgf.luamath.parser") +-- +-- local result = pgfluamathparser.pgfmathparse("1+ 2*4^2") +-- +-- This LUA class has a direct backend in \pgfuselibrary{luamath}, see the documentation of that TeX package. + +local pgfluamathparser = pgfluamathparser or {} + +pgfluamathfunctions = require("pgf.luamath.functions") + +-- lpeg is always present in luatex +local lpeg = require("lpeg") + +local S, P, R = lpeg.S, lpeg.P, lpeg.R +local C, Cc, Ct = lpeg.C, lpeg.Cc, lpeg.Ct +local Cf, Cg, Cs = lpeg.Cf, lpeg.Cg, lpeg.Cs +local V = lpeg.V +local match = lpeg.match + +local space_pattern = S(" \n\r\t")^0 +local tex_unit = + P('pt') + P('mm') + P('cm') + P('in') + + -- while valid units, the font-depending ones need special attention... move them to the TeX side. For now. + -- P('ex') + P('em') + + P('bp') + P('pc') + + P('dd') + P('cc') + P('sp'); + +local one_digit_pattern = R("09") +local positive_integer_pattern = one_digit_pattern^1 +-- FIXME : it might be a better idea to remove '-' from all number_patterns! Instead, rely on the prefix operator 'neg' to implement negative numbers. +-- Is that wise? It is certainly less efficient... +local integer_pattern = S("+-")^-1 * positive_integer_pattern +-- Valid positive decimals are |xxx.xxx|, |.xxx| and |xxx.| +local positive_integer_or_decimal_pattern = positive_integer_pattern * ( P(".") * one_digit_pattern^0)^-1 + + (P(".") * one_digit_pattern^1) +local integer_or_decimal_pattern = S("+-")^-1 * positive_integer_or_decimal_pattern +local fpu_pattern = R"15" * P"Y" * positive_integer_or_decimal_pattern * P"e" * P("-")^-1 * R("09")^1 * P"]" +local unbounded_pattern = P"inf" + P"INF" + P"nan" + P"NaN" + P"Inf" +local number_pattern = C(unbounded_pattern + fpu_pattern + integer_or_decimal_pattern * (S"eE" * integer_pattern + C(tex_unit))^-1) + +local underscore_pattern = P("_") + +local letter_pattern = R("az","AZ") +local alphanum__pattern = letter_pattern + one_digit_pattern + underscore_pattern + +local identifier_pattern = letter_pattern^1 * alphanum__pattern^0 + +local openparen_pattern = P("(") * space_pattern +local closeparen_pattern = P(")") +local opencurlybrace_pattern = P("{") +local closecurlybrace_pattern = P("}") +local openbrace_pattern = P("[") +local closebrace_pattern = P("]") + +-- hm. what about '\\' or '\%' ? +-- accept \pgf@x, \count0, \dimen42, \c@pgf@counta, \wd0, \ht0, \dp 0 +local controlsequence_pattern = P"\\" * C( (R("az","AZ") + P"@")^1) * space_pattern* C( R"09"^0 ) + +-- local string = P('"') * C((1 - P('"'))^0) * P('"') + +local comma_pattern = P(",") * space_pattern + + +---------------- +local TermOp = C(S("+-")) * space_pattern +local RelationalOp = C( P"==" + P"!=" + P"<=" + P">=" + P"<" + P">" ) * space_pattern +local FactorOp = C(S("*/")) * space_pattern + +-- Grammar +local Exp, Term, Factor = V"Exp", V"Term", V"Factor" +local Prefix = V"Prefix" +local Postfix = V"Postfix" + + + +local function eval (v1, op, v2) + if (op == "+") then return v1 + v2 + elseif (op == "-") then return v1 - v2 + elseif (op == "*") then return v1 * v2 + elseif (op == "/") then return v1 / v2 + else + error("This function must not be invoked for operator "..op) + end +end + +local pgfStringToFunctionMap = pgfluamathfunctions.stringToFunctionMap +local function function_eval(name, ... ) + local f = pgfStringToFunctionMap[name] + if not f then + error("Function '" .. name .. "' is undefined (did not find pgfluamathfunctions."..name .." (looked into pgfluamathfunctions.stringToFunctionMap))") + end + -- FIXME: validate signature + return f(...) +end + + +local func = + (C(identifier_pattern) * space_pattern * openparen_pattern * Exp * (comma_pattern * Exp)^0 * closeparen_pattern) / function_eval; + +local functionWithoutArg = identifier_pattern / function_eval + +-- this is what can occur as exponent after '^'. +-- I have the impression that the priorities could be implemented in a better way than this... but it seems to work. +local pow_exponent = + -- allows 2^-4, 2^1e4, 2^2 + -- FIXME : why not 2^1e2 ? + Cg(C(integer_or_decimal_pattern) + -- 2^pi, 2^multiply(2,2) + + Cg(func+functionWithoutArg) + -- 2^(2+2) + + openparen_pattern * Exp * closeparen_pattern ) + +local function prefix_eval(op, x) + if op == "-" then + return pgfluamathfunctions.neg(x) + elseif op == "!" then + return pgfluamathfunctions.notPGF(x) + else + error("This function must not be invoked for operator "..op) + end +end + + +local prefix_operator = C( S"-!" ) +local prefix_operator_pattern = (prefix_operator * space_pattern * Cg(Prefix) ) / prefix_eval + +-- apparently, we need to distinghuish between <expr> ! and <expr> != <expr2>: +local postfix_operator = C( S"r!" - P"!=" ) + C(P"^") * space_pattern * pow_exponent + + +local ternary_eval = pgfluamathfunctions.ifthenelse + +local factorial_eval = pgfluamathfunctions.factorial +local deg = pgfluamathfunctions.deg +local pow_eval = pgfluamathfunctions.pow + +-- @param prefix the argument before the postfix operator. +-- @param op either nil or the postfix operator +-- @param arg either nil or the (mandatory) argument for 'op' +local function postfix_eval(prefix, op, arg) + local result + if op == nil then + result = prefix + elseif op == "r" then + if arg then error("parser setup error: expected nil argument") end + result = deg(prefix) + elseif op == "!" then + if arg then error("parser setup error: expected nil argument") end + result = factorial_eval(prefix) + elseif op == "^" then + if not arg then error("parser setup error: ^ with its argument") end + result = pow_eval(prefix, arg) + else + error("Parser setup error: " .. tostring(op) .. " unexpected in this context") + end + return result +end + +local function relational_eval(v1, op, v2) + local fct + if (op == "==") then fct = pgfluamathfunctions.equal + elseif (op == "!=") then fct = pgfluamathfunctions.notequal + elseif (op == "<") then fct = pgfluamathfunctions.less + elseif (op == ">") then fct = pgfluamathfunctions.greater + elseif (op == ">=") then fct = pgfluamathfunctions.notless + elseif (op == "<=") then fct = pgfluamathfunctions.notgreater + else + error("This function must not be invoked for operator "..op) + end + return fct(v1,v2) +end + +-- @return either the box property or nil +-- @param cs "wd", "ht", or "dp" +-- @param intSuffix some integer +local function get_tex_box(cs, intSuffix) + -- assume get_tex_box is only called when a dimension is required. + local result + pgfluamathparser.units_declared = true + local box =tex.box[tonumber(intSuffix)] + if not box then error("There is no box " .. intSuffix) end + if cs == "wd" then + result = box.width / 65536 + elseif cs == "ht" then + result = box.height / 65536 + elseif cs == "dp" then + result = box.depth / 65536 + else + result = nil + end + return result +end + + +local function controlsequence_eval(cs, intSuffix) + local result + if intSuffix and #intSuffix >0 then + if cs == "count" then + result= pgfluamathparser.get_tex_count(intSuffix) + elseif cs == "dimen" then + result= pgfluamathparser.get_tex_dimen(intSuffix) + else + result = get_tex_box(cs,intSuffix) + if not result then + -- this can happen - we cannot expand \chardef'ed boxes here. + -- this will be done by the TeX part + error('I do not know/support the TeX register "\\' .. cs .. '"') + end + end + else + result = pgfluamathparser.get_tex_register(cs) + end + return result +end + +pgfluamathparser.units_declared = false +function pgfluamathparser.get_tex_register(register) + -- register is a string which could be a count or a dimen. + if pcall(tex.getcount, register) then + return tex.count[register] + elseif pcall(tex.getdimen, register) then + pgfluamathparser.units_declared = true + return tex.dimen[register] / 65536 -- return in points. + else + error('I do not know the TeX register "' .. register .. '"') + return nil + end + +end + +function pgfluamathparser.get_tex_count(count) + -- count is expected to be a number + return tex.count[tonumber(count)] +end + +function pgfluamathparser.get_tex_dimen(dimen) + -- dimen is expected to be a number + pgfluamathparser.units_declared = true + return tex.dimen[tonumber(dimen)] / 65536 +end + +function pgfluamathparser.get_tex_sp(dimension) + -- dimension should be a string + pgfluamathparser.units_declared = true + return tex.sp(dimension) / 65536 +end + + +local initialRule = V"initial" + +local Summand = V"Summand" +local Relational = V"Relational" +local LogicalOr = V"LogicalOr" +local LogicalAnd = V"LogicalAnd" + +local pgftonumber = pgfluamathfunctions.tonumber +local tonumber_withunit = pgfluamathparser.get_tex_sp +local function number_optional_units_eval(x, unit) + if not unit then + return pgftonumber(x) + else + return tonumber_withunit(x) + end +end + +-- @param scale the number. +-- @param controlsequence either nil in which case just the number must be returned or a control sequence +-- @see controlsequence_eval +local function scaled_controlsequence_eval(scale, controlsequence, intSuffix) + if controlsequence==nil then + return scale + else + return scale * controlsequence_eval(controlsequence, intSuffix) + end +end + +-- Grammar +-- +-- for me: +-- - use '/' to evaluate all expressions which contain a _constant_ number of captures. +-- - use Cf to evaluate expressions which contain a _dynamic_ number of captures +-- +-- see unittest_luamathparser.tex for tons of examples +local G = P{ "initialRule", + initialRule = space_pattern* Exp * -1; + -- ternary operator (or chained ternary operators): + -- FIXME : is this chaining a good idea!? + Exp = Cf( Relational * Cg(P"?" * space_pattern * Relational * P":" *space_pattern * Relational )^0, ternary_eval) ; + -- FIXME : do we really allow something like " 1 == 1 != 2" ? I would prefer (1==1) != 2 !? + Relational = Cf(LogicalOr * Cg(RelationalOp * LogicalOr)^0, relational_eval); + LogicalOr = Cf(LogicalAnd * (P"||" * space_pattern * LogicalAnd)^0, pgfluamathfunctions.orPGF); + LogicalAnd = Cf(Summand * (P"&&" * space_pattern * Summand)^0, pgfluamathfunctions.andPGF); + Summand = Cf(Term * Cg(TermOp * Term)^0, eval) ; + Term = Cf(Prefix * Cg(FactorOp * Prefix)^0, eval); + Prefix = prefix_operator_pattern + Postfix; + -- this calls 'postfix_eval' with nil arguments if it is no postfix operation.. but that does not hurt (right?) + Postfix = Factor * (postfix_operator * space_pattern)^-1 / postfix_eval; + Factor = + ( + number_pattern / number_optional_units_eval * + -- this construction will evaluate number_pattern with 'number_optional_units_eval' FIRST. + -- also accept '0.5 \pgf@x' here: + space_pattern *controlsequence_pattern^-1 / scaled_controlsequence_eval + + func + + functionWithoutArg + + openparen_pattern * Exp * closeparen_pattern + + controlsequence_pattern / controlsequence_eval + ) *space_pattern + ; +} + +-- does not reset units_declared. +local function pgfmathparseinternal(str) + local result = match(G,str) + if result == nil then + error("The string '" .. str .. "' is no valid PGF math expression. Please check for syntax errors.") + end + return result +end + + +-- This is the math parser function in this module. +-- +-- @param str a string like "1+1" which is accepted by the PGF math language +-- @return the result of the expression. +-- +-- Throws an error if the string is no valid expression. +function pgfluamathparser.pgfmathparse(str) + pgfluamathparser.units_declared = false + + return pgfmathparseinternal(str) +end + +local pgfmathparse = pgfluamathparser.pgfmathparse +local tostringfixed = pgfluamathfunctions.tostringfixed +local tostringfpu = pgfluamathfunctions.toTeXstring + +local tmpFunctionArgumentPrefix = "tmpVar" +local stackOfLocalFunctions = {} + +-- This is a backend for PGF's 'declare function'. +-- \tikzset{declare function={mu(\x,\i)=\x^\i;}} +-- will boil down to +-- pgfluamathparser.declareExpressionFunction("mu", 2, "#1^#2") +-- +-- The local function will be pushed on a stack of known local functions and is +-- available until popLocalExpressionFunction() is called. TeX will call this using +-- \aftergroup. +-- +-- @param name the name of the new function +-- @param numArgs the number of arguments +-- @param expression an expression containing #1, ... #n where n is numArgs +-- +-- ATTENTION: local functions behave DIFFERENTLY in LUA! +-- In LUA, local variables are not expanded whereas TeX expands them. +-- The difference is +-- +-- declare function={mu1(\x,\i)=\x^\i;} +-- \pgfmathparse{mu1(-5,2)} --> -25 +-- \pgfluamathparse{mu1(-5,2)} --> 25 +-- +-- x = -5 +-- \pgfmathparse{mu1(x,2)} --> 25 +-- \pgfluamathparse{mu1(x,2)} --> 25 +-- +-- In an early prototype, I simulated TeX's expansion to fix the first case (successfully). +-- BUT: that "simulated expansion" broke the second case because LUA will evaluate "x" and hand -5 to the local function. +-- I decided to keep it as is. Perhaps we should fix PGF's expansion approach in TeX (which is ugly anyway) +function pgfluamathparser.pushLocalExpressionFunction(name, numArgs, expression) + -- now we have "tmpVar1^tmpVar2" instead of "#1^#2" + local normalizedExpr = expression:gsub("#", tmpFunctionArgumentPrefix) + local restores = {} + local tmpVars = {} + for i=1,numArgs do + local tmpVar = tmpFunctionArgumentPrefix .. tostring(i) + tmpVars[i] = tmpVar + end + + local newFunction = function(...) + local args = table.pack(...) + + -- define "tmpVar1" ... "tmpVarN" to return args[i]. + -- Of course, we need to restore "tmpVar<i>" after we return! + for i=1,numArgs do + local tmpVar = tmpVars[i] + local value = args[i] + restores[i] = pgfStringToFunctionMap[tmpVar] + pgfStringToFunctionMap[tmpVar] = function () return value end + end + + -- parse our expression. + + -- FIXME : this here is an attempt to mess around with "units_declared". + -- It would be better to call pgfmathparse and introduce some + -- semaphore to check if pgfmathparse is a nested call-- in this case, it should + -- not reset units_declared. But there is no "finally" block and pcall is crap (looses stack trace). + local success,result = pcall(pgfmathparseinternal, normalizedExpr) + + -- remove 'tmpVar1', ... from the function table: + for i=1,numArgs do + local tmpVar = tmpVars[i] + pgfStringToFunctionMap[tmpVar] = restores[i] + end + + if success==false then error(result) end + return result + end + table.insert(stackOfLocalFunctions, name) + pgfStringToFunctionMap[name] = newFunction +end + +function pgfluamathparser.popLocalExpressionFunction() + local name = stackOfLocalFunctions[#stackOfLocalFunctions] + pgfStringToFunctionMap[name] = nil + -- this removes the last element: + table.remove(stackOfLocalFunctions) +end + + +-- A Utility function which simplifies the interaction with the TeX code +-- @param expression the input expression (string) +-- @param outputFormatChoice 0 if the result should be a fixed point number, 1 if it should be in FPU format +-- @param showErrorMessage (boolean) true if any error should be displayed, false if errors should simply result in an invocation of TeX's parser (the default) +-- +-- it defines \pgfmathresult and \ifpgfmathunitsdeclared +function pgfluamathparser.texCallParser(expression, outputFormatChoice, showErrorMessage) + local success, result + if showErrorMessage then + result = pgfmathparse(expression) + success = true + else + success, result = pcall(pgfmathparse, expression) + end + + if success and result then + local result_str + if outputFormatChoice == 0 then + -- luamath/output format=fixed + result_str = tostringfixed(result) + else + -- luamath/output format=fixed + result_str = tostringfpu(result) + end + tex.sprint("\\def\\pgfmathresult{" .. result_str .. "}") + if pgfluamathparser.units_declared then + tex.sprint("\\pgfmathunitsdeclaredtrue") + else + tex.sprint("\\pgfmathunitsdeclaredfalse") + end + else + tex.sprint("\\def\\pgfmathresult{}") + tex.sprint("\\pgfmathunitsdeclaredfalse") + end +end + +return pgfluamathparser diff --git a/Master/texmf-dist/tex/generic/pgf/libraries/luamath/pgflibraryluamath.code.tex b/Master/texmf-dist/tex/generic/pgf/libraries/luamath/pgflibraryluamath.code.tex index b06695a87fa..1d7a5227dd6 100644 --- a/Master/texmf-dist/tex/generic/pgf/libraries/luamath/pgflibraryluamath.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/libraries/luamath/pgflibraryluamath.code.tex @@ -1,4 +1,5 @@ % Copyright 2011 by Christophe Jorssen and Mark Wibrow +% Copyright 2014 by Christian Feuersänger % % This file may be distributed and/or modified % @@ -7,14 +8,43 @@ % % See the file doc/generic/pgf/licenses/LICENSE for more details. % -% $Id: pgflibraryluamath.code.tex,v 1.11 2012/03/06 16:06:09 cjorssen Exp $ +% $Id: pgflibraryluamath.code.tex,v 1.20 2015/06/05 06:23:21 cfeuersaenger Exp $ % -% !!! Warning: this library does not work with fpu!!! +% +% This is a library for a LUA math parser and LUA math operations. +% Advantage compared to its TeX pendant: it is FASTER and has HIGHER +% ACCURACY. +% Disadvantage: any function declared by means of +% \pgfmathdeclarefunction is NOT automatically transported to the LUA +% side (at the time of this writing). +% LUA functions need to be defined by means of LUA code +% +% function pgfluamathfunctions.myoperation(a,b) +% return a*2*b +% end +% +% this will automatically set up 'myoperation' for use in +% \pgfluamathparse{myoperation(4,2)} +% +% The library has TWO use-cases which are more or less distinct: one +% is to use LUA for all math function, but not for math expression +% parsing -- this was still under control of the TeX math parser. +% This approach works like the 'fpu' library. +% +% The second approach is to use LUA to parse all math expressions - +% but if someone calls \pgfmathadd@{1}{2}, it would use the TeX +% command. This approach is relatively lightweight because it does not +% need to substitute all \pgfmath* macros. +% +% One can mix both modes. % ******************************************************************* % Some luatex stuff. Should be put elsewhere (e.g. in % pgfutil-luatex-engine). +\edef\pgfliblua@oldcatcodedoublequote{\the\catcode`\"}% +\catcode`\"=12 + % We assume luatex version > 0.39: % - \directlua <general text> will work % - \directlua is the only luatex primitive that we can assume @@ -38,11 +68,92 @@ \def\pgfutil@luaescapestring#1{} \fi +\pgfutil@directlua{% + pgfluamathfunctions = require("pgf.luamath.functions") + pgfluamathparser = require("pgf.luamath.parser")} + + +% Patch some configuration macros such that the modifications are +% available in LUA as well: +\pgfkeys{ + /pgf/trig format/deg/.add code={}{\directlua{pgfluamathfunctions.setTrigFormat("deg")}\aftergroup\pgfmath@settrigformat}, + /pgf/trig format/rad/.add code={}{\directlua{pgfluamathfunctions.setTrigFormat("rad")}\aftergroup\pgfmath@settrigformat}, +} +% ... and reactivate the key: +\pgfmathiftrigonometricusesdeg{% + \pgfkeys{/pgf/trig format/deg}% +}{% + \pgfkeys{/pgf/trig format/rad}% +}% + +% re-activates the current trig format. This is important after a TeX +% group has been closed. +\def\pgfmath@settrigformat{% + \pgfmathiftrigonometricusesdeg{% + \directlua{pgfluamathfunctions.setTrigFormat("deg")}% + }{% + \directlua{pgfluamathfunctions.setTrigFormat("rad")}% + }% +}% + +\let\pgfmathsetseed@pgfbasic = \pgfmathsetseed +\def\pgfmathsetseed#1{% + \pgfmathsetseed@pgfbasic{#1}% + \directlua{pgfluamathfunctions.setRandomSeed(pgfluamathfunctions.tonumber("\pgfmathresult"))}% +}% + +% Patch 'declare function' such that it communicates the function +% directly to LUA. +\let\pgfmathnotifynewdeclarefunction@orig=\pgfmathnotifynewdeclarefunction +\def\pgfmathnotifynewdeclarefunction#1#2#3{% + \pgfmathnotifynewdeclarefunction@orig{#1}{#2}{#3}% + \directlua{pgfluamathparser.pushLocalExpressionFunction(% + "\pgfutil@luaescapestring{#1}",% + #2,% + "\pgfutil@luaescapestring{#3}")}% + % + % ensure that the local function is removed at the end of the + % scope. To this end, we maintain a stack on the LUA side. + \aftergroup\pgfluamathparse@pop@local@function +}% + +\def\pgfluamathparse@pop@local@function{% + \directlua{pgfluamathparser.popLocalExpressionFunction()}% +}% + % End of luatex stuff % ******************************************************************* % Loading part: based on fpu library + +% if LUA failed to evaluate the expression, it will be evaluated in +% TeX as fallback. This boolean defines if the error message shall be +% shown or suppressed. The default is to suppress it and show any +% resulting TeX errors. +% +% If LUA fails \pgfmathresult will be empty. +% +% This is actually only for debugging; it will be set implicitly when +% activating/deactivating TeX fallback. +\newif\ifpgfluamathshowerrormessage + +% Defines what happens if LUA failed to evaluate the expression: if +% this is true, the TeX parser will be invoked as fallback. +% +% This happens +% - for \chardef'ed boxes for which LUA lacks evaluation capabilities +% - if the expression includes some function which is unavailable in +% LUA (defined only in TeX) +% - some special cases which simply haven't been added to the LUA +% parser (yet). +% At the time of this writing, this includes +% -- arrays created via '{}' and indexed with '[]' +% -- strings with "<str>" +% -- 'scalar' function +% -- hex/octal/binary input +\newif\ifpgfluamathenableTeXfallback + \newif\ifpgfluamathcomputationactive \newif\ifpgfluamathparseractive @@ -60,6 +171,7 @@ \pgfluamathcomputationactivefalse \fi} +\let\pgfluamath@pgfmathparse\pgfmathparse \def\pgfluamath@makeparseractive{% \ifpgfluamathparseractive \else @@ -97,7 +209,33 @@ luamath/off/.code={% \pgfluamath@makecomputationinactive \pgfluamath@makeparserinactive}, - luamath/.default=only computation} + luamath/.default=only computation, + % + % activates ONLY the parser. This is fast and does not replace the + % \pgfmath* functions. + % @see |parser and computation| which also allows to write + % \pgfmathadd{1}{2} to call LUA + luamath/parser/.code={% + \pgfutil@ifluatex + \pgfluamath@makeparseractive + \else + \pgfmath@error{Sorry, you need the luaTeX engine to use the + luamath library}% + \fi + }, + luamath/output format/.is choice, + luamath/output format/fixed/.code= {\def\pgfluamath@outputformat@choice{0}}, + % returns results for use in the FPU + luamath/output format/float/.code= {\def\pgfluamath@outputformat@choice{1}}, + luamath/output format/fixed, + % this is merely useful for debugging purposes, I guess. + luamath/show error message/.is if=pgfluamathshowerrormessage, + luamath/enable TeX fallback/.is choice, + luamath/enable TeX fallback/true/.code={\pgfluamathenableTeXfallbacktrue\pgfluamathshowerrormessagefalse}, + luamath/enable TeX fallback/false/.code={\pgfluamathenableTeXfallbackfalse\pgfluamathshowerrormessagetrue}, + luamath/enable TeX fallback/.default=true, + luamath/enable TeX fallback=true, +} \def\pgfluamath@uninstall@appendcmd#1{% \expandafter\gdef\expandafter\pgfluamath@uninstall\expandafter{% @@ -107,9 +245,6 @@ % uninstall assemblation. \def\pgfluamath@checkuninstallcmd{% \pgfutil@ifundefined{pgfluamath@uninstall}{% - \pgfutil@directlua{% - pgfluamathfunctions = require("pgfluamath.functions") - pgfluamathparser = require("pgfluamath.parser")} \global\let\pgfluamath@uninstall=\pgfutil@empty }{% % We already HAVE an uninstall command (prepared globally). @@ -334,166 +469,45 @@ \newif\ifpgfluamathunitsdeclared +% true if and only if LUA failed to evaluate the expression and the +% expression was evaluated by means of the TeX parser as fallback. +% +% This happens +% - for \chardef'ed boxes for which LUA lacks evaluation capabilities +% - if the expression includes some function which is unavailable in +% LUA (defined only in TeX) +% - some special cases which simply haven't been added to the LUA +% parser (yet). +% At the time of this writing, this includes +% -- arrays created via '{}' and indexed with '[]' +% -- strings with "<str>" +% -- 'scalar' function +% -- hex/octal/binary input +\newif\ifpgfluamathusedTeXfallback + +% Parses the math expression and defines \pgfmathresult and +% \ifpgfmathunitsdeclared to contain the result. +% +% If \ifpgfluamathparseractive then the result is also assigned to +% \pgfmathresult. Furthermore, if the expression cannot be evaluated (because LUA does not support +% it), it will be evaluated by mean of TeX as fallback. +% +% @see \ifpgfluamathusedTeXfallback +% @see \ifpgfluamathshowerrormessage \def\pgfluamathparse#1{% - \pgfluamathunitsdeclaredfalse - % The following "two passes" (TeX -> lua -> TeX -> lua -> TeX) is - % required for chadef'ed named boxes. The parser - % adds \number in front of the box name (e.g. \mybox -> - % \number\mybox). Then this is expanded to the chardef'ed number via - % \edef expansion. - \edef\pgfluamath@temp{% - \pgfutil@directlua{% - % Double quotes " are needed here. On the lua side, single quotes - % ' are used. Take care to don't mix them. - pgfluamathparser.parse("\pgfutil@luaescapestring{#1}") - tex.sprint(parsed_expression)}}% - % We can now feed back the evaluator. - \edef\pgfluamathresult{% - \pgfutil@directlua{% - pgfluamathparser.eval('\pgfluamath@temp') - if pgfluamathparser.result == nil then - tex.print('nil') - else - tex.print(pgfluamathparser.result) - end}}% - \csname pgfluamathunitsdeclared\pgfutil@directlua{% - if pgfluamathparser.units_declared == true then - tex.print('true') - else - tex.print('false') - end}\endcsname - \ifpgfluamathparseractive - \let\pgfmathresult\pgfluamathresult - \let\ifpgfmathunitsdeclared=\ifpgfluamathunitsdeclared - \fi} + \pgfluamathusedTeXfallbackfalse + \pgfutil@directlua{pgfluamathparser.texCallParser( + "\pgfutil@luaescapestring{#1}", + \pgfluamath@outputformat@choice, + \ifpgfluamathshowerrormessage true\else false\fi)% + }% + \ifx\pgfmathresult\pgfutil@empty + \ifpgfluamathenableTeXfallback + \pgfluamathusedTeXfallbacktrue + \pgfluamath@pgfmathparse{#1}% + \fi + \fi +} +\catcode`\"=\pgfliblua@oldcatcodedoublequote \endinput -% NEW: CJ (06 March 2012) Work in progress -\documentclass{minimal} - -\usepackage{pgfmath} - -\makeatletter -\let\pgfutil@directlua\directlua - -\directlua{dofile('pgfmathparser.lua')} - -\def\pgfluamathdeclarefunction#1#2#3{% - \pgfutil@directlua{% - pgfluamath.declare_new_function('#1',#2,#3)}} - -\pgfluamathdeclarefunction{add}{2}{% - function (a,b) return a + b end} - -\pgfluamathdeclarefunction{substract}{2}{% - function (a,b) return a - (b) end} - -\pgfluamathdeclarefunction{neg}{1}{% - function (a) return -(a) end} - -\pgfluamathdeclarefunction{multiply}{2}{% - function (a,b) return a * b end} - -\pgfluamathdeclarefunction{divide}{2}{% - function (a,b) return a / b end} - -\pgfluamathdeclarefunction{pow}{2}{% - function (a,b) return math.pow(a,b) end} - -\pgfluamathdeclarefunction{deg}{1}{% - function (a) return math.deg(a) end} - -\pgfluamathdeclarefunction{ifthenelse}{3}{% - function (a,b,c) if a == 1 then return b else return c end end} - -\pgfluamathdeclarefunction{equal}{2}{% - function (a,b) if a == b then return 1 else return 0 end end} - -\pgfluamathdeclarefunction{greater}{2}{% - function (a,b) if a > b then return 1 else return 0 end end} - -\pgfluamathdeclarefunction{less}{2}{% - function (a,b) if a < b then return 1 else return 0 end end} - -\pgfluamathdeclarefunction{notequal}{2}{% - function (a,b) if a < b or a > b then return 1 else return 0 end end} - -\pgfluamathdeclarefunction{notless}{2}{% - function (a,b) if a >= b then return 1 else return 0 end end} - -\pgfluamathdeclarefunction{notgreater}{2}{% - function (a,b) if a <= b then return 1 else return 0 end end} - -\pgfluamathdeclarefunction{andPGF}{2}{% - function (a,b) if (a < 0 or a > 0) and (b < 0 or b > 0) then return - 1 else return 0 end end} - -\pgfluamathdeclarefunction{orPGF}{2}{% - function (a,b) if (a < 0 or a > 0) or (b < 0 or b > 0) then return 1 - else return 0 end end} - -\pgfluamathdeclarefunction{modulo}{2}{% - % This is the definition of the lua % modulo operator - % The % operator cannot be used here (catcode issue) - function (a,b) return a - math.floor(a/b)*b end} - -\pgfluamathdeclarefunction{int}{1}{% - function (a) return a - pgfluamath.defined_functions.modulo.code(a,1) end} - -\pgfluamathdeclarefunction{frac}{1}{% - function (a) return pgfluamath.defined_functions.modulo.code(a,1) end} - -\pgfluamathdeclarefunction{factorial}{1}{% - function (a) - a = math.abs(pgfluamath.defined_functions.int.code(a)) - if a == 1 then - return 1 - else - return a * pgfluamath.defined_functions.factorial.code(a-1) - end - end} - -\pgfluamathdeclarefunction{sqrt}{1}{% - function (a) return math.sqrt(a) end} - - - -\def\pgfluamathparseandresult#1{% - \pgfutil@directlua{% - local s = pgfluamath.transform_math_expr('#1',pgfluamath.defined_functions_pattern) - texio.write_nl('pgfluamath: parsed expression "' .. s .. '"') - loadstring('tex.sprint(-1,' .. s .. ')')()}} - -\makeatother -\begin{document} - -$\pgfluamathparseandresult{1+2} = 3$ - -$\pgfluamathparseandresult{2*3} = 6$ - -$\pgfluamathparseandresult{1--1} = 2$ - -$\pgfluamathparseandresult{6/2} = 3$ - -$\pgfluamathparseandresult{2^2} = 4$ - -$\pgfluamathparseandresult{1>2} = 0$ - -$\pgfluamathparseandresult{2>1} = 1$ - -$\pgfluamathparseandresult{1!=1} = 0$ - -$\pgfluamathparseandresult{1?2:3} = 2$ - -$\pgfluamathparseandresult{1.0||0} = 1$ - -$\pgfluamathparseandresult{1&&0} = 0$ - -$\pgfluamathparseandresult{sqrt(2)} = \pgfmathparse{sqrt(2)}\pgfmathresult$ - -%\pgfluamathparseandresult{{1,{2,3-7}[1],4}[1]^2} - -\end{document} -% Local Variables: -% TeX-engine: luatex -% End:
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/pgf/libraries/luamath/pgfluamath.functions.lua b/Master/texmf-dist/tex/generic/pgf/libraries/luamath/pgfluamath.functions.lua deleted file mode 100644 index fa3c1872a58..00000000000 --- a/Master/texmf-dist/tex/generic/pgf/libraries/luamath/pgfluamath.functions.lua +++ /dev/null @@ -1,313 +0,0 @@ --- Copyright 2011 by Christophe Jorssen --- --- 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. --- --- $Id: pgfluamath.functions.lua,v 1.9 2013/07/25 10:39:34 tantau Exp $ --- - -local pgfluamathfunctions = pgfluamathfunctions or {} - -local mathabs, mathacos, mathasin = math.abs, math.acos, math.asin -local mathatan, mathatan2, mathceil = math.atan, math.atan2, math.ceil -local mathcos, mathcosh, mathdeg = math.cos, math.cosh, math.deg -local mathexp, mathfloor, mathfmod = math.exp, math.floor, math.fmod -local mathfrexp, mathhuge, mathldexp = math.frexp, math.huge, math.ldexp -local mathlog, mathlog10, mathmax = math.log, math.log10, math.max -local mathmin, mathmodf, mathpi = math.min, math.modf, math.pi -local mathpow, mathrad, mathrandom = math.pow, math.rad, math.random -local mathrandomseed, mathsin = math.randomseed, math.sin -local mathsinh, mathsqrt, mathtanh = math.sinh, math.sqrt, math.tanh -local mathtan = math.tan - -function pgfluamathfunctions.add(x,y) - return x+y -end - -function pgfluamathfunctions.substract(x,y) - return x-y -end - -function pgfluamathfunctions.neg(x) - return -x -end - -function pgfluamathfunctions.multiply(x,y) - return x*y -end - -function pgfluamathfunctions.divide(x,y) - return x/y -end - -function pgfluamathfunctions.pow(x,y) - return mathpow(x,y) -end - -function pgfluamathfunctions.factorial(x) --- TODO: x must be an integer - if x == 0 then - return 1 - else - return x * factorial(x-1) - end -end - -function pgfluamathfunctions.deg(x) - return mathdeg(x) -end - -function pgfluamathfunctions.ifthenelse(x,y,z) - if x~= 0 then - return y - else - return z - end -end - -function pgfluamathfunctions.equal(x,y) - if x == y then - return 1 - else - return 0 - end -end - -function pgfluamathfunctions.greater(x,y) - if x > y then - return 1 - else - return 0 - end -end - -function pgfluamathfunctions.less(x,y) - if x < y then - return 1 - else - return 0 - end -end - -function pgfluamathfunctions.notequal(x,y) - if x ~= y then - return 1 - else - return 0 - end -end - -function pgfluamathfunctions.notless(x,y) - if x >= y then - return 1 - else - return 0 - end -end - -function pgfluamathfunctions.notgreater(x,y) - if x <= y then - return 1 - else - return 0 - end -end - -function pgfluamathfunctions.andPGF(x,y) - if (x ~= 0) and (y ~= 0) then - return 1 - else - return 0 - end -end - -function pgfluamathfunctions.orPGF(x,y) - if (x ~= 0) or (y ~= 0) then - return 1 - else - return 0 - end -end - -function pgfluamathfunctions.notPGF(x) - if x == 0 then - return 1 - else - return 0 - end -end - -function pgfluamathfunctions.pi() - return mathpi -end - -function pgfluamathfunctions.e() - return mathexp(1) -end - -function pgfluamathfunctions.abs(x) - return mathabs(x) -end - -function pgfluamathfunctions.floor(x) - return mathfloor(x) -end - -function pgfluamathfunctions.ceil(x) - return mathceil(x) -end - -function pgfluamathfunctions.exp(x) - return mathexp(x) -end - -function pgfluamathfunctions.log(x) - return mathlog(x) -end - -function pgfluamathfunctions.log10(x) - return mathlog10(x) -end - -function pgfluamathfunctions.sqrt(x) - return mathsqrt(x) -end - -function pgfluamathfunctions.rnd() - return mathrandom() -end - -function pgfluamathfunctions.rand() - return mathrandom(-1,1) -end - -function pgfluamathfunctions.deg(x) - return mathdeg(x) -end - -function pgfluamathfunctions.rad(x) - return mathrad(x) -end - -function pgfluamathfunctions.round(x) - if x<0 then - return -mathceil(mathabs(x)) - else - return mathceil(x) - end -end - -function pgfluamathfunctions.gcd(a, b) - if b == 0 then - return a - else - return gcd(b, a%b) - end -end - -function pgfluamathfunctions.isprime(a) - local ifisprime = true - if a == 1 then - ifisprime = false - elseif a == 2 then - ifisprime = true --- if a > 2 then - else - local i, imax = 2, mathceil(mathsqrt(a)) + 1 - while ifisprime and (i < imax) do - if gcd(a,i) ~= 1 then - ifisprime = false - end - i = i + 1 - end - end - if ifisprime then - return 1 - else - return 0 - end -end - - -function pgfluamathfunctions.split_braces_to_explist(s) - -- (Thanks to mpg and zappathustra from fctt) - -- Make unpack available whatever lua version is used - -- (unpack in lua 5.1 table.unpack in lua 5.2) - local unpack = table.unpack or unpack - local t = {} - for i in s:gmatch('%b{}') do - table.insert(t, tonumber(i:sub(2, -2))) - end - return unpack(t) -end - -function pgfluamathfunctions.split_braces_to_table(s) - local t = {} - for i in s:gmatch('%b{}') do - table.insert(t, tonumber(i:sub(2, -2))) - end - return t -end - -function pgfluamathfunctions.mod(x,y) - if x/y < 0 then - return -(mathabs(x)%mathabs(y)) - else - return mathabs(x)%mathabs(y) - end -end - -function pgfluamathfunctions.Mod(x,y) - return mathabs(x)%mathabs(y) -end - -function pgfluamathfunctions.Sin(x) - return mathsin(mathrad(x)) -end - -function pgfluamathfunctions.Cos(x) - return mathcos(mathrad(x)) -end - -function pgfluamathfunctions.Tan(x) - return mathtan(mathrad(x)) -end - -function pgfluamathfunctions.aSin(x) - return mathdeg(mathasin(x)) -end - -function pgfluamathfunctions.aCos(x) - return mathdeg(mathacos(x)) -end - -function pgfluamathfunctions.aTan(x) - return mathdeg(mathatan(x)) -end - -function pgfluamathfunctions.aTan2(y,x) - return mathdeg(mathatan2(y,x)) -end - -function pgfluamathfunctions.pointnormalised (pgfx, pgfy) - local pgfx_normalised, pgfy_normalised - if pgfx == 0. and pgfy == 0. then - -- Orginal pgf macro gives this result - tex.dimen['pgf@x'] = "0pt" - tex.dimen['pgf@y'] = "1pt" - else - pgfx_normalised = pgfx/math.sqrt(pgfx^2 + pgfy^2) - pgfx_normalised = pgfx_normalised - pgfx_normalised%0.00001 - pgfy_normalised = pgfy/math.sqrt(pgfx^2 + pgfy^2) - pgfy_normalised = pgfy_normalised - pgfy_normalised%0.00001 - tex.dimen['pgf@x'] = tostring(pgfx_normalised) .. "pt" - tex.dimen['pgf@y'] = tostring(pgfy_normalised) .. "pt" - end - return nil -end - -return pgfluamathfunctions
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/pgf/libraries/luamath/pgfluamath.parser.lua b/Master/texmf-dist/tex/generic/pgf/libraries/luamath/pgfluamath.parser.lua deleted file mode 100644 index b059e334358..00000000000 --- a/Master/texmf-dist/tex/generic/pgf/libraries/luamath/pgfluamath.parser.lua +++ /dev/null @@ -1,647 +0,0 @@ --- Copyright 2011 by Christophe Jorssen and Mark Wibrow --- --- 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. --- --- $Id: pgfluamath.parser.lua,v 1.14 2012/04/29 20:36:29 ludewich Exp $ - -local pgfluamathparser = pgfluamathparser or {} - -require("pgfluamath.functions") - --- lpeg is always present in luatex -local lpeg = require("lpeg") - -local S, P, R = lpeg.S, lpeg.P, lpeg.R -local C, Cc, Ct = lpeg.C, lpeg.Cc, lpeg.Ct -local Cf, Cg, Cs = lpeg.Cf, lpeg.Cg, lpeg.Cs -local V = lpeg.V - -local space_pattern = S(" \n\r\t")^0 - -local exponent_pattern = S("eE") - -local one_digit_pattern = R("09") -local positive_integer_pattern = one_digit_pattern^1 -local integer_pattern = P("-")^-1 * positive_integer_pattern --- Valid positive decimals are |xxx.xxx|, |.xxx| and |xxx.| -local positive_decimal_pattern = (one_digit_pattern^1 * P(".") * - one_digit_pattern^1) + - (P(".") * one_digit_pattern^1) + - (one_digit_pattern^1 * P(".")) -local decimal_pattern = P("-")^-1 * positive_decimal_pattern -local float_pattern = decimal_pattern * exponent_pattern * integer_pattern -local number_pattern = float_pattern + decimal_pattern + integer_pattern - -local at_pattern = P("@") - -local underscore_pattern = P("_") - -local lower_letter_pattern = R("az") -local upper_letter_pattern = R("AZ") -local letter_pattern = lower_letter_pattern + upper_letter_pattern -local alphanum_pattern = letter_pattern + one_digit_pattern -local alphanum__pattern = alphanum_pattern + underscore_pattern -local alpha__pattern = letter_pattern + underscore_pattern - -local openparen_pattern = P("(") -local closeparen_pattern = P(")") -local opencurlybrace_pattern = P("{") -local closecurlybrace_pattern = P("}") -local openbrace_pattern = P("[") -local closebrace_pattern = P("]") - --- local string = P('"') * C((1 - P('"'))^0) * P('"') - -local orop_pattern = P("||") -local andop_pattern = P("&&") - -local neqop_pattern = P("!=") - -local then_pattern = P("?") -local else_pattern = P(":") -local factorial_pattern = P("!") -local not_mark_pattern = P("!") -local radians_pattern = P("r") - -local comma_pattern = P(",") - ---[[ -local grammar = P { - -- "E" stands for expression - "ternary_logical_E", - ternary_logical_E = Cf(V("logical_or_E") * - Cg( then_mark * V("logical_or_E") * else_mark * V("logical_or_E"))^0,evalternary); - logical_or_E = Cf(V("logical_and_E") * Cg(orop * V("logical_and_E"))^0,evalbinary); - logical_and_E = Cf(V("equality_E") * Cg(andop * V("equality_E"))^0,evalbinary); - equality_E = Cf(V("relational_E") * - Cg((eqop * V("relational_E")) + (neqop * V("relational_E")))^0,evalbinary); - relational_E = Cf(V("additive_E") * Cg((lessop * V("additive_E")) + - (greatop * V("additive_E")) + - (lesseqop * V("additive_E")) + - (greateqop * V("additive_E")))^0,evalbinary); - additive_E = Cf(V("multiplicative_E") * Cg((addop * V("multiplicative_E")) + - (subop * V("multiplicative_E")))^0,evalbinary); - multiplicative_E = Cf(V("power_E") * Cg((mulop * V("power_E")) + - divop * V("power_E"))^0,evalbinary); - power_E = Cf(V("postfix_unary_E") * Cg(powop * V("postfix_unary_E"))^0,evalbinary); - postfix_unary_E = Cf(V("prefix_unary_E") * Cg(radians + factorial)^0,evalpostfixunary); - prefix_unary_E = Cf(Cg(not_mark + negop)^0 * V("E"),evalprefixunary), - E = string + float + decimal + integer / tonumber + - (openparen * V("ternary_logical_E") * closeparen) + - (func * param_beg * V("ternary_logical_E") * - (comma * V("ternary_logical_E"))^0 * param_end); -} - -local parser = space_pattern * grammar * -1 ---]] - --- NOTE: \pgfmathparse{pi/3.14} will fail giving pgfluamathfunctions.pi()3.14 --- (the / is missing, probably gobbled by one of the captures of the grammar). - -pgfluamathparser.transform_operands = P({ - 'transform_operands'; - - one_char = lpeg.P(1), - lowercase = lpeg.R('az'), - uppercase = lpeg.R('AZ'), - numeric = lpeg.R('09'), - dot = lpeg.P('.'), - exponent = lpeg.S('eE'), - sign_prefix = lpeg.S('-+'), - begingroup = lpeg.P('('), - endgroup = lpeg.P(')'), - backslash = lpeg.P'\\', - at = lpeg.P'@', - - alphabetic = lpeg.V'lowercase' + lpeg.V'uppercase', - alphanumeric = lpeg.V'alphabetic' + lpeg.V'numeric', - - integer = lpeg.V'numeric'^1, - real = lpeg.V'numeric'^0 * lpeg.V'dot' * lpeg.V'numeric'^1, - scientific = (lpeg.V'real' + lpeg.V'integer') * lpeg.V'exponent' * lpeg.V'sign_prefix'^0 * lpeg.V'integer', - - number = lpeg.V'scientific' + lpeg.V'real' + lpeg.V'integer', - function_name = lpeg.V('alphabetic') * lpeg.V('alphanumeric')^0, - - tex_cs = lpeg.V'backslash' * (lpeg.V'alphanumeric' + lpeg.V'at')^1, - tex_box_dimension_primative = lpeg.V'backslash' * (lpeg.P'wd' + lpeg.P'ht' + lpeg.P'dp'), - tex_register_primative = lpeg.V'backslash' * (lpeg.P'count' + lpeg.P'dimen'), - - tex_primative = lpeg.V'tex_box_dimension_primative' + lpeg.V'tex_register_primative', - tex_macro = -lpeg.V'tex_primative' * lpeg.V'tex_cs', - - tex_unit = - lpeg.P('pt') + lpeg.P('mm') + lpeg.P('cm') + lpeg.P('in') + - lpeg.P('ex') + lpeg.P('em') + lpeg.P('bp') + lpeg.P('pc') + - lpeg.P('dd') + lpeg.P('cc') + lpeg.P('sp'), - - tex_register_named = lpeg.C(lpeg.V'tex_macro'), - tex_register_numbered = lpeg.C(lpeg.V'tex_register_primative') * lpeg.C(lpeg.V'integer'), - tex_register_basic = lpeg.Cs(lpeg.Ct(lpeg.V'tex_register_numbered' + lpeg.V'tex_register_named') / pgfluamathparser.process_tex_register), - - tex_multiplier = lpeg.Cs((lpeg.V'tex_register_basic' + lpeg.C(lpeg.V'number')) / pgfluamathparser.process_muliplier), - - tex_box_width = lpeg.Cs(lpeg.P('\\wd') / 'width'), - tex_box_height = lpeg.Cs(lpeg.P('\\ht') / 'height'), - tex_box_depth = lpeg.Cs(lpeg.P('\\dp') / 'depth'), - tex_box_dimensions = lpeg.V'tex_box_width' + lpeg.V'tex_box_height' + lpeg.V'tex_box_depth', - tex_box_named = lpeg.Cs(lpeg.Ct(lpeg.V'tex_box_dimensions' * lpeg.C(lpeg.V'tex_macro')) / pgfluamathparser.process_tex_box_named), - tex_box_numbered = lpeg.Cs(lpeg.Ct(lpeg.V'tex_box_dimensions' * lpeg.C(lpeg.V'number')) / pgfluamathparser.process_tex_box_numbered), - tex_box_basic = lpeg.V'tex_box_named' + lpeg.V'tex_box_numbered', - - tex_register = lpeg.Cs(lpeg.V'tex_multiplier' * lpeg.V'tex_register_basic') + lpeg.V'tex_register_basic', - tex_box = lpeg.Cs(lpeg.Cs(lpeg.V'tex_multiplier') * lpeg.V'tex_box_basic') + lpeg.V'tex_box_basic', - tex_dimension = lpeg.Cs(lpeg.V'number' * lpeg.V'tex_unit' / pgfluamathparser.process_tex_dimension), - - tex_operand = lpeg.Cs(lpeg.V'tex_dimension' + lpeg.V'tex_box' + lpeg.V'tex_register'), - - function_name = lpeg.V'alphabetic' * (lpeg.V'alphanumeric'^1), - function_operand = lpeg.Cs(lpeg.Ct(lpeg.C(lpeg.V'function_name') * lpeg.C(lpeg.V'one_char') + lpeg.C(lpeg.V'function_name')) / pgfluamathparser.process_function), - - -- order is (always) important! - operands = lpeg.V'tex_operand' + lpeg.V'number' + lpeg.V'function_operand', - - transform_operands = lpeg.Cs((lpeg.V'operands' + 1)^0) - }) - --- Namespaces will be searched in the following order. -pgfluamathparser.function_namespaces = { - 'pgfluamathfunctions', 'math', '_G'} - -pgfluamathparser.units_declared = false - -function pgfluamathparser.get_tex_box(box, dimension) - -- assume get_tex_box is only called when a dimension is required. - pgfluamathparser.units_declared = true - if dimension == 'width' then - return tex.box[box].width / 65536 -- return in points. - elseif dimension == 'height' then - return tex.box[box].height / 65536 - else - return tex.box[box].depth / 65536 - end -end - -function pgfluamathparser.get_tex_register(register) - -- register is a string which could be a count or a dimen. - if pcall(tex.getcount, register) then - return tex.count[register] - elseif pcall(tex.getdimen, register) then - pgfluamathparser.units_declared = true - return tex.dimen[register] / 65536 -- return in points. - else - pgfluamathparser.error = 'I do not know the TeX register "' .. register '"' - return nil - end - -end - -function pgfluamathparser.get_tex_count(count) - -- count is expected to be a number - return tex.count[tonumber(count)] -end - -function pgfluamathparser.get_tex_dimen(dimen) - -- dimen is expected to be a number - pgfluamathparser.units_declared = true - return tex.dimen[tonumber(dimen)] / 65536 -end - -function pgfluamathparser.get_tex_sp(dimension) - -- dimension should be a string - pgfluamathparser.units_declared = true - return tex.sp(dimension) / 65536 -end - - - --- transform named box specification --- e.g., \wd\mybox -> pgfluamathparser.get_tex_box["mybox"].width --- -function pgfluamathparser.process_tex_box_named(box) - return 'pgfluamathparser.get_tex_box(\\number' .. box[2] .. ', "' .. box[1] .. '")' -end - --- transform numbered box specification --- e.g., \wd0 -> pgfluamathparser.get_tex_box["0"].width --- -function pgfluamathparser.process_tex_box_numbered(box) - return 'pgfluamathparser.get_tex_box("' .. box[2] .. '", "' .. box[1] .. '")' -end - --- transform a register --- e.g., \mycount -> pgfluamathparser.get_tex_register["mycount"] --- \dimen12 -> pgfluamathparser.get_tex_dimen[12] --- -function pgfluamathparser.process_tex_register(register) - if register[2] == nil then -- a named register - return 'pgfluamathparser.get_tex_register("' .. register[1]:sub(2, register[1]:len()) .. '")' - else -- a numbered register - return 'pgfluamathparser.get_tex_' .. register[1]:sub(2, register[1]:len()) .. '(' .. register[2] .. ')' - end -end - --- transform a 'multiplier' --- e.g., 0.5 -> 0.5* (when followed by a box/register) --- -function pgfluamathparser.process_muliplier(multiplier) - return multiplier .. '*' -end - --- transform an explicit dimension to points --- e.g., 1cm -> pgfluamathparser.get_tex_sp("1cm") --- -function pgfluamathparser.process_tex_dimension(dimension) - return 'pgfluamathparser.get_tex_sp("' .. dimension .. '")' -end - --- Check the type and 'namespace' of a function F. --- --- If F cannot be found as a Lua function or a Lua number in the --- namespaces in containted in pgfluamathparser.function_namespaces --- then an error results. --- --- if F is a Lua function and isn't followd by () (a requirement of Lua) --- then the parentheses are inserted. --- --- e.g., random -> random() (if random is a function in the _G namespace) --- pi -> math.pi (if pi is a constant that is only in the math namespace) --- -function pgfluamathparser.process_function(function_table) - local function_name = function_table[1] - local char = function_table[2] - if (char == nil) then - char = '' - end - for _, namespace in pairs(pgfluamathparser.function_namespaces) do - local function_type = assert(loadstring('return type(' .. namespace .. '.' .. function_name .. ')'))() - if function_type == 'function' then - if not (char == '(') then - char = '()' - end - return namespace .. '.' .. function_name .. char - elseif function_type == 'number' then - return namespace .. '.' .. function_name .. char - end - end - pgfluamathparser.error = 'I don\'t know the function or constant \'' .. function_name .. '\'' -end - - -pgfluamathparser.remove_spaces = lpeg.Cs((lpeg.S' \n\t' / '' + 1)^0) - - -function pgfluamathparser.evaluate(expression) - assert(loadstring('pgfluamathparser._result=' .. expression))() - pgfluamathparser.result = pgfluamathparser._result -end - -function pgfluamathparser.parse(expression) - pgfluamathparser.write_to_log("Parsing expression:" .. expression) - pgfluamathparser.units_declared = false - - pgfluamathparser.error = nil - pgfluamathparser.result = nil - - -- Remove spaces - expression = pgfluamathparser.remove_spaces:match(expression) - - parsed_expression = - pgfluamathparser.transform_operands:match(expression) - pgfluamathparser.write_to_log("Transformed expression:" - .. parsed_expression) -end - -function pgfluamathparser.eval(expression) - pgfluamathparser.write_to_log("Evaluating expression:" .. expression) - pcall(pgfluamathparser.evaluate, expression) - pgfluamathparser.write_to_log("Result:" .. pgfluamathparser.result) - if pgfluamathparser.result == nil then - pgfluamathparser.error = "Sorry, I could not evaluate '" .. expression .. "'" - return nil - else - return pgfluamathparser.result - end -end - -pgfluamathparser.trace = true - -function pgfluamathparser.write_to_log (s) - if pgfluamathparser.trace then - texio.write_nl(s) - end -end - -return pgfluamathparser - ---[[ NEW: 2012/02/21, CJ, work in progress --- We need 3 parsers (or 2, 2 and 3 could be merged) --- (1) To get the number associated with a (\chardef'ed) box (e.g. --- \ht\mybox -> \ht26) --- This is part of a TeX ->(\directlua == \edef) -> lua -> (lpeg parser 1) --- -> TeX -> (\directlua == \edef) --- (2) To transform math and functions operands --- (3) To transform units, dimen and count register - --- TODO: strings delimited by "..." --- TODO: units. \pgfmathparse{12+1cm}\pgfmathresult and \the\dimexpr 12pt+1cm\relax have the same result. Note: \pgfmathparse{(12+1)cm} won't work in plain pgfmath. --- TODO: Parser 3 - - -pgfluamath = pgfluamath or {} - -pgfluamath.debug = true - -local lpeg = require('lpeg') -local P, R, S, V = lpeg.P, lpeg.R, lpeg.S, lpeg.V -local C, Cc, Cs = lpeg.C, lpeg.Cc, lpeg.Cs -local Cf, Cg, Ct = lpeg.Cf, lpeg.Cg, lpeg.Ct -local match = lpeg.match - -local space = S(' \n\t') - -local lowercase = R('az') -local uppercase = R('AZ') -local alphabetic = lowercase + uppercase - -local digit = R('09') - -local alphanumeric = alphabetic + digit - -local dot = P('.') -local exponent = S('eE') -local sign_prefix = S('+-') - -local integer = digit^1 -local float = (digit^1 * dot * digit^0) + (digit^0 * dot * digit^1) -local scientific = (float + integer) * exponent * sign_prefix^-1 * integer - -local number = scientific + float + integer - -local at = P('@') - -local backslash = P('\\') - -local box_width = P('\\wd') -local box_height = P('\\ht') -local box_depth = P('\\dp') -local box_dimension = box_width + box_height + box_depth - -local tex_cs = backslash * (alphabetic + at)^1 - -local lparen = P('(') -local rparen = P(')') - -local lbrace = P('{') -local rbrace = P('}') - -local lbracket = P('[') -local rbracket = P(']') - -local thenop = P('?') -local elseop = P(':') - -local orop = P('||') -local andop = P('&&') - -local eqop = P('==') -local neqop = P('!=') - -local greaterop = P('>') -local lessop = P('<') -local greatereqop = P('>=') -local lesseqop = P('<=') - -local addop = P('+') -local subop = P('-') - -local mulop = P('*') -local divop = P('/') - -local powop = P('^') - -local radop = P('r') - -local notop = P('!') -local negop = P('-') - -local comma = P(',') - -function pgfluamath.namedbox_to_numberedbox (s) - -- Transforms '{\wd|\ht|\dp}\mybox' to '{\wd|\ht|\dp}\number\mybox' - local function transform (capture) - print('Captured ' .. capture) - return '\\number' .. capture - end - local dimension_of_a_named_box = - box_dimension * space^0 * (tex_cs / transform) - -- P(1) matches exactly one character - -- V(1) is the entry of the grammar with index 1. It defines the initial rule. - -- The manual says: - -- "If that entry is a string, it is assumed to be the name of the initial rule. - -- Otherwise, LPeg assumes that the entry 1 itself is the initial rule." - local grammar = - P({ - [1] = (dimension_of_a_named_box + P(1)) * V(1) + P(true) - }) - return print(match(Cs(grammar),s)) -end ---[[ -namedbox_to_numberedbox('test') -namedbox_to_numberedbox('\\test') -namedbox_to_numberedbox('\\wd\\test') -namedbox_to_numberedbox('\\wd\\test0') -namedbox_to_numberedbox('\\wd\\test01') -namedbox_to_numberedbox('\\wd\\test@t 012') -namedbox_to_numberedbox(' \\wd \\test012') -namedbox_to_numberedbox('\\wd\\test012\\test \\ht\\zozo0') -namedbox_to_numberedbox('\\wd0') ---]] - --- Grammar (from lowest to highest precedence) --- Need to adjust to the precedences in plain pgfmath parser --- IfThenElse Expression -local ITE_E = V('ITE_E') --- logical OR Expression -local OR_E = V('OR_E') --- logical AND Expression -local AND_E = V('AND_E') --- EQuality Expression -local EQ_E = V('EQ_E') --- Relational EQuality Expression -local REQ_E = V('REQ_E') --- ADDitive Expression -local ADD_E = V('ADD_E') --- MULtiplicative Expression -local MUL_E = V('MUL_E') --- POWer Expression -local POW_E = V('POW_E') --- POSTfix Expression -local POST_E = V('POST_E') --- PREfix Expression -local PRE_E = V('PRE_E') --- ARRAY Expression -local ARRAY_E = V('ARRAY_E') --- Expression -local E = V('E') - -function pgfluamath.transform_math_expr (s, f_patt) - if pgfluamath.debug then - texio.write_nl('pgfluamath: parsing expression "' .. s ..'"') - end - -- f_patt extends the grammar dynamically at the time of the call to the - -- parser. - -- The idea is to have a set of predefined acceptable functions (via e.g. - -- \pgfmathdeclarefunction) - if not f_patt then - -- P(false) is a pattern that always fails - -- (neutral element for the + operator on patterns) - f_patt = P(false) - end - local function transform_ITE(a, b, c) - if not b then - return a - else - return string.format('pgfluamath.defined_functions.ifthenelse.code(%s,%s,%s)', a, b, c) - end - end - local function transform_binary(a, b, c) - if not b then - return a - else - return string.format('pgfluamath.defined_functions.%s.code(%s,%s)', b, a, c) - end - end - local function transform_postunary(a, b) - if not b then - return a - else - return string.format('pgfluamath.defined_functions.%s.code(%s)', b, a) - end - end - local function transform_preunary(a, b) - if not b then - return a - else - return string.format('pgfluamath.defined_functions.%s.code(%s)', a, b) - end - end - local function transform_array(a, b) - -- One exception to the mimmic of plain pgfmath. I do not use the equivalent array function to transform the arrays because I don't know how to handle both cases {1,{2,3}[1],4}[1] and {1,{2,3},4}[1][1] with the parser and the array function. - -- So I convert a pgf array to a lua table. One can access one entry of the table like this ({1,2})[1] (note the parenthesis, ie {1,2}[1] won't work). - local s - if not b then - s = '{' - else - s = '({' - end - for i = 1,#a do - -- We change the index to fit with pgfmath plain convention (index starts at 0 while in lua index starts at 1) - s = s .. '[' .. tostring(i-1) .. ']=' .. a[i] - if i < #a then - s = s .. ',' - end - end - if b then - s = s .. '})' - for i = 1,#b do - s = s .. '[' .. b[i] .. ']' - end - else - s = s .. '}' - end - return s - end - local grammar = - lpeg.P({ - 'ITE_E', - ITE_E = (OR_E * (thenop * OR_E * elseop * OR_E)^-1) / transform_ITE, - OR_E = (AND_E * (orop * Cc('orPGF') * AND_E)^-1) / transform_binary, - AND_E = (EQ_E * (andop * Cc('andPGF') * EQ_E)^-1) / transform_binary, - EQ_E = (REQ_E * ((eqop * Cc('equal') + neqop * Cc('notequal')) * REQ_E)^-1) / transform_binary, - REQ_E = (ADD_E * ((lessop * Cc('less') + greaterop * Cc('greater') + lesseqop * Cc('notgreater') + greatereqop * Cc('notless')) * ADD_E)^-1) / transform_binary, - ADD_E = Cf(MUL_E * Cg((addop * Cc('add') + subop * Cc('substract')) * MUL_E)^0,transform_binary), - MUL_E = Cf(POW_E * Cg((mulop * Cc('multiply') + divop * Cc('divide')) * POW_E)^0,transform_binary), - POW_E = Cf(POST_E * Cg(powop * Cc('pow') * POST_E)^0,transform_binary), - POST_E = (PRE_E * (radop * Cc('rad'))^-1) / transform_postunary, - PRE_E = ((notop * Cc('notPGF') + negop * Cc('neg'))^-1 * E) / transform_preunary, - ARRAY_E = (lbrace * Ct(ITE_E * (comma * ITE_E)^0) * rbrace * Ct((lbracket * ITE_E * rbracket)^0)) / transform_array, - E = ((integer + float)^-1 * tex_cs^1) + f_patt + C(number) + (lparen * ITE_E * rparen) + ARRAY_E + lbrace * ITE_E * rbrace - }) - return lpeg.match(Cs(grammar),s) -end - -function pgfluamath.ptransform_math_expr(s, f_patt) - local st = pgfluamath.transform_math_expr(s, f_patt) - if st ~= nil then - return texio.write_nl(st) - end -end - -pgfluamath.defined_functions = {} -pgfluamath.defined_functions_pattern = P(false) - -function pgfluamath.declare_new_function (name, nargs, code) - -- nil is true - -- The function name CANNOT be a lua reserved word (so no 'and' nor 'or') - if pgfluamath.defined_functions[name] then - print('Function ' .. name .. ' is already defined. ' .. - 'I overwrite it!') - end - pgfluamath.defined_functions[name] = {['name'] = name, ['nargs'] = nargs, ['code'] = code} - - -- TODO - -- We need a function to dynamically (depending on the number of arguments) define a patten (in order to avoid the long ifcase-type structure). - local pattern - if nargs == 0 then - pattern = P(name) / function (s) return name .. '()' end - else if nargs == 1 then - pattern = ((P(name) * lparen * Cs(ITE_E) * rparen) / function (s) return 'pgfluamath.defined_functions.' .. name .. '.code(' .. s .. ')' end) - else if nargs == 2 then - pattern = (P(name) * lparen * Cs(ITE_E) * comma * Cs(ITE_E) * rparen / function (s1,s2) return 'pgfluamath.defined_functions.' .. name .. 'code(' .. s1 .. ',' .. s2 .. ')' end) - else if nargs == 3 then - pattern = (P(name) * lparen * Cs(ITE_E) * comma * Cs(ITE_E) * comma * Cs(ITE_E) * rparen / function (s1,s2,s3) return 'pgfluamath.defined_functions.' .. name .. 'code(' .. s1 .. ',' .. s2 .. ',' .. s3 .. ')' end) - end - end - end - end - -- TODO - -- This needs to be regenerated every time a new function is added, in conjunction with a sort of the table (see IMPORTANT below) - pgfluamath.defined_functions_pattern = pgfluamath.defined_functions_pattern + pattern -end - --- IMPORTANT: for 'function' with *0* argument, the longest string, the first --- ie declaring pi before pit won't work. -pgfluamath.declare_new_function('pit',0) -pgfluamath.declare_new_function('pi',0) -pgfluamath.declare_new_function('exp',1) -pgfluamath.declare_new_function('toto',1) -pgfluamath.declare_new_function('gauss',2) - -pgfluamath.ptransform_math_expr('exp(exp(1+1))',pgfluamath.defined_functions_pattern) - -pgfluamath.ptransform_math_expr('1?(2?3:4^5):gauss(6+toto(7),8+9>10?11:12))',pgfluamath.defined_functions_pattern) - -pgfluamath.ptransform_math_expr('!(1!=-2)>3?(4+5*6+7?8||9&&10:11):12^13r||14') -pgfluamath.ptransform_math_expr('-1^2\\test\\toto^3') -pgfluamath.ptransform_math_expr('{1,{2+3,4}[1],5}[2]+6') -pgfluamath.ptransform_math_expr('{1,{2+3,4},5}[1][1]') -pgfluamath.ptransform_math_expr('{1,{2,3},4}[1][1]') -pgfluamath.ptransform_math_expr('{1,{2,3}[1],4}[1]') - ---Loadstring: If it succeeds in converting the string to a *function*, it returns that function; otherwise, it returns nil and an error message. -toto = loadstring('texio.write_nl(' .. pgfluamath.transform_math_expr('{1,{2,3},4}[1][1]') .. ')') -toto() - --- IMPORTANT NOTE!! --- local function add (a,b) will fail within loadstring. Needs to be global. loadstring opens a new chunk that does not know the local variables of other chunks. - ---toto = loadstring('texio.write_nl(' .. pgfluamath.transform_math_expr('{1,{2,3E-1+7}[1],4}[1]') .. ')') ---toto() - -return pgfluamath diff --git a/Master/texmf-dist/tex/generic/pgf/libraries/pgflibraryarrows.meta.code.tex b/Master/texmf-dist/tex/generic/pgf/libraries/pgflibraryarrows.meta.code.tex index 77edfcd8dc6..80b2573a0c4 100644 --- a/Master/texmf-dist/tex/generic/pgf/libraries/pgflibraryarrows.meta.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/libraries/pgflibraryarrows.meta.code.tex @@ -7,7 +7,7 @@ % % See the file doc/generic/pgf/licenses/LICENSE for more details. -\ProvidesFileRCS[v\pgfversion] $Header: /cvsroot/pgf/pgf/generic/pgf/libraries/pgflibraryarrows.meta.code.tex,v 1.12 2013/12/13 15:11:58 tantau Exp $ +\ProvidesFileRCS[v\pgfversion] $Header: /cvsroot/pgf/pgf/generic/pgf/libraries/pgflibraryarrows.meta.code.tex,v 1.13 2015/05/13 21:19:11 cfeuersaenger Exp $ @@ -139,13 +139,13 @@ }, setup code = { % Compute front miter length: - \pgfmathdivide@\pgfarrowlength\pgfarrowwidth% + \pgfmathdivide@{\pgf@sys@tonumber\pgfarrowlength}{\pgf@sys@tonumber\pgfarrowwidth}% \let\pgf@temp@quot\pgfmathresult% \pgf@x\pgfmathresult pt% \pgf@x\pgfmathresult\pgf@x% \pgf@x4\pgf@x% \advance\pgf@x by1pt% - \pgfmathsqrt@\pgf@x% + \pgfmathsqrt@{\pgf@sys@tonumber\pgf@x}% \pgf@xc\pgfmathresult\pgfarrowlinewidth% xc is front miter \pgf@xc.5\pgf@xc \pgf@xa\pgf@temp@quot\pgfarrowlinewidth% xa is extra harpoon miter @@ -548,13 +548,13 @@ \advance\pgfutil@tempdimb by-\pgfarrowlinewidth \ifpgfarrowroundjoin% \else% - \pgfmathdivide@\pgfutil@tempdima\pgfutil@tempdimb% + \pgfmathdivide@{\pgf@sys@tonumber\pgfutil@tempdima}{\pgf@sys@tonumber\pgfutil@tempdimb}% \let\pgf@temp@quot\pgfmathresult% \pgf@x\pgfmathresult pt% \pgf@x\pgfmathresult\pgf@x% \pgf@x40.96\pgf@x% \advance\pgf@x by1pt% \pgflinewidth^2 + (6.4 \pgftempdim@a / \pgfutil@tempdimb) \pgflinewidth^2 - \pgfmathsqrt@\pgf@x% + \pgfmathsqrt@{\pgf@sys@tonumber\pgf@x}% \pgf@xc\pgfmathresult\pgfarrowlinewidth% xc is front miter \pgf@xc.5\pgf@xc \fi% @@ -686,13 +686,13 @@ % Front miter: \ifpgfarrowroundjoin% \else% - \pgfmathdivide@\pgfutil@tempdima\pgfutil@tempdimb% + \pgfmathdivide@{\pgf@sys@tonumber\pgfutil@tempdima}{\pgf@sys@tonumber\pgfutil@tempdimb}% \let\pgf@temp@quot\pgfmathresult% \pgf@x\pgfmathresult pt% \pgf@x\pgfmathresult\pgf@x% \pgf@x49.44662\pgf@x% \advance\pgf@x by1pt% \pgfarrowlinewidth^2 + (0.41019/0.0583333 \pgftempdim@a / \pgfutil@tempdimb) \pgfarrowlinewidth^2 - \pgfmathsqrt@\pgf@x% + \pgfmathsqrt@{\pgf@sys@tonumber\pgf@x}% \pgf@xc\pgfmathresult\pgfarrowlinewidth% xc is front miter \pgf@xc.5\pgf@xc \pgf@xa\pgf@temp@quot\pgfarrowlinewidth% xa is extra harpoon miter @@ -826,13 +826,13 @@ \fi \pgfarrowssavethe\pgfarrowlinewidth% % Compute front miter length: - \pgfmathdivide@\pgfarrowlength\pgfarrowwidth% + \pgfmathdivide@{\pgf@sys@tonumber\pgfarrowlength}{\pgf@sys@tonumber\pgfarrowwidth}% \let\pgf@temp@quot\pgfmathresult% \pgf@x\pgfmathresult pt% \pgf@x\pgfmathresult\pgf@x% \pgf@x9\pgf@x% \advance\pgf@x by1pt% - \pgfmathsqrt@\pgf@x% + \pgfmathsqrt@{\pgf@sys@tonumber\pgf@x}% \pgf@xc\pgfmathresult\pgfarrowlinewidth% \pgf@xa\pgf@temp@quot\pgfarrowlinewidth % Inner length (pgfutil@tempdima) is now arrowlength - front miter @@ -862,7 +862,7 @@ \pgf@process{\pgfpointnormalised{\pgfqpoint{.3\pgfarrowlength}{.2333333\pgfarrowwidth}}}% \advance\pgf@y by1pt% \pgf@yc\pgf@y\pgf@xc\pgf@x% - \pgfmathdivide@\pgf@yc\pgf@xc% + \pgfmathdivide@{\pgf@sys@tonumber\pgf@yc}{\pgf@sys@tonumber\pgf@xc}% \pgfutil@tempdimb\pgfmathresult\pgfarrowlinewidth% \pgfutil@tempdimb-.5\pgfutil@tempdimb% \advance\pgfutil@tempdimb by.5\pgfarrowwidth% @@ -922,13 +922,13 @@ \pgfarrowlinewidth\pgf@x \fi % Compute front miter length: - \pgfmathdivide@\pgfarrowlength\pgfarrowwidth% + \pgfmathdivide@{\pgf@sys@tonumber\pgfarrowlength}{\pgf@sys@tonumber\pgfarrowwidth}% \let\pgf@temp@quot\pgfmathresult% \pgf@x\pgfmathresult pt% \pgf@x\pgfmathresult\pgf@x% \pgf@x4\pgf@x% \advance\pgf@x by1pt% - \pgfmathsqrt@\pgf@x% + \pgfmathsqrt@{\pgf@sys@tonumber\pgf@x}% \pgf@xc\pgfmathresult\pgfarrowlinewidth% xc is front miter \pgf@xc.5\pgf@xc \pgf@xa\pgf@temp@quot\pgfarrowlinewidth% xa is extra harpoon miter @@ -940,25 +940,25 @@ \pgf@ya\pgfmathresult pt% \advance\pgf@yb by-\pgf@ya% \pgf@yb.5\pgf@yb% half angle in yb - \pgfmathtan@{\pgf@yb}% + \pgfmathtan@{\pgf@sys@tonumber\pgf@yb}% \pgfmathreciprocal@{\pgfmathresult}% \pgf@yc\pgfmathresult\pgfarrowlinewidth% \pgf@yc.5\pgf@yc% \advance\pgf@ya by\pgf@yb% - \pgfmathsincos@{\pgf@ya}% + \pgfmathsincos@{\pgf@sys@tonumber\pgf@ya}% \pgf@ya\pgfmathresulty\pgf@yc% ya is the back miter \pgf@yb\pgfmathresultx\pgf@yc% yb is the top miter \ifdim\pgfarrowinset=0pt% \pgf@ya.5\pgfarrowlinewidth% easy: back miter is half linewidth \fi % Compute inset miter length: - \pgfmathdivide@\pgfarrowinset\pgfarrowwidth% + \pgfmathdivide@{\pgf@sys@tonumber\pgfarrowinset}{\pgf@sys@tonumber\pgfarrowwidth}% \let\pgf@temp@quot\pgfmathresult% \pgf@x\pgfmathresult pt% \pgf@x\pgfmathresult\pgf@x% \pgf@x4\pgf@x% \advance\pgf@x by1pt% - \pgfmathsqrt@\pgf@x% + \pgfmathsqrt@{\pgf@sys@tonumber\pgf@x}% \pgf@yc\pgfmathresult\pgfarrowlinewidth% yc is inset miter \pgf@yc.5\pgf@yc% % Inner length (pgfutil@tempdima) is now arrowlength - front miter - back miter @@ -1054,24 +1054,24 @@ % Compute front miter length: \pgf@xa\pgfarrowlength% \advance\pgf@xa by-\pgfarrowinset% - \pgfmathdivide@\pgf@xa\pgfarrowwidth% + \pgfmathdivide@{\pgf@sys@tonumber\pgf@xa}{\pgf@sys@tonumber\pgfarrowwidth}% \let\pgf@temp@quot\pgfmathresult% \pgf@x\pgfmathresult pt% \pgf@x\pgfmathresult\pgf@x% \pgf@x4\pgf@x% \advance\pgf@x by1pt% - \pgfmathsqrt@\pgf@x% + \pgfmathsqrt@{\pgf@sys@tonumber\pgf@x}% \pgf@xc\pgfmathresult\pgfarrowlinewidth% xc is front miter \pgf@xc.5\pgf@xc \pgf@xa\pgf@temp@quot\pgfarrowlinewidth% xa is extra harpoon miter % Compute back miter length: - \pgfmathdivide@\pgfarrowinset\pgfarrowwidth% + \pgfmathdivide@{\pgf@sys@tonumber\pgfarrowinset}{\pgf@sys@tonumber\pgfarrowwidth}% \let\pgf@temp@quot\pgfmathresult% \pgf@x\pgfmathresult pt% \pgf@x\pgfmathresult\pgf@x% \pgf@x4\pgf@x% \advance\pgf@x by1pt% - \pgfmathsqrt@\pgf@x% + \pgfmathsqrt@{\pgf@sys@tonumber\pgf@x}% \pgf@yc\pgfmathresult\pgfarrowlinewidth% yc is back miter \pgf@yc.5\pgf@yc \pgf@ya\pgf@temp@quot\pgfarrowlinewidth% ya is extra harpoon miter @@ -1088,7 +1088,7 @@ \ifdim\pgf@yb=45pt% \def\pgfmathresult{1.414213}% \else% - \pgfmathsin@{\pgf@yb}% + \pgfmathsin@{\pgf@sys@tonumber\pgf@yb}% \pgfmathreciprocal@{\pgfmathresult}% \fi% \pgf@yc\pgfmathresult\pgfarrowlinewidth% @@ -1096,7 +1096,7 @@ \pgf@ya-\pgf@ya% \advance\pgf@ya by-90pt% \advance\pgf@ya by\pgf@yb% - \pgfmathsincos@{\pgf@ya}% + \pgfmathsincos@{\pgf@sys@tonumber\pgf@ya}% \pgf@xb\pgfmathresultx\pgf@yc% ya is the back miter \pgf@yb\pgfmathresulty\pgf@yc% yb is the top miter \expandafter\expandafter\expandafter% @@ -1368,7 +1368,7 @@ cap angle/.code={% \pgfmathsetlength\pgf@x{#1}% \pgf@x.5\pgf@x - \pgfmathtan@{\pgf@x}% + \pgfmathtan@{\pgf@sys@tonumber\pgf@x}% \pgfmathreciprocal@{\pgfmathresult}% \pgf@x\pgfmathresult pt% \pgf@x.5\pgf@x% @@ -1530,7 +1530,7 @@ % Compute tips: \pgf@xa\pgfarrow@inc pt% \ifodd\pgfarrown\pgf@ya.25\pgf@xa\else\pgf@ya.5\pgf@xa\fi% - \pgfmathsincos@\pgf@ya% + \pgfmathsincos@{\pgf@sys@tonumber\pgf@ya}% \pgf@x.5\pgfarrowlength% \pgf@xa\pgfmathresultx\pgf@x% \ifpgfarrowroundcap diff --git a/Master/texmf-dist/tex/generic/pgf/libraries/pgflibrarycurvilinear.code.tex b/Master/texmf-dist/tex/generic/pgf/libraries/pgflibrarycurvilinear.code.tex index 18fa1951b05..2ae9eb00e5a 100644 --- a/Master/texmf-dist/tex/generic/pgf/libraries/pgflibrarycurvilinear.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/libraries/pgflibrarycurvilinear.code.tex @@ -7,7 +7,7 @@ % % See the file doc/generic/pgf/licenses/LICENSE for more details. -\ProvidesFileRCS[v\pgfversion] $Header: /cvsroot/pgf/pgf/generic/pgf/libraries/pgflibrarycurvilinear.code.tex,v 1.3 2013/10/07 15:51:46 tantau Exp $ +\ProvidesFileRCS[v\pgfversion] $Header: /cvsroot/pgf/pgf/generic/pgf/libraries/pgflibrarycurvilinear.code.tex,v 1.4 2015/05/14 14:43:05 cfeuersaenger Exp $ % % This file defines commands for computing points in curvilinear @@ -75,7 +75,7 @@ \pgf@yb=-\pgf@y% \advance\pgf@x by\pgf@xa% \advance\pgf@y by\pgf@ya% - \pgfmathveclen@{\pgf@x}{\pgf@y}% + \pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}% \let\pgf@curvilinear@lenab\pgfmathresult% \pgf@process{#3}% \edef\pgf@curvilinear@line@c{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}% @@ -83,26 +83,26 @@ \pgf@yc=-\pgf@y% \advance\pgf@x by\pgf@xb% \advance\pgf@y by\pgf@yb% - \pgfmathveclen@{\pgf@x}{\pgf@y}% + \pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}% \let\pgf@curvilinear@lenbc\pgfmathresult% \pgf@process{#4}% \edef\pgf@curvilinear@line@d{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}% \advance\pgf@x by\pgf@xc% \advance\pgf@y by\pgf@yc% - \pgfmathveclen@{\pgf@x}{\pgf@y}% + \pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}% \let\pgf@curvilinear@lencd\pgfmathresult % \pgf@x=\pgf@curvilinear@lenab pt% \advance\pgf@x by\pgf@curvilinear@lenbc pt% \advance\pgf@x by\pgf@curvilinear@lencd pt% - \pgfmathreciprocal@{\pgf@x}% + \pgfmathreciprocal@{\pgf@sys@tonumber\pgf@x}% \pgf@curvilinear@time@a\pgfmathresult pt% \pgf@process{\pgfpointcurveattime{\pgf@curvilinear@time@a}{\pgf@curvilinear@line@a}{\pgf@curvilinear@line@b}{\pgf@curvilinear@line@c}{\pgf@curvilinear@line@d}}% \pgf@xb=-\pgf@x% \pgf@yb=-\pgf@y% \advance\pgf@x by\pgf@xa% \advance\pgf@y by\pgf@ya% - \pgfmathveclen@{\pgf@x}{\pgf@y}% + \pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}% \pgf@curvilinear@length@a\pgfmathresult pt% \ifdim\pgf@curvilinear@length@a>1pt\relax% % Ok, too large, let us make this smaller @@ -113,7 +113,7 @@ \pgf@yb=-\pgf@y% \advance\pgf@x by\pgf@xa% \advance\pgf@y by\pgf@ya% - \pgfmathveclen@{\pgf@x}{\pgf@y}% + \pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}% \pgf@curvilinear@length@a\pgfmathresult pt% \fi% % Compute three positions: @@ -122,7 +122,7 @@ \pgf@ya=-\pgf@y% \advance\pgf@x by\pgf@xb% \advance\pgf@y by\pgf@yb% - \pgfmathveclen@{\pgf@x}{\pgf@y}% + \pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}% \pgf@curvilinear@length@b\pgfmathresult pt% \advance\pgf@curvilinear@length@b by\pgf@curvilinear@length@a% \pgf@process{\pgfpointcurveattime{4\pgf@curvilinear@time@a}{\pgf@curvilinear@line@a}{\pgf@curvilinear@line@b}{\pgf@curvilinear@line@c}{\pgf@curvilinear@line@d}} @@ -130,13 +130,13 @@ \pgf@yb=-\pgf@y% \advance\pgf@x by\pgf@xa% \advance\pgf@y by\pgf@ya% - \pgfmathveclen@{\pgf@x}{\pgf@y}% + \pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}% \pgf@curvilinear@length@c\pgfmathresult pt% \advance\pgf@curvilinear@length@c by\pgf@curvilinear@length@b% \pgf@process{\pgfpointcurveattime{8\pgf@curvilinear@time@a}{\pgf@curvilinear@line@a}{\pgf@curvilinear@line@b}{\pgf@curvilinear@line@c}{\pgf@curvilinear@line@d}} \advance\pgf@x by\pgf@xb% \advance\pgf@y by\pgf@yb% - \pgfmathveclen@{\pgf@x}{\pgf@y}% + \pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}% \pgf@curvilinear@length@d\pgfmathresult pt% \advance\pgf@curvilinear@length@d by\pgf@curvilinear@length@c% \let\pgf@curvilinear@comp@a\pgf@curvilinear@comp@a@initial% @@ -154,7 +154,7 @@ \def\pgf@curvilinear@comp@a@initial{% - \pgfmathdivide@\pgf@curvilinear@time@a\pgf@curvilinear@length@a% + \pgfmathdivide@{\pgf@sys@tonumber\pgf@curvilinear@time@a}{\pgf@sys@tonumber\pgf@curvilinear@length@a}% \let\pgf@curvilinear@quot@a\pgfmathresult% \let\pgf@curvilinear@comp@a\pgf@curvilinear@comp@a@cont% \pgf@curvilinear@comp@a@cont% @@ -166,7 +166,7 @@ \def\pgf@curvilinear@comp@b@initial{% \pgf@y=\pgf@curvilinear@length@b% \advance\pgf@y by-\pgf@curvilinear@length@a% - \pgfmathdivide@\pgf@curvilinear@time@a\pgf@y% + \pgfmathdivide@{\pgf@sys@tonumber\pgf@curvilinear@time@a}{\pgf@sys@tonumber\pgf@y}% \let\pgf@curvilinear@quot@b\pgfmathresult% \pgf@y\pgfmathresult\pgf@curvilinear@length@a% \pgf@y-\pgf@y% @@ -184,7 +184,7 @@ \pgf@y=\pgf@curvilinear@length@c% \advance\pgf@y by-\pgf@curvilinear@length@b% \pgf@y.5\pgf@y% - \pgfmathdivide@\pgf@curvilinear@time@a\pgf@y% + \pgfmathdivide@{\pgf@sys@tonumber\pgf@curvilinear@time@a}{\pgf@sys@tonumber\pgf@y}% \let\pgf@curvilinear@quot@c\pgfmathresult% \pgf@y\pgf@curvilinear@quot@c\pgf@curvilinear@length@b% \pgf@y-\pgf@y% @@ -202,7 +202,7 @@ \pgf@y=\pgf@curvilinear@length@d% \advance\pgf@y by-\pgf@curvilinear@length@c% \pgf@y.25\pgf@y% - \pgfmathdivide@\pgf@curvilinear@time@a\pgf@y% + \pgfmathdivide@{\pgf@sys@tonumber\pgf@curvilinear@time@a}{\pgf@sys@tonumber\pgf@y}% \let\pgf@curvilinear@quot@d\pgfmathresult% \pgf@y\pgf@curvilinear@quot@d\pgf@curvilinear@length@c% \pgf@y-\pgf@y% @@ -217,7 +217,8 @@ } \def\pgf@curvilinear@comp@e@initial{% - \pgfmathdivide@{8\pgf@curvilinear@time@a}{\pgf@curvilinear@length@d}% + \pgfmathmultiply@{8}{\pgf@sys@tonumber\pgf@curvilinear@time@a}% + \expandafter\pgfmathdivide@\expandafter{\pgfmathresult}{\pgf@sys@tonumber\pgf@curvilinear@length@d}% \let\pgf@curvilinear@quot@e\pgfmathresult% \let\pgf@curvilinear@comp@e\pgf@curvilinear@comp@e@cont% \pgf@curvilinear@comp@e@cont% @@ -353,7 +354,7 @@ {\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}% {\pgf@sys@tonumber\pgf@ya}{\pgf@sys@tonumber\pgf@x}{0pt}{0pt}% \pgftransformshift{\pgfpointscale{-1}{\pgf@curvilinear@line@a}}% - \pgfmathveclen@{\pgfutil@tempdima}{\pgfutil@tempdimb}% + \pgfmathveclen@{\pgf@sys@tonumber\pgfutil@tempdima}{\pgf@sys@tonumber\pgfutil@tempdimb}% \ifdim\pgfutil@tempdima<0pt% \edef\pgfmathresult{-\pgfmathresult}% \fi% diff --git a/Master/texmf-dist/tex/generic/pgf/libraries/pgflibraryfixedpointarithmetic.code.tex b/Master/texmf-dist/tex/generic/pgf/libraries/pgflibraryfixedpointarithmetic.code.tex index f82f8640c4f..50a7521f826 100644 --- a/Master/texmf-dist/tex/generic/pgf/libraries/pgflibraryfixedpointarithmetic.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/libraries/pgflibraryfixedpointarithmetic.code.tex @@ -273,7 +273,7 @@ } \def\pgfmathfpabs@#1{% \begingroup% - \FPabs\pgfmathresult{#1} + \FPabs\pgfmathresult{#1}% \pgfmath@smuggleone\pgfmathresult% \endgroup% } @@ -561,7 +561,7 @@ \begingroup% \FPmul\pgfmathresult{#1}{0.017453292519943295}% \FPcos\pgfmathresult{\pgfmathresult}% - \FPdiv\pgfmathresult{1}{\pgfmathresult} + \FPdiv\pgfmathresult{1}{\pgfmathresult}% \pgfmath@smuggleone\pgfmathresult% \endgroup% } @@ -576,7 +576,7 @@ \begingroup% \FPmul\pgfmathresult{#1}{0.017453292519943295}% \FPsin\pgfmathresult{\pgfmathresult}% - \FPdiv\pgfmathresult{1}{\pgfmathresult} + \FPdiv\pgfmathresult{1}{\pgfmathresult}% \pgfmath@smuggleone\pgfmathresult% \endgroup% } diff --git a/Master/texmf-dist/tex/generic/pgf/libraries/pgflibraryfpu.code.tex b/Master/texmf-dist/tex/generic/pgf/libraries/pgflibraryfpu.code.tex index dbaf9847cd1..00ce27705f8 100644 --- a/Master/texmf-dist/tex/generic/pgf/libraries/pgflibraryfpu.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/libraries/pgflibraryfpu.code.tex @@ -157,24 +157,13 @@ \expandafter\let\expandafter#1\csname pgfmathfloat@backup@\string#1\endcsname% }% } -\def\pgfmathfloat@prepareuninstallcmd@csname#1{% - % and store backup information (globally - I don't want to do that - % all the time when the FPU is used!): - {% - \globaldefs=1 - \pgfutil@namelet{pgfmathfloat@backup@#1}{#1}% - \expandafter\gdef\expandafter\pgfmathfloat@uninstall\expandafter{\pgfmathfloat@uninstall - \pgfutil@namelet{#1}{pgfmathfloat@backup@#1}% - }% - }% -} \def\pgfmathfloat@install#1=#2{% \pgfmathfloat@prepareuninstallcmd{#1}% \let#1=#2% } \def\pgfmathfloat@install@csname#1#2{% - \pgfmathfloat@prepareuninstallcmd@csname{#1}% + \expandafter\pgfmathfloat@prepareuninstallcmd\csname #1\endcsname% \pgfutil@namelet{#1}{#2}% } \def\pgfmathfloat@install@unimplemented#1{% @@ -213,8 +202,11 @@ \pgfmathfloat@install\pgfmathmultiply@=\pgfmathfloatmultiply@% \pgfmathfloat@install\pgfmathdivide@=\pgfmathfloatdivide@% \pgfmathfloat@install\pgfmathabs@=\pgfmathfloatabs@% + \pgfmathfloat@install\pgfmathsign@=\pgfmathfloatsign@% \pgfmathfloat@install\pgfmathround@=\pgfmathfloatround@% \pgfmathfloat@install\pgfmathfloor@=\pgfmathfloatfloor@% + \pgfmathfloat@install\pgfmathceil@=\pgfmathfloatceil@ + \pgfmathfloat@install\pgfmathint@=\pgfmathfloatint@ \pgfmathfloat@install\pgfmathmod@=\pgfmathfloatmod@% \pgfmathfloat@install\pgfmathmax@=\pgfmathfloatmax@% \pgfmathfloat@install\pgfmathmin@=\pgfmathfloatmin@% @@ -268,13 +260,12 @@ \pgfmathfloat@install\pgfmathcosh@=\pgfmathfloatcosh@ \pgfmathfloat@install\pgfmathsinh@=\pgfmathfloatsinh@ \pgfmathfloat@install\pgfmathtanh@=\pgfmathfloattanh@ - \pgfmathfloat@install@unimplemented{ceil}% + \expandafter\pgfmathfloat@install\csname pgfmathatan2@\endcsname=\pgfmathfloatatantwo@ \pgfmathfloat@install@unimplemented{frac}% \pgfmathfloat@install@unimplemented{random}% \pgfmathfloat@install@unimplemented{setseed}% \pgfmathfloat@install@unimplemented{Mod}% \pgfmathfloat@install@unimplemented{real}% -% \pgfmathfloat@install@unimplemented{atan2}% % \pgfmathfloat@install@unimplemented{height}% % % @@ -308,6 +299,21 @@ \pgfmathfloat@install\pgfmath@parse@exponent=\pgfmathfloat@parse@float@or@exponent % \pgfmathfloat@install\pgfmathparse=\pgfmathfloatparse% + %\pgfmathfloat@install\pgfmathparse@trynumber@token=\pgfmathfloat@parse@trynumber@token + \pgfmathfloat@install\pgfmathparse@expression@is@number=\pgfmathfloat@parse@expression@is@number +}% + +% This here might bring speed improvements... if implemented +% correctly. +% However, this heuristics might fail in cases like "1+1" vs "1e+1" ... +%\def\pgfmathfloat@parse@trynumber@token{numericfpu} +%\pgfmath@tokens@make{numericfpu}{eE+-Y.0123456789} + +\def\pgfmathfloat@parse@expression@is@number{% + \pgfmathfloatparsenumber{\pgfmath@expression}% + \pgfmath@smuggleone\pgfmathresult% + \endgroup + \ignorespaces }% \def\pgfmathfloat@defineadapter@for@pgf@two@null@null@ONEARG#1{% @@ -993,7 +999,7 @@ \if#2+% \pgfmathfloatifflags{#1}{1}{#3}{#4}% \else - \pgfmathfloatgetflagstomacro#1\pgfmathfloat@loc@TMPa + \pgfmathfloatgetflagstomacro{#1}\pgfmathfloat@loc@TMPa \if#2u% \ifnum\pgfmathfloat@loc@TMPa>2 #3\relax @@ -1424,8 +1430,24 @@ }% \def\pgfmathfloatint@@loop@gobble#1\pgfmathfloat@EOI{}% \let\pgfmathfloatint=\pgfmathfloatint@ -\let\pgfmathfloatfloor=\pgfmathfloatint -\let\pgfmathfloatfloor@=\pgfmathfloatint@ + +\def\pgfmathfloatfloor#1{% + \edef\pgfmathfloat@loc@TMPa{#1}% + \pgfmathfloatcreate{2}{5.0}{-1}% -0.5 + \let\pgfmathfloat@loc@TMPb=\pgfmathresult + \pgfmathfloatadd@{\pgfmathfloat@loc@TMPa}{\pgfmathfloat@loc@TMPb}% + \expandafter\pgfmathfloatround@\expandafter{\pgfmathresult}% +} +\let\pgfmathfloatfloor@=\pgfmathfloatfloor + +\def\pgfmathfloatceil#1{% + \edef\pgfmathfloat@loc@TMPa{#1}% + \pgfmathfloatcreate{1}{5.0}{-1}% +0.5 + \let\pgfmathfloat@loc@TMPb=\pgfmathresult + \pgfmathfloatadd@{\pgfmathfloat@loc@TMPa}{\pgfmathfloat@loc@TMPb}% + \expandafter\pgfmathfloatround@\expandafter{\pgfmathresult}% +} +\let\pgfmathfloatceil@=\pgfmathfloatceil \def\pgfmathfloat@notimplemented#1{% \pgfmath@error{Sorry, the operation '#1' has not yet been implemented in the floating point unit :-(}{}% @@ -1476,7 +1498,34 @@ \pgfmath@smuggleone\pgfmathresult \endgroup }% -\let\pgfmathfloatabs=\pgfmathfloatabs@ +% +% Defines \pgfmathresult to be sign(#1) +\def\pgfmathfloatsign@#1{% + \begingroup + \expandafter\pgfmathfloat@decompose@tok#1\relax\pgfmathfloat@a@S\pgfmathfloat@a@Mtok\pgfmathfloat@a@E + \ifcase\pgfmathfloat@a@S + % 0: + \pgfmathfloatcreate{0}{0.0}{0}% + \or + % +: ok, is positive. + \pgfmathfloatcreate{1}{1.0}{0}% + \or + % -: + \pgfmathfloatcreate{2}{1.0}{0}% + \or + % nan: do nothing. + \pgfmathfloatcreate{\the\pgfmathfloat@a@S}{\the\pgfmathfloat@a@Mtok}{\the\pgfmathfloat@a@E}% + \or + % +infty:. + \pgfmathfloatcreate{1}{1.0}{0}% + \or + % -infty: + \pgfmathfloatcreate{2}{1.0}{0}% + \fi + \pgfmath@smuggleone\pgfmathresult + \endgroup +}% +\let\pgfmathfloatsign=\pgfmathfloatsign@ % Computes the absolute error |#1 - #2| into \pgfmathresult. \def\pgfmathfloatabserror@#1#2{% @@ -1494,8 +1543,8 @@ \let\pgfmathresult=\pgfmathfloat@subtract }{% \pgfmathfloatdivide@{\pgfmathfloat@subtract}{#2}% - \pgfmathfloatabs@{\pgfmathresult}% }% + \pgfmathfloatabs@{\pgfmathresult}% }% \let\pgfmathfloatrelerror=\pgfmathfloatrelerror@ @@ -1567,14 +1616,27 @@ % % #1 is a one-argument macro which assigns \pgfmathresult. \def\pgfmathfloatTRIG@#1#2{% - \expandafter\ifx\csname pgfmathfloatTRIG@NUM\endcsname\relax% - % Lazy evaluation: - \pgfmathfloatcreate{1}{3.6}{2}% - \global\let\pgfmathfloatTRIG@NUM=\pgfmathresult - \pgfmathfloatcreate{1}{2.77777777777778}{-3}% - \global\let\pgfmathfloatTRIG@NUM@INV=\pgfmathresult + \if0\pgfmath@trig@format@choice + % trig format=deg + \expandafter\ifx\csname pgfmathfloatTRIG@NUM\endcsname\relax% + % Lazy evaluation: + \pgfmathfloatcreate{1}{3.6}{2}% + \global\let\pgfmathfloatTRIG@NUM=\pgfmathresult + \pgfmathfloatcreate{1}{2.77777777777778}{-3}% + \global\let\pgfmathfloatTRIG@NUM@INV=\pgfmathresult + \fi + \pgfmathfloatmodknowsinverse@{#2}{\pgfmathfloatTRIG@NUM}{\pgfmathfloatTRIG@NUM@INV}% + \else + % trig format=rad + \expandafter\ifx\csname pgfmathfloatTRIG@rad@NUM\endcsname\relax% + % Lazy evaluation: + \pgfmathfloatcreate{1}{6.28318530717959}{0}% + \global\let\pgfmathfloatTRIG@rad@NUM=\pgfmathresult + \pgfmathfloatcreate{1}{1.59154943091895}{-1}% + \global\let\pgfmathfloatTRIG@rad@NUM@INV=\pgfmathresult + \fi + \pgfmathfloatmodknowsinverse@{#2}{\pgfmathfloatTRIG@rad@NUM}{\pgfmathfloatTRIG@rad@NUM@INV}% \fi - \pgfmathfloatmodknowsinverse@{#2}{\pgfmathfloatTRIG@NUM}{\pgfmathfloatTRIG@NUM@INV}% \pgfmathfloattofixed@{\pgfmathresult}% \expandafter#1\expandafter{\pgfmathresult}% \pgfmathfloatparsenumber{\pgfmathresult}% @@ -1618,11 +1680,19 @@ \fi \pgfmathfloatgreaterthan@{#1}{\pgfmathfloatatan@TMP}% \ifpgfmathfloatcomparison - \pgfmathfloatcreate{1}{9.0}{1}% + \pgfmathiftrigonometricusesdeg{% + \pgfmathfloatcreate{1}{9.0}{1}% + }{% + \pgfmathfloatcreate{1}{1.570796326794}{0}% + }% \else \pgfmathfloatlessthan{#1}{\pgfmathfloatatan@TMPB}% \ifpgfmathfloatcomparison - \pgfmathfloatcreate{2}{9.0}{1}% + \pgfmathiftrigonometricusesdeg{% + \pgfmathfloatcreate{2}{9.0}{1}% + }{% + \pgfmathfloatcreate{2}{1.570796326794}{0}% + }% \else \pgfmathfloattofixed@{#1}% \expandafter\pgfmath@basic@atan@\expandafter{\pgfmathresult}% @@ -1634,6 +1704,76 @@ }% \let\pgfmathfloatatan=\pgfmathfloatatan@ +\def\pgfmathfloatatantwo#1#2{% + % Note: first parameter is y (!), second is x (!) + \begingroup% + \let\pgfmath@trig@format@choice@@=\pgfmath@trig@format@choice + \def\pgfmath@trig@format@choice{0}% + % + \expandafter\pgfmathfloat@decompose@tok#1\relax\pgfmathfloat@a@S\pgfmathfloat@a@Mtok\pgfmathfloat@a@E + \expandafter\pgfmathfloat@decompose#2\relax\pgfmathfloat@b@S\pgfmathfloat@b@M\pgfmathfloat@b@E + \ifnum\pgfmathfloat@a@S=0 + % ok, #1 = 0. Substitute by 1e-16 such that the next \ifnum catches it: + \pgfmathfloat@a@E=-16 % + \fi + % + \ifnum\pgfmathfloat@a@E<-3 % + \ifnum\pgfmathfloat@b@S=2 % + % #2 < 0 + \pgfmathfloatcreate{1}{1.8}{2}% +180 + \else + \ifnum\pgfmathfloat@b@S=1 % + % #2 >0 + \pgfmathfloatcreate{0}{0.0}{0}% + \else + % + or - 90, just use the sign of #1: + \pgfmathfloatcreate{\the\pgfmathfloat@a@S}{9.0}{1}% + \fi + \fi + \else% + \pgfmathfloatabs@{#1}\let\pgfmath@tempa\pgfmathresult% + \pgfmathfloatabs@{#2}\let\pgfmath@tempb\pgfmathresult% + \pgfmathfloatgreaterthan@{\pgfmath@tempa}{\pgfmath@tempb}% + \ifpgfmathfloatcomparison + \pgfmathfloatdivide@{#2}{\pgfmath@tempa}% + \expandafter\pgfmathfloatatan@\expandafter{\pgfmathresult}% + \let\pgfmath@tempa=\pgfmathresult + \pgfmathfloatcreate{1}{9.0}{1}% + \let\pgfmath@tempb=\pgfmathresult + \pgfmathfloatsubtract@{\pgfmath@tempb}{\pgfmath@tempa}% + \else% + \pgfmathfloatdivide@{\pgfmath@tempa}{#2}% + \expandafter\pgfmathfloatatan@\expandafter{\pgfmathresult}% + \expandafter\pgfmathfloatifflags\expandafter{\pgfmathresult}{2}{% + \let\pgfmath@tempa=\pgfmathresult + \pgfmathfloatcreate{1}{1.8}{2}% + \let\pgfmath@tempb=\pgfmathresult + \pgfmathfloatadd@{\pgfmath@tempa}{\pgfmath@tempb}% + }{}% + \fi% + % + \pgfmathfloatifflags{#1}{-}{% + % #1 < 0: + \pgfmathfloatmultiplyfixed@{\pgfmathresult}{-1}% + }{}% + \fi% + \if1\pgfmath@trig@format@choice@@ + % trig format=rad + \pgfmathfloat@scale@deg@to@rad\pgfmathresult + \fi + \pgfmath@smuggleone\pgfmathresult% + \endgroup% +}% +\let\pgfmathfloatatantwo@=\pgfmathfloatatantwo +\expandafter\let\csname pgfmathfloatatan2\endcsname=\pgfmathfloatatantwo +\expandafter\let\csname pgfmathfloatatan2@\endcsname=\pgfmathfloatatantwo@ + +\def\pgfmathfloat@scale@deg@to@rad#1{% + \edef\pgfmathfloat@loc@TMPb{#1}% + \pgfmathfloatcreate{1}{1.74532925199433}{-2}% = pi / 180 + \pgfmathfloatmultiply@{\pgfmathresult}{\pgfmathfloat@loc@TMPb}% +}% + \def\pgfmathfloatsec@#1{\pgfmathfloatTRIG@\pgfmath@basic@cos@{#1}\pgfmathfloatreciprocal@{\pgfmathresult}} \let\pgfmathfloatsec=\pgfmathfloatsec@ \def\pgfmathfloatcosec@#1{\pgfmathfloatTRIG@\pgfmath@basic@sin@{#1}\pgfmathfloatreciprocal@{\pgfmathresult}} @@ -1664,16 +1804,24 @@ \expandafter\def\csname pgfmathfloatlog10@\endcsname#1{% \pgfmathfloatln@{#1}% - \let\pgfmathfloat@log@ten=\pgfmathresult + \let\pgfmathfloat@log@e=\pgfmathresult \pgfmathfloatcreate{1}{4.34294481903252}{-1}% 1/ln(10) - \pgfmathfloatmultiply@{\pgfmathresult}{\pgfmathfloat@log@ten}% + \pgfmathfloatmultiply@{\pgfmathresult}{\pgfmathfloat@log@e}% }% +\pgfutil@namelet{pgfmathfloatlog10}{pgfmathfloatlog10@}% + \expandafter\def\csname pgfmathfloatlog2@\endcsname#1{% \pgfmathfloatln@{#1}% - \let\pgfmathfloat@log@two=\pgfmathresult + \let\pgfmathfloat@log@e=\pgfmathresult \pgfmathfloatcreate{1}{1.44269504088896}{0}% 1/ln(2) - \pgfmathfloatmultiply@{\pgfmathresult}{\pgfmathfloat@log@two}% + \pgfmathfloatmultiply@{\pgfmathresult}{\pgfmathfloat@log@e}% }% +\pgfutil@namelet{pgfmathfloatlog2}{pgfmathfloatlog2@}% + +\expandafter\let\expandafter\pgfmathfloatlogtwo\csname pgfmathfloatlog2\endcsname +\expandafter\let\expandafter\pgfmathfloatlogtwo@\csname pgfmathfloatlog2@\endcsname +\expandafter\let\expandafter\pgfmathfloatlogten\csname pgfmathfloatlog10\endcsname +\expandafter\let\expandafter\pgfmathfloatlogten@\csname pgfmathfloatlog10@\endcsname % Computes log(x) into \pgfmathresult. % diff --git a/Master/texmf-dist/tex/generic/pgf/libraries/pgflibraryintersections.code.tex b/Master/texmf-dist/tex/generic/pgf/libraries/pgflibraryintersections.code.tex index b90e96c8b5a..41c0d1cdc19 100644 --- a/Master/texmf-dist/tex/generic/pgf/libraries/pgflibraryintersections.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/libraries/pgflibraryintersections.code.tex @@ -11,6 +11,8 @@ % Experimentally, it performed well while computing ~12 intersections of two % plots, each with 600 samples. It failed when the number of samples exceeded 700. +\usepgflibrary{fpu} + \newcount\pgf@intersect@solutions \newif\ifpgf@intersect@sort @@ -50,6 +52,9 @@ % % -> \first may be 0 if point #0 is in the 0'th segment % -> \second may be 42 if point #0 is in the 42'th segment +% +% The "segment index" is actually close to the "time" of the solution. +% If a solution is at "time" 42.2, it will have segment index 42. \def\pgfintersectiongetsolutionsegmentindices#1#2#3{% \ifnum#1<1\relax% \let#2=\pgfutil@empty @@ -59,8 +64,56 @@ \let#2=\pgfutil@empty \let#3=\pgfutil@empty \else% - \edef#2{\csname pgf@intersect@solution@segment@a@#1\endcsname}% - \edef#3{\csname pgf@intersect@solution@segment@b@#1\endcsname}% + \def\pgf@temp##1##2##3##4{% + \edef#2{##1}% + \edef#3{##2}% + }% + \expandafter\let\expandafter\pgf@tempb\csname pgf@intersect@solution@props@#1\endcsname + \expandafter\pgf@temp\pgf@tempb + \fi% + \fi% +}% + +% Gets the time indices of solution #1. +% +% #1: the solution index (i.e. the same argument as in \pgfpointintersectionsolution) +% #2: [output] a macro name which will contain the time of the first path which contains the solution +% It will never be empty. +% #3: [output] a macro name which will contain the time of the second path which contains the solution +% It will never be empty. +% +% Example: \pgfintersectiongetsolutiontimes{0}{\first}{\second} +% +% -> \first may be 0.5 if point #0 is in just in the middle of the path +% -> \second may be 42.8 if point #0 is in the 42'th segment (compare +% \pgfintersectiongetsolutionsegmentindices) and is at 80% of the +% 42'th segment +% +% Note that the precise time inside of a segment may be unavailable +% (currently, it is only computed for curveto paths and not +% necessarily for lineto). If the precise time is unavailable, this +% call will return the value of +% \pgfintersectiongetsolutionsegmentindices (which is a +% "coarse-grained" time). +\def\pgfintersectiongetsolutiontimes#1#2#3{% + \ifnum#1<1\relax% + \let#2=\pgfutil@empty + \let#3=\pgfutil@empty + \else% + \ifnum#1>\pgfintersectionsolutions\relax% + \let#2=\pgfutil@empty + \let#3=\pgfutil@empty + \else% + \def\pgf@temp##1##2##3##4{% + \edef#2{##3}% + \edef#3{##4}% + % + % check for fallback to segment indices: + \ifx#2\pgfutil@empty \edef#2{##1}\fi + \ifx#3\pgfutil@empty \edef#3{##2}\fi + }% + \expandafter\let\expandafter\pgf@tempb\csname pgf@intersect@solution@props@#1\endcsname + \expandafter\pgf@temp\pgf@tempb \fi% \fi% }% @@ -100,7 +153,7 @@ \let\pgf@intersect@path@b=\pgf@intersect@path@temp% % \pgf@intersect@solutions=0\relax% - \def\pgf@intersect@time@offset{0}% + \pgf@intersect@path@reset@a % \ifpgf@intersect@sort@by@second@path% \let\pgf@intersect@temp=\pgf@intersect@path@a% @@ -119,7 +172,7 @@ \else% \pgfutil@namelet{pgfpoint@intersect@solution@\pgfmathcounter}% {pgfpoint@g@intersect@solution@\pgfmathcounter}% - \edef\pgf@marshal{\noexpand\pgf@intersection@set@properties\csname pgfpoint@g@intersect@solution@\pgfmathcounter @props\endcsname}% + \edef\pgf@marshal{\noexpand\pgf@intersection@set@properties{\csname pgfpoint@g@intersect@solution@\pgfmathcounter @props\endcsname}}% \pgf@marshal \ifpgf@intersect@sort% \pgfutil@namelet{pgf@intersect@solution@\pgfmathcounter @time@a}% @@ -131,15 +184,28 @@ \fi% } -\def\pgf@intersection@set@properties#1#2{% - \pgfutil@namedef{pgf@intersect@solution@segment@a@\pgfmathcounter}{#1}% - \pgfutil@namedef{pgf@intersect@solution@segment@b@\pgfmathcounter}{#2}% +\def\pgf@intersection@set@properties#1{% + \pgfutil@namedef{pgf@intersect@solution@props@\pgfmathcounter}{#1}% }% % #1 a global name prefix to store properties. \def\pgf@intersection@store@properties#1{% % we store the time offsets as well and make them available programmatically: - \expandafter\xdef\csname #1@props\endcsname{{\pgf@intersect@time@offset}{\pgf@intersect@time@offset@b}}% + % note that \pgf@intersect@time@a and \pgf@intersect@time@b may be empty. + % + % However, \pgf@intersect@time@offset and + % \pgf@intersect@time@offset@b are *always* valid. In fact,they + % resemble a part of the time: it holds + % 0 <= \pgf@intersect@time@a < 1 + % and \pgf@intersect@time@offset > 0. + % + % If we have an intersection in segment 42 of path A, + % \pgf@intersect@time@offset will be 42. The time inside of that + % segment is given as number in the interval [0,1]. If it is 0.3, + % the total time will be 42.3 and that number will be stored as + % \pgf@intersect@time@a. + % + \expandafter\xdef\csname #1@props\endcsname{{\pgf@intersect@time@offset}{\pgf@intersect@time@offset@b}{\pgf@intersect@time@a}{\pgf@intersect@time@b}}% } \def\pgf@intersectionofpaths#1{% @@ -204,7 +270,7 @@ \def\pgf@intersect@path@process@a{% \pgf@intersect@path@getpoints@a% \let\pgf@intersect@token@after=\pgf@intersect@path@process@b% - \def\pgf@intersect@time@offset@b{0}% + \pgf@intersect@path@reset@b \expandafter\pgf@intersectionofpaths\pgf@intersect@path@b\pgf@stop% \let\pgfpoint@intersect@start=\pgfpoint@intersect@end@a% \let\pgf@intersect@token@after=\pgf@intersect@path@process@a% @@ -214,6 +280,16 @@ \pgf@intersectionofpaths% } +\def\pgf@intersect@path@reset@a{% + \def\pgf@intersect@time@offset{0}% + \def\pgf@intersect@time@a{}% +}% + +\def\pgf@intersect@path@reset@b{% + \def\pgf@intersect@time@offset@b{0}% + \def\pgf@intersect@time@b{}% +}% + \def\pgf@intersect@path@getpoints@a{% \let\pgfpoint@intersect@start@a=\pgfpoint@intersect@start% \let\pgfpoint@intersect@end@a=\pgfpoint@intersect@end% @@ -275,33 +351,43 @@ \def\pgf@intersectionoflines#1#2#3#4{% \pgf@iflinesintersect{#1}{#2}{#3}{#4}% {% - \global\advance\pgf@intersect@solutions by1\relax% - \expandafter\pgfextract@process\csname pgfpoint@g@intersect@solution@\the\pgf@intersect@solutions\endcsname{% + \pgfextract@process\pgf@intersect@solution@candidate{% \pgfpointintersectionoflines{\pgfpoint@intersect@start@a}{\pgfpoint@intersect@end@a}% {\pgfpoint@intersect@start@b}{\pgfpoint@intersect@end@b}% }% - \pgf@intersection@store@properties{pgfpoint@g@intersect@solution@\the\pgf@intersect@solutions}% + \pgf@ifsolution@duplicate{\pgf@intersect@solution@candidate}{% + % ah - we a duplicate. Apparently, we have a hit on an + % endpoint. + }{% + \global\advance\pgf@intersect@solutions by1\relax% + \expandafter\global\expandafter\let\csname pgfpoint@g@intersect@solution@\the\pgf@intersect@solutions\endcsname=\pgf@intersect@solution@candidate + \ifpgf@intersect@sort% + \pgf@xc=\pgf@x% + \pgf@yc=\pgf@y% + \pgf@process{\pgfpointdiff{\pgfpoint@intersect@start@a}{\pgfpoint@intersect@end@a}}% + \edef\pgf@marshal{% + \noexpand\pgfmathveclen@{\pgfmath@tonumber{\pgf@xa}}{\pgfmath@tonumber{\pgf@ya}}% + }% + \pgf@marshal% + \let\pgf@intersect@length@a=\pgfmathresult% + \pgf@process{\pgfpointdiff{\pgfpoint@intersect@start@a}{\pgfqpoint{\pgf@xc}{\pgf@yc}}}% + \edef\pgf@marshal{% + \noexpand\pgfmathveclen@{\pgfmath@tonumber{\pgf@x}}{\pgfmath@tonumber{\pgf@y}}% + }% + \pgf@marshal% + \pgfmathdivide@{\pgfmathresult}{\pgf@intersect@length@a}% + \pgf@x=\pgfmathresult pt\relax% + \advance\pgf@x by\pgf@intersect@time@offset pt\relax% + \edef\pgf@intersect@time@a{\pgfmath@tonumber{\pgf@x}}% + \expandafter\global\expandafter\let\csname pgf@g@intersect@solution@\the\pgf@intersect@solutions @time@a\endcsname= + \pgf@intersect@time@a + \else + \let\pgf@intersect@time@a=\pgfutil@empty + \fi% + \let\pgf@intersect@time@b=\pgfutil@empty + \pgf@intersection@store@properties{pgfpoint@g@intersect@solution@\the\pgf@intersect@solutions}% + }% % - \ifpgf@intersect@sort% - \pgf@xc=\pgf@x% - \pgf@yc=\pgf@y% - \pgf@process{\pgfpointdiff{\pgfpoint@intersect@start@a}{\pgfpoint@intersect@end@a}}% - \edef\pgf@marshal{% - \noexpand\pgfmathveclen@{\pgfmath@tonumber{\pgf@xa}}{\pgfmath@tonumber{\pgf@ya}}% - }% - \pgf@marshal% - \let\pgf@intersect@length@a=\pgfmathresult% - \pgf@process{\pgfpointdiff{\pgfpoint@intersect@start@a}{\pgfqpoint{\pgf@xc}{\pgf@yc}}}% - \edef\pgf@marshal{% - \noexpand\pgfmathveclen@{\pgfmath@tonumber{\pgf@x}}{\pgfmath@tonumber{\pgf@y}}% - }% - \pgf@marshal% - \pgfmathdivide@{\pgfmathresult}{\pgf@intersect@length@a}% - \pgf@x=\pgfmathresult pt\relax% - \advance\pgf@x by\pgf@intersect@time@offset pt\relax% - \expandafter\xdef\csname pgf@g@intersect@solution@\the\pgf@intersect@solutions @time@a\endcsname% - {\pgfmath@tonumber{\pgf@x}}% - \fi% }{}% } @@ -572,6 +658,8 @@ \pgf@intersect@boundingbox@update{#2}% \pgf@intersect@boundingbox@update{#3}% \pgf@intersect@boundingbox@update{#4}% + % (\pgf@xa, \pgf@ya) is lower-left + % (\pgf@xb, \pgf@yb) is upper-right \edef\pgf@intersect@boundingbox@b{% \noexpand\pgf@x=\the\pgf@xa% \noexpand\pgf@y=\the\pgf@ya% @@ -591,6 +679,7 @@ }% \pgf@intersect@boundingbox@a% \pgf@intersect@boundingbox@b% + % check if the two bounding boxes overlap: \ifdim\pgf@xa<\pgf@xb% \else% \ifdim\pgf@x>\pgf@xc% @@ -599,16 +688,21 @@ \else% \ifdim\pgf@y>\pgf@yc% \else% + % compute DIFFERENCE vectors: \advance\pgf@xc by-\pgf@xb% \advance\pgf@yc by-\pgf@yb% \advance\pgf@xa by-\pgf@x% \advance\pgf@ya by-\pgf@y% \let\pgf@intersect@subdivde=\relax% + % check if both difference vectors are point wise + % less than tolerance (i.e. |v|_infty < eps ). + % That means that both bounding boxes are "small enough" \ifdim\pgf@xc<\pgfintersectiontolerance\relax% \ifdim\pgf@xa<\pgfintersectiontolerance\relax% \ifdim\pgf@yc<\pgfintersectiontolerance\relax% \ifdim\pgf@ya<\pgfintersectiontolerance\relax% \pgfextract@process\pgf@intersect@solution@candidate{% + % set (x,y) = mean(the 4 points of the two bounding boxes): \pgf@intersect@boundingbox@a% \pgf@intersect@boundingbox@b% \pgf@x=0.25\pgf@x% @@ -625,20 +719,27 @@ \pgf@ifsolution@duplicate\pgf@intersect@solution@candidate{}% {% \global\advance\pgf@intersect@solutions by1\relax% + \begingroup + \advance\pgf@time@a by\pgf@time@aa% + \divide\pgf@time@a by2\relax% + \advance\pgf@time@a by\pgf@intersect@time@offset pt\relax% + \edef\pgf@intersect@time@a{\pgfmath@tonumber{\pgf@time@a}}% + % + \advance\pgf@time@b by\pgf@time@bb% + \divide\pgf@time@b by2\relax% + \advance\pgf@time@b by\pgf@intersect@time@offset@b pt\relax% + \edef\pgf@intersect@time@b{\pgfmath@tonumber{\pgf@time@b}}% + % \pgf@intersection@store@properties{pgfpoint@g@intersect@solution@\the\pgf@intersect@solutions}% \expandafter\global\expandafter\let% \csname pgfpoint@g@intersect@solution@\the\pgf@intersect@solutions\endcsname=% \pgf@intersect@solution@candidate% - {% - \ifpgf@intersect@sort% - \advance\pgf@time@a by\pgf@time@aa% - \divide\pgf@time@a by2\relax% - \advance\pgf@time@a by\pgf@intersect@time@offset pt\relax% - \expandafter\xdef% - \csname pgf@g@intersect@solution@\the\pgf@intersect@solutions @time@a\endcsname% - {\pgfmath@tonumber{\pgf@time@a}}% - \fi% - }% + \ifpgf@intersect@sort% + \expandafter\xdef% + \csname pgf@g@intersect@solution@\the\pgf@intersect@solutions @time@a\endcsname% + {\pgf@intersect@time@a}% + \fi% + \endgroup }% \fi% \fi% @@ -699,33 +800,74 @@ \ifdim\pgf@y>\pgf@yb\pgf@yb=\pgf@y\fi% } +% The following subroutines are part of a conversion from pgfbasic +% math to FPU. This transition is necessary due to the restricted +% accuracy of pgfbasic. In order to limit the error rate of the +% transition pgfbasic -> FPU, I chose to +% keep the old "pattern" of sorts \advance\pgf@xa by0.5\pgf@y etc and +% simply adapt to some FPU call. +% +% The following routines constitute the "adapter": + +\def\pgf@float@adapter@setxy{% + \pgfmathfloatparsenumber{\pgf@sys@tonumber\pgf@x}\let\pgf@fpu@x=\pgfmathresult + \pgfmathfloatparsenumber{\pgf@sys@tonumber\pgf@y}\let\pgf@fpu@y=\pgfmathresult +}% +\def\pgf@float@adapter@mult#1=#2*#3{% + \pgfmathfloatmultiplyfixed@{#3}{#2}% + \let#1=\pgfmathresult +}% +\def\pgf@float@adapter@advance#1by#2*#3{% + \pgfmathfloatmultiplyfixed@{#3}{#2}% + \let\pgfutil@temp=\pgfmathresult + \pgfmathfloatadd@{#1}{\pgfutil@temp}% + \let#1=\pgfmathresult +}% + +\def\pgf@float@adapter@tostring#1{% + \pgfmathfloattofixed{#1}\edef#1{\pgfmathresult pt }% +}% \def\pgf@curve@subdivide@left#1#2#3#4{% % % The left curve (from t=0 to t=.5) % + \begingroup #1\relax% \pgfutil@tempdima=\pgf@x% \pgfutil@tempdimb=\pgf@y% - \pgf@xa=.5\pgf@x\pgf@ya=.5\pgf@y% - \pgf@xb=.25\pgf@x\pgf@yb=.25\pgf@y% - \pgf@xc=.125\pgf@x\pgf@yc=.125\pgf@y% + \pgf@float@adapter@setxy + \pgf@float@adapter@mult\pgf@fpu@xa=.5*\pgf@fpu@x \pgf@float@adapter@mult\pgf@fpu@ya=.5*\pgf@fpu@y% + \pgf@float@adapter@mult\pgf@fpu@xb=.25*\pgf@fpu@x \pgf@float@adapter@mult\pgf@fpu@yb=.25*\pgf@fpu@y% + \pgf@float@adapter@mult\pgf@fpu@xc=.125*\pgf@fpu@x\pgf@float@adapter@mult\pgf@fpu@yc=.125*\pgf@fpu@y% #2\relax% - \advance\pgf@xa by.5\pgf@x\advance\pgf@ya by.5\pgf@y% - \advance\pgf@xb by.5\pgf@x\advance\pgf@yb by.5\pgf@y% - \advance\pgf@xc by.375\pgf@x\advance\pgf@yc by.375\pgf@y% + \pgf@float@adapter@setxy + \pgf@float@adapter@advance\pgf@fpu@xa by.5*\pgf@fpu@x\pgf@float@adapter@advance\pgf@fpu@ya by.5*\pgf@fpu@y% + \pgf@float@adapter@advance\pgf@fpu@xb by.5*\pgf@fpu@x\pgf@float@adapter@advance\pgf@fpu@yb by.5*\pgf@fpu@y% + \pgf@float@adapter@advance\pgf@fpu@xc by.375*\pgf@fpu@x\pgf@float@adapter@advance\pgf@fpu@yc by.375*\pgf@fpu@y% #3\relax% - \advance\pgf@xb by.25\pgf@x\advance\pgf@yb by.25\pgf@y% - \advance\pgf@xc by.375\pgf@x\advance\pgf@yc by.375\pgf@y% + \pgf@float@adapter@setxy + \pgf@float@adapter@advance\pgf@fpu@xb by.25*\pgf@fpu@x\pgf@float@adapter@advance\pgf@fpu@yb by.25*\pgf@fpu@y% + \pgf@float@adapter@advance\pgf@fpu@xc by.375*\pgf@fpu@x\pgf@float@adapter@advance\pgf@fpu@yc by.375*\pgf@fpu@y% #4\relax% - \advance\pgf@xc by.125\pgf@x\advance\pgf@yc by.125\pgf@y% + \pgf@float@adapter@setxy + \pgf@float@adapter@advance\pgf@fpu@xc by.125*\pgf@fpu@x\pgf@float@adapter@advance\pgf@fpu@yc by.125*\pgf@fpu@y% + % + \pgf@float@adapter@tostring\pgf@fpu@xa + \pgf@float@adapter@tostring\pgf@fpu@ya + \pgf@float@adapter@tostring\pgf@fpu@xb + \pgf@float@adapter@tostring\pgf@fpu@yb + \pgf@float@adapter@tostring\pgf@fpu@xc + \pgf@float@adapter@tostring\pgf@fpu@yc \edef\pgf@marshal{% \noexpand\pgf@curve@subdivde@after% {\noexpand\pgf@x=\the\pgfutil@tempdima\noexpand\pgf@y=\the\pgfutil@tempdimb}% - {\noexpand\pgf@x=\the\pgf@xa\noexpand\pgf@y\the\pgf@ya}% - {\noexpand\pgf@x=\the\pgf@xb\noexpand\pgf@y=\the\pgf@yb} - {\noexpand\pgf@x=\the\pgf@xc\noexpand\pgf@y=\the\pgf@yc}% + {\noexpand\pgf@x=\pgf@fpu@xa\noexpand\pgf@y=\pgf@fpu@ya}% + {\noexpand\pgf@x=\pgf@fpu@xb\noexpand\pgf@y=\pgf@fpu@yb} + {\noexpand\pgf@x=\pgf@fpu@xc\noexpand\pgf@y=\pgf@fpu@yc}% }% + \expandafter + \endgroup \pgf@marshal% } @@ -733,26 +875,43 @@ % % The right curve (from t=0.5 to t=1) % + \begingroup #1\relax% - \pgfutil@tempdima=.125\pgf@x\pgfutil@tempdimb=.125\pgf@y% + \pgf@float@adapter@setxy + \pgf@float@adapter@mult\pgf@float@tmpa=.125*\pgf@fpu@x\pgf@float@adapter@mult\pgf@float@tmpb=.125*\pgf@fpu@y% #2\relax% - \advance\pgfutil@tempdima by.375\pgf@x\advance\pgfutil@tempdimb by.375\pgf@y% - \pgf@xa=.25\pgf@x\pgf@ya=.25\pgf@y% + \pgf@float@adapter@setxy + \pgf@float@adapter@advance\pgf@float@tmpa by.375*\pgf@fpu@x\pgf@float@adapter@advance\pgf@float@tmpb by.375*\pgf@fpu@y% + \pgf@float@adapter@mult\pgf@fpu@xa=.25*\pgf@fpu@x\pgf@float@adapter@mult\pgf@fpu@ya=.25*\pgf@fpu@y% #3\relax% - \advance\pgfutil@tempdima by.375\pgf@x\advance\pgfutil@tempdimb by.375\pgf@y% - \advance\pgf@xa by.5\pgf@x\advance\pgf@ya by.5\pgf@y% - \pgf@xb=.5\pgf@x\pgf@yb=.5\pgf@y% + \pgf@float@adapter@setxy + \pgf@float@adapter@advance\pgf@float@tmpa by.375*\pgf@fpu@x\pgf@float@adapter@advance\pgf@float@tmpb by.375*\pgf@fpu@y% + \pgf@float@adapter@advance\pgf@fpu@xa by.5*\pgf@fpu@x\pgf@float@adapter@advance\pgf@fpu@ya by.5*\pgf@fpu@y% + \pgf@float@adapter@mult\pgf@fpu@xb=.5*\pgf@fpu@x\pgf@float@adapter@mult\pgf@fpu@yb=.5*\pgf@fpu@y% #4\relax% - \advance\pgfutil@tempdima by.125\pgf@x\advance\pgfutil@tempdimb by.125\pgf@y% - \advance\pgf@xa by.25\pgf@x\advance\pgf@ya by.25\pgf@y% - \advance\pgf@xb by.5\pgf@x\advance\pgf@yb by.5\pgf@y% - \pgf@xc=\pgf@x\pgf@yc=\pgf@y% + \pgf@float@adapter@setxy + \pgf@float@adapter@advance\pgf@float@tmpa by.125*\pgf@fpu@x\pgf@float@adapter@advance\pgf@float@tmpb by.125*\pgf@fpu@y% + \pgf@float@adapter@advance\pgf@fpu@xa by.25*\pgf@fpu@x\pgf@float@adapter@advance\pgf@fpu@ya by.25*\pgf@fpu@y% + \pgf@float@adapter@advance\pgf@fpu@xb by.5*\pgf@fpu@x\pgf@float@adapter@advance\pgf@fpu@yb by.5*\pgf@fpu@y% + \let\pgf@fpu@xc=\pgf@fpu@x\let\pgf@fpu@yc=\pgf@fpu@y% + % + \pgf@float@adapter@tostring\pgf@float@tmpa + \pgf@float@adapter@tostring\pgf@float@tmpb + \pgf@float@adapter@tostring\pgf@fpu@xa + \pgf@float@adapter@tostring\pgf@fpu@ya + \pgf@float@adapter@tostring\pgf@fpu@xb + \pgf@float@adapter@tostring\pgf@fpu@yb + \pgf@float@adapter@tostring\pgf@fpu@xc + \pgf@float@adapter@tostring\pgf@fpu@yc \edef\pgf@marshal{% \noexpand\pgf@curve@subdivde@after% - {\pgf@x\the\pgfutil@tempdima\pgf@y\the\pgfutil@tempdimb}% - {\pgf@x\the\pgf@xa\pgf@y\the\pgf@ya}{\pgf@x\the\pgf@xb\pgf@y\the\pgf@yb} - {\pgf@x\the\pgf@xc\pgf@y\the\pgf@yc}% + {\noexpand\pgf@x=\pgf@float@tmpa\noexpand\pgf@y=\pgf@float@tmpb}% + {\noexpand\pgf@x=\pgf@fpu@xa\noexpand\pgf@y=\pgf@fpu@ya} + {\noexpand\pgf@x=\pgf@fpu@xb\noexpand\pgf@y=\pgf@fpu@yb} + {\noexpand\pgf@x=\pgf@fpu@xc\noexpand\pgf@y=\pgf@fpu@yc}% }% + \expandafter + \endgroup \pgf@marshal% } @@ -773,23 +932,26 @@ \pgfmathloop% \ifnum\pgfmathcounter>\pgf@intersect@solutions\relax% \else% - \pgf@process{\csname pgfpoint@g@intersect@solution@\pgfmathcounter\endcsname}% - \advance\pgf@x by-\pgf@xa% - \advance\pgf@y by-\pgf@ya% - \ifdim\pgf@x<0pt\relax\pgf@x=-\pgf@x\fi% - \ifdim\pgf@y<0pt\relax\pgf@y=-\pgf@y\fi% - % - \pgf@x=\pgfintersectiontolerancefactor\pgf@x% - \pgf@y=\pgfintersectiontolerancefactor\pgf@y% - \ifdim\pgf@x<\pgfintersectiontolerance\relax% - \ifdim\pgf@y<\pgfintersectiontolerance\relax% - \let\pgf@intersect@next=\pgfutil@firstoftwo% - \fi% - \fi% + \pgf@ifsolution@duplicate@{\pgfmathcounter}% \repeatpgfmathloop% \pgf@intersect@next% } +\def\pgf@ifsolution@duplicate@#1{% + \pgf@process{\csname pgfpoint@g@intersect@solution@#1\endcsname}% + \advance\pgf@x by-\pgf@xa% + \advance\pgf@y by-\pgf@ya% + \ifdim\pgf@x<0pt\relax\pgf@x=-\pgf@x\fi% + \ifdim\pgf@y<0pt\relax\pgf@y=-\pgf@y\fi% + % + \pgf@x=\pgfintersectiontolerancefactor\pgf@x% + \pgf@y=\pgfintersectiontolerancefactor\pgf@y% + \ifdim\pgf@x<\pgfintersectiontolerance\relax% + \ifdim\pgf@y<\pgfintersectiontolerance\relax% + \let\pgf@intersect@next=\pgfutil@firstoftwo% + \fi% + \fi% +}% \newif\ifpgf@intersect@solutions@sortfinish @@ -798,8 +960,7 @@ \def\pgfintersectionsolutionsortbytime{% \pgf@intersect@solutions@sortfinishtrue% \pgfmathloop% - \ifnum\pgfmathcounter=\pgfintersectionsolutions\relax% - \else% + \ifnum\pgfmathcounter<\pgfintersectionsolutions\relax% \pgfutil@tempcnta=\pgfmathcounter% \advance\pgfutil@tempcnta by1\relax% \ifdim\csname pgf@intersect@solution@\pgfmathcounter @time@a\endcsname pt>% @@ -812,10 +973,8 @@ \pgfintersectionsolutionsortbytime@swap{pgf@intersect@solution@\pgfmathcounter @time@a}% {pgf@intersect@solution@\the\pgfutil@tempcnta @time@a}% % - \pgfintersectionsolutionsortbytime@swap{pgf@intersect@solution@segment@a@\pgfmathcounter}% - {pgf@intersect@solution@segment@a@\the\pgfutil@tempcnta}% - \pgfintersectionsolutionsortbytime@swap{pgf@intersect@solution@segment@b@\pgfmathcounter}% - {pgf@intersect@solution@segment@b@\the\pgfutil@tempcnta}% + \pgfintersectionsolutionsortbytime@swap{pgf@intersect@solution@props@\pgfmathcounter}% + {pgf@intersect@solution@props@\the\pgfutil@tempcnta}% \fi% \repeatpgfmathloop% \ifpgf@intersect@solutions@sortfinish% diff --git a/Master/texmf-dist/tex/generic/pgf/libraries/pgflibrarypatterns.meta.code.tex b/Master/texmf-dist/tex/generic/pgf/libraries/pgflibrarypatterns.meta.code.tex new file mode 100644 index 00000000000..467fa1fee46 --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/libraries/pgflibrarypatterns.meta.code.tex @@ -0,0 +1,266 @@ +% Copyright 2015 by Mark Wibrow +% +% 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. + +\def\pgf@pat@type@uncolored{0} +\def\pgf@pat@type@colored{1} +\newif\ifpgf@pat@makepatternimmutable + +\pgfkeys{/pgf/patterns/.cd, + name/.store in=\pgf@pat@name, + number ../.store in=\pgf@pat@number, + type/.is choice, + type/uncolored/.code={\let\pgf@pat@type=\pgf@pat@type@uncolored}, + type/colored/.code={\let\pgf@pat@type=\pgf@pat@type@colored}, + type/form only/.style={/pgf/patterns/type=uncolored}, + type/inherently colored/.style={/pgf/patterns/type=colored}, + x/.store in=\pgf@pat@xvec, + y/.store in=\pgf@pat@yvec, + parameters/.store in=\pgf@pat@parameters, + defaults/.store in=\pgf@pat@defaults, + append to defaults/.code={% + \pgf@pat@addto@macro\pgf@pat@defaults{,#1}% + }, + bottom left/.store in=\pgf@pat@bottomleft, + top right/.store in=\pgf@pat@topright, + tile size/.store in=\pgf@pat@tilesize, + tile transformation/.store in=\pgf@pat@transformation, + code/.store in=\pgf@pat@code, + set up code/.store in=\pgf@pat@declarebefore, + % + name=, + number ..=, + type=uncolored, + x=1cm, y=1cm, + parameters=, + defaults=, + bottom left=\pgfpointorigin, + top right=\pgfpointorigin, + tile size=\pgfpointorigin, + tile transformation=, + code=, + set up code=, +} + +\def\pgf@pat@name@prefix{pgf@pattern@name@meta@} + +\def\pgfifpatternundefined#1{% + \pgfutil@ifundefined{\pgf@pat@name@prefix#1}% +} + +\def\pgf@pat@adddef@to@macro#1#2{% + \expandafter\expandafter\expandafter\def% + \expandafter\expandafter\expandafter#1% + \expandafter\expandafter\expandafter{\expandafter#1\expandafter% + \def\expandafter#2\expandafter{#2}}% +} + +\def\pgf@pat@addto@macro#1#2{% + \expandafter\def\expandafter#1\expandafter{#1#2}}% + +\def\pgf@pat@process#1{% + \pgf@process{#1}% +} + +\def\pgf@pat@doifnotempty#1{% + \ifx#1\pgfutil@empty% + \let\pgf@pat@next=\relax% + \else% + \let\pgf@pat@next=#1% + \fi% + \pgf@pat@next% +} + +\def\pgf@pat@processtransformations#1{#1} +\def\pgf@pat@processpoint#1{% + \pgf@process{#1}% +} + + +\def\pgfdeclarepattern#1{% + \begingroup% + \nullfont% + \def\pgf@pat@options{#1}% + \pgfkeys{/pgf/patterns/.cd, #1}% + \pgf@declarepattern% + \endgroup% +} +\def\pgf@declarepattern{% + \pgfifpatternundefined{\pgf@pat@name}{% + \ifx\pgf@pat@parameters\pgfutil@empty% + % No parameters, so pattern is declared now. + \pgf@pat@declare% + \edef\pgf@marshal{% + \noexpand\pgf@pat@addto@macro\noexpand\pgf@pat@options{,number ..=\pgf@pattern@number}}% + \pgf@marshal% + \fi% + % It is a bit inefficient that all the options for + % immutable patterns are saved when only the type + % and number are needed. + \expandafter\global\expandafter\let\csname\pgf@pat@name@prefix\pgf@pat@name\endcsname=\pgf@pat@options% + }{% + \pgferror{Pattern `\pgf@pat@name' already defined}% + }% +} +\let\pgf@pat@declarebefore=\pgfutil@empty +\let\pgf@pat@declareafter=\pgfutil@empty +\let\pgf@pat@codebefore=\pgfutil@empty +\let\pgf@pat@codeafter=\pgfutil@empty + +\def\pgf@pat@declare{% + \pgfsysprotocol@getcurrentprotocol\pgf@pattern@temp% + {% + % Set up x and y vectors. Should use a scope rather than TeX group? + % Vectors may be needed when the tile bounding box is + % calculated. + \pgfsetxvec{\pgfpoint{\pgf@pat@xvec}{+0pt}}% + \pgfsetyvec{\pgfpoint{+0pt}{\pgf@pat@yvec}}% + \pgf@pat@doifnotempty\pgf@pat@declarebefore% + \pgfinterruptpath% + \pgfpicturetrue% + \pgf@relevantforpicturesizetrue% + \pgftransformreset% + \pgfsysprotocol@setcurrentprotocol\pgfutil@empty% + \pgfsysprotocol@bufferedtrue% + \pgfsys@beginscope% + \pgfinterruptboundingbox% + \pgfsetarrows{-}% + \pgf@pat@doifnotempty\pgf@pat@codebefore + \pgf@pat@code% + \pgf@pat@doifnotempty\pgf@pat@codeafter% + \pgfsys@endscope% + \endpgfinterruptboundingbox% + \pgfsysprotocol@getcurrentprotocol\pgf@pattern@code% + \global\let\pgf@pattern@code=\pgf@pattern@code% + \endpgfinterruptpath% + \pgf@pat@doifnotempty\pgf@pat@declareafter% + \pgf@pat@processpoint{\pgf@pat@bottomleft}% + \pgf@xa=\pgf@x% + \pgf@ya=\pgf@y% + \pgf@pat@processpoint{\pgf@pat@topright}% + \pgf@xb=\pgf@x% + \pgf@yb=\pgf@y% + \pgf@pat@processpoint{\pgf@pat@tilesize}% + \pgf@xc=\pgf@x% + \pgf@yc=\pgf@y% + \begingroup% + \pgftransformreset% + \pgf@pat@processtransformations\pgf@pat@transformation% + \pgfgettransformentries\aa\ab\ba\bb\shiftx\shifty% + \global\edef\pgf@pattern@matrix{{\aa}{\ab}{\ba}{\bb}{\shiftx}{\shifty}}% + \endgroup% + % Now, build a name for the pattern + \pgfutil@tempcnta=\pgf@pattern@number\relax% + \advance\pgfutil@tempcnta by1\relax% + \xdef\pgf@pattern@number{\the\pgfutil@tempcnta}% + \xdef\pgf@marshal{\noexpand\pgfsys@declarepattern@meta% + {\pgf@pattern@number}% + {\the\pgf@xa}{\the\pgf@ya}{\the\pgf@xb}{\the\pgf@yb}{\the\pgf@xc}{\the\pgf@yc}\pgf@pattern@matrix{\pgf@pattern@code}{\pgf@pat@type}}% + }% + \pgf@marshal% + \pgfsysprotocol@setcurrentprotocol\pgf@pattern@temp% + } + +\def\pgf@pat@checkname#1{% + \pgf@pat@@checkname#1[]\pgf@patstop} + +\def\pgf@pat@@checkname#1[#2]#3\pgf@patstop{% + \def\pgf@pat@onlinename{#1}% + \def\pgf@pat@onlineoptions{#2}% +} + + +\def\pgf@pat@unravel#1/{% + \pgfutil@ifnextchar\pgf@stop{\def\pgf@pat@unravelled{#1}}{\pgf@pat@unravel}} + +\pgfkeys{/handlers/.pattern/.code={% + \expandafter\expandafter\expandafter\pgf@pat@unravel\pgfkeyscurrentpath/\pgf@stop% + \pgfpatternalias{#1}{\pgf@pat@unravelled}% +}} + +\def\pgfpatternalias#1#2{% + \begingroup% + \pgf@pat@checkname{#1}% + \expandafter\let\expandafter\pgf@pat@options\expandafter=% + \csname\pgf@pat@name@prefix\pgf@pat@onlinename\endcsname% + \pgf@pat@macroaskeys{/pgf/patterns/.cd}{\pgf@pat@options}% + \pgfutil@toks@\expandafter{\pgf@pat@onlineoptions}% + \edef\pgf@pat@tmp{append to defaults={\the\pgfutil@toks@}}% + \expandafter\pgf@pat@addto@macro\expandafter\pgf@pat@options\expandafter{\expandafter,\pgf@pat@tmp}% + \pgf@pat@addto@macro\pgf@pat@options{,name=#2}% + \expandafter\global\expandafter\let\csname\pgf@pat@name@prefix#2\endcsname=\pgf@pat@options% + \endgroup% +} + + +\let\pgfsetfillpattern@old=\pgfsetfillpattern + +\def\pgf@pat@macroaskeys#1#2{% + \pgfutil@toks@\expandafter{#2}% + \edef\pgf@marshal{\noexpand\pgfkeys{#1, \the\pgfutil@toks@}}% + \pgf@marshal% +} +\def\pgfsetfillpattern#1#2{% + \pgf@pat@checkname{#1}% + \pgfutil@ifundefined{\pgf@pat@name@prefix\pgf@pat@onlinename}{% + \pgfsetfillpattern@old{\pgf@pat@onlinename}{#2}% + }{% + \let\pgf@pat@parameters=\pgfutil@empty% + % Get pattern parameters, type, and number + \expandafter\let\expandafter\pgf@pat@options\expandafter=% + \csname\pgf@pat@name@prefix\pgf@pat@onlinename\endcsname% + \pgf@pat@macroaskeys{/pgf/patterns/.cd}{\pgf@pat@options}% + \ifx\pgf@pat@parameters\pgfutil@empty% + % Immutable pattern. Do nothing. + \else% + % Mutable. Do a *lot*. + \begingroup% + \pgf@pat@macroaskeys{/pgf/pattern keys/.cd}{\pgf@pat@defaults}% + \pgf@pat@macroaskeys{/pgf/pattern keys/.cd}{\pgf@pat@onlineoptions}% + % ...to get the values of the current parameters... + \edef\pgf@pat@current@parameters{\pgf@pat@parameters}% + % ...and the internal pattern name. + \edef\pgf@pat@onlinename{\pgf@pat@onlinename\pgf@pat@current@parameters}% + \let\pgf@pat@name=\pgf@pat@onlinename% + \pgfutil@ifundefined{\pgf@pat@name@prefix\pgf@pat@onlinename}{% + %\ifpgf@pat@makepatternimmutable% + \let\pgf@pat@parameters=\pgfutil@empty% + %\fi% + \pgf@declarepattern% + }{}% + \expandafter% + \endgroup% + \expandafter\def\expandafter\pgf@pat@onlinename\expandafter{\pgf@pat@onlinename}% + \expandafter\let\expandafter\pgf@pat@options\expandafter=% + \csname\pgf@pat@name@prefix\pgf@pat@onlinename\endcsname% + \pgf@pat@macroaskeys{/pgf/patterns/.cd}{\pgf@pat@options}% + \fi% + \ifx\pgf@pat@type\pgf@pat@type@uncolored% + \pgf@pat@setpatternuncolored{\pgf@pat@number}{#2}% + \else% + \pgfsys@setpatterncolored{\pgf@pat@number}% + \fi% + }% +} + +\def\pgf@pat@setpatternuncolored#1#2{% + \pgfutil@colorlet{pgf@tempcolor}{#2}% + \pgfutil@ifundefined{applycolormixins}{}{\applycolormixins{pgf@tempcolor}}% + \pgfutil@extractcolorspec{pgf@tempcolor}{\pgf@tempcolor}% + \expandafter\pgfutil@convertcolorspec\pgf@tempcolor{rgb}{\pgf@rgbcolor}% + \expandafter\pgf@pat@set@fill@patternuncolored\pgf@rgbcolor\relax{#1}% +} +\def\pgf@pat@set@fill@patternuncolored#1,#2,#3\relax#4{% + \pgfsys@setpatternuncolored{#4}{#1}{#2}{#3}% +} + + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: t +%%% End: diff --git a/Master/texmf-dist/tex/generic/pgf/libraries/pgflibraryplotmarks.code.tex b/Master/texmf-dist/tex/generic/pgf/libraries/pgflibraryplotmarks.code.tex index 94862191a3a..b64138dabf3 100644 --- a/Master/texmf-dist/tex/generic/pgf/libraries/pgflibraryplotmarks.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/libraries/pgflibraryplotmarks.code.tex @@ -7,7 +7,7 @@ % % See the file doc/generic/pgf/licenses/LICENSE for more details. -\ProvidesFileRCS[v\pgfversion] $Header: /cvsroot/pgf/pgf/generic/pgf/libraries/pgflibraryplotmarks.code.tex,v 1.13 2013/07/20 13:56:18 ludewich Exp $ +\ProvidesFileRCS[v\pgfversion] $Header: /cvsroot/pgf/pgf/generic/pgf/libraries/pgflibraryplotmarks.code.tex,v 1.14 2015/08/03 10:04:36 cfeuersaenger Exp $ % A stroked circle mark @@ -23,23 +23,23 @@ \pgfdeclareplotmark{Mercedes star} {% - \pgfpathmoveto{\pgfqpointpolar{90}{\pgfplotmarksize}} - \pgfpathlineto{\pgfpointorigin} - \pgfpathmoveto{\pgfqpointpolar{-30}{\pgfplotmarksize}} - \pgfpathlineto{\pgfpointorigin} - \pgfpathmoveto{\pgfqpointpolar{-150}{\pgfplotmarksize}} - \pgfpathlineto{\pgfpointorigin} + \pgfpathmoveto{\pgfqpointpolar{90}{\pgfplotmarksize}}% + \pgfpathlineto{\pgfpointorigin}% + \pgfpathmoveto{\pgfqpointpolar{-30}{\pgfplotmarksize}}% + \pgfpathlineto{\pgfpointorigin}% + \pgfpathmoveto{\pgfqpointpolar{-150}{\pgfplotmarksize}}% + \pgfpathlineto{\pgfpointorigin}% \pgfusepathqstroke } \pgfdeclareplotmark{Mercedes star flipped} {% - \pgfpathmoveto{\pgfqpointpolar{-90}{\pgfplotmarksize}} - \pgfpathlineto{\pgfpointorigin} - \pgfpathmoveto{\pgfqpointpolar{30}{\pgfplotmarksize}} - \pgfpathlineto{\pgfpointorigin} - \pgfpathmoveto{\pgfqpointpolar{150}{\pgfplotmarksize}} - \pgfpathlineto{\pgfpointorigin} + \pgfpathmoveto{\pgfqpointpolar{-90}{\pgfplotmarksize}}% + \pgfpathlineto{\pgfpointorigin}% + \pgfpathmoveto{\pgfqpointpolar{30}{\pgfplotmarksize}}% + \pgfpathlineto{\pgfpointorigin}% + \pgfpathmoveto{\pgfqpointpolar{150}{\pgfplotmarksize}}% + \pgfpathlineto{\pgfpointorigin}% \pgfusepathqstroke } @@ -50,12 +50,12 @@ \pgfdeclareplotmark{asterisk} {% - \pgfpathmoveto{\pgfqpoint{0pt}{-\pgfplotmarksize}} - \pgfpathlineto{\pgfqpoint{0pt}{\pgfplotmarksize}} - \pgfpathmoveto{\pgfqpointpolar{30}{\pgfplotmarksize}} - \pgfpathlineto{\pgfqpointpolar{210}{\pgfplotmarksize}} - \pgfpathmoveto{\pgfqpointpolar{-30}{\pgfplotmarksize}} - \pgfpathlineto{\pgfqpointpolar{-210}{\pgfplotmarksize}} + \pgfpathmoveto{\pgfqpoint{0pt}{-\pgfplotmarksize}}% + \pgfpathlineto{\pgfqpoint{0pt}{\pgfplotmarksize}}% + \pgfpathmoveto{\pgfqpointpolar{30}{\pgfplotmarksize}}% + \pgfpathlineto{\pgfqpointpolar{210}{\pgfplotmarksize}}% + \pgfpathmoveto{\pgfqpointpolar{-30}{\pgfplotmarksize}}% + \pgfpathlineto{\pgfqpointpolar{-210}{\pgfplotmarksize}}% \pgfusepathqstroke } @@ -64,11 +64,11 @@ \pgfdeclareplotmark{star} {% - \pgfpathmoveto{\pgfpointorigin}\pgfpathlineto{\pgfqpoint{0pt}{\pgfplotmarksize}} - \pgfpathmoveto{\pgfpointorigin}\pgfpathlineto{\pgfqpointpolar{18}{\pgfplotmarksize}} - \pgfpathmoveto{\pgfpointorigin}\pgfpathlineto{\pgfqpointpolar{-54}{\pgfplotmarksize}} - \pgfpathmoveto{\pgfpointorigin}\pgfpathlineto{\pgfqpointpolar{234}{\pgfplotmarksize}} - \pgfpathmoveto{\pgfpointorigin}\pgfpathlineto{\pgfqpointpolar{162}{\pgfplotmarksize}} + \pgfpathmoveto{\pgfpointorigin}\pgfpathlineto{\pgfqpoint{0pt}{\pgfplotmarksize}}% + \pgfpathmoveto{\pgfpointorigin}\pgfpathlineto{\pgfqpointpolar{18}{\pgfplotmarksize}}% + \pgfpathmoveto{\pgfpointorigin}\pgfpathlineto{\pgfqpointpolar{-54}{\pgfplotmarksize}}% + \pgfpathmoveto{\pgfpointorigin}\pgfpathlineto{\pgfqpointpolar{234}{\pgfplotmarksize}}% + \pgfpathmoveto{\pgfpointorigin}\pgfpathlineto{\pgfqpointpolar{162}{\pgfplotmarksize}}% \pgfusepathqstroke } @@ -77,11 +77,11 @@ \pgfdeclareplotmark{10-pointed star} {% - \pgfpathmoveto{\pgfqpoint{0pt}{-\pgfplotmarksize}}\pgfpathlineto{\pgfqpoint{0pt}{\pgfplotmarksize}} - \pgfpathmoveto{\pgfqpointpolar{18}{-\pgfplotmarksize}}\pgfpathlineto{\pgfqpointpolar{18}{\pgfplotmarksize}} - \pgfpathmoveto{\pgfqpointpolar{-54}{-\pgfplotmarksize}}\pgfpathlineto{\pgfqpointpolar{-54}{\pgfplotmarksize}} - \pgfpathmoveto{\pgfqpointpolar{234}{-\pgfplotmarksize}}\pgfpathlineto{\pgfqpointpolar{234}{\pgfplotmarksize}} - \pgfpathmoveto{\pgfqpointpolar{162}{-\pgfplotmarksize}}\pgfpathlineto{\pgfqpointpolar{162}{\pgfplotmarksize}} + \pgfpathmoveto{\pgfqpoint{0pt}{-\pgfplotmarksize}}\pgfpathlineto{\pgfqpoint{0pt}{\pgfplotmarksize}}% + \pgfpathmoveto{\pgfqpointpolar{18}{-\pgfplotmarksize}}\pgfpathlineto{\pgfqpointpolar{18}{\pgfplotmarksize}}% + \pgfpathmoveto{\pgfqpointpolar{-54}{-\pgfplotmarksize}}\pgfpathlineto{\pgfqpointpolar{-54}{\pgfplotmarksize}}% + \pgfpathmoveto{\pgfqpointpolar{234}{-\pgfplotmarksize}}\pgfpathlineto{\pgfqpointpolar{234}{\pgfplotmarksize}}% + \pgfpathmoveto{\pgfqpointpolar{162}{-\pgfplotmarksize}}\pgfpathlineto{\pgfqpointpolar{162}{\pgfplotmarksize}}% \pgfusepathqstroke } @@ -90,21 +90,21 @@ \pgfdeclareplotmark{oplus} {% - \pgfpathcircle{\pgfpointorigin}{\pgfplotmarksize} - \pgfpathmoveto{\pgfqpoint{-\pgfplotmarksize}{0pt}} - \pgfpathlineto{\pgfqpoint{\pgfplotmarksize}{0pt}} - \pgfpathmoveto{\pgfqpoint{0pt}{\pgfplotmarksize}} - \pgfpathlineto{\pgfqpoint{0pt}{-\pgfplotmarksize}} + \pgfpathcircle{\pgfpointorigin}{\pgfplotmarksize}% + \pgfpathmoveto{\pgfqpoint{-\pgfplotmarksize}{0pt}}% + \pgfpathlineto{\pgfqpoint{\pgfplotmarksize}{0pt}}% + \pgfpathmoveto{\pgfqpoint{0pt}{\pgfplotmarksize}}% + \pgfpathlineto{\pgfqpoint{0pt}{-\pgfplotmarksize}}% \pgfusepathqstroke } \pgfdeclareplotmark{oplus*} {% - \pgfpathcircle{\pgfpointorigin}{\pgfplotmarksize} - \pgfpathmoveto{\pgfqpoint{-\pgfplotmarksize}{0pt}} - \pgfpathlineto{\pgfqpoint{\pgfplotmarksize}{0pt}} - \pgfpathmoveto{\pgfqpoint{0pt}{\pgfplotmarksize}} - \pgfpathlineto{\pgfqpoint{0pt}{-\pgfplotmarksize}} + \pgfpathcircle{\pgfpointorigin}{\pgfplotmarksize}% + \pgfpathmoveto{\pgfqpoint{-\pgfplotmarksize}{0pt}}% + \pgfpathlineto{\pgfqpoint{\pgfplotmarksize}{0pt}}% + \pgfpathmoveto{\pgfqpoint{0pt}{\pgfplotmarksize}}% + \pgfpathlineto{\pgfqpoint{0pt}{-\pgfplotmarksize}}% \pgfusepathqfillstroke } @@ -113,21 +113,21 @@ \pgfdeclareplotmark{otimes} {% - \pgfpathcircle{\pgfpointorigin}{\pgfplotmarksize} - \pgfpathmoveto{\pgfqpoint{-.70710678\pgfplotmarksize}{-.70710678\pgfplotmarksize}} - \pgfpathlineto{\pgfqpoint{.70710678\pgfplotmarksize}{.70710678\pgfplotmarksize}} - \pgfpathmoveto{\pgfqpoint{-.70710678\pgfplotmarksize}{.70710678\pgfplotmarksize}} - \pgfpathlineto{\pgfqpoint{.70710678\pgfplotmarksize}{-.70710678\pgfplotmarksize}} + \pgfpathcircle{\pgfpointorigin}{\pgfplotmarksize}% + \pgfpathmoveto{\pgfqpoint{-.70710678\pgfplotmarksize}{-.70710678\pgfplotmarksize}}% + \pgfpathlineto{\pgfqpoint{.70710678\pgfplotmarksize}{.70710678\pgfplotmarksize}}% + \pgfpathmoveto{\pgfqpoint{-.70710678\pgfplotmarksize}{.70710678\pgfplotmarksize}}% + \pgfpathlineto{\pgfqpoint{.70710678\pgfplotmarksize}{-.70710678\pgfplotmarksize}}% \pgfusepathqstroke } \pgfdeclareplotmark{otimes*} {% - \pgfpathcircle{\pgfpointorigin}{\pgfplotmarksize} - \pgfpathmoveto{\pgfqpoint{-.70710678\pgfplotmarksize}{-.70710678\pgfplotmarksize}} - \pgfpathlineto{\pgfqpoint{.70710678\pgfplotmarksize}{.70710678\pgfplotmarksize}} - \pgfpathmoveto{\pgfqpoint{-.70710678\pgfplotmarksize}{.70710678\pgfplotmarksize}} - \pgfpathlineto{\pgfqpoint{.70710678\pgfplotmarksize}{-.70710678\pgfplotmarksize}} + \pgfpathcircle{\pgfpointorigin}{\pgfplotmarksize}% + \pgfpathmoveto{\pgfqpoint{-.70710678\pgfplotmarksize}{-.70710678\pgfplotmarksize}}% + \pgfpathlineto{\pgfqpoint{.70710678\pgfplotmarksize}{.70710678\pgfplotmarksize}}% + \pgfpathmoveto{\pgfqpoint{-.70710678\pgfplotmarksize}{.70710678\pgfplotmarksize}}% + \pgfpathlineto{\pgfqpoint{.70710678\pgfplotmarksize}{-.70710678\pgfplotmarksize}}% \pgfusepathqfillstroke } @@ -136,8 +136,8 @@ \pgfdeclareplotmark{|} {% - \pgfpathmoveto{\pgfqpoint{0pt}{\pgfplotmarksize}} - \pgfpathlineto{\pgfqpoint{0pt}{-\pgfplotmarksize}} + \pgfpathmoveto{\pgfqpoint{0pt}{\pgfplotmarksize}}% + \pgfpathlineto{\pgfqpoint{0pt}{-\pgfplotmarksize}}% \pgfusepathqstroke } @@ -147,8 +147,8 @@ \pgfdeclareplotmark{-} {% - \pgfpathmoveto{\pgfqpoint{\pgfplotmarksize}{0pt}} - \pgfpathlineto{\pgfqpoint{-\pgfplotmarksize}{0pt}} + \pgfpathmoveto{\pgfqpoint{\pgfplotmarksize}{0pt}}% + \pgfpathlineto{\pgfqpoint{-\pgfplotmarksize}{0pt}}% \pgfusepathqstroke } @@ -174,9 +174,9 @@ \pgfdeclareplotmark{triangle} {% - \pgfpathmoveto{\pgfqpoint{0pt}{\pgfplotmarksize}} - \pgfpathlineto{\pgfqpointpolar{-30}{\pgfplotmarksize}} - \pgfpathlineto{\pgfqpointpolar{-150}{\pgfplotmarksize}} + \pgfpathmoveto{\pgfqpoint{0pt}{\pgfplotmarksize}}% + \pgfpathlineto{\pgfqpointpolar{-30}{\pgfplotmarksize}}% + \pgfpathlineto{\pgfqpointpolar{-150}{\pgfplotmarksize}}% \pgfpathclose \pgfusepathqstroke } @@ -186,9 +186,9 @@ \pgfdeclareplotmark{triangle*} {% - \pgfpathmoveto{\pgfqpoint{0pt}{\pgfplotmarksize}} - \pgfpathlineto{\pgfqpointpolar{-30}{\pgfplotmarksize}} - \pgfpathlineto{\pgfqpointpolar{-150}{\pgfplotmarksize}} + \pgfpathmoveto{\pgfqpoint{0pt}{\pgfplotmarksize}}% + \pgfpathlineto{\pgfqpointpolar{-30}{\pgfplotmarksize}}% + \pgfpathlineto{\pgfqpointpolar{-150}{\pgfplotmarksize}}% \pgfpathclose \pgfusepathqfillstroke } @@ -199,10 +199,10 @@ \pgfdeclareplotmark{diamond} {% - \pgfpathmoveto{\pgfqpoint{0pt}{\pgfplotmarksize}} - \pgfpathlineto{\pgfqpoint{.75\pgfplotmarksize}{0pt}} - \pgfpathlineto{\pgfqpoint{0pt}{-\pgfplotmarksize}} - \pgfpathlineto{\pgfqpoint{-.75\pgfplotmarksize}{0pt}} + \pgfpathmoveto{\pgfqpoint{0pt}{\pgfplotmarksize}}% + \pgfpathlineto{\pgfqpoint{.75\pgfplotmarksize}{0pt}}% + \pgfpathlineto{\pgfqpoint{0pt}{-\pgfplotmarksize}}% + \pgfpathlineto{\pgfqpoint{-.75\pgfplotmarksize}{0pt}}% \pgfpathclose \pgfusepathqstroke } @@ -212,10 +212,10 @@ \pgfdeclareplotmark{diamond*} {% - \pgfpathmoveto{\pgfqpoint{0pt}{\pgfplotmarksize}} - \pgfpathlineto{\pgfqpoint{.75\pgfplotmarksize}{0pt}} - \pgfpathlineto{\pgfqpoint{0pt}{-\pgfplotmarksize}} - \pgfpathlineto{\pgfqpoint{-.75\pgfplotmarksize}{0pt}} + \pgfpathmoveto{\pgfqpoint{0pt}{\pgfplotmarksize}}% + \pgfpathlineto{\pgfqpoint{.75\pgfplotmarksize}{0pt}}% + \pgfpathlineto{\pgfqpoint{0pt}{-\pgfplotmarksize}}% + \pgfpathlineto{\pgfqpoint{-.75\pgfplotmarksize}{0pt}}% \pgfpathclose \pgfusepathqfillstroke } @@ -226,11 +226,11 @@ \pgfdeclareplotmark{pentagon} {% - \pgfpathmoveto{\pgfqpoint{0pt}{\pgfplotmarksize}} - \pgfpathlineto{\pgfqpointpolar{18}{\pgfplotmarksize}} - \pgfpathlineto{\pgfqpointpolar{-54}{\pgfplotmarksize}} - \pgfpathlineto{\pgfqpointpolar{234}{\pgfplotmarksize}} - \pgfpathlineto{\pgfqpointpolar{162}{\pgfplotmarksize}} + \pgfpathmoveto{\pgfqpoint{0pt}{\pgfplotmarksize}}% + \pgfpathlineto{\pgfqpointpolar{18}{\pgfplotmarksize}}% + \pgfpathlineto{\pgfqpointpolar{-54}{\pgfplotmarksize}}% + \pgfpathlineto{\pgfqpointpolar{234}{\pgfplotmarksize}}% + \pgfpathlineto{\pgfqpointpolar{162}{\pgfplotmarksize}}% \pgfpathclose \pgfusepathqstroke } @@ -239,11 +239,11 @@ \pgfdeclareplotmark{pentagon*} {% - \pgfpathmoveto{\pgfqpoint{0pt}{\pgfplotmarksize}} - \pgfpathlineto{\pgfqpointpolar{18}{\pgfplotmarksize}} - \pgfpathlineto{\pgfqpointpolar{-54}{\pgfplotmarksize}} - \pgfpathlineto{\pgfqpointpolar{234}{\pgfplotmarksize}} - \pgfpathlineto{\pgfqpointpolar{162}{\pgfplotmarksize}} + \pgfpathmoveto{\pgfqpoint{0pt}{\pgfplotmarksize}}% + \pgfpathlineto{\pgfqpointpolar{18}{\pgfplotmarksize}}% + \pgfpathlineto{\pgfqpointpolar{-54}{\pgfplotmarksize}}% + \pgfpathlineto{\pgfqpointpolar{234}{\pgfplotmarksize}}% + \pgfpathlineto{\pgfqpointpolar{162}{\pgfplotmarksize}}% \pgfpathclose \pgfusepathqfillstroke } @@ -436,15 +436,15 @@ % A stroke-filled heart-shaped mark % created by Magnus Tewes \pgfdeclareplotmark{heart}{% - \pgfpathmoveto{\pgfqpoint{0pt}{-1.75\pgfplotmarksize}} - \pgfpathcurveto{\pgfqpoint{0pt}{-1.75\pgfplotmarksize}}{\pgfqpoint{0pt}{-1.66\pgfplotmarksize}}{\pgfqpoint{-.5\pgfplotmarksize}{-1.165\pgfplotmarksize}} - \pgfpathcurveto{\pgfqpoint{-.5\pgfplotmarksize}{-1.165\pgfplotmarksize}}{\pgfqpoint{-\pgfplotmarksize}{-.75\pgfplotmarksize}}{\pgfqpoint{-\pgfplotmarksize}{0pt}} - \pgfpathcurveto{\pgfqpoint{-\pgfplotmarksize}{0pt}}{\pgfqpoint{-\pgfplotmarksize}{.5825\pgfplotmarksize}}{\pgfqpoint{-.5825\pgfplotmarksize}{.5825\pgfplotmarksize}} - \pgfpathcurveto{\pgfqpoint{-.5825\pgfplotmarksize}{.5825\pgfplotmarksize}}{\pgfqpoint{0pt}{.5825\pgfplotmarksize}}{\pgfqpoint{0pt}{0pt}} - \pgfpathcurveto{\pgfqpoint{0pt}{0pt}}{\pgfqpoint{0pt}{.5825\pgfplotmarksize}}{\pgfqpoint{.5825\pgfplotmarksize}{.5825\pgfplotmarksize}} - \pgfpathcurveto{\pgfqpoint{.5825\pgfplotmarksize}{.5825\pgfplotmarksize}}{\pgfqpoint{\pgfplotmarksize}{.5825\pgfplotmarksize}}{\pgfqpoint{\pgfplotmarksize}{0pt}} - \pgfpathcurveto{\pgfqpoint{\pgfplotmarksize}{0pt}}{\pgfqpoint{\pgfplotmarksize}{-.75\pgfplotmarksize}}{\pgfqpoint{.5\pgfplotmarksize}{-1.165\pgfplotmarksize}} - \pgfpathcurveto{\pgfqpoint{.5\pgfplotmarksize}{-1.165\pgfplotmarksize}}{\pgfqpoint{0pt}{-1.66\pgfplotmarksize}}{\pgfqpoint{0pt}{-1.75\pgfplotmarksize}} + \pgfpathmoveto{\pgfqpoint{0pt}{-1.75\pgfplotmarksize}}% + \pgfpathcurveto{\pgfqpoint{0pt}{-1.75\pgfplotmarksize}}{\pgfqpoint{0pt}{-1.66\pgfplotmarksize}}{\pgfqpoint{-.5\pgfplotmarksize}{-1.165\pgfplotmarksize}}% + \pgfpathcurveto{\pgfqpoint{-.5\pgfplotmarksize}{-1.165\pgfplotmarksize}}{\pgfqpoint{-\pgfplotmarksize}{-.75\pgfplotmarksize}}{\pgfqpoint{-\pgfplotmarksize}{0pt}}% + \pgfpathcurveto{\pgfqpoint{-\pgfplotmarksize}{0pt}}{\pgfqpoint{-\pgfplotmarksize}{.5825\pgfplotmarksize}}{\pgfqpoint{-.5825\pgfplotmarksize}{.5825\pgfplotmarksize}}% + \pgfpathcurveto{\pgfqpoint{-.5825\pgfplotmarksize}{.5825\pgfplotmarksize}}{\pgfqpoint{0pt}{.5825\pgfplotmarksize}}{\pgfqpoint{0pt}{0pt}}% + \pgfpathcurveto{\pgfqpoint{0pt}{0pt}}{\pgfqpoint{0pt}{.5825\pgfplotmarksize}}{\pgfqpoint{.5825\pgfplotmarksize}{.5825\pgfplotmarksize}}% + \pgfpathcurveto{\pgfqpoint{.5825\pgfplotmarksize}{.5825\pgfplotmarksize}}{\pgfqpoint{\pgfplotmarksize}{.5825\pgfplotmarksize}}{\pgfqpoint{\pgfplotmarksize}{0pt}}% + \pgfpathcurveto{\pgfqpoint{\pgfplotmarksize}{0pt}}{\pgfqpoint{\pgfplotmarksize}{-.75\pgfplotmarksize}}{\pgfqpoint{.5\pgfplotmarksize}{-1.165\pgfplotmarksize}}% + \pgfpathcurveto{\pgfqpoint{.5\pgfplotmarksize}{-1.165\pgfplotmarksize}}{\pgfqpoint{0pt}{-1.66\pgfplotmarksize}}{\pgfqpoint{0pt}{-1.75\pgfplotmarksize}}% \pgfpathclose \pgfusepathqfillstroke } diff --git a/Master/texmf-dist/tex/generic/pgf/libraries/shapes/circuits/pgflibraryshapes.gates.logic.code.tex b/Master/texmf-dist/tex/generic/pgf/libraries/shapes/circuits/pgflibraryshapes.gates.logic.code.tex index 8b047f04ab1..72d6a6d22ba 100644 --- a/Master/texmf-dist/tex/generic/pgf/libraries/shapes/circuits/pgflibraryshapes.gates.logic.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/libraries/shapes/circuits/pgflibraryshapes.gates.logic.code.tex @@ -11,9 +11,9 @@ % Common keys for all logic gates. % \pgfkeys{/pgf/.cd,% - logic gate input sep/.initial=0.125cm, - logic gate inputs/.initial={normal,normal},% - logic gate inverted radius/.initial=2pt + logic gate input sep/.initial=0.125cm, + logic gate inputs/.initial={normal,normal},% + logic gate inverted radius/.initial=2pt } @@ -21,77 +21,84 @@ % \expandafter\ifx\csname pgf@lib@sh@logicgate@parseinputs\endcsname\relax% \def\pgf@lib@sh@logicgate@parseinputs#1{% - \edef\pgf@lib@sh@temp{\pgfkeysvalueof{/pgf/logic gate inputs}}% - \c@pgf@counta#1\relax% - \c@pgf@countb0\relax% - \expandafter\pgfutil@in@\expandafter,\expandafter{\pgf@lib@sh@temp}% - \ifpgfutil@in@% - \let\pgf@lib@sh@next\pgf@lib@sh@logicgate@parseinputs@long% - \else% - \let\pgf@lib@sh@next\pgf@lib@sh@logicgate@parseinputs@short% - \fi% - \pgf@lib@sh@next% -} + \edef\pgf@lib@sh@temp{\pgfkeysvalueof{/pgf/logic gate inputs}}% + \c@pgf@counta#1\relax% + \c@pgf@countb0\relax% + \expandafter\pgfutil@in@\expandafter,\expandafter{\pgf@lib@sh@temp}% + \ifpgfutil@in@% + \let\pgf@lib@sh@next\pgf@lib@sh@logicgate@parseinputs@long% + \else% + \let\pgf@lib@sh@next\pgf@lib@sh@logicgate@parseinputs@short% + \fi% + \pgf@lib@sh@next% +} \def\pgf@lib@sh@itext{i} \def\pgf@lib@sh@invertedtext{inverted} +\def\pgf@lib@sh@atchar{@} +\def\pgf@lib@sh@gobbletilat#1@{} +\def\pgf@lib@sh@gobbletilatcomma#1@,{} % -% The `short' version for input specifcation is an extension of -% ideas due to Juergen Werber and Christoph Bartoschek. +% The `short' version for input specifcation is an extension of +% ideas due to Juergen Werber and Christoph Bartoschek. % \def\pgf@lib@sh@logicgate@parseinputs@short{% - \expandafter\pgf@lib@sh@logicgate@parseinputs@@short\pgf@lib@sh@temp\pgf@stop% + \expandafter\pgf@lib@sh@logicgate@parseinputs@@short\pgf@lib@sh@temp @% } \def\pgf@lib@sh@logicgate@parseinputs@@short#1{% - \ifx#1\pgf@stop% - \edef\pgf@lib@sh@logicgate@numinputs{\the\c@pgf@countb}% - \let\pgf@lib@sh@next\relax% - \else% - \ifnum\c@pgf@countb=\c@pgf@counta% - \edef\pgf@lib@sh@logicgate@numinputs{\the\c@pgf@countb}% - \let\pgf@lib@sh@next\relax% - \else% - \advance\c@pgf@countb1\relax% - \expandafter\ifx\pgf@lib@sh@itext#1% - \expandafter\pgf@sh@resavedmacro\expandafter{\csname input-\the\c@pgf@countb\endcsname}{% - \expandafter\def\csname input-\the\c@pgf@countb\endcsname{i}}% - \else% - \expandafter\pgf@sh@resavedmacro\expandafter{\csname input-\the\c@pgf@countb\endcsname}{% - \expandafter\def\csname input-\the\c@pgf@countb\endcsname{n}}% - \fi% - \let\pgf@lib@sh@next\pgf@lib@sh@logicgate@parseinputs@@short% - \fi% - \fi% - \pgf@lib@sh@next% + \def\pgf@lib@sh@tmp{#1}% + \ifx\pgf@lib@sh@tmp\pgf@lib@sh@atchar% + \edef\pgf@lib@sh@logicgate@numinputs{\the\c@pgf@countb}% + \let\pgf@lib@sh@next=\relax% + \else% + \ifnum\c@pgf@countb=\c@pgf@counta% + \edef\pgf@lib@sh@logicgate@numinputs{\the\c@pgf@countb}% + \let\pgf@lib@sh@next=\pgf@lib@sh@gobbletilat% + \else% + \advance\c@pgf@countb by1\relax% + \expandafter\ifx\pgf@lib@sh@itext#1% + \expandafter\pgf@sh@resavedmacro\expandafter{\csname input-\the\c@pgf@countb\endcsname}{% + \expandafter\def\csname input-\the\c@pgf@countb\endcsname{i}}% + \else% + \expandafter\pgf@sh@resavedmacro\expandafter{\csname input-\the\c@pgf@countb\endcsname}{% + \expandafter\def\csname input-\the\c@pgf@countb\endcsname{n}}% + \fi% + \let\pgf@lib@sh@next=\pgf@lib@sh@logicgate@parseinputs@@short% + \fi% + \fi% + \pgf@lib@sh@next% } + + \def\pgf@lib@sh@logicgate@parseinputs@long{% - \expandafter\pgf@lib@sh@logicgate@parseinputs@@long\pgf@lib@sh@temp,\pgf@stop,% + \expandafter\pgf@lib@sh@logicgate@parseinputs@@long\pgf@lib@sh@temp,@,% } \def\pgf@lib@sh@logicgate@parseinputs@@long#1,{% - \ifx#1\pgf@stop% - \edef\pgf@lib@sh@logicgate@numinputs{\the\c@pgf@countb}% - \let\pgf@lib@sh@next\relax% - \else% - \ifnum\c@pgf@countb=\c@pgf@counta% - \edef\pgf@lib@sh@logicgate@numinputs{\the\c@pgf@countb}% - \let\pgf@lib@sh@next\relax% - \else% - \advance\c@pgf@countb1\relax% - \def\pgf@lib@sh@temp{#1}% - \ifx\pgf@lib@sh@invertedtext\pgf@lib@sh@temp% - \expandafter\pgf@sh@resavedmacro\expandafter{\csname input-\the\c@pgf@countb\endcsname}{% - \expandafter\def\csname input-\the\c@pgf@countb\endcsname{i}}% - \else% - \expandafter\pgf@sh@resavedmacro\expandafter{\csname input-\the\c@pgf@countb\endcsname}{% - \expandafter\def\csname input-\the\c@pgf@countb\endcsname{n}}% - \fi% - \let\pgf@lib@sh@next\pgf@lib@sh@logicgate@parseinputs@@@long% - \fi% - \fi% - \pgf@lib@sh@next% + \def\pgf@lib@sh@tmp{#1}% + \ifx\pgf@lib@sh@tmp\pgf@lib@sh@atchar% + \edef\pgf@lib@sh@logicgate@numinputs{\the\c@pgf@countb}% + \let\pgf@lib@sh@next=\relax% + \else% + \ifnum\c@pgf@countb=\c@pgf@counta% + \edef\pgf@lib@sh@logicgate@numinputs{\the\c@pgf@countb}% + \let\pgf@lib@sh@next=\pgf@lib@sh@gobbletilatcomma% + \else% + \advance\c@pgf@countb by1\relax% + \def\pgf@lib@sh@temp{#1}% + \ifx\pgf@lib@sh@invertedtext\pgf@lib@sh@temp% + \expandafter\pgf@sh@resavedmacro\expandafter{\csname input-\the\c@pgf@countb\endcsname}{% + \expandafter\def\csname input-\the\c@pgf@countb\endcsname{i}}% + \else% + \expandafter\pgf@sh@resavedmacro\expandafter{\csname input-\the\c@pgf@countb\endcsname}{% + \expandafter\def\csname input-\the\c@pgf@countb\endcsname{n}}% + \fi% + \let\pgf@lib@sh@next=\pgf@lib@sh@logicgate@parseinputs@@@long% + \fi% + \fi% + \pgf@lib@sh@next% } \def\pgf@lib@sh@logicgate@parseinputs@@@long{% - \pgfutil@ifnextchar x{\pgf@lib@sh@logicgate@parseinputs@@long}% - {\pgf@lib@sh@logicgate@parseinputs@@long}% + \pgfutil@ifnextchar x{\pgf@lib@sh@logicgate@parseinputs@@long}% + {\pgf@lib@sh@logicgate@parseinputs@@long}% } \fi% diff --git a/Master/texmf-dist/tex/generic/pgf/lua/pgf/manual/DocumentParser.lua b/Master/texmf-dist/tex/generic/pgf/lua/pgf/manual/DocumentParser.lua index 3905f348358..116809a473c 100644 --- a/Master/texmf-dist/tex/generic/pgf/lua/pgf/manual/DocumentParser.lua +++ b/Master/texmf-dist/tex/generic/pgf/lua/pgf/manual/DocumentParser.lua @@ -7,7 +7,7 @@ -- -- See the file doc/generic/pgf/licenses/LICENSE for more information --- @release $Header: /cvsroot/pgf/pgf/generic/pgf/lua/pgf/manual/DocumentParser.lua,v 1.2 2013/08/01 16:02:22 tantau Exp $ +-- @release $Header: /cvsroot/pgf/pgf/generic/pgf/lua/pgf/manual/DocumentParser.lua,v 1.3 2014/02/24 10:40:33 tantau Exp $ @@ -491,6 +491,8 @@ function print_docline_on_output(output, l, mode) mode = "text" elseif l:match("^%s*@library") then -- do nothing + elseif l:match("^%s*@function") then + -- do nothing elseif l:match("^%s*@end") then close_mode(output, mode) mode = "done" diff --git a/Master/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex b/Master/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex index 727af976f8d..34a5e406a68 100644 --- a/Master/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex @@ -427,8 +427,29 @@ % Expands a floating point number to scientific format 1.234e5. % % This operation is very fast. -\def\pgfmathfloatvalueof#1{\expandafter\pgfmathfloatvalueof@@#1\relax}% -\def\pgfmathfloatvalueof@@#1Y#2e#3]\relax{% +\def\pgfmathfloatvalueof#1{\expandafter\pgfmathfloatvalueof@@#1@@}% + +% Make it fool proof such that the following arguments work: +% \pgfmathfloatvalueof{1Y1.0e1} -> 1.0e1 +% \pgfmathfloatvalueof{2Y1.0e1} -> -1.0e1 +% and wrong arguments as well: +% \pgfmathfloatvalueof{1} -> 1 +% \pgfmathfloatvalueof{1e2} -> 1e2 +\def\pgfmathfloatvalueof@@#1#2{% + \if#2Y% + % keep in mind that \pgfmathfloatvalueof should be expandable! + % We must not use \let here. Let's hope that #1 and #2 are + % single tokens (not something which was enclosed by curly + % braces...) + \expandafter\pgfmathfloatvalueof@@@\expandafter#1\expandafter#2% + \else + % Oh - no float!? Ok, we cannot report errors in this context. + % So: make it a feature and return the input argument as-is. + % Might be useful, in fact... + \expandafter\pgfmathfloatvalueof@abort\expandafter#1\expandafter#2% + \fi +} +\def\pgfmathfloatvalueof@@@#1Y#2e#3]@@{% \ifcase#1 % 0.0e0% \or @@ -440,6 +461,8 @@ \or -inf% \fi }% +\def\pgfmathfloatvalueof@abort#1@@{#1}% + % Rounds a fixed point number #1 to \pgfmathfloat@round@precision digits precision and returns @@ -907,6 +930,7 @@ \newif\ifpgfmathprintnumber@showpositive \newif\ifpgfmathprintnumber@frac@warn \newif\ifpgfmathprintnumber@frac@whole +\newif\ifpgfmathparsenumber@comma@as@period \long\def\pgfmathfloatfrac@verbatim#1#2{#1/#2}% @@ -987,6 +1011,8 @@ showpos/.default=true, print sign/.is if=pgfmathprintnumber@showpositive, print sign/.default=true, + read comma as period/.is if=pgfmathparsenumber@comma@as@period, + read comma as period/.default=true, skip 0./.is if=pgfmathprintnumberskipzeroperiod, skip 0./.default=true, skip 0.= false, @@ -2245,6 +2271,9 @@ \pgfmathfloatcreate{0}{0.0}{0}% }% },% + /pgf/fpu/handlers/invalid separator/.code 2 args={% + \pgfmath@error{Could not parse input '#1' as a floating point number, sorry. The unreadable part was near the decimal separator '#2'. Do you need the option 'read comma as period'?}{}% + }, /pgf/fpu/handlers/invalid number/.code 2 args={% \pgfmath@error{Could not parse input '#1' as a floating point number, sorry. The unreadable part was near '#2'.}{}% }, @@ -2317,6 +2346,30 @@ \expandafter\def\csname pgffltA@.\endcsname{% read '.9' like '0.9' \pgfmathfloat@a@E=-1 \pgfflt@leadingzero@foundperiod}% +\expandafter\def\csname pgffltA@,\endcsname{% read ',9' like '0,9' + \pgfmathfloat@frenchinput{% + \pgfmathfloat@a@E=-1 + \pgfflt@leadingzero@foundperiod + }% +}% + +\def\pgfmathfloat@frenchinput#1{% + \ifpgfmathparsenumber@comma@as@period + \def\pgf@marshal{#1}% + \expandafter\pgf@marshal + \else + \expandafter\pgfflt@error@separator\expandafter,% + \fi +}% +\def\pgfflt@error@separator#1\pgfflt@EOI{% + \begingroup + \pgfmathfloat@a@Mtok={#1}% + \xdef\pgfmathfloat@glob@TMP{% + \noexpand\pgfmathfloatparsenumber@handleerror + {invalid separator}{\pgfmathresult}{\the\pgfmathfloat@a@Mtok}}% + \endgroup + \pgfmathfloat@glob@TMP +}% \def\pgfflt@finish#1\pgfflt@EOI{} @@ -2374,6 +2427,12 @@ \expandafter\def\csname pgffltB@.\endcsname{% \pgfmathfloat@a@E=-1 \pgfflt@leadingzero@foundperiod}% +\expandafter\def\csname pgffltB@,\endcsname{% + \pgfmathfloat@frenchinput{% + \pgfmathfloat@a@E=-1 + \pgfflt@leadingzero@foundperiod + }% +}% \expandafter\def\csname pgffltB@e\endcsname{% \pgfmathfloat@a@S=0\relax% \pgfmathfloat@a@Mtok={0.0}% @@ -2438,6 +2497,7 @@ \expandafter\def\csname pgffltD@9\endcsname{\pgffltD@nonzerodigit9}% \expandafter\def\csname pgffltD@\pgfmathfloat@POSTFLAGSCHAR\endcsname{\pgfflt@readlowlevelfloat}% \expandafter\def\csname pgffltD@.\endcsname{\pgfflt@finish@number@after@period}% FIXME : inlining? +\expandafter\def\csname pgffltD@,\endcsname{\pgfmathfloat@frenchinput{\pgfflt@finish@number@after@period}}% \expandafter\def\csname pgffltD@e\endcsname{\pgfflt@readexponent}% FIXME : inlining? \let\pgffltD@E=\pgffltD@e \expandafter\def\csname pgffltD@\pgfflt@EOI\endcsname{}% NOP @@ -2497,6 +2557,7 @@ \expandafter\def\csname pgffltE@8\endcsname{\pgffltE@nonzerodigit8}% \expandafter\def\csname pgffltE@9\endcsname{\pgffltE@nonzerodigit9}% \expandafter\def\csname pgffltE@.\endcsname{\pgfflt@finish@number@after@period}% FIXME : inlining? +\expandafter\def\csname pgffltE@,\endcsname{\pgfmathfloat@frenchinput{\pgfflt@finish@number@after@period}}% FIXME : inlining? \def\pgffltE@e{\pgfflt@readexponent}% FIXME : inlining? \let\pgffltE@E=\pgffltE@e \expandafter\def\csname pgffltE@\pgfflt@EOI\endcsname{}% NOP diff --git a/Master/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic.code.tex b/Master/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic.code.tex index 99f8ccbb2c0..b6ac16c8bf3 100644 --- a/Master/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic.code.tex @@ -308,6 +308,22 @@ \endgroup% } +% sign(x) +\pgfmathdeclarefunction{sign}{1}{% + \begingroup + \ifdim#1pt>0sp % + \def\pgfmathresult{1}% + \else + \ifdim#1pt=0sp % + \def\pgfmathresult{0}% + \else + \def\pgfmathresult{-1}% + \fi + \fi + \pgfmath@smuggleone\pgfmathresult + \endgroup +} + % e constant. % \pgfmathdeclarefunction{e}{0}{\def\pgfmathresult{2.718281828}} @@ -503,6 +519,12 @@ \endgroup% } +% This is needed since \pgfmathlog2 and \pgfmathlog10 are not legal macro names +\expandafter\let\expandafter\pgfmathlogtwo\csname pgfmathlog2\endcsname +\expandafter\let\expandafter\pgfmathlogtwo@\csname pgfmathlog2@\endcsname +\expandafter\let\expandafter\pgfmathlogten\csname pgfmathlog10\endcsname +\expandafter\let\expandafter\pgfmathlogten@\csname pgfmathlog10@\endcsname + % exp function. % \pgfmathdeclarefunction{exp}{1}{% diff --git a/Master/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code.tex b/Master/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code.tex index 55ef700c14d..b35e3d2595b 100644 --- a/Master/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code.tex @@ -28,7 +28,9 @@ \expandafter\ifx\csname pgfmath@function@#1\endcsname\relax% \pgfmath@error{The function `#1' does not exist}{}% \else% - \pgfmath@namedef{pgfmath#1@}{#2}% + % was: \pgfmath@namedef{pgfmath#1@}{#2}% TT + \edef\pgf@marshal{\noexpand\pgfmathdeclarefunction*{#1}{\csname pgfmath@operation@#1@arity\endcsname}}% + \pgf@marshal{#2}% \fi% } @@ -164,13 +166,21 @@ \expandafter\pgfmath@local@function@@body\pgfmath@local@args,,% \fi% \xdef\pgfmath@local@temp{% - \noexpand\pgfmathdeclarefunction{\pgfmath@local@name}{\the\c@pgf@counta}% - {\noexpand\pgfmathparse{\the\pgfmath@toks}}% + \noexpand\pgfmathnotifynewdeclarefunction{\pgfmath@local@name}{\the\c@pgf@counta}% + {\the\pgfmath@toks}% }% \endgroup% \pgfmath@local@temp% } +% #1: the name +% #2: the number of arguments <n> +% #3: a math expression containing '#1', '#2', ... ,'#'<n> +% This callback is overwritten by pgflibraryluamath. +\def\pgfmathnotifynewdeclarefunction#1#2#3{% + \pgfmathdeclarefunction{#1}{#2}{\pgfmathparse{#3}}% +}% + \def\pgfmath@local@function@@body#1,{% \def\pgfmath@local@test{#1}% \ifx\pgfmath@local@test\pgfutil@empty% diff --git a/Master/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc.code.tex b/Master/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc.code.tex index e00786d7a37..9b807992787 100644 --- a/Master/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc.code.tex @@ -339,3 +339,11 @@ \expandafter\pgfmathmin@\expandafter{\pgfmathresult}% } + + +% scalar function. +% +\pgfmathdeclarefunction{scalar}{1}{% + \def\pgfmathresult{#1}% + \global\pgfmathunitsdeclaredfalse% +}
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.random.code.tex b/Master/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.random.code.tex index 2811d67c101..44b8ef8f6ef 100644 --- a/Master/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.random.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.random.code.tex @@ -39,7 +39,11 @@ % % #1 -> the new seed. % -\def\pgfmathsetseed#1{\pgfmathparse{#1}\expandafter\pgfmath@setseed\pgfmathresult.0\pgfmath@stop}% +\def\pgfmathsetseed#1{% + % Attention pgflibraryluamath.code.tex relies on the fact that + % this method also modifies \pgfmathresult: + \pgfmathparse{#1}\expandafter\pgfmath@setseed\pgfmathresult.0\pgfmath@stop +}% \def\pgfmath@setseed#1.#2\pgfmath@stop{\def\pgfmath@rnd@z{#1}}% % Alternative paramaters - see Press et al (1992) p278-279, @@ -236,4 +240,4 @@ \edef\pgfmath@randomlistlength{\csname pgfmath@randomlist@#2\endcsname}% \pgfmathrandominteger{\pgfmath@randomtemp}{1}{\pgfmath@randomlistlength}% \def#1{\csname pgfmath@randomlist@#2@\pgfmath@randomtemp\endcsname}}} -
\ No newline at end of file + diff --git a/Master/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigonometric.code.tex b/Master/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigonometric.code.tex index 02726731357..aa98934e807 100644 --- a/Master/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigonometric.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigonometric.code.tex @@ -18,6 +18,23 @@ % \pgfmathdeclarefunction{pi}{0}{\def\pgfmathresult{3.141592654}} +\pgfkeys{ + /pgf/trig format/.is choice, + % attention: the luamath library will hook into these code keys. + /pgf/trig format/deg/.code={\def\pgfmath@trig@format@choice{0}}, + /pgf/trig format/rad/.code={\def\pgfmath@trig@format@choice{1}}, + /pgf/trig format/deg, +} + +% Executes #1 if 'trig format=deg' and #2 otherwise. +\def\pgfmathiftrigonometricusesdeg#1#2{% + \if0\pgfmath@trig@format@choice + #1% + \else + #2% + \fi +}% + % \pgfmathradians % (for comptability with 1.18 beta, will be deprecated) % @@ -38,11 +55,15 @@ \pgfmathdeclarefunction{deg}{1}{% \begingroup% \expandafter\pgfmath@x#1pt\relax% - \pgfmath@x57.29577\pgfmath@x\relax% 57.29577 = 360/(2*pi) + \pgfmath@scale@rad@to@deg\pgfmath@x \pgfmath@returnone\pgfmath@x% \endgroup% }% +\def\pgfmath@scale@rad@to@deg#1{% + #1=57.29577#1\relax% 57.29577 = 360/(2*pi) +}% + % \pgfmathrad % % Convert #1 from degrees to radians. @@ -50,12 +71,16 @@ \pgfmathdeclarefunction{rad}{1}{% \begingroup% \expandafter\pgfmath@x#1pt\relax% - \pgfmath@x3.14159\pgfmath@x% - \divide\pgfmath@x180\relax% + \pgfmath@scale@deg@to@rad\pgfmath@x \pgfmath@returnone\pgfmath@x% \endgroup% }% +\def\pgfmath@scale@deg@to@rad#1{% + #1=3.14159#1% + \divide#1180\relax% +}% + % \pgfmathsin % % Calculate the sine of #1 (in degrees). @@ -66,6 +91,10 @@ % \begingroup% \expandafter\pgfmath@x#1pt\relax% + \if1\pgfmath@trig@format@choice + % trig format=rad + \pgfmath@scale@rad@to@deg\pgfmath@x + \fi \advance\pgfmath@x-90pt\relax% \afterassignment\pgfmath@gobbletilpgfmath@ \expandafter\c@pgfmath@counta\the\pgfmath@x\relax\pgfmath@ @@ -108,6 +137,10 @@ % \begingroup% \expandafter\pgfmath@x#1pt\relax% + \if1\pgfmath@trig@format@choice + % trig format=rad + \pgfmath@scale@rad@to@deg\pgfmath@x + \fi \afterassignment\pgfmath@gobbletilpgfmath@% \expandafter\c@pgfmath@counta\the\pgfmath@x\relax\pgfmath@% \divide\c@pgfmath@counta360\relax% @@ -229,6 +262,10 @@ \ifdim\pgfmath@xa<0pt\relax% \pgfmath@x-\pgfmath@x% \fi% + \if1\pgfmath@trig@format@choice + % trig format=rad + \pgfmath@scale@deg@to@rad\pgfmath@x + \fi \pgfmath@returnone\pgfmath@x% \endgroup% } @@ -281,6 +318,10 @@ \pgfmath@x-\pgfmath@x% \advance\pgfmath@x by180pt\relax% \fi% + \if1\pgfmath@trig@format@choice + % trig format=rad + \pgfmath@scale@deg@to@rad\pgfmath@x + \fi \pgfmath@returnone\pgfmath@x% \endgroup% } @@ -310,6 +351,10 @@ \ifdim\pgfmath@xa<0pt\relax% \pgfmath@x-\pgfmath@x% \fi% + \if1\pgfmath@trig@format@choice + % trig format=rad + \pgfmath@scale@deg@to@rad\pgfmath@x + \fi \pgfmath@returnone\pgfmath@x% \endgroup% } @@ -317,13 +362,15 @@ \pgfmathdeclarefunction{atan2}{2}{% % Note: first parameter is y (!), second is x (!) \begingroup% + \let\pgfmath@trig@format@choice@@=\pgfmath@trig@format@choice + \def\pgfmath@trig@format@choice{0}% \pgfmath@y=#1pt\relax% \ifdim\pgfmath@y<0pt\relax% \pgfmath@y=-\pgfmath@y% \fi% \ifdim\pgfmath@y<0.001pt\relax% \ifdim#2pt<0pt\relax% - \pgfmath@x=-180pt\relax% + \pgfmath@x=+180pt\relax% \else% \ifdim#2pt>0pt\relax% \pgfmath@x=0pt\relax% @@ -355,6 +402,10 @@ \pgfmath@x=-\pgfmath@x% \fi% \fi% + \if1\pgfmath@trig@format@choice@@ + % trig format=rad + \pgfmath@scale@deg@to@rad\pgfmath@x + \fi \pgfmath@returnone\pgfmath@x% \endgroup% } diff --git a/Master/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex b/Master/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex index 71843fb2499..e2c78d1fdf4 100644 --- a/Master/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex @@ -25,10 +25,10 @@ \pgfmath@parse@next} \def\pgfmath@catcodes{% Maybe unecessary. - \catcode`\==12% - \catcode`\,=12% - \catcode`\|=12% - \catcode`\&=12% + \catcode`\==12 % + \catcode`\,=12 % + \catcode`\|=12 % + \catcode`\&=12 % } \def\pgfmathqparse{% @@ -38,6 +38,77 @@ \pgfmathparse@} \def\pgfmathparse@#1{% + % No (math) units yet. + \global\pgfmathunitsdeclaredfalse + \global\pgfmathmathunitsdeclaredfalse + % Expand expression so any reamining CSs are registers + % or box dimensions (i.e. |\wd|, |\ht|, |\dp|). + \edef\pgfmath@expression{#1}% + % + \expandafter\pgfmathparse@trynumber@loop\pgfmath@expression\pgfmath@parse@stop + % + % this here is the _real_ parser. it is invoked by + % \pgfmathparse@trynumber@loop if that says "this is no number" + %\pgfmathparse@@\pgfmath@parse@stop% +} + +\def\pgfmath@parse@stop{\pgfmath@parse@stop}% equals only itsself + +\def\pgfmathparse@trynumber@token{numeric} +\begingroup +\def\\{\global\let\pgf@let@space@token= } \\ % now, \pgf@let@space@token is a space token +\endgroup + +% This a "fast-lane": if the expressions consist merely of number +% tokens, we can simply return the number as-is. +% +% This is significantly faster and should resemble the 80% use-case. +% +% #1 a single token +\def\pgfmathparse@trynumber@loop{% + \futurelet\pgfmath@token@let\pgfmathparse@trynumber@loop@ +}% +\def\pgfmathparse@trynumber@loop@#1{% + \ifx\pgfmath@token@let\pgf@let@space@token + % Hm. we found a white space... and we have no support for + % trimming. That means we have to assume that the white space + % occurred somewhere in the middle - and fall back to the + % expensive method. + \def\pgfmath@parse@next{\pgfmathparse@@#1}% + \else + \ifx\pgfmath@token@let\bgroup% + % oh! We found '{' #1. + % Well, these braces appear to be special; fall back to + % the complicated routine... + \let\pgfmath@parse@next=\pgfmathparse@@ + \else + \ifx\pgfmath@token@let\pgfmath@parse@stop + % Ah: we have passed the check! The expression consists only + % of 0123456789. , so do not parse anything and return it + % as-is! + \let\pgfmath@parse@next=\pgfmathparse@expression@is@number + \else + \expandafter\ifx\csname pgfmath@token@\pgfmathparse@trynumber@token @\string#1\endcsname\relax% + % hm. It is none of 0123456789. + \let\pgfmath@parse@next=\pgfmathparse@@ + \else + % continue... we only found one of 0123456789. so + % far... + \let\pgfmath@parse@next=\pgfmathparse@trynumber@loop + \fi + \fi + \fi + \fi + \pgfmath@parse@next +}% + +\def\pgfmathparse@expression@is@number{% + \let\pgfmathresult=\pgfmath@expression + \pgfmath@smuggleone\pgfmathresult% + \endgroup + \ignorespaces +}% +\def\pgfmathparse@@#1\pgfmath@parse@stop{% % We are inside a group (opened in |\pgfmathparse| or % |\pgfmathqparse|). % Stuff for calc compatiability. @@ -50,12 +121,6 @@ \let\depthof=\pgfmath@calc@depthof % Restore font (defined in pgfmathutil.code.tex) \pgfmath@selectfont - % Expand expression so any reamining CSs are registers - % or box dimensions (i.e. |\wd|, |\ht|, |\dp|). - \edef\pgfmath@expression{#1}% - % No (math) units yet. - \global\pgfmathunitsdeclaredfalse - \global\pgfmathmathunitsdeclaredfalse % Set up stack. \pgfmath@stack@operation={{}{}{}}% \pgfmath@stack@operand={{}{}{}}% @@ -896,4 +961,4 @@ % Local Variables: % tab-width: 2 -% End:
\ No newline at end of file +% End: diff --git a/Master/texmf-dist/tex/generic/pgf/modules/pgfmoduledatavisualization.code.tex b/Master/texmf-dist/tex/generic/pgf/modules/pgfmoduledatavisualization.code.tex index 243f8ce225d..f991fdedaef 100644 --- a/Master/texmf-dist/tex/generic/pgf/modules/pgfmoduledatavisualization.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/modules/pgfmoduledatavisualization.code.tex @@ -7,7 +7,7 @@ % % See the file doc/generic/pgf/licenses/LICENSE for more details. -\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/modules/pgfmoduledatavisualization.code.tex,v 1.47 2013/07/19 13:16:48 tantau Exp $ +\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/modules/pgfmoduledatavisualization.code.tex,v 1.50 2015/05/18 17:01:16 tantau Exp $ \usepgfmodule{oo,shapes} \usepgflibrary{fpu} @@ -1523,11 +1523,10 @@ % has a value different from \relax, it will always be used instead % of the in attribute itself. This can be useful to temporarily % set a constant value to a key inside a mapping chain. + % + % If the subkey /is min or max is set to "min" or "max", the mapping + % will always be done to the respective out min or out max values. -% \attribute clip; -% % The code for clipping the interval. Will set \pgf@dvcliptrue, if a -% % clip is necessary. - \attribute out; % The name of the output attribute. @@ -1577,35 +1576,6 @@ \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,map,map datapoint signal) } -% % Method -% \method set clip interval(#1,#2) { -% \def\pgfdvmin{#1}% -% \def\pgfdvmax{#2}% -% \ifx\pgfdvmin\pgfutil@empty% -% \else% -% \pgfdvmathenter{\pgf@dv@temp}{\pgfdvmin}% -% \pgfdvmathexitbyserializing{\pgfdvmin}{\pgf@dv@temp}% -% \fi -% \ifx\pgfdvmax\pgfutil@empty% -% \else% -% \pgfdvmathenter{\pgf@dv@temp}{\pgfdvmax}% -% \pgfdvmathexitbyserializing{\pgfdvmax}{\pgf@dv@temp}% -% \fi -% \pgfooeset{clip}{% -% \noexpand\pgf@dvclipfalse% -% \ifx\pgfdvmin\pgfutil@empty% -% \else% -% \noexpand\pgfdvmathenter{\noexpand\pgf@dv@temp}{\pgfdvmin}% -% \noexpand\pgfdvmathifless{\noexpand\pgfvalue}{\noexpand\pgf@dv@temp}{\noexpand\pgf@dvcliptrue}{}% -% \fi% -% \ifx\pgfdvmax\pgfutil@empty% -% \else% -% \noexpand\pgfdvmathenter{\noexpand\pgf@dv@temp}{\pgfdvmax}% -% \noexpand\pgfdvmathifless{\noexpand\pgf@dv@temp}{\noexpand\pgfvalue}{\noexpand\pgf@dvcliptrue}{}% -% \fi% -% } -% } - % Method % % #1 = in interval minimum @@ -1624,67 +1594,88 @@ % Let's start with the output, it's easier... \pgfoolet{out min}{\pgf@out@interval@min} \pgfoolet{out max}{\pgf@out@interval@max} - \pgfdvmathsub{\pgf@out@diff}{\pgf@out@interval@max}{\pgf@out@interval@min} - \let\pgfvalue=\pgf@in@interval@min - \pgfoovalueof{trans} - \let\pgf@in@interval@min@transformed=\pgfvalue - \pgfoolet{trans in min}{\pgf@in@interval@min@transformed}% - \let\pgfvalue=\pgf@in@interval@max - \pgfoovalueof{trans} - \let\pgf@in@interval@max@transformed=\pgfvalue - \pgfdvmathsub{\pgf@diff@in@transformed}{\pgf@in@interval@max@transformed}{\pgf@in@interval@min@transformed} - % - % Precompute the scaling - % - \pgfdvmathdiv{\pgf@scale}{\pgf@out@diff}{\pgf@diff@in@transformed}% - \pgfoolet{scale}{\pgf@scale}% + \pgfdvmathifless{\pgf@in@interval@min}{\pgf@in@interval@max}{% + \pgfdvmathsub{\pgf@out@diff}{\pgf@out@interval@max}{\pgf@out@interval@min} + \let\pgfvalue=\pgf@in@interval@min + \pgfoovalueof{trans} + \let\pgf@in@interval@min@transformed=\pgfvalue + \pgfoolet{trans in min}{\pgf@in@interval@min@transformed}% + \let\pgfvalue=\pgf@in@interval@max + \pgfoovalueof{trans} + \let\pgf@in@interval@max@transformed=\pgfvalue + \pgfdvmathsub{\pgf@diff@in@transformed}{\pgf@in@interval@max@transformed}{\pgf@in@interval@min@transformed} + % + % Precompute the scaling + % + \pgfdvmathdiv{\pgf@scale}{\pgf@out@diff}{\pgf@diff@in@transformed}% + \pgfoolet{scale}{\pgf@scale}% + }{% + \pgfoolet{scale}\pgf@dv@no@scale% + }% }% } - + \def\pgf@dv@no@scale{noscale} + % Slot \method map() { - \pgfooget{scale}\pgf@temp - \ifx\pgf@temp\pgfutil@empty% + \pgfooget{scale}\pgf@dv@scale + \ifx\pgf@dv@scale\pgfutil@empty% % not yet setup \else% - \pgfkeysgetvalue{/data point/\pgfoovalueof{in}/const}\pgf@dv@external@value% - \ifx\pgf@dv@external@value\relax% - \pgfkeysgetvalue{/data point/\pgfoovalueof{in}}\pgf@dv@external@value% - \fi% - \ifx\pgf@dv@external@value\pgfutil@empty% - \pgf@dv@mapper@pos@check% + \pgfkeysgetvalue{/data point/\pgfoovalueof{in}/is min or max}\pgf@dv@is% + \ifx\pgf@dv@is\pgf@min@text% + \pgf@dv@set@out@min% \else% - \ifx\pgf@dv@external@value\relax% - \pgf@dv@mapper@pos@check% + \ifx\pgf@dv@is\pgf@max@text% + \pgf@dv@set@out@max% \else% -% % Clip? - \pgfdvmathenter{\pgfvalue}{\pgf@dv@external@value}% -% \pgfoovalueof{clip}% -% \ifpgf@dvclip% -% \pgfkeyslet{/data point/\pgfoovalueof{out}}\pgfutil@empty% -% \else% - \pgf@dv@mapper@trans{} -% \fi% + \ifx\pgf@dv@scale\pgf@dv@no@scale% + \pgf@dv@mapper@goto@mid% + \else% + \pgfkeysgetvalue{/data point/\pgfoovalueof{in}/const}\pgf@dv@external@value% + \ifx\pgf@dv@external@value\relax% + \pgfkeysgetvalue{/data point/\pgfoovalueof{in}}\pgf@dv@external@value% + \fi% + \ifx\pgf@dv@external@value\pgfutil@empty% + \pgf@dv@mapper@pos@check% + \else% + \ifx\pgf@dv@external@value\relax% + \pgf@dv@mapper@pos@check% + \else% + \pgfdvmathenter{\pgfvalue}{\pgf@dv@external@value}% + \pgf@dv@mapper@trans + \fi% + \fi% + \fi% \fi% \fi% -% \pgfkeysgetvalue{/data point/\pgfoovalueof{in}/min}\pgf@dv@external@value% -% \ifx\pgf@dv@external@value\relax\else% -% \ifx\pgf@dv@external@value\pgfutil@empty\else% -% \pgfdvmathenter{\pgfvalue}{\pgf@dv@external@value}% -% \pgf@dv@mapper@trans{/min} -% \fi -% \fi -% \pgfkeysgetvalue{/data point/\pgfoovalueof{in}/max}\pgf@dv@external@value% -% \ifx\pgf@dv@external@value\relax\else% -% \ifx\pgf@dv@external@value\pgfutil@empty\else% -% \pgfdvmathenter{\pgfvalue}{\pgf@dv@external@value}% -% \pgf@dv@mapper@trans{/max} -% \fi -% \fi \fi% } - \def\pgf@dv@mapper@trans#1{ + \def\pgf@dv@set@out@min{% + \pgfkeyslet{/data point/\pgfoovalueof{out}/is min or max}\pgf@min@text% + \pgfooget{out min}{\pgf@minmax@temp}% + \pgf@dv@set@out@now% + } + \def\pgf@dv@set@out@max{% + \pgfkeyslet{/data point/\pgfoovalueof{out}/is min or max}\pgf@max@text% + \pgfooget{out max}{\pgf@minmax@temp}% + \pgf@dv@set@out@now% + } + \def\pgf@dv@set@out@now{% + \pgfkeysgetvalue{/data point/\pgfoovalueof{out}/offset}\pgf@dv@external@offset% + \ifx\pgf@dv@external@offset\relax\else% + \ifx\pgf@dv@external@offset\pgfutil@empty\else% + \pgfdvmathenter{\pgfvalue}{\pgf@minmax@temp}% + \pgfdvmathenter{\pgf@dv@offset}{\pgf@dv@external@offset}% + \pgfdvmathadd{\pgfvalue}{\pgfvalue}{\pgf@dv@offset} + \pgfdvmathexitbyserializing{\pgf@minmax@temp}{\pgfvalue}% + \fi + \fi + \pgfkeyslet{/data point/\pgfoovalueof{out}}\pgf@minmax@temp% + } + + \def\pgf@dv@mapper@trans{ \pgfooget{trans in min}{\pgf@dv@trans@in@min}% \pgfooget{scale}{\pgf@dv@scale}% \pgfooget{out min}{\pgf@dv@out@min}% @@ -1692,7 +1683,7 @@ \pgfdvmathsub{\pgfvalue}{\pgfvalue}{\pgf@dv@trans@in@min}% \pgfdvmathmul{\pgfvalue}{\pgfvalue}{\pgf@dv@scale}% \pgfdvmathadd{\pgfvalue}{\pgfvalue}{\pgf@dv@out@min}% - \pgfkeysgetvalue{/data point/\pgfoovalueof{out}#1/offset}\pgf@dv@external@offset% + \pgfkeysgetvalue{/data point/\pgfoovalueof{out}/offset}\pgf@dv@external@offset% \ifx\pgf@dv@external@offset\relax\else% \ifx\pgf@dv@external@offset\pgfutil@empty\else% \pgfdvmathenter{\pgf@dv@offset}{\pgf@dv@external@offset}% @@ -1700,7 +1691,7 @@ \fi \fi \pgfdvmathexitbyserializing{\pgf@temp}{\pgfvalue}% - \pgfkeyslet{/data point/\pgfoovalueof{out}#1}\pgf@temp% + \pgfkeyslet{/data point/\pgfoovalueof{out}}\pgf@temp% } \def\pgf@dv@mapper@pos@check{% @@ -1718,6 +1709,17 @@ \pgfkeyslet{/data point/\pgfoovalueof{out}}\pgf@temp% \fi\fi% } + + \def\pgf@dv@mapper@goto@mid{% + % Ok, compute transformed min position: + \pgfooget{out min}{\pgf@out@interval@min} + \pgfooget{out max}{\pgf@out@interval@max} + \pgfdvmathmulfixed{\pgf@out@interval@min}{\pgf@out@interval@min}{.5} + \pgfdvmathmulfixed{\pgf@out@interval@max}{\pgf@out@interval@max}{.5} + \pgfdvmathadd{\pgf@out@val}{\pgf@out@interval@min}{\pgf@out@interval@max}% + \pgfdvmathexitbyserializing{\pgf@temp}{\pgf@out@val}% + \pgfkeyslet{/data point/\pgfoovalueof{out}}\pgf@temp% + } } @@ -1775,6 +1777,14 @@ % that deforms the linear mapping. In case f is specified, % f(#1) is mapped to #2 and f(#3) is mapped to #4. + \attribute spec maps min; + % When the scaling spec maps "min" to some value, rather than some + % specific value to that value, then spec maps min will be set to + % \pgfutil@firstoftwo, otherwise to \pgfutil@secondoftwo + + \attribute spec maps max; + % Like spec maps min + \attribute function; % Stores the function @@ -1826,18 +1836,6 @@ \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,phase,phase signal) } - -% % Method -% % -% % #1 = a min clip -- everything below this value will be clipped -% % #2 = a max value -- everything above this value will be clipped -% % -% % Sets a clipping for the underlying interval mapper. -% % -% \method set clip interval(#1,#2) { -% \pgfoovalueof{interval mapper}.set clip interval({#1},{#2})% -% } - % Getter % % Returns an interval object that stores the range of the in @@ -1887,21 +1885,23 @@ % In case #1 is set to the special value "min", it evaluates to % \pgfdvmin, when set to "max" it evaluates to \pgfdvmax. % - \method set in to(#1) { - \edef\pgf@temp{#1} - \ifx\pgf@temp\pgf@min@text + \method set in to(#1) {% + \edef\pgf@temp{#1}% + \ifx\pgf@temp\pgf@min@text% \pgf@dv@lib@set@mm% - \let\pgf@dv@value\pgfdvmin - \else - \ifx\pgf@temp\pgf@max@text + \let\pgf@dv@value\pgfdvmin% + \pgfoovalueof{spec maps min}{\pgfkeyslet{/data point/\pgfoovalueof{in}/is min or max}\pgf@min@text}{}% + \else% + \ifx\pgf@temp\pgf@max@text% \pgf@dv@lib@set@mm% - \let\pgf@dv@value\pgfdvmax - \else - \pgfdvmathenter{\pgf@dv@value}{\pgf@temp} - \fi - \fi - \pgfdvmathexitbyserializing{\pgf@dv@serial}{\pgf@dv@value} - \pgfkeyslet{/data point/\pgfoovalueof{in}}\pgf@dv@serial + \let\pgf@dv@value\pgfdvmax% + \pgfoovalueof{spec maps min}{\pgfkeyslet{/data point/\pgfoovalueof{in}/is min or max}\pgf@max@text}{}% + \else% + \pgfdvmathenter{\pgf@dv@value}{\pgf@temp}% + \fi% + \fi% + \pgfdvmathexitbyserializing{\pgf@dv@serial}{\pgf@dv@value}% + \pgfkeyslet{/data point/\pgfoovalueof{in}}\pgf@dv@serial% } \def\pgf@dv@lib@set@mm{ \pgfooget{in range obj}\pgfdvinrangeinterval @@ -1918,7 +1918,7 @@ \pgfoovalueof{in range obj}.get min and max() \ifx\pgfdvmin\pgfutil@empty% undefined, since no data points \else% - \pgfooget{scaling spec}\pgf@temp + \pgfooget{scaling spec}\pgf@temp% \expandafter\pgf@lib@dv@parse@scaling\pgf@temp\pgf@stop% \pgfoovalueof{interval mapper}.set interval values(% \pgf@lib@dv@min,\pgf@lib@dv@max,% @@ -1936,13 +1936,17 @@ \pgfdvmathenter{\pgf@lib@dv@max@at@mv}{#4} \ifx\pgf@lib@dv@min\pgf@min@text% \let\pgf@lib@dv@min@mv\pgfdvmin + \pgfoolet{spec maps min}\pgfutil@firstoftwo% \else \pgfdvmathenter{\pgf@lib@dv@min@mv}{\pgf@lib@dv@min} + \pgfoolet{spec maps min}\pgfutil@secondoftwo% \fi \ifx\pgf@lib@dv@max\pgf@max@text% \let\pgf@lib@dv@max@mv\pgfdvmax + \pgfoolet{spec maps max}\pgfutil@firstoftwo% \else \pgfdvmathenter{\pgf@lib@dv@max@mv}{\pgf@lib@dv@max} + \pgfoolet{spec maps max}\pgfutil@secondoftwo% \fi \pgfdvmathexitbyserializing{\pgf@lib@dv@min}{\pgf@lib@dv@min@mv} \pgfdvmathexitbyserializing{\pgf@lib@dv@min@at}{\pgf@lib@dv@min@at@mv} @@ -2767,7 +2771,7 @@ \c@pgf@counta=\c@pgf@countb\relax \c@pgf@countb=\c@pgf@countc\relax \fi - \edef\temp{rows: \the\c@pgf@counta, columns: \the\c@pgf@countb}\temp + %\edef\temp{rows: \the\c@pgf@counta, columns: \the\c@pgf@countb}\temp % % Now arrange the matrix % diff --git a/Master/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code.tex b/Master/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code.tex index 8620a91e4de..696608e31e8 100644 --- a/Master/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code.tex @@ -7,7 +7,7 @@ % % See the file doc/generic/pgf/licenses/LICENSE for more details. -\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/modules/pgfmoduleplot.code.tex,v 1.12 2013/07/31 16:22:24 tantau Exp $ +\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/modules/pgfmoduleplot.code.tex,v 1.13 2015/08/03 07:57:07 cfeuersaenger Exp $ % PGF's plotting interface works as follows: @@ -328,6 +328,7 @@ \def\pgfplotxyfile#1{% \begingroup% + \def\b@pgfplotsxyfile@scanning@for@first{1}% \pgfplotstreamstart% \openin\r@pgf@reada=#1 \ifeof\r@pgf@reada @@ -348,9 +349,15 @@ \let\par=\pgf@savedpar% \edef\pgf@temp{\pgf@temp}% \ifx\pgf@temp\pgfutil@empty% - \ifeof\r@pgf@reada\else\pgfplotstreamnewdataset\fi% + \if1\b@pgfplotsxyfile@scanning@for@first + \else + \ifeof\r@pgf@reada\else\pgfplotstreamnewdataset\fi% + \fi \else\ifx\pgf@temp\pgf@partext% - \ifeof\r@pgf@reada\else\pgfplotstreamnewdataset\fi% + \if1\b@pgfplotsxyfile@scanning@for@first + \else + \ifeof\r@pgf@reada\else\pgfplotstreamnewdataset\fi% + \fi \else% \expandafter\pgf@parsexyline\pgf@temp\pgf@stop% \fi\fi% @@ -358,6 +365,7 @@ } \def\pgf@parsexyline#1 #2 #3\pgf@stop{% + \def\b@pgfplotsxyfile@scanning@for@first{0}% \edef\pgf@xyline@flag@val{#3}% \ifx\pgf@xyline@flag@val\pgf@xyline@flag@undef% \pgfplotstreampointundefined% @@ -405,9 +413,15 @@ \def\pgf@readxyzfile{% \pgfutil@read\r@pgf@reada to \pgf@temp% \ifx\pgf@temp\pgfutil@empty% - \ifeof\r@pgf@reada\else\pgfplotstreamnewdataset\fi% + \if1\b@pgfplotsxyfile@scanning@for@first + \else + \ifeof\r@pgf@reada\else\pgfplotstreamnewdataset\fi% + \fi \else\ifx\pgf@temp\pgf@partext% - \ifeof\r@pgf@reada\else\pgfplotstreamnewdataset\fi% + \if1\b@pgfplotsxyfile@scanning@for@first + \else + \ifeof\r@pgf@reada\else\pgfplotstreamnewdataset\fi% + \fi \else% \expandafter\pgf@parsexyzline\pgf@temp\pgf@stop% \fi\fi% @@ -415,6 +429,7 @@ } \def\pgf@parsexyzline#1 #2 #3 #4\pgf@stop{% + \def\b@pgfplotsxyfile@scanning@for@first{0}% \edef\pgf@xyline@flag@val{#4}% \ifx\pgf@xyline@flag@val\pgf@xyline@flag@undef% \pgfplotstreampointundefined% diff --git a/Master/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.code.tex b/Master/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.code.tex index 7e4e65d4c38..6a4d0932393 100644 --- a/Master/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.code.tex @@ -7,7 +7,7 @@ % % See the file doc/generic/pgf/licenses/LICENSE for more details. -\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/modules/pgfmoduleshapes.code.tex,v 1.34 2013/10/31 15:44:19 tantau Exp $ +\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/modules/pgfmoduleshapes.code.tex,v 1.35 2014/03/21 19:52:38 tantau Exp $ @@ -41,6 +41,7 @@ {\pgferror{Unknown shape ``#1''}}% {% {% + \pgf@outer@adjust@hook% \let\pgf@sh@savedmacros=\pgfutil@empty% MW \let\pgf@sh@savedpoints=\pgfutil@empty% \def\pgf@sm@shape@name{#1}% CJ % TT added prefix! @@ -108,6 +109,7 @@ }% }% } +\let\pgf@outer@adjust@hook\relax \def\pgf@shapes@late@pos@begin{% % Rename node @@ -153,8 +155,6 @@ }% } -\let\pgf@nodecallback=\pgfutil@gobble - % Creates a node @@ -400,6 +400,8 @@ } + + % Quickly create a coordinate node % % #1 = name @@ -849,12 +851,33 @@ inner sep/.style ={/pgf/inner xsep=#1,/pgf/inner ysep=#1}, outer xsep/.initial =.5\pgflinewidth, outer ysep/.initial =.5\pgflinewidth, - outer sep/.style ={/pgf/outer xsep=#1,/pgf/outer ysep=#1}, + outer sep/.code =\pgf@handle@outer@sep{#1}, minimum width/.initial =1pt, minimum height/.initial =1pt, minimum size/.style ={/pgf/minimum width=#1,/pgf/minimum height=#1}, } + + +\def\pgf@handle@outer@sep#1{% + \def\pgf@temp{#1}% + \ifx\pgf@temp\pgf@auto@text% + \def\pgf@outer@adjust@hook{% + \pgftransformationadjustments% + \pgfkeyssetvalue{/pgf/outer xsep}{.5\pgflinewidth*\pgfhorizontaltransformationadjustment}% + \pgfkeyssetvalue{/pgf/outer ysep}{.5\pgflinewidth*\pgfverticaltransformationadjustment}% + \pgf@outer@auto@adjust@hook% + }% + \else% + \pgfkeyssetvalue{/pgf/outer xsep}{#1}% + \pgfkeyssetvalue{/pgf/outer ysep}{#1}% + \fi% +} +\def\pgf@auto@text{auto} + +\let\pgf@outer@auto@adjust@hook\relax + + % Keys for rotating the shape border. % (may not be supported by all shapes) % diff --git a/Master/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-dvipdfm.def b/Master/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-dvipdfm.def index 0ad85414779..54cd937a591 100644 --- a/Master/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-dvipdfm.def +++ b/Master/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-dvipdfm.def @@ -7,7 +7,7 @@ % % See the file doc/generic/pgf/licenses/LICENSE for more details. -\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/systemlayer/pgfsys-dvipdfm.def,v 1.21 2013/07/16 16:03:13 tantau Exp $ +\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/systemlayer/pgfsys-dvipdfm.def,v 1.22 2014/07/09 14:01:22 cfeuersaenger Exp $ % Driver commands for dvipdfm @@ -30,6 +30,12 @@ % } } +\def\pgfsys@prepare@papersize#1#2{% + \expandafter\gdef\expandafter\pgfsys@atbegindocument% + \expandafter{\pgfsys@atbegindocument + \special{papersize=#1,#2}% + } +} % % Position tracking (needs pdftex >= 1.40.0-alpha-20051205 in dvi mode) diff --git a/Master/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-dvipdfmx.def b/Master/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-dvipdfmx.def index a5806aeab78..cf1d5b9fe1e 100644 --- a/Master/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-dvipdfmx.def +++ b/Master/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-dvipdfmx.def @@ -7,7 +7,7 @@ % % See the file doc/generic/pgf/licenses/LICENSE for more details. -\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/systemlayer/pgfsys-dvipdfmx.def,v 1.12 2013/08/28 11:00:54 tantau Exp $ +\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/systemlayer/pgfsys-dvipdfmx.def,v 1.14 2014/07/09 14:01:22 cfeuersaenger Exp $ % Driver commands for dvipdfmx % @@ -232,6 +232,7 @@ } \def\pgfsyspdfmark##1##2##3{% \expandafter\gdef\csname pgf@sys@pdf@mark@pos@##1\endcsname{\pgfqpoint{##2sp}{##3sp}}% + \pgfutil@check@rerun{##1}{{##2}{##3}}% } \def\pgfsys@getposition##1##2{% \edef\pgf@marshal{\let\noexpand##2=\expandafter\noexpand\csname pgf@sys@pdf@mark@pos@##1\endcsname}% @@ -481,6 +482,12 @@ \special{papersize=#1,#2}% % } } +\def\pgfsys@prepare@papersize#1#2{% + \expandafter\gdef\expandafter\pgfsys@atbegindocument%% + \expandafter{\pgfsys@atbegindocument + \special{papersize=#1,#2}% + } +} \endinput diff --git a/Master/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-dvips.def b/Master/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-dvips.def index 3847d14a6c8..c3a2b6200f8 100644 --- a/Master/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-dvips.def +++ b/Master/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-dvips.def @@ -7,7 +7,7 @@ % % See the file doc/generic/pgf/licenses/LICENSE for more details. -\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/systemlayer/pgfsys-dvips.def,v 1.23 2013/07/16 16:03:13 tantau Exp $ +\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/systemlayer/pgfsys-dvips.def,v 1.25 2014/07/09 14:01:22 cfeuersaenger Exp $ % Driver commands for dvips @@ -52,8 +52,12 @@ \def\pgfsys@imagesuffixlist{.epsi:.eps:.ps:} \def\pgfsys@papersize#1#2{% - \special{papersize=#1,#2}% -}% \expandafter\gdef\expandafter\pgfsys@atbegindocument\expandafter{\pgfsys@atbegindocument\special{papersize=#1,#2}}} + \special{papersize=#1,#2}% + % \expandafter\gdef\expandafter\pgfsys@atbegindocument\expandafter{\pgfsys@atbegindocument\special{papersize=#1,#2}}% +} +\def\pgfsys@prepare@papersize#1#2{% + \expandafter\gdef\expandafter\pgfsys@atbegindocument\expandafter{\pgfsys@atbegindocument\special{papersize=#1,#2}}% +} \expandafter\gdef\expandafter\pgfsys@atbegindocument\expandafter{\pgfsys@atbegindocument% \pgf@sys@postscript@header{ @@ -107,6 +111,7 @@ \def\pgfsyspdfmark#1#2#3{% \expandafter\gdef\csname pgf@sys@pdf@mark@pos@#1\endcsname{\pgfqpoint{#2sp}{#3sp}}% + \pgfutil@check@rerun{#1}{{#2}{#3}}% } \def\pgfsys@getposition#1#2{% diff --git a/Master/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-pdftex.def b/Master/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-pdftex.def index b9ee92c3622..0cc939675f6 100644 --- a/Master/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-pdftex.def +++ b/Master/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-pdftex.def @@ -7,7 +7,7 @@ % % See the file doc/generic/pgf/licenses/LICENSE for more details. -\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/systemlayer/pgfsys-pdftex.def,v 1.33 2013/07/18 10:34:44 tantau Exp $ +\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/systemlayer/pgfsys-pdftex.def,v 1.35 2014/10/11 09:23:31 vibrovski Exp $ % Driver commands for pdf @@ -216,6 +216,55 @@ \pgfsysprotocol@literal{/Pattern cs /pgfpat#1\space scn}% } +% System layer for meta patterns +% Takes 15(!) arguments +% #1 pattern name +% #2 #3 bounding box lower left +% #4 #5 bounding box upper right +% #6 #7 tile size +% #8 #9 #10 #11 #12 #13 transformation matrix +% #14 protocoled text +% #15 pattern type +\def\pgfsys@declarepattern@meta#1#2#3#4#5#6#7{% + % Start building the pattern dictionary: + \pgf@xa=#2\relax% + \pgf@ya=#3\relax% + \pgf@xb=#4\relax% + \pgf@yb=#5\relax% + \pgf@xc=#6\relax% + \pgf@yc=#7\relax% + \pgf@sys@bp@correct\pgf@xa% + \pgf@sys@bp@correct\pgf@ya% + \pgf@sys@bp@correct\pgf@xb% + \pgf@sys@bp@correct\pgf@yb% + \pgf@sys@bp@correct\pgf@xc% + \pgf@sys@bp@correct\pgf@yc% + \pgfsys@@declarepattern@meta{#1}} + +\def\pgfsys@@declarepattern@meta#1#2#3#4#5#6#7#8#9{% + \pgfutil@tempdima=#6\relax% + \pgfutil@tempdimb=#7\relax% + \pgf@sys@bp@correct\pgf@xa% + \pgf@sys@bp@correct\pgf@ya% + % Now create the pattern object: + \immediate\pdfobj stream + attr + { + /Type /Pattern + /PatternType 1 + /PaintType \ifnum#9=0 2 \else 1 \fi + /TilingType 1 + /BBox [\pgf@sys@tonumber\pgf@xa\space\pgf@sys@tonumber\pgf@ya\space\pgf@sys@tonumber\pgf@xb\space\pgf@sys@tonumber\pgf@yb] + /XStep \pgf@sys@tonumber\pgf@xc\space + /YStep \pgf@sys@tonumber\pgf@yc\space + /Matrix [#2\space#3\space#4\space#5\space\pgf@sys@tonumber\pgfutil@tempdima\space\pgf@sys@tonumber\pgfutil@tempdimb] + /Resources << >> %<< + } + {#8}% + \pgfutil@addpdfresource@patterns{/pgfpat#1\space \the\pdflastobj\space 0 R}% + } + + \def\pgfsys@papersize#1#2{\pdfpageheight#2\relax\pdfpagewidth#1\relax} @@ -239,6 +288,7 @@ \def\pgfsyspdfmark#1#2#3{% \expandafter\gdef\csname pgf@sys@pdf@mark@pos@#1\endcsname{\pgfqpoint{#2sp}{#3sp}}% + \pgfutil@check@rerun{#1}{{#2}{#3}}% } \def\pgfsys@getposition#1#2{% diff --git a/Master/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-xetex.def b/Master/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-xetex.def index 9d13ae1ae70..e23e48c2f57 100644 --- a/Master/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-xetex.def +++ b/Master/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-xetex.def @@ -7,7 +7,7 @@ % % See the file doc/generic/pgf/licenses/LICENSE for more details. -\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/systemlayer/pgfsys-xetex.def,v 1.9 2013/07/16 16:03:13 tantau Exp $ +\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/systemlayer/pgfsys-xetex.def,v 1.11 2014/07/09 14:01:22 cfeuersaenger Exp $ \input pgfsys-dvipdfmx.def @@ -19,12 +19,12 @@ % XeTeX supports pdftex commands for paper size \def\pgfsys@papersize#1#2{% - \pdfpageheight#2% - \pdfpagewidth#1} + \pdfpageheight#2\relax% + \pdfpagewidth#1\relax} \def\pgfsys@global@papersize#1#2{% - \global\pdfpageheight#2% - \global\pdfpagewidth#1} + \global\pdfpageheight#2\relax% + \global\pdfpagewidth#1\relax} % Xetex does not support interpolate and not mask @@ -54,6 +54,7 @@ \def\pgfsyspdfmark#1#2#3{% \expandafter\gdef\csname pgf@sys@pdf@mark@pos@#1\endcsname{\pgfqpoint{#2sp}{#3sp}}% + \pgfutil@check@rerun{#1}{{#2}{#3}}% } \def\pgfsys@getposition#1#2{% diff --git a/Master/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex b/Master/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex index 63a1aac41a5..e33a132c29b 100644 --- a/Master/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex @@ -7,7 +7,7 @@ % % See the file doc/generic/pgf/licenses/LICENSE for more details. -\ProvidesPackageRCS[v\pgfversion] $Header: /cvsroot/pgf/pgf/generic/pgf/systemlayer/pgfsys.code.tex,v 1.47 2013/11/30 11:35:10 ludewich Exp $ +\ProvidesPackageRCS[v\pgfversion] $Header: /cvsroot/pgf/pgf/generic/pgf/systemlayer/pgfsys.code.tex,v 1.48 2014/07/09 14:01:22 cfeuersaenger Exp $ % Load key mechanism @@ -683,6 +683,19 @@ % #1 = width % #2 = height +\def\pgfsys@prepare@papersize#1#2{\pgfsys@papersize{#1}{#2}} +% Like \pgfsys@papersize, this prepares the paper size in a portable +% way -- but it is supposed to be a preparation step before the +% document has started. Drivers may decide to postpone the action +% until the document has started. +% +% The root cause why I added this method is that image externalization +% seems to suffer from the fact that some drivers need a "prepared" +% routine whereas others must not have a prepared routine and have to +% apply the action right-away. This method is the solution for image +% externalization. +% #1 = width +% #2 = height \ifx\paperheight\@undefined \def\pgfsys@thepageheight{\the\vsize} % this is wrong, but I do not diff --git a/Master/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex b/Master/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex index 4f9d167e7bb..545466ab78c 100644 --- a/Master/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex @@ -15,8 +15,18 @@ % prints out a message to the log. -\def\pgfversion{3.0.0} -\def\pgftypesetversion{\oldstylenums{3}.\oldstylenums{0}.\oldstylenums{0}} +%\def\pgfversion{3.0.1-cvs} +\def\pgfversion{3.0.1} + +\begingroup +\catcode`\"=12 +\pgfutil@IfUndefined{directlua}{}{% + \directlua{pgf = {}; pgf.pgfversion = "\pgfversion"}% +}% +\endgroup + +%\def\pgftypesetversion{\oldstylenums{3}.\oldstylenums{0}.\oldstylenums{1}-cvs} +\def\pgftypesetversion{\oldstylenums{3}.\oldstylenums{0}.\oldstylenums{1}} \ifx\pgfrcsloaded\undefined @@ -87,7 +97,7 @@ \def\ProvidesFile#1[#2]{\wlog{Loading file #1 version #2.}} \fi -\ProvidesPackageRCS[v\pgfversion] $Header: /cvsroot/pgf/pgf/generic/pgf/utilities/pgfrcs.code.tex,v 1.28 2013/12/20 14:44:47 tantau Exp $ +\ProvidesPackageRCS[v\pgfversion] $Header: /cvsroot/pgf/pgf/generic/pgf/utilities/pgfrcs.code.tex,v 1.31 2015/08/07 10:17:34 cfeuersaenger Exp $ \catcode`\@=\pgfrcsatcode diff --git a/Master/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.tex b/Master/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.tex index cdf0cfe821d..782d0d44748 100644 --- a/Master/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.tex +++ b/Master/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.tex @@ -511,6 +511,10 @@ % curtesy for latex: \let\pgfutil@protect\relax +% Used by latex for doing reruns +% #1 = an internal label +% #2 = a to-be-tested text +\def\pgfutil@check@rerun#1#2{} % new tempdims: \newdimen\pgfutil@tempdima diff --git a/Master/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def b/Master/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def index c990a3730a4..6c740514bba 100644 --- a/Master/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def +++ b/Master/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def @@ -78,13 +78,14 @@ \let\pgfmath@tempcnta\pgfutil@tempcnta \let\pgfmath@tempcntb\pgfutil@tempcntb +\def\pgfutil@check@rerun#1#2{\@newl@bel{pgf@lab}{#1}{#2}} \AtBeginDocument{\AtEndDocument{\par\vfil\penalty-10000\relax\the\pgfutil@everybye}} \def\pgfutil@insertatbegincurrentpagefrombox#1{% \edef\pgf@temp{\the\wd\pgfutil@abb}% \global\setbox\pgfutil@abb\hbox{% - \unhbox\pgfutil@abb + \unhbox\pgfutil@abb% % % the order in which \pgfutil@insertatbegincurrentpagefrombox % matters unless we make the following -shift! @@ -94,7 +95,7 @@ % % CF observed problems when placing patterns in XObjects without % this skip (dvipdfmx driver for pgfplots shader=interp) - \hskip-\pgf@temp\relax + \hskip-\pgf@temp\relax% #1% }% } @@ -112,11 +113,32 @@ \EveryShipout{% % Add at begin page stuff \setbox\@cclv=\vbox{% - \setbox\z@=\hbox{\pgfutil@abe\unhbox\pgfutil@abb\pgfutil@abc\global\let\pgfutil@abc\pgfutil@empty}% + \setbox\z@=\hbox{% + % the boxes \pgfutil@abe ("every page") and \pgfutil@abb ("current page") + % are used to generate pdf objects / dictionaries which are + % required for the graphics which are somewhere in the "real" + % page content. + % BUT: these pdf objects MUST NOT be affected by text layout + % shifts! Consequently, we have to undo \hoffset and \voffset + % (which are h/v shifts to the page layout). + % + % Note that this of importance for shadings. To be more + % specific: try out shadings with standalone (which uses + % \hoffset) and with xdvipdfmx (which appears to be more + % fragile than pdflatex) - they break unless we undo \hoffset + % and \voffset. + \ifdim\hoffset=0pt \else \hskip-\hoffset\fi + \pgfutil@abe\unhbox\pgfutil@abb\pgfutil@abc\global\let\pgfutil@abc\pgfutil@empty + \ifdim\hoffset=0pt \else \hskip+\hoffset\fi + }% \wd\z@=\z@% \ht\z@=\z@% \dp\z@=\z@% + % ... see remark above regarding \hoffset/\voffset: + \ifdim\voffset=0pt \else \vskip-\voffset\fi \box\z@% + \ifdim\voffset=0pt \else \vskip+\voffset\fi + % % if TeX changes into vertical mode, it inserts \parskip and % \lineskip. Disable it here: \nointerlineskip% @@ -132,18 +154,18 @@ % Preview hack: preview.sty hacks into \shipout (which is ok), but % does not honour everyshi.sty (which is not ok). This causes everyshi % material to get lost. - \AtBeginDocument{ - \@ifpackageloaded{preview}{% - % Ok, package loaded. Swap definitions of everyshi.sty's shipout - % and preview.sty's shipout: - \let\pgf@temp\pr@shipout% This is the original shipout - \let\pr@shipout\@EveryShipout@Shipout% This is what preview.sty should call - \let\@EveryShipout@Org@Shipout\pgf@temp% Everyshi should now use the original one - }{}% + \@ifpackageloaded{preview}{% + % Ok, package loaded. Swap definitions of everyshi.sty's shipout + % and preview.sty's shipout: + \ifPreview + \let\shipout\@EveryShipout@Org@Shipout%This is the null version of \shipout, created by preview and saved by everyshi + \let\@EveryShipout@Org@Shipout\pr@shipout% This is the original shipout + \let\pr@shipout\@EveryShipout@Shipout% + \fi + }{}% } - - + % Guess the driver: \def\pgfutil@guessdriver{ diff --git a/Master/texmf-dist/tex/generic/pgf/utilities/pgfutil-plain.def b/Master/texmf-dist/tex/generic/pgf/utilities/pgfutil-plain.def index 31d0d21d10c..b05887f84cf 100644 --- a/Master/texmf-dist/tex/generic/pgf/utilities/pgfutil-plain.def +++ b/Master/texmf-dist/tex/generic/pgf/utilities/pgfutil-plain.def @@ -241,7 +241,21 @@ % Hack shipout. Now use atbegshi \def\pgfutil@insertatbegincurrentpagefrombox#1{% - \global\setbox\pgfutil@abb\hbox{\unhbox\pgfutil@abb#1}% + \edef\pgf@temp{\the\wd\pgfutil@abb}% + \global\setbox\pgfutil@abb\hbox{% + \unhbox\pgfutil@abb + % + % the order in which \pgfutil@insertatbegincurrentpagefrombox + % matters unless we make the following -shift! + % To see this, consider writing two such statements. The second + % one will (naturally) be placed more to the right, although there + % is no apparent reason why it should. + % + % CF observed problems when placing patterns in XObjects without + % this skip (dvipdfmx driver for pgfplots shader=interp) + \hskip-\pgf@temp\relax + #1% + }% } \newbox\pgfutil@abb% \def\pgfutil@insertatbegincurrentpage#1{% @@ -259,16 +273,34 @@ \setbox\AtBeginShipoutBox=\vbox{% \setbox0=\hbox{% \begingroup + % the boxes \pgfutil@abe ("every page") and \pgfutil@abb ("current page") + % are used to generate pdf objects / dictionaries which are + % required for the graphics which are somewhere in the "real" + % page content. + % BUT: these pdf objects MUST NOT be affected by text layout + % shifts! Consequently, we have to undo \hoffset and \voffset + % (which are h/v shifts to the page layout). + % + % Note that this of importance for shadings. To be more + % specific: try out shadings with standalone (which uses + % \hoffset) and with xdvipdfmx (which appears to be more + % fragile than pdflatex) - they break unless we undo \hoffset + % and \voffset. + \ifdim\hoffset=0pt \else \hskip-\hoffset\fi \pgfutil@abe \unhbox\pgfutil@abb \pgfutil@abc \global\let\pgfutil@abc\pgfutil@empty + \ifdim\hoffset=0pt \else \hskip+\hoffset\fi \endgroup }% \wd0=0pt\relax \ht0=0pt\relax \dp0=0pt\relax + % ... see remark above regarding \hoffset/\voffset: + \ifdim\voffset=0pt \else \vskip-\voffset\fi \box0 % + \ifdim\voffset=0pt \else \vskip+\voffset\fi \nointerlineskip \box\AtBeginShipoutBox }% |