Mandelbrot Softalk


What is it?

Our plot will plot points on the graph defined by the value of C. It will be displayed with a unique color.
The points will be tested to see whether or not they are elements of the Mandelbrot set.
Those points that are elements of the set will have their own unique color.
Those that are nearly elements of the set will have an assigned color depending on their proximety to the set.
Those points that are not elements will be plotted as some background color.

The Mandelbrot set can be plotted in a field between points (-2,-2i) and (+2,+2i). All the complex points within the field can be evaluated and determined whether or not they are an element of the set. This evaluation consists of subjecting an initial value to an iterative process on an accumulator by repeatedly squaring the value of the accumulator and adding the value of a constant to it.
The accumulator in our program is a complex number z(zx,zyi)
The constant is c(x,yi) and defines a single point within the field of interest.

Each iteration is described by the function:    new Z =  Z2 + C
The value of Z begins with the complex number (0,0i)
The value of C is the point being text and remains constant throughout the test.

If point C is a member of the set, then each new Z will remain within the x by 2i field.
Z(x,yi) will leave this area and fly off into infinity for points outside the set.

In our plot, each point c(cx,cyi) is sequentially tested to see if it is part of the set and plotted appropriatly. membership is determined by the number of iterations reached. Points near the set's boundary are also given unique colors. Additionally, our program will permit us to examine a selected area within the field. The patterns returned in our plot are the images that are widely showed as MandelBrot fractals.

Basically, I wish to make a program that displays the Mandelbrot set of elements in as much detail as I can. Working with graphics has its own particular considerations. When the program hick-ups, then the way the error mode presents itself is sometimes quite cryptic, such as locking up. The usual method of talking about a program is to walk through the code, step by step. However, this example will explain the program in terms of the steps I took to develop it and why. Not only does this method lend itself to trouble shooting during development, but it often provides new ideas that present themselves during the process. Any-way... here is how I did it.



OOPs

A quickie word about graphics. Computers do the most wonderful things, like faithfull storing and recalling data on command. Performing calculations that would be impossible to do by hand. And displaying these data in such a way that it can be understood. Graphics is a fascinating way of displaying the results of some calculations.

Our approach is to make some calulations that determine how a virtual point in a virtual field relates to a set of points that can be represented by a mathmatical function. This exercise deals with the Mandelbrot set. This takes us into a third dimension that need be displayed on a two dimensional viewport called a monitor. Fortunately, there are arithmetical tools that permit us to display a 2D plot of an x absissa value that is said to be in the real plane in relation to an oridinate value in what is commonly called the imaginary plane. I don't like to use the word imaginary because it is no more imaginary than is the real plane, so I will refer to it as the complex plane in this text. Simply, the complex plane is expressed with an
i or sometimes a j symbol to differentiate it with the more common y value. This exercise plots a graph using the x and i co-ordinates to express values in the Mandelbrot set.

To the plot: We use a screen that consists of a bunch of pixels. Their position on the SCREEN 9 display can be represented with an absissa and ordinate value closed within parens as (absissa, ordinate). Our limitations are (640,350) pixels. We also can display each of these pixel locations with one of 16 different colors.

Now comes the fun part. How do we think of these points and how are we to express them? We need to become artists.
Fortunately, someone has already given us a way of thinking that works well. OOPs is commenly considered an apologetic expression of surprise. Well, its also the acronym for Object Oriented Programming. Our plots are going to use this way of thinking. A graph will be described by defining it's upper left beginning point, length and width. What is displayed will be within these boundaries. Additionally the points within these boundaries will have unique properties expressed by different colors. Our plots will express properties of points within a field of interest and display the these points appropriately.

Initially, we initalize our plot viewport by defining a screen pixel some pixel numbers from the left and top of our window of screen pixels. Then we define the number of pixels needed to span our selected viewport. Each point in our plot can be examined independently for its properties and displayed as we wish. This is important because if we declare a point between pixel points in our calculations, it might not get represented in its proper position. If we plotted some value that falls between pixels then the plot would hickup and display a color in the nearest pixel position that the program can find, resulting in some pixels getting painted twice and some not getting painted at all. OOPs......

So,,,, our approach will be to select each pixel point, convert it to its appropriate position in the Mandelbrot field, determine its properties and declare that property, for that pixel appropriately. We do this by stepping through each pixel point in our plot, calculating its value as the product if that point and the span ratio of our graph with that of the virtual field of interest and doing whatever calculation are necessary on the virtual position to determine its proterties.

