Hlavní navigace

Parametrické křivky používané v designu i při tvorbě animací

26. 8. 2021
Doba čtení: 44 minut

Sdílet

 Autor: Wikipedia, podle licence: CC-BY-SA
Dnes se budeme znovu zabývat parametrickými křivkami. Nejdříve dokončíme téma Bézierových křivek a s nimi souvisejících Bernsteinových polynomů. Dále se zaměříme na křivky používané při tvorbě animací.

Obsah

1. Bézierovy křivky podrobněji

2. Lineární interpolace

3. Zobecnění lineární interpolace

4. Binomická věta a Bernsteinovy polynomy

5. Bernsteinovy polynomy stupně jedna až pět

6. Ověření základních vlastností Bernsteinových polynomů

7. Součet všech Bernsteinových polynomů stupně jedna až pět

8. Jak je tomu v případě Coonsových kubik?

9. Konstrukce křivky z několika na sebe navazujících segmentů

10. Parametrická a geometrická spojitost Cn a Gn

11. Zajištění spojitosti C1 nebo G1 u Bézierových křivek

12. Poznámka k Coonsovým kubikám a uniformním racionálním B-spline křivkám

13. Křivky používané v animacích

14. Catmul-Romovy spline

15. Bázové polynomy Catmul-Romovy spline

16. Výpočet a vykreslení jednoho segmentu Catmul-Romovy spline

17. Vykreslení celé spline složené z většího množství segmentů

18. Násobné koncové body Catmul-Romovy spline

19. Repositář s demonstračními příklady

20. Odkazy na Internetu

1. Bézierovy křivky podrobněji

Na předchozí část seriálu o křivkách používaných (nejenom) v počítačové grafice dnes navážeme. Minule jsme si totiž – prozatím ovšem bez větších podrobností – představili jeden velmi důležitý typ parametrických křivek. Jedná se o Bézierovy aproximační křivky, jenž se dnes používají například při popisu znaků (TrueType), dále v PostScriptu (a odvozeně taktéž v PDF), ve formátu SVG, taktéž v mnoha kreslicích programech (CorelDraw!, Adobe Illustrator, Inkscape) atd. (ovšem nenechme se unést, protože například v animacích se již používají odlišné křivky, o čemž se dnes záhy taktéž přesvědčíme).

Bézierovy křivky jsou reprezentovány polynomem n-tého stupně, kde n je volitelná celočíselná hodnota (typicky větší než jedna). Z mnoha praktických důvodů (výpočetní složitost, lokalita změn, omezení zákmitů, jednoduchost práce z pohledu uživatele) se ovšem setkáme zejména z Bézierovými křivkami druhého a třetího stupně, tedy s kubikami a kvadrikami. Tyto křivky lze na sebe navázat, popř. je zkombinovat s lineárními segmenty, kruhovými oblouky atd.

Připomeňme si, jak je možné Bézierovy křivky vykreslit. Použijeme přitom jednoduchý, ale současně i naivní algoritmus, který pro hodnoty t v rozsahu 0 až 1 vypočte x-ové a y-ové souřadnice křivky, které následně propojí. Nejprve je uveden příklad zobrazující Bézierovu kvadriku, tedy parametrickou křivku stupně 2, která je z pohledu uživatele specifikována třemi body – dvěma body koncovými (těmi křivka prochází) a jedním řídicím bodem, jímž tato křivka obecně neprochází (jen pokud by všechny body ležely na jedné přímce), ovšem poloha tohoto bodu ovlivňuje tvar křivky:

"""Parametrická křivka: Bézierova kvadrika."""
 
import numpy as np
import matplotlib.pyplot as plt
 
# hodnoty parametru t
t = np.arange(0, 1.05, 0.05)
 
# řídicí body Bézierovy kubiky
xc = (1, 2, 3)
yc = (1, 2.9, 1)
 
# Bernsteinovy polynomy pro Bézierovu kvadriku
B = [(1-t)**2,
     2*t*(1-t),
     t**2]
 
# výpočet bodů ležících na Bézierově kvadrice
x = 0
y = 0
for i in range(0, 3):
    x += xc[i]*B[i]
    y += yc[i]*B[i]
 
# rozměry grafu při uložení: 640x480 pixelů
fig, ax = plt.subplots(1, figsize=(6.4, 4.8))
 
# titulek grafu
fig.suptitle('Bézierova kvadrika', fontsize=15)
 
# určení rozsahů na obou souřadných osách
ax.set_xlim(0, 4)
ax.set_ylim(0, 3)
 
# vrcholy na křivce pospojované úsečkami
ax.plot(x, y, 'g-')
 
# řídicí body Bézierovy kvadriky
ax.plot(xc, yc, 'ro')
 
# uložení grafu do rastrového obrázku
plt.savefig("bezier_quadric.png")
 
# zobrazení grafu
plt.show()

S tímto výsledkem:

Obrázek 1: Bézierova kvadrika vykreslená předchozím demonstračním příkladem.

Prakticky stejným způsobem, ovšem s využitím čtyř bodů (dvou koncových a dvou řídicích) lze vykreslit Bézierovu kubickou křivku (neboli zkráceně kubiku). Zdrojový kód demonstračního příkladu se liší zejména tím, že se používají odlišné Bernsteinovy polynomu:

"""Parametrická křivka: Bézierova kubika."""
 
import numpy as np
import matplotlib.pyplot as plt
 
# hodnoty parametru t
t = np.arange(0, 1.05, 0.05)
 
# řídicí body Bézierovy kubiky
xc = (1, 1, 3, 3)
yc = (1, 2.9, 0.1, 2)
 
# Bernsteinovy polynomy
B = [(1-t)**3,
     3*t*(1-t)**2,
     3*t**2*(1-t),
     t**3]
 
# výpočet bodů ležících na Bézierově kubice
x = 0
y = 0
for i in range(0, 4):
    x += xc[i]*B[i]
    y += yc[i]*B[i]
 
# rozměry grafu při uložení: 640x480 pixelů
fig, ax = plt.subplots(1, figsize=(6.4, 4.8))
 
# titulek grafu
fig.suptitle('Bézierova kubika', fontsize=15)
 
# určení rozsahů na obou souřadných osách
ax.set_xlim(0, 4)
ax.set_ylim(0, 3)
 
# vrcholy na křivce pospojované úsečkami
ax.plot(x, y, 'g-')
 
# řídicí body Bézierovy kubiky
ax.plot(xc, yc, 'ro')
 
# uložení grafu do rastrového obrázku
plt.savefig("bezier_cubic.png")
 
# zobrazení grafu
plt.show()

Nyní by měl výsledek vypadat následovně:

Obrázek 2: Bézierova kubika vykreslená předchozím demonstračním příkladem.

2. Lineární interpolace

Podívejme se ještě jednou podrobněji na to, jak se vlastně provádí výpočet bodů ležících na Bézierově křivce. Konkrétně se jedná o tuto část programového kódu, v níž se počítají souřadnice x,y:

# výpočet bodů ležících na Bézierově kubice
x = 0
y = 0
for i in range(0, 4):
    x += xc[i]*B[i]
    y += yc[i]*B[i]
Poznámka: tento zápis vlastně popisuje operace prováděné nad všemi prvky vektorů hodnot uložených v objektu B[i]. Výsledkem budou dva vektory, první obsahující x-ové souřadnice, druhé souřadnice y-ové. Toto zkrácení zápisu – operací nad všemi prvky vektorů – ovšem nic nemění na dalších úvahách.

Výše uvedený výpočet je jednou z forem lineární kombinace. Ovšem pro demonstrační účely je lepší nepoužít ani Bézierovu kvadriku (stupně 2) či kubiku (stupně 3), ale Bézierovu křivku stupně 1. Jedná se o křivku určenou pouze dvěma body, jimiž tato křivka prochází (což odpovídá i kvadrikám a kubikám, do nichž jsou přidány pouze další řídicí body). Tato parametrická křivka je zcela jistě všem dobře známá – jedná se totiž o běžnou úsečku. I tu lze pochopitelně vyjádřit parametricky a současně i formou lineární kombinace dvou polynomů. Konkrétně se bude jednat o polynomy 1-t a t, kde t leží v rozsahu 0 až 1. Bézierova křivka prvního stupně (tento název ovšem prakticky nikdo pochopitelně nepoužívá) se tedy může vykreslit tímto demonstračním příkladem:

"""Parametrická křivka: lineární interpolace."""
 
import numpy as np
import matplotlib.pyplot as plt
 
# hodnoty parametru t
t = np.arange(0, 1.05, 0.05)
 
# řídicí body
xc = (1, 3)
yc = (1, 2)
 
# Bernsteinovy polynomy pro lineární interpolaci
B = [1 * (1-t),
     1 * t]
 
# výpočet bodů ležících na interpolační křivce
x = 0
y = 0
for i in range(0, 2):
    x += xc[i]*B[i]
    y += yc[i]*B[i]
 
# rozměry grafu při uložení: 640x480 pixelů
fig, ax = plt.subplots(1, figsize=(6.4, 4.8))
 
# titulek grafu
fig.suptitle('Lineární interpolace', fontsize=15)
 
# určení rozsahů na obou souřadných osách
ax.set_xlim(0, 4)
ax.set_ylim(0, 3)
 
# vrcholy na křivce pospojované úsečkami
ax.plot(x, y, 'g-')
 
# řídicí body
ax.plot(xc, yc, 'ro')
 
# uložení grafu do rastrového obrázku
plt.savefig("linear_interpolation.png")
 
# zobrazení grafu
plt.show()

S výsledkem:

Obrázek 3: Bézierova křivka stupně 1 neboli úsečka.

Poznámka: úsečka může mít jakýkoli sklon, tedy i 90°, a to díky tomu, že je použito její parametrické vyjádření.

3. Zobecnění lineární interpolace

Pierre Bézier své křivky odvodil matematicky, na rozdíl od jeho současníka Paula de Casteljau, který nezávisle na Bézierovi (vlastně již před ním) našel geometrickou konstrukci těchto křivek. Ovšem nejdříve se podívejme na způsob odvození, který zvolil Bézier. Ten se snažil zobecnit možnosti lineární interpolace popsané v předchozí kapitole. Ta je založena, jak již víme, na použití dvou polynomů prvního stupně:

f(t) = (1-t)
g(t) = t

Bézier si uvědomil, že (triviálně) platí:

f(t) + g(t) = 1
(1-t) + t = 1

tedy že součet obou funkcí pro libovolné t v daném rozsahu 0 až 1 je vždy roven jedné.

Dále Bézier umocnil obě strany předchozí rovnice:

((1-t) + t)2 = 12

Po úpravě tedy:

(1-t)2 + 2t(1-t) + t2 = 1

Výsledkem jsou tedy nám již známé bázové polynomy křivky druhého stupně (Bézierovy kvadriky):

(1-t)2
2t(1-t)
t2

Což přesně odpovídá vzorcům použitým v demonstračním příkladu uvedeného v úvodní kapitole.

