对NURBS的一些理解

本文介绍了NURBS曲线的几个核心问题!

NURBS 其名

NURBS是CAD、CAE、CAM、OpenCASCADE、Rhino、SolidWorks等几何系统中非常核心的曲线和曲面表示方法。NURBS全称是:

Non-Uniform Rational B-Spline\text{Non-Uniform Rational B-Spline}

中文通常叫:非均匀有理 B 样条

这个名字可以拆成:

1
2
3
Non-Uniform   非均匀
Rational 有理
B-Spline B 样条

也就是说:NURBS = 非均匀 + 有理 + B 样条

B样条曲线解决了什么问题

普通 Bézier 曲线公式是:

C(t)=i=0nBi,n(t)PiC(t)=\sum_{i=0}^{n}B_{i,n}(t)P_i

其中:

Bi,n(t)=(ni)(1t)nitiB_{i,n}(t)=\binom{n}{i}(1-t)^{n-i}t^i

PiP_i 是控制点,Bi,n(t)B_{i,n}(t) 是 Bernstein 基函数。

Bézier 曲线的优点是:

  • 形式简单
  • 控制点直观
  • 适合低阶曲线
  • 二次、三次 Bézier 很常用

但 Bézier 曲线也有明显缺点:

  • 高阶 Bézier 不稳定
  • 任意一个控制点会影响整条曲线
  • 复杂曲线需要很多段拼接
  • 分段拼接时连续性需要额外处理

也就是说,Bézier 曲线更适合描述“一段曲线”,不太适合统一描述复杂长曲线。

B 样条曲线可以解决以上问题,它可以看作 Bézier 曲线的推广:

C(u)=i=0nNi,p(u)PiC(u)=\sum_{i=0}^{n}N_{i,p}(u)P_i

其中:

  • PiP_i 是控制点
  • Ni,p(u)N_{i,p}(u) 是 B 样条基函数
  • pp 是曲线次数
  • uu 是参数

和 Bézier 不同,B 样条使用的是 Ni,p(u)N_{i,p}(u),而不是 Bernstein 基函数。

B 样条最大的优势是:**局部控制。**也就是说,移动一个控制点通常只影响曲线的一小段,而不会影响整条曲线。

假设一条三次 Bézier 曲线有 4 个控制点:

1
P0, P1, P2, P3

如果移动 P1P_1,整条 Bézier 曲线都会受到影响。而 B 样条可能有很多控制点:

1
P0, P1, P2, P3, P4, P5, P6, ...

对于三次 B 样条,在某个参数区间内,通常只有相邻的 4 个控制点起作用。例如某一段可能只受:

1
P2, P3, P4, P5

影响。

移动 P3P_3 时,只会影响它附近的几段曲线,而不会影响整条曲线。这就是 B 样条的局部支撑性。

数学上,B 样条曲线为:

C(u)=i=0nNi,p(u)PiC(u)=\sum_{i=0}^{n}N_{i,p}(u)P_i

但在某个参数 uu 处,大部分 Ni,p(u)N_{i,p}(u) 都是 00,只有少数几个非零。

对于 pp 次 B 样条,任意一个参数位置通常最多只有:

p+1p+1

个基函数非零。

因此,计算某个点时只需要用局部的 p+1p+1 个控制点。

NURBS 曲线的四大组成

  • 控制点:P0,P1,,PnP_0,P_1,\dots,P_n决定曲线的大致形状。曲线通常不会经过所有控制点,但会被控制多边形牵引。

  • 权重:w0,w1,,wnw_0,w_1,\dots,w_n决定每个控制点对曲线的吸引力。权重越大,曲线越靠近对应控制点。

  • 次数:pp决定曲线的阶数和光滑能力,CAD 中常用2或3。

  • 节点向量:U=[u0,u1,,um]U=[u_0,u_1,\dots,u_m]决定参数分段、局部影响范围和连续性。

什么是节点向量

节点向量是 NURBS / B 样条里最容易让人困惑的概念。

一句话先说结论:节点向量不是空间中的点,而是参数轴上的分段标记。

