You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
542 lines
13 KiB
542 lines
13 KiB
% Copyright 2007 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.
|
|
|
|
% This file loads all the parsing, functions and operator stuff
|
|
%
|
|
% Version 1.414213 29/9/2007
|
|
|
|
\input pgfmathutil.code.tex
|
|
\input pgfmathparser.code.tex
|
|
\input pgfmathfunctions.code.tex
|
|
%\input pgfmathbase.code.tex
|
|
|
|
% \pgfmathsetlength, \pgfmathaddtolength
|
|
%
|
|
% #1 = dimension register
|
|
% #2 = expression
|
|
%
|
|
% Description:
|
|
%
|
|
% These functions work similar to \setlength and \addtolength. Only,
|
|
% they allow #2 to contain an expression, which is evaluated before
|
|
% assignment. Furthermore, the font is setup before the assignment is
|
|
% done, so that dimensions like 1em are evaluated correctly.
|
|
%
|
|
% If #2 starts with "+", then a simple assignment is done (but the
|
|
% font is still setup). This is orders of magnitude faster than a
|
|
% parsed assignment.
|
|
|
|
\def\pgfmathsetlength#1#2{%
|
|
\expandafter\pgfmath@onquick#2\pgfmath@%
|
|
{%
|
|
% Ok, quick version:
|
|
\begingroup%
|
|
\pgfmath@selectfont%
|
|
#1#2\unskip%
|
|
\expandafter\endgroup%
|
|
\expandafter#1\the#1\relax%
|
|
}%
|
|
{%
|
|
\pgfmathparse{#2}%
|
|
\ifpgfmathmathunitsdeclared%
|
|
#1\pgfmathresult mu\relax%
|
|
\else%
|
|
#1\pgfmathresult pt\relax%
|
|
\fi%
|
|
}%
|
|
\ignorespaces%
|
|
}
|
|
|
|
% \pgfmathaddtolength
|
|
%
|
|
% Add to #1 the result of evaluating #2.
|
|
%
|
|
% #1 - a dimension register
|
|
% #2 - an expression
|
|
%
|
|
\def\pgfmathaddtolength#1#2{%
|
|
\expandafter\pgfmath@onquick#2\pgfmath@%
|
|
{%
|
|
\begingroup%
|
|
\pgfmath@selectfont%
|
|
\advance#1#2\unskip%
|
|
\expandafter%
|
|
\endgroup%
|
|
\expandafter#1\the#1\relax%
|
|
}%
|
|
{%
|
|
\pgfmathparse{#2}%
|
|
\ifpgfmathmathunitsdeclared%
|
|
\advance#1\pgfmathresult mu\relax%
|
|
\else%
|
|
\advance#1\pgfmathresult pt\relax%
|
|
\fi%
|
|
}%
|
|
\ignorespaces%
|
|
}
|
|
|
|
% \pgfmathsetcount
|
|
%
|
|
% Assign #1 the truncated evaluation of #2.
|
|
%
|
|
% #1 - a count register
|
|
% #2 - an expression
|
|
%
|
|
\def\pgfmathsetcount#1#2{%
|
|
\expandafter\pgfmath@onquick#2\pgfmath@%
|
|
{%
|
|
\afterassignment\pgfmath@gobbletilpgfmath@%
|
|
#1#2\relax\pgfmath@%
|
|
}%
|
|
{%
|
|
\pgfmathparse{#2}%
|
|
\afterassignment\pgfmath@gobbletilpgfmath@%
|
|
#1\pgfmathresult\relax\pgfmath@%
|
|
}%
|
|
\ignorespaces%
|
|
}
|
|
|
|
% \pgfmathaddtocount
|
|
%
|
|
% Add to #1 the truncated evaluation of #2.
|
|
%
|
|
% #1 - a count register
|
|
% #2 - an expression
|
|
%
|
|
\def\pgfmathaddtocount#1#2{%
|
|
\expandafter\pgfmath@onquick#2\pgfmath@%
|
|
{%
|
|
\edef\pgfmath@addtocounttemp{\the#1}%
|
|
\afterassignment\pgfmath@gobbletilpgfmath@%
|
|
#1#2\relax\pgfmath@%
|
|
\advance#1\pgfmath@addtocounttemp\relax%
|
|
}%
|
|
{%
|
|
\edef\pgfmath@addtocounttemp{\the#1}%
|
|
\pgfmathparse{#2}%
|
|
\afterassignment\pgfmath@gobbletilpgfmath@%
|
|
#1\pgfmathresult\relax\pgfmath@%
|
|
\advance#1\pgfmath@addtocounttemp\relax%
|
|
}%
|
|
\ignorespaces%
|
|
}
|
|
|
|
% \pgfmathnewcounter
|
|
%
|
|
% LaTeX style counter which also works in plain TeX. Defines
|
|
% \c@<name> as a count register and also defines \the<name>.
|
|
%
|
|
% #1 the name of the counter.
|
|
%
|
|
% Example:
|
|
%
|
|
% \pgfmathnewcounter{counter}
|
|
% \pgfmathsetcounter{counter}{12}
|
|
% \thecounter (same as \the\c@counter)
|
|
%
|
|
\def\pgfmathnewcounter#1{%
|
|
\expandafter\ifx\csname c@#1\endcsname\relax%
|
|
\def\pgfmath@marshal{\csname newcount\endcsname}% Ha! Who cares about \outer?
|
|
\expandafter\pgfmath@marshal\csname c@#1\endcsname%
|
|
\expandafter\def\csname the#1\endcsname{\expandafter\the\csname c@#1\endcsname}%
|
|
\fi%
|
|
}
|
|
|
|
% \pgfmathsetcounter
|
|
%
|
|
% Set the counter #1 to the evaluation of #2.
|
|
%
|
|
% #1 - a counter name
|
|
% #2 - an expression
|
|
%
|
|
\def\pgfmathsetcounter#1#2{%
|
|
\expandafter\pgfmathsetcount\csname c@#1\endcsname{#2}%
|
|
}
|
|
|
|
% \pgfmathaddtocounter
|
|
%
|
|
% Add the counter #1 to the evaluation of #2.
|
|
%
|
|
% #1 - a counter name
|
|
% #2 - an expression
|
|
%
|
|
\def\pgfmathaddtocounter#1#2{%
|
|
\expandafter\pgfmathaddtocount\csname c@#1\endcsname{#2}%
|
|
}
|
|
|
|
% \pgfmathmakecounterglobal
|
|
%
|
|
% Make the current value of a counter globally defined.
|
|
%
|
|
% #1 - a (valid) counter name.
|
|
%
|
|
\def\pgfmath@pgftext{pgf}
|
|
\def\pgfmath@tikztext{tikz}
|
|
\def\pgfmathmakecounterglobal#1{%
|
|
\pgfmath@ifundefined{c@#1}{}{%
|
|
\expandafter\pgfmath@in@\expandafter{\pgfmath@pgftext}{#1}%
|
|
\ifpgfmath@in@%
|
|
\else%
|
|
\expandafter\pgfmath@in@\expandafter{\pgfmath@tikztext}{#1}%
|
|
\ifpgfmath@in@%
|
|
\else%
|
|
\expandafter\global\csname c@#1\endcsname\csname c@#1\endcsname\relax%
|
|
\fi%
|
|
\fi%
|
|
}%
|
|
}
|
|
|
|
% \pgfmathsetmacro
|
|
%
|
|
% \edef#1 as the result of evaluating #2.
|
|
%
|
|
% #1 - a macro
|
|
% #2 - an expression
|
|
%
|
|
\def\pgfmathsetmacro#1#2{%
|
|
\begingroup%
|
|
\pgfmathparse{#2}%
|
|
\let#1=\pgfmathresult
|
|
\pgfmath@smuggleone{#1}%
|
|
\endgroup%
|
|
}
|
|
|
|
% \pgfmathsetlengthmacro
|
|
%
|
|
% \edef#1 as the result of evaluating #2 with pt.
|
|
%
|
|
% #1 - a macro
|
|
% #2 - an expression
|
|
%
|
|
\def\pgfmathsetlengthmacro#1#2{%
|
|
\begingroup%
|
|
\pgfmathsetlength\pgfmath@x{#2}%
|
|
\edef#1{\the\pgfmath@x}%
|
|
\pgfmath@smuggleone{#1}%
|
|
\endgroup%
|
|
}
|
|
|
|
% \pgfmathtruncatemacro
|
|
%
|
|
% \edef#1 as the truncated result of evaluating #2.
|
|
%
|
|
% #1 - a macro
|
|
% #2 - an expression
|
|
%
|
|
\def\pgfmathtruncatemacro#1#2{%
|
|
\begingroup%
|
|
\pgfmathsetcount\c@pgfmath@counta{#2}%
|
|
\edef#1{\the\c@pgfmath@counta}%
|
|
\pgfmath@smuggleone{#1}%
|
|
\endgroup%
|
|
}
|
|
|
|
% Check whether a given parameter starts with quick.
|
|
%
|
|
% The command should be followed by nonempty text, ending with
|
|
% \pgfmath@ as a stop-token. Then should follow
|
|
%
|
|
% #1 - code to execute if text starts with +
|
|
% #2 - code to execute if text does not
|
|
%
|
|
% Example:
|
|
%
|
|
% \pgfmath@onquick+0pt\pgfmath@{is quick}{is slow}
|
|
|
|
\def\pgfmath@onquick{%
|
|
\futurelet\pgfmath@next%
|
|
\pgfmath@@onquick}
|
|
\def\pgfmath@@onquick#1\pgfmath@{%
|
|
\ifx\pgfmath@next+%
|
|
\let\pgfmath@next=\pgfmath@firstoftwo%
|
|
\else%
|
|
\let\pgfmath@next=\pgfmath@secondoftwo%
|
|
\fi%
|
|
\pgfmath@next%
|
|
}
|
|
|
|
% *** The following commands DO NOT WORK without the rest of PGF ***
|
|
%
|
|
% (a dumping ground for stuff that doesn't really belong anywhere else)
|
|
|
|
% \pgfmathanglebetweenpoints
|
|
%
|
|
% Define \pgfmathresult as the angle between points #1 and #2
|
|
% Should get the quadrants right as well.
|
|
%
|
|
\def\pgfmathanglebetweenpoints#1#2{%
|
|
\begingroup%
|
|
\pgf@process{\pgfpointdiff{#1}{#2}}%
|
|
\edef\pgf@marshall{\expandafter\noexpand\csname pgfmathatan2@\endcsname{\expandafter\Pgf@geT\the\pgf@y}{\expandafter\Pgf@geT\the\pgf@x}}%
|
|
\pgf@marshall%
|
|
\ifdim\pgfmathresult pt<0pt%
|
|
\pgfmathparse{\pgfmathresult+360}%
|
|
\fi%
|
|
\expandafter%
|
|
\endgroup\expandafter\def\expandafter\pgfmathresult\expandafter{\pgfmathresult}%
|
|
}
|
|
|
|
%
|
|
% \pgfmathrotatepointaround
|
|
%
|
|
% Rotate point #1 about point #2 by #3 degrees.
|
|
%
|
|
\def\pgfmathrotatepointaround#1#2#3{%
|
|
\pgf@process{%
|
|
\pgf@process{#1}%
|
|
\pgf@xc=\pgf@x%
|
|
\pgf@yc=\pgf@y%
|
|
\pgf@process{#2}%
|
|
\pgf@xa\pgf@x%
|
|
\pgf@ya\pgf@y%
|
|
\pgf@xb\pgf@x%
|
|
\pgf@yb\pgf@y%
|
|
\pgf@x=\pgf@xc%
|
|
\pgf@y=\pgf@yc%
|
|
\advance\pgf@x-\pgf@xa%
|
|
\advance\pgf@y-\pgf@ya%
|
|
\pgfmathsetmacro\angle{#3}%
|
|
\pgfmathsin@{\angle}%
|
|
\let\sineangle\pgfmathresult%
|
|
\pgfmathcos@{\angle}%
|
|
\let\cosineangle\pgfmathresult%
|
|
\pgf@xa\cosineangle\pgf@x%
|
|
\advance\pgf@xa-\sineangle\pgf@y%
|
|
\pgf@ya\sineangle\pgf@x%
|
|
\advance\pgf@ya\cosineangle\pgf@y%
|
|
\pgf@x\pgf@xb%
|
|
\pgf@y\pgf@yb%
|
|
\advance\pgf@x\pgf@xa%
|
|
\advance\pgf@y\pgf@ya%
|
|
}%
|
|
}
|
|
|
|
% \pgfmathanglebetweenlines
|
|
%
|
|
% Calculate the clockwise angle between a line from point #1
|
|
% to point #2 and a line from #3 to point #4.
|
|
%
|
|
\def\pgfmathanglebetweenlines#1#2#3#4{%
|
|
\begingroup%
|
|
\pgfmathanglebetweenpoints{#1}{#2}%
|
|
\let\firstangle\pgfmathresult%
|
|
\pgfmathanglebetweenpoints{#3}{#4}%
|
|
\let\secondangle\pgfmathresult%
|
|
\ifdim\firstangle pt>\secondangle pt\relax%
|
|
\pgfmathadd@{\secondangle}{360}%
|
|
\let\secondangle\pgfmathresult%
|
|
\fi%
|
|
\pgfmathsubtract@{\secondangle}{\firstangle}%
|
|
\pgfmath@smuggleone\pgfmathresult%
|
|
\endgroup%
|
|
}
|
|
|
|
% \pgfmathpointreflectalongaxis
|
|
%
|
|
% Reflects point #2 around an axis centered on #2 at an angle #3.
|
|
%
|
|
\def\pgfmathreflectpointalongaxis#1#2#3{%
|
|
\pgf@process{%
|
|
\pgfmathanglebetweenpoints{#2}{#1}%
|
|
\pgfmath@tempdima\pgfmathresult pt\relax%
|
|
\pgfmathparse{#3}%
|
|
\advance\pgfmath@tempdima-\pgfmathresult pt\relax%
|
|
\pgfmath@tempdima-2.0\pgfmath@tempdima%
|
|
\pgfmathrotatepointaround{#1}{#2}{\pgfmath@tonumber{\pgfmath@tempdima}}%
|
|
}%
|
|
}
|
|
|
|
|
|
|
|
% \pgfmathpointintersectionoflineandarc
|
|
%
|
|
% A bit experimental at the moment:
|
|
%
|
|
% Locates the point where a line crosses an eliptical arc. If the line
|
|
% does not cross the arc, a meaningless point will result.
|
|
%
|
|
% #1 the point of the line on the "convex" side of the arc.
|
|
% #2 the point of the line on the "concave" side of the arc.
|
|
% #3 the center of the eliptical arc.
|
|
% #4 start angle of the arc.
|
|
% #5 end angle of the arc.
|
|
% #6 radii of the arc.
|
|
%
|
|
\def\pgfmathpointintersectionoflineandarc#1#2#3#4#5#6{%
|
|
\pgf@process{%
|
|
%
|
|
% Get the required angle.
|
|
%
|
|
\pgfmathanglebetweenpoints{#2}{#1}%
|
|
\let\x\pgfmathresult%
|
|
%
|
|
% Get the radii of the arc.
|
|
%
|
|
\pgfmath@in@{and }{#6}%
|
|
\ifpgfmath@in@%
|
|
\pgf@polar@#6\@@%
|
|
\else%
|
|
\pgf@polar@#6 and #6\@@%
|
|
\fi%
|
|
\edef\xarcradius{\the\pgf@x}%
|
|
\edef\yarcradius{\the\pgf@y}%
|
|
%
|
|
% Get the start and end angles of the arc...
|
|
%
|
|
\pgfmathsetmacro\s{#4}%
|
|
\pgfmathsetmacro\e{#5}%
|
|
%
|
|
% ...and also with rounding.
|
|
%
|
|
\pgfmathmod@{\s}{360}%
|
|
\ifdim\pgfmathresult pt<0pt\relax%
|
|
\pgfmathadd@{\pgfmathresult}{360}%
|
|
\fi%
|
|
\let\ss\pgfmathresult%
|
|
\pgfmathmod@{\e}{360}%
|
|
\ifdim\pgfmathresult pt<0pt\relax%
|
|
\pgfmathadd@{\pgfmathresult}{360}%
|
|
\fi%
|
|
\let\ee\pgfmathresult%
|
|
%
|
|
% Hackery for when arc straddles zero.
|
|
%
|
|
\ifdim\ee pt<\ss pt\relax%
|
|
\pgfmathadd@{\x}{180}%
|
|
\pgfmathmod@{\pgfmathresult}{360}%
|
|
\let\x\pgfmathresult%
|
|
\fi%
|
|
\def\m{360}% Measure of nearness.
|
|
\pgfmathadd@{\s}{\e}%
|
|
\pgfmathdivide@{\pgfmathresult}{2}%
|
|
\let\n\pgfmathresult% The best estimate (default to middle of arc).
|
|
\pgfmathloop%
|
|
\pgfmathadd@{\s}{\e}%
|
|
\pgfmathdivide@{\pgfmathresult}{2}%
|
|
\let\p\pgfmathresult%
|
|
\ifdim\p pt=\s pt\relax%
|
|
\else%
|
|
\pgfmathanglebetweenpoints{#2}{%
|
|
\pgfpointadd{#3}{%
|
|
\pgf@x\xarcradius\relax%
|
|
\pgfmathcos@{\p}%
|
|
\pgf@x\pgfmathresult\pgf@x%
|
|
\pgf@y\yarcradius\relax%
|
|
\pgfmathsin@{\p}%
|
|
\pgf@y\pgfmathresult\pgf@y%
|
|
}%
|
|
}%
|
|
%
|
|
% Hackery for when arc straddles zero.
|
|
%
|
|
\ifdim\ee pt<\ss pt\relax%
|
|
\pgfmathadd@{\pgfmathresult}{180}%
|
|
\pgfmathmod@{\pgfmathresult}{360}%
|
|
\fi%
|
|
\let\q\pgfmathresult%
|
|
%
|
|
% More hackery...
|
|
%
|
|
\ifdim\x pt>335pt\relax%
|
|
\ifdim\q pt<45pt\relax%
|
|
\pgfmathadd@{\q}{360}%
|
|
\let\q\pgfmathresult%
|
|
\fi%
|
|
\fi%
|
|
\ifdim\x pt=\q pt% Found it!
|
|
\pgfmathbreakloop% Breaks after current iteration is complete.
|
|
\else
|
|
\ifdim\x pt<\q pt\relax%
|
|
\let\e\p%
|
|
\else%
|
|
\let\s\p%
|
|
\fi%
|
|
\fi%
|
|
\pgfmathsubtract@{\x}{\q}%
|
|
\pgfmathabs@{\pgfmathresult}%
|
|
%
|
|
% Save the estimate if it is better than any previous estimate.
|
|
%
|
|
\ifdim\pgfmathresult pt<\m pt\relax%
|
|
\let\m\pgfmathresult%
|
|
\let\n\p%
|
|
\fi%
|
|
\repeatpgfmathloop%
|
|
\pgfpointadd{#3}{\pgfpointpolar{\n}{\xarcradius and \yarcradius}}%
|
|
}%
|
|
}
|
|
|
|
% \pgfmathangleonellipse
|
|
%
|
|
% Find the angle corresponding to a point on the border of an ellispe.
|
|
%
|
|
% #1 - the point on the border.
|
|
% #2 - the radii of the ellipse.
|
|
%
|
|
\def\pgfmathangleonellipse#1#2{%
|
|
\begingroup%
|
|
\pgfmath@in@{and }{#2}%
|
|
\ifpgfmath@in@%
|
|
\pgf@polar@#2\@@%
|
|
\else%
|
|
\pgf@polar@#2 and #2\@@%
|
|
\fi%
|
|
\pgf@xa\pgf@x%
|
|
\pgf@ya\pgf@y%
|
|
\pgf@process{#1}%
|
|
\ifdim\pgf@x=0pt\relax%
|
|
\pgfutil@tempdima1pt\relax%
|
|
\else%
|
|
\pgfutil@tempdima\pgf@x%
|
|
\pgfmathdivide@{\pgfmath@tonumber{\pgf@xa}}{\pgfmath@tonumber{\pgfutil@tempdima}}%
|
|
\pgfutil@tempdima\pgfmathresult pt\relax%
|
|
\fi%
|
|
\ifdim\pgf@y=0pt\relax%
|
|
\pgfutil@tempdima1pt\relax%
|
|
\else%
|
|
\pgfmathdivide@{\pgfmath@tonumber{\pgf@y}}{\pgfmath@tonumber{\pgf@ya}}%
|
|
\pgfutil@tempdima\pgfmathresult\pgfutil@tempdima%
|
|
\pgfmathatan@{\pgfmath@tonumber{\pgfutil@tempdima}}%
|
|
\fi%
|
|
%
|
|
\pgfutil@tempdima\pgfmathresult pt\relax%
|
|
\ifdim\pgfutil@tempdima<0pt\relax%
|
|
\advance\pgfutil@tempdima360pt\relax%
|
|
\fi%
|
|
\ifdim\pgf@x<0pt\relax%
|
|
\ifdim\pgf@y=0pt\relax%
|
|
\pgfutil@tempdima180pt\relax%
|
|
\else%
|
|
\ifdim\pgf@y<0pt\relax%
|
|
\advance\pgfutil@tempdima180pt\relax%
|
|
\else%
|
|
\advance\pgfutil@tempdima-180pt\relax%
|
|
\fi%
|
|
\fi%
|
|
\else%
|
|
\ifdim\pgf@x=0pt\relax%
|
|
\ifdim\pgf@y<0pt\relax%
|
|
\pgfutil@tempdima270pt\relax%
|
|
\else%
|
|
\pgfutil@tempdima90pt\relax%
|
|
\fi%
|
|
\else%
|
|
\ifdim\pgf@y=0pt\relax%
|
|
\pgfutil@tempdima0pt\relax%
|
|
\fi%
|
|
\fi%
|
|
\fi%
|
|
\pgfmath@returnone\pgfutil@tempdima%
|
|
\endgroup%
|
|
}
|
|
|
|
|
|
% Local Variables:
|
|
% tab-width: 2
|
|
% End:
|
|
|