To answer the more important question first: No, nesting tikzpictures is not the right way to do this. The simplest way to achieve the effect that you seem to want is to use the fit
library. Here's an example:
\documentclass[12pt, a4paper]{scrartcl}
\usepackage{tikz}
\usetikzlibrary{fit}
\begin{document}
Before
\begin{tikzpicture}[baseline=(inbox.base)]%
\node[draw,rectangle](inbox){\textcolor{gray}{in}};
\node[draw,rounded corners,fit=(inbox)](outbox) {%
};
\end{tikzpicture}
After
\end{document}
The general principle here is that TikZ/PGF does not need to know about the hierarchy that you wish to specify (namely that inbox
is inside outbox
), it just needs to know how they relate in terms of positioning. So you figure out inbox
first and then put outbox
around it. TikZ is happy as it knows where to put things. If you really, really need to have a hierarchy, us the matrix
node type.
Now for the explanation of what goes wrong. It's all down to the fact that tikzpicture
s are not meant to be stacked inside each other so there is no regard for grouping or scoping. There should be just one tikzpicture
(or \tikz
) containing all the elements and that's what the code expects. This is a great example of this (and one I'll probably refer to many times in explaining why this is a Bad Idea as it comes up quite often).
Let's look at the key command: the baseline
option on the outer tikzpicture
. This says, "I want the following point to be on the baseline of the surrounding text.". The problem with that is that TikZ (or rather, PGF) doesn't know where that point is until it has drawn the picture. So it has to say "Okay, I'll remember that point and at the end of the picture I'll work it out.". So now it goes about its business, figuring out the picture, and at the end it computes the coordinates of the point that you specified.
Here's where the scoping issue comes in. That baseline
option sets some macro which will get evaluated as part of the stuff that happens in \end{tikzpicture}
. If the macro is empty, nothing happens. If it is not empty, PGF uses it to work out the baseline. At the start of the document, the macro is empty. Since \begin{tikzpicture} ... \end{tikzpicture}
happens inside a group, setting it in the options to \begin{tikzpicture}
doesn't change what happens with other pictures unless they are in the same group. So what it happening here is that the inner tikzpicture is inheriting the baseline
command from the outer one, and complaining vociferously because it doesn't know where outer
is!. By the time the inner picture finishes, the outer
node hasn't been positioned yet.
You could say that the \begin{tikzpicture}
should wipe that macro inside its group (which wouldn't affect the outer picture because it is in the outer group). But this would mean that you couldn't say \tikzset{baseline=0pt}
at the start and have that apply to all your pictures in your document - something that is far more useful than nesting tikzpicture
s. So it's a feature, not a bug.
To see that this is the case, run the following code:
\documentclass[12pt, a4paper]{scrartcl}
\usepackage{tikz}
\makeatletter
\def\helpme#1{%
\message{#1}%
\show\pgf@sh@ns@outbox
\show\pgf@baseline
}
\makeatother
\begin{document}
Before
\begin{tikzpicture}[baseline=(outbox.base)]%
\helpme{Start of picture:}
\node[draw,rounded corners](outbox) {%
\helpme{Start of node:}
\begin{tikzpicture}[scale=1]%
\helpme{Start of inner picture:}
\node[draw,rectangle](inbox){\textcolor{gray}{in}};
\end{tikzpicture}
\helpme{After inner picture:}
};
\helpme{End of picture:}
\end{tikzpicture}
After
\end{document}
The diagnostics are a bit crude, I'll admit, but they show what's going on. Actually, you don't need to run it as I'll put (a condensed version of) the output here:
Start of picture:
> \pgf@sh@ns@outbox=undefined.
> \pgf@baseline=macro:
->\tikz@scan@one@point \pgfutil@firstofone (outbox.base).
Start of node:
> \pgf@sh@ns@outbox=undefined.
> \pgf@baseline=macro:
->\tikz@scan@one@point \pgfutil@firstofone (outbox.base).
Start of inner picture:
> \pgf@sh@ns@outbox=undefined.
> \pgf@baseline=macro:
->\tikz@scan@one@point \pgfutil@firstofone (outbox.base).
! Package pgf Error: No shape named outbox is known.
l.20 \end{tikzpicture}
After inner picture:
> \pgf@sh@ns@outbox=undefined.
> \pgf@baseline=macro:
->\tikz@scan@one@point \pgfutil@firstofone (outbox.base).
End of picture:
> \pgf@sh@ns@outbox=macro:
->rectangle.
> \pgf@baseline=macro:
->\tikz@scan@one@point \pgfutil@firstofone (outbox.base).
Notice that \pgf@sh@ns@outbox
is only set after the node has been fully defined (that's what is directly causing the error as it's used to test if a node has been declared). Notice that the error occurs when the inner picture finishes, not the outer one. Notice also that \pgf@baseline
is the same throughout, including in the inner picture.
The moral of the story is: don't nest tikzpictures. They don't like it.
Best Answer
After the definition via
\pgfmathsetmacro
, the macro\dest
contains a real number (1.0
,2.0
, ...), but very likely you need an integer. This can be achieved by using\pgfmathtruncatemacro
instead of\pgfmathsetmacro
to cut the decimal fraction part:Alternatively an integer addition can be used, e.g. via eTeX's
\numexpr
:Another method uses the
evaluate
key (instead of\pgfmathsetmacro
) and theint
function (to truncate your addition):