6

I have a graph that works by itself and I have to scale this graph inside my document (see code below). I got inspired for this from this post (Scale tikz figure to a percentage of \textwidth) that works on a much simpler drawing (which I assume works for that reason only, but seems not to generalize well to more complex forms).

I would like to scale this conveniently like any other figure (pdf, png) that load from disk, but i am getting the error message:

Package tikzscale Error: Requested to scale unscalable graphic.

Since I am using this graph many times in document, is it possible to wrap this also in a command?

Here the code:

\usepackage{tikz}
\usetikzlibrary{arrows}
\usepackage{tikz}
\usepackage{tikzscale}
\usepackage{filecontents}

\begin{document}

\begin{filecontents*}{test.tikz}
\begin{tikzpicture}[->,>=stealth',shorten >=1pt,auto,node distance=3cm,
  thick,main node/.style={circle,fill=black,draw=none,text=white,font=\LARGE\bfseries}]

    % nodes
    \node[main node] (A) {L1};
    \node[main node] (B) [below left of=A] {L2};
    \node[main node] (C) [below right of=A] {L3};
    \node[main node] (D) [below right of=B] {L4};
    \node[main node] (E) [right of=C] {L5};
    \node[main node] (F) [above of=E] {L6};

    % lines
    \path[every node/.style={font=\sffamily\large}]
       (A) edge [bend right] node [right] {0.0} (B)
       (B) edge [loop left] node {0.0} (B)
           edge [bend right] node [right] {0.0} (D)
           edge [bend right] node[below] {0.0} (C)
       (C) edge [bend right] node [left] {0.0} (A)
           edge [bend right] node [below] {0.0} (B)
           edge [bend left] node [left] {0.0} (D)
           edge [right] node [below] {0.0} (E)
       (D) edge [loop below] node {0.0} (D);
\end{tikzpicture}
\end{filecontents*}

\begin{figure}[htb]
    \centering
    \includegraphics[width=0.2\textwidth]{test.tikz}
    \caption{This figure has standard width}
\end{figure}
\begin{figure}[htb]
    \centering
    \includegraphics[width=0.4\textwidth]{test.tikz}
    \caption{This figure has double width}
\end{figure}

\end{document} 
8

Scaling with tikzscale (line widths, fonts are not scaled)

Package tikzscale adds option scale to scale the picture to the requested size. But if the option is set and the graphics has the same size as before, it throws the error message, that the graphics is not resizable.

You can also test this by adding scale=2. If the picture has the same size as the default value of 1, then you are out of luck and have to redesign the picture to make it scalable.

The following example hacks into \pgftransformscale to store the scale factor in a global macro \ScaleFactor. This factor is then used to scale the node distance:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{arrows}
\usetikzlibrary{bending}% nicer bended arrow heads.
\usetikzlibrary{calc}
\usepackage{tikzscale}
\usepackage{filecontents}

