import java.applet.Applet; import java.awt.image.*; import java.awt.*; import java.lang.Math; class Controls { double max; Scrollbar rate, amount; public double getRate() { return rate.getValue()/max; } public double getAmount() { return amount.getValue()/max; } } class Coords { double x, y; Coords(double x, double y) { this.x=x; this.y=y; } } interface AffMap { AffMap mutate(); Coords apply(Coords coords); } class oAffineMap implements AffMap { double elt[]; Controls controls; oAffineMap(Controls c) { elt=new double[6]; controls = c; do { for (int i=0; i<6; i++) elt[i]=2.0*Math.random()-1.0; } while (!isContraction()); } public AffMap mutate() { oAffineMap map=new oAffineMap(controls); do { for (int i=0; i<6; i++) if (Math.random()>controls.getRate()) map.elt[i]=elt[i]+(Math.random()-0.5)*controls.getAmount(); else map.elt[i]=elt[i]; } while (!map.isContraction()); return map; } public Coords apply(Coords coord) { return new Coords(elt[0]*coord.x+elt[1]*coord.y+elt[2], elt[3]*coord.x+elt[4]*coord.y+elt[5]); } public boolean isContraction() { double a=elt[0]*elt[0]+elt[1]*elt[1]; double b=elt[0]*elt[3]+elt[1]*elt[4]; double c=b; double d=elt[3]*elt[3]+elt[4]*elt[4]; double aa=-1; double bb=-a-d; double cc=a*d-b*c; double det=Math.sqrt(bb*bb-4*aa*cc); double s1=(-bb+det)/(2*aa); double s2=(-bb-det)/(2*aa); double max=s1; if (s2>max) max=s2; return (max<1.0); } } class AffineMap implements AffMap { double elt[]; double h, k; // Translation double theta, phi; // Rotation double r, s; // Scaling Controls controls; AffineMap(Controls c) { controls = c; elt = new double[6]; do { h = 2.0*Math.random()-1.0; k = 2.0*Math.random()-1.0; theta = 4.0*Math.PI*Math.random()-2.0*Math.PI; phi = 4.0*Math.PI*Math.random()-2.0*Math.PI; r = 2.0*Math.random()-1.0; s = 2.0*Math.random()-1.0; elt[0] = r*Math.cos(theta); elt[1] = -s*Math.sin(phi); elt[2] = h; elt[3] = r*Math.sin(theta); elt[4] = s*Math.cos(phi); elt[5] =k; } while (!isContraction()); } public AffMap mutate() { AffineMap map=new AffineMap(controls); double rate = controls.getRate(); double amount = controls.getAmount(); do { if (Math.random()>rate) map.h = h + (Math.random()-0.5)*amount; else map.h = h; if (Math.random()>rate) map.k = k + (Math.random()-0.5)*amount; else map.k = k; if (Math.random()>rate) map.theta = theta + (Math.random()-0.5)*amount; else map.theta = theta; if (Math.random()>rate) map.phi = phi + (Math.random()-0.5)*amount; else map.phi = phi; if (Math.random()>rate) map.r = r + (Math.random()-0.5)*amount; else map.r = r; if (Math.random()>rate) map.s = s + (Math.random()-0.5)*amount; else map.s = s; map.elt[0] = map.r*Math.cos(theta); map.elt[1] = -map.s*Math.sin(phi); map.elt[2] = map.h; map.elt[3] = map.r*Math.sin(theta); map.elt[4] = map.s*Math.cos(phi); map.elt[5] = map.k; } while (!map.isContraction()); return map; } public Coords apply(Coords coord) { return new Coords(elt[0]*coord.x+elt[1]*coord.y+elt[2], elt[3]*coord.x+elt[4]*coord.y+elt[5]); } public boolean isContraction() { double a=elt[0]*elt[0]+elt[1]*elt[1]; double b=elt[0]*elt[3]+elt[1]*elt[4]; double c=b; double d=elt[3]*elt[3]+elt[4]*elt[4]; double aa=-1; double bb=-a-d; double cc=a*d-b*c; double det=Math.sqrt(bb*bb-4*aa*cc); double s1=(-bb+det)/(2*aa); double s2=(-bb-det)/(2*aa); double max=s1; if (s2>max) max=s2; return (max<1.0); } } class IFS { int sizex, sizey; AffMap maps[]; double probs[]; double cutoffs[]; Image img; Controls controls; static IndexColorModel cm; static int numMaps; static int numPoints; static { numMaps=4; numPoints=2000; byte red[]=new byte[256]; byte green[]=new byte[256]; byte blue[]=new byte[256]; byte alpha[]=new byte[256]; red[0]=(byte)0; green[0]=(byte)0; blue[0]=(byte)0; alpha[0]=(byte)0; red[1]=(byte)0; green[1]=(byte)0; blue[1]=(byte)255; alpha[1]=(byte)255; cm=new IndexColorModel(8,256,red,green,blue,alpha); } IFS(int sx, int sy, Controls c) { sizex=sx; sizey=sy; controls = c; maps=new AffMap[numMaps]; probs=new double[numMaps]; cutoffs=new double[numMaps]; for (int i=0; icutoffs[i]) i++; return i; } synchronized Image getImage(Component comp) { if (img==null) { Coords xy=new Coords(0,0); for (int i=0; i<10; i++) xy=maps[pickMap()].apply(xy); double minx=xy.x, maxx=xy.x, miny=xy.y, maxy=xy.y; Coords coords[]=new Coords[numPoints]; coords[0]=xy; for (int i=1; i=0 && y>=0 && xcontrols.getRate()) probs[i]=ifs.probs[i]+Math.random()*controls.getAmount()*2.0- controls.getAmount(); probs[i]=ifs.probs[i]; } while (probs[i]<=0.0); } normalizeProbs(); } } } class Population extends Canvas { IFS genomes[]; int numx, numy, sizex, sizey; Population(int numx, int numy, int sizex, int sizey, Controls c) { genomes=new IFS[numx*numy]; this.numx=numx; this.numy=numy; this.sizex=sizex; this.sizey=sizey; resize(numx*sizex,numy*sizey); for (int i=0; i