inch-blog

Welcome to Inch-blog ! Home is a place where you can read mainly technical articles. LIFE is mainly about my personal life.

Python を使った L-システムによる 2 次元樹木の画像生成

import matplotlib.pyplot as plt
from scipy.spatial import distance
import numpy as np

generation = 5 # 世代数
# 枝のどこから生やすか, 生やす枝の長さ, 生やす枝の角度
infomation = np.array([
        [1, 0.5, -30], 
        [0.5, 0.45, 45],
        [0.3, 0.7, -20],
        [0.8, 0.3, 60],
        [1, 0.5, 30],
])

def rotation_o(u, t):
    # 度数単位の角度をラジアンに変換
    t = np.deg2rad(t)
    # 回転行列
    R = np.array([[np.cos(t), -np.sin(t)],
                  [np.sin(t),  np.cos(t)]])
    return  np.dot(R, u)

def l_system(gen, infomation, old_x, old_y):
    for info in infomation:
        if gen == 0:
            pass
        else:
            position_r = info[0] # 枝のどこから生やすか
            length_r = info[1] # 生やす枝の長さ
            deg = info[2] # 生やす枝の角度

            # はやす枝の生えぎわの座標
            root_x = old_x[1] * position_r + old_x[0] * (1-position_r)
            root_y = old_y[1] * position_r + old_y[0] * (1-position_r)

            # はやす枝の長さ
            old_a = np.array([old_x[0], old_y[0]])
            old_b = np.array([old_x[1], old_y[1]])
            edge_length = distance.euclidean(old_a, old_b) * length_r

            # はやす枝の角度
            vec = np.array([
                            old_x[1] - old_x[0], old_y[1] - old_y[0]
            ])
            base_deg = - np.rad2deg(np.arctan2(vec[0], vec[1]))
            new_deg = deg + base_deg

            # 原点から枝をはやし傾ける
            edge = np.array([0, 0 + edge_length])
            leaf_xy = rotation_o(edge, new_deg)

            # はやす枝の生えぎわの座標に移動させ
            # はやした枝の先の座標を求める
            leaf_x = root_x + leaf_xy[0]
            leaf_y = root_y + leaf_xy[1]

            new_x = np.array([root_x, leaf_x])
            new_y = np.array([root_y, leaf_y])

            # 描画
            ax.plot([root_x, leaf_x], [root_y, leaf_y])

            # 再帰
            l_system(gen-1, infomation, new_x, new_y)


fig = plt.figure(figsize=(6.4, 6.4))
ax = fig.add_subplot(1, 1, 1)

x = np.array([0, 0])
y = np.array([0, 1])
ax.plot(x, y)
l_system(generation, infomation, x, y)

ax.axis("off")
fig.savefig('L-System.png')
image block