Programming by Example

 

A BB4W Compendium

freeman69@gmx.com

IDIC BBC_Owl2 M&P

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.

 

    When is an answer not an answer?

 

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

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.

Arrow black large Arrow black large