Algorytm wzrostu
-
- Andrzej Stasiewicz,
- 01.09.2005

Roślina z czynnikiem pseudolosowym, modyfikującym długość akurat wykreślanych gałązek i kąty ich wyrastania.
Naszkicujmy jeszcze program główny, wywołujący te dwie kluczowe, przed chwilą zarysowane funkcje:
String FORMULA = "AB";
int POZYCJA = 1;
rozwin();
rozwin();
rozwin();
rysuj( 100, 100, 90, 20);
Program ten najpierw ustala początkową definicję roślinki, potem trzykrotnie ją rozwija, "hodując" zupełnie nową (zapewne dłuższą) recepturę. Na koniec roślina zostaje wykreślona w punkcie ekranu o współrzędnych (100,100), rosnąc w kierunku oznaczonym kątem o wartości 90 stopni. Gałązka rośliny ma długość 20 pikseli. W algorytmie tym na uwagę zasługuje też globalna zmienna POZYCJA, informująca funkcję rysuj() o tym, który symbol z receptury FORMULA należy realizować. Jest to ważne, bo jak już wiemy, funkcja rysuj() wywołuje niekiedy samą siebie i łatwo może się pogubić w gąszczu symbolicznych znaków - genomu rośliny.
Jak to zwykle bywa, ten surowy algorytm wymaga jeszcze sporo pracy. Przede wszystkim zauważamy, że nasze rośliny w trakcie hodowli stają się coraz większe, nawet wychodzą poza ekran, a nam zdecydowanie bardziej zależy na ich komplikacji, nie powiększaniu rozmiaru - nie chcemy przecież wykreślić 20-metrowej ściany lasu... Z tym problemem poradzimy sobie bardzo prosto - na każdym etapie hodowli odpowiednio zmniejszymy długość gałązki:
dlg = 20;
rozwin();
dlg = dlg / 2;
rozwin();
dlg = dlg / 2;
rozwin();
rysuj( 100, 100, 90, dlg);

W tym bukiecie delikatnych ziół zastosowano dwa nowe chwyty - pseudolosowe mutowanie koloru za pomocą funkcji naszkicowanej w tekście oraz powielenie roślin w bukiecie przez czterokrotne wywołanie funkcji rysuj(). Gałązka typu A jest krótką linią o dużej grubości - chyba należy ją nazwać listkiem.
double mutuj( double val, double r)
{
return val +
(r - random( 2 * r * 1000 + 1) / 1000.0);
}
Funkcja mutuj() zmienia wartość val o czynnik losowy, nie większy niż parametr r i nie mniejszy niż -r. Czynnik 1000 zmniejsza tutaj ziarnistość losowania. Funkcję tę możemy choćby w następujący sposób wpleść do wcześniej przytoczonej funkcji rysuj(), odpowiedzialnej za wykreślanie rośliny:
void rysuj(int x0, int y0, double kat, int dlg)
{
...
switch( znak)
{
case 'A': // gałązka A
x1 = x0 + mutuj( dlg, 10) *
cos( mutuj( kat, 5) * M_PI / 180.);
...
Nowa długość gałązki jest tu określona zmutowaną wartością dlg +/- 10, a nowy kąt wzrastania wartością kat +/- 5. Osiągnęliśmy zmienność formy roślinnej.

Do formuły rośliny dodano dwa nowe symbole: L - skręć w lewo i R - w prawo. Inna jest też sama formuła rośliny, co widać choćby po pęczkach czterech odrostów w każdym węźle. Gałązka typu A jest zwyczajnym, zielonym odcinkiem. Gałązka typu B jest grubym, niebieskim odcinkiem z jednym, białym pikselem na końcu. Algorytm powtórzono trzykrotnie, otrzymując pęczek nierealnych polnych kwiatów.
TColor mutuj_kolor( TColor k, int r)
{
int R = GetRValue( k)
G = GetGValue( k)
B = GetBValue( k);
R = mutuj( R, r);
if ( R < 0) R = 0;
if ( R > 255) R = 255;
G = mutuj( G, r);
if ( G < 0) G = 0;
if ( G > 255) G = 255;
B = mutuj( B, r);
if( B < 0) B = 0;
if( B > 255) B = 255;
return RGB( R, G, B);
}
Funkcja ta rozkłada barwę wejściową k na składniki czerwony, zielony i niebieski. Potem każdy z nich jest niezależnie mutowany naszą wcześniejszą funkcją i sprawdzany, czy w wyniku mutacji nie przekroczył dopuszczalnego zakresu wartości amplitud barw podstawowych. Na koniec następuje synteza koloru ze zmutowanych składników R, G i B.
Możemy do gry wprowadzić więcej typów gałązek, jednocześnie określając reguły ich wzrostu oraz definiując ich interpretację wewnątrz funkcji rysuj(). Gałązki mogą mieć więcej parametrów - choćby grubość, może jakieś parametry odpowiedzialne za kształt, rozłożenie barwnych plam lub co jeszcze przyjdzie nam do głowy... Wszystko to powinno:
1. Wzrastać, czyli rozwijać się na poziomie formuły tekstowej.
2. Mutować, czyli nieoczekiwanie zmieniać swoje kolory, długości, kąty odrostu itp.
3. Na koniec dać się narysować na ekranie.
Zaprezentowane tutaj obrazy zostały wygenerowane programami, których teksty źródłowe znajdują się na krążku CD. Teksty są przygotowane w C++ Builderze. Jak zwykle, proszę nie sugerować się przedstawionymi tutaj rozwiązaniami, odważnie zapuszczając się w cyfrowy gąszcz. Czekamy na Państwa hodowlę. Prosimy przysyłać programy, fotografie, opisy, spostrzeżenia. Programy można przygotowywać w dowolnym języku i przysyłać do redakcji na adres [email protected] Wkrótce wrócimy do tego zagadnienia, a najciekawsze opracowania nagrodzimy.