IDIC

# Mandelbrot Explorer

The Mandelbrot set is just a bunch of numbers. A mathematician would talk about complex and imaginary numbers, but we simply want to see the pattern they form on an ordinary graph. The graph has the usual x-axis and y-axis, both ranging from -2 to +2. The pattern is interesting because it contains infinite detail. When we magnify a section of the graph, more detail emerges.

Normally, when we plot lines on a graph or a fancy pattern, the values we use are the direct result of a simple formula. A Mandelbrot is subtly different because the formula we use produces an answer, but it's not the answer that we plot. Instead, we test the answer to see if it's greater than 2. If the answer is not greater than 2 then we feed the answer back into the formula and try again. This process is repeated until the answer is greater than 2, or we give up.

The value that we plot is the count of the number of times the calculation is performed.

Here's the catch: The amount of detail we see depends on the area we magnify and the number of times we're willing to perform the calculation. The colour of each point on the graph (or pixel) is the result of this repetitive process. Many pixels = many calculations = time spent waiting for the pattern to be drawn.

This Mandelbrot Explorer has been optimised to paint the initial pattern quickly, but to increase the level of detail as we magnify (up to a maximum limit).

Use the mouse to select the area to magnify.

10 MODE 9:OFF

20 ORIGIN 640,512

30

40 bsize=127:REM Length of side = bsize*2+1 pixels

50 MAXloops=16:REM max calculations we're prepared to perform, per pixel

60 startx=0:starty=0:startsize=2

70 zoom=4

80

90 DIM brotgrid(bsize*2,bsize*2,1)

100

110 ON MOUSE:PROCmouse:RETURN

120

130 goodtogo=TRUE

140 needtogo=TRUE

150 minishowing=FALSE

160 REPEAT

170   TIME=0

180   IF goodtogo THEN

190     IF needtogo THEN

200       PROCinitbrot:PROCdrawbrot:needtogo=FALSE

210     ELSE

220       PROCminisquare

230     ENDIF

240   ENDIF

250   WAIT 4-TIME

260 UNTIL FALSE

270 END

280

290 DEF PROCinitbrot

300 goodtogo=FALSE

310 FOR y=-bsize TO bsize

320   FOR x=-bsize TO bsize

330     brotgrid(x+bsize,y+bsize,0)=startx+startsize*x/bsize:REM alpha

340     brotgrid(x+bsize,y+bsize,1)=starty+startsize*y/bsize:REM beta

350   NEXT

360 NEXT

370 ENDPROC

380

390 DEF PROCdrawbrot

400 CLS

410 FOR y=-bsize TO bsize

420   FOR x=-bsize TO bsize

430     c=MAXloops:escaped=FALSE

440     alpha=0:beta=0

450     REPEAT

460       newalpha=alpha^2-beta^2+brotgrid(x+bsize,y+bsize,0)

470       newbeta=2*alpha*beta+brotgrid(x+bsize,y+bsize,1)

480       alpha=newalpha:beta=newbeta

490       IF alpha^2+beta^2>=4 escaped=TRUE

500       c-=1

510     UNTIL c=0 OR escaped

520     IF escaped THEN

530       COLOUR 7,c*32,c*16,c*16

540       GCOL 0,7:PLOT x*4,y*4

550     ENDIF

560   NEXT

570 NEXT

580 goodtogo=TRUE:minishowing=FALSE

590 ENDPROC

600

610 DEF PROCmouse

620 IF NOT goodtogo THEN

630   COLOUR 1:PRINT"Wait!"

640 ELSE

650   MOUSE x,y,buttons

660   x DIV=4:y DIV=4

670   IF x>bsize*-1 AND x<bsize AND y>bsize*-1 AND y<bsize THEN

680     startx=startx+startsize*x/bsize

690     starty=starty+startsize*y/bsize

700     startsize/=zoom

710     MAXloops*=2:IF MAXloops>256 MAXloops=256

720     needtogo=TRUE

730   ENDIF

740 ENDIF

750 ENDPROC

760

770 DEF PROCminisquare

780 GCOL 3,6

790 f=zoom/4

800 IF minishowing RECTANGLE mx-bsize/f,my-bsize/f,bsize*2/f

810 MOUSE mx,my,buttons

820 IF mx>bsize*-4 AND mx<bsize*4 AND my>bsize*-4 AND my<bsize*4 THEN

830   RECTANGLE mx-bsize/f,my-bsize/f,bsize*2/f:minishowing=TRUE

840 ELSE

850   minishowing=FALSE

860 ENDIF

870 ENDPROC

Mandelbrot Explorer: Code explained...

10 MODE 9:OFF

20 ORIGIN 640,512

40 bsize=127:REM Length of side = bsize*2+1 pixels

Using a square grid, and an odd number of pixels for each side, simplifies the initial calculations.

50 MAXloops=16:REM max calculations we're prepared to perform, per pixel

MAXloops increases as we magnify, to a maximum of 256.

60 startx=0:starty=0:startsize=2

70 zoom=4

90 DIM brotgrid(bsize*2,bsize*2,1)

The centre of the initial image is centred on x, y co-ordinates zero, zero.

'brotgrid' is used to store the initial values that are fed into the repeating (recursive) calculation. This array is unnecessary as the values stored are easily calculated, but its inclusion hopefully aids understanding.

110 ON MOUSE:PROCmouse:RETURN

Not encountered since the character designer. This programs clearly demonstrates the nature and behaviour of a mouse interrupt (see below).

130 goodtogo=TRUE

140 needtogo=TRUE

150 minishowing=FALSE

'goodtogo' indicates that the current image has finished drawing.

'needtogo' indicates a request to draw/magnify.

'minishowing' indicates that the magnification square has been drawn at least once.

160 REPEAT

170   TIME=0

180   IF goodtogo THEN

190     IF needtogo THEN

200       PROCinitbrot:PROCdrawbrot:needtogo=FALSE

Draws a mandelbrot pattern

210     ELSE

220       PROCminisquare

Draws a square, following the mouse, that shows the area to be magnified.

290 DEF PROCinitbrot

300 goodtogo=FALSE

310 FOR y=-bsize TO bsize

320   FOR x=-bsize TO bsize

330     brotgrid(x+bsize,y+bsize,0)=startx+startsize*x/bsize:REM alpha

340     brotgrid(x+bsize,y+bsize,1)=starty+startsize*y/bsize:REM beta

350   NEXT

360 NEXT

370 ENDPROC

This routine calculates the initial values to be fed into the recursive algorithm. The values fall between

-2 and +2 and are equal to the x-axis and y-axis values of the point to be plotted.

Note that plotting of the Mandelbrot pattern is limited by the accuracy of floating point calculations (i.e. how well the computer can handle fractions).

As mentioned above, the array is unnecessary because the values can be calculated when required.

390 DEF PROCdrawbrot

400 CLS

410 FOR y=-bsize TO bsize

420   FOR x=-bsize TO bsize

430     c=MAXloops:escaped=FALSE

MAXloops defines the maximum number of calculations we're willing to perform, before we quit in order to save time.

'escaped' indicates that the result of the calculation is >= 2.

440     alpha=0:beta=0

'alpha' and 'beta' together hold the values (the answer) that may be required to be fed back into the recursive calculation.

450     REPEAT

460       newalpha=alpha^2-beta^2+brotgrid(x+bsize,y+bsize,0)

470       newbeta=2*alpha*beta+brotgrid(x+bsize,y+bsize,1)

This is the heart of the recursive algorithm.

480       alpha=newalpha:beta=newbeta

490       IF alpha^2+beta^2>=4 escaped=TRUE

Note that Line 490 tests for a value >=4. This line is equivalent to the following:

IF SQR(alpha^2+beta^2)>=2 escaped=TRUE

The reason that line 490 is preferable is because it omits the (SQR) square root function which dramatically speeds up the calculation!

500       c-=1

510     UNTIL c=0 OR escaped

520     IF escaped THEN

530       COLOUR 7,c*32,c*16,c*16

540       GCOL 0,7:PLOT x*4,y*4

If/when we quit the current cycle of caluculations then we plot nothing, but if we 'escaped' then we plot a colour derived from the number of times the calculation was performed.

610 DEF PROCmouse

620 IF NOT goodtogo THEN

630   COLOUR 1:PRINT"Wait!"

640 ELSE

650   MOUSE x,y,buttons

660   x DIV=4:y DIV=4

670   IF x>bsize*-1 AND x<bsize AND y>bsize*-1 AND y<bsize THEN

680     startx=startx+startsize*x/bsize

690     starty=starty+startsize*y/bsize

700     startsize/=zoom

710     MAXloops*=2:IF MAXloops>256 MAXloops=256

720     needtogo=TRUE

730   ENDIF

740 ENDIF

750 ENDPROC

The ON MOUSE command at the beginning of the program instructs BB4W to temporarily divert to this routine whenever a mouse button is clicked.

The routine immediately checks to see if a Mandelbrot is being drawn. If 'goodtogo' is FALSE then the user is instructed to wait. This event clearly demonstrates how control passes from one part of the program to another in response to a specific interrupt (and then back again).

If the current Mandelbrot pattern is complete then the centre of the area to be magnified is calculated from the position of the mouse. The total area magnified is determined by 'startsize'.

770 DEF PROCminisquare

780 GCOL 3,6

790 f=zoom/4

800 IF minishowing RECTANGLE mx-bsize/f,my-bsize/f,bsize*2/f

810 MOUSE mx,my,buttons

820 IF mx>bsize*-4 AND mx<bsize*4 AND my>bsize*-4 AND my<bsize*4 THEN

830   RECTANGLE mx-bsize/f,my-bsize/f,bsize*2/f:minishowing=TRUE

840 ELSE

850   minishowing=FALSE

860 ENDIF

870 ENDPROC

PROCminisquare uses exclusive-or graphics to draw a square over a completed Mandelbrot, following the position of the mouse. The square only appears when the mouse pointer is over the area of the pattern.