Python Turtle Drawing - Fractal, Recursion and Recursive Algorithm (Part 2)

    The last part ( Python Turtle Drawing - Fractal, Recursion and Recursive Algorithms (Part 1) ) introduces the use of fractal theory and recursive functions to draw fractal trees with Python's turtle. Similar and completely symmetrical, relatively rigid. It is necessary to add random number perturbation to the trunk, branch length, and random number perturbation to the angle between branches, which is more like a natural tree.

    Before talking about the trunk, branch length, branch angle and random number disturbance, let's draw a cedar tree (Christmas tree).

4. Python draws a fractal tree that forks downwards - cedar tree (Christmas tree)

    If the bifurcation of the binary tree is 120°, the branches hang down, just like a cedar tree. Finally, the trunk is drawn with an isosceles triangle with a vertex angle of 2°.

    Let the waist length of the triangle be l, then the base length is d=2lsin(1°)≈2πl/180

    Python uses turtle to draw cedar tree (Christmas tree) program code as follows:

#############################################
# 设计 Zhang Ruilin   创建 2021-12-05 12:55 #
# 用分形理论+递归,turtle绘制雪松树(圣诞树) #
#############################################
import turtle as tl
import random

n=100.0

def tree(d, s): 				# 递归画树、树枝
    if d <=0: return 
    tl.fd(s) 					# 画树干
    tree(d-1, s*.8) 				# 在树干上画树枝
    tl.rt(120)
    tree(d-3,s*.5) 			 	# 向右下方在树干上画树枝
    tl.rt(120) 
    tree(d-3,s*.5) 			 	# 向左下方在树干上画树枝
    tl.rt(120) 
    tl.bk(s) 			 		# 返回上层分叉点
    
tl.speed('fastest')
tl.screensize(bg='lightyellow')
tl.ht()						# 隐藏海龟形状,可加快绘图速度
tl.lt(90)					# 方向向上
tl.fd(2.5 * n)
tl.color('orange', 'yellow')			# 画笔橘红色、填充黄颜色
tl.begin_fill()
tl.lt(126)
for i in range(5):				# 画橘红色边黄颜色五角星
    tl.fd(n/5) 
    tl.rt(144) 
    tl.fd(n/5) 
    tl.lt(72) 
tl.end_fill()
tl.rt(126)					# 方向向上
tl.color('dark green') 
tl.bk(n * 4.8) 

tree(15,n)					# 画树
tl.bk(n/2)
tl.begin_fill()					# 画树干(顶角2°的等腰三角形)
tl.fd(n * 5.3)
tl.lt(179)
tl.fd(n * 5.3)
tl.lt(91)
tl.fd(2 * n * 5.3 * 3.141592654 / 180)		# 角度较小时的sin近似算法
tl.lt(91)
tl.fd(n * 5.3)
tl.end_fill()
tl.up()
tl.lt(180)
tl.fd(n * 5.3)
tl.rt(91)
tl.fd(4 * n * 5.3 * 3.141592654 / 180)
tl.rt(91)
tl.fd(n * 5.3)
tl.rt(179)
tl.fd(n * 5.3)

a = 200
b = 40
for i in range(200):				# 画小礼物
    x = a - 2 * a * random.random() 
    y = b - 2 * b * random.random()
    if x*x/a/a+y*y/b/b <= 1:			# 2a、2b的sbe椭圆范围内
        tl.up()
        tl.fd(y) 
        tl.lt(90) 
        tl.fd(x) 
        tl.pd()
        if random.randint(0, 1) == 0:
            tl.color( 'violet' )
        else:
            tl.color( 'orange' )
        tl.dot(8)
        tl.up()
        tl.bk(x) 
        tl.rt(90) 
        tl.bk(y) 

tl.done()

    The running result is shown in Figure 1.

 Figure 1 Cedar tree (Christmas tree)

5. Python draws peach trees that have germinated and bloomed with peach blossoms

    Based on the previous article, this article adds random number disturbances to the branch length and fork angle. In order to avoid the branch being too long, the recursion depth is controlled by the branch length and branch thickness (the condition for ending the recursion).

    In Python, the random() function of the random module can be used to generate a random number of [0, 1), including 0 but not 1. Length The length of each recursion is shortened by 0~30% (length=length*(1-0.3*random())), the bifurcation angle changes between 0~120% (ang= ang *1.2*random()), bifurcation An angle of 0 means no bifurcation. The randint(a, b) function generates a random integer of [a, b], including a and b.

    Peach trees bloom first and then grow leaves. When blooming, the leaves are only leaf buds of about 1 or 2 centimeters.

    Python uses turtle to draw peach trees that have germinated and bloomed with peach blossoms. The program code is as follows:

