// 3D percolating cluster, Evgeny Demidov, 17 Dec 2001 import java.awt.*; import java.awt.event.*; import java.util.StringTokenizer; public class @file extends java.applet.Applet implements MouseListener, MouseMotionListener, KeyListener, ActionListener{ int w,h, h2,w2, mx0,my0, iCol[], maxCl, hBut = 30, xi[],yi[],zi[], x1[],y1[],zs[], Fx[][],Fy[][], L = 30, L1, cl[][][]; double p = .312, fiX = .2, fiY = .3, dfi = .01, scale, z1[]; boolean painted = false; Image buffImage; Graphics buffGraphics; Label lbP; TextField tfP; Button btNew; Color[] col; public void init() { w = getSize().width; h = getSize().height - hBut; h2=h/2; w2=w/2; String s=getParameter("L"); if (s != null) L = Integer.parseInt(s); s=getParameter("p"); if (s != null) p = Double.valueOf(s).doubleValue(); int L3 = L*L*L, L2 = L+2; L1 = L+1; scale = w2/(Math.sqrt(3.)*L); xi = new int[L3]; yi = new int[L3]; zi = new int[L3]; x1 = new int[L3]; y1 = new int[L3]; zs = new int[L3]; z1 = new double[L3]; for (int i = 0; i < maxCl; i++){ xi[i] = 2*(int)(10*(Math.random() - .5)); yi[i] = 2*(int)(10*(Math.random() - .5)); zi[i] = 2*(int)(10*(Math.random() - .5)); zs[i] = i;} cl = new int[L2][L2][L2]; for (int i = 0; i < L2; i++) for (int j = 0; j < L2; j++) for (int k = 0; k < L2; k++) cl[i][j][k] = -1; Fx = new int[3][]; Fy = new int[3][]; // 3 cube faces for (int i = 0; i < 3; i++){ Fx[i] = new int[4]; Fy[i] = new int[4];} col = new Color[256]; for (int i = 0; i < 256; i++) col[i] = new Color(i, i, i); iCol = new int[3]; buffImage = createImage(w, h); buffGraphics = buffImage.getGraphics(); addMouseListener(this); addMouseMotionListener(this); lbP = new Label("p", Label.RIGHT); add(lbP); tfP = new TextField( "" + (float)p, 5); add(tfP); tfP.addKeyListener(this); btNew = new Button("New"); btNew.addActionListener(this); add(btNew); built(); } public void built(){ for (int i = 1; i < L1; i++) for (int j = 1; j < L1; j++) for (int k = 1; k < L1; k++) cl[i][j][k] = 0; int i0 = L/2, dx[] = {1,-1,0,0,0,0}, dy[] = {0,0,1,-1,0,0}, dz[] = {0,0,0,0,1,-1}; cl[i0][i0][i0] = 1; for (int i = 0; i < 6; i++) cl[(xi[i]=i0+dx[i])][(yi[i]=i0+dy[i])][(zi[i]=i0+dz[i])] = 2; int nb = 5; do{ int n = nb--, xn = xi[n], yn = yi[n], zn = zi[n]; if (cl[xn][yn][zn] == 2){ if (Math.random() > p) cl[xn][yn][zn] = -1; else{ cl[xn][yn][zn] = 1; for (int i = 0; i < 6; i++){ int xt = xn+dx[i], yt = yn+dy[i], zt = zn+dz[i]; if (cl[xt][yt][zt] == 0){ cl[xt][yt][zt] = 2; xi[++nb] = xt; yi[nb] = yt; zi[nb] = zt;}}}} } while (nb >= 0); maxCl = 0; for (int i = 1; i < L1; i++) for (int j = 1; j < L1; j++) for (int k = 1; k < L1; k++) if (cl[i][j][k] == 1){ xi[maxCl] = 2*(i-i0); yi[maxCl] = 2*(j-i0); zi[maxCl++] = 2*(k-i0);} for (int i = 0; i < maxCl; i++) zs[i] = i; rotate(); } public void destroy(){ removeMouseListener(this); removeMouseMotionListener(this); } public void mouseClicked(MouseEvent e){} // event handling public void mousePressed(MouseEvent e) { mx0 = e.getX(); my0 = e.getY(); e.consume(); } public void mouseReleased(MouseEvent e){} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mouseDragged(MouseEvent e) { int x1 = e.getX(); int y1 = e.getY(); if ( e.isShiftDown() ) scale *= Math.exp(-(y1 - my0)/(double)w); else fiX += dfi*(y1 - my0); fiY += dfi*(x1 - mx0); mx0 = x1; my0 = y1; rotate(); repaint(); e.consume(); } public void mouseMoved(MouseEvent e){} public void keyTyped(KeyEvent e){} public void keyPressed(KeyEvent e){} public void keyReleased(KeyEvent e){ final int keyEnter = 10; if (e.getKeyCode() == keyEnter){ try{ p = Double.valueOf(tfP.getText()).doubleValue(); }catch(NumberFormatException ne){} built(); repaint(); } e.consume(); } public void actionPerformed(ActionEvent e){ built(); repaint(); } public void rotate(){ double ct = Math.cos(fiX), cf = Math.cos(fiY), st = Math.sin(fiX), sf = Math.sin(fiY), ix = scale*cf, kx = scale*sf, iy = scale*st*sf, jy = scale*ct, ky = -scale*st*cf, iz = -255*ct*sf, jz = 255*st, kz = 255*ct*cf; int Vx[] = {(int)(ix+kx), (int)(ix+kx), (int)(ix-kx), (int)(ix-kx), // cube (int)(-ix+kx),(int)(-ix+kx),(int)(-ix-kx),(int)(-ix-kx)}, Vy[] = {(int)(iy+jy+ky), (int)(iy-jy+ky), (int)(iy-jy-ky), (int)(iy+jy-ky), (int)(-iy+jy+ky),(int)(-iy-jy+ky),(int)(-iy-jy-ky),(int)(-iy+jy-ky)}, x0123[] = {Vx[0],Vx[1],Vx[2],Vx[3]}, y0123[] = {Vy[0],Vy[1],Vy[2],Vy[3]}, x4567[] = {Vx[4],Vx[5],Vx[6],Vx[7]}, y4567[] = {Vy[4],Vy[5],Vy[6],Vy[7]}, x0374[] = {Vx[0],Vx[3],Vx[7],Vx[4]}, y0374[] = {Vy[0],Vy[3],Vy[7],Vy[4]}, x1265[] = {Vx[1],Vx[2],Vx[6],Vx[5]}, y1265[] = {Vy[1],Vy[2],Vy[6],Vy[5]}, x0451[] = {Vx[0],Vx[4],Vx[5],Vx[1]}, y0451[] = {Vy[0],Vy[4],Vy[5],Vy[1]}, x3762[] = {Vx[3],Vx[7],Vx[6],Vx[2]}, y3762[] = {Vy[3],Vy[7],Vy[6],Vy[2]}; if (iz > 0){ Fx[0] = x0123; Fy[0] = y0123;} else{ Fx[0] = x4567; Fy[0] = y4567;} if (jz > 0){ Fx[1] = x0374; Fy[1] = y0374;} else{ Fx[1] = x1265; Fy[1] = y1265;} if (kz > 0){ Fx[2] = x0451; Fy[2] = y0451;} else{ Fx[2] = x3762; Fy[2] = y3762;} iCol[0] = (int)Math.abs(iz); iCol[1] = (int)Math.abs(jz); iCol[2] = (int)Math.abs(kz); for (int i = 0; i < maxCl; i++){ // clusters grid x1[i] = (int)(ix*xi[i] + kx*zi[i]); y1[i] = (int)(iy*xi[i] + jy*yi[i] + ky*zi[i]); z1[i] = iz*xi[i] + jz*yi[i] + kz*zi[i];} //System.out.println(" Hi"+" "); for (int i = maxCl - 1; --i >= 0;){ boolean flipped = false; for (int j = 0; j <= i; j++) { int a = zs[j], b = zs[j + 1]; if (z1[a] > z1[b]) { zs[j + 1] = a; zs[j] = b; flipped = true; } } if (!flipped) break; } painted = false; } public void paint(Graphics g) { if ( !painted ){ int px[] = new int[4], py[] = new int[4]; buffGraphics.setColor(Color.blue); buffGraphics.fillRect(0, 0, w, h); for (int l = 0; l < maxCl; l++){ int k = zs[l]; for (int i = 0; i < 3; i++){ for (int j = 0; j < 4; j++){ px[j] = w2 + x1[k] + Fx[i][j]; py[j] = h2 - y1[k] - Fy[i][j];} buffGraphics.setColor(col[iCol[i]]); buffGraphics.fillPolygon(px,py, 4);} } painted = true;} g.drawImage(buffImage, 0,hBut, this); showStatus( "fiX=" + (int)(360*fiX) + " fiY=" + (int)(360*fiY)); } public void update(Graphics g) { paint(g); } }