理论--一文了解bspline曲线的理论知识,学会手撸代码

简介:

在规划领域,表达path的方式有离散点,五次多项式,贝塞尔曲线,B样条曲线,螺旋线。作为从业者,掌握一种曲线,对于做轨迹优化是非常有必要的。如果自己想要做一些轨迹优化的项目,能够自己手写一个曲线,还是很有用的。因为搬轮子虽然也可以,但如果如果需要利用曲线特有的性质做一些事儿,就得很了解才行。

在这里插入图片描述

B样条曲线性质和代码示例

参考文献:

https://pages.mtu.edu/~shene/COURSES/cs3621/NOTES/

1.B样条的优势

天然分段,分段之间是天然C2连续的,这对于运动规划是很好的性质,是分段多项式和分段贝塞尔不具备的性质。
二阶连续的特性,使得B样条在拼接处,只需保持控制点不变,就可达到曲率连续,而对于离散点,很难约束拼接处曲率连续,对于五次多项式,倒是可以,但不如b样条方便。

2.理论知识

C ( u ) = ∑ 0 n N i , p ( u ) P i ( 2.1 ) C(u) = \sum_0^nN_{i,p}(u)P_i\qquad \qquad \qquad(2.1) C(u)=0nNi,p(u)Pi(2.1)
三大元素:基函数 N i , p N_{i,p} Ni,p,控制点 P i P_i Pi,节点向量knot vector U = { u 0 , u 1 , . . . , u m } U = \{u_0,u_1,...,u_m\} U={u0,u1,...,um}

数量关系:控制点个数n+1,节点个数m+1,阶数p,m = n + p + 1

三种类型:open, clamped, closed B-spline curve
曲线起点不过第一个控制点;曲线起点通过第一个控制点;曲线闭合。

在这里插入图片描述

2.1 节点向量和基函数

2.1.1 基本概念

有一些概念需要分清楚:

  1. p阶bezier曲线:共有p+1个控制点,只有一段轨迹
  2. p阶b-spline曲线:控制点不限,最少p+1个,多段C2连续的轨迹(段之间天然C2连续)
  3. 分段(peicewise)p阶bezier曲线:控制点不限,多段C2连续的轨迹(段之间C2连续需要边界约束)
    这里需要搞清楚一个问题,每一小段曲线,由相应的p+1个控制点加相应的p+1个基函数确定,那b-样条曲线是如何自动分段,自动选取相应的相应的基函数和控制点的呢?如下图所示:

在这里插入图片描述

  1. 红色控制点生成红色曲线,蓝色控制点生成蓝色曲线,其中由p个控制点是重复使用的。
  2. N i , p ( u ) N_{i,p}(u) Ni,p(u)是一个关于的分段函数,对于指定的 i i i来说, N i , p N_{i,p} Ni,p仅在某一段u的取值范围内是非零的,其他都是0。
  3. 通过 N i , p N_{i,p} Ni,p是否为零,达到指定控制点的目的。根据不同的 u u u,假设3阶,得到3+1个非零的基函数 N i , p , N i + 1 , p , N i + 2 , p , N i + 3 , p N_{i,p},N_{i+1,p},N_{i+2,p},N_{i+3,p} Ni,p,Ni+1,p,Ni+2,p,Ni+3,p
  4. 对于红色曲线,其曲线方程可以看作:
    C ( u ) = N 0 , 3 ( u ) P 0 + N 1 , 3 ( u ) P 1 + N 2 , 3 ( u ) P 3 + N 3 , 3 ( u ) P 3 + 0 ∗ P 4 + 0 ∗ P 5 + 0 ∗ P 6 + 0 ∗ P 7 . . . C(u)=N_{0,3}(u)P_0 + N_{1,3}(u)P_1+N_{2,3}(u)P3+N_{3,3}(u)P_3+0*P_4+0*P_5+0*P_6+0*P_7... C(u)=N0,3(u)P0+N1,3(u)P1+N2,3(u)P3+N3,3(u)P3+0P4+0P5+0P6+0P7...
  5. 对于蓝色曲线,其曲线方程可以看作:
    C ( u ) = 0 ∗ P 0 + N 1 , 3 ( u ) P 1 + N 2 , 3 ( u ) P 3 + N 3 , 3 ( u ) P 3 + N 4 , 3 P 4 + 0 ∗ P 5 + 0 ∗ P 6 + 0 ∗ P 7 . . . C(u)=0*P_0 + N_{1,3}(u)P_1+N_{2,3}(u)P3+N_{3,3}(u)P_3+N_{4,3}P_4+0*P_5+0*P_6+0*P_7... C(u)=0P0+N1,3(u)P1+N2,3(u)P3+N3,3(u)P3+N4,3P4+0P5+0P6+0P7...
