本章绘图要点:

  • turtle模块:python标准库自带的一个模块,可用来绘制二维图形。该模块封装了底层的数据处理逻辑,向外提供了更符合手工绘图习惯的接口函数,适用于绘制对质量、精度要求不高的图形。
  • 递归:当所绘制的图形需要多次嵌套重复计算时,可采用递归策略降低程序的复杂性,减少程序的代码量。

海岸线

独上高原,眺望沧海,海洋与陆地之间,蜿蜒而行的海岸线有多长呢?这个问题似乎很简单。按照传统的几何和数学观点,有形状的东西应该都可以被测量。例如,我们可以通过尺子来测量方桌的长和宽,从而获得它的周长。而海岸线虽曲折,但只要测量足够精确,应该就可以得到一个具体的长度。但是问题在于,当用不同大小的度量标准来测量时,每次都会得出完全不同的结果。度量标准的尺度越小,测量出的海岸线长度就会越长,以至于无穷。以1km为单位测量海岸线时,近似长度短于1km的迂回曲折线就会被忽略掉,而以1m为单位测量时,则能测出这些被忽略掉的迂回曲折,长度将变大。以此类推,测量单位越小,测得的长度将越大,这些越来越大的长度并不是趋近于一个确定值,而是会无限增大,所以海岸线的长度是不确定的,或者说,在一定意义上海岸线的长度是无穷的。

为什么会这样呢?这是因为作为海洋与陆地的分界线,海岸线的形状是极不规则、极不光滑的。海岸线由无数的曲线组成,假设我们用一把固定长度的直尺,例如米尺来测量的话,海岸线上两点间小于一米的曲线,就只能用直线来近似地表示,因此,测得的长度肯定是不精确的。使用更短的尺子来量,同样也无法测量更细小的曲线。哪怕我们有一把1纳米长(1纳米大约是1米的10亿分之一)的尺子,情况依旧如此。长度也许已不能正确地概括海岸线这类不规则图形的特征。

海岸线虽然很复杂,但是却有一个重要的性质——自相似性。从不同比例尺的地形图上,我们可以看出海岸线的形状大体相同,其曲折、复杂程度也很相似,也就是说,海岸线的任一小部分都包含有与整体相同或相似的细节。如果将一段海岸线的曲线加以放大,我们会发现,这部分放大的曲线(我们称之为A曲线)与更大范围内的海岸线形状惊人地相似。如果继续放大A曲线中更小的一段,这一小段曲线的形状又与A曲线有相似性。换句话说,任意一段海岸线就象是整个海岸线按比例缩小的结果。

科赫(Koch)曲线

我们可以在计算机上生成科赫曲线来模拟海岸线。科赫曲线是瑞典数学家科赫在1904年提出的一种不规则的几何图形。它的生成方法是把一条直线等分成三段,将中间的一段用夹角为60度的两条等长折线来替代,形成一个生成元,然后再把每个直线段都用生成元来进行替换,如此经过无穷多次迭代后就呈现出了一条有无穷多弯曲的科赫曲线。如图所示:

第一次迭代(生成元):

第二次迭代:

第三次迭代:

第六次迭代:

可以看到多次迭代后的科赫曲线由无数的曲线组成。与海岸线一样,科赫曲线的局部与整体相似,也就是说,局部是整体的缩影。

算法

我们可以在计算机上用以下方法递归生成Koch曲线:

将线段三等分,描画完第一个三分之一段后逆时针方向旋转60度,接着描画三分之一段长度,再顺时针方向旋转120度,描画三分之一段长度,再逆时针方向旋转60度,描画最后三分之一段长度。

结合上图就是:

1)       初始:起始点A,角度为0;假设线段AB长度为L;

2)       线段三等分,每一段长度为L/3,从点A开始,向前描画L/3长度到达C点;

3)       逆时针方向(也就是向左)旋转60度,向前描画L/3长度,到达D点;

4)       顺时针方向(也就是向右)旋转120度,向前描画L/3长度,到达E点;

5)       逆时针方向(也就是向左)旋转60度,向前描画L/3长度,到达结束点:B点。

源码

 1 # 导入模块
