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.

I need to scale Tikz pictures automatically, and I do this using the following custom environment:

% Automagically scale a Tikz picture, so it has the desired (given) width.
% Does NOT scale line width/text width! Needs the package "environ"!
%
% Usage:
%
% \begin{myscaletikzwidth}{\textwidth}
%   \begin{tikzpicture}[scale=\tikzscale]
%     ..
%   \end{tikzpicture}
% \end{myscaletikzwidth}
%
\makeatletter
\newsavebox{\measure@tikzpicture}
\NewEnviron{myscaletikzwidth}[1]{%
  \def\tikz@width{#1}%
  \def\tikzscale{1}\begin{lrbox}{\measure@tikzpicture}%
  \BODY
  \end{lrbox}%
  \pgfmathparse{#1/\wd\measure@tikzpicture}%
  \edef\tikzscale{\pgfmathresult}%
  \BODY
}
\makeatother

(I got that code from another topic on Stackexchange.)

This code works perfectly fine, however it doesn't work anymore, when I turn on externalization (graphics will then be created in their original size).

How can I make auto-scaling work in conjunction with externalization?

I am using the modern externalization approach that has been introduced with newer Tikz versions ("\tikzexternalize").

Maybe some hack with writing "\def\tikzscale{MyDeterminedScaleFactor}" to an external file and inputting that file afterwards?

Could you please help me with that?

share|improve this question
add comment

1 Answer 1

up vote 6 down vote accepted

The problem is that the external library will automatically assign names for each encountered tikzpicture - but in your case, you effectively have one name and two pictures.

One could think about a solution which assigns individual file names for each of the two involved pictures - but that is a waste of time because you are never interested in the first one.

So, I propose the following solution: we check if we are currently generating an external picture. If so, we will always typeset the first (which is necessary to determine the picture's size) and we will externalize the second one. If we are currently NOT exporting the (current) picture, we can safely assume that there is an external picture ready at hand - and use it.

Here is the modification. It requires that \usetikzlibrary{external} has been loaded (although it does not necessarily need to be active).

% Automagically scale a Tikz picture, so it has the desired (given) width.
% Does NOT scale line width/text width! Needs the package "environ"!
%
% Usage:
%
% \begin{myscaletikzwidth}{\textwidth}
%   \begin{tikzpicture}[scale=\tikzscale]
%     ..
%   \end{tikzpicture}
% \end{myscaletikzwidth}
%
\makeatletter
\newsavebox{\measure@tikzpicture}
\NewEnviron{myscaletikzwidth}[1]{%
  \tikzifexternalizingnext{%
      \def\tikz@width{#1}%
      \def\tikzscale{1}\begin{lrbox}{\measure@tikzpicture}%
      \tikzset{external/export next=false,external/optimize=false}% force translation of this BODY (and do not optimize it away as it would usually do):
      \BODY
      \end{lrbox}%
      \pgfmathparse{#1/\wd\measure@tikzpicture}%
      \edef\tikzscale{\pgfmathresult}%
      \BODY
  }{% this will re-use an existing external graphics:
    \BODY
  }%
}
\makeatother

EDIT: You are right, there are problems with the todonotes package. It is (unfortunately) incompatible with the tikz external image. Apparently,

\usepackage{todonotes}
\makeatletter
\renewcommand{\todo}[2][]{%
   \tikzexternaldisable\@todo[#1]{#2}\tikzexternalenable%
}
\makeatother

helps here.

share|improve this answer
    
Thanks for your quick help! Your code works fine when everything is kept in a single file. However, my setup was slightly more complicated: - Code split across many files - I used "todonotes" (which uses Tikz), and I did not want that graphics to be externalized - I used "\tikzsetnextfilename{...}" on my images - Tikz pictures are stored in seperate files (each starting with "\begin{tikzpicture}...") Doesn't sound too difficult, but there were a few hours of that typical LaTeX-pain-in-the-ass-fun, until everything worked. Thanks for your answer, it helped me a lot on that way! –  kopierkatze Sep 21 '11 at 23:42
1  
I edited my answer to show some work-around for todonotes (which is, indeed, incompatible with image externalization). –  Christian Feuersänger Sep 23 '11 at 19:28
    
@kopierkatze, a similar approach is uses in the tikzscale package (also proposed by Christian), which simplifies your code from a user perspective. –  Patrick Häcker Oct 31 '12 at 14:40
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.