lindenmayer systems
This commit is contained in:
parent
ad318ccf54
commit
44eae1157f
|
@ -1,5 +1,6 @@
|
||||||
from .device import Device
|
from .device import Device
|
||||||
from .drawing import Drawing
|
from .drawing import Drawing
|
||||||
|
from .lindenmayer import LSystem
|
||||||
from .paths import simplify_paths, sort_paths, join_paths, load_paths
|
from .paths import simplify_paths, sort_paths, join_paths, load_paths
|
||||||
from .planner import Planner
|
from .planner import Planner
|
||||||
from .turtle import Turtle
|
from .turtle import Turtle
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
import random
|
||||||
|
import re
|
||||||
|
|
||||||
|
from math import sin, cos, radians
|
||||||
|
|
||||||
|
from .drawing import Drawing
|
||||||
|
|
||||||
|
class LSystem(object):
|
||||||
|
def __init__(self, rules):
|
||||||
|
self.rules = rules
|
||||||
|
self.pattern = re.compile('|'.join('(%s)' % x for x in rules))
|
||||||
|
|
||||||
|
def step(self, value):
|
||||||
|
def func(match):
|
||||||
|
rule = self.rules[match.group(0)]
|
||||||
|
if isinstance(rule, basestring):
|
||||||
|
return rule
|
||||||
|
return random.choice(rule)
|
||||||
|
return self.pattern.sub(func, value)
|
||||||
|
|
||||||
|
def steps(self, value, iterations):
|
||||||
|
for i in range(iterations):
|
||||||
|
value = self.step(value)
|
||||||
|
return value
|
||||||
|
|
||||||
|
def run(self, start, iterations, angle=None):
|
||||||
|
program = self.steps(start, iterations)
|
||||||
|
angle = angle and radians(angle)
|
||||||
|
state = (0.0, 0.0, 0.0)
|
||||||
|
stack = []
|
||||||
|
paths = []
|
||||||
|
point = (0.0, 0.0)
|
||||||
|
for instruction in program:
|
||||||
|
x, y, a = state
|
||||||
|
if instruction == '-':
|
||||||
|
a -= angle
|
||||||
|
elif instruction == '+':
|
||||||
|
a += angle
|
||||||
|
elif instruction == '[':
|
||||||
|
stack.append(state)
|
||||||
|
elif instruction == ']':
|
||||||
|
x, y, a = stack.pop()
|
||||||
|
point = (x, y)
|
||||||
|
else:
|
||||||
|
x += cos(a)
|
||||||
|
y += sin(a)
|
||||||
|
if paths and point == paths[-1][-1]:
|
||||||
|
paths[-1].append((x, y))
|
||||||
|
else:
|
||||||
|
paths.append([point, (x, y)])
|
||||||
|
point = (x, y)
|
||||||
|
state = (x, y, a)
|
||||||
|
return Drawing(paths)
|
|
@ -0,0 +1,21 @@
|
||||||
|
import axi
|
||||||
|
|
||||||
|
def main():
|
||||||
|
system = axi.LSystem({
|
||||||
|
'A': 'A-B--B+A++AA+B-',
|
||||||
|
'B': '+A-BB--B-A++A+B',
|
||||||
|
})
|
||||||
|
d = system.run('A', 5, 60)
|
||||||
|
# system = axi.LSystem({
|
||||||
|
# 'X': 'F-[[X]+X]+F[+FX]-X',
|
||||||
|
# 'F': 'FF',
|
||||||
|
# })
|
||||||
|
# d = system.run('X', 6, 20)
|
||||||
|
d = d.rotate_and_scale_to_fit(12, 8.5, step=90)
|
||||||
|
# d = d.sort_paths()
|
||||||
|
# d = d.join_paths(0.015)
|
||||||
|
d.render().write_to_png('out.png')
|
||||||
|
axi.draw(d)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
Loading…
Reference in New Issue