/*****************************************************************************/
/** adapted from code by Gerhard W. Zumbusch, 1996 SINTEF, Oslo Norway       */
/** the changes are mostly cosmetic, speed improvment and simplificatons.    */
/*****************************************************************************/

import java.awt.*;

public class burger extends java.applet.Applet implements Runnable {
    Thread show;
    float func[];
    int width;
    int height;
    int height_sqr;
    int speed;
    int prevx;
    int prevy;

    private void define_function() {
      width      = size().width;
      height     = size().height;
      height_sqr = height*height; 
      func       = new float[width+1];
        for (int x=0 ; x<=width; x++) {
        float w = (width-x)/(float)width;
        func[x] = height/2*(float)(1+Math.sin(10.5f*3.1415692f*w*w*w));
      }
      prevx = -10;
    }

    private void calculate_function() {
      float old[] = new float[width+1];
      float w;
      float h = height+1;
      float a = 3.0f/height_sqr;
      for (int i=1; i<=5; i++) {
          for (int x=0; x<=width ; x++) { old[x] = h-func[x]; }
          for (int x=1; x< width ; x++) {
          if ((old[x]>0) && (old[x-1]>0))
              w = old[x]*old[x] - old[x-1]*old[x-1];
          else if ((old[x]<0) && (old[x+1]<0))
              w = old[x+1]*old[x+1]-old[x]*old[x];
          else w = 0;
          func[x] += a*w;
          }
        func[width] = func[width-1];
        func[0]     = func[1];
        if (prevx>=0) func[prevx] = prevy;
      }
    }

    private void draw_graph(Graphics g) {
        g.setColor(Color.white);
        g.fillRect(0,0,size().width,size().height);
        for (int x = 0 ; x < width ; x++) {
          g.setColor(new Color(0,0,100) );
          g.drawLine(x,(int)func[x],x+1, (int)func[x+1]);
        }
    }

    public void init() {
       String att = getParameter("speed");
       speed = (att==null) ? 400:(1000/Integer.valueOf(att).intValue());
    }

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

    public void start() {
      define_function();
      show = new Thread(this);
      show.start();
    }

    public void stop() {
      func = new float[0];
      width= -1;
      prevx= -1;
        show.stop();
    }

    public boolean mouseDown(Event e, int x, int y) {
      if (x<0) x=0; if (x>width) x=width;
      func[x] = y;
      prevx = x; prevy = y;
      repaint();
        return true;
    }

    public boolean mouseUp(Event e, int x, int y) {
      if (x<0) x=0; if (x>width) x=width;
      func[x] = y;
      prevx = -1; prevy = y;
      repaint();
        return true;
    }

    public boolean mouseDrag(Event e, int x, int y) {
      if (x<0) x = 0; if (x>width) x = width;
      if (x==prevx) { func[x] = y; } else if (x>prevx) {
        float h = (prevy-y)/(prevx-x);
        for (int i=prevx; i<=x; i++)
           func[i] = y + (int)((i-x) * h);
      } else {
        float h = (prevy-y)/(prevx-x);
        for (int i=x; i<=prevx; i++)
           func[i] = y + (int)((i-x) * h);
      }
      prevx = x; prevy = y;      
      repaint();
        return true;
    }

  public void update(Graphics g) {
      g.clearRect(0,0,size().width, size().height);
      paint(g);
  }

  public void run() {
    while (true) {
      try {Thread.currentThread().sleep(speed);}
      catch (InterruptedException e){}
      if (width != size().width) define_function();
      repaint();
      calculate_function();
    }
  }
}
