0

I am generating a document (exam, based on exam documentclass) that takes a random set of questions and imports them using input. Each of the questions references a 'source image', e.g., question A references figure F1, B references F2, C references F1. The images can be reused in each of the questions. As the questions are randomly taken from a pool, I have no control over which images will appear. My aim is to avoid repetition of images in the master document, showing the image only once.

\documentclass{article}
\usepackage{graphicx}
\begin{document}
\includegraphics[width=\textwidth]{img1.png}
\includegraphics[width=\textwidth]{img1.png}
\includegraphics[width=\textwidth]{img2.png}
\end{document}

I would like to have this produce a document with

  • img1 and img2 included only once
  • have captions for the images
  • ideally wrap the figures in a figure float
  • ideally push the figures to the end of the document

Before going on a wild goosechase involving convoluted latexcode, I'd thought to check here and see whether I'm missing some simple and default behaviour that can aid me here. Thanks!

p.s.: my initial thought would be to have a command that includes a figure by referencing the name, e.g., "f1". That command could then initialise / increase a counter that i can check before actually producing the figure.

0

2 Answers 2

0

It is a bit non-standard LaTeX code but with \csname ... \endcsname it is easy to "remember" things, and that is a kind of standard technique uses in classes and packages. So here is a solution that uses that technique. It remembers with \csname image:#1\endcsname whether an image is already loaded, and if not, puts it in a figure and creates a label to refer to it. The figures are put in a \AtEndDocument to move them to the end of the document.

\documentclass{article}
\usepackage{graphicx}
\newcommand{\refimage}[1]{%
  \expandafter\ifx\csname image:#1\endcsname\relax %image not yet loaded
  \AtEndDocument{\begin{figure}[bp]
    \includegraphics[width=\textwidth]{#1}
    \caption{Image #1}
    \label{image:#1}
  \end{figure}}
  \expandafter\gdef\csname image:#1\endcsname{image:#1}
  \fi
  \ref{image:#1}
}
\begin{document}
\listoffigures

\section{Introduction}

This section used figure \refimage{example-image-a}.

\subsection{Subsec}

This subsection uses figure \refimage{example-image-a}.

\subsection{Another sub}

This section used figure \refimage{example-image-b}

\end{document}

enter image description here

5
  • Nice Pieter, that provides me with a bit more insight into expandafter and csname. There's still something that is messing up the approach in my case, as I am looping over a 'set of questions' in my code, using foreach. It looks like that macro resets the command somehow, which I do not understand. I have added the foreach loop I use to your MWE: gist.github.com/joachimnielandt/… May 19, 2021 at 8:50
  • As an aside, I was trying myself to get a solution going with a boolean toggle, and I'm encountering the same 'reset behaviour' in the foreach loop: gist.github.com/joachimnielandt/… May 19, 2021 at 9:00
  • Changing the \def into \gdef solves that. I should have done that from the beginning (I had thought of the problem that \def wouldn't work inside groups). I have modified my answer accordingly. May 19, 2021 at 9:23
  • You might also contemplate putting the code that goes into the \AtEndDocument into a separate macro. May 19, 2021 at 9:25
  • Awesome! Thanks Pieter! May 19, 2021 at 9:34
0

Based on Pieter's answers I have cobbled together an alternative solution (although not completely equivalent). It uses a global counter and works in combination with a foreach loop. I included this for future reference, or if anyone else might find this useful.

\documentclass[12pt]{article}

\usepackage{etoolbox}
\usepackage{graphicx}
\usepackage{tikz}
\usepackage{float}

% https://tex.stackexchange.com/questions/279780/on-demand-ad-hoc-counters
\makeatletter
\newcommand{\figurecounter}[1]{%
  \@ifundefined{c@#1}{%
    \newcounter{#1}%
    \global\defcounter{#1}{0}% global counter makes sure it doesn't reset in the foreach loop
  }{%
    \global\stepcounter{#1}%
  }%
}
\makeatother

\newcommand{\inputfigure}[1]{%
    \figurecounter{#1}% bump the counter
    \ifnumcomp{\csname the#1\endcsname}{=}{0}% if the counter has not yet been used, input the figure
    {
        \begin{figure}[H]
            \centering
            \includegraphics[width=0.1\textwidth]{example-image-a}
            \caption{image ``#1''}
            \label{fig:#1}
        \end{figure}    
    }%
    {}%
}

\newcommand*{\questionsets}{%
    setone,%
    settwo%
}%

\begin{document}
    \foreach \questionset in \questionsets {%
        questionset: \questionset \\
        \inputfigure{a}
        \inputfigure{a}
        \inputfigure{b}
        \inputfigure{b}
    }
\end{document}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .