Hlavní navigace

Fraktály v počítačové grafice VIII

14. 12. 2005
Doba čtení: 10 minut

Sdílet

V dnešním pokračování seriálu o fraktálech používaných (nejenom) v počítačové grafice budeme pokračovat v popisu dynamických systémů, u nichž se provádí zobrazování jejich orbitů v rovině nebo třídimenzionálním prostoru. Popíšeme si tvorbu zajímavých obrazců pomocí zobecněného dynamického systému, zobrazení orbitů Mandelbrotovy množiny (takzvané Mandelbrotovo mračno) a zobrazení dynamického systému nazvaného Popcorn.

Obsah

1. Orbity dynamického systému zobrazované pro různé počáteční podmínky
2. Barevné zvýraznění orbitů
3. Dynamický systém nazvaný Popcorn zobrazený v ploše
4. Barevné zvýraznění dynamického systému Popcorn
5. Mandelbrotovo mračno
6. Obsah dalšího pokračování tohoto seriálu

1. Orbity dynamického systému zobrazované pro různé počáteční podmínky

Všechny dříve popsané dynamické systémy byly ve své podstatě zobrazovány tím způsobem, že se pro zadané počáteční podmínky (a samozřejmě i další parametry systému) vykreslil jejich orbit. Prozatím jedinou výjimkou z tohoto pravidla byl dynamický systém nazvaný Kamtorus (viz předchozí část tohoto seriálu, první a čtvrtá kapitola), u kterého se jeden parametr postupně měnil a pro jeho každou hodnotu se vykreslil jiný orbit. Při programové implementaci byly použity dvě do sebe vložené programové smyčky, ve vnější smyčce se měnil vybraný parametr systému, vnitřní smyčka zajišťovala vykreslení orbitu pro tento parametr. Ideu naznačenou u systému Kamtorus je možné zobecnit pro prakticky libovolný dynamický systém – parametry systému se podle nějakého pravidla postupně mění a pro každý počáteční vektor (tj. souhrn parametrů) se vykreslí zvláštní orbit, který může mít pro odlišení přiřazenu jinou barvu než předchozí orbity. Pro rovinné obrazce se mnohdy používá značně zjednodušený dynamický systém, jež vychází ze soustavy dvou diferenciálních rovnic ve kterých se vyskytuje obecná funkcef(x):

x'(t)=-f(y(t))
y'(t)=f(x(t))

Tuto soustavu je možné převést do diskrétní podoby zavedením konstantní změny času dt (tj. převodem diferenciálních rovnic na rovnice diferenční):

xn+1=xn-dt × f(yn)
yn+1=yn+dt × f(xn)

Poslední dva uvedené výrazy ve své podstatě odpovídají výrazům použitým v programové iterační smyčce, jedná se tedy o podobu vhodnou pro algoritmické zpracování, samozřejmě až po nahrazení obecné funkce f(x) konkrétní matematickou funkcí, jejíž definiční obor by měl odpovídat oboru reálných čísel. V následující proceduře jsou počáteční podmínky (tj. body x0 a y0) zvoleny tak, že v rovině vytvoří pravidelnou mřížku:

//-----------------------------------------------------------------------------
// Překreslení dynamického systému
//-----------------------------------------------------------------------------
void recalcDynamic(pixmap *pix,                  // pixmapa pro vykreslování
                   double a, double b,           // parametry funkce f(x)
                   int    maxiter,               // maximální počet iterací
                   double scale,                 // měřítko obrazce
                   double panx,                  // posun obrazce v ploše
                   double pany)
{
    double x0, y0;                               // proměnné obsahující počáteční podmínky
    double x2;
    double x, y;
    double dt=0.01;                              // integrační krok
    int    iter;                                 // počitadlo iterací
    for (y0=MINY; y0<MAXY; y0+=(MAXY-MINY)/(double)STEPS) {
        for (x0=MINX; x0<MAXX; x0+=(MAXX-MINX)/(double)STEPS) {
            double x=x0;                         // nastavení počátečních podmínek
            double y=y0;                         // pro daný orbit
            for (iter=0; iter<maxiter; iter++) { // vnitřní iterační smyčka
                x2=x-dt*fk(y,a,b);
                y=y+dt*fk(x,a,b);
                x=x2;
                addluminance(pix, x*scale+panx, y*scale+pany);
            }
        }
    }
} 

Procedura recalcDynamic() je použita i v dnešním prvním demonstračním příkladu, ve kterém je za obecnou funkci f(x) dosazena následující funkce se dvěma dalšími parametry a a b:

//-----------------------------------------------------------------------------
// Funkce použitá při výpočtu orbitů dynamického systému
//-----------------------------------------------------------------------------
double fk(double k, double a, double b)
{
    return sin(k+a*sin(b*k));
} 
Frac 08 - 1

Obrázek 1: Orbity dynamického systému zobrazované pro různé počáteční podmínky

Zdrojový kód prvního demonstračního příkladu je uložený ke stažení, k dispozici je i HTML verze se zvýrazněnou syntaxí. Po spuštění tohoto demonstračního příkladu se provede přepočet celého obrazce. Vzhledem k velkému počtu iterací a poměrně husté mřížce bodů vytvářejících počáteční podmínky trvá přepočet delší dobu. Podobně jako u dynamického systémuPickover a Latoocarfian je použita vykreslovací metoda, při které se nevykreslují přímo barvy jednotlivých vypočtených bodů, ale zvyšují se jejich intenzity (světlost). Výsledkem aplikace této metody je obraz se zvýrazněnou hustotou vypočtených bodů. S rostoucím rozlišením rastrového obrázku musí narůstat i počet iterací provedených pro jednu počáteční podmínku, jakož i hustota mřížky s počátečními body. V kódu demonstračního příkladu je možné také změnit rozměry a hustotu mřížky bodů vytvářejících počáteční podmínky. K tomu slouží definice konstant uvedené na čtyřicátém šestém až padesátém řádku kódu:

#define MINX -20.0
#define MAXX  20.0
#define MINY -20.0
#define MAXY  20.0
#define STEPS 50 
Frac 08 - 2

Obrázek 2: Další varianta tohoto dynamického systému

Po překladu a spuštění prvního demonstračního příkladu je možné používat několik klávesových zkratek, které jsou přehledně uvedeny v tabulce:

Klávesy použité v prvním demonstračním příkladu
Klávesa Význam
1 zmenšení hodnoty parametru a o jednu desetinu
2 zvětšení hodnoty parametru a o jednu desetinu
3 zmenšení hodnoty parametru b o jednu desetinu
4 zvětšení hodnoty parametru b o jednu desetinu
< snížení počtu iterací pro každou počáteční podmínku
> zvýšení počtu iterací pro každou počáteční podmínku
Page Up změna měřítka obrázku
Page Down změna měřítka obrázku
šipky posun obrázku
S uložení rastrového obrázku do externího souboru
Q ukončení tohoto demonstračního příkladu
Esc má stejný význam jako klávesa Q
Frac 08 - 3

Obrázek 3: Třetí varianta tohoto dynamického systému

2. Barevné zvýraznění orbitů

Nepatrnou změnou ve výše uvedené proceduře recalcDynamic()je možné dosáhnout barevného zvýraznění jednotlivých orbitů. Místo postupného zvyšování intenzity pixelů se pixely vykreslí barevně, například tak, že červená barevná složka bude odpovídat y-ové souřadnici počátečního bodu, modrá barevná složka x-ové souřadnici počátečního bodu a konečně zelená barvová složka provedené iteraci. Pozměněná procedura recalcDynamic() vypadá následovně:

//-----------------------------------------------------------------------------
// Překreslení dynamického systému
//-----------------------------------------------------------------------------
void recalcDynamic(pixmap *pix,                  // pixmapa pro vykreslování
                   double a, double b,           // parametry funkce f(x)
                   int    maxiter,               // maximální počet iterací
                   double scale,                 // měřítko obrazce
                   double panx,                  // posun obrazce v ploše
                   double pany)
{
    double x0, y0;                               // proměnné obsahující počáteční podmínky
    double x2;
    double x, y;
    double dt=0.01;                              // integrační krok
    int    iter;                                 // počitadlo iterací
    for (y0=MINY; y0<MAXY; y0+=(MAXY-MINY)/(double)STEPS) {
        for (x0=MINX; x0<MAXX; x0+=(MAXX-MINX)/(double)STEPS) {
            double x=x0;                         // nastavení počátečních podmínek
            double y=y0;                         // pro daný orbit
            for (iter=0; iter<maxiter; iter++) { // vnitřní iterační smyčka
                x2=x-dt*fk(y,a,b);
                y=y+dt*fk(x,a,b);
                x=x2;
                putpixel(pix, x*scale+panx, y*scale+pany, (y0-MINY)*255.0/(MAXY-MINY), iter*255.0/maxiter, (x0-MINX)*255.0/(MAXX-MINX));
            }
        }
    }
} 
Frac 08 - 4

Obrázek 4: Obarvená varianta předchozího dynamického systému

3. Dynamický systém nazvaný Popcorn zobrazený v ploše

Změnou funkce f(x) v předchozím dynamickém systému složitějšími vztahy

xn+1=xn – H × sin(yn + tan(cr × yn)) – H × sin(xn + tan(ci × xn))

yn+1=yn – H × sin(xn + tan(cr × xn)) – H × sin(yn + tan(ci × yn))

je získán nový typ dynamického systému nazývaný Popcorn. I tento dynamický systém je zobrazován tím způsobem, že se pro každou počáteční podmínku (kde množina počátečních podmínek tvoří plošnou mřížku) vykreslí orbit. V předchozí dvojici rovnic představuje člen H konstantní hodnotu zhruba odpovídající integračnímu kroku, cr a ci jsou hodnoty konstantní pouze pro jednu počáteční podmínku. Se změnou počátečních podmínek se mohou změnit i tyto hodnoty. Rozměry a hustotu mřížky s body odpovídajícími počátečním podmínkám je možné měnit přímo ve zdrojovém kódu programu na řádcích 50–56:

// změna počátečních parametrů x0 a y0
#define MINX   -3.0
#define MAXX    3.0
#define MINY   -2.25
#define MAXY    2.25
#define STEP_X  0.03
#define STEP_Y  0.03 

Počáteční nastavení i postupné změny hodnot cr a ci je možné upravit na programových řádcích 44–48:

// změna reálné a imaginární multiplikativní konstanty cr a ci
#define STEP_R 0.00
#define STEP_I 0.00
#define CR     3.0
#define CI     0.0 

Výsledná procedura, která provádí přepočet a vykreslení orbitů dynamického systému Popcorn může vypadat následovně:

//-----------------------------------------------------------------------------
// Překreslení dynamického systému Popcorn
//-----------------------------------------------------------------------------
void recalcPopcorn(pixmap *pix,              // pixmapa pro vykreslování
                  int    maxiter,            // maximální počet iterací
                  double scale,              // měřítko obrazce
                  double panx,               // posun obrazce
                  double pany)
{
    double x0, y0, x2, y2;
    double x, y;
    double cr, ci=CI;
    int iter;
    for (y0=MINY; y0<MAXY; y0+=STEP_Y) {     // "mřížka" počátečních podmínek
        cr=CR;
        for (x0=MINX; x0<MAXX; x0+=STEP_X) {
            double x=x0;
            double y=y0;
            for (iter=0; iter<maxiter; iter++) { // iterační smyčka
                x2=x-H*sin(y+tan(cr*y))-H*sin(x+tan(ci*x));
                y2=y-H*sin(x+tan(cr*x))-H*sin(y+tan(ci*y));
                x=x2;
                y=y2;
                addluminance(pix, x*scale+panx, y*scale+pany);
            }
            cr+=STEP_R;                      // změna reálné části multiplikativní konstanty
        }
        ci+=STEP_I;                          // změna imaginární části multiplikativní konstanty
    }
} 
Frac 08 - 5

Obrázek 5: Orbity dynamického systému Popcorn zobrazované pro různé počáteční podmínky

Vykreslení orbitů dynamického systému Popcorn je implementováno ve druhém demonstračním příkladu (HTML verze se zvýrazněnou syntaxí). Po překladu a spuštění tohoto demonstračního příkladu se provede výpočet s následným zobrazením dynamického systému, přičemž je použita stejná vykreslovací metoda jako v prvním demonstračním příkladu – zobrazení hustoty vypočtených bodů.

Frac 08 - 6

Obrázek 6: Další varianta dynamického systému Popcorn

Frac 08 - 7

Obrázek 7: Další varianta dynamického systému Popcorn

4. Barevné zvýraznění dynamického systému Popcorn

Proceduru recalcPopcorn() je možné upravit tak, aby se jednotlivé orbity barevně zvýraznily. Je to provedeno tím způsobem, že jednotlivé pixely jsou obarveny podle hodnot počátečních podmínek a právě probíhající iterace. Záporem tohoto způsobu zobrazení je, že se jednotlivé překrývající se body vzájemně překreslují, takže se mnoho informací o systému ztratí, nehledě na to, že výsledný obrázek je závislý na způsobu výběru počátečních podmínek.

//-----------------------------------------------------------------------------
// Překreslení dynamického systému Popcorn
//-----------------------------------------------------------------------------
void recalcPopcorn(pixmap *pix,              // pixmapa pro vykreslování
                  int    maxiter,            // maximální počet iterací
                  double scale,              // měřítko obrazce
                  double panx,               // posun obrazce
                  double pany)
{
    double x0, y0, x2, y2;
    double x, y;
    double cr, ci=CI;
    int iter;
    for (y0=MINY; y0<MAXY; y0+=STEP_Y) {     // "mřížka" počátečních podmínek
        cr=CR;
        for (x0=MINX; x0<MAXX; x0+=STEP_X) {
            double x=x0;
            double y=y0;
            for (iter=0; iter<maxiter; iter++) { // iterační smyčka
                x2=x-H*sin(y+tan(cr*y))-H*sin(x+tan(ci*x));
                y2=y-H*sin(x+tan(cr*x))-H*sin(y+tan(ci*y));
                x=x2;
                y=y2;
                putpixel(pix, x*scale+panx, y*scale+pany, (y0-MINY)*255.0/(MAXY-MINY), iter*255.0/maxiter, (x0-MINX)*255.0/(MAXX-MINX));
            }
            cr+=STEP_R;                      // změna reálné části multiplikativní konstanty
        }
        ci+=STEP_I;                          // změna imaginární části multiplikativní konstanty
    }
} 
Frac 08 - 8

Obrázek 8: Obarvená varianta dynamického systému Popcorn

5. Mandelbrotovo mračno

Graficky velmi zajímavé orbity obsahuje i známá Mandelbrotova množina, kterou se budeme podrobněji zabývat v dalších pokračováních tohoto seriálu. Při vykreslování orbitů Mandelbrotovy množiny (orbity zobrazené současně pro různé počáteční podmínky se zde nazývají Mandelbrotovo mračno) se vychází ze vztahu:

zn+1=zn2+c

kde c představuje hodnotu konstantní pro daný orbit a znc leží v komplexní rovině. Se změnou konstanty c se radikálně mění i s ní související orbit. Prakticky se hodnota konstanty c pohybuje v rozsahu -2–2i do2+2i (i je imaginární jednotka), množina používaných hodnot v komplexní rovině tvoří čtverec. V níže uvedené funkci je vztah pro Mandelbrotovu množinu rozepsán pro reálnou a imaginární složku. Kromě toho je zavedena další ukončující podmínka pro iterační smyčku: v případě, že absolutní hodnota zn přesáhne hodnotu 2, iterační smyčka se ukončí. Důvody pro tuto podmínku si podrobně vysvětlíme v dalších pokračováních. Další podmínkou je stanoveno, že samotné vykreslování orbitů začne až po dvacáté iteraci. Tato hodnota, která byla zjištěna empiricky, zajistí, že se každý orbit dostatečně přiblíží ke svému atraktoru a výsledný obrázek nebude zatížen body zdánlivě náhodně rozmístěnými v ploše.

//-----------------------------------------------------------------------------
// Překreslení Mandelbrotova mračna
//-----------------------------------------------------------------------------
void recalcMandelCloud(pixmap *pix,          // pixmapa pro vykreslování
                  int    maxiter,            // maximální počet iterací
                  double scale,              // měřítko obrazce
                  double panx,               // posun obrazce
                  double pany)
{
    double zx, zy, zx2, zy2;
    double cx, cy;
    int iter;
    for (cy=MINY; cy<MAXY; cy+=STEPY) {      // "mřížka" počátečních podmínek
        for (cx=MINX; cx<MAXX; cx+=STEPX) {
            zx=zy=0;
            for (iter=0; iter<maxiter; iter++) { // iterační smyčka
                zx2=zx*zx;
                zy2=zy*zy;
                if (zx2+zy2>4.0) break;      // ukončující podmínka smyčky
                zy=2.0*zx*zy+cy;
                zx=zx2-zy2+cx;
                if (iter>20)
                    putpixel(pix, zx*scale+panx, zy*scale+pany, (cy-MINY)*255.0/(MAXY-MINY), iter*255.0/maxiter, (cx-MINX)*255.0/(MAXX-MINX));
            }
        }
    }
} 
Frac 08 - 9

Obrázek 9: Celkový pohled na Mandelbrotovo mračno

Vykreslení Mandelbrotova mračna je implementováno ve třetím demonstračním příkladu (HTML verze se zvýrazněním syntaxe). Pomocí tohoto demonstračního příkladu byl vytvořen devátý a desátý obrázek.

Frac 08 - 10

Obrázek 10: Detailní pohled na Mandelbrotovo mračno

CS24_early

6. Obsah dalšího pokračování tohoto seriálu

V devátém pokračování tohoto seriálu se budeme zabývat dynamickými systémy, jejichž orbity budou vykresleny v 3D prostoru. Mezi tyto systémy patří i známý Lorenzův a Rosslerův atraktor.

ikonka

Zajímá vás toto téma? Chcete se o něm dozvědět víc?

Objednejte si upozornění na nově vydané články do vašeho mailu. Žádný článek vám tak neuteče.

Byl pro vás článek přínosný?

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.