【高级UI】【009】贝塞尔曲线图形原理和公式推导

(169) 2024-03-24 15:01:01

什么是贝塞尔曲线

贝塞尔曲线,英文名Bezier Curve,是计算机图形学非常重要的一种曲线

它可以将若干的点,用一条平滑自然的曲线来连接起来

比如我们在地图库中绘制用户行走轨迹时,如果用折线来展示,就比较难看

如果通过贝塞尔曲线,转为曲线来显示,就特别舒服自然了

像安卓中的水纹,波形等,很多就是通过贝塞尔曲线实现的

所以在讲绘制之前,先把这个基础知识给讲了

贝塞尔曲线简单示例

【高级UI】【009】贝塞尔曲线图形原理和公式推导 (https://mushiming.com/)  第1张
如图,P0和P2为贝塞尔曲线要经过的点,P1为控制点

选择不同的控制点,可以得到不同的曲线路径,但都可以结果P0和P2

贝塞尔曲线上的点如何确定

以上图为例,我们来推演下,最简单的贝塞尔曲线是如何确定点的

从P0开始,连接所有控制点,最后再连接到终点P2

我们随便在P0-P1上取一个点Q1,假设Q1的位置为t

t是指Q1到起点的位置,占整条线段长度的比例,所以它的范围是在0-1之间的小数

我们再在P1-P2上位置为t的地方,取一个点Q2

连接Q1-Q2,就形成了图中的绿线

再在Q1-Q2上位置为t的地方,取一个点R,就是图中的黑点

当t从0开始变化,逐渐增长到1,所有的黑点加起来,就形成了图中的红色曲线,它就是一条贝塞尔曲线

为什么贝塞尔曲线是连续的

从上面的推演过程,我们可以知道,贝塞尔曲线的路径,是一个关于t的函数

它的公式具体如何我们暂时不写出来,但一定是一个比较容易推到出来的公式

因为点确定的过程,就是根据两点的坐标,取线上中间某个比例位置的坐标,这就是个简单的乘法运算

当有多个控制点时,实际也就是进行了多次乘法运算,曲线是一个关于t的n次方的函数

学过高中数学的基本都知道,乘方函数,当变量t是均匀变化的,形成的肯定是一个圆滑连续的曲线

在高数中,这也叫做函数的连续性

贝塞尔曲线的阶数和公式

上面已经提到,贝塞尔曲线是关于比例t的乘方函数,t最高的次方数,就是贝塞尔曲线的阶数

上面的简单曲线,是一个二阶的贝塞尔曲线,只有一个控制点,公式中t的最高次方为2

L阶的贝塞尔曲线,有L-1个控制点,公式中t的最高次方为L

L阶的贝塞尔曲线公式如下

F ( t ) = P L 0 = ∑ i = 0 L   C L i ∗ P 0 i ∗ ( 1 − t ) L − i ∗ t i F(t) = P{^0_L} = \sum_{i=0}^{L}\ C^i_L * P{^i_0} * (1 - t)^{L-i} * t^i F(t)=PL0=i=0L CLiP0i(1t)Liti

多阶贝塞尔曲线效果展示

曲线
【高级UI】【009】贝塞尔曲线图形原理和公式推导 (https://mushiming.com/)  第2张
一阶贝塞尔曲线
【高级UI】【009】贝塞尔曲线图形原理和公式推导 (https://mushiming.com/)  第3张
二阶贝塞尔曲线
【高级UI】【009】贝塞尔曲线图形原理和公式推导 (https://mushiming.com/)  第4张
三阶贝塞尔曲线
【高级UI】【009】贝塞尔曲线图形原理和公式推导 (https://mushiming.com/)  第5张
四阶贝塞尔曲线
【高级UI】【009】贝塞尔曲线图形原理和公式推导 (https://mushiming.com/)  第6张
五阶贝塞尔曲线

通过递归函数计算贝塞尔曲线

通过上面的数学公式,我们可以求得贝塞尔曲线上的点,但在编程中编写复杂的数学公式,是有点繁琐的

其实我们可以通过递归函数,直接算出比例t对应的坐标位置

递归运算的效率会比数学公式低,但是更加简单,偷懒的可以使用递归方法

这里我们以四阶贝塞尔曲线为例,简单讲解下递归过程

【高级UI】【009】贝塞尔曲线图形原理和公式推导 (https://mushiming.com/)  第7张

  1. 将所有起点-控制点-终点连接起来,形成4条灰色线段
  2. 每条灰色线段上的t位置取一个点,再连接起来,形成3条绿色线段
  3. 每条灰色线段上的t位置取一个点,再连接起来,形成2条蓝色线段
  4. 每条蓝色线段上的t位置取一个点,再连接起来,形成1条粉色线段
  5. 在粉色线段上的t位置取一个点,这个点就是贝塞尔曲线上t对应的位置

可以看出,整个过程就是一个不断递归的过程,每次在t位置取点,重新连接成新的线段,直到最后只有一个点

这个递归实现起来非常简单,这里就不给出具体代码了

  1. 用一个List存储全部的坐标值
  2. 再每相邻两个元素取t位置的中间值,形成一个新的List
  3. 如此递归,直到List中只剩一个点,这个点就是贝塞尔曲线上t对应的位置

贝塞尔曲线公式推导

这部分属于数学公式推导,不感兴趣或看不懂的,可以直接跳过,直接使用上面的结论公式即可

【高级UI】【009】贝塞尔曲线图形原理和公式推导 (https://mushiming.com/)  第8张
设最大阶数为Level,P[n,i]表示递归过程中的所有取点,n表示第几轮递归,i表示P在该轮所有取点中的顺序

已知所有P[0,i]的坐标,就是最初的已知点坐标,每一轮递归,n加1,i的最大值,也就是取点的总数减1

当n=Level时,只能取到唯一一个点,这个点就是我们想要求得的,贝塞尔曲线上比例t对应的点P[Level,0]

通过图示,我们可以很明显地看出,相邻两轮取点间的递推关系

P n i = ( 1 − t ) P n − 1 i + t P n − 1 i + 1 P{^i_n} = (1 - t)P{^i_{n-1}} + tP{^{i+1}_{n-1}} Pni=(1t)Pn1i+tPn1i+1

根据这个递推公式,我们就可以得到最终的贝塞尔曲线公式(需要一定的数学知识和想象力)

F ( t ) = P L 0 = ∑ i = 0 L   C L i ∗ P 0 i ∗ ( 1 − t ) L − i ∗ t i F(t) = P{^0_L} = \sum_{i=0}^{L}\ C^i_L * P{^i_0} * (1 - t)^{L-i} * t^i F(t)=PL0=i=0L CLiP0i(1t)Liti

这个递推算法又叫做"德卡斯特里奥算法",下面的图可以帮助我们更好地理解推理过程

【高级UI】【009】贝塞尔曲线图形原理和公式推导 (https://mushiming.com/)  第9张

参考文献

这篇博客中的图片,转载自这里

贝塞尔曲线(Bezier Curve)原理及公式推导_CCC的专栏-CSDN博客

在此对原作者表示感谢和点赞

THE END

发表回复