0.引言
直线方程的参数形式:
{
x
=
x
1
+
(
x
2
−
x
1
)
t
y
=
y
1
+
(
y
2
−
y
1
)
t
,
t
∈
[
0
,
1
]
\left\{\begin{array}{l} x=x_{1}+\left(x_{2}-x_{1}\right) t \\ y=y_{1}+\left(y_{2}-y_{1}\right) t \end{array}, \quad t \in[0,1]\right.
{x=x1+(x2−x1)ty=y1+(y2−y1)t,t∈[0,1]
B样条是为了克服Bezier曲线的缺点而诞生,就是为了克服Bezier的缺点:
- (1)一旦确定了特征多边形的顶点数(n+1)个,也就决定了曲线的阶次(n次)
- (2)Bezier 曲线或曲面的拼接比较复杂
- (3)Bezier 曲线或曲面不能作局部修改
B-Spline(样条—分段连续多项式)曲线优点:
- (1) B-Spline多项式次数可独立于控制点数目(有一定限制)
- (2) B-Spline允许局部控制曲线或曲面
1.de Boor-Cox 递推定义
B-Spline 曲线坐标位置的计算,表示为混合函数形式:
P
(
u
)
=
∑
k
=
0
n
p
k
B
k
,
d
(
u
)
,
u
min
=
u
d
−
1
⩽
u
<
u
max
=
u
n
+
1
,
2
⩽
d
⩽
n
+
1
\mathbf{P}(u)=\sum_{k=0}^{n} \mathbf{p}_{k} B_{k, d}(u), \quad u_{\min }=u_{d-1} \leqslant u < u_{\max }=u_{n+1}, \quad 2 \leqslant d \leqslant n+1
P(u)=k=0∑npkBk,d(u),umin=ud−1⩽u<umax=un+1,2⩽d⩽n+1
- p k \mathbf{p}_{k} pk 为 ( n + 1 ) (n+1) (n+1) 个控制点
- B k , d ( u ) B_{k, d}(u) Bk,d(u) 为 ( d − 1 ) (d-1) (d−1) 次的基函数(混合函数)— d d d 表示 degree 阶数
- 参数 k k k, 取值分别从 0 0 0 到 n n n, 每个控制点对应一个参数(基函数)。
- u u u 为基函数定义域,参考链接.
de Boor-Cox 递推定义:
B
k
,
1
(
u
)
=
{
1
u
k
⩽
u
<
u
k
+
1
0
Otherwise
B
k
,
d
(
u
)
=
u
−
u
k
u
k
+
d
−
1
−
u
k
B
k
,
d
−
1
(
u
)
+
u
k
+
d
−
u
u
k
+
d
−
u
k
+
1
B
k
+
1
,
d
−
1
(
u
)
\begin{aligned} &B_{k, 1}(u)= \begin{cases}1 & u_{k} \leqslant u<u_{k+1} \\ 0 & \text { Otherwise }\end{cases} \\ &B_{k, d}(u)=\frac{u-u_{k}}{u_{k+d-1}-u_{k}} B_{k, d-1}(u)+\frac{u_{k+d}-u}{u_{k+d}-u_{k+1}} B_{k+1, d-1}(u) \end{aligned}
Bk,1(u)={10uk⩽u<uk+1 Otherwise Bk,d(u)=uk+d−1−uku−ukBk,d−1(u)+uk+d−uk+1uk+d−uBk+1,d−1(u)
约定 0 / 0 = 0. 0/0=0. 0/0=0.
B-Spline 曲线的部分性质:
- u m i n u_{min} umin 与 u m a x u_{max} umax 的值取决于 控制点个数、参数 d d d 、如何建立子区间(节点向量)
2.瞎解释
直线的参数方程则插值为: A ∗ t + B ∗ ( 1 − t ) A * t+B *(1-t) A∗t+B∗(1−t)
曲线的整体公式,逼近为: t A + ( 1 − t ) B + ( − 4 t 2 + 4 t ) C t A+(1-t) B+\left(-4 t^{2}+4 t\right) C tA+(1−t)B+(−4t2+4t)C
对于 B-Spline 曲线来讲,B-Spline 曲线坐标位置的计算,表示为混合函数形式:
P
(
u
)
=
∑
k
=
0
n
p
k
B
k
,
d
(
u
)
,
u
min
⩽
u
<
u
max
,
2
⩽
d
⩽
n
+
1
\mathbf{P}(u)=\sum_{k=0}^{n} \mathbf{p}_{k} B_{k, d}(u), \quad u_{\min } \leqslant u < u_{\max }, \quad 2 \leqslant d \leqslant n+1
P(u)=k=0∑npkBk,d(u),umin⩽u<umax,2⩽d⩽n+1
依然是: 曲线逼近 = Σ 控制点 ∗ 基函数 曲线逼近 = \Sigma{控制点 * 基函数} 曲线逼近=Σ控制点∗基函数 这样的方式进行逼近,只是基函数变得更为复杂了。
3.节点向量
一般设置的方法有两种:顺序方法和Clamped方法。前者用于制作标准的B-样条开曲线和闭曲线,后者用于制作一种比较实用的B-样条曲线。顺序列表只需要从0-1线性递增设置即可,Clamped列表则需要将前后各 d d d (阶数)个节点设置成0。
假设曲线有6个控制点,阶数是4阶,那么节点向量大小=5+4+1=10。
-
顺序列表,只需要按顺序设置: 0 , 1 9 , 2 9 , 3 9 , 4 9 , 5 9 , 6 9 , 7 9 , 8 9 , 1 0, \frac{1}{9}, \frac{2}{9}, \frac{3}{9}, \frac{4}{9}, \frac{5}{9}, \frac{6}{9}, \frac{7}{9}, \frac{8}{9}, 1 0,91,92,93,94,95,96,97,98,1 ;
-
Clamped列表,由于是4阶,前面4个参数均设置为0,后面4个参数均设置为1,然后剩余参数均匀递增: 0 , 0 , 0 , 0 , 1 3 , 2 3 , 1 , 1 , 1 , 1 0,0,0,0, \frac{1}{3}, \frac{2}{3}, 1,1,1,1 0,0,0,0,31,32,1,1,1,1
4.基函数
B k , 1 ( u ) = { 1 u k ⩽ u < u k + 1 0 Otherwise B k , d ( u ) = u − u k u k + d − 1 − u k B k , d − 1 ( u ) + u k + d − u u k + d − u k + 1 B k + 1 , d − 1 ( u ) \begin{aligned} &B_{k, 1}(u)= \begin{cases}1 & u_{k} \leqslant u<u_{k+1} \\ 0 & \text { Otherwise }\end{cases} \\ &B_{k, d}(u)=\frac{u-u_{k}}{u_{k+d-1}-u_{k}} B_{k, d-1}(u)+\frac{u_{k+d}-u}{u_{k+d}-u_{k+1}} B_{k+1, d-1}(u) \end{aligned} Bk,1(u)={10uk⩽u<uk+1 Otherwise Bk,d(u)=uk+d−1−uku−ukBk,d−1(u)+uk+d−uk+1uk+d−uBk+1,d−1(u)
举个例子,控制点P为 n + 1 = 5 n+1=5 n+1=5 个,一个 d = 4 d=4 d=4 阶3次B样条, k k k 是从 0 到 n n n,节点数 n + d + 1 = 9 n+d+1=9 n+d+1=9 ,涉及的区间如下(图中最大节点表示方式有区别):
(这里的 t t t 就是前文的 u u u)可以看得出 t 3 − t 5 t3-t5 t3−t5 这个区间内,所有基函数都不为0,因此 t 3 − t 5 t3-t5 t3−t5( u d − 1 = 3 − u n + 1 = 5 u_{d-1=3}- u_{n+1=5} ud−1=3−un+1=5)是该B样条函数的定义区间,这也解释了为什么上面的B样条定义里给出了 t 属于 u d − 1 − u n + 1 u_{d-1}- u_{n+1} ud−1−un+1 区间的条件。
给定的控制点为P0,P1,P2,P3,P4.可以看出P0P1P2P3P4刚好在[t3,t4)区间有定义(基函数的系数,基函数有定义,控制点才有定义),而P1P2P3P4P5,在[t4,t5)区间有定义,因此这个曲线被分成了2段,P0P1P2P3P4和P1P2P3P4P5,两段曲线的控制点P1P2P3是一样,这样就保证了两段曲线衔接非常好了, C d − 2 = 2 C^{d-2=2} Cd−2=2连续。
直观的理解,三次函数逼近需要4个点,一共有5个点,滑窗滑动一次,可逼近出两条三次函数曲线。
算一下:
从参考文章中扒了三个图,意会一下:
5.测试
待更。
2022.01.06更新。利用 C++ 与 pangolin 进行实现显示:
5个控制点:
6个控制点:
7个控制点:
20个控制点(瞎搞):
B样条做平滑: