texlive[57639] Master/texmf-dist: spath3 (6feb21)

commits+karl at tug.org commits+karl at tug.org
Sat Feb 6 23:29:38 CET 2021


Revision: 57639
          http://tug.org/svn/texlive?view=revision&revision=57639
Author:   karl
Date:     2021-02-06 23:29:38 +0100 (Sat, 06 Feb 2021)
Log Message:
-----------
spath3 (6feb21)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/latex/spath3/calligraphy.pdf
    trunk/Master/texmf-dist/doc/latex/spath3/calligraphy.tex
    trunk/Master/texmf-dist/doc/latex/spath3/knots.pdf
    trunk/Master/texmf-dist/doc/latex/spath3/knots.tex
    trunk/Master/texmf-dist/doc/latex/spath3/spath3.pdf
    trunk/Master/texmf-dist/doc/latex/spath3/spath3.tex
    trunk/Master/texmf-dist/doc/latex/spath3/spath3_code.pdf
    trunk/Master/texmf-dist/source/latex/spath3/spath3_code.dtx
    trunk/Master/texmf-dist/source/latex/spath3/spath3_code.ins
    trunk/Master/texmf-dist/tex/latex/spath3/spath3.sty
    trunk/Master/texmf-dist/tex/latex/spath3/tikzlibrarycalligraphy.code.tex
    trunk/Master/texmf-dist/tex/latex/spath3/tikzlibraryknots.code.tex
    trunk/Master/texmf-dist/tex/latex/spath3/tikzlibraryspath3.code.tex

Modified: trunk/Master/texmf-dist/doc/latex/spath3/calligraphy.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/spath3/calligraphy.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/spath3/calligraphy.tex	2021-02-06 22:28:55 UTC (rev 57638)
+++ trunk/Master/texmf-dist/doc/latex/spath3/calligraphy.tex	2021-02-06 22:29:38 UTC (rev 57639)
@@ -1,4 +1,4 @@
-\immediate\write18{tex spath3_doc.dtx}
+%\immediate\write18{tex spath3_doc.dtx}
 \documentclass{ltxdoc}
 \usepackage[T1]{fontenc}
 \usepackage{trace}
@@ -41,6 +41,11 @@
 \providecommand*{\url}{\texttt}
 \GetFileInfo{spath3.sty}
 
+\pdfstringdefDisableCommands{%
+  \def\\{}%
+  \def\url#1{<#1>}%
+}
+
 \title{The \textsf{calligraphy} Package: Documentation}
 \author{Andrew Stacey \\ \url{loopspace at mathforge.org}}
 \date{\fileversion~from \filedate}

Modified: trunk/Master/texmf-dist/doc/latex/spath3/knots.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/spath3/knots.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/spath3/knots.tex	2021-02-06 22:28:55 UTC (rev 57638)
+++ trunk/Master/texmf-dist/doc/latex/spath3/knots.tex	2021-02-06 22:29:38 UTC (rev 57639)
@@ -1,4 +1,4 @@
-\immediate\write18{tex spath3_code.dtx}
+%\immediate\write18{tex spath3_code.dtx}
 \documentclass{ltxdoc}
 \usepackage[T1]{fontenc}
 \usepackage{trace}
@@ -42,6 +42,11 @@
 \providecommand*{\url}{\texttt}
 \GetFileInfo{spath3.sty}
 
+\pdfstringdefDisableCommands{%
+  \def\\{}%
+  \def\url#1{<#1>}%
+}
+ 
 \title{The \textsf{knots} Package: Documentation}
 \author{Andrew Stacey \\ \url{loopspace at mathforge.org}}
 \date{\fileversion~from \filedate}
@@ -393,8 +398,10 @@
 \item \DescribeMacro{background colour} \DescribeMacro{background color}
 The keys \Verb+background colour=<colour>+ and  \Verb+background color=<color>+ set the background colour for the crossings.
 
-\item \DescribeMacro{intersection <number>}
-The style in \Verb+intersection <number>+ is applied just before that crossing is drawn so can be used to modify the crossing style just for that crossing.
+\item \DescribeMacro{every intersection>} \DescribeMacro{intersection <number>}
+The style in \Verb+every intersection+ is applied before rendering each crossing, with \Verb+intersection <number>+ applied just before that specific crossing.
+These can be used to change how the over-strands are rendered when they are redrawn.
+For an example on using \Verb+every intersection+, see Section~\ref{sec:celtic}.
 
 
 \item \DescribeMacro{draft mode}
@@ -435,6 +442,100 @@
 \end{lstlisting}
 \end{itemize}
 
+
+\subsection{Celtic Knots}
+\label{sec:celtic}
+
+By ``Celtic knot'' here, I mean a knot drawn in a way to suggest a carved object.
+Usually, this is achieved by using the \Verb+double+ style to outline the path.
+This interacts a little oddly with how the knots package redraws the curve near crossings which can result in small artefacts visible when the diagram is viewed (my understanding is that they are not present when the diagram is printed).
+There is, however, a way to get these diagrams right, as this section will show.
+
+I will just note here that there is the \href{celtic knots}{https://ctan.org/pkg/celtic} package which works for a particular type of Celtic knots.
+If your Celtic knot fits what that package can produce, it is a better choice.
+See that package for details.
+
+Back to what this package can provide.
+When rendering a crossing, the over-strand is redrawn clipped to a small region around the crossing.
+The clipping, however, interacts badly with the \Verb+double+ effect.
+The \Verb+double+ effect is achieved by drawing the line twice, once thicker with the outer colour and once thinner with the inner colour.
+At the boundary of the clipping region there is ``bleed through'' of the outer colour into the inner colour, at least when the image is displayed on a screen.
+If the inner colour is darker, this is not noticeable.
+But with a Celtic style knot then the inner colour is usually a lighter colour, such as the page colour, and so the effect is visible.
+
+The solution to this is to exploit the fact that when using the Celtic style then one doesn't actually want gaps in the under-strand to show that it is the under-strand.
+The Celtic style makes it very obvious which strand is which without that.
+These gaps are achieved by drawing the over-strand in a thicker line with the colour of the background.
+This is almost exactly what the \Verb+double+ key does.
+So rather than using the \Verb+double+ key directly, we use the mechanism of how the knot crossings are rendered to reproduce the effect.
+This avoids the artefacts because when the knot library draws the two paths then it clips them to slightly different sized regions.
+
+\begin{example}
+\begin{tikzpicture}[scale=0.8]
+\begin{knot}[
+  consider self intersections=no splits,
+  end tolerance=1pt,
+  line join=round,
+  clip width=1,
+  ignore endpoint intersections=true,
+  background color=red,
+  every intersection/.style={
+    line width=13pt,
+    only when rendering/.style={
+      draw=white,
+      line width=9pt,
+      double=none,
+    }
+  },
+  only when rendering/.style={
+    red,
+    line width=2pt,
+    double=white,
+    double distance=9pt,
+  },
+  flip crossing/.list={2,3,6,8}
+]
+
+\strand
+(0.5,1) to [out=north, in=south]
+(2.5,4) to [out=north, in=south]
+(0.5,7) -- (0.5,7) -- (0.5,7.5) --
+(1,7.5) to [out=east, in=west]
+(3,6.5) to [out=east, in=225]
+(4.5,7.5) to [out=45, in=south]
+(5.5,9) to [out=north, in=-45]
+(4.5,10.5) to [out=135,in=east]
+(3,11.5) to [out=west,in=45]
+(1.5,10.5) to [out=225,in=north]
+(0.5,9) -- (0.5,8.5) --
+(1,8.5) to [out=east, in=south]
+(2.5,10) to [out=north, in=east]
+(1,11.5) -- (0.5,11.5) --
+(0.5,11) to [out=south, in=north]
+(2.5,8) to [out=south, in=north]
+(0.5,5) -- (0.5,4.5) --
+(1,4.5) to [out=east, in=west]
+(3,5.5) to [out=east, in=135]
+(4.5,4.5) to [out=-45, in=north]
+(5.5,3) to [out=south, in=45]
+(4.5,1.5) to [out=225, in=east]
+(3,0.5) to [out=west, in=-45]
+(1.5,1.5) to [out=135, in=south]
+(0.5,3) -- (0.5,3.5) --
+(1,3.5) to [out=east, in=north]
+(2.5,2) to [out=south, in=east]
+(1,0.5) -- (0.5,0.5) -- (0.5,1);
+\end{knot}
+
+\end{tikzpicture}
+
+\end{example}
+
+
+
+
+
+
 \subsection{Other Styles}
 
 The other things defined by this package are for drawing knot diagrams when the user knows in advance either the locations of the crossings or can arrange that the paths are drawn in the correct order.

Modified: trunk/Master/texmf-dist/doc/latex/spath3/spath3.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/spath3/spath3.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/spath3/spath3.tex	2021-02-06 22:28:55 UTC (rev 57638)
+++ trunk/Master/texmf-dist/doc/latex/spath3/spath3.tex	2021-02-06 22:29:38 UTC (rev 57639)
@@ -1,5 +1,5 @@
-\RequirePackage{shellesc}
-\immediate\write18{tex spath3_code.dtx}
+%\RequirePackage{shellesc}
+%\immediate\write18{tex spath3_code.dtx}
 \documentclass{l3doc}
 \usepackage{tikz}
 \usetikzlibrary{
@@ -43,6 +43,11 @@
 \providecommand*{\url}{\texttt}
 \GetFileInfo{spath3.sty}
 
+\pdfstringdefDisableCommands{%
+  \def\\{}%
+  \def\url#1{<#1>}%
+}
+
 \title{The \textsf{spath3} Package: Documentation}
 \author{Andrew Stacey \\ \url{loopspace at mathforge.org}}
   \date{\fileversion~from \filedate}
@@ -63,7 +68,7 @@
   However, over time I've found myself wanting to use the routines of this package at a higher level and so have designed some user-level interfaces.
   This document documents those.
 
-  To clarify some terminology, paths are composed of \emph{segment} and \emph{components}.
+  To clarify some terminology used in this document (and more generally, this package), I regard paths as being composed of \emph{segments} and \emph{components}.
 A \emph{segment} is a minimal drawing piece.
 Thus it might be a straight line or a B\'ezier curve.
 A \emph{component} is a minimal connected section of the path.
@@ -70,6 +75,10 @@
 So every component starts with a move command and continues until the next move command.
 For ease of implementation (and to enable a copperplate pen in the calligraphy package!), an isolated move is considered as a component.
 
+There are no doubt bugs in this package, and useful things that I haven't implemented.
+If you have found one of either of these, please let me know!
+The best way is to open an issue at the code repository on github, at \href{https://github.com/loopspace/spath3}{https://github.com/loopspace/spath3}.
+
   
   \section{TikZ Keys}
 
@@ -78,13 +87,19 @@
 \end{lstlisting}
 
 The \texttt{spath3} TikZ library defines a set of keys that can be issued to muck about with soft paths.
-These are all defined in the \texttt{spath} family, so all the following keys should be prefixed by \texttt{spath/}, or the key \texttt{spath/.cd} needs to be used beforehand.
+These are all defined in the \texttt{spath} family, so all the following keys should be prefixed by \texttt{spath/}, or the key \texttt{spath/.cd} needs to be used beforehand (but note that as yet I haven't implemented sending unknown keys back to the main \Verb+tikz+ directory).
 
+The keys try to gracefully fail if the path doesn't exist or is empty.
+The intention is that the document should still compile with a warning in the log file (and on the console output).
+If this doesn't happen, please report it.
+
+
 \subsection{Saving and Using Soft Paths}
 
-\begin{function}{save}
+\begin{function}{save, save global}
 \begin{syntax}
 |save=|\meta{name}
+|save global=|\meta{name}
 \end{syntax}
 
 Saves the current path with name \texttt{<name>}.
@@ -91,6 +106,7 @@
 This delays until the path is fully constructed so can be issued in the options to the main command.
 
 Soft paths constructed this way are local to the group in which the path command is issued.
+The |global| version saves the path globally which is useful when the original path is inside a scope or even another tikzpicture.
 
 The soft path is actually stored in a macro constructed from the name.
 There are a couple of reasons for using a \emph{name} rather than a macro directly.
@@ -98,28 +114,24 @@
 The other is to provide a way to link a soft path with a set of TikZ styles (this is particularly useful when splitting the path into components).
 \end{function}
 
-\begin{function}{save global}
+\begin{function}{clone, clone globally}
 \begin{syntax}
-|save global=|\meta{name}
-\end{syntax}
-
-Saves the current soft path globally.
-\end{function}
-
-\begin{function}{clone}
-\begin{syntax}
 |clone=|\marg{target}\marg{source}
+|clone globally=|\marg{target}\marg{source}
 \end{syntax}
 
 Clones one soft path into another.
+In the second, the clone is global (the original need not be).
 \end{function}
 
-\begin{function}{restore}
+\begin{function}{restore, restore reverse}
 \begin{syntax}
 |restore=|\meta{name}
+|restore reverse=|\meta{name}
 \end{syntax}
 
 Restores a previously saved soft path to the current path.
+The \Verb+reverse+ version reverses the soft path first.
 This happens immediately so can be issued in the options to the main command and then the path can be extended with normal drawing commands.
 Any keys that affect the soft path directly should be applied \emph{before} this one.
 
@@ -126,73 +138,88 @@
 One thing should be noted about transformations.
 By the time a soft path is built, all available transformations have been applied.
 This means that when re-inserting a soft path back into a high level command (such as |\draw|), the effect of existing transformations might produce some confusing effects.
-When restoring a path then the library tries to set the last point correctly, but depending on how this is used it can result in transformations being applied twice.
+When restoring a path then the library tries to set up various internals of TikZ correctly, but there may be some things I've overlooked or not accounted for particularly with regard to existing transformations; if you spot anything working oddly then please report it to me.
+
+Restoring a path also sets things right for positioning nodes along the path.
+Using the \Verb+pos=D+ key on a node positions that node at a particular point on the path.
+Exactly how the parameter is interpreted is the same as for the \Verb+spath+ coordinate system described in Section~\ref{sec:coordinates}.
 \end{function}
 
-\begin{function}{append}
+\begin{function}{
+  append,
+  append reverse,
+  append no move,
+  append reverse no move
+}
 \begin{syntax}
 |append=|\meta{name}
+|append reverse=|\meta{name}
+|append no move=|\meta{name}
+|append reverse no move=|\meta{name}
 \end{syntax}
 
-This inserts a soft path into the path at the current point, it is therefore more suited to being used part way through a path construction.
+This inserts a soft path, or its reverse, into the path at the current point, it is therefore more suited to being used part way through a path construction.
 In a sense, it is a little like a \texttt{pic} in that it enables the user to construct a path segment early to be reused at various places.
 
-The path is \emph{welded} on to the current path, meaning that it starts from the current point and there is no \texttt{move}.
+The path is \emph{welded} on to the current path, meaning that the intervening \Verb+move+ is removed.
 This is particularly useful for creating filled regions.
+The first two versions translate the path so that it starts at the last point on the existing path, the second two versions don't do this translation (the intention being that in such a case the translation is omitted because it is \emph{unnecessary} rather than simply not wanted because the effect of removing the intervening move will adjust the initial segment of the appended path otherwise).
+
+As with restoring a path, the last point and node positioning machinery is established.
+The positioning is relative to the appended part of the path, not the full path.
 \end{function}
 
-\begin{function}{reverse}
+\begin{function}{insert, insert reverse}
 \begin{syntax}
-|reverse=|\meta{name}
+|insert=|\meta{name}
+|insert reverse=|\meta{name}
 \end{syntax}
 
-Reverses the path in the named spath object.
-This doesn't do any actually drawing.
-The effect is local, but if you want to work with both the original path and its reversal in the same path then use the \texttt{clone} key to copy it first.
+Like \Verb+append+ except that it doesn't remove the intervening \Verb+move+ and doesn't translate the inserted path.
+The \Verb+reverse+ version reverses the path first.
 \end{function}
 
-\begin{function}{append reverse}
+\begin{function}{to}
 \begin{syntax}
-|append reverse=|\meta{name}
+|to=|\marg{name}
 \end{syntax}
 
-Like \texttt{append} except that the inserted path is reversed first.
+This defines a \Verb+to+ path from a soft path, so it inserts the soft path into the current path to span the gap between the start and end.
+The path is transformed by rotation, translation, and uniform scaling so that it exactly spans the gap required by the \Verb+to+ syntax.
+(If the start and end point of the soft path are very close together then it won't span the gap.)
 \end{function}
 
-\begin{function}{insert}
-\begin{syntax}
-|insert=|\meta{name}
-\end{syntax}
 
-Like \texttt{append} except that it doesn't move the inserted path and there is a move between the current path and the inserted path.
-\end{function}
+\subsection{Transformation Routines}
 
-\begin{function}{
-  shorten at end,
-shorten at start,
-shorten at both ends
-}
+The following keys all apply some sort of transformation to the soft path.
+They do not render the path, but simply adjust it.
+The global versions apply their transformation globally, otherwise it is local to the current group (or scope).
+
+\begin{function}{reverse, reverse global}
 \begin{syntax}
-|shorten at end=|\marg{name}\marg{dimen}
+|reverse=|\meta{name}
+|reverse globally=|\meta{name}
 \end{syntax}
 
-Shortens the soft path by the dimension from one or both ends.
-This shortens the soft path along its length so that it is guaranteed that the shorter path traces a subset of the original path.
-For B\'ezier curves, however, the amount of shortening is approximate and is better for shorter distances.
-If wanting to shorten by a large amount it is better to shorten by a small amount a number of times.
+Reverses the soft path in place.
+If you want to use the original path and its reversal in the same path (for example, for constructing a region to fill) then use the \texttt{clone} key to copy it first.
 \end{function}
 
-\begin{function}{translate}
+
+\begin{function}{translate, translate global}
 \begin{syntax}
 |translate=|\marg{name}\marg{x-dimen}\marg{y-dimen}
+|translate globally=|\marg{name}\marg{x-dimen}\marg{y-dimen}
 \end{syntax}
 
 Translates the soft path by the given dimensions.
 \end{function}
 
-\begin{function}{transform}
+\begin{function}{transform, transform global}
 \begin{syntax}
 |transform=|\marg{name}\marg{transformations}
+|transform globally=|\marg{name}\marg{transformations}
 \end{syntax}
 
 This applies the transformation to the soft path.
@@ -199,21 +226,92 @@
 The transformation is processed by TikZ so should consist of TikZ-level transformations such as |shift={(2,2)}|.
 \end{function}
 
+\begin{function}{span, span global}
+\begin{syntax}
+|span=|\marg{name}\marg{start point}\marg{end point}
+|span globally=|\marg{name}\marg{start point}\marg{end point}
+\end{syntax}
+
+This transforms the named path so that it goes from the start point to the end point.
+As with the \Verb+to+ path construction and the \Verb+splice+ method, this won't work if the path ends very close to where it starts.
+\end{function}
+
+\begin{function}{splice, splice global}
+\begin{syntax}
+|splice=|\marg{initial path}\marg{splice path}\marg{final path}
+|splice globally=|\marg{initial path}\marg{splice path}\marg{final path}
+\end{syntax}
+
+This splices the middle path into the gap between the initial and final paths.
+The middle path is transformed to fit (don't try this with a path whose starting and ending points are close together) and the paths are joined so that the last component of the initial path and the first component of the splice path become a single component, and similarly at the other end.
+\end{function}
+
+\begin{function}{join components with, join components globally with}
+\begin{syntax}
+|join components with=|\marg{path}\marg{splice path}
+|join components globally with=|\marg{path}\marg{splice path}
+\end{syntax}
+
+This inserts the |splice path| in the gaps between components of |path|.
+A \emph{spot weld} is performed first to join any components where the end of one is the start of the next.
+The result is a single component path.
+This does \emph{not} close the resulting path, for that see the key |close with|.
+\end{function}
+
+\begin{function}{close, close globally, close with, close globally with}
+\begin{syntax}
+|close=|\marg{path}
+|close globally=|\marg{path}
+|close with=|\marg{path}\marg{splice path}
+|close globally with=|\marg{path}\marg{splice path}
+\end{syntax}
+
+These all close the last component of the given path.
+The first two will insert a line segment if the initial and final points of the component are not sufficiently close.
+The latter two allow you to specify another path to insert.
+\end{function}
+
 \subsection{Intersection Routines}
 
 To use these features you need to use the \texttt{intersections} library.
+Note that there is currently an issue with the intersections routine when trying to intersect two parallel (or near parallel) lines.
+One workaround is to replace one of the lines by a B\'ezier curve along the same path.
+The best such replacement is to put the control points at one third and two thirds between the start and end.
 
-\begin{function}{split at self intersections}
+\begin{function}{
+  split at self intersections,
+  split globally at self intersections
+}
 \begin{syntax}
 |split at self intersections=|\meta{path}
+|split globally at self intersections=|\meta{path}
 \end{syntax}
 
 This inserts breaks into the named soft path at the points where it intersects itself.
+The breaks are not gaps, to achieve that use the shortening routines after this, rather they are a change of component.
+Think of it as if you took the pen off the page at that point and then put it straight back down again.
 \end{function}
 
-\begin{function}{split at intersections}
+\begin{function}{
+  split at intersections with,
+  split globally at intersections with
+}
 \begin{syntax}
+|split at intersections with=|\marg{first}\marg{second}
+|split globally at intersections with=|\marg{first}\marg{second}
+\end{syntax}
+
+This inserts breaks into the first path where it intersects with the second.
+The second path is not changed.
+\end{function}
+
+\begin{function}{
+  split at intersections,
+  split globally at intersections
+}
+\begin{syntax}
 |split at intersections=|\marg{first}\marg{second}
+|split globally at intersections=|\marg{first}\marg{second}
 \end{syntax}
 
 This inserts breaks into a pair of paths at their mutual intersections.
@@ -221,13 +319,26 @@
 
 \subsection{Working with Components}
 
-\begin{function}{get components of}
+\begin{function}{
+  get components of,
+  get components of globally,
+  \getComponentOf
+}
 \begin{syntax}
-|get components of=|\marg{macro}\marg{path}
+|get components of=|\marg{path}\marg{macro}
+|get components of globally=|\marg{path}\marg{macro}
+|\getComponentOf|\marg{macro}\marg{number}
 \end{syntax}
   
 This splits the path into a list of its components, which are stored in the macro.
 The macro can be used in a |\foreach|.
+
+The macro consists of a comma separated list of names of the components (the actual names used are of the form \Verb+anonymous_N+).
+To access an individual component, use the command \Verb+\getComponentOf+.
+This can be used directly in place of a path name in any other key, such as \Verb+restore+, (it is just the \LaTeX3 command \Verb+\clist_item:Nn+).
+
+Note that these are \emph{copies} of the components of the original path.
+Changing a component doesn't update the original path.
 \end{function}
 
 \begin{function}{render components}
@@ -248,49 +359,87 @@
 \end{enumerate}
 \end{function}
 
-\begin{function}{insert gaps after components}
+\begin{function}{
+  insert gaps after components,
+  insert gaps globally after components
+}
 \begin{syntax}
 |insert gaps after components=|\marg{path}\marg{gap}\marg{components}
+|insert gaps globally after components=|\marg{path}\marg{gap}\marg{components}
 \end{syntax}
 
 This inserts a gap between components of a path by shortening the end of the specified component and start of the next one.
-The list of components is passed through a |\foreach| loop so that syntax like |2,4,...,16|.
+The list of components is passed through a |\foreach| loop so that syntax like |2,4,...,16| can be used.
 \end{function}
 
-\begin{function}{join components}
+\begin{function}{
+  join components,
+  join components globally
+}
 \begin{syntax}
 |join components=|\marg{path}\marg{components}
+|join components globally=|\marg{path}\marg{components}
 \end{syntax}
 
-This removes the \texttt{move} between the given component and the previous one.
+This removes the |move| between each of the given components and the previous one.
+The list of components is processed by |\foreach|.
 If the component is the first one then it is joined to the last component.
 \end{function}
 
-\begin{function}{spot weld}
+\begin{function}{
+  spot weld,
+  spot weld globally
+}
 \begin{syntax}
 |spot weld=|\meta{path}
+|spot weld globally=|\meta{path}
 \end{syntax}
 
 This removes the \texttt{move} between any two components of the path where the end point of one component is the same as the initial point of the next (the tolerance on error here is \(0.01\)pt).
 \end{function}
 
-\begin{function}{remove empty components}
+\begin{function}{
+  remove empty components,
+  remove empty components globally
+}
 \begin{syntax}
 |remove empty components=|\meta{path}
+|remove empty components globally=|\meta{path}
 \end{syntax}
 
 This removes empty components of the path (which consist of simply a move).
 \end{function}
 
+\begin{function}{
+  remove components,
+  remove components globally
+}
+\begin{syntax}
+|remove components=|\marg{path}\marg{list}
+|remove components globally=|\marg{path}\marg{list}
+\end{syntax}
+
+This removes the listed components of the path.
+As with other list routines, the list is parsed via |foreach| first.
+\end{function}
+
 \subsection{Shortening Paths}
 
 \begin{function}{
-shorten path at end,
-shorten path at start,
-shorten path at both ends
+shorten at end,
+shorten at start,
+shorten at both ends,
+shorten globally at end,
+shorten globally at start,
+shorten globally at both ends,
 }
 \begin{syntax}
-|shorten path at end=|\marg{path}\marg{length}
+|shorten at start=|\marg{path}\marg{length}
+|shorten at end=|\marg{path}\marg{length}
+|shorten at both ends=|\marg{path}\marg{length}
+|shorten globally at start=|\marg{path}\marg{length}
+|shorten globally at end=|\marg{path}\marg{length}
+|shorten globally at both ends=|\marg{path}\marg{length}
 \end{syntax}
 
 This shortens a path by the given amount from the specified end.
@@ -298,6 +447,7 @@
 This is particularly true for B\'ezier paths and if there is a very short segment at the end.
 
 It uses the derivative at the end to work out how much to shorten by.
+If wanting to shorten by a large amount it is better to shorten by a small amount a number of times.
 \end{function}
 
 \subsection{Exporting Paths}
@@ -322,9 +472,14 @@
 
 \subsection{Knots}
 
-\begin{function}{knot}
+\begin{function}{
+  global knot,
+  knot,
+  draft mode
+}
 \begin{syntax}
 |knot=|\meta{path}\meta{gap}\meta{components}
+|global knot=|\meta{path}\meta{gap}\meta{components}
 \end{syntax}
 
 This style combines various of the above to make it simpler to draw knots and links.
@@ -340,6 +495,8 @@
 }
 \end{lstlisting}
 
+(The \Verb+global+ version makes the path manipulating commands work globally.)
+
 This splits a path at the points where it self-intersects and then inserts gaps between specified components.
 The key |maybe spot weld| does a |spot weld| depending on whether or not the key |draft mode| is set to |true| or |false|.
 The point here is that when designing the knot it is useful to not weld together components since that changes the component count.
@@ -349,8 +506,9 @@
 \end{function}
 
 \subsection{Coordinates}
+\label{sec:coordinates}
 
-Soft paths are not natural TikZ objects and so when replaced back into a TikZ path construction then they don't fully interact with other TikZ things, like placing nodes at points on the path.
+Soft paths are not natural TikZ objects and so when replaced back into a TikZ path construction then they don't fully interact with other TikZ things, like placing nodes at points on the path (though I've done my best to make that work).
 To make things a little easier there is defined a coordinate system which identifies a point at a certain location along a soft path and keys which apply a transformation.
 
 \begin{function}{spath cs}
@@ -444,6 +602,45 @@
 \end{tikzpicture}
 \end{example}
 
+\begin{example}
+\begin{tikzpicture}
+\path[draw=orange,ultra thick,spath/save=a] (3,2) -- ++(1,1) to[out=90,in=-90] ++(3,0);
+
+\tikzset{
+  spath/span={a}{(4,5)}{(7,1)}
+}
+
+\fill
+(4,5) circle[radius=3pt]
+(7,1) circle[radius=3pt]
+;
+
+\draw[spath/restore=a];
+\end{tikzpicture}
+\end{example}
+
+
+\item To paths.
+
+\begin{example}
+\begin{tikzpicture}
+\path[draw=orange,ultra thick,spath/save=a] (3,2) -- ++(1,1) to[out=90,in=-90] ++(3,0);
+
+\draw (0,0) -- +(1,1) to[spath/to={a}] node[pos=.6,auto] {node} ++(2,-1) -- +(3,1);
+\end{tikzpicture}
+\end{example}
+
+\item Node placement.
+
+\begin{example}
+\begin{tikzpicture}
+\path[spath/save=curve] (0,0) to[out=0,in=180] +(1,1);
+
+\draw (0,0) -- (2,0) [spath/append=curve] node[pos=.5,auto,sloped] {node} -- +(2,0);
+
+\end{tikzpicture}
+\end{example}
+
 \item Shortening.
 
 \begin{example}

Modified: trunk/Master/texmf-dist/doc/latex/spath3/spath3_code.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/source/latex/spath3/spath3_code.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/spath3/spath3_code.dtx	2021-02-06 22:28:55 UTC (rev 57638)
+++ trunk/Master/texmf-dist/source/latex/spath3/spath3_code.dtx	2021-02-06 22:29:38 UTC (rev 57639)
@@ -35,7 +35,7 @@
 \endpreamble
 \postamble
 
-Copyright (C) 2011-2019 by Andrew Stacey <loopspace at mathforge.org>
+Copyright (C) 2011-2021 by Andrew Stacey <loopspace at mathforge.org>
 
 This work may be distributed and/or modified under the
 conditions of the LaTeX Project Public License (LPPL), either
@@ -47,7 +47,7 @@
 This work is "maintained" (as per LPPL maintenance status) by
 Andrew Stacey.
 
-This work consists of the files  spath3.dtx
+This work consists of the files  spath3_code.dtx
                                  calligraphy_doc.tex
                                  knots_doc.tex
                                  spath3.tex
@@ -143,7 +143,7 @@
 %</driver>
 % \fi
 %
-% \CheckSum{6848}
+% \CheckSum{8404}
 %
 % \CharacterTable
 %  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
@@ -167,9 +167,15 @@
 % \changes{1.2}{2019/02/12}{More fixes due to changes in LaTeX3}
 % \changes{1.4}{2020/12/18}{A fair amount of code reimplementation and reorganisation, together with defining TikZ keys to make functions available for use.}
 % \changes{2.0}{2021/01/19}{Refactored the code to remove the OO approach and make it functional, introduced the spath3 TikZ library to provide a user interface.}
+% \changes{2.2}{2021/02/05}{Bugfixes and improvements, mainly with regard to the intersection and splitting routines.}
 %
 % \DoNotIndex{\newcommand,\newenvironment}
 %
+% \pdfstringdefDisableCommands{%
+%  \def\\{}%
+%  \def\url#1{<#1>}%
+% }
+%
 % \providecommand*{\url}{\texttt}
 % \GetFileInfo{spath3.sty}
 % \title{The \textsf{spath3} package: code}
@@ -250,12 +256,13 @@
 \NeedsTeXFormat{LaTeX2e}
 \RequirePackage{expl3}
 \RequirePackage{pgf}
-\ProvidesExplPackage {spath3} {2021/01/19} {2.0} {Functions for
+\ProvidesExplPackage {spath3} {2021/02/05} {2.2} {Functions for
 manipulating PGF soft paths}
 \RequirePackage{xparse}
 %    \end{macrocode}
 %
 % Utilities copied from \url{https://github.com/loopspace/LaTeX3-Utilities} for adding something in braces to a token list.
+% I find I use this quite a lot in my packages.
 %    \begin{macrocode}
 \cs_new_protected:Nn \@@_tl_put_right_braced:Nn
 {
@@ -281,33 +288,77 @@
 \cs_generate_variant:Nn \@@_tl_gput_left_braced:Nn { NV, cV, cv, Nx, cx }
 %    \end{macrocode}
 %
-% We need a slew of temporary variables.
+%
+% I had to think a bit about how to get \TeX\ to work the way I wanted.
+% I'm really defining \emph{functions} but \TeX\ doesn't really have that concept, even with all the amazing \LaTeX3 stuff.
+% The main issue I had was with scoping and return values.
+% By default, \TeX\ functions aren't scoped -- they work on the same level as the calling functions.
+% To protect the internals from being overwritten, each core function works inside a group.
+% But then I have to work to get the answer out of it.
+% So each of my core functions finishes by storing its return value in an appropriate \Verb+output+ variable.
+% The core functions are then wrapped in a more user friendly interface that will take that output and assign it to a variable.
+% This also means that I can deal with local and global versions without duplicating code.
+%
 %    \begin{macrocode}
+\tl_new:N \g_@@_output_tl
+\int_new:N \g_@@_output_int
+\seq_new:N \g_@@_output_seq
+\bool_new:N \g_@@_output_bool
+%    \end{macrocode}
+%
+% To avoid creating vast numbers of variables, we provide ourselves with a few that we reuse frequently.
+% For that reason, most of them don't have very exciting names.
+%
+% These are general purpose variables.
+%    \begin{macrocode}
 \tl_new:N \l_@@_tmpa_tl
 \tl_new:N \l_@@_tmpb_tl
 \tl_new:N \l_@@_tmpc_tl
 \tl_new:N \l_@@_tmpd_tl
 \tl_new:N \l_@@_tmpe_tl
+\tl_new:N \l_@@_tmpf_tl
+\tl_new:N \l_@@_tmpg_tl
+\tl_new:N \l_@@_tmph_tl
+\tl_new:N \l_@@_tmpi_tl
 
 \seq_new:N \l_@@_tmpa_seq
 \seq_new:N \l_@@_tmpb_seq
+\seq_new:N \l_@@_tmpc_seq
 
-\tl_new:N \g_@@_output_tl
-\int_new:N \g_@@_output_int
-\seq_new:N \g_@@_output_seq
-
 \dim_new:N \l_@@_tmpa_dim
 \dim_new:N \l_@@_tmpb_dim
-\dim_new:N \l_@@_move_x_dim
-\dim_new:N \l_@@_move_y_dim
+
 \fp_new:N \l_@@_tmpa_fp
 \fp_new:N \l_@@_tmpb_fp
+\fp_new:N \l_@@_tmpc_fp
+
 \int_new:N \l_@@_tmpa_int
+\int_new:N \l_@@_tmpb_int
 
-\bool_new:N \g_@@_output_bool
+\bool_new:N \l_@@_tmpa_bool
+%    \end{macrocode}
+%
+% Whenever I need more than two \Verb+dim+ variables it is because I need to remember the position of a move.
+%
+%    \begin{macrocode}
+\dim_new:N \l_@@_move_x_dim
+\dim_new:N \l_@@_move_y_dim
+%    \end{macrocode}
+%
+% Closed paths often need special handling.
+% When it's needed, this will say whether the path is closed or not.
+%
+%    \begin{macrocode}
 \bool_new:N \l_@@_closed_bool
 %    \end{macrocode}
 %
+% The intersection routine can't happen inside a group so we need two token lists to hold the paths that we'll intersect.
+%
+%    \begin{macrocode}
+\tl_new:N \l_@@_intersecta_tl
+\tl_new:N \l_@@_intersectb_tl
+%    \end{macrocode}
+%
 % We need to be able to compare against the macros that can occur in  a soft path so these token lists contain them.
 % These are global constants so that they can be used in other packages.
 %    \begin{macrocode}
@@ -319,7 +370,6 @@
 \tl_const:Nn \c_spath_closepath_tl {\pgfsyssoftpath at closepathtoken}
 %    \end{macrocode}
 %
-%
 % We will want to be able to use anonymous spaths internally, so we create a global counter that we can use to refer to them.
 %    \begin{macrocode}
 \int_new:N \g_@@_anon_int
@@ -326,21 +376,10 @@
 \int_gzero:N \g_@@_anon_int
 %    \end{macrocode}
 %
-% Groups and iterations don't mix well and I haven't got a good scheme for protecting local calculations when iterating, so we do our best with iteration-specific variables.
-%    \begin{macrocode}
-\tl_new:N \l_@@_itera_tl
-\tl_new:N \l_@@_iterb_tl
-\tl_new:N \l_@@_iterc_tl
-\tl_new:N \l_@@_iterd_tl
-\tl_new:N \l_@@_iterp_tl
-\dim_new:N \l_@@_itera_dim
-\dim_new:N \l_@@_iterb_dim
-\seq_new:N \l_@@_iter_seq
-%    \end{macrocode}
-%
 % And some error messages
 %    \begin{macrocode}
-\msg_new:nnn { spath3 } { unknown path construction } { The~ path~ construction~ element~ #1~ is~ not~ currently~ supported.}
+\msg_new:nnn { spath3 } { unknown path construction }
+{ The~ path~ construction~ element~ #1~ is~ not~ currently~ supported.}
 %    \end{macrocode}
 %
 %
@@ -351,7 +390,7 @@
 % The macro to store it in is the first argument.
 % These functions occur in two versions, the one with the \texttt{g} makes the assignment global.
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_segments_to_seq:Nn,
 % \spath_segments_gto_seq:Nn
 %}
@@ -360,35 +399,35 @@
 \cs_new_protected_nopar:Npn \@@_segments_to_seq:n #1
 {
   \group_begin:
-  \tl_set:Nn \l_@@_itera_tl {#1}
-  \tl_clear:N \l_@@_iterb_tl
-  \seq_clear:N \l_@@_iter_seq
-  \dim_zero:N \l_@@_itera_dim
-  \dim_zero:N \l_@@_iterb_dim
+  \tl_set:Nn \l_@@_tmpa_tl {#1}
+  \tl_clear:N \l_@@_tmpb_tl
+  \seq_clear:N \l_@@_tmpa_seq
+  \dim_zero:N \l_@@_tmpa_dim
+  \dim_zero:N \l_@@_tmpb_dim
 
   \bool_until_do:nn {
-    \tl_if_empty_p:N \l_@@_itera_tl
+    \tl_if_empty_p:N \l_@@_tmpa_tl
   }
   {
-    \tl_set:Nx \l_@@_iterc_tl {\tl_head:N \l_@@_itera_tl}
-    \tl_set:Nx \l_@@_itera_tl {\tl_tail:N \l_@@_itera_tl}
-    \tl_case:NnF \l_@@_iterc_tl
+    \tl_set:Nx \l_@@_tmpc_tl {\tl_head:N \l_@@_tmpa_tl}
+    \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
+    \tl_case:NnF \l_@@_tmpc_tl
     {
       \c_spath_moveto_tl
       {
-        \tl_set_eq:NN \l_@@_iterb_tl \c_spath_moveto_tl
-        \tl_put_right:Nx \l_@@_iterb_tl {{\tl_head:N \l_@@_itera_tl}}
-        \dim_set:Nn \l_@@_itera_dim {\tl_head:N \l_@@_itera_tl}
-        \tl_set:Nx \l_@@_itera_tl {\tl_tail:N \l_@@_itera_tl}
+        \tl_set_eq:NN \l_@@_tmpb_tl \c_spath_moveto_tl
+        \tl_put_right:Nx \l_@@_tmpb_tl {{\tl_head:N \l_@@_tmpa_tl}}
+        \dim_set:Nn \l_@@_tmpa_dim {\tl_head:N \l_@@_tmpa_tl}
+        \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
 
-        \tl_put_right:Nx \l_@@_iterb_tl {{\tl_head:N \l_@@_itera_tl}}
-        \dim_set:Nn \l_@@_iterb_dim {\tl_head:N \l_@@_itera_tl}
-        \tl_set:Nx \l_@@_itera_tl {\tl_tail:N \l_@@_itera_tl}
+        \tl_put_right:Nx \l_@@_tmpb_tl {{\tl_head:N \l_@@_tmpa_tl}}
+        \dim_set:Nn \l_@@_tmpb_dim {\tl_head:N \l_@@_tmpa_tl}
+        \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
 
-        \tl_set:Nx \l_@@_iterd_tl {\tl_head:N \l_@@_itera_tl}
-        \tl_if_eq:NNF \l_@@_iterd_tl \c_spath_moveto_tl
+        \tl_set:Nx \l_@@_tmpd_tl {\tl_head:N \l_@@_tmpa_tl}
+        \tl_if_eq:NNF \l_@@_tmpd_tl \c_spath_moveto_tl
         {
-          \tl_clear:N \l_@@_iterb_tl
+          \tl_clear:N \l_@@_tmpb_tl
         }
 
       }
@@ -395,70 +434,70 @@
 
       \c_spath_lineto_tl
       {
-        \tl_set_eq:NN \l_@@_iterb_tl \c_spath_moveto_tl
-        \tl_put_right:Nx \l_@@_iterb_tl
+        \tl_set_eq:NN \l_@@_tmpb_tl \c_spath_moveto_tl
+        \tl_put_right:Nx \l_@@_tmpb_tl
         {
-          {\dim_use:N \l_@@_itera_dim}
-          {\dim_use:N \l_@@_iterb_dim}
+          {\dim_use:N \l_@@_tmpa_dim}
+          {\dim_use:N \l_@@_tmpb_dim}
         }
-        \tl_put_right:NV \l_@@_iterb_tl \c_spath_lineto_tl
+        \tl_put_right:NV \l_@@_tmpb_tl \c_spath_lineto_tl
 
-        \tl_put_right:Nx \l_@@_iterb_tl {{\tl_head:N \l_@@_itera_tl}}
-        \dim_set:Nn \l_@@_itera_dim {\tl_head:N \l_@@_itera_tl}
-        \tl_set:Nx \l_@@_itera_tl {\tl_tail:N \l_@@_itera_tl}
+        \tl_put_right:Nx \l_@@_tmpb_tl {{\tl_head:N \l_@@_tmpa_tl}}
+        \dim_set:Nn \l_@@_tmpa_dim {\tl_head:N \l_@@_tmpa_tl}
+        \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
 
-        \tl_put_right:Nx \l_@@_iterb_tl {{\tl_head:N \l_@@_itera_tl}}
-        \dim_set:Nn \l_@@_iterb_dim {\tl_head:N \l_@@_itera_tl}
-        \tl_set:Nx \l_@@_itera_tl {\tl_tail:N \l_@@_itera_tl}
+        \tl_put_right:Nx \l_@@_tmpb_tl {{\tl_head:N \l_@@_tmpa_tl}}
+        \dim_set:Nn \l_@@_tmpb_dim {\tl_head:N \l_@@_tmpa_tl}
+        \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
 
       }
 
       \c_spath_curvetoa_tl
       {
-        \tl_set_eq:NN \l_@@_iterb_tl \c_spath_moveto_tl
-        \tl_put_right:Nx \l_@@_iterb_tl
+        \tl_set_eq:NN \l_@@_tmpb_tl \c_spath_moveto_tl
+        \tl_put_right:Nx \l_@@_tmpb_tl
         {
-          {\dim_use:N \l_@@_itera_dim}
-          {\dim_use:N \l_@@_iterb_dim}
+          {\dim_use:N \l_@@_tmpa_dim}
+          {\dim_use:N \l_@@_tmpb_dim}
         }
-        \tl_put_right:NV \l_@@_iterb_tl \c_spath_curvetoa_tl
+        \tl_put_right:NV \l_@@_tmpb_tl \c_spath_curvetoa_tl
 
         \prg_replicate:nn {2} {
-          \tl_put_right:Nx \l_@@_iterb_tl {{\tl_head:N \l_@@_itera_tl}}
-          \tl_set:Nx \l_@@_itera_tl {\tl_tail:N \l_@@_itera_tl}
-          \tl_put_right:Nx \l_@@_iterb_tl {{\tl_head:N               \l_@@_itera_tl}}
-          \tl_set:Nx \l_@@_itera_tl {\tl_tail:N \l_@@_itera_tl}
-          \tl_put_right:Nx \l_@@_iterb_tl {\tl_head:N             \l_@@_itera_tl}
-          \tl_set:Nx \l_@@_itera_tl {\tl_tail:N \l_@@_itera_tl}
+          \tl_put_right:Nx \l_@@_tmpb_tl {{\tl_head:N \l_@@_tmpa_tl}}
+          \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
+          \tl_put_right:Nx \l_@@_tmpb_tl {{\tl_head:N \l_@@_tmpa_tl}}
+          \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
+          \tl_put_right:Nx \l_@@_tmpb_tl {\tl_head:N \l_@@_tmpa_tl}
+          \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
         }
 
-        \tl_put_right:Nx \l_@@_iterb_tl {{\tl_head:N \l_@@_itera_tl}}
-        \dim_set:Nn \l_@@_itera_dim {\tl_head:N \l_@@_itera_tl}
-        \tl_set:Nx \l_@@_itera_tl {\tl_tail:N \l_@@_itera_tl}
+        \tl_put_right:Nx \l_@@_tmpb_tl {{\tl_head:N \l_@@_tmpa_tl}}
+        \dim_set:Nn \l_@@_tmpa_dim {\tl_head:N \l_@@_tmpa_tl}
+        \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
 
-        \tl_put_right:Nx \l_@@_iterb_tl {{\tl_head:N \l_@@_itera_tl}}
-        \dim_set:Nn \l_@@_iterb_dim {\tl_head:N \l_@@_itera_tl}
-        \tl_set:Nx \l_@@_itera_tl {\tl_tail:N \l_@@_itera_tl}
+        \tl_put_right:Nx \l_@@_tmpb_tl {{\tl_head:N \l_@@_tmpa_tl}}
+        \dim_set:Nn \l_@@_tmpb_dim {\tl_head:N \l_@@_tmpa_tl}
+        \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
 
       }
 
       \c_spath_closepath_tl
       {
-        \tl_set_eq:NN \l_@@_iterb_tl \c_spath_moveto_tl
-        \tl_put_right:Nx \l_@@_iterb_tl
+        \tl_set_eq:NN \l_@@_tmpb_tl \c_spath_moveto_tl
+        \tl_put_right:Nx \l_@@_tmpb_tl
         {
-          {\dim_use:N \l_@@_itera_dim}
-          {\dim_use:N \l_@@_iterb_dim}
+          {\dim_use:N \l_@@_tmpa_dim}
+          {\dim_use:N \l_@@_tmpb_dim}
         }
-        \tl_put_right:NV \l_@@_iterb_tl \c_spath_lineto_tl
+        \tl_put_right:NV \l_@@_tmpb_tl \c_spath_lineto_tl
 
-        \tl_put_right:Nx \l_@@_iterb_tl {{\tl_head:N \l_@@_itera_tl}}
-        \dim_set:Nn \l_@@_itera_dim {\tl_head:N \l_@@_itera_tl}
-        \tl_set:Nx \l_@@_itera_tl {\tl_tail:N \l_@@_itera_tl}
+        \tl_put_right:Nx \l_@@_tmpb_tl {{\tl_head:N \l_@@_tmpa_tl}}
+        \dim_set:Nn \l_@@_tmpa_dim {\tl_head:N \l_@@_tmpa_tl}
+        \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
 
-        \tl_put_right:Nx \l_@@_iterb_tl {{\tl_head:N \l_@@_itera_tl}}
-        \dim_set:Nn \l_@@_iterb_dim {\tl_head:N \l_@@_itera_tl}
-        \tl_set:Nx \l_@@_itera_tl {\tl_tail:N \l_@@_itera_tl}
+        \tl_put_right:Nx \l_@@_tmpb_tl {{\tl_head:N \l_@@_tmpa_tl}}
+        \dim_set:Nn \l_@@_tmpb_dim {\tl_head:N \l_@@_tmpa_tl}
+        \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
 
       }
       
@@ -465,26 +504,26 @@
     }    
     {
 
-      \tl_set_eq:NN \l_@@_iterb_tl \l_@@_iterc_tl
-      \tl_put_right:Nx \l_@@_iterb_tl {{\tl_head:N \l_@@_itera_tl}}
-      \dim_set:Nn \l_@@_itera_dim {\tl_head:N \l_@@_itera_tl}
-      \tl_set:Nx \l_@@_itera_tl {\tl_tail:N \l_@@_itera_tl}
+      \tl_set_eq:NN \l_@@_tmpb_tl \l_@@_tmpc_tl
+      \tl_put_right:Nx \l_@@_tmpb_tl {{\tl_head:N \l_@@_tmpa_tl}}
+      \dim_set:Nn \l_@@_tmpa_dim {\tl_head:N \l_@@_tmpa_tl}
+      \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
 
-      \tl_put_right:Nx \l_@@_iterb_tl {{\tl_head:N \l_@@_itera_tl}}
-      \dim_set:Nn \l_@@_iterb_dim {\tl_head:N \l_@@_itera_tl}
-      \tl_set:Nx \l_@@_itera_tl {\tl_tail:N \l_@@_itera_tl}
+      \tl_put_right:Nx \l_@@_tmpb_tl {{\tl_head:N \l_@@_tmpa_tl}}
+      \dim_set:Nn \l_@@_tmpb_dim {\tl_head:N \l_@@_tmpa_tl}
+      \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
       
     }
 
-    \tl_if_empty:NF \l_@@_iterb_tl
+    \tl_if_empty:NF \l_@@_tmpb_tl
     {
-      \seq_put_right:NV \l_@@_iter_seq \l_@@_iterb_tl
+      \seq_put_right:NV \l_@@_tmpa_seq \l_@@_tmpb_tl
     }
-    \tl_clear:N \l_@@_iterb_tl
+    \tl_clear:N \l_@@_tmpb_tl
   }
 
   \seq_gclear:N \g_@@_output_seq
-  \seq_gset_eq:NN \g_@@_output_seq \l_@@_iter_seq
+  \seq_gset_eq:NN \g_@@_output_seq \l_@@_tmpa_seq
   \group_end:
 }
 \cs_new_protected_nopar:Npn \spath_segments_to_seq:Nn #1#2
@@ -506,7 +545,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_components_to_seq:Nn,
 % \spath_components_gto_seq:Nn,
 % \spath_components_to_clist:Nn,
@@ -517,33 +556,33 @@
 \cs_new_protected_nopar:Npn \@@_components_to_seq:n #1
 {
   \group_begin:
-  \tl_set:Nn \l_@@_itera_tl {#1}
-  \seq_clear:N \l_@@_iter_seq
-  \tl_set:Nx \l_@@_itera_tl {\tl_tail:N \l_@@_itera_tl}
-  \tl_put_right:NV \l_@@_itera_tl \c_spath_moveto_tl
-  \tl_set_eq:NN \l_@@_iterb_tl \c_spath_moveto_tl
+  \tl_set:Nn \l_@@_tmpa_tl {#1}
+  \seq_clear:N \l_@@_tmpa_seq
+  \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
+  \tl_put_right:NV \l_@@_tmpa_tl \c_spath_moveto_tl
+  \tl_set_eq:NN \l_@@_tmpb_tl \c_spath_moveto_tl
   \bool_do_until:nn {
-    \tl_if_empty_p:N \l_@@_itera_tl
+    \tl_if_empty_p:N \l_@@_tmpa_tl
   }
   {
-    \tl_set:Nx \l_@@_iterc_tl {\tl_head:N \l_@@_itera_tl}
-    \tl_if_eq:NNT \l_@@_iterc_tl \c_spath_moveto_tl
+    \tl_set:Nx \l_@@_tmpc_tl {\tl_head:N \l_@@_tmpa_tl}
+    \tl_if_eq:NNT \l_@@_tmpc_tl \c_spath_moveto_tl
     {
-      \seq_put_right:NV \l_@@_iter_seq \l_@@_iterb_tl
-      \tl_clear:N \l_@@_iterb_tl
+      \seq_put_right:NV \l_@@_tmpa_seq \l_@@_tmpb_tl
+      \tl_clear:N \l_@@_tmpb_tl
     }
-    \tl_if_single:NTF \l_@@_iterc_tl
+    \tl_if_single:NTF \l_@@_tmpc_tl
     {
-      \tl_put_right:NV \l_@@_iterb_tl \l_@@_iterc_tl
+      \tl_put_right:NV \l_@@_tmpb_tl \l_@@_tmpc_tl
     }
     {
-      \tl_put_right:Nx \l_@@_iterb_tl {{\l_@@_iterc_tl}}
+      \tl_put_right:Nx \l_@@_tmpb_tl {{\l_@@_tmpc_tl}}
     }
-    \tl_set:Nx \l_@@_itera_tl {\tl_tail:N \l_@@_itera_tl}
+    \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
   }
 
   \seq_gclear:N \g_@@_output_seq
-  \seq_gset_eq:NN \g_@@_output_seq \l_@@_iter_seq
+  \seq_gset_eq:NN \g_@@_output_seq \l_@@_tmpa_seq
   \group_end:
 }
 \cs_new_protected_nopar:Npn \spath_components_to_seq:Nn #1#2
@@ -582,7 +621,7 @@
 % \end{macro}
 %
 %
-% \begin{macro}{\spath_length:n}
+% \begin{macro}[internal]{\spath_length:n}
 % Counts the number of triples in the path.
 %    \begin{macrocode}
 \cs_new_protected_nopar:Npn \spath_length:n #1
@@ -593,7 +632,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_reallength:Nn,
 % \spath_greallength:Nn
 % }
@@ -604,8 +643,8 @@
   \group_begin:
   \int_set:Nn \l_@@_tmpa_int {0}
   \tl_map_inline:nn {#1} {
-    \tl_set:Nn \l_@@_tmpc_tl {##1}
-    \tl_case:NnT \l_@@_tmpc_tl
+    \tl_set:Nn \l_@@_tmpa_tl {##1}
+    \tl_case:NnT \l_@@_tmpa_tl
     {
       \c_spath_lineto_tl {}
       \c_spath_curveto_tl {}
@@ -636,7 +675,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_numberofcomponents:Nn,
 % \spath_gnumberofcomponents:Nn
 % }
@@ -667,7 +706,7 @@
   \int_set_eq:NN #1 \g_@@_output_int
   \int_gzero:N \g_@@_output_int
 }
-\cs_generate_variant:Nn \spath_numberofcomponents:Nn {NV, cn, cV}
+\cs_generate_variant:Nn \spath_numberofcomponents:Nn {NV, cn, cV, Nv}
 \cs_new_protected_nopar:Npn \spath_gnumberofcomponents:Nn #1#2
 {
   \@@_numberofcomponents:n {#2}
@@ -674,11 +713,11 @@
   \int_gset_eq:NN #1 \g_@@_output_int
   \int_gzero:N \g_@@_output_int
 }
-\cs_generate_variant:Nn \spath_gnumberofcomponents:Nn {NV, cn, cV}
+\cs_generate_variant:Nn \spath_gnumberofcomponents:Nn {NV, cn, cV, Nv}
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_initialpoint:Nn,
 % \spath_ginitialpoint:Nn
 % }
@@ -687,13 +726,13 @@
 \cs_new_protected_nopar:Npn \@@_initialpoint:n #1
 {
   \group_begin:
-  \tl_clear:N \l_@@_tmpb_tl
-  \tl_set:Nx \l_@@_tmpb_tl
+  \tl_clear:N \l_@@_tmpa_tl
+  \tl_set:Nx \l_@@_tmpa_tl
   {
     { \tl_item:nn {#1} {2} }
     { \tl_item:nn {#1} {3} }
   }
-  \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpb_tl
+  \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpa_tl
   \group_end:
 }
 \cs_new_protected_nopar:Npn \spath_initialpoint:Nn #1#2
@@ -713,7 +752,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_finalpoint:Nn,
 % \spath_gfinalpoint:Nn,
 % }
@@ -750,7 +789,60 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
+% \spath_finalmovepoint:Nn,
+% \spath_gfinalmovepoint:Nn
+% }
+% Get the last move on the path.
+%    \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_finalmovepoint:n #1
+{
+  \group_begin:
+  \tl_set:Nn \l_@@_tmpc_tl { {0pt} {0pt} }
+  \tl_set:Nn \l_@@_tmpa_tl {#1}
+  \bool_do_until:nn
+  {
+    \tl_if_empty_p:N \l_@@_tmpa_tl
+  }
+  {
+    \tl_set:Nx \l_@@_tmpb_tl {\tl_head:N \l_@@_tmpa_tl}
+    \tl_case:Nn \l_@@_tmpb_tl
+    {
+      \c_spath_moveto_tl
+      {
+        \tl_set:Nx \l_@@_tmpc_tl
+        {
+          { \tl_item:Nn \l_@@_tmpa_tl {2} }
+          { \tl_item:Nn \l_@@_tmpa_tl {3} }
+        }
+      }
+    }
+    \prg_replicate:nn {3}
+    {
+      \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
+    }
+  }
+  \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpc_tl
+  \group_end:
+}
+\cs_new_protected_nopar:Npn \spath_finalmovepoint:Nn #1#2
+{
+  \@@_finalmovepoint:n {#2}
+  \tl_set_eq:NN #1 \g_@@_output_tl
+  \tl_gclear:N \g_@@_output_tl
+}
+\cs_generate_variant:Nn \spath_finalmovepoint:Nn {NV, cn, cV}
+\cs_new_protected_nopar:Npn \spath_gfinalmovepoint:Nn #1#2
+{
+  \@@_finalmovepoint:n {#2}
+  \tl_gset_eq:NN #1 \g_@@_output_tl
+  \tl_gclear:N \g_@@_output_tl
+}
+\cs_generate_variant:Nn \spath_gfinalmovepoint:Nn {NV, cn, cV}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{
 % \spath_reverse:Nn,
 % \spath_greverse:Nn
 % }
@@ -836,7 +928,10 @@
         \bool_set_true:N \l_@@_closed_bool
       }
       {
-        \msg_warning:nnx { spath3 } { unknown path construction } {\l_@@_tmpc_tl }
+        \msg_warning:nnx
+        { spath3 }
+        { unknown path construction }
+        {\l_@@_tmpc_tl }
       }
 
       \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
@@ -891,7 +986,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_initialaction:Nn,
 % \spath_ginitialaction:Nn,
 % }
@@ -931,7 +1026,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_finalaction:Nn,
 % \spath_gfinalaction:Nn
 % }
@@ -977,7 +1072,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_minbb:Nn,
 % \spath_gminbb:Nn
 % }
@@ -997,9 +1092,11 @@
   }
   {
     \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
-    \dim_set:Nn \l_@@_tmpa_dim {\dim_min:nn {\tl_head:N \l_@@_tmpa_tl} {\l_@@_tmpa_dim}}
+    \dim_set:Nn \l_@@_tmpa_dim
+    {\dim_min:nn {\tl_head:N \l_@@_tmpa_tl} {\l_@@_tmpa_dim}}
     \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
-    \dim_set:Nn \l_@@_tmpb_dim {\dim_min:nn {\tl_head:N \l_@@_tmpa_tl} {\l_@@_tmpb_dim}}
+    \dim_set:Nn \l_@@_tmpb_dim
+    {\dim_min:nn {\tl_head:N \l_@@_tmpa_tl} {\l_@@_tmpb_dim}}
     \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
   }
   \tl_clear:N \l_@@_tmpb_tl
@@ -1028,7 +1125,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_maxbb:Nn,
 % \spath_gmaxbb:Nn,
 % }
@@ -1048,9 +1145,11 @@
   }
   {
     \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
-    \dim_set:Nn \l_@@_tmpa_dim {\dim_max:nn {\tl_head:N \l_@@_tmpa_tl} {\l_@@_tmpa_dim}}
+    \dim_set:Nn \l_@@_tmpa_dim
+    {\dim_max:nn {\tl_head:N \l_@@_tmpa_tl} {\l_@@_tmpa_dim}}
     \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
-    \dim_set:Nn \l_@@_tmpb_dim {\dim_max:nn {\tl_head:N \l_@@_tmpa_tl} {\l_@@_tmpb_dim}}
+    \dim_set:Nn \l_@@_tmpb_dim
+    {\dim_max:nn {\tl_head:N \l_@@_tmpa_tl} {\l_@@_tmpb_dim}}
     \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
   }
   \tl_clear:N \l_@@_tmpb_tl
@@ -1079,7 +1178,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_save_to_aux:Nn,
 % \spath_save_to_aux:N
 % }
@@ -1124,13 +1223,13 @@
 % There is always a variant in which the path is specified by a macro and restored back in that same macro. 
 %
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_translate:Nnnn,
 % \spath_translate:Nnn,
 % \spath_gtranslate:Nnnn,
 % \spath_gtranslate:Nnn
 % }
-% Translates a path.
+% Translates a path by an amount.
 %    \begin{macrocode}
 \cs_new_protected_nopar:Npn \@@_translate:nnn #1#2#3
 {
@@ -1159,6 +1258,7 @@
   \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpb_tl
   \group_end:
 }
+\cs_generate_variant:Nn \@@_translate:nnn {nVV}
 \cs_new_protected_nopar:Npn \spath_translate:Nnnn #1#2#3#4
 {
   \@@_translate:nnn {#2}{#3}{#4}
@@ -1200,8 +1300,80 @@
 %    \end{macrocode}
 % \end{macro}
 %
+% 
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
+% \spath_translate_to:Nnnn,
+% \spath_translate_to:Nnn,
+% \spath_gtranslate_to:Nnnn,
+% \spath_gtranslate_to:Nnn
+% }
+% Translates a path so that it starts at a point.
+%    \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_translate_to:nnn #1#2#3
+{
+  \group_begin:
+  \spath_initialpoint:Nn \l_@@_tmpa_tl {#1}
+
+  \dim_set:Nn \l_@@_tmpa_dim
+  {
+    #2
+    -
+    \tl_item:Nn \l_@@_tmpa_tl {1}
+  }
+  \dim_set:Nn \l_@@_tmpb_dim
+  {
+    #3
+    -
+    \tl_item:Nn \l_@@_tmpa_tl {2}
+  }
+
+  \@@_translate:nVV {#1} \l_@@_tmpa_dim \l_@@_tmpb_dim
+  \group_end:
+}
+\cs_new_protected_nopar:Npn \spath_translate_to:Nnnn #1#2#3#4
+{
+  \@@_translate_to:nnn {#2}{#3}{#4}
+  \tl_set_eq:NN #1 \g_@@_output_tl
+  \tl_gclear:N \g_@@_output_tl
+}
+\cs_generate_variant:Nn \spath_translate_to:Nnnn {NVxx, NVVV, NVnn}
+\cs_new_protected_nopar:Npn \spath_translate_to:Nnn #1#2#3
+{
+  \spath_translate_to:NVnn #1#1{#2}{#3}
+}
+\cs_generate_variant:Nn \spath_translate_to:Nnn {NVV, cnn, cVV}
+\cs_new_protected_nopar:Npn \spath_gtranslate_to:Nnnn #1#2#3#4
+{
+  \@@_translate_to:nnn {#2}{#3}{#4}
+  \tl_gset_eq:NN #1 \g_@@_output_tl
+  \tl_gclear:N \g_@@_output_tl
+}
+\cs_generate_variant:Nn \spath_gtranslate_to:Nnnn {NVxx, NVVV, NVnn}
+\cs_new_protected_nopar:Npn \spath_gtranslate_to:Nnn #1#2#3
+{
+  \spath_gtranslate_to:NVnn #1#1{#2}{#3}
+}
+\cs_generate_variant:Nn \spath_gtranslate_to:Nnn {NVV, cnn, cVV}
+%    \end{macrocode}
+%
+% This variant allows for passing the coordinates as a single braced group as it strips off the outer braces of the second argument.
+%    \begin{macrocode}
+\cs_new_protected_nopar:Npn \spath_translate_to:Nn #1#2
+{
+  \spath_translate_to:Nnn #1 #2
+}
+\cs_generate_variant:Nn \spath_translate_to:Nn {NV}
+\cs_new_protected_nopar:Npn \spath_gtranslate_to:Nn #1#2
+{
+  \spath_gtranslate_to:Nnn #1 #2
+}
+\cs_generate_variant:Nn \spath_gtranslate_to:Nn {NV}
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}[internal]{
 % \spath_scale:Nnnn,
 % \spath_scale:Nnn,
 % \spath_gscale:Nnnn,
@@ -1279,7 +1451,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_transform:Nnnnnnnn,
 % \spath_transform:Nnnnnnn,
 % \spath_gtransform:Nnnnnnnn,
@@ -1304,8 +1476,10 @@
     \tl_set:Nx \l_@@_tmpd_tl {\tl_head:N \l_@@_tmpa_tl}
     \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
 
-    \fp_set:Nn \l_@@_tmpa_fp {\l_@@_tmpc_tl * #2 + \l_@@_tmpd_tl * #4 + #6}
-    \fp_set:Nn \l_@@_tmpb_fp {\l_@@_tmpc_tl * #3 + \l_@@_tmpd_tl * #5 + #7}
+    \fp_set:Nn \l_@@_tmpa_fp
+    {\l_@@_tmpc_tl * #2 + \l_@@_tmpd_tl * #4 + #6}
+    \fp_set:Nn \l_@@_tmpb_fp
+    {\l_@@_tmpc_tl * #3 + \l_@@_tmpd_tl * #5 + #7}
     \tl_put_right:Nx \l_@@_tmpb_tl
     {
       {\fp_to_dim:N \l_@@_tmpa_fp}
@@ -1322,7 +1496,8 @@
   \tl_set_eq:NN #1 \g_@@_output_tl
   \tl_gclear:N \g_@@_output_tl
 }
-\cs_generate_variant:Nn \spath_transform:Nnnnnnnn {NVnnnnnn, Nnxxxxxx, cnnnnnnn}
+\cs_generate_variant:Nn \spath_transform:Nnnnnnnn
+{NVnnnnnn, Nnxxxxxx, cnnnnnnn}
 \cs_new_protected_nopar:Npn \spath_transform:Nnnnnnn #1#2#3#4#5#6#7
 {
   \spath_transform:NVnnnnnn #1#1{#2}{#3}{#4}{#5}{#6}{#7}
@@ -1364,7 +1539,305 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
+%  \spath_span:Nnnn,
+%  \spath_span:Nnn,
+%  \spath_gspan:Nnnn,
+%  \spath_gspan:Nnn,
+%  \spath_normalise:Nn,
+%  \spath_normalise:N,
+%  \spath_gnormalise:Nn,
+%  \spath_gnormalise:N
+% }
+% The \Verb+span+ functions transform a path to start and end at specified points.
+% The \Verb+normalise+ functions transform it to start at the origin and end at \((1\mathrm{pt},0\mathrm{pt})\).
+%
+% If the path starts and ends at the same point then it is translated to the specified point (or origin) but not otherwise changed.
+%    \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_span:nnn #1#2#3
+{
+  \group_begin:
+  \spath_initialpoint:Nn \l_@@_tmpa_tl {#1}
+  \spath_finalpoint:Nn \l_@@_tmpb_tl {#1}
+  
+  \fp_set:Nn \l_@@_tmpa_fp
+  {
+    (\tl_item:Nn \l_@@_tmpb_tl {1}) -
+    (\tl_item:Nn \l_@@_tmpa_tl {1})
+  }
+  \fp_set:Nn \l_@@_tmpb_fp
+  {
+    (\tl_item:Nn \l_@@_tmpb_tl {2}) -
+    (\tl_item:Nn \l_@@_tmpa_tl {2})
+  }
+  \fp_set:Nn \l_@@_tmpc_fp
+  {
+    (\l_@@_tmpa_fp) * (\l_@@_tmpa_fp)
+    +
+    (\l_@@_tmpb_fp * \l_@@_tmpb_fp)
+  }
+
+  \fp_compare:nTF
+  {
+    \l_@@_tmpc_fp < 0.001
+  }
+  {
+    \spath_translate_to:Nnnn \l_@@_tmpd_tl {#1} #2
+  }
+  {
+    \fp_set:Nn \l_@@_tmpa_fp
+    {
+      (
+      ((\tl_item:nn {#3} {1})
+      -
+      (\tl_item:nn {#2} {1}))
+      *
+      ((\tl_item:Nn \l_@@_tmpb_tl {1})
+      -
+      (\tl_item:Nn \l_@@_tmpa_tl {1}))
+      +
+      ((\tl_item:nn {#3} {2})
+      -
+      (\tl_item:nn {#2} {2}))
+      *
+      ((\tl_item:Nn \l_@@_tmpb_tl {2})
+      -
+      (\tl_item:Nn \l_@@_tmpa_tl {2}))
+      )
+      /
+      \l_@@_tmpc_fp
+    }
+    \fp_set:Nn \l_@@_tmpb_fp
+    {
+      (
+      ((\tl_item:nn {#3} {2})
+      -
+      (\tl_item:nn {#2} {2}))
+      *
+      ((\tl_item:Nn \l_@@_tmpb_tl {1})
+      -
+      (\tl_item:Nn \l_@@_tmpa_tl {1}))
+      -
+      ((\tl_item:nn {#3} {1})
+      -
+      (\tl_item:nn {#2} {1}))
+      *
+      ((\tl_item:Nn \l_@@_tmpb_tl {2})
+      -
+      (\tl_item:Nn \l_@@_tmpa_tl {2}))
+      )
+      /
+      \l_@@_tmpc_fp
+    }
+    
+    \tl_set:Nx \l_@@_tmpc_tl
+    {
+      {
+        \fp_to_decimal:N \l_@@_tmpa_fp
+      }
+      {
+        \fp_to_decimal:N \l_@@_tmpb_fp
+      }
+      {
+        \fp_eval:n { - \l_@@_tmpb_fp }
+      }
+      {
+        \fp_to_decimal:N \l_@@_tmpa_fp
+      }
+      {
+        \fp_to_dim:n
+        {
+          \tl_item:nn {#2} {1}
+          -
+          \l_@@_tmpa_fp * (\tl_item:Nn \l_@@_tmpa_tl {1})
+          +
+          \l_@@_tmpb_fp * (\tl_item:Nn \l_@@_tmpa_tl {2})
+        }
+      }
+      {
+        \fp_to_dim:n
+        {
+          \tl_item:nn {#2} {2}
+          -
+          \l_@@_tmpb_fp * (\tl_item:Nn \l_@@_tmpa_tl {1})
+          -
+          \l_@@_tmpa_fp * (\tl_item:Nn \l_@@_tmpa_tl {2})
+        }
+      }
+    }
+    \spath_transform:NnV \l_@@_tmpd_tl {#1} \l_@@_tmpc_tl
+  }
+  \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpd_tl
+  \group_end:
+}
+\cs_new_protected_nopar:Npn \spath_span:Nnnn #1#2#3#4
+{
+  \@@_span:nnn {#2}{#3}{#4}
+  \tl_set_eq:NN #1 \g_@@_output_tl
+  \tl_gclear:N \g_@@_output_tl
+}
+\cs_generate_variant:Nn \spath_span:Nnnn {NVnn, NVVV, NnVV}
+\cs_new_protected_nopar:Npn \spath_span:Nnn #1#2#3
+{
+  \spath_span:NVnn #1#1{#2}{#3}
+}
+\cs_generate_variant:Nn \spath_span:Nnn {NVV, cnn, cvv, cVV}
+\cs_new_protected_nopar:Npn \spath_gspan:Nnnn #1#2#3#4
+{
+  \@@_span:nnn {#2}{#3}{#4}
+  \tl_gset_eq:NN #1 \g_@@_output_tl
+  \tl_gclear:N \g_@@_output_tl
+}
+\cs_generate_variant:Nn \spath_gspan:Nnnn {NVnn, NVVV}
+\cs_new_protected_nopar:Npn \spath_gspan:Nnn #1#2#3
+{
+  \spath_gspan:NVnn #1#1{#2}{#3}
+}
+\cs_generate_variant:Nn \spath_gspan:Nnn {NVV, cnn, cvv, cVV}
+\cs_new_protected_nopar:Npn \@@_normalise:n #1
+{
+  \@@_span:nnn {#1}{{0pt}{0pt}}{{1pt}{0pt}}
+}
+\cs_new_protected_nopar:Npn \spath_normalise:Nn #1#2
+{
+  \@@_normalise:n {#2}
+  \tl_set_eq:NN #1 \g_@@_output_tl
+  \tl_gclear:N \g_@@_output_tl
+}
+\cs_generate_variant:Nn \spath_normalise:Nn {cn,NV, cV, cv}
+\cs_new_protected_nopar:Npn \spath_normalise:N #1
+{
+  \spath_normalise:NV #1#1
+}
+\cs_generate_variant:Nn \spath_normalise:N {c}
+\cs_new_protected_nopar:Npn \spath_gnormalise:Nn #1#2
+{
+  \@@_normalise:n {#2}
+  \tl_gset_eq:NN #1 \g_@@_output_tl
+  \tl_gclear:N \g_@@_output_tl
+}
+\cs_generate_variant:Nn \spath_gnormalise:Nn {cn,NV, cV, cv}
+\cs_new_protected_nopar:Npn \spath_gnormalise:N #1
+{
+  \spath_gnormalise:NV #1#1
+}
+\cs_generate_variant:Nn \spath_gnormalise:N {c}
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}[internal]{
+% \spath_splice_between:Nnnn,
+% \spath_splice_between:Nnn,
+% \spath_gsplice_between:Nnnn,
+% \spath_gsplice_between:Nnn
+% }
+% This takes three paths and returns a single path in which the middle one is adjusted (and welded) so that it joins the first path to the third.
+%    \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_splice_between:nnn #1#2#3
+{
+  \group_begin:
+  \spath_finalpoint:NV \l_@@_tmpd_tl {#1}
+  \spath_initialpoint:NV \l_@@_tmpe_tl {#3}
+  \spath_span:NnVV \l_@@_tmpb_tl {#2} \l_@@_tmpd_tl \l_@@_tmpe_tl
+  \spath_append_no_move:NnV \l_@@_tmpa_tl {#1} \l_@@_tmpb_tl
+  \spath_append_no_move:Nn \l_@@_tmpa_tl {#3}
+  \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpa_tl
+  \group_end:
+}
+\cs_new_protected_nopar:Npn \spath_splice_between:Nnnn #1#2#3#4
+{
+  \@@_splice_between:nnn {#2}{#3}{#4}
+  \tl_set_eq:NN #1 \g_@@_output_tl
+  \tl_gclear:N \g_@@_output_tl
+}
+\cs_generate_variant:Nn \spath_splice_between:Nnnn {NVnn, NVVV}
+\cs_new_protected_nopar:Npn \spath_splice_between:Nnn #1#2#3
+{
+  \spath_splice_between:NVnn #1#1{#2}{#3}
+}
+\cs_generate_variant:Nn \spath_splice_between:Nnn {NVV, cnn, cvv, Nvn}
+\cs_new_protected_nopar:Npn \spath_gsplice_between:Nnnn #1#2#3#4
+{
+  \@@_splice_between:nnn {#2}{#3}{#4}
+  \tl_gset_eq:NN #1 \g_@@_output_tl
+  \tl_gclear:N \g_@@_output_tl
+}
+\cs_generate_variant:Nn \spath_gsplice_between:Nnnn {NVnn, NVVV}
+\cs_new_protected_nopar:Npn \spath_gsplice_between:Nnn #1#2#3
+{
+  \spath_gsplice_between:NVnn #1#1{#2}{#3}
+}
+\cs_generate_variant:Nn \spath_gsplice_between:Nnn {NVV, cnn, cvv}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{
+% \spath_close_with:Nn,
+% \spath_gclose_with:Nn
+% }
+% Closes the first path by splicing in the second.
+%    \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_close_with:nn #1#2
+{
+  \group_begin:
+  \spath_finalmovepoint:Nn \l_@@_tmpa_tl {#1}
+  \spath_finalpoint:Nn \l_@@_tmpb_tl {#1}
+  \dim_compare:nTF
+  {
+    \dim_abs:n
+    {
+      \tl_item:Nn \l_@@_tmpa_tl {1}
+      -
+      \tl_item:Nn \l_@@_tmpb_tl {1}
+    }
+    +
+    \dim_abs:n
+    {
+      \tl_item:Nn \l_@@_tmpa_tl {2}
+      -
+      \tl_item:Nn \l_@@_tmpb_tl {2}
+    }
+    < 0.01pt
+  }
+  {
+    \@@_close:n {#1}
+  }
+  {
+    \spath_span:NnVV \l_@@_tmpc_tl {#2} \l_@@_tmpb_tl \l_@@_tmpa_tl
+    \spath_append_no_move:NnV \l_@@_tmpd_tl {#1} \l_@@_tmpc_tl
+    \@@_close:V \l_@@_tmpd_tl
+  }
+  \group_end:
+}
+\cs_new_protected_nopar:Npn \spath_close_with:Nnn #1#2#3
+{
+  \@@_close_with:nn {#2}{#3}
+  \tl_set_eq:NN #1 \g_@@_output_tl
+  \tl_gclear:N \g_@@_output_tl
+}
+\cs_generate_variant:Nn \spath_close_with:Nnn {cnn, cVV, cvv, NVn}
+\cs_new_protected_nopar:Npn \spath_close_with:Nn #1#2
+{
+  \spath_close_with:NVn #1#1{#2}
+}
+\cs_generate_variant:Nn \spath_close_with:Nn {cn, cV, cv, NV}
+\cs_new_protected_nopar:Npn \spath_gclose_with:Nnn #1#2#3
+{
+  \@@_close_with:nn {#2}{#3}
+  \tl_gset_eq:NN #1 \g_@@_output_tl
+  \tl_gclear:N \g_@@_output_tl
+}
+\cs_generate_variant:Nn \spath_gclose_with:Nnn {cnn, cVV, cvv, NVn}
+\cs_new_protected_nopar:Npn \spath_gclose_with:Nn #1#2
+{
+  \spath_gclose_with:NVn #1#1{#2}
+}
+\cs_generate_variant:Nn \spath_gclose_with:Nn {cn, cV, cv, NV}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{
 % \spath_weld:Nnn,
 % \spath_weld:Nn,
 % \spath_gweld:Nnn,
@@ -1378,32 +1851,10 @@
   \group_begin:
   \tl_set:Nn \l_@@_tmpa_tl {#1}
   \tl_set:Nn \l_@@_tmpb_tl {#2}
+  \spath_finalpoint:Nn \l_@@_tmpc_tl {#1}
+  \spath_translate_to:NV \l_@@_tmpb_tl \l_@@_tmpc_tl
 
-  \spath_finalpoint:NV \l_@@_tmpc_tl \l_@@_tmpa_tl
-  \spath_initialpoint:NV \l_@@_tmpd_tl \l_@@_tmpb_tl
-
-  \dim_set:Nn \l_@@_tmpa_dim
-  {
-    \tl_item:Nn \l_@@_tmpc_tl {1}
-    -
-    \tl_item:Nn \l_@@_tmpd_tl {1}
-  }
-  \dim_set:Nn \l_@@_tmpb_dim
-  {
-    \tl_item:Nn \l_@@_tmpc_tl {2}
-    -
-    \tl_item:Nn \l_@@_tmpd_tl {2}
-  }
-
-  \spath_translate:NVV \l_@@_tmpb_tl \l_@@_tmpa_dim \l_@@_tmpb_dim
-
-  \prg_replicate:nn {3}
-  {
-    \tl_set:Nx \l_@@_tmpb_tl {\tl_tail:N \l_@@_tmpb_tl}
-  }
-
-  \tl_put_right:NV \l_@@_tmpa_tl \l_@@_tmpb_tl
-  \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpa_tl
+  \@@_append_no_move:VV \l_@@_tmpa_tl \l_@@_tmpb_tl
   \group_end:
 }
 \cs_new_protected_nopar:Npn \spath_weld:Nnn #1#2#3
@@ -1434,7 +1885,7 @@
 % \end{macro}
 %
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_append_no_move:Nnn,
 % \spath_append_no_move:Nn,
 % \spath_gappend_no_move:Nnn,
@@ -1456,6 +1907,7 @@
   \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpa_tl
   \group_end:
 }
+\cs_generate_variant:Nn \@@_append_no_move:nn {VV}
 \cs_new_protected_nopar:Npn \spath_append_no_move:Nnn #1#2#3
 {
   \@@_append_no_move:nn {#2}{#3}
@@ -1462,12 +1914,12 @@
   \tl_set_eq:NN #1 \g_@@_output_tl
   \tl_gclear:N \g_@@_output_tl
 }
-\cs_generate_variant:Nn \spath_append_no_move:Nnn {NVV, NVn}
+\cs_generate_variant:Nn \spath_append_no_move:Nnn {NVV, NVn, NnV}
 \cs_new_protected_nopar:Npn \spath_append_no_move:Nn #1#2
 {
   \spath_append_no_move:NVn #1#1{#2}
 }
-\cs_generate_variant:Nn \spath_append_no_move:Nn {NV, cv}
+\cs_generate_variant:Nn \spath_append_no_move:Nn {NV, cv, Nv}
 \cs_new_protected_nopar:Npn \spath_gappend_no_move:Nnn #1#2#3
 {
   \@@_append_no_move:nn {#2}{#3}
@@ -1479,11 +1931,11 @@
 {
   \spath_gappend_no_move:NVn #1#1{#2}
 }
-\cs_generate_variant:Nn \spath_gappend_no_move:Nn {NV, cv}
+\cs_generate_variant:Nn \spath_gappend_no_move:Nn {NV, cv, Nv}
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_append:Nnn,
 % \spath_append:Nn,
 % \spath_gappend:Nnn,
@@ -1501,7 +1953,7 @@
 {
   \spath_append:NVn #1#1{#2}
 }
-\cs_generate_variant:Nn \spath_append:Nn {NV, Nv}
+\cs_generate_variant:Nn \spath_append:Nn {NV, Nv, cv}
 \cs_new_protected_nopar:Npn \spath_gappend:Nnn #1#2#3
 {
   \tl_gset:Nn #1 {#2}
@@ -1512,12 +1964,12 @@
 {
   \spath_gappend:NVn #1#1{#2}
 }
-\cs_generate_variant:Nn \spath_gappend:Nn {NV, Nv}
+\cs_generate_variant:Nn \spath_gappend:Nn {NV, Nv, cv}
 %    \end{macrocode}
 % \end{macro}
 %
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_prepend_no_move:Nnn,
 % \spath_prepend_no_move:Nn,
 % \spath_gprepend_no_move:Nnn,
@@ -1549,7 +2001,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_prepend:Nnn,
 % \spath_prepend:Nn,
 % \spath_gprepend:Nnn,
@@ -1580,7 +2032,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_bake_round:Nn,
 % \spath_bake_round:N,
 % \spath_gbake_round:Nn,
@@ -1625,7 +2077,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_close:Nn,
 % \spath_close:N,
 % \spath_gclose:Nn,
@@ -1632,19 +2084,18 @@
 % \spath_gclose:N
 % }
 % Appends a close path to the end of the path.
-% For now, the point is the initial or final point (respectively).
-% To be future proof, it ought to be the point of the adjacent move to.
 %    \begin{macrocode}
 \cs_new_protected_nopar:Npn \@@_close:n #1
 {
   \group_begin:
   \tl_set:Nn \l_@@_tmpa_tl {#1}
-  \spath_initialpoint:NV \l_@@_tmpb_tl \l_@@_tmpa_tl
+  \spath_finalmovepoint:NV \l_@@_tmpb_tl \l_@@_tmpa_tl
   \tl_put_right:NV \l_@@_tmpa_tl \c_spath_closepath_tl
   \tl_put_right:NV \l_@@_tmpa_tl \l_@@_tmpb_tl
   \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpa_tl
   \group_end:
 }
+\cs_generate_variant:Nn \@@_close:n {V}
 \cs_new_protected_nopar:Npn \spath_close:Nn #1#2
 {
   \@@_close:n {#2}
@@ -1673,7 +2124,7 @@
 % \end{macro}
 %
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_open:Nn,
 % \spath_open:N,
 % \spath_gopen:Nn,
@@ -1783,7 +2234,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_remove_empty_components:Nn,
 % \spath_remove_empty_components:N,
 % \spath_gremove_empty_components:Nn,
@@ -1836,7 +2287,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{\spath_if_eq:nn}
+% \begin{macro}[internal]{\spath_if_eq:nn}
 % Test if two soft paths are equal, we allow a little tolerance on the calculations.
 %    \begin{macrocode}
 \prg_new_protected_conditional:Npnn \spath_if_eq:nn #1#2 { T, F, TF }
@@ -1845,7 +2296,10 @@
   \tl_set:Nn \l_@@_tmpa_tl {#1}
   \tl_set:Nn \l_@@_tmpb_tl {#2}
   \bool_gset_true:N \g_@@_tmpa_bool
-  \int_compare:nNnTF {\tl_count:N \l_@@_tmpa_tl} = {\tl_count:N \l_@@_tmpb_tl}
+  \int_compare:nNnTF
+  {\tl_count:N \l_@@_tmpa_tl}
+  =
+  {\tl_count:N \l_@@_tmpb_tl}
   {
     \int_step_inline:nnnn {1} {3} {\tl_count:N \l_@@_tmpa_tl}
     {
@@ -1857,14 +2311,28 @@
       }
       \dim_set:Nn \l_@@_tmpa_dim {\tl_item:Nn \l_@@_tmpa_tl {##1+1}}
       \dim_set:Nn \l_@@_tmpb_dim {\tl_item:Nn \l_@@_tmpb_tl {##1+1}}
-      \dim_compare:nF { \dim_abs:n { \l_@@_tmpa_dim - \l_@@_tmpb_dim} < 0.001pt }
+      \dim_compare:nF
       {
+        \dim_abs:n
+        {
+          \l_@@_tmpa_dim - \l_@@_tmpb_dim
+        }
+        < 0.001pt
+      }
+      {
         \bool_gset_false:N \g_@@_tmpa_bool
       }
       \dim_set:Nn \l_@@_tmpa_dim {\tl_item:Nn \l_@@_tmpa_tl {##1+2}}
       \dim_set:Nn \l_@@_tmpb_dim {\tl_item:Nn \l_@@_tmpb_tl {##1+2}}
-      \dim_compare:nF { \dim_abs:n { \l_@@_tmpa_dim - \l_@@_tmpb_dim} < 0.001pt }
+      \dim_compare:nF
       {
+        \dim_abs:n
+        {
+          \l_@@_tmpa_dim - \l_@@_tmpb_dim
+        }
+        < 0.001pt
+      }
+      {
         \bool_gset_false:N \g_@@_tmpa_bool
       }
     }
@@ -1887,7 +2355,7 @@
 %
 % \subsection{Splitting Commands}
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_split_curve:NNnn,
 % \spath_gsplit_curve:NNnn
 % }
@@ -1919,11 +2387,15 @@
   {
     {\fp_to_dim:n
     {
-      (1 - #2)^2 * \tl_item:nn {#1} {2} + 2 * (1 - #2) * (#2) * \tl_item:nn {#1} {5} + (#2)^2 * \tl_item:nn {#1} {8}
+      (1 - #2)^2 * \tl_item:nn {#1} {2}
+      + 2 * (1 - #2) * (#2) * \tl_item:nn {#1} {5}
+      + (#2)^2 * \tl_item:nn {#1} {8}
     }}
     {\fp_to_dim:n
     {
-      (1 - #2)^2 * \tl_item:nn {#1} {3} + 2 * (1 - #2) * (#2) * \tl_item:nn {#1} {6} + (#2)^2 * \tl_item:nn {#1} {9}
+      (1 - #2)^2 * \tl_item:nn {#1} {3}
+      + 2 * (1 - #2) * (#2) * \tl_item:nn {#1} {6}
+      + (#2)^2 * \tl_item:nn {#1} {9}
     }}
   }
 
@@ -1932,11 +2404,17 @@
   {
     {\fp_to_dim:n
       {
-      (1 - #2)^3 * \tl_item:nn {#1} {2} + 3 * (1 - #2)^2 * (#2) * \tl_item:nn {#1} {5} + 3 * (1 - #2) * (#2)^2 * \tl_item:nn {#1} {8} + (#2)^3 * \tl_item:nn {#1} {11}
+        (1 - #2)^3 * \tl_item:nn {#1} {2}
+        + 3 * (1 - #2)^2 * (#2) * \tl_item:nn {#1} {5}
+        + 3 * (1 - #2) * (#2)^2 * \tl_item:nn {#1} {8}
+        + (#2)^3 * \tl_item:nn {#1} {11}
     }}
     {\fp_to_dim:n
     {
-      (1 - #2)^3 * \tl_item:nn {#1} {3} + 3 * (1 - #2)^2 * (#2) * \tl_item:nn {#1} {6} + 3 * (1 - #2) * (#2)^2 * \tl_item:nn {#1} {9} + (#2)^3 * \tl_item:nn {#1} {12}
+      (1 - #2)^3 * \tl_item:nn {#1} {3}
+      + 3 * (1 - #2)^2 * (#2) * \tl_item:nn {#1} {6}
+      + 3 * (1 - #2) * (#2)^2 * \tl_item:nn {#1} {9}
+      + (#2)^3 * \tl_item:nn {#1} {12}
     }}
   }
 
@@ -1949,11 +2427,17 @@
   {
     {\fp_to_dim:n
       {
-      (1 - #2)^3 * \tl_item:nn {#1} {2} + 3 * (1 - #2)^2 * (#2) * \tl_item:nn {#1} {5} + 3 * (1 - #2) * (#2)^2 * \tl_item:nn {#1} {8} + (#2)^3 * \tl_item:nn {#1} {11}
+        (1 - #2)^3 * \tl_item:nn {#1} {2}
+        + 3 * (1 - #2)^2 * (#2) * \tl_item:nn {#1} {5}
+        + 3 * (1 - #2) * (#2)^2 * \tl_item:nn {#1} {8}
+        + (#2)^3 * \tl_item:nn {#1} {11}
     }}
     {\fp_to_dim:n
     {
-      (1 - #2)^3 * \tl_item:nn {#1} {3} + 3 * (1 - #2)^2 * (#2) * \tl_item:nn {#1} {6} + 3 * (1 - #2) * (#2)^2 * \tl_item:nn {#1} {9} + (#2)^3 * \tl_item:nn {#1} {12}
+      (1 - #2)^3 * \tl_item:nn {#1} {3}
+      + 3 * (1 - #2)^2 * (#2) * \tl_item:nn {#1} {6}
+      + 3 * (1 - #2) * (#2)^2 * \tl_item:nn {#1} {9}
+      + (#2)^3 * \tl_item:nn {#1} {12}
     }}
   }
 
@@ -1962,11 +2446,15 @@
   {
     {\fp_to_dim:n
     {
-      (1 - #2)^2 * \tl_item:nn {#1} {5} + 2 * (1 - #2) * (#2) * \tl_item:nn {#1} {8} + (#2)^2 * \tl_item:nn {#1} {11}
+      (1 - #2)^2 * \tl_item:nn {#1} {5}
+      + 2 * (1 - #2) * (#2) * \tl_item:nn {#1} {8}
+      + (#2)^2 * \tl_item:nn {#1} {11}
     }}
     {\fp_to_dim:n
     {
-      (1 - #2)^2 * \tl_item:nn {#1} {6} + 2 * (1 - #2) * (#2) * \tl_item:nn {#1} {9} + (#2)^2 * \tl_item:nn {#1} {12}
+      (1 - #2)^2 * \tl_item:nn {#1} {6}
+      + 2 * (1 - #2) * (#2) * \tl_item:nn {#1} {9}
+      + (#2)^2 * \tl_item:nn {#1} {12}
     }}
   }
   \tl_put_right:NV \l_@@_tmpa_tl \c_spath_curvetob_tl
@@ -1990,6 +2478,7 @@
   \@@_tl_gput_right_braced:NV \g_@@_output_tl \l_@@_tmpa_tl
   \group_end:
 }
+\cs_generate_variant:Nn \@@_split_curve:nn {nv, nV}
 \cs_new_protected_nopar:Npn \spath_split_curve:NNnn #1#2#3#4
 {
   \@@_split_curve:nn {#3}{#4}
@@ -2009,7 +2498,224 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{
+%
+% \begin{macro}[internal]{
+% \spath_maybe_split_curve:Nn,
+% \spath_maybe_gsplit_curve:Nn,
+% }
+% Possibly splits a bezier curve to ensure that the pieces don't self-intersect.
+% Figuring out whether a Bezier cubic self intersects is apparently a difficult problem so we don't bother.
+% We compute a point such that if there is an intersection then it lies on either side of the point.
+% I don't recall where the formula came from!
+%    \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_maybe_split_curve:n #1
+{
+  \group_begin:
+  \fp_set:Nn \l_@@_tmpa_fp
+  {
+    (
+    \tl_item:nn {#1} {3}
+    - 3 * \tl_item:nn {#1} {6}
+    + 3 * \tl_item:nn {#1} {9}
+    - \tl_item:nn {#1} {12}
+    )
+    *
+    (3 * \tl_item:nn {#1} {8} - 3 * \tl_item:nn {#1} {11})
+    -
+    (
+    \tl_item:nn {#1} {2}
+    - 3 * \tl_item:nn {#1} {5}
+    + 3 * \tl_item:nn {#1} {8}
+    - \tl_item:nn {#1} {11}
+    )
+    *
+    (3 * \tl_item:nn {#1} {9} - 3 * \tl_item:nn {#1} {12})
+  }
+  \fp_set:Nn \l_@@_tmpb_fp
+  {
+    (
+    \tl_item:nn {#1} {2}
+    - 3 * \tl_item:nn {#1} {5}
+    + 3 * \tl_item:nn {#1} {8}
+    - \tl_item:nn {#1} {11}
+    )
+    *
+    (
+    3 * \tl_item:nn {#1} {6}
+    - 6 * \tl_item:nn {#1} {9}
+    + 3 * \tl_item:nn {#1} {12}
+    )
+    -
+    (
+    \tl_item:nn {#1} {3}
+    - 3 * \tl_item:nn {#1} {6}
+    + 3 * \tl_item:nn {#1} {9}
+    - \tl_item:nn {#1} {12}
+    )
+    *
+    (
+    3 * \tl_item:nn {#1} {5}
+    - 6 * \tl_item:nn {#1} {8}
+    + 3 * \tl_item:nn {#1} {11}
+    )
+  }
+  \fp_compare:nTF
+  {
+    \l_@@_tmpb_fp != 0
+  }
+  {
+    \fp_set:Nn \l_@@_tmpa_fp {.5 * \l_@@_tmpa_fp / \l_@@_tmpb_fp}
+    \fp_compare:nTF
+    {
+      0 < \l_@@_tmpa_fp && \l_@@_tmpa_fp < 1
+    }
+    {
+      \@@_split_curve:nV {#1} \l_@@_tmpa_fp
+    }
+    {
+      \tl_gset:Nn \g_@@_output_tl { {#1} {} }
+    }
+  }
+  {
+    \tl_gset:Nn \g_@@_output_tl { {#1} {} }
+  }
+  \group_end:
+}
+\cs_new_protected_nopar:Npn \spath_maybe_split_curve:NNn #1#2#3
+{
+  \@@_maybe_split_curve:n {#3}
+  \tl_set:Nx #1 {\tl_item:Nn \g_@@_output_tl {1}}
+  \tl_set:Nx #2 {\tl_item:Nn \g_@@_output_tl {2}}
+  \tl_gclear:N \g_@@_output_tl
+}
+\cs_generate_variant:Nn \spath_maybe_split_curve:NNn {NNn, NNV }
+\cs_new_protected_nopar:Npn \spath_maybe_gsplit_curve:NNn #1#2#3
+{
+  \@@_maybe_split_curve:n {#3}
+  \tl_gset:Nx #1 {\tl_item:Nn \g_@@_output_tl {1}}
+  \tl_gset:Nx #2 {\tl_item:Nn \g_@@_output_tl {2}}
+  \tl_gclear:N \g_@@_output_tl
+}
+\cs_generate_variant:Nn \spath_maybe_gsplit_curve:NNn {NNn, NNV}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{
+% \spath_split_curves:Nn,
+% \spath_gsplit_curves:Nn,
+% }
+% Slurp through the path ensuring that beziers don't self-intersect.
+%    \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_split_curves:n #1
+{
+  \group_begin:
+  \tl_set:Nn \l_@@_tmpa_tl {#1}
+  \tl_clear:N \l_@@_tmpb_tl
+  \tl_clear:N \l_@@_tmpc_tl
+  \bool_do_until:nn
+  {
+    \tl_if_empty_p:N \l_@@_tmpa_tl
+  }
+  {
+    \tl_set:Nx \l_@@_tmpc_tl {\tl_head:N \l_@@_tmpa_tl}
+    \tl_case:NnF \l_@@_tmpc_tl
+    {
+      \c_spath_curvetoa_tl
+      {
+        \tl_clear:N \l_@@_tmpd_tl
+        \tl_set_eq:NN \l_@@_tmpd_tl \c_spath_moveto_tl
+        \tl_put_right:Nx \l_@@_tmpd_tl
+        {
+          { \dim_use:N \l_@@_tmpa_dim }
+          { \dim_use:N \l_@@_tmpb_dim }
+        }
+        \dim_set:Nn \l_@@_tmpa_dim
+        {
+          \tl_item:Nn \l_@@_tmpa_tl {8}
+        }
+        \dim_set:Nn \l_@@_tmpb_dim
+        {
+          \tl_item:Nn \l_@@_tmpa_tl {9}
+        }
+        \prg_replicate:nn {3}
+        {
+          \tl_put_right:Nx \l_@@_tmpd_tl
+          {
+            \tl_item:Nn \l_@@_tmpa_tl {1}
+            {\tl_item:Nn \l_@@_tmpa_tl {2}}
+            {\tl_item:Nn \l_@@_tmpa_tl {3}}
+          }
+          \prg_replicate:nn {3}
+          {
+            \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
+          }
+        }
+
+        \spath_maybe_split_curve:NNV
+        \l_@@_tmpd_tl
+        \l_@@_tmpe_tl
+        \l_@@_tmpd_tl
+        \prg_replicate:nn {3}
+        {
+          \tl_set:Nx \l_@@_tmpd_tl {\tl_tail:N \l_@@_tmpd_tl}
+          \tl_set:Nx \l_@@_tmpe_tl {\tl_tail:N \l_@@_tmpe_tl}
+        }
+        \tl_put_right:NV \l_@@_tmpb_tl \l_@@_tmpd_tl
+        \tl_put_right:NV \l_@@_tmpb_tl \l_@@_tmpe_tl
+      }
+    }
+    {
+      \dim_set:Nn \l_@@_tmpa_dim
+      {
+        \tl_item:Nn \l_@@_tmpa_tl {2}
+      }
+      \dim_set:Nn \l_@@_tmpb_dim
+      {
+        \tl_item:Nn \l_@@_tmpa_tl {3}
+      }
+      \tl_put_right:Nx \l_@@_tmpb_tl
+      {
+        \tl_item:Nn \l_@@_tmpa_tl {1}
+        {\tl_item:Nn \l_@@_tmpa_tl {2}}
+        {\tl_item:Nn \l_@@_tmpa_tl {3}}
+      }
+      \prg_replicate:nn {3}
+      {
+        \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
+      }
+    }
+  }
+  \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpb_tl
+  \group_end:
+}
+\cs_new_protected_nopar:Npn \spath_split_curves:Nn #1#2
+{
+  \@@_split_curves:n {#2}
+  \tl_set_eq:NN #1 \g_@@_output_tl
+  \tl_gclear:N \g_@@_output_tl
+}
+\cs_generate_variant:Nn \spath_split_curves:Nn {NV, cV, cn, cv }
+\cs_new_protected_nopar:Npn \spath_split_curves:N #1
+{
+  \spath_split_curves:NV #1#1
+}
+\cs_generate_variant:Nn \spath_split_curves:N {c}
+\cs_new_protected_nopar:Npn \spath_gsplit_curves:Nn #1#2
+{
+  \@@_split_curves:n {#2}
+  \tl_gset_eq:NN #1 \g_@@_output_tl
+  \tl_gclear:N \g_@@_output_tl
+}
+\cs_generate_variant:Nn \spath_gsplit_curves:Nn {NV, cV, cn, cv }
+\cs_new_protected_nopar:Npn \spath_gsplit_curves:N #1
+{
+  \spath_gsplit_curves:NV #1#1
+}
+\cs_generate_variant:Nn \spath_gsplit_curves:N {c}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{
 % \spath_split_line:NNnn,
 % \spath_gsplit_line:NNnn
 % }
@@ -2079,21 +2785,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-%    \begin{macrocode}
-\int_new:N \l_@@_split_int
-\int_new:N \l_@@_splitat_int
-\fp_new:N \l_@@_split_fp
-\bool_new:N \l_@@_split_bool
-\tl_new:N \l_@@_split_path_tl
-\tl_new:N \l_@@_split_patha_tl
-\tl_new:N \l_@@_split_pathb_tl
-\tl_new:N \l_@@_split_intoa_tl
-\tl_new:N \l_@@_split_intob_tl
-\dim_new:N \l_@@_splitx_dim
-\dim_new:N \l_@@_splity_dim
-%    \end{macrocode}
-%
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_split_at:NNnn,
 % \spath_split_at:Nnn,
 % \spath_split_at:Nn,
@@ -2107,165 +2799,165 @@
 \cs_new_protected_nopar:Npn \@@_split_at:nn #1#2
 {
   \group_begin:
-  \int_set:Nn \l_@@_splitat_int {\fp_to_int:n {floor(#2) + 1}}
-  \fp_set:Nn \l_@@_split_fp {#2 - floor(#2)}
+  \int_set:Nn \l_@@_tmpa_int {\fp_to_int:n {floor(#2) + 1}}
+  \fp_set:Nn \l_@@_tmpa_fp {#2 - floor(#2)}
 
   % Is split point near one end or other of a component?
   \fp_compare:nT
   {
-    \l_@@_split_fp < 0.01
+    \l_@@_tmpa_fp < 0.01
   }
   {
     % Near the start, so we'll place it at the start
-    \fp_set:Nn \l_@@_split_fp {0}
+    \fp_set:Nn \l_@@_tmpa_fp {0}
   }
   \fp_compare:nT
   {
-    \l_@@_split_fp > 0.99
+    \l_@@_tmpa_fp > 0.99
   }
   {
     % Near the end, so we'll place it at the end
-    \fp_set:Nn \l_@@_split_fp {0}
-    \int_incr:N \l_@@_splitat_int
+    \fp_set:Nn \l_@@_tmpa_fp {0}
+    \int_incr:N \l_@@_tmpa_int
   }
   
-  \int_zero:N \l_@@_split_int
-  \bool_set_true:N \l_@@_split_bool
+  \int_zero:N \l_@@_tmpb_int
+  \bool_set_true:N \l_@@_tmpa_bool
 
-  \tl_set:Nn \l_@@_split_path_tl {#1}
-  \tl_clear:N \l_@@_split_patha_tl
+  \tl_set:Nn \l_@@_tmpe_tl {#1}
+  \tl_clear:N \l_@@_tmpc_tl
 
-  \dim_zero:N \l_@@_splitx_dim
-  \dim_zero:N \l_@@_splity_dim
+  \dim_zero:N \l_@@_tmpa_dim
+  \dim_zero:N \l_@@_tmpb_dim
 
   \bool_until_do:nn {
-    \tl_if_empty_p:N \l_@@_split_path_tl
+    \tl_if_empty_p:N \l_@@_tmpe_tl
     ||
-    \int_compare_p:n { \l_@@_splitat_int == \l_@@_split_int  }
+    \int_compare_p:n { \l_@@_tmpa_int == \l_@@_tmpb_int  }
   }
   {
-    \tl_set:Nx \l_@@_tmpc_tl {\tl_head:N \l_@@_split_path_tl}
-    \tl_set:Nx \l_@@_split_path_tl {\tl_tail:N \l_@@_split_path_tl }
-    \tl_case:Nn \l_@@_tmpc_tl
+    \tl_set:Nx \l_@@_tmpf_tl {\tl_head:N \l_@@_tmpe_tl}
+    \tl_set:Nx \l_@@_tmpe_tl {\tl_tail:N \l_@@_tmpe_tl }
+    \tl_case:Nn \l_@@_tmpf_tl
     {
       \c_spath_lineto_tl
       {
-        \int_incr:N \l_@@_split_int
+        \int_incr:N \l_@@_tmpb_int
       }
       \c_spath_curvetoa_tl
       {
-        \int_incr:N \l_@@_split_int
+        \int_incr:N \l_@@_tmpb_int
       }
     }
-    \int_compare:nT { \l_@@_split_int < \l_@@_splitat_int  }
+    \int_compare:nT { \l_@@_tmpb_int < \l_@@_tmpa_int  }
     {
-      \tl_put_right:NV \l_@@_split_patha_tl \l_@@_tmpc_tl
+      \tl_put_right:NV \l_@@_tmpc_tl \l_@@_tmpf_tl
       
-      \tl_put_right:Nx \l_@@_split_patha_tl
-      {{ \tl_head:N \l_@@_split_path_tl }}
-      \dim_set:Nn \l_@@_splitx_dim {\tl_head:N \l_@@_split_path_tl}
-      \tl_set:Nx \l_@@_split_path_tl {\tl_tail:N \l_@@_split_path_tl }
+      \tl_put_right:Nx \l_@@_tmpc_tl
+      {{ \tl_head:N \l_@@_tmpe_tl }}
+      \dim_set:Nn \l_@@_tmpa_dim {\tl_head:N \l_@@_tmpe_tl}
+      \tl_set:Nx \l_@@_tmpe_tl {\tl_tail:N \l_@@_tmpe_tl }
       
-      \tl_put_right:Nx \l_@@_split_patha_tl
-      {{ \tl_head:N \l_@@_split_path_tl }}
-      \dim_set:Nn \l_@@_splity_dim {\tl_head:N \l_@@_split_path_tl}
-      \tl_set:Nx \l_@@_split_path_tl {\tl_tail:N \l_@@_split_path_tl }
+      \tl_put_right:Nx \l_@@_tmpc_tl
+      {{ \tl_head:N \l_@@_tmpe_tl }}
+      \dim_set:Nn \l_@@_tmpb_dim {\tl_head:N \l_@@_tmpe_tl}
+      \tl_set:Nx \l_@@_tmpe_tl {\tl_tail:N \l_@@_tmpe_tl }
       
     }
   }
 
-  \tl_clear:N \l_@@_split_pathb_tl
-  \tl_put_right:NV \l_@@_split_pathb_tl \c_spath_moveto_tl
-  \tl_put_right:Nx \l_@@_split_pathb_tl
+  \tl_clear:N \l_@@_tmpd_tl
+  \tl_put_right:NV \l_@@_tmpd_tl \c_spath_moveto_tl
+  \tl_put_right:Nx \l_@@_tmpd_tl
   {
-    {\dim_use:N \l_@@_splitx_dim}
-    {\dim_use:N \l_@@_splity_dim}
+    {\dim_use:N \l_@@_tmpa_dim}
+    {\dim_use:N \l_@@_tmpb_dim}
   }
 
   \fp_compare:nTF
   {
-    \l_@@_split_fp == 0
+    \l_@@_tmpa_fp == 0
   }
   {
-    \tl_set_eq:NN \l_@@_split_intob_tl \l_@@_split_pathb_tl
-    \tl_if_empty:NF \l_@@_split_path_tl
+    \tl_set_eq:NN \l_@@_tmpb_tl \l_@@_tmpd_tl
+    \tl_if_empty:NF \l_@@_tmpe_tl
     {
-      \tl_put_right:NV \l_@@_split_intob_tl \l_@@_tmpc_tl
-      \tl_put_right:NV \l_@@_split_intob_tl \l_@@_split_path_tl
+      \tl_put_right:NV \l_@@_tmpb_tl \l_@@_tmpf_tl
+      \tl_put_right:NV \l_@@_tmpb_tl \l_@@_tmpe_tl
     }
   }
   {
 
-    \tl_case:Nn \l_@@_tmpc_tl
+    \tl_case:Nn \l_@@_tmpf_tl
     {
       \c_spath_lineto_tl
       {
-        \tl_put_right:NV \l_@@_split_pathb_tl \l_@@_tmpc_tl
-        \tl_put_right:Nx \l_@@_split_pathb_tl
-        {{ \tl_head:N \l_@@_split_path_tl }}
-        \tl_set:Nx \l_@@_split_path_tl {\tl_tail:N \l_@@_split_path_tl }
+        \tl_put_right:NV \l_@@_tmpd_tl \l_@@_tmpf_tl
+        \tl_put_right:Nx \l_@@_tmpd_tl
+        {{ \tl_head:N \l_@@_tmpe_tl }}
+        \tl_set:Nx \l_@@_tmpe_tl {\tl_tail:N \l_@@_tmpe_tl }
       
-        \tl_put_right:Nx \l_@@_split_pathb_tl
-        {{ \tl_head:N \l_@@_split_path_tl }}
-        \tl_set:Nx \l_@@_split_path_tl {\tl_tail:N \l_@@_split_path_tl }
+        \tl_put_right:Nx \l_@@_tmpd_tl
+        {{ \tl_head:N \l_@@_tmpe_tl }}
+        \tl_set:Nx \l_@@_tmpe_tl {\tl_tail:N \l_@@_tmpe_tl }
 
         \spath_split_line:NNVV
-        \l_@@_split_intoa_tl
-        \l_@@_split_intob_tl
-        \l_@@_split_pathb_tl
-        \l_@@_split_fp
+        \l_@@_tmpa_tl
+        \l_@@_tmpb_tl
+        \l_@@_tmpd_tl
+        \l_@@_tmpa_fp
 
         \prg_replicate:nn {3} {
-          \tl_set:Nx \l_@@_split_intoa_tl {\tl_tail:N \l_@@_split_intoa_tl}
+          \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
         }
 
-        \tl_put_right:NV \l_@@_split_patha_tl \l_@@_split_intoa_tl
-        \tl_put_right:NV \l_@@_split_intob_tl \l_@@_split_path_tl
+        \tl_put_right:NV \l_@@_tmpc_tl \l_@@_tmpa_tl
+        \tl_put_right:NV \l_@@_tmpb_tl \l_@@_tmpe_tl
       }
       \c_spath_curvetoa_tl
       {
-        \tl_put_right:NV \l_@@_split_pathb_tl \l_@@_tmpc_tl
-        \tl_put_right:Nx \l_@@_split_pathb_tl
-        {{ \tl_head:N \l_@@_split_path_tl }}
-        \tl_set:Nx \l_@@_split_path_tl {\tl_tail:N \l_@@_split_path_tl }
+        \tl_put_right:NV \l_@@_tmpd_tl \l_@@_tmpf_tl
+        \tl_put_right:Nx \l_@@_tmpd_tl
+        {{ \tl_head:N \l_@@_tmpe_tl }}
+        \tl_set:Nx \l_@@_tmpe_tl {\tl_tail:N \l_@@_tmpe_tl }
       
-        \tl_put_right:Nx \l_@@_split_pathb_tl
-        {{ \tl_head:N \l_@@_split_path_tl }}
-        \tl_set:Nx \l_@@_split_path_tl {\tl_tail:N \l_@@_split_path_tl }
+        \tl_put_right:Nx \l_@@_tmpd_tl
+        {{ \tl_head:N \l_@@_tmpe_tl }}
+        \tl_set:Nx \l_@@_tmpe_tl {\tl_tail:N \l_@@_tmpe_tl }
       
         \prg_replicate:nn {2} {
         
-          \tl_put_right:Nx \l_@@_split_pathb_tl
-          { \tl_head:N \l_@@_split_path_tl }
-          \tl_set:Nx \l_@@_split_path_tl {\tl_tail:N \l_@@_split_path_tl }
+          \tl_put_right:Nx \l_@@_tmpd_tl
+          { \tl_head:N \l_@@_tmpe_tl }
+          \tl_set:Nx \l_@@_tmpe_tl {\tl_tail:N \l_@@_tmpe_tl }
         
-          \tl_put_right:Nx \l_@@_split_pathb_tl
-          {{ \tl_head:N \l_@@_split_path_tl }}
-          \tl_set:Nx \l_@@_split_path_tl {\tl_tail:N \l_@@_split_path_tl }
+          \tl_put_right:Nx \l_@@_tmpd_tl
+          {{ \tl_head:N \l_@@_tmpe_tl }}
+          \tl_set:Nx \l_@@_tmpe_tl {\tl_tail:N \l_@@_tmpe_tl }
       
-          \tl_put_right:Nx \l_@@_split_pathb_tl
-          {{ \tl_head:N \l_@@_split_path_tl }}
-          \tl_set:Nx \l_@@_split_path_tl {\tl_tail:N \l_@@_split_path_tl }
+          \tl_put_right:Nx \l_@@_tmpd_tl
+          {{ \tl_head:N \l_@@_tmpe_tl }}
+          \tl_set:Nx \l_@@_tmpe_tl {\tl_tail:N \l_@@_tmpe_tl }
         }
 
         \spath_split_curve:NNVV
-        \l_@@_split_intoa_tl
-        \l_@@_split_intob_tl
-        \l_@@_split_pathb_tl \l_@@_split_fp
+        \l_@@_tmpa_tl
+        \l_@@_tmpb_tl
+        \l_@@_tmpd_tl \l_@@_tmpa_fp
 
         \prg_replicate:nn {3} {
-          \tl_set:Nx \l_@@_split_intoa_tl {\tl_tail:N \l_@@_split_intoa_tl}
+          \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
         }
 
-        \tl_put_right:NV \l_@@_split_patha_tl \l_@@_split_intoa_tl
-        \tl_put_right:NV \l_@@_split_intob_tl \l_@@_split_path_tl
+        \tl_put_right:NV \l_@@_tmpc_tl \l_@@_tmpa_tl
+        \tl_put_right:NV \l_@@_tmpb_tl \l_@@_tmpe_tl
       }
     }
   }
 
   \tl_gclear:N \g_@@_output_tl
-  \@@_tl_gput_right_braced:NV \g_@@_output_tl \l_@@_split_patha_tl
-  \@@_tl_gput_right_braced:NV \g_@@_output_tl \l_@@_split_intob_tl
+  \@@_tl_gput_right_braced:NV \g_@@_output_tl \l_@@_tmpc_tl
+  \@@_tl_gput_right_braced:NV \g_@@_output_tl \l_@@_tmpb_tl
   \group_end:
 }
 \cs_new_protected_nopar:Npn \spath_split_at:NNnn #1#2#3#4
@@ -2291,7 +2983,11 @@
 \cs_new_protected_nopar:Npn \spath_split_at:Nnn #1#2#3
 {
   \@@_split_at:nn {#2}{#3}
-  \tl_set:Nx #1 {\tl_item:Nn \g_@@_output_tl {1} \tl_item:Nn \g_@@_output_tl {2}}
+  \tl_set:Nx #1
+  {
+    \tl_item:Nn \g_@@_output_tl {1}
+    \tl_item:Nn \g_@@_output_tl {2}
+  }
   \tl_gclear:N \g_@@_output_tl
 }
 \cs_generate_variant:Nn \spath_split_at:Nnn {NVn, NVV}
@@ -2302,7 +2998,11 @@
 \cs_new_protected_nopar:Npn \spath_gsplit_at:Nnn #1#2#3
 {
   \@@_split_at:nn {#2}{#3}
-  \tl_gset:Nx #1 {\tl_item:Nn \g_@@_output_tl {1} \tl_item:Nn \g_@@_output_tl {2}}
+  \tl_gset:Nx #1
+  {
+    \tl_item:Nn \g_@@_output_tl {1}
+    \tl_item:Nn \g_@@_output_tl {2}
+  }
   \tl_gclear:N \g_@@_output_tl
 }
 \cs_generate_variant:Nn \spath_gsplit_at:Nnn {NVn, NVV}
@@ -2323,19 +3023,7 @@
 % As in the previous section, there are various versions.
 % In particular, there are versions where the path can be specified by a macro and is saved back into that macro.
 %
-%    \begin{macrocode}
-\tl_new:N \l_@@_shorten_fa_tl
-\tl_new:N \l_@@_shorten_path_tl
-\tl_new:N \l_@@_shorten_last_tl
-\tl_new:N \l_@@_shorten_lasta_tl
-\tl_new:N \l_@@_shorten_lastb_tl
-\int_new:N \l_@@_shorten_int
-\fp_new:N \l_@@_shorten_x_fp
-\fp_new:N \l_@@_shorten_y_fp
-\fp_new:N \l_@@_shorten_len_fp
-%    \end{macrocode}
-%
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_shorten_at_end:Nnn
 % }
 % This macro shortens a path from the end by a dimension.
@@ -2349,106 +3037,106 @@
   }
   {
     \group_begin:
-    \tl_set:Nn \l_@@_shorten_path_tl {#1}
-    \tl_reverse:N \l_@@_shorten_path_tl
+    \tl_set:Nn \l_@@_tmpa_tl {#1}
+    \tl_reverse:N \l_@@_tmpa_tl
 
-    \tl_set:Nx \l_@@_shorten_fa_tl {\tl_item:Nn \l_@@_shorten_path_tl {3}}
+    \tl_set:Nx \l_@@_tmpb_tl {\tl_item:Nn \l_@@_tmpa_tl {3}}
 
-    \tl_clear:N \l_@@_shorten_last_tl
-    \tl_if_eq:NNTF \l_@@_shorten_fa_tl \c_spath_curveto_tl
+    \tl_clear:N \l_@@_tmpe_tl
+    \tl_if_eq:NNTF \l_@@_tmpb_tl \c_spath_curveto_tl
     {
-      \int_set:Nn \l_@@_shorten_int {3}
+      \int_set:Nn \l_@@_tmpa_int {3}
     }
     {
-      \int_set:Nn \l_@@_shorten_int {1}
+      \int_set:Nn \l_@@_tmpa_int {1}
     }
 
-    \prg_replicate:nn { \l_@@_shorten_int }
+    \prg_replicate:nn { \l_@@_tmpa_int }
     {
-      \tl_put_right:Nx \l_@@_shorten_last_tl
+      \tl_put_right:Nx \l_@@_tmpe_tl
       {
-        {\tl_head:N \l_@@_shorten_path_tl}
+        {\tl_head:N \l_@@_tmpa_tl}
       }
-      \tl_set:Nx \l_@@_shorten_path_tl {\tl_tail:N \l_@@_shorten_path_tl}
-      \tl_put_right:Nx \l_@@_shorten_last_tl
+      \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
+      \tl_put_right:Nx \l_@@_tmpe_tl
       {
-        {\tl_head:N \l_@@_shorten_path_tl}
+        {\tl_head:N \l_@@_tmpa_tl}
       }
-      \tl_set:Nx \l_@@_shorten_path_tl {\tl_tail:N \l_@@_shorten_path_tl}
-      \tl_put_right:Nx \l_@@_shorten_last_tl
+      \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
+      \tl_put_right:Nx \l_@@_tmpe_tl
       {
-        \tl_head:N \l_@@_shorten_path_tl
+        \tl_head:N \l_@@_tmpa_tl
       }
-      \tl_set:Nx \l_@@_shorten_path_tl {\tl_tail:N \l_@@_shorten_path_tl}
+      \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
     }
 
-    \tl_put_right:Nx \l_@@_shorten_last_tl
+    \tl_put_right:Nx \l_@@_tmpe_tl
     {
-      {\tl_item:Nn \l_@@_shorten_path_tl {1}}
-      {\tl_item:Nn \l_@@_shorten_path_tl {2}}
+      {\tl_item:Nn \l_@@_tmpa_tl {1}}
+      {\tl_item:Nn \l_@@_tmpa_tl {2}}
     }
-    \tl_put_right:NV \l_@@_shorten_last_tl \c_spath_moveto_tl
+    \tl_put_right:NV \l_@@_tmpe_tl \c_spath_moveto_tl
     
-    \tl_reverse:N \l_@@_shorten_path_tl
+    \tl_reverse:N \l_@@_tmpa_tl
 
-    \fp_set:Nn \l_@@_shorten_x_fp
+    \fp_set:Nn \l_@@_tmpa_fp
     {
-      \dim_to_fp:n {\tl_item:Nn \l_@@_shorten_last_tl {4}}
+      \dim_to_fp:n {\tl_item:Nn \l_@@_tmpe_tl {4}}
       -
-      \dim_to_fp:n {\tl_item:Nn \l_@@_shorten_last_tl {1}}
+      \dim_to_fp:n {\tl_item:Nn \l_@@_tmpe_tl {1}}
     }
   
-    \fp_set:Nn \l_@@_shorten_y_fp
+    \fp_set:Nn \l_@@_tmpb_fp
     {
-      \dim_to_fp:n {\tl_item:Nn \l_@@_shorten_last_tl {5}}
+      \dim_to_fp:n {\tl_item:Nn \l_@@_tmpe_tl {5}}
       -
-      \dim_to_fp:n {\tl_item:Nn \l_@@_shorten_last_tl {2}}
+      \dim_to_fp:n {\tl_item:Nn \l_@@_tmpe_tl {2}}
     }
 
-    \fp_set:Nn \l_@@_shorten_len_fp
+    \fp_set:Nn \l_@@_tmpc_fp
     {
-      sqrt( \l_@@_shorten_x_fp * \l_@@_shorten_x_fp +  \l_@@_shorten_y_fp *  \l_@@_shorten_y_fp )
+      sqrt(
+      \l_@@_tmpa_fp * \l_@@_tmpa_fp
+      +
+      \l_@@_tmpb_fp *  \l_@@_tmpb_fp
+      ) * \l_@@_tmpa_int
     }
 
     \fp_compare:nTF
     {
-      \l_@@_shorten_len_fp > #2
+      \l_@@_tmpc_fp > #2
     }
     {
   
-      \fp_set:Nn \l_@@_shorten_len_fp
+      \fp_set:Nn \l_@@_tmpc_fp
       {
-        (\l_@@_shorten_len_fp - #2)/ \l_@@_shorten_len_fp
+        (\l_@@_tmpc_fp - #2)/ \l_@@_tmpc_fp
       }
 
-      \tl_reverse:N \l_@@_shorten_last_tl
+      \tl_reverse:N \l_@@_tmpe_tl
 
-      \tl_if_eq:NNTF \l_@@_shorten_fa_tl \c_spath_curveto_tl
+      \tl_if_eq:NNTF \l_@@_tmpb_tl \c_spath_curveto_tl
       {
-        \fp_set:Nn \l_@@_shorten_len_fp
-        {
-          1 - (1 -\l_@@_shorten_len_fp)/3
-        }
         \spath_split_curve:NNVV
-        \l_@@_shorten_lasta_tl
-        \l_@@_shorten_lastb_tl
-        \l_@@_shorten_last_tl
-        \l_@@_shorten_len_fp
+        \l_@@_tmpc_tl
+        \l_@@_tmpd_tl
+        \l_@@_tmpe_tl
+        \l_@@_tmpc_fp
       }
       {
         \spath_split_line:NNVV
-        \l_@@_shorten_lasta_tl
-        \l_@@_shorten_lastb_tl
-        \l_@@_shorten_last_tl
-        \l_@@_shorten_len_fp
+        \l_@@_tmpc_tl
+        \l_@@_tmpd_tl
+        \l_@@_tmpe_tl
+        \l_@@_tmpc_fp
       }
 
       \prg_replicate:nn {3}
       {
-        \tl_set:Nx \l_@@_shorten_lasta_tl {\tl_tail:N \l_@@_shorten_lasta_tl}
+        \tl_set:Nx \l_@@_tmpc_tl {\tl_tail:N \l_@@_tmpc_tl}
       }
 
-      \tl_put_right:NV \l_@@_shorten_path_tl \l_@@_shorten_lasta_tl
+      \tl_put_right:NV \l_@@_tmpa_tl \l_@@_tmpc_tl
 
     }
     {
@@ -2455,15 +3143,15 @@
 
       \int_compare:nT
       {
-        \tl_count:N \l_@@_shorten_path_tl > 3
+        \tl_count:N \l_@@_tmpa_tl > 3
       }
       {
-        \dim_set:Nn \l_@@_tmpa_dim {\fp_to_dim:n {#2 - \l_@@_shorten_len_fp } }
-        \spath_shorten_at_end:NV \l_@@_shorten_path_tl \l_@@_tmpa_dim
+        \dim_set:Nn \l_@@_tmpa_dim {\fp_to_dim:n {#2 - \l_@@_tmpc_fp } }
+        \spath_shorten_at_end:NV \l_@@_tmpa_tl \l_@@_tmpa_dim
       }
     }
 
-    \tl_gset_eq:NN \g_@@_output_tl \l_@@_shorten_path_tl
+    \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpa_tl
     \group_end:
   }
   {
@@ -2497,7 +3185,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_shorten_at_start:Nnn,
 % \spath_shorten_at_start:Nn,
 % \spath_gshorten_at_start:Nnn,
@@ -2515,110 +3203,120 @@
   }
   {
   \group_begin:
-  \tl_set:Nn \l_@@_shorten_path_tl {#1}
+  \tl_set:Nn \l_@@_tmpa_tl {#1}
 
-  \tl_set:Nx \l_@@_shorten_fa_tl {\tl_item:Nn \l_@@_shorten_path_tl {4}}
+  \tl_set:Nx \l_@@_tmpb_tl {\tl_item:Nn \l_@@_tmpa_tl {4}}
 
-    \tl_clear:N \l_@@_shorten_last_tl
+    \tl_clear:N \l_@@_tmpe_tl
 
-  \tl_if_eq:NNTF \l_@@_shorten_fa_tl \c_spath_curvetoa_tl
+  \tl_if_eq:NNTF \l_@@_tmpb_tl \c_spath_curvetoa_tl
   {
-    \int_set:Nn \l_@@_shorten_int {3}
+    \int_set:Nn \l_@@_tmpa_int {3}
   }
   {
-    \int_set:Nn \l_@@_shorten_int {1}
+    \int_set:Nn \l_@@_tmpa_int {1}
   }
 
-  \tl_set_eq:NN \l_@@_shorten_last_tl \c_spath_moveto_tl
-  \tl_set:Nx \l_@@_shorten_path_tl {\tl_tail:N \l_@@_shorten_path_tl }
+  \tl_set_eq:NN \l_@@_tmpe_tl \c_spath_moveto_tl
+  \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl }
 
-  \prg_replicate:nn { \l_@@_shorten_int }
+  \prg_replicate:nn { \l_@@_tmpa_int }
   {
-    \@@_tl_put_right_braced:Nx \l_@@_shorten_last_tl {\tl_item:Nn \l_@@_shorten_path_tl {1}}
-    \@@_tl_put_right_braced:Nx \l_@@_shorten_last_tl {\tl_item:Nn \l_@@_shorten_path_tl {2}}
-    \tl_put_right:Nx \l_@@_shorten_last_tl {\tl_item:Nn \l_@@_shorten_path_tl {3}}
+    \@@_tl_put_right_braced:Nx
+    \l_@@_tmpe_tl
+    {\tl_item:Nn \l_@@_tmpa_tl {1}}
+    \@@_tl_put_right_braced:Nx
+    \l_@@_tmpe_tl
+    {\tl_item:Nn \l_@@_tmpa_tl {2}}
+    \tl_put_right:Nx \l_@@_tmpe_tl {\tl_item:Nn \l_@@_tmpa_tl {3}}
 
     \prg_replicate:nn {3}
     {
-      \tl_set:Nx \l_@@_shorten_path_tl {\tl_tail:N \l_@@_shorten_path_tl }
+      \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl }
     }
   }
-  \@@_tl_put_right_braced:Nx \l_@@_shorten_last_tl {\tl_item:Nn \l_@@_shorten_path_tl {1}}
-  \@@_tl_put_right_braced:Nx \l_@@_shorten_last_tl {\tl_item:Nn \l_@@_shorten_path_tl {2}}
+  \@@_tl_put_right_braced:Nx
+  \l_@@_tmpe_tl
+  {\tl_item:Nn \l_@@_tmpa_tl {1}}
+  \@@_tl_put_right_braced:Nx
+  \l_@@_tmpe_tl
+  {\tl_item:Nn \l_@@_tmpa_tl {2}}
 
-  \fp_set:Nn \l_@@_shorten_x_fp
+  \fp_set:Nn \l_@@_tmpa_fp
   {
-    \dim_to_fp:n {\tl_item:Nn \l_@@_shorten_last_tl {5}}
+    \dim_to_fp:n {\tl_item:Nn \l_@@_tmpe_tl {5}}
     -
-    \dim_to_fp:n {\tl_item:Nn \l_@@_shorten_last_tl {2}}
+    \dim_to_fp:n {\tl_item:Nn \l_@@_tmpe_tl {2}}
   }
   
-  \fp_set:Nn \l_@@_shorten_y_fp
+  \fp_set:Nn \l_@@_tmpb_fp
   {
-    \dim_to_fp:n {\tl_item:Nn \l_@@_shorten_last_tl {6}}
+    \dim_to_fp:n {\tl_item:Nn \l_@@_tmpe_tl {6}}
     -
-    \dim_to_fp:n {\tl_item:Nn \l_@@_shorten_last_tl {3}}
+    \dim_to_fp:n {\tl_item:Nn \l_@@_tmpe_tl {3}}
   }
 
-  \fp_set:Nn \l_@@_shorten_len_fp
+  \fp_set:Nn \l_@@_tmpc_fp
   {
-    sqrt( \l_@@_shorten_x_fp * \l_@@_shorten_x_fp +  \l_@@_shorten_y_fp *  \l_@@_shorten_y_fp )
+    sqrt(
+    \l_@@_tmpa_fp * \l_@@_tmpa_fp
+    +
+    \l_@@_tmpb_fp *  \l_@@_tmpb_fp
+    )
+    *
+    \l_@@_tmpa_int
   }
 
   \fp_compare:nTF
   {
-    \l_@@_shorten_len_fp > #2
+    \l_@@_tmpc_fp > #2
   }
   {
   
-    \fp_set:Nn \l_@@_shorten_len_fp
+    \fp_set:Nn \l_@@_tmpc_fp
     {
-      #2/ \l_@@_shorten_len_fp
+      #2/ \l_@@_tmpc_fp
     }
 
-    \tl_if_eq:NNTF \l_@@_shorten_fa_tl \c_spath_curvetoa_tl
+    \tl_if_eq:NNTF \l_@@_tmpb_tl \c_spath_curvetoa_tl
     {
-      \fp_set:Nn \l_@@_shorten_len_fp
-      {
-        \l_@@_shorten_len_fp/3
-      }
       \spath_split_curve:NNVV
-      \l_@@_shorten_lasta_tl
-      \l_@@_shorten_lastb_tl
-      \l_@@_shorten_last_tl
-      \l_@@_shorten_len_fp
+      \l_@@_tmpc_tl
+      \l_@@_tmpd_tl
+      \l_@@_tmpe_tl
+      \l_@@_tmpc_fp
     }
     {
       \spath_split_line:NNVV
-      \l_@@_shorten_lasta_tl
-      \l_@@_shorten_lastb_tl
-      \l_@@_shorten_last_tl
-      \l_@@_shorten_len_fp
+      \l_@@_tmpc_tl
+      \l_@@_tmpd_tl
+      \l_@@_tmpe_tl
+      \l_@@_tmpc_fp
     }
 
     \prg_replicate:nn {2}
     {
-      \tl_set:Nx \l_@@_shorten_path_tl {\tl_tail:N \l_@@_shorten_path_tl}
+      \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
     }
 
-    \tl_put_left:NV \l_@@_shorten_path_tl \l_@@_shorten_lastb_tl
+    \tl_put_left:NV \l_@@_tmpa_tl \l_@@_tmpd_tl
 
   }
   {
 
-    \tl_put_left:NV \l_@@_shorten_path_tl \c_spath_moveto_tl
+    \tl_put_left:NV \l_@@_tmpa_tl \c_spath_moveto_tl
     
     \int_compare:nT
     {
-      \tl_count:N \l_@@_shorten_path_tl > 3
+      \tl_count:N \l_@@_tmpa_tl > 3
     }
     {
-      \dim_set:Nn \l_@@_tmpa_dim {\fp_to_dim:n {#2 - \l_@@_shorten_len_fp } }
-      \spath_shorten_at_start:NV \l_@@_shorten_path_tl \l_@@_tmpa_dim
+      \dim_set:Nn \l_@@_tmpa_dim {\fp_to_dim:n {#2 - \l_@@_tmpc_fp } }
+      \spath_shorten_at_start:NV \l_@@_tmpa_tl \l_@@_tmpa_dim
     }
   }
 
-  \tl_gset_eq:NN \g_@@_output_tl \l_@@_shorten_path_tl
+  \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpa_tl
   \group_end:
   }
   {
@@ -2655,7 +3353,7 @@
 %
 % \subsection{Points on a Path}
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_point_at:Nnn,
 % \spath_gpoint_at:Nnn,
 % }
@@ -2687,7 +3385,9 @@
     }
     {
   
-      \tl_set:Nx \l_@@_tmpa_tl {\seq_item:Nn \l_@@_tmpa_seq { \l_@@_tmpa_int} }
+      \tl_set:Nx
+      \l_@@_tmpa_tl
+      {\seq_item:Nn \l_@@_tmpa_seq { \l_@@_tmpa_int} }
 
       \int_compare:nTF
       {
@@ -2765,11 +3465,21 @@
           {
             {\fp_to_dim:n
               {
-                (1 - \l_@@_tmpa_fp)^3 * \tl_item:Nn \l_@@_tmpa_tl {2} + 3 * (1 - \l_@@_tmpa_fp)^2 * (\l_@@_tmpa_fp) * \tl_item:Nn \l_@@_tmpa_tl {5} + 3 * (1 - \l_@@_tmpa_fp) * (\l_@@_tmpa_fp)^2 * \tl_item:Nn \l_@@_tmpa_tl {8} + (\l_@@_tmpa_fp)^3 * \tl_item:Nn \l_@@_tmpa_tl {11}
+                (1 - \l_@@_tmpa_fp)^3 * \tl_item:Nn \l_@@_tmpa_tl {2}
+                + 3 * (1 - \l_@@_tmpa_fp)^2 * (\l_@@_tmpa_fp)
+                * \tl_item:Nn \l_@@_tmpa_tl {5}
+                + 3 * (1 - \l_@@_tmpa_fp) * (\l_@@_tmpa_fp)^2
+                * \tl_item:Nn \l_@@_tmpa_tl {8}
+                + (\l_@@_tmpa_fp)^3 * \tl_item:Nn \l_@@_tmpa_tl {11}
             }}
             {\fp_to_dim:n
               {
-                (1 - \l_@@_tmpa_fp)^3 * \tl_item:Nn \l_@@_tmpa_tl {3} + 3 * (1 - \l_@@_tmpa_fp)^2 * (\l_@@_tmpa_fp) * \tl_item:Nn \l_@@_tmpa_tl {6} + 3 * (1 - \l_@@_tmpa_fp) * (\l_@@_tmpa_fp)^2 * \tl_item:Nn \l_@@_tmpa_tl {9} + (\l_@@_tmpa_fp)^3 * \tl_item:Nn \l_@@_tmpa_tl {12}
+                (1 - \l_@@_tmpa_fp)^3 * \tl_item:Nn \l_@@_tmpa_tl {3}
+                + 3 * (1 - \l_@@_tmpa_fp)^2 * (\l_@@_tmpa_fp)
+                * \tl_item:Nn \l_@@_tmpa_tl {6}
+                + 3 * (1 - \l_@@_tmpa_fp) * (\l_@@_tmpa_fp)^2
+                * \tl_item:Nn \l_@@_tmpa_tl {9}
+                + (\l_@@_tmpa_fp)^3 * \tl_item:Nn \l_@@_tmpa_tl {12}
             }}
           }
         }
@@ -2799,7 +3509,7 @@
 % \end{macro}
 %
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_tangent_at:Nnn,
 % \spath_gtangent_at:Nnn,
 % }
@@ -2831,7 +3541,9 @@
     }
     {
   
-      \tl_set:Nx \l_@@_tmpa_tl {\seq_item:Nn \l_@@_tmpa_seq { \l_@@_tmpa_int} }
+      \tl_set:Nx
+      \l_@@_tmpa_tl
+      {\seq_item:Nn \l_@@_tmpa_seq { \l_@@_tmpa_int} }
 
       \int_compare:nTF
       {
@@ -2909,16 +3621,24 @@
           {
             {\fp_to_dim:n
               {
-                3*(1 - \l_@@_tmpa_fp)^2 * (\tl_item:Nn \l_@@_tmpa_tl {5} - \tl_item:Nn \l_@@_tmpa_tl {2})
-                + 6 * (1 - \l_@@_tmpa_fp) * (\l_@@_tmpa_fp) *  (\tl_item:Nn \l_@@_tmpa_tl {8} - \tl_item:Nn \l_@@_tmpa_tl {5})
-                + 3*(\l_@@_tmpa_fp)^2 * (\tl_item:Nn \l_@@_tmpa_tl {11} - \tl_item:Nn \l_@@_tmpa_tl {8})
+                3*(1 - \l_@@_tmpa_fp)^2 * (\tl_item:Nn \l_@@_tmpa_tl {5}
+                - \tl_item:Nn \l_@@_tmpa_tl {2})
+                + 6 * (1 - \l_@@_tmpa_fp) * (\l_@@_tmpa_fp) *
+                (\tl_item:Nn \l_@@_tmpa_tl {8}
+                - \tl_item:Nn \l_@@_tmpa_tl {5})
+                + 3*(\l_@@_tmpa_fp)^2 * (\tl_item:Nn \l_@@_tmpa_tl {11}
+                - \tl_item:Nn \l_@@_tmpa_tl {8})
               }
             }
             {\fp_to_dim:n
               {
-                3*(1 - \l_@@_tmpa_fp)^2 * (\tl_item:Nn \l_@@_tmpa_tl {6} - \tl_item:Nn \l_@@_tmpa_tl {3})
-                + 6 * (1 - \l_@@_tmpa_fp) * (\l_@@_tmpa_fp) *  (\tl_item:Nn \l_@@_tmpa_tl {9} - \tl_item:Nn \l_@@_tmpa_tl {6})
-                + 3*(\l_@@_tmpa_fp)^2 * (\tl_item:Nn \l_@@_tmpa_tl {12} - \tl_item:Nn \l_@@_tmpa_tl {9})
+                3*(1 - \l_@@_tmpa_fp)^2 * (\tl_item:Nn \l_@@_tmpa_tl {6}
+                - \tl_item:Nn \l_@@_tmpa_tl {3})
+                + 6 * (1 - \l_@@_tmpa_fp) * (\l_@@_tmpa_fp) *
+                (\tl_item:Nn \l_@@_tmpa_tl {9}
+                - \tl_item:Nn \l_@@_tmpa_tl {6})
+                + 3*(\l_@@_tmpa_fp)^2 * (\tl_item:Nn \l_@@_tmpa_tl {12}
+                - \tl_item:Nn \l_@@_tmpa_tl {9})
             }}
           }
         }
@@ -2948,7 +3668,7 @@
 % \end{macro}
 %
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_transformation_at:Nnn,
 % \spath_gtransformation_at:Nnn
 % }
@@ -2960,7 +3680,14 @@
   \tl_clear:N \l_@@_tmpa_tl
   \@@_tangent_at:nn {#1}{#2}
   \tl_set_eq:NN \l_@@_tmpb_tl \g_@@_output_tl
-  \fp_set:Nn \l_@@_tmpa_fp { sqrt( (\tl_item:Nn \l_@@_tmpb_tl {1})^2 +  (\tl_item:Nn \l_@@_tmpb_tl {2})^2 ) }
+  \fp_set:Nn \l_@@_tmpa_fp
+  {
+    sqrt(
+    (\tl_item:Nn \l_@@_tmpb_tl {1})^2
+    +
+    (\tl_item:Nn \l_@@_tmpb_tl {2})^2
+    )
+  }
   \fp_compare:nTF {\l_@@_tmpa_fp = 0}
   {
     \fp_set:Nn \l_@@_tmpa_fp {1}
@@ -2967,8 +3694,10 @@
     \fp_set:Nn \l_@@_tmpb_fp {0}
   }
   {
-    \fp_set:Nn \l_@@_tmpb_fp { (\tl_item:Nn \l_@@_tmpb_tl {2}) / \l_@@_tmpa_fp }
-    \fp_set:Nn \l_@@_tmpa_fp { (\tl_item:Nn \l_@@_tmpb_tl {1}) / \l_@@_tmpa_fp }
+    \fp_set:Nn \l_@@_tmpb_fp
+    { (\tl_item:Nn \l_@@_tmpb_tl {2}) / \l_@@_tmpa_fp }
+    \fp_set:Nn \l_@@_tmpa_fp
+    { (\tl_item:Nn \l_@@_tmpb_tl {1}) / \l_@@_tmpa_fp }
   }
   \tl_set:Nx \l_@@_tmpa_tl
   {
@@ -3005,26 +3734,7 @@
 % The intersection library is 0-based, but the user interface is 1-based (since if we ``count'' in a \Verb+\foreach+ then it starts at 1).
 % This should be more consistent.
 %
-%    \begin{macrocode}
-\tl_new:N \l_@@_split_path_a_tl
-\tl_new:N \l_@@_split_path_b_tl
-\tl_new:N \l_@@_split_path_a_start_tl
-\tl_new:N \l_@@_split_path_b_start_tl
-\tl_new:N \l_@@_split_path_a_end_tl
-\tl_new:N \l_@@_split_path_b_end_tl
-\tl_new:N \l_@@_split_path_a_final_tl
-\tl_new:N \l_@@_split_path_b_final_tl
-
-\tl_new:N \l_@@_split_prev_first_tl
-\tl_new:N \l_@@_split_prev_second_tl
-
-\seq_new:N \l_@@_split_first_seq
-\seq_new:N \l_@@_split_second_seq
-
-\int_new:N \l_@@_split_segment_int
-%    \end{macrocode}
-%
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_intersect:NN,
 % \spath_intersect:nn,
 % }
@@ -3039,8 +3749,6 @@
     \pgfsetpath #2
   }
 }
-\tl_new:N \l_@@_intersecta_tl
-\tl_new:N \l_@@_intersectb_tl
 \cs_new_protected_nopar:Npn \spath_intersect:nn #1#2
 {
   \tl_set:Nn \l_@@_intersecta_tl {#1}
@@ -3050,154 +3758,220 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{
-% \spath_split_at_intersections:NNnn,
-% \spath_split_at_intersections:NN,
-% \spath_gsplit_at_intersections:NNnn,
-% \spath_gsplit_at_intersections:NN
+% \begin{macro}[internal]{
+% \spath_split_component_at_intersections:Nnn
 % }
-% Given two paths, split them at points where they intersect and store them in the macros.
+% Split a component where it intersects a path.
+% Key assumption is that the first path is a single component, so if it is closed then the end joins up to the beginning.
+% The component is modified but the path is not.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_split_at_intersections:nn #1#2
+\cs_new_protected_nopar:Npn \@@_split_component_at_intersections:nn #1#2
 {
   \group_begin:
-
-  % Clear some token lists and sequences
-  \tl_clear:N \l_@@_split_path_a_final_tl
-  \tl_clear:N \l_@@_split_path_b_final_tl
-  \seq_clear:N \l_@@_split_first_seq
-  \seq_clear:N \l_@@_split_second_seq
+  \tl_clear:N \l_@@_tmpe_tl
+  \seq_clear:N \l_@@_tmpb_seq
   
-  \pgfintersectionsortbyfirstpath
   % Find the intersections of these segments
-  \tl_set:Nn \l_@@_split_path_a_tl {#1}
-  \tl_set:Nn \l_@@_split_path_b_tl {#2}
-  % Remove empty components
-%  \spath_path_remove_empty_components:N \l_@@_split_path_a_tl
-%  \spath_path_remove_empty_components:N \l_@@_split_path_b_tl
+  \tl_set:Nn \l_@@_tmpb_tl {#1}
+  \tl_set:Nn \l_@@_tmpc_tl {#2}
 
-  \spath_intersect:NN \l_@@_split_path_a_tl \l_@@_split_path_b_tl
+  \spath_reallength:Nn \l_@@_tmpa_int {#1}
   
-  % If we get intersections
-  \int_compare:nT {\pgfintersectionsolutions > 0}
+  % Remember if the component is closed
+  \spath_finalaction:NV \l_@@_tmpa_tl \l_@@_tmpb_tl
+  
+  \bool_set:Nn \l_@@_closed_bool
   {
-    % Find the times of the intersections on each path
-    \int_step_inline:nnnn {1} {1} {\pgfintersectionsolutions}
-    {
-    \pgfintersectiongetsolutiontimes{##1}{\l_@@_split_first_tl}{\l_@@_split_second_tl}
-      \seq_put_left:NV \l_@@_split_first_seq \l_@@_split_first_tl
-    }
+    \tl_if_eq_p:NN \l_@@_tmpa_tl \c_spath_closepath_tl
   }
 
-  \spath_intersect:NN \l_@@_split_path_b_tl \l_@@_split_path_a_tl
+  % Open it
+  \spath_open:N \l_@@_tmpb_tl
+
+  % Sort intersections along the component
+  \pgfintersectionsortbyfirstpath
+  \spath_intersect:NN \l_@@_tmpb_tl \l_@@_tmpc_tl
   
   % If we get intersections
   \int_compare:nT {\pgfintersectionsolutions > 0}
   {
-    % Find the times of the intersections on each path
+    % Find the times of the intersections on the component
     \int_step_inline:nnnn {1} {1} {\pgfintersectionsolutions}
     {
-    \pgfintersectiongetsolutiontimes{##1}{\l_@@_split_first_tl}{\l_@@_split_second_tl}
-      \seq_put_left:NV \l_@@_split_second_seq \l_@@_split_first_tl
+      \pgfintersectiongetsolutiontimes{##1}{\l_@@_tmph_tl}{\l_@@_tmpi_tl}
+      \seq_put_left:NV \l_@@_tmpb_seq \l_@@_tmph_tl
     }
-  }
 
-  \tl_set:Nn \l_@@_split_prev_first_tl {-1}
-
-  \seq_map_inline:Nn \l_@@_split_first_seq
-  {
-    \tl_set:Nn \l_@@_split_first_tl {##1}
-    
-    \tl_set_eq:NN \l_@@_tmpa_tl \l_@@_split_first_tl
-    \int_compare:nT
+    \seq_get_left:NN \l_@@_tmpb_seq \l_@@_tmpa_tl
+    \fp_compare:nT
     {
-      \fp_to_int:n {floor( \l_@@_split_first_tl) }
-      =
-      \fp_to_int:n {floor( \l_@@_split_prev_first_tl) }
+      \l_@@_tmpa_tl > \l_@@_tmpa_int - .01
     }
     {
-      \tl_set:Nx \l_@@_split_first_tl
-      {
-        \fp_eval:n {
-          floor( \l_@@_split_first_tl )
-          +
-          ( \l_@@_split_first_tl - floor( \l_@@_split_first_tl) )
-          /
-          ( \l_@@_split_prev_first_tl - floor( \l_@@_split_prev_first_tl) )
-        }
-      }
+      \bool_set_false:N \l_@@_closed_bool
     }
-    \tl_set_eq:NN \l_@@_split_prev_first_tl \l_@@_tmpa_tl
+    \seq_get_right:NN \l_@@_tmpb_seq \l_@@_tmpa_tl
+    \fp_compare:nT
+    {
+      \l_@@_tmpa_tl < .01
+    }
+    {
+      \bool_set_false:N \l_@@_closed_bool
+    }
+
     
-    \spath_split_at:NNVV \l_@@_split_path_a_start_tl \l_@@_split_path_a_end_tl  \l_@@_split_path_a_tl \l_@@_split_first_tl
-    
-    \tl_put_left:NV \l_@@_split_path_a_final_tl \l_@@_split_path_a_end_tl
-    \tl_set_eq:NN \l_@@_split_path_a_tl \l_@@_split_path_a_start_tl
-    
-  }
-    
-  \tl_set:Nn \l_@@_split_prev_second_tl {-1}
+    \tl_set:Nn \l_@@_tmpg_tl {-1}
 
-  \seq_map_inline:Nn \l_@@_split_second_seq
-  {
-    \tl_set:Nn \l_@@_split_second_tl {##1}
+    \seq_map_inline:Nn \l_@@_tmpb_seq
+    {
+      \tl_set:Nn \l_@@_tmph_tl {##1}
     
-    \tl_set_eq:NN \l_@@_tmpa_tl \l_@@_split_second_tl
-    \int_compare:nT
-    {
-      \fp_to_int:n {floor( \l_@@_split_second_tl) }
-      =
-      \fp_to_int:n {floor( \l_@@_split_prev_second_tl) }
-    }
-    {
-      \tl_set:Nx \l_@@_split_second_tl
+      \tl_set_eq:NN \l_@@_tmpa_tl \l_@@_tmph_tl
+      \int_compare:nT
       {
-        \fp_eval:n {
-          floor( \l_@@_split_second_tl )
-          +
-          ( \l_@@_split_second_tl - floor( \l_@@_split_second_tl) )
-          /
-          ( \l_@@_split_prev_second_tl - floor( \l_@@_split_prev_second_tl) )
+        \fp_to_int:n {floor( \l_@@_tmph_tl) }
+        =
+        \fp_to_int:n {floor( \l_@@_tmpg_tl) }
+      }
+      {
+        \tl_set:Nx \l_@@_tmph_tl
+        {
+          \fp_eval:n {
+            floor( \l_@@_tmph_tl )
+            +
+            ( \l_@@_tmph_tl - floor( \l_@@_tmph_tl) )
+            /
+            ( \l_@@_tmpg_tl - floor( \l_@@_tmpg_tl) )
+          }
         }
       }
+      \tl_set_eq:NN \l_@@_tmpg_tl \l_@@_tmpa_tl
+    
+      \spath_split_at:NNVV
+      \l_@@_tmpd_tl
+      \l_@@_tmpf_tl
+      \l_@@_tmpb_tl
+      \l_@@_tmph_tl
+    
+      \tl_put_left:NV \l_@@_tmpe_tl \l_@@_tmpf_tl
+      \tl_set_eq:NN \l_@@_tmpb_tl \l_@@_tmpd_tl
+    
     }
-    \tl_set_eq:NN \l_@@_split_prev_second_tl \l_@@_tmpa_tl
 
-    \spath_split_at:NNVV \l_@@_split_path_b_start_tl \l_@@_split_path_b_end_tl  \l_@@_split_path_b_tl\l_@@_split_second_tl
-      
-    \tl_put_left:NV \l_@@_split_path_b_final_tl \l_@@_split_path_b_end_tl
-    \tl_set_eq:NN \l_@@_split_path_b_tl \l_@@_split_path_b_start_tl
-    
-  }
 
-  \tl_put_left:NV \l_@@_split_path_a_final_tl \l_@@_split_path_a_tl
-  \tl_put_left:NV \l_@@_split_path_b_final_tl \l_@@_split_path_b_tl
+    \tl_put_left:NV \l_@@_tmpe_tl \l_@@_tmpb_tl
+  
+    \spath_remove_empty_components:N \l_@@_tmpe_tl
 
-  \tl_if_empty:NT \l_@@_split_path_a_final_tl
-  {
-    \tl_set_eq:NN \l_@@_split_path_a_final_tl \l_@@_split_path_a_tl
+    \tl_set_eq:NN \l_@@_tmpb_tl \l_@@_tmpe_tl
   }
-  \tl_if_empty:NT \l_@@_split_path_b_final_tl
+
+  \bool_if:NT \l_@@_closed_bool
   {
-    \tl_set_eq:NN \l_@@_split_path_b_final_tl \l_@@_split_path_b_tl
+    \spath_join_component:Nn \l_@@_tmpb_tl {1}
   }
+
+  \tl_gclear:N \g_@@_output_tl
+  \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpb_tl
   
-  \spath_remove_empty_components:N \l_@@_split_path_a_final_tl
-  \spath_remove_empty_components:N \l_@@_split_path_b_final_tl
+  \group_end:
+}
+\cs_new_protected_nopar:Npn \spath_split_component_at_intersections:Nnn #1#2#3
+{
+  \@@_split_component_at_intersections:nn {#2}{#3}
+  \tl_set_eq:NN #1 \g_@@_output_tl
+  \tl_gclear:N \g_@@_output_tl
+}
+\cs_generate_variant:Nn \spath_split_component_at_intersections:Nnn {NVn, NVV}
+\cs_new_protected_nopar:Npn \spath_split_component_at_intersections:Nn #1#2
+{
+  \spath_split_component_at_intersections:NVn #1#1{#2}
+}
+\cs_generate_variant:Nn \spath_split_component_at_intersections:Nn {cn, cv}
+\cs_new_protected_nopar:Npn \spath_gsplit_component_at_intersections:Nnn #1#2#3
+{
+  \@@_split_component_at_intersections:nn {#2}{#3}
+  \tl_gset_eq:NN #1 \g_@@_output_tl
+  \tl_gclear:N \g_@@_output_tl
+}
+\cs_generate_variant:Nn \spath_gsplit_component_at_intersections:Nnn {NVn, NVV}
+\cs_new_protected_nopar:Npn \spath_gsplit_component_at_intersections:Nn #1#2
+{
+  \spath_gsplit_component_at_intersections:NVn #1#1{#2}
+}
+\cs_generate_variant:Nn \spath_gsplit_component_at_intersections:Nn {cn, cv}
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}[internal]{
+% \spath_split_path_at_intersections:Nnn,
+% \spath_split_path_at_intersections:Nn,
+% \spath_gsplit_path_at_intersections:Nnn,
+% \spath_gsplit_path_at_intersections:Nn,
+% \spath_split_at_intersections:NNnn,
+% \spath_split_at_intersections:NN,
+% \spath_gsplit_at_intersections:NNnn,
+% \spath_gsplit_at_intersections:NN,
+% }
+% Split paths at their intersections.
+% The \Verb+path+ versions only split the first path.
+% The others split both paths.
+%    \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_split_path_at_intersections:nn #1#2
+{
+  \group_begin:
+
+  \seq_clear:N \l_@@_tmpa_seq
+  \seq_clear:N \l_@@_tmpb_seq
   
+  \spath_components_to_seq:Nn \l_@@_tmpa_seq {#1}
+  \seq_map_inline:Nn \l_@@_tmpa_seq
+  {
+    \spath_split_component_at_intersections:Nnn \l_@@_tmpa_tl {##1} {#2}
+    \seq_put_right:NV \l_@@_tmpb_seq \l_@@_tmpa_tl
+  }
+
   \tl_gclear:N \g_@@_output_tl
-  \@@_tl_gput_right_braced:NV \g_@@_output_tl \l_@@_split_path_a_final_tl
-  \@@_tl_gput_right_braced:NV \g_@@_output_tl \l_@@_split_path_b_final_tl
+  \tl_gset:Nx \g_@@_output_tl {\seq_use:Nn \l_@@_tmpb_seq {} }
   \group_end:
 }
+\cs_new_protected_nopar:Npn \spath_split_path_at_intersections:Nnn #1#2#3
+{
+  \@@_split_path_at_intersections:nn {#2}{#3}
+  \tl_set_eq:NN #1 \g_@@_output_tl
+  \tl_gclear:N \g_@@_output_tl
+}
+\cs_generate_variant:Nn \spath_split_path_at_intersections:Nnn
+{NVn, NVV, cVn, cVV, cvn, cvv}
+\cs_new_protected_nopar:Npn \spath_split_path_at_intersections:Nn #1#2
+{
+  \spath_split_path_at_intersections:NVn #1#1{#2}
+}
+\cs_generate_variant:Nn \spath_split_path_at_intersections:Nn {cv, NV}
+\cs_new_protected_nopar:Npn \spath_gsplit_path_at_intersections:Nnn #1#2#3
+{
+  \@@_split_path_at_intersections:nn {#2}{#3}
+  \tl_gset_eq:NN #1 \g_@@_output_tl
+  \tl_gclear:N \g_@@_output_tl
+}
+\cs_generate_variant:Nn \spath_gsplit_path_at_intersections:Nnn
+{NVn, NVV, cVn, cVV, cvn, cvv}
+\cs_new_protected_nopar:Npn \spath_gsplit_path_at_intersections:Nn #1#2
+{
+  \spath_gsplit_path_at_intersections:NVn #1#1{#2}
+}
+\cs_generate_variant:Nn \spath_gsplit_path_at_intersections:Nn {cv, NV}
 \cs_new_protected_nopar:Npn \spath_split_at_intersections:NNnn #1#2#3#4
 {
-  \@@_split_at_intersections:nn {#3}{#4}
-  \tl_set:Nx #1 {\tl_item:Nn \g_@@_output_tl {1}}
-  \tl_set:Nx #2 {\tl_item:Nn \g_@@_output_tl {2}}
+  \@@_split_path_at_intersections:nn {#3}{#4}
+  \tl_set_eq:NN #1 \g_@@_output_tl
+  \@@_split_path_at_intersections:nn {#4}{#3}
+  \tl_set_eq:NN #2 \g_@@_output_tl
   \tl_gclear:N \g_@@_output_tl
 }
-\cs_generate_variant:Nn \spath_split_at_intersections:NNnn {NNVV, ccVV, ccvv}
+\cs_generate_variant:Nn \spath_split_at_intersections:NNnn
+{NNVn, NNVV, ccVn, ccVV, ccvn, ccvv}
 \cs_new_protected_nopar:Npn \spath_split_at_intersections:NN #1#2
 {
   \spath_split_at_intersections:NNVV #1#2#1#2
@@ -3205,12 +3979,14 @@
 \cs_generate_variant:Nn \spath_split_at_intersections:NN {cc}
 \cs_new_protected_nopar:Npn \spath_gsplit_at_intersections:NNnn #1#2#3#4
 {
-  \@@_split_at_intersections:nn {#3}{#4}
-  \tl_gset:Nx #1 {\tl_item:Nn \g_@@_output_tl {1}}
-  \tl_gset:Nx #2 {\tl_item:Nn \g_@@_output_tl {2}}
+  \@@_split_path_at_intersections:nn {#3}{#4}
+  \tl_gset_eq:NN #1 \g_@@_output_tl
+  \@@_split_path_at_intersections:nn {#4}{#3}
+  \tl_gset_eq:NN #2 \g_@@_output_tl
   \tl_gclear:N \g_@@_output_tl
 }
-\cs_generate_variant:Nn \spath_gsplit_at_intersections:NNnn {NNVV, ccVV, ccvv}
+\cs_generate_variant:Nn \spath_gsplit_at_intersections:NNnn
+{NNVn, NNVV, ccVn, ccVV, ccvn, ccvv}
 \cs_new_protected_nopar:Npn \spath_gsplit_at_intersections:NN #1#2
 {
   \spath_gsplit_at_intersections:NNVV #1#2#1#2
@@ -3219,144 +3995,116 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{
-% \spath_split_at_self_intersections:Nn,
-% \spath_split_at_self_intersections:N,
-% \spath_gsplit_at_self_intersections:Nn,
-% \spath_gsplit_at_self_intersections:N,
+%
+% \begin{macro}[internal]{
+% \spath_split_component_at_self_intersections:Nn,
+% \spath_split_component_at_self_intersections:N,
+% \spath_gsplit_component_at_self_intersections:Nn,
+% \spath_gsplit_component_at_self_intersections:N,
 % }
-% Given a path, split it at points where it self-intersects and store in the given macro.
+% Given a component of a path, split it at points where it self-intersects.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_split_at_self_intersections:n #1
+\cs_new_protected_nopar:Npn \@@_split_component_at_self_intersections:n #1
 {
   \group_begin:
+  \tl_set:Nn \l_@@_tmpe_tl {#1}
+
+  % Remember if the component is closed
+  \spath_finalaction:NV \l_@@_tmpa_tl \l_@@_tmpe_tl
+
+  \bool_set:Nn \l_@@_closed_bool
+  {
+    \tl_if_eq_p:NN \l_@@_tmpa_tl \c_spath_closepath_tl
+  }
   
   % Copy the path
-  \tl_set:Nn \l_@@_split_path_b_tl {#1}
+  \tl_set:Nn \l_@@_tmpe_tl {#1}
 
   % Open the path
-  \spath_open:N \l_@@_split_path_b_tl
-  % Remove empty components
-  \spath_remove_empty_components:N \l_@@_split_path_b_tl
+  \spath_open:N \l_@@_tmpe_tl
+  % Ensure beziers don't self-intersect
+  \spath_split_curves:N \l_@@_tmpe_tl
+
   % Make a copy for later
-  \tl_set_eq:NN \l_@@_split_path_b_final_tl \l_@@_split_path_b_tl
+  \tl_set_eq:NN \l_@@_tmpg_tl \l_@@_tmpe_tl
   
   % Clear some token lists and sequences
-  \tl_clear:N \l_@@_split_path_a_tl
-  \seq_clear:N \l_@@_split_first_seq
-  \int_zero:N \l_@@_split_segment_int
+  \tl_clear:N \l_@@_tmpd_tl
+  \seq_clear:N \l_@@_tmpb_seq
+  \int_zero:N \l_@@_tmpa_int
 
   \pgfintersectionsortbyfirstpath
 
-  \bool_do_until:nn
+  % Split the path into a sequence of segments
+  \spath_segments_to_seq:NV \l_@@_tmpa_seq \l_@@_tmpe_tl
+
+  \seq_map_indexed_inline:Nn \l_@@_tmpa_seq
   {
-    \int_compare_p:n
+    \seq_map_indexed_inline:Nn \l_@@_tmpa_seq
     {
-      \tl_count:N \l_@@_split_path_b_tl < 4
-    }
-  }
-  {
-    \tl_clear:N \l_@@_split_path_a_tl
-    \tl_put_right:Nx \l_@@_split_path_a_tl
-    {
-      \tl_item:Nn \l_@@_split_path_b_tl {1}
-      {\tl_item:Nn \l_@@_split_path_b_tl {2}}
-      {\tl_item:Nn \l_@@_split_path_b_tl {3}}
-    }
-
-    \tl_set:Nx \l_@@_tmpa_tl { \tl_item:Nn \l_@@_split_path_b_tl {4} }
-
-    \tl_set:Nx \l_@@_split_path_b_tl {\tl_tail:N \l_@@_split_path_b_tl}
-
-    \int_zero:N \l_@@_tmpa_int
-    
-    \tl_case:Nn \l_@@_tmpa_tl
-    {
-      \c_spath_moveto_tl
+      % Don't intersect a segment with itself
+      \int_compare:nF
       {
-        \tl_clear:N \l_@@_split_path_a_tl
-        \tl_set:Nx \l_@@_split_path_b_tl {\tl_tail:N \l_@@_split_path_b_tl}
-        \tl_set:Nx \l_@@_split_path_b_tl {\tl_tail:N \l_@@_split_path_b_tl}
-        \tl_set:Nx \l_@@_split_path_b_tl {\tl_tail:N \l_@@_split_path_b_tl}
+        ##1 == ####1
       }
-      \c_spath_lineto_tl
       {
-        \int_set:Nn \l_@@_tmpa_int {1}
-      }
-      \c_spath_curvetoa_tl
-      {
-        \int_set:Nn \l_@@_tmpa_int {3}
-      }
-    }
-
-    \prg_replicate:nn { \l_@@_tmpa_int }
-    {
-      \tl_set:Nx \l_@@_split_path_b_tl {\tl_tail:N \l_@@_split_path_b_tl}
-      \tl_set:Nx \l_@@_split_path_b_tl {\tl_tail:N \l_@@_split_path_b_tl}
-      
-      \tl_put_right:Nx \l_@@_split_path_a_tl
-      {
-        \tl_item:Nn \l_@@_split_path_b_tl {1}
-        {\tl_item:Nn \l_@@_split_path_b_tl {2}}
-        {\tl_item:Nn \l_@@_split_path_b_tl {3}}
-      }
-
-      \tl_set:Nx \l_@@_split_path_b_tl {\tl_tail:N \l_@@_split_path_b_tl}
-    }
-    
-    \tl_put_left:NV \l_@@_split_path_b_tl \c_spath_moveto_tl
-
-    \tl_if_empty:NF \l_@@_split_path_a_tl
-    {
-      % Intersect the current segment with the rest of the path
-      \spath_intersect:NN \l_@@_split_path_a_tl \l_@@_split_path_b_tl
-
-
-      % If we get intersections
-      \int_compare:nT {\pgfintersectionsolutions > 0}
-      {
-        % Find the times of the intersections on each path
-        \int_step_inline:nnnn {1} {1} {\pgfintersectionsolutions}
+        \spath_intersect:nn {##2} {####2}
+        
+        \int_compare:nT {\pgfintersectionsolutions > 0}
         {
-          \pgfintersectiongetsolutiontimes{##1}{\l_@@_split_first_tl}{\l_@@_split_second_tl}
-          \fp_compare:nT
+          % Find the times of the intersections on each path
+          \int_step_inline:nnnn {1} {1} {\pgfintersectionsolutions}
           {
-            \l_@@_split_first_tl < .99
+            \pgfintersectiongetsolutiontimes
+            {########1}{\l_@@_tmpb_tl}{\l_@@_tmpc_tl}
+            
+            \bool_if:nT
+            {
+              !(
+              \fp_compare_p:n { \l_@@_tmpb_tl > .99 }
+              &&
+              \int_compare_p:n {##1 + 1 == ####1}
+              )
+              &&
+              !(
+              \fp_compare_p:n { \l_@@_tmpb_tl < .01 }
+              &&
+              \int_compare_p:n {##1 - 1 == ####1}
+              )
+              &&
+              !(
+              \l_@@_closed_bool
+              &&
+              \fp_compare_p:n { \l_@@_tmpb_tl < .01 }
+              &&
+              \int_compare_p:n {##1 == 1}
+              &&
+              \int_compare_p:n {\seq_count:N \l_@@_tmpa_seq == ####1}
+              )
+              &&
+              !(
+              \l_@@_closed_bool
+              &&
+              \fp_compare_p:n { \l_@@_tmpb_tl > .99 }
+              &&
+              \int_compare_p:n {####1 == 1}
+              &&
+              \int_compare_p:n {\seq_count:N \l_@@_tmpa_seq == ##1}
+              )
+            }
+            {
+              \tl_set:Nx \l_@@_tmpa_tl
+              {\fp_to_decimal:n {\l_@@_tmpb_tl +  ##1 - 1}}
+              \seq_put_right:NV \l_@@_tmpb_seq \l_@@_tmpa_tl
+            }
           }
-          {
-            \tl_set:Nx \l_@@_tmpa_tl {\fp_to_decimal:n {\l_@@_split_first_tl +  \l_@@_split_segment_int}}
-            \seq_put_right:NV \l_@@_split_first_seq \l_@@_tmpa_tl
-          }
         }
       }
-
-      \spath_intersect:NN \l_@@_split_path_b_tl \l_@@_split_path_a_tl
-
-      % If we get intersections
-      \int_compare:nT {\pgfintersectionsolutions > 0}
-      {
-        % Find the times of the intersections on each path
-        \int_step_inline:nnnn {1} {1} {\pgfintersectionsolutions}
-        {
-          \pgfintersectiongetsolutiontimes{##1}{\l_@@_split_first_tl}{\l_@@_split_second_tl}
-          \fp_compare:nT
-          {
-            \l_@@_split_first_tl > .01
-          }
-          {
-            \tl_set:Nx \l_@@_tmpa_tl {\fp_to_decimal:n {\l_@@_split_first_tl +  \l_@@_split_segment_int + 1}}
-            \seq_put_right:NV \l_@@_split_first_seq \l_@@_tmpa_tl
-          }
-        }
-      }
-      
     }
-    % Increment the segment counter
-    \int_incr:N \l_@@_split_segment_int
   }
 
   % Sort the sequence by reverse order along the path
-  \seq_sort:Nn \l_@@_split_first_seq
+  \seq_sort:Nn \l_@@_tmpb_seq
   {
     \fp_compare:nNnTF { ##1 } < { ##2 }
     { \sort_return_swapped: }
@@ -3363,60 +4111,170 @@
     { \sort_return_same: }
   }
 
+  \seq_get_left:NN \l_@@_tmpb_seq \l_@@_tmpa_tl
+  \fp_compare:nT
+  {
+    \l_@@_tmpa_tl > \seq_count:N \l_@@_tmpa_seq - .01
+  }
+  {
+    \bool_set_false:N \l_@@_closed_bool
+  }
+  \seq_get_right:NN \l_@@_tmpb_seq \l_@@_tmpa_tl
+  \fp_compare:nT
+  {
+    \l_@@_tmpa_tl < .01
+  }
+  {
+    \bool_set_false:N \l_@@_closed_bool
+  }
+  
   % Restore the original copy of the path
-  \tl_set_eq:NN \l_@@_split_path_b_tl \l_@@_split_path_b_final_tl
+  \tl_set_eq:NN \l_@@_tmpe_tl \l_@@_tmpg_tl
 
   % Clear the token lists
-  \tl_clear:N \l_@@_split_path_b_start_tl
-  \tl_clear:N \l_@@_split_path_b_end_tl
-  \tl_clear:N \l_@@_split_path_b_final_tl
+  \tl_clear:N \l_@@_tmpf_tl
+  \tl_clear:N \l_@@_tmph_tl
+  \tl_clear:N \l_@@_tmpg_tl
 
-  \tl_set:Nn \l_@@_split_prev_first_tl {-1}
+  \tl_set:Nn \l_@@_tmpi_tl {-1}
 
-  \seq_map_inline:Nn \l_@@_split_first_seq
+  \seq_map_inline:Nn \l_@@_tmpb_seq
   {
-    \tl_set:Nn \l_@@_split_first_tl {##1}
-    \tl_set_eq:NN \l_@@_tmpa_tl \l_@@_split_first_tl
+    \tl_set:Nn \l_@@_tmpb_tl {##1}
+    \tl_set_eq:NN \l_@@_tmpa_tl \l_@@_tmpb_tl
     \int_compare:nT
     {
-      \fp_to_int:n {floor( \l_@@_split_first_tl ) }
+      \fp_to_int:n {floor( \l_@@_tmpb_tl ) }
       =
-      \fp_to_int:n {floor( \l_@@_split_prev_first_tl) }
+      \fp_to_int:n {floor( \l_@@_tmpi_tl) }
     }
     {
-      \tl_set:Nx \l_@@_split_first_tl
+      \tl_set:Nx \l_@@_tmpb_tl
       {
         \fp_eval:n {
-          floor( \l_@@_split_first_tl )
+          floor( \l_@@_tmpb_tl )
           +
-          ( \l_@@_split_first_tl - floor( \l_@@_split_first_tl) )
+          ( \l_@@_tmpb_tl - floor( \l_@@_tmpb_tl) )
           /
-          ( \l_@@_split_prev_first_tl - floor( \l_@@_split_prev_first_tl) )
+          ( \l_@@_tmpi_tl - floor( \l_@@_tmpi_tl) )
         }
       }
     }
-    \tl_set_eq:NN \l_@@_split_prev_first_tl \l_@@_tmpa_tl
+    \tl_set_eq:NN \l_@@_tmpi_tl \l_@@_tmpa_tl
 
-    \spath_split_at:NNVV \l_@@_split_path_b_start_tl \l_@@_split_path_b_end_tl  \l_@@_split_path_b_tl \l_@@_split_first_tl
+    \spath_split_at:NNVV
+    \l_@@_tmpf_tl
+    \l_@@_tmph_tl
+    \l_@@_tmpe_tl
+    \l_@@_tmpb_tl
       
-    \tl_put_left:NV \l_@@_split_path_b_final_tl \l_@@_split_path_b_end_tl
-    \tl_set_eq:NN \l_@@_split_path_b_tl \l_@@_split_path_b_start_tl
+    \tl_put_left:NV \l_@@_tmpg_tl \l_@@_tmph_tl
+    \tl_set_eq:NN \l_@@_tmpe_tl \l_@@_tmpf_tl
 
   }
 
-  \tl_put_left:NV \l_@@_split_path_b_final_tl \l_@@_split_path_b_tl
+  \tl_put_left:NV \l_@@_tmpg_tl \l_@@_tmpe_tl
 
-  \tl_if_empty:NT \l_@@_split_path_b_final_tl
+  \tl_if_empty:NT \l_@@_tmpg_tl
   {
-    \tl_set_eq:NN \l_@@_split_path_b_final_tl \l_@@_split_path_b_tl
+    \tl_set_eq:NN \l_@@_tmpg_tl \l_@@_tmpe_tl
   }
 
-  \spath_remove_empty_components:N \l_@@_split_path_b_final_tl
+  \spath_remove_empty_components:N \l_@@_tmpg_tl
+
+  % Do something with closed
+  \bool_if:NT \l_@@_closed_bool
+  {
+    \spath_join_component:Nn \l_@@_tmpg_tl {1}
+  }
   
   \tl_gclear:N \g_@@_output_tl
-  \tl_gset_eq:NN \g_@@_output_tl \l_@@_split_path_b_final_tl
+  \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpg_tl
   \group_end:
 }
+\cs_new_protected_nopar:Npn \spath_split_component_at_self_intersections:Nn #1#2
+{
+  \@@_split_component_at_self_intersections:n {#2}
+  \tl_set_eq:NN #1 \g_@@_output_tl
+  \tl_gclear:N \g_@@_output_tl
+}
+\cs_generate_variant:Nn \spath_split_component_at_self_intersections:Nn {NV}
+\cs_new_protected_nopar:Npn \spath_split_component_at_self_intersections:N #1
+{
+  \spath_split_component_at_self_intersections:NV #1#1
+}
+\cs_generate_variant:Nn \spath_split_component_at_self_intersections:N {c}
+\cs_new_protected_nopar:Npn \spath_gsplit_component_at_self_intersections:Nn #1#2
+{
+  \@@_split_component_at_self_intersections:n {#2}
+  \tl_gset_eq:NN #1 \g_@@_output_tl
+  \tl_gclear:N \g_@@_output_tl
+}
+\cs_generate_variant:Nn \spath_gsplit_component_at_self_intersections:Nn {NV}
+\cs_new_protected_nopar:Npn \spath_gsplit_component_at_self_intersections:N #1
+{
+  \spath_gsplit_component_at_self_intersections:NV #1#1
+}
+\cs_generate_variant:Nn \spath_gsplit_component_at_self_intersections:N {c}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{
+% \spath_split_at_self_intersections:Nn,
+% \spath_split_at_self_intersections:N,
+% \spath_gsplit_at_self_intersections:Nn,
+% \spath_gsplit_at_self_intersections:N,
+% }
+% Split a path at its self intersections.
+% We iterate over the components, splitting each where it meets all the others and itself.
+% To make this more efficient, we split against the components of the original path rather than updating each time.
+%
+%    \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_split_at_self_intersections:n #1
+{
+  \group_begin:
+  \spath_components_to_seq:Nn \l_@@_tmpa_seq {#1}
+  \seq_clear:N \l_@@_tmpb_seq
+  \seq_clear:N \l_@@_tmpc_seq
+
+  % Iterate over the components of the original path.
+  \bool_do_until:nn
+  {
+    \seq_if_empty_p:N \l_@@_tmpa_seq
+  }
+  {
+    % Get the next component
+    \seq_pop_left:NN \l_@@_tmpa_seq \l_@@_tmpa_tl
+    % Copy for later
+    \tl_set_eq:NN \l_@@_tmpc_tl \l_@@_tmpa_tl
+    \int_compare:nT
+    {
+      \tl_count:N \l_@@_tmpa_tl > 3
+    }
+    {
+    
+      % Split against itself
+      \spath_split_component_at_self_intersections:N \l_@@_tmpa_tl
+      % Grab the rest of the path
+      \tl_set:Nx \l_@@_tmpb_tl
+      {
+        \seq_use:Nn \l_@@_tmpb_seq {}
+        \seq_use:Nn \l_@@_tmpa_seq {}
+      }
+      % Split against the rest of the path
+      \spath_split_path_at_intersections:NV \l_@@_tmpa_tl \l_@@_tmpb_tl
+    }
+    % Save the split path
+    \seq_put_right:NV \l_@@_tmpc_seq \l_@@_tmpa_tl
+    % Add the original copy to the sequence of processed components
+    \seq_put_right:NV \l_@@_tmpb_seq \l_@@_tmpc_tl
+  }
+
+  \tl_gclear:N \g_@@_output_tl
+  \tl_gset:Nx \g_@@_output_tl {\seq_use:Nn \l_@@_tmpc_seq {} }
+  \group_end:
+}
+\cs_generate_variant:Nn \@@_split_at_self_intersections:n {V, v}
 \cs_new_protected_nopar:Npn \spath_split_at_self_intersections:Nn #1#2
 {
   \@@_split_at_self_intersections:n {#2}
@@ -3423,7 +4281,7 @@
   \tl_set_eq:NN #1 \g_@@_output_tl
   \tl_gclear:N \g_@@_output_tl
 }
-\cs_generate_variant:Nn \spath_split_at_self_intersections:Nn {NV}
+\cs_generate_variant:Nn \spath_split_at_self_intersections:Nn {NV, cn, cV, cv}
 \cs_new_protected_nopar:Npn \spath_split_at_self_intersections:N #1
 {
   \spath_split_at_self_intersections:NV #1#1
@@ -3435,7 +4293,7 @@
   \tl_gset_eq:NN #1 \g_@@_output_tl
   \tl_gclear:N \g_@@_output_tl
 }
-\cs_generate_variant:Nn \spath_gsplit_at_self_intersections:Nn {NV}
+\cs_generate_variant:Nn \spath_gsplit_at_self_intersections:Nn {NV, cn, cV, cv}
 \cs_new_protected_nopar:Npn \spath_gsplit_at_self_intersections:N #1
 {
   \spath_gsplit_at_self_intersections:NV #1#1
@@ -3444,8 +4302,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-%
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_join_component:Nnn,
 % \spath_join_component:Nn,
 % \spath_gjoin_component:Nnn,
@@ -3453,58 +4310,76 @@
 % }
 % Join the specified component of the spath to its predecessor.
 %    \begin{macrocode}
-\tl_new:N \l_@@_tmpj_tl
 \cs_new_protected_nopar:Npn \@@_join_component:nn #1#2
 {
   \group_begin:
-  \spath_components_to_seq:Nn \l_@@_tmpa_seq {#1}
-  \int_compare:nT
+  \spath_numberofcomponents:Nn \l_@@_tmpa_int {#1}
+
+  \bool_if:nTF
   {
-    #2 == 1
+    \int_compare_p:n { #2 >= 1 }
+    &&
+    \int_compare_p:n { #2 <= \l_@@_tmpa_int }
   }
   {
-    \tl_clear:N \l_@@_tmpj_tl
-    \seq_pop_left:NN \l_@@_tmpa_seq \l_@@_tmpj_tl
-    
-    \prg_replicate:nn {3}
+    \int_compare:nTF
     {
-      \tl_set:Nx \l_@@_tmpj_tl {\tl_tail:N \l_@@_tmpj_tl}
+      #2 == 1
     }
+    {
+      \int_compare:nTF
+      {
+        \l_@@_tmpa_int == 1
+      }
+      {
+        \tl_set:Nn \l_@@_tmpa_tl {#1}
+        \spath_initialpoint:Nn \l_@@_tmpb_tl {#1}
+        \tl_put_right:NV \l_@@_tmpa_tl \c_spath_closepath_tl
+        \tl_put_right:NV \l_@@_tmpa_tl \l_@@_tmpb_tl
+        \tl_gclear:N \g_@@_output_tl
+        \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpa_tl
+      }
+      {
+        \spath_components_to_seq:Nn \l_@@_tmpa_seq {#1}
+        \seq_pop_left:NN \l_@@_tmpa_seq \l_@@_tmpa_tl
+    
+        \prg_replicate:nn {3}
+        {
+          \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
+        }
 
-    \seq_put_right:NV \l_@@_tmpb_seq \l_@@_tmpj_tl
-  }
-  \bool_if:nT
-  {
-    \int_compare_p:n
-    {
-      #2 > 1
+        \seq_put_right:NV \l_@@_tmpa_seq \l_@@_tmpa_tl
+
+        \tl_gclear:N \g_@@_output_tl
+        \tl_gset:Nx \g_@@_output_tl {\seq_use:Nn \l_@@_tmpa_seq {}}
+      }
     }
-    &&
-    \int_compare_p:n
     {
-      #2 <= \seq_count:N \l_@@_tmpa_seq
-    }
-  }
-  {
-
-    \seq_clear:N \l_@@_tmpb_seq
-    \seq_map_indexed_inline:Nn \l_@@_tmpa_seq
-    {
-      \tl_set:Nn \l_@@_tmpj_tl {##2}
-      \int_compare:nT {##1 = #2}
+      \spath_components_to_seq:Nn \l_@@_tmpa_seq {#1}
+      
+      \seq_clear:N \l_@@_tmpb_seq
+      \seq_map_indexed_inline:Nn \l_@@_tmpa_seq
       {
-        \prg_replicate:nn {3}
+        \tl_set:Nn \l_@@_tmpa_tl {##2}
+        \int_compare:nT {##1 = #2}
         {
-          \tl_set:Nx \l_@@_tmpj_tl {\tl_tail:N \l_@@_tmpj_tl}
+          \prg_replicate:nn {3}
+          {
+            \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
+          }
         }
+        \seq_put_right:NV \l_@@_tmpb_seq \l_@@_tmpa_tl
       }
-      \seq_put_right:NV \l_@@_tmpb_seq \l_@@_tmpj_tl
+
+      \tl_gclear:N \g_@@_output_tl
+      \tl_gset:Nx \g_@@_output_tl {\seq_use:Nn \l_@@_tmpb_seq {}}
     }
-
-    \seq_set_eq:NN \l_@@_tmpa_seq \l_@@_tmpb_seq
   }
+  {
+    \tl_gclear:N \g_@@_output_tl
+    \tl_gset:Nn \g_@@_output_tl {#1}
+  }
 
-  \tl_gset:Nx \g_@@_output_tl {\seq_use:Nn \l_@@_tmpa_seq {} }
   \group_end:
 }
 \cs_new_protected_nopar:Npn \spath_join_component:Nnn #1#2#3
@@ -3534,7 +4409,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_spot_weld_components:Nn,
 % \spath_spot_weld_components:N,
 % \spath_spot_gweld_components:Nn,
@@ -3562,12 +4437,16 @@
     {
       \dim_compare_p:n
       {
-        \dim_abs:n {\l_@@_move_x_dim - \tl_item:Nn \l_@@_tmpa_tl {2} } < 0.01pt
+        \dim_abs:n
+        {\l_@@_move_x_dim - \tl_item:Nn \l_@@_tmpa_tl {2} }
+        < 0.01pt
       }
       &&
       \dim_compare_p:n
       {
-        \dim_abs:n {\l_@@_move_y_dim - \tl_item:Nn \l_@@_tmpa_tl {3} } < 0.01pt
+        \dim_abs:n
+        {\l_@@_move_y_dim - \tl_item:Nn \l_@@_tmpa_tl {3} }
+        < 0.01pt
       }
     }
     {
@@ -3595,12 +4474,22 @@
   {
     \dim_compare_p:n
     {
-      \dim_abs:n {\tl_item:Nn \l_@@_tmpa_tl {1} - \tl_item:Nn \l_@@_tmpb_tl {1} } < 0.01pt
+      \dim_abs:n
+      {
+        \tl_item:Nn \l_@@_tmpa_tl {1} - \tl_item:Nn \l_@@_tmpb_tl {1}
+      }
+      <
+      0.01pt
     }
     &&
     \dim_compare_p:n
     {
-      \dim_abs:n {\tl_item:Nn \l_@@_tmpa_tl {2} - \tl_item:Nn \l_@@_tmpb_tl {2} } < 0.01pt
+      \dim_abs:n
+      {
+        \tl_item:Nn \l_@@_tmpa_tl {2} - \tl_item:Nn \l_@@_tmpb_tl {2}
+      }
+      <
+      0.01pt
     }
   }
   {
@@ -3660,7 +4549,7 @@
 %
 % \subsection{Exporting Commands}
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_convert_to_svg:Nn,
 % \spath_gconvert_to_svg:Nn,
 % }
@@ -3679,7 +4568,7 @@
     \iow_newline:
     <svg~ xmlns="http://www.w3.org/2000/svg"~ version="1.1"~viewBox="
   }
-
+  
   \spath_minbb:Nn \l_@@_tmpb_tl {#1}
   \spath_maxbb:Nn \l_@@_tmpc_tl {#1}
   \tl_put_right:Nx \l_@@_tmpa_tl
@@ -3718,7 +4607,7 @@
     <path~ d="
   }
   \tl_set:Nn \l_@@_tmpc_tl {use:n}
-  \tl_map_inline:Nn #1
+  \tl_map_inline:nn {#1}
   {
     \tl_set:Nn \l_@@_tmpb_tl {##1}
     \tl_case:NnF \l_@@_tmpb_tl
@@ -3751,7 +4640,9 @@
       }
     }
     {
-      \tl_put_right:Nx \l_@@_tmpa_tl {\use:c { \l_@@_tmpc_tl } {\dim_to_decimal:n {##1}} ~}
+      \tl_put_right:Nx
+      \l_@@_tmpa_tl
+      {\use:c { \l_@@_tmpc_tl } {\dim_to_decimal:n {##1}} ~}
     }
   }
   \tl_put_right:Nn \l_@@_tmpa_tl
@@ -3779,7 +4670,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_export_to_svg:nn
 % }
 % Save a soft path to an SVG file.
@@ -3787,18 +4678,21 @@
 \iow_new:N \g_@@_stream
 \cs_new_protected_nopar:Npn \spath_export_to_svg:nn #1#2
 {
-  \spath_convert_path_to_svg:Nn \l_@@_iterp_tl {#2}
+  \group_begin:
+  \spath_convert_to_svg:Nn \l_@@_tmpa_tl {#2}
   \iow_open:Nn \g_@@_stream {#1 .svg}
   \iow_now:Nx \g_@@_stream
   {
-    \tl_use:N \l_@@_iterp_tl
+    \tl_use:N \l_@@_tmpa_tl
   }
   \iow_close:N \g_@@_stream
+  \group_end:
 }
+\cs_generate_variant:Nn \spath_export_to_svg:nn {nv, nV}
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{\spath_show:n}
+% \begin{macro}[internal]{\spath_show:n}
 % Displays the soft path on the terminal.
 %    \begin{macrocode}
 \cs_new_protected_nopar:Npn \spath_show:n #1
@@ -3806,9 +4700,9 @@
   \int_step_inline:nnnn {1} {3} {\tl_count:n {#1}}
   {
     \iow_term:x {
-      \tl_item:Nn \l_@@_tmpa_tl {##1}
-      {\tl_item:Nn \l_@@_tmpa_tl {##1+1}}
-      {\tl_item:Nn \l_@@_tmpa_tl {##1+2}}
+      \tl_item:nn {#1} {##1}
+      {\tl_item:nn {#1} {##1+1}}
+      {\tl_item:nn {#1} {##1+2}}
     }
   }
 }
@@ -3820,7 +4714,7 @@
 %
 % Spaths come from PGF so we need some functions that get and set spaths from the pgf system.
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_get_current_path:N,
 % \spath_gget_current_path:N
 % }
@@ -3841,7 +4735,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{\spath_protocol_path:n}
+% \begin{macro}[internal]{\spath_protocol_path:n}
 % This feeds the bounding box of the soft path to PGF to ensure that its current bounding box contains the soft path.
 %    \begin{macrocode}
 \cs_new_protected_nopar:Npn \spath_protocol_path:n #1
@@ -3856,7 +4750,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_set_current_path:n,
 % \spath_set_current_path:N
 % }
@@ -3877,7 +4771,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{
+% \begin{macro}[internal]{
 % \spath_use_path:nn
 % }
 % Uses the given soft path at the PGF level.
@@ -3890,7 +4784,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{\spath_tikz_path:nn}
+% \begin{macro}[internal]{\spath_tikz_path:nn}
 % Uses the given soft path at the TikZ level.
 %    \begin{macrocode}
 \cs_new_protected_nopar:Npn \spath_tikz_path:nn #1#2
@@ -3904,22 +4798,99 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{\spath_set_tikz_coords:n}
+% \begin{macro}[internal]{\spath_set_tikz_data:n}
 % Sets the \Verb+\tikz at lastx+ and other coordinates from the soft path.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \spath_set_tikz_coords:n #1
+\cs_new_protected_nopar:Npn \spath_set_tikz_data:n #1
 {
   \spath_finalpoint:Nn \l_@@_tmpa_tl {#1}
   \tl_set:Nx \l_@@_tmpa_tl
   {
-    \exp_not:c {tikz at lastx}=\tl_item:Nn \l_@@_tmpa_tl {1}
-    \exp_not:c {tikz at lasty}=\tl_item:Nn \l_@@_tmpa_tl {2}
-    \exp_not:c {tikz at lastxsaved}=\tl_item:Nn \l_@@_tmpa_tl {1}
-    \exp_not:c {tikz at lastysaved}=\tl_item:Nn \l_@@_tmpa_tl {2}
+    \exp_not:c {pgf at x}=\tl_item:Nn \l_@@_tmpa_tl {1}
+    \exp_not:c {pgf at y}=\tl_item:Nn \l_@@_tmpa_tl {2}
   }
+  \use:c {pgf at process}{%
+    \tl_use:N \l_@@_tmpa_tl
+    \pgftransforminvert
+    \use:c {pgf at pos@transform at glob}
+  }
+  \tl_set:Nx \l_@@_tmpa_tl
+  {
+    \exp_not:c {tikz at lastx}=\exp_not:c {pgf at x}
+    \exp_not:c {tikz at lasty}=\exp_not:c {pgf at y}
+    \exp_not:c {tikz at lastxsaved}=\exp_not:c {pgf at x}
+    \exp_not:c {tikz at lastysaved}=\exp_not:c {pgf at y}
+  }
   \tl_use:N \l_@@_tmpa_tl
+  \spath_finalmovepoint:Nn \l_@@_tmpa_tl {#1}
+  \ifpgfsyssoftpathmovetorelevant%
+  \tl_gset_eq:cN {pgfsyssoftpath at lastmoveto} \l_@@_tmpa_tl
+  \fi
+  \tl_set:Nx \l_@@_tmpa_tl
+  {
+    \exp_not:c {pgf at x}=\tl_item:Nn \l_@@_tmpa_tl {1}
+    \exp_not:c {pgf at y}=\tl_item:Nn \l_@@_tmpa_tl {2}
+  }
+  \use:c {pgf at process}{%
+    \tl_use:N \l_@@_tmpa_tl
+    \pgftransforminvert
+    \use:c {pgf at pos@transform at glob}
+  }
+  \tl_set:Nx \l_@@_tmpa_tl
+  {
+    \exp_not:c {tikz at lastmovetox}=\exp_not:c {pgf at x}
+    \exp_not:c {tikz at lastmovetoy}=\exp_not:c {pgf at y}
+  }
+  \tl_use:N \l_@@_tmpa_tl
+  \tl_clear_new:c {tikz at timer}
+  \tl_set:cn {tikz at timer}
+  {
+    \spath_reallength:Nn \l_@@_tmpa_int {#1}
+    \tl_set_eq:Nc \l_@@_tmpb_tl {tikz at time}
+    \tl_set:Nx \l_@@_tmpb_tl
+    {\fp_to_decimal:n {(\l_@@_tmpb_tl) * (\l_@@_tmpa_int)}}
+    \spath_transformation_at:NnV \l_@@_tmpc_tl {#1} \l_@@_tmpb_tl
+    
+    \tl_set:Nx \l_@@_tmpa_tl
+    {
+      \exp_not:N \pgfpoint
+      { \tl_item:Nn \l_@@_tmpc_tl {5} }
+      { \tl_item:Nn \l_@@_tmpc_tl {6} }
+    }
+    \exp_args:NV \pgftransformshift \l_@@_tmpa_tl
+
+    \ifpgfresetnontranslationattime
+    \pgftransformresetnontranslations
+    \fi
+
+    \ifpgfslopedattime
+
+    \tl_set:Nx \l_@@_tmpa_tl
+    {
+      { \tl_item:Nn \l_@@_tmpc_tl {1} }
+      { \tl_item:Nn \l_@@_tmpc_tl {2} }
+      { \tl_item:Nn \l_@@_tmpc_tl {3} }
+      { \tl_item:Nn \l_@@_tmpc_tl {4} }
+    }
+    \ifpgfallowupsidedownattime
+    \else
+    \fp_compare:nT { \tl_item:Nn \l_@@_tmpc_tl {4} < 0}
+    {
+      \tl_set:Nx \l_@@_tmpa_tl
+      {
+        { \fp_eval:n { - (\tl_item:Nn \l_@@_tmpc_tl {1})} }
+        { \fp_eval:n { - (\tl_item:Nn \l_@@_tmpc_tl {2})} }
+        { \fp_eval:n { - (\tl_item:Nn \l_@@_tmpc_tl {3})} }
+        { \fp_eval:n { - (\tl_item:Nn \l_@@_tmpc_tl {4})} }
+      }
+    }
+    \fi
+    \tl_put_right:Nn \l_@@_tmpa_tl {{\pgfpointorigin}}
+    \exp_last_unbraced:NV \pgftransformcm \l_@@_tmpa_tl
+    \fi
+  }
 }
-\cs_generate_variant:Nn \spath_set_tikz_coords:n {V, v}
+\cs_generate_variant:Nn \spath_set_tikz_data:n {V, v}
 %    \end{macrocode}
 % \end{macro}
 %
@@ -3952,6 +4923,13 @@
 \bool_new:N \l_@@_draft_bool
 %    \end{macrocode}
 %
+% We surround all the keys with checks to ensure that the soft path under consideration does actually exist, but if it doesn't we should warn the user.
+%
+%    \begin{macrocode}
+\msg_new:nnn { spath3 } { missing soft path } { Soft~ path~ #1~ doesn't~ exist }
+\msg_new:nnn { spath3 } { empty soft path } { Soft~ path~ #1~ is~ empty }
+%    \end{macrocode}
+%
 % When saving a soft path, by default we use a naming convention that is compatible with the intersections library so that paths saved here and paths saved by the \texttt{name path} facility of the intersections library are mutually exchangeable.
 %
 %    \begin{macrocode}
@@ -3991,6 +4969,34 @@
 \cs_generate_variant:Nn \spath_gsave_path:Nn {cn, NV, cV}
 %    \end{macrocode}
 %
+% \begin{macro}[internal]{
+% \@@_process_tikz_point:Nn
+% }
+% Process a point via TikZ and store the resulting dimensions.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_process_tikz_point:Nn #1#2
+{
+  \group_begin:
+  \use:c {tikz at scan@one at point} \use:n #2 \scan_stop:
+  \tl_gset:Nx \g_@@_output_tl
+  {
+    { \dim_use:c {pgf at x} }
+    { \dim_use:c {pgf at y} }
+  }
+  \group_end:
+  \tl_set_eq:NN #1 \g_@@_output_tl
+  \tl_gclear:N \g_@@_output_tl
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% When we split a soft path into components, we make it a comma separated list so that it can be fed into a \Verb+\foreach+ loop.
+% This can also make it possible to extract a single component, but to do this we need a wrapper around \Verb+\clist_item:Nn+ (there doesn't appear to be a PGF way of getting an item of a CS list).
+%
+%    \begin{macrocode}
+\cs_set_eq:NN \getComponentOf \clist_item:Nn
+%    \end{macrocode}
+%
 % Now we define all of our keys.
 %
 %    \begin{macrocode}
@@ -4031,11 +5037,14 @@
     \tikz at addmode{
       \spath_get_current_path:N \l_@@_tmpa_tl
       \spath_bake_round:NV \l_@@_tmpa_tl \l_@@_tmpa_tl
-      \spath_save_path:cV {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} \l_@@_tmpa_tl
+      \spath_save_path:cV
+      {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+      \l_@@_tmpa_tl
     }
   },
   clone/.code~ 2~ args={
-    \tl_if_exist:cT {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl}
     {
       \tl_clear_new:c
       {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
@@ -4043,9 +5052,13 @@
       {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
       {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl}
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #2 }
+    }
   },
   clone~ global/.code~ 2~ args={
-    \tl_if_exist:cT {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl}
     {
       \tl_gclear_new:c
       {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
@@ -4053,6 +5066,9 @@
       {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
       {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl}
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #2 }
+    }
   },
   save~ global/.code={
     \tikz at addmode{
@@ -4069,11 +5085,15 @@
 %
 %    \begin{macrocode}
   save~ to~ aux/.code={
-    \tl_if_exist:cT {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     {
       \spath_save_to_aux:c
       {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
 %    \end{macrocode}
 %
@@ -4081,13 +5101,70 @@
 %
 %    \begin{macrocode}
   restore/.code={
-    \tl_if_exist:cT {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     {
-      \spath_set_current_path:c
+      \tl_if_empty:cTF
       {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
-      \spath_set_tikz_coords:v
+      {
+        \tl_clear:N \l_@@_tmpa_tl
+        \tl_put_right:NV \l_@@_tmpa_tl \c_spath_moveto_tl
+        \tl_put_right:Nn \l_@@_tmpa_tl {{0pt}{0pt}}
+        \spath_set_current_path:V \l_@@_tmpa_tl
+        \spath_set_tikz_data:V \l_@@_tmpa_tl
+        \msg_warning:nnn { spath3 } { empty soft path } { #1 }
+      }
+      {
+        \spath_set_current_path:c
+        {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+        \spath_set_tikz_data:v
+        {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+      }
+    }
+    {
+      \tl_clear:N \l_@@_tmpa_tl
+      \tl_put_right:NV \l_@@_tmpa_tl \c_spath_moveto_tl
+      \tl_put_right:Nn \l_@@_tmpa_tl {{0pt}{0pt}}
+      \spath_set_current_path:V \l_@@_tmpa_tl
+      \spath_set_tikz_data:V \l_@@_tmpa_tl
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+%    \end{macrocode}
+%
+% Restores the reverse of a soft path to the current path.
+%
+%    \begin{macrocode}
+  restore~ reverse/.code={
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \tl_if_empty:cTF
       {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+      {
+        \tl_clear:N \l_@@_tmpa_tl
+        \tl_put_right:NV \l_@@_tmpa_tl \c_spath_moveto_tl
+        \tl_put_right:Nn \l_@@_tmpa_tl {{0pt}{0pt}}
+        \spath_set_current_path:V \l_@@_tmpa_tl
+        \spath_set_tikz_data:V \l_@@_tmpa_tl
+        \msg_warning:nnn { spath3 } { empty soft path } { #1 }
+      }
+      {
+        \spath_reverse:Nv
+        \l_@@_reverse_tl
+        {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+        \spath_set_current_path:N \l_@@_reverse_tl
+        \spath_set_tikz_data:V \l_@@_reverse_tl
+      }
     }
+    {
+      \tl_clear:N \l_@@_tmpa_tl
+      \tl_put_right:NV \l_@@_tmpa_tl \c_spath_moveto_tl
+      \tl_put_right:Nn \l_@@_tmpa_tl {{0pt}{0pt}}
+      \spath_set_current_path:V \l_@@_tmpa_tl
+      \spath_set_tikz_data:V \l_@@_tmpa_tl
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
 %    \end{macrocode}
 %
@@ -4107,11 +5184,23 @@
 %
 %    \begin{macrocode}
   show/.code={
-    \tl_if_exist:cT {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     {
-      \iow_term:n {---~ soft~ path~ #1~ ---}
-      \spath_show:v {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+      \tl_if_empty:cTF
+      {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+      {
+        \msg_warning:nnn { spath3 } { empty soft path } { #1 }
+      }
+      {
+        \iow_term:n {---~ soft~ path~ #1~ ---}
+        \spath_show:v
+        {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+      }
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
 %    \end{macrocode}
 %
@@ -4119,15 +5208,22 @@
 %
 %    \begin{macrocode}
   append/.code={
-    \tl_if_exist:cT {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     {
       \spath_get_current_path:N \l_@@_current_tl
-      \spath_weld:Nv
-      \l_@@_current_tl
+      \spath_finalpoint:NV \l_@@_tmpa_tl \l_@@_current_tl
+      \tl_set_eq:Nc
+      \l_@@_tmpb_tl
       {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+      \spath_translate_to:NV \l_@@_tmpb_tl \l_@@_tmpa_tl
+      \spath_append_no_move:NV \l_@@_current_tl \l_@@_tmpb_tl
       \spath_set_current_path:N \l_@@_current_tl
-      \spath_set_tikz_coords:V \l_@@_current_tl
+      \spath_set_tikz_data:V \l_@@_tmpb_tl
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
 %    \end{macrocode}
 %
@@ -4135,15 +5231,23 @@
 %
 %    \begin{macrocode}
   join~ with/.code~ 2~ args={
-    \tl_if_exist:cT {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     {
-      \tl_if_exist:cT {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl}
+      \tl_if_exist:cTF
+      {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl}
       {
         \spath_append:cv
         {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
         {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl}
       }
+      {
+        \msg_warning:nnn { spath3 } { missing soft path } { #2 }
+      }
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
 %    \end{macrocode}
 %
@@ -4151,12 +5255,27 @@
 %
 %    \begin{macrocode}
   spot~ weld/.code={
-    \tl_if_exist:cT {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     {
       \spath_spot_weld_components:c
       {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
+  spot~ weld~ globally/.code={
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \spath_spot_gweld_components:c
+      {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
 %    \end{macrocode}
 %
 % Reverses the named path.
@@ -4163,12 +5282,27 @@
 %
 %    \begin{macrocode}
   reverse/.code={
-    \tl_if_exist:cT {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     {
       \spath_reverse:c
       {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
+  reverse~ globally/.code={
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \spath_reverse:c
+      {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
 %    \end{macrocode}
 %
 % Appends the reversal of the path to the current path.
@@ -4175,16 +5309,22 @@
 %
 %    \begin{macrocode}
   append~ reverse/.code={
-    \tl_if_exist:cT {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     {
       \spath_reverse:Nv
       \l_@@_reverse_tl
       {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
       \spath_get_current_path:N \l_@@_current_tl
-      \spath_weld:NV \l_@@_current_tl \l_@@_reverse_tl
+      \spath_finalpoint:NV \l_@@_tmpa_tl \l_@@_current_tl
+      \spath_translate_to:NV \l_@@_reverse_tl \l_@@_tmpa_tl
+      \spath_append_no_move:NV \l_@@_current_tl \l_@@_reverse_tl
       \spath_set_current_path:N \l_@@_current_tl
-      \spath_set_tikz_coords:V \l_@@_current_tl
+      \spath_set_tikz_data:V \l_@@_reverse_tl
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },    
 %    \end{macrocode}
 %
@@ -4192,7 +5332,8 @@
 %
 %    \begin{macrocode}
   insert/.code={
-    \tl_if_exist:cT {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     {
       \spath_get_current_path:N \l_@@_current_tl
       \spath_append:Nv
@@ -4199,8 +5340,12 @@
       \l_@@_current_tl
       {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
       \spath_set_current_path:N \l_@@_current_tl
-      \spath_set_tikz_coords:V \l_@@_current_tl
+      \spath_set_tikz_data:v
+      {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
 %    \end{macrocode}
 %
@@ -4208,7 +5353,8 @@
 % 
 %    \begin{macrocode}
   insert~ reverse/.code={
-    \tl_if_exist:cT {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     {
       \spath_reverse:Nv
       \l_@@_reverse_tl
@@ -4216,30 +5362,333 @@
       \spath_get_current_path:N \l_@@_current_tl
       \spath_append:NV \l_@@_current_tl \l_@@_reverse_tl
       \spath_set_current_path:N \l_@@_current_tl
-      \spath_set_tikz_coords:V \l_@@_current_tl
+      \spath_set_tikz_data:V \l_@@_reverse_tl
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
 %    \end{macrocode}
 %
+% Appends the named path to the current path without translating it.
+%
+%    \begin{macrocode}
+  append~ no~ move/.code={
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \spath_get_current_path:N \l_@@_current_tl
+      \spath_append_no_move:Nv
+      \l_@@_current_tl
+      {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+      \spath_set_current_path:N \l_@@_current_tl
+      \spath_set_tikz_data:v
+      {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+%    \end{macrocode}
+%
+% Appends the reverse of the named path without translating it.
+% 
+%    \begin{macrocode}
+  append~ reverse~ no~ move/.code={
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \spath_reverse:Nv
+      \l_@@_reverse_tl
+      {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+      \spath_get_current_path:N \l_@@_current_tl
+      \spath_append_no_move:NV \l_@@_current_tl \l_@@_reverse_tl
+      \spath_set_current_path:N \l_@@_current_tl
+      \spath_set_tikz_data:V \l_@@_reverse_tl
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+%    \end{macrocode}
+%
+% Adjust a path to span between two points.
+%  
+%    \begin{macrocode}
+  span/.code ~n~ args={3}{
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \@@_process_tikz_point:Nn \l_@@_tmpa_tl {#2}
+      \@@_process_tikz_point:Nn \l_@@_tmpb_tl {#3}
+      \spath_span:cVV
+      {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+      \l_@@_tmpa_tl \l_@@_tmpb_tl
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+  span~ global/.code ~n~ args={3}{
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \@@_process_tikz_point:Nn \l_@@_tmpa_tl {#2}
+      \@@_process_tikz_point:Nn \l_@@_tmpb_tl {#3}
+      \spath_gspan:cVV
+      {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+      \l_@@_tmpa_tl \l_@@_tmpb_tl
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+%    \end{macrocode}
+% 
+% Defines a to path
+% 
+%    \begin{macrocode}
+  to/.style={
+    to~path={
+      [
+        spath/span={#1}{(\tikztostart)}{(\tikztotarget)},
+        spath/append~no~move={#1},
+      ]
+      \tikztonodes
+    }
+  },
+%    \end{macrocode}  
+%
+% Splice three paths together, transforming the middle one so that it exactly fits between the first and third.
+%  
+%    \begin{macrocode}
+  splice/.code ~n~ args={3}{
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \tl_if_exist:cTF
+      {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl}
+      {
+        \tl_if_exist:cTF
+        {\tl_use:N \l_@@_prefix_tl #3 \tl_use:N \l_@@_suffix_tl}
+        {
+          \spath_splice_between:cvv
+          {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+          {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl}
+          {\tl_use:N \l_@@_prefix_tl #3 \tl_use:N \l_@@_suffix_tl}
+        }
+        {
+          \msg_warning:nnn { spath3 } { missing soft path } { #3 }
+        }
+      }
+      {
+        \msg_warning:nnn { spath3 } { missing soft path } { #2 }
+      }
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+  splice~ global/.code ~n~ args={3}{
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \tl_if_exist:cTF
+      {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl}
+      {
+        \tl_if_exist:cTF
+        {\tl_use:N \l_@@_prefix_tl #3 \tl_use:N \l_@@_suffix_tl}
+        {
+          \spath_gsplice_between:cvv
+          {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+          {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl}
+          {\tl_use:N \l_@@_prefix_tl #3 \tl_use:N \l_@@_suffix_tl}
+        }
+        {
+          \msg_warning:nnn { spath3 } { missing soft path } { #3 }
+        }
+      }
+      {
+        \msg_warning:nnn { spath3 } { missing soft path } { #2 }
+      }
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+%    \end{macrocode}
+%
+% Join the components of a path by splicing in the second path whenever the components are sufficiently far apart.
+%
+%    \begin{macrocode}
+  join~ components~ with/.code~2~args={
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \tl_if_exist:cTF
+      {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl}
+      {
+        \spath_spot_weld_components:c
+        {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+
+        \spath_components_to_seq:Nv
+        \l_@@_tmpa_seq
+        {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+
+        \seq_pop_left:NN \l_@@_tmpa_seq \l_@@_tmpa_tl
+      
+        \seq_map_inline:Nn \l_@@_tmpa_seq
+        {
+          \spath_splice_between:Nvn \l_@@_tmpa_tl
+          {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl}
+          {##1}
+        }
+        \tl_set_eq:cN
+        {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+        \l_@@_tmpa_tl
+      }
+      {
+        \msg_warning:nnn { spath3 } { missing soft path } { #2 }
+      }
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+  join~ components~ globally~ with/.code~2~args={
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \tl_if_exist:cTF
+      {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl}
+      {
+        \spath_spot_gweld_components:c
+        {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+        
+        \spath_components_to_seq:Nv
+        \l_@@_tmpa_seq
+        {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+
+        \seq_pop_left:NN \l_@@_tmpa_seq \l_@@_tmpa_tl
+      
+        \seq_map_inline:Nn \l_@@_tmpa_seq
+        {
+          \spath_gsplice_between:Nvn \l_@@_tmpa_tl
+          {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl}
+          {##1}
+        }
+        \tl_set_eq:cN
+        {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+        \l_@@_tmpa_tl
+      }
+      {
+        \msg_warning:nnn { spath3 } { missing soft path } { #2 }
+      }
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+%    \end{macrocode}
+%
+% Close a path.
+%
+%    \begin{macrocode}
+  close/.code={
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \spath_close:c
+      {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+  close~ globally/.code={
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \spath_gclose:c
+      {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+%    \end{macrocode}
+%
+% Close a path with another path.
+%
+%    \begin{macrocode}
+  close~ with/.code~ 2~ args={
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \tl_if_exist:cTF
+      {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl}
+      {
+        \spath_close_with:cv
+        {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+        {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl}
+      }
+      {
+        \msg_warning:nnn { spath3 } { missing soft path } { #2 }
+      }
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+  close~ globally~ with/.code~ 2~ args={
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \tl_if_exist:cTF
+      {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl}
+      {
+        \spath_gclose_with:cv
+        {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+        {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl}
+      }
+      {
+        \msg_warning:nnn { spath3 } { missing soft path } { #2 }
+      }
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+%    \end{macrocode}
+%
 % These keys shorten the path.
 %
 %    \begin{macrocode}
   shorten~ at~ end/.code~ 2~ args={
-    \tl_if_exist:cT {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     {
       \spath_shorten_at_end:cn
       {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} {#2}
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
   shorten~ at~ start/.code~ 2~ args ={
-    \tl_if_exist:cT {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     {
       \spath_shorten_at_start:cn
       {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} {#2}
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
   shorten~ at~ both~ ends/.code~ 2~ args={
-    \tl_if_exist:cT {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     {
       \spath_shorten_at_end:cn
       {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} {#2}
@@ -4246,7 +5695,45 @@
       \spath_shorten_at_start:cn
       {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} {#2}
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
+  shorten~ globally~ at~ end/.code~ 2~ args={
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \spath_gshorten_at_end:cn
+      {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} {#2}
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+  shorten~ globally~ at~ start/.code~ 2~ args ={
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \spath_gshorten_at_start:cn
+      {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} {#2}
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+  shorten~ globally~ at~ both~ ends/.code~ 2~ args={
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \spath_shorten_at_end:cn
+      {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} {#2}
+      \spath_shorten_at_start:cn
+      {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} {#2}
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
 %    \end{macrocode}
 %
 % This translates the named path.
@@ -4253,23 +5740,69 @@
 %
 %    \begin{macrocode}
   translate/.code~ n~ args={3}{
-    \tl_if_exist:cT {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     {
       \spath_translate:cnn
       {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}{#2}{#3}
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
+  translate~ globally/.code~ n~ args={3}{
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \spath_gtranslate:cnn
+      {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}{#2}{#3}
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
 %    \end{macrocode}
 %
+% This normalises the named path.
+%
+%    \begin{macrocode}
+  normalise/.code={
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \spath_normalise:c
+      {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+  normalise~ globally/.code={
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \spath_gnormalise:c
+      {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+%    \end{macrocode}
+%
 % Exports the path as an SVG file.
 %
 %    \begin{macrocode}
   export~ to~ svg/.code={
-    \tl_if_exist:cT {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     {
-      \spath_export_to_svg:c
+      \spath_export_to_svg:nv {#1}
       {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
 %    \end{macrocode}
 %
@@ -4277,7 +5810,8 @@
 %
 %    \begin{macrocode}
   transform/.code~ 2~ args={
-    \tl_if_exist:cT {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     {
       \group_begin:
       \pgftransformreset
@@ -4292,9 +5826,13 @@
       \group_end:
       \tl_use:N \g_@@_smuggle_tl
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
-  transform~global/.code~ 2~ args={
-    \tl_if_exist:cT {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+  transform~globally/.code~ 2~ args={
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     {
       \group_begin:
       \pgftransformreset
@@ -4309,23 +5847,96 @@
       \group_end:
       \tl_use:N \g_@@_smuggle_tl
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
 %    \end{macrocode}
 %
+% Splits first path where it intersects with the second.
+%
+%    \begin{macrocode}
+  split~ at~ intersections~ with/.code~ n~ args={2}{
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \tl_if_exist:cTF
+      {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl}
+      {
+        \spath_split_path_at_intersections:cv
+        {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+        {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl}
+      }
+      {
+        \msg_warning:nnn { spath3 } { missing soft path } { #2 }
+      }
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+  split~ globally~ at~ intersections~ with/.code~ n~ args={2}{
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \tl_if_exist:cTF
+      {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl}
+      {
+        \spath_gsplit_path_at_intersections:cv
+        {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+        {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl}
+      }
+      {
+        \msg_warning:nnn { spath3 } { missing soft path } { #2 }
+      }
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+%    \end{macrocode}
+%
 % Splits two paths at their mutual intersections.
 %
 %    \begin{macrocode}
   split~ at~ intersections/.code~ n~ args={2}{
-    \tl_if_exist:cT {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     {
-      \tl_if_exist:cT {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl}
+      \tl_if_exist:cTF
+      {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl}
       {
         \spath_split_at_intersections:cc
         {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
         {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl}
       }
+      {
+        \msg_warning:nnn { spath3 } { missing soft path } { #2 }
+      }
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
+  split~ globally~ at~ intersections/.code~ n~ args={2}{
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \tl_if_exist:cTF
+      {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl}
+      {
+        \spath_gsplit_at_intersections:cc
+        {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+        {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl}
+      }
+      {
+        \msg_warning:nnn { spath3 } { missing soft path } { #2 }
+      }
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
 %    \end{macrocode}
 %
 % Splits a path at its self-intersections.
@@ -4332,12 +5943,27 @@
 %
 %    \begin{macrocode}
   split~ at~ self~ intersections/.code={
-    \tl_if_exist:cT {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     {
       \spath_split_at_self_intersections:c
       {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
+  split~ globally~ at~ self~ intersections/.code={
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \spath_gsplit_at_self_intersections:c
+      {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
 %    \end{macrocode}
 %
 % Extract the components of a path into a comma separated list (suitable for using in a \Verb+\foreach+ loop).
@@ -4344,7 +5970,8 @@
 %
 %    \begin{macrocode}
   get~ components~ of/.code~ 2~ args={
-    \tl_if_exist:cT {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     {
       \clist_clear_new:N #2
       \spath_components_to_seq:Nv
@@ -4353,14 +5980,55 @@
       \seq_map_inline:Nn \l_@@_tmpa_seq
       {
         \tl_new:c
-        {\tl_use:N \l_@@_prefix_tl anonymous_\int_use:N \g_@@_anon_int \tl_use:N \l_@@_suffix_tl}
+        {
+          \tl_use:N \l_@@_prefix_tl
+          anonymous_\int_use:N \g_@@_anon_int
+          \tl_use:N \l_@@_suffix_tl
+        }
         \tl_set:cn
-        {\tl_use:N \l_@@_prefix_tl anonymous_\int_use:N \g_@@_anon_int \tl_use:N \l_@@_suffix_tl} {##1}
+        {
+          \tl_use:N \l_@@_prefix_tl
+          anonymous_\int_use:N \g_@@_anon_int
+          \tl_use:N \l_@@_suffix_tl
+        } {##1}
         \clist_put_right:Nx #2 {anonymous_\int_use:N \g_@@_anon_int}
         \int_gincr:N \g_@@_anon_int
       }
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
+  get~ components~ of~ globally/.code~ 2~ args={
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \clist_gclear_new:N #2
+      \spath_components_to_seq:Nv
+      \l_@@_tmpa_seq
+      {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+      \seq_map_inline:Nn \l_@@_tmpa_seq
+      {
+        \tl_new:c
+        {
+          \tl_use:N \l_@@_prefix_tl
+          anonymous_\int_use:N \g_@@_anon_int
+          \tl_use:N \l_@@_suffix_tl
+        }
+        \tl_gset:cn
+        {
+          \tl_use:N \l_@@_prefix_tl
+          anonymous_\int_use:N \g_@@_anon_int
+          \tl_use:N \l_@@_suffix_tl
+        } {##1}
+        \clist_gput_right:Nx #2 {anonymous_\int_use:N \g_@@_anon_int}
+        \int_gincr:N \g_@@_anon_int
+      }
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
 %    \end{macrocode}
 %
 % Loop through the components of a soft path and render each as a separate TikZ path so that they can be individually styled.
@@ -4367,7 +6035,8 @@
 %
 %    \begin{macrocode}
   render~ components/.code={
-    \tl_if_exist:cT {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     {
       \group_begin:
       \spath_components_to_seq:Nv
@@ -4390,6 +6059,9 @@
       }
       \group_end:
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
 %    \end{macrocode}
 %
@@ -4398,15 +6070,24 @@
 %
 %    \begin{macrocode}
   insert~ gaps~ after~ components/.code~ n~ args={3}{
-    \tl_if_exist:cT {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     {
       \group_begin:
       \seq_gclear:N \g_@@_tmpa_seq
       \seq_gclear:N \g_@@_tmpb_seq
+      \spath_numberofcomponents:Nv \l_@@_tmpa_int
+      {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
       \foreach \l_@@_tmpa_tl in {#3}
       {
         \seq_gput_right:NV \g_@@_tmpa_seq \l_@@_tmpa_tl
-        \seq_gput_right:Nx \g_@@_tmpb_seq {\int_eval:n { \l_@@_tmpa_tl + 1 }}
+        \seq_gput_right:Nx
+        \g_@@_tmpb_seq
+        {\int_eval:n
+          {
+            \int_mod:nn { \l_@@_tmpa_tl }{ \l_@@_tmpa_int } + 1
+          }
+        }
       }
       \spath_components_to_seq:Nv
       \l_@@_tmpa_seq
@@ -4432,7 +6113,59 @@
       \g_@@_output_tl
       \tl_gclear:N \g_@@_output_tl
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
+  insert~ gaps~ globally~ after~ components/.code~ n~ args={3}{
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \group_begin:
+      \seq_gclear:N \g_@@_tmpa_seq
+      \seq_gclear:N \g_@@_tmpb_seq
+      \spath_numberofcomponents:Nv \l_@@_tmpa_int
+      {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+      \foreach \l_@@_tmpa_tl in {#3}
+      {
+        \seq_gput_right:NV \g_@@_tmpa_seq \l_@@_tmpa_tl
+        \seq_gput_right:Nx
+        \g_@@_tmpb_seq
+        {
+          \int_eval:n
+          {
+            \int_mod:nn { \l_@@_tmpa_tl }{ \l_@@_tmpa_int } + 1
+          }
+        }
+      }
+      \spath_components_to_seq:Nv
+      \l_@@_tmpa_seq
+      {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+      \seq_clear:N \l_@@_tmpb_seq
+      \seq_map_indexed_inline:Nn \l_@@_tmpa_seq
+      {
+        \tl_set:Nn \l_@@_tmpa_tl {##2}
+        \seq_if_in:NnT \g_@@_tmpa_seq {##1}
+        {
+          \spath_shorten_at_end:Nn \l_@@_tmpa_tl {#2/2}
+        }
+        \seq_if_in:NnT \g_@@_tmpb_seq {##1}
+        {
+          \spath_shorten_at_start:Nn \l_@@_tmpa_tl {#2/2}
+        }
+        \seq_put_right:NV \l_@@_tmpb_seq \l_@@_tmpa_tl
+      }
+      \tl_gset:Nx \g_@@_output_tl {\seq_use:Nn \l_@@_tmpb_seq {} }
+      \group_end:
+      \tl_gset_eq:cN
+      {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+      \g_@@_output_tl
+      \tl_gclear:N \g_@@_output_tl
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
 %    \end{macrocode}
 %
 % Join the specified components together, joining each to its previous one.
@@ -4439,7 +6172,8 @@
 %
 %    \begin{macrocode}
   join~ components/.code~ 2~ args={
-    \tl_if_exist:cT {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     {
       \seq_gclear:N \g_@@_tmpa_seq
       \foreach \l_@@_tmpa_tl in {#2}
@@ -4458,7 +6192,35 @@
         {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}{##1}
       }
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
+  join~ components~ globally/.code~ 2~ args={
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \seq_gclear:N \g_@@_tmpa_seq
+      \foreach \l_@@_tmpa_tl in {#2}
+      {
+        \seq_gput_right:NV \g_@@_tmpa_seq \l_@@_tmpa_tl
+      }
+      \seq_gsort:Nn \g_@@_tmpa_seq
+      {
+        \int_compare:nNnTF {##1} > {##2}
+        { \sort_return_same: }
+        { \sort_return_swapped: }
+      }
+      \seq_map_inline:Nn \g_@@_tmpa_seq
+      {
+        \spath_gjoin_component:cn
+        {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}{##1}
+      }
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
 %    \end{macrocode}
 %
 % Remove all components of the path that don't actually draw anything.
@@ -4465,14 +6227,123 @@
 %
 %    \begin{macrocode}
   remove~ empty~ components/.code={
-    \tl_if_exist:cT {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     {
       \spath_remove_empty_components:c
       {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
+  remove~ empty~ components~ globally/.code={
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \spath_gremove_empty_components:c
+      {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
 %    \end{macrocode}
 %
+%
+% Join the specified components together, joining each to its previous one.
+%
+%    \begin{macrocode}
+  remove~ components/.code~ 2~ args={
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \seq_gclear:N \g_@@_tmpa_seq
+      \foreach \l_@@_tmpa_tl in {#2}
+      {
+        \seq_gput_right:NV \g_@@_tmpa_seq \l_@@_tmpa_tl
+      }
+      \seq_gsort:Nn \g_@@_tmpa_seq
+      {
+        \int_compare:nNnTF {##1} < {##2}
+        { \sort_return_same: }
+        { \sort_return_swapped: }
+      }
+      \spath_components_to_seq:Nv
+      \l_@@_tmpa_seq
+      {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+      \seq_gpop_left:NNF \g_@@_tmpa_seq \l_@@_tmpa_tl
+      {
+        \tl_clear:N \l_@@_tmpa_tl
+      }
+      \seq_clear:N \l_@@_tmpb_seq
+      \seq_map_indexed_inline:Nn \l_@@_tmpa_seq
+      {
+        \tl_set:Nn \l_@@_tmpb_tl {##1}
+        \tl_if_eq:NNTF \l_@@_tmpb_tl \l_@@_tmpa_tl
+        {
+          \seq_gpop_left:NNF \g_@@_tmpa_seq \l_@@_tmpa_tl
+          {
+            \tl_clear:N \l_@@_tmpa_tl
+          }
+        }
+        {
+          \seq_put_right:Nn \l_@@_tmpb_seq {##2}
+        }
+      }
+      \tl_set:cx {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+      {\seq_use:Nn \l_@@_tmpb_seq {} }
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+  remove~ components~ globally/.code~ 2~ args={
+    \tl_if_exist:cTF
+    {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+    {
+      \seq_gclear:N \g_@@_tmpa_seq
+      \foreach \l_@@_tmpa_tl in {#2}
+      {
+        \seq_gput_right:NV \g_@@_tmpa_seq \l_@@_tmpa_tl
+      }
+      \seq_gsort:Nn \g_@@_tmpa_seq
+      {
+        \int_compare:nNnTF {##1} < {##2}
+        { \sort_return_same: }
+        { \sort_return_swapped: }
+      }
+      \spath_components_to_seq:Nv
+      \l_@@_tmpa_seq
+      {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+      \seq_gpop_left:NNF \g_@@_tmpa_seq \l_@@_tmpa_tl
+      {
+        \tl_clear:N \l_@@_tmpa_tl
+      }
+      \seq_clear:N \l_@@_tmpb_seq
+      \seq_map_indexed_inline:Nn \l_@@_tmpa_seq
+      {
+        \tl_set:Nn \l_@@_tmpb_tl {##1}
+        \tl_if_eq:NNTF \l_@@_tmpb_tl \l_@@_tmpa_tl
+        {
+          \seq_gpop_left:NNF \g_@@_tmpa_seq \l_@@_tmpa_tl
+          {
+            \tl_clear:N \l_@@_tmpa_tl
+          }
+        }
+        {
+          \seq_put_right:Nn \l_@@_tmpb_seq {##2}
+        }
+      }
+      \tl_gset:cx {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+      {\seq_use:Nn \l_@@_tmpb_seq {} }
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+%    \end{macrocode}
+%   
 % This puts a conditional around the \texttt{spot weld} key because when figuring out a knot drawing then we will initially want to render it without the spot weld to keep the number of components constant.
 %
 %    \begin{macrocode}
@@ -4486,13 +6357,31 @@
   maybe~ spot~ weld/.code={
     \bool_if:NF \l_@@_draft_bool
     {
-      \tl_if_exist:cT {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+      \tl_if_exist:cTF
+      {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
       {
         \spath_spot_weld_components:c
         {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
       }
+      {
+        \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+      }
     }
   },
+  maybe~ spot~ weld~ globally/.code={
+    \bool_if:NF \l_@@_draft_bool
+    {
+      \tl_if_exist:cTF
+      {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+      {
+        \spath_spot_gweld_components:c
+        {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}
+      }
+      {
+        \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+      }
+    }
+  },
 %    \end{macrocode}
 %
 % Set the transformation to lie along a path.
@@ -4527,6 +6416,7 @@
       \tl_gset_eq:NN \g_@@_smuggle_tl \l_@@_tmpc_tl
     }
     {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
       \tl_gset_eq:NN \g_@@_smuggle_tl { {1}{0}{0}{1}{0pt}{0pt} }
     }
     \group_end:
@@ -4567,6 +6457,7 @@
       \tl_gset_eq:NN \g_@@_smuggle_tl \l_@@_tmpc_tl
     }
     {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
       \tl_gset_eq:NN \g_@@_smuggle_tl { {1}{0}{0}{1}{0pt}{0pt} }
     }
     \fp_compare:nT { \tl_item:Nn \g_@@_smuggle_tl {4} < 0}
@@ -4591,12 +6482,19 @@
 %
 %    \begin{macrocode}
   knot/.style~ n~ args={3}{
-    spath/.cd,
-    split~ at~ self~ intersections=#1,
-    insert~ gaps~ after~ components={#1}{#2}{#3},
-    maybe~ spot~ weld=#1,
-    render~ components=#1
+    spath/split~ at~ self~ intersections=#1,
+    spath/remove~ empty~ components=#1,
+    spath/insert~ gaps~ after~ components={#1}{#2}{#3},
+    spath/maybe~ spot~ weld=#1,
+    spath/render~ components=#1
   },
+  global~ knot/.style~ n~ args={3}{
+    spath/split~ globally~ at~ self~ intersections=#1,
+    spath/remove~ empty~ components~ globally=#1,
+    spath/insert~ gaps~ globally ~after~ components={#1}{#2}{#3},
+    spath/maybe~ spot~ weld~ globally=#1,
+    spath/render~ components=#1
+  },
 }
 %    \end{macrocode}
 %
@@ -4649,10 +6547,15 @@
     }
   }
   {
+    \msg_warning:nnx { spath3 } { missing soft path } { \tl_use:N \l_@@_tmpa_tl }
     \tl_gset_eq:NN \g_@@_smuggle_tl \pgfpointorigin
   }
-    \group_end:
+  \group_end:
+  \use:c {pgf at process}{%
     \tl_use:N \g_@@_smuggle_tl
+    \pgftransforminvert
+    \use:c {pgf at pos@transform at glob}
+  }
 }
 
 \ExplSyntaxOff
@@ -4733,7 +6636,8 @@
       \pgfsyssoftpath at getcurrentpath\l_@@_tmpa_tl
       \spath_components_to_seq:NV \l_@@_tmpa_seq \l_@@_tmpa_tl
       \seq_gclear_new:c {g_@@_pen_\pgfkeysvalueof{/tikz/pen~name}_seq}
-      \seq_gset_eq:cN {g_@@_pen_\pgfkeysvalueof{/tikz/pen~name}_seq} \l_@@_tmpa_seq
+      \seq_gset_eq:cN
+      {g_@@_pen_\pgfkeysvalueof{/tikz/pen~name}_seq} \l_@@_tmpa_seq
       \pgfusepath{discard}%
     }
   },
@@ -4747,10 +6651,12 @@
       \spath_components_to_seq:NV \l_@@_tmpa_seq \l_@@_tmpa_tl
       \tl_if_exist:cTF {g_@@_pen_\pgfkeysvalueof{/tikz/pen~name}_seq}
       {
-        \cal_path_create:Nc \l_@@_tmpa_seq {g_@@_pen_\pgfkeysvalueof{/tikz/pen~name}_seq}
+        \cal_path_create:Nc \l_@@_tmpa_seq
+        {g_@@_pen_\pgfkeysvalueof{/tikz/pen~name}_seq}
       }
       {
-        \msg_warning:nnx { calligraphy } { undefined pen } { \pgfkeysvalueof{/tikz/pen~name} }
+        \msg_warning:nnx { calligraphy } { undefined pen }
+        { \pgfkeysvalueof{/tikz/pen~name} }
       }
     }
   },
@@ -4823,8 +6729,10 @@
     \tl_set:cn {l_@@_stroke_style_#1} {#2}
   },
   this~stroke~style/.code={
-    \tl_clear_new:c {l_@@_stroke_inline_style_ \int_use:N \g_@@_path_component_int}
-    \tl_set:cn {l_@@_stroke_inline_style_ \int_use:N \g_@@_path_component_int} {#1}
+    \tl_clear_new:c
+    {l_@@_stroke_inline_style_ \int_use:N \g_@@_path_component_int}
+    \tl_set:cn
+    {l_@@_stroke_inline_style_ \int_use:N \g_@@_path_component_int} {#1}
   },
   annotate/.style={
     annotate~if,
@@ -4944,23 +6852,29 @@
           \spath_weld:NV \l_@@_tmp_patha_tl \l_@@_tmp_rpathb_tl
 
           \tl_clear:N \l_@@_tmpa_tl
-          \tl_set:Nn \l_@@_tmpa_tl {fill=\pgfkeysvalueof{/tikz/pen~colour},draw=none}
+          \tl_set:Nn \l_@@_tmpa_tl
+          {
+            fill=\pgfkeysvalueof{/tikz/pen~colour},
+            draw=none
+          }
           \tl_if_exist:cT  {l_@@_stroke_style_ \int_use:N \l_@@_tmpa_int}
           {
-            \tl_put_right:Nv \l_@@_tmpa_tl {l_@@_stroke_style_ \int_use:N \l_@@_tmpa_int}
+            \tl_put_right:Nv \l_@@_tmpa_tl
+            {l_@@_stroke_style_ \int_use:N \l_@@_tmpa_int}
           }
           \tl_if_exist:cT  {l_@@_stroke_inline_style_ \int_use:N \l_@@_tmpa_int}
           {
             \tl_put_right:Nn \l_@@_tmpa_tl {,}
-            \tl_put_right:Nv \l_@@_tmpa_tl {l_@@_stroke_inline_style_ \int_use:N \l_@@_tmpa_int}
+            \tl_put_right:Nv \l_@@_tmpa_tl
+            {l_@@_stroke_inline_style_ \int_use:N \l_@@_tmpa_int}
           }
           \tl_if_exist:cT  {l_@@_nib_style_ \int_use:N \l_@@_tmpb_int}
           {
             \tl_put_right:Nn \l_@@_tmpa_tl {,}
-            \tl_put_right:Nv \l_@@_tmpa_tl {l_@@_nib_style_ \int_use:N \l_@@_tmpb_int}
+            \tl_put_right:Nv \l_@@_tmpa_tl
+            {l_@@_nib_style_ \int_use:N \l_@@_tmpb_int}
           }
           \spath_tikz_path:VV \l_@@_tmpa_tl \l_@@_tmp_patha_tl
-
         }
         \pgfsys at endscope
         \group_end:
@@ -4971,7 +6885,9 @@
         \seq_get_right:NN #2 \l_@@_tmpa_tl
         \spath_finalpoint:NV \l_@@_tmpa_tl \l_@@_tmpa_tl
         \spath_translate:NV \l_@@_tmp_path_tl \l_@@_tmpa_tl
-        \tikz at scan@one at point\pgfutil at firstofone\pgfkeysvalueof{/tikz/annotation~shift}
+        \tikz at scan@one at point
+        \pgfutil at firstofone
+        \pgfkeysvalueof{/tikz/annotation~shift}
 
         \spath_translate:Nnn \l_@@_tmp_path_tl {\pgf at x} {\pgf at y}
       
@@ -4982,7 +6898,10 @@
 
         \exp_last_unbraced:NV \pgfqpoint \l_@@_tmpa_tl
         \begin{scope}[reset~ cm]
-        \node[every~annotation~node/.try,tl~use:c =  {l_@@_annotation_style_ \int_use:N \l_@@_tmpa_int _tl}] at (\pgf at x,\pgf at y) {\int_use:N \l_@@_tmpa_int};
+        \node[
+          every~annotation~node/.try,
+          tl~use:c = {l_@@_annotation_style_ \int_use:N \l_@@_tmpa_int _tl}
+        ] at (\pgf at x,\pgf at y) {\int_use:N \l_@@_tmpa_int};
         \end{scope}
       }
     }
@@ -5191,8 +7110,18 @@
     (\l_@@_tmpa_fp^2 + \l_@@_tmpb_fp^2)^.5
   }
   
-  \fp_set:Nn \l_@@_tmpa_fp {.5*\l_@@_taper_width_dim *     \l_@@_tmpa_fp / \l_@@_tmpe_fp}
-  \fp_set:Nn \l_@@_tmpb_fp {.5*\l_@@_taper_width_dim *     \l_@@_tmpb_fp / \l_@@_tmpe_fp}
+  \fp_set:Nn \l_@@_tmpa_fp
+  {
+    .5*\l_@@_taper_width_dim
+    *
+    \l_@@_tmpa_fp / \l_@@_tmpe_fp
+  }
+  \fp_set:Nn \l_@@_tmpb_fp
+  {
+    .5*\l_@@_taper_width_dim
+    *
+    \l_@@_tmpb_fp / \l_@@_tmpe_fp
+  }
 
   \fp_set:Nn \l_@@_tmpc_fp
   {
@@ -5207,13 +7136,23 @@
     (\l_@@_tmpc_fp^2 + \l_@@_tmpd_fp^2)^.5
   }
 
-  \fp_set:Nn \l_@@_tmpc_fp {.5*\l_@@_line_width_dim * \l_@@_tmpc_fp / \l_@@_tmpe_fp}
-  \fp_set:Nn \l_@@_tmpd_fp {.5*\l_@@_line_width_dim * \l_@@_tmpd_fp / \l_@@_tmpe_fp}
+  \fp_set:Nn \l_@@_tmpc_fp
+  {
+    .5*\l_@@_line_width_dim
+    *
+    \l_@@_tmpc_fp / \l_@@_tmpe_fp
+  }
+  \fp_set:Nn \l_@@_tmpd_fp
+  {
+    .5*\l_@@_line_width_dim
+    *
+    \l_@@_tmpd_fp / \l_@@_tmpe_fp
+  }
 
   \tl_put_right:Nx \l_@@_tmpb_tl
   {
     {\dim_eval:n { \fp_to_dim:N \l_@@_tmpa_fp + \l_@@_tmpa_dim}}
-    {\dim_eval:n { \fp_to_dim:N \l_@@_tmpb_fp +             \l_@@_tmpb_dim}}
+    {\dim_eval:n { \fp_to_dim:N \l_@@_tmpb_fp + \l_@@_tmpb_dim}}
   }
 
   \tl_put_right:NV \l_@@_tmpb_tl \c_spath_curvetoa_tl
@@ -5244,8 +7183,22 @@
 
   \tl_put_right:Nx \l_@@_tmpb_tl
   {
-    {\dim_eval:n { \fp_to_dim:N \l_@@_tmpc_fp + \l_@@_tmpg_dim - \fp_to_dim:n{ 1.32 * \l_@@_tmpd_fp}}}
-    {\dim_eval:n { \fp_to_dim:N \l_@@_tmpd_fp + \l_@@_tmph_dim + \fp_to_dim:n {1.32* \l_@@_tmpc_fp}}}
+    {
+      \dim_eval:n
+      {
+        \fp_to_dim:N \l_@@_tmpc_fp + \l_@@_tmpg_dim
+        - \fp_to_dim:n{ 1.32 * \l_@@_tmpd_fp
+        }
+      }
+    }
+    {
+      \dim_eval:n
+      {
+        \fp_to_dim:N \l_@@_tmpd_fp + \l_@@_tmph_dim
+        + \fp_to_dim:n {1.32* \l_@@_tmpc_fp
+        }
+      }
+    }
   }
 
   \tl_put_right:NV \l_@@_tmpb_tl \c_spath_curvetob_tl
@@ -5252,8 +7205,22 @@
 
   \tl_put_right:Nx \l_@@_tmpb_tl
   {
-    {\dim_eval:n { -\fp_to_dim:N \l_@@_tmpc_fp + \l_@@_tmpg_dim - \fp_to_dim:n {1.32 * \l_@@_tmpd_fp}}}
-    {\dim_eval:n { -\fp_to_dim:N \l_@@_tmpd_fp + \l_@@_tmph_dim + \fp_to_dim:n {1.32 * \l_@@_tmpc_fp}}}
+    {
+      \dim_eval:n
+      {
+        -\fp_to_dim:N \l_@@_tmpc_fp + \l_@@_tmpg_dim
+        - \fp_to_dim:n {1.32 * \l_@@_tmpd_fp
+        }
+      }
+    }
+    {
+      \dim_eval:n
+      {
+        -\fp_to_dim:N \l_@@_tmpd_fp + \l_@@_tmph_dim
+        + \fp_to_dim:n {1.32 * \l_@@_tmpc_fp
+        }
+      }
+    }
   }
 
   \tl_put_right:NV \l_@@_tmpb_tl \c_spath_curveto_tl
@@ -5292,8 +7259,20 @@
 
   \tl_put_right:Nx \l_@@_tmpb_tl
   {
-    {\dim_eval:n { -\fp_to_dim:N \l_@@_tmpa_fp + \l_@@_tmpa_dim + \fp_to_dim:n{ 1.32 * \l_@@_tmpb_fp}}}
-    {\dim_eval:n { -\fp_to_dim:N \l_@@_tmpb_fp + \l_@@_tmpb_dim - \fp_to_dim:n {1.32* \l_@@_tmpa_fp}}}
+    {
+      \dim_eval:n
+      {
+        -\fp_to_dim:N \l_@@_tmpa_fp + \l_@@_tmpa_dim
+        + \fp_to_dim:n{ 1.32 * \l_@@_tmpb_fp}
+      }
+    }
+    {
+      \dim_eval:n
+      {
+        -\fp_to_dim:N \l_@@_tmpb_fp + \l_@@_tmpb_dim
+        - \fp_to_dim:n {1.32* \l_@@_tmpa_fp}
+      }
+    }
   }
 
   \tl_put_right:NV \l_@@_tmpb_tl \c_spath_curvetob_tl
@@ -5300,8 +7279,20 @@
 
   \tl_put_right:Nx \l_@@_tmpb_tl
   {
-    {\dim_eval:n { \fp_to_dim:N \l_@@_tmpa_fp + \l_@@_tmpa_dim + \fp_to_dim:n {1.32 * \l_@@_tmpb_fp}}}
-    {\dim_eval:n { \fp_to_dim:N \l_@@_tmpb_fp + \l_@@_tmpb_dim - \fp_to_dim:n {1.32 * \l_@@_tmpa_fp}}}
+    {
+      \dim_eval:n
+      {
+        \fp_to_dim:N \l_@@_tmpa_fp + \l_@@_tmpa_dim
+        + \fp_to_dim:n {1.32 * \l_@@_tmpb_fp}
+      }
+    }
+    {
+      \dim_eval:n
+      {
+        \fp_to_dim:N \l_@@_tmpb_fp + \l_@@_tmpb_dim
+        - \fp_to_dim:n {1.32 * \l_@@_tmpa_fp}
+      }
+    }
   }
 
   \tl_put_right:NV \l_@@_tmpb_tl \c_spath_curveto_tl
@@ -5309,7 +7300,7 @@
   \tl_put_right:Nx \l_@@_tmpb_tl
   {
     {\dim_eval:n { \fp_to_dim:N \l_@@_tmpa_fp + \l_@@_tmpa_dim}}
-    {\dim_eval:n { \fp_to_dim:N \l_@@_tmpb_fp +             \l_@@_tmpb_dim}}
+    {\dim_eval:n { \fp_to_dim:N \l_@@_tmpb_fp + \l_@@_tmpb_dim}}
   }
 
   \pgfsyssoftpath at setcurrentpath\l_@@_tmpb_tl
@@ -5327,7 +7318,7 @@
 \seq_gset_eq:NN \g_@@_pen_copperplate_seq \l_@@_tmpa_seq
 %    \end{macrocode}
 %
-% \begin{macro}{\CopperplatePath}
+% \begin{macro}[internal]{\CopperplatePath}
 % This is used in the decorations section to convert a path to a copperplate path.
 %    \begin{macrocode}
 \DeclareDocumentCommand \CopperplatePath { m }
@@ -5350,46 +7341,106 @@
 %    \begin{macrocode}
 \expandafter\ifx\csname pgfdeclaredecoration\endcsname\relax
 \else
-\pgfdeclaredecoration{calligraphic brace}{brace}
-{
-  \state{brace}[width=+\pgfdecoratedremainingdistance,next state=final]
-  {
-    \pgfsyssoftpath at setcurrentpath{\pgfutil at empty}
-    \pgfpathmoveto{\pgfpointorigin}
-    \pgfpathcurveto
-    {\pgfqpoint{.15\pgfdecorationsegmentamplitude}{.3\pgfdecorationsegmentamplitude}}
-    {\pgfqpoint{.5\pgfdecorationsegmentamplitude}{.5\pgfdecorationsegmentamplitude}}
-    {\pgfqpoint{\pgfdecorationsegmentamplitude}{.5\pgfdecorationsegmentamplitude}}
-    {
-      \pgftransformxshift{+\pgfdecorationsegmentaspect\pgfdecoratedremainingdistance}
-      \pgfpathlineto{\pgfqpoint{-\pgfdecorationsegmentamplitude}{.5\pgfdecorationsegmentamplitude}}
+\pgfdeclaredecoration{calligraphic brace}{brace}%
+{%
+  \state{brace}[width=+\pgfdecoratedremainingdistance,next state=final]%
+  {%
+    \pgfsyssoftpath at setcurrentpath{\pgfutil at empty}%
+    \pgfpathmoveto{\pgfpointorigin}%
+    \pgfpathcurveto%
+    {%
+      \pgfqpoint%
+      {.15\pgfdecorationsegmentamplitude}%
+      {.3\pgfdecorationsegmentamplitude}%
+    }%
+    {%
+      \pgfqpoint%
+      {.5\pgfdecorationsegmentamplitude}%
+      {.5\pgfdecorationsegmentamplitude}%
+    }%
+    {%
+      \pgfqpoint%
+      {\pgfdecorationsegmentamplitude}%
+      {.5\pgfdecorationsegmentamplitude}%
+    }%
+    {%
+      \pgftransformxshift%
+      {+\pgfdecorationsegmentaspect\pgfdecoratedremainingdistance}%
+      \pgfpathlineto%
+      {%
+        \pgfqpoint%
+        {-\pgfdecorationsegmentamplitude}%
+        {.5\pgfdecorationsegmentamplitude}%
+      }%
       \pgfpathcurveto
-      {\pgfqpoint{-.5\pgfdecorationsegmentamplitude}{.5\pgfdecorationsegmentamplitude}}
-      {\pgfqpoint{-.15\pgfdecorationsegmentamplitude}{.7\pgfdecorationsegmentamplitude}}
-      {\pgfqpoint{0\pgfdecorationsegmentamplitude}{1\pgfdecorationsegmentamplitude}}
-      \pgfpathmoveto{\pgfqpoint{0\pgfdecorationsegmentamplitude}{1\pgfdecorationsegmentamplitude}}
-      \pgfpathcurveto
-      {\pgfqpoint{.15\pgfdecorationsegmentamplitude}{.7\pgfdecorationsegmentamplitude}}
-      {\pgfqpoint{.5\pgfdecorationsegmentamplitude}{.5\pgfdecorationsegmentamplitude}}
-      {\pgfqpoint{\pgfdecorationsegmentamplitude}{.5\pgfdecorationsegmentamplitude}}
-    }
-    {
-      \pgftransformxshift{+\pgfdecoratedremainingdistance}
-      \pgfpathlineto{\pgfqpoint{-\pgfdecorationsegmentamplitude}{.5\pgfdecorationsegmentamplitude}}
-      \pgfpathcurveto
-      {\pgfqpoint{-.5\pgfdecorationsegmentamplitude}{.5\pgfdecorationsegmentamplitude}}
-      {\pgfqpoint{-.15\pgfdecorationsegmentamplitude}{.3\pgfdecorationsegmentamplitude}}
-      {\pgfqpoint{0pt}{0pt}}
-    }
-    \tikzset{
-      taper width=.5\pgflinewidth,
-      taper
+      {%
+        \pgfqpoint%
+        {-.5\pgfdecorationsegmentamplitude}%
+        {.5\pgfdecorationsegmentamplitude}%
+      }%
+      {%
+        \pgfqpoint%
+        {-.15\pgfdecorationsegmentamplitude}%
+        {.7\pgfdecorationsegmentamplitude}%
+      }%
+      {%
+        \pgfqpoint%
+        {0\pgfdecorationsegmentamplitude}%
+        {1\pgfdecorationsegmentamplitude}%
+      }%
+      \pgfpathmoveto%
+      {%
+        \pgfqpoint%
+        {0\pgfdecorationsegmentamplitude}%
+        {1\pgfdecorationsegmentamplitude}%
+      }%
+      \pgfpathcurveto%
+      {%
+        \pgfqpoint%
+        {.15\pgfdecorationsegmentamplitude}%
+        {.7\pgfdecorationsegmentamplitude}%
+      }%
+      {%
+        \pgfqpoint%
+        {.5\pgfdecorationsegmentamplitude}%
+        {.5\pgfdecorationsegmentamplitude}%
+      }%
+      {%
+        \pgfqpoint%
+        {\pgfdecorationsegmentamplitude}%
+        {.5\pgfdecorationsegmentamplitude}%
+      }%
     }%
-    \pgfsyssoftpath at getcurrentpath\cal at tmp@path
-    \CopperplatePath{\cal at tmp@path}
-  }
-  \state{final}{}
-}
+    {%
+      \pgftransformxshift{+\pgfdecoratedremainingdistance}%
+      \pgfpathlineto%
+      {%
+        \pgfqpoint%
+        {-\pgfdecorationsegmentamplitude}%
+        {.5\pgfdecorationsegmentamplitude}%
+      }%
+      \pgfpathcurveto%
+      {%
+        \pgfqpoint%
+        {-.5\pgfdecorationsegmentamplitude}%
+        {.5\pgfdecorationsegmentamplitude}%
+      }%
+      {%
+        \pgfqpoint%
+        {-.15\pgfdecorationsegmentamplitude}%
+        {.3\pgfdecorationsegmentamplitude}%
+      }%
+      {\pgfqpoint{0pt}{0pt}}%
+    }%
+    \tikzset{%
+      taper width=.5\pgflinewidth,%
+      taper%
+    }%%
+    \pgfsyssoftpath at getcurrentpath\cal at tmp@path%
+    \CopperplatePath{\cal at tmp@path}%
+  }%
+  \state{final}{}%
+}%
 %    \end{macrocode}
 %
 % The second is a straightened parenthesis (so that when very large it doesn't bow out too far).
@@ -5396,29 +7447,54 @@
 %    \begin{macrocode}
 \pgfdeclaredecoration{calligraphic straight parenthesis}{brace}
 {
-  \state{brace}[width=+\pgfdecoratedremainingdistance,next state=final]
-  {
-    \pgfsyssoftpath at setcurrentpath{\pgfutil at empty}
-    \pgfpathmoveto{\pgfpointorigin}
-    \pgfpathcurveto
-    {\pgfqpoint{.76604\pgfdecorationsegmentamplitude}{.64279\pgfdecorationsegmentamplitude}}
-    {\pgfqpoint{2.3333\pgfdecorationsegmentamplitude}{\pgfdecorationsegmentamplitude}}
-    {\pgfqpoint{3.3333\pgfdecorationsegmentamplitude}{\pgfdecorationsegmentamplitude}}
-    {
-      \pgftransformxshift{+\pgfdecoratedremainingdistance}
-      \pgfpathlineto{\pgfqpoint{-3.3333\pgfdecorationsegmentamplitude}{\pgfdecorationsegmentamplitude}}
-      \pgfpathcurveto
-      {\pgfqpoint{-2.3333\pgfdecorationsegmentamplitude}{\pgfdecorationsegmentamplitude}}
-      {\pgfqpoint{-.76604\pgfdecorationsegmentamplitude}{.64279\pgfdecorationsegmentamplitude}}
-      {\pgfqpoint{0pt}{0pt}}
-    }
-    \tikzset{
-      taper width=.5\pgflinewidth,
-      taper
+  \state{brace}[width=+\pgfdecoratedremainingdistance,next state=final]%
+  {%
+    \pgfsyssoftpath at setcurrentpath{\pgfutil at empty}%
+    \pgfpathmoveto{\pgfpointorigin}%
+    \pgfpathcurveto%
+    {%
+      \pgfqpoint%
+      {.76604\pgfdecorationsegmentamplitude}%
+      {.64279\pgfdecorationsegmentamplitude}%
     }%
-    \pgfsyssoftpath at getcurrentpath\cal at tmp@path
-    \CopperplatePath{\cal at tmp@path}
-  }
+    {%
+      \pgfqpoint%
+      {2.3333\pgfdecorationsegmentamplitude}%
+      {\pgfdecorationsegmentamplitude}%
+    }%
+    {%
+      \pgfqpoint%
+      {3.3333\pgfdecorationsegmentamplitude}%
+      {\pgfdecorationsegmentamplitude}%
+    }%
+    {%
+      \pgftransformxshift{+\pgfdecoratedremainingdistance}%
+      \pgfpathlineto%
+      {%
+        \pgfqpoint%
+        {-3.3333\pgfdecorationsegmentamplitude}%
+        {\pgfdecorationsegmentamplitude}%
+      }%
+      \pgfpathcurveto%
+      {%
+        \pgfqpoint%
+        {-2.3333\pgfdecorationsegmentamplitude}%
+        {\pgfdecorationsegmentamplitude}%
+      }%
+      {%
+        \pgfqpoint%
+        {-.76604\pgfdecorationsegmentamplitude}%
+        {.64279\pgfdecorationsegmentamplitude}%
+      }%
+      {\pgfqpoint{0pt}{0pt}}%
+    }%
+    \tikzset{%
+      taper width=.5\pgflinewidth,%
+      taper%
+    }%
+    \pgfsyssoftpath at getcurrentpath\cal at tmp@path%
+    \CopperplatePath{\cal at tmp@path}%
+  }%
   \state{final}{}%
 }
 %    \end{macrocode}
@@ -5427,24 +7503,28 @@
 %    \begin{macrocode}
 \pgfdeclaredecoration{calligraphic curved parenthesis}{brace}
 {
-  \state{brace}[width=+\pgfdecoratedremainingdistance,next state=final]
-  {
-    \pgfsyssoftpath at setcurrentpath{\pgfutil at empty}
-    \pgfpathmoveto{\pgfpointorigin}
-    \pgf at xa=\pgfdecoratedremainingdistance\relax
-    \advance\pgf at xa by -1.5890\pgfdecorationsegmentamplitude\relax
-    \edef\cgrphy at xa{\the\pgf at xa}
-    \pgfpathcurveto
-    {\pgfqpoint{1.5890\pgfdecorationsegmentamplitude}{1.3333\pgfdecorationsegmentamplitude}}
-    {\pgfqpoint{\cgrphy at xa}{1.3333\pgfdecorationsegmentamplitude}}
-    {\pgfqpoint{\pgfdecoratedremainingdistance}{0pt}}
-    \tikzset{
-      taper width=.5\pgflinewidth,
-      taper
+  \state{brace}[width=+\pgfdecoratedremainingdistance,next state=final]%
+  {%
+    \pgfsyssoftpath at setcurrentpath{\pgfutil at empty}%
+    \pgfpathmoveto{\pgfpointorigin}%
+    \pgf at xa=\pgfdecoratedremainingdistance\relax%
+    \advance\pgf at xa by -1.5890\pgfdecorationsegmentamplitude\relax%
+    \edef\cgrphy at xa{\the\pgf at xa}%
+    \pgfpathcurveto%
+    {%
+      \pgfqpoint%
+      {1.5890\pgfdecorationsegmentamplitude}%
+      {1.3333\pgfdecorationsegmentamplitude}%
     }%
-    \pgfsyssoftpath at getcurrentpath\cal at tmp@path
-    \CopperplatePath{\cal at tmp@path}
-  }
+    {\pgfqpoint{\cgrphy at xa}{1.3333\pgfdecorationsegmentamplitude}}%
+    {\pgfqpoint{\pgfdecoratedremainingdistance}{0pt}}%
+    \tikzset{%
+      taper width=.5\pgflinewidth,%
+      taper%
+    }%
+    \pgfsyssoftpath at getcurrentpath\cal at tmp@path%
+    \CopperplatePath{\cal at tmp@path}%
+  }%
   \state{final}{}%
 }
 %    \end{macrocode}
@@ -5504,6 +7584,7 @@
 \dim_new:N \l_@@_tmpa_dim
 \dim_new:N \l_@@_tmpb_dim
 \dim_new:N \l_@@_tolerance_dim
+\dim_new:N \l_@@_redraw_tolerance_dim
 \dim_new:N \l_@@_clip_bg_radius_dim
 \dim_new:N \l_@@_clip_draw_radius_dim
 
@@ -5747,6 +7828,14 @@
   \pgfscope
   \pgftransformreset
 %    \end{macrocode}
+% Set the dimension for deciding when to include neighbouring strands
+%    \begin{macrocode}
+  \dim_set:Nn \l_@@_redraw_tolerance_dim {\fp_to_dim:n
+    {
+      sqrt(2) * max(\l_@@_clip_bg_radius_dim, \l_@@_clip_draw_radius_dim)
+    }
+  }
+%    \end{macrocode}
 % Loop through the strands drawing each one for the first time.
 %    \begin{macrocode}
   \int_step_function:nnnN {1} {1} {\l_@@_strands_int} \knot_draw_strand:n
@@ -5784,7 +7873,12 @@
     {
       \tl_set:Nn \l_@@_node_tl {
         \exp_not:N \node[coordinate,
-          pin={[node~ contents={\int_use:N \g_@@_intersections_int},knot~ diagram/draft/crossing~ label, knot~ diagram/draft/crossing~ \int_use:N \g_@@_intersections_int \c_space_tl label/.try]
+          pin={[
+              node~ contents={\int_use:N \g_@@_intersections_int},
+              knot~ diagram/draft/crossing~ label,
+              knot~ diagram/draft/crossing~
+              \int_use:N \g_@@_intersections_int \c_space_tl label/.try
+            ]
             }]
       }
     }
@@ -5793,7 +7887,10 @@
 %    \begin{macrocode}
     \int_step_variable:nnnNn {1} {1} {\l_@@_tmpa_int - 1} \l_@@_tmpa_tl
     {
-      \int_step_variable:nnnNn {\tl_use:N \l_@@_tmpa_tl + 1} {1}     {\l_@@_tmpa_int} \l_@@_tmpb_tl
+      \int_step_variable:nnnNn
+      {\tl_use:N \l_@@_tmpa_tl + 1}
+      {1}
+      {\l_@@_tmpa_int} \l_@@_tmpb_tl
       {
         \knot_intersections:VV \l_@@_tmpa_tl \l_@@_tmpb_tl
       }
@@ -5825,7 +7922,12 @@
   \spath_bake_round:c {knot strand #1}
   \tl_set:Nn \l_@@_tmpa_tl {knot~ diagram/every~ strand/.try,}
   \tl_put_right:Nv \l_@@_tmpa_tl {l_@@_options_strand #1}
-  \tl_put_right:Nn \l_@@_tmpa_tl {,knot~ diagram/only~ when~ rendering/.try,only~ when~ rendering/.try}
+  \tl_put_right:Nn \l_@@_tmpa_tl
+  {
+    ,
+    knot~ diagram/only~ when~ rendering/.try,
+    only~ when~ rendering/.try
+  }
   \spath_tikz_path:Vv \l_@@_tmpa_tl {knot strand #1}
   \group_end:
   \endpgfscope
@@ -5845,11 +7947,15 @@
     \spath_finalpoint:Nv \l_@@_tmpb_tl {knot strand #1}
     \dim_set:Nn \l_@@_tmpa_dim {\tl_item:Nn \l_@@_tmpb_tl {1}}
     \dim_set:Nn \l_@@_tmpb_dim {\tl_item:Nn \l_@@_tmpb_tl {2}}
-    \node[knot~ diagram/draft/strand~label] at (\l_@@_tmpa_dim,\l_@@_tmpb_dim) {#1};
+    \node[
+      knot~ diagram/draft/strand~label
+    ] at (\l_@@_tmpa_dim,\l_@@_tmpb_dim) {#1};
     \spath_initialpoint:Nv \l_@@_tmpb_tl {knot strand #1}
     \dim_set:Nn \l_@@_tmpa_dim {\tl_item:Nn \l_@@_tmpb_tl {1}}
     \dim_set:Nn \l_@@_tmpb_dim {\tl_item:Nn \l_@@_tmpb_tl {2}}
-    \node[knot~ diagram/draft/strand~label] at (\l_@@_tmpa_dim,\l_@@_tmpb_dim) {#1};
+    \node[
+      knot~ diagram/draft/strand~label
+    ] at (\l_@@_tmpa_dim,\l_@@_tmpb_dim) {#1};
   }
   \bool_if:nT {
     \l_@@_self_intersections_bool
@@ -5858,6 +7964,8 @@
   }
   {
     \tl_clear:N \l_@@_tmpa_tl
+    \spath_initialpoint:Nv \l_@@_tmpa_tl {knot strand #1}
+    \tl_put_left:NV \l_@@_tmpa_tl \c_spath_moveto_tl
     \spath_segments_to_seq:Nv \l_@@_segments_seq {knot strand #1}
     \seq_map_function:NN \l_@@_segments_seq \knot_split_self_intersects:N
     \tl_set_eq:cN {knot strand #1} \l_@@_tmpa_tl
@@ -5881,23 +7989,29 @@
     {
       \fp_set:Nn \l_@@_tmpa_fp
       {
-        (\tl_item:nn {#1} {3} - 3 * \tl_item:nn {#1} {6} + 3 * \tl_item:nn {#1} {9} - \tl_item:nn {#1} {12})
+        (\tl_item:nn {#1} {3} - 3 * \tl_item:nn {#1} {6}
+        + 3 * \tl_item:nn {#1} {9} - \tl_item:nn {#1} {12})
         *
         (3 * \tl_item:nn {#1} {8} - 3 * \tl_item:nn {#1} {11})
         -
-        (\tl_item:nn {#1} {2} - 3 * \tl_item:nn {#1} {5} + 3 * \tl_item:nn {#1} {8} - \tl_item:nn {#1} {11})
+        (\tl_item:nn {#1} {2} - 3 * \tl_item:nn {#1} {5}
+        + 3 * \tl_item:nn {#1} {8} - \tl_item:nn {#1} {11})
         *
         (3 * \tl_item:nn {#1} {9} - 3 * \tl_item:nn {#1} {12})
       }
       \fp_set:Nn \l_@@_tmpb_fp
       {
-        (\tl_item:nn {#1} {2} - 3 * \tl_item:nn {#1} {5} + 3 * \tl_item:nn {#1} {8} - \tl_item:nn {#1} {11})
+        (\tl_item:nn {#1} {2} - 3 * \tl_item:nn {#1} {5}
+        + 3 * \tl_item:nn {#1} {8} - \tl_item:nn {#1} {11})
         *
-        (3 * \tl_item:nn {#1} {6} - 6 * \tl_item:nn {#1} {9} + 3 * \tl_item:nn {#1} {12})
+        (3 * \tl_item:nn {#1} {6} - 6 * \tl_item:nn {#1} {9}
+        + 3 * \tl_item:nn {#1} {12})
         -
-        (\tl_item:nn {#1} {3} - 3 * \tl_item:nn {#1} {6} + 3 * \tl_item:nn {#1} {9} - \tl_item:nn {#1} {12})
+        (\tl_item:nn {#1} {3} - 3 * \tl_item:nn {#1} {6}
+        + 3 * \tl_item:nn {#1} {9} - \tl_item:nn {#1} {12})
         *
-        (3 * \tl_item:nn {#1} {5} - 6 * \tl_item:nn {#1} {8} + 3 * \tl_item:nn {#1} {11})
+        (3 * \tl_item:nn {#1} {5} - 6 * \tl_item:nn {#1} {8}
+        + 3 * \tl_item:nn {#1} {11})
       }
       \fp_compare:nTF
       {
@@ -5910,7 +8024,11 @@
           0 < \l_@@_tmpa_fp && \l_@@_tmpa_fp < 1
         }
         {
-          \spath_split_curve:NNnV \l_@@_tmpc_tl \l_@@_tmpd_tl {#1} \l_@@_tmpa_fp
+          \spath_split_curve:NNnV
+          \l_@@_tmpc_tl
+          \l_@@_tmpd_tl
+          {#1}
+          \l_@@_tmpa_fp
           \tl_set:Nx \l_@@_tmpc_tl {\tl_tail:N \l_@@_tmpc_tl}
           \tl_set:Nx \l_@@_tmpc_tl {\tl_tail:N \l_@@_tmpc_tl}
           \tl_set:Nx \l_@@_tmpc_tl {\tl_tail:N \l_@@_tmpc_tl}
@@ -5968,19 +8086,33 @@
   \bool_if:nTF {
     \l_@@_save_bool
     &&
-    \tl_if_exist_p:c {knot~ intersections~ \tl_use:N \l_@@_name_tl - \tl_use:N \l_@@_tmpa_tl -  \tl_use:N \l_@@_tmpb_tl}
+    \tl_if_exist_p:c {
+      knot~ intersections~
+      \tl_use:N \l_@@_name_tl -
+      \tl_use:N \l_@@_tmpa_tl -
+      \tl_use:N \l_@@_tmpb_tl
+    }
   }
   {
-    \tl_use:c {knot~ intersections~ \tl_use:N \l_@@_name_tl - \tl_use:N \l_@@_tmpa_tl -  \tl_use:N \l_@@_tmpb_tl}
+    \tl_use:c
+    {
+      knot~ intersections~ \tl_use:N \l_@@_name_tl -
+      \tl_use:N \l_@@_tmpa_tl -
+      \tl_use:N \l_@@_tmpb_tl
+    }
   }
   {
-\pgfintersectionofpaths{\pgfsetpath\l_@@_tmpc_tl}{\pgfsetpath\l_@@_tmpd_tl}
+    \pgfintersectionofpaths{\pgfsetpath\l_@@_tmpc_tl}{\pgfsetpath\l_@@_tmpd_tl}
 
   }
 
   \int_compare:nT {\pgfintersectionsolutions > 0}
   {
-    \int_step_function:nnnN {1} {1} {\pgfintersectionsolutions} \knot_do_intersection:n
+    \int_step_function:nnnN
+    {1}
+    {1}
+    {\pgfintersectionsolutions}
+    \knot_do_intersection:n
   }
 
   \knot_save_intersections:VV \l_@@_tmpa_tl \l_@@_tmpb_tl
@@ -6017,7 +8149,16 @@
         }
         \tl_put_right:Nx \l_@@_aux_tl
         {
-          {\exp_not:N \pgf at x=\dim_use:N \l_@@_tmpa_dim\exp_not:N\relax\exp_not:N \pgf at y =\dim_use:N \l_@@_tmpb_dim\relax}
+          {
+            \exp_not:N \pgf at x
+            =
+            \dim_use:N \l_@@_tmpa_dim
+            \exp_not:N \relax
+            \exp_not:N \pgf at y
+            =
+            \dim_use:N \l_@@_tmpb_dim
+            \exp_not:N \relax
+          }
         }
       }
       \tl_set:Nn \l_@@_auxa_tl {\expandafter \gdef \csname knot~ intersections~}
@@ -6057,7 +8198,7 @@
     \tl_set:Nv \l_@@_tmpc_tl \l_@@_tmpc_tl
     \tl_if_eq:NNT \l_@@_tmpc_tl \l_@@_tmpb_tl
     {
-      \knot_test_endpoint:VnT \l_@@_tmpb_tl {final point}
+      \knot_test_endpoint:NVnT \l_@@_tolerance_dim \l_@@_tmpb_tl {final point}
       {
         \bool_set_true:N \l_@@_skip_bool
       }
@@ -6068,7 +8209,7 @@
     \tl_set:Nv \l_@@_tmpc_tl \l_@@_tmpc_tl
     \tl_if_eq:NNT \l_@@_tmpc_tl \l_@@_tmpa_tl
     {
-      \knot_test_endpoint:VnT \l_@@_tmpa_tl {final point}
+      \knot_test_endpoint:NVnT \l_@@_tolerance_dim \l_@@_tmpa_tl {final point}
       {
         \bool_set_true:N \l_@@_skip_bool
       }
@@ -6079,19 +8220,19 @@
 %    \begin{macrocode}
   \bool_if:NT \l_@@_ignore_ends_bool
   {
-    \knot_test_endpoint:VnT \l_@@_tmpa_tl {initial point}
+    \knot_test_endpoint:NVnT \l_@@_tolerance_dim \l_@@_tmpa_tl {initial point}
     {
       \bool_set_true:N \l_@@_skip_bool
     }
-    \knot_test_endpoint:VnT \l_@@_tmpa_tl {final point}
+    \knot_test_endpoint:NVnT \l_@@_tolerance_dim \l_@@_tmpa_tl {final point}
     {
       \bool_set_true:N \l_@@_skip_bool
     }
-    \knot_test_endpoint:VnT \l_@@_tmpb_tl {initial point}
+    \knot_test_endpoint:NVnT \l_@@_tolerance_dim \l_@@_tmpb_tl {initial point}
     {
       \bool_set_true:N \l_@@_skip_bool
     }
-    \knot_test_endpoint:VnT \l_@@_tmpb_tl {final point}
+    \knot_test_endpoint:NVnT \l_@@_tolerance_dim \l_@@_tmpb_tl {final point}
     {
       \bool_set_true:N \l_@@_skip_bool
     }
@@ -6140,7 +8281,8 @@
 %    \begin{macrocode} 
       \bool_if:NT \l_@@_self_intersections_bool
       {
-        \knot_test_endpoint:VnT \l_@@_tmpg_tl {initial point}
+        \knot_test_endpoint:NVnT
+        \l_@@_redraw_tolerance_dim \l_@@_tmpg_tl {initial point}
         {
           \bool_set_true:N \l_@@_prepend_prev_bool
         }
@@ -6147,7 +8289,8 @@
         {
           \bool_set_false:N \l_@@_prepend_prev_bool
         }
-        \knot_test_endpoint:VnT \l_@@_tmpg_tl {final point}
+        \knot_test_endpoint:NVnT
+        \l_@@_redraw_tolerance_dim \l_@@_tmpg_tl {final point}
         {
           \bool_set_true:N \l_@@_append_next_bool
         }
@@ -6163,10 +8306,14 @@
         }
         {
           \tl_clear_new:c {knot \tl_use:N \l_@@_prefix_tl -1}
-          \tl_set_eq:cc {knot \tl_use:N \l_@@_prefix_tl -1} {knot \tl_use:N \l_@@_tmpg_tl}
+          \tl_set_eq:cc
+          {knot \tl_use:N \l_@@_prefix_tl -1}
+          {knot \tl_use:N \l_@@_tmpg_tl}
 
           \tl_clear_new:c {l_@@_options_ \tl_use:N \l_@@_prefix_tl -1}
-          \tl_set_eq:cc {l_@@_options_ \tl_use:N \l_@@_prefix_tl -1} {l_@@_options_ \tl_use:N \l_@@_tmpg_tl}
+          \tl_set_eq:cc
+          {l_@@_options_ \tl_use:N \l_@@_prefix_tl -1}
+          {l_@@_options_ \tl_use:N \l_@@_tmpg_tl}
 
           \bool_if:nT
           {
@@ -6177,7 +8324,9 @@
             !\tl_if_empty_p:c {knot previous \tl_use:N \l_@@_tmpg_tl}
           }
           {
-            \spath_prepend_no_move:cv {knot \tl_use:N \l_@@_prefix_tl -1} {knot \tl_use:c {knot previous \tl_use:N \l_@@_tmpg_tl}}
+            \spath_prepend_no_move:cv
+            {knot \tl_use:N \l_@@_prefix_tl -1}
+            {knot \tl_use:c {knot previous \tl_use:N \l_@@_tmpg_tl}}
 %    \end{macrocode}
 % If we split potentially self intersecting curves, we test to see if we should prepend yet another segment.
 %    \begin{macrocode}
@@ -6190,10 +8339,18 @@
               !\tl_if_empty_p:c {knot previous \tl_use:N \l_@@_tmpg_tl}
             }
             {
-              \knot_test_endpoint:vnT {knot previous \tl_use:N \l_@@_tmpg_tl} {initial point}
+              \knot_test_endpoint:NvnT
+              \l_@@_redraw_tolerance_dim
+              {knot previous \tl_use:N \l_@@_tmpg_tl}
+              {initial point}
               {
-                
-                \spath_prepend_no_move:cv {knot \tl_use:N \l_@@_prefix_tl -1} {knot \tl_use:c {knot previous \tl_use:c {knot previous \tl_use:N \l_@@_tmpg_tl}}}
+                \spath_prepend_no_move:cv
+                {knot \tl_use:N \l_@@_prefix_tl -1}
+                {knot \tl_use:c
+                  {knot previous \tl_use:c
+                    {knot previous \tl_use:N \l_@@_tmpg_tl}
+                  }
+                }
                 \tl_set_eq:Nc \l_@@_tmpa_tl {knot \tl_use:N \l_@@_prefix_tl -1}
               }
             }
@@ -6210,7 +8367,9 @@
             !\tl_if_empty_p:c {knot previous \tl_use:N \l_@@_tmpg_tl}
           }
           {
-            \spath_append_no_move:cv {knot \tl_use:N \l_@@_prefix_tl -1} {knot \tl_use:c {knot next \tl_use:N \l_@@_tmpg_tl}}
+            \spath_append_no_move:cv
+            {knot \tl_use:N \l_@@_prefix_tl -1}
+            {knot \tl_use:c {knot next \tl_use:N \l_@@_tmpg_tl}}
             \bool_if:nT
             {
               \l_@@_splits_bool
@@ -6221,14 +8380,21 @@
               !\tl_if_empty_p:c {knot previous \tl_use:N \l_@@_tmpg_tl}
             }
             {
-              \knot_test_endpoint:vnT {knot previous \tl_use:N \l_@@_tmpg_tl} {final point}
+              \knot_test_endpoint:NvnT
+              \l_@@_redraw_tolerance_dim
+              {knot previous \tl_use:N \l_@@_tmpg_tl}
+              {final point}
               {
-                \spath_append_no_move:cv {knot \tl_use:N \l_@@_prefix_tl -1} {knot \tl_use:c {knot next \tl_use:c {knot next \tl_use:N \l_@@_tmpg_tl}}}
-                
+                \spath_append_no_move:cv
+                {knot \tl_use:N \l_@@_prefix_tl -1}
+                {knot \tl_use:c
+                  {knot next \tl_use:c
+                    {knot next \tl_use:N \l_@@_tmpg_tl}
+                  }
+                }
               }
             }
           }
-
           \tl_set:Nn \l_@@_tmpg_tl {\tl_use:N \l_@@_prefix_tl -1}
         }
       }
@@ -6237,9 +8403,15 @@
 %    \begin{macrocode}
       \pgfscope
       \group_begin:
-      \tikzset{knot~ diagram/every~ intersection/.try, every~ intersection/.try, knot~ diagram/intersection~ \int_use:N \g_@@_intersections_int/.try}
+      \tikzset{
+        knot~ diagram/every~ intersection/.try,
+        every~ intersection/.try,
+        knot~ diagram/intersection~ \int_use:N \g_@@_intersections_int/.try
+      }
       \knot_draw_crossing:VVV \l_@@_tmpg_tl \l_@@_tmpa_dim \l_@@_tmpb_dim
-      \coordinate (\l_@@_name_tl \c_space_tl \int_use:N \g_@@_intersections_int) at (\dim_use:N \l_@@_tmpa_dim, \dim_use:N \l_@@_tmpb_dim);
+      \coordinate
+      (\l_@@_name_tl \c_space_tl \int_use:N \g_@@_intersections_int)
+      at (\dim_use:N \l_@@_tmpa_dim, \dim_use:N \l_@@_tmpb_dim);
       \group_end:
       \endpgfscope
 %    \end{macrocode}
@@ -6251,7 +8423,13 @@
 %    \begin{macrocode}
     \tl_if_empty:NF \l_@@_node_tl
     {
-      \seq_gpush:Nx \g_@@_nodes_seq { \l_@@_node_tl at (\dim_use:N \l_@@_tmpa_dim, \dim_use:N \l_@@_tmpb_dim) {};}
+      \seq_gpush:Nx
+      \g_@@_nodes_seq
+      {
+        \l_@@_node_tl
+        at
+        (\dim_use:N \l_@@_tmpa_dim, \dim_use:N \l_@@_tmpb_dim) {};
+      }
     }
   }
 }
@@ -6263,15 +8441,15 @@
 % \begin{macro}[internal]{\knot_test_endpoint:N}
 % Test whether the point is near the intersection point.
 %    \begin{macrocode}
-\prg_new_conditional:Npnn \knot_test_endpoint:N #1 {p,T,F,TF}
+\prg_new_conditional:Npnn \knot_test_endpoint:NN #1#2 {p,T,F,TF}
 {
   \dim_compare:nTF
   {
-    \dim_abs:n { \l_@@_tmpa_dim - \tl_item:Nn #1 {1}}
+    \dim_abs:n { \l_@@_tmpa_dim - \tl_item:Nn #2 {1}}
     +
-    \dim_abs:n { \l_@@_tmpb_dim - \tl_item:Nn #1 {2}}
+    \dim_abs:n { \l_@@_tmpb_dim - \tl_item:Nn #2 {2}}
     <
-    \l_@@_tolerance_dim
+    #1
   }
   {
     \prg_return_true:
@@ -6286,10 +8464,10 @@
 % \begin{macro}[internal]{\knot_test_endpoint:nn}
 % Wrapper around the above.
 %    \begin{macrocode}
-\prg_new_protected_conditional:Npnn \knot_test_endpoint:nn #1#2 {T,F,TF}
+\prg_new_protected_conditional:Npnn \knot_test_endpoint:Nnn #1#2#3 {T,F,TF}
 {
-  \use:c {spath_#2:Nv} \l_@@_tmpd_tl {knot #1}
-  \knot_test_endpoint:NTF \l_@@_tmpd_tl
+  \use:c {spath_#3:Nv} \l_@@_tmpd_tl {knot #2}
+  \knot_test_endpoint:NNTF #1 \l_@@_tmpd_tl
   {
     \prg_return_true:
   }
@@ -6298,9 +8476,9 @@
   }
 }
 
-\cs_generate_variant:Nn \knot_test_endpoint:nnT {VnT,vnT}
-\cs_generate_variant:Nn \knot_test_endpoint:nnF {VnF,vnF}
-\cs_generate_variant:Nn \knot_test_endpoint:nnTF {VnTF,vnTF}
+\cs_generate_variant:Nn \knot_test_endpoint:NnnT {NVnT,NvnT}
+\cs_generate_variant:Nn \knot_test_endpoint:NnnF {NVnF,NvnF}
+\cs_generate_variant:Nn \knot_test_endpoint:NnnTF {NVnTF,NvnTF}
 %    \end{macrocode}
 % \end{macro}
 %
@@ -6311,7 +8489,8 @@
 {
   \group_begin:
   \pgfscope
-  \path[knot~ diagram/background~ clip] (#2, #3) circle[radius=\l_@@_clip_bg_radius_dim];
+  \path[knot~ diagram/background~ clip] (#2, #3)
+  circle[radius=\l_@@_clip_bg_radius_dim];
 
   \tl_set:Nn \l_@@_tmpa_tl {knot~ diagram/every~ strand/.try,}
   \tl_if_exist:cT {l_@@_options_ #1}
@@ -6318,13 +8497,18 @@
   {
   \tl_put_right:Nv \l_@@_tmpa_tl {l_@@_options_ #1}
   }
-  \tl_put_right:Nn \l_@@_tmpa_tl {,knotbg,line~ width= \tl_use:N \l_@@_clip_width_tl * \pgflinewidth}
+  \tl_put_right:Nn \l_@@_tmpa_tl
+  {
+    ,knotbg
+    ,line~ width= \tl_use:N \l_@@_clip_width_tl * \pgflinewidth
+  }
   \spath_tikz_path:Vv \l_@@_tmpa_tl {knot #1}
 
   \endpgfscope
 
   \pgfscope
-  \path[knot~ diagram/clip] (#2, #3) circle[radius=\l_@@_clip_draw_radius_dim];
+  \path[knot~ diagram/clip] (#2, #3)
+  circle[radius=\l_@@_clip_draw_radius_dim];
 
   \tl_set:Nn \l_@@_tmpa_tl {knot~ diagram/every~ strand/.try,}
   \tl_if_exist:cT {l_@@_options_ #1}
@@ -6331,7 +8515,11 @@
   {
   \tl_put_right:Nv \l_@@_tmpa_tl {l_@@_options_ #1}
   }
-  \tl_put_right:Nn \l_@@_tmpa_tl {,knot~ diagram/only~ when~ rendering/.try,only~ when~ rendering/.try}
+  \tl_put_right:Nn \l_@@_tmpa_tl
+  {
+    ,knot~ diagram/only~ when~ rendering/.try
+    ,only~ when~ rendering/.try
+  }
   \spath_tikz_path:Vv \l_@@_tmpa_tl {knot #1}
 
   \endpgfscope
@@ -6408,12 +8596,14 @@
       \tl_set:cn {knot filament \int_use:N \g_@@_filaments_int} {#1}
       
       \tl_clear_new:c {l_@@_options_filament \int_use:N \g_@@_filaments_int}
-      \tl_set_eq:cN {l_@@_options_filament \int_use:N \g_@@_filaments_int} \l_@@_tmpa_tl
+      \tl_set_eq:cN {l_@@_options_filament \int_use:N \g_@@_filaments_int}
+      \l_@@_tmpa_tl
 
       \tl_clear_new:c {knot previous filament \int_use:N \g_@@_filaments_int}
       \int_compare:nF {\l_@@_component_start_int == \g_@@_filaments_int}
       {
-        \tl_set:cx {knot previous filament \int_use:N \g_@@_filaments_int} {filament \int_eval:n {\g_@@_filaments_int - 1}}
+        \tl_set:cx {knot previous filament \int_use:N \g_@@_filaments_int}
+        {filament \int_eval:n {\g_@@_filaments_int - 1}}
       }
     }
     \c_spath_curvetoa_tl
@@ -6422,12 +8612,15 @@
       \tl_clear_new:c {knot filament \int_use:N \g_@@_filaments_int}
       \tl_set:cn {knot filament \int_use:N \g_@@_filaments_int} {#1}
       \tl_clear_new:c {l_@@_options_filament \int_use:N \g_@@_filaments_int}
-      \tl_set_eq:cN {l_@@_options_filament \int_use:N \g_@@_filaments_int} \l_@@_tmpa_tl
+      \tl_set_eq:cN {l_@@_options_filament \int_use:N \g_@@_filaments_int}
+      \l_@@_tmpa_tl
 
       \tl_clear_new:c {knot previous filament \int_use:N \g_@@_filaments_int}
       \int_compare:nF {\l_@@_component_start_int == \g_@@_filaments_int}
       {
-        \tl_set:cx {knot previous filament \int_use:N \g_@@_filaments_int} {filament \int_eval:n {\g_@@_filaments_int - 1}}
+        \tl_set:cx
+        {knot previous filament \int_use:N \g_@@_filaments_int}
+        {filament \int_eval:n {\g_@@_filaments_int - 1}}
       }
     }
     \c_spath_closepath_tl
@@ -6435,18 +8628,26 @@
       \int_gincr:N \g_@@_filaments_int
       \tl_clear_new:c {knot filament \int_use:N \g_@@_filaments_int}
       \tl_clear:N \l_@@_tmpa_tl
-      \tl_put_right:Nx {\tl_item:nn {#1} {1}\tl_item:nn {#1} {2}\tl_item:nn {#1} {3}}
+      \tl_put_right:Nx
+      {
+        \tl_item:nn {#1} {1}\tl_item:nn {#1} {2}\tl_item:nn {#1} {3}
+      }
       \tl_put_right:NV \l_@@_tmpa_tl \c_spath_lineto_tl
       \tl_put_right:Nx {\tl_item:nn {#1} {5}\tl_item:nn {#1} {6}}
 
       \tl_set:cV {knot filament \int_use:N \g_@@_filaments_int} \l_@@_tmpa_tl
-      \tl_set_eq:cN {l_@@_options_filament \int_use:N \g_@@_filaments_int} \l_@@_tmpa_tl
+      \tl_set_eq:cN {l_@@_options_filament \int_use:N \g_@@_filaments_int}
+      \l_@@_tmpa_tl
       \tl_clear_new:c {knot previous filament \int_use:N \g_@@_filaments_int}
       \int_compare:nF {\l_@@_component_start_int == \g_@@_filaments_int}
       {
-        \tl_set:cx {knot previous filament \int_use:N \g_@@_filaments_int} {filament \int_eval:n {\g_@@_filaments_int - 1}}
+        \tl_set:cx
+        {knot previous filament \int_use:N \g_@@_filaments_int}
+        {filament \int_eval:n {\g_@@_filaments_int - 1}}
       }
-      \tl_set:cx {knot previous filament \int_use:N \l_@@_component_start_int} {filament \int_use:N \g_@@_filaments_int}
+      \tl_set:cx
+      {knot previous filament \int_use:N \l_@@_component_start_int}
+      {filament \int_use:N \g_@@_filaments_int}
     }
   }
   {

Modified: trunk/Master/texmf-dist/source/latex/spath3/spath3_code.ins
===================================================================
--- trunk/Master/texmf-dist/source/latex/spath3/spath3_code.ins	2021-02-06 22:28:55 UTC (rev 57638)
+++ trunk/Master/texmf-dist/source/latex/spath3/spath3_code.ins	2021-02-06 22:29:38 UTC (rev 57639)
@@ -26,7 +26,7 @@
 \endpreamble
 \postamble
 
-Copyright (C) 2011-2019 by Andrew Stacey <loopspace at mathforge.org>
+Copyright (C) 2011-2021 by Andrew Stacey <loopspace at mathforge.org>
 
 This work may be distributed and/or modified under the
 conditions of the LaTeX Project Public License (LPPL), either
@@ -38,7 +38,7 @@
 This work is "maintained" (as per LPPL maintenance status) by
 Andrew Stacey.
 
-This work consists of the files  spath3.dtx
+This work consists of the files  spath3_code.dtx
                                  calligraphy_doc.tex
                                  knots_doc.tex
                                  spath3.tex
@@ -69,7 +69,7 @@
 }
 \endbatchfile
 %% 
-%% Copyright (C) 2011-2019 by Andrew Stacey <loopspace at mathforge.org>
+%% Copyright (C) 2011-2021 by Andrew Stacey <loopspace at mathforge.org>
 %% 
 %% This work may be distributed and/or modified under the
 %% conditions of the LaTeX Project Public License (LPPL), either
@@ -81,7 +81,7 @@
 %% This work is "maintained" (as per LPPL maintenance status) by
 %% Andrew Stacey.
 %% 
-%% This work consists of the files  spath3.dtx
+%% This work consists of the files  spath3_code.dtx
 %%                                  calligraphy_doc.tex
 %%                                  knots_doc.tex
 %%                                  spath3.tex

Modified: trunk/Master/texmf-dist/tex/latex/spath3/spath3.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/spath3/spath3.sty	2021-02-06 22:28:55 UTC (rev 57638)
+++ trunk/Master/texmf-dist/tex/latex/spath3/spath3.sty	2021-02-06 22:29:38 UTC (rev 57639)
@@ -15,7 +15,7 @@
 \NeedsTeXFormat{LaTeX2e}
 \RequirePackage{expl3}
 \RequirePackage{pgf}
-\ProvidesExplPackage {spath3} {2021/01/19} {2.0} {Functions for
+\ProvidesExplPackage {spath3} {2021/02/05} {2.2} {Functions for
 manipulating PGF soft paths}
 \RequirePackage{xparse}
 \cs_new_protected:Nn \__spath_tl_put_right_braced:Nn
@@ -40,29 +40,40 @@
   \tl_gput_left:Nn #1 { { #2 } }
 }
 \cs_generate_variant:Nn \__spath_tl_gput_left_braced:Nn { NV, cV, cv, Nx, cx }
+\tl_new:N \g__spath_output_tl
+\int_new:N \g__spath_output_int
+\seq_new:N \g__spath_output_seq
+\bool_new:N \g__spath_output_bool
 \tl_new:N \l__spath_tmpa_tl
 \tl_new:N \l__spath_tmpb_tl
 \tl_new:N \l__spath_tmpc_tl
 \tl_new:N \l__spath_tmpd_tl
 \tl_new:N \l__spath_tmpe_tl
+\tl_new:N \l__spath_tmpf_tl
+\tl_new:N \l__spath_tmpg_tl
+\tl_new:N \l__spath_tmph_tl
+\tl_new:N \l__spath_tmpi_tl
 
 \seq_new:N \l__spath_tmpa_seq
 \seq_new:N \l__spath_tmpb_seq
+\seq_new:N \l__spath_tmpc_seq
 
-\tl_new:N \g__spath_output_tl
-\int_new:N \g__spath_output_int
-\seq_new:N \g__spath_output_seq
-
 \dim_new:N \l__spath_tmpa_dim
 \dim_new:N \l__spath_tmpb_dim
-\dim_new:N \l__spath_move_x_dim
-\dim_new:N \l__spath_move_y_dim
+
 \fp_new:N \l__spath_tmpa_fp
 \fp_new:N \l__spath_tmpb_fp
+\fp_new:N \l__spath_tmpc_fp
+
 \int_new:N \l__spath_tmpa_int
+\int_new:N \l__spath_tmpb_int
 
-\bool_new:N \g__spath_output_bool
+\bool_new:N \l__spath_tmpa_bool
+\dim_new:N \l__spath_move_x_dim
+\dim_new:N \l__spath_move_y_dim
 \bool_new:N \l__spath_closed_bool
+\tl_new:N \l__spath_intersecta_tl
+\tl_new:N \l__spath_intersectb_tl
 \tl_const:Nn \c_spath_moveto_tl {\pgfsyssoftpath at movetotoken}
 \tl_const:Nn \c_spath_lineto_tl {\pgfsyssoftpath at linetotoken}
 \tl_const:Nn \c_spath_curveto_tl {\pgfsyssoftpath at curvetotoken}
@@ -71,47 +82,40 @@
 \tl_const:Nn \c_spath_closepath_tl {\pgfsyssoftpath at closepathtoken}
 \int_new:N \g__spath_anon_int
 \int_gzero:N \g__spath_anon_int
-\tl_new:N \l__spath_itera_tl
-\tl_new:N \l__spath_iterb_tl
-\tl_new:N \l__spath_iterc_tl
-\tl_new:N \l__spath_iterd_tl
-\tl_new:N \l__spath_iterp_tl
-\dim_new:N \l__spath_itera_dim
-\dim_new:N \l__spath_iterb_dim
-\seq_new:N \l__spath_iter_seq
-\msg_new:nnn { spath3 } { unknown path construction } { The~ path~ construction~ element~ #1~ is~ not~ currently~ supported.}
+\msg_new:nnn { spath3 } { unknown path construction }
+{ The~ path~ construction~ element~ #1~ is~ not~ currently~ supported.}
 \cs_new_protected_nopar:Npn \__spath_segments_to_seq:n #1
 {
   \group_begin:
-  \tl_set:Nn \l__spath_itera_tl {#1}
-  \tl_clear:N \l__spath_iterb_tl
-  \seq_clear:N \l__spath_iter_seq
-  \dim_zero:N \l__spath_itera_dim
-  \dim_zero:N \l__spath_iterb_dim
+  \tl_set:Nn \l__spath_tmpa_tl {#1}
+  \tl_clear:N \l__spath_tmpb_tl
+  \seq_clear:N \l__spath_tmpa_seq
+  \dim_zero:N \l__spath_tmpa_dim
+  \dim_zero:N \l__spath_tmpb_dim
 
   \bool_until_do:nn {
-    \tl_if_empty_p:N \l__spath_itera_tl
+    \tl_if_empty_p:N \l__spath_tmpa_tl
   }
   {
-    \tl_set:Nx \l__spath_iterc_tl {\tl_head:N \l__spath_itera_tl}
-    \tl_set:Nx \l__spath_itera_tl {\tl_tail:N \l__spath_itera_tl}
-    \tl_case:NnF \l__spath_iterc_tl
+    \tl_set:Nx \l__spath_tmpc_tl {\tl_head:N \l__spath_tmpa_tl}
+    \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
+    \tl_case:NnF \l__spath_tmpc_tl
     {
       \c_spath_moveto_tl
       {
-        \tl_set_eq:NN \l__spath_iterb_tl \c_spath_moveto_tl
-        \tl_put_right:Nx \l__spath_iterb_tl {{\tl_head:N \l__spath_itera_tl}}
-        \dim_set:Nn \l__spath_itera_dim {\tl_head:N \l__spath_itera_tl}
-        \tl_set:Nx \l__spath_itera_tl {\tl_tail:N \l__spath_itera_tl}
+        \tl_set_eq:NN \l__spath_tmpb_tl \c_spath_moveto_tl
+        \tl_put_right:Nx \l__spath_tmpb_tl {{\tl_head:N \l__spath_tmpa_tl}}
+        \dim_set:Nn \l__spath_tmpa_dim {\tl_head:N \l__spath_tmpa_tl}
+        \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
 
-        \tl_put_right:Nx \l__spath_iterb_tl {{\tl_head:N \l__spath_itera_tl}}
-        \dim_set:Nn \l__spath_iterb_dim {\tl_head:N \l__spath_itera_tl}
-        \tl_set:Nx \l__spath_itera_tl {\tl_tail:N \l__spath_itera_tl}
+        \tl_put_right:Nx \l__spath_tmpb_tl {{\tl_head:N \l__spath_tmpa_tl}}
+        \dim_set:Nn \l__spath_tmpb_dim {\tl_head:N \l__spath_tmpa_tl}
+        \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
 
-        \tl_set:Nx \l__spath_iterd_tl {\tl_head:N \l__spath_itera_tl}
-        \tl_if_eq:NNF \l__spath_iterd_tl \c_spath_moveto_tl
+        \tl_set:Nx \l__spath_tmpd_tl {\tl_head:N \l__spath_tmpa_tl}
+        \tl_if_eq:NNF \l__spath_tmpd_tl \c_spath_moveto_tl
         {
-          \tl_clear:N \l__spath_iterb_tl
+          \tl_clear:N \l__spath_tmpb_tl
         }
 
       }
@@ -118,70 +122,70 @@
 
       \c_spath_lineto_tl
       {
-        \tl_set_eq:NN \l__spath_iterb_tl \c_spath_moveto_tl
-        \tl_put_right:Nx \l__spath_iterb_tl
+        \tl_set_eq:NN \l__spath_tmpb_tl \c_spath_moveto_tl
+        \tl_put_right:Nx \l__spath_tmpb_tl
         {
-          {\dim_use:N \l__spath_itera_dim}
-          {\dim_use:N \l__spath_iterb_dim}
+          {\dim_use:N \l__spath_tmpa_dim}
+          {\dim_use:N \l__spath_tmpb_dim}
         }
-        \tl_put_right:NV \l__spath_iterb_tl \c_spath_lineto_tl
+        \tl_put_right:NV \l__spath_tmpb_tl \c_spath_lineto_tl
 
-        \tl_put_right:Nx \l__spath_iterb_tl {{\tl_head:N \l__spath_itera_tl}}
-        \dim_set:Nn \l__spath_itera_dim {\tl_head:N \l__spath_itera_tl}
-        \tl_set:Nx \l__spath_itera_tl {\tl_tail:N \l__spath_itera_tl}
+        \tl_put_right:Nx \l__spath_tmpb_tl {{\tl_head:N \l__spath_tmpa_tl}}
+        \dim_set:Nn \l__spath_tmpa_dim {\tl_head:N \l__spath_tmpa_tl}
+        \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
 
-        \tl_put_right:Nx \l__spath_iterb_tl {{\tl_head:N \l__spath_itera_tl}}
-        \dim_set:Nn \l__spath_iterb_dim {\tl_head:N \l__spath_itera_tl}
-        \tl_set:Nx \l__spath_itera_tl {\tl_tail:N \l__spath_itera_tl}
+        \tl_put_right:Nx \l__spath_tmpb_tl {{\tl_head:N \l__spath_tmpa_tl}}
+        \dim_set:Nn \l__spath_tmpb_dim {\tl_head:N \l__spath_tmpa_tl}
+        \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
 
       }
 
       \c_spath_curvetoa_tl
       {
-        \tl_set_eq:NN \l__spath_iterb_tl \c_spath_moveto_tl
-        \tl_put_right:Nx \l__spath_iterb_tl
+        \tl_set_eq:NN \l__spath_tmpb_tl \c_spath_moveto_tl
+        \tl_put_right:Nx \l__spath_tmpb_tl
         {
-          {\dim_use:N \l__spath_itera_dim}
-          {\dim_use:N \l__spath_iterb_dim}
+          {\dim_use:N \l__spath_tmpa_dim}
+          {\dim_use:N \l__spath_tmpb_dim}
         }
-        \tl_put_right:NV \l__spath_iterb_tl \c_spath_curvetoa_tl
+        \tl_put_right:NV \l__spath_tmpb_tl \c_spath_curvetoa_tl
 
         \prg_replicate:nn {2} {
-          \tl_put_right:Nx \l__spath_iterb_tl {{\tl_head:N \l__spath_itera_tl}}
-          \tl_set:Nx \l__spath_itera_tl {\tl_tail:N \l__spath_itera_tl}
-          \tl_put_right:Nx \l__spath_iterb_tl {{\tl_head:N               \l__spath_itera_tl}}
-          \tl_set:Nx \l__spath_itera_tl {\tl_tail:N \l__spath_itera_tl}
-          \tl_put_right:Nx \l__spath_iterb_tl {\tl_head:N             \l__spath_itera_tl}
-          \tl_set:Nx \l__spath_itera_tl {\tl_tail:N \l__spath_itera_tl}
+          \tl_put_right:Nx \l__spath_tmpb_tl {{\tl_head:N \l__spath_tmpa_tl}}
+          \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
+          \tl_put_right:Nx \l__spath_tmpb_tl {{\tl_head:N \l__spath_tmpa_tl}}
+          \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
+          \tl_put_right:Nx \l__spath_tmpb_tl {\tl_head:N \l__spath_tmpa_tl}
+          \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
         }
 
-        \tl_put_right:Nx \l__spath_iterb_tl {{\tl_head:N \l__spath_itera_tl}}
-        \dim_set:Nn \l__spath_itera_dim {\tl_head:N \l__spath_itera_tl}
-        \tl_set:Nx \l__spath_itera_tl {\tl_tail:N \l__spath_itera_tl}
+        \tl_put_right:Nx \l__spath_tmpb_tl {{\tl_head:N \l__spath_tmpa_tl}}
+        \dim_set:Nn \l__spath_tmpa_dim {\tl_head:N \l__spath_tmpa_tl}
+        \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
 
-        \tl_put_right:Nx \l__spath_iterb_tl {{\tl_head:N \l__spath_itera_tl}}
-        \dim_set:Nn \l__spath_iterb_dim {\tl_head:N \l__spath_itera_tl}
-        \tl_set:Nx \l__spath_itera_tl {\tl_tail:N \l__spath_itera_tl}
+        \tl_put_right:Nx \l__spath_tmpb_tl {{\tl_head:N \l__spath_tmpa_tl}}
+        \dim_set:Nn \l__spath_tmpb_dim {\tl_head:N \l__spath_tmpa_tl}
+        \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
 
       }
 
       \c_spath_closepath_tl
       {
-        \tl_set_eq:NN \l__spath_iterb_tl \c_spath_moveto_tl
-        \tl_put_right:Nx \l__spath_iterb_tl
+        \tl_set_eq:NN \l__spath_tmpb_tl \c_spath_moveto_tl
+        \tl_put_right:Nx \l__spath_tmpb_tl
         {
-          {\dim_use:N \l__spath_itera_dim}
-          {\dim_use:N \l__spath_iterb_dim}
+          {\dim_use:N \l__spath_tmpa_dim}
+          {\dim_use:N \l__spath_tmpb_dim}
         }
-        \tl_put_right:NV \l__spath_iterb_tl \c_spath_lineto_tl
+        \tl_put_right:NV \l__spath_tmpb_tl \c_spath_lineto_tl
 
-        \tl_put_right:Nx \l__spath_iterb_tl {{\tl_head:N \l__spath_itera_tl}}
-        \dim_set:Nn \l__spath_itera_dim {\tl_head:N \l__spath_itera_tl}
-        \tl_set:Nx \l__spath_itera_tl {\tl_tail:N \l__spath_itera_tl}
+        \tl_put_right:Nx \l__spath_tmpb_tl {{\tl_head:N \l__spath_tmpa_tl}}
+        \dim_set:Nn \l__spath_tmpa_dim {\tl_head:N \l__spath_tmpa_tl}
+        \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
 
-        \tl_put_right:Nx \l__spath_iterb_tl {{\tl_head:N \l__spath_itera_tl}}
-        \dim_set:Nn \l__spath_iterb_dim {\tl_head:N \l__spath_itera_tl}
-        \tl_set:Nx \l__spath_itera_tl {\tl_tail:N \l__spath_itera_tl}
+        \tl_put_right:Nx \l__spath_tmpb_tl {{\tl_head:N \l__spath_tmpa_tl}}
+        \dim_set:Nn \l__spath_tmpb_dim {\tl_head:N \l__spath_tmpa_tl}
+        \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
 
       }
 
@@ -188,26 +192,26 @@
     }
     {
 
-      \tl_set_eq:NN \l__spath_iterb_tl \l__spath_iterc_tl
-      \tl_put_right:Nx \l__spath_iterb_tl {{\tl_head:N \l__spath_itera_tl}}
-      \dim_set:Nn \l__spath_itera_dim {\tl_head:N \l__spath_itera_tl}
-      \tl_set:Nx \l__spath_itera_tl {\tl_tail:N \l__spath_itera_tl}
+      \tl_set_eq:NN \l__spath_tmpb_tl \l__spath_tmpc_tl
+      \tl_put_right:Nx \l__spath_tmpb_tl {{\tl_head:N \l__spath_tmpa_tl}}
+      \dim_set:Nn \l__spath_tmpa_dim {\tl_head:N \l__spath_tmpa_tl}
+      \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
 
-      \tl_put_right:Nx \l__spath_iterb_tl {{\tl_head:N \l__spath_itera_tl}}
-      \dim_set:Nn \l__spath_iterb_dim {\tl_head:N \l__spath_itera_tl}
-      \tl_set:Nx \l__spath_itera_tl {\tl_tail:N \l__spath_itera_tl}
+      \tl_put_right:Nx \l__spath_tmpb_tl {{\tl_head:N \l__spath_tmpa_tl}}
+      \dim_set:Nn \l__spath_tmpb_dim {\tl_head:N \l__spath_tmpa_tl}
+      \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
 
     }
 
-    \tl_if_empty:NF \l__spath_iterb_tl
+    \tl_if_empty:NF \l__spath_tmpb_tl
     {
-      \seq_put_right:NV \l__spath_iter_seq \l__spath_iterb_tl
+      \seq_put_right:NV \l__spath_tmpa_seq \l__spath_tmpb_tl
     }
-    \tl_clear:N \l__spath_iterb_tl
+    \tl_clear:N \l__spath_tmpb_tl
   }
 
   \seq_gclear:N \g__spath_output_seq
-  \seq_gset_eq:NN \g__spath_output_seq \l__spath_iter_seq
+  \seq_gset_eq:NN \g__spath_output_seq \l__spath_tmpa_seq
   \group_end:
 }
 \cs_new_protected_nopar:Npn \spath_segments_to_seq:Nn #1#2
@@ -229,33 +233,33 @@
 \cs_new_protected_nopar:Npn \__spath_components_to_seq:n #1
 {
   \group_begin:
-  \tl_set:Nn \l__spath_itera_tl {#1}
-  \seq_clear:N \l__spath_iter_seq
-  \tl_set:Nx \l__spath_itera_tl {\tl_tail:N \l__spath_itera_tl}
-  \tl_put_right:NV \l__spath_itera_tl \c_spath_moveto_tl
-  \tl_set_eq:NN \l__spath_iterb_tl \c_spath_moveto_tl
+  \tl_set:Nn \l__spath_tmpa_tl {#1}
+  \seq_clear:N \l__spath_tmpa_seq
+  \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
+  \tl_put_right:NV \l__spath_tmpa_tl \c_spath_moveto_tl
+  \tl_set_eq:NN \l__spath_tmpb_tl \c_spath_moveto_tl
   \bool_do_until:nn {
-    \tl_if_empty_p:N \l__spath_itera_tl
+    \tl_if_empty_p:N \l__spath_tmpa_tl
   }
   {
-    \tl_set:Nx \l__spath_iterc_tl {\tl_head:N \l__spath_itera_tl}
-    \tl_if_eq:NNT \l__spath_iterc_tl \c_spath_moveto_tl
+    \tl_set:Nx \l__spath_tmpc_tl {\tl_head:N \l__spath_tmpa_tl}
+    \tl_if_eq:NNT \l__spath_tmpc_tl \c_spath_moveto_tl
     {
-      \seq_put_right:NV \l__spath_iter_seq \l__spath_iterb_tl
-      \tl_clear:N \l__spath_iterb_tl
+      \seq_put_right:NV \l__spath_tmpa_seq \l__spath_tmpb_tl
+      \tl_clear:N \l__spath_tmpb_tl
     }
-    \tl_if_single:NTF \l__spath_iterc_tl
+    \tl_if_single:NTF \l__spath_tmpc_tl
     {
-      \tl_put_right:NV \l__spath_iterb_tl \l__spath_iterc_tl
+      \tl_put_right:NV \l__spath_tmpb_tl \l__spath_tmpc_tl
     }
     {
-      \tl_put_right:Nx \l__spath_iterb_tl {{\l__spath_iterc_tl}}
+      \tl_put_right:Nx \l__spath_tmpb_tl {{\l__spath_tmpc_tl}}
     }
-    \tl_set:Nx \l__spath_itera_tl {\tl_tail:N \l__spath_itera_tl}
+    \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
   }
 
   \seq_gclear:N \g__spath_output_seq
-  \seq_gset_eq:NN \g__spath_output_seq \l__spath_iter_seq
+  \seq_gset_eq:NN \g__spath_output_seq \l__spath_tmpa_seq
   \group_end:
 }
 \cs_new_protected_nopar:Npn \spath_components_to_seq:Nn #1#2
@@ -300,8 +304,8 @@
   \group_begin:
   \int_set:Nn \l__spath_tmpa_int {0}
   \tl_map_inline:nn {#1} {
-    \tl_set:Nn \l__spath_tmpc_tl {##1}
-    \tl_case:NnT \l__spath_tmpc_tl
+    \tl_set:Nn \l__spath_tmpa_tl {##1}
+    \tl_case:NnT \l__spath_tmpa_tl
     {
       \c_spath_lineto_tl {}
       \c_spath_curveto_tl {}
@@ -353,7 +357,7 @@
   \int_set_eq:NN #1 \g__spath_output_int
   \int_gzero:N \g__spath_output_int
 }
-\cs_generate_variant:Nn \spath_numberofcomponents:Nn {NV, cn, cV}
+\cs_generate_variant:Nn \spath_numberofcomponents:Nn {NV, cn, cV, Nv}
 \cs_new_protected_nopar:Npn \spath_gnumberofcomponents:Nn #1#2
 {
   \__spath_numberofcomponents:n {#2}
@@ -360,17 +364,17 @@
   \int_gset_eq:NN #1 \g__spath_output_int
   \int_gzero:N \g__spath_output_int
 }
-\cs_generate_variant:Nn \spath_gnumberofcomponents:Nn {NV, cn, cV}
+\cs_generate_variant:Nn \spath_gnumberofcomponents:Nn {NV, cn, cV, Nv}
 \cs_new_protected_nopar:Npn \__spath_initialpoint:n #1
 {
   \group_begin:
-  \tl_clear:N \l__spath_tmpb_tl
-  \tl_set:Nx \l__spath_tmpb_tl
+  \tl_clear:N \l__spath_tmpa_tl
+  \tl_set:Nx \l__spath_tmpa_tl
   {
     { \tl_item:nn {#1} {2} }
     { \tl_item:nn {#1} {3} }
   }
-  \tl_gset_eq:NN \g__spath_output_tl \l__spath_tmpb_tl
+  \tl_gset_eq:NN \g__spath_output_tl \l__spath_tmpa_tl
   \group_end:
 }
 \cs_new_protected_nopar:Npn \spath_initialpoint:Nn #1#2
@@ -415,6 +419,50 @@
   \tl_gclear:N \g__spath_output_tl
 }
 \cs_generate_variant:Nn \spath_gfinalpoint:Nn {NV, cn, cV, Nv}
+\cs_new_protected_nopar:Npn \__spath_finalmovepoint:n #1
+{
+  \group_begin:
+  \tl_set:Nn \l__spath_tmpc_tl { {0pt} {0pt} }
+  \tl_set:Nn \l__spath_tmpa_tl {#1}
+  \bool_do_until:nn
+  {
+    \tl_if_empty_p:N \l__spath_tmpa_tl
+  }
+  {
+    \tl_set:Nx \l__spath_tmpb_tl {\tl_head:N \l__spath_tmpa_tl}
+    \tl_case:Nn \l__spath_tmpb_tl
+    {
+      \c_spath_moveto_tl
+      {
+        \tl_set:Nx \l__spath_tmpc_tl
+        {
+          { \tl_item:Nn \l__spath_tmpa_tl {2} }
+          { \tl_item:Nn \l__spath_tmpa_tl {3} }
+        }
+      }
+    }
+    \prg_replicate:nn {3}
+    {
+      \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
+    }
+  }
+  \tl_gset_eq:NN \g__spath_output_tl \l__spath_tmpc_tl
+  \group_end:
+}
+\cs_new_protected_nopar:Npn \spath_finalmovepoint:Nn #1#2
+{
+  \__spath_finalmovepoint:n {#2}
+  \tl_set_eq:NN #1 \g__spath_output_tl
+  \tl_gclear:N \g__spath_output_tl
+}
+\cs_generate_variant:Nn \spath_finalmovepoint:Nn {NV, cn, cV}
+\cs_new_protected_nopar:Npn \spath_gfinalmovepoint:Nn #1#2
+{
+  \__spath_finalmovepoint:n {#2}
+  \tl_gset_eq:NN #1 \g__spath_output_tl
+  \tl_gclear:N \g__spath_output_tl
+}
+\cs_generate_variant:Nn \spath_gfinalmovepoint:Nn {NV, cn, cV}
 \cs_new_protected_nopar:Npn \__spath_reverse:n #1
 {
   \group_begin:
@@ -495,7 +543,10 @@
         \bool_set_true:N \l__spath_closed_bool
       }
       {
-        \msg_warning:nnx { spath3 } { unknown path construction } {\l__spath_tmpc_tl }
+        \msg_warning:nnx
+        { spath3 }
+        { unknown path construction }
+        {\l__spath_tmpc_tl }
       }
 
       \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
@@ -629,9 +680,11 @@
   }
   {
     \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
-    \dim_set:Nn \l__spath_tmpa_dim {\dim_min:nn {\tl_head:N \l__spath_tmpa_tl} {\l__spath_tmpa_dim}}
+    \dim_set:Nn \l__spath_tmpa_dim
+    {\dim_min:nn {\tl_head:N \l__spath_tmpa_tl} {\l__spath_tmpa_dim}}
     \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
-    \dim_set:Nn \l__spath_tmpb_dim {\dim_min:nn {\tl_head:N \l__spath_tmpa_tl} {\l__spath_tmpb_dim}}
+    \dim_set:Nn \l__spath_tmpb_dim
+    {\dim_min:nn {\tl_head:N \l__spath_tmpa_tl} {\l__spath_tmpb_dim}}
     \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
   }
   \tl_clear:N \l__spath_tmpb_tl
@@ -671,9 +724,11 @@
   }
   {
     \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
-    \dim_set:Nn \l__spath_tmpa_dim {\dim_max:nn {\tl_head:N \l__spath_tmpa_tl} {\l__spath_tmpa_dim}}
+    \dim_set:Nn \l__spath_tmpa_dim
+    {\dim_max:nn {\tl_head:N \l__spath_tmpa_tl} {\l__spath_tmpa_dim}}
     \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
-    \dim_set:Nn \l__spath_tmpb_dim {\dim_max:nn {\tl_head:N \l__spath_tmpa_tl} {\l__spath_tmpb_dim}}
+    \dim_set:Nn \l__spath_tmpb_dim
+    {\dim_max:nn {\tl_head:N \l__spath_tmpa_tl} {\l__spath_tmpb_dim}}
     \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
   }
   \tl_clear:N \l__spath_tmpb_tl
@@ -752,6 +807,7 @@
   \tl_gset_eq:NN \g__spath_output_tl \l__spath_tmpb_tl
   \group_end:
 }
+\cs_generate_variant:Nn \__spath_translate:nnn {nVV}
 \cs_new_protected_nopar:Npn \spath_translate:Nnnn #1#2#3#4
 {
   \__spath_translate:nnn {#2}{#3}{#4}
@@ -786,6 +842,61 @@
   \spath_gtranslate:Nnn #1 #2
 }
 \cs_generate_variant:Nn \spath_gtranslate:Nn {NV}
+\cs_new_protected_nopar:Npn \__spath_translate_to:nnn #1#2#3
+{
+  \group_begin:
+  \spath_initialpoint:Nn \l__spath_tmpa_tl {#1}
+
+  \dim_set:Nn \l__spath_tmpa_dim
+  {
+    #2
+    -
+    \tl_item:Nn \l__spath_tmpa_tl {1}
+  }
+  \dim_set:Nn \l__spath_tmpb_dim
+  {
+    #3
+    -
+    \tl_item:Nn \l__spath_tmpa_tl {2}
+  }
+
+  \__spath_translate:nVV {#1} \l__spath_tmpa_dim \l__spath_tmpb_dim
+  \group_end:
+}
+\cs_new_protected_nopar:Npn \spath_translate_to:Nnnn #1#2#3#4
+{
+  \__spath_translate_to:nnn {#2}{#3}{#4}
+  \tl_set_eq:NN #1 \g__spath_output_tl
+  \tl_gclear:N \g__spath_output_tl
+}
+\cs_generate_variant:Nn \spath_translate_to:Nnnn {NVxx, NVVV, NVnn}
+\cs_new_protected_nopar:Npn \spath_translate_to:Nnn #1#2#3
+{
+  \spath_translate_to:NVnn #1#1{#2}{#3}
+}
+\cs_generate_variant:Nn \spath_translate_to:Nnn {NVV, cnn, cVV}
+\cs_new_protected_nopar:Npn \spath_gtranslate_to:Nnnn #1#2#3#4
+{
+  \__spath_translate_to:nnn {#2}{#3}{#4}
+  \tl_gset_eq:NN #1 \g__spath_output_tl
+  \tl_gclear:N \g__spath_output_tl
+}
+\cs_generate_variant:Nn \spath_gtranslate_to:Nnnn {NVxx, NVVV, NVnn}
+\cs_new_protected_nopar:Npn \spath_gtranslate_to:Nnn #1#2#3
+{
+  \spath_gtranslate_to:NVnn #1#1{#2}{#3}
+}
+\cs_generate_variant:Nn \spath_gtranslate_to:Nnn {NVV, cnn, cVV}
+\cs_new_protected_nopar:Npn \spath_translate_to:Nn #1#2
+{
+  \spath_translate_to:Nnn #1 #2
+}
+\cs_generate_variant:Nn \spath_translate_to:Nn {NV}
+\cs_new_protected_nopar:Npn \spath_gtranslate_to:Nn #1#2
+{
+  \spath_gtranslate_to:Nnn #1 #2
+}
+\cs_generate_variant:Nn \spath_gtranslate_to:Nn {NV}
 \cs_new_protected_nopar:Npn \__spath_scale:nnn #1#2#3
 {
   \group_begin:
@@ -865,8 +976,10 @@
     \tl_set:Nx \l__spath_tmpd_tl {\tl_head:N \l__spath_tmpa_tl}
     \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
 
-    \fp_set:Nn \l__spath_tmpa_fp {\l__spath_tmpc_tl * #2 + \l__spath_tmpd_tl * #4 + #6}
-    \fp_set:Nn \l__spath_tmpb_fp {\l__spath_tmpc_tl * #3 + \l__spath_tmpd_tl * #5 + #7}
+    \fp_set:Nn \l__spath_tmpa_fp
+    {\l__spath_tmpc_tl * #2 + \l__spath_tmpd_tl * #4 + #6}
+    \fp_set:Nn \l__spath_tmpb_fp
+    {\l__spath_tmpc_tl * #3 + \l__spath_tmpd_tl * #5 + #7}
     \tl_put_right:Nx \l__spath_tmpb_tl
     {
       {\fp_to_dim:N \l__spath_tmpa_fp}
@@ -883,7 +996,8 @@
   \tl_set_eq:NN #1 \g__spath_output_tl
   \tl_gclear:N \g__spath_output_tl
 }
-\cs_generate_variant:Nn \spath_transform:Nnnnnnnn {NVnnnnnn, Nnxxxxxx, cnnnnnnn}
+\cs_generate_variant:Nn \spath_transform:Nnnnnnnn
+{NVnnnnnn, Nnxxxxxx, cnnnnnnn}
 \cs_new_protected_nopar:Npn \spath_transform:Nnnnnnn #1#2#3#4#5#6#7
 {
   \spath_transform:NVnnnnnn #1#1{#2}{#3}{#4}{#5}{#6}{#7}
@@ -922,39 +1036,276 @@
   \spath_gtransform:NVnnnnnn #1#1#2
 }
 \cs_generate_variant:Nn \spath_gtransform:Nn {cn, cV, NV}
-\cs_new_protected_nopar:Npn \__spath_weld:nn #1#2
+\cs_new_protected_nopar:Npn \__spath_span:nnn #1#2#3
 {
   \group_begin:
-  \tl_set:Nn \l__spath_tmpa_tl {#1}
-  \tl_set:Nn \l__spath_tmpb_tl {#2}
+  \spath_initialpoint:Nn \l__spath_tmpa_tl {#1}
+  \spath_finalpoint:Nn \l__spath_tmpb_tl {#1}
 
-  \spath_finalpoint:NV \l__spath_tmpc_tl \l__spath_tmpa_tl
-  \spath_initialpoint:NV \l__spath_tmpd_tl \l__spath_tmpb_tl
-
-  \dim_set:Nn \l__spath_tmpa_dim
+  \fp_set:Nn \l__spath_tmpa_fp
   {
-    \tl_item:Nn \l__spath_tmpc_tl {1}
-    -
-    \tl_item:Nn \l__spath_tmpd_tl {1}
+    (\tl_item:Nn \l__spath_tmpb_tl {1}) -
+    (\tl_item:Nn \l__spath_tmpa_tl {1})
   }
-  \dim_set:Nn \l__spath_tmpb_dim
+  \fp_set:Nn \l__spath_tmpb_fp
   {
-    \tl_item:Nn \l__spath_tmpc_tl {2}
-    -
-    \tl_item:Nn \l__spath_tmpd_tl {2}
+    (\tl_item:Nn \l__spath_tmpb_tl {2}) -
+    (\tl_item:Nn \l__spath_tmpa_tl {2})
   }
+  \fp_set:Nn \l__spath_tmpc_fp
+  {
+    (\l__spath_tmpa_fp) * (\l__spath_tmpa_fp)
+    +
+    (\l__spath_tmpb_fp * \l__spath_tmpb_fp)
+  }
 
-  \spath_translate:NVV \l__spath_tmpb_tl \l__spath_tmpa_dim \l__spath_tmpb_dim
-
-  \prg_replicate:nn {3}
+  \fp_compare:nTF
   {
-    \tl_set:Nx \l__spath_tmpb_tl {\tl_tail:N \l__spath_tmpb_tl}
+    \l__spath_tmpc_fp < 0.001
   }
+  {
+    \spath_translate_to:Nnnn \l__spath_tmpd_tl {#1} #2
+  }
+  {
+    \fp_set:Nn \l__spath_tmpa_fp
+    {
+      (
+      ((\tl_item:nn {#3} {1})
+      -
+      (\tl_item:nn {#2} {1}))
+      *
+      ((\tl_item:Nn \l__spath_tmpb_tl {1})
+      -
+      (\tl_item:Nn \l__spath_tmpa_tl {1}))
+      +
+      ((\tl_item:nn {#3} {2})
+      -
+      (\tl_item:nn {#2} {2}))
+      *
+      ((\tl_item:Nn \l__spath_tmpb_tl {2})
+      -
+      (\tl_item:Nn \l__spath_tmpa_tl {2}))
+      )
+      /
+      \l__spath_tmpc_fp
+    }
+    \fp_set:Nn \l__spath_tmpb_fp
+    {
+      (
+      ((\tl_item:nn {#3} {2})
+      -
+      (\tl_item:nn {#2} {2}))
+      *
+      ((\tl_item:Nn \l__spath_tmpb_tl {1})
+      -
+      (\tl_item:Nn \l__spath_tmpa_tl {1}))
+      -
+      ((\tl_item:nn {#3} {1})
+      -
+      (\tl_item:nn {#2} {1}))
+      *
+      ((\tl_item:Nn \l__spath_tmpb_tl {2})
+      -
+      (\tl_item:Nn \l__spath_tmpa_tl {2}))
+      )
+      /
+      \l__spath_tmpc_fp
+    }
 
-  \tl_put_right:NV \l__spath_tmpa_tl \l__spath_tmpb_tl
+    \tl_set:Nx \l__spath_tmpc_tl
+    {
+      {
+        \fp_to_decimal:N \l__spath_tmpa_fp
+      }
+      {
+        \fp_to_decimal:N \l__spath_tmpb_fp
+      }
+      {
+        \fp_eval:n { - \l__spath_tmpb_fp }
+      }
+      {
+        \fp_to_decimal:N \l__spath_tmpa_fp
+      }
+      {
+        \fp_to_dim:n
+        {
+          \tl_item:nn {#2} {1}
+          -
+          \l__spath_tmpa_fp * (\tl_item:Nn \l__spath_tmpa_tl {1})
+          +
+          \l__spath_tmpb_fp * (\tl_item:Nn \l__spath_tmpa_tl {2})
+        }
+      }
+      {
+        \fp_to_dim:n
+        {
+          \tl_item:nn {#2} {2}
+          -
+          \l__spath_tmpb_fp * (\tl_item:Nn \l__spath_tmpa_tl {1})
+          -
+          \l__spath_tmpa_fp * (\tl_item:Nn \l__spath_tmpa_tl {2})
+        }
+      }
+    }
+    \spath_transform:NnV \l__spath_tmpd_tl {#1} \l__spath_tmpc_tl
+  }
+  \tl_gset_eq:NN \g__spath_output_tl \l__spath_tmpd_tl
+  \group_end:
+}
+\cs_new_protected_nopar:Npn \spath_span:Nnnn #1#2#3#4
+{
+  \__spath_span:nnn {#2}{#3}{#4}
+  \tl_set_eq:NN #1 \g__spath_output_tl
+  \tl_gclear:N \g__spath_output_tl
+}
+\cs_generate_variant:Nn \spath_span:Nnnn {NVnn, NVVV, NnVV}
+\cs_new_protected_nopar:Npn \spath_span:Nnn #1#2#3
+{
+  \spath_span:NVnn #1#1{#2}{#3}
+}
+\cs_generate_variant:Nn \spath_span:Nnn {NVV, cnn, cvv, cVV}
+\cs_new_protected_nopar:Npn \spath_gspan:Nnnn #1#2#3#4
+{
+  \__spath_span:nnn {#2}{#3}{#4}
+  \tl_gset_eq:NN #1 \g__spath_output_tl
+  \tl_gclear:N \g__spath_output_tl
+}
+\cs_generate_variant:Nn \spath_gspan:Nnnn {NVnn, NVVV}
+\cs_new_protected_nopar:Npn \spath_gspan:Nnn #1#2#3
+{
+  \spath_gspan:NVnn #1#1{#2}{#3}
+}
+\cs_generate_variant:Nn \spath_gspan:Nnn {NVV, cnn, cvv, cVV}
+\cs_new_protected_nopar:Npn \__spath_normalise:n #1
+{
+  \__spath_span:nnn {#1}{{0pt}{0pt}}{{1pt}{0pt}}
+}
+\cs_new_protected_nopar:Npn \spath_normalise:Nn #1#2
+{
+  \__spath_normalise:n {#2}
+  \tl_set_eq:NN #1 \g__spath_output_tl
+  \tl_gclear:N \g__spath_output_tl
+}
+\cs_generate_variant:Nn \spath_normalise:Nn {cn,NV, cV, cv}
+\cs_new_protected_nopar:Npn \spath_normalise:N #1
+{
+  \spath_normalise:NV #1#1
+}
+\cs_generate_variant:Nn \spath_normalise:N {c}
+\cs_new_protected_nopar:Npn \spath_gnormalise:Nn #1#2
+{
+  \__spath_normalise:n {#2}
+  \tl_gset_eq:NN #1 \g__spath_output_tl
+  \tl_gclear:N \g__spath_output_tl
+}
+\cs_generate_variant:Nn \spath_gnormalise:Nn {cn,NV, cV, cv}
+\cs_new_protected_nopar:Npn \spath_gnormalise:N #1
+{
+  \spath_gnormalise:NV #1#1
+}
+\cs_generate_variant:Nn \spath_gnormalise:N {c}
+\cs_new_protected_nopar:Npn \__spath_splice_between:nnn #1#2#3
+{
+  \group_begin:
+  \spath_finalpoint:NV \l__spath_tmpd_tl {#1}
+  \spath_initialpoint:NV \l__spath_tmpe_tl {#3}
+  \spath_span:NnVV \l__spath_tmpb_tl {#2} \l__spath_tmpd_tl \l__spath_tmpe_tl
+  \spath_append_no_move:NnV \l__spath_tmpa_tl {#1} \l__spath_tmpb_tl
+  \spath_append_no_move:Nn \l__spath_tmpa_tl {#3}
   \tl_gset_eq:NN \g__spath_output_tl \l__spath_tmpa_tl
   \group_end:
 }
+\cs_new_protected_nopar:Npn \spath_splice_between:Nnnn #1#2#3#4
+{
+  \__spath_splice_between:nnn {#2}{#3}{#4}
+  \tl_set_eq:NN #1 \g__spath_output_tl
+  \tl_gclear:N \g__spath_output_tl
+}
+\cs_generate_variant:Nn \spath_splice_between:Nnnn {NVnn, NVVV}
+\cs_new_protected_nopar:Npn \spath_splice_between:Nnn #1#2#3
+{
+  \spath_splice_between:NVnn #1#1{#2}{#3}
+}
+\cs_generate_variant:Nn \spath_splice_between:Nnn {NVV, cnn, cvv, Nvn}
+\cs_new_protected_nopar:Npn \spath_gsplice_between:Nnnn #1#2#3#4
+{
+  \__spath_splice_between:nnn {#2}{#3}{#4}
+  \tl_gset_eq:NN #1 \g__spath_output_tl
+  \tl_gclear:N \g__spath_output_tl
+}
+\cs_generate_variant:Nn \spath_gsplice_between:Nnnn {NVnn, NVVV}
+\cs_new_protected_nopar:Npn \spath_gsplice_between:Nnn #1#2#3
+{
+  \spath_gsplice_between:NVnn #1#1{#2}{#3}
+}
+\cs_generate_variant:Nn \spath_gsplice_between:Nnn {NVV, cnn, cvv}
+\cs_new_protected_nopar:Npn \__spath_close_with:nn #1#2
+{
+  \group_begin:
+  \spath_finalmovepoint:Nn \l__spath_tmpa_tl {#1}
+  \spath_finalpoint:Nn \l__spath_tmpb_tl {#1}
+  \dim_compare:nTF
+  {
+    \dim_abs:n
+    {
+      \tl_item:Nn \l__spath_tmpa_tl {1}
+      -
+      \tl_item:Nn \l__spath_tmpb_tl {1}
+    }
+    +
+    \dim_abs:n
+    {
+      \tl_item:Nn \l__spath_tmpa_tl {2}
+      -
+      \tl_item:Nn \l__spath_tmpb_tl {2}
+    }
+    < 0.01pt
+  }
+  {
+    \__spath_close:n {#1}
+  }
+  {
+    \spath_span:NnVV \l__spath_tmpc_tl {#2} \l__spath_tmpb_tl \l__spath_tmpa_tl
+    \spath_append_no_move:NnV \l__spath_tmpd_tl {#1} \l__spath_tmpc_tl
+    \__spath_close:V \l__spath_tmpd_tl
+  }
+  \group_end:
+}
+\cs_new_protected_nopar:Npn \spath_close_with:Nnn #1#2#3
+{
+  \__spath_close_with:nn {#2}{#3}
+  \tl_set_eq:NN #1 \g__spath_output_tl
+  \tl_gclear:N \g__spath_output_tl
+}
+\cs_generate_variant:Nn \spath_close_with:Nnn {cnn, cVV, cvv, NVn}
+\cs_new_protected_nopar:Npn \spath_close_with:Nn #1#2
+{
+  \spath_close_with:NVn #1#1{#2}
+}
+\cs_generate_variant:Nn \spath_close_with:Nn {cn, cV, cv, NV}
+\cs_new_protected_nopar:Npn \spath_gclose_with:Nnn #1#2#3
+{
+  \__spath_close_with:nn {#2}{#3}
+  \tl_gset_eq:NN #1 \g__spath_output_tl
+  \tl_gclear:N \g__spath_output_tl
+}
+\cs_generate_variant:Nn \spath_gclose_with:Nnn {cnn, cVV, cvv, NVn}
+\cs_new_protected_nopar:Npn \spath_gclose_with:Nn #1#2
+{
+  \spath_gclose_with:NVn #1#1{#2}
+}
+\cs_generate_variant:Nn \spath_gclose_with:Nn {cn, cV, cv, NV}
+\cs_new_protected_nopar:Npn \__spath_weld:nn #1#2
+{
+  \group_begin:
+  \tl_set:Nn \l__spath_tmpa_tl {#1}
+  \tl_set:Nn \l__spath_tmpb_tl {#2}
+  \spath_finalpoint:Nn \l__spath_tmpc_tl {#1}
+  \spath_translate_to:NV \l__spath_tmpb_tl \l__spath_tmpc_tl
+
+  \__spath_append_no_move:VV \l__spath_tmpa_tl \l__spath_tmpb_tl
+  \group_end:
+}
 \cs_new_protected_nopar:Npn \spath_weld:Nnn #1#2#3
 {
   \__spath_weld:nn {#2}{#3}
@@ -992,6 +1343,7 @@
   \tl_gset_eq:NN \g__spath_output_tl \l__spath_tmpa_tl
   \group_end:
 }
+\cs_generate_variant:Nn \__spath_append_no_move:nn {VV}
 \cs_new_protected_nopar:Npn \spath_append_no_move:Nnn #1#2#3
 {
   \__spath_append_no_move:nn {#2}{#3}
@@ -998,12 +1350,12 @@
   \tl_set_eq:NN #1 \g__spath_output_tl
   \tl_gclear:N \g__spath_output_tl
 }
-\cs_generate_variant:Nn \spath_append_no_move:Nnn {NVV, NVn}
+\cs_generate_variant:Nn \spath_append_no_move:Nnn {NVV, NVn, NnV}
 \cs_new_protected_nopar:Npn \spath_append_no_move:Nn #1#2
 {
   \spath_append_no_move:NVn #1#1{#2}
 }
-\cs_generate_variant:Nn \spath_append_no_move:Nn {NV, cv}
+\cs_generate_variant:Nn \spath_append_no_move:Nn {NV, cv, Nv}
 \cs_new_protected_nopar:Npn \spath_gappend_no_move:Nnn #1#2#3
 {
   \__spath_append_no_move:nn {#2}{#3}
@@ -1015,7 +1367,7 @@
 {
   \spath_gappend_no_move:NVn #1#1{#2}
 }
-\cs_generate_variant:Nn \spath_gappend_no_move:Nn {NV, cv}
+\cs_generate_variant:Nn \spath_gappend_no_move:Nn {NV, cv, Nv}
 \cs_new_protected_nopar:Npn \spath_append:Nnn #1#2#3
 {
   \tl_set:Nn #1 {#2}
@@ -1026,7 +1378,7 @@
 {
   \spath_append:NVn #1#1{#2}
 }
-\cs_generate_variant:Nn \spath_append:Nn {NV, Nv}
+\cs_generate_variant:Nn \spath_append:Nn {NV, Nv, cv}
 \cs_new_protected_nopar:Npn \spath_gappend:Nnn #1#2#3
 {
   \tl_gset:Nn #1 {#2}
@@ -1037,7 +1389,7 @@
 {
   \spath_gappend:NVn #1#1{#2}
 }
-\cs_generate_variant:Nn \spath_gappend:Nn {NV, Nv}
+\cs_generate_variant:Nn \spath_gappend:Nn {NV, Nv, cv}
 \cs_new_protected_nopar:Npn \spath_prepend_no_move:Nnn #1#2#3
 {
   \spath_append_no_move:Nnn #1{#3}{#2}
@@ -1114,12 +1466,13 @@
 {
   \group_begin:
   \tl_set:Nn \l__spath_tmpa_tl {#1}
-  \spath_initialpoint:NV \l__spath_tmpb_tl \l__spath_tmpa_tl
+  \spath_finalmovepoint:NV \l__spath_tmpb_tl \l__spath_tmpa_tl
   \tl_put_right:NV \l__spath_tmpa_tl \c_spath_closepath_tl
   \tl_put_right:NV \l__spath_tmpa_tl \l__spath_tmpb_tl
   \tl_gset_eq:NN \g__spath_output_tl \l__spath_tmpa_tl
   \group_end:
 }
+\cs_generate_variant:Nn \__spath_close:n {V}
 \cs_new_protected_nopar:Npn \spath_close:Nn #1#2
 {
   \__spath_close:n {#2}
@@ -1291,7 +1644,10 @@
   \tl_set:Nn \l__spath_tmpa_tl {#1}
   \tl_set:Nn \l__spath_tmpb_tl {#2}
   \bool_gset_true:N \g__spath_tmpa_bool
-  \int_compare:nNnTF {\tl_count:N \l__spath_tmpa_tl} = {\tl_count:N \l__spath_tmpb_tl}
+  \int_compare:nNnTF
+  {\tl_count:N \l__spath_tmpa_tl}
+  =
+  {\tl_count:N \l__spath_tmpb_tl}
   {
     \int_step_inline:nnnn {1} {3} {\tl_count:N \l__spath_tmpa_tl}
     {
@@ -1303,14 +1659,28 @@
       }
       \dim_set:Nn \l__spath_tmpa_dim {\tl_item:Nn \l__spath_tmpa_tl {##1+1}}
       \dim_set:Nn \l__spath_tmpb_dim {\tl_item:Nn \l__spath_tmpb_tl {##1+1}}
-      \dim_compare:nF { \dim_abs:n { \l__spath_tmpa_dim - \l__spath_tmpb_dim} < 0.001pt }
+      \dim_compare:nF
       {
+        \dim_abs:n
+        {
+          \l__spath_tmpa_dim - \l__spath_tmpb_dim
+        }
+        < 0.001pt
+      }
+      {
         \bool_gset_false:N \g__spath_tmpa_bool
       }
       \dim_set:Nn \l__spath_tmpa_dim {\tl_item:Nn \l__spath_tmpa_tl {##1+2}}
       \dim_set:Nn \l__spath_tmpb_dim {\tl_item:Nn \l__spath_tmpb_tl {##1+2}}
-      \dim_compare:nF { \dim_abs:n { \l__spath_tmpa_dim - \l__spath_tmpb_dim} < 0.001pt }
+      \dim_compare:nF
       {
+        \dim_abs:n
+        {
+          \l__spath_tmpa_dim - \l__spath_tmpb_dim
+        }
+        < 0.001pt
+      }
+      {
         \bool_gset_false:N \g__spath_tmpa_bool
       }
     }
@@ -1354,11 +1724,15 @@
   {
     {\fp_to_dim:n
     {
-      (1 - #2)^2 * \tl_item:nn {#1} {2} + 2 * (1 - #2) * (#2) * \tl_item:nn {#1} {5} + (#2)^2 * \tl_item:nn {#1} {8}
+      (1 - #2)^2 * \tl_item:nn {#1} {2}
+      + 2 * (1 - #2) * (#2) * \tl_item:nn {#1} {5}
+      + (#2)^2 * \tl_item:nn {#1} {8}
     }}
     {\fp_to_dim:n
     {
-      (1 - #2)^2 * \tl_item:nn {#1} {3} + 2 * (1 - #2) * (#2) * \tl_item:nn {#1} {6} + (#2)^2 * \tl_item:nn {#1} {9}
+      (1 - #2)^2 * \tl_item:nn {#1} {3}
+      + 2 * (1 - #2) * (#2) * \tl_item:nn {#1} {6}
+      + (#2)^2 * \tl_item:nn {#1} {9}
     }}
   }
 
@@ -1367,11 +1741,17 @@
   {
     {\fp_to_dim:n
       {
-      (1 - #2)^3 * \tl_item:nn {#1} {2} + 3 * (1 - #2)^2 * (#2) * \tl_item:nn {#1} {5} + 3 * (1 - #2) * (#2)^2 * \tl_item:nn {#1} {8} + (#2)^3 * \tl_item:nn {#1} {11}
+        (1 - #2)^3 * \tl_item:nn {#1} {2}
+        + 3 * (1 - #2)^2 * (#2) * \tl_item:nn {#1} {5}
+        + 3 * (1 - #2) * (#2)^2 * \tl_item:nn {#1} {8}
+        + (#2)^3 * \tl_item:nn {#1} {11}
     }}
     {\fp_to_dim:n
     {
-      (1 - #2)^3 * \tl_item:nn {#1} {3} + 3 * (1 - #2)^2 * (#2) * \tl_item:nn {#1} {6} + 3 * (1 - #2) * (#2)^2 * \tl_item:nn {#1} {9} + (#2)^3 * \tl_item:nn {#1} {12}
+      (1 - #2)^3 * \tl_item:nn {#1} {3}
+      + 3 * (1 - #2)^2 * (#2) * \tl_item:nn {#1} {6}
+      + 3 * (1 - #2) * (#2)^2 * \tl_item:nn {#1} {9}
+      + (#2)^3 * \tl_item:nn {#1} {12}
     }}
   }
 
@@ -1384,11 +1764,17 @@
   {
     {\fp_to_dim:n
       {
-      (1 - #2)^3 * \tl_item:nn {#1} {2} + 3 * (1 - #2)^2 * (#2) * \tl_item:nn {#1} {5} + 3 * (1 - #2) * (#2)^2 * \tl_item:nn {#1} {8} + (#2)^3 * \tl_item:nn {#1} {11}
+        (1 - #2)^3 * \tl_item:nn {#1} {2}
+        + 3 * (1 - #2)^2 * (#2) * \tl_item:nn {#1} {5}
+        + 3 * (1 - #2) * (#2)^2 * \tl_item:nn {#1} {8}
+        + (#2)^3 * \tl_item:nn {#1} {11}
     }}
     {\fp_to_dim:n
     {
-      (1 - #2)^3 * \tl_item:nn {#1} {3} + 3 * (1 - #2)^2 * (#2) * \tl_item:nn {#1} {6} + 3 * (1 - #2) * (#2)^2 * \tl_item:nn {#1} {9} + (#2)^3 * \tl_item:nn {#1} {12}
+      (1 - #2)^3 * \tl_item:nn {#1} {3}
+      + 3 * (1 - #2)^2 * (#2) * \tl_item:nn {#1} {6}
+      + 3 * (1 - #2) * (#2)^2 * \tl_item:nn {#1} {9}
+      + (#2)^3 * \tl_item:nn {#1} {12}
     }}
   }
 
@@ -1397,11 +1783,15 @@
   {
     {\fp_to_dim:n
     {
-      (1 - #2)^2 * \tl_item:nn {#1} {5} + 2 * (1 - #2) * (#2) * \tl_item:nn {#1} {8} + (#2)^2 * \tl_item:nn {#1} {11}
+      (1 - #2)^2 * \tl_item:nn {#1} {5}
+      + 2 * (1 - #2) * (#2) * \tl_item:nn {#1} {8}
+      + (#2)^2 * \tl_item:nn {#1} {11}
     }}
     {\fp_to_dim:n
     {
-      (1 - #2)^2 * \tl_item:nn {#1} {6} + 2 * (1 - #2) * (#2) * \tl_item:nn {#1} {9} + (#2)^2 * \tl_item:nn {#1} {12}
+      (1 - #2)^2 * \tl_item:nn {#1} {6}
+      + 2 * (1 - #2) * (#2) * \tl_item:nn {#1} {9}
+      + (#2)^2 * \tl_item:nn {#1} {12}
     }}
   }
   \tl_put_right:NV \l__spath_tmpa_tl \c_spath_curvetob_tl
@@ -1425,6 +1815,7 @@
   \__spath_tl_gput_right_braced:NV \g__spath_output_tl \l__spath_tmpa_tl
   \group_end:
 }
+\cs_generate_variant:Nn \__spath_split_curve:nn {nv, nV}
 \cs_new_protected_nopar:Npn \spath_split_curve:NNnn #1#2#3#4
 {
   \__spath_split_curve:nn {#3}{#4}
@@ -1441,6 +1832,201 @@
   \tl_gclear:N \g__spath_output_tl
 }
 \cs_generate_variant:Nn \spath_gsplit_curve:NNnn {NNnV, NNVn, NNVV}
+\cs_new_protected_nopar:Npn \__spath_maybe_split_curve:n #1
+{
+  \group_begin:
+  \fp_set:Nn \l__spath_tmpa_fp
+  {
+    (
+    \tl_item:nn {#1} {3}
+    - 3 * \tl_item:nn {#1} {6}
+    + 3 * \tl_item:nn {#1} {9}
+    - \tl_item:nn {#1} {12}
+    )
+    *
+    (3 * \tl_item:nn {#1} {8} - 3 * \tl_item:nn {#1} {11})
+    -
+    (
+    \tl_item:nn {#1} {2}
+    - 3 * \tl_item:nn {#1} {5}
+    + 3 * \tl_item:nn {#1} {8}
+    - \tl_item:nn {#1} {11}
+    )
+    *
+    (3 * \tl_item:nn {#1} {9} - 3 * \tl_item:nn {#1} {12})
+  }
+  \fp_set:Nn \l__spath_tmpb_fp
+  {
+    (
+    \tl_item:nn {#1} {2}
+    - 3 * \tl_item:nn {#1} {5}
+    + 3 * \tl_item:nn {#1} {8}
+    - \tl_item:nn {#1} {11}
+    )
+    *
+    (
+    3 * \tl_item:nn {#1} {6}
+    - 6 * \tl_item:nn {#1} {9}
+    + 3 * \tl_item:nn {#1} {12}
+    )
+    -
+    (
+    \tl_item:nn {#1} {3}
+    - 3 * \tl_item:nn {#1} {6}
+    + 3 * \tl_item:nn {#1} {9}
+    - \tl_item:nn {#1} {12}
+    )
+    *
+    (
+    3 * \tl_item:nn {#1} {5}
+    - 6 * \tl_item:nn {#1} {8}
+    + 3 * \tl_item:nn {#1} {11}
+    )
+  }
+  \fp_compare:nTF
+  {
+    \l__spath_tmpb_fp != 0
+  }
+  {
+    \fp_set:Nn \l__spath_tmpa_fp {.5 * \l__spath_tmpa_fp / \l__spath_tmpb_fp}
+    \fp_compare:nTF
+    {
+      0 < \l__spath_tmpa_fp && \l__spath_tmpa_fp < 1
+    }
+    {
+      \__spath_split_curve:nV {#1} \l__spath_tmpa_fp
+    }
+    {
+      \tl_gset:Nn \g__spath_output_tl { {#1} {} }
+    }
+  }
+  {
+    \tl_gset:Nn \g__spath_output_tl { {#1} {} }
+  }
+  \group_end:
+}
+\cs_new_protected_nopar:Npn \spath_maybe_split_curve:NNn #1#2#3
+{
+  \__spath_maybe_split_curve:n {#3}
+  \tl_set:Nx #1 {\tl_item:Nn \g__spath_output_tl {1}}
+  \tl_set:Nx #2 {\tl_item:Nn \g__spath_output_tl {2}}
+  \tl_gclear:N \g__spath_output_tl
+}
+\cs_generate_variant:Nn \spath_maybe_split_curve:NNn {NNn, NNV }
+\cs_new_protected_nopar:Npn \spath_maybe_gsplit_curve:NNn #1#2#3
+{
+  \__spath_maybe_split_curve:n {#3}
+  \tl_gset:Nx #1 {\tl_item:Nn \g__spath_output_tl {1}}
+  \tl_gset:Nx #2 {\tl_item:Nn \g__spath_output_tl {2}}
+  \tl_gclear:N \g__spath_output_tl
+}
+\cs_generate_variant:Nn \spath_maybe_gsplit_curve:NNn {NNn, NNV}
+\cs_new_protected_nopar:Npn \__spath_split_curves:n #1
+{
+  \group_begin:
+  \tl_set:Nn \l__spath_tmpa_tl {#1}
+  \tl_clear:N \l__spath_tmpb_tl
+  \tl_clear:N \l__spath_tmpc_tl
+  \bool_do_until:nn
+  {
+    \tl_if_empty_p:N \l__spath_tmpa_tl
+  }
+  {
+    \tl_set:Nx \l__spath_tmpc_tl {\tl_head:N \l__spath_tmpa_tl}
+    \tl_case:NnF \l__spath_tmpc_tl
+    {
+      \c_spath_curvetoa_tl
+      {
+        \tl_clear:N \l__spath_tmpd_tl
+        \tl_set_eq:NN \l__spath_tmpd_tl \c_spath_moveto_tl
+        \tl_put_right:Nx \l__spath_tmpd_tl
+        {
+          { \dim_use:N \l__spath_tmpa_dim }
+          { \dim_use:N \l__spath_tmpb_dim }
+        }
+        \dim_set:Nn \l__spath_tmpa_dim
+        {
+          \tl_item:Nn \l__spath_tmpa_tl {8}
+        }
+        \dim_set:Nn \l__spath_tmpb_dim
+        {
+          \tl_item:Nn \l__spath_tmpa_tl {9}
+        }
+        \prg_replicate:nn {3}
+        {
+          \tl_put_right:Nx \l__spath_tmpd_tl
+          {
+            \tl_item:Nn \l__spath_tmpa_tl {1}
+            {\tl_item:Nn \l__spath_tmpa_tl {2}}
+            {\tl_item:Nn \l__spath_tmpa_tl {3}}
+          }
+          \prg_replicate:nn {3}
+          {
+            \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
+          }
+        }
+
+        \spath_maybe_split_curve:NNV
+        \l__spath_tmpd_tl
+        \l__spath_tmpe_tl
+        \l__spath_tmpd_tl
+        \prg_replicate:nn {3}
+        {
+          \tl_set:Nx \l__spath_tmpd_tl {\tl_tail:N \l__spath_tmpd_tl}
+          \tl_set:Nx \l__spath_tmpe_tl {\tl_tail:N \l__spath_tmpe_tl}
+        }
+        \tl_put_right:NV \l__spath_tmpb_tl \l__spath_tmpd_tl
+        \tl_put_right:NV \l__spath_tmpb_tl \l__spath_tmpe_tl
+      }
+    }
+    {
+      \dim_set:Nn \l__spath_tmpa_dim
+      {
+        \tl_item:Nn \l__spath_tmpa_tl {2}
+      }
+      \dim_set:Nn \l__spath_tmpb_dim
+      {
+        \tl_item:Nn \l__spath_tmpa_tl {3}
+      }
+      \tl_put_right:Nx \l__spath_tmpb_tl
+      {
+        \tl_item:Nn \l__spath_tmpa_tl {1}
+        {\tl_item:Nn \l__spath_tmpa_tl {2}}
+        {\tl_item:Nn \l__spath_tmpa_tl {3}}
+      }
+      \prg_replicate:nn {3}
+      {
+        \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
+      }
+    }
+  }
+  \tl_gset_eq:NN \g__spath_output_tl \l__spath_tmpb_tl
+  \group_end:
+}
+\cs_new_protected_nopar:Npn \spath_split_curves:Nn #1#2
+{
+  \__spath_split_curves:n {#2}
+  \tl_set_eq:NN #1 \g__spath_output_tl
+  \tl_gclear:N \g__spath_output_tl
+}
+\cs_generate_variant:Nn \spath_split_curves:Nn {NV, cV, cn, cv }
+\cs_new_protected_nopar:Npn \spath_split_curves:N #1
+{
+  \spath_split_curves:NV #1#1
+}
+\cs_generate_variant:Nn \spath_split_curves:N {c}
+\cs_new_protected_nopar:Npn \spath_gsplit_curves:Nn #1#2
+{
+  \__spath_split_curves:n {#2}
+  \tl_gset_eq:NN #1 \g__spath_output_tl
+  \tl_gclear:N \g__spath_output_tl
+}
+\cs_generate_variant:Nn \spath_gsplit_curves:Nn {NV, cV, cn, cv }
+\cs_new_protected_nopar:Npn \spath_gsplit_curves:N #1
+{
+  \spath_gsplit_curves:NV #1#1
+}
+\cs_generate_variant:Nn \spath_gsplit_curves:N {c}
 \cs_new_protected_nopar:Npn \__spath_split_line:nn #1#2
 {
   \group_begin:
@@ -1502,179 +2088,168 @@
   \tl_gclear:N \g__spath_output_tl
 }
 \cs_generate_variant:Nn \spath_gsplit_line:NNnn {NNnV, NNVn, NNVV}
-\int_new:N \l__spath_split_int
-\int_new:N \l__spath_splitat_int
-\fp_new:N \l__spath_split_fp
-\bool_new:N \l__spath_split_bool
-\tl_new:N \l__spath_split_path_tl
-\tl_new:N \l__spath_split_patha_tl
-\tl_new:N \l__spath_split_pathb_tl
-\tl_new:N \l__spath_split_intoa_tl
-\tl_new:N \l__spath_split_intob_tl
-\dim_new:N \l__spath_splitx_dim
-\dim_new:N \l__spath_splity_dim
 \cs_new_protected_nopar:Npn \__spath_split_at:nn #1#2
 {
   \group_begin:
-  \int_set:Nn \l__spath_splitat_int {\fp_to_int:n {floor(#2) + 1}}
-  \fp_set:Nn \l__spath_split_fp {#2 - floor(#2)}
+  \int_set:Nn \l__spath_tmpa_int {\fp_to_int:n {floor(#2) + 1}}
+  \fp_set:Nn \l__spath_tmpa_fp {#2 - floor(#2)}
 
   % Is split point near one end or other of a component?
   \fp_compare:nT
   {
-    \l__spath_split_fp < 0.01
+    \l__spath_tmpa_fp < 0.01
   }
   {
     % Near the start, so we'll place it at the start
-    \fp_set:Nn \l__spath_split_fp {0}
+    \fp_set:Nn \l__spath_tmpa_fp {0}
   }
   \fp_compare:nT
   {
-    \l__spath_split_fp > 0.99
+    \l__spath_tmpa_fp > 0.99
   }
   {
     % Near the end, so we'll place it at the end
-    \fp_set:Nn \l__spath_split_fp {0}
-    \int_incr:N \l__spath_splitat_int
+    \fp_set:Nn \l__spath_tmpa_fp {0}
+    \int_incr:N \l__spath_tmpa_int
   }
 
-  \int_zero:N \l__spath_split_int
-  \bool_set_true:N \l__spath_split_bool
+  \int_zero:N \l__spath_tmpb_int
+  \bool_set_true:N \l__spath_tmpa_bool
 
-  \tl_set:Nn \l__spath_split_path_tl {#1}
-  \tl_clear:N \l__spath_split_patha_tl
+  \tl_set:Nn \l__spath_tmpe_tl {#1}
+  \tl_clear:N \l__spath_tmpc_tl
 
-  \dim_zero:N \l__spath_splitx_dim
-  \dim_zero:N \l__spath_splity_dim
+  \dim_zero:N \l__spath_tmpa_dim
+  \dim_zero:N \l__spath_tmpb_dim
 
   \bool_until_do:nn {
-    \tl_if_empty_p:N \l__spath_split_path_tl
+    \tl_if_empty_p:N \l__spath_tmpe_tl
     ||
-    \int_compare_p:n { \l__spath_splitat_int == \l__spath_split_int  }
+    \int_compare_p:n { \l__spath_tmpa_int == \l__spath_tmpb_int  }
   }
   {
-    \tl_set:Nx \l__spath_tmpc_tl {\tl_head:N \l__spath_split_path_tl}
-    \tl_set:Nx \l__spath_split_path_tl {\tl_tail:N \l__spath_split_path_tl }
-    \tl_case:Nn \l__spath_tmpc_tl
+    \tl_set:Nx \l__spath_tmpf_tl {\tl_head:N \l__spath_tmpe_tl}
+    \tl_set:Nx \l__spath_tmpe_tl {\tl_tail:N \l__spath_tmpe_tl }
+    \tl_case:Nn \l__spath_tmpf_tl
     {
       \c_spath_lineto_tl
       {
-        \int_incr:N \l__spath_split_int
+        \int_incr:N \l__spath_tmpb_int
       }
       \c_spath_curvetoa_tl
       {
-        \int_incr:N \l__spath_split_int
+        \int_incr:N \l__spath_tmpb_int
       }
     }
-    \int_compare:nT { \l__spath_split_int < \l__spath_splitat_int  }
+    \int_compare:nT { \l__spath_tmpb_int < \l__spath_tmpa_int  }
     {
-      \tl_put_right:NV \l__spath_split_patha_tl \l__spath_tmpc_tl
+      \tl_put_right:NV \l__spath_tmpc_tl \l__spath_tmpf_tl
 
-      \tl_put_right:Nx \l__spath_split_patha_tl
-      {{ \tl_head:N \l__spath_split_path_tl }}
-      \dim_set:Nn \l__spath_splitx_dim {\tl_head:N \l__spath_split_path_tl}
-      \tl_set:Nx \l__spath_split_path_tl {\tl_tail:N \l__spath_split_path_tl }
+      \tl_put_right:Nx \l__spath_tmpc_tl
+      {{ \tl_head:N \l__spath_tmpe_tl }}
+      \dim_set:Nn \l__spath_tmpa_dim {\tl_head:N \l__spath_tmpe_tl}
+      \tl_set:Nx \l__spath_tmpe_tl {\tl_tail:N \l__spath_tmpe_tl }
 
-      \tl_put_right:Nx \l__spath_split_patha_tl
-      {{ \tl_head:N \l__spath_split_path_tl }}
-      \dim_set:Nn \l__spath_splity_dim {\tl_head:N \l__spath_split_path_tl}
-      \tl_set:Nx \l__spath_split_path_tl {\tl_tail:N \l__spath_split_path_tl }
+      \tl_put_right:Nx \l__spath_tmpc_tl
+      {{ \tl_head:N \l__spath_tmpe_tl }}
+      \dim_set:Nn \l__spath_tmpb_dim {\tl_head:N \l__spath_tmpe_tl}
+      \tl_set:Nx \l__spath_tmpe_tl {\tl_tail:N \l__spath_tmpe_tl }
 
     }
   }
 
-  \tl_clear:N \l__spath_split_pathb_tl
-  \tl_put_right:NV \l__spath_split_pathb_tl \c_spath_moveto_tl
-  \tl_put_right:Nx \l__spath_split_pathb_tl
+  \tl_clear:N \l__spath_tmpd_tl
+  \tl_put_right:NV \l__spath_tmpd_tl \c_spath_moveto_tl
+  \tl_put_right:Nx \l__spath_tmpd_tl
   {
-    {\dim_use:N \l__spath_splitx_dim}
-    {\dim_use:N \l__spath_splity_dim}
+    {\dim_use:N \l__spath_tmpa_dim}
+    {\dim_use:N \l__spath_tmpb_dim}
   }
 
   \fp_compare:nTF
   {
-    \l__spath_split_fp == 0
+    \l__spath_tmpa_fp == 0
   }
   {
-    \tl_set_eq:NN \l__spath_split_intob_tl \l__spath_split_pathb_tl
-    \tl_if_empty:NF \l__spath_split_path_tl
+    \tl_set_eq:NN \l__spath_tmpb_tl \l__spath_tmpd_tl
+    \tl_if_empty:NF \l__spath_tmpe_tl
     {
-      \tl_put_right:NV \l__spath_split_intob_tl \l__spath_tmpc_tl
-      \tl_put_right:NV \l__spath_split_intob_tl \l__spath_split_path_tl
+      \tl_put_right:NV \l__spath_tmpb_tl \l__spath_tmpf_tl
+      \tl_put_right:NV \l__spath_tmpb_tl \l__spath_tmpe_tl
     }
   }
   {
 
-    \tl_case:Nn \l__spath_tmpc_tl
+    \tl_case:Nn \l__spath_tmpf_tl
     {
       \c_spath_lineto_tl
       {
-        \tl_put_right:NV \l__spath_split_pathb_tl \l__spath_tmpc_tl
-        \tl_put_right:Nx \l__spath_split_pathb_tl
-        {{ \tl_head:N \l__spath_split_path_tl }}
-        \tl_set:Nx \l__spath_split_path_tl {\tl_tail:N \l__spath_split_path_tl }
+        \tl_put_right:NV \l__spath_tmpd_tl \l__spath_tmpf_tl
+        \tl_put_right:Nx \l__spath_tmpd_tl
+        {{ \tl_head:N \l__spath_tmpe_tl }}
+        \tl_set:Nx \l__spath_tmpe_tl {\tl_tail:N \l__spath_tmpe_tl }
 
-        \tl_put_right:Nx \l__spath_split_pathb_tl
-        {{ \tl_head:N \l__spath_split_path_tl }}
-        \tl_set:Nx \l__spath_split_path_tl {\tl_tail:N \l__spath_split_path_tl }
+        \tl_put_right:Nx \l__spath_tmpd_tl
+        {{ \tl_head:N \l__spath_tmpe_tl }}
+        \tl_set:Nx \l__spath_tmpe_tl {\tl_tail:N \l__spath_tmpe_tl }
 
         \spath_split_line:NNVV
-        \l__spath_split_intoa_tl
-        \l__spath_split_intob_tl
-        \l__spath_split_pathb_tl
-        \l__spath_split_fp
+        \l__spath_tmpa_tl
+        \l__spath_tmpb_tl
+        \l__spath_tmpd_tl
+        \l__spath_tmpa_fp
 
         \prg_replicate:nn {3} {
-          \tl_set:Nx \l__spath_split_intoa_tl {\tl_tail:N \l__spath_split_intoa_tl}
+          \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
         }
 
-        \tl_put_right:NV \l__spath_split_patha_tl \l__spath_split_intoa_tl
-        \tl_put_right:NV \l__spath_split_intob_tl \l__spath_split_path_tl
+        \tl_put_right:NV \l__spath_tmpc_tl \l__spath_tmpa_tl
+        \tl_put_right:NV \l__spath_tmpb_tl \l__spath_tmpe_tl
       }
       \c_spath_curvetoa_tl
       {
-        \tl_put_right:NV \l__spath_split_pathb_tl \l__spath_tmpc_tl
-        \tl_put_right:Nx \l__spath_split_pathb_tl
-        {{ \tl_head:N \l__spath_split_path_tl }}
-        \tl_set:Nx \l__spath_split_path_tl {\tl_tail:N \l__spath_split_path_tl }
+        \tl_put_right:NV \l__spath_tmpd_tl \l__spath_tmpf_tl
+        \tl_put_right:Nx \l__spath_tmpd_tl
+        {{ \tl_head:N \l__spath_tmpe_tl }}
+        \tl_set:Nx \l__spath_tmpe_tl {\tl_tail:N \l__spath_tmpe_tl }
 
-        \tl_put_right:Nx \l__spath_split_pathb_tl
-        {{ \tl_head:N \l__spath_split_path_tl }}
-        \tl_set:Nx \l__spath_split_path_tl {\tl_tail:N \l__spath_split_path_tl }
+        \tl_put_right:Nx \l__spath_tmpd_tl
+        {{ \tl_head:N \l__spath_tmpe_tl }}
+        \tl_set:Nx \l__spath_tmpe_tl {\tl_tail:N \l__spath_tmpe_tl }
 
         \prg_replicate:nn {2} {
 
-          \tl_put_right:Nx \l__spath_split_pathb_tl
-          { \tl_head:N \l__spath_split_path_tl }
-          \tl_set:Nx \l__spath_split_path_tl {\tl_tail:N \l__spath_split_path_tl }
+          \tl_put_right:Nx \l__spath_tmpd_tl
+          { \tl_head:N \l__spath_tmpe_tl }
+          \tl_set:Nx \l__spath_tmpe_tl {\tl_tail:N \l__spath_tmpe_tl }
 
-          \tl_put_right:Nx \l__spath_split_pathb_tl
-          {{ \tl_head:N \l__spath_split_path_tl }}
-          \tl_set:Nx \l__spath_split_path_tl {\tl_tail:N \l__spath_split_path_tl }
+          \tl_put_right:Nx \l__spath_tmpd_tl
+          {{ \tl_head:N \l__spath_tmpe_tl }}
+          \tl_set:Nx \l__spath_tmpe_tl {\tl_tail:N \l__spath_tmpe_tl }
 
-          \tl_put_right:Nx \l__spath_split_pathb_tl
-          {{ \tl_head:N \l__spath_split_path_tl }}
-          \tl_set:Nx \l__spath_split_path_tl {\tl_tail:N \l__spath_split_path_tl }
+          \tl_put_right:Nx \l__spath_tmpd_tl
+          {{ \tl_head:N \l__spath_tmpe_tl }}
+          \tl_set:Nx \l__spath_tmpe_tl {\tl_tail:N \l__spath_tmpe_tl }
         }
 
         \spath_split_curve:NNVV
-        \l__spath_split_intoa_tl
-        \l__spath_split_intob_tl
-        \l__spath_split_pathb_tl \l__spath_split_fp
+        \l__spath_tmpa_tl
+        \l__spath_tmpb_tl
+        \l__spath_tmpd_tl \l__spath_tmpa_fp
 
         \prg_replicate:nn {3} {
-          \tl_set:Nx \l__spath_split_intoa_tl {\tl_tail:N \l__spath_split_intoa_tl}
+          \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
         }
 
-        \tl_put_right:NV \l__spath_split_patha_tl \l__spath_split_intoa_tl
-        \tl_put_right:NV \l__spath_split_intob_tl \l__spath_split_path_tl
+        \tl_put_right:NV \l__spath_tmpc_tl \l__spath_tmpa_tl
+        \tl_put_right:NV \l__spath_tmpb_tl \l__spath_tmpe_tl
       }
     }
   }
 
   \tl_gclear:N \g__spath_output_tl
-  \__spath_tl_gput_right_braced:NV \g__spath_output_tl \l__spath_split_patha_tl
-  \__spath_tl_gput_right_braced:NV \g__spath_output_tl \l__spath_split_intob_tl
+  \__spath_tl_gput_right_braced:NV \g__spath_output_tl \l__spath_tmpc_tl
+  \__spath_tl_gput_right_braced:NV \g__spath_output_tl \l__spath_tmpb_tl
   \group_end:
 }
 \cs_new_protected_nopar:Npn \spath_split_at:NNnn #1#2#3#4
@@ -1696,7 +2271,11 @@
 \cs_new_protected_nopar:Npn \spath_split_at:Nnn #1#2#3
 {
   \__spath_split_at:nn {#2}{#3}
-  \tl_set:Nx #1 {\tl_item:Nn \g__spath_output_tl {1} \tl_item:Nn \g__spath_output_tl {2}}
+  \tl_set:Nx #1
+  {
+    \tl_item:Nn \g__spath_output_tl {1}
+    \tl_item:Nn \g__spath_output_tl {2}
+  }
   \tl_gclear:N \g__spath_output_tl
 }
 \cs_generate_variant:Nn \spath_split_at:Nnn {NVn, NVV}
@@ -1707,7 +2286,11 @@
 \cs_new_protected_nopar:Npn \spath_gsplit_at:Nnn #1#2#3
 {
   \__spath_split_at:nn {#2}{#3}
-  \tl_gset:Nx #1 {\tl_item:Nn \g__spath_output_tl {1} \tl_item:Nn \g__spath_output_tl {2}}
+  \tl_gset:Nx #1
+  {
+    \tl_item:Nn \g__spath_output_tl {1}
+    \tl_item:Nn \g__spath_output_tl {2}
+  }
   \tl_gclear:N \g__spath_output_tl
 }
 \cs_generate_variant:Nn \spath_gsplit_at:Nnn {NVn, NVV}
@@ -1715,15 +2298,6 @@
 {
   \spath_gsplit_at:NVn #1#1{#2}
 }
-\tl_new:N \l__spath_shorten_fa_tl
-\tl_new:N \l__spath_shorten_path_tl
-\tl_new:N \l__spath_shorten_last_tl
-\tl_new:N \l__spath_shorten_lasta_tl
-\tl_new:N \l__spath_shorten_lastb_tl
-\int_new:N \l__spath_shorten_int
-\fp_new:N \l__spath_shorten_x_fp
-\fp_new:N \l__spath_shorten_y_fp
-\fp_new:N \l__spath_shorten_len_fp
 \cs_new_protected_nopar:Npn \__spath_shorten_at_end:nn #1#2
 {
   \int_compare:nTF
@@ -1732,106 +2306,106 @@
   }
   {
     \group_begin:
-    \tl_set:Nn \l__spath_shorten_path_tl {#1}
-    \tl_reverse:N \l__spath_shorten_path_tl
+    \tl_set:Nn \l__spath_tmpa_tl {#1}
+    \tl_reverse:N \l__spath_tmpa_tl
 
-    \tl_set:Nx \l__spath_shorten_fa_tl {\tl_item:Nn \l__spath_shorten_path_tl {3}}
+    \tl_set:Nx \l__spath_tmpb_tl {\tl_item:Nn \l__spath_tmpa_tl {3}}
 
-    \tl_clear:N \l__spath_shorten_last_tl
-    \tl_if_eq:NNTF \l__spath_shorten_fa_tl \c_spath_curveto_tl
+    \tl_clear:N \l__spath_tmpe_tl
+    \tl_if_eq:NNTF \l__spath_tmpb_tl \c_spath_curveto_tl
     {
-      \int_set:Nn \l__spath_shorten_int {3}
+      \int_set:Nn \l__spath_tmpa_int {3}
     }
     {
-      \int_set:Nn \l__spath_shorten_int {1}
+      \int_set:Nn \l__spath_tmpa_int {1}
     }
 
-    \prg_replicate:nn { \l__spath_shorten_int }
+    \prg_replicate:nn { \l__spath_tmpa_int }
     {
-      \tl_put_right:Nx \l__spath_shorten_last_tl
+      \tl_put_right:Nx \l__spath_tmpe_tl
       {
-        {\tl_head:N \l__spath_shorten_path_tl}
+        {\tl_head:N \l__spath_tmpa_tl}
       }
-      \tl_set:Nx \l__spath_shorten_path_tl {\tl_tail:N \l__spath_shorten_path_tl}
-      \tl_put_right:Nx \l__spath_shorten_last_tl
+      \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
+      \tl_put_right:Nx \l__spath_tmpe_tl
       {
-        {\tl_head:N \l__spath_shorten_path_tl}
+        {\tl_head:N \l__spath_tmpa_tl}
       }
-      \tl_set:Nx \l__spath_shorten_path_tl {\tl_tail:N \l__spath_shorten_path_tl}
-      \tl_put_right:Nx \l__spath_shorten_last_tl
+      \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
+      \tl_put_right:Nx \l__spath_tmpe_tl
       {
-        \tl_head:N \l__spath_shorten_path_tl
+        \tl_head:N \l__spath_tmpa_tl
       }
-      \tl_set:Nx \l__spath_shorten_path_tl {\tl_tail:N \l__spath_shorten_path_tl}
+      \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
     }
 
-    \tl_put_right:Nx \l__spath_shorten_last_tl
+    \tl_put_right:Nx \l__spath_tmpe_tl
     {
-      {\tl_item:Nn \l__spath_shorten_path_tl {1}}
-      {\tl_item:Nn \l__spath_shorten_path_tl {2}}
+      {\tl_item:Nn \l__spath_tmpa_tl {1}}
+      {\tl_item:Nn \l__spath_tmpa_tl {2}}
     }
-    \tl_put_right:NV \l__spath_shorten_last_tl \c_spath_moveto_tl
+    \tl_put_right:NV \l__spath_tmpe_tl \c_spath_moveto_tl
 
-    \tl_reverse:N \l__spath_shorten_path_tl
+    \tl_reverse:N \l__spath_tmpa_tl
 
-    \fp_set:Nn \l__spath_shorten_x_fp
+    \fp_set:Nn \l__spath_tmpa_fp
     {
-      \dim_to_fp:n {\tl_item:Nn \l__spath_shorten_last_tl {4}}
+      \dim_to_fp:n {\tl_item:Nn \l__spath_tmpe_tl {4}}
       -
-      \dim_to_fp:n {\tl_item:Nn \l__spath_shorten_last_tl {1}}
+      \dim_to_fp:n {\tl_item:Nn \l__spath_tmpe_tl {1}}
     }
 
-    \fp_set:Nn \l__spath_shorten_y_fp
+    \fp_set:Nn \l__spath_tmpb_fp
     {
-      \dim_to_fp:n {\tl_item:Nn \l__spath_shorten_last_tl {5}}
+      \dim_to_fp:n {\tl_item:Nn \l__spath_tmpe_tl {5}}
       -
-      \dim_to_fp:n {\tl_item:Nn \l__spath_shorten_last_tl {2}}
+      \dim_to_fp:n {\tl_item:Nn \l__spath_tmpe_tl {2}}
     }
 
-    \fp_set:Nn \l__spath_shorten_len_fp
+    \fp_set:Nn \l__spath_tmpc_fp
     {
-      sqrt( \l__spath_shorten_x_fp * \l__spath_shorten_x_fp +  \l__spath_shorten_y_fp *  \l__spath_shorten_y_fp )
+      sqrt(
+      \l__spath_tmpa_fp * \l__spath_tmpa_fp
+      +
+      \l__spath_tmpb_fp *  \l__spath_tmpb_fp
+      ) * \l__spath_tmpa_int
     }
 
     \fp_compare:nTF
     {
-      \l__spath_shorten_len_fp > #2
+      \l__spath_tmpc_fp > #2
     }
     {
 
-      \fp_set:Nn \l__spath_shorten_len_fp
+      \fp_set:Nn \l__spath_tmpc_fp
       {
-        (\l__spath_shorten_len_fp - #2)/ \l__spath_shorten_len_fp
+        (\l__spath_tmpc_fp - #2)/ \l__spath_tmpc_fp
       }
 
-      \tl_reverse:N \l__spath_shorten_last_tl
+      \tl_reverse:N \l__spath_tmpe_tl
 
-      \tl_if_eq:NNTF \l__spath_shorten_fa_tl \c_spath_curveto_tl
+      \tl_if_eq:NNTF \l__spath_tmpb_tl \c_spath_curveto_tl
       {
-        \fp_set:Nn \l__spath_shorten_len_fp
-        {
-          1 - (1 -\l__spath_shorten_len_fp)/3
-        }
         \spath_split_curve:NNVV
-        \l__spath_shorten_lasta_tl
-        \l__spath_shorten_lastb_tl
-        \l__spath_shorten_last_tl
-        \l__spath_shorten_len_fp
+        \l__spath_tmpc_tl
+        \l__spath_tmpd_tl
+        \l__spath_tmpe_tl
+        \l__spath_tmpc_fp
       }
       {
         \spath_split_line:NNVV
-        \l__spath_shorten_lasta_tl
-        \l__spath_shorten_lastb_tl
-        \l__spath_shorten_last_tl
-        \l__spath_shorten_len_fp
+        \l__spath_tmpc_tl
+        \l__spath_tmpd_tl
+        \l__spath_tmpe_tl
+        \l__spath_tmpc_fp
       }
 
       \prg_replicate:nn {3}
       {
-        \tl_set:Nx \l__spath_shorten_lasta_tl {\tl_tail:N \l__spath_shorten_lasta_tl}
+        \tl_set:Nx \l__spath_tmpc_tl {\tl_tail:N \l__spath_tmpc_tl}
       }
 
-      \tl_put_right:NV \l__spath_shorten_path_tl \l__spath_shorten_lasta_tl
+      \tl_put_right:NV \l__spath_tmpa_tl \l__spath_tmpc_tl
 
     }
     {
@@ -1838,15 +2412,15 @@
 
       \int_compare:nT
       {
-        \tl_count:N \l__spath_shorten_path_tl > 3
+        \tl_count:N \l__spath_tmpa_tl > 3
       }
       {
-        \dim_set:Nn \l__spath_tmpa_dim {\fp_to_dim:n {#2 - \l__spath_shorten_len_fp } }
-        \spath_shorten_at_end:NV \l__spath_shorten_path_tl \l__spath_tmpa_dim
+        \dim_set:Nn \l__spath_tmpa_dim {\fp_to_dim:n {#2 - \l__spath_tmpc_fp } }
+        \spath_shorten_at_end:NV \l__spath_tmpa_tl \l__spath_tmpa_dim
       }
     }
 
-    \tl_gset_eq:NN \g__spath_output_tl \l__spath_shorten_path_tl
+    \tl_gset_eq:NN \g__spath_output_tl \l__spath_tmpa_tl
     \group_end:
   }
   {
@@ -1885,110 +2459,120 @@
   }
   {
   \group_begin:
-  \tl_set:Nn \l__spath_shorten_path_tl {#1}
+  \tl_set:Nn \l__spath_tmpa_tl {#1}
 
-  \tl_set:Nx \l__spath_shorten_fa_tl {\tl_item:Nn \l__spath_shorten_path_tl {4}}
+  \tl_set:Nx \l__spath_tmpb_tl {\tl_item:Nn \l__spath_tmpa_tl {4}}
 
-    \tl_clear:N \l__spath_shorten_last_tl
+    \tl_clear:N \l__spath_tmpe_tl
 
-  \tl_if_eq:NNTF \l__spath_shorten_fa_tl \c_spath_curvetoa_tl
+  \tl_if_eq:NNTF \l__spath_tmpb_tl \c_spath_curvetoa_tl
   {
-    \int_set:Nn \l__spath_shorten_int {3}
+    \int_set:Nn \l__spath_tmpa_int {3}
   }
   {
-    \int_set:Nn \l__spath_shorten_int {1}
+    \int_set:Nn \l__spath_tmpa_int {1}
   }
 
-  \tl_set_eq:NN \l__spath_shorten_last_tl \c_spath_moveto_tl
-  \tl_set:Nx \l__spath_shorten_path_tl {\tl_tail:N \l__spath_shorten_path_tl }
+  \tl_set_eq:NN \l__spath_tmpe_tl \c_spath_moveto_tl
+  \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl }
 
-  \prg_replicate:nn { \l__spath_shorten_int }
+  \prg_replicate:nn { \l__spath_tmpa_int }
   {
-    \__spath_tl_put_right_braced:Nx \l__spath_shorten_last_tl {\tl_item:Nn \l__spath_shorten_path_tl {1}}
-    \__spath_tl_put_right_braced:Nx \l__spath_shorten_last_tl {\tl_item:Nn \l__spath_shorten_path_tl {2}}
-    \tl_put_right:Nx \l__spath_shorten_last_tl {\tl_item:Nn \l__spath_shorten_path_tl {3}}
+    \__spath_tl_put_right_braced:Nx
+    \l__spath_tmpe_tl
+    {\tl_item:Nn \l__spath_tmpa_tl {1}}
+    \__spath_tl_put_right_braced:Nx
+    \l__spath_tmpe_tl
+    {\tl_item:Nn \l__spath_tmpa_tl {2}}
+    \tl_put_right:Nx \l__spath_tmpe_tl {\tl_item:Nn \l__spath_tmpa_tl {3}}
 
     \prg_replicate:nn {3}
     {
-      \tl_set:Nx \l__spath_shorten_path_tl {\tl_tail:N \l__spath_shorten_path_tl }
+      \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl }
     }
   }
-  \__spath_tl_put_right_braced:Nx \l__spath_shorten_last_tl {\tl_item:Nn \l__spath_shorten_path_tl {1}}
-  \__spath_tl_put_right_braced:Nx \l__spath_shorten_last_tl {\tl_item:Nn \l__spath_shorten_path_tl {2}}
+  \__spath_tl_put_right_braced:Nx
+  \l__spath_tmpe_tl
+  {\tl_item:Nn \l__spath_tmpa_tl {1}}
+  \__spath_tl_put_right_braced:Nx
+  \l__spath_tmpe_tl
+  {\tl_item:Nn \l__spath_tmpa_tl {2}}
 
-  \fp_set:Nn \l__spath_shorten_x_fp
+  \fp_set:Nn \l__spath_tmpa_fp
   {
-    \dim_to_fp:n {\tl_item:Nn \l__spath_shorten_last_tl {5}}
+    \dim_to_fp:n {\tl_item:Nn \l__spath_tmpe_tl {5}}
     -
-    \dim_to_fp:n {\tl_item:Nn \l__spath_shorten_last_tl {2}}
+    \dim_to_fp:n {\tl_item:Nn \l__spath_tmpe_tl {2}}
   }
 
-  \fp_set:Nn \l__spath_shorten_y_fp
+  \fp_set:Nn \l__spath_tmpb_fp
   {
-    \dim_to_fp:n {\tl_item:Nn \l__spath_shorten_last_tl {6}}
+    \dim_to_fp:n {\tl_item:Nn \l__spath_tmpe_tl {6}}
     -
-    \dim_to_fp:n {\tl_item:Nn \l__spath_shorten_last_tl {3}}
+    \dim_to_fp:n {\tl_item:Nn \l__spath_tmpe_tl {3}}
   }
 
-  \fp_set:Nn \l__spath_shorten_len_fp
+  \fp_set:Nn \l__spath_tmpc_fp
   {
-    sqrt( \l__spath_shorten_x_fp * \l__spath_shorten_x_fp +  \l__spath_shorten_y_fp *  \l__spath_shorten_y_fp )
+    sqrt(
+    \l__spath_tmpa_fp * \l__spath_tmpa_fp
+    +
+    \l__spath_tmpb_fp *  \l__spath_tmpb_fp
+    )
+    *
+    \l__spath_tmpa_int
   }
 
   \fp_compare:nTF
   {
-    \l__spath_shorten_len_fp > #2
+    \l__spath_tmpc_fp > #2
   }
   {
 
-    \fp_set:Nn \l__spath_shorten_len_fp
+    \fp_set:Nn \l__spath_tmpc_fp
     {
-      #2/ \l__spath_shorten_len_fp
+      #2/ \l__spath_tmpc_fp
     }
 
-    \tl_if_eq:NNTF \l__spath_shorten_fa_tl \c_spath_curvetoa_tl
+    \tl_if_eq:NNTF \l__spath_tmpb_tl \c_spath_curvetoa_tl
     {
-      \fp_set:Nn \l__spath_shorten_len_fp
-      {
-        \l__spath_shorten_len_fp/3
-      }
       \spath_split_curve:NNVV
-      \l__spath_shorten_lasta_tl
-      \l__spath_shorten_lastb_tl
-      \l__spath_shorten_last_tl
-      \l__spath_shorten_len_fp
+      \l__spath_tmpc_tl
+      \l__spath_tmpd_tl
+      \l__spath_tmpe_tl
+      \l__spath_tmpc_fp
     }
     {
       \spath_split_line:NNVV
-      \l__spath_shorten_lasta_tl
-      \l__spath_shorten_lastb_tl
-      \l__spath_shorten_last_tl
-      \l__spath_shorten_len_fp
+      \l__spath_tmpc_tl
+      \l__spath_tmpd_tl
+      \l__spath_tmpe_tl
+      \l__spath_tmpc_fp
     }
 
     \prg_replicate:nn {2}
     {
-      \tl_set:Nx \l__spath_shorten_path_tl {\tl_tail:N \l__spath_shorten_path_tl}
+      \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
     }
 
-    \tl_put_left:NV \l__spath_shorten_path_tl \l__spath_shorten_lastb_tl
+    \tl_put_left:NV \l__spath_tmpa_tl \l__spath_tmpd_tl
 
   }
   {
 
-    \tl_put_left:NV \l__spath_shorten_path_tl \c_spath_moveto_tl
+    \tl_put_left:NV \l__spath_tmpa_tl \c_spath_moveto_tl
 
     \int_compare:nT
     {
-      \tl_count:N \l__spath_shorten_path_tl > 3
+      \tl_count:N \l__spath_tmpa_tl > 3
     }
     {
-      \dim_set:Nn \l__spath_tmpa_dim {\fp_to_dim:n {#2 - \l__spath_shorten_len_fp } }
-      \spath_shorten_at_start:NV \l__spath_shorten_path_tl \l__spath_tmpa_dim
+      \dim_set:Nn \l__spath_tmpa_dim {\fp_to_dim:n {#2 - \l__spath_tmpc_fp } }
+      \spath_shorten_at_start:NV \l__spath_tmpa_tl \l__spath_tmpa_dim
     }
   }
 
-  \tl_gset_eq:NN \g__spath_output_tl \l__spath_shorten_path_tl
+  \tl_gset_eq:NN \g__spath_output_tl \l__spath_tmpa_tl
   \group_end:
   }
   {
@@ -2044,7 +2628,9 @@
     }
     {
 
-      \tl_set:Nx \l__spath_tmpa_tl {\seq_item:Nn \l__spath_tmpa_seq { \l__spath_tmpa_int} }
+      \tl_set:Nx
+      \l__spath_tmpa_tl
+      {\seq_item:Nn \l__spath_tmpa_seq { \l__spath_tmpa_int} }
 
       \int_compare:nTF
       {
@@ -2122,11 +2708,21 @@
           {
             {\fp_to_dim:n
               {
-                (1 - \l__spath_tmpa_fp)^3 * \tl_item:Nn \l__spath_tmpa_tl {2} + 3 * (1 - \l__spath_tmpa_fp)^2 * (\l__spath_tmpa_fp) * \tl_item:Nn \l__spath_tmpa_tl {5} + 3 * (1 - \l__spath_tmpa_fp) * (\l__spath_tmpa_fp)^2 * \tl_item:Nn \l__spath_tmpa_tl {8} + (\l__spath_tmpa_fp)^3 * \tl_item:Nn \l__spath_tmpa_tl {11}
+                (1 - \l__spath_tmpa_fp)^3 * \tl_item:Nn \l__spath_tmpa_tl {2}
+                + 3 * (1 - \l__spath_tmpa_fp)^2 * (\l__spath_tmpa_fp)
+                * \tl_item:Nn \l__spath_tmpa_tl {5}
+                + 3 * (1 - \l__spath_tmpa_fp) * (\l__spath_tmpa_fp)^2
+                * \tl_item:Nn \l__spath_tmpa_tl {8}
+                + (\l__spath_tmpa_fp)^3 * \tl_item:Nn \l__spath_tmpa_tl {11}
             }}
             {\fp_to_dim:n
               {
-                (1 - \l__spath_tmpa_fp)^3 * \tl_item:Nn \l__spath_tmpa_tl {3} + 3 * (1 - \l__spath_tmpa_fp)^2 * (\l__spath_tmpa_fp) * \tl_item:Nn \l__spath_tmpa_tl {6} + 3 * (1 - \l__spath_tmpa_fp) * (\l__spath_tmpa_fp)^2 * \tl_item:Nn \l__spath_tmpa_tl {9} + (\l__spath_tmpa_fp)^3 * \tl_item:Nn \l__spath_tmpa_tl {12}
+                (1 - \l__spath_tmpa_fp)^3 * \tl_item:Nn \l__spath_tmpa_tl {3}
+                + 3 * (1 - \l__spath_tmpa_fp)^2 * (\l__spath_tmpa_fp)
+                * \tl_item:Nn \l__spath_tmpa_tl {6}
+                + 3 * (1 - \l__spath_tmpa_fp) * (\l__spath_tmpa_fp)^2
+                * \tl_item:Nn \l__spath_tmpa_tl {9}
+                + (\l__spath_tmpa_fp)^3 * \tl_item:Nn \l__spath_tmpa_tl {12}
             }}
           }
         }
@@ -2177,7 +2773,9 @@
     }
     {
 
-      \tl_set:Nx \l__spath_tmpa_tl {\seq_item:Nn \l__spath_tmpa_seq { \l__spath_tmpa_int} }
+      \tl_set:Nx
+      \l__spath_tmpa_tl
+      {\seq_item:Nn \l__spath_tmpa_seq { \l__spath_tmpa_int} }
 
       \int_compare:nTF
       {
@@ -2255,16 +2853,24 @@
           {
             {\fp_to_dim:n
               {
-                3*(1 - \l__spath_tmpa_fp)^2 * (\tl_item:Nn \l__spath_tmpa_tl {5} - \tl_item:Nn \l__spath_tmpa_tl {2})
-                + 6 * (1 - \l__spath_tmpa_fp) * (\l__spath_tmpa_fp) *  (\tl_item:Nn \l__spath_tmpa_tl {8} - \tl_item:Nn \l__spath_tmpa_tl {5})
-                + 3*(\l__spath_tmpa_fp)^2 * (\tl_item:Nn \l__spath_tmpa_tl {11} - \tl_item:Nn \l__spath_tmpa_tl {8})
+                3*(1 - \l__spath_tmpa_fp)^2 * (\tl_item:Nn \l__spath_tmpa_tl {5}
+                - \tl_item:Nn \l__spath_tmpa_tl {2})
+                + 6 * (1 - \l__spath_tmpa_fp) * (\l__spath_tmpa_fp) *
+                (\tl_item:Nn \l__spath_tmpa_tl {8}
+                - \tl_item:Nn \l__spath_tmpa_tl {5})
+                + 3*(\l__spath_tmpa_fp)^2 * (\tl_item:Nn \l__spath_tmpa_tl {11}
+                - \tl_item:Nn \l__spath_tmpa_tl {8})
               }
             }
             {\fp_to_dim:n
               {
-                3*(1 - \l__spath_tmpa_fp)^2 * (\tl_item:Nn \l__spath_tmpa_tl {6} - \tl_item:Nn \l__spath_tmpa_tl {3})
-                + 6 * (1 - \l__spath_tmpa_fp) * (\l__spath_tmpa_fp) *  (\tl_item:Nn \l__spath_tmpa_tl {9} - \tl_item:Nn \l__spath_tmpa_tl {6})
-                + 3*(\l__spath_tmpa_fp)^2 * (\tl_item:Nn \l__spath_tmpa_tl {12} - \tl_item:Nn \l__spath_tmpa_tl {9})
+                3*(1 - \l__spath_tmpa_fp)^2 * (\tl_item:Nn \l__spath_tmpa_tl {6}
+                - \tl_item:Nn \l__spath_tmpa_tl {3})
+                + 6 * (1 - \l__spath_tmpa_fp) * (\l__spath_tmpa_fp) *
+                (\tl_item:Nn \l__spath_tmpa_tl {9}
+                - \tl_item:Nn \l__spath_tmpa_tl {6})
+                + 3*(\l__spath_tmpa_fp)^2 * (\tl_item:Nn \l__spath_tmpa_tl {12}
+                - \tl_item:Nn \l__spath_tmpa_tl {9})
             }}
           }
         }
@@ -2296,7 +2902,14 @@
   \tl_clear:N \l__spath_tmpa_tl
   \__spath_tangent_at:nn {#1}{#2}
   \tl_set_eq:NN \l__spath_tmpb_tl \g__spath_output_tl
-  \fp_set:Nn \l__spath_tmpa_fp { sqrt( (\tl_item:Nn \l__spath_tmpb_tl {1})^2 +  (\tl_item:Nn \l__spath_tmpb_tl {2})^2 ) }
+  \fp_set:Nn \l__spath_tmpa_fp
+  {
+    sqrt(
+    (\tl_item:Nn \l__spath_tmpb_tl {1})^2
+    +
+    (\tl_item:Nn \l__spath_tmpb_tl {2})^2
+    )
+  }
   \fp_compare:nTF {\l__spath_tmpa_fp = 0}
   {
     \fp_set:Nn \l__spath_tmpa_fp {1}
@@ -2303,8 +2916,10 @@
     \fp_set:Nn \l__spath_tmpb_fp {0}
   }
   {
-    \fp_set:Nn \l__spath_tmpb_fp { (\tl_item:Nn \l__spath_tmpb_tl {2}) / \l__spath_tmpa_fp }
-    \fp_set:Nn \l__spath_tmpa_fp { (\tl_item:Nn \l__spath_tmpb_tl {1}) / \l__spath_tmpa_fp }
+    \fp_set:Nn \l__spath_tmpb_fp
+    { (\tl_item:Nn \l__spath_tmpb_tl {2}) / \l__spath_tmpa_fp }
+    \fp_set:Nn \l__spath_tmpa_fp
+    { (\tl_item:Nn \l__spath_tmpb_tl {1}) / \l__spath_tmpa_fp }
   }
   \tl_set:Nx \l__spath_tmpa_tl
   {
@@ -2332,22 +2947,6 @@
   \tl_gclear:N \g__spath_output_tl
 }
 \cs_generate_variant:Nn \spath_gtransformation_at:Nnn {NVn, NVV, NnV}
-\tl_new:N \l__spath_split_path_a_tl
-\tl_new:N \l__spath_split_path_b_tl
-\tl_new:N \l__spath_split_path_a_start_tl
-\tl_new:N \l__spath_split_path_b_start_tl
-\tl_new:N \l__spath_split_path_a_end_tl
-\tl_new:N \l__spath_split_path_b_end_tl
-\tl_new:N \l__spath_split_path_a_final_tl
-\tl_new:N \l__spath_split_path_b_final_tl
-
-\tl_new:N \l__spath_split_prev_first_tl
-\tl_new:N \l__spath_split_prev_second_tl
-
-\seq_new:N \l__spath_split_first_seq
-\seq_new:N \l__spath_split_second_seq
-
-\int_new:N \l__spath_split_segment_int
 \cs_new_protected_nopar:Npn \spath_intersect:NN #1#2
 {
   \pgfintersectionofpaths%
@@ -2357,8 +2956,6 @@
     \pgfsetpath #2
   }
 }
-\tl_new:N \l__spath_intersecta_tl
-\tl_new:N \l__spath_intersectb_tl
 \cs_new_protected_nopar:Npn \spath_intersect:nn #1#2
 {
   \tl_set:Nn \l__spath_intersecta_tl {#1}
@@ -2365,144 +2962,193 @@
   \tl_set:Nn \l__spath_intersectb_tl {#2}
   \spath_intersect:NN \l__spath_intersecta_tl \l__spath_intersectb_tl
 }
-\cs_new_protected_nopar:Npn \__spath_split_at_intersections:nn #1#2
+\cs_new_protected_nopar:Npn \__spath_split_component_at_intersections:nn #1#2
 {
   \group_begin:
+  \tl_clear:N \l__spath_tmpe_tl
+  \seq_clear:N \l__spath_tmpb_seq
 
-  % Clear some token lists and sequences
-  \tl_clear:N \l__spath_split_path_a_final_tl
-  \tl_clear:N \l__spath_split_path_b_final_tl
-  \seq_clear:N \l__spath_split_first_seq
-  \seq_clear:N \l__spath_split_second_seq
-
-  \pgfintersectionsortbyfirstpath
   % Find the intersections of these segments
-  \tl_set:Nn \l__spath_split_path_a_tl {#1}
-  \tl_set:Nn \l__spath_split_path_b_tl {#2}
-  % Remove empty components
+  \tl_set:Nn \l__spath_tmpb_tl {#1}
+  \tl_set:Nn \l__spath_tmpc_tl {#2}
 
-  \spath_intersect:NN \l__spath_split_path_a_tl \l__spath_split_path_b_tl
+  \spath_reallength:Nn \l__spath_tmpa_int {#1}
 
-  % If we get intersections
-  \int_compare:nT {\pgfintersectionsolutions > 0}
+  % Remember if the component is closed
+  \spath_finalaction:NV \l__spath_tmpa_tl \l__spath_tmpb_tl
+
+  \bool_set:Nn \l__spath_closed_bool
   {
-    % Find the times of the intersections on each path
-    \int_step_inline:nnnn {1} {1} {\pgfintersectionsolutions}
-    {
-    \pgfintersectiongetsolutiontimes{##1}{\l__spath_split_first_tl}{\l__spath_split_second_tl}
-      \seq_put_left:NV \l__spath_split_first_seq \l__spath_split_first_tl
-    }
+    \tl_if_eq_p:NN \l__spath_tmpa_tl \c_spath_closepath_tl
   }
 
-  \spath_intersect:NN \l__spath_split_path_b_tl \l__spath_split_path_a_tl
+  % Open it
+  \spath_open:N \l__spath_tmpb_tl
 
+  % Sort intersections along the component
+  \pgfintersectionsortbyfirstpath
+  \spath_intersect:NN \l__spath_tmpb_tl \l__spath_tmpc_tl
+
   % If we get intersections
   \int_compare:nT {\pgfintersectionsolutions > 0}
   {
-    % Find the times of the intersections on each path
+    % Find the times of the intersections on the component
     \int_step_inline:nnnn {1} {1} {\pgfintersectionsolutions}
     {
-    \pgfintersectiongetsolutiontimes{##1}{\l__spath_split_first_tl}{\l__spath_split_second_tl}
-      \seq_put_left:NV \l__spath_split_second_seq \l__spath_split_first_tl
+      \pgfintersectiongetsolutiontimes{##1}{\l__spath_tmph_tl}{\l__spath_tmpi_tl}
+      \seq_put_left:NV \l__spath_tmpb_seq \l__spath_tmph_tl
     }
-  }
 
-  \tl_set:Nn \l__spath_split_prev_first_tl {-1}
-
-  \seq_map_inline:Nn \l__spath_split_first_seq
-  {
-    \tl_set:Nn \l__spath_split_first_tl {##1}
-
-    \tl_set_eq:NN \l__spath_tmpa_tl \l__spath_split_first_tl
-    \int_compare:nT
+    \seq_get_left:NN \l__spath_tmpb_seq \l__spath_tmpa_tl
+    \fp_compare:nT
     {
-      \fp_to_int:n {floor( \l__spath_split_first_tl) }
-      =
-      \fp_to_int:n {floor( \l__spath_split_prev_first_tl) }
+      \l__spath_tmpa_tl > \l__spath_tmpa_int - .01
     }
     {
-      \tl_set:Nx \l__spath_split_first_tl
-      {
-        \fp_eval:n {
-          floor( \l__spath_split_first_tl )
-          +
-          ( \l__spath_split_first_tl - floor( \l__spath_split_first_tl) )
-          /
-          ( \l__spath_split_prev_first_tl - floor( \l__spath_split_prev_first_tl) )
-        }
-      }
+      \bool_set_false:N \l__spath_closed_bool
     }
-    \tl_set_eq:NN \l__spath_split_prev_first_tl \l__spath_tmpa_tl
+    \seq_get_right:NN \l__spath_tmpb_seq \l__spath_tmpa_tl
+    \fp_compare:nT
+    {
+      \l__spath_tmpa_tl < .01
+    }
+    {
+      \bool_set_false:N \l__spath_closed_bool
+    }
 
-    \spath_split_at:NNVV \l__spath_split_path_a_start_tl \l__spath_split_path_a_end_tl  \l__spath_split_path_a_tl \l__spath_split_first_tl
+    \tl_set:Nn \l__spath_tmpg_tl {-1}
 
-    \tl_put_left:NV \l__spath_split_path_a_final_tl \l__spath_split_path_a_end_tl
-    \tl_set_eq:NN \l__spath_split_path_a_tl \l__spath_split_path_a_start_tl
+    \seq_map_inline:Nn \l__spath_tmpb_seq
+    {
+      \tl_set:Nn \l__spath_tmph_tl {##1}
 
-  }
+      \tl_set_eq:NN \l__spath_tmpa_tl \l__spath_tmph_tl
+      \int_compare:nT
+      {
+        \fp_to_int:n {floor( \l__spath_tmph_tl) }
+        =
+        \fp_to_int:n {floor( \l__spath_tmpg_tl) }
+      }
+      {
+        \tl_set:Nx \l__spath_tmph_tl
+        {
+          \fp_eval:n {
+            floor( \l__spath_tmph_tl )
+            +
+            ( \l__spath_tmph_tl - floor( \l__spath_tmph_tl) )
+            /
+            ( \l__spath_tmpg_tl - floor( \l__spath_tmpg_tl) )
+          }
+        }
+      }
+      \tl_set_eq:NN \l__spath_tmpg_tl \l__spath_tmpa_tl
 
-  \tl_set:Nn \l__spath_split_prev_second_tl {-1}
+      \spath_split_at:NNVV
+      \l__spath_tmpd_tl
+      \l__spath_tmpf_tl
+      \l__spath_tmpb_tl
+      \l__spath_tmph_tl
 
-  \seq_map_inline:Nn \l__spath_split_second_seq
-  {
-    \tl_set:Nn \l__spath_split_second_tl {##1}
+      \tl_put_left:NV \l__spath_tmpe_tl \l__spath_tmpf_tl
+      \tl_set_eq:NN \l__spath_tmpb_tl \l__spath_tmpd_tl
 
-    \tl_set_eq:NN \l__spath_tmpa_tl \l__spath_split_second_tl
-    \int_compare:nT
-    {
-      \fp_to_int:n {floor( \l__spath_split_second_tl) }
-      =
-      \fp_to_int:n {floor( \l__spath_split_prev_second_tl) }
     }
-    {
-      \tl_set:Nx \l__spath_split_second_tl
-      {
-        \fp_eval:n {
-          floor( \l__spath_split_second_tl )
-          +
-          ( \l__spath_split_second_tl - floor( \l__spath_split_second_tl) )
-          /
-          ( \l__spath_split_prev_second_tl - floor( \l__spath_split_prev_second_tl) )
-        }
-      }
-    }
-    \tl_set_eq:NN \l__spath_split_prev_second_tl \l__spath_tmpa_tl
 
-    \spath_split_at:NNVV \l__spath_split_path_b_start_tl \l__spath_split_path_b_end_tl  \l__spath_split_path_b_tl\l__spath_split_second_tl
+    \tl_put_left:NV \l__spath_tmpe_tl \l__spath_tmpb_tl
 
-    \tl_put_left:NV \l__spath_split_path_b_final_tl \l__spath_split_path_b_end_tl
-    \tl_set_eq:NN \l__spath_split_path_b_tl \l__spath_split_path_b_start_tl
+    \spath_remove_empty_components:N \l__spath_tmpe_tl
 
+    \tl_set_eq:NN \l__spath_tmpb_tl \l__spath_tmpe_tl
   }
 
-  \tl_put_left:NV \l__spath_split_path_a_final_tl \l__spath_split_path_a_tl
-  \tl_put_left:NV \l__spath_split_path_b_final_tl \l__spath_split_path_b_tl
-
-  \tl_if_empty:NT \l__spath_split_path_a_final_tl
+  \bool_if:NT \l__spath_closed_bool
   {
-    \tl_set_eq:NN \l__spath_split_path_a_final_tl \l__spath_split_path_a_tl
+    \spath_join_component:Nn \l__spath_tmpb_tl {1}
   }
-  \tl_if_empty:NT \l__spath_split_path_b_final_tl
+
+  \tl_gclear:N \g__spath_output_tl
+  \tl_gset_eq:NN \g__spath_output_tl \l__spath_tmpb_tl
+
+  \group_end:
+}
+\cs_new_protected_nopar:Npn \spath_split_component_at_intersections:Nnn #1#2#3
+{
+  \__spath_split_component_at_intersections:nn {#2}{#3}
+  \tl_set_eq:NN #1 \g__spath_output_tl
+  \tl_gclear:N \g__spath_output_tl
+}
+\cs_generate_variant:Nn \spath_split_component_at_intersections:Nnn {NVn, NVV}
+\cs_new_protected_nopar:Npn \spath_split_component_at_intersections:Nn #1#2
+{
+  \spath_split_component_at_intersections:NVn #1#1{#2}
+}
+\cs_generate_variant:Nn \spath_split_component_at_intersections:Nn {cn, cv}
+\cs_new_protected_nopar:Npn \spath_gsplit_component_at_intersections:Nnn #1#2#3
+{
+  \__spath_split_component_at_intersections:nn {#2}{#3}
+  \tl_gset_eq:NN #1 \g__spath_output_tl
+  \tl_gclear:N \g__spath_output_tl
+}
+\cs_generate_variant:Nn \spath_gsplit_component_at_intersections:Nnn {NVn, NVV}
+\cs_new_protected_nopar:Npn \spath_gsplit_component_at_intersections:Nn #1#2
+{
+  \spath_gsplit_component_at_intersections:NVn #1#1{#2}
+}
+\cs_generate_variant:Nn \spath_gsplit_component_at_intersections:Nn {cn, cv}
+\cs_new_protected_nopar:Npn \__spath_split_path_at_intersections:nn #1#2
+{
+  \group_begin:
+
+  \seq_clear:N \l__spath_tmpa_seq
+  \seq_clear:N \l__spath_tmpb_seq
+
+  \spath_components_to_seq:Nn \l__spath_tmpa_seq {#1}
+  \seq_map_inline:Nn \l__spath_tmpa_seq
   {
-    \tl_set_eq:NN \l__spath_split_path_b_final_tl \l__spath_split_path_b_tl
+    \spath_split_component_at_intersections:Nnn \l__spath_tmpa_tl {##1} {#2}
+    \seq_put_right:NV \l__spath_tmpb_seq \l__spath_tmpa_tl
   }
 
-  \spath_remove_empty_components:N \l__spath_split_path_a_final_tl
-  \spath_remove_empty_components:N \l__spath_split_path_b_final_tl
-
   \tl_gclear:N \g__spath_output_tl
-  \__spath_tl_gput_right_braced:NV \g__spath_output_tl \l__spath_split_path_a_final_tl
-  \__spath_tl_gput_right_braced:NV \g__spath_output_tl \l__spath_split_path_b_final_tl
+  \tl_gset:Nx \g__spath_output_tl {\seq_use:Nn \l__spath_tmpb_seq {} }
   \group_end:
 }
+\cs_new_protected_nopar:Npn \spath_split_path_at_intersections:Nnn #1#2#3
+{
+  \__spath_split_path_at_intersections:nn {#2}{#3}
+  \tl_set_eq:NN #1 \g__spath_output_tl
+  \tl_gclear:N \g__spath_output_tl
+}
+\cs_generate_variant:Nn \spath_split_path_at_intersections:Nnn
+{NVn, NVV, cVn, cVV, cvn, cvv}
+\cs_new_protected_nopar:Npn \spath_split_path_at_intersections:Nn #1#2
+{
+  \spath_split_path_at_intersections:NVn #1#1{#2}
+}
+\cs_generate_variant:Nn \spath_split_path_at_intersections:Nn {cv, NV}
+\cs_new_protected_nopar:Npn \spath_gsplit_path_at_intersections:Nnn #1#2#3
+{
+  \__spath_split_path_at_intersections:nn {#2}{#3}
+  \tl_gset_eq:NN #1 \g__spath_output_tl
+  \tl_gclear:N \g__spath_output_tl
+}
+\cs_generate_variant:Nn \spath_gsplit_path_at_intersections:Nnn
+{NVn, NVV, cVn, cVV, cvn, cvv}
+\cs_new_protected_nopar:Npn \spath_gsplit_path_at_intersections:Nn #1#2
+{
+  \spath_gsplit_path_at_intersections:NVn #1#1{#2}
+}
+\cs_generate_variant:Nn \spath_gsplit_path_at_intersections:Nn {cv, NV}
 \cs_new_protected_nopar:Npn \spath_split_at_intersections:NNnn #1#2#3#4
 {
-  \__spath_split_at_intersections:nn {#3}{#4}
-  \tl_set:Nx #1 {\tl_item:Nn \g__spath_output_tl {1}}
-  \tl_set:Nx #2 {\tl_item:Nn \g__spath_output_tl {2}}
+  \__spath_split_path_at_intersections:nn {#3}{#4}
+  \tl_set_eq:NN #1 \g__spath_output_tl
+  \__spath_split_path_at_intersections:nn {#4}{#3}
+  \tl_set_eq:NN #2 \g__spath_output_tl
   \tl_gclear:N \g__spath_output_tl
 }
-\cs_generate_variant:Nn \spath_split_at_intersections:NNnn {NNVV, ccVV, ccvv}
+\cs_generate_variant:Nn \spath_split_at_intersections:NNnn
+{NNVn, NNVV, ccVn, ccVV, ccvn, ccvv}
 \cs_new_protected_nopar:Npn \spath_split_at_intersections:NN #1#2
 {
   \spath_split_at_intersections:NNVV #1#2#1#2
@@ -2510,146 +3156,120 @@
 \cs_generate_variant:Nn \spath_split_at_intersections:NN {cc}
 \cs_new_protected_nopar:Npn \spath_gsplit_at_intersections:NNnn #1#2#3#4
 {
-  \__spath_split_at_intersections:nn {#3}{#4}
-  \tl_gset:Nx #1 {\tl_item:Nn \g__spath_output_tl {1}}
-  \tl_gset:Nx #2 {\tl_item:Nn \g__spath_output_tl {2}}
+  \__spath_split_path_at_intersections:nn {#3}{#4}
+  \tl_gset_eq:NN #1 \g__spath_output_tl
+  \__spath_split_path_at_intersections:nn {#4}{#3}
+  \tl_gset_eq:NN #2 \g__spath_output_tl
   \tl_gclear:N \g__spath_output_tl
 }
-\cs_generate_variant:Nn \spath_gsplit_at_intersections:NNnn {NNVV, ccVV, ccvv}
+\cs_generate_variant:Nn \spath_gsplit_at_intersections:NNnn
+{NNVn, NNVV, ccVn, ccVV, ccvn, ccvv}
 \cs_new_protected_nopar:Npn \spath_gsplit_at_intersections:NN #1#2
 {
   \spath_gsplit_at_intersections:NNVV #1#2#1#2
 }
 \cs_generate_variant:Nn \spath_gsplit_at_intersections:NN {cc}
-\cs_new_protected_nopar:Npn \__spath_split_at_self_intersections:n #1
+\cs_new_protected_nopar:Npn \__spath_split_component_at_self_intersections:n #1
 {
   \group_begin:
+  \tl_set:Nn \l__spath_tmpe_tl {#1}
 
+  % Remember if the component is closed
+  \spath_finalaction:NV \l__spath_tmpa_tl \l__spath_tmpe_tl
+
+  \bool_set:Nn \l__spath_closed_bool
+  {
+    \tl_if_eq_p:NN \l__spath_tmpa_tl \c_spath_closepath_tl
+  }
+
   % Copy the path
-  \tl_set:Nn \l__spath_split_path_b_tl {#1}
+  \tl_set:Nn \l__spath_tmpe_tl {#1}
 
   % Open the path
-  \spath_open:N \l__spath_split_path_b_tl
-  % Remove empty components
-  \spath_remove_empty_components:N \l__spath_split_path_b_tl
+  \spath_open:N \l__spath_tmpe_tl
+  % Ensure beziers don't self-intersect
+  \spath_split_curves:N \l__spath_tmpe_tl
+
   % Make a copy for later
-  \tl_set_eq:NN \l__spath_split_path_b_final_tl \l__spath_split_path_b_tl
+  \tl_set_eq:NN \l__spath_tmpg_tl \l__spath_tmpe_tl
 
   % Clear some token lists and sequences
-  \tl_clear:N \l__spath_split_path_a_tl
-  \seq_clear:N \l__spath_split_first_seq
-  \int_zero:N \l__spath_split_segment_int
+  \tl_clear:N \l__spath_tmpd_tl
+  \seq_clear:N \l__spath_tmpb_seq
+  \int_zero:N \l__spath_tmpa_int
 
   \pgfintersectionsortbyfirstpath
 
-  \bool_do_until:nn
+  % Split the path into a sequence of segments
+  \spath_segments_to_seq:NV \l__spath_tmpa_seq \l__spath_tmpe_tl
+
+  \seq_map_indexed_inline:Nn \l__spath_tmpa_seq
   {
-    \int_compare_p:n
+    \seq_map_indexed_inline:Nn \l__spath_tmpa_seq
     {
-      \tl_count:N \l__spath_split_path_b_tl < 4
-    }
-  }
-  {
-    \tl_clear:N \l__spath_split_path_a_tl
-    \tl_put_right:Nx \l__spath_split_path_a_tl
-    {
-      \tl_item:Nn \l__spath_split_path_b_tl {1}
-      {\tl_item:Nn \l__spath_split_path_b_tl {2}}
-      {\tl_item:Nn \l__spath_split_path_b_tl {3}}
-    }
-
-    \tl_set:Nx \l__spath_tmpa_tl { \tl_item:Nn \l__spath_split_path_b_tl {4} }
-
-    \tl_set:Nx \l__spath_split_path_b_tl {\tl_tail:N \l__spath_split_path_b_tl}
-
-    \int_zero:N \l__spath_tmpa_int
-
-    \tl_case:Nn \l__spath_tmpa_tl
-    {
-      \c_spath_moveto_tl
+      % Don't intersect a segment with itself
+      \int_compare:nF
       {
-        \tl_clear:N \l__spath_split_path_a_tl
-        \tl_set:Nx \l__spath_split_path_b_tl {\tl_tail:N \l__spath_split_path_b_tl}
-        \tl_set:Nx \l__spath_split_path_b_tl {\tl_tail:N \l__spath_split_path_b_tl}
-        \tl_set:Nx \l__spath_split_path_b_tl {\tl_tail:N \l__spath_split_path_b_tl}
+        ##1 == ####1
       }
-      \c_spath_lineto_tl
       {
-        \int_set:Nn \l__spath_tmpa_int {1}
-      }
-      \c_spath_curvetoa_tl
-      {
-        \int_set:Nn \l__spath_tmpa_int {3}
-      }
-    }
+        \spath_intersect:nn {##2} {####2}
 
-    \prg_replicate:nn { \l__spath_tmpa_int }
-    {
-      \tl_set:Nx \l__spath_split_path_b_tl {\tl_tail:N \l__spath_split_path_b_tl}
-      \tl_set:Nx \l__spath_split_path_b_tl {\tl_tail:N \l__spath_split_path_b_tl}
-
-      \tl_put_right:Nx \l__spath_split_path_a_tl
-      {
-        \tl_item:Nn \l__spath_split_path_b_tl {1}
-        {\tl_item:Nn \l__spath_split_path_b_tl {2}}
-        {\tl_item:Nn \l__spath_split_path_b_tl {3}}
-      }
-
-      \tl_set:Nx \l__spath_split_path_b_tl {\tl_tail:N \l__spath_split_path_b_tl}
-    }
-
-    \tl_put_left:NV \l__spath_split_path_b_tl \c_spath_moveto_tl
-
-    \tl_if_empty:NF \l__spath_split_path_a_tl
-    {
-      % Intersect the current segment with the rest of the path
-      \spath_intersect:NN \l__spath_split_path_a_tl \l__spath_split_path_b_tl
-
-      % If we get intersections
-      \int_compare:nT {\pgfintersectionsolutions > 0}
-      {
-        % Find the times of the intersections on each path
-        \int_step_inline:nnnn {1} {1} {\pgfintersectionsolutions}
+        \int_compare:nT {\pgfintersectionsolutions > 0}
         {
-          \pgfintersectiongetsolutiontimes{##1}{\l__spath_split_first_tl}{\l__spath_split_second_tl}
-          \fp_compare:nT
+          % Find the times of the intersections on each path
+          \int_step_inline:nnnn {1} {1} {\pgfintersectionsolutions}
           {
-            \l__spath_split_first_tl < .99
-          }
-          {
-            \tl_set:Nx \l__spath_tmpa_tl {\fp_to_decimal:n {\l__spath_split_first_tl +  \l__spath_split_segment_int}}
-            \seq_put_right:NV \l__spath_split_first_seq \l__spath_tmpa_tl
-          }
-        }
-      }
+            \pgfintersectiongetsolutiontimes
+            {########1}{\l__spath_tmpb_tl}{\l__spath_tmpc_tl}
 
-      \spath_intersect:NN \l__spath_split_path_b_tl \l__spath_split_path_a_tl
-
-      % If we get intersections
-      \int_compare:nT {\pgfintersectionsolutions > 0}
-      {
-        % Find the times of the intersections on each path
-        \int_step_inline:nnnn {1} {1} {\pgfintersectionsolutions}
-        {
-          \pgfintersectiongetsolutiontimes{##1}{\l__spath_split_first_tl}{\l__spath_split_second_tl}
-          \fp_compare:nT
-          {
-            \l__spath_split_first_tl > .01
+            \bool_if:nT
+            {
+              !(
+              \fp_compare_p:n { \l__spath_tmpb_tl > .99 }
+              &&
+              \int_compare_p:n {##1 + 1 == ####1}
+              )
+              &&
+              !(
+              \fp_compare_p:n { \l__spath_tmpb_tl < .01 }
+              &&
+              \int_compare_p:n {##1 - 1 == ####1}
+              )
+              &&
+              !(
+              \l__spath_closed_bool
+              &&
+              \fp_compare_p:n { \l__spath_tmpb_tl < .01 }
+              &&
+              \int_compare_p:n {##1 == 1}
+              &&
+              \int_compare_p:n {\seq_count:N \l__spath_tmpa_seq == ####1}
+              )
+              &&
+              !(
+              \l__spath_closed_bool
+              &&
+              \fp_compare_p:n { \l__spath_tmpb_tl > .99 }
+              &&
+              \int_compare_p:n {####1 == 1}
+              &&
+              \int_compare_p:n {\seq_count:N \l__spath_tmpa_seq == ##1}
+              )
+            }
+            {
+              \tl_set:Nx \l__spath_tmpa_tl
+              {\fp_to_decimal:n {\l__spath_tmpb_tl +  ##1 - 1}}
+              \seq_put_right:NV \l__spath_tmpb_seq \l__spath_tmpa_tl
+            }
           }
-          {
-            \tl_set:Nx \l__spath_tmpa_tl {\fp_to_decimal:n {\l__spath_split_first_tl +  \l__spath_split_segment_int + 1}}
-            \seq_put_right:NV \l__spath_split_first_seq \l__spath_tmpa_tl
-          }
         }
       }
-
     }
-    % Increment the segment counter
-    \int_incr:N \l__spath_split_segment_int
   }
 
   % Sort the sequence by reverse order along the path
-  \seq_sort:Nn \l__spath_split_first_seq
+  \seq_sort:Nn \l__spath_tmpb_seq
   {
     \fp_compare:nNnTF { ##1 } < { ##2 }
     { \sort_return_swapped: }
@@ -2656,60 +3276,156 @@
     { \sort_return_same: }
   }
 
+  \seq_get_left:NN \l__spath_tmpb_seq \l__spath_tmpa_tl
+  \fp_compare:nT
+  {
+    \l__spath_tmpa_tl > \seq_count:N \l__spath_tmpa_seq - .01
+  }
+  {
+    \bool_set_false:N \l__spath_closed_bool
+  }
+  \seq_get_right:NN \l__spath_tmpb_seq \l__spath_tmpa_tl
+  \fp_compare:nT
+  {
+    \l__spath_tmpa_tl < .01
+  }
+  {
+    \bool_set_false:N \l__spath_closed_bool
+  }
+
   % Restore the original copy of the path
-  \tl_set_eq:NN \l__spath_split_path_b_tl \l__spath_split_path_b_final_tl
+  \tl_set_eq:NN \l__spath_tmpe_tl \l__spath_tmpg_tl
 
   % Clear the token lists
-  \tl_clear:N \l__spath_split_path_b_start_tl
-  \tl_clear:N \l__spath_split_path_b_end_tl
-  \tl_clear:N \l__spath_split_path_b_final_tl
+  \tl_clear:N \l__spath_tmpf_tl
+  \tl_clear:N \l__spath_tmph_tl
+  \tl_clear:N \l__spath_tmpg_tl
 
-  \tl_set:Nn \l__spath_split_prev_first_tl {-1}
+  \tl_set:Nn \l__spath_tmpi_tl {-1}
 
-  \seq_map_inline:Nn \l__spath_split_first_seq
+  \seq_map_inline:Nn \l__spath_tmpb_seq
   {
-    \tl_set:Nn \l__spath_split_first_tl {##1}
-    \tl_set_eq:NN \l__spath_tmpa_tl \l__spath_split_first_tl
+    \tl_set:Nn \l__spath_tmpb_tl {##1}
+    \tl_set_eq:NN \l__spath_tmpa_tl \l__spath_tmpb_tl
     \int_compare:nT
     {
-      \fp_to_int:n {floor( \l__spath_split_first_tl ) }
+      \fp_to_int:n {floor( \l__spath_tmpb_tl ) }
       =
-      \fp_to_int:n {floor( \l__spath_split_prev_first_tl) }
+      \fp_to_int:n {floor( \l__spath_tmpi_tl) }
     }
     {
-      \tl_set:Nx \l__spath_split_first_tl
+      \tl_set:Nx \l__spath_tmpb_tl
       {
         \fp_eval:n {
-          floor( \l__spath_split_first_tl )
+          floor( \l__spath_tmpb_tl )
           +
-          ( \l__spath_split_first_tl - floor( \l__spath_split_first_tl) )
+          ( \l__spath_tmpb_tl - floor( \l__spath_tmpb_tl) )
           /
-          ( \l__spath_split_prev_first_tl - floor( \l__spath_split_prev_first_tl) )
+          ( \l__spath_tmpi_tl - floor( \l__spath_tmpi_tl) )
         }
       }
     }
-    \tl_set_eq:NN \l__spath_split_prev_first_tl \l__spath_tmpa_tl
+    \tl_set_eq:NN \l__spath_tmpi_tl \l__spath_tmpa_tl
 
-    \spath_split_at:NNVV \l__spath_split_path_b_start_tl \l__spath_split_path_b_end_tl  \l__spath_split_path_b_tl \l__spath_split_first_tl
+    \spath_split_at:NNVV
+    \l__spath_tmpf_tl
+    \l__spath_tmph_tl
+    \l__spath_tmpe_tl
+    \l__spath_tmpb_tl
 
-    \tl_put_left:NV \l__spath_split_path_b_final_tl \l__spath_split_path_b_end_tl
-    \tl_set_eq:NN \l__spath_split_path_b_tl \l__spath_split_path_b_start_tl
+    \tl_put_left:NV \l__spath_tmpg_tl \l__spath_tmph_tl
+    \tl_set_eq:NN \l__spath_tmpe_tl \l__spath_tmpf_tl
 
   }
 
-  \tl_put_left:NV \l__spath_split_path_b_final_tl \l__spath_split_path_b_tl
+  \tl_put_left:NV \l__spath_tmpg_tl \l__spath_tmpe_tl
 
-  \tl_if_empty:NT \l__spath_split_path_b_final_tl
+  \tl_if_empty:NT \l__spath_tmpg_tl
   {
-    \tl_set_eq:NN \l__spath_split_path_b_final_tl \l__spath_split_path_b_tl
+    \tl_set_eq:NN \l__spath_tmpg_tl \l__spath_tmpe_tl
   }
 
-  \spath_remove_empty_components:N \l__spath_split_path_b_final_tl
+  \spath_remove_empty_components:N \l__spath_tmpg_tl
 
+  % Do something with closed
+  \bool_if:NT \l__spath_closed_bool
+  {
+    \spath_join_component:Nn \l__spath_tmpg_tl {1}
+  }
+
   \tl_gclear:N \g__spath_output_tl
-  \tl_gset_eq:NN \g__spath_output_tl \l__spath_split_path_b_final_tl
+  \tl_gset_eq:NN \g__spath_output_tl \l__spath_tmpg_tl
   \group_end:
 }
+\cs_new_protected_nopar:Npn \spath_split_component_at_self_intersections:Nn #1#2
+{
+  \__spath_split_component_at_self_intersections:n {#2}
+  \tl_set_eq:NN #1 \g__spath_output_tl
+  \tl_gclear:N \g__spath_output_tl
+}
+\cs_generate_variant:Nn \spath_split_component_at_self_intersections:Nn {NV}
+\cs_new_protected_nopar:Npn \spath_split_component_at_self_intersections:N #1
+{
+  \spath_split_component_at_self_intersections:NV #1#1
+}
+\cs_generate_variant:Nn \spath_split_component_at_self_intersections:N {c}
+\cs_new_protected_nopar:Npn \spath_gsplit_component_at_self_intersections:Nn #1#2
+{
+  \__spath_split_component_at_self_intersections:n {#2}
+  \tl_gset_eq:NN #1 \g__spath_output_tl
+  \tl_gclear:N \g__spath_output_tl
+}
+\cs_generate_variant:Nn \spath_gsplit_component_at_self_intersections:Nn {NV}
+\cs_new_protected_nopar:Npn \spath_gsplit_component_at_self_intersections:N #1
+{
+  \spath_gsplit_component_at_self_intersections:NV #1#1
+}
+\cs_generate_variant:Nn \spath_gsplit_component_at_self_intersections:N {c}
+\cs_new_protected_nopar:Npn \__spath_split_at_self_intersections:n #1
+{
+  \group_begin:
+  \spath_components_to_seq:Nn \l__spath_tmpa_seq {#1}
+  \seq_clear:N \l__spath_tmpb_seq
+  \seq_clear:N \l__spath_tmpc_seq
+
+  % Iterate over the components of the original path.
+  \bool_do_until:nn
+  {
+    \seq_if_empty_p:N \l__spath_tmpa_seq
+  }
+  {
+    % Get the next component
+    \seq_pop_left:NN \l__spath_tmpa_seq \l__spath_tmpa_tl
+    % Copy for later
+    \tl_set_eq:NN \l__spath_tmpc_tl \l__spath_tmpa_tl
+    \int_compare:nT
+    {
+      \tl_count:N \l__spath_tmpa_tl > 3
+    }
+    {
+
+      % Split against itself
+      \spath_split_component_at_self_intersections:N \l__spath_tmpa_tl
+      % Grab the rest of the path
+      \tl_set:Nx \l__spath_tmpb_tl
+      {
+        \seq_use:Nn \l__spath_tmpb_seq {}
+        \seq_use:Nn \l__spath_tmpa_seq {}
+      }
+      % Split against the rest of the path
+      \spath_split_path_at_intersections:NV \l__spath_tmpa_tl \l__spath_tmpb_tl
+    }
+    % Save the split path
+    \seq_put_right:NV \l__spath_tmpc_seq \l__spath_tmpa_tl
+    % Add the original copy to the sequence of processed components
+    \seq_put_right:NV \l__spath_tmpb_seq \l__spath_tmpc_tl
+  }
+
+  \tl_gclear:N \g__spath_output_tl
+  \tl_gset:Nx \g__spath_output_tl {\seq_use:Nn \l__spath_tmpc_seq {} }
+  \group_end:
+}
+\cs_generate_variant:Nn \__spath_split_at_self_intersections:n {V, v}
 \cs_new_protected_nopar:Npn \spath_split_at_self_intersections:Nn #1#2
 {
   \__spath_split_at_self_intersections:n {#2}
@@ -2716,7 +3432,7 @@
   \tl_set_eq:NN #1 \g__spath_output_tl
   \tl_gclear:N \g__spath_output_tl
 }
-\cs_generate_variant:Nn \spath_split_at_self_intersections:Nn {NV}
+\cs_generate_variant:Nn \spath_split_at_self_intersections:Nn {NV, cn, cV, cv}
 \cs_new_protected_nopar:Npn \spath_split_at_self_intersections:N #1
 {
   \spath_split_at_self_intersections:NV #1#1
@@ -2728,64 +3444,82 @@
   \tl_gset_eq:NN #1 \g__spath_output_tl
   \tl_gclear:N \g__spath_output_tl
 }
-\cs_generate_variant:Nn \spath_gsplit_at_self_intersections:Nn {NV}
+\cs_generate_variant:Nn \spath_gsplit_at_self_intersections:Nn {NV, cn, cV, cv}
 \cs_new_protected_nopar:Npn \spath_gsplit_at_self_intersections:N #1
 {
   \spath_gsplit_at_self_intersections:NV #1#1
 }
 \cs_generate_variant:Nn \spath_gsplit_at_self_intersections:N {c}
-\tl_new:N \l__spath_tmpj_tl
 \cs_new_protected_nopar:Npn \__spath_join_component:nn #1#2
 {
   \group_begin:
-  \spath_components_to_seq:Nn \l__spath_tmpa_seq {#1}
-  \int_compare:nT
+  \spath_numberofcomponents:Nn \l__spath_tmpa_int {#1}
+
+  \bool_if:nTF
   {
-    #2 == 1
+    \int_compare_p:n { #2 >= 1 }
+    &&
+    \int_compare_p:n { #2 <= \l__spath_tmpa_int }
   }
   {
-    \tl_clear:N \l__spath_tmpj_tl
-    \seq_pop_left:NN \l__spath_tmpa_seq \l__spath_tmpj_tl
-
-    \prg_replicate:nn {3}
+    \int_compare:nTF
     {
-      \tl_set:Nx \l__spath_tmpj_tl {\tl_tail:N \l__spath_tmpj_tl}
+      #2 == 1
     }
+    {
+      \int_compare:nTF
+      {
+        \l__spath_tmpa_int == 1
+      }
+      {
+        \tl_set:Nn \l__spath_tmpa_tl {#1}
+        \spath_initialpoint:Nn \l__spath_tmpb_tl {#1}
+        \tl_put_right:NV \l__spath_tmpa_tl \c_spath_closepath_tl
+        \tl_put_right:NV \l__spath_tmpa_tl \l__spath_tmpb_tl
+        \tl_gclear:N \g__spath_output_tl
+        \tl_gset_eq:NN \g__spath_output_tl \l__spath_tmpa_tl
+      }
+      {
+        \spath_components_to_seq:Nn \l__spath_tmpa_seq {#1}
+        \seq_pop_left:NN \l__spath_tmpa_seq \l__spath_tmpa_tl
 
-    \seq_put_right:NV \l__spath_tmpb_seq \l__spath_tmpj_tl
-  }
-  \bool_if:nT
-  {
-    \int_compare_p:n
-    {
-      #2 > 1
+        \prg_replicate:nn {3}
+        {
+          \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
+        }
+
+        \seq_put_right:NV \l__spath_tmpa_seq \l__spath_tmpa_tl
+
+        \tl_gclear:N \g__spath_output_tl
+        \tl_gset:Nx \g__spath_output_tl {\seq_use:Nn \l__spath_tmpa_seq {}}
+      }
     }
-    &&
-    \int_compare_p:n
     {
-      #2 <= \seq_count:N \l__spath_tmpa_seq
-    }
-  }
-  {
+      \spath_components_to_seq:Nn \l__spath_tmpa_seq {#1}
 
-    \seq_clear:N \l__spath_tmpb_seq
-    \seq_map_indexed_inline:Nn \l__spath_tmpa_seq
-    {
-      \tl_set:Nn \l__spath_tmpj_tl {##2}
-      \int_compare:nT {##1 = #2}
+      \seq_clear:N \l__spath_tmpb_seq
+      \seq_map_indexed_inline:Nn \l__spath_tmpa_seq
       {
-        \prg_replicate:nn {3}
+        \tl_set:Nn \l__spath_tmpa_tl {##2}
+        \int_compare:nT {##1 = #2}
         {
-          \tl_set:Nx \l__spath_tmpj_tl {\tl_tail:N \l__spath_tmpj_tl}
+          \prg_replicate:nn {3}
+          {
+            \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
+          }
         }
+        \seq_put_right:NV \l__spath_tmpb_seq \l__spath_tmpa_tl
       }
-      \seq_put_right:NV \l__spath_tmpb_seq \l__spath_tmpj_tl
+
+      \tl_gclear:N \g__spath_output_tl
+      \tl_gset:Nx \g__spath_output_tl {\seq_use:Nn \l__spath_tmpb_seq {}}
     }
-
-    \seq_set_eq:NN \l__spath_tmpa_seq \l__spath_tmpb_seq
   }
+  {
+    \tl_gclear:N \g__spath_output_tl
+    \tl_gset:Nn \g__spath_output_tl {#1}
+  }
 
-  \tl_gset:Nx \g__spath_output_tl {\seq_use:Nn \l__spath_tmpa_seq {} }
   \group_end:
 }
 \cs_new_protected_nopar:Npn \spath_join_component:Nnn #1#2#3
@@ -2832,12 +3566,16 @@
     {
       \dim_compare_p:n
       {
-        \dim_abs:n {\l__spath_move_x_dim - \tl_item:Nn \l__spath_tmpa_tl {2} } < 0.01pt
+        \dim_abs:n
+        {\l__spath_move_x_dim - \tl_item:Nn \l__spath_tmpa_tl {2} }
+        < 0.01pt
       }
       &&
       \dim_compare_p:n
       {
-        \dim_abs:n {\l__spath_move_y_dim - \tl_item:Nn \l__spath_tmpa_tl {3} } < 0.01pt
+        \dim_abs:n
+        {\l__spath_move_y_dim - \tl_item:Nn \l__spath_tmpa_tl {3} }
+        < 0.01pt
       }
     }
     {
@@ -2864,12 +3602,22 @@
   {
     \dim_compare_p:n
     {
-      \dim_abs:n {\tl_item:Nn \l__spath_tmpa_tl {1} - \tl_item:Nn \l__spath_tmpb_tl {1} } < 0.01pt
+      \dim_abs:n
+      {
+        \tl_item:Nn \l__spath_tmpa_tl {1} - \tl_item:Nn \l__spath_tmpb_tl {1}
+      }
+      <
+      0.01pt
     }
     &&
     \dim_compare_p:n
     {
-      \dim_abs:n {\tl_item:Nn \l__spath_tmpa_tl {2} - \tl_item:Nn \l__spath_tmpb_tl {2} } < 0.01pt
+      \dim_abs:n
+      {
+        \tl_item:Nn \l__spath_tmpa_tl {2} - \tl_item:Nn \l__spath_tmpb_tl {2}
+      }
+      <
+      0.01pt
     }
   }
   {
@@ -2976,7 +3724,7 @@
     <path~ d="
   }
   \tl_set:Nn \l__spath_tmpc_tl {use:n}
-  \tl_map_inline:Nn #1
+  \tl_map_inline:nn {#1}
   {
     \tl_set:Nn \l__spath_tmpb_tl {##1}
     \tl_case:NnF \l__spath_tmpb_tl
@@ -3009,7 +3757,9 @@
       }
     }
     {
-      \tl_put_right:Nx \l__spath_tmpa_tl {\use:c { \l__spath_tmpc_tl } {\dim_to_decimal:n {##1}} ~}
+      \tl_put_right:Nx
+      \l__spath_tmpa_tl
+      {\use:c { \l__spath_tmpc_tl } {\dim_to_decimal:n {##1}} ~}
     }
   }
   \tl_put_right:Nn \l__spath_tmpa_tl
@@ -3037,22 +3787,25 @@
 \iow_new:N \g__spath_stream
 \cs_new_protected_nopar:Npn \spath_export_to_svg:nn #1#2
 {
-  \spath_convert_path_to_svg:Nn \l__spath_iterp_tl {#2}
+  \group_begin:
+  \spath_convert_to_svg:Nn \l__spath_tmpa_tl {#2}
   \iow_open:Nn \g__spath_stream {#1 .svg}
   \iow_now:Nx \g__spath_stream
   {
-    \tl_use:N \l__spath_iterp_tl
+    \tl_use:N \l__spath_tmpa_tl
   }
   \iow_close:N \g__spath_stream
+  \group_end:
 }
+\cs_generate_variant:Nn \spath_export_to_svg:nn {nv, nV}
 \cs_new_protected_nopar:Npn \spath_show:n #1
 {
   \int_step_inline:nnnn {1} {3} {\tl_count:n {#1}}
   {
     \iow_term:x {
-      \tl_item:Nn \l__spath_tmpa_tl {##1}
-      {\tl_item:Nn \l__spath_tmpa_tl {##1+1}}
-      {\tl_item:Nn \l__spath_tmpa_tl {##1+2}}
+      \tl_item:nn {#1} {##1}
+      {\tl_item:nn {#1} {##1+1}}
+      {\tl_item:nn {#1} {##1+2}}
     }
   }
 }
@@ -3101,21 +3854,98 @@
   };
 }
 \cs_generate_variant:Nn \spath_tikz_path:nn {Vn, VV, nv, Vv, nV}
-\cs_new_protected_nopar:Npn \spath_set_tikz_coords:n #1
+\cs_new_protected_nopar:Npn \spath_set_tikz_data:n #1
 {
   \spath_finalpoint:Nn \l__spath_tmpa_tl {#1}
   \tl_set:Nx \l__spath_tmpa_tl
   {
-    \exp_not:c {tikz at lastx}=\tl_item:Nn \l__spath_tmpa_tl {1}
-    \exp_not:c {tikz at lasty}=\tl_item:Nn \l__spath_tmpa_tl {2}
-    \exp_not:c {tikz at lastxsaved}=\tl_item:Nn \l__spath_tmpa_tl {1}
-    \exp_not:c {tikz at lastysaved}=\tl_item:Nn \l__spath_tmpa_tl {2}
+    \exp_not:c {pgf at x}=\tl_item:Nn \l__spath_tmpa_tl {1}
+    \exp_not:c {pgf at y}=\tl_item:Nn \l__spath_tmpa_tl {2}
   }
+  \use:c {pgf at process}{%
+    \tl_use:N \l__spath_tmpa_tl
+    \pgftransforminvert
+    \use:c {pgf at pos@transform at glob}
+  }
+  \tl_set:Nx \l__spath_tmpa_tl
+  {
+    \exp_not:c {tikz at lastx}=\exp_not:c {pgf at x}
+    \exp_not:c {tikz at lasty}=\exp_not:c {pgf at y}
+    \exp_not:c {tikz at lastxsaved}=\exp_not:c {pgf at x}
+    \exp_not:c {tikz at lastysaved}=\exp_not:c {pgf at y}
+  }
   \tl_use:N \l__spath_tmpa_tl
+  \spath_finalmovepoint:Nn \l__spath_tmpa_tl {#1}
+  \ifpgfsyssoftpathmovetorelevant%
+  \tl_gset_eq:cN {pgfsyssoftpath at lastmoveto} \l__spath_tmpa_tl
+  \fi
+  \tl_set:Nx \l__spath_tmpa_tl
+  {
+    \exp_not:c {pgf at x}=\tl_item:Nn \l__spath_tmpa_tl {1}
+    \exp_not:c {pgf at y}=\tl_item:Nn \l__spath_tmpa_tl {2}
+  }
+  \use:c {pgf at process}{%
+    \tl_use:N \l__spath_tmpa_tl
+    \pgftransforminvert
+    \use:c {pgf at pos@transform at glob}
+  }
+  \tl_set:Nx \l__spath_tmpa_tl
+  {
+    \exp_not:c {tikz at lastmovetox}=\exp_not:c {pgf at x}
+    \exp_not:c {tikz at lastmovetoy}=\exp_not:c {pgf at y}
+  }
+  \tl_use:N \l__spath_tmpa_tl
+  \tl_clear_new:c {tikz at timer}
+  \tl_set:cn {tikz at timer}
+  {
+    \spath_reallength:Nn \l__spath_tmpa_int {#1}
+    \tl_set_eq:Nc \l__spath_tmpb_tl {tikz at time}
+    \tl_set:Nx \l__spath_tmpb_tl
+    {\fp_to_decimal:n {(\l__spath_tmpb_tl) * (\l__spath_tmpa_int)}}
+    \spath_transformation_at:NnV \l__spath_tmpc_tl {#1} \l__spath_tmpb_tl
+
+    \tl_set:Nx \l__spath_tmpa_tl
+    {
+      \exp_not:N \pgfpoint
+      { \tl_item:Nn \l__spath_tmpc_tl {5} }
+      { \tl_item:Nn \l__spath_tmpc_tl {6} }
+    }
+    \exp_args:NV \pgftransformshift \l__spath_tmpa_tl
+
+    \ifpgfresetnontranslationattime
+    \pgftransformresetnontranslations
+    \fi
+
+    \ifpgfslopedattime
+
+    \tl_set:Nx \l__spath_tmpa_tl
+    {
+      { \tl_item:Nn \l__spath_tmpc_tl {1} }
+      { \tl_item:Nn \l__spath_tmpc_tl {2} }
+      { \tl_item:Nn \l__spath_tmpc_tl {3} }
+      { \tl_item:Nn \l__spath_tmpc_tl {4} }
+    }
+    \ifpgfallowupsidedownattime
+    \else
+    \fp_compare:nT { \tl_item:Nn \l__spath_tmpc_tl {4} < 0}
+    {
+      \tl_set:Nx \l__spath_tmpa_tl
+      {
+        { \fp_eval:n { - (\tl_item:Nn \l__spath_tmpc_tl {1})} }
+        { \fp_eval:n { - (\tl_item:Nn \l__spath_tmpc_tl {2})} }
+        { \fp_eval:n { - (\tl_item:Nn \l__spath_tmpc_tl {3})} }
+        { \fp_eval:n { - (\tl_item:Nn \l__spath_tmpc_tl {4})} }
+      }
+    }
+    \fi
+    \tl_put_right:Nn \l__spath_tmpa_tl {{\pgfpointorigin}}
+    \exp_last_unbraced:NV \pgftransformcm \l__spath_tmpa_tl
+    \fi
+  }
 }
-\cs_generate_variant:Nn \spath_set_tikz_coords:n {V, v}
+\cs_generate_variant:Nn \spath_set_tikz_data:n {V, v}
 %% 
-%% Copyright (C) 2011-2019 by Andrew Stacey <loopspace at mathforge.org>
+%% Copyright (C) 2011-2021 by Andrew Stacey <loopspace at mathforge.org>
 %% 
 %% This work may be distributed and/or modified under the
 %% conditions of the LaTeX Project Public License (LPPL), either
@@ -3127,7 +3957,7 @@
 %% This work is "maintained" (as per LPPL maintenance status) by
 %% Andrew Stacey.
 %% 
-%% This work consists of the files  spath3.dtx
+%% This work consists of the files  spath3_code.dtx
 %%                                  calligraphy_doc.tex
 %%                                  knots_doc.tex
 %%                                  spath3.tex

Modified: trunk/Master/texmf-dist/tex/latex/spath3/tikzlibrarycalligraphy.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/spath3/tikzlibrarycalligraphy.code.tex	2021-02-06 22:28:55 UTC (rev 57638)
+++ trunk/Master/texmf-dist/tex/latex/spath3/tikzlibrarycalligraphy.code.tex	2021-02-06 22:29:38 UTC (rev 57639)
@@ -66,7 +66,8 @@
       \pgfsyssoftpath at getcurrentpath\l__cal_tmpa_tl
       \spath_components_to_seq:NV \l__cal_tmpa_seq \l__cal_tmpa_tl
       \seq_gclear_new:c {g__cal_pen_\pgfkeysvalueof{/tikz/pen~name}_seq}
-      \seq_gset_eq:cN {g__cal_pen_\pgfkeysvalueof{/tikz/pen~name}_seq} \l__cal_tmpa_seq
+      \seq_gset_eq:cN
+      {g__cal_pen_\pgfkeysvalueof{/tikz/pen~name}_seq} \l__cal_tmpa_seq
       \pgfusepath{discard}%
     }
   },
@@ -80,10 +81,12 @@
       \spath_components_to_seq:NV \l__cal_tmpa_seq \l__cal_tmpa_tl
       \tl_if_exist:cTF {g__cal_pen_\pgfkeysvalueof{/tikz/pen~name}_seq}
       {
-        \cal_path_create:Nc \l__cal_tmpa_seq {g__cal_pen_\pgfkeysvalueof{/tikz/pen~name}_seq}
+        \cal_path_create:Nc \l__cal_tmpa_seq
+        {g__cal_pen_\pgfkeysvalueof{/tikz/pen~name}_seq}
       }
       {
-        \msg_warning:nnx { calligraphy } { undefined pen } { \pgfkeysvalueof{/tikz/pen~name} }
+        \msg_warning:nnx { calligraphy } { undefined pen }
+        { \pgfkeysvalueof{/tikz/pen~name} }
       }
     }
   },
@@ -156,8 +159,10 @@
     \tl_set:cn {l__cal_stroke_style_#1} {#2}
   },
   this~stroke~style/.code={
-    \tl_clear_new:c {l__cal_stroke_inline_style_ \int_use:N \g__cal_path_component_int}
-    \tl_set:cn {l__cal_stroke_inline_style_ \int_use:N \g__cal_path_component_int} {#1}
+    \tl_clear_new:c
+    {l__cal_stroke_inline_style_ \int_use:N \g__cal_path_component_int}
+    \tl_set:cn
+    {l__cal_stroke_inline_style_ \int_use:N \g__cal_path_component_int} {#1}
   },
   annotate/.style={
     annotate~if,
@@ -264,23 +269,29 @@
           \spath_weld:NV \l__cal_tmp_patha_tl \l__cal_tmp_rpathb_tl
 
           \tl_clear:N \l__cal_tmpa_tl
-          \tl_set:Nn \l__cal_tmpa_tl {fill=\pgfkeysvalueof{/tikz/pen~colour},draw=none}
+          \tl_set:Nn \l__cal_tmpa_tl
+          {
+            fill=\pgfkeysvalueof{/tikz/pen~colour},
+            draw=none
+          }
           \tl_if_exist:cT  {l__cal_stroke_style_ \int_use:N \l__cal_tmpa_int}
           {
-            \tl_put_right:Nv \l__cal_tmpa_tl {l__cal_stroke_style_ \int_use:N \l__cal_tmpa_int}
+            \tl_put_right:Nv \l__cal_tmpa_tl
+            {l__cal_stroke_style_ \int_use:N \l__cal_tmpa_int}
           }
           \tl_if_exist:cT  {l__cal_stroke_inline_style_ \int_use:N \l__cal_tmpa_int}
           {
             \tl_put_right:Nn \l__cal_tmpa_tl {,}
-            \tl_put_right:Nv \l__cal_tmpa_tl {l__cal_stroke_inline_style_ \int_use:N \l__cal_tmpa_int}
+            \tl_put_right:Nv \l__cal_tmpa_tl
+            {l__cal_stroke_inline_style_ \int_use:N \l__cal_tmpa_int}
           }
           \tl_if_exist:cT  {l__cal_nib_style_ \int_use:N \l__cal_tmpb_int}
           {
             \tl_put_right:Nn \l__cal_tmpa_tl {,}
-            \tl_put_right:Nv \l__cal_tmpa_tl {l__cal_nib_style_ \int_use:N \l__cal_tmpb_int}
+            \tl_put_right:Nv \l__cal_tmpa_tl
+            {l__cal_nib_style_ \int_use:N \l__cal_tmpb_int}
           }
           \spath_tikz_path:VV \l__cal_tmpa_tl \l__cal_tmp_patha_tl
-
         }
         \pgfsys at endscope
         \group_end:
@@ -291,7 +302,9 @@
         \seq_get_right:NN #2 \l__cal_tmpa_tl
         \spath_finalpoint:NV \l__cal_tmpa_tl \l__cal_tmpa_tl
         \spath_translate:NV \l__cal_tmp_path_tl \l__cal_tmpa_tl
-        \tikz at scan@one at point\pgfutil at firstofone\pgfkeysvalueof{/tikz/annotation~shift}
+        \tikz at scan@one at point
+        \pgfutil at firstofone
+        \pgfkeysvalueof{/tikz/annotation~shift}
 
         \spath_translate:Nnn \l__cal_tmp_path_tl {\pgf at x} {\pgf at y}
 
@@ -302,7 +315,10 @@
 
         \exp_last_unbraced:NV \pgfqpoint \l__cal_tmpa_tl
         \begin{scope}[reset~ cm]
-        \node[every~annotation~node/.try,tl~use:c =  {l__cal_annotation_style_ \int_use:N \l__cal_tmpa_int _tl}] at (\pgf at x,\pgf at y) {\int_use:N \l__cal_tmpa_int};
+        \node[
+          every~annotation~node/.try,
+          tl~use:c = {l__cal_annotation_style_ \int_use:N \l__cal_tmpa_int _tl}
+        ] at (\pgf at x,\pgf at y) {\int_use:N \l__cal_tmpa_int};
         \end{scope}
       }
     }
@@ -480,8 +496,18 @@
     (\l__cal_tmpa_fp^2 + \l__cal_tmpb_fp^2)^.5
   }
 
-  \fp_set:Nn \l__cal_tmpa_fp {.5*\l__cal_taper_width_dim *     \l__cal_tmpa_fp / \l__cal_tmpe_fp}
-  \fp_set:Nn \l__cal_tmpb_fp {.5*\l__cal_taper_width_dim *     \l__cal_tmpb_fp / \l__cal_tmpe_fp}
+  \fp_set:Nn \l__cal_tmpa_fp
+  {
+    .5*\l__cal_taper_width_dim
+    *
+    \l__cal_tmpa_fp / \l__cal_tmpe_fp
+  }
+  \fp_set:Nn \l__cal_tmpb_fp
+  {
+    .5*\l__cal_taper_width_dim
+    *
+    \l__cal_tmpb_fp / \l__cal_tmpe_fp
+  }
 
   \fp_set:Nn \l__cal_tmpc_fp
   {
@@ -496,13 +522,23 @@
     (\l__cal_tmpc_fp^2 + \l__cal_tmpd_fp^2)^.5
   }
 
-  \fp_set:Nn \l__cal_tmpc_fp {.5*\l__cal_line_width_dim * \l__cal_tmpc_fp / \l__cal_tmpe_fp}
-  \fp_set:Nn \l__cal_tmpd_fp {.5*\l__cal_line_width_dim * \l__cal_tmpd_fp / \l__cal_tmpe_fp}
+  \fp_set:Nn \l__cal_tmpc_fp
+  {
+    .5*\l__cal_line_width_dim
+    *
+    \l__cal_tmpc_fp / \l__cal_tmpe_fp
+  }
+  \fp_set:Nn \l__cal_tmpd_fp
+  {
+    .5*\l__cal_line_width_dim
+    *
+    \l__cal_tmpd_fp / \l__cal_tmpe_fp
+  }
 
   \tl_put_right:Nx \l__cal_tmpb_tl
   {
     {\dim_eval:n { \fp_to_dim:N \l__cal_tmpa_fp + \l__cal_tmpa_dim}}
-    {\dim_eval:n { \fp_to_dim:N \l__cal_tmpb_fp +             \l__cal_tmpb_dim}}
+    {\dim_eval:n { \fp_to_dim:N \l__cal_tmpb_fp + \l__cal_tmpb_dim}}
   }
 
   \tl_put_right:NV \l__cal_tmpb_tl \c_spath_curvetoa_tl
@@ -533,8 +569,22 @@
 
   \tl_put_right:Nx \l__cal_tmpb_tl
   {
-    {\dim_eval:n { \fp_to_dim:N \l__cal_tmpc_fp + \l__cal_tmpg_dim - \fp_to_dim:n{ 1.32 * \l__cal_tmpd_fp}}}
-    {\dim_eval:n { \fp_to_dim:N \l__cal_tmpd_fp + \l__cal_tmph_dim + \fp_to_dim:n {1.32* \l__cal_tmpc_fp}}}
+    {
+      \dim_eval:n
+      {
+        \fp_to_dim:N \l__cal_tmpc_fp + \l__cal_tmpg_dim
+        - \fp_to_dim:n{ 1.32 * \l__cal_tmpd_fp
+        }
+      }
+    }
+    {
+      \dim_eval:n
+      {
+        \fp_to_dim:N \l__cal_tmpd_fp + \l__cal_tmph_dim
+        + \fp_to_dim:n {1.32* \l__cal_tmpc_fp
+        }
+      }
+    }
   }
 
   \tl_put_right:NV \l__cal_tmpb_tl \c_spath_curvetob_tl
@@ -541,8 +591,22 @@
 
   \tl_put_right:Nx \l__cal_tmpb_tl
   {
-    {\dim_eval:n { -\fp_to_dim:N \l__cal_tmpc_fp + \l__cal_tmpg_dim - \fp_to_dim:n {1.32 * \l__cal_tmpd_fp}}}
-    {\dim_eval:n { -\fp_to_dim:N \l__cal_tmpd_fp + \l__cal_tmph_dim + \fp_to_dim:n {1.32 * \l__cal_tmpc_fp}}}
+    {
+      \dim_eval:n
+      {
+        -\fp_to_dim:N \l__cal_tmpc_fp + \l__cal_tmpg_dim
+        - \fp_to_dim:n {1.32 * \l__cal_tmpd_fp
+        }
+      }
+    }
+    {
+      \dim_eval:n
+      {
+        -\fp_to_dim:N \l__cal_tmpd_fp + \l__cal_tmph_dim
+        + \fp_to_dim:n {1.32 * \l__cal_tmpc_fp
+        }
+      }
+    }
   }
 
   \tl_put_right:NV \l__cal_tmpb_tl \c_spath_curveto_tl
@@ -581,8 +645,20 @@
 
   \tl_put_right:Nx \l__cal_tmpb_tl
   {
-    {\dim_eval:n { -\fp_to_dim:N \l__cal_tmpa_fp + \l__cal_tmpa_dim + \fp_to_dim:n{ 1.32 * \l__cal_tmpb_fp}}}
-    {\dim_eval:n { -\fp_to_dim:N \l__cal_tmpb_fp + \l__cal_tmpb_dim - \fp_to_dim:n {1.32* \l__cal_tmpa_fp}}}
+    {
+      \dim_eval:n
+      {
+        -\fp_to_dim:N \l__cal_tmpa_fp + \l__cal_tmpa_dim
+        + \fp_to_dim:n{ 1.32 * \l__cal_tmpb_fp}
+      }
+    }
+    {
+      \dim_eval:n
+      {
+        -\fp_to_dim:N \l__cal_tmpb_fp + \l__cal_tmpb_dim
+        - \fp_to_dim:n {1.32* \l__cal_tmpa_fp}
+      }
+    }
   }
 
   \tl_put_right:NV \l__cal_tmpb_tl \c_spath_curvetob_tl
@@ -589,8 +665,20 @@
 
   \tl_put_right:Nx \l__cal_tmpb_tl
   {
-    {\dim_eval:n { \fp_to_dim:N \l__cal_tmpa_fp + \l__cal_tmpa_dim + \fp_to_dim:n {1.32 * \l__cal_tmpb_fp}}}
-    {\dim_eval:n { \fp_to_dim:N \l__cal_tmpb_fp + \l__cal_tmpb_dim - \fp_to_dim:n {1.32 * \l__cal_tmpa_fp}}}
+    {
+      \dim_eval:n
+      {
+        \fp_to_dim:N \l__cal_tmpa_fp + \l__cal_tmpa_dim
+        + \fp_to_dim:n {1.32 * \l__cal_tmpb_fp}
+      }
+    }
+    {
+      \dim_eval:n
+      {
+        \fp_to_dim:N \l__cal_tmpb_fp + \l__cal_tmpb_dim
+        - \fp_to_dim:n {1.32 * \l__cal_tmpa_fp}
+      }
+    }
   }
 
   \tl_put_right:NV \l__cal_tmpb_tl \c_spath_curveto_tl
@@ -598,7 +686,7 @@
   \tl_put_right:Nx \l__cal_tmpb_tl
   {
     {\dim_eval:n { \fp_to_dim:N \l__cal_tmpa_fp + \l__cal_tmpa_dim}}
-    {\dim_eval:n { \fp_to_dim:N \l__cal_tmpb_fp +             \l__cal_tmpb_dim}}
+    {\dim_eval:n { \fp_to_dim:N \l__cal_tmpb_fp + \l__cal_tmpb_dim}}
   }
 
   \pgfsyssoftpath at setcurrentpath\l__cal_tmpb_tl
@@ -617,98 +705,187 @@
 \ExplSyntaxOff
 \expandafter\ifx\csname pgfdeclaredecoration\endcsname\relax
 \else
-\pgfdeclaredecoration{calligraphic brace}{brace}
-{
-  \state{brace}[width=+\pgfdecoratedremainingdistance,next state=final]
-  {
-    \pgfsyssoftpath at setcurrentpath{\pgfutil at empty}
-    \pgfpathmoveto{\pgfpointorigin}
-    \pgfpathcurveto
-    {\pgfqpoint{.15\pgfdecorationsegmentamplitude}{.3\pgfdecorationsegmentamplitude}}
-    {\pgfqpoint{.5\pgfdecorationsegmentamplitude}{.5\pgfdecorationsegmentamplitude}}
-    {\pgfqpoint{\pgfdecorationsegmentamplitude}{.5\pgfdecorationsegmentamplitude}}
-    {
-      \pgftransformxshift{+\pgfdecorationsegmentaspect\pgfdecoratedremainingdistance}
-      \pgfpathlineto{\pgfqpoint{-\pgfdecorationsegmentamplitude}{.5\pgfdecorationsegmentamplitude}}
+\pgfdeclaredecoration{calligraphic brace}{brace}%
+{%
+  \state{brace}[width=+\pgfdecoratedremainingdistance,next state=final]%
+  {%
+    \pgfsyssoftpath at setcurrentpath{\pgfutil at empty}%
+    \pgfpathmoveto{\pgfpointorigin}%
+    \pgfpathcurveto%
+    {%
+      \pgfqpoint%
+      {.15\pgfdecorationsegmentamplitude}%
+      {.3\pgfdecorationsegmentamplitude}%
+    }%
+    {%
+      \pgfqpoint%
+      {.5\pgfdecorationsegmentamplitude}%
+      {.5\pgfdecorationsegmentamplitude}%
+    }%
+    {%
+      \pgfqpoint%
+      {\pgfdecorationsegmentamplitude}%
+      {.5\pgfdecorationsegmentamplitude}%
+    }%
+    {%
+      \pgftransformxshift%
+      {+\pgfdecorationsegmentaspect\pgfdecoratedremainingdistance}%
+      \pgfpathlineto%
+      {%
+        \pgfqpoint%
+        {-\pgfdecorationsegmentamplitude}%
+        {.5\pgfdecorationsegmentamplitude}%
+      }%
       \pgfpathcurveto
-      {\pgfqpoint{-.5\pgfdecorationsegmentamplitude}{.5\pgfdecorationsegmentamplitude}}
-      {\pgfqpoint{-.15\pgfdecorationsegmentamplitude}{.7\pgfdecorationsegmentamplitude}}
-      {\pgfqpoint{0\pgfdecorationsegmentamplitude}{1\pgfdecorationsegmentamplitude}}
-      \pgfpathmoveto{\pgfqpoint{0\pgfdecorationsegmentamplitude}{1\pgfdecorationsegmentamplitude}}
-      \pgfpathcurveto
-      {\pgfqpoint{.15\pgfdecorationsegmentamplitude}{.7\pgfdecorationsegmentamplitude}}
-      {\pgfqpoint{.5\pgfdecorationsegmentamplitude}{.5\pgfdecorationsegmentamplitude}}
-      {\pgfqpoint{\pgfdecorationsegmentamplitude}{.5\pgfdecorationsegmentamplitude}}
-    }
-    {
-      \pgftransformxshift{+\pgfdecoratedremainingdistance}
-      \pgfpathlineto{\pgfqpoint{-\pgfdecorationsegmentamplitude}{.5\pgfdecorationsegmentamplitude}}
-      \pgfpathcurveto
-      {\pgfqpoint{-.5\pgfdecorationsegmentamplitude}{.5\pgfdecorationsegmentamplitude}}
-      {\pgfqpoint{-.15\pgfdecorationsegmentamplitude}{.3\pgfdecorationsegmentamplitude}}
-      {\pgfqpoint{0pt}{0pt}}
-    }
-    \tikzset{
-      taper width=.5\pgflinewidth,
-      taper
+      {%
+        \pgfqpoint%
+        {-.5\pgfdecorationsegmentamplitude}%
+        {.5\pgfdecorationsegmentamplitude}%
+      }%
+      {%
+        \pgfqpoint%
+        {-.15\pgfdecorationsegmentamplitude}%
+        {.7\pgfdecorationsegmentamplitude}%
+      }%
+      {%
+        \pgfqpoint%
+        {0\pgfdecorationsegmentamplitude}%
+        {1\pgfdecorationsegmentamplitude}%
+      }%
+      \pgfpathmoveto%
+      {%
+        \pgfqpoint%
+        {0\pgfdecorationsegmentamplitude}%
+        {1\pgfdecorationsegmentamplitude}%
+      }%
+      \pgfpathcurveto%
+      {%
+        \pgfqpoint%
+        {.15\pgfdecorationsegmentamplitude}%
+        {.7\pgfdecorationsegmentamplitude}%
+      }%
+      {%
+        \pgfqpoint%
+        {.5\pgfdecorationsegmentamplitude}%
+        {.5\pgfdecorationsegmentamplitude}%
+      }%
+      {%
+        \pgfqpoint%
+        {\pgfdecorationsegmentamplitude}%
+        {.5\pgfdecorationsegmentamplitude}%
+      }%
     }%
-    \pgfsyssoftpath at getcurrentpath\cal at tmp@path
-    \CopperplatePath{\cal at tmp@path}
-  }
-  \state{final}{}
-}
+    {%
+      \pgftransformxshift{+\pgfdecoratedremainingdistance}%
+      \pgfpathlineto%
+      {%
+        \pgfqpoint%
+        {-\pgfdecorationsegmentamplitude}%
+        {.5\pgfdecorationsegmentamplitude}%
+      }%
+      \pgfpathcurveto%
+      {%
+        \pgfqpoint%
+        {-.5\pgfdecorationsegmentamplitude}%
+        {.5\pgfdecorationsegmentamplitude}%
+      }%
+      {%
+        \pgfqpoint%
+        {-.15\pgfdecorationsegmentamplitude}%
+        {.3\pgfdecorationsegmentamplitude}%
+      }%
+      {\pgfqpoint{0pt}{0pt}}%
+    }%
+    \tikzset{%
+      taper width=.5\pgflinewidth,%
+      taper%
+    }%%
+    \pgfsyssoftpath at getcurrentpath\cal at tmp@path%
+    \CopperplatePath{\cal at tmp@path}%
+  }%
+  \state{final}{}%
+}%
 \pgfdeclaredecoration{calligraphic straight parenthesis}{brace}
 {
-  \state{brace}[width=+\pgfdecoratedremainingdistance,next state=final]
-  {
-    \pgfsyssoftpath at setcurrentpath{\pgfutil at empty}
-    \pgfpathmoveto{\pgfpointorigin}
-    \pgfpathcurveto
-    {\pgfqpoint{.76604\pgfdecorationsegmentamplitude}{.64279\pgfdecorationsegmentamplitude}}
-    {\pgfqpoint{2.3333\pgfdecorationsegmentamplitude}{\pgfdecorationsegmentamplitude}}
-    {\pgfqpoint{3.3333\pgfdecorationsegmentamplitude}{\pgfdecorationsegmentamplitude}}
-    {
-      \pgftransformxshift{+\pgfdecoratedremainingdistance}
-      \pgfpathlineto{\pgfqpoint{-3.3333\pgfdecorationsegmentamplitude}{\pgfdecorationsegmentamplitude}}
-      \pgfpathcurveto
-      {\pgfqpoint{-2.3333\pgfdecorationsegmentamplitude}{\pgfdecorationsegmentamplitude}}
-      {\pgfqpoint{-.76604\pgfdecorationsegmentamplitude}{.64279\pgfdecorationsegmentamplitude}}
-      {\pgfqpoint{0pt}{0pt}}
-    }
-    \tikzset{
-      taper width=.5\pgflinewidth,
-      taper
+  \state{brace}[width=+\pgfdecoratedremainingdistance,next state=final]%
+  {%
+    \pgfsyssoftpath at setcurrentpath{\pgfutil at empty}%
+    \pgfpathmoveto{\pgfpointorigin}%
+    \pgfpathcurveto%
+    {%
+      \pgfqpoint%
+      {.76604\pgfdecorationsegmentamplitude}%
+      {.64279\pgfdecorationsegmentamplitude}%
     }%
-    \pgfsyssoftpath at getcurrentpath\cal at tmp@path
-    \CopperplatePath{\cal at tmp@path}
-  }
+    {%
+      \pgfqpoint%
+      {2.3333\pgfdecorationsegmentamplitude}%
+      {\pgfdecorationsegmentamplitude}%
+    }%
+    {%
+      \pgfqpoint%
+      {3.3333\pgfdecorationsegmentamplitude}%
+      {\pgfdecorationsegmentamplitude}%
+    }%
+    {%
+      \pgftransformxshift{+\pgfdecoratedremainingdistance}%
+      \pgfpathlineto%
+      {%
+        \pgfqpoint%
+        {-3.3333\pgfdecorationsegmentamplitude}%
+        {\pgfdecorationsegmentamplitude}%
+      }%
+      \pgfpathcurveto%
+      {%
+        \pgfqpoint%
+        {-2.3333\pgfdecorationsegmentamplitude}%
+        {\pgfdecorationsegmentamplitude}%
+      }%
+      {%
+        \pgfqpoint%
+        {-.76604\pgfdecorationsegmentamplitude}%
+        {.64279\pgfdecorationsegmentamplitude}%
+      }%
+      {\pgfqpoint{0pt}{0pt}}%
+    }%
+    \tikzset{%
+      taper width=.5\pgflinewidth,%
+      taper%
+    }%
+    \pgfsyssoftpath at getcurrentpath\cal at tmp@path%
+    \CopperplatePath{\cal at tmp@path}%
+  }%
   \state{final}{}%
 }
 \pgfdeclaredecoration{calligraphic curved parenthesis}{brace}
 {
-  \state{brace}[width=+\pgfdecoratedremainingdistance,next state=final]
-  {
-    \pgfsyssoftpath at setcurrentpath{\pgfutil at empty}
-    \pgfpathmoveto{\pgfpointorigin}
-    \pgf at xa=\pgfdecoratedremainingdistance\relax
-    \advance\pgf at xa by -1.5890\pgfdecorationsegmentamplitude\relax
-    \edef\cgrphy at xa{\the\pgf at xa}
-    \pgfpathcurveto
-    {\pgfqpoint{1.5890\pgfdecorationsegmentamplitude}{1.3333\pgfdecorationsegmentamplitude}}
-    {\pgfqpoint{\cgrphy at xa}{1.3333\pgfdecorationsegmentamplitude}}
-    {\pgfqpoint{\pgfdecoratedremainingdistance}{0pt}}
-    \tikzset{
-      taper width=.5\pgflinewidth,
-      taper
+  \state{brace}[width=+\pgfdecoratedremainingdistance,next state=final]%
+  {%
+    \pgfsyssoftpath at setcurrentpath{\pgfutil at empty}%
+    \pgfpathmoveto{\pgfpointorigin}%
+    \pgf at xa=\pgfdecoratedremainingdistance\relax%
+    \advance\pgf at xa by -1.5890\pgfdecorationsegmentamplitude\relax%
+    \edef\cgrphy at xa{\the\pgf at xa}%
+    \pgfpathcurveto%
+    {%
+      \pgfqpoint%
+      {1.5890\pgfdecorationsegmentamplitude}%
+      {1.3333\pgfdecorationsegmentamplitude}%
     }%
-    \pgfsyssoftpath at getcurrentpath\cal at tmp@path
-    \CopperplatePath{\cal at tmp@path}
-  }
+    {\pgfqpoint{\cgrphy at xa}{1.3333\pgfdecorationsegmentamplitude}}%
+    {\pgfqpoint{\pgfdecoratedremainingdistance}{0pt}}%
+    \tikzset{%
+      taper width=.5\pgflinewidth,%
+      taper%
+    }%
+    \pgfsyssoftpath at getcurrentpath\cal at tmp@path%
+    \CopperplatePath{\cal at tmp@path}%
+  }%
   \state{final}{}%
 }
 \fi
 %% 
-%% Copyright (C) 2011-2019 by Andrew Stacey <loopspace at mathforge.org>
+%% Copyright (C) 2011-2021 by Andrew Stacey <loopspace at mathforge.org>
 %% 
 %% This work may be distributed and/or modified under the
 %% conditions of the LaTeX Project Public License (LPPL), either
@@ -720,7 +897,7 @@
 %% This work is "maintained" (as per LPPL maintenance status) by
 %% Andrew Stacey.
 %% 
-%% This work consists of the files  spath3.dtx
+%% This work consists of the files  spath3_code.dtx
 %%                                  calligraphy_doc.tex
 %%                                  knots_doc.tex
 %%                                  spath3.tex

Modified: trunk/Master/texmf-dist/tex/latex/spath3/tikzlibraryknots.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/spath3/tikzlibraryknots.code.tex	2021-02-06 22:28:55 UTC (rev 57638)
+++ trunk/Master/texmf-dist/tex/latex/spath3/tikzlibraryknots.code.tex	2021-02-06 22:29:38 UTC (rev 57639)
@@ -45,6 +45,7 @@
 \dim_new:N \l__knot_tmpa_dim
 \dim_new:N \l__knot_tmpb_dim
 \dim_new:N \l__knot_tolerance_dim
+\dim_new:N \l__knot_redraw_tolerance_dim
 \dim_new:N \l__knot_clip_bg_radius_dim
 \dim_new:N \l__knot_clip_draw_radius_dim
 
@@ -247,6 +248,11 @@
 {
   \pgfscope
   \pgftransformreset
+  \dim_set:Nn \l__knot_redraw_tolerance_dim {\fp_to_dim:n
+    {
+      sqrt(2) * max(\l__knot_clip_bg_radius_dim, \l__knot_clip_draw_radius_dim)
+    }
+  }
   \int_step_function:nnnN {1} {1} {\l__knot_strands_int} \knot_draw_strand:n
   \bool_if:NF \l__knot_super_draft_bool
   {
@@ -267,13 +273,21 @@
     {
       \tl_set:Nn \l__knot_node_tl {
         \exp_not:N \node[coordinate,
-          pin={[node~ contents={\int_use:N \g__knot_intersections_int},knot~ diagram/draft/crossing~ label, knot~ diagram/draft/crossing~ \int_use:N \g__knot_intersections_int \c_space_tl label/.try]
+          pin={[
+              node~ contents={\int_use:N \g__knot_intersections_int},
+              knot~ diagram/draft/crossing~ label,
+              knot~ diagram/draft/crossing~
+              \int_use:N \g__knot_intersections_int \c_space_tl label/.try
+            ]
             }]
       }
     }
     \int_step_variable:nnnNn {1} {1} {\l__knot_tmpa_int - 1} \l__knot_tmpa_tl
     {
-      \int_step_variable:nnnNn {\tl_use:N \l__knot_tmpa_tl + 1} {1}     {\l__knot_tmpa_int} \l__knot_tmpb_tl
+      \int_step_variable:nnnNn
+      {\tl_use:N \l__knot_tmpa_tl + 1}
+      {1}
+      {\l__knot_tmpa_int} \l__knot_tmpb_tl
       {
         \knot_intersections:VV \l__knot_tmpa_tl \l__knot_tmpb_tl
       }
@@ -290,7 +304,12 @@
   \spath_bake_round:c {knot strand #1}
   \tl_set:Nn \l__knot_tmpa_tl {knot~ diagram/every~ strand/.try,}
   \tl_put_right:Nv \l__knot_tmpa_tl {l__knot_options_strand #1}
-  \tl_put_right:Nn \l__knot_tmpa_tl {,knot~ diagram/only~ when~ rendering/.try,only~ when~ rendering/.try}
+  \tl_put_right:Nn \l__knot_tmpa_tl
+  {
+    ,
+    knot~ diagram/only~ when~ rendering/.try,
+    only~ when~ rendering/.try
+  }
   \spath_tikz_path:Vv \l__knot_tmpa_tl {knot strand #1}
   \group_end:
   \endpgfscope
@@ -303,11 +322,15 @@
     \spath_finalpoint:Nv \l__knot_tmpb_tl {knot strand #1}
     \dim_set:Nn \l__knot_tmpa_dim {\tl_item:Nn \l__knot_tmpb_tl {1}}
     \dim_set:Nn \l__knot_tmpb_dim {\tl_item:Nn \l__knot_tmpb_tl {2}}
-    \node[knot~ diagram/draft/strand~label] at (\l__knot_tmpa_dim,\l__knot_tmpb_dim) {#1};
+    \node[
+      knot~ diagram/draft/strand~label
+    ] at (\l__knot_tmpa_dim,\l__knot_tmpb_dim) {#1};
     \spath_initialpoint:Nv \l__knot_tmpb_tl {knot strand #1}
     \dim_set:Nn \l__knot_tmpa_dim {\tl_item:Nn \l__knot_tmpb_tl {1}}
     \dim_set:Nn \l__knot_tmpb_dim {\tl_item:Nn \l__knot_tmpb_tl {2}}
-    \node[knot~ diagram/draft/strand~label] at (\l__knot_tmpa_dim,\l__knot_tmpb_dim) {#1};
+    \node[
+      knot~ diagram/draft/strand~label
+    ] at (\l__knot_tmpa_dim,\l__knot_tmpb_dim) {#1};
   }
   \bool_if:nT {
     \l__knot_self_intersections_bool
@@ -316,6 +339,8 @@
   }
   {
     \tl_clear:N \l__knot_tmpa_tl
+    \spath_initialpoint:Nv \l__knot_tmpa_tl {knot strand #1}
+    \tl_put_left:NV \l__knot_tmpa_tl \c_spath_moveto_tl
     \spath_segments_to_seq:Nv \l__knot_segments_seq {knot strand #1}
     \seq_map_function:NN \l__knot_segments_seq \knot_split_self_intersects:N
     \tl_set_eq:cN {knot strand #1} \l__knot_tmpa_tl
@@ -330,23 +355,29 @@
     {
       \fp_set:Nn \l__knot_tmpa_fp
       {
-        (\tl_item:nn {#1} {3} - 3 * \tl_item:nn {#1} {6} + 3 * \tl_item:nn {#1} {9} - \tl_item:nn {#1} {12})
+        (\tl_item:nn {#1} {3} - 3 * \tl_item:nn {#1} {6}
+        + 3 * \tl_item:nn {#1} {9} - \tl_item:nn {#1} {12})
         *
         (3 * \tl_item:nn {#1} {8} - 3 * \tl_item:nn {#1} {11})
         -
-        (\tl_item:nn {#1} {2} - 3 * \tl_item:nn {#1} {5} + 3 * \tl_item:nn {#1} {8} - \tl_item:nn {#1} {11})
+        (\tl_item:nn {#1} {2} - 3 * \tl_item:nn {#1} {5}
+        + 3 * \tl_item:nn {#1} {8} - \tl_item:nn {#1} {11})
         *
         (3 * \tl_item:nn {#1} {9} - 3 * \tl_item:nn {#1} {12})
       }
       \fp_set:Nn \l__knot_tmpb_fp
       {
-        (\tl_item:nn {#1} {2} - 3 * \tl_item:nn {#1} {5} + 3 * \tl_item:nn {#1} {8} - \tl_item:nn {#1} {11})
+        (\tl_item:nn {#1} {2} - 3 * \tl_item:nn {#1} {5}
+        + 3 * \tl_item:nn {#1} {8} - \tl_item:nn {#1} {11})
         *
-        (3 * \tl_item:nn {#1} {6} - 6 * \tl_item:nn {#1} {9} + 3 * \tl_item:nn {#1} {12})
+        (3 * \tl_item:nn {#1} {6} - 6 * \tl_item:nn {#1} {9}
+        + 3 * \tl_item:nn {#1} {12})
         -
-        (\tl_item:nn {#1} {3} - 3 * \tl_item:nn {#1} {6} + 3 * \tl_item:nn {#1} {9} - \tl_item:nn {#1} {12})
+        (\tl_item:nn {#1} {3} - 3 * \tl_item:nn {#1} {6}
+        + 3 * \tl_item:nn {#1} {9} - \tl_item:nn {#1} {12})
         *
-        (3 * \tl_item:nn {#1} {5} - 6 * \tl_item:nn {#1} {8} + 3 * \tl_item:nn {#1} {11})
+        (3 * \tl_item:nn {#1} {5} - 6 * \tl_item:nn {#1} {8}
+        + 3 * \tl_item:nn {#1} {11})
       }
       \fp_compare:nTF
       {
@@ -359,7 +390,11 @@
           0 < \l__knot_tmpa_fp && \l__knot_tmpa_fp < 1
         }
         {
-          \spath_split_curve:NNnV \l__knot_tmpc_tl \l__knot_tmpd_tl {#1} \l__knot_tmpa_fp
+          \spath_split_curve:NNnV
+          \l__knot_tmpc_tl
+          \l__knot_tmpd_tl
+          {#1}
+          \l__knot_tmpa_fp
           \tl_set:Nx \l__knot_tmpc_tl {\tl_tail:N \l__knot_tmpc_tl}
           \tl_set:Nx \l__knot_tmpc_tl {\tl_tail:N \l__knot_tmpc_tl}
           \tl_set:Nx \l__knot_tmpc_tl {\tl_tail:N \l__knot_tmpc_tl}
@@ -411,19 +446,33 @@
   \bool_if:nTF {
     \l__knot_save_bool
     &&
-    \tl_if_exist_p:c {knot~ intersections~ \tl_use:N \l__knot_name_tl - \tl_use:N \l__knot_tmpa_tl -  \tl_use:N \l__knot_tmpb_tl}
+    \tl_if_exist_p:c {
+      knot~ intersections~
+      \tl_use:N \l__knot_name_tl -
+      \tl_use:N \l__knot_tmpa_tl -
+      \tl_use:N \l__knot_tmpb_tl
+    }
   }
   {
-    \tl_use:c {knot~ intersections~ \tl_use:N \l__knot_name_tl - \tl_use:N \l__knot_tmpa_tl -  \tl_use:N \l__knot_tmpb_tl}
+    \tl_use:c
+    {
+      knot~ intersections~ \tl_use:N \l__knot_name_tl -
+      \tl_use:N \l__knot_tmpa_tl -
+      \tl_use:N \l__knot_tmpb_tl
+    }
   }
   {
-\pgfintersectionofpaths{\pgfsetpath\l__knot_tmpc_tl}{\pgfsetpath\l__knot_tmpd_tl}
+    \pgfintersectionofpaths{\pgfsetpath\l__knot_tmpc_tl}{\pgfsetpath\l__knot_tmpd_tl}
 
   }
 
   \int_compare:nT {\pgfintersectionsolutions > 0}
   {
-    \int_step_function:nnnN {1} {1} {\pgfintersectionsolutions} \knot_do_intersection:n
+    \int_step_function:nnnN
+    {1}
+    {1}
+    {\pgfintersectionsolutions}
+    \knot_do_intersection:n
   }
 
   \knot_save_intersections:VV \l__knot_tmpa_tl \l__knot_tmpb_tl
@@ -455,7 +504,16 @@
         }
         \tl_put_right:Nx \l__knot_aux_tl
         {
-          {\exp_not:N \pgf at x=\dim_use:N \l__knot_tmpa_dim\exp_not:N\relax\exp_not:N \pgf at y =\dim_use:N \l__knot_tmpb_dim\relax}
+          {
+            \exp_not:N \pgf at x
+            =
+            \dim_use:N \l__knot_tmpa_dim
+            \exp_not:N \relax
+            \exp_not:N \pgf at y
+            =
+            \dim_use:N \l__knot_tmpb_dim
+            \exp_not:N \relax
+          }
         }
       }
       \tl_set:Nn \l__knot_auxa_tl {\expandafter \gdef \csname knot~ intersections~}
@@ -480,7 +538,7 @@
     \tl_set:Nv \l__knot_tmpc_tl \l__knot_tmpc_tl
     \tl_if_eq:NNT \l__knot_tmpc_tl \l__knot_tmpb_tl
     {
-      \knot_test_endpoint:VnT \l__knot_tmpb_tl {final point}
+      \knot_test_endpoint:NVnT \l__knot_tolerance_dim \l__knot_tmpb_tl {final point}
       {
         \bool_set_true:N \l__knot_skip_bool
       }
@@ -491,7 +549,7 @@
     \tl_set:Nv \l__knot_tmpc_tl \l__knot_tmpc_tl
     \tl_if_eq:NNT \l__knot_tmpc_tl \l__knot_tmpa_tl
     {
-      \knot_test_endpoint:VnT \l__knot_tmpa_tl {final point}
+      \knot_test_endpoint:NVnT \l__knot_tolerance_dim \l__knot_tmpa_tl {final point}
       {
         \bool_set_true:N \l__knot_skip_bool
       }
@@ -499,19 +557,19 @@
   }
   \bool_if:NT \l__knot_ignore_ends_bool
   {
-    \knot_test_endpoint:VnT \l__knot_tmpa_tl {initial point}
+    \knot_test_endpoint:NVnT \l__knot_tolerance_dim \l__knot_tmpa_tl {initial point}
     {
       \bool_set_true:N \l__knot_skip_bool
     }
-    \knot_test_endpoint:VnT \l__knot_tmpa_tl {final point}
+    \knot_test_endpoint:NVnT \l__knot_tolerance_dim \l__knot_tmpa_tl {final point}
     {
       \bool_set_true:N \l__knot_skip_bool
     }
-    \knot_test_endpoint:VnT \l__knot_tmpb_tl {initial point}
+    \knot_test_endpoint:NVnT \l__knot_tolerance_dim \l__knot_tmpb_tl {initial point}
     {
       \bool_set_true:N \l__knot_skip_bool
     }
-    \knot_test_endpoint:VnT \l__knot_tmpb_tl {final point}
+    \knot_test_endpoint:NVnT \l__knot_tolerance_dim \l__knot_tmpb_tl {final point}
     {
       \bool_set_true:N \l__knot_skip_bool
     }
@@ -545,7 +603,8 @@
       }
       \bool_if:NT \l__knot_self_intersections_bool
       {
-        \knot_test_endpoint:VnT \l__knot_tmpg_tl {initial point}
+        \knot_test_endpoint:NVnT
+        \l__knot_redraw_tolerance_dim \l__knot_tmpg_tl {initial point}
         {
           \bool_set_true:N \l__knot_prepend_prev_bool
         }
@@ -552,7 +611,8 @@
         {
           \bool_set_false:N \l__knot_prepend_prev_bool
         }
-        \knot_test_endpoint:VnT \l__knot_tmpg_tl {final point}
+        \knot_test_endpoint:NVnT
+        \l__knot_redraw_tolerance_dim \l__knot_tmpg_tl {final point}
         {
           \bool_set_true:N \l__knot_append_next_bool
         }
@@ -565,10 +625,14 @@
         }
         {
           \tl_clear_new:c {knot \tl_use:N \l__knot_prefix_tl -1}
-          \tl_set_eq:cc {knot \tl_use:N \l__knot_prefix_tl -1} {knot \tl_use:N \l__knot_tmpg_tl}
+          \tl_set_eq:cc
+          {knot \tl_use:N \l__knot_prefix_tl -1}
+          {knot \tl_use:N \l__knot_tmpg_tl}
 
           \tl_clear_new:c {l__knot_options_ \tl_use:N \l__knot_prefix_tl -1}
-          \tl_set_eq:cc {l__knot_options_ \tl_use:N \l__knot_prefix_tl -1} {l__knot_options_ \tl_use:N \l__knot_tmpg_tl}
+          \tl_set_eq:cc
+          {l__knot_options_ \tl_use:N \l__knot_prefix_tl -1}
+          {l__knot_options_ \tl_use:N \l__knot_tmpg_tl}
 
           \bool_if:nT
           {
@@ -579,7 +643,9 @@
             !\tl_if_empty_p:c {knot previous \tl_use:N \l__knot_tmpg_tl}
           }
           {
-            \spath_prepend_no_move:cv {knot \tl_use:N \l__knot_prefix_tl -1} {knot \tl_use:c {knot previous \tl_use:N \l__knot_tmpg_tl}}
+            \spath_prepend_no_move:cv
+            {knot \tl_use:N \l__knot_prefix_tl -1}
+            {knot \tl_use:c {knot previous \tl_use:N \l__knot_tmpg_tl}}
             \bool_if:nT
             {
               \l__knot_splits_bool
@@ -589,10 +655,18 @@
               !\tl_if_empty_p:c {knot previous \tl_use:N \l__knot_tmpg_tl}
             }
             {
-              \knot_test_endpoint:vnT {knot previous \tl_use:N \l__knot_tmpg_tl} {initial point}
+              \knot_test_endpoint:NvnT
+              \l__knot_redraw_tolerance_dim
+              {knot previous \tl_use:N \l__knot_tmpg_tl}
+              {initial point}
               {
-
-                \spath_prepend_no_move:cv {knot \tl_use:N \l__knot_prefix_tl -1} {knot \tl_use:c {knot previous \tl_use:c {knot previous \tl_use:N \l__knot_tmpg_tl}}}
+                \spath_prepend_no_move:cv
+                {knot \tl_use:N \l__knot_prefix_tl -1}
+                {knot \tl_use:c
+                  {knot previous \tl_use:c
+                    {knot previous \tl_use:N \l__knot_tmpg_tl}
+                  }
+                }
                 \tl_set_eq:Nc \l__knot_tmpa_tl {knot \tl_use:N \l__knot_prefix_tl -1}
               }
             }
@@ -606,7 +680,9 @@
             !\tl_if_empty_p:c {knot previous \tl_use:N \l__knot_tmpg_tl}
           }
           {
-            \spath_append_no_move:cv {knot \tl_use:N \l__knot_prefix_tl -1} {knot \tl_use:c {knot next \tl_use:N \l__knot_tmpg_tl}}
+            \spath_append_no_move:cv
+            {knot \tl_use:N \l__knot_prefix_tl -1}
+            {knot \tl_use:c {knot next \tl_use:N \l__knot_tmpg_tl}}
             \bool_if:nT
             {
               \l__knot_splits_bool
@@ -617,42 +693,61 @@
               !\tl_if_empty_p:c {knot previous \tl_use:N \l__knot_tmpg_tl}
             }
             {
-              \knot_test_endpoint:vnT {knot previous \tl_use:N \l__knot_tmpg_tl} {final point}
+              \knot_test_endpoint:NvnT
+              \l__knot_redraw_tolerance_dim
+              {knot previous \tl_use:N \l__knot_tmpg_tl}
+              {final point}
               {
-                \spath_append_no_move:cv {knot \tl_use:N \l__knot_prefix_tl -1} {knot \tl_use:c {knot next \tl_use:c {knot next \tl_use:N \l__knot_tmpg_tl}}}
-
+                \spath_append_no_move:cv
+                {knot \tl_use:N \l__knot_prefix_tl -1}
+                {knot \tl_use:c
+                  {knot next \tl_use:c
+                    {knot next \tl_use:N \l__knot_tmpg_tl}
+                  }
+                }
               }
             }
           }
-
           \tl_set:Nn \l__knot_tmpg_tl {\tl_use:N \l__knot_prefix_tl -1}
         }
       }
       \pgfscope
       \group_begin:
-      \tikzset{knot~ diagram/every~ intersection/.try, every~ intersection/.try, knot~ diagram/intersection~ \int_use:N \g__knot_intersections_int/.try}
+      \tikzset{
+        knot~ diagram/every~ intersection/.try,
+        every~ intersection/.try,
+        knot~ diagram/intersection~ \int_use:N \g__knot_intersections_int/.try
+      }
       \knot_draw_crossing:VVV \l__knot_tmpg_tl \l__knot_tmpa_dim \l__knot_tmpb_dim
-      \coordinate (\l__knot_name_tl \c_space_tl \int_use:N \g__knot_intersections_int) at (\dim_use:N \l__knot_tmpa_dim, \dim_use:N \l__knot_tmpb_dim);
+      \coordinate
+      (\l__knot_name_tl \c_space_tl \int_use:N \g__knot_intersections_int)
+      at (\dim_use:N \l__knot_tmpa_dim, \dim_use:N \l__knot_tmpb_dim);
       \group_end:
       \endpgfscope
     }
     \tl_if_empty:NF \l__knot_node_tl
     {
-      \seq_gpush:Nx \g__knot_nodes_seq { \l__knot_node_tl at (\dim_use:N \l__knot_tmpa_dim, \dim_use:N \l__knot_tmpb_dim) {};}
+      \seq_gpush:Nx
+      \g__knot_nodes_seq
+      {
+        \l__knot_node_tl
+        at
+        (\dim_use:N \l__knot_tmpa_dim, \dim_use:N \l__knot_tmpb_dim) {};
+      }
     }
   }
 }
 
 \cs_generate_variant:Nn \knot_intersections:nn {VV}
-\prg_new_conditional:Npnn \knot_test_endpoint:N #1 {p,T,F,TF}
+\prg_new_conditional:Npnn \knot_test_endpoint:NN #1#2 {p,T,F,TF}
 {
   \dim_compare:nTF
   {
-    \dim_abs:n { \l__knot_tmpa_dim - \tl_item:Nn #1 {1}}
+    \dim_abs:n { \l__knot_tmpa_dim - \tl_item:Nn #2 {1}}
     +
-    \dim_abs:n { \l__knot_tmpb_dim - \tl_item:Nn #1 {2}}
+    \dim_abs:n { \l__knot_tmpb_dim - \tl_item:Nn #2 {2}}
     <
-    \l__knot_tolerance_dim
+    #1
   }
   {
     \prg_return_true:
@@ -661,10 +756,10 @@
     \prg_return_false:
   }
 }
-\prg_new_protected_conditional:Npnn \knot_test_endpoint:nn #1#2 {T,F,TF}
+\prg_new_protected_conditional:Npnn \knot_test_endpoint:Nnn #1#2#3 {T,F,TF}
 {
-  \use:c {spath_#2:Nv} \l__knot_tmpd_tl {knot #1}
-  \knot_test_endpoint:NTF \l__knot_tmpd_tl
+  \use:c {spath_#3:Nv} \l__knot_tmpd_tl {knot #2}
+  \knot_test_endpoint:NNTF #1 \l__knot_tmpd_tl
   {
     \prg_return_true:
   }
@@ -673,14 +768,15 @@
   }
 }
 
-\cs_generate_variant:Nn \knot_test_endpoint:nnT {VnT,vnT}
-\cs_generate_variant:Nn \knot_test_endpoint:nnF {VnF,vnF}
-\cs_generate_variant:Nn \knot_test_endpoint:nnTF {VnTF,vnTF}
+\cs_generate_variant:Nn \knot_test_endpoint:NnnT {NVnT,NvnT}
+\cs_generate_variant:Nn \knot_test_endpoint:NnnF {NVnF,NvnF}
+\cs_generate_variant:Nn \knot_test_endpoint:NnnTF {NVnTF,NvnTF}
 \cs_new_protected_nopar:Npn \knot_draw_crossing:nnn #1#2#3
 {
   \group_begin:
   \pgfscope
-  \path[knot~ diagram/background~ clip] (#2, #3) circle[radius=\l__knot_clip_bg_radius_dim];
+  \path[knot~ diagram/background~ clip] (#2, #3)
+  circle[radius=\l__knot_clip_bg_radius_dim];
 
   \tl_set:Nn \l__knot_tmpa_tl {knot~ diagram/every~ strand/.try,}
   \tl_if_exist:cT {l__knot_options_ #1}
@@ -687,13 +783,18 @@
   {
   \tl_put_right:Nv \l__knot_tmpa_tl {l__knot_options_ #1}
   }
-  \tl_put_right:Nn \l__knot_tmpa_tl {,knotbg,line~ width= \tl_use:N \l__knot_clip_width_tl * \pgflinewidth}
+  \tl_put_right:Nn \l__knot_tmpa_tl
+  {
+    ,knotbg
+    ,line~ width= \tl_use:N \l__knot_clip_width_tl * \pgflinewidth
+  }
   \spath_tikz_path:Vv \l__knot_tmpa_tl {knot #1}
 
   \endpgfscope
 
   \pgfscope
-  \path[knot~ diagram/clip] (#2, #3) circle[radius=\l__knot_clip_draw_radius_dim];
+  \path[knot~ diagram/clip] (#2, #3)
+  circle[radius=\l__knot_clip_draw_radius_dim];
 
   \tl_set:Nn \l__knot_tmpa_tl {knot~ diagram/every~ strand/.try,}
   \tl_if_exist:cT {l__knot_options_ #1}
@@ -700,7 +801,11 @@
   {
   \tl_put_right:Nv \l__knot_tmpa_tl {l__knot_options_ #1}
   }
-  \tl_put_right:Nn \l__knot_tmpa_tl {,knot~ diagram/only~ when~ rendering/.try,only~ when~ rendering/.try}
+  \tl_put_right:Nn \l__knot_tmpa_tl
+  {
+    ,knot~ diagram/only~ when~ rendering/.try
+    ,only~ when~ rendering/.try
+  }
   \spath_tikz_path:Vv \l__knot_tmpa_tl {knot #1}
 
   \endpgfscope
@@ -752,12 +857,14 @@
       \tl_set:cn {knot filament \int_use:N \g__knot_filaments_int} {#1}
 
       \tl_clear_new:c {l__knot_options_filament \int_use:N \g__knot_filaments_int}
-      \tl_set_eq:cN {l__knot_options_filament \int_use:N \g__knot_filaments_int} \l__knot_tmpa_tl
+      \tl_set_eq:cN {l__knot_options_filament \int_use:N \g__knot_filaments_int}
+      \l__knot_tmpa_tl
 
       \tl_clear_new:c {knot previous filament \int_use:N \g__knot_filaments_int}
       \int_compare:nF {\l__knot_component_start_int == \g__knot_filaments_int}
       {
-        \tl_set:cx {knot previous filament \int_use:N \g__knot_filaments_int} {filament \int_eval:n {\g__knot_filaments_int - 1}}
+        \tl_set:cx {knot previous filament \int_use:N \g__knot_filaments_int}
+        {filament \int_eval:n {\g__knot_filaments_int - 1}}
       }
     }
     \c_spath_curvetoa_tl
@@ -766,12 +873,15 @@
       \tl_clear_new:c {knot filament \int_use:N \g__knot_filaments_int}
       \tl_set:cn {knot filament \int_use:N \g__knot_filaments_int} {#1}
       \tl_clear_new:c {l__knot_options_filament \int_use:N \g__knot_filaments_int}
-      \tl_set_eq:cN {l__knot_options_filament \int_use:N \g__knot_filaments_int} \l__knot_tmpa_tl
+      \tl_set_eq:cN {l__knot_options_filament \int_use:N \g__knot_filaments_int}
+      \l__knot_tmpa_tl
 
       \tl_clear_new:c {knot previous filament \int_use:N \g__knot_filaments_int}
       \int_compare:nF {\l__knot_component_start_int == \g__knot_filaments_int}
       {
-        \tl_set:cx {knot previous filament \int_use:N \g__knot_filaments_int} {filament \int_eval:n {\g__knot_filaments_int - 1}}
+        \tl_set:cx
+        {knot previous filament \int_use:N \g__knot_filaments_int}
+        {filament \int_eval:n {\g__knot_filaments_int - 1}}
       }
     }
     \c_spath_closepath_tl
@@ -779,18 +889,26 @@
       \int_gincr:N \g__knot_filaments_int
       \tl_clear_new:c {knot filament \int_use:N \g__knot_filaments_int}
       \tl_clear:N \l__knot_tmpa_tl
-      \tl_put_right:Nx {\tl_item:nn {#1} {1}\tl_item:nn {#1} {2}\tl_item:nn {#1} {3}}
+      \tl_put_right:Nx
+      {
+        \tl_item:nn {#1} {1}\tl_item:nn {#1} {2}\tl_item:nn {#1} {3}
+      }
       \tl_put_right:NV \l__knot_tmpa_tl \c_spath_lineto_tl
       \tl_put_right:Nx {\tl_item:nn {#1} {5}\tl_item:nn {#1} {6}}
 
       \tl_set:cV {knot filament \int_use:N \g__knot_filaments_int} \l__knot_tmpa_tl
-      \tl_set_eq:cN {l__knot_options_filament \int_use:N \g__knot_filaments_int} \l__knot_tmpa_tl
+      \tl_set_eq:cN {l__knot_options_filament \int_use:N \g__knot_filaments_int}
+      \l__knot_tmpa_tl
       \tl_clear_new:c {knot previous filament \int_use:N \g__knot_filaments_int}
       \int_compare:nF {\l__knot_component_start_int == \g__knot_filaments_int}
       {
-        \tl_set:cx {knot previous filament \int_use:N \g__knot_filaments_int} {filament \int_eval:n {\g__knot_filaments_int - 1}}
+        \tl_set:cx
+        {knot previous filament \int_use:N \g__knot_filaments_int}
+        {filament \int_eval:n {\g__knot_filaments_int - 1}}
       }
-      \tl_set:cx {knot previous filament \int_use:N \l__knot_component_start_int} {filament \int_use:N \g__knot_filaments_int}
+      \tl_set:cx
+      {knot previous filament \int_use:N \l__knot_component_start_int}
+      {filament \int_use:N \g__knot_filaments_int}
     }
   }
   {
@@ -1008,7 +1126,7 @@
  }
 }
 %% 
-%% Copyright (C) 2011-2019 by Andrew Stacey <loopspace at mathforge.org>
+%% Copyright (C) 2011-2021 by Andrew Stacey <loopspace at mathforge.org>
 %% 
 %% This work may be distributed and/or modified under the
 %% conditions of the LaTeX Project Public License (LPPL), either
@@ -1020,7 +1138,7 @@
 %% This work is "maintained" (as per LPPL maintenance status) by
 %% Andrew Stacey.
 %% 
-%% This work consists of the files  spath3.dtx
+%% This work consists of the files  spath3_code.dtx
 %%                                  calligraphy_doc.tex
 %%                                  knots_doc.tex
 %%                                  spath3.tex

Modified: trunk/Master/texmf-dist/tex/latex/spath3/tikzlibraryspath3.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/spath3/tikzlibraryspath3.code.tex	2021-02-06 22:28:55 UTC (rev 57638)
+++ trunk/Master/texmf-dist/tex/latex/spath3/tikzlibraryspath3.code.tex	2021-02-06 22:29:38 UTC (rev 57639)
@@ -24,6 +24,8 @@
 \seq_new:N \g__spath_tmpa_seq
 \seq_new:N \g__spath_tmpb_seq
 \bool_new:N \l__spath_draft_bool
+\msg_new:nnn { spath3 } { missing soft path } { Soft~ path~ #1~ doesn't~ exist }
+\msg_new:nnn { spath3 } { empty soft path } { Soft~ path~ #1~ is~ empty }
 \tl_set:Nn \l__spath_prefix_tl {tikz at intersect@path at name@}
 \tl_set:Nn \l__spath_suffix_tl {}
 \tl_new:N \g__spath_tikzfinish_tl
@@ -53,6 +55,20 @@
   }
 }
 \cs_generate_variant:Nn \spath_gsave_path:Nn {cn, NV, cV}
+\cs_new_protected_nopar:Npn \__spath_process_tikz_point:Nn #1#2
+{
+  \group_begin:
+  \use:c {tikz at scan@one at point} \use:n #2 \scan_stop:
+  \tl_gset:Nx \g__spath_output_tl
+  {
+    { \dim_use:c {pgf at x} }
+    { \dim_use:c {pgf at y} }
+  }
+  \group_end:
+  \tl_set_eq:NN #1 \g__spath_output_tl
+  \tl_gclear:N \g__spath_output_tl
+}
+\cs_set_eq:NN \getComponentOf \clist_item:Nn
 \tikzset{
   spath/.is~family,
   spath/.cd,
@@ -74,11 +90,14 @@
     \tikz at addmode{
       \spath_get_current_path:N \l__spath_tmpa_tl
       \spath_bake_round:NV \l__spath_tmpa_tl \l__spath_tmpa_tl
-      \spath_save_path:cV {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} \l__spath_tmpa_tl
+      \spath_save_path:cV
+      {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+      \l__spath_tmpa_tl
     }
   },
   clone/.code~ 2~ args={
-    \tl_if_exist:cT {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl}
     {
       \tl_clear_new:c
       {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
@@ -86,9 +105,13 @@
       {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
       {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl}
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #2 }
+    }
   },
   clone~ global/.code~ 2~ args={
-    \tl_if_exist:cT {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl}
     {
       \tl_gclear_new:c
       {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
@@ -96,6 +119,9 @@
       {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
       {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl}
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #2 }
+    }
   },
   save~ global/.code={
     \tikz at addmode{
@@ -107,20 +133,76 @@
     }
   },
   save~ to~ aux/.code={
-    \tl_if_exist:cT {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     {
       \spath_save_to_aux:c
       {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
   restore/.code={
-    \tl_if_exist:cT {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     {
-      \spath_set_current_path:c
+      \tl_if_empty:cTF
       {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
-      \spath_set_tikz_coords:v
+      {
+        \tl_clear:N \l__spath_tmpa_tl
+        \tl_put_right:NV \l__spath_tmpa_tl \c_spath_moveto_tl
+        \tl_put_right:Nn \l__spath_tmpa_tl {{0pt}{0pt}}
+        \spath_set_current_path:V \l__spath_tmpa_tl
+        \spath_set_tikz_data:V \l__spath_tmpa_tl
+        \msg_warning:nnn { spath3 } { empty soft path } { #1 }
+      }
+      {
+        \spath_set_current_path:c
+        {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+        \spath_set_tikz_data:v
+        {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+      }
+    }
+    {
+      \tl_clear:N \l__spath_tmpa_tl
+      \tl_put_right:NV \l__spath_tmpa_tl \c_spath_moveto_tl
+      \tl_put_right:Nn \l__spath_tmpa_tl {{0pt}{0pt}}
+      \spath_set_current_path:V \l__spath_tmpa_tl
+      \spath_set_tikz_data:V \l__spath_tmpa_tl
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+  restore~ reverse/.code={
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \tl_if_empty:cTF
       {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+      {
+        \tl_clear:N \l__spath_tmpa_tl
+        \tl_put_right:NV \l__spath_tmpa_tl \c_spath_moveto_tl
+        \tl_put_right:Nn \l__spath_tmpa_tl {{0pt}{0pt}}
+        \spath_set_current_path:V \l__spath_tmpa_tl
+        \spath_set_tikz_data:V \l__spath_tmpa_tl
+        \msg_warning:nnn { spath3 } { empty soft path } { #1 }
+      }
+      {
+        \spath_reverse:Nv
+        \l__spath_reverse_tl
+        {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+        \spath_set_current_path:N \l__spath_reverse_tl
+        \spath_set_tikz_data:V \l__spath_reverse_tl
+      }
     }
+    {
+      \tl_clear:N \l__spath_tmpa_tl
+      \tl_put_right:NV \l__spath_tmpa_tl \c_spath_moveto_tl
+      \tl_put_right:Nn \l__spath_tmpa_tl {{0pt}{0pt}}
+      \spath_set_current_path:V \l__spath_tmpa_tl
+      \spath_set_tikz_data:V \l__spath_tmpa_tl
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
   show~current~path/.code={
     \tikz at addmode{
@@ -130,62 +212,126 @@
     }
   },
   show/.code={
-    \tl_if_exist:cT {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     {
-      \iow_term:n {---~ soft~ path~ #1~ ---}
-      \spath_show:v {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+      \tl_if_empty:cTF
+      {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+      {
+        \msg_warning:nnn { spath3 } { empty soft path } { #1 }
+      }
+      {
+        \iow_term:n {---~ soft~ path~ #1~ ---}
+        \spath_show:v
+        {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+      }
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
   append/.code={
-    \tl_if_exist:cT {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     {
       \spath_get_current_path:N \l__spath_current_tl
-      \spath_weld:Nv
-      \l__spath_current_tl
+      \spath_finalpoint:NV \l__spath_tmpa_tl \l__spath_current_tl
+      \tl_set_eq:Nc
+      \l__spath_tmpb_tl
       {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+      \spath_translate_to:NV \l__spath_tmpb_tl \l__spath_tmpa_tl
+      \spath_append_no_move:NV \l__spath_current_tl \l__spath_tmpb_tl
       \spath_set_current_path:N \l__spath_current_tl
-      \spath_set_tikz_coords:V \l__spath_current_tl
+      \spath_set_tikz_data:V \l__spath_tmpb_tl
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
   join~ with/.code~ 2~ args={
-    \tl_if_exist:cT {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     {
-      \tl_if_exist:cT {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl}
+      \tl_if_exist:cTF
+      {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl}
       {
         \spath_append:cv
         {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
         {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl}
       }
+      {
+        \msg_warning:nnn { spath3 } { missing soft path } { #2 }
+      }
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
   spot~ weld/.code={
-    \tl_if_exist:cT {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     {
       \spath_spot_weld_components:c
       {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
+  spot~ weld~ globally/.code={
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \spath_spot_gweld_components:c
+      {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
   reverse/.code={
-    \tl_if_exist:cT {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     {
       \spath_reverse:c
       {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
+  reverse~ globally/.code={
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \spath_reverse:c
+      {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
   append~ reverse/.code={
-    \tl_if_exist:cT {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     {
       \spath_reverse:Nv
       \l__spath_reverse_tl
       {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
       \spath_get_current_path:N \l__spath_current_tl
-      \spath_weld:NV \l__spath_current_tl \l__spath_reverse_tl
+      \spath_finalpoint:NV \l__spath_tmpa_tl \l__spath_current_tl
+      \spath_translate_to:NV \l__spath_reverse_tl \l__spath_tmpa_tl
+      \spath_append_no_move:NV \l__spath_current_tl \l__spath_reverse_tl
       \spath_set_current_path:N \l__spath_current_tl
-      \spath_set_tikz_coords:V \l__spath_current_tl
+      \spath_set_tikz_data:V \l__spath_reverse_tl
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
   insert/.code={
-    \tl_if_exist:cT {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     {
       \spath_get_current_path:N \l__spath_current_tl
       \spath_append:Nv
@@ -192,11 +338,16 @@
       \l__spath_current_tl
       {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
       \spath_set_current_path:N \l__spath_current_tl
-      \spath_set_tikz_coords:V \l__spath_current_tl
+      \spath_set_tikz_data:v
+      {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
   insert~ reverse/.code={
-    \tl_if_exist:cT {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     {
       \spath_reverse:Nv
       \l__spath_reverse_tl
@@ -204,25 +355,288 @@
       \spath_get_current_path:N \l__spath_current_tl
       \spath_append:NV \l__spath_current_tl \l__spath_reverse_tl
       \spath_set_current_path:N \l__spath_current_tl
-      \spath_set_tikz_coords:V \l__spath_current_tl
+      \spath_set_tikz_data:V \l__spath_reverse_tl
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
+  append~ no~ move/.code={
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \spath_get_current_path:N \l__spath_current_tl
+      \spath_append_no_move:Nv
+      \l__spath_current_tl
+      {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+      \spath_set_current_path:N \l__spath_current_tl
+      \spath_set_tikz_data:v
+      {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+  append~ reverse~ no~ move/.code={
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \spath_reverse:Nv
+      \l__spath_reverse_tl
+      {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+      \spath_get_current_path:N \l__spath_current_tl
+      \spath_append_no_move:NV \l__spath_current_tl \l__spath_reverse_tl
+      \spath_set_current_path:N \l__spath_current_tl
+      \spath_set_tikz_data:V \l__spath_reverse_tl
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+  span/.code ~n~ args={3}{
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \__spath_process_tikz_point:Nn \l__spath_tmpa_tl {#2}
+      \__spath_process_tikz_point:Nn \l__spath_tmpb_tl {#3}
+      \spath_span:cVV
+      {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+      \l__spath_tmpa_tl \l__spath_tmpb_tl
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+  span~ global/.code ~n~ args={3}{
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \__spath_process_tikz_point:Nn \l__spath_tmpa_tl {#2}
+      \__spath_process_tikz_point:Nn \l__spath_tmpb_tl {#3}
+      \spath_gspan:cVV
+      {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+      \l__spath_tmpa_tl \l__spath_tmpb_tl
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+  to/.style={
+    to~path={
+      [
+        spath/span={#1}{(\tikztostart)}{(\tikztotarget)},
+        spath/append~no~move={#1},
+      ]
+      \tikztonodes
+    }
+  },
+  splice/.code ~n~ args={3}{
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \tl_if_exist:cTF
+      {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl}
+      {
+        \tl_if_exist:cTF
+        {\tl_use:N \l__spath_prefix_tl #3 \tl_use:N \l__spath_suffix_tl}
+        {
+          \spath_splice_between:cvv
+          {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+          {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl}
+          {\tl_use:N \l__spath_prefix_tl #3 \tl_use:N \l__spath_suffix_tl}
+        }
+        {
+          \msg_warning:nnn { spath3 } { missing soft path } { #3 }
+        }
+      }
+      {
+        \msg_warning:nnn { spath3 } { missing soft path } { #2 }
+      }
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+  splice~ global/.code ~n~ args={3}{
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \tl_if_exist:cTF
+      {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl}
+      {
+        \tl_if_exist:cTF
+        {\tl_use:N \l__spath_prefix_tl #3 \tl_use:N \l__spath_suffix_tl}
+        {
+          \spath_gsplice_between:cvv
+          {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+          {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl}
+          {\tl_use:N \l__spath_prefix_tl #3 \tl_use:N \l__spath_suffix_tl}
+        }
+        {
+          \msg_warning:nnn { spath3 } { missing soft path } { #3 }
+        }
+      }
+      {
+        \msg_warning:nnn { spath3 } { missing soft path } { #2 }
+      }
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+  join~ components~ with/.code~2~args={
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \tl_if_exist:cTF
+      {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl}
+      {
+        \spath_spot_weld_components:c
+        {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+
+        \spath_components_to_seq:Nv
+        \l__spath_tmpa_seq
+        {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+
+        \seq_pop_left:NN \l__spath_tmpa_seq \l__spath_tmpa_tl
+
+        \seq_map_inline:Nn \l__spath_tmpa_seq
+        {
+          \spath_splice_between:Nvn \l__spath_tmpa_tl
+          {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl}
+          {##1}
+        }
+        \tl_set_eq:cN
+        {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+        \l__spath_tmpa_tl
+      }
+      {
+        \msg_warning:nnn { spath3 } { missing soft path } { #2 }
+      }
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+  join~ components~ globally~ with/.code~2~args={
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \tl_if_exist:cTF
+      {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl}
+      {
+        \spath_spot_gweld_components:c
+        {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+
+        \spath_components_to_seq:Nv
+        \l__spath_tmpa_seq
+        {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+
+        \seq_pop_left:NN \l__spath_tmpa_seq \l__spath_tmpa_tl
+
+        \seq_map_inline:Nn \l__spath_tmpa_seq
+        {
+          \spath_gsplice_between:Nvn \l__spath_tmpa_tl
+          {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl}
+          {##1}
+        }
+        \tl_set_eq:cN
+        {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+        \l__spath_tmpa_tl
+      }
+      {
+        \msg_warning:nnn { spath3 } { missing soft path } { #2 }
+      }
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+  close/.code={
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \spath_close:c
+      {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+  close~ globally/.code={
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \spath_gclose:c
+      {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+  close~ with/.code~ 2~ args={
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \tl_if_exist:cTF
+      {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl}
+      {
+        \spath_close_with:cv
+        {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+        {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl}
+      }
+      {
+        \msg_warning:nnn { spath3 } { missing soft path } { #2 }
+      }
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+  close~ globally~ with/.code~ 2~ args={
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \tl_if_exist:cTF
+      {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl}
+      {
+        \spath_gclose_with:cv
+        {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+        {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl}
+      }
+      {
+        \msg_warning:nnn { spath3 } { missing soft path } { #2 }
+      }
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
   shorten~ at~ end/.code~ 2~ args={
-    \tl_if_exist:cT {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     {
       \spath_shorten_at_end:cn
       {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} {#2}
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
   shorten~ at~ start/.code~ 2~ args ={
-    \tl_if_exist:cT {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     {
       \spath_shorten_at_start:cn
       {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} {#2}
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
   shorten~ at~ both~ ends/.code~ 2~ args={
-    \tl_if_exist:cT {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     {
       \spath_shorten_at_end:cn
       {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} {#2}
@@ -229,23 +643,103 @@
       \spath_shorten_at_start:cn
       {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} {#2}
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
+  shorten~ globally~ at~ end/.code~ 2~ args={
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \spath_gshorten_at_end:cn
+      {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} {#2}
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+  shorten~ globally~ at~ start/.code~ 2~ args ={
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \spath_gshorten_at_start:cn
+      {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} {#2}
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+  shorten~ globally~ at~ both~ ends/.code~ 2~ args={
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \spath_shorten_at_end:cn
+      {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} {#2}
+      \spath_shorten_at_start:cn
+      {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} {#2}
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
   translate/.code~ n~ args={3}{
-    \tl_if_exist:cT {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     {
       \spath_translate:cnn
       {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}{#2}{#3}
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
+  translate~ globally/.code~ n~ args={3}{
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \spath_gtranslate:cnn
+      {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}{#2}{#3}
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+  normalise/.code={
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \spath_normalise:c
+      {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+  normalise~ globally/.code={
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \spath_gnormalise:c
+      {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
   export~ to~ svg/.code={
-    \tl_if_exist:cT {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     {
-      \spath_export_to_svg:c
+      \spath_export_to_svg:nv {#1}
       {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
   transform/.code~ 2~ args={
-    \tl_if_exist:cT {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     {
       \group_begin:
       \pgftransformreset
@@ -260,9 +754,13 @@
       \group_end:
       \tl_use:N \g__spath_smuggle_tl
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
-  transform~global/.code~ 2~ args={
-    \tl_if_exist:cT {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+  transform~globally/.code~ 2~ args={
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     {
       \group_begin:
       \pgftransformreset
@@ -277,27 +775,111 @@
       \group_end:
       \tl_use:N \g__spath_smuggle_tl
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
+  split~ at~ intersections~ with/.code~ n~ args={2}{
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \tl_if_exist:cTF
+      {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl}
+      {
+        \spath_split_path_at_intersections:cv
+        {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+        {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl}
+      }
+      {
+        \msg_warning:nnn { spath3 } { missing soft path } { #2 }
+      }
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+  split~ globally~ at~ intersections~ with/.code~ n~ args={2}{
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \tl_if_exist:cTF
+      {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl}
+      {
+        \spath_gsplit_path_at_intersections:cv
+        {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+        {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl}
+      }
+      {
+        \msg_warning:nnn { spath3 } { missing soft path } { #2 }
+      }
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
   split~ at~ intersections/.code~ n~ args={2}{
-    \tl_if_exist:cT {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     {
-      \tl_if_exist:cT {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl}
+      \tl_if_exist:cTF
+      {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl}
       {
         \spath_split_at_intersections:cc
         {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
         {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl}
       }
+      {
+        \msg_warning:nnn { spath3 } { missing soft path } { #2 }
+      }
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
+  split~ globally~ at~ intersections/.code~ n~ args={2}{
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \tl_if_exist:cTF
+      {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl}
+      {
+        \spath_gsplit_at_intersections:cc
+        {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+        {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl}
+      }
+      {
+        \msg_warning:nnn { spath3 } { missing soft path } { #2 }
+      }
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
   split~ at~ self~ intersections/.code={
-    \tl_if_exist:cT {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     {
       \spath_split_at_self_intersections:c
       {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
+  split~ globally~ at~ self~ intersections/.code={
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \spath_gsplit_at_self_intersections:c
+      {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
   get~ components~ of/.code~ 2~ args={
-    \tl_if_exist:cT {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     {
       \clist_clear_new:N #2
       \spath_components_to_seq:Nv
@@ -306,16 +888,58 @@
       \seq_map_inline:Nn \l__spath_tmpa_seq
       {
         \tl_new:c
-        {\tl_use:N \l__spath_prefix_tl anonymous_\int_use:N \g__spath_anon_int \tl_use:N \l__spath_suffix_tl}
+        {
+          \tl_use:N \l__spath_prefix_tl
+          anonymous_\int_use:N \g__spath_anon_int
+          \tl_use:N \l__spath_suffix_tl
+        }
         \tl_set:cn
-        {\tl_use:N \l__spath_prefix_tl anonymous_\int_use:N \g__spath_anon_int \tl_use:N \l__spath_suffix_tl} {##1}
+        {
+          \tl_use:N \l__spath_prefix_tl
+          anonymous_\int_use:N \g__spath_anon_int
+          \tl_use:N \l__spath_suffix_tl
+        } {##1}
         \clist_put_right:Nx #2 {anonymous_\int_use:N \g__spath_anon_int}
         \int_gincr:N \g__spath_anon_int
       }
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
+  get~ components~ of~ globally/.code~ 2~ args={
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \clist_gclear_new:N #2
+      \spath_components_to_seq:Nv
+      \l__spath_tmpa_seq
+      {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+      \seq_map_inline:Nn \l__spath_tmpa_seq
+      {
+        \tl_new:c
+        {
+          \tl_use:N \l__spath_prefix_tl
+          anonymous_\int_use:N \g__spath_anon_int
+          \tl_use:N \l__spath_suffix_tl
+        }
+        \tl_gset:cn
+        {
+          \tl_use:N \l__spath_prefix_tl
+          anonymous_\int_use:N \g__spath_anon_int
+          \tl_use:N \l__spath_suffix_tl
+        } {##1}
+        \clist_gput_right:Nx #2 {anonymous_\int_use:N \g__spath_anon_int}
+        \int_gincr:N \g__spath_anon_int
+      }
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
   render~ components/.code={
-    \tl_if_exist:cT {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     {
       \group_begin:
       \spath_components_to_seq:Nv
@@ -338,17 +962,29 @@
       }
       \group_end:
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
   insert~ gaps~ after~ components/.code~ n~ args={3}{
-    \tl_if_exist:cT {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     {
       \group_begin:
       \seq_gclear:N \g__spath_tmpa_seq
       \seq_gclear:N \g__spath_tmpb_seq
+      \spath_numberofcomponents:Nv \l__spath_tmpa_int
+      {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
       \foreach \l__spath_tmpa_tl in {#3}
       {
         \seq_gput_right:NV \g__spath_tmpa_seq \l__spath_tmpa_tl
-        \seq_gput_right:Nx \g__spath_tmpb_seq {\int_eval:n { \l__spath_tmpa_tl + 1 }}
+        \seq_gput_right:Nx
+        \g__spath_tmpb_seq
+        {\int_eval:n
+          {
+            \int_mod:nn { \l__spath_tmpa_tl }{ \l__spath_tmpa_int } + 1
+          }
+        }
       }
       \spath_components_to_seq:Nv
       \l__spath_tmpa_seq
@@ -374,9 +1010,62 @@
       \g__spath_output_tl
       \tl_gclear:N \g__spath_output_tl
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
+  insert~ gaps~ globally~ after~ components/.code~ n~ args={3}{
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \group_begin:
+      \seq_gclear:N \g__spath_tmpa_seq
+      \seq_gclear:N \g__spath_tmpb_seq
+      \spath_numberofcomponents:Nv \l__spath_tmpa_int
+      {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+      \foreach \l__spath_tmpa_tl in {#3}
+      {
+        \seq_gput_right:NV \g__spath_tmpa_seq \l__spath_tmpa_tl
+        \seq_gput_right:Nx
+        \g__spath_tmpb_seq
+        {
+          \int_eval:n
+          {
+            \int_mod:nn { \l__spath_tmpa_tl }{ \l__spath_tmpa_int } + 1
+          }
+        }
+      }
+      \spath_components_to_seq:Nv
+      \l__spath_tmpa_seq
+      {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+      \seq_clear:N \l__spath_tmpb_seq
+      \seq_map_indexed_inline:Nn \l__spath_tmpa_seq
+      {
+        \tl_set:Nn \l__spath_tmpa_tl {##2}
+        \seq_if_in:NnT \g__spath_tmpa_seq {##1}
+        {
+          \spath_shorten_at_end:Nn \l__spath_tmpa_tl {#2/2}
+        }
+        \seq_if_in:NnT \g__spath_tmpb_seq {##1}
+        {
+          \spath_shorten_at_start:Nn \l__spath_tmpa_tl {#2/2}
+        }
+        \seq_put_right:NV \l__spath_tmpb_seq \l__spath_tmpa_tl
+      }
+      \tl_gset:Nx \g__spath_output_tl {\seq_use:Nn \l__spath_tmpb_seq {} }
+      \group_end:
+      \tl_gset_eq:cN
+      {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+      \g__spath_output_tl
+      \tl_gclear:N \g__spath_output_tl
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
   join~ components/.code~ 2~ args={
-    \tl_if_exist:cT {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     {
       \seq_gclear:N \g__spath_tmpa_seq
       \foreach \l__spath_tmpa_tl in {#2}
@@ -395,14 +1084,145 @@
         {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}{##1}
       }
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
+  join~ components~ globally/.code~ 2~ args={
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \seq_gclear:N \g__spath_tmpa_seq
+      \foreach \l__spath_tmpa_tl in {#2}
+      {
+        \seq_gput_right:NV \g__spath_tmpa_seq \l__spath_tmpa_tl
+      }
+      \seq_gsort:Nn \g__spath_tmpa_seq
+      {
+        \int_compare:nNnTF {##1} > {##2}
+        { \sort_return_same: }
+        { \sort_return_swapped: }
+      }
+      \seq_map_inline:Nn \g__spath_tmpa_seq
+      {
+        \spath_gjoin_component:cn
+        {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}{##1}
+      }
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
   remove~ empty~ components/.code={
-    \tl_if_exist:cT {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     {
       \spath_remove_empty_components:c
       {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
     }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
   },
+  remove~ empty~ components~ globally/.code={
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \spath_gremove_empty_components:c
+      {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+  remove~ components/.code~ 2~ args={
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \seq_gclear:N \g__spath_tmpa_seq
+      \foreach \l__spath_tmpa_tl in {#2}
+      {
+        \seq_gput_right:NV \g__spath_tmpa_seq \l__spath_tmpa_tl
+      }
+      \seq_gsort:Nn \g__spath_tmpa_seq
+      {
+        \int_compare:nNnTF {##1} < {##2}
+        { \sort_return_same: }
+        { \sort_return_swapped: }
+      }
+      \spath_components_to_seq:Nv
+      \l__spath_tmpa_seq
+      {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+      \seq_gpop_left:NNF \g__spath_tmpa_seq \l__spath_tmpa_tl
+      {
+        \tl_clear:N \l__spath_tmpa_tl
+      }
+      \seq_clear:N \l__spath_tmpb_seq
+      \seq_map_indexed_inline:Nn \l__spath_tmpa_seq
+      {
+        \tl_set:Nn \l__spath_tmpb_tl {##1}
+        \tl_if_eq:NNTF \l__spath_tmpb_tl \l__spath_tmpa_tl
+        {
+          \seq_gpop_left:NNF \g__spath_tmpa_seq \l__spath_tmpa_tl
+          {
+            \tl_clear:N \l__spath_tmpa_tl
+          }
+        }
+        {
+          \seq_put_right:Nn \l__spath_tmpb_seq {##2}
+        }
+      }
+      \tl_set:cx {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+      {\seq_use:Nn \l__spath_tmpb_seq {} }
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
+  remove~ components~ globally/.code~ 2~ args={
+    \tl_if_exist:cTF
+    {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+    {
+      \seq_gclear:N \g__spath_tmpa_seq
+      \foreach \l__spath_tmpa_tl in {#2}
+      {
+        \seq_gput_right:NV \g__spath_tmpa_seq \l__spath_tmpa_tl
+      }
+      \seq_gsort:Nn \g__spath_tmpa_seq
+      {
+        \int_compare:nNnTF {##1} < {##2}
+        { \sort_return_same: }
+        { \sort_return_swapped: }
+      }
+      \spath_components_to_seq:Nv
+      \l__spath_tmpa_seq
+      {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+      \seq_gpop_left:NNF \g__spath_tmpa_seq \l__spath_tmpa_tl
+      {
+        \tl_clear:N \l__spath_tmpa_tl
+      }
+      \seq_clear:N \l__spath_tmpb_seq
+      \seq_map_indexed_inline:Nn \l__spath_tmpa_seq
+      {
+        \tl_set:Nn \l__spath_tmpb_tl {##1}
+        \tl_if_eq:NNTF \l__spath_tmpb_tl \l__spath_tmpa_tl
+        {
+          \seq_gpop_left:NNF \g__spath_tmpa_seq \l__spath_tmpa_tl
+          {
+            \tl_clear:N \l__spath_tmpa_tl
+          }
+        }
+        {
+          \seq_put_right:Nn \l__spath_tmpb_seq {##2}
+        }
+      }
+      \tl_gset:cx {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+      {\seq_use:Nn \l__spath_tmpb_seq {} }
+    }
+    {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+    }
+  },
   draft~ mode/.is~ choice,
   draft~ mode/true/.code={
     \bool_set_true:N \l__spath_draft_bool
@@ -413,13 +1233,31 @@
   maybe~ spot~ weld/.code={
     \bool_if:NF \l__spath_draft_bool
     {
-      \tl_if_exist:cT {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+      \tl_if_exist:cTF
+      {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
       {
         \spath_spot_weld_components:c
         {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
       }
+      {
+        \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+      }
     }
   },
+  maybe~ spot~ weld~ globally/.code={
+    \bool_if:NF \l__spath_draft_bool
+    {
+      \tl_if_exist:cTF
+      {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+      {
+        \spath_spot_gweld_components:c
+        {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}
+      }
+      {
+        \msg_warning:nnn { spath3 } { missing soft path } { #1 }
+      }
+    }
+  },
   transform~ to/.code~ 2~ args={
     \group_begin:
     \tl_if_exist:cTF
@@ -449,6 +1287,7 @@
       \tl_gset_eq:NN \g__spath_smuggle_tl \l__spath_tmpc_tl
     }
     {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
       \tl_gset_eq:NN \g__spath_smuggle_tl { {1}{0}{0}{1}{0pt}{0pt} }
     }
     \group_end:
@@ -484,6 +1323,7 @@
       \tl_gset_eq:NN \g__spath_smuggle_tl \l__spath_tmpc_tl
     }
     {
+      \msg_warning:nnn { spath3 } { missing soft path } { #1 }
       \tl_gset_eq:NN \g__spath_smuggle_tl { {1}{0}{0}{1}{0pt}{0pt} }
     }
     \fp_compare:nT { \tl_item:Nn \g__spath_smuggle_tl {4} < 0}
@@ -503,12 +1343,19 @@
     \tl_gclear:N \g__spath_smuggle_tl
   },
   knot/.style~ n~ args={3}{
-    spath/.cd,
-    split~ at~ self~ intersections=#1,
-    insert~ gaps~ after~ components={#1}{#2}{#3},
-    maybe~ spot~ weld=#1,
-    render~ components=#1
+    spath/split~ at~ self~ intersections=#1,
+    spath/remove~ empty~ components=#1,
+    spath/insert~ gaps~ after~ components={#1}{#2}{#3},
+    spath/maybe~ spot~ weld=#1,
+    spath/render~ components=#1
   },
+  global~ knot/.style~ n~ args={3}{
+    spath/split~ globally~ at~ self~ intersections=#1,
+    spath/remove~ empty~ components~ globally=#1,
+    spath/insert~ gaps~ globally ~after~ components={#1}{#2}{#3},
+    spath/maybe~ spot~ weld~ globally=#1,
+    spath/render~ components=#1
+  },
 }
 \tikzdeclarecoordinatesystem{spath}{%
   \group_begin:
@@ -556,15 +1403,20 @@
     }
   }
   {
+    \msg_warning:nnx { spath3 } { missing soft path } { \tl_use:N \l__spath_tmpa_tl }
     \tl_gset_eq:NN \g__spath_smuggle_tl \pgfpointorigin
   }
-    \group_end:
+  \group_end:
+  \use:c {pgf at process}{%
     \tl_use:N \g__spath_smuggle_tl
+    \pgftransforminvert
+    \use:c {pgf at pos@transform at glob}
+  }
 }
 
 \ExplSyntaxOff
 %% 
-%% Copyright (C) 2011-2019 by Andrew Stacey <loopspace at mathforge.org>
+%% Copyright (C) 2011-2021 by Andrew Stacey <loopspace at mathforge.org>
 %% 
 %% This work may be distributed and/or modified under the
 %% conditions of the LaTeX Project Public License (LPPL), either
@@ -576,7 +1428,7 @@
 %% This work is "maintained" (as per LPPL maintenance status) by
 %% Andrew Stacey.
 %% 
-%% This work consists of the files  spath3.dtx
+%% This work consists of the files  spath3_code.dtx
 %%                                  calligraphy_doc.tex
 %%                                  knots_doc.tex
 %%                                  spath3.tex



More information about the tex-live-commits mailing list.