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

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