4. Binomická věta a Bernsteinovy polynomy

Naprosto stejným způsobem, tedy umocněním (na třetí, čtvrtou atd.), lze odvodit bázové polynomy i pro Bézierovy křivky vyšších stupňů, tedy především pro Bézierovu kubiku. Ovšem ve skutečnosti si můžeme pomoci jednoduchou zkratkou – binomickou větou, díky níž dokážeme jednoduše spočítat ((1-t) + t)n. Jednotlivé členy rozvoje se nazývají Bernsteinovy bázové polynomy. Každý takový polynom má tvar:

bv,n(t) = Cvn tv (1-t)n-v

kde Cvn je binomický koeficient „n nad v“. Tento koeficient lze získat z Pascalova trojúhelníku:

            1
          1   1
        1   2   1
      1   3   3   1
    1   4   6   4   1
  1   5  10  10   5   1
1   6  15  20  15   6   1

Uveďme si příklady Bernsteinových bázových polynomů.

Lineární případ n=1 je triviální (druhý řádek v trojúhelníku):

1 × (1-t)
1 × t

Bázové polynomy druhého stupně pro n=2 (třetí řádek v trojúhelníku):

1 × (1-t)2
2 × t × (1-t)
1 × t2

Bázové polynomy třetího stupně pro n=3:

1 × (1-t)3
3 × t × (1-t)2
3 × t2 × (1-t)
1 × t3

atd. atd.

Poznámka: čistě náhodou se tedy setkáváme se dvěma jmény začínajícími na „B“ – Bézier a Bernstein. Aby se to pletlo, používáme i B-spliny, jejichž jméno je ovšem odvozeno od slova „basis“.

5. Bernsteinovy polynomy stupně jedna až pět

Nyní již víme, jakým způsobem je možné vypočítat Bernsteinovy bázové polynomy libovolného stupně. Ukažme si tedy jejich průběh graficky. Začneme (prakticky triviálním) lineárním případem:

"""Bázové polynomy pro lineární interpolaci."""
 
import numpy as np
import matplotlib.pyplot as plt
 
# hodnoty parametru t
t = np.arange(0, 1.05, 0.02)
 
# Bernsteinovy polynomy pro lineární interpolaci
B = [1 * (1-t),
     1 * t]
 
# rozměry grafu při uložení: 640x480 pixelů
fig, ax = plt.subplots(1, figsize=(6.4, 4.8))
 
# titulek grafu
fig.suptitle('Bázové polynomy', fontsize=15)
 
# určení rozsahů na obou souřadných osách
ax.set_xlim(0, 1)
ax.set_ylim(0, 1)
 
# bázové polynomy
ax.plot(t, B[0], 'r-', label='b0,1')
ax.plot(t, B[1], 'g-', label='b1,1')
 
# zobrazení legendy
ax.legend()
 
# uložení grafu do rastrového obrázku
plt.savefig("linear_basis.png")
 
# zobrazení grafu
plt.show()

S výsledkem:

Obrázek 4: Bernsteinovy bázové polynomy stupně jedna.

Bernsteinovy bázové polynomy stupně dva použité pro Bézierovy kvadriky:

"""Bázové polynomy Bézierovy kvadriky."""
 
import numpy as np
import matplotlib.pyplot as plt
 
# hodnoty parametru t
t = np.arange(0, 1.05, 0.02)
 
# Bernsteinovy polynomy pro Bézierovu kvadriku
B = [1 * (1-t)**2,
     2 * t * (1-t),
     1 * t**2]
 
# rozměry grafu při uložení: 640x480 pixelů
fig, ax = plt.subplots(1, figsize=(6.4, 4.8))
 
# titulek grafu
fig.suptitle('Bázové polynomy', fontsize=15)
 
# určení rozsahů na obou souřadných osách
ax.set_xlim(0, 1)
ax.set_ylim(0, 1)
 
# bázové polynomy
ax.plot(t, B[0], 'r-', label='b0,2')
ax.plot(t, B[1], 'g-', label='b1,2')
ax.plot(t, B[2], 'b-', label='b2,2')
 
# zobrazení legendy
ax.legend()
 
# uložení grafu do rastrového obrázku
plt.savefig("bezier_quadric_basis_.png")
 
# zobrazení grafu
plt.show()

S výsledkem:

Obrázek 5: Bernsteinovy bázové polynomy stupně dva.

Bernsteinovy bázové polynomy stupně tři použité pro Bézierovy kubiky:

"""Bázové polynomy Bézierovy kubiky."""
 
import numpy as np
import matplotlib.pyplot as plt
 
# hodnoty parametru t
t = np.arange(0, 1.05, 0.02)
 
# Bernsteinovy polynomy
B = [1 * (1-t)**3,
     3 * t * (1-t)**2,
     3 * t**2 * (1-t),
     1 * t**3]
 
# rozměry grafu při uložení: 640x480 pixelů
fig, ax = plt.subplots(1, figsize=(6.4, 4.8))
 
# titulek grafu
fig.suptitle('Bázové polynomy', fontsize=15)
 
# určení rozsahů na obou souřadných osách
ax.set_xlim(0, 1)
ax.set_ylim(0, 1)
 
# bázové polynomy
ax.plot(t, B[0], 'r-', label='b0,3')
ax.plot(t, B[1], 'g-', label='b1,3')
ax.plot(t, B[2], 'b-', label='b2,3')
ax.plot(t, B[3], 'k-', label='b3,3')
 
# zobrazení legendy
ax.legend()
 
# uložení grafu do rastrového obrázku
plt.savefig("bezier_cubic_basis.png")
 
# zobrazení grafu
plt.show()

Obrázek 6: Bernsteinovy bázové polynomy stupně tři.

Ovšem můžeme jít i dále a zobrazit si polynomy stupně čtyři:

"""Bázové polynomy Bézierovy kvartiky."""
 
import numpy as np
import matplotlib.pyplot as plt
 
# hodnoty parametru t
t = np.arange(0, 1.05, 0.02)
 
# Bernsteinovy polynomy pro Bézierovu kvartiku
B = [1 * (1-t)**4,
     4 * t * (1-t)**3,
     6 * t**2 * (1-t)**2,
     4 * t**3 * (1-t),
     1 * t**4]
 
# rozměry grafu při uložení: 640x480 pixelů
fig, ax = plt.subplots(1, figsize=(6.4, 4.8))
 
# titulek grafu
fig.suptitle('Bázové polynomy', fontsize=15)
 
# určení rozsahů na obou souřadných osách
ax.set_xlim(0, 1)
ax.set_ylim(0, 1)
 
# bázové polynomy
ax.plot(t, B[0], 'r-', label='b0,4')
ax.plot(t, B[1], 'g-', label='b1,4')
ax.plot(t, B[2], 'b-', label='b2,4')
ax.plot(t, B[3], 'k-', label='b3,4')
ax.plot(t, B[4], 'm-', label='b4,4')
 
# zobrazení legendy
ax.legend()
 
# uložení grafu do rastrového obrázku
plt.savefig("bezier_quartic_basis_.png")
 
# zobrazení grafu
plt.show()

Obrázek 7: Bernsteinovy bázové polynomy stupně čtyři.

Pro úplnost bázové polynomy stupně pět, i když ty již v grafice většinou neuvidíme:

"""Bázové polynomy Bézierovy křivky stupně 5."""
 
import numpy as np
import matplotlib.pyplot as plt
 
# hodnoty parametru t
t = np.arange(0, 1.05, 0.02)
 
# Bernsteinovy polynomy pro Bézierovu křivku stupně 5
B = [1 * (1-t)**5,
     5 * t * (1-t)**4,
     10 * t**2 * (1-t)**3,
     10 * t**3 * (1-t)**2,
     5 * t**4 * (1-t),
     1 * t**5]
 
# rozměry grafu při uložení: 640x480 pixelů
fig, ax = plt.subplots(1, figsize=(6.4, 4.8))
 
# titulek grafu
fig.suptitle('Bázové polynomy', fontsize=15)
 
# určení rozsahů na obou souřadných osách
ax.set_xlim(0, 1)
ax.set_ylim(0, 1)
 
# bázové polynomy
ax.plot(t, B[0], 'r-', label='b0,5')
ax.plot(t, B[1], 'g-', label='b1,5')
ax.plot(t, B[2], 'b-', label='b2,5')
ax.plot(t, B[3], 'k-', label='b3,5')
ax.plot(t, B[4], 'm-', label='b4,5')
ax.plot(t, B[5], 'y-', label='b5,5')
 
# zobrazení legendy
ax.legend()
 
# uložení grafu do rastrového obrázku
plt.savefig("bezier_quintic_basis_.png")
 
# zobrazení grafu
plt.show()

Obrázek 8: Bernsteinovy bázové polynomy stupně pět.

6. Ověření základních vlastností Bernsteinových polynomů

Bernsteinovy polynomy, které jsou využity jako bázové polynomy Bézierových křivek, splňují několik podmínek, které jsou při tvorbě křivek a jejich využívání důležité. Jedná se o tyto podmínky:

  1. Pro t=0 má první polynom hodnotu 1 a ostatní polynomy hodnotu 0. Z geometrického hlediska to znamená, že je zaručeno, že křivka prochází prvním koncovým bodem (protože ostatní členy při výpočtu jsou vynulovány).
  2. Podobně pro t=1 mají všechny polynomy, až na polynom poslední, nulovou hodnotu. Tudíž křivka prochází i svým posledním koncovým bodem.
  3. Součet hodnot všech Bernsteinových polynomů pro libovolnét v rozsahu od 0 do 1 je vždy roven jedné, současně je hodnota každého Bernsteinova polynomu vždy nezáporná. Z geometrického hlediska to znamená, že se celá křivka nachází v konvexním obalu svých řídicích bodů (tedy v mnohoúhelníku, který získáme propojením řídicích bodů tak, že je mnohoúhelník konvexní).
  4. Současně můžeme z grafů zobrazených v předchozí kapitole zjistit, jak hodnoty Bernsteinových polynomů postupně (podle jejich indexu) rostou se změnou t a posléze zase klesají k nule. Výjimkou je první a poslední polynom, který jen klesá, resp. jen roste. Geometricky to znamená, že křivka se postupně přibližuje k jednotlivým řídicím bodům.

7. Součet všech Bernsteinových polynomů stupně jedna až pět

Základní a pro mnoho aplikací důležitá vlastnost Bernsteinových polynomů – jejich součet je pro libovolné t z definičního oboru vždy roven jedné – sice nemusí být z grafů přímo patrná, ale můžeme si ji ověřit numericky, a to pro polynomy různého stupně. V tabulkách, které jsou vypočteny a zobrazeny dále uvedenými demonstračními příklady, by měly hodnoty v posledních sloupcích být vždy jedničkové nebo alespoň v rámci přesnosti výpočtů velmi blízké jedničce.

Polynom prvního stupně:

"""Bázové polynomy lineární interpolace."""
 
