Bifurcation Map Generator

The following code is that of the java applet which generates the bifurcation map for the equation x = cx(1 - x).
/**
  * Bifurcation Map Generator for x = cx(1 - x)
  * @author Robert J Morton
  * @version 5 December 1997
*/

import java.awt.*;

public class bifmap1 extends java.applet.Applet implements Runnable {
   int H = 17, V = 15;                                //top and left margins (in pixels)
   int X, Y;                                          //dimensions of display window (in pixels)
   int x, y;                                          //co-ords of resultant plot (in pixels)
   int scale = 160;                                   //number of pixels per 1.0 real
   int cMAX = scale * 3 + 1, rMAX = scale + 1;        //dimensions of the plotting area
   int W = V + scale;                                 //origin on the vertical scale
   double r;                                          //the 'real' variable
   double c;                                          //the 'real' constant
   double Scale = (int)(scale);                       //pixels per unit 'real' (100 pixels = 1.00)
   int I;                                             //number of iterations of x = x * x + c
   int i;                                             //current iteration number of the above
   boolean finished = false;                          //indicates when the map has been completed
   Image buffer = null;                               //reference for an off-screen image buffer
   Graphics gc = null;                                //graphics context for the off-screen image
   Color bg, tc, ac;                                  //background colour, trace colour, attractor colour
   Color A[][];                                       //pixel array to minimise calls to drawLine()
   Thread Bif;                                        //thread reference variable for this program
   long TimeFrame = 150;                              //inter-plot time frame (milliseconds)
   long T;                                            //future system time at which a new plot is due to begin

   public void init() {                               //NORMAL APPLET INITIALISER METHOD
      int j, k;                                       //utility loop variables
      bg = Color.lightGray;                           //set background colour
      ac = new Color(  0, 128,  64);                  //create the trace colour
      tc = new Color(  0, 255, 128);                  //create the attractor colour
      Dimension d = size();                           //get size of window as given in HTML applet tag
      X = d.width; Y = d.height;                      //establish window width and height
      buffer = createImage(X, Y);                     //create the off-screen image buffer
      gc = buffer.getGraphics();                      //graphics context reference for the off-screen image
      gc.setColor(Color.lightGray);                   //set background colour for the off-screen image
      gc.fillRect(0, 0, X, Y);                        //paint the background colour for the off-screen image
      A = new Color[cMAX][rMAX];                      //create a pixel array for pixels
      for(j = 0 ; j < cMAX ; j++)                     //and set them all to light grey
         for(k = 0 ; k < rMAX ; k++)                  //Pixels are plotted in here so they can be checked
            A[j][k] = bg;                             //to avoid having to call drawLine() unnecessarily.

      gc.setColor(Color.gray);                        //set colour for scale lines
      j = H - 5;                                      //start of scale marks for vertical scale 
      gc.drawLine(H, V, H, W);                        //draw the vertical scale line
      int di = scale / 5;                             //increment between scale marks on vertical scale
      for(i = 0 ; i <= scale; i += di)                //At each mark position on vertical scale
         gc.drawLine(j, V + i, H, V + i);             // draw the vertical scale's scale marks.

      I = scale * 3;                                  //length of the horizontal scale
      j = W + 5;                                      //bottom of scale marks for horizontal scale
      gc.drawLine(H, W, H + I, W);                    //draw the horizontal scale line
      di = scale / 2;                                 //increment between scale marks
      for(i = 0 ; i <= I; i += di)                    //At each scale mark position
         gc.drawLine(H + i, W, H + i, j);             // draw a scale mark.

      Font font = new Font("Dialog", Font.PLAIN, 12); //choose the font for the text in this applet
      gc.setFont(font);
      int h = H - 15,                                 //horizontal co-ordinate of vertical scale figures
          v = V + 3;                                  //start position of vertical co-ordinates
      gc.drawString("1",  h + 4, v);                  //number the vertical axis
      gc.drawString(".8", h, v + (int)(scale * .2));
      gc.drawString(".6", h, v + (int)(scale * .4));
      gc.drawString(".4", h, v + (int)(scale * .6));
      gc.drawString(".2", h, v + (int)(scale * .8));
      gc.drawString("0",  h + 3, v + scale);
      h = H - 2;                                      //start position of horizontal scale figures
      v = V + scale + 16;                             //vertical co-ord of base of figures for horiz scale
      gc.drawString("1", h, v);                       //number horizontal scale
      gc.drawString("2", h + scale, v);
      gc.drawString("3", h + (int)(Scale * 2), v);
      gc.drawString("4", h + (int)(Scale * 3), v);
      gc.setColor(Color.black);                       //set color for lettering
      gc.drawString("x", H - 2, V - 4);               //label the vertical axis
      gc.drawString("c", H + 485, W + 2);             //label the horizontal
      x = 0;                                          //set to start map from right-hand edge
      T = System.currentTimeMillis()  + TimeFrame;    //end of first plot's time frame
   }

   public void paint(Graphics g) {                    //PAINT / RE-PAINT THE PICTURE SO FAR
      g.drawImage(buffer, 0, 0, null);                //(re)draw from the off-screen image buffer
   }

   public void update(Graphics g) {                   //called in response a request for a repaint()
      Color C = tc;                                   //set current colour to aura trace colour
      if(x < cMAX) {                                  //if not yet reached end of c axis
         c = (double)(x) / Scale + 1;                 //real c value corresponding to current x-pixel
         r = .01;                                     //Reset r for a new iteration run
         for(i = 0; i < 10000; i++) {                 //for I (further) iterations
            if(i > 100) C = ac;                       //change colour when r has had time to settle
            r = c * r * (1 - r);                      //advance the iteration process
            if(r >= 1 || r <= 0) break;               //bail out if r gone off screen
            y = (int)(r * Scale);                     //y-plot for current value of r
            Color K = A[x][y];                        //current colour of corresponding pixel
            if(K == bg || C == ac && K == tc) {       //if pixel needs to be drawn
               A[x][y] = C;                           //set pixel element to appropriate trace colour
               int h = H + x, v = W - y;              //applet window co-ords of new plot
               gc.setColor(C);                        //set colour for final stretch of current line
               gc.drawLine(h, v, h, v);               //draw line from start dot to previous dot
               g.setColor(C);                         //set colour for final stretch of current line
               g.drawLine(h, v, h, v);                //draw line from start dot to previous dot
            }
         } x++;                                       //advance right one pixel
      } else finished = true;                         //if we've completed the attractor, the map is finished
   }

   public void run() {                                //run the Track Recorder painting thread
      while(true) {                                   //permanent loop
         if(!finished) repaint();                     //paint in the next plot
         long s = T - System.currentTimeMillis();     //get time left in this plot's time frame
         if(s < 5) s = 5;                             //in case machine isn't fast enough
         try { Thread.currentThread().sleep(s);       //sleep for the time remaining
         } catch (InterruptedException e) { }         //catch interrupt from GUI or browser
         T = System.currentTimeMillis() + TimeFrame;  //get when next plot's time frame will end
      }
   }

   public void start() {                              //Start the program thread by
      Bif = new Thread(this);                         //creating the thread object
      Bif.start();                                    //and starting it running by
   }                                                  //requesting a call to run()

   public void stop() { Bif.stop(); }                 //Stop this a program thread

/*  Robert J Morton, the author of this program, 
    is a poor but Right Honourable Fellow of the
    Ancient and Noble Order of the Long-term Unemployed.

    Offers of work please to: robmorton@clara.net  */
}

This page's parent within this Web Site. About this Web Site. Its home page. Email its Author.