import java.awt.*; import java.awt.image.*; import java.lang.System; public class ChTmMandel extends java.applet.Applet implements Runnable { int iRedM=8, iGreenM=16, iBlueM=4, iRedA=0, iGreenA=0, iBlueA=192; int iMax, iMul, iZoom; int iMinDepth, iDepth, iDepthPlus; int iBuf[], bBuf[], iColor[], iZ[]; // int iPoints; int iBusy, iCalc, iSelect, iStartX, iStartY, iCount, iAutozoom, iMoving, iAlways; int iControls, iNeedToInit, iType, iJulia, iJuliaSize, iAutodepth; int i3D, iUpdown, iDamping, iLimiting, iFactor, iAngle, iDamp, iLimit; double dX, dY, dSize, dGap; MemoryImageSource mImage; Image iImage; Thread tAnim; ControlPanel cPanel; double dMX, dMY, dMSize; synchronized public void init() { iType=0; iJulia=0; iJuliaSize=32; iUpdown=1; iFactor=10; iAngle=10; iDamping=0; iDamp=5; iLimiting=0; iLimit=0; iAutodepth=1; iDepthPlus=64; String s=null; s=getParameter("size"); iMax=(s!=null)?Integer.parseInt(s):256; s=getParameter("sleep"); iNeedToInit=(s!=null)?Integer.parseInt(s):0; s=getParameter("controls"); iControls=(s!=null)?Integer.parseInt(s):1; iMul=iMax+1; if(iControls==1) { setLayout(new FlowLayout(FlowLayout.RIGHT)); add(cPanel=new ControlPanel(this)); layout(); writeParameter(); } if(iNeedToInit==0) { initMemory(); s=getParameter("command"); if(s!=null) doCommand(s); } } void initMemory() { iBuf=new int[iMul*iMul]; bBuf=new int[iMul*iMul]; mImage=new MemoryImageSource(iMul, iMul, iBuf, 0, iMul); iImage=createImage(mImage); iColor=new int[256]; iZ=new int[iMul]; iNeedToInit=0; goHome(); updateColors(); calcAll(); iBusy=0; } int calcPoint(double rx, double ry, double dx, double dy, int max, int min) { int t=0; double xx, yy; switch(iType) { case 0: while(t4) break; ry=(ry=rx*ry)+ry+dy; rx=xx-yy+dx; } while( t++4) break; ry=(ry=rx*ry)+ry; rx=xx-yy; if((xx=rx*rx)+(yy=ry*ry)>4) break; ry=(ry=rx*ry)+ry+dy; rx=xx-yy+dx; } while( t++4) break; ry=(ry=rx*ry)+ry+dy; rx=xx-yy+dx; dx=dx/2+rx; dy=dy/2+ry; } while( t++4) break; rx+=rx; ry+=ry; if(ry>1.) ry-=1.; else if(rx>1.) rx-=1.; } while( t++4) break; xx=rx-xx+yy; yy=-(ry*rx); yy+=yy+ry; rx=dx*xx-dy*yy; ry=dx*yy+dy*xx; } while( t++>13)+idx; iry=((irx*iry)>>(13-1))+idy; irx=ixx; t++; } do { if((ixx=((irx*irx)>>13))+(iyy=((iry*iry)>>13))>(4*8192)) break; iry=((irx*iry)>>(13-1))+idy; irx=ixx-iyy+idx; } while( t++max) return p-(max-min+1); else return p; } synchronized void calcJuliaPreview(int sx, int sy) { double mx, my, dx, dy; for(int x=0; x=10) r=0xff<<24; else r=iColor[r & 255]; iBuf[x+5+iMul*(y+5)]=r; } } iImage.flush(); } synchronized void calcAll() { // iPoints=0; iBusy=1; for(int i=iMul*iMul-1; i>=0; i--) bBuf[i]=0; dGap=dSize/iMul; calcDepth(); iCount=0; calcSmart(); updateImage(); paintFast(); iBusy=0; iCalc=0; //writeParameter(); } synchronized void calcZoomIn() { // iPoints=0; iBusy=1; dX+=dSize/iMul*(iStartX-iMax/4); dY+=dSize/iMul*(iStartY-iMax/4); dSize/=2.; // copy all sure points with scaling for(int i=iMul*iMul-1;i>=0;i--) iBuf[i]=0; for(int x=0; x<=iMax/2; x++) { for(int y=0; y<=iMax/2; y++) { int m=bBuf[x+iStartX+iMul*(y+iStartY)]; iBuf[x+x+iMul*(y+y)]=((m & 0x1000000)==0)? 0 : m; // SURE } } System.arraycopy(iBuf, 0, bBuf, 0, iMul*iMul-1); // remove unsure dGap=dSize/iMul; int olddepth=iDepth; calcDepth(); if(iDepth>olddepth) { int unsure=olddepth | 0x1000000; // SURE for(int y=iMax; y>=0; y-=2) { for(int x=iMax, i=x+iMul*y; x>=0; x-=2, i-=2) { if(iBuf[i]>=unsure) iBuf[i]=bBuf[i]=0; } } } iCount=0; calcSmart(); for(int x=0; x<=iMax; x+=2) { for(int y=0; y<=iMax; y+=2) { int i=x+iMul*y; int c=iBuf[i]; if((c&0x1000000)!=0) bBuf[i]=c; // SURE } } updateImage(); paintZoom(); if(iAutozoom==0) setCursor(-1, 0, 0); writeParameter(); iBusy=0; iCalc=0; } void calcBackground() { if(iAutozoom!=0) { int x=0, y=0, i=0; for(;i<1000;i++) { int a, b, c, d, m; x=(int)(Math.random()*(iMax-1))/2; y=(int)(Math.random()*(iMax-1))/2; if(x>=iMax || y>=iMax) continue; bBuf[(x+iMax/4)+iMul*(y+iMax/4)]=0; m=calcArrayPoint(x+iMax/4, y+iMax/4); if(miDepth-5) continue; bBuf[x+iMul*y]=0; bBuf[(x+iMax/2)+iMul*y]=0; bBuf[(x+iMax/2)+iMul*y]=0; bBuf[(x+iMax/2)+iMul*(y+iMax/2)]=0; a=calcArrayPoint(x, y); b=calcArrayPoint(x+iMax/2, y+iMax/2); c=calcArrayPoint(x+iMax/2, y); d=calcArrayPoint(x, y+iMax/2); if(a==b && c==d && a==c) i=1000; if(aiDepth-20 && b>iDepth-20 && c>iDepth-20 & d>iDepth-20) continue; break; } if(i<1000) { iStartX=x; iStartY=y; calcZoomIn(); } else { goHome(); calcAll(); } } if(iBusy==1 || (iSelect!=1 && iAlways==0) || iCalc==-1) { return; } else if(iMoving>0) { iMoving--; } else if(iCalc0) break; } } else { iCalc=-1; iBusy=1; updateImage(); paintFast(); iBusy=0; } } void calcSmart() { for(int b=16;b>1;b>>=1) { for(int x=0;x<=iMax;x+=b) for(int y=0;y<=iMax;y+=b) calcArrayPoint(x, y); for(int x=0;x2) continue; int cm; if(c1-c4 !=1 && c1-c4 !=-1) { cm=bBuf[x+1+iMul*(y+1)]=(c1+c4)>>1; } else if(c2-c3 !=1 && c2-c3 !=-1) { cm=bBuf[x+1+iMul*(y+1)]=(c2+c3)>>1; } else cm=calcArrayPoint(x+1, y+1); if(y>0) { int cu=(0x1000000-1) & bBuf[x+1+iMul*(y-1)]; if(c1-c3 !=1 && c1-c3 !=-1) { bBuf[x+1+iMul*y]=(c1+c3)>>1; } else if(cu-cm !=1 && cu-cm !=-1) { bBuf[x+1+iMul*y]=(cu+cm)>>1; } else calcArrayPoint(x+1, y); } if(x>0) { int cl=(0x1000000-1) & bBuf[x-1+iMul*(y+1)]; if(c1-c2 !=1 && c1-c2 !=-1) { bBuf[x+iMul*(y+1)]=(c1+c2)>>1; } else if(cl-cm !=1 && cl-cm !=-1) { bBuf[x+iMul*(y+1)]=(cl+cm)>>1; } else calcArrayPoint(x, y+1); } } } } } void updateColors() { for(int i=0; i<256; i++) iColor[i]= ((i*iRedM+iRedA)&0xff)*0x10000 | ((i*iGreenM+iGreenA)&0xff)*0x100 | ((i*iBlueM+iBlueA)&0xff) | (0xff<<24); // COLOR } void updateImage() { int c; if(i3D==0) { for(int i=iMul*iMul-1; i>=0; i--) { // some debug stuff: see what points where really calculated /* c=bBuf[i]; c= (c & 0x1000000)!=0 ? iColor[c & 255] : 0xff<<24; */ c=bBuf[i] & (0x1000000-1); // SURE if(c>=iDepth) c=0xff<<24; else c=iColor[c & 255]; iBuf[i]=c; } } else { if(iDamping!=0) { for(int y=iMax-1; y>0; y--) { for(int x=2; xiDamp) { bBuf[x+iMul*y]=l+iDamp; } } for(int x=iMax-2; x>0; x--) { int t=bBuf[x+iMul*y] & (0x1000000-1); int l=bBuf[x+1+iMul*y] & (0x1000000-1); if(t-l>iDamp) { bBuf[x+iMul*y]=l+iDamp; } } } } for(int i=1; i=0; i--) iBuf[i]=0xff<<24; int minus=10000; // really maximum for(int x=1; x0; y--) { for(int x=1; xiDepth-iLimit) c=iDepth-iLimit; c=((iUpdown*c)*iFactor)/10; int i=iZ[x]; if(i>iMax) i=iMax; int yh=((y+c-minus)*iAngle)/10; for(; i>=yh && i>0; i--) { iBuf[x+iMul*i]=iColor[(c+i-yh) & 255]; } i++; if(iiMax/2) x=iMax/2; } y-=iMax/4; if(y<0) y=0; if(y>iMax/2) y=iMax/2; if(e==1 && x==iStartX && y==iStartY) return; Graphics g=getGraphics(); g.setXORMode(Color.white); if(iSelect==1 && iStartY>=0) { paintFast(); } if(e==1) { if(x>iMax) { iStartY=-1; iSelect=0; return; } iStartX=x; iStartY=y; iAutozoom=0; g.drawRect(iStartX, iStartY, iMax/2, iMax/2); iSelect=1; } else { iSelect=0; } } synchronized public void update(Graphics g) { paint(g); } synchronized public void paint(Graphics g) { if(iNeedToInit!=0) { g.drawString("Click here to Start.",2,100); return; } if(iBusy==1) return; g.drawImage(iImage, 0, 0, this); super.paint(g); if(iSelect==1) setCursor(-1, 0, 0); } synchronized void paintFast() { Graphics g=getGraphics(); g.drawImage(iImage, 0, 0, this); if(iSelect==1) setCursor(-1, 0, 0); } void paintZoom() { iImage.flush(); Graphics g=getGraphics(); if(iZoom==1) { for(int k=iMax/2; k 3D-Setting")); pMain.add(new Label("")); pMain.add(new Button("> Colors")); pMain.add(new Label("")); pMain.add(new Button("> Settings")); pMain.add(new Label("")); pMain.add(new Label("")); pMain.add(new Label("Fractal Type")); cType=new Choice(); cType.addItem("Mandelbrot"); cType.addItem("Mandelbrot ^ 4"); cType.addItem("Spider"); cType.addItem("Sierpinski"); cType.addItem("Lambda"); cType.addItem("Mandelbrot (int)"); pMain.add(cType); pMain.add(new Label("")); pMain.add(cJulia=new Checkbox("Julia-Set")); pMain.add(new Button("Go Back")); pMain.add(new Label("")); pMain.add(new Button("Go Home")); pMain.add(new Label("")); pMain.add(new Button("Automatic")); pMain.add(new Label("")); pMain.add(cAnimations=new Checkbox("Animations")); pMain.add(new Label("")); add("Main",pMain); Panel pSettings=new Panel(); pSettings.setLayout(new GridLayout(11, 2, 1, 1)); pSettings.add(new Label("Settings")); pSettings.add(new Button("> Main")); pSettings.add(new Label("")); pSettings.add(new Label("")); pSettings.add(new Label("Command")); pSettings.add(tCommand=new TextField("")); pSettings.add(new Label("")); pSettings.add(new Button("Send")); pSettings.add(new Label("")); pSettings.add(new Label("")); pSettings.add(new Label("Current State")); pSettings.add(tParameter=new TextField("")); pSettings.add(new Label("")); pSettings.add(new Label("")); pSettings.add(new Label("Depth")); pSettings.add(lDepth=new Label("")); pSettings.add(bDepthM=new Button("<")); pSettings.add(bDepthP=new Button(">")); pSettings.add(cAutodepth=new Checkbox("Auto-Depth")); pSettings.add(cAlways=new Checkbox("Always Calc")); pSettings.add(new Label("")); pSettings.add(new Label("")); add("Settings",pSettings); Panel pColors=new Panel(); pColors.setLayout(new GridLayout(11, 2, 1, 1)); pColors.add(new Label("Colors")); pColors.add(new Button("> Main")); pColors.add(new Label("Presets")); cColorPreset=new Choice(); cColorPreset.addItem("Standard"); cColorPreset.addItem("Strong Colors"); cColorPreset.addItem("Gray scale"); pColors.add(cColorPreset); pColors.add(new Label("Red")); pColors.add(lRed=new Label("")); pColors.add(bRedMm=new Button("<*")); pColors.add(bRedMp=new Button("*>>")); pColors.add(bRedAm=new Button("<+")); pColors.add(bRedAp=new Button("+>>")); pColors.add(new Label("Green")); pColors.add(lGreen=new Label("")); pColors.add(bGreenMm=new Button("<*")); pColors.add(bGreenMp=new Button("*>>")); pColors.add(bGreenAm=new Button("<+")); pColors.add(bGreenAp=new Button("+>>")); pColors.add(new Label("Blue")); pColors.add(lBlue=new Label("")); pColors.add(bBlueMm=new Button("<*")); pColors.add(bBlueMp=new Button("*>>")); pColors.add(bBlueAm=new Button("<+")); pColors.add(bBlueAp=new Button("+>>")); add("Colors",pColors); Panel p3D=new Panel(); p3D.setLayout(new GridLayout(11, 2, 1, 1)); p3D.add(new Label("3D-Setup")); p3D.add(new Button("> Main")); p3D.add(new Label("Direction")); cUpdown=new Choice(); cUpdown.addItem("Down"); cUpdown.addItem("Up"); p3D.add(cUpdown); p3D.add(new Label("Factor")); p3D.add(lFactor=new Label("")); p3D.add(bFactorM=new Button("<")); p3D.add(bFactorP=new Button(">")); p3D.add(new Label("View angle")); p3D.add(lAngle=new Label("")); p3D.add(bAngleM=new Button("<")); p3D.add(bAngleP=new Button(">")); p3D.add(cDamping=new Checkbox("Damping")); p3D.add(lDamp=new Label("")); p3D.add(bDampM=new Button("<")); p3D.add(bDampP=new Button(">")); p3D.add(cLimiting=new Checkbox("Limit")); p3D.add(lLimit=new Label("")); p3D.add(bLimitM=new Button("<")); p3D.add(bLimitP=new Button(">")); p3D.add(new Label("")); p3D.add(new Label("")); add("3D-Setup",p3D); } synchronized public boolean action(Event evt, Object arg) { String cmd=""; if("> Colors".equals(arg)) { ((CardLayout)this.getLayout()).show(this, "Colors"); } else if("> Main".equals(arg)) { ((CardLayout)this.getLayout()).show(this, "Main"); } else if("> Settings".equals(arg)) { ((CardLayout)this.getLayout()).show(this, "Settings"); } else if("> 3D-Setting".equals(arg)) { ((CardLayout)this.getLayout()).show(this, "3D-Setup"); } else if(arg instanceof Boolean) { String v=arg.equals(Boolean.TRUE)?"1":"0"; if(((Checkbox)evt.target).getLabel().equals("3D")) cmd+=";3d="+v; else if(((Checkbox)evt.target).getLabel().equals("Animations")) cmd+=";zoom="+v; else if(((Checkbox)evt.target).getLabel().equals("Damping")) cmd+=";damping="+v; else if(((Checkbox)evt.target).getLabel().equals("Limit")) cmd+=";limiting="+v; else if(((Checkbox)evt.target).getLabel().equals("Auto-Depth")) cmd+=";autodepth="+v; else if(((Checkbox)evt.target).getLabel().equals("Always Calc")) cmd+=";always="+v; else if(((Checkbox)evt.target).getLabel().equals("Julia-Set")) cmd+=";julia="+v; } else if("<".equals(arg)) { if(((Button)evt.target)==bDepthM) cmd+=";depth+-4"; if(((Button)evt.target)==bFactorM) cmd+=";factor+-1"; if(((Button)evt.target)==bAngleM) cmd+=";angle+-1"; if(((Button)evt.target)==bDampM) cmd+=";damp+-1"; if(((Button)evt.target)==bLimitM) cmd+=";limit+-2"; } else if(">".equals(arg)) { if(((Button)evt.target)==bDepthP) cmd+=";depth+4"; if(((Button)evt.target)==bFactorP) cmd+=";factor+1"; if(((Button)evt.target)==bAngleP) cmd+=";angle+1"; if(((Button)evt.target)==bDampP) cmd+=";damp+1"; if(((Button)evt.target)==bLimitP) cmd+=";limit+2"; } else if("<+".equals(arg)) { if(((Button)evt.target)==bRedAm) cmd+=";ra+-1"; if(((Button)evt.target)==bGreenAm) cmd+=";ga+-1"; if(((Button)evt.target)==bBlueAm) cmd+=";ba+-1"; } else if("+>>".equals(arg)) { if(((Button)evt.target)==bRedAp) cmd+=";ra+8"; if(((Button)evt.target)==bGreenAp) cmd+=";ga+8"; if(((Button)evt.target)==bBlueAp) cmd+=";ba+8"; } else if("<*".equals(arg)) { if(((Button)evt.target)==bRedMm) cmd+=";rm+-1"; if(((Button)evt.target)==bGreenMm) cmd+=";gm+-1"; if(((Button)evt.target)==bBlueMm) cmd+=";bm+-1"; } else if("*>>".equals(arg)) { if(((Button)evt.target)==bRedMp) cmd+=";rm+4"; if(((Button)evt.target)==bGreenMp) cmd+=";gm+4"; if(((Button)evt.target)==bBlueMp) cmd+=";bm+4"; } else if("Standard".equals(arg)) { cmd+=";rm=8;gm=16;bm=5;ra=0;ga=0;ba=192"; } else if("Gray scale".equals(arg)) { cmd+=";rm=4;gm=4;bm=4;ra=0;ga=0;ba=0"; } else if("Strong Colors".equals(arg)) { cmd+=";rm=11;gm=-25;bm=4;ra=0;ga=255;ba=197"; } else if("Up".equals(arg)) { cmd+=";updown=-1"; } else if("Down".equals(arg)) { cmd+=";updown=1"; } else if("Mandelbrot".equals(arg)) { cmd+=";gohome;type=0"; } else if("Mandelbrot ^ 4".equals(arg)) { cmd+=";gohome;type=1"; } else if("Spider".equals(arg)) { cmd+=";gohome;type=2"; } else if("Sierpinski".equals(arg)) { cmd+=";gohome;type=3"; } else if("Lambda".equals(arg)) { cmd+=";gohome;type=4"; } else if("Mandelbrot (int)".equals(arg)) { cmd+=";gohome;type=5"; } else if("Go Back".equals(arg)) { cmd+=";size*2"; } else if("Automatic".equals(arg)) { cmd+=";autozoom"; } else if("Calculate".equals(arg)) { cmd+=";calcall"; } else if("Go Home".equals(arg)) { cmd+=";gohome"; } else if("Send".equals(arg)) { cmd+=tCommand.getText(); } aMain.doCommand(cmd); return true; } public Dimension preferredSize() { return new Dimension(200, 256); } } /* This would change the statusline: if(iAutozoom==0) getAppletContext().showStatus("Calculating."); The compiler don't really handle this as constants. So I 'precompiled' them by hands: static int SURE=0x1000000, COLOR=(0xff<<24); */