For each vy value of our virtual plot that corresponds to the appropriate X pixel point
  For each vx value of our
virtual plot that corresponds to the appropriate Y pixel point
       determine the properties of the virtual point in relation to our Mandelbrot criteria
       convert this virtual position proportionally to its appropriate (x,y) coordinates position
       PSET that pixel with an appropriate color
  Next vx value
Next vy value

OK.... now we can get into the program.




Create a Skeleton for the program

I will begin with my usual skeleton and test it out. The explainations will follow the time line I used in development.

I start off with my usual skeleton.
It begins with the program name with a short description of the program's intent.

10 '                  prog Mandel.bas
20 '
30 '       Mandelbrot series.... new Z equals Z squared plus C
40 '   Z and C are complex numbers. Z (z,zi) always begins at (0,0)
50 '   (-2,-2) =< C(c,ci) => (2,2) for each possible point.
60 '   if iteration count > test value then the point is in the set.
70 '
80 '

90 '

Next I set up the program environment and initalize the screen.
variable plots defines the number of canned plots I will use in the plots table of contents.

90 '
100 '         program start
110           KEY OFF: SCREEN 0: COLOR 0,7:  PLOTS= 5: CLS: PRINT
120           CLS:  PRINT

130 '

The program BANNER and selection of parameters will go here eventually.
In the mean time, put something here to prove the program is running properly as written so far.
A print statement should display in the SCREEN 0 color that has been selected.
This will be followed by entering the SCREEN 9 mode with my error handler enabled.

410 ''''''''''''''''' Graphics Begin Here '''''''''''''''''''''
420 '
430       CLS: SCREEN 9: COLOR 7,0: ON ERROR GOTO 980


Again, put something here to satisfy that the program enters SCREEN 9 with the selected. Some random temperary code such as a print statement will serve this purpose.

The end game for the program'w initial skeleton permits some functions I want to be included.

A sub-routine to simply await the operator's key-stroke before continuation of the program. I made it a sub-routine because I might wish to put the gosub statement in any number of places in the program while developing it for diagnostic purposes.

I restore the error handler from my own, to the Basic Interpreter's error handler when the graphic's SCREEN 9 section is completed and the program is re-run back into the initial SCREEN 0 mode. I will enable my own error handler during the graphic SCREEN 9 section. It serves to catch any error I make during development. On error, my handler simply prints out the two Basic system variables and stops. ERL is the line number and ERR is the error number.

890 ' .... patiently wait for a keystroke, then re-run the program ...
900          GOSUB 940
910          ON ERROR GOTO 0
920          RUN
930 '
940 ' ...... Sub Routine WAIT ..........
950      N$= INKEY$: IF N$= "" THEN 950
960          RETURN
970 '
980 ' ...... error handler ....
990      PRINT "error message ",ERL,ERR: STOP
1000 '
1010 ' ..... developmental section ......


The END statement protects me from accidently executing the SAVE function. The SAVE function lets me periodically save my work during development. I have saved myself a lot of work by useing it frequently during development.

1020 END
1030 SAVE "mandel",A



PERIODIC  BACK-UP is good. Saves losing your work if the processor locks up.

Now is a good time to test the program for errors. Heaven forbid... even I make typos when entering code ...!!
After satisfying yourself that the program is working as per coded, then the functional part can be developed.





Program BANNER and plot parameter selection

Copy this code into your program and test it out.
Variable PLOTS determines the number of DATA statements used to load up three Numeric arrays and one String array.
  N1( ), N2( ), N3( ) will contain vx,vy and vspan for the selected plot. N$( )  will describe the plot.
A header is printed to identify the use for these data.

140 '       read data and print the index of plots
150 FOR N= 0 TO PLOTS: READ  N1(N),N2(N),N3(N),N$(N): NEXT N
160     PRINT"Plot X  Y width        description"
170 '


The selectable plots are posted, followed by more options that may be selected rather than a plot.

180 '        print out the additional options
190 FOR N= 0 TO PLOTS: PRINT N;" "; N1(N);N2(N);N3(N);"    ";N$(N): NEXT N
200     PRINT PLOTS+1; "   select your own parameters"
210     PRINT PLOTS+2; "   terminate the program"
220 '

Data statements for the arrays

230 DATA -2,-2,4, classic full scale Mandelbrot plot"
240 DATA  0,-2,2, upper right quadrant I"
250 DATA  0, 0,2, lower right quadrant II"
260 DATA -2, 0,2, lower left  quadrant III"
270 DATA -2,-2,2, upper left  quadrant IV"
280 DATA -1.49,-.05,.1, left  needle structure
290 '


