0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

3Dデータ(STL)をmatplotableで表示させ、球を徐々に青から赤にしてgifで保存

Posted at

タイトルの通り3Dデータ(STL)をmatplotableで表示させ、球を徐々に青から赤にしてgifで保存させます。

pip install numpy matplotlib numpy-stl

view_top.gif

発想のままやったので球は適当...
可視化等に役に立つと思います

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()

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?