2 import turtle
3
4 # 恢复海龟状态到p点
5 def restore(p):
6 turtle.penup() # 抬起海龟画笔
7 turtle.setpos(p[0],p[1]) # 移动到p点
8 turtle.pendown() # 放下画笔
9 turtle.seth(p[2]) # 设置海龟方向
10
11 # 获取海龟当前点状态
12 def get_point():
13 x,y = turtle.pos() # 获取海龟的位置
14 d = turtle.heading() # 获取海龟的方向
15 return (x,y,d)
16
17 # 生成器函数,A为起始点,B为结束点,L为线段AB的长度,n为递归次数
18 def Generator(A,B,L,n):
19 if n == 1:
20 # 绘制图形
21 restore(A)
22 turtle.forward(L/3) # 画笔向前移动L/3距离
23 turtle.left(60) # 画笔方向向左旋转60度(也就是逆时针旋转)
24 turtle.forward(L/3)
25 turtle.right(120) # 向右旋转120度(也就是顺时针旋转)
26 turtle.forward(L/3)
27 turtle.left(60)
28 turtle.setpos(B[0],B[1]) # 移动到B点,并画线
29 else:
30 # 获取中间点:C、D、E的位置和方向,不显示图形
31 restore(A)
32 turtle.pencolor((59,209,207)) # 画笔颜色设置和背景色相同
33 turtle.forward(L/3)
34 turtle.left(60)
35 C = get_point()
36 turtle.forward(L/3)
37 turtle.right(120)
38 D = get_point()
39 turtle.forward(L/3)
40 turtle.left(60)
41 E = get_point()
42 turtle.pencolor('white') # 画笔颜色设置为白色
43
44 # 递归调用生成器,使用生成元替换线段AC、CD、DE、EB
45 Generator(A,C,L/3,n-1)
46 Generator(C,D,L/3,n-1)
47 Generator(D,E,L/3,n-1)
48 Generator(E,B,L/3,n-1)
49
50 return True
51
52 # 开始主程序
53 if __name__ == '__main__':
54 # 隐藏画笔形状
55 turtle.hideturtle()
56 # 设置颜色模式
57 turtle.colormode(255)
58 # 设置背景色为海蓝色
59 turtle.bgcolor((59,209,207))
60 # 设置画笔颜色为白色
61 turtle.pencolor('white')
62 # 设置画笔大小
63 turtle.pensize(2)
64
65 # 设置初始值
66 A = (-450,0,0)
67 B = (450,0,0)
68 L = 900
69 n = 6
70
71 # 生成科赫曲线
72 restore(A)
73 Generator(A,B,L,n)
 

科赫曲线彩图(海蓝色RGB(59,209,207)/白色)

程序剖析

turtle模块

turtle模块是python标准库自带的一个模块,用于绘制二维图形。在使用之前,需要使用import turtle语句导入该模块。

turtle在英文中的含义是海龟,想象一下,在画布的中间,有一只海龟,四处行走,走过的痕迹就绘成了图形。在画布中,海龟的位置是以二维笛卡尔坐标的方式来确定的,也就是x-y轴坐标,如下图:

海龟的初始位置在原点(0,0)处。海龟的状态除了位置以外,还有一个方向,方向以与水平的角度来确定,逆时针的角度为正数,顺时针的角度为负数。海龟的初始方向为0,也就是在原点上,向右朝向x正轴。

所以,海龟的状态可以用一个三元组(x,y,d)来表示,x和y分别代表横坐标和纵坐标,d代表方向。

以下列出了程序中所用到的turtle模块函数:

turtle.hideturtle() # 海龟画笔是有形状的,如果只想看到绘制的图形,可以使用该函数把画笔的形状隐藏起来

turtle.setpos(x,y)  # 移动海龟到指定位置,

使用turtle.setpos(x,y)改变海龟的位置,默认情况会在画布上留下痕迹,也就是一条直线。要想不留下痕迹,就必须把海龟画笔抬起来,函数是:turtle.penup(),到达指定位置后,把画笔放下来,函数是:turtle.pendown()。

turtle.seth(angle)# 海龟方向旋转angle度,这个角度是相对于水平x正轴的,和海龟当前的方向无关

angle为正数,逆时针旋转;angle为负数,顺时针旋转

turtle.pos() # 获取海龟的坐标位置

turtle.heading() # 获取海龟的方向

