IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> 如何画一棵树 -> 正文阅读

[Python知识库]如何画一棵树

画一棵树

从一个树枝开始,分叉向两端(或者更多端),然后继续从新的树枝进行分叉,…

while True:
    树枝 = 树枝.分叉

如果不限制,树可以一直这么长下去…

请添加图片描述

最后会长成这样:(限制了分叉层数)

请添加图片描述

对颜色等参数进行一些改变,就可以得到不同的树:

请添加图片描述
请添加图片描述

好了,我们已经知道树的生长原理了,现在让我们把这个过程画出来。

turtle 海龟绘图

turtle是Python内置的一个画图库,使用tkinter实现基本图形界面。

它的方法就是用一只海龟作为画笔在屏幕绘图。

更多方法参考标准库中turtle一节。

这里用一个画正方形的例子演示turtle用法:

import turtle       # 首先导入turtle库

p = turtle.Turtle() # 初始化画笔p
p.speed(1)          # 设置速度为1,最慢。
for i in range(4):  
    p.forward(300)  # 画笔向前移动300像素点
    p.right(90)     # 画笔角度右转90度。

turtle.mainloop()   #启动绘图。

(注:画笔初始方向朝右)

turtle自带了一些示例,我们可以在命令行输入python -m turtledemo 查看
示例包括特殊图形、噪声、时钟、混色器、森林、分形曲线、nim游戏、画笔、彩虹、penrose、星球、球、三角、排序模拟、树、上下画布、太极图。

请添加图片描述里面有很多例子,可以选择。左边可以查看代码,右边点击START运行。

tree

tree为例,

下面tree的生成使用了广度优先。把当前层的树枝画完,并且把下一层的放入列表,然后递归处理下一层。

from turtle import Turtle, mainloop
from time import perf_counter as clock

def tree(plist, l, a, f):
    """ plist 笔的列表
    l 树枝长度
    a 树枝转弯角度
    f 树枝长度衰减因子
    from level to level."""
    if l > 3:
        lst = []
        for p in plist:
            p.forward(l)
            q = p.clone()
            p.left(a) #左转
            q.right(a) #右转
            lst.append(p)
            lst.append(q)
        tree(lst, l*f, a, f)


def maketree():
    p = Turtle()
    p.setundobuffer(None)
    p.hideturtle()
    p.speed(1)
    p.getscreen().tracer(10,0)
    p.left(90) #初始朝右,左转90度朝上
    p.penup()
    p.forward(-210)
    p.pendown()
    tree([p], 200, 65, 0.635)


def main():
    a=clock()
    maketree()
    b=clock()
    return "done: %.2f sec." % (b-a)

if __name__ == "__main__":
    msg = main()
    print(msg)
    mainloop()


forest

文章开始画的树示是例中的forest.

也使用了广度优先。代码比较长,就不全放了。只看关键的树的生成:

def tree(tlist, size, level, widthfactor, branchlists, angledist=10, sizedist=5):
    # benutzt Liste von turtles und Liste von Zweiglisten,
    # fuer jede turtle eine!
    if level > 0:
        lst = []
        brs = []
        for t, branchlist in list(zip(tlist,branchlists)):
            t.pensize( size * widthfactor )
            t.pencolor( 255 - (180 - 11 * level + symRandom(15)),
                        180 - 11 * level + symRandom(15),
                        0 )
            t.pendown()
            randomfd(t, size, level, angledist )
            yield 1
            for angle, sizefactor in branchlist:
                t.left(angle)
                lst.append(t.clone())
                brs.append(randomize(branchlist, angledist, sizedist))
                t.right(angle)
        for x in tree(lst, size*sizefactor, level-1, widthfactor, brs,
                      angledist, sizedist):
            yield None

原始的代码比较难懂,因为他用了yield来方便后面的交替画树。(带有yield的函数实际上是一个生成器。后面再说生成器。)

我们把yield去掉,改成常规的递归调用。这就是一个典型的广度优先遍历。和上面的tree基本一样。

