![随着时间的推移弹跳球](https://linux22.com/image/283555/%E9%9A%8F%E7%9D%80%E6%97%B6%E9%97%B4%E7%9A%84%E6%8E%A8%E7%A7%BB%E5%BC%B9%E8%B7%B3%E7%90%83.png)
我有一段笨拙的代码来绘制弹跳球随时间变化的高度。是否有可能进行优化?也许直接使用 tikz 数学库编写函数?此外,目前无法处理负时间输入。具有多个输入参数的宏如何调用 lua 代码?
\documentclass[tikz]{standalone}
\usepackage{fontspec}
\usepackage{pgfplots}
\usepackage{luatextra}
\begin{luacode}
function height(h0, idx)
return h0*(3/4)^(math.abs(idx))
end
function time(h0, idx)
t = math.sqrt(2*height(h0, 0)/9.81)
for i=1,idx,1 do
t = t+2*math.sqrt(2*height(h0, i)/9.81)
end
return t
end
function offset(h0, idx)
o = 0
if idx > 0 then
o = time(h0, idx-1)+(time(h0, idx)-time(h0, idx-1))/2
end
return o
end
\end{luacode}
\makeatletter
\pgfmathdeclarefunction{luaheight}{1}{%
\begingroup
\pgfkeys{/pgf/fpu,/pgf/fpu/output format=sci}%
\pgfmathparse{#1}%
\edef\pgfmathresult{\directlua{tex.print("" .. height(10,\pgfmathresult))}}%
\pgfmathsmuggle\pgfmathresult%
\endgroup
}%
\pgfmathdeclarefunction{luatime}{1}{%
\begingroup
\pgfkeys{/pgf/fpu,/pgf/fpu/output format=sci}%
\pgfmathparse{#1}%
\edef\pgfmathresult{\directlua{tex.print("" .. time(10,\pgfmathresult))}}%
\pgfmathsmuggle\pgfmathresult%
\endgroup
}%
\pgfmathdeclarefunction{luaoffset}{1}{%
\begingroup
\pgfkeys{/pgf/fpu,/pgf/fpu/output format=sci}%
\pgfmathparse{#1}%
\edef\pgfmathresult{\directlua{tex.print("" .. offset(10,\pgfmathresult))}}%
\pgfmathsmuggle\pgfmathresult%
\endgroup
}%
\makeatother
\begin{document}
\begin{tikzpicture}
\begin{axis}
\addplot[domain=0:luatime(0)] {luaheight(0)-9.81/2*x^2};
\foreach \p in {1,...,5} {
\addplot[domain=luatime(\p-1):luatime(\p)] {luaheight(\p)-9.81/2*(x-luaoffset(\p))^2};
}
\end{axis}
\end{tikzpicture}
\end{document}
它看起来像这样:
答案1
经过一番数学运算(关键词是几何级数),我找到了一个计算时间的解析解。现在有一个简洁的解决方案,但它比第一个慢得多。
\documentclass[tikz]{standalone}
\usepackage{fontspec}
\usepackage{pgfplots}
\usepackage{luatextra}
\begin{document}
\begin{tikzpicture}[
declare function={
bounce(\hz,\idx) = \hz*(3/4)^\idx;
duration(\hz,\idx) = sqrt(2*\hz/9.81)*(1+sqrt(3)*(1-sqrt(3/4)^\idx)/(1-sqrt(3/4)));
offset(\hz,\idx) = duration(\hz,\idx-1)+(duration(\hz,\idx)-duration(\hz,\idx-1))/2;
flight(\hz,\idx,\t) = bounce(\hz,\idx)-9.81/2*(\t-offset(\hz,\idx))^2;
}
]
\begin{axis}[
xmin=0, xmax=20,
ymin=0, ymax=12,
thick,
axis lines=left,
xtick={14.047},
%xtick={{duration(10,8)}},
xticklabels={$t_c$},
yticklabels={},
xlabel={Zeit},
ylabel={Höhe},
tick style=transparent,
]
\addplot[red,domain=0:{duration(10,0)}] {bounce(10,0)-9.81/2*\x^2};
\addplot[dashed,gray]coordinates {({duration(10,8)},0) ({duration(10,8)},12)};
\foreach \p in {9,...,20} {
\addplot[domain={duration(10,\p-1)}:{duration(10,\p)}] {flight(10,\p,\x)};
}
\foreach \p in {1,...,8} {
\addplot[red,domain={duration(10,\p-1)}:{duration(10,\p)}] {flight(10,\p,\x)};
}
\addplot[red]coordinates{({duration(10,8)},0) (20,0)};
\end{axis}
\end{tikzpicture}
\end{document}
它看起来像这样:
为什么我不能调用其中声明的函数xtick
?
答案2
使用 PSTricks 只是为了好玩。其余琐碎部分是为了简单起见而故意留下的。
\documentclass[pstricks,border=12pt]{standalone}
\SpecialCoor
\psset{linecolor=red}
\begin{document}
\begin{pspicture}(11,10)
\foreach \i in {0,...,10}{\parabola(\i,0)(!\i\space .5 add 10 .65 \i\space exp mul)}
\end{pspicture}
\end{document}