turtle.pensize(width) # 指定画笔的大小,参数width为一个正整数

turtle.pencolor(color)# 指定画笔的颜色

turtle.bgcolor(color) # 指定画布背景的颜色

pencolor()和bgcolor()函数的参数color可以是字符串,如“red“,”yellow”,“white”等,也可以是一个RGB数字,如(255,255,0),但是,在使用RGB数字前,必须调用colormode()函数指定颜色的模式:

turtle.colormode(255) # 指定颜色的色彩取值范围为0-255的整数

turtle.forward(distance) # 画笔向前移动distance距离

turtle.left(angle)  # 海龟的方向向左旋转angle度,这个角度angle是相对于海龟当前方向的

turtle.right(angle) # 海龟的方向向右旋转angle度,这个角度angle是相对于海龟当前方向的

可以使用python自带的帮助文件,来查看模块函数的具体说明。帮助文件打开的方式:单击开始按钮,选择【所有程序】→【Python 3.6】 → 【Python 3.6 Manuals (32-bit)】,显示窗口如下:

单击“索引”,在输入框中输入turtle,在下拉列表中选择“turtle (module)”,显示窗口如下:

右边文档中包含了turtle模块所有函数的说明和示例。

递归

程序中的Generator()函数使用了递归来生成曲线。在计算机科学中,递归(Recursion)指的是函数的定义中使用函数本身的方法,也就是说,自己调用自己。递归是有去(递去)有回(回归)的。“有去”是指:递归问题可以分解为若干个规模较小,与原问题形式相同的子问题,这些子问题可以用相同的解题思路来解决;“有回”是指:问题由大到小、层层分解,会到达一个明确的终点,从这个终点开始,不再分解,原路返回到原点。

分形图像具有自我相似、自我嵌套的特点,因此非常适合用递归算法来生成。我们来看一下函数Generator(A,B,L,n)的运行过程:

假设n为2,n不等于1,所以执行else子句:

获取中间点:C、D、E的位置和方向,不显示图形

调用函数Generator(A,C,L/3,1)

n等于1,所以执行if子句:

恢复海龟状态到A点,绘制AC段图形

返回到函数Generator(A,B,L,2)

调用函数Generator(C,D,L/3,1)

n等于1,所以执行if子句:

恢复海龟状态到C点,绘制CD段图形

返回到函数Generator(A,B,L,2)

调用函数Generator(D,E,L/3,1)

n等于1,所以执行if子句:

恢复海龟状态到D点,绘制DE段图形

返回到函数Generator(A,B,L,2)

调用函数Generator(E,B,L/3,1)

n等于1,所以执行if子句:

恢复海龟状态到E点,绘制EB段图形

返回到函数Generator(A,B,L,2)

函数Generator(A,B,L,2)结束

数据可视化Tips

颜色

在信息可视化与视觉设计中,颜色、形状与布局构成了最基本的数据编码手段,其中,颜色可以编码大量的数据信息。如何设置可视化元素的颜色?采用什么样的颜色来编码数据信息,也就是如何将数据信息映射到颜色上?这些决定了可视化结果的表达力与视觉美感。

色彩空间(也称色彩模型或色彩系统)是使用一组数值(通常使用3个或4个值)来表示颜色的抽象数学模型。常用的色彩模式有CMYK、RGB以及HSB等等,其中,CMYK是在印刷上使用比较普遍的色彩模式,RGB是常用于计算机的色彩模式,而HSB的色相、饱和度和明度则是基于人眼视觉细胞而设定的。不同的色彩模式之间通常存在有损或无损的数学转换关系。

计算机采用的RGB色彩模式,R代表red(红 ),G代表green(绿),B代表blue(蓝)。红、绿、蓝叫做三原色,用它们的组合可以表示任何一种颜色。R、G和B的取值范围都是0到255,各有256种取值。通常说的“纯红”,用RGB值表示就是(255,0,0);“纯绿”用RGB表示为(0,255,0);“纯蓝”用RGB表示就是(0,0,255);“黄”色用RGB表示则为(255,255,0);“青”色用RGB表示则为(0,255,255); “粉红”色用RGB表示则为(255,0,255);任意三个值也必定对应一种颜色。如果在RGB模式上再加上一个值,就是RGBA (red, green, blue,
alpha),RGBA格式的最后一个元素表示颜色的透明度。

