5

I'm trying to include a scaled graph into another picture (yes I need to use nested tikz pictures, but I can't find any better way), and the problem is that the arrow heads are not scaled properly, so the scaled graph looks weird. Any idea to scale properly a graph?

I tried \scalebox{.6}{...} which works great for tikzpicture alone, but in nested tikzpicture, the bounding box used is as if the graph wouldn't have been scaled, which makes the positionning ugly.

Also, I could generate first a pdf and include it, but it's not really practical because I want to use it in a beamer slide and I need to include some \onslide<...> command inside, so it means that I would need to create one tex/pdf for each slide...

Bonus: you get a bonus if the method also allow links to nested tikzpicture with remember options.

MWE:

\documentclass[a4paper]{article}

\usepackage{tikz}

\begin{document}
Not scaled:
\begin{tikzpicture}[
    qubit/.style={draw, circle, color=black, anchor=center,
      fill={rgb,255:red,143;green,146;blue,237},
      inner sep=0pt,minimum width=5mm}
    ]
  \node[qubit] (q1) at (0,0){};
  \draw[red,-stealth] (q1.center) -- (q1.north);
\end{tikzpicture}


Scaled:
\begin{tikzpicture}[scale=.5, every node/.style={scale=.5},
    qubit/.style={draw, circle, color=black, anchor=center,
      fill={rgb,255:red,143;green,146;blue,237},
      inner sep=0pt,minimum width=5mm}
    ]
  \node[qubit] (q1) at (0,0){};
  \draw[red,-stealth] (q1.center) -- (q1.north);
\end{tikzpicture}
\end{document}

enter image description here

-- EDIT -- Here is a MWE with the included nested tikzpicture:

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{calc,positioning}

\begin{document}
Not scaled:
\begin{tikzpicture}[
  qubit/.style={draw, circle, color=black, anchor=center,
    fill={rgb,255:red,143;green,146;blue,237},
    inner sep=0pt,minimum width=5mm}
  ]
  \node[qubit] (q1) at (0,0){};
  \node[qubit,right=of q1] (q2) {};
  \draw[-] (q1) -- (q2);
  \draw[red,-stealth] (q1.center) -- (q1.north);
\end{tikzpicture}

Scale + transform shape:\\
\begin{tikzpicture}
  \node[circle,draw,fill=green] (A) {A};
  \node[circle,draw,fill=green,right=of A] (B) {B};
  \node[circle,draw,fill=green,above=of A] (C) {C};
  \node[above=of B.center,anchor=south east] (graph) {
    \begin{tikzpicture}[scale=0.5, every node/.style={transform shape},
      qubit/.style={draw, circle, color=black, anchor=center,
        fill={rgb,255:red,143;green,146;blue,237},
        inner sep=0pt,minimum width=5mm}
      ]
      \node[qubit] (q1) at (0,0){};
      \node[qubit,right=of q1] (q2) {};
      \draw[-] (q1) -- (q2);
      \draw[red,-stealth] (q1.center) -- (q1.north);
    \end{tikzpicture}
  };
  \node[fill=green,inner sep=0pt,minimum size=3pt] at (graph.north east) {};
  \node[fill=red,inner sep=0pt,minimum size=3pt] at (graph.north west) {};
  \node[fill=yellow,inner sep=0pt,minimum size=3pt] at (graph.south east) {};
  \node[fill=orange,inner sep=0pt,minimum size=3pt] at (graph.south west) {};
\end{tikzpicture}

transform canvas, good arrow size, bad position:\\
\begin{tikzpicture}
  \node[circle,draw,fill=green] (A) {A};
  \node[circle,draw,fill=green,right=of A] (B) {B};
  \node[circle,draw,fill=green,above=of A] (C) {C};
  \node[above=of B.center,anchor=south east] (graph2) {
    \begin{tikzpicture}[transform canvas={scale=0.5},
      qubit/.style={draw, circle, color=black, anchor=center,
        fill={rgb,255:red,143;green,146;blue,237},
        inner sep=0pt,minimum width=5mm}
      ]
      \node[qubit] (q3) at (0,0){};
      \node[qubit,right=of q3] (q4) {};
      \draw[-] (q3) -- (q4);
      \draw[red,-stealth] (q3.center) -- (q3.north);
    \end{tikzpicture}
  };
  \node[fill=green,inner sep=0pt,minimum size=3pt] at (graph2.north east) {};
  \node[fill=red,inner sep=0pt,minimum size=3pt] at (graph2.north west) {};
  \node[fill=yellow,inner sep=0pt,minimum size=3pt] at (graph2.south east) {};
  \node[fill=orange,inner sep=0pt,minimum size=3pt] at (graph2.south west) {};
