03-幂基曲线(2)
文章目录
本文属于 “NURBS学习笔记” 专栏,更多文章可以点击↓↓↓
NURBS学习笔记专栏
3. 幂基曲线的修改
3.1 系数可以用于交互修改吗
CAD软件强调几何对象的交互修改:试想当我们通过鼠标交互、文件读取、键盘输入点的信息等方式创建一条幂基曲线后,我们更希望能够通过拖拽附加在曲线上的点等手段完成对曲线的修改。比如公式 ( 13 ) (13) (13) (Lesson 02-幂基曲线(1))所描述的曲线,我们可以给用户提供两个端点及端点上切矢的调整方式,通过鼠标拖动,就可以直观地调整曲线了。再比如,我们可以拖动插值得到的幂基曲线的插值点,从而调整曲线。
再次观察方程
(
8
)
(8)
(8) (Lesson 02-幂基曲线(1)),我们能够得出这样一个认识:当幂基曲线的次数确定时,一组插值点和曲线的系数之间是可以通过一个范德蒙矩阵进行转换的。而从调整曲线的角度看,插值点显然更具有几何直观,当用户选中一个插值点,让其向预期的方向调整,曲线发生的变化也在预期内。调整系数呢?实际上,系数并没有很强的几何直观。其与曲线的最终形态间的关系让设计者难以捉摸。
上图将公式
(
1
)
(1)
(1) (Lesson 02-幂基曲线(1))的幂基曲线本身以及5个系数均绘制出来了,首先可以看到的是曲线本身和系数在空间上是分隔的,而且位置差异比较大。我们分别调整
a
0
\mathbf{a}_0
a0 和
a
1
\mathbf{a}_1
a1 ,将这两个系数分别从原有位置拖动同样的变动量
[
10
,
10
]
[10,10]
[10,10] ,可以看到两个点对曲线的形状的作用是难以预料的:
a
0
\mathbf{a}_0
a0 的变动仅仅改变了曲线的空间位置(
a
0
\mathbf{a}_0
a0 作为常数项确实可以赋予平移变换的意义);
a
1
\mathbf{a}_1
a1 的变动就让曲线的形状发生了较大变化。
系数对曲线最终形态的影响不一致,且没有直观的几何规律。这也是幂基曲线的一个缺点,后面我们将引入Bézier曲线,届时就将惊奇地发现Bézier曲线的系数既能描述曲线,也能直接用于调整曲线,而且具有很强的几何直观。
3.2 对幂基曲线做旋转平移
在CAD中,常常需要对曲线做旋转平移。我们可以用一个旋转矩阵
M
\mathbf{M}
M 和平移矢量
b
\mathbf{b}
b 作用在幂基曲线上,来看看会发生什么事情。我们先对曲线做旋转,而后做平移。
C
n
e
w
(
u
)
=
M
C
(
u
)
+
b
=
M
∑
i
=
0
n
a
i
u
i
+
b
=
∑
i
=
0
n
M
a
i
u
i
+
b
(17)
\mathbf{C}^{new}(u)=\mathbf{M}\mathbf{C}(u)+\mathbf{b}=\mathbf{M}\sum_{i=0}^{n}\mathbf{a}_iu^i+\mathbf{b}=\sum_{i=0}^{n}\mathbf{M}\mathbf{a}_iu^i+\mathbf{b} \tag{17}
Cnew(u)=MC(u)+b=Mi=0∑naiui+b=i=0∑nMaiui+b(17)
可以看到,旋转矩阵是能够最终作用到幂基曲线的系数的,而平移却不行。当我们对次数为
n
n
n ,系数为
a
0
,
a
1
,
…
,
a
n
\mathbf{a}_0,\mathbf{a}_1,\dots,\mathbf{a}_n
a0,a1,…,an 的幂基曲线做平移旋转后,新的系数是
M
a
0
+
b
,
M
a
1
,
…
,
M
a
n
\mathbf{M}\mathbf{a}_0+\mathbf{b},\mathbf{M}\mathbf{a}_1,\dots,\mathbf{M}\mathbf{a}_n
Ma0+b,Ma1,…,Man ,
a
0
\mathbf{a}_0
a0 作为常数项,独自承担了所有的平移操作。我们的直观认识是:曲线作为一个整体,旋转平移后,上面的系数最好是都受到了旋转平移的影响,即我们想要的新的系数是
M
a
0
+
b
,
M
a
1
+
b
,
…
,
M
a
n
+
b
\mathbf{M}\mathbf{a}_0+\mathbf{b},\mathbf{M}\mathbf{a}_1+\mathbf{b},\dots,\mathbf{M}\mathbf{a}_n+\mathbf{b}
Ma0+b,Ma1+b,…,Man+b ,我们从公式上看看这样的期待需要满足什么条件。
M
C
(
u
)
+
b
≠
∑
i
=
0
n
(
M
a
i
+
b
)
u
i
=
∑
i
=
0
n
M
a
i
u
i
+
b
∑
i
=
0
n
u
i
(18)
\mathbf{M}\mathbf{C}(u)+\mathbf{b}\ne\sum_{i=0}^{n}(\mathbf{M}\mathbf{a}_i+\mathbf{b})u^i=\sum_{i=0}^{n}\mathbf{M}\mathbf{a}_iu^i+\mathbf{b}\sum_{i=0}^{n}u^i \tag{18}
MC(u)+b=i=0∑n(Mai+b)ui=i=0∑nMaiui+bi=0∑nui(18)
上式中,只要 ∑ i = 0 n u i = 1 \sum_{i=0}^{n}u^i=1 ∑i=0nui=1 对任何的 u u u 都满足,那么公式的等号就是成立的。也就是说,基函数需要满足 规范性。很显然,目前的幂基并不满足这个条件。这又是幂基曲线的一个缺点。
3.2.1 基的规范化
自然地,我们想到是否可以对幂基改造成规范化的,比如当确定了次数
n
n
n ,构造如下所示的一组基,即让
1
,
u
1
,
u
2
,
…
,
u
n
1,u^{1},u^{2},\dots,u^{n}
1,u1,u2,…,un 除以它们的加和。
1
∑
i
=
0
n
u
i
,
u
∑
i
=
0
n
u
i
,
…
,
u
n
∑
i
=
0
n
u
i
0
≤
u
≤
1
(19)
\frac{1}{\sum_{i=0}^{n}u^i},\frac{u}{\sum_{i=0}^{n}u^i},\dots,\frac{u^n}{\sum_{i=0}^{n}u^i} \quad 0\le u\le 1 \tag{19}
∑i=0nui1,∑i=0nuiu,…,∑i=0nuiun0≤u≤1(19)
这是满足了规范性的一组基,我们不妨举例看看这样的曲线有没有什么更好的性质。
取
n
=
2
n=2
n=2 ,基函数为
B
0
(
u
)
=
1
1
+
u
+
u
2
B
1
(
u
)
=
u
1
+
u
+
u
2
B
2
(
u
)
=
u
2
1
+
u
+
u
2
0
≤
u
≤
1
(20)
\mathbf{B}_0(u)=\frac{1}{1+u+u^2} \\ \mathbf{B}_1(u)=\frac{u}{1+u+u^2} \\ \mathbf{B}_2(u)=\frac{u^2}{1+u+u^2} \\ \quad 0\le u\le 1 \tag{20}
B0(u)=1+u+u21B1(u)=1+u+u2uB2(u)=1+u+u2u20≤u≤1(20)
为其配置系数
a
0
=
(
1.0
,
0.5
)
T
\mathbf{a}_0=(1.0,0.5)^T
a0=(1.0,0.5)T ,
a
1
=
(
1.0
,
1.0
)
T
\mathbf{a}_1=(1.0,1.0)^T
a1=(1.0,1.0)T ,
a
2
=
(
0.5
,
1.0
)
T
\mathbf{a}_2=(0.5,1.0)^T
a2=(0.5,1.0)T ,则其图像和系数以及图像的构成过程如下图所示。
当我们对这样的曲线进行平移旋转,就可以直接将平移旋转作用在系数上了。比如说,我们要将本例曲线逆时针旋转
θ
=
30
°
\theta=30\degree
θ=30° ,然后向右移动
1.0
1.0
1.0 个单位,向下移动
1.0
1.0
1.0 个单位,则
M
=
(
c
o
s
θ
−
s
i
n
θ
s
i
n
θ
c
o
s
θ
)
=
(
3
2
−
1
2
1
2
3
2
)
(21)
\mathbf{M}=\begin{pmatrix} cos\theta & -sin\theta \\ sin\theta & cos\theta \end{pmatrix}=\begin{pmatrix} \frac{\sqrt{3}}{2} & -\frac{1}{2} \\ \frac{1}{2} & \frac{\sqrt{3}}{2} \end{pmatrix} \tag{21}
M=(cosθsinθ−sinθcosθ)=(2321−2123)(21)
b = [ 1.0 − 1.0 ] T (22) \mathbf{b}=[1.0 -1.0]^T \tag{22} b=[1.0−1.0]T(22)
我们可以计算出新的系数
a
0
n
e
w
=
M
a
0
+
b
=
(
3
2
−
1
2
1
2
3
2
)
(
1.0
0.5
)
+
(
1.0
−
1.0
)
=
(
1.6160
−
0.0670
)
(23)
\mathbf{a}_0^{new}=\mathbf{M}\mathbf{a}_0+\mathbf{b}= \begin{pmatrix} \frac{\sqrt{3}}{2} & -\frac{1}{2} \\ \frac{1}{2} & \frac{\sqrt{3}}{2} \end{pmatrix} \begin{pmatrix} 1.0 \\ 0.5 \end{pmatrix}+ \begin{pmatrix} 1.0 \\ -1.0 \end{pmatrix} =\begin{pmatrix} 1.6160 \\ -0.0670 \end{pmatrix} \tag{23}
a0new=Ma0+b=(2321−2123)(1.00.5)+(1.0−1.0)=(1.6160−0.0670)(23)
a 1 n e w = M a 1 + b = ( 3 2 − 1 2 1 2 3 2 ) ( 1.0 1.0 ) + ( 1.0 − 1.0 ) = ( 1.3660 0.3660 ) (24) \mathbf{a}_1^{new}=\mathbf{M}\mathbf{a}_1+\mathbf{b}= \begin{pmatrix} \frac{\sqrt{3}}{2} & -\frac{1}{2} \\ \frac{1}{2} & \frac{\sqrt{3}}{2} \end{pmatrix} \begin{pmatrix} 1.0 \\ 1.0 \end{pmatrix}+ \begin{pmatrix} 1.0 \\ -1.0 \end{pmatrix} =\begin{pmatrix} 1.3660 \\ 0.3660 \end{pmatrix} \tag{24} a1new=Ma1+b=(2321−2123)(1.01.0)+(1.0−1.0)=(1.36600.3660)(24)
a 2 n e w = M a 2 + b = ( 3 2 − 1 2 1 2 3 2 ) ( 0.5 1.0 ) + ( 1.0 − 1.0 ) = ( 0.9330 0.1160 ) (25) \mathbf{a}_2^{new}=\mathbf{M}\mathbf{a}_2+\mathbf{b}= \begin{pmatrix} \frac{\sqrt{3}}{2} & -\frac{1}{2} \\ \frac{1}{2} & \frac{\sqrt{3}}{2} \end{pmatrix} \begin{pmatrix} 0.5 \\ 1.0 \end{pmatrix}+ \begin{pmatrix} 1.0 \\ -1.0 \end{pmatrix} =\begin{pmatrix} 0.9330 \\ 0.1160 \end{pmatrix} \tag{25} a2new=Ma2+b=(2321−2123)(0.51.0)+(1.0−1.0)=(0.93300.1160)(25)
基函数不变,我们将新的系数带入,得到的就是旋转平移后的曲线了。
基函数满足规范性的另一个优势在上图中并不明显,我们举这样一个例子:
n
=
2
n=2
n=2 ,然后随机取
3
3
3 个系数,分别用幂基和我们构造的具有规范性的基,来对比看看曲线的样子。
发现了吗?我将系数组成的三角形高亮出来了,无论系数怎样变,规范化基曲线总在三角形内,而普通的幂基曲线就不具有这个性质。更一般的,对于非负的规范化基,其曲线总在系数的凸包内。这又该如何理解呢?
非负指的是 B i ( u ) ≥ 0 \mathbf{B}_i(u)\geq 0 Bi(u)≥0 ,规范指的是 ∑ i = 0 n B i ( u ) = 1 \sum_{i=0}^{n}\mathbf{B}_i(u)=1 ∑i=0nBi(u)=1 。对于任意一个取定参数 u ∗ u^* u∗ ,计算其对应的曲线上的点 C ( u ∗ ) \mathbf{C}(u^{*}) C(u∗) 可以看做是对系数 a 0 , a 1 , … , a n \mathbf{a}_0,\mathbf{a}_1,\dots,\mathbf{a}_n a0,a1,…,an 做了线性组合 B 0 ( u ∗ ) , B 1 ( u ∗ ) , … , B n ( u ∗ ) \mathbf{B}_0(u^*),\mathbf{B}_1(u^*),\dots,\mathbf{B}_n(u^*) B0(u∗),B1(u∗),…,Bn(u∗) ,而当 B i ( u ∗ ) ≥ 0 \mathbf{B}_i(u^*)\geq 0 Bi(u∗)≥0 且 ∑ i = 0 n B i ( u ∗ ) = 1 \sum_{i=0}^{n}\mathbf{B}_i(u^*)=1 ∑i=0nBi(u∗)=1 ,则曲线上的点 C ( u ∗ ) \mathbf{C}(u^{*}) C(u∗) 就是 a 0 , a 1 , … , a n \mathbf{a}_0,\mathbf{a}_1,\dots,\mathbf{a}_n a0,a1,…,an 的 凸组合 了。 a 0 , a 1 , … , a n \mathbf{a}_0,\mathbf{a}_1,\dots,\mathbf{a}_n a0,a1,…,an 中任意有限个点的凸组合的全体称为 a 0 , a 1 , … , a n \mathbf{a}_0,\mathbf{a}_1,\dots,\mathbf{a}_n a0,a1,…,an 的凸包。所以我们就可以得出:当参数曲线的基是非负的规范化基,则曲线在系数的凸包内。
计算系数 a 0 , a 1 , … , a n \mathbf{a}_0,\mathbf{a}_1,\dots,\mathbf{a}_n a0,a1,…,an 的凸包是一个经典的计算几何中的问题。当我们确定了这个凸包,也就获知了这组系数确定的非负规范化基参数曲线的一个范围。利用这个范围我们可以做很多事情:
- 如果有两个非负规范化基参数曲线 C 1 ( u ) \mathbf{C}_{1}(u) C1(u) 和 C 2 ( v ) \mathbf{C}_{2}(v) C2(v),需要对其进行求交,则我们可以先计算两条曲线的凸包,如果凸包是相交的,则曲线可能也是相交的,可以根据曲线的类别做进一步分析;如果凸包都不相交,则曲线必然不交。由此,我们实现了对曲线求交的一种加速判断。值得一提的是,CAD中会根据几何对象构建各种层次的范围估计,这就是包围盒技术,如轴对齐包围盒(Axis-aligned bounding box,AABB)。凸包也是一类包围盒。
- 曲线更加可控了,当我们知道了这类曲线的系数,就对曲线的位置有了明确的把握:曲线一定在系数的凸包内。让曲线可控、易控是我们提出形式更复杂的曲线的根本动力之一。
3.2.2 另一类规范化基
另一种很难想到的构造方式是:既然基函数要满足
∑
i
=
0
n
B
i
(
u
)
=
1
\sum_{i=0}^{n}\mathbf{B}_i(u)=1
∑i=0nBi(u)=1 ,那我们就选择
n
n
n 个含
u
u
u 的表达式,使得其加和为
1
1
1 。可以将
1
1
1 看作是
1
=
(
u
+
(
1
−
u
)
)
n
1=(u+(1-u))^n
1=(u+(1−u))n 然后将其进行二项式展开。则有
1
=
(
u
+
(
1
−
u
)
)
n
=
∑
i
=
0
n
(
n
i
)
u
i
(
1
−
u
)
n
−
i
=
n
!
0
!
(
n
−
0
)
!
u
0
(
1
−
u
)
n
−
0
+
n
!
1
!
(
n
−
1
)
!
u
1
(
1
−
u
)
n
−
1
+
⋯
+
n
!
i
!
(
n
−
i
)
!
u
i
(
1
−
u
)
n
−
i
+
⋯
+
n
!
n
!
(
n
−
n
)
!
u
n
(
1
−
u
)
n
−
n
(26)
\begin{aligned} 1&=(u+(1-u))^n \\ &=\sum_{i=0}^{n}{n \choose i}u^i(1-u)^{n-i} \\ &=\frac{n!}{0!(n-0)!}u^0(1-u)^{n-0}+\frac{n!}{1!(n-1)!}u^1(1-u)^{n-1}+\dots+\frac{n!}{i!(n-i)!}u^i(1-u)^{n-i}+\dots+\frac{n!}{n!(n-n)!}u^n(1-u)^{n-n} \\ \end{aligned} \tag{26}
1=(u+(1−u))n=i=0∑n(in)ui(1−u)n−i=0!(n−0)!n!u0(1−u)n−0+1!(n−1)!n!u1(1−u)n−1+⋯+i!(n−i)!n!ui(1−u)n−i+⋯+n!(n−n)!n!un(1−u)n−n(26)
那么就有
B
0
,
n
(
u
)
=
n
!
0
!
(
n
−
0
)
!
u
0
(
1
−
u
)
n
−
0
=
(
1
−
u
)
n
B
1
,
n
(
u
)
=
n
!
1
!
(
n
−
1
)
!
u
1
(
1
−
u
)
n
−
1
=
n
⋅
u
(
1
−
u
)
n
−
1
B
2
,
n
(
u
)
=
n
!
2
!
(
n
−
2
)
!
u
2
(
1
−
u
)
n
−
2
=
n
(
n
−
1
)
2
⋅
1
⋅
u
2
(
1
−
u
)
n
−
2
⋮
B
i
,
n
(
u
)
=
n
!
i
!
(
n
−
i
)
!
u
i
(
1
−
u
)
n
−
i
=
n
(
n
−
1
)
⋯
(
n
−
i
+
1
)
i
⋅
(
i
−
1
)
⋅
(
i
−
2
)
⋯
2
⋅
1
⋅
u
i
(
1
−
u
)
n
−
i
⋮
B
n
,
n
(
u
)
=
n
!
n
!
(
n
−
n
)
!
u
n
(
1
−
u
)
n
−
n
=
u
n
(27)
\begin{aligned} \mathbf{B}_{0,n}(u)&=\frac{n!}{0!(n-0)!}u^0(1-u)^{n-0}=(1-u)^n \\ \mathbf{B}_{1,n}(u)&=\frac{n!}{1!(n-1)!}u^1(1-u)^{n-1}=n\cdot u(1-u)^{n-1} \\ \mathbf{B}_{2,n}(u)&=\frac{n!}{2!(n-2)!}u^2(1-u)^{n-2}=\frac{n(n-1)}{2\cdot 1}\cdot u^2(1-u)^{n-2} \\ \vdots \\ \mathbf{B}_{i,n}(u)&=\frac{n!}{i!(n-i)!}u^i(1-u)^{n-i}=\frac{n(n-1)\cdots (n-i+1)}{i\cdot(i-1)\cdot(i-2)\cdots 2 \cdot 1}\cdot u^i(1-u)^{n-i} \\ \vdots \\ \mathbf{B}_{n,n}(u)&=\frac{n!}{n!(n-n)!}u^n(1-u)^{n-n}=u^n \\ \end{aligned} \tag{27}
B0,n(u)B1,n(u)B2,n(u)⋮Bi,n(u)⋮Bn,n(u)=0!(n−0)!n!u0(1−u)n−0=(1−u)n=1!(n−1)!n!u1(1−u)n−1=n⋅u(1−u)n−1=2!(n−2)!n!u2(1−u)n−2=2⋅1n(n−1)⋅u2(1−u)n−2=i!(n−i)!n!ui(1−u)n−i=i⋅(i−1)⋅(i−2)⋯2⋅1n(n−1)⋯(n−i+1)⋅ui(1−u)n−i=n!(n−n)!n!un(1−u)n−n=un(27)
当
n
=
1
n=1
n=1 时
B
0
,
1
(
u
)
=
1
−
u
B
1
,
1
(
u
)
=
u
(28)
\begin{aligned} \mathbf{B}_{0,1}(u)&=1-u \\ \mathbf{B}_{1,1}(u)&=u \\ \end{aligned} \tag{28}
B0,1(u)B1,1(u)=1−u=u(28)
当
n
=
2
n=2
n=2 时
B
0
,
2
(
u
)
=
(
1
−
u
)
2
B
1
,
2
(
u
)
=
2
⋅
u
(
1
−
u
)
B
2
,
2
(
u
)
=
u
2
(29)
\begin{aligned} \mathbf{B}_{0,2}(u)&=(1-u)^2 \\ \mathbf{B}_{1,2}(u)&=2\cdot u(1-u) \\ \mathbf{B}_{2,2}(u)&=u^2 \\ \end{aligned} \tag{29}
B0,2(u)B1,2(u)B2,2(u)=(1−u)2=2⋅u(1−u)=u2(29)
当
n
=
3
n=3
n=3 时
B
0
,
3
(
u
)
=
(
1
−
u
)
3
B
1
,
3
(
u
)
=
3
⋅
u
(
1
−
u
)
2
B
2
,
3
(
u
)
=
3
⋅
u
2
(
1
−
u
)
B
3
,
3
(
u
)
=
u
3
(30)
\begin{aligned} \mathbf{B}_{0,3}(u)&=(1-u)^3 \\ \mathbf{B}_{1,3}(u)&=3\cdot u(1-u)^2 \\ \mathbf{B}_{2,3}(u)&=3\cdot u^2(1-u) \\ \mathbf{B}_{3,3}(u)&=u^3 \\ \end{aligned} \tag{30}
B0,3(u)B1,3(u)B2,3(u)B3,3(u)=(1−u)3=3⋅u(1−u)2=3⋅u2(1−u)=u3(30)
可以看到,这样的基每一项都是关于 u u u 的 n n n 次多项式。其实这就是鼎鼎有名的 Bezier基 ,由其构成的曲线就是 Bezier曲线 。关于Bezier曲线,我还将花大篇幅专门讲解,此处浅尝辄止,仅希望读者可以对比幂基曲线感受 Bezier基 的规范性,以及由规范性带来的好处:旋转平移直接作用在基的系数上,曲线位于系数的凸包内 。而 Bezier基 的好处远不止于此,它的几何直观、计算的稳定性都会让幂基曲线相形见绌,以至于各类图形学相关的接口难见幂基曲线、曲面,而将Bezier曲线、曲面作为一种基础的设施。
为什么要将 1 1 1 看做 ( u + ( 1 − u ) ) n (u+(1-u))^n (u+(1−u))n ,这颇有强行说理的味道。历史上,Bezier曲线的由来也并非是Bezier本人恰好凑出了 1 = ( u + ( 1 − u ) ) n 1=(u+(1-u))^n 1=(u+(1−u))n ,而后又惊奇地发现了它具有诸般良好性质。实际上,Bezier基也叫伯恩斯坦基或伯恩斯坦多项式(Bernstein polynomial),他是前苏联数学家谢尔盖·伯恩斯坦(Sergei Bernstein)于1912年提出,而在半个世纪后的70年代,Bezier才将由伯恩斯坦多项式构成的曲线发扬光大。
3.3 能局部修改的幂基曲线
回到一般的幂基曲线。我们再想想当用户拖动某一个元素时,他的设计意图是什么?他更希望的对某个局部的拖动只会影响曲线局部。我们再看看“三次幂基曲线的调整”示意图。不管我的调整是什么,整根曲线都将发生改变,虽然有些部分的改变很微小。但这种“顾头不顾腚”式的交互方式显然会给设计者带来不好的交互体验。为什么会发生这种事情?我们可以从基函数的角度理解。幂基曲线的基函数在整个定义域内都是非0的(除了起始点),那这就意味着,我们对任意一个系数做微小的调整,都将作用到整根曲线上。或者我们说幂基的支撑区域是整个定义域,它不具有局部支撑性。那什么样子的基函数才具有局部支撑呢?我们可以构造这样的一组基函数。
B
0
(
u
)
=
{
1
,
0
≤
u
<
1
3
0
,
o
t
h
e
r
B
1
(
u
)
=
{
u
,
1
3
≤
u
<
2
3
0
,
o
t
h
e
r
B
2
(
u
)
=
{
u
2
,
2
3
≤
u
≤
1
0
,
o
t
h
e
r
(31)
\begin{aligned} \mathbf{B}_0(u)&=\left\{\begin{matrix}\begin{aligned} &1, \quad 0\le u< \frac{1}{3} \\ &0, \quad other \end{aligned}\end{matrix}\right. \\ \mathbf{B}_1(u)&=\left\{\begin{matrix}\begin{aligned} &u, \quad \frac{1}{3}\le u< \frac{2}{3} \\ &0, \quad other \end{aligned}\end{matrix}\right. \\ \mathbf{B}_2(u)&=\left\{\begin{matrix}\begin{aligned} &u^2, \quad \frac{2}{3}\le u\le 1 \\ &0, \quad other \end{aligned}\end{matrix}\right. \end{aligned} \tag{31}
B0(u)B1(u)B2(u)=⎩
⎨
⎧1,0≤u<310,other=⎩
⎨
⎧u,31≤u<320,other=⎩
⎨
⎧u2,32≤u≤10,other(31)
实际上我们只是将
2
2
2 次幂基曲线的基函数进行了修改,把它做成分段的了。我们可以搭配
3
3
3 个系数
a
0
(
0
,
0
)
\mathbf{a}_0(0,0)
a0(0,0) ,
a
1
(
1
,
1
)
\mathbf{a}_1(1,1)
a1(1,1) ,
a
2
(
1
,
2
)
\mathbf{a}_2(1,2)
a2(1,2) 组成一条曲线
C
(
u
)
=
a
2
B
2
(
u
)
+
a
1
B
1
(
u
)
+
a
0
B
0
(
u
)
0
≤
u
≤
1
(32)
\mathbf{C}(u)=\mathbf{a}_2\mathbf{B}_2(u)+\mathbf{a}_1\mathbf{B}_1(u)+\mathbf{a}_0\mathbf{B}_0(u) \quad 0\le u \le 1 \tag{32}
C(u)=a2B2(u)+a1B1(u)+a0B0(u)0≤u≤1(32)
同时将
a
2
(
1
,
2
)
\mathbf{a}_2(1,2)
a2(1,2) 调整至
a
2
(
−
0.5
,
0.5
)
\mathbf{a}_2(-0.5,0.5)
a2(−0.5,0.5) 。我们构造的曲线以及调整过程如下图所示。可以看到,我们在调整点
a
2
\mathbf{a}_2
a2 时,曲线只有一部分发生了改动,但很不幸,这样的构造有一个最大的缺陷:曲线本身分段了。本例曲线分成了三段,其中第一段还退化成了一个点,第二段是一根直线,第三段是一根不太明显的曲线段。当移动
a
2
\mathbf{a}_2
a2 时,仅第三段发生了变动。
诚然,我们构造的具有局部支撑的曲线是粗糙的,那是什么原因导致曲线分段了呢?每一根基函数都发生了阶跃。如下图所示,我们重点分析
u
=
1
/
3
u=1/3
u=1/3 和
u
=
2
/
3
u=2/3
u=2/3 两个参数。当
u
u
u 跨越
1
/
3
1/3
1/3 时,
a
0
B
0
(
u
)
\mathbf{a}_0\mathbf{B}_0(u)
a0B0(u) 的作用突然消失,
a
1
B
1
(
u
)
\mathbf{a}_1\mathbf{B}_1(u)
a1B1(u) 突然开始发生作用;当
u
u
u 跨越
2
/
3
2/3
2/3 时,
a
1
B
1
(
u
)
\mathbf{a}_1\mathbf{B}_1(u)
a1B1(u) 的作用突然消失,
a
2
B
2
(
u
)
\mathbf{a}_2\mathbf{B}_2(u)
a2B2(u) 突然开始发生作用。这是导致曲线发生分段的原因。看来,我们构造的基函数如果想让曲线连续,除了基函数分段外,还需要满足 基函数的消失与出现不要发生阶跃 。让他们在内部点处,起于
0
0
0 ,归于
0
0
0 。
根据上面的要求,我们重新定义一套基函数:
B
0
(
u
)
n
e
w
=
{
1
,
0
≤
u
<
1
3
−
6
u
+
3
,
1
3
≤
u
<
1
2
0
,
o
t
h
e
r
B
1
(
u
)
n
e
w
=
{
2
u
−
1
3
,
1
6
≤
u
<
1
3
u
,
1
3
≤
u
<
2
3
−
4
u
+
10
3
,
2
3
≤
u
<
5
6
0
,
o
t
h
e
r
B
2
(
u
)
n
e
w
=
{
8
3
u
−
4
3
,
1
2
≤
u
<
2
3
u
2
,
2
3
≤
u
≤
1
0
,
o
t
h
e
r
(33)
\begin{aligned} \mathbf{B}_0(u)^{new}&=\left\{\begin{matrix}\begin{aligned} &1, &\quad 0\le u< \frac{1}{3} \\ &-6u+3, &\quad \frac{1}{3}\le u< \frac{1}{2} \\ &0, &\quad other \end{aligned}\end{matrix}\right. \\ \mathbf{B}_1(u)^{new}&=\left\{\begin{matrix}\begin{aligned} &2u-\frac{1}{3}, &\quad \frac{1}{6}\le u< \frac{1}{3} \\ &u, &\quad \frac{1}{3}\le u< \frac{2}{3} \\ &-4u+\frac{10}{3}, &\quad \frac{2}{3}\le u< \frac{5}{6} \\ &0, &\quad other \end{aligned}\end{matrix}\right. \\ \mathbf{B}_2(u)^{new}&=\left\{\begin{matrix}\begin{aligned} &\frac{8}{3}u-\frac{4}{3}, &&\quad \frac{1}{2}\le u< \frac{2}{3} \\ &u^2, &&\quad \frac{2}{3}\le u\le 1 \\ &0, &&\quad other \end{aligned}\end{matrix}\right. \end{aligned} \tag{33}
B0(u)newB1(u)newB2(u)new=⎩
⎨
⎧1,−6u+3,0,0≤u<3131≤u<21other=⎩
⎨
⎧2u−31,u,−4u+310,0,61≤u<3131≤u<3232≤u<65other=⎩
⎨
⎧38u−34,u2,0,21≤u<3232≤u≤1other(33)
这套定义看起来太过复杂,我们绘制出图像看一看。实际上我只是给原有的基函数加上了一段线性的渐入渐出。这样就避免了阶跃的发生,我们预期这样的基函数能够使整段曲线连续,并且在调整某一个系数时,曲线拥有局部支撑。
和上面例子采用同一套系数,并且做同样的调整,看看效果。不错,曲线获得了局部调整的能力,而且还是连续的。当然了,这个曲线并不是光滑连续的,这是因为上面的基函数没有进一步精心构造。你可以试试修改下基函数渐入渐出的曲线段,让曲线看起来够光滑。
好了,到此为止,我们为了满足局部调整且曲线连续,已经把最简单的幂基曲线调整得面目全非。通过上面的一通操作,只希望读者感受下幂基曲线的不足。并对局部调整、连续这些概念有一个初步的感受。在后面当我们引入了B样条的概念时,将有一套新的讲故事的方式把这些概念覆盖到。届时我们不妨再回来看看此时留在本节的这一伏笔。
4. 幂基曲线与圆
幂基曲线已经拥有很高的表达能力了,次数可以调整,幂基对应的系数也可以调整。有了幂基曲线,设计者就能够表达更自由的曲线了。想一下,如果没有幂基曲线,我们能给设计者提供的曲线种类会有什么,最常用的不外乎两种:直线和圆。这两类曲线并不自由:一种曲率恒为0,一种曲率恒为定值。而幂基曲线给了我们更多的可能:可以创建一条曲线,曲率不再是恒定的0或者其他非零值。这么看,直线和圆也可以看做一种特殊的幂基曲线吗?直线固然可以,取
1
1
1 次幂基曲线就行,那圆是否也可以?我们不妨做一个尝试。假设幂基曲线
C
(
u
)
\mathbf{C}(u)
C(u) 表达了单位圆,那它至少要满足下式。
(
a
0
x
+
a
1
x
u
1
+
⋯
+
a
n
x
u
n
)
2
+
(
a
0
y
+
a
1
y
u
1
+
⋯
+
a
n
y
u
n
)
2
=
1
(34)
\left(\mathbf{a}_0^x+\mathbf{a}_1^x{u}^1+\dots+\mathbf{a}_n^x{u}^n\right)^2+\left(\mathbf{a}_0^y+\mathbf{a}_1^y{u}^1+\dots+\mathbf{a}_n^y{u}^n\right)^2=1 \tag{34}
(a0x+a1xu1+⋯+anxun)2+(a0y+a1yu1+⋯+anyun)2=1(34)
对其进行展开、合并同类项是个不小的挑战,硬着头皮试试看,下面的一番推导只有一个简单的结论:幂基曲线不能表达圆。为了不写矢量符号和上角标,我们令
a
i
=
a
i
x
,
b
i
=
a
i
y
i
=
0
,
1
,
2
,
⋯
,
n
(35)
a_i=\mathbf{a}_i^x,b_i=\mathbf{a}_i^y\quad i=0,1,2,\cdots,n \tag{35}
ai=aix,bi=aiyi=0,1,2,⋯,n(35)
那么就有
(
a
0
+
a
1
u
1
+
⋯
+
a
n
u
n
)
2
+
(
b
0
+
b
1
u
1
+
⋯
+
b
n
u
n
)
2
=
1
(
a
0
2
+
b
0
2
−
1
)
+
(
a
0
a
1
+
a
1
a
0
+
b
0
b
1
+
b
1
b
0
)
u
+
(
a
0
a
2
+
a
1
2
+
a
2
a
0
+
b
0
b
2
+
b
1
2
+
b
2
b
0
)
u
2
+
⋯
+
(
∑
k
=
0
i
a
k
a
i
−
k
+
∑
k
=
0
i
b
k
b
i
−
k
)
u
i
+
⋯
+
(
∑
k
=
0
n
a
k
a
n
−
k
+
∑
k
=
0
n
b
k
b
n
−
k
)
u
n
+
(
∑
k
=
1
n
a
k
a
n
+
1
−
k
+
∑
k
=
1
n
b
k
b
n
+
1
−
k
)
u
n
+
1
+
⋯
+
(
∑
k
=
i
n
a
k
a
n
+
i
−
k
+
∑
k
=
i
i
b
k
b
n
+
i
−
k
)
u
n
+
i
+
⋯
+
(
a
n
−
2
a
n
+
a
n
−
1
2
+
a
n
a
n
−
2
+
b
n
−
2
b
n
+
b
n
−
1
2
+
b
n
b
n
−
2
)
u
2
n
−
2
+
(
a
n
−
1
a
n
+
a
n
a
n
−
1
+
b
n
−
1
b
n
+
b
n
b
n
−
1
)
u
2
n
−
1
+
(
a
n
2
+
b
n
2
)
u
2
n
=
0
(36)
\left(a_0+a_1u^1+\dots+a_nu^n\right)^2+\left(b_0+b_1u^1+\dots+b_nu^n\right)^2=1 \\ \color{red} \left( a_0^2 + b_0^2 - 1 \right)+ \left( a_0a_1 + a_1a_0 + b_0b_1 + b_1b_0 \right)u+ \left( a_0a_2 + a_1^2 + a_2a_0 + b_0b_2 + b_1^2 + b_2b_0 \right)u^2+ \cdots \\ \color{red} +\left( \sum_{k=0}^{i}{a_ka_{i-k} }+\sum_{k=0}^{i}{b_kb_{i-k} } \right)u^i +\cdots +\left( \sum_{k=0}^{n}{a_ka_{n-k} }+\sum_{k=0}^{n}{b_kb_{n-k} } \right)u^n \\ \color{blue} +\left( \sum_{k=1}^{n}{a_ka_{n+1-k} }+\sum_{k=1}^{n}{b_kb_{n+1-k} } \right)u^{n+1} +\cdots +\left( \sum_{k=i}^{n}{a_ka_{n+i-k} }+\sum_{k=i}^{i}{b_kb_{n+i-k} } \right)u^{n+i} +\cdots + \\ \color{blue} \left( a_{n-2}a_{n} + a_{n-1}^2 + a_{n}a_{n-2} + b_{n-2}b_{n} + b_{n-1}^2 + b_{n}b_{n-2} \right)u^{2n-2}+ \left( a_{n-1}a_{n} + a_{n}a_{n-1} + b_{n-1}b_{n} + b_{n}b_{n-1} \right)u^{2n-1}+ \left( a_{n}^2 + b_{n}^2\right)u^{2n} \color{black}=0 \tag{36}
(a0+a1u1+⋯+anun)2+(b0+b1u1+⋯+bnun)2=1(a02+b02−1)+(a0a1+a1a0+b0b1+b1b0)u+(a0a2+a12+a2a0+b0b2+b12+b2b0)u2+⋯+(k=0∑iakai−k+k=0∑ibkbi−k)ui+⋯+(k=0∑nakan−k+k=0∑nbkbn−k)un+(k=1∑nakan+1−k+k=1∑nbkbn+1−k)un+1+⋯+(k=i∑nakan+i−k+k=i∑ibkbn+i−k)un+i+⋯+(an−2an+an−12+anan−2+bn−2bn+bn−12+bnbn−2)u2n−2+(an−1an+anan−1+bn−1bn+bnbn−1)u2n−1+(an2+bn2)u2n=0(36)
这个公式也仅仅是看起来很复杂罢了,其按照
u
u
u 的
0
0
0 次到
2
n
2n
2n 次进行合并,就得到了
2
n
+
1
2n+1
2n+1 项。这个方程对于任意的无穷个
u
u
u 都成立,那么可以推知,
u
u
u 的每一项的系数都为
0
0
0 。
我们从 2 n 2n 2n 次项开始分析。既然 a n a n + b n b n = 0 a_{n}a_{n} + b_{n}b_{n}=0 anan+bnbn=0 ,那么 a n = b n = 0 a_n=b_n=0 an=bn=0 ;
再考察 2 n − 2 2n-2 2n−2 次项,其系数为 a n − 2 a n + a n − 1 a n − 1 + a n a n − 2 + b n − 2 b n + b n − 1 b n − 1 + b n b n − 2 = 0 a_{n-2}a_{n} + a_{n-1}a_{n-1} + a_{n}a_{n-2} + b_{n-2}b_{n} + b_{n-1}b_{n-1} + b_{n}b_{n-2}=0 an−2an+an−1an−1+anan−2+bn−2bn+bn−1bn−1+bnbn−2=0 , 那么 a n − 1 a n − 1 + b n − 1 b n − 1 = 0 a_{n-1}a_{n-1} + b_{n-1}b_{n-1}=0 an−1an−1+bn−1bn−1=0 ,从而 a n − 1 = b n − 1 = 0 a_{n-1}=b_{n-1}=0 an−1=bn−1=0 ;
……
考察 2 2 2 次项,其系数为 a 0 a 2 + a 1 a 1 + a 2 a 0 + b 0 b 2 + b 1 b 1 + b 2 b 0 = 0 a_0a_2 + a_1a_1 + a_2a_0 + b_0b_2 + b_1b_1 + b_2b_0=0 a0a2+a1a1+a2a0+b0b2+b1b1+b2b0=0 ,那么 a 1 a 1 + b 1 b 1 = 0 a_1a_1 + b_1b_1=0 a1a1+b1b1=0 ,从而 a 1 = b 1 = 0 a_{1}=b_{1}=0 a1=b1=0。
那么,幂基曲线就成了
C
(
u
)
=
{
x
(
u
)
=
a
0
y
(
u
)
=
b
0
0
≤
u
≤
1
(37)
\mathbf{C}\left(u\right)=\left\{\begin{matrix}\begin{aligned}x\left(u\right)&=a_0 \\y\left(u\right)&=b_0\end{aligned} \end{matrix} \right.\quad 0\le u \le 1 \tag{37}
C(u)={x(u)y(u)=a0=b00≤u≤1(37)
这只是一个点。所以我们就得到了一个结论:幂基曲线不能表达圆。眼看着我们就将用幂基曲线统一直线、圆的表达,结果临门一脚却提到了门框上,还引出了一个大问题——圆应该怎么用幂基曲线表示?
4.1 有理幂基曲线
回想下之前介绍的
1
/
4
1/4
1/4 圆弧的各种表达形式,其中有一个表达形式最接近幂基的形式,只不过其是有理形式。另外,我们可以注意到:
x
(
u
)
x(u)
x(u) 和
y
(
u
)
y(u)
y(u) 的分母都是
1
+
u
2
1+u^2
1+u2 。
C
(
u
)
=
{
x
(
u
)
=
1
−
u
2
1
+
u
2
y
(
u
)
=
2
u
1
+
u
2
0
≤
u
≤
1
(38)
\mathbf{C}\left(u\right)=\left\{\begin{matrix}\begin{aligned} x\left(u\right)&=\frac{1-u^2}{1+u^2} \\ y\left(u\right)&=\frac{2u}{1+u^2} \end{aligned}\end{matrix}\right. \quad 0\le u\le 1 \tag{38}
C(u)=⎩
⎨
⎧x(u)y(u)=1+u21−u2=1+u22u0≤u≤1(38)
熟悉射影几何或者齐次坐标的读者已经能感受到了,上面这个平面上的曲线,实际上是三维空间曲线向平面上做的一个投影。
我们可以构建一个三维曲线
C
H
(
u
)
=
{
x
(
u
)
=
1
−
u
2
y
(
u
)
=
2
u
z
(
u
)
=
1
+
u
2
0
≤
u
≤
1
(39)
\mathbf{C}_H\left(u\right)=\left\{\begin{matrix}\begin{aligned} x\left(u\right)&=1-u^2 \\ y\left(u\right)&=2u \\ z\left(u\right)&=1+u^2 \\ \end{aligned}\end{matrix}\right. \quad 0\le u\le 1 \tag{39}
CH(u)=⎩
⎨
⎧x(u)y(u)z(u)=1−u2=2u=1+u20≤u≤1(39)
将这个三维空间的曲线上的每一点朝向原点向
z
=
1
z=1
z=1 平面上做投影,投影后的曲线是
C
H
(
u
)
p
r
o
j
=
{
x
(
u
)
=
1
−
u
2
1
+
u
2
y
(
u
)
=
2
u
1
+
u
2
z
(
u
)
=
1
+
u
2
1
+
u
2
=
1
0
≤
u
≤
1
(40)
\mathbf{C}_{H(u)}^{proj}=\left\{\begin{matrix}\begin{aligned} x\left(u\right)&=\frac{1-u^2}{1+u^2} \\ y\left(u\right)&=\frac{2u}{1+u^2} \\ z\left(u\right)&=\frac{1+u^2}{1+u^2}=1 \\ \end{aligned}\end{matrix}\right. \quad 0\le u\le 1 \tag{40}
CH(u)proj=⎩
⎨
⎧x(u)y(u)z(u)=1+u21−u2=1+u22u=1+u21+u2=10≤u≤1(40)
可以看到,
C
H
\mathbf{C}_H
CH 在
z
=
1
z=1
z=1 平面上的投影正是
C
\mathbf{C}
C 。我们用动图展示这个投影过程。
另外,我们注意到,
C
H
\mathbf{C}_H
CH 正是一个三维的幂基曲线。
C
H
(
u
)
=
(
−
1
0
1
)
u
2
+
(
0
2
0
)
u
+
(
1
0
1
)
0
≤
u
≤
1
(41)
\begin{aligned} \mathbf{C}_H(u)&= \begin{pmatrix}-1\\0\\1\end{pmatrix}u^2+ \begin{pmatrix}0\\2\\0\end{pmatrix}u+ \begin{pmatrix}1\\0\\1\end{pmatrix} \end{aligned} \quad 0\le u \le 1 \tag{41}
CH(u)=
−101
u2+
020
u+
101
0≤u≤1(41)