过已知的n个点如何画出平滑的曲线呢? 你会觉得很简单啊,使用贝塞尔曲线就行了,可最多只能使用三阶贝塞尔曲线,如何使两个贝塞尔曲线在连接点保持平滑呢?
贝塞尔曲线
贝塞尔曲线的数学基础是早在 1912 年就广为人知的伯恩斯坦多项式。但直到 1959 年,当时就职于雪铁龙的法国数学家 Paul de Casteljau 才开始对它进行图形化应用的尝试,并提出了一种数值稳定的 de Casteljau 算法。然而贝塞尔曲线的得名,却是由于 1962 年另一位就职于雷诺的法国工程师 Pierre Bézier 的广泛宣传。他使用这种只需要很少的控制点就能够生成复杂平滑曲线的方法,来辅助汽车车体的工业设计。
正是因为控制简便却具有极强的描述能力,贝塞尔曲线在工业设计领域迅速得到了广泛的应用。不仅如此,在计算机图形学领域,尤其是矢量图形学,贝塞尔曲线也占有重要的地位。今天我们最常见的一些矢量绘图软件,如 Flash、Illustrator、CorelDraw 等,无一例外都提供了绘制贝塞尔曲线的功能。甚至像 Photoshop 这样的位图编辑软件,也把贝塞尔曲线作为仅有的矢量绘制工具(钢笔工具)包含其中。
- 一阶贝塞尔曲线
一阶曲线只有起点和终点P0和P1,就是一直线(图片和方程引用wiki,下同)
方程: - 二阶贝塞尔曲线
二阶曲线除了起点P0,终点P2,还有一个控制点P1,此时就是一个曲线
方程:
整理后:
一阶导数:
二阶导数: - 三阶贝塞尔曲线
三阶曲线除了起点P0,终点P3,还有两个控制点P1, P2,此时也是一个曲线
方程:
简化后:
一阶导数:
二阶导数:
何谓平滑
什么叫两个贝塞尔曲线在连接点P处保持平滑呢?从数学意义上讲,应该是曲线在P处可导,同时我们还希望P点左右两边曲线的凹凸性相同,也就是P点左右两边一阶和二阶导数相等
分析
给定n个点,我们可以取相邻两个点画一个三阶贝塞尔曲线,关键在于如何获得两个点之间的控制点,使得相邻的曲线在相邻点处的一阶和二阶导数相等;
三阶贝塞尔曲线可以表示成:
整理:
我们现在需要边界点处一阶导数相等, 一阶导数可以表示成:
第i个曲线的起点处有方程:
有:
既然曲线是连续的,那么就有:
我们可以简化(1)式:
同样我们也需要二阶导数相等:
在边界处二阶导数相等:
简化后等到(2)式:
将(1)和(2)组合消去P2,i和P2,i-1
这符合三对角矩阵算法,但上面只有n-2个等式,还需要2个等式,我们可以找边界条件:
由此我们可以等到(3)和(4):
使用(1)式将(3)中消去P2,0,得到:
在(1)式和(2)式中,令i=n-1,带入(4)式中消去P2,n-1,得到:
利用三对角矩阵算法可以算出P1,i,再由(1)和(4)式可以得到P2,i
和
code snippet
1 | private void makeCubicBezierPath(List<PointF> points, Path path) { |