IonicWind Software

IWBasic => Games and Graphics => Topic started by: GWS on March 28, 2012, 04:03:30 AM

Title: The Julia Set
Post by: GWS on March 28, 2012, 04:03:30 AM
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

Title: Re: The Julia Set
Post by: GWS on March 29, 2012, 03:03:36 AM
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