Obsah
1. Patologické křivky a jiná matematická monstra
3. Weierstrassova funkce, Riemannova funkce atd.
4. Sněhová vločka Helge von Kocha
7. Gosperova křivka vyplňující plochu
8. Úvodní informace o L-systémech
9. Gramatiky a přepisovací pravidla
10. Úprava gramatik pro L-systémy
12. Počítačová želva a programovací jazyk Python
13. Triviální L-systém: základ pro další demonstrační příklady
14. L-systém pro sněhovou vločku Helge von Kocha
17. L-systém pro Gosperovu křivku
18. Malá odbočka – Cantorova množina
19. Repositář s demonstračními příklady
1. Patologické křivky a jiná matematická monstra
Původní křivky byly, jak již víme, konstruovány čistě geometrickou cestou, s využitím kružítka a pravítka. Proto byly tyto křivky spojité a bylo je možné nakreslit jedním tahem tužky. Již Eukleidés, s nímž jsme se nepřímo setkali v předchozím textu, si ovšem uvědomoval, že geometrické konstrukce založené na použití pravítka a kružítka ve skutečnosti nedokážou popsat všechny tvary, s nimiž se lze setkat jak v přírodě (hod předmětu), tak i v architektuře. Proto se mj. začal věnovat studiu křivek, které dnes nazýváme kuželosečkami. Ovšem Eukleidés nebyl první, protože minimálně dvě z kuželoseček – konkrétně parabolu a hyperbolu – pro západní svět objevil Menaechmus (přítel Platóna) již okolo roku 350 př.n.l. Na Eukleida navázal jeho žák Apollónios z Pergy (cca 200 př.n.l.), který zavedl pojmenování „hyperbola“ a „parabola“, jenž jsme převzali a používáme dodnes. Ovšem i kuželosečky se chovaly „korektně“ – daly se nakreslit jedním tahem tužky.
Apollónios taktéž objevil, že hyperbola má dvě větve, zatímco Eukleidés pracoval pouze s větví v prvním kvadrantu. To byl první problém, protože obě větve hyperboly není pochopitelně možné nakreslit jedním tahem, takže se pojem křivky musel poněkud zobecnit. Později, vlastně už v novověku, kdy se začaly křivky popisovat analyticky, vznikly další problematické křivky, například křivky, které jsou spojité, ale v žádném bodě diferencovatelné, křivky s „dírami“ (příkladem je y=x/x), později taktéž fraktální křivky, dokonce křivky vyplňující celou plochu atd.
V době, kdy byly tyto tvary objeveny, je mnoho i velmi vzdělaných lidí považovalo za matematická monstra a odmítalo se jimi dále teoreticky i prakticky zabývat. Že se ze strany těchto lidí jednalo o velký omyl, se ukázalo až na začátku osmdesátých let minulého století s prudkým rozvojem fraktální geometrie – ony „monstrózní“ tvary totiž představovaly zjednodušené a minimalistické topologické podoby složitých přírodních útvarů a fyzikálních jevů. Opět se tedy musela přepsat definice toho, co je to křivka. Některé z těchto křivek si dnes ukážeme.
2. Průběh funkce y=sin 1/x
Jednou z křivek, která se chová „divně“, je křivka získaná vykreslením funkce y=sin 1/x v okolí nulové hodnoty x. Zde totiž křivka začíná stále rychleji oscilovat, což je ostatně (částečně) patrné i při pohledu na její průběh (ten je ovšem v okolí nuly jen odhadnut – přesně tuto křivku totiž nakreslit nelze!):
Obrázek 1: Průběh funkce y=sin 1/x.
Průběh této funkce lze získat tímto skriptem:
"""Průběh funkce y=sin 1/x.""" import numpy as np import matplotlib.pyplot as plt # hodnoty parametru x x = np.linspace(0, 2, 500) # výpočet bodů ležících na křivce vytvořené funkcí y = np.sin(1/x) # rozměry grafu při uložení: 640x480 pixelů fig, ax = plt.subplots(1, figsize=(6.4, 4.8)) # titulek grafu fig.suptitle('y=sin 1/x', fontsize=15) # vrcholy na křivce pospojované úsečkami ax.plot(x, y, 'g-') # uložení grafu do rastrového obrázku plt.savefig("sin_1_over_x.png") # zobrazení grafu plt.show()
3. Weierstrassova funkce, Riemannova funkce atd.
Mnohem slavnější je však Weierstrassova funkce, která je ve všech svých bodech spojitá, ale v žádném bodě nemá derivaci. Taktéž se jedná o soběpodobnou křivku, protože její zvětšené části se podobají tvaru celé křivky. Weierstrassova funkce je pro každou hodnotu x definována jako:
f(x) = ∑an cos(bnπx)
pro n od nuly do nekonečna a pro vhodně zvolené koeficienty a a b.
Obrázek 2: Weirerstrassova funkce (resp. přesněji řečeno její hrubá aproximace).
Průběh Weierstrassovy funkce lze získat tímto skriptem:
"""Průběh Weierstrassovy funkce.""" import numpy as np import matplotlib.pyplot as plt # hodnoty parametru x x = np.linspace(-2, 2, 500) # úroveň detailů details = 100 # koeficienty a = 0.7 b = 7 def weierstrass(x, a, b, details): """Definice Weierstrassovy funkce.""" w = 0 for n in range(0, details): w += a**n*np.cos(b**n*np.pi*x) return w # příprava na vlastní výpočet y = np.vectorize(weierstrass) # výpočet s převodem na typ numpy_array approx = y(x, a, b, details) # rozměry grafu při uložení: 640x480 pixelů fig, ax = plt.subplots(1, figsize=(6.4, 4.8)) # titulek grafu fig.suptitle('Wiererstrassova funkce', fontsize=15) # vrcholy na křivce pospojované úsečkami ax.plot(x, approx, 'g-') # uložení grafu do rastrového obrázku plt.savefig("weierstrass.png") # zobrazení grafu plt.show()
4. Sněhová vločka Helge von Kocha
Velmi známým fraktálem konstruovaným pomocí L-systémů, je křivka a sněhová vločka Helge von Kocha (jednalo se skutečně o muže). Popišme si nejdříve křivku Helge von Kocha, sněhová vločka vzniká pouhou (nepatrnou) změnou počátečních podmínek. Vytváření křivky Helge von Kocha spočívá v provedení následujících kroků:
- Nejprve se, podobně jako v případě Cantorovy množiny, vykreslí úsečka s jednotkovou délkou.
- Ve druhém kroku se tato úsečka rozdělí na třetiny, a to opět stejným způsobem, jako v případě Cantorovy množiny. Prostřední třetina se vyjme a na jejím místě se sestrojí dvě ramena rovnoramenného trojúhelníku. Vznikne tedy obrazec, který se skládá z lomené úsečky (polyčáry), jejíž délka je rovna 4/3 délky původní úsečky, tj. celková délka se o třetinu prodlouží.
- Na vzniklý obrazec se opakovaně aplikuje pravidlo uvedené v předchozím bodě, tj. každá úsečka je rozdělena na třetiny, prostřední třetina se vyjme a nahradí se dvojicí ramen rovnoramenného trojúhelníka.
Obrázek 3: První iterace křivky Helge von Kocha.
Obrázek 4: Druhá iterace křivky Helge von Kocha.
Obrázek 5: Třetí iterace křivky Helge von Kocha.
Obrázek 6: Čtvrtá iterace křivky Helge von Kocha.
Obrázek 7: Pátá iterace křivky Helge von Kocha.
Při trojnásobném zjemnění se délka křivky Helge von Kocha zvětší čtyřikrát, proto Hausdorffova (fraktální) dimenze není celočíselná. Pro N=4 se tedy měřítko musí zmenšit na třetinu:
s=1/3
N=4
Hausdorffova dimenze křivky Helge von Kocha se vypočítá jako:
D=log N/log (1/s)=log 4/log 3=1,2618595
Křivka Helge von Kocha má i další zajímavé matematické a geometrické vlastnosti. Mezi ně patří to, že sice je v celém svém rozsahu spojitá, ale v žádném bodě nemá derivaci. Každý bod na křivce je totiž po nekonečně mnoha transformacích průnikem dvou nekonečně malých úseček, které tvoří strany trojúhelníka, který je taktéž nekonečně malý. Tato křivka je také nekonečně dlouhá, i když zabírá konečný (z obou stran omezený) prostor, jak je ostatně patrné z obrázků.
Křivku Helge von Kocha je možné popsat pomocí následující gramatiky GKochCurve:
GKochCurve=[V,P,S]
V={F,+,–}
P={F→F=F+F–F+F}
S=F
přičemž úhel otáčení želvy je nastaven na 60°
Sněhová vločka Helge von Kocha je vytvořena pomocí gramatiky GKochFlake, ve které je změněna pouze počáteční podmínka, tj. v první iteraci se nevykreslí pouhá úsečka, ale trojúhelník:
GKochFlake=[V,P,S]
V={F,+,–}
P={F→F=F+F–F+F}
S=F–F–F
5. Dračí křivka
Dračí křivka je dalším známým typem fraktálního objektu vytvářeného s využitím L-systémů. Její význam tkví především v tom, že její první iterace je možné vytvořit pouze pomocí ohýbání proužku papíru; žádné další složitější pomůcky nejsou zapotřebí. Postup tvorby dračí křivky je ukázán na následujícím animovaném obrázku. Začíná se s jednou úsečkou. Tato úsečka je ve své polovině ohnuta o pravý úhel doleva, takže vzniknou dvě úsečky navzájem svírající pravý úhel. Výsledkem je tvar zobrazený na zmíněné animaci:
Obrázek 8: Animace postupného vzniku dračí křivky.
Poté se již postupuje podobně jako u předchozích typů fraktálů, tj. iterativním způsobem. Obě úsečky jsou opět ohnuty, první o pravý úhel doleva, druhá o pravý úhel doprava. Výsledkem je čtveřice úseček tvořících lomenou čáru. Ohyb úseček probíhá podle popsaného principu dále a po několika iteracích se již začíná rýsovat tvar dračího těla i s ocasem a hlavou. Mimochodem, tento fraktál je velmi oblíbený například i mezi uživateli AutoCADu, kteří ho tvoří pomocí skriptů napsaných v LISPu.
Gramatika pro dračí křivku GDragon má tvar:
GDragon=[V,P,S] V={X,Y,F,+,–} P={Y→+FX–FY+, X→-FX++FY-} S=FX
6. C-křivka
Další „divnou“ křivkou, kterou lze vytvořit s využitím L-systémů je křivka připomínající písmeno C (C-curve). Jedná se o fraktální objekt vykreslený jednou lomenou čarou (polyčarou). Úhel „zalomení“ této polyčáry je vždy roven devadesáti stupňům a všechny úsečkové segmenty, ze kterých je polyčára složena, mají stejnou délku. Při bližším pohledu na celou konstrukci (viz první tři obrázky) zjistíme, že jde o rekurzivní křivku, tj. při každé iteraci se původní úsečkové segmenty rozdělí na dvě C-křivky, přičemž na poslední úrovni se pouze vykreslí horizontální či vertikální čára (podle aktuální orientace želvy). Při nastavení maximální úrovně iterace na nulu se vykreslí pouze vertikální úsečka (provede se kód za příkazem if), nastavení úrovně na jedničku má za následek vykreslení dvou na sebe kolmých úseček, při úrovni nastavené na dvojku se již vykreslí základ písmena „C“ atd.
Obrázek 9: C-křivka, malý počet přepisů L-systému (viz další text).
Obrázek 10: C-křivka.
Obrázek 11: C-křivka, velký počet přepisů L-systému.
7. Gosperova křivka vyplňující plochu
Některé křivky nebyly považovány za matematická „monstra“ pouze z toho důvodu, že neměly v žádném bodě derivaci. Existují totiž křivky, které dokážou vyplnit celou plochu nebo část plochy, což byla pro jednorozměrné útvary dosti neobvyklá vlastnost (se znalostí fraktální dimenze však dnes již víme, že nikoli neobvyklá). Mezi takové křivky patří například známá Hilbertova křivka. My si ovšem dnes pro zajímavost uvedeme jinou křivku, a to křivku Gosperovu, v níž se úsečky lomí v úhlu 60°. Způsob konstrukce této křivky je zřejmý z pohledu na další obrázky:
Obrázek 12: Gosperova křivka postupně vyplňující omezenou část plochy.
8. Úvodní informace o L-systémech
L-systémy, v minulosti též známé pod názvem Lindenmayerovy systémy, jsou skupinou fraktálů definovaných ve své nejjednodušší podobě pomocí regulárních nebo bezkontextových přepisovacích gramatik. Název této skupiny fraktálů, na jejichž výzkumu má největší podíl Aristid Lindenmayer a Przemyslaw Prusinkiewicz, pochází ze zkráceniny anglického sousloví Lindenmayer system nebo též LOGO-like turtle. LOGO je velmi zajímavý programovací jazyk vycházející z funkcionálního programovacího jazyka LISP (syntaxe je však „přezávorkovanému“ LISPu vzdálená), ve kterém se, kromě snadného zpracování datových struktur, dají s využitím jednoduchých příkazů pomocí takzvané želvy kreslit různé obrazce složené z úseček. S tímto zajímavým a ve světě oblíbeným programovacím jazykem jsme se ostatně na Rootu podrobněji seznámili v samostatném výukovém seriálu.
Podstatou tvorby těch nejjednodušších a nejpoužívanějších L-systémů je přepisování řetězců podle určitých pravidel, která jsou buď předem zadaná množinou přepisovacích pravidel (gramatiky), nebo se mění v průběhu generování fraktálního obrazce, například na základě zpětné vazby či na podněty okolního prostředí (gravitace, dopadající světlo apod.). Přepisování některých symbolů řetězce je většinou pevně dané, ale může být také určeno na základě generátoru náhodných čísel (stochastické L-systémy). Každý symbol v řetězci má přiřazen jistý geometrický význam, například transformaci či generování/nakreslení objektu. V případě použití želví grafiky se jedná o příkazy pro posun a natočení želvy (ale lze přidat i příkazy pro změnu typu či šířky kreslených úseček, pro změnu barvy, vyplnění obrazce atd.).
Zajímavé obrazce se začnou tvořit, jestliže v programu určeném pro LOGO použijeme iteraci resp. rekurzi, což odpovídá iteraci v gramatice, tj. stavu, kdy na pravé straně přepisovacího pravidla je nonterminální symbol shodný se symbolem na levé straně téhož pravidla (o terminálních a nonterminálních symbolech bude řeč v deváté kapitole). S pomocí L-systémů lze generovat fraktální objekty, které se podobají rostlinám, stromům a dalším přírodním útvarům. Poslední aplikace také směřují k využití těchto fraktálů při generování 3D modelů technologických artefaktů a dokonce i textur.
Z toho, jak se fraktál pomocí L-systémů generuje, je zřejmé, že se jedná o deterministický postup (pokud se při aplikaci přepisovacích pravidel nepoužije generátor náhodných čísel) a výsledný fraktál je tedy též deterministický. Těmto velmi pravidelným a mnohdy i symetrickým fraktálům se také někdy říká graftály. V dalších kapitolách se budeme zabývat právě deterministickými L-systémy, stochastickým systémům se budeme věnovat v některém z dalších částí tohoto seriálu.
Obrázek 13: Trojrozměrný L-systém.
9. Gramatiky a přepisovací pravidla
Naše povídání o L-systémech by nebylo úplné, pokud bychom si alespoň stručně nepopsali význam gramatik, přepisovacích pravidel a terminálních i nonterminálních symbolů. Gramatiky mají v teoretické informatice velký význam, zejména při studiu umělých jazyků (například programovacích). Gramatiku je možné popsat uspořádanou čtveřicí:
G=[N,Σ,P,S]
kde:
- N je konečná abeceda nonterminálních symbolů
- Σ je konečná abeceda terminálních symbolů
- P je konečná množina přepisovacích pravidel tvaru A → B
- S je axiom: neprázdná posloupnost symbolů S Є (N u Σ)+
Přepisovací pravidla jsou tvaru S→aBC, B→XY, C→a, C→D (dokonce i XYZ=DB), kde velkými písmeny jsou označeny nonterminální symboly a písmeny malými symboly terminální (ty se již dále nerozepisují). Podle tvaru přepisovacích pravidel rozlišujeme gramatiky regulární, bezkontextové, kontextové a obecné (Chomského hierarchie). Regulární gramatiky jsou z této skupiny nejjednodušší (popisují množinu nejméně „složitých“ jazyků), avšak velmi často používané, protože jazyky z této množiny lze snadno popsat i rozpoznat, například velmi oblíbeným regulárním výrazem. L-systémy jsou většinou popsány právě regulárními gramatikami, i když poněkud upravenými, což si blíže popíšeme v následující kapitole.
10. Úprava gramatik pro L-systémy
V L-systémech je použita zjednodušená forma gramatik, ve kterých splývají terminální a nonterminální symboly. Deterministický bezkontextový L-systém je tvořen uspořádanou trojicí:
G=[V,P,S]
kde:
- V je konečná abeceda symbolů (zde nerozlišujeme symboly terminální a nonterminální)
- P je konečná množina pravidel tvaru A → B; AЄV; BЄV*
- S je axiom: neprázdná posloupnost symbolů S Є V+
Jak již bylo řečeno v předchozích odstavcích, u L-systémů se dělení na terminální a nonterminální symboly většinou formálně nezavádí, zejména proto, že počet derivací (přepisů) je libovolný a po proběhnutí zadaného počtu derivací se původně nonterminální symboly změní na symboly terminální, tj. symboly interpretovatelné želvou (viz další odstavce zabývající se želví grafikou). Determinismus tohoto L-systému pramení z podmínky, že v množině P nesmějí existovat dvě pravidla se stejnou levou stranou. Při přepisování tedy vždy přesně víme, které pravidlo pro přepis vybrat. Existují i další třídy gramatik, jejichž zpracování je však složitější, proto se při práci s L-systémy tyto gramatiky nepoužívají a místo nich se aplikují jiné (méně „vědecké“ resp. formalizované) metody; například se jedná o parametrizovatelné L-systémy, jejichž přepis do gramatik (přepisovacích pravidel) je sice teoreticky možný, ale v praxi těžko realizovatelný (byly by použity kontextové gramatiky).
Derivace (označovaná také matematickým symbolem →) řetězce AЄV* znamená paralelní přepsání všech symbolů XЄA řetězce V z pravé strany pravidel z množiny P.
Například první dvě derivace L-systému G:
G=[{A,F,–,+}, {A → F – – F – – F,F → F + F – – F + F,+ → +,– → -},A]
se startovním symbolem A mají podobu:
A → F – – F – – F → F + F – – F + F – – F + F – – F + F – – F + F – – F + F
(mezery mezi symboly jsou uvedeny pouze pro přehlednost, ve skutečnosti se ve výsledném řetězci nevyskytují). Poslední uvedená posloupnost symbolů získaná v poslední derivaci se ve druhém kroku geometricky interpretuje. K tomu se používá takzvaná želví grafika (turtle graphics), ve které želva reprezentuje pomyslné kreslící zařízení, pomocí kterého se vytváří obrazce složené z úseček.
11. Želví grafika
Takzvaná želví grafika (turtle graphics) tvoří základní nástroj použitý při vytváření deterministických L-systémů, jedná se i o nedílnou součást programovacího jazyka LOGO. Nyní si řekneme základní informace o želví grafice. Základem je takzvaná želva, která je definována svým stavem a tabulkou akcí, které může provádět – z hlediska OOP se tedy jedná o klasicky pojatý objekt, kde stavu želvy odpovídá obsah datových složek objektu a tabulka akcí odpovídá metodám, kterými se mění datové složky a provádí další činnosti.
Stav želvy se skládá ze dvou prvků: z polohy želvy a z její orientace. Želva čte sekvenčně zadaný řetězec (získaný v případě L-systémů několikerým přepsáním startovacího symbolu S) a pomocí tabulky akcí interpretuje jednotlivé symboly jako příkazy. Pro úplné zadání tedy musíme přiřadit každému symbolu jeho význam. Nejjednodušší forma L-systému interpretovaného želvou v ploše může používat následující symboly:
Symbol | Příkaz pro želvu | Význam symbolu |
---|---|---|
F | draw forward | posun želvy dopředu s kreslením úsečky |
G | move forward | posun želvy dopředu bez kreslení úsečky |
B | draw backward | posun želvy dozadu s kreslením úsečky |
+ | turn left | natočení želvy doleva o předem známý počet stupňů |
– | turn right | natočení želvy doprava o předem známý počet stupňů |
Želva se nachází na kreslicí ploše a pomocí výše uvedených symbolů (příkazů) se může otáček okolo své osy doprava a doleva, přesouvat se dopředu bez kreslení nebo se přesouvat dopředu i dozadu spolu s kreslením, tj. mezi počáteční a koncovou pozicí želvy je nakreslena úsečka (želva se vždy pohybuje ve směru či proti směru své orientace). Vhodnou kombinací všech příkazů je možné vykreslovat i zdánlivě kulaté tvary (posun o malý krok spolu s nepatrným natočením), což je ukázáno na dalším obrázku. Za povšimnutí stojí, že želva pro svůj posun nepotřebuje znát svoji absolutní polohu, je tedy nezávislá na souřadném systému.
Obrázek 14: Screenshot grafického okna interpreteru LOGA – UCB Logo (želva je po vytvoření screenshotu zvýrazněna červenou barvou)
12. Počítačová želva a programovací jazyk Python
Želví grafika byla tak úspěšná a přitom implementačně jednoduchá, že se začala používat i mimo samotný jazyk Logo. To je mj. případ programovacího jazyka Python, který uživatelům nabízí standardní modul nazvaný turtle, jenž nabízí příkazy shodné s původním Logem. Modul turtle pro vykreslování používá Tkinter. Postup si ukážeme v dalších příkladech, v nichž vyřešíme i problematiku pomalého vykreslování celé scény, které sice nevadí při interaktivním ladění (tam naopak pomáhá), ale při kresbě složitějších obrazců již může být zpomalení neúnosné.
Obrázek 15: Želví grafika vykreslená v aplikaci, jejíž GUI bylo vytvořeno přes knihovnu appJar.
V prvním kroku musíme ve skriptu získat „želvu“, a to typicky zavoláním konstruktoru turtle.Turtle() (ten současně vytvoří i nové okno s kreslicí plochou). Dále je již možné s „želvou“ manipulovat běžným způsobem, tj. skrýt její sprite (obrázek), nastavit rychlost kreslení (0=nejvyšší rychlost :-) či barvu vykreslované křivky:
t = turtle.Turtle() t.hideturtle() t.speed(0) t.pencolor("green")
Nakreslíme nějaký jednodušší obrazec, přitom nám postačí příkazy forward a right:
side = 0 angle = 117 for _ in range(160): t.forward(side) t.right(angle) side += 1
Příkazem forward posuneme želvou o zadaný počet jednotek dopředu, tedy ve směru její hlavičky. V implicitním nastavení má území, na kterém se želva pohybuje, rozměry 200×200 jednotek s počátkem souřadnic uprostřed plátna. Příkazem right se želva otočí doprava o zadaný počet stupňů (nikoli radiánů).
Obrázek 16: Obrazec vykreslený přes modul turtle.
13. Triviální L-systém: základ pro další demonstrační příklady
Nyní již máme k dispozici jak znalosti o L-systémech, tak i o želví grafice. Tyto znalosti nyní můžeme spojit dohromady. Vytvoříme si jednoduchý příklad (nerekurzivního!) obrazce, jímž je čtverec. Ten vykreslíme želví grafikou na základě řetězce s příkazy pro želvu, který byl vygenerován L-systémem.
Samotná část s implementací přepisu řetězce vypadá jednoduše:
def produce_control_string(axiom, rewrite_rules, n): """Výpočet řídicího řetězce.""" s = axiom for i in range(n): tmp = "" for c in s: tmp += apply_rule(rewrite_rules, c) s = tmp return s
Aplikace zvoleného pravidla (přečteného z řetězce):
def apply_rule(rules, c): """Aplikace přepisovacího pravidla.""" output = "" for rule, result in rules.items(): if c == rule: return result else: output = c return output
A konečně funkce, která na základě obsahu řetězce (například „F+FF-B+“) provede vykreslení s využitím želví grafiky:
def draw_l_system(control_string, step, angle, start_x, start_y): """Vykreslení L-systému na obrazovku s využitím želví grafiky.""" # styl vykreslování color("red") pensize(2) penup() setpos(start_x, start_y) pendown() # projít všemi příkazy z řídicího řetězce for command in control_string: if command == "F": forward(step) elif command == "B": backward(step) elif command == "+": left(angle) elif command == "-": right(angle) # dokončení vykreslení a čekání na zavření okna done()
Celý skript bude vypadat následovně. Povšimněte si způsobu nastavení vlastností L-systému (úhel natočení želvy, krok, axiom):
"""Jednoduchý L-systém: vykreslení čtverce.""" from turtle import * # krok želvy pro příkazy "F" a "B" step = 300 # úhel otočení želvy pro příkazy "+" a "-" angle = 90 # startovní symbol axiom = "F" # přepisovací pravidla rewrite_rules = {} rewrite_rules["F"] = "F+F+F+F" # počet aplikací přepisovacích pravidel iterations = 1 # počáteční pozice želvy start_x = -150 start_y = -150 def apply_rule(rules, c): """Aplikace přepisovacího pravidla.""" output = "" for rule, result in rules.items(): if c == rule: return result else: output = c return output def produce_control_string(axiom, rewrite_rules, n): """Výpočet řídicího řetězce.""" s = axiom for i in range(n): tmp = "" for c in s: tmp += apply_rule(rewrite_rules, c) s = tmp return s def draw_l_system(control_string, step, angle, start_x, start_y): """Vykreslení L-systému na obrazovku s využitím želví grafiky.""" # styl vykreslování color("red") pensize(2) penup() setpos(start_x, start_y) pendown() # projít všemi příkazy z řídicího řetězce for command in control_string: if command == "F": forward(step) elif command == "B": backward(step) elif command == "+": left(angle) elif command == "-": right(angle) # dokončení vykreslení a čekání na zavření okna done() # výpočet řídicího řetězce control_string = produce_control_string(axiom, rewrite_rules, iterations) print(control_string) # vykreslení L-systému draw_l_system(control_string, step, angle, start_x, start_y)
Obrázek 17: Výsledek běhu předchozího demonstračního příkladu.
14. L-systém pro sněhovou vločku Helge von Kocha
V dalším demonstračním příkladu je ukázáno využití L-systému pro vykreslení křivky Helge von Kocha, kterou jsme si popsali ve čtvrté kapitole. Zdrojový kód tohoto příkladu vypadá následovně:
"""Jednoduchý L-systém: sněhová vločka Helge von Kocha.""" from turtle import * # krok želvy pro příkazy "F" a "B" step = 300 # úhel otočení želvy pro příkazy "+" a "-" angle = 60 # startovní symbol axiom = "F" # přepisovací pravidla rewrite_rules = {} rewrite_rules["F"] = "F+F--F+F" # počet aplikací přepisovacích pravidel iterations = 1 # počáteční pozice želvy start_x = -440 start_y = 0 def apply_rule(rules, c): """Aplikace přepisovacího pravidla.""" output = "" for rule, result in rules.items(): if c == rule: return result else: output = c return output def produce_control_string(axiom, rewrite_rules, n): """Výpočet řídicího řetězce.""" s = axiom for i in range(n): tmp = "" for c in s: tmp += apply_rule(rewrite_rules, c) s = tmp return s def draw_l_system(control_string, step, angle, start_x, start_y): """Vykreslení L-systému na obrazovku s využitím želví grafiky.""" # styl vykreslování color("red") pensize(2) penup() setpos(start_x, start_y) pendown() # projít všemi příkazy z řídicího řetězce for command in control_string: if command == "F": forward(step) elif command == "B": backward(step) elif command == "+": left(angle) elif command == "-": right(angle) # dokončení vykreslení a čekání na zavření okna done() # výpočet řídicího řetězce control_string = produce_control_string(axiom, rewrite_rules, iterations) print(control_string) # vykreslení L-systému draw_l_system(control_string, step, angle, start_x, start_y)
S výsledkem:
Obrázek 18: Výsledek běhu předchozího demonstračního příkladu.
Zvětšení počtu přepisů a zmenšení délky nakreslené úsečky:
"""Jednoduchý L-systém: sněhová vločka Helge von Kocha.""" from turtle import * # krok želvy pro příkazy "F" a "B" step = 33 # úhel otočení želvy pro příkazy "+" a "-" angle = 60 # startovní symbol axiom = "F" # přepisovací pravidla rewrite_rules = {} rewrite_rules["F"] = "F+F--F+F" # počet aplikací přepisovacích pravidel iterations = 3 # počáteční pozice želvy start_x = -440 start_y = 0 def apply_rule(rules, c): """Aplikace přepisovacího pravidla.""" output = "" for rule, result in rules.items(): if c == rule: return result else: output = c return output def produce_control_string(axiom, rewrite_rules, n): """Výpočet řídicího řetězce.""" s = axiom for i in range(n): tmp = "" for c in s: tmp += apply_rule(rewrite_rules, c) s = tmp return s def draw_l_system(control_string, step, angle, start_x, start_y): """Vykreslení L-systému na obrazovku s využitím želví grafiky.""" # styl vykreslování color("red") pensize(2) penup() setpos(start_x, start_y) pendown() # projít všemi příkazy z řídicího řetězce for command in control_string: if command == "F": forward(step) elif command == "B": backward(step) elif command == "+": left(angle) elif command == "-": right(angle) # dokončení vykreslení a čekání na zavření okna done() # výpočet řídicího řetězce control_string = produce_control_string(axiom, rewrite_rules, iterations) print(control_string) # vykreslení L-systému draw_l_system(control_string, step, angle, start_x, start_y)
15. L-systém pro C-křivku
Prakticky stejným programem, pouze s využitím jiné sady přepisovacích pravidel a odlišného úhlu natočení želvy, získáme C-křivku, o níž jsme se taktéž zmínili v předchozím textu:
"""Jednoduchý L-systém: C-křivka.""" from turtle import * # krok želvy pro příkazy "F" a "B" step = 10 # úhel otočení želvy pro příkazy "+" a "-" angle = 45 # startovní symbol axiom = "F" # přepisovací pravidla rewrite_rules = {} rewrite_rules["F"] = "+F--F+" # počet aplikací přepisovacích pravidel iterations = 8 # počáteční pozice želvy start_x = -100 start_y = 0 def apply_rule(rules, c): """Aplikace přepisovacího pravidla.""" output = "" for rule, result in rules.items(): if c == rule: return result else: output = c return output def produce_control_string(axiom, rewrite_rules, n): """Výpočet řídicího řetězce.""" s = axiom for i in range(n): tmp = "" for c in s: tmp += apply_rule(rewrite_rules, c) s = tmp return s def draw_l_system(control_string, step, angle, start_x, start_y): """Vykreslení L-systému na obrazovku s využitím želví grafiky.""" # styl vykreslování color("red") pensize(2) penup() setpos(start_x, start_y) pendown() # projít všemi příkazy z řídicího řetězce for command in control_string: if command == "F": forward(step) elif command == "B": backward(step) elif command == "+": left(angle) elif command == "-": right(angle) # dokončení vykreslení a čekání na zavření okna done() # výpočet řídicího řetězce control_string = produce_control_string(axiom, rewrite_rules, iterations) print(control_string) # vykreslení L-systému speed(0) hideturtle() draw_l_system(control_string, step, angle, start_x, start_y)
Obrázek 19: Výsledek běhu předchozího demonstračního příkladu.
Obrázek 20: Větší počet přepsání axiomu vede k detailnějšímu snímku.
16. L-systém pro dračí křivku
Vykreslení dračí křivky s využitím vhodně zvoleného L-systému je snadné, povšimněte si ovšem, že zde již máme dvě přepisovací pravidla (nikoli pouze jedno) a navíc se liší i axiom, tedy počáteční hodnota řetězce s příkazy pro želvu:
"""Jednoduchý L-systém: dračí křivka.""" from turtle import * # krok želvy pro příkazy "F" a "B" step = 20 # úhel otočení želvy pro příkazy "+" a "-" angle = 90 # startovní symbol axiom = "FX" # přepisovací pravidla rewrite_rules = {} rewrite_rules["X"] = "X+YF+" rewrite_rules["Y"] = "-FX-Y" # počet aplikací přepisovacích pravidel iterations = 9 # počáteční pozice želvy start_x = -300 start_y = -150 def apply_rule(rules, c): """Aplikace přepisovacího pravidla.""" output = "" for rule, result in rules.items(): if c == rule: return result else: output = c return output def produce_control_string(axiom, rewrite_rules, n): """Výpočet řídicího řetězce.""" s = axiom for i in range(n): tmp = "" for c in s: tmp += apply_rule(rewrite_rules, c) s = tmp return s def draw_l_system(control_string, step, angle, start_x, start_y): """Vykreslení L-systému na obrazovku s využitím želví grafiky.""" # styl vykreslování color("red") pensize(2) penup() setpos(start_x, start_y) pendown() # projít všemi příkazy z řídicího řetězce for command in control_string: if command == "F": forward(step) elif command == "B": backward(step) elif command == "+": left(angle) elif command == "-": right(angle) # dokončení vykreslení a čekání na zavření okna done() # výpočet řídicího řetězce control_string = produce_control_string(axiom, rewrite_rules, iterations) print(control_string) # vykreslení L-systému speed(0) draw_l_system(control_string, step, angle, start_x, start_y)
Obrázek 21: Výsledek běhu předchozího demonstračního příkladu s dračí-křivkou.
Obrázek 22: Detailnější dračí křivka.
17. L-systém pro Gosperovu křivku
V dnešním posledním demonstračním příkladu je realizována Gosperova křivka, opět s využitím knihovny turtle:
"""Jednoduchý L-systém: Gosperova-křivka.""" from turtle import * # krok želvy pro příkazy "F" a "B" step = 10 # úhel otočení želvy pro příkazy "+" a "-" angle = 60 # startovní symbol axiom = "F" # přepisovací pravidla rewrite_rules = {} rewrite_rules["F"] = "F-G--G+F++FF+G-" rewrite_rules["G"] = "+F-GG--G-F++F+G" # počet aplikací přepisovacích pravidel iterations = 4 # počáteční pozice želvy start_x = 100 start_y = 250 def apply_rule(rules, c): """Aplikace přepisovacího pravidla.""" output = "" for rule, result in rules.items(): if c == rule: return result else: output = c return output def produce_control_string(axiom, rewrite_rules, n): """Výpočet řídicího řetězce.""" s = axiom for i in range(n): tmp = "" for c in s: tmp += apply_rule(rewrite_rules, c) s = tmp return s def draw_l_system(control_string, step, angle, start_x, start_y): """Vykreslení L-systému na obrazovku s využitím želví grafiky.""" # styl vykreslování color("red") pensize(2) penup() setpos(start_x, start_y) pendown() # projít všemi příkazy z řídicího řetězce for command in control_string: if command == "F" or command=="G": forward(step) elif command == "B": backward(step) elif command == "+": left(angle) elif command == "-": right(angle) # dokončení vykreslení a čekání na zavření okna done() # výpočet řídicího řetězce control_string = produce_control_string(axiom, rewrite_rules, iterations) print(control_string) # vykreslení L-systému speed(0) hideturtle() draw_l_system(control_string, step, angle, start_x, start_y)
Obrázek 23: Výsledek běhu předchozího demonstračního příkladu s Gosperovou křivkou.
18. Malá odbočka – Cantorova množina
Článek, v němž se zmiňujeme o matematických „monstrozitách“ i o L-systémech by nebyl úplný, kdybychom se v něm nezmínili o Cantorově množině, která do určité míry změnila pohled na matematiku. Nejedná se o křivku v pravém slova smyslu, takže se skutečně jedná o malou odbočku.
Cantorova množina je pojmenována po matematikovi ruského původu, jehož celé jméno zní Georg Ferdinand Ludwig Philipp Cantor. Tento pravděpodobně nejjednodušší fraktál může být iterativně zkonstruován následujícím způsobem:
- Konstrukce začíná s úsečkou, která má jednotkovou délku. Tato úsečka se většinou kreslí ve vodorovné poloze, na konstrukci fraktálu však nemá orientace úsečky žádný vliv.
- Úsečka se rozdělí na tři stejně dlouhé části. Prostřední část (třetina) se vyjme, takže nám ve druhé iteraci vzniknou dvě úsečky, z nichž každá má třetinovou délku oproti úsečce původní.
- Rozdělování úseček a odstraňování jejich prostředních částí pokračuje iterativně dále a v limitě, tj. po provedení nekonečně mnoha iterací, získáme množinu bodů (úseček s nulovou délkou), které nejsou navzájem propojeny, protože mezi každou dvojicí sousedních bodů se nachází „díra“ (také s nulovou délkou) vzniklá postupným vyjímáním prostřední třetiny úseček.
- Po provedení předchozích třech bodů dostaneme fraktální obrazec, který však tvoří pouze část celé Cantorovy množiny. Aby vznikl skutečný fraktál, musíme vytvořený obrazec vzít a nekonečněkrát ho zkopírovat na přímce odpovídající orientaci původní úsečky. Vzdálenost mezi sousedními kopiemi obrazce je rovna dvěma, přičemž původní úsečka je jednotková. Tento krok je pro zachování symetrie měřítka nutný (jak na to upozornil již před cca 25 lety B. Mandelbrot), i když na něj v některé literatuře není myšleno.
Cantorovu množinu je možné popsat pomocí následující gramatiky GCantor:
GCantor=[V,P,S]
V={F,G}
P={F→FGF, G→GGG}
S=F
Význam Cantorovy množiny
Cantorova množina je významná hned ze tří hledisek:
- Z historického hlediska je důležité, že Cantor s pomocí své množiny (a také Cantorovy funkce) upozornil na některé do té doby ignorované aspekty algebry a geometrie. Přibližně ve stejné době prezentoval Weierstrass svoji slavnou funkci, která je sice spojitá, ale nediferencovatelná. Obě práce měly významný vliv na další vývoj matematiky a fyziky, která se v období kolem roku 1870 nacházela v krizi, která vyústila v celkovou změnu myšlení.
- Současně se jedná o nejjednodušší fraktální objekt, na kterém se snadno vysvětlují základní pojmy fraktální geometrie, zejména význam soběpodobnosti a nezávislosti na změně měřítka (prakticky nic jednoduššího, než množinu bodů ležících na úsečce není možné vymyslet). I výpočet fraktální dimenze Cantorovy množiny je poměrně jednoduchý. Také konstrukce Cantorovy množiny – alespoň pro prvních několik iterací – nevyžaduje prakticky žádné složité pomůcky, pouze pravítko a tužku. To neplatí například u Mandelbrotovy množiny, na jejíž výpočet je počítač nutností.
- Cantorovu množinu můžeme nalézt v mnoha složitějších dynamických systémech s fraktální charakteristikou. Například při vertikálním řezu bifurkačního diagramu získáme Cantorovu množinu. Totéž platí pro řez nespojitou Juliovou množinou atd. V některých případech se místo s termínem Cantorova množina setkáme s Cantorovým prachem (Cantor dust).
Obrázek 24: Způsob vzniku Cantorovy množiny.
19. Repositář s demonstračními příklady
Všechny dříve 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/presentations. 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ář:
20. Odkazy na Internetu
- The spiral: the eternal sign of the creative and organising principle at work in the universe
https://geoffjward.medium.com/the-spiral-the-eternal-sign-of-the-creative-and-organising-principle-at-work-in-the-universe-8889ba092300 - Speira(Spiral): one of the oldest and most powerful symbols in the world
https://www.greecehighdefinition.com/blog/speira-spiral-oldest-greek-symbols-in-the-world-ancient-greece - Spirals
https://web.stanford.edu/~siegelr/photography/spirals.html - Why Do Spirals Exist Everywhere in Nature?
https://www.samwoolfe.com/2014/05/spirals-everywhere.html - Patterns In Nature: Where to Spot Spirals
https://www.scienceworld.ca/stories/patterns-nature-where-spot-spirals/ - Spirals in Nature
https://extension.illinois.edu/blogs/naturalist-news/2021–06–23-spirals-nature - The Curves of Life (Dover Books Explaining Science)
https://www.amazon.com/Curves-Dover-Books-Explaining-Science/dp/048623701X - Famous Curves Index
https://mathshistory.st-andrews.ac.uk/Curves/ - Curve (Wikipedia)
https://en.wikipedia.org/wiki/Curve - Mathematical curves
https://www.2dcurves.com/index.html - Curves (Wolfram MathWorld)
https://mathworld.wolfram.com/topics/Curves.html - Smooth Curve (Wolfram MathWorld)
https://mathworld.wolfram.com/SmoothCurve.html - Spirals (Wolfram MathWorld)
https://mathworld.wolfram.com/topics/Spirals.html - An Interactive Introduction to Splines
https://ibiblio.org/e-notes/Splines/Intro.htm - Parabola
https://www.2dcurves.com/conicsection/conicsectionp.html - Hyperbola
https://www.2dcurves.com/conicsection/conicsectionh.html - Dioklova kisoida
https://cs.wikipedia.org/wiki/Dioklova_kisoida - Archimédova spirála
https://cs.wikipedia.org/wiki/Archim%C3%A9dova_spir%C3%A1la - Conchoid (mathematics)
https://en.wikipedia.org/wiki/Conchoid_(mathematics) - Algebraic curve
https://en.wikipedia.org/wiki/Algebraic_curve - Transcendental curve
https://en.wikipedia.org/wiki/Transcendental_curve - Spiral
https://en.wikipedia.org/wiki/Spiral - List of spirals
https://en.wikipedia.org/wiki/List_of_spirals - Hyperbolická spirála
https://cs.wikipedia.org/wiki/Hyperbolick%C3%A1_spir%C3%A1la - Hyperbolic Spiral
https://mathworld.wolfram.com/HyperbolicSpiral.html - Lituus (mathematics)
https://en.wikipedia.org/wiki/Lituus_(mathematics) - Spiral of Spirals Fractals 2 with Python Turtle (Source Code)
https://pythonturtle.academy/spiral-of-spirals-fractals-2-with-python-turtle-source-code/ - Cornu Spiral
http://hyperphysics.gsu.edu/hbase/phyopt/cornu.html - Spiral
https://www.2dcurves.com/spiral/spiral.html - Cornu’s spiral
https://www.johndcook.com/blog/2016/03/23/cornus-spiral/ - Cornu Spiral
https://mathworld.wolfram.com/CornuSpiral.html - Fresnel Integrals
https://mathworld.wolfram.com/FresnelIntegrals.html - Fresnel integral
https://en.wikipedia.org/wiki/Fresnel_integral - Algebraic Curves
https://mathworld.wolfram.com/topics/AlgebraicCurves.html - Elliptic Curves
https://mathworld.wolfram.com/topics/EllipticCurves.html - Eukleidovská konstrukce
https://cs.wikipedia.org/wiki/Eukleidovsk%C3%A1_konstrukce - Euclidean Constructions
http://www.cs.cas.cz/portal/AlgoMath/Geometry/PlaneGeometry/GeometricConstructions/EuclideanConstructions.htm - Kvadratura kruhu
https://cs.wikipedia.org/wiki/Kvadratura_kruhu - Trisekce úhlu
https://cs.wikipedia.org/wiki/Trisekce_%C3%BAhlu - Straightedge and compass construction
https://en.wikipedia.org/wiki/Straightedge_and_compass_construction - C.a.R.
http://car.rene-grothmann.de/doc_en/index.html - CaRMetal (Wikipedia)
https://en.wikipedia.org/wiki/C.a.R. - CaRMetal (Španělsky a Francouzsky)
http://carmetal.org/index.php/fr/ - CaRMetal (Wikipedia)
https://en.wikipedia.org/wiki/CaRMetal - Regular Polygon
http://mathforum.org/dr.math/faq/formulas/faq.regpoly.html - Geometric Construction with the Compass Alone
http://www.cut-the-knot.org/do_you_know/compass.shtml - Kvadratura kruhu (Wikipedie)
https://cs.wikipedia.org/wiki/Kvadratura_kruhu - Compass equivalence theorem
https://en.wikipedia.org/wiki/Compass_equivalence_theorem - Curves we (mostly) don't learn in high school (and applications)
https://www.youtube.com/watch?v=3izFMB91K_Q - Can You Really Derive Conic Formulae from a Cone? – Menaechmus' Constructions
https://www.maa.org/press/periodicals/convergence/can-you-really-derive-conic-formulae-from-a-cone-menaechmus-constructions - Apollonius of Perga
https://en.wikipedia.org/wiki/Apollonius_of_Perga - Catenary arch
https://en.wikipedia.org/wiki/Catenary_arch - Parabolic arch
https://en.wikipedia.org/wiki/Parabolic_arch - Wattova křivka
https://www.geogebra.org/m/gNh4bW9r - Model stegosaura byl získán na stránce
http://www.turbosquid.com/HTMLClient/FullPreview/Index.cfm/ID/171071/Action/FullPreview - Obrázek nohy dinosaura byl získán na adrese
http://perso.wanadoo.fr/rimasson/3d/leg.htm - Spirograph
https://en.wikipedia.org/wiki/Spirograph - Epicykloida
https://cs.wikipedia.org/wiki/Epicykloida - Hypocykloida
https://cs.wikipedia.org/wiki/Hypocykloida - Hypotrochoida
https://cs.wikipedia.org/wiki/Hypotrochoida - Superelipsoidy a kvadriky v POV-Rayi
https://www.root.cz/clanky/superelipsoidy-a-kvadriky-v-pov-rayi/ - Fifty Famous Curves, Lots of Calculus Questions, And a Few Answers
https://elepa.files.wordpress.com/2013/11/fifty-famous-curves.pdf - Barr, A.H.: Superquadrics and Angle Preserving Transformations,
IEEE Computer Graphics and Applications, January 1981 - Bourke Paul: Quadrics,
July 1996 - Bourke Paul: Superellipse and Superellipsoid,
January 1990 - Faux, I.D. a Pratt, M.J.: Computational Geometry for Design and Manufacture,
Ellis Horwood Ltd., Wiley & Sons, 1979 - Wallace A.: Differential Topology,
Benjamin/Cummings Co., Reading, Massachussetts, USA, 1968 - Glossary of Bridge Terminology
http://sdrc.lib.uiowa.edu/eng/bridges/WaddellGlossary/GlossC.htm - Brachistochrona
https://cs.wikipedia.org/wiki/Brachistochrona - Missions: Cassini
https://solarsystem.nasa.gov/missions/cassini/overview/ - Giovanni Domenico Cassini
https://en.wikipedia.org/wiki/Giovanni_Domenico_Cassini - Cassini Ovals
https://mathworld.wolfram.com/CassiniOvals.html - Geocentrismus
https://cs.wikipedia.org/wiki/Geocentrismus - Who was Giovanni Cassini?
https://www.universetoday.com/130823/who-was-giovanni-cassini/ - Special plane curves
http://xahlee.info/SpecialPlaneCurves_dir/ConicSections_dir/conicSections.html - Why Does Slicing a Cone Give an Ellipse?
https://infinityisreallybig.com/2019/02/08/why-does-slicing-a-cone-give-an-ellipse/ - Interpolace
https://mathonline.fme.vutbr.cz/pg/Algoritmy/05_APROX_KRIVKY.htm - Lagrange Polynomial Interpolation
https://pythonnumericalmethods.berkeley.edu/notebooks/chapter17.04-Lagrange-Polynomial-Interpolation.html - Python Program for Lagrange Interpolation Method (with Output)
https://www.codesansar.com/numerical-methods/python-program-lagrange-interpolation-method.htm - Smooth Paths Using Catmull-Rom Splines
https://qroph.github.io/2018/07/30/smooth-paths-using-catmull-rom-splines.html - Lecture 11: Linear Interpolation Again – Bézier Curves
http://www.math.kent.edu/~reichel/courses/intr.num.comp.1/fall09/lecture12/bez.pdf - Geometrie/Úvod do křivek
https://cs.wikibooks.org/wiki/Geometrie/%C3%9Avod_do_k%C5%99ivek - B-Spline Curves and Surfaces (1)
http://www.cad.zju.edu.cn/home/zhx/GM/006/00-bscs1.pdf - Praktické ukázky možností aplikace Mandelbulber při tvorbě animací
https://www.root.cz/clanky/prakticke-ukazky-moznosti-aplikace-mandelbulber-pri-tvorbe-animaci/ - Kochanek–Bartels spline
https://en.wikipedia.org/wiki/Kochanek%E2%80%93Bartels_spline - class KochanekBartels
https://splines.readthedocs.io/en/latest/_modules/splines.html#KochanekBartels - Fraktály v počítačové grafice XVIII
https://www.root.cz/clanky/fraktaly-v-pocitacove-grafice-xviii/ - Fraktály v počítačové grafice XVI
https://www.root.cz/clanky/fraktaly-v-pocitacove-grafice-xvi/ - Fraktály v počítačové grafice IV
https://www.root.cz/clanky/fraktaly-v-pocitacove-grafice-iv/ - Systémy iterovaných funkcí a algoritmus náhodné procházky
https://www.root.cz/clanky/systemy-iterovanych-funkci-a-algoritmus-nahodne-prochazky/ - Pravděpodobnosti transformací v systémech iterovaných funkcí
https://www.root.cz/clanky/pravdepodobnosti-transformaci-v-systemech-iterovanych-funkci/ - Marie Alfred Cornu
https://en.wikipedia.org/wiki/Marie_Alfred_Cornu - Přechodnice
https://cs.wikipedia.org/wiki/P%C5%99echodnice - Evolventa
https://cs.wikipedia.org/wiki/Evolventa - Polopřímka
https://cs.wikipedia.org/wiki/Polop%C5%99%C3%ADmka - Involute (anglické označení pro evolventu)
https://en.wikipedia.org/wiki/Involute - Evolventní ozubení
https://cs.wikipedia.org/wiki/Evolventn%C3%AD_ozuben%C3%AD - Pathological (mathematics)
https://en.wikipedia.org/wiki/Pathological_(mathematics) - Dirichletova funkce
https://cs.wikipedia.org/wiki/Dirichletova_funkce - Weierstrassova funkce
https://cs.wikipedia.org/wiki/Weierstrassova_funkce - Riemannova funkce
https://cs.wikipedia.org/wiki/Riemannova_funkce - Křivka vyplňující prostor
https://cs.wikipedia.org/wiki/K%C5%99ivka_vypl%C5%88uj%C3%ADc%C3%AD_prostor - Peanova křivka
https://cs.wikipedia.org/wiki/Peanova_k%C5%99ivka - Dračí křivka
https://cs.wikipedia.org/wiki/Dra%C4%8D%C3%AD_k%C5%99ivka - Sierpińského křivka
https://cs.wikipedia.org/wiki/Sierpi%C5%84sk%C3%A9ho_k%C5%99ivka - Rozumná funkce
https://cs.wikipedia.org/wiki/Rozumn%C3%A1_funkce