Bezier曲线,又有人叫贝赛尔曲线,贝兹曲线,在计算机绘图中经常被用到,由于前些天事件要用到这个,所以就研究了下。
有了参考资料,其实也不是很复杂。
曲线的介绍(转自维基百科,见本文的最下方)
初一看还是有些复杂的,其实贝兹曲线的绘制方法很简单,仔细看看一阶贝赛尔曲线,
一阶贝赛尔曲线上的由两个点确定 P0 和P1,当t在0--->1区间上递增时,根据式(1)
会得到多个点的坐标,其实这些的点就是一条直线上的点。
B(t) = (1-t)P0 + tP1--------------------------------------(1)
即:
B(t).x = (1-t)P0.x + tP1.x
B(t).y = (1-t)P0.y + tP1.y
二阶贝赛尔曲线由3个点确定,它可以理解成是这样的一阶贝赛尔曲线:确定该一阶贝赛尔曲线的两个点是变化的。
这两个点(设分别为Pm,Pn)是怎样变化的呢,这两个点又分别是(P0,P1)确定的一阶贝赛尔曲线和(P1,P2)确定的一阶贝赛尔
曲线上的点。
于是有了2阶贝赛尔曲线的公式
Pm(t) = (1-t)P0 + tP1
Pn(t) = (1-t)P1 + tP2
B(t) = (1-t)Pm(t) + tPn(t) = (1-t)^2 P0 + 2(1-t)tP1+ t^2P2
以此类推可以得到3阶贝赛尔曲线,是不是很简单?
怎样绘制是不是很简单了?
绘制3阶段贝赛尔曲线的函数,这里用VB语言实现
'函数说明: 画3阶贝塞尔曲线,该3阶贝塞尔曲线由3个点确定(原本该三阶曲线是由4个点确定的,不过这里把中间两 个 点合为一个点)
输入:cp,用来控制贝塞尔曲线形状的3个点形成的数组
PointeOnCurve()数组用来记录曲线上的点,iPointsNum该曲线上的点的数目,也就是PointOnCureve数组的大小
iPointsNum越大,曲线越光滑。因为该算法的实质是通过这些点的连成的直线形成曲线。
Private Type POINT_User
X As Single
Y As Single
End Type
Private Sub Draw3PointBezier(cp() As POINT_User, ByRef PointOnCurve() As POINT_User, ByVal iPointsNum As Integer)
Dim dt, t As Single
dt = 1# /( iPointsNum-1)
Dim i As Integer
For i = 0 To iPointsNum - 1
t = i * dt
PointOnCurve(i).X = (1 - t) ^ 3 * cp(0).X + 3 * t * (1 - t) * cp(1).X + t ^ 3 * cp(2).X
PointOnCurve(i).Y = (1 - t) ^ 3 * cp(0).Y + 3 * t * (1 - t) * cp(1).Y + t ^ 3 * cp(2).Y
' If (i > 0) Then
' Picture_1.Line (Int(PointOnCurve(i).X), Picture_1.ScaleHeight - Int(PointOnCurve(i).Y)) _
' -(Int(PointOnCurve(i - 1).X), Picture_1.ScaleHeight - Int(PointOnCurve(i - 1).Y))
' End If
Next i
End Sub
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
在數學的數值分析領域中,貝茲曲線(Bézier curve)是電腦圖形學中相當重要的參數曲線。更高維度的廣泛化貝茲曲線就稱作貝茲曲面,其中貝茲三角是一種特殊的實例。
貝茲曲線於1962年,由法國工程師皮埃爾·貝茲所廣泛發表,他運用貝茲曲線來為汽車的主體進行設計。貝茲曲線最初由 Paul de Casteljau 於1959年運用 de Casteljau 演算法開發,以穩定數值的方法求出貝茲曲線。
目錄[隱藏]
|
給定點 P0、P1,線性貝茲曲線只是一條兩點之間的直線。這條線由下式給出:
且其等同於線性插值。
二次方貝茲曲線的路徑由給定點 P0、P1、P2 的函數 B(t) 追蹤:
TrueType 字型就運用了以貝茲樣條組成的二次貝茲曲線。
P0、P1、P2、P3 四個點在平面或在三維空間中定義了三次方貝茲曲線。曲線起始於 P0 走向 P1,並從 P2 的方向來到 P3。一般不會經過 P1 或 P2;這兩個點只是在那裡提供方向資訊。 P0 和 P1 之間的間距,決定了曲線在轉而趨進 P3 之前,走向 P2 方向的「長度有多長」。
曲線的參數形式為:
現代的成象系統,如 PostScript、Asymptote 和 Metafont,運用了以貝茲樣條組成的三次貝茲曲線,用來描繪曲線輪廓。
n 階貝茲曲線可如下推斷。給定點 P0、P1、…、Pn,其貝茲曲線即
例如 n = 5:
如上公式可如下遞歸表達: 用 表示由點 P0、P1、…、Pn 所決定的貝茲曲線。則
用平常話來說,n 階的貝茲曲線,即雙 n - 1 階貝茲曲線之間的插值。
一些關於參數曲線的術語,有
即多項式
又稱作 n 階的伯恩斯坦基底多項式,定義 00 = 1。
點 Pi 稱作貝茲曲線的控制點。多邊形以帶有線的貝茲點連接而成,起始於 P0 並以 Pn 終止,稱作貝茲多邊形(或控制多邊形)。貝茲多邊形的凸包(convex hull)包含有貝茲曲線。
線性貝茲曲線演示動畫,t in [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 in [0,1] |
為建構高階曲線,便需要相應更多的中介點。對於三次曲次,可由線性貝茲曲線描述的中介點 Q0、Q1、Q2,和由二次曲線描述的點 R0、R1 所建構:
三次貝茲曲線的結構 | 三次貝茲曲線演示動畫,t in [0,1] |
對於四次曲線,可由線性貝茲曲線描述的中介點 Q0、Q1、Q2、Q3,由二次貝茲曲線描述的點 R0、R1、R2,和由三次貝茲曲線描述的點 S0、S1 所建構:
四次貝茲曲線的結構 | 四次貝茲曲線演示動畫,t in [0,1] |
(還可參閱五階貝茲曲線的構成。)
貝茲曲線被廣泛地在計算機圖形中用來為平滑曲線建立模型。
二次和三次貝茲曲線最為常見
下列程式碼為一簡單的實際運用範例,展示如何使用 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 位置不用來標示曲線,但用來表示圖形位置。當用在這種形式時,連續點之間的距離會變的更為重要,且大多不是平均比例。點將會串的更緊密,控制點更接近每一個點,而更為稀疏的控制點會散的更開。如果需要線性運動速度,進一步處理時就需要循所需路徑將點平均分散。
有理貝茲增加可調節的權重,以提供更近似於隨意的形狀。分子是加權的伯恩斯坦形式貝茲曲線,而分母是加權的伯恩斯坦多項式的總和。
給定 n + 1 控制點 Pi,有理貝茲曲線可如下描述:
或簡單的