def tree(tlist, size, level, widthfactor, branchlists, angledist=10, sizedist=5):
    if level > 0:
        lst = []
        brs = []
        for t, branchlist in list(zip(tlist,branchlists)):
            t.pensize( size * widthfactor )
            t.pencolor( 255 - (180 - 11 * level + symRandom(15)),
                        180 - 11 * level + symRandom(15),
                        0 )
            t.pendown()
            #树枝进行生长
            randomfd(t, size, level, angledist)
            for angle, sizefactor in branchlist:
                t.left(angle)
                lst.append(t.clone()) #做出选择,并保存
                brs.append(randomize(branchlist, angledist, sizedist))
                t.right(angle)  #back 回撤选择
        #递归处理下一层
        tree(lst, size*sizefactor, level-1, widthfactor, brs,
                      angledist, sizedist)

微调:

我们对原始代码的pensize, pencolor中的参数进行调整,就可以改变树的颜色和粗细。

RGB颜色对照表 (oschina.net)

用下面方法可以创建一棵树。可以调整参数,创建n棵数。

pen.hideturtle()
start(pen, 20, -208)
#参数: 笔(Turtle对象),线条宽度,树的层数,宽度因子,[[(树枝改变角度,宽度衰减因子)]]
t = tree( [pen], 80, level, 0.1, [[ (45,0.69), (0,0.65), (-45,0.71) ]] )

附录:

完整代码:
tree.py

from turtle import Turtle, mainloop
from time import perf_counter as clock

def tree(plist, l, a, f):
    """ plist 笔的列表
    l 树枝长度
    a 树枝转弯角度
    f 树枝长度衰减因子
    from level to level."""
    if l > 3:
        lst = []
        for p in plist:
            p.forward(l)
            q = p.clone()
            p.left(a) #左转
            q.right(a) #右转
            lst.append(p)
            lst.append(q)
        tree(lst, l*f, a, f)


def maketree():
    p = Turtle()
    p.setundobuffer(None)
    p.hideturtle()
    p.speed(1)
    p.getscreen().tracer(10,0)
    p.left(90) #初始朝右,左转90度朝上
    p.penup()
    p.forward(-210)
    p.pendown()
    tree([p], 200, 65, 0.635)


def main():
    a=clock()
    maketree()
    b=clock()
    return "done: %.2f sec." % (b-a)

if __name__ == "__main__":
    msg = main()
    print(msg)
    mainloop()

forest.py

#!/usr/bin/env python3
"""     turtlegraphics-example-suite:

             tdemo_forest.py

Displays a 'forest' of 3 breadth-first-trees
similar to the one in tree.
For further remarks see tree.py

This example is a 'breadth-first'-rewrite of
a Logo program written by Erich Neuwirth. See
http://homepage.univie.ac.at/erich.neuwirth/
"""
from turtle import Turtle, colormode, tracer, mainloop
from random import randrange
from time import perf_counter as clock

def symRandom(n):
    return randrange(-n,n+1)

def randomize( branchlist, angledist, sizedist ):
    return [ (angle+symRandom(angledist),
              sizefactor*1.01**symRandom(sizedist))
                     for angle, sizefactor in branchlist ]

def randomfd( t, distance, parts, angledist ):
    for i in range(parts):
        t.left(symRandom(angledist))
        t.forward( (1.0 * distance)/parts )

def tree(tlist, size, level, widthfactor, branchlists, angledist=10, sizedist=5):
    # benutzt Liste von turtles und Liste von Zweiglisten,
    # fuer jede turtle eine!
    if level > 0:
        lst = []
        brs = []
        for t, branchlist in list(zip(tlist,branchlists)):
            t.pensize( size * widthfactor )
            t.pencolor( 255 - (180 - 11 * level + symRandom(15)),
                        180 - 11 * level + symRandom(15),
                        0 )
            t.pendown()
            randomfd(t, size, level, angledist )
            yield 1
            for angle, sizefactor in branchlist:
                t.left(angle)
                lst.append(t.clone())
                brs.append(randomize(branchlist, angledist, sizedist))
                t.right(angle)
        for x in tree(lst, size*sizefactor, level-1, widthfactor, brs,
                      angledist, sizedist):
            yield None


def start(t,x,y):
    colormode(255)
    t.reset()
    t.speed(0)
    t.hideturtle()
    t.left(90)
    t.penup()
    t.setpos(x,y)
    t.pendown()

def doit1(level, pen):
    pen.hideturtle()
    start(pen, 20, -208)
    t = tree( [pen], 80, level, 0.1, [[ (45,0.69), (0,0.65), (-45,0.71) ]] )
    return t

