diff options
author | Karl Berry <karl@freefriends.org> | 2022-10-26 19:59:14 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2022-10-26 19:59:14 +0000 |
commit | f5ff19180266238e2ed7754f8818ed8c149f950c (patch) | |
tree | c9a1c7d5d25172d9f1474038a8ad021a255ea550 /Master | |
parent | 1727757c182b7cd2377643274a192119053353ff (diff) |
spath3 (26oct22)
git-svn-id: svn://tug.org/texlive/trunk@64818 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master')
-rw-r--r-- | Master/texmf-dist/doc/latex/spath3/knots.pdf | bin | 341621 -> 367400 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/latex/spath3/knots.tex | 113 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/spath3/spath3.pdf | bin | 388662 -> 441114 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/latex/spath3/spath3.tex | 223 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/spath3/spath3_code.pdf | bin | 571802 -> 833596 bytes | |||
-rw-r--r-- | Master/texmf-dist/source/latex/spath3/spath3_code.dtx | 5203 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/spath3/spath3.sty | 1753 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/spath3/tikzlibraryknots.code.tex | 86 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/spath3/tikzlibraryspath3.code.tex | 3071 | ||||
-rwxr-xr-x | Master/tlpkg/libexec/ctan2tds | 1 |
10 files changed, 7201 insertions, 3249 deletions
diff --git a/Master/texmf-dist/doc/latex/spath3/knots.pdf b/Master/texmf-dist/doc/latex/spath3/knots.pdf Binary files differindex 39067dee2e4..9f4d6b0fa74 100644 --- a/Master/texmf-dist/doc/latex/spath3/knots.pdf +++ b/Master/texmf-dist/doc/latex/spath3/knots.pdf diff --git a/Master/texmf-dist/doc/latex/spath3/knots.tex b/Master/texmf-dist/doc/latex/spath3/knots.tex index 7e0d885843a..9236af6aa54 100644 --- a/Master/texmf-dist/doc/latex/spath3/knots.tex +++ b/Master/texmf-dist/doc/latex/spath3/knots.tex @@ -611,6 +611,119 @@ This can be combined with the facilities of this package but also has some featu For braids themselves, there is the \Verb+braids+ package which allows input specification in the form of a word in the braid group. +\section{Troubleshooting} + +The diagrams drawn by this package can involve quite complicated calculations and they don't always turn out as expected. +There are plenty of \href{https://tex.stackexchange.com/search?q=knots}{questions on TeX-SX} about this package, but sifting through them can be tricky. +Through answering some of them, I've developed a few strategies for figuring out what's going on. +This section details some of what can go wrong and some of those strategies for finding out what's going on. + +\subsection{Small Diagrams} + +A common situation when the diagrams don't always work out is when the diagram is relatively small. +The defaults in this library are set for a diagram of a few centimetres across. +Some of the key properties are stored as dimensions which means that they don't naturally scale but have to be reset. +In particular, the \Verb!end tolerance! and \Verb!clip radius! are dimensions with defaults \Verb!14pt! and \Verb!10pt! respectively. + +The \Verb!end tolerance! is used to weed out false intersections that occur when a strand is split into pieces. +Therefore, if the \Verb!consider self intersections! key is not set then \Verb!end tolerance! is largely unneeded (though it is still used) so can safely be set to something very small. + +The effect of this can be seen in the following (where to make the issue evident, I've made \Verb!end tolerance! larger rather than make the diagram small). + +\begin{example} +\begin{tikzpicture} +\begin{knot}[ + end tolerance=1.5cm + ] +\strand[red] (0,0) to[out=0,in=180] ++(1,1); +\strand[blue] (0,1) to[out=0,in=180] ++(1,-1); +\end{knot} +\begin{knot} +\strand[red] (1.5,0) to[out=0,in=180] ++(1,1); +\strand[blue] (1.5,1) to[out=0,in=180] ++(1,-1); +\end{knot} +\end{tikzpicture} +\end{example} + +The \Verb!clip radius! determines how much of the diagram is redrawn near a crossing. +If the crossings are very close together, the redraws can interfere with each other. + +\begin{example} +\begin{tikzpicture} +\begin{knot}[ + clip radius=.6cm, + flip crossing=2 + ] +\strand[red] (0,0) to[out=0,in=180] ++(1,.6) to[out=0,in=180] ++(1,-.6); +\strand[blue] (0,1) to[out=0,in=180] ++(1,-.6) to[out=0,in=180] ++(1,.6); +\end{knot} +\begin{knot}[flip crossing=2] +\strand[red] (2.5,0) to[out=0,in=180] ++(1,.6) to[out=0,in=180] ++(1,-.6); +\strand[blue] (2.5,1) to[out=0,in=180] ++(1,-.6) to[out=0,in=180] ++(1,.6); +\end{knot} +\end{tikzpicture} +\end{example} + +\subsection{Strategies} + +\begin{itemize} +\item \Verb+draft mode=crossings+ + +This is useful to check that all the intersections are actually being found. +Any that aren't might be due to \Verb!end tolerance! being too large. +Or if \Verb!consider self intersections! is set to \Verb!no splits! then some self intersections might not be found. + +\item \Verb+background clip+ and \Verb+clip+ styles. + +When a crossing is redrawn, the over strand is clipped to a circle centred on the crossing. +First a background path is drawn to ``wipe out'' the under strand and then the over strand is drawn. +The clip circle for the background path is slightly smaller than the over path to avoid an issue whereby faint artefacts are visible (called \href{https://tex.stackexchange.com/q/188447/86}{crop circles} in one question on TeX-SX). +Rather than use a \Verb!\clip! directly, I use \Verb!\path[background clip]! and \Verb!\path[clip]! which means that these styles can be modified to show the region that is being used. +A useful style is: + +\begin{lstlisting} + background clip/.append style={ + preaction={ + fill=gray, + fill opacity=.5, + } + } +\end{lstlisting} + +\begin{example} +\begin{tikzpicture} +\begin{knot}[ + clip radius=.6cm, + flip crossing=2, + background clip/.append style={ + preaction={ + fill=gray, + fill opacity=.5, + } + } +] +\strand[red] (0,0) to[out=0,in=180] ++(1,.6) to[out=0,in=180] ++(1,-.6); +\strand[blue] (0,1) to[out=0,in=180] ++(1,-.6) to[out=0,in=180] ++(1,.6); +\end{knot} +\begin{knot}[ + flip crossing=2, + background clip/.append style={ + preaction={ + fill=gray, + fill opacity=.5, + } + } +] +\strand[red] (2.5,0) to[out=0,in=180] ++(1,.6) to[out=0,in=180] ++(1,-.6); +\strand[blue] (2.5,1) to[out=0,in=180] ++(1,-.6) to[out=0,in=180] ++(1,.6); +\end{knot} +\end{tikzpicture} +\end{example} + + +\end{itemize} + + \end{document} % Local Variables: % tex-output-type: "pdf18" diff --git a/Master/texmf-dist/doc/latex/spath3/spath3.pdf b/Master/texmf-dist/doc/latex/spath3/spath3.pdf Binary files differindex ebbefefa1a1..9282e0adfeb 100644 --- a/Master/texmf-dist/doc/latex/spath3/spath3.pdf +++ b/Master/texmf-dist/doc/latex/spath3/spath3.pdf diff --git a/Master/texmf-dist/doc/latex/spath3/spath3.tex b/Master/texmf-dist/doc/latex/spath3/spath3.tex index 7621db4a287..c8e9d65af72 100644 --- a/Master/texmf-dist/doc/latex/spath3/spath3.tex +++ b/Master/texmf-dist/doc/latex/spath3/spath3.tex @@ -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{ @@ -89,12 +89,62 @@ The best way is to open an issue at the code repository on github, at \href{http \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 (but note that as yet I haven't implemented sending unknown keys back to the main \Verb+tikz+ directory). +These are all defined in the |spath| family, so all the following keys should be prefixed by |spath/|, or the key |spath/.cd| needs to be used beforehand (but note that as yet I haven't implemented sending unknown keys back to the main |tikz| directory). -The keys try to gracefully fail if the path doesn't exist or is empty. +The keys try to gracefully fail if the path doesn't exist or is empty\footnote{A path that was defined inside a group will be empty if referred to outside that group rather than not existing.}. 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{Path Names} + +Soft paths are stored in macros but are referred to via a name. +The macro is constructed from the name, but there is scope for a prefix and suffix. +By default, these are set up so to be compatible with the |intersections| library -- this package and that save their paths in the same underlying macro. +Some packages that are built on top of this one (such as the |knot| and |penrose| packages) install their own prefixes and suffixes to avoid clashes. + +\begin{function}{ + set prefix, + set suffix, + prefix, + suffix +} +\begin{syntax} +|set prefix=|\marg{prefix} +|set suffix=|\marg{suffix} +|prefix=|\oarg{name} +|suffix=|\oarg{name} +|set name=|\oarg{name} +\end{syntax} +The first two keys set the prefix and suffix directly. +The other keys allow for defining a label for a prefix and suffix for quick switching between different ones. +The default (with key |default| or no key specified) is to match the |intersections| library. +The |knots| library uses this to set a different prefix. +\end{function} + +Using names rather than macros directly also makes it possible to link a soft path with a set of TikZ styles (this is particularly useful when splitting the path into components). + +\begin{variable}{current} +\begin{syntax} +|\path (0,0) -- (3,0) to[out=90, in=90] (1,0) [spath/adjust and close=current];| +\end{syntax} + +There is a special path name, |current|, which refers to the current path being built. +To be clear, the test for this name takes place before any prefix or suffix is applied so it depends only on what the user uses. + +When this name is encountered, the current path is copied into a macro and that path is used in the command. +If the command is such that it is possible that the path is modified in some fashion then after the command is finished the old current path is replaced by the new one. +There are several commands that take multiple paths and |current| can be used in place of any of the paths, but usually there is only one that is modified and so that is the only one that would be used to replace the old current path. + +It only makes sense to use it in a path-building context, and it refers to the path at the moment of invocation, so it doesn't do a lot in the main options on that path but it can be used in options later on in the process. + +Sometimes it isn't possible to put commands partway through a path (for example, if the path command is buried in another macro) so there is a key which can be used to delay things to the end of the construction: + +\begin{verbatim} +at end path construction={code} +\end{verbatim} +% +This invokes the |code| right after the path has finished being built. +\end{variable} \subsection{Saving and Using Soft Paths} @@ -104,16 +154,14 @@ If this doesn't happen, please report it. |save global=|\meta{name} \end{syntax} -Saves the current path with name \texttt{<name>}. +Saves the current path with name \meta{name}. 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. -One is so that it is compatible with the \texttt{intersections} library -- by default both this package and that save their paths in the same underlying macro. -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). +If wanting to save the border of a node then because there are extra levels of grouping, the global version of this key has to be used. + \end{function} \begin{function}{clone, clone globally} @@ -124,6 +172,22 @@ The other is to provide a way to link a soft path with a set of TikZ styles (thi Clones one soft path into another. In the second, the clone is global (the original need not be). + +By using |current| as the source name, the current soft path in its current state is copied. +This can be used to get round the restriction whereby |save path| waits until the path is fully constructed before being saved. +\end{function} + +\begin{function}{show, show current path} +\begin{syntax} +|show=|\meta{name} +|show current path| +\end{syntax} + +These keys display a path on the terminal and in the log file. +They do a bit of sensible line formatting so that the paths are relatively easy to scan through. + +The key |show current path| delays the logging until the path is fully constructed. +To get a view of what the path is at an intermediate stage of construction, use |show=current|. \end{function} \begin{function}{use} @@ -145,20 +209,22 @@ The options is a comma separated list and can include: \item |weld|, |no weld| determines whether to weld the inserted path to the current path. Welding means that the |move to| at the start of the inserted path is removed. Note that this doesn't \emph{move} the inserted path so this will usually modify the first segment of the inserted path, possibly in unexpected ways. +The expected use is that when the |weld| key is used then the inserted path starts where the current path ends either because it already does or because the |move| key has also been invoked. +But there's nothing \emph{stopping} anyone using this key in other circumstances. \item |move|, |no move| determines whether the inserted path is translated so that it starts where the current path ends. \item |transform=|\marg{transformations} applies the specified transformations to the inserted path. -See the |transform| key in Section~\ref{sec:transform} +See the |transform| key in Section~\ref{sec:transform}. +\item |use current transformation| applies the current transformation to the inserted path. +Note that because the keys are processed and then acted upon, this key is always applied \emph{before} the |transform| key. \item Any other key is taken as the name of the path (so it doesn't have to be specified first) with the last one winning. \end{itemize} 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 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. - -In particular, restoring a path should 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. +This means that when re-inserting a soft path back into a high level command (such as |\draw|), existing transformations should have no effect (other than those specified via the |transform| key). +Where this gets a little tricky is with things like node placement -- 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}. +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. \end{function} \begin{function}{ @@ -183,6 +249,19 @@ The equivalences are: \end{itemize} \end{function} +\begin{function}{join with} +\begin{syntax} +|join with=|\marg{path}\marg{path, options} +\end{syntax} + +This joins the second path to the first, with applying the specified options. +The options are the same as for the |use| key. +The first path is modified, the second is not (the second path is copied before any modifications are applied). + +It is almost the case that |join with={current}{...}| is synonymous with |use={...}|. +The difference is that |use={...}| applies an extra check to ensure that the resulting path is not empty. +\end{function} + \begin{function}{to} \begin{syntax} |to=|\marg{name} @@ -198,7 +277,7 @@ The path is transformed by rotation, translation, and uniform scaling so that it \label{sec:transform} The following keys all apply some sort of transformation to the soft path. -They do not render the path, but simply adjust it. +They do not render the path, but simply adjust it (but they can be used to modify the current path by invoking with the path name |current|). The global versions apply their transformation globally, otherwise it is local to the current group (or scope). \begin{function}{reverse, reverse global} @@ -245,9 +324,6 @@ As with the \Verb+to+ path construction and the \Verb+splice+ method, this won't \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, @@ -346,18 +422,27 @@ It applies the following styles (in this order): \begin{function}{ insert gaps after components, - insert gaps globally after components + insert gaps globally after components, + insert gaps after segments, + insert gaps globally after segments } \begin{syntax} |insert gaps after components=|\marg{path}\marg{gap}\marg{components} |insert gaps after components=|\marg{path}\marg{gap} |insert gaps globally after components=|\marg{path}\marg{gap}\marg{components} |insert gaps globally after components=|\marg{path}\marg{gap} +|insert gaps after segments=|\marg{path}\marg{gap}\marg{segments} +|insert gaps after segments=|\marg{path}\marg{gap} +|insert gaps globally after segments=|\marg{path}\marg{gap}\marg{segments} +|insert gaps globally after segments=|\marg{path}\marg{gap} \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| can be used. If the list of components is not given the gaps are inserted between all components. + +The \texttt{segments} versions work on the segments of the path rather than its components. +A \emph{segment} is a minimal drawing piece, meaning a line or B\'ezier curve. \end{function} \begin{function}{ @@ -374,16 +459,20 @@ 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}{join components with, join components globally with, join components upright with, join components globally upright with} +\begin{function}{join components with, join components globally with, join components upright with, join components globally upright with, join components with curve, join components globally with curve} \begin{syntax} |join components with=|\marg{path}\marg{splice path} |join components with=|\marg{path}\marg{splice path}\marg{list} |join components upright with=|\marg{path}\marg{splice path} |join components upright with=|\marg{path}\marg{splice path}\marg{list} +|join components with curve=|\marg{path} +|join components with curve=|\marg{path}\marg{list} |join components globally with=|\marg{path}\marg{splice path} |join components globally with=|\marg{path}\marg{splice path}\marg{list} |join components globally upright with=|\marg{path}\marg{splice path} |join components globally upright with=|\marg{path}\marg{splice path}\marg{list} +|join components globally with curve=|\marg{path} +|join components globally with curve=|\marg{path}\marg{list} \end{syntax} This inserts the |splice path| in the gaps between components of |path| specified by a comma separated list. @@ -396,6 +485,9 @@ This does \emph{not} close the resulting path, even if the last component is spe Note that because there is an optional third argument to this key, the second argument must always be enclosed in braces unless it is a single token. The |upright| versions do a little test to see if the gap is oriented upside-down and if so then they insert the reflection of the splice path. + +The |with curve| versions insert a single B\'ezier curve into the gap. +The curve is chosen to match the tangents of the segments either side of the gap and uses John Hobby's construction of a B\'ezier curve from its tangent directions. \end{function} @@ -436,18 +528,36 @@ This removes the listed components of the path. As with other list routines, the list is parsed via |foreach| first. \end{function} +\begin{function}{open, open globally} +\begin{syntax} +|open=|\marg{path} +|open globally=|\marg{path} +\end{syntax} -\begin{function}{close, close globally, close with, close globally with} +These open the path by removing all of the closing elements. +If the closing elements add substantially to the path then they are replaced by a line segment. +\end{function} + + +\begin{function}{close, close globally, close with, close globally with, close with curve, close globally with curve, adjust and close, adjust and close globally} \begin{syntax} |close=|\marg{path} |close globally=|\marg{path} |close with=|\marg{path}\marg{splice path} |close globally with=|\marg{path}\marg{splice path} +|close with curve=|\marg{path} +|close globally with curve=|\marg{path} +|adjust and close=|\marg{path} +|adjust and close globally=|\marg{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. +The two |with| variants allow you to specify another path to insert between the end and start of the path. +The two |with curve| variants insert a B\'ezier curve in the gap; the choice of curve depends on the tangents of the path segments being joined and uses John Hobby's B\'ezier curve construction (as used in the \texttt{hobby} TikZ library). +The two |adjust| variants shift the end point of the path so that it is at the same place as the start of that component. +If the last segment is a B\'ezier curve then the second control point is also shifted. +(The intention with the |adjust| keys is where the start and end of the component are very close together so the adjustment creates a smaller visual effect than adding in a line -- see Example~\ref{ex:close}.) \end{function} \begin{function}{splice, splice global} @@ -461,7 +571,7 @@ The middle path is transformed to fit (don't try this with a path whose starting \end{function} -\subsection{Shortening Paths} +\subsection{Shortening and Splitting Paths} \begin{function}{ shorten at end, @@ -488,6 +598,42 @@ 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} +\begin{function}{ + split at, + split globally at, + split at into, + split globally at into, + split at keep start, + split globally at keep start, + split at keep end, + split globally at keep end, + split at keep middle, + split globally at keep middle, +} +\begin{syntax} +|split at=|\marg{path}\marg{parameter} +|split globally at=|\marg{path}\marg{parameter} +|split at into=|\marg{start path}\marg{end path}\marg{path}\marg{parameter} +|split globally at into=|\marg{start path}\marg{end path}\marg{path}\marg{parameter} +|split at keep start=|\marg{path}\marg{parameter} +|split globally at keep start=|\marg{path}\marg{parameter} +|split at keep end=|\marg{path}\marg{parameter} +|split globally at keep end=|\marg{path}\marg{parameter} +|split at keep middle=|\marg{path}\marg{parameter}\marg{parameter} +|split globally at keep middle=|\marg{path}\marg{parameter}\marg{parameter} +\end{syntax} + +These keys split a path at a point specified by a parameter. +The interpretation of the parameter is described in Section~\ref{sec:coordinates}. + +The first two keys replace the path with the split path, so this introduces a break at the point specified by the parameter. +The second two save the split path into a new path. + +The ones with \texttt{keep} in the name split a path and keep the designated piece (so throw away the rest). +The ones that keep the middle need two parameters to specify the break points. + +\end{function} + \subsection{Exporting Paths} There are two keys to export a path. @@ -516,8 +662,8 @@ Saves the path to the file \texttt{path.svg} as an SVG document. draft mode } \begin{syntax} -|knot=|\meta{path}\meta{gap}\meta{components} -|global knot=|\meta{path}\meta{gap}\meta{components} +|knot=|\marg{path}\marg{gap}\marg{components} +|global knot=|\marg{path}\marg{gap}\marg{components} \end{syntax} This style combines various of the above to make it simpler to draw knots and links. @@ -679,6 +825,24 @@ The intention with the second key is that it is similar to what happens with the \end{tikzpicture} \end{example} +\item Closing and adjusting paths. +\label{ex:close} + +\begin{example} +\begin{tikzpicture} +\draw[line width=.2cm] (0,0) -- +(1,0) -- +(1,1) -- +(0,1) -- +(.01,.01); + +\draw[line width=.2cm] (2,0) -- +(1,0) -- +(1,1) -- +(0,1) -- +(.01,.01) +-- cycle; + +\draw[line width=.2cm] (4,0) -- +(1,0) -- +(1,1) -- +(0,1) -- +(.01,.01) +[spath/close=current]; + +\draw[line width=.2cm] (6,0) -- +(1,0) -- +(1,1) -- +(0,1) -- +(.01,.01) +[spath/adjust and close=current]; +\end{tikzpicture} +\end{example} + \item Shortening. \begin{example} @@ -929,8 +1093,8 @@ sin ++(1.57,1); } % If used in the preamble, this needs surrounding in \AtBeginDocument -%\AtBeginDocument{ -\tikz[overlay] \path[spath/save=arc] (0,0) arc[radius=1cm, start angle=180, delta angle=-180]; +%\AtBeginDocument{% +\tikz[overlay] { \path[spath/save global=arc] (0,0) arc[radius=1cm, start angle=180, delta angle=-180]; }% %} \begin{tikzpicture} \path[spath/save=over] (0,0) -| ++(1,1) -| ++(-1,1) -| ++(1,1) -| ++(-1,1); @@ -941,5 +1105,8 @@ sin ++(1.57,1); \end{tikzpicture} \end{example} +The command defining the arc does introduce a box which can introduce additional spacing. +The syntax above, with the \% at the end of the lines, shouldn't add space but if for some reason it does then more sophisticated solutions to this are detailed at \href{https://tex.stackexchange.com/q/605800/86}{How to save or define a TikZ path for spath3 without introducing artifacts?}. + \end{enumerate} \end{document} diff --git a/Master/texmf-dist/doc/latex/spath3/spath3_code.pdf b/Master/texmf-dist/doc/latex/spath3/spath3_code.pdf Binary files differindex e61a569ddf7..f773a0b534d 100644 --- a/Master/texmf-dist/doc/latex/spath3/spath3_code.pdf +++ b/Master/texmf-dist/doc/latex/spath3/spath3_code.pdf diff --git a/Master/texmf-dist/source/latex/spath3/spath3_code.dtx b/Master/texmf-dist/source/latex/spath3/spath3_code.dtx index afd132938c7..031c0e7bd3f 100644 --- a/Master/texmf-dist/source/latex/spath3/spath3_code.dtx +++ b/Master/texmf-dist/source/latex/spath3/spath3_code.dtx @@ -143,7 +143,7 @@ and the derived files spath3.ins, %</driver> % \fi % -% \CheckSum{8929} +% \CheckSum{10189} % % \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 @@ -169,6 +169,8 @@ and the derived files spath3.ins, % \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.} % \changes{2.4}{2021/02/21}{Rejigged how the routines for using paths were implemented, added some more routines for joining paths.} +% \changes{2.6}{2021/11/23}{Modified core routines to cope with a "true rectangle" path; added routines for splitting at a parametrised point.} +% \changes{2.7}{2022/08/24}{Bug fixes} % % \DoNotIndex{\newcommand,\newenvironment} % @@ -257,7 +259,7 @@ and the derived files spath3.ins, \NeedsTeXFormat{LaTeX2e} \RequirePackage{expl3} \RequirePackage{pgf} -\ProvidesExplPackage {spath3} {2021/02/21} {2.4} {Functions for +\ProvidesExplPackage {spath3} {2022/08/24} {2.7} {Functions for manipulating PGF soft paths} \RequirePackage{xparse} % \end{macrocode} @@ -332,6 +334,9 @@ manipulating PGF soft paths} \fp_new:N \l_@@_tmpa_fp \fp_new:N \l_@@_tmpb_fp \fp_new:N \l_@@_tmpc_fp +\fp_new:N \l_@@_tmpd_fp +\fp_new:N \l_@@_tmpe_fp +\fp_new:N \l_@@_tmpf_fp \int_new:N \l_@@_tmpa_int \int_new:N \l_@@_tmpb_int @@ -353,6 +358,23 @@ manipulating PGF soft paths} \bool_new:N \l_@@_closed_bool % \end{macrocode} % +% True rectangles are rare, but need special handling. +% They are specified by two tokens, the first specifies the lower left corner which can be handled pretty much as other tokens but the second specifies the width and height meaning that it transforms differently. +% So when encountering on, the coordinates of the lower left corner are useful to remember. +% +% \begin{macrocode} +\dim_new:N \l_@@_rectx_dim +\dim_new:N \l_@@_recty_dim + +\bool_new:N \l_@@_rect_bool +% \end{macrocode} +% +% When restoring a path we need to know whether to update the stored moveto. +% +% \begin{macrocode} +\bool_new:N \l_spath_movetorelevant_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} @@ -369,6 +391,8 @@ manipulating PGF soft paths} \tl_const:Nn \c_spath_curvetoa_tl {\pgfsyssoftpath@curvetosupportatoken} \tl_const:Nn \c_spath_curvetob_tl {\pgfsyssoftpath@curvetosupportbtoken} \tl_const:Nn \c_spath_closepath_tl {\pgfsyssoftpath@closepathtoken} +\tl_const:Nn \c_spath_rectcorner_tl {\pgfsyssoftpath@rectcornertoken} +\tl_const:Nn \c_spath_rectsize_tl {\pgfsyssoftpath@rectsizetoken} % \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. @@ -377,6 +401,27 @@ manipulating PGF soft paths} \int_gzero:N \g_@@_anon_int % \end{macrocode} % +% \begin{macro}[internal]{ +% \spath_anonymous:N, +% \spath_ganonymous:N +% } +% Set the token list to the next anonymous name. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \spath_anonymous:N #1 +{ + \tl_set:Nx #1 {anonymous_\int_use:N \g_@@_anon_int} + \int_gincr:N \g_@@_anon_int +} +\cs_new_protected_nopar:Npn \spath_ganonymous:N #1 +{ + \tl_gset:Nx #1 {anonymous_\int_use:N \g_@@_anon_int} + \int_gincr:N \g_@@_anon_int +} +\cs_generate_variant:Nn \spath_anonymous:N {c} +\cs_generate_variant:Nn \spath_ganonymous:N {c} +% \end{macrocode} +% \end{macro} +% % And some error messages % \begin{macrocode} \msg_new:nnn { spath3 } { unknown path construction } @@ -482,6 +527,27 @@ manipulating PGF soft paths} } + \c_spath_rectcorner_tl + { + \tl_set_eq:NN \l_@@_tmpb_tl \c_spath_rectcorner_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_@@_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_@@_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_@@_tmpb_tl \c_spath_moveto_tl @@ -559,9 +625,11 @@ manipulating PGF soft paths} \group_begin: \tl_set:Nn \l_@@_tmpa_tl {#1} \seq_clear:N \l_@@_tmpa_seq + \tl_set: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: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_@@_tmpa_tl } @@ -572,6 +640,11 @@ manipulating PGF soft paths} \seq_put_right:NV \l_@@_tmpa_seq \l_@@_tmpb_tl \tl_clear:N \l_@@_tmpb_tl } + \tl_if_eq:NNT \l_@@_tmpc_tl \c_spath_rectcorner_tl + { + \seq_put_right:NV \l_@@_tmpa_seq \l_@@_tmpb_tl + \tl_clear:N \l_@@_tmpb_tl + } \tl_if_single:NTF \l_@@_tmpc_tl { \tl_put_right:NV \l_@@_tmpb_tl \l_@@_tmpc_tl @@ -637,7 +710,7 @@ manipulating PGF soft paths} % \spath_reallength:Nn, % \spath_greallength:Nn % } -% The real length of a path is the number of triples that actually draw something (that is, the number of lines, curves, and closepaths). +% The real length of a path is the number of triples that actually draw something (that is, the number of lines, curves, rectangles, and closepaths). % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_reallength:n #1 { @@ -650,6 +723,7 @@ manipulating PGF soft paths} \c_spath_lineto_tl {} \c_spath_curveto_tl {} \c_spath_closepath_tl {} + \c_spath_rectsize_tl {} } { \int_incr:N \l_@@_tmpa_int @@ -695,6 +769,10 @@ manipulating PGF soft paths} { \int_incr:N \l_@@_tmpa_int } + \c_spath_rectcorner_tl + { + \int_incr:N \l_@@_tmpa_int + } } } \int_gzero:N \g_@@_output_int @@ -765,10 +843,35 @@ manipulating PGF soft paths} \tl_set:Nn \l_@@_tmpa_tl {#1} \tl_reverse:N \l_@@_tmpa_tl \tl_clear:N \l_@@_tmpb_tl - \tl_set:Nx \l_@@_tmpb_tl + \tl_set:Nx \l_@@_tmpc_tl {\tl_item:Nn \l_@@_tmpa_tl {3}} + \tl_if_eq:NNTF \l_@@_tmpc_tl \c_spath_rectsize_tl + { + \tl_set:Nx \l_@@_tmpb_tl + { + { + \dim_eval:n + { + \tl_item:Nn \l_@@_tmpa_tl {2} + + + \tl_item:Nn \l_@@_tmpa_tl {5} + } + } + { + \dim_eval:n + { + \tl_item:Nn \l_@@_tmpa_tl {1} + + + \tl_item:Nn \l_@@_tmpa_tl {4} + } + } + } + } { - { \tl_item:Nn \l_@@_tmpa_tl {2} } - { \tl_item:Nn \l_@@_tmpa_tl {1} } + \tl_set:Nx \l_@@_tmpb_tl + { + { \tl_item:Nn \l_@@_tmpa_tl {2} } + { \tl_item:Nn \l_@@_tmpa_tl {1} } + } } \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpb_tl \group_end: @@ -817,6 +920,16 @@ manipulating PGF soft paths} { \tl_item:Nn \l_@@_tmpa_tl {3} } } } + + \c_spath_rectcorner_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} { @@ -844,119 +957,404 @@ manipulating PGF soft paths} % \end{macro} % % \begin{macro}[internal]{ -% \spath_reverse:Nn, -% \spath_greverse:Nn +% \spath_initialtangent:Nn, +% \spath_ginitialtangent:Nn % } -% This computes the reverse of the path. +% The starting tangent of the path. % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_reverse:n #1 +\cs_new_protected_nopar:Npn \@@_initialtangent:n #1 +{ + \group_begin: + \tl_set:Nx \l_@@_tmpb_tl {\tl_item:nn {#1} {4}} + \tl_if_eq:NNTF \l_@@_tmpb_tl \c_spath_curvetoa_tl + { + \fp_set:Nn \l_@@_tmpa_fp {3} + } + { + \fp_set:Nn \l_@@_tmpa_fp {1} + } + \tl_clear:N \l_@@_tmpa_tl + \tl_set:Nx \l_@@_tmpa_tl + { + { + \fp_to_dim:n { + \l_@@_tmpa_fp + * + ( + \tl_item:nn {#1} {5} + - + \tl_item:nn {#1} {2} + ) + } + } + { + \fp_to_dim:n { + \l_@@_tmpa_fp + * + ( + \tl_item:nn {#1} {6} + - + \tl_item:nn {#1} {3} + ) + } + } + } + \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpa_tl + \group_end: +} +\cs_new_protected_nopar:Npn \spath_initialtangent:Nn #1#2 +{ + \@@_initialtangent:n {#2} + \tl_set_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_initialtangent:Nn {NV, cn, cV, Nv} +\cs_new_protected_nopar:Npn \spath_ginitialtangent:Nn #1#2 +{ + \@@_initialtangent:n {#2} + \tl_gset_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_ginitialtangent:Nn {NV, cn, cV, Nv} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{ +% \spath_finaltangent:Nn, +% \spath_gfinaltangent:Nn, +% } +% The final tangent of the path. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_finaltangent:n #1 { \group_begin: \tl_set:Nn \l_@@_tmpa_tl {#1} - + \tl_reverse:N \l_@@_tmpa_tl + \tl_set:Nx \l_@@_tmpb_tl {\tl_item:nn {#1} {6}} + \tl_if_eq:NNTF \l_@@_tmpb_tl \c_spath_curveto_tl + { + \fp_set:Nn \l_@@_tmpa_fp {3} + } + { + \fp_set:Nn \l_@@_tmpa_fp {1} + } \tl_clear:N \l_@@_tmpb_tl - \tl_clear:N \l_@@_tmpd_tl - \tl_set:Nx \l_@@_tmpa_tl {\tl_tail: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} - \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_put_left:Nx \l_@@_tmpd_tl + \tl_set:Nx \l_@@_tmpb_tl { - {\dim_use:N \l_@@_tmpa_dim} - {\dim_use:N \l_@@_tmpb_dim} + { + \fp_to_dim:n { + \l_@@_tmpa_fp + * + ( + \tl_item:Nn \l_@@_tmpa_tl {2} + - + \tl_item:Nn \l_@@_tmpa_tl {5} + ) + } + } + { + \fp_to_dim:n { + \l_@@_tmpa_fp + * + ( + \tl_item:Nn \l_@@_tmpa_tl {1} + - + \tl_item:Nn \l_@@_tmpa_tl {4} + ) + } + } } - - \bool_set_false:N \l_@@_closed_bool - - \bool_until_do:nn { + \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpb_tl + \group_end: +} +\cs_new_protected_nopar:Npn \spath_finaltangent:Nn #1#2 +{ + \@@_finaltangent:n {#2} + \tl_set_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_finaltangent:Nn {NV, cn, cV, Nv} +\cs_new_protected_nopar:Npn \spath_gfinaltangent:Nn #1#2 +{ + \@@_finaltangent:n {#2} + \tl_gset_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_gfinaltangent:Nn {NV, cn, cV, Nv} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}[internal]{ +% \spath_finalmovetangent:Nn, +% \spath_gfinalmovetangent:Nn +% } +% Get the last move on the path. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_finalmovetangent: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_@@_tmpc_tl {\tl_head:N \l_@@_tmpa_tl} - - \tl_case:NnTF \l_@@_tmpc_tl + \tl_set:Nx \l_@@_tmpb_tl {\tl_head:N \l_@@_tmpa_tl} + \tl_case:Nn \l_@@_tmpb_tl { - \c_spath_moveto_tl { - - \bool_if:NT \l_@@_closed_bool + \c_spath_moveto_tl + { + \tl_set:Nx \l_@@_tmpd_tl { \tl_item:Nn \l_@@_tmpa_tl {4} } + \tl_if_eq:NNTF \l_@@_tmpd_tl \c_spath_curveto_tl + { + \fp_set:Nn \l_@@_tmpa_fp {3} + } + { + \fp_set:Nn \l_@@_tmpa_fp {1} + } + \tl_set:Nx \l_@@_tmpc_tl { - \tl_put_right:NV \l_@@_tmpd_tl \c_spath_closepath_tl - \tl_set:Nx \l_@@_tmpe_tl {\tl_tail:N \l_@@_tmpd_tl} - \tl_put_right:Nx \l_@@_tmpd_tl { - { \tl_head:N \l_@@_tmpd_tl } - { \tl_head:N \l_@@_tmpe_tl } + \fp_to_dim:n + { + \l_@@_tmpa_fp + * + ( + \tl_item:Nn \l_@@_tmpa_tl {5} + - + \tl_item:Nn \l_@@_tmpa_tl {2} + ) + } + } + { + \fp_to_dim:n + { + \l_@@_tmpa_fp + * + ( + \tl_item:Nn \l_@@_tmpa_tl {6} + - + \tl_item:Nn \l_@@_tmpa_tl {3} + ) + } } } - \bool_set_false:N \l_@@_closed_bool - \tl_put_left:NV \l_@@_tmpd_tl \c_spath_moveto_tl - \tl_put_left:NV \l_@@_tmpb_tl \l_@@_tmpd_tl - \tl_clear:N \l_@@_tmpd_tl - } - \c_spath_lineto_tl { - \tl_put_left:NV \l_@@_tmpd_tl \c_spath_lineto_tl - } - \c_spath_curveto_tl { - \tl_put_left:NV \l_@@_tmpd_tl \c_spath_curvetoa_tl - } - \c_spath_curvetoa_tl { - \tl_put_left:NV \l_@@_tmpd_tl \c_spath_curveto_tl - } - \c_spath_curvetob_tl { - \tl_put_left:NV \l_@@_tmpd_tl \c_spath_curvetob_tl } } + \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_finalmovetangent:Nn #1#2 +{ + \@@_finalmovetangent:n {#2} + \tl_set_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_finalmovetangent:Nn {NV, cn, cV} +\cs_new_protected_nopar:Npn \spath_gfinalmovetangent:Nn #1#2 +{ + \@@_finalmovetangent:n {#2} + \tl_gset_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_gfinalmovetangent:Nn {NV, cn, cV} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{ +% \spath_reverse:Nn, +% \spath_greverse:Nn +% } +% This computes the reverse of the path. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_reverse:n #1 +{ + \group_begin: + \tl_set:Nn \l_@@_tmpa_tl {#1} - \dim_set:Nn \l_@@_tmpa_dim {\tl_head:N \l_@@_tmpa_tl} - \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl} - \dim_set:Nn \l_@@_tmpb_dim {\tl_head:N \l_@@_tmpa_tl} + \tl_clear:N \l_@@_tmpb_tl + \tl_clear:N \l_@@_tmpd_tl + + \bool_set_false:N \l_@@_rect_bool + + \tl_set:Nx \l_@@_tmpc_tl {\tl_head:N \l_@@_tmpa_tl} + \bool_while_do:nn { + \tl_if_eq_p:NN \l_@@_tmpc_tl \c_spath_rectcorner_tl + } + { + \tl_put_left: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}} + \tl_item:Nn \l_@@_tmpa_tl {4} + {\tl_item:Nn \l_@@_tmpa_tl {5}} + {\tl_item:Nn \l_@@_tmpa_tl {6}} + } + \prg_replicate:nn {6} + { \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl} + } + \tl_set:Nx \l_@@_tmpc_tl {\tl_head:N \l_@@_tmpa_tl} + \bool_set_true:N \l_@@_rect_bool + } - \tl_put_left:Nx \l_@@_tmpd_tl - { - {\dim_use:N \l_@@_tmpa_dim} - {\dim_use:N \l_@@_tmpb_dim} - } + \tl_if_empty:NF \l_@@_tmpa_tl + { + \tl_set:Nx \l_@@_tmpa_tl {\tl_tail: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} + \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_put_left:Nx \l_@@_tmpd_tl + { + {\dim_use:N \l_@@_tmpa_dim} + {\dim_use:N \l_@@_tmpb_dim} + } + + \bool_set_false:N \l_@@_closed_bool + \bool_until_do:nn { + \tl_if_empty_p:N \l_@@_tmpa_tl } { - \tl_if_eq:NNTF \l_@@_tmpc_tl \c_spath_closepath_tl + \tl_set:Nx \l_@@_tmpc_tl {\tl_head:N \l_@@_tmpa_tl} + \bool_set_false:N \l_@@_rect_bool + + \tl_case:NnTF \l_@@_tmpc_tl { - \bool_set_true:N \l_@@_closed_bool + \c_spath_moveto_tl { + + \bool_if:NT \l_@@_closed_bool + { + \tl_put_right:NV \l_@@_tmpd_tl \c_spath_closepath_tl + \tl_set:Nx \l_@@_tmpe_tl {\tl_tail:N \l_@@_tmpd_tl} + \tl_put_right:Nx \l_@@_tmpd_tl + { + { \tl_head:N \l_@@_tmpd_tl } + { \tl_head:N \l_@@_tmpe_tl } + } + } + \bool_set_false:N \l_@@_closed_bool + \tl_put_left:NV \l_@@_tmpd_tl \c_spath_moveto_tl + \tl_put_left:NV \l_@@_tmpb_tl \l_@@_tmpd_tl + \tl_clear:N \l_@@_tmpd_tl + } + \c_spath_rectcorner_tl { + + \bool_if:NT \l_@@_closed_bool + { + \tl_put_right:NV \l_@@_tmpd_tl \c_spath_closepath_tl + \tl_set:Nx \l_@@_tmpe_tl {\tl_tail:N \l_@@_tmpd_tl} + \tl_put_right:Nx \l_@@_tmpd_tl + { + { \tl_head:N \l_@@_tmpd_tl } + { \tl_head:N \l_@@_tmpe_tl } + } + } + \bool_set_false:N \l_@@_closed_bool + \tl_put_left:NV \l_@@_tmpd_tl \c_spath_moveto_tl + \tl_put_left:NV \l_@@_tmpb_tl \l_@@_tmpd_tl + \tl_clear:N \l_@@_tmpd_tl + + \bool_while_do:nn { + \tl_if_eq_p:NN \l_@@_tmpc_tl \c_spath_rectcorner_tl + } + { + \tl_put_left: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}} + \tl_item:Nn \l_@@_tmpa_tl {4} + {\tl_item:Nn \l_@@_tmpa_tl {5}} + {\tl_item:Nn \l_@@_tmpa_tl {6}} + } + \prg_replicate:nn {6} + { + \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl} + } + \tl_set:Nx \l_@@_tmpc_tl {\tl_head:N \l_@@_tmpa_tl} + } + \bool_set_true:N \l_@@_rect_bool + + } + \c_spath_lineto_tl { + \tl_put_left:NV \l_@@_tmpd_tl \c_spath_lineto_tl + } + \c_spath_curveto_tl { + \tl_put_left:NV \l_@@_tmpd_tl \c_spath_curvetoa_tl + } + \c_spath_curvetoa_tl { + \tl_put_left:NV \l_@@_tmpd_tl \c_spath_curveto_tl + } + \c_spath_curvetob_tl { + \tl_put_left:NV \l_@@_tmpd_tl \c_spath_curvetob_tl + } } { - \msg_warning:nnx - { spath3 } - { unknown path construction } - {\l_@@_tmpc_tl } + \tl_if_empty:NF \l_@@_tmpa_tl + { + \tl_set:Nx \l_@@_tmpa_tl {\tl_tail: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} + \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_put_left:Nx \l_@@_tmpd_tl + { + {\dim_use:N \l_@@_tmpa_dim} + {\dim_use:N \l_@@_tmpb_dim} + } + } } + { + \tl_if_eq:NNTF \l_@@_tmpc_tl \c_spath_closepath_tl + { + \bool_set_true:N \l_@@_closed_bool + } + { + \msg_warning:nnx + { spath3 } + { unknown path construction } + { \l_@@_tmpc_tl } + } - \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl} - \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl} - \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl} + \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl} + \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl} + \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl} + + } + } + \bool_if:NT \l_@@_closed_bool + { + \tl_put_right:NV \l_@@_tmpd_tl \c_spath_closepath_tl + \tl_set:Nx \l_@@_tmpe_tl {\tl_tail:N \l_@@_tmpd_tl} + \tl_put_right:Nx \l_@@_tmpd_tl + { + { \tl_head:N \l_@@_tmpd_tl } + { \tl_head:N \l_@@_tmpe_tl } + } } - } - \bool_if:NT \l_@@_closed_bool - { - \tl_put_right:NV \l_@@_tmpd_tl \c_spath_closepath_tl - \tl_set:Nx \l_@@_tmpe_tl {\tl_tail:N \l_@@_tmpd_tl} - \tl_put_right:Nx \l_@@_tmpd_tl + \bool_set_false:N \l_@@_closed_bool + \bool_if:NF \l_@@_rect_bool { - { \tl_head:N \l_@@_tmpd_tl } - { \tl_head:N \l_@@_tmpe_tl } + \tl_put_left:NV \l_@@_tmpd_tl \c_spath_moveto_tl } } - - \bool_set_false:N \l_@@_closed_bool - \tl_put_left:NV \l_@@_tmpd_tl \c_spath_moveto_tl + \tl_put_left:NV \l_@@_tmpb_tl \l_@@_tmpd_tl - \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpb_tl \group_end: } @@ -997,14 +1395,21 @@ manipulating PGF soft paths} { \group_begin: \tl_clear:N \l_@@_tmpa_tl - \int_compare:nT + \tl_set:Nx \l_@@_tmpb_tl {\tl_head:n {#1}} + \tl_if_eq:NNTF \l_@@_tmpb_tl \c_spath_rectcorner_tl { - \tl_count:n {#1} > 3 + \tl_set_eq:NN \l_@@_tmpa_tl \c_spath_rectcorner_tl } { - \tl_set:Nx \l_@@_tmpa_tl + \int_compare:nT { - \tl_item:Nn {#1} {4} + \tl_count:n {#1} > 3 + } + { + \tl_set:Nx \l_@@_tmpa_tl + { + \tl_item:Nn {#1} {4} + } } } \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpa_tl @@ -1052,6 +1457,10 @@ manipulating PGF soft paths} { \tl_set_eq:NN \l_@@_tmpb_tl \c_spath_curveto_tl } + \tl_if_eq:NNT \l_@@_tmpb_tl \c_spath_rectsize_tl + { + \tl_set_eq:NN \l_@@_tmpb_tl \c_spath_rectcorner_tl + } } \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpb_tl \group_end: @@ -1083,22 +1492,60 @@ manipulating PGF soft paths} { \group_begin: \tl_set:Nn \l_@@_tmpa_tl {#1} + + \tl_set:Nx \l_@@_tmpc_tl {\tl_head:N \l_@@_tmpa_tl} \tl_set:Nx \l_@@_tmpa_tl {\tl_tail: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} + \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_eq:NNT \l_@@_tmpc_tl \c_spath_rectcorner_tl + { + \dim_set_eq:NN \l_@@_rectx_dim \l_@@_tmpa_dim + \dim_set_eq:NN \l_@@_recty_dim \l_@@_tmpb_dim + } \bool_until_do:nn { \tl_if_empty_p:N \l_@@_tmpa_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} - \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}} - \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl} + + \tl_if_eq:NNTF \l_@@_tmpc_tl \c_spath_rectsize_tl + { + \dim_set:Nn \l_@@_tmpa_dim + {\dim_min:nn + {\tl_head:N \l_@@_tmpa_tl + \l_@@_rectx_dim} {\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_@@_recty_dim} {\l_@@_tmpb_dim} + } + \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}} + \tl_if_eq:NNT \l_@@_tmpc_tl \c_spath_rectcorner_tl + { + \dim_set:Nn \l_@@_rectx_dim {\tl_head:N \l_@@_tmpa_tl} + } + \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}} + \tl_if_eq:NNT \l_@@_tmpc_tl \c_spath_rectcorner_tl + { + \dim_set:Nn \l_@@_recty_dim {\tl_head:N \l_@@_tmpa_tl} + } + \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl} + } + } \tl_clear:N \l_@@_tmpb_tl \tl_put_right:Nx \l_@@_tmpb_tl @@ -1136,25 +1583,63 @@ manipulating PGF soft paths} { \group_begin: \tl_set:Nn \l_@@_tmpa_tl {#1} + + \tl_set:Nx \l_@@_tmpc_tl {\tl_head:N \l_@@_tmpa_tl} \tl_set:Nx \l_@@_tmpa_tl {\tl_tail: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} + \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_eq:NNT \l_@@_tmpc_tl \c_spath_rectcorner_tl + { + \dim_set_eq:NN \l_@@_rectx_dim \l_@@_tmpa_dim + \dim_set_eq:NN \l_@@_recty_dim \l_@@_tmpb_dim + } \bool_until_do:nn { \tl_if_empty_p:N \l_@@_tmpa_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} - \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}} - \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl} + + \tl_if_eq:NNTF \l_@@_tmpc_tl \c_spath_rectsize_tl + { + \dim_set:Nn \l_@@_tmpa_dim + {\dim_max:nn + {\tl_head:N \l_@@_tmpa_tl + \l_@@_rectx_dim} {\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_@@_recty_dim} {\l_@@_tmpb_dim} + } + \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}} + \tl_if_eq:NNT \l_@@_tmpc_tl \c_spath_rectcorner_tl + { + \dim_set:Nn \l_@@_rectx_dim {\tl_head:N \l_@@_tmpa_tl} + } + \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}} + \tl_if_eq:NNT \l_@@_tmpc_tl \c_spath_rectcorner_tl + { + \dim_set:Nn \l_@@_recty_dim {\tl_head:N \l_@@_tmpa_tl} + } + \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl} + } + } \tl_clear:N \l_@@_tmpb_tl - \tl_put_right:Nx \l_@@_tmpb_tl + \tl_set:Nx \l_@@_tmpb_tl { {\dim_use:N \l_@@_tmpa_dim} {\dim_use:N \l_@@_tmpb_dim} @@ -1194,7 +1679,7 @@ manipulating PGF soft paths} \tl_clear:N \l_@@_tmpa_tl \tl_put_right:Nn \l_@@_tmpa_tl { \ExplSyntaxOn - \tl_clear:N #1 + \tl_clear_new:N #1 \tl_set:Nn #1 {#2} \ExplSyntaxOff } @@ -1212,6 +1697,7 @@ manipulating PGF soft paths} \spath_save_to_aux:NV #1#1 } } +\cs_generate_variant:Nn \spath_save_to_aux:N {c} % \end{macrocode} % \end{macro} % @@ -1241,13 +1727,27 @@ manipulating PGF soft paths} \tl_if_empty_p:N \l_@@_tmpa_tl } { + \tl_set:Nx \l_@@_tmpc_tl {\tl_head: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} - - \dim_set:Nn \l_@@_tmpa_dim {\tl_head:N \l_@@_tmpa_tl + #2} + + \tl_if_eq:NNTF \l_@@_tmpc_tl \c_spath_rectsize_tl + { + \dim_set:Nn \l_@@_tmpa_dim {\tl_head:N \l_@@_tmpa_tl} + } + { + \dim_set:Nn \l_@@_tmpa_dim {\tl_head:N \l_@@_tmpa_tl + #2} + } \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl} - \dim_set:Nn \l_@@_tmpb_dim {\tl_head:N \l_@@_tmpa_tl + #3} + \tl_if_eq:NNTF \l_@@_tmpc_tl \c_spath_rectsize_tl + { + \dim_set:Nn \l_@@_tmpb_dim {\tl_head:N \l_@@_tmpa_tl} + } + { + \dim_set:Nn \l_@@_tmpb_dim {\tl_head:N \l_@@_tmpa_tl + #3} + } \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl} \tl_put_right:Nx \l_@@_tmpb_tl @@ -1470,17 +1970,29 @@ manipulating PGF soft paths} \tl_if_empty_p:N \l_@@_tmpa_tl } { + \tl_set:Nx \l_@@_tmpe_tl {\tl_head: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_set:Nx \l_@@_tmpc_tl {\tl_head:N \l_@@_tmpa_tl} \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl} \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} + + \tl_if_eq:NNTF \l_@@_tmpe_tl \c_spath_rectsize_tl + { + \fp_set:Nn \l_@@_tmpa_fp + {\l_@@_tmpc_tl * #2 + \l_@@_tmpd_tl * #4} + \fp_set:Nn \l_@@_tmpb_fp + {\l_@@_tmpc_tl * #3 + \l_@@_tmpd_tl * #5} + } + { + \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} @@ -1738,8 +2250,8 @@ manipulating PGF soft paths} \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_finalpoint:Nn \l_@@_tmpd_tl {#1} + \spath_initialpoint:Nn \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} @@ -1774,6 +2286,340 @@ manipulating PGF soft paths} % \end{macro} % % \begin{macro}[internal]{ +% \spath_hobby_curve:Nnnnn +% } +% Construct the curve from Hobby's algorithm given the start, end, and tangent directions. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_hobby_curve:nnnn #1#2#3#4 +{ + \group_begin: +% \end{macrocode} +% First tangent vector projected onto vector between endpoints +% +% Something a bit weird here as the components are opposite to how I thought they should be ... +% \begin{macrocode} + \fp_set:Nn \l_@@_tmpa_fp + { + ( + (\tl_item:nn {#2} {1}) + * + (\tl_item:nn {#4} {1} - \tl_item:nn {#1} {1}) + + + (\tl_item:nn {#2} {2}) + * + (\tl_item:nn {#4} {2} - \tl_item:nn {#1} {2}) + ) + / + sqrt + ( + ( + (\tl_item:nn {#2} {1})^2 + + + (\tl_item:nn {#2} {2})^2 + ) + * + ( + (\tl_item:nn {#4} {1} - \tl_item:nn {#1} {1})^2 + + + (\tl_item:nn {#4} {2} - \tl_item:nn {#1} {2})^2 + ) + ) + } + \fp_set:Nn \l_@@_tmpb_fp + { + ( + - + (\tl_item:nn {#2} {1}) + * + (\tl_item:nn {#4} {2} - \tl_item:nn {#1} {2}) + + + (\tl_item:nn {#2} {2}) + * + (\tl_item:nn {#4} {1} - \tl_item:nn {#1} {1}) + ) + / + sqrt + ( + ( + (\tl_item:nn {#2} {1})^2 + + + (\tl_item:nn {#2} {2})^2 + ) + * + ( + (\tl_item:nn {#4} {1} - \tl_item:nn {#1} {1})^2 + + + (\tl_item:nn {#4} {2} - \tl_item:nn {#1} {2})^2 + ) + ) + } +% \end{macrocode} +% Second tangent vector projected onto vector between endpoints +% \begin{macrocode} + \fp_set:Nn \l_@@_tmpc_fp + { + ( + (\tl_item:nn {#3} {1}) + * + (\tl_item:nn {#4} {1} - \tl_item:nn {#1} {1}) + + + (\tl_item:nn {#3} {2}) + * + (\tl_item:nn {#4} {2} - \tl_item:nn {#1} {2}) + ) + / + sqrt + ( + ( + (\tl_item:nn {#3} {1})^2 + + + (\tl_item:nn {#3} {2})^2 + ) + * + ( + (\tl_item:nn {#4} {1} - \tl_item:nn {#1} {1})^2 + + + (\tl_item:nn {#4} {2} - \tl_item:nn {#1} {2})^2 + ) + ) + } + \fp_set:Nn \l_@@_tmpd_fp + { + ( + (\tl_item:nn {#3} {1}) + * + (\tl_item:nn {#4} {2} - \tl_item:nn {#1} {2}) + - + (\tl_item:nn {#3} {2}) + * + (\tl_item:nn {#4} {1} - \tl_item:nn {#1} {1}) + ) + / + sqrt + ( + ( + (\tl_item:nn {#3} {1})^2 + + + (\tl_item:nn {#3} {2})^2 + ) + * + ( + (\tl_item:nn {#4} {1} - \tl_item:nn {#1} {1})^2 + + + (\tl_item:nn {#4} {2} - \tl_item:nn {#1} {2})^2 + ) + ) + } + + \fp_set:Nn \l_@@_tmpe_fp + { + ( + 2 + sqrt(2) * + (\l_@@_tmpb_fp - 1/16 * \l_@@_tmpd_fp) + * + (\l_@@_tmpd_fp - 1/16 * \l_@@_tmpb_fp) + * + (\l_@@_tmpa_fp - \l_@@_tmpc_fp) + ) + / + ( + 1 + + + (1 - (3 - sqrt(5))/2) + * + \l_@@_tmpa_fp + + + (3 - sqrt(5))/2 + * + \l_@@_tmpc_fp + ) + * + sqrt + ( + ( + (\tl_item:nn {#4} {1} - \tl_item:nn {#1} {1})^2 + + + (\tl_item:nn {#4} {2} - \tl_item:nn {#1} {2})^2 + ) + / + ( + (\tl_item:nn {#2} {1})^2 + + + (\tl_item:nn {#2} {2})^2 + ) + ) + /3 + } + \fp_set:Nn \l_@@_tmpf_fp + { + ( + 2 - sqrt(2) * + (\l_@@_tmpb_fp - 1/16 * \l_@@_tmpd_fp) + * + (\l_@@_tmpd_fp - 1/16 * \l_@@_tmpb_fp) + * + (\l_@@_tmpa_fp - \l_@@_tmpc_fp) + ) + / + ( + 1 + + + (1 - (3 - sqrt(5))/2) + * + \l_@@_tmpc_fp + + + (3 - sqrt(5))/2 + * + \l_@@_tmpa_fp + ) + * + sqrt + ( + ( + (\tl_item:nn {#4} {1} - \tl_item:nn {#1} {1})^2 + + + (\tl_item:nn {#4} {2} - \tl_item:nn {#1} {2})^2 + ) + / + ( + (\tl_item:nn {#3} {1})^2 + + + (\tl_item:nn {#3} {2})^2 + ) + ) + /3 + } + + \tl_set:Nx \l_@@_tmpa_tl + { + { + \fp_to_dim:n + { + \tl_item:nn {#1} {1} + + + \l_@@_tmpe_fp + * + (\tl_item:nn {#2} {1}) + } + } + { + \fp_to_dim:n + { + \tl_item:nn {#1} {2} + + + \l_@@_tmpe_fp + * + (\tl_item:nn {#2} {2}) + } + } + } + \tl_set:Nx \l_@@_tmpb_tl + { + { + \fp_to_dim:n + { + \tl_item:nn {#4} {1} + - + \l_@@_tmpf_fp + * + (\tl_item:nn {#3} {1}) + } + } + { + \fp_to_dim:n + { + \tl_item:nn {#4} {2} + - + \l_@@_tmpf_fp + * + (\tl_item:nn {#3} {2}) + } + } + } + + \tl_clear:N \l_@@_tmpc_tl + \tl_set:NV \l_@@_tmpc_tl \c_spath_moveto_tl + \tl_put_right:Nn \l_@@_tmpc_tl {#1} + \tl_put_right:NV \l_@@_tmpc_tl \c_spath_curvetoa_tl + \tl_put_right:NV \l_@@_tmpc_tl \l_@@_tmpa_tl + \tl_put_right:NV \l_@@_tmpc_tl \c_spath_curvetob_tl + \tl_put_right:NV \l_@@_tmpc_tl \l_@@_tmpb_tl + \tl_put_right:NV \l_@@_tmpc_tl \c_spath_curveto_tl + \tl_put_right:Nn \l_@@_tmpc_tl {#4} + \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpc_tl + \group_end: +} +\cs_new_protected_nopar:Npn \spath_hobby_curve:Nnnnn #1#2#3#4#5 +{ + \@@_hobby_curve:nnnn {#2}{#3}{#4}{#5} + \tl_set_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_hobby_curve:Nnnnn {NVVVV} +\cs_new_protected_nopar:Npn \spath_ghobby_curve:Nnnnn #1#2#3#4#5 +{ + \@@_hobby_curve:nnnn {#2}{#3}{#4}{#5} + \tl_gset_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_ghobby_curve:Nnnnn {NVVVV} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}[internal]{ +% \spath_curve_between:Nnn, +% \spath_curve_between:Nn, +% \spath_gcurve_between:Nnn, +% \spath_gcurve_between:Nn +% } +% This takes two paths and returns a single path formed by joining the two paths by a curve. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_curve_between:nn #1#2 +{ + \group_begin: + \spath_finalpoint:Nn \l_@@_tmpa_tl {#1} + \spath_finaltangent:Nn \l_@@_tmpb_tl {#1} + \spath_initialpoint:Nn \l_@@_tmpc_tl {#2} + \spath_initialtangent:Nn \l_@@_tmpd_tl {#2} + + \spath_hobby_curve:NVVVV \l_@@_tmpe_tl + \l_@@_tmpa_tl \l_@@_tmpb_tl \l_@@_tmpd_tl \l_@@_tmpc_tl + + \tl_set:Nn \l_@@_tmpa_tl {#1} + \spath_append_no_move:NV \l_@@_tmpa_tl \l_@@_tmpe_tl + \spath_append_no_move:Nn \l_@@_tmpa_tl {#2} + \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpa_tl + \group_end: +} +\cs_new_protected_nopar:Npn \spath_curve_between:Nnn #1#2#3 +{ + \@@_curve_between:nn {#2}{#3} + \tl_set_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_curve_between:Nnn {NVn, NVV} +\cs_new_protected_nopar:Npn \spath_curve_between:Nn #1#2 +{ + \spath_curve_between:NVn #1#1{#2} +} +\cs_generate_variant:Nn \spath_curve_between:Nn {NV, cn, cv} +\cs_new_protected_nopar:Npn \spath_gcurve_between:Nnn #1#2#3 +{ + \@@_curve_between:nn {#2} + \tl_gset_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_gcurve_between:Nnn {NVn, NVV} +\cs_new_protected_nopar:Npn \spath_gcurve_between:Nn #1#2 +{ + \spath_gcurve_between:NVnn #1#1{#2} +} +\cs_generate_variant:Nn \spath_gcurve_between:Nn {NV, cn, cv} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{ % \spath_close_with:Nn, % \spath_gclose_with:Nn % } @@ -1839,6 +2685,77 @@ manipulating PGF soft paths} % \end{macro} % % \begin{macro}[internal]{ +% \spath_close_with_curve:N, +% \spath_gclose_with_curve:N +% } +% Closes the path with a curve. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_close_with_curve:n #1 +{ + \group_begin: + \spath_finalpoint:Nn \l_@@_tmpa_tl {#1} + \spath_finaltangent:Nn \l_@@_tmpb_tl {#1} + \spath_finalmovepoint:Nn \l_@@_tmpc_tl {#1} + \spath_finalmovetangent:Nn \l_@@_tmpd_tl {#1} + \dim_compare:nTF + { + \dim_abs:n + { + \tl_item:Nn \l_@@_tmpa_tl {1} + - + \tl_item:Nn \l_@@_tmpc_tl {1} + } + + + \dim_abs:n + { + \tl_item:Nn \l_@@_tmpa_tl {2} + - + \tl_item:Nn \l_@@_tmpc_tl {2} + } + < 0.01pt + } + { + \@@_close:n {#1} + } + { + + \spath_hobby_curve:NVVVV \l_@@_tmpe_tl + \l_@@_tmpa_tl \l_@@_tmpb_tl \l_@@_tmpd_tl \l_@@_tmpc_tl + + \tl_set:Nn \l_@@_tmpa_tl {#1} + \spath_append_no_move:NV \l_@@_tmpa_tl \l_@@_tmpe_tl + \@@_close:V \l_@@_tmpa_tl + } + \group_end: +} +\cs_new_protected_nopar:Npn \spath_close_with_curve:Nn #1#2 +{ + \@@_close_with_curve:n {#2} + \tl_set_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_close_with_curve:Nn {cn, cV, cv, NV} +\cs_new_protected_nopar:Npn \spath_close_with_curve:N #1 +{ + \spath_close_with_curve:NV #1#1 +} +\cs_generate_variant:Nn \spath_close_with_curve:N {c} +\cs_new_protected_nopar:Npn \spath_gclose_with_curve:Nn #1#2 +{ + \@@_close_with_curve:n {#2} + \tl_gset_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_gclose_with_curve:Nn {cn, cV, cv, NV} +\cs_new_protected_nopar:Npn \spath_gclose_with_curve:N #1 +{ + \spath_gclose_with_curve:NV #1#1 +} +\cs_generate_variant:Nn \spath_gclose_with_curve:N {c} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{ % \spath_weld:Nnn, % \spath_weld:Nn, % \spath_gweld:Nnn, @@ -1893,16 +2810,27 @@ manipulating PGF soft paths} % \spath_gappend_no_move:Nn, % } % Append the path from the second \Verb+spath+ to the first, removing -% the adjoining move. +% the adjoining move if neither path has a rectangle either side of the join or if the first path isn't closed. % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_append_no_move:nn #1#2 { \group_begin: \tl_set:Nn \l_@@_tmpa_tl {#1} \tl_set:Nn \l_@@_tmpb_tl {#2} - \tl_set:Nx \l_@@_tmpb_tl {\tl_tail:N \l_@@_tmpb_tl} - \tl_set:Nx \l_@@_tmpb_tl {\tl_tail:N \l_@@_tmpb_tl} - \tl_set:Nx \l_@@_tmpb_tl {\tl_tail:N \l_@@_tmpb_tl} + \tl_set:Nx \l_@@_tmpc_tl {\tl_head:N \l_@@_tmpb_tl} + \spath_finalaction:Nn \l_@@_tmpd_tl {#1} + \bool_if:nT { + ! \tl_if_eq_p:NN \l_@@_tmpd_tl \c_spath_closepath_tl + && + ! \tl_if_eq_p:NN \l_@@_tmpd_tl \c_spath_rectcorner_tl + && + \tl_if_eq_p:NN \l_@@_tmpc_tl \c_spath_moveto_tl + } + { + \tl_set:Nx \l_@@_tmpb_tl {\tl_tail:N \l_@@_tmpb_tl} + \tl_set:Nx \l_@@_tmpb_tl {\tl_tail:N \l_@@_tmpb_tl} + \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 @@ -2079,6 +3007,56 @@ manipulating PGF soft paths} % \end{macro} % % \begin{macro}[internal]{ +% \spath_bake_shorten:Nn, +% \spath_bake_shorten:N, +% \spath_gbake_shorten:Nn, +% \spath_gbake_shorten:N +% } +% +% The shortening routine is applied quite late in the process of building a soft path so this ensures that it is done. +% +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_bake_shorten:n #1 +{ + \group_begin: + \tl_set:Nn \l_@@_tmpa_tl {#1} + \pgfsyssoftpath@getcurrentpath\l_@@_tmpb_tl + \pgfsyssoftpath@setcurrentpath\l_@@_tmpa_tl + \pgf@prepare@end@of@path + \pgf@prepare@start@of@path + \pgfsyssoftpath@getcurrentpath\l_@@_tmpa_tl + \pgfsyssoftpath@setcurrentpath\l_@@_tmpb_tl + \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpa_tl + \group_end: +} +\cs_new_protected_nopar:Npn \spath_bake_shorten:Nn #1#2 +{ + \@@_bake_shorten:n {#2} + \tl_set_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_bake_shorten:Nn {NV} +\cs_new_protected_nopar:Npn \spath_bake_shorten:N #1 +{ + \spath_bake_shorten:NV #1#1 +} +\cs_generate_variant:Nn \spath_bake_shorten:N {c} +\cs_new_protected_nopar:Npn \spath_gbake_shorten:Nn #1#2 +{ + \@@_bake_shorten:n {#2} + \tl_gset_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_gbake_shorten:Nn {NV} +\cs_new_protected_nopar:Npn \spath_gbake_shorten:N #1 +{ + \spath_gbake_shorten:NV #1#1 +} +\cs_generate_variant:Nn \spath_gbake_shorten:N {c} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{ % \spath_close:Nn, % \spath_close:N, % \spath_gclose:Nn, @@ -2124,6 +3102,91 @@ manipulating PGF soft paths} % \end{macrocode} % \end{macro} % +% \begin{macro}[internal]{ +% \spath_adjust_close:Nn, +% \spath_adjust_close:N, +% \spath_adjust_gclose:Nn, +% \spath_adjust_gclose:N +% } +% This closes a path and adjusts the end point to be where the final move point (so where the close points to) is. +% The intention is that this should be used if the two points are visually the same point but mathematically different. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_adjust_close:n #1 +{ + \group_begin: + \tl_set:Nn \l_@@_tmpa_tl {#1} + \spath_finalmovepoint:NV \l_@@_tmpb_tl \l_@@_tmpa_tl + \spath_finalpoint:NV \l_@@_tmpc_tl \l_@@_tmpa_tl + \tl_reverse:N \l_@@_tmpa_tl + \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl} + \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl} + \tl_set:Nx \l_@@_tmpd_tl {\tl_head:N \l_@@_tmpa_tl} + \tl_if_eq:NNT \l_@@_tmpd_tl \c_spath_curveto_tl + { + \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl} + \tl_clear:N \l_@@_tmpe_tl + \tl_set:Nx \l_@@_tmpe_tl { + { + \dim_eval:n + { + \tl_item:Nn \l_@@_tmpa_tl {1} + - + \tl_item:Nn \l_@@_tmpc_tl {2} + + + \tl_item:Nn \l_@@_tmpb_tl {2} + } + } + { + \dim_eval:n + { + \tl_item:Nn \l_@@_tmpa_tl {2} + - + \tl_item:Nn \l_@@_tmpc_tl {1} + + + \tl_item:Nn \l_@@_tmpb_tl {1} + } + } + } + \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl} + \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl} + \tl_put_left:NV \l_@@_tmpa_tl \l_@@_tmpe_tl + \tl_put_left:NV \l_@@_tmpa_tl \l_@@_tmpd_tl + } + \tl_reverse:N \l_@@_tmpa_tl + \tl_put_right:NV \l_@@_tmpa_tl \l_@@_tmpb_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 \@@_adjust_close:n {V} +\cs_new_protected_nopar:Npn \spath_adjust_close:Nn #1#2 +{ + \@@_adjust_close:n {#2} + \tl_set_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_adjust_close:Nn {NV} +\cs_new_protected_nopar:Npn \spath_adjust_close:N #1 +{ + \spath_adjust_close:NV #1#1 +} +\cs_generate_variant:Nn \spath_adjust_close:N {c} +\cs_new_protected_nopar:Npn \spath_adjust_gclose:Nn #1#2 +{ + \@@_adjust_close:n {#2} + \tl_gset_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_adjust_gclose:Nn {NV} +\cs_new_protected_nopar:Npn \spath_adjust_gclose:N #1 +{ + \spath_adjust_gclose:NV #1#1 +} +\cs_generate_variant:Nn \spath_adjust_gclose:N {c} +% \end{macrocode} +% \end{macro} +% % % \begin{macro}[internal]{ % \spath_open:Nn, @@ -2132,11 +3195,12 @@ manipulating PGF soft paths} % \spath_gopen:N % } % Removes all close paths from the path, replacing them by \Verb+lineto+ if they move any distance. +% Rectangles are replaced by lines with the start/end at the lower left corner. % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_open:n #1 { \group_begin: - \tl_set:Nn \l_@@_tmpa_tl {#1} + \spath_replace_rectangles:Nn \l_@@_tmpa_tl {#1} \tl_clear:N \l_@@_tmpb_tl \bool_until_do:nn { \tl_if_empty_p:N \l_@@_tmpa_tl @@ -2210,6 +3274,7 @@ manipulating PGF soft paths} \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpb_tl \group_end: } +\cs_generate_variant:Nn \@@_open:n {V} \cs_new_protected_nopar:Npn \spath_open:Nn #1#2 { \@@_open:n {#2} @@ -2232,6 +3297,8 @@ manipulating PGF soft paths} { \spath_gopen:NV #1#1 } +\cs_generate_variant:Nn \spath_open:N {c} +\cs_generate_variant:Nn \spath_gopen:N {c} % \end{macrocode} % \end{macro} % @@ -2358,6 +3425,126 @@ manipulating PGF soft paths} % \end{macro} % % \begin{macro}[internal]{ +% \spath_replace_rectangles:Nn, +% \spath_replace_rectangles:Nn, +% \spath_replace_rectangles:Nn, +% \spath_replace_rectangles:Nn, +% } +% Replace any rectangle components by lines. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_replace_rectangles:n #1 +{ + \group_begin: + \tl_set:Nn \l_@@_tmpa_tl {#1} + \tl_clear:N \l_@@_tmpb_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_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl } + \tl_set:Nx \l_@@_tmpd_tl {\tl_head:N \l_@@_tmpa_tl } + \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl } + \tl_set:Nx \l_@@_tmpe_tl {\tl_head:N \l_@@_tmpa_tl } + \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl } + + \tl_if_eq:NNTF \l_@@_tmpc_tl \c_spath_rectcorner_tl + { + + \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl } + \dim_set:Nn \l_@@_tmpa_dim + { + \tl_item:Nn \l_@@_tmpa_tl {1} + } + \dim_set:Nn \l_@@_tmpb_dim + { + \tl_item:Nn \l_@@_tmpa_tl {2} + } + + \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl } + \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl } + + \tl_put_right:NV \l_@@_tmpb_tl \c_spath_moveto_tl + \@@_tl_put_right_braced:NV \l_@@_tmpb_tl \l_@@_tmpd_tl + \@@_tl_put_right_braced:NV \l_@@_tmpb_tl \l_@@_tmpe_tl + + \tl_put_right:NV \l_@@_tmpb_tl \c_spath_lineto_tl + \tl_put_right:Nx \l_@@_tmpb_tl + { + { + \fp_to_dim:n { \l_@@_tmpd_tl + \l_@@_tmpa_dim } + } + } + \@@_tl_put_right_braced:NV \l_@@_tmpb_tl \l_@@_tmpe_tl + + \tl_put_right:NV \l_@@_tmpb_tl \c_spath_lineto_tl + \tl_put_right:Nx \l_@@_tmpb_tl + { + { + \fp_to_dim:n { \l_@@_tmpd_tl + \l_@@_tmpa_dim } + } + } + \tl_put_right:Nx \l_@@_tmpb_tl + { + { + \fp_to_dim:n { \l_@@_tmpe_tl + \l_@@_tmpb_dim } + } + } + + \tl_put_right:NV \l_@@_tmpb_tl \c_spath_lineto_tl + \@@_tl_put_right_braced:NV \l_@@_tmpb_tl \l_@@_tmpd_tl + \tl_put_right:Nx \l_@@_tmpb_tl + { + { + \fp_to_dim:n { \l_@@_tmpe_tl + \l_@@_tmpb_dim } + } + } + + \tl_put_right:NV \l_@@_tmpb_tl \c_spath_closepath_tl + \@@_tl_put_right_braced:NV \l_@@_tmpb_tl \l_@@_tmpd_tl + \@@_tl_put_right_braced:NV \l_@@_tmpb_tl \l_@@_tmpe_tl + + } + { + \tl_put_right:NV \l_@@_tmpb_tl \l_@@_tmpc_tl + \@@_tl_put_right_braced:NV \l_@@_tmpb_tl \l_@@_tmpd_tl + \@@_tl_put_right_braced:NV \l_@@_tmpb_tl \l_@@_tmpe_tl + } + } + \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpb_tl + \group_end: +} +\cs_generate_variant:Nn \@@_replace_rectangles:n {V} +\cs_new_protected_nopar:Npn \spath_replace_rectangles:Nn #1#2 +{ + \@@_replace_rectangles:n {#2} + \tl_set_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_replace_rectangles:Nn {NV, cV, cv, Nv} +\cs_new_protected_nopar:Npn \spath_replace_rectangles:N #1 +{ + \spath_replace_rectangles:NV #1#1 +} +\cs_generate_variant:Nn \spath_replace_rectangles:N {c} +\cs_new_protected_nopar:Npn \spath_greplace_rectangles:Nn #1#2 +{ + \@@_replace_rectangles:n {#2} + \tl_gset_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_greplace_rectangles:Nn {NV, cV, cv, Nv} +\cs_new_protected_nopar:Npn \spath_greplace_rectangles:N #1 +{ + \spath_greplace_rectangles:NV #1#1 +} +\cs_generate_variant:Nn \spath_greplace_rectangles:N {c} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{ % \spath_remove_empty_components:Nn, % \spath_remove_empty_components:N, % \spath_gremove_empty_components:Nn, @@ -2688,9 +3875,11 @@ manipulating PGF soft paths} } { \fp_set:Nn \l_@@_tmpa_fp {.5 * \l_@@_tmpa_fp / \l_@@_tmpb_fp} - \fp_compare:nTF + \bool_if:nTF { - 0 < \l_@@_tmpa_fp && \l_@@_tmpa_fp < 1 + \fp_compare_p:n {0 < \l_@@_tmpa_fp} + && + \fp_compare_p:n {\l_@@_tmpa_fp < 1} } { \@@_split_curve:nV {#1} \l_@@_tmpa_fp @@ -2908,16 +4097,74 @@ manipulating PGF soft paths} % \end{macrocode} % \end{macro} % +% +% \begin{macro}[internal]{ +% \spath_split_rectangle:Nnn, +% \spath_gsplit_rectangle:Nnn +% } +% Cuts a rectangle at a point. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_split_rectangle:nn #1#2 +{ + \group_begin: + \spath_open:Nn \l_@@_tmpa_tl {#1} + \fp_set:Nn \l_@@_tmpa_fp {4*(#2)} + \spath_split_at:NNVV + \l_@@_tmpa_tl \l_@@_tmpb_tl \l_@@_tmpa_tl \l_@@_tmpa_fp + \@@_append_no_move:VV \l_@@_tmpb_tl \l_@@_tmpa_tl + \group_end: +} +\cs_new_protected_nopar:Npn \spath_split_rectangle:Nnn #1#2#3 +{ + \@@_split_rectangle:nn {#2}{#3} + \tl_set_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_split_rectangle:Nnn {NnV, NVn, NVV} +\cs_new_protected_nopar:Npn \spath_gsplit_rectangle:Nnn #1#2#3 +{ + \@@_split_rectangle:nn {#2}{#3} + \tl_gset_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_gsplit_rectangle:Nnn {NnV, NVn, NVV} +% \end{macrocode} +% \end{macro} +% +% % \begin{macro}[internal]{ % \spath_split_at:NNnn, % \spath_split_at:Nnn, % \spath_split_at:Nn, % \spath_gsplit_at:NNnn % \spath_gsplit_at:Nnn, -% \spath_gsplit_at:Nn +% \spath_gsplit_at:Nn, +% \spath_split_at_keep_start:Nnn, +% \spath_split_at_keep_start:Nn, +% \spath_gsplit_at_keep_start:Nnn, +% \spath_gsplit_at_keep_start:Nn, +% \spath_split_at_keep_end:Nnn, +% \spath_split_at_keep_end:Nn, +% \spath_gsplit_at_keep_end:Nnn, +% \spath_gsplit_at_keep_end:Nn, +% \spath_split_at_normalised:NNnn, +% \spath_split_at_normalised:Nnn, +% \spath_split_at_normalised:Nn, +% \spath_gsplit_at_normalised:NNnn +% \spath_gsplit_at_normalised:Nnn, +% \spath_gsplit_at_normalised:Nn, +% \spath_split_at_normalised_keep_start:Nnn, +% \spath_split_at_normalised_keep_start:Nn, +% \spath_gsplit_at_normalised_keep_start:Nnn, +% \spath_gsplit_at_normalised_keep_start:Nn, +% \spath_split_at_normalised_keep_end:Nnn, +% \spath_split_at_normalised_keep_end:Nn, +% \spath_gsplit_at_normalised_keep_end:Nnn, +% \spath_gsplit_at_normalised_keep_end:Nn, % } % Split a path according to the parameter generated by the intersection routine. % The versions with two \texttt{N} arguments stores the two parts in two macros, the version with a single \texttt{N} joins them back into a single path (as separate components). +% The \texttt{keep} versions throw away the other part of the curve. % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_split_at:nn #1#2 { @@ -2948,11 +4195,28 @@ manipulating PGF soft paths} \bool_set_true:N \l_@@_tmpa_bool \tl_set:Nn \l_@@_tmpe_tl {#1} - \tl_clear:N \l_@@_tmpc_tl \dim_zero:N \l_@@_tmpa_dim \dim_zero:N \l_@@_tmpb_dim + % 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 + || + \tl_if_eq_p:NN \l_@@_tmpa_tl \c_spath_rectcorner_tl + } + + % Open it + \spath_open:N \l_@@_tmpe_tl + + \tl_clear:N \l_@@_tmpa_tl + \tl_clear:N \l_@@_tmpb_tl + \tl_clear:N \l_@@_tmpc_tl + \tl_clear:N \l_@@_tmpd_tl + \bool_until_do:nn { \tl_if_empty_p:N \l_@@_tmpe_tl || @@ -2971,6 +4235,10 @@ manipulating PGF soft paths} { \int_incr:N \l_@@_tmpb_int } + \c_spath_rectcorner_tl + { + \int_incr:N \l_@@_tmpb_int + } } \int_compare:nT { \l_@@_tmpb_int < \l_@@_tmpa_int } { @@ -3075,14 +4343,65 @@ manipulating PGF soft paths} \tl_put_right:NV \l_@@_tmpc_tl \l_@@_tmpa_tl \tl_put_right:NV \l_@@_tmpb_tl \l_@@_tmpe_tl } + + \c_spath_rectcorner_tl + { + \tl_clear:N \l_@@_tmpd_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_@@_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_@@_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_@@_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_@@_tmpd_tl {{\tl_head:N \l_@@_tmpe_tl}} + \tl_set:Nx \l_@@_tmpe_tl {\tl_tail:N \l_@@_tmpe_tl} + + \spath_split_rectangle:NVV + \l_@@_tmpa_tl + \l_@@_tmpd_tl + \l_@@_tmpa_fp + + \tl_put_right:NV \l_@@_tmpc_tl \l_@@_tmpa_tl + \tl_put_right:NV \l_@@_tmpb_tl \l_@@_tmpe_tl + } + } } + \bool_if:NT \l_@@_closed_bool + { + \prg_replicate:nn {3} + { + \tl_set:Nx \l_@@_tmpc_tl {\tl_tail:N \l_@@_tmpc_tl} + } + \tl_put_right:NV \l_@@_tmpb_tl \l_@@_tmpc_tl + \tl_set_eq:NN \l_@@_tmpc_tl \l_@@_tmpb_tl + \tl_clear:N \l_@@_tmpb_tl + } + \tl_gclear:N \g_@@_output_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_generate_variant:Nn \@@_split_at:nn {nV, VV} +\cs_new_protected_nopar:Npn \@@_split_at_normalised:nn #1#2 +{ + \group_begin: + \spath_reallength:Nn \l_@@_tmpa_int {#1} + + \tl_set:Nx \l_@@_tmpa_tl + {\fp_to_decimal:n {(#2) * (\l_@@_tmpa_int)}} + \@@_split_at:nV {#1} \l_@@_tmpa_tl + \group_end: +} +\cs_generate_variant:Nn \@@_split_at_normalised:nn {nV} \cs_new_protected_nopar:Npn \spath_split_at:NNnn #1#2#3#4 { \@@_split_at:nn {#3}{#4} @@ -3099,6 +4418,114 @@ manipulating PGF soft paths} \tl_gclear:N \g_@@_output_tl } \cs_generate_variant:Nn \spath_gsplit_at:NNnn {NNVn, NNVV, NNnV} +\cs_new_protected_nopar:Npn \spath_split_at_keep_start:Nnn #1#2#3 +{ + \@@_split_at:nn {#2}{#3} + \tl_set:Nx #1 {\tl_item:Nn \g_@@_output_tl {1}} + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_split_at_keep_start:Nnn {NVn} +\cs_new_protected_nopar:Npn \spath_split_at_keep_start:Nn #1#2 +{ + \spath_split_at_keep_start:NVn #1#1{#2} +} +\cs_new_protected_nopar:Npn \spath_gsplit_at_keep_start:Nnn #1#2#3 +{ + \@@_split_at:nn {#2}{#3} + \tl_gset:Nx #1 {\tl_item:Nn \g_@@_output_tl {1}} + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_gsplit_at_keep_start:Nnn {NVn} +\cs_new_protected_nopar:Npn \spath_gsplit_at_keep_start:Nn #1#2 +{ + \spath_gsplit_at_keep_start:NVn #1#1{#2} +} +\cs_new_protected_nopar:Npn \spath_split_at_keep_end:Nnn #1#2#3 +{ + \@@_split_at:nn {#2}{#3} + \tl_set:Nx #1 {\tl_item:Nn \g_@@_output_tl {2}} + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_split_at_keep_end:Nnn {NVn} +\cs_new_protected_nopar:Npn \spath_split_at_keep_end:Nn #1#2 +{ + \spath_split_at_keep_end:NVn #1#1{#2} +} +\cs_new_protected_nopar:Npn \spath_gsplit_at_keep_end:Nnn #1#2#3 +{ + \@@_split_at:nn {#2}{#3} + \tl_gset:Nx #1 {\tl_item:Nn \g_@@_output_tl {2}} + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_gsplit_at_keep_end:Nnn {NVn} +\cs_new_protected_nopar:Npn \spath_gsplit_at_keep_end:Nn #1#2 +{ + \spath_gsplit_at_keep_end:NVn #1#1{#2} +} +\cs_new_protected_nopar:Npn \spath_split_at_normalised:NNnn #1#2#3#4 +{ + \@@_split_at_normalised: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}} + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_split_at_normalised:NNnn {NNVn, NNVV, NNnV, ccvn} +\cs_new_protected_nopar:Npn \spath_gsplit_at_normalised:NNnn #1#2#3#4 +{ + \@@_split_at_normalised: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}} + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_gsplit_at_normalised:NNnn {NNVn, NNVV, NNnV, ccvn} +\cs_new_protected_nopar:Npn \spath_split_at_normalised_keep_start:Nnn #1#2#3 +{ + \@@_split_at_normalised:nn {#2}{#3} + \tl_set:Nx #1 {\tl_item:Nn \g_@@_output_tl {1}} + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_split_at_normalised_keep_start:Nnn {NVn} +\cs_new_protected_nopar:Npn \spath_split_at_normalised_keep_start:Nn #1#2 +{ + \spath_split_at_normalised_keep_start:NVn #1#1{#2} +} +\cs_generate_variant:Nn \spath_split_at_normalised_keep_start:Nn {cn} +\cs_new_protected_nopar:Npn \spath_gsplit_at_normalised_keep_start:Nnn #1#2#3 +{ + \@@_split_at_normalised:nn {#2}{#3} + \tl_gset:Nx #1 {\tl_item:Nn \g_@@_output_tl {1}} + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_gsplit_at_normalised_keep_start:Nnn {NVn} +\cs_new_protected_nopar:Npn \spath_gsplit_at_normalised_keep_start:Nn #1#2 +{ + \spath_gsplit_at_normalised_keep_start:NVn #1#1{#2} +} +\cs_generate_variant:Nn \spath_gsplit_at_normalised_keep_start:Nn {cn} +\cs_new_protected_nopar:Npn \spath_split_at_normalised_keep_end:Nnn #1#2#3 +{ + \@@_split_at_normalised:nn {#2}{#3} + \tl_set:Nx #1 {\tl_item:Nn \g_@@_output_tl {2}} + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_split_at_normalised_keep_end:Nnn {NVn} +\cs_new_protected_nopar:Npn \spath_split_at_normalised_keep_end:Nn #1#2 +{ + \spath_split_at_normalised_keep_end:NVn #1#1{#2} +} +\cs_generate_variant:Nn \spath_split_at_normalised_keep_end:Nn {cn} +\cs_new_protected_nopar:Npn \spath_gsplit_at_normalised_keep_end:Nnn #1#2#3 +{ + \@@_split_at_normalised:nn {#2}{#3} + \tl_gset:Nx #1 {\tl_item:Nn \g_@@_output_tl {2}} + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_gsplit_at_normalised_keep_end:Nnn {NVn} +\cs_new_protected_nopar:Npn \spath_gsplit_at_normalised_keep_end:Nn #1#2 +{ + \spath_gsplit_at_normalised_keep_end:NVn #1#1{#2} +} +\cs_generate_variant:Nn \spath_gsplit_at_normalised_keep_end:Nn {cn} % \end{macrocode} % % @@ -3133,6 +4560,38 @@ manipulating PGF soft paths} { \spath_gsplit_at:NVn #1#1{#2} } +\cs_new_protected_nopar:Npn \spath_split_at_normalised:Nnn #1#2#3 +{ + \@@_split_at_normalised:nn {#2}{#3} + \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_normalised:Nnn {NVn, NVV} +\cs_new_protected_nopar:Npn \spath_split_at_normalised:Nn #1#2 +{ + \spath_split_at_normalised:NVn #1#1{#2} +} +\cs_generate_variant:Nn \spath_split_at_normalised:Nn {cn} +\cs_new_protected_nopar:Npn \spath_gsplit_at_normalised:Nnn #1#2#3 +{ + \@@_split_at_normalised:nn {#2}{#3} + \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_normalised:Nnn {NVn, NVV} +\cs_new_protected_nopar:Npn \spath_gsplit_at_normalised:Nn #1#2 +{ + \spath_gsplit_at_normalised:NVn #1#1{#2} +} +\cs_generate_variant:Nn \spath_gsplit_at_normalised:Nn {cn} % \end{macrocode} % \end{macro} % @@ -3473,6 +4932,40 @@ manipulating PGF soft paths} % \end{macrocode} % \end{macro} % +% \begin{macro}[internal]{ +% \spath_shorten_at_both_ends:Nnn, +% \spath_shorten_at_both_ends:Nn, +% \spath_gshorten_at_both_ends:Nnn, +% \spath_gshorten_at_both_ends:Nn +% } +% +% This macro shortens a path from the start by a dimension. +% +% \begin{macrocode} +\cs_new_protected_nopar:Npn \spath_shorten_at_both_ends:Nnn #1#2#3 +{ + \spath_shorten_at_start:Nnn #1{#2}{#3} + \spath_shorten_at_end:Nnn #1{#2}{#3} +} +\cs_new_protected_nopar:Npn \spath_shorten_at_both_ends:Nn #1#2 +{ + \spath_shorten_at_start:Nn #1{#2} + \spath_shorten_at_end:Nn #1{#2} +} +\cs_generate_variant:Nn \spath_shorten_at_both_ends:Nn {cn, cV, NV} +\cs_new_protected_nopar:Npn \spath_gshorten_at_both_ends:Nnn #1#2#3 +{ + \spath_gshorten_at_start:Nnn #1{#2}{#3} + \spath_gshorten_at_end:Nnn #1{#2}{#3} +} +\cs_new_protected_nopar:Npn \spath_gshorten_at_both_ends:Nn #1#2 +{ + \spath_gshorten_at_start:Nn #1{#2} + \spath_gshorten_at_end:Nn #1{#2} +} +\cs_generate_variant:Nn \spath_gshorten_at_both_ends:Nn {cn, cV, NV} +% \end{macrocode} +% \end{macro} % % \subsection{Points on a Path} % @@ -3561,6 +5054,95 @@ manipulating PGF soft paths} } } + \c_spath_rectsize_tl + { + \fp_compare:nTF + { + \l_@@_tmpa_fp <= .25 + } + { + \tl_set:Nx \l_@@_tmpc_tl + { + {\fp_to_dim:n + { + ( \tl_item:Nn \l_@@_tmpa_tl {2} ) + + + 4 * \l_@@_tmpa_fp * ( \tl_item:Nn \l_@@_tmpa_tl {5} ) + } + } + {\fp_to_dim:n {\tl_item:Nn \l_@@_tmpa_tl {3} } } + } + } + { + \fp_compare:nTF + { + \l_@@_tmpa_fp <= .5 + } + { + \tl_set:Nx \l_@@_tmpc_tl + { + {\fp_to_dim:n + { + ( \tl_item:Nn \l_@@_tmpa_tl {2} ) + + + ( \tl_item:Nn \l_@@_tmpa_tl {5} ) + } + } + {\fp_to_dim:n + { + ( \tl_item:Nn \l_@@_tmpa_tl {3} ) + + + (4 * (\l_@@_tmpa_fp) - 1) * ( \tl_item:Nn \l_@@_tmpa_tl {6} ) + } + } + } + } + { + \fp_compare:nTF + { + \l_@@_tmpa_fp <= .75 + } + { + \tl_set:Nx \l_@@_tmpc_tl + { + {\fp_to_dim:n + { + ( \tl_item:Nn \l_@@_tmpa_tl {2} ) + + + (3 - 4 * (\l_@@_tmpa_fp)) *( \tl_item:Nn \l_@@_tmpa_tl {5} ) + } + } + {\fp_to_dim:n + { + ( \tl_item:Nn \l_@@_tmpa_tl {3} ) + + + ( \tl_item:Nn \l_@@_tmpa_tl {6} ) + } + } + } + + } + { + \tl_set:Nx \l_@@_tmpc_tl + { + {\fp_to_dim:n + { + ( \tl_item:Nn \l_@@_tmpa_tl {2} ) + } + } + {\fp_to_dim:n + { + ( \tl_item:Nn \l_@@_tmpa_tl {3} ) + + + (4 - 4 *(\l_@@_tmpa_fp)) * ( \tl_item:Nn \l_@@_tmpa_tl {6} ) + } + } + } + } + } + } + } + \c_spath_closepath_tl { \tl_set:Nx \l_@@_tmpc_tl @@ -3717,6 +5299,71 @@ manipulating PGF soft paths} } } + \c_spath_rectsize_tl + { + \fp_compare:nTF + { + \l_@@_tmpa_fp <= .25 + } + { + \tl_set:Nx \l_@@_tmpc_tl + { + {\fp_to_dim:n + { + \tl_item:Nn \l_@@_tmpa_tl {5} + } + } + {0pt} + } + } + { + \fp_compare:nTF + { + \l_@@_tmpa_fp <= .5 + } + { + \tl_set:Nx \l_@@_tmpc_tl + { + {0pt} + {\fp_to_dim:n + { + ( \tl_item:Nn \l_@@_tmpa_tl {6} ) + } + } + } + } + { + \fp_compare:nTF + { + \l_@@_tmpa_fp <= .75 + } + { + \tl_set:Nx \l_@@_tmpc_tl + { + {\fp_to_dim:n + { + -( \tl_item:Nn \l_@@_tmpa_tl {5} ) + } + } + {0pt} + } + + } + { + \tl_set:Nx \l_@@_tmpc_tl + { + {0pt} + {\fp_to_dim:n + { + - ( \tl_item:Nn \l_@@_tmpa_tl {6} ) + } + } + } + } + } + } + } + \c_spath_closepath_tl { \tl_set:Nx \l_@@_tmpc_tl @@ -3898,19 +5545,21 @@ manipulating PGF soft paths} \tl_set:Nn \l_@@_tmpb_tl {#1} \tl_set:Nn \l_@@_tmpc_tl {#2} - \spath_reallength:Nn \l_@@_tmpa_int {#1} - % Remember if the component is closed \spath_finalaction:NV \l_@@_tmpa_tl \l_@@_tmpb_tl - + \bool_set:Nn \l_@@_closed_bool { \tl_if_eq_p:NN \l_@@_tmpa_tl \c_spath_closepath_tl + || + \tl_if_eq_p:NN \l_@@_tmpa_tl \c_spath_rectcorner_tl } - + % Open it \spath_open:N \l_@@_tmpb_tl + \spath_reallength:NV \l_@@_tmpa_int \l_@@_tmpb_tl + % Sort intersections along the component \pgfintersectionsortbyfirstpath \spath_intersect:NN \l_@@_tmpb_tl \l_@@_tmpc_tl @@ -3933,6 +5582,7 @@ manipulating PGF soft paths} { \bool_set_false:N \l_@@_closed_bool } + \seq_get_right:NN \l_@@_tmpb_seq \l_@@_tmpa_tl \fp_compare:nT { @@ -3941,7 +5591,6 @@ manipulating PGF soft paths} { \bool_set_false:N \l_@@_closed_bool } - \tl_set:Nn \l_@@_tmpg_tl {-1} @@ -3989,6 +5638,7 @@ manipulating PGF soft paths} \tl_set_eq:NN \l_@@_tmpb_tl \l_@@_tmpe_tl } + \bool_if:NT \l_@@_closed_bool { \spath_join_component:Nn \l_@@_tmpb_tl {1} @@ -4847,6 +6497,7 @@ manipulating PGF soft paths} { \pgfsyssoftpath@getcurrentpath #1 } +\cs_generate_variant:Nn \spath_get_current_path:N {c} % \end{macrocode} % % \begin{macrocode} @@ -4855,6 +6506,7 @@ manipulating PGF soft paths} \pgfsyssoftpath@getcurrentpath #1 \tl_gset_eq:NN #1 #1 } +\cs_generate_variant:Nn \spath_gget_current_path:N {c} % \end{macrocode} % \end{macro} % @@ -4912,10 +6564,13 @@ manipulating PGF soft paths} % \begin{macrocode} \cs_new_protected_nopar:Npn \spath_tikz_path:nn #1#2 { - \path[#1] \pgfextra{ - \spath_set_current_path:n {#2} - \tl_put_right:Nn \tikz@preactions {\def\tikz@actions@path{#2}} - }; + \tl_if_empty:nF {#2} + { + \path[#1] \pgfextra{ + \spath_set_current_path:n {#2} + \tl_put_left:Nn \tikz@preactions {\def\tikz@actions@path{#2}} + }; + } } \cs_generate_variant:Nn \spath_tikz_path:nn {Vn, VV, nv, Vv, nV} % \end{macrocode} @@ -4929,8 +6584,8 @@ manipulating PGF soft paths} \spath_finalpoint:Nn \l_@@_tmpa_tl {#1} \tl_set:Nx \l_@@_tmpa_tl { - \exp_not:c {pgf@x}=\tl_item:Nn \l_@@_tmpa_tl {1} - \exp_not:c {pgf@y}=\tl_item:Nn \l_@@_tmpa_tl {2} + \exp_not:c {pgf@x}=\tl_item:Nn \l_@@_tmpa_tl {1} \relax + \exp_not:c {pgf@y}=\tl_item:Nn \l_@@_tmpa_tl {2} \relax } \use:c {pgf@process}{% \tl_use:N \l_@@_tmpa_tl @@ -4939,32 +6594,41 @@ manipulating PGF soft paths} } \tl_set:Nx \l_@@_tmpa_tl { - \exp_not:c {tikz@lastx}=\exp_not:c {pgf@x} - \exp_not:c {tikz@lasty}=\exp_not:c {pgf@y} - \exp_not:c {tikz@lastxsaved}=\exp_not:c {pgf@x} - \exp_not:c {tikz@lastysaved}=\exp_not:c {pgf@y} + \exp_not:c {tikz@lastx}=\exp_not:c {pgf@x} \relax + \exp_not:c {tikz@lasty}=\exp_not:c {pgf@y} \relax + \exp_not:c {tikz@lastxsaved}=\exp_not:c {pgf@x} \relax + \exp_not:c {tikz@lastysaved}=\exp_not:c {pgf@y} \relax } \tl_use:N \l_@@_tmpa_tl \spath_finalmovepoint:Nn \l_@@_tmpa_tl {#1} - \ifpgfsyssoftpathmovetorelevant% - \tl_gset_eq:cN {pgfsyssoftpath@lastmoveto} \l_@@_tmpa_tl - \fi + \bool_if:NT \l_spath_movetorelevant_bool + { + \ifpgfsyssoftpathmovetorelevant% + \tl_gset_eq:cN {pgfsyssoftpath@lastmoveto} \l_@@_tmpa_tl + \fi + } \tl_set:Nx \l_@@_tmpa_tl { - \exp_not:c {pgf@x}=\tl_item:Nn \l_@@_tmpa_tl {1} - \exp_not:c {pgf@y}=\tl_item:Nn \l_@@_tmpa_tl {2} + \exp_not:c {pgf@x}=\tl_item:Nn \l_@@_tmpa_tl {1} \relax + \exp_not:c {pgf@y}=\tl_item:Nn \l_@@_tmpa_tl {2} \relax } \use:c {pgf@process}{% \tl_use:N \l_@@_tmpa_tl \pgftransforminvert \use:c {pgf@pos@transform@glob} } - \tl_set:Nx \l_@@_tmpa_tl + \bool_if:NT \l_spath_movetorelevant_bool { - \exp_not:c {tikz@lastmovetox}=\exp_not:c {pgf@x} - \exp_not:c {tikz@lastmovetoy}=\exp_not:c {pgf@y} + \dim_if_exist:cT {tikz@lastmovetox} + { + \tl_set:Nx \l_@@_tmpa_tl + { + \exp_not:c {tikz@lastmovetox}=\exp_not:c {pgf@x} \relax + \exp_not:c {tikz@lastmovetoy}=\exp_not:c {pgf@y} \relax + } + \tl_use:N \l_@@_tmpa_tl + } } - \tl_use:N \l_@@_tmpa_tl \tl_clear_new:c {tikz@timer} \tl_set:cn {tikz@timer} { @@ -5028,6 +6692,11 @@ manipulating PGF soft paths} %<*tikzspath3> % \fi % +% \begin{macrocode} +%<@@=tikzspath> +% \end{macrocode} +% +% % This provides an interface to the soft path manipulation routines via a series of TikZ keys. % They all live in the \texttt{spath} family. % @@ -5037,24 +6706,44 @@ manipulating PGF soft paths} \RequirePackage{expl3} \ExplSyntaxOn +\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 + +\int_new:N \l_@@_tmpa_int +\seq_new:N \l_@@_tmpa_seq +\seq_new:N \l_@@_tmpb_seq +\seq_new:N \l_@@_tmpc_seq +\seq_new:N \l_@@_tmpd_seq + \tl_new:N \l_@@_current_tl \tl_new:N \l_@@_reverse_tl \tl_new:N \l_@@_prefix_tl \tl_new:N \l_@@_suffix_tl \tl_new:N \g_@@_smuggle_tl +\tl_new:N \g_@@_output_tl +\tl_new:N \l_@@_check_tl +\clist_new:N \g_@@_output_clist \seq_new:N \g_@@_tmpa_seq \seq_new:N \g_@@_tmpb_seq +\seq_new:N \g_@@_output_seq \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:nnnn { spath3 } { empty soft path } { Soft~ path~ #1~ is~ empty} +\msg_new:nnn { spath3 } { missing soft path } +{ Soft~ path~ #1~ doesn't~ exist~ \msg_line_context:} +\msg_new:nnnn { spath3 } { empty soft path } +{ Soft~ path~ #1~ is~ empty~ \msg_line_context:} {If~ it~ was~ defined~ inside~ a~ group,~ try~ using~ "save~ global". } \msg_new:nnn { spath3 } { load intersections } -{ You~ need~ to~ load~ the~ "intersections"~ library~ to~ work~ with~ intersections } +{ You~ need~ to~ load~ the~ "intersections"~ library~ + to~ work~ with~ intersections } % \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. @@ -5065,9 +6754,14 @@ manipulating PGF soft paths} % \end{macrocode} % % When a soft path is grabbed from TikZ we're usually deep in a group so I've adapted the code from the intersections library to dig the definition out of the group without making everything global. -% +% +% Interestingly, the intersections library doesn't clear its naming code once it is used meaning that it keeps resetting the definition of a path back to its original one every time a path command is called. +% +% Also, when the hook is restored outside a scope then no check is made to ensure that the inner one was actually invoked. +% This can cause issues when the syntax \Verb!\tikz .. ;! is used since the end of the path coincides with the end of the picture. % \begin{macrocode} \tl_new:N \g_@@_tikzfinish_tl +\tl_new:N \l_@@_tikzfinish_outside_tl \cs_new_protected_nopar:Npn \spath_at_end_of_path: { \tl_use:N \g_@@_tikzfinish_tl @@ -5075,8 +6769,43 @@ manipulating PGF soft paths} } \tl_put_right:Nn \tikz@finish {\spath_at_end_of_path:} +\tikzset{ + every~ scope/.append~ style={ + execute~ at~ begin~ scope={ + \tl_set_eq:NN \l_@@_tikzfinish_outside_tl \g_@@_tikzfinish_tl + }, + execute~ at~ end~ scope={ + \tl_use:N \g_@@_tikzfinish_tl + \tl_gclear:N \g_@@_tikzfinish_tl + \tl_gset_eq:NN \g_@@_tikzfinish_tl \l_@@_tikzfinish_outside_tl + }, + }, +} +% \end{macrocode} +% +% This is for delaying something until the path is fully constructed (but no later), sometimes useful to be able to specify this in the path options rather than directly at the end of the path. +% +% \begin{macrocode} +\tl_new:N \l_@@_tikzpath_finish_tl + +\cs_new_protected_nopar:Npn \@@_at_end_of_path_construction: +{ + \tl_use:N \l_@@_tikzpath_finish_tl + \tl_clear:N \l_@@_tikzpath_finish_tl +} + +\tl_put_left:Nn \tikz@finish {\@@_at_end_of_path_construction:} +% \end{macrocode} +% +% Code for saving a path +% +% \begin{macrocode} \cs_new_protected_nopar:Npn \spath_save_path:Nn #1#2 { + \tl_if_empty:NF \g_@@_tikzfinish_tl + { + \tl_use:N \g_@@_tikzfinish_tl + } \tl_gput_right:Nn \g_@@_tikzfinish_tl { \tl_clear_new:N #1 @@ -5127,6 +6856,228 @@ manipulating PGF soft paths} % \end{macrocode} % \end{macro} % +% \begin{macro}[internal]{ +% \@@_check_path:nnn +% \@@_check_two_paths:nnnn +% \@@_check_three_paths:nnnnn +% } +% Given a path name as the second argument, check if it exists and is not empty, and if so reinsert it after the first argument. +% The third argument is code to be executed in case of a missing or empty path. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_check_path:nnn #1#2#3 +{ + \tl_set:Nn \l_@@_check_tl {#3} + \tl_if_exist:cTF {\@@_path_name:n {#2}} + { + \tl_if_empty:cTF {\@@_path_name:n {#2}} + { + \msg_warning:nnn { spath3 } { empty soft path } { #2 } + } + { + \tl_set:Nn \l_@@_check_tl { + #1 {\@@_path_name:n {#2}} + } + } + } + { + \msg_warning:nnn { spath3 } { missing soft path } { #2 } + } + \tl_use:N \l_@@_check_tl +} +\cs_new_protected_nopar:Npn \@@_check_two_paths:nnnn #1#2#3#4 +{ + \@@_check_path:nnn { + \@@_check_path:nnn {#1}{#2}{#4} + }{#3}{#4} +} +\cs_new_protected_nopar:Npn \@@_check_three_paths:nnnnn #1#2#3#4#5 +{ + \@@_check_path:nnn { + \@@_check_path:nnn { + \@@_check_path:nnn {#1}{#2}{#5} + }{#3}{#5} + }{#4}{#5} +} +\cs_generate_variant:Nn \@@_check_path:nnn {nVn} +\cs_generate_variant:Nn \@@_check_two_paths:nnnn {nnVn} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{ +% \@@_maybe_current_path:nn +% \@@_maybe_current_path_reuse:nnn +% \@@_maybe_current_two_paths_reuse_both:nnnn +% \@@_maybe_current_two_paths_reuse_first:nnnn +% \@@_maybe_current_two_paths_reuse_second:nnnn +% } +% If the named path is ``current'' then get the current path and use that. +% The second version puts the resulting path back as the current path. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_maybe_current_path:nn #1#2 +{ + \tl_if_eq:nnT {#2} {current} + { + \spath_get_current_path:c {\@@_path_name:n {#2}} + } + #1 {#2} +} +\cs_new_protected_nopar:Npn \@@_maybe_current_path_reuse:nnn #1#2#3 +{ + \bool_set_true:N \l_spath_movetorelevant_bool + \tl_if_eq:nnT {#2} {current} + { + \spath_get_current_path:c {\@@_path_name:n {#2}} + } + #1 {#2} #3 + \tl_if_eq:nnT {#2} {current} + { + \tl_if_empty:cF {\@@_path_name:n {#2}} + { + \spath_set_current_path:c {\@@_path_name:n {#2}} + \spath_set_tikz_data:v {\@@_path_name:n {#2}} + } + } +} +\cs_new_protected_nopar:Npn \@@_maybe_current_two_paths_reuse_both:nnnn #1#2#3#4 +{ + \bool_set_true:N \l_spath_movetorelevant_bool + \tl_if_eq:nnT {#2} {current} + { + \spath_get_current_path:c {\@@_path_name:n {#2}} + } + \tl_if_eq:nnT {#3} {current} + { + \spath_get_current_path:c {\@@_path_name:n {#3}} + } + #1 {#2} {#3} #4 + \tl_if_eq:nnT {#2} {current} + { + \tl_if_empty:cF {\@@_path_name:n {#2}} + { + \spath_set_current_path:c {\@@_path_name:n {#2}} + \spath_set_tikz_data:v {\@@_path_name:n {#2}} + } + } + \tl_if_eq:nnT {#3} {current} + { + \tl_if_empty:cF {\@@_path_name:n {#3}} + { + \spath_set_current_path:c {\@@_path_name:n {#3}} + \spath_set_tikz_data:v {\@@_path_name:n {#3}} + } + } +} +\cs_new_protected_nopar:Npn \@@_maybe_current_two_paths_reuse_first:nnnn #1#2#3#4 +{ + \bool_set_true:N \l_spath_movetorelevant_bool + \tl_if_eq:nnT {#2} {current} + { + \spath_get_current_path:c {\@@_path_name:n {#2}} + } + \tl_if_eq:nnT {#3} {current} + { + \spath_get_current_path:c {\@@_path_name:n {#3}} + } + #1 {#2} {#3} #4 + \tl_if_eq:nnT {#2} {current} + { + \tl_if_empty:cF {\@@_path_name:n {#2}} + { + \spath_set_current_path:c {\@@_path_name:n {#2}} + \spath_set_tikz_data:v {\@@_path_name:n {#2}} + } + } +} +\cs_new_protected_nopar:Npn \@@_maybe_current_two_paths_reuse_second:nnnn #1#2#3#4 +{ + \bool_set_true:N \l_spath_movetorelevant_bool + \tl_if_eq:nnT {#2} {current} + { + \spath_get_current_path:c {\@@_path_name:n {#2}} + } + \tl_if_eq:nnT {#3} {current} + { + \spath_get_current_path:c {\@@_path_name:n {#3}} + } + #1 {#2} {#3} #4 + \tl_if_eq:nnT {#3} {current} + { + \tl_if_empty:cF {\@@_path_name:n {#3}} + { + \spath_set_current_path:c {\@@_path_name:n {#3}} + \spath_set_tikz_data:v {\@@_path_name:n {#3}} + } + } +} +\cs_generate_variant:Nn \@@_maybe_current_path:nn {nV} +\cs_generate_variant:Nn \@@_maybe_current_path_reuse:nnn {nVn} +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{ +% \@@_seq_from_foreach:NNn +% } +% +% Convert a PGF foreach list, as the third argument, to a sequence. +% The second argument is the maximum number on the list. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_seq_from_foreach:Nnn #1#2#3 +{ + \group_begin: + \seq_gclear:N \g_@@_output_seq + + \tl_if_empty:nTF {#3} + { + \int_step_inline:nnnn {1}{1} {#2} + { + \seq_gput_right:Nn \g_@@_output_seq {##1} + } + } + { + \foreach \l_@@_tmpa_tl in {#3} + { + \int_compare:nTF { \l_@@_tmpa_tl > 0 } + { + \seq_gput_right:NV \g_@@_output_seq \l_@@_tmpa_tl + } + { + \seq_gput_right:Nx \g_@@_output_seq + {\int_eval:n {#2 - \l_@@_tmpa_tl}} + } + } + \seq_gsort:Nn \g_@@_output_seq + { + \int_compare:nNnTF {##1} < {##2} + { \sort_return_same: } + { \sort_return_swapped: } + } + } + \group_end: + \seq_set_eq:NN #1 \g_@@_output_seq + \seq_gclear:N \g_@@_output_seq +} +\cs_generate_variant:Nn \@@_seq_from_foreach:Nnn {NVV, NVn} +% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{ +% \@@_path_name:n +% } +% Wrap the argument in the prefix and suffix to generate the proper name. +% \begin{macrocode} +\cs_new:Npn \@@_path_name:n #1 +{ + \tl_use:N \l_@@_prefix_tl + #1 + \tl_use:N \l_@@_suffix_tl +} +\cs_generate_variant:Nn \@@_path_name:n {V} +% \end{macrocode} +% \end{macro} +% % When joining two paths we provide a set of options for how to process the second path. % % \begin{macrocode} @@ -5134,6 +7085,7 @@ manipulating PGF soft paths} \bool_new:N \l_@@_weld_bool \bool_new:N \l_@@_move_bool \bool_new:N \l_@@_global_bool +\bool_new:N \l_@@_current_transformation_bool \tl_new:N \l_@@_joinpath_tl \tl_new:N \l_@@_transformation_tl @@ -5176,6 +7128,10 @@ manipulating PGF soft paths} \@@_set_bool:Nn \l_@@_global_bool {#1} }, global/.default = true, + use~ current~ transformation/.code={ + \@@_set_bool:Nn \l_@@_current_transformation_bool {#1} + }, + use~ current~ transformation/.default = true, transform/.store~in=\l_@@_transformation_tl, .unknown/.code = { \tl_set_eq:NN \l_@@_joinpath_tl \pgfkeyscurrentname @@ -5191,6 +7147,766 @@ manipulating PGF soft paths} \cs_set_eq:NN \getComponentOf \clist_item:Nn % \end{macrocode} % +% \subsection{Helper Functions} +% +% \begin{macro}[internal]{ +% \@@_use_path:n +% } +% Use a path, possibly manipulating it first. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_use_path:n #1 +{ + \tl_set:Nn \l_@@_joinpath_tl {#1} + \spath_get_current_path:N \l_@@_current_tl + + \bool_if:NT \l_@@_reverse_bool + { + \spath_reverse:N \l_@@_joinpath_tl + } + + \bool_if:NT \l_@@_current_transformation_bool + { + \pgfgettransform \l_@@_tmpa_tl + \spath_transform:NV + \l_@@_joinpath_tl + \l_@@_tmpa_tl + } + + \tl_if_empty:NF \l_@@_transformation_tl + { + \group_begin: + \pgftransformreset + \@@_tikzset:V \l_@@_transformation_tl + \pgfgettransform \l_@@_tmpa_tl + \tl_gset:Nn \g_@@_smuggle_tl + { + \spath_transform:Nnnnnnn + \l_@@_joinpath_tl + } + \tl_gput_right:NV \g_@@_smuggle_tl \l_@@_tmpa_tl + \group_end: + \tl_use:N \g_@@_smuggle_tl + } + + \bool_if:NT \l_@@_move_bool + { + \tl_if_empty:NTF \l_@@_current_tl + { + \tl_set:Nn \l_@@_tmpc_tl { {0pt} {0pt} } + } + { + \spath_finalpoint:NV + \l_@@_tmpc_tl + \l_@@_current_tl + } + \spath_translate_to:NV \l_@@_joinpath_tl \l_@@_tmpc_tl + } + + \tl_if_empty:NTF \l_@@_current_tl + { + \tl_if_empty:NTF \l_@@_joinpath_tl + { + \tl_set_eq:NN \l_@@_current_tl \c_spath_moveto_tl + \tl_put_right:Nn \l_@@_current_tl {{0pt}{0pt}} + } + { + \tl_set_eq:NN \l_@@_current_tl \l_@@_joinpath_tl + } + } + { + + \tl_clear:N \l_@@_tmpa_tl + \tl_set:Nn \l_@@_tmpa_tl {spath_} + + \tl_put_right:Nn \l_@@_tmpa_tl {append} + + \bool_if:NT \l_@@_weld_bool + { + \tl_put_right:Nn \l_@@_tmpa_tl {_no_move} + \spath_numberofcomponents:NV \l_@@_tmpa_int \l_@@_joinpath_tl + \int_compare:nT {\l_@@_tmpa_int == 1} + { + \bool_set_false:N \l_spath_movetorelevant_bool + } + } + \tl_put_right:Nn \l_@@_tmpa_tl {:NV} + + \use:c {\tl_use:N \l_@@_tmpa_tl } + \l_@@_current_tl + \l_@@_joinpath_tl + } + + \spath_set_current_path:N \l_@@_current_tl + \spath_set_tikz_data:V \l_@@_joinpath_tl +} +\cs_generate_variant:Nn \@@_use_path:n {V, v} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}[internal]{ +% \@@_join_with:nn +% } +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_join_with:Nn #1#2 +{ + \tl_set:Nn \l_@@_joinpath_tl {#2} + + \bool_if:NT \l_@@_reverse_bool + { + \spath_reverse:N \l_@@_joinpath_tl + } + + \tl_if_empty:NF \l_@@_transformation_tl + { + \group_begin: + \pgftransformreset + \@@_tikzset:V \l_@@_transformation_tl + \pgfgettransform \l_@@_tmpa_tl + \tl_gset:Nn \g_@@_smuggle_tl + { + \spath_transform:Nnnnnnn + \l_@@_joinpath_tl + } + \tl_gput_right:NV \g_@@_smuggle_tl \l_@@_tmpa_tl + \group_end: + \tl_use:N \g_@@_smuggle_tl + } + + \bool_if:NT \l_@@_move_bool + { + \spath_finalpoint:NV + \l_@@_tmpc_tl + #1 + \spath_translate_to:NV \l_@@_joinpath_tl \l_@@_tmpc_tl + } + + \tl_clear:N \l_@@_tmpa_tl + \tl_set:Nn \l_@@_tmpa_tl {spath_} + + \bool_if:NT \l_@@_global_bool + { + \tl_put_right:Nn \l_@@_tmpa_tl {g} + } + + \tl_put_right:Nn \l_@@_tmpa_tl {append} + + \bool_if:NT \l_@@_weld_bool + { + \tl_put_right:Nn \l_@@_tmpa_tl {_no_move} + } + \tl_put_right:Nn \l_@@_tmpa_tl {:NV} + + \cs_if_exist:cF {\tl_use:N \l_@@_tmpa_tl} + { + \tl_show:N \l_@@_tmpa_tl + } + + \use:c {\tl_use:N \l_@@_tmpa_tl } #1 + \l_@@_joinpath_tl +} +\cs_generate_variant:Nn \@@_join_with:Nn {cv, cn} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{ +% \@@_join_components_with:Nnn +% \@@_join_components_upright_with:Nnn +% } +% Join the specified components of the first path by splicing in the second. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_join_components_with_aux:nnn #1#2#3 +{ + \group_begin: + \tl_set:Nn \l_@@_tmpc_tl {#1} + \tl_if_empty:nT {#3} + { + \spath_spot_weld_components:N \l_@@_tmpc_tl + } + + \spath_numberofcomponents:NV \l_@@_tmpa_int \l_@@_tmpc_tl + \@@_seq_from_foreach:NVn \l_@@_tmpb_seq \l_@@_tmpa_int {#3} + + \spath_components_to_seq:NV \l_@@_tmpa_seq \l_@@_tmpc_tl + + \seq_pop_left:NN \l_@@_tmpa_seq \l_@@_tmpa_tl + \seq_pop_left:NN \l_@@_tmpb_seq \l_@@_tmpb_tl + + \seq_map_indexed_inline:Nn \l_@@_tmpa_seq + { + \int_compare:nTF + { + ##1 == \l_@@_tmpb_tl + } + { + \seq_pop_left:NNF \l_@@_tmpb_seq \l_@@_tmpb_tl + { + \tl_set:Nn \l_@@_tmpb_tl {-1} + } + \spath_splice_between:Nnn \l_@@_tmpa_tl {#2} {##2} + } + { + \tl_put_right:Nn \l_@@_tmpa_tl {##2} + } + } + \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpa_tl + \group_end: +} +\cs_new_protected_nopar:Npn \@@_join_components_with:Nnnn #1#2#3#4 +{ + \@@_join_components_with_aux:nnn {#2}{#3}{#4} + \tl_set_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \@@_join_components_with:Nnnn {NVnn} +\cs_new_protected_nopar:Npn \@@_join_components_with:Nnn #1#2#3 +{ + \@@_join_components_with:NVnn #1#1{#2}{#3} +} +\cs_generate_variant:Nn \@@_join_components_with:Nnn {cvV} +\cs_new_protected_nopar:Npn \@@_gjoin_components_with:Nnnn #1#2#3#4 +{ + \@@_join_components_with_aux:nnn {#2}{#3}{#4} + \tl_gset_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \@@_gjoin_components_with:Nnnn {NVnn} +\cs_new_protected_nopar:Npn \@@_gjoin_components_with:Nnn #1#2#3 +{ + \@@_gjoin_components_with:NVnn #1#1{#2}{#3} +} +\cs_generate_variant:Nn \@@_gjoin_components_with:Nnn {cvV} +\cs_new_protected_nopar:Npn \@@_join_components_upright_with_aux:nnn #1#2#3 +{ + \group_begin: + \tl_set:Nn \l_@@_tmpc_tl {#1} + \tl_if_empty:nT {#3} + { + \spath_spot_weld_components:N \l_@@_tmpc_tl + } + + \spath_numberofcomponents:NV \l_@@_tmpa_int \l_@@_tmpc_tl + \@@_seq_from_foreach:NVn \l_@@_tmpb_seq \l_@@_tmpa_int {#3} + + \spath_components_to_seq:NV \l_@@_tmpa_seq \l_@@_tmpc_tl + + \seq_pop_left:NN \l_@@_tmpa_seq \l_@@_tmpa_tl + \seq_pop_left:NN \l_@@_tmpb_seq \l_@@_tmpb_tl + + \tl_set:Nn \l_@@_tmpc_tl {#2} + \spath_transform:NVnnnnnn \l_@@_tmpd_tl \l_@@_tmpc_tl {1}{0}{0}{-1}{0pt}{0pt} + + \seq_map_indexed_inline:Nn \l_@@_tmpa_seq + { + \int_compare:nTF + { + ##1 == \l_@@_tmpb_tl + } + { + \seq_pop_left:NNF \l_@@_tmpb_seq \l_@@_tmpb_tl + { + \tl_set:Nn \l_@@_tmpb_tl {-1} + } + + \spath_finalpoint:NV \l_@@_tmpe_tl \l_@@_tmpa_tl + \spath_initialpoint:Nn \l_@@_tmpf_tl {##2} + + \dim_compare:nTF + { + \tl_item:Nn \l_@@_tmpe_tl {1} + > + \tl_item:Nn \l_@@_tmpf_tl {1} + } + { + \spath_splice_between:NVn + \l_@@_tmpa_tl + \l_@@_tmpd_tl + {##2} + } + { + \spath_splice_between:NVn + \l_@@_tmpa_tl + \l_@@_tmpc_tl + {##2} + } + } + { + \tl_put_right:Nn \l_@@_tmpa_tl {##2} + } + } + \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpa_tl + \group_end: +} +\cs_new_protected_nopar:Npn \@@_join_components_upright_with:Nnnn #1#2#3#4 +{ + \@@_join_components_upright_with_aux:nnn {#2}{#3}{#4} + \tl_set_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \@@_join_components_upright_with:Nnnn {NVnn} +\cs_new_protected_nopar:Npn \@@_join_components_upright_with:Nnn #1#2#3 +{ + \@@_join_components_upright_with:NVnn #1#1{#2}{#3} +} +\cs_generate_variant:Nn \@@_join_components_upright_with:Nnn {cvV} +\cs_new_protected_nopar:Npn \@@_gjoin_components_upright_with:Nnnn #1#2#3#4 +{ + \@@_join_components_upright_with_aux:nnn {#2}{#3}{#4} + \tl_gset_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \@@_gjoin_components_upright_with:Nnnn {NVnn} +\cs_new_protected_nopar:Npn \@@_gjoin_components_upright_with:Nnn #1#2#3 +{ + \@@_gjoin_components_upright_with:NVnn #1#1{#2}{#3} +} +\cs_generate_variant:Nn \@@_gjoin_components_upright_with:Nnn {cvV} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{ +% \@@_get_components:Nn +% } +% Get the components of the named path to the token list. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_get_components_aux:n #1 +{ + \clist_gclear_new:N \g_@@_output_clist + \spath_components_to_seq:Nn \l_@@_tmpa_seq {#1} + + \seq_map_inline:Nn \l_@@_tmpa_seq + { + \spath_anonymous:N \l_@@_tmpa_tl + \tl_new:c {\@@_path_name:V \l_@@_tmpa_tl} + \tl_set:cn {\@@_path_name:V \l_@@_tmpa_tl} {##1} + \clist_gput_right:NV \g_@@_output_clist \l_@@_tmpa_tl + } +} +\cs_new_protected_nopar:Npn \@@_get_components:Nn #1#2 +{ + \clist_clear_new:N #1 + \@@_get_components_aux:n {#2} + \clist_set_eq:NN #1 \g_@@_output_clist + \clist_gclear:N \g_@@_output_clist +} +\cs_generate_variant:Nn \@@_get_components:Nn {NV, Nv} +\cs_new_protected_nopar:Npn \@@_gget_components:Nn #1#2 +{ + \clist_gclear_new:N #1 + \@@_get_components_aux:n {#2} + \clist_gset_eq:NN #1 \g_@@_output_clist + \clist_gclear:N \g_@@_output_clist +} +\cs_generate_variant:Nn \@@_gget_components:Nn {NV, Nv} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{ +% \@@_render_components:n +% } +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_render_components:nn #1#2 +{ + \group_begin: + \spath_components_to_seq:Nn \l_@@_tmpa_seq {#2} + \seq_map_indexed_inline:Nn \l_@@_tmpa_seq + { + \spath_tikz_path:nn + { + every~ spath~ component/.try, + spath ~component~ ##1/.try, + spath ~component/.try={##1}, + every~ #1~ component/.try, + #1 ~component~ ##1/.try, + #1 ~component/.try={##1}, + } + { + ##2 + } + } + \group_end: +} +\cs_generate_variant:Nn \@@_render_components:nn {nv} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{ +% \@@_insert_gaps_after_components:nn +% } +% +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_insert_gaps_after_components_aux:nnn #1#2#3 +{ + \group_begin: + \spath_numberofcomponents:Nn \l_@@_tmpa_int {#1} + \@@_seq_from_foreach:NVn \l_@@_tmpa_seq \l_@@_tmpa_int {#3} + + \tl_if_empty:nT {#3} + { + \seq_pop_right:NN \l_@@_tmpa_seq \l_@@_tmpa_tl + } + + \seq_clear:N \l_@@_tmpb_seq + \seq_map_inline:Nn \l_@@_tmpa_seq { + \seq_put_right:Nx + \l_@@_tmpb_seq + {\int_eval:n + { + \int_mod:nn { ##1 }{ \l_@@_tmpa_int } + 1 + } + } + } + + \spath_components_to_seq:Nn \l_@@_tmpc_seq {#1} + + \seq_clear:N \l_@@_tmpd_seq + \seq_map_indexed_inline:Nn \l_@@_tmpc_seq + { + \tl_set:Nn \l_@@_tmpa_tl {##2} + \seq_if_in:NnT \l_@@_tmpa_seq {##1} + { + \spath_shorten_at_end:Nn \l_@@_tmpa_tl {(#2)/2} + } + \seq_if_in:NnT \l_@@_tmpb_seq {##1} + { + \spath_shorten_at_start:Nn \l_@@_tmpa_tl {(#2)/2} + } + \seq_put_right:NV \l_@@_tmpd_seq \l_@@_tmpa_tl + } + \tl_gset:Nx \g_@@_output_tl {\seq_use:Nn \l_@@_tmpd_seq {} } + \group_end: +} +\cs_new_protected_nopar:Npn \@@_insert_gaps_after_components:Nnnn #1#2#3#4 +{ + \@@_insert_gaps_after_components_aux:nnn {#2}{#3}{#4} + \tl_set_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \@@_insert_gaps_after_components:Nnnn {NVnn} +\cs_new_protected_nopar:Npn \@@_insert_gaps_after_components:Nnn #1#2#3 +{ + \@@_insert_gaps_after_components:NVnn #1#1{#2}{#3} +} +\cs_generate_variant:Nn \@@_insert_gaps_after_components:Nnn {cnn, cVV} +\cs_new_protected_nopar:Npn \@@_ginsert_gaps_after_components:Nnnn #1#2#3#4 +{ + \@@_insert_gaps_after_components_aux:nnn {#2}{#3}{#4} + \tl_gset_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \@@_ginsert_gaps_after_components:Nnnn {NVnn} +\cs_new_protected_nopar:Npn \@@_ginsert_gaps_after_components:Nnn #1#2#3 +{ + \@@_ginsert_gaps_after_components:NVnn #1#1{#2}{#3} +} +\cs_generate_variant:Nn \@@_ginsert_gaps_after_components:Nnn {cnn, cVV} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{ +% \@@_insert_gaps_after_segments:Nn +% } +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_insert_gaps_after_segments_aux:nnn #1#2#3 +{ + \group_begin: + \spath_reallength:Nn \l_@@_tmpa_int {#1} + \@@_seq_from_foreach:NVn \l_@@_tmpa_seq \l_@@_tmpa_int {#3} + + \tl_if_empty:nT {#3} + { + \seq_pop_right:NN \l_@@_tmpb_seq \l_@@_tmpa_tl + } + + \seq_clear:N \l_@@_tmpb_seq + \seq_map_inline:Nn \l_@@_tmpa_seq { + \seq_put_right:Nx + \l_@@_tmpb_seq + {\int_eval:n + { + \int_mod:nn { ##1 }{ \l_@@_tmpa_int } + 1 + } + } + } + + \spath_segments_to_seq:Nn \l_@@_tmpc_seq {#1} + + \seq_clear:N \l_@@_tmpd_seq + \seq_map_indexed_inline:Nn \l_@@_tmpc_seq + { + \tl_set:Nn \l_@@_tmpa_tl {##2} + \seq_if_in:NnT \l_@@_tmpa_seq {##1} + { + \spath_shorten_at_end:Nn \l_@@_tmpa_tl {(#2)/2} + } + \seq_if_in:NnT \l_@@_tmpb_seq {##1} + { + \spath_shorten_at_start:Nn \l_@@_tmpa_tl {(#2)/2} + } + \seq_put_right:NV \l_@@_tmpd_seq \l_@@_tmpa_tl + } + \tl_gset:Nx \g_@@_output_tl {\seq_use:Nn \l_@@_tmpd_seq {} } + \group_end: +} +\cs_new_protected_nopar:Npn \@@_insert_gaps_after_segments:Nnnn #1#2#3#4 +{ + \@@_insert_gaps_after_segments_aux:nnn {#2}{#3}{#4} + \tl_set_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \@@_insert_gaps_after_segments:Nnnn {NVnn} +\cs_new_protected_nopar:Npn \@@_insert_gaps_after_segments:Nnn #1#2#3 +{ + \@@_insert_gaps_after_segments:NVnn #1#1{#2}{#3} +} +\cs_generate_variant:Nn \@@_insert_gaps_after_segments:Nnn {cnn, cVV} +\cs_new_protected_nopar:Npn \@@_ginsert_gaps_after_segments:Nnnn #1#2#3#4 +{ + \@@_insert_gaps_after_segments_aux:nnn {#2}{#3}{#4} + \tl_gset_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \@@_ginsert_gaps_after_segments:Nnnn {NVnn} +\cs_new_protected_nopar:Npn \@@_ginsert_gaps_after_segments:Nnn #1#2#3 +{ + \@@_ginsert_gaps_after_segments:NVnn #1#1{#2}{#3} +} +\cs_generate_variant:Nn \@@_ginsert_gaps_after_segments:Nnn {cnn, cVV} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{ +% \@@_join_components:Nn +% } +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_join_components_aux:nn #1#2 +{ + \group_begin: + + \tl_set:Nn \l_@@_tmpa_tl {#1} + \spath_numberofcomponents:NV \l_@@_tmpa_int \l_@@_tmpa_tl + \@@_seq_from_foreach:NVn \l_@@_tmpa_seq \l_@@_tmpa_int {#2} + + \seq_reverse:N \l_@@_tmpa_seq + + \seq_map_inline:Nn \l_@@_tmpa_seq + { + \spath_join_component:Nn \l_@@_tmpa_tl {##1} + } + \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpa_tl + \group_end: +} +\cs_new_protected_nopar:Npn \@@_join_components:Nnn #1#2#3 +{ + \@@_join_components_aux:nn {#2}{#3} + \tl_set_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \@@_join_components:Nnn {NVn} +\cs_new_protected_nopar:Npn \@@_join_components:Nn #1#2 +{ + \@@_join_components:NVn #1#1{#2} +} +\cs_generate_variant:Nn \@@_join_components:Nn {cn} +\cs_new_protected_nopar:Npn \@@_gjoin_components:Nnn #1#2#3 +{ + \@@_join_components_aux:nn {#2}{#3} + \tl_gset_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \@@_gjoin_components:Nnn {NVn} +\cs_new_protected_nopar:Npn \@@_gjoin_components:Nn #1#2 +{ + \@@_gjoin_components:NVn #1#1{#2} +} +\cs_generate_variant:Nn \@@_gjoin_components:Nn {cn} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{ +% \@@_join_components_with_bezier:Nn +% } +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_join_components_with_bezier_aux:nn #1#2 +{ + \group_begin: + \tl_set:Nn \l_@@_tmpc_tl {#1} + \tl_if_empty:nT {#2} + { + \spath_spot_weld_components:N \l_@@_tmpc_tl + } + + \spath_numberofcomponents:NV \l_@@_tmpa_int \l_@@_tmpc_tl + \@@_seq_from_foreach:NVn \l_@@_tmpb_seq \l_@@_tmpa_int {#2} + + \spath_components_to_seq:NV \l_@@_tmpa_seq \l_@@_tmpc_tl + + \seq_pop_left:NN \l_@@_tmpa_seq \l_@@_tmpa_tl + \seq_pop_left:NN \l_@@_tmpb_seq \l_@@_tmpb_tl + + \seq_map_indexed_inline:Nn \l_@@_tmpa_seq + { + \int_compare:nTF + { + ##1 == \l_@@_tmpb_tl + } + { + \seq_pop_left:NNF \l_@@_tmpb_seq \l_@@_tmpb_tl + { + \tl_set:Nn \l_@@_tmpb_tl {-1} + } + \spath_curve_between:Nn \l_@@_tmpa_tl {##2} + } + { + \tl_put_right:Nn \l_@@_tmpa_tl {##2} + } + } + \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpa_tl + \group_end: +} +\cs_new_protected_nopar:Npn \@@_join_components_with_bezier:Nnn #1#2#3 +{ + \@@_join_components_with_bezier_aux:nn {#2}{#3} + \tl_set_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \@@_join_components_with_bezier:Nnn {NVn} +\cs_new_protected_nopar:Npn \@@_join_components_with_bezier:Nn #1#2 +{ + \@@_join_components_with_bezier:NVn #1#1{#2} +} +\cs_generate_variant:Nn \@@_join_components_with_bezier:Nn {cV} +\cs_new_protected_nopar:Npn \@@_gjoin_components_with_bezier:Nnn #1#2#3 +{ + \@@_join_components_with_bezier_aux:nn {#2}{#3} + \tl_gset_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \@@_gjoin_components_with_bezier:Nnn {NVn} +\cs_new_protected_nopar:Npn \@@_gjoin_components_with_bezier:Nn #1#2 +{ + \@@_gjoin_components_with_bezier:NVn #1#1{#2} +} +\cs_generate_variant:Nn \@@_gjoin_components_with_bezier:Nn {cV} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{ +% \@@_remove_components:nn +% } +% +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_remove_components_aux:nn #1#2 +{ + \group_begin: + + \spath_numberofcomponents:Nn \l_@@_tmpa_int {#1} + \@@_seq_from_foreach:NVn \l_@@_tmpa_seq \l_@@_tmpa_int {#2} + + \spath_components_to_seq:Nn \l_@@_tmpb_seq {#1} + + \seq_pop_left:NNF \l_@@_tmpa_seq \l_@@_tmpa_tl + { + \tl_clear:N \l_@@_tmpa_tl + } + + \seq_clear:N \l_@@_tmpc_seq + \seq_map_indexed_inline:Nn \l_@@_tmpb_seq + { + \tl_set:Nn \l_@@_tmpb_tl {##1} + \tl_if_eq:NNTF \l_@@_tmpb_tl \l_@@_tmpa_tl + { + \seq_pop_left:NNF \l_@@_tmpa_seq \l_@@_tmpa_tl + { + \tl_clear:N \l_@@_tmpa_tl + } + } + { + \seq_put_right:Nn \l_@@_tmpc_seq {##2} + } + } + + \tl_gset:Nx \g_@@_output_tl {\seq_use:Nn \l_@@_tmpc_seq {} } + \group_end: +} +\cs_new_protected_nopar:Npn \@@_remove_components:Nnn #1#2#3 +{ + \@@_remove_components_aux:nn {#2}{#3} + \tl_set_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \@@_remove_components:Nnn {NVn} +\cs_new_protected_nopar:Npn \@@_remove_components:Nn #1#2 +{ + \@@_remove_components:NVn #1#1{#2} +} +\cs_generate_variant:Nn \@@_remove_components:Nn {cn} +\cs_new_protected_nopar:Npn \@@_gremove_components:Nnn #1#2#3 +{ + \@@_remove_components_aux:nn {#2}{#3} + \tl_gset_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \@@_gremove_components:Nnn {NVn} +\cs_new_protected_nopar:Npn \@@_gremove_components:Nn #1#2 +{ + \@@_gremove_components:NVn #1#1{#2} +} +\cs_generate_variant:Nn \@@_gremove_components:Nn {cn} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}[internal]{ +% \@@_transform_to:nn, +% \@@_transform_upright_to:nn +% } +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_transform_to_aux:nn #1#2 +{ + \group_begin: + \spath_reallength:Nn \l_@@_tmpa_int {#2} + + \tl_set:Nx \l_@@_tmpb_tl + {\fp_to_decimal:n {(#1) * (\l_@@_tmpa_int)}} + \spath_transformation_at:NnV \l_@@_tmpc_tl {#2} \l_@@_tmpb_tl + \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpc_tl + \group_end: +} +\cs_new_protected_nopar:Npn \@@_transform_to:nn #1#2 +{ + \@@_transform_to_aux:nn {#1}{#2} + \exp_last_unbraced:NV \pgfsettransformentries \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \@@_transform_to:nn {nv} +\cs_new_protected_nopar:Npn \@@_transform_upright_to:nn #1#2 +{ + \@@_transform_to_aux:nn {#1}{#2} + \fp_compare:nT { \tl_item:Nn \g_@@_output_tl {4} < 0} + { + \tl_gset:Nx \g_@@_output_tl + { + { \fp_eval:n { - (\tl_item:Nn \g_@@_output_tl {1})} } + { \fp_eval:n { - (\tl_item:Nn \g_@@_output_tl {2})} } + { \fp_eval:n { - (\tl_item:Nn \g_@@_output_tl {3})} } + { \fp_eval:n { - (\tl_item:Nn \g_@@_output_tl {4})} } + { \tl_item:Nn \g_@@_output_tl {5} } + { \tl_item:Nn \g_@@_output_tl {6} } + } + } + \exp_last_unbraced:NV \pgfsettransformentries \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \@@_transform_upright_to:nn {nv} +% \end{macrocode} +% \end{macro} +% +% +% +% \subsection{Keys} % Now we define all of our keys. % % \begin{macrocode} @@ -5224,6 +7940,14 @@ manipulating PGF soft paths} }, % \end{macrocode} % +% Hook in to the end of the path construction +% +% \begin{macrocode} + at~ end~ path~ construction/.code={ + \tl_put_right:Nn \l_@@_tikzpath_finish_tl {#1} + }, +% \end{macrocode} +% % Keys for saving and cloning a soft path. % % \begin{macrocode} @@ -5231,8 +7955,8 @@ manipulating PGF soft paths} \tikz@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} + \spath_bake_shorten:NV \l_@@_tmpa_tl \l_@@_tmpa_tl + \spath_save_path:cV {\@@_path_name:n {#1}} \l_@@_tmpa_tl } }, @@ -5240,38 +7964,30 @@ manipulating PGF soft paths} \tikz@addmode{ \spath_get_current_path:N \l_@@_tmpa_tl \spath_bake_round:NV \l_@@_tmpa_tl \l_@@_tmpa_tl - \spath_gsave_path:cV - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \spath_bake_shorten:NV \l_@@_tmpa_tl \l_@@_tmpa_tl + \spath_gsave_path:cV {\@@_path_name:n {#1}} \l_@@_tmpa_tl } }, clone/.code~ 2~ args={ - \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} - \tl_set_eq: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} - } + \@@_maybe_current_path:nn { - \msg_warning:nnn { spath3 } { missing soft path } { #2 } + \@@_check_path:nnn { + \tl_clear_new:c {\@@_path_name:n {#1}} + \tl_set_eq:cc {\@@_path_name:n {#1}} + } } + {#2}{} }, clone~ global/.code~ 2~ args={ - \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} - \tl_gset_eq: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} - } + \@@_maybe_current_path:nn { - \msg_warning:nnn { spath3 } { missing soft path } { #2 } + \@@_check_path:nnn { + \tl_gclear_new:c {\@@_path_name:n {#1}} + \tl_gset_eq:cc {\@@_path_name:n {#1}} + } } + {#2}{} }, % \end{macrocode} % @@ -5279,15 +7995,14 @@ manipulating PGF soft paths} % % \begin{macrocode} save~ to~ aux/.code={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \@@_maybe_current_path:nn { - \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 } + \@@_check_path:nnn { + \spath_save_to_aux:c + } } + {#1} + {} }, % \end{macrocode} % @@ -5295,15 +8010,14 @@ manipulating PGF soft paths} % % \begin{macrocode} export~ to~ svg/.code={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - { - \spath_export_to_svg:nv {#1} - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - } + \@@_maybe_current_path:nn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } + \@@_check_path:nnn { + \spath_export_to_svg:nv {#1} + } } + {#1} + {} }, % \end{macrocode} % @@ -5317,6 +8031,8 @@ manipulating PGF soft paths} \bool_set_false:N \l_@@_reverse_bool \bool_set_false:N \l_@@_weld_bool \bool_set_false:N \l_@@_move_bool + \bool_set_false:N \l_@@_current_transformation_bool + \bool_set_true:N \l_spath_movetorelevant_bool \tl_clear:N \l_@@_joinpath_tl \tl_clear:N \l_@@_transformation_tl \tikzset{ @@ -5324,103 +8040,11 @@ manipulating PGF soft paths} #1 } - \tl_if_exist:cTF + \@@_check_path:nVn { - \tl_use:N \l_@@_prefix_tl - \tl_use:N \l_@@_joinpath_tl - \tl_use:N \l_@@_suffix_tl - } - { - \tl_if_empty:cT - { - \tl_use:N \l_@@_prefix_tl - \tl_use:N \l_@@_joinpath_tl - \tl_use:N \l_@@_suffix_tl - } - { - \msg_warning:nnn { spath3 } { empty soft path } { #1 } - } - \tl_set_eq:Nc \l_@@_joinpath_tl - { - \tl_use:N \l_@@_prefix_tl - \tl_use:N \l_@@_joinpath_tl - \tl_use:N \l_@@_suffix_tl - } - \spath_get_current_path:N \l_@@_current_tl - - \bool_if:NT \l_@@_reverse_bool - { - \spath_reverse:N \l_@@_joinpath_tl - } - - \tl_if_empty:NF \l_@@_transformation_tl - { - \group_begin: - \pgftransformreset - \@@_tikzset:V \l_@@_transformation_tl - \pgfgettransform \l_@@_tmpa_tl - \tl_gset:Nn \g_@@_smuggle_tl - { - \spath_transform:Nnnnnnn - \l_@@_joinpath_tl - } - \tl_gput_right:NV \g_@@_smuggle_tl \l_@@_tmpa_tl - \group_end: - \tl_use:N \g_@@_smuggle_tl - } - - \bool_if:NT \l_@@_move_bool - { - \tl_if_empty:NTF \l_@@_current_tl - { - \tl_set:Nn \l_@@_tmpc_tl { {0pt} {0pt} } - } - { - \spath_finalpoint:NV - \l_@@_tmpc_tl - \l_@@_current_tl - } - \spath_translate_to:NV \l_@@_joinpath_tl \l_@@_tmpc_tl - } - - \tl_if_empty:NTF \l_@@_current_tl - { - \tl_if_empty:NTF \l_@@_joinpath_tl - { - \tl_set_eq:NN \l_@@_current_tl \c_spath_moveto_tl - \tl_put_right:Nn \l_@@_current_tl {{0pt}{0pt}} - } - { - \tl_set_eq:NN \l_@@_current_tl \l_@@_joinpath_tl - } - } - { - - \tl_clear:N \l_@@_tmpa_tl - \tl_set:Nn \l_@@_tmpa_tl {spath_} - - \tl_put_right:Nn \l_@@_tmpa_tl {append} - - \bool_if:NT \l_@@_weld_bool - { - \tl_put_right:Nn \l_@@_tmpa_tl {_no_move} - } - \tl_put_right:Nn \l_@@_tmpa_tl {:NV} - - \use:c {\tl_use:N \l_@@_tmpa_tl } - \l_@@_current_tl - \l_@@_joinpath_tl - } + \@@_use_path:v + } \l_@@_joinpath_tl {} - \spath_set_current_path:N \l_@@_current_tl - \spath_set_tikz_data:V \l_@@_joinpath_tl - } - { - \msg_warning:nnx - { spath3 } - { missing soft path } - {\tl_use:N \l_@@_joinpath_tl } - } }, % \end{macrocode} % @@ -5453,23 +8077,10 @@ manipulating PGF soft paths} % % \begin{macrocode} show/.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} - { - \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 } - } + \@@_check_path:nnn { + \iow_term:n {---~ soft~ path~ #1~ ---} + \spath_show:v + } {#1} {} }, % \end{macrocode} % @@ -5479,98 +8090,25 @@ manipulating PGF soft paths} % % \begin{macrocode} join~ with/.code~ 2~ args={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - { - \bool_set_false:N \l_@@_reverse_bool - \bool_set_false:N \l_@@_weld_bool - \bool_set_false:N \l_@@_move_bool - \bool_set_false:N \l_@@_global_bool - \tl_clear:N \l_@@_joinpath_tl - \tl_clear:N \l_@@_transformation_tl - \tikzset{ - spath/join/.cd, - #2 - } - - \tl_if_exist:cTF - { - \tl_use:N \l_@@_prefix_tl - \tl_use:N \l_@@_joinpath_tl - \tl_use:N \l_@@_suffix_tl - } - { - \tl_set_eq:Nc \l_@@_joinpath_tl - { - \tl_use:N \l_@@_prefix_tl - \tl_use:N \l_@@_joinpath_tl - \tl_use:N \l_@@_suffix_tl - } - - \bool_if:NT \l_@@_reverse_bool - { - \spath_reverse:N \l_@@_joinpath_tl - } - - \tl_if_empty:NF \l_@@_transformation_tl - { - \group_begin: - \pgftransformreset - \@@_tikzset:V \l_@@_transformation_tl - \pgfgettransform \l_@@_tmpa_tl - \tl_gset:Nn \g_@@_smuggle_tl - { - \spath_transform:Nnnnnnn - \l_@@_joinpath_tl - } - \tl_gput_right:NV \g_@@_smuggle_tl \l_@@_tmpa_tl - \group_end: - \tl_use:N \g_@@_smuggle_tl - } - - \bool_if:NT \l_@@_move_bool - { - \spath_finalpoint:Nv - \l_@@_tmpc_tl - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - \spath_translate_to:NV \l_@@_joinpath_tl \l_@@_tmpc_tl - } - - \tl_clear:N \l_@@_tmpa_tl - \tl_set:Nn \l_@@_tmpa_tl {spath_} - - \bool_if:NT \l_@@_global_bool - { - \tl_put_right:Nn \l_@@_tmpa_tl {g} - } - - \tl_put_right:Nn \l_@@_tmpa_tl {append} - - \bool_if:NT \l_@@_weld_bool - { - \tl_put_right:Nn \l_@@_tmpa_tl {_no_move} - } - \tl_put_right:Nn \l_@@_tmpa_tl {:cV} + \bool_set_false:N \l_@@_reverse_bool + \bool_set_false:N \l_@@_weld_bool + \bool_set_false:N \l_@@_move_bool + \bool_set_false:N \l_@@_global_bool + \bool_set_false:N \l_@@_current_transformation_bool + \tl_clear:N \l_@@_joinpath_tl + \tl_clear:N \l_@@_transformation_tl + \tikzset{ + spath/join/.cd, + #2 + } - \cs_if_exist:cF {\tl_use:N \l_@@_tmpa_tl} - { - \tl_show:N \l_@@_tmpa_tl - } - - \use:c {\tl_use:N \l_@@_tmpa_tl } - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - \l_@@_joinpath_tl - } + \@@_maybe_current_path_reuse:nnn + { + \@@_check_two_paths:nnVn { - \msg_warning:nnx - { spath3 } - { missing soft path } - {\tl_use:N \l_@@_joinpath_tl } + \@@_join_with:cv } - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + } {#1} { \l_@@_joinpath_tl {} } }, % \end{macrocode} % @@ -5578,26 +8116,22 @@ manipulating PGF soft paths} % % \begin{macrocode} spot~ weld/.code={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \@@_maybe_current_path_reuse:nnn { - \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 } - } + \@@_check_path:nnn + { + \spath_spot_weld_components:c + } + } {#1} { {} } }, spot~ weld~ globally/.code={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \@@_maybe_current_path_reuse:nnn { - \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 } - } + \@@_check_path:nnn + { + \spath_spot_gweld_components:c + } + } {#1} { {} } }, % \end{macrocode} % @@ -5605,26 +8139,22 @@ manipulating PGF soft paths} % % \begin{macrocode} reverse/.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} - } + \@@_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \@@_check_path:nnn + { + \spath_reverse:c + } + } {#1} { {} } }, reverse~ globally/.code={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \@@_maybe_current_path_reuse:nnn { - \spath_reverse:c - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \@@_check_path:nnn + { + \spath_greverse:c + } + } {#1} { {} } }, % \end{macrocode} % @@ -5632,32 +8162,26 @@ manipulating PGF soft paths} % % \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 - } + \@@_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \@@_check_path:nnn + { + \@@_process_tikz_point:Nn \l_@@_tmpa_tl {#2} + \@@_process_tikz_point:Nn \l_@@_tmpb_tl {#3} + \spath_span:cVV + } + } {#1} { {} \l_@@_tmpa_tl \l_@@_tmpb_tl } }, span~ global/.code ~n~ args={3}{ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \@@_maybe_current_path_reuse:nnn { - \@@_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 } - } + \@@_check_path:nnn + { + \@@_process_tikz_point:Nn \l_@@_tmpa_tl {#2} + \@@_process_tikz_point:Nn \l_@@_tmpb_tl {#3} + \spath_span:cVV + } + } {#1} { {} \l_@@_tmpa_tl \l_@@_tmpb_tl } }, % \end{macrocode} % @@ -5668,69 +8192,34 @@ manipulating PGF soft paths} to~path={ [ spath/span={#1}{(\tikztostart)}{(\tikztotarget)}, - spath/append~no~move={#1}, + spath/use={#1,weld}, ] \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} + \@@_maybe_current_path_reuse:nnn { - \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 } - } - } + \@@_check_three_paths:nnnnn { - \msg_warning:nnn { spath3 } { missing soft path } { #2 } + \spath_splice_between:cvv } - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + } {#1} { {#2} {#3} {} } }, splice~ global/.code ~n~ args={3}{ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \@@_maybe_current_path_reuse:nnn { - \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 } - } - } + \@@_check_three_paths:nnnnn { - \msg_warning:nnn { spath3 } { missing soft path } { #2 } + \spath_gsplice_between:cvv } - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + } {#1} { {#2} {#3} {} } }, % \end{macrocode} % @@ -5742,447 +8231,177 @@ manipulating PGF soft paths} % % \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_head_is_group:nTF {#2} { - \tl_if_head_is_group:nTF {#2} - { - \tl_set:Nx \l_@@_tmpc_tl { \tl_item:nn {#2} {1} } - \tl_set:Nx \l_@@_tmpd_tl { \tl_item:nn {#2} {2} } - } - { - \tl_set:Nn \l_@@_tmpc_tl {#2} - \tl_clear:N \l_@@_tmpd_tl - } - \tl_if_exist:cTF - { - \tl_use:N \l_@@_prefix_tl - \tl_use:N \l_@@_tmpc_tl - \tl_use:N \l_@@_suffix_tl - } - { - \tl_if_empty:NT \l_@@_tmpd_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_gclear:N \g_@@_tmpa_seq - - \tl_if_empty:NTF \l_@@_tmpd_tl - { - \int_step_inline:nnnn {1}{1} {\seq_count:N \l_@@_tmpa_seq} - { - \seq_gput_right:Nn \g_@@_tmpa_seq {##1} - } - } - { - \foreach \l_@@_tmpa_tl in \l_@@_tmpd_tl - { - \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_pop_left:NN \l_@@_tmpa_seq \l_@@_tmpa_tl - \seq_gpop_left:NN \g_@@_tmpa_seq \l_@@_tmpb_tl - - \seq_map_indexed_inline:Nn \l_@@_tmpa_seq - { - \int_compare:nTF - { - ##1 == \l_@@_tmpb_tl - } - { - \seq_gpop_left:NNF \g_@@_tmpa_seq \l_@@_tmpb_tl - { - \tl_set:Nn \l_@@_tmpb_tl {-1} - } - \spath_splice_between:Nvn \l_@@_tmpa_tl - { - \tl_use:N \l_@@_prefix_tl - \tl_use:N \l_@@_tmpc_tl - \tl_use:N \l_@@_suffix_tl - } - {##2} - } - { - \tl_put_right:Nn \l_@@_tmpa_tl {##2} - } - } - \tl_set_eq:cN - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - \l_@@_tmpa_tl - } - { - \msg_warning:nnx - { spath3 } - { missing soft path } - { \tl_use:N \l_@@_tmpc_tl } - } + \tl_set:Nx \l_@@_tmpc_tl { \tl_item:nn {#2} {1} } + \tl_set:Nx \l_@@_tmpd_tl { \tl_item:nn {#2} {2} } } { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } + \tl_set:Nn \l_@@_tmpc_tl {#2} + \tl_clear:N \l_@@_tmpd_tl } - }, - join~ components~ globally~ with/.code~2~args={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + + \@@_maybe_current_path_reuse:nnn { - \tl_if_head_is_group:nTF {#2} - { - \tl_set:Nx \l_@@_tmpc_tl { \tl_item:nn {#2} {1} } - \tl_set:Nx \l_@@_tmpd_tl { \tl_item:nn {#2} {2} } - } - { - \tl_set:Nn \l_@@_tmpc_tl {#2} - \tl_clear:N \l_@@_tmpd_tl - } - \tl_if_exist:cTF + \@@_check_two_paths:nnVn { - \tl_use:N \l_@@_prefix_tl - \tl_use:N \l_@@_tmpc_tl - \tl_use:N \l_@@_suffix_tl + \@@_join_components_with:cvV } - { - \tl_if_empty:NT \l_@@_tmpd_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_gclear:N \g_@@_tmpa_seq - - \tl_if_empty:NTF \l_@@_tmpd_tl - { - \int_step_inline:nnnn {1}{1} {\seq_count:N \l_@@_tmpa_seq} - { - \seq_gput_right:Nn \g_@@_tmpa_seq {##1} - } - } - { - \foreach \l_@@_tmpa_tl in \l_@@_tmpd_tl - { - \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_pop_left:NN \l_@@_tmpa_seq \l_@@_tmpa_tl - \seq_gpop_left:NN \g_@@_tmpa_seq \l_@@_tmpb_tl + } {#1} { \l_@@_tmpc_tl {} \l_@@_tmpd_tl } + }, + join~ components~ globally~ with/.code~2~args={ + \tl_if_head_is_group:nTF {#2} + { + \tl_set:Nx \l_@@_tmpc_tl { \tl_item:nn {#2} {1} } + \tl_set:Nx \l_@@_tmpd_tl { \tl_item:nn {#2} {2} } + } + { + \tl_set:Nn \l_@@_tmpc_tl {#2} + \tl_clear:N \l_@@_tmpd_tl + } - \seq_map_indexed_inline:Nn \l_@@_tmpa_seq - { - \int_compare:nTF - { - ##1 == \l_@@_tmpb_tl - } - { - \seq_gpop_left:NNF \g_@@_tmpa_seq \l_@@_tmpb_tl - { - \tl_set:Nn \l_@@_tmpb_tl {-1} - } - \spath_splice_between:Nvn \l_@@_tmpa_tl - { - \tl_use:N \l_@@_prefix_tl - \tl_use:N \l_@@_tmpc_tl - \tl_use:N \l_@@_suffix_tl - } - {##2} - } - { - \tl_put_right:Nn \l_@@_tmpa_tl {##2} - } - } - \tl_gset_eq:cN - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - \l_@@_tmpa_tl - } + \@@_maybe_current_path_reuse:nnn + { + \@@_check_two_paths:nnVn { - \msg_warning:nnx - { spath3 } - { missing soft path } - { \tl_use:N \l_@@_tmpc_tl } + \@@_gjoin_components_with:cvV } + } {#1} { \l_@@_tmpc_tl {} \l_@@_tmpd_tl } + }, + join~ components~ upright~ with/.code~2~args={ + \tl_if_head_is_group:nTF {#2} + { + \tl_set:Nx \l_@@_tmpc_tl { \tl_item:nn {#2} {1} } + \tl_set:Nx \l_@@_tmpd_tl { \tl_item:nn {#2} {2} } } { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } + \tl_set:Nn \l_@@_tmpc_tl {#2} + \tl_clear:N \l_@@_tmpd_tl } - }, - join~ components~ upright~ with/.code~2~args={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + + \@@_maybe_current_path_reuse:nnn { - \tl_if_head_is_group:nTF {#2} - { - \tl_set:Nx \l_@@_tmpc_tl { \tl_item:nn {#2} {1} } - \tl_set:Nx \l_@@_tmpd_tl { \tl_item:nn {#2} {2} } - } - { - \tl_set:Nn \l_@@_tmpc_tl {#2} - \tl_clear:N \l_@@_tmpd_tl - } - \tl_if_exist:cTF + \@@_check_two_paths:nnVn { - \tl_use:N \l_@@_prefix_tl - \tl_use:N \l_@@_tmpc_tl - \tl_use:N \l_@@_suffix_tl + \@@_join_components_upright_with:cvV } - { - \tl_if_empty:NT \l_@@_tmpd_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_gclear:N \g_@@_tmpa_seq - - \tl_if_empty:NTF \l_@@_tmpd_tl - { - \int_step_inline:nnnn {1}{1} {\seq_count:N \l_@@_tmpa_seq} - { - \seq_gput_right:Nn \g_@@_tmpa_seq {##1} - } - } - { - \foreach \l_@@_tmpa_tl in \l_@@_tmpd_tl - { - \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_pop_left:NN \l_@@_tmpa_seq \l_@@_tmpa_tl - \seq_gpop_left:NN \g_@@_tmpa_seq \l_@@_tmpb_tl - - \tl_set_eq:Nc \l_@@_tmpc_tl - { - \tl_use:N \l_@@_prefix_tl - \tl_use:N \l_@@_tmpc_tl - \tl_use:N \l_@@_suffix_tl - } - \spath_transform:NVnnnnnn \l_@@_tmpd_tl \l_@@_tmpc_tl {1}{0}{0}{-1}{0pt}{0pt} - - \seq_map_indexed_inline:Nn \l_@@_tmpa_seq - { - \int_compare:nTF - { - ##1 == \l_@@_tmpb_tl - } - { - \seq_gpop_left:NNF \g_@@_tmpa_seq \l_@@_tmpb_tl - { - \tl_set:Nn \l_@@_tmpb_tl {-1} - } - \spath_finalpoint:NV \l_@@_tmpe_tl \l_@@_tmpa_tl - \spath_initialpoint:Nn \l_@@_tmpf_tl {##2} + } {#1} { \l_@@_tmpc_tl {} \l_@@_tmpd_tl } + }, + join~ components~ globally~ upright~ with/.code~2~args={ + \tl_if_head_is_group:nTF {#2} + { + \tl_set:Nx \l_@@_tmpc_tl { \tl_item:nn {#2} {1} } + \tl_set:Nx \l_@@_tmpd_tl { \tl_item:nn {#2} {2} } + } + { + \tl_set:Nn \l_@@_tmpc_tl {#2} + \tl_clear:N \l_@@_tmpd_tl + } - \dim_compare:nTF - { - \tl_item:Nn \l_@@_tmpe_tl {1} - > - \tl_item:Nn \l_@@_tmpf_tl {1} - } - { - \spath_splice_between:NVn - \l_@@_tmpa_tl - \l_@@_tmpd_tl - {##2} - } - { - \spath_splice_between:NVn - \l_@@_tmpa_tl - \l_@@_tmpc_tl - {##2} - } - } - { - \tl_put_right:Nn \l_@@_tmpa_tl {##2} - } - } - \tl_set_eq:cN - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - \l_@@_tmpa_tl - } + \@@_maybe_current_path_reuse:nnn + { + \@@_check_two_paths:nnVn { - \msg_warning:nnx - { spath3 } - { missing soft path } - { \tl_use:N \l_@@_tmpc_tl } + \@@_gjoin_components_upright_with:cvV } + } {#1} { \l_@@_tmpc_tl {} \l_@@_tmpd_tl } + }, + join~ components~ with~ bezier/.code={ + \tl_if_head_is_group:nTF {#1} + { + \tl_set:Nx \l_@@_tmpc_tl { \tl_item:nn {#1} {1} } + \tl_set:Nx \l_@@_tmpd_tl { \tl_item:nn {#1} {2} } } { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } + \tl_set:Nn \l_@@_tmpc_tl {#1} + \tl_clear:N \l_@@_tmpd_tl } - }, - join~ components~ globally~ upright~ with/.code~2~args={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + + \@@_maybe_current_path_reuse:nVn { - \tl_if_head_is_group:nTF {#2} + \@@_check_path:nnn { - \tl_set:Nx \l_@@_tmpc_tl { \tl_item:nn {#2} {1} } - \tl_set:Nx \l_@@_tmpd_tl { \tl_item:nn {#2} {2} } + \@@_join_components_with_bezier:cV } + } \l_@@_tmpc_tl { {} \l_@@_tmpd_tl } + }, + join~ components~ globally~ with~ bezier/.code~2~args={ + \@@_maybe_current_path_reuse:nnn + { + \@@_check_path:nnn { - \tl_set:Nn \l_@@_tmpc_tl {#2} - \tl_clear:N \l_@@_tmpd_tl + \@@_gjoin_components_with_bezier:cn } - \tl_if_exist:cTF + } {#1} { {} {#2} } + }, +% \end{macrocode} +% +% Close a path. +% +% \begin{macrocode} + close/.code={ + \@@_maybe_current_path_reuse:nnn + { + \@@_check_path:nnn { - \tl_use:N \l_@@_prefix_tl - \tl_use:N \l_@@_tmpc_tl - \tl_use:N \l_@@_suffix_tl + \spath_close:c } + } {#1} { {} } + }, + close~ globally/.code={ + \@@_maybe_current_path_reuse:nnn + { + \@@_check_path:nnn { - \tl_if_empty:NT \l_@@_tmpd_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_gclear:N \g_@@_tmpa_seq - - \tl_if_empty:NTF \l_@@_tmpd_tl - { - \int_step_inline:nnnn {1}{1} {\seq_count:N \l_@@_tmpa_seq} - { - \seq_gput_right:Nn \g_@@_tmpa_seq {##1} - } - } - { - \foreach \l_@@_tmpa_tl in \l_@@_tmpd_tl - { - \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_pop_left:NN \l_@@_tmpa_seq \l_@@_tmpa_tl - \seq_gpop_left:NN \g_@@_tmpa_seq \l_@@_tmpb_tl - - \tl_set_eq:Nc \l_@@_tmpc_tl - { - \tl_use:N \l_@@_prefix_tl - \tl_use:N \l_@@_tmpc_tl - \tl_use:N \l_@@_suffix_tl - } - \spath_transform:NVnnnnnn \l_@@_tmpd_tl \l_@@_tmpc_tl {1}{0}{0}{-1}{0pt}{0pt} - - \seq_map_indexed_inline:Nn \l_@@_tmpa_seq - { - \int_compare:nTF - { - ##1 == \l_@@_tmpb_tl - } - { - \seq_gpop_left:NNF \g_@@_tmpa_seq \l_@@_tmpb_tl - { - \tl_set:Nn \l_@@_tmpb_tl {-1} - } - \spath_finalpoint:NV \l_@@_tmpe_tl \l_@@_tmpa_tl - \spath_initialpoint:Nn \l_@@_tmpf_tl {##2} - - \dim_compare:nTF - { - \tl_item:Nn \l_@@_tmpe_tl {1} - > - \tl_item:Nn \l_@@_tmpf_tl {1} - } - { - \spath_splice_between:NVn - \l_@@_tmpa_tl - \l_@@_tmpd_tl - {##2} - } - { - \spath_splice_between:NVn - \l_@@_tmpa_tl - \l_@@_tmpc_tl - {##2} - } - } - { - \tl_put_right:Nn \l_@@_tmpa_tl {##2} - } - } - \tl_gset_eq:cN - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - \l_@@_tmpa_tl + \spath_gclose:c } + } {#1} { {} } + }, +% \end{macrocode} +% +% Open a path. +% +% \begin{macrocode} + open/.code={ + \@@_maybe_current_path_reuse:nnn + { + \@@_check_path:nnn { - \msg_warning:nnx - { spath3 } - { missing soft path } - { \tl_use:N \l_@@_tmpc_tl } + \spath_open:c } - } + } {#1} { {} } + }, + open~ globally/.code={ + \@@_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \@@_check_path:nnn + { + \spath_gopen:c + } + } {#1} { {} } }, % \end{macrocode} % -% Close a path. +% Close a path, ensuring that the end point is exactly where it will close up to. % % \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} - } + adjust~ and~ close/.code={ + \@@_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \@@_check_path:nnn + { + \spath_adjust_close:c + } + } {#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} - } + adjust~ and~ close~ globally/.code={ + \@@_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \@@_check_path:nnn + { + \spath_adjust_gclose:c + } + } {#1} { {} } }, % \end{macrocode} % @@ -6190,117 +8409,191 @@ manipulating PGF soft paths} % % \begin{macrocode} close~ with/.code~ 2~ args={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \@@_maybe_current_path_reuse:nnn { - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl} + \@@_check_two_paths:nnnn { \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 } - } + } {#1} { {#2} {} } }, close~ globally~ with/.code~ 2~ args={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \@@_maybe_current_path_reuse:nnn { - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl} + \@@_check_two_paths:nnnn { \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} } + } {#1} { {#2} {} } + }, +% \end{macrocode} +% +% Close a path with a curve. +% +% \begin{macrocode} + close~ with~ curve/.code={ + \@@_maybe_current_path_reuse:nnn + { + \@@_check_path:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #2 } + \spath_close_with_curve:c } - } + } {#1} { {} } + }, + close~ globally~ with~ curve/.code={ + \@@_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \@@_check_path:nnn + { + \spath_gclose_with_curve:c + } + } {#1} { {} } }, % \end{macrocode} % -% These keys shorten the path. +% These keys shorten the path by a dimension. % % \begin{macrocode} shorten~ at~ end/.code~ 2~ args={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \@@_maybe_current_path_reuse:nnn { - \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 } - } + \@@_check_path:nnn + { + \spath_shorten_at_end:cn + } + } {#1} { {} {#2} } }, shorten~ at~ start/.code~ 2~ args ={ - \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} - } + \@@_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \@@_check_path:nnn + { + \spath_shorten_at_start:cn + } + } {#1} { {} {#2} } }, shorten~ at~ both~ ends/.code~ 2~ args={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \@@_maybe_current_path_reuse:nnn { - \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 } - } + \@@_check_path:nnn + { + \spath_shorten_at_both_ends:cn + } + } {#1} { {} {#2} } }, 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} - } + \@@_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \@@_check_path:nnn + { + \spath_gshorten_at_end:cn + } + } {#1} { {} {#2} } }, 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} - } + \@@_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \@@_check_path:nnn + { + \spath_gshorten_at_start:cn + } + } {#1} { {} {#2} } }, 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} + \@@_maybe_current_path_reuse:nnn { - \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} - } + \@@_check_path:nnn + { + \spath_gshorten_at_both_ends:cn + } + } {#1} { {} {#2} } + }, +% \end{macrocode} +% +% These keys split a path at a parameter, the \texttt{keep} versions only keep one part of the resultant path. +% +% \begin{macrocode} + split~ at/.code~ 2~ args={ + \@@_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \@@_check_path:nnn + { + \spath_split_at_normalised:cn + } + } {#1} { {} {#2} } + }, + split~ globally~ at/.code~ 2~ args={ + \@@_maybe_current_path_reuse:nnn + { + \@@_check_path:nnn + { + \spath_gsplit_at_normalised:cn + } + } {#1} { {} {#2} } + }, + split~ at~ into/.code~ n~ args={4}{ + \@@_maybe_current_path_reuse:nnn + { + \@@_check_path:nnn + { + \spath_split_at_normalised:ccvn {\@@_path_name:n {#1}} + {\@@_path_name:n {#2}} + } + } {#3} { {} {#4} } + }, + split~ globally~ at~ into/.code~ n~ args={4}{ + \@@_maybe_current_path_reuse:nnn + { + \@@_check_path:nnn + { + \spath_gsplit_at_normalised:ccvn {\@@_path_name:n {#1}} + {\@@_path_name:n {#2}} + } + } {#3} { {} {#4} } + }, + split~ at~ keep~ start/.code~ 2~ args={ + \@@_maybe_current_path_reuse:nnn + { + \@@_check_path:nnn + { + \spath_split_at_normalised_keep_start:cn + } + } {#1} { {} {#2} } + }, + split~ globally~ at~ keep~ start/.code~ 2~ args={ + \@@_maybe_current_path_reuse:nnn + { + \@@_check_path:nnn + { + \spath_gsplit_at_normalised_keep_start:cn + } + } {#1} { {} {#2} } + }, + split~ at~ keep~ end/.code~ 2~ args={ + \@@_maybe_current_path_reuse:nnn + { + \@@_check_path:nnn + { + \spath_split_at_normalised_keep_end:cn + } + } {#1} { {} {#2} } + }, + split~ globally~ at~ keep~ end/.code~ 2~ args={ + \@@_maybe_current_path_reuse:nnn + { + \@@_check_path:nnn + { + \spath_gsplit_at_normalised_keep_end:cn + } + } {#1} { {} {#2} } + }, + split~ at~ keep~ middle/.style~ n~ args={3}{ + /tikz/spath/split~ at~ keep~ start={#1}{#3}, + /tikz/spath/split~ at~ keep~ end={#1}{(#2)/(#3)}, + }, + split~ globally~ at~ keep~ middle/.style~ n~ args={3}{ + /tikz/spath/split~ globally~ at~ keep~ start={#1}{#3}, + /tikz/spath/split~ globally~ at~ keep~ end={#1}{(#2)/(#3)}, }, % \end{macrocode} % @@ -6308,26 +8601,22 @@ manipulating PGF soft paths} % % \begin{macrocode} translate/.code~ n~ args={3}{ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \@@_maybe_current_path_reuse:nnn { - \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 } - } + \@@_check_path:nnn + { + \spath_translate:cnn + } + } {#1} { {} {#2}{#3} } }, 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} - } + \@@_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \@@_check_path:nnn + { + \spath_gtranslate:cnn + } + } {#1} { {} {#2}{#3} } }, % \end{macrocode} % @@ -6335,26 +8624,22 @@ manipulating PGF soft paths} % % \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} - } + \@@_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \@@_check_path:nnn + { + \spath_normalise:c + } + } {#1} { {} } }, normalise~ globally/.code={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \@@_maybe_current_path_reuse:nnn { - \spath_gnormalise:c - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \@@_check_path:nnn + { + \spath_gnormalise:c + } + } {#1} { {} } }, % \end{macrocode} % @@ -6362,75 +8647,55 @@ manipulating PGF soft paths} % % \begin{macrocode} transform/.code~ 2~ args={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \group_begin: + \pgftransformreset + \tikzset{#2} + \pgfgettransform \l_@@_tmpa_tl + \tl_gset_eq:NN \g_@@_smuggle_tl \l_@@_tmpa_tl + \group_end: + + \@@_maybe_current_path_reuse:nnn { - \group_begin: - \pgftransformreset - \tikzset{#2} - \pgfgettransform \l_@@_tmpa_tl - \tl_gset:Nn \g_@@_smuggle_tl + \@@_check_path:nnn { - \spath_transform:cnnnnnn - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \spath_transform:cV } - \tl_gput_right:NV \g_@@_smuggle_tl \l_@@_tmpa_tl - \group_end: - \tl_use:N \g_@@_smuggle_tl - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + } {#1} { {} \g_@@_smuggle_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 + \tikzset{#2} + \pgfgettransform \l_@@_tmpa_tl + \tl_gset_eq:NN \g_@@_smuggle_tl \l_@@_tmpa_tl + \group_end: + + \@@_maybe_current_path_reuse:nnn { - \group_begin: - \pgftransformreset - \tikzset{#2} - \pgfgettransform \l_@@_tmpa_tl - \tl_gset:Nn \g_@@_smuggle_tl + \@@_check_path:nnn { - \spath_gtransform:cnnnnnn - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \spath_gtransform:cV } - \tl_gput_right:NV \g_@@_smuggle_tl \l_@@_tmpa_tl - \group_end: - \tl_use:N \g_@@_smuggle_tl - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + } {#1} { {} \g_@@_smuggle_tl } }, % \end{macrocode} % % Splits first path where it intersects with the second. % % \begin{macrocode} - split~ at~ intersections~ with/.code~ n~ args={2}{ + split~ at~ intersections~ with/.code~ 2~ args={ \tl_if_exist:cTF { tikz@library@intersections@loaded } { - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \@@_maybe_current_two_paths_reuse_first:nnnn { - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl} + \@@_check_two_paths:nnnn { - \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} + \spath_split_path_at_intersections:cv } - { - \msg_warning:nnn { spath3 } { missing soft path } { #2 } - } - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + } {#1} {#2} { {} } } { \msg_warning:nn { spath3 } { load intersections } @@ -6442,23 +8707,13 @@ manipulating PGF soft paths} tikz@library@intersections@loaded } { - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \@@_maybe_current_two_paths_reuse_first:nnnn { - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl} + \@@_check_two_paths:nnnn { \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 } - } + } {#1} {#2} { {} } } { \msg_warning:nn { spath3 } { load intersections } @@ -6475,23 +8730,13 @@ manipulating PGF soft paths} tikz@library@intersections@loaded } { - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \@@_maybe_current_two_paths_reuse_both:nnnn { - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl} + \@@_check_two_paths:nnnn { \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 } - } + } {#1} {#2} { {} } } { \msg_warning:nn { spath3 } { load intersections } @@ -6503,23 +8748,13 @@ manipulating PGF soft paths} tikz@library@intersections@loaded } { - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \@@_maybe_current_two_paths_reuse_both:nnnn { - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl} + \@@_check_two_paths:nnnn { \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 } - } + } {#1} {#2} { {} } } { \msg_warning:nn { spath3 } { load intersections } @@ -6536,15 +8771,13 @@ manipulating PGF soft paths} tikz@library@intersections@loaded } { - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \@@_maybe_current_path_reuse:nnn { - \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 } - } + \@@_check_path:nnn + { + \spath_split_at_self_intersections:c + } + } {#1} { {} } } { \msg_warning:nn { spath3 } { load intersections } @@ -6556,15 +8789,13 @@ manipulating PGF soft paths} tikz@library@intersections@loaded } { - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \@@_maybe_current_path_reuse:nnn { - \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 } - } + \@@_check_path:nnn + { + \spath_gsplit_at_self_intersections:c + } + } {#1} { {} } } { \msg_warning:nn { spath3 } { load intersections } @@ -6576,64 +8807,24 @@ manipulating PGF soft paths} % % \begin{macrocode} get~ components~ of/.code~ 2~ args={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \@@_maybe_current_path:nn { - \clist_clear_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_set:cn - { - \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 + \@@_check_path:nnn { + \@@_get_components:Nv #2 } } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + {#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} + \@@_maybe_current_path:nn { - \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 + \@@_check_path:nnn { + \@@_gget_components:Nv #2 } } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + {#1} + {} }, % \end{macrocode} % @@ -6641,33 +8832,14 @@ manipulating PGF soft paths} % % \begin{macrocode} render~ components/.code={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \@@_maybe_current_path:nn { - \group_begin: - \spath_components_to_seq:Nv - \l_@@_tmpa_seq - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - \seq_map_indexed_inline:Nn \l_@@_tmpa_seq - { - \spath_tikz_path:nn - { - every~ spath~ component/.try, - spath ~component~ ##1/.try, - spath ~component/.try={##1}, - every~ #1~ component/.try, - #1 ~component~ ##1/.try, - #1 ~component/.try={##1}, - } - { - ##2 - } + \@@_check_path:nnn { + \@@_render_components:nv {#1} } - \group_end: - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } } + {#1} + {} }, % \end{macrocode} % @@ -6676,148 +8848,86 @@ manipulating PGF soft paths} % % \begin{macrocode} insert~ gaps~ after~ components/.code~ 2~ args={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \tl_if_head_is_group:nTF {#2} { - \group_begin: - \tl_if_head_is_group:nTF {#2} - { - \tl_set:Nx \l_@@_tmpc_tl { \tl_item:nn {#2} {1} } - \tl_set:Nx \l_@@_tmpd_tl { \tl_item:nn {#2} {2} } - } - { - \tl_set:Nn \l_@@_tmpc_tl {#2} - \tl_clear:N \l_@@_tmpd_tl - } - \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} - - \spath_components_to_seq:Nv - \l_@@_tmpa_seq - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - - \tl_if_empty:NTF \l_@@_tmpd_tl - { - \int_step_inline:nnnn {1}{1} { \l_@@_tmpa_int - 1 } - { - \seq_gput_right:Nn \g_@@_tmpa_seq {##1} - \seq_gput_right:Nx - \g_@@_tmpb_seq - {\int_eval:n {##1 + 1}} - } - } - { - \foreach \l_@@_tmpa_tl in \l_@@_tmpd_tl - { - \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 - } - } - } - } - - \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 {\l_@@_tmpc_tl/2} - } - \seq_if_in:NnT \g_@@_tmpb_seq {##1} - { - \spath_shorten_at_start:Nn \l_@@_tmpa_tl {\l_@@_tmpc_tl/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_set_eq:cN - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - \g_@@_output_tl - \tl_gclear:N \g_@@_output_tl + \tl_set:Nx \l_@@_tmpc_tl { \tl_item:nn {#2} {1} } + \tl_set:Nx \l_@@_tmpd_tl { \tl_item:nn {#2} {2} } } { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } + \tl_set:Nn \l_@@_tmpc_tl {#2} + \tl_clear:N \l_@@_tmpd_tl } - }, - insert~ gaps~ globally~ after~ components/.code~ 2~ args={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + + \@@_maybe_current_path_reuse:nnn { - \group_begin: - \tl_if_head_is_group:nTF {#2} - { - \tl_set:Nx \l_@@_tmpc_tl { \tl_item:nn {#2} {1} } - \tl_set:Nx \l_@@_tmpd_tl { \tl_item:nn {#2} {2} } - } + \@@_check_path:nnn { - \tl_set:Nn \l_@@_tmpc_tl {#2} - \tl_clear:N \l_@@_tmpd_tl + \@@_insert_gaps_after_components:cVV } - \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} + } {#1} { {} \l_@@_tmpc_tl \l_@@_tmpd_tl } + }, + insert~ gaps~ globally~ after~ components/.code~ 2~ args={ + \tl_if_head_is_group:nTF {#2} + { + \tl_set:Nx \l_@@_tmpc_tl { \tl_item:nn {#2} {1} } + \tl_set:Nx \l_@@_tmpd_tl { \tl_item:nn {#2} {2} } + } + { + \tl_set:Nn \l_@@_tmpc_tl {#2} + \tl_clear:N \l_@@_tmpd_tl + } - \spath_components_to_seq:Nv - \l_@@_tmpa_seq - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - - \tl_if_empty:NTF \l_@@_tmpd_tl - { - \int_step_inline:nnnn {1}{1} { \l_@@_tmpa_int - 1 } - { - \seq_gput_right:Nn \g_@@_tmpa_seq {##1} - \seq_gput_right:Nx - \g_@@_tmpb_seq - {\int_eval:n {##1 + 1}} - } - } + \@@_maybe_current_path_reuse:nnn + { + \@@_check_path:nnn { - \foreach \l_@@_tmpa_tl in \l_@@_tmpd_tl - { - \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 - } - } - } + \@@_ginsert_gaps_after_components:cVV } + } {#1} { {} \l_@@_tmpc_tl \l_@@_tmpd_tl } + }, +% \end{macrocode} +% +% This puts gaps between segments of a soft path. +% The list of segments is passed through a \Verb+\foreach+ loop so can use the shortcut syntax from those loops. +% +% \begin{macrocode} + insert~ gaps~ after~ segments/.code~ 2~ args={ + \tl_if_head_is_group:nTF {#2} + { + \tl_set:Nx \l_@@_tmpc_tl { \tl_item:nn {#2} {1} } + \tl_set:Nx \l_@@_tmpd_tl { \tl_item:nn {#2} {2} } + } + { + \tl_set:Nn \l_@@_tmpc_tl {#2} + \tl_clear:N \l_@@_tmpd_tl + } - \seq_clear:N \l_@@_tmpb_seq - \seq_map_indexed_inline:Nn \l_@@_tmpa_seq + \@@_maybe_current_path_reuse:nnn + { + \@@_check_path:nnn { - \tl_set:Nn \l_@@_tmpa_tl {##2} - \seq_if_in:NnT \g_@@_tmpa_seq {##1} - { - \spath_shorten_at_end:Nn \l_@@_tmpa_tl {\l_@@_tmpc_tl/2} - } - \seq_if_in:NnT \g_@@_tmpb_seq {##1} - { - \spath_shorten_at_start:Nn \l_@@_tmpa_tl {\l_@@_tmpc_tl/2} - } - \seq_put_right:NV \l_@@_tmpb_seq \l_@@_tmpa_tl + \@@_insert_gaps_after_segments:cVV } - \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 + } {#1} { {} \l_@@_tmpc_tl \l_@@_tmpd_tl } + }, + insert~ gaps~ globally~ after~ segments/.code~ 2~ args={ + \tl_if_head_is_group:nTF {#2} + { + \tl_set:Nx \l_@@_tmpc_tl { \tl_item:nn {#2} {1} } + \tl_set:Nx \l_@@_tmpd_tl { \tl_item:nn {#2} {2} } } { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } + \tl_set:Nn \l_@@_tmpc_tl {#2} + \tl_clear:N \l_@@_tmpd_tl } + + \@@_maybe_current_path_reuse:nnn + { + \@@_check_path:nnn + { + \@@_ginsert_gaps_after_segments:cVV + } + } {#1} { {} \l_@@_tmpc_tl \l_@@_tmpd_tl } }, % \end{macrocode} % @@ -6825,54 +8935,22 @@ manipulating PGF soft paths} % % \begin{macrocode} join~ components/.code~ 2~ args={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \@@_maybe_current_path_reuse:nnn { - \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 + \@@_check_path:nnn { - \spath_join_component:cn - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}{##1} + \@@_join_components:cn } - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + } {#1} { {} {#2} } }, join~ components~ globally/.code~ 2~ args={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \@@_maybe_current_path_reuse:nnn { - \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 + \@@_check_path:nnn { - \spath_gjoin_component:cn - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl}{##1} + \@@_gjoin_components:cn } - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + } {#1} { {} {#2} } }, % \end{macrocode} % @@ -6880,26 +8958,22 @@ manipulating PGF soft paths} % % \begin{macrocode} remove~ empty~ components/.code={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \@@_maybe_current_path_reuse:nnn { - \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 } - } + \@@_check_path:nnn + { + \spath_remove_empty_components:c + } + } {#1} { {} } }, remove~ empty~ components~ globally/.code={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \@@_maybe_current_path_reuse:nnn { - \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 } - } + \@@_check_path:nnn + { + \spath_gremove_empty_components:c + } + } {#1} { {} } }, % \end{macrocode} % @@ -6907,120 +8981,46 @@ manipulating PGF soft paths} % % \begin{macrocode} replace~ lines/.code={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - { - \spath_replace_lines:c - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - } + \@@_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \@@_check_path:nnn + { + \spath_replace_lines:c + } + } {#1} { {} } }, replace~ lines~ globally/.code={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \@@_maybe_current_path_reuse:nnn { - \spath_greplace_lines:c - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \@@_check_path:nnn + { + \spath_greplace_lines:c + } + } {#1} { {} } }, % \end{macrocode} % % -% Join the specified components together, joining each to its previous one. +% Remove the specified components. % % \begin{macrocode} remove~ components/.code~ 2~ args={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \@@_maybe_current_path_reuse:nnn { - \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 + \@@_check_path:nnn { - \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} - } + \@@_remove_components:cn } - \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 } - } + } {#1} { {} {#2} } }, remove~ components~ globally/.code~ 2~ args={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \@@_maybe_current_path_reuse:nnn { - \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 + \@@_check_path:nnn { - \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} - } + \@@_gremove_components:cn } - \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 } - } + } {#1} { {} {#2} } }, % \end{macrocode} % @@ -7037,29 +9037,25 @@ manipulating PGF soft paths} maybe~ spot~ weld/.code={ \bool_if:NF \l_@@_draft_bool { - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \@@_maybe_current_path_reuse:nnn { - \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 } - } + \@@_check_path:nnn + { + \spath_spot_weld_components:c + } + } {#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} - } + \@@_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \@@_check_path:nnn + { + \spath_spot_gweld_components:c + } + } {#1} { {} } } }, % \end{macrocode} @@ -7068,40 +9064,16 @@ manipulating PGF soft paths} % % \begin{macrocode} transform~ to/.code~ 2~ args={ - \group_begin: - \tl_if_exist:cTF + \@@_maybe_current_path:nn { - \tl_use:N \l_@@_prefix_tl - #1 - \tl_use:N \l_@@_suffix_tl - } - { - \spath_reallength:Nv - \l_@@_tmpa_int - { - \tl_use:N \l_@@_prefix_tl - #1 - \tl_use:N \l_@@_suffix_tl + \@@_check_path:nnn { + \@@_transform_to:nv {#2} } - - \tl_set:Nx \l_@@_tmpb_tl - {\fp_to_decimal:n {(#2) * (\l_@@_tmpa_int)}} - \spath_transformation_at:NvV \l_@@_tmpc_tl - { - \tl_use:N \l_@@_prefix_tl - #1 - \tl_use:N \l_@@_suffix_tl - } - \l_@@_tmpb_tl - \tl_gset_eq:NN \g_@@_smuggle_tl \l_@@_tmpc_tl } + {#1} { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - \tl_gset_eq:NN \g_@@_smuggle_tl { {1}{0}{0}{1}{0pt}{0pt} } + \pgfsettransformentries {1}{0}{0}{1}{0pt}{0pt} } - \group_end: - \exp_last_unbraced:NV \pgfsettransformentries \g_@@_smuggle_tl - \tl_gclear:N \g_@@_smuggle_tl }, % \end{macrocode} % @@ -7109,52 +9081,16 @@ manipulating PGF soft paths} % % \begin{macrocode} upright~ transform~ to/.code~ 2~ args={ - \group_begin: - \tl_if_exist:cTF - { - \tl_use:N \l_@@_prefix_tl - #1 - \tl_use:N \l_@@_suffix_tl - } + \@@_maybe_current_path:nn { - \spath_reallength:Nv - \l_@@_tmpa_int - { - \tl_use:N \l_@@_prefix_tl - #1 - \tl_use:N \l_@@_suffix_tl - } - - \tl_set:Nx \l_@@_tmpb_tl - {\fp_to_decimal:n {(#2) * (\l_@@_tmpa_int)}} - \spath_transformation_at:NvV \l_@@_tmpc_tl - { - \tl_use:N \l_@@_prefix_tl - #1 - \tl_use:N \l_@@_suffix_tl + \@@_check_path:nnn { + \@@_transform_upright_to:nv {#2} } - \l_@@_tmpb_tl - \tl_gset_eq:NN \g_@@_smuggle_tl \l_@@_tmpc_tl } + {#1} { - \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} - { - \tl_gset:Nx \g_@@_smuggle_tl - { - { \fp_eval:n { - (\tl_item:Nn \g_@@_smuggle_tl {1})} } - { \fp_eval:n { - (\tl_item:Nn \g_@@_smuggle_tl {2})} } - { \fp_eval:n { - (\tl_item:Nn \g_@@_smuggle_tl {3})} } - { \fp_eval:n { - (\tl_item:Nn \g_@@_smuggle_tl {4})} } - { \tl_item:Nn \g_@@_smuggle_tl {5} } - { \tl_item:Nn \g_@@_smuggle_tl {6} } - } + \pgfsettransformentries {1}{0}{0}{1}{0pt}{0pt} } - \group_end: - \exp_last_unbraced:NV \pgfsettransformentries \g_@@_smuggle_tl - \tl_gclear:N \g_@@_smuggle_tl }, % \end{macrocode} % @@ -7162,25 +9098,70 @@ manipulating PGF soft paths} % % \begin{macrocode} knot/.style~ n~ args={3}{ - 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 + /tikz/spath/split~ at~ self~ intersections=#1, + /tikz/spath/remove~ empty~ components=#1, + /tikz/spath/insert~ gaps~ after~ components={#1}{#2}{#3}, + /tikz/spath/maybe~ spot~ weld=#1, + /tikz/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 + /tikz/spath/split~ globally~ at~ self~ intersections=#1, + /tikz/spath/remove~ empty~ components~ globally=#1, + /tikz/spath/insert~ gaps~ globally ~after~ components={#1}{#2}{#3}, + /tikz/spath/maybe~ spot~ weld~ globally=#1, + /tikz/spath/render~ components=#1 }, +% \end{macrocode} +% +% For single argument commands which take a path as their argument, set the default to be \Verb+current+ so that they use the current path. +% +% \begin{macrocode} + show/.default=current, + spot~ weld/.default=current, + spot~ weld~ globally/.default=current, + reverse/.default=current, + reverse~ globally/.default=current, + close/.default=current, + close~ globally/.default=current, + open/.default=current, + open~ globally/.default=current, + adjust~ and~ close/.default=current, + adjust~ and~ close~ globally/.default=current, + close~ with~ curve/.default=current, + close~ globally~ with~ curve/.default=current, + remove~ empty~ components/.default=current, + remove~ empty~ components~ globally/.default=current, + replace~ lines/.default=current, + replace~ lines~ globally/.default=current, + maybe~ spot~ weld/.default=current, + maybe~ spot~ weld~ globally/.default=current, } % \end{macrocode} % % This defines a coordinate system that finds a position on a soft path. % % \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_get_point_at:nn #1#2 +{ + \group_begin: + \spath_reallength:Nn \l_@@_tmpa_int {#2} + \tl_set:Nx \l_@@_tmpb_tl + {\fp_to_decimal:n {(#1) * (\l_@@_tmpa_int)}} + \spath_point_at:NnV \l_@@_tmpc_tl {#2} \l_@@_tmpb_tl + + \tl_clear:N \l_@@_tmpd_tl + \tl_put_right:Nn \l_@@_tmpd_tl {\pgf@x=} + \tl_put_right:Nx \l_@@_tmpd_tl {\tl_item:Nn \l_@@_tmpc_tl {1}} + \tl_put_right:Nn \l_@@_tmpd_tl {\relax} + \tl_put_right:Nn \l_@@_tmpd_tl {\pgf@y=} + \tl_put_right:Nx \l_@@_tmpd_tl {\tl_item:Nn \l_@@_tmpc_tl {2}} + \tl_put_right:Nn \l_@@_tmpd_tl {\relax} + + \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpd_tl + \group_end: + } +\cs_generate_variant:Nn \@@_get_point_at:nn {VV, Vn, Vv} + \tikzdeclarecoordinatesystem{spath}{% \group_begin: \tl_set:Nn \l_@@_tmpa_tl {#1} @@ -7190,55 +9171,25 @@ manipulating PGF soft paths} \seq_pop_right:NN \l_@@_tmpa_seq \l_@@_tmpb_tl \tl_set:Nx \l_@@_tmpa_tl { \seq_use:Nn \l_@@_tmpa_seq {~} } - \tl_if_exist:cTF - { - \tl_use:N \l_@@_prefix_tl - \tl_use:N \l_@@_tmpa_tl - \tl_use:N \l_@@_suffix_tl - } - { - - \tl_set_eq:Nc - \l_@@_tmpa_tl - { - \tl_use:N \l_@@_prefix_tl - \tl_use:N \l_@@_tmpa_tl - \tl_use:N \l_@@_suffix_tl - } - - \tl_if_empty:NTF \l_@@_tmpa_tl - { - \tl_gset_eq:NN \g_@@_smuggle_tl \pgfpointorigin - } - { - \spath_reallength:NV \l_@@_tmpa_int \l_@@_tmpa_tl - \tl_set:Nx \l_@@_tmpb_tl - {\fp_to_decimal:n {(\l_@@_tmpb_tl) * (\l_@@_tmpa_int)}} - \spath_point_at:NVV \l_@@_tmpc_tl \l_@@_tmpa_tl \l_@@_tmpb_tl - \tl_clear:N \l_@@_tmpd_tl - \tl_put_right:Nn \l_@@_tmpd_tl {\pgf@x=} - \tl_put_right:Nx \l_@@_tmpd_tl {\tl_item:Nn \l_@@_tmpc_tl {1}} - \tl_put_right:Nn \l_@@_tmpd_tl {\relax} - \tl_put_right:Nn \l_@@_tmpd_tl {\pgf@y=} - \tl_put_right:Nx \l_@@_tmpd_tl {\tl_item:Nn \l_@@_tmpc_tl {2}} - \tl_put_right:Nn \l_@@_tmpd_tl {\relax} - \tl_gset_eq:NN \g_@@_smuggle_tl \l_@@_tmpd_tl + \@@_maybe_current_path:nV + { + \@@_check_path:nnn { + \@@_get_point_at:Vv \l_@@_tmpb_tl } } + \l_@@_tmpa_tl { - \msg_warning:nnx - { spath3 } - { missing soft path } - { \tl_use:N \l_@@_tmpa_tl } - \tl_gset_eq:NN \g_@@_smuggle_tl \pgfpointorigin + \tl_gset_eq:NN \g_@@_output_tl \pgfpointorigin } + \group_end: \use:c {pgf@process}{% - \tl_use:N \g_@@_smuggle_tl + \tl_use:N \g_@@_output_tl \pgftransforminvert \use:c {pgf@pos@transform@glob} } + \tl_gclear:N \g_@@_output_tl } \ExplSyntaxOff @@ -8281,6 +10232,7 @@ manipulating PGF soft paths} \bool_new:N \l_@@_append_next_bool \bool_new:N \l_@@_skip_bool \bool_new:N \l_@@_save_bool +\bool_new:N \l_@@_debugging_bool \seq_new:N \g_@@_nodes_seq @@ -8417,6 +10369,14 @@ manipulating PGF soft paths} \bool_set_true:N \l_@@_draft_bool \bool_set_true:N \l_@@_super_draft_bool }, + debug/.is~ choice, + debug/true/.code={ + \bool_set_true:N \l_@@_debugging_bool + }, + debug/false/.code={ + \bool_set_false:N \l_@@_debugging_bool + }, + debug/.default=true, draft/.is~ family, draft, crossing~ label/.style={ @@ -8440,10 +10400,26 @@ manipulating PGF soft paths} } % \end{macrocode} % +% \begin{macro}[internal]{\knot_debug:n} +% Debugging +% \begin{macrocode} +\cs_new_nopar:Npn \knot_debug:n #1 +{ + \bool_if:NT \l_@@_debugging_bool + { + \iow_term:n {===Knot~ debug: #1===} + } +} + +\cs_generate_variant:Nn \knot_debug:n {x} +% \end{macrocode} +% \end{macro} +% % Wrapper around \Verb+\tikzset+ for applying keys from a token list, checking for if the given token list exists. % \begin{macrocode} \cs_new_nopar:Npn \knot_apply_style:N #1 { + \knot_debug:n {knot~ apply~ style} \tl_if_exist:NT #1 { \exp_args:NV \tikzset #1 } @@ -8492,6 +10468,7 @@ manipulating PGF soft paths} % \begin{macrocode} \cs_new_protected_nopar:Npn \knot_initialise:n #1 { + \knot_debug:n {knot~ initialise} \tikzset{knot~ diagram/.cd,every~ knot~ diagram/.try,#1} \int_zero:N \l_@@_strands_int \tl_clear:N \l_@@_redraws_tl @@ -8505,6 +10482,7 @@ manipulating PGF soft paths} % \begin{macrocode} \cs_new_protected_nopar:Npn \knot_render: { + \knot_debug:n {knot~ render} % \end{macrocode} % Start a scope and reset the transformation (since all transformations have already been taken into account when defining the strands). % \begin{macrocode} @@ -8591,6 +10569,8 @@ manipulating PGF soft paths} % Close the scope % \begin{macrocode} \endpgfscope + \knot_debug:x {knot~rendered, + ~found~\int_use:N \g_@@_intersections_int \c_space_tl~intersections} } % \end{macrocode} % \end{macro} @@ -8600,6 +10580,7 @@ manipulating PGF soft paths} % \begin{macrocode} \cs_new_protected_nopar:Npn \knot_draw_strand:n #1 { + \knot_debug:n {knot~ draw~ strand~ #1} \pgfscope \group_begin: \spath_bake_round:c {knot strand #1} @@ -8609,7 +10590,7 @@ manipulating PGF soft paths} { , knot~ diagram/only~ when~ rendering/.try, - only~ when~ rendering/.try + only~ when~ rendering/.try, } \spath_tikz_path:Vv \l_@@_tmpa_tl {knot strand #1} \group_end: @@ -8625,6 +10606,7 @@ manipulating PGF soft paths} % \begin{macrocode} \cs_new_protected_nopar:Npn \knot_draw_labels:n #1 { + \knot_debug:n {knot~ draw~ labels} \bool_if:NT \l_@@_draft_bool { \spath_finalpoint:Nv \l_@@_tmpb_tl {knot strand #1} @@ -8665,6 +10647,7 @@ manipulating PGF soft paths} % \begin{macrocode} \cs_new_protected_nopar:Npn \knot_split_self_intersects:N #1 { + \knot_debug:n {knot~ split~ self~ intersects} \tl_set:Nx \l_@@_tmpc_tl {\tl_item:nn {#1} {4}} \tl_case:NnF \l_@@_tmpc_tl { @@ -8702,9 +10685,11 @@ manipulating PGF soft paths} } { \fp_set:Nn \l_@@_tmpa_fp {.5 * \l_@@_tmpa_fp / \l_@@_tmpb_fp} - \fp_compare:nTF + \bool_if:nTF { - 0 < \l_@@_tmpa_fp && \l_@@_tmpa_fp < 1 + \fp_compare_p:n {0 < \l_@@_tmpa_fp} + && + \fp_compare_p:n {\l_@@_tmpa_fp < 1} } { \spath_split_curve:NNnV @@ -8758,6 +10743,8 @@ manipulating PGF soft paths} % \begin{macrocode} \cs_new_protected_nopar:Npn \knot_intersections:nn #1#2 { + \knot_debug:x {knot~ intersections~ between~ + \l_@@_prefix_tl \c_space_tl #1~ and~ #2} \group_begin: \tl_set_eq:NN \l_@@_tmpa_tl \l_@@_prefix_tl \tl_put_right:Nn \l_@@_tmpa_tl {#1} @@ -8789,6 +10776,7 @@ manipulating PGF soft paths} } + \knot_debug:x {found~\pgfintersectionsolutions\c_space_tl~ intersections} \int_compare:nT {\pgfintersectionsolutions > 0} { \int_step_function:nnnN @@ -8808,6 +10796,7 @@ manipulating PGF soft paths} % \begin{macrocode} \cs_new_protected_nopar:Npn \knot_save_intersections:nn #1#2 { + \knot_debug:n {knot~ save~ intersections} \bool_if:NT \l_@@_save_bool { \tl_clear:N \l_@@_aux_tl @@ -8861,12 +10850,15 @@ manipulating PGF soft paths} % \begin{macrocode} \cs_new_protected_nopar:Npn \knot_do_intersection:n #1 { + \knot_debug:n {knot~ do~ intersection~ #1} % \end{macrocode} % Get the intersection coordinates. % \begin{macrocode} \pgfpointintersectionsolution{#1} \dim_set:Nn \l_@@_tmpa_dim {\pgf@x} \dim_set:Nn \l_@@_tmpb_dim {\pgf@y} + \knot_debug:x {intersection~at~ + (\dim_use:N \l_@@_tmpa_dim,\dim_use:N \l_@@_tmpb_dim)} % \end{macrocode} % If we're dealing with filaments, we can get false positives from the end points. % \begin{macrocode} @@ -8925,8 +10917,9 @@ manipulating PGF soft paths} % \begin{macrocode} \bool_if:NF \l_@@_skip_bool { - + \int_gincr:N \g_@@_intersections_int + \knot_debug:x {Processing~intersection~\int_use:N \g_@@_intersections_int} % \end{macrocode} % This is the intersection test. % If the intersection finder finds too many, it might be useful to ignore some. @@ -9007,6 +11000,8 @@ manipulating PGF soft paths} !\tl_if_empty_p:c {knot previous \tl_use:N \l_@@_tmpg_tl} } { + \knot_debug:x {Prepending~ + \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}} @@ -9017,9 +11012,13 @@ manipulating PGF soft paths} { \l_@@_splits_bool && - \tl_if_exist_p:c {knot previous \tl_use:N \l_@@_tmpg_tl} + \tl_if_exist_p:c {knot previous + \tl_use:c {knot previous \tl_use:N \l_@@_tmpg_tl} + } && - !\tl_if_empty_p:c {knot previous \tl_use:N \l_@@_tmpg_tl} + !\tl_if_empty_p:c {knot previous + \tl_use:c {knot previous \tl_use:N \l_@@_tmpg_tl} + } } { \knot_test_endpoint:NvnT @@ -9027,6 +11026,11 @@ manipulating PGF soft paths} {knot previous \tl_use:N \l_@@_tmpg_tl} {initial point} { + \knot_debug:x {Prepending~ + \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 @@ -9034,10 +11038,12 @@ manipulating PGF soft paths} {knot previous \tl_use:N \l_@@_tmpg_tl} } } - \tl_set_eq:Nc \l_@@_tmpa_tl {knot \tl_use:N \l_@@_prefix_tl -1} + \tl_set_eq:Nc \l_@@_tmpa_tl + {knot \tl_use:N \l_@@_prefix_tl -1} } } } + % \end{macrocode} % Now the same for appending. % \begin{macrocode} @@ -9047,9 +11053,11 @@ manipulating PGF soft paths} && \tl_if_exist_p:c {knot next \tl_use:N \l_@@_tmpg_tl} && - !\tl_if_empty_p:c {knot previous \tl_use:N \l_@@_tmpg_tl} + !\tl_if_empty_p:c {knot next \tl_use:N \l_@@_tmpg_tl} } { + \knot_debug:x {Appending~ + \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}} @@ -9057,17 +11065,25 @@ manipulating PGF soft paths} { \l_@@_splits_bool && - \tl_if_exist_p:c {knot previous \tl_use:N - \l_@@_tmpg_tl} + \tl_if_exist_p:c {knot next \tl_use:c { knot next \tl_use:N + \l_@@_tmpg_tl}} && - !\tl_if_empty_p:c {knot previous \tl_use:N \l_@@_tmpg_tl} + !\tl_if_empty_p:c {knot next + \tl_use:c { knot next \tl_use:N \l_@@_tmpg_tl} + } } { + \knot_debug:x {Testing~ whether~ to~ append~ + {knot next \tl_use:c { knot next \tl_use:N \l_@@_tmpg_tl}} + } \knot_test_endpoint:NvnT \l_@@_redraw_tolerance_dim - {knot previous \tl_use:N \l_@@_tmpg_tl} + {knot next \tl_use:N \l_@@_tmpg_tl} {final point} { + \knot_debug:x {Appending~ + {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 @@ -9170,6 +11186,7 @@ manipulating PGF soft paths} % \begin{macrocode} \cs_new_protected_nopar:Npn \knot_draw_crossing:nnn #1#2#3 { + \knot_debug:n {knot~ draw~ crossing} \group_begin: \pgfscope \path[knot~ diagram/background~ clip] (#2, #3) @@ -9224,6 +11241,7 @@ manipulating PGF soft paths} % \begin{macrocode} \cs_new_protected_nopar:Npn \knot_split_strands: { + \knot_debug:n {knot~ split~ strands} \int_gzero:N \g_@@_filaments_int \int_step_function:nnnN {1} {1} {\l_@@_strands_int} \knot_split_strand:n \int_step_function:nnnN {1} {1} {\g_@@_filaments_int} \knot_compute_nexts:n @@ -9237,6 +11255,7 @@ manipulating PGF soft paths} % \begin{macrocode} \cs_new_protected_nopar:Npn \knot_compute_nexts:n #1 { + \knot_debug:n {knot~ compute~ nexts} \tl_clear_new:c {knot next \tl_use:c {knot previous filament #1}} \tl_set:cn {knot next \tl_use:c {knot previous filament #1}} {filament #1} } @@ -9248,6 +11267,7 @@ manipulating PGF soft paths} % \begin{macrocode} \cs_new_protected_nopar:Npn \knot_split_strand:n #1 { + \knot_debug:n {knot~ split~ strand} \int_set_eq:NN \l_@@_component_start_int \g_@@_filaments_int \int_incr:N \l_@@_component_start_int \tl_set_eq:Nc \l_@@_tmpa_tl {l_@@_options_strand #1} @@ -9262,6 +11282,7 @@ manipulating PGF soft paths} % \begin{macrocode} \cs_new_protected_nopar:Npn \knot_save_filament:N #1 { + \knot_debug:n {knot~ save~ filament} \tl_set:Nx \l_@@_tmpb_tl {\tl_item:nn {#1} {4}} \tl_case:NnF \l_@@_tmpb_tl { diff --git a/Master/texmf-dist/tex/latex/spath3/spath3.sty b/Master/texmf-dist/tex/latex/spath3/spath3.sty index 6a136789262..65273f15fc6 100644 --- a/Master/texmf-dist/tex/latex/spath3/spath3.sty +++ b/Master/texmf-dist/tex/latex/spath3/spath3.sty @@ -15,7 +15,7 @@ \NeedsTeXFormat{LaTeX2e} \RequirePackage{expl3} \RequirePackage{pgf} -\ProvidesExplPackage {spath3} {2021/02/21} {2.4} {Functions for +\ProvidesExplPackage {spath3} {2022/08/24} {2.7} {Functions for manipulating PGF soft paths} \RequirePackage{xparse} \cs_new_protected:Nn \__spath_tl_put_right_braced:Nn @@ -64,6 +64,9 @@ manipulating PGF soft paths} \fp_new:N \l__spath_tmpa_fp \fp_new:N \l__spath_tmpb_fp \fp_new:N \l__spath_tmpc_fp +\fp_new:N \l__spath_tmpd_fp +\fp_new:N \l__spath_tmpe_fp +\fp_new:N \l__spath_tmpf_fp \int_new:N \l__spath_tmpa_int \int_new:N \l__spath_tmpb_int @@ -72,6 +75,11 @@ manipulating PGF soft paths} \dim_new:N \l__spath_move_x_dim \dim_new:N \l__spath_move_y_dim \bool_new:N \l__spath_closed_bool +\dim_new:N \l__spath_rectx_dim +\dim_new:N \l__spath_recty_dim + +\bool_new:N \l__spath_rect_bool +\bool_new:N \l_spath_movetorelevant_bool \tl_new:N \l__spath_intersecta_tl \tl_new:N \l__spath_intersectb_tl \tl_const:Nn \c_spath_moveto_tl {\pgfsyssoftpath@movetotoken} @@ -80,8 +88,22 @@ manipulating PGF soft paths} \tl_const:Nn \c_spath_curvetoa_tl {\pgfsyssoftpath@curvetosupportatoken} \tl_const:Nn \c_spath_curvetob_tl {\pgfsyssoftpath@curvetosupportbtoken} \tl_const:Nn \c_spath_closepath_tl {\pgfsyssoftpath@closepathtoken} +\tl_const:Nn \c_spath_rectcorner_tl {\pgfsyssoftpath@rectcornertoken} +\tl_const:Nn \c_spath_rectsize_tl {\pgfsyssoftpath@rectsizetoken} \int_new:N \g__spath_anon_int \int_gzero:N \g__spath_anon_int +\cs_new_protected_nopar:Npn \spath_anonymous:N #1 +{ + \tl_set:Nx #1 {anonymous_\int_use:N \g__spath_anon_int} + \int_gincr:N \g__spath_anon_int +} +\cs_new_protected_nopar:Npn \spath_ganonymous:N #1 +{ + \tl_gset:Nx #1 {anonymous_\int_use:N \g__spath_anon_int} + \int_gincr:N \g__spath_anon_int +} +\cs_generate_variant:Nn \spath_anonymous:N {c} +\cs_generate_variant:Nn \spath_ganonymous:N {c} \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 @@ -169,6 +191,27 @@ manipulating PGF soft paths} } + \c_spath_rectcorner_tl + { + \tl_set_eq:NN \l__spath_tmpb_tl \c_spath_rectcorner_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_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_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_tmpb_tl \c_spath_moveto_tl @@ -235,9 +278,11 @@ manipulating PGF soft paths} \group_begin: \tl_set:Nn \l__spath_tmpa_tl {#1} \seq_clear:N \l__spath_tmpa_seq + \tl_set: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: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_tmpa_tl } @@ -248,6 +293,11 @@ manipulating PGF soft paths} \seq_put_right:NV \l__spath_tmpa_seq \l__spath_tmpb_tl \tl_clear:N \l__spath_tmpb_tl } + \tl_if_eq:NNT \l__spath_tmpc_tl \c_spath_rectcorner_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_tmpc_tl { \tl_put_right:NV \l__spath_tmpb_tl \l__spath_tmpc_tl @@ -310,6 +360,7 @@ manipulating PGF soft paths} \c_spath_lineto_tl {} \c_spath_curveto_tl {} \c_spath_closepath_tl {} + \c_spath_rectsize_tl {} } { \int_incr:N \l__spath_tmpa_int @@ -345,6 +396,10 @@ manipulating PGF soft paths} { \int_incr:N \l__spath_tmpa_int } + \c_spath_rectcorner_tl + { + \int_incr:N \l__spath_tmpa_int + } } } \int_gzero:N \g__spath_output_int @@ -397,10 +452,35 @@ manipulating PGF soft paths} \tl_set:Nn \l__spath_tmpa_tl {#1} \tl_reverse:N \l__spath_tmpa_tl \tl_clear:N \l__spath_tmpb_tl - \tl_set:Nx \l__spath_tmpb_tl + \tl_set:Nx \l__spath_tmpc_tl {\tl_item:Nn \l__spath_tmpa_tl {3}} + \tl_if_eq:NNTF \l__spath_tmpc_tl \c_spath_rectsize_tl + { + \tl_set:Nx \l__spath_tmpb_tl + { + { + \dim_eval:n + { + \tl_item:Nn \l__spath_tmpa_tl {2} + + + \tl_item:Nn \l__spath_tmpa_tl {5} + } + } + { + \dim_eval:n + { + \tl_item:Nn \l__spath_tmpa_tl {1} + + + \tl_item:Nn \l__spath_tmpa_tl {4} + } + } + } + } { - { \tl_item:Nn \l__spath_tmpa_tl {2} } - { \tl_item:Nn \l__spath_tmpa_tl {1} } + \tl_set:Nx \l__spath_tmpb_tl + { + { \tl_item:Nn \l__spath_tmpa_tl {2} } + { \tl_item:Nn \l__spath_tmpa_tl {1} } + } } \tl_gset_eq:NN \g__spath_output_tl \l__spath_tmpb_tl \group_end: @@ -440,6 +520,16 @@ manipulating PGF soft paths} { \tl_item:Nn \l__spath_tmpa_tl {3} } } } + + \c_spath_rectcorner_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} { @@ -463,114 +553,371 @@ manipulating PGF soft paths} \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 +\cs_new_protected_nopar:Npn \__spath_initialtangent:n #1 +{ + \group_begin: + \tl_set:Nx \l__spath_tmpb_tl {\tl_item:nn {#1} {4}} + \tl_if_eq:NNTF \l__spath_tmpb_tl \c_spath_curvetoa_tl + { + \fp_set:Nn \l__spath_tmpa_fp {3} + } + { + \fp_set:Nn \l__spath_tmpa_fp {1} + } + \tl_clear:N \l__spath_tmpa_tl + \tl_set:Nx \l__spath_tmpa_tl + { + { + \fp_to_dim:n { + \l__spath_tmpa_fp + * + ( + \tl_item:nn {#1} {5} + - + \tl_item:nn {#1} {2} + ) + } + } + { + \fp_to_dim:n { + \l__spath_tmpa_fp + * + ( + \tl_item:nn {#1} {6} + - + \tl_item:nn {#1} {3} + ) + } + } + } + \tl_gset_eq:NN \g__spath_output_tl \l__spath_tmpa_tl + \group_end: +} +\cs_new_protected_nopar:Npn \spath_initialtangent:Nn #1#2 +{ + \__spath_initialtangent:n {#2} + \tl_set_eq:NN #1 \g__spath_output_tl + \tl_gclear:N \g__spath_output_tl +} +\cs_generate_variant:Nn \spath_initialtangent:Nn {NV, cn, cV, Nv} +\cs_new_protected_nopar:Npn \spath_ginitialtangent:Nn #1#2 +{ + \__spath_initialtangent:n {#2} + \tl_gset_eq:NN #1 \g__spath_output_tl + \tl_gclear:N \g__spath_output_tl +} +\cs_generate_variant:Nn \spath_ginitialtangent:Nn {NV, cn, cV, Nv} +\cs_new_protected_nopar:Npn \__spath_finaltangent:n #1 { \group_begin: \tl_set:Nn \l__spath_tmpa_tl {#1} - + \tl_reverse:N \l__spath_tmpa_tl + \tl_set:Nx \l__spath_tmpb_tl {\tl_item:nn {#1} {6}} + \tl_if_eq:NNTF \l__spath_tmpb_tl \c_spath_curveto_tl + { + \fp_set:Nn \l__spath_tmpa_fp {3} + } + { + \fp_set:Nn \l__spath_tmpa_fp {1} + } \tl_clear:N \l__spath_tmpb_tl - \tl_clear:N \l__spath_tmpd_tl - \tl_set:Nx \l__spath_tmpa_tl {\tl_tail: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} - \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_put_left:Nx \l__spath_tmpd_tl + \tl_set:Nx \l__spath_tmpb_tl { - {\dim_use:N \l__spath_tmpa_dim} - {\dim_use:N \l__spath_tmpb_dim} + { + \fp_to_dim:n { + \l__spath_tmpa_fp + * + ( + \tl_item:Nn \l__spath_tmpa_tl {2} + - + \tl_item:Nn \l__spath_tmpa_tl {5} + ) + } + } + { + \fp_to_dim:n { + \l__spath_tmpa_fp + * + ( + \tl_item:Nn \l__spath_tmpa_tl {1} + - + \tl_item:Nn \l__spath_tmpa_tl {4} + ) + } + } } - - \bool_set_false:N \l__spath_closed_bool - - \bool_until_do:nn { + \tl_gset_eq:NN \g__spath_output_tl \l__spath_tmpb_tl + \group_end: +} +\cs_new_protected_nopar:Npn \spath_finaltangent:Nn #1#2 +{ + \__spath_finaltangent:n {#2} + \tl_set_eq:NN #1 \g__spath_output_tl + \tl_gclear:N \g__spath_output_tl +} +\cs_generate_variant:Nn \spath_finaltangent:Nn {NV, cn, cV, Nv} +\cs_new_protected_nopar:Npn \spath_gfinaltangent:Nn #1#2 +{ + \__spath_finaltangent:n {#2} + \tl_gset_eq:NN #1 \g__spath_output_tl + \tl_gclear:N \g__spath_output_tl +} +\cs_generate_variant:Nn \spath_gfinaltangent:Nn {NV, cn, cV, Nv} +\cs_new_protected_nopar:Npn \__spath_finalmovetangent: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_tmpc_tl {\tl_head:N \l__spath_tmpa_tl} - - \tl_case:NnTF \l__spath_tmpc_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 { - - \bool_if:NT \l__spath_closed_bool + \c_spath_moveto_tl + { + \tl_set:Nx \l__spath_tmpd_tl { \tl_item:Nn \l__spath_tmpa_tl {4} } + \tl_if_eq:NNTF \l__spath_tmpd_tl \c_spath_curveto_tl + { + \fp_set:Nn \l__spath_tmpa_fp {3} + } + { + \fp_set:Nn \l__spath_tmpa_fp {1} + } + \tl_set:Nx \l__spath_tmpc_tl { - \tl_put_right:NV \l__spath_tmpd_tl \c_spath_closepath_tl - \tl_set:Nx \l__spath_tmpe_tl {\tl_tail:N \l__spath_tmpd_tl} - \tl_put_right:Nx \l__spath_tmpd_tl { - { \tl_head:N \l__spath_tmpd_tl } - { \tl_head:N \l__spath_tmpe_tl } + \fp_to_dim:n + { + \l__spath_tmpa_fp + * + ( + \tl_item:Nn \l__spath_tmpa_tl {5} + - + \tl_item:Nn \l__spath_tmpa_tl {2} + ) + } + } + { + \fp_to_dim:n + { + \l__spath_tmpa_fp + * + ( + \tl_item:Nn \l__spath_tmpa_tl {6} + - + \tl_item:Nn \l__spath_tmpa_tl {3} + ) + } } } - \bool_set_false:N \l__spath_closed_bool - \tl_put_left:NV \l__spath_tmpd_tl \c_spath_moveto_tl - \tl_put_left:NV \l__spath_tmpb_tl \l__spath_tmpd_tl - \tl_clear:N \l__spath_tmpd_tl - } - \c_spath_lineto_tl { - \tl_put_left:NV \l__spath_tmpd_tl \c_spath_lineto_tl - } - \c_spath_curveto_tl { - \tl_put_left:NV \l__spath_tmpd_tl \c_spath_curvetoa_tl - } - \c_spath_curvetoa_tl { - \tl_put_left:NV \l__spath_tmpd_tl \c_spath_curveto_tl - } - \c_spath_curvetob_tl { - \tl_put_left:NV \l__spath_tmpd_tl \c_spath_curvetob_tl } } + \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_finalmovetangent:Nn #1#2 +{ + \__spath_finalmovetangent:n {#2} + \tl_set_eq:NN #1 \g__spath_output_tl + \tl_gclear:N \g__spath_output_tl +} +\cs_generate_variant:Nn \spath_finalmovetangent:Nn {NV, cn, cV} +\cs_new_protected_nopar:Npn \spath_gfinalmovetangent:Nn #1#2 +{ + \__spath_finalmovetangent:n {#2} + \tl_gset_eq:NN #1 \g__spath_output_tl + \tl_gclear:N \g__spath_output_tl +} +\cs_generate_variant:Nn \spath_gfinalmovetangent:Nn {NV, cn, cV} +\cs_new_protected_nopar:Npn \__spath_reverse:n #1 +{ + \group_begin: + \tl_set:Nn \l__spath_tmpa_tl {#1} - \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} - \dim_set:Nn \l__spath_tmpb_dim {\tl_head:N \l__spath_tmpa_tl} + \tl_clear:N \l__spath_tmpb_tl + \tl_clear:N \l__spath_tmpd_tl + + \bool_set_false:N \l__spath_rect_bool + + \tl_set:Nx \l__spath_tmpc_tl {\tl_head:N \l__spath_tmpa_tl} + \bool_while_do:nn { + \tl_if_eq_p:NN \l__spath_tmpc_tl \c_spath_rectcorner_tl + } + { + \tl_put_left: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}} + \tl_item:Nn \l__spath_tmpa_tl {4} + {\tl_item:Nn \l__spath_tmpa_tl {5}} + {\tl_item:Nn \l__spath_tmpa_tl {6}} + } + \prg_replicate:nn {6} + { \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl} + } + \tl_set:Nx \l__spath_tmpc_tl {\tl_head:N \l__spath_tmpa_tl} + \bool_set_true:N \l__spath_rect_bool + } - \tl_put_left:Nx \l__spath_tmpd_tl - { - {\dim_use:N \l__spath_tmpa_dim} - {\dim_use:N \l__spath_tmpb_dim} - } + \tl_if_empty:NF \l__spath_tmpa_tl + { + \tl_set:Nx \l__spath_tmpa_tl {\tl_tail: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} + \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_put_left:Nx \l__spath_tmpd_tl + { + {\dim_use:N \l__spath_tmpa_dim} + {\dim_use:N \l__spath_tmpb_dim} + } + + \bool_set_false:N \l__spath_closed_bool + \bool_until_do:nn { + \tl_if_empty_p:N \l__spath_tmpa_tl } { - \tl_if_eq:NNTF \l__spath_tmpc_tl \c_spath_closepath_tl + \tl_set:Nx \l__spath_tmpc_tl {\tl_head:N \l__spath_tmpa_tl} + \bool_set_false:N \l__spath_rect_bool + + \tl_case:NnTF \l__spath_tmpc_tl { - \bool_set_true:N \l__spath_closed_bool + \c_spath_moveto_tl { + + \bool_if:NT \l__spath_closed_bool + { + \tl_put_right:NV \l__spath_tmpd_tl \c_spath_closepath_tl + \tl_set:Nx \l__spath_tmpe_tl {\tl_tail:N \l__spath_tmpd_tl} + \tl_put_right:Nx \l__spath_tmpd_tl + { + { \tl_head:N \l__spath_tmpd_tl } + { \tl_head:N \l__spath_tmpe_tl } + } + } + \bool_set_false:N \l__spath_closed_bool + \tl_put_left:NV \l__spath_tmpd_tl \c_spath_moveto_tl + \tl_put_left:NV \l__spath_tmpb_tl \l__spath_tmpd_tl + \tl_clear:N \l__spath_tmpd_tl + } + \c_spath_rectcorner_tl { + + \bool_if:NT \l__spath_closed_bool + { + \tl_put_right:NV \l__spath_tmpd_tl \c_spath_closepath_tl + \tl_set:Nx \l__spath_tmpe_tl {\tl_tail:N \l__spath_tmpd_tl} + \tl_put_right:Nx \l__spath_tmpd_tl + { + { \tl_head:N \l__spath_tmpd_tl } + { \tl_head:N \l__spath_tmpe_tl } + } + } + \bool_set_false:N \l__spath_closed_bool + \tl_put_left:NV \l__spath_tmpd_tl \c_spath_moveto_tl + \tl_put_left:NV \l__spath_tmpb_tl \l__spath_tmpd_tl + \tl_clear:N \l__spath_tmpd_tl + + \bool_while_do:nn { + \tl_if_eq_p:NN \l__spath_tmpc_tl \c_spath_rectcorner_tl + } + { + \tl_put_left: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}} + \tl_item:Nn \l__spath_tmpa_tl {4} + {\tl_item:Nn \l__spath_tmpa_tl {5}} + {\tl_item:Nn \l__spath_tmpa_tl {6}} + } + \prg_replicate:nn {6} + { + \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl} + } + \tl_set:Nx \l__spath_tmpc_tl {\tl_head:N \l__spath_tmpa_tl} + } + \bool_set_true:N \l__spath_rect_bool + + } + \c_spath_lineto_tl { + \tl_put_left:NV \l__spath_tmpd_tl \c_spath_lineto_tl + } + \c_spath_curveto_tl { + \tl_put_left:NV \l__spath_tmpd_tl \c_spath_curvetoa_tl + } + \c_spath_curvetoa_tl { + \tl_put_left:NV \l__spath_tmpd_tl \c_spath_curveto_tl + } + \c_spath_curvetob_tl { + \tl_put_left:NV \l__spath_tmpd_tl \c_spath_curvetob_tl + } } { - \msg_warning:nnx - { spath3 } - { unknown path construction } - {\l__spath_tmpc_tl } + \tl_if_empty:NF \l__spath_tmpa_tl + { + \tl_set:Nx \l__spath_tmpa_tl {\tl_tail: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} + \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_put_left:Nx \l__spath_tmpd_tl + { + {\dim_use:N \l__spath_tmpa_dim} + {\dim_use:N \l__spath_tmpb_dim} + } + } } + { + \tl_if_eq:NNTF \l__spath_tmpc_tl \c_spath_closepath_tl + { + \bool_set_true:N \l__spath_closed_bool + } + { + \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} - \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl} - \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl} + \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl} + \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl} + \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl} + } } - } - \bool_if:NT \l__spath_closed_bool - { - \tl_put_right:NV \l__spath_tmpd_tl \c_spath_closepath_tl - \tl_set:Nx \l__spath_tmpe_tl {\tl_tail:N \l__spath_tmpd_tl} - \tl_put_right:Nx \l__spath_tmpd_tl + \bool_if:NT \l__spath_closed_bool + { + \tl_put_right:NV \l__spath_tmpd_tl \c_spath_closepath_tl + \tl_set:Nx \l__spath_tmpe_tl {\tl_tail:N \l__spath_tmpd_tl} + \tl_put_right:Nx \l__spath_tmpd_tl + { + { \tl_head:N \l__spath_tmpd_tl } + { \tl_head:N \l__spath_tmpe_tl } + } + } + + \bool_set_false:N \l__spath_closed_bool + \bool_if:NF \l__spath_rect_bool { - { \tl_head:N \l__spath_tmpd_tl } - { \tl_head:N \l__spath_tmpe_tl } + \tl_put_left:NV \l__spath_tmpd_tl \c_spath_moveto_tl } } - \bool_set_false:N \l__spath_closed_bool - \tl_put_left:NV \l__spath_tmpd_tl \c_spath_moveto_tl \tl_put_left:NV \l__spath_tmpb_tl \l__spath_tmpd_tl - \tl_gset_eq:NN \g__spath_output_tl \l__spath_tmpb_tl \group_end: } @@ -602,14 +949,21 @@ manipulating PGF soft paths} { \group_begin: \tl_clear:N \l__spath_tmpa_tl - \int_compare:nT + \tl_set:Nx \l__spath_tmpb_tl {\tl_head:n {#1}} + \tl_if_eq:NNTF \l__spath_tmpb_tl \c_spath_rectcorner_tl { - \tl_count:n {#1} > 3 + \tl_set_eq:NN \l__spath_tmpa_tl \c_spath_rectcorner_tl } { - \tl_set:Nx \l__spath_tmpa_tl + \int_compare:nT + { + \tl_count:n {#1} > 3 + } { - \tl_item:Nn {#1} {4} + \tl_set:Nx \l__spath_tmpa_tl + { + \tl_item:Nn {#1} {4} + } } } \tl_gset_eq:NN \g__spath_output_tl \l__spath_tmpa_tl @@ -648,6 +1002,10 @@ manipulating PGF soft paths} { \tl_set_eq:NN \l__spath_tmpb_tl \c_spath_curveto_tl } + \tl_if_eq:NNT \l__spath_tmpb_tl \c_spath_rectsize_tl + { + \tl_set_eq:NN \l__spath_tmpb_tl \c_spath_rectcorner_tl + } } \tl_gset_eq:NN \g__spath_output_tl \l__spath_tmpb_tl \group_end: @@ -670,22 +1028,60 @@ manipulating PGF soft paths} { \group_begin: \tl_set:Nn \l__spath_tmpa_tl {#1} + + \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} + \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} + \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_eq:NNT \l__spath_tmpc_tl \c_spath_rectcorner_tl + { + \dim_set_eq:NN \l__spath_rectx_dim \l__spath_tmpa_dim + \dim_set_eq:NN \l__spath_recty_dim \l__spath_tmpb_dim + } \bool_until_do: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_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}} - \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}} - \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl} + + \tl_if_eq:NNTF \l__spath_tmpc_tl \c_spath_rectsize_tl + { + \dim_set:Nn \l__spath_tmpa_dim + {\dim_min:nn + {\tl_head:N \l__spath_tmpa_tl + \l__spath_rectx_dim} {\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_recty_dim} {\l__spath_tmpb_dim} + } + \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}} + \tl_if_eq:NNT \l__spath_tmpc_tl \c_spath_rectcorner_tl + { + \dim_set:Nn \l__spath_rectx_dim {\tl_head:N \l__spath_tmpa_tl} + } + \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}} + \tl_if_eq:NNT \l__spath_tmpc_tl \c_spath_rectcorner_tl + { + \dim_set:Nn \l__spath_recty_dim {\tl_head:N \l__spath_tmpa_tl} + } + \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl} + } + } \tl_clear:N \l__spath_tmpb_tl \tl_put_right:Nx \l__spath_tmpb_tl @@ -714,25 +1110,63 @@ manipulating PGF soft paths} { \group_begin: \tl_set:Nn \l__spath_tmpa_tl {#1} + + \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} + \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} + \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_eq:NNT \l__spath_tmpc_tl \c_spath_rectcorner_tl + { + \dim_set_eq:NN \l__spath_rectx_dim \l__spath_tmpa_dim + \dim_set_eq:NN \l__spath_recty_dim \l__spath_tmpb_dim + } \bool_until_do: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_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}} - \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}} - \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl} + + \tl_if_eq:NNTF \l__spath_tmpc_tl \c_spath_rectsize_tl + { + \dim_set:Nn \l__spath_tmpa_dim + {\dim_max:nn + {\tl_head:N \l__spath_tmpa_tl + \l__spath_rectx_dim} {\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_recty_dim} {\l__spath_tmpb_dim} + } + \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}} + \tl_if_eq:NNT \l__spath_tmpc_tl \c_spath_rectcorner_tl + { + \dim_set:Nn \l__spath_rectx_dim {\tl_head:N \l__spath_tmpa_tl} + } + \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}} + \tl_if_eq:NNT \l__spath_tmpc_tl \c_spath_rectcorner_tl + { + \dim_set:Nn \l__spath_recty_dim {\tl_head:N \l__spath_tmpa_tl} + } + \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl} + } + } \tl_clear:N \l__spath_tmpb_tl - \tl_put_right:Nx \l__spath_tmpb_tl + \tl_set:Nx \l__spath_tmpb_tl { {\dim_use:N \l__spath_tmpa_dim} {\dim_use:N \l__spath_tmpb_dim} @@ -762,7 +1196,7 @@ manipulating PGF soft paths} \tl_clear:N \l__spath_tmpa_tl \tl_put_right:Nn \l__spath_tmpa_tl { \ExplSyntaxOn - \tl_clear:N #1 + \tl_clear_new:N #1 \tl_set:Nn #1 {#2} \ExplSyntaxOff } @@ -780,6 +1214,7 @@ manipulating PGF soft paths} \spath_save_to_aux:NV #1#1 } } +\cs_generate_variant:Nn \spath_save_to_aux:N {c} \cs_new_protected_nopar:Npn \__spath_translate:nnn #1#2#3 { \group_begin: @@ -789,13 +1224,27 @@ manipulating PGF soft paths} \tl_if_empty_p:N \l__spath_tmpa_tl } { + \tl_set:Nx \l__spath_tmpc_tl {\tl_head: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} - \dim_set:Nn \l__spath_tmpa_dim {\tl_head:N \l__spath_tmpa_tl + #2} + \tl_if_eq:NNTF \l__spath_tmpc_tl \c_spath_rectsize_tl + { + \dim_set:Nn \l__spath_tmpa_dim {\tl_head:N \l__spath_tmpa_tl} + } + { + \dim_set:Nn \l__spath_tmpa_dim {\tl_head:N \l__spath_tmpa_tl + #2} + } \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl} - \dim_set:Nn \l__spath_tmpb_dim {\tl_head:N \l__spath_tmpa_tl + #3} + \tl_if_eq:NNTF \l__spath_tmpc_tl \c_spath_rectsize_tl + { + \dim_set:Nn \l__spath_tmpb_dim {\tl_head:N \l__spath_tmpa_tl} + } + { + \dim_set:Nn \l__spath_tmpb_dim {\tl_head:N \l__spath_tmpa_tl + #3} + } \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl} \tl_put_right:Nx \l__spath_tmpb_tl @@ -969,6 +1418,8 @@ manipulating PGF soft paths} \tl_if_empty_p:N \l__spath_tmpa_tl } { + \tl_set:Nx \l__spath_tmpe_tl {\tl_head: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_set:Nx \l__spath_tmpc_tl {\tl_head:N \l__spath_tmpa_tl} @@ -976,10 +1427,20 @@ manipulating PGF soft paths} \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} + \tl_if_eq:NNTF \l__spath_tmpe_tl \c_spath_rectsize_tl + { + \fp_set:Nn \l__spath_tmpa_fp + {\l__spath_tmpc_tl * #2 + \l__spath_tmpd_tl * #4} + \fp_set:Nn \l__spath_tmpb_fp + {\l__spath_tmpc_tl * #3 + \l__spath_tmpd_tl * #5} + } + { + \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} @@ -1207,8 +1668,8 @@ manipulating PGF soft paths} \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_finalpoint:Nn \l__spath_tmpd_tl {#1} + \spath_initialpoint:Nn \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} @@ -1239,6 +1700,312 @@ manipulating PGF soft paths} \spath_gsplice_between:NVnn #1#1{#2}{#3} } \cs_generate_variant:Nn \spath_gsplice_between:Nnn {NVV, cnn, cvv, Nvn, NVn} +\cs_new_protected_nopar:Npn \__spath_hobby_curve:nnnn #1#2#3#4 +{ + \group_begin: + \fp_set:Nn \l__spath_tmpa_fp + { + ( + (\tl_item:nn {#2} {1}) + * + (\tl_item:nn {#4} {1} - \tl_item:nn {#1} {1}) + + + (\tl_item:nn {#2} {2}) + * + (\tl_item:nn {#4} {2} - \tl_item:nn {#1} {2}) + ) + / + sqrt + ( + ( + (\tl_item:nn {#2} {1})^2 + + + (\tl_item:nn {#2} {2})^2 + ) + * + ( + (\tl_item:nn {#4} {1} - \tl_item:nn {#1} {1})^2 + + + (\tl_item:nn {#4} {2} - \tl_item:nn {#1} {2})^2 + ) + ) + } + \fp_set:Nn \l__spath_tmpb_fp + { + ( + - + (\tl_item:nn {#2} {1}) + * + (\tl_item:nn {#4} {2} - \tl_item:nn {#1} {2}) + + + (\tl_item:nn {#2} {2}) + * + (\tl_item:nn {#4} {1} - \tl_item:nn {#1} {1}) + ) + / + sqrt + ( + ( + (\tl_item:nn {#2} {1})^2 + + + (\tl_item:nn {#2} {2})^2 + ) + * + ( + (\tl_item:nn {#4} {1} - \tl_item:nn {#1} {1})^2 + + + (\tl_item:nn {#4} {2} - \tl_item:nn {#1} {2})^2 + ) + ) + } + \fp_set:Nn \l__spath_tmpc_fp + { + ( + (\tl_item:nn {#3} {1}) + * + (\tl_item:nn {#4} {1} - \tl_item:nn {#1} {1}) + + + (\tl_item:nn {#3} {2}) + * + (\tl_item:nn {#4} {2} - \tl_item:nn {#1} {2}) + ) + / + sqrt + ( + ( + (\tl_item:nn {#3} {1})^2 + + + (\tl_item:nn {#3} {2})^2 + ) + * + ( + (\tl_item:nn {#4} {1} - \tl_item:nn {#1} {1})^2 + + + (\tl_item:nn {#4} {2} - \tl_item:nn {#1} {2})^2 + ) + ) + } + \fp_set:Nn \l__spath_tmpd_fp + { + ( + (\tl_item:nn {#3} {1}) + * + (\tl_item:nn {#4} {2} - \tl_item:nn {#1} {2}) + - + (\tl_item:nn {#3} {2}) + * + (\tl_item:nn {#4} {1} - \tl_item:nn {#1} {1}) + ) + / + sqrt + ( + ( + (\tl_item:nn {#3} {1})^2 + + + (\tl_item:nn {#3} {2})^2 + ) + * + ( + (\tl_item:nn {#4} {1} - \tl_item:nn {#1} {1})^2 + + + (\tl_item:nn {#4} {2} - \tl_item:nn {#1} {2})^2 + ) + ) + } + + \fp_set:Nn \l__spath_tmpe_fp + { + ( + 2 + sqrt(2) * + (\l__spath_tmpb_fp - 1/16 * \l__spath_tmpd_fp) + * + (\l__spath_tmpd_fp - 1/16 * \l__spath_tmpb_fp) + * + (\l__spath_tmpa_fp - \l__spath_tmpc_fp) + ) + / + ( + 1 + + + (1 - (3 - sqrt(5))/2) + * + \l__spath_tmpa_fp + + + (3 - sqrt(5))/2 + * + \l__spath_tmpc_fp + ) + * + sqrt + ( + ( + (\tl_item:nn {#4} {1} - \tl_item:nn {#1} {1})^2 + + + (\tl_item:nn {#4} {2} - \tl_item:nn {#1} {2})^2 + ) + / + ( + (\tl_item:nn {#2} {1})^2 + + + (\tl_item:nn {#2} {2})^2 + ) + ) + /3 + } + \fp_set:Nn \l__spath_tmpf_fp + { + ( + 2 - sqrt(2) * + (\l__spath_tmpb_fp - 1/16 * \l__spath_tmpd_fp) + * + (\l__spath_tmpd_fp - 1/16 * \l__spath_tmpb_fp) + * + (\l__spath_tmpa_fp - \l__spath_tmpc_fp) + ) + / + ( + 1 + + + (1 - (3 - sqrt(5))/2) + * + \l__spath_tmpc_fp + + + (3 - sqrt(5))/2 + * + \l__spath_tmpa_fp + ) + * + sqrt + ( + ( + (\tl_item:nn {#4} {1} - \tl_item:nn {#1} {1})^2 + + + (\tl_item:nn {#4} {2} - \tl_item:nn {#1} {2})^2 + ) + / + ( + (\tl_item:nn {#3} {1})^2 + + + (\tl_item:nn {#3} {2})^2 + ) + ) + /3 + } + + \tl_set:Nx \l__spath_tmpa_tl + { + { + \fp_to_dim:n + { + \tl_item:nn {#1} {1} + + + \l__spath_tmpe_fp + * + (\tl_item:nn {#2} {1}) + } + } + { + \fp_to_dim:n + { + \tl_item:nn {#1} {2} + + + \l__spath_tmpe_fp + * + (\tl_item:nn {#2} {2}) + } + } + } + \tl_set:Nx \l__spath_tmpb_tl + { + { + \fp_to_dim:n + { + \tl_item:nn {#4} {1} + - + \l__spath_tmpf_fp + * + (\tl_item:nn {#3} {1}) + } + } + { + \fp_to_dim:n + { + \tl_item:nn {#4} {2} + - + \l__spath_tmpf_fp + * + (\tl_item:nn {#3} {2}) + } + } + } + + \tl_clear:N \l__spath_tmpc_tl + \tl_set:NV \l__spath_tmpc_tl \c_spath_moveto_tl + \tl_put_right:Nn \l__spath_tmpc_tl {#1} + \tl_put_right:NV \l__spath_tmpc_tl \c_spath_curvetoa_tl + \tl_put_right:NV \l__spath_tmpc_tl \l__spath_tmpa_tl + \tl_put_right:NV \l__spath_tmpc_tl \c_spath_curvetob_tl + \tl_put_right:NV \l__spath_tmpc_tl \l__spath_tmpb_tl + \tl_put_right:NV \l__spath_tmpc_tl \c_spath_curveto_tl + \tl_put_right:Nn \l__spath_tmpc_tl {#4} + \tl_gset_eq:NN \g__spath_output_tl \l__spath_tmpc_tl + \group_end: +} +\cs_new_protected_nopar:Npn \spath_hobby_curve:Nnnnn #1#2#3#4#5 +{ + \__spath_hobby_curve:nnnn {#2}{#3}{#4}{#5} + \tl_set_eq:NN #1 \g__spath_output_tl + \tl_gclear:N \g__spath_output_tl +} +\cs_generate_variant:Nn \spath_hobby_curve:Nnnnn {NVVVV} +\cs_new_protected_nopar:Npn \spath_ghobby_curve:Nnnnn #1#2#3#4#5 +{ + \__spath_hobby_curve:nnnn {#2}{#3}{#4}{#5} + \tl_gset_eq:NN #1 \g__spath_output_tl + \tl_gclear:N \g__spath_output_tl +} +\cs_generate_variant:Nn \spath_ghobby_curve:Nnnnn {NVVVV} +\cs_new_protected_nopar:Npn \__spath_curve_between:nn #1#2 +{ + \group_begin: + \spath_finalpoint:Nn \l__spath_tmpa_tl {#1} + \spath_finaltangent:Nn \l__spath_tmpb_tl {#1} + \spath_initialpoint:Nn \l__spath_tmpc_tl {#2} + \spath_initialtangent:Nn \l__spath_tmpd_tl {#2} + + \spath_hobby_curve:NVVVV \l__spath_tmpe_tl + \l__spath_tmpa_tl \l__spath_tmpb_tl \l__spath_tmpd_tl \l__spath_tmpc_tl + + \tl_set:Nn \l__spath_tmpa_tl {#1} + \spath_append_no_move:NV \l__spath_tmpa_tl \l__spath_tmpe_tl + \spath_append_no_move:Nn \l__spath_tmpa_tl {#2} + \tl_gset_eq:NN \g__spath_output_tl \l__spath_tmpa_tl + \group_end: +} +\cs_new_protected_nopar:Npn \spath_curve_between:Nnn #1#2#3 +{ + \__spath_curve_between:nn {#2}{#3} + \tl_set_eq:NN #1 \g__spath_output_tl + \tl_gclear:N \g__spath_output_tl +} +\cs_generate_variant:Nn \spath_curve_between:Nnn {NVn, NVV} +\cs_new_protected_nopar:Npn \spath_curve_between:Nn #1#2 +{ + \spath_curve_between:NVn #1#1{#2} +} +\cs_generate_variant:Nn \spath_curve_between:Nn {NV, cn, cv} +\cs_new_protected_nopar:Npn \spath_gcurve_between:Nnn #1#2#3 +{ + \__spath_curve_between:nn {#2} + \tl_gset_eq:NN #1 \g__spath_output_tl + \tl_gclear:N \g__spath_output_tl +} +\cs_generate_variant:Nn \spath_gcurve_between:Nnn {NVn, NVV} +\cs_new_protected_nopar:Npn \spath_gcurve_between:Nn #1#2 +{ + \spath_gcurve_between:NVnn #1#1{#2} +} +\cs_generate_variant:Nn \spath_gcurve_between:Nn {NV, cn, cv} \cs_new_protected_nopar:Npn \__spath_close_with:nn #1#2 { \group_begin: @@ -1295,6 +2062,68 @@ manipulating PGF soft paths} \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_close_with_curve:n #1 +{ + \group_begin: + \spath_finalpoint:Nn \l__spath_tmpa_tl {#1} + \spath_finaltangent:Nn \l__spath_tmpb_tl {#1} + \spath_finalmovepoint:Nn \l__spath_tmpc_tl {#1} + \spath_finalmovetangent:Nn \l__spath_tmpd_tl {#1} + \dim_compare:nTF + { + \dim_abs:n + { + \tl_item:Nn \l__spath_tmpa_tl {1} + - + \tl_item:Nn \l__spath_tmpc_tl {1} + } + + + \dim_abs:n + { + \tl_item:Nn \l__spath_tmpa_tl {2} + - + \tl_item:Nn \l__spath_tmpc_tl {2} + } + < 0.01pt + } + { + \__spath_close:n {#1} + } + { + + \spath_hobby_curve:NVVVV \l__spath_tmpe_tl + \l__spath_tmpa_tl \l__spath_tmpb_tl \l__spath_tmpd_tl \l__spath_tmpc_tl + + \tl_set:Nn \l__spath_tmpa_tl {#1} + \spath_append_no_move:NV \l__spath_tmpa_tl \l__spath_tmpe_tl + \__spath_close:V \l__spath_tmpa_tl + } + \group_end: +} +\cs_new_protected_nopar:Npn \spath_close_with_curve:Nn #1#2 +{ + \__spath_close_with_curve:n {#2} + \tl_set_eq:NN #1 \g__spath_output_tl + \tl_gclear:N \g__spath_output_tl +} +\cs_generate_variant:Nn \spath_close_with_curve:Nn {cn, cV, cv, NV} +\cs_new_protected_nopar:Npn \spath_close_with_curve:N #1 +{ + \spath_close_with_curve:NV #1#1 +} +\cs_generate_variant:Nn \spath_close_with_curve:N {c} +\cs_new_protected_nopar:Npn \spath_gclose_with_curve:Nn #1#2 +{ + \__spath_close_with_curve:n {#2} + \tl_gset_eq:NN #1 \g__spath_output_tl + \tl_gclear:N \g__spath_output_tl +} +\cs_generate_variant:Nn \spath_gclose_with_curve:Nn {cn, cV, cv, NV} +\cs_new_protected_nopar:Npn \spath_gclose_with_curve:N #1 +{ + \spath_gclose_with_curve:NV #1#1 +} +\cs_generate_variant:Nn \spath_gclose_with_curve:N {c} \cs_new_protected_nopar:Npn \__spath_weld:nn #1#2 { \group_begin: @@ -1335,9 +2164,20 @@ manipulating PGF soft paths} \group_begin: \tl_set:Nn \l__spath_tmpa_tl {#1} \tl_set:Nn \l__spath_tmpb_tl {#2} - \tl_set:Nx \l__spath_tmpb_tl {\tl_tail:N \l__spath_tmpb_tl} - \tl_set:Nx \l__spath_tmpb_tl {\tl_tail:N \l__spath_tmpb_tl} - \tl_set:Nx \l__spath_tmpb_tl {\tl_tail:N \l__spath_tmpb_tl} + \tl_set:Nx \l__spath_tmpc_tl {\tl_head:N \l__spath_tmpb_tl} + \spath_finalaction:Nn \l__spath_tmpd_tl {#1} + \bool_if:nT { + ! \tl_if_eq_p:NN \l__spath_tmpd_tl \c_spath_closepath_tl + && + ! \tl_if_eq_p:NN \l__spath_tmpd_tl \c_spath_rectcorner_tl + && + \tl_if_eq_p:NN \l__spath_tmpc_tl \c_spath_moveto_tl + } + { + \tl_set:Nx \l__spath_tmpb_tl {\tl_tail:N \l__spath_tmpb_tl} + \tl_set:Nx \l__spath_tmpb_tl {\tl_tail:N \l__spath_tmpb_tl} + \tl_set:Nx \l__spath_tmpb_tl {\tl_tail:N \l__spath_tmpb_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 @@ -1462,6 +2302,43 @@ manipulating PGF soft paths} \spath_gbake_round:NV #1#1 } \cs_generate_variant:Nn \spath_gbake_round:N {c} +\cs_new_protected_nopar:Npn \__spath_bake_shorten:n #1 +{ + \group_begin: + \tl_set:Nn \l__spath_tmpa_tl {#1} + \pgfsyssoftpath@getcurrentpath\l__spath_tmpb_tl + \pgfsyssoftpath@setcurrentpath\l__spath_tmpa_tl + \pgf@prepare@end@of@path + \pgf@prepare@start@of@path + \pgfsyssoftpath@getcurrentpath\l__spath_tmpa_tl + \pgfsyssoftpath@setcurrentpath\l__spath_tmpb_tl + \tl_gset_eq:NN \g__spath_output_tl \l__spath_tmpa_tl + \group_end: +} +\cs_new_protected_nopar:Npn \spath_bake_shorten:Nn #1#2 +{ + \__spath_bake_shorten:n {#2} + \tl_set_eq:NN #1 \g__spath_output_tl + \tl_gclear:N \g__spath_output_tl +} +\cs_generate_variant:Nn \spath_bake_shorten:Nn {NV} +\cs_new_protected_nopar:Npn \spath_bake_shorten:N #1 +{ + \spath_bake_shorten:NV #1#1 +} +\cs_generate_variant:Nn \spath_bake_shorten:N {c} +\cs_new_protected_nopar:Npn \spath_gbake_shorten:Nn #1#2 +{ + \__spath_bake_shorten:n {#2} + \tl_gset_eq:NN #1 \g__spath_output_tl + \tl_gclear:N \g__spath_output_tl +} +\cs_generate_variant:Nn \spath_gbake_shorten:Nn {NV} +\cs_new_protected_nopar:Npn \spath_gbake_shorten:N #1 +{ + \spath_gbake_shorten:NV #1#1 +} +\cs_generate_variant:Nn \spath_gbake_shorten:N {c} \cs_new_protected_nopar:Npn \__spath_close:n #1 { \group_begin: @@ -1497,10 +2374,83 @@ manipulating PGF soft paths} \spath_gclose:NV #1#1 } \cs_generate_variant:Nn \spath_gclose:N {c} -\cs_new_protected_nopar:Npn \__spath_open:n #1 +\cs_new_protected_nopar:Npn \__spath_adjust_close:n #1 { \group_begin: \tl_set:Nn \l__spath_tmpa_tl {#1} + \spath_finalmovepoint:NV \l__spath_tmpb_tl \l__spath_tmpa_tl + \spath_finalpoint:NV \l__spath_tmpc_tl \l__spath_tmpa_tl + \tl_reverse:N \l__spath_tmpa_tl + \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl} + \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl} + \tl_set:Nx \l__spath_tmpd_tl {\tl_head:N \l__spath_tmpa_tl} + \tl_if_eq:NNT \l__spath_tmpd_tl \c_spath_curveto_tl + { + \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl} + \tl_clear:N \l__spath_tmpe_tl + \tl_set:Nx \l__spath_tmpe_tl { + { + \dim_eval:n + { + \tl_item:Nn \l__spath_tmpa_tl {1} + - + \tl_item:Nn \l__spath_tmpc_tl {2} + + + \tl_item:Nn \l__spath_tmpb_tl {2} + } + } + { + \dim_eval:n + { + \tl_item:Nn \l__spath_tmpa_tl {2} + - + \tl_item:Nn \l__spath_tmpc_tl {1} + + + \tl_item:Nn \l__spath_tmpb_tl {1} + } + } + } + \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl} + \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl} + \tl_put_left:NV \l__spath_tmpa_tl \l__spath_tmpe_tl + \tl_put_left:NV \l__spath_tmpa_tl \l__spath_tmpd_tl + } + \tl_reverse:N \l__spath_tmpa_tl + \tl_put_right:NV \l__spath_tmpa_tl \l__spath_tmpb_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_adjust_close:n {V} +\cs_new_protected_nopar:Npn \spath_adjust_close:Nn #1#2 +{ + \__spath_adjust_close:n {#2} + \tl_set_eq:NN #1 \g__spath_output_tl + \tl_gclear:N \g__spath_output_tl +} +\cs_generate_variant:Nn \spath_adjust_close:Nn {NV} +\cs_new_protected_nopar:Npn \spath_adjust_close:N #1 +{ + \spath_adjust_close:NV #1#1 +} +\cs_generate_variant:Nn \spath_adjust_close:N {c} +\cs_new_protected_nopar:Npn \spath_adjust_gclose:Nn #1#2 +{ + \__spath_adjust_close:n {#2} + \tl_gset_eq:NN #1 \g__spath_output_tl + \tl_gclear:N \g__spath_output_tl +} +\cs_generate_variant:Nn \spath_adjust_gclose:Nn {NV} +\cs_new_protected_nopar:Npn \spath_adjust_gclose:N #1 +{ + \spath_adjust_gclose:NV #1#1 +} +\cs_generate_variant:Nn \spath_adjust_gclose:N {c} +\cs_new_protected_nopar:Npn \__spath_open:n #1 +{ + \group_begin: + \spath_replace_rectangles:Nn \l__spath_tmpa_tl {#1} \tl_clear:N \l__spath_tmpb_tl \bool_until_do:nn { \tl_if_empty_p:N \l__spath_tmpa_tl @@ -1574,6 +2524,7 @@ manipulating PGF soft paths} \tl_gset_eq:NN \g__spath_output_tl \l__spath_tmpb_tl \group_end: } +\cs_generate_variant:Nn \__spath_open:n {V} \cs_new_protected_nopar:Npn \spath_open:Nn #1#2 { \__spath_open:n {#2} @@ -1596,6 +2547,8 @@ manipulating PGF soft paths} { \spath_gopen:NV #1#1 } +\cs_generate_variant:Nn \spath_open:N {c} +\cs_generate_variant:Nn \spath_gopen:N {c} \cs_new_protected_nopar:Npn \__spath_replace_lines:n #1 { \group_begin: @@ -1707,6 +2660,115 @@ manipulating PGF soft paths} \spath_greplace_lines:NV #1#1 } \cs_generate_variant:Nn \spath_greplace_lines:N {c} +\cs_new_protected_nopar:Npn \__spath_replace_rectangles:n #1 +{ + \group_begin: + \tl_set:Nn \l__spath_tmpa_tl {#1} + \tl_clear:N \l__spath_tmpb_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_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl } + \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 } + \tl_set:Nx \l__spath_tmpe_tl {\tl_head:N \l__spath_tmpa_tl } + \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl } + + \tl_if_eq:NNTF \l__spath_tmpc_tl \c_spath_rectcorner_tl + { + + \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl } + \dim_set:Nn \l__spath_tmpa_dim + { + \tl_item:Nn \l__spath_tmpa_tl {1} + } + \dim_set:Nn \l__spath_tmpb_dim + { + \tl_item:Nn \l__spath_tmpa_tl {2} + } + + \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl } + \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl } + + \tl_put_right:NV \l__spath_tmpb_tl \c_spath_moveto_tl + \__spath_tl_put_right_braced:NV \l__spath_tmpb_tl \l__spath_tmpd_tl + \__spath_tl_put_right_braced:NV \l__spath_tmpb_tl \l__spath_tmpe_tl + + \tl_put_right:NV \l__spath_tmpb_tl \c_spath_lineto_tl + \tl_put_right:Nx \l__spath_tmpb_tl + { + { + \fp_to_dim:n { \l__spath_tmpd_tl + \l__spath_tmpa_dim } + } + } + \__spath_tl_put_right_braced:NV \l__spath_tmpb_tl \l__spath_tmpe_tl + + \tl_put_right:NV \l__spath_tmpb_tl \c_spath_lineto_tl + \tl_put_right:Nx \l__spath_tmpb_tl + { + { + \fp_to_dim:n { \l__spath_tmpd_tl + \l__spath_tmpa_dim } + } + } + \tl_put_right:Nx \l__spath_tmpb_tl + { + { + \fp_to_dim:n { \l__spath_tmpe_tl + \l__spath_tmpb_dim } + } + } + + \tl_put_right:NV \l__spath_tmpb_tl \c_spath_lineto_tl + \__spath_tl_put_right_braced:NV \l__spath_tmpb_tl \l__spath_tmpd_tl + \tl_put_right:Nx \l__spath_tmpb_tl + { + { + \fp_to_dim:n { \l__spath_tmpe_tl + \l__spath_tmpb_dim } + } + } + + \tl_put_right:NV \l__spath_tmpb_tl \c_spath_closepath_tl + \__spath_tl_put_right_braced:NV \l__spath_tmpb_tl \l__spath_tmpd_tl + \__spath_tl_put_right_braced:NV \l__spath_tmpb_tl \l__spath_tmpe_tl + + } + { + \tl_put_right:NV \l__spath_tmpb_tl \l__spath_tmpc_tl + \__spath_tl_put_right_braced:NV \l__spath_tmpb_tl \l__spath_tmpd_tl + \__spath_tl_put_right_braced:NV \l__spath_tmpb_tl \l__spath_tmpe_tl + } + } + \tl_gset_eq:NN \g__spath_output_tl \l__spath_tmpb_tl + \group_end: +} +\cs_generate_variant:Nn \__spath_replace_rectangles:n {V} +\cs_new_protected_nopar:Npn \spath_replace_rectangles:Nn #1#2 +{ + \__spath_replace_rectangles:n {#2} + \tl_set_eq:NN #1 \g__spath_output_tl + \tl_gclear:N \g__spath_output_tl +} +\cs_generate_variant:Nn \spath_replace_rectangles:Nn {NV, cV, cv, Nv} +\cs_new_protected_nopar:Npn \spath_replace_rectangles:N #1 +{ + \spath_replace_rectangles:NV #1#1 +} +\cs_generate_variant:Nn \spath_replace_rectangles:N {c} +\cs_new_protected_nopar:Npn \spath_greplace_rectangles:Nn #1#2 +{ + \__spath_replace_rectangles:n {#2} + \tl_gset_eq:NN #1 \g__spath_output_tl + \tl_gclear:N \g__spath_output_tl +} +\cs_generate_variant:Nn \spath_greplace_rectangles:Nn {NV, cV, cv, Nv} +\cs_new_protected_nopar:Npn \spath_greplace_rectangles:N #1 +{ + \spath_greplace_rectangles:NV #1#1 +} +\cs_generate_variant:Nn \spath_greplace_rectangles:N {c} \cs_new_protected_nopar:Npn \__spath_remove_empty_components:n #1 { \group_begin: @@ -2000,9 +3062,11 @@ manipulating PGF soft paths} } { \fp_set:Nn \l__spath_tmpa_fp {.5 * \l__spath_tmpa_fp / \l__spath_tmpb_fp} - \fp_compare:nTF + \bool_if:nTF { - 0 < \l__spath_tmpa_fp && \l__spath_tmpa_fp < 1 + \fp_compare_p:n {0 < \l__spath_tmpa_fp} + && + \fp_compare_p:n {\l__spath_tmpa_fp < 1} } { \__spath_split_curve:nV {#1} \l__spath_tmpa_fp @@ -2199,6 +3263,30 @@ manipulating PGF soft paths} \tl_gclear:N \g__spath_output_tl } \cs_generate_variant:Nn \spath_gsplit_line:NNnn {NNnV, NNVn, NNVV} +\cs_new_protected_nopar:Npn \__spath_split_rectangle:nn #1#2 +{ + \group_begin: + \spath_open:Nn \l__spath_tmpa_tl {#1} + \fp_set:Nn \l__spath_tmpa_fp {4*(#2)} + \spath_split_at:NNVV + \l__spath_tmpa_tl \l__spath_tmpb_tl \l__spath_tmpa_tl \l__spath_tmpa_fp + \__spath_append_no_move:VV \l__spath_tmpb_tl \l__spath_tmpa_tl + \group_end: +} +\cs_new_protected_nopar:Npn \spath_split_rectangle:Nnn #1#2#3 +{ + \__spath_split_rectangle: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_rectangle:Nnn {NnV, NVn, NVV} +\cs_new_protected_nopar:Npn \spath_gsplit_rectangle:Nnn #1#2#3 +{ + \__spath_split_rectangle: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_rectangle:Nnn {NnV, NVn, NVV} \cs_new_protected_nopar:Npn \__spath_split_at:nn #1#2 { \group_begin: @@ -2228,11 +3316,28 @@ manipulating PGF soft paths} \bool_set_true:N \l__spath_tmpa_bool \tl_set:Nn \l__spath_tmpe_tl {#1} - \tl_clear:N \l__spath_tmpc_tl \dim_zero:N \l__spath_tmpa_dim \dim_zero:N \l__spath_tmpb_dim + % 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 + || + \tl_if_eq_p:NN \l__spath_tmpa_tl \c_spath_rectcorner_tl + } + + % Open it + \spath_open:N \l__spath_tmpe_tl + + \tl_clear:N \l__spath_tmpa_tl + \tl_clear:N \l__spath_tmpb_tl + \tl_clear:N \l__spath_tmpc_tl + \tl_clear:N \l__spath_tmpd_tl + \bool_until_do:nn { \tl_if_empty_p:N \l__spath_tmpe_tl || @@ -2251,6 +3356,10 @@ manipulating PGF soft paths} { \int_incr:N \l__spath_tmpb_int } + \c_spath_rectcorner_tl + { + \int_incr:N \l__spath_tmpb_int + } } \int_compare:nT { \l__spath_tmpb_int < \l__spath_tmpa_int } { @@ -2355,14 +3464,65 @@ manipulating PGF soft paths} \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_rectcorner_tl + { + \tl_clear:N \l__spath_tmpd_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_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_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_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_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_rectangle:NVV + \l__spath_tmpa_tl + \l__spath_tmpd_tl + \l__spath_tmpa_fp + + \tl_put_right:NV \l__spath_tmpc_tl \l__spath_tmpa_tl + \tl_put_right:NV \l__spath_tmpb_tl \l__spath_tmpe_tl + } + } } + \bool_if:NT \l__spath_closed_bool + { + \prg_replicate:nn {3} + { + \tl_set:Nx \l__spath_tmpc_tl {\tl_tail:N \l__spath_tmpc_tl} + } + \tl_put_right:NV \l__spath_tmpb_tl \l__spath_tmpc_tl + \tl_set_eq:NN \l__spath_tmpc_tl \l__spath_tmpb_tl + \tl_clear:N \l__spath_tmpb_tl + } + \tl_gclear:N \g__spath_output_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_generate_variant:Nn \__spath_split_at:nn {nV, VV} +\cs_new_protected_nopar:Npn \__spath_split_at_normalised:nn #1#2 +{ + \group_begin: + \spath_reallength:Nn \l__spath_tmpa_int {#1} + + \tl_set:Nx \l__spath_tmpa_tl + {\fp_to_decimal:n {(#2) * (\l__spath_tmpa_int)}} + \__spath_split_at:nV {#1} \l__spath_tmpa_tl + \group_end: +} +\cs_generate_variant:Nn \__spath_split_at_normalised:nn {nV} \cs_new_protected_nopar:Npn \spath_split_at:NNnn #1#2#3#4 { \__spath_split_at:nn {#3}{#4} @@ -2379,6 +3539,114 @@ manipulating PGF soft paths} \tl_gclear:N \g__spath_output_tl } \cs_generate_variant:Nn \spath_gsplit_at:NNnn {NNVn, NNVV, NNnV} +\cs_new_protected_nopar:Npn \spath_split_at_keep_start:Nnn #1#2#3 +{ + \__spath_split_at:nn {#2}{#3} + \tl_set:Nx #1 {\tl_item:Nn \g__spath_output_tl {1}} + \tl_gclear:N \g__spath_output_tl +} +\cs_generate_variant:Nn \spath_split_at_keep_start:Nnn {NVn} +\cs_new_protected_nopar:Npn \spath_split_at_keep_start:Nn #1#2 +{ + \spath_split_at_keep_start:NVn #1#1{#2} +} +\cs_new_protected_nopar:Npn \spath_gsplit_at_keep_start:Nnn #1#2#3 +{ + \__spath_split_at:nn {#2}{#3} + \tl_gset:Nx #1 {\tl_item:Nn \g__spath_output_tl {1}} + \tl_gclear:N \g__spath_output_tl +} +\cs_generate_variant:Nn \spath_gsplit_at_keep_start:Nnn {NVn} +\cs_new_protected_nopar:Npn \spath_gsplit_at_keep_start:Nn #1#2 +{ + \spath_gsplit_at_keep_start:NVn #1#1{#2} +} +\cs_new_protected_nopar:Npn \spath_split_at_keep_end:Nnn #1#2#3 +{ + \__spath_split_at:nn {#2}{#3} + \tl_set:Nx #1 {\tl_item:Nn \g__spath_output_tl {2}} + \tl_gclear:N \g__spath_output_tl +} +\cs_generate_variant:Nn \spath_split_at_keep_end:Nnn {NVn} +\cs_new_protected_nopar:Npn \spath_split_at_keep_end:Nn #1#2 +{ + \spath_split_at_keep_end:NVn #1#1{#2} +} +\cs_new_protected_nopar:Npn \spath_gsplit_at_keep_end:Nnn #1#2#3 +{ + \__spath_split_at:nn {#2}{#3} + \tl_gset:Nx #1 {\tl_item:Nn \g__spath_output_tl {2}} + \tl_gclear:N \g__spath_output_tl +} +\cs_generate_variant:Nn \spath_gsplit_at_keep_end:Nnn {NVn} +\cs_new_protected_nopar:Npn \spath_gsplit_at_keep_end:Nn #1#2 +{ + \spath_gsplit_at_keep_end:NVn #1#1{#2} +} +\cs_new_protected_nopar:Npn \spath_split_at_normalised:NNnn #1#2#3#4 +{ + \__spath_split_at_normalised: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}} + \tl_gclear:N \g__spath_output_tl +} +\cs_generate_variant:Nn \spath_split_at_normalised:NNnn {NNVn, NNVV, NNnV, ccvn} +\cs_new_protected_nopar:Npn \spath_gsplit_at_normalised:NNnn #1#2#3#4 +{ + \__spath_split_at_normalised: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}} + \tl_gclear:N \g__spath_output_tl +} +\cs_generate_variant:Nn \spath_gsplit_at_normalised:NNnn {NNVn, NNVV, NNnV, ccvn} +\cs_new_protected_nopar:Npn \spath_split_at_normalised_keep_start:Nnn #1#2#3 +{ + \__spath_split_at_normalised:nn {#2}{#3} + \tl_set:Nx #1 {\tl_item:Nn \g__spath_output_tl {1}} + \tl_gclear:N \g__spath_output_tl +} +\cs_generate_variant:Nn \spath_split_at_normalised_keep_start:Nnn {NVn} +\cs_new_protected_nopar:Npn \spath_split_at_normalised_keep_start:Nn #1#2 +{ + \spath_split_at_normalised_keep_start:NVn #1#1{#2} +} +\cs_generate_variant:Nn \spath_split_at_normalised_keep_start:Nn {cn} +\cs_new_protected_nopar:Npn \spath_gsplit_at_normalised_keep_start:Nnn #1#2#3 +{ + \__spath_split_at_normalised:nn {#2}{#3} + \tl_gset:Nx #1 {\tl_item:Nn \g__spath_output_tl {1}} + \tl_gclear:N \g__spath_output_tl +} +\cs_generate_variant:Nn \spath_gsplit_at_normalised_keep_start:Nnn {NVn} +\cs_new_protected_nopar:Npn \spath_gsplit_at_normalised_keep_start:Nn #1#2 +{ + \spath_gsplit_at_normalised_keep_start:NVn #1#1{#2} +} +\cs_generate_variant:Nn \spath_gsplit_at_normalised_keep_start:Nn {cn} +\cs_new_protected_nopar:Npn \spath_split_at_normalised_keep_end:Nnn #1#2#3 +{ + \__spath_split_at_normalised:nn {#2}{#3} + \tl_set:Nx #1 {\tl_item:Nn \g__spath_output_tl {2}} + \tl_gclear:N \g__spath_output_tl +} +\cs_generate_variant:Nn \spath_split_at_normalised_keep_end:Nnn {NVn} +\cs_new_protected_nopar:Npn \spath_split_at_normalised_keep_end:Nn #1#2 +{ + \spath_split_at_normalised_keep_end:NVn #1#1{#2} +} +\cs_generate_variant:Nn \spath_split_at_normalised_keep_end:Nn {cn} +\cs_new_protected_nopar:Npn \spath_gsplit_at_normalised_keep_end:Nnn #1#2#3 +{ + \__spath_split_at_normalised:nn {#2}{#3} + \tl_gset:Nx #1 {\tl_item:Nn \g__spath_output_tl {2}} + \tl_gclear:N \g__spath_output_tl +} +\cs_generate_variant:Nn \spath_gsplit_at_normalised_keep_end:Nnn {NVn} +\cs_new_protected_nopar:Npn \spath_gsplit_at_normalised_keep_end:Nn #1#2 +{ + \spath_gsplit_at_normalised_keep_end:NVn #1#1{#2} +} +\cs_generate_variant:Nn \spath_gsplit_at_normalised_keep_end:Nn {cn} \cs_new_protected_nopar:Npn \spath_split_at:Nnn #1#2#3 { \__spath_split_at:nn {#2}{#3} @@ -2409,6 +3677,38 @@ manipulating PGF soft paths} { \spath_gsplit_at:NVn #1#1{#2} } +\cs_new_protected_nopar:Npn \spath_split_at_normalised:Nnn #1#2#3 +{ + \__spath_split_at_normalised:nn {#2}{#3} + \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_normalised:Nnn {NVn, NVV} +\cs_new_protected_nopar:Npn \spath_split_at_normalised:Nn #1#2 +{ + \spath_split_at_normalised:NVn #1#1{#2} +} +\cs_generate_variant:Nn \spath_split_at_normalised:Nn {cn} +\cs_new_protected_nopar:Npn \spath_gsplit_at_normalised:Nnn #1#2#3 +{ + \__spath_split_at_normalised:nn {#2}{#3} + \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_normalised:Nnn {NVn, NVV} +\cs_new_protected_nopar:Npn \spath_gsplit_at_normalised:Nn #1#2 +{ + \spath_gsplit_at_normalised:NVn #1#1{#2} +} +\cs_generate_variant:Nn \spath_gsplit_at_normalised:Nn {cn} \cs_new_protected_nopar:Npn \__spath_shorten_at_end:nn #1#2 { \int_compare:nTF @@ -2714,6 +4014,28 @@ manipulating PGF soft paths} \spath_gshorten_at_start:NVn #1#1{#2} } \cs_generate_variant:Nn \spath_gshorten_at_start:Nn {cn, cV, NV} +\cs_new_protected_nopar:Npn \spath_shorten_at_both_ends:Nnn #1#2#3 +{ + \spath_shorten_at_start:Nnn #1{#2}{#3} + \spath_shorten_at_end:Nnn #1{#2}{#3} +} +\cs_new_protected_nopar:Npn \spath_shorten_at_both_ends:Nn #1#2 +{ + \spath_shorten_at_start:Nn #1{#2} + \spath_shorten_at_end:Nn #1{#2} +} +\cs_generate_variant:Nn \spath_shorten_at_both_ends:Nn {cn, cV, NV} +\cs_new_protected_nopar:Npn \spath_gshorten_at_both_ends:Nnn #1#2#3 +{ + \spath_gshorten_at_start:Nnn #1{#2}{#3} + \spath_gshorten_at_end:Nnn #1{#2}{#3} +} +\cs_new_protected_nopar:Npn \spath_gshorten_at_both_ends:Nn #1#2 +{ + \spath_gshorten_at_start:Nn #1{#2} + \spath_gshorten_at_end:Nn #1{#2} +} +\cs_generate_variant:Nn \spath_gshorten_at_both_ends:Nn {cn, cV, NV} \cs_new_protected_nopar:Npn \__spath_point_at:nn #1#2 { \group_begin: @@ -2792,6 +4114,95 @@ manipulating PGF soft paths} } } + \c_spath_rectsize_tl + { + \fp_compare:nTF + { + \l__spath_tmpa_fp <= .25 + } + { + \tl_set:Nx \l__spath_tmpc_tl + { + {\fp_to_dim:n + { + ( \tl_item:Nn \l__spath_tmpa_tl {2} ) + + + 4 * \l__spath_tmpa_fp * ( \tl_item:Nn \l__spath_tmpa_tl {5} ) + } + } + {\fp_to_dim:n {\tl_item:Nn \l__spath_tmpa_tl {3} } } + } + } + { + \fp_compare:nTF + { + \l__spath_tmpa_fp <= .5 + } + { + \tl_set:Nx \l__spath_tmpc_tl + { + {\fp_to_dim:n + { + ( \tl_item:Nn \l__spath_tmpa_tl {2} ) + + + ( \tl_item:Nn \l__spath_tmpa_tl {5} ) + } + } + {\fp_to_dim:n + { + ( \tl_item:Nn \l__spath_tmpa_tl {3} ) + + + (4 * (\l__spath_tmpa_fp) - 1) * ( \tl_item:Nn \l__spath_tmpa_tl {6} ) + } + } + } + } + { + \fp_compare:nTF + { + \l__spath_tmpa_fp <= .75 + } + { + \tl_set:Nx \l__spath_tmpc_tl + { + {\fp_to_dim:n + { + ( \tl_item:Nn \l__spath_tmpa_tl {2} ) + + + (3 - 4 * (\l__spath_tmpa_fp)) *( \tl_item:Nn \l__spath_tmpa_tl {5} ) + } + } + {\fp_to_dim:n + { + ( \tl_item:Nn \l__spath_tmpa_tl {3} ) + + + ( \tl_item:Nn \l__spath_tmpa_tl {6} ) + } + } + } + + } + { + \tl_set:Nx \l__spath_tmpc_tl + { + {\fp_to_dim:n + { + ( \tl_item:Nn \l__spath_tmpa_tl {2} ) + } + } + {\fp_to_dim:n + { + ( \tl_item:Nn \l__spath_tmpa_tl {3} ) + + + (4 - 4 *(\l__spath_tmpa_fp)) * ( \tl_item:Nn \l__spath_tmpa_tl {6} ) + } + } + } + } + } + } + } + \c_spath_closepath_tl { \tl_set:Nx \l__spath_tmpc_tl @@ -2937,6 +4348,71 @@ manipulating PGF soft paths} } } + \c_spath_rectsize_tl + { + \fp_compare:nTF + { + \l__spath_tmpa_fp <= .25 + } + { + \tl_set:Nx \l__spath_tmpc_tl + { + {\fp_to_dim:n + { + \tl_item:Nn \l__spath_tmpa_tl {5} + } + } + {0pt} + } + } + { + \fp_compare:nTF + { + \l__spath_tmpa_fp <= .5 + } + { + \tl_set:Nx \l__spath_tmpc_tl + { + {0pt} + {\fp_to_dim:n + { + ( \tl_item:Nn \l__spath_tmpa_tl {6} ) + } + } + } + } + { + \fp_compare:nTF + { + \l__spath_tmpa_fp <= .75 + } + { + \tl_set:Nx \l__spath_tmpc_tl + { + {\fp_to_dim:n + { + -( \tl_item:Nn \l__spath_tmpa_tl {5} ) + } + } + {0pt} + } + + } + { + \tl_set:Nx \l__spath_tmpc_tl + { + {0pt} + {\fp_to_dim:n + { + - ( \tl_item:Nn \l__spath_tmpa_tl {6} ) + } + } + } + } + } + } + } + \c_spath_closepath_tl { \tl_set:Nx \l__spath_tmpc_tl @@ -3083,19 +4559,21 @@ manipulating PGF soft paths} \tl_set:Nn \l__spath_tmpb_tl {#1} \tl_set:Nn \l__spath_tmpc_tl {#2} - \spath_reallength:Nn \l__spath_tmpa_int {#1} - % Remember if the component is closed \spath_finalaction:NV \l__spath_tmpa_tl \l__spath_tmpb_tl \bool_set:Nn \l__spath_closed_bool { \tl_if_eq_p:NN \l__spath_tmpa_tl \c_spath_closepath_tl + || + \tl_if_eq_p:NN \l__spath_tmpa_tl \c_spath_rectcorner_tl } % Open it \spath_open:N \l__spath_tmpb_tl + \spath_reallength:NV \l__spath_tmpa_int \l__spath_tmpb_tl + % Sort intersections along the component \pgfintersectionsortbyfirstpath \spath_intersect:NN \l__spath_tmpb_tl \l__spath_tmpc_tl @@ -3118,6 +4596,7 @@ manipulating PGF soft paths} { \bool_set_false:N \l__spath_closed_bool } + \seq_get_right:NN \l__spath_tmpb_seq \l__spath_tmpa_tl \fp_compare:nT { @@ -3925,11 +5404,13 @@ manipulating PGF soft paths} { \pgfsyssoftpath@getcurrentpath #1 } +\cs_generate_variant:Nn \spath_get_current_path:N {c} \cs_new_protected_nopar:Npn \spath_gget_current_path:N #1 { \pgfsyssoftpath@getcurrentpath #1 \tl_gset_eq:NN #1 #1 } +\cs_generate_variant:Nn \spath_gget_current_path:N {c} \cs_new_protected_nopar:Npn \spath_protocol_path:n #1 { \spath_minbb:Nn \l__spath_tmpa_tl {#1} @@ -3958,10 +5439,13 @@ manipulating PGF soft paths} } \cs_new_protected_nopar:Npn \spath_tikz_path:nn #1#2 { - \path[#1] \pgfextra{ - \spath_set_current_path:n {#2} - \tl_put_right:Nn \tikz@preactions {\def\tikz@actions@path{#2}} - }; + \tl_if_empty:nF {#2} + { + \path[#1] \pgfextra{ + \spath_set_current_path:n {#2} + \tl_put_left:Nn \tikz@preactions {\def\tikz@actions@path{#2}} + }; + } } \cs_generate_variant:Nn \spath_tikz_path:nn {Vn, VV, nv, Vv, nV} \cs_new_protected_nopar:Npn \spath_set_tikz_data:n #1 @@ -3969,8 +5453,8 @@ manipulating PGF soft paths} \spath_finalpoint:Nn \l__spath_tmpa_tl {#1} \tl_set:Nx \l__spath_tmpa_tl { - \exp_not:c {pgf@x}=\tl_item:Nn \l__spath_tmpa_tl {1} - \exp_not:c {pgf@y}=\tl_item:Nn \l__spath_tmpa_tl {2} + \exp_not:c {pgf@x}=\tl_item:Nn \l__spath_tmpa_tl {1} \relax + \exp_not:c {pgf@y}=\tl_item:Nn \l__spath_tmpa_tl {2} \relax } \use:c {pgf@process}{% \tl_use:N \l__spath_tmpa_tl @@ -3979,32 +5463,41 @@ manipulating PGF soft paths} } \tl_set:Nx \l__spath_tmpa_tl { - \exp_not:c {tikz@lastx}=\exp_not:c {pgf@x} - \exp_not:c {tikz@lasty}=\exp_not:c {pgf@y} - \exp_not:c {tikz@lastxsaved}=\exp_not:c {pgf@x} - \exp_not:c {tikz@lastysaved}=\exp_not:c {pgf@y} + \exp_not:c {tikz@lastx}=\exp_not:c {pgf@x} \relax + \exp_not:c {tikz@lasty}=\exp_not:c {pgf@y} \relax + \exp_not:c {tikz@lastxsaved}=\exp_not:c {pgf@x} \relax + \exp_not:c {tikz@lastysaved}=\exp_not:c {pgf@y} \relax } \tl_use:N \l__spath_tmpa_tl \spath_finalmovepoint:Nn \l__spath_tmpa_tl {#1} - \ifpgfsyssoftpathmovetorelevant% - \tl_gset_eq:cN {pgfsyssoftpath@lastmoveto} \l__spath_tmpa_tl - \fi + \bool_if:NT \l_spath_movetorelevant_bool + { + \ifpgfsyssoftpathmovetorelevant% + \tl_gset_eq:cN {pgfsyssoftpath@lastmoveto} \l__spath_tmpa_tl + \fi + } \tl_set:Nx \l__spath_tmpa_tl { - \exp_not:c {pgf@x}=\tl_item:Nn \l__spath_tmpa_tl {1} - \exp_not:c {pgf@y}=\tl_item:Nn \l__spath_tmpa_tl {2} + \exp_not:c {pgf@x}=\tl_item:Nn \l__spath_tmpa_tl {1} \relax + \exp_not:c {pgf@y}=\tl_item:Nn \l__spath_tmpa_tl {2} \relax } \use:c {pgf@process}{% \tl_use:N \l__spath_tmpa_tl \pgftransforminvert \use:c {pgf@pos@transform@glob} } - \tl_set:Nx \l__spath_tmpa_tl + \bool_if:NT \l_spath_movetorelevant_bool { - \exp_not:c {tikz@lastmovetox}=\exp_not:c {pgf@x} - \exp_not:c {tikz@lastmovetoy}=\exp_not:c {pgf@y} + \dim_if_exist:cT {tikz@lastmovetox} + { + \tl_set:Nx \l__spath_tmpa_tl + { + \exp_not:c {tikz@lastmovetox}=\exp_not:c {pgf@x} \relax + \exp_not:c {tikz@lastmovetoy}=\exp_not:c {pgf@y} \relax + } + \tl_use:N \l__spath_tmpa_tl + } } - \tl_use:N \l__spath_tmpa_tl \tl_clear_new:c {tikz@timer} \tl_set:cn {tikz@timer} { diff --git a/Master/texmf-dist/tex/latex/spath3/tikzlibraryknots.code.tex b/Master/texmf-dist/tex/latex/spath3/tikzlibraryknots.code.tex index c6ae085925a..f075665178c 100644 --- a/Master/texmf-dist/tex/latex/spath3/tikzlibraryknots.code.tex +++ b/Master/texmf-dist/tex/latex/spath3/tikzlibraryknots.code.tex @@ -59,6 +59,7 @@ \bool_new:N \l__knot_append_next_bool \bool_new:N \l__knot_skip_bool \bool_new:N \l__knot_save_bool +\bool_new:N \l__knot_debugging_bool \seq_new:N \g__knot_nodes_seq @@ -191,6 +192,14 @@ \bool_set_true:N \l__knot_draft_bool \bool_set_true:N \l__knot_super_draft_bool }, + debug/.is~ choice, + debug/true/.code={ + \bool_set_true:N \l__knot_debugging_bool + }, + debug/false/.code={ + \bool_set_false:N \l__knot_debugging_bool + }, + debug/.default=true, draft/.is~ family, draft, crossing~ label/.style={ @@ -212,8 +221,18 @@ inner~ sep=0pt }, } +\cs_new_nopar:Npn \knot_debug:n #1 +{ + \bool_if:NT \l__knot_debugging_bool + { + \iow_term:n {===Knot~ debug: #1===} + } +} + +\cs_generate_variant:Nn \knot_debug:n {x} \cs_new_nopar:Npn \knot_apply_style:N #1 { + \knot_debug:n {knot~ apply~ style} \tl_if_exist:NT #1 { \exp_args:NV \tikzset #1 } @@ -239,6 +258,7 @@ } \cs_new_protected_nopar:Npn \knot_initialise:n #1 { + \knot_debug:n {knot~ initialise} \tikzset{knot~ diagram/.cd,every~ knot~ diagram/.try,#1} \int_zero:N \l__knot_strands_int \tl_clear:N \l__knot_redraws_tl @@ -246,6 +266,7 @@ } \cs_new_protected_nopar:Npn \knot_render: { + \knot_debug:n {knot~ render} \pgfscope \pgftransformreset \dim_set:Nn \l__knot_redraw_tolerance_dim {\fp_to_dim:n @@ -296,9 +317,12 @@ \seq_use:Nn \g__knot_nodes_seq {} } \endpgfscope + \knot_debug:x {knot~rendered, + ~found~\int_use:N \g__knot_intersections_int \c_space_tl~intersections} } \cs_new_protected_nopar:Npn \knot_draw_strand:n #1 { + \knot_debug:n {knot~ draw~ strand~ #1} \pgfscope \group_begin: \spath_bake_round:c {knot strand #1} @@ -308,7 +332,7 @@ { , knot~ diagram/only~ when~ rendering/.try, - only~ when~ rendering/.try + only~ when~ rendering/.try, } \spath_tikz_path:Vv \l__knot_tmpa_tl {knot strand #1} \group_end: @@ -317,6 +341,7 @@ \cs_generate_variant:Nn \tl_put_right:Nn {Nv} \cs_new_protected_nopar:Npn \knot_draw_labels:n #1 { + \knot_debug:n {knot~ draw~ labels} \bool_if:NT \l__knot_draft_bool { \spath_finalpoint:Nv \l__knot_tmpb_tl {knot strand #1} @@ -348,6 +373,7 @@ } \cs_new_protected_nopar:Npn \knot_split_self_intersects:N #1 { + \knot_debug:n {knot~ split~ self~ intersects} \tl_set:Nx \l__knot_tmpc_tl {\tl_item:nn {#1} {4}} \tl_case:NnF \l__knot_tmpc_tl { @@ -385,9 +411,11 @@ } { \fp_set:Nn \l__knot_tmpa_fp {.5 * \l__knot_tmpa_fp / \l__knot_tmpb_fp} - \fp_compare:nTF + \bool_if:nTF { - 0 < \l__knot_tmpa_fp && \l__knot_tmpa_fp < 1 + \fp_compare_p:n {0 < \l__knot_tmpa_fp} + && + \fp_compare_p:n {\l__knot_tmpa_fp < 1} } { \spath_split_curve:NNnV @@ -435,6 +463,8 @@ } \cs_new_protected_nopar:Npn \knot_intersections:nn #1#2 { + \knot_debug:x {knot~ intersections~ between~ + \l__knot_prefix_tl \c_space_tl #1~ and~ #2} \group_begin: \tl_set_eq:NN \l__knot_tmpa_tl \l__knot_prefix_tl \tl_put_right:Nn \l__knot_tmpa_tl {#1} @@ -466,6 +496,7 @@ } + \knot_debug:x {found~\pgfintersectionsolutions\c_space_tl~ intersections} \int_compare:nT {\pgfintersectionsolutions > 0} { \int_step_function:nnnN @@ -480,6 +511,7 @@ } \cs_new_protected_nopar:Npn \knot_save_intersections:nn #1#2 { + \knot_debug:n {knot~ save~ intersections} \bool_if:NT \l__knot_save_bool { \tl_clear:N \l__knot_aux_tl @@ -527,9 +559,12 @@ \cs_generate_variant:Nn \knot_save_intersections:nn {VV} \cs_new_protected_nopar:Npn \knot_do_intersection:n #1 { + \knot_debug:n {knot~ do~ intersection~ #1} \pgfpointintersectionsolution{#1} \dim_set:Nn \l__knot_tmpa_dim {\pgf@x} \dim_set:Nn \l__knot_tmpb_dim {\pgf@y} + \knot_debug:x {intersection~at~ + (\dim_use:N \l__knot_tmpa_dim,\dim_use:N \l__knot_tmpb_dim)} \bool_set_false:N \l__knot_skip_bool \bool_if:NT \l__knot_self_intersections_bool { @@ -578,6 +613,7 @@ { \int_gincr:N \g__knot_intersections_int + \knot_debug:x {Processing~intersection~\int_use:N \g__knot_intersections_int} \bool_if:nF { \tl_if_exist_p:c {l__knot_ignore_crossing_ \int_use:N @@ -643,6 +679,8 @@ !\tl_if_empty_p:c {knot previous \tl_use:N \l__knot_tmpg_tl} } { + \knot_debug:x {Prepending~ + \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}} @@ -650,9 +688,13 @@ { \l__knot_splits_bool && - \tl_if_exist_p:c {knot previous \tl_use:N \l__knot_tmpg_tl} + \tl_if_exist_p:c {knot previous + \tl_use:c {knot previous \tl_use:N \l__knot_tmpg_tl} + } && - !\tl_if_empty_p:c {knot previous \tl_use:N \l__knot_tmpg_tl} + !\tl_if_empty_p:c {knot previous + \tl_use:c {knot previous \tl_use:N \l__knot_tmpg_tl} + } } { \knot_test_endpoint:NvnT @@ -660,6 +702,11 @@ {knot previous \tl_use:N \l__knot_tmpg_tl} {initial point} { + \knot_debug:x {Prepending~ + \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 @@ -667,19 +714,23 @@ {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} + \tl_set_eq:Nc \l__knot_tmpa_tl + {knot \tl_use:N \l__knot_prefix_tl -1} } } } + \bool_if:nT { \l__knot_append_next_bool && \tl_if_exist_p:c {knot next \tl_use:N \l__knot_tmpg_tl} && - !\tl_if_empty_p:c {knot previous \tl_use:N \l__knot_tmpg_tl} + !\tl_if_empty_p:c {knot next \tl_use:N \l__knot_tmpg_tl} } { + \knot_debug:x {Appending~ + \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}} @@ -687,17 +738,25 @@ { \l__knot_splits_bool && - \tl_if_exist_p:c {knot previous \tl_use:N - \l__knot_tmpg_tl} + \tl_if_exist_p:c {knot next \tl_use:c { knot next \tl_use:N + \l__knot_tmpg_tl}} && - !\tl_if_empty_p:c {knot previous \tl_use:N \l__knot_tmpg_tl} + !\tl_if_empty_p:c {knot next + \tl_use:c { knot next \tl_use:N \l__knot_tmpg_tl} + } } { + \knot_debug:x {Testing~ whether~ to~ append~ + {knot next \tl_use:c { knot next \tl_use:N \l__knot_tmpg_tl}} + } \knot_test_endpoint:NvnT \l__knot_redraw_tolerance_dim - {knot previous \tl_use:N \l__knot_tmpg_tl} + {knot next \tl_use:N \l__knot_tmpg_tl} {final point} { + \knot_debug:x {Appending~ + {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 @@ -773,6 +832,7 @@ \cs_generate_variant:Nn \knot_test_endpoint:NnnTF {NVnTF,NvnTF} \cs_new_protected_nopar:Npn \knot_draw_crossing:nnn #1#2#3 { + \knot_debug:n {knot~ draw~ crossing} \group_begin: \pgfscope \path[knot~ diagram/background~ clip] (#2, #3) @@ -821,17 +881,20 @@ } \cs_new_protected_nopar:Npn \knot_split_strands: { + \knot_debug:n {knot~ split~ strands} \int_gzero:N \g__knot_filaments_int \int_step_function:nnnN {1} {1} {\l__knot_strands_int} \knot_split_strand:n \int_step_function:nnnN {1} {1} {\g__knot_filaments_int} \knot_compute_nexts:n } \cs_new_protected_nopar:Npn \knot_compute_nexts:n #1 { + \knot_debug:n {knot~ compute~ nexts} \tl_clear_new:c {knot next \tl_use:c {knot previous filament #1}} \tl_set:cn {knot next \tl_use:c {knot previous filament #1}} {filament #1} } \cs_new_protected_nopar:Npn \knot_split_strand:n #1 { + \knot_debug:n {knot~ split~ strand} \int_set_eq:NN \l__knot_component_start_int \g__knot_filaments_int \int_incr:N \l__knot_component_start_int \tl_set_eq:Nc \l__knot_tmpa_tl {l__knot_options_strand #1} @@ -840,6 +903,7 @@ } \cs_new_protected_nopar:Npn \knot_save_filament:N #1 { + \knot_debug:n {knot~ save~ filament} \tl_set:Nx \l__knot_tmpb_tl {\tl_item:nn {#1} {4}} \tl_case:NnF \l__knot_tmpb_tl { diff --git a/Master/texmf-dist/tex/latex/spath3/tikzlibraryspath3.code.tex b/Master/texmf-dist/tex/latex/spath3/tikzlibraryspath3.code.tex index bd81706e3b9..47f61c587d7 100644 --- a/Master/texmf-dist/tex/latex/spath3/tikzlibraryspath3.code.tex +++ b/Master/texmf-dist/tex/latex/spath3/tikzlibraryspath3.code.tex @@ -16,32 +16,78 @@ \RequirePackage{expl3} \ExplSyntaxOn -\tl_new:N \l__spath_current_tl -\tl_new:N \l__spath_reverse_tl -\tl_new:N \l__spath_prefix_tl -\tl_new:N \l__spath_suffix_tl -\tl_new:N \g__spath_smuggle_tl -\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:nnnn { spath3 } { empty soft path } { Soft~ path~ #1~ is~ empty} +\tl_new:N \l__tikzspath_tmpa_tl +\tl_new:N \l__tikzspath_tmpb_tl +\tl_new:N \l__tikzspath_tmpc_tl +\tl_new:N \l__tikzspath_tmpd_tl +\tl_new:N \l__tikzspath_tmpe_tl +\tl_new:N \l__tikzspath_tmpf_tl + +\int_new:N \l__tikzspath_tmpa_int +\seq_new:N \l__tikzspath_tmpa_seq +\seq_new:N \l__tikzspath_tmpb_seq +\seq_new:N \l__tikzspath_tmpc_seq +\seq_new:N \l__tikzspath_tmpd_seq + +\tl_new:N \l__tikzspath_current_tl +\tl_new:N \l__tikzspath_reverse_tl +\tl_new:N \l__tikzspath_prefix_tl +\tl_new:N \l__tikzspath_suffix_tl +\tl_new:N \g__tikzspath_smuggle_tl +\tl_new:N \g__tikzspath_output_tl +\tl_new:N \l__tikzspath_check_tl +\clist_new:N \g__tikzspath_output_clist +\seq_new:N \g__tikzspath_tmpa_seq +\seq_new:N \g__tikzspath_tmpb_seq +\seq_new:N \g__tikzspath_output_seq +\bool_new:N \l__tikzspath_draft_bool +\msg_new:nnn { spath3 } { missing soft path } +{ Soft~ path~ #1~ doesn't~ exist~ \msg_line_context:} +\msg_new:nnnn { spath3 } { empty soft path } +{ Soft~ path~ #1~ is~ empty~ \msg_line_context:} {If~ it~ was~ defined~ inside~ a~ group,~ try~ using~ "save~ global". } \msg_new:nnn { spath3 } { load intersections } -{ You~ need~ to~ load~ the~ "intersections"~ library~ to~ work~ with~ intersections } -\tl_set:Nn \l__spath_prefix_tl {tikz@intersect@path@name@} -\tl_set:Nn \l__spath_suffix_tl {} -\tl_new:N \g__spath_tikzfinish_tl +{ You~ need~ to~ load~ the~ "intersections"~ library~ + to~ work~ with~ intersections } +\tl_set:Nn \l__tikzspath_prefix_tl {tikz@intersect@path@name@} +\tl_set:Nn \l__tikzspath_suffix_tl {} +\tl_new:N \g__tikzspath_tikzfinish_tl +\tl_new:N \l__tikzspath_tikzfinish_outside_tl \cs_new_protected_nopar:Npn \spath_at_end_of_path: { - \tl_use:N \g__spath_tikzfinish_tl - \tl_gclear:N \g__spath_tikzfinish_tl + \tl_use:N \g__tikzspath_tikzfinish_tl + \tl_gclear:N \g__tikzspath_tikzfinish_tl } \tl_put_right:Nn \tikz@finish {\spath_at_end_of_path:} +\tikzset{ + every~ scope/.append~ style={ + execute~ at~ begin~ scope={ + \tl_set_eq:NN \l__tikzspath_tikzfinish_outside_tl \g__tikzspath_tikzfinish_tl + }, + execute~ at~ end~ scope={ + \tl_use:N \g__tikzspath_tikzfinish_tl + \tl_gclear:N \g__tikzspath_tikzfinish_tl + \tl_gset_eq:NN \g__tikzspath_tikzfinish_tl \l__tikzspath_tikzfinish_outside_tl + }, + }, +} +\tl_new:N \l__tikzspath_tikzpath_finish_tl + +\cs_new_protected_nopar:Npn \__tikzspath_at_end_of_path_construction: +{ + \tl_use:N \l__tikzspath_tikzpath_finish_tl + \tl_clear:N \l__tikzspath_tikzpath_finish_tl +} + +\tl_put_left:Nn \tikz@finish {\__tikzspath_at_end_of_path_construction:} \cs_new_protected_nopar:Npn \spath_save_path:Nn #1#2 { - \tl_gput_right:Nn \g__spath_tikzfinish_tl + \tl_if_empty:NF \g__tikzspath_tikzfinish_tl + { + \tl_use:N \g__tikzspath_tikzfinish_tl + } + \tl_gput_right:Nn \g__tikzspath_tikzfinish_tl { \tl_clear_new:N #1 \tl_set:Nn #1 {#2} @@ -51,36 +97,214 @@ \cs_new_protected_nopar:Npn \spath_gsave_path:Nn #1#2 { - \tl_gput_right:Nn \g__spath_tikzfinish_tl + \tl_gput_right:Nn \g__tikzspath_tikzfinish_tl { \tl_gclear_new:N #1 \tl_gset:Nn #1 {#2} } } \cs_generate_variant:Nn \spath_gsave_path:Nn {cn, NV, cV} -\cs_new_protected_nopar:Npn \__spath_process_tikz_point:Nn #1#2 +\cs_new_protected_nopar:Npn \__tikzspath_process_tikz_point:Nn #1#2 { \group_begin: \use:c {tikz@scan@one@point} \use:n #2 \scan_stop: - \tl_gset:Nx \g__spath_output_tl + \tl_gset:Nx \g__tikzspath_output_tl { { \dim_use:c {pgf@x} } { \dim_use:c {pgf@y} } } \group_end: - \tl_set_eq:NN #1 \g__spath_output_tl - \tl_gclear:N \g__spath_output_tl -} -\cs_set_eq:NN \__spath_tikzset:n \tikzset -\cs_generate_variant:Nn \__spath_tikzset:n {V, v} -\bool_new:N \l__spath_reverse_bool -\bool_new:N \l__spath_weld_bool -\bool_new:N \l__spath_move_bool -\bool_new:N \l__spath_global_bool -\tl_new:N \l__spath_joinpath_tl -\tl_new:N \l__spath_transformation_tl - -\cs_new_protected_nopar:Npn \__spath_set_bool:Nn #1#2 + \tl_set_eq:NN #1 \g__tikzspath_output_tl + \tl_gclear:N \g__tikzspath_output_tl +} +\cs_set_eq:NN \__tikzspath_tikzset:n \tikzset +\cs_generate_variant:Nn \__tikzspath_tikzset:n {V, v} +\cs_new_protected_nopar:Npn \__tikzspath_check_path:nnn #1#2#3 +{ + \tl_set:Nn \l__tikzspath_check_tl {#3} + \tl_if_exist:cTF {\__tikzspath_path_name:n {#2}} + { + \tl_if_empty:cTF {\__tikzspath_path_name:n {#2}} + { + \msg_warning:nnn { spath3 } { empty soft path } { #2 } + } + { + \tl_set:Nn \l__tikzspath_check_tl { + #1 {\__tikzspath_path_name:n {#2}} + } + } + } + { + \msg_warning:nnn { spath3 } { missing soft path } { #2 } + } + \tl_use:N \l__tikzspath_check_tl +} +\cs_new_protected_nopar:Npn \__tikzspath_check_two_paths:nnnn #1#2#3#4 +{ + \__tikzspath_check_path:nnn { + \__tikzspath_check_path:nnn {#1}{#2}{#4} + }{#3}{#4} +} +\cs_new_protected_nopar:Npn \__tikzspath_check_three_paths:nnnnn #1#2#3#4#5 +{ + \__tikzspath_check_path:nnn { + \__tikzspath_check_path:nnn { + \__tikzspath_check_path:nnn {#1}{#2}{#5} + }{#3}{#5} + }{#4}{#5} +} +\cs_generate_variant:Nn \__tikzspath_check_path:nnn {nVn} +\cs_generate_variant:Nn \__tikzspath_check_two_paths:nnnn {nnVn} +\cs_new_protected_nopar:Npn \__tikzspath_maybe_current_path:nn #1#2 +{ + \tl_if_eq:nnT {#2} {current} + { + \spath_get_current_path:c {\__tikzspath_path_name:n {#2}} + } + #1 {#2} +} +\cs_new_protected_nopar:Npn \__tikzspath_maybe_current_path_reuse:nnn #1#2#3 +{ + \bool_set_true:N \l_spath_movetorelevant_bool + \tl_if_eq:nnT {#2} {current} + { + \spath_get_current_path:c {\__tikzspath_path_name:n {#2}} + } + #1 {#2} #3 + \tl_if_eq:nnT {#2} {current} + { + \tl_if_empty:cF {\__tikzspath_path_name:n {#2}} + { + \spath_set_current_path:c {\__tikzspath_path_name:n {#2}} + \spath_set_tikz_data:v {\__tikzspath_path_name:n {#2}} + } + } +} +\cs_new_protected_nopar:Npn \__tikzspath_maybe_current_two_paths_reuse_both:nnnn #1#2#3#4 +{ + \bool_set_true:N \l_spath_movetorelevant_bool + \tl_if_eq:nnT {#2} {current} + { + \spath_get_current_path:c {\__tikzspath_path_name:n {#2}} + } + \tl_if_eq:nnT {#3} {current} + { + \spath_get_current_path:c {\__tikzspath_path_name:n {#3}} + } + #1 {#2} {#3} #4 + \tl_if_eq:nnT {#2} {current} + { + \tl_if_empty:cF {\__tikzspath_path_name:n {#2}} + { + \spath_set_current_path:c {\__tikzspath_path_name:n {#2}} + \spath_set_tikz_data:v {\__tikzspath_path_name:n {#2}} + } + } + \tl_if_eq:nnT {#3} {current} + { + \tl_if_empty:cF {\__tikzspath_path_name:n {#3}} + { + \spath_set_current_path:c {\__tikzspath_path_name:n {#3}} + \spath_set_tikz_data:v {\__tikzspath_path_name:n {#3}} + } + } +} +\cs_new_protected_nopar:Npn \__tikzspath_maybe_current_two_paths_reuse_first:nnnn #1#2#3#4 +{ + \bool_set_true:N \l_spath_movetorelevant_bool + \tl_if_eq:nnT {#2} {current} + { + \spath_get_current_path:c {\__tikzspath_path_name:n {#2}} + } + \tl_if_eq:nnT {#3} {current} + { + \spath_get_current_path:c {\__tikzspath_path_name:n {#3}} + } + #1 {#2} {#3} #4 + \tl_if_eq:nnT {#2} {current} + { + \tl_if_empty:cF {\__tikzspath_path_name:n {#2}} + { + \spath_set_current_path:c {\__tikzspath_path_name:n {#2}} + \spath_set_tikz_data:v {\__tikzspath_path_name:n {#2}} + } + } +} +\cs_new_protected_nopar:Npn \__tikzspath_maybe_current_two_paths_reuse_second:nnnn #1#2#3#4 +{ + \bool_set_true:N \l_spath_movetorelevant_bool + \tl_if_eq:nnT {#2} {current} + { + \spath_get_current_path:c {\__tikzspath_path_name:n {#2}} + } + \tl_if_eq:nnT {#3} {current} + { + \spath_get_current_path:c {\__tikzspath_path_name:n {#3}} + } + #1 {#2} {#3} #4 + \tl_if_eq:nnT {#3} {current} + { + \tl_if_empty:cF {\__tikzspath_path_name:n {#3}} + { + \spath_set_current_path:c {\__tikzspath_path_name:n {#3}} + \spath_set_tikz_data:v {\__tikzspath_path_name:n {#3}} + } + } +} +\cs_generate_variant:Nn \__tikzspath_maybe_current_path:nn {nV} +\cs_generate_variant:Nn \__tikzspath_maybe_current_path_reuse:nnn {nVn} +\cs_new_protected_nopar:Npn \__tikzspath_seq_from_foreach:Nnn #1#2#3 +{ + \group_begin: + \seq_gclear:N \g__tikzspath_output_seq + + \tl_if_empty:nTF {#3} + { + \int_step_inline:nnnn {1}{1} {#2} + { + \seq_gput_right:Nn \g__tikzspath_output_seq {##1} + } + } + { + \foreach \l__tikzspath_tmpa_tl in {#3} + { + \int_compare:nTF { \l__tikzspath_tmpa_tl > 0 } + { + \seq_gput_right:NV \g__tikzspath_output_seq \l__tikzspath_tmpa_tl + } + { + \seq_gput_right:Nx \g__tikzspath_output_seq + {\int_eval:n {#2 - \l__tikzspath_tmpa_tl}} + } + } + \seq_gsort:Nn \g__tikzspath_output_seq + { + \int_compare:nNnTF {##1} < {##2} + { \sort_return_same: } + { \sort_return_swapped: } + } + } + \group_end: + \seq_set_eq:NN #1 \g__tikzspath_output_seq + \seq_gclear:N \g__tikzspath_output_seq +} +\cs_generate_variant:Nn \__tikzspath_seq_from_foreach:Nnn {NVV, NVn} +\cs_new:Npn \__tikzspath_path_name:n #1 +{ + \tl_use:N \l__tikzspath_prefix_tl + #1 + \tl_use:N \l__tikzspath_suffix_tl +} +\cs_generate_variant:Nn \__tikzspath_path_name:n {V} +\bool_new:N \l__tikzspath_reverse_bool +\bool_new:N \l__tikzspath_weld_bool +\bool_new:N \l__tikzspath_move_bool +\bool_new:N \l__tikzspath_global_bool +\bool_new:N \l__tikzspath_current_transformation_bool +\tl_new:N \l__tikzspath_joinpath_tl +\tl_new:N \l__tikzspath_transformation_tl + +\cs_new_protected_nopar:Npn \__tikzspath_set_bool:Nn #1#2 { \tl_if_eq:nnTF {#2}{false} { @@ -94,230 +318,804 @@ spath/join/.is~ family, spath/join/.cd, reverse/.code = { - \__spath_set_bool:Nn \l__spath_reverse_bool {#1} + \__tikzspath_set_bool:Nn \l__tikzspath_reverse_bool {#1} }, reverse/.default = true, weld/.code = { - \__spath_set_bool:Nn \l__spath_weld_bool {#1} + \__tikzspath_set_bool:Nn \l__tikzspath_weld_bool {#1} }, weld/.default = true, no~ weld/.code = { - \__spath_set_bool:Nn \l__spath_weld_bool {#1} - \bool_set:Nn \l__spath_weld_bool {! \l__spath_weld_bool} + \__tikzspath_set_bool:Nn \l__tikzspath_weld_bool {#1} + \bool_set:Nn \l__tikzspath_weld_bool {! \l__tikzspath_weld_bool} }, no~ weld/.default = true, move/.code = { - \__spath_set_bool:Nn \l__spath_move_bool {#1} + \__tikzspath_set_bool:Nn \l__tikzspath_move_bool {#1} }, move/.default = true, no~ move/.code = { - \__spath_set_bool:Nn \l__spath_move_bool {#1} - \bool_set:Nn \l__spath_move_bool {! \l__spath_move_bool} + \__tikzspath_set_bool:Nn \l__tikzspath_move_bool {#1} + \bool_set:Nn \l__tikzspath_move_bool {! \l__tikzspath_move_bool} }, no~ move/.default = true, global/.code = { - \__spath_set_bool:Nn \l__spath_global_bool {#1} + \__tikzspath_set_bool:Nn \l__tikzspath_global_bool {#1} }, global/.default = true, - transform/.store~in=\l__spath_transformation_tl, + use~ current~ transformation/.code={ + \__tikzspath_set_bool:Nn \l__tikzspath_current_transformation_bool {#1} + }, + use~ current~ transformation/.default = true, + transform/.store~in=\l__tikzspath_transformation_tl, .unknown/.code = { - \tl_set_eq:NN \l__spath_joinpath_tl \pgfkeyscurrentname + \tl_set_eq:NN \l__tikzspath_joinpath_tl \pgfkeyscurrentname } } \cs_set_eq:NN \getComponentOf \clist_item:Nn -\tikzset{ - spath/.is~family, - spath/.cd, - set~ prefix/.store~ in=\l__spath_prefix_tl, - prefix/.is~choice, - prefix/default/.style={ - /tikz/spath/set~ prefix=tikz@intersect@path@name@ - }, - set~ suffix/.store~ in=\l__spath_suffix_tl, - suffix/.is~choice, - suffix/default/.style={ - /tikz/spath/set~ suffix={} - }, - set~ name/.style={ - /tikz/spath/prefix=#1, - /tikz/spath/suffix=#1 - }, - save/.code={ - \tikz@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 - } - }, - save~ global/.code={ - \tikz@addmode{ - \spath_get_current_path:N \l__spath_tmpa_tl - \spath_bake_round:NV \l__spath_tmpa_tl \l__spath_tmpa_tl - \spath_gsave_path:cV - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - \l__spath_tmpa_tl +\cs_new_protected_nopar:Npn \__tikzspath_use_path:n #1 +{ + \tl_set:Nn \l__tikzspath_joinpath_tl {#1} + \spath_get_current_path:N \l__tikzspath_current_tl + + \bool_if:NT \l__tikzspath_reverse_bool + { + \spath_reverse:N \l__tikzspath_joinpath_tl + } + + \bool_if:NT \l__tikzspath_current_transformation_bool + { + \pgfgettransform \l__tikzspath_tmpa_tl + \spath_transform:NV + \l__tikzspath_joinpath_tl + \l__tikzspath_tmpa_tl + } + + \tl_if_empty:NF \l__tikzspath_transformation_tl + { + \group_begin: + \pgftransformreset + \__tikzspath_tikzset:V \l__tikzspath_transformation_tl + \pgfgettransform \l__tikzspath_tmpa_tl + \tl_gset:Nn \g__tikzspath_smuggle_tl + { + \spath_transform:Nnnnnnn + \l__tikzspath_joinpath_tl } - }, - clone/.code~ 2~ args={ - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl} + \tl_gput_right:NV \g__tikzspath_smuggle_tl \l__tikzspath_tmpa_tl + \group_end: + \tl_use:N \g__tikzspath_smuggle_tl + } + + \bool_if:NT \l__tikzspath_move_bool + { + \tl_if_empty:NTF \l__tikzspath_current_tl { - \tl_clear_new:c - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - \tl_set_eq: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} + \tl_set:Nn \l__tikzspath_tmpc_tl { {0pt} {0pt} } } { - \msg_warning:nnn { spath3 } { missing soft path } { #2 } + \spath_finalpoint:NV + \l__tikzspath_tmpc_tl + \l__tikzspath_current_tl } - }, - clone~ global/.code~ 2~ args={ - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl} + \spath_translate_to:NV \l__tikzspath_joinpath_tl \l__tikzspath_tmpc_tl + } + + \tl_if_empty:NTF \l__tikzspath_current_tl + { + \tl_if_empty:NTF \l__tikzspath_joinpath_tl { - \tl_gclear_new:c - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - \tl_gset_eq: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} + \tl_set_eq:NN \l__tikzspath_current_tl \c_spath_moveto_tl + \tl_put_right:Nn \l__tikzspath_current_tl {{0pt}{0pt}} } { - \msg_warning:nnn { spath3 } { missing soft path } { #2 } + \tl_set_eq:NN \l__tikzspath_current_tl \l__tikzspath_joinpath_tl } - }, - save~ to~ aux/.code={ - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + } + { + + \tl_clear:N \l__tikzspath_tmpa_tl + \tl_set:Nn \l__tikzspath_tmpa_tl {spath_} + + \tl_put_right:Nn \l__tikzspath_tmpa_tl {append} + + \bool_if:NT \l__tikzspath_weld_bool { - \spath_save_to_aux:c - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + \tl_put_right:Nn \l__tikzspath_tmpa_tl {_no_move} + \spath_numberofcomponents:NV \l__tikzspath_tmpa_int \l__tikzspath_joinpath_tl + \int_compare:nT {\l__tikzspath_tmpa_int == 1} + { + \bool_set_false:N \l_spath_movetorelevant_bool + } } + \tl_put_right:Nn \l__tikzspath_tmpa_tl {:NV} + + \use:c {\tl_use:N \l__tikzspath_tmpa_tl } + \l__tikzspath_current_tl + \l__tikzspath_joinpath_tl + } + + \spath_set_current_path:N \l__tikzspath_current_tl + \spath_set_tikz_data:V \l__tikzspath_joinpath_tl +} +\cs_generate_variant:Nn \__tikzspath_use_path:n {V, v} +\cs_new_protected_nopar:Npn \__tikzspath_join_with:Nn #1#2 +{ + \tl_set:Nn \l__tikzspath_joinpath_tl {#2} + + \bool_if:NT \l__tikzspath_reverse_bool + { + \spath_reverse:N \l__tikzspath_joinpath_tl + } + + \tl_if_empty:NF \l__tikzspath_transformation_tl + { + \group_begin: + \pgftransformreset + \__tikzspath_tikzset:V \l__tikzspath_transformation_tl + \pgfgettransform \l__tikzspath_tmpa_tl + \tl_gset:Nn \g__tikzspath_smuggle_tl { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } + \spath_transform:Nnnnnnn + \l__tikzspath_joinpath_tl } - }, - export~ to~ svg/.code={ - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + \tl_gput_right:NV \g__tikzspath_smuggle_tl \l__tikzspath_tmpa_tl + \group_end: + \tl_use:N \g__tikzspath_smuggle_tl + } + + \bool_if:NT \l__tikzspath_move_bool + { + \spath_finalpoint:NV + \l__tikzspath_tmpc_tl + #1 + \spath_translate_to:NV \l__tikzspath_joinpath_tl \l__tikzspath_tmpc_tl + } + + \tl_clear:N \l__tikzspath_tmpa_tl + \tl_set:Nn \l__tikzspath_tmpa_tl {spath_} + + \bool_if:NT \l__tikzspath_global_bool + { + \tl_put_right:Nn \l__tikzspath_tmpa_tl {g} + } + + \tl_put_right:Nn \l__tikzspath_tmpa_tl {append} + + \bool_if:NT \l__tikzspath_weld_bool + { + \tl_put_right:Nn \l__tikzspath_tmpa_tl {_no_move} + } + \tl_put_right:Nn \l__tikzspath_tmpa_tl {:NV} + + \cs_if_exist:cF {\tl_use:N \l__tikzspath_tmpa_tl} + { + \tl_show:N \l__tikzspath_tmpa_tl + } + + \use:c {\tl_use:N \l__tikzspath_tmpa_tl } #1 + \l__tikzspath_joinpath_tl +} +\cs_generate_variant:Nn \__tikzspath_join_with:Nn {cv, cn} +\cs_new_protected_nopar:Npn \__tikzspath_join_components_with_aux:nnn #1#2#3 +{ + \group_begin: + \tl_set:Nn \l__tikzspath_tmpc_tl {#1} + \tl_if_empty:nT {#3} + { + \spath_spot_weld_components:N \l__tikzspath_tmpc_tl + } + + \spath_numberofcomponents:NV \l__tikzspath_tmpa_int \l__tikzspath_tmpc_tl + \__tikzspath_seq_from_foreach:NVn \l__tikzspath_tmpb_seq \l__tikzspath_tmpa_int {#3} + + \spath_components_to_seq:NV \l__tikzspath_tmpa_seq \l__tikzspath_tmpc_tl + + \seq_pop_left:NN \l__tikzspath_tmpa_seq \l__tikzspath_tmpa_tl + \seq_pop_left:NN \l__tikzspath_tmpb_seq \l__tikzspath_tmpb_tl + + \seq_map_indexed_inline:Nn \l__tikzspath_tmpa_seq + { + \int_compare:nTF { - \spath_export_to_svg:nv {#1} - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + ##1 == \l__tikzspath_tmpb_tl } { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } + \seq_pop_left:NNF \l__tikzspath_tmpb_seq \l__tikzspath_tmpb_tl + { + \tl_set:Nn \l__tikzspath_tmpb_tl {-1} + } + \spath_splice_between:Nnn \l__tikzspath_tmpa_tl {#2} {##2} } - }, - use/.code={ - \bool_set_false:N \l__spath_reverse_bool - \bool_set_false:N \l__spath_weld_bool - \bool_set_false:N \l__spath_move_bool - \tl_clear:N \l__spath_joinpath_tl - \tl_clear:N \l__spath_transformation_tl - \tikzset{ - spath/join/.cd, - #1 + { + \tl_put_right:Nn \l__tikzspath_tmpa_tl {##2} } + } + \tl_gset_eq:NN \g__tikzspath_output_tl \l__tikzspath_tmpa_tl + \group_end: +} +\cs_new_protected_nopar:Npn \__tikzspath_join_components_with:Nnnn #1#2#3#4 +{ + \__tikzspath_join_components_with_aux:nnn {#2}{#3}{#4} + \tl_set_eq:NN #1 \g__tikzspath_output_tl + \tl_gclear:N \g__tikzspath_output_tl +} +\cs_generate_variant:Nn \__tikzspath_join_components_with:Nnnn {NVnn} +\cs_new_protected_nopar:Npn \__tikzspath_join_components_with:Nnn #1#2#3 +{ + \__tikzspath_join_components_with:NVnn #1#1{#2}{#3} +} +\cs_generate_variant:Nn \__tikzspath_join_components_with:Nnn {cvV} +\cs_new_protected_nopar:Npn \__tikzspath_gjoin_components_with:Nnnn #1#2#3#4 +{ + \__tikzspath_join_components_with_aux:nnn {#2}{#3}{#4} + \tl_gset_eq:NN #1 \g__tikzspath_output_tl + \tl_gclear:N \g__tikzspath_output_tl +} +\cs_generate_variant:Nn \__tikzspath_gjoin_components_with:Nnnn {NVnn} +\cs_new_protected_nopar:Npn \__tikzspath_gjoin_components_with:Nnn #1#2#3 +{ + \__tikzspath_gjoin_components_with:NVnn #1#1{#2}{#3} +} +\cs_generate_variant:Nn \__tikzspath_gjoin_components_with:Nnn {cvV} +\cs_new_protected_nopar:Npn \__tikzspath_join_components_upright_with_aux:nnn #1#2#3 +{ + \group_begin: + \tl_set:Nn \l__tikzspath_tmpc_tl {#1} + \tl_if_empty:nT {#3} + { + \spath_spot_weld_components:N \l__tikzspath_tmpc_tl + } - \tl_if_exist:cTF + \spath_numberofcomponents:NV \l__tikzspath_tmpa_int \l__tikzspath_tmpc_tl + \__tikzspath_seq_from_foreach:NVn \l__tikzspath_tmpb_seq \l__tikzspath_tmpa_int {#3} + + \spath_components_to_seq:NV \l__tikzspath_tmpa_seq \l__tikzspath_tmpc_tl + + \seq_pop_left:NN \l__tikzspath_tmpa_seq \l__tikzspath_tmpa_tl + \seq_pop_left:NN \l__tikzspath_tmpb_seq \l__tikzspath_tmpb_tl + + \tl_set:Nn \l__tikzspath_tmpc_tl {#2} + \spath_transform:NVnnnnnn \l__tikzspath_tmpd_tl \l__tikzspath_tmpc_tl {1}{0}{0}{-1}{0pt}{0pt} + + \seq_map_indexed_inline:Nn \l__tikzspath_tmpa_seq + { + \int_compare:nTF { - \tl_use:N \l__spath_prefix_tl - \tl_use:N \l__spath_joinpath_tl - \tl_use:N \l__spath_suffix_tl + ##1 == \l__tikzspath_tmpb_tl } { - \tl_if_empty:cT + \seq_pop_left:NNF \l__tikzspath_tmpb_seq \l__tikzspath_tmpb_tl { - \tl_use:N \l__spath_prefix_tl - \tl_use:N \l__spath_joinpath_tl - \tl_use:N \l__spath_suffix_tl + \tl_set:Nn \l__tikzspath_tmpb_tl {-1} } + + \spath_finalpoint:NV \l__tikzspath_tmpe_tl \l__tikzspath_tmpa_tl + \spath_initialpoint:Nn \l__tikzspath_tmpf_tl {##2} + + \dim_compare:nTF { - \msg_warning:nnn { spath3 } { empty soft path } { #1 } + \tl_item:Nn \l__tikzspath_tmpe_tl {1} + > + \tl_item:Nn \l__tikzspath_tmpf_tl {1} } - \tl_set_eq:Nc \l__spath_joinpath_tl { - \tl_use:N \l__spath_prefix_tl - \tl_use:N \l__spath_joinpath_tl - \tl_use:N \l__spath_suffix_tl + \spath_splice_between:NVn + \l__tikzspath_tmpa_tl + \l__tikzspath_tmpd_tl + {##2} } - \spath_get_current_path:N \l__spath_current_tl - - \bool_if:NT \l__spath_reverse_bool { - \spath_reverse:N \l__spath_joinpath_tl + \spath_splice_between:NVn + \l__tikzspath_tmpa_tl + \l__tikzspath_tmpc_tl + {##2} } + } + { + \tl_put_right:Nn \l__tikzspath_tmpa_tl {##2} + } + } + \tl_gset_eq:NN \g__tikzspath_output_tl \l__tikzspath_tmpa_tl + \group_end: +} +\cs_new_protected_nopar:Npn \__tikzspath_join_components_upright_with:Nnnn #1#2#3#4 +{ + \__tikzspath_join_components_upright_with_aux:nnn {#2}{#3}{#4} + \tl_set_eq:NN #1 \g__tikzspath_output_tl + \tl_gclear:N \g__tikzspath_output_tl +} +\cs_generate_variant:Nn \__tikzspath_join_components_upright_with:Nnnn {NVnn} +\cs_new_protected_nopar:Npn \__tikzspath_join_components_upright_with:Nnn #1#2#3 +{ + \__tikzspath_join_components_upright_with:NVnn #1#1{#2}{#3} +} +\cs_generate_variant:Nn \__tikzspath_join_components_upright_with:Nnn {cvV} +\cs_new_protected_nopar:Npn \__tikzspath_gjoin_components_upright_with:Nnnn #1#2#3#4 +{ + \__tikzspath_join_components_upright_with_aux:nnn {#2}{#3}{#4} + \tl_gset_eq:NN #1 \g__tikzspath_output_tl + \tl_gclear:N \g__tikzspath_output_tl +} +\cs_generate_variant:Nn \__tikzspath_gjoin_components_upright_with:Nnnn {NVnn} +\cs_new_protected_nopar:Npn \__tikzspath_gjoin_components_upright_with:Nnn #1#2#3 +{ + \__tikzspath_gjoin_components_upright_with:NVnn #1#1{#2}{#3} +} +\cs_generate_variant:Nn \__tikzspath_gjoin_components_upright_with:Nnn {cvV} +\cs_new_protected_nopar:Npn \__tikzspath_get_components_aux:n #1 +{ + \clist_gclear_new:N \g__tikzspath_output_clist + \spath_components_to_seq:Nn \l__tikzspath_tmpa_seq {#1} + + \seq_map_inline:Nn \l__tikzspath_tmpa_seq + { + \spath_anonymous:N \l__tikzspath_tmpa_tl + \tl_new:c {\__tikzspath_path_name:V \l__tikzspath_tmpa_tl} + \tl_set:cn {\__tikzspath_path_name:V \l__tikzspath_tmpa_tl} {##1} + \clist_gput_right:NV \g__tikzspath_output_clist \l__tikzspath_tmpa_tl + } +} +\cs_new_protected_nopar:Npn \__tikzspath_get_components:Nn #1#2 +{ + \clist_clear_new:N #1 + \__tikzspath_get_components_aux:n {#2} + \clist_set_eq:NN #1 \g__tikzspath_output_clist + \clist_gclear:N \g__tikzspath_output_clist +} +\cs_generate_variant:Nn \__tikzspath_get_components:Nn {NV, Nv} +\cs_new_protected_nopar:Npn \__tikzspath_gget_components:Nn #1#2 +{ + \clist_gclear_new:N #1 + \__tikzspath_get_components_aux:n {#2} + \clist_gset_eq:NN #1 \g__tikzspath_output_clist + \clist_gclear:N \g__tikzspath_output_clist +} +\cs_generate_variant:Nn \__tikzspath_gget_components:Nn {NV, Nv} +\cs_new_protected_nopar:Npn \__tikzspath_render_components:nn #1#2 +{ + \group_begin: + \spath_components_to_seq:Nn \l__tikzspath_tmpa_seq {#2} + \seq_map_indexed_inline:Nn \l__tikzspath_tmpa_seq + { + \spath_tikz_path:nn + { + every~ spath~ component/.try, + spath ~component~ ##1/.try, + spath ~component/.try={##1}, + every~ #1~ component/.try, + #1 ~component~ ##1/.try, + #1 ~component/.try={##1}, + } + { + ##2 + } + } + \group_end: +} +\cs_generate_variant:Nn \__tikzspath_render_components:nn {nv} +\cs_new_protected_nopar:Npn \__tikzspath_insert_gaps_after_components_aux:nnn #1#2#3 +{ + \group_begin: + \spath_numberofcomponents:Nn \l__tikzspath_tmpa_int {#1} + \__tikzspath_seq_from_foreach:NVn \l__tikzspath_tmpa_seq \l__tikzspath_tmpa_int {#3} - \tl_if_empty:NF \l__spath_transformation_tl + \tl_if_empty:nT {#3} + { + \seq_pop_right:NN \l__tikzspath_tmpa_seq \l__tikzspath_tmpa_tl + } + + \seq_clear:N \l__tikzspath_tmpb_seq + \seq_map_inline:Nn \l__tikzspath_tmpa_seq { + \seq_put_right:Nx + \l__tikzspath_tmpb_seq + {\int_eval:n { - \group_begin: - \pgftransformreset - \__spath_tikzset:V \l__spath_transformation_tl - \pgfgettransform \l__spath_tmpa_tl - \tl_gset:Nn \g__spath_smuggle_tl - { - \spath_transform:Nnnnnnn - \l__spath_joinpath_tl - } - \tl_gput_right:NV \g__spath_smuggle_tl \l__spath_tmpa_tl - \group_end: - \tl_use:N \g__spath_smuggle_tl + \int_mod:nn { ##1 }{ \l__tikzspath_tmpa_int } + 1 } + } + } - \bool_if:NT \l__spath_move_bool + \spath_components_to_seq:Nn \l__tikzspath_tmpc_seq {#1} + + \seq_clear:N \l__tikzspath_tmpd_seq + \seq_map_indexed_inline:Nn \l__tikzspath_tmpc_seq + { + \tl_set:Nn \l__tikzspath_tmpa_tl {##2} + \seq_if_in:NnT \l__tikzspath_tmpa_seq {##1} + { + \spath_shorten_at_end:Nn \l__tikzspath_tmpa_tl {(#2)/2} + } + \seq_if_in:NnT \l__tikzspath_tmpb_seq {##1} + { + \spath_shorten_at_start:Nn \l__tikzspath_tmpa_tl {(#2)/2} + } + \seq_put_right:NV \l__tikzspath_tmpd_seq \l__tikzspath_tmpa_tl + } + \tl_gset:Nx \g__tikzspath_output_tl {\seq_use:Nn \l__tikzspath_tmpd_seq {} } + \group_end: +} +\cs_new_protected_nopar:Npn \__tikzspath_insert_gaps_after_components:Nnnn #1#2#3#4 +{ + \__tikzspath_insert_gaps_after_components_aux:nnn {#2}{#3}{#4} + \tl_set_eq:NN #1 \g__tikzspath_output_tl + \tl_gclear:N \g__tikzspath_output_tl +} +\cs_generate_variant:Nn \__tikzspath_insert_gaps_after_components:Nnnn {NVnn} +\cs_new_protected_nopar:Npn \__tikzspath_insert_gaps_after_components:Nnn #1#2#3 +{ + \__tikzspath_insert_gaps_after_components:NVnn #1#1{#2}{#3} +} +\cs_generate_variant:Nn \__tikzspath_insert_gaps_after_components:Nnn {cnn, cVV} +\cs_new_protected_nopar:Npn \__tikzspath_ginsert_gaps_after_components:Nnnn #1#2#3#4 +{ + \__tikzspath_insert_gaps_after_components_aux:nnn {#2}{#3}{#4} + \tl_gset_eq:NN #1 \g__tikzspath_output_tl + \tl_gclear:N \g__tikzspath_output_tl +} +\cs_generate_variant:Nn \__tikzspath_ginsert_gaps_after_components:Nnnn {NVnn} +\cs_new_protected_nopar:Npn \__tikzspath_ginsert_gaps_after_components:Nnn #1#2#3 +{ + \__tikzspath_ginsert_gaps_after_components:NVnn #1#1{#2}{#3} +} +\cs_generate_variant:Nn \__tikzspath_ginsert_gaps_after_components:Nnn {cnn, cVV} +\cs_new_protected_nopar:Npn \__tikzspath_insert_gaps_after_segments_aux:nnn #1#2#3 +{ + \group_begin: + \spath_reallength:Nn \l__tikzspath_tmpa_int {#1} + \__tikzspath_seq_from_foreach:NVn \l__tikzspath_tmpa_seq \l__tikzspath_tmpa_int {#3} + + \tl_if_empty:nT {#3} + { + \seq_pop_right:NN \l__tikzspath_tmpb_seq \l__tikzspath_tmpa_tl + } + + \seq_clear:N \l__tikzspath_tmpb_seq + \seq_map_inline:Nn \l__tikzspath_tmpa_seq { + \seq_put_right:Nx + \l__tikzspath_tmpb_seq + {\int_eval:n { - \tl_if_empty:NTF \l__spath_current_tl - { - \tl_set:Nn \l__spath_tmpc_tl { {0pt} {0pt} } - } - { - \spath_finalpoint:NV - \l__spath_tmpc_tl - \l__spath_current_tl - } - \spath_translate_to:NV \l__spath_joinpath_tl \l__spath_tmpc_tl + \int_mod:nn { ##1 }{ \l__tikzspath_tmpa_int } + 1 } + } + } + + \spath_segments_to_seq:Nn \l__tikzspath_tmpc_seq {#1} + + \seq_clear:N \l__tikzspath_tmpd_seq + \seq_map_indexed_inline:Nn \l__tikzspath_tmpc_seq + { + \tl_set:Nn \l__tikzspath_tmpa_tl {##2} + \seq_if_in:NnT \l__tikzspath_tmpa_seq {##1} + { + \spath_shorten_at_end:Nn \l__tikzspath_tmpa_tl {(#2)/2} + } + \seq_if_in:NnT \l__tikzspath_tmpb_seq {##1} + { + \spath_shorten_at_start:Nn \l__tikzspath_tmpa_tl {(#2)/2} + } + \seq_put_right:NV \l__tikzspath_tmpd_seq \l__tikzspath_tmpa_tl + } + \tl_gset:Nx \g__tikzspath_output_tl {\seq_use:Nn \l__tikzspath_tmpd_seq {} } + \group_end: +} +\cs_new_protected_nopar:Npn \__tikzspath_insert_gaps_after_segments:Nnnn #1#2#3#4 +{ + \__tikzspath_insert_gaps_after_segments_aux:nnn {#2}{#3}{#4} + \tl_set_eq:NN #1 \g__tikzspath_output_tl + \tl_gclear:N \g__tikzspath_output_tl +} +\cs_generate_variant:Nn \__tikzspath_insert_gaps_after_segments:Nnnn {NVnn} +\cs_new_protected_nopar:Npn \__tikzspath_insert_gaps_after_segments:Nnn #1#2#3 +{ + \__tikzspath_insert_gaps_after_segments:NVnn #1#1{#2}{#3} +} +\cs_generate_variant:Nn \__tikzspath_insert_gaps_after_segments:Nnn {cnn, cVV} +\cs_new_protected_nopar:Npn \__tikzspath_ginsert_gaps_after_segments:Nnnn #1#2#3#4 +{ + \__tikzspath_insert_gaps_after_segments_aux:nnn {#2}{#3}{#4} + \tl_gset_eq:NN #1 \g__tikzspath_output_tl + \tl_gclear:N \g__tikzspath_output_tl +} +\cs_generate_variant:Nn \__tikzspath_ginsert_gaps_after_segments:Nnnn {NVnn} +\cs_new_protected_nopar:Npn \__tikzspath_ginsert_gaps_after_segments:Nnn #1#2#3 +{ + \__tikzspath_ginsert_gaps_after_segments:NVnn #1#1{#2}{#3} +} +\cs_generate_variant:Nn \__tikzspath_ginsert_gaps_after_segments:Nnn {cnn, cVV} +\cs_new_protected_nopar:Npn \__tikzspath_join_components_aux:nn #1#2 +{ + \group_begin: + + \tl_set:Nn \l__tikzspath_tmpa_tl {#1} + \spath_numberofcomponents:NV \l__tikzspath_tmpa_int \l__tikzspath_tmpa_tl + \__tikzspath_seq_from_foreach:NVn \l__tikzspath_tmpa_seq \l__tikzspath_tmpa_int {#2} + + \seq_reverse:N \l__tikzspath_tmpa_seq + + \seq_map_inline:Nn \l__tikzspath_tmpa_seq + { + \spath_join_component:Nn \l__tikzspath_tmpa_tl {##1} + } + \tl_gset_eq:NN \g__tikzspath_output_tl \l__tikzspath_tmpa_tl + \group_end: +} +\cs_new_protected_nopar:Npn \__tikzspath_join_components:Nnn #1#2#3 +{ + \__tikzspath_join_components_aux:nn {#2}{#3} + \tl_set_eq:NN #1 \g__tikzspath_output_tl + \tl_gclear:N \g__tikzspath_output_tl +} +\cs_generate_variant:Nn \__tikzspath_join_components:Nnn {NVn} +\cs_new_protected_nopar:Npn \__tikzspath_join_components:Nn #1#2 +{ + \__tikzspath_join_components:NVn #1#1{#2} +} +\cs_generate_variant:Nn \__tikzspath_join_components:Nn {cn} +\cs_new_protected_nopar:Npn \__tikzspath_gjoin_components:Nnn #1#2#3 +{ + \__tikzspath_join_components_aux:nn {#2}{#3} + \tl_gset_eq:NN #1 \g__tikzspath_output_tl + \tl_gclear:N \g__tikzspath_output_tl +} +\cs_generate_variant:Nn \__tikzspath_gjoin_components:Nnn {NVn} +\cs_new_protected_nopar:Npn \__tikzspath_gjoin_components:Nn #1#2 +{ + \__tikzspath_gjoin_components:NVn #1#1{#2} +} +\cs_generate_variant:Nn \__tikzspath_gjoin_components:Nn {cn} +\cs_new_protected_nopar:Npn \__tikzspath_join_components_with_bezier_aux:nn #1#2 +{ + \group_begin: + \tl_set:Nn \l__tikzspath_tmpc_tl {#1} + \tl_if_empty:nT {#2} + { + \spath_spot_weld_components:N \l__tikzspath_tmpc_tl + } + + \spath_numberofcomponents:NV \l__tikzspath_tmpa_int \l__tikzspath_tmpc_tl + \__tikzspath_seq_from_foreach:NVn \l__tikzspath_tmpb_seq \l__tikzspath_tmpa_int {#2} + + \spath_components_to_seq:NV \l__tikzspath_tmpa_seq \l__tikzspath_tmpc_tl + + \seq_pop_left:NN \l__tikzspath_tmpa_seq \l__tikzspath_tmpa_tl + \seq_pop_left:NN \l__tikzspath_tmpb_seq \l__tikzspath_tmpb_tl - \tl_if_empty:NTF \l__spath_current_tl + \seq_map_indexed_inline:Nn \l__tikzspath_tmpa_seq + { + \int_compare:nTF + { + ##1 == \l__tikzspath_tmpb_tl + } + { + \seq_pop_left:NNF \l__tikzspath_tmpb_seq \l__tikzspath_tmpb_tl { - \tl_if_empty:NTF \l__spath_joinpath_tl - { - \tl_set_eq:NN \l__spath_current_tl \c_spath_moveto_tl - \tl_put_right:Nn \l__spath_current_tl {{0pt}{0pt}} - } - { - \tl_set_eq:NN \l__spath_current_tl \l__spath_joinpath_tl - } + \tl_set:Nn \l__tikzspath_tmpb_tl {-1} } - { + \spath_curve_between:Nn \l__tikzspath_tmpa_tl {##2} + } + { + \tl_put_right:Nn \l__tikzspath_tmpa_tl {##2} + } + } + \tl_gset_eq:NN \g__tikzspath_output_tl \l__tikzspath_tmpa_tl + \group_end: +} +\cs_new_protected_nopar:Npn \__tikzspath_join_components_with_bezier:Nnn #1#2#3 +{ + \__tikzspath_join_components_with_bezier_aux:nn {#2}{#3} + \tl_set_eq:NN #1 \g__tikzspath_output_tl + \tl_gclear:N \g__tikzspath_output_tl +} +\cs_generate_variant:Nn \__tikzspath_join_components_with_bezier:Nnn {NVn} +\cs_new_protected_nopar:Npn \__tikzspath_join_components_with_bezier:Nn #1#2 +{ + \__tikzspath_join_components_with_bezier:NVn #1#1{#2} +} +\cs_generate_variant:Nn \__tikzspath_join_components_with_bezier:Nn {cV} +\cs_new_protected_nopar:Npn \__tikzspath_gjoin_components_with_bezier:Nnn #1#2#3 +{ + \__tikzspath_join_components_with_bezier_aux:nn {#2}{#3} + \tl_gset_eq:NN #1 \g__tikzspath_output_tl + \tl_gclear:N \g__tikzspath_output_tl +} +\cs_generate_variant:Nn \__tikzspath_gjoin_components_with_bezier:Nnn {NVn} +\cs_new_protected_nopar:Npn \__tikzspath_gjoin_components_with_bezier:Nn #1#2 +{ + \__tikzspath_gjoin_components_with_bezier:NVn #1#1{#2} +} +\cs_generate_variant:Nn \__tikzspath_gjoin_components_with_bezier:Nn {cV} +\cs_new_protected_nopar:Npn \__tikzspath_remove_components_aux:nn #1#2 +{ + \group_begin: - \tl_clear:N \l__spath_tmpa_tl - \tl_set:Nn \l__spath_tmpa_tl {spath_} + \spath_numberofcomponents:Nn \l__tikzspath_tmpa_int {#1} + \__tikzspath_seq_from_foreach:NVn \l__tikzspath_tmpa_seq \l__tikzspath_tmpa_int {#2} - \tl_put_right:Nn \l__spath_tmpa_tl {append} + \spath_components_to_seq:Nn \l__tikzspath_tmpb_seq {#1} - \bool_if:NT \l__spath_weld_bool - { - \tl_put_right:Nn \l__spath_tmpa_tl {_no_move} - } - \tl_put_right:Nn \l__spath_tmpa_tl {:NV} + \seq_pop_left:NNF \l__tikzspath_tmpa_seq \l__tikzspath_tmpa_tl + { + \tl_clear:N \l__tikzspath_tmpa_tl + } - \use:c {\tl_use:N \l__spath_tmpa_tl } - \l__spath_current_tl - \l__spath_joinpath_tl + \seq_clear:N \l__tikzspath_tmpc_seq + \seq_map_indexed_inline:Nn \l__tikzspath_tmpb_seq + { + \tl_set:Nn \l__tikzspath_tmpb_tl {##1} + \tl_if_eq:NNTF \l__tikzspath_tmpb_tl \l__tikzspath_tmpa_tl + { + \seq_pop_left:NNF \l__tikzspath_tmpa_seq \l__tikzspath_tmpa_tl + { + \tl_clear:N \l__tikzspath_tmpa_tl } + } + { + \seq_put_right:Nn \l__tikzspath_tmpc_seq {##2} + } + } - \spath_set_current_path:N \l__spath_current_tl - \spath_set_tikz_data:V \l__spath_joinpath_tl + \tl_gset:Nx \g__tikzspath_output_tl {\seq_use:Nn \l__tikzspath_tmpc_seq {} } + \group_end: +} +\cs_new_protected_nopar:Npn \__tikzspath_remove_components:Nnn #1#2#3 +{ + \__tikzspath_remove_components_aux:nn {#2}{#3} + \tl_set_eq:NN #1 \g__tikzspath_output_tl + \tl_gclear:N \g__tikzspath_output_tl +} +\cs_generate_variant:Nn \__tikzspath_remove_components:Nnn {NVn} +\cs_new_protected_nopar:Npn \__tikzspath_remove_components:Nn #1#2 +{ + \__tikzspath_remove_components:NVn #1#1{#2} +} +\cs_generate_variant:Nn \__tikzspath_remove_components:Nn {cn} +\cs_new_protected_nopar:Npn \__tikzspath_gremove_components:Nnn #1#2#3 +{ + \__tikzspath_remove_components_aux:nn {#2}{#3} + \tl_gset_eq:NN #1 \g__tikzspath_output_tl + \tl_gclear:N \g__tikzspath_output_tl +} +\cs_generate_variant:Nn \__tikzspath_gremove_components:Nnn {NVn} +\cs_new_protected_nopar:Npn \__tikzspath_gremove_components:Nn #1#2 +{ + \__tikzspath_gremove_components:NVn #1#1{#2} +} +\cs_generate_variant:Nn \__tikzspath_gremove_components:Nn {cn} +\cs_new_protected_nopar:Npn \__tikzspath_transform_to_aux:nn #1#2 +{ + \group_begin: + \spath_reallength:Nn \l__tikzspath_tmpa_int {#2} + + \tl_set:Nx \l__tikzspath_tmpb_tl + {\fp_to_decimal:n {(#1) * (\l__tikzspath_tmpa_int)}} + \spath_transformation_at:NnV \l__tikzspath_tmpc_tl {#2} \l__tikzspath_tmpb_tl + \tl_gset_eq:NN \g__tikzspath_output_tl \l__tikzspath_tmpc_tl + \group_end: +} +\cs_new_protected_nopar:Npn \__tikzspath_transform_to:nn #1#2 +{ + \__tikzspath_transform_to_aux:nn {#1}{#2} + \exp_last_unbraced:NV \pgfsettransformentries \g__tikzspath_output_tl + \tl_gclear:N \g__tikzspath_output_tl +} +\cs_generate_variant:Nn \__tikzspath_transform_to:nn {nv} +\cs_new_protected_nopar:Npn \__tikzspath_transform_upright_to:nn #1#2 +{ + \__tikzspath_transform_to_aux:nn {#1}{#2} + \fp_compare:nT { \tl_item:Nn \g__tikzspath_output_tl {4} < 0} + { + \tl_gset:Nx \g__tikzspath_output_tl + { + { \fp_eval:n { - (\tl_item:Nn \g__tikzspath_output_tl {1})} } + { \fp_eval:n { - (\tl_item:Nn \g__tikzspath_output_tl {2})} } + { \fp_eval:n { - (\tl_item:Nn \g__tikzspath_output_tl {3})} } + { \fp_eval:n { - (\tl_item:Nn \g__tikzspath_output_tl {4})} } + { \tl_item:Nn \g__tikzspath_output_tl {5} } + { \tl_item:Nn \g__tikzspath_output_tl {6} } } + } + \exp_last_unbraced:NV \pgfsettransformentries \g__tikzspath_output_tl + \tl_gclear:N \g__tikzspath_output_tl +} +\cs_generate_variant:Nn \__tikzspath_transform_upright_to:nn {nv} +\tikzset{ + spath/.is~family, + spath/.cd, + set~ prefix/.store~ in=\l__tikzspath_prefix_tl, + prefix/.is~choice, + prefix/default/.style={ + /tikz/spath/set~ prefix=tikz@intersect@path@name@ + }, + set~ suffix/.store~ in=\l__tikzspath_suffix_tl, + suffix/.is~choice, + suffix/default/.style={ + /tikz/spath/set~ suffix={} + }, + set~ name/.style={ + /tikz/spath/prefix=#1, + /tikz/spath/suffix=#1 + }, + at~ end~ path~ construction/.code={ + \tl_put_right:Nn \l__tikzspath_tikzpath_finish_tl {#1} + }, + save/.code={ + \tikz@addmode{ + \spath_get_current_path:N \l__tikzspath_tmpa_tl + \spath_bake_round:NV \l__tikzspath_tmpa_tl \l__tikzspath_tmpa_tl + \spath_bake_shorten:NV \l__tikzspath_tmpa_tl \l__tikzspath_tmpa_tl + \spath_save_path:cV {\__tikzspath_path_name:n {#1}} + \l__tikzspath_tmpa_tl + } + }, + save~ global/.code={ + \tikz@addmode{ + \spath_get_current_path:N \l__tikzspath_tmpa_tl + \spath_bake_round:NV \l__tikzspath_tmpa_tl \l__tikzspath_tmpa_tl + \spath_bake_shorten:NV \l__tikzspath_tmpa_tl \l__tikzspath_tmpa_tl + \spath_gsave_path:cV {\__tikzspath_path_name:n {#1}} + \l__tikzspath_tmpa_tl + } + }, + clone/.code~ 2~ args={ + \__tikzspath_maybe_current_path:nn { - \msg_warning:nnx - { spath3 } - { missing soft path } - {\tl_use:N \l__spath_joinpath_tl } + \__tikzspath_check_path:nnn { + \tl_clear_new:c {\__tikzspath_path_name:n {#1}} + \tl_set_eq:cc {\__tikzspath_path_name:n {#1}} + } } + {#2}{} + }, + clone~ global/.code~ 2~ args={ + \__tikzspath_maybe_current_path:nn + { + \__tikzspath_check_path:nnn { + \tl_gclear_new:c {\__tikzspath_path_name:n {#1}} + \tl_gset_eq:cc {\__tikzspath_path_name:n {#1}} + } + } + {#2}{} + }, + save~ to~ aux/.code={ + \__tikzspath_maybe_current_path:nn + { + \__tikzspath_check_path:nnn { + \spath_save_to_aux:c + } + } + {#1} + {} + }, + export~ to~ svg/.code={ + \__tikzspath_maybe_current_path:nn + { + \__tikzspath_check_path:nnn { + \spath_export_to_svg:nv {#1} + } + } + {#1} + {} + }, + use/.code={ + \bool_set_false:N \l__tikzspath_reverse_bool + \bool_set_false:N \l__tikzspath_weld_bool + \bool_set_false:N \l__tikzspath_move_bool + \bool_set_false:N \l__tikzspath_current_transformation_bool + \bool_set_true:N \l_spath_movetorelevant_bool + \tl_clear:N \l__tikzspath_joinpath_tl + \tl_clear:N \l__tikzspath_transformation_tl + \tikzset{ + spath/join/.cd, + #1 + } + + \__tikzspath_check_path:nVn + { + \__tikzspath_use_path:v + } \l__tikzspath_joinpath_tl {} + }, restore/.style={/tikz/spath/use={#1}}, restore~ reverse/.style={/tikz/spath/use={reverse, #1}}, @@ -329,914 +1127,534 @@ insert~ reverse/.style={/tikz/spath/use={reverse, #1}}, show~current~path/.code={ \tikz@addmode{ - \pgfsyssoftpath@getcurrentpath\l__spath_tmpa_tl + \pgfsyssoftpath@getcurrentpath\l__tikzspath_tmpa_tl \iow_term:n {---~ current~ soft~ path~ ---} - \spath_show:V \l__spath_tmpa_tl + \spath_show:V \l__tikzspath_tmpa_tl } }, show/.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} - { - \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 } - } + \__tikzspath_check_path:nnn { + \iow_term:n {---~ soft~ path~ #1~ ---} + \spath_show:v + } {#1} {} }, join~ with/.code~ 2~ args={ - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - { - \bool_set_false:N \l__spath_reverse_bool - \bool_set_false:N \l__spath_weld_bool - \bool_set_false:N \l__spath_move_bool - \bool_set_false:N \l__spath_global_bool - \tl_clear:N \l__spath_joinpath_tl - \tl_clear:N \l__spath_transformation_tl - \tikzset{ - spath/join/.cd, - #2 - } - - \tl_if_exist:cTF - { - \tl_use:N \l__spath_prefix_tl - \tl_use:N \l__spath_joinpath_tl - \tl_use:N \l__spath_suffix_tl - } - { - \tl_set_eq:Nc \l__spath_joinpath_tl - { - \tl_use:N \l__spath_prefix_tl - \tl_use:N \l__spath_joinpath_tl - \tl_use:N \l__spath_suffix_tl - } - - \bool_if:NT \l__spath_reverse_bool - { - \spath_reverse:N \l__spath_joinpath_tl - } - - \tl_if_empty:NF \l__spath_transformation_tl - { - \group_begin: - \pgftransformreset - \__spath_tikzset:V \l__spath_transformation_tl - \pgfgettransform \l__spath_tmpa_tl - \tl_gset:Nn \g__spath_smuggle_tl - { - \spath_transform:Nnnnnnn - \l__spath_joinpath_tl - } - \tl_gput_right:NV \g__spath_smuggle_tl \l__spath_tmpa_tl - \group_end: - \tl_use:N \g__spath_smuggle_tl - } - - \bool_if:NT \l__spath_move_bool - { - \spath_finalpoint:Nv - \l__spath_tmpc_tl - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - \spath_translate_to:NV \l__spath_joinpath_tl \l__spath_tmpc_tl - } - - \tl_clear:N \l__spath_tmpa_tl - \tl_set:Nn \l__spath_tmpa_tl {spath_} - - \bool_if:NT \l__spath_global_bool - { - \tl_put_right:Nn \l__spath_tmpa_tl {g} - } - - \tl_put_right:Nn \l__spath_tmpa_tl {append} - - \bool_if:NT \l__spath_weld_bool - { - \tl_put_right:Nn \l__spath_tmpa_tl {_no_move} - } - \tl_put_right:Nn \l__spath_tmpa_tl {:cV} - - \cs_if_exist:cF {\tl_use:N \l__spath_tmpa_tl} - { - \tl_show:N \l__spath_tmpa_tl - } + \bool_set_false:N \l__tikzspath_reverse_bool + \bool_set_false:N \l__tikzspath_weld_bool + \bool_set_false:N \l__tikzspath_move_bool + \bool_set_false:N \l__tikzspath_global_bool + \bool_set_false:N \l__tikzspath_current_transformation_bool + \tl_clear:N \l__tikzspath_joinpath_tl + \tl_clear:N \l__tikzspath_transformation_tl + \tikzset{ + spath/join/.cd, + #2 + } - \use:c {\tl_use:N \l__spath_tmpa_tl } - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - \l__spath_joinpath_tl - } + \__tikzspath_maybe_current_path_reuse:nnn + { + \__tikzspath_check_two_paths:nnVn { - \msg_warning:nnx - { spath3 } - { missing soft path } - {\tl_use:N \l__spath_joinpath_tl } + \__tikzspath_join_with:cv } - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + } {#1} { \l__tikzspath_joinpath_tl {} } }, spot~ weld/.code={ - \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} - } + \__tikzspath_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \__tikzspath_check_path:nnn + { + \spath_spot_weld_components:c + } + } {#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} - } + \__tikzspath_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \__tikzspath_check_path:nnn + { + \spath_spot_gweld_components:c + } + } {#1} { {} } }, reverse/.code={ - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + \__tikzspath_maybe_current_path_reuse:nnn { - \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 } - } + \__tikzspath_check_path:nnn + { + \spath_reverse:c + } + } {#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} - } + \__tikzspath_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \__tikzspath_check_path:nnn + { + \spath_greverse:c + } + } {#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} + \__tikzspath_maybe_current_path_reuse:nnn { - \__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 } - } + \__tikzspath_check_path:nnn + { + \__tikzspath_process_tikz_point:Nn \l__tikzspath_tmpa_tl {#2} + \__tikzspath_process_tikz_point:Nn \l__tikzspath_tmpb_tl {#3} + \spath_span:cVV + } + } {#1} { {} \l__tikzspath_tmpa_tl \l__tikzspath_tmpb_tl } }, 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 - } + \__tikzspath_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \__tikzspath_check_path:nnn + { + \__tikzspath_process_tikz_point:Nn \l__tikzspath_tmpa_tl {#2} + \__tikzspath_process_tikz_point:Nn \l__tikzspath_tmpb_tl {#3} + \spath_span:cVV + } + } {#1} { {} \l__tikzspath_tmpa_tl \l__tikzspath_tmpb_tl } }, to/.style={ to~path={ [ spath/span={#1}{(\tikztostart)}{(\tikztotarget)}, - spath/append~no~move={#1}, + spath/use={#1,weld}, ] \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} + \__tikzspath_maybe_current_path_reuse:nnn { - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl} + \__tikzspath_check_three_paths:nnnnn { - \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 } - } + \spath_splice_between:cvv } + } {#1} { {#2} {#3} {} } + }, + splice~ global/.code ~n~ args={3}{ + \__tikzspath_maybe_current_path_reuse:nnn + { + \__tikzspath_check_three_paths:nnnnn { - \msg_warning:nnn { spath3 } { missing soft path } { #2 } + \spath_gsplice_between:cvv } + } {#1} { {#2} {#3} {} } + }, + join~ components~ with/.code~2~args={ + \tl_if_head_is_group:nTF {#2} + { + \tl_set:Nx \l__tikzspath_tmpc_tl { \tl_item:nn {#2} {1} } + \tl_set:Nx \l__tikzspath_tmpd_tl { \tl_item:nn {#2} {2} } } { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } + \tl_set:Nn \l__tikzspath_tmpc_tl {#2} + \tl_clear:N \l__tikzspath_tmpd_tl } - }, - 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} + + \__tikzspath_maybe_current_path_reuse:nnn { - \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 } - } - } + \__tikzspath_check_two_paths:nnVn { - \msg_warning:nnn { spath3 } { missing soft path } { #2 } + \__tikzspath_join_components_with:cvV } + } {#1} { \l__tikzspath_tmpc_tl {} \l__tikzspath_tmpd_tl } + }, + join~ components~ globally~ with/.code~2~args={ + \tl_if_head_is_group:nTF {#2} + { + \tl_set:Nx \l__tikzspath_tmpc_tl { \tl_item:nn {#2} {1} } + \tl_set:Nx \l__tikzspath_tmpd_tl { \tl_item:nn {#2} {2} } } { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } + \tl_set:Nn \l__tikzspath_tmpc_tl {#2} + \tl_clear:N \l__tikzspath_tmpd_tl } - }, - 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} + + \__tikzspath_maybe_current_path_reuse:nnn { - \tl_if_head_is_group:nTF {#2} - { - \tl_set:Nx \l__spath_tmpc_tl { \tl_item:nn {#2} {1} } - \tl_set:Nx \l__spath_tmpd_tl { \tl_item:nn {#2} {2} } - } + \__tikzspath_check_two_paths:nnVn { - \tl_set:Nn \l__spath_tmpc_tl {#2} - \tl_clear:N \l__spath_tmpd_tl + \__tikzspath_gjoin_components_with:cvV } - \tl_if_exist:cTF + } {#1} { \l__tikzspath_tmpc_tl {} \l__tikzspath_tmpd_tl } + }, + join~ components~ upright~ with/.code~2~args={ + \tl_if_head_is_group:nTF {#2} + { + \tl_set:Nx \l__tikzspath_tmpc_tl { \tl_item:nn {#2} {1} } + \tl_set:Nx \l__tikzspath_tmpd_tl { \tl_item:nn {#2} {2} } + } + { + \tl_set:Nn \l__tikzspath_tmpc_tl {#2} + \tl_clear:N \l__tikzspath_tmpd_tl + } + + \__tikzspath_maybe_current_path_reuse:nnn + { + \__tikzspath_check_two_paths:nnVn { - \tl_use:N \l__spath_prefix_tl - \tl_use:N \l__spath_tmpc_tl - \tl_use:N \l__spath_suffix_tl + \__tikzspath_join_components_upright_with:cvV } - { - \tl_if_empty:NT \l__spath_tmpd_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_gclear:N \g__spath_tmpa_seq - - \tl_if_empty:NTF \l__spath_tmpd_tl - { - \int_step_inline:nnnn {1}{1} {\seq_count:N \l__spath_tmpa_seq} - { - \seq_gput_right:Nn \g__spath_tmpa_seq {##1} - } - } - { - \foreach \l__spath_tmpa_tl in \l__spath_tmpd_tl - { - \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_pop_left:NN \l__spath_tmpa_seq \l__spath_tmpa_tl - \seq_gpop_left:NN \g__spath_tmpa_seq \l__spath_tmpb_tl + } {#1} { \l__tikzspath_tmpc_tl {} \l__tikzspath_tmpd_tl } + }, + join~ components~ globally~ upright~ with/.code~2~args={ + \tl_if_head_is_group:nTF {#2} + { + \tl_set:Nx \l__tikzspath_tmpc_tl { \tl_item:nn {#2} {1} } + \tl_set:Nx \l__tikzspath_tmpd_tl { \tl_item:nn {#2} {2} } + } + { + \tl_set:Nn \l__tikzspath_tmpc_tl {#2} + \tl_clear:N \l__tikzspath_tmpd_tl + } - \seq_map_indexed_inline:Nn \l__spath_tmpa_seq - { - \int_compare:nTF - { - ##1 == \l__spath_tmpb_tl - } - { - \seq_gpop_left:NNF \g__spath_tmpa_seq \l__spath_tmpb_tl - { - \tl_set:Nn \l__spath_tmpb_tl {-1} - } - \spath_splice_between:Nvn \l__spath_tmpa_tl - { - \tl_use:N \l__spath_prefix_tl - \tl_use:N \l__spath_tmpc_tl - \tl_use:N \l__spath_suffix_tl - } - {##2} - } - { - \tl_put_right:Nn \l__spath_tmpa_tl {##2} - } - } - \tl_set_eq:cN - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - \l__spath_tmpa_tl - } + \__tikzspath_maybe_current_path_reuse:nnn + { + \__tikzspath_check_two_paths:nnVn { - \msg_warning:nnx - { spath3 } - { missing soft path } - { \tl_use:N \l__spath_tmpc_tl } + \__tikzspath_gjoin_components_upright_with:cvV } + } {#1} { \l__tikzspath_tmpc_tl {} \l__tikzspath_tmpd_tl } + }, + join~ components~ with~ bezier/.code={ + \tl_if_head_is_group:nTF {#1} + { + \tl_set:Nx \l__tikzspath_tmpc_tl { \tl_item:nn {#1} {1} } + \tl_set:Nx \l__tikzspath_tmpd_tl { \tl_item:nn {#1} {2} } } { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } + \tl_set:Nn \l__tikzspath_tmpc_tl {#1} + \tl_clear:N \l__tikzspath_tmpd_tl } - }, - 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} + + \__tikzspath_maybe_current_path_reuse:nVn { - \tl_if_head_is_group:nTF {#2} + \__tikzspath_check_path:nnn { - \tl_set:Nx \l__spath_tmpc_tl { \tl_item:nn {#2} {1} } - \tl_set:Nx \l__spath_tmpd_tl { \tl_item:nn {#2} {2} } + \__tikzspath_join_components_with_bezier:cV } + } \l__tikzspath_tmpc_tl { {} \l__tikzspath_tmpd_tl } + }, + join~ components~ globally~ with~ bezier/.code~2~args={ + \__tikzspath_maybe_current_path_reuse:nnn + { + \__tikzspath_check_path:nnn { - \tl_set:Nn \l__spath_tmpc_tl {#2} - \tl_clear:N \l__spath_tmpd_tl + \__tikzspath_gjoin_components_with_bezier:cn } - \tl_if_exist:cTF + } {#1} { {} {#2} } + }, + close/.code={ + \__tikzspath_maybe_current_path_reuse:nnn + { + \__tikzspath_check_path:nnn { - \tl_use:N \l__spath_prefix_tl - \tl_use:N \l__spath_tmpc_tl - \tl_use:N \l__spath_suffix_tl + \spath_close:c } + } {#1} { {} } + }, + close~ globally/.code={ + \__tikzspath_maybe_current_path_reuse:nnn + { + \__tikzspath_check_path:nnn { - \tl_if_empty:NT \l__spath_tmpd_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_gclear:N \g__spath_tmpa_seq - - \tl_if_empty:NTF \l__spath_tmpd_tl - { - \int_step_inline:nnnn {1}{1} {\seq_count:N \l__spath_tmpa_seq} - { - \seq_gput_right:Nn \g__spath_tmpa_seq {##1} - } - } - { - \foreach \l__spath_tmpa_tl in \l__spath_tmpd_tl - { - \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_pop_left:NN \l__spath_tmpa_seq \l__spath_tmpa_tl - \seq_gpop_left:NN \g__spath_tmpa_seq \l__spath_tmpb_tl - - \seq_map_indexed_inline:Nn \l__spath_tmpa_seq - { - \int_compare:nTF - { - ##1 == \l__spath_tmpb_tl - } - { - \seq_gpop_left:NNF \g__spath_tmpa_seq \l__spath_tmpb_tl - { - \tl_set:Nn \l__spath_tmpb_tl {-1} - } - \spath_splice_between:Nvn \l__spath_tmpa_tl - { - \tl_use:N \l__spath_prefix_tl - \tl_use:N \l__spath_tmpc_tl - \tl_use:N \l__spath_suffix_tl - } - {##2} - } - { - \tl_put_right:Nn \l__spath_tmpa_tl {##2} - } - } - \tl_gset_eq:cN - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - \l__spath_tmpa_tl + \spath_gclose:c } + } {#1} { {} } + }, + open/.code={ + \__tikzspath_maybe_current_path_reuse:nnn + { + \__tikzspath_check_path:nnn { - \msg_warning:nnx - { spath3 } - { missing soft path } - { \tl_use:N \l__spath_tmpc_tl } + \spath_open:c } - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + } {#1} { {} } }, - join~ components~ upright~ with/.code~2~args={ - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + open~ globally/.code={ + \__tikzspath_maybe_current_path_reuse:nnn { - \tl_if_head_is_group:nTF {#2} + \__tikzspath_check_path:nnn { - \tl_set:Nx \l__spath_tmpc_tl { \tl_item:nn {#2} {1} } - \tl_set:Nx \l__spath_tmpd_tl { \tl_item:nn {#2} {2} } + \spath_gopen:c } + } {#1} { {} } + }, + adjust~ and~ close/.code={ + \__tikzspath_maybe_current_path_reuse:nnn + { + \__tikzspath_check_path:nnn { - \tl_set:Nn \l__spath_tmpc_tl {#2} - \tl_clear:N \l__spath_tmpd_tl + \spath_adjust_close:c } - \tl_if_exist:cTF + } {#1} { {} } + }, + adjust~ and~ close~ globally/.code={ + \__tikzspath_maybe_current_path_reuse:nnn + { + \__tikzspath_check_path:nnn { - \tl_use:N \l__spath_prefix_tl - \tl_use:N \l__spath_tmpc_tl - \tl_use:N \l__spath_suffix_tl + \spath_adjust_gclose:c } + } {#1} { {} } + }, + close~ with/.code~ 2~ args={ + \__tikzspath_maybe_current_path_reuse:nnn + { + \__tikzspath_check_two_paths:nnnn { - \tl_if_empty:NT \l__spath_tmpd_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_gclear:N \g__spath_tmpa_seq - - \tl_if_empty:NTF \l__spath_tmpd_tl - { - \int_step_inline:nnnn {1}{1} {\seq_count:N \l__spath_tmpa_seq} - { - \seq_gput_right:Nn \g__spath_tmpa_seq {##1} - } - } - { - \foreach \l__spath_tmpa_tl in \l__spath_tmpd_tl - { - \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_pop_left:NN \l__spath_tmpa_seq \l__spath_tmpa_tl - \seq_gpop_left:NN \g__spath_tmpa_seq \l__spath_tmpb_tl - - \tl_set_eq:Nc \l__spath_tmpc_tl - { - \tl_use:N \l__spath_prefix_tl - \tl_use:N \l__spath_tmpc_tl - \tl_use:N \l__spath_suffix_tl - } - \spath_transform:NVnnnnnn \l__spath_tmpd_tl \l__spath_tmpc_tl {1}{0}{0}{-1}{0pt}{0pt} - - \seq_map_indexed_inline:Nn \l__spath_tmpa_seq - { - \int_compare:nTF - { - ##1 == \l__spath_tmpb_tl - } - { - \seq_gpop_left:NNF \g__spath_tmpa_seq \l__spath_tmpb_tl - { - \tl_set:Nn \l__spath_tmpb_tl {-1} - } - \spath_finalpoint:NV \l__spath_tmpe_tl \l__spath_tmpa_tl - \spath_initialpoint:Nn \l__spath_tmpf_tl {##2} - - \dim_compare:nTF - { - \tl_item:Nn \l__spath_tmpe_tl {1} - > - \tl_item:Nn \l__spath_tmpf_tl {1} - } - { - \spath_splice_between:NVn - \l__spath_tmpa_tl - \l__spath_tmpd_tl - {##2} - } - { - \spath_splice_between:NVn - \l__spath_tmpa_tl - \l__spath_tmpc_tl - {##2} - } - } - { - \tl_put_right:Nn \l__spath_tmpa_tl {##2} - } - } - \tl_set_eq:cN - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - \l__spath_tmpa_tl + \spath_close_with:cv } + } {#1} { {#2} {} } + }, + close~ globally~ with/.code~ 2~ args={ + \__tikzspath_maybe_current_path_reuse:nnn + { + \__tikzspath_check_two_paths:nnnn { - \msg_warning:nnx - { spath3 } - { missing soft path } - { \tl_use:N \l__spath_tmpc_tl } + \spath_gclose_with:cv } - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + } {#1} { {#2} {} } }, - join~ components~ globally~ upright~ with/.code~2~args={ - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + close~ with~ curve/.code={ + \__tikzspath_maybe_current_path_reuse:nnn { - \tl_if_head_is_group:nTF {#2} + \__tikzspath_check_path:nnn { - \tl_set:Nx \l__spath_tmpc_tl { \tl_item:nn {#2} {1} } - \tl_set:Nx \l__spath_tmpd_tl { \tl_item:nn {#2} {2} } + \spath_close_with_curve:c } + } {#1} { {} } + }, + close~ globally~ with~ curve/.code={ + \__tikzspath_maybe_current_path_reuse:nnn + { + \__tikzspath_check_path:nnn { - \tl_set:Nn \l__spath_tmpc_tl {#2} - \tl_clear:N \l__spath_tmpd_tl + \spath_gclose_with_curve:c } - \tl_if_exist:cTF + } {#1} { {} } + }, + shorten~ at~ end/.code~ 2~ args={ + \__tikzspath_maybe_current_path_reuse:nnn + { + \__tikzspath_check_path:nnn { - \tl_use:N \l__spath_prefix_tl - \tl_use:N \l__spath_tmpc_tl - \tl_use:N \l__spath_suffix_tl + \spath_shorten_at_end:cn } + } {#1} { {} {#2} } + }, + shorten~ at~ start/.code~ 2~ args ={ + \__tikzspath_maybe_current_path_reuse:nnn + { + \__tikzspath_check_path:nnn { - \tl_if_empty:NT \l__spath_tmpd_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_gclear:N \g__spath_tmpa_seq - - \tl_if_empty:NTF \l__spath_tmpd_tl - { - \int_step_inline:nnnn {1}{1} {\seq_count:N \l__spath_tmpa_seq} - { - \seq_gput_right:Nn \g__spath_tmpa_seq {##1} - } - } - { - \foreach \l__spath_tmpa_tl in \l__spath_tmpd_tl - { - \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_pop_left:NN \l__spath_tmpa_seq \l__spath_tmpa_tl - \seq_gpop_left:NN \g__spath_tmpa_seq \l__spath_tmpb_tl - - \tl_set_eq:Nc \l__spath_tmpc_tl - { - \tl_use:N \l__spath_prefix_tl - \tl_use:N \l__spath_tmpc_tl - \tl_use:N \l__spath_suffix_tl - } - \spath_transform:NVnnnnnn \l__spath_tmpd_tl \l__spath_tmpc_tl {1}{0}{0}{-1}{0pt}{0pt} - - \seq_map_indexed_inline:Nn \l__spath_tmpa_seq - { - \int_compare:nTF - { - ##1 == \l__spath_tmpb_tl - } - { - \seq_gpop_left:NNF \g__spath_tmpa_seq \l__spath_tmpb_tl - { - \tl_set:Nn \l__spath_tmpb_tl {-1} - } - \spath_finalpoint:NV \l__spath_tmpe_tl \l__spath_tmpa_tl - \spath_initialpoint:Nn \l__spath_tmpf_tl {##2} - - \dim_compare:nTF - { - \tl_item:Nn \l__spath_tmpe_tl {1} - > - \tl_item:Nn \l__spath_tmpf_tl {1} - } - { - \spath_splice_between:NVn - \l__spath_tmpa_tl - \l__spath_tmpd_tl - {##2} - } - { - \spath_splice_between:NVn - \l__spath_tmpa_tl - \l__spath_tmpc_tl - {##2} - } - } - { - \tl_put_right:Nn \l__spath_tmpa_tl {##2} - } - } - \tl_gset_eq:cN - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - \l__spath_tmpa_tl + \spath_shorten_at_start:cn } + } {#1} { {} {#2} } + }, + shorten~ at~ both~ ends/.code~ 2~ args={ + \__tikzspath_maybe_current_path_reuse:nnn + { + \__tikzspath_check_path:nnn { - \msg_warning:nnx - { spath3 } - { missing soft path } - { \tl_use:N \l__spath_tmpc_tl } + \spath_shorten_at_both_ends:cn } - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + } {#1} { {} {#2} } }, - 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} - } + shorten~ globally~ at~ end/.code~ 2~ args={ + \__tikzspath_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \__tikzspath_check_path:nnn + { + \spath_gshorten_at_end:cn + } + } {#1} { {} {#2} } }, - 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} - } + shorten~ globally~ at~ start/.code~ 2~ args ={ + \__tikzspath_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \__tikzspath_check_path:nnn + { + \spath_gshorten_at_start:cn + } + } {#1} { {} {#2} } }, - close~ with/.code~ 2~ args={ - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + shorten~ globally~ at~ both~ ends/.code~ 2~ args={ + \__tikzspath_maybe_current_path_reuse:nnn { - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl} + \__tikzspath_check_path:nnn { - \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} + \spath_gshorten_at_both_ends:cn } + } {#1} { {} {#2} } + }, + split~ at/.code~ 2~ args={ + \__tikzspath_maybe_current_path_reuse:nnn + { + \__tikzspath_check_path:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #2 } + \spath_split_at_normalised:cn } - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + } {#1} { {} {#2} } }, - 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} + split~ globally~ at/.code~ 2~ args={ + \__tikzspath_maybe_current_path_reuse:nnn { - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl} + \__tikzspath_check_path:nnn { - \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} + \spath_gsplit_at_normalised:cn } + } {#1} { {} {#2} } + }, + split~ at~ into/.code~ n~ args={4}{ + \__tikzspath_maybe_current_path_reuse:nnn + { + \__tikzspath_check_path:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #2 } + \spath_split_at_normalised:ccvn {\__tikzspath_path_name:n {#1}} + {\__tikzspath_path_name:n {#2}} } - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + } {#3} { {} {#4} } }, - shorten~ 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_shorten_at_end:cn - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} {#2} - } + split~ globally~ at~ into/.code~ n~ args={4}{ + \__tikzspath_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \__tikzspath_check_path:nnn + { + \spath_gsplit_at_normalised:ccvn {\__tikzspath_path_name:n {#1}} + {\__tikzspath_path_name:n {#2}} + } + } {#3} { {} {#4} } }, - shorten~ 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_shorten_at_start:cn - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} {#2} - } + split~ at~ keep~ start/.code~ 2~ args={ + \__tikzspath_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \__tikzspath_check_path:nnn + { + \spath_split_at_normalised_keep_start:cn + } + } {#1} { {} {#2} } }, - shorten~ 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} - } + split~ globally~ at~ keep~ start/.code~ 2~ args={ + \__tikzspath_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \__tikzspath_check_path:nnn + { + \spath_gsplit_at_normalised_keep_start:cn + } + } {#1} { {} {#2} } }, - 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} + split~ at~ keep~ end/.code~ 2~ args={ + \__tikzspath_maybe_current_path_reuse:nnn { - \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 } - } + \__tikzspath_check_path:nnn + { + \spath_split_at_normalised_keep_end:cn + } + } {#1} { {} {#2} } }, - 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} - } + split~ globally~ at~ keep~ end/.code~ 2~ args={ + \__tikzspath_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \__tikzspath_check_path:nnn + { + \spath_gsplit_at_normalised_keep_end:cn + } + } {#1} { {} {#2} } }, - 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 } - } + split~ at~ keep~ middle/.style~ n~ args={3}{ + /tikz/spath/split~ at~ keep~ start={#1}{#3}, + /tikz/spath/split~ at~ keep~ end={#1}{(#2)/(#3)}, + }, + split~ globally~ at~ keep~ middle/.style~ n~ args={3}{ + /tikz/spath/split~ globally~ at~ keep~ start={#1}{#3}, + /tikz/spath/split~ globally~ at~ keep~ end={#1}{(#2)/(#3)}, }, translate/.code~ n~ args={3}{ - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + \__tikzspath_maybe_current_path_reuse:nnn { - \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 } - } + \__tikzspath_check_path:nnn + { + \spath_translate:cnn + } + } {#1} { {} {#2}{#3} } }, 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} - } + \__tikzspath_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \__tikzspath_check_path:nnn + { + \spath_gtranslate:cnn + } + } {#1} { {} {#2}{#3} } }, normalise/.code={ - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + \__tikzspath_maybe_current_path_reuse:nnn { - \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 } - } + \__tikzspath_check_path:nnn + { + \spath_normalise:c + } + } {#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} - } + \__tikzspath_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \__tikzspath_check_path:nnn + { + \spath_gnormalise:c + } + } {#1} { {} } }, transform/.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 + \tikzset{#2} + \pgfgettransform \l__tikzspath_tmpa_tl + \tl_gset_eq:NN \g__tikzspath_smuggle_tl \l__tikzspath_tmpa_tl + \group_end: + + \__tikzspath_maybe_current_path_reuse:nnn { - \group_begin: - \pgftransformreset - \tikzset{#2} - \pgfgettransform \l__spath_tmpa_tl - \tl_gset:Nn \g__spath_smuggle_tl + \__tikzspath_check_path:nnn { - \spath_transform:cnnnnnn - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + \spath_transform:cV } - \tl_gput_right:NV \g__spath_smuggle_tl \l__spath_tmpa_tl - \group_end: - \tl_use:N \g__spath_smuggle_tl - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + } {#1} { {} \g__tikzspath_smuggle_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 + \tikzset{#2} + \pgfgettransform \l__tikzspath_tmpa_tl + \tl_gset_eq:NN \g__tikzspath_smuggle_tl \l__tikzspath_tmpa_tl + \group_end: + + \__tikzspath_maybe_current_path_reuse:nnn { - \group_begin: - \pgftransformreset - \tikzset{#2} - \pgfgettransform \l__spath_tmpa_tl - \tl_gset:Nn \g__spath_smuggle_tl + \__tikzspath_check_path:nnn { - \spath_gtransform:cnnnnnn - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + \spath_gtransform:cV } - \tl_gput_right:NV \g__spath_smuggle_tl \l__spath_tmpa_tl - \group_end: - \tl_use:N \g__spath_smuggle_tl - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + } {#1} { {} \g__tikzspath_smuggle_tl } }, - split~ at~ intersections~ with/.code~ n~ args={2}{ + split~ at~ intersections~ with/.code~ 2~ args={ \tl_if_exist:cTF { tikz@library@intersections@loaded } { - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + \__tikzspath_maybe_current_two_paths_reuse_first:nnnn { - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl} + \__tikzspath_check_two_paths:nnnn { \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 } - } + } {#1} {#2} { {} } } { \msg_warning:nn { spath3 } { load intersections } @@ -1248,23 +1666,13 @@ tikz@library@intersections@loaded } { - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + \__tikzspath_maybe_current_two_paths_reuse_first:nnnn { - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl} + \__tikzspath_check_two_paths:nnnn { \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 } - } + } {#1} {#2} { {} } } { \msg_warning:nn { spath3 } { load intersections } @@ -1276,23 +1684,13 @@ tikz@library@intersections@loaded } { - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + \__tikzspath_maybe_current_two_paths_reuse_both:nnnn { - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl} + \__tikzspath_check_two_paths:nnnn { \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 } - } + } {#1} {#2} { {} } } { \msg_warning:nn { spath3 } { load intersections } @@ -1304,23 +1702,13 @@ tikz@library@intersections@loaded } { - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + \__tikzspath_maybe_current_two_paths_reuse_both:nnnn { - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl} + \__tikzspath_check_two_paths:nnnn { \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 } - } + } {#1} {#2} { {} } } { \msg_warning:nn { spath3 } { load intersections } @@ -1332,15 +1720,13 @@ tikz@library@intersections@loaded } { - \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} - } + \__tikzspath_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \__tikzspath_check_path:nnn + { + \spath_split_at_self_intersections:c + } + } {#1} { {} } } { \msg_warning:nn { spath3 } { load intersections } @@ -1352,627 +1738,334 @@ tikz@library@intersections@loaded } { - \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} - } + \__tikzspath_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \__tikzspath_check_path:nnn + { + \spath_gsplit_at_self_intersections:c + } + } {#1} { {} } } { \msg_warning:nn { spath3 } { load intersections } } }, get~ components~ of/.code~ 2~ args={ - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + \__tikzspath_maybe_current_path:nn { - \clist_clear_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_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} - \clist_put_right:Nx #2 {anonymous_\int_use:N \g__spath_anon_int} - \int_gincr:N \g__spath_anon_int + \__tikzspath_check_path:nnn { + \__tikzspath_get_components:Nv #2 } } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + {#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} + \__tikzspath_maybe_current_path:nn { - \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 + \__tikzspath_check_path:nnn { + \__tikzspath_gget_components:Nv #2 } } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + {#1} + {} }, render~ components/.code={ - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + \__tikzspath_maybe_current_path:nn { - \group_begin: - \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_indexed_inline:Nn \l__spath_tmpa_seq - { - \spath_tikz_path:nn - { - every~ spath~ component/.try, - spath ~component~ ##1/.try, - spath ~component/.try={##1}, - every~ #1~ component/.try, - #1 ~component~ ##1/.try, - #1 ~component/.try={##1}, - } - { - ##2 - } + \__tikzspath_check_path:nnn { + \__tikzspath_render_components:nv {#1} } - \group_end: - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } } + {#1} + {} }, insert~ gaps~ after~ components/.code~ 2~ args={ - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + \tl_if_head_is_group:nTF {#2} { - \group_begin: - \tl_if_head_is_group:nTF {#2} - { - \tl_set:Nx \l__spath_tmpc_tl { \tl_item:nn {#2} {1} } - \tl_set:Nx \l__spath_tmpd_tl { \tl_item:nn {#2} {2} } - } - { - \tl_set:Nn \l__spath_tmpc_tl {#2} - \tl_clear:N \l__spath_tmpd_tl - } - \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} - - \spath_components_to_seq:Nv - \l__spath_tmpa_seq - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - - \tl_if_empty:NTF \l__spath_tmpd_tl - { - \int_step_inline:nnnn {1}{1} { \l__spath_tmpa_int - 1 } - { - \seq_gput_right:Nn \g__spath_tmpa_seq {##1} - \seq_gput_right:Nx - \g__spath_tmpb_seq - {\int_eval:n {##1 + 1}} - } - } - { - \foreach \l__spath_tmpa_tl in \l__spath_tmpd_tl - { - \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 - } - } - } - } - - \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 {\l__spath_tmpc_tl/2} - } - \seq_if_in:NnT \g__spath_tmpb_seq {##1} - { - \spath_shorten_at_start:Nn \l__spath_tmpa_tl {\l__spath_tmpc_tl/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_set_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 + \tl_set:Nx \l__tikzspath_tmpc_tl { \tl_item:nn {#2} {1} } + \tl_set:Nx \l__tikzspath_tmpd_tl { \tl_item:nn {#2} {2} } } { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } + \tl_set:Nn \l__tikzspath_tmpc_tl {#2} + \tl_clear:N \l__tikzspath_tmpd_tl } - }, - insert~ gaps~ globally~ after~ components/.code~ 2~ args={ - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - { - \group_begin: - \tl_if_head_is_group:nTF {#2} - { - \tl_set:Nx \l__spath_tmpc_tl { \tl_item:nn {#2} {1} } - \tl_set:Nx \l__spath_tmpd_tl { \tl_item:nn {#2} {2} } - } - { - \tl_set:Nn \l__spath_tmpc_tl {#2} - \tl_clear:N \l__spath_tmpd_tl - } - \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} - - \spath_components_to_seq:Nv - \l__spath_tmpa_seq - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - \tl_if_empty:NTF \l__spath_tmpd_tl - { - \int_step_inline:nnnn {1}{1} { \l__spath_tmpa_int - 1 } - { - \seq_gput_right:Nn \g__spath_tmpa_seq {##1} - \seq_gput_right:Nx - \g__spath_tmpb_seq - {\int_eval:n {##1 + 1}} - } - } + \__tikzspath_maybe_current_path_reuse:nnn + { + \__tikzspath_check_path:nnn { - \foreach \l__spath_tmpa_tl in \l__spath_tmpd_tl - { - \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 - } - } - } + \__tikzspath_insert_gaps_after_components:cVV } + } {#1} { {} \l__tikzspath_tmpc_tl \l__tikzspath_tmpd_tl } + }, + insert~ gaps~ globally~ after~ components/.code~ 2~ args={ + \tl_if_head_is_group:nTF {#2} + { + \tl_set:Nx \l__tikzspath_tmpc_tl { \tl_item:nn {#2} {1} } + \tl_set:Nx \l__tikzspath_tmpd_tl { \tl_item:nn {#2} {2} } + } + { + \tl_set:Nn \l__tikzspath_tmpc_tl {#2} + \tl_clear:N \l__tikzspath_tmpd_tl + } - \seq_clear:N \l__spath_tmpb_seq - \seq_map_indexed_inline:Nn \l__spath_tmpa_seq + \__tikzspath_maybe_current_path_reuse:nnn + { + \__tikzspath_check_path:nnn { - \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 {\l__spath_tmpc_tl/2} - } - \seq_if_in:NnT \g__spath_tmpb_seq {##1} - { - \spath_shorten_at_start:Nn \l__spath_tmpa_tl {\l__spath_tmpc_tl/2} - } - \seq_put_right:NV \l__spath_tmpb_seq \l__spath_tmpa_tl + \__tikzspath_ginsert_gaps_after_components:cVV } - \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 + } {#1} { {} \l__tikzspath_tmpc_tl \l__tikzspath_tmpd_tl } + }, + insert~ gaps~ after~ segments/.code~ 2~ args={ + \tl_if_head_is_group:nTF {#2} + { + \tl_set:Nx \l__tikzspath_tmpc_tl { \tl_item:nn {#2} {1} } + \tl_set:Nx \l__tikzspath_tmpd_tl { \tl_item:nn {#2} {2} } } { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } + \tl_set:Nn \l__tikzspath_tmpc_tl {#2} + \tl_clear:N \l__tikzspath_tmpd_tl } - }, - join~ components/.code~ 2~ args={ - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + + \__tikzspath_maybe_current_path_reuse:nnn { - \seq_gclear:N \g__spath_tmpa_seq - \foreach \l__spath_tmpa_tl in {#2} + \__tikzspath_check_path:nnn { - \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_join_component:cn - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}{##1} + \__tikzspath_insert_gaps_after_segments:cVV } + } {#1} { {} \l__tikzspath_tmpc_tl \l__tikzspath_tmpd_tl } + }, + insert~ gaps~ globally~ after~ segments/.code~ 2~ args={ + \tl_if_head_is_group:nTF {#2} + { + \tl_set:Nx \l__tikzspath_tmpc_tl { \tl_item:nn {#2} {1} } + \tl_set:Nx \l__tikzspath_tmpd_tl { \tl_item:nn {#2} {2} } } { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } + \tl_set:Nn \l__tikzspath_tmpc_tl {#2} + \tl_clear:N \l__tikzspath_tmpd_tl } - }, - 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} + + \__tikzspath_maybe_current_path_reuse:nnn { - \seq_gclear:N \g__spath_tmpa_seq - \foreach \l__spath_tmpa_tl in {#2} + \__tikzspath_check_path:nnn { - \seq_gput_right:NV \g__spath_tmpa_seq \l__spath_tmpa_tl + \__tikzspath_ginsert_gaps_after_segments:cVV } - \seq_gsort:Nn \g__spath_tmpa_seq + } {#1} { {} \l__tikzspath_tmpc_tl \l__tikzspath_tmpd_tl } + }, + join~ components/.code~ 2~ args={ + \__tikzspath_maybe_current_path_reuse:nnn + { + \__tikzspath_check_path:nnn { - \int_compare:nNnTF {##1} > {##2} - { \sort_return_same: } - { \sort_return_swapped: } + \__tikzspath_join_components:cn } - \seq_map_inline:Nn \g__spath_tmpa_seq + } {#1} { {} {#2} } + }, + join~ components~ globally/.code~ 2~ args={ + \__tikzspath_maybe_current_path_reuse:nnn + { + \__tikzspath_check_path:nnn { - \spath_gjoin_component:cn - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl}{##1} + \__tikzspath_gjoin_components:cn } - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + } {#1} { {} {#2} } }, remove~ empty~ components/.code={ - \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} - } + \__tikzspath_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \__tikzspath_check_path:nnn + { + \spath_remove_empty_components:c + } + } {#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} - } + \__tikzspath_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \__tikzspath_check_path:nnn + { + \spath_gremove_empty_components:c + } + } {#1} { {} } }, replace~ lines/.code={ - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - { - \spath_replace_lines:c - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - } + \__tikzspath_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \__tikzspath_check_path:nnn + { + \spath_replace_lines:c + } + } {#1} { {} } }, replace~ lines~ globally/.code={ - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - { - \spath_greplace_lines:c - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - } + \__tikzspath_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \__tikzspath_check_path:nnn + { + \spath_greplace_lines:c + } + } {#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} + \__tikzspath_maybe_current_path_reuse:nnn { - \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 + \__tikzspath_check_path:nnn { - \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} - } + \__tikzspath_remove_components:cn } - \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 } - } + } {#1} { {} {#2} } }, 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} + \__tikzspath_maybe_current_path_reuse:nnn { - \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 + \__tikzspath_check_path:nnn { - \int_compare:nNnTF {##1} < {##2} - { \sort_return_same: } - { \sort_return_swapped: } + \__tikzspath_gremove_components:cn } - \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 } - } + } {#1} { {} {#2} } }, draft~ mode/.is~ choice, draft~ mode/true/.code={ - \bool_set_true:N \l__spath_draft_bool + \bool_set_true:N \l__tikzspath_draft_bool }, draft~ mode/false/.code={ - \bool_set_false:N \l__spath_draft_bool + \bool_set_false:N \l__tikzspath_draft_bool }, maybe~ spot~ weld/.code={ - \bool_if:NF \l__spath_draft_bool + \bool_if:NF \l__tikzspath_draft_bool { - \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} - } + \__tikzspath_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \__tikzspath_check_path:nnn + { + \spath_spot_weld_components:c + } + } {#1} { {} } } }, maybe~ spot~ weld~ globally/.code={ - \bool_if:NF \l__spath_draft_bool + \bool_if:NF \l__tikzspath_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} - } + \__tikzspath_maybe_current_path_reuse:nnn { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } + \__tikzspath_check_path:nnn + { + \spath_spot_gweld_components:c + } + } {#1} { {} } } }, transform~ to/.code~ 2~ args={ - \group_begin: - \tl_if_exist:cTF - { - \tl_use:N \l__spath_prefix_tl - #1 - \tl_use:N \l__spath_suffix_tl - } + \__tikzspath_maybe_current_path:nn { - \spath_reallength:Nv - \l__spath_tmpa_int - { - \tl_use:N \l__spath_prefix_tl - #1 - \tl_use:N \l__spath_suffix_tl - } - - \tl_set:Nx \l__spath_tmpb_tl - {\fp_to_decimal:n {(#2) * (\l__spath_tmpa_int)}} - \spath_transformation_at:NvV \l__spath_tmpc_tl - { - \tl_use:N \l__spath_prefix_tl - #1 - \tl_use:N \l__spath_suffix_tl + \__tikzspath_check_path:nnn { + \__tikzspath_transform_to:nv {#2} } - \l__spath_tmpb_tl - \tl_gset_eq:NN \g__spath_smuggle_tl \l__spath_tmpc_tl } + {#1} { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - \tl_gset_eq:NN \g__spath_smuggle_tl { {1}{0}{0}{1}{0pt}{0pt} } + \pgfsettransformentries {1}{0}{0}{1}{0pt}{0pt} } - \group_end: - \exp_last_unbraced:NV \pgfsettransformentries \g__spath_smuggle_tl - \tl_gclear:N \g__spath_smuggle_tl }, upright~ transform~ to/.code~ 2~ args={ - \group_begin: - \tl_if_exist:cTF - { - \tl_use:N \l__spath_prefix_tl - #1 - \tl_use:N \l__spath_suffix_tl - } + \__tikzspath_maybe_current_path:nn { - \spath_reallength:Nv - \l__spath_tmpa_int - { - \tl_use:N \l__spath_prefix_tl - #1 - \tl_use:N \l__spath_suffix_tl - } - - \tl_set:Nx \l__spath_tmpb_tl - {\fp_to_decimal:n {(#2) * (\l__spath_tmpa_int)}} - \spath_transformation_at:NvV \l__spath_tmpc_tl - { - \tl_use:N \l__spath_prefix_tl - #1 - \tl_use:N \l__spath_suffix_tl + \__tikzspath_check_path:nnn { + \__tikzspath_transform_upright_to:nv {#2} } - \l__spath_tmpb_tl - \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} + {#1} { - \tl_gset:Nx \g__spath_smuggle_tl - { - { \fp_eval:n { - (\tl_item:Nn \g__spath_smuggle_tl {1})} } - { \fp_eval:n { - (\tl_item:Nn \g__spath_smuggle_tl {2})} } - { \fp_eval:n { - (\tl_item:Nn \g__spath_smuggle_tl {3})} } - { \fp_eval:n { - (\tl_item:Nn \g__spath_smuggle_tl {4})} } - { \tl_item:Nn \g__spath_smuggle_tl {5} } - { \tl_item:Nn \g__spath_smuggle_tl {6} } - } + \pgfsettransformentries {1}{0}{0}{1}{0pt}{0pt} } - \group_end: - \exp_last_unbraced:NV \pgfsettransformentries \g__spath_smuggle_tl - \tl_gclear:N \g__spath_smuggle_tl }, knot/.style~ n~ args={3}{ - 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 + /tikz/spath/split~ at~ self~ intersections=#1, + /tikz/spath/remove~ empty~ components=#1, + /tikz/spath/insert~ gaps~ after~ components={#1}{#2}{#3}, + /tikz/spath/maybe~ spot~ weld=#1, + /tikz/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 - }, + /tikz/spath/split~ globally~ at~ self~ intersections=#1, + /tikz/spath/remove~ empty~ components~ globally=#1, + /tikz/spath/insert~ gaps~ globally ~after~ components={#1}{#2}{#3}, + /tikz/spath/maybe~ spot~ weld~ globally=#1, + /tikz/spath/render~ components=#1 + }, + show/.default=current, + spot~ weld/.default=current, + spot~ weld~ globally/.default=current, + reverse/.default=current, + reverse~ globally/.default=current, + close/.default=current, + close~ globally/.default=current, + open/.default=current, + open~ globally/.default=current, + adjust~ and~ close/.default=current, + adjust~ and~ close~ globally/.default=current, + close~ with~ curve/.default=current, + close~ globally~ with~ curve/.default=current, + remove~ empty~ components/.default=current, + remove~ empty~ components~ globally/.default=current, + replace~ lines/.default=current, + replace~ lines~ globally/.default=current, + maybe~ spot~ weld/.default=current, + maybe~ spot~ weld~ globally/.default=current, } -\tikzdeclarecoordinatesystem{spath}{% +\cs_new_protected_nopar:Npn \__tikzspath_get_point_at:nn #1#2 +{ \group_begin: - \tl_set:Nn \l__spath_tmpa_tl {#1} - \tl_trim_spaces:N \l__spath_tmpa_tl + \spath_reallength:Nn \l__tikzspath_tmpa_int {#2} + \tl_set:Nx \l__tikzspath_tmpb_tl + {\fp_to_decimal:n {(#1) * (\l__tikzspath_tmpa_int)}} + \spath_point_at:NnV \l__tikzspath_tmpc_tl {#2} \l__tikzspath_tmpb_tl - \seq_set_split:NnV \l__spath_tmpa_seq {~} \l__spath_tmpa_tl - \seq_pop_right:NN \l__spath_tmpa_seq \l__spath_tmpb_tl + \tl_clear:N \l__tikzspath_tmpd_tl + \tl_put_right:Nn \l__tikzspath_tmpd_tl {\pgf@x=} + \tl_put_right:Nx \l__tikzspath_tmpd_tl {\tl_item:Nn \l__tikzspath_tmpc_tl {1}} + \tl_put_right:Nn \l__tikzspath_tmpd_tl {\relax} + \tl_put_right:Nn \l__tikzspath_tmpd_tl {\pgf@y=} + \tl_put_right:Nx \l__tikzspath_tmpd_tl {\tl_item:Nn \l__tikzspath_tmpc_tl {2}} + \tl_put_right:Nn \l__tikzspath_tmpd_tl {\relax} - \tl_set:Nx \l__spath_tmpa_tl { \seq_use:Nn \l__spath_tmpa_seq {~} } - \tl_if_exist:cTF - { - \tl_use:N \l__spath_prefix_tl - \tl_use:N \l__spath_tmpa_tl - \tl_use:N \l__spath_suffix_tl - } - { + \tl_gset_eq:NN \g__tikzspath_output_tl \l__tikzspath_tmpd_tl + \group_end: + } +\cs_generate_variant:Nn \__tikzspath_get_point_at:nn {VV, Vn, Vv} - \tl_set_eq:Nc - \l__spath_tmpa_tl - { - \tl_use:N \l__spath_prefix_tl - \tl_use:N \l__spath_tmpa_tl - \tl_use:N \l__spath_suffix_tl - } +\tikzdeclarecoordinatesystem{spath}{% + \group_begin: + \tl_set:Nn \l__tikzspath_tmpa_tl {#1} + \tl_trim_spaces:N \l__tikzspath_tmpa_tl - \tl_if_empty:NTF \l__spath_tmpa_tl - { - \tl_gset_eq:NN \g__spath_smuggle_tl \pgfpointorigin - } - { - \spath_reallength:NV \l__spath_tmpa_int \l__spath_tmpa_tl - \tl_set:Nx \l__spath_tmpb_tl - {\fp_to_decimal:n {(\l__spath_tmpb_tl) * (\l__spath_tmpa_int)}} - \spath_point_at:NVV \l__spath_tmpc_tl \l__spath_tmpa_tl \l__spath_tmpb_tl + \seq_set_split:NnV \l__tikzspath_tmpa_seq {~} \l__tikzspath_tmpa_tl + \seq_pop_right:NN \l__tikzspath_tmpa_seq \l__tikzspath_tmpb_tl + + \tl_set:Nx \l__tikzspath_tmpa_tl { \seq_use:Nn \l__tikzspath_tmpa_seq {~} } - \tl_clear:N \l__spath_tmpd_tl - \tl_put_right:Nn \l__spath_tmpd_tl {\pgf@x=} - \tl_put_right:Nx \l__spath_tmpd_tl {\tl_item:Nn \l__spath_tmpc_tl {1}} - \tl_put_right:Nn \l__spath_tmpd_tl {\relax} - \tl_put_right:Nn \l__spath_tmpd_tl {\pgf@y=} - \tl_put_right:Nx \l__spath_tmpd_tl {\tl_item:Nn \l__spath_tmpc_tl {2}} - \tl_put_right:Nn \l__spath_tmpd_tl {\relax} - \tl_gset_eq:NN \g__spath_smuggle_tl \l__spath_tmpd_tl + \__tikzspath_maybe_current_path:nV + { + \__tikzspath_check_path:nnn { + \__tikzspath_get_point_at:Vv \l__tikzspath_tmpb_tl } } + \l__tikzspath_tmpa_tl { - \msg_warning:nnx - { spath3 } - { missing soft path } - { \tl_use:N \l__spath_tmpa_tl } - \tl_gset_eq:NN \g__spath_smuggle_tl \pgfpointorigin + \tl_gset_eq:NN \g__tikzspath_output_tl \pgfpointorigin } + \group_end: \use:c {pgf@process}{% - \tl_use:N \g__spath_smuggle_tl + \tl_use:N \g__tikzspath_output_tl \pgftransforminvert \use:c {pgf@pos@transform@glob} } + \tl_gclear:N \g__tikzspath_output_tl } \ExplSyntaxOff diff --git a/Master/tlpkg/libexec/ctan2tds b/Master/tlpkg/libexec/ctan2tds index 9613c5cb032..9c65516c5b3 100755 --- a/Master/tlpkg/libexec/ctan2tds +++ b/Master/tlpkg/libexec/ctan2tds @@ -3193,6 +3193,7 @@ my $core_latex = "$Master/texmf-dist/tex/latex"; 'silence' => 'latex -translate-file=empty.tcx', # no 8-bit 'sillypage' => 'etex', 'skdoc' => 'tex', + 'spath3' => 'etex', 'stix2-type1' => 'tex', 'svg' => 'etex', 'svn-multi' => 'latex', # interaction for .pl |