edit:
I believe the TikZ key external/mode=graphics if exists
does exactly what you want. (See the TikZ/PGF Manual v2.10 Section 32.4.4, page 349.) Try the following for your example:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{external}
\tikzexternalize
\tikzset{external/mode=graphics if exists}
\begin{document}
\def\mypic#1{
\begin{tikzpicture}\clip (-1,-1) rectangle (1,2);
\draw[red] plot (\x,{#1});
\end{tikzpicture}
}
\mypic{(\x)^2}
\begin{tikzpicture}\clip (-1,-1) rectangle (1,2);
\draw[red] plot (\x,{\x*\x*\x});
\end{tikzpicture}
\end{document}
original answer:
If you know that the external graphics has a particular extension (as seems to be given in your case) you can use \IfFileExists{<file>}{}{}
, e.g.
\documentclass{article}
\usepackage{tikz}
\begin{document}
\IfFileExists{./logo.pdf}{%
\includegraphics{logo}
}{%
\begin{tikzpicture}
\draw (0,0) rectangle (1,1);
\end{tikzpicture}
}
\end{document}
Ok, I've found a workaround for this. As this has been bothering me for a long time and also includes some other issues to consider, I'll answer this step by step.
Task: Create a tikzpicture consisting of an external graphics (.png,.jpg,.pdf) that will not result in an error when used with tikzscale
and \tikzexternalize
.
Questions: Why a tikzpicture
and not just \includegraphics
?
-Because I want to add some elements to the picture, which is easy to do in tikz
.
Why using tikzscale
?
-Because I like to have my figures to have the same width as the text while keeping the fontsize
of axes, nodes etc. independent of the figure's width. tikzscale
is the tool for this.
Why \tikzexternalize
?
-Not using \tikzexternalize
means that every tikzpicture
is recompiled every time, the document is compiled. Depending on the tikzpicture
's complexity, this will take a lot of time.
The first approach:
The first approach can be seen in the original question. I placed a node
in a tikzpicture
and filled it with \includegraphics
. This results in an error. The document is produced correctly, but the tikzpicture
is not externalized i.e. saved in a separate .pdf.
The second approach:
In some earlier work I learned that pgfplots
' \addplot graphics
actually works with tikzscale
and \tikzexternalize
. The idea is now to put the exterael graphic in the axis
environment and to hide the axes, ticks and labels. Let's assume we want a tikzpicture
containing the following graphics (example-image-16x10.jpg included in the mwe
package):
The code then reads as follows (the tikzpicture is written in a separate file test.tikz
to load it with tikzscale
's \includegraphics
). note the ticks=none
and axis lines=none
options to hide the axes, ticks and labels:
\documentclass[10pt]{scrartcl}
\usepackage[english]{babel}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{external}
\tikzexternalize[shell escape=-enable-write18]
\usepackage{tikzscale}
\usepackage{pgfplots}
\usepackage{mwe}
\usepackage{filecontents}
\pgfplotsset{compat=1.10}
\begin{document}
\begin{filecontents}{test.tikz}
\begin{tikzpicture}
\begin{axis}[
xmin=0,xmax=1,ymin=0,ymax=1,
ticks=none,
axis lines=none,
]
\addplot graphics [xmin=0,xmax=1,ymin=0,ymax=1] {example-image-16x10};
\end{axis}
\end{tikzpicture}
\end{filecontents}
First we will include the picture as a normal graphics:
\begin{figure}[hb]
\centering
\includegraphics[width=0.5\textwidth]{example-image-16x10}
\caption{This is the figure without using \textit{tikzpicture}.}
\end{figure}
\newline Next, we include the figure as a \textit{tikzpicture} using \textit{tikzscale}.
\begin{figure}
\centering
\includegraphics[width=0.5\textwidth]{test.tikz}
\caption{This is my figure in \textit{tikzpicture}'s \textit{axis} environment. Unfortunaltely it is stretched into a square shape.}
\end{figure}
\end{document}
When one compiles this code (twice), one will note, that the graphics in the tikzpicture
is streched vertically, as pgfplots
' axis
environment tends to crate square shaped plots. To keep the original image's aspect ratio, one has to define a new \addplot
command that will measure the original image's aspect ratio and scale the axes accordingly as demonstrated in an earlier question \addplot graphics: maintaining image's aspect ratio despite different scaling of axes.
The final code is then:
\documentclass[10pt]{scrartcl}
\usepackage[english]{babel}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{external}
\tikzexternalize[shell escape=-enable-write18]
\usepackage{tikzscale}
\usepackage{pgfplots}
\usepackage{mwe}
\usepackage{filecontents}
\pgfplotsset{compat=1.10}
\makeatletter
\newcommand\addplotgraphicsnatural[2][]{%
\begingroup
\pgfqkeys{/pgfplots/plot graphics}{#1}%
\setbox0=\hbox{\includegraphics{#2}}%
\pgfmathparse{\wd0/(\pgfkeysvalueof{/pgfplots/plot graphics/xmax} - \pgfkeysvalueof{/pgfplots/plot graphics/xmin})}%
\let\xunit=\pgfmathresult
\pgfmathparse{\ht0/(\pgfkeysvalueof{/pgfplots/plot graphics/ymax} - \pgfkeysvalueof{/pgfplots/plot graphics/ymin})}%
\let\yunit=\pgfmathresult
\xdef\marshal{%
\noexpand\pgfplotsset{unit vector ratio={\xunit\space \yunit}}%
}%
\endgroup
\marshal
\addplot graphics[#1] {#2};
}
\makeatother
\begin{document}
\begin{filecontents}{test.tikz}
\begin{tikzpicture}
\begin{axis}[
xmin=0,xmax=1,ymin=0,ymax=1,
ticks=none,
axis lines=none,
]
\addplotgraphicsnatural [xmin=0,xmax=1,ymin=0,ymax=1] {example-image-16x10};
\end{axis}
\end{tikzpicture}
\end{filecontents}
First we will include the picture as a normal graphics:
\begin{figure}[hb]
\centering
\includegraphics[width=0.5\textwidth]{example-image-16x10}
\caption{This is the figure without using \textit{tikzpicture}.}
\end{figure}
\newline Next, we include the figure as a \textit{tikzpicture} using \textit{tikzscale}.
\begin{figure}
\centering
\includegraphics[width=0.5\textwidth]{test.tikz}
\caption{This is my figure in \textit{tikzpicture}'s \textit{axis} environment. Unfortunaltely it is stretched into a square shape.}
\end{figure}
\end{document}
This will produce the desired document as well as the externalized figure. I don't know whether there is a more elegant way to do this, but it works.
Best Answer
I hope I fully understood what you requested. Here goes.
\tikzexternalize
accepts aprefix
parameter which tellspdflatex
where to store the externalised graphics. So even if you use\input
inmain.tex
to include exercises withtikzpicture
s, you can setprefix=<something>
inmain.tex
to letpdflatex
know that externalised graphics should be stored in that directory – specifically, you want them in the directory of the exercise. You can also separate the code from the processing by saving the externalised graphics in a sub-directory where all exercises of a chapter are stored. Here I useexternal
as the directory.There is a caveat, however: if your main file is not always named
main.tex
, then theexternal
library will re-externalise graphics with a new filename (I believe the format is\jobname-figureX
whereX
is a running counter starting from 0. This is not what you want; you want to avoid re-externalisation. Thankfully, this issue can be easily circumvented by lettingpdflatex
know what the externalised graphic should be named using\tikzsetnextfilename
:This means that if this exercise is
\input
in a filemain.tex
and a filefile.tex
compiled withpdflatex -shell-escape
, the external library will only create the figure ifex1fig1.pdf
does not exist (or if something has changed in thetikzpicture
environment etc.)With all that in mind, your main
.tex
file would look like this:main.tex
Where
firstexercise.tex
is stored inaclass/achapter/exercises/
.firstexercise.tex
:If you want to include only externalised graphics instead of the whole
firstexercise.tex
, all you need to do is to set thegraphicspath
inmain.tex
to the\externaldirectory
, like so:\graphicspath{ {\externaldirectory} }
. Thereafter, you simply use\includegraphics
with the figure filename, like so:I hope this makes at least some sense and that it is in fact what you requested.