##############################################
# 设计 Zhang Ruilin    创建 2021-12-04 20:45 #
# 用分形理论+递归,turtle 绘制开着桃花的桃树 #
##############################################
import turtle as tl
import random

tl.setup(600, 600)					# 定义窗体大小
tl.speed(0)
tl.ht()							# 隐藏画笔形状

def draw_branches(tree_length, tree_size, tree_angle):	# 画桃树的躯干枝叶和花
    if tree_length > 3 and tree_size > 1:
        if 8 <= tree_length <= 12:
            k = random.randint(0, 4)
            if k == 0:					# 20%画浅色桃花
                tl.color('mistyrose')			# 薄雾玫瑰色
            elif k == 1 or  k == 2:			# 40%画树叶
                tl.color('green')			# 绿色
            else:					# 40%画深色桃花
                tl.color('pink')			# 粉色(桃红)
            tl.pensize(tree_length / 3)
        elif tree_length < 8:
            if random.randint(0, 1) == 0:
                tl.color('mistyrose')			# 薄雾玫瑰色
            else:
                tl.color('pink')			# 粉色(桃红)
            tl.pensize(tree_length / 2)
        else:
            tl.color('brown')				# 综色
            tl.pensize(tree_size)
        if tl.color()[0] == 'green':			# 画叶子
            if tree_length >=5:
                for _ in range(int(tree_length+0.5)):
                    tl.pensize(tree_length/2 -_*(tree_length/2-1)/tree_length)
                    tl.fd(1)
            else:
                tl.pensize(3)
                tl.fd(int(tree_length/2))
                tl.pensize(1)
                tl.fd(tree_length-int(tree_length/2))
        else:						# 画树枝或花朵
            tl.fd(tree_length)
        a = 1.2 * random.random()
        b = random.random()
        tl.rt(tree_angle * a)
        draw_branches(tree_length * (1-0.3*b), tree_size * 0.85, tree_angle)
        tl.lt(2 * tree_angle * a)
        draw_branches(tree_length * (1-0.3*b), tree_size * 0.85, tree_angle)
        tl.rt(tree_angle * a)
        tl.up()
        tl.bk(tree_length)
        tl.pd()

if __name__ == '__main__':
    tl.getscreen().tracer(5, 0)				# 设置海龟动画更新及延迟,加快绘图
    tl.screensize(bg='honeydew')			# 蜜瓜色(白淡绿色)
    tl.lt(90)						# 方向向上(12点方向)
    tl.up()
    tl.bk(200)						# 移动到树干起始位置
    tree_length = 70					# 设置的树干树枝初始长度
    tree_size = 6					# 设置的树干树枝初始粗细
    tree_angle = 25					# 设置基准树枝分叉角度
    tl.pd()
    tl.color('brown')					# 树干部分为棕色
    draw_branches(tree_length, tree_size, tree_angle)	# 启动绘图
    tl.exitonclick()					# 单击鼠标左键退出
    tl.done()						# 结束时保持图形窗体

    The running result is shown in Figure 2.

 Figure 2 A peach tree that has germinated and bloomed

    In order to avoid too long branches in the program, the recursion depth is controlled by the length of the branches and the thickness of the branches:

    tree_length> 3 and tree_size > 1

    Therefore, some branches do not meet the conditions for drawing leaves or peach blossoms, so no leaves or peach blossoms are drawn, giving people the feeling of peach blossoms withering.

    In addition, use randint(0, 4) to generate random numbers of [0, 4] five integers. The probability of each number is 20%. When the branches are not too thin, 20% draw light-colored peach blossoms, 40% draw leaf buds and 40% % Draw dark peach blossoms, when the branches are thinner, use 50% probability to draw light peach blossoms and dark peach blossoms. Since the leaf bud is very small, it is simulated with a straight line (long triangle) from thick to thin.

    What about the withered flowers? It should have fallen to the ground.

6. Python draws a peach tree with falling petals and peach blossoms

    The crown of the peach tree is roughly circular when viewed from the top, and the fallen flowers basically fall in a circular area, and it is roughly an oval area when viewed from the side. The ellipse equation is x 2 / a 2+ y 2/ b 2=1 , and the condition inside the ellipse is x 2 / a 2+ y 2/ b 2<=1 . So x is in [- aa ] and y is in [- bb ] within the rectangular area: x 2 / a 2+ y 2/ b 2<=1 , that is, within the range of the ellipse.

    Since the fallen petals will be drawn on the trunk (see Figure 1), it is necessary to draw the fallen petals first, and then draw the peach tree, so as to ensure that there are no fallen petals on the trunk. Falling petals are drawn only within the bounds of the ellipse.

    Python uses turtle to draw a peach tree with falling petals and peach blossoms. The program code is as follows:

#################################################
# 设计 Zhang Ruilin       创建 2021-12-05 07:35 #
# 用分形+递归,turtle绘制洒落花瓣开着桃花的桃树 #
#################################################
import turtle as tl
import random

tl.setup(600, 600)					# 定义窗体大小
tl.speed(0)
tl.ht()							# 隐藏画笔形状

def draw_branches(tree_length, tree_size, tree_angle):	# 画桃树的躯干枝叶和花
    if tree_length > 3 and tree_size > 1:
        if 8 <= tree_length <= 12:
            k = random.randint(0, 4)
            if k == 0:					# 20%画浅色桃花
                tl.color('mistyrose')			# 薄雾玫瑰色
            elif k == 1 or  k == 2:			# 40%画树叶
                tl.color('green')			# 绿色
            else:					# 40%画深色桃花
                tl.color('pink')			# 粉色(桃红)
            tl.pensize(tree_length / 3)
        elif tree_length < 8:
            if random.randint(0, 1) == 0:
                tl.color('mistyrose')			# 薄雾玫瑰色
            else:
                tl.color('pink')			# 粉色(桃红)
            tl.pensize(tree_length / 2)
        else:
            tl.color('brown')				# 综色
            tl.pensize(tree_size)
        if tl.color()[0] == 'green':			# 画叶子
            if tree_length >=5:
                for _ in range(int(tree_length+0.5)):
                    tl.pensize(tree_length/2 -_*(tree_length/2-1)/tree_length)
                    tl.fd(1)
            else:
                tl.pensize(3)
                tl.fd(int(tree_length/2))
                tl.pensize(1)
                tl.fd(tree_length-int(tree_length/2))
        else:						# 画树枝或花朵
            tl.fd(tree_length)
        a = 1.2 * random.random()
        b = random.random()
        tl.rt(tree_angle * a)
        draw_branches(tree_length * (1-0.3*b), tree_size * 0.85, tree_angle)
        tl.lt(2 * tree_angle * a)
        draw_branches(tree_length * (1-0.3*b), tree_size * 0.85, tree_angle)
        tl.rt(tree_angle * a)
        tl.up()
        tl.bk(tree_length)
        tl.pd()

def petals(m):						# 画掉落的花瓣
    a0 = 225
    b0 = 20
    for i in range(m):
        x = a0 - 2 * a0 * random.random()
        y = b0 - 2 * b0 * random.random()
        if x * x /a0 / a0 + y * y / b0 / b0 <= 1:	# 只画在2a、2b的椭圆中
            tl.up()
            tl.fd(y)
            tl.lt(90)
            tl.fd(x)
            tl.pd()
            tl.color('pink')				# 粉色(桃红)
            tl.dot(3)
            tl.up()
            tl.bk(x)
            tl.rt(90)
            tl.bk(y)

if __name__ == '__main__':
    tl.getscreen().tracer(5, 0)				# 设置海龟动画更新及延迟,加快绘图
    tl.screensize(bg='honeydew')			# 蜜瓜色(白淡绿色)
    tl.lt(90)						# 方向向上(12点方向)
    tl.up()
    tl.bk(200)						# 移动到树干起始位置
    tl.pd()
    petals(400)						# 以树干起始为中心画落花
    tree_length = 70					# 设置的树干树枝初始长度
    tree_size = 6					# 设置的树干树枝初始粗细
    tree_angle = 25					# 设置基准树枝分叉角度
    tl.pd()
    tl.color('brown')					# 树干部分为棕色
    draw_branches(tree_length, tree_size, tree_angle)	# 启动绘图
    tl.exitonclick()					# 单击鼠标左键退出
    tl.done()						# 结束时保持图形窗体

    The running result is shown in Figure 3.

 Figure 3 A peach tree with fallen petals and blooming peach blossoms

    Due to the use of random numbers, the peach trees drawn in each run will be different. Please see Figure 4, which is another peach tree with peach blossoms drawn at different times. Some drawings may be unsatisfactory, and you can choose to save them if you are satisfied.

 Figure 4 Peach trees with falling petals and peach blossoms generated by running at different times

Guess you like

Origin blog.csdn.net/hz_zhangrl/article/details/131017244