它决定:

  • 曲线被分成几段
  • 每段由哪些控制点影响(由分段序号和曲线次数决定)
  • 控制点影响范围有多大
  • 曲线是否经过首尾控制点
  • 曲线在某些位置是否光滑
  • 参数 uu 如何对应到曲线上的位置

假设有一条曲线,它的参数叫 uu

我们可以把 uu 看成一条一维数轴:

1
2
3
u 轴:
0 1 2 3 4
|--------|--------|--------|--------|

这里的 0,1,2,3,40,1,2,3,4 就像道路上的里程碑。

NURBS 的节点向量就是这条参数轴上的一串里程碑:

U=[0,0,0,0,1,2,3,4,4,4,4]U=[0,0,0,0,1,2,3,4,4,4,4]

注意:节点值不是控制点坐标,也不是曲线点坐标。它们只是参数 uu 的分段位置。

节点向量和控制点数量的关系

假设:

  • 控制点数量是 n+1n+1
  • 曲线次数是 pp
  • 节点数量是 m+1m+1

它们满足:

m+1=(n+1)+p+1m+1=(n+1)+p+1

也就是:

m=n+p+1m=n+p+1

换句话说:

节点数量=控制点数量+次数+1\text{节点数量}=\text{控制点数量}+\text{次数}+1

有效参数范围

NURBS 的参数范围不一定必须是 [0,1][0,1][0,1][0,1] 只是常见的归一化选择,不是数学规定。

对于一条 pp 次 NURBS 曲线,节点向量为:

U=[u0,u1,,um]U=[u_0,u_1,\dots,u_m]

它的有效参数范围通常是:

[up,ump][u_p,u_{m-p}]

也常写成:

[up,un+1][u_p,u_{n+1}]

其中:

  • pp 是曲线次数
  • n+1n+1 是控制点数量
  • m+1m+1 是节点数量

例如三次曲线:

p=3p=3

节点向量:

U=[0,0,0,0,1,2,3,4,4,4,4]U=[0,0,0,0,1,2,3,4,4,4,4]

那么有效参数范围是:

[u3,u7][u_3,u_7]

查节点向量:

u3=0,u7=4u_3=0,\quad u_7=4

所以:

u[0,4]u\in[0,4]

这条曲线的参数范围就是 [0,4][0,4],不是 [0,1][0,1]

节点值本质上只是参数轴上的刻度,所以可以大于 11,也可以是负数,只要节点向量是非递减序列即可。

节点大于 1 与归一化

节点向量:

[0,0,0,0,1,2,3,4,4,4,4][0,0,0,0,1,2,3,4,4,4,4]

可以整体除以 44,变成:

[0,0,0,0,0.25,0.5,0.75,1,1,1,1][0,0,0,0,0.25,0.5,0.75,1,1,1,1]

这两个节点向量只是做了线性参数变换。

原参数:

u[0,4]u\in[0,4]

新参数:

uˉ[0,1]\bar{u}\in[0,1]

二者关系是:

uˉ=u4\bar{u}=\frac{u}{4}

或者:

u=4uˉu=4\bar{u}

如果控制点和权重不变,它们表示的几何曲线通常是一样的,只是参数表示不同。

例如使用节点向量:

U=[0,0,0,0,1,2,3,4,4,4,4]U=[0,0,0,0,1,2,3,4,4,4,4]

参数取:

u=2u=2

如果归一化为:

Uˉ=[0,0,0,0,0.25,0.5,0.75,1,1,1,1]\bar{U}=[0,0,0,0,0.25,0.5,0.75,1,1,1,1]

那么对应参数是:

uˉ=0.5\bar{u}=0.5

因为:

uˉ=24=0.5\bar{u}=\frac{2}{4}=0.5

这两个参数对应的是曲线上的同一个位置:

CU(2)=CUˉ(0.5)C_U(2)=C_{\bar{U}}(0.5)

所以节点大于 11 并不奇怪,只是参数刻度没有归一化。

节点区间决定曲线分段

仍然看这个例子:

U=[0,0,0,0,1,2,3,4,4,4,4]U=[0,0,0,0,1,2,3,4,4,4,4]

有效参数范围是:

[0,4][0,4]

有效节点区间是:

1
[0,1], [1,2], [2,3], [3,4]

