我的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 来扩大队列中浮点数的最大数量。
您也可以对表格使用相同的宏。