// Henon mapping, Evgeny Demidov, 27 June 2007 import java.awt.*; import java.awt.image.*; import java.awt.event.*; import java.util.StringTokenizer; public class @file extends java.applet.Applet implements MouseListener, KeyListener, ActionListener, MouseMotionListener{ double Yc=0, Xc=0, dx=35, dy=dx, Xm, Ym, Rm=.3, R=.5, a=-8, b=1; int maxColor=5, N=2, w, h, w2, h2, ix, ixo, iy, iyo, ir, ir2, pixArr[], px[],py[], pxo[],pyo[]; Image img; IndexColorModel RainbowColor; Label lbA, lbB, lbR, lbN; TextField tfXY, tfA, tfB, tfR, tfN; Button btPl, btMn; boolean bXOR=false, bR2=false; public void init() { String s=getParameter("XYmidDelCD"); if (s != null) { StringTokenizer st = new StringTokenizer(s); Xc = Double.valueOf(st.nextToken()).doubleValue(); Yc = Double.valueOf(st.nextToken()).doubleValue(); dx = Double.valueOf(st.nextToken()).doubleValue(); dy = Double.valueOf(st.nextToken()).doubleValue();} Xm = Xc; Ym = Yc; s=getParameter("ab"); if (s != null) { StringTokenizer st = new StringTokenizer(s); a = Double.valueOf(st.nextToken()).doubleValue(); b = Double.valueOf(st.nextToken()).doubleValue();} s=getParameter("R2"); if (s != null) bR2 = true; s=getParameter("R"); if (s != null) R = Double.valueOf(s).doubleValue(); s=getParameter("Rm"); if (s != null) Rm = Double.valueOf(s).doubleValue(); s=getParameter("N"); if (s != null) N=Integer.parseInt(s); if (N < 0) N = 0; s=getParameter("MaxColor"); if (s != null) maxColor=Integer.parseInt(s); byte rColor[] = new byte[maxColor], bColor[] = new byte[maxColor], gColor[] = new byte[maxColor]; rColor[0] = gColor[0] = bColor[0] = (byte)255; gColor[1] = (byte)255; bColor[2] = (byte)255; rColor[3] = (byte)255; bColor[4] = gColor[4] = rColor[4] = 0; RainbowColor = new IndexColorModel( 8, maxColor, rColor,gColor,bColor); w = getSize().width; h = getSize().height; w2 = w/2; h2 = h/2; pixArr = new int[w*h]; this.setLayout( new FlowLayout(FlowLayout.LEFT, 0, 0) ); tfXY = new TextField( ""+(float)Xc+" "+(float)Yc+"; "+(float)dx+ " "+(float)dy, 20); add(tfXY); lbA = new Label("A", Label.RIGHT); add(lbA); tfA = new TextField( "" + a, 2); add(tfA); tfA.addKeyListener(this); lbB = new Label("B", Label.RIGHT); add(lbB); tfB = new TextField( "" + b, 2); add(tfB); tfB.addKeyListener(this); lbR = new Label("R", Label.RIGHT); add(lbR); tfR = new TextField( "" + R, 2); add(tfR); tfR.addKeyListener(this); lbN = new Label("N", Label.RIGHT); add(lbN); tfN = new TextField( "" + N, 1); add(tfN); tfN.addKeyListener(this); btPl = new Button("+"); btPl.addActionListener(this); add(btPl); btMn = new Button("-"); btMn.addActionListener(this); add(btMn); px = new int[9]; pxo = new int[9]; py = new int[9]; pyo = new int[9]; addMouseMotionListener(this); addMouseListener(this); Draw(); } public void destroy() { removeMouseMotionListener(this); 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) { if (e.isControlDown()||e.isAltDown()){ Xc = Xc+(e.getX()-w2)*dx/w; Yc = Yc-(e.getY()-h2)*dx/w;} else return; if (e.isControlDown()){ dy *= 2.; if (!e.isShiftDown()) dx *= 2.;} if (e.isAltDown()) { dy /= 2.; if (!e.isShiftDown()) dx /= 2.;} tfXY.setText( ""+(float)Xc+" "+(float)Yc+"; "+(float)dx+" "+(float)dy); Draw(); repaint(); } public void mouseMoved(MouseEvent e){} //1.1 event handling public void mouseDragged(MouseEvent e) { if (e.isControlDown()||e.isAltDown()) return; ix = e.getX(); iy = e.getY(); Xm = Xc+(ix-w2)*dx/w; Ym = Yc-(iy-h2)*dx/w; Polygon(); bXOR = true; repaint(); } public void actionPerformed(ActionEvent e){ if ( e.getActionCommand().equals("+") ) N++; else N--; if (N < 0) N = 0; tfN.setText(""+N); Draw(); repaint(); } public void keyTyped(KeyEvent e) {} public void keyPressed(KeyEvent e) {} public void keyReleased(KeyEvent e) { final int keyEnter = 10; if (e.getKeyCode() == keyEnter) { try{ a = Double.valueOf(tfA.getText()).doubleValue(); b = Double.valueOf(tfB.getText()).doubleValue(); R = Double.valueOf(tfR.getText()).doubleValue(); N = Integer.parseInt(tfN.getText()); if (N < 0) { N = 0; tfN.setText(""+N); } Draw(); repaint(); }catch ( NumberFormatException ne) {} } e.consume(); } public void update(Graphics g){ paint(g); } public void paint(Graphics g) { if(!bXOR){ g.drawImage(img, 0, 0, this); g.setColor(Color.black); drawLabel(g); g.setColor(Color.white); g.setXORMode(Color.black); double X, b1 = (1-b)*.5, d=b1*b1-a; if (d > 0){ X = b1 - Math.sqrt(d); int ix = w2 + (int)((X - Xc)*w/dx); int iy = h2 - (int)((X - Yc)*h/dy); g.drawLine(ix-5,iy, ix+5,iy); g.drawLine(ix,iy-5, ix,iy+5); X = b1 + Math.sqrt(d); ix = w2 + (int)((X - Xc)*w/dx); iy = h2 - (int)((X - Yc)*h/dy); g.drawLine(ix-5,iy, ix+5,iy); g.drawLine(ix,iy-5, ix,iy+5);} g.fillPolygon(px,py,9); g.drawRect(ix-ir,iy-ir,ir2,ir2); g.setPaintMode();} else{ g.setXORMode(Color.black); g.setColor(Color.white); g.fillPolygon(pxo,pyo,9); g.drawRect(ixo-ir,iyo-ir,ir2,ir2); System.arraycopy(px,0,pxo,0,9); System.arraycopy(py,0,pyo,0,9); ixo = ix; iyo = iy; g.fillPolygon(px,py,9); g.drawRect(ix-ir,iy-ir,ir2,ir2); g.setPaintMode(); bXOR=false;} } public void Draw(){ ix = ixo = w2 + (int)((Xm - Xc)*w/dx); iy = iyo = h2 - (int)((Ym - Yc)*h/dy); ir = (int)(Rm*w/dx); ir2 = 2*ir; Polygon(); System.arraycopy(px,0,pxo,0,9); System.arraycopy(py,0,pyo,0,9); for (int p = h*w; p > 0;) pixArr[--p] = 0; int pix, ix,iy; pix = 0; double X,Y, Xo,Yo, Xs, Xs1, X1,Y1, t, Rn,Rb; double b1 = (1-b)*.5, d=b1*b1-a; Xs = b1 + Math.sqrt(d); Xs1 = b1 - Math.sqrt(d); Rn=R*R; Rb=Rn*b*b*b*b; for (iy=0; iy < h; iy++) { Yo = Yc + (h2-iy)*dy/h; for (ix=0; ix < w; ix++){ Xo = X = Xc + (ix-w2)*dx/w; Y = Yo; for(int i=N; i>0; i--){ t = a + X*X +b*Y; Y = X; X = t; } if( (X-Xs)*(X-Xs)+(Y-Xs)*(Y-Xs) < Rb ) pixArr[pix] = 2; if( bR2 && ( (X-Xs1)*(X-Xs1)+(Y-Xs1)*(Y-Xs1) < Rb ) ) pixArr[pix] = 4; Y = Yo; X = Xo; for(int i=N; i>0; i--){ t = (X-Y*Y-a)/b; X = Y; Y = t; } if( (X-Xs)*(X-Xs)+(Y-Xs)*(Y-Xs) < Rn ) pixArr[pix] = 3; if(bR2 && ( (X-Xs1)*(X-Xs1)+(Y-Xs1)*(Y-Xs1) < Rn) ) pixArr[pix] = 1; pix++;} } //System.out.println(""+Xc +" "+Yc); img = createImage(new MemoryImageSource(w, h, RainbowColor, pixArr, 0, w)); } public void drawLabel(Graphics gra) { gra.setColor(Color.black); int x,y; gra.setFont( new Font( gra.getFont().getName(), Font.BOLD, 15 ) ); int maxLabel=0; while (true) { String s=getParameter("lb"+maxLabel); if (s == null) break; StringTokenizer st = new StringTokenizer(s); x=w2+(int)((Double.valueOf(st.nextToken()).doubleValue()-Xc)*w/dx); y=h2+(int)((Yc-Double.valueOf(st.nextToken()).doubleValue())*h/dy); gra.drawString(st.nextToken(), x,y); maxLabel++; } } public void Polygon(){ double X=Xm-Rm, Y=Ym-Rm; st(X, Y, 0); X=Xm; st(X,Y,1); X=Xm+Rm; st(X,Y,2); Y=Ym; st(X,Y,3); Y=Ym+Rm; st(X,Y,4); X=Xm; st(X,Y,5); X=Xm-Rm; st(X,Y,6); Y=Ym; st(X,Y,7); px[8]=px[0]; py[8]=py[0]; } public void st(double X, double Y, int k){ px[k] = w2 + (int)((a + X*X +b*Y - Xc)*w/dx); py[k] = h2 - (int)((X - Yc)*h/dy); } }