タイトルの通り3Dデータ(STL)をmatplotableで表示させ、球を徐々に青から赤にしてgifで保存させます。
pip install numpy matplotlib numpy-stl
発想のままやったので球は適当...
可視化等に役に立つと思います
import numpy as np
from stl import mesh
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
from matplotlib.animation import FuncAnimation, PillowWriter
views = [
(20, 135, "view_oblique.gif"), # 斜め
(0, 0, "view_front.gif"), # 正面
(90, 0, "view_top.gif") # 真上
]
# STL 読み込み
stl_file = r".../3d\A.stl" # ここを置き換え
your_mesh = mesh.Mesh.from_file(stl_file)
tris = your_mesh.vectors
fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111, projection="3d")
# STL メッシュを追加
collection = Poly3DCollection(tris, linewidths=0.3, alpha=0.9)
# 面の色 (RGBA または色名文字列)
#collection.set_facecolor((0.2, 0.6, 0.8, 0.6)) # 半透明の水色
# または
collection.set_facecolor("lightgreen")
# 輪郭線の色と太さ
collection.set_edgecolor("black")
collection.set_linewidth(0)
ax.add_collection3d(collection)
# 球を準備
def plot_sphere(center, radius=1.0, resolution=30):
u = np.linspace(0, 2*np.pi, resolution)
v = np.linspace(0, np.pi, resolution)
uu, vv = np.meshgrid(u, v)
x = center[0] + radius * np.cos(uu) * np.sin(vv)
y = center[1] + radius * np.sin(uu) * np.sin(vv)
z = center[2] + radius * np.cos(vv)
return x, y, z
centers = [(0, 0, 0)]
radii = [3.0]
spheres = []
sphere_coords = []
for c, r in zip(centers, radii):
X, Y, Z = plot_sphere(c, r)
surf = ax.plot_surface(X, Y, Z, color=(0, 0, 1), alpha=0.8)
spheres.append(surf)
sphere_coords.append((X, Y, Z))
# 軸スケール調整
all_pts = np.concatenate((tris.reshape(-1, 3), np.array(centers)), axis=0)
xmin, ymin, zmin = all_pts.min(axis=0)
xmax, ymax, zmax = all_pts.max(axis=0)
max_range = np.max([xmax-xmin, ymax-ymin, zmax-zmin]) * 0.6
midx, midy, midz = (0.5*(xmax+xmin), 0.5*(ymax+ymin), 0.5*(zmax+zmin))
ax.set_xlim(midx-max_range, midx+max_range)
ax.set_ylim(midy-max_range, midy+max_range)
ax.set_zlim(midz-max_range, midz+max_range)
ax.view_init(elev=20, azim=135)
# 経過時間テキスト (右下に固定配置)
time_text = ax.text2D(0.95, 0.05, "", transform=ax.transAxes,
ha="right", va="bottom", fontsize=12, color="black")
# 更新関数
def update(frame):
t = frame / 100
color = (t, 0, 1-t)
# 球の色更新
for i, surf in enumerate(spheres):
surf.remove()
X, Y, Z = sphere_coords[i]
spheres[i] = ax.plot_surface(X, Y, Z, color=color, alpha=0.8)
# 経過時間更新 (秒換算: interval=100ms → 0.1秒/フレーム)
elapsed = frame * 0.1
time_text.set_text(f"Time: {elapsed:.1f} s")
return spheres + [time_text]
# アニメーション作成
ani = FuncAnimation(fig, update, frames=100, interval=100, blit=False, repeat=True)
# --- アニメーション作成 ---
#ani = FuncAnimation(fig, update, frames=100, interval=100, blit=False, repeat=True)
path = r"...\3d" #path変更
# GIFとして保存
for elev, azim, filename in views:
ax.view_init(elev=elev, azim=azim)
ani = FuncAnimation(fig, update, frames=100, interval=100, blit=False, repeat=True)
ani.save(path+"/"+filename, writer=PillowWriter(fps=10))
print(f"保存しました: {filename}")
plt.show()