Loading [MathJax]/jax/output/HTML-CSS/config.js

[matplotlib animation] 37. 3Dグラフの縦回転アニメーション

matplotlib 3D

はじめに

matplotlib FuncAnimationによる3Dグラフの縦回転アニメーションについて説明する。

コード

from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
from IPython.display import HTML
import matplotlib.animation as animation
import numpy as np
fig = plt.figure(figsize=(5,5)
ax = fig.add_subplot(111, projection='3d')
x, y, z = np.indices((17, 17, 17))
num = np.linspace(1,15,15)
v1 = (z == 0)
v2 = (x <= num[-1]) & (y <= num[-1]) & (z == num[0]) & (x >= num[0]) & (y >= num[0])
v3 = (x <= num[-2]) & (y <= num[-2]) & (z == num[1]) & (x >= num[1]) & (y >= num[1])
v4 = (x <= num[-3]) & (y <= num[-3]) & (z == num[2]) & (x >= num[2]) & (y >= num[2])
v5 = (x <= num[-4]) & (y <= num[-4]) & (z == num[3]) & (x >= num[3]) & (y >= num[3])
v6 = (x <= num[-5]) & (y <= num[-5]) & (z == num[4]) & (x >= num[4]) & (y >= num[4])
v7 = (x <= num[-6]) & (y <= num[-6]) & (z == num[5]) & (x >= num[5]) & (y >= num[5])
v8 = (x <= num[-7]) & (y <= num[-7]) & (z == num[6]) & (x >= num[6]) & (y >= num[6])
v9 = (x <= num[-8]) & (y <= num[-8]) & (z == num[7]) & (x >= num[7]) & (y >= num[7])
voxels = v1 | v2 | v3 | v4| v5 | v6 | v7 | v8 | v9
ax.voxels(voxels, facecolors='gold', edgecolor='gray')
#view
rotate_elev = np.concatenate((np.linspace(0,180,50,endpoint = False),np.linspace(-180,0,51)))
rotate_azim = np.linspace(60,420,101)
def init():
ax.set_zlim(0,10)
#ax.set_aspect('equal')
return fig,
def animate(i):
#rotate azim
#ax.view_init(elev=30, azim=rotate_azim[i])
#rotate elev
ax.view_init(elev=rotate_elev[i], azim=60)
#rotate elev and azim
#ax.view_init(elev=rotate_elev[i], azim=rotate_azim[i])
return fig,
# Animate
ani = animation.FuncAnimation(fig, animate, init_func=init,
frames=101, interval=100, blit=False)
ani.save('rotate_pyramid_1.mp4', writer="ffmpeg",dpi=100)
HTML(ani.to_html5_video())
コードをダウンロード(.pyファイル) コードをダウンロード(.ipynbファイル)

解説

モジュールのインポート

from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
from IPython.display import HTML
import matplotlib.animation as animation
import numpy as np

グラフの設定

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

ピラミッドの作成

ピラミッドはボクセルで↓と同様に作成。

[matplotlib 3D] 46.ボクセルピラミッド(Voxel Pyramid)
matplotlib mplot3dでvoxelによるピラミッド
x, y, z = np.indices((17, 17, 17))
num = np.linspace(1,15,15)
v1 = (z == 0)
v2 = (x <= num[-1]) & (y <= num[-1]) & (z == num[0]) & (x >= num[0]) & (y >= num[0])
v3 = (x <= num[-2]) & (y <= num[-2]) & (z == num[1]) & (x >= num[1]) & (y >= num[1])
v4 = (x <= num[-3]) & (y <= num[-3]) & (z == num[2]) & (x >= num[2]) & (y >= num[2])
v5 = (x <= num[-4]) & (y <= num[-4]) & (z == num[3]) & (x >= num[3]) & (y >= num[3])
v6 = (x <= num[-5]) & (y <= num[-5]) & (z == num[4]) & (x >= num[4]) & (y >= num[4])
v7 = (x <= num[-6]) & (y <= num[-6]) & (z == num[5]) & (x >= num[5]) & (y >= num[5])
v8 = (x <= num[-7]) & (y <= num[-7]) & (z == num[6]) & (x >= num[6]) & (y >= num[6])
v9 = (x <= num[-8]) & (y <= num[-8]) & (z == num[7]) & (x >= num[7]) & (y >= num[7])
voxels = v1 | v2 | v3 | v4| v5 | v6 | v7 | v8 | v9

アニメーションの設定

視点変更するための配列の生成

rotate_elev = np.concatenate((np.linspace(0,180,50,endpoint = False),np.linspace(-180,0,51)))

3Dグラフの高さ方向の視点elevにおいて、180と-180はおなじなので、endpoint = Falseとすることで180を配列にいれないようにした。np.concatenate()で配列を連結する。配列の大きさは101とした。

アニメーションの設定

def init():
ax.set_zlim(0,10)
#ax.set_aspect('equal')
return fig,

アニメーションの初期設定でグラフのアスペクト比とz軸範囲を調整する。

def animate(i):
#rotate elev
ax.view_init(elev=rotate_elev[i], azim=60)

ax.view_init()で視点を変更できる。
azim=60と固定で、elev=rotate_elev[i]でelevが変化するアニメーションとする。

アニメーションの表示

ani = animation.FuncAnimation(fig, animate, init_func=init,
frames=101, interval=100, blit=False)
ani.save('rotate_pyramid_1.mp4', writer="ffmpeg",dpi=100)
HTML(ani.to_html5_video())

HTML(ani.to_html5_video())とすればjupyter notebook上にアニメーションを表示できる。

参考

[matplotlib 3D] 14. 3Dグラフの回転アニメーション
matplotlib mplot3d のグラフの回転アニメーション

コメント