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.

There are many questions on this web site and elsewhere about ensuring that floats are displayed in the order in which they are placed in the source. What I want is different—I have all my floats at the end of my document and want to ensure that floats are displayed in the order in which they are referenced using \ref or \autoref. Using something like the endfloat package is not sufficient, because that requires me to make sure that the source order of the floats is the same as the reference order. It is easy to disrupt this ordering during editing.

It would suffice to have some sort of process that checked this for me automatically and required manual adjustments. Just as long as I don't have to go through and manually check again that Figure 13 is referenced in the output text before Figure 14.

share|improve this question
add comment

1 Answer

up vote 7 down vote accepted

Commenting out the \figuresatendtrue the paper will compile as normally (with figures in place). Otherwise, they will go at the end in order of references.

\documentclass{article}
\usepackage{environ,etoolbox}
\usepackage{lipsum}
\usepackage{hyperref}

\newif\iffiguresatend
\figuresatendtrue

\makeatletter
\iffiguresatend

\NewEnviron{figureatend}[2][\fps@figure]{%
  % #1 = placement options
  % #2 = key
  \global\expandafter\def\csname figureatend@store@#2\expandafter\endcsname
    \expandafter{\BODY\label{#2}}}

\providecommand\@namelet[1]{\expandafter\let\csname#1\endcsname}
\def\figureatend@save{}
\def\figureatend@ref#1{%
    \g@addto@macro\figureatend@save{\figureatend@do{#1}}}
\def\figureatend@do#1{%
   \@ifundefined{figureatend@store@#1}{}{%
     \begin{figure}[p]\@nameuse{figureatend@store@#1}\end{figure}%
     \global\@namelet{figureatend@store@#1}\relax}}
\AtEndDocument{
  \ifx\figureatend@save\@empty\else
    \clearpage
    \figureatend@save
  \fi}

\pretocmd\@setref{\figureatend@ref{#3}}{}{}

\else

\newenvironment{figureatend}[2][\fps@figure]
  {\def\figureatendtemp{#2}\begin{figure}[#1]}
  {\label{\figureatendtemp}\end{figure}}

\fi


\begin{document}

\section{abc}\label{abc}

\ref{abc}--\ref{AAA}\lipsum[1] 

\begin{figureatend}{BBB}
\caption{Figure BBB}
\end{figureatend}

\begin{figureatend}{AAA}
\caption{Figure AAA}
\end{figureatend}

\ref{BBB}\ref{AAA}\autoref{AAA}

\end{document}

Comments

The idea is to gather both the code for the figures and the references. Each command \ref{label} (and also \autoref{label} if hyperref is loaded) will update the internal variable \figureatend@save by adding \figureatend@do{label} to it. At the end we will execute this macro, see later.

Each figureatend environment takes as optional argument the usual positioning specifications; they will be ignored if we are in "endfigures" mode, but are handy for printing the document with figures in place. The mandatory argument is the label with which the figure will be referred to that mustn't be placed after \caption, contrary to the usual format. (It would be quite difficult to intercept a \label command in this environment and a label is necessary anyway.)

The contents of the environment becomes, in endfigures mode, the replacement text of the macro \figureatend@store@label, where label is the argument to the environment.

At the end of the run (with \AtEndDocument) we check whether the \figureatend@save macro is non empty and we execute it, that is we do

\figureatend@do{label}

for each label found during the LaTeX run (in the exact order of appearance). The macro \figureatend@do{label} just check if \figureatend@store@label is defined and, if so, it does

\begin{figure}[p]
<contents of the figureatend environment labeled by label> \label{label}\end{figure}

if the macro is defined; otherwise it does nothing.

A couple of LaTeX runs are required, as usual.

If the \figuresatend line is commented out, the figureatend environment becomes just a figure environment and nothing is added to the \ref related macro \@setref.

share|improve this answer
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.