3. 自由曲面表示方法

Bezier曲线,说白了就是自由曲面设计的“地基”。我做了这么多年曲面设计,可以负责任地告诉你——如果你搞不懂Bezier,后面NURBS、B样条什么的,学起来会非常痛苦。这一章我们就把Bezier曲线彻底讲透。

3.1 Bezier曲线的定义

Bezier曲线由法国工程师Pierre Bézier在1960年代提出,最初用于汽车车身设计。它的数学定义其实很简洁:

给定n+1个控制点P₀, P₁, ..., Pₙ,n次Bezier曲线定义为:

C(t) = Σᵢ₌₀ⁿ Bᵢₙ(t) · Pᵢ,  t ∈ [0, 1]

其中Bᵢₙ(t)是Bernstein基函数:

Bᵢₙ(t) = C(n, i) · tⁱ · (1-t)ⁿ⁻ⁱ

这里C(n, i)是组合数。嗯,公式看着有点抽象,我们来看个具体的例子。

三次Bezier曲线(n=3)是最常用的,有4个控制点:

C(t) = (1-t)³·P₀ + 3t(1-t)²·P₁ + 3t²(1-t)·P₂ + t³·P₃

我个人习惯把控制点想象成“磁铁”——曲线并不穿过中间的控制点,但会被它们“吸引”过去。你想想看,t从0走到1,曲线从P₀出发,逐渐偏向P₁、P₂,最后停在P₃。

核心要点:Bezier曲线始终在控制点构成的凸包内。这个性质在碰撞检测中非常有用——我在做汽车外形设计时,就靠这个快速判断曲面是否与周围部件干涉。

3.2 Bezier曲线的性质

Bezier曲线有5个关键性质,我建议你记牢:

性质 描述 工程意义
端点插值 曲线通过P₀和Pₙ 保证曲线首尾精确连接
端点切线 在P₀处切向P₀→P₁,在Pₙ处切向Pₙ₋₁→Pₙ 控制曲线进出方向
凸包性 曲线完全在控制点凸包内 快速预估曲线范围
几何不变性 仿射变换后仍是Bezier曲线 旋转平移不影响曲线形状
变差缩减性 曲线与控制多边形交点不多于控制多边形 曲线比控制多边形更“平滑”

为什么会这样?端点插值是因为t=0时只有B₀ₙ(0)=1,其他基函数全为0;t=1时同理。端点切线性质则来自基函数在端点处的导数特性。

我的经验:做曲面拼接时,端点切线性质是“命根子”。我曾经在汽车A级曲面项目中,就因为没控制好相邻曲线的切线方向,导致曲面接缝处出现肉眼可见的“鼓包”——后来花了整整两天返工。

3.3 de Casteljau算法

de Casteljau算法是计算Bezier曲线上点的最稳定方法。它基于一个简单的几何思想:递归线性插值。

算法步骤(以三次Bezier为例):

  1. 在四条边上按t比例取点:P₀₁、P₁₂、P₂₃
  2. 连接新点,再取点:P₀₁₂、P₁₂₃
  3. 最后连接,取点得到C(t)

代码实现非常直观:

function deCasteljau(points, t) {
    // points: 控制点数组,长度 = 次数 + 1
    // t: 参数值 [0, 1]
    let n = points.length - 1;
    let temp = [...points];  // 复制控制点
    
    for (let r = 1; r <= n; r++) {
        for (let i = 0; i <= n - r; i++) {
            temp[i] = (1 - t) * temp[i] + t * temp[i + 1];
        }
    }
    return temp[0];  // 最终点
}

这个算法的好处是数值稳定性极好。我记得有一次做高精度模具设计,直接用多项式求值会出现抖动,换成de Casteljau算法后,问题立刻解决了。

避坑指南:我曾经在项目中直接用Bernstein基函数求值,结果在t接近0或1时出现数值误差。de Casteljau算法虽然计算量稍大,但数值稳定性好得多——尤其是高次曲线(n≥5)时,千万别偷懒。

3.4 Bezier曲线的拼接

单条Bezier曲线能表示的形状有限。实际工程中,我们通常把多条Bezier曲线首尾相连——这就是拼接。

C⁰连续(位置连续):前一条曲线的终点等于后一条曲线的起点。

Pₙ = Q₀

C¹连续(切线连续):在C⁰连续的基础上,切线方向一致且长度成比例。

Pₙ - Pₙ₋₁ = k · (Q₁ - Q₀),  k > 0

当k=1时,称为G¹连续(几何连续),只要求方向相同,不要求长度相等。

C²连续(曲率连续):在C¹连续的基础上,二阶导数也连续。这个要求更严格:

Pₙ₋₂, Pₙ₋₁, Pₙ(=Q₀), Q₁, Q₂ 五点共面且满足特定比例关系

我做个对比表格,方便你理解:

连续类型 条件 视觉效果 工程应用
C⁰ 位置相同 有折角 简单轮廓
C¹ / G¹ 切线方向一致 光滑无折角 一般工业曲面
C² 曲率连续 高光连续 汽车A级曲面

工程真相:汽车外覆盖件要求至少G²连续,否则喷漆后会出现“橘皮”或“波浪”。我参与过的一个项目,就因为拼接处只做到了G¹,样车出来后高光线一照,接缝处明显“断光”——最后全部返工重做。

3.5 知识体系总览

下面这张图把本章的核心逻辑串起来了:

Bezier曲线知识体系 数学定义 Bernstein基函数 5大性质 端点/凸包/几何不变... de Casteljau算法 递归线性插值 曲线拼接 C⁰ / C¹ / C² 连续 工程应用场景 汽车外形设计 → 飞机机翼曲面 → 消费电子产品造型 → 字体轮廓 核心逻辑:定义 → 性质 → 算法 → 拼接 → 工程应用 一条Bezier不够?拼接多条,用连续性条件控制接缝质量

3.6 工程实践建议

最后,我总结几条实战经验:

  • 控制点数量:单条Bezier曲线不要超过7个控制点(6次),否则容易出现数值振荡。需要复杂形状时,用多条低次曲线拼接。
  • 参数范围:t始终在[0,1]区间。如果遇到需要分段参数的情况,考虑用B样条代替。
  • 连续性检查:拼接后一定要用曲率梳(Curvature Comb)检查——肉眼看不出的问题,曲率梳一照就现原形。
  • 数值稳定性:高精度计算时,优先用de Casteljau算法而不是直接展开多项式。

我的习惯:每次做完曲线拼接,我都会在接缝处取5-10个点,手动计算切线方向和曲率值。虽然工具能自动检查,但亲手算一遍能发现很多工具发现不了的细节问题。

Bezier曲线是自由曲面设计的起点。把这一章吃透,后面学B样条和NURBS会轻松很多。记住:控制点就是你的“画笔”,连续性条件就是你的“标尺”——两者配合好,才能画出漂亮的曲面。