An INPUT statement permits selection into N$ and transfered to N if it is a valid number.
If N is the first selection after the plots number then branch to selection of your own parameters.
If N corresponds to the next selection, then the program terminates.
If a number outside the PLOTS array is selected, then N becomes zero.
vx, vy, and vspan are selected from the array and loaded into the appropriate variable.


300 INPUT " choose a plot number or event ",N$: N=VAL(N$)
310   IF N=(PLOTS+1) THEN 380
320   IF N=(PLOTS+2) THEN PRINT: PRINT "program terminate": END
330 '
340    IF N$="" OR N=0 OR N>(PLOTS+2) THEN N=0
350       VX=N1(N): VY=N2(N): VSPAN= N3(N)
360       GOTO 410
370 '
380 INPUT "Enter vx,vy,vspan ",VX,VY,VSPAN
390 '
400 '


The program is now ready to execute the graphics part of our program with the starting values of that part of the virtual Mandelbrot set that we wish to display. vx and vy define the upper left corner of the area to be displayed and vspan defines how large the area will be. To be satisfied that this part of the program is working, temperarily put in a line of code that prints out vx,vy and vxpan.





Graphics set up

This section introduces the SCREEN 9 graphics display. Its isn't necessary to CLS SCREEN 0, but I like to leave previous pages tidy. Swith to SCREEN 9 and use COLOR 7. Enable our own ERROR handler if we decide to use it. Post the selected values for vx, vy and vspan.


410 ''''''''''''''''' Graphics Begin Here '''''''''''''''''''''
420 '
430       CLS: SCREEN 9: COLOR 7,0: ON ERROR GOTO 980
440 LOCATE 19,1: PRINT "   vx= ";VX
450 LOCATE 20,1: PRINT "   vy= ";VY
460 LOCATE 21,1: PRINT "vspan= ";VSPAN
470 '


Of all the right ways to define our ViewPorts, lets define the top left corner and the span of the VIEWPORT, as we did with our virtual image with vx,vy and vspan. The main image will use SCREEN 9 pixel's locations beginning at (LEFT%,TOP%) with a span of SPAN%.

The integer % variables are used to ensure that our PSET values are calculated to non fractional locations. Each calculated value will indeed be the location of the adjacent pixel on our display rather than round off to a possible adjacent location, leaving a gap in our final plot. Another smaller VIEWPORT with the variable labels of Q.... is defined because we just might want to use it later.


480 ' ... define the Plot ViewPort for the display ........
490       LEFT%= 200:  TOP%=  10:     SPAN%= 340
500      QLEFT%= 60:  QTOP%=  20:    QSPAN%= 80
510 '
520   LINE ( LEFT% ,  TOP%) - ( LEFT% + SPAN% ,  TOP% +  SPAN%) ,14 ,BF
530   LINE (QLEFT% , QTOP%) - (QLEFT% +QSPAN% , QTOP% + QSPAN%) ,14 ,BF
540 '
550 '






Draw the two Viewports
 
Each point of the virtual set is tested. The complex number C=  ( C,Ci ) is the absissa and ordinate for each analyzed point of interest in the Mandelbrot field. This nested FOR/ NEXT loop tests each C value from vx throughout the entire vx span and each Ci value from vy throughout it's span in discreet steps. The steps used are in the ratio of the virtual span to the span of the main display. This ensures that there will be as many tests in the virtual field as there are pixels in the main display VIEWPORT.


560 ' ... begin the nested loops to analyze one point .....
570 '
580              FOR C = VX TO VX+VSPAN STEP VSPAN/SPAN%
590              FOR CI= VY TO VY+VSPAN STEP VSPAN/SPAN%
600 '


This code between line 600 and 780 is where the actual Mandelbrot plot is calculated. Each point of the Mandelbrot virtual area is tested for its properties and assigned an appropriate color. Then associated pixel in the plot is plotted.
A given pixel color can be temperarily assigned by giving the variable TINT a number other than the VIEWPORT's background number. Insert line   
700 TINT=1 ' blue    here to give each pixel a default color for testing.

X% is calculated by adding the distance to the LEFT most pixel to the calculated position in the main plot. The calculated position is C less the distance from the virtual center of (0,0) and the left edge, given by C-vx. The Y% on the Ci axis is calculated the same way. Both must be converted by the ratio of the Main plot span to the virtual area's span. Finally the point is plotted on the main plot using the PSET function using the color TINT.

