Javascript 貝塞爾曲線

2023-02-17 10:58 更新

貝塞爾曲線用于計算機(jī)圖形繪制形狀,CSS 動畫和許多其他地方。

它們其實(shí)非常簡單,值得學(xué)習(xí)一次并且在矢量圖形和高級動畫的世界里非常受用。

控制點(diǎn)

貝塞爾曲線由控制點(diǎn)定義。

這些點(diǎn)可能有 2、3、4 或更多。

例如,兩點(diǎn)曲線:


三點(diǎn)曲線:


四點(diǎn)曲線:


如果仔細(xì)觀察這些曲線,你會立即注意到:

  1. 控制點(diǎn)不總是在曲線上這是非常正常的,稍后我們將看到曲線是如何構(gòu)建的。
  2. 曲線的階次等于控制點(diǎn)的數(shù)量減一。 對于兩個點(diǎn)我們能得到一條線性曲線(直線),三個點(diǎn) — 一條二階曲線,四個點(diǎn) — 一條三階曲線。
  3. 曲線總是在控制點(diǎn)的凸包內(nèi)部:


由于最后一個屬性,在計算機(jī)圖形學(xué)中,可以優(yōu)化相交測試。如果凸包不相交,則曲線也不相交。因此,首先檢查凸包的交叉點(diǎn)可以非??斓亟o出“無交叉”結(jié)果。檢查交叉區(qū)域或凸包更容易,因?yàn)樗鼈兪蔷匦?,三角形等(見上圖),比曲線簡單的多。

貝塞爾曲線繪制的主要重點(diǎn) —— 通過移動曲線,曲線以直觀明顯的方式變化。

經(jīng)過一些練習(xí)后,很明顯我們知道怎樣通過放置控制點(diǎn)來獲得所需要的曲線。通過連接幾條曲線,我們幾乎可以得到任何東西。

這里有一些例子:


數(shù)學(xué)

貝塞爾曲線可以使用數(shù)學(xué)方程式來描述。

很快我們就能看到 —— 沒必要知道它。但是為了完整性 —— 請看這里。

給定控制點(diǎn) Pi 的坐標(biāo):第一個控制點(diǎn)的坐標(biāo)為 P1 = (x1, y1),第二個控制點(diǎn)的坐標(biāo)為 P2 = (x2, y2),以此類推,曲線坐標(biāo)由方程式描述,這個方程式依賴屬于區(qū)間 [0,1] 的參數(shù) t。

  • 有兩個控制點(diǎn)的曲線方程:
  • ?P = (1-t)P1 + tP2
    ?

  • 有三個控制點(diǎn)的曲線方程:
  • ?P = (1?t)2P1 + 2(1?t)tP2 + t2P3
    ?

  • 有四個控制點(diǎn)的曲線方程:
  • ?P = (1?t)3P1 + 3(1?t)2tP2 +3(1?t)t2P3 + t3P4
    ?

這些是矢量方程。

我們可以逐坐標(biāo)重寫它們,例如 3 點(diǎn)曲線:

  • x = (1?t)2x1 + 2(1?t)tx2 + t2x3
  • y = (1?t)2y1 + 2(1?t)ty2 + t2y3

我們應(yīng)該放置 3 個控制點(diǎn)的坐標(biāo),而不是 x1、y1、x2、y2、x3 和 y3。

例如,如果控制點(diǎn)是 (0,0)、(0.5, 1) 和 (1, 0),則方程式為:

  • x = (1?t)2 * 0 + 2(1?t)t * 0.5 + t2 * 1 = (1-t)t + t2 = t
  • y = (1?t)2 * 0 + 2(1?t)t * 1 + t2 * 0 = 2(1-t)t = –t2 + 2t

現(xiàn)在隨著 t 從 0 到 1 變化,每個 t 對應(yīng)的 (x,y) 集合可以構(gòu)成曲線。

這可能太學(xué)術(shù)化了,對于曲線為什么看起來像這樣以及它們?nèi)绾我蕾囉诳刂泣c(diǎn)的描述并不是很明顯。

所以繪制算法可能更容易理解。

德卡斯特里奧算法

德卡斯特里奧算法與曲線的數(shù)學(xué)定義相同,但直觀地顯示了曲線是如何被建立的。

讓我們看看 3 個控制點(diǎn)的例子。

這里是一個演示,隨后會有解釋。

控制點(diǎn)可以用鼠標(biāo)移動,點(diǎn)擊 “play” 運(yùn)行演示。

示例

