貝茲曲線

在數學的數值分析領域中，貝茲曲線（英語：Bézier curve）是计算机圖形學中相當重要的參數曲線。更高維度的廣泛化貝茲曲線就稱作貝茲曲面（英语：Bézier surface），其中貝茲三角（英语：Bézier triangle）是一種特殊的實例。 貝茲曲線於1962年，由法國工程師皮埃爾·貝茲（Pierre Bézier）所廣泛發表，他運用貝茲曲線來為汽車的主體進行設計。貝茲曲線最初由保尔·德·卡斯特里奥（英语：Paul de Casteljau）於1959年運用德卡斯特里奥演算法開發，以穩定數值的方法求出貝茲曲線。 給定點P0、P1，線性貝茲曲線只是一條兩點之間的直線。這條線由下式給出： B ( t ) = P 0 + ( P 1 − P 0 ) t = ( 1 − t ) P 0 + t P 1  ,  t ∈ [ 0 , 1 ] {\displaystyle \mathbf {B} (t)=\mathbf {P} _{0}+(\mathbf {P} _{1}-\mathbf {P} _{0})t=(1-t)\mathbf {P} _{0}+t\mathbf {P} _{1}{\mbox{ , }}t\in [0,1]} 且其等同於線性插值。 二次方貝茲曲線的路徑由給定點P0、P1、P2的函數B（t）追蹤： B ( t ) = ( 1 − t ) 2 P 0 + 2 t ( 1 − t ) P 1 + t 2 P 2  ,  t ∈ [ 0 , 1 ] {\displaystyle \mathbf {B} (t)=(1-t)^{2}\mathbf {P} _{0}+2t(1-t)\mathbf {P} _{1}+t^{2}\mathbf {P} _{2}{\mbox{ , }}t\in [0,1]} TrueType字型就運用了以貝茲樣條組成的二次貝茲曲線。 P0、P1、P2、P3四個點在平面或在三維空間中定義了三次方貝茲曲線。曲線起始於P0走向P1，並從P2的方向來到P3。一般不會經過P1或P2；這兩個點只是在那裡提供方向資訊。P0和P1之間的間距，決定了曲線在轉而趨進P2之前，走向P1方向的「長度有多長」。 曲線的參數形式為： B ( t ) = P 0 ( 1 − t ) 3 + 3 P 1 t ( 1 − t ) 2 + 3 P 2 t 2 ( 1 − t ) + P 3 t 3  ,  t ∈ [ 0 , 1 ] {\displaystyle \mathbf {B} (t)=\mathbf {P} _{0}(1-t)^{3}+3\mathbf {P} _{1}t(1-t)^{2}+3\mathbf {P} _{2}t^{2}(1-t)+\mathbf {P} _{3}t^{3}{\mbox{ , }}t\in [0,1]} 現代的成象系統，如PostScript、Asymptote和Metafont，運用了以貝茲樣條組成的三次貝茲曲線，用來描繪曲線輪廓。 n {\displaystyle n} 階貝茲曲線可如下推斷。給定點P0、P1、…、Pn，其貝茲曲線即 B ( t ) = ∑ i = 0 n ( n i ) P i ( 1 − t ) n − i t i = ( n 0 ) P 0 ( 1 − t ) n t 0 + ( n 1 ) P 1 ( 1 − t ) n − 1 t 1 + ⋯ + ( n n − 1 ) P n − 1 ( 1 − t ) 1 t n − 1 + ( n n ) P n ( 1 − t ) 0 t n  ,  t ∈ [ 0 , 1 ] {\displaystyle \mathbf {B} (t)=\sum _{i=0}^{n}{n \choose i}\mathbf {P} _{i}(1-t)^{n-i}t^{i}={n \choose 0}\mathbf {P} _{0}(1-t)^{n}t^{0}+{n \choose 1}\mathbf {P} _{1}(1-t)^{n-1}t^{1}+\cdots +{n \choose n-1}\mathbf {P} _{n-1}(1-t)^{1}t^{n-1}+{n \choose n}\mathbf {P} _{n}(1-t)^{0}t^{n}{\mbox{ , }}t\in [0,1]} 。 例如 n = 5 {\displaystyle n=5} ： B ( t ) = P 0 ( 1 − t ) 5 + 5 P 1 t ( 1 − t ) 4 + 10 P 2 t 2 ( 1 − t ) 3 + 10 P 3 t 3 ( 1 − t ) 2 + 5 P 4 t 4 ( 1 − t ) + P 5 t 5  ,  t ∈ [ 0 , 1 ] {\displaystyle \mathbf {B} (t)=\mathbf {P} _{0}(1-t)^{5}+5\mathbf {P} _{1}t(1-t)^{4}+10\mathbf {P} _{2}t^{2}(1-t)^{3}+10\mathbf {P} _{3}t^{3}(1-t)^{2}+5\mathbf {P} _{4}t^{4}(1-t)+\mathbf {P} _{5}t^{5}{\mbox{ , }}t\in [0,1]} 。 如上公式可如下遞歸表達： 用 B P 0 P 1 … P n {\displaystyle \mathbf {B} _{\mathbf {P} _{0}\mathbf {P} _{1}\ldots \mathbf {P} _{n}}} 表示由點P0、P1、…、Pn所決定的貝茲曲線。則 B ( t ) = B P 0 P 1 … P n ( t ) = ( 1 − t ) B P 0 P 1 … P n − 1 ( t ) + t B P 1 P 2 … P n ( t ) {\displaystyle \mathbf {B} (t)=\mathbf {B} _{\mathbf {P} _{0}\mathbf {P} _{1}\ldots \mathbf {P} _{n}}(t)=(1-t)\mathbf {B} _{\mathbf {P} _{0}\mathbf {P} _{1}\ldots \mathbf {P} _{n-1}}(t)+t\mathbf {B} _{\mathbf {P} _{1}\mathbf {P} _{2}\ldots \mathbf {P} _{n}}(t)} 用平常話來說， n {\displaystyle n} 階的貝茲曲線，即雙 n − 1 {\displaystyle n-1} 階貝茲曲線之間的插值。 一些關於參數曲線的術語，有 B ( t ) = ∑ i = 0 n P i b i , n ( t ) , t ∈ [ 0 , 1 ] {\displaystyle \mathbf {B} (t)=\sum _{i=0}^{n}\mathbf {P} _{i}\mathbf {b} _{i,n}(t),\quad t\in [0,1]} 即多項式 b i , n ( t ) = ( n i ) t i ( 1 − t ) n − i , i = 0 , … n {\displaystyle \mathbf {b} _{i,n}(t)={n \choose i}t^{i}(1-t)^{n-i},\quad i=0,\ldots n} 又稱作n階的伯恩斯坦基底多項式，定義00 = 1。 點Pi稱作貝茲曲線的控制點。多邊形以帶有線的貝茲點連接而成，起始於P0並以Pn終止，稱作貝茲多邊形（或控制多邊形）。貝茲多邊形的凸包（convex hull）包含有貝茲曲線。 開始於P0並結束於Pn的曲線，即所謂的端點插值法屬性。 曲線是直線的充分必要條件是所有的控制點都位在曲線上。同樣的，貝茲曲線是直線的充分必要條件是控制點共線。 曲線的起始點（結束點）相切於貝茲多邊形的第一節（最後一節）。 一條曲線可在任意點切割成兩條或任意多條子曲線，每一條子曲線仍是貝茲曲線。 一些看似簡單的曲線（如圓）無法以貝茲曲線精確的描述，或分段成貝茲曲線（雖然當每個內部控制點對單位圓上的外部控制點水平或垂直的的距離為 4 ( 2 − 1 ) / 3 {\displaystyle 4\left({\sqrt {2}}-1\right)/3} 時，分成四段的貝茲曲線，可以小於千分之一的最大半徑誤差近似於圓）。 位於固定偏移量的曲線（來自給定的貝茲曲線），又稱作偏移曲線（假平行於原來的曲線，如兩條鐵軌之間的偏移）無法以貝茲曲線精確的形成（某些平凡實例除外）。無論如何，現存的啟發法通常可為實際用途中給出近似值。 線性貝茲曲線函數中的t會經過由P0至P1的B（t）所描述的曲線。例如當t=0.25時，B（t）即一條由點P0至P1路徑的四分之一處。就像由0至1的連續t，B（t）描述一條由P0至P1的直線。 為建構二次貝茲曲線，可以中介點Q0和Q1作為由0至1的t： 由P0至P1的連續點Q0，描述一條線性貝茲曲線。 由P1至P2的連續點Q1，描述一條線性貝茲曲線。 由Q0至Q1的連續點B（t），描述一條二次貝茲曲線。 為建構高階曲線，便需要相應更多的中介點。對於三次曲线，可由線性貝茲曲線描述的中介點Q0、Q1、Q2，和由二次曲線描述的點R0、R1所建構： 對於四次曲線，可由線性貝茲曲線描述的中介點Q0、Q1、Q2、Q3，由二次貝茲曲線描述的點R0、R1、R2，和由三次貝茲曲線描述的點S0、S1所建構： 還可參閱五階貝茲曲線的構成： 这些运动轨迹使用德卡斯特里奥算法计算出贝塞尔曲线。 n次貝茲曲線可以轉換為一個形狀完全相同的n+1次貝茲曲線。 這在軟體只支援特定階次的貝茲曲線時很有用。 例如，Cairo只支援三次貝茲曲線，你就可以用升階的方法在Cairo畫出二次貝茲曲線。 我們利用 B ( t ) = ( 1 − t ) B ( t ) + t B ( t ) {\displaystyle \mathbf {B} (t)=(1-t)\mathbf {B} (t)+t\mathbf {B} (t)} 這個特性來做升階。我們把曲線方程式中每一項 b i , n ( t ) P i {\displaystyle \mathbf {b} _{i,n}(t)\mathbf {P} _{i}} 都乘上 (1 − t) 或 t，讓每一項都往上升一階。以下是將二階升為三階的範例 ( 1 − t ) 2 P 0 + 2 ( 1 − t ) t P 1 + t 2 P 2 = ( 1 − t ) 3 P 0 + ( 1 − t ) 2 t P 0 + 2 ( 1 − t ) 2 t P 1 + 2 ( 1 − t ) t 2 P 1 + ( 1 − t ) t 2 P 2 + t 3 P 2 = ( 1 − t ) 3 P 0 + 3 ( 1 − t ) 2 t P 0 + 2 P 1 3 + 3 ( 1 − t ) t 2 2 P 1 + P 2 3 + t 3 P 2 {\displaystyle {\begin{aligned}&{}\quad (1-t)^{2}\mathbf {P} _{0}+2(1-t)t\mathbf {P} _{1}+t^{2}\mathbf {P} _{2}\\&=(1-t)^{3}\mathbf {P} _{0}+(1-t)^{2}t\mathbf {P} _{0}+2(1-t)^{2}t\mathbf {P} _{1}\\&{}\qquad +2(1-t)t^{2}\mathbf {P} _{1}+(1-t)t^{2}\mathbf {P} _{2}+t^{3}\mathbf {P} _{2}\\&=(1-t)^{3}\mathbf {P} _{0}+3(1-t)^{2}t{\frac {\mathbf {P} _{0}+2\mathbf {P} _{1}}{3}}+3(1-t)t^{2}{\frac {2\mathbf {P} _{1}+\mathbf {P} _{2}}{3}}+t^{3}\mathbf {P} _{2}\end{aligned}}} 對任何的n值，我們都可以使用以下等式 ( n + 1 i ) ( 1 − t ) b i , n = ( n i ) b i , n + 1 , ( 1 − t ) b i , n = n + 1 − i n + 1 b i , n + 1 {\displaystyle {n+1 \choose i}(1-t)\mathbf {b} _{i,n}={n \choose i}\mathbf {b} _{i,n+1},\quad (1-t)\mathbf {b} _{i,n}={\frac {n+1-i}{n+1}}\mathbf {b} _{i,n+1}} ( n + 1 i + 1 ) t b i , n = ( n i ) b i + 1 , n + 1 , t b i , n = i + 1 n + 1 b i + 1 , n + 1 {\displaystyle {n+1 \choose i+1}t\mathbf {b} _{i,n}={n \choose i}\mathbf {b} _{i+1,n+1},\quad t\mathbf {b} _{i,n}={\frac {i+1}{n+1}}\mathbf {b} _{i+1,n+1}} B ( t ) = ( 1 − t ) ∑ i = 0 n b i , n ( t ) P i + t ∑ i = 0 n b i , n ( t ) P i = ∑ i = 0 n n + 1 − i n + 1 b i , n + 1 ( t ) P i + ∑ i = 0 n i + 1 n + 1 b i + 1 , n + 1 ( t ) P i = ∑ i = 0 n + 1 ( i n + 1 P i − 1 + n + 1 − i n + 1 P i ) b i , n + 1 ( t ) = ∑ i = 0 n + 1 b i , n + 1 ( t ) P ′ i {\displaystyle {\begin{aligned}\mathbf {B} (t)&=(1-t)\sum _{i=0}^{n}\mathbf {b} _{i,n}(t)\mathbf {P} _{i}+t\sum _{i=0}^{n}\mathbf {b} _{i,n}(t)\mathbf {P} _{i}\\&=\sum _{i=0}^{n}{\frac {n+1-i}{n+1}}\mathbf {b} _{i,n+1}(t)\mathbf {P} _{i}+\sum _{i=0}^{n}{\frac {i+1}{n+1}}\mathbf {b} _{i+1,n+1}(t)\mathbf {P} _{i}\\&=\sum _{i=0}^{n+1}\left({\frac {i}{n+1}}\mathbf {P} _{i-1}+{\frac {n+1-i}{n+1}}\mathbf {P} _{i}\right)\mathbf {b} _{i,n+1}(t)=\sum _{i=0}^{n+1}\mathbf {b} _{i,n+1}(t)\mathbf {P'} _{i}\end{aligned}}} 式中 P − 1 {\displaystyle \mathbf {P} _{-1}} 和 P n + 1 {\displaystyle \mathbf {P} _{n+1}} 可以任意挑選。 因此，新的控制點為 P ′ i = i n + 1 P i − 1 + n + 1 − i n + 1 P i , i = 0 , … , n + 1. {\displaystyle \mathbf {P'} _{i}={\frac {i}{n+1}}\mathbf {P} _{i-1}+{\frac {n+1-i}{n+1}}\mathbf {P} _{i},\quad i=0,\ldots ,n+1.} 由于需要點陣化更精细的解析度时，重新插值（補點）的计算量较小，貝茲曲線被广泛地在计算机图形中用来为平滑曲线建立模型。貝茲曲線是矢量图形文件和相应软件（如PostScript、PDF等）能够处理的唯一曲线，用于光滑地近似其他曲线。 二次和三次貝茲曲線最为常用。 下列程式碼為一簡單的實際運用範例，展示如何使用C語言標出三次方貝茲曲線。注意，此處僅簡單的計算多項式係數，並讀盡一系列由0至1的t值；實踐中一般不會這麼做，遞歸求解通常會更快速——以更多的記憶體為代價，花費較少的處理器時間。不過直接的方法較易於理解並產生相同結果。以下程式碼已使運算更為清晰。實踐中的最佳化會先計算係數一次，並在實際計算曲線點的迴圈中反複使用。此處每次都會重新計算，損失了效率，但程式碼更清楚易讀。 曲線的計算可在曲線陣列上將相連點畫上直線——點越多，曲線越平滑。 在部分架構中，下以程式碼也可由動態规划進行最佳化。舉例來說，dt是一個常數，cx * t則等同於每次反覆就修改一次常數。經反覆應用這種最佳化後，迴圈可被重寫為沒有任何乘法（雖然這個過程不是穩定數值的）。 /* 產生三次方貝茲曲線的程式碼 */ typedef struct { float x; float y; } Point2D; /* cp在此是四個元素的陣列: cp[0]為起始點，或上圖中的P0 cp[1]為第一個控制點，或上圖中的P1 cp[2]為第二個控制點，或上圖中的P2 cp[3]為結束點，或上圖中的P3 t為參數值，0 <= t <= 1 */ Point2D PointOnCubicBezier( Point2D* cp, float t ) { float ax, bx, cx; float ay, by, cy; float tSquared, tCubed; Point2D result; /*計算多項式係數*/ cx = 3.0 * (cp[1].x - cp[0].x); bx = 3.0 * (cp[2].x - cp[1].x) - cx; ax = cp[3].x - cp[0].x - cx - bx; cy = 3.0 * (cp[1].y - cp[0].y); by = 3.0 * (cp[2].y - cp[1].y) - cy; ay = cp[3].y - cp[0].y - cy - by; /*計算位於參數值t的曲線點*/ tSquared = t * t; tCubed = tSquared * t; result.x = (ax * tCubed) + (bx * tSquared) + (cx * t) + cp[0].x; result.y = (ay * tCubed) + (by * tSquared) + (cy * t) + cp[0].y; return result; } /* ComputeBezier以控制點cp所產生的曲線點，填入Point2D結構的陣列。 呼叫者必須分配足夠的記憶體以供輸出結果，其為<sizeof(Point2D) numberOfPoints> */ void ComputeBezier( Point2D* cp, int numberOfPoints, Point2D* curve ) { float dt; int i; dt = 1.0 / ( numberOfPoints - 1 ); for( i = 0; i < numberOfPoints; i++) curve[i] = PointOnCubicBezier( cp, i*dt ); } 另一種貝茲曲線的應用是在動畫中，描述物件的運動路徑等等。此處，曲線的x、y位置不用來標示曲線，但用來表示圖形位置。當用在這種形式時，連續點之間的距離會變的更為重要，且大多不是平均比例。點將會串的更緊密，控制點更接近每一個點，而更為稀疏的控制點會散的更開。如果需要線性運動速度，進一步處理時就需要循所需路徑將點平均分散。 有時我們可能想要把貝茲曲線表示為多項式，而非比較不直接的伯恩斯坦多項式。使用二項式定理和貝茲曲線的定義，重新整理後可以得到： B ( t ) = ∑ j = 0 n t j C j {\displaystyle \mathbf {B} (t)=\sum _{j=0}^{n}{t^{j}\mathbf {C} _{j}}} 此處 C j = n ! ( n − j ) ! ∑ i = 0 j ( − 1 ) i + j P i i ! ( j − i ) ! = ∏ m = 0 j − 1 ( n − m ) ∑ i = 0 j ( − 1 ) i + j P i i ! ( j − i ) ! . {\displaystyle \mathbf {C} _{j}={\frac {n!}{(n-j)!}}\sum _{i=0}^{j}{\frac {(-1)^{i+j}\mathbf {P} _{i}}{i!(j-i)!}}=\prod _{m=0}^{j-1}(n-m)\sum _{i=0}^{j}{\frac {(-1)^{i+j}\mathbf {P} _{i}}{i!(j-i)!}}.} 計算曲線上的點時需要多次計算 B ( t ) {\displaystyle \mathbf {B} (t)} ，因此事先計算好 C j {\displaystyle \mathbf {C} _{j}} 會比較實際；然而要小心高階曲線可能會缺乏數值穩定性（需使用德卡斯特里奥算法來處理）。注意其空积為1。 有理貝茲增加可調節的權重，以提供更近似於隨意的形狀。分子是加權的伯恩斯坦形式貝茲曲線，而分母是加權的伯恩斯坦多項式的總和。 給定n + 1控制點Pi，有理貝茲曲線可如下描述： B ( t ) = ∑ i = 0 n b i , n ( t ) P i w i ∑ i = 0 n b i , n ( t ) w i {\displaystyle \mathbf {B} (t)={\frac {\sum _{i=0}^{n}b_{i,n}(t)\mathbf {P} _{i}w_{i}}{\sum _{i=0}^{n}b_{i,n}(t)w_{i}}}} 或簡單的 B ( t ) = ∑ i = 0 n ( n i ) t i ( 1 − t ) n − i P i w i ∑ i = 0 n ( n i ) t i ( 1 − t ) n − i w i {\displaystyle \mathbf {B} (t)={\frac {\sum _{i=0}^{n}{n \choose i}t^{i}(1-t)^{n-i}\mathbf {P} _{i}w_{i}}{\sum _{i=0}^{n}{n \choose i}t^{i}(1-t)^{n-i}w_{i}}}} 德卡斯特里奥算法 樣條 貝茲樣條 貝茲曲面 貝茲三角 NURBS string art（英语：string art），Bézier curves are also formed by many common forms of string art, where strings are looped across a frame of nails. 埃爾米特曲線 Shene, C.K. Finding a Point on a Bézier Curve: De Casteljau's Algorithm. [6 September 2012]. （原始内容存档于2017-08-15）.  Farin, Gerald, Curves and surfaces for computer-aided geometric design 4, Elsevier Science & Technology Books, 1997, ISBN 978 0 12249054 5  Paul Bourke: Bézier curves, https://web.archive.org/web/20060708162825/http://astronomy.swin.edu.au/%7Epbourke/curves/bezier/ Donald Knuth: Metafont: the Program, Addison-Wesley 1986, pp. 123-131. Excellent discussion of implementation details; available for free as part of the TeX distribution. Dr Thomas Sederberg, BYU Bézier curves, https://web.archive.org/web/20060221000535/http://www.tsplines.com/resources/class_notes/Bezier_curves.pdf J.D. Foley et al.: Computer Graphics: Principles and Practice in C (2nd ed., Addison Wesley, 1992) 三階貝茲曲線applet （页面存档备份，存于互联网档案馆）（英文） 即時數學貝茲applet （页面存档备份，存于互联网档案馆）（英文） 各種樣條類型的即時數學貝茲applet，樣條的JAVA程式設計 （页面存档备份，存于互联网档案馆）在互動式介紹樣條 （页面存档备份，存于互联网档案馆）（英文） Hermite與Bezier曲線繪製方法 北斗星君簡介貝茲曲線 （页面存档备份，存于互联网档案馆）