绘制以部分定义的函数的plot_surface动画

huangapple go评论72阅读模式
英文:

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=&#39;3d&#39;)

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) &lt; 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) &gt; t[i]:
            z[i,j] = 0



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

&quot;&quot;&quot;this doesn&#39;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&quot;&quot;&quot;
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(即,不使用循环),请利用xy的二维形式,通过对整个数组执行操作。由于在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)

绘制以部分定义的函数的plot_surface动画

英文:

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) &lt; 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(&quot;all&quot;)

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) &lt; t3d] = 0.

zmin = z.min()
zmax = z.max()
fig, ax = plt.subplots(subplot_kw={&quot;projection&quot;:&quot;3d&quot;})
    
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(&quot;temp.gif&quot;, writer=&quot;pillow&quot;, fps=10, dpi=100)

绘制以部分定义的函数的plot_surface动画

huangapple
  • 本文由 发表于 2023年6月15日 03:48:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/76477082.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定