3、B样条曲线基础:B样条的定义、节点向量、控制点与基函数

聊到样条插补,B样条是绕不开的核心。说实话,我刚入行那会儿,看到“B样条”这三个字就头大。什么节点向量、控制点、基函数,一堆术语堆在一起,感觉像天书。后来在机床上调了两年参数,踩了无数坑,才慢慢摸清楚它的脾气。

今天我就用最直白的方式,把B样条的底裤给你扒干净。你只要搞懂三样东西:节点向量控制点基函数。这三者一组合,B样条曲线就出来了。

3.1 什么是B样条?

B样条,全称是 Basis Spline,也就是“基样条”。说白了,它是一段一段多项式曲线拼起来的。每一段都受几个控制点的影响,但又不是所有控制点都管它——这就是“局部性”。

我打个比方。你想想看,一条马路上的路灯。每个路灯只照亮它附近的一段路,远了就照不到了。B样条的控制点也是这样,每个控制点只影响曲线的一小段。你挪动一个控制点,曲线只在局部变形,不会像贝塞尔曲线那样整个都跟着跑。

这个特性在数控加工里太重要了。我在调试五轴机床时,经常需要微调刀路。如果每次改一个点,整条路径都重算,那调试效率就太低了。B样条的局部支撑性,让我可以“指哪打哪”,只改局部,不动全局。

3.2 节点向量(Knot Vector)

节点向量是B样条的“骨架”。它是一个非递减的实数序列,记作:

U = {u₀, u₁, u₂, ..., uₘ}

其中每个 uᵢ 叫一个节点(knot)。节点把参数空间分成一段一段的区间,每一段对应一条多项式曲线。

节点向量的长度 m 和控制点个数 n、曲线阶数 p 有关系:

m = n + p + 1

举个例子。假设我们有 4 个控制点(n=3),曲线是 3 阶(p=2,也就是二次曲线),那么节点向量长度 m = 3+2+1 = 6。节点向量可能是:

U = {0, 0, 0, 1, 2, 3, 4, 4, 4}

注意看,开头和结尾的节点重复了三次。这叫“重复节点”,作用是让曲线强制通过首尾控制点。我在做刀路规划时,经常用这个技巧让刀具路径的起点和终点精确落在指定位置。

节点向量的两种常见类型:
  • 均匀节点向量:节点等距分布,如 {0, 1, 2, 3, 4, 5}。曲线在参数空间里均匀变化,但首尾不经过控制点。
  • 准均匀节点向量:首尾重复 p+1 次,中间均匀。如 {0,0,0,1,2,3,4,4,4}。这是工程中最常用的,既保证首尾经过控制点,又保持内部均匀。
我的经验:在数控插补中,我建议优先使用准均匀节点向量。它能让刀具路径的起点和终点精确可控,同时内部段落的过渡也比较平滑。我曾经试过用均匀节点向量做刀路,结果起点位置总差那么几个微米,后来换成准均匀就解决了。

3.3 控制点(Control Points)

控制点就是你想让曲线“靠近”的那些点。记作:

P₀, P₁, P₂, ..., Pₙ

每个控制点是一个二维或三维坐标。曲线不一定经过控制点,但会被它们“拉”过去。控制点越多,曲线能表达的形态就越复杂。

这里有个容易搞混的地方:控制点个数 n+1 和节点向量长度 m 的关系,就是上面那个公式 m = n + p + 1。你定好了阶数 p 和控制点个数,节点向量的长度就定了。

我记得有一次调试一个复杂曲面加工,用了 20 个控制点。结果曲线在中间段出现了不希望的波动。后来发现是控制点分布太密,导致曲线“过拟合”。解决办法是减少控制点,或者提高阶数。嗯,这里要注意:控制点不是越多越好,够用就行。

3.4 基函数(Basis Functions)

基函数是B样条的灵魂。它决定了每个控制点对曲线的影响范围。B样条的基函数是用递归方式定义的,叫 Cox-de Boor 公式:

Nᵢ,₀(u) = 1  如果 uᵢ ≤ u < uᵢ₊₁,否则 0

Nᵢ,ₚ(u) = (u - uᵢ) / (uᵢ₊ₚ - uᵢ) * Nᵢ,ₚ₋₁(u) 
         + (uᵢ₊ₚ₊₁ - u) / (uᵢ₊ₚ₊₁ - uᵢ₊₁) * Nᵢ₊₁,ₚ₋₁(u)

看着复杂是吧?其实它的核心思想就一句话:每个基函数只在局部区间内非零。这个区间由节点向量决定。

举个例子。对于二次B样条(p=2),每个基函数只在三个节点区间内非零。也就是说,每个控制点只影响曲线上的三段区间。你改一个控制点,曲线最多变三段,其他部分纹丝不动。

这个性质在工程上太有用了。我在做刀路优化时,经常需要微调某个拐角处的路径。如果用的是贝塞尔曲线,改一个点整条线都重算,计算量大不说,还容易引入新的问题。但B样条就不同了,我只改局部,其他地方不动,调试效率高得多。

3.5 B样条曲线的数学表达

有了节点向量、控制点和基函数,B样条曲线就可以写成:

C(u) = Σᵢ₌₀ⁿ Nᵢ,ₚ(u) * Pᵢ

其中 u 是参数,取值范围从 uₚ 到 uₘ₋ₚ(去掉首尾重复节点后的范围)。

这个公式说白了就是:曲线上每个点,都是所有控制点的加权平均。权重就是基函数的值。基函数值大的控制点,对曲线的影响就大。

我刚开始学的时候,总觉得这个公式太抽象。后来在代码里跑了一遍,看到曲线随着参数 u 的变化一点点生成,才真正理解了。建议你也动手写一段代码试试,哪怕只是用 Python 的 numpy 简单实现一下,也比光看公式强。

3.6 知识体系结构图

下面这张图,把B样条的核心逻辑串起来了。你看一遍就能明白这三者是怎么配合的。

B样条曲线核心逻辑 节点向量 Knot Vector 控制点 Control Points 基函数 Basis Functions 定义区间 提供坐标 提供权重 C(u) = Σ Nᵢ,ₚ(u) · Pᵢ 加权求和 → 曲线上每个点 B样条曲线特性 • 局部支撑:改一个控制点,只影响局部 • 连续性:阶数越高,曲线越平滑 • 凸包性:曲线在控制点凸包内 • 仿射不变性:变换控制点即变换曲线

3.7 实际应用中的注意事项

避坑指南:
  • 节点重复度不能超过阶数:重复度 p+1 是上限,超过会导致曲线在该点失去连续性。我曾经在调试时不小心把重复度设成了 p+2,结果曲线在那个节点处直接断开了,查了半天才发现。
  • 控制点不要过于密集:控制点太密会导致曲线出现不必要的波动,尤其是在曲率变化大的区域。我一般建议控制点间距不要小于曲线最小曲率半径的 1/10。
  • 阶数不是越高越好:阶数高了,曲线更平滑,但计算量也更大,而且容易在端点处出现振荡。工程上常用三次B样条(p=3),平衡了平滑性和计算效率。
我的调试习惯:拿到一条B样条曲线,我第一步不是看控制点,而是看节点向量。节点向量的分布直接决定了曲线的“性格”。如果节点分布不均匀,曲线在参数空间里的变化速度就不均匀,加工时容易出现速度波动。我一般会先检查节点向量,确保它是准均匀的,然后再看控制点的位置是否合理。

好了,B样条的基础就这些。说白了就是三样东西:节点向量定区间,控制点定位置,基函数定权重。这三者一配合,就能生成一条平滑的曲线。下一节我们会聊B样条在数控插补中的具体应用,包括如何计算曲线上的点、如何控制速度等。但那是后话了,先把今天的基础消化掉。


公众号:蓝海资料掘金营,微信deep3321