5

I have several tikz pictures which only differ in one line. I want to reuse the parts that are always the same with \savebox (Source) but I keep getting errors. What's wrong?

MWE (without \savebox)

\documentclass[tikz]{standalone}

\begin{document}

\begin{tikzpicture}
\draw[step=1,help lines,black!20] (-0.99,-0.99) grid (8.99,8.99);
\draw[thick,->] (-1,0) -- (9,0) node[pos=0.97,below] {$x$};
\draw[thick,->] (0,-1) -- (0,9) node[pos=0.97,left] {$y$};
% Graph 1 
\draw[very thick,color=black,domain=-1:9] plot (\x,{\x});
\end{tikzpicture}

\begin{tikzpicture}
\draw[step=1,help lines,black!20] (-0.99,-0.99) grid (8.99,8.99);
\draw[thick,->] (-1,0) -- (9,0) node[pos=0.97,below] {$x$};
\draw[thick,->] (0,-1) -- (0,9) node[pos=0.97,left] {$y$};
% Graph 2 
\draw[very thick,color=black,domain=-1:9] plot (\x,{0.5*\x});
\end{tikzpicture}

\end{document}

MWE (with \savebox)

\documentclass[tikz]{standalone}

\begin{document}

\newsavebox{\mygrid}
\savebox{\mygrid}{
    \draw[step=1,help lines,black!20] (-0.99,-0.99) grid (8.99,8.99);
    \draw[thick,->] (-1,0) -- (9,0) node[pos=0.97,below] {$x$};
    \draw[thick,->] (0,-1) -- (0,9) node[pos=0.97,left] {$y$};
}

\begin{tikzpicture}
\usebox{\mygrid}
% Graph 1 
\draw[very thick,color=black,domain=-1:9] plot (\x,{\x});
\end{tikzpicture}

\begin{tikzpicture}
\usebox{\mygrid}
% Graph 2 
\draw[very thick,color=black,domain=-1:9] plot (\x,{0.5*\x});
\end{tikzpicture}

\end{document}

Screenshots

Graph 1

enter image description here

Graph 2

enter image description here

2 Answers2

7

