
import java.awt. *;

public class DrawIterate extends java.awt.Canvas
{

  private int xpoint, ypoint;
  private int xoffset, yoffset, xsize, ysize;
  private double xscale, yscale, xmin, xmax, ymin, ymax;

  private Image image2;
  private Graphics g2;
  private Dimension oldSize;

  private int xp[], yp[];
  private int MAXPOINTS = 5000;
  private int lastPoint;
  private double oldA1, oldA2;
  private BifurcateApplet app;

// default constructor - allocates arrays etc 

    DrawIterate (BifurcateApplet ref)
  {
    xp = new int[MAXPOINTS];
      yp = new int[MAXPOINTS];
      setBackground (Color.white);
      app = ref;
  }

// clear screen when change parameter or starting iterate

  public void clearScreen ()
  {
    lastPoint = -1;
  }

// formatting method for writing doubles

  private double myformat (double x, int n)
  {
    double d;
    int i;
      d = x * n;
      i = (int) d;
      d = (double) i / (double) n;
      return (d);
  }

// determines sizes, scaling etc 

  private void determineSize ()
  {

// physical sizes first

    xmin = app.mycom.getA1 ();
    xmax = app.mycom.getA2 ();
    ymin = -2.0;
    ymax = 2.0;

// pixel stuff now

    xoffset = 40;
    yoffset = 40;
    xsize = this.size ().width - 2 * xoffset;
    ysize = this.size ().height - 2 * yoffset;
    yoffset = yoffset + ysize;

// scaling required

    xscale = (double) xsize / (xmax - xmin);
    yscale = -(double) ysize / (ymax - ymin);

  }

// computes local coords on new point and paints to screen 

  public void addPoints (double x, double y)
  {

// wrap around in x

    xpoint = (int) ((x - xmin) * xscale) + xoffset;
    ypoint = (int) ((y - ymin) * yscale) + yoffset;

    if (++lastPoint >= MAXPOINTS)
      {
	lastPoint = 0;
      }
    xp[lastPoint] = xpoint;
    yp[lastPoint] = ypoint;

    repaint ();

  }

// if parameters change or resize need to recompute size stuff

  public void paint (Graphics g)
  {

    if (g2 == null)
      {
	paintSetup ();
	determineSize ();
      }
    else if ((this.size ().width != oldSize.width) ||
	       (this.size ().height != oldSize.height))
        paintSetup ();
    else if ((app.mycom.getA1 () != oldA1) || (app.mycom.getA2 () != oldA2))
      {
	paintSetup ();
	determineSize ();
      }


// double buffering here

    g2.setColor (this.getBackground ());
    g2.fillRect (0, 0, oldSize.width, oldSize.height);

    draw_Axes ();

    g2.setColor (Color.blue);
    for (int i = 0; i <= lastPoint; i++)
      g2.fillOval (xp[i] - 2, yp[i] - 2, 4, 4);

    g.drawImage (image2, 0, 0, this);

  }

  private void paintSetup ()
  {
    oldSize = this.size ();
    oldA1 = app.mycom.getA1 ();
    oldA2 = app.mycom.getA2 ();

    image2 = createImage (oldSize.width, oldSize.height);
    g2 = image2.getGraphics ();
  }


  public void update (Graphics g)
  {
    paint (g);
  }

  private void draw_Axes ()
  {
    int i, ix;
    double x;

      g2.setColor (Color.black);
      g2.drawLine (xoffset, yoffset, xsize + xoffset, yoffset);
      g2.drawLine (xoffset, yoffset, xoffset, yoffset - ysize);

    for (i = 0; i <= 10; i++)
      {
	x = myformat ((double) (xmin + i * (xmax - xmin) / 10.0), 100);
	g2.drawString (String.valueOf (x),
	(int) ((i * (xmax - xmin) / 10.0) * xscale + xoffset), yoffset + 10);
      }

    for (i = 0; i <= 3; i++)
      {
	x = myformat ((double) (ymin + i * (ymax - ymin) / 3.0), 100);
	g2.drawString (String.valueOf (x),
		  10, (int) ((i * (ymax - ymin) / 3.0) * yscale) + yoffset);
      }
    return;
  }

}

