Фракталы 3d |
Фракталы 3d |
Altair |
8.02.2006 11:32
Сообщение
#1
|
Ищущий истину Группа: Модераторы Сообщений: 4 824 Пол: Мужской Реальное имя: Олег Репутация: 45 |
Множество Мандельброта и множество Жюлиа.
Одним из интереснейших явлений в природе, можно по праву выделить фракталы. Более 30 лет назад, Бенуа Мандельброт ввел термин -фрактал, но до сих пор точного определения не существует. Одним из известных алгебраических фракталов, является фрактал Мандельброта (множество Мандельброта), который был так назван, в честь французского математика, упомянутого выше. Я решил рассмотреть фрактал Мандельброта и Жюлиа в трехмерном пространстве. Сначала кратно рассмотрим процедуру построения фрактального множества. Возьмем формулу z'=F(z,c) Это функцию от двух комплексных переменных z и c. Вообще говоря одна из переменных "закрепляется" при построении, и в зависимости от того. какую переменную мы закрепим, мы получим либо множество Жюлиа либо множество Мандельброта. Фактически z'=F(z,c) - чистейшая рекурсия. Но почему-то (видимо для скорости вычисления) принято использовать итерацию. В результате n итераций функции, мы получим некое значение Z которое будет предельным (вообще говоря выбирать этот предел можно произвольно... ) А само число n, будет показывать сколько итераций необходимо для достижения этого предела. Выполнив для каждой точки пространства такой процесс, мы получим не что иное как фрактал. Если z выбирается в зависимости от точки M(x,y) на плоскости, то получаем фрактал Мандельброта (при с- фиксированной), иначе, если z - константа, а c - переменная x+iy, то получим множество Жюлиа. Саму функцию f(z,c) можно вообще говоря брать любую (будем получать различные фракталы) но как пример используют f= z^2 +c; Простейшая программа рисования множества Мандельброта и Жюлиа (для построения Жюлиа, измените :{$define mandel} на {$define _mandel} например )
Но на этом останавливаться неинтересно! Что если вместо цвета, определять высоту точки над плоскостью, и посмотреть эту фигурку в 3D пространстве? Что же, так и поступим... вот текст программы, реализующий вывод множества в виде 3D поверхности. (не обращайте внимание на странный метод - построение матрицы и дальнейшее конвертирование в массив, этот лишний шаг был сделан на этапе тестирования, вопрос с памятью, так же пусть не пугает вас, я специально завысил параметры, текст программы не оптимизирован, да и цель не текст программы а множество Мандельброта) Код unit main_types; interface const _maxx = 160; _maxy = 100; maxpixelcount = _maxx*_maxy*256; type tfloat = single; tlong = longint; tint = integer; tbyte = byte; maparr = array[1.._maxx, 1.._maxy] of tbyte; tcomplex = record cmplx_x, cmplx_y :tfloat; end; tpixelarr = array[0..maxpixelcount] of tfloat; //cube { (-1,-1,-1,-1,-1,1,-1,1,-1,-1,1,1,1,-1,-1,1,-1,1, 1,1,-1,1,1,1);} tlineindex = array[0..maxpixelcount] of tint; //cube { (0,1,0,4,0,2,1,3,1,5,2,3,2,6,3,7,4,5,4,6,5,7,6,7);} implementation end. Код {$mode objfpc} unit fract; interface uses windows, graph, wincrt, main_types; function complex (re, im: tfloat ): tcomplex; procedure InitGraphMode (mode:smallint); procedure create_mandel(zoomx,zoomy,dx,dy:tfloat; var a:maparr ); implementation function complex (re, im: tfloat ): tcomplex; begin with result do begin cmplx_x:=re; cmplx_y:=im; end; end; operator + ( const cmx_1, cmx_2 : tcomplex ) r:tcomplex; begin r.cmplx_x:=cmx_1.cmplx_x+cmx_2.cmplx_x; r.cmplx_y:=cmx_1.cmplx_y+cmx_2.cmplx_y; end; operator - ( const cmx_1, cmx_2 : tcomplex ) r:tcomplex; begin r.cmplx_x:=cmx_1.cmplx_x-cmx_2.cmplx_x; r.cmplx_y:=cmx_1.cmplx_y-cmx_2.cmplx_y end; operator * ( const cmx_1, cmx_2 : tcomplex ) r:tcomplex; begin r.cmplx_x:= (cmx_1.cmplx_x*cmx_2.cmplx_x) - (cmx_1.cmplx_y*cmx_2.cmplx_y); r.cmplx_y:= (cmx_1.cmplx_x*cmx_2.cmplx_y) + (cmx_1.cmplx_y*cmx_2.cmplx_x) end; procedure InitGraphMode (mode:smallint); var gd: smallint; begin gd:= D8bit; initgraph (gd, mode, ''); SetWindowText(FindWindow(Nil,Pchar('Graph window application')),pchar('Fractals')); EnableMenuItem(GetSystemMenu(FindWindow(Nil, Pchar('Fractals')),False) ,SC_CLOSE,MF_BYCOMMAND or MF_GRAYED); end; Const color =16; iter = 50; max = 2*color; procedure create_mandel(zoomx,zoomy,dx,dy:tfloat; var a:maparr ); var z,c: tcomplex; mx,my,x,y:longint; n:integer; begin for x:=1 to _maxx do for y:=1 to _maxy do a[x,y]:=0; Mx := _maxx div 2; My := _maxy div 2; For y := -my to my do For x := -mx to mx do Begin n := 0; {$ifdef _mandel} c:=complex (x *zoomx+dx, y*zoomy +dy); z:=complex (0, 0 ); {$else} z:=complex (x* zoomx+dx, y*zoomy+dy); c:=complex(0.11, -0.66); {$ifdef dendrid} c:=complex(0,1); {$endif} {$endif} While (sqr(z.cmplx_x) + sqr(z.cmplx_Y) < max) and (n < iter) do Begin //z:=c*z - c*z*z; z:=z*z - c; //z:=z*z-complex(x *zoomx+dx, y*zoomy +dy); Inc(n); End; If n < iter then a[mx + x,my + y]:= 64 - (n mod color) else a[mx +x, my +y]:=15; end; end; end. {var gd,gm:smallint; dx,dy,zoomx, zoomy: tfloat; i,j:longint; mandel_map : maparr; begin zoomx := 0.007; zoomy := 0.007; dx := 0.5; dy := 0.0; Randomize; InitGraphMode (m800x600); create_mandel(zoomx,zoomy,dx,dy,mandel_map); for i:=1 to _maxx do for j:=1 to _maxy do putpixel(i,j,mandel_map[i,j]); readkey; CloseGraph; end.} Код {$M 99000000, 0, 0} {$mode objfpc} {$apptype gui} {$define mode1} {$define no_debugmode} uses graph,wincrt, windows, fract, main_types; const {global} kontur:boolean = false; procedure drawpixel_l(x,y: tint; points:tpixelarr; zoom: tfloat; pointcount:tint; color:tint); var sx,sy,sx1,sy1,p:tlong; begin for p:=0 to pointcount-1 do begin sx:=round(zoom*points[p*3])+x; sy:=round(zoom*points[p*3+1])+y; sx1:=round(zoom*points[(p+1)*3])+x; sy1:=round(zoom*points[(p+1)*3])+x; setcolor(color); line(sx,sy,sx1,sy1); end; end; procedure drawpixel(var mandel:maparr; x,y: tint; points:tpixelarr; zoom: tfloat; pointcount:tint; color:tint); var sx,sy,sx1,sy1,p:tlong; gv:tint; begin for p:=0 to pointcount-1 do begin sx:=round(zoom*points[p*3])+x; sy:=round(zoom*points[p*3+1])+y; {setcolor(color);} if p < pointcount -5 then // gv:=mandel[trunc(points[p*3]), trunc(points[p*3+1]) ]; // if gv>250 then gv:=31; gv:=15; if color=15 then putpixel(sx,sy,gv) else putpixel(sx,sy,color) end; end; procedure calc(var cube:tpixelarr; pointcount:tint;xan,yan,zan:tfloat); var p:tlong; xt,yt,zt:tfloat; begin for p:=0 to pointcount-1 do begin yt := cube[p*3+1] * cos(xan) - cube[p*3+2] * sin(xan); zt := cube[p*3+1] * sin(xan) + cube[p*3+2] * cos(Xan); cube[p*3+1] := Yt; cube[p*3+2] := Zt; xt := cube[p*3] * cos(Yan) - cube[p*3+2] * sin(Yan); zt := cube[p*3] * sin(Yan) + cube[p*3+2] * cos(Yan); cube[p*3] := xt; cube[p*3+2] := Zt; xt := cube[p*3] * cos(zan) - cube[p*3+1] * sin(zan); yt := cube[p*3] * sin(Zan) + cube[p*3+1] * cos(Zan); cube[p*3] := xt; cube[p*3+1] := yt end; end; procedure draw_and_calc ( x,y: tint; var points:tpixelarr; zoom: tfloat; pointcount:tint; color:tint; xan,yan,zan:tfloat ); var sx,sy,sx1,sy1:tlong; gv:tint; xt,yt,zt:tfloat; p:integer; st:byte; begin st:=4; //no color //st=3; for p:=0 to pointcount-1 do begin if (round(points[p*st+3])<>15) or (kontur=true) then begin {§ ¬Єгвл© Є®вга... } sx:=round(zoom*points[p*st])+x; sy:=round(zoom*points[p*st+1])+y; gv:=0; putpixel(sx,sy,gv); // new coords... yt := points[p*st+1] * cos(xan) - points[p*st+2] * sin(xan); zt := points[p*st+1] * sin(xan) + points[p*st+2] * cos(Xan); points[p*st+1] := Yt; points[p*st+2] := Zt; xt := points[p*st] * cos(Yan) - points[p*st+2] * sin(Yan); zt := points[p*st] * sin(Yan) + points[p*st+2] * cos(Yan); points[p*st] := xt; points[p*st+2] := Zt; xt := points[p*st] * cos(zan) - points[p*st+1] * sin(zan); yt := points[p*st] * sin(Zan) + points[p*st+1] * cos(Zan); points[p*st] := xt; points[p*st+1] := yt; sx:=round(zoom*points[p*st])+x; sy:=round(zoom*points[p*st+1])+y; gv:=round(points[p*st+3]); putpixel(sx,sy,gv+64); end; end; end; function read_from_file (fn: string; var objpoint:tpixelarr; var pixcount: tint ): boolean; var sourcefile:text; i:tint; _count:tint; begin assign( sourcefile, fn); {$I-} reset( sourcefile );{$I+} result := (ioresult=0); if ioresult =0 then begin readln( sourcefile , pixcount ); _count:=pixcount*3; for i:=0 to _count-1 do begin read( sourcefile, objpoint[i] ); end; end end; procedure convert_map(var _map:maparr; var _pmap:tpixelarr); var i,j,k:tlong; begin k:=0; for i:=1 to _maxx do for j:=1 to _maxy do begin _pmap[k]:=i; inc(k); _pmap[k]:=j; inc(k); _pmap[k]:=_map[i,j]; inc(k); end; {pixcount:=_maxx*_maxy;} end; var t:char; xan,yan,zan, zoom:tfloat; objpoint:tpixelarr; { objline :tlineindex;} pixcount,linecount: tint; filename:string; {i:integer;} dx,dy,zoomx, zoomy: tfloat; mandel_map : maparr; vp, i,j,k: integer; r:tfloat; begin zoomx := 0.02; zoomy := 0.02; dx := 0.2; dy := 0.0; {$ifdef debugmode} writeln ('create mandel map...'); {$endif} create_mandel(zoomx,zoomy,dx,dy,mandel_map); {$ifdef debugmode}writeln('ok! press any key!'); readln; {$endif} { filename:='d:/g.txt'; if not read_from_file (filename, objpoint, pixcount ) then begin writeln ('Error I\O'); halt end else begin } { for i:=0 to pixcount do write ( objpoint[i]:3); end;} {writeln('convert ...'); convert_map( mandel_map, objpoint); writeln('ok! press any key!'); } k:=-1; for i:=1 to _maxx do for j:=1 to _maxy do begin inc(k); objpoint[k]:=0; end; // writeln('zero!');readln; k:=-1; for i:=- _maxx div 2 to _maxx div 2 do for j:=- _maxy div 2 to _maxy div 2 do begin inc(k); objpoint[k]:=i; inc(k); objpoint[k]:=j; inc(k); objpoint[k]:=mandel_map[(_maxx div 2) + i, (_maxy div 2) +j]; //color inc(k); objpoint[k] :=mandel_map[(_maxx div 2) + i, (_maxy div 2) +j]; end; // writeln('ok! press any key!'); {} pixcount:=_maxx*_maxy; initgraphmode (m800x600); // initgraphmode (g1024x768x16); zoom:=exp(1); vp:=10; r:=0; repeat zan := 0.01; yan := 0.01; xan := 0.02; {$ifdef mode1} draw_and_calc (getmaxx div 2, getmaxy div 2, objpoint, zoom ,pixcount,15, xan,yan,zan); delay(10); {$else} setactivepage(1); cleardevice; calc(objpoint, pixcount,xan,yan,zan); drawpixel(mandel_map,getmaxx div 2, getmaxy div 2, objpoint, zoom ,pixcount, 15); setvisualpage(1); delay(vp); setactivepage(2); cleardevice; calc(objpoint, pixcount,xan,yan,zan); drawpixel(mandel_map,getmaxx div 2, getmaxy div 2, objpoint, zoom ,pixcount, 15); setvisualpage(2); delay(vp); {$endif} // delay(20); { drawpixel(getmaxx div 2, getmaxy div 2, objpoint, zoom ,pixcount, 0);} // cleardevice; // calc(objpoint, pixcount,xan,yan,zan); if keypressed then begin t:=readkey; case t of '=':zoom:=zoom+0.1; {+} '-': zoom:=zoom-0.1;{-} end; cleardevice; end until t=#13; closegraph; { writeln('press any key...');} { readln;} end. Вот скомпилированная программа: gr3d.zip ( 51.63 килобайт ) Кол-во скачиваний: 646 В ней выводиться множество Жюлиа, при желании измением define переменной, можно выводить множество Манделброта. Выход их программы - ENTER, клавиши - и = - увеличение и уменьшение сетки вывода. А теперь мысленно представим , что выведенная сетка - повехность! Какая же красота открывается нашему взгляду! Ничто пожалуй так не притягивает взор как математические объекты - графики, аттракторы, фракталы, со своей математической красотой и совершенством форм и линий! (просматривайте скриншеты, они не пустые ) -------------------- Помогая друг другу, мы справимся с любыми трудностями!
"Не опускать крылья!" (С) |
Dark |
8.02.2006 11:36
Сообщение
#2
|
Знаток Группа: Пользователи Сообщений: 408 Пол: Мужской Репутация: 3 |
Еще одного в нашем полку прибыло
я так люблю эти плазмы и фракталы и множества и много много другого я имею ввиду в компутерном виде демок много много видел - вот тама - класс -------------------- - Где я?
- Во тьме. - В какой тьме? - Во тьме твоего мозга. |
Текстовая версия | 27.04.2024 22:09 |