// Continuum percolation, Evgeny Demidov, 17 Feb 2002 import java.awt.*; import java.awt.event.*; import java.awt.image.*; public class @file extends java.applet.Applet implements ItemListener, ActionListener, MouseMotionListener{ int Rc = 8, Lc, w, h, lbSize = 30, iV[], maxColor = 9, cWhite = maxColor, cBlack = maxColor+1, hBar, hCol, nb[], delNb[]; double V[], f[][], G[][], Vo, sV, Vp = -.95; Choice chRc; Label lbRc; Button btNew; Image img, imBar; IndexColorModel iColor; long generTime; boolean bBurn = false; Checkbox cbBurn; public void init() { w = getSize().width - 30; h = getSize().height - lbSize; nb = new int[w*h]; delNb = new int[4]; delNb[0] = 1; delNb[1] = -1; delNb[2] = w; delNb[3] = -w; String s=getParameter("Rc"); if (s != null) Rc = Integer.parseInt(s); s=getParameter("Vp"); if (s != null) Vp = Double.valueOf(s).doubleValue(); V = new double[w*h]; iV = new int[w*(h+2)]; f = new double[h+64][w+64]; for (int i = 0; i < h+64; i++) for (int j = 0; j < w+64; j++) f[i][j] = 2*Math.random() - 1; // f[100][100] = 1; G = new double[32][32]; Lc = 2*Rc; double Rc2 = Rc*Rc; G[0][0] = 1; for (int i = 1; i < Lc; i++){ G[0][i] = Math.exp(-(i*i/Rc2)); for (int j = 1; j <= i; j++) G[j][i] = G[0][i]*G[0][j];} byte rColor[] = new byte[maxColor+2], bColor[] = new byte[maxColor+2], gColor[] = new byte[maxColor+2]; int M=maxColor/2; long M4 = (long)M*M*M*M; for (int i = 0; i < M; i++){ long dum = i; dum *=dum; dum *=dum; bColor[i] = gColor[M+i] = gColor[M-i] = rColor[maxColor-1-i] = (byte)(255 - (255*dum)/M4);} gColor[M] = (byte)220; rColor[cWhite] = gColor[cWhite] = bColor[cWhite] = (byte)255; iColor = new IndexColorModel( 8, maxColor+2, rColor,gColor,bColor); hCol = h/maxColor; hBar = maxColor*hCol; int cBar[] = new int[20*hBar], t = 0; for (int i = maxColor-1; i >=0; i--) for (int j = 0; j < hCol; j++) for (int k = 0; k < 20; k++) cBar[t++] = i; imBar = createImage(new MemoryImageSource(20, hBar, iColor, cBar, 0, 20)); lbRc = new Label("Rc", Label.RIGHT); add(lbRc); chRc = new Choice(); for (int i = 0, r = 1; i < 5; 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); s=getParameter("Burn"); if (s != null) bBurn = true; cbBurn = new Checkbox("Burn", bBurn); add(cbBurn); cbBurn.addItemListener(this); addMouseMotionListener(this); averaging(); } public void destroy(){ removeMouseMotionListener(this); } public void averaging(){ generTime = System.currentTimeMillis(); double Vmin = 100, Vmax = -100; sV = 0; int t = 0, w32 = w+32; for (int i = 32; i < h+32; i++){ for (int j = 32; j < w32; j++){ double s = G[0][0]*f[i][j]; for (int m = 1; m < Lc; m++){ int im = i+m, i_m = i-m, jm = j+m, j_m = j-m; s += G[0][m]*(f[im][j]+f[i_m][j]+f[i][jm]+f[i][j_m]) + G[m][m]*(f[im][jm]+f[i_m][jm]+f[im][j_m]+f[i_m][j_m]); for (int n = 1; n < m; n++){ int in = i+n, i_n = i-n, jn = j+n, j_n = j-n; s += G[n][m]*(f[im][jn]+f[i_m][jn]+f[im][j_n]+f[i_m][j_n] + f[in][jm]+f[i_n][jm]+f[in][j_m]+f[i_n][j_m]);}} V[t++] = s; if (s > Vmax) Vmax = s; if (s < Vmin) Vmin = s; sV += s;}} sV /= w*h; Vo = Vmax; if (Vmax < -Vmin) Vo = -Vmin; makeImg(); generTime = System.currentTimeMillis() - generTime; } public void makeImg(){ double a = .5*maxColor/Vo, tmp, VpVo = Vp*Vo; for (int i = 0; i < w*h; i++) if ((tmp = V[i]) < VpVo) iV[i+w] = cWhite; else iV[i+w] = (int)(a*(tmp+Vo)); if ( bBurn ){ int lastNb = -1; for (int i = w; i < 2*w; i++) if (iV[i] == cWhite) nb[++lastNb] = i; while ( lastNb >= 0){ int n = nb[lastNb--]; if (iV[n] == cWhite){ iV[n] = cBlack; for (int i = 0; i < 4; i++){ int t = n+delNb[i]; if (iV[t] == cWhite) nb[++lastNb] = t;}}}} if ( img != null) img.flush(); img = createImage(new MemoryImageSource(w, h, iColor, iV, w, w)); } public void paint(Graphics g) { g.drawImage(img, 0, lbSize, this); g.drawImage(imBar, w+10, lbSize, this); g.setColor(Color.white); int y = lbSize + (int)(hBar*(1 - sV/Vo)/2); g.drawLine(w+10, y, w+30, y); g.setColor(Color.black); y = lbSize + (int)(hBar*(1 - Vp)/2); g.drawLine(w+10, y, w+30, y); showStatus( "T=" + generTime + "ms "); } public void mouseMoved(MouseEvent e){} public void mouseDragged(MouseEvent e) { if( e.getX() > w){ int y = e.getY() - lbSize; Vp = 1 - y*2.0/hBar; if (Vp < -1) Vp = -1; if (Vp > 1) Vp = 1; makeImg(); repaint(); } } public void itemStateChanged(ItemEvent e){ Object src = e.getSource(); if (src == cbBurn){ bBurn = cbBurn.getState(); makeImg();} if (src == chRc){ Rc = Integer.parseInt(chRc.getSelectedItem()); Lc = 2*Rc; double Rc2 = Rc*Rc; G[0][0] = 1; for (int i = 1; i < Lc; i++){ G[0][i] = Math.exp(-(i*i/Rc2)); for (int j = 1; j <= i; j++) G[j][i] = G[0][i]*G[0][j];} averaging();} repaint(); } public void actionPerformed(ActionEvent e){ for (int i = 0; i < h+64; i++) for (int j = 0; j < w+64; j++) f[i][j] = 2*Math.random() - 1; averaging(); repaint(); } public void update(Graphics g){ paint(g); } }