英文:
Animating plot_surface of section-wise defined function
问题
我已经绘制了曲面,但不知道如何制作动画。也许我已经过于复杂化了一些事情,可以更加优雅地完成。以下是到目前为止的代码:
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])
# 填充z值,也许可以更加优雅地完成
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")
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)
所以我的问题是,我不知道如何使更新函数或动画本身运行起来。我在互联网上找到了一些教程,但大多数都比较混乱,不如有帮助。也许我的问题甚至更加基本(比如z值的初始化,对此也不是百分之百确定),所以任何帮助都将不胜感激。
英文:
I have a given function f(x,y,t) with f=exp(-t/10)* sin(sqrt(x²+y²)-t) where sqrt(x²+y²)<t and f=0 else (if greater than t).
x and y range from -30 to 30 and t from 0 to 35. My goal is to animate the surface over the time.
I already have plotted the surface but dont' know how to animate it. Maybe I already overcomplicated some things which could be done more elegantly. Here's my code so far:
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)
So my problem is, I don't know, how to get the update function or the animation itself up and running. I found some tuts on the internet but most of them are rather confusing than helping. Maybe my problem is even more fundamental (like the initialization of the z values, not 100 percent sure about that either), so any help will be appreciated.
答案1
得分: 1
以下是要翻译的内容:
要更高效地创建z
(即,不使用循环),请利用x
和y
的二维形式,通过对整个数组执行操作。由于在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)
英文:
To create z
more efficiently (i.e. without loops), make use of the 2D form of x
and y
by performing the operations with those entire arrays. Since there are no numerical issues when np.sqrt(x**2 + y**2) < t
, you can just calculate f
everywhere and then correct it afterward where necessary. One other change with that calculation is to make t
3D where it is 100 100x100 arrays, with each being a constant value for the t
at that timestep. With that, you can then loop through z
for the animation.
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)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论