分形
分形,具有以非整数维形式充填空间的形态特征。通常被定义为“一个粗糙或零碎的几何形状,可以分成数个部分,且每一部分都(至少近似地)是整体缩小后的形状”,即具有自相似的性质。分形(Fractal)一词,是芒德勃罗创造出来的,其原意具有不规则、支离破碎等意义。1973年,芒德勃罗(B.B.Mandelbrot)在法兰西学院讲课时,首次提出了分维和分形的设想。
turtle模块
turtle模块时python自带的一个绘图模块,俗称海龟绘图.
方法 | 描述 | 简写 |
t=turtle.Turtle() | 新建海龟 | None |
forward(length) | 前进length个像素单位 | fd() |
backward(length) | 后退ength个像素单位 | bw() |
left(degree) | 左转degree度(角度制) | lt() |
right(degree) | 右转degree度(角度制) | rt() |
penup() | 抬笔,后续移动不会产生轨迹 | up() |
pendown() | 落笔,后续移动会产生轨迹 | down() |
goto(x,y) | 从当前位置移动到(x,y)位置 | \ |
color(color1,color2) | 将画笔颜色设置为color1,填充颜色设置为color2 | \ |
setheading(degree) | 设置海龟头朝向 | \ |
hideturtle() | 隐藏海龟 | ht() |
begin_fill() | 开始填充 | \ |
end_fill() | 结束填充 | \ |
分形的特点是放大图形的任一局部和整体具有自相似性,这个特点刚好和递归函数的性质相似,所以今天我们通过调用海龟模块使用递归函数来绘制分形图
一.餐前甜点--螺旋线
from turtle import * # 导入海龟模块
my_turtle = Turtle() # 创建海龟对象
my_win = my_turtle.getscreen() # 创建屏幕对象
def draw_spiral(my_turtle,linelen): # 定义绘制螺旋线的递归函数
if linelen > 0: # 递归边界
my_turtle.fd(linelen)
my_turtle.rt(90)
draw_spiral(my_turtle,linelen-5) # 递归调用
my_turtle.speed(10)
my_turtle.up()
my_turtle.goto(-200,200)
my_turtle.down()
draw_spiral(my_turtle,300)
my_turtle.hideturtle() # 隐藏海龟
my_win.exitonclick() # 为保证绘制完成后不自动退出,使用这个方法点击后关闭窗口
结果
是不是有点动图的眩晕感!!!
二.分形--二叉树
import random
from turtle import *
my_turtle = Turtle()
my_win = my_turtle.getscreen()
def tree(branch_len,t):
if branch_len > 5:
if branch_len <= 20:
t.pencolor('green') # 当树枝很小时,画笔绿色.模拟树叶
else:
t.pencolor('black')
t.pensize(branch_len//10) # 随着递归的进行 树枝越来越细
t.fd(branch_len)
degree = random.randint(15,30) # 随机角度
t.rt(degree)
gap = random.uniform(10,15) # 随机减少的增量
tree(branch_len-gap,t)
t.lt(2*degree)
tree(branch_len-gap, t)
t.rt(degree)
t.backward(branch_len)
my_turtle.setheading(90)
my_turtle.speed(10)
my_turtle.up()
my_turtle.backward(300)
my_turtle.down()
tree(100,my_turtle)
my_win.exitonclick()
结果
三.分形--谢尔宾斯基三角形
from turtle import *
def draw_triangle(points,color,t):
'''给定三个点绘制三角形'''
t.fillcolor(color)
t.up()
t.goto(points[0])
t.down()
t.begin_fill()
t.goto(points[1])
t.goto(points[2])
t.end_fill()
def get_mid(p1,p2):
'''求中点'''
return ((p1[0] +p2[0]) / 2,(p1[1] +p2[1]) / 2)
def sierpinski(points,depth,t):
color_map = ['black','white','yellow','red','pink','purple','orange','cyan','violet'
,'blue','green']
draw_triangle(points,color_map[depth],t)
if depth > 0: # 当递归深度大于0时,在3各小三角形中递归调用谢尔宾斯基三角形
sierpinski([points[0],get_mid(points[0],points[1]),\
get_mid(points[0],points[2])],depth-1, t)
sierpinski([points[1],get_mid(points[0],points[1]),\
get_mid(points[1],points[2])],depth-1, t)
sierpinski([points[2],get_mid(points[0],points[2]),\
get_mid(points[1],points[2])],depth-1, t)
my_turtle = Turtle()
my_turtle.speed(10)
my_win = my_turtle.getscreen()
screensize(1600,900)
my_points = [(-300,-250),(0,300),(300,-250)]
sierpinski(my_points,8,my_turtle)
my_win.exitonclick()
结果:
画了5层,绘制大概用了2分钟
四.分形山
import random
from turtle import *
# turtle.colormode(255)
my_turtle = Turtle()
my_win = my_turtle.getscreen()
def draw_triangle(points,color,t):
'''给定三个点绘制三角形'''
t.color(color)
t.up()
t.goto(points[0])
t.down()
t.begin_fill()
t.goto(points[1])
t.goto(points[2])
t.end_fill()
def mountain(t,start_x,start_y,end_x,end_y,depth,color):
y_offset = random.randint(10,30)
mid_x = (start_x + end_x) / 2
mid_y = (start_y + end_y) / 2 + y_offset
draw_triangle([(start_x,start_y),
(end_x,end_y),
(mid_x,mid_y)],color,t)
if depth > 0 :
mountain(t,start_x,start_y,mid_x,mid_y,depth-1,color)
mountain(t, mid_x, mid_y, end_x,end_y, depth - 1,color)
x1,y1,x2,y2 = -400,-50,400,-50
colors = ['#DAE0DF','#959998','#505453','#070707']
for i in range(4):
mountain(my_turtle,x1,y1-i*30,x2,y2-i*30,6,colors[i])
my_win.exitonclick()
结果
循环画了四次,但是四次的主要特征还是态明显.应该还能调整一下参数显得更真实一点
五.科赫雪花
努力求解中
六.伪希尔伯特曲线
努力求解中
参考:
百度百科:分形(几何学术语)_百度百科 (baidu.com)
布拉德利.米勒 戴维.拉努姆<<pythons数据结构与算法分析>>(第二版)第四章递归