randel.java
By hansl - July 26th, 2008
/* * Auto-colouring, randmly sampled 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 randel extends Applet implements Runnable,MouseListener,MouseMotionListener { private int sumBuffer[]; private int countBuffer[]; int vmax; private int hist[]; 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 lasthits; private boolean mouseInside=false; private int MAXITER=65535; private int col_r; private int col_g; private int col_b; 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"); } public void init() { gc_x=-0.6134; gc_y=0; gd_x=3.136; gd_y=2.352; vmax=0; hist=new int[1]; select_x0=0; select_y0=0; select_x1=0; select_y1=0; width = getSize().width; height = getSize().height; 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; wh = width * height; gv_x=gd_x/(double)width; gv_y=gd_y/(double)height; sumBuffer = new int[wh]; countBuffer = new int[wh]; ofsImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); ofsG = ofsImage.getGraphics(); ofsRaster = ofsImage.getRaster(); ofsPixels = ( (DataBufferInt) ofsRaster.getDataBuffer()).getData(); for (int i = 0 ; i < wh; i++) { sumBuffer[i] = 0; countBuffer[i] = 0; } 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) { mouseInside=true; } public void mouseExited(MouseEvent e) { mouseInside=false; } public void mousePressed(MouseEvent e) { int x=e.getX(); int y=e.getY(); 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.getX(); int y=e.getY(); 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(x0, y0, dx, dy); 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(x0, y0, dx, dy); } e.consume(); } public void mouseReleased(MouseEvent e) { int x=e.getX(); int y=e.getY(); select_x1=x; select_y1=y; int dx=Math.abs(select_x1 - select_x0); int dy=Math.abs(select_y1 - select_y0); Thread oldPaintThread = paintThread; paintThread = new Thread(this, "Paint"); while (oldPaintThread.isAlive()); if (e.isMetaDown()) { gd_x *= 2; gd_y *= 2; } else if (dx == 0 && dy == 0) { gc_x += gd_x * ((double)(select_x0 - width/2) / (double)width); gc_y += gd_y * ((double)((height-1-select_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; } double x0 = Math.min(select_x0, select_x1); double y0 = Math.max(select_y0, select_y1); gc_x += gd_x * ((double)(x0 + dx/2 - width/2) / (double)width); gc_y += gd_y * ((double)((height-1-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; vmax=0; hist=new int[1]; for (int i = 0 ; i < wh; i++) { sumBuffer[i] = 0; countBuffer[i] = 0; } paintThread.start(); e.consume(); } public void paint(Graphics g) { super.paint(g); int loval, hival, i, j; for (hival=vmax; hival>0 && hist[hival]<width*height/2000; hival--); for (loval=1; loval<=hival && hist[loval]<width*height/2000; loval++); for (i=0; i<wh; i++) { if (countBuffer[i] == 0 || sumBuffer[i]/countBuffer[i] == MAXITER) { col_r=0; col_g=0; col_b=0; } else { double val=sumBuffer[i]/countBuffer[i]; double h=0; if (hival > loval) h=(double)((val-loval) % (MAXITER-loval))/(double)(MAXITER-loval); double s=h; double v=h; h *= 255.2; h += 0.7; double v1 = Math.floor(h); h -= v1; s *= 211.7; v1 = Math.floor(s); s -= v1; s = 1-s; v *= 111.7; v1 = Math.floor(v); v -= v1; v = 1-v; hsv2rgb(h,s,v); } ofsPixels[i] = 0xff000000 | (col_r << 16) | (col_g << 8) | 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(x0, y0, dx, dy); } if (mouseInside) { ofsG.setColor(Color.white); ofsG.fillRect(2,2,width-4,36); ofsG.setColor(Color.black); ofsG.setFont(new Font("Helvetica", Font.PLAIN, 9)); String info="[vmax="+vmax+",hival="+hival+",loval="+loval+"]"; ofsG.drawString(info, width-150, 32); } ofsG.setColor(Color.black); ofsG.setFont(new Font("Helvetica", Font.PLAIN, 9)); String info1="[(x,y)=("+gc_x+","+gc_y+")"; String info2="dx="+gd_x+"]"; ofsG.drawString(info1, 20, 16); ofsG.drawString(info2, 20, 32); g.drawImage( ofsImage, 0, 0, this); } int mandel(double cx, double cy) { int i=MAXITER; double zx=cx, zy=cy, y, zx2=cx*cx, zy2=cy*cy, ox=cx, oy=cy, ccx=cx, ccy=cy; while((i > 0) && (zx2 + zy2 < 4.0)) { ox=zx; oy=zy; zy=2*zx*zy + ccy; zx=zx2-zy2 + ccx; zx2=zx*zx; zy2=zy*zy; i--; } int rx=(int)((cx - (gc_x - gd_x/2))/gv_x); int ry=(int)((cy - (gc_y - gd_y/2))/gv_y); int pos=((height-1-ry)*width+rx)%wh; sumBuffer[pos] += (MAXITER - i); countBuffer[pos]++; int newval=sumBuffer[pos]/countBuffer[pos]; if (newval > vmax) { int hist2[]=new int[newval + 1]; if (vmax > 0) System.arraycopy(hist, 0, hist2, 0, vmax+1); hist=hist2; for (int j=vmax+1; j<=newval; j++) hist[j]=0; vmax=newval; } else hist[newval]++; return i; } public void hsv2rgb(double H,double S,double V) { int i; double f,p,q,t; H = H*6; if (H>=6) H-=6; i=(int)H; f=H-(double)i; p=V*(1.0-S); q=V*(1.0-(S*f)); t=V*(1.0-(S*(1.0-f))); switch(i) { case 0: col_r=(int)(V*255); col_g=(int)(t*255); col_b=(int)(p*255); break; case 1: col_r=(int)(q*255); col_g=(int)(V*255); col_b=(int)(p*255); break; case 2: col_r=(int)(p*255); col_g=(int)(V*255); col_b=(int)(t*255); break; case 3: col_r=(int)(p*255); col_g=(int)(q*255); col_b=(int)(V*255); break; case 4: col_r=(int)(t*255); col_g=(int)(p*255); col_b=(int)(V*255); break; case 5: col_r=(int)(V*255); col_g=(int)(p*255); col_b=(int)(q*255); break; } } public void mutate(Double m) { int x, y; double mx, my; if (Math.random() > 0.95) { do { mx=(double)(Math.random()*width)*gv_x + (gc_x - gd_x/2); my=(double)(Math.random()*height)*gv_y + (gc_y - gd_y/2); x=(int)((mx - (gc_x - gd_x/2))/gv_x); y=(int)((my - (gc_y - gd_y/2))/gv_y); } while (x < 0 || x >= width || y < 0 || y >= height); m.setLocation(mx, my); } else { do { double phi=Math.random() * Math.PI * 2; double r=(gd_x / 100) * Math.exp(Math.random() * 4); mx=m.getX() + r*Math.cos(phi); my=m.getY() + r*Math.sin(phi); x=(int)((mx - (gc_x - gd_x/2))/gv_x); y=(int)((my - (gc_y - gd_y/2))/gv_y); } while (x < 0 || x >= width || y < 0 || y >= height); 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(); for (int i=0; i<=vmax; i++) hist[i]=0; long n=10000000000L; int oldhits=-1; int oldt=0; double cx=(double)(Math.random()*width)*gv_x + (gc_x - gd_x/2); double cy=(double)(Math.random()*height)*gv_y + (gc_y - gd_y/2); while (true) { if (paintThread != myThread) return; if (oldhits == -1) { oldt=mandel(cx, cy); if (oldt>0) oldhits=1; else oldhits=0; } Double m=new Double(cx,cy); mutate(m); int newt=mandel(m.getX(), m.getY()); int newhits; if (newt>0) newhits=1; else newhits=0; 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 (((n--) % 100) == 0) 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