“贝式曲线与贝克汉姆啥关系?”

说起来贝氏曲线,我们可能首先会想到下面这个男人:

图1. 一位不愿透露姓名的英国球员

但实际上我们说的不是这个叫贝克汉姆的英国男人,而是另外一个人,就是下面这个叫“皮埃尔·贝塞尔”(Pierre Bézier)的法国男人:

图2. 皮埃尔·贝塞尔

贝塞尔论起知名度,也许不如小贝,但说起对人类的贡献,那可是杠杠的,著名的“贝塞尔曲线”就出自他之手。1962年,贝塞尔发表了贝塞尔曲线的相关理论研究,当时在雷诺公司工作的他,主要运用贝塞尔曲线进行汽车设计。说到这里可能还是有很多人没明白贝塞尔曲线到底是什么,看一下下面这个图,大家就明白了。

图3. 设计中用到的贝赛尔曲线

在Photoshop等多种设计软件中,画曲线时主要用到的是就是贝赛尔曲线,就是类似于上图中的这个曲线,设计师们可以通过控制中间的控制点来画出自己需要的曲线。早先设计师们想要用电脑画出一条直线灰常简单,但要画出一条平滑的曲线却非常难,而贝塞尔曲线的诞生,让大家用电脑绘制出一条平滑曲线成为了现实,这也就是贝塞尔曲线的最大用途。

而今天我们就来说一下最简单的二阶贝塞尔曲线的推导,并用matplotlib进行展示。(实际上最简单的是一阶,但因为其只有一条直线,所以没有什么实际用途,就忽略了)

我们先来了解一下二阶贝赛尔曲线的原理。假如连在一起的两条线段AB和BC,如下图:

图4. 二阶贝赛尔曲线原理图 1

现在AB上取一点D,BC上取一点E,使得AD/AB=BE/BC,如下图:

图5. 二阶贝赛尔曲线原理图 2

而在线段DE上还要求一点F,使得DF/DE=AD/AB=BE/BC,如下图:

图6. 二阶贝赛尔曲线原理图 3

而当D在AB上不断移动,E在BC上不断移动,形成的F点的轨迹便是一条曲线,这条曲线就是二阶贝塞尔曲线。这就是今天我们要推导并演示的曲线。

下面直接用Python代码来展示一下。首先还是导入各种包:

import numpy as npimport matplotlib.pyplot as pltfrom matplotlib import animation

因为我们用的是matplotlib来做的演示,所以要设置一下matplotlib的后端,也就是显示方式。这一行代码最好单独使用,否则容易失效,所以把它单独列出来:

%matplotlib

这是非常重要的一步,这一步能让matplotlib在绘图时弹出一个新窗口,而不是在原窗口直接绘制,因为原窗口无法显示动画,这里用了ipython的magic 命令,也就是在一个命令前面加上“%”。在这里说明一下,笔者用的是win7系统,开发工具为Anaconda最新版,可以直接去Anaconda官网下载。

因为我们要用到A、B、C三个点,所以要设置一下三个点坐标。A点坐标为x1和y1,B点为x2和y2,C点为x3和y3,再设置一个区间内点的个数dots_num,这个dots_num后面会有解释。所有这些变量的值都可以随意设定,但有一些要求,因为笔者把绘图的坐标系设定在100,也就是x轴和y轴的范围都是0—100,所以上面三个点的坐标都不要超过这个范围,而dots_num的数量尽可能大一些,做动画时更连贯一些,所以上面这些参数的设置如下:

x1=10y1=80x2=50y2=10x3=90y3=80dots_num=100

接下来是获得贝塞尔曲线的轨迹的函数:

def two_degree_bc(x1=10, y1=80, x2=50, y2=10, x3=90, y3=80, dots_num=100): #bezier curve    global xt, yt, x_dots12, x_dots23, y_dots12, y_dots23    xt = [] #目标点的x坐标    yt = [] #目标点的y坐标    x_dots12 = np.linspace(x1, x2, dots_num) #线段AB的x坐标    y_dots12 = np.linspace(y1, y2, dots_num) #线段AB的y坐标    x_dots23 = np.linspace(x2, x3, dots_num) #线段BC的x坐标    y_dots23 = np.linspace(y2, y3, dots_num) #线段BC的y坐标    for i in range(dots_num): #获得目标点的轨迹        x = x_dots12[i] + (x_dots23[i]-x_dots12[i])*i / (dots_num-1)        y = y_dots12[i] + (y_dots23[i]-y_dots12[i])*i / (dots_num-1)        xt.append(x)        yt.append(y)

这里的xt和yt是两个list,就是用来存放目标点的x坐标和y坐标,而x_dots12和y_dots12分别是线段AB的x和y坐标,x_dots23和y_dots23分别是线段BC的x和y坐标,这四个是numpy的array格式,所有这些数据都设置成全局变量。而从上面的代码中我们可以看到变量dots_num的作用是在线段AB和BC上取这么多的点,然后用这些点推导目标点的坐标,点的数量越多,目标点的坐标也就越多,绘制出来的曲线也就更平滑。

