%% pgflibrarybezieroffset.code.tex %% Copyright 2023 Jonathan Schulz % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3c % of this license or (at your option) any later version. % The latest version of this license is in % http://www.latex-project.org/lppl.txt % and version 1.3c or later is part of all distributions of LaTeX % version 2008-05-04 or later. % % This work has the LPPL maintenance status 'maintained'. % % The Current Maintainer of this work is Jonathan Schulz. % % This work consists of the files % pgflibrarybezieroffset.code.tex, pgflibrarynfold.code.tex, pgflibraryoffsetpath.code.tex, tikz-nfold-doc.tex, tikzlibrarynfold.code.tex, tikz-nfold-doc.tex, and tikz-nfold-doc.pdf. % % % A commented version of this file can be found on https://github.com/jonschz/tikz-nfold . % \def\pgf@halfsplitbezier#1#2#3#4{% \pgfextract@process\pgf@splitbezier@ii@iv{#4}% \pgf@xc=\pgf@x% \pgf@yc=\pgf@y% \pgf@process{#3}% \pgf@xb=\pgf@x% \pgf@yb=\pgf@y% \pgf@process{#2}% \pgf@xa=\pgf@x% \pgf@ya=\pgf@y% \pgfextract@process\pgf@splitbezier@i@i{#1}% \pgf@x=.5\pgf@x\advance\pgf@x by.5\pgf@xa% \pgf@y=.5\pgf@y\advance\pgf@y by.5\pgf@ya% \edef\pgf@splitbezier@i@ii{\pgf@x\the\pgf@x\pgf@y\the\pgf@y}% \pgf@xa=.5\pgf@xa\advance\pgf@xa by.5\pgf@xb% \pgf@ya=.5\pgf@ya\advance\pgf@ya by.5\pgf@yb% \pgf@xb=.5\pgf@xb\advance\pgf@xb by.5\pgf@xc% \pgf@yb=.5\pgf@yb\advance\pgf@yb by.5\pgf@yc% \edef\pgf@splitbezier@ii@iii{\pgf@x\the\pgf@xb\pgf@y\the\pgf@yb}% \pgf@x=.5\pgf@x\advance\pgf@x by.5\pgf@xa% \pgf@y=.5\pgf@y\advance\pgf@y by.5\pgf@ya% \edef\pgf@splitbezier@i@iii{\pgf@x\the\pgf@x\pgf@y\the\pgf@y}% \pgf@xa=.5\pgf@xa\advance\pgf@xa by.5\pgf@xb% \pgf@ya=.5\pgf@ya\advance\pgf@ya by.5\pgf@yb% \edef\pgf@splitbezier@ii@ii{\pgf@x\the\pgf@xa\pgf@y\the\pgf@ya}% \pgf@x=.5\pgf@x\advance\pgf@x by.5\pgf@xa% \pgf@y=.5\pgf@y\advance\pgf@y by.5\pgf@ya% \edef\pgf@splitbezier@i@iv{\pgf@x\the\pgf@x\pgf@y\the\pgf@y}% \let\pgf@splitbezier@ii@i\pgf@splitbezier@i@iv } \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 } \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 } \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 } \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 } \def\pgf@offset@compute@tangents#1#2#3#4{% \pgf@process{\pgfpointdiff{#1}{#2}}% \pgfpointtaxicabnorm\pgf@xa \ifdim\pgf@xa<0.1pt\relax \pgf@process{\pgfpointdiff{#1}{#3}}% \pgfpointtaxicabnorm\pgf@xa \ifdim\pgf@xa<0.1pt\relax \pgf@process{\pgfpointdiff{#1}{#4}}% \fi \fi \pgfextract@process\pgf@tmp@tang@i{% \pgfpointnormalised{}% \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 \pgfextract@process\pgf@tmp@tang@ii{\pgfpointnormalised{}\global\let\pgf@nfold@tmp\pgf@tmp}% \let\pgf@tmp@angle@ii\pgf@nfold@tmp% } \def\pgf@offset@bezier@segment#1#2#3#4#5{% \pgf@offset@compute@tangents{#1}{#2}{#3}{#4}% \pgf@offset@bezier@segment@{#1}{#2}{#3}{#4}{#5}% } \def\pgf@offset@bezier@segment@#1#2#3#4#5{% \pgf@tmp@tang@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}}% \pgf@tmp@tang@ii \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}}% \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 \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 \pgfextract@process\pgf@tmp@secant{\pgfpointnormalised{}}% \pgfmathcrossdot{}{\pgf@tmp@tang@ii}% \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{#1}{#2}}} \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}}}% }% \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}}}% \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 } \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 } \newcount\pgf@offset@max@recursion \pgf@offset@max@recursion=4 \def\pgfoffsetcurve#1#2#3#4#5{% \pgfoffsetcurvecallback{#1}{#2}{#3}{#4}{#5}{\pgf@nfold@callback@move}% } \def\pgfoffsetcurvenomove#1#2#3#4#5{% \pgfoffsetcurvecallback{#1}{#2}{#3}{#4}{#5}{\pgf@nfold@callback@nomove}% } \def\pgf@nfold@callback@move#1#2#3#4#5{% \if#50\pgfpathmoveto{#1}\fi% \pgfpathcurveto{#2}{#3}{#4}% } \def\pgf@nfold@callback@nomove#1#2#3#4#5{\pgfpathcurveto{#2}{#3}{#4}} \def\pgfoffsetcurvecallback#1#2#3#4#5#6{% \edef\pgf@offset@tmp@callback##1##2##3##4##5{% \noexpand\pgf@offset@bezier@segment{##1}{##2}{##3}{##4}{#5}% \noexpand#6{\noexpand\pgf@bezier@offset@i}{\noexpand\pgf@bezier@offset@ii}{\noexpand\pgf@bezier@offset@iii}{\noexpand\pgf@bezier@offset@iv}{##5}% } \pgf@subdividecurve{#1}{#2}{#3}{#4}{\pgf@offset@max@recursion}{0}{\pgf@offset@tmp@callback}% } \newif\ifpgf@offset@subdivide \def\pgf@subdividecurve#1#2#3#4#5#6#7{% \begingroup% \pgfextract@process\pgf@ctrl@i{#1}% \pgfextract@process\pgf@ctrl@ii{#2}% \pgfextract@process\pgf@ctrl@iii{#3}% \pgfextract@process\pgf@ctrl@iv{#4}% \pgf@offset@compute@tangents{\pgf@ctrl@i}{\pgf@ctrl@ii}{\pgf@ctrl@iii}{\pgf@ctrl@iv}% \pgf@subdividecurve@{#5}{#6}{#7}% \endgroup% } \def\pgf@subdividecurve@#1#2#3{% \pgf@offset@subdividefalse% \c@pgf@counta=#1\relax \advance\c@pgf@counta by -1 \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}% \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 % \pgf@offset@subdividetrue% \else% \pgfmathdotproduct{\pgf@tmp@tang@i}{\pgf@tmp@tang@ii}% \ifdim\pgfmathresult pt<.5pt\relax% \pgf@offset@subdividetrue% \else \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 \ifdim\pgf@xa<\pgf@xb \pgf@offset@subdividetrue \fi \fi% \fi% \ifpgf@offset@subdivide% \ifnum\c@pgf@counta<0% \pgfutil@packagewarning{tikz-nfold}{Recursion limit reached, glitches may occur. % Consider increasing \string\pgf@offset@max@recursion}% #3{\pgf@ctrl@i}{\pgf@ctrl@ii}{\pgf@ctrl@iii}{\pgf@ctrl@iv}{#2}% \else \pgf@halfsplitbezier{\pgf@ctrl@i}{\pgf@ctrl@ii}{\pgf@ctrl@iii}{\pgf@ctrl@iv}% \pgfextract@process\pgf@middletangent{% \pgfpointnormalised{\pgfpointdiff{\pgf@splitbezier@i@iii}{\pgf@splitbezier@i@iv}}}% \begingroup% \let\pgf@tmp@tang@ii\pgf@middletangent% \let\pgf@ctrl@i\pgf@splitbezier@i@i% \let\pgf@ctrl@ii\pgf@splitbezier@i@ii% \let\pgf@ctrl@iii\pgf@splitbezier@i@iii% \let\pgf@ctrl@iv\pgf@splitbezier@i@iv% \pgf@subdividecurve@{\c@pgf@counta}{#2}{#3}% \endgroup% \begingroup% \let\pgf@tmp@tang@i\pgf@middletangent% \let\pgf@ctrl@i\pgf@splitbezier@ii@i% \let\pgf@ctrl@ii\pgf@splitbezier@ii@ii% \let\pgf@ctrl@iii\pgf@splitbezier@ii@iii% \let\pgf@ctrl@iv\pgf@splitbezier@ii@iv% \pgf@subdividecurve@{\c@pgf@counta}{1}{#3}% \endgroup% \fi% \else% #3{\pgf@ctrl@i}{\pgf@ctrl@ii}{\pgf@ctrl@iii}{\pgf@ctrl@iv}{#2}% \fi% } \def\pgfoffsetline#1#2#3{% \pgfmathparse{#3}% \pgfoffsetline@{#1}{#2}{\pgfmathresult}{\pgfpointnormalised{\pgfpointdiff{#1}{#2}}}% } \def\pgfoffsetline@#1#2#3#4{% \pgfqpointscale{#3}{#4}% \pgf@xc=-\pgf@y \pgf@yc=\pgf@x \pgfpathmoveto{\pgfpointadd{#1}{\pgfqpoint{\pgf@xc}{\pgf@yc}}}% \pgfpathlineto{\pgfpointadd{#2}{\pgfqpoint{\pgf@xc}{\pgf@yc}}}% } \def\pgfoffsetlinenomove#1#2#3{% \pgfoffsetlinenomove@{#1}{#2}{#3}{\pgfpointnormalised{\pgfpointdiff{#1}{#2}}}% } \def\pgfoffsetlinenomove@#1#2#3#4{% \pgfqpointscale{#3}{#4}% \pgf@xc=-\pgf@y \pgf@yc=\pgf@x \pgfpathlineto{\pgfpointadd{#2}{\pgfqpoint{\pgf@xc}{\pgf@yc}}}% }