所以这条 NURBS 曲线可以看成由 4 段曲线拼接而成:

1
2
3
4
第 1 段:u ∈ [0,1]
第 2 段:u ∈ [1,2]
第 3 段:u ∈ [2,3]
第 4 段:u ∈ [3,4]

但它们不是随便拼起来的,而是由 B 样条基函数保证连续性。

只有 uk<uk+1u_k < u_{k+1} 的区间才是真正的曲线段。

如果节点重复导致出现:

1
[2,2]

这种零长度区间,它不对应真实曲线段。

根据分段和次数确定控制点

这是理解节点向量最关键的一步。

对于 pp 次 B 样条 / NURBS:

每个非零节点区间内,最多由 p+1 个控制点参与计算\boxed{ \text{每个非零节点区间内,最多由 }p+1\text{ 个控制点参与计算} }

如果参数 uu 落在节点区间:

uku<uk+1u_k \le u < u_{k+1}

那么参与计算的控制点通常是:

Pkp,Pkp+1,,Pk\boxed{ P_{k-p},P_{k-p+1},\dots,P_k }

一共:

p+1p+1

个控制点。

这里的 kk 就是当前 knot span 的索引。

三次 NURBS 分段控制点示例

假设曲线次数为:

p=3p=3

控制点为:

P0,P1,P2,P3,P4,P5,P6P_0,P_1,P_2,P_3,P_4,P_5,P_6

节点向量为:

U=[0,0,0,0,1,2,3,4,4,4,4]U=[0,0,0,0,1,2,3,4,4,4,4]

有效参数区间是:

[0,4][0,4]

非零节点区间为:

1
[0,1], [1,2], [2,3], [3,4]

因为 p=3p=3,所以每一段由:

p+1=4p+1=4

个控制点参与。

曲线段 参数区间 span 索引 kk 参与控制点
第 1 段 [0,1][0,1] 33 P0,P1,P2,P3P_0,P_1,P_2,P_3
第 2 段 [1,2][1,2] 44 P1,P2,P3,P4P_1,P_2,P_3,P_4
第 3 段 [2,3][2,3] 55 P2,P3,P4,P5P_2,P_3,P_4,P_5
第 4 段 [3,4][3,4] 66 P3,P4,P5,P6P_3,P_4,P_5,P_6

开放节点向量与首尾插值

对于三次曲线:

p=3p=3

常见开放节点向量会让首尾节点重复 p+1=4p+1=4 次:

U=[0,0,0,0,1,2,3,4,4,4,4]U=[0,0,0,0,1,2,3,4,4,4,4]

开头四个 00

0,0,0,00,0,0,0

结尾四个 44

4,4,4,44,4,4,4

这样做的效果是:曲线会经过第一个控制点和最后一个控制点。

也就是:

C(0)=P0C(0)=P_0

C(4)=P6C(4)=P_6

这和 Bézier 曲线类似,比较符合建模直觉。

如果不重复首尾节点,曲线一般不会经过首尾控制点。

节点重复与连续性

节点向量中可以重复内部节点。例如三次曲线:

U=[0,0,0,0,1,2,2,3,4,4,4,4]U=[0,0,0,0,1,2,2,3,4,4,4,4]

这里内部节点 22 重复了两次。

对于 pp 次曲线,如果内部节点重复 rr 次,该节点处连续性为:

CprC^{p-r}

三次曲线 p=3p=3

  • 内部节点重复 11 次:连续性 C2C^2
  • 内部节点重复 22 次:连续性 C1C^1
  • 内部节点重复 33 次:连续性 C0C^0
  • 内部节点重复 44 次:可能断开或形成强制插值

没有额外重复时

节点向量:

U=[0,0,0,0,1,2,3,4,4,4,4]U=[0,0,0,0,1,2,3,4,4,4,4]

内部节点 1,2,31,2,3 都只出现一次。

对于三次曲线:

p=3,r=1p=3,\quad r=1

连续性是:

C31=C2C^{3-1}=C^2

也就是说,曲线在这些节点处非常光滑:

  • 位置连续
  • 一阶导数连续
  • 二阶导数连续

节点重复两次

节点向量:

U=[0,0,0,0,1,2,2,3,4,4,4,4]U=[0,0,0,0,1,2,2,3,4,4,4,4]

