// Henon + Lyapunov, Evgeny Demidov, 27 July 2006 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 Ymid=0, Xmid=-.5, stX,stJ, A=-1.4, B=.3, Xj=0,Yj=0, Xs,Ys; int MaxIt = 256, maxColor = 96, w,w2,h,h2, pixArr[], pixJ[]; Image img, imgJ; IndexColorModel RainbowColor; boolean drawM = true, drawJ = true; public void init() { w = getSize().width/2; h = getSize().height; w2 = w/2; h2 = h/2; stX = 3./w; stJ = 5./w; String s=getParameter("XYmidDelCD"); if (s != null) { StringTokenizer st = new StringTokenizer(s); Xmid = Double.valueOf(st.nextToken()).doubleValue(); Ymid = Double.valueOf(st.nextToken()).doubleValue(); stX = Double.valueOf(st.nextToken()).doubleValue()/w;} // paramC = Double.valueOf(st.nextToken()).doubleValue(); // paramD = Double.valueOf(st.nextToken()).doubleValue();} s=getParameter("MaxIt"); if (s != null) MaxIt=Integer.parseInt(s); 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); pixArr = new int[w*h]; pixJ = new int[w*h]; Draw(Xmid, Ymid, stX); DrawJ(); double b1 = (1-B)*.5, d=b1*b1-A; if (d < 0) Xs = Ys = 0; else Xs = Ys = b1 - Math.sqrt(d) + 1e-10; 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) { int ix = e.getX(); double xt,yt; if (ix < w){ xt = Xmid+(ix-w2)*stX; yt = Ymid-(e.getY()-h2)*stX; if ( e.isControlDown() ){ if ( e.isShiftDown() ) stX *=4.; else stX *=2.; Xmid = xt; Ymid = yt; Draw(Xmid, Ymid, stX);} else if( e.isAltDown() ){ if ( e.isShiftDown() ) stX /=4.; else stX /=2.; Xmid = xt; Ymid = yt; Draw(Xmid, Ymid, stX);} else{ A = xt; B = yt; DrawJ(); double b1 = (1-B)*.5, d=b1*b1-A; if (d < 0) Xs = Ys = 0; else Xs = Ys = b1 - Math.sqrt(d) + 1e-10; showStatus( "a=" + (float)A + " b=" + (float)B);}} else{ xt = Xj+(ix-w2-w)*stJ; yt = Yj-(e.getY()-h2)*stJ; if ( e.isControlDown() ){ if ( e.isShiftDown() ) stJ *=4.; else stJ *=2.; Xj = xt; Yj = yt; DrawJ();} else if( e.isAltDown() ){ if ( e.isShiftDown() ) stJ /=4.; else stJ /=2.; Xj = xt; Yj = yt; DrawJ();} else{ Xs = xt; Ys = yt; Lyapunov(); }} repaint(); } void Lyapunov(){ double X=Xs, X2, XX=X*X, X1, Y=Ys, m11=2.*X, m12=B, m21=1., m22=.0, t11,t21, L; int n=0, it=1000; do{ X1 = A + XX + B*Y; Y = X; X = X1; X2 = X+X; XX = X*X; n++; t11 = m11*X2+m12; t21 = m21*X2+m22; m12 = B*m11; m22 = B*m21; m11 = t11; m21 = t21; } while ((XX < 1000.) && (n < it) ); L = Math.log(Math.abs(m11 + m22))/(n+1); showStatus( "x=" + (float)Xs + " y=" + (float)Ys + " L=" + (float)L); } public void paint(Graphics g) { g.drawImage(img, 0, 0, this); g.drawImage(imgJ, w, 0, this); g.setColor(Color.white); int n=0, x,y; y = h2 + (int)(Ymid/stX); g.drawLine(0,y, w,y); x = w2 + (int)((A - Xmid)/stX); y = h2 - (int)((B - Ymid)/stX); if(x < w) g.drawLine(x-3,y, x+3,y); g.drawLine(x,y-3, x,y+3); double X,Y,X1,X2, b1 = (1-B)*.5, d=b1*b1-A; if (d < 0) X = X1 = 0; else{ X = b1 - Math.sqrt(d) + 1e-10; X1 = b1 + Math.sqrt(d) + 1e-10;} x = w2 + (int)((X - Xj)/stJ); y = h2 - (int)((X - Yj)/stJ); g.setColor(Color.black); if(x > 0){ x += w; g.drawLine(x-3,y, x+3,y); g.drawLine(x,y-3, x,y+3);} x = w2 + (int)((X1 - Xj)/stJ); y = h2 - (int)((X1 - Yj)/stJ); if(x > 0){ x += w; g.drawLine(x-3,y-3, x+3,y+3); g.drawLine(x+3,y-3, x-3,y+3);} X = Xs; Y = Ys; X2 = X*X; do{ x = w2 + (int)((X - Xj)/stJ); y = h2 - (int)((Y - Yj)/stJ); if(x > 0){ x += w; g.drawLine(x,y, x,y);} X1 = A + X2 + B*Y; Y = X; X = X1; X2 = X*X; n++; } while ((X2 < 1000.) && (n < 10*MaxIt) ); } public void Draw( double Xm, double Ym, double Step){ double X,Y; int pix=0, ix,iy; for (iy=0, Y=Ym+Step*h2; iy < h; iy++, Y-=Step) { for (ix=0, X=Xm-Step*(w2-1); ix < w; ix++, X+=Step, pix++){ pixArr[pix] = iterate(X, Y);}} img = createImage(new MemoryImageSource(w, h, RainbowColor, pixArr, 0, w)); } int iterate(double a, double b){ double X, X2, X1, Y; int n=0; double b1 = (1-b)*.5, d=b1*b1-a; if (d < 0) X = 0; else X = b1 - Math.sqrt(d) + 1e-10; Y = X; X2 = X*X; do{ X1 = a + X2 + b*Y; Y = X; X = X1; X2 = X*X; n++; } while ((X2 < 1000.) && (n < MaxIt) ); if (n < MaxIt) return maxColor+1; double Xo = X, Yo = Y; n = -1; do{ X1 = a + X*X + b*Y; Y = X; X = X1; n++; } while ((Math.abs(X - Xo) + Math.abs(Y - Yo) > 1e-8) && (n < 64) ); if (n == 64) return maxColor; return n % maxColor; } public void DrawJ(){ double X,Y; int pix=0, ix,iy; for (iy=0, Y=Yj+stJ*h2; iy < h; iy++, Y-=stJ) { for (ix=0, X=Xj-stJ*w2; ix < w; ix++, X+=stJ, pix++){ pixJ[pix] = iterateJ(X, Y);}} imgJ = createImage(new MemoryImageSource(w, h, RainbowColor, pixJ, 0, w)); } int iterateJ(double Xo, double Yo){ 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 maxColor+1; else return n % maxColor; } }