德卡斯特里奧算法構(gòu)造三點(diǎn)貝塞爾曲線:

  1. 繪制控制點(diǎn)。在上面的演示中,它們標(biāo)有:?1?、?2? 和 ?3?。
  2. 創(chuàng)建控制點(diǎn) 1 → 2 → 3 間的線段. 在上面的演示中它們是棕色的。
  3. 參數(shù) ?t? 從 ?0? to ?1? 變化。 在上面的演示中取值 ?0.05?:循環(huán)遍歷 ?0, 0.05, 0.1, 0.15, ... 0.95, 1?。
  4. 對于每一個 t 的取值:

    • 在每一個棕色線段上我們?nèi)∫粋€點(diǎn),這個點(diǎn)距起點(diǎn)的距離按比例 ?t? 取值。由于有兩條線段,我們能得到兩個點(diǎn)。
    • 例如,當(dāng) t=0 — 所有點(diǎn)都在線段起點(diǎn)處,當(dāng) t=0.25 — 點(diǎn)到起點(diǎn)的距離為線段長度的 25%,當(dāng) t=0.5 — 50%(中間),當(dāng) t=1 — 線段終點(diǎn)。

    • 連接這些點(diǎn),下面這張圖中連好的線被繪制成藍(lán)色。
    • 當(dāng) t=0.25 當(dāng) t=0.5
  5. 現(xiàn)在在藍(lán)色線段上取一個點(diǎn),距離比例取相同數(shù)值的 ?t?。也就是說,當(dāng) ?t=0.25?(左圖)時,我們?nèi)〉降狞c(diǎn)位于線段的左 1/4 終點(diǎn)處,當(dāng) ?t=0.5?(右圖)時 — 線段中間。在上圖中這一點(diǎn)是紅色的。
  6. 隨著 ?t? 從 ?0? to ?1? 變化,每一個 ?t? 的值都會添加一個點(diǎn)到曲線上。這些點(diǎn)的集合就形成的貝塞爾曲線。它在上面的圖中是紅色的,并且是拋物線狀的。

這是三控制點(diǎn)的處理過程,但是對于 4 個點(diǎn)同樣適用。

4 個控制點(diǎn)的演示(點(diǎn)可以被鼠標(biāo)移動):

示例

算法:

  • 控制點(diǎn)通過線段連接:1 → 2、2 → 3 和 3 → 4。 我們能得到 3 條棕色的線段。
  • 對于 ?0? to ?1? 之間的每一個 ?t?:
    • 我們在這些線段上距起點(diǎn)距離比例為 ?t? 的位置取點(diǎn)。把這些點(diǎn)連接起來,然后得到兩條綠色線段。
    • 在這些線段上同樣按比例 ?t? 取點(diǎn),得到一條藍(lán)色線段。
    • 在藍(lán)色線段按比例 ?t? 取點(diǎn)。在上面的例子中是紅色的。
  • 這些點(diǎn)在一起組成了曲線。

該算法是遞歸的,并且可以適應(yīng)于任意數(shù)量的控制點(diǎn)。

給定 N 個控制點(diǎn),我們將它們連接起來以獲得初始的 N-1 個線段。

然后對從 0 到 1 的每一個 t

  • 在每條線段上按 ?t? 比例距離取一個點(diǎn)并且連接 —— 會得到 N-2 個線段。
  • 在上面得到的每條線段上按 ?t? 比例距離取一個點(diǎn)并且連接 —— 會得到 N-3 個線段,以此類推……
  • 直到我們得到一個點(diǎn)。得到的這些點(diǎn)就形成了曲線。

曲線的移動演示:

和其它的點(diǎn):

環(huán)形:

非平滑貝塞爾曲線:

由于算法是遞歸的,我們可以構(gòu)建任何順序的貝塞爾曲線:使用 5 個、6 個或更多個控制點(diǎn)。但在實(shí)踐中它們沒那么有用。通常我們?nèi)?2-3 個點(diǎn),對于復(fù)雜的線條,將幾條曲線拼接在一起。這更容易開發(fā)和計算。

如何通過給定點(diǎn)繪制曲線?

我們使用控制點(diǎn)制作貝塞爾曲線。正如我們所見,它們并不在曲線上?;蛘吒鼫?zhǔn)確地說,第一個和最后一個在曲線上,但其它的不在。

有時我們有另一種任務(wù):繪制一條曲線通過幾個點(diǎn),讓它們都在一條平滑曲線上。這種任務(wù)叫插值,這里我們不覆蓋講解它。

這些曲線有數(shù)學(xué)方程式,例如拉格朗日多項式。

在計算機(jī)圖形中樣條插值通常用于構(gòu)建連接多個點(diǎn)的平滑曲線。

總結(jié)

貝塞爾曲線由其控制點(diǎn)定義。

貝塞爾曲線的兩種定義方法:

  1. 使用數(shù)學(xué)方程式。
  2. 使用繪圖過程:德卡斯特里奧算法

貝塞爾曲線的優(yōu)點(diǎn):

  • 我們可以通過控制點(diǎn)移動來用鼠標(biāo)繪制平滑線條。
  • 復(fù)雜的形狀可以由多條貝塞爾曲線組成。

用途:

  • 在計算機(jī)圖形學(xué),建模,矢量圖形編輯器中。字體由貝塞爾曲線描述。
  • 在 Web 開發(fā)中 — 用于 Canvas 上的圖形和 SVG 格式。順便說一下,上面的“實(shí)時”示例是用 SVG 編寫的。它們實(shí)際上是一個 SVG 文檔,被賦予不同的控制點(diǎn)做參數(shù)。你可以在單獨(dú)的窗口中打開它并查源碼:demo.svg。
  • 在 CSS 動畫中描述動畫的路徑和速度。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號