// Direct algorithm, Evgeny Demidov, 11 November 2002 import java.awt.*; import java.awt.image.*; import java.awt.event.*; import java.util.StringTokenizer; public class @file extends java.applet.Applet implements MouseListener { double maxIZI2=10., Ymid=.0, Xmid=-.5, DelX=3., paramC,paramD; int MaxIt = 256, maxColor = 96, w, h, pixArr[]; Image img; IndexColorModel RainbowColor; long generTime; boolean showXY = true; FormulaD formD; TextField tfXY; public void init() { String s=getParameter("XYmidDelCD"); if (s != null) { StringTokenizer st = new StringTokenizer(s); Xmid = Double.valueOf(st.nextToken()).doubleValue(); Ymid = Double.valueOf(st.nextToken()).doubleValue(); DelX = Double.valueOf(st.nextToken()).doubleValue(); paramC = Double.valueOf(st.nextToken()).doubleValue(); paramD = Double.valueOf(st.nextToken()).doubleValue();} s=getParameter("MaxIt"); if (s != null) MaxIt=Integer.parseInt(s); s=getParameter("MaxIZI2"); if (s != null) maxIZI2 = Double.valueOf(s).doubleValue(); s=getParameter("MaxColor"); if (s != null) maxColor=Integer.parseInt(s); int M=maxColor/3, M2=2*M; maxColor = 3*M; // maxColor is 3*int long M4 = (long)M*M*M*M; byte rColor[] = new byte[maxColor+2], bColor[] = new byte[maxColor+2], gColor[] = new byte[maxColor+2]; for (int i = 1; i < M2; i++){ // set Color Map long dum = M - i; dum *=dum; dum *=dum; gColor[i] = bColor[(i+M) % maxColor] = rColor[(i+M2) % maxColor] = (byte)(255 - (255*dum)/M4);} rColor[maxColor+1] = gColor[maxColor+1] = bColor[maxColor+1] = (byte)200; RainbowColor = new IndexColorModel( 8, maxColor+2, rColor,gColor,bColor); w = getSize().width; h = getSize().height; s=getParameter("showXY"); if ( (s != null) && (s.equalsIgnoreCase("N")) ) showXY = false; else{ setLayout(new BorderLayout()); if (Ymid < 0.) s = ""+Xmid+" "+Ymid+"*i; "+(float)DelX; else s = ""+Xmid+" +"+Ymid+"*i; "+(float)DelX; tfXY = new TextField( s ); add("South", tfXY); h -= tfXY.getPreferredSize().height;} pixArr = new int[w*(h+2)]; s=getParameter("Formula"); if (s != null) try{ formD = (FormulaD)Class.forName( s ).newInstance(); }catch(Exception e){} else formD = new DirectJ3(); Draw(Xmid, Ymid, DelX/w, formD, paramC, paramD ); addMouseListener(this); } public void destroy() { removeMouseListener(this); } public void mouseClicked(MouseEvent e) {} //1.1 event handling public void mousePressed(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mouseReleased(MouseEvent e) { Xmid = Xmid+(e.getX()-w/2)*DelX/w; Ymid = Ymid-(e.getY()-h/2)*DelX/w; if ( e.isControlDown() ) { if ( e.isShiftDown() ) DelX *=4.; else DelX *=2.;} else { if ( e.isShiftDown() ) DelX /=4.; else DelX /=2.;} Draw(Xmid, Ymid, DelX/w, formD, paramC, paramD); if (showXY) { if (Ymid < 0.) tfXY.setText( ""+Xmid+" "+Ymid+"*i; "+(float)DelX); else tfXY.setText( ""+Xmid+" +"+Ymid+"*i; "+(float)DelX);}; repaint(); } public void paint(Graphics g) { g.drawImage(img, 0, 0, this); if (DelX > .01) drawLabel(g); showStatus( "Time=" + generTime + " msec"); } public void drawLabel(Graphics gra) { double R=0.,I=0., StZ=DelX/w; gra.setColor(Color.white); int x,y; String s=getParameter("sqrRID"); if (s != null) { StringTokenizer st = new StringTokenizer(s); double sqrRmid = Double.valueOf(st.nextToken()).doubleValue(), sqrImid = Double.valueOf(st.nextToken()).doubleValue(); int sqr = (int)(Double.valueOf(st.nextToken()).doubleValue()/StZ); x = (w - sqr)/2 + (int)((sqrRmid-Xmid)/StZ); y = (h - sqr)/2 + (int)((Ymid - sqrImid) /StZ); gra.drawRect(x,y, sqr,sqr);} gra.setFont( new Font( gra.getFont().getName(), Font.BOLD, 15 ) ); int maxLabel=0; while (true) { s=getParameter("lb"+maxLabel); if (s == null) break; StringTokenizer st = new StringTokenizer(s); x=w/2+(int)((Double.valueOf(st.nextToken()).doubleValue()-Xmid)/StZ); y=h/2+(int)((Ymid-Double.valueOf(st.nextToken()).doubleValue())/StZ); gra.drawString(st.nextToken(), x,y); maxLabel++; } } public void Draw( double Xmid, double Ymid, double Step, FormulaD form, double parC, double parD){ double X,Y; int pix=w, ix,iy; generTime = System.currentTimeMillis(); for (iy=0, Y=Ymid+Step*h/2; iy < h; iy++, Y-=Step) { for (ix=0, X=Xmid-Step*(w/2-1); ix < w; ix++, X+=Step, pix++) { pixArr[pix] =form.iterate(X, Y, parC, parD, maxIZI2, MaxIt, maxColor); } } img = createImage(new MemoryImageSource(w, h, RainbowColor, pixArr, w, w)); generTime = System.currentTimeMillis()-generTime; } } abstract class FormulaD{ abstract int iterate(double x, double y, double paramC, double paramD, double max, int MaxIt, int maxCol); } class DirectJ2 extends FormulaD{ int iterate(double re, double im, double Cr, double Ci, double max, int MaxIt, int maxCol){ double I=im, R=re, I2=I*I, R2=R*R; int n=0; if (R2+I2 > max) return 0; do { I=(R+R)*I+Ci; R=R2-I2+Cr; R2=R*R; I2=I*I; n++; } while ((R2+I2 < max) && (n < MaxIt) ); if (n == MaxIt) return maxCol; else return n % maxCol; } } class DirectJ2DE extends FormulaD{ int iterate(double re, double im, double Cr, double Ci, double max, int MaxIt, int maxCol){ double I=im, R=re, I2=I*I, R2=R*R, Dr=.7,Di=.7,D, K=18; int n=0; do { D = (R*Dr - I*Di); Di = (R*Di + I*Dr); Dr = D; I=(R+R)*I+Ci; R=R2-I2+Cr; R2=R*R; I2=I*I; n++; } while ((R2+I2 < 100.) && (n < MaxIt) ); if (n == MaxIt) return maxCol; else{ R = -K*(Math.log(Math.log(R2+I2)*Math.sqrt((R2+I2)/(Dr*Dr+Di*Di)))-n*.693); if (R < 0) R=0; return (int)R % maxCol; }; } } class DirectJ3 extends FormulaD{ int iterate(double re, double im, double Cr, double Ci, double max, int MaxIt, int maxCol){ double I=im, R=re, I2=I*I, R2=R*R; int n=0; do { I=(3.*R2-I2-1.08)*I; R=(R2-3.*I2-1.08)*R+1.032; R2=R*R; I2=I*I; n++; } while ( (R2+I2 < 242.8415) && (n < MaxIt) ); if (n == MaxIt) return maxCol; else return n % maxCol; } } class DirectJ3a extends FormulaD{ int iterate(double re, double im, double Cr, double Ci, double max, int MaxIt, int maxCol){ double I=im, R=re, I2=I*I, R2=R*R; int n=0; do { I=(3.*R2-I2-1.6875)*I; R=(R2-3.*I2-1.6875)*R+.984; R2=R*R; I2=I*I; n++; } while ( (R2+I2 < 3421.45) && (n < MaxIt) ); if (n == MaxIt) return maxCol; else return n % maxCol; } } class ManExp extends FormulaD{ public int iterate(double cr, double ci, double Re0, double Im0, double max, int MaxIt, int maxCol){ double I=Im0, R=Re0, r,i, exp; int n=0; do{ exp = Math.exp(R); i=Math.sin(I)*exp; r=Math.cos(I)*exp; R=cr*r-ci*i; I=ci*r+cr*i; n++; } while ((R < 50.) && (n < MaxIt) ); if (n == MaxIt) return maxCol; else return n % maxCol; } } class Biquad extends FormulaD{ int iterate(double A, double B, double Cr, double Ci, double max, int MaxIt, int maxCol){ double X, X2=0; int n=0, n0; do { X2 += A; X = X2*X2+B; X2 = X*X; n++; } while ((X2 < 1000.) && (n < MaxIt) ); n0 = n; n = 0; if(A < 0){ X = Math.sqrt(-A); X2 = X*X; do { X2 += A; X = X2*X2+B; X2 = X*X; n++; } while ((X2 < 1000.) && (n < MaxIt) ); if (n == MaxIt){ if (n0 == MaxIt) return maxCol; else return 2*maxCol/3;} else{ if (n0 == MaxIt) return maxCol/2; else return ((n+n0)/2) % maxCol;}} else{ if (n0 == MaxIt) return maxCol/2; else return n0 % maxCol;} } } class HenonDyn extends FormulaD{ int iterate(double Xo, double Yo, double a, double b, double max, int MaxIt, int maxCol){ double X=Xo, X2=X*X, X1, Y=Yo; int n=0; do{ X1 = a + X2 + b*Y; Y = X; X = X1; X2 = X*X; n++; } while ((X2 < 1000.) && (n < MaxIt) ); if (n == MaxIt) return maxCol; return n % maxCol; } }