Warning: The magic method __unset() must have public visibility and cannot be static in /mnt/data/accounts/j/jslab/data/www/notepad/__core__/lib/cfgen/texy/texy-compact.php on line 47

Warning: The magic method __isset() must have public visibility and cannot be static in /mnt/data/accounts/j/jslab/data/www/notepad/__core__/lib/cfgen/texy/texy-compact.php on line 49

Warning: The magic method __unset() must have public visibility and cannot be static in /mnt/data/accounts/j/jslab/data/www/notepad/__core__/lib/cfgen/texy/texy-compact.php on line 77

Warning: The magic method __isset() must have public visibility and cannot be static in /mnt/data/accounts/j/jslab/data/www/notepad/__core__/lib/cfgen/texy/texy-compact.php on line 79

Warning: The magic method __unset() must have public visibility and cannot be static in /mnt/data/accounts/j/jslab/data/www/notepad/__core__/lib/cfgen/texy/texy-compact.php on line 98

Warning: The magic method __isset() must have public visibility and cannot be static in /mnt/data/accounts/j/jslab/data/www/notepad/__core__/lib/cfgen/texy/texy-compact.php on line 100

Warning: The magic method __unset() must have public visibility and cannot be static in /mnt/data/accounts/j/jslab/data/www/notepad/__core__/lib/cfgen/texy/texy-compact.php on line 201

Warning: The magic method __isset() must have public visibility and cannot be static in /mnt/data/accounts/j/jslab/data/www/notepad/__core__/lib/cfgen/texy/texy-compact.php on line 203

Warning: The magic method __unset() must have public visibility and cannot be static in /mnt/data/accounts/j/jslab/data/www/notepad/__core__/lib/cfgen/texy/texy-compact.php on line 217

Warning: The magic method __isset() must have public visibility and cannot be static in /mnt/data/accounts/j/jslab/data/www/notepad/__core__/lib/cfgen/texy/texy-compact.php on line 219

Warning: The magic method __unset() must have public visibility and cannot be static in /mnt/data/accounts/j/jslab/data/www/notepad/__core__/lib/cfgen/texy/texy-compact.php on line 277

Warning: The magic method __isset() must have public visibility and cannot be static in /mnt/data/accounts/j/jslab/data/www/notepad/__core__/lib/cfgen/texy/texy-compact.php on line 279

Warning: The magic method __unset() must have public visibility and cannot be static in /mnt/data/accounts/j/jslab/data/www/notepad/__core__/lib/cfgen/texy/texy-compact.php on line 291

Warning: The magic method __isset() must have public visibility and cannot be static in /mnt/data/accounts/j/jslab/data/www/notepad/__core__/lib/cfgen/texy/texy-compact.php on line 293

Warning: The magic method __unset() must have public visibility and cannot be static in /mnt/data/accounts/j/jslab/data/www/notepad/__core__/lib/cfgen/texy/texy-compact.php on line 807

Warning: The magic method __isset() must have public visibility and cannot be static in /mnt/data/accounts/j/jslab/data/www/notepad/__core__/lib/cfgen/texy/texy-compact.php on line 809

Warning: Cannot modify header information - headers already sent by (output started at /mnt/data/accounts/j/jslab/data/www/notepad/__core__/lib/cfgen/texy/texy-compact.php:47) in /mnt/data/accounts/j/jslab/data/www/notepad/__core__/lib/http.class.php on line 8
Náhodný fraktál | Adam's Notepad

Náhodný fraktál

Na této stránce se dovíte něco o náhodném fraktálu a jak jej jednoduše vykreslovat na internetové stránce pomocí JS a <canvas>.

O co jde

Fraktál o kterém zde bude řeč, vzniká následujícím způsobem.

  1. Máme čtverec.
  2. Rozdělíme ho na 4 stejné díly.
  3. Jeden díl vynecháme.

A tak pokračujeme s každým čtvercem dál a dál…

Jako náhodný se označuje proto, že čtverec, který v každém kroku vynecháme je určen generátorem pseudonáhodného čísla.

· · ·

Ukázky

