如何让图形准确出现在第16页?

如何让图形准确出现在第16页?

我的MWE

\documentclass[twoside]{book}%

% 2 Packages only for demonstration purposes:
\usepackage{tikzducks}% Delivers figures for testing purposes
\usepackage{lipsum}% Delivers blind text


\begin{document}
%\pushfiguretopage{16}% Push figure to page 16
\begin{figure}[b]% 
    \begin{center}
        \includegraphics[width=0.5\textwidth]{example-image-duck}
    \end{center}
    \caption{A duck}
\end{figure}
\lipsum
\lipsum
\lipsum
\lipsum
\lipsum
\lipsum
\lipsum
\lipsum
\lipsum
\lipsum
\lipsum
\lipsum
    
\end{document}

我希望现在出现在第 1 页的图形准确出现在第 16 页。我可以使用非浮动环境来实现这一点 —— 但只有在我不改变图形之前的文本的情况下才有效。或者我可以使用 \afterpage 来实现这一点 —— 但这样我就必须使用 \afterpage 16 次,而过去我遇到了一些脚注问题...

\pushfiguretopage{16}是否还有另一种可能性,即我在 MWE 中所说的宏?

答案1

这使用\AddToHook(标准 LaTeX)重置totalnumber计数器。请注意,这不会影响[!]浮点数,但它们必须保持顺序。还请注意,\pushfiguretopage在当前计数器完成之前,您无法重复使用(第 16 页)。

\documentclass[twoside]{book}%

% 2 Packages only for demonstration purposes:
\usepackage{tikzducks}% Delivers figures for testing purposes
\usepackage{lipsum}% Delivers blind text

\newcounter{pushtopage}

