本文作为 CAGD 导论,从曲线发展的角度上简单介绍一下最重要的曲线,即多项式曲线 - Bezier曲线 - B 样条曲线 - NURBS曲线的发展路径。
引言
曲线和曲面造型是计算机辅助几何设计(CAGD)中的核心内容,主要研究如何用数学方法来描述和构造曲线、曲面的形状,以满足工程设计和图形显示的需要。
曲线和曲面造型在工程设计中具有重要作用,如汽车车身设计、飞机机翼设计、船舶船体设计等。通过精确的曲线和曲面造型,可以提高产品的性能、美观性和制造精度。
本文作为 CAGD 导论,从曲线发展的角度上简单介绍一下最重要的曲线,即多项式曲线 - Bezier曲线 - B 样条曲线 - NURBS曲线的发展路径。
基函数
基函数,即函数空间的一组基,可以用来表出指定函数。
这个思想是可以用一组确定的基函数来表示目标函数。
这个思想非常重要,之后我们把所有曲线都拆分成基函数的线性组合进行研究。
常见的基函数有多项式基,三角函数基(傅里叶基),有理函数基等。
由于需要构造曲线的给出是任意的,选择基函数的原则应该是能满足任意函数的一致逼近的; 由于需要构造曲线通常不具有周期性,因此多项式基更适合(参考Weierstrass逼近定理)。
插值
要想按照一个点列构造一条曲线,最简单的想法就是插值。
插值在上篇文章详细讲了,这里只做简单叙述。
插值是一种数学方法,通过已知的一组数据点 $(x_1, y_1), (x_2, y_2), \ldots, (x_n, y_n)$,构造一个函数 $ f(x) $,使得该函数在这些数据点上满足 $ f(x_i) = y_i $。
换句话说,插值函数通过已知数据点,并且可以用来估计这些数据点之间的未知点的值。
这个插值函数就可以作为一条穿过这些点,确定的曲线。
多项式插值
多项式插值是最传统的插值,即用幂基${1,x,x^2,…}$作为基函数插值。
对于给定点列,多项式插值具有唯一性。
显然多项式基组成函数的矩阵是范德蒙矩阵,范德蒙行列式不为零,即得多项式系数唯一。
对于多项式插值的算法,常见的有拉格朗日插值,牛顿插值。
这一类算法较为简单,计算量也小,但多项式插值在次数超过4次时可能会产生严重的龙格现象,有时不能满足对于平滑性的要求。
为了保证曲线的平滑,可以通过分段拼接多项式的方式来组成平滑曲线,这就是分段多项式插值。
分段多项式插值
通常工业需求中要求轨迹是二阶光滑的,因此分段线性插值,分段埃尔米特插值等算法无法达到光滑性要求。
三次样条插值可以保证二阶光滑,同时求解系数时只需解三对角矩阵,计算效率高。因此在要求低时可以考虑使用。
需要考虑多项式插值在次数超过4次时可能会产生严重的龙格现象,对平滑性有严重影响,因此较少用4次以上的多项式插值。
现代的一些高级工业中通常要求超过二阶光滑,即至少保证加速度光滑。那么可选的有分段Bezier 曲线和 B 样条曲线。
Bezier 曲线
Bezier 曲线由一系列的点(称为控制点)定义,通过调整这些点的位置,可以绘制出平滑且复杂的曲线形状。
Bezier 曲线可以是线性的(一次),也可以是高阶的(二次、三次等)。一个 n 次 Bezier 曲线由 n+1 个控制点 $ P_0, P_1, …, P_n $ 定义。
控制点:分布在空间中的点。
- 控制点确定曲线的整体形状和走势。
- 每个控制点都对应一个基函数,所有控制点与对应的基函数的乘积求和即可得到Bezier曲线的函数表达式。
Bezier 曲线的数学表达式为: \(C(t) = \sum_{i=0}^{n} B_{i,n}(t) \cdot P_i\) 其中 $ B_{i,n}(t) $ 是 Bernstein 基多项式。
Bezier 曲线的计算方法较多,常见的有 Bernstein 多项式算法和 deCasteljau 算法,考虑数值稳定性一般选择 deCasteljau 算法。
deCasteljau 算法:这是一种递归算法,通过逐步计算内插点来逼近曲线。由于其数值稳定性,通常优先选择 deCasteljau 算法。
Bezier基函数
对于 Bezier 曲线,基函数为 Bernstein 多项式 Bernstein 基多项式定义为: \(B_{i,n}(t) = C_{n}^{i} t^i (1-t)^{n-i}\) 其中 $ C_{n}^{i} $ 是组合数,表示从 n 个不同元素中取 i 个元素的组合方式数量。
更进一步
根据定义,显然 Bezier 曲线每一个点变化都会影响整条曲线。如果要改变一个很长的曲线的中间一部分,就非常困难。
最简单的方式是把曲线分成多段,每段是单独的Bezier曲线,这样就更容易调整。
因此,分段 Bezier 曲线的控制点可以较容易的控制曲线,同时控制点的个数可以决定曲线的次数,进而控制光滑程度。
然而这个操作还是有限的,即划分到最后依旧是一段 Bezier 曲线作为最小调整单位,同时这个调整还是不均匀的。
B样条(NURBS)曲线作为分段 Bezier 曲线的扩展,解决了这个问题。
同时分段 Bezier 曲线无法精确的表示某些二次曲线(如圆),解析式就存在误差。
NURBS 曲线作为B样条曲线的扩展,解决了这个问题。
注:另一种解决方案是 有理 Bezier 曲线,但其本质是仍是 NURBS 曲线,在此不展开讲了。
B样条曲线
B样条曲线是一个分段连续的多项式曲线,一段B样条曲线由一组控制点和一组节点定义。
其中,控制点是实际空间中的点,而节点是分割出来的不同段的参数点。
B样条曲线是 Bezier 曲线的扩展,定义不仅需要一组控制点,还需要一组节点。
实际B样条曲线上的点是由多段基函数得到的点混合的,这个段数量即为B样条的次数。
控制点:分布在空间中的点。
- 控制点确定曲线的整体形状和走势。
- 每个控制点都对应一个基函数,所有控制点与对应的基函数的乘积求和即可得到B样条曲线的函数表达式。
节点:划分区间的参数点。
- 节点将曲线划分为不同的段,并决定每段的形状和连续性。
在B样条曲线中,控制点的数量、节点的数量和曲线的阶数之间满足一定的关系。
具体来说,若B样条曲线由n+1个控制点(从P0到Pn),有m+1个节点(从u0到um),阶数为p+1(次数为p),则必须满足m=n+p+1。
B样条曲线的数学表达式为: \(C(u) = \sum_{i=0}^{n} N_{i,p}(u) \cdot P_i\)
B样条基函数
B样条基函数的定义方式比较多,这里以 DeBo-Cox 递推定义为准,因为这种定义对于计算机实现最精确。
\[N_{i,0}(u) = \begin{cases} 1, & \text{if } u_i \leq u < u_{i+1} \\ 0, & \text{otherwise} \end{cases}\]令 $ U={u_0,u_1,…u_m} $ 是一个单调不减的实数序列,其中 $ u_i $ 称为节点,$U$称为节点矢量;
$N_{i,p}(u)$ 表示第i个p次(p+1阶)B样条基函数,定义为
\(N_{i,p}(u) = \frac{u - u_i}{u_{i+p} - u_i} N_{i,p-1}(u) + \frac{u_{i+p+1} - u}{u_{i+p+1} - u_{i+1}} N_{i+1,p-1}(u)\)
对于可能出现 0/0 的情况,这里规定0/0=0
显然,$p>0$ 时$N_{i,p}(u)$ 是两个 $p-1$次基函数的线性组合。
当 $N_{i,2}(u)$ 的节点向量为${0,0,…,0,1,1,…,1}$时(有p+1个0和p+1个1),恰好为2阶Bernstein多项式,这表明B样条多项式是Bezier多项式的推广。
更进一步
分段 Bezier 曲线无法精确的表示某些二次曲线,解析式存在误差,B样条也有相同的问题。
NURBS 曲线作为B样条曲线的扩展,解决了这个问题。
NURBS 曲线
B样条曲线可以根据节点间距分类,
- 均匀B样条曲线:所有节点间等间距
- 准均匀B样条曲线:可以分成几组等间距节点
- 非均匀B样条曲线:节点间距不等
NURBS 曲线 全称为 非均匀有理B样条,是 “有理” 的非均匀B样条曲线。
其中 “有理” 指代有理多项式,表现为每个控制点对曲线的贡献不再为1,而是由各自对应的权重控制。
NURBS 曲线定义为: \(C(u) = \frac{\sum_{i=0}^{n} w_i N_{i,p}(u) P_i}{\sum_{i=0}^{n} w_i N_{i,p}(u)}, a \le u \le b\)
其中:
- $C(u)$ 表示曲线上的点。
- $w_i$ 表示权重,与控制点$P_i$相关,用于调整控制点对曲线形状的贡献,进而调整曲线的形状。
- $P_i$ 表示控制点,是定义曲线形状的空间点。
- $N_{i,p}(u)$ 是p阶B样条基函数,决定曲线在控制点之间的插值方式。
有理基函数
可以定义$ 0 \le u \le 1$区间上的有理基函数 \(R_{i,p}(u) = \frac{ w_i N_{i,p}(u)}{\sum_{j=0}^{n} w_j N_{j,p}(u)}\)
进而 NURBS 曲线可以改写为 \(C(u) = \sum_{i=0}^{n} R_{i,p}(u) \cdot P_i\)
升维扩展
将控制点坐标和权重的组合看作齐次坐标,可以把权重作为一个新的维度加入控制点。
即对于控制点 $P_i[x_0,x_1,…x_n]$ 扩展为 $P_i[w_0x_0,w_1x_1,…w_nx_n,w_{sum}]$
则 NURBS 曲线在新的升维空间中变回 B样条曲线。
或者说 NURBS 是升维的B样条曲线的投影。
因此,NURBS 曲线的全部算法,可以使用B样条曲线算法扩展。