############################################################################ # # File: mandel2.icn # # Subject: Program to draw the Mandelbrot set # # Author: Roger Hare # # Date: June 17, 1994 # ############################################################################ # # This file is in the public domain. # ############################################################################ # # This program draws portions of the Mandelbrot set according to the values # input # on the command line. The method is that described in the articles by # Dewdney # in the Computer Recreations column of Scientific American in August # '85, # October '87 and February '89. # # I have problems with colours (not enough of 'em!), so I have used alternated # black and white. Those with decent X-terminals will be able to do far # better than me. # # The program certainly doesn't display images as striking as those seen # in publications. Perhaps the scaling of the value of k needs to be # different? All suggestions gratefully received. # # It is possible to speed things up by displaying the points row by row # rather than randomly, but as the program is resident in the 100 cycle # iteration most of the time, this is only ~5% speed-up. Not really # worth it. # # One of Dewdney's articles mentions other methods to speed things up - I # will search out the algorithms one of these days... # # Usage is - xmand startr startc size n & # # where: # # startr, startc are the co-ordinates of the lower left hand corner of the # area of the complex plane to be displayed # size is the size of the (square) area of the complex plane to be displayed # n is the number of pixels into which size is to be divided for display # purposes # # For example - xmand -1.5 -1.25 2.5 400 & # # will display the Mandelbrot set in the 2.5x2.5 region of the complex plane # whose s-w corner is -1.5-i1.25. The display will be 400x400 pixels. # # The program has been tested on a Sun 4 using the Icon compiler, and # on a Sequent Symmetry running Version 5 Unix using both the # compiler and translator. # ############################################################################ # # Links: random, wopen # ############################################################################ # # Requires: Version 9 graphics # ############################################################################ link random link wopen procedure main(args) local a, b, c, colours, coords, events, gap, i, k, n, r, size local startc, startr, t, x, xmand, y # check the number of arguments - if it's not 4, select 4 arbitrary values if *args == 4 then {startr:=args[1] startc:=args[2] size:=args[3] n:=args[4] n:=integer(n)} else {startr:=-1.5 startc:=-1.25 size:=2.5 n:=200} # set max size to 400 if (n>400) then n:=400 # calculate 'size' of each pixel gap:=size/n # open window xmand:=WOpen("label=xmand", "height="||n+40, "width="||n+40) | stop("Can't open xmand") # set colours to be 5 cycles of alternating black & white - this for the # benefit of those with monochrome screens, or (like me!), a crummy palette. colours:=["black","white"] colours:=colours|||colours|||colours|||colours|||colours # write image info in window GotoXY(xmand,20,35+n) writes(xmand,startr," ",startc," ",size," ",n) # this bit coupled with counting y *downwards* later, effectively means that # the image in the X-window is 'right way up' for those who live in a # cartesian world. startc+:=size # set up co-ordinates, one for every point in the display and randomize coords:=list(n*n,0) every i:=1 to n*n do coords[i]:=i-1 randomize() every !coords:=:?coords # main loop every i := 1 to n*n do {t:=get(coords) # compute random x,y value from co-ordinate x:=(t/n) y:=(t%n) # compute value of this x,y point in complex plane - count downwards in # y direction to get image 'right way up' r:=startr+x*gap c:=startc-y*gap a:=0 b:=0 # and calculate if point is in set or not every k:=1 to 100 do {t:=a*a-b*b+r b:=2*a*b+c a:=t if (a*a+b*b) > 4.0 then break} # scale final value of k to one of range of colours # subtract 1 to put in range 0->99; divide by 10 to put in range 0->9 # add 1 to put in range 1->10 - I have 10 'colours' selected # this scaling gives fairly unexciting displays, is there a better scaling # (eg: logarithmic, square root, w.h.y)? k-:=1 k/:=10 k+:=1 # and display Fg(xmand,colours[k]) DrawPoint(xmand,(x+20),(y+20)) # this bit bales out of loop if left button is pressed if (events:=Pending(xmand)) & (*events > 0) then if Event(xmand)==&lpress then break} WFlush(xmand) # just close the window and exit when it is finished Event(xmand) end