在 Beamer 中外部化 pgfplots/gnuplots——计算每张幻灯片的轮廓

在 Beamer 中外部化 pgfplots/gnuplots——计算每张幻灯片的轮廓

我正在尝试将 外化pgfplotsgnuplot并将contour gnuplot内化beamer。为此,我正在使用visible on=<>的功能\usetikzlibrary{overlay-beamer-styles}(参见这个答案按用户丹尼尔)以及自动编号解决方案来自用户循环空间

我创建了一个由 3 个框架组成的 MWE,每个框架包含 3 张幻灯片,其中包含(A)原始 pgfplots(B)gnuplots(C)轮廓 gnuplots。

预期行为:当外部化时,比如说第二帧的图像,其他帧上的图像应该被忽略。

实际行为:在每个叠加层中都会计算轮廓图。总共计算了 81 组轮廓图。如果删除前 2 帧(不包含轮廓图),则仍会计算 27 组轮廓图。

如何修复此错误?

\documentclass{beamer}
\usepackage{tikz, pgfplots}
\pgfplotsset{compat=1.16}
\usepgfplotslibrary{external}
\usetikzlibrary{overlay-beamer-styles}

% automatic beamer numbering
%\url{https://tex.stackexchange.com/q/119428/86}
\makeatletter
\newcommand*{\overlaynumber}{\number\beamer@slideinframe}
\tikzset{
  beamer externalizing/.style={%
    execute at end picture={%
      \tikzifexternalizing{%
        \ifbeamer@anotherslide
        \pgfexternalstorecommand{\string\global\string\beamer@anotherslidetrue}%
        \fi
      }{}%
    }%
  },
  external/optimize=false
}
\let\orig@tikzsetnextfilename=\tikzsetnextfilename
\renewcommand\tikzsetnextfilename[1]{\orig@tikzsetnextfilename{#1-\overlaynumber}}
\makeatother

\tikzset{every picture/.style={beamer externalizing}}
\tikzexternalize[only named=true]


\begin{document}
\begin{frame}{pgfplots}
\tikzsetnextfilename{pgfplots}
\begin{tikzpicture}
\begin{axis}
\addplot[visible on=<1-3>] {x};
\addplot[visible on=<2-3>] {exp(x)};
\addplot[visible on=<3-3>] {x*x};
\end{axis}
\end{tikzpicture}
\end{frame}

\begin{frame}{gnuplot}
\tikzsetnextfilename{gnuplot}
\begin{tikzpicture}
\begin{axis}
\addplot[visible on=<1-3>] gnuplot{x};
\addplot[visible on=<2-3>] gnuplot{exp(x)};
\addplot[visible on=<3-3>] gnuplot{x*x};
\end{axis}
\end{tikzpicture}
\end{frame}

\begin{frame}{gnuplot contour}
\tikzsetnextfilename{contour}
\begin{tikzpicture}
\begin{axis}[view={0}{90}, domain=-2:2]
  \addplot3[visible on=<1-3>,contour gnuplot={draw color=red,number=20, labels=false}] {x};
  \addplot3[visible on=<2-3>,contour gnuplot={draw color=blue,number=20, labels=false}] {y};
  \addplot3[visible on=<3-3>,contour gnuplot={draw color=black,number=20, labels=false}] {x^2+y^2};
\end{axis}
\end{tikzpicture}
\end{frame}
\end{document}

答案1

消除这些额外轮廓图的最简单方法是使用\only而不是visible on=<>键。这样,图表只会在指定的幻灯片上生成(使用visible on=<>,它们会在所有幻灯片上生成,但只会显示在选定的幻灯片上)。

\begin{axis}[view={0}{90}, domain=-2:2]
  \addplot3[visible on=<1-3>,contour gnuplot={draw color=red,number=20, labels=false}] {x};
  \only<2-3>{\addplot3[contour gnuplot={draw color=blue,number=20, labels=false}] {y};}
  \only<3>{\addplot3[contour gnuplot={draw color=black,number=20, labels=false}] {x^2+y^2};}
\end{axis}

去除在外部化框架时生成的轮廓图,在其他框架上绘制图比较棘手,但可行。我在另一个问题中添加了此问题的解决方案 (看这里)。

下面是一个完整的 MWE,它结合了两种解决方案,只生成 10 个contourmpX.table文件并且编译速度更快。

\documentclass{beamer}
\usepackage{tikz, pgfplots}
\pgfplotsset{compat=1.16}
\usepgfplotslibrary{external}
\usetikzlibrary{overlay-beamer-styles}

% automatic beamer numbering
%\url{https://tex.stackexchange.com/q/119428/86}
\makeatletter
    \newcommand*{\overlaynumber}{\number\beamer@slideinframe}
    \tikzset{
      beamer externalizing/.style={%
        execute at end picture={%
          \tikzifexternalizing{%
            \ifbeamer@anotherslide
            \pgfexternalstorecommand{\string\global\string\beamer@anotherslidetrue}%
            \fi
          }{}%
        }%
      },
      every picture/.style={beamer externalizing}
    }
    
    % remove the `-\overlaynumber` suffix from the jobname
    % the name is stored in `\job@no@suffix` and the number in `\job@suffix@number`
    \def\strip@suffix#1{%
        \begingroup%
        \edef\@tempa{#1-}%
        \expandafter\endgroup%
        \expandafter\@strip@suffix\@tempa\relax%
    }
    \def\@strip@suffix#1-#2\relax{%
        \ifx\relax#2\relax%
            \edef\job@suffix@number{#1}%
            \def\next{\relax}%
        \else%
            \expandafter\ifx\expandafter\relax\job@no@suffix\relax%
                \def\job@no@suffix{#1}%
            \else%
                \edef\job@no@suffix{\job@no@suffix-#1}%
            \fi%
            \def\next{\@strip@suffix#2\relax}%
        \fi%
        \next%
    }
    % check if the next tikzpicture is the to-be-externalized one
    % or has the same basename and precedes it
    \def\if@is@current@pic#1{%
        \begingroup%
        \def\job@no@suffix{}%
        \strip@suffix\pgfactualjobname%
        \ifnum\job@suffix@number<\overlaynumber\relax%
            \def\job@no@suffix{}%
        \fi%
        \edef\current@pic@basename{#1}%
        \edef\current@pic@basename{%
            \expandafter\detokenize\expandafter{\current@pic@basename}%
        }%
        \ifx\job@no@suffix\current@pic@basename%
            \expandafter\endgroup\expandafter\@firstoftwo%
        \else%
            \expandafter\endgroup\expandafter\@secondoftwo%
        \fi%
    }
    
    % add a `-\overlaynumber` suffix to the next tikzpicture name
    % and disable tikz external optimization where needed
    \let\orig@tikzsetnextfilename=\tikzsetnextfilename
    \renewcommand\tikzsetnextfilename[1]{%
        \orig@tikzsetnextfilename{#1-\overlaynumber}%
        \tikzifexternalizing{
            \if@is@current@pic{\tikzexternal@filenameprefix#1}{%
                \tikzset{external/optimize=false}%
            }{%
                \tikzset{external/optimize=true}%
            }%
        }{}%
    }
\makeatother

\tikzexternalize[only named=true]

\begin{document}
\begin{frame}{pgfplots}
\tikzsetnextfilename{pgfplots}
\begin{tikzpicture}
\begin{axis}
\addplot[visible on=<1-3>] {x};
\addplot[visible on=<2-3>] {exp(x)};
\addplot[visible on=<3-3>] {x*x};
\end{axis}
\end{tikzpicture}
\end{frame}

\begin{frame}{gnuplot}
\tikzsetnextfilename{gnuplot}
\begin{tikzpicture}
\begin{axis}
\addplot[visible on=<1-3>] gnuplot{x};
\addplot[visible on=<2-3>] gnuplot{exp(x)};
\addplot[visible on=<3-3>] gnuplot{x*x};
\end{axis}
\end{tikzpicture}
\end{frame}

\begin{frame}{gnuplot contour}
\tikzsetnextfilename{contour}
\begin{tikzpicture}
\begin{axis}[view={0}{90}, domain=-2:2]
  \addplot3[visible on=<1-3>,contour gnuplot={draw color=red,number=20, labels=false}] {x};
  \only<2-3>{\addplot3[contour gnuplot={draw color=blue,number=20, labels=false}] {y};}
  \only<3>{\addplot3[contour gnuplot={draw color=black,number=20, labels=false}] {x^2+y^2};}
\end{axis}
\end{tikzpicture}
\end{frame}
\end{document}

相关内容