Dywany na nieograniczonej powierzchni są wynikiem działania nadzwyczaj prostych algorytmów. Powstające przy tym grafiki zaliczają się do najpiękniejszych obrazów, jakie potrafimy utworzyć za pomocą komputera. Przy tym wszystkim matematyczne implikacje formuł, które za chwilę przytoczymy, są bardzo złożone i inspirujące. Rzućmy okiem na ten świat pełen niezwykłych obrazów.
Dywany na nieograniczonej powierzchni są wynikiem działania nadzwyczaj prostych algorytmów. Powstające przy tym grafiki zaliczają się do najpiękniejszych obrazów, jakie potrafimy utworzyć za pomocą komputera. Przy tym wszystkim matematyczne implikacje formuł, które za chwilę przytoczymy, są bardzo złożone i inspirujące. Rzućmy okiem na ten świat pełen niezwykłych obrazów.

Rysunek 1. Do tej pory materiały dla programistów przygotowywałem w środowiskach C++ Builder lub Delphi. Niedawno pojawiło się nowe środowisko Borlanda o nazwie Turbo Explorer, integrujące kilka różnych języków programowania, w tym wspomniane C++ Builder i Delphi. Środowisko Turbo obszernie przedstawiliśmy w numerze 11/2006 naszego miesięcznika, załączając też komplet gotowego do pracy oprogramowania, które można bezpłatnie pobrać ze strony http://www.borland.pl. Nasze przykłady od teraz będą przygotowywane w nowym środowisku Borlanda.Zacznijmy od zdefiniowania podstawowych pojęć. Niech para rzeczywistych wartości (x, y) reprezentuje pojedynczy punkt w przestrzeni. Punkt ten gdzieś sobie spoczywa, czyli jego współrzędne (x, y) mają ustalone wartości. Ale oto współrzędne punktu trafiają do wnętrza pętli, która miliony razy nadaje im nowe wartości, przesuwając punkt w kolejne położenie. Dokąd zawędruje? Jaki ślad pozostawi po sobie? To są najważniejsze pytania stojące przed badaczem nieograniczonych dywanów.
Surowy schemat algorytmu wygląda zachęcająco:
double x, y;
x = 0;
y = 0;
for( i = 0; i < 1000000; i++)
{
putpixel( x, y);
x = f( x, y);
y = g( x, y);
}
Współrzędne punktu, tutaj na początek wyzerowane, we wnętrzu pętli o ogromnej liczbie obrotów są wykreślane jako pojedynczy piksel, a potem przekształcane za pomocą pary tajemniczych funkcji f() i g(). Proces ten jest wielokrotnie powtarzany, zatem na ekranie może się pojawić mnóstwo punktów. Wszystko zale-ży od pary funkcji f() i g()- źle dobrane wypędzą punkt nazbyt daleko, a może zmuszą do nieciekawej wędrówki po ograniczonym obszarze albo nawet nie ruszą go z miejsca.
Niezwykle istotne i zasługujące na najmocniejsze podkreślenie jest to, że nowe położenie punktu zależy wyłącznie od bieżącego położenia (porównaj rysunek 2):
Pi+1 = fun(Pi)

Rysunek 2. Punkt o pierwotnie ustalonym położeniu (tutaj spoczywający w środku układu odniesienia) jest miliony razy przesuwany w nowe miejsce za pomocą pary funkcji f () i g (). Funkcje te przekształcają wartości współrzędnych punktu, znajdując mu wciąż nową lokalizację. Tak się tka dywany iterowane. Tylko dokąd zawędruje punkt i jaki ślad po sobie pozostawi?Proces taki nazywa się iteracją położenia punktu. Iteracja jest bardzo powszechną regułą - podczas wspinaczki na strych iterujesz kolejne szczeble drabiny, a zaczynając kolejny dzień, prawdopodobnie iterujesz swoje życie. Z tego powodu nasze dywany na nieograniczonej powierzchni bywają też nazywane dywanami iterowanymi.
Nasz schemat od razu musimy trochę skorygować, bo - jak łatwo zauważyć - funkcja f() za szybko modyfikuje współrzędną x i trochę psuje robotę właśnie wchodzącej do gry funkcji g(). Wprowadźmy też do algorytmu kolory, bo właśnie po kolorach dywanów spodziewamy się najwięcej:
double xx;
TColor k;
for( i = 0; i < 1000000; i++)
{
k = daj_kolor( x, y, ?);
putpixel( x, y, k);
xx = f( x, y);
y = g( x, y);
x = xx;
}

Rysunek 3. Ten dziwny dywan powstał w wyniku iteracji położenia niebieskiego punktu, dokonywanej za pomocą pary prostych funkcji trygonometrycznych. Jego niepokojące piękno jest efektem zastosowania specyficznego algorytmu dobierania kolorów - barwa każdego punktu zależy od liczby jego odwiedzin w procesie iteracji.W schemacie pojawiła się dodatkowa zmienna xx, której zadaniem jest ochrona zmiennej x przed zbyt szybką modyfikacją. Pojawiła się też funkcja daj_kolor(), która na podstawie bieżącego położenia punktu w wymyślny sposób określa jego barwę. Trzeci argument funkcji jest tutaj symbolicznie oznaczony znakiem zapytania - kolor punktu może zależeć od tego, czego zapragniemy - od fazy Księżyca, stanu sąsiednich punktów, zaawansowania tkania dywanu (czyli aktualnej wartości indeksu pętli i). Te wszystkie zmienne okażą się bardzo przydatne i efektowne.
Na rysunku 3 widzimy efekt działania pierwszego prawdziwego programu. Oto algorytm - najpierw niezbyt ciekawego dywanu niebieskiego:
int i, max_i = 100000;
double max_x = ClientWidth/2;
double max_y = ClientHeight/2;
double x, y, xx;
x = y = 0;
for( i = 0; i < max_i; ++i)
{
Canvas -> Pixels[ x][ y] = clBlue;
xx = max_x + (max_x * sin(x/69.) + cos(y/47));
y = max_y + max_y * cos(( xx + y)/71.);
x = xx;
}