接下来是动画函数,这个函数后面再解释:

def run(i):    art1.set_data(x_dots12[i], y_dots12[i])    art2.set_data(x_dots23[i], y_dots23[i])    art3.set_data([x_dots12[i], x_dots23[i]], [y_dots12[i], y_dots23[i]])    art4.set_data(xt[i], yt[i])return art1,art2,art3,art4

最后就是绘制动画了,代码如下:

two_degree_bc() #先生成目标点的轨迹fig, ax = plt.subplots(figsize=(8,8))ax.set_aspect(1) #让两个坐标轴等比例plt.xlim([0,100]) #设置坐标轴范围plt.ylim([0,100])ax.plot([x1, x2], [y1, y2], color='#3e82fc') #绘制AB线段ax.plot([x2, x3], [y2, y3], color='#3e82fc') #绘制BC线段ax.plot(xt,yt,color='orange') #绘制目标曲线art1, = ax.plot(x_dots12[0], y_dots12[0], color='green', marker='o') #不能用scatter,因为得到的对象不是一个list,是一个objectart2, = ax.plot(x_dots23[0], y_dots23[0], color='green', marker='o')art3, = ax.plot([x_dots12[0], x_dots23[0]], [y_dots12[0], y_dots23[0]], color = 'purple') #plot得到的结果是一个list,只包含一个元素,即一个形状objectart4, = ax.plot(xt[0], yt[0], color='red', marker='o') ani = animation.FuncAnimation(    fig, run, frames=range(100), interval=2, save_count=50)plt.show()

这里首先运行two_degree_bc()函数得到目标点的轨迹,然后绘制AB、BC线段以及目标曲线,这些都是静态图。接着从变量art1开始就是绘制动画的部分了。这部分比较复杂,一共有art1、art2、art3和art4这四个变量,其分别对应线段AB、BC、DE和目标曲线的移动轨迹,点在这四个轨迹上移动,才能形成动画。而要生成动画,就要用到animation的方法FuncAnimation,其含有多个参数,fig就是我们绘图的那个画布,run就是我们生成动画时运行的函数,frames是帧画面,其每一帧画面包含了这些移动轨迹中的一个点所对应的静态图,把这些点的轨迹也就是每一帧连起来就是动画轨迹,frames一般是一个sequence,也就是包含多个变量,每个变量都赋值给run函数,run函数利用这个参数生成一个静态图,这么多静态图连起来就是动画,这和我们在电影或电视中看到的动画片是一样道理。interval是帧之间的时间间隔,200代表0.2秒,这个可以随意设定。save_count=50是把帧缓存起来用于回放,缓存帧的数量越多,回放越流畅,这个影响不大,随意设定。

下面再说一下运行动画的函数run的作用,可以看到run一共有5行代码,前4行代码是绘图代码,最后一个是返回参数的代码,前4行中每一行都代表了前面我们说过的点的轨迹, art1是线段AB上的点,用set_data(x_dots12[i], y_dots12[i])方法就生成了一个对应的帧,变量i就是前面讲的frames里的一个参数,生成的这个帧返回给FuncAnimation,让其用于连续播放,这就形成了动画。后面art2、art3和art4的道理是一样的。生成的动画效果的静态截图如下:

图7. 二阶贝赛尔曲线静态成图

最后再放上一个动图,让我们在一个深V的运动中结束本次话题:

图8. 二阶贝赛尔曲线动态示意图

二阶贝塞尔曲线的推导相对还容易一些,而三阶甚至更高阶的推导就复杂一点,笔者目前正在研究三阶贝赛尔曲线,以后会给大家分享一下。

完整代码已经上传:

https://gitee.com/leonmovie/two_degree_bc

有需要的可以去自行下载。


入门python数据分析,点击“

本文作者:小李子

编辑:佳佳

扫码关注我们

关注送狗子表情包一张&精选python资料一份

用数据改变未来

后排的朋友,让我知道你在看行吗~↓↓↓

