Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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  

enter image description here

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 ?

share|improve this question
add comment

2 Answers

up vote 9 down vote accepted

A lot of users think that [nesting TikZ pictures] is a wrong practice

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:

\documentclass[11pt]{scrartcl}
\usepackage{tikz}    
\begin{document}

baseline\begin{tikzpicture}[baseline=(current bounding box.north west)] 

At the start of a tikzpicture, it is set to: -16000.0pt

 \tikz[overlay]

Technically, it is set to -16000.0pt here as well

                \path (0,0) --  (1,1) node  {\color{blue}$\bullet$};

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.

 \draw[help lines,blue!20] (0,0) grid (2,2) ;

Now, it is set to 57.00548pt which is the extent of the above command.

\end{tikzpicture}baseline%

It is still at 57.00548pt here since it is globally assigned.

% 
\begin{tikzpicture}[baseline=(current bounding box.south west)] 

Now it is reset to -16000.0pt

  \draw[help lines,red!20] (0,0) grid (2,2) ;

Here, it is set to 57.00548pt

  \tikz[overlay]

At this point, we get reset to -16000.0pt as we've started a new tikzpicture.

                 \path (0,0) --  (1,1) node  {\color{red}$\bullet$}; 

Due to the overlay key, we get an assignment of 0.0pt here, which is in effect until the end of the picture.

\end{tikzpicture}baseline    

And here it is still 0.0pt.

\end{document}

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:

What is the real differences between a scope and a tikzpicture ?

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).

share|improve this answer
add comment

A possibility is when an environment tikzpicture with \begin{tikzpicture} or \tikz is created a lot of variables and options are setup correctly. The path is now empty but why is it the same path ?

The next code shows without an overlay we can place something on the page and the bounding box is correct

I avoid \begin{pgfinterruptboundingbox} with two macros \savecurrentboundingbox and \restorecurrentboundingbox

    \documentclass[11pt]{scrartcl}
    \usepackage{tikz,lipsum}
    \newcommand\savecurrentboundingbox{%
    \coordinate (saved cbb ne) at (current bounding box.north east);
    \coordinate (saved cbb sw) at (current bounding box.south west);  }
    \newcommand\restorecurrentboundingbox{%
    \useasboundingbox (saved cbb sw) rectangle (saved cbb ne); }         
    \begin{document}

    \lipsum[1]
    \fbox{%
      \begin{tikzpicture}[baseline=(current bounding box.south west)] 
      \draw[help lines,red!20] (0,0) grid (2,2) ;
      \savecurrentboundingbox
      \tikz {%
      \path[use as bounding box] (0,0) rectangle (0,0); 
      \path (0,0) --  (4,4) node  {\color{red}$\bullet$};}%
     \restorecurrentboundingbox 
    \end{tikzpicture}%
    }baseline

    \end{document} 

enter image description here

It will be interesting to know what are the important variables used at the beginning of an tikzpicture environment.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.