Autor: Jiří Hnídek / jiri.hnidek@tul.cz
“Curve need not to be curved!”
“ One ring to rule them all,
one ring to find them,
one ring to bring them all,
and in the darkness bind them ”
Úsečka leží na přímce, kterou můžeme vyjádřit pomocí:
$$ y = kx + q $$Úsečka je část přímky, která je jednoznačně určena body $ P_{1} = [x_{1}, y_{1}]$ a $ P_{2} = [x_{2}, y_{2}] $. Směrnice přímky je:
$$ k = \frac{\Delta y}{\Delta x} = \frac{y_{2} - y_{1}}{x_{1} - x_{2}} $$Pro osmispojitou úsečku s tloušťkou jedna a rezignací na antialiasing lze použít například algoritmus DDA (Digital Differential Analyzer)
Varianta algoritmu pro $ k < 1 $:
var k = (y2 - y1)/(x2 - x1);
var x = x1;
var y = y1;
while(x < x2) {
draw(x, y);
x += 1;
y += k;
}
V praxi je často nutné vykreslovat úsečku jako geometrický útvar (nejčastěji obdelník) a řešit další netriviální problémy.
Naštěstí existuje spousta knihoven a API (HTML5 Canvas, WebGL, atd.), které tyto problémy řeší za nás.
Úsečku můžeme do canvasu vykreslit jednoduše pomocí následujícího kódu v Javascriptu.
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(150, 100);
ctx.lineTo(390,170);
ctx.lineWidth = 10;
ctx.strokeStyle = 'white';
ctx.lineCap = 'round';
ctx.stroke();
Oproti funkcím může křivka protínat samu sebe, může se uzavřít, může být rovnoběžná s libovolnou osou, apod.
Parametr $ t $ můžeme chápat jako čas.
Lze je používat jak ve 2D, tak i v 3D prostoru.
Říkáme, že křivku $ Q(t) $ nazýváme parametricky spojitou $ C^{n} $, pokud ve všech jejích bodech existuje derivace stupně $ n $
Dvě křivky $ Q_{1} $ a $ Q_{2} $ jsou geometricky spojité $ G^{n} $ ve společném bodě, pokud je zaručeno:
$$ q_{1}^{(n)} = k q_{2}^{(n)}; \quad k > 0 $$Jinými slovy pro $ G^{1} $ není potřeba rovnost tečných vektorů, ale pouze rovnost tečen v daném bodě.
Je-li křivka $ C^{1} $ je potom i $ G^{1} $ spojitá?
Ano, je-li křivka $ C^{n} $ tak je potom automaticky i $ G^{n} $ spojitá.
“Polynoms rule the world of parametric curves”
Parametrické vyjádření kubik má následující tvar:
$$ \begin{align} x(t) &= a_{x}t^{3} + b_{x}t^{2} + c_{x}t + d_{x} \\ y(t) &= a_{y}t^{3} + b_{y}t^{2} + c_{y}t + d_{y} \\ z(t) &= a_{z}t^{3} + b_{z}t^{2} + c_{z}t + d_{z} \end{align} $$Matici $ C $ můžeme vyjádřit: $ C = MG $
$$ \begin{bmatrix} a_{x} & a_{y} & a_{z} \\ b_{x} & b_{y} & b_{z} \\ c_{x} & c_{y} & c_{z} \\ d_{x} & d_{y} & d_{z} \\ \end{bmatrix} = \begin{bmatrix} m_{11} & m_{12} & m_{13} & m_{14} \\ m_{21} & m_{22} & m_{23} & m_{24} \\ m_{31} & m_{32} & m_{33} & m_{34} \\ m_{41} & m_{42} & m_{43} & m_{44} \\ \end{bmatrix} \begin{bmatrix} G_{1} \\ G_{2} \\ G_{3} \\ G_{4} \\ \end{bmatrix} $$kde $ M $ se nazývá bázová matice (určuje druh křivky) a $ G $ je vektor geometrických podmínek (řídící body a vektory)
Výsledný podoba maticového vyjádření:
$$ Q(t) = \begin{bmatrix} t^3 & t^2 & t & 1 \end{bmatrix} \begin{bmatrix} m_{11} & m_{12} & m_{13} & m_{14} \\ m_{21} & m_{22} & m_{23} & m_{24} \\ m_{31} & m_{32} & m_{33} & m_{34} \\ m_{41} & m_{42} & m_{43} & m_{44} \\ \end{bmatrix} \begin{bmatrix} G_{1} \\ G_{2} \\ G_{3} \\ G_{4} \\ \end{bmatrix} $$Určují váhu jednotlivých řídících bodů/vektorů pro různé hodnoty $ t \in \langle 0, 1 \rangle $
Mějme křivku, která je určena body $ P_{1} $ a $ P_{2} $:
$$ Q(t) = (1 - t)P_{1} + tP_{2} \quad 0 \leq t \leq 1 $$O jakou křivku se jedná?
Je to úsečka s krajními body $ P_{1} $ a $ P_{2} $.
Interpolační křivky procházejí všemi řídícími body.
Aproximační křivky nemusí procházet žádným ze svých řídící bodů.
Patří mezi ně například Hermitovské kubiky nebo TCB křivky, ale v praxi se příliš npoužívají
Ty se v počítačové grafice používají naopak velmi často. Patří mezi ně především Bézierovy kubyky, B-Spline křivky a konečně NURBs křivky
“Aproximate or interpolate? That's the question!”
Je dána vztahem:
$$ Q(t) = \sum_{i=0}^{n} P_{i} B_{i}^{n}(t); \quad t \in \langle 0, 1 \rangle $$kde $ P_{i} $ je i-tý řídící bod a $ B_{i}^{n}(t) $ je Bernsteinův polynom n-tého stupně
$$ B_{i}^{n}(t) = \binom{n}{i} t^{i} (1 - t)^{n-i}; \quad i = 0, 1, \dots, n $$Mějme dvě Bézierovy křivky $ Q_{1}(t) $ a $ Q_{2}(t) $
Bernstainovy polynomy 3. stupně:
$$ \begin{align} B_{0}(t) &= (1 - t)^{3} \\ B_{1}(t) &= 3t(1 - t)^{2} \\ B_{2}(t) &= 3t^{2}(1 - t) \\ B_{3}(t) &= t^{3} \\ \end{align} $$Výsledná podoba bázových polynomů:
$$ \begin{align} Q(t) = & ( -t^{3} + 3t^{2} - 3t + 1)P_{0} + \\ & ( 3t^{3} - 6t^{2} + 3t)P_{1} + \\ & (-3t^{3} + 3t^{2})P_{2} \\ & (t^{3})P_{3} \\ \end{align} $$“Adaptive or non-adaptive? That's the question too.”
Parameter $ t $ zvyšujeme o pevně daný krok (např.: $dt = 0.01$). Dostaneme množinu bodů, které spojíme lomenou čárou.
Prvním problémem je určit, jak má být tento krok jemný.
Druhým problémem je, že rovné části jsou často vykreslované zbytečně jemně a zakřivené části nedostatečně jemně.
Při vykreslování pomocí tohoto algoritmu se využívá dělení Bézierovy křivky na dvě části.
Mějme množinu 2D bodů $ P^{T} = [ P_{1}, P{2}, \dots, P_{n} ]$, kde $ P_{i} = [ x_{i}, y_{i} ]$.
Následně můžeme definovat dva samostatné vektory:
$$ \begin{align} x^{T} &= [x_{1}, x_{2}, \dots, x_{n}] \\ y^{T} &= [y_{1}, y_{2}, \dots, y_{n}] \\ \end{align} $$Pro aproximaci množiny bodů $P=[P_{1}, P_{2}, \dots, P_{n}]$ potřebujeme definovat vektor parametrů:
$$ T = [t_{1}, t_{2}, \dots, t_{n}] \quad t \in <0, 1> $$, který mapuje jednotlivé body $P_{i}$ na body Bézierovy křivky. První nástřel mapování může být vytvořen pomocí vzdálenosti boduů $P_{i}$ od počátečního bodu $P_{0}$.
Vzdálenost i-tého bodu od počátku křivky je:
$$ d_{i} = \sum_{j=2}^{i}|P_{j} - P_{j-1}| $$pak můžeme pro každý aproximovaný bod $P_{i}$ spočítat odpovídající parametr $t_{i}$:
$$ t_{i} = \frac{d_{i}}{d_{n}}; \quad t_{0} = 0 $$Pro výpočet aproximace metodou nejmenších čtverců potřebujeme vztah, který nám určuje celkovou chybu:
$$ \begin{align} E(C_{x}) &= \sum_{i=1}^{n}(x_{i} - B(t_{i}))^{2} \\ E(C_{y}) &= \sum_{i=1}^{n}(y_{i} - B(t_{i}))^{2} \\ \end{align} $$ kde $C_{x}$ a $C_{y}$ jsou vektory x/y-ových souřadnic hledaných řídích bodů a $B(t)= T.M.C$Pro parametrizaci bodů $P$ si definujeme matici:
$$ \Pi = \begin{bmatrix} t_{1}^{3} & t_{1}^{2} & t_{1} & 1 \\ t_{2}^{3} & t_{2}^{2} & t_{2} & 1 \\ \vdots & \vdots & \vdots & \vdots \\ t_{n}^{3} & t_{n}^{2} & t_{n} & 1 \\ \end{bmatrix} $$Předhozí vztahy pro výpočet chyby tak můžeme přepsat na:
$$ E(C_{x}) = (x - \Pi M C_{x})^{T} (x - \Pi M C_{x}) $$Pro nalezení minima vztah parciálně zderivujeme podle $C_{x}$ a dáme roven nule:
$$ \frac{\partial E(C_{x})}{\partial C_{x}} = -2 \Pi (x - \Pi M C_{x}) = 0 $$Výsledné vztahy mají tvar:
$$ \begin{align} C_{x} &= M^{-1} (\Pi^{T}\Pi)^{-1}\Pi^{T} x \\ C_{y} &= M^{-1} (\Pi^{T}\Pi)^{-1}\Pi^{T} y \\ \end{align} $$$$ C_{z} = M^{-1} (\Pi^{T}\Pi)^{-1}\Pi^{T} z $$
V počítačové grafice má smysl se zabývat následujícími případy
Implicitní vyjádření přímky: $ y - kx - q = 0$
Parametrické vyjádření Bézierovy křivky:
$$ \begin{align} x &= a_{x}t^{3} + b_{x}t^2 + c_{x}t + d_{x} \\ y &= a_{y}t^{3} + b_{y}t^2 + c_{y}t + d_{y} \end{align} $$Obecné rovnice má tvar:
$$ (a_{y} - ka_{x})t^{3} + (b_{y} - kb{x})t^{2} + (c_{y} - kc_{y})t \\ + (d_{y} - kd_{x} - q) = 0 $$
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(150, 100);
ctx.bezierCurveTo(140,10, 390,10, 390,170);
ctx.lineWidth = 10;
ctx.strokeStyle = 'white';
ctx.lineCap = 'round';
ctx.stroke();
Označována také uniformní racionální B-spline, zkráceně B-spline a je důležitým mezikrokem k pochopení NURBS křivek a NURBS ploch
Je určena 4 řídícími body: $P_{0}$, $P_{1}$, $P_{2}$, $P_{3}$ a vztahem:
$$ Q(t) = \frac{1}{6} \begin{bmatrix} t^{3} & t^{2} & t & 1 \end{bmatrix} \begin{bmatrix} -1 & 3 & -3 & 1 \\ 3 & -6 & 3 & 0 \\ -3 & 0 & 3 & 0 \\ 1 & 4 & 1 & 0 \end{bmatrix} \begin{bmatrix} P_{0} \\ P_{1} \\ P_{2} \\ P_{3} \\ \end{bmatrix} $$Vzniká navazováním Coonsových kubik na sebe. Poslední tři řídící body jednoho segmentu jsou první tři řídíci body následujícího segmentu.
Pokud máme v nějaké části křivky trojnásobný bod (tři body leží na sobě), tak křivka tímto bodem prochází.
Uzlový vektor určuje hodnoty parametru $ t $ v uzlových bodech, přičemž platí $ t_{i+1} - t = c$
“Non Uniform Rational B-spline! What?!”
NURBs křivka je dána následujícím vztahem:
$$ Q(t) = \frac{\sum_{i=0}^{n}w_{i}P_{i}N_{i,k}(t)}{\sum_{i=0}^{n}w_{i}N_{i,k}(t)} $$ kde $ w_{i} $ je váha i-tého bodu a $ N_{i,k}(t) $ jsou normalizované B-spline bázové funkce.Jsou definované následujícím rekurentním vztahem:
$$ N_{i,1} = \begin{cases} 1; &\quad t_{i} \leq t \le t_{i+1} \\ 0; &\quad \text{otherwise} \end{cases} $$ $$ N_{i,k} = \frac{t - t_{i}}{t_{i+k-1} - t_{i}}N_{i,k-1}(t) + \frac{t_{i+k} - t}{t_{i+k} - t_{i+1}}N_{i+1,k-1}(t) $$Předchozí vztah platí pro:
$$ t_{i} \le t_{i+1+k}; 0 \leq i \leq n $$Pokud se ve jmenovateli vyskytuje nula, tak výsledná hodnota je v tomto případě rovna nule.
Především NURBs plochy se používají v CAD/CAM aplikacích.
B-spline nebo NURBs není podporováno v SVG ani v Canvasu. Je nutné použít externí knihovnu.
verbnurbs.com