De Casteljau算法
題目 在Bezier曲線上找到點(diǎn):De Casteljau算法
翻譯文章來(lái)自http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/Bezier/de-casteljau.html
在貝塞爾曲線繪制完成后,下一個(gè)重要的任務(wù)是選定特定u的情況下在曲線上找到點(diǎn)C(u)。一個(gè)簡(jiǎn)單的方法是把u插到每一個(gè)基函數(shù)上,計(jì)算每個(gè)其與基函數(shù)的乘積以及其相應(yīng)的控制頂點(diǎn),最后將其相加。雖然這種方法很好,但是缺乏數(shù)值穩(wěn)定性(例如在計(jì)算Bernstein多項(xiàng)式的時(shí)候可能引進(jìn)數(shù)值(numerical errors)誤差)。
在下文中,我們僅僅記下控制點(diǎn)的數(shù)字。例如00對(duì)應(yīng)控制點(diǎn)P0,01對(duì)應(yīng)P1,...,0i對(duì)應(yīng)Pi,...,0n對(duì)應(yīng)Pn。因此在這些數(shù)字中0s表示初始的或者是第0次迭代。在之后,0被其他數(shù)字1,2,3代替表示第1,2,3次迭代,等等。
De Casteljau算法的基本觀點(diǎn)是選擇在AB中的一個(gè)點(diǎn)C,C將AB分為u:1-u(A到C的距離與AB之間的距離之比是u),讓我們找到?jīng)Q定C在哪里的方法
從A到B的向量是B-A。因?yàn)閡是在0和1之間的比率,點(diǎn)C位于u(B-A)。將A的位置加以考慮,點(diǎn)C為A+u(B-A)=(1-u)A+uB。因此,對(duì)于給定的u,(1-u)A+uB是在A和B之間的點(diǎn)C,將AB分為u:1-u的兩段
De Casteljau算法的想法如下。假設(shè)我們想要找到C(u),u在[0,1]中。由第一個(gè)多段線00-01-02-03...-0n開(kāi)始,利用上面的法則找到在線段上的點(diǎn)1i,1i在0i到0(i+1)的連線上并且將這段線分為u:1-u的兩部分。依次地,我們可以得到n個(gè)點(diǎn)10,11,12,...,1(n-1),他們定義了一個(gè)新的多段線(polyline),一共有n-1段
在上圖中,u是0.4,10是在00和01的線段(leg),11是在01和02的線段,...,并且14是在04到05的線段,所有的新點(diǎn)都由藍(lán)色的表示。
新點(diǎn)由1i進(jìn)行標(biāo)記,再次利用上面的規(guī)則我們可以得到第二個(gè)多段線,具有n-1個(gè)點(diǎn)(20,21,...,2(n-2))和n-2條邊。從這個(gè)多段線開(kāi)始,進(jìn)行第三次,得到新的多段線,由n-2個(gè)點(diǎn)30,31,...,3(n-3)和n-3條邊組成。重復(fù)這個(gè)過(guò)程n次得到一個(gè)點(diǎn)n0,Casteljau已經(jīng)證明在曲線上的點(diǎn)C(u)對(duì)應(yīng)u
以上圖舉例,20是在10和11上將這段線分為u:1-u的點(diǎn),類(lèi)似地選取21在11和12上,22在12和13上,23在13和14上.第三個(gè)多段線是20,21,22,23.第三個(gè)多段線有四個(gè)點(diǎn)和三條邊。繼續(xù)做得到30,31,32組成的多段線,這是第四個(gè)多段線。繼續(xù)得到有40和41組成的線段,再做一次得到50,為點(diǎn)C(0.4)。
這是de Casteljau算法的幾何解釋,是在曲線設(shè)計(jì)中最漂亮(elegant)的結(jié)果之一。
實(shí)際計(jì)算
給定了de Casteljau的幾何解釋之后,我們現(xiàn)在展示一個(gè)計(jì)算方法,由下圖
首先,在如圖中的最左邊一列是給定的控制點(diǎn)。對(duì)于每一對(duì)臨近的控制點(diǎn),可以畫(huà)出一條右上方和右下方的箭頭,并且在兩個(gè)箭頭的交點(diǎn)處寫(xiě)下一個(gè)新點(diǎn)。例如相鄰的兩個(gè)點(diǎn)分別為ij 和i(j+1),新點(diǎn)是(i+1)j,右下方(相對(duì)應(yīng)的左下方)的箭頭表示將其尾數(shù)ij(相對(duì)應(yīng)的為i(j+1))乘以1-u(相對(duì)應(yīng)的乘以u(píng)),新的點(diǎn)是兩個(gè)的和。
因此,從初始的第0列開(kāi)始,我們計(jì)算第1列。之后從第1列得到第2列。最終,在n次計(jì)算之后我們最終到達(dá)了一個(gè)單個(gè)的點(diǎn)n0并且這個(gè)點(diǎn)就是在曲線上的點(diǎn)。下面的算法總結(jié)了上面我們討論的內(nèi)容,輸入的是具有n+1個(gè)點(diǎn)的數(shù)列P和在0到1之間的u,最終得到在Bezier曲線上的點(diǎn)C(u)
Input: array P[0:n] of n+1 points and real number u in [0,1] Output: point on curve, C(u) Working: point array Q[0:n] for i := 0 to n do Q[i] := P[i]; // save input for k := 1 to n do for i := 0 to n - k do Q[i] := (1 - u)Q[i] + u Q[i + 1]; return Q[0];一個(gè)遞歸關(guān)系
上面的計(jì)算過(guò)程可以用遞歸的方法表示,對(duì)于j=0,1,...,n用P0,j表示Pj,也就是P0,j是第0列的第j項(xiàng)元素,在第i列計(jì)算第j項(xiàng)如下
元素Pi,j是(1-u)Pi-1,j(左上方元素和 uPi-1,j+1(左下方元素)的和,最終的結(jié)果(在曲線上的點(diǎn))是Pn,0.在這種想法的基礎(chǔ)上,我們可以快速得到以下過(guò)程
function deCasteljau(i,j) begin if i = 0 then return P0,j else return (1-u)* deCasteljau(i-1,j) + u* deCasteljau(i-1,j+1) end這個(gè)過(guò)程看起來(lái)簡(jiǎn)單,表達(dá)上也很簡(jiǎn)練,但是效率卻不高。因?yàn)槲覀兿胍獙?duì)于Pn,0計(jì)算deCasteljau(n,0) ,我們要分別對(duì)Pn-1,0計(jì)算deCasteljau(n-1,0),0,對(duì)Pn-1,1計(jì)算deCasteljau(n-1,1)
再考慮計(jì)算deCasteljau(n-1,0)。分為對(duì)于Pn-2,0計(jì)算deCasteljau(n-2,0),和對(duì)于Pn-2,1計(jì)算deCasteljau(n-2,1)。對(duì)于deCasteljau(n-1,1)也是分為兩部分如上圖所示。因此deCasteljau(n-2,1)被計(jì)算了兩遍,如果我們擴(kuò)展這些函數(shù)計(jì)算,我們會(huì)發(fā)現(xiàn)對(duì)于Pi,j的計(jì)算重復(fù)了很多遍,而不是僅僅計(jì)算了一遍。事實(shí)上,上面的計(jì)算和計(jì)算Fibonacci數(shù)列的第n項(xiàng)是類(lèi)似的
function Fibonacci(n) begin if n = 0 or n = 1 then return 1 elsereturn Fibonacci (n-1) + Fibonacci (n-2) end為了計(jì)算 Fibonacci( n)函數(shù)被調(diào)用了指數(shù)次,因此上面的de Casteljau算法對(duì)于直接的實(shí)現(xiàn)來(lái)說(shuō)是不合適的,雖說(shuō)代碼看上去比較簡(jiǎn)潔。
一個(gè)有趣的觀察
de Casteljau算法的三角形計(jì)算方法提供了一種有趣的現(xiàn)象,舉一個(gè)例子,八個(gè)控制點(diǎn)00,01,...,07組成的7階Bezier曲線。選擇控制點(diǎn)列中的連續(xù)序列,對(duì)于給定的u,怎樣計(jì)算其在Bezier曲線上對(duì)應(yīng)的點(diǎn)呢?事實(shí)上,如果利用de Casteljau算法,發(fā)現(xiàn)在曲線上的點(diǎn)就是等邊三角形的頂點(diǎn)!其底是選擇的連續(xù)點(diǎn)列。
舉例來(lái)說(shuō),如果我們選擇02,03,04,05,其對(duì)應(yīng)于u這四個(gè)控制頂點(diǎn)的曲線上的點(diǎn)就是32,就是上圖中的藍(lán)色三角形,如果選擇11,12,13,在曲線上的點(diǎn)就是31,如黃色三角形。如果選擇30,31,32,33和34,那么在曲線上的點(diǎn)就是70.
也是同樣的原因,70在由60和61組成的Bezier曲線上。同樣地,也是50,51和52上的點(diǎn),也是40,41,42,43.一般地,如果我們選擇一個(gè)點(diǎn)并且如上所示畫(huà)一個(gè)等邊三角形,其底上的控制點(diǎn)就是被選擇用來(lái)計(jì)算的點(diǎn)。
總結(jié)
以上是生活随笔為你收集整理的De Casteljau算法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: [vue] 说说你对keep-alive
- 下一篇: 保姆级的Arduino循迹小车研发日志及