diff options
author | Karl Berry <karl@freefriends.org> | 2021-02-22 21:52:11 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2021-02-22 21:52:11 +0000 |
commit | eddf3073a8f4953603e7a5d21fcbba7d1104d502 (patch) | |
tree | 8bbd12381085e1d57c5684f733cd4e662b21e947 /Master | |
parent | d9e54ef03db8d244f5386fc89efffccb3d483a5e (diff) |
spath3 (22feb21)
git-svn-id: svn://tug.org/texlive/trunk@57842 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master')
-rw-r--r-- | Master/texmf-dist/doc/latex/spath3/calligraphy.pdf | bin | 259702 -> 259536 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/latex/spath3/knots.pdf | bin | 341151 -> 341621 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/latex/spath3/spath3.pdf | bin | 353909 -> 388662 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/latex/spath3/spath3.tex | 272 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/spath3/spath3_code.pdf | bin | 576597 -> 571802 bytes | |||
-rw-r--r-- | Master/texmf-dist/source/latex/spath3/spath3_code.dtx | 1261 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/spath3/spath3.sty | 127 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/spath3/tikzlibraryspath3.code.tex | 1039 |
8 files changed, 2076 insertions, 623 deletions
diff --git a/Master/texmf-dist/doc/latex/spath3/calligraphy.pdf b/Master/texmf-dist/doc/latex/spath3/calligraphy.pdf Binary files differindex 6896a3b2895..a700b4fc0e1 100644 --- a/Master/texmf-dist/doc/latex/spath3/calligraphy.pdf +++ b/Master/texmf-dist/doc/latex/spath3/calligraphy.pdf diff --git a/Master/texmf-dist/doc/latex/spath3/knots.pdf b/Master/texmf-dist/doc/latex/spath3/knots.pdf Binary files differindex 1a2afd39dbf..39067dee2e4 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/spath3.pdf b/Master/texmf-dist/doc/latex/spath3/spath3.pdf Binary files differindex 466b71e7e55..ebbefefa1a1 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 49b897c4816..7621db4a287 100644 --- a/Master/texmf-dist/doc/latex/spath3/spath3.tex +++ b/Master/texmf-dist/doc/latex/spath3/spath3.tex @@ -56,6 +56,8 @@ \maketitle +\tableofcontents + \section{Introduction} The \texttt{spath3} package was originally designed as a low-level package for manipulating the \emph{soft paths} defined by PGF/TikZ. @@ -124,59 +126,61 @@ Clones one soft path into another. In the second, the clone is global (the original need not be). \end{function} -\begin{function}{restore, restore reverse} +\begin{function}{use} \begin{syntax} -|restore=|\meta{name} -|restore reverse=|\meta{name} +|use=|\meta{name} +|use=|\marg{name, options} \end{syntax} -Restores a previously saved soft path to the current path. -The \Verb+reverse+ version reverses the soft path first. -This happens immediately so can be issued in the options to the main command and then the path can be extended with normal drawing commands. -Any keys that affect the soft path directly should be applied \emph{before} this one. +This uses a previously saved soft path at the current juncture in the path declaration. +If before the path has begun, it is the initial part of the new path. +If during the path construction then it is stuck in at the current place. +Note that any keys that affect the soft path directly should be applied \emph{before} this one. + +The path can be modified first by using the second form -- note that as far as the \Verb+use+ key is concerned, the whole thing is a single argument. +The options is a comma separated list and can include: +% +\begin{itemize} +\item |reverse| reverses the inserted path first. +\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. +\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} +\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. -Restoring a path also sets things right for positioning nodes along the path. +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. Exactly how the parameter is interpreted is the same as for the \Verb+spath+ coordinate system described in Section~\ref{sec:coordinates}. \end{function} \begin{function}{ + restore, + restore reverse + insert, + insert reverse, append, append reverse, append no move, append reverse no move } -\begin{syntax} -|append=|\meta{name} -|append reverse=|\meta{name} -|append no move=|\meta{name} -|append reverse no move=|\meta{name} -\end{syntax} - -This inserts a soft path, or its reverse, into the path at the current point, it is therefore more suited to being used part way through a path construction. -In a sense, it is a little like a \texttt{pic} in that it enables the user to construct a path segment early to be reused at various places. -The path is \emph{welded} on to the current path, meaning that the intervening \Verb+move+ is removed. -This is particularly useful for creating filled regions. -The first two versions translate the path so that it starts at the last point on the existing path, the second two versions don't do this translation (the intention being that in such a case the translation is omitted because it is \emph{unnecessary} rather than simply not wanted because the effect of removing the intervening move will adjust the initial segment of the appended path otherwise). +These are all aliases to various versions of \Verb+use+ (they originally existed as separate code before I united them all as variants of \Verb+use+). +The equivalences are: -As with restoring a path, the last point and node positioning machinery is established. -The positioning is relative to the appended part of the path, not the full path. -\end{function} - -\begin{function}{insert, insert reverse} -\begin{syntax} -|insert=|\meta{name} -|insert reverse=|\meta{name} -\end{syntax} - -Like \Verb+append+ except that it doesn't remove the intervening \Verb+move+ and doesn't translate the inserted path. -The \Verb+reverse+ version reverses the path first. +\begin{itemize} +\item |restore| and |insert| are aliases for |use|. +\item |append| sets the |move| and |weld| keys. +\item |append no move| just sets the |weld| key. +\item |reverse| sets the |reverse| key. +\end{itemize} \end{function} \begin{function}{to} @@ -191,6 +195,7 @@ The path is transformed by rotation, translation, and uniform scaling so that it \subsection{Transformation Routines} +\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. @@ -236,40 +241,6 @@ This transforms the named path so that it goes from the start point to the end p As with the \Verb+to+ path construction and the \Verb+splice+ method, this won't work if the path ends very close to where it starts. \end{function} -\begin{function}{splice, splice global} -\begin{syntax} -|splice=|\marg{initial path}\marg{splice path}\marg{final path} -|splice globally=|\marg{initial path}\marg{splice path}\marg{final path} -\end{syntax} - -This splices the middle path into the gap between the initial and final paths. -The middle path is transformed to fit (don't try this with a path whose starting and ending points are close together) and the paths are joined so that the last component of the initial path and the first component of the splice path become a single component, and similarly at the other end. -\end{function} - -\begin{function}{join components with, join components globally with} -\begin{syntax} -|join components with=|\marg{path}\marg{splice path} -|join components globally with=|\marg{path}\marg{splice path} -\end{syntax} - -This inserts the |splice path| in the gaps between components of |path|. -A \emph{spot weld} is performed first to join any components where the end of one is the start of the next. -The result is a single component path. -This does \emph{not} close the resulting path, for that see the key |close with|. -\end{function} - -\begin{function}{close, close globally, close with, close globally with} -\begin{syntax} -|close=|\marg{path} -|close globally=|\marg{path} -|close with=|\marg{path}\marg{splice path} -|close globally with=|\marg{path}\marg{splice path} -\end{syntax} - -These all close the last component of the given path. -The first two will insert a line segment if the initial and final points of the component are not sufficiently close. -The latter two allow you to specify another path to insert. -\end{function} \subsection{Intersection Routines} @@ -317,6 +288,20 @@ The second path is not changed. This inserts breaks into a pair of paths at their mutual intersections. \end{function} +\begin{function}{ + replace lines, + replace lines globally +} +\begin{syntax} +|replace lines=|\meta{path} +|replace lines globally=|\meta{path} +\end{syntax} + +The PGF intersection routines have difficulties with parallel, or near parallel, lines. +One way to counter this is to replace all line segments by ``curves''. +This is done so that the parametrisation of the curve matches that of the line segment that it is replacing. +\end{function} + \subsection{Working with Components} \begin{function}{ @@ -335,7 +320,7 @@ The macro can be used in a |\foreach|. The macro consists of a comma separated list of names of the components (the actual names used are of the form \Verb+anonymous_N+). To access an individual component, use the command \Verb+\getComponentOf+. -This can be used directly in place of a path name in any other key, such as \Verb+restore+, (it is just the \LaTeX3 command \Verb+\clist_item:Nn+). +This can be used directly in place of a path name in any other key, such as \Verb+use+, (it is just the \LaTeX3 command \Verb+\clist_item:Nn+). Note that these are \emph{copies} of the components of the original path. Changing a component doesn't update the original path. @@ -365,11 +350,14 @@ It applies the following styles (in this order): } \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} \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. \end{function} \begin{function}{ @@ -386,6 +374,31 @@ 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{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 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} +\end{syntax} + +This inserts the |splice path| in the gaps between components of |path| specified by a comma separated list. +The splice is inserted between each specified component and the next one. +If the \marg{list} is not given (or is empty) then the splice is inserted between every component except that a \emph{spot weld} is performed first to join any components where the end of one is the start of the next. +The spot weld is only performed if the list of components is empty. + +This does \emph{not} close the resulting path, even if the last component is specified in the list, for that see the key |close with|. + +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. +\end{function} + + \begin{function}{ spot weld, spot weld globally @@ -423,6 +436,31 @@ This removes the listed components of the path. As with other list routines, the list is parsed via |foreach| first. \end{function} + +\begin{function}{close, close globally, close with, close globally with} +\begin{syntax} +|close=|\marg{path} +|close globally=|\marg{path} +|close with=|\marg{path}\marg{splice path} +|close globally with=|\marg{path}\marg{splice path} +\end{syntax} + +These all close the last component of the given path. +The first two will insert a line segment if the initial and final points of the component are not sufficiently close. +The latter two allow you to specify another path to insert. +\end{function} + +\begin{function}{splice, splice global} +\begin{syntax} +|splice=|\marg{initial path}\marg{splice path}\marg{final path} +|splice globally=|\marg{initial path}\marg{splice path}\marg{final path} +\end{syntax} + +This splices the middle path into the gap between the initial and final paths. +The middle path is transformed to fit (don't try this with a path whose starting and ending points are close together) and the paths are joined so that the last component of the initial path and the first component of the splice path become a single component, and similarly at the other end. +\end{function} + + \subsection{Shortening Paths} \begin{function}{ @@ -473,8 +511,8 @@ Saves the path to the file \texttt{path.svg} as an SVG document. \subsection{Knots} \begin{function}{ - global knot, knot, + global knot, draft mode } \begin{syntax} @@ -544,7 +582,7 @@ The intention with the second key is that it is similar to what happens with the \section{Examples} \begin{enumerate} -\item Saving, restoring, inserting, and appending. +\item Saving and re-using. \begin{example} \begin{tikzpicture} @@ -554,10 +592,10 @@ The intention with the second key is that it is similar to what happens with the \node[above left] at (spath cs:rpath 0.\k) {\(0.\k\)}; } \fill[green] (2,2) circle[radius=3pt]; -\draw[blue, spath/transform={rpath}{shift={(2,2)}}, spath/restore=rpath] node[right] {transform}; -\draw[orange] (3,0) [spath/insert=rpath] node[right] {insert}; +\draw[blue, spath/transform={rpath}{shift={(2,2)}}, spath/use=rpath] node[right] {transform}; +\draw[orange] (3,0) [spath/use={rpath, move}] node[right] {moving}; \draw[red] (3,-1) -- +(0,2) [spath/append=rpath] node[above] {append}; -\draw[spath/restore=rpath] node[right] {restore}; +\draw[spath/use=rpath] node[right] {use}; \end{tikzpicture} \end{example} @@ -570,8 +608,8 @@ The intention with the second key is that it is similar to what happens with the green, draw=black, ultra thick, - spath/restore=apath -] -- ++(0,-4) [spath/append reverse=apath] -- cycle; + spath/use=apath +] -- ++(0,-4) [spath/use={apath, reverse, move, weld}] -- cycle; \end{tikzpicture} \end{example} @@ -583,7 +621,7 @@ The intention with the second key is that it is similar to what happens with the \draw[rotate=45, xscale=2, yscale=3, ultra thick, red] (0,0) rectangle +(1,1); \draw[ spath/transform={tpath}{rotate=45, xscale=2, yscale=3}, - spath/restore={tpath}]; + spath/use={tpath}]; \end{tikzpicture} \end{example} @@ -615,7 +653,7 @@ The intention with the second key is that it is similar to what happens with the (7,1) circle[radius=3pt] ; -\draw[spath/restore=a]; +\draw[spath/use=a]; \end{tikzpicture} \end{example} @@ -653,9 +691,9 @@ The intention with the second key is that it is similar to what happens with the shorten at end={apath}{7pt}, shorten at start={apath}{9pt}, translate={apath}{0pt}{1pt}, - restore=apath, + use=apath, ]; -\draw (0,0) circle[radius=9pt] [spath/insert=apath] circle[radius=7pt]; +\draw (0,0) circle[radius=9pt] [spath/use=apath] circle[radius=7pt]; \end{tikzpicture} \end{example} @@ -670,9 +708,9 @@ The intention with the second key is that it is similar to what happens with the shorten at end={apath}{7pt}, shorten at start={apath}{9pt}, translate={apath}{0pt}{1pt}, - restore=apath, + use=apath, ]; -\draw (0,0) circle[radius=9pt] [spath/insert=apath] circle[radius=7pt]; +\draw (0,0) circle[radius=9pt] [spath/use=apath] circle[radius=7pt]; \end{tikzpicture} \end{example} @@ -699,7 +737,7 @@ The intention with the second key is that it is similar to what happens with the path \k/.try, spath/.cd, translate=\cpt{0pt}{\k pt}, - restore=\cpt, + use=\cpt, ] +(0,3pt) -- +(0,-3pt); \node[text=red] at (spath cs:{\cpt} .5) {\(\k\)}; } @@ -734,12 +772,12 @@ One of the main motivations for implementing the intersection routines was to pr } \foreach[count=\k] \cpt in \pathAcomponents { - \draw[spath/restore=\cpt,-Circle]; + \draw[spath/use=\cpt,-Circle]; \node[fill=white, fill opacity=.5, circle, text opacity=1] at (spath cs:{\cpt} .5) {\(\k\)}; } \foreach[count=\k] \cpt in \pathBcomponents { - \draw[spath/restore=\cpt,-Circle]; + \draw[spath/use=\cpt,-Circle]; \node[fill=white, fill opacity=.5, circle, text opacity=1] at (spath cs:{\cpt} .5) {\(\k\)}; } \end{tikzpicture} @@ -766,12 +804,12 @@ Although the paths were defined globally, the splitting in the previous example \fill[pattern=bricks, pattern color=white] (-.5,-.5) rectangle (8.5,1.5); \foreach[count=\k] \cpt in \pathAcomponents { - \draw[blue, line width=2pt,spath/restore=\cpt]; + \draw[blue, line width=2pt,spath/use=\cpt]; \node[fill=cyan, fill opacity=.5, circle, text opacity=1] at (spath cs:{\cpt} .3) {\(\k\)}; } \foreach[count=\k] \cpt in \pathBcomponents { - \draw[green, line width=2pt,spath/restore=\cpt]; + \draw[green, line width=2pt,spath/use=\cpt]; \node[fill=green!50, fill opacity=.5, circle, text opacity=1] at (spath cs:{\cpt} .3) {\(\k\)}; } \end{tikzpicture} @@ -807,7 +845,7 @@ arc[radius=.5cm,start angle=90, delta angle=-180] } \foreach[count=\k] \cpt in \pathcomponents { - \draw[spath/restore=\cpt,-|]; + \draw[spath/use=\cpt,-|]; \node[fill=white, fill opacity=.5, circle, text opacity=1] at (spath cs:{\cpt} .5) {\(\k\)}; } \end{tikzpicture} @@ -826,7 +864,7 @@ arc[radius=.5cm,start angle=90, delta angle=-180] } \foreach[count=\k] \cpt in \pathcomponents { - \draw[blue, line width=2pt,spath/restore=\cpt]; + \draw[blue, line width=2pt,spath/use=\cpt]; } \end{tikzpicture} \end{example} @@ -843,5 +881,65 @@ arc[radius=.5cm,start angle=90, delta angle=-180] \tikzset{spath/knot={trefoil}{8pt}{1,3,5}} \end{tikzpicture} \end{example} + +\item Here's how to mark intersections of paths with ``bridges''. +\begin{example} +\begin{tikzpicture} +\coordinate (a) at (-1,0.5); +\coordinate (b) at (8,0.5); +\coordinate (c) at (3,-0.5); +\path[spath/save=sine] +(-1.57,-1) +cos ++(1.57,1) +sin ++(1.57,1) +cos ++(1.57,-1) +sin ++(1.57,-1) +cos ++(1.57,1) +sin ++(1.57,1); +\path[spath/save=over] (a) -- (c) |- (b); + +\path[spath/save=arc] (0,0) arc[radius=1cm, start angle=180, delta angle=-180]; + +\tikzset{ + spath/split at intersections with={over}{sine}, + spath/insert gaps after components={over}{8pt}, + spath/join components upright with={over}{arc}, + spath/split at intersections with={sine}{over}, + spath/insert gaps after components={sine}{4pt}, +} + +\draw[spath/use=sine]; +\draw[spath/use=over]; +\end{tikzpicture} +\end{example} + +\item If there are lots of paths like the previous example, here's a convenient style to put them together. +\begin{example} +\tikzset{ + bridging path/.initial=arc, + bridging span/.initial=8pt, + bridging gap/.initial=4pt, + bridge/.style 2 args={ + spath/split at intersections with={#1}{#2}, + spath/insert gaps after components={#1}{\pgfkeysvalueof{/tikz/bridging span}}, + spath/join components upright with={#1}{\pgfkeysvalueof{/tikz/bridging path}}, + spath/split at intersections with={#2}{#1}, + spath/insert gaps after components={#2}{\pgfkeysvalueof{/tikz/bridging gap}}, + } +} + +% 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]; +%} +\begin{tikzpicture} +\path[spath/save=over] (0,0) -| ++(1,1) -| ++(-1,1) -| ++(1,1) -| ++(-1,1); +\path[spath/save=under] (.5,-.5) -- ++(0,4); +\tikzset{bridge={over}{under}} +\draw[spath/use=over]; +\draw[spath/use=under]; +\end{tikzpicture} +\end{example} + \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 0fe9fd3e43b..e61a569ddf7 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 621ab942f7b..afd132938c7 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{8404} +% \CheckSum{8929} % % \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 @@ -168,6 +168,7 @@ and the derived files spath3.ins, % \changes{1.4}{2020/12/18}{A fair amount of code reimplementation and reorganisation, together with defining TikZ keys to make functions available for use.} % \changes{2.0}{2021/01/19}{Refactored the code to remove the OO approach and make it functional, introduced the spath3 TikZ library to provide a user interface.} % \changes{2.2}{2021/02/05}{Bugfixes and improvements, mainly with regard to the intersection and splitting routines.} +% \changes{2.4}{2021/02/21}{Rejigged how the routines for using paths were implemented, added some more routines for joining paths.} % % \DoNotIndex{\newcommand,\newenvironment} % @@ -256,7 +257,7 @@ and the derived files spath3.ins, \NeedsTeXFormat{LaTeX2e} \RequirePackage{expl3} \RequirePackage{pgf} -\ProvidesExplPackage {spath3} {2021/02/05} {2.2} {Functions for +\ProvidesExplPackage {spath3} {2021/02/21} {2.4} {Functions for manipulating PGF soft paths} \RequirePackage{xparse} % \end{macrocode} @@ -1756,7 +1757,7 @@ manipulating PGF soft paths} { \spath_splice_between:NVnn #1#1{#2}{#3} } -\cs_generate_variant:Nn \spath_splice_between:Nnn {NVV, cnn, cvv, Nvn} +\cs_generate_variant:Nn \spath_splice_between:Nnn {NVV, cnn, cvv, Nvn, NVn} \cs_new_protected_nopar:Npn \spath_gsplice_between:Nnnn #1#2#3#4 { \@@_splice_between:nnn {#2}{#3}{#4} @@ -1768,7 +1769,7 @@ manipulating PGF soft paths} { \spath_gsplice_between:NVnn #1#1{#2}{#3} } -\cs_generate_variant:Nn \spath_gsplice_between:Nnn {NVV, cnn, cvv} +\cs_generate_variant:Nn \spath_gsplice_between:Nnn {NVV, cnn, cvv, Nvn, NVn} % \end{macrocode} % \end{macro} % @@ -1919,7 +1920,7 @@ manipulating PGF soft paths} { \spath_append_no_move:NVn #1#1{#2} } -\cs_generate_variant:Nn \spath_append_no_move:Nn {NV, cv, Nv} +\cs_generate_variant:Nn \spath_append_no_move:Nn {NV, cv, Nv, cV} \cs_new_protected_nopar:Npn \spath_gappend_no_move:Nnn #1#2#3 { \@@_append_no_move:nn {#2}{#3} @@ -1931,7 +1932,7 @@ manipulating PGF soft paths} { \spath_gappend_no_move:NVn #1#1{#2} } -\cs_generate_variant:Nn \spath_gappend_no_move:Nn {NV, cv, Nv} +\cs_generate_variant:Nn \spath_gappend_no_move:Nn {NV, cv, Nv, cV} % \end{macrocode} % \end{macro} % @@ -1953,7 +1954,7 @@ manipulating PGF soft paths} { \spath_append:NVn #1#1{#2} } -\cs_generate_variant:Nn \spath_append:Nn {NV, Nv, cv} +\cs_generate_variant:Nn \spath_append:Nn {NV, Nv, cv, cV} \cs_new_protected_nopar:Npn \spath_gappend:Nnn #1#2#3 { \tl_gset:Nn #1 {#2} @@ -1964,7 +1965,7 @@ manipulating PGF soft paths} { \spath_gappend:NVn #1#1{#2} } -\cs_generate_variant:Nn \spath_gappend:Nn {NV, Nv, cv} +\cs_generate_variant:Nn \spath_gappend:Nn {NV, Nv, cv, cV} % \end{macrocode} % \end{macro} % @@ -2235,6 +2236,128 @@ manipulating PGF soft paths} % \end{macro} % % \begin{macro}[internal]{ +% \spath_replace_lines:Nn, +% \spath_replace_lines:Nn, +% \spath_replace_lines:Nn, +% \spath_replace_lines:Nn, +% } +% Replace any line segments by B\'ezier curves. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_replace_lines:n #1 +{ + \group_begin: + \tl_set:Nn \l_@@_tmpa_tl {#1} + \tl_clear:N \l_@@_tmpb_tl + \dim_set:Nn \l_@@_tmpa_dim {0pt} + \dim_set:Nn \l_@@_tmpb_dim {0pt} + + \bool_do_until:nn + { + \tl_if_empty_p:N \l_@@_tmpa_tl + } + { + \tl_set:Nx \l_@@_tmpc_tl {\tl_item:Nn \l_@@_tmpa_tl {1}} + \tl_set:Nx \l_@@_tmpd_tl {\tl_item:Nn \l_@@_tmpa_tl {2}} + \tl_set:Nx \l_@@_tmpe_tl {\tl_item:Nn \l_@@_tmpa_tl {3}} + + \tl_if_eq:NNTF \l_@@_tmpc_tl \c_spath_lineto_tl + { + \tl_put_right:NV \l_@@_tmpb_tl \c_spath_curvetoa_tl + \tl_put_right:Nx \l_@@_tmpb_tl + { + { + \fp_to_dim:n + { + 2/3 * (\l_@@_tmpa_dim) + + + 1/3 * (\l_@@_tmpd_tl) + } + } + } + \tl_put_right:Nx \l_@@_tmpb_tl + { + { + \fp_to_dim:n + { + 2/3 * (\l_@@_tmpb_dim) + + + 1/3 * (\l_@@_tmpe_tl) + } + } + } + \tl_put_right:NV \l_@@_tmpb_tl \c_spath_curvetob_tl + \tl_put_right:Nx \l_@@_tmpb_tl + { + { + \fp_to_dim:n + { + 1/3 * (\l_@@_tmpa_dim) + + + 2/3 * (\l_@@_tmpd_tl) + } + } + } + \tl_put_right:Nx \l_@@_tmpb_tl + { + { + \fp_to_dim:n + { + 1/3 * (\l_@@_tmpb_dim) + + + 2/3 * (\l_@@_tmpe_tl) + } + } + } + \tl_put_right:NV \l_@@_tmpb_tl \c_spath_curveto_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 + } + + \dim_set:Nn \l_@@_tmpa_dim {\l_@@_tmpd_tl} + \dim_set:Nn \l_@@_tmpb_dim {\l_@@_tmpe_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_@@_tmpb_tl + \group_end: +} +\cs_generate_variant:Nn \@@_replace_lines:n {V} +\cs_new_protected_nopar:Npn \spath_replace_lines:Nn #1#2 +{ + \@@_replace_lines:n {#2} + \tl_set_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_replace_lines:Nn {NV, cV, cv, Nv} +\cs_new_protected_nopar:Npn \spath_replace_lines:N #1 +{ + \spath_replace_lines:NV #1#1 +} +\cs_generate_variant:Nn \spath_replace_lines:N {c} +\cs_new_protected_nopar:Npn \spath_greplace_lines:Nn #1#2 +{ + \@@_replace_lines:n {#2} + \tl_gset_eq:NN #1 \g_@@_output_tl + \tl_gclear:N \g_@@_output_tl +} +\cs_generate_variant:Nn \spath_greplace_lines:Nn {NV, cV, cv, Nv} +\cs_new_protected_nopar:Npn \spath_greplace_lines:N #1 +{ + \spath_greplace_lines:NV #1#1 +} +\cs_generate_variant:Nn \spath_greplace_lines:N {c} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{ % \spath_remove_empty_components:Nn, % \spath_remove_empty_components:N, % \spath_gremove_empty_components:Nn, @@ -4709,8 +4832,8 @@ manipulating PGF soft paths} \cs_generate_variant:Nn \spath_show:n {V, v} % \end{macrocode} % \end{macro} - -% \subsubsection{PGF and TikZ Interface Functions} +% +% \subsection{PGF and TikZ Interface Functions} % % Spaths come from PGF so we need some functions that get and set spaths from the pgf system. % @@ -4845,6 +4968,7 @@ manipulating PGF soft paths} \tl_clear_new:c {tikz@timer} \tl_set:cn {tikz@timer} { + \pgftransformreset \spath_reallength:Nn \l_@@_tmpa_int {#1} \tl_set_eq:Nc \l_@@_tmpb_tl {tikz@time} \tl_set:Nx \l_@@_tmpb_tl @@ -4927,7 +5051,10 @@ manipulating PGF soft paths} % % \begin{macrocode} \msg_new:nnn { spath3 } { missing soft path } { Soft~ path~ #1~ doesn't~ exist } -\msg_new:nnn { spath3 } { empty soft path } { Soft~ path~ #1~ is~ empty } +\msg_new:nnnn { spath3 } { empty soft path } { Soft~ path~ #1~ is~ empty} +{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 } % \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. @@ -4990,6 +5117,73 @@ manipulating PGF soft paths} % \end{macrocode} % \end{macro} % +% \begin{macro}[internal]{ +% \@@_tikzset:n +% } +% Wrapper around \Verb+\tikzset+ for expansion. +% \begin{macrocode} +\cs_set_eq:NN \@@_tikzset:n \tikzset +\cs_generate_variant:Nn \@@_tikzset:n {V, v} +% \end{macrocode} +% \end{macro} +% +% When joining two paths we provide a set of options for how to process the second path. +% +% \begin{macrocode} +\bool_new:N \l_@@_reverse_bool +\bool_new:N \l_@@_weld_bool +\bool_new:N \l_@@_move_bool +\bool_new:N \l_@@_global_bool +\tl_new:N \l_@@_joinpath_tl +\tl_new:N \l_@@_transformation_tl + +\cs_new_protected_nopar:Npn \@@_set_bool:Nn #1#2 +{ + \tl_if_eq:nnTF {#2}{false} + { + \bool_set_false:N #1 + } + { + \bool_set_true:N #1 + } +} +\tikzset { + spath/join/.is~ family, + spath/join/.cd, + reverse/.code = { + \@@_set_bool:Nn \l_@@_reverse_bool {#1} + }, + reverse/.default = true, + weld/.code = { + \@@_set_bool:Nn \l_@@_weld_bool {#1} + }, + weld/.default = true, + no~ weld/.code = { + \@@_set_bool:Nn \l_@@_weld_bool {#1} + \bool_set:Nn \l_@@_weld_bool {! \l_@@_weld_bool} + }, + no~ weld/.default = true, + move/.code = { + \@@_set_bool:Nn \l_@@_move_bool {#1} + }, + move/.default = true, + no~ move/.code = { + \@@_set_bool:Nn \l_@@_move_bool {#1} + \bool_set:Nn \l_@@_move_bool {! \l_@@_move_bool} + }, + no~ move/.default = true, + global/.code = { + \@@_set_bool:Nn \l_@@_global_bool {#1} + }, + global/.default = true, + transform/.store~in=\l_@@_transformation_tl, + .unknown/.code = { + \tl_set_eq:NN \l_@@_joinpath_tl \pgfkeyscurrentname + } +} +% \end{macrocode} +% +% % When we split a soft path into components, we make it a comma separated list so that it can be fed into a \Verb+\foreach+ loop. % This can also make it possible to extract a single component, but to do this we need a wrapper around \Verb+\clist_item:Nn+ (there doesn't appear to be a PGF way of getting an item of a CS list). % @@ -5042,6 +5236,15 @@ manipulating PGF soft paths} \l_@@_tmpa_tl } }, + save~ global/.code={ + \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} + \l_@@_tmpa_tl + } + }, clone/.code~ 2~ args={ \tl_if_exist:cTF {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl} @@ -5070,15 +5273,6 @@ manipulating PGF soft paths} \msg_warning:nnn { spath3 } { missing soft path } { #2 } } }, - save~ global/.code={ - \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} - \l_@@_tmpa_tl - } - }, % \end{macrocode} % % Saves a soft path to the aux file. @@ -5097,77 +5291,152 @@ manipulating PGF soft paths} }, % \end{macrocode} % -% Restores a soft path to the current path. +% Exports the path as an SVG file. % % \begin{macrocode} - restore/.code={ + export~ to~ svg/.code={ \tl_if_exist:cTF {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} { - \tl_if_empty:cTF + \spath_export_to_svg:nv {#1} {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - { - \tl_clear:N \l_@@_tmpa_tl - \tl_put_right:NV \l_@@_tmpa_tl \c_spath_moveto_tl - \tl_put_right:Nn \l_@@_tmpa_tl {{0pt}{0pt}} - \spath_set_current_path:V \l_@@_tmpa_tl - \spath_set_tikz_data:V \l_@@_tmpa_tl - \msg_warning:nnn { spath3 } { empty soft path } { #1 } - } - { - \spath_set_current_path:c - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - \spath_set_tikz_data:v - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - } } { - \tl_clear:N \l_@@_tmpa_tl - \tl_put_right:NV \l_@@_tmpa_tl \c_spath_moveto_tl - \tl_put_right:Nn \l_@@_tmpa_tl {{0pt}{0pt}} - \spath_set_current_path:V \l_@@_tmpa_tl - \spath_set_tikz_data:V \l_@@_tmpa_tl \msg_warning:nnn { spath3 } { missing soft path } { #1 } } }, % \end{macrocode} % -% Restores the reverse of a soft path to the current path. +% Inserts the named path at the current point in the path, with options for how this is accomplished. +% The inserted path can be transformed, reversed, moved to the current point, and welded to the current path. +% If this is used before the path has been started then it becomes the start of the path (and the ``current point'' is taken as the origin). +% % % \begin{macrocode} - restore~ reverse/.code={ + use/.code={ + \bool_set_false:N \l_@@_reverse_bool + \bool_set_false:N \l_@@_weld_bool + \bool_set_false:N \l_@@_move_bool + \tl_clear:N \l_@@_joinpath_tl + \tl_clear:N \l_@@_transformation_tl + \tikzset{ + spath/join/.cd, + #1 + } + \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} { - \tl_if_empty:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \tl_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 + } { - \tl_clear:N \l_@@_tmpa_tl - \tl_put_right:NV \l_@@_tmpa_tl \c_spath_moveto_tl - \tl_put_right:Nn \l_@@_tmpa_tl {{0pt}{0pt}} - \spath_set_current_path:V \l_@@_tmpa_tl - \spath_set_tikz_data:V \l_@@_tmpa_tl \msg_warning:nnn { spath3 } { empty soft path } { #1 } } + \tl_set_eq:Nc \l_@@_joinpath_tl { - \spath_reverse:Nv - \l_@@_reverse_tl - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - \spath_set_current_path:N \l_@@_reverse_tl - \spath_set_tikz_data:V \l_@@_reverse_tl + \tl_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 } + + \spath_set_current_path:N \l_@@_current_tl + \spath_set_tikz_data:V \l_@@_joinpath_tl } { - \tl_clear:N \l_@@_tmpa_tl - \tl_put_right:NV \l_@@_tmpa_tl \c_spath_moveto_tl - \tl_put_right:Nn \l_@@_tmpa_tl {{0pt}{0pt}} - \spath_set_current_path:V \l_@@_tmpa_tl - \spath_set_tikz_data:V \l_@@_tmpa_tl - \msg_warning:nnn { spath3 } { missing soft path } { #1 } + \msg_warning:nnx + { spath3 } + { missing soft path } + {\tl_use:N \l_@@_joinpath_tl } } }, % \end{macrocode} % +% Some aliases for the above. +% +% \begin{macrocode} + restore/.style={/tikz/spath/use={#1}}, + restore~ reverse/.style={/tikz/spath/use={reverse, #1}}, + append/.style={/tikz/spath/use={move, weld, #1}}, + append~ no~ move/.style={/tikz/spath/use={weld, #1}}, + append~ reverse/.style={/tikz/spath/use={move, weld, reverse, #1}}, + append~ reverse~ no~ move/.style={/tikz/spath/use={weld, reverse, #1}}, + insert/.style={/tikz/spath/use={#1}}, + insert~ reverse/.style={/tikz/spath/use={reverse, #1}}, +% \end{macrocode} +% % Diagnostic, show the current path in the terminal and log. % % \begin{macrocode} @@ -5204,45 +5473,99 @@ manipulating PGF soft paths} }, % \end{macrocode} % -% Appends the named path to the current path with a weld. -% -% \begin{macrocode} - append/.code={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - { - \spath_get_current_path:N \l_@@_current_tl - \spath_finalpoint:NV \l_@@_tmpa_tl \l_@@_current_tl - \tl_set_eq:Nc - \l_@@_tmpb_tl - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - \spath_translate_to:NV \l_@@_tmpb_tl \l_@@_tmpa_tl - \spath_append_no_move:NV \l_@@_current_tl \l_@@_tmpb_tl - \spath_set_current_path:N \l_@@_current_tl - \spath_set_tikz_data:V \l_@@_tmpb_tl - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } - }, -% \end{macrocode} -% -% Joins the second named path to the first. +% This joins a path on to an existing path, possibly modifying it first. +% The possible options are the same as those for \Verb+use+. +% It is possible to specify the same path both for the initial and the joining path as a copy is made internally first. % % \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 #2 \tl_use:N \l_@@_suffix_tl} { - \spath_append:cv + \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} + + \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} - {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl} + \l_@@_joinpath_tl } { - \msg_warning:nnn { spath3 } { missing soft path } { #2 } + \msg_warning:nnx + { spath3 } + { missing soft path } + {\tl_use:N \l_@@_joinpath_tl } } } { @@ -5305,113 +5628,6 @@ manipulating PGF soft paths} }, % \end{macrocode} % -% Appends the reversal of the path to the current path. -% -% \begin{macrocode} - append~ reverse/.code={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - { - \spath_reverse:Nv - \l_@@_reverse_tl - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - \spath_get_current_path:N \l_@@_current_tl - \spath_finalpoint:NV \l_@@_tmpa_tl \l_@@_current_tl - \spath_translate_to:NV \l_@@_reverse_tl \l_@@_tmpa_tl - \spath_append_no_move:NV \l_@@_current_tl \l_@@_reverse_tl - \spath_set_current_path:N \l_@@_current_tl - \spath_set_tikz_data:V \l_@@_reverse_tl - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } - }, -% \end{macrocode} -% -% Inserts the named path into the current path as-is, meaning without transforming or welding it. -% -% \begin{macrocode} - insert/.code={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - { - \spath_get_current_path:N \l_@@_current_tl - \spath_append:Nv - \l_@@_current_tl - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - \spath_set_current_path:N \l_@@_current_tl - \spath_set_tikz_data:v - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } - }, -% \end{macrocode} -% -% Inserts the reverse of the named path. -% -% \begin{macrocode} - insert~ reverse/.code={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - { - \spath_reverse:Nv - \l_@@_reverse_tl - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - \spath_get_current_path:N \l_@@_current_tl - \spath_append:NV \l_@@_current_tl \l_@@_reverse_tl - \spath_set_current_path:N \l_@@_current_tl - \spath_set_tikz_data:V \l_@@_reverse_tl - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } - }, -% \end{macrocode} -% -% Appends the named path to the current path without translating it. -% -% \begin{macrocode} - append~ no~ move/.code={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - { - \spath_get_current_path:N \l_@@_current_tl - \spath_append_no_move:Nv - \l_@@_current_tl - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - \spath_set_current_path:N \l_@@_current_tl - \spath_set_tikz_data:v - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } - }, -% \end{macrocode} -% -% Appends the reverse of the named path without translating it. -% -% \begin{macrocode} - append~ reverse~ no~ move/.code={ - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - { - \spath_reverse:Nv - \l_@@_reverse_tl - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} - \spath_get_current_path:N \l_@@_current_tl - \spath_append_no_move:NV \l_@@_current_tl \l_@@_reverse_tl - \spath_set_current_path:N \l_@@_current_tl - \spath_set_tikz_data:V \l_@@_reverse_tl - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } - }, -% \end{macrocode} -% % Adjust a path to span between two points. % % \begin{macrocode} @@ -5519,36 +5735,99 @@ manipulating PGF soft paths} % \end{macrocode} % % Join the components of a path by splicing in the second path whenever the components are sufficiently far apart. +% The third argument is a list of components to splice after, if it is empty then all components are used and a spot weld is done first so that the splicing only happens if there is an actual gap. +% +% The \Verb+upright+ versions will join with the reflection of the splice path if it detects that the gap is ``upside-down''. +% % % \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_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 #2 \tl_use:N \l_@@_suffix_tl} { - \spath_spot_weld_components:c - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \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_map_inline:Nn \l_@@_tmpa_seq + \seq_gpop_left:NN \g_@@_tmpa_seq \l_@@_tmpb_tl + + \seq_map_indexed_inline:Nn \l_@@_tmpa_seq { - \spath_splice_between:Nvn \l_@@_tmpa_tl - {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl} - {##1} + \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:nnn { spath3 } { missing soft path } { #2 } + \msg_warning:nnx + { spath3 } + { missing soft path } + { \tl_use:N \l_@@_tmpc_tl } } } { @@ -5559,30 +5838,319 @@ manipulating PGF soft paths} \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_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 #2 \tl_use:N \l_@@_suffix_tl} { - \spath_spot_gweld_components:c + \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_gset_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 } + } + } + { + \msg_warning:nnn { spath3 } { missing soft path } { #1 } + } + }, + join~ components~ upright~ 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_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_map_inline:Nn \l_@@_tmpa_seq + \seq_gpop_left:NN \g_@@_tmpa_seq \l_@@_tmpb_tl + + \tl_set_eq:Nc \l_@@_tmpc_tl { - \spath_gsplice_between:Nvn \l_@@_tmpa_tl - {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl} - {##1} + \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_set_eq:cN {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} \l_@@_tmpa_tl } { - \msg_warning:nnn { spath3 } { missing soft path } { #2 } + \msg_warning:nnx + { spath3 } + { missing soft path } + { \tl_use:N \l_@@_tmpc_tl } + } + } + { + \msg_warning:nnn { spath3 } { missing soft path } { #1 } + } + }, + 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} + { + \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 + + \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 + } + { + \msg_warning:nnx + { spath3 } + { missing soft path } + { \tl_use:N \l_@@_tmpc_tl } } } { @@ -5790,22 +6358,6 @@ manipulating PGF soft paths} }, % \end{macrocode} % -% Exports the path as an SVG file. -% -% \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} - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } - }, -% \end{macrocode} -% % Transforms the named path using TikZ transformation specifications. % % \begin{macrocode} @@ -5858,40 +6410,58 @@ manipulating PGF soft paths} % \begin{macrocode} split~ at~ intersections~ with/.code~ n~ args={2}{ \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + { + tikz@library@intersections@loaded + } { \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl} + {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} { - \spath_split_path_at_intersections:cv - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \tl_if_exist:cTF {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl} + { + \spath_split_path_at_intersections:cv + {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl} + } + { + \msg_warning:nnn { spath3 } { missing soft path } { #2 } + } } { - \msg_warning:nnn { spath3 } { missing soft path } { #2 } + \msg_warning:nnn { spath3 } { missing soft path } { #1 } } } { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } + \msg_warning:nn { spath3 } { load intersections } } }, split~ globally~ at~ intersections~ with/.code~ n~ args={2}{ \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} { - \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl} + tikz@library@intersections@loaded + } + { + \tl_if_exist:cTF + {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} { - \spath_gsplit_path_at_intersections:cv - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \tl_if_exist:cTF {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl} + { + \spath_gsplit_path_at_intersections:cv + {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl} + } + { + \msg_warning:nnn { spath3 } { missing soft path } { #2 } + } } { - \msg_warning:nnn { spath3 } { missing soft path } { #2 } + \msg_warning:nnn { spath3 } { missing soft path } { #1 } } } { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } + \msg_warning:nn { spath3 } { load intersections } } }, % \end{macrocode} @@ -5901,40 +6471,58 @@ manipulating PGF soft paths} % \begin{macrocode} split~ at~ intersections/.code~ n~ args={2}{ \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + { + tikz@library@intersections@loaded + } { \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl} + {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} { - \spath_split_at_intersections:cc - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \tl_if_exist:cTF {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl} + { + \spath_split_at_intersections:cc + {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl} + } + { + \msg_warning:nnn { spath3 } { missing soft path } { #2 } + } } { - \msg_warning:nnn { spath3 } { missing soft path } { #2 } + \msg_warning:nnn { spath3 } { missing soft path } { #1 } } } { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } + \msg_warning:nn { spath3 } { load intersections } } }, split~ globally~ at~ intersections/.code~ n~ args={2}{ \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + { + tikz@library@intersections@loaded + } { \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl} + {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} { - \spath_gsplit_at_intersections:cc - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \tl_if_exist:cTF {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl} + { + \spath_gsplit_at_intersections:cc + {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + {\tl_use:N \l_@@_prefix_tl #2 \tl_use:N \l_@@_suffix_tl} + } + { + \msg_warning:nnn { spath3 } { missing soft path } { #2 } + } } { - \msg_warning:nnn { spath3 } { missing soft path } { #2 } + \msg_warning:nnn { spath3 } { missing soft path } { #1 } } } { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } + \msg_warning:nn { spath3 } { load intersections } } }, % \end{macrocode} @@ -5944,24 +6532,42 @@ manipulating PGF soft paths} % \begin{macrocode} split~ at~ self~ intersections/.code={ \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} { - \spath_split_at_self_intersections:c + tikz@library@intersections@loaded + } + { + \tl_if_exist:cTF {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + { + \spath_split_at_self_intersections:c + {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + } + { + \msg_warning:nnn { spath3 } { missing soft path } { #1 } + } } { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } + \msg_warning:nn { spath3 } { load intersections } } }, split~ globally~ at~ self~ intersections/.code={ \tl_if_exist:cTF - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} { - \spath_gsplit_at_self_intersections:c + tikz@library@intersections@loaded + } + { + \tl_if_exist:cTF {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + { + \spath_gsplit_at_self_intersections:c + {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + } + { + \msg_warning:nnn { spath3 } { missing soft path } { #1 } + } } { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } + \msg_warning:nn { spath3 } { load intersections } } }, % \end{macrocode} @@ -6069,40 +6675,64 @@ manipulating PGF soft paths} % The list of components is passed through a \Verb+\foreach+ loop so can use the shortcut syntax from those loops. % % \begin{macrocode} - insert~ gaps~ after~ components/.code~ n~ args={3}{ + insert~ gaps~ after~ components/.code~ 2~ args={ \tl_if_exist:cTF {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} { \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} - \foreach \l_@@_tmpa_tl in {#3} + + \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 { - \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 + \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 + } } } } - \spath_components_to_seq:Nv - \l_@@_tmpa_seq - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \seq_clear:N \l_@@_tmpb_seq \seq_map_indexed_inline:Nn \l_@@_tmpa_seq { \tl_set:Nn \l_@@_tmpa_tl {##2} \seq_if_in:NnT \g_@@_tmpa_seq {##1} { - \spath_shorten_at_end:Nn \l_@@_tmpa_tl {#2/2} + \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 {#2/2} + \spath_shorten_at_start:Nn \l_@@_tmpa_tl {\l_@@_tmpc_tl/2} } \seq_put_right:NV \l_@@_tmpb_seq \l_@@_tmpa_tl } @@ -6117,41 +6747,64 @@ manipulating PGF soft paths} \msg_warning:nnn { spath3 } { missing soft path } { #1 } } }, - insert~ gaps~ globally~ after~ components/.code~ n~ args={3}{ + 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} { \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} - \foreach \l_@@_tmpa_tl in {#3} + + \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 { - \seq_gput_right:NV \g_@@_tmpa_seq \l_@@_tmpa_tl - \seq_gput_right:Nx - \g_@@_tmpb_seq + \int_step_inline:nnnn {1}{1} { \l_@@_tmpa_int - 1 } { - \int_eval:n - { - \int_mod:nn { \l_@@_tmpa_tl }{ \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 + } } } } - \spath_components_to_seq:Nv - \l_@@_tmpa_seq - {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + \seq_clear:N \l_@@_tmpb_seq \seq_map_indexed_inline:Nn \l_@@_tmpa_seq { \tl_set:Nn \l_@@_tmpa_tl {##2} \seq_if_in:NnT \g_@@_tmpa_seq {##1} { - \spath_shorten_at_end:Nn \l_@@_tmpa_tl {#2/2} + \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 {#2/2} + \spath_shorten_at_start:Nn \l_@@_tmpa_tl {\l_@@_tmpc_tl/2} } \seq_put_right:NV \l_@@_tmpb_seq \l_@@_tmpa_tl } @@ -6250,6 +6903,33 @@ manipulating PGF soft paths} }, % \end{macrocode} % +% Replace all line segments by B\'ezier curves. +% +% \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} + } + { + \msg_warning:nnn { spath3 } { missing soft path } { #1 } + } + }, + replace~ lines~ globally/.code={ + \tl_if_exist:cTF + {\tl_use:N \l_@@_prefix_tl #1 \tl_use:N \l_@@_suffix_tl} + { + \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 } + } + }, +% \end{macrocode} +% % % Join the specified components together, joining each to its previous one. % @@ -6547,7 +7227,10 @@ manipulating PGF soft paths} } } { - \msg_warning:nnx { spath3 } { missing soft path } { \tl_use:N \l_@@_tmpa_tl } + \msg_warning:nnx + { spath3 } + { missing soft path } + { \tl_use:N \l_@@_tmpa_tl } \tl_gset_eq:NN \g_@@_smuggle_tl \pgfpointorigin } \group_end: diff --git a/Master/texmf-dist/tex/latex/spath3/spath3.sty b/Master/texmf-dist/tex/latex/spath3/spath3.sty index 868e648f570..6a136789262 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/05} {2.2} {Functions for +\ProvidesExplPackage {spath3} {2021/02/21} {2.4} {Functions for manipulating PGF soft paths} \RequirePackage{xparse} \cs_new_protected:Nn \__spath_tl_put_right_braced:Nn @@ -1226,7 +1226,7 @@ manipulating PGF soft paths} { \spath_splice_between:NVnn #1#1{#2}{#3} } -\cs_generate_variant:Nn \spath_splice_between:Nnn {NVV, cnn, cvv, Nvn} +\cs_generate_variant:Nn \spath_splice_between:Nnn {NVV, cnn, cvv, Nvn, NVn} \cs_new_protected_nopar:Npn \spath_gsplice_between:Nnnn #1#2#3#4 { \__spath_splice_between:nnn {#2}{#3}{#4} @@ -1238,7 +1238,7 @@ manipulating PGF soft paths} { \spath_gsplice_between:NVnn #1#1{#2}{#3} } -\cs_generate_variant:Nn \spath_gsplice_between:Nnn {NVV, cnn, cvv} +\cs_generate_variant:Nn \spath_gsplice_between:Nnn {NVV, cnn, cvv, Nvn, NVn} \cs_new_protected_nopar:Npn \__spath_close_with:nn #1#2 { \group_begin: @@ -1355,7 +1355,7 @@ manipulating PGF soft paths} { \spath_append_no_move:NVn #1#1{#2} } -\cs_generate_variant:Nn \spath_append_no_move:Nn {NV, cv, Nv} +\cs_generate_variant:Nn \spath_append_no_move:Nn {NV, cv, Nv, cV} \cs_new_protected_nopar:Npn \spath_gappend_no_move:Nnn #1#2#3 { \__spath_append_no_move:nn {#2}{#3} @@ -1367,7 +1367,7 @@ manipulating PGF soft paths} { \spath_gappend_no_move:NVn #1#1{#2} } -\cs_generate_variant:Nn \spath_gappend_no_move:Nn {NV, cv, Nv} +\cs_generate_variant:Nn \spath_gappend_no_move:Nn {NV, cv, Nv, cV} \cs_new_protected_nopar:Npn \spath_append:Nnn #1#2#3 { \tl_set:Nn #1 {#2} @@ -1378,7 +1378,7 @@ manipulating PGF soft paths} { \spath_append:NVn #1#1{#2} } -\cs_generate_variant:Nn \spath_append:Nn {NV, Nv, cv} +\cs_generate_variant:Nn \spath_append:Nn {NV, Nv, cv, cV} \cs_new_protected_nopar:Npn \spath_gappend:Nnn #1#2#3 { \tl_gset:Nn #1 {#2} @@ -1389,7 +1389,7 @@ manipulating PGF soft paths} { \spath_gappend:NVn #1#1{#2} } -\cs_generate_variant:Nn \spath_gappend:Nn {NV, Nv, cv} +\cs_generate_variant:Nn \spath_gappend:Nn {NV, Nv, cv, cV} \cs_new_protected_nopar:Npn \spath_prepend_no_move:Nnn #1#2#3 { \spath_append_no_move:Nnn #1{#3}{#2} @@ -1596,6 +1596,117 @@ manipulating PGF soft paths} { \spath_gopen:NV #1#1 } +\cs_new_protected_nopar:Npn \__spath_replace_lines:n #1 +{ + \group_begin: + \tl_set:Nn \l__spath_tmpa_tl {#1} + \tl_clear:N \l__spath_tmpb_tl + \dim_set:Nn \l__spath_tmpa_dim {0pt} + \dim_set:Nn \l__spath_tmpb_dim {0pt} + + \bool_do_until:nn + { + \tl_if_empty_p:N \l__spath_tmpa_tl + } + { + \tl_set:Nx \l__spath_tmpc_tl {\tl_item:Nn \l__spath_tmpa_tl {1}} + \tl_set:Nx \l__spath_tmpd_tl {\tl_item:Nn \l__spath_tmpa_tl {2}} + \tl_set:Nx \l__spath_tmpe_tl {\tl_item:Nn \l__spath_tmpa_tl {3}} + + \tl_if_eq:NNTF \l__spath_tmpc_tl \c_spath_lineto_tl + { + \tl_put_right:NV \l__spath_tmpb_tl \c_spath_curvetoa_tl + \tl_put_right:Nx \l__spath_tmpb_tl + { + { + \fp_to_dim:n + { + 2/3 * (\l__spath_tmpa_dim) + + + 1/3 * (\l__spath_tmpd_tl) + } + } + } + \tl_put_right:Nx \l__spath_tmpb_tl + { + { + \fp_to_dim:n + { + 2/3 * (\l__spath_tmpb_dim) + + + 1/3 * (\l__spath_tmpe_tl) + } + } + } + \tl_put_right:NV \l__spath_tmpb_tl \c_spath_curvetob_tl + \tl_put_right:Nx \l__spath_tmpb_tl + { + { + \fp_to_dim:n + { + 1/3 * (\l__spath_tmpa_dim) + + + 2/3 * (\l__spath_tmpd_tl) + } + } + } + \tl_put_right:Nx \l__spath_tmpb_tl + { + { + \fp_to_dim:n + { + 1/3 * (\l__spath_tmpb_dim) + + + 2/3 * (\l__spath_tmpe_tl) + } + } + } + \tl_put_right:NV \l__spath_tmpb_tl \c_spath_curveto_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 + } + + \dim_set:Nn \l__spath_tmpa_dim {\l__spath_tmpd_tl} + \dim_set:Nn \l__spath_tmpb_dim {\l__spath_tmpe_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_tmpb_tl + \group_end: +} +\cs_generate_variant:Nn \__spath_replace_lines:n {V} +\cs_new_protected_nopar:Npn \spath_replace_lines:Nn #1#2 +{ + \__spath_replace_lines:n {#2} + \tl_set_eq:NN #1 \g__spath_output_tl + \tl_gclear:N \g__spath_output_tl +} +\cs_generate_variant:Nn \spath_replace_lines:Nn {NV, cV, cv, Nv} +\cs_new_protected_nopar:Npn \spath_replace_lines:N #1 +{ + \spath_replace_lines:NV #1#1 +} +\cs_generate_variant:Nn \spath_replace_lines:N {c} +\cs_new_protected_nopar:Npn \spath_greplace_lines:Nn #1#2 +{ + \__spath_replace_lines:n {#2} + \tl_gset_eq:NN #1 \g__spath_output_tl + \tl_gclear:N \g__spath_output_tl +} +\cs_generate_variant:Nn \spath_greplace_lines:Nn {NV, cV, cv, Nv} +\cs_new_protected_nopar:Npn \spath_greplace_lines:N #1 +{ + \spath_greplace_lines:NV #1#1 +} +\cs_generate_variant:Nn \spath_greplace_lines:N {c} \cs_new_protected_nopar:Npn \__spath_remove_empty_components:n #1 { \group_begin: @@ -3810,7 +3921,6 @@ manipulating PGF soft paths} } } \cs_generate_variant:Nn \spath_show:n {V, v} - \cs_new_protected_nopar:Npn \spath_get_current_path:N #1 { \pgfsyssoftpath@getcurrentpath #1 @@ -3898,6 +4008,7 @@ manipulating PGF soft paths} \tl_clear_new:c {tikz@timer} \tl_set:cn {tikz@timer} { + \pgftransformreset \spath_reallength:Nn \l__spath_tmpa_int {#1} \tl_set_eq:Nc \l__spath_tmpb_tl {tikz@time} \tl_set:Nx \l__spath_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 9c1c158e52a..bd81706e3b9 100644 --- a/Master/texmf-dist/tex/latex/spath3/tikzlibraryspath3.code.tex +++ b/Master/texmf-dist/tex/latex/spath3/tikzlibraryspath3.code.tex @@ -25,7 +25,10 @@ \seq_new:N \g__spath_tmpb_seq \bool_new:N \l__spath_draft_bool \msg_new:nnn { spath3 } { missing soft path } { Soft~ path~ #1~ doesn't~ exist } -\msg_new:nnn { spath3 } { empty soft path } { Soft~ path~ #1~ is~ empty } +\msg_new:nnnn { spath3 } { empty soft path } { Soft~ path~ #1~ is~ empty} +{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 @@ -68,6 +71,59 @@ \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_if_eq:nnTF {#2}{false} + { + \bool_set_false:N #1 + } + { + \bool_set_true:N #1 + } +} +\tikzset { + spath/join/.is~ family, + spath/join/.cd, + reverse/.code = { + \__spath_set_bool:Nn \l__spath_reverse_bool {#1} + }, + reverse/.default = true, + weld/.code = { + \__spath_set_bool:Nn \l__spath_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} + }, + no~ weld/.default = true, + move/.code = { + \__spath_set_bool:Nn \l__spath_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} + }, + no~ move/.default = true, + global/.code = { + \__spath_set_bool:Nn \l__spath_global_bool {#1} + }, + global/.default = true, + transform/.store~in=\l__spath_transformation_tl, + .unknown/.code = { + \tl_set_eq:NN \l__spath_joinpath_tl \pgfkeyscurrentname + } +} \cs_set_eq:NN \getComponentOf \clist_item:Nn \tikzset{ spath/.is~family, @@ -95,6 +151,15 @@ \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 + } + }, clone/.code~ 2~ args={ \tl_if_exist:cTF {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl} @@ -123,15 +188,6 @@ \msg_warning:nnn { spath3 } { missing soft path } { #2 } } }, - 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 - } - }, save~ to~ aux/.code={ \tl_if_exist:cTF {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} @@ -143,67 +199,134 @@ \msg_warning:nnn { spath3 } { missing soft path } { #1 } } }, - restore/.code={ + export~ to~ svg/.code={ \tl_if_exist:cTF {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} { - \tl_if_empty:cTF + \spath_export_to_svg:nv {#1} {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - { - \tl_clear:N \l__spath_tmpa_tl - \tl_put_right:NV \l__spath_tmpa_tl \c_spath_moveto_tl - \tl_put_right:Nn \l__spath_tmpa_tl {{0pt}{0pt}} - \spath_set_current_path:V \l__spath_tmpa_tl - \spath_set_tikz_data:V \l__spath_tmpa_tl - \msg_warning:nnn { spath3 } { empty soft path } { #1 } - } - { - \spath_set_current_path:c - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - \spath_set_tikz_data:v - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - } } { - \tl_clear:N \l__spath_tmpa_tl - \tl_put_right:NV \l__spath_tmpa_tl \c_spath_moveto_tl - \tl_put_right:Nn \l__spath_tmpa_tl {{0pt}{0pt}} - \spath_set_current_path:V \l__spath_tmpa_tl - \spath_set_tikz_data:V \l__spath_tmpa_tl \msg_warning:nnn { spath3 } { missing soft path } { #1 } } }, - restore~ reverse/.code={ + 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_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} { - \tl_if_empty:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + \tl_use:N \l__spath_prefix_tl + \tl_use:N \l__spath_joinpath_tl + \tl_use:N \l__spath_suffix_tl + } + { + \tl_if_empty:cT + { + \tl_use:N \l__spath_prefix_tl + \tl_use:N \l__spath_joinpath_tl + \tl_use:N \l__spath_suffix_tl + } { - \tl_clear:N \l__spath_tmpa_tl - \tl_put_right:NV \l__spath_tmpa_tl \c_spath_moveto_tl - \tl_put_right:Nn \l__spath_tmpa_tl {{0pt}{0pt}} - \spath_set_current_path:V \l__spath_tmpa_tl - \spath_set_tikz_data:V \l__spath_tmpa_tl \msg_warning:nnn { spath3 } { empty soft path } { #1 } } + \tl_set_eq:Nc \l__spath_joinpath_tl { - \spath_reverse:Nv - \l__spath_reverse_tl - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - \spath_set_current_path:N \l__spath_reverse_tl - \spath_set_tikz_data:V \l__spath_reverse_tl + \tl_use:N \l__spath_prefix_tl + \tl_use:N \l__spath_joinpath_tl + \tl_use:N \l__spath_suffix_tl + } + \spath_get_current_path:N \l__spath_current_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 + { + \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 + } + + \tl_if_empty:NTF \l__spath_current_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_clear:N \l__spath_tmpa_tl + \tl_set:Nn \l__spath_tmpa_tl {spath_} + + \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 {:NV} + + \use:c {\tl_use:N \l__spath_tmpa_tl } + \l__spath_current_tl + \l__spath_joinpath_tl + } + + \spath_set_current_path:N \l__spath_current_tl + \spath_set_tikz_data:V \l__spath_joinpath_tl } { - \tl_clear:N \l__spath_tmpa_tl - \tl_put_right:NV \l__spath_tmpa_tl \c_spath_moveto_tl - \tl_put_right:Nn \l__spath_tmpa_tl {{0pt}{0pt}} - \spath_set_current_path:V \l__spath_tmpa_tl - \spath_set_tikz_data:V \l__spath_tmpa_tl - \msg_warning:nnn { spath3 } { missing soft path } { #1 } + \msg_warning:nnx + { spath3 } + { missing soft path } + {\tl_use:N \l__spath_joinpath_tl } } }, + restore/.style={/tikz/spath/use={#1}}, + restore~ reverse/.style={/tikz/spath/use={reverse, #1}}, + append/.style={/tikz/spath/use={move, weld, #1}}, + append~ no~ move/.style={/tikz/spath/use={weld, #1}}, + append~ reverse/.style={/tikz/spath/use={move, weld, reverse, #1}}, + append~ reverse~ no~ move/.style={/tikz/spath/use={weld, reverse, #1}}, + insert/.style={/tikz/spath/use={#1}}, + insert~ reverse/.style={/tikz/spath/use={reverse, #1}}, show~current~path/.code={ \tikz@addmode{ \pgfsyssoftpath@getcurrentpath\l__spath_tmpa_tl @@ -230,37 +353,94 @@ \msg_warning:nnn { spath3 } { missing soft path } { #1 } } }, - append/.code={ - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - { - \spath_get_current_path:N \l__spath_current_tl - \spath_finalpoint:NV \l__spath_tmpa_tl \l__spath_current_tl - \tl_set_eq:Nc - \l__spath_tmpb_tl - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - \spath_translate_to:NV \l__spath_tmpb_tl \l__spath_tmpa_tl - \spath_append_no_move:NV \l__spath_current_tl \l__spath_tmpb_tl - \spath_set_current_path:N \l__spath_current_tl - \spath_set_tikz_data:V \l__spath_tmpb_tl - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #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 #2 \tl_use:N \l__spath_suffix_tl} { - \spath_append:cv + \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 + } + + \use:c {\tl_use:N \l__spath_tmpa_tl } {\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} + \l__spath_joinpath_tl } { - \msg_warning:nnn { spath3 } { missing soft path } { #2 } + \msg_warning:nnx + { spath3 } + { missing soft path } + {\tl_use:N \l__spath_joinpath_tl } } } { @@ -311,88 +491,6 @@ \msg_warning:nnn { spath3 } { missing soft path } { #1 } } }, - append~ reverse/.code={ - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - { - \spath_reverse:Nv - \l__spath_reverse_tl - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - \spath_get_current_path:N \l__spath_current_tl - \spath_finalpoint:NV \l__spath_tmpa_tl \l__spath_current_tl - \spath_translate_to:NV \l__spath_reverse_tl \l__spath_tmpa_tl - \spath_append_no_move:NV \l__spath_current_tl \l__spath_reverse_tl - \spath_set_current_path:N \l__spath_current_tl - \spath_set_tikz_data:V \l__spath_reverse_tl - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } - }, - insert/.code={ - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - { - \spath_get_current_path:N \l__spath_current_tl - \spath_append:Nv - \l__spath_current_tl - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - \spath_set_current_path:N \l__spath_current_tl - \spath_set_tikz_data:v - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } - }, - insert~ reverse/.code={ - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - { - \spath_reverse:Nv - \l__spath_reverse_tl - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - \spath_get_current_path:N \l__spath_current_tl - \spath_append:NV \l__spath_current_tl \l__spath_reverse_tl - \spath_set_current_path:N \l__spath_current_tl - \spath_set_tikz_data:V \l__spath_reverse_tl - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } - }, - append~ no~ move/.code={ - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - { - \spath_get_current_path:N \l__spath_current_tl - \spath_append_no_move:Nv - \l__spath_current_tl - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - \spath_set_current_path:N \l__spath_current_tl - \spath_set_tikz_data:v - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } - }, - append~ reverse~ no~ move/.code={ - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - { - \spath_reverse:Nv - \l__spath_reverse_tl - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - \spath_get_current_path:N \l__spath_current_tl - \spath_append_no_move:NV \l__spath_current_tl \l__spath_reverse_tl - \spath_set_current_path:N \l__spath_current_tl - \spath_set_tikz_data:V \l__spath_reverse_tl - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } - }, span/.code ~n~ args={3}{ \tl_if_exist:cTF {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} @@ -488,30 +586,89 @@ \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} + { + \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 + } \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl} { - \spath_spot_weld_components:c - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + \tl_use:N \l__spath_prefix_tl + \tl_use:N \l__spath_tmpc_tl + \tl_use:N \l__spath_suffix_tl + } + { + \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_inline:Nn \l__spath_tmpa_seq + \seq_map_indexed_inline:Nn \l__spath_tmpa_seq { - \spath_splice_between:Nvn \l__spath_tmpa_tl - {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl} - {##1} + \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 } { - \msg_warning:nnn { spath3 } { missing soft path } { #2 } + \msg_warning:nnx + { spath3 } + { missing soft path } + { \tl_use:N \l__spath_tmpc_tl } } } { @@ -522,30 +679,319 @@ \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} + { + \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 + } \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl} { - \spath_spot_gweld_components:c + \tl_use:N \l__spath_prefix_tl + \tl_use:N \l__spath_tmpc_tl + \tl_use:N \l__spath_suffix_tl + } + { + \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 + } + { + \msg_warning:nnx + { spath3 } + { missing soft path } + { \tl_use:N \l__spath_tmpc_tl } + } + } + { + \msg_warning:nnn { spath3 } { missing soft path } { #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} + { + \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 + } + \tl_if_exist:cTF + { + \tl_use:N \l__spath_prefix_tl + \tl_use:N \l__spath_tmpc_tl + \tl_use:N \l__spath_suffix_tl + } + { + \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_inline:Nn \l__spath_tmpa_seq + \tl_set_eq:Nc \l__spath_tmpc_tl { - \spath_gsplice_between:Nvn \l__spath_tmpa_tl - {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl} - {##1} + \tl_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 } { - \msg_warning:nnn { spath3 } { missing soft path } { #2 } + \msg_warning:nnx + { spath3 } + { missing soft path } + { \tl_use:N \l__spath_tmpc_tl } + } + } + { + \msg_warning:nnn { spath3 } { missing soft path } { #1 } + } + }, + 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} + { + \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 + } + \tl_if_exist:cTF + { + \tl_use:N \l__spath_prefix_tl + \tl_use:N \l__spath_tmpc_tl + \tl_use:N \l__spath_suffix_tl + } + { + \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 + } + { + \msg_warning:nnx + { spath3 } + { missing soft path } + { \tl_use:N \l__spath_tmpc_tl } } } { @@ -726,17 +1172,6 @@ \msg_warning:nnn { spath3 } { missing soft path } { #1 } } }, - export~ to~ svg/.code={ - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - { - \spath_export_to_svg:nv {#1} - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} - } - { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } - } - }, transform/.code~ 2~ args={ \tl_if_exist:cTF {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} @@ -781,100 +1216,154 @@ }, split~ at~ intersections~ with/.code~ n~ args={2}{ \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + { + tikz@library@intersections@loaded + } { \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl} + {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} { - \spath_split_path_at_intersections:cv - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + \tl_if_exist:cTF {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl} + { + \spath_split_path_at_intersections:cv + {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl} + } + { + \msg_warning:nnn { spath3 } { missing soft path } { #2 } + } } { - \msg_warning:nnn { spath3 } { missing soft path } { #2 } + \msg_warning:nnn { spath3 } { missing soft path } { #1 } } } { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } + \msg_warning:nn { spath3 } { load intersections } } }, split~ globally~ at~ intersections~ with/.code~ n~ args={2}{ \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} { - \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl} + 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_path_at_intersections:cv - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + \tl_if_exist:cTF {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl} + { + \spath_gsplit_path_at_intersections:cv + {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl} + } + { + \msg_warning:nnn { spath3 } { missing soft path } { #2 } + } } { - \msg_warning:nnn { spath3 } { missing soft path } { #2 } + \msg_warning:nnn { spath3 } { missing soft path } { #1 } } } { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } + \msg_warning:nn { spath3 } { load intersections } } }, split~ at~ intersections/.code~ n~ args={2}{ \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + { + tikz@library@intersections@loaded + } { \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl} + {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} { - \spath_split_at_intersections:cc - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + \tl_if_exist:cTF {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl} + { + \spath_split_at_intersections:cc + {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl} + } + { + \msg_warning:nnn { spath3 } { missing soft path } { #2 } + } } { - \msg_warning:nnn { spath3 } { missing soft path } { #2 } + \msg_warning:nnn { spath3 } { missing soft path } { #1 } } } { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } + \msg_warning:nn { spath3 } { load intersections } } }, split~ globally~ at~ intersections/.code~ n~ args={2}{ \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + { + tikz@library@intersections@loaded + } { \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl} + {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} { - \spath_gsplit_at_intersections:cc - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + \tl_if_exist:cTF {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl} + { + \spath_gsplit_at_intersections:cc + {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + {\tl_use:N \l__spath_prefix_tl #2 \tl_use:N \l__spath_suffix_tl} + } + { + \msg_warning:nnn { spath3 } { missing soft path } { #2 } + } } { - \msg_warning:nnn { spath3 } { missing soft path } { #2 } + \msg_warning:nnn { spath3 } { missing soft path } { #1 } } } { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } + \msg_warning:nn { spath3 } { load intersections } } }, split~ at~ self~ intersections/.code={ \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 + 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} + } + { + \msg_warning:nnn { spath3 } { missing soft path } { #1 } + } } { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } + \msg_warning:nn { spath3 } { load intersections } } }, split~ globally~ at~ self~ intersections/.code={ \tl_if_exist:cTF - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} { - \spath_gsplit_at_self_intersections:c + 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} + } + { + \msg_warning:nnn { spath3 } { missing soft path } { #1 } + } } { - \msg_warning:nnn { spath3 } { missing soft path } { #1 } + \msg_warning:nn { spath3 } { load intersections } } }, get~ components~ of/.code~ 2~ args={ @@ -966,40 +1455,64 @@ \msg_warning:nnn { spath3 } { missing soft path } { #1 } } }, - insert~ gaps~ after~ components/.code~ n~ args={3}{ + 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} { \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} - \foreach \l__spath_tmpa_tl in {#3} + + \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 { - \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 + \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 + } } } } - \spath_components_to_seq:Nv - \l__spath_tmpa_seq - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + \seq_clear:N \l__spath_tmpb_seq \seq_map_indexed_inline:Nn \l__spath_tmpa_seq { \tl_set:Nn \l__spath_tmpa_tl {##2} \seq_if_in:NnT \g__spath_tmpa_seq {##1} { - \spath_shorten_at_end:Nn \l__spath_tmpa_tl {#2/2} + \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 {#2/2} + \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 } @@ -1014,41 +1527,64 @@ \msg_warning:nnn { spath3 } { missing soft path } { #1 } } }, - insert~ gaps~ globally~ after~ components/.code~ n~ args={3}{ + 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} - \foreach \l__spath_tmpa_tl in {#3} + + \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 { - \seq_gput_right:NV \g__spath_tmpa_seq \l__spath_tmpa_tl - \seq_gput_right:Nx - \g__spath_tmpb_seq + \int_step_inline:nnnn {1}{1} { \l__spath_tmpa_int - 1 } { - \int_eval:n - { - \int_mod:nn { \l__spath_tmpa_tl }{ \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 + } } } } - \spath_components_to_seq:Nv - \l__spath_tmpa_seq - {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} + \seq_clear:N \l__spath_tmpb_seq \seq_map_indexed_inline:Nn \l__spath_tmpa_seq { \tl_set:Nn \l__spath_tmpa_tl {##2} \seq_if_in:NnT \g__spath_tmpa_seq {##1} { - \spath_shorten_at_end:Nn \l__spath_tmpa_tl {#2/2} + \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 {#2/2} + \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 } @@ -1135,6 +1671,28 @@ \msg_warning:nnn { spath3 } { missing soft path } { #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} + } + { + \msg_warning:nnn { spath3 } { missing soft path } { #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} + } + { + \msg_warning:nnn { spath3 } { missing soft path } { #1 } + } + }, remove~ components/.code~ 2~ args={ \tl_if_exist:cTF {\tl_use:N \l__spath_prefix_tl #1 \tl_use:N \l__spath_suffix_tl} @@ -1403,7 +1961,10 @@ } } { - \msg_warning:nnx { spath3 } { missing soft path } { \tl_use:N \l__spath_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 } \group_end: |