summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2023-07-23 20:45:55 +0000
committerKarl Berry <karl@freefriends.org>2023-07-23 20:45:55 +0000
commitc1bfd0a25d81a98bbc0c1c15063221e59947f974 (patch)
tree715281fb93dccd8acffaf7089d65e4b80c3105dc
parent7c1d8b696f56903c8d59bfe440d934656c2e1e10 (diff)
tikz-nfold (23jul23)
git-svn-id: svn://tug.org/texlive/trunk@67711 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r--Master/texmf-dist/doc/latex/tikz-nfold/README.md2
-rw-r--r--Master/texmf-dist/doc/latex/tikz-nfold/tikz-nfold-doc.pdfbin302816 -> 304060 bytes
-rw-r--r--Master/texmf-dist/doc/latex/tikz-nfold/tikz-nfold-doc.tex38
-rw-r--r--Master/texmf-dist/tex/latex/tikz-nfold/pgflibrarybezieroffset.code.tex170
-rw-r--r--Master/texmf-dist/tex/latex/tikz-nfold/pgflibrarynfold.code.tex88
-rw-r--r--Master/texmf-dist/tex/latex/tikz-nfold/pgflibraryoffsetpath.code.tex913
-rw-r--r--Master/texmf-dist/tex/latex/tikz-nfold/tikzlibrarynfold.code.tex1303
7 files changed, 1048 insertions, 1466 deletions
diff --git a/Master/texmf-dist/doc/latex/tikz-nfold/README.md b/Master/texmf-dist/doc/latex/tikz-nfold/README.md
index c1466687133..4c1d75c2494 100644
--- a/Master/texmf-dist/doc/latex/tikz-nfold/README.md
+++ b/Master/texmf-dist/doc/latex/tikz-nfold/README.md
@@ -1,5 +1,5 @@
# tikz-nfold
-## Version 0.1.3
+## Version 1.0.0
This library adds higher-order paths to [TikZ](https://ctan.org/pkg/pgf) and also fixes some graphical issues with TikZ' `double` paths, used e.g. in wide arrows. It is also compatible with [tikz-cd](https://ctan.org/pkg/tikz-cd), adding support for triple and higher arrows. See the [documentation](tikz-nfold-doc.pdf) for full details.
diff --git a/Master/texmf-dist/doc/latex/tikz-nfold/tikz-nfold-doc.pdf b/Master/texmf-dist/doc/latex/tikz-nfold/tikz-nfold-doc.pdf
index 9df9c937ac2..8dad39e27f0 100644
--- a/Master/texmf-dist/doc/latex/tikz-nfold/tikz-nfold-doc.pdf
+++ b/Master/texmf-dist/doc/latex/tikz-nfold/tikz-nfold-doc.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/tikz-nfold/tikz-nfold-doc.tex b/Master/texmf-dist/doc/latex/tikz-nfold/tikz-nfold-doc.tex
index 46132fb7f5b..094924d2e8b 100644
--- a/Master/texmf-dist/doc/latex/tikz-nfold/tikz-nfold-doc.tex
+++ b/Master/texmf-dist/doc/latex/tikz-nfold/tikz-nfold-doc.tex
@@ -1,4 +1,4 @@
-%% tikz-nfold.sty
+%% tikz-nfold-doc.tex
%% Copyright 2023 Jonathan Schulz
%
% This work may be distributed and/or modified under the
@@ -13,8 +13,12 @@
%
% The Current Maintainer of this work is Jonathan Schulz.
%
-% This work consists of the files pgflibrarybezieroffset.code.tex,
-% tikzlibrarynfold.code.tex, tikz-nfold-doc.tex, and tikz-nfold-doc.pdf.
+% 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 .
+%
\documentclass[12pt,a4paper]{article}
@@ -27,7 +31,6 @@
\usepackage{parskip}
\usepackage[margin=2.5cm]{geometry}
-% recommended order: 1) hyperref 2) amsthm 3) cleveref 4) \newtheorem
\usepackage[colorlinks]{hyperref}
\usepackage{amsmath}
\usepackage{amsthm}
@@ -38,7 +41,6 @@
\theoremstyle{definition}
\newtheorem{definition}{Definition}[section]
-%\newcommand{\todo}[1]{{\color{red}\bfseries#1}}
\newcommand{\tikzdouble}{\texttt{/tikz/double}}
\newcommand{\nfold}{\texttt{nfold}}
\newcommand{\tikznfold}{\texttt{/tikz/nfold}}
@@ -52,7 +54,6 @@
\newcommand{\uv}{\vec{u}}
\newcommand{\vv}{\vec{v}}
-% to be used in pre=... to stop the proparation of warnings outside of tkzexample environments
\makeatletter
\def\disablewarnings{\def\pgfutil@packagewarning##1##2{}}
\makeatother
@@ -209,6 +210,19 @@ This package is by no means perfect, and even if it were, there would still be s
\subsection{Impossible or very hard to fix}
\begin{itemize}
+ \item Self-intersecting paths do not have the expected intersections:
+\begin{tkzexample}[latex=4.5cm]
+\begin{tikzpicture}
+ \draw[double distance=5pt, line width=1pt]
+ (0,2.5) -- (1,2.5) (1,3) -- (1,2)
+ (2,2) -- (3,2) rectangle (4,3);
+ \node[right] at (0,3.5) {double:};
+ \draw[double distance=5pt, line width=1pt, nfold]
+ (0,.5) -- (1,.5) (1,1) -- (1,0)
+ (2,0) -- (3,0) rectangle (4,1);
+ \node[right] at (0,1.5) {nfold:};
+\end{tikzpicture}
+\end{tkzexample}
\item \nfold{} struggles with high curvatures and wide paths: Let $\kappa(t)$ be the curvature of the path in a given point, and let $\texttt{double distance} = \alpha$. If $\kappa(t) > \frac{2}{\alpha}$ (i.e. the radius of the osculating circle is smaller than half the width of the path) for some $0 \leq t \leq 1$, the output of \nfold{} will not be correct:
\begin{tkzexample}[latex=4.25cm]
\begin{tikzpicture}
@@ -268,12 +282,14 @@ This package is by no means perfect, and even if it were, there would still be s
\section{The basic layer \texttt{pgf} commands}
+This package contains three \emph{pgf} libraries building upon one another: \texttt{bezieroffset}, \texttt{offsetpath}, and \nfold. All of these are contained in the \emph{TikZ} library \nfold.
+
\subsection{Offsetting curves}
-This package provides some basic layer commands for offsetting curves and straight lines. Use
+This library provides some basic layer commands for offsetting curves and straight lines. Use
\begin{verbatim}
\usepgflibrary{bezieroffset}
\end{verbatim}
-to only import the base layer library. The following commands are provided:
+to only import this base layer library. The following commands are provided:
\begin{itemize}
\item \verb|\pgfoffsetcurve{pt1}{pt2}{pt3}{pt4}{distance}|\\%
This macro draws the parallel of a Bézier curve. The first four parameters are the control points of the Bézier curve (e.g.\ in the form of \verb|\pgfpoint{}{}|), the fifth parameter is the distance by which the curve should be offset. A negative value offsets the curve in the opposite direction. This macro begins with a \verb|\pgfpointmoveto| to the offset of \texttt{pt1}.
@@ -286,7 +302,7 @@ to only import the base layer library. The following commands are provided:
\end{itemize}
\subsection{Offsetting paths}
-The following macros are part of the TikZ library \nfold{} and offset an entire soft path.
+The following macros are part of the pgf library \texttt{offsetpath} and offset the whole softpath.
\begin{itemize}
\item \verb|\pgfoffsetpath{softpath}{distance}|\\%
This macro offsets \texttt{softpath} by \texttt{distance}. The latter may be negative.
@@ -295,7 +311,7 @@ The following macros are part of the TikZ library \nfold{} and offset an entire
\item \verb|\pgfoffsetpathqfraction{softpath}{hwidth}{fraction}|\\%
This macro is a quicker version of the previous macro does not parse the input values using the \texttt{pgfmath}-engine.
\item \verb|\pgfoffsetpathindex{softpath}{width}{i}{n}|\\%
- In this convenience method, \texttt{i} and \texttt{n} are integers with $1 \leq i \leq n$. It calls the previous macro with \texttt{fraction=-1.0} for \texttt{i=1} and with \texttt{fraction=1.0} for \texttt{i=n} and is thus capable of reproducing the output of \texttt{/tikz/nfold=n} (albeit in a less efficient way).
+ In this convenience method, \texttt{i} and \texttt{n} are integers with $1 \leq i \leq n$. It calls the previous macro with \texttt{fraction=-1.0} for \texttt{i=1} and with \texttt{fraction=1.0} for \texttt{i=n}, hence it is capable of reproducing the output of \texttt{/tikz/nfold=n} (albeit in a less efficient way).
\end{itemize}
In the following example we see how \verb|\pgfoffsetpath{..}{0pt}| reproduces the input path (rendered in black) and how \verb|\pgfoffsetpathfraction{..}{8pt}{0}| differs.
\begin{tkzexample}[latex=4cm]
@@ -329,6 +345,7 @@ Here we see how the commands can be used to customise $n$-fold paths:
\section{Version history}
\begin{itemize}
+ \item \textbf{v1.0.0}: Restructure and bug fixes
\item \textbf{v0.1.3}: Bug fixes
\item \textbf{v0.1.2}: Bug fixes
\item \textbf{v0.1.1}: Closing paths and structural changes
@@ -497,7 +514,6 @@ Note that $-\tfrac{\pi}{3} \leq \beta \leq \tfrac{\pi}{3}$ (and hence $\cos(\bet
\end{equation}
and all of these terms can be computed directly from dot and cross products of vectors between the original control points. To summarise, let $\vv_{ij} := \overrightarrow{A_iA_j}$, and let $\vv_0$, $\vv_1$ be the normalised tangents at $t=0$ and $t=1$, respectively (see \cref{subsec:stabilisation} how they are computed). Then
\begin{equation}
-% for checking
\overline{A'_1A'_2} = \overline{A_1A_2} + \frac{d}{\overline{A_1A_4}^2}\cdot\left(\vv_{12} \times \vv_{14} - \vv_{12}\cdot\vv_{14} \frac{\vv_{14}\times\tv_1}{\vv_{14}\cdot\tv_1} \right) \ .
\end{equation}
Let furthermore $\uv_{ij} := \vv_{ij}/|\vv_{ij}|$ be the normalised vectors. Then we find
diff --git a/Master/texmf-dist/tex/latex/tikz-nfold/pgflibrarybezieroffset.code.tex b/Master/texmf-dist/tex/latex/tikz-nfold/pgflibrarybezieroffset.code.tex
index 275fa0fdf39..06c9912f6c2 100644
--- a/Master/texmf-dist/tex/latex/tikz-nfold/pgflibrarybezieroffset.code.tex
+++ b/Master/texmf-dist/tex/latex/tikz-nfold/pgflibrarybezieroffset.code.tex
@@ -1,4 +1,4 @@
-%% tikz-nfold.sty
+%% pgflibrarybezieroffset.code.tex
%% Copyright 2023 Jonathan Schulz
%
% This work may be distributed and/or modified under the
@@ -13,102 +13,40 @@
%
% The Current Maintainer of this work is Jonathan Schulz.
%
-% This work consists of the files pgflibrarybezieroffset.code.tex,
-% tikzlibrarynfold.code.tex, tikz-nfold-doc.tex, and tikz-nfold-doc.pdf.
+% 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 .
+%
-% Don't delete this code in case we need it in the future
-%
-% Split a Bezier curve (de Casteljau's algorithm)
-% #1 = time (between 0 and 1)
-% #2-#5: control points
-% Outputs the first part into \pgf@splitbezier@i@i, ... , \pgf@splitbezier@i@iv,
-% and the second part into \pgf@splitbezier@ii@i, ... , \pgf@splitbezier@ii@iv.
-%\def\pgf@splitbezier#1#2#3#4#5{%
-% % based on pgfcorepoints.code.tex, \pgfpointcurveattime
-% \edef\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
-% \pgfextract@process\pgf@splitbezier@ii@iv{#5}%
-% \pgf@xc=\pgf@x%
-% \pgf@yc=\pgf@y%
-% % P^0_2
-% \pgf@process{#4}%
-% \pgf@xb=\pgf@x%
-% \pgf@yb=\pgf@y%
-% % P^0_1
-% \pgf@process{#3}%
-% \pgf@xa=\pgf@x%
-% \pgf@ya=\pgf@y%
-% % P^0_0
-% \pgfextract@process\pgf@splitbezier@i@i{#2}%
-% % First iteration:
-% % P^1_0
-% \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\pgfqpoint{\the\pgf@xb}{\the\pgf@yb}}%
-% % P^2_0
-% \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\pgfqpoint{\the\pgf@xa}{\the\pgf@ya}}%
-% % P^3_0
-% \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
-%}
-% Split the Bezier curve defined by #1-#4 at t=0.5 using de Casteljau's algorithm
\def\pgf@halfsplitbezier#1#2#3#4{%
- % based on pgfcorepoints.code.tex, \pgfpointcurveattime
- % P^0_3
\pgfextract@process\pgf@splitbezier@ii@iv{#4}%
\pgf@xc=\pgf@x%
\pgf@yc=\pgf@y%
- % P^0_2
- \pgf@process{#3}% removing these does not yield a significant speedup
+ \pgf@process{#3}%
\pgf@xb=\pgf@x%
\pgf@yb=\pgf@y%
- % P^0_1
\pgf@process{#2}%
\pgf@xa=\pgf@x%
\pgf@ya=\pgf@y%
- % P^0_0
\pgfextract@process\pgf@splitbezier@i@i{#1}%
- % First iteration:
- % P^1_0
\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}%
- % P^1_1
\pgf@xa=.5\pgf@xa\advance\pgf@xa by.5\pgf@xb%
\pgf@ya=.5\pgf@ya\advance\pgf@ya by.5\pgf@yb%
- % P^1_2
\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}%
- % P^2_0
\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}%
- % P^2_1
\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}%
- % P^3_0
\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}%
@@ -116,7 +54,6 @@
}
-% computes the cross product and puts it into \pgfmathresult
\def\pgfmathcrossproduct#1#2{%
\begingroup
\pgf@process{#1}%
@@ -159,7 +96,6 @@
\endgroup\pgf@temp
}
-% Calculates abs(\pgf@x) + abs(\pgf@y) in #1
\def\pgfpointtaxicabnorm#1{%
\ifdim\pgf@x<0pt
#1=-\pgf@x
@@ -173,24 +109,18 @@
\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.
\def\pgf@offset@compute@tangents#1#2#3#4{%
- \pgf@process{\pgfpointdiff{#1}{#2}}% unintuitively, this is PTii - PTi
+ \pgf@process{\pgfpointdiff{#1}{#2}}%
\pgfpointtaxicabnorm\pgf@xa
\ifdim\pgf@xa<0.1pt\relax
- % edge case: first point and first control point are equal
\pgf@process{\pgfpointdiff{#1}{#3}}%
\pgfpointtaxicabnorm\pgf@xa
\ifdim\pgf@xa<0.1pt\relax
- % edge case: first three points are equal
\pgf@process{\pgfpointdiff{#1}{#4}}%
\fi
\fi
\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%
@@ -208,37 +138,25 @@
}
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% Offsetting a simple section %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\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@bezier@segment@{#1}{#2}{#3}{#4}{#5}%
}
-% this version assumes that the tangents have been precomputed in \pgf@tmp@tang@i and @ii
\def\pgf@offset@bezier@segment@#1#2#3#4#5{%
- % offset A1
- % compute the normal
\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}}%
- % offset A4
\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}}%
- % now compute A'_2 and A'_3
\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.
\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}}}%
@@ -248,22 +166,18 @@
\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
\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}}}
- % 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)}%
\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
\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}%
@@ -272,7 +186,6 @@
\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
@@ -282,12 +195,6 @@
\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}%
@@ -301,48 +208,24 @@
\endgroup
}
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% Subdividing and offsetting %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% Maximum level of recursion. The theoretical limit to the number of subdivisions in the final curve
-% is given by 2^\pgf@offset@max@recursion
\newcount\pgf@offset@max@recursion
\pgf@offset@max@recursion=4
-%
-% 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 \pgfpathmoveto{}
-% to the new starting point.
-%
-% Interface:
-% #1-#4: control points of the whole Bezier curve
-% #5: offset
\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}%
+ \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)
\def\pgf@nfold@callback@move#1#2#3#4#5{%
\if#50\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.
\def\pgf@nfold@callback@nomove#1#2#3#4#5{\pgfpathcurveto{#2}{#3}{#4}}
-% This macro subdivides and offsets a curve and executes a given callback on every offset simple segment.
-% #1-#4: control points of the segment
-% #5: =0 if this is the first segment of the curve, =1 otherwise
-% #6: callback (see \pgf@nfold@callback@move) for the parameters
\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}%
@@ -352,11 +235,6 @@
}
-% This macro subdivides (but does not offset) a curve and executes a callback on every simple segment.
-% #1-#4: control points
-% #5: recursion limit (decreases on every recursive call)
-% #6: =0 if this is the start of the curve, =1 otherwise
-% #7: callback for output (see above)
\newif\ifpgf@offset@subdivide
\def\pgf@subdividecurve#1#2#3#4#5#6#7{%
\begingroup%
@@ -369,32 +247,24 @@
\endgroup%
}
-% This macro assumes that the curve is defined in \pgf@ctrl@i-\pgf@ctrl@iv
-% and that its tangents have already been computed.
\def\pgf@subdividecurve@#1#2#3{%
\pgf@offset@subdividefalse%
\c@pgf@counta=#1\relax
\advance\c@pgf@counta by -1
- % Use the non-degenerate tangents for the simplicity check
\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!
+ \relax %
\pgf@offset@subdividetrue%
\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%
\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
@@ -404,7 +274,6 @@
\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(iv-i) < veclen(ii-i) + veclen(iv-iii)
\ifdim\pgf@xa<\pgf@xb
\pgf@offset@subdividetrue
\fi
@@ -412,27 +281,19 @@
\fi%
\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
#3{\pgf@ctrl@i}{\pgf@ctrl@ii}{\pgf@ctrl@iii}{\pgf@ctrl@iv}{#2}%
\else
- % split the non-simple segment and execute recursive calls
\pgf@halfsplitbezier{\pgf@ctrl@i}{\pgf@ctrl@ii}{\pgf@ctrl@iii}{\pgf@ctrl@iv}%
- % compute the tangent at the spitting point; this vector is only zero if the curve
- % is degenerate to a point, in which case we can't compute the tangent anyway
\pgfextract@process\pgf@middletangent{%
\pgfpointnormalised{\pgfpointdiff{\pgf@splitbezier@i@iii}{\pgf@splitbezier@i@iv}}}%
\begingroup%
- % we need a group to avoid overwriting variables in recursive calls
\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%
- % pass on the "start of the curve flag" only to the first term
\pgf@subdividecurve@{\c@pgf@counta}{#2}{#3}%
\endgroup%
\begingroup%
@@ -445,25 +306,16 @@
\endgroup%
\fi%
\else%
- % curve is simple
#3{\pgf@ctrl@i}{\pgf@ctrl@ii}{\pgf@ctrl@iii}{\pgf@ctrl@iv}{#2}%
\fi%
}
-%
-% Offsetting straight lines
-% -------------------------
-%
-% For convenience we also provide macros that offset straight lines. These also come in two variants
-% similar to the macros for curves.
-%
\def\pgfoffsetline#1#2#3{%
\pgfmathparse{#3}%
\pgfoffsetline@{#1}{#2}{\pgfmathresult}{\pgfpointnormalised{\pgfpointdiff{#1}{#2}}}%
}
-% a quicker version in case we already know the tangent and #3 is a number without unit
\def\pgfoffsetline@#1#2#3#4{%
\pgfqpointscale{#3}{#4}%
\pgf@xc=-\pgf@y
diff --git a/Master/texmf-dist/tex/latex/tikz-nfold/pgflibrarynfold.code.tex b/Master/texmf-dist/tex/latex/tikz-nfold/pgflibrarynfold.code.tex
new file mode 100644
index 00000000000..f593c787b42
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/tikz-nfold/pgflibrarynfold.code.tex
@@ -0,0 +1,88 @@
+%% pgflibrarynfold.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 .
+%
+
+
+\usepgflibrary{offsetpath}
+
+
+\newcount\pgf@nfold@index
+\def\pgf@nfold@run@loop{%
+ \pgf@nfold@index=\pgf@nfold@order%
+ \pgf@nfold@run@loop@%
+}
+
+\def\pgf@nfold@run@loop@{%
+ \pgf@nfold@loop@inner%
+ \advance\pgf@nfold@index by -1\relax
+ \ifnum\pgf@nfold@index>0\relax%
+ \pgf@nfold@run@loop@%
+ \fi%
+}
+
+\def\pgf@nfold@loop@inner{%
+ \pgfmathsetmacro{\pgf@nfold@shift@fraction}%
+ {-1+2*(\pgf@nfold@index-1)/(\pgf@nfold@order-1)}%
+ \pgfmathsetmacro{\pgf@nfold@shiftamount}{\pgf@nfold@hwidth*\pgf@nfold@shift@fraction}
+ \pgftransformreset%
+ \parsedpath%
+ \pgfsyssoftpath@flushcurrentpath%
+ \pgf@up@action%
+}
+
+\def\pgf@nfold@compute@widths@from@double{
+ \pgf@x=\pgflinewidth\relax%
+ \pgf@y=\pgf@x\relax%
+ \advance\pgf@x-\pgfinnerlinewidth\relax%
+ \advance\pgf@y+\pgfinnerlinewidth\relax%
+ \pgf@x=.5\pgf@x\relax%
+ \pgf@y=.25\pgf@y\relax%
+}
+
+\def\pgf@nfold@render@cached@softpath{%
+ \pgfscope%
+ \pgf@nfold@compute@widths@from@double%
+ \pgfsetlinewidth\pgf@x%
+ \edef\pgf@nfold@hwidth{\the\pgf@y}%
+ \pgfprocessround{\pgf@nfold@cachedpath}{\pgf@nfold@cachedpath}%
+ \pgf@nfold@parsearrows%
+ \pgf@nfold@parsesoftpath{\pgf@nfold@cachedpath}{\parsedpath}%
+ \pgf@nfold@run@loop%
+ \endpgfscope%
+}
+
+
+\pgfkeys{
+ /pgf/nfold/.code={%
+ \pgf@nfold@order=#1\relax%
+ \ifnum\pgf@nfold@order<1\relax%
+ \pgfutil@packageerror{tikz-nfold}{The key /pgf/nfold must take a value of at least 1, got \the\pgf@nfold@order}{}%
+ \fi%
+ \ifnum\pgf@nfold@order>\pgf@nfold@intersec@numcached\relax
+ \ifdefined\pgfintersectionofpaths\else
+ \pgf@nfold@intersectionsnotloadedtrue
+ \fi
+ \fi
+ },
+ /pgf/nfold/.default=2
+}
+
+\endinput
diff --git a/Master/texmf-dist/tex/latex/tikz-nfold/pgflibraryoffsetpath.code.tex b/Master/texmf-dist/tex/latex/tikz-nfold/pgflibraryoffsetpath.code.tex
new file mode 100644
index 00000000000..645812ecb13
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/tikz-nfold/pgflibraryoffsetpath.code.tex
@@ -0,0 +1,913 @@
+%% pgflibraryoffsetpath.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 .
+%
+
+\usepgflibrary{bezieroffset}
+
+
+
+
+
+
+\gdef\pgf@nfold@cached@miterlimit{10}
+\let\pgf@nfold@old@miterlimit\pgfsetmiterlimit
+\def\pgfsetmiterlimit#1{%
+ \pgf@nfold@old@miterlimit{#1}%
+ \edef\pgf@nfold@cached@miterlimit{#1}%
+}
+
+\global\let\pgf@cached@linejoin=m%
+\let\pgf@nfold@old@setbeveljoin\pgfsetbeveljoin
+\let\pgf@nfold@old@setmiterjoin\pgfsetmiterjoin
+\let\pgf@nfold@old@setroundjoin\pgfsetroundjoin
+\def\pgfsetbeveljoin{%
+ \pgf@nfold@old@setbeveljoin%
+ \let\pgf@cached@linejoin=b%
+}
+\def\pgfsetmiterjoin{%
+ \pgf@nfold@old@setmiterjoin%
+ \let\pgf@cached@linejoin=m%
+}
+\def\pgfsetroundjoin{%
+ \pgf@nfold@old@setroundjoin%
+ \let\pgf@cached@linejoin=r%
+}
+
+
+
+\def\pgf@nfold@miterjoin{
+ \pgfpathlineto{
+ \pgfpointadd{\pgf@nfold@join@centre}{%
+ \pgfpointpolar{\pgf@nfold@firstang+.5*\pgf@nfold@deltaphi+90}%
+ {\pgf@nfold@shiftamount/cos(.5*\pgf@nfold@deltaphi)}%
+ }%
+ }%
+}
+
+\def\pgf@nfold@beveljoin{
+ \pgfmathsetlengthmacro{\bevelouterprotrusion}%
+ {\pgf@nfold@shortenstartjoin pt - .5*\pgflinewidth*abs(tan(.25*\pgf@nfold@deltaphi))}
+ \pgfmathsetmacro{\bevelshorten}{2*\insidepercentage*abs(tan(.25*\pgf@nfold@deltaphi))}
+ \pgfmathparse{\bevelshorten < abs(sin(.5*\pgf@nfold@deltaphi))}
+ \ifnum\pgfmathresult=1\relax
+ \pgfmathsetlengthmacro{\bevelextension}{\bevelouterprotrusion-\bevelshorten*\pgf@nfold@hwidth}
+ \pgfpointadd{\pgf@nfold@join@start}{\pgfpointpolar{\pgf@nfold@firstang}{\bevelextension}}
+ \pgfpathlineto{}
+ \pgfpointadd{\pgf@nfold@join@end}{\pgfpointpolar{\pgf@nfold@secondang}{-\bevelextension}}
+ \pgfpathlineto{}
+ \else
+ \pgf@nfold@miterjoin
+ \fi
+}
+
+\def\pgf@nfold@roundjoin{
+ \ifdim\insidepercentage pt<.5pt\relax
+ \pgfpointadd{\pgf@nfold@join@start}{\pgfpointpolar{\pgf@nfold@firstang}{\pgf@nfold@shortenstartjoin}}
+ \pgfpathlineto{}
+ \pgfmathsetmacro\pgf@tmp@firstang{\pgf@nfold@firstang+90*\turnindicator}
+ \pgfpatharc%
+ {\pgf@tmp@firstang}%
+ {\pgf@tmp@firstang+\pgf@nfold@deltaphi}%
+ {abs(\pgf@nfold@shift@fraction)*\pgf@nfold@hwidth}%
+ \else
+ \pgf@nfold@miterjoin
+ \fi
+}
+
+\def\pgf@nfold@token@join#1#2#3#4#5#6#7#8{%
+ \def\pgf@nfold@join@centre{#1}%
+ \def\pgf@nfold@join@prevend{#2}%
+ \def\pgf@nfold@join@nextstart{#3}%
+ \def\pgf@nfold@firstang{#4}%
+ \def\pgf@nfold@secondang{#5}%
+ \pgfextract@process\pgf@nfold@join@start{%
+ \pgfpointadd{#2}{\pgfpointpolar{\pgf@nfold@firstang+90}{\pgf@nfold@shiftamount}}}%
+ \pgfextract@process\pgf@nfold@join@end{%
+ \pgfpointadd{#3}{\pgfpointpolar{\pgf@nfold@secondang+90}{\pgf@nfold@shiftamount}}}%
+ \pgf@process{\pgfpointdiff{\pgf@nfold@join@start}{\pgf@nfold@join@end}}
+ \pgfpointtaxicabnorm\pgfutil@tempdima
+ \ifdim\pgfutil@tempdima>0.1pt\relax
+ \def\pgf@nfold@deltaphi{#6}%
+ \def\pgf@nfold@shortenstartjoin{#7}%
+ \ifdim\pgf@nfold@deltaphi pt<0pt
+ \def\turnindicator{1}
+ \else
+ \def\turnindicator{-1}
+ \fi
+ \pgfutil@tempdima=\pgf@nfold@shift@fraction pt\relax
+ \pgfutil@tempdima=\turnindicator\pgfutil@tempdima
+ \advance\pgfutil@tempdima by-1pt\relax
+ \pgfutil@tempdima=-.5\pgfutil@tempdima
+ \edef\insidepercentage{\pgf@sys@tonumber\pgfutil@tempdima}%
+ #8%
+ \fi
+}
+
+
+\def\pgf@nfold@process@join{%
+ \pgf@xa=\pgf@nfold@deltaphi@start pt\relax
+ \ifdim\pgf@xa<0pt\relax
+ \pgf@xa=-\pgf@xa
+ \fi
+ \ifdim\pgf@xa>1pt\relax
+ \edef\pgf@nfold@jointype{\pgf@cached@linejoin}
+ \if\pgf@cached@linejoin m%
+ \pgf@xa=.5\pgf@xa
+ \pgfmathcos@{\pgf@sys@tonumber\pgf@xa}
+ \pgf@xa=\pgfmathresult pt\relax
+ \pgf@xa=\pgf@nfold@cached@miterlimit\pgf@xa
+ \ifdim\pgf@xa>1pt\relax
+ \def\pgf@nfold@tmp@joinmacro{\pgf@nfold@miterjoin}
+ \else
+ \def\pgf@nfold@tmp@joinmacro{\pgf@nfold@beveljoin}
+ \fi
+ \else
+ \if b\pgf@cached@linejoin\relax
+ \def\pgf@nfold@tmp@joinmacro{\pgf@nfold@beveljoin}
+ \else
+ \def\pgf@nfold@tmp@joinmacro{\pgf@nfold@roundjoin}
+ \fi
+ \fi
+ \edef\pgf@nfold@macrotoadd{%
+ \noexpand\pgf@nfold@token@join{\pgf@nfold@cur@first}{\pgf@nfold@prev@segment@end}
+ {\pgf@nfold@cur@movedfirst}{\pgf@nfold@prev@angle@ii}{\pgf@nfold@cur@angle@i}%
+ {\pgf@nfold@deltaphi@start}{\pgf@nfold@shortenstartjoin}{%
+ \expandafter\noexpand\pgf@nfold@tmp@joinmacro%
+ \expandafter\noexpand\ifpgf@nfold@closejoinsedgecase%
+ \pgf@nfold@token@finish@edgecase{\pgf@nfold@cur@movedlast}%
+ \else%
+ \pgf@nfold@token@finish@normal%
+ \fi%
+ }%
+ }%
+ \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
+ \fi%
+}
+
+
+\def\pgf@nfold@token@finish@normal{%
+ \pgfpathlineto{\pgf@nfold@join@end}%
+}
+
+\def\pgf@nfold@token@finish@edgecase#1{%
+ \pgf@nfold@join@end%
+ \ifdim\insidepercentage pt<.5pt\relax%
+ \pgf@process{\pgfpointadd{#1}{\pgfpointpolar{\pgf@nfold@secondang+90}{\pgf@nfold@shiftamount}}}
+ \fi%
+ \pgfpathlineto{}%
+}
+
+
+
+\newif\ifpgf@nfold@continuesegment
+\newif\ifpgf@nfold@closejoinsedgecase
+\newif\ifpgf@nfold@angletoosharp
+\newif\ifpgf@nfold@intersectionsnotloaded
+\newif\ifpgf@nfold@lastconnsubpath
+
+
+\def\pgf@nfold@process@segment{%
+ \if\pgf@nfold@cur@visible0
+ \if\pgf@nfold@cur@type m
+ \if\pgf@nfold@start@arrowcode1
+ \ifpgf@nfold@lastconnsubpath
+ \if\pgf@nfold@prev@type f
+ \if\pgf@nfold@next@visible1
+ \edef\pgf@nfold@macrotoadd{%
+ \noexpand\pgf@nfold@extendtotip{s}{\pgf@nfold@cur@last}{\pgf@nfold@next@angle@i}
+ }%
+ \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
+ \let\pgf@nfold@cur@type l
+ \let\pgf@nfold@cur@visible1
+ \let\pgf@nfold@cur@angle@ii\pgf@nfold@next@angle@i
+ \let\pgf@nfold@cur@tang@ii\pgf@nfold@next@tang@i
+ \def\pgf@nfold@deltaphi@end{0}
+ \pgf@nfold@angletoosharpfalse
+ \fi
+ \fi%
+ \fi
+ \fi
+ \fi%
+ \else%
+ \let\pgf@nfold@cur@movedfirst\pgf@nfold@cur@first
+ \let\pgf@nfold@cur@movedlast\pgf@nfold@cur@last
+ \def\pgf@nfold@shortenstartjoin{0}
+ \def\pgf@nfold@shortenendjoin{0}
+ \pgf@nfold@closejoinsedgecasefalse
+ \if\pgf@nfold@prev@visible0
+ \pgf@nfold@continuesegmentfalse
+ \else
+ \pgf@nfold@continuesegmenttrue
+ \let\pgf@nfold@deltaphi@start\pgf@nfold@deltaphi@end
+ \pgf@xb=\pgf@nfold@deltaphi@start pt\relax
+ \ifdim\pgf@xb<0pt\relax
+ \pgf@xb=-\pgf@xb
+ \fi
+ \ifpgf@nfold@angletoosharp\else
+ \ifdim\pgf@xb>0.5pt\relax
+ \pgf@yb=.5\pgf@xb
+ \pgfmathtan@{\pgf@sys@tonumber\pgf@yb}
+ \pgf@yb=\pgf@nfold@hwidth\relax
+ \pgf@yb=\pgfmathresult\pgf@yb
+ \edef\pgf@nfold@shortenstartjoin{\pgf@sys@tonumber\pgf@yb}
+ \pgfextract@process\pgf@nfold@cur@movedfirst{%
+ \pgfpointadd{\pgf@nfold@cur@first}%
+ {\pgfqpointscale{\pgf@nfold@shortenstartjoin}{\pgf@nfold@cur@tang@i}}}%
+ \if\pgf@nfold@cur@type c
+ \pgf@process{\pgfpointdiff{\pgf@nfold@cur@first}{\pgf@nfold@cur@supporta}}
+ \pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}
+ \ifdim\pgfmathresult pt>0.1pt\relax
+ \pgfmathveclen@{\pgfmathresult}{\pgf@sys@tonumber\pgf@yb}
+ \pgfextract@process\pgf@nfold@cur@supporta{\pgfpointadd%
+ {\pgf@nfold@cur@first}%
+ {\pgfqpointscale{\pgfmathresult}{\pgf@nfold@cur@tang@i}}}%
+ \else
+ \let\pgf@nfold@cur@supporta\pgf@nfold@cur@movedfirst
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ \if\pgf@nfold@next@visible1
+ \pgfmathsubtract@{\pgf@nfold@next@angle@i}{\pgf@nfold@cur@angle@ii}
+ \pgf@nfold@clampangle
+ \edef\pgf@nfold@deltaphi@end{\pgfmathresult}
+ \pgf@xb=\pgf@nfold@deltaphi@end pt\relax
+ \ifdim\pgf@xb<0pt\relax
+ \pgf@xb=-\pgf@xb
+ \fi
+ \ifdim\pgf@xb>178pt\relax
+ \pgfutil@packagewarning{tikz-nfold}{Angle too sharp, expect visual errors}
+ \pgf@nfold@angletoosharptrue
+ \else
+ \pgf@nfold@angletoosharpfalse
+ \ifdim\pgf@xb>0.5pt\relax
+ \pgf@yb=.5\pgf@xb
+ \pgfmathtan@{\pgf@sys@tonumber\pgf@yb}
+ \pgf@yb=\pgf@nfold@hwidth\relax
+ \pgf@yb=\pgfmathresult\pgf@yb
+ \edef\pgf@nfold@shortenendjoin{\pgf@sys@tonumber\pgf@yb}
+ \pgf@yb=-\pgf@yb
+ \pgfextract@process\pgf@nfold@cur@movedlast{%
+ \pgfpointadd{\pgf@nfold@cur@last}%
+ {\pgfqpointscale{-\pgf@nfold@shortenendjoin}{\pgf@nfold@cur@tang@ii}}}%
+ \pgfextract@process\pgf@nfold@cur@movedlast{%
+ \pgfpointadd{\pgf@nfold@cur@last}%
+ {\pgfqpointpolar{\pgf@nfold@cur@angle@ii}{\pgf@yb}}}%
+ \if\pgf@nfold@cur@type c
+ \pgf@process{\pgfpointdiff{\pgf@nfold@cur@supportb}{\pgf@nfold@cur@last}}
+ \pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}
+ \ifdim\pgfmathresult pt>0.1pt\relax
+ \pgfmathveclen@{\pgfmathresult}{\pgf@sys@tonumber\pgf@yb}
+ \pgfextract@process\pgf@nfold@cur@supportb{\pgfpointadd%
+ {\pgf@nfold@cur@last}%
+ {\pgfqpointscale{-\pgfmathresult}{\pgf@nfold@cur@tang@ii}}}%
+ \else
+ \let\pgf@nfold@cur@supportb\pgf@nfold@cur@movedlast
+ \fi
+ \fi
+ \fi
+ \fi
+ \if\pgf@nfold@cur@type l
+ \pgf@process{\pgfpointdiff{\pgf@nfold@cur@first}{\pgf@nfold@cur@last}}
+ \pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}
+ \pgf@xa=\pgf@nfold@shortenstartjoin pt\relax
+ \advance\pgf@xa by\pgf@nfold@shortenendjoin pt\relax
+ \ifdim\pgf@xa>\pgfmathresult pt\relax
+ \pgf@nfold@closejoinsedgecasetrue
+ \fi
+ \fi
+ \fi%
+ \if\pgf@nfold@prev@visible0%
+ \ifpgf@nfold@closejoinsedgecase
+ \edef\pgf@nfold@macrotoadd{%
+ \noexpand\pgf@nfold@token@edgecase@movetostart{\pgf@nfold@cur@movedfirst}{\pgf@nfold@cur@angle@i}%
+ }%
+ \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
+ \fi
+ \else
+ \ifpgf@nfold@angletoosharp\else
+ \if\pgf@nfold@cur@type z\else
+ \pgf@nfold@process@join
+ \fi
+ \fi
+ \fi
+ \let\pgf@nfold@prev@segment@end\pgf@nfold@cur@movedlast
+ \if\pgf@nfold@cur@type i
+ \let\pgf@nfold@connsubpath@tang@i\pgf@nfold@next@tang@i%
+ \let\pgf@nfold@connsubpath@angle@i\pgf@nfold@next@angle@i%
+ \fi
+ \if\pgf@nfold@cur@type l
+ \ifpgf@nfold@closejoinsedgecase\else
+ \edef\pgf@nfold@macrotoadd{%
+ \expandafter\noexpand\ifpgf@nfold@continuesegment%
+ \pgf@nfold@token@lineto@continue%
+ \else%
+ \pgf@nfold@token@lineto%
+ \fi{\pgf@nfold@cur@movedfirst}{\pgf@nfold@cur@movedlast}{\pgf@nfold@cur@tang@i}%
+ }%
+ \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
+ \fi
+ \fi
+ \if\pgf@nfold@cur@type o
+ \def\pgf@nfold@macrotoadd{\pgf@nfold@token@closepath}%
+ \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
+ \fi
+ \if\pgf@nfold@cur@type z
+ \def\pgf@nfold@macrotoadd{\pgf@nfold@token@closepath}%
+ \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
+ \fi
+ \if\pgf@nfold@cur@type c
+ \ifpgf@nfold@continuesegment
+ \pgf@subdividecurve{\pgf@nfold@cur@movedfirst}{\pgf@nfold@cur@supporta}{\pgf@nfold@cur@supportb}{\pgf@nfold@cur@movedlast}{\pgf@offset@max@recursion}{0}{\pgf@nfold@addcurvesegment@callback@continue}
+ \else
+ \pgf@subdividecurve{\pgf@nfold@cur@movedfirst}{\pgf@nfold@cur@supporta}{\pgf@nfold@cur@supportb}{\pgf@nfold@cur@movedlast}{\pgf@offset@max@recursion}{0}{\pgf@nfold@addcurvesegment@callback}%
+ \fi
+ \fi
+ \if\pgf@nfold@cur@type i
+ \edef\pgf@nfold@macrotoadd{%
+ \noexpand\pgf@nfold@token@invisibleline{\pgf@nfold@cur@movedfirst}{\pgf@nfold@cur@movedlast}{\pgf@nfold@cur@tang@i}%
+ }%
+ \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
+ \fi
+ \if\pgf@nfold@next@type t%
+ \ifnum\pgf@nfold@end@arrowcode=1
+ \edef\pgf@nfold@macrotoadd{%
+ \noexpand\pgf@nfold@extendtotip{e}{\pgf@nfold@cur@last}{\pgf@nfold@cur@angle@ii}}%
+ \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
+ \fi%
+ \fi%
+ \fi%
+}
+
+
+\def\pgf@nfold@addcurvesegment@callback#1#2#3#4#5{%
+ \if#50%
+ \edef\pgf@nfold@macrotoadd{%
+ \noexpand\pgf@nfold@token@curveto{#1}{#2}{#3}{#4}{\pgf@tmp@tang@i}{\pgf@tmp@tang@ii}%
+ }%
+ \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
+ \else%
+ \pgf@nfold@addcurvesegment@callback@continue{#1}{#2}{#3}{#4}{#5}%
+ \fi%
+}
+
+\def\pgf@nfold@addcurvesegment@callback@continue#1#2#3#4#5{%
+ \edef\pgf@nfold@macrotoadd{%
+ \noexpand\pgf@nfold@token@curveto@continue{#1}{#2}{#3}{#4}{\pgf@tmp@tang@i}{\pgf@tmp@tang@ii}%
+ }%
+ \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
+}
+
+
+
+\expandafter\def\csname pgf@nfold@intersec@cache@2@3\endcsname{\pgfqpoint{2pt}{0pt}}
+\expandafter\def\csname pgf@nfold@intersec@cache@2@4\endcsname{\pgfqpoint{0.94063pt}{-0.33333pt}}
+\expandafter\def\csname pgf@nfold@intersec@cache@3@4\endcsname{\pgfqpoint{0.94063pt}{0.33333pt}}
+\expandafter\def\csname pgf@nfold@intersec@cache@2@5\endcsname{\pgfqpoint{0.64167pt}{-0.5pt}}
+\expandafter\def\csname pgf@nfold@intersec@cache@3@5\endcsname{\pgfqpoint{2pt}{0pt}}
+\expandafter\def\csname pgf@nfold@intersec@cache@4@5\endcsname{\pgfqpoint{0.64167pt}{0.5pt}}
+\def\pgf@nfold@intersec@numcached{5}
+
+\newif\ifpgf@nfold@ontheedge
+\def\pgf@nfold@extendtotip#1#2#3{
+ \ifpgf@nfold@intersectionsnotloaded
+ \pgfutil@packageerror{tikz-nfold}{%
+ If `nfold' is larger than \pgf@nfold@intersec@numcached\space and you use
+ an `Implies' arrow tip you need to say \string\usetikzlibrary{intersections}}{}
+ \else
+ \pgf@nfold@ontheedgetrue
+ \ifnum\pgf@nfold@index>1\relax\ifnum\pgf@nfold@index<\pgf@nfold@order\relax%
+ \pgf@nfold@ontheedgefalse
+ \fi\fi
+ \ifpgf@nfold@ontheedge%
+ \if#1s
+ \pgfpathmoveto{\pgfpointadd{#2}{\pgfpointpolar{#3+90}{\pgf@nfold@shiftamount}}}%
+ \fi
+ \else
+ \ifcsname pgf@nfold@intersec@cache@\the\pgf@nfold@index @\the\pgf@nfold@order\endcsname
+ \pgfextract@process\pgf@nfold@arrowintersect
+ {\csname pgf@nfold@intersec@cache@\the\pgf@nfold@index @\the\pgf@nfold@order\endcsname}%
+ \else
+ \pgfintersectionofpaths{
+ \pgfpathmoveto{\pgfqpoint{-1.4pt}{2.65pt}}
+ \pgfpathcurveto{\pgfqpoint{-0.75pt}{1.25pt}}{\pgfqpoint{1pt}{0.05pt}}{\pgfqpoint{2pt}{0pt}}
+ \pgfpathcurveto{\pgfqpoint{1pt}{-0.05pt}}{\pgfqpoint{-0.75pt}{-1.25pt}}{\pgfqpoint{-1.4pt}{-2.65pt}}
+ }{
+ \pgfpathmoveto{\pgfqpoint{-3pt}{\pgf@nfold@shift@fraction pt}}
+ \pgfpathlineto{\pgfqpoint{3pt}{\pgf@nfold@shift@fraction pt}}
+ }
+ \ifnum\pgfintersectionsolutions>0
+ \pgfextract@process\pgf@nfold@arrowintersect{\pgfpointintersectionsolution{1}}%
+ \immediate\write17{tikz-nfold: computed intersection cache@\the\pgf@nfold@index @\the\pgf@nfold@order: \string\pgfqpoint{\the\pgf@x}{\the\pgf@y}^^J}
+ \expandafter\xdef\csname pgf@nfold@intersec@cache@\the\pgf@nfold@index @\the\pgf@nfold@order\endcsname{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}
+ \else
+ \pgfutil@packagewarning{tikz-nfold}{did not find intersection}
+ \pgfextract@process\pgf@nfold@arrowintersect{\pgfqpoint{0pt}{\pgf@nfold@shift@fraction pt}}%
+ \fi
+ \fi%
+ \begingroup
+ \pgftransformreset
+ \pgftransformshift{#2}
+ \pgftransformrotate{#3}
+ \if#1s
+ \pgftransformxscale{-1}
+ \fi
+ \pgfutil@tempdima=\pgf@nfold@hwidth
+ \pgfutil@tempdima=\pgf@nfold@shift@fraction\pgfutil@tempdima
+ \pgfextract@process\pgf@nfold@startofextension
+ {\pgfpointtransformed{\pgfqpoint{0pt}{\pgfutil@tempdima}}}
+ \pgftransformshift{\pgfqpoint{.42\pgflinewidth}{0pt}}
+ \pgftransformscale{\pgf@nfold@hwidth}
+ \pgfextract@process\pgf@nfold@arrowintersect{\pgfpointtransformed{\pgf@nfold@arrowintersect}}
+ \global\let\pgf@nfold@startofextension\pgf@nfold@startofextension
+ \global\let\pgf@nfold@arrowintersect\pgf@nfold@arrowintersect
+ \endgroup
+ \if#1s
+ \pgfpathmoveto{\pgf@nfold@arrowintersect}
+ \pgfpathlineto{\pgf@nfold@startofextension}
+ \else\if#1e
+ \pgfpathlineto{\pgf@nfold@arrowintersect}
+ \else
+ \pgfutil@packageerror{tikz-nfold}{Invalid argument to \string\pgf@nfold@extendtotip: \meaning#1}{}
+ \fi\fi
+ \pgftransformreset
+ \fi%
+ \fi%
+}
+
+
+\def\pgf@nfold@start@arrowcode{0}
+\def\pgf@nfold@end@arrowcode{0}
+
+\def\pgf@nfold@parsearrows{
+ \ifpgfutil@tempswa%
+ \expandafter\pgf@nfold@parsearrowmacro\pgf@start@tip@sequence\relax
+ \let\pgf@nfold@start@arrowcode\pgf@nfold@detectedarrow
+ \expandafter\pgf@nfold@parsearrowmacro\pgf@end@tip@sequence\relax
+ \let\pgf@nfold@end@arrowcode\pgf@nfold@detectedarrow
+ \else
+ \def\pgf@nfold@start@arrowcode{0}
+ \def\pgf@nfold@end@arrowcode{0}
+ \fi
+}
+
+\def\pgf@nfold@parsearrowmacro#1{%
+ \def\pgf@nfold@detectedarrow{0}
+ \ifx#1\relax
+ \let\pgf@next\relax
+ \else
+ \ifx#1\pgf@arrow@handle
+ \let\pgf@next\pgf@nfold@parse@arrow@handle
+ \else
+ \ifx#1\pgf@arrow@handle@shorthand@empty
+ \let\pgf@next\pgf@nfold@parse@shorthandempty
+ \else
+ \let\pgf@next\pgfutil@gobble@until@relax
+ \fi
+ \fi
+ \fi
+ \pgf@next
+}
+
+\def\pgf@nfold@param@Implies{Implies}
+
+\def\pgf@nfold@parse@arrow@handle#1{%
+ \def\pgf@tmp{#1}
+ \ifx\pgf@tmp\pgf@nfold@param@Implies
+ \def\pgf@nfold@detectedarrow{1}
+ \fi
+ \pgfutil@gobble@until@relax
+}
+
+\def\pgf@nfold@parse@shorthandempty#1{
+ \expandafter\def\expandafter\pgf@tmp\expandafter{#1}
+ \expandafter\pgf@nfold@parsearrowmacro\pgf@tmp\relax
+ \pgfutil@gobble@until@relax
+}
+
+
+
+\newcount\pgf@nfold@order
+\pgf@nfold@order=1
+
+\def\pgf@nfold@preparenfoldpath{%
+ \ifnum\pgf@nfold@order>1\relax
+ \ifdim\pgfinnerlinewidth>0pt\relax
+ \pgfsyssoftpath@getcurrentpath\pgf@nfold@cachedpath%
+ \pgfsyssoftpath@setcurrentpath\pgfutil@empty%
+ \else
+ \pgfutil@packageerror{tikz-nfold}{Must set \string\pgfinnerlinewidth\space to use nfold, e.g. by setting /tikz/double distance}{}
+ \fi
+ \fi
+}
+
+\let\pgf@nfold@old@path@check@proper\pgf@path@check@proper
+\def\pgf@path@check@proper{%
+ \pgf@nfold@old@path@check@proper%
+ \ifpgfutil@tempswa\else%
+ \pgf@nfold@preparenfoldpath%
+ \fi%
+}
+
+\let\pgf@nfold@old@prepare@start@of@path\pgf@prepare@start@of@path
+\def\pgf@prepare@start@of@path{%
+ \pgf@nfold@old@prepare@start@of@path%
+ \pgf@nfold@preparenfoldpath%
+}
+
+\let\pgf@nfold@old@stroke@inner@line\pgf@stroke@inner@line
+\def\pgf@stroke@inner@line{%
+ \ifnum\pgf@nfold@order>1\relax%
+ \pgf@nfold@render@cached@softpath%
+ \else%
+ \pgf@nfold@old@stroke@inner@line%
+ \fi%
+}
+
+
+
+
+\def\pgf@nfold@parsemoveto#1#2{%
+ \ifx\pgf@cur@conn@subpath\pgfutil@empty%
+ \def\pgf@nfold@parser@last@moveto{{#1}{#2}}%
+ \def\pgf@cur@conn@subpath{\relax}%
+ \else%
+ \def\pgf@nfold@macrotoadd{\pgf@nfold@processmoveto{#1}{#2}}%
+ \pgf@nfold@addmacro\pgf@cur@conn@subpath%
+ \pgf@nfold@lastconnsubpathfalse%
+ \pgf@nfold@process@conn@subpath%
+ \let\pgf@nfold@last@closepath@from\pgfutil@empty%
+ \let\pgf@cur@conn@subpath\pgfutil@empty%
+ \pgf@nfold@parser@setupfirst%
+ \def\pgf@nfold@parser@last@moveto{{#1}{#2}}%
+ \fi%
+ \pgf@nfold@parsesoftpath@finish{#1}{#2}%
+}
+
+\def\pgf@nfold@parselineto#1#2{%
+ \def\pgf@nfold@macrotoadd{\pgf@nfold@processlineto{#1}{#2}}%
+ \pgf@nfold@addmacro\pgf@cur@conn@subpath%
+ \pgf@nfold@parsesoftpath@finish{#1}{#2}%
+}
+
+\def\pgf@nfold@parseclosepath#1#2{%
+ \let\pgf@nfold@last@closepath@from\pgf@nfold@parser@previous@pt%
+ \def\pgf@nfold@macrotoadd{\pgf@nfold@processclosepath{#1}{#2}}%
+ \pgf@nfold@addmacro\pgf@cur@conn@subpath%
+ \pgf@nfold@parsesoftpath@finish{#1}{#2}%
+}
+
+\def\pgf@nfold@parsecurveto#1#2{%
+ \edef\pgf@nfold@macrotoadd{\noexpand\pgf@nfold@processcurveto\pgf@nfold@parser@supporta\pgf@nfold@parser@supportb{#1}{#2}}%
+ \pgf@nfold@addmacro\pgf@cur@conn@subpath%
+ \pgf@nfold@parsesoftpath@finish{#1}{#2}%
+}
+
+\def\pgf@nfold@parserect#1#2#3#4{%
+ \pgf@nfold@parsemoveto{#1}{#2}%
+ \pgf@xc=#1\relax
+ \pgf@yc=#2\relax
+ \pgf@xd=#3\relax
+ \pgf@yd=#4\relax
+ \advance\pgf@yc\pgf@yd%
+ \edef\pgf@temp{{\the\pgf@xc}{\the\pgf@yc}}%
+ \expandafter\pgf@nfold@parselineto\pgf@temp%
+ \advance\pgf@xc\pgf@xd%
+ \edef\pgf@temp{{\the\pgf@xc}{\the\pgf@yc}}%
+ \expandafter\pgf@nfold@parselineto\pgf@temp%
+ \advance\pgf@yc-\pgf@yd%
+ \edef\pgf@temp{{\the\pgf@xc}{\the\pgf@yc}}%
+ \expandafter\pgf@nfold@parselineto\pgf@temp%
+ \advance\pgf@xc-\pgf@xd%
+ \edef\pgf@temp{{\the\pgf@xc}{\the\pgf@yc}}%
+ \expandafter\pgf@nfold@parseclosepath\pgf@temp%
+ \pgf@nfold@parsemoveto{#1}{#2}%
+}
+
+
+\def\pgf@nfold@parsesoftpath#1#2{%
+ \let\pgf@cur@conn@subpath\pgfutil@empty%
+ \let\pgf@all@parsed@subpaths\pgfutil@empty%
+ \edef\pgf@nfold@parser@last@moveto{{\the\pgf@path@lastx}{\the\pgf@path@lasty}}%
+ \let\pgf@nfold@last@closepath@from\pgfutil@empty%
+ \pgf@nfold@parser@setupfirst%
+ \expandafter\pgf@nfold@@parsesoftpath#1\pgf@stop{}{}%
+ \let#2\pgf@all@parsed@subpaths%
+}%
+
+\def\pgf@nfold@@parsesoftpath#1#2#3{%
+ \let\pgf@next\pgf@nfold@@parsesoftpath%
+ \ifx#1\pgf@stop%
+ \def\pgf@nfold@macrotoadd{\pgf@nfold@processlast}%
+ \pgf@nfold@addmacro\pgf@cur@conn@subpath%
+ \pgf@nfold@lastconnsubpathtrue%
+ \pgf@nfold@process@conn@subpath%
+ \let\pgf@next\relax%
+ \else%
+ \ifx#1\pgfsyssoftpath@movetotoken%
+ \pgf@nfold@parsemoveto{#2}{#3}%
+ \else%
+ \ifx#1\pgfsyssoftpath@linetotoken%
+ \pgf@nfold@parselineto{#2}{#3}%
+ \else%
+ \ifx#1\pgfsyssoftpath@curvetosupportatoken%
+ \def\pgf@nfold@parser@supporta{{#2}{#3}}%
+ \else%
+ \ifx#1\pgfsyssoftpath@curvetosupportbtoken%
+ \def\pgf@nfold@parser@supportb{{#2}{#3}}%
+ \else%
+ \ifx#1\pgfsyssoftpath@curvetotoken%
+ \pgf@nfold@parsecurveto{#2}{#3}%
+ \else%
+ \ifx#1\pgfsyssoftpath@closepathtoken%
+ \pgf@nfold@parseclosepath{#2}{#3}%
+ \else%
+ \ifx#1\pgfsyssoftpath@rectcornertoken%
+ \def\pgf@nfold@parser@rectcorner{{#2}{#3}}%
+ \else%
+ \ifx#1\pgfsyssoftpath@rectsizetoken%
+ \expandafter\pgf@nfold@parserect\pgf@nfold@parser@rectcorner{#2}{#3}%
+ \else%
+ \pgfutil@packageerror{tikz-nfold}{Unrecognised soft path token `#1'}{}%
+ \fi%
+ \fi%
+ \fi%
+ \fi%
+ \fi%
+ \fi%
+ \fi%
+ \fi%
+ \fi%
+ \pgf@next%
+}%
+
+\def\pgf@nfold@parsesoftpath@finish#1#2{%
+ \def\pgf@nfold@parser@previous@pt{{#1}{#2}}%
+ \let\pgf@nfold@sectolast@segment\pgf@nfold@last@segment%
+ \let\pgf@nfold@last@segment\pgf@nfold@macrotoadd%
+}
+
+\def\pgf@nfold@process@conn@subpath{%
+ \let\pgf@parsed@cur@conn@seg\pgfutil@empty%
+ \ifx\pgf@nfold@last@closepath@from\pgfutil@empty%
+ \expandafter\pgf@nfold@processmoveto\pgf@nfold@parser@last@moveto%
+ \else%
+ \expandafter\pgf@nfold@processmoveto\pgf@nfold@last@closepath@from%
+ \expandafter\pgf@nfold@processinvisibleline\pgf@nfold@parser@last@moveto%
+ \fi%
+ \pgf@cur@conn@subpath%
+ \let\pgf@nfold@macrotoadd\pgf@parsed@cur@conn@seg%
+ \pgf@nfold@addmacro\pgf@all@parsed@subpaths%
+}
+
+
+\def\pgf@nfold@processmoveto#1#2{%
+ \pgf@nfold@process@moveup%
+ \let\pgf@nfold@next@type=m%
+ \let\pgf@nfold@next@visible=0%
+ \edef\pgf@nfold@next@last{\pgf@x#1\pgf@y#2}%
+ \pgf@nfold@process@segment%
+}%
+
+\def\pgf@nfold@process@line@common#1#2#3{%
+ \pgf@nfold@process@moveup%
+ \pgfextract@process\pgf@tmp@tang@i{\pgfpointnormalised{}\global\let\pgf@nfold@tmp\pgf@tmp}
+ \let\pgf@nfold@next@type=#3%
+ \let\pgf@nfold@next@visible=1%
+ \let\pgf@nfold@next@tang@i\pgf@tmp@tang@i
+ \let\pgf@nfold@next@tang@ii\pgf@tmp@tang@i
+ \let\pgf@nfold@next@angle@i\pgf@nfold@tmp
+ \let\pgf@nfold@next@angle@ii\pgf@nfold@tmp
+ \let\pgf@nfold@next@first\pgf@nfold@cur@last
+ \def\pgf@nfold@next@last{\pgf@x#1\pgf@y#2}%
+ \pgf@nfold@process@segment%
+}
+
+\def\pgf@nfold@processlineto#1#2{%
+ \pgf@process{\pgfpointdiff{\pgf@nfold@next@last}{\pgf@x#1\pgf@y#2}}%
+ \pgfpointtaxicabnorm\pgf@xa%
+ \ifdim\pgf@xa>.1pt\relax%
+ \pgf@nfold@process@line@common{#1}{#2}{l}%
+ \fi%
+}%
+
+\def\pgf@nfold@processcurveto#1#2#3#4#5#6{%
+ \pgf@nfold@process@moveup%
+ \pgf@offset@compute@tangents{\pgf@nfold@cur@last}{\pgf@x#1\pgf@y#2}{\pgf@x#3\pgf@y#4}{\pgf@x#5\pgf@y#6}%
+ \let\pgf@nfold@next@type=c%
+ \let\pgf@nfold@next@visible=1%
+ \let\pgf@nfold@next@tang@i=\pgf@tmp@tang@i
+ \let\pgf@nfold@next@tang@ii=\pgf@tmp@tang@ii
+ \let\pgf@nfold@next@angle@i\pgf@tmp@angle@i
+ \let\pgf@nfold@next@angle@ii\pgf@tmp@angle@ii
+ \let\pgf@nfold@next@first\pgf@nfold@cur@last
+ \def\pgf@nfold@next@supporta{\pgf@x#1\pgf@y#2}
+ \def\pgf@nfold@next@supportb{\pgf@x#3\pgf@y#4}
+ \def\pgf@nfold@next@last{\pgf@x#5\pgf@y#6}
+ \pgf@nfold@process@segment%
+}%
+
+\def\pgf@nfold@processclosepath#1#2{%
+ \pgf@process{\pgfpointdiff{\pgf@nfold@next@last}{\pgf@x#1\pgf@y#2}}%
+ \pgfpointtaxicabnorm\pgf@xa%
+ \ifdim\pgf@xa<0.1pt\relax%
+ \pgf@nfold@process@closepath@zerolength{#1}{#2}%
+ \else%
+ \pgf@nfold@process@line@common{#1}{#2}{o}%
+ \fi%
+}%
+
+\def\pgf@nfold@process@closepath@zerolength#1#2{%
+ \pgf@nfold@process@moveup%
+ \let\pgf@nfold@next@type=z%
+ \let\pgf@nfold@next@visible=1%
+ \let\pgf@nfold@next@tang@i\pgf@nfold@connsubpath@tang@i
+ \let\pgf@nfold@next@tang@ii\pgf@nfold@connsubpath@tang@i
+ \let\pgf@nfold@next@angle@i\pgf@nfold@connsubpath@angle@i
+ \let\pgf@nfold@next@angle@ii\pgf@nfold@connsubpath@angle@i
+ \let\pgf@nfold@next@first\pgf@nfold@cur@last
+ \def\pgf@nfold@next@last{\pgf@x#1\pgf@y#2}%
+ \pgf@nfold@process@segment%
+}
+
+\def\pgf@nfold@processinvisibleline#1#2{%
+ \pgf@process{\pgfpointdiff{\pgf@nfold@next@last}{\pgf@x#1\pgf@y#2}}%
+ \pgfpointtaxicabnorm\pgf@xa%
+ \ifdim\pgf@xa>.1pt\relax%
+ \pgf@nfold@process@line@common{#1}{#2}{i}%
+ \else%
+ \begingroup%
+ \let\pgf@nfold@process@segment\relax%
+ \pgf@nfold@sectolast@segment%
+ \global\let\pgf@nfold@tmp\pgf@nfold@next@tang@ii%
+ \endgroup%
+ \pgfextract@process\pgf@nfold@next@first{\pgfpointdiff{\pgf@nfold@tmp}{\pgfqpoint{#1}{#2}}}%
+ \pgf@nfold@tmp%
+ \pgf@nfold@process@line@common{#1}{#2}{i}%
+ \fi%
+}%
+
+\def\pgf@nfold@processlast{%
+ \pgf@nfold@process@moveup%
+ \let\pgf@nfold@next@type=t%
+ \let\pgf@nfold@next@visible=0%
+ \pgf@nfold@process@segment%
+}
+
+\def\pgf@nfold@addmacro#1{%
+ \expandafter\expandafter\expandafter\gdef%
+ \expandafter\expandafter\expandafter#1%
+ \expandafter\expandafter\expandafter{%
+ \expandafter#1\pgf@nfold@macrotoadd}%
+}
+
+
+
+\def\pgf@nfold@token@lineto#1#2#3{%
+ \pgfoffsetline@{#1}{#2}{\pgf@nfold@shiftamount}{#3}%
+}
+
+\def\pgf@nfold@token@lineto@continue#1#2#3{%
+ \pgfoffsetlinenomove@{#1}{#2}{\pgf@nfold@shiftamount}{#3}%
+}
+
+\def\pgf@nfold@token@invisibleline#1#2#3{%
+ \pgfqpointscale{\pgf@nfold@shiftamount}{#3}%
+ \pgf@xc=-\pgf@y%
+ \pgf@y=\pgf@x%
+ \pgf@x=\pgf@xc%
+ \pgfpathmoveto{\pgfpointadd{}{#2}}%
+}
+
+\def\pgf@nfold@token@curveto#1#2#3#4#5#6{%
+ \def\pgf@tmp@tang@i{#5}%
+ \def\pgf@tmp@tang@ii{#6}%
+ \pgf@offset@bezier@segment@{#1}{#2}{#3}{#4}{\pgf@nfold@shiftamount}%
+ \pgfpathmoveto{\pgf@bezier@offset@i}%
+ \pgfpathcurveto{\pgf@bezier@offset@ii}{\pgf@bezier@offset@iii}{\pgf@bezier@offset@iv}%
+}
+
+\def\pgf@nfold@token@curveto@continue#1#2#3#4#5#6{%
+ \def\pgf@tmp@tang@i{#5}%
+ \def\pgf@tmp@tang@ii{#6}%
+ \pgf@offset@bezier@segment@{#1}{#2}{#3}{#4}{\pgf@nfold@shiftamount}%
+ \pgfpathcurveto{\pgf@bezier@offset@ii}{\pgf@bezier@offset@iii}{\pgf@bezier@offset@iv}%
+}
+
+\def\pgf@nfold@token@closepath{%
+ \pgfpathclose%
+}
+
+\def\pgf@nfold@token@edgecase@movetostart#1#2{%
+ \pgfpathmoveto{\pgfpointadd%
+ {#1}{\pgfpointpolar{#2+90}{\pgf@nfold@shiftamount}}}%
+}
+
+
+\def\pgf@nfold@parser@setupfirst{%
+ \let\pgf@nfold@next@type=f%
+ \let\pgf@nfold@next@visible=0%
+ \edef\pgf@nfold@next@last{\pgf@x\the\pgf@path@lastx\pgf@y\the\pgf@path@lasty}%
+}
+
+\def\pgf@nfold@clampangle{
+ \ifdim\pgfmathresult pt<-180pt\relax
+ \pgfutil@tempdima=\pgfmathresult pt
+ \advance\pgfutil@tempdima by 360pt
+ \edef\pgfmathresult{\pgf@sys@tonumber\pgfutil@tempdima}
+ \else\ifdim\pgfmathresult pt>180pt\relax
+ \pgfutil@tempdima=\pgfmathresult pt
+ \advance\pgfutil@tempdima by -360pt
+ \edef\pgfmathresult{\pgf@sys@tonumber\pgfutil@tempdima}
+ \fi\fi
+}
+
+
+\def\pgf@nfold@process@moveup{%
+ \let\pgf@nfold@prev@type\pgf@nfold@cur@type%
+ \let\pgf@nfold@prev@visible\pgf@nfold@cur@visible%
+ \let\pgf@nfold@prev@tang@i\pgf@nfold@cur@tang@i%
+ \let\pgf@nfold@prev@tang@ii\pgf@nfold@cur@tang@ii%
+ \let\pgf@nfold@prev@angle@i\pgf@nfold@cur@angle@i%
+ \let\pgf@nfold@prev@angle@ii\pgf@nfold@cur@angle@ii%
+ \let\pgf@nfold@prev@first\pgf@nfold@cur@first%
+ \let\pgf@nfold@prev@supporta\pgf@nfold@cur@supporta%
+ \let\pgf@nfold@prev@supportb\pgf@nfold@cur@supportb%
+ \let\pgf@nfold@prev@last\pgf@nfold@cur@last%
+ \let\pgf@nfold@cur@type\pgf@nfold@next@type%
+ \let\pgf@nfold@cur@visible\pgf@nfold@next@visible%
+ \let\pgf@nfold@cur@tang@i\pgf@nfold@next@tang@i%
+ \let\pgf@nfold@cur@tang@ii\pgf@nfold@next@tang@ii%
+ \let\pgf@nfold@cur@angle@i\pgf@nfold@next@angle@i%
+ \let\pgf@nfold@cur@angle@ii\pgf@nfold@next@angle@ii
+ \let\pgf@nfold@cur@first\pgf@nfold@next@first%
+ \let\pgf@nfold@cur@supporta\pgf@nfold@next@supporta%
+ \let\pgf@nfold@cur@supportb\pgf@nfold@next@supportb%
+ \let\pgf@nfold@cur@last\pgf@nfold@next@last%
+}
+
+
+\def\pgfoffsetpath#1#2{%
+ \begingroup
+ \pgfmathsetlengthmacro\pgf@nfold@parsed@hwidth{#2}
+ \pgf@x=\pgf@nfold@parsed@hwidth\relax
+ \ifdim\pgf@x<0pt\relax
+ \pgf@x=-\pgf@x
+ \def\pgf@nfold@shift@fraction{-1}
+ \else
+ \def\pgf@nfold@shift@fraction{1}
+ \fi
+ \edef\pgf@nfold@parsed@hwidth{\the\pgf@x}
+ \pgfoffsetpathqfraction{#1}{\pgf@nfold@parsed@hwidth}{\pgf@nfold@shift@fraction}
+ \endgroup
+}
+
+\def\pgfoffsetpathfraction#1#2#3{%
+ \begingroup
+ \pgfmathsetlengthmacro\pgf@nfold@parsed@hwidth{#2}
+ \pgfmathsetmacro\pgf@nfold@shift@fraction{#3}
+ \pgfoffsetpathqfraction{#1}{\pgf@nfold@parsed@hwidth}{\pgf@nfold@shift@fraction}
+ \endgroup
+}
+
+\def\pgfoffsetpathindex#1#2#3#4{%
+ \begingroup
+ \pgfmathsetmacro\pgf@nfold@shift@fraction{-1+2*(#3-1)/(#4-1)}
+ \pgfoffsetpathqfraction{#1}{#2}{\pgf@nfold@shift@fraction}
+ \endgroup
+}
+
+\def\pgfoffsetpathqfraction#1#2#3{%
+ \begingroup
+ \pgf@x=#2\relax
+ \edef\pgf@nfold@hwidth{\the\pgf@x}
+ \edef\pgf@nfold@shift@fraction{#3}
+ \pgf@x=\pgf@nfold@shift@fraction\pgf@x\relax
+ \edef\pgf@nfold@shiftamount{\pgf@sys@tonumber\pgf@x}
+ \pgfprocessround{#1}{\pgf@nfold@cachedpath}%
+ \pgf@nfold@parsesoftpath{\pgf@nfold@cachedpath}{\parsedpath}%
+ \pgftransformreset%
+ \parsedpath%
+ \endgroup
+}
+
+\endinput
diff --git a/Master/texmf-dist/tex/latex/tikz-nfold/tikzlibrarynfold.code.tex b/Master/texmf-dist/tex/latex/tikz-nfold/tikzlibrarynfold.code.tex
index 342191b0ad7..799fa6b4d97 100644
--- a/Master/texmf-dist/tex/latex/tikz-nfold/tikzlibrarynfold.code.tex
+++ b/Master/texmf-dist/tex/latex/tikz-nfold/tikzlibrarynfold.code.tex
@@ -1,4 +1,4 @@
-%% tikz-nfold.sty
+%% tikzlibrarynfold.code.tex
%% Copyright 2023 Jonathan Schulz
%
% This work may be distributed and/or modified under the
@@ -13,1312 +13,30 @@
%
% The Current Maintainer of this work is Jonathan Schulz.
%
-% This work consists of the files pgflibrarybezieroffset.code.tex,
-% tikzlibrarynfold.code.tex, tikz-nfold-doc.tex, and tikz-nfold-doc.pdf.
-
-\usetikzlibrary{arrows.meta}
-\usepgflibrary{bezieroffset}
-
-
-%
-% General idea
-% ============
-%
-% In order to offset a path, we must first analyse and slightly modify it. For example,
-% the start and end points of segments need to be relocated slightly in order to make room
-% for the joins, and most curves must be subdivided for the offsetting algorithm. To avoid
-% redundant computations in n-fold paths, we pre-compute as much data as possible and store
-% all this information in a "parsed path" macro. The structure of the parsed path resembles
-% the structure of a pgf softpath, but it consists of different tokens.
-%
-
-
-
-%
-% Intercepting join settings
-% --------------------------
-%
-% The current settings of the line joins are not stored in any TeX registers; instead, direct system
-% calls are made to apply the settings. Therefore, we need to modify the pgf macros in order
-% to cache the current settings.
-%
-
-% According to the pgf documentation, miter limit=10 is the default value,
-% but I couldn't find and verify this setting in the pgf code
-\gdef\pgf@nfold@cached@miterlimit{10}
-\let\pgf@nfold@old@miterlimit\pgfsetmiterlimit
-\def\pgfsetmiterlimit#1{%
- \pgf@nfold@old@miterlimit{#1}%
- \edef\pgf@nfold@cached@miterlimit{#1}%
-}
-
-% default line join is "miter"
-\global\let\pgf@cached@linejoin=m% % b = bevel, m=miter, r=round
-\let\pgf@nfold@old@setbeveljoin\pgfsetbeveljoin
-\let\pgf@nfold@old@setmiterjoin\pgfsetmiterjoin
-\let\pgf@nfold@old@setroundjoin\pgfsetroundjoin
-\def\pgfsetbeveljoin{%
- \pgf@nfold@old@setbeveljoin%
- % do NOT change this globally! Needs to be changed back at the end of groups for scoping reasons
- \let\pgf@cached@linejoin=b%
-}
-\def\pgfsetmiterjoin{%
- \pgf@nfold@old@setmiterjoin%
- \let\pgf@cached@linejoin=m%
-}
-\def\pgfsetroundjoin{%
- \pgf@nfold@old@setroundjoin%
- \let\pgf@cached@linejoin=r%
-}
-
-
-%
-% Joining offset lines
-% --------------------
-%
-% One of the more difficult aspects is joining the segments of an offset path. Without this step,
-% the path would be interrupted or self-intersect whenever there is a non-zero angle between
-% two segments. This code reproduces the existing line joins "bevel", "miter" and "round".
-%
-
-\def\pgf@nfold@miterjoin{
- % The tip of the miter join is computed starting from the original (unshifted) centre of the join;
- % we then move orthorgonal to the average of the old and new angle
- \pgfpathlineto{
- \pgfpointadd{\pgf@nfold@join@centre}{%
- \pgfpointpolar{\pgf@nfold@firstang+.5*\pgf@nfold@deltaphi+90}% do not change
- {\pgf@nfold@shiftamount/cos(.5*\pgf@nfold@deltaphi)}%
- }%
- }%
-}
-
-\def\pgf@nfold@beveljoin{
- % The bevel join for one component line consists of three parts:
- % 1) an extension of the ingoing line,
- % 2) a middle line, angled at the average of the incoming and outgoing line,
- % 3) an extension of the outgoing line.
- % Different components of the ingoing and outgoing lines have a constant distance from each other.
- % For a good-looking output, the mittle parts of the component lines thus should also have a constant distance,
- % which is a non-trivial condition. To generate such an output the outer lines get a bevel-like join
- % and the inner lines get a miter-like join; the threshold depends on deltaphi.
- % We first compute by how much the outermost line must be continued from the beginning of the join.
- % The protrusion amount must be lowered by a little bit for a rather complicated reason: The offset would be
- % dead on if the outermost offset line were centered on the _edge_ of the wide line, but we want to draw
- % the outside line _fully inside_ the wide line. The factor of tan(deltaphi/4) can be derived, but is not obvious.
- \pgfmathsetlengthmacro{\bevelouterprotrusion}%
- {\pgf@nfold@shortenstartjoin pt - .5*\pgflinewidth*abs(tan(.25*\pgf@nfold@deltaphi))}
- % The following applies to middle lines only: We compute by how much they need to be shortened so the distance
- % between the lines in the join is correct.
- \pgfmathsetmacro{\bevelshorten}{2*\insidepercentage*abs(tan(.25*\pgf@nfold@deltaphi))}
- % This threshold decides if the inside line has a bevel or a miter join
- \pgfmathparse{\bevelshorten < abs(sin(.5*\pgf@nfold@deltaphi))}
- \ifnum\pgfmathresult=1\relax
- \pgfmathsetlengthmacro{\bevelextension}{\bevelouterprotrusion-\bevelshorten*\pgf@nfold@hwidth}
- \pgfpointadd{\pgf@nfold@join@start}{\pgfpointpolar{\pgf@nfold@firstang}{\bevelextension}}
- \pgfpathlineto{}
- \pgfpointadd{\pgf@nfold@join@end}{\pgfpointpolar{\pgf@nfold@secondang}{-\bevelextension}}
- \pgfpathlineto{}
- \else
- \pgf@nfold@miterjoin
- \fi
-}
-
-\def\pgf@nfold@roundjoin{
- % The outer half of the lines get arcs, the others get miters
- \ifdim\insidepercentage pt<.5pt\relax
- \pgfpointadd{\pgf@nfold@join@start}{\pgfpointpolar{\pgf@nfold@firstang}{\pgf@nfold@shortenstartjoin}}
- \pgfpathlineto{}
- % TODO needs unit tests for all cases left, right, across the 360 gap etc.
- \pgfmathsetmacro\pgf@tmp@firstang{\pgf@nfold@firstang+90*\turnindicator}
- \pgfpatharc%
- {\pgf@tmp@firstang}%
- {\pgf@tmp@firstang+\pgf@nfold@deltaphi}%
- {abs(\pgf@nfold@shift@fraction)*\pgf@nfold@hwidth}%
- \else
- \pgf@nfold@miterjoin
- \fi
-}
-
-% The handler that will be added to the parsed path
-% #1: The centre of the join
-% #2: The end point of the first segment
-% #3: The starting point of the second segment
-% #4: The angle of the first segment
-% #5: The angle of the second segment
-% #6: deltaphi in the range [-180, 180]
-% #7: the distance between #1 and #2
-% #8: the join + finish macro
-\def\pgf@nfold@token@join#1#2#3#4#5#6#7#8{%
- \def\pgf@nfold@join@centre{#1}%
- \def\pgf@nfold@join@prevend{#2}%
- \def\pgf@nfold@join@nextstart{#3}%
- \def\pgf@nfold@firstang{#4}%
- \def\pgf@nfold@secondang{#5}%
- % Offset the start and end of this join
- \pgfextract@process\pgf@nfold@join@start{%
- \pgfpointadd{#2}{\pgfpointpolar{\pgf@nfold@firstang+90}{\pgf@nfold@shiftamount}}}%
- \pgfextract@process\pgf@nfold@join@end{%
- \pgfpointadd{#3}{\pgfpointpolar{\pgf@nfold@secondang+90}{\pgf@nfold@shiftamount}}}%
- \pgf@process{\pgfpointdiff{\pgf@nfold@join@start}{\pgf@nfold@join@end}}
- % Check if the start of this segment is very close to the end of the previous segment.
- % In that case we don't need a join at all
- \pgfpointtaxicabnorm\pgfutil@tempdima
- \ifdim\pgfutil@tempdima>0.1pt\relax
- \def\pgf@nfold@deltaphi{#6}%
- \def\pgf@nfold@shortenstartjoin{#7}%
- % First step: Check if left or right turn (-1=left, 1=right)
- \ifdim\pgf@nfold@deltaphi pt<0pt
- \def\turnindicator{1}
- \else
- \def\turnindicator{-1}
- \fi
- % \insidepercentage: between 0.0 and 1.0;
- % 0=no distance to cover in the join, 1=maximum distance to cover
- \pgfutil@tempdima=\pgf@nfold@shift@fraction pt\relax
- \pgfutil@tempdima=\turnindicator\pgfutil@tempdima
- \advance\pgfutil@tempdima by-1pt\relax
- \pgfutil@tempdima=-.5\pgfutil@tempdima
- % \insidepercentage = .5 * (1 - \turnindicator*\pgf@nfold@shift@fraction)
- \edef\insidepercentage{\pgf@sys@tonumber\pgfutil@tempdima}%
- #8%
- \fi
-}
-
-
-%
-% Parser: Join handler
-%
-\def\pgf@nfold@parser@handlejoin{%
- % \pgf@xa := abs(deltaphi@start)
- \pgf@xa=\pgf@nfold@deltaphi@start pt\relax
- \ifdim\pgf@xa<0pt\relax
- \pgf@xa=-\pgf@xa
- \fi
- % Skip the entire join if abs(deltaphi) is too small
- \ifdim\pgf@xa>1pt\relax
- \edef\pgf@nfold@jointype{\pgf@cached@linejoin}
- \if\pgf@cached@linejoin m% \ifx is not needed because both are only one character
- % miter join
- % First we implement the miter limit: If the angle is too sharp, the miter join is replaced
- % by a bevel join. This is controlled by /tikz/miter limit=..., initially 10.
- \pgf@xa=.5\pgf@xa
- \pgfmathcos@{\pgf@sys@tonumber\pgf@xa}
- \pgf@xa=\pgfmathresult pt\relax
- \pgf@xa=\pgf@nfold@cached@miterlimit\pgf@xa
- % Switch to bevel if miterlimit*cos(.5*abs(deltaphi)) <= 1
- \ifdim\pgf@xa>1pt\relax
- \def\pgf@nfold@tmp@joinmacro{\pgf@nfold@miterjoin}
- \else
- \def\pgf@nfold@tmp@joinmacro{\pgf@nfold@beveljoin}
- \fi
- \else
- \if b\pgf@cached@linejoin\relax
- \def\pgf@nfold@tmp@joinmacro{\pgf@nfold@beveljoin}
- \else
- \def\pgf@nfold@tmp@joinmacro{\pgf@nfold@roundjoin}
- \fi
- \fi
- % The last parameter is a macro to be called when this segment of the join is non-trivial.
- % It consists of
- % - the macro to actually draw the join,
- % - either finish@normal or finish@edgecase.
- \edef\pgf@nfold@macrotoadd{%
- \noexpand\pgf@nfold@token@join{\pgf@nfold@cur@first}{\pgf@nfold@prev@segment@end}
- {\pgf@nfold@cur@movedfirst}{\pgf@nfold@prev@angle@ii}{\pgf@nfold@cur@angle@i}%
- {\pgf@nfold@deltaphi@start}{\pgf@nfold@shortenstartjoin}{%
- \expandafter\noexpand\pgf@nfold@tmp@joinmacro%
- \expandafter\noexpand\ifpgf@nfold@closejoinsedgecase%
- \pgf@nfold@token@finish@edgecase{\pgf@nfold@cur@movedlast}%
- \else%
- \pgf@nfold@token@finish@normal%
- \fi%
- }%
- }%
- \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
- \fi% end if abs(deltaphi) > 1
-}
-
-
-% All non-trivial joins connect to the end of the join, which is the starting point of the next segment.
-% Note that this entire macro is skipped by if the start and end of the join coincide, so we never create a zero length segment here.
-%
-% There is one edge case here: If two subsequent joins are so close that \pgf@nfold@cur@movedlast
-% and \pgf@nfold@cur@movedfirst exchange places *and* we are on the outside of the first join
-% (implying that we are on the inside of the second join), the first join must not connect all the way to
-% to \pgf@nfold@cur@movedfirst, because that would overshoot the second join. Instead we connect to
-% \pgf@nfold@cur@movedlast (which is *closer* to the first join than \pgf@nfold@cur@movedfirst in this edge case).
-% To accomodate for the vertical offset we connect to \pgf@nfold@join@end which is the vertical
-% offset of \pgf@nfold@cur@movedlast by definition.
-\def\pgf@nfold@token@finish@normal{%
- \pgfpathlineto{\pgf@nfold@join@end}%
-}
-
-% parameter #1: @movedlast of the next segment
-\def\pgf@nfold@token@finish@edgecase#1{%
- \pgf@nfold@join@end%
- \ifdim\insidepercentage pt<.5pt\relax%
- \pgf@process{\pgfpointadd{#1}{\pgfpointpolar{\pgf@nfold@secondang+90}{\pgf@nfold@shiftamount}}}
- \fi%
- \pgfpathlineto{}%
-}
-
-
-%
-% Main rendering pipeline
-% -----------------------
-%
-
-% This stores whether the current segment should begin with a moveto to its offset
-\newif\ifpgf@nfold@continuesegment
-% This stores whether we are in some edge case of very close joins, see below for details
-\newif\ifpgf@nfold@closejoinsedgecase
-% This stores whether we are in an error case where we need to avoid dividing by zero
-\newif\ifpgf@nfold@angletoosharp
-% This stores whether we need the intersections library for an arrow tip but it is not loaded
-\newif\ifpgf@nfold@intersectionsnotloaded
-% This stores whether the currently processed connected sub-path is the final one on this path
-\newif\ifpgf@nfold@lastconnsubpath
-
-
-\def\pgf@nfold@parser@handlesegment{%
- \if\pgf@nfold@cur@visible0
- % first, last and moveto are invisible
- \if\pgf@nfold@cur@type m
- % We don't need to do anything for a moveto; if a visible segment follows, it will move to
- % its starting location by itself. However, we might need to draw the arrow tip extension
- % at the start (if present).
- % Draw a tip extension only if all of the following conditions are met:
- % 1. There is an Implies tip at the start of this path
- % 2. We are currently on the last connected sub-path of this path
- % 3. The next segment is visible
- % 4. This moveto is the first segment on this path
- \if\pgf@nfold@start@arrowcode1
- \ifpgf@nfold@lastconnsubpath
- \if\pgf@nfold@prev@type f
- \if\pgf@nfold@next@visible1
- \edef\pgf@nfold@macrotoadd{%
- \noexpand\pgf@nfold@extendtotip{s}{\pgf@nfold@cur@last}{\pgf@nfold@next@angle@i}
- }%
- \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
- % hack: We make the next segment believe that this segment was a lineto
- % so the path does not get interrupted
- \let\pgf@nfold@cur@type l
- \let\pgf@nfold@cur@visible1
- \let\pgf@nfold@cur@angle@ii\pgf@nfold@next@angle@i
- \let\pgf@nfold@cur@tang@ii\pgf@nfold@next@tang@i
- \def\pgf@nfold@deltaphi@end{0}
- \pgf@nfold@angletoosharpfalse
- \fi
- \fi%
- \fi
- \fi
- \fi%
- \else%
- \let\pgf@nfold@cur@movedfirst\pgf@nfold@cur@first
- \let\pgf@nfold@cur@movedlast\pgf@nfold@cur@last
- %%% Step 1: Make room for joins if necessary
- % In order to make room for the join, it may be necessary to shorten the current segment
- % at the start and/or the end. In here we store by how much the segment needs to be shortened.
- \def\pgf@nfold@shortenstartjoin{0}
- \def\pgf@nfold@shortenendjoin{0}
- \pgf@nfold@closejoinsedgecasefalse
- % Step 1.1: Make room for the join at the start if needed
- \if\pgf@nfold@prev@visible0
- \pgf@nfold@continuesegmentfalse
- \else
- \pgf@nfold@continuesegmenttrue
- % deltaphi@start can be recycled from deltaphi@end;
- % \ifpgf@nfold@angletoosharp is also still set
- \let\pgf@nfold@deltaphi@start\pgf@nfold@deltaphi@end
- % set \pgf@xb := abs(deltaphi@start)
- \pgf@xb=\pgf@nfold@deltaphi@start pt\relax
- \ifdim\pgf@xb<0pt\relax
- \pgf@xb=-\pgf@xb
- \fi
- \ifpgf@nfold@angletoosharp\else
- \ifdim\pgf@xb>0.5pt\relax
- % make room for the start join if the angle is nonzero;
- % shortenstartjoin := hwidth*tan(.5*abs(deltaphi@start))
- \pgf@yb=.5\pgf@xb
- \pgfmathtan@{\pgf@sys@tonumber\pgf@yb}
- \pgf@yb=\pgf@nfold@hwidth\relax
- \pgf@yb=\pgfmathresult\pgf@yb
- \edef\pgf@nfold@shortenstartjoin{\pgf@sys@tonumber\pgf@yb}
- \pgfextract@process\pgf@nfold@cur@movedfirst{%
- \pgfpointadd{\pgf@nfold@cur@first}%
- {\pgfqpointscale{\pgf@nfold@shortenstartjoin}{\pgf@nfold@cur@tang@i}}}%
- % If the current segment is a curve, we need to relocate @supporta point as well,
- % as otherwise the @first point could overtake it
- \if\pgf@nfold@cur@type c
- \pgf@process{\pgfpointdiff{\pgf@nfold@cur@first}{\pgf@nfold@cur@supporta}}
- \pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}
- \ifdim\pgfmathresult pt>0.1pt\relax
- % regular curves (supporta != first):
- % Increase dist(first, supporta) to sqrt(a^2 + b^2) where a=dist(first, supporta) and b=shortenstart. This way, the order of first and supporta is guaranteed to be preserved, and the change to supporta is as small as reasonably possible.
- \pgfmathveclen@{\pgfmathresult}{\pgf@sys@tonumber\pgf@yb}
- \pgfextract@process\pgf@nfold@cur@supporta{\pgfpointadd%
- {\pgf@nfold@cur@first}%
- {\pgfqpointscale{\pgfmathresult}{\pgf@nfold@cur@tang@i}}}%
- \else
- % special treatment for singular curves (supporta = first) to avoid rounding error glitches.
- % In this special case, a slight corner at the end of the join is unavoidable unless we
- % also relocate @supportb, which may have unintended side effects
- \let\pgf@nfold@cur@supporta\pgf@nfold@cur@movedfirst
- \fi
- \fi
- \fi
- \fi
- \fi
- % Step 1.2: Make room for the join at the end if needed
- \if\pgf@nfold@next@visible1
- % Compute the angle difference at the end (between -180 and +180 degrees)
- % using \pgfmathsubtract@ is more readable and no less efficient than computing this manually
- \pgfmathsubtract@{\pgf@nfold@next@angle@i}{\pgf@nfold@cur@angle@ii}
- \pgf@nfold@clampangle
- % Edge case handling: If the next segment is a closepath and has length zero, deltaphi is set
- % to zero to prevent glitches (a zero length segment has no well-defined angle anyway)
- \edef\pgf@nfold@deltaphi@end{\pgfmathresult}
- \pgf@xb=\pgf@nfold@deltaphi@end pt\relax
- \ifdim\pgf@xb<0pt\relax
- \pgf@xb=-\pgf@xb
- \fi
- \ifdim\pgf@xb>178pt\relax
- \pgfutil@packagewarning{tikz-nfold}{Angle too sharp, expect visual errors}
- \pgf@nfold@angletoosharptrue
- \else
- \pgf@nfold@angletoosharpfalse
- \ifdim\pgf@xb>0.5pt\relax
- % make room for the start join if the angle is nonzero
- % shortenendjoin := hwidth*tan(.5*abs(deltaphi@end))
- \pgf@yb=.5\pgf@xb
- \pgfmathtan@{\pgf@sys@tonumber\pgf@yb}
- \pgf@yb=\pgf@nfold@hwidth\relax
- \pgf@yb=\pgfmathresult\pgf@yb
- \edef\pgf@nfold@shortenendjoin{\pgf@sys@tonumber\pgf@yb}
- \pgf@yb=-\pgf@yb
- \pgfextract@process\pgf@nfold@cur@movedlast{%
- % the use of the minus sign is fine here because \pgf@nfold@shortenendjoin >= 0.0
- \pgfpointadd{\pgf@nfold@cur@last}%
- {\pgfqpointscale{-\pgf@nfold@shortenendjoin}{\pgf@nfold@cur@tang@ii}}}%
- \pgfextract@process\pgf@nfold@cur@movedlast{%
- \pgfpointadd{\pgf@nfold@cur@last}%
- {\pgfqpointpolar{\pgf@nfold@cur@angle@ii}{\pgf@yb}}}%
- \if\pgf@nfold@cur@type c
- % Same procedure as above: relocate supportb if we have a curve
- \pgf@process{\pgfpointdiff{\pgf@nfold@cur@supportb}{\pgf@nfold@cur@last}}
- \pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}
- \ifdim\pgfmathresult pt>0.1pt\relax
- \pgfmathveclen@{\pgfmathresult}{\pgf@sys@tonumber\pgf@yb}
- \pgfextract@process\pgf@nfold@cur@supportb{\pgfpointadd%
- {\pgf@nfold@cur@last}%
- % can use qpointscale and a minus because \pgfmathresult is guaranteed to be positive
- {\pgfqpointscale{-\pgfmathresult}{\pgf@nfold@cur@tang@ii}}}%
- \else
- \let\pgf@nfold@cur@supportb\pgf@nfold@cur@movedlast
- \fi
- \fi
- \fi
- \fi
- % Step 1.3: Detect an edge case
- % This edge case appears whenever the current segment is such a short line that we would
- % have to reduce its length to less than zero to make room for the joins. In such cases,
- % the line is not drawn at all, and slight modifications must be made to the joins to ensure
- % a correct output (i.e. one join is immediately followed by the next without a segment in between).
- %
- % This edge case can appear for curves as well, but they are much harder to deal with.
- \if\pgf@nfold@cur@type l
- % No need to check for \pgf@nfold@inputsegmentclosepath as it should not be followed by any further segments
- % Now: Check if the total amount of shortening is larger than the length of the segment
- \pgf@process{\pgfpointdiff{\pgf@nfold@cur@first}{\pgf@nfold@cur@last}}
- \pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}
- \pgf@xa=\pgf@nfold@shortenstartjoin pt\relax
- \advance\pgf@xa by\pgf@nfold@shortenendjoin pt\relax
- \ifdim\pgf@xa>\pgfmathresult pt\relax
- \pgf@nfold@closejoinsedgecasetrue
- \fi
- \fi
- \fi% end if next segment visible
- %
- % Step 2.1: Draw the join at the start if applicable
- %
- \if\pgf@nfold@prev@visible0%
- \ifpgf@nfold@closejoinsedgecase
- % If the previous segment is a moveto and the current segment is a "close joins" edge case,
- % nothing needs to be drawn here (the relevant draw call will be made at the join of the subsequent
- % segment). We must therefore make sure that we move to the correct end point of this segment.
- % Counterintuitively, this is given by the offset of \pgf@nfold@cur@movedFIRST since the start and end
- % are reversed in the edge case.
- \edef\pgf@nfold@macrotoadd{%
- \noexpand\pgf@nfold@token@edgecase@movetostart{\pgf@nfold@cur@movedfirst}{\pgf@nfold@cur@angle@i}%
- }%
- \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
- \fi
- \else
- % If we draw the join when the start angle is close to 180 degrees, we get a division by zero
- \ifpgf@nfold@angletoosharp\else
- \if\pgf@nfold@cur@type z\else
- \pgf@nfold@parser@handlejoin
- \fi
- \fi
- \fi
- % Step 2.2: Store information that may be needed later
- % Step 2.2.1: Store where the current (non-offset) end point was relocated
- % in order to make space for the end join. This may be used if the next
- % segment begins with a join
- \let\pgf@nfold@prev@segment@end\pgf@nfold@cur@movedlast
- % Step 2.2.2: Store the tangent of the first proper segment of closed path.
- % This is needed in case the \pgfpathclose-segment has length zero,
- % since in that case its tangent cannot be computed.
- \if\pgf@nfold@cur@type i
- \let\pgf@nfold@connsubpath@tang@i\pgf@nfold@next@tang@i%
- \let\pgf@nfold@connsubpath@angle@i\pgf@nfold@next@angle@i%
- \fi
- %
- % Step 3: Draw the new segment.
- %
- % The value of \ifpgf@nfold@continuesegment decides whether we start with a moveto.
- \if\pgf@nfold@cur@type l
- % In the edge case, one join is followed immediately by the next. The line segment
- % thus has a negative length and will be skipped.
- \ifpgf@nfold@closejoinsedgecase\else
- \edef\pgf@nfold@macrotoadd{%
- \expandafter\noexpand\ifpgf@nfold@continuesegment%
- \pgf@nfold@token@lineto@continue%
- \else%
- \pgf@nfold@token@lineto%
- \fi{\pgf@nfold@cur@movedfirst}{\pgf@nfold@cur@movedlast}{\pgf@nfold@cur@tang@i}%
- }%
- \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
- \fi
- \fi
- \if\pgf@nfold@cur@type o
- \def\pgf@nfold@macrotoadd{\pgf@nfold@token@closepath}%
- \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
- \fi
- \if\pgf@nfold@cur@type z
- % zero and non-zero closepath's differ in the join handling, but are identical in rendering
- \def\pgf@nfold@macrotoadd{\pgf@nfold@token@closepath}%
- \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
- \fi
- \if\pgf@nfold@cur@type c
- \ifpgf@nfold@continuesegment
- \pgf@subdividecurve{\pgf@nfold@cur@movedfirst}{\pgf@nfold@cur@supporta}{\pgf@nfold@cur@supportb}{\pgf@nfold@cur@movedlast}{\pgf@offset@max@recursion}{0}{\pgf@nfold@addcurvesegment@callback@continue}
- \else
- \pgf@subdividecurve{\pgf@nfold@cur@movedfirst}{\pgf@nfold@cur@supporta}{\pgf@nfold@cur@supportb}{\pgf@nfold@cur@movedlast}{\pgf@offset@max@recursion}{0}{\pgf@nfold@addcurvesegment@callback}%
- \fi
- \fi
- \if\pgf@nfold@cur@type i
- \edef\pgf@nfold@macrotoadd{%
- \noexpand\pgf@nfold@token@invisibleline{\pgf@nfold@cur@movedfirst}{\pgf@nfold@cur@movedlast}{\pgf@nfold@cur@tang@i}%
- }%
- \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
- \fi
- % Step 4: Extend into the arrow tip at the end (if present)
- \if\pgf@nfold@next@type t%
- \ifnum\pgf@nfold@end@arrowcode=1
- \edef\pgf@nfold@macrotoadd{%
- \noexpand\pgf@nfold@extendtotip{e}{\pgf@nfold@cur@last}{\pgf@nfold@cur@angle@ii}}%
- \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
- \fi%
- \fi%
- \fi% end if current visible
-}
-
-
-\def\pgf@nfold@addcurvesegment@callback#1#2#3#4#5{%
- \if#50%
- \edef\pgf@nfold@macrotoadd{%
- % The subdivision algorithm has already computed the tangents
- \noexpand\pgf@nfold@token@curveto{#1}{#2}{#3}{#4}{\pgf@tmp@tang@i}{\pgf@tmp@tang@ii}%
- }%
- \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
- \else%
- \pgf@nfold@addcurvesegment@callback@continue{#1}{#2}{#3}{#4}{#5}%
- \fi%
-}
-
-\def\pgf@nfold@addcurvesegment@callback@continue#1#2#3#4#5{%
- % The subdivision algorithm has already computed the tangents
- \edef\pgf@nfold@macrotoadd{%
- \noexpand\pgf@nfold@token@curveto@continue{#1}{#2}{#3}{#4}{\pgf@tmp@tang@i}{\pgf@tmp@tang@ii}%
- }%
- \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
-}
-
-
-% Rendering arrow tips
-% --------------------
-
-% Precomputed intersections
-%
-% For arrows of order n > 2 with an Implies tip, the constituent parts of the n-fold arrow
-% end somewhere in the middle of the tip. The exact end point must be computed using
-% the intersections library. To speed up compilation times, the intersection points are precomputed
-% up to n = 5. If your document contains arrows of order 6 or larger, consider adding those
-% as well; the values are output in the log file.
-\expandafter\def\csname pgf@nfold@intersec@cache@2@3\endcsname{\pgfqpoint{2pt}{0pt}}
-\expandafter\def\csname pgf@nfold@intersec@cache@2@4\endcsname{\pgfqpoint{0.94063pt}{-0.33333pt}}
-\expandafter\def\csname pgf@nfold@intersec@cache@3@4\endcsname{\pgfqpoint{0.94063pt}{0.33333pt}}
-\expandafter\def\csname pgf@nfold@intersec@cache@2@5\endcsname{\pgfqpoint{0.64167pt}{-0.5pt}}
-\expandafter\def\csname pgf@nfold@intersec@cache@3@5\endcsname{\pgfqpoint{2pt}{0pt}}
-\expandafter\def\csname pgf@nfold@intersec@cache@4@5\endcsname{\pgfqpoint{0.64167pt}{0.5pt}}
-% intersections are precomputed up to this order
-\def\pgf@nfold@intersec@numcached{5}
-
-% This macro extends the arrow body to the tips
-% #1: s=start, e=end
-% #2: start/end point of the path
-% #3: angle
-\newif\ifpgf@nfold@ontheedge
-\def\pgf@nfold@extendtotip#1#2#3{
- \ifpgf@nfold@intersectionsnotloaded
- \pgfutil@packageerror{tikz-nfold}{%
- If `nfold' is larger than \pgf@nfold@intersec@numcached\space and you use
- an `Implies' arrow tip you need to say \string\usetikzlibrary{intersections}}{}
- \else
- \pgf@nfold@ontheedgetrue
- % Do not extend the arrow for index=1 and index=order, it already ends in the right place
- \ifnum\pgf@nfold@index>1\relax\ifnum\pgf@nfold@index<\pgf@nfold@order\relax%
- \pgf@nfold@ontheedgefalse
- \fi\fi
- \ifpgf@nfold@ontheedge%
- % the extension at the start needs a moveto to the correct starting point
- \if#1s
- \pgfpathmoveto{\pgfpointadd{#2}{\pgfpointpolar{#3+90}{\pgf@nfold@shiftamount}}}%
- \fi
- \else
- % Step 1: Find the intersection of the arrow's path with the head
- \ifcsname pgf@nfold@intersec@cache@\the\pgf@nfold@index @\the\pgf@nfold@order\endcsname
- \pgfextract@process\pgf@nfold@arrowintersect
- {\csname pgf@nfold@intersec@cache@\the\pgf@nfold@index @\the\pgf@nfold@order\endcsname}%
- \else
- % the intersection has not been precomputed, thus compute on the fly here
- \pgfintersectionofpaths{
- % specify the tip
- \pgfpathmoveto{\pgfqpoint{-1.4pt}{2.65pt}}
- \pgfpathcurveto{\pgfqpoint{-0.75pt}{1.25pt}}{\pgfqpoint{1pt}{0.05pt}}{\pgfqpoint{2pt}{0pt}}
- \pgfpathcurveto{\pgfqpoint{1pt}{-0.05pt}}{\pgfqpoint{-0.75pt}{-1.25pt}}{\pgfqpoint{-1.4pt}{-2.65pt}}
- }{
- % extend the body to intersect the tip
- \pgfpathmoveto{\pgfqpoint{-3pt}{\pgf@nfold@shift@fraction pt}}
- \pgfpathlineto{\pgfqpoint{3pt}{\pgf@nfold@shift@fraction pt}}
- }
- \ifnum\pgfintersectionsolutions>0
- \pgfextract@process\pgf@nfold@arrowintersect{\pgfpointintersectionsolution{1}}%
- \immediate\write17{tikz-nfold: computed intersection cache@\the\pgf@nfold@index @\the\pgf@nfold@order: \string\pgfqpoint{\the\pgf@x}{\the\pgf@y}^^J}
- % add the new intersection to the cache
- \expandafter\xdef\csname pgf@nfold@intersec@cache@\the\pgf@nfold@index @\the\pgf@nfold@order\endcsname{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}
- \else
- % this is a failsafe and should never be reached
- \pgfutil@packagewarning{tikz-nfold}{did not find intersection}
- \pgfextract@process\pgf@nfold@arrowintersect{\pgfqpoint{0pt}{\pgf@nfold@shift@fraction pt}}%
- \fi
- \fi% if precomputed
- % Step 2: Extend the arrow body to the intersection point.
- % If the tip is at the beginning of the path, we have to move to the intersection
- % and then draw a line to the "regular" starting point. The subsequent segment then
- % should omit its moveto.
- % If the tip is at the end, we are already in the right position and only need to extend
- % the current path to the intersection point.
- \begingroup
- \pgftransformreset
- \pgftransformshift{#2}
- \pgftransformrotate{#3}
- \if#1s
- \pgftransformxscale{-1}
- \fi
- % we don't want to undo the shift by .42\pgflinewidth after the scaling
- \pgfutil@tempdima=\pgf@nfold@hwidth
- \pgfutil@tempdima=\pgf@nfold@shift@fraction\pgfutil@tempdima
- \pgfextract@process\pgf@nfold@startofextension
- {\pgfpointtransformed{\pgfqpoint{0pt}{\pgfutil@tempdima}}}
- % 0.5 - 0.06 = 0.42
- \pgftransformshift{\pgfqpoint{.42\pgflinewidth}{0pt}}
- \pgftransformscale{\pgf@nfold@hwidth}
- \pgfextract@process\pgf@nfold@arrowintersect{\pgfpointtransformed{\pgf@nfold@arrowintersect}}
- \global\let\pgf@nfold@startofextension\pgf@nfold@startofextension
- \global\let\pgf@nfold@arrowintersect\pgf@nfold@arrowintersect
- \endgroup
- \if#1s
- \pgfpathmoveto{\pgf@nfold@arrowintersect}
- % This is precisely the start of the body, shifted vertically
- \pgfpathlineto{\pgf@nfold@startofextension}
- \else\if#1e
- \pgfpathlineto{\pgf@nfold@arrowintersect}
- \else
- \pgfutil@packageerror{tikz-nfold}{Invalid argument to \string\pgf@nfold@extendtotip: \meaning#1}{}
- \fi\fi
- \pgftransformreset
- \fi% if 1 < i < nArrows
- \fi% if intersections is needed and not loaded
-}
-
-% Parsing the arrow tips
-% ----------------------
-%
-% We need to detect if the user has set Implies[] arrows at the start and/or end tip.
-% To do so, we parse \pgf@start@tip@sequence. If the user specifies Implies[] manually,
-% we find that
-% pgf@start@tip@sequence=\pgf@arrow@handle{Implies}{...}
-% However, in other cases (like tikz-cd) we may find
-% \pgf@arrow@handle@shorthand@empty {\csname pgf@ar@means@tikzcd implies cap\endcsname }
-% In such cases we must expand the first parameter once and then match as above.
-
-% Set global defaults
-\def\pgf@nfold@start@arrowcode{0}
-\def\pgf@nfold@end@arrowcode{0}
-
-\def\pgf@nfold@parsearrows{
- \ifpgfutil@tempswa% this is set in \pgfusepath and stores whether we draw arrow tips at all
- \expandafter\pgf@nfold@parsearrowmacro\pgf@start@tip@sequence\relax
- \let\pgf@nfold@start@arrowcode\pgf@nfold@detectedarrow
- \expandafter\pgf@nfold@parsearrowmacro\pgf@end@tip@sequence\relax
- \let\pgf@nfold@end@arrowcode\pgf@nfold@detectedarrow
- \else
- \def\pgf@nfold@start@arrowcode{0}
- \def\pgf@nfold@end@arrowcode{0}
- \fi
-}
-
-\def\pgf@nfold@parsearrowmacro#1{%
- \def\pgf@nfold@detectedarrow{0}
- \ifx#1\relax
- \let\pgf@next\relax
- \else
- \ifx#1\pgf@arrow@handle
- % found \pgf@arrow@handle{...}, now parse the first parameter
- \let\pgf@next\pgf@nfold@parse@arrow@handle
- \else
- \ifx#1\pgf@arrow@handle@shorthand@empty
- \let\pgf@next\pgf@nfold@parse@shorthandempty
- \else
- % found nothing
- \let\pgf@next\pgfutil@gobble@until@relax
- \fi
- \fi
- \fi
- \pgf@next
-}
-
-\def\pgf@nfold@param@Implies{Implies}
-
-\def\pgf@nfold@parse@arrow@handle#1{%
- \def\pgf@tmp{#1}
- \ifx\pgf@tmp\pgf@nfold@param@Implies
- \def\pgf@nfold@detectedarrow{1}
- \fi
- \pgfutil@gobble@until@relax
-}
-
-\def\pgf@nfold@parse@shorthandempty#1{
- % Expand #1 once (\pgf@arrow@handle@shorthand@empty is just an identity operator)
- \expandafter\def\expandafter\pgf@tmp\expandafter{#1}
- \expandafter\pgf@nfold@parsearrowmacro\pgf@tmp\relax
- % still need to gobble the rest of the orginal arrow definition
- \pgfutil@gobble@until@relax
-}
-
-
-%
-% Hooking into pgf's rendering pipeline
-% -------------------------------------
-%
-% The new code has to be injected into \pgfusepath (pgfcorepathusage.code.tex). For rendering the new paths,
-% \pgf@stroke@inner@line is a natural choice as this is where /tikz/double is rendered. However, we also
-% need to disable rendering the ordinary path, which is not as easy. In the future I will make a pull request
-% to TikZ to simplify such injections.
-%
-% The call to draw the path comes right before \pgf@stroke@inner@line. The macro before \pgf@stroke@inner@line
-% is either \pgf@path@check@proper or \pgf@prepare@start@of@path (depending on the result of the proper check).
-% We therefore must inject code into both of them to see if nfold is enabled. If it is, we call the old macro,
-% cache and delete the current softpath (so the call to \pgfsyssoftpath@invokecurrentpath has no effect), then we
-% restore and offset the cached softpath in \pgf@stroke@inner@line.
-%
-% The macros \pgf@path@check@proper and \pgf@prepare@start@of@path are also used in \pgf@up@draw@arrows@only,
-% so we must make sure that the latter is unaffected by the modifications. Luckily, this turns out not to be
-% a problem - the only macros that are called after the modified ones are \pgf@add@arrow@at@start and
-% \pgf@add@arrow@at@end, which do not change their behaviour even if we modify the paths.
-%
-
-\newcount\pgf@nfold@order
-\pgf@nfold@order=1
-
-\def\pgf@nfold@preparenfoldpath{%
- \ifnum\pgf@nfold@order>1\relax
- \ifdim\pgfinnerlinewidth>0pt\relax
- % Hack the rendering pipeline: There is a \pgfsyssoftpath@invokecurrentpath call following
- % which we do not want if nfold is active. We therefore clear the current path here
- % and then perform the nfold drawing in our modification of \pgf@stroke@inner@line
- \pgfsyssoftpath@getcurrentpath\pgf@nfold@cachedpath%
- \pgfsyssoftpath@setcurrentpath\pgfutil@empty%
- \else
- \pgfutil@packageerror{tikz-nfold}{Must set \string\pgfinnerlinewidth\space to use nfold, e.g. by setting /tikz/double distance}{}
- \fi
- \fi
-}
-
-\let\pgf@nfold@old@path@check@proper\pgf@path@check@proper
-\def\pgf@path@check@proper{%
- \pgf@nfold@old@path@check@proper%
- \ifpgfutil@tempswa\else%
- % if \pgfutil@tempswa is false, this is the last macro we can overwrite before the draw call.
- % Otherwise, we inject into \pgf@prepare@start@of@path%
- \pgf@nfold@preparenfoldpath%
- \fi%
-}
-
-\let\pgf@nfold@old@prepare@start@of@path\pgf@prepare@start@of@path
-\def\pgf@prepare@start@of@path{%
- \pgf@nfold@old@prepare@start@of@path%
- \pgf@nfold@preparenfoldpath%
-}
-
-\let\pgf@nfold@old@stroke@inner@line\pgf@stroke@inner@line
-\def\pgf@stroke@inner@line{%
- \ifnum\pgf@nfold@order>1\relax%
- \pgf@nfold@render@cached@softpath%
- \else%
- % Old behaviour
- \pgf@nfold@old@stroke@inner@line%
- \fi%
-}
-
-
-%
-% Parsing the soft path
-% ---------------------
-%
-% A significant part of the code below is based on pgfmoduledecorations.code.tex (c) 2019 Mark Wibrow and Till Tantau.
-% Quite similar to decorations we parse the current soft path and put it into a form that makes it easier
-% to iterate over.
-%
+% 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.
%
-
-
%
-% In order to correctly implement \pgfpathclose we already need to know about
-% the \pgfpathclose (and the penultimate point) at the beginning of this
-% connected sub-path as these data affect the first/last join.
-% We therefore parse one connected sub-path of the softpath and store it in a modified
-% form in \pgf@cur@conn@subpath. When reaching the end of the connected sub-path we call
-% the proper parser to turn \pgf@cur@conn@subpath into a parsed path. We do this for
-% all connected sub-paths and concatenate all the parsed paths.
+% A commented version of this file can be found on https://github.com/jonschz/tikz-nfold .
%
-\def\pgf@nfold@parsesoftpath#1#2{%
- \let\pgf@cur@conn@subpath\pgfutil@empty%
- \let\pgf@all@parsed@subpaths\pgfutil@empty%
- \edef\pgf@nfold@parser@last@moveto{{\the\pgf@path@lastx}{\the\pgf@path@lasty}}%
- \let\pgf@nfold@last@closepath@from\pgfutil@empty%
- \pgf@nfold@parse@setupfirst%
- \expandafter\pgf@nfold@@parsesoftpath#1\pgf@stop{}{}%
- \let#2\pgf@all@parsed@subpaths%
-}%
-
-\def\pgf@nfold@@parsesoftpath#1#2#3{%
- \let\pgf@next\pgf@nfold@@parsesoftpath%
- \ifx#1\pgf@stop%
- \def\pgf@nfold@macrotoadd{\pgf@nfold@parselast}%
- \pgf@nfold@addmacro\pgf@cur@conn@subpath%
- \pgf@nfold@lastconnsubpathtrue%
- \pgf@nfold@process@conn@subpath%
- \let\pgf@next\relax%
- \else%
- \ifx#1\pgfsyssoftpath@movetotoken%
- \ifx\pgf@cur@conn@subpath\pgfutil@empty%
- % This case happens for the very first segment or for double movetos.
- % We need special treatment here, as otherwise the arrow tip extension
- % does not work correctly. The \pgf@nfold@parsemoveto will be called
- % in \pgf@nfold@process@conn@subpath.
- \def\pgf@nfold@parser@last@moveto{{#2}{#3}}%
- % Make sure \pgf@cur@conn@subpath is no longer empty so double movetos are not
- % treated the same as single movetos. This is also relevant to arrow tip extensions
- \def\pgf@cur@conn@subpath{\relax}%
- \else%
- \def\pgf@nfold@macrotoadd{\pgf@nfold@parsemoveto{#2}{#3}}%
- \pgf@nfold@addmacro\pgf@cur@conn@subpath%
- \pgf@nfold@lastconnsubpathfalse%
- % A moveto marks the beginning/end of one connected sub-path
- \pgf@nfold@process@conn@subpath%
- \let\pgf@nfold@last@closepath@from\pgfutil@empty%
- \let\pgf@cur@conn@subpath\pgfutil@empty%
- % set up "first" again which may be needed for the arrow tip extension
- \pgf@nfold@parse@setupfirst%
- \def\pgf@nfold@parser@last@moveto{{#2}{#3}}%
- \fi
- \else%
- \ifx#1\pgfsyssoftpath@linetotoken%
- \def\pgf@nfold@macrotoadd{\pgf@nfold@parselineto{#2}{#3}}%
- \pgf@nfold@addmacro\pgf@cur@conn@subpath%
- \else%
- \ifx#1\pgfsyssoftpath@curvetosupportatoken%
- \def\pgf@nfold@parse@supporta{{#2}{#3}}%
- \else%
- \ifx#1\pgfsyssoftpath@curvetosupportbtoken%
- \def\pgf@nfold@parse@supportb{{#2}{#3}}%
- \else%
- \ifx#1\pgfsyssoftpath@curvetotoken%
- \edef\pgf@nfold@macrotoadd{\noexpand\pgf@nfold@parsecurveto\pgf@nfold@parse@supporta\pgf@nfold@parse@supportb{#2}{#3}}%
- \pgf@nfold@addmacro\pgf@cur@conn@subpath%
- \else%
- \ifx#1\pgfsyssoftpath@closepathtoken%
- \let\pgf@nfold@last@closepath@from\pgf@nfold@parser@previous@pt%
- \def\pgf@nfold@macrotoadd{\pgf@nfold@parseclosepath{#2}{#3}}%
- \pgf@nfold@addmacro\pgf@cur@conn@subpath%
- \else%
- \ifx#1\pgfsyssoftpath@rectcornertoken%
- \def\pgf@nfold@parse@rectcorner{{#2}{#3}}%
- \else%
- \ifx#1\pgfsyssoftpath@rectsizetoken%
- \edef\pgf@nfold@macrotoadd{\noexpand\pgf@nfold@parserect\pgf@nfold@parse@rectcorner{#2}{#3}}%
- \pgf@nfold@addmacro\pgf@cur@conn@subpath%
- \else%
- \pgfutil@packageerror{tikz-nfold}{Unrecognised soft path token `#1'}{}%
- \fi%
- \fi%
- \fi%
- \fi%
- \fi%
- \fi%
- \fi%
- \fi%
- \fi%
- \def\pgf@nfold@parser@previous@pt{{#2}{#3}}%
- % store the last two segments, as they might be needed for zero-length \pgfpathclose-segments
- \let\pgf@nfold@sectolast@segment\pgf@nfold@last@segment%
- \let\pgf@nfold@last@segment\pgf@nfold@macrotoadd%
- \pgf@next}%
-
-\def\pgf@nfold@process@conn@subpath{%
- \let\pgf@parsed@cur@conn@seg\pgfutil@empty%
- \ifx\pgf@nfold@last@closepath@from\pgfutil@empty%
- \expandafter\pgf@nfold@parsemoveto\pgf@nfold@parser@last@moveto%
- \else%
- % This connected sub-path ends on a closepath. In order to get
- % the join right, we prepend the current sub-path with an invisible line
- % identical to the line of the \pgfpathclose.
- \expandafter\pgf@nfold@parsemoveto\pgf@nfold@last@closepath@from%
- \expandafter\pgf@nfold@parseinvisibleline\pgf@nfold@parser@last@moveto%
- \fi%
- \pgf@cur@conn@subpath%
- \let\pgf@nfold@macrotoadd\pgf@parsed@cur@conn@seg%
- \pgf@nfold@addmacro\pgf@all@parsed@subpaths%
-}
-
-%
-% Values for \pgf@nfold@next@type:
-% f=first, m=moveto, c=curveto, l=lineto, r=rect, o=closepath, z=zero length closepath, t=last, i=invisibleline
-%
-
-\def\pgf@nfold@parsemoveto#1#2{%
- \pgf@nfold@parser@moveup%
- \let\pgf@nfold@next@type=m%
- \let\pgf@nfold@next@visible=0%
- \edef\pgf@nfold@next@last{\pgf@x#1\pgf@y#2}%
- \pgf@nfold@parser@handlesegment%
-}%
-
-
-% Common code for parselineto and parseclosepath
-\def\pgf@nfold@parse@line@common#1#2#3{%
- \pgf@nfold@parser@moveup%
- \pgfextract@process\pgf@tmp@tang@i{\pgfpointnormalised{}\global\let\pgf@nfold@tmp\pgf@tmp}
- \let\pgf@nfold@next@type=#3%
- \let\pgf@nfold@next@visible=1%
- \let\pgf@nfold@next@tang@i\pgf@tmp@tang@i
- \let\pgf@nfold@next@tang@ii\pgf@tmp@tang@i
- \let\pgf@nfold@next@angle@i\pgf@nfold@tmp
- \let\pgf@nfold@next@angle@ii\pgf@nfold@tmp
- \let\pgf@nfold@next@first\pgf@nfold@cur@last
- \def\pgf@nfold@next@last{\pgf@x#1\pgf@y#2}%
- \pgf@nfold@parser@handlesegment%
-}
-
-\def\pgf@nfold@parselineto#1#2{%
- % the current end is still stored in next@last because parser@moveup has not been called yet
- \pgf@process{\pgfpointdiff{\pgf@nfold@next@last}{\pgf@x#1\pgf@y#2}}%
- \pgfpointtaxicabnorm\pgf@xa%
- % remove degenerate line segments (reduces glitches)
- \ifdim\pgf@xa>.1pt\relax%
- \pgf@nfold@parse@line@common{#1}{#2}{l}%
- \fi%
-}%
-
-\def\pgf@nfold@parsecurveto#1#2#3#4#5#6{%
- \pgf@nfold@parser@moveup%
- \pgf@offset@compute@tangents{\pgf@nfold@cur@last}{\pgf@x#1\pgf@y#2}{\pgf@x#3\pgf@y#4}{\pgf@x#5\pgf@y#6}%
- \let\pgf@nfold@next@type=c%
- \let\pgf@nfold@next@visible=1%
- % the following only need to be set if visible=1
- \let\pgf@nfold@next@tang@i=\pgf@tmp@tang@i
- \let\pgf@nfold@next@tang@ii=\pgf@tmp@tang@ii
- \let\pgf@nfold@next@angle@i\pgf@tmp@angle@i
- \let\pgf@nfold@next@angle@ii\pgf@tmp@angle@ii
- \let\pgf@nfold@next@first\pgf@nfold@cur@last
- \def\pgf@nfold@next@supporta{\pgf@x#1\pgf@y#2}
- \def\pgf@nfold@next@supportb{\pgf@x#3\pgf@y#4}
- \def\pgf@nfold@next@last{\pgf@x#5\pgf@y#6}
- \pgf@nfold@parser@handlesegment%
-}%
-
-\def\pgf@nfold@parseclosepath#1#2{%
- \pgf@process{\pgfpointdiff{\pgf@nfold@next@last}{\pgf@x#1\pgf@y#2}}%
- % closepath segments should always be processed even if they have zero length
- \pgfpointtaxicabnorm\pgf@xa%
- \ifdim\pgf@xa<0.1pt\relax%
- \pgf@nfold@parse@closepath@zerolength{#1}{#2}%
- \else%
- \pgf@nfold@parse@line@common{#1}{#2}{o}%
- \fi%
-}%
-
-\def\pgf@nfold@parse@closepath@zerolength#1#2{%
- \pgf@nfold@parser@moveup%
- \let\pgf@nfold@next@type=z%
- \let\pgf@nfold@next@visible=1%
- % Set the start and end tangent to the tangent of the first segment
- \let\pgf@nfold@next@tang@i\pgf@nfold@connsubpath@tang@i
- \let\pgf@nfold@next@tang@ii\pgf@nfold@connsubpath@tang@i
- \let\pgf@nfold@next@angle@i\pgf@nfold@connsubpath@angle@i
- \let\pgf@nfold@next@angle@ii\pgf@nfold@connsubpath@angle@i
- \let\pgf@nfold@next@first\pgf@nfold@cur@last
- % If problems arise, we need to put a fake point here (like \pgf@nfold@next@first + \pgf@nfold@next@tang@i)
- \def\pgf@nfold@next@last{\pgf@x#1\pgf@y#2}%
- \pgf@nfold@parser@handlesegment%
-}
-
-\def\pgf@nfold@parseinvisibleline#1#2{%
- \pgf@process{\pgfpointdiff{\pgf@nfold@next@last}{\pgf@x#1\pgf@y#2}}%
- \pgfpointtaxicabnorm\pgf@xa%
- % In order to correctly render the start/end join in a closed path,
- % the \pgfpathclose segment is copied to the start of the path as an invisible line.
- % Counterintuitively, an "invisibleline" segment has next@visible=1 because
- % we want its end join to be rendered.
- % In case the \pgfpathclose segment has non-zero length, we can just use a copy of
- % this segment for the invisible line. Otherwise, the invisble line segment must will receive
- % the same angle/tangent as the last finite-sized segment, which is the second-to-last
- % segment overall (cached in \pgf@nfold@sectolast@segment).
- \ifdim\pgf@xa>.1pt\relax%
- \pgf@nfold@parse@line@common{#1}{#2}{i}%
- \else%
- \begingroup%
- % find the tangent of the second-to-last segment
- \let\pgf@nfold@parser@handlesegment\relax%
- \pgf@nfold@sectolast@segment%
- \global\let\pgf@nfold@tmp\pgf@nfold@next@tang@ii%
- \endgroup%
- % Construct an invisible line with length 1pt and the correct tangent.
- % This step might not be needed since the join computations only require the tangent,
- % but the invisibleline segment would be inconsistent otherwise, so better play it safe.
- \pgfextract@process\pgf@nfold@next@first{\pgfpointdiff{\pgf@nfold@tmp}{\pgfqpoint{#1}{#2}}}%
- % write the tangent into (\pgf@x, \pgf@y) where the next macro expects it to be
- \pgf@nfold@tmp%
- \pgf@nfold@parse@line@common{#1}{#2}{i}%
- \fi%
-}%
-
-\def\pgf@nfold@parselast{%
- \pgf@nfold@parser@moveup%
- \let\pgf@nfold@next@type=t%
- \let\pgf@nfold@next@visible=0%
- \pgf@nfold@parser@handlesegment%
-}
-
-% Mostly for the sake of completeness; using TikZ' "\path (0,0) rectangle (1,1);" does not call this code
-\def\pgf@nfold@parserect#1#2#3#4{%
- \pgf@nfold@parsemoveto{#1}{#2}%
- \pgf@xc=#1\relax
- \pgf@yc=#2\relax
- \pgf@xd=#3\relax
- \pgf@yd=#4\relax
- \advance\pgf@yc\pgf@yd%
- \edef\pgf@temp{{\the\pgf@xc}{\the\pgf@yc}}%
- \expandafter\pgf@nfold@parselineto\pgf@temp%
- \advance\pgf@xc\pgf@xd%
- \edef\pgf@temp{{\the\pgf@xc}{\the\pgf@yc}}%
- \expandafter\pgf@nfold@parselineto\pgf@temp%
- \advance\pgf@yc-\pgf@yd%
- \edef\pgf@temp{{\the\pgf@xc}{\the\pgf@yc}}%
- \expandafter\pgf@nfold@parselineto\pgf@temp%
- \advance\pgf@xc-\pgf@xd%
- \edef\pgf@temp{{\the\pgf@xc}{\the\pgf@yc}}%
- \expandafter\pgf@nfold@parselineto\pgf@temp%
- \edef\pgf@marshal{\noexpand\pgf@nfold@parsemoveto{\the\pgf@xc}{\the\pgf@yc}}%
- \pgf@marshal%
-}
-
-% adds the contents of \pgf@nfold@macrotoadd to #1
-\def\pgf@nfold@addmacro#1{%
- % need a \gdef because we have nested groups in the subdivision
- \expandafter\expandafter\expandafter\gdef%
- \expandafter\expandafter\expandafter#1%
- \expandafter\expandafter\expandafter{%
- \expandafter#1\pgf@nfold@macrotoadd}%
-}
-
-
-%
-% Tokens for the parsed path
-%
-
-%#3: cached normalised tangent (for efficiency)
-\def\pgf@nfold@token@lineto#1#2#3{%
- \pgfoffsetline@{#1}{#2}{\pgf@nfold@shiftamount}{#3}%
-}
-
-\def\pgf@nfold@token@lineto@continue#1#2#3{%
- \pgfoffsetlinenomove@{#1}{#2}{\pgf@nfold@shiftamount}{#3}%
-}
-
-\def\pgf@nfold@token@invisibleline#1#2#3{%
- % An invisible line should execute a moveto to the end point of the line
- \pgfqpointscale{\pgf@nfold@shiftamount}{#3}%
- \pgf@xc=-\pgf@y%
- \pgf@y=\pgf@x%
- \pgf@x=\pgf@xc%
- \pgfpathmoveto{\pgfpointadd{}{#2}}%
-}
-
-% #5, #6: cached normalised tangents at start and end (for efficiency)
-\def\pgf@nfold@token@curveto#1#2#3#4#5#6{%
- \def\pgf@tmp@tang@i{#5}%
- \def\pgf@tmp@tang@ii{#6}%
- \pgf@offset@bezier@segment@{#1}{#2}{#3}{#4}{\pgf@nfold@shiftamount}%
- \pgfpathmoveto{\pgf@bezier@offset@i}%
- \pgfpathcurveto{\pgf@bezier@offset@ii}{\pgf@bezier@offset@iii}{\pgf@bezier@offset@iv}%
-}
-
-\def\pgf@nfold@token@curveto@continue#1#2#3#4#5#6{%
- \def\pgf@tmp@tang@i{#5}%
- \def\pgf@tmp@tang@ii{#6}%
- \pgf@offset@bezier@segment@{#1}{#2}{#3}{#4}{\pgf@nfold@shiftamount}%
- \pgfpathcurveto{\pgf@bezier@offset@ii}{\pgf@bezier@offset@iii}{\pgf@bezier@offset@iv}%
-}
-
-\def\pgf@nfold@token@closepath{%
- \pgfpathclose%
-}
-
-% This is needed for some edge case explained above.
-% #1: segment@start, which is actually the end point of the current segment in the edge case
-% #2: the angle of the current segment (start or end does not matter for straight lines)
-\def\pgf@nfold@token@edgecase@movetostart#1#2{%
- \pgfpathmoveto{\pgfpointadd%
- {#1}{\pgfpointpolar{#2+90}{\pgf@nfold@shiftamount}}}%
-}
-
-
-\def\pgf@nfold@parse@setupfirst{%
- \let\pgf@nfold@next@type=f%
- % technically, @visible can be derived from @type, but I think this is more efficient
- \let\pgf@nfold@next@visible=0%
- \edef\pgf@nfold@next@last{\pgf@x\the\pgf@path@lastx\pgf@y\the\pgf@path@lasty}%
- % the following only need to be set if visible=1
- % TODO these are disabled temporarily; an attempt to read them suggests that there
- % is a bug, because their content has no meaning at this point. Consider reenabling
- % if compile errors show up, but if they do, the root of the problem is likely to be elsewhere
- %\let\pgf@nfold@next@tang@i=\pgfpointorigin%
- %\let\pgf@nfold@next@tang@ii=\pgfpointorigin%
- % \def\pgf@nfold@next@angle@i{0}%
- % \def\pgf@nfold@next@angle@ii{0}%
- % \let\pgf@nfold@next@first\pgfpointorigin%
- % the following only need to be set if type=c
- % \let\pgf@nfold@next@supporta\pgfpointorigin%
- % \let\pgf@nfold@next@supportb\pgfpointorigin%
-}
-
-\def\pgf@nfold@clampangle{
- % The computed angles are values between 0 and 360, so their difference is between 360 and -360;
- % we want the difference to be between -180 and 180
- \ifdim\pgfmathresult pt<-180pt\relax
- \pgfutil@tempdima=\pgfmathresult pt
- \advance\pgfutil@tempdima by 360pt
- \edef\pgfmathresult{\pgf@sys@tonumber\pgfutil@tempdima}
- \else\ifdim\pgfmathresult pt>180pt\relax
- \pgfutil@tempdima=\pgfmathresult pt
- \advance\pgfutil@tempdima by -360pt
- \edef\pgfmathresult{\pgf@sys@tonumber\pgfutil@tempdima}
- \fi\fi
-}
-
-
-
-\def\pgf@nfold@parser@moveup{%
- \let\pgf@nfold@prev@type\pgf@nfold@cur@type%
- \let\pgf@nfold@prev@visible\pgf@nfold@cur@visible%
- \let\pgf@nfold@prev@tang@i\pgf@nfold@cur@tang@i%
- \let\pgf@nfold@prev@tang@ii\pgf@nfold@cur@tang@ii%
- \let\pgf@nfold@prev@angle@i\pgf@nfold@cur@angle@i%
- \let\pgf@nfold@prev@angle@ii\pgf@nfold@cur@angle@ii%
- \let\pgf@nfold@prev@first\pgf@nfold@cur@first%
- \let\pgf@nfold@prev@supporta\pgf@nfold@cur@supporta%
- \let\pgf@nfold@prev@supportb\pgf@nfold@cur@supportb%
- \let\pgf@nfold@prev@last\pgf@nfold@cur@last%
- \let\pgf@nfold@cur@type\pgf@nfold@next@type%
- \let\pgf@nfold@cur@visible\pgf@nfold@next@visible%
- \let\pgf@nfold@cur@tang@i\pgf@nfold@next@tang@i%
- \let\pgf@nfold@cur@tang@ii\pgf@nfold@next@tang@ii%
- \let\pgf@nfold@cur@angle@i\pgf@nfold@next@angle@i%
- \let\pgf@nfold@cur@angle@ii\pgf@nfold@next@angle@ii
- \let\pgf@nfold@cur@first\pgf@nfold@next@first%
- \let\pgf@nfold@cur@supporta\pgf@nfold@next@supporta%
- \let\pgf@nfold@cur@supportb\pgf@nfold@next@supportb%
- \let\pgf@nfold@cur@last\pgf@nfold@next@last%
-}
-
-%
-% Iterating over the parsed soft path
-% -----------------------------------
-%
-
-\newcount\pgf@nfold@index
-\def\pgf@nfold@run@loop{%
- \pgf@nfold@index=\pgf@nfold@order%
- \pgf@nfold@run@loop@%
-}
-
-\def\pgf@nfold@run@loop@{%
- \pgf@nfold@loop@inner%
- \advance\pgf@nfold@index by -1\relax
- \ifnum\pgf@nfold@index>0\relax%
- \pgf@nfold@run@loop@%
- \fi%
-}
-
-\def\pgf@nfold@loop@inner{%
- \pgfmathsetmacro{\pgf@nfold@shift@fraction}%
- {-1+2*(\pgf@nfold@index-1)/(\pgf@nfold@order-1)}%
- % Do not store shiftamount as a length (i.e. with pt) because we want to use it in \pgfqpointscale{}{}
- \pgfmathsetmacro{\pgf@nfold@shiftamount}{\pgf@nfold@hwidth*\pgf@nfold@shift@fraction}
- % Transformations are already baked into the path; without this call, they would be applied twice
- \pgftransformreset%
- \parsedpath%
- \pgfsyssoftpath@flushcurrentpath%
- \pgf@up@action%
-}
-
-% Computes both the width of the component lines into \pgf@x and the distance
-% from the center to the outermost line centers into \pgf@y
-% from the current values of \pgflinewidth and \pgfinnerlinewidth.
-\def\pgf@nfold@compute@widths@from@double{
- \pgf@x=\pgflinewidth\relax%
- \pgf@y=\pgf@x\relax%
- \advance\pgf@x-\pgfinnerlinewidth\relax%
- \advance\pgf@y+\pgfinnerlinewidth\relax%
- \pgf@x=.5\pgf@x\relax%
- \pgf@y=.25\pgf@y\relax%
-}
-
-\def\pgf@nfold@render@cached@softpath{%
- \pgfscope% must use a scope, otherwise we break the arrow tips
- % Compute the full and constituent part line widths
- \pgf@nfold@compute@widths@from@double%
- \pgfsetlinewidth\pgf@x%
- \edef\pgf@nfold@hwidth{\the\pgf@y}%
- \pgfprocessround{\pgf@nfold@cachedpath}{\pgf@nfold@cachedpath}% remove tokens from the soft path
- \pgf@nfold@parsearrows%
- \pgf@nfold@parsesoftpath{\pgf@nfold@cachedpath}{\parsedpath}%
- \pgf@nfold@run@loop%
- \endpgfscope%
-}
-
-
-%
-% user interface and pgf/TikZ keys
-% --------------------------------
-%
-
-% Outputs a provided soft path in #1 offset by a distance provided in #2.
-\def\pgfoffsetpath#1#2{%
- \begingroup
- \pgfmathsetlengthmacro\pgf@nfold@parsed@hwidth{#2}
- % \pgf@nfold@hwidth must always be positive
- \pgf@x=\pgf@nfold@parsed@hwidth\relax
- \ifdim\pgf@x<0pt\relax
- \pgf@x=-\pgf@x
- \def\pgf@nfold@shift@fraction{-1}
- \else
- \def\pgf@nfold@shift@fraction{1}
- \fi
- \edef\pgf@nfold@parsed@hwidth{\the\pgf@x}
- \pgfoffsetpathqfraction{#1}{\pgf@nfold@parsed@hwidth}{\pgf@nfold@shift@fraction}
- \endgroup
-}
-
-% Outputs a provided soft path in #1 offset by #3*#2 where #2 is a length (>= 0 pt)
-% and #3 is a number between -1.0 and 1.0. This differs from \pgfoffsetpath{#1}{#2*#3}
-% in how the joins between segments are rendered. In particular, \pgfoffsetpathfraction{#1}{10pt}{0}
-% does *not* yield the original path, but a new path in the centre of #1 drawn at line width 20pt.
-%
-\def\pgfoffsetpathfraction#1#2#3{%
- \begingroup
- \pgfmathsetlengthmacro\pgf@nfold@parsed@hwidth{#2}
- \pgfmathsetmacro\pgf@nfold@shift@fraction{#3}
- \pgfoffsetpathqfraction{#1}{\pgf@nfold@parsed@hwidth}{\pgf@nfold@shift@fraction}
- \endgroup
-}
-
-% This has the same output as the #3-th segment of nfold=#4.
-\def\pgfoffsetpathindex#1#2#3#4{%
- \begingroup
- \pgfmathsetmacro\pgf@nfold@shift@fraction{-1+2*(#3-1)/(#4-1)}
- \pgfoffsetpathqfraction{#1}{#2}{\pgf@nfold@shift@fraction}
- \endgroup
-}
-
-% A quick version that skips processing the input values
-\def\pgfoffsetpathqfraction#1#2#3{%
- \begingroup
- \pgf@x=#2\relax
- \edef\pgf@nfold@hwidth{\the\pgf@x}
- \edef\pgf@nfold@shift@fraction{#3}
- \pgf@x=\pgf@nfold@shift@fraction\pgf@x\relax
- \edef\pgf@nfold@shiftamount{\pgf@sys@tonumber\pgf@x}
- \pgfprocessround{#1}{\pgf@nfold@cachedpath}% remove tokens from the soft path
- \pgf@nfold@parsesoftpath{\pgf@nfold@cachedpath}{\parsedpath}%
- % Transformations are already baked into the path; without this call, they would be applied twice
- \pgftransformreset%
- \parsedpath%
- \endgroup
-}
-
-
-\pgfkeys{
- /pgf/nfold/.code={%
- \pgf@nfold@order=#1\relax%
- \ifnum\pgf@nfold@order<1\relax%
- \pgfutil@packageerror{tikz-nfold}{The key /pgf/nfold must take a value of at least 1, got \the\pgf@nfold@order}{}%
- \fi%
- % If nfold > numcached AND intersections is not loaded AND we draw an Implies tip, we get an error.
- % We check the first two conditions now and set the respective flag
- \ifnum\pgf@nfold@order>\pgf@nfold@intersec@numcached\relax
- \ifdefined\pgfintersectionofpaths\else
- \pgf@nfold@intersectionsnotloadedtrue
- \fi
- \fi
- },
- /pgf/nfold/.default=2
-}
-
+\usepgflibrary{nfold}
+\usetikzlibrary{arrows.meta}
-% use \tikzset for scoping reasons, does not appear to be equivalent to \pgfset{/tikz/...=...}
\tikzset{
nfold/.code={
\edef\pgf@tmp{\noexpand\pgfkeys{/pgf/nfold=#1}}
- % patch \tikz@double@setup to set /pgf/nfold=#1 as well
\expandafter\expandafter\expandafter\def%
\expandafter\expandafter\expandafter\tikz@double@setup%
\expandafter\expandafter\expandafter{\expandafter\tikz@double@setup\pgf@tmp}
},
nfold/.default=2,
scaling nfold/.code={%
- \pgfscope% scope to contain \tikz@double@setup
+ \pgfscope%
\tikz@double@setup
- % extract double distance between line centers into \pgf@x
\pgf@nfold@compute@widths@from@double
\pgf@y=2\pgf@y
- % store (order-1)*\pgf@x in \pgf@xa
\c@pgf@counta=#1
\advance\c@pgf@counta by -1\relax
\global\pgf@y=\c@pgf@counta\pgf@y
@@ -1329,21 +47,16 @@
}
},
scaling nfold/.default=2,
- % This simply defines the key if tikzcd is not loaded, so we don't run into any errors
commutative diagrams/scaling nfold/.code={
- \pgfscope% scope to contain \tikz@double@setup
+ \pgfscope%
\tikz@double@setup
- % extract double distance between line centers into \pgf@x
\pgf@nfold@compute@widths@from@double
- % store (order-1)*\pgf@y in \pgf@ya
\c@pgf@counta=#1
\advance\c@pgf@counta by -1\relax
\pgf@ya=\c@pgf@counta\pgf@y
- % compute the label offset, which is (order-2)*\pgf@y + .5*\pgf@x
\advance\c@pgf@counta by -1\relax
\pgf@xa=\c@pgf@counta\pgf@y
\advance\pgf@xa by .5\pgf@x
- % save the results in \pgf@x and \pgf@y
\global\pgf@x=\pgf@xa
\global\pgf@y=2\pgf@ya
\endpgfscope