Created
December 16, 2015 20:06
-
-
Save zeffii/a8de9e6961908c60c98d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
lifted from: http://www.4dsolutions.net/ocn/lsystems.html | |
"F": Move forward a step of length d. A line segment between | |
points (X,Y,Z) and (X',Y',Z') is drawn. | |
"[" | |
and | |
"]": bracket - push and pop the current state, in this project | |
it is used to generate the tree branches | |
"+": Turn left by angle Delta, Using rotation matrix R_U(Delta) | |
"-": Turn right by angle Delta, Using rotation matrix R_U(-Delta) | |
"&": Pitch down by angle Delta, Using rotation matrix R_L(Delta) | |
"+": Pitch up by angle Delta, Using rotation matrix R_L(-Delta) | |
"<": Roll left by angle Delta, Using rotation matrix R_H(Delta) | |
">": Roll right by angle Delta, Using rotation matrix R_H(-Delta) | |
"|": Turn around, Using rotation matrix R_H(180) | |
""" | |
import math | |
import bpy | |
import bmesh | |
from mathutils import Vector, Euler | |
Xvec = Vector((1, 0, 0)) | |
Yvec = Vector((0, 1, 0)) | |
Zvec = Vector((0, 0, 1)) | |
def produce(axiom, rules): | |
output = "" | |
for i in axiom: | |
output = output + rules.get(i, i) | |
return output | |
def iterate(n, axiom, rules): | |
# print(axiom) | |
if n > 0: | |
axiom = produce(axiom, rules) | |
return iterate(n - 1, axiom, rules) | |
return axiom | |
class Lturtle: | |
# looking down on YX axis. Z is vertical. | |
stackstate = [] # remembers saved state | |
Heading = Vector((0, 0, 1)) | |
delta = 0.2 # angle of rotation | |
length = 0.5 # full length of turtle move | |
thickness = 0.02 # default thickness of cylinder | |
instrudict = { | |
'+': 'turnleft', | |
'-': 'turnright', | |
'&': 'pitchdown', | |
'^': 'pitchup', | |
'<': 'leftroll', | |
'>': 'rightroll', | |
'[': 'storeloc_rot', | |
']': 'restoreloc_rot', | |
'%': 'roll180', | |
'$': 'rollhoriz', | |
'x': 'randturn', | |
't': 'gravity', | |
'F': 'fdraw', | |
'f': 'fnodraw', | |
'Z': 'halfdraw', | |
'z': 'halfnodraw', | |
'g': 'Fnorecord', | |
'.': 'Nomove' | |
} | |
verts = [] | |
edges = [] | |
def __init__(self, vPos=Vector((0, 0, 0)), vH=Xvec, vL=Yvec, vU=Zvec): | |
self.vPos, self.vH, self.vL, self.vU = vPos, vH, vL, vU | |
def chomp(self, instructions): | |
getparam = 0 | |
checkparam = 0 | |
param = "" | |
for item in instructions: | |
if getparam: | |
if item == ")": | |
getparam = 0 # done getting | |
command = command + "(" + param + ")" | |
eval(command) | |
continue | |
else: | |
param = param + item # building parameter | |
continue | |
if checkparam: # checking for parameter? | |
checkparam = 0 | |
if item == "(": | |
param = "" | |
getparam = 1 # parameter exists | |
continue | |
else: | |
command = command + "()" # no parameter | |
eval(command) | |
# initializing command string | |
command = "self." + self.instrudict.get(item, 'notHandled') | |
checkparam = 1 # set flag | |
else: # dealing with last item | |
if checkparam: | |
command = command + "()" # no parameter | |
eval(command) | |
if self.edges and self.verts: | |
mesh = bpy.data.meshes.new("Base_Data") | |
mesh.from_pydata(Verts, Edges, []) | |
mesh.update() | |
obj = bpy.data.objects.new("Base_Object", mesh) | |
scene = bpy.context.scene | |
scene.objects.link(obj) | |
def add_edge(self): | |
i = len(self.verts) | |
self.edges.append([i - 2, i - 1]) | |
def add_verts(self, amp=1): | |
self.verts.append(vPos[:]) | |
self.vPos = self.vPos + vHeading * length * amp | |
self.verts.append(vPos[:]) | |
def fnodraw(self, n=""): | |
self.vPos = self.vPos + vHeading * length | |
print("Forward %s (no draw)" % n) | |
def halfnodraw(self, n=""): | |
self.vPos = self.vPos + (vHeading * length * 0.5) | |
print("half no draw %s" % n) | |
def fdraw(self, n=""): | |
self.add_verts() | |
self.add_edge() | |
print("fdraw %s" % n) | |
def halfdraw(self, n=""): | |
self.add_verts(amp=0.5) | |
self.add_edge() | |
print("half draw %s" % n) | |
# Turning | |
def do_rotation(self, sign, n=""): | |
if n: | |
self.delta = float(n) | |
myEul = Euler((0, 0, sign * math.radians(self.delta)), 'XYZ') | |
self.vHeading.rotate(myEul) | |
def turnleft(self, n=""): | |
self.do_rotation(1, n) | |
print("Turn Left around Z axis %s" % n) | |
def turnright(self, n=""): | |
self.do_rotation(-1, n) | |
print("Turn Right around Z axis %s" % n) | |
def storeloc_rot(self, n=""): | |
print("Store rotation and location %s" % n) | |
def restoreloc_rot(self, n=""): | |
print("Restore rotation and location %s" % n) | |
def pitchdown(self, n=""): | |
print("Pitch down %s" % n) | |
def pitchup(self, n=""): | |
print("Pitch up %s" % n) | |
def leftroll(self, n=""): | |
print("left roll %s" % n) | |
# Rolling | |
def rightroll(self, n=""): | |
print("right roll %s" % n) | |
def turn180(self, n=""): | |
print("turn180 %s" % n) | |
def roll180(self, n=""): | |
print("roll180 %s" % n) | |
def rollhoriz(self, n=""): | |
print("roll horiz %s" % n) | |
def randturn(self, n=""): | |
print("randturn %s" % n) | |
def gravity(self, n=""): | |
print("gravity %s" % n) | |
def Fnorecord(self, n=""): | |
print("Fnorecord %s" % n) | |
def Nomove(self, n=""): | |
print("No move %s" % n) | |
def notHandled(self, n=""): | |
print("Not handled %s" % n) | |
rules = {} | |
rules['I'] = '+(40)ffHccI' | |
rules['H'] = '[+fffG]c[-fffG]c[^fffG]c[&fffG]G' | |
rules['G'] = '[dS]e[d]e[d]e[d]e[d]e[d]e[d]e[d]' | |
rules['e'] = '+(90)f-(90)>(-45)' | |
rules['d'] = '[f+(90)f+(90)f+(90)f>(+38)-(105)ff-(151)ff][f&(38)+(15)ff+(151)ff]' | |
axiom = 'I' | |
m = iterate(2, axiom, rules) | |
print(m) | |
poonjab = Lturtle() | |
poonjab.chomp(m) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment