一、问题描述

分形通常被定义为“一个粗糙或零碎的几何形状,可以分成数个部分,且每一部分都(至少近似地)是整体缩小后的形状”。分形树则顾名思义——亦即理论上无论放大多少倍,都具有相同形状。

(以下图形均由turtle库绘制)

2 Python 分形 python 分形树问题_2 Python 分形

二、问题分析

因为分形树每个部分都具有相同形状,因而我们可以从最基本的情况开始考虑,亦即当树只有一层分枝时。可以定义一个函数tree_1(),用turtle画出一层分枝的树并回到树根处。于是可以很显然的想到两层分枝时的绘制,可以定义一个函数tree_2(),在第一次的分枝末段调用tree_1()来画出第二层分枝。同理可以定义tree_3(),同时在第一次分枝末段调用tree_2()来画出第二、三层分枝。于是每画到倒数第n层树枝末段时,调用函数tree_n-1(),直到n = 1。由此易知定义tree(n),通过递归实现分形树的绘制。

2 Python 分形 python 分形树问题_几何学_02

三、算法设计

import turtle

t = turtle

tree_1()、tree_2()、tree_3()

def tree_1(lent=15):
    """绘制一层分枝分形树"""
    t.forward(lent + 20)    # 树干比树枝长20
    t.right(30)
    t.forward(lent)
    t.backward(lent)
    t.left(60)
    t.forward(lent)
    t.backward(lent)
    t.right(30)
    t.backward(lent + 20)    # 回到树根处


def tree_2(lent=55):
    """绘制两层分枝分形树"""
    t.forward(lent + 20)
    t.right(30)
    tree_1()    # 末段调用一层分形树的绘制
    t.left(60)
    tree_1()    # 再次调用
    t.right(30)
    t.backward(lent + 20)    # 回到树根处


def tree_3(lent=75):
    """绘制三层分枝分形树"""
    t.forward(lent + 20)
    t.right(30)
    tree_2()    # 末段调用两层分形树的绘制
    t.left(60)
    tree_2()    # 再次调用
    t.right(30)
    t.backward(lent + 20)    # 回到树根处

tree()

def tree(lent):
    """递归绘制分形树"""
    if lent == 15:  # 直到下一层为一层分枝分形树
        t.forward(lent + 20)
        t.right(30)
        t.forward(lent)
        t.backward(lent)
        t.left(60)
        t.forward(lent)
        t.backward(lent)
        t.right(30)
        t.backward(lent + 20)
    else:
        t.forward(lent + 20)
        t.right(30)
        tree(lent)  # 调用倒数下一层树的绘制
        t.left(60)
        tree(lent)   # 再次调用
        t.right(30)
        t.backward(lent + 20)

然而对于上述tree()函数,最顶层分枝实际上并没有画出下一层分枝(理论上有),再注意到,当tree(lent)不被调用时,该层分枝满足else下的方法,于是可以对tree()函数进行优化,同时将角度ang,主树干长度,树枝树干长度差均设为参数。

def tree(lent, ang=30, dif=20):
    """递归绘制分形树"""
    if lent > 0:
        t.forward(lent)
        t.right(ang)
        tree(lent - dif)
        t.left(2 * ang)
        tree(lent - dif)
        t.right(ang)
        t.backward(lent)
    else:
        print("done")

四、完整程序

import turtle
import random

t = turtle
t.color('brown')
t.left(90)
t.penup()
t.goto(0, -300)
t.pendown()
t.speed(999)


def tree(lent, dif=15):
    """递归绘制分形树"""
    ang = random.randint(18, 36)    # 随机角度使树更加真实
    if lent > 0:
        t.width(lent//10)
        t.forward(lent)
        t.right(ang)
        tree(lent - dif)
        t.left(2 * ang)
        tree(lent - dif + 8)
        if lent - dif <= 0:
            t.color('pink')
            t.dot(20)
            t.color('brown')
        t.right(ang)
        t.backward(lent)
    else:
        pass


tree(120)
t.done()

五、运行结果

2 Python 分形 python 分形树问题_几何学_03