上一篇我们介绍了一种手绘玫瑰的方法,你当然也可以用类似的方法画一朵或者几朵樱花 咯,看你的艺术底子了。
不过今天我们用优美的数学方法来画樱花,也会很漂亮的。
先画朵太阳花暖暖身吧。
import turtle # 导入海龟作图函数库
from mylib.myflowers import * # 导入自定义的画花函数库
tt = turtle.Turtle() # 产生一个海龟,名叫tt
sunflower(tt,"orange") # 调用自定义的画太阳花的函数
tt.hideturtle() # 隐藏海龟箭头
turtle.done() # 画画结束
画出来的效果是这样的:
哇,这么有格局的太阳花,也只要五六行代码么?哦哦,没那么简单,我们只是把画花的部分自定义了一个函数sunflower( ),并且把它放到了另外一个文件里而已。注意到这句话了吗:
from mylib.myflowers import *
它的意思就是从mylib.myflowers模块里,导入自定义的画花函数库。这个模块是一个名为myflowers.py文件,放在mylib目录下,如下图所示:
这是在Pycharm里面的项目目录结构,其它平台上可能有所不同。并且,myflowers.py还用到了mymath.py,后者定义了最大公约数和最小公倍数怎么算(不要觉得脑壳疼,这是小学数学的内容而已喔)。这两个文件的源代码,请见本文附录,里面的数学公式看不懂略过亦无妨。
为什么要用到这些数学知识呢?因为我们是用一种叫做hypotrochoid(内转轨迹线)的方法在画图。名字很拗口,其实就是用一个小圈套在大圈里滚动作图而已。若有兴趣探究一下可以看看这个网站(Hypotrochoid)。
通过调整公式和参数,可以得到不同的轨迹线,也就可以组合出各种“花”来了。
下面我们画樱花,也是用到这种线中的一类,叫“玫瑰线”,名字好听一点吧?主程序如下:
import turtle
from random import *
from mylib.myflowers import * # 导入自定义的画花的函数库
win = turtle.Screen()
win.bgcolor('#8A5370') # 背景设为深紫色
tt = turtle.Turtle()
color_table = ['#EBD6D9', '#C46C98', '#DB91B2']
size_table = [1, 1, 1, 1, 2, 2, 2, 3, 4]
N = 25 # 一共画N朵樱花
for i in range(N):
size = size_table[randint(0,len(size_table)-1)] # 随机选择一种花瓣大小
color = color_table[randint(0,len(color_table)-1)] # 随机选择一种花瓣颜色
angle = pi * random() # 随机选择花瓣方向
x0 = randint(0, 600) - 300 # 随机选择位置横坐标
y0 = randint(0, 600) - 300 # 随机位置纵坐标
sakura(tt, size, x0, y0, angle, color, 'fastest') # 调用自定义画花函数库中的"樱花"函数
tt.hideturtle() # 隐藏海龟箭头
turtle.done()
同样,我们用到了自定义画花函数模块中的一个函数,叫sakura( ),使用了很多参数,因为我们要画好多樱花,每一朵的位置、大小、方向、颜色都是随机产生的。这样更真实嘛!Python落樱图https://www.zhihu.com/video/1239311228306190336
好了,这就是我们今天画的“落樱图”。哈哈,我的艺术水平就止步于此了,看看你有没有更好的创意吧?
动手练习:拷贝或到下面的github网址下载源代码,放到你的编程平台上,注意两个函数库模块文件,要保持原来的目录结构。调试运行无误。
随意调节myflowers.py文件中sunflower( )函数中的r、R、d三个参数,看看你会得到什么样不同的“花”。
自己写代码,画一个五角星,并填上金色。(提示:你可以Google搜索“Python五角星”找现成的代码加以改造,或者完全自己写——例如画五条线段,每次转弯144度,或者严谨一点,画十条线段,转弯方法你得琢磨一下。)
Python自然学习法全部源代码网址:
这里是《简单又好玩的Python》,欢迎关注。
附录一:myflowers.py源代码
from math import *
from mylib.mymath import * # 导入自定义的数学函数库
# 自定义太阳花函数
def sunflower(tt, color = 'orange'):
r = 25
R = 120
d = 50
tt.penup()
tt.color(color)
tt.pensize("2")
tt.begin_fill()
theta = 0
while theta <= 2 * pi * least_common_multiple(r, R)/R + 0.01: # 多画0.01弧度避免有缺陷
x = (R-r) * cos(theta) + d * cos((R - r) / r * theta)
y = (R-r) * sin(theta) - d * sin((R - r) / r * theta)
tt.goto(x, y)
tt.pendown()
theta += pi/100
tt.end_fill()
# 自定义樱花函数
def sakura(tt, size = 3, x0 = 0, y0 = 0, angle = 0, color ='#EBD6D9', speed = 'fastest'):
# 画花瓣
p = 5
q = 3
R = size * 15
tt.penup()
tt.color(color)
tt.pensize("2")
tt.begin_fill()
tt.speed(speed)
theta = 0
while theta <= pi * q + 0.01: # 多画0.01弧度避免缺陷
x = R * cos(p / q * theta + angle) * cos(theta + angle) + x0
y = R * cos(p / q * theta + angle) * sin(theta + angle) + y0
tt.goto(x, y)
tt.pendown()
theta += pi/R
tt.penup()
tt.end_fill()
# 画花蕊
tt.color('#B17085')
tt.begin_fill()
r = size
R = size * 5
d = r * 1.3
angle = angle * pi/5
theta = 0
while theta <= 2 * pi * least_common_multiple(r, R) / R + 0.01: # 多画0.01弧度避免有缺陷
x = (R - r) * cos(theta + angle) + d * cos((R - r) / r * theta + angle) + x0
y = (R - r) * sin(theta + angle) - d * sin((R - r) / r * theta + angle) + y0
tt.goto(x, y)
tt.pendown()
theta += pi / R
tt.end_fill()
tt.penup()
if __name__ == '__main__': # 测试用,仅在本文件为主程序时,才会执行下面的代码
import turtle
tt = turtle.Turtle()
sunflower(tt,'orange')
win = turtle.Screen()
win.bgcolor('#8A5370')
sakura(tt, 3, 0, 0, 0, "pink", 'fastest')
tt.hideturtle()
turtle.done()
附录二:mymath.py源代码
def greatest_common_divisor(m,n):
while m!=n:
if m > n :
m = m - n
else:
n = n - m
return m
def least_common_multiple(m,n):
return m * n // greatest_common_divisor(m,n)
if __name__ == "__main__" :
m,n = eval(input('请输入两个正整数(逗号隔开):'))
print('m =',m, ', n =',n)
print('它们的最大公约数是:', greatest_common_divisor(m,n))
print('它们的最小公倍数是:', least_common_multiple(m,n))