texlive[67711] Master/texmf-dist: tikz-nfold (23jul23)
commits+karl at tug.org
commits+karl at tug.org
Sun Jul 23 22:45:56 CEST 2023
Revision: 67711
http://tug.org/svn/texlive?view=revision&revision=67711
Author: karl
Date: 2023-07-23 22:45:55 +0200 (Sun, 23 Jul 2023)
Log Message:
-----------
tikz-nfold (23jul23)
Modified Paths:
--------------
trunk/Master/texmf-dist/doc/latex/tikz-nfold/README.md
trunk/Master/texmf-dist/doc/latex/tikz-nfold/tikz-nfold-doc.pdf
trunk/Master/texmf-dist/doc/latex/tikz-nfold/tikz-nfold-doc.tex
trunk/Master/texmf-dist/tex/latex/tikz-nfold/pgflibrarybezieroffset.code.tex
trunk/Master/texmf-dist/tex/latex/tikz-nfold/tikzlibrarynfold.code.tex
Added Paths:
-----------
trunk/Master/texmf-dist/tex/latex/tikz-nfold/pgflibrarynfold.code.tex
trunk/Master/texmf-dist/tex/latex/tikz-nfold/pgflibraryoffsetpath.code.tex
Modified: trunk/Master/texmf-dist/doc/latex/tikz-nfold/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/tikz-nfold/README.md 2023-07-22 23:49:15 UTC (rev 67710)
+++ trunk/Master/texmf-dist/doc/latex/tikz-nfold/README.md 2023-07-23 20:45:55 UTC (rev 67711)
@@ -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.
Modified: trunk/Master/texmf-dist/doc/latex/tikz-nfold/tikz-nfold-doc.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/tikz-nfold/tikz-nfold-doc.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/tikz-nfold/tikz-nfold-doc.tex 2023-07-22 23:49:15 UTC (rev 67710)
+++ trunk/Master/texmf-dist/doc/latex/tikz-nfold/tikz-nfold-doc.tex 2023-07-23 20:45:55 UTC (rev 67711)
@@ -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 at packagewarning##1##2{}}
\makeatother
@@ -209,6 +210,19 @@
\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 @@
\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 @@
\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 @@
\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 @@
\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 @@
\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
Modified: trunk/Master/texmf-dist/tex/latex/tikz-nfold/pgflibrarybezieroffset.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/tikz-nfold/pgflibrarybezieroffset.code.tex 2023-07-22 23:49:15 UTC (rev 67710)
+++ trunk/Master/texmf-dist/tex/latex/tikz-nfold/pgflibrarybezieroffset.code.tex 2023-07-23 20:45:55 UTC (rev 67711)
@@ -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 at splitbezier@i at i, ... , \pgf at splitbezier@i at iv,
-% and the second part into \pgf at splitbezier@ii at i, ... , \pgf at splitbezier@ii at iv.
-%\def\pgf at splitbezier#1#2#3#4#5{%
-% % based on pgfcorepoints.code.tex, \pgfpointcurveattime
-% \edef\pgf at time@s{#1}%
-% \pgf at x=-\pgf at time@s pt%
-% \advance\pgf at x by 1pt%
-% \edef\pgf at time@t{\pgf at sys@tonumber{\pgf at x}}%
-% % P^0_3
-% \pgfextract at process\pgf at splitbezier@ii at iv{#5}%
-% \pgf at xc=\pgf at x%
-% \pgf at yc=\pgf at y%
-% % P^0_2
-% \pgf at process{#4}%
-% \pgf at xb=\pgf at x%
-% \pgf at yb=\pgf at y%
-% % P^0_1
-% \pgf at process{#3}%
-% \pgf at xa=\pgf at x%
-% \pgf at ya=\pgf at y%
-% % P^0_0
-% \pgfextract at process\pgf at splitbezier@i at i{#2}%
-% % First iteration:
-% % P^1_0
-% \pgf at x=\pgf at time@t\pgf at x\advance\pgf at x by\pgf at time@s\pgf at xa%
-% \pgf at y=\pgf at time@t\pgf at y\advance\pgf at y by\pgf at time@s\pgf at ya%
-% \pgfextract at process\pgf at splitbezier@i at ii{}%
-% % P^1_1
-% \pgf at xa=\pgf at time@t\pgf at xa\advance\pgf at xa by\pgf at time@s\pgf at xb%
-% \pgf at ya=\pgf at time@t\pgf at ya\advance\pgf at ya by\pgf at time@s\pgf at yb%
-% % P^1_2
-% \pgf at xb=\pgf at time@t\pgf at xb\advance\pgf at xb by\pgf at time@s\pgf at xc%
-% \pgf at yb=\pgf at time@t\pgf at yb\advance\pgf at yb by\pgf at time@s\pgf at yc%
-% \edef\pgf at splitbezier@ii at iii{\noexpand\pgfqpoint{\the\pgf at xb}{\the\pgf at yb}}%
-% % P^2_0
-% \pgf at x=\pgf at time@t\pgf at x\advance\pgf at x by\pgf at time@s\pgf at xa%
-% \pgf at y=\pgf at time@t\pgf at y\advance\pgf at y by\pgf at time@s\pgf at ya%
-% \pgfextract at process\pgf at splitbezier@i at iii{}%
-% % P^2_1
-% \pgf at xa=\pgf at time@t\pgf at xa\advance\pgf at xa by\pgf at time@s\pgf at xb%
-% \pgf at ya=\pgf at time@t\pgf at ya\advance\pgf at ya by\pgf at time@s\pgf at yb%
-% \edef\pgf at splitbezier@ii at ii{\noexpand\pgfqpoint{\the\pgf at xa}{\the\pgf at ya}}%
-% % P^3_0
-% \pgf at x=\pgf at time@t\pgf at x\advance\pgf at x by\pgf at time@s\pgf at xa%
-% \pgf at y=\pgf at time@t\pgf at y\advance\pgf at y by\pgf at time@s\pgf at ya%
-% \pgfextract at process\pgf at splitbezier@i at iv{}%
-% \let\pgf at splitbezier@ii at i\pgf at splitbezier@i at iv
-%}
-% Split the Bezier curve defined by #1-#4 at t=0.5 using de Casteljau's algorithm
\def\pgf at halfsplitbezier#1#2#3#4{%
- % based on pgfcorepoints.code.tex, \pgfpointcurveattime
- % P^0_3
\pgfextract at process\pgf at splitbezier@ii at iv{#4}%
\pgf at xc=\pgf at x%
\pgf at yc=\pgf at y%
- % P^0_2
- \pgf at process{#3}% removing these does not yield a significant speedup
+ \pgf at process{#3}%
\pgf at xb=\pgf at x%
\pgf at yb=\pgf at y%
- % P^0_1
\pgf at process{#2}%
\pgf at xa=\pgf at x%
\pgf at ya=\pgf at y%
- % P^0_0
\pgfextract at process\pgf at splitbezier@i at i{#1}%
- % First iteration:
- % P^1_0
\pgf at x=.5\pgf at x\advance\pgf at x by.5\pgf at xa%
\pgf at y=.5\pgf at y\advance\pgf at y by.5\pgf at ya%
\edef\pgf at splitbezier@i at ii{\pgf at x\the\pgf at x\pgf at y\the\pgf at y}%
- % P^1_1
\pgf at xa=.5\pgf at xa\advance\pgf at xa by.5\pgf at xb%
\pgf at ya=.5\pgf at ya\advance\pgf at ya by.5\pgf at yb%
- % P^1_2
\pgf at xb=.5\pgf at xb\advance\pgf at xb by.5\pgf at xc%
\pgf at yb=.5\pgf at yb\advance\pgf at yb by.5\pgf at yc%
\edef\pgf at splitbezier@ii at iii{\pgf at x\the\pgf at xb\pgf at y\the\pgf at yb}%
- % P^2_0
\pgf at x=.5\pgf at x\advance\pgf at x by.5\pgf at xa%
\pgf at y=.5\pgf at y\advance\pgf at y by.5\pgf at ya%
\edef\pgf at splitbezier@i at iii{\pgf at x\the\pgf at x\pgf at y\the\pgf at y}%
- % P^2_1
\pgf at xa=.5\pgf at xa\advance\pgf at xa by.5\pgf at xb%
\pgf at ya=.5\pgf at ya\advance\pgf at ya by.5\pgf at yb%
\edef\pgf at splitbezier@ii at ii{\pgf at x\the\pgf at xa\pgf at y\the\pgf at ya}%
- % P^3_0
\pgf at x=.5\pgf at x\advance\pgf at x by.5\pgf at xa%
\pgf at y=.5\pgf at y\advance\pgf at y by.5\pgf at ya%
\edef\pgf at splitbezier@i at iv{\pgf at x\the\pgf at x\pgf at y\the\pgf at y}%
@@ -116,7 +54,6 @@
}
-% computes the cross product and puts it into \pgfmathresult
\def\pgfmathcrossproduct#1#2{%
\begingroup
\pgf at process{#1}%
@@ -159,7 +96,6 @@
\endgroup\pgf at temp
}
-% Calculates abs(\pgf at x) + abs(\pgf at y) in #1
\def\pgfpointtaxicabnorm#1{%
\ifdim\pgf at x<0pt
#1=-\pgf at x
@@ -173,24 +109,18 @@
\fi
}
-% Computes the normalised tangents of a given Bezier curve and stores them in \pgf at tmp@tang at i and \pgf at tmp@tang at ii.
-% Also computes the angles and stores them in \pgf at tmp@angle at i and \pgf at tmp@angle at ii.
-% All degenerate cases are covered. For a triple degenerate curve (all points equal), the vector (1,0) is returned.
\def\pgf at offset@compute at tangents#1#2#3#4{%
- \pgf at process{\pgfpointdiff{#1}{#2}}% unintuitively, this is PTii - PTi
+ \pgf at process{\pgfpointdiff{#1}{#2}}%
\pgfpointtaxicabnorm\pgf at xa
\ifdim\pgf at xa<0.1pt\relax
- % edge case: first point and first control point are equal
\pgf at process{\pgfpointdiff{#1}{#3}}%
\pgfpointtaxicabnorm\pgf at xa
\ifdim\pgf at xa<0.1pt\relax
- % edge case: first three points are equal
\pgf at process{\pgfpointdiff{#1}{#4}}%
\fi
\fi
\pgfextract at process\pgf at tmp@tang at i{%
\pgfpointnormalised{}%
- % \pgfpointnormalised stores the angle of the vector in \pgf at tmp
\global\let\pgf at nfold@tmp\pgf at tmp%
}%
\let\pgf at tmp@angle at i\pgf at nfold@tmp%
@@ -208,37 +138,25 @@
}
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% Offsetting a simple section %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\def\pgf at offset@bezier at 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 at offset@compute at tangents{#1}{#2}{#3}{#4}%
\pgf at offset@bezier at segment@{#1}{#2}{#3}{#4}{#5}%
}
-% this version assumes that the tangents have been precomputed in \pgf at tmp@tang at i and @ii
\def\pgf at offset@bezier at segment@#1#2#3#4#5{%
- % offset A1
- % compute the normal
\pgf at tmp@tang at i
\edef\pgf at tmp@normal at i{\noexpand\pgfqpoint{-\the\pgf at y}{\the\pgf at x}}%
\pgfextract at process\pgf at bezier@offset at i
{\pgfpointadd{\pgfpointscale{#5}{\pgf at tmp@normal at i}}{#1}}%
- % offset A4
\pgf at tmp@tang at ii
\edef\pgf at tmp@normal at ii{\noexpand\pgfqpoint{-\the\pgf at y}{\the\pgf at x}}%
\pgfextract at process\pgf at bezier@offset at iv
{\pgfpointadd{\pgfpointscale{#5}{\pgf at tmp@normal at ii}}{#4}}%
- % now compute A'_2 and A'_3
\pgf at process{\pgfpointdiff{#1}{#4}}%
\pgfmathveclen@{\pgf at sys@tonumber\pgf at x}{\pgf at sys@tonumber\pgf at y}%
\let\pgf at tmp@secantlen\pgfmathresult
\ifdim\pgf at 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 at packagewarning{tikz-nfold}{first and last point are too close, expect glitches}%
\pgfextract at process\pgf at bezier@offset at ii
{\pgfpointadd{\pgf at bezier@offset at i}{\pgfpointdiff{#1}{#2}}}%
@@ -248,7 +166,6 @@
\pgfextract at process\pgf at tmp@secant{\pgfpointnormalised{}}%
\pgfmathcrossdot{}{\pgf at tmp@tang at ii}%
\ifdim\pgf at tmp@dot pt<.5pt\relax%
- % this can only happen in non-simple curves
\pgfutil at packagewarning{tikz-nfold}{cosine of \pgf at tmp@dot\space clamped to 0.5 in non-simple segment}%
\def\pgf at tmp@dot{.5}%
\fi%
@@ -255,8 +172,6 @@
\pgfmathdivide@{\pgf at tmp@cross}{\pgf at tmp@dot}%
\let\pgf at tmp@tanbeta\pgfmathresult
\pgfmathcrossdot{\pgf at 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 at tmp@secantlen*(\pgf at tmp@cross - \pgf at tmp@dot*\pgf at tmp@tanbeta)}%
\pgfmath at offset@calculate at scale{\pgf at tmp@secantlen}{\pgf at tmp@cross}{\pgf at tmp@dot}{\pgf at tmp@tanbeta}{#5}%
\pgfextract at process\pgf at bezier@offset at ii{%
\pgfpointadd
@@ -263,7 +178,6 @@
{\pgf at bezier@offset at i}
{\pgfqpointscale{\pgfmathresult}{\pgfpointdiff{#1}{#2}}}%
}%
- % third control point
\pgfmathcrossdot{\pgf at tmp@secant}{\pgf at tmp@tang at i}%
\ifdim\pgf at tmp@dot pt<.5pt\relax
\pgfutil at packagewarning{tikz-nfold}{cosine of \pgf at tmp@dot\space clamped to 0.5 in non-simple segment}%
@@ -272,7 +186,6 @@
\pgfmathdivide@{\pgf at tmp@cross}{\pgf at tmp@dot}%
\let\pgf at tmp@tanbeta\pgfmathresult
\pgfmathcrossdot{\pgf at tmp@secant}{\pgfpointnormalised{\pgfpointdiff{#4}{#3}}}%
- % \pgfmathparse{1 + #5/\pgf at tmp@secantlen*(\pgf at tmp@cross - \pgf at tmp@dot*\pgf at tmp@tanbeta)}%
\pgfmath at offset@calculate at scale{\pgf at tmp@secantlen}{\pgf at tmp@cross}{\pgf at tmp@dot}{\pgf at tmp@tanbeta}{#5}%
\pgfextract at process\pgf at bezier@offset at 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 at offset@calculate at 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 at offset@max at recursion
\newcount\pgf at offset@max at recursion
\pgf at offset@max at 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 at nfold@callback at move}%
}
\def\pgfoffsetcurvenomove#1#2#3#4#5{%
- \pgfoffsetcurvecallback{#1}{#2}{#3}{#4}{#5}{\pgf at nfold@callback at nomove}%
+ \pgfoffsetcurvecallback{#1}{#2}{#3}{#4}{#5}{\pgf at nfold@callback at 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 at nfold@callback at 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 at nfold@callback at 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 at nfold@callback at move) for the parameters
\def\pgfoffsetcurvecallback#1#2#3#4#5#6{%
\edef\pgf at offset@tmp at callback##1##2##3##4##5{%
\noexpand\pgf at offset@bezier at 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 at offset@subdivide
\def\pgf at subdividecurve#1#2#3#4#5#6#7{%
\begingroup%
@@ -369,32 +247,24 @@
\endgroup%
}
-% This macro assumes that the curve is defined in \pgf at ctrl@i-\pgf at ctrl@iv
-% and that its tangents have already been computed.
\def\pgf at subdividecurve@#1#2#3{%
\pgf at offset@subdividefalse%
\c at pgf@counta=#1\relax
\advance\c at pgf@counta by -1
- % Use the non-degenerate tangents for the simplicity check
\pgfextract at process\pgf at itoiv{\pgfpointdiff{\pgf at ctrl@i}{\pgf at ctrl@iv}}%
\pgfmathcrossproduct{\pgf at itoiv}{\pgf at tmp@tang at i}%
\let\firstcross\pgfmathresult
\pgfmathcrossproduct{\pgf at itoiv}{\pgf at tmp@tang at 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 at offset@subdividetrue%
\else%
- % Second simplicity check: How large is the angle between the tangents in A1 and A4?
\pgfmathdotproduct{\pgf at tmp@tang at i}{\pgf at tmp@tang at ii}%
\ifdim\pgfmathresult pt<.5pt\relax%
\pgf at offset@subdividetrue%
\else
- % Third simplicity check: Put a limit on the lengths of the i-ii and iii-iv vectors combined
\pgf at itoiv
\pgfmathveclen@{\pgf at sys@tonumber\pgf at x}{\pgf at sys@tonumber\pgf at y}%
\pgf at xa=\pgfmathresult pt
@@ -404,7 +274,6 @@
\pgf at process{\pgfpointdiff{\pgf at ctrl@iii}{\pgf at ctrl@iv}}%
\pgfmathveclen@{\pgf at sys@tonumber\pgf at x}{\pgf at sys@tonumber\pgf at y}%
\advance\pgf at xb by \pgfmathresult pt
- % veclen(iv-i) < veclen(ii-i) + veclen(iv-iii)
\ifdim\pgf at xa<\pgf at xb
\pgf at offset@subdividetrue
\fi
@@ -412,27 +281,19 @@
\fi%
\ifpgf at offset@subdivide%
\ifnum\c at pgf@counta<0%
- % We hit the recursion limit but the segment is not simple
\pgfutil at packagewarning{tikz-nfold}{Recursion limit reached, glitches may occur. %
Consider increasing \string\pgf at offset@max at recursion}%
- % Try to offset the curve anyway. The result will not be precise,
- % but the code is sufficiently robust to not crash
#3{\pgf at ctrl@i}{\pgf at ctrl@ii}{\pgf at ctrl@iii}{\pgf at ctrl@iv}{#2}%
\else
- % split the non-simple segment and execute recursive calls
\pgf at halfsplitbezier{\pgf at ctrl@i}{\pgf at ctrl@ii}{\pgf at ctrl@iii}{\pgf at 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 at process\pgf at middletangent{%
\pgfpointnormalised{\pgfpointdiff{\pgf at splitbezier@i at iii}{\pgf at splitbezier@i at iv}}}%
\begingroup%
- % we need a group to avoid overwriting variables in recursive calls
\let\pgf at tmp@tang at ii\pgf at middletangent%
\let\pgf at ctrl@i\pgf at splitbezier@i at i%
\let\pgf at ctrl@ii\pgf at splitbezier@i at ii%
\let\pgf at ctrl@iii\pgf at splitbezier@i at iii%
\let\pgf at ctrl@iv\pgf at splitbezier@i at iv%
- % pass on the "start of the curve flag" only to the first term
\pgf at subdividecurve@{\c at pgf@counta}{#2}{#3}%
\endgroup%
\begingroup%
@@ -445,25 +306,16 @@
\endgroup%
\fi%
\else%
- % curve is simple
#3{\pgf at ctrl@i}{\pgf at ctrl@ii}{\pgf at ctrl@iii}{\pgf at 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 at xc=-\pgf at y
Added: trunk/Master/texmf-dist/tex/latex/tikz-nfold/pgflibrarynfold.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/tikz-nfold/pgflibrarynfold.code.tex (rev 0)
+++ trunk/Master/texmf-dist/tex/latex/tikz-nfold/pgflibrarynfold.code.tex 2023-07-23 20:45:55 UTC (rev 67711)
@@ -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 at nfold@index
+\def\pgf at nfold@run at loop{%
+ \pgf at nfold@index=\pgf at nfold@order%
+ \pgf at nfold@run at loop@%
+}
+
+\def\pgf at nfold@run at loop@{%
+ \pgf at nfold@loop at inner%
+ \advance\pgf at nfold@index by -1\relax
+ \ifnum\pgf at nfold@index>0\relax%
+ \pgf at nfold@run at loop@%
+ \fi%
+}
+
+\def\pgf at nfold@loop at inner{%
+ \pgfmathsetmacro{\pgf at nfold@shift at fraction}%
+ {-1+2*(\pgf at nfold@index-1)/(\pgf at nfold@order-1)}%
+ \pgfmathsetmacro{\pgf at nfold@shiftamount}{\pgf at nfold@hwidth*\pgf at nfold@shift at fraction}
+ \pgftransformreset%
+ \parsedpath%
+ \pgfsyssoftpath at flushcurrentpath%
+ \pgf at up@action%
+}
+
+\def\pgf at nfold@compute at widths@from at double{
+ \pgf at x=\pgflinewidth\relax%
+ \pgf at y=\pgf at x\relax%
+ \advance\pgf at x-\pgfinnerlinewidth\relax%
+ \advance\pgf at y+\pgfinnerlinewidth\relax%
+ \pgf at x=.5\pgf at x\relax%
+ \pgf at y=.25\pgf at y\relax%
+}
+
+\def\pgf at nfold@render at cached@softpath{%
+ \pgfscope%
+ \pgf at nfold@compute at widths@from at double%
+ \pgfsetlinewidth\pgf at x%
+ \edef\pgf at nfold@hwidth{\the\pgf at y}%
+ \pgfprocessround{\pgf at nfold@cachedpath}{\pgf at nfold@cachedpath}%
+ \pgf at nfold@parsearrows%
+ \pgf at nfold@parsesoftpath{\pgf at nfold@cachedpath}{\parsedpath}%
+ \pgf at nfold@run at loop%
+ \endpgfscope%
+}
+
+
+\pgfkeys{
+ /pgf/nfold/.code={%
+ \pgf at nfold@order=#1\relax%
+ \ifnum\pgf at nfold@order<1\relax%
+ \pgfutil at packageerror{tikz-nfold}{The key /pgf/nfold must take a value of at least 1, got \the\pgf at nfold@order}{}%
+ \fi%
+ \ifnum\pgf at nfold@order>\pgf at nfold@intersec at numcached\relax
+ \ifdefined\pgfintersectionofpaths\else
+ \pgf at nfold@intersectionsnotloadedtrue
+ \fi
+ \fi
+ },
+ /pgf/nfold/.default=2
+}
+
+\endinput
Property changes on: trunk/Master/texmf-dist/tex/latex/tikz-nfold/pgflibrarynfold.code.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/tex/latex/tikz-nfold/pgflibraryoffsetpath.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/tikz-nfold/pgflibraryoffsetpath.code.tex (rev 0)
+++ trunk/Master/texmf-dist/tex/latex/tikz-nfold/pgflibraryoffsetpath.code.tex 2023-07-23 20:45:55 UTC (rev 67711)
@@ -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 at nfold@cached at miterlimit{10}
+\let\pgf at nfold@old at miterlimit\pgfsetmiterlimit
+\def\pgfsetmiterlimit#1{%
+ \pgf at nfold@old at miterlimit{#1}%
+ \edef\pgf at nfold@cached at miterlimit{#1}%
+}
+
+\global\let\pgf at cached@linejoin=m%
+\let\pgf at nfold@old at setbeveljoin\pgfsetbeveljoin
+\let\pgf at nfold@old at setmiterjoin\pgfsetmiterjoin
+\let\pgf at nfold@old at setroundjoin\pgfsetroundjoin
+\def\pgfsetbeveljoin{%
+ \pgf at nfold@old at setbeveljoin%
+ \let\pgf at cached@linejoin=b%
+}
+\def\pgfsetmiterjoin{%
+ \pgf at nfold@old at setmiterjoin%
+ \let\pgf at cached@linejoin=m%
+}
+\def\pgfsetroundjoin{%
+ \pgf at nfold@old at setroundjoin%
+ \let\pgf at cached@linejoin=r%
+}
+
+
+
+\def\pgf at nfold@miterjoin{
+ \pgfpathlineto{
+ \pgfpointadd{\pgf at nfold@join at centre}{%
+ \pgfpointpolar{\pgf at nfold@firstang+.5*\pgf at nfold@deltaphi+90}%
+ {\pgf at nfold@shiftamount/cos(.5*\pgf at nfold@deltaphi)}%
+ }%
+ }%
+}
+
+\def\pgf at nfold@beveljoin{
+ \pgfmathsetlengthmacro{\bevelouterprotrusion}%
+ {\pgf at nfold@shortenstartjoin pt - .5*\pgflinewidth*abs(tan(.25*\pgf at nfold@deltaphi))}
+ \pgfmathsetmacro{\bevelshorten}{2*\insidepercentage*abs(tan(.25*\pgf at nfold@deltaphi))}
+ \pgfmathparse{\bevelshorten < abs(sin(.5*\pgf at nfold@deltaphi))}
+ \ifnum\pgfmathresult=1\relax
+ \pgfmathsetlengthmacro{\bevelextension}{\bevelouterprotrusion-\bevelshorten*\pgf at nfold@hwidth}
+ \pgfpointadd{\pgf at nfold@join at start}{\pgfpointpolar{\pgf at nfold@firstang}{\bevelextension}}
+ \pgfpathlineto{}
+ \pgfpointadd{\pgf at nfold@join at end}{\pgfpointpolar{\pgf at nfold@secondang}{-\bevelextension}}
+ \pgfpathlineto{}
+ \else
+ \pgf at nfold@miterjoin
+ \fi
+}
+
+\def\pgf at nfold@roundjoin{
+ \ifdim\insidepercentage pt<.5pt\relax
+ \pgfpointadd{\pgf at nfold@join at start}{\pgfpointpolar{\pgf at nfold@firstang}{\pgf at nfold@shortenstartjoin}}
+ \pgfpathlineto{}
+ \pgfmathsetmacro\pgf at tmp@firstang{\pgf at nfold@firstang+90*\turnindicator}
+ \pgfpatharc%
+ {\pgf at tmp@firstang}%
+ {\pgf at tmp@firstang+\pgf at nfold@deltaphi}%
+ {abs(\pgf at nfold@shift at fraction)*\pgf at nfold@hwidth}%
+ \else
+ \pgf at nfold@miterjoin
+ \fi
+}
+
+\def\pgf at nfold@token at join#1#2#3#4#5#6#7#8{%
+ \def\pgf at nfold@join at centre{#1}%
+ \def\pgf at nfold@join at prevend{#2}%
+ \def\pgf at nfold@join at nextstart{#3}%
+ \def\pgf at nfold@firstang{#4}%
+ \def\pgf at nfold@secondang{#5}%
+ \pgfextract at process\pgf at nfold@join at start{%
+ \pgfpointadd{#2}{\pgfpointpolar{\pgf at nfold@firstang+90}{\pgf at nfold@shiftamount}}}%
+ \pgfextract at process\pgf at nfold@join at end{%
+ \pgfpointadd{#3}{\pgfpointpolar{\pgf at nfold@secondang+90}{\pgf at nfold@shiftamount}}}%
+ \pgf at process{\pgfpointdiff{\pgf at nfold@join at start}{\pgf at nfold@join at end}}
+ \pgfpointtaxicabnorm\pgfutil at tempdima
+ \ifdim\pgfutil at tempdima>0.1pt\relax
+ \def\pgf at nfold@deltaphi{#6}%
+ \def\pgf at nfold@shortenstartjoin{#7}%
+ \ifdim\pgf at nfold@deltaphi pt<0pt
+ \def\turnindicator{1}
+ \else
+ \def\turnindicator{-1}
+ \fi
+ \pgfutil at tempdima=\pgf at nfold@shift at fraction pt\relax
+ \pgfutil at tempdima=\turnindicator\pgfutil at tempdima
+ \advance\pgfutil at tempdima by-1pt\relax
+ \pgfutil at tempdima=-.5\pgfutil at tempdima
+ \edef\insidepercentage{\pgf at sys@tonumber\pgfutil at tempdima}%
+ #8%
+ \fi
+}
+
+
+\def\pgf at nfold@process at join{%
+ \pgf at xa=\pgf at nfold@deltaphi at start pt\relax
+ \ifdim\pgf at xa<0pt\relax
+ \pgf at xa=-\pgf at xa
+ \fi
+ \ifdim\pgf at xa>1pt\relax
+ \edef\pgf at nfold@jointype{\pgf at cached@linejoin}
+ \if\pgf at cached@linejoin m%
+ \pgf at xa=.5\pgf at xa
+ \pgfmathcos@{\pgf at sys@tonumber\pgf at xa}
+ \pgf at xa=\pgfmathresult pt\relax
+ \pgf at xa=\pgf at nfold@cached at miterlimit\pgf at xa
+ \ifdim\pgf at xa>1pt\relax
+ \def\pgf at nfold@tmp at joinmacro{\pgf at nfold@miterjoin}
+ \else
+ \def\pgf at nfold@tmp at joinmacro{\pgf at nfold@beveljoin}
+ \fi
+ \else
+ \if b\pgf at cached@linejoin\relax
+ \def\pgf at nfold@tmp at joinmacro{\pgf at nfold@beveljoin}
+ \else
+ \def\pgf at nfold@tmp at joinmacro{\pgf at nfold@roundjoin}
+ \fi
+ \fi
+ \edef\pgf at nfold@macrotoadd{%
+ \noexpand\pgf at nfold@token at join{\pgf at nfold@cur at first}{\pgf at nfold@prev at segment@end}
+ {\pgf at nfold@cur at movedfirst}{\pgf at nfold@prev at angle@ii}{\pgf at nfold@cur at angle@i}%
+ {\pgf at nfold@deltaphi at start}{\pgf at nfold@shortenstartjoin}{%
+ \expandafter\noexpand\pgf at nfold@tmp at joinmacro%
+ \expandafter\noexpand\ifpgf at nfold@closejoinsedgecase%
+ \pgf at nfold@token at finish@edgecase{\pgf at nfold@cur at movedlast}%
+ \else%
+ \pgf at nfold@token at finish@normal%
+ \fi%
+ }%
+ }%
+ \pgf at nfold@addmacro\pgf at parsed@cur at conn@seg%
+ \fi%
+}
+
+
+\def\pgf at nfold@token at finish@normal{%
+ \pgfpathlineto{\pgf at nfold@join at end}%
+}
+
+\def\pgf at nfold@token at finish@edgecase#1{%
+ \pgf at nfold@join at end%
+ \ifdim\insidepercentage pt<.5pt\relax%
+ \pgf at process{\pgfpointadd{#1}{\pgfpointpolar{\pgf at nfold@secondang+90}{\pgf at nfold@shiftamount}}}
+ \fi%
+ \pgfpathlineto{}%
+}
+
+
+
+\newif\ifpgf at nfold@continuesegment
+\newif\ifpgf at nfold@closejoinsedgecase
+\newif\ifpgf at nfold@angletoosharp
+\newif\ifpgf at nfold@intersectionsnotloaded
+\newif\ifpgf at nfold@lastconnsubpath
+
+
+\def\pgf at nfold@process at segment{%
+ \if\pgf at nfold@cur at visible0
+ \if\pgf at nfold@cur at type m
+ \if\pgf at nfold@start at arrowcode1
+ \ifpgf at nfold@lastconnsubpath
+ \if\pgf at nfold@prev at type f
+ \if\pgf at nfold@next at visible1
+ \edef\pgf at nfold@macrotoadd{%
+ \noexpand\pgf at nfold@extendtotip{s}{\pgf at nfold@cur at last}{\pgf at nfold@next at angle@i}
+ }%
+ \pgf at nfold@addmacro\pgf at parsed@cur at conn@seg%
+ \let\pgf at nfold@cur at type l
+ \let\pgf at nfold@cur at visible1
+ \let\pgf at nfold@cur at angle@ii\pgf at nfold@next at angle@i
+ \let\pgf at nfold@cur at tang@ii\pgf at nfold@next at tang@i
+ \def\pgf at nfold@deltaphi at end{0}
+ \pgf at nfold@angletoosharpfalse
+ \fi
+ \fi%
+ \fi
+ \fi
+ \fi%
+ \else%
+ \let\pgf at nfold@cur at movedfirst\pgf at nfold@cur at first
+ \let\pgf at nfold@cur at movedlast\pgf at nfold@cur at last
+ \def\pgf at nfold@shortenstartjoin{0}
+ \def\pgf at nfold@shortenendjoin{0}
+ \pgf at nfold@closejoinsedgecasefalse
+ \if\pgf at nfold@prev at visible0
+ \pgf at nfold@continuesegmentfalse
+ \else
+ \pgf at nfold@continuesegmenttrue
+ \let\pgf at nfold@deltaphi at start\pgf at nfold@deltaphi at end
+ \pgf at xb=\pgf at nfold@deltaphi at start pt\relax
+ \ifdim\pgf at xb<0pt\relax
+ \pgf at xb=-\pgf at xb
+ \fi
+ \ifpgf at nfold@angletoosharp\else
+ \ifdim\pgf at xb>0.5pt\relax
+ \pgf at yb=.5\pgf at xb
+ \pgfmathtan@{\pgf at sys@tonumber\pgf at yb}
+ \pgf at yb=\pgf at nfold@hwidth\relax
+ \pgf at yb=\pgfmathresult\pgf at yb
+ \edef\pgf at nfold@shortenstartjoin{\pgf at sys@tonumber\pgf at yb}
+ \pgfextract at process\pgf at nfold@cur at movedfirst{%
+ \pgfpointadd{\pgf at nfold@cur at first}%
+ {\pgfqpointscale{\pgf at nfold@shortenstartjoin}{\pgf at nfold@cur at tang@i}}}%
+ \if\pgf at nfold@cur at type c
+ \pgf at process{\pgfpointdiff{\pgf at nfold@cur at first}{\pgf at nfold@cur at supporta}}
+ \pgfmathveclen@{\pgf at sys@tonumber\pgf at x}{\pgf at sys@tonumber\pgf at y}
+ \ifdim\pgfmathresult pt>0.1pt\relax
+ \pgfmathveclen@{\pgfmathresult}{\pgf at sys@tonumber\pgf at yb}
+ \pgfextract at process\pgf at nfold@cur at supporta{\pgfpointadd%
+ {\pgf at nfold@cur at first}%
+ {\pgfqpointscale{\pgfmathresult}{\pgf at nfold@cur at tang@i}}}%
+ \else
+ \let\pgf at nfold@cur at supporta\pgf at nfold@cur at movedfirst
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ \if\pgf at nfold@next at visible1
+ \pgfmathsubtract@{\pgf at nfold@next at angle@i}{\pgf at nfold@cur at angle@ii}
+ \pgf at nfold@clampangle
+ \edef\pgf at nfold@deltaphi at end{\pgfmathresult}
+ \pgf at xb=\pgf at nfold@deltaphi at end pt\relax
+ \ifdim\pgf at xb<0pt\relax
+ \pgf at xb=-\pgf at xb
+ \fi
+ \ifdim\pgf at xb>178pt\relax
+ \pgfutil at packagewarning{tikz-nfold}{Angle too sharp, expect visual errors}
+ \pgf at nfold@angletoosharptrue
+ \else
+ \pgf at nfold@angletoosharpfalse
+ \ifdim\pgf at xb>0.5pt\relax
+ \pgf at yb=.5\pgf at xb
+ \pgfmathtan@{\pgf at sys@tonumber\pgf at yb}
+ \pgf at yb=\pgf at nfold@hwidth\relax
+ \pgf at yb=\pgfmathresult\pgf at yb
+ \edef\pgf at nfold@shortenendjoin{\pgf at sys@tonumber\pgf at yb}
+ \pgf at yb=-\pgf at yb
+ \pgfextract at process\pgf at nfold@cur at movedlast{%
+ \pgfpointadd{\pgf at nfold@cur at last}%
+ {\pgfqpointscale{-\pgf at nfold@shortenendjoin}{\pgf at nfold@cur at tang@ii}}}%
+ \pgfextract at process\pgf at nfold@cur at movedlast{%
+ \pgfpointadd{\pgf at nfold@cur at last}%
+ {\pgfqpointpolar{\pgf at nfold@cur at angle@ii}{\pgf at yb}}}%
+ \if\pgf at nfold@cur at type c
+ \pgf at process{\pgfpointdiff{\pgf at nfold@cur at supportb}{\pgf at nfold@cur at last}}
+ \pgfmathveclen@{\pgf at sys@tonumber\pgf at x}{\pgf at sys@tonumber\pgf at y}
+ \ifdim\pgfmathresult pt>0.1pt\relax
+ \pgfmathveclen@{\pgfmathresult}{\pgf at sys@tonumber\pgf at yb}
+ \pgfextract at process\pgf at nfold@cur at supportb{\pgfpointadd%
+ {\pgf at nfold@cur at last}%
+ {\pgfqpointscale{-\pgfmathresult}{\pgf at nfold@cur at tang@ii}}}%
+ \else
+ \let\pgf at nfold@cur at supportb\pgf at nfold@cur at movedlast
+ \fi
+ \fi
+ \fi
+ \fi
+ \if\pgf at nfold@cur at type l
+ \pgf at process{\pgfpointdiff{\pgf at nfold@cur at first}{\pgf at nfold@cur at last}}
+ \pgfmathveclen@{\pgf at sys@tonumber\pgf at x}{\pgf at sys@tonumber\pgf at y}
+ \pgf at xa=\pgf at nfold@shortenstartjoin pt\relax
+ \advance\pgf at xa by\pgf at nfold@shortenendjoin pt\relax
+ \ifdim\pgf at xa>\pgfmathresult pt\relax
+ \pgf at nfold@closejoinsedgecasetrue
+ \fi
+ \fi
+ \fi%
+ \if\pgf at nfold@prev at visible0%
+ \ifpgf at nfold@closejoinsedgecase
+ \edef\pgf at nfold@macrotoadd{%
+ \noexpand\pgf at nfold@token at edgecase@movetostart{\pgf at nfold@cur at movedfirst}{\pgf at nfold@cur at angle@i}%
+ }%
+ \pgf at nfold@addmacro\pgf at parsed@cur at conn@seg%
+ \fi
+ \else
+ \ifpgf at nfold@angletoosharp\else
+ \if\pgf at nfold@cur at type z\else
+ \pgf at nfold@process at join
+ \fi
+ \fi
+ \fi
+ \let\pgf at nfold@prev at segment@end\pgf at nfold@cur at movedlast
+ \if\pgf at nfold@cur at type i
+ \let\pgf at nfold@connsubpath at tang@i\pgf at nfold@next at tang@i%
+ \let\pgf at nfold@connsubpath at angle@i\pgf at nfold@next at angle@i%
+ \fi
+ \if\pgf at nfold@cur at type l
+ \ifpgf at nfold@closejoinsedgecase\else
+ \edef\pgf at nfold@macrotoadd{%
+ \expandafter\noexpand\ifpgf at nfold@continuesegment%
+ \pgf at nfold@token at lineto@continue%
+ \else%
+ \pgf at nfold@token at lineto%
+ \fi{\pgf at nfold@cur at movedfirst}{\pgf at nfold@cur at movedlast}{\pgf at nfold@cur at tang@i}%
+ }%
+ \pgf at nfold@addmacro\pgf at parsed@cur at conn@seg%
+ \fi
+ \fi
+ \if\pgf at nfold@cur at type o
+ \def\pgf at nfold@macrotoadd{\pgf at nfold@token at closepath}%
+ \pgf at nfold@addmacro\pgf at parsed@cur at conn@seg%
+ \fi
+ \if\pgf at nfold@cur at type z
+ \def\pgf at nfold@macrotoadd{\pgf at nfold@token at closepath}%
+ \pgf at nfold@addmacro\pgf at parsed@cur at conn@seg%
+ \fi
+ \if\pgf at nfold@cur at type c
+ \ifpgf at nfold@continuesegment
+ \pgf at subdividecurve{\pgf at nfold@cur at movedfirst}{\pgf at nfold@cur at supporta}{\pgf at nfold@cur at supportb}{\pgf at nfold@cur at movedlast}{\pgf at offset@max at recursion}{0}{\pgf at nfold@addcurvesegment at callback@continue}
+ \else
+ \pgf at subdividecurve{\pgf at nfold@cur at movedfirst}{\pgf at nfold@cur at supporta}{\pgf at nfold@cur at supportb}{\pgf at nfold@cur at movedlast}{\pgf at offset@max at recursion}{0}{\pgf at nfold@addcurvesegment at callback}%
+ \fi
+ \fi
+ \if\pgf at nfold@cur at type i
+ \edef\pgf at nfold@macrotoadd{%
+ \noexpand\pgf at nfold@token at invisibleline{\pgf at nfold@cur at movedfirst}{\pgf at nfold@cur at movedlast}{\pgf at nfold@cur at tang@i}%
+ }%
+ \pgf at nfold@addmacro\pgf at parsed@cur at conn@seg%
+ \fi
+ \if\pgf at nfold@next at type t%
+ \ifnum\pgf at nfold@end at arrowcode=1
+ \edef\pgf at nfold@macrotoadd{%
+ \noexpand\pgf at nfold@extendtotip{e}{\pgf at nfold@cur at last}{\pgf at nfold@cur at angle@ii}}%
+ \pgf at nfold@addmacro\pgf at parsed@cur at conn@seg%
+ \fi%
+ \fi%
+ \fi%
+}
+
+
+\def\pgf at nfold@addcurvesegment at callback#1#2#3#4#5{%
+ \if#50%
+ \edef\pgf at nfold@macrotoadd{%
+ \noexpand\pgf at nfold@token at curveto{#1}{#2}{#3}{#4}{\pgf at tmp@tang at i}{\pgf at tmp@tang at ii}%
+ }%
+ \pgf at nfold@addmacro\pgf at parsed@cur at conn@seg%
+ \else%
+ \pgf at nfold@addcurvesegment at callback@continue{#1}{#2}{#3}{#4}{#5}%
+ \fi%
+}
+
+\def\pgf at nfold@addcurvesegment at callback@continue#1#2#3#4#5{%
+ \edef\pgf at nfold@macrotoadd{%
+ \noexpand\pgf at nfold@token at curveto@continue{#1}{#2}{#3}{#4}{\pgf at tmp@tang at i}{\pgf at tmp@tang at ii}%
+ }%
+ \pgf at nfold@addmacro\pgf at parsed@cur at conn@seg%
+}
+
+
+
+\expandafter\def\csname pgf at nfold@intersec at cache@2 at 3\endcsname{\pgfqpoint{2pt}{0pt}}
+\expandafter\def\csname pgf at nfold@intersec at cache@2 at 4\endcsname{\pgfqpoint{0.94063pt}{-0.33333pt}}
+\expandafter\def\csname pgf at nfold@intersec at cache@3 at 4\endcsname{\pgfqpoint{0.94063pt}{0.33333pt}}
+\expandafter\def\csname pgf at nfold@intersec at cache@2 at 5\endcsname{\pgfqpoint{0.64167pt}{-0.5pt}}
+\expandafter\def\csname pgf at nfold@intersec at cache@3 at 5\endcsname{\pgfqpoint{2pt}{0pt}}
+\expandafter\def\csname pgf at nfold@intersec at cache@4 at 5\endcsname{\pgfqpoint{0.64167pt}{0.5pt}}
+\def\pgf at nfold@intersec at numcached{5}
+
+\newif\ifpgf at nfold@ontheedge
+\def\pgf at nfold@extendtotip#1#2#3{
+ \ifpgf at nfold@intersectionsnotloaded
+ \pgfutil at packageerror{tikz-nfold}{%
+ If `nfold' is larger than \pgf at nfold@intersec at numcached\space and you use
+ an `Implies' arrow tip you need to say \string\usetikzlibrary{intersections}}{}
+ \else
+ \pgf at nfold@ontheedgetrue
+ \ifnum\pgf at nfold@index>1\relax\ifnum\pgf at nfold@index<\pgf at nfold@order\relax%
+ \pgf at nfold@ontheedgefalse
+ \fi\fi
+ \ifpgf at nfold@ontheedge%
+ \if#1s
+ \pgfpathmoveto{\pgfpointadd{#2}{\pgfpointpolar{#3+90}{\pgf at nfold@shiftamount}}}%
+ \fi
+ \else
+ \ifcsname pgf at nfold@intersec at cache@\the\pgf at nfold@index @\the\pgf at nfold@order\endcsname
+ \pgfextract at process\pgf at nfold@arrowintersect
+ {\csname pgf at nfold@intersec at cache@\the\pgf at nfold@index @\the\pgf at 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 at nfold@shift at fraction pt}}
+ \pgfpathlineto{\pgfqpoint{3pt}{\pgf at nfold@shift at fraction pt}}
+ }
+ \ifnum\pgfintersectionsolutions>0
+ \pgfextract at process\pgf at nfold@arrowintersect{\pgfpointintersectionsolution{1}}%
+ \immediate\write17{tikz-nfold: computed intersection cache@\the\pgf at nfold@index @\the\pgf at nfold@order: \string\pgfqpoint{\the\pgf at x}{\the\pgf at y}^^J}
+ \expandafter\xdef\csname pgf at nfold@intersec at cache@\the\pgf at nfold@index @\the\pgf at nfold@order\endcsname{\noexpand\pgfqpoint{\the\pgf at x}{\the\pgf at y}}
+ \else
+ \pgfutil at packagewarning{tikz-nfold}{did not find intersection}
+ \pgfextract at process\pgf at nfold@arrowintersect{\pgfqpoint{0pt}{\pgf at nfold@shift at fraction pt}}%
+ \fi
+ \fi%
+ \begingroup
+ \pgftransformreset
+ \pgftransformshift{#2}
+ \pgftransformrotate{#3}
+ \if#1s
+ \pgftransformxscale{-1}
+ \fi
+ \pgfutil at tempdima=\pgf at nfold@hwidth
+ \pgfutil at tempdima=\pgf at nfold@shift at fraction\pgfutil at tempdima
+ \pgfextract at process\pgf at nfold@startofextension
+ {\pgfpointtransformed{\pgfqpoint{0pt}{\pgfutil at tempdima}}}
+ \pgftransformshift{\pgfqpoint{.42\pgflinewidth}{0pt}}
+ \pgftransformscale{\pgf at nfold@hwidth}
+ \pgfextract at process\pgf at nfold@arrowintersect{\pgfpointtransformed{\pgf at nfold@arrowintersect}}
+ \global\let\pgf at nfold@startofextension\pgf at nfold@startofextension
+ \global\let\pgf at nfold@arrowintersect\pgf at nfold@arrowintersect
+ \endgroup
+ \if#1s
+ \pgfpathmoveto{\pgf at nfold@arrowintersect}
+ \pgfpathlineto{\pgf at nfold@startofextension}
+ \else\if#1e
+ \pgfpathlineto{\pgf at nfold@arrowintersect}
+ \else
+ \pgfutil at packageerror{tikz-nfold}{Invalid argument to \string\pgf at nfold@extendtotip: \meaning#1}{}
+ \fi\fi
+ \pgftransformreset
+ \fi%
+ \fi%
+}
+
+
+\def\pgf at nfold@start at arrowcode{0}
+\def\pgf at nfold@end at arrowcode{0}
+
+\def\pgf at nfold@parsearrows{
+ \ifpgfutil at tempswa%
+ \expandafter\pgf at nfold@parsearrowmacro\pgf at start@tip at sequence\relax
+ \let\pgf at nfold@start at arrowcode\pgf at nfold@detectedarrow
+ \expandafter\pgf at nfold@parsearrowmacro\pgf at end@tip at sequence\relax
+ \let\pgf at nfold@end at arrowcode\pgf at nfold@detectedarrow
+ \else
+ \def\pgf at nfold@start at arrowcode{0}
+ \def\pgf at nfold@end at arrowcode{0}
+ \fi
+}
+
+\def\pgf at nfold@parsearrowmacro#1{%
+ \def\pgf at nfold@detectedarrow{0}
+ \ifx#1\relax
+ \let\pgf at next\relax
+ \else
+ \ifx#1\pgf at arrow@handle
+ \let\pgf at next\pgf at nfold@parse at arrow@handle
+ \else
+ \ifx#1\pgf at arrow@handle at shorthand@empty
+ \let\pgf at next\pgf at nfold@parse at shorthandempty
+ \else
+ \let\pgf at next\pgfutil at gobble@until at relax
+ \fi
+ \fi
+ \fi
+ \pgf at next
+}
+
+\def\pgf at nfold@param at Implies{Implies}
+
+\def\pgf at nfold@parse at arrow@handle#1{%
+ \def\pgf at tmp{#1}
+ \ifx\pgf at tmp\pgf at nfold@param at Implies
+ \def\pgf at nfold@detectedarrow{1}
+ \fi
+ \pgfutil at gobble@until at relax
+}
+
+\def\pgf at nfold@parse at shorthandempty#1{
+ \expandafter\def\expandafter\pgf at tmp\expandafter{#1}
+ \expandafter\pgf at nfold@parsearrowmacro\pgf at tmp\relax
+ \pgfutil at gobble@until at relax
+}
+
+
+
+\newcount\pgf at nfold@order
+\pgf at nfold@order=1
+
+\def\pgf at nfold@preparenfoldpath{%
+ \ifnum\pgf at nfold@order>1\relax
+ \ifdim\pgfinnerlinewidth>0pt\relax
+ \pgfsyssoftpath at getcurrentpath\pgf at nfold@cachedpath%
+ \pgfsyssoftpath at setcurrentpath\pgfutil at empty%
+ \else
+ \pgfutil at packageerror{tikz-nfold}{Must set \string\pgfinnerlinewidth\space to use nfold, e.g. by setting /tikz/double distance}{}
+ \fi
+ \fi
+}
+
+\let\pgf at nfold@old at path@check at proper\pgf at path@check at proper
+\def\pgf at path@check at proper{%
+ \pgf at nfold@old at path@check at proper%
+ \ifpgfutil at tempswa\else%
+ \pgf at nfold@preparenfoldpath%
+ \fi%
+}
+
+\let\pgf at nfold@old at prepare@start at of@path\pgf at prepare@start at of@path
+\def\pgf at prepare@start at of@path{%
+ \pgf at nfold@old at prepare@start at of@path%
+ \pgf at nfold@preparenfoldpath%
+}
+
+\let\pgf at nfold@old at stroke@inner at line\pgf at stroke@inner at line
+\def\pgf at stroke@inner at line{%
+ \ifnum\pgf at nfold@order>1\relax%
+ \pgf at nfold@render at cached@softpath%
+ \else%
+ \pgf at nfold@old at stroke@inner at line%
+ \fi%
+}
+
+
+
+
+\def\pgf at nfold@parsemoveto#1#2{%
+ \ifx\pgf at cur@conn at subpath\pgfutil at empty%
+ \def\pgf at nfold@parser at last@moveto{{#1}{#2}}%
+ \def\pgf at cur@conn at subpath{\relax}%
+ \else%
+ \def\pgf at nfold@macrotoadd{\pgf at nfold@processmoveto{#1}{#2}}%
+ \pgf at nfold@addmacro\pgf at cur@conn at subpath%
+ \pgf at nfold@lastconnsubpathfalse%
+ \pgf at nfold@process at conn@subpath%
+ \let\pgf at nfold@last at closepath@from\pgfutil at empty%
+ \let\pgf at cur@conn at subpath\pgfutil at empty%
+ \pgf at nfold@parser at setupfirst%
+ \def\pgf at nfold@parser at last@moveto{{#1}{#2}}%
+ \fi%
+ \pgf at nfold@parsesoftpath at finish{#1}{#2}%
+}
+
+\def\pgf at nfold@parselineto#1#2{%
+ \def\pgf at nfold@macrotoadd{\pgf at nfold@processlineto{#1}{#2}}%
+ \pgf at nfold@addmacro\pgf at cur@conn at subpath%
+ \pgf at nfold@parsesoftpath at finish{#1}{#2}%
+}
+
+\def\pgf at nfold@parseclosepath#1#2{%
+ \let\pgf at nfold@last at closepath@from\pgf at nfold@parser at previous@pt%
+ \def\pgf at nfold@macrotoadd{\pgf at nfold@processclosepath{#1}{#2}}%
+ \pgf at nfold@addmacro\pgf at cur@conn at subpath%
+ \pgf at nfold@parsesoftpath at finish{#1}{#2}%
+}
+
+\def\pgf at nfold@parsecurveto#1#2{%
+ \edef\pgf at nfold@macrotoadd{\noexpand\pgf at nfold@processcurveto\pgf at nfold@parser at supporta\pgf at nfold@parser at supportb{#1}{#2}}%
+ \pgf at nfold@addmacro\pgf at cur@conn at subpath%
+ \pgf at nfold@parsesoftpath at finish{#1}{#2}%
+}
+
+\def\pgf at nfold@parserect#1#2#3#4{%
+ \pgf at nfold@parsemoveto{#1}{#2}%
+ \pgf at xc=#1\relax
+ \pgf at yc=#2\relax
+ \pgf at xd=#3\relax
+ \pgf at yd=#4\relax
+ \advance\pgf at yc\pgf at yd%
+ \edef\pgf at temp{{\the\pgf at xc}{\the\pgf at yc}}%
+ \expandafter\pgf at nfold@parselineto\pgf at temp%
+ \advance\pgf at xc\pgf at xd%
+ \edef\pgf at temp{{\the\pgf at xc}{\the\pgf at yc}}%
+ \expandafter\pgf at nfold@parselineto\pgf at temp%
+ \advance\pgf at yc-\pgf at yd%
+ \edef\pgf at temp{{\the\pgf at xc}{\the\pgf at yc}}%
+ \expandafter\pgf at nfold@parselineto\pgf at temp%
+ \advance\pgf at xc-\pgf at xd%
+ \edef\pgf at temp{{\the\pgf at xc}{\the\pgf at yc}}%
+ \expandafter\pgf at nfold@parseclosepath\pgf at temp%
+ \pgf at nfold@parsemoveto{#1}{#2}%
+}
+
+
+\def\pgf at nfold@parsesoftpath#1#2{%
+ \let\pgf at cur@conn at subpath\pgfutil at empty%
+ \let\pgf at all@parsed at subpaths\pgfutil at empty%
+ \edef\pgf at nfold@parser at last@moveto{{\the\pgf at path@lastx}{\the\pgf at path@lasty}}%
+ \let\pgf at nfold@last at closepath@from\pgfutil at empty%
+ \pgf at nfold@parser at setupfirst%
+ \expandafter\pgf at nfold@@parsesoftpath#1\pgf at stop{}{}%
+ \let#2\pgf at all@parsed at subpaths%
+}%
+
+\def\pgf at nfold@@parsesoftpath#1#2#3{%
+ \let\pgf at next\pgf at nfold@@parsesoftpath%
+ \ifx#1\pgf at stop%
+ \def\pgf at nfold@macrotoadd{\pgf at nfold@processlast}%
+ \pgf at nfold@addmacro\pgf at cur@conn at subpath%
+ \pgf at nfold@lastconnsubpathtrue%
+ \pgf at nfold@process at conn@subpath%
+ \let\pgf at next\relax%
+ \else%
+ \ifx#1\pgfsyssoftpath at movetotoken%
+ \pgf at nfold@parsemoveto{#2}{#3}%
+ \else%
+ \ifx#1\pgfsyssoftpath at linetotoken%
+ \pgf at nfold@parselineto{#2}{#3}%
+ \else%
+ \ifx#1\pgfsyssoftpath at curvetosupportatoken%
+ \def\pgf at nfold@parser at supporta{{#2}{#3}}%
+ \else%
+ \ifx#1\pgfsyssoftpath at curvetosupportbtoken%
+ \def\pgf at nfold@parser at supportb{{#2}{#3}}%
+ \else%
+ \ifx#1\pgfsyssoftpath at curvetotoken%
+ \pgf at nfold@parsecurveto{#2}{#3}%
+ \else%
+ \ifx#1\pgfsyssoftpath at closepathtoken%
+ \pgf at nfold@parseclosepath{#2}{#3}%
+ \else%
+ \ifx#1\pgfsyssoftpath at rectcornertoken%
+ \def\pgf at nfold@parser at rectcorner{{#2}{#3}}%
+ \else%
+ \ifx#1\pgfsyssoftpath at rectsizetoken%
+ \expandafter\pgf at nfold@parserect\pgf at nfold@parser at rectcorner{#2}{#3}%
+ \else%
+ \pgfutil at packageerror{tikz-nfold}{Unrecognised soft path token `#1'}{}%
+ \fi%
+ \fi%
+ \fi%
+ \fi%
+ \fi%
+ \fi%
+ \fi%
+ \fi%
+ \fi%
+ \pgf at next%
+}%
+
+\def\pgf at nfold@parsesoftpath at finish#1#2{%
+ \def\pgf at nfold@parser at previous@pt{{#1}{#2}}%
+ \let\pgf at nfold@sectolast at segment\pgf at nfold@last at segment%
+ \let\pgf at nfold@last at segment\pgf at nfold@macrotoadd%
+}
+
+\def\pgf at nfold@process at conn@subpath{%
+ \let\pgf at parsed@cur at conn@seg\pgfutil at empty%
+ \ifx\pgf at nfold@last at closepath@from\pgfutil at empty%
+ \expandafter\pgf at nfold@processmoveto\pgf at nfold@parser at last@moveto%
+ \else%
+ \expandafter\pgf at nfold@processmoveto\pgf at nfold@last at closepath@from%
+ \expandafter\pgf at nfold@processinvisibleline\pgf at nfold@parser at last@moveto%
+ \fi%
+ \pgf at cur@conn at subpath%
+ \let\pgf at nfold@macrotoadd\pgf at parsed@cur at conn@seg%
+ \pgf at nfold@addmacro\pgf at all@parsed at subpaths%
+}
+
+
+\def\pgf at nfold@processmoveto#1#2{%
+ \pgf at nfold@process at moveup%
+ \let\pgf at nfold@next at type=m%
+ \let\pgf at nfold@next at visible=0%
+ \edef\pgf at nfold@next at last{\pgf at x#1\pgf at y#2}%
+ \pgf at nfold@process at segment%
+}%
+
+\def\pgf at nfold@process at line@common#1#2#3{%
+ \pgf at nfold@process at moveup%
+ \pgfextract at process\pgf at tmp@tang at i{\pgfpointnormalised{}\global\let\pgf at nfold@tmp\pgf at tmp}
+ \let\pgf at nfold@next at type=#3%
+ \let\pgf at nfold@next at visible=1%
+ \let\pgf at nfold@next at tang@i\pgf at tmp@tang at i
+ \let\pgf at nfold@next at tang@ii\pgf at tmp@tang at i
+ \let\pgf at nfold@next at angle@i\pgf at nfold@tmp
+ \let\pgf at nfold@next at angle@ii\pgf at nfold@tmp
+ \let\pgf at nfold@next at first\pgf at nfold@cur at last
+ \def\pgf at nfold@next at last{\pgf at x#1\pgf at y#2}%
+ \pgf at nfold@process at segment%
+}
+
+\def\pgf at nfold@processlineto#1#2{%
+ \pgf at process{\pgfpointdiff{\pgf at nfold@next at last}{\pgf at x#1\pgf at y#2}}%
+ \pgfpointtaxicabnorm\pgf at xa%
+ \ifdim\pgf at xa>.1pt\relax%
+ \pgf at nfold@process at line@common{#1}{#2}{l}%
+ \fi%
+}%
+
+\def\pgf at nfold@processcurveto#1#2#3#4#5#6{%
+ \pgf at nfold@process at moveup%
+ \pgf at offset@compute at tangents{\pgf at nfold@cur at last}{\pgf at x#1\pgf at y#2}{\pgf at x#3\pgf at y#4}{\pgf at x#5\pgf at y#6}%
+ \let\pgf at nfold@next at type=c%
+ \let\pgf at nfold@next at visible=1%
+ \let\pgf at nfold@next at tang@i=\pgf at tmp@tang at i
+ \let\pgf at nfold@next at tang@ii=\pgf at tmp@tang at ii
+ \let\pgf at nfold@next at angle@i\pgf at tmp@angle at i
+ \let\pgf at nfold@next at angle@ii\pgf at tmp@angle at ii
+ \let\pgf at nfold@next at first\pgf at nfold@cur at last
+ \def\pgf at nfold@next at supporta{\pgf at x#1\pgf at y#2}
+ \def\pgf at nfold@next at supportb{\pgf at x#3\pgf at y#4}
+ \def\pgf at nfold@next at last{\pgf at x#5\pgf at y#6}
+ \pgf at nfold@process at segment%
+}%
+
+\def\pgf at nfold@processclosepath#1#2{%
+ \pgf at process{\pgfpointdiff{\pgf at nfold@next at last}{\pgf at x#1\pgf at y#2}}%
+ \pgfpointtaxicabnorm\pgf at xa%
+ \ifdim\pgf at xa<0.1pt\relax%
+ \pgf at nfold@process at closepath@zerolength{#1}{#2}%
+ \else%
+ \pgf at nfold@process at line@common{#1}{#2}{o}%
+ \fi%
+}%
+
+\def\pgf at nfold@process at closepath@zerolength#1#2{%
+ \pgf at nfold@process at moveup%
+ \let\pgf at nfold@next at type=z%
+ \let\pgf at nfold@next at visible=1%
+ \let\pgf at nfold@next at tang@i\pgf at nfold@connsubpath at tang@i
+ \let\pgf at nfold@next at tang@ii\pgf at nfold@connsubpath at tang@i
+ \let\pgf at nfold@next at angle@i\pgf at nfold@connsubpath at angle@i
+ \let\pgf at nfold@next at angle@ii\pgf at nfold@connsubpath at angle@i
+ \let\pgf at nfold@next at first\pgf at nfold@cur at last
+ \def\pgf at nfold@next at last{\pgf at x#1\pgf at y#2}%
+ \pgf at nfold@process at segment%
+}
+
+\def\pgf at nfold@processinvisibleline#1#2{%
+ \pgf at process{\pgfpointdiff{\pgf at nfold@next at last}{\pgf at x#1\pgf at y#2}}%
+ \pgfpointtaxicabnorm\pgf at xa%
+ \ifdim\pgf at xa>.1pt\relax%
+ \pgf at nfold@process at line@common{#1}{#2}{i}%
+ \else%
+ \begingroup%
+ \let\pgf at nfold@process at segment\relax%
+ \pgf at nfold@sectolast at segment%
+ \global\let\pgf at nfold@tmp\pgf at nfold@next at tang@ii%
+ \endgroup%
+ \pgfextract at process\pgf at nfold@next at first{\pgfpointdiff{\pgf at nfold@tmp}{\pgfqpoint{#1}{#2}}}%
+ \pgf at nfold@tmp%
+ \pgf at nfold@process at line@common{#1}{#2}{i}%
+ \fi%
+}%
+
+\def\pgf at nfold@processlast{%
+ \pgf at nfold@process at moveup%
+ \let\pgf at nfold@next at type=t%
+ \let\pgf at nfold@next at visible=0%
+ \pgf at nfold@process at segment%
+}
+
+\def\pgf at nfold@addmacro#1{%
+ \expandafter\expandafter\expandafter\gdef%
+ \expandafter\expandafter\expandafter#1%
+ \expandafter\expandafter\expandafter{%
+ \expandafter#1\pgf at nfold@macrotoadd}%
+}
+
+
+
+\def\pgf at nfold@token at lineto#1#2#3{%
+ \pgfoffsetline@{#1}{#2}{\pgf at nfold@shiftamount}{#3}%
+}
+
+\def\pgf at nfold@token at lineto@continue#1#2#3{%
+ \pgfoffsetlinenomove@{#1}{#2}{\pgf at nfold@shiftamount}{#3}%
+}
+
+\def\pgf at nfold@token at invisibleline#1#2#3{%
+ \pgfqpointscale{\pgf at nfold@shiftamount}{#3}%
+ \pgf at xc=-\pgf at y%
+ \pgf at y=\pgf at x%
+ \pgf at x=\pgf at xc%
+ \pgfpathmoveto{\pgfpointadd{}{#2}}%
+}
+
+\def\pgf at nfold@token at curveto#1#2#3#4#5#6{%
+ \def\pgf at tmp@tang at i{#5}%
+ \def\pgf at tmp@tang at ii{#6}%
+ \pgf at offset@bezier at segment@{#1}{#2}{#3}{#4}{\pgf at nfold@shiftamount}%
+ \pgfpathmoveto{\pgf at bezier@offset at i}%
+ \pgfpathcurveto{\pgf at bezier@offset at ii}{\pgf at bezier@offset at iii}{\pgf at bezier@offset at iv}%
+}
+
+\def\pgf at nfold@token at curveto@continue#1#2#3#4#5#6{%
+ \def\pgf at tmp@tang at i{#5}%
+ \def\pgf at tmp@tang at ii{#6}%
+ \pgf at offset@bezier at segment@{#1}{#2}{#3}{#4}{\pgf at nfold@shiftamount}%
+ \pgfpathcurveto{\pgf at bezier@offset at ii}{\pgf at bezier@offset at iii}{\pgf at bezier@offset at iv}%
+}
+
+\def\pgf at nfold@token at closepath{%
+ \pgfpathclose%
+}
+
+\def\pgf at nfold@token at edgecase@movetostart#1#2{%
+ \pgfpathmoveto{\pgfpointadd%
+ {#1}{\pgfpointpolar{#2+90}{\pgf at nfold@shiftamount}}}%
+}
+
+
+\def\pgf at nfold@parser at setupfirst{%
+ \let\pgf at nfold@next at type=f%
+ \let\pgf at nfold@next at visible=0%
+ \edef\pgf at nfold@next at last{\pgf at x\the\pgf at path@lastx\pgf at y\the\pgf at path@lasty}%
+}
+
+\def\pgf at nfold@clampangle{
+ \ifdim\pgfmathresult pt<-180pt\relax
+ \pgfutil at tempdima=\pgfmathresult pt
+ \advance\pgfutil at tempdima by 360pt
+ \edef\pgfmathresult{\pgf at sys@tonumber\pgfutil at tempdima}
+ \else\ifdim\pgfmathresult pt>180pt\relax
+ \pgfutil at tempdima=\pgfmathresult pt
+ \advance\pgfutil at tempdima by -360pt
+ \edef\pgfmathresult{\pgf at sys@tonumber\pgfutil at tempdima}
+ \fi\fi
+}
+
+
+\def\pgf at nfold@process at moveup{%
+ \let\pgf at nfold@prev at type\pgf at nfold@cur at type%
+ \let\pgf at nfold@prev at visible\pgf at nfold@cur at visible%
+ \let\pgf at nfold@prev at tang@i\pgf at nfold@cur at tang@i%
+ \let\pgf at nfold@prev at tang@ii\pgf at nfold@cur at tang@ii%
+ \let\pgf at nfold@prev at angle@i\pgf at nfold@cur at angle@i%
+ \let\pgf at nfold@prev at angle@ii\pgf at nfold@cur at angle@ii%
+ \let\pgf at nfold@prev at first\pgf at nfold@cur at first%
+ \let\pgf at nfold@prev at supporta\pgf at nfold@cur at supporta%
+ \let\pgf at nfold@prev at supportb\pgf at nfold@cur at supportb%
+ \let\pgf at nfold@prev at last\pgf at nfold@cur at last%
+ \let\pgf at nfold@cur at type\pgf at nfold@next at type%
+ \let\pgf at nfold@cur at visible\pgf at nfold@next at visible%
+ \let\pgf at nfold@cur at tang@i\pgf at nfold@next at tang@i%
+ \let\pgf at nfold@cur at tang@ii\pgf at nfold@next at tang@ii%
+ \let\pgf at nfold@cur at angle@i\pgf at nfold@next at angle@i%
+ \let\pgf at nfold@cur at angle@ii\pgf at nfold@next at angle@ii
+ \let\pgf at nfold@cur at first\pgf at nfold@next at first%
+ \let\pgf at nfold@cur at supporta\pgf at nfold@next at supporta%
+ \let\pgf at nfold@cur at supportb\pgf at nfold@next at supportb%
+ \let\pgf at nfold@cur at last\pgf at nfold@next at last%
+}
+
+
+\def\pgfoffsetpath#1#2{%
+ \begingroup
+ \pgfmathsetlengthmacro\pgf at nfold@parsed at hwidth{#2}
+ \pgf at x=\pgf at nfold@parsed at hwidth\relax
+ \ifdim\pgf at x<0pt\relax
+ \pgf at x=-\pgf at x
+ \def\pgf at nfold@shift at fraction{-1}
+ \else
+ \def\pgf at nfold@shift at fraction{1}
+ \fi
+ \edef\pgf at nfold@parsed at hwidth{\the\pgf at x}
+ \pgfoffsetpathqfraction{#1}{\pgf at nfold@parsed at hwidth}{\pgf at nfold@shift at fraction}
+ \endgroup
+}
+
+\def\pgfoffsetpathfraction#1#2#3{%
+ \begingroup
+ \pgfmathsetlengthmacro\pgf at nfold@parsed at hwidth{#2}
+ \pgfmathsetmacro\pgf at nfold@shift at fraction{#3}
+ \pgfoffsetpathqfraction{#1}{\pgf at nfold@parsed at hwidth}{\pgf at nfold@shift at fraction}
+ \endgroup
+}
+
+\def\pgfoffsetpathindex#1#2#3#4{%
+ \begingroup
+ \pgfmathsetmacro\pgf at nfold@shift at fraction{-1+2*(#3-1)/(#4-1)}
+ \pgfoffsetpathqfraction{#1}{#2}{\pgf at nfold@shift at fraction}
+ \endgroup
+}
+
+\def\pgfoffsetpathqfraction#1#2#3{%
+ \begingroup
+ \pgf at x=#2\relax
+ \edef\pgf at nfold@hwidth{\the\pgf at x}
+ \edef\pgf at nfold@shift at fraction{#3}
+ \pgf at x=\pgf at nfold@shift at fraction\pgf at x\relax
+ \edef\pgf at nfold@shiftamount{\pgf at sys@tonumber\pgf at x}
+ \pgfprocessround{#1}{\pgf at nfold@cachedpath}%
+ \pgf at nfold@parsesoftpath{\pgf at nfold@cachedpath}{\parsedpath}%
+ \pgftransformreset%
+ \parsedpath%
+ \endgroup
+}
+
+\endinput
Property changes on: trunk/Master/texmf-dist/tex/latex/tikz-nfold/pgflibraryoffsetpath.code.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Master/texmf-dist/tex/latex/tikz-nfold/tikzlibrarynfold.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/tikz-nfold/tikzlibrarynfold.code.tex 2023-07-22 23:49:15 UTC (rev 67710)
+++ trunk/Master/texmf-dist/tex/latex/tikz-nfold/tikzlibrarynfold.code.tex 2023-07-23 20:45:55 UTC (rev 67711)
@@ -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,1300 +13,20 @@
%
% 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}
-
-
+% 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.
%
-% 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.
+% A commented version of this file can be found on https://github.com/jonschz/tikz-nfold .
%
+\usepgflibrary{nfold}
+\usetikzlibrary{arrows.meta}
-%
-% 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 at nfold@cached at miterlimit{10}
-\let\pgf at nfold@old at miterlimit\pgfsetmiterlimit
-\def\pgfsetmiterlimit#1{%
- \pgf at nfold@old at miterlimit{#1}%
- \edef\pgf at nfold@cached at miterlimit{#1}%
-}
-
-% default line join is "miter"
-\global\let\pgf at cached@linejoin=m% % b = bevel, m=miter, r=round
-\let\pgf at nfold@old at setbeveljoin\pgfsetbeveljoin
-\let\pgf at nfold@old at setmiterjoin\pgfsetmiterjoin
-\let\pgf at nfold@old at setroundjoin\pgfsetroundjoin
-\def\pgfsetbeveljoin{%
- \pgf at nfold@old at setbeveljoin%
- % do NOT change this globally! Needs to be changed back at the end of groups for scoping reasons
- \let\pgf at cached@linejoin=b%
-}
-\def\pgfsetmiterjoin{%
- \pgf at nfold@old at setmiterjoin%
- \let\pgf at cached@linejoin=m%
-}
-\def\pgfsetroundjoin{%
- \pgf at nfold@old at setroundjoin%
- \let\pgf at 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 at 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 at nfold@join at centre}{%
- \pgfpointpolar{\pgf at nfold@firstang+.5*\pgf at nfold@deltaphi+90}% do not change
- {\pgf at nfold@shiftamount/cos(.5*\pgf at nfold@deltaphi)}%
- }%
- }%
-}
-
-\def\pgf at 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 at nfold@shortenstartjoin pt - .5*\pgflinewidth*abs(tan(.25*\pgf at 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 at nfold@deltaphi))}
- % This threshold decides if the inside line has a bevel or a miter join
- \pgfmathparse{\bevelshorten < abs(sin(.5*\pgf at nfold@deltaphi))}
- \ifnum\pgfmathresult=1\relax
- \pgfmathsetlengthmacro{\bevelextension}{\bevelouterprotrusion-\bevelshorten*\pgf at nfold@hwidth}
- \pgfpointadd{\pgf at nfold@join at start}{\pgfpointpolar{\pgf at nfold@firstang}{\bevelextension}}
- \pgfpathlineto{}
- \pgfpointadd{\pgf at nfold@join at end}{\pgfpointpolar{\pgf at nfold@secondang}{-\bevelextension}}
- \pgfpathlineto{}
- \else
- \pgf at nfold@miterjoin
- \fi
-}
-
-\def\pgf at nfold@roundjoin{
- % The outer half of the lines get arcs, the others get miters
- \ifdim\insidepercentage pt<.5pt\relax
- \pgfpointadd{\pgf at nfold@join at start}{\pgfpointpolar{\pgf at nfold@firstang}{\pgf at nfold@shortenstartjoin}}
- \pgfpathlineto{}
- % TODO needs unit tests for all cases left, right, across the 360 gap etc.
- \pgfmathsetmacro\pgf at tmp@firstang{\pgf at nfold@firstang+90*\turnindicator}
- \pgfpatharc%
- {\pgf at tmp@firstang}%
- {\pgf at tmp@firstang+\pgf at nfold@deltaphi}%
- {abs(\pgf at nfold@shift at fraction)*\pgf at nfold@hwidth}%
- \else
- \pgf at 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 at nfold@token at join#1#2#3#4#5#6#7#8{%
- \def\pgf at nfold@join at centre{#1}%
- \def\pgf at nfold@join at prevend{#2}%
- \def\pgf at nfold@join at nextstart{#3}%
- \def\pgf at nfold@firstang{#4}%
- \def\pgf at nfold@secondang{#5}%
- % Offset the start and end of this join
- \pgfextract at process\pgf at nfold@join at start{%
- \pgfpointadd{#2}{\pgfpointpolar{\pgf at nfold@firstang+90}{\pgf at nfold@shiftamount}}}%
- \pgfextract at process\pgf at nfold@join at end{%
- \pgfpointadd{#3}{\pgfpointpolar{\pgf at nfold@secondang+90}{\pgf at nfold@shiftamount}}}%
- \pgf at process{\pgfpointdiff{\pgf at nfold@join at start}{\pgf at nfold@join at 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 at tempdima
- \ifdim\pgfutil at tempdima>0.1pt\relax
- \def\pgf at nfold@deltaphi{#6}%
- \def\pgf at nfold@shortenstartjoin{#7}%
- % First step: Check if left or right turn (-1=left, 1=right)
- \ifdim\pgf at 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 at tempdima=\pgf at nfold@shift at fraction pt\relax
- \pgfutil at tempdima=\turnindicator\pgfutil at tempdima
- \advance\pgfutil at tempdima by-1pt\relax
- \pgfutil at tempdima=-.5\pgfutil at tempdima
- % \insidepercentage = .5 * (1 - \turnindicator*\pgf at nfold@shift at fraction)
- \edef\insidepercentage{\pgf at sys@tonumber\pgfutil at tempdima}%
- #8%
- \fi
-}
-
-
-%
-% Parser: Join handler
-%
-\def\pgf at nfold@parser at handlejoin{%
- % \pgf at xa := abs(deltaphi at start)
- \pgf at xa=\pgf at nfold@deltaphi at start pt\relax
- \ifdim\pgf at xa<0pt\relax
- \pgf at xa=-\pgf at xa
- \fi
- % Skip the entire join if abs(deltaphi) is too small
- \ifdim\pgf at xa>1pt\relax
- \edef\pgf at nfold@jointype{\pgf at cached@linejoin}
- \if\pgf at 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 at xa=.5\pgf at xa
- \pgfmathcos@{\pgf at sys@tonumber\pgf at xa}
- \pgf at xa=\pgfmathresult pt\relax
- \pgf at xa=\pgf at nfold@cached at miterlimit\pgf at xa
- % Switch to bevel if miterlimit*cos(.5*abs(deltaphi)) <= 1
- \ifdim\pgf at xa>1pt\relax
- \def\pgf at nfold@tmp at joinmacro{\pgf at nfold@miterjoin}
- \else
- \def\pgf at nfold@tmp at joinmacro{\pgf at nfold@beveljoin}
- \fi
- \else
- \if b\pgf at cached@linejoin\relax
- \def\pgf at nfold@tmp at joinmacro{\pgf at nfold@beveljoin}
- \else
- \def\pgf at nfold@tmp at joinmacro{\pgf at 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 at normal or finish at edgecase.
- \edef\pgf at nfold@macrotoadd{%
- \noexpand\pgf at nfold@token at join{\pgf at nfold@cur at first}{\pgf at nfold@prev at segment@end}
- {\pgf at nfold@cur at movedfirst}{\pgf at nfold@prev at angle@ii}{\pgf at nfold@cur at angle@i}%
- {\pgf at nfold@deltaphi at start}{\pgf at nfold@shortenstartjoin}{%
- \expandafter\noexpand\pgf at nfold@tmp at joinmacro%
- \expandafter\noexpand\ifpgf at nfold@closejoinsedgecase%
- \pgf at nfold@token at finish@edgecase{\pgf at nfold@cur at movedlast}%
- \else%
- \pgf at nfold@token at finish@normal%
- \fi%
- }%
- }%
- \pgf at nfold@addmacro\pgf at parsed@cur at 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 at nfold@cur at movedlast
-% and \pgf at nfold@cur at 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 at nfold@cur at movedfirst, because that would overshoot the second join. Instead we connect to
-% \pgf at nfold@cur at movedlast (which is *closer* to the first join than \pgf at nfold@cur at movedfirst in this edge case).
-% To accomodate for the vertical offset we connect to \pgf at nfold@join at end which is the vertical
-% offset of \pgf at nfold@cur at movedlast by definition.
-\def\pgf at nfold@token at finish@normal{%
- \pgfpathlineto{\pgf at nfold@join at end}%
-}
-
-% parameter #1: @movedlast of the next segment
-\def\pgf at nfold@token at finish@edgecase#1{%
- \pgf at nfold@join at end%
- \ifdim\insidepercentage pt<.5pt\relax%
- \pgf at process{\pgfpointadd{#1}{\pgfpointpolar{\pgf at nfold@secondang+90}{\pgf at nfold@shiftamount}}}
- \fi%
- \pgfpathlineto{}%
-}
-
-
-%
-% Main rendering pipeline
-% -----------------------
-%
-
-% This stores whether the current segment should begin with a moveto to its offset
-\newif\ifpgf at nfold@continuesegment
-% This stores whether we are in some edge case of very close joins, see below for details
-\newif\ifpgf at nfold@closejoinsedgecase
-% This stores whether we are in an error case where we need to avoid dividing by zero
-\newif\ifpgf at nfold@angletoosharp
-% This stores whether we need the intersections library for an arrow tip but it is not loaded
-\newif\ifpgf at nfold@intersectionsnotloaded
-% This stores whether the currently processed connected sub-path is the final one on this path
-\newif\ifpgf at nfold@lastconnsubpath
-
-
-\def\pgf at nfold@parser at handlesegment{%
- \if\pgf at nfold@cur at visible0
- % first, last and moveto are invisible
- \if\pgf at nfold@cur at 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 at nfold@start at arrowcode1
- \ifpgf at nfold@lastconnsubpath
- \if\pgf at nfold@prev at type f
- \if\pgf at nfold@next at visible1
- \edef\pgf at nfold@macrotoadd{%
- \noexpand\pgf at nfold@extendtotip{s}{\pgf at nfold@cur at last}{\pgf at nfold@next at angle@i}
- }%
- \pgf at nfold@addmacro\pgf at parsed@cur at conn@seg%
- % hack: We make the next segment believe that this segment was a lineto
- % so the path does not get interrupted
- \let\pgf at nfold@cur at type l
- \let\pgf at nfold@cur at visible1
- \let\pgf at nfold@cur at angle@ii\pgf at nfold@next at angle@i
- \let\pgf at nfold@cur at tang@ii\pgf at nfold@next at tang@i
- \def\pgf at nfold@deltaphi at end{0}
- \pgf at nfold@angletoosharpfalse
- \fi
- \fi%
- \fi
- \fi
- \fi%
- \else%
- \let\pgf at nfold@cur at movedfirst\pgf at nfold@cur at first
- \let\pgf at nfold@cur at movedlast\pgf at nfold@cur at 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 at nfold@shortenstartjoin{0}
- \def\pgf at nfold@shortenendjoin{0}
- \pgf at nfold@closejoinsedgecasefalse
- % Step 1.1: Make room for the join at the start if needed
- \if\pgf at nfold@prev at visible0
- \pgf at nfold@continuesegmentfalse
- \else
- \pgf at nfold@continuesegmenttrue
- % deltaphi at start can be recycled from deltaphi at end;
- % \ifpgf at nfold@angletoosharp is also still set
- \let\pgf at nfold@deltaphi at start\pgf at nfold@deltaphi at end
- % set \pgf at xb := abs(deltaphi at start)
- \pgf at xb=\pgf at nfold@deltaphi at start pt\relax
- \ifdim\pgf at xb<0pt\relax
- \pgf at xb=-\pgf at xb
- \fi
- \ifpgf at nfold@angletoosharp\else
- \ifdim\pgf at xb>0.5pt\relax
- % make room for the start join if the angle is nonzero;
- % shortenstartjoin := hwidth*tan(.5*abs(deltaphi at start))
- \pgf at yb=.5\pgf at xb
- \pgfmathtan@{\pgf at sys@tonumber\pgf at yb}
- \pgf at yb=\pgf at nfold@hwidth\relax
- \pgf at yb=\pgfmathresult\pgf at yb
- \edef\pgf at nfold@shortenstartjoin{\pgf at sys@tonumber\pgf at yb}
- \pgfextract at process\pgf at nfold@cur at movedfirst{%
- \pgfpointadd{\pgf at nfold@cur at first}%
- {\pgfqpointscale{\pgf at nfold@shortenstartjoin}{\pgf at nfold@cur at 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 at nfold@cur at type c
- \pgf at process{\pgfpointdiff{\pgf at nfold@cur at first}{\pgf at nfold@cur at supporta}}
- \pgfmathveclen@{\pgf at sys@tonumber\pgf at x}{\pgf at sys@tonumber\pgf at 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 at sys@tonumber\pgf at yb}
- \pgfextract at process\pgf at nfold@cur at supporta{\pgfpointadd%
- {\pgf at nfold@cur at first}%
- {\pgfqpointscale{\pgfmathresult}{\pgf at nfold@cur at 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 at nfold@cur at supporta\pgf at nfold@cur at movedfirst
- \fi
- \fi
- \fi
- \fi
- \fi
- % Step 1.2: Make room for the join at the end if needed
- \if\pgf at nfold@next at 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 at nfold@next at angle@i}{\pgf at nfold@cur at angle@ii}
- \pgf at 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 at nfold@deltaphi at end{\pgfmathresult}
- \pgf at xb=\pgf at nfold@deltaphi at end pt\relax
- \ifdim\pgf at xb<0pt\relax
- \pgf at xb=-\pgf at xb
- \fi
- \ifdim\pgf at xb>178pt\relax
- \pgfutil at packagewarning{tikz-nfold}{Angle too sharp, expect visual errors}
- \pgf at nfold@angletoosharptrue
- \else
- \pgf at nfold@angletoosharpfalse
- \ifdim\pgf at xb>0.5pt\relax
- % make room for the start join if the angle is nonzero
- % shortenendjoin := hwidth*tan(.5*abs(deltaphi at end))
- \pgf at yb=.5\pgf at xb
- \pgfmathtan@{\pgf at sys@tonumber\pgf at yb}
- \pgf at yb=\pgf at nfold@hwidth\relax
- \pgf at yb=\pgfmathresult\pgf at yb
- \edef\pgf at nfold@shortenendjoin{\pgf at sys@tonumber\pgf at yb}
- \pgf at yb=-\pgf at yb
- \pgfextract at process\pgf at nfold@cur at movedlast{%
- % the use of the minus sign is fine here because \pgf at nfold@shortenendjoin >= 0.0
- \pgfpointadd{\pgf at nfold@cur at last}%
- {\pgfqpointscale{-\pgf at nfold@shortenendjoin}{\pgf at nfold@cur at tang@ii}}}%
- \pgfextract at process\pgf at nfold@cur at movedlast{%
- \pgfpointadd{\pgf at nfold@cur at last}%
- {\pgfqpointpolar{\pgf at nfold@cur at angle@ii}{\pgf at yb}}}%
- \if\pgf at nfold@cur at type c
- % Same procedure as above: relocate supportb if we have a curve
- \pgf at process{\pgfpointdiff{\pgf at nfold@cur at supportb}{\pgf at nfold@cur at last}}
- \pgfmathveclen@{\pgf at sys@tonumber\pgf at x}{\pgf at sys@tonumber\pgf at y}
- \ifdim\pgfmathresult pt>0.1pt\relax
- \pgfmathveclen@{\pgfmathresult}{\pgf at sys@tonumber\pgf at yb}
- \pgfextract at process\pgf at nfold@cur at supportb{\pgfpointadd%
- {\pgf at nfold@cur at last}%
- % can use qpointscale and a minus because \pgfmathresult is guaranteed to be positive
- {\pgfqpointscale{-\pgfmathresult}{\pgf at nfold@cur at tang@ii}}}%
- \else
- \let\pgf at nfold@cur at supportb\pgf at nfold@cur at 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 at nfold@cur at type l
- % No need to check for \pgf at 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 at process{\pgfpointdiff{\pgf at nfold@cur at first}{\pgf at nfold@cur at last}}
- \pgfmathveclen@{\pgf at sys@tonumber\pgf at x}{\pgf at sys@tonumber\pgf at y}
- \pgf at xa=\pgf at nfold@shortenstartjoin pt\relax
- \advance\pgf at xa by\pgf at nfold@shortenendjoin pt\relax
- \ifdim\pgf at xa>\pgfmathresult pt\relax
- \pgf at nfold@closejoinsedgecasetrue
- \fi
- \fi
- \fi% end if next segment visible
- %
- % Step 2.1: Draw the join at the start if applicable
- %
- \if\pgf at nfold@prev at visible0%
- \ifpgf at 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 at nfold@cur at movedFIRST since the start and end
- % are reversed in the edge case.
- \edef\pgf at nfold@macrotoadd{%
- \noexpand\pgf at nfold@token at edgecase@movetostart{\pgf at nfold@cur at movedfirst}{\pgf at nfold@cur at angle@i}%
- }%
- \pgf at nfold@addmacro\pgf at parsed@cur at 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 at nfold@angletoosharp\else
- \if\pgf at nfold@cur at type z\else
- \pgf at nfold@parser at 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 at nfold@prev at segment@end\pgf at nfold@cur at 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 at nfold@cur at type i
- \let\pgf at nfold@connsubpath at tang@i\pgf at nfold@next at tang@i%
- \let\pgf at nfold@connsubpath at angle@i\pgf at nfold@next at angle@i%
- \fi
- %
- % Step 3: Draw the new segment.
- %
- % The value of \ifpgf at nfold@continuesegment decides whether we start with a moveto.
- \if\pgf at nfold@cur at 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 at nfold@closejoinsedgecase\else
- \edef\pgf at nfold@macrotoadd{%
- \expandafter\noexpand\ifpgf at nfold@continuesegment%
- \pgf at nfold@token at lineto@continue%
- \else%
- \pgf at nfold@token at lineto%
- \fi{\pgf at nfold@cur at movedfirst}{\pgf at nfold@cur at movedlast}{\pgf at nfold@cur at tang@i}%
- }%
- \pgf at nfold@addmacro\pgf at parsed@cur at conn@seg%
- \fi
- \fi
- \if\pgf at nfold@cur at type o
- \def\pgf at nfold@macrotoadd{\pgf at nfold@token at closepath}%
- \pgf at nfold@addmacro\pgf at parsed@cur at conn@seg%
- \fi
- \if\pgf at nfold@cur at type z
- % zero and non-zero closepath's differ in the join handling, but are identical in rendering
- \def\pgf at nfold@macrotoadd{\pgf at nfold@token at closepath}%
- \pgf at nfold@addmacro\pgf at parsed@cur at conn@seg%
- \fi
- \if\pgf at nfold@cur at type c
- \ifpgf at nfold@continuesegment
- \pgf at subdividecurve{\pgf at nfold@cur at movedfirst}{\pgf at nfold@cur at supporta}{\pgf at nfold@cur at supportb}{\pgf at nfold@cur at movedlast}{\pgf at offset@max at recursion}{0}{\pgf at nfold@addcurvesegment at callback@continue}
- \else
- \pgf at subdividecurve{\pgf at nfold@cur at movedfirst}{\pgf at nfold@cur at supporta}{\pgf at nfold@cur at supportb}{\pgf at nfold@cur at movedlast}{\pgf at offset@max at recursion}{0}{\pgf at nfold@addcurvesegment at callback}%
- \fi
- \fi
- \if\pgf at nfold@cur at type i
- \edef\pgf at nfold@macrotoadd{%
- \noexpand\pgf at nfold@token at invisibleline{\pgf at nfold@cur at movedfirst}{\pgf at nfold@cur at movedlast}{\pgf at nfold@cur at tang@i}%
- }%
- \pgf at nfold@addmacro\pgf at parsed@cur at conn@seg%
- \fi
- % Step 4: Extend into the arrow tip at the end (if present)
- \if\pgf at nfold@next at type t%
- \ifnum\pgf at nfold@end at arrowcode=1
- \edef\pgf at nfold@macrotoadd{%
- \noexpand\pgf at nfold@extendtotip{e}{\pgf at nfold@cur at last}{\pgf at nfold@cur at angle@ii}}%
- \pgf at nfold@addmacro\pgf at parsed@cur at conn@seg%
- \fi%
- \fi%
- \fi% end if current visible
-}
-
-
-\def\pgf at nfold@addcurvesegment at callback#1#2#3#4#5{%
- \if#50%
- \edef\pgf at nfold@macrotoadd{%
- % The subdivision algorithm has already computed the tangents
- \noexpand\pgf at nfold@token at curveto{#1}{#2}{#3}{#4}{\pgf at tmp@tang at i}{\pgf at tmp@tang at ii}%
- }%
- \pgf at nfold@addmacro\pgf at parsed@cur at conn@seg%
- \else%
- \pgf at nfold@addcurvesegment at callback@continue{#1}{#2}{#3}{#4}{#5}%
- \fi%
-}
-
-\def\pgf at nfold@addcurvesegment at callback@continue#1#2#3#4#5{%
- % The subdivision algorithm has already computed the tangents
- \edef\pgf at nfold@macrotoadd{%
- \noexpand\pgf at nfold@token at curveto@continue{#1}{#2}{#3}{#4}{\pgf at tmp@tang at i}{\pgf at tmp@tang at ii}%
- }%
- \pgf at nfold@addmacro\pgf at parsed@cur at 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 at nfold@intersec at cache@2 at 3\endcsname{\pgfqpoint{2pt}{0pt}}
-\expandafter\def\csname pgf at nfold@intersec at cache@2 at 4\endcsname{\pgfqpoint{0.94063pt}{-0.33333pt}}
-\expandafter\def\csname pgf at nfold@intersec at cache@3 at 4\endcsname{\pgfqpoint{0.94063pt}{0.33333pt}}
-\expandafter\def\csname pgf at nfold@intersec at cache@2 at 5\endcsname{\pgfqpoint{0.64167pt}{-0.5pt}}
-\expandafter\def\csname pgf at nfold@intersec at cache@3 at 5\endcsname{\pgfqpoint{2pt}{0pt}}
-\expandafter\def\csname pgf at nfold@intersec at cache@4 at 5\endcsname{\pgfqpoint{0.64167pt}{0.5pt}}
-% intersections are precomputed up to this order
-\def\pgf at nfold@intersec at 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 at nfold@ontheedge
-\def\pgf at nfold@extendtotip#1#2#3{
- \ifpgf at nfold@intersectionsnotloaded
- \pgfutil at packageerror{tikz-nfold}{%
- If `nfold' is larger than \pgf at nfold@intersec at numcached\space and you use
- an `Implies' arrow tip you need to say \string\usetikzlibrary{intersections}}{}
- \else
- \pgf at nfold@ontheedgetrue
- % Do not extend the arrow for index=1 and index=order, it already ends in the right place
- \ifnum\pgf at nfold@index>1\relax\ifnum\pgf at nfold@index<\pgf at nfold@order\relax%
- \pgf at nfold@ontheedgefalse
- \fi\fi
- \ifpgf at nfold@ontheedge%
- % the extension at the start needs a moveto to the correct starting point
- \if#1s
- \pgfpathmoveto{\pgfpointadd{#2}{\pgfpointpolar{#3+90}{\pgf at nfold@shiftamount}}}%
- \fi
- \else
- % Step 1: Find the intersection of the arrow's path with the head
- \ifcsname pgf at nfold@intersec at cache@\the\pgf at nfold@index @\the\pgf at nfold@order\endcsname
- \pgfextract at process\pgf at nfold@arrowintersect
- {\csname pgf at nfold@intersec at cache@\the\pgf at nfold@index @\the\pgf at 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 at nfold@shift at fraction pt}}
- \pgfpathlineto{\pgfqpoint{3pt}{\pgf at nfold@shift at fraction pt}}
- }
- \ifnum\pgfintersectionsolutions>0
- \pgfextract at process\pgf at nfold@arrowintersect{\pgfpointintersectionsolution{1}}%
- \immediate\write17{tikz-nfold: computed intersection cache@\the\pgf at nfold@index @\the\pgf at nfold@order: \string\pgfqpoint{\the\pgf at x}{\the\pgf at y}^^J}
- % add the new intersection to the cache
- \expandafter\xdef\csname pgf at nfold@intersec at cache@\the\pgf at nfold@index @\the\pgf at nfold@order\endcsname{\noexpand\pgfqpoint{\the\pgf at x}{\the\pgf at y}}
- \else
- % this is a failsafe and should never be reached
- \pgfutil at packagewarning{tikz-nfold}{did not find intersection}
- \pgfextract at process\pgf at nfold@arrowintersect{\pgfqpoint{0pt}{\pgf at nfold@shift at 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 at tempdima=\pgf at nfold@hwidth
- \pgfutil at tempdima=\pgf at nfold@shift at fraction\pgfutil at tempdima
- \pgfextract at process\pgf at nfold@startofextension
- {\pgfpointtransformed{\pgfqpoint{0pt}{\pgfutil at tempdima}}}
- % 0.5 - 0.06 = 0.42
- \pgftransformshift{\pgfqpoint{.42\pgflinewidth}{0pt}}
- \pgftransformscale{\pgf at nfold@hwidth}
- \pgfextract at process\pgf at nfold@arrowintersect{\pgfpointtransformed{\pgf at nfold@arrowintersect}}
- \global\let\pgf at nfold@startofextension\pgf at nfold@startofextension
- \global\let\pgf at nfold@arrowintersect\pgf at nfold@arrowintersect
- \endgroup
- \if#1s
- \pgfpathmoveto{\pgf at nfold@arrowintersect}
- % This is precisely the start of the body, shifted vertically
- \pgfpathlineto{\pgf at nfold@startofextension}
- \else\if#1e
- \pgfpathlineto{\pgf at nfold@arrowintersect}
- \else
- \pgfutil at packageerror{tikz-nfold}{Invalid argument to \string\pgf at 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 at start@tip at sequence. If the user specifies Implies[] manually,
-% we find that
-% pgf at start@tip at sequence=\pgf at arrow@handle{Implies}{...}
-% However, in other cases (like tikz-cd) we may find
-% \pgf at arrow@handle at shorthand@empty {\csname pgf at ar@means at tikzcd implies cap\endcsname }
-% In such cases we must expand the first parameter once and then match as above.
-
-% Set global defaults
-\def\pgf at nfold@start at arrowcode{0}
-\def\pgf at nfold@end at arrowcode{0}
-
-\def\pgf at nfold@parsearrows{
- \ifpgfutil at tempswa% this is set in \pgfusepath and stores whether we draw arrow tips at all
- \expandafter\pgf at nfold@parsearrowmacro\pgf at start@tip at sequence\relax
- \let\pgf at nfold@start at arrowcode\pgf at nfold@detectedarrow
- \expandafter\pgf at nfold@parsearrowmacro\pgf at end@tip at sequence\relax
- \let\pgf at nfold@end at arrowcode\pgf at nfold@detectedarrow
- \else
- \def\pgf at nfold@start at arrowcode{0}
- \def\pgf at nfold@end at arrowcode{0}
- \fi
-}
-
-\def\pgf at nfold@parsearrowmacro#1{%
- \def\pgf at nfold@detectedarrow{0}
- \ifx#1\relax
- \let\pgf at next\relax
- \else
- \ifx#1\pgf at arrow@handle
- % found \pgf at arrow@handle{...}, now parse the first parameter
- \let\pgf at next\pgf at nfold@parse at arrow@handle
- \else
- \ifx#1\pgf at arrow@handle at shorthand@empty
- \let\pgf at next\pgf at nfold@parse at shorthandempty
- \else
- % found nothing
- \let\pgf at next\pgfutil at gobble@until at relax
- \fi
- \fi
- \fi
- \pgf at next
-}
-
-\def\pgf at nfold@param at Implies{Implies}
-
-\def\pgf at nfold@parse at arrow@handle#1{%
- \def\pgf at tmp{#1}
- \ifx\pgf at tmp\pgf at nfold@param at Implies
- \def\pgf at nfold@detectedarrow{1}
- \fi
- \pgfutil at gobble@until at relax
-}
-
-\def\pgf at nfold@parse at shorthandempty#1{
- % Expand #1 once (\pgf at arrow@handle at shorthand@empty is just an identity operator)
- \expandafter\def\expandafter\pgf at tmp\expandafter{#1}
- \expandafter\pgf at nfold@parsearrowmacro\pgf at tmp\relax
- % still need to gobble the rest of the orginal arrow definition
- \pgfutil at gobble@until at 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 at stroke@inner at 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 at stroke@inner at line. The macro before \pgf at stroke@inner at line
-% is either \pgf at path@check at proper or \pgf at prepare@start at 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 at invokecurrentpath has no effect), then we
-% restore and offset the cached softpath in \pgf at stroke@inner at line.
-%
-% The macros \pgf at path@check at proper and \pgf at prepare@start at of@path are also used in \pgf at up@draw at 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 at add@arrow at at@start and
-% \pgf at add@arrow at at@end, which do not change their behaviour even if we modify the paths.
-%
-
-\newcount\pgf at nfold@order
-\pgf at nfold@order=1
-
-\def\pgf at nfold@preparenfoldpath{%
- \ifnum\pgf at nfold@order>1\relax
- \ifdim\pgfinnerlinewidth>0pt\relax
- % Hack the rendering pipeline: There is a \pgfsyssoftpath at 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 at stroke@inner at line
- \pgfsyssoftpath at getcurrentpath\pgf at nfold@cachedpath%
- \pgfsyssoftpath at setcurrentpath\pgfutil at empty%
- \else
- \pgfutil at packageerror{tikz-nfold}{Must set \string\pgfinnerlinewidth\space to use nfold, e.g. by setting /tikz/double distance}{}
- \fi
- \fi
-}
-
-\let\pgf at nfold@old at path@check at proper\pgf at path@check at proper
-\def\pgf at path@check at proper{%
- \pgf at nfold@old at path@check at proper%
- \ifpgfutil at tempswa\else%
- % if \pgfutil at tempswa is false, this is the last macro we can overwrite before the draw call.
- % Otherwise, we inject into \pgf at prepare@start at of@path%
- \pgf at nfold@preparenfoldpath%
- \fi%
-}
-
-\let\pgf at nfold@old at prepare@start at of@path\pgf at prepare@start at of@path
-\def\pgf at prepare@start at of@path{%
- \pgf at nfold@old at prepare@start at of@path%
- \pgf at nfold@preparenfoldpath%
-}
-
-\let\pgf at nfold@old at stroke@inner at line\pgf at stroke@inner at line
-\def\pgf at stroke@inner at line{%
- \ifnum\pgf at nfold@order>1\relax%
- \pgf at nfold@render at cached@softpath%
- \else%
- % Old behaviour
- \pgf at nfold@old at stroke@inner at 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.
-%
-%
-
-
-%
-% 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 at cur@conn at subpath. When reaching the end of the connected sub-path we call
-% the proper parser to turn \pgf at cur@conn at subpath into a parsed path. We do this for
-% all connected sub-paths and concatenate all the parsed paths.
-%
-
-
-\def\pgf at nfold@parsesoftpath#1#2{%
- \let\pgf at cur@conn at subpath\pgfutil at empty%
- \let\pgf at all@parsed at subpaths\pgfutil at empty%
- \edef\pgf at nfold@parser at last@moveto{{\the\pgf at path@lastx}{\the\pgf at path@lasty}}%
- \let\pgf at nfold@last at closepath@from\pgfutil at empty%
- \pgf at nfold@parse at setupfirst%
- \expandafter\pgf at nfold@@parsesoftpath#1\pgf at stop{}{}%
- \let#2\pgf at all@parsed at subpaths%
-}%
-
-\def\pgf at nfold@@parsesoftpath#1#2#3{%
- \let\pgf at next\pgf at nfold@@parsesoftpath%
- \ifx#1\pgf at stop%
- \def\pgf at nfold@macrotoadd{\pgf at nfold@parselast}%
- \pgf at nfold@addmacro\pgf at cur@conn at subpath%
- \pgf at nfold@lastconnsubpathtrue%
- \pgf at nfold@process at conn@subpath%
- \let\pgf at next\relax%
- \else%
- \ifx#1\pgfsyssoftpath at movetotoken%
- \ifx\pgf at cur@conn at subpath\pgfutil at 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 at nfold@parsemoveto will be called
- % in \pgf at nfold@process at conn@subpath.
- \def\pgf at nfold@parser at last@moveto{{#2}{#3}}%
- % Make sure \pgf at cur@conn at 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 at cur@conn at subpath{\relax}%
- \else%
- \def\pgf at nfold@macrotoadd{\pgf at nfold@parsemoveto{#2}{#3}}%
- \pgf at nfold@addmacro\pgf at cur@conn at subpath%
- \pgf at nfold@lastconnsubpathfalse%
- % A moveto marks the beginning/end of one connected sub-path
- \pgf at nfold@process at conn@subpath%
- \let\pgf at nfold@last at closepath@from\pgfutil at empty%
- \let\pgf at cur@conn at subpath\pgfutil at empty%
- % set up "first" again which may be needed for the arrow tip extension
- \pgf at nfold@parse at setupfirst%
- \def\pgf at nfold@parser at last@moveto{{#2}{#3}}%
- \fi
- \else%
- \ifx#1\pgfsyssoftpath at linetotoken%
- \def\pgf at nfold@macrotoadd{\pgf at nfold@parselineto{#2}{#3}}%
- \pgf at nfold@addmacro\pgf at cur@conn at subpath%
- \else%
- \ifx#1\pgfsyssoftpath at curvetosupportatoken%
- \def\pgf at nfold@parse at supporta{{#2}{#3}}%
- \else%
- \ifx#1\pgfsyssoftpath at curvetosupportbtoken%
- \def\pgf at nfold@parse at supportb{{#2}{#3}}%
- \else%
- \ifx#1\pgfsyssoftpath at curvetotoken%
- \edef\pgf at nfold@macrotoadd{\noexpand\pgf at nfold@parsecurveto\pgf at nfold@parse at supporta\pgf at nfold@parse at supportb{#2}{#3}}%
- \pgf at nfold@addmacro\pgf at cur@conn at subpath%
- \else%
- \ifx#1\pgfsyssoftpath at closepathtoken%
- \let\pgf at nfold@last at closepath@from\pgf at nfold@parser at previous@pt%
- \def\pgf at nfold@macrotoadd{\pgf at nfold@parseclosepath{#2}{#3}}%
- \pgf at nfold@addmacro\pgf at cur@conn at subpath%
- \else%
- \ifx#1\pgfsyssoftpath at rectcornertoken%
- \def\pgf at nfold@parse at rectcorner{{#2}{#3}}%
- \else%
- \ifx#1\pgfsyssoftpath at rectsizetoken%
- \edef\pgf at nfold@macrotoadd{\noexpand\pgf at nfold@parserect\pgf at nfold@parse at rectcorner{#2}{#3}}%
- \pgf at nfold@addmacro\pgf at cur@conn at subpath%
- \else%
- \pgfutil at packageerror{tikz-nfold}{Unrecognised soft path token `#1'}{}%
- \fi%
- \fi%
- \fi%
- \fi%
- \fi%
- \fi%
- \fi%
- \fi%
- \fi%
- \def\pgf at nfold@parser at previous@pt{{#2}{#3}}%
- % store the last two segments, as they might be needed for zero-length \pgfpathclose-segments
- \let\pgf at nfold@sectolast at segment\pgf at nfold@last at segment%
- \let\pgf at nfold@last at segment\pgf at nfold@macrotoadd%
- \pgf at next}%
-
-\def\pgf at nfold@process at conn@subpath{%
- \let\pgf at parsed@cur at conn@seg\pgfutil at empty%
- \ifx\pgf at nfold@last at closepath@from\pgfutil at empty%
- \expandafter\pgf at nfold@parsemoveto\pgf at nfold@parser at 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 at nfold@parsemoveto\pgf at nfold@last at closepath@from%
- \expandafter\pgf at nfold@parseinvisibleline\pgf at nfold@parser at last@moveto%
- \fi%
- \pgf at cur@conn at subpath%
- \let\pgf at nfold@macrotoadd\pgf at parsed@cur at conn@seg%
- \pgf at nfold@addmacro\pgf at all@parsed at subpaths%
-}
-
-%
-% Values for \pgf at nfold@next at type:
-% f=first, m=moveto, c=curveto, l=lineto, r=rect, o=closepath, z=zero length closepath, t=last, i=invisibleline
-%
-
-\def\pgf at nfold@parsemoveto#1#2{%
- \pgf at nfold@parser at moveup%
- \let\pgf at nfold@next at type=m%
- \let\pgf at nfold@next at visible=0%
- \edef\pgf at nfold@next at last{\pgf at x#1\pgf at y#2}%
- \pgf at nfold@parser at handlesegment%
-}%
-
-
-% Common code for parselineto and parseclosepath
-\def\pgf at nfold@parse at line@common#1#2#3{%
- \pgf at nfold@parser at moveup%
- \pgfextract at process\pgf at tmp@tang at i{\pgfpointnormalised{}\global\let\pgf at nfold@tmp\pgf at tmp}
- \let\pgf at nfold@next at type=#3%
- \let\pgf at nfold@next at visible=1%
- \let\pgf at nfold@next at tang@i\pgf at tmp@tang at i
- \let\pgf at nfold@next at tang@ii\pgf at tmp@tang at i
- \let\pgf at nfold@next at angle@i\pgf at nfold@tmp
- \let\pgf at nfold@next at angle@ii\pgf at nfold@tmp
- \let\pgf at nfold@next at first\pgf at nfold@cur at last
- \def\pgf at nfold@next at last{\pgf at x#1\pgf at y#2}%
- \pgf at nfold@parser at handlesegment%
-}
-
-\def\pgf at nfold@parselineto#1#2{%
- % the current end is still stored in next at last because parser at moveup has not been called yet
- \pgf at process{\pgfpointdiff{\pgf at nfold@next at last}{\pgf at x#1\pgf at y#2}}%
- \pgfpointtaxicabnorm\pgf at xa%
- % remove degenerate line segments (reduces glitches)
- \ifdim\pgf at xa>.1pt\relax%
- \pgf at nfold@parse at line@common{#1}{#2}{l}%
- \fi%
-}%
-
-\def\pgf at nfold@parsecurveto#1#2#3#4#5#6{%
- \pgf at nfold@parser at moveup%
- \pgf at offset@compute at tangents{\pgf at nfold@cur at last}{\pgf at x#1\pgf at y#2}{\pgf at x#3\pgf at y#4}{\pgf at x#5\pgf at y#6}%
- \let\pgf at nfold@next at type=c%
- \let\pgf at nfold@next at visible=1%
- % the following only need to be set if visible=1
- \let\pgf at nfold@next at tang@i=\pgf at tmp@tang at i
- \let\pgf at nfold@next at tang@ii=\pgf at tmp@tang at ii
- \let\pgf at nfold@next at angle@i\pgf at tmp@angle at i
- \let\pgf at nfold@next at angle@ii\pgf at tmp@angle at ii
- \let\pgf at nfold@next at first\pgf at nfold@cur at last
- \def\pgf at nfold@next at supporta{\pgf at x#1\pgf at y#2}
- \def\pgf at nfold@next at supportb{\pgf at x#3\pgf at y#4}
- \def\pgf at nfold@next at last{\pgf at x#5\pgf at y#6}
- \pgf at nfold@parser at handlesegment%
-}%
-
-\def\pgf at nfold@parseclosepath#1#2{%
- \pgf at process{\pgfpointdiff{\pgf at nfold@next at last}{\pgf at x#1\pgf at y#2}}%
- % closepath segments should always be processed even if they have zero length
- \pgfpointtaxicabnorm\pgf at xa%
- \ifdim\pgf at xa<0.1pt\relax%
- \pgf at nfold@parse at closepath@zerolength{#1}{#2}%
- \else%
- \pgf at nfold@parse at line@common{#1}{#2}{o}%
- \fi%
-}%
-
-\def\pgf at nfold@parse at closepath@zerolength#1#2{%
- \pgf at nfold@parser at moveup%
- \let\pgf at nfold@next at type=z%
- \let\pgf at nfold@next at visible=1%
- % Set the start and end tangent to the tangent of the first segment
- \let\pgf at nfold@next at tang@i\pgf at nfold@connsubpath at tang@i
- \let\pgf at nfold@next at tang@ii\pgf at nfold@connsubpath at tang@i
- \let\pgf at nfold@next at angle@i\pgf at nfold@connsubpath at angle@i
- \let\pgf at nfold@next at angle@ii\pgf at nfold@connsubpath at angle@i
- \let\pgf at nfold@next at first\pgf at nfold@cur at last
- % If problems arise, we need to put a fake point here (like \pgf at nfold@next at first + \pgf at nfold@next at tang@i)
- \def\pgf at nfold@next at last{\pgf at x#1\pgf at y#2}%
- \pgf at nfold@parser at handlesegment%
-}
-
-\def\pgf at nfold@parseinvisibleline#1#2{%
- \pgf at process{\pgfpointdiff{\pgf at nfold@next at last}{\pgf at x#1\pgf at y#2}}%
- \pgfpointtaxicabnorm\pgf at 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 at 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 at nfold@sectolast at segment).
- \ifdim\pgf at xa>.1pt\relax%
- \pgf at nfold@parse at line@common{#1}{#2}{i}%
- \else%
- \begingroup%
- % find the tangent of the second-to-last segment
- \let\pgf at nfold@parser at handlesegment\relax%
- \pgf at nfold@sectolast at segment%
- \global\let\pgf at nfold@tmp\pgf at nfold@next at 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 at process\pgf at nfold@next at first{\pgfpointdiff{\pgf at nfold@tmp}{\pgfqpoint{#1}{#2}}}%
- % write the tangent into (\pgf at x, \pgf at y) where the next macro expects it to be
- \pgf at nfold@tmp%
- \pgf at nfold@parse at line@common{#1}{#2}{i}%
- \fi%
-}%
-
-\def\pgf at nfold@parselast{%
- \pgf at nfold@parser at moveup%
- \let\pgf at nfold@next at type=t%
- \let\pgf at nfold@next at visible=0%
- \pgf at nfold@parser at handlesegment%
-}
-
-% Mostly for the sake of completeness; using TikZ' "\path (0,0) rectangle (1,1);" does not call this code
-\def\pgf at nfold@parserect#1#2#3#4{%
- \pgf at nfold@parsemoveto{#1}{#2}%
- \pgf at xc=#1\relax
- \pgf at yc=#2\relax
- \pgf at xd=#3\relax
- \pgf at yd=#4\relax
- \advance\pgf at yc\pgf at yd%
- \edef\pgf at temp{{\the\pgf at xc}{\the\pgf at yc}}%
- \expandafter\pgf at nfold@parselineto\pgf at temp%
- \advance\pgf at xc\pgf at xd%
- \edef\pgf at temp{{\the\pgf at xc}{\the\pgf at yc}}%
- \expandafter\pgf at nfold@parselineto\pgf at temp%
- \advance\pgf at yc-\pgf at yd%
- \edef\pgf at temp{{\the\pgf at xc}{\the\pgf at yc}}%
- \expandafter\pgf at nfold@parselineto\pgf at temp%
- \advance\pgf at xc-\pgf at xd%
- \edef\pgf at temp{{\the\pgf at xc}{\the\pgf at yc}}%
- \expandafter\pgf at nfold@parselineto\pgf at temp%
- \edef\pgf at marshal{\noexpand\pgf at nfold@parsemoveto{\the\pgf at xc}{\the\pgf at yc}}%
- \pgf at marshal%
-}
-
-% adds the contents of \pgf at nfold@macrotoadd to #1
-\def\pgf at 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 at nfold@macrotoadd}%
-}
-
-
-%
-% Tokens for the parsed path
-%
-
-%#3: cached normalised tangent (for efficiency)
-\def\pgf at nfold@token at lineto#1#2#3{%
- \pgfoffsetline@{#1}{#2}{\pgf at nfold@shiftamount}{#3}%
-}
-
-\def\pgf at nfold@token at lineto@continue#1#2#3{%
- \pgfoffsetlinenomove@{#1}{#2}{\pgf at nfold@shiftamount}{#3}%
-}
-
-\def\pgf at nfold@token at invisibleline#1#2#3{%
- % An invisible line should execute a moveto to the end point of the line
- \pgfqpointscale{\pgf at nfold@shiftamount}{#3}%
- \pgf at xc=-\pgf at y%
- \pgf at y=\pgf at x%
- \pgf at x=\pgf at xc%
- \pgfpathmoveto{\pgfpointadd{}{#2}}%
-}
-
-% #5, #6: cached normalised tangents at start and end (for efficiency)
-\def\pgf at nfold@token at curveto#1#2#3#4#5#6{%
- \def\pgf at tmp@tang at i{#5}%
- \def\pgf at tmp@tang at ii{#6}%
- \pgf at offset@bezier at segment@{#1}{#2}{#3}{#4}{\pgf at nfold@shiftamount}%
- \pgfpathmoveto{\pgf at bezier@offset at i}%
- \pgfpathcurveto{\pgf at bezier@offset at ii}{\pgf at bezier@offset at iii}{\pgf at bezier@offset at iv}%
-}
-
-\def\pgf at nfold@token at curveto@continue#1#2#3#4#5#6{%
- \def\pgf at tmp@tang at i{#5}%
- \def\pgf at tmp@tang at ii{#6}%
- \pgf at offset@bezier at segment@{#1}{#2}{#3}{#4}{\pgf at nfold@shiftamount}%
- \pgfpathcurveto{\pgf at bezier@offset at ii}{\pgf at bezier@offset at iii}{\pgf at bezier@offset at iv}%
-}
-
-\def\pgf at nfold@token at closepath{%
- \pgfpathclose%
-}
-
-% This is needed for some edge case explained above.
-% #1: segment at 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 at nfold@token at edgecase@movetostart#1#2{%
- \pgfpathmoveto{\pgfpointadd%
- {#1}{\pgfpointpolar{#2+90}{\pgf at nfold@shiftamount}}}%
-}
-
-
-\def\pgf at nfold@parse at setupfirst{%
- \let\pgf at nfold@next at type=f%
- % technically, @visible can be derived from @type, but I think this is more efficient
- \let\pgf at nfold@next at visible=0%
- \edef\pgf at nfold@next at last{\pgf at x\the\pgf at path@lastx\pgf at y\the\pgf at 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 at nfold@next at tang@i=\pgfpointorigin%
- %\let\pgf at nfold@next at tang@ii=\pgfpointorigin%
- % \def\pgf at nfold@next at angle@i{0}%
- % \def\pgf at nfold@next at angle@ii{0}%
- % \let\pgf at nfold@next at first\pgfpointorigin%
- % the following only need to be set if type=c
- % \let\pgf at nfold@next at supporta\pgfpointorigin%
- % \let\pgf at nfold@next at supportb\pgfpointorigin%
-}
-
-\def\pgf at 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 at tempdima=\pgfmathresult pt
- \advance\pgfutil at tempdima by 360pt
- \edef\pgfmathresult{\pgf at sys@tonumber\pgfutil at tempdima}
- \else\ifdim\pgfmathresult pt>180pt\relax
- \pgfutil at tempdima=\pgfmathresult pt
- \advance\pgfutil at tempdima by -360pt
- \edef\pgfmathresult{\pgf at sys@tonumber\pgfutil at tempdima}
- \fi\fi
-}
-
-
-
-\def\pgf at nfold@parser at moveup{%
- \let\pgf at nfold@prev at type\pgf at nfold@cur at type%
- \let\pgf at nfold@prev at visible\pgf at nfold@cur at visible%
- \let\pgf at nfold@prev at tang@i\pgf at nfold@cur at tang@i%
- \let\pgf at nfold@prev at tang@ii\pgf at nfold@cur at tang@ii%
- \let\pgf at nfold@prev at angle@i\pgf at nfold@cur at angle@i%
- \let\pgf at nfold@prev at angle@ii\pgf at nfold@cur at angle@ii%
- \let\pgf at nfold@prev at first\pgf at nfold@cur at first%
- \let\pgf at nfold@prev at supporta\pgf at nfold@cur at supporta%
- \let\pgf at nfold@prev at supportb\pgf at nfold@cur at supportb%
- \let\pgf at nfold@prev at last\pgf at nfold@cur at last%
- \let\pgf at nfold@cur at type\pgf at nfold@next at type%
- \let\pgf at nfold@cur at visible\pgf at nfold@next at visible%
- \let\pgf at nfold@cur at tang@i\pgf at nfold@next at tang@i%
- \let\pgf at nfold@cur at tang@ii\pgf at nfold@next at tang@ii%
- \let\pgf at nfold@cur at angle@i\pgf at nfold@next at angle@i%
- \let\pgf at nfold@cur at angle@ii\pgf at nfold@next at angle@ii
- \let\pgf at nfold@cur at first\pgf at nfold@next at first%
- \let\pgf at nfold@cur at supporta\pgf at nfold@next at supporta%
- \let\pgf at nfold@cur at supportb\pgf at nfold@next at supportb%
- \let\pgf at nfold@cur at last\pgf at nfold@next at last%
-}
-
-%
-% Iterating over the parsed soft path
-% -----------------------------------
-%
-
-\newcount\pgf at nfold@index
-\def\pgf at nfold@run at loop{%
- \pgf at nfold@index=\pgf at nfold@order%
- \pgf at nfold@run at loop@%
-}
-
-\def\pgf at nfold@run at loop@{%
- \pgf at nfold@loop at inner%
- \advance\pgf at nfold@index by -1\relax
- \ifnum\pgf at nfold@index>0\relax%
- \pgf at nfold@run at loop@%
- \fi%
-}
-
-\def\pgf at nfold@loop at inner{%
- \pgfmathsetmacro{\pgf at nfold@shift at fraction}%
- {-1+2*(\pgf at nfold@index-1)/(\pgf at nfold@order-1)}%
- % Do not store shiftamount as a length (i.e. with pt) because we want to use it in \pgfqpointscale{}{}
- \pgfmathsetmacro{\pgf at nfold@shiftamount}{\pgf at nfold@hwidth*\pgf at nfold@shift at fraction}
- % Transformations are already baked into the path; without this call, they would be applied twice
- \pgftransformreset%
- \parsedpath%
- \pgfsyssoftpath at flushcurrentpath%
- \pgf at up@action%
-}
-
-% Computes both the width of the component lines into \pgf at x and the distance
-% from the center to the outermost line centers into \pgf at y
-% from the current values of \pgflinewidth and \pgfinnerlinewidth.
-\def\pgf at nfold@compute at widths@from at double{
- \pgf at x=\pgflinewidth\relax%
- \pgf at y=\pgf at x\relax%
- \advance\pgf at x-\pgfinnerlinewidth\relax%
- \advance\pgf at y+\pgfinnerlinewidth\relax%
- \pgf at x=.5\pgf at x\relax%
- \pgf at y=.25\pgf at y\relax%
-}
-
-\def\pgf at nfold@render at cached@softpath{%
- \pgfscope% must use a scope, otherwise we break the arrow tips
- % Compute the full and constituent part line widths
- \pgf at nfold@compute at widths@from at double%
- \pgfsetlinewidth\pgf at x%
- \edef\pgf at nfold@hwidth{\the\pgf at y}%
- \pgfprocessround{\pgf at nfold@cachedpath}{\pgf at nfold@cachedpath}% remove tokens from the soft path
- \pgf at nfold@parsearrows%
- \pgf at nfold@parsesoftpath{\pgf at nfold@cachedpath}{\parsedpath}%
- \pgf at nfold@run at 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 at nfold@parsed at hwidth{#2}
- % \pgf at nfold@hwidth must always be positive
- \pgf at x=\pgf at nfold@parsed at hwidth\relax
- \ifdim\pgf at x<0pt\relax
- \pgf at x=-\pgf at x
- \def\pgf at nfold@shift at fraction{-1}
- \else
- \def\pgf at nfold@shift at fraction{1}
- \fi
- \edef\pgf at nfold@parsed at hwidth{\the\pgf at x}
- \pgfoffsetpathqfraction{#1}{\pgf at nfold@parsed at hwidth}{\pgf at nfold@shift at 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 at nfold@parsed at hwidth{#2}
- \pgfmathsetmacro\pgf at nfold@shift at fraction{#3}
- \pgfoffsetpathqfraction{#1}{\pgf at nfold@parsed at hwidth}{\pgf at nfold@shift at fraction}
- \endgroup
-}
-
-% This has the same output as the #3-th segment of nfold=#4.
-\def\pgfoffsetpathindex#1#2#3#4{%
- \begingroup
- \pgfmathsetmacro\pgf at nfold@shift at fraction{-1+2*(#3-1)/(#4-1)}
- \pgfoffsetpathqfraction{#1}{#2}{\pgf at nfold@shift at fraction}
- \endgroup
-}
-
-% A quick version that skips processing the input values
-\def\pgfoffsetpathqfraction#1#2#3{%
- \begingroup
- \pgf at x=#2\relax
- \edef\pgf at nfold@hwidth{\the\pgf at x}
- \edef\pgf at nfold@shift at fraction{#3}
- \pgf at x=\pgf at nfold@shift at fraction\pgf at x\relax
- \edef\pgf at nfold@shiftamount{\pgf at sys@tonumber\pgf at x}
- \pgfprocessround{#1}{\pgf at nfold@cachedpath}% remove tokens from the soft path
- \pgf at nfold@parsesoftpath{\pgf at 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 at nfold@order=#1\relax%
- \ifnum\pgf at nfold@order<1\relax%
- \pgfutil at packageerror{tikz-nfold}{The key /pgf/nfold must take a value of at least 1, got \the\pgf at 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 at nfold@order>\pgf at nfold@intersec at numcached\relax
- \ifdefined\pgfintersectionofpaths\else
- \pgf at nfold@intersectionsnotloadedtrue
- \fi
- \fi
- },
- /pgf/nfold/.default=2
-}
-
-
-% use \tikzset for scoping reasons, does not appear to be equivalent to \pgfset{/tikz/...=...}
\tikzset{
nfold/.code={
\edef\pgf at tmp{\noexpand\pgfkeys{/pgf/nfold=#1}}
- % patch \tikz at double@setup to set /pgf/nfold=#1 as well
\expandafter\expandafter\expandafter\def%
\expandafter\expandafter\expandafter\tikz at double@setup%
\expandafter\expandafter\expandafter{\expandafter\tikz at double@setup\pgf at tmp}
@@ -1313,12 +33,10 @@
},
nfold/.default=2,
scaling nfold/.code={%
- \pgfscope% scope to contain \tikz at double@setup
+ \pgfscope%
\tikz at double@setup
- % extract double distance between line centers into \pgf at x
\pgf at nfold@compute at widths@from at double
\pgf at y=2\pgf at y
- % store (order-1)*\pgf at x in \pgf at xa
\c at pgf@counta=#1
\advance\c at pgf@counta by -1\relax
\global\pgf at y=\c at pgf@counta\pgf at 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 at double@setup
+ \pgfscope%
\tikz at double@setup
- % extract double distance between line centers into \pgf at x
\pgf at nfold@compute at widths@from at double
- % store (order-1)*\pgf at y in \pgf at ya
\c at pgf@counta=#1
\advance\c at pgf@counta by -1\relax
\pgf at ya=\c at pgf@counta\pgf at y
- % compute the label offset, which is (order-2)*\pgf at y + .5*\pgf at x
\advance\c at pgf@counta by -1\relax
\pgf at xa=\c at pgf@counta\pgf at y
\advance\pgf at xa by .5\pgf at x
- % save the results in \pgf at x and \pgf at y
\global\pgf at x=\pgf at xa
\global\pgf at y=2\pgf at ya
\endpgfscope
More information about the tex-live-commits
mailing list.