/** Mandelbrot Set Generator by Robert John Morton 27 October 1997 */ import java.awt.*; import javax.swing.*; import java.awt.image.BufferedImage; public class mandelgraph extends JPanel implements Runnable { private int XE, // Horizontal extent of window and JFrame. YE, // Vertical extent of window and JFrame. XBIAS = 225, YBIAS = 190, // pixel co-ordinates of real point 0,0 XMAX = 350, YMAX = 380, // dimensions of the display area (pixels) i, j, v = 0; private long tf = 150, // inter-plot time frame (milliseconds) t; // current system time private double Scale = 100; // pixels per unit real eg 100 pixels = 1.00d private boolean finished = false; private Color colour, // current plot colour C[], A[][]; // create colour array for display area private BufferedImage I; // off-screen image on which to plot the graph private Graphics2D gi; // graphics reference for off-screen image private Thread T; // declare a thread reference variable public mandelgraph(int XE, int YE) { this.XE = XE; // horizontal [X] dimension of the JPanel this.YE = YE; // vertical [Y] dimension of the JPanel setBounds(0,0,XE,YE); // the JPanel fills the whole of the JFrame area setLayout(null); // JPanel has free-form layout [for graph] /* Create a Buffered Image "I" on which to plot Henon's Attractor off- screen and get its graphics context "gi" for realising the plots. */ I = new BufferedImage(XE,YE,BufferedImage.TYPE_INT_RGB); gi = I.createGraphics(); /* Create colours for the display. The first colour represents convergence of the Mandelbrot series after only one iteration. Successive colours represent convergence after 2, 3, 4... iterationas and so on up to 20. */ C = new Color[20]; C[ 0] = Color.lightGray; C[ 1] = new Color( 0, 0, 128); C[ 2] = new Color( 0, 136, 0); C[ 3] = new Color(144, 0, 0); C[ 4] = new Color( 0, 152, 152); C[ 5] = new Color(160, 0, 160); C[ 6] = new Color(168, 168, 0); C[ 7] = new Color(176, 176, 176); C[ 8] = new Color( 16, 16, 184); C[ 9] = new Color( 16, 192, 16); C[10] = new Color(200, 16, 16); C[11] = new Color( 16, 208, 208); C[12] = new Color(216, 16, 216); C[13] = new Color(224, 224, 16); C[14] = new Color(232, 232, 232); C[15] = new Color( 64, 64, 240); C[16] = new Color( 64, 248, 64); C[17] = new Color(252, 64, 64); C[18] = new Color(255, 255, 64); C[19] = new Color(255, 255, 255); A = new Color[XMAX][YMAX]; // create colour array for display area for(i = 0; i < XMAX; i++) // clear colour array to background colour for(j = 0; j < YMAX; j++) A[i][j] = Color.black; // Set the system time at which the next plot's time frame must end. t = System.currentTimeMillis() + tf; T = new Thread(this); // creating the thread object T.start(); // and starting it running by } public void paint(Graphics g) { // PAINT / RE-PAINT THE PICTURE SO FAR g.drawImage(I,20,20,this); // display the buffered image } private void initialPlot() { for(j = 0; j < YMAX; j++) { // for each of the 180 lines in the picture int I = 0, // starting dot of next single-colour stretch of line i = 0; // to find next pixel in current line with a different colour colour = A[I][j]; // make colour of first dot the reference colour while(++i < XMAX){ // while not yet reached end of current line // If this dot is a different colour from the previous dot if(colour != A[i][j]) { gi.setColor(colour); // set colour to colour of previous dot gi.drawLine(I,j,i-1,j); // draw line from start dot to previous colour = A[I = i][j]; // make reference colour that of this dot } } gi.setColor(colour); // set colour for final stretch of current line gi.drawLine(I,j,i-1,j); // draw the last stretch of the current line } } private void currentPlot() { if(v < YMAX) { // if last line not yet painted int I = 0, // start pixel for current colour i = 0; // current pixel of current colour colour = A[I][v]; // make colour of first dot the reference colour while(++i < XMAX) { // for each pixel on the current line... double x = .01, // reset values to start another convergence test y = .01, z, /* Convert the current pixel co-ordinates to real co-ordinates on the complex plane. */ cx = (double)(i-XBIAS)/Scale, cy = (double)(YBIAS-v)/Scale; for(int k = 0; k < 128; k++){ // if not yet completed 128 iterations z = x * y; // Compute and add in the next term of x = x * x - y * y + cx; // the complex series. y = z + z + cy; /* If the value of the complex quantity has gone beyond the bounds of the display area. */ if(x < -2.6 || x > 1.6 ||y < -2.75 || y > 2.75) { if(k > 19) k = 19; // max number of iterations for divergence A[i][v] = C[k]; // store the pixel colour break; } } if(colour != A[i][v]) { // if colour has changed then set it gi.setColor(colour); // according to number of iterations gi.drawLine(I,v,i-1,v); // draw the plot colour = A[I = i][v]; // set current colour as reference colour } } gi.setColor(colour); // set colour for final stretch of current line gi.drawLine(I,v,i-1,v); // draw the last stretch of the current line v++; // advance downwards to the next line } else finished = true; } public void run() { // run the Track Recorder painting thread initialPlot(); // set up colour array while(true) { // permanent loop if(!finished) { currentPlot(); // do current plot in buffered image repaint(); // paint in the next plot on the screen } /* Get the time left in this plot's time frame and if it is less than 5 milliseconds, set it to 5 milliseconds. */ long s = t - System.currentTimeMillis(); if(s < 5) s = 5; /* Sleep for the remainder of the time frame. If an external interrupt occurs during this time, catch it and process it. */ try{Thread.currentThread().sleep(s); } catch (InterruptedException e) { } // Set the system time at which the next plot's time frame will end t = System.currentTimeMillis() + tf; } } }