# How to save or define a TikZ path for spath3 without introducing artifacts?

On pg 19 and 20 of the spath3 documentation an arc is defined within \AtBeginDocument to allow its use as a joining path between two crossing paths, as in this MWE (here I've called the arc myarc to distinguish it from arc):

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{spath3, intersections}

\AtBeginDocument{
\tikz[overlay] \path[spath/save=myarc] (0,0) arc[radius=1cm, start angle=180, delta angle=-180];
}

\tikzset{
bridge/.style 2 args={
spath/split at intersections with={#1}{#2},
spath/insert gaps after components={#1}{8pt},
spath/join components upright with={#1}{myarc},
spath/split at intersections with={#2}{#1},
spath/insert gaps after components={#2}{4pt},
}
}

\title{This should be page 1}
\begin{document}
\maketitle
\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{document}


The appearance of the picture is correct but an empty page is produced before the title, seemingly due to the use of \AtBeginDocument:

The documentation suggests placing the \path[spath/save=arc] ... within the tikzpicture environment instead of within AtBeginDocument but (a) this is undesirable for my use because it will force users of the package I'm writing to provide such code for every instance, and (b) this too introduces artifacts sometimes in the form of empty space in the image which you can see using the standalone document class instead of article:

Is there another way to save (or otherwise define) myarc in the preamble so that it's compatible with the spath3 package but without introducing extra artifacts like those described above?

• Try \AtBeginDocument{\sbox0{\tikz[overlay] \path[spath/save global=myarc] (0,0) arc[radius=1cm, start angle=180, delta ang\ le=-180];}} Jul 20 at 19:44
• Is it the same arc every time? If so, you could hard code it into your package. A saved path is just a macro with a specific template name. Jul 20 at 20:30
• @HenriMenke That seems to work perfectly! There's a small typo in your code where ang\ le should be angle but I'm pretty sure that's just a copy/paste thing because when I removed it everything worked fine. If you'll make that an answer I'll select it. Jul 20 at 21:22
• @AndrewStacey That was something I had initially tried with variations using \pgfarc because yes, it does seem to be the same arc every time (I don't know exactly how the internals of spath3 uses it, but at any rate there's never any part of my package that changes its definition). Unfortunately I couldn't figure out how to define it in such a way that the bridge style could find it. Jul 20 at 21:24
• Unfortunately, overleaf doesn't have spath3 installed so I can't test to find the exact syntax you'd need, but if you do a spath/show=myarc then you should get the required soft path in the log file, then define the macro to that. The default naming scheme is \tikz@intersect@path@name@<name> (for compatibility with the intersections library) but you can use a different prefix and/or suffix. There's also a key spath/save to aux which should write the definition to the aux file and that could be copied directly to your package. Jul 20 at 23:05

The problem stems from the fact that an empty tikzpicture will still insert an empty box into the document. This is picked up by commands like \maketitle which force a page break.

To get around this you can typeset the tikzpicture in a box which you then discard. For this I use \sbox0{...} which will save the typeset contents into the box in register 0. However, boxes form an implicit group, so to access the saved path outside the box we need to use spath/save global.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{spath3, intersections}

\AtBeginDocument{%
\sbox0{\tikz[overlay] \path[spath/save global=myarc] (0,0) arc[radius=1cm, start angle=180, delta angle=-180];}%
}

\tikzset{
bridge/.style 2 args={
spath/split at intersections with={#1}{#2},
spath/insert gaps after components={#1}{8pt},
spath/join components upright with={#1}{myarc},
spath/split at intersections with={#2}{#1},
spath/insert gaps after components={#2}{4pt},
}
}

\title{This should be page 1}
\begin{document}
\maketitle
\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{document}


If you are defining a path that won't change (as it would seem from your use-case) then you can hard-code it in the package without needing to define it through a tikz picture. To figure out the definition, define it in a separate document and use the save to aux key. Then you can copy the code from the aux file into your package.

Here's a document to define a semi-circle:

\documentclass{article}
%\url{https://tex.stackexchange.com/q/605800/86}

\usepackage{tikz}
\usetikzlibrary{spath3}

\begin{document}
\begin{tikzpicture}
\path[spath/save=semicircle] (0,0) arc[radius=1,start angle=-180, delta angle=180];
\tikzset{spath/save to aux=semicircle}
\end{tikzpicture}
\end{document}


The auxfile contains the code (line breaks added for clarity):

\ExplSyntaxOn
\tl_clear_new:N \tikz@intersect@path@name@semicircle
\tl_set:Nn \tikz@intersect@path@name@semicircle
{
\pgfsyssoftpath@movetotoken {0.0pt}{0.0pt}
\pgfsyssoftpath@curvetosupportatoken {0.0pt}{-15.71422pt}
\pgfsyssoftpath@curvetosupportbtoken {12.73853pt}{-28.45274pt}
\pgfsyssoftpath@curvetotoken {28.45274pt}{-28.45274pt}
\pgfsyssoftpath@curvetosupportatoken {44.16696pt}{-28.45274pt}
\pgfsyssoftpath@curvetosupportbtoken {56.90549pt}{-15.71422pt}
\pgfsyssoftpath@curvetotoken {56.90549pt}{0.0pt}
}
\ExplSyntaxOff


The name should just contain letters (no digits, spaces, or numbers) since the save to aux key isn't very sophisticated. This can be changed later by editing the code, say to:

\ExplSyntaxOn
\tl_clear_new:c {tikz@intersect@path@name@semi-circle}
\tl_set:cn {tikz@intersect@path@name@semi-circle}
{
\pgfsyssoftpath@movetotoken {0.0pt}{0.0pt}
\pgfsyssoftpath@curvetosupportatoken {0.0pt}{-15.71422pt}
\pgfsyssoftpath@curvetosupportbtoken {12.73853pt}{-28.45274pt}
\pgfsyssoftpath@curvetotoken {28.45274pt}{-28.45274pt}
\pgfsyssoftpath@curvetosupportatoken {44.16696pt}{-28.45274pt}
\pgfsyssoftpath@curvetosupportbtoken {56.90549pt}{-15.71422pt}
\pgfsyssoftpath@curvetotoken {56.90549pt}{0.0pt}
}
\ExplSyntaxOff


Note that the default naming scheme for soft paths is to make them compatible with the intersections library (hence the tikz@intersect@path@name@ bit at the start). There is facility for changing this in the package via the prefix and suffix keys, so by using them within your package you could protect your path from being overwritten accidentally by the user.