Hi,
Here's another type of fractal based on the Mandelbrot set.
Whereas the Mandelbrot set has only one shape, the Julia set has an infinite number of shapes.
The controlling factor is a complex number that is chosen to be added at each iteration.
You get a different pattern depending on the real and imaginary values that you choose.
' Julia Set - GWS March 2012
' Click on the fractal to enlarge the pattern at that point.
' Click ReSet to return to the standard Mandlebrot display.
autodefine "OFF"
window w
int i,y,px,wstyle,run
int Width,Height
int mx,my,clickcount
float Z_re2,Z_im2,Z_re,Z_im,c_re,c_im
float x1,x2,y1,y2,j_re,j_im
float Rfac,Ifac,scale,Re,Im
pointer sprite1
int col[255]
for i = 0 to 63
col[0+i] = rgb(4*i,65-i,256-3*i)
col[64+i] = rgb(3*i,2*i,255-3*i)
col[128+i] = rgb(4*i,0,20*i)
col[192+i] = rgb(255-3*i,2*i-1,4*i)
next i
Width=1024
Height=768
run = 1
wstyle = @minbox|@noautodraw
openwindow w,-Width,0,Width,Height,wstyle,0,"Mandlebrot",&handler
setwindowcolor w,rgb(0,0,30)
' create a DirectX screen (no allowance is made for the user not having DirectX - just go for it) ...
attachscreen(w,Width,Height,0)
frontpen backBuffer,RGB(255,255,255)
setfont backbuffer,"Arial",10,500
drawmode backBuffer,@TRANSPARENT
control backbuffer,@BUTTON,"Reset",Width*0.1,Height*0.85,70,25,0, 1
control backbuffer,@BUTTON,"Exit",Width*0.8,Height*0.85,70,25,0, 2
' working sprite to draw on - and to refresh from if the window needs re-painting ..
sprite1 = CREATESPRITE(Width,Height,1,1)
flip
centerwindow w
scale = 1.0
clickcount = 0
' set a selected Julia complex number .. (you can choose any values between +/- 2.0)
j_re = -0.54
j_im = 0.2
' define the corners for two complex numbers (x1+iy1) and (x2+iy2) ..
x1 = -2
y1 = -1.5
x2 = 2
y2 = 1.5
' calculate factors to match screen pixels to corresponding complex values ..
Rfac = (x2 - x1)/(Width - 1)
Ifac = (y2 - y1)/(Height - 1)
gosub NewPattern
gosub redraw
waituntil run = 0
freesprite sprite1
closescreen
closewindow w
end
sub handler(),int
select @MESSAGE
case @idclosewindow
run = 0
case @idcontrol
select @controlid
case 1
' set to display normal fractal ..
clickcount = 0
Scale = 1.0
x1 = -2
y1 = -1.5
x2 = 2
y2 = 1.5
' restore the original Julia real and imaginary values ..
j_re = -0.54
j_im = 0.2
setfocus w
gosub Redraw
case 2
run = 0
endselect
case @idkeydown
select @wparam
case 0x25 :'left arrow key (reduce j_re)
if (j_re > -1.99) then j_re = j_re - 0.01
case 0x27 :'right arrow key (increase j_re)
if (j_re < 1.99) then j_re = j_re + 0.01
case 0x26 :'up arrow key (increase j_im)
if (j_im < 1.99) then j_im = j_im + 0.01
case 0x28 :'down arrow key (decrease j_im)
if (j_im > -1.99) then j_im = j_im - 0.01
endselect
case @idkeyup
if (@wparam = 0x25|@wparam = 0x26|@wparam = 0x27|@wparam = 0x28)
' redo the display ..
gosub Redraw
endif
case @IDLBUTTONDN
' where was the mouse button clicked ..
mx = @MOUSEX
my = @MOUSEY
clickcount = clickcount + 1
' magnify by 20 at each click ..
Scale = clickcount * 20
' calculate the Real and Imaginary values corresponding to the point clicked ..
Re = x1 + @mousex * Rfac
Im = y2 - @mousey * Ifac
' plot from the selected Re +/- 1.5 , and from Im -/+ 1.2
x1 = Re - 1.5 / Scale
x2 = Re + 1.5 / Scale
y1 = Im - 1.2 / Scale
y2 = Im + 1.2 / Scale
' recalculate the Re and Im factors for the current scale ..
gosub Redraw
case @IDPAINT
drawspritexy sprite1,0,0
flip
endselect
return(0)
endsub
sub NewPattern
int NIter,clr,xm
' routine to generate a Julia set pattern ..
NIter = 50
SpriteToBuffer(sprite1)
Fillscreen RGB(0,0,20), SpriteBuffer
LOCKBUFFER SpriteBuffer
for y = 0 to Height - 1
c_im = y2 - y * Ifac
for px = 0 to (Width - 1)
c_re = x1 + px * Rfac
Z_re = c_re
Z_im = c_im
for i = 1 to NIter
xm = 3*(i%255) :' colour multiplier
Z_re2 = Z_re * Z_re
Z_im2 = Z_im * Z_im
if (Z_re2 + Z_im2 > 4)
if xm = NIter
clr = 0
else
clr = col[xm]
endif
WritePixelFast px,y,clr,SpriteBuffer
goto breaknext
endif
Z_im = 2 * Z_re * Z_im + j_re
Z_re = Z_re2 - Z_im2 + j_im
next i
label breaknext
next px
next y
UNLOCKBUFFER SpriteBuffer
flip
endsub
sub Redraw
' redraw the pattern after a change ..
Rfac = (x2 - x1)/(Width - 1)
Ifac = (y2 - y1)/(Height - 1)
gosub NewPattern
drawsprite sprite1
move backBuffer,20,20
print backBuffer,"Click on the Fractal to enlarge a section."
move backBuffer,20,40
print backBuffer,"Use Arrow keys to change the fractal"
move backBuffer,20,60
print backBuffer,"Keep key down for rapid changes"
move backbuffer,20,600
print backbuffer,"Real = ",j_re
move backbuffer,20,620
print backbuffer,"Imag = ",j_im
flip
endsub
The colouring method seems reasonable, but could probably be improved upon to smooth out the colours based on an HSV colouring scheme - just haven't figured out how to do it yet .. ::)
Click anywhere on a pattern to zoom in.
Use the arrow keys to 'move around' in the Julia patterns .. the values change only slowly - if you want quicker changes, just hold the keys down longer.
best wishes, :)
Graham
There's a cute pattern at: Real - 0.57, Imag: 0.20 .. ;D
You never know what you find as you move around this thing ..
all the best, :)
Graham