为2021年的第一场雪锦上添花:用matplotlib绘制雪花和雪景


Posted in Python onJanuary 05, 2021

一场大雪,覆盖了华北、华东。天地连成一片,城市银装素裹,处处诗情画意、人人兴高采烈。朋友圈被雪景图和调侃路滑摔跤的段子刷屏,气氛比过年还要热烈几分。我也来凑个热闹,用python为2020年的第一场雪锦上添花。

绘制雪花图案,网上有很多文章介绍,但几乎都是用 Python 的内置模块 turtle 绘制的,这个模块适合用来引导孩子学习编程,很难真正用在项目开发上。也有用 pygame 实现的,不过 pygame 追求的是动画效果,雪花图案是随机生成的圆,效果很一般。

用 matplotlib 绘制雪花,重点是生成科赫曲线(Koch Curve)。科赫曲线是一种分形,其形态似雪花,又称科赫雪花、雪花曲线。给定线段pq,k阶科赫曲线可以由以下步骤生成:

  • 找出三等分点u、v
  • 以线段uv为底,向外(或内外)画等边三角形uwv
  • 将线段uv移除
  • 对pq之间的每一段重复上述操作k-1次

科赫雪花是以等边三角形三边生成的科赫曲线组成的。基于上述分析,我们可以很容易地写出科赫雪花的生成函数:给定一个等边三角形,和科赫曲线阶数k,返回科赫雪花图案中的所有点。

import numpy as np

plt.rcParams['font.sans-serif'] = ['FangSong'] # 指定默认字体
plt.rcParams['axes.unicode_minus'] = False #解决中文显示为方块的问题

def rotate(p, d):
  """返回点p绕原点逆时针旋转d度的坐标"""
  
  a = np.radians(d)
  m = np.array([[np.cos(a), np.sin(a)],[-np.sin(a), np.cos(a)]])
  return np.dot(p, m)

def koch_curve(p, q):
  """将线段pq生成科赫曲线,返回uvw三个点"""
  
  p, q = np.array(p), np.array(q)
  u = p + (q-p)/3 # 三等分点u的坐标
  v = q - (q-p)/3 # 三等分点V的坐标
  w = rotate(v-u, 60) + u # 线段uv绕u点逆时针旋转60°得到点w的坐标
  
  return u.tolist(), v.tolist(), w.tolist()
  
def snow(triangle, k):
  """给定三角形,生成封闭的科赫雪花"""
  
  for i in range(k):
    result = list()
    t_len = len(triangle)
    for j in range(t_len):
      p = triangle[j]
      q = triangle[(j+1)%t_len]
      u, v, w = koch_curve(p, q)
      result.extend([p, u, w, v])
    triangle = result.copy()
  
  triangle.append(triangle[0])
  return triangle

有了雪花图案的数据,接下来使用 matplotlib 绘图就非常轻松了:

import numpy as np
import matplotlib.pyplot as plt

def plot_snow(snow_list):
  """绘制雪花"""
  
  for triangle, k in snow_list:
    data = np.array(snow(triangle, k))
    x, y = np.split(data, 2, axis=1)
    plt.plot(x, y)
  
  plt.axis('equal') 
  plt.show()

snow_list = [
  ([(0,0), (0.5,0.8660254), (1,0)], 5),
  ([(1.1,0.4), (1.35,0.8330127), (1.6,0.4)], 4),
  ([(1.1,-0.1), (1.25,0.15980761), (1.4,-0.1)], 3)
]
plot_snow(snow_list)

来看看我们的雪花效果。从小到大,3片雪花分别对应的是3阶、4阶、5阶的科赫雪花。

为2021年的第一场雪锦上添花:用matplotlib绘制雪花和雪景

更进一步,我们还可以把雪花画在背景图上,配合大小浓淡的变化,画出另一种韵味的雪景图。

import numpy as np
import matplotlib.pyplot as plt
from PIL import Image

def draw_scenery():
  """绘制雪景图"""
  
  im = Image.open('brage.png')
  bg = np.array(im)
  plt.imshow(bg) # 绘制背景图
  
  for i in range(80):
    x = np.random.randint(80, im.size[0]-80)
    y = np.random.randint(30, im.size[1]-30)
    r = np.random.randint(5, 20)
    a = np.random.random()*0.6 + 0.2
    v = np.array((x-r/2, y))
    u = np.array((x+r/2, y))
    w = rotate(v-u, 60) + u
    
    data = np.array(snow([(u[0],u[1]),(w[0],w[1]),(v[0],v[1])], 5))
    x, y = np.split(data, 2, axis=1)
    plt.plot(x, y, c='#AABBCC', lw=1, ls='-', alpha=a)
  
  plt.axis('equal') 
  plt.show()