海岸线、科赫曲线、turtle、递归的更多相关文章

  1. 科赫曲线和科赫雪花的绘制Python

    #KochDrawV1.pyimport turtledef koch(size,n): if n == 0: turtle.fd(size) else: for angle in [0,60,-12 ...

  2. python画图——雪花(科赫曲线)

    科赫曲线是一种分形,其形态非常像雪花,因此又被称作科赫雪花.雪花曲线. 下面是用python的turtle包让我们来实时画一个 import turtledef koch(t,n): #定义一个函数 ...

  3. 分形之科赫(Koch)雪花

    科赫曲线是一种分形.其形态似雪花,又称科赫雪花.雪花曲线.瑞典人科赫于1904年提出了著名的“雪花”曲线,这种曲线的作法是,从一个正三角形开始,把每条边分成三等份,然后以各边的中间长度为底边.分别向外 ...

  4. python: 递归函数(科赫雪花)

    import turtle as t def kehe(size,n): #递归函数 if n==0: t.fd(size) #阶数为0时,为一直线 else: for i in [0,60,-120 ...

  5. 科赫雪花利用python海龟绘图代码

    #KochDraw.py import turtle //海龟绘图 def koch(size, n): if n == 0: turtle.fd(size) else: for angle in [ ...

  6. pyinstaller库的简单使用 打包科赫雪花几何图形

    pyinstaller 简单使用 (cmd命令行) pyinstaller -F <文件名.py> Pyinstaller库常用参数 参数 描述 -h 查看帮助 --clean 清理打包过 ...

  7. python turtle 例子 海归绘图

          太阳花 1 # coding=utf-8 2 import turtle 3 import time 4   5 # 同时设置pencolor="red", fillc ...

  8. Koch曲线

    Koch曲线是一种分形,完整的Koch曲线像雪花,维基百科上记录Koch曲线最早出现在海里格·冯·科赫的论文<关于一条连续而无切线,可由初等几何构作的曲线>中,它的定义如下,给定线段AB, ...

  9. python学习笔记(5)

    .................................................................................................... ...

随机推荐

  1. Google Tag Manager

    Google Tag Manager SEO https://www.wappalyzer.com/technologies/tag-managers/google-tag-manager/ UTM ...

  2. WebIDE All In One

    WebIDE All In One web IDE Visual Studio Code vscode Code editing Redefined. Free. Built on open sour ...

  3. Android Studio show whitespace & Android studio 设置注释缩进

    Android Studio show whitespace & Android studio 设置注释缩进 https://github.com/xgqfrms/flutter/issues ...

  4. no code form generator

    no code form generator 无代码,表单生成器 H5 Drag & Drop UI => codes click copy demo https://www.forms ...

  5. 小程序 & taro 踩坑指南

    小程序 & taro 踩坑指南 微信开发者工具, 不支持 react bug https://github.com/NervJS/taro/issues/5042 solution just ...

  6. element-ui的树型结构图,半选状态数据给后台后,返回数据带有半选父节点的剔除展示

    // html <h2 class="text-gray">功能权限</h2><el-tree :data="permissionList& ...

  7. APC推出鞋底缓震科技 两款中高端跑鞋将陆续上市

    近日,英国知名运动品牌APC(公司编号:08703733)推出了全新的鞋底缓震科技 NOVR,该项技术将首先应用于两款跑步鞋上,随后陆续应用到其他重点鞋类产品. 是对于各大运动品牌来说,鞋底研发一直是 ...

  8. TYLER ADAMS BRADBERRY的私人投资分享

    TYLER ADAMS BRADBERRY是星盟全球投资公司(USA International Covenant 公司编号:20091457685)的创始人.投资委员会发起了15支项目基金,通过多方 ...

  9. 02.Fancy Indexing

    import numpy as np x = np.arange(16) index = [3,5,8] x[index] array([3, 5, 8]) X = x.reshape(4,-1) X ...

  10. ECMAScript 等性运算符

    判断两个变量是否相等是程序设计中非常重要的运算.在处理原始值时,这种运算相当简单,但涉及对象,任务就稍有点复杂. ECMAScript 提供了两套等性运算符:等号和非等号用于处理原始值,全等号和非全等 ...