本文介绍了NURBS曲线的几个核心问题!
NURBS 其名
NURBS是CAD、CAE、CAM、OpenCASCADE、Rhino、SolidWorks等几何系统中非常核心的曲线和曲面表示方法。NURBS全称是:
Non-Uniform Rational B-Spline
中文通常叫:非均匀有理 B 样条
这个名字可以拆成:
1 2 3
| Non-Uniform 非均匀 Rational 有理 B-Spline B 样条
|
也就是说:NURBS = 非均匀 + 有理 + B 样条
B样条曲线解决了什么问题
普通 Bézier 曲线公式是:
C(t)=i=0∑nBi,n(t)Pi
其中:
Bi,n(t)=(in)(1−t)n−iti
Pi 是控制点,Bi,n(t) 是 Bernstein 基函数。
Bézier 曲线的优点是:
- 形式简单
- 控制点直观
- 适合低阶曲线
- 二次、三次 Bézier 很常用
但 Bézier 曲线也有明显缺点:
- 高阶 Bézier 不稳定
- 任意一个控制点会影响整条曲线
- 复杂曲线需要很多段拼接
- 分段拼接时连续性需要额外处理
也就是说,Bézier 曲线更适合描述“一段曲线”,不太适合统一描述复杂长曲线。
B 样条曲线可以解决以上问题,它可以看作 Bézier 曲线的推广:
C(u)=i=0∑nNi,p(u)Pi
其中:
- Pi 是控制点
- Ni,p(u) 是 B 样条基函数
- p 是曲线次数
- u 是参数
和 Bézier 不同,B 样条使用的是 Ni,p(u),而不是 Bernstein 基函数。
B 样条最大的优势是:**局部控制。**也就是说,移动一个控制点通常只影响曲线的一小段,而不会影响整条曲线。
假设一条三次 Bézier 曲线有 4 个控制点:
如果移动 P1,整条 Bézier 曲线都会受到影响。而 B 样条可能有很多控制点:
1
| P0, P1, P2, P3, P4, P5, P6, ...
|
对于三次 B 样条,在某个参数区间内,通常只有相邻的 4 个控制点起作用。例如某一段可能只受:
影响。
移动 P3 时,只会影响它附近的几段曲线,而不会影响整条曲线。这就是 B 样条的局部支撑性。
数学上,B 样条曲线为:
C(u)=i=0∑nNi,p(u)Pi
但在某个参数 u 处,大部分 Ni,p(u) 都是 0,只有少数几个非零。
对于 p 次 B 样条,任意一个参数位置通常最多只有:
p+1
个基函数非零。
因此,计算某个点时只需要用局部的 p+1 个控制点。
NURBS 曲线的四大组成
-
控制点:P0,P1,…,Pn决定曲线的大致形状。曲线通常不会经过所有控制点,但会被控制多边形牵引。
-
权重:w0,w1,…,wn决定每个控制点对曲线的吸引力。权重越大,曲线越靠近对应控制点。
-
次数:p决定曲线的阶数和光滑能力,CAD 中常用2或3。
-
节点向量:U=[u0,u1,…,um]决定参数分段、局部影响范围和连续性。
什么是节点向量
节点向量是 NURBS / B 样条里最容易让人困惑的概念。
一句话先说结论:节点向量不是空间中的点,而是参数轴上的分段标记。
它决定:
- 曲线被分成几段
- 每段由哪些控制点影响(由分段序号和曲线次数决定)
- 控制点影响范围有多大
- 曲线是否经过首尾控制点
- 曲线在某些位置是否光滑
- 参数 u 如何对应到曲线上的位置
假设有一条曲线,它的参数叫 u。
我们可以把 u 看成一条一维数轴:
1 2 3
| u 轴: 0 1 2 3 4 |--------|--------|--------|--------|
|
这里的 0,1,2,3,4 就像道路上的里程碑。
NURBS 的节点向量就是这条参数轴上的一串里程碑:
U=[0,0,0,0,1,2,3,4,4,4,4]
注意:节点值不是控制点坐标,也不是曲线点坐标。它们只是参数 u 的分段位置。
节点向量和控制点数量的关系
假设:
- 控制点数量是 n+1
- 曲线次数是 p
- 节点数量是 m+1
它们满足:
m+1=(n+1)+p+1
也就是:
m=n+p+1
换句话说:
节点数量=控制点数量+次数+1
有效参数范围
NURBS 的参数范围不一定必须是 [0,1],[0,1] 只是常见的归一化选择,不是数学规定。
对于一条 p 次 NURBS 曲线,节点向量为:
U=[u0,u1,…,um]
它的有效参数范围通常是:
[up,um−p]
也常写成:
[up,un+1]
其中:
- p 是曲线次数
- n+1 是控制点数量
- m+1 是节点数量
例如三次曲线:
p=3
节点向量:
U=[0,0,0,0,1,2,3,4,4,4,4]
那么有效参数范围是:
[u3,u7]
查节点向量:
u3=0,u7=4
所以:
u∈[0,4]
这条曲线的参数范围就是 [0,4],不是 [0,1]。
节点值本质上只是参数轴上的刻度,所以可以大于 1,也可以是负数,只要节点向量是非递减序列即可。
节点大于 1 与归一化
节点向量:
[0,0,0,0,1,2,3,4,4,4,4]
可以整体除以 4,变成:
[0,0,0,0,0.25,0.5,0.75,1,1,1,1]
这两个节点向量只是做了线性参数变换。
原参数:
u∈[0,4]
新参数:
uˉ∈[0,1]
二者关系是:
uˉ=4u
或者:
u=4uˉ
如果控制点和权重不变,它们表示的几何曲线通常是一样的,只是参数表示不同。
例如使用节点向量:
U=[0,0,0,0,1,2,3,4,4,4,4]
参数取:
u=2
如果归一化为:
Uˉ=[0,0,0,0,0.25,0.5,0.75,1,1,1,1]
那么对应参数是:
uˉ=0.5
因为:
uˉ=42=0.5
这两个参数对应的是曲线上的同一个位置:
CU(2)=CUˉ(0.5)
所以节点大于 1 并不奇怪,只是参数刻度没有归一化。
节点区间决定曲线分段
仍然看这个例子:
U=[0,0,0,0,1,2,3,4,4,4,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+1 的区间才是真正的曲线段。
如果节点重复导致出现:
这种零长度区间,它不对应真实曲线段。
根据分段和次数确定控制点
这是理解节点向量最关键的一步。
对于 p 次 B 样条 / NURBS:
每个非零节点区间内,最多由 p+1 个控制点参与计算
如果参数 u 落在节点区间:
uk≤u<uk+1
那么参与计算的控制点通常是:
Pk−p,Pk−p+1,…,Pk
一共:
p+1
个控制点。
这里的 k 就是当前 knot span 的索引。
三次 NURBS 分段控制点示例
假设曲线次数为:
p=3
控制点为:
P0,P1,P2,P3,P4,P5,P6
节点向量为:
U=[0,0,0,0,1,2,3,4,4,4,4]
有效参数区间是:
[0,4]
非零节点区间为:
1
| [0,1], [1,2], [2,3], [3,4]
|
因为 p=3,所以每一段由:
p+1=4
个控制点参与。
| 曲线段 |
参数区间 |
span 索引 k |
参与控制点 |
| 第 1 段 |
[0,1] |
3 |
P0,P1,P2,P3 |
| 第 2 段 |
[1,2] |
4 |
P1,P2,P3,P4 |
| 第 3 段 |
[2,3] |
5 |
P2,P3,P4,P5 |
| 第 4 段 |
[3,4] |
6 |
P3,P4,P5,P6 |
开放节点向量与首尾插值
对于三次曲线:
p=3
常见开放节点向量会让首尾节点重复 p+1=4 次:
U=[0,0,0,0,1,2,3,4,4,4,4]
开头四个 0:
0,0,0,0
结尾四个 4:
4,4,4,4
这样做的效果是:曲线会经过第一个控制点和最后一个控制点。
也就是:
C(0)=P0
C(4)=P6
这和 Bézier 曲线类似,比较符合建模直觉。
如果不重复首尾节点,曲线一般不会经过首尾控制点。
节点重复与连续性
节点向量中可以重复内部节点。例如三次曲线:
U=[0,0,0,0,1,2,2,3,4,4,4,4]
这里内部节点 2 重复了两次。
对于 p 次曲线,如果内部节点重复 r 次,该节点处连续性为:
Cp−r
三次曲线 p=3:
- 内部节点重复 1 次:连续性 C2
- 内部节点重复 2 次:连续性 C1
- 内部节点重复 3 次:连续性 C0
- 内部节点重复 4 次:可能断开或形成强制插值
没有额外重复时
节点向量:
U=[0,0,0,0,1,2,3,4,4,4,4]
内部节点 1,2,3 都只出现一次。
对于三次曲线:
p=3,r=1
连续性是:
C3−1=C2
也就是说,曲线在这些节点处非常光滑:
节点重复两次
节点向量:
U=[0,0,0,0,1,2,2,3,4,4,4,4]
内部节点 2 重复两次:
r=2
连续性变为:
C3−2=C1
曲线仍然位置连续、切线连续,但曲率可能不连续。
直观上就是:
曲线在 u=2 附近会更“紧”一些,光滑程度下降。
节点重复三次
节点向量:
U=[0,0,0,0,1,2,2,2,3,4,4,4,4]
内部节点 2 重复三次:
r=3
连续性变为:
C3−3=C0
也就是只有位置连续,切线方向可以发生突变。
直观上可能形成一个尖点或折角。
非均匀节点有什么意义
如果节点间距相等,例如:
U=[0,0,0,0,1,2,3,4,4,4,4]
中间间距都是 1,这是比较均匀的参数分布。
如果节点间距不等,例如:
U=[0,0,0,0,0.2,0.8,3,4,4,4,4]
这就是非均匀节点。
非均匀节点的作用是:
- 可以让参数分布更灵活
- 可以让曲线在某些区域变化更快或更慢
- 可以控制局部形状
- 可以表示端点插值
- 可以控制节点处连续性
注意:非均匀节点不一定直接改变曲线的几何形状,但会影响参数化方式、基函数分布,以及控制点影响的参数范围。
节点不是曲线长度比例
需要特别注意:节点区间长度不是曲线真实弧长。
例如:
[0,0.25]
这个参数区间长度是:
0.25
但它不意味着这一段曲线的真实长度占整条曲线的 25%。
NURBS 的参数 u 通常不是弧长参数。
所以:
- 参数走了 25%
- 不代表曲线长度也走了 25%
- 不代表屏幕上的距离是 25%
它只是参数空间中的比例。
控制点影响范围
可以把参数 u 想象成动画时间。
控制点的影响不是一直存在,而是在某个时间段内逐渐出现、达到最大、再逐渐消失。
例如三次 B 样条中,一个控制点 Pi 的影响范围大致从:
ui
到:
ui+p+1
也就是说:
Pi 的影响区间 =[ui,ui+p+1]
对于三次曲线 p=3:
Pi 的影响区间 =[ui,ui+4]
这就是为什么节点向量决定控制点影响范围。
例子:P2影响哪些区间
节点向量:
U=[0,0,0,0,1,2,3,4,4,4,4]
次数:
p=3
控制点 P2 的影响范围是:
[u2,u2+p+1]=[u2,u6]
查节点向量:
u2=0,u6=3
所以:
P2 影响 u∈[0,3]
也就是影响这些区间:
它不会影响:
例子:P5影响哪些区间
控制点 P5 的影响范围是:
[u5,u5+p+1]=[u5,u9]
查节点向量:
u5=2,u9=4
所以:
P5 影响 u∈[2,4]
也就是只影响后两段:
它不会影响前面的:
B 样条基函数
B 样条基函数 Ni,p(u) 是递归定义的。
零次基函数为:
Ni,0(u)={1,0,ui≤u<ui+1otherwise
高次基函数递推为:
Ni,p(u)=ui+p−uiu−uiNi,p−1(u)+ui+p+1−ui+1ui+p+1−uNi+1,p−1(u)
这个递推公式称为 Cox-de Boor 递推公式。
如果分母为 0,对应项通常按 0 处理。
这个公式看起来复杂,但直观意义是:高阶 B 样条基函数由低阶基函数逐层混合得到。
这和 de Casteljau 算法中逐层线性插值的思想很像。
NURBS 的有理形式
普通 B 样条是:
C(u)=i=0∑nNi,p(u)Pi
NURBS 多了权重 wi:
C(u)=∑i=0nNi,p(u)wi∑i=0nNi,p(u)wiPi
这就是 Rational,也就是“有理”的意思。
它和有理 Bézier 非常类似。
可以定义有理基函数:
Ri,p(u)=∑j=0nNj,p(u)wjNi,p(u)wi
于是 NURBS 可以写成:
C(u)=i=0∑nRi,p(u)Pi
权重的作用仍然是:
改变控制点对曲线的相对吸引力。
当所有权重都为 1 时,NURBS 退化为普通 B 样条:
w0=w1=⋯=wn=1
NURBS 的计算方法
NURBS 可以用公式直接计算:
C(u)=∑i=0nNi,p(u)wi∑i=0nNi,p(u)wiPi
但实际工程中通常使用 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)
对 Pih 使用 de Boor 算法,得到:
Q(u)=(X(u),Y(u),W(u))
最后投影:
C(u)=(W(u)X(u),W(u)Y(u))
三维时类似:
Pih=(wixi,wiyi,wizi,wi)
C(u)=(W(u)X(u),W(u)Y(u),W(u)Z(u))
de Boor 算法也是逐层插值。
假设参数 u 位于:
uk≤u<uk+1
对于 p 次 B 样条,参与计算的控制点是:
Pk−p,Pk−p+1,…,Pk
递推初始化为:
Pi(0)=Pi
然后逐层计算:
Pi(r)=(1−αi(r))Pi−1(r−1)+αi(r)Pi(r−1)
其中:
αi(r)=ui+p−r+1−uiu−ui
最后得到曲线点。
这个形式和 de Casteljau 很像,区别是:
- de Casteljau 的插值参数通常就是 t
- de Boor 的插值参数由节点向量决定
所以可以理解为:de Boor = 带节点向量控制的 de Casteljau。
Bezier、B 样条、NURBS 的关系
三者可以这样理解:
1 2 3 4 5
| Bézier ↓ 增加节点向量和局部控制 B-Spline ↓ 增加权重和有理形式 NURBS
|
也可以说:
- Bézier 是特殊的 B 样条
- B 样条是权重全为 1 的 NURBS
- 有理 Bézier 是特殊节点向量下的 NURBS
对于 n 次 Bézier,可以用节点向量:
[0,0,…,0,1,1,…,1]
其中 0 重复 n+1 次,1 重复 n+1 次。
例如三次 Bézier:
[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=1.5
变成:
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 更复杂
- 需要理解节点向量
- 参数 u 不一定对应真实弧长
- 权重过大或过小可能导致数值问题
- 曲线形状不如低阶 Bézier 那么直观
- 节点重复会影响连续性,需要谨慎处理
所以在简单 UI 绘图中,可能 Bézier 更方便;但在 CAD 几何建模中,NURBS 更强大。
总结
NURBS 可以这样理解:
NURBS=非均匀节点向量+B 样条基函数+控制点权重
从曲线家族关系看:
Beˊzier⊂B-Spline⊂NURBS
从计算角度看:
Beˊzier 用 de Casteljau,NURBS 用 de Boor
从几何能力看:
NURBS 既能表示自由曲线,也能精确表示圆和圆锥曲线
节点向量不是曲线上的点,也不是控制点,而是参数轴上的分段规则。
一句话总结节点向量:
节点向量=参数轴上的分段表 + 控制点影响范围表 + 连续性控制表
更直观地说:控制点决定曲线往哪里走,权重决定控制点吸引力,节点向量决定曲线按什么参数节奏分段、每段由谁控制、段与段之间有多光滑。