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);證明的證明不依賴它們。直線與二次曲線的三次表示把它用在直線與二次曲線,也就是本套件需要的情形。