/* mandelbrotset.m mandelbrot set generator optimized for mobile use by airbit AG, 15-jun-2008/bj usage: if in idle mode -> zoom frame is displayed "5" or gokey: compute fractal from the range in the zoom frame "2" or upkey: move zoomframe up "8" or downkey: move zoomframe down "4" or leftkey: move zoomframe left "6" or rightkey: move zoomframe right "1": enlarge zoomframe "3": decrease zoomframe "7": shift color palette to brighter "9": shift color palette to darker "0": save current graph to .jpg file "*": toggle frame color "#": exit/end program if in compute mode -> fractal is being drawed gokey: stop calculation and drawing when current detail level is finished */ use ui, array as a, math as m, graph as g, time, audio const detail=400; // maximum number of iterations, as higher as better the quality, but takes more time to calculate const zooms=10; // max number of zoom levels for frame const grid=2; // how many pixels one step shifts the frame // declare and init globals g.scale(false); scr=g.full(false); g.size(scr[0], scr[1]); g.bg(g.black); g.clear(); mbca=array.create(scr[0], 0); for i=0 to len(mbca)-1 do mbca[i]=array.create(scr[1], 0) end; function colors(cs=1) forward; cola=colors(); colc=1600*m.log(detail/3)/detail; // scale fractal to screen scale=scr[0]/scr[1]; ex=(4*scale)/2; sx=-ex; sy=-2.5; ey=1.5; zoom=1; acuteness=1; fx=0; fy=0; fw=0; fh=0; fox=0; foy=0; sf=[null,null,null,null]; fname="mb_"+time.str(time.get(), "YYYY-MM-DD_hh-mm-ss_"); calcs=0; greenframe=true; function mandelbrot(sx, ex, sy, ey, det, cola, colc, psize) for j=0 to ..scr[1]-1 by psize do for i=0 to ..scr[0]-1 by psize do iter=0; x0=ex-(ex-sx)/..scr[0]*(i+psize/2); y0=ey-(ey-sy)/..scr[1]*(j+psize/2); //flip axis temp=y0; y0=x0; x0=temp; x=x0; y=y0; maxiter=det; //interior check //small circle if (x+1)*(x+1)+y*y<0.0625 then iter=maxiter end; //big cardioide d=256*(x*x+y*y)*(x*x+y*y)-96*(x*x+y*y)+32*x-3; if d<=0 then iter=maxiter end; //interior check finished //escape time algorithm while (x*x+y*y<4) and (iter0 then color=cola[(colbase*colc)%(255*6)] else color=0; colbase=0 end end; g.pen(color); g.brush(color); g.rect(i, j, psize, psize); g.show(); // save result ..mbca[i][j] = colbase; end end end function colorize(colc, psize) for j=0 to ..scr[1]-1 by psize do for i=0 to ..scr[0]-1 by psize do color=..cola[(..mbca[i][j]*colc)%(255*6)]; g.pen(color); g.brush(color); g.rect(i, j, psize, psize); g.show() end end; while ui.cmd(0) # null do end; ..calcs++ end function calcmandel(sx, ex, sy, ey, colc) for i=16 to 0 by -4 do if i = 0 then mandelbrot(sx, ex, sy, ey, ..detail, ..cola, colc, 1); ..acuteness=1 else mandelbrot(sx, ex, sy, ey, ..detail, ..cola, colc, i); ..acuteness=i end; if ui.cmd(100)=ui.gokey then break end end; while ui.cmd(0) # null do end; ..calcs++ end; function restoreframe() if ..sf[0] # null then g.put(..fx, ..fy, ..sf[0]); g.put(..fx, ..fy, ..sf[1]); g.put(..fx+..fw-1, ..fy, ..sf[2]); g.put(..fx, ..fy+..fh-1, ..sf[3]) end; end; function drawframe(zoom=1) ..fw=(..scr[0]/..zooms)*(..zooms-zoom); ..fx=..fox+(..scr[0]-..fw)/2; ..fh=(..scr[1]/..zooms)*(..zooms-zoom); ..fy=..foy+(..scr[1]-..fh)/2; ..sf[0]=g.get(..fx, ..fy, ..fw, 1); // - ..sf[1]=g.get(..fx, ..fy, 1, ..fh); // | ..sf[2]=g.get(..fx+..fw-1, ..fy, 1, ..fh); // | ..sf[3]=g.get(..fx, ..fy+..fh-1, ..fw, 1); // _ g.brush(false); if ..greenframe then g.pen(g.green) else g.pen(g.black) end; g.rect(..fx, ..fy, ..fw, ..fh); g.show() end function colors(cs=1) // color array cola=a.create(255*6, 0); ind=0; col=0; for b=1 to 255 by cs do col+=1; cola[ind]=col; ind++ end; for g=1 to 255 by cs do col+=256; cola[ind]=col; ind++ end; for r=1 to 255 by cs do col+=65536; cola[ind]=col; ind++ end; for b=255 to 1 by -cs do col-=1; cola[ind]=col; ind++ end; for g=255 to 1 by -cs do col-=256; cola[ind]=col; ind++ end; for r=255 to 1 by -cs do col-=65536; cola[ind]=col; ind++ end; return cola end; // --------------- // prep screen log cls(); print "mandelbrotset start:"; print date(); print "=========================="; print 'by airbit AG'; ui.keys(false); calcmandel(sx, ex, sy, ey, colc); drawframe(zoom); //main loop do cmd=ui.cmd(10); if isnum(cmd) then restoreframe(); case char(cmd) in "3" : if zoom < zooms-1 then zoom++ end; in "1" : if zoom > 1 then zoom-- end; in "7" : colc=colc*2; colorize(colc, acuteness) in "9" : colc=colc/2; colorize(colc, acuteness) in "0" : g.save(fname+calcs+".jpg"); audio.beep() in "*" : greenframe = not greenframe end; if cmd = ui.rightkey or char(cmd) = "6" then if fx+fw < scr[0] then fox+=2 end; elsif cmd = ui.leftkey or char(cmd) = "4" then if fx > 0 then fox-=grid end; elsif cmd = ui.upkey or char(cmd) = "2" then if fy > 0 then foy-=grid end; elsif cmd = ui.downkey or char(cmd) = "8" then if fy+fh < scr[1] then foy+=grid end; elsif cmd = ui.gokey or char(cmd) = "5" then // calculate mapping for zoom ext=ex; sxt=sx; eyt=ey; syt=sy; ex=ext-(ext-sxt)/scr[0]*(fx); ey=eyt-(eyt-syt)/scr[1]*fy; sx=ext-(ext-sxt)/scr[0]*(fx+fw); sy=eyt-(eyt-syt)/scr[1]*(fy+fh); calcmandel(sx, ex, sy, ey, colc) end; drawframe(zoom); end; until isnum(cmd) and char(cmd) = "#"; g.hide(); print "mandelbrotset stopped:"; print date(); print calcs, "fractal(s) computed"