贝塞尔曲线扫盲

相信很是多同窗都知道“贝塞尔曲线”这个词,咱们在很是多地方都能经常看到。但是,可能并不是每位同窗都清楚地知道。究竟什么是“贝塞尔曲线”,又是什么特色让它有这么高的知名度。javascript

贝塞尔曲线的数学基础是早在 1912 年就广为人知的伯恩斯坦多项式。但直到 1959 年,当时就任于雪铁龙的法国数学家 Paul de Casteljau 才開始对它进行图形化应用的尝试,并提出了一种数值稳定的 de Casteljau 算法css

然而贝塞尔曲线的得名,倒是由于 1962 年还有一位就任于雷诺的法国project师 Pierre Bézier 的普遍宣传。他使用这样的仅仅需要很是少的控制点就行生成复杂平滑曲线的方法,来辅助汽车车体的工业设计。html

正是因为控制简便却具备极强的描写叙述能力,贝塞尔曲线在工业设计领域迅速获得了普遍的应用。不只如此,在计算机图形学领域,尤为是矢量图形学。贝塞尔曲线也占有重要的地位。今天咱们最多见的一些矢量画图软件,如 Flash、Illustrator、CorelDraw 等,无一例外都提供了绘制贝塞尔曲线的功能。甚至像 Photoshop 这种位图编辑软件。也把贝塞尔曲线做为仅有的矢量绘制工具(钢笔工具)包括当中。java

贝塞尔曲线在 web 开发领域相同占有一席之地。CSS3 新增了 transition-timing-function 属性。它的取值就可以设置为一个三次贝塞尔曲线方程。css3

在此以前,也有很多 JavaScript 动画库使用贝塞尔曲线来实现美观逼真的缓动效果。git

如下咱们就经过样例来了解一下怎样用 de Casteljau 算法绘制一条贝塞尔曲线。github

在平面内任选 3 个不共线的点。依次用线段链接。enter image description hereweb

在第一条线段上任选一个点 D。计算该点到线段起点的距离 AD。与该线段总长 AB 的比例。enter image description here算法

依据上一步获得的比例。从第二条线段上找出相应的点 E。使得 AD:AB= BE:BCenter image description here数据结构

链接这两点 DE。enter image description here

重新的线段 DE 上再次找出一样比例的点 F,使得 DF:DE= AD:AB= BE:BC

enter image description here

到这里,咱们就肯定了贝塞尔曲线上的一个点 F。

接下来,请略微回忆一下中学所学的极限知识。让选取的点 D 在第一条线段上从起点 A 移动到终点 B。找出所有的贝塞尔曲线上的点 F。

所有的点找出来以后,咱们也获得了这条贝塞尔曲线。enter image description here

假设你实在想象不出这个过程。不要紧,看动画!

enter image description here

回过头来看这条贝塞尔曲线,为了肯定曲线上的一个点,需要进行两轮取点的操做。所以咱们称获得的贝塞尔曲线为二次曲线(这样记忆很是直观,但曲线的次数事实上是由前面提到的伯恩斯坦多项式决定的)。

当控制点个数为 4 时。状况是如何的?enter image description here

步骤都是一样的,仅仅只是咱们每肯定一个贝塞尔曲线上的点,要进行三轮取点操做。

如图,AE:AB= BF:BC= CG:CD= EH:EF= FI:FG= HJ:HI,当中点 J 就是终于获得的贝塞尔曲线上的一个点。enter image description here

这样咱们获得的是一条三次贝塞尔曲线。

enter image description here

看过了二次和三次曲线,更高次的贝塞尔曲线你们应该也知道要怎么画了吧。

那么比二次曲线更简单的一次(线性)贝塞尔曲线存在吗?长什么样?依据前面的介绍,仅仅要稍做思考,想必你也能猜出来了。哈。就是一条直线~enter image description here

能画曲线也能画直线。是否是很是厉害?要绘制更复杂的曲线。控制点的添加也不过线性的。这一特色使其不光在工业设计领域大展拳脚,就连数学基础很差的人也可以比較easy地掌握,比方大多数平面美术设计师们。enter image description here

上面介绍的内容并不足以展现贝塞尔曲线的真正威力。推广到三维空间的贝塞尔曲面,以及更进一步的非均匀有理 B 样条(NURBS),早已成为当今计算机辅助设计(CAD)的行业标准。不管是咱们寻常用到的各类产品,仍是在电影院看到的精彩大片。都少不了它们的功劳。enter image description here

enter image description here

动态绘制贝塞尔曲线的在线演示



------------------------------华丽切割线------------------------------------

接下来,用贝塞尔曲线实现一个战斗中船体的简单移动

local sp = cc.Sprite:create("image/skip.png")
    sp:setPosition(size.width/2, size.height/2)
    self:addChild(sp)
    
    local x, y = sp:getPosition( )
    local offsetX = 300
    local offsetY = 300
    local bezierPoint1 ={
        cc.p( x - offsetX, y ),  --2
        cc.p( x - offsetX, y + offsetY ),  --3
        cc.p( x, y + offsetY )  --4
    }

    local bezierPoint2 ={
        cc.p( x + offsetX , y + offsetY ), --5
        cc.p( x + offsetX, y ), --6
        cc.p( x, y )  --1
    }
    local duration = 2
    local bezierTo1 = cc.BezierTo:create( duration, bezierPoint1 )
    local bezierTo2 = cc.BezierTo:create( duration, bezierPoint2 )
    local action  = cc.Sequence:create(
        bezierTo1,
        bezierTo2
    )
    sp:runAction(cc.RepeatForever:create(action))
那么,精灵大概运动轨迹如上,可以实现一个简单的往复的一个运动。