buddhabrot.java
By hansl - July 26th, 2008
/* * Buddhabrot Java applet * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * * Hans Liss <Hans@Liss.pp.se> * http://hans.liss.pp.se * */ import java.awt.*; import java.awt.geom.Point2D.Double; import java.awt.image.*; import java.awt.event.*; import java.applet.*; import java.io.*; public class buddhabrot extends Applet implements Runnable,MouseListener,MouseMotionListener { private int tmpBuffer_r[]; private int tmpBuffer_g[]; private int tmpBuffer_b[]; private int hist_r[], hist_g[], hist_b[]; private int vmax_r, vmax_g, vmax_b; private BufferedImage ofsImage; private Graphics ofsG; private WritableRaster ofsRaster; private int[] ofsPixels; private volatile Thread paintThread = null; private int width; private int height; private int wh; private int limit_r; private int limit_g; private int limit_b; private int maxiter; private int lasthits; private double gc_x; private double gc_y; private double gd_x; private double gd_y; private double gv_x; private double gv_y; private int select_x0; private int select_y0; private int select_x1; private int select_y1; private int last_x1; private int last_y1; public static void main (String args[]) { System.out.println ("Run this program in a browser or in AppletViewer"); } private int getIntParam(String pname, int defaultValue) { String param = getParameter(pname); if (param != null) { try { int N = Integer.parseInt(param); if (N > 0) return N; } catch (NumberFormatException e) { } } return defaultValue; } public void init() { gc_x=-0.6134; gc_y=0; gd_x=4; gd_y=3; select_x0=0; select_y0=0; select_x1=0; select_y1=0; width = getSize().height; height = getSize().width; limit_r=getIntParam("limit_r", 1000); limit_g=getIntParam("limit_g", 25); limit_b=getIntParam("limit_b", 12); maxiter=(Math.max(limit_r, Math.max(limit_g, limit_b))); int tmpw=(int)((double)height * gd_x / gd_y); int tmph=(int)((double)width * gd_y / gd_x); if (tmpw < width) width=tmpw; else if (tmph < height) height=tmph; gv_x=gd_x/(double)width; gv_y=gd_y/(double)height; wh = width * height; tmpBuffer_r = new int[wh]; tmpBuffer_g = new int[wh]; tmpBuffer_b = new int[wh]; ofsImage = new BufferedImage(height, width, BufferedImage.TYPE_INT_ARGB); ofsG = ofsImage.getGraphics(); ofsRaster = ofsImage.getRaster(); ofsPixels = ( (DataBufferInt) ofsRaster.getDataBuffer()).getData(); for (int i = 0 ; i < wh; i++) { tmpBuffer_r[i] = 0; tmpBuffer_g[i] = 0; tmpBuffer_b[i] = 0; } vmax_r=vmax_g=vmax_b = 0; hist_r=hist_g=hist_b=null; addMouseMotionListener( this ); addMouseListener( this ); } public void start() { if (paintThread == null) { paintThread = new Thread(this, "Paint"); paintThread.start(); } } public void mouseClicked(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void mousePressed(MouseEvent e) { int x=e.getY(); int y=e.getX(); select_x0=x; select_y0=y; select_x1=x; select_y1=y; last_x1=x; last_y1=y; e.consume(); } public void mouseMoved(MouseEvent e) { } public void mouseDragged(MouseEvent e) { int x=e.getY(); int y=e.getX(); Graphics g = getGraphics(); if (x != select_x1 || y != select_y1) { int x0 = Math.min(select_x0, select_x1); int y0 = Math.min(select_y0, select_y1); int dx=Math.abs(select_x1 - select_x0); int dy=Math.abs(select_y1 - select_y0); g.setXORMode(getBackground()); if (dx>0 || dy>0) g.drawRect(y0, x0, dy, dx); select_x1=x; select_y1=y; dx=Math.abs(select_x1 - select_x0); dy=Math.abs(select_y1 - select_y0); if (dx < dy * width / height) { dx = dy * width/height; if (select_x1 < select_x0) select_x1 = select_x0 - dx; else select_x1=select_x0 + dx; } else if (dy < dx * height / width) { dy = dx * height/width; if (select_y1 < select_y0) select_y1 = select_y0 - dy; else select_y1=select_y0 + dy; } x0 = Math.min(select_x0, select_x1); y0 = Math.min(select_y0, select_y1); if (dx>0 || dy>0) g.drawRect(y0, x0, dy, dx); } e.consume(); } public void mouseReleased(MouseEvent e) { int x=e.getY(); int y=e.getX(); select_x1=x; select_y1=y; int dx=Math.abs(select_x1 - select_x0); int dy=Math.abs(select_y1 - select_y0); double x0 = Math.min(select_x0, select_x1); double y0 = Math.min(select_y0, select_y1); if (e.isMetaDown()) { gd_x *= 2; gd_y *= 2; } else if (dx == 0 && dy == 0) { gc_x += gd_x * ((double)(x0 - width/2) / (double)width); gc_y += gd_y * ((double)(y0 - height/2) / (double)height); gd_x /= 2; gd_y /= 2; } else { if (dx < dy * width / height) { dx = dy * width / height; if (select_x1 < select_x0) select_x1 = select_x0 - dx; else select_x1=select_x0 + dx; } else if (dy < dx * height / width) { dy = dx * height / width; if (select_y1 < select_y0) select_y1 = select_y0 - dy; else select_y1=select_y0 + dy; } gc_x += gd_x * ((double)(x0 + dx/2 - width/2) / (double)width); gc_y += gd_y * ((double)(y0 + dy/2 - height/2) / (double)height); gd_x *= (double)dx/(double)width; gd_y *= (double)dy/(double)height; } gv_x=gd_x/(double)width; gv_y=gd_y/(double)height; select_x0=0; select_y0=0; select_x1=0; select_y1=0; for (int i = 0 ; i < wh; i++) { tmpBuffer_r[i] = 0; tmpBuffer_g[i] = 0; tmpBuffer_b[i] = 0; } vmax_r=vmax_g=vmax_b = 0; hist_r=hist_g=hist_b=null; paintThread = new Thread(this, "Paint"); paintThread.start(); e.consume(); } public void paint(Graphics g) { super.paint(g); int hival_r; int hival_g; int hival_b; int i, j; synchronized(this) { for (i=0; i<width*height; i++) { double col_r=0, col_g=0, col_b=0; for (hival_r = vmax_r; hival_r > 0 && hist_r[hival_r]<=4; hival_r--); for (hival_g = vmax_g; hival_g > 0 && hist_g[hival_g]<=4; hival_g--); for (hival_b = vmax_b; hival_b > 0 && hist_b[hival_b]<=4; hival_b--); if (hival_r > 0) col_r=(double)(tmpBuffer_r[i])/(double)hival_r; if (hival_g > 0) col_g=(double)(tmpBuffer_g[i])/(double)hival_g; if (hival_b > 0) col_b=(double)(tmpBuffer_b[i])/(double)hival_b; if (col_r > 1) col_r=1; if (col_g > 1) col_g=1; if (col_b > 1) col_b=1; ofsPixels[i] = 0xff000000 | ((int)(255*col_r) << 16) | ((int)(255*col_g) << 8) | (int)(255*col_b); } if (select_x1 != select_x0 && select_y1 != select_y0) { int x0 = Math.min(select_x0, select_x1); int x1 = Math.max(select_x0, select_x1); int y0 = Math.min(select_y0, select_y1); int y1 = Math.max(select_y0, select_y1); int dx=x1-x0; int dy=y1-y0; ofsG.drawRect(y0, x0, dy, dx); } } g.drawImage( ofsImage, 0, 0, this); } int mandel(double cx, double cy) { int i=maxiter, xpos, ypos; int hits=0; double zx=cx, zy=cy, y, zx2=cx*cx, zy2=cy*cy; while((i > 0) && (zx2 + zy2 < 4.0)) { zy=2*zx*zy + cy; zx=zx2-zy2 + cx; zx2=zx*zx; zy2=zy*zy; i--; } if (i>0) { int n=i; i=maxiter; zx=cx; zy=cy; zx2=cx*cx; zy2=cy*cy; while((i > 0) && (zx2 + zy2 < 4.0)) { zy=2*zx*zy + cy; zx=zx2-zy2 + cx; zx2=zx*zx; zy2=zy*zy; i--; xpos=(int)((zx - (gc_x - gd_x/2))/gv_x); ypos=(int)((zy - (gc_y - gd_y/2))/gv_x); if (xpos >= 0 && xpos < width && ypos >= 1 && ypos < height) { hits++; int arpos=ypos + height * xpos; if (n > maxiter - limit_r) { tmpBuffer_r[arpos]++; if (tmpBuffer_r[arpos] > vmax_r) { int hist2[]=new int[tmpBuffer_r[arpos]+1]; if (vmax_r > 0) System.arraycopy(hist_r, 0, hist2, 0, vmax_r+1); hist_r=hist2; for (int j=vmax_r+1; j<=tmpBuffer_r[arpos]; j++) hist_r[j]=0; vmax_r=tmpBuffer_r[arpos]; } hist_r[tmpBuffer_r[arpos]]++; } if (n > maxiter - limit_g) { tmpBuffer_g[arpos]++; if (tmpBuffer_g[arpos] > vmax_g) { int hist2[]=new int[tmpBuffer_g[arpos]+1]; if (vmax_g > 0) System.arraycopy(hist_g, 0, hist2, 0, vmax_g+1); hist_g=hist2; for (int j=vmax_g+1; j<=tmpBuffer_g[arpos]; j++) hist_g[j]=0; vmax_g=tmpBuffer_g[arpos]; } hist_g[tmpBuffer_g[arpos]]++; } if (n > maxiter - limit_b) { tmpBuffer_b[arpos]++; if (tmpBuffer_b[arpos] > vmax_b) { int hist2[]=new int[tmpBuffer_b[arpos]+1]; if (vmax_b > 0) System.arraycopy(hist_b, 0, hist2, 0, vmax_b+1); hist_b=hist2; for (int j=vmax_b+1; j<=tmpBuffer_b[arpos]; j++) hist_b[j]=0; vmax_b=tmpBuffer_b[arpos]; } hist_b[tmpBuffer_b[arpos]]++; } } } } lasthits=hits; return i; } public void mutate(Double m) { if (Math.random() > 0.95) { m.setLocation(Math.random()*4-2, Math.random()*4-2); } else { double phi=Math.random() * Math.PI * 2; double r=(gd_x / 100) * Math.exp(Math.random() * 4); double mx=m.getX() + r*Math.cos(phi); double my=m.getY() + r*Math.sin(phi); m.setLocation(mx, my); } } public double TransitionProbability(int n1, int n2) { return (1 - ((double)n1/maxiter)) / (1 - ((double)n2/maxiter)); } public void run() { Thread myThread = Thread.currentThread(); int oldhits=-1; long n=10000000000L; int oldt=0; double cx=0; double cy=0; while (true) { if (paintThread != myThread) return; synchronized(this) { if (oldhits == -1) { oldt=mandel(cx, cy); oldhits=lasthits; } Double m=new Double(cx,cy); mutate(m); int newt=mandel(m.getX(), m.getY()); int newhits=lasthits; double t1=TransitionProbability(newt, oldt); double t2=TransitionProbability(oldt, newt); if (oldhits > 0) { double alpha=Math.min(1, Math.exp(Math.log((double)newhits * t1) - Math.log((double)oldhits * t2))); if (alpha > Math.random()) { cx = m.getX(); cy = m.getY(); oldt=newt; oldhits=newhits; } } else { cx = m.getX(); cy = m.getY(); oldt=newt; oldhits=newhits; } if ((newhits > 0) && (((n--) % 20) == 0)) { if (n == 0) n=10000000000L; repaint(); } } } } public void stop() { paintThread = null; } public void update ( Graphics g ){ paint(g); } }


Recent comments
1 year 4 weeks ago
1 year 31 weeks ago
1 year 34 weeks ago
1 year 39 weeks ago
1 year 39 weeks ago
2 years 2 weeks ago
2 years 13 weeks ago
2 years 13 weeks ago
2 years 13 weeks ago
2 years 14 weeks ago