q(t) = (4.9/ (w^2))*(cosh(w*t)-cos(w*t))
我正在尝试绘制参数的几个值的函数w
。也就是说,我想绘制q
vs的整个图形t
,在其中插入w=1
、w=2
、w=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}
我希望能够用它做的是
- 绘制参数的几个值
w
(大概 20 个),而无需为每个值输入单独的\draw
或\addplot
行。 - 为每个不同的图添加略微不同的颜色,并添加图例,让读者根据颜色大致了解每个图的参数值。
- (仅限 TikZ 图)使用范围而不是函数的定义域,以便每个图看起来大致相同——我尝试用
domain=-1:1
say替换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 进行处理。输出: