🔥

claude codeに3次元のフラクタル図形書かせてみた

に公開

昨日は2次元のフラクタル図形をClaude Codeに作成させましたが、今回は3Dのフラクタル図形を作成させてみました。ぜひ昨日の記事もご覧ください。

https://zenn.dev/akasan/articles/91d41376641ffc

早速やってみる

まずは環境構築をします。

uv init fractal_3d -p 3.12
cd fractal_3d
uv add matplotlib numpy pillow

今回claude codeに与えた指示は以下になります。

pythonを使って、3次元のフラクタル図形を段階的に生成してアニメーションとして保存するコードを書いて。uvを使って

今回実装されたコードは以下になります。

fractal_3d.py
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation, PillowWriter
from mpl_toolkits.mplot3d import Axes3D
import itertools
import time

def generate_sierpinski_tetrahedron(level, base_vertices=None):
    """シェルピンスキー四面体を生成"""
    if base_vertices is None:
        base_vertices = np.array([
            [1, 1, 1],
            [1, -1, -1],
            [-1, 1, -1],
            [-1, -1, 1]
        ])
    
    if level == 0:
        return [base_vertices]
    
    midpoints = []
    for i, j in itertools.combinations(range(4), 2):
        midpoints.append((base_vertices[i] + base_vertices[j]) / 2)
    
    tetrahedra = []
    for i in range(4):
        new_vertices = [base_vertices[i]]
        for j in range(4):
            if i != j:
                for k, (a, b) in enumerate(itertools.combinations(range(4), 2)):
                    if (a == i and b == j) or (a == j and b == i):
                        new_vertices.append(midpoints[k])
                        break
        
        new_vertices = np.array(new_vertices[:4])
        tetrahedra.extend(generate_sierpinski_tetrahedron(level - 1, new_vertices))
    
    return tetrahedra

def create_rotating_animation():
    """回転するシェルピンスキー四面体のアニメーション"""
    print("Creating rotating Sierpinski tetrahedron animation...")
    
    fig = plt.figure(figsize=(8, 8))
    ax = fig.add_subplot(111, projection='3d')
    
    # レベル3のフラクタルを生成
    level = 3
    tetrahedra = generate_sierpinski_tetrahedron(level)
    print(f"Generated {len(tetrahedra)} tetrahedra for level {level}")
    
    def update(frame):
        ax.clear()
        ax.set_xlabel('X')
        ax.set_ylabel('Y')
        ax.set_zlabel('Z')
        ax.set_title(f'Sierpinski Tetrahedron - Level {level}')
        ax.set_xlim([-2, 2])
        ax.set_ylim([-2, 2])
        ax.set_zlim([-2, 2])
        
        # 回転角度を設定
        ax.view_init(elev=20, azim=frame * 3)
        
        # 四面体を描画
        for tetra in tetrahedra:
            faces = [
                [tetra[0], tetra[1], tetra[2]],
                [tetra[0], tetra[1], tetra[3]],
                [tetra[0], tetra[2], tetra[3]],
                [tetra[1], tetra[2], tetra[3]]
            ]
            
            for face in faces:
                face_array = np.array(face)
                face_closed = np.vstack([face_array, face_array[0]])
                ax.plot(face_closed[:, 0], 
                       face_closed[:, 1], 
                       face_closed[:, 2], 
                       'b-', alpha=0.6, linewidth=0.5)
    
    # アニメーション作成(120フレーム = 360度回転)
    anim = FuncAnimation(fig, update, frames=120, interval=50)
    
    # GIF保存
    writer = PillowWriter(fps=20)
    anim.save('sierpinski_rotating.gif', writer=writer)
    print("Saved sierpinski_rotating.gif")
    
    plt.close()


def create_animation():
    """段階的にフラクタルを生成するアニメーションを作成"""
    fig = plt.figure(figsize=(10, 10))
    ax = fig.add_subplot(111, projection='3d')
    
    max_level = 4
    all_levels = []
    
    # 各レベルのフラクタルを事前に生成
    for level in range(max_level + 1):
        tetrahedra = generate_sierpinski_tetrahedron(level)
        all_levels.append(tetrahedra)
    
    # 回転角度の設定
    angles = np.linspace(0, 360, 60)
    
    def update(frame):
        level = frame // len(angles)
        angle_idx = frame % len(angles)
        
        if level < len(all_levels):
            plot_tetrahedra(ax, all_levels[level], alpha=0.6)
            ax.view_init(elev=20, azim=angles[angle_idx])
            ax.set_title(f'3D Sierpinski Tetrahedron - Level {level}')
        
        return ax,
    
    # 総フレーム数:各レベルで1回転
    total_frames = len(all_levels) * len(angles)
    
    anim = FuncAnimation(fig, update, frames=total_frames, 
                        interval=50, blit=False)
    
    # GIFとして保存
    writer = PillowWriter(fps=20)
    anim.save('fractal_3d_animation.gif', writer=writer)
    print("Animation saved as 'fractal_3d_animation.gif'")
    
    plt.close()



if __name__ == "__main__":
    start_time = time.time()
    
    print("=" * 50)
    print("3D Fractal Animation Generator")
    print("=" * 50)
    
    create_rotating_animation()
    create_animation()

コードを見ると、今回作成されたのはシェルピンスキー四面体というもののようです。以下のページが参考になります。

https://www.i.h.kyoto-u.ac.jp/users/tsuiki/cfractal/kaisetu.html

それでは早速実行してみましょう。

uv run fractal_3d.py

結果を見ると、以下のような結果が取得できました。なお、生成されたgifは大きすぎて載せられないので、スクリーンショットになります。見ると確かに添付したリンクのような図形た生成されていることが確認できました。

まとめ

今回は3Dのフラクタル図形を作らせてみました。2Dの時と違って処理時間が全く違っており、生成される動画のファイルサイズも大きくなってしまいました。結果が動画で共有できないのが残念ですが、結果を見るとちゃんとフラクタル図形になっていることが確認できますので、ぜひ実行してみてください。

Discussion