分形树的基本分形元如下图所示,用比较简单的单规则LS文法即可生成。
只是有一个地方要注意,即图形中存在分叉点A和B,从这两点出发绘制完支线后,还要再回到出发点,所以在画到这种点时,要把当前的位置和方向信息入栈保存,支线画完后,再把信息恢复出来,从分支点接着画。
照以下文法可以生成一个最简单的分形树:
delta = 25(度)
omega = "F"
P : F -> F[-F]F[+F]F
其中[表示当前位置和方向信息入栈,]为出栈。
以下是构造这一分形树的Python程序及运行图。
#!/apps/bin/python
from Tkinter import *
import math

# Point类存储分支点的位置(X,Y)和方向direction信息
class Point :
X = 0
Y = 0
direction = 0

def __init__ (self, x, y, d):
self.X = x
self.Y = y
self.direction = d

def getX(self):
return self.X

def getY(self):
return self.Y

def getDirection(self):
return self.direction


class Tree(Frame):

statement = "F"
replacement = "F[-F]F[+F]F"
level = 5
direction = math.pi/2
winkle = math.pi/180*25
endX = 400
endY = 50
step = 2
# stack是一个堆栈
stack = []
def __init__(self, master=None):
self.caluStatement()
Frame.__init__(self, master)
self.grid()
self.createWidgets()

def caluStatement(self):
for currentLevel in range(0, self.level):
newStatement = ""
for index in range(0,len(self.statement)):
if (self.statement[index] == "F"):
newStatement = newStatement + self.replacement
else :
newStatement = newStatement + self.statement[index]
self.statement = newStatement
print self.statement

def createWidgets(self):
#self.quitButton = Button(self, text="QUIT", command=self.quit)
#self.quitButton.pack(side=BOTTOM, fill=BOTH)
self.draw = Canvas(self, width=800, height=600)
self.draw.pack(side=LEFT)
self.drawCanvas()

def drawCanvas(self):
for index in range(0,len(self.statement)):
if (self.statement[index] == "F"):
startX = self.endX
startY = self.endY
self.endX = startX + self.step*(math.cos(self.direction))
self.endY = startY + self.step*(math.sin(self.direction))
self.draw.create_line(startX,startY,self.endX,self.endY)
elif (self.statement[index] == "-"):
self.direction = self.direction - self.winkle
elif (self.statement[index] == "+"):
self.direction = self.direction + self.winkle
elif (self.statement[index] == "["):
self.stack.append(Point(self.endX, self.endY, self.direction))
elif (self.statement[index] == "]"):
oldPoint = self.stack.pop()
self.endX = oldPoint.getX()
self.endY = oldPoint.getY()
self.direction = oldPoint.getDirection()




app = Tree()
app.master.title("Tree (LS)")
app.mainloop()

.png)
分形树还可以再复杂一点,在上面的例子中,替换规则被指定为P,构造成的树的形状就是确定的;但如果替换规则有很多种(比如P1、P2、…、PN)可选,而每一次替换的时候是随选一个的话,生成的树的形状也将是不确定的,是随机的,这种多替换规则随机选取的LS文法称为随机LS文法。以下是由基本分形树经过修改得到的随机分形树的源程序以及运行效果图:
#!/apps/bin/python
from Tkinter import *
import math
import random

class Point :
X = 0
Y = 0
direction = 0

def __init__ (self, x, y, d):
self.X = x
self.Y = y
self.direction = d

def getX(self):
return self.X

def getY(self):
return self.Y

def getDirection(self):
return self.direction


class RandomTree(Frame):

statement = "F"
#随机规则
replacementA = "F[+F]F[-F]F"
replacementB = "F[+F]F[-F[+F]]"
replacementC = "FF[-F+F+F]+[+F-F-F]"
level = 5
direction = math.pi/2
winkle = math.pi/180*25
endX = 600
endY = 50
step = 4
stack = []
def __init__(self, master=None):
self.caluStatement()
Frame.__init__(self, master)
self.grid()
self.createWidgets()

def caluStatement(self):
for currentLevel in range(0, self.level):
newStatement = ""
for index in range(0,len(self.statement)):
if (self.statement[index] == "F"):
if (random.random()<0.6):
newStatement = newStatement + self.replacementA
elif (random.random()<0.8):
newStatement = newStatement + self.replacementB
else :
newStatement = newStatement + self.replacementC
else :
newStatement = newStatement + self.statement[index]
self.statement = newStatement
print self.statement

def createWidgets(self):
#self.quitButton = Button(self, text="QUIT", command=self.quit)
#self.quitButton.pack(side=BOTTOM, fill=BOTH)
self.draw = Canvas(self, width=800, height=600)
self.draw.pack(side=LEFT)
self.drawCanvas()

def drawCanvas(self):
for index in range(0,len(self.statement)):
if (self.statement[index] == "F"):
startX = self.endX
startY = self.endY
self.endX = startX + self.step*(math.cos(self.direction))
self.endY = startY + self.step*(math.sin(self.direction))
self.draw.create_line(startX,startY,self.endX,self.endY)
elif (self.statement[index] == "-"):
self.direction = self.direction - self.winkle
elif (self.statement[index] == "+"):
self.direction = self.direction + self.winkle
elif (self.statement[index] == "["):
self.stack.append(Point(self.endX, self.endY, self.direction))
elif (self.statement[index] == "]"):
oldPoint = self.stack.pop()
self.endX = oldPoint.getX()
self.endY = oldPoint.getY()
self.direction = oldPoint.getDirection()




app = RandomTree()
app.master.title("RandomTree (LS)")
app.mainloop()

.png)
发表于 @ 2007年01月26日 10:31:00|评论(loading...)|编辑