使用迭代语法来减少代码量:

使用迭代语法来减少代码量:

q(t) = (4.9/ (w^2))*(cosh(w*t)-cos(w*t))我正在尝试绘制参数的几个值的函数w。也就是说,我想绘制qvs的整个图形t,在其中插入w=1w=2w=100或其他任何值,以查看绘图如何随着参数的更改而变化。

这是一个使用 TikZ 的最小工作示例:

\documentclass{minimal}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}
\draw[thick,->] (-2,0) -- (2,0) node[right]{$t$};
\draw[thick,->] (0,0) -- (0,5) node[above]{$q$};
\draw[blue,domain=-1:1] plot (\x,{(2.45/(3^2))*(exp(3*\x)+exp(-3*    \x)-2*cos(3*\x))});
\draw[violet,domain=-1.3:1.3] plot (\x,{(2.45/(1^2))*(exp(1*\x)+exp(-1*\x)-2*cos(1*\x))});
\draw[red,domain=-1.4:1.4] plot (\x,{(2.45/(0.1^2))*(exp(0.1*\x)+exp(-0.1*\x)-2*cos(0.1*\x))});
\end{tikzpicture}
\end{document}

下面是使用 PGFplots 的示例:

\documentclass{minimal}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture} 
\begin{axis}[xmin=-5,xmax=5,ymin=-0.5,ymax=100,no markers, grid=both]
\addplot {(2.45/(0.1^2))*(exp(0.1*x)+exp(-0.1*x)-2*cos(0.1*x))};
\addplot {(2.45/(0.5^2))*(exp(0.5*x)+exp(-0.5*x)-2*cos(0.5*x))};
\addplot {(2.45/(1^2))*(exp(1*x)+exp(-1*x)-2*cos(1*x))};
\end{axis}
\end{tikzpicture}
\end{document}

在此处输入图片描述

我希望能够用它做的是

  1. 绘制参数的几个值w(大概 20 个),而无需为每个值输入单独的\draw\addplot行。
  2. 为每个不同的图添加略微不同的颜色,并添加图例,让读者根据颜色大致了解每个图的参数值。
  3. (仅限 TikZ 图)使用范围而不是函数的定义域,以便每个图看起来大致相同——我尝试用domain=-1:1say替换range=0:5,但没有效果。

我没有太多使用 LaTeX 制作图表的经验,但我更喜欢使用或来回答,TikZ因为pgfplots我之前至少使用过它们几次。

答案1

我怀疑这是想要的结果?较大的值\w将导致函数崩溃,并返回错误消息。

在此处输入图片描述

\documentclass{standalone}
\usepackage{pgfplots}

\def\mycolone{yellow}
\def\mycoltwo{green}

\pgfplotsset{every axis legend/.append style={
at={(.5,-.2)},
anchor=north}} 

\begin{document}
\begin{tikzpicture} 
\begin{axis}[xmin=-5,xmax=5,ymin=-0.5,ymax=100,no markers, grid=both]
\foreach \w in {5,10,...,100} {
\edef\tmp{\noexpand\addplot[\mycolone!\w!\mycoltwo]}
\pgfmathparse{\w/100}
\edef\x{\pgfmathresult}
\tmp{(4.9/((\w/100)^2))*(cosh(\w*x/100)-cos(\w*x/100))};
\edef\legendentry{\noexpand\addlegendentry{$\omega =
\noexpand\pgfmathprintnumber[fixed,fixed zerofill, precision=2]{\x}$}};
       \legendentry
}
\end{axis}
\end{tikzpicture}
\end{document}

答案2

首先,我要感谢你提出这个问题;我是 LaTeX 的基本用户,通过思考你的问题,我学到了很多东西。以下是代码和我对你的问题的解决方案;

在此处输入图片描述

% pdflatex
\documentclass{standalone}
    \usepackage{siunitx}
    \sisetup{round-mode=places,round-precision=1}
    %
    \usepackage{tikz}
    \usepackage{pgfplots}
    %
    \def\colora{red}
    \def\colorb{green}