import numpy as np
import pandas as pd
from tabulate import tabulate
 
# hodnoty parametru t
t = np.arange(0, 1.01, 0.10)
 
# Bernsteinovy polynomy pro lineární interpolaci
B = [1 * (1-t),
     1 * t]
 
# vytvoření datového rámce pro uložení hodnot Bernsteinových polynomů
df = pd.DataFrame(index=t, columns=["b0,1", "b1,1", "sum"])
 
# inicializace jednotlivých sloupců datového rámce
df["b0,1"] = B[0]
df["b1,1"] = B[1]
 
# součet hodnot Bernsteinových polynomů
df["sum"] = B[0]+B[1]
 
# vytištění obsahu datového rámce
print(tabulate(df, headers = 'keys', tablefmt = 'psql'))

Výsledky:

+-----+--------+--------+-------+
|     |   b0,1 |   b1,1 |   sum |
|-----+--------+--------+-------|
| 0   |    1   |    0   |     1 |
| 0.1 |    0.9 |    0.1 |     1 |
| 0.2 |    0.8 |    0.2 |     1 |
| 0.3 |    0.7 |    0.3 |     1 |
| 0.4 |    0.6 |    0.4 |     1 |
| 0.5 |    0.5 |    0.5 |     1 |
| 0.6 |    0.4 |    0.6 |     1 |
| 0.7 |    0.3 |    0.7 |     1 |
| 0.8 |    0.2 |    0.8 |     1 |
| 0.9 |    0.1 |    0.9 |     1 |
| 1   |    0   |    1   |     1 |
+-----+--------+--------+-------+

Polynom druhého stupně:

"""Bázové polynomy Bézierovy kvadriky."""
 
import numpy as np
import pandas as pd
from tabulate import tabulate
 
# hodnoty parametru t
t = np.arange(0, 1.01, 0.10)
 
# Bernsteinovy polynomy pro Bézierovu kvadriku
B = [1 * (1-t)**2,
     2 * t * (1-t),
     1 * t**2]
 
# vytvoření datového rámce pro uložení hodnot Bernsteinových polynomů
df = pd.DataFrame(index=t, columns=["b0,2", "b1,2", "b2,2", "sum"])
 
# inicializace jednotlivých sloupců datového rámce
df["b0,2"] = B[0]
df["b1,2"] = B[1]
df["b2,2"] = B[2]
 
# součet hodnot Bernsteinových polynomů
df["sum"] = B[0]+B[1]+B[2]
 
# vytištění obsahu datového rámce
print(tabulate(df, headers = 'keys', tablefmt = 'psql'))

Výsledky:

+-----+--------+--------+--------+-------+
|     |   b0,2 |   b1,2 |   b2,2 |   sum |
|-----+--------+--------+--------+-------|
| 0   |   1    |   0    |   0    |     1 |
| 0.1 |   0.81 |   0.18 |   0.01 |     1 |
| 0.2 |   0.64 |   0.32 |   0.04 |     1 |
| 0.3 |   0.49 |   0.42 |   0.09 |     1 |
| 0.4 |   0.36 |   0.48 |   0.16 |     1 |
| 0.5 |   0.25 |   0.5  |   0.25 |     1 |
| 0.6 |   0.16 |   0.48 |   0.36 |     1 |
| 0.7 |   0.09 |   0.42 |   0.49 |     1 |
| 0.8 |   0.04 |   0.32 |   0.64 |     1 |
| 0.9 |   0.01 |   0.18 |   0.81 |     1 |
| 1   |   0    |   0    |   1    |     1 |
+-----+--------+--------+--------+-------+

Polynom třetího stupně:

"""Bázové polynomy Bézierovy kubiky."""
 
import numpy as np
import pandas as pd
from tabulate import tabulate
 
# hodnoty parametru t
t = np.arange(0, 1.01, 0.10)
 
# Bernsteinovy polynomy pro Bézierovu kubiku
B = [1 * (1-t)**3,
     3 * t * (1-t)**2,
     3 * t**2 * (1-t),
     1 * t**3]
 
# vytvoření datového rámce pro uložení hodnot Bernsteinových polynomů
df = pd.DataFrame(index=t, columns=["b0,3", "b1,3", "b2,3", "b3,3", "sum"])
 
# inicializace jednotlivých sloupců datového rámce
df["b0,3"] = B[0]
df["b1,3"] = B[1]
df["b2,3"] = B[2]
df["b3,3"] = B[3]
 
# součet hodnot Bernsteinových polynomů
df["sum"] = B[0]+B[1]+B[2]+B[3]
 
# vytištění obsahu datového rámce
print(tabulate(df, headers = 'keys', tablefmt = 'psql'))

Výsledky:

+-----+--------+--------+--------+--------+-------+
|     |   b0,3 |   b1,3 |   b2,3 |   b3,3 |   sum |
|-----+--------+--------+--------+--------+-------|
| 0   |  1     |  0     |  0     |  0     |     1 |
| 0.1 |  0.729 |  0.243 |  0.027 |  0.001 |     1 |
| 0.2 |  0.512 |  0.384 |  0.096 |  0.008 |     1 |
| 0.3 |  0.343 |  0.441 |  0.189 |  0.027 |     1 |
| 0.4 |  0.216 |  0.432 |  0.288 |  0.064 |     1 |
| 0.5 |  0.125 |  0.375 |  0.375 |  0.125 |     1 |
| 0.6 |  0.064 |  0.288 |  0.432 |  0.216 |     1 |
| 0.7 |  0.027 |  0.189 |  0.441 |  0.343 |     1 |
| 0.8 |  0.008 |  0.096 |  0.384 |  0.512 |     1 |
| 0.9 |  0.001 |  0.027 |  0.243 |  0.729 |     1 |
| 1   |  0     |  0     |  0     |  1     |     1 |
+-----+--------+--------+--------+--------+-------+

Polynom čtvrtého stupně:

"""Bázové polynomy Bézierovy kvartiky."""
 
import numpy as np
import pandas as pd
from tabulate import tabulate
 
# hodnoty parametru t
t = np.arange(0, 1.01, 0.10)
 
# Bernsteinovy polynomy pro Bézierovu kvartiku
B = [1 * (1-t)**4,
     4 * t * (1-t)**3,
     6 * t**2 * (1-t)**2,
     4 * t**3 * (1-t),
     1 * t**4]
 
# vytvoření datového rámce pro uložení hodnot Bernsteinových polynomů
df = pd.DataFrame(index=t, columns=["b0,4", "b1,4", "b2,4", "b3,4", "b4,4", "sum"])
 
# inicializace jednotlivých sloupců datového rámce
df["b0,4"] = B[0]
df["b1,4"] = B[1]
df["b2,4"] = B[2]
df["b3,4"] = B[3]
df["b4,4"] = B[4]
 
# součet hodnot Bernsteinových polynomů
df["sum"] = B[0]+B[1]+B[2]+B[3]+B[4]
 
# vytištění obsahu datového rámce
print(tabulate(df, headers = 'keys', tablefmt = 'psql'))

Výsledky:

+-----+--------+--------+--------+--------+--------+-------+
|     |   b0,4 |   b1,4 |   b2,4 |   b3,4 |   b4,4 |   sum |
|-----+--------+--------+--------+--------+--------+-------|
| 0   | 1      | 0      | 0      | 0      | 0      |     1 |
| 0.1 | 0.6561 | 0.2916 | 0.0486 | 0.0036 | 0.0001 |     1 |
| 0.2 | 0.4096 | 0.4096 | 0.1536 | 0.0256 | 0.0016 |     1 |
| 0.3 | 0.2401 | 0.4116 | 0.2646 | 0.0756 | 0.0081 |     1 |
| 0.4 | 0.1296 | 0.3456 | 0.3456 | 0.1536 | 0.0256 |     1 |
| 0.5 | 0.0625 | 0.25   | 0.375  | 0.25   | 0.0625 |     1 |
| 0.6 | 0.0256 | 0.1536 | 0.3456 | 0.3456 | 0.1296 |     1 |
| 0.7 | 0.0081 | 0.0756 | 0.2646 | 0.4116 | 0.2401 |     1 |
| 0.8 | 0.0016 | 0.0256 | 0.1536 | 0.4096 | 0.4096 |     1 |
| 0.9 | 0.0001 | 0.0036 | 0.0486 | 0.2916 | 0.6561 |     1 |
| 1   | 0      | 0      | 0      | 0      | 1      |     1 |
+-----+--------+--------+--------+--------+--------+-------+

A konečně polynom pátého stupně:

"""Bázové polynomy Bézierovy křivky stupně 5."""
 
import numpy as np
import pandas as pd
from tabulate import tabulate
 
# hodnoty parametru t
t = np.arange(0, 1.01, 0.10)
 
# Bernsteinovy polynomy pro Bézierovu křivku stupně 5
B = [1 * (1-t)**5,
     5 * t * (1-t)**4,
     10 * t**2 * (1-t)**3,
     10 * t**3 * (1-t)**2,
     5 * t**4 * (1-t),
     1 * t**5]
 
# vytvoření datového rámce pro uložení hodnot Bernsteinových polynomů
df = pd.DataFrame(index=t, columns=["b0,5", "b1,5", "b2,5", "b3,5", "b4,5", "b5,5", "sum"])
 
# inicializace jednotlivých sloupců datového rámce
df["b0,5"] = B[0]
df["b1,5"] = B[1]
df["b2,5"] = B[2]
df["b3,5"] = B[3]
df["b4,5"] = B[4]
df["b5,5"] = B[5]
 
# součet hodnot Bernsteinových polynomů
df["sum"] = B[0]+B[1]+B[2]+B[3]+B[4]+B[5]
 
# vytištění obsahu datového rámce
print(tabulate(df, headers = 'keys', tablefmt = 'psql'))

Výsledky:

+-----+---------+---------+--------+--------+---------+---------+-------+
|     |    b0,5 |    b1,5 |   b2,5 |   b3,5 |    b4,5 |    b5,5 |   sum |
|-----+---------+---------+--------+--------+---------+---------+-------|
| 0   | 1       | 0       | 0      | 0      | 0       | 0       |     1 |
| 0.1 | 0.59049 | 0.32805 | 0.0729 | 0.0081 | 0.00045 | 1e-05   |     1 |
| 0.2 | 0.32768 | 0.4096  | 0.2048 | 0.0512 | 0.0064  | 0.00032 |     1 |
| 0.3 | 0.16807 | 0.36015 | 0.3087 | 0.1323 | 0.02835 | 0.00243 |     1 |
| 0.4 | 0.07776 | 0.2592  | 0.3456 | 0.2304 | 0.0768  | 0.01024 |     1 |
| 0.5 | 0.03125 | 0.15625 | 0.3125 | 0.3125 | 0.15625 | 0.03125 |     1 |
| 0.6 | 0.01024 | 0.0768  | 0.2304 | 0.3456 | 0.2592  | 0.07776 |     1 |
| 0.7 | 0.00243 | 0.02835 | 0.1323 | 0.3087 | 0.36015 | 0.16807 |     1 |
| 0.8 | 0.00032 | 0.0064  | 0.0512 | 0.2048 | 0.4096  | 0.32768 |     1 |
| 0.9 | 1e-05   | 0.00045 | 0.0081 | 0.0729 | 0.32805 | 0.59049 |     1 |
| 1   | 0       | 0       | 0      | 0      | 0       | 1       |     1 |
+-----+---------+---------+--------+--------+---------+---------+-------+