The Q VIEWPORT is ploted into its assigned area of the screen the same way, but the values are expressed in one line. Either PSET format may be used; however, the one line rather the three lines and two extra variables is enherently faster if speed is a  consideration. The Q display is simply for this example and may be illiminated entirely in your program which will speed up the plotting process considerably too.

780 ' ... Convert (C,Ci) to (X%,Y%) and plot the points ...
790 '
800       X%= LEFT% +  ( ( C-VX)  * (SPAN%/VSPAN) )
810       Y%=  TOP% +  ( (CI-VY)  * (SPAN%/VSPAN) )
820               PSET (X%,Y%),TINT
830 '
840   PSET(QLEFT%+(C-VX)*QSPAN%/VSPAN,QTOP%+(CI-VY)*QSPAN%/VSPAN),TINT
850 '
860       NEXT CI
870     NEXT C
880 '



The only thing left to do now is to calculate the number of iterations in the new Z= Z2+C loop and assign a color to it to give it the proper tint in the final plot.



Analyzing the virtual point's property

This is the heart of the program. The value of  Z 
is expressed in variables Z for its real value and Zi for its complex value. Z and Zi are both set to zero at the start of the process. The index count in INX is also zeroed. The value for the constant C and Ci are provided with the nested FOR/ NEXT loops. All thats necessare is to repeadly calculate the new Z until it either leaves the virtual field or reaches an acceptedly large number to be inclued in the loop. In either case, the program drops through to the next step where an appropriate color attribute is assigned for that (C,Ci) point.




610             INX=0:   Z=0:      ZI=0
620          A= (Z*Z) - (ZI*ZI):   BI= 2*Z*ZI
630          Z= A+C:            ZI=BI+CI
640          INX= INX+1
650       IF ABS(Z) > 2 OR ABS(ZI) > 2 THEN 690
660       IF INX < 800 THEN 620
670 '
680 '




Given the number of iterations in the variable INX, a color may be assigned. Many of the points won't even reach 3, but if it is larger than three TINT will become red. Larger than 5 then brown and so on. These colors and number boundaries can be toyed with to get the plot you like best. The PSET instruction under SCREEN 9 provides 16 colors from 0 to 15.


690 ' ....... set color attribute .......
700        TINT=1                 ' blue
710     IF INX >   3 THEN TINT=12 ' red
720     IF INX >   5 THEN TINT=6  ' brown
730     IF INX >  40 THEN TINT=10 ' green..light
740     IF INX >  80 THEN TINT=4  ' red....light
750     IF INX > 700 THEN TINT=0  ' black
760 '
770 '



Skip this part if you are satisfied with the new Z=  Z2 + C  algorithm. Otherwise

Substitute A for the Z term:   Substitute Bi for the Complex term.
         (Z+Zi)2 becomes    A2 +2*A*Bi + B2i2      and since  i2 is -1 then B2i2 becomes  real, -B2
then 
(Z+Zi)2 becomes    Z2 + 2*Z*Zi  - Zi2

collect the real and complex  terms the  (Z,Zi)2 becomes    A2 - B2 ,  2*A*B
Let A =  the first new     real     Z   term :  A  = Z*Z
Let Bi=  the first new complex Zi  term:   Bi = 2*Z*Zi

Add the constant real C and complex Ci terms to the new real Z and complex Zi terms
Zi = A plus C      and      Zi = Bi plus Ci



       






Summary

Each part of the Mandel.bas program has been explored in detail in the text above. The program itself is showed in the text below and may be copied and  pasted into a plain text file and run with the GWBasic Interpreter.
Many parts of the program may be modified to meet your own choice of interaction and display.
The size and position of the plots may be altered easily.
Different colors and itteration counts may be used to display points near the Mandelbrot set.
The arrow keys may be used to define a new Window.
Dos INT 33 calls may be used to use the Mouse as a pointer instead of the arrow keys.
The Mandelbrot algorithm may be replaced with an algorithm for another function.

In short.... play around and have fun.........



10 '                  prog Mandel.bas
20 '
30 '       Mandelbrot series.... new Z equals Z squared plus C
40 '   Z and C are complex numbers. Z (z,zi) always begins at (0,0)
50 '   (-2,-2) =< C(c,ci) => (2,2) for each possible point.
60 '   if iteration count > test value then the point is in the set.
70 '
80 '
90 '
100 '         program start
110           KEY OFF: SCREEN 0: COLOR 0,7:  PLOTS= 5: CLS: PRINT
120           CLS:  PRINT
130 '


