我遇到了一些奇怪的问题,tikzexternalize 有时会工作,有时不工作。我把问题缩小到 fixltx2e。这是一个 MWNE(最小不工作示例)
@ ALtermundus:是的,这是你的照片(不使用它实在是太好了 ;-)
\documentclass{article}
\usepackage{fixltx2e}
\usepackage{pgf}
\usepackage{tikz}
\usepackage{pgfplots}
\usetikzlibrary{calc}
\usetikzlibrary{external}
\tikzexternalize
\newcommand{\fancypicture}{
% from http://altermundus.com/pages/tikz/tikz-examples/index.html
\path (0,0) coordinate (A)
(-60:12cm) coordinate (B)
(240:12cm) coordinate (C);
\foreach \density in {10,20,...,160}
\draw[fill=blue!\density]
(A) coordinate (X) -- (B) coordinate[pos=.15] (A) --
(C) coordinate[pos=.15] (B) --
(X) coordinate[pos=.15] (C);
}
\begin{document}
\begin{figure}[ht] %[!b!h!t]
\centering
\begin{tikzpicture}
\fancypicture
\end{tikzpicture}
\end{figure}
\begin{figure}[ht] %[!b!h!t]
\centering
\begin{tikzpicture}
\fancypicture
\end{tikzpicture}
\end{figure}
\begin{figure}[ht] %[!b!h!t]
\centering
\begin{tikzpicture}
\fancypicture
\end{tikzpicture}
\end{figure}
\begin{figure}[ht] %[!b!h!t]
\centering
\begin{tikzpicture}
\fancypicture
\end{tikzpicture}
\end{figure}
\end{document}
上述代码的奇怪之处在于:如果只插入两张图片,一切正常。只有绘制更多图片时,我怀疑这会触发 fixltx2e 中的某些修复,导致外部化失败。由于这很难追踪,我只是想知道 tikzexternalize 或 fixltx2e 是否还有更多这样的微妙之处。
答案1
问题似乎在于,fixltx2e
重新定义的\@doclearpage
方式不符合externalize
库的要求:输出例程运行而不生成任何页面,编译停止。我猜,当只有两个图形时不会发生这种情况,因为它们适合放在一页上。
我认为除了不加载之外没有什么其他事情可做fixltx2e
。
答案2
更新:此问题现已在 PGF CVS 中修复,请参阅下面 Christian Feuersänger 的评论。
当 TikZ/PGF 进入外部化模式时,它仍会处理整个文档。它需要这样做以确保在处理当前正在处理的图片时处于正确的“状态”(即任何宏或样式或其他内容都与普通文档中一样)。这意味着它仍会经历构建页面和对浮动进行排序的过程,只是在最后一刻将其全部丢弃。
它确实做了一些优化。 里面的任何东西\includegraphics
都可以安全地丢弃。 任何不是正在处理的 tikz 图片也是如此。
然而,这有一个意想不到的副作用。它会丢弃命令\includegraphics
或tikzpicture
环境,但不会丢弃包含浮动元素(这是合理的,因为浮动元素可以包含图片以外的内容)。但是,如果浮动元素做过仅包含图片,那么它现在是一个高度为零的框。当 LaTeX 尝试构建一个完全由这些丢弃的图形组成的浮动页面时(请记住,这些图形可能是其他 tikz 图片),这会导致问题。正如 TikZ 为每一个除了正在外部化的图形之外,这种情况很容易发生。
由此导致的问题是,生成的浮动页面的高度也很可能为零。这是一个问题,因为 LaTeX 会测试浮动页面的高度是否不为零,以检查其是否正确制作。如果浮动页面的高度为零,则假设它以某种方式失败了,并且必须将所有浮动元素推到下一个浮动页面上。但如果浮动元素本身的高度为零,我们就永远无法摆脱这个循环。
之所以fixltx2e
这样做很明显,是因为它添加了一个循环来确保所有浮点数都被正确处理(之前,如果这个失败了,它只会丢失那些浮点数 - 我想,我不是这方面的专家)。
这表明有多种选择:
- 禁用循环
\@doclearpage
。这是线路\ifx\@deferlist\@empty \else\clearpage \fi
。 - 禁用 tikz 外部化库中的优化步骤。这意味着将选项放在
\tikzset{external/optimize=false}
你的序言中。这可能是最安全但可能使外化步骤变得更慢。 允许零高度浮动页面。这涉及重新定义测试,如下所示:
\def\@ytryfc #1{% \begingroup \gdef\@flsucceed{\@elt #1}% \global\let\@flfail\@empty \@tempdima\ht #1% \let\@elt\@ztryfc \@trylist \ifdim \@tempdima <\@fpmin \@cons\@failedlist #1% \else \global\@fcolmadetrue \fi \endgroup \if@fcolmade \let\@elt\@gobble \fi}
修复 TikZ/PGF 优化,
tikzpicture
以便它创建一个非零高度的框。(我试过这个,但想不出能保证有效的方法。)- 在每个外部浮动之后添加
\newpage
。这意味着它最终不会生成浮动页面。这有点极端,但您可以将其放入\tikzifexternalizing
以确保它只在外部化运行中发生。
现在,我仅建议在外部化运行中对 Deep Core 进行更改。幸运的是,TikZ 提供了命令,因此如果您不想丢失优化,\tikzifexternalizing
请将重新定义放入其中(用 包围所有内容)。\makeatletter ... \makeatother