如何使用Matplotlib 3D实现环面绕Oz轴的旋转动画
问题分析
- 你当前的代码没有实现旋转的核心原因是
update函数中每次生成的环面坐标完全相同,没有应用绕Oz轴的旋转变换,自然不会产生旋转效果 - 额外的小问题:代码缺少numpy导入语句,直接运行会抛出名称错误
实现原理
绕Oz轴的二维旋转变换公式如下,θ为当前帧的旋转角度:
x_new = x * cosθ - y * sinθ
y_new = x * sinθ + y * cosθ
z_new = z
在动画帧更新时,随帧序号递增修改θ值,再代入上述公式计算新的环面坐标即可实现自旋效果。
修改后的完整代码
import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation t = np.linspace(0, 2 * np.pi, 50) th, ph = np.meshgrid(t, t) r = 0.4 # 预计算初始环面坐标,后续只做旋转变换不用重复生成 x_ori, y_ori, z_ori = 1.5*r * np.sin(ph), (2 + r * np.cos(ph)) * np.sin(th), (2 + r * np.cos(ph)) * np.cos(th) z_ori += 2 # 提前加z轴偏移 fig = plt.figure() ax = fig.add_subplot(projection='3d') plot = [ax.plot_surface(x_ori, y_ori, z_ori, rstride=2, cstride=1, color='green', alpha=.5)] ax.set(xlim=[-4, 4], ylim=[-4, 4], zlim=[0, 4]) # 静态蓝色小球部分不用修改 u = np.linspace(0, 2 * np.pi, 100) v = np.linspace(0, np.pi, 100) a = 0.5 * np.outer(np.cos(u), np.sin(v)) b = 0.5 * np.outer(np.sin(u), np.sin(v)) c = 0.4 * np.outer(np.ones(np.size(u)), np.cos(v)) ax.plot_surface(a, b, c+4, rstride=4, cstride=4, color='b', linewidth=0) ax.view_init(elev=60, azim=0) def update(num): plot[0].remove() # 计算当前帧旋转角度,100帧转一圈 theta = num * 2 * np.pi / 100 cos_theta = np.cos(theta) sin_theta = np.sin(theta) # 应用绕Oz轴旋转变换 x_new = x_ori * cos_theta - y_ori * sin_theta y_new = x_ori * sin_theta + y_ori * cos_theta z_new = z_ori plot[0] = ax.plot_surface(x_new, y_new, z_new, rstride=2, cstride=1, color='green', alpha=.5) ani = animation.FuncAnimation(fig, update, frames=100, interval=40) plt.show()
修改说明
- 新增了numpy导入,修复运行报错问题
- 预计算初始环面坐标,避免每帧重复生成冗余计算
- 在
update函数中根据帧序号计算旋转角度,应用z轴旋转矩阵得到新的坐标,实现自旋效果 - 把视角初始化统一放到
view_init中,避免分散设置的混乱
内容的提问来源于stack exchange,提问作者tyt
相关产品推荐
相关产品推荐

