Rayman的专栏

MSN: fyzhao2004@hotmail.com

原创 LS文法构图算法(4) 分形树收藏

新一篇: “我的”XFree86 | 旧一篇: LS文法构图算法(3) Hilbert-Peano曲线

        分形树的基本分形元如下图所示,用比较简单的单规则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()
 
        分形树还可以再复杂一点,在上面的例子中,替换规则被指定为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()

 

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

新一篇: “我的”XFree86 | 旧一篇: LS文法构图算法(3) Hilbert-Peano曲线

评论

#wuhao09112003 发表于2007-02-10 21:40:05  IP: 221.6.143.*
第二棵树模拟的真好!
#flushtime 发表于2007-04-28 02:02:28  IP: 221.238.245.*
这一系列的文章写的很不错,赞一个~
楼主还会继续写下去么?
发表评论  


当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
Csdn Blog version 3.1a
Copyright © 赵凤阳