2.1.2 节点向量knot vector

在上一节中提到,根据不同的u,可以确定哪几个基函数是非零的,哪些是0。可以直观感受到, N i , p ( u ) N_{i,p}(u) Ni,p(u)是关于u的分段函数,这里的分段,其实就是不同的节点之间的分段。
一些基本名词:

  1. 节点向量knot vector: U = { u 0 , u 1 , u 2 , . . . u m } U=\{u_0, u_1, u_2, ... u_m\} U={u0,u1,u2,...um}
  2. 节点knot: u i u_i ui
  3. knot span: [ u i , u i + 1 ) [u_i, u_{i+1}) [ui,ui+1), 称为第i个knot span
  4. 均匀和非均匀: knot span间隔相等则为均匀b样条
  5. multiple knot: u i = u i + 1 = . . . u i + k − 1 , k > 1 u_i=u_{i+1}=...u_{i+k-1},k>1 ui=ui+1=...ui+k1,k>1,即两个或以上重复knot,k称为multiplicity
  6. simple knot: 没有相同的knot,则该kont为simple knot
(1) 节点向量生成

本文讨论范围为均匀b样条,因此节点是均匀的,且 u 0 < = u 1 < = u 2 . . . < = u m u_0<=u_1<=u_2...<=u_m u0<=u1<=u2...<=um

节点个数:假设n+1个控制点,p阶, m = n + p + 1 m=n+p+1 m=n+p+1,节点个数为 m + 1 m+1 m+1

取值范围 [ u 0 , u m ] [u_0,u_m] [u0,um],常见的是取 u 0 = 0 , u m = 1 u_0=0,u_m=1 u0=0,um=1,当然也可以任意取值,[0,7],然后进行归一化即可

(2) open curve和clamped curve

根据knot vector是否满足 u 0 = u 1 = u 2 , . . . = u p = 0 u_0=u_1=u_2,...=u_p=0 u0=u1=u2,...=up=0 u m − p = u m − p + 1 , . . . = u m = 1 u_{m-p}=u_{m-p+1},...=u_m=1 ump=ump+1,...=um=1区分,下边以p=3为例:

open curve

曲线的起点不经过第一个控制点,其节点向量如为 [ 0 , 0.1 , 0.2 , 0.3 , 0.4 , 0.5 , 0.6 , 0.7 , 0.8 , 0.9 , 1.0 ] [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0] [0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0]

clampled curve

曲线起点经过第一个控制点,其节点向量为 [ 0 , 0 , 0 , 0 , 0.4 , 0.5 , 0.6 , 1.0 , 1.0 , 1.0 , 1.0 ] [0, 0, 0, 0, 0.4, 0.5, 0.6, 1.0, 1.0, 1.0, 1.0] [0,0,0,0,0.4,0.5,0.6,1.0,1.0,1.0,1.0]
原因在后边基函数三角形那里在讲 #三角形

2.1.3 基函数定义

b-spline的基函数,没有明确的公式可以直接计算,只有Cox-de Boor递推形式公式,通过0阶基函数,递推到p阶基函数.

(1) Cox-de Boor递推公式

假设节点向量 U = { 0 , 1 , 2 , 3 , 4 , 5 , 6... } , p = 3 U=\{0,1,2,3,4,5,6...\},p=3 U={0,1,2,3,4,5,6...},p=3