A \savebox can only store a complete box. A complete tikzpicture qualifies for being used in a \savebox, a collection of paths does not. The TikZy way of doing this is to define a pic. (style=grid wasn't defined in your MWE so I made something up.)

\documentclass[tikz]{standalone}
\tikzset{grid/.style={draw=gray,thin},
pics/alwaysthesame/.style={code={%
\draw[style=grid] (-0.99,-0.99) grid (8.99,8.99);
\draw[thick,->] (-1,0) -- (9,0) node[pos=0.97,below] {$x$};
\draw[thick,->] (0,-1) -- (0,9) node[pos=0.97,left] {$y$};
}}}
\begin{document}

\begin{tikzpicture}
\pic{alwaysthesame};
% Graph 1 
\draw[very thick,color=black,domain=-1:9] plot (\x,{\x});
\end{tikzpicture}

\begin{tikzpicture}
\pic{alwaysthesame};
% Graph 2 
\draw[very thick,color=black,domain=-1:9] plot (\x,{0.5*\x});
\end{tikzpicture}

\end{document}

You can also use the every picture and execute at begin picture keys to spare you from punching in the pics in every picture. Now with the updated code for the grid.

\documentclass[tikz]{standalone}
\tikzset{pics/alwaysthesame/.style={code={%
\draw[step=1,help lines,black!20] (-0.99,-0.99) grid (8.99,8.99);
\draw[thick,->] (-1,0) -- (9,0) node[pos=0.97,below] {$x$};
\draw[thick,->] (0,-1) -- (0,9) node[pos=0.97,left] {$y$};
}},every picture/.append style={execute at begin picture={\pic{alwaysthesame};}}}
\begin{document}

\begin{tikzpicture}
% Graph 1 
\draw[very thick,color=black,domain=-1:9] plot (\x,{\x});
\end{tikzpicture}

\begin{tikzpicture}
% Graph 2 
\draw[very thick,color=black,domain=-1:9] plot (\x,{0.5*\x});
\end{tikzpicture}

\end{document}

enter image description here

You could save a complete tikzpicture in a \savebox and put it in a node. This does work, but you need to be very careful to use e.g. inner sep when you do that.

\documentclass[tikz]{standalone}
\newsavebox\AlwaysTheSame
\sbox\AlwaysTheSame{\begin{tikzpicture}
\draw[step=1,help lines,black!20] (-0.99,-0.99) grid (8.99,8.99);
\draw[thick,->] (-1,0) -- (9,0) node[pos=0.97,below] {$x$};
\draw[thick,->] (0,-1) -- (0,9) node[pos=0.97,left] {$y$};
\end{tikzpicture}}
\begin{document}

\begin{tikzpicture}
\node[anchor=south west,inner sep=0pt,outer sep=0pt] at (-0.99,-0.99)
{\usebox\AlwaysTheSame};
% Graph 1 
\draw[very thick,color=black,domain=-1:9] plot (\x,{\x});
\end{tikzpicture}

\begin{tikzpicture}
\node[anchor=south west,inner sep=0pt,outer sep=0pt] at (-0.99,-0.99)
{\usebox\AlwaysTheSame};
% Graph 2 
\draw[very thick,color=black,domain=-1:9] plot (\x,{0.5*\x});
\end{tikzpicture}

\end{document}
  • \savebox doesn't work in my case? – Andreas Schneider Dec 19 '19 at 16:23
  • @Sr.Schneider No. A \savebox saves a box. A complete tikzpicture is a box, a collection of paths is not a box. But thanks for completing your MWE! (+1) –  Dec 19 '19 at 16:25
  • I'll write a slightly more detailed explanation in another answer. – Hood Chatham Dec 19 '19 at 16:26
  • @Schrödinger'scat Do you know what happens in a pic behind the scenes? In particular, in what ways is using \pic different than using a macro? I suppose I should read the manual... – Hood Chatham Dec 19 '19 at 16:29
  • @HoodChatham In short, a pic is more powerful. To give you an example, you could e.g. say \path (0,0) -- (3,0) pic[midway,sloped] {<some pic>}; which clearly does not work with \newcommand. –  Dec 19 '19 at 16:33
  • @Sr.Schneider I added an example which uses a \savebox. It does work, but is not as versatile as the pic (but a bit faster to compile). –  Dec 19 '19 at 16:36
  • @Schrödinger'scat Makes sense thanks -- it uses a local coordinate system and scoping and interacts well with tikz syntax. – Hood Chatham Dec 19 '19 at 16:45
3

In addition to the solution Schrodinger's cat provided, it's also possible to do this using \newcommand.

Someone should explain here why boxes are not the right way to approach this problem. I don't think this is the clearest explanation, but here it is. Roughly speaking, a \box is a collection of stored material that has already been formatted. When you "use" a box, the already formatted material stored in the box is just dumped onto the page. In particular, no logic is allowed to be stored in the box. Tikz needs a whole lot of logic in order to control the drawing global state (so for instance, if tikz adds a curve to the pdf, the color, line thickness, and dash pattern used to draw the curve depends on the global state). So if you want to store up Tikz code, store it in a macro or using one of the techniques Scrodinger's cat indicated.

\documentclass[tikz]{standalone}

\begin{document}

\tikzset{gridstyle/.style={help lines}}
\newcommand{\mygrid}{
    \draw[gridstyle] (-0.99,-0.99) grid (8.99,8.99);
    \draw[thick,->] (-1,0) -- (9,0) node[pos=0.97,below] {$x$};
    \draw[thick,->] (0,-1) -- (0,9) node[pos=0.97,left] {$y$};
}

\begin{tikzpicture}
\mygrid
% Graph 1
\draw[very thick,color=black,domain=-1:9] plot (\x,{\x});
\end{tikzpicture}

\begin{tikzpicture}
\mygrid
% Graph 2
\draw[very thick,color=black,domain=-1:9] plot (\x,{0.5*\x});
\end{tikzpicture}
\end{document} 
Hood Chatham
  • 5,467
  • Is it better to use \newcommand or pic? – Andreas Schneider Dec 19 '19 at 17:08
  • 1
    I think it's purely a matter of taste. pic offers increased flexibility, but requires you to use a less familiar syntax and you might not ever use that flexibility. If your goal is to learn tikz, perhaps it'd be best to use pic. – Hood Chatham Dec 19 '19 at 18:49