STUDIO TAMA

Rhinoceros & Grasshopper Utilities

© 2025 STUDIO TAMA

Day 23

L-Systemで生成する立体的な木構造

#recursive#tree#3d
L-Systemで生成する立体的な木構造

✅ Inputs

- axiom: str – 初期文字列(例: `"F"`)
- rules: dict – 書き換えルール(例: `{"F": "F[+F][-F][^F][&F][\\F][/F]"}`)
- angle: float – 各回転の角度(度)
- base_length: float – 初期の枝の長さ
- depth: int – ルール展開の反復回数(再帰深度)
- decay: float – 各分岐で枝が短くなる比率(0.8 など)
- pipe_radius: float – Pipeの太さ

✅ Outputs

- results: list of Brep – 3D空間に立体的に分岐するL-System構造をPipeで可視化したもの

✅ Code

import Rhino.Geometry as rg
import math

# === 🔧 入力パラメータ例(全方向への分岐)
axiom = "F"
rules = {
    "F": "F[+F][-F][^F][&F][\\F][/F]"  # 全方向へバランスよく分岐
}
angle = 40.0         # 回転角度(度)
base_length = 100.0   # 初期枝の長さ
depth = 4            # 再帰深度
decay = 0.8          # 枝の長さ減衰率
pipe_radius = 1.0

# === 🧬 L-Systemの展開
def expand_lsystem(axiom, rules, depth):
    result = axiom
    for _ in range(depth):
        next_result = ""
        for char in result:
            next_result += rules.get(char, char)
        result = next_result
    return result

# === 🐢 Turtle描画(3D Turtle with Length Decay)
def interpret_lsystem(lsys_string, angle_deg, base_length, decay):
    pos_stack = []
    dir_stack = []
    up_stack = []
    right_stack = []
    length_stack = []

    pos = rg.Point3d(0, 0, 0)
    dir = rg.Vector3d(0, 0, 1)     # Z方向に伸びる
    up = rg.Vector3d(1, 0, 0)      # X軸方向
    right = rg.Vector3d(0, 1, 0)   # Y軸方向
    length = base_length

    lines = []
    angle_rad = math.radians(angle_deg)

    for char in lsys_string:
        if char == "F":
            new_pos = pos + dir * length
            lines.append(rg.Line(pos, new_pos))
            pos = new_pos
        elif char == "+":
            xform = rg.Transform.Rotation(angle_rad, up, pos)
            dir.Transform(xform)
        elif char == "-":
            xform = rg.Transform.Rotation(-angle_rad, up, pos)
            dir.Transform(xform)
        elif char == "&":
            xform = rg.Transform.Rotation(angle_rad, right, pos)
            dir.Transform(xform)
        elif char == "^":
            xform = rg.Transform.Rotation(-angle_rad, right, pos)
            dir.Transform(xform)
        elif char == "\\":
            xform = rg.Transform.Rotation(angle_rad, dir, pos)
            up.Transform(xform)
            right.Transform(xform)
        elif char == "/":
            xform = rg.Transform.Rotation(-angle_rad, dir, pos)
            up.Transform(xform)
            right.Transform(xform)
        elif char == "[":
            pos_stack.append(rg.Point3d(pos))
            dir_stack.append(rg.Vector3d(dir))
            up_stack.append(rg.Vector3d(up))
            right_stack.append(rg.Vector3d(right))
            length_stack.append(length)
            length *= decay  # 枝を短くする
        elif char == "]":
            pos = pos_stack.pop()
            dir = dir_stack.pop()
            up = up_stack.pop()
            right = right_stack.pop()
            length = length_stack.pop()

    return [l.ToNurbsCurve() for l in lines]

# === 🚀 実行
lsys_string = expand_lsystem(axiom, rules, depth)
curves = interpret_lsystem(lsys_string, angle, base_length, decay)

results = []
for c in curves:
    pipes = rg.Brep.CreatePipe(c, pipe_radius, False, rg.PipeCapMode.Round, True, 0.001, 0.001)
    if pipes:
        results.extend(pipes)

ライセンス・利用規約

項目可否説明
自身のプロジェクトへの組み込み個人・商用問わず、スクリプトや作品の一部として自由に使えます。
コードの改変・学習利用自身の学習や、目的に合わせたカスタマイズは大歓迎です。
SNSへのシェア・紹介作品の画像やURLのシェアは許可不要です。ぜひご紹介ください!
再配布・転載×コードやファイルを丸ごと自身のサイト等でコンテンツとして公開しないでください。
素材・プログラムとしての転売×本サイトの内容をそのまま、あるいは微調整のみで有料販売しないでください。
著作権表示・リンク任意必須ではありませんが、引用元としてリンクを貼っていただけると励みになります。
Day Day 23 - L-Systemで生成する立体的な木構造 | Grasshopper Python 入門チュートリアル | STUDIO TAMA - Rhinoceros & Grasshopper Utilities