内部节点 22 重复两次:

r=2r=2

连续性变为:

C32=C1C^{3-2}=C^1

曲线仍然位置连续、切线连续,但曲率可能不连续。

直观上就是:

曲线在 u=2u=2 附近会更“紧”一些,光滑程度下降。

节点重复三次

节点向量:

U=[0,0,0,0,1,2,2,2,3,4,4,4,4]U=[0,0,0,0,1,2,2,2,3,4,4,4,4]

内部节点 22 重复三次:

r=3r=3

连续性变为:

C33=C0C^{3-3}=C^0

也就是只有位置连续,切线方向可以发生突变。

直观上可能形成一个尖点或折角。

非均匀节点有什么意义

如果节点间距相等,例如:

U=[0,0,0,0,1,2,3,4,4,4,4]U=[0,0,0,0,1,2,3,4,4,4,4]

中间间距都是 11,这是比较均匀的参数分布。

如果节点间距不等,例如:

U=[0,0,0,0,0.2,0.8,3,4,4,4,4]U=[0,0,0,0,0.2,0.8,3,4,4,4,4]

这就是非均匀节点。

非均匀节点的作用是:

  • 可以让参数分布更灵活
  • 可以让曲线在某些区域变化更快或更慢
  • 可以控制局部形状
  • 可以表示端点插值
  • 可以控制节点处连续性

注意:非均匀节点不一定直接改变曲线的几何形状,但会影响参数化方式、基函数分布,以及控制点影响的参数范围。

节点不是曲线长度比例

需要特别注意:节点区间长度不是曲线真实弧长。

例如:

[0,0.25][0,0.25]

这个参数区间长度是:

0.250.25

但它不意味着这一段曲线的真实长度占整条曲线的 25%25\%

NURBS 的参数 uu 通常不是弧长参数。

所以:

  • 参数走了 25%25\%
  • 不代表曲线长度也走了 25%25\%
  • 不代表屏幕上的距离是 25%25\%

它只是参数空间中的比例。

控制点影响范围

可以把参数 uu 想象成动画时间。

控制点的影响不是一直存在,而是在某个时间段内逐渐出现、达到最大、再逐渐消失。

例如三次 B 样条中,一个控制点 PiP_i 的影响范围大致从:

uiu_i

到:

ui+p+1u_{i+p+1}

也就是说:

Pi 的影响区间 =[ui,ui+p+1]P_i \text{ 的影响区间 }=[u_i,u_{i+p+1}]

对于三次曲线 p=3p=3

Pi 的影响区间 =[ui,ui+4]P_i \text{ 的影响区间 }=[u_i,u_{i+4}]

这就是为什么节点向量决定控制点影响范围。

例子:P2影响哪些区间

节点向量:

U=[0,0,0,0,1,2,3,4,4,4,4]U=[0,0,0,0,1,2,3,4,4,4,4]

次数:

p=3p=3

控制点 P2P_2 的影响范围是:

[u2,u2+p+1]=[u2,u6][u_2,u_{2+p+1}]=[u_2,u_6]

查节点向量:

u2=0,u6=3u_2=0,\quad u_6=3

所以:

P2 影响 u[0,3]P_2 \text{ 影响 } u \in [0,3]

也就是影响这些区间:

1
[0,1], [1,2], [2,3]

它不会影响:

1
[3,4]

例子:P5影响哪些区间

控制点 P5P_5 的影响范围是:

[u5,u5+p+1]=[u5,u9][u_5,u_{5+p+1}]=[u_5,u_9]

查节点向量:

u5=2,u9=4u_5=2,\quad u_9=4

所以:

P5 影响 u[2,4]P_5 \text{ 影响 } u \in [2,4]

也就是只影响后两段:

1
[2,3], [3,4]

它不会影响前面的:

1
[0,1], [1,2]

B 样条基函数

B 样条基函数 Ni,p(u)N_{i,p}(u) 是递归定义的。

零次基函数为:

Ni,0(u)={1,uiu<ui+10,otherwiseN_{i,0}(u)= \begin{cases} 1, & u_i \le u < u_{i+1} \\ 0, & \text{otherwise} \end{cases}

高次基函数递推为:

Ni,p(u)=uuiui+puiNi,p1(u)+ui+p+1uui+p+1ui+1Ni+1,p1(u)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)