\end{tikzpicture}

\end{document}

enter image description here

-- EDIT 2 -- I tried with xsavebox as proposed in comments, and it works pretty well, except that it does not deal with beamer overlay, which is quite a big issue in my case...

\documentclass{beamer}
\usepackage{xsavebox}
\usepackage{tikz}
\usetikzlibrary{calc,positioning}

\begin{document}

\begin{frame}
Not scaled:
\begin{tikzpicture}[
  qubit/.style={draw, circle, color=black, anchor=center,
    fill={rgb,255:red,143;green,146;blue,237},
    inner sep=0pt,minimum width=5mm}
  ]
  \node[qubit] (q1) at (0,0){};
  \node[qubit,right=of q1] (q2) {};
  \draw[-] (q1) -- (q2);
  \draw[red,-stealth] (q1.center) -- (q1.north);
\end{tikzpicture}
\end{frame}

\begin{frame}
Scale + transform shape, good position, bad arrow size:\\
\begin{tikzpicture}
  \node[circle,draw,fill=green] (A) {A};
  \node[circle,draw,fill=green,right=of A] (B) {B};
  \node[circle,draw,fill=green,above=of A] (C) {C};
  \node[above=of B.center,anchor=south east] (graph) {
    \begin{tikzpicture}[scale=0.5, every node/.style={transform shape},
      qubit/.style={draw, circle, color=black, anchor=center,
        fill={rgb,255:red,143;green,146;blue,237},
        inner sep=0pt,minimum width=5mm}
      ]
      \node[qubit] (q1) at (0,0){};
      \node[qubit,right=of q1] (q2) {};
      \draw[-] (q1) -- (q2);
      \draw[red,-stealth] (q1.center) -- (q1.north);
      \node<2>[qubit,above=of q2] (q2bis) {};
    \end{tikzpicture}
  };
  \node[fill=green,inner sep=0pt,minimum size=3pt] at (graph.north east) {};
  \node[fill=red,inner sep=0pt,minimum size=3pt] at (graph.north west) {};
  \node[fill=yellow,inner sep=0pt,minimum size=3pt] at (graph.south east) {};
  \node[fill=orange,inner sep=0pt,minimum size=3pt] at (graph.south west) {};
\end{tikzpicture}
\end{frame}

\begin{frame}
  transform canvas, good arrow size, bad position:\\
  \begin{tikzpicture}
    \node[circle,draw,fill=green] (A) {A};
    \node[circle,draw,fill=green,right=of A] (B) {B};
    \node[circle,draw,fill=green,above=of A] (C) {C};
    \node[above=of B.center,anchor=south east] (graph2) {
      \begin{tikzpicture}[transform canvas={scale=0.5},
        qubit/.style={draw, circle, color=black, anchor=center,
          fill={rgb,255:red,143;green,146;blue,237},
          inner sep=0pt,minimum width=5mm}
        ]
        \node[qubit] (q3) at (0,0){};
        \node[qubit,right=of q3] (q4) {};
        \draw[-] (q3) -- (q4);
        \draw[red,-stealth] (q3.center) -- (q3.north);
        \node<2>[qubit,above=of q4] (q5) {};
      \end{tikzpicture}
    };
    \node[fill=green,inner sep=0pt,minimum size=3pt] at (graph2.north east) {};
    \node[fill=red,inner sep=0pt,minimum size=3pt] at (graph2.north west) {};
    \node[fill=yellow,inner sep=0pt,minimum size=3pt] at (graph2.south east) {};
    \node[fill=orange,inner sep=0pt,minimum size=3pt] at (graph2.south west) {};
  \end{tikzpicture}
\end{frame}


