kde w jsou váhové funkce a P vstupní body.
Ukázka a vlastnosti
Pro křivku definovanou čtyřmi body ve 2D, dostaneme P_x(t)=w_0(t)P_{0,x}+w_1(t)P_{1,x}+w_2(t)P_{2,x}+w_3(t)P_{3,x}
P_y(t)=w_0(t)P_{0,y}+w_1(t)P_{1,y}+w_2(t)P_{2,y}+w_3(t)P_{3,y}
Křivka definovaná čtyřmi body se nazývá křivka třetího stupně. Připomeňme, že parametr t nabývá hodnot <0;1>.
Bézierova křivka třetího stupně může vypadat třeba takto
![]() |
![]() |
![]() |
![]() |
Vstupní čtyři body zadává uživatel a jejich změnou je schopen docílit změny výsledné křivky. Při editaci je třeba mít na paměti tři základní vlastnosti
- křivka nikdy neopustí konvexní obal definovaný vstupními body
- křivka bude vždy procházet prvním a posledním bodem
- směr křivky v koncových bodech je určen sousedními body
Váhové funkce
Ze vzorců výše vyplývá, že krom zadaných vstupních bodů budeme potřebovat ještě funkce w_i. Tyto funkce jsou generovány z Bernsteinových polynomů, které jsou definovány jako w_k(t)=\binom{n}{k}(1-t)^{n-k}(t)^k
kde n je počet stupňů výsledné křivky. Počet stupňů se pak rovná počtu řídících bodů mínus jedna.
Vypočítejme tedy funkce w_i pro křivku třetího stupně (čtyři řídící body)
\begin{array}{lcl}
w_0(t)&=&\binom{3}{0}(1-t)^{3-0}(t)^0= \\
&=&1(1-t)^3\cdot1= \\
&=&(1-t)^3 \\
\end{array}
\begin{array}{lcl}
w_1(t)&=&\binom{3}{1}(1-t)^{3-1}(t)^1= \\
&=&3(1-t)^2t^1= \\
&=&3(1-t)^2t \\
\end{array}
\begin{array}{lcl}
w_2(t)&=&\binom{3}{2}(1-t)^{3-2}(t)^2= \\
&=&3(1-t)^1t^2= \\
&=&3(1-t)t^2 \\
\end{array}
\begin{array}{lcl}
w_3(t)&=&\binom{3}{3}(1-t)^{3-3}(t)^3= \\
&=&1(1-t)^0t^3= \\
&=&1t^3= \\
&=&t^3 \\
\end{array}
a vynesme je pro názornost do grafu

Příklad
Zkusme dle obecného vztahu výše, postupně vypočítat Bézierovu křivku pro následující čtyři bodyP | x | y |
0 | 0 | 0 |
1 | 30 | 50 |
2 | 60 | 50 |
3 | 90 | 0 |
Dosadíme pro x P_x(t)=(1-t)^3\cdot0+3(1-t)t^2\cdot30+3(1-t)^2t\cdot60+t^3\cdot90
a pro y
P_y(t)=(1-t)^3\cdot0+3(1-t)t^2\cdot50+3(1-t)^2t\cdot50+t^3\cdot0
Po úpravách pak dostáváme
\begin{align*}
P_x(t)&=30\cdot3(1-t)t^2+60\cdot3(1-t)^2t+90t^3 \\
P_y(t)&=50\cdot3(1-t)t^2+50\cdot3(1-t)^2t
\end{align*}
Zkusme vypočítat hodnoty x a y pro bod v čase t=0
\begin{array}{lcl}
P_x(0)&=&30\cdot3(1-0)0^2+60\cdot3(1-0)^2\cdot0+90\cdot0^3= \\
&=&30\cdot3\cdot1\cdot0+60\cdot3\cdot1\cdot0+90\cdot0= \\
&=&0+0+0= \\
&=&0 \\
P_y(0)&=&50 \cdot 3(1-0)0^2+50\cdot3(1-0)^20= \\
&=&50\cdot3\cdot1 \cdot 0+50\cdot3\cdot1\cdot0= \\
&=&0+0= \\
&=&0 \\
\end{array}
a přidejme také výpočet pro čas t=1
\begin{array}{lcl}
P_x(1)&=&30 \cdot 3(1-1)1^2+60 \cdot 3(1-1)^2 \cdot 1+90 \cdot 1^3= \\
&=&30 \cdot 3\cdot0 \cdot 1+60 \cdot 3\cdot0+90\cdot1= \\
&=&0+0+90= \\
&=&90 \\
P_y(1)&=&50\cdot3(1-1)1^2+50 \cdot 3(1-1)^2 \cdot 1= \\
&=&50\cdot3 \cdot 0 \cdot 1+50\cdot3\cdot0\cdot1= \\
&=&0+0= \\
&=&0 \\
\end{array}
Jak vidíme, dostali jsme první bod výsledné křivky [0,0] a poslední [90,0]. Toto koresponduje s 2. vlastností Bézierových křivek, tedy že první bod musí odpovídat bodu P_0 a poslední bodu P_{n-1}. Stejným způsobem vypočítáme hodnoty pro x a y na celém intervalu t.

Implementace
Algoritmus má pár zvláštností, které můžou být v rozporu s naší individuální představou. Pseudokód pro výpočet křivky třetího stupně může vypadat taktod = 0.01; for(t = 0, t <= 1; t = t + d) { w0 = (1-t)*(1-t)*(1-t) w1 = 3*(1-t)*(1-t)*t w2 = 3*(1-t)*t*t w3 = t*t*t; x = w0*P0x + w1*P1x + w2*P2x + w3*P3x; y = w0*P0y + w1*P1y + w2*P2y + w3*P3y; putPixel(x, y); }Narážíme na problém - nejsme schopni spočítat všechny hodnoty na intervalu od 0 do 1! Pracujeme v diskrétním prostoru, což pro nás znamená použití určitého kroku. Vypočítáme tedy množinu bodů s krokem definovaným v proměnné d a ty vykreslíme na obrazovku. Nedostaneme krásnou křivku jako na obrázcích výše, ale více či méně separovaných bodů. Nabízí se řešení nastavit d dostatečně malé. Tento způsob nebude uspokojivě fungovat z několika důvodů. Pokud bude d příliš malé, budeme počítat hodnoty pro menší velikost, než je šířka pixelu na obrazovce. Pokud bude příliš velké, budou nám vznikat díry. Například pro d=0.2 dostaneme hodnoty pro pouhých šest bodů {0, 0.2, 0.4, 0.6, 0.8, 1}. Jako optimální řešení volíme spojení dvou bezprostředně za sebou následujících bodů úsečkou.
d = 0.01; predchozi_x = x0; predchozi_y = y0; for(t = 0, t <= 1; t = t + d) { w0 = (1-t)*(1-t)*(1-t) w1 = 3*(1-t)*(1-t)*t w2 = 3*(1-t)*t*t w3 = t*t*t; x = w0*P0x + w1*P1x + w2*P2x + w3*P3x; y = w0*P0y + w1*P1y + w2*P2y + w3*P3y; line(predchozi_x, predchozi_y, x, y); predchozi_x = x; predchozi_y = y; }Při zvolení vhodného d si tuto aproximaci můžeme dovolit, protože i oblouček můžeme diskrétně chápat jako spojení více krátkých úseček.
Literatura a odkazy
KOLCUN, A. Základy počítačovej grafiky. Učební texty, Ostrava 2006.ŽÁRA, J.; SOCHOR, J.; BENEŠ, B.; FELKEL, P. Moderní počítačová grafika. Computerpress, Brno 2004.
http://lubovo.misto.cz/_MAIL_/curves/ - pěkné zpracování tématiky v češtině, včetně appletů
http://herakles.zcu.cz/education/zpg/cviceni.php?no=11 - materiály ze Zápodočeské Univerzity v Plzni, také interaktivní
http://processingjs.nihongoresources.com/bezierinfo/ - spousta dalších informací a detailů (anglicky)
http://en.wikipedia.org/wiki/B%C3%A9zier_curve
Žádné komentáře:
Okomentovat