这个递推公式称为 Cox-de Boor 递推公式。

如果分母为 00,对应项通常按 00 处理。

这个公式看起来复杂,但直观意义是:高阶 B 样条基函数由低阶基函数逐层混合得到。

这和 de Casteljau 算法中逐层线性插值的思想很像。

NURBS 的有理形式

普通 B 样条是:

C(u)=i=0nNi,p(u)PiC(u)=\sum_{i=0}^{n}N_{i,p}(u)P_i

NURBS 多了权重 wiw_i

C(u)=i=0nNi,p(u)wiPii=0nNi,p(u)wiC(u)= \frac{ \sum_{i=0}^{n}N_{i,p}(u)w_iP_i }{ \sum_{i=0}^{n}N_{i,p}(u)w_i }

这就是 Rational,也就是“有理”的意思。

它和有理 Bézier 非常类似。

可以定义有理基函数:

Ri,p(u)=Ni,p(u)wij=0nNj,p(u)wjR_{i,p}(u)= \frac{ N_{i,p}(u)w_i }{ \sum_{j=0}^{n}N_{j,p}(u)w_j }

于是 NURBS 可以写成:

C(u)=i=0nRi,p(u)PiC(u)=\sum_{i=0}^{n}R_{i,p}(u)P_i

权重的作用仍然是:

改变控制点对曲线的相对吸引力。

当所有权重都为 11 时,NURBS 退化为普通 B 样条:

w0=w1==wn=1w_0=w_1=\cdots=w_n=1

NURBS 的计算方法

NURBS 可以用公式直接计算:

C(u)=i=0nNi,p(u)wiPii=0nNi,p(u)wiC(u)= \frac{ \sum_{i=0}^{n}N_{i,p}(u)w_iP_i }{ \sum_{i=0}^{n}N_{i,p}(u)w_i }

但实际工程中通常使用 de Boor 算法

它是 B 样条 / NURBS 版本的 de Casteljau 算法。

计算流程是:

1
2
3
4
5
6
7
8
9
10
11
12
13
参数 u

找到 u 所在的 knot span

取出局部 p+1 个控制点

如果是 NURBS,先转为齐次坐标

使用 de Boor 递推插值

投影回普通坐标

得到曲线点 C(u)

对于二维 NURBS,先将控制点转成齐次坐标:

Pi=(xi,yi)Pih=(wixi,wiyi,wi)P_i=(x_i,y_i)\\ P_i^h=(w_ix_i,w_iy_i,w_i)

PihP_i^h 使用 de Boor 算法,得到:

Q(u)=(X(u),Y(u),W(u))Q(u)=(X(u),Y(u),W(u))

最后投影:

C(u)=(X(u)W(u),Y(u)W(u))C(u)= \left( \frac{X(u)}{W(u)}, \frac{Y(u)}{W(u)} \right)

三维时类似:

Pih=(wixi,wiyi,wizi,wi)P_i^h=(w_ix_i,w_iy_i,w_iz_i,w_i)

C(u)=(X(u)W(u),Y(u)W(u),Z(u)W(u))C(u)= \left( \frac{X(u)}{W(u)}, \frac{Y(u)}{W(u)}, \frac{Z(u)}{W(u)} \right)

de Boor 算法也是逐层插值。

假设参数 uu 位于:

uku<uk+1u_k \le u < u_{k+1}

对于 pp 次 B 样条,参与计算的控制点是:

Pkp,Pkp+1,,PkP_{k-p},P_{k-p+1},\dots,P_k

递推初始化为:

Pi(0)=PiP_i^{(0)}=P_i

然后逐层计算:

Pi(r)=(1αi(r))Pi1(r1)+αi(r)Pi(r1)P_i^{(r)} = (1-\alpha_i^{(r)})P_{i-1}^{(r-1)} + \alpha_i^{(r)}P_i^{(r-1)}

其中:

αi(r)=uuiui+pr+1ui\alpha_i^{(r)} = \frac{ u-u_i }{ u_{i+p-r+1}-u_i }

