summaryrefslogtreecommitdiff
path: root/graphics/pgf/contrib/tikz-nfold/pgflibrarybezieroffset.code.tex
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/pgf/contrib/tikz-nfold/pgflibrarybezieroffset.code.tex')
-rw-r--r--graphics/pgf/contrib/tikz-nfold/pgflibrarybezieroffset.code.tex416
1 files changed, 235 insertions, 181 deletions
diff --git a/graphics/pgf/contrib/tikz-nfold/pgflibrarybezieroffset.code.tex b/graphics/pgf/contrib/tikz-nfold/pgflibrarybezieroffset.code.tex
index e3391ed92c..7d9a86312f 100644
--- a/graphics/pgf/contrib/tikz-nfold/pgflibrarybezieroffset.code.tex
+++ b/graphics/pgf/contrib/tikz-nfold/pgflibrarybezieroffset.code.tex
@@ -16,12 +16,6 @@
% This work consists of the files pgflibrarybezieroffset.code.tex,
% tikzlibrarynfold.code.tex, tikz-nfold-doc.tex, and tikz-nfold-doc.pdf.
-
-% stores the current \pgf@x and \pgf@y in #1
-\def\pgfstorepoint#1{\edef#1{\noexpand\pgfpoint{\the\pgf@x}{\the\pgf@y}}}
-% global version in case we need it:
-\def\pgfglobalstorepoint#1{\xdef#1{\noexpand\pgfpoint{\the\pgf@x}{\the\pgf@y}}}
-
% Split a Bezier curve (de Casteljau's algorithm)
% #1 = time (between 0 and 1)
% #2-#5: control points
@@ -32,19 +26,16 @@
% this is partially implemented in some pgf file, possibly decorations or basic paths.
% But maybe I will need the general case in the future, maybe with some advanced fully simple detection.
% Leave it in for now
-\newcommand{\pgf@splitbezier}[5]{
+\def\pgf@splitbezier#1#2#3#4#5{%
% based on pgfcorepoints.code.tex, \pgfpointcurveattime
- \pgfmathparse{#1}%
- \let\pgf@time@s=\pgfmathresult%
- \global\pgf@x=\pgfmathresult pt%
- \global\pgf@x=-\pgf@x%
+ \pgfmathsetmacro\pgf@time@s{#1}%
+ \pgf@x=-\pgf@time@s pt%
\advance\pgf@x by 1pt%
\edef\pgf@time@t{\pgf@sys@tonumber{\pgf@x}}%
% P^0_3
- \pgf@process{#5}%
+ \pgfextract@process\pgf@splitbezier@ii@iv{#5}%
\pgf@xc=\pgf@x%
\pgf@yc=\pgf@y%
- \pgfstorepoint{\pgf@splitbezier@ii@iv}
% P^0_2
\pgf@process{#4}%
\pgf@xb=\pgf@x%
@@ -54,90 +45,123 @@
\pgf@xa=\pgf@x%
\pgf@ya=\pgf@y%
% P^0_0
- \pgf@process{#2}%
- \pgfstorepoint{\pgf@splitbezier@i@i}
+ \pgfextract@process\pgf@splitbezier@i@i{#2}%
% First iteration:
% P^1_0
- \global\pgf@x=\pgf@time@t\pgf@x\global\advance\pgf@x by\pgf@time@s\pgf@xa%
- \global\pgf@y=\pgf@time@t\pgf@y\global\advance\pgf@y by\pgf@time@s\pgf@ya%
- \pgfstorepoint{\pgf@splitbezier@i@ii}
+ \pgf@x=\pgf@time@t\pgf@x\advance\pgf@x by\pgf@time@s\pgf@xa%
+ \pgf@y=\pgf@time@t\pgf@y\advance\pgf@y by\pgf@time@s\pgf@ya%
+ \pgfextract@process\pgf@splitbezier@i@ii{}%
% P^1_1
\pgf@xa=\pgf@time@t\pgf@xa\advance\pgf@xa by\pgf@time@s\pgf@xb%
\pgf@ya=\pgf@time@t\pgf@ya\advance\pgf@ya by\pgf@time@s\pgf@yb%
% P^1_2
\pgf@xb=\pgf@time@t\pgf@xb\advance\pgf@xb by\pgf@time@s\pgf@xc%
\pgf@yb=\pgf@time@t\pgf@yb\advance\pgf@yb by\pgf@time@s\pgf@yc%
- \edef\pgf@splitbezier@ii@iii{\noexpand\pgfpoint{\the\pgf@xb}{\the\pgf@yb}}
+ \edef\pgf@splitbezier@ii@iii{\noexpand\pgfqpoint{\the\pgf@xb}{\the\pgf@yb}}%
% P^2_0
- \global\pgf@x=\pgf@time@t\pgf@x\global\advance\pgf@x by\pgf@time@s\pgf@xa%
- \global\pgf@y=\pgf@time@t\pgf@y\global\advance\pgf@y by\pgf@time@s\pgf@ya%
- \pgfstorepoint{\pgf@splitbezier@i@iii}
+ \pgf@x=\pgf@time@t\pgf@x\advance\pgf@x by\pgf@time@s\pgf@xa%
+ \pgf@y=\pgf@time@t\pgf@y\advance\pgf@y by\pgf@time@s\pgf@ya%
+ \pgfextract@process\pgf@splitbezier@i@iii{}%
% P^2_1
\pgf@xa=\pgf@time@t\pgf@xa\advance\pgf@xa by\pgf@time@s\pgf@xb%
\pgf@ya=\pgf@time@t\pgf@ya\advance\pgf@ya by\pgf@time@s\pgf@yb%
- \edef\pgf@splitbezier@ii@ii{\noexpand\pgfpoint{\the\pgf@xa}{\the\pgf@ya}}
+ \edef\pgf@splitbezier@ii@ii{\noexpand\pgfqpoint{\the\pgf@xa}{\the\pgf@ya}}%
% P^3_0
- \global\pgf@x=\pgf@time@t\pgf@x\global\advance\pgf@x by\pgf@time@s\pgf@xa%
- \global\pgf@y=\pgf@time@t\pgf@y\global\advance\pgf@y by\pgf@time@s\pgf@ya%
- \pgfstorepoint{\pgf@splitbezier@i@iv}
- \pgfstorepoint{\pgf@splitbezier@ii@i}
+ \pgf@x=\pgf@time@t\pgf@x\advance\pgf@x by\pgf@time@s\pgf@xa%
+ \pgf@y=\pgf@time@t\pgf@y\advance\pgf@y by\pgf@time@s\pgf@ya%
+ \pgfextract@process\pgf@splitbezier@i@iv{}%
+ \let\pgf@splitbezier@ii@i\pgf@splitbezier@i@iv
}
% computes the cross product and puts it into \pgfmathresult
-\newcommand{\pgfcrossproduct}[2]{
- \pgf@process{#1}%
- \pgf@xa=\pgf@x%
- \pgf@ya=\pgf@y%
- \pgf@process{#2}%
- \pgfmathparse{\pgf@xa*\pgf@y-\pgf@ya*\pgf@x}%
+\def\pgfmathcrossproduct#1#2{%
+ \begingroup
+ \pgf@process{#1}%
+ \pgf@xa=\pgf@x%
+ \pgf@ya=\pgf@y%
+ \pgf@process{#2}%
+ \pgf@y=\pgf@sys@tonumber\pgf@xa\pgf@y
+ \advance\pgf@y by -\pgf@sys@tonumber\pgf@ya\pgf@x
+ \pgfmath@returnone\pgf@y
+ \endgroup
}
-\newcommand{\pgfdotproduct}[2]{
- \pgf@process{#1}%
- \pgf@xa=\pgf@x%
- \pgf@ya=\pgf@y%
- \pgf@process{#2}%
- \pgfmathparse{\pgf@xa*\pgf@x+\pgf@ya*\pgf@y}%
+\def\pgfmathdotproduct#1#2{%
+ \begingroup
+ \pgf@process{#1}%
+ \pgf@xa=\pgf@x%
+ \pgf@ya=\pgf@y%
+ \pgf@process{#2}%
+ \pgf@x=\pgf@sys@tonumber\pgf@xa\pgf@x
+ \advance\pgf@x by \pgf@sys@tonumber\pgf@ya\pgf@y
+ \pgfmath@returnone\pgf@x
+ \endgroup
}
-\newcommand{\pgfcrossdot}[2]{
- \pgf@process{#1}%
- \pgf@xa=\pgf@x%
- \pgf@ya=\pgf@y%
- \pgf@process{#2}%
- \pgfmathsetlengthmacro{\pgf@tmp@dot}{\pgf@xa*\pgf@x+\pgf@ya*\pgf@y}%
- \pgfmathsetlengthmacro{\pgf@tmp@cross}{\pgf@xa*\pgf@y-\pgf@ya*\pgf@x}%
+\def\pgfmathcrossdot#1#2{%
+ \begingroup
+ \pgf@process{#1}%
+ \pgf@xa=\pgf@x%
+ \pgf@ya=\pgf@y%
+ \pgf@process{#2}%
+ \pgf@xb=\pgf@sys@tonumber\pgf@xa\pgf@x
+ \pgf@yb=\pgf@sys@tonumber\pgf@xa\pgf@y
+ \advance\pgf@xb by \pgf@sys@tonumber\pgf@ya\pgf@y
+ \advance\pgf@yb by -\pgf@sys@tonumber\pgf@ya\pgf@x
+ \edef\pgf@temp{%
+ \edef\noexpand\pgf@tmp@dot{\pgf@sys@tonumber\pgf@xb}%
+ \edef\noexpand\pgf@tmp@cross{\pgf@sys@tonumber\pgf@yb}%
+ }%
+ \expandafter
+ \endgroup\pgf@temp
}
-
+% Calculates abs(\pgf@x) + abs(\pgf@y) in #1
+\def\pgfpointtaxicabnorm#1{%
+ \ifdim\pgf@x<0pt
+ #1=-\pgf@x
+ \else
+ #1=\pgf@x
+ \fi
+ \ifdim\pgf@y<0pt
+ \advance#1 by -\pgf@y
+ \else
+ \advance#1 by \pgf@y
+ \fi
+}
% Computes the normalised tangents of a given Bezier curve and stores them in \pgf@tmp@tang@i and \pgf@tmp@tang@ii.
+% Also computes the angles and stores them in \pgf@tmp@angle@i and \pgf@tmp@angle@ii.
% All degenerate cases are covered. For a triple degenerate curve (all points equal), the vector (1,0) is returned.
-\newcommand{\pgf@offset@compute@tangents}[4]{
- \pgfpointdiff{#1}{#2} % unintuitively, this is PTii - PTi
- \pgfmathparse{abs(\pgf@x) + abs(\pgf@y)}
- \ifdim\pgfmathresult pt<0.1pt\relax
+\def\pgf@offset@compute@tangents#1#2#3#4{%
+ \pgf@process{\pgfpointdiff{#1}{#2}}% unintuitively, this is PTii - PTi
+ \pgfpointtaxicabnorm\pgf@xa
+ \ifdim\pgf@xa<0.1pt\relax
% edge case: first point and first control point are equal
- \pgfpointdiff{#1}{#3}
- \pgfmathparse{abs(\pgf@x) + abs(\pgf@y)}
- \ifdim\pgfmathresult pt<0.1pt\relax
+ \pgf@process{\pgfpointdiff{#1}{#3}}%
+ \pgfpointtaxicabnorm\pgf@xa
+ \ifdim\pgf@xa<0.1pt\relax
% edge case: first three points are equal
- \pgfpointdiff{#1}{#4}
+ \pgf@process{\pgfpointdiff{#1}{#4}}%
\fi
\fi
- \pgfpointnormalised{}
- \pgfstorepoint\pgf@tmp@tang@i
- \pgfpointdiff{#3}{#4}
- \pgfmathparse{abs(\pgf@x) + abs(\pgf@y)}
- \ifdim\pgfmathresult pt<0.1pt\relax
- \pgfpointdiff{#2}{#4}
- \pgfmathparse{abs(\pgf@x) + abs(\pgf@y)}
- \ifdim\pgfmathresult pt<0.1pt\relax
- \pgfpointdiff{#1}{#4}
+ \pgfextract@process\pgf@tmp@tang@i{%
+ \pgfpointnormalised{}%
+ % \pgfpointnormalised stores the angle of the vector in \pgf@tmp
+ \global\let\pgf@nfold@tmp\pgf@tmp%
+ }%
+ \let\pgf@tmp@angle@i\pgf@nfold@tmp%
+ \pgf@process{\pgfpointdiff{#3}{#4}}%
+ \pgfpointtaxicabnorm\pgf@xa
+ \ifdim\pgf@xa<0.1pt\relax
+ \pgf@process{\pgfpointdiff{#2}{#4}}%
+ \pgfpointtaxicabnorm\pgf@xa
+ \ifdim\pgf@xa<0.1pt\relax
+ \pgf@process{\pgfpointdiff{#1}{#4}}%
\fi
\fi
- \pgfpointnormalised{}
- \pgfstorepoint\pgf@tmp@tang@ii
+ \pgfextract@process\pgf@tmp@tang@ii{\pgfpointnormalised{}\global\let\pgf@nfold@tmp\pgf@tmp}%
+ \let\pgf@tmp@angle@ii\pgf@nfold@tmp%
}
@@ -145,73 +169,89 @@
% Offsetting a simple section %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\newcommand{\pgf@offset@bezier@segment}[5]{%
- % TODO would it make sense to use \pgf@process here?
+\def\pgf@offset@bezier@segment#1#2#3#4#5{%
% normalise tangents and normals; this avoids overflow issues later, and we need
% the normal vector to be of length 1 anyway
- \pgf@offset@compute@tangents{#1}{#2}{#3}{#4}
+ \pgf@offset@compute@tangents{#1}{#2}{#3}{#4}%
% offset A1
% compute the normal
\pgf@tmp@tang@i
- \pgf@xa=\pgf@x
- \pgf@x=-\pgf@y
- \pgf@y=\pgf@xa
- \pgfstorepoint\pgf@tmp@normal@i
- % Leaving this parameter empty amounts to working directly on the register
- \pgfpointadd{\pgfpointscale{#5}{}}{#1}
- \pgfstorepoint{\pgf@bezier@offset@i}
+ \edef\pgf@tmp@normal@i{\noexpand\pgfqpoint{-\the\pgf@y}{\the\pgf@x}}%
+ \pgfextract@process\pgf@bezier@offset@i
+ {\pgfpointadd{\pgfpointscale{#5}{\pgf@tmp@normal@i}}{#1}}%
% offset A4
\pgf@tmp@tang@ii
- \pgf@xa=\pgf@x
- \pgf@x=-\pgf@y
- \pgf@y=\pgf@xa
- \pgfstorepoint\pgf@tmp@normal@ii
- \pgfpointadd{\pgfpointscale{#5}{}}{#4}
- \pgfstorepoint\pgf@bezier@offset@iv
+ \edef\pgf@tmp@normal@ii{\noexpand\pgfqpoint{-\the\pgf@y}{\the\pgf@x}}%
+ \pgfextract@process\pgf@bezier@offset@iv
+ {\pgfpointadd{\pgfpointscale{#5}{\pgf@tmp@normal@ii}}{#4}}%
% now compute A'_2 and A'_3
- \pgfpointdiff{#1}{#4}
- \pgfmathsetmacro{\pgf@tmp@secantlen}{veclen(\pgf@x,\pgf@y)}
+ \pgf@process{\pgfpointdiff{#1}{#4}}%
+ \pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}%
+ \let\pgf@tmp@secantlen\pgfmathresult
\ifdim\pgf@tmp@secantlen pt<0.1pt\relax
% Edge case: Either the curve is degenerate to a point or it is not simple.
% Either way we offset A1 and A4, and preserve the vectors A1A2 and A3A4.
- \pgfwarning{pgf-offset: first and last point are too close, expect glitches}
- \pgfpointadd{\pgf@bezier@offset@i}{\pgfpointdiff{#1}{#2}}
- \pgfstorepoint\pgf@bezier@offset@ii
- \pgfpointadd{\pgf@bezier@offset@iv}{\pgfpointdiff{#4}{#3}}
- \pgfstorepoint\pgf@bezier@offset@iii
+ \pgfutil@packagewarning{tikz-nfold}{first and last point are too close, expect glitches}%
+ \pgfextract@process\pgf@bezier@offset@ii
+ {\pgfpointadd{\pgf@bezier@offset@i}{\pgfpointdiff{#1}{#2}}}%
+ \pgfextract@process\pgf@bezier@offset@iii
+ {\pgfpointadd{\pgf@bezier@offset@iv}{\pgfpointdiff{#4}{#3}}}%
\else
- \pgfpointnormalised{}
- \pgfstorepoint\pgf@tmp@secant
- \pgfcrossdot{}{\pgf@tmp@tang@ii}
- \ifdim\pgf@tmp@dot<.5pt\relax%
+ \pgfextract@process\pgf@tmp@secant{\pgfpointnormalised{}}%
+ \pgfmathcrossdot{}{\pgf@tmp@tang@ii}%
+ \ifdim\pgf@tmp@dot pt<.5pt\relax%
% this can only happen in non-simple curves
- \pgfwarning{pgf-offset: cosine of \pgf@tmp@dot\space clamped to 0.5 in non-simple segment}%
- \def\pgf@tmp@dot{.5pt}%
+ \pgfutil@packagewarning{tikz-nfold}{cosine of \pgf@tmp@dot\space clamped to 0.5 in non-simple segment}%
+ \def\pgf@tmp@dot{.5}%
\fi%
- \pgfmathsetmacro{\pgf@tmp@tanbeta}{\pgf@tmp@cross/\pgf@tmp@dot}%
- \pgfcrossdot{\pgf@tmp@secant}{\pgfpointnormalised{\pgfpointdiff{#1}{#2}}}
+ \pgfmathdivide@{\pgf@tmp@cross}{\pgf@tmp@dot}%
+ \let\pgf@tmp@tanbeta\pgfmathresult
+ \pgfmathcrossdot{\pgf@tmp@secant}{\pgfpointnormalised{\pgfpointdiff{#1}{#2}}}
% There are cases where we want #5/secantlen to be quite large, so we should not clamp the value here
- \pgfmathparse{1 + #5/\pgf@tmp@secantlen*(\pgf@tmp@cross - \pgf@tmp@dot*\pgf@tmp@tanbeta)}
- \pgfpointadd%
- {\pgf@bezier@offset@i}%
- {\pgfpointscale{\pgfmathresult pt}{\pgfpointdiff{#1}{#2}}}%
- \pgfstorepoint\pgf@bezier@offset@ii
+ % \pgfmathparse{1 + #5/\pgf@tmp@secantlen*(\pgf@tmp@cross - \pgf@tmp@dot*\pgf@tmp@tanbeta)}%
+ \pgfmath@offset@calculate@scale{\pgf@tmp@secantlen}{\pgf@tmp@cross}{\pgf@tmp@dot}{\pgf@tmp@tanbeta}{#5}%
+ \pgfextract@process\pgf@bezier@offset@ii{%
+ \pgfpointadd
+ {\pgf@bezier@offset@i}
+ {\pgfqpointscale{\pgfmathresult}{\pgfpointdiff{#1}{#2}}}%
+ }%
% third control point
- \pgfcrossdot{\pgf@tmp@secant}{\pgf@tmp@tang@i}
- \ifdim\pgf@tmp@dot<.5pt\relax%
- \pgfwarning{pgf-offset: cosine of \pgf@tmp@dot\space clamped to 0.5 in non-simple segment}%
- \def\pgf@tmp@dot{.5pt}%
- \fi%
- \pgfmathsetmacro{\pgf@tmp@tanbeta}{\pgf@tmp@cross/\pgf@tmp@dot}%
- \pgfcrossdot{\pgf@tmp@secant}{\pgfpointnormalised{\pgfpointdiff{#4}{#3}}}%
- \pgfmathparse{1 + #5/\pgf@tmp@secantlen*(\pgf@tmp@cross - \pgf@tmp@dot*\pgf@tmp@tanbeta)}%
- \pgfpointadd%
- {\pgf@bezier@offset@iv}%
- {\pgfpointscale{\pgfmathresult pt}{\pgfpointdiff{#4}{#3}}}%
- \pgfstorepoint\pgf@bezier@offset@iii%
+ \pgfmathcrossdot{\pgf@tmp@secant}{\pgf@tmp@tang@i}%
+ \ifdim\pgf@tmp@dot pt<.5pt\relax
+ \pgfutil@packagewarning{tikz-nfold}{cosine of \pgf@tmp@dot\space clamped to 0.5 in non-simple segment}%
+ \def\pgf@tmp@dot{.5}%
+ \fi
+ \pgfmathdivide@{\pgf@tmp@cross}{\pgf@tmp@dot}%
+ \let\pgf@tmp@tanbeta\pgfmathresult
+ \pgfmathcrossdot{\pgf@tmp@secant}{\pgfpointnormalised{\pgfpointdiff{#4}{#3}}}%
+ % \pgfmathparse{1 + #5/\pgf@tmp@secantlen*(\pgf@tmp@cross - \pgf@tmp@dot*\pgf@tmp@tanbeta)}%
+ \pgfmath@offset@calculate@scale{\pgf@tmp@secantlen}{\pgf@tmp@cross}{\pgf@tmp@dot}{\pgf@tmp@tanbeta}{#5}%
+ \pgfextract@process\pgf@bezier@offset@iii{%
+ \pgfpointadd
+ {\pgf@bezier@offset@iv}
+ {\pgfqpointscale{\pgfmathresult}{\pgfpointdiff{#4}{#3}}}%
+ }%
\fi
}
+% calculates 1+#5/#1*(#2-#3*#4)
+% #1 = secantlen
+% #2 = cross
+% #3 = dot
+% #4 = tanbeta
+% #5 = #5 (offset)
+\def\pgfmath@offset@calculate@scale#1#2#3#4#5{%
+ \begingroup
+ \pgfmathmultiply@{#3}{#4}%
+ \pgfmathsubtract@{#2}{\pgfmathresult}%
+ \let\pgfmath@temp\pgfmathresult
+ \pgfmathreciprocal@{#1}%
+ \pgfmathmultiply@{\pgfmathresult}{\pgfmath@temp}%
+ \pgfmathmultiply{\pgfmathresult}{#5}%
+ \pgfmathadd@{\pgfmathresult}{1}%
+ \pgfmath@smuggleone\pgfmathresult
+ \endgroup
+}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Subdividing and offsetting %
@@ -225,35 +265,42 @@
%
% Subdivides a Bezier curve into "simple" segments (according to the definition below),
% offsets the segments, and draws them. Because offsetting also involves relocating
-% the starting points, these macros come in two variants: with and without a \pgfmoveto{}
+% the starting points, these macros come in two variants: with and without a \pgfpathmoveto{}
% to the new starting point.
%
% Interface:
% #1-#4: control points of the whole Bezier curve
% #5: offset
-\newcommand{\pgfoffsetcurve}[5]{%
- \pgf@subdivideandoffsetcurve{#1}{#2}{#3}{#4}{#5}{\pgf@offset@max@recursion}{0}{\pgf@nfold@callback@move}%
+% \def\pgfoffsetcurve#1#2#3#4#5{%
+% \pgf@subdivideandoffsetcurve{#1}{#2}{#3}{#4}{#5}{\pgf@offset@max@recursion}{0}{\pgf@nfold@callback@move}%
+% }
+% \def\pgfoffsetcurvenomove#1#2#3#4#5{%
+% \pgf@subdivideandoffsetcurve{#1}{#2}{#3}{#4}{#5}{\pgf@offset@max@recursion}{0}{\pgf@nfold@callback@nomove}%
+% }
+
+\def\pgfoffsetcurve#1#2#3#4#5{%
+ \pgfoffsetcurvecallback{#1}{#2}{#3}{#4}{#5}{\pgf@nfold@callback@move}%
}
-\newcommand{\pgfoffsetcurvenomove}[5]{%
- \pgf@subdivideandoffsetcurve{#1}{#2}{#3}{#4}{#5}{\pgf@offset@max@recursion}{0}{\pgf@nfold@callback@nomove}%
+\def\pgfoffsetcurvenomove#1#2#3#4#5{%
+ \pgfoffsetcurvecallback{#1}{#2}{#3}{#4}{#5}{\pgf@nfold@callback@nomove}%
}
% Arguments:
% #1-#4: control points of the segment
% #5: =0 if this is the first segment of the curve, =1 otherwise
% (checking for #5=0 allows us to draw the curve without interruptions)
-\newcommand{\pgf@nfold@callback@move}[5]{%
+\def\pgf@nfold@callback@move#1#2#3#4#5{%
\ifnum#5=0\relax\pgfpathmoveto{#1}\fi%
\pgfpathcurveto{#2}{#3}{#4}%
}
% this version never does a moveto at the start. Useful for drawing a path consisting of
% multiple Bezier curves.
-\newcommand{\pgf@nfold@callback@nomove}[5]{\pgfpathcurveto{#2}{#3}{#4}}
+\def\pgf@nfold@callback@nomove#1#2#3#4#5{\pgfpathcurveto{#2}{#3}{#4}}
% Like the previous macro, but with a custom callback macro for each segment instead of
% executing \drawsegment as defined above. See \drawsegment for the arguments.
-\newcommand{\pgfoffsetcurvecallback}[6]{%
+\def\pgfoffsetcurvecallback#1#2#3#4#5#6{%
\pgf@subdivideandoffsetcurve{#1}{#2}{#3}{#4}{#5}{\pgf@offset@max@recursion}{0}{#6}%
}
@@ -265,66 +312,73 @@
% #7: =0 if this is the start of the curve, =1 otherwise;
% #8: callback for output (see above)
\newif\ifpgf@offset@subdivide
-\newcommand{\pgf@subdivideandoffsetcurve}[8]{%
+\def\pgf@subdivideandoffsetcurve#1#2#3#4#5#6#7#8{%
% we need a group to avoid overwriting variables in recursive calls
\begingroup%
- \pgf@offset@subdividefalse%
- \c@pgf@counta=#6%
- \advance\c@pgf@counta by-1%
- \pgf@process{#1}\pgfstorepoint{\pgf@ctrl@i}%
- \pgf@process{#2}\pgfstorepoint{\pgf@ctrl@ii}%
- \pgf@process{#3}\pgfstorepoint{\pgf@ctrl@iii}%
- \pgf@process{#4}\pgfstorepoint{\pgf@ctrl@iv}%
- % Use the non-degenerate tangents for the simplicity check
- \pgf@offset@compute@tangents{\pgf@ctrl@i}{\pgf@ctrl@ii}{\pgf@ctrl@iii}{\pgf@ctrl@iv}%
- \pgfpointdiff{\pgf@ctrl@i}{\pgf@ctrl@iv}\pgfstorepoint{\pgf@itoiv}%
- \pgfcrossproduct{\pgf@itoiv}{\pgf@tmp@tang@i}%
- \edef\firstcross{\pgfmathresult}%
- \pgfcrossproduct{\pgf@itoiv}{\pgf@tmp@tang@ii}%
- % First simplicity check: Are A2 and A3 on the same side of the A1-A4 line?
- % -> compute the sign of the cross products, use the sign function to avoid overflows
- \pgfmathparse{sign(\firstcross)*sign(\pgfmathresult)}%
- \ifdim\pgfmathresult pt>0pt\relax%
- \pgf@offset@subdividetrue%
- \else%
- % Second simplicity check: How large is the angle between the tangents in A1 and A4?
- \pgfdotproduct{\pgf@tmp@tang@i}{\pgf@tmp@tang@ii}%
- \ifdim\pgfmathresult pt<.5pt\relax%
+ \pgf@offset@subdividefalse%
+ \c@pgf@counta=#6\relax
+ \advance\c@pgf@counta by -1
+ \pgfextract@process\pgf@ctrl@i{#1}%
+ \pgfextract@process\pgf@ctrl@ii{#2}%
+ \pgfextract@process\pgf@ctrl@iii{#3}%
+ \pgfextract@process\pgf@ctrl@iv{#4}%
+ % Use the non-degenerate tangents for the simplicity check
+ \pgf@offset@compute@tangents{\pgf@ctrl@i}{\pgf@ctrl@ii}{\pgf@ctrl@iii}{\pgf@ctrl@iv}%
+ \pgfextract@process\pgf@itoiv{\pgfpointdiff{\pgf@ctrl@i}{\pgf@ctrl@iv}}%
+ \pgfmathcrossproduct{\pgf@itoiv}{\pgf@tmp@tang@i}%
+ \let\firstcross\pgfmathresult
+ \pgfmathcrossproduct{\pgf@itoiv}{\pgf@tmp@tang@ii}%
+ % First simplicity check: Are A2 and A3 on the same side of the A1-A4 line?
+ % -> compute the sign of the cross products, use the sign function to avoid overflows
+ % just give it a pass if one of them is zero, hence 2 and 3 at the end
+ \ifnum
+ \ifdim \firstcross pt<0pt -1\else\ifdim \firstcross pt>0pt 1\else 2\fi\fi
+ =\ifdim\pgfmathresult pt<0pt -1\else\ifdim\pgfmathresult pt>0pt 1\else 3\fi\fi
+ \relax % the \relax is important!
\pgf@offset@subdividetrue%
- \else
- % Third simplicity check: Put a limit on the lengths of the i-ii and iii-iv vectors combined
- \pgf@itoiv
- \pgfmathsetmacro{\pgf@tmp@len@i@iv}{veclen(\pgf@x,\pgf@y)}
- \pgfpointdiff{\pgf@ctrl@i}{\pgf@ctrl@ii}
- \pgf@xb=\pgf@x\pgf@yb=\pgf@y
- \pgfpointdiff{\pgf@ctrl@iii}{\pgf@ctrl@iv}
- \pgfmathparse{\pgf@tmp@len@i@iv < veclen(\pgf@xb,\pgf@yb) + veclen(\pgf@x,\pgf@y)}
- \ifnum\pgfmathresult=1\relax
+ \else%
+ % Second simplicity check: How large is the angle between the tangents in A1 and A4?
+ \pgfmathdotproduct{\pgf@tmp@tang@i}{\pgf@tmp@tang@ii}%
+ \ifdim\pgfmathresult pt<.5pt\relax%
\pgf@offset@subdividetrue%
- \fi
+ \else
+ % Third simplicity check: Put a limit on the lengths of the i-ii and iii-iv vectors combined
+ \pgf@itoiv
+ \pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}%
+ \pgf@xa=\pgfmathresult pt
+ \pgf@process{\pgfpointdiff{\pgf@ctrl@i}{\pgf@ctrl@ii}}%
+ \pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}%
+ \pgf@xb=\pgfmathresult pt
+ \pgf@process{\pgfpointdiff{\pgf@ctrl@iii}{\pgf@ctrl@iv}}%
+ \pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}%
+ \advance\pgf@xb by \pgfmathresult pt
+ % \veclen(itoiv) < veclen(ii-i) + veclen(iv-iii)
+ \ifdim\pgf@xa<\pgf@xb
+ \pgf@offset@subdividetrue
+ \fi
+ \fi%
\fi%
- \fi%
- \ifpgf@offset@subdivide%
- \ifnum\c@pgf@counta<0%
- % We hit the recursion limit but the segment is not simple
- \pgfwarning{pgf-offset: Recursion limit reached, glitches may occur. %
- Consider increasing \string\pgf@offset@max@recursion}%
- % Try to offset the curve anyway. The result will not be precise,
- % but the code is sufficiently robust to not crash
+ \ifpgf@offset@subdivide%
+ \ifnum\c@pgf@counta<0%
+ % We hit the recursion limit but the segment is not simple
+ \pgfutil@packagewarning{tikz-nfold}{Recursion limit reached, glitches may occur. %
+ Consider increasing \string\pgf@offset@max@recursion}%
+ % Try to offset the curve anyway. The result will not be precise,
+ % but the code is sufficiently robust to not crash
+ \pgf@offset@bezier@segment{\pgf@ctrl@i}{\pgf@ctrl@ii}{\pgf@ctrl@iii}{\pgf@ctrl@iv}{#5}%
+ #8{\pgf@bezier@offset@i}{\pgf@bezier@offset@ii}{\pgf@bezier@offset@iii}{\pgf@bezier@offset@iv}{#7}%
+ \else
+ % split the non-simple segment and execute recursive calls
+ \pgf@splitbezier{.5}{\pgf@ctrl@i}{\pgf@ctrl@ii}{\pgf@ctrl@iii}{\pgf@ctrl@iv}%
+ % pass on the "start of the curve flag" only to the first term
+ \pgf@subdivideandoffsetcurve{\pgf@splitbezier@i@i}{\pgf@splitbezier@i@ii}{\pgf@splitbezier@i@iii}{\pgf@splitbezier@i@iv}{#5}{\c@pgf@counta}{#7}{#8}%
+ \pgf@subdivideandoffsetcurve{\pgf@splitbezier@ii@i}{\pgf@splitbezier@ii@ii}{\pgf@splitbezier@ii@iii}{\pgf@splitbezier@ii@iv}{#5}{\c@pgf@counta}{1}{#8}%
+ \fi%
+ \else%
+ % curve is simple
\pgf@offset@bezier@segment{\pgf@ctrl@i}{\pgf@ctrl@ii}{\pgf@ctrl@iii}{\pgf@ctrl@iv}{#5}%
#8{\pgf@bezier@offset@i}{\pgf@bezier@offset@ii}{\pgf@bezier@offset@iii}{\pgf@bezier@offset@iv}{#7}%
- \else
- % split the non-simple segment and execute recursive calls
- \pgf@splitbezier{.5}{\pgf@ctrl@i}{\pgf@ctrl@ii}{\pgf@ctrl@iii}{\pgf@ctrl@iv}%
- % pass on the "start of the curve flag" only to the first term
- \pgf@subdivideandoffsetcurve{\pgf@splitbezier@i@i}{\pgf@splitbezier@i@ii}{\pgf@splitbezier@i@iii}{\pgf@splitbezier@i@iv}{#5}{\c@pgf@counta}{#7}{#8}%
- \pgf@subdivideandoffsetcurve{\pgf@splitbezier@ii@i}{\pgf@splitbezier@ii@ii}{\pgf@splitbezier@ii@iii}{\pgf@splitbezier@ii@iv}{#5}{\c@pgf@counta}{1}{#8}%
\fi%
- \else%
- % curve is simple
- \pgf@offset@bezier@segment{\pgf@ctrl@i}{\pgf@ctrl@ii}{\pgf@ctrl@iii}{\pgf@ctrl@iv}{#5}%
- #8{\pgf@bezier@offset@i}{\pgf@bezier@offset@ii}{\pgf@bezier@offset@iii}{\pgf@bezier@offset@iv}{#7}%
- \fi%
\endgroup%
}
@@ -336,16 +390,16 @@
% For convenience we also provide macros that offset straight lines. These also come in two variants
% similar to the macros for curves.
%
-\newcommand{\pgfoffsetline}[3]{
- \pgfpointscale{#3}{\pgfpointnormalised{\pgfpointdiff{#1}{#2}}}
+\def\pgfoffsetline#1#2#3{%
+ \pgfpointscale{#3}{\pgfpointnormalised{\pgfpointdiff{#1}{#2}}}%
\pgf@xc=-\pgf@y
\pgf@yc=\pgf@x
- \pgfpathmoveto{\pgfpointadd{#1}{\pgfqpoint{\pgf@xc}{\pgf@yc}}}
- \pgfpathlineto{\pgfpointadd{#2}{\pgfqpoint{\pgf@xc}{\pgf@yc}}}
+ \pgfpathmoveto{\pgfpointadd{#1}{\pgfqpoint{\pgf@xc}{\pgf@yc}}}%
+ \pgfpathlineto{\pgfpointadd{#2}{\pgfqpoint{\pgf@xc}{\pgf@yc}}}%
}
-\newcommand{\pgfoffsetlinenomove}[3]{
- \pgfpointscale{#3}{\pgfpointnormalised{\pgfpointdiff{#1}{#2}}}
+\def\pgfoffsetlinenomove#1#2#3{%
+ \pgfpointscale{#3}{\pgfpointnormalised{\pgfpointdiff{#1}{#2}}}%
\pgf@xc=-\pgf@y
\pgf@yc=\pgf@x
- \pgfpathlineto{\pgfpointadd{#2}{\pgfqpoint{\pgf@xc}{\pgf@yc}}}
+ \pgfpathlineto{\pgfpointadd{#2}{\pgfqpoint{\pgf@xc}{\pgf@yc}}}%
}