贝塞尔曲线学习笔记

前言

近段时间我在工作中实现了一个动画功能,其中涉及到动画元素要按一定的轨迹在屏幕上移动,运动轨迹的生成我使用了Path.cubicTo方法来实现的,这个方法其实是生成了一条有两个控制点的贝塞尔曲线。借此机会我再收集了一些资料,想系统地学习一下贝塞尔曲线相关的知识。

简介

贝塞尔曲线(Bézier curve)又被称为贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线,它的数学基础是伯恩斯坦多项式(Bernstein polynomial,since 1912),1959年法国数学家Paul de Casteljau提出了数值稳定的de Casteljau算法,开始贝塞尔曲线的图形化应用研究,而贝塞尔曲线的名称来源于一位就职于雷诺的法国工程师Pierre Bézier,他在1962年开始对贝塞尔曲线做了广泛的宣传,他使用这种只需要很少的控制点就能生成复杂平滑曲线的方法来进行汽车车体的工业设计。

贝塞尔曲线因为它控制简便却具有极强的描述能力,迅速在工业设计和计算机图形学等相关领域得到了广泛应用。比如在矢量绘图中,贝塞尔曲线用来给需要无限制地缩放的平滑曲线定模,许多绘图软件都提供了绘制贝塞尔曲线的功能。贝塞尔曲线还用于动画时间控制以实现美观逼真的缓动效果,还用于机器人转动手臂等方面的设计。

de Casteljau算法原理

在向量AB上选择一个点C,使得C分向量AB为u:1-u(即|AC|:|AB|=u)。给定点A、B的坐标以及u(u∈[0,1])的值,点C的坐标则为C=A+(B-A)*u=(1-u)*A+u*B。

de Casteljau算法基本原理

贝塞尔曲线原理

利用de Casteljau算法可以计算贝塞尔曲线上的点C(u),u∈[0,1]。因此,通过给定一组u的值,即可算出贝塞尔曲线上的坐标序列,从而绘制出贝塞尔曲线。

为了计算n阶贝塞尔曲线上的点C(u),u∈[0,1],首先将控制点连接形成一条折线00-01-02······0(n-1)-0n,利用de Casteljau算法,计算出折线中每条线段0j-0(j+1)上的一个点1j,使得点1j分该线段的比为u:1-u,然后在折线10-11-12-······-1(n-1)上递归调用该算法,以此类推。最终求得一个点n0,已证明点n0一定是曲线上的点。

de Casteljau算法的几何表达

上图中u=0.4,这从几何形状上形象地说明了de Casteljau算法的过程,可以将上述直观的几何描述表达为算术方法,如下图所示:

de Casteljau算法的算术表达图示

首先将所有的控制点排成一列,如上图最左列,每一对相邻的控制点之间画出两个箭头,分别指向右下方和右上方,在两个箭头交汇的位置记下一个新的点。比如控制点ij和i(j+1)生成新的控制点(i+1)j。指向右下方的箭头表示乘以(1-u),指向右上方的箭头表示乘以u。

将上述过程表达为下面的算法:

Input:arrayP[0:n] ofn+1 points and real numberuin [0,1]

Output:point on curve,C(u)

Working:point arrayQ[0:n]

fori:= 0 to n do

    Q[i] :=P[i]; // save input

fork:= 1 to n do

    fori:= 0ton - kdo

        Q[i] := (1 -u)Q[i] +uQ[i+ 1];

returnQ[0];

这个算法还可以被递归地表达,上述点列还有其他有趣的性质,详细描述请参考论文Finding a Point on a Bézier Curve: De Casteljau's Algorithm

贝塞尔曲线展示

一阶贝塞尔曲线

一阶贝塞尔曲线动画,t∈[0,1]

给定点P0和P1,一阶贝塞尔曲线就是这两点间的一条直线段,对应公式:

一阶贝塞尔曲线的一般方程

二阶贝塞尔曲线

二阶贝塞尔曲线动画,t∈[0,1]

给定点P0、P1和P2,二阶贝塞尔曲线是由下述方程产生的轨迹

二阶贝塞尔曲线的直接方程

这个方程可以被描述为由两段独立的一阶贝塞尔曲线再按de Casteljau算法合成的,分别是由 P0 至 P1 的连续点 Q0描述一条线段,由 P1 至 P2 的连续点 Q1描述另一条线段,最后由 Q0 至 Q1 的连续点 B(t)描述了贝塞尔曲线。整理上述公式变成:

二阶贝塞尔曲线的一般方程

三阶贝塞尔曲线


三阶贝塞尔曲线动画,t∈[0,1]

二维平面或者更高维度的空间中的4个点P0、P1、P2和P3可以定义一条三阶的贝塞尔曲线,这条曲线从P0点开始向P1点方向运动,最后从来自P2点的方向运动到达P3点。一般点P1和P2不会在曲线上,它们用来控制曲线运动的方向;点P0与P1间的距离将会影响曲线在转向P2之前向P1点方向运动的远近和快慢。按照二阶贝塞尔曲线方程可以表达为一阶的形式,三阶贝塞尔曲线也可以由两个二阶贝塞尔曲线组合来线性地表达:

三阶贝塞尔曲线的线性表达式

将方程递归带入整理得到:

三阶贝塞尔曲线的一般方程

更一般地,n阶贝塞尔曲线的一般方程为:

n阶贝塞尔曲线的一般表达式

例如,n=5时,即5阶贝塞尔曲线的方程为:

5阶贝塞尔曲线的一般方程

贝塞尔曲线应用

Android SDK中提供的API

在android.graphics包中的Path类提供了几个可以绘制贝塞尔曲线的API,常用的就是lineTo、quadTo和cubicTo三个方法,分别可以绘制一、二、三阶的贝塞尔曲线,一阶没什么可说的,就是通常的画直线,传入的参数就是目标点坐标。下面分别是quadTo和cubicTo方法的接口说明:

Path类的quadTo方法说明
Path类的cubicTo方法说明

自定义贝塞尔工具

在实际项目中我自己写了一个贝塞尔估值器类,核心方法如下:

自定义贝塞尔估值器


后记

我第一次写这样长篇的技术博客,惭愧!!想以此加深自己的理解,也方便以后迅速查阅相关的资料。写博客真的是一个深入学习的好方法,让我不再流于解决问题的表面,通过查找资料可以透过直接的技术方案发现方案背后的逻辑和原理。理解了最本质的东西,其他的都是可以举一反三、触类旁通的方法变幻。加油,少年!~


Thanks To:

贝塞尔曲线扫盲

贝塞尔曲线初探

Wikipedia:Bézier curve

Finding a Point on a Bézier Curve: De Casteljau's Algorithm

BezierDemo源码解析-实现qq消息气泡拖拽消失的效果

基于贝塞尔曲线的Android动画差值器

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,311评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,339评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,671评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,252评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,253评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,031评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,340评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,973评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,466评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,937评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,039评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,701评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,254评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,259评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,497评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,786评论 2 345

推荐阅读更多精彩内容