matplotlib 为分段定义函数的plot_surface制作动画

piv4azn7  于 2023-06-30  发布在  其他
关注(0)|答案(1)|浏览(111)

我有一个给定的函数f(x,y,t),f=exp(-t/10)* sin(sqrt(x²+y²)-t),其中sqrt(x ² + y²)<t,f=0,否则(如果大于t)。x和y的范围为-30至30,t的范围为0至35。我的目标是随着时间的推移设置曲面的动画。
我已经绘制了表面,但不知道如何动画。也许我已经把一些本可以做得更优雅的事情复杂化了。以下是我目前为止的代码:

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation

    
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

x_data = np.linspace(-30,30,100)
y_data = np.linspace(-30,30,100)
t = np.linspace(0,35,100)
x, y = np.meshgrid(x_data, x_data)
z = np.zeros([100,100])

#filling in the values for z maybe this could be done more elegantly
for i in range(100):
    for j in range(100):
        if np.sqrt(x[i,j]**2+y[i,j]**2) < t[i]:
            z[i,j] = np.sin(np.sqrt(x[i,j]**2+y[i,j]**2) -t[i]) * np.exp(-t[i]/10.)
        elif np.sqrt(x[i,j]**2+y[i,j]**2) > t[i]:
            z[i,j] = 0


dataSet = np.array([x, y, z])
line = ax.plot_surface(dataSet[0], dataSet[1], dataSet[2], cmap="plasma")

"""this doesn't work because line is a mpl_toolkits.mplot3d.art3d.Poly3Dcollection object. We learned this kind of update function in our university-script for another example where line was a mpl_toolkits.mplot3d.art3d.Line3D object"""
def update(n):
    line.set_data(dataSet[0:2, :n])
    line.set_3d_properties(dataSet[2, :n])
    return line,

ani = matplotlib.animation.FuncAnimation(fig, update, interval = 30, blit = True)

所以我的问题是,我不知道,如何获得更新功能或动画本身启动和运行。我在网上找到了一些tuts,但大多数都是令人困惑的,而不是帮助。也许我的问题更基本(比如z值的初始化,也不是100%确定),所以任何帮助都将受到欢迎。

mo49yndu

mo49yndu1#

为了更有效地创建z(即没有循环),通过对这些整个数组执行操作来利用xy的2D形式。由于np.sqrt(x**2 + y**2) < t没有数值问题,因此您可以在任何地方计算f,然后在必要时对其进行校正。该计算的另一个变化是使t成为3D,其中它是100个100x100阵列,每个阵列都是该时间步长t的常数值。这样,您就可以为动画循环z

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.animation import FuncAnimation

plt.close("all")

N = 100
x_data = np.linspace(-30, 30, N)
y_data = np.linspace(-30, 30, N)
t = np.linspace(0, 35, N)
x, y = np.meshgrid(x_data, x_data)

t3d = np.ones((N, N, N))*t[:,None,None]
z = np.exp(-t3d/10.)*np.sin(np.sqrt(x**2 + y**2) - t3d)
z[np.sqrt(x**2 + y**2) < t3d] = 0.

zmin = z.min()
zmax = z.max()
fig, ax = plt.subplots(subplot_kw={"projection":"3d"})
    
def animate(i):
    ax.cla()
    ax.plot_surface(x, y, z[i])
    ax.set_zlim(zmin, zmax)
    fig.tight_layout()

ani = FuncAnimation(fig, animate, frames=100, interval=30)
ani.save("temp.gif", writer="pillow", fps=10, dpi=100)

相关问题