1. ukázka [obr]
Náhodný fraktál o rozměrech 512×512px, s iterací 9.
1. ukázka – iterace do hloubky
Od předchozí ukázky se liší v tom, že přednostně iteruje jednotlivé čtverce do hloubky a ne do šířky jako předchozí ukázka. To změní způsob vykreslování fraktálu.
2. ukázka [obr]
Náhodný fraktál o rozměrech 265×256px, s iterací 8. Jednotlivé iterace se liší odstínem obdobně jako předchozí ukázky, ale na rozdíl od nich, nedochází k úplnéme překreslení předchozí iterace.
3. ukázka – trojúhelník [obr]
Fraktál o rozměrech 256×256px, s iterací 8. Nejedá se ale o náhodný fraktál, ale vždy je vynechán levý horní čtverec. Výsledkem je známý pravoúhlý trojúhleník
3. ukázka – trojúhelník, iterace do hloubky
Předchozí ukázka s iterací do hloubky.
4. ukázka [obr]
Fraktál o rozměrech 512×512px, s iterací 9. Opět se nejedná o náhodný fraktál, ale vynechaný čtverec je dán hloubkou iterace, jako hloubka mod 3.
Libovolné další
Stačí, když si libovolnou stránku s ukázkou uložíte na disk a upravíte nastavení vykreslování ve zdrojovém kódu stránky.

Řešení vykreslování

Pro vykreslování je použit prvek canvas, který dnes podporuje již velká část prohlížečů (nejrozšířenější IE bohužel nikoli).

<body>

  <canvas id="platno" width="256" height="256" />

</body>

Upozornění pro OOP programátory následující kód je psán v JavaScriptu za pomoci funkcionální filozofie. Takže mě nekamenujte, když se Vám to bude zdát poněkud neobjektové. Mějte strpení, jsem nakažen LISPem :)

Nejdříve si nedefinujeme 2 pomocné funkce pro vykreslování.

function rec( x, y, a, color){
  ctx.fillStyle = color ? "white" : "black";
  ctx.fillRect(x, y, a, a);
}

Vykreslí čtverec na pozici x, y o délce strany a s bílou nebo černou barvou podle boolean hodnoty color. ctx je 2D kontext plátna, viz dále.

Druhá funkce vykreslí jeden element fraktálu na pozici x, y s délkou strany a, přičemž čtverec daný parametrem w (číslo 0 .. 3) bude bílý.

function element( x, y, a, w){
  a = Math.ceil(a/2);

  rec( x      , y       , a , color , w==0);
  rec( x + a  , y       , a , color , w==1);
  rec( x      , y + a   , a , color , w==2);
  rec( x + a  , y + a   , a , color , w==3);
}

A konečně vlastní funkce pro vykreslení fraktálu.

function frac( x, y, a, n ){

  var rnd = Math.round(Math.random()*3);        // náhodné číslo (0 .. 3)

  element(x, y, a, rnd );

  if( n-- == 0 ) return;                        // konec

  a = Math.ceil(a/2);
  if(rnd != 0) frac( x     , y     , a , n);
  if(rnd != 1) frac( x + a , y     , a , n);
  if(rnd != 2) frac( x     , y + a , a , n);
  if(rnd != 3) frac( x + a , y + a , a , n);

}

Vykreslí fraktál na pozici x, y s délkou strany a. Jedná se o rekurentní funkci, která volá sama sebe na vykreslení dílčích čtverců. Parametr n je počet volání (iterací).

Nyní už jen spustit vykreslení po načtení stránky.

var ctx;

onload = function(){
  var can = document.getElementById('can');
  ctx = can.getContext("2d");

  frac(0, 0, 256, 8);
}

Krátké, ne?

Praktické řešení

Výše uvedený rekurentní algoritmus poměrně časově náročný. Proto je lepší provádět jenotlivé kroky rekurze v časových intervalech, tím dosáhneme efektu animace.

Výhodou použití tohoto relativně neefektivního algoritmu, vyjma toho, že je velmi snadno pochopitelný, je fakt, že rozšíření o časové zpoždění je otázkou přidání jedné fce. a náhradou bloku volání ve fci. frac.

...

  if(rnd != 0) sequence( function(){ frac( x, y, a, n) });

...

Funkce sequence je implementace jaké si čekací fronty. Nebudu ji příliš rozebírat, pokud vás zajímá, koukněte se do zrojáku. Zda-li se bude fraktál vykreslovat do šířky čí do hlouby záleží na imlpementaci právě fce. sequence (pujde li o forntu nebo zásobník).