下面的說明只注重對概念的表述和對實際操作過程的說明,並不進行嚴格的證明。
一般的貝茲路徑:
對給定的 n+1 個點,可以作出 n 階的貝茲路徑。其中最前和最後這兩個點在曲線上,其餘 n-1 個中間點是控制點,主要用於控制曲線的形狀,不一定在曲線上。
假如給定的 n+1 個點是 (x0,y0),...,(xn,yn), 以 t 作為參數,則產生的曲線上的所有點可以表示如下:
n
x = ∑ C(n,i) *t^i *(1-t)^(n-i) *xi
i=0
n
y = ∑ C(n,i) *t^i *(1-t)^(n-i) *yi
i=0
其中 x,y 分別是產生的曲線上的點的 橫座標 和 縱座標。
t 是參數,其有效範圍是 [0,1]。
C(n,i)就是組合數,比如 C(3,1) = 3。
實用 3 階貝茲路徑:
實際應用中,常用 3 階的貝茲路徑,也就是要對 4 個點進行計算。
設 已知 的4點為 p0(x0,y0),p1(x1,y1),p2(x2,y2),p3(x3,y3),其中 0 和 3 是端點, 1,2是控制點,則 該曲線上的所有點表示為:
x = (1-t)^3 *x0 + 3*t*(1-t)^2 *x1 + 3*t^2*(1-t) *x2 + t^3 *x3
y = (1-t)^3 *y0 + 3*t*(1-t)^2 *y1 + 3*t^2*(1-t) *y2 + t^3 *y3
其中 0 <= t <= 1.
直接的簡單實現:
按照公式,對每個t,代入式子就可以得到曲線上對應點的座標了。當然具體實現時,可根據適當的間隔取 t 值,然後用直線將這些值對應的點連起來就是了。
類似於多項式的計算,在電腦上計算的時候,可以用 德卡斯翠奧演算法 來求出,而不必直接計算高次冪。
設四個控制頂點是p0,p1,p2,p3,對每個具體的 t,可以做出下面的表:
p00
p10 p11
p20 p21 p22
p30 p31 p32 p33
其中:
p00 = p0
p10 = p1
p20 = p2
p30 = p3
p11 = p00*(1-t) + p10*t
p21 = p10*(1-t) + p20*t
p31 = p20*(1-t) + p30*t
p22 = p11*(1-t) + p21*t
p32 = p21*(1-t) + p31*t
p33 = p22*(1-t) + p32*t
通過驗證可以知道,p33就是要求的值。
代碼略。
簡單實現遇到的問題:
上面說的簡單實現,t 的間距不好確定。因為曲線的形狀可能千奇百怪,間隔太大則誤差太大,太小的話則效率太低,難以確定一個對所有情況都合適的間隔值。而在實際應用中,則是用 遞迴 的方法來解決這個問題的。
實際中的遞迴處理:
回頭看上面求值的那個演算法,當取 t=1/2 時, t = 1-t = 1/2,計算過程可以簡化如下:
p00
p10 p11
p20 p21 p22
p30 p31 p32 p33
其中:
pi0跟上面一樣,分別就是那4個輸入焦點p0,p1,p2,p3
pij = [ p(i-1)(j-1) + p(i-1)j ] / 2 (簡化的就是這個計算過程)
顯然,p33就是 t=1/2 時所對應曲線上的點。
而且,
如果以p00,p11,p22,p33為4個新的輸入焦點,產生新的3階貝茲路徑,則該曲線跟原來p0~p3產生的曲線在t∈[0,1/2]的部分“完全重合”。
如果以p33,p32,p31,p30為4個新的輸入焦點,產生新的3階貝茲路徑,則該曲線跟原來p0~p3產生的曲線在t∈[1/2,1]的部分“完全重合”。
這裡注意新輸入焦點的輸入順序。
上面漏了說貝茲路徑跟輸入焦點的一個關係,就是貝茲路徑總是處在 輸入焦點的凸包 內。那麼可以得知,曲線上的點到 線段p0p3(就是兩個端點) 的距離不大於 max(p1到p0p3的距離, p2到p0p3的距離)。
而採用 德卡斯翠奧演算法,取t=1/2 所求出來的中間點pij,其實就是 p(i-1)(j-1),pi(j-1) 的中點。比劃一下也可以看出,中間點全部都在 p00,p10,p20,p30的凸包裡面,也就是 p00,p11,p22,p33所形成的凸包 和 p33,p32,p21,p30的凸包也被包含在 p0,p1,p2,p3 的凸包裡面。
綜上所述:
p00,p11,p22,p33 和 p33,p32,p31,p30 所產生的曲線拼起來,就是p0,p1,p2,p3產生的曲線。
對p0,p1,p2,p3,用線段 p0p3 代替 產生的曲線,並以曲線上的點到線段的最大距離為誤差,則 p00,p11,p22,p33 和 p33,p32,p31,p30的誤差比 p0,p1,p2,p3 的要小。
所以,得到的遞迴產生曲線步驟如下:
1、
對 p0,p1,p2,p3 4個點,先檢查
max( d(p1, p0p3), d(p2, p0p3) ) < E (d()是點到直線距離,E是給定的誤差範圍,表示p0,p2,p3,p3的凸包的邊跟產生曲線的最大差距。)
是否成立。
如果 滿足 條件,則簡單用線段 p0p3 代替產生的曲線,返回。
如果不滿足,繼續。
2、
對 p0,p1,p2,p3 4個點,進行 t=1/2 的德卡裡奧演算法。
對得到的 p00,p11,p22,p33,遞迴進行步驟 1 的操作;
對得到的 p33,p32,p31,p30,遞迴進行步驟 1 的操作。
返回。