\makeatletter
\newcommand{\pushfiguretopage}[1]{% #1 = page number
  \setcounter{pushtopage}{#1}%
  \addtocounter{pushtopage}{-1}% activate on previous page
  \setcounter{totalnumber}{0}% turn off all floats
  \global\@colnum=\c@totalnumber% this page too
  \AddToHook{shipout/after}[myhookid]{\ifnum\value{page}=\value{pushtopage}\relax
    \setcounter{totalnumber}{3}% default
    \RemoveFromHook{shipout/after}[myhookid]%
  \fi}}
\makeatother

\begin{document}
\pushfiguretopage{16}% Push figure to page 16

\begin{figure}[b]% will not work if [!].
    \begin{center}
        \includegraphics[width=0.5\textwidth]{example-image-duck}
    \end{center}
    \caption{A duck}
\end{figure}


\lipsum[1-100]
    
\end{document}

此版本使用屏障浮点数,即太大而无法打印的浮点数(除了\clearpage)。它只是从队列中移除,以便允许打印下一个浮点数。

这不会检查移除的浮点数是否实际上是屏障浮点数,尽管它可以(\ht\@id>\textheight)。

\documentclass[twoside]{book}%

% 2 Packages only for demonstration purposes:
\usepackage{tikzducks}% Delivers figures for testing purposes
\usepackage{lipsum}% Delivers blind text

\newcounter{pushtopage}

\makeatletter
\newcommand{\pushfiguretopage}[1]{% #1 = page number
  \begin{figure}[ht]% create barrier float
    \rule{1.2\linewidth}{1.2\textheight}
  \end{figure}
  \setcounter{pushtopage}{#1}%
  \addtocounter{pushtopage}{-1}% activate on previous page
  \AddToHook{shipout/after}[myhookid]{\ifnum\value{page}=\value{pushtopage}\relax
    \@next\@id\@deferlist{}{}% remove next float from queue
    \@cons\@freelist\@id
    \RemoveFromHook{shipout/after}[myhookid]%
  \fi}}
\makeatother

\begin{document}
\pushfiguretopage{16}% Push figure to page 16

\begin{figure}[b]% will not work if [!].
    \begin{center}
        \includegraphics[width=0.5\textwidth]{example-image-duck}
    \end{center}
    \caption{A duck}
\end{figure}

\lipsum[1-100]
    
\end{document}

答案2

当我尝试使用我自己的答案中的算法时,它并不总是完全可靠地工作,但有时会将图推到第 17 页。因此,我尝试增强 John Kormylo 的答案,以便可以在 \pushfiguretopage 之前放置尽可能多的图,而无需到达第 16 页。为此,在 \pushfiguretopage 内部,在所有其他图的末尾发出一个“不可见图”,其标签通过 Johns 钩子将 totalnumber 减少到 0。

\documentclass[twoside]{book}%
\RequirePackage{zref-abspage,zref-user}% Needed for zlabel{}

% 2 Packages only for demonstration purposes:
\usepackage{tikzducks}% Delivers figures for testing purposes
\usepackage{lipsum}% Delivers blind text

\newcounter{pushtopage}

\makeatletter
\newcommand{\pushfiguretopage}[1]{% #1 = page number
    \setcounter{pushtopage}{#1}%
    \addtocounter{pushtopage}{-1}% activate on previous page

    % Invisible figure
    \setlength\textfloatsep{0pt}% no distance between text and float
    \begin{figure}[!htb]%
        \zlabel{testfloat}% This will be the last figure before ours
        % for more than one figure we need unique labels here
    \end{figure}%
    \AddToHook{shipout/after}[myhookid]{%
        \ifnum\value{page}=\zref@extractdefault{testfloat}{abspage}{-1}%
            \setcounter{totalnumber}{0}%
        \fi%
        \ifnum\value{page}=\value{pushtopage}\relax
        \setcounter{totalnumber}{3}% default
        \RemoveFromHook{shipout/after}[myhookid]%
        \fi}}
\makeatother

\begin{document}
    \begin{figure}[b]% will not work if [!].
        \begin{center}
            \includegraphics[width=0.5\textwidth]{example-image-duck}
        \end{center}
        \caption{A duck}
    \end{figure}
    \begin{figure}[b]% will not work if [!].
        \begin{center}
            \includegraphics[width=0.5\textwidth]{example-image-duck}
        \end{center}
        \caption{A duck}
    \end{figure}
    \begin{figure}[b]% will not work if [!].
        \begin{center}
            \includegraphics[width=0.5\textwidth]{example-image-duck}
        \end{center}
        \caption{A duck}
    \end{figure}
    \begin{figure}[b]% will not work if [!].
        \begin{center}
            \includegraphics[width=0.5\textwidth]{example-image-duck}
        \end{center}
        \caption{A duck}
    \end{figure}

    \pushfiguretopage{16}% Push following figure to page 16
    \begin{figure}[b]% will not work if [!].
        \begin{center}
            \includegraphics[width=0.5\textwidth]{example-image-duck}
        \end{center}
        \caption{This one should be placed at page 16}
    \end{figure}
    
    
    \lipsum[1-100]
    
\end{document}

现在,控制页面上浮点总数的计数器 totalnumber 不再从一开始设置为 0,而是仅在打印所有其他图形末尾的“不可见图形”时才设置为 0。因此,如果您现在将 \pushfiguretopage{} 放在要推送的图形之前,则之前的所有其他图形都会正常打印。

答案3

我的 MWE:

\documentclass[twoside]{book}%
\RequirePackage{refcount}% For \getpagerefnumber{}
%\RequirePackage[maxfloats=256]{morefloats}% For not getting the error "too many unprocessed floats"
%\maxdeadcycles=200%


% 2 Packages only for demonstration purposes:
\usepackage{tikzducks}% Delivers figures for testing purposes
\usepackage{lipsum}% Delivers blind text


\newcount\invisiblefloat%
\invisiblefloat=0
\newcount\safety%
\safety=0

\makeatletter%
\def\pushfloattopage#1#2{% #1: page to reach
    \setlength\textfloatsep{0pt}% no distance between text and float makes empty float unvisible    
    \loop\ifnum\safety<40%
        \advance\invisiblefloat by 1\relax
        \ifnum\numexpr#1-1\relax < \getpagerefnumber{invisiblefloat\number\invisiblefloat}%
            \let\iterate\relax
        \fi
        \begin{@float}{#2}[b]% No \caption, so \counter{figure} is not increased
            \label{invisiblefloat\number\invisiblefloat}% test label: where are we?
        \end{@float}%
        \advance\safety by 1\relax
    \repeat
}% End \pushfloattopage
\makeatother    
    

\begin{document}
\pushfloattopage{16}{figure}% Push figure to page 16
\begin{figure}[!b]% Place it there, even if the float placement restrictions are not allowing it, as there is already the invisible float
    \begin{center}
        \includegraphics[width=0.5\textwidth]{example-image-duck}
    \end{center}
    \caption{A duck}
\end{figure}
\lipsum
\lipsum
\lipsum
\lipsum
\lipsum
\lipsum
\lipsum
\lipsum
\lipsum
\lipsum
\lipsum
\lipsum
    
\end{document}

\pushfloattopage通过用“隐形图形”(或表格)填充页面来推动图形(或表格)向前,直到到达要放置图形的页面(第 16 页)。这些“隐形图形”不会增加图形计数器,因为它们没有标题。

如果你想将数字向前推进过多页数,可能会出现问题。那么你应该将计数器的最大数字\safety从 40 扩大到更多,也许计数器\maxdeadcycles也应该扩大。

在这种情况下以及当您想要多次使用此技巧时,您可能需要使用包 morefloats 来扩大队列中浮点数的最大数量。

您也可以对表格使用相同的宏。

相关内容