draw_scenery()

为2021年的第一场雪锦上添花:用matplotlib绘制雪花和雪景

到此这篇关于为2021年的第一场雪锦上添花:用matplotlib绘制雪花和雪景的文章就介绍到这了,更多相关matplotlib绘制雪花和雪景内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
打开电脑上的QQ的python代码
Feb 10 Python
python命令行参数sys.argv使用示例
Jan 28 Python
Python中list初始化方法示例
Sep 18 Python
Python读取sqlite数据库文件的方法分析
Aug 07 Python
python实现求解列表中元素的排列和组合问题
Mar 15 Python
使用python生成目录树
Mar 29 Python
使用Python来开发微信功能
Jun 13 Python
python 对给定可迭代集合统计出现频率,并排序的方法
Oct 18 Python
django自带调试服务器的使用详解
Aug 29 Python
使用python实现kNN分类算法
Oct 16 Python
Python使用Turtle库绘制一棵西兰花
Nov 23 Python
Python 通过正则表达式快速获取电影的下载地址
Aug 17 Python
Matplotlib中rcParams使用方法
Jan 05 #Python
matplotlib常见函数之plt.rcParams、matshow的使用(坐标轴设置)
Jan 05 #Python
matplotlib运行时配置(Runtime Configuration,rc)参数rcParams解析
Jan 05 #Python
matplotlib制作雷达图报错ValueError的实现
Jan 05 #Python
python实现三种随机请求头方式
Jan 05 #Python
scrapy实践之翻页爬取的实现
Jan 05 #Python
python里glob模块知识点总结
Jan 05 #Python
You might like
十大催泪虐心动漫电影,有几部你还没看
2020/03/04 日漫
PHP mcrypt可逆加密算法分析
2011/07/19 PHP
CodeIgniter图像处理类的深入解析
2013/06/17 PHP
PHP结合Jquery和ajax实现瀑布流特效
2016/01/07 PHP
PHP查询并删除数据库多列重复数据的方法(利用数组函数实现)
2016/02/23 PHP
PHP中file_put_contents追加和换行的实现方法
2017/04/01 PHP
PHP生成各种随机验证码的方法总结【附demo源码】
2017/06/05 PHP
php+js实现的拖动滑块验证码验证表单操作示例【附源码下载】
2020/05/27 PHP
js的写法基础分析
2011/01/17 Javascript
用js实现判断当前网址的来路如果不是指定的来路就跳转到指定页面
2011/05/02 Javascript
jQuery News Ticker 基于jQuery的即时新闻行情展示插件
2011/11/05 Javascript
用js调用迅雷下载代码的二种方法
2013/04/15 Javascript
为什么要在引入的css或者js文件后面加参数的详细讲解
2013/05/03 Javascript
jquery和javascript的区别(常用方法比较)
2013/07/04 Javascript
jquery 获取表单元素里面的值示例代码
2013/07/28 Javascript
JS中类或对象的定义说明
2014/03/10 Javascript
现代 JavaScript 开发编程风格Idiomatic.js指南中文版
2014/05/28 Javascript
JavaScript数组排序reverse()和sort()方法详解
2017/12/24 Javascript
jQuery实现列表的增加和删除功能
2018/06/14 jQuery
mpvue开发音频类小程序踩坑和建议详解
2019/03/12 Javascript
vue在响应头response中获取自定义headers操作
2020/07/24 Javascript
Vue绑定用户接口实现代码示例
2020/11/04 Javascript
Python中表达式x += y和x = x+y 的区别详解
2017/06/20 Python
Python读取xlsx文件的实现方法
2019/07/04 Python
python中enumerate() 与zip()函数的使用比较实例分析
2019/09/03 Python
如何解决django-celery启动后迅速关闭
2019/10/16 Python
python 微信好友特征数据分析及可视化
2020/01/07 Python
对django 2.x版本中models.ForeignKey()外键说明介绍
2020/03/30 Python
Python中有几个关键字
2020/06/04 Python
时装界的“朋克之母”:Vivienne Westwood
2017/07/06 全球购物
2014新年元旦活动策划方案
2014/02/18 职场文书
会计专业毕业生自荐书
2014/06/25 职场文书
基层医务人员三严三实心得体会
2016/01/05 职场文书
springmvc直接不经过controller访问WEB-INF中的页面问题
2022/02/24 Java/Android
Win11黑色桌面背景怎么办?Win11黑色壁纸解决方法汇总
2022/04/05 数码科技
Java中的Kafka为什么性能这么快及4大核心详析
2022/09/23 Java/Android