python个人项目进度管理系统源码_Python项目练习:40行代码画出动态贝氏曲线(附源码)...相关推荐

  1. 新手也能立即上手,用Python90多行代码画出“樱花园”仙境(源码+注释)

    还记得在大学时,靠近西边有一片特别大的樱花园,每到3-4月,樱花开了,美的啊!那片区域特别多学妹与学姐来拍照,男生个个面如带花,实际心如一头狼,就想偶遇个小学妹,不怕嘲笑,我也去蹲点过,还幸运的与校园 ...

  2. 免费开源的高精度OCR文本提取,支持 100 多种语言、自动文本定位和脚本检测,几行代码即可实现离线使用(附源码)

    免费开源的高精度OCR文本提取,支持 100 多种语言.自动文本定位和脚本检测,几行代码即可实现离线使用(附源码). 要从图像.照片中提取文本吗?是否刚刚拍了讲义的照片并想将其转换为文本?那么您将需要 ...

  3. python调用计算器卡死_Python+tkinter使用40行代码实现计算器功能

    本文实例为大家分享了40行Python代码实现计算器功能,供大家参考,具体内容如下 偶尔用脚本写点东西也是不错的. 效果图 代码 from tkinter import * reset=True de ...

  4. 用python写web网页实现音乐数据库查询_Python tornado用40行代码搭建数据库交互网页实现快速全栈开发...

    作为数据分析师,我们大部分时间做的事情都是搭建线下Excel报表,这既有优点也有缺点 优点是: 开发效率 快速建模,最快十分钟就可以建模 数据传播 便于传播,发文件就是发模型 交互友好 对使用者门槛低 ...

  5. c语言程序员写贪吃蛇代码28,厉害了,程序员28行代码写贪吃蛇游戏,附源码!...

    对于贪吃蛇游戏,大家基本上都玩过,但是作为一个程序员,大家是否想过要自己去写一个贪吃蛇,毕竟玩别人写的游戏和自己写的游戏是两种截然不同的感受,而且也可以通过制作来提升自己的技术! 其实贪吃蛇的逻辑并不 ...

  6. 记事本贪吃蛇游戏代码_厉害了,程序员28行代码写贪吃蛇游戏,附源码!

    对于贪吃蛇游戏,大家基本上都玩过,但是作为一个程序员,大家是否想过要自己去写一个贪吃蛇,毕竟玩别人写的游戏和自己写的游戏是两种截然不同的感受,而且也可以通过制作来提升自己的技术! 其实贪吃蛇的逻辑并不 ...

  7. python代码300行程序_python小工具,15行代码秒出工资条

    公司工资条经常使用Excel制作,但是每个月都要做一遍,能不能用python写个程序自动化完成这想工作?当然可以,而且只是分分钟的事! 先来看看原始数据是什么样子: 最后做成的效果: 使用Excel每 ...

  8. 500 行代码写一个俄罗斯方块游戏(附源码)

    点击上方[全栈开发者社区]→右上角[...]→[设为星标⭐] 导读:本文我们要制作一个俄罗斯方块游戏. 作者 | 派森学python 来源 | https://segmentfault.com/a/1 ...

  9. python闹钟界面源码_Python GUI 教程 25行代码写一个小闹钟

    今天我们讲一下用Python写的GUI小程序.一个小闹钟(只是屏幕提示,没有声音哦) 让我们先介绍这个闹钟如何奇葩. 需要通过命令行启动. 没有标题栏. 没菜单. 甚至没有关闭按钮. 没有运行界面. ...

  10. python怎么实现音乐快进_Python 超简单3行代码提取音乐高潮(附批量提取)

    有些时候,为了设定手机铃声或者发抖音视频,我们会耗费大量时间在剪辑音乐高潮部分上.那么这个音乐高潮的提取能不能自动化呢?当然可以. 先来听听效果,孤芳自赏提取高潮后的部分: 怎么样,是不是迫不及待想往 ...

最新文章

  1. vue实例没有挂载到html上,vue 源码学习 - 实例挂载
  2. rabbit-mq cluster安装
  3. webservice(基础)
  4. Activity 切换动画
  5. OpenCV中GPU模块使用
  6. Codeforces 1182A Filling Shapes
  7. [bbk5307]第76集 第9章 -数据库性能维护 03
  8. 华为、三星都崴了脚:石墨烯充电还有戏吗
  9. ※部分VB文章汇总B※
  10. JS编写全选,复选按钮
  11. JavaScript 02
  12. sas+eg连接mysql_SAS EG 连接 SQL Server 2017数据库
  13. Python + 大数据-Python 学习(一)
  14. 黄聪:使用Python中的HTMLParser、cookielib抓取和解析网页、从HTML文档中提取链接、图像、文本、Cookies(二)
  15. 国培计算机网络技术培训心得,2017国培学习心得体会及感受
  16. pycharm的 crtl + r 使用正则表达式进行 request-header格式更改
  17. 从拖延到高效,我推荐这7本书
  18. 智慧灯杆行业:千亿级大市场!这种“杆”打开新风口
  19. 卡丽来相片卡拉OK VCD制作系统破解版(大型)
  20. 网络抓包技术: scapy

热门文章

  1. DB_RUNRECOVERY: Fatal error, run database recovery StackTrace问题的解决办法
  2. 某厂AD 2008R2/Exchange2010升级迁移项目实施方案
  3. 尽量用iterator代替const_iterator
  4. jstack分析CPU高的问题
  5. Microsoft Caffe(msCaffe)无GPU快速配置
  6. spring-aop源码分析
  7. Vue 组件库 (一)
  8. RxJava -- 从 create 开始 (一)
  9. Urllib3 库详解
  10. 2017-2018-1 20155222 《信息安全系统设计基础》课上实验2、3