28 listopada 2008

Zbiór Mandelbrota w OCamlu

Ostatnio na pracowni z programowania funkcyjnego kazano nam napisać program w OCamlu rysujący zbiór Mandelbrota.
Postanowiłem zamieścić tutaj swoje rozwiązanie dlatego, że niewiarygodne jest jakie piękne efekty możemy otrzymać za pomocą 20-linijkowego programu.
(* Mandelbrot :-) *)

#load "graphics.cma";;
open Graphics;;
open Complex;;

let conve a =
float_of_int(a) /. (640. /. 4.) -. 2.;;

let rec calc_color p zn k =
if k = 0 then 0
else if norm zn >= 2. then k
else calc_color p (add (mul zn zn) p) (k-1);;

let display () =
open_graph " 640x640";
for x = 0 to 640 do
for y = 0 to 640 do
let p = {re = conve x; im = conve y} in
let k = 8 * calc_color p p 31 in
set_color (rgb k k k);
plot x y
done
done;
let _ = read_key () in close_graph();;
Zbiorem Mandelbrota nazywamy zbiór punktów p na przestrzeni zespolonej, który spełnia warunek |zn| < 2. Przy czym z0 = p oraz zn = zn-1 * zn-1 + p dla n > 0. Przybliżenie tego zbioru otrzymujemy ustalając pewną liczbę powtórzeń m, a następnie sprawdzając, które punkty płaszczyzny spełniają z0 < 2, z1 < 2, ..., zm < 2.

Funkcja conve zamienia liczbę naturalną z przedziału [0..640] (w oknie o rozdzielczości 640x640 będziemy rysowali zbiór Mandelbrota) na liczbę rzeczywistą z przedziału [-2..2] (jeśli, któraś ze współrzędnych danego punktu jest spoza tego przedziału to punkt ten nie należy do zbioru Mandelbrota).

Funkcja calc_color liczy kolejne wartości ciągu zn dla n = 0..k i szuka najmniejszego takiego m, że zm >= 2. Funkcja zwraca k - m. Od tej wartości będzie zależał kolor na jaki pomalujemy dany punkt na płaszczyźnie (stąd nazwa).

Funkcja display tworzy okno o rozmiarach 640 x 640. Następnie dla każdego piksela w tym oknie liczymy jego współrzędne zespolone. Następnie obliczamy kolor w jakim będziemy malować ten piksel, ustawiamy pędzel na ten kolor i na końcu malujemy ten piksel na dany kolor.

O funkcyjnym paradygmacie programowania napiszę słów kilka w niedalekiej przyszłości.
Jeśli coś było niejasnego w tej notce, lub notka zawiera błąd, to będę wdzięczny za komentarze.

1 komentarz:

Unknown pisze...

Rzeczywiście, odpaliłem u siebie i wygląda prześlicznie. :)