Fork me on GitHub

利用python绘制树形图

用python绘制小树,最后图案就长这个样子



首先看见这张图发现没有什么思路,其实仔细想想,它其实是在每一个分支上又加了一个分支,如此下去,就得到了这张图。因此主要思路就是利用递归的方法。

在画图之前,我们的知道简单图形的绘制指令,例如,如何绘制线段,如何改变线段的方向,改变线段粗细,颜色等等指令。之后我们就要对树的绘制设计相应的算法。

这里,我们利用python中的turtle函数库,它是一种简单图形绘制模块,而且,它的函数指令是很形象和简单的,它绘制的坐标轴以屏幕中心为原点。接下来我们就介绍一下turtle库里的常用函数。

  • 画笔的属性
    1.turtle.pensize():设置画笔的宽度;
    2.turtle.pencolor():没有参数传入,返回当前画笔颜色,传入参数设置画笔颜色,可以是字符串如”green”, “red”,也可以是RGB 3元组。
    3.turtle.speed(speed):设置画笔移动速度,画笔绘制的速度范围[0,10]整数,数字越大越快。

  • 绘图命令

    画笔运动命令

命令 说明
turtle.forward(distance) 向当前画笔方向移动distance像素长度
turtle.backward(distance) 向当前画笔相反方向移动distance像素长度
turtle.right(degree) 顺时针移动degree°
turtle.left(degree) 逆时针移动degree°
turtle.pendown() 移动时绘制图形,缺省时也为绘制
turtle.goto(x,y) 将画笔移动到坐标为x,y的位置
turtle.penup() 提起笔移动,不绘制图形,用于另起一个地方绘制
turtle.circle() 画圆,半径为正(负),表示圆心在画笔的左边(右边)画圆
setx() 将当前x轴移动到指定位置
sety() 将当前y轴移动到指定位置
setheading(angle) 设置当前朝向为angle角度
home() 设置当前画笔位置为原点,朝向东。
dot(r) 绘制一个指定直径和颜色的圆点

画笔控制命令

命令 说明
turtle.fillcolor(colorstring) 绘制图形的填充颜色
turtle.(color1,color2) 同时设置pencolor=color1, fillcolor=color2
turtle.filling() 返回当前是否在填充状态
turtle.begin_fill() 准备开始填充图形
turtle.end_fill() 填充完成
turtle.hideturtle() 隐藏画笔的turtle形状
turtle.showturtle() 显示画笔的turtle形状

全局控制命令

命令 说明
turtle.clear() 清空turtle窗口,但是turtle的位置和状态不会改变
turtle.reset() 清空窗口,重置turtle状态为起始状态
turtle.undo() 撤销上一个turtle动作
turtle.isvisible() 返回当前turtle是否可见
stamp() 复制当前图形
turtle.write(s,[,font=(“font-name”,font_size,”font_type”)]) 写文本,s为文本内容,font是字体的参数,分别为字体名称,大小和类型;font为可选项,font参数也是可选项

其他命令

命令 说明
turtle.mainloop()或turtle.done() 启动事件循环-调用Tkinter的mainloop函数.必须是乌龟图形程序中的最后一个语句
turtle.mode(mode=None) 设置乌龟模式(“standard”,“logo”或“world”)并执行重置。如果没有给出模式,则返回当前模式
turtle.delay(delay=None) 设置或返回以毫秒为单位的绘图延迟
turtle.begin_poly() 开始记录多边形的顶点。当前的乌龟位置是多边形的第一个顶点
turtle.end_poly() 停止记录多边形的顶点。当前的乌龟位置是多边形的最后一个顶点。将与第一个顶点相连
turtle.get_poly() 返回最后记录的多边形

介绍了这么多的函数,一时间可能不能全部理解和记忆,接下来先利用上面介绍的函数做一些简单的事情。

画一个五角星


它的做法其实不难,利用上面的函数就可以轻松完成了,但是要知道,五角星的每两条线段之间的折返角度是144°就ok了。

代码

1
2
3
4
5
6
7
8
9
10
from turtle import Turtle
p = Turtle()
p.speed(2)
p.pensize(5)
p.color("black","yellow")
p.begin_fill()
for i in range(5):
p.forward(400)
p.right(144)
p.end_fill()

接下来回到我们的主题上去,我们的目的是为了绘制一个小树,观察图形,我们发现它是一个对称的图形,每一个枝杈上会以相同的角度生成更小的枝杈,之前说过,就是利用递归思想来绘图。首先给出代码。。。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
from turtle import Turtle
def tree(plist,l,a,f):
if l>5:
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(x,y):
p=Turtle()
p.color("green")
p.pensize(5)
p.hideturtle()
p.speed(10)
p.left(90)
p.penup()
p.goto(x,y)
p.pendown()
t=tree([p],200,65,0.6375)
print(len(p.getscreen().turtles()))
def main():
maketree(-200,-200)
maketree(0,0)
maketree(200,-200)
main()

其中tree()函数中,plist是一个存放函数对象的列表,l是树枝的长度,a是画笔调整角度,f是下一层枝杈长度与上层枝杈长度的比例,clone()是为了将左边的图形克隆到右边,将原对象向左旋转角度a,将克隆对象向右旋转角度a,然后将两个对象放在slt列表的最后,用于进行下一次枝杈绘制的递归调用。这种思想也是一种广度优先绘制法。然后在递归调用时,下一层枝杈长度为l*f,下一层枝杈的长度以f的比例缩短。

这里在主函数中绘制了三棵小树,起始坐标分别是(-200,-200),(0,0),(200,-200)。

turtle库是一个很有意思的函数库,之前还绘制了蟒蛇图案

其代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import turtle
def drawSnake(rad,angle,len,neckrad):
for i in range(len):
turtle.circle(rad,angle)
turtle.circle(-rad,angle)
turtle.circle(rad,angle/2)
turtle.fd(rad)
turtle.circle(neckrad+2,180)
turtle.fd(rad*2/3)
def main():
turtle.setup(1300,800,0,0)
pythonsize = 30
turtle.pensize(pythonsize)
turtle.pencolor("blue")
turtle.seth(-40)
drawSnake(40,80,5,pythonsize/2)
main()

加油,python不难!

-------------本文结束感谢您的阅读-------------
obsidian wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!
坚持原创技术分享,您的支持是我最大的动力!