\begin{document}
\begin{tikzpicture}
       \pgfmathdeclarefunction{q}{2}{\pgfmathparse{(4.9/(#1^2))*(cosh(#1*#2)-cos(#1*#2)}}
\begin{axis}
        [
    axis lines = center,
    grid=both,minor tick num=1,
    xlabel=$t$,ylabel=$q$,
    tick align=inside,
    every axis y label/.style={rotate=0, black, at={(0.5,1.05)},},
    every axis x label/.style={rotate=0, black, at={(1.05,0)},},
    %
    legend style={at={(0.65,1.0)},
    anchor=north west,legend columns=1},
    %
    domain=-5:5,
    smooth,
        ]
    \foreach \w in {0.10,0.20,...,0.5} {
    \pgfmathparse{200*\w}
    \xdef\x{\pgfmathresult}
    %
    \edef\tempa{\noexpand\addlegendentry{\num{\w}}}\tempa
    \edef\tempb{\noexpand\addplot [\colora!\x!\colorb]}\tempb{q(\w,x)};
    }
\end{axis}
\end{tikzpicture}
\end{document}

我已经在线定义了该函数

   \pgfmathdeclarefunction{q}{2}{\pgfmathparse{(4.9/(#1^2))*(cosh(#1*#2)-cos(#1*#2)}}

\addplot但是,人们可能不会像上面那样定义他的函数,而只是在代码中的语法前面键入它。这里没有区别。我想提到的一点是,你将部分函数引入为cos(w*t)。请确保变量在函数中应该如何。它应该是度数还是弧度?通过检查问题中 MWE 输出的图的值;我可以看到您没有使用度数函数。但是,如果您必须以度数引入变量,请将该部分更改为cos(deg(#1*#2))。您的图表略有变化。

使用迭代语法来减少代码量:

为了方便绘制多个图,避免代码太长,我尝试使用迭代语法\foreach。此部分由生成图例、绘制图和关注图颜色的部分组成。在以下行中

\foreach \w in {0.10,0.20,...,0.5} {

w您可以在函数中引入所需的值。我选择的值是0.1, 0.2, 0.3, 0.4和,0.5但您可以随意选择。只需引入迭代的下限、步骤和上限。如您所见,有在 pgfplots 循环中使用 \addlegendentry 时出现问题。我尝试了一种临时技术来解决这一部分,但如果你检查这个答案中的替代代码,你会发现至少对于图例来说,没有必要使用这种临时技术。

该组图的颜色各异:

为了改变图表的颜色,我使用了这个答案。如果您不这样做,pgfplots 也会为您的图表选择漂亮的颜色;只需替换以下语法并查看结果。

\edef\tempb{\noexpand\addplot +[mark=none]}\tempb{q(\w,x)};

在此处输入图片描述

迭代中的图例和绘图语法问题:

由于您想要迭代绘图,因此您应该将图例和绘图部分放在迭代语法中。这会导致许多我们应该考虑的问题,其中一部分已在上一部分中描述。我将指出这个问题以及我遇到的浮点数的其他问题,并一起回答所有这些问题。数字浮点作为图例的一部分存在一些问题;如果不注意这一点,图例的输出会非常丑陋。

在此处输入图片描述

出现此类问题的原因如下一个答案这个问题。但是,你问题中的情节的解决方案不同。有很多不同的解决方案来解决这个问题。我选择使用sinitx包裹因为对于我这个基础用户来说,使用它更容易。本文部分讨论了这一点问题回答

@JosephWright 在聊天室中提议

您需要在 \w 上使用打印功能,而不仅仅是插入 \w,例如;(关联

\foreach \w in {0.1,0.2,...,1} {
    \pgfmathparse{100*\w}
    \edef\x{\pgfmathresult}
    \edef\temp{\noexpand\addplot [\colora!\x!\colorb]}\temp{q(\w,x)};
    \edef\temp{\noexpand\addlegendentry{\noexpand\pgfmathprintnumber{\w}}}\temp
}

或者你可以强制 \w 采取“正确”的值,当然我可能会强制 1 为 1.0 并稍微整理一下(关联

\foreach \w in {0.1,0.2,...,1} {
    \pgfmathparse{round(\w)}
    \pgfmathparse{100*\w}
    \edef\x{\pgfmathresult}
    \edef\temp{\noexpand\addplot [\colora!\x!\colorb]}\temp{q(\w,x)};
    \pgfkeys{/pgf/number format/.cd, fixed, precision = 1, zerofill}
    \pgfmathprintnumberto{\w}{\temp}
    \addlegendentryexpanded{\temp}
}

他还提出了一些其他方法,例如(关联) 和 (关联)绘制函数:

% pdflatex
\documentclass{standalone}
\usepackage{expl3}
\usepackage{pgfplots}
\ExplSyntaxOn
\cs_new_eq:NN \fpeval \fp_eval:n
\ExplSyntaxOff

\begin{document}
\begin{tikzpicture}
       \pgfmathdeclarefunction{q}{2}{\pgfmathparse{(4.9/(#1^2))*(cosh(#1*#2)-cos(#1*#2)}}
\begin{axis}
    \foreach \w in {10,20,...,100} {
      \edef\temp{\noexpand\addplot [red!\w]}\temp{q((\w/100),x)};
      \addlegendentryexpanded{\fpeval{\w/100}}
    }
\end{axis}
\end{tikzpicture}
\end{document}

在此处输入图片描述

如你所见,这两个解决方案都由expl3 包和 LaTeX3 编程

% pdflatex
\documentclass{standalone}
\usepackage{expl3}
\usepackage{pgfplots}
\ExplSyntaxOn
\cs_new_eq:NN \fpeval \fp_eval:n
\ExplSyntaxOff

\begin{document}
\begin{tikzpicture}
       \pgfmathdeclarefunction{q}{2}{\pgfmathparse{(4.9/(#1^2))*(cosh(#1*#2)-cos(#1*#2)}}
\begin{axis}
    \foreach \w in {0.1,0.2,...,1.0} {
      \edef\temp{\noexpand\addplot [red!\fpeval{100 * \w}]}\temp{q(\w,x)};
      \addlegendentryexpanded{\fpeval{round(\w,1)}}
    }
\end{axis}
\end{tikzpicture}
\end{document}

如果我们想要引入图例和addplot语法,我们会面临很多问题。您可以选择以何种方式处理浮点、迭代和图例问题。如果您可以访问所需的包,请按照我的解决方案操作。如果没有,请尝试其他解决方案。

答案3

MetaPost 解决方案,这是一项非常有趣的练习,深受“1010011010”的答案的启发。

我已经为这项任务使用了两个自己的宏。简单调用的一个宏function允许输入函数表达式作为参数(如其定义),并返回其相关曲线。该define_cartouche宏生成一个包含图例的椭圆形框。

为了保证数值准确性,计算采用浮点数(double数字系统)进行。Metafun 格式提供了余弦和双曲余弦函数。

至于热心学生提出的舍入问题,这里已经使用该numprint包进行了解决。

\documentclass[border=2mm]{standalone}
\usepackage[autolanguage]{numprint}
  \nprounddigits{1}
\usepackage{luamplib}
  \mplibsetformat{metafun}
  \mplibtextextlabel{enable}
  \mplibnumbersystem{double}
\begin{document}
  \begin{mplibcode}
    def define_cartouche(text cartouche)(expr pos) = 
      picture cartouche; cartouche = nullpicture;
      numeric _cnt; _cnt = 0;
      def addto_cartouche (suffix cartouche)(expr wd, str, curve_color) =
        addto cartouche also (image(draw pos - (wd,0) -- pos withcolor curve_color; 
          label.rt(str, pos) withcolor black;)
            yshifted -_cnt*\mpdim{1.1\baselineskip});
        _cnt := _cnt + 1;
      enddef;
    enddef;

    vardef function(expr xmin, xmax, xstep)(text f_x) =
      save x; x := xmin;
      (x, f_x) forever: hide(x := x + xstep) exitif x > xmax; .. (x, f_x) endfor
      if x - xstep < xmax: hide(x := xmax) .. (x, f_x) fi
    enddef;

    numeric u, v, xmin, xmax, xstep; 
    u = cm; v = .1cm;
    xmax = -xmin = 4.9; ymin = 0; ymax = 100; xstep := 0.01;

    vardef thefunction(expr w) =
      function(xmin, xmax, xstep)((4.9/(w**2)) * (cosh(w*x)-cos(w*x)))
    enddef;

    beginfig(1);
      define_cartouche(cartouche)(origin); % Cartouche initialization
      % Grid
      for i = ceiling(xmin) step 2 until floor(xmax):
        if i<>0: draw (i*u, ymin*v) -- (i*u, ymax*v) withcolor .8white;
          label.bot("$" & decimal i & "$", (i*u, 0)); fi
      endfor
      for j = ceiling(ymin) step 20 until floor(ymax):
        if j<>0: draw (xmin*u, j*v) -- (xmax*u, j*v) withcolor .8white; 
        label.llft("$" & decimal j & "$", (0, j*v)); fi
      endfor
      % Curves (and clipping)
      color curve_color;
      picture curves; curves = image(
        for w = 0.1 step 0.1 until 2.05:
          curve_color := ((w-.1)/1.9)[blue,red];
          draw thefunction(w) xyscaled (u, v) withcolor curve_color;
          addto_cartouche(cartouche)(.5cm, 
            "$\omega=\numprint{" & decimal w & "}$", curve_color);
        endfor);
      clip curves to 
        ((xmin, ymin) -- (xmax, ymin) -- (xmax, ymax) -- (xmin, ymax) -- cycle)
          xyscaled (u, v);
      draw curves;
      % Axes and cartouche
      drawarrow (xmin*u, 0) -- (xmax*u, 0); 
      drawarrow (0, ymin*v) -- (0, ymax*v);
      label.bot("$O$", origin);
      draw cartouche shifted ((xmax+1)*u, (ymax-5)*v);
    endfig;
  \end{mplibcode}
\end{document}

使用 LuaLaTeX 进行处理。输出:

在此处输入图片描述

相关内容