8. Jak je tomu v případě Coonsových kubik?

V předchozím článku jsme se mj. seznámili i s takzvanými Coonsovými kubikami, resp. s Coonsovými oblouky (Coons arc), které tvoří základ klasických (neracionálních uniformních) B-spline křivek. Tyto kubiky se počítají a vykreslují naprosto stejným způsobem jako kubiky Bézierovy, až na jednu „maličkost“ – jejich bázové polynomy jsou odlišné od Bernsteinovým polynomů. To má za následek nejenom odlišný tvar křivky, ale i to, že B-spline neprochází svými koncovými body. Tuto vlastnost můžeme vyčíst z grafu průběhu hodnot bázových polynomů, protože zde není splněna podmínka, že pro t=0 má první polynom hodnotu 1 a ostatní polynomy hodnotu 0 a pro t=1 mají všechny polynomy, až na polynom poslední, hodnotu nulovou. Křivka tedy začíná i končí v bodech, jejichž souřadnice jsou ovlivněny dalšími řídicími body:

Obrázek 9: Bázové polynomy Coonsovy kubiky.

Průběhy jsou tedy dosti odlišné od Bernsteinových polynomů, které jsme mohli vidět v předchozích kapitolách.

Předchozí graf byl vykreslen tímto skriptem:

"""Bázové polynomy Coonsovy kubiky."""
 
import numpy as np
import matplotlib.pyplot as plt
 
# hodnoty parametru t
t = np.arange(0, 1.05, 0.02)
 
# Coonsovy polynomy
C = [(1-t)**3,
     3*t**3 - 6*t**2 + 4,
     -3*t**3 + 3*t**2 + 3*t + 1,
     t**3]
 
# rozměry grafu při uložení: 640x480 pixelů
fig, ax = plt.subplots(1, figsize=(6.4, 4.8))
 
# titulek grafu
fig.suptitle('Bázové polynomy', fontsize=15)
 
# určení rozsahů na obou souřadných osách
ax.set_xlim(0, 1)
ax.set_ylim(0, 4)
 
# bázové polynomy
ax.plot(t, C[0]/6, 'r-')
ax.plot(t, C[1]/6, 'g-')
ax.plot(t, C[2]/6, 'b-')
ax.plot(t, C[3]/6, 'k-')
 
# uložení grafu do rastrového obrázku
plt.savefig("coons_basis.png")
 
# zobrazení grafu
plt.show()

9. Konstrukce křivky z několika na sebe navazujících segmentů

Prozatím jsme se zabývali (a nutno dodat, že i nadále budeme zabývat) parametrickými křivkami vytvořenými postupně z několika na sebe navazujících segmentů, přičemž každý segment je popsán polynomem nízkého stupně (typicky stupně tři nebo čtyři, jedná se tedy o kvadriku nebo kubiku). Velmi důležité body v takovém případě vznikají v místě napojení jednotlivých segmentů. Samozřejmě je možné segmenty napojit libovolným způsobem (takže vznikne „roh“ nebo dokonce mezera mezi segmenty), ale většinou je požadováno hladké napojení. Přitom slovo „hladké“ má podle kontextu matematický nebo geometrický význam. Rozlišujeme parametrickou spojitost třídy Cn a taktéž geometrickou spojitost Gn. Různé aplikace, v nichž se křivky používají, přitom mají různé požadavky, takže například nelze říci, že nám všude budou vyhovovat pouze křivky se spojitostí G1. A naopak použití křivek se spojitostí C2 může být naopak značně limitující.

10. Parametrická a geometrická spojitost Cn a Gn

Dva segmenty jsou spojitě navázány (neboli mají spojitost třídy C0) v případě, že je koncový bod prvního segmentu počátečním bodem segmentu druhého – tudíž jsou dovoleny i výše zmíněné „rohy“. Dva segmenty mají spojitost C1 v případě, že je tečný vektor v koncovém bodě segmentu Q1, roven tečnému vektoru v jeho počátečním bodě navazujícího segmentu Q2. Analogicky rovnost vektoru první a druhé derivace je požadována pro spojité navázání třídy C2. Teoreticky je možné požadovat popř. i zajistit totožnost třetí i vyšší derivace, ovšem konkrétně u polynomů nižších stupňů to již postrádá praktický význam (derivace budou nulové).

Čím vyšší spojitost je požadována, tím delší „dobu“ (ve smyslu parametru t) se oba segmenty k sobě přimykají a tím pádem je křivka tužší při snaze o změnu jejího tvaru. Ze spojitosti C0 dále plyne, že bod se pohybuje po spojité dráze, ale v uzlu může měnit skokem směr pohybu, rychlost i zrychlení, což může vadit při animacích. Směr pohybu se nemůže měnit skokem při spojitosti C1 (ovšem může se skokově změnit rychlost) a zrychlení zůstává nezměněné až při spojitosti C2 (což je ideální právě pro animační křivky).

V počítačové grafice se mnohdy setkáme spíše s termínem geometrické spojitosti Gn. Opticky zaručuje G1 spojitost dvou segmentů křivky s prakticky stejnou vizuální hladkostí, jako je tomu u parametrické spojitosti C1. Důležitá je ovšem praktická implementace, tj. programový kód, který spojitost G1 nebo C1 zajišťuje. Z tohoto hlediska bývá daleko snazší zaručit spojitost G1 (dtto při požadavku na spojitost G2 resp. C2), protože případné tečné vektory nemusí být totožné, ale „pouze“ musí mít stejný směr, nikoli už velikost (jsou tedy kolineární).

Jak již bylo napsáno v předchozím odstavci, je jednodušší dosažení geometrické spojitosti G1, kde je nutné, mimo totožnosti posledního řídicího bodu první křivky a prvního bodu druhé křivky, dodržet alespoň kolinearitu tečného vektoru na konci první křivky a na začátku křivky druhé (vektory tedy musí mít stejný směr, ale mohou mít různou velikost, jinými slovy, tyto vektory jsou na sobě lineárně závislé). Geometrickou spojitost je snazší dodržet i z toho důvodu, že volnost uživatele při zadávání řídicích bodů je větší než v případě parametrické spojitosti, zejména při použití Bézierových kvadratických a (méně kriticky) kubických křivek – viz následující kapitolu.

11. Zajištění spojitosti C1 nebo G1 u Bézierových křivek

Podívejme se nyní, jak je tomu v případě Bézierových křivek. Pokud na sebe mají jednotlivé segmenty křivky hladce navazovat, tj. pokud mají mít parametrickou spojitost alespoň C1, musí být poslední bod první křivky totožný s prvním bodem křivky druhé: Pn=P'0 – tím je zajištěno napojení obou křivek, tj. spojitost C0. Také tečný vektor na konci první křivky musí být stejný jako tečný vektor na začátku druhé (navazující) křivky. Na dalším obrázku jsou zobrazeny dvě Bézierovy kvadratické křivky, které jsou hladce navázány se spojitostí C1. Vzhledem k tomu, že se jedná o kvadratické křivky, je každá křivka specifikována počátečním bodem, jedním řídicím bodem a koncovým bodem. Podobným způsobem jsou konstruovány obrysy písmen v TrueType fontech.

Obrázek 10: Hladké navázání dvou Bézierových kvadratických křivek.

Poznámka: povšimněte si, jak omezující je v tomto případě požadavek na spojitost C1 – uživatel nemůže posunout řídicí bod jednoho segmentu, aniž by ovlivnil oba segmenty okolní (což se kaskádovitě rozšíří po celé křivce). Proto se také typicky v tomto případě zadávají jen koncové body dalších segmentů, protože řídicí body se dopočítají automaticky.

12. Poznámka k Coonsovým kubikám a uniformním racionálním B-spline křivkám

Minule jsme se zmínili i o Coonsových kubikách, které se taktéž někdy nazývají Coonsovy oblouky. Tyto křivky začínají a končí v antitěžišti trojúhelníků vytvořených z trojice řídicích bodů – jedná se tedy o čisté aproximační křivky. Způsob vykreslení se až na rozdílné bázové polynomy neliší od Bézierových kubik:

"""Parametrická křivka: Coonsova kubika."""
 
import numpy as np
import matplotlib.pyplot as plt
 
# hodnoty parametru t
t = np.arange(0, 1.05, 0.05)
 
# řídicí body Coonsovy kubiky
xc = (1, 1, 3, 3)
yc = (1, 2, 2, 0.5)
 
# Coonsovy polynomy
C = [(1-t)**3,
     3*t**3 - 6*t**2 + 4,
     -3*t**3 + 3*t**2 + 3*t + 1,
     t**3]
 
# výpočet bodů ležících na Coonsově kubice
x = 0
y = 0
for i in range(0, 4):
    x += xc[i]*C[i]
    y += yc[i]*C[i]
 
# konečná úprava sumy
x /= 6
y /= 6
 
# rozměry grafu při uložení: 640x480 pixelů
fig, ax = plt.subplots(1, figsize=(6.4, 4.8))
 
# titulek grafu
fig.suptitle('Coonsova kubika', fontsize=15)
 
# určení rozsahů na obou souřadných osách
ax.set_xlim(0, 4)
ax.set_ylim(0, 3)
 
# vrcholy na křivce pospojované úsečkami
ax.plot(x, y, 'g-')
 
# řídicí body Coonsovy kubiky
ax.plot(xc, yc, 'ro')
 
# uložení grafu do rastrového obrázku
plt.savefig("coons.png")
 
# zobrazení grafu
plt.show()

Obrázek 11: Coonsova kubika pro čtyři řídicí body.

Tyto kubiky lze snadno navázat takovým způsobem, že se vždy tři řídicí body opakují (resp. jsou společné pro dva na sebe navazující segmenty). Ovšem co je důležité – po vyjádření prvních a druhých derivací polynomů lze zjistit, že je zachována spojitost C2, a to bez jakýchkoli dalších podmínek:

"""Parametrická křivka: B-spline složená z Coonsových oblouků."""
 
import numpy as np
import matplotlib.pyplot as plt
 
# hodnoty parametru t
t = np.arange(0, 1.05, 0.05)
 
# řídicí body B-spline
xc = (1, 1, 2, 2.5, 3, 2)
yc = (1, 2, 2, 0.1, 2.9, 2.9)
 
# Coonsovy polynomy
C = [(1-t)**3,
     3*t**3 - 6*t**2 + 4,
     -3*t**3 + 3*t**2 + 3*t + 1,
     t**3]
 
 
def draw_coons_arc(xc, yc, ax, style):
        # výpočet bodů ležících na Coonsově kubice
    x = 0
    y = 0
    for i in range(0, 4):
        x += xc[i]*C[i]
        y += yc[i]*C[i]
 
        # konečná úprava sumy
    x /= 6
    y /= 6
 
        # vrcholy na křivce pospojované úsečkami
    ax.plot(x, y, style)
 
 
# rozměry grafu při uložení: 640x480 pixelů
fig, ax = plt.subplots(1, figsize=(6.4, 4.8))
 
# titulek grafu
fig.suptitle('B-spline', fontsize=15)
 
# určení rozsahů na obou souřadných osách
ax.set_xlim(0, 4)
ax.set_ylim(0, 3)
 
# řídicí body B-spline
ax.plot(xc, yc, 'k--', alpha=0.5)
ax.plot(xc, yc, 'ro')
 
# první oblouk
draw_coons_arc(xc[0:4], yc[0:4], ax, "r-")
 
# druhý oblouk
draw_coons_arc(xc[1:5], yc[1:5], ax, "b-")
 
# třetí oblouk
draw_coons_arc(xc[2:6], yc[2:6], ax, "g-")
 
# uložení grafu do rastrového obrázku
plt.savefig("B-spline_1.png")
 
# zobrazení grafu
plt.show()

Obrázek 12: B-spline vytvořená z Coonsových oblouků.

13. Křivky používané v animacích

Konečně se dostáváme k další důležité oblasti počítačové grafiky, v níž jsou využívány parametrické křivky, konkrétně křivky definované s využitím polynomů nižších řádů. Jedná se o oblast animací, konkrétně animací založených na takzvaných klíčových snímcích neboli keyframes, mezi nimiž jsou automaticky dopočítány parametry mezisnímků, kterých může být libovolný počet (například třicet mezisnímků mezi každým klíčovým snímkem). Takový typ animací lze v případě potřeby vytvářet velmi precizním způsobem, protože pozice kamery a její orientaci, stejně jako další parametry vykreslované scény, je možné nastavit pomocí interaktivních metod a/nebo dialogů a poté pouze zvolit, jak se má dopočítat přechod mezi jednotlivými snímky.

14. Catmul-Romovy spline

Při vytváření a úpravách animací je vhodné vědět, jak vlastně interně pracuje algoritmus výpočtu mezisnímků, které jsou vkládány mezi jednotlivé klíčové snímky. Nejprve si musíme uvědomit, jak je interně celá animace reprezentována. Zjednodušeně řečeno se jedná o sadu neměnných parametrů a dále o sadu parametrů, které se v čase (tj. mezi jednotlivými snímky) mohou měnit (třeba pozice animované postavičky). Sadou neměnných parametrů se nemusíme dále zabývat, protože ty jsou pro všechny snímky shodné. U proměnných parametrů se většinou jedná o reálná čísla, ovšem v některých případech (pozice a orientace kamery) se taktéž může jednat o vektory různé délky. Tyto vektory se opět rozkládají na reálná čísla. Hodnoty všech parametrů jsou předem známé v jednotlivých klíčových snímcích, takže by se mohlo zdát, že postačuje mezihodnoty dopočítat tím nejprimitivnějším možným způsobem – lineární interpolací, kterou již velmi dobře známe.

To sice skutečně možné je, protože výsledkem bude animace, ve které nebude docházet ke skokové změně hodnot jednotlivých parametrů, ovšem bude docházet ke změně rychlosti změny hodnot (což je zrychlení). Výhodnější je tedy proložení hodnot nějakou vhodnou křivkou, která mj. zajistí, aby nedocházelo ani ke skokovému rozdílu v rychlosti změny parametrů (takzvaná parametrická spojitost C1, viz též předchozí kapitoly). V počítačové grafice, především právě při tvorbě animací (pohyb kamery), se k tomuto účelu používají křivky pojmenované podle svých tvůrců Edwina Catmulla a Raphaela Roma Catmull–Rom spline. Alternativní křivkou je Akima spline (Akimova spline křivka), která je opět pojmenovaná podle svého tvůrce (Hiroshi Akima).

Poznámka: názorný popis teorie stojící za Catmull-Romovými spline křivkami naleznete na videu: https://www.youtube.com/wat­ch?v=yRGXJL9r9bs.

Catmul-Romovy spline lze, podobně jako B-spline, vyjádřit sekvencí na sebe navazujících segmentů, přičemž každý segment je (opět) reprezentován kubikou. Ovšem zatímco B-spline jsou aproximačními křivkami, které neprochází svými řídicími body, Catmul-Romovy spline jsou interpolační křivky, tedy prochází všemi svými řídicími body. To je ostatně logické, protože řídicí body odpovídají hodnotám v klíčových snímcích a tyto snímky potřebujeme v animaci zobrazit přesně tak, jak je grafik vytvořil. Ovšem současně to – při požadavku na parametrickou spojitost – znamená, že tyto křivky obecně neleží v konvexním obalu vytvořeného z řídicích bodů, což může v některých případech způsobovat problémy.

15. Bázové polynomy Catmul-Romovy spline

Podívejme se nyní na to, jak vypadají bázové polynomy Catmul-Romovy spline. Vizualizaci provedeme tímto skriptem, ze kterého je patrné, jaké bázové polynomy jsou použity:

"""Bázové polynomy Catmul-Romovy spline."""
 
import numpy as np
import matplotlib.pyplot as plt
 
# hodnoty parametru t
t = np.arange(0, 1.05, 0.02)
 
# koeficient Catmul-Romovy spline
tau = 0.5
 
# bázové polynomy
Q = [-tau*t + 2*tau*t**2 - tau*t**3,
     1+(tau-3)*t**2+(2-tau)*t**3,
     tau*t + (3-2*tau)*t**2 + (tau-2)*t**3,
     -tau*t**2+tau*t**3]
 
# rozměry grafu při uložení: 640x480 pixelů
fig, ax = plt.subplots(1, figsize=(6.4, 4.8))
 
# titulek grafu
fig.suptitle('Bázové polynomy', fontsize=15)
 
# určení rozsahů na obou souřadných osách
ax.set_xlim(0, 1)
ax.set_ylim(-0.25, 1)
 
# bázové polynomy
ax.plot(t, Q[0], 'r-')
ax.plot(t, Q[1], 'g-')
ax.plot(t, Q[2], 'b-')
ax.plot(t, Q[3], 'k-')
 
# uložení grafu do rastrového obrázku
plt.savefig("catmul-rom_basis.png")
 
# zobrazení grafu
plt.show()

Výsledek:

Obrázek 13: Bázové polynomy Catmul-Romovy spline.

Vyjádřit můžeme i součet hodnot všech bázových polynomů:

"""Bázové polynomy Catmul-Romovy spline."""
 
import numpy as np
import pandas as pd
from tabulate import tabulate
 
# hodnoty parametru t
t = np.arange(0, 1.01, 0.10)
 
# koeficient Catmul-Romovy spline
tau = 0.5
 
# bázové polynomy
Q = [-tau*t + 2*tau*t**2 - tau*t**3,
     1+(tau-3)*t**2+(2-tau)*t**3,
     tau*t + (3-2*tau)*t**2 + (tau-2)*t**3,
     -tau*t**2+tau*t**3]
 
# vytvoření datového rámce pro uložení hodnot polynomů
df = pd.DataFrame(index=t, columns=["q0", "q1", "q2", "q3", "sum"])
 
# inicializace jednotlivých sloupců datového rámce
df["q0"] = Q[0]
df["q1"] = Q[1]
df["q2"] = Q[2]
df["q3"] = Q[3]
 
# součet hodnot polynomů
df["sum"] = Q[0]+Q[1]+Q[2]+Q[3]
 
# vytištění obsahu datového rámce
print(tabulate(df, headers = 'keys', tablefmt = 'psql'))

Součet hodnot všech polynomů v daném místě je roven jedné, ovšem některé hodnoty konkrétních polynomů jsou záporné:

+-----+---------+--------+--------+---------+-------+
|     |      q0 |     q1 |     q2 |      q3 |   sum |
|-----+---------+--------+--------+---------+-------|
| 0   |  0      | 1      | 0      |  0      |     1 |
| 0.1 | -0.0405 | 0.9765 | 0.0685 | -0.0045 |     1 |
| 0.2 | -0.064  | 0.912  | 0.168  | -0.016  |     1 |
| 0.3 | -0.0735 | 0.8155 | 0.2895 | -0.0315 |     1 |
| 0.4 | -0.072  | 0.696  | 0.424  | -0.048  |     1 |
| 0.5 | -0.0625 | 0.5625 | 0.5625 | -0.0625 |     1 |
| 0.6 | -0.048  | 0.424  | 0.696  | -0.072  |     1 |
| 0.7 | -0.0315 | 0.2895 | 0.8155 | -0.0735 |     1 |
| 0.8 | -0.016  | 0.168  | 0.912  | -0.064  |     1 |
| 0.9 | -0.0045 | 0.0685 | 0.9765 | -0.0405 |     1 |
| 1   |  0      | 0      | 1      |  0      |     1 |
+-----+---------+--------+--------+---------+-------+

16. Výpočet a vykreslení jednoho segmentu Catmul-Romovy spline

Jeden segment Catmul-Romovy spline se vykresluje stejně, jako segment Bézierovy křivky nebo Coonsova oblouku. Liší se pouze výpočet bodů na křivce na základě bázových polynomů:

"""Parametrická křivka: Catmul-Romova spline."""
 
import numpy as np
import matplotlib.pyplot as plt
 
# hodnoty parametru t
t = np.arange(0, 1.05, 0.05)
 
# řídicí body
xc = (1, 1, 3, 3)
yc = (1, 2.9, 0.1, 2)
 
# koeficient Catmul-Romovy spline
tau = 0.5
 
# bázové polynomy
Q = [-tau*t + 2*tau*t**2 - tau*t**3,
     1+(tau-3)*t**2+(2-tau)*t**3,
     tau*t + (3-2*tau)*t**2 + (tau-2)*t**3,
     -tau*t**2+tau*t**3]
 
# výpočet bodů ležících na spline
x = 0
y = 0
for i in range(0, 4):
    x += xc[i]*Q[i]
    y += yc[i]*Q[i]
 
# rozměry grafu při uložení: 640x480 pixelů
fig, ax = plt.subplots(1, figsize=(6.4, 4.8))
 
# titulek grafu
fig.suptitle('Catmul-Romova spline', fontsize=15)
 
# určení rozsahů na obou souřadných osách
ax.set_xlim(0, 4)
ax.set_ylim(0, 3)
 
# vrcholy na křivce pospojované úsečkami
ax.plot(x, y, 'g-')
 
# řídicí body kubiky
ax.plot(xc, yc, 'ro')
 
# uložení grafu do rastrového obrázku
plt.savefig("catmul-rom_cubic.png")
 
# zobrazení grafu
plt.show()

Obrázek 14: Catmul-Romova spline složená z jednoho segmentu.

17. Vykreslení celé spline složené z většího množství segmentů

Z na sebe navazujících segmentů Catmul-Romovy kubiky lze vytvořit celou spline definovanou n řídicími body. Postup je snadný – vždy čtyři po sobě jdoucí body vytváří jeden segment; celkově je nutné vykreslit n-3 takových oblouků. Přitom je zaručeno, že tyto oblouky na sebe hladce navazují, což je ostatně ukázáno i v dalším (dnes již předposledním posledním) demonstračním příkladu:

"""Parametrická křivka: Catmul-Romova spline."""
 
import numpy as np
import matplotlib.pyplot as plt
 
# hodnoty parametru t
t = np.arange(0, 1.05, 0.05)
 
# řídicí body B-spline
xc = (1, 1, 2, 2.5, 3, 2)
yc = (1, 2, 2, 0.1, 2.9, 2.9)
 
# koeficient Catmul-Romovy spline
tau = 0.5
 
# bázové polynomy
Q = [-tau*t + 2*tau*t**2 - tau*t**3,
     1+(tau-3)*t**2+(2-tau)*t**3,
     tau*t + (3-2*tau)*t**2 + (tau-2)*t**3,
     -tau*t**2+tau*t**3]
 
 
def draw_catmul_rom_arc(xc, yc, ax, style):
    x = 0
    y = 0
    for i in range(0, 4):
        x += xc[i]*Q[i]
        y += yc[i]*Q[i]
 
    # vrcholy na křivce pospojované úsečkami
    ax.plot(x, y, style)
 
 
# rozměry grafu při uložení: 640x480 pixelů
fig, ax = plt.subplots(1, figsize=(6.4, 4.8))
 
# titulek grafu
fig.suptitle('Catmul-Rom spline', fontsize=15)
 
# určení rozsahů na obou souřadných osách
ax.set_xlim(0, 4)
ax.set_ylim(0, 4)
 
# řídicí body B-spline
ax.plot(xc, yc, 'k--', alpha=0.5)
ax.plot(xc, yc, 'ro')
 
# první oblouk
draw_catmul_rom_arc(xc[0:4], yc[0:4], ax, "r-")
 
# druhý oblouk
draw_catmul_rom_arc(xc[1:5], yc[1:5], ax, "b-")
 
# třetí oblouk
draw_catmul_rom_arc(xc[2:6], yc[2:6], ax, "g-")
 
# uložení grafu do rastrového obrázku
plt.savefig("catmul-rom_spline_A.png")
 
# zobrazení grafu
plt.show()

Obrázek 15: Catmul-Romova spline složená z několika segmentů.

18. Násobné koncové body Catmul-Romovy spline

Při práci s Catmul-Rom spline se, podobně jako u B-spline, často používají takzvané násobné řídící body, což jsou sousední řídící body, které jsou umístěny na stejné souřadnici v ploše či v prostoru. S využitím násobných řídících bodů lze na křivce vytvářet zlomy či úseky, které se k řídícím bodům více přimykají (tím se částečně nahrazují váhy řídících bodů). Také lze zajistit (což je důležitější), aby křivka procházela svými krajními body:

Podnikové It nový

"""Parametrická křivka: Catmul-Romova spline s násobnými body."""
 
import numpy as np
import matplotlib.pyplot as plt
 
# hodnoty parametru t
t = np.arange(0, 1.05, 0.05)
 
# řídicí body B-spline
xc = (1, 1, 2, 2.5, 3, 2)
yc = (1, 2, 2, 0.1, 2.9, 2.9)
 
# koeficient Catmul-Romovy spline
tau = 0.5
 
# bázové polynomy
Q = [-tau*t + 2*tau*t**2 - tau*t**3,
     1+(tau-3)*t**2+(2-tau)*t**3,
     tau*t + (3-2*tau)*t**2 + (tau-2)*t**3,
     -tau*t**2+tau*t**3]
 
 
def draw_catmul_rom_arc(xc, yc, ax, style):
    x = 0
    y = 0
    for i in range(0, 4):
        x += xc[i]*Q[i]
        y += yc[i]*Q[i]
 
    # vrcholy na křivce pospojované úsečkami
    ax.plot(x, y, style)
 
 
# rozměry grafu při uložení: 640x480 pixelů
fig, ax = plt.subplots(1, figsize=(6.4, 4.8))
 
# titulek grafu
fig.suptitle('Catmul-Rom spline', fontsize=15)
 
# určení rozsahů na obou souřadných osách
ax.set_xlim(0, 4)
ax.set_ylim(0, 4)
 
# řídicí body B-spline
ax.plot(xc, yc, 'k--', alpha=0.5)
ax.plot(xc, yc, 'ro')
 
# oblouk s násobnými body
draw_catmul_rom_arc((xc[0], xc[0], xc[1], xc[2]),
               (yc[0], yc[0], yc[1], yc[2]), ax, "k-")
 
# první oblouk
draw_catmul_rom_arc(xc[0:4], yc[0:4], ax, "r-")
 
# druhý oblouk
draw_catmul_rom_arc(xc[1:5], yc[1:5], ax, "b-")
 
# třetí oblouk
draw_catmul_rom_arc(xc[2:6], yc[2:6], ax, "g-")
 
# oblouk s násobnými body
draw_catmul_rom_arc((xc[3], xc[4], xc[5], xc[5]),
               (yc[3], yc[4], yc[5], yc[5]), ax, "k-")
 
# uložení grafu do rastrového obrázku
plt.savefig("catmul-rom_spline_B.png")
 
# zobrazení grafu
plt.show()

Obrázek 16: Catmul-Romova spline složená z několika segmentů, která prochází svými krajními body.

19. Repositář s demonstračními příklady

Všechny předminule, minule i dnes popisované demonstrační příklady určené pro Python 3 a knihovnu Matplotlib byly uloženy do Git repositáře, který je dostupný na adrese https://github.com/tisnik/pre­sentations. Příklady si můžete v případě potřeby stáhnout i jednotlivě bez nutnosti klonovat celý (dnes již poměrně rozsáhlý) repositář:

# Příklad Popis Adresa
1 line.py úsečka https://github.com/tisnik/pre­sentations/blob/master/cur­ves/line.py
2 parabola.py parabola https://github.com/tisnik/pre­sentations/blob/master/cur­ves/parabola.py
3 hyperbola.py hyperbola https://github.com/tisnik/pre­sentations/blob/master/cur­ves/hyperbola.py
4 ellipse_parametric.py parametricky zadaná elipsa https://github.com/tisnik/pre­sentations/blob/master/cur­ves/ellipse_parametric.py
5 ellipse_general.py obecná elipsa https://github.com/tisnik/pre­sentations/blob/master/cur­ves/ellipse_general.py
6 circle_parametric.py parametricky zadaná kružnice https://github.com/tisnik/pre­sentations/blob/master/cur­ves/circle_parametric.py
7 circle_polar.py polární souřadnice při kreslení kružnice https://github.com/tisnik/pre­sentations/blob/master/cur­ves/circle_polar.py
8 archimedes_spiral.py Archimédova spirála https://github.com/tisnik/pre­sentations/blob/master/cur­ves/archimedes_spiral.py
9 fermats_spiral.py Fermatova spirála https://github.com/tisnik/pre­sentations/blob/master/cur­ves/fermats_spiral.py
10 hyperbolic_spiral.py Hyperbolická spirála https://github.com/tisnik/pre­sentations/blob/master/cur­ves/hyperbolic_spiral.py
11 logarithmic_spiral.py Logaritmická spirála https://github.com/tisnik/pre­sentations/blob/master/cur­ves/logarithmic_spiral.py
12 parabola_catenary1.py parabola vs. řetězovka https://github.com/tisnik/pre­sentations/blob/master/cur­ves/parabola_catenary1.py
13 parabola_catenary2.py parabola vs. řetězovka https://github.com/tisnik/pre­sentations/blob/master/cur­ves/parabola_catenary2.py
14 cardioid.py srdcovka https://github.com/tisnik/pre­sentations/blob/master/cur­ves/cardioid.py
15 catenary.py řetězovka https://github.com/tisnik/pre­sentations/blob/master/cur­ves/catenary.py
17 fresnel.py Fresnelův integrál https://github.com/tisnik/pre­sentations/blob/master/cur­ves/fresnel.py
19 lissajous.py Lissajousův obrazec https://github.com/tisnik/pre­sentations/blob/master/cur­ves/lissajous.py
       
20 superellipse1.py superelipsa https://github.com/tisnik/pre­sentations/blob/master/cur­ves/superellipse1.py
21 superellipse2.py superelipsa, ovšem s odlišnými parametry https://github.com/tisnik/pre­sentations/blob/master/cur­ves/superellipse2.py
22 cycloid.py cykloida https://github.com/tisnik/pre­sentations/blob/master/cur­ves/cycloid.py
23 epicycloid1.py epicykloida https://github.com/tisnik/pre­sentations/blob/master/cur­ves/epicycloid1.py
24 epicycloid2.py epicykloida, ovšem s odlišnými parametry https://github.com/tisnik/pre­sentations/blob/master/cur­ves/epicycloid2.py
25 hypocycloid1.py hypocykloida https://github.com/tisnik/pre­sentations/blob/master/cur­ves/hypocycloid1.py
26 hypocycloid2.py hypocykloida, ovšem s odlišnými parametry https://github.com/tisnik/pre­sentations/blob/master/cur­ves/hypocycloid2.py
27 hypotrochoid1.py hypotrochoida https://github.com/tisnik/pre­sentations/blob/master/cur­ves/hypotrochoid1.py
28 hypotrochoid2.py hypotrochoida, ovšem s odlišnými parametry https://github.com/tisnik/pre­sentations/blob/master/cur­ves/hypotrochoid2.py
29 hypotrochoid3.py hypotrochoida, ovšem s odlišnými parametry https://github.com/tisnik/pre­sentations/blob/master/cur­ves/hypotrochoid3.py
30 implicit/implicit.py křivka zadaná implicitní funkcí https://github.com/tisnik/pre­sentations/blob/master/cur­ves/implicit/implicit.py
       
31 3d_plot/parabola1A.py funkce pro parabolu ve 3D https://github.com/tisnik/pre­sentations/blob/master/cur­ves/3d_plot/parabola1A.py
32 3d_plot/parabola1B.py funkce pro parabolu ve 3D + kontury https://github.com/tisnik/pre­sentations/blob/master/cur­ves/3d_plot/parabola1B.py
33 3d_plot/parabola2A.py funkce pro parabolu ve 3D https://github.com/tisnik/pre­sentations/blob/master/cur­ves/3d_plot/parabola2A.py
34 3d_plot/parabola2B.py funkce pro parabolu ve 3D + kontury https://github.com/tisnik/pre­sentations/blob/master/cur­ves/3d_plot/parabola2B.py
35 3d_plot/hyperbolaA.py funkce pro hyperbolu ve 3D https://github.com/tisnik/pre­sentations/blob/master/cur­ves/3d_plot/hyperbolaA.py
36 3d_plot/hyperbolaB.py funkce pro hyperbolu ve 3D + kontury https://github.com/tisnik/pre­sentations/blob/master/cur­ves/3d_plot/hyperbolaB.py
37 3d_plot/sin_cos1.py goniometrická funkce ve 3D https://github.com/tisnik/pre­sentations/blob/master/cur­ves/3d_plot/sin_cos1.py
38 3d_plot/sin_cos2.py goniometrická funkce ve 3D https://github.com/tisnik/pre­sentations/blob/master/cur­ves/3d_plot/sin_cos2.py
39 anim/cassini_anim.py animace změny koeficientů Cassiniho oválu https://github.com/tisnik/pre­sentations/blob/master/cur­ves/anim/cassini_anim.py
40 anim/spiric_anim.py animace změny koeficientů průsečíku roviny s toroidem https://github.com/tisnik/pre­sentations/blob/master/cur­ves/anim/spiric_anim.py
41 implicit/cassini1.py Cassiniho ovál https://github.com/tisnik/pre­sentations/blob/master/cur­ves/implicit/cassini1.py
42 implicit/cassini2.py Cassiniho ovál https://github.com/tisnik/pre­sentations/blob/master/cur­ves/implicit/cassini2.py
43 implicit/cassini3.py Cassiniho ovál https://github.com/tisnik/pre­sentations/blob/master/cur­ves/implicit/cassini3.py
44 implicit/cassini4.py Cassiniho ovál https://github.com/tisnik/pre­sentations/blob/master/cur­ves/implicit/cassini4.py
45 implicit/circle1.py kružnice specifikovaná implicitní funkcí https://github.com/tisnik/pre­sentations/blob/master/cur­ves/implicit/circle1.py
46 implicit/circle2.py kružnice specifikovaná implicitní funkcí https://github.com/tisnik/pre­sentations/blob/master/cur­ves/implicit/circle2.py
47 implicit/ellipse1.py elipsa specifikovaná implicitní funkcí https://github.com/tisnik/pre­sentations/blob/master/cur­ves/implicit/ellipse1.py
48 implicit/ellipse2.py elipsa specifikovaná implicitní funkcí https://github.com/tisnik/pre­sentations/blob/master/cur­ves/implicit/ellipse2.py
49 implicit/ellipse3.py elipsa specifikovaná implicitní funkcí https://github.com/tisnik/pre­sentations/blob/master/cur­ves/implicit/ellipse3.py
50 implicit/elliptic1.py eliptická křivka https://github.com/tisnik/pre­sentations/blob/master/cur­ves/implicit/elliptic1.py
51 implicit/elliptic2.py mřížka několika eliptických křivek https://github.com/tisnik/pre­sentations/blob/master/cur­ves/implicit/elliptic2.py
52 implicit/flower.py křivka připomínající květ https://github.com/tisnik/pre­sentations/blob/master/cur­ves/implicit/flower.py
53 implicit/hyperbola1.py hyperbola specifikovaná implicitní funkcí https://github.com/tisnik/pre­sentations/blob/master/cur­ves/implicit/hyperbola1.py
54 implicit/hyperbola2.py hyperbola specifikovaná implicitní funkcí https://github.com/tisnik/pre­sentations/blob/master/cur­ves/implicit/hyperbola2.py
55 implicit/line1.py přímka specifikovaná implicitní funkcí https://github.com/tisnik/pre­sentations/blob/master/cur­ves/implicit/line1.py
56 implicit/line2.py přímka specifikovaná implicitní funkcí https://github.com/tisnik/pre­sentations/blob/master/cur­ves/implicit/line2.py
57 implicit/parabola1.py parabola specifikovaná implicitní funkcí https://github.com/tisnik/pre­sentations/blob/master/cur­ves/implicit/parabola1.py
58 implicit/parabola2.py parabola specifikovaná implicitní funkcí https://github.com/tisnik/pre­sentations/blob/master/cur­ves/implicit/parabola2.py
59 implicit/sin_cos1.py implicitní funkce obsahující goniometrické funkce https://github.com/tisnik/pre­sentations/blob/master/cur­ves/implicit/sin_cos1.py
60 implicit/sin_cos2.py implicitní funkce obsahující goniometrické funkce https://github.com/tisnik/pre­sentations/blob/master/cur­ves/implicit/sin_cos2.py
61 implicit/spiric1.py řez toroidu plochou https://github.com/tisnik/pre­sentations/blob/master/cur­ves/implicit/spiric1.py
62 implicit/spiric2.py řez toroidu plochou https://github.com/tisnik/pre­sentations/blob/master/cur­ves/implicit/spiric2.py
63 implicit/spiric3.py řez toroidu plochou https://github.com/tisnik/pre­sentations/blob/master/cur­ves/implicit/spiric3.py
       
64 interpolation/lagrange_in­terpolation1.py interpolace Lagrangeovým polynomem https://github.com/tisnik/pre­sentations/blob/master/cur­ves/interpolation/lagrange_in­terpolation1.py
65 interpolation/lagrange_in­terpolation2.py interpolace Lagrangeovým polynomem https://github.com/tisnik/pre­sentations/blob/master/cur­ves/interpolation/lagrange_in­terpolation2.py
66 interpolation/lagrange_poly1.py konstrukce Lagrangeova polynomu https://github.com/tisnik/pre­sentations/blob/master/cur­ves/interpolation/lagrange_po­ly1.py
67 interpolation/lagrange_poly2.py konstrukce Lagrangeova polynomu https://github.com/tisnik/pre­sentations/blob/master/cur­ves/interpolation/lagrange_po­ly2.py
68 approximation/linear_regression1.py lineární regrese https://github.com/tisnik/pre­sentations/blob/master/cur­ves/approximation/linear_re­gression1.py
68 approximation/linear_regression2.py lineární regrese https://github.com/tisnik/pre­sentations/blob/master/cur­ves/approximation/linear_re­gression2.py
69 approximation/linear_regression3.py lineární regrese https://github.com/tisnik/pre­sentations/blob/master/cur­ves/approximation/linear_re­gression3.py
70 approximation/poly_regression1.py aproximace polynomem https://github.com/tisnik/pre­sentations/blob/master/cur­ves/approximation/poly_re­gression1.py
71 approximation/poly_regression2.py aproximace polynomem https://github.com/tisnik/pre­sentations/blob/master/cur­ves/approximation/poly_re­gression2.py
72 approximation/random_data_linear.py náhodná data pro lineární regresi https://github.com/tisnik/pre­sentations/blob/master/cur­ves/approximation/random_da­ta_linear.py
73 approximation/random_data_poly.py náhodná data pro aproximaci polynomem https://github.com/tisnik/pre­sentations/blob/master/cur­ves/approximation/random_da­ta_poly.py
74 approximation/taylor_sin1.py aproximace funkce sin Taylorovým rozvojem https://github.com/tisnik/pre­sentations/blob/master/cur­ves/approximation/taylor_sin.py
75 approximation/taylor_sin2.py aproximace funkce sin Taylorovým rozvojem https://github.com/tisnik/pre­sentations/blob/master/cur­ves/approximation/taylor_sin.py
76 approximation/taylor_sin5.py aproximace funkce sin Taylorovým rozvojem https://github.com/tisnik/pre­sentations/blob/master/cur­ves/approximation/taylor_sin.py
77 approximation/taylor_sin9.py aproximace funkce sin Taylorovým rozvojem https://github.com/tisnik/pre­sentations/blob/master/cur­ves/approximation/taylor_sin.py
78 approximation/taylor_sin_x.py aproximace funkce sin Taylorovým rozvojem https://github.com/tisnik/pre­sentations/blob/master/cur­ves/approximation/taylor_sin_x­.py
79 parametric/circle.py parametricky zadaná kružnice https://github.com/tisnik/pre­sentations/blob/master/cur­ves/parametric/circle.py
80 parametric/Bezier_basis.py Bernsteinovy polynomy https://github.com/tisnik/pre­sentations/blob/master/cur­ves/parametric/Bezier_basis­.py
81 parametric/Bezier_cubic.py Bézierova kubika https://github.com/tisnik/pre­sentations/blob/master/cur­ves/parametric/Bezier_cubic­.py
82 parametric/Bezier_kvadric.py Bézierova kvadrika https://github.com/tisnik/pre­sentations/blob/master/cur­ves/parametric/Bezier_kva­dric.py
83 parametric/B-spline-1.py B-spline křivka https://github.com/tisnik/pre­sentations/blob/master/cur­ves/parametric/B-spline-1.py
84 parametric/B-spline-2.py B-spline křivka s násobnými body https://github.com/tisnik/pre­sentations/blob/master/cur­ves/parametric/B-spline-2.py
85 parametric/Coons_basis.py Coonsovy bázové polynomy https://github.com/tisnik/pre­sentations/blob/master/cur­ves/parametric/Coons_basis­.py
86 parametric/Coons.py Coonsova křivka https://github.com/tisnik/pre­sentations/blob/master/cur­ves/parametric/Coons.py
       
