CodeNet / Приложения / Алгоритмы / Фракталы
Фрактальные множества [Delphi]
Вы наверное часто видели довольно хитроумные картины, на которых непонятно что изображено, но все равно необычность их форм завораживает и приковывает внимание. Как правило, это хитроумные формы не поддающиеся казалось бы какому-либо математическому описанию. Вы к примеру видели узоры на стекле после мороза или к примеру хитроумные кляксы, оставленные на листе чернильной ручкой, так вот что-то подобное вполне можно записать в виде некоторого алгоритма, а следовательно доступно объясниться с компьютером. Подобные множества называют фрактальными. Вобще, как мне известно фракталы появились не так уж давно, но сразу завоевали свою важную нишу. Фракталы не похожи на привычные нам фигуры, известные из геометрии, и строятся они по определенным алгоритмам, а эти алгоритмы с помощью компьютера можно изобразить на экране. Вобще, если все слегка упростить, то фракталы - это некое преобразование многократно примененное к исходной фигуре.
Здесь хочу остановиться на фрактальных множествах Мандельброта и Жюлиа. Изображения этих множеств не имеют каких либо четко очерченных границ. Особенностью фракталов является то, что даже маленькая часть изображения в конечном итоге представлет общее целое, особенно хорошо этот эффект можно пронаблюдать на примере множества Жюлиа. Кстати на основе этого свойства фракталов основано фрактальное сжатие данных, но эту тему разберем как-нибудь позже (когда накопиться достаточно нужного материала).
Итак приступим к самому главному, ради чего мы здесь и собрались. Как же строятся эти удивителные множества ?
Все сводится к вычислению одной единственной формулы.
Zi+1=Zi2+C
Здесь Z и C - комплексные числа. Как видно, формулы по сути представляет собой обычную рекурсию (или что-то вроде многократно примененного преобразования). Зная правила работы с комплексными числами данную формулу можно упростить и привести к следующему виду.
xi+1=xi2-yi2+a yi+1=2*xi*yi+b
Построение множества Мандельброта сводится к следующему. Для каждой точки (a,b) проводится серия вычислений по вышеприведенным формулам, причем x0 и y0 принимаются равными нулю, т.е. точка в формуле выступает в качестве константы. На каждом шаге вычиляется величина r=sqrt(x2+y2 ). Значением r ,как ни трудно заметить, является расстояние точки с координатами (x,y) от начала координат ( r=sqrt[ (x-0)2+(y-0)2] ). Исходная точка (a,b) считается принадлежащей множеству Мандельброта, если она никогда не удаляется от начала координат на какое-то критическое число. Для отображения можно подсчитать скорость удаления от центра, если например точка ушла за критическое расстояние, и в зависимости от нее окрасить исходную точку в соответствующие цвет. Полное изображение множества Мандельброта можно получить на плоскости от -2 до 1 по оси x и от -1.5 до 1.5 по оси y. Также известно, что для получения примелимой точности достаточно 100 итеарций (по теории их должно быть бесконечно много). Ниже представлен листинг функции реализующей выполнение итераций и определение принадлежности точки множеству Мандельброта, точнее на выходе мы получаем цвет для соответствующе точки. В качестве критического числа взято число 2. Чтобы не вычислять корень, мы сравниваем квадрат расстояния (r2) с квадратом критического числа, т.е. сравниваем (x2+y2) и 4.
function MandelBrot(a,b: real): TColor; var x,y,xy: real; x2,y2: real; r:real; k: integer; begin r:=0; x:=0; y:=0; k:=100; while (k>0)and(r<4) do begin x2:=x*x; y2:=y*y; xy:=x*y; x:=x2-y2+a; y:=2*xy+b; r:=x2+y2; dec(k) end; k:=round((k/100)*255); result:=RGB(k,k,k); end;Множество Жюлиа получается если зафиксировать в формуле значение комплексной константы (a+ib), которая будет одинакова для всех точек, а начальные значения x0 и y0 принимать равными значениям координатам вычисляемой точки. Листинг для множества Жюлиа приведен ниже.
function Julia(x0,y0: real): TColor; var a,b,x,y,x2,y2,xy: real; r:real; speed,k: integer; begin r:=1; a:=-0.55; b:=-0.55; x:=x0; y:=y0; k:=100; while (k>0)and(r<4) do begin x2:=x*x; y2:=y*y; xy:=x*y; x:=x2-y2+a; y:=2*xy+b; r:=x2+y2; dec(k) end; k:=round((k/100)*255); result:=RGB(k,k,k); end;
Ниже приведен листинг функции отображающий данные множества.
procedure TForm1.BitBtn2Click(Sender: TObject); var x_min,y_min,x_max,y_max,hx,hy,x,y: real; i,j,n: integer; color: TColor; begin x_min:=-1.5; x_max:=2; y_min:=-1.5; y_max:=1.5; n:=300; y:=y_min; hx:=(x_max-x_min)/n; hy:=(y_max-y_min)/n; for j:=0 to n do begin x:=x_min; for i:=0 to n do begin if rbM.Checked then color:=MandelBrot(x,y); if rbJ.Checked then color:=Julia(x,y); imPict.Picture.Bitmap.Canvas.Pixels[i,j]:=color; x:=x+hx; end; y:=y+hy; end; end;
При рассмотрении темы большую помощь оказала статья А.Колесникова "Визуализация фрактальных структур" в "Компьтерных вестях".
Оставить комментарий
Комментарии
imPict - рисунок с панели инстр (обозван)
поищи "нотации" в нете (как обзывать для читабельности текста)
Для тех, кто плохо знает Delphi, исправте
imPict.Picture.Bitmap.Canvas.Pixels[i,j]:=color;
на
imPict.Canvas.Pixels[i,j]:=color;
Просьба откликнуться всем, кто занимаеися сжатием изображений...