Bézier 曲线
Bernstein 基底
定义 · Bernstein 多项式
\(n \ge 0\) 次 Bernstein 多项式为
其他整数 \(i\) 令 \(b_{i,n} = 0\)。
这组多项式出自 Bernstein (1912);Farouki (2012)回顾其历史与性质,三次的情形如三次 Bernstein 多项式。。以下证明用到两个二项式系数恒等式。
引理 · 二项式恒等式
令 \(n \ge 1\),\(i\)、\(j\) 为整数,并约定 \(k < 0\) 或 \(k > m\) 时 \(\binom{m}{k} = 0\)。则
且
命题 · Bernstein 基底
对 \(n \ge 0\),多项式 \(b_{0,n}, \ldots, b_{n,n}\) 是次数不超过 \(n\) 的实系数多项式向量空间的一组基底。
这是 Floater (2025) 的定理 1.1;证明从头证明。
命题 · 单位分解
对每个 \(t \in [0, 1]\),所有 \(b_{i,n}(t) \ge 0\),且
定义 · Bézier 曲线
设 \(P_0, \ldots, P_n \in \mathbb{R}^d\)。以 \(P_0, \ldots, P_n\) 为控制点的 \(n\) 次 Bézier 曲线为
其控制多边形为折线 \(P_0 P_1 \ldots P_n\)。
此定义依循 B{\'e}zier (1966),形式如 Farin (2002) 与 Prautzsch (2002)。
命题 · 端点
\(b_{i,n}(0)\) 在 \(i = 0\) 时为 1,其余为 0;\(b_{i,n}(1)\) 在 \(i = n\) 时为 1,其余为 0。因此 \(B(0) = P_0\)、\(B(1) = P_n\)。
推论 · 凸包
每个 \(B(t)\)(\(t \in [0, 1]\))都位于控制点 \(P_0, \ldots, P_n\) 的凸包内。
命题 · 仿射不变性
对每个仿射映射 \(A(x) = M x + v\) 与每个 \(t \in [0, 1]\),
变换曲线等同于变换其控制点。
凸包让曲线不超出控制多边形所张的区域;仿射不变性则是导出器与 Matplotlib 适配器只需移动控制点,就能平移、缩放或旋转曲线的原因。
BernsteinBasis(int)(float)
BernsteinBasis(int).matrix(values)
某一次数的基底,位于 bezierkit.bezier.basis。在 \(t\) 调用时,以数组返回 \(i = 0, \ldots, n\) 的 \(b_{i,n}(t)\);matrix() 对每个参数值返回一列。
曲线
BezierCurve(
points,
*,
evaluator=None
)
BezierCurve.linear(p0, p1)
BezierCurve.quadratic(
p0,
p1,
p2
)
BezierCurve.cubic(
p0,
p1,
p2,
p3
)
次数 \(n\)。
维度 \(d\)。
以 PointSet 表示的控制点。
以 Point 返回 \(B(t)\);曲线对象也可直接调用,curve(t)。
以 PointSet 返回多个参数下的值。
求值策略(见下文)。
不可变的 Bézier 曲线,次数 \(n \ge 0\)、维度 \(d \ge 1\) 均不限,参数范围为 \([0, 1]\)。points 可为 Point 序列、PointSet、\((n + 1) \times d\) 数组或 ControlPolygon;所有控制点必须同一维度。
曲线的运算 derivative()、split()、segment() 与 reversed() 详见导数、反转与分割。
求值
de Casteljau 算法以反复的线性插值计算 \(B(t)\)。
定义 · de Casteljau 点
对参数 \(t\),令 \(P_i^{(0)} = P_i\),并对 \(r = 1, \ldots, n\) 令
每一轮对相邻点取平均,多边形少一个点;\(n\) 轮后只剩一点(参见de Casteljau 算法,\(t = 0.4\)。)。此算法源自 Paul de Casteljau 约 1959 年在 Citroën 的工作 M{\"u}ller (2024)。
定理 · de Casteljau
对 \(0 \le r \le n\) 与 \(0 \le i \le n - r\),
特别地,\(P_0^{(n)} = B(t)\)。
此叙述见 Floater (2025) 的定理 1.6 与 1.7。
每个中间点都是控制点的凸组合,算法不会产生互相抵消的大数,因此在高次数时数值稳定。每个参数的计算量为 \(O(n^2)\)。
DeCasteljauEvaluator
默认的求值策略,位于 bezierkit.bezier.evaluation:以 NumPy 一次对整批参数运行上述算法。
BernsteinEvaluator
以 Bernstein 矩阵乘上控制点。次数低、批量大时较快,但高次数时会求和可能互相抵消的项。根据de Casteljau,两种策略计算的是同一个多项式。
from bezierkit import BezierCurve
from bezierkit.bezier.evaluation import BernsteinEvaluator
fast = BezierCurve(
curve.control_points, evaluator=BernsteinEvaluator()
)
# Point(coords=(2.0, 1.5)), as with the default
print(fast.at(0.5))
仓库的 benchmarks/ 目录比较两者在 400、10,000 与 100,000 个参数值下的效能。
升阶
\(n\) 次曲线也是 \(n + 1\) 次曲线;新的控制点是旧控制点中相邻两点的凸组合。
引理 · 升阶恒等式
对 \(n \ge 0\)、\(0 \le i \le n\) 与每个 \(t\),
命题 · 升阶
设 \(B\) 的控制点为 \(P_0, \ldots, P_n\)。对 \(k = 0, \ldots, n + 1\) 令
其中 \(P_{-1}\) 与 \(P_{n+1}\) 可任意选取,因为它们的系数为零。则
曲线及其参数化都不变。
此公式是标准结果 Farin (2002)Prautzsch (2002);证明的证明不依赖它们。直线与二次曲线的三次表示把它用在直线与二次曲线,也就是本软件包需要的情形。