\begin{xlrbox}{mybox}
  \begin{tikzpicture}[
    qubit/.style={draw, circle, color=black, anchor=center,
      fill={rgb,255:red,143;green,146;blue,237},
      inner sep=0pt,minimum width=5mm}
    ]
    \node[qubit] (q3) at (0,0){};
    \node[qubit,right=of q3] (q4) {};
    \draw[-] (q3) -- (q4);
    \draw[red,-stealth] (q3.center) -- (q3.north);
    \node<2>[qubit,above=of q4] (q5) {};
  \end{tikzpicture}
\end{xlrbox}

\begin{frame}
xlrbox, good resize, no beamer overlay:\\
\begin{tikzpicture}
  \node[circle,draw,fill=green] (A) {A};
  \node[circle,draw,fill=green,right=of A] (B) {B};
  \node[circle,draw,fill=green,above=of A] (C) {C};
  \node[above=of B.center,anchor=south east] (graph2) {\scalebox{0.5}{\themybox}};
  \node[fill=green,inner sep=0pt,minimum size=3pt] at (graph2.north east) {};
  \node[fill=red,inner sep=0pt,minimum size=3pt] at (graph2.north west) {};
  \node[fill=yellow,inner sep=0pt,minimum size=3pt] at (graph2.south east) {};
  \node[fill=orange,inner sep=0pt,minimum size=3pt] at (graph2.south west) {};
\end{tikzpicture}
\end{frame}

\end{document}
5
  • 2
    Please check this answer, this answer and this answer. Aug 13 '18 at 12:37
  • 1
    Not to advertise one of my own questions, but you might find what is the best way to combine tikzpictures and beamer overlays interesting for your application. The proposed answer allows to create 1 pdf document that handles overlays. You could create every specific symbol in a standalone image then include it with overlay specifications ...
    – BambOo
    Aug 13 '18 at 12:51
  • 2
    @RuixiZhang The only two methods that really scale correctly are resizebox and transform canvas={scale=0.5}. All the other ones (scale=0.5, every node/.style={transform shape}, scale=.5, every node/.style={scale=.5}...) fails to resize line width and arrow width correctly. The problem of resizebox and transform canvas={scale=0.5} is that they break the bounding box : resizebox does not scale the bounding box, and transform canvas sets the bounding box to the empty box, so the positionning gets ugly when I include the graph in a nested tikzpicture... I'll try to create MWE with nested
    – tobiasBora
    Aug 13 '18 at 13:05
  • @BambOo : this question is really interesting, and for now it's the best solution I have so far (and it also solve the problem of compilation time). The only issue is that I need to create one file for each nested picture, and that I can't refer to nodes inside the nested tikzpicture with remember option.
    – tobiasBora
    Aug 13 '18 at 14:00
  • 2
    Why didn't anyone comment so far that one should not nest tikzpictures?
    – user121799
    Aug 13 '18 at 16:37
6

With the xsavebox package you can save the tikzpicture in a xlrbox, and scale it when using:

\documentclass[a4paper]{article}

\usepackage{tikz}
\usepackage{xsavebox}

\begin{xlrbox}{mybox}
\begin{tikzpicture}[
    qubit/.style={draw, circle, color=black, anchor=center,
      fill={rgb,255:red,143;green,146;blue,237},
      inner sep=0pt,minimum width=5mm}
    ]
  \node[qubit] (q1) at (0,0){};
  \draw[red,-stealth] (q1.center) -- (q1.north);
\end{tikzpicture}%
\end{xlrbox}

\begin{document}
Not scaled: \themybox

Scaled: \scalebox{0.5}{\themybox}
\end{document}

This also solves the nesting of tikzpictures.

enter image description here

EDIT (by marmot who is happy to take the blame for all errors;-): You should never nest tikzpictures. You can work with scopes, which you can assign name with the local bounding box trick, these scopes will then behave pretty much like nodes (as far as the remembering and placing stuff relative to them is concerned). Clearly, inside the scope you can work with all overlays in the usual way. The perhaps easiest way to go is to load the arrows.meta library and downscale the arrow. (\pgflowlevelsynccm does not work here in a straightforward way because of the additional translations, otherwise it scales the arrow automatically to the right size, but this command should anyway be used with great care.)

