如何使用循环来改进基于 TikZ/pgfplots 的动画?

如何使用循环来改进基于 TikZ/pgfplots 的动画?

我创建了一个简单的动画来说明我的代码如何线性化一个函数。我使用 TikZ 和 pgfplots 创建了动画。由于我对这两个软件包都很陌生,所以我肯定没有使用所有的功能。我想听听大家对我如何使用循环功能来改进这个动画的反馈。

我目前的实现是这样的:

\documentclass{beamer}
\usepackage{tikz}
\usepackage{pgfplots}

\pgfplotsset{compat=newest}

\begin{document}

\begin{frame}[fragile]{Frame title}
  \begin{tikzpicture}
      \begin{axis}[
        ticks = none,
        axis x line = bottom,
        axis y line = left,
        xmin = 0.0,
        ymin = 0.0,
        ymax = 4.0,
      ]
      \addplot[ black, samples=200] {1/sqrt(x)};

      \only<2->{\addplot[only marks, color=black,fill=white,samples at={0.10}]{1/sqrt(x)}; node 1}
      \only<2->{\addplot[only marks, color=black,fill=white,samples at={4.0}]{1/sqrt(x)};}
      \only<3>{\draw[thick, dashed, color=red] (0.10, 1/sqrt{0.10}) -- (4.0, 1/sqrt{4.0});}

      \only<4->{\addplot[only marks, color=black,fill=white,samples at={1.95}]{1/sqrt(x)};}
      \only<4->{\draw[thick, dashed, color=red] (1.95, 1/sqrt{1.95}) -- (4.0, 1/sqrt{4.0});}
      \only<4>{\draw[thick, dashed, color=red] (0.10, 1/sqrt{0.10}) -- (1.95, 1/sqrt{1.95});}

      \only<5->{\addplot[only marks, color=black,fill=white,samples at={0.925}]{1/sqrt(x)};}
      \only<5->{\draw[thick, dashed, color=red] (0.925, 1/sqrt{0.925}) -- (1.95, 1/sqrt{1.95});}
      \only<5>{\draw[thick, dashed, color=red] (0.10, 1/sqrt{0.10}) -- (0.925, 1/sqrt{0.925});}

      \only<6->{\addplot[only marks, color=black,fill=white,samples at={0.4125}]{1/sqrt(x)};}
      \only<6->{\draw[thick, dashed, color=red] (0.4125, 1/sqrt{0.4125}) -- (0.925, 1/sqrt{0.925});}
      \only<6>{\draw[thick, dashed, color=red] (0.10, 1/sqrt{0.10}) -- (0.4125, 1/sqrt{0.4125});}

      \only<7>{\addplot[only marks, color=black,fill=white,samples at={0.15625}]{1/sqrt(x)};}
      \only<7>{\draw[thick, dashed, color=red] (0.15625, 1/sqrt{0.15625}) -- (0.4125, 1/sqrt{0.4125});}
      \only<7>{\draw[thick, dashed, color=red] (0.10, 1/sqrt{0.10}) -- (0.15625, 1/sqrt{0.15625});}

      \end{axis}
  \end{tikzpicture}
\end{frame}
\end{document}

我确信有更好的方法可以做到这一点。我知道如何在代码中执行此操作以获取实际数据,但我不确定在 TikZ/pgfplots 中执行此操作的咒语。如何?我感兴趣的几件事:

  1. 我如何存储该函数以便每次我想要计算一个点时不必重复它?
  2. 我如何使用循环来自动化这个?(这里有太多重复的代码。)
  3. 我可以不使用投影仪来做到这一点吗?

我在这里使用的算法是,给定一个函数(本例中为 1/sqrt(x))和该曲线上的两个点。在这两点之间画一条直线。如果该直线与曲线的近似值很差:

  1. 在两个原始点的中间选取一点。
  2. 从中点到端点之间画线。
  3. 对每一组新点重复此操作,直到线性近似“足够好”。

现在,我并不真正关心如何确定“足够好”,这比这个动画所需的还要多。我真的只想迭代一定次数(在本例中为 5 次),因为这样至少在视觉上可以达到目的。

答案1

事实上,它可以被简化。

\documentclass{beamer}
\usepackage{tikz}
\usepackage{pgfplots}

\pgfplotsset{compat=newest}
\tikzset{declare function={myf(\x)=1/sqrt(\x);}}
\begin{document}

\begin{frame}[fragile]{Frame title}
  \begin{tikzpicture}
      \begin{axis}[
        ticks = none,
        axis x line = bottom,
        axis y line = left,
        xmin = 0,
        ymin = 0.0,
        ymax = 4.0,
      ]
      \addplot[ black, samples=200,domain=0.1:4] {myf(x)};
      \xdef\Lst{(4,{myf(4)}) }
      \only<1>{
      \addplot[thick,dashed, color=red] coordinates {\Lst (0.1,{myf(0.1)}) };
      \addplot[only marks,mark=o,clip=false] coordinates {\Lst (0.1,{myf(0.1)}) };
      }
      \foreach \X in {2,3,4}
      {
      \xdef\Lst{\Lst  ({8*pow(2,-\X)},{myf(8*pow(2,-\X))}) }
      \only<\X>{
      \addplot[thick,dashed, color=red,] coordinates {\Lst (0.1,{myf(0.1)})};
      \addplot[only marks,mark=o,clip=false] coordinates {\Lst (0.1,{myf(0.1)}) };
      }
      }
      \end{axis}
  \end{tikzpicture}
\end{frame}
\end{document}

在此处输入图片描述

使用@percusse 的建议并真正将函数绘制为 4,输出几乎相同:

\documentclass{beamer}
\usepackage{tikz}
\usepackage{pgfplots}

\pgfplotsset{compat=newest}
\tikzset{declare function={myf(\x)=1/sqrt(\x);}}
\begin{document}

\begin{frame}[fragile]{Frame title}
  \begin{tikzpicture}
      \begin{axis}[
        ticks = none,
        axis x line = bottom,
        axis y line = left,
        xmin = 0,
        ymin = 0.0,
        ymax = 4.0,
      ]
      \addplot[ black, samples=200,domain={1/16}:4] {myf(x)};
      \xdef\Lst{4}
      \only<1>{
      \addplot[thick,dashed, color=red,samples at={\Lst,0.0625}] {myf(x)};
      \addplot[only marks,mark=o,clip=false,samples at={\Lst,0.0625}] {myf(x)};
      }
      \foreach \X [evaluate={\Y=1/16+2*(4-1/16)*pow(2,-\X)}] in {2,3,4}
      {
      \xdef\Lst{\Lst,\Y}
      \only<\X>{
        \addplot[thick,dashed, color=red,samples at={\Lst,0.0625}] {myf(x)};
        \addplot[only marks,mark=o,clip=false,samples at={\Lst,0.0625}] {myf(x)};
      }
      }
      \end{axis}
  \end{tikzpicture}
\end{frame}
\end{document}

在此处输入图片描述

答案2

在对括号和圆括号进行了一些修改之后,我将你的 mwe 修改为这样

(但我知道这并没有回答 OP 关于执行循环的问题:它只显示了如何让原始 MWE 编译时没有错误)

\documentclass{beamer}
\usepackage{tikz}
\usepackage{pgfplots}

\pgfplotsset{compat=newest}

\begin{document}

\begin{frame}[fragile]{Frame title}
  \begin{tikzpicture}
      \begin{axis}[
        ticks = none,
        axis x line = bottom,
        axis y line = left,
        xmin = 0.0,
        ymin = 0.0,
        ymax = 4.0,
      ]
      \addplot[ black, samples=200] {1/sqrt(x)};

      \only<2->{\addplot[only marks, color=black,fill=white,samples at={0.10}]{1/sqrt(x)};}
      \only<2->{\addplot[only marks, color=black,fill=white,samples at={4.0}]{1/sqrt(x)};}
      \only<3>{\draw[thick, dashed, color=red] (0.10, {1/sqrt(0.10)}) -- (4.0, {1/sqrt(4.0)});}

      \only<4->{\addplot[only marks, color=black,fill=white,samples at={1.95}]{1/sqrt(x)};}
      \only<4->{\draw[thick, dashed, color=red] (1.95, {1/sqrt(1.95)}) -- (4.0, {1/sqrt(4.0)});}
      \only<4>{\draw[thick, dashed, color=red] (0.10, {1/sqrt(0.10)}) -- (1.95, {1/sqrt(1.95)});}

      \only<5->{\addplot[only marks, color=black,fill=white,samples at={0.925}]{1/sqrt(x)};}
      \only<5->{\draw[thick, dashed, color=red] (0.925, {1/sqrt(0.925)}) -- (1.95, {1/sqrt(1.95)});}
      \only<5>{\draw[thick, dashed, color=red] (0.10, {1/sqrt(0.10)}) -- (0.925, {1/sqrt(0.925)});}

      \only<6->{\addplot[only marks, color=black,fill=white,samples at={0.4125}]{1/sqrt(x)};}
      \only<6->{\draw[thick, dashed, color=red] (0.4125, {1/sqrt(0.4125)}) -- (0.925, {1/sqrt(0.925)});}
      \only<6>{\draw[thick, dashed, color=red] (0.10, {1/sqrt(0.10)}) -- (0.4125, {1/sqrt(0.4125)});}

      \only<7>{\addplot[only marks, color=black,fill=white,samples at={0.15625}]{1/sqrt(x)};}
      \only<7>{\draw[thick, dashed, color=red] (0.15625, {1/sqrt(0.15625)}) -- (0.4125, {1/sqrt(0.4125)});}
      \only<7>{\draw[thick, dashed, color=red] (0.10, {1/sqrt(0.10)}) -- (0.15625, {1/sqrt(0.15625)});}

      \end{axis}
  \end{tikzpicture}
\end{frame}
\end{document}

并且它有效。(在文章类中编译只有 tikz 代码比使用 beamer 要快得多,我不知道为什么)。

编辑但日志中有数十条溢出警告1/sqrt(0),感谢@marmot 提醒我注意这一点。使用

\addplot[ black, samples=200, domain=0.1:4] {1/sqrt(x)};

正如@marmot 的回答所修复的那样并显著加快处理速度!

以下是注释掉frame、添加\def\only<#1>#2{#2}和使用文章类的内容:

在此处输入图片描述

相关内容