update i discovered lately this question where Nickolay Kolev uses \tikz
inside a tikzpicture environment. A lot of users think that is a wrong practice and I agree that is very strange but sometimes very useful. I agree too that it's preferable to avoid this kind of situation. I use this possibility in pgfornament
.
I don't understand why if I invert the two lines of the tikzpicture (the wrapper) I get different results. overlay
I think, resets the bounding box but why inside the second tikzpicture, the overlay resests the general bounding box.
When I use a scope, the problem disappears ?
update I suppose that tikz's experts think it's preferable to use a scope and the question is stupid …
Or in the pgfmanual, I read
All graphic options are local to the {tikzpicture} to which they
apply.
The picture in red has no bounding box.
\documentclass[11pt]{scrartcl}
\usepackage{tikz}
\begin{document}
baseline\begin{tikzpicture}[baseline=(current bounding box.north west)]
\tikz[overlay] \path (0,0) -- (1,1) node {\color{blue}$\bullet$};
\draw[help lines,blue!20] (0,0) grid (2,2) ;
\end{tikzpicture}baseline%
%
\begin{tikzpicture}[baseline=(current bounding box.south west)]
\draw[help lines,red!20] (0,0) grid (2,2) ;
\tikz[overlay] \path (0,0) -- (1,1) node {\color{red}$\bullet$};
\end{tikzpicture}baseline
\end{document}
With pgfinterruptboundingbox
Picture in green. The bounding box is correct. The first bounding box is protected.
The solution is to place the line with overlay inside a pgfinterruptboundingbox environment so the problem is linked to the current bounding box.
baseline\begin{tikzpicture}[baseline=(current bounding box.south west)]
\draw[help lines,green!50] (0,0) grid (2,2) ;
\begin{pgfinterruptboundingbox}
\tikz[overlay] \path (0,0) -- (1,1) node {\color{green}$\bullet$};
\end{pgfinterruptboundingbox}
\end{tikzpicture}baseline
No problem with a scope
\documentclass[11pt]{scrartcl}
\usepackage{tikz}
\begin{document}
baseline\begin{tikzpicture}[baseline=(current bounding box.north west)]
\tikz[overlay] \path (0,0) -- (1,1) node {\color{blue}$\bullet$};
\draw[help lines,blue!20] (0,0) grid (2,2) ;
\end{tikzpicture}baseline
\begin{tikzpicture}[baseline=(current bounding box.south west)]
\draw[help lines,red!20] (0,0) grid (2,2) ;
\begin{scope} [overlay] \path (0,0) -- (1,1) node {\color{red}$\bullet$};
\end{scope}
\end{tikzpicture}baseline
\end{document}
( What is the real differences between a scope and a tikzpicture ?)
update The question is perhaps too general, better is How tikz performs overlay
?
Best Answer
That'd be me, then.
This is another example of where unexpected results can occur. The overarching reason is simple: TikZ doesn't expect its environments to be nested and therefore doesn't check various assumptions when it starts and stops. In particular, tracing through the code then one sees that TikZ goes to a lot of effort to work with scopes and groupings within a tikzpicture environment. Since some information has to be extracted from within a scope - for example, bounding box information - TikZ has to "smuggle" this information out and it does that is by using globals. It is quite ingenious how it does this in such a way that the information is passed only to where TikZ wants it to be passed and not, for example, out of any further grouping.
But with the main tikzpicture environment itself, it doesn't expect nesting and so doesn't use these complicated methods. With the bounding box, for example, it knows that
\pgf@picmaxx
is the maximum x-value of the bounding box of the current picture and that there is only one picture involved, so it can regard it as a global variable because that makes life so much easier: every assignment to\pgf@picmaxx
can be global to avoid the hassle with groups and scopes. To avoid complications, all we need to do is ensure that at the start of a tikzpicture environment then all of these globals are set to their defaults.Let's trace the assignment of
\pgf@picmaxx
through your code:At the start of a tikzpicture, it is set to: -16000.0pt
Technically, it is set to -16000.0pt here as well
By the end of this command, it is set to 0.0pt, which is the maximum x-extent of that tikzpicture since it has the
overlay
key.Now, it is set to 57.00548pt which is the extent of the above command.
It is still at 57.00548pt here since it is globally assigned.
Now it is reset to -16000.0pt
Here, it is set to 57.00548pt
At this point, we get reset to -16000.0pt as we've started a new tikzpicture.
Due to the
overlay
key, we get an assignment of 0.0pt here, which is in effect until the end of the picture.And here it is still 0.0pt.
The reason that it works for scopes is that since scopes are meant to be nested, TikZ/PGF goes to great lengths to ensure that things like bounding boxes work correctly as scopes are set up and torn down. This, I think, is the answer to the most fundamental of your questions:
To properly nest tikzpictures, one would have to look at the code for scopes and see what keys, lengths, and macros it goes to great lengths to preserve. Then do the same. This is, I guess, what you are effectively doing with your
\savecurrentboundingbox
and\restorecurrentboundingbox
. I think that the question at the end of your answer would make a very good question in its own right. Even if, as I think, nesting TikZ pictures isn't a good idea, there are, as you point out, inevitably occasions when it is desirable. Knowing how to ensure that when one has to do it, one does it safely would be invaluable information (and, I think, it would show that one should not do this lightly so it would act as a deterrent).