Hlavní navigace

Algoritmus Fractal Flame prakticky

Pavel Tišnovský 25. 7. 2006

V dnešní části seriálu dokončíme část věnovanou algoritmu Fractal Flame. Vysvětlíme si postup použitý při implementaci některých algoritmů navržených Scottem Dravesem a posléze implementovaných dalšími autory v několika programech jako QS Flame, GFlare, Apophysis či Kai's FraxFlame z balíku Kai's Power Tools 5.

Obsah

1. Implementace algoritmu Fractal Flame
2. Nelineární funkce – variace
3. Logaritmická závislost při výpočtu plošného histogramu
4. Monochromatické obrázky
5. Vícebarevné obrázky
6. Funkce pro překreslení fraktálu
7. Popis demonstračního příkladu určeného pro vykreslování algoritmem Fractal Flame
8. Obsah dalšího pokračování tohoto seriálu

1. Implementace algoritmu Fractal Flame

V předchozím pokračování tohoto seriálu jsme si uvedli teoretické informace o velmi úspěšném algoritmu Fractal Flame. Již tedy víme, že se ve své podstatě jedná o generalizaci „klasických“ systémů iterovaných funkcí Michaela Barnsleye. Vlastní princip generování obrázku však zůstal zachován – stále se používá chaotická hra (Chaos Game) neboli algoritmus náhodné procházky (RWA – Random Walk Algorithm), i když i zde došlo k několika rozšířením. Dnes na teoretický úvod navážeme a ukážeme si praktickou implementaci některých částí algoritmu Fractal Flame. Předesílám, že dále implementované algoritmy jsou mé vlastní, a z tohoto důvodu zcela přesně neodpovídají algoritmům použitým například v aplikaci Apophysis. V případě zájmu o originální algoritmy je dobré nejprve pročíst článek od Scotta Dravese (http://flam3­.com/flame_dra­ves.pdf) a posléze navštívit další stránky, například http://flam3.com/ a http://www.apop­hysis.org/.

fractals39_1

Obrázek 1: Fraktál vytvořený Scottem Dravesem pomocí algoritmu Fractal Flame

2. Nelineární funkce – variace

Nejvýraznějším rozdílem mezi klasickými systémy iterovaných funkcí IFS a fraktály typu Fractal Flame je kombinace lineárních a nelineárních funkcí pro každou transformaci. V následující tabulce jsou zobrazeny všechny nelineární funkce navržené Scottem Dravesem, které jsou používány (spolu s lineárními transformacemi) pro výpočet nových souřadnic bodů:

Označení funkce Výrazy pro výpočet souřadnic Originální název
V0(x,y) (x,y) linear
V1(x,y) (sin x, sin y) sinusoidal
V2(x,y) (x/r2, y/r2) spherical
V3(x,y) (r×cos(φ+r), r×sin(φ+r)) swirl
V4(x,y) (r×cos(2φ), r×sin(2φ)) horseshoe
V5(x,y) (φ/π, r-1) polar
V6(x,y) (r×sin(φ+r), r×cos(φ-r)) handkerchief
V7(x,y) (r×sin(φr), -r×cos(φr)) heart
V8(x,y) (φ×sin(πr)/π, φcos(πr)/π) disc
V9(x,y) ((cos φ+sin r)/r, (sin φ-cos r)/r) spiral
V10(x,y) ((sin φ)/r, (cos φ)r) hyperbolic
V11(x,y) ((sin φ)(cos r), (cos φ)(sin r)) diamond
V12(x,y) (r×sin3(φ+r), r×cos3(φ-r)) ex
V13(x,y) (r1/2×cos(φ/2+Ω), r1/2×sin(φ/2+Ω)) julia
V16(x,y) (2r/(r+1)x, 2r/(r+1)y) fisheye
V20(x,y) (cos(πx)×cosh(y), -sin(πx)×sinh(y)) cosine

V programovacím jazyku C jsou vytvořeny dvě funkce nazvané jednoduše vx() a vy(). Každá z těchto funkcí akceptuje tři parametry. Prvním parametrem je číslo variace, tj. celočíselná hodnota v rozsahu 0..20. Druhým a třetím parametrem je poloha bodu Xn v rovině, tj. jeho souřadnice x a y. Funkce vx() vrátí x-ovou polohu nového bodu Xn+1, zatímco funkce vy() vrátí jeho y-ovou souřadnici. Implementace obou zmiňovaných funkcí je poměrně jednoduchá (všimněte si výpočtu pomocných hodnot na začátcích obou funkcí):

//-----------------------------------------------------------------------------
// Výpočet x-ové souřadnice pomocí funkce Vn()
//-----------------------------------------------------------------------------
double vx(int type, double x, double y)
{
    double r=sqrt(x*x+y*y);             // vzdálenost od počátku
    double phi=atan2(y,x);              // úhel od x-ové osy
    double result;
    switch (type) {
        case 0:                         // linear
            result=x;
            break;
        case 1:                         // sinusoidal
            result=sin(x);
            break;
        case 2:                         // spherical
            result=x/(r*r);
            break;
        case 3:                         // swirl
            result=r*cos(phi+r);
            break;
        case 4:                         // horseshoe
            result=r*cos(2*phi);
            break;
        case 5:                         // polar
            result=phi/M_PI;
            break;
        case 6:                         // handkerchief
            result=r*sin(phi+r);
            break;
        case 7:                         // heart
            result=r*sin(phi*r);
            break;
        case 8:                         // disc
            result=phi*sin(M_PI*r)/M_PI;
            break;
        case 9:                         // spiral
            result=(cos(phi)+sin(r))/r;
            break;
        case 10:                        // hyperbolic
            result=sin(phi)/r;
            break;
        case 11:                        // diamond
            result=sin(phi)*cos(r);
            break;
        case 12:                        // ex
            result=r*pow(sin(phi+r),3);
            break;
        case 13:                        // Julia
            result=sqrt(r)*cos(phi/2);
            break;
        case 16:                        // fisheye
            result=2*r/((r+1)*x);
            break;
        case 20:                        // cosine
            result=cos(M_PI*x)*cosh(y);
            break;
        default:
            result=x;
            break;
    };
    return result;
} 
//-----------------------------------------------------------------------------
// Výpočet y-ové souřadnice pomocí funkce Vn()
//-----------------------------------------------------------------------------
double vy(int type, double x, double y)
{
    double r=sqrt(x*x+y*y);             // vzdálenost od počátku
    double phi=atan2(y,x);              // úhel od x-ové osy
    double result;
    switch (type) {
        case 0:                         // linear
            result=y;
            break;
        case 1:                         // sinusoidal
            result=sin(y);
            break;
        case 2:                         // spherical
            result=y/(r*r);
            break;
        case 3:                         // swirl
            result=r*sin(phi+r);
            break;
        case 4:                         // horseshoe
            result=r*sin(2*phi);
            break;
        case 5:                         // polar
            result=r-1;
            break;
        case 6:                         // handkerchief
            result=r*cos(phi-r);
            break;
        case 7:                         // heart
            result=-r*cos(phi*r);
            break;
        case 8:                         // disc
            result=phi*cos(M_PI*r)/M_PI;
            break;
        case 9:                         // spiral
            result=(sin(phi)-cos(r))/r;
            break;
        case 10:                        // hyperbolic
            result=cos(phi)/r;
            break;
        case 11:                        // diamond
            result=cos(phi)*sin(r);
            break;
        case 12:                        // ex
            result=r*pow(cos(phi-r),3);
            break;
        case 13:                        // Julia
            result=sqrt(r)*sin(phi/2);
            break;
        case 16:                        // fisheye
            result=2*r/((r+1)*y);
            break;
        case 20:                        // cosine
            result=-sin(M_PI*x)*sinh(y);
            break;
        default:
            result=y;
            break;
    };
    return result;
} 

fractals39_2

Obrázek 2: Další fraktál vytvořený Scottem Dravesem pomocí algoritmu Fractal Flame

3. Logaritmická závislost při výpočtu plošného histogramu

Pro dosažení zdánlivého trojrozměrného vzhledu obrázků je důležitá změna lineární závislosti při výpočtu barev pixelů v plošném histogramu na závislost logaritmickou. Samotný výpočet histogramu je velmi jednoduchý – v dvourozměrném poli jsou uchovávány hodnoty čítačů příslušejících jednotlivým pixelům. Při každém „zásahu“ pixelu je čítač zvýšen o jedničku. V následujících dvou kapitolách jsou ukázány implementace algoritmů pro výpočet barev v monochromatických obrázcích i obrázcích vícebarevných.

fractals39_3

Obrázek 3: Fraktál vytvořený ve známém grafickém editoru GIMP za pomoci filtru GFlare

4. Monochromatické obrázky

Práce s monochromatickými obrázky je poměrně jednoduchá. Pixely se přímo nezapisují do pixmapy určené pro vykreslování, ale do pomocného pole obsahujícího položky typu float. Toto pole uchovává hodnoty čítačů, ve kterých se mění hodnota po zavolání funkce addfloat(). Tato funkce má tvar:

//-----------------------------------------------------------------------------
// Přírůstek barvy pixelu na zadaných souřadnicích ve floatové monochromatické
// pixmapě
//-----------------------------------------------------------------------------
void addfloat(const unsigned int x, const unsigned int y)
{
    // kontrola, zda není překročena velikost pixmapy
    // (záporné hodnoty není díky převodu na unsigned int zapotřebí
    //  brát v potaz)
    if (x>=PIXMAP_WIDTH || y>=PIXMAP_HEIGHT) return;
    // zvýšit hodnotu čítače
    floatMap[y][x]++;
} 

Po vygenerování zadaného počtu bodů se na základě hodnot uložených v jednotlivých čítačích vybere hodnota maximální a následně se provede logaritmování a převod hodnot do rozsahu 0..255; tyto hodnoty se již mohou zapsat do cílové pixmapy, která je určena pro vykreslení na obrazovce pomocí příkazů grafické knihovny OpenGL. Funkce provádějící všechny převody mezi oběma typy pixmap vypadá následovně:

//-----------------------------------------------------------------------------
// Kopie pixelu z floatové pixmapy do pixmapy kompatibilní s OpenGL spolu
// s logaritmickým převodem měřítka
//-----------------------------------------------------------------------------
void convertFloatMap(void)
{
    float maxp=0;
    float pixelFactor;                      // faktor konverze
    int   i, j;                             // čítače smyček

    for (j=0; j<PIXMAP_HEIGHT; j++)         // zjistit maximální hodnotu uloženou
        for (i=0; i<PIXMAP_WIDTH; i++)      // ve floatové pixmapě
            if (maxp<floatMap[j][i]) maxp=floatMap[j][i];

    pixelFactor=255.0/log(maxp);            // vypočítat faktor konverze

    for (j=0; j<PIXMAP_HEIGHT; j++) {       // konverze a změna na logaritmické měřítko
        for (i=0; i<PIXMAP_WIDTH; i++) {    // s tím, že výsledné barvové složky jsou
            float pixel=log(floatMap[j][i])*pixelFactor; // v rozsahu 0..255
            putpixel(pixFractalFlame, i, j, (int)pixel, (int)pixel, (int)pixel);
        }
    }
} 

fractals39_4

Obrázek 4: Monochromatický fraktál vytvořený ve známém grafickém editoru GIMP za pomoci filtru GFlare

5. Vícebarevné obrázky

Vícebarevné obrázky se od obrázků monochromatických liší pouze tím, že místo jednoho barevného kanálu obsahují kanály tři; pro každou základní barvovou složku jeden. Z toho důvodu se nepatrně pozmění jak funkce pro zápis „zásahu“ jednoho pixelu, tak i funkce provádějící převod na logaritmické měřítko. Na rozdíl od Scotta Dravese ve svých funkcích každou barvovou složku převádím zvlášť, originální algoritmy používaly pouze jeden faktor konverze. Funkce, která je zavolána pro zápis „zásahu“ pixelu, má následující tvar:

//-----------------------------------------------------------------------------
// Přírůstek barvy pixelu na zadaných souřadnicích ve floatové pixmapě
// typu RGB
//-----------------------------------------------------------------------------
void addfloatRGB(const unsigned int x, const unsigned int y, int r, int g, int b)
{
    // kontrola, zda není překročena velikost pixmapy
    // (záporné hodnoty není díky převodu na unsigned int zapotřebí
    //  brát v potaz)
    if (x>=PIXMAP_WIDTH || y>=PIXMAP_HEIGHT) return;
    // zvýšit hodnotu všech tří čítačů
    floatMapRGB[y][x][0]+=r;
    floatMapRGB[y][x][1]+=g;
    floatMapRGB[y][x][2]+=b;
} 

V parametrech r, g a b jsou předány přírůstky, které se mají přičíst k hodnotám uloženým v jednotlivých čítačích. Pro většinu IFS systémů je vhodné hodnoty zvyšovat o jednotku, tj. všechny zmiňované parametry budou rovny r=g=b=1. V některých případech však může být vhodné některou barvovou složku více zvýraznit a nastavit například parametr r na trojku. Funkce pro přepočet hodnot z původní pixmapy do pixmapy vhodné pro vykreslení, je také složitější, neboť místo jedné hodnoty platné pro daný pixel se vždy počítá s vektorem tří hodnot. Tomu také odpovídají použité datové typy a vložené smyčky:

//-----------------------------------------------------------------------------
// Kopie pixelů v pixmapě tak, aby se změnila lineární závislost mezi počtem
// zásahů pixelů na závislost logaritmickou
//-----------------------------------------------------------------------------
void convertFloatMapRGB(void)
{
    float max[3]={0, 0, 0};                 // vektor maximálních hodnot
    float factor[3];                        // vektor konverzních faktorů
    int   i, j, k;

    for (j=0; j<PIXMAP_HEIGHT; j++)         // zjistit maximální hodnoty uložené
        for (i=0; i<PIXMAP_WIDTH; i++)      // ve floatové pixmapě
            for (k=0; k<3; k++)
                if (max[k]<floatMapRGB[j][i][k]) max[k]=floatMapRGB[j][i][k];

    for (k=0; k<3; k++)                     // vypočítat vektor faktorů konverze
        factor[k]=255.0/log(max[k]);

    for (j=0; j<PIXMAP_HEIGHT; j++) {       // převod pixmapy
        for (i=0; i<PIXMAP_WIDTH; i++) {
            float pixel[3];
            for (k=0; k<3; k++)
                pixel[k]=log(floatMapRGB[j][i][k])*factor[k];
            putpixel(pixFractalFlame, i, j, (int)pixel[0], (int)pixel[1], (int)pixel[2]);
        }
    }
} 

fractals39_5

Obrázek 5: Trojice fraktálů typu Fractals Flames vytvořená v grafickém editoru GIMP (sloučení provedeno pomocí vrstev)

6. Funkce pro překreslení fraktálu

Funkce, která provádí překreslení fraktálu podle algoritmu „Fractal Flames“, využívá všechny výše zmíněné céčkovské funkce. Každý systém iterovaných funkcí je pro jednoduchost popsán polem, přičemž každý řádek pole obsahuje informace o jedné transformaci (počet transformací je vždy roven třem, je však možné provést rozšíření na větší či naopak menší počet transformací). Každá transformace je popsána sedmisložkovým vektorem; úvodní šestice složek popisuje lineární transformaci:

(xn+1, yn+1)=(aixn+byn+ci, dixn+eiyn+fi)

zatímco v poslední složce vektoru je uložen index nelineární transformace (variace), která rozšiřuje výše uvedenou transformaci lineární:

(xn+1, yn+1)=(aixn+byn+ci, dixn+eiyn+fi)

Přepočet vypadá následovně:

//-----------------------------------------------------------------------------
// Překreslení fraktálu typu FractalFlame
//-----------------------------------------------------------------------------
void recalcFractalFlame( pixmap *pix,               // pixmapa pro vykreslování
                  int    maxiter,                   // maximální počet iterací
                  double scale,                     // měřítko obrazce
                  double xpos,                      // posun obrazce
                  double ypos,
                  int    type,                      // vybraný IFS systém
                  int    rf, int gf, int bf,        // příznaky barvových složek
                  int    dr, int dg, int db,        // přírustky barvových složek
                  DrawType drawType)                // způsob vykreslení IFS systému
{
    int    iter=0;                                  // počitadlo iterací
    int    threshold=50;                            // hranice počtu iterací pro vykreslování

    double x, y;                                    // poloha iterovaného bodu
    double xn, yn;                                  // nová poloha iterovaného bodu
    int    k;                                       // číslo vybraného řídicího bodu

    unsigned char red=rf ? dr : 0;                  // reálné přírůstky barvových složek
    unsigned char green=gf ? dg : 0;
    unsigned char blue=bf ? db : 0;

    double coefs[][3][7]={                          // koeficienty jednotlivých transformací
        {
            { 0.500000,  0.0000000,  0.000000,  0.5000000,  0.000000,  0.000000,  2},
            { 0.500000,  0.0000000,  0.000000,  0.5000000,  0.000000,  1.000000,  0},
            { 0.500000,  0.0000000,  0.000000,  0.5000000,  1.000000,  1.000000,  0}
        },
        {
            { 0.983960,  0.2983280,  0.359416, -0.5835410, -0.850590, -0.378754,  0},
            {-0.900388,  0.2930630,  0.397598,  0.0225629,  0.465126, -0.277212,  9},
            {-0.329863, -0.0855261, -0.369381, -0.8583790,  0.977861,  0.547595,  3},
        },
        {
            { 0.562482,  0.3978610, -0.539599,  0.5010880, -0.429920, -0.112404,  2},
            { 0.830039, -0.4961740,  0.162480,  0.7504680,  0.910220,  0.288389,  2},
            { 1.000000,  0.0000000,  0.000000,  1.0000000,  0.000000,  0.000000,  0},
        },
        {
            { 0.983960,  0.2983280,  0.359416, -0.5835410, -0.850590, -0.378754,  2},
            { 0.830039, -0.4961740,  0.162480,  0.7504680,  0.910220,  0.288389,  2},
            { 0.500000,  0.0000000,  0.000000,  0.5000000,  1.000000,  1.000000,  0}
        },
        {
            { 0.983960,  0.2983280,  0.359416, -0.5835410, -0.850590, -0.378754,  3},
            { 0.830039, -0.4961740,  0.162480,  0.7504680,  0.910220,  0.288389,  3},
            { 0.500000,  0.0000000,  0.000000,  0.5000000,  1.000000,  1.000000,  3}
        },
        {
            { 0.500000, -0.4000000,  0.000000,  0.5000000,  0.000000,  0.000000,  20},
            { 0.500000,  0.1000000,  0.000000,  0.5000000,  0.000000,  0.300000,  3},
            { 0.500000,  0.0000000,  0.100000,  0.4000000,  0.500000,  1.000000,  5}
        },
        {
            { 0.983960,  0.2983280,  0.359416, -0.5835410, -0.850590, -0.378754,  1},
            {-0.900388,  0.2930630,  0.397598,  0.0225629,  0.465126, -0.277212,  2},
            {-0.329863, -0.0855261, -0.369381, -0.8583790,  0.977861,  0.547595,  3}
        },
        {
            { 0.983960,  0.2983280,  0.359416, -0.5835410, -0.850590, -0.378754,  4},
            {-0.900388,  0.2930630,  0.397598,  0.0225629,  0.465126, -0.277212,  5},
            {-0.329863, -0.0855261, -0.369381, -0.8583790,  0.977861,  0.547595,  6}
        },
        {
            { 0.983960,  0.2983280,  0.359416, -0.5835410, -0.850590, -0.378754,  7},
            {-0.900388,  0.2930630,  0.397598,  0.0225629,  0.465126, -0.277212,  8},
            {-0.329863, -0.0855261, -0.369381, -0.8583790,  0.977861,  0.547595,  9}
        },
        {
            { 0.983960,  0.2983280,  0.359416, -0.5835410, -0.850590, -0.378754,  10},
            {-0.900388,  0.2930630,  0.397598,  0.0225629,  0.465126, -0.277212,  11},
            {-0.329863, -0.0855261, -0.369381, -0.8583790,  0.977861,  0.547595,  12}
        },
    };
    unsigned char pal[8][3]={                       // barvová paleta
        {0xff, 0x00, 0x00},
        {0x00, 0xff, 0x00},
        {0x00, 0x00, 0xff},
        {0xff, 0xff, 0x00},
        {0x00, 0xff, 0xff},
        {0xff, 0x00, 0xff},
        {0xff, 0xff, 0xff},
        {0x80, 0x80, 0x80},
    };

    x=0;
    y=0;                                            // nastavení počáteční polohy bodu
    srand(0);                                       // v rovině

    while (iter++<maxiter*100) {                    // iterační smyčka
        k=rand()%3;                                 // zvolit jednu ze tří transformací
        xn=x*coefs[type][k][0]+y*coefs[type][k][2]+coefs[type][k][4]; // aplikovat lineární
        yn=x*coefs[type][k][1]+y*coefs[type][k][3]+coefs[type][k][5]; // transformaci
        x=vx((int)coefs[type][k][6], xn, yn);       // aplikovat nelineární transformaci
        y=vy((int)coefs[type][k][6], xn, yn);
        if (iter>threshold) {                       // je-li dosaženo hranice iterací
            double xx=x*scale+xpos;
            double yy=y*scale+ypos;
            switch (drawType) {                     // výběr vykreslovacího režimu
                case IterPutPixel:
                    putpixel(pix, xx, yy, rf ? 0xff:0x00, gf ? 0xff:0x00, bf ? 0xff:0x00);
                    break;
                case IterAddPixel:
                    addpixel(pix, xx, yy, red, green, blue);
                    break;
                case IterLogPixel:
                    addfloat(xx, yy);
                    break;
                case TransfPutPixel:
                    putpixel(pix, xx, yy, pal[k&7][0], pal[k&7][1], pal[k&7][2]);
                    break;
                case TransfAddPixel:
                    addpixel(pix, xx, yy, (!!pal[k&7][0])*dr, (!!pal[k&7][1])*dg, (!!pal[k&7][2])*db);
                    break;
                case TransfLogPixel:
                    addfloatRGB(xx, yy, (!!pal[k&7][0]), (!!pal[k&7][1]), (!!pal[k&7][2]));
                    break;
                default:
                    break;
            }
        }
        x=xn;
        y=yn;
    }
    // u logaritmických převodů provést finální konverzi pixmap
    if (drawType==IterLogPixel) convertFloatMap();
    if (drawType==TransfLogPixel) convertFloatMap2();
} 

fractals39_6

Obrázek 6: Obrázek vytvořený za pomoci dnešního demonstračního příkladu (po inverzi)

7. Popis demonstračního příkladu určeného pro vykreslování algoritmem Fractal Flame

Všechny výše uvedené funkce jsou implementovány v dnešním demonstračním příkladu. Po překladu a spuštění tohoto demonstračního příkladu se zobrazí první obrázek vytvořený pomocí algoritmu „Fractal Flame“, který má rozlišení 512×384 pixelů. Pomocí klávesnice (viz tabulka s popisem ovládání) je možné měnit lineární a nelineární funkce, pomocí nichž je obraz IFS systému definován. Také je možné měnit způsob vybarvení jednotlivých pixelů, maximální počet iterací, přírůstky barvových složek atd. Na sedmém obrázku je zobrazen screenshot spuštěného demonstračního příkladu. S demonstračním příkladem je možné laborovat i změnou koeficientů lineárních a nelineárních transformací, které jsou uloženy v poli coefs ve funkci recalcFractal­Flame(). Nejjednodušší a nejvýraznější je změna posledního koeficientu, který určuje typ nelineární transformace, tj. funkci variace.

fractals39_7

Obrázek 7: Screenshot demonstračního příkladu

Ovládání dnešního demonstračního příkladu pomocí klávesnice je sepsáno v následující tabulce:

Klávesová zkratka Význam klávesové zkratky
F1 výběr vykreslovací metody s konstantní barvou (IterPutPixel)
F2 výběr vykreslovací metody s plošným histogramem (IterAddPixel)
F3 výběr vykreslovací metody s plošným histogramem s logaritmickou charakteristikou (IterLogPixel)
F4 výběr vykreslovací metody s barvou pixelů závisející na transformaci (TransfPutPixel)
F5 výběr vykreslovací metody kombinující plošný histogram s barvou transformace (TransfAddPixel)
F6 výběr vykreslovací metody kombinující plošný histogram s barvou transformace, ale s logaritmickou závislostí (TransfLogPixel)
F7 snížení změny červené barvové složky při tvorbě plošného histogramu
F8 zvýšení změny červené barvové složky při tvorbě plošného histogramu
F9 snížení změny zelené barvové složky při tvorbě plošného histogramu
F10 zvýšení změny zelené barvové složky při tvorbě plošného histogramu
F11 snížení změny modré barvové složky při tvorbě plošného histogramu
F12 zvýšení změny modré barvové složky při tvorbě plošného histogramu
S uložení rastrového obrázku s fraktálem do externího souboru
Q ukončení demonstračního příkladu
Esc ukončení demonstračního příkladu
, snížení maximálního počtu iterací o hodnotu 1000
. zvýšení maximálního počtu iterací o hodnotu 1000
< snížení maximálního počtu iterací o hodnotu 10000
> zvýšení maximálního počtu iterací o hodnotu 10000
R povolení/zákaz použití červené barvové složky při vykreslování
G povolení/zákaz použití zelené barvové složky při vykreslování
B povolení/zákaz použití modré barvové složky při vykreslování
posun obrazce s fraktálem o pět pixelů doleva
posun obrazce s fraktálem o pět pixelů doprava
posun obrazce s fraktálem o pět pixelů nahoru
posun obrazce s fraktálem o pět pixelů dolů
Page ↑ změna měřítka obrazce o 10% (zvětšení)
Page ↓ změna měřítka obrazce o 10% (zmenšení)
0 výběr první sady transformací IFS systému
1 výběr druhé sady transformací IFS systému
2 výběr třetí sady transformací IFS systému
3 výběr čtvrté sady transformací IFS systému
4 výběr páté sady transformací IFS systému
5 výběr šesté sady transformací IFS systému
6 výběr sedmé sady transformací IFS systému
7 výběr osmé sady transformací IFS systému
8 výběr deváté sady transformací IFS systému
9 výběr desáté sady transformací IFS systému

fractals39_8

Obrázek 8: Další obrázek vytvořený za pomoci dnešního demonstračního příkladu (po inverzi)

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

V následujícím pokračování tohoto seriálu dokončíme poměrně rozsáhlou část věnovanou systémům iterovaných funkcí (IFS) a jejich modifikacím, tj. linearizovaným IFS a algoritmu Fractal Flame. Příště si ukážeme, jakým způsobem je možné vytvářet trojrozměrné modely těles pomocí systémů iterovaných funkcí IFS. V jednom z demonstračních příkladů také budeme vytvářet trojrozměrné scény určené pro známý raytracer POV-Ray.

fractals39_9

Obrázek 9: Téma příštího pokračování – trojrozměrné IFS
Našli jste v článku chybu?

26. 7. 2006 16:28

Cau Pavle,

to me tesi, ze se praci ve Smalltalku uzivis. Ja ted musim pouzivat ten nejmenovany mainstreamovy jazyk a zrovna pro nase ulohy (intranetove aplikace) se staticky typovany jazyk vubec nehodi - uz jenom z toho duvodu, ze mnoho metod aplikacniho serveru pracuje s typem Object, takze nejaka staticka typovost jde vis kam :-)))

Na Squeak lidi dost nadavali kvuli tomu, ze je to moloch a nejenom kvuli nedelitelnosti jadra, ale take napr. ze GUI je uplne nezavisle na hostujicim OS apod. To …



26. 7. 2006 9:09

Naštěstí mě Squeak/VisualWorks/Seaside uživí, ale když jsem nucen šáhnout příležitostně jinam, tak teče krev :-)

Paradoxně se v poslední době ve vývoji Squeaku zaměřuju na jeho modularizaci a separování jádra. Víceméně něco jako jeho částečnou (cizinec promine) degradaci na úroveň jazyků jako Ruby nebo Python. Brouzdat v image a hledat a likvidovat zapomenuté objekty jenom s textovou konzolí, to je zážitek :-)

Ale cekem se daří, už se mi podařilo vyčlenit nezbytné jádro a celkem ho pročistit, …



Podnikatel.cz: Přivýdělek u Airbnb nebo Uberu? Čekejte kontrolu

Přivýdělek u Airbnb nebo Uberu? Čekejte kontrolu

Vitalia.cz: Jak koupit Mikuláše a nenaletět

Jak koupit Mikuláše a nenaletět

Podnikatel.cz: Platební brány a EET? Stále s otazníkem

Platební brány a EET? Stále s otazníkem

DigiZone.cz: Další dva kanály nabídnou HbbTV

Další dva kanály nabídnou HbbTV

Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

120na80.cz: Pánové, pečujte o svoje přirození a prostatu

Pánové, pečujte o svoje přirození a prostatu

Měšec.cz: U levneELEKTRO.cz už reklamaci nevyřídíte

U levneELEKTRO.cz už reklamaci nevyřídíte

DigiZone.cz: Recenze Westworld: zavraždit a...

Recenze Westworld: zavraždit a...

Podnikatel.cz: Prodává přes internet. Kdy platí zdravotko?

Prodává přes internet. Kdy platí zdravotko?

DigiZone.cz: Flix TV má set-top box s HEVC

Flix TV má set-top box s HEVC

Vitalia.cz: Chtějí si léčit kvasinky. Lék je jen v Německu

Chtějí si léčit kvasinky. Lék je jen v Německu

Lupa.cz: Google měl výpadek, nejel Gmail ani YouTube

Google měl výpadek, nejel Gmail ani YouTube

Podnikatel.cz: EET: Totálně nezvládli metodologii projektu

EET: Totálně nezvládli metodologii projektu

Vitalia.cz: Baletky propagují zdravotní superpostel

Baletky propagují zdravotní superpostel

Lupa.cz: Proč firmy málo chrání data? Chovají se logicky

Proč firmy málo chrání data? Chovají se logicky

DigiZone.cz: NG natáčí v Praze seriál o Einsteinovi

NG natáčí v Praze seriál o Einsteinovi

Vitalia.cz: To není kašel! Správná diagnóza zachrání život

To není kašel! Správná diagnóza zachrání život

Měšec.cz: Finančním poradcům hrozí vracení provizí

Finančním poradcům hrozí vracení provizí

Podnikatel.cz: Víme první výsledky doby odezvy #EET

Víme první výsledky doby odezvy #EET

Podnikatel.cz: 1. den EET? Problémy s pokladnami

1. den EET? Problémy s pokladnami