\documentclass{beamer}
\usepackage{tikz}
\usetikzlibrary{calc,positioning,arrows.meta}

\begin{document}


\begin{frame}
Scale + transform shape, good position, bad arrow size:\\
\begin{tikzpicture}
  \node[circle,draw,fill=green] (A) {A};
  \node[circle,draw,fill=green,right=of A] (B) {B};
  \node[circle,draw,fill=green,above=of A] (C) {C};
  \coordinate[above=of B.center] (X);

    \begin{scope}[shift={($(X)+(-1,0)$)},
    transform shape,scale=0.5, 
      qubit/.style={draw, circle, color=black, anchor=center,
        fill={rgb,255:red,143;green,146;blue,237},
        inner sep=0pt,minimum width=5mm},local bounding box=graph]
      \node[qubit] (q1) at (0,0){};
      \node[qubit,right=of q1] (q2) {};
      \draw[-] (q1) -- (q2);
      \node<2>[qubit,above=of q2] (q2bis) {};
      \draw[red,-{Stealth[scale=0.5]}] (q1.center) -- (q1.north);
    \end{scope}
    % comparison
    \draw[red,-stealth] ([xshift=2mm,yshift=-1cm]q1.center) -- ([xshift=2mm]q1.north);
  \node[fill=green,inner sep=0pt,minimum size=3pt] at (graph.north east) {};
  \node[fill=red,inner sep=0pt,minimum size=3pt] at (graph.north west) {};
  \node[fill=yellow,inner sep=0pt,minimum size=3pt] at (graph.south east) {};
  \node[fill=orange,inner sep=0pt,minimum size=3pt] at (graph.south west) {};
\end{tikzpicture}
\end{frame}

\end{document}
7
  • Thank you for the trick, which is a great solution in "fixed" pictures (so you get a +1), but as far as I know it does not handle beamer overlays, which is a big issue in my case.
    – tobiasBora
    Aug 13 '18 at 13:57
  • @tobiasBora What exactly does/doesn't it do that you would expect otherwise?
    – Max
    Aug 13 '18 at 14:01
  • I uploaded a MWE that shows that this solution cannot use beamer overlays like \node<2>[qubit,above=of q4] (q5) {};, or \only<2>{...}.
    – tobiasBora
    Aug 13 '18 at 14:03
  • 1
    @tobiasBora Ah so you want nested tikzpictures to comply to beamer overlays. That's a different story entirely.
    – Max
    Aug 13 '18 at 14:06
  • 1
    @Max I added something with a scope and local bounding box, please feel free to roll that back.
    – user121799
    Aug 13 '18 at 17:24
4

Arrowheads are scaled by the line width (more or less), which is not scaled. Mostly because very thin lines are hard to see.

\documentclass[varwidth]{standalone}

\usepackage{tikz}

\begin{document}
Not scaled:
\begin{tikzpicture}[
    qubit/.style={draw, circle, color=black, anchor=center,
      fill={rgb,255:red,143;green,146;blue,237},
      inner sep=0pt,minimum width=5mm},
      line width=\pgflinewidth % default value
    ]
  \node[qubit] (q1) at (0,0){};
  \draw[red,-stealth] (q1.center) -- (q1.north);
\end{tikzpicture}


Scaled:
\begin{tikzpicture}[scale=.5, every node/.style={scale=.5},
    qubit/.style={draw, circle, color=black, anchor=center,
      fill={rgb,255:red,143;green,146;blue,237},
      inner sep=0pt,minimum width=5mm},
      line width=0.5\pgflinewidth
    ]
  \node[qubit] (q1) at (0,0){};
  \draw[red,-stealth] (q1.center) -- (q1.north);
\end{tikzpicture}
\end{document}

demo


Defaults:

\pgfdeclarearrow{
  name = Stealth,
  defaults = {
    length  = +3pt 4.5 .8,
    width'  = +0pt .75,
    inset'  = +0pt 0.325,
    line width = +0pt 1 1,
  },
1
  • Thanks for the \pgflinewidth trick. Do you know what is the default value for arrow length, so that I can use -{Stealth[width=...,height=...]} to have perfect scale?
    – tobiasBora
    Aug 13 '18 at 15:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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