我想用 绘制一些复杂的函数pgfplots
。问题是绘制确实需要花费很多时间,尤其是一些子函数是重复的(计算多次)。例如
0.165*sin(2*x)-0.128*sin(x+5616/73)
cos(23.44*sin(x))
出现在多个位置上。
有没有什么办法可以优化计算,让绘图更快呢?
感谢您的建议。
\documentclass{minimal}
\usepackage{pgfplots}
\usepackage{filecontents}
\begin{document}
\def\anga{47} % latitude
\begin{tikzpicture}
\begin{axis}
\foreach \i in {-4,-3,...,4}{%
\addplot[domain=0:360,samples=60] ({180+asin(cos(23.44*sin(x))*sin(15*(\i+0.165*sin(2*x)-0.128*sin(x+5616/73)))/sqrt(1-(sin(\anga)*sin(23.44*sin(x))+cos(\anga)*cos(23.44*sin(x))*cos(15*(\i+0.165*sin(2*x)-0.128*sin(x+5616/73))))^2))},{asin(sin(\anga)*sin(23.44*sin(x))+cos(\anga)*cos(23.44*sin(x))*cos(15*(\i+0.165*sin(2*x)-0.128*sin(x+5616/73))))});
}
\end{axis}
\end{tikzpicture}
\end{document}
答案1
让gnuplot
进行计算可能会快得多。在这种情况下,纯pgfplots
代码通常在我的计算机上花费 5 秒多一点的时间,而gnuplot
版本则花费 0.5 秒到 0.6 秒的时间。
它当然需要gnuplot
安装,并且必须在shell-escape
启用的情况下进行编译,例如pdflatex --shell-escape file.tex
。
\documentclass{article}
\usepackage{pgfplots}
\usepackage{filecontents}
\begin{document}
\def\anga{47} % latitude
\begin{tikzpicture}
\begin{axis}
\foreach \i in {-4,-3,...,4}{%
\addplot [black] gnuplot [raw gnuplot,id = p\i, mark=none] {
set parametric;
set trange [0:360];
set samples 60;
set angles degrees;
fx(t) = 180 + asin(cos(23.44*sin(t))*sin(15*(\i+0.165*sin(2*t) - 0.128*sin(t+5616/73)))/sqrt(1-(sin(\anga)*sin(23.44*sin(t)) + cos(\anga)*cos(23.44*sin(t))*cos(15*(\i+0.165*sin(2*t) - 0.128*sin(t+5616/73))))^2));
fy(t) = asin(sin(\anga)*sin(23.44*sin(t)) + cos(\anga)*cos(23.44*sin(t))*cos(15*(\i+0.165*sin(2*t) - 0.128*sin(t+5616/73))));
plot fx(t),fy(t)
};
}
\end{axis}
\end{tikzpicture}
\end{document}
答案2
以下是使用 LuaLaTeX 的解决方案:
\documentclass{minimal}
\usepackage{pgfplots}
\usepackage{filecontents}
\usepackage{luacode}
\begin{document}
\begin{luacode*}
anga=47 -- latitude
function sindeg(x)
return math.sin(x*math.pi/180)
end
function cosdeg(x)
return math.cos(x*math.pi/180)
end
function plot_curve(i)
local N=60
tex.sprint("\\addplot[line width=1pt,black] coordinates {")
for theta=0,360,360/N do
fct1=0.165*sindeg(2*theta)-0.128*sindeg(theta+5616/73)
fct2=cosdeg(23.44*sindeg(theta))
x=180+180/math.pi*math.asin(fct2*sindeg(15*(i+fct1))/math.sqrt(1-(sindeg(anga)*sindeg(23.44*sindeg(theta))+cosdeg(anga)*fct2*cosdeg(15*(i+fct1)))^2))
y=180/math.pi*math.asin(sindeg(anga)*sindeg(23.44*sindeg(theta))+cosdeg(anga)*fct2*cosdeg(15*(i+fct1)))
tex.sprint("("..x..","..y..")")
end
tex.print("};")
end
\end{luacode*}
\begin{tikzpicture}
\begin{axis}
\foreach \i in {-4,-3,...,4}{%
\directlua{plot_curve(\i);}
}
\end{axis}
\end{tikzpicture}
\end{document}
由于 Lua 使用弧度表示角度,因此我必须重新定义弧度表示正弦和余弦函数。这样速度就非常快了。
当然你应该使用lualatex
命令来编译它。
答案3
我感谢所有贡献者的回答。最后,我决定采用经典解决方案,即在 Python 中计算曲线点并导入它们。(我实际上以代码输出可以直接插入 .tex 的方式编写了程序,从而避免了另一个外部表。)
如果稍后出现更优雅的解决方案,我会接受它而不是我的。