Pouze tento týden sleva až 80 % na e-learning týkající se C# .NET. Zároveň využij akci až 30 % zdarma při nákupu e-learningu - Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 5 - Mandelbrotova a Juliova množina

V minulé lekci, Obecná teorie a dělení fraktálů, jsme rozdělili fraktály na L-systémy, IFS, polynomické a náhodné. Vysvětlili jsme si také obecnou teorii a pojmy soběpodobnosti a soběpříbuznosti.

V této lekci probereme Mandelbrotovu a Juliovu množinu, jejich popis a uvedeme si zdrojový kód ke generování těchto známých fraktálů.

Mandelbrotova množina

Jedná se o polynomický nelineární deterministický fraktál a patrně nejznámější fraktál vůbec. Objevil jej Benoît Mandelbrot v 70. letech 20. století při pokusu o nalezení jakéhosi "katalogu" Juliových množin. Vzniká iterativně a je definován rovnicí z=z2+c, kde z i c jsou komplexní čísla. Je to potvrzení teorie, že i velice jednoduché systémy mohou vykazovat chaotické chování. V m-set, jak se zkráceně Mandelbrotova množina nazývá, je c konstanta a zároveň pozice vykreslovaného bodu. Počáteční hodnota z je [0;0] a slouží de facto k uchování hodnoty. Správně by se měly vyzkoušet všechny body roviny (dosadit je za c), ale pro |z| systém diverguje. Jak to můžeme tvrdit? Použijeme důkazu, který využívá trojúhelníkové nerovnosti pro komplexní čísla |a+b|>=|a|-|b|, kde za a dosadíme z2 a za b konstantu c. Tedy |z2+ c| = |z2| - |c|. Nyní je nutné najít minimální hodnotu |z|, při jejímž překročení je |z2+ c|>|z|. Nazvěme tuto hodnotu třeba r. Potom r2-|c|=r a když převedeme vše nalevo, dostaneme r2-r-|c|=0. Z rovnice vyplývá, že r=(1+(1+4|c|1­/2)/2. Známe tedy hodnotu r. Vzhledem k tomu, že před první iterací z=0, tak po ní z=c. V předchozích vzorcích můžeme tedy r nahradit |c|. |c|2-2|c|=0, tzn. |c|=2. Nyní můžeme bez obav vypustit z výpočtu všechny body, které nepatří do kružnice o poloměru 2 s počátkem v bodě [0,0]. Pro případ, kdy |z| směřuje k nule, neexistuje žádný důkaz, a proto musíme poctivě vyzkoušet všechny body v kruhu o poloměru 2. Všechny body vně a některé uvnitř, které divergují, nepatří do množiny, ostatní ano. M-set je souměrná podle osy x, podle osy y nikoli. Hranice mezi dvěma oblastmi přitažlivosti je nekonečně tenká, ale také nekonečně členitá. Její Hausdorffova dimenze je rovna 2, jedná se tedy o nejčlenitelnější útvar v ploše o omezeném obsahu. V základní množině nejsou pochopitelně patrné všechny detaily, a proto se provádí zoomování. Tak můžeme např. objevit menší kopie M-set, různě natočené či modifikované. M-set můžeme zvětšovat donekonečna a stále objevujeme nové a nové detaily. Jednotlivé body můžeme obarvit podle libovolné palety, a tak ze zdánlivě stejného obrázku dostaneme různé variace na to samé téma.

Mandelbrotova množina

Mandelbrotova množina

Výpočet Mandelbrotovy množiny

Jedná se o Time escape algorithm. Potřebujeme dva vnořené cykly, které nám vyznačují zkoumaný čtverec (obdélník). V základní množině je to -2;2 a -2;2. Dále si určíme maximální počet iterací, např. 100. Při dobré implementaci dostáváme kvalitní obrázky i s přesností 30, ale čím menší přesnost, tím menší detaily. Řídící proměnné cyklů představují konstantu c, a proto uvnitř druhého cyklu se nachází další, jehož horní hranice je právě hodnota přesnosti. Pokud abs(z) > 2 tak se cyklus ukončí a bod se obarví příslušnou barvou. Pokud není nalezen směr atraktoru, bod do množiny patří a obarví se například černě. Díky paletě můžeme dosáhnou až překvapivě efektních obrázků. M-set nenaleznete v přírodě, ale třeba ve Photoshopu a podobných programech.

Algoritmus v metajazyce C

for (x=-2,x>2,x+=posun)
{
    a++
    for (y=-2,y>2,y+=pusun)
    {
        for (p=1,p>presnost,p++)
        {
            b++
            ztemp = [z]*[z]+[x,y]
            z = ztemp
            //Pokud (z1z1+z2z2) > 4 pak bod nepatří; obarvi bod [a,b]přislušnou barvou
        }
        //Pokud  cyklus proběhl celý, bod [a,b] patří
    }
}

Zde hranaté závorky neoznačují pole, ale komplexní číslo. Např. [z] se zde chápe jako [z1;z2]. Proměnná posun označuje jemnost našeho postupu. Pokud bude např. 0,1, cykly proběhnou 40x a obrázek bude mít rozměr 40x40 bodů. Výhodné je nastavit ji na 0,01, to je podle mě ideální kompromis mezi velikostí a rychlostí. Rychlost je skutečně limitující faktor, při přesnosti 100 a posunu 0,01 jsem napočítal přes 1 000 000 iterací. Tady už záleží jen na tom, jak si s příslušným jazykem dokážete pohrát. Na mém dinosauřím pentiu 200, 32 MB RAM trval výpočet základní množiny (posun = 0,01; přesnost 100) asi 3,5 vteřiny. Program byl napsán ve Visual Basic a optimalizován pro rychlost. Program i se zdrojákem si můžete stáhnout na http://www.sweb.cz/…et_balik.exe, v případě nefunkčnosti pod článkem. Rozhodně není dotažený do konce, a tak pokud máte VB, zkuste si své vývojářské schopnosti. Doporučuji při kompilaci zakázat všechny ochrany proti chybám. Sbírku algoritmů uvádím v několika jazycích zde.

Visual Basic

'Tady je zdroják ve Visual Basicu. Potřebuje jeden PictureBox, pár textboxů [6], a je dobré jej opatřit i tlačítkem start.
Private Declare Function SetPixelV Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal crColor As Long) As Long
Private Type Komplexni
x As Double
y As Double
End Type

Dim barva() 'počet barev-ten si musíte nastavit sami, ale měl by se rovnat či být větší než přesnost výpočtu
Dim hdc1 as long
Dim přesnost As Long, zx As Double
Dim zy As Double, i As Long
Dim t As Long, tt As Long
Dim ttt As Double, tttt As Double
Dim z As Komplexni, o As Double
Dim okolikT As Double, pres As Double
Dim pom As Long

hdc1 = picture1.hdc
Picture1.Cls 'Vyčištění pictureboxu-oceníte zejména tehdy, když je další obrázek podobný tomu předchozímu
startt = CDbl(Text1.Text) 'Uživatel nastaví x-ovou souřadnici
starttt = CDbl(Text2.Text) 'Uživatel nastaví y-ovou souřadnici
zoom = CDbl(Text3.Text) 'Uživatel nastaví zvětšení
přesnost = CDbl(Text4.Text) 'Uživatel nastaví max. počet iterací pro jeden bod
pres = (přesnost \ 2) - 1 'Menší fígl, vysvětlen dále
výška = CLng(Text6.Text) 'Uživatel nastaví výšku obrázku(počet bodů)
šířka = CLng(Text5.Text) 'Uživatel nastaví šířku obrázku
okolikT = 1 / zoom 'Posun reálné a imaginární složky
ttt = startt
tttt = starttt
NaplňBarvy() 'Pouze imaginární procedura pro určení barev
For t = 0 To výška
ttt = ttt + okolikT 'Posun reálné složky
For tt = 0 To šířka
tttt = tttt + okolikT 'Posun imaginární složky
z.x = ttt 'Místo z=0 rovnou přiřadíme z hodnotu c[ttt,tttt]-opatření pro snížení počtu operací
z.y = tttt
For i = 1 To pres
zx = z.x * z.x - z.y * z.y + ttt ' Jedna iterace
zy = 2 * z.x * z.y + tttt
z.x = (zx * zx - zy * zy) + ttt' Druhá iterace- proto si můžeme dovolit přesnost dělit dvěma, na přesnost to nemá vliv
z.y = 2 * zx * zy + tttt 'Pokud vám nejsou operace s komplexními čísly známy, musíte mi věřit.
If z.x * z.x + z.y * z.y > 4 Then GoTo oto 'Pokud je mimo, vykresli bod. z*z je použito proto, že z2 je výrazně pomalejší
Next i
GoTo otoo1 'Pokud patří, nic nekresli (bod má barvu pozadí). Dost to zrychluje
oto:
SetPixelV hdc1, t, tt, barva(i) 'Funkce API je asi o dva řády rychlejší než metoda line
otoo1: 'Pokud neholdujete nepodmíněným skokům, tak se moc nerozčilte
Next tt
tttt = starttt 'Nastavení pomocné proměnné pro z na správnou hodnotu
DoEvents
Next t

Java

Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

Nekomentovaný zdrojový kód v jazyce Java. Staženo z http://honzour.kgb.cz/ (teď to přesměrovává na libimseti.cz :D), nevím jestli funguje:

import java.awt.event.;
import java.awt.;
import java.applet.;
import java.awt.image.;

public class mandel extends Applet {
Image i;

Image MandelBrot(int x,int y){
    int i,j,iter;
    double im,re,zr,zi,pom;

    int[] p=new int[x*y];
    for (i=0; i<x; i++) {
        re=3*i;
        re=re/x-2.1;
        for (j=0; j<y; j++) {
            im=3*j; im=im/y-1.5;
            zr=0;
            zi=0;

            for (iter=0; iter <= 9;) {
                pom=(zrzr-zizi)+re;
                zi=(2zrzi)+im;
                zr=pom;
                if (zrzr+zizi >= 4) break;
                iter++;
            }
            p[i+j*x] = (255<<24)|((25*iter) << 16) | ((255-20*iter) << 8) | 100+10*iter;
        }
    }
    return createImage(new MemoryImageSource(x, y, p, 0, x));
}

public void init() {
   i = MandelBrot(400,400);
}

public void paint(Graphics g) {
   g.drawImage(i,0,0,java.awt.Color.black,this);
   }
}

Zajímavé útvary netvoří jen rovnice z=z2+c. Známe různé variace dané např. změnou exponentu či úpravou původního vzorce ( z=sin(z2)+c, z=cos(z2)+c). Ještě zajímavější fraktály vzniknou, jestliže mocníme exponentem komplexním, ne reálným. Pak totiž začnou vznikat čtyřrozměrné útvary. Pokud vyříznete část 4D prostoru 3D prostorem, pak můžete spatřit, co jste ještě neslyšeli.

Následující bajty tohoto souboru obsahují nejprve "normální" m-set, a pak její variace:

Jiná paleta m-set

Malá modifikace vzorce

Ještě menší modifikace

Má oči po babičce

Polynomické fraktály tvoří fascinující obrazce a pokud máte dobrou tiskárnu, můžete si vytapetovat pokojíček.

Juliovy množiny

Jedná se o polynomický fraktál, stejně jako m-set. Podobnost zde nekončí. Jset (čeho to je asi zkratka?) vzniká na základě stejného vztahu jako M-set, tedy z=z2+c, kde z i c jsou komplexní čísla. Počáteční hodnota z ale není 0, ale rovná se pozici vykreslovaného bodu a c je libovolná konstanta, která se po dobu výpočtu celé množiny nemění. Na konci výpočtu obarvíme pochopitelně bod definovaný počáteční hodnotou z. Tím se od Mandelbrotovy množiny liší. Každá J-set vlastně představuje jeden bod v Mandelbrotově množině. M-set představuje jakýsi ucelený katalog všech Jset. Juliových množin je díky způsobu volby konstanty c nekonečný počet. Jejich historie je poněkud delší než historie m-set. Na průkopnické práce Gastona Julia a Pierre Fatoua ale pohlíželi tehdejší vědci s despektem a často je označovali jako matematické nestvůry. Uznání tedy došlo až později.

Hranice množiny je stejně jako u m-set fraktálem jehož Hausdorffova dimenze je rovna dvěma. Výsledný obrázek je silně závislý na konstantě c, takže pro jen nepatrně se lišící c můžete dostat i velice rozdílné výsledky (další příklad deterministického chaosu).

Jeden barevný příklad Juliovy množiny.

Celý soubor tentokrát černobílých obrázků.

Některé "zoomy" dokážou opravdu překvapit.

Pokud se v rovnici z=z2+c uspokojíte s reálným exponentem (2) a použijete komplexní, získáte útvar, pro jehož popis musíte zavést souřadnicový systém v hyperkomplexní rovině. Aby jste se mohli pokochat, musíte nejdříve vyříznout část 4D prostoru 3D prostorem. Pak už dokážete počítač přinutit vygenerovat obrázek. A že to za tu námahu stojí, potvrzuje následující obrázek.

Jset ve 4D

Tak tohle na ulici neuvidíte.

V další lekci, IFS fraktály, jsme probrali Cantorovo mračno, Sierpinského trojúhelník, Sierpinského kobereček, Kapradí a Kochova vločka.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 0x (52.35 kB)
Aplikace je včetně zdrojových kódů

 

Předchozí článek
Obecná teorie a dělení fraktálů
Všechny články v sekci
Fraktály
Přeskočit článek
(nedoporučujeme)
IFS fraktály
Článek pro vás napsal Tomáš Sixta
Avatar
Uživatelské hodnocení:
3 hlasů
Jméno jeho jest Tomáš Sixta. Narodil se v roce 1987 krátce po výbuchu Černobylu v Kolíně u Veltrub. Vystudoval Základní školu ve Veltrubech a nyní studuje na gymnáziu Kolín.
Aktivity

 

 

Komentáře

Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zatím nikdo nevložil komentář - buď první!