def doit2(level, pen):
    pen.hideturtle()
    start(pen, -135, -130)
    t = tree( [pen], 120, level, 0.1, [[ (45,0.69), (-45,0.71) ]] )
    return t

def doit3(level, pen):
    pen.hideturtle()
    start(pen, 190, -90)
    t = tree( [pen], 100, level, 0.1, [[ (45,0.7), (0,0.72), (-45,0.65) ]] )
    return t

# Hier 3 Baumgeneratoren:
def main():
    p = Turtle()
    p.ht()
    tracer(75,0)
    u = doit1(6, Turtle(undobuffersize=1))
    s = doit2(7, Turtle(undobuffersize=1))
    t = doit3(5, Turtle(undobuffersize=1))
    a = clock()
    while True:
        done = 0
        for b in u,s,t:
            try:
                b.__next__()
            except:
                done += 1
        if done == 3:
            break

    tracer(1,10)
    b = clock()
    return "runtime: %.2f sec." % (b-a)

if __name__ == '__main__':
    run_time = main()
    print(run_time)
    mainloop()

修改后的forest,去掉了yield

#!/usr/bin/env python3
"""     turtlegraphics-example-suite:

             tdemo_forest.py

Displays a 'forest' of 3 breadth-first-trees
similar to the one in tree.
For further remarks see tree.py

This example is a 'breadth-first'-rewrite of
a Logo program written by Erich Neuwirth. See
http://homepage.univie.ac.at/erich.neuwirth/
"""
from turtle import Turtle, colormode, tracer, mainloop
from random import randrange
from time import perf_counter as clock


def symRandom(n):
    return randrange(-n, n + 1)


def randomize(branchlist, angledist, sizedist):
    return [(angle + symRandom(angledist),
             sizefactor * 1.01 ** symRandom(sizedist))
            for angle, sizefactor in branchlist]


def randomfd(t, distance, parts, angledist):
    for i in range(parts):
        t.left(symRandom(angledist))
        t.forward((1.0 * distance) / parts)


def tree(tlist, size, level, widthfactor, branchlists, angledist=10, sizedist=5):
    if level > 0:
        lst = []
        brs = []
        for t, branchlist in list(zip(tlist, branchlists)):
            t.pensize(size * widthfactor)
            t.pencolor(255 - (180 - 11 * level + symRandom(15)),
                       180 - 11 * level + symRandom(15),
                       0)
            t.pendown()
            # 树枝进行生长
            randomfd(t, size, level, angledist)
            for angle, sizefactor in branchlist:
                t.left(angle)
                lst.append(t.clone())  # 做出选择,并保存
                brs.append(randomize(branchlist, angledist, sizedist))
                t.right(angle)  # back 回撤选择
        # 递归处理下一层
        tree(lst, size * sizefactor, level - 1, widthfactor, brs,
             angledist, sizedist)


def start(t, x, y):
    colormode(255)
    t.reset()
    t.speed(0)
    t.hideturtle()
    t.left(90)
    t.penup()
    t.setpos(x, y)
    t.pendown()


def doit1(level, pen):
    pen.hideturtle()
    start(pen, 20, -208)
    t = tree([pen], 80, level, 0.1, [[(45, 0.69), (0, 0.65), (-45, 0.71)]])
    return t


def doit2(level, pen):
    pen.hideturtle()
    start(pen, -135, -130)
    t = tree([pen], 120, level, 0.1, [[(45, 0.69), (-45, 0.71)]])
    return t


def doit3(level, pen):
    pen.hideturtle()
    start(pen, 190, -90)
    t = tree([pen], 100, level, 0.1, [[(45, 0.7), (0, 0.72), (-45, 0.65)]])
    return t


# Hier 3 Baumgeneratoren:
def main():
    a = clock()
    p = Turtle()
    p.ht()
    tracer(75, 0)
    u = doit1(6, Turtle(undobuffersize=1))
    s = doit2(7, Turtle(undobuffersize=1))
    t = doit3(5, Turtle(undobuffersize=1))
    b = clock()
    return "runtime: %.2f sec." % (b - a)


if __name__ == '__main__':
    run_time = main()
    print(run_time)
    mainloop()

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-05-27 17:17:41  更:2022-05-27 17:18:55 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/27 16:20:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计