多种曲线插值方法
问题背景
在动画帧率不足、传感器采样率有限或路径点稀疏时,需要在已知数据点之间估算中间值。插值就是这件事:给定若干控制点,对任意参数位置求出一个平滑过渡的数值。本文讨论五种常见的一维插值方法,从最简单的线性到带张力/偏置控制的 Hermite 曲线,并给出纯 C 参考实现。
所有方法共用一个参数约定:mu 表示当前估计点在两个相邻控制点之间的相对位置,取值为 [0, 1],0 对应前一个点,1 对应后一个点。以下代码均为简化示例,未做越界检查、未处理 mu 超出 [0,1] 的情况,也未考虑多线程并发访问;实际项目中请根据场景补充边界保护。
线性插值
线性插值是最直接的方法:用一条直线段连接相邻两个数据点,每个线段独立计算。只需两个端点 y1、y2 和参数 mu。
优点是实现极简、计算量最小;缺点是相邻线段在控制点处斜率突变,曲线不光滑(仅 C0 连续)。
double LinearInterpolate(
double y1,double y2,
double mu)
{
return(y1*(1-mu)+y2*mu);
}
余弦插值
线性插值在每个控制点处产生明显的折角。余弦插值利用余弦函数在 [0, π] 区间内从 0 平滑过渡到 1 的特性,将 mu 映射为 mu2 = (1 - cos(mu·π)) / 2,使端点处导数为零,从而消除折角。
它仍然只需要两个端点,但曲线在控制点处切线水平,视觉上比线性平滑。代价是曲线在控制点附近变化较慢,中间段变化较快,整体节奏不如三次方法均匀。
double CosineInterpolate(
double y1,double y2,
double mu)
{
double mu2;
mu2 = (1-cos(mu*PI))/2;
return(y1*(1-mu2)+y2*mu2);
}
三次插值
三次插值(Cubic Interpolation)是能提供线段之间真正 C1 连续性的最简方法。它需要当前线段两个端点 y1、y2,以及两侧各一个辅助点 y0、y3,共 4 个点。多项式系数由这 4 个点一次性确定。
边界问题: 序列首段缺少 y0,末段缺少 y3。常见处理方式是:
- 在起点前、终点后各虚拟一个点,其值由端点斜率外推得到;
- 或首末段退化为二次/线性插值。
本文示例代码未处理边界,调用方需自行保证 y0、y3 有效。
double CubicInterpolate(
double y0,double y1,
double y2,double y3,
double mu)
{
double a0,a1,a2,a3,mu2;
mu2 = mu*mu;
a0 = y3 - y2 - y0 + y1;
a1 = y0 - y1 - a0;
a2 = y2 - y0;
a3 = y1;
return(a0*mu*mu2+a1*mu2+a2*mu+a3);
}
Catmull-Rom 样条
Catmull-Rom 样条是三次插值的一个特例:它在每个端点处用相邻两点的中心差分(即 (y2 - y0) / 2 和 (y3 - y1) / 2)作为切线估计,从而得到更自然的曲线形状。Paul Breeuwsma 给出的系数如下,可直接替换三次插值中的 a0–a3 计算:
a0 = -0.5*y0 + 1.5*y1 - 1.5*y2 + 0.5*y3;
a1 = y0 - 2.5*y1 + 2*y2 - 0.5*y3;
a2 = -0.5*y0 + 0.5*y2;
a3 = y1;与通用三次插值相比,Catmull-Rom 的切线幅度减半,过冲(overshoot)通常较小,在路径动画和相机轨迹中较为常用。它同样需要 4 个点,边界处理策略与三次插值一致。
Hermite 插值
Hermite 插值同样需要 4 个点,但额外引入两个控制参数:
- 张力(tension): 缩放切线幅度。tension = 0 时切线取正常大小;tension = 1 时切线归零,曲线退化为两端斜率为零的 S 形(smoothstep);tension = -1 时切线加倍,曲线更弯曲。
- 偏置(bias): 控制曲线在已知点处向哪一侧倾斜。正值偏向前一段,负值偏向后一段。默认 0 表示对称。
通过调节这两个参数,可以在不改变控制点的前提下微调曲线形态,适合需要交互调参的场景。

方法对比与选择建议
| 方法 | 所需控制点 | 连续性 | 额外参数 | 典型场景 |
|---|---|---|---|---|
| 线性 | 2 | C0 | 无 | 性能极敏感、对平滑无要求 |
| 余弦 | 2 | C1(端点导数为 0) | 无 | 简单淡入淡出、轻量过渡 |
| 三次 | 4 | C1 | 无 | 通用平滑曲线 |
| Catmull-Rom | 4 | C1 | 无 | 路径动画、相机轨迹 |
| Hermite | 4 | C1 | tension, bias | 需要交互调参的曲线编辑 |
选择时可先问两个问题:
- 能否提供 4 个控制点(含边界虚拟点)?不能则只能选线性或余弦。
- 是否需要运行时调节曲线形态?需要则选 Hermite。
使用注意事项
- 以上代码均为双精度
double的一维实现。扩展到二维或三维时,对 x、y(、z)分量分别调用即可,但需注意各分量mu一致。 mu超出[0, 1]时,线性与余弦方法仍可外推,但三次及 Hermite 方法的外推行为可能产生剧烈振荡,生产代码中建议 clamp 或分段处理。- 代码中未包含
#include <math.h>及PI宏定义,余弦插值需自行补充。 - 所有方法均为确定性计算,无随机性;若用于实时渲染,注意
cos函数的平台性能差异(ARM 软浮点 vs FPU)。
小结
从线性到 Hermite,插值方法在控制点数量、连续性和可调性之间逐步递进。对于大多数嵌入式动画或路径生成场景,Catmull-Rom 样条在实现复杂度和视觉效果之间取得了较好的平衡;若需要用户可调的曲线形态,Hermite 是自然的选择。实际落地时,别忘了处理序列首尾的边界点,并对 mu 做范围保护。
本文最初于 2023/12/11 发布在 CSDN。
评论
正在读取评论…