// "Shrimps hunter" with Threads, Evgeny Demidov, 12 Nov 07 import java.awt.*; import java.awt.image.*; import java.awt.event.*; import java.util.StringTokenizer; public class DirectMT extends java.applet.Applet implements MouseListener { double Ymid=.0, Xmid=-.5, DelX=3., paramC,paramD; int MaxIt = 256, maxColor = 96, w, h, pixArr[], workingBees, nBees = 4; Image img; IndexColorModel RainbowColor; long generTime; boolean showXY = true, culculated = false; FormulaMT formula; 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("Threads"); if (s != null) nBees=Integer.parseInt(s); s=getParameter("MaxIt"); if (s != null) MaxIt=Integer.parseInt(s); s=getParameter("MaxColor"); if (s != null) maxColor=Integer.parseInt(s); byte rColor[] = new byte[maxColor+2], bColor[] = new byte[maxColor+2], gColor[] = new byte[maxColor+2]; Color c; for (int i = 0; i < maxColor; i++){ // set Color Map c= Color.getHSBColor((float)i/maxColor,1.0f,1.0f); rColor[i]=(byte)c.getRed(); gColor[i]=(byte)c.getGreen(); bColor[i]=(byte)c.getBlue();} 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()); s = ""+Xmid+", "+Ymid+"; "+(float)DelX; tfXY = new TextField( s ); add("South", tfXY); h -= tfXY.getPreferredSize().height;} pixArr = new int[w*h]; s=getParameter("Formula"); if (s != null) try{ formula = (FormulaMT)Class.forName( s ).newInstance(); }catch(Exception e){} else formula = new Circle(); Draw(); 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) { double Xo = Xmid+(e.getX()-w/2)*DelX/w, Yo = Ymid-(e.getY()-h/2)*DelX/w; if ( !(e.isAltDown() || e.isControlDown()) ){ int p = formula.iterate(Xo, Yo, paramC, paramD, MaxIt, maxColor)+1; if (showXY) tfXY.setText( "p="+p+" "+(float)Xo+", "+(float)Yo); return;} Xmid = Xo; Ymid = Yo; if ( e.isControlDown() ) { if ( e.isShiftDown() ) DelX *=4.; else DelX *=2.;} else { if ( e.isShiftDown() ) DelX /=4.; else DelX /=2.;} if (showXY) tfXY.setText( ""+Xmid+", "+Ymid+"; "+(float)DelX); Draw(); } public void paint(Graphics g) { if(culculated){ g.drawImage(img, 0, 0, this); if (DelX > .01) drawLabel(g); showStatus( "Time=" + generTime + " msec " + nBees + " threads");} } 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 synchronized void CountingBees(){ if (--workingBees == 0){ img = createImage(new MemoryImageSource(w, h, RainbowColor, pixArr, 0, w)); generTime = System.currentTimeMillis()-generTime; culculated = true; repaint();} } public void Draw(){ generTime = System.currentTimeMillis(); workingBees = nBees; int stY=h/nBees, y0=0, yk=stY; for (int i=1; i < nBees; i++){ new Bee(this, y0, yk).start(); y0 = yk; yk += stY;} new Bee(this, y0, h).start(); } } // end Applet class Bee extends Thread{ double Xmid, Ymid, Step, parC, parD; int w, h, h0, hk, MaxIt, maxColor, pixArr[]; DirectMT applet; Bee(DirectMT app, int y0, int yk){ w = app.w; h = app.h; h0=y0; hk=yk; MaxIt=app.MaxIt; maxColor=app.maxColor; pixArr = app.pixArr; applet = app; Xmid=app.Xmid; Ymid=app.Ymid; Step=app.DelX/w; parC=app.paramC; parD=app.paramD; } public void run(){ double X,Y; int pix=w*h0, ix,iy, p; for (iy=h0, Y=Ymid+Step*(h/2-h0); iy < hk; iy++, Y-=Step) { for (ix=0, X=Xmid-Step*(w/2-1); ix < w; ix++, X+=Step, pix++) { p=applet.formula.iterate(X, Y, parC, parD, MaxIt, maxColor); if (p == 999) p = maxColor; else if (p > maxColor) p %= maxColor; else if (p < 0) p = maxColor + 1; pixArr[pix] = p; } } applet.CountingBees(); } } // end Bee abstract class FormulaMT{ abstract int iterate(double x, double y, double paramC, double paramD, int MaxIt, int maxCol); } class Circle extends FormulaMT{ int iterate(double A, double B, double C, double Ci, int MaxIt, int maxCol){ double X = .5, Xo, B1=25.13*B; int n=0; do{ X = X + A + B1*X*(X-.5)*(X-1.); X -= Math.floor(X); n++; } while (n < MaxIt); Xo = X; n = -1; do{ X = X + A + B1*X*(X-.5)*(X-1.); X -= Math.floor(X); n++; } while ((Math.abs(X - Xo) > 1e-8) && (n < 64) ); if (n == 64) return 999; return n; } } class PBiquadH extends FormulaMT{ int iterate(double A, double B, double C, double Ci, int MaxIt, int maxCol){ double X, X2=0, Xo; int n=0; if (C > 0){ if(A > 0) return maxCol; 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) return -1; Xo = X; n = -1; do{ X2 += A; X = X2*X2+B; X2 = X*X; n++; } while ((Math.abs(X - Xo) > 1e-8) && (n < 64) ); if (n == 64) return 999; return n; } } class CubicH extends FormulaMT{ int iterate(double A, double B, double C, double Ci, int MaxIt, int maxCol){ double X = A, X2, Xo, A2 = 3*A*A; int n=0; if (C > 0) X = -A; X2=A*A; do{ X2 -= A2; X = X2*X+B; X2 = X*X; n++; } while ((X2 < 1000.) && (n < MaxIt) ); if (n < MaxIt) return -1; Xo = X; n = -1; do{ X2 -= A2; X = X2*X+B; X2 = X*X; n++; } while ((Math.abs(X - Xo) > 1e-8) && (n < 64) ); if (n == 64) return 999; return n; } } class HenonHJ extends FormulaMT{ int iterate(double a, double b, double Xo, double Yo, int MaxIt, int maxCol){ double b2 = (1-b)*.5, Xs,Ys; if (a < 0) Xs = 0; else if (Xo > 0) Xs = -b2 + Math.sqrt(b2*b2 + a) + 1e-10; else Xs = -b2 - Math.sqrt(b2*b2 + a) + 1e-10; Ys = Xs; double X= a - Xs*Xs + b*Ys, X2=X*X, X1, Y=Ys; 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 -1; 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 999; return n; } } class HenonH extends FormulaMT{ int iterate(double a, double b, double Xo, double Yo, int MaxIt, int maxCol){ double b1 = (1-b)*.5, d=b1*b1-a, Xs,Ys; if (d < 0) Xs = 0; else if (Xo > 0) Xs = b1 + Math.sqrt(d) + 1e-10; else Xs = b1 - Math.sqrt(d) + 1e-10; Ys = Xs; double X= a + Xs*Xs + b*Ys, X2=X*X, X1, Y=Ys; 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 -1; 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 999; return n; } }