140 '       read data and print the index of plots
150 FOR N= 0 TO PLOTS: READ  N1(N),N2(N),N3(N),N$(N): NEXT N
160     PRINT"Plot X  Y width        description"
170 '
180 '        print out the additional options
190 FOR N= 0 TO PLOTS: PRINT N;" "; N1(N);N2(N);N3(N);"    ";N$(N): NEXT N
200     PRINT PLOTS+1; "   select your own parameters"
210     PRINT PLOTS+2; "   terminate the program"
220 '
230 DATA -2,-2,4, classic full scale Mandelbrot plot"
240 DATA  0,-2,2, upper right quadrant I"
250 DATA  0, 0,2, lower right quadrant II"
260 DATA -2, 0,2, lower left  quadrant III"
270 DATA -2,-2,2, upper left  quadrant IV"
280 DATA -1.49,-.05,.1, left  needle structure
290 '
300 INPUT " choose a plot number or event ",N$: N=VAL(N$)
310   IF N=(PLOTS+1) THEN 380
320   IF N=(PLOTS+2) THEN PRINT: PRINT "program terminate": END
330 '
340    IF N$="" OR N=0 OR N>(PLOTS+2) THEN N=0
350       VX=N1(N): VY=N2(N): VSPAN= N3(N)
360       GOTO 410
370 '
380 INPUT "Enter vx,vy,vspan ",VX,VY,VSPAN
390 '
400 '


410 ''''''''''''''''' Graphics Begin Here '''''''''''''''''''''
420 '
430       CLS: SCREEN 9: COLOR 7,0: ON ERROR GOTO 980
440 LOCATE 19,1: PRINT "   vx= ";VX
450 LOCATE 20,1: PRINT "   vy= ";VY
460 LOCATE 21,1: PRINT "vspan= ";VSPAN
470 '
480 ' ... define the Plot ViewPort for the display ........
490       LEFT%= 200:  TOP%=  10:     SPAN%= 340
500      QLEFT%= 60:  QTOP%=  20:    QSPAN%= 80
510 '
520   LINE ( LEFT% ,  TOP%) - ( LEFT% + SPAN% ,  TOP% +  SPAN%) ,14 ,BF
530   LINE (QLEFT% , QTOP%) - (QLEFT% +QSPAN% , QTOP% + QSPAN%) ,14 ,BF
540 '
550 '




560 ' ... begin the nested loops to analyze one point .....
570 '
580              FOR C = VX TO VX+VSPAN STEP VSPAN/SPAN%
590              FOR CI= VY TO VY+VSPAN STEP VSPAN/SPAN%
600 '


610             INX=0:   Z=0:      ZI=0
620          A= (Z*Z) - (ZI*ZI):   BI= 2*Z*ZI
630          Z= A+C:            ZI=BI+CI
640          INX= INX+1
650       IF ABS(Z) > 2 OR ABS(ZI) > 2 THEN 690
660       IF INX < 800 THEN 620
670 '
680 '
690 ' ....... set color attribute .......
700        TINT=1                 ' blue
710     IF INX >   3 THEN TINT=12 ' red
720     IF INX >   5 THEN TINT=6  ' brown
730     IF INX >  40 THEN TINT=10 ' green..light
740     IF INX >  80 THEN TINT=4  ' red....light
750     IF INX > 700 THEN TINT=0  ' black
760 '
770 '


780 ' ... Convert (C,Ci) to (X%,Y%) and plot the points ...
790 '
800       X%= LEFT% +  ( ( C-VX)  * (SPAN%/VSPAN) )
810       Y%=  TOP% +  ( (CI-VY)  * (SPAN%/VSPAN) )
820               PSET (X%,Y%),TINT
830 '
840   PSET(QLEFT%+(C-VX)*QSPAN%/VSPAN,QTOP%+(CI-VY)*QSPAN%/VSPAN),TINT
850 '
860       NEXT CI
870     NEXT C
880 '


890 ' .... patiently wait for a keystroke, then re-run the program ...
900          GOSUB 940
910          ON ERROR GOTO 0
920          RUN
930 '
940 ' ...... Sub Routine WAIT ..........
950      N$= INKEY$: IF N$= "" THEN 950
960          RETURN
970 '
980 ' ...... error handler ....
990      PRINT "error message ",ERL,ERR: STOP
1000 '
1010 ' ..... developmental section ......
1020 END
1030 SAVE "mandel",A