\let\OrgPgfTransformScale\pgftransformscale
\renewcommand*{\pgftransformscale}[1]{%
  \gdef\ScaleFactor{#1}%
  \OrgPgfTransformScale{#1}%
}
\def\ScaleFactor{1}

\begin{document}

\begin{filecontents*}{test.tikz}
\begin{tikzpicture}[
  ->,
  >=stealth',
  shorten >=1pt,
  auto,
  node distance=3cm*\ScaleFactor,
  thick,
  main node/.style={
    circle,
    fill=black,
    draw=none,
    text=white,
    font=\LARGE\bfseries
  }
]
    \typeout{* Scale factor: \ScaleFactor}

    % nodes
    \node[main node] (A) {L1};
    \node[main node] (B) [below left of=A] {L2};
    \node[main node] (C) [below right of=A] {L3};
    \node[main node] (D) [below right of=B] {L4};
    \node[main node] (E) [right of=C] {L5};
    \node[main node] (F) [above of=E] {L6};

    % lines
    \path[every node/.style={font=\sffamily\large}]
       (A) edge [bend right] node [right] {0.0} (B)
       (B) edge [loop left] node {0.0} (B)
           edge [bend right] node [right] {0.0} (D)
           edge [bend right] node[below] {0.0} (C)
       (C) edge [bend right] node [left] {0.0} (A)
           edge [bend right] node [below] {0.0} (B)
           edge [bend left] node [left] {0.0} (D)
           edge [right] node [below] {0.0} (E)
       (D) edge [loop below] node {0.0} (D);
\end{tikzpicture}
\end{filecontents*}

\begin{figure} 
    \centering
    \includegraphics[width=\textwidth]{test.tikz}
    \caption{This figure has standard width}
\end{figure}
\begin{figure}
    \centering
    \includegraphics[width=0.75\textwidth]{test.tikz}
    \caption{This figure has double width}
\end{figure}

\end{document}

Result

The last scale factors of the \typeout message:

First image: 1.3079
Second image: 0.88972

The \ScaleFactor can also be used to decrease the font size, e.g.:

   font=\bfseries
      \ifdim\ScaleFactor pt>0.95pt\LARGE\else 
      \ifdim\ScaleFactor pt>0.9pt\Large\else
      \ifdim\ScaleFactor pt>0.85pt\large\else
      \ifdim\ScaleFactor pt>0.8pt\normalsize\else
        \small
      \fi\fi\fi\fi,

Then the result with

\begin{figure}
    \centering
    \includegraphics[width=0.6\textwidth]{test.tikz}
    \caption{This figure has double width}
\end{figure}

as second image is:

Result smaller font

Scaling via \resizebox (everything is scaled)

If you want to scale the whole picture the same way, \includegraphics would scale a normal image, that means also the line widths, fonts, ... are scaled, then \resizebox helps:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{arrows}
\usepackage{tikz}
\usepackage{filecontents}

\begin{document}

\begin{filecontents*}{test.tikz}
\begin{tikzpicture}[->,>=stealth',shorten >=1pt,auto,node distance=3cm,
  thick,main
node/.style={circle,fill=black,draw=none,text=white,font=\LARGE\bfseries}]

    % nodes
    \node[main node] (A) {L1};
    \node[main node] (B) [below left of=A] {L2};
    \node[main node] (C) [below right of=A] {L3};
    \node[main node] (D) [below right of=B] {L4};
    \node[main node] (E) [right of=C] {L5};
    \node[main node] (F) [above of=E] {L6};

    % lines
    \path[every node/.style={font=\sffamily\large}]
       (A) edge [bend right] node [right] {0.0} (B)
       (B) edge [loop left] node {0.0} (B)
           edge [bend right] node [right] {0.0} (D)
           edge [bend right] node[below] {0.0} (C)
       (C) edge [bend right] node [left] {0.0} (A)
           edge [bend right] node [below] {0.0} (B)
           edge [bend left] node [left] {0.0} (D)
           edge [right] node [below] {0.0} (E)
       (D) edge [loop below] node {0.0} (D);
\end{tikzpicture}
\end{filecontents*}

\begin{figure}[htb]
    \centering
    \resizebox{.2\textwidth}{!}{\input{test.tikz}\unskip}
    \caption{This figure has standard width}
\end{figure}
\begin{figure}[htb]
    \centering
    \resizebox{.4\textwidth}{!}{\input{test.tikz}\unskip}
    \caption{This figure has double width}
\end{figure}

\end{document}

Result of \resizebox scaling

Remarks:

  • The \unskip after \input{test.tikz} removes the space by the line end of the last line with \end{tikzpicture}.
| improve this answer | |
  • Perhaps a dump question: Is there a solution or package that simply scales every object in tikz diagram equally without explicitly declaring it ? This would, if I am not mistaken, have the same effect as if a pixel version of the diagram would be scaled... or not? – RalfB Jun 11 '15 at 15:56
  • @user2377039 See section "Scaling via \resizebox". – Heiko Oberdiek Jun 11 '15 at 16:01
1
\begin{frame}
    \frametitle{Ranking on the Web}
    \framesubtitle{PageRank Example}
    \centering
    \resizebox{.5\textwidth}{!}{\MyExample}
\end{frame}

where MyExample is the tikzpicture...

The solution was much easier than expected, all i want it to scale everything equally and the tip from Heiko Oberdiek helped me to find it somewhere. Thanks!

| improve this answer | |

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.