Remove ads
来自维基百科,自由的百科全书
在數學的數值分析領域中,貝茲曲線(英語:Bézier curve)是計算機圖形學中相當重要的參數曲線。更高維度的廣泛化貝茲曲線就稱作貝茲曲面,其中貝茲三角是一種特殊的實例。
貝茲曲線於1962年,由法國工程師皮埃爾·貝茲(Pierre Bézier)所廣泛發表,他運用貝茲曲線來為汽車的主體進行設計。貝茲曲線最初由保爾·德·卡斯特里奧於1959年運用德卡斯特里奧演算法開發,以穩定數值的方法求出貝茲曲線。
給定點P0、P1,線性貝茲曲線只是一條兩點之間的直線。這條線由下式給出:
且其等同於線性插值。
二次方貝茲曲線的路徑由給定點P0、P1、P2的函數B(t)追蹤:
P0、P1、P2、P3四個點在平面或在三維空間中定義了三次方貝茲曲線。曲線起始於P0走向P1,並從P2的方向來到P3。一般不會經過P1或P2;這兩個點只是在那裡提供方向資訊。P0和P1之間的間距,決定了曲線在轉而趨進P2之前,走向P1方向的「長度有多長」。
曲線的參數形式為:
現代的成象系統,如PostScript、Asymptote和Metafont,運用了以貝茲樣條組成的三次貝茲曲線,用來描繪曲線輪廓。
階貝茲曲線可如下推斷。給定點P0、P1、…、Pn,其貝茲曲線即
例如:
如上公式可如下遞歸表達: 用表示由點P0、P1、…、Pn所決定的貝茲曲線。則
用平常話來說,階的貝茲曲線,即雙階貝茲曲線之間的插值。
一些關於參數曲線的術語,有
即多項式
又稱作n階的伯恩斯坦基底多項式,定義00 = 1。
點Pi稱作貝茲曲線的控制點。多邊形以帶有線的貝茲點連接而成,起始於P0並以Pn終止,稱作貝茲多邊形(或控制多邊形)。貝茲多邊形的凸包(convex hull)包含有貝茲曲線。
線性貝茲曲線演示動畫,t在[0,1]區間 |
線性貝茲曲線函數中的t會經過由P0至P1的B(t)所描述的曲線。例如當t=0.25時,B(t)即一條由點P0至P1路徑的四分之一處。就像由0至1的連續t,B(t)描述一條由P0至P1的直線。
為建構二次貝茲曲線,可以中介點Q0和Q1作為由0至1的t:
二次貝茲曲線的結構 | 二次貝茲曲線演示動畫,t在[0,1]區間 |
為建構高階曲線,便需要相應更多的中介點。對於三次曲線,可由線性貝茲曲線描述的中介點Q0、Q1、Q2,和由二次曲線描述的點R0、R1所建構:
三次貝茲曲線的結構 | 三次貝茲曲線演示動畫,t在[0,1]區間 |
對於四次曲線,可由線性貝茲曲線描述的中介點Q0、Q1、Q2、Q3,由二次貝茲曲線描述的點R0、R1、R2,和由三次貝茲曲線描述的點S0、S1所建構:
四次貝茲曲線的結構 | 四次貝茲曲線演示動畫,t在[0,1]區間 |
還可參閱五階貝茲曲線的構成:
五次貝茲曲線演示動畫,t在[0,1]區間 |
n次貝茲曲線可以轉換為一個形狀完全相同的n+1次貝茲曲線。 這在軟體只支援特定階次的貝茲曲線時很有用。 例如,Cairo只支援三次貝茲曲線,你就可以用升階的方法在Cairo畫出二次貝茲曲線。
我們利用這個特性來做升階。我們把曲線方程式中每一項都乘上 (1 − t) 或 t,讓每一項都往上升一階。以下是將二階升為三階的範例
對任何的n值,我們都可以使用以下等式
式中 和 可以任意挑選。
因此,新的控制點為[2]
由於需要點陣化更精細的解析度時,重新插值(補點)的計算量較小,貝茲曲線被廣泛地在計算機圖形中用來為平滑曲線建立模型。貝茲曲線是矢量圖形文件和相應軟件(如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位置不用來標示曲線,但用來表示圖形位置。當用在這種形式時,連續點之間的距離會變的更為重要,且大多不是平均比例。點將會串的更緊密,控制點更接近每一個點,而更為稀疏的控制點會散的更開。如果需要線性運動速度,進一步處理時就需要循所需路徑將點平均分散。
有時我們可能想要把貝茲曲線表示為多項式,而非比較不直接的伯恩斯坦多項式。使用二項式定理和貝茲曲線的定義,重新整理後可以得到:
此處
計算曲線上的點時需要多次計算,因此事先計算好會比較實際;然而要小心高階曲線可能會缺乏數值穩定性(需使用德卡斯特里奧算法來處理)。注意其空積為1。
有理貝茲增加可調節的權重,以提供更近似於隨意的形狀。分子是加權的伯恩斯坦形式貝茲曲線,而分母是加權的伯恩斯坦多項式的總和。
給定n + 1控制點Pi,有理貝茲曲線可如下描述:
或簡單的
Seamless Wikipedia browsing. On steroids.
Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.
Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.