样条曲线
在上一篇笔记中, 我们介绍了 Bézier 曲线, 它是一条由若干控制点给出的光滑的多项式曲线, 而这些控制点对应的基函数是 Bernstein 基函数. 不难注意到, Bernstein 基函数 B k n ( t ) B^n_k(t) B k n ( t ) 在 k n \frac{k}{n} n k 处达到极大值, 在远离 k n \frac{k}{n} n k 时不断减小直到 0 0 0 . 因此每一个控制点在它附近对 Bézier 曲线的形状影响最大, 而在远处影响较小但始终非 0 0 0 . 用户移动某一控制点时, 总会对曲线整体造成影响. 此外, 当控制点增多时, 会产生更高阶的多项式, 影响计算效率.
在实践中, 我们有时会希望控制点只在它的附近对曲线的形状有影响, 并且避免高阶多项式, 此时 Bézier 曲线将无法达到要求. 为此我们需要使用另一种曲线: 样条曲线 (Spline curve) .
样条曲线指的是平滑的分段多项式曲线, 而这个名字来自于二战期间英国制造飞机时的技术, 使用若干段薄木条穿过固定的点来形成飞机上的曲线. 因为样条曲线是分段的, 所以可以使每一个控制点的影响范围在它的附近. 此外, 样条曲线的另一个优势在于可以控制曲线的阶数, 避免高次多项式的出现.
本文将介绍 Bézier 样条曲线和 B 样条曲线两种样条曲线, 它们的区别在于构造方法的不同, 但本质都是分段的多项式曲线.
Bézier 样条曲线
Bézier 样条曲线 (Bézier spline curve) 的想法很简单, 就是给定一系列的控制点, 构造一系列相连的 Bézier 曲线将它们相连, 并要求它们在相连点处有很好的连续性.
问题背景
对于空间中的 n + 1 n+1 n + 1 个控制点 { p 0 , p 1 , … , p n } \{p_0, p_1, \dots, p_n\} { p 0 , p 1 , … , p n } , 和若干参数结点 { 0 = t 0 < t 1 < ⋯ < t n = 1 } \{0 = t_0 < t_1 < \dots < t_n = 1\} { 0 = t 0 < t 1 < ⋯ < t n = 1 } , 我们希望有一段参数曲线 p ( t ) p(t) p ( t ) , 满足
p ( t k ) = p k , k = 0 , … , n (1) p(t_k) = p_k,\ k = 0, \dots, n
\tag{1}
p ( t k ) = p k , k = 0 , … , n ( 1 )
对于每一个 0 ≤ k ≤ n − 1 0 \leq k \leq n-1 0 ≤ k ≤ n − 1 在 t k < t < t k + 1 t_k < t < t_{k+1} t k < t < t k + 1 上 p ( t ) p(t) p ( t ) 是一段 Bézier 曲线, 并且曲线 p ( t ) p(t) p ( t ) 有较好的连续性 (有限阶可导).
计算一条 Bézier 样条曲线, 要做的就是根据连续性条件确定每一段 Bézier 曲线中控制点的位置. 其中每一段曲线的首尾两个控制点就是 p k , p k + 1 p_k, p_{k+1} p k , p k + 1 .
3 阶样条曲线
3 阶的 Bézier 样条曲线指的是, 每一段 Bézier 曲线都是 3 阶的, 有 4 个控制点的曲线, 它使得曲线直到 2 阶的导数都是连续的. 这也是实践中常用的样条曲线, 被称为 3 阶样条曲线 (Cubic spline curve) . 我们希望
对于 t k < t < t k + 1 t_k < t < t_{k+1} t k < t < t k + 1 上的一段 Bézier 曲线, 它的控制点记为 p k , p k + , p k + 1 − , p k + 1 p_k, p_k^+, p_{k+1}^-, p_{k+1} p k , p k + , p k + 1 − , p k + 1 . 通过 [ t k , t k + 1 ] [t_k, t_{k+1}] [ t k , t k + 1 ] 与 [ 0 , 1 ] [0, 1] [ 0 , 1 ] 之间的参数变换, 可以计算出
lim t → t k + 0 p ′ ( t ) = m t k + 1 − t k ( p k + − p k ) lim t → t k + 1 − 0 p ′ ( t ) = m t k + 1 − t k ( p k + 1 − p k + 1 − ) lim t → t k + 0 p ′ ′ ( t ) = m ( m − 1 ) ( t k + 1 − t k ) 2 ( p k − 2 p k + + p k + 1 − ) lim t → t k + 1 − 0 p ′ ( t ) = m ( m − 1 ) ( t k + 1 − t k ) 2 ( p k + − 2 p k + 1 − + p k + 1 ) \begin{aligned}
\lim_{t \rightarrow t_k +0} p' (t) & = \frac{m}{t_{k+1}-t_k} \left(p_k^+ - p_k\right) \\
\lim_{t \rightarrow t_{k+1} -0} p' (t) & = \frac{m}{t_{k+1}-t_k} \left(p_{k+1} - p_{k+1}^-\right) \\
\lim_{t \rightarrow t_k +0} p'' (t) & = \frac{m(m-1)}{(t_{k+1}-t_k)^2} \left(p_k - 2 p_k^+ + p_{k+1}^-\right) \\
\lim_{t \rightarrow t_{k+1} -0} p' (t) & = \frac{m(m-1)}{(t_{k+1}-t_k)^2} \left(p_k^+ - 2 p_{k+1}^- + p_{k+1}\right)
\end{aligned}
t → t k + 0 lim p ′ ( t ) t → t k + 1 − 0 lim p ′ ( t ) t → t k + 0 lim p ′′ ( t ) t → t k + 1 − 0 lim p ′ ( t ) = t k + 1 − t k m ( p k + − p k ) = t k + 1 − t k m ( p k + 1 − p k + 1 − ) = ( t k + 1 − t k ) 2 m ( m − 1 ) ( p k − 2 p k + + p k + 1 − ) = ( t k + 1 − t k ) 2 m ( m − 1 ) ( p k + − 2 p k + 1 − + p k + 1 )
因此曲线在 t k t_k t k 处的高阶连续性条件为
p k − p k − t k − t k − 1 = p k + − p k t k + 1 − t k p k − 1 + − 2 p k − + p k ( t k − t k − 1 ) 2 = p k − 2 p k + + p k + 1 − ( t k + 1 − t k ) 2 (2) \begin{aligned}
\frac{p_k - p_k^-}{t_{k}-t_{k-1}} & = \frac{p_k^+ - p_k}{t_{k+1}-t_k} \\
\frac{p_{k-1}^+ - 2 p_{k}^- + p_{k}}{(t_{k}-t_{k-1})^2} & = \frac{p_k - 2 p_k^+ + p_{k+1}^-}{(t_{k+1}-t_k)^2}
\end{aligned}
\tag{2}
t k − t k − 1 p k − p k − ( t k − t k − 1 ) 2 p k − 1 + − 2 p k − + p k = t k + 1 − t k p k + − p k = ( t k + 1 − t k ) 2 p k − 2 p k + + p k + 1 − ( 2 )
此时我们有 2 n 2n 2 n 个未确定的控制点和 2 ( n − 1 ) 2(n-1) 2 ( n − 1 ) 个条件, 需要额外再增加 2 个条件以确定唯一的一条曲线, 以下为两种附加条件:
自然端点条件: p ′ ′ ( 0 ) = p ′ ′ ( 1 ) = 0 p''(0) = p''(1) = \mathbf{0} p ′′ ( 0 ) = p ′′ ( 1 ) = 0 ;
Bessel 端点条件: p ′ ( 0 ) = q ′ ( 0 ) , p ′ ( 1 ) = r ′ ( 1 ) p'(0) = q'(0),\ p'(1) = r'(1) p ′ ( 0 ) = q ′ ( 0 ) , p ′ ( 1 ) = r ′ ( 1 ) , 其中 q q q 插值前三个点 ( t 0 , p 0 ) , ( t 1 , p 1 ) , ( t 2 , p 2 ) (t_0, p_0), (t_1, p_1), (t_2, p_2) ( t 0 , p 0 ) , ( t 1 , p 1 ) , ( t 2 , p 2 ) 的 2 次多项式曲线, r r r 是插值后三个点的 2 次多项式曲线.
如下图所示, 不同的附加条件将导致曲线有不同的形状.
如下图所示的是采用自然端点条件绘制的 3 阶自然样条曲线. 其中蓝色折线为插值点, 空心黑色折线为各段 Bézier 曲线的控制多边形, 后者的位置是根据插值点的位置计算出来的.
观察如上的连续性条件可知, 可以发现 p k p_k p k 并非只会影响与它相邻区间中控制点的位置 , 因此移动它也不止会改变与它相邻的两段 Bézier 曲线的形状. 事实上, 在实践中我们有时可以舍弃二阶连续性的条件 (例如 Photoshop 软件中的钢笔工具) 以达到使各个插值点对曲线的影响限制在局部的效果, 这时将把各段 Bézier 曲线的控制点也开放给用户修改.
参数化
通常情况下, 绘制 Bézier 样条曲线时只有给定若干控制点的条件, 而参数结点 { 0 = t 0 < t 1 < ⋯ < t n = 1 } \{0 = t_0 < t_1 < \dots < t_n = 1\} { 0 = t 0 < t 1 < ⋯ < t n = 1 } 的值需要另外确定, Bézier 样条曲线的参数化指的就是确定这一组数的值. 值得注意的是, 通常情况下的参数化是给定某一个曲线或曲面, 然后构造一个它与参数域之间的一一映射, 但这里的参数化则不同, 因为如式 (2) 所示, 所绘制的 Bézier 样条曲线的形状是与参数结点的选取相关的 . 以下为几种参数化方法:
等距参数化 (Equidistant (uniform) parameterization): t k + 1 − t k = const t_{k+1} - t_k = \text{const} t k + 1 − t k = const ;
向心参数化 (Centripetal parameterization) [1] : t k + 1 − t k = ∥ p k + 1 − p k ∥ t_{k+1} - t_k = \sqrt{\|p_{k+1} - p_k\|} t k + 1 − t k = ∥ p k + 1 − p k ∥ .
如下图所示, 不同的参数化方法将导致曲线有不同的形状.
B 样条曲线
B 样条曲线 (B-spline curve) 的 “B” 代表 basis (基), 它的形式与 Bézier 曲线类似, 也是用控制点对基函数作线性组合得到的. B 样条曲线与 Bézier 曲线的不同之处在于它的基函数具有局部支撑性, 并且曲线的阶数与控制点的个数无关.
B 样条基函数
设 ( t 0 , t 1 , … , t m ) (t_0, t_1, \dots, t_m) ( t 0 , t 1 , … , t m ) 为结点向量, t 0 ≤ t 1 ≤ ⋯ ≤ t m t_0 \leq t_1 \leq \dots \leq t_m t 0 ≤ t 1 ≤ ⋯ ≤ t m . 如下的 Cox-de Boor 递归公式 给出了 B 样条基函数 (B-spline basis function) 的定义
N k , 0 ( t ) = { 1 , t k ≤ t < t k + 1 0 , otherwise N k , d ( t ) = t − t k t k + d − t k N k , d − 1 ( t ) + t k + d + 1 − t t k + d + 1 − t k + 1 N k + 1 , d − 1 ( t ) , for d > 1 and k = 0 , … , n \begin{aligned}
N_{k, 0}(t) & =
\left\{\begin{array}{ll}
1, & t_k \leq t<t_{k+1} \\
0, & \text { otherwise }
\end{array}\right. \\
N_{k, d}(t) & =\frac{t-t_k}{t_{k+d}-t_k} N_{k, d-1}(t)+\frac{t_{k+d+1}-t}{t_{k+d+1}-t_{k+1}} N_{k+1, d-1}(t), \
\text{for } d>1 \text{ and } k=0, \dots, n
\end{aligned}
N k , 0 ( t ) N k , d ( t ) = { 1 , 0 , t k ≤ t < t k + 1 otherwise = t k + d − t k t − t k N k , d − 1 ( t ) + t k + d + 1 − t k + 1 t k + d + 1 − t N k + 1 , d − 1 ( t ) , for d > 1 and k = 0 , … , n
N k , d N_{k, d} N k , d 称为 d d d 阶的第 k k k 个 B 样条基函数. 不难发现, N k , d N_{k,d} N k , d 在使它非负的每一个区间 [ t l , t l + 1 ] [t_{l}, t_{l+1}] [ t l , t l + 1 ] 上都是 d d d 次的多项式.
例子
根据定义, 当结点向量中不出现重复时, 计算 B 样条基函数显式表达式的 Mathematica 代码如下:
1 2 3 4 5 6 BsBF [ t_ , k_ , d_ , knotVector_ ] := If [ d == 0 , If [ t >= knotVector [ [ k ] ] && t < knotVector [ [ k + 1 ] ] , 1 , 0 ] , ( t - knotVector [ [ k ] ] ) / ( knotVector [ [ k + d - 1 ] ] - knotVector [ [ k ] ] ) BsBF [ t , k , d - 1 , knotVector ] + ( knotVector [ [ k + d ] ] - t ) / ( knotVector [ [ k + d ] ] - knotVector [ [ k + 1 ] ] ) BsBF [ t , k + 1 , d - 1 , knotVector ] ]
取结点向量为 t i = i t_i = i t i = i , 计算 2 阶的第 2 个 B 样条基函数得到显式表达式为
N 2 , 2 ( t ) = { 1 2 t 2 − t + 1 2 1 ≤ t < 2 ; − t 2 + 5 t − 11 2 2 ≤ t < 3 ; 1 2 t 2 − 4 t + 8 3 ≤ t < 4 ; 0 otherwise . N_{2,2}(t) =
\left\{
\begin{array}{lc}
\frac{1}{2}t^2- t+\frac{1}{2} & 1\leq t<2; \\
-t^2+5 t-\frac{11}{2} & 2\leq t<3; \\
\frac{1}{2} t^2-4 t+8 & 3\leq t<4; \\
0 & \text{otherwise}.
\end{array}
\right.
N 2 , 2 ( t ) = ⎩ ⎨ ⎧ 2 1 t 2 − t + 2 1 − t 2 + 5 t − 2 11 2 1 t 2 − 4 t + 8 0 1 ≤ t < 2 ; 2 ≤ t < 3 ; 3 ≤ t < 4 ; otherwise .
其图像为
这一函数具有局部支撑性. 并且容易验证, 它的 1 阶导数连续, 而 2 阶导数不连续.
B 样条基函数的性质
B 样条基函数具有如下性质
N k , d ( t ) ≥ 0 N_{k,d}(t) \geq 0 N k , d ( t ) ≥ 0 ;
d > 0 d>0 d > 0 时, N k , d ( t ) N_{k,d}(t) N k , d ( t ) 的支撑集为 ( t k , t k + 1 + d ) (t_k, t_{k+1+d}) ( t k , t k + 1 + d ) ;
在任意一个区间 [ t k , t k + 1 ) [t_k, t_{k+1}) [ t k , t k + 1 ) 上至多只有 d + 1 d+1 d + 1 个 d d d 阶基函数非负;
n + 1 n+1 n + 1 个 d d d 阶的 B 样条基函数需要 n + d + 2 n+d+2 n + d + 2 个结点;
单位分解性 (Partition of Unity): 若某一区间上恰有 d + 1 d+1 d + 1 个 d d d 阶基函数非负, 那么这全部的 d + 1 d+1 d + 1 个非负的基函数之和为 1;
若一个结点重复 p p p 次, 则基函数在这一点处是 C d − p C^{d-p} C d − p .
下图为定义在结点向量 ( 0 , 1 , … , 10 ) (0, 1, \dots, 10) ( 0 , 1 , … , 10 ) 上的 7 个 3 阶 B 样条基函数及它们的和.
拥有 d + 1 = 4 d+1 = 4 d + 1 = 4 个非负基函数的区间共有 4 个, 即 [ 3 , 4 ) , … , [ 6 , 7 ) [3, 4),\ \dots,\ [6,7) [ 3 , 4 ) , … , [ 6 , 7 ) , 并且它们的和恰好在这些区间上为 1.
我们知道, Bézier 曲线的 Bernstein 基函数满足单位分解性, 这使得曲线上的每个点都是控制点的凸组合. 同样地, 我们也希望 B 样条曲线也具备同样的性质. 因此对于有 n + 1 n+1 n + 1 个 d d d 阶的 B 样条基函数的曲线, 它的结点向量为 ( t 0 , t 1 , … , t n + d + 1 ) (t_0, t_1, \dots, t_{n+d+1}) ( t 0 , t 1 , … , t n + d + 1 ) , 并且在区间 [ t d , t n + 1 ) [t_d, t_{n+1}) [ t d , t n + 1 ) 上这些基函数满足单位分解性, 取这一区间为曲线的参数域.
B 样条曲线的性质
根据 B 样条基函数的性质, 我们可以得到一些 B 样条曲线的性质.
中间结点只出现 1 次的 d d d 阶 B 样条曲线是 C d − 1 C^{d-1} C d − 1 的;
控制点 p k p_k p k 只影响曲线上 t ∈ [ t k , t k + 1 + d ] t \in [t_k, t_{k+1+d}] t ∈ [ t k , t k + 1 + d ] 的部分;
凸包性, 仿射无关性.
de Boor 算法
在本节中, 我们将介绍如何用 de Boor 算法绘制 B 样条曲线.
根据 B 样条基函数的递归定义, 我们将直接推导出 de Boor 算法.
d d d 阶的 B 样条曲线可以表示为
p ( t ) = ∑ k = 0 n N k , d ( t ) p k p(t) = \sum_{k=0}^{n} N_{k, d} (t) p_{k}
p ( t ) = k = 0 ∑ n N k , d ( t ) p k
其中控制点 p k p_k p k 也被称为 de Boor 点.
假设 t ∈ [ t l , t l + 1 ) t \in [t_{l}, t_{l+1}) t ∈ [ t l , t l + 1 ) , 则根据 Cox-de Boor 递归公式, 有
p ( t ) = ∑ k = 0 n N k , d ( t ) p k = ∑ k = l − d l N k , d ( t ) p k = ∑ k = l − d l ( t − t k t k + d − t k N k , d − 1 ( t ) + t k + d + 1 − t t k + d + 1 − t k + 1 N k + 1 , d − 1 ( t ) ) p k = ∑ k = l − d l t − t k t k + d − t k N k , d − 1 ( t ) p k + ∑ k = l − d + 1 l + 1 t k + d − t t k + d − t k N k , d − 1 ( t ) p k − 1 = ∑ k = l − d + 1 l t − t k t k + d − t k N k , d − 1 ( t ) p k + ∑ k = l − d + 1 l t k + d − t t k + d − t k N k , d − 1 ( t ) p k − 1 = ∑ k = l − d + 1 l ( t − t k t k + d − t k p k + t k + d − t t k + d − t k p k − 1 ) N k , d − 1 ( t ) \begin{aligned}
p(t) & = \sum_{k=0}^{n} N_{k, d} (t) p_{k} = \sum_{k=l-d}^{l} N_{k, d} (t) p_{k} \\
& = \sum_{k=l-d}^{l} \left(\frac{t-t_k}{t_{k+d}-t_k} N_{k, d-1}(t)+\frac{t_{k+d+1}-t}{t_{k+d+1}-t_{k+1}} N_{k+1, d-1}(t)\right) p_k \\
& = \sum_{k=l-d}^{l} \frac{t-t_k}{t_{k+d}-t_k} N_{k, d-1}(t) p_k
+ \sum_{k=l-d+1}^{l+1} \frac{t_{k+d}-t}{t_{k+d}-t_{k}} N_{k, d-1}(t) p_{k-1} \\
& = \sum_{k=l-d+1}^{l} \frac{t-t_k}{t_{k+d}-t_k} N_{k, d-1}(t) p_k
+ \sum_{k=l-d+1}^{l} \frac{t_{k+d}-t}{t_{k+d}-t_{k}} N_{k, d-1}(t) p_{k-1} \\
& = \sum_{k=l-d+1}^{l} \left( \frac{t-t_k}{t_{k+d}-t_k} p_k + \frac{t_{k+d}-t}{t_{k+d}-t_{k}} p_{k-1} \right) N_{k, d-1}(t)
\end{aligned}
p ( t ) = k = 0 ∑ n N k , d ( t ) p k = k = l − d ∑ l N k , d ( t ) p k = k = l − d ∑ l ( t k + d − t k t − t k N k , d − 1 ( t ) + t k + d + 1 − t k + 1 t k + d + 1 − t N k + 1 , d − 1 ( t ) ) p k = k = l − d ∑ l t k + d − t k t − t k N k , d − 1 ( t ) p k + k = l − d + 1 ∑ l + 1 t k + d − t k t k + d − t N k , d − 1 ( t ) p k − 1 = k = l − d + 1 ∑ l t k + d − t k t − t k N k , d − 1 ( t ) p k + k = l − d + 1 ∑ l t k + d − t k t k + d − t N k , d − 1 ( t ) p k − 1 = k = l − d + 1 ∑ l ( t k + d − t k t − t k p k + t k + d − t k t k + d − t p k − 1 ) N k , d − 1 ( t )
现令
p k ( r ) ( t ) = { ( 1 − α k ( r − 1 ) ( t ) ) p k − 1 ( r − 1 ) ( t ) + α k ( r − 1 ) ( t ) p k ( r − 1 ) ( t ) if 1 ≤ r ≤ d p k if r = 0 p_k^{(r)}(t) =
\left\{\begin{array}{ll}
(1 - \alpha_k^{(r-1)} (t)) p_{k-1}^{(r-1)} (t) + \alpha_k^{(r-1)}(t) p_{k}^{(r-1)}(t) & \text{if } 1 \leq r \leq d \\
p_k & \text{if } r = 0
\end{array}\right.
p k ( r ) ( t ) = { ( 1 − α k ( r − 1 ) ( t )) p k − 1 ( r − 1 ) ( t ) + α k ( r − 1 ) ( t ) p k ( r − 1 ) ( t ) p k if 1 ≤ r ≤ d if r = 0
其中
α k r = t − t k t k + d − r − t k \alpha_k^r = \frac{t-t_k}{t_{k+d-r}-t_k}
α k r = t k + d − r − t k t − t k
则有
p ( t ) = ∑ k = l − d + 1 l ( t k + d − 1 − t t k + d − 1 − t k p k − 1 + t − t k t k + d − 1 − t k p k ) N k , d − 1 ( t ) = ∑ k = l − d + 1 l p k ( 1 ) ( t ) N k , d − 1 ( t ) = ∑ k = l − d + r l p k ( r ) ( t ) N k , d − r ( t ) = p l ( d ) ( t ) \begin{aligned}
p(t) & = \sum_{k=l-d+1}^{l} \left( \frac{t_{k+d-1}-t}{t_{k+d-1}-t_{k}} p_{k-1} + \frac{t-t_k}{t_{k+d-1}-t_k} p_k \right) N_{k, d-1}(t) \\
& = \sum_{k=l-d+1}^{l} p_k^{(1)}(t) N_{k, d-1}(t) = \sum_{k=l-d+r}^{l} p_k^{(r)}(t) N_{k, d-r}(t) \\
& = p_l^{(d)}(t)
\end{aligned}
p ( t ) = k = l − d + 1 ∑ l ( t k + d − 1 − t k t k + d − 1 − t p k − 1 + t k + d − 1 − t k t − t k p k ) N k , d − 1 ( t ) = k = l − d + 1 ∑ l p k ( 1 ) ( t ) N k , d − 1 ( t ) = k = l − d + r ∑ l p k ( r ) ( t ) N k , d − r ( t ) = p l ( d ) ( t )
根据上述讨论, de Boor 算法计算 B 样条曲线的算法如下:
1 2 3 4 5 6 7 8 find l satisfying t_l <= t < t_ {l+1 }for k = l - d, ..., l q[k - l + d] = p[k]for r = 1 , ..., d for k = l, ..., l - d + r a = (t - t[k]) / (t[k + d - r] - t[k]) q[k - d + r] = (1 - a) * q[k - 1 - d + r] + a * q[k - d + r] output: q[d]
结点向量
和 Bézier 样条曲线类似地, B 样条曲线的形状也与结点向量的选取有关. 若某一 d d d 阶的 B 样条曲线有 n + 1 n+1 n + 1 个控制点, 则它有 n + d + 2 n+d+2 n + d + 2 个参数结点, 以下是几种结点向量的选取方法:
均匀 B 样条: t k + 1 − t k = const t_{k+1} - t_k = \text{const} t k + 1 − t k = const ;
准均匀 B 样条: 设 s k = k m s_k = \frac{k}{m} s k = m k , 节点向量为 ( t 0 , t 1 , … , t n + d + 1 ) = ( s 0 , s 0 , … , s 0 ⏞ 重复 d + 1 次 , s 1 , … , s m − 1 , s m , s m , … , s m ⏞ 重复 d + 1 次 ) (t_0, t_1, \dots, t_{n+d+1})
= (\overbrace{s_0, s_0, \dots, s_0}^{\text{重复 } d+1 \text{ 次}}, s_1, \dots, s_{m-1}, \overbrace{s_m, s_m, \dots, s_m}^{\text{重复 } d+1 \text{ 次}}) ( t 0 , t 1 , … , t n + d + 1 ) = ( s 0 , s 0 , … , s 0 重复 d + 1 次 , s 1 , … , s m − 1 , s m , s m , … , s m 重复 d + 1 次 ) , 比较等式两端分量个数可知 m = n − d + 1 m = n-d+1 m = n − d + 1 .
分段 Bézier 曲线: 首尾结点重复度[2] 为 d + 1 d+1 d + 1 , 其它结点重复度为 d d d , 则 B 样条基函数退化为若干组 Bernstein 基函数;
非均匀 B 样条基: 最一般的情况, 只要求首尾结点重复度 ≤ d + 1 \leq d+1 ≤ d + 1 , 其它结点重复度 ≤ d \leq d ≤ d .
下图依次为均匀 B 样条基函数, 准均匀 B 样条基函数, 分段 Bernstein 基函数的图像.
在实践中, 通常使用准均匀 B 样条, 它可以保证曲线的首尾分别为首尾的控制点, 即
p ( t 0 ) = p 0 , p ( t n + d + 1 ) = p n p(t_0) = p_0,\ p(t_{n+d+1}) = p_n
p ( t 0 ) = p 0 , p ( t n + d + 1 ) = p n
插值
设有插值点 p 0 , p 1 , … , p m p_0, p_1, \dots, p_m p 0 , p 1 , … , p m , 严格增的参数 s 0 , s 1 , … , s m s_0, s_1, \dots, s_m s 0 , s 1 , … , s m , 要求一条 B 样条曲线, 使得
p ( s k ) = p k , 0 ≤ k ≤ m p(s_k) = p_k,\ 0 \leq k \leq m
p ( s k ) = p k , 0 ≤ k ≤ m
采取 3 阶准均匀 B 样条曲线来解决这一插值问题. 根据上一节中的讨论, 共有 m + 7 m+7 m + 7 个参数结点和 m + 3 m+3 m + 3 个基函数. 结点向量 ( t 0 , t 1 , … , t m + 6 ) (t_0, t_1, \dots, t_{m+6}) ( t 0 , t 1 , … , t m + 6 ) , 满足
s 0 = t 0 = t 1 = t 2 = t 3 s k = t k + 3 , 0 ≤ k ≤ m s m = t m + 3 = t m + 4 = t m + 5 = t m + 6 \begin{aligned}
s_0 & = t_0 = t_1 = t_2 = t_3 \\
s_k & = t_{k+3},\ 0 \leq k \leq m \\
s_m & = t_{m+3} = t_{m+4} = t_{m+5} = t_{m+6}
\end{aligned}
s 0 s k s m = t 0 = t 1 = t 2 = t 3 = t k + 3 , 0 ≤ k ≤ m = t m + 3 = t m + 4 = t m + 5 = t m + 6
记 B 样条曲线的控制点为 d l , 0 ≤ l ≤ m + 2 d_l,\ 0 \leq l \leq m+2 d l , 0 ≤ l ≤ m + 2 , 则曲线的表达式为
p ( t ) = ∑ l = 0 m + 2 N l 3 ( t ) d l p(t) = \sum_{l = 0}^{m+2} N^3_{l}(t) d_l
p ( t ) = l = 0 ∑ m + 2 N l 3 ( t ) d l
各个控制点所满足的条件为
p ( s k ) = p ( t k + 3 ) = ∑ l = 0 m + 2 N l 3 ( t k + 3 ) d l = ∑ l = k k + 2 N l 3 ( t k + 3 ) d l = p k p(s_k) = p(t_{k+3}) = \sum_{l = 0}^{m+2} N^3_{l}(t_{k+3}) d_l = \sum_{l = k}^{k+2} N_l^3(t_{k+3}) d_l = p_k
p ( s k ) = p ( t k + 3 ) = l = 0 ∑ m + 2 N l 3 ( t k + 3 ) d l = l = k ∑ k + 2 N l 3 ( t k + 3 ) d l = p k
此时共有 m + 3 m+3 m + 3 个变量和 m + 1 m+1 m + 1 个条件. 添加自然端点条件 p ′ ′ ( s 0 ) = p ′ ′ ( s m ) = 0 p''(s_0) = p'' (s_m) = 0 p ′′ ( s 0 ) = p ′′ ( s m ) = 0 即可求解出所需要的 3 阶准均匀 B 样条曲线.
如下图所示的是采用自然端点条件绘制的 3 阶准均匀 B 样条曲线. 其中蓝色折线为插值点, 空心黑色折线为 de Boor 点组成的控制多边形, 后者的位置是根据插值点的位置计算出来的.
B 样条曲线与 Bézier 样条曲线
容易发现上一节中 3 阶准均匀自然 B 样条是二阶连续的、首尾二阶导为 0 的分段 3 阶多项式曲线. 那么它和本文中前半部分中介绍的 3 阶自然样条之间有什么关系?
TODO: 3 阶准均匀自然 B 样条和 3 阶自然样条是一个东西吗?