1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
| import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from mpl_toolkits.mplot3d import Axes3D # 3Dプロットのために必要
def make_animation(data_frames, filename="animation.gif"):
"""
3Dデータをアニメーション(GIF)として作成し保存する関数。
:param data_frames: 各フレームの3D座標 (X, Y, Z) のリスト。
例: [[X_frame1, Y_frame1, Z_frame1], [X_frame2, Y_frame2, Z_frame2], ...]
:param filename: 保存するGIFファイルのパス。
"""
print("フレームを生成中...")
fig = plt.figure(figsize=(8, 6)) # 図のサイズを指定
ax = fig.add_subplot(111, projection='3d')
# 軸ラベルの設定
ax.set_xlabel('X-axis')
ax.set_ylabel('Y-axis')
ax.set_zlabel('Z-axis')
# 軸の範囲をデータに合わせて自動調整、または手動で設定
# ax.set_xlim(-500, 500) # 例
# ax.set_ylim(-3, 3)
# ax.set_zlim(-3, 3)
ims = [] # 各フレームのArtistオブジェクトを格納するリスト
for i, (X, Y, Z) in enumerate(data_frames):
# プログレスバー表示
progress = (i + 1) * 100 / len(data_frames)
print(f"\r進捗: {progress:.1f}%", end="")
# 3Dプロット。marker='o' で点を表示、linestyle='None' で線を表示しない
# im = ax.plot(X, Y, Z, marker="o", color="red", linestyle='None')
# plot()はリストを返すので、ims.append(im[0])のように要素を取り出す
im, = ax.plot(X, Y, Z, marker="o", color="red", linestyle='None') # カンマでアンパック
ims.append([im]) # ArtistAnimationはリストのリストを期待する
print("\nアニメーションを生成中...")
# アニメーションの作成
# fig: アニメーションの対象となるFigureオブジェクト
# ims: 各フレームのArtistオブジェクトのリスト
# interval: フレーム間の遅延時間(ミリ秒)
# blit: Trueにすると、変更された部分のみを再描画し高速化(ただし、複雑な3Dプロットでは問題を起こす可能性あり)
ani = animation.ArtistAnimation(fig, ims, interval=50, blit=False)
# アニメーションの保存
# writer: アニメーションを保存するためのライター。'ffmpeg' や 'imagemagick' などが必要になる場合がある。
# fps: フレーム/秒
ani.save(filename, writer='pillow', fps=20) # 'pillow' は追加のライブラリ不要でGIF保存可能
print(f"アニメーションを {filename} に保存しました。")
plt.show() # アニメーションを表示
def main():
# サンプルデータの生成
# 時刻tに応じてsin波とcos波が変化する3D軌跡
t = np.linspace(0, 20 * np.pi, 500) # 0から20πまで500点
data_frames = []
for i in range(len(t)):
# 各フレームで1点だけプロットする例
X_val = t[i] / (20 * np.pi) * 5 # X軸は時間経過で変化
Y_val = np.sin(t[i])
Z_val = np.cos(t[i])
data_frames.append([[X_val], [Y_val], [Z_val]]) # 各要素をリストにする
make_animation(data_frames, filename="sin_cos_3d_animation.gif")
if __name__ == '__main__':
main()
|