最后得到曲线点。

这个形式和 de Casteljau 很像,区别是:

  • de Casteljau 的插值参数通常就是 tt
  • de Boor 的插值参数由节点向量决定

所以可以理解为:de Boor = 带节点向量控制的 de Casteljau。

Bezier、B 样条、NURBS 的关系

三者可以这样理解:

1
2
3
4
5
Bézier
↓ 增加节点向量和局部控制
B-Spline
↓ 增加权重和有理形式
NURBS

也可以说:

  • Bézier 是特殊的 B 样条
  • B 样条是权重全为 11 的 NURBS
  • 有理 Bézier 是特殊节点向量下的 NURBS

对于 nn 次 Bézier,可以用节点向量:

[0,0,,0,1,1,,1][0,0,\dots,0,1,1,\dots,1]

其中 00 重复 n+1n+1 次,11 重复 n+1n+1 次。

例如三次 Bézier:

[0,0,0,0,1,1,1,1][0,0,0,0,1,1,1,1]

所以 Bézier 其实可以看作只有一个 knot span 的 B 样条。

节点插入

节点插入就是在节点向量中增加一个节点值。

例如原来:

U=[0,0,0,0,1,2,3,4,4,4,4]U=[0,0,0,0,1,2,3,4,4,4,4]

插入一个节点:

u=1.5u=1.5

变成:

U=[0,0,0,0,1,1.5,2,3,4,4,4,4]U'=[0,0,0,0,1,1.5,2,3,4,4,4,4]

节点插入后:

  • 曲线形状可以保持不变
  • 控制点数量会增加
  • 曲线被分成更多段
  • 局部编辑能力增强

这在 CAD 中非常重要。

也就是说:插入节点不是为了改变曲线形状,而是为了增加局部控制能力。

NURBS 曲线的优缺点

NURBS 在 CAD 中广泛使用,是因为它同时具备以下优点:

  • 可以精确表示直线、圆、椭圆、圆锥曲线
  • 可以表示自由曲线
  • 支持局部控制
  • 支持高阶连续性
  • 可以通过权重调节形状
  • 节点向量可以控制参数分布和连续性
  • 适合曲线、曲面统一表示
  • 适合几何内核计算

这也是为什么 OpenCASCADE、Parasolid、ACIS 等几何内核都大量使用 NURBS 或 B 样条。

NURBS 也不是没有缺点:

  • 数据结构比 Bézier 更复杂
  • 需要理解节点向量
  • 参数 uu 不一定对应真实弧长
  • 权重过大或过小可能导致数值问题
  • 曲线形状不如低阶 Bézier 那么直观
  • 节点重复会影响连续性,需要谨慎处理

所以在简单 UI 绘图中,可能 Bézier 更方便;但在 CAD 几何建模中,NURBS 更强大。

总结

NURBS 可以这样理解:

NURBS=非均匀节点向量+B 样条基函数+控制点权重\boxed{ \text{NURBS}=\text{非均匀节点向量}+\text{B 样条基函数}+\text{控制点权重} }

从曲线家族关系看:

BeˊzierB-SplineNURBS\boxed{ \text{Bézier} \subset \text{B-Spline} \subset \text{NURBS} }

从计算角度看:

Beˊzier 用 de Casteljau,NURBS 用 de Boor\boxed{ \text{Bézier 用 de Casteljau,NURBS 用 de Boor} }

从几何能力看:

NURBS 既能表示自由曲线,也能精确表示圆和圆锥曲线\boxed{ \text{NURBS 既能表示自由曲线,也能精确表示圆和圆锥曲线} }

节点向量不是曲线上的点,也不是控制点,而是参数轴上的分段规则。

一句话总结节点向量:

节点向量=参数轴上的分段表 + 控制点影响范围表 + 连续性控制表\boxed{ \text{节点向量} = \text{参数轴上的分段表 + 控制点影响范围表 + 连续性控制表} }

更直观地说:控制点决定曲线往哪里走,权重决定控制点吸引力,节点向量决定曲线按什么参数节奏分段、每段由谁控制、段与段之间有多光滑。

(转载本站文章请注明作者和出处lihaohello.top,请勿用于任何商业用途)