N i , 0 = { 1 if  u i ≤ u < u i + 1 ( 2.3 ) 0 otherwise N_{i,0}= \begin{cases} 1 & \text{if } u_i \leq u < u_{i+1} \\ &&&&&&&&(2.3)\\ 0 & \text{otherwise} \end{cases} Ni,0= 10if uiu<ui+1otherwise(2.3)

N i , p ( u ) = ( u − u i ) u i + p − u i N i , p − 1 ( u ) + u i + p + 1 − u u i + p + 1 − u i + 1 N i + 1 , p − 1 ( u ) ( 2.4 ) 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) \qquad \qquad(2.4) Ni,p(u)=ui+pui(uui)Ni,p1(u)+ui+p+1ui+1ui+p+1uNi+1,p1(u)(2.4)

0阶基函数 N i , 0 N_{i,0} Ni,0是已知的,是分段函数

N 0 , 0 N 0 , 1 N 1 , 0 N 0 , 2 N 1 , 1 N 0 , 3 N 2 , 0 N 1 , 2 N 0 , 4 N 2 , 1 N 1 , 3 N 0 , 5 ( 2.6 ) N 3 , 0 N 2 , 2 N 1 , 4 N 3 , 1 N 2 , 3 N 4 , 0 N 3 , 2 N 4 , 1 N 5 , 0 \begin{aligned} N_{0,0} \\&& N_{0,1}\\ N_{1,0} &&&&N_{0,2} \\&& N_{1,1} &&&&N_{0,3} \\ N_{2,0} &&&&N_{1,2} &&&&N_{0,4} \\&& N_{2,1} &&&&N_{1,3} &&&&N_{0,5}&&&&&&&&(2.6)\\ N_{3,0} &&&&N_{2,2} &&&&N_{1,4} \\&& N_{3,1} &&&&N_{2,3} \\ N_{4,0} &&&&N_{3,2} \\&& N_{4,1}\\ N_{5,0} \end{aligned} N0,0N1,0N2,0N3,0N4,0N5,0N0,1N1,1N2,1N3,1N4,1N0,2N1,2N2,2N3,2N0,3N1,3N2,3N0,4N1,4N0,5(2.6)
N i , 0 N_{i,0} Ni,0的是0阶基函数,它是关于 u u u的分段函数,只有0阶基函数可以通过判断u所在的knot span来确定其值为1还是0。更高阶(1,2,3…)的基函数只能通过低阶基函数递推计算

  • 0阶基函数计算

N 0 , 0 = { 1 if  u 0 ≤ u < u 1 0 if  u 1 ≤ u < u 2 0 if  u 2 ≤ u < u 3 0 otherwise ( 2.7 ) N_{0,0}= \begin{cases} 1 & \text{if } u_0 \leq u < u_1 \\ 0 & \text{if } u_1 \leq u < u_2 \\ 0 & \text{if } u_2 \leq u < u_3 \\ 0 & \text{otherwise} \end{cases} \quad (2.7) N0,0= 1000if u0u<u1if u1u<u2if u2u<u3otherwise(2.7)
N 1 , 0 = { 1 if  u 1 ≤ u < u 2 0 otherwise ( 2.8 ) N_{1,0}= \begin{cases} 1 & \text{if } u_1 \leq u < u_2 \\ 0 & \text{otherwise} \quad (2.8) \end{cases} N1,0={10if u1u<u2otherwise(2.8)

N 2 , 0 = { 1 if  u 1 ≤ u < u 2 0 otherwise ( 2.9 ) N_{2,0}= \begin{cases} 1 & \text{if } u_1 \leq u < u_2 \\ 0 & \text{otherwise} \quad (2.9) \end{cases} N2,0={10if u1u<u2otherwise(2.9)

N 3 , 0 = { 1 if  u 1 ≤ u < u 2 0 otherwise ( 2.10 ) N_{3,0}= \begin{cases} 1 & \text{if } u_1 \leq u < u_2 \\ 0 & \text{otherwise} \quad (2.10) \end{cases} N3,0={10if u1u<u2otherwise(2.10)

  • 1阶基函数计算

由公式2.4,递推计算 N i , 1 N_i,1 Ni,1:
N 0 , 1 ( u ) = u − u 0 u 1 − u 0 N 0 , 0 ( u ) + u 2 − u u 2 − u 1 N 1 , 0 ( u ) N_{0,1}(u)=\frac{u-u_0}{u_1-u_0}N_{0,0}(u)+\frac{u_2-u}{u_2-u_1}N_{1,0}(u) N0,1(u)=u1u0uu0N0,0(u)+u2u1u2uN1,0(u)

u 0 = 0 , u 1 = 1 , u 2 = 2 u_0=0,u_1=1,u_2=2 u0=0,u1=1,u2=2带入上式,得到:

N 0 , 1 ( u ) = u N 0 , 0 ( u ) + ( 2 − u ) N 1 , 0 ( u ) N_{0,1}(u)=uN_{0,0}(u)+(2-u)N_{1,0}(u) N0,1(u)=uN0,0(u)+(2u)N1,0(u)

u ∈ [ 0 , 1 ) 时, N 0 , 0 = 1 , 否则为 0 u\in[0,1)时,N_{0,0}=1,否则为0 u[0,1)时,N0,0=1,否则为0,当 u ∈ [ 1 , 2 ) 时, N 1 , 0 = 1 , 否则为 0 u\in[1,2)时,N_{1,0}=1,否则为0 u[1,2)时,N1,0=1,否则为0,因此可以得到 N 0 , 1 N_0,1 N0,1的分段函数为:

N 0 , 1 = { u N 0 , 0 ( u ) 0 < = u < 1 ( 2 − u ) N 1 , 0 ( u ) 1 < = u < 2 0 o t h e r w i s e \begin{equation} N_{0,1}= \left\{ \begin{aligned} uN_{0,0}(u) & & 0<=u<1 \\ (2-u)N_{1,0}(u) & & 1<=u<2 \\ 0 & &otherwise \end{aligned} \right. \end{equation} N0,1= uN0,0(u)(2u)N1,0(u)00<=u<11<=u<2otherwise
N 1 , 1 , N 2 , 1 , N 3 , 1 . . . 同理可得,不再赘述 N_{1,1},N_{2,1},N_{3,1}...同理可得,不再赘述 N1,1,N2,1,N3,1...同理可得,不再赘述

  • 2阶基函数计算
    同理可以推导出2阶基函数:

N 0 , 2 ( u ) = u − u 0 u 2 − u 0 N 0 , 1 ( u ) + u 3 − u u 3 − u 1 N 1 , 1 ( u ) N_{0,2}(u)=\frac{u-u_0}{u_2-u_0}N_{0,1}(u)+\frac{u_3-u}{u_3-u_1}N_{1,1}(u) N0,2(u)=u2u0uu0N0,1(u)+u3u1u3uN1,1(u)
N 0 , 2 ( u ) = 0.5 u N 0 , 1 ( u ) + 0.5 ( 3 − u ) N 1 , 1 ( u ) N_{0,2}(u)=0.5uN_{0,1}(u)+0.5(3-u)N_{1,1}(u) N0,2(u)=0.5uN0,1(u)+0.5(3u)N1,1(u)
N 0 , 2 = { 0.5 u N 0 , 1 ( u ) 0 < = u < 1 0.5 u N 0 , 1 ( u ) + 0.5 ( 3 − u ) N 1 , 1 ( u ) 1 < = u < 2 0.5 ( 3 − u ) N 1 , 1 ( u ) 2 < = u < 3 0 o t h e r w i s e \begin{equation} N_{0,2}= \left\{ \begin{aligned} 0.5uN_{0,1}(u) & & 0<=u<1 \\ 0.5uN_{0,1}(u) + 0.5(3-u)N_{1,1}(u) & & 1<=u<2 \\ 0.5(3-u)N_{1,1}(u) & & 2<=u<3 \\ 0 & & otherwise \end{aligned} \right. \end{equation} N0,2= 0.5uN0,1(u)0.5uN0,1(u)+0.5(3u)N1,1(u)0.5(3u)N1,1(u)00<=u<11<=u<22<=u<3otherwise

  • 3阶基函数计算

https://www.ibiblio.org/e-notes/Splines/basis.html
N 0 , 3 ( u ) = u − u 0 u 3 − u 0 N 0 , 2 ( u ) + u 4 − u u 4 − u 1 N 1 , 2 ( u ) N_{0,3}(u)=\frac{u-u_0}{u_3-u_0}N_{0,2}(u)+\frac{u_4-u}{u_4-u_1}N_{1,2}(u) N0,3(u)=u3u0uu0N0,2(u)+u4u1u4uN1,2(u)

总结递推规律如下图所示。
需要注意一个特点,基函数的非零区间,随着阶数增加,逐步增加。

  • 如0阶基函数 N i , 0 N_{i,0} Ni,0的非零区间为 [ u i , u i + 1 ) [u_i,u_{i+1}) [ui,ui+1)
  • 1阶基函数 N i , 1 N_{i,1} Ni,1的非零区间为 [ u i , u i + 2 ) [u_i,u_{i+2}) [ui,ui+2)
  • 即p阶基函数 N i , p N_{i,p} Ni,p的非零区间为 [ u i , u i + p + 1 ) [u_i,u_{i+p+1}) [ui,ui+p+1)

在这里插入图片描述

2.1.4 重要性质

下边性质是非常重要的,想要自己写一个b样条曲线,必须要明白,其中性质2和性质3是写出基函数的关键,必须要理解。

性质1 N i , p ( u ) N_{i,p}(u) Ni,p(u)关于u的是p阶多项式,准确说是分段多项式函数 #性质1

性质2 N i , p ( u ) N_{i,p}(u) Ni,p(u)的非零区间为 [ u i , u i + p + 1 ) [u_i,u_{i+p+1}) [ui,ui+p+1) #性质2

以三阶基函数为例, N 1 , 3 N_{1,3} N1,3是由 N 1 , 2 、 N 2 , 2 N_{1,2}、N_{2,2} N1,2N2,2递推得到,以此类推, N 1 , 0 , N 2 , 0 , N 3 , 0 , N 4 , 0 N_{1,0},N_{2,0},N_{3,0},N_{4,0} N1,0,N2,0,N3,0,N4,0是递推的初始值,其u所在区间为 [ u 1 , u 5 ) [u_1,u_5) [u1,u5),该区间即为 N 1 , 3 N_{1,3} N1,3的非零区间
#三角形1

在这里插入图片描述

性质3:任意span [ u i , u i + 1 ) [u_i,u_{i+1}) [ui,ui+1)的非零基函数是: N i − p , p ( u ) , N i − p + 1 , p ( u ) , N i − p + 2 , p , . . . , N i , p ( u ) N_{i-p,p}(u),N_{i-p+1,p}(u),N_{i-p+2,p},...,N_{i,p}(u) Nip,p(u),Nip+1,p(u),Nip+2,p,...,Ni,p(u) #性质3
#三角形2
以3次b样条为例,对于任意 u u u,如何确定该它属于哪一段b样条,即如何确定哪四个控制点和基函数控制着该段曲线呢,通过下边的三角形可以找到答案
C ( u ) = ∑ 0 n N i , p ( u ) P i C(u) = \sum_0^nN_{i,p}(u)P_i\qquad \qquad \qquad C(u)=0nNi,p(u)Pi
假设 u ∈ [ u 3 , u 4 ) u\in[u_3,u_4) u[u3,u4),向右做三角形,如橙色三角形,三角形包含的三阶基函数 N 0 , 3 , N 1 , 3 , N 2 , 3 , N 3 , 3 N_{0,3},N_{1,3},N_{2,3},N_{3,3} N0,3,N1,3,N2,3,N3,3,即 [ u 3 , u 4 ) [u_3,u_4) [u3,u4)上非零3阶基函数只有 N 0 , 3 , N 1 , 3 , N 2 , 3 , N 3 , 3 N_{0,3},N_{1,3},N_{2,3},N_{3,3} N0,3,N1,3,N2,3,N3,3

在这里插入图片描述

性质4:open curve类型,b样条的有效knot为 [ u p , u m − p ] [u_p,u_{m-p}] [up,ump] #性质4
假设p=3,knot个数为m+1,m=7,则有效knot为 [ u 3 , u 4 ) [u_3,u_4) [u3,u4),如下图所示。
在这里插入图片描述

思考一下,如果u取在 [ u 0 , u 3 ) [u_0,u_3) [u0,u3),意味着什么?
由 #三角形2 可知,在 [ u 2 , u 3 ) [u_2,u_3) [u2,u3)上,无法找到4个非零基函数,也就无法计算b样条;
另一个解释是,只有在 [ u 3 , u 4 ) [u_3,u_4) [u3,u4),才能使得b样条的二阶导数存在,这个求导性质后边会讲。

性质5:在span [ u i , u i + 1 ) [u_i,u_{i+1}) [ui,ui+1)上,所有非零基函数之和为1 #性质5

性质6:knots的个数为 m + 1 m+1 m+1,基函数个数=控制点个数= n + 1 n+1 n+1 p p p阶,则 m = n + p + 1 m=n+p+1 m=n+p+1 #性质6

性质7:在一个multiplicity为k的knot,基函数 N i , p ( u ) N_{i,p}(u) Ni,p(u) C p − k C^{p-k} Cpk连续的 #性质7

  1. 对于simple knot,其multiplicity k = 1.

  2. 举个例子,二阶基函数 N 0 , 2 N_{0,2} N0,2是在 [ u 2 , u 3 ) [u_2,u3) [u2,u3)上是 C 1 C^1 C1连续的;

  3. 注意到,根据性质2,可知 N 0 , 2 ( u ) N_{0,2}(u) N0,2(u) [ u 0 , u 3 ) [u_0,u_3) [u0,u3)上都是非零的,为什么只有在 [ u 2 , u 3 ) [u_2,u_3) [u2,u3) C 1 C^1 C1连续呢?这个问题在后边讲完‘两个三角形’后就可以明白 #三角形 先说结论, N 0 , 2 , N 1 , 2 , N 2 , 2 N_{0,2},N_{1,2},N_{2,2} N0,2,N1,2,N2,2三个基函数加上 P 0 , P 1 , P 2 P_0,P_1,P_2 P0,P1,P2三个控制点,共同表示第一段曲线(假设为open curve)。该曲线的u区间为 [ u 2 , u 3 ) [u_2,u_3) [u2,u3)。即其实的u并不是 u 0 u_0 u0,而是 u 0 + p u_{0+p} u0+p

2.2 求值方法(Evalute)

已知控制点和节点向量的情况下,给定u求b样条上的点,即求值(Evalute)操作。De boor算法是一种快速且数值稳定的方法。这里按我理解,b样条求值(Evalute)由三种方式。

2.2.1 de boor算法计算 C ( u ) C(u) C(u)

https://en.wikipedia.org/wiki/De_Boor%27s_algorithm#cite_note-4

de boor算法需要用到一个性质:knot的重复度增加,这个knot对应的非零基函数就会减少,当节点的重复度为 p p p时(p阶b样条),将只剩下一个非零基函数,那么 C ( u ) = N i , p ( u ) = P i C(u)=N_{i,p}(u)=P_i C(u)=Ni,p(u)=Pi
通过不断插入u,使得u对应的非零基函数只有一个,那对应的控制点就是B样条曲线上的点。(注意这里的控制点,会随着插入knot u而重新生成)。
下边举例说明:

Eigen::Vector3d NonUniformBspline::evaluateDeBoor(double t)
{
  if (t < this->u_(this->p_) || t > this->u_(this->m_ - this->p_))
  {
    if (t < this->u_(this->p_))
      t = this->u_(this->p_);
    if (t > this->u_(this->m_ - this->p_))
      t = this->u_(this->m_ - this->p_);
  }
  // determine which [ui,ui+1] lay in
  int k = this->p_;
  while (true)
  {
    if (this->u_(k + 1) >= t)
      break;
    ++k;
  }
  /* deBoor's alg */
  vector<Eigen::Vector3d> d;
  for (int i = 0; i <= p_; ++i)
  {
    d.push_back(control_points_.row(k - p_ + i));
  }
  for (int r = 1; r <= p_; ++r)
  {
    for (int i = p_; i >= r; --i)
    {
      double alpha = (t - u_[i + k - p_]) / (u_[i + 1 + k - r] - u_[i + k - p_]);
      d[i] = (1 - alpha) * d[i - 1] + alpha * d[i];
    }
  }
  return d[p_];
}
2.2.2 de boor递推公式,求出所有的非零基函数(重点掌握)

确定u所处的knot span,挑选相应的基函数和控制点,根据b样条表达式求出 C ( u ) C(u) C(u)。这里需要用到的时基函数的递推公式。
下边举例说明:

2.2.3 计算矩阵表达形式

带入不同的u和控制点,计算 C ( u ) C(u) C(u)。这里需要推导b样条的矩阵表达形式。

本文讨论的是均匀B样条,即节点矢量沿参数轴均匀等距分布。 Δ i = u i + 1 − u i \Delta_i=u_{i+1}-u_i Δi=ui+1ui是一个常数。每一个节点区间 [ u i , u i + 1 ) [u_i,u_{i+1}) [ui,ui+1)对应着一段b样条曲线,通过归一化将u归一化到 t ∈ [ 0 , 1 ] t\in[0,1] t[0,1],可以用整体的u来表示b样条。
1.归一化
u = u ( t ) = ( 1 − t ) u i + t u i + 1 , t ∈ [ 0 , 1 ] , i = p , p + 1 , . . . n u=u(t)=(1-t)u_i+tu_{i+1}, \quad t\in[0,1],i=p,p+1,...n u=u(t)=(1t)ui+tui+1,t[0,1],i=p,p+1,...n

2.分段表达式
C i ( t ) = C ( u ( t ) ) = ∑ j = i − k i P j N j , p ( u ( t ) ) , t ∈ [ 0 , 1 ] , i = p , p + 1 , . . . n C_i(t)=C(u(t))=\sum_{j=i-k}^iP_jN_{j,p}(u(t)), \quad t\in[0,1],i=p,p+1,...n Ci(t)=C(u(t))=j=ikiPjNj,p(u(t)),t[0,1],i=p,p+1,...n
矩阵表达式如下:
C i ( t ) = [ 1 t t 2 . . . t p ] M p [ p i − p p i − p + 1 ⋮ p i ] , t ∈ [ 0 , 1 ] , i = p , p + 1 , . . . n C_i(t)= \begin{bmatrix} 1 & t & t^2 & ... & t^p \end{bmatrix} M_p \begin{bmatrix} p_{i-p} \\ p_{i-p+1} \\ \vdots \\ p_i\end{bmatrix}, \quad t\in[0,1],i=p,p+1,...n Ci(t)=[1tt2...tp]Mp pippip+1pi ,t[0,1],i=p,p+1,...n
对于二次b样条, p = 2 p=2 p=2,系数矩阵为
M 2 = [ 1 1 0 − 2 2 0 1 − 2 1 ] M_2= \begin{bmatrix} 1 & 1 & 0 \\ -2 & 2 & 0 \\ 1 & -2 & 1 \end{bmatrix} M2= 121122001
对于三次b样条, p = 3 p=3 p=3,系数矩阵为
M 3 = [ 1 4 1 0 − 3 0 3 0 3 − 6 3 0 − 1 3 − 3 1 ] M_3= \begin{bmatrix} 1 & 4 & 1 & 0\\ -3 & 0 & 3 & 0\\ 3 & -6 & 3 & 0\\ -1 & 3 & -3 & 1 \end{bmatrix} M3= 1331406313330001
三次均匀b样条曲线方程的矩阵形式为:
C i ( t ) = [ 1 t t 2 t 3 ] [ 1 4 1 0 − 3 0 3 0 3 − 6 3 0 − 1 3 − 3 1 ] [ p i − 3 p i − 2 p i − 1 p i ] , t ∈ [ 0 , 1 ] , i = p , p + 1 , . . . n C_i(t)= \begin{bmatrix} 1 & t & t^2 & t^3 \end{bmatrix} \begin{bmatrix} 1 & 4 & 1 & 0\\ -3 & 0 & 3 & 0\\ 3 & -6 & 3 & 0\\ -1 & 3 & -3 & 1 \end{bmatrix} \begin{bmatrix} p_{i-3} \\ p_{i-2} \\ p_{i-1} \\ p_i\end{bmatrix}, \quad t\in[0,1],i=p,p+1,...n Ci(t)=[1tt2t3] 1331406313330001 pi3pi2pi1pi ,t[0,1],i=p,p+1,...n
下边举例说明:

Vector2d GetPos(int span_index){
	MatrixXd M3(4,4);
	M3 << -1,  3, -3,  1,
	       3, -6,  3,  0,
	      -3,  0,  3,  0,
	       1,  4,  1,  0;
	
	MatrixXd tm(4,4);
	tm  << tf*tf*tf*tf, tf*tf, tf, 1;
	
	MatrixXd control_points; //记录了所有控制点
	MatrixXd pm(4,2);
	pm = control_points.block(span_index,0,4,2);
	//根据knot span, 从control_points中选取4个控制点
	
	MatrixXd pos = tm*M3*pm;
	return Vector2d(pos(0,0), pos(0,1));
}

2.3 曲率和求导

2.3.1 曲率计算公式:

k = ∣ x ′ y ′ ′ − y ′ x ′ ′ ∣ ( x ′ 2 + y ′ 2 ) 3 2 k=\frac{|x^{'}y^{''}-y^{'}x^{''}|}{(x^{'2}+y^{'2})^{\frac{3}{2}}} k=(x2+y2)23xy′′yx′′
对于b样条来说,假设曲线为2维的,xy坐标系,则 C ( u ) C(u) C(u)是一个二维的点( C ( u ) . x , C ( u ) . y C(u).x,C(u).y C(u).x,C(u).y)。
为了求得曲率,需要求出曲线的一阶 C ′ ( u ) C^{'}(u) C(u)和二阶导数 C ′ ′ ( u ) C^{''}(u) C′′(u)

2.3.2 b样条求导

注:这里不讨论clamped curve,仅讨论open curve
p阶b样条的导数为p-1阶b样条。假设p阶b样条定义为:
C ( u ) = ∑ 0 n N i , p ( u ) P i C(u) = \sum_0^nN_{i,p}(u)P_i C(u)=0nNi,p(u)Pi
b样条的三大元素,节点向量,控制点,基函数,下边分别介绍求导后的b样条的三大元素。
新的基函数:
d d u N i , p ( u ) = N i , p ′ ( u ) = p u i + p − u i N i , p − 1 ( u ) − p u i + p + 1 − u i + 1 N i + 1 , p − 1 ( u ) \frac{\mathrm{d}}{\mathrm{d}u}N_{i,p}(u) =N^{'}_{i,p}(u)=\frac{p}{u_{i+p}-u_i}N_{i,p-1}(u)-\frac{p}{u_{i+p+1}-u_{i+1}}N_{i+1,p-1}(u) dudNi,p(u)=Ni,p(u)=ui+puipNi,p1(u)ui+p+1ui+1pNi+1,p1(u)
曲线求导公式:
d d u C ( u ) = C ′ ( u ) = ∑ i = 0 n − 1 N i + 1 , p − 1 ( u ) Q i \frac{\mathrm{d}}{\mathrm{d}u}C(u)=C^{'}(u)=\sum^{n-1}_{i=0}N_{i+1,p-1}(u)Q_i dudC(u)=C(u)=i=0n1Ni+1,p1(u)Qi
新的控制点 Q i Q_i Qi
(新的控制点 Q i Q_i Qi的个数会比旧的控制点 P i P_i Pi的个数少一个)
Q i = p u i + p + 1 − u i + 1 ( P i + 1 − P i ) , i = 0 , 1 , 2 , . . . n − 1 Q_i=\frac{p}{u_{i+p+1}-u_{i+1}}(P_{i+1}-P_i), \quad i=0,1,2,...n-1 Qi=ui+p+1ui+1p(Pi+1Pi),i=0,1,2,...n1

新节点向量:
原始的节点向量去除首和尾的两个节点,得到新的节点向量。

原始的节点向量: { u 0 , u 1 , u 2 , . . . u m } \{u_0,u_1,u_2,...u_m\} {u0,u1,u2,...um}

新的节点向量: { u 1 , u 2 , . . . u m − 1 } \{u_1,u_2,...u_{m-1}\} {u1,u2,...um1}

更多内容,请关注公众号 哎嗨人生
在这里插入图片描述

  • 25
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值