87 parametric/Bezier_cubic_basis.py bázové vektory Bézierovy kubiky https://github.com/tisnik/pre­sentations/blob/master/cur­ves/parametric/Bezier_cubic_ba­sis.py
88 parametric/Bezier_cubic_basis_sum.py součet bázových vektorů Bézierovy kubiky https://github.com/tisnik/pre­sentations/blob/master/cur­ves/parametric/Bezier_cubic_ba­sis_sum.py
89 parametric/Bezier_quadric_basis.py bázové vektory Bézierovy kvadriky https://github.com/tisnik/pre­sentations/blob/master/cur­ves/parametric/Bezier_qua­dric_basis.py
90 parametric/Bezier_quadric_basis_sum.py součet bázových vektorů Bézierovy kvadriky https://github.com/tisnik/pre­sentations/blob/master/cur­ves/parametric/Bezier_qua­dric_basis_sum.py
91 parametric/Bezier_quartic_basis.py bázové vektory Bézierovy quartiky https://github.com/tisnik/pre­sentations/blob/master/cur­ves/parametric/Bezier_quar­tic_basis.py
92 parametric/Bezier_quartic_basis_sum.py součet bázových vektorů Bézierovy kvartiky https://github.com/tisnik/pre­sentations/blob/master/cur­ves/parametric/Bezier_quar­tic_basis_sum.py
93 parametric/Bezier_quintic_basis.py bázové vektory Bézierovy quintiky https://github.com/tisnik/pre­sentations/blob/master/cur­ves/parametric/Bezier_quin­tic_basis.py
94 parametric/Bezier_quintic_basis_sum.py součet bázových vektorů Bézierovy quintiky https://github.com/tisnik/pre­sentations/blob/master/cur­ves/parametric/Bezier_quin­tic_basis_sum.py
95 parametric/Catmul-Rom_basis.py bázové vektory Catmul-Romovy spline https://github.com/tisnik/pre­sentations/blob/master/cur­ves/parametric/Catmul-Rom_basis.py
96 parametric/Catmul-Rom_basis_sum.py součet bázových vektorů Catmul-Romovy spline https://github.com/tisnik/pre­sentations/blob/master/cur­ves/parametric/Catmul-Rom_basis_sum.py
97 parametric/Catmul-Rom_cubic.py Catmul-Romova kubika https://github.com/tisnik/pre­sentations/blob/master/cur­ves/parametric/Catmul-Rom_cubic.py
98 parametric/Catmul-Rom_spline_A.py Catmul-Romova spline https://github.com/tisnik/pre­sentations/blob/master/cur­ves/parametric/Catmul-Rom_spline_A.py
99 parametric/Catmul-Rom_spline_B.py Catmul-Romova spline procházející koncovými body https://github.com/tisnik/pre­sentations/blob/master/cur­ves/parametric/Catmul-Rom_spline_B.py
100 parametric/Coons_basis2.py bázové vektory Coonsovy kubiky https://github.com/tisnik/pre­sentations/blob/master/cur­ves/parametric/Coons_basis.py
101 parametric/Coons_basis_sum.py součet bázových vektorů Coonsovy kubiky https://github.com/tisnik/pre­sentations/blob/master/cur­ves/parametric/Coons_basis_sum­.py
102 parametric/linear_basis.py bázové vektory lineární interpolace https://github.com/tisnik/pre­sentations/blob/master/cur­ves/parametric/linear_basis­.py
103 parametric/linear_basis_sum.py součet bázových vektorů lineární interpolace https://github.com/tisnik/pre­sentations/blob/master/cur­ves/parametric/linear_basis_sum­.py
104 parametric/linear_interpolation.py zobrazení lineární interpolace https://github.com/tisnik/pre­sentations/blob/master/cur­ves/parametric/linear_inter­polation.py

20. Odkazy na Internetu

  1. Famous Curves Index
    https://mathshistory.st-andrews.ac.uk/Curves/
  2. Curve (Wikipedia)
    https://en.wikipedia.org/wiki/Curve
  3. Mathematical curves
    https://www.2dcurves.com/index.html
  4. Curves (Wolfram MathWorld)
    https://mathworld.wolfram­.com/topics/Curves.html
  5. Smooth Curve (Wolfram MathWorld)
    https://mathworld.wolfram­.com/SmoothCurve.html
  6. Spirals (Wolfram MathWorld)
    https://mathworld.wolfram­.com/topics/Spirals.html
  7. An Interactive Introduction to Splines
    https://ibiblio.org/e-notes/Splines/Intro.htm
  8. Parabola
    https://www.2dcurves.com/co­nicsection/conicsectionp.html
  9. Hyperbola
    https://www.2dcurves.com/co­nicsection/conicsectionh.html
  10. Dioklova kisoida
    https://cs.wikipedia.org/wi­ki/Dioklova_kisoida
  11. Archimédova spirála
    https://cs.wikipedia.org/wi­ki/Archim%C3%A9dova_spir%C3%A1la
  12. Conchoid (mathematics)
    https://en.wikipedia.org/wi­ki/Conchoid_(mathematics)
  13. Algebraic curve
    https://en.wikipedia.org/wi­ki/Algebraic_curve
  14. Transcendental curve
    https://en.wikipedia.org/wi­ki/Transcendental_curve
  15. Spiral
    https://en.wikipedia.org/wiki/Spiral
  16. List of spirals
    https://en.wikipedia.org/wi­ki/List_of_spirals
  17. Hyperbolická spirála
    https://cs.wikipedia.org/wi­ki/Hyperbolick%C3%A1_spir%C3%A1la
  18. Hyperbolic Spiral
    https://mathworld.wolfram­.com/HyperbolicSpiral.html
  19. Lituus (mathematics)
    https://en.wikipedia.org/wi­ki/Lituus_(mathematics)
  20. Spiral of Spirals Fractals 2 with Python Turtle (Source Code)
    https://pythonturtle.academy/spiral-of-spirals-fractals-2-with-python-turtle-source-code/
  21. Cornu Spiral
    http://hyperphysics.gsu.e­du/hbase/phyopt/cornu.html
  22. Spiral
    https://www.2dcurves.com/spi­ral/spiral.html
  23. Algebraic Curves
    https://mathworld.wolfram­.com/topics/AlgebraicCurves­.html
  24. Elliptic Curves
    https://mathworld.wolfram­.com/topics/EllipticCurves­.html
  25. Eukleidovská konstrukce
    https://cs.wikipedia.org/wi­ki/Eukleidovsk%C3%A1_konstruk­ce
  26. Euclidean Constructions
    http://www.cs.cas.cz/portal/Al­goMath/Geometry/PlaneGeome­try/GeometricConstruction­s/EuclideanConstructions.htm
  27. Kvadratura kruhu
    https://cs.wikipedia.org/wi­ki/Kvadratura_kruhu
  28. Trisekce úhlu
    https://cs.wikipedia.org/wi­ki/Trisekce_%C3%BAhlu
  29. Straightedge and compass construction
    https://en.wikipedia.org/wi­ki/Straightedge_and_compas­s_construction
  30. C.a.R.
    http://car.rene-grothmann.de/doc_en/index.html
  31. CaRMetal (Wikipedia)
    https://en.wikipedia.org/wiki/C.a.R.
  32. CaRMetal (Španělsky a Francouzsky)
    http://carmetal.org/index.php/fr/
  33. CaRMetal (Wikipedia)
    https://en.wikipedia.org/wi­ki/CaRMetal
  34. Regular Polygon
    http://mathforum.org/dr.mat­h/faq/formulas/faq.regpoly­.html
  35. Geometric Construction with the Compass Alone
    http://www.cut-the-knot.org/do_you_know/compass.shtml
  36. Kvadratura kruhu (Wikipedie)
    https://cs.wikipedia.org/wi­ki/Kvadratura_kruhu
  37. Compass equivalence theorem
    https://en.wikipedia.org/wi­ki/Compass_equivalence_the­orem
  38. Curves we (mostly) don't learn in high school (and applications)
    https://www.youtube.com/wat­ch?v=3izFMB91K_Q
  39. Can You Really Derive Conic Formulae from a Cone? – Menaechmus' Constructions
    https://www.maa.org/press/pe­riodicals/convergence/can-you-really-derive-conic-formulae-from-a-cone-menaechmus-constructions
  40. Apollonius of Perga
    https://en.wikipedia.org/wi­ki/Apollonius_of_Perga
  41. Catenary arch
    https://en.wikipedia.org/wi­ki/Catenary_arch
  42. Parabolic arch
    https://en.wikipedia.org/wi­ki/Parabolic_arch
  43. Wattova křivka
    https://www.geogebra.org/m/gNh4bW9r
  44. Model stegosaura byl získán na stránce
    http://www.turbosquid.com/HTMLCli­ent/FullPreview/Index.cfm/ID/171071/Ac­tion/FullPreview
  45. Obrázek nohy dinosaura byl získán na adrese
    http://perso.wanadoo.fr/ri­masson/3d/leg.htm
  46. Spirograph
    https://en.wikipedia.org/wi­ki/Spirograph
  47. Epicykloida
    https://cs.wikipedia.org/wi­ki/Epicykloida
  48. Hypocykloida
    https://cs.wikipedia.org/wi­ki/Hypocykloida
  49. Hypotrochoida
    https://cs.wikipedia.org/wi­ki/Hypotrochoida
  50. Superelipsoidy a kvadriky v POV-Rayi
    https://www.root.cz/clanky/su­perelipsoidy-a-kvadriky-v-pov-rayi/
  51. Fifty Famous Curves, Lots of Calculus Questions, And a Few Answers
    https://elepa.files.wordpres­s.com/2013/11/fifty-famous-curves.pdf
  52. Barr, A.H.: Superquadrics and Angle Preserving Transformations,
    IEEE Computer Graphics and Applications, January 1981
  53. Bourke Paul: Quadrics,
    July 1996
  54. Bourke Paul: Superellipse and Superellipsoid,
    January 1990
  55. Faux, I.D. a Pratt, M.J.: Computational Geometry for Design and Manufacture,
    Ellis Horwood Ltd., Wiley & Sons, 1979
  56. Wallace A.: Differential Topology,
    Benjamin/Cummings Co., Reading, Massachussetts, USA, 1968
  57. Glossary of Bridge Terminology
    http://sdrc.lib.uiowa.edu/en­g/bridges/WaddellGlossary/Glos­sC.htm
  58. Brachistochrona
    https://cs.wikipedia.org/wi­ki/Brachistochrona
  59. Missions: Cassini
    https://solarsystem.nasa.gov/mis­sions/cassini/overview/
  60. Giovanni Domenico Cassini
    https://en.wikipedia.org/wi­ki/Giovanni_Domenico_Cassi­ni
  61. Cassini Ovals
    https://mathworld.wolfram­.com/CassiniOvals.html
  62. Geocentrismus
    https://cs.wikipedia.org/wi­ki/Geocentrismus
  63. Who was Giovanni Cassini?
    https://www.universetoday­.com/130823/who-was-giovanni-cassini/
  64. Special plane curves
    http://xahlee.info/Special­PlaneCurves_dir/ConicSecti­ons_dir/conicSections.html
  65. Why Does Slicing a Cone Give an Ellipse?
    https://infinityisreallybig­.com/2019/02/08/why-does-slicing-a-cone-give-an-ellipse/
  66. Interpolace
    https://mathonline.fme.vut­br.cz/pg/Algoritmy/05_APROX_KRIV­KY.htm
  67. Lagrange Polynomial Interpolation
    https://pythonnumericalmet­hods.berkeley.edu/notebook­s/chapter17.04-Lagrange-Polynomial-Interpolation.html
  68. Python Program for Lagrange Interpolation Method (with Output)
    https://www.codesansar.com/numerical-methods/python-program-lagrange-interpolation-method.htm
  69. Smooth Paths Using Catmull-Rom Splines
    https://qroph.github.io/2018/07/30/smo­oth-paths-using-catmull-rom-splines.html
  70. Lecture 11: Linear Interpolation Again – Bézier Curves
    http://www.math.kent.edu/~re­ichel/courses/intr.num.com­p.1/fall09/lecture12/bez.pdf
  71. Geometrie/Úvod do křivek
    https://cs.wikibooks.org/wi­ki/Geometrie/%C3%9Avod_do_k%C5%99i­vek
  72. B-Spline Curves and Surfaces (1)
    http://www.cad.zju.edu.cn/ho­me/zhx/GM/006/00-bscs1.pdf
  73. Praktické ukázky možností aplikace Mandelbulber při tvorbě animací
    https://www.root.cz/clanky/prakticke-ukazky-moznosti-aplikace-mandelbulber-pri-tvorbe-animaci/