// Fractal contour plot,  Evgeny Demidov, 11 Feb 2002
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
public class ContourF extends java.applet.Applet
 implements ItemListener, ActionListener{
  int  Rc = 2, w, h, lbSize = 30, iM[], maxColor = 60;
  double M[];
  Choice chRc;    Label lbRc;    Button btNew;
  Image img;      IndexColorModel iColor;

public void init() {
  w = getSize().width;
  h = getSize().height - lbSize;

  int M=maxColor/3,  M2=2*M;
  long M4 = (long)M*M*M*M;
  byte rColor[] = new byte[maxColor+1], bColor[] = new byte[maxColor+1],
       gColor[] = new byte[maxColor+1];
  for (int i = 1; i < M2; i++){
    long dum = M - i;  dum *=dum;  dum *=dum;
    gColor[i] =  bColor[(i+M) % maxColor] = rColor[(i+M2) % maxColor] =
        (byte)(255 - (255*dum)/M4);}
  iColor = new IndexColorModel( 8, maxColor+1, rColor,gColor,bColor);

  lbRc = new Label("Rc", Label.RIGHT);  add(lbRc);
  chRc = new Choice();
  for (int i = 0, r = 1; i < 8; i++){
    chRc.addItem(Integer.toString(r));  r *= 2;}
  chRc.select("" + Rc);  chRc.addItemListener(this);  add(chRc);
  btNew = new Button("New");   btNew.addActionListener(this);
  add(btNew);
  averaging();
}
public void averaging(){
  double Vmin = 100, Vmax = -100, sV = 0, H = 2;

  int n=512, n1=n+1, nc=n, Max=n1*n1;

  M = new double[Max];
  while ( (nc /= 2) >= 1) {
    int ncn1 = nc*n1;    H /= 2;
    for (int j =ncn1; j < Max; j += ncn1+ncn1){
      for (int i = nc; i< n; i += nc+nc) {
        M[i+j] = (M[i+j+nc-ncn1] + M[i+j-nc+ncn1])/2.+H*(Math.random()-.5);
        M[i+j+nc] = (M[i+j+nc+ncn1] + M[i+j+nc-ncn1])/2.+H*(Math.random()-.5);
        M[i+j+ncn1] = (M[i+j-nc+ncn1] + M[i+j+nc+ncn1])/2.+H*(Math.random()-.5);
  }}}
  
  iM = new int[Max];
  for (int i = 0; i < Max; i++) iM[i] = (int)(40*(M[i]+1));
  img = createImage(new MemoryImageSource(n1, n1, iColor, iM, 0, n1));
}

public void paint(Graphics g) {
  g.drawImage(img, 0, lbSize, this);
}

public void itemStateChanged(ItemEvent e){
//  Rc = Integer.parseInt(chRc.getSelectedItem());
  averaging();
  repaint();
}
public void actionPerformed(ActionEvent e){
//  for (int i = 0; i < n; i++) p[i] = 2*Math.random() - 1;
  averaging();
  repaint();
}
public void update(Graphics g){ paint(g); }
}
