amultimand.java
By hansl - July 26th, 2008
/* * Multimand Java applet * Mandelbrot graph colouring algorithm based on More Than Usual * information * * See http://hans.liss.pp.se/multimand.html for more info on this * * 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.image.*; import java.awt.event.*; import java.applet.*; import java.io.*; public class amultimand extends Applet implements Runnable,MouseListener,MouseMotionListener { private int tmpBuffer_speed[]; private int tmpBuffer_angle[]; private int tmpBuffer_iter[]; private int vmax_speed, vmax_angle, vmax_iter; private int hival_speed, hival_angle, hival_iter; private int hist_speed[], hist_angle[], hist_iter[]; private Image ofsImage; private Graphics ofsG; private volatile Thread paintThread = null; private int width; private int height; private int wh; private int maxpos; private int maxiter=65535; 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 col_r, col_g, col_b; private int select_x0; private int select_y0; private int select_x1; private int select_y1; private int last_x1; private int last_y1; private final int SLEEPTIME=20; 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().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; gv_x=gd_x/(double)width; gv_y=gd_y/(double)height; wh = width * height; tmpBuffer_speed = new int[wh]; tmpBuffer_angle = new int[wh]; tmpBuffer_iter = new int[wh]; ofsImage = createImage (width, height); ofsG = ofsImage.getGraphics(); for (int y = 0 ; y < height; y++) { for (int x = 0 ; x < width; x++) { tmpBuffer_speed[x + y*width] = 0; tmpBuffer_angle[x + y*width] = 0; tmpBuffer_iter[x + y*width] = 0; } } vmax_speed=vmax_angle=vmax_iter = 0; hival_speed=hival_angle=hival_iter = 0; hist_speed=new int[vmax_speed+1]; hist_angle=new int[vmax_angle+1]; hist_iter=new int[vmax_iter+1]; 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.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); 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; for (int i = 0 ; i < wh; i++) { tmpBuffer_speed[i] = 0; tmpBuffer_angle[i] = 0; tmpBuffer_iter[i] = 0; } vmax_speed=vmax_angle=vmax_iter = 0; hival_speed=hival_angle=hival_iter = 0; hist_speed=new int[vmax_speed+1]; hist_angle=new int[vmax_angle+1]; hist_iter=new int[vmax_iter+1]; paintThread = new Thread(this, "Paint"); paintThread.start(); e.consume(); } 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 paint(Graphics g) { super.paint(g); // int hival_speed; // int hival_angle; // int hival_iter; int loval_iter; int i, j; double h, s, v; synchronized(this) { // System.out.print("Painting..."); // for (hival_speed = vmax_speed; hival_speed > 0 && hist_speed[hival_speed]<=1; hival_speed--); // for (hival_angle = vmax_angle; hival_angle > 0 && hist_angle[hival_angle]<=1; hival_angle--); // for (hival_iter = vmax_iter; hival_iter > 0 && hist_iter[hival_iter]<=1; hival_iter--); for (loval_iter = 0; loval_iter < vmax_iter && hist_iter[hival_iter]<=1; loval_iter++); for (i=0; i<maxpos; i++) { h=s=v=0; if (hival_speed > 0) v=(double)(2*tmpBuffer_speed[i])/(double)hival_speed; if (v>2) v=2; if (v>1) v=2-v; v=0.5+v/2; if (hival_angle > 0) h=(double)tmpBuffer_angle[i]/(double)hival_angle; if (h>1) h=1; if (tmpBuffer_iter[i] != maxiter) { if ((hival_iter-loval_iter) > 0) s=(double)(2*(tmpBuffer_iter[i]-loval_iter))/(double)(hival_iter-loval_iter); else s=0; } else s=2; if (s>2) s=2; if (s>1) s=2-s; s=0.5+s/2; hsv2rgb(h,s,v); ofsG.setColor(new Color(col_r, col_g, col_b)); ofsG.drawLine((int)(i % width), i / width, (int)(i % width), i / width); } 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); } // System.out.println("done."); } g.drawImage( ofsImage, 0, 0, this); } void mandel(double cx, double cy, int arpos) { int i=maxiter, speed, angle; 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--; } double v1=Math.sqrt((zx-ox)*(zx-ox)+(zy-oy)*(zy-oy)) / 100; if (v1 > 1) v1=1; speed = (int)(v1*10000); angle = (int)(360*(Math.atan2((zx-ox),(zy-oy))+3.141592)/6.283184); synchronized(this) { tmpBuffer_speed[arpos] = speed; if (tmpBuffer_speed[arpos] > vmax_speed) { // System.out.println("vmax_speed changed from "+vmax_speed+" to "+tmpBuffer_speed[arpos]); int hist2[]=new int[tmpBuffer_speed[arpos]+1]; if (vmax_speed > 0) System.arraycopy(hist_speed, 0, hist2, 0, vmax_speed+1); hist_speed=hist2; for (int j=vmax_speed+1; j<=tmpBuffer_speed[arpos]; j++) hist_speed[j]=0; vmax_speed=tmpBuffer_speed[arpos]; } hist_speed[tmpBuffer_speed[arpos]]++; if (hist_speed[tmpBuffer_speed[arpos]] > 1 && tmpBuffer_speed[arpos]>hival_speed) hival_speed=tmpBuffer_speed[arpos]; tmpBuffer_angle[arpos] = angle; if (tmpBuffer_angle[arpos] > vmax_angle) { // System.out.println("vmax_angle changed from "+vmax_angle+" to "+tmpBuffer_angle[arpos]); int hist2[]=new int[tmpBuffer_angle[arpos]+1]; if (vmax_angle > 0) System.arraycopy(hist_angle, 0, hist2, 0, vmax_angle+1); hist_angle=hist2; for (int j=vmax_angle+1; j<=tmpBuffer_angle[arpos]; j++) hist_angle[j]=0; vmax_angle=tmpBuffer_angle[arpos]; } hist_angle[tmpBuffer_angle[arpos]]++; if (hist_angle[tmpBuffer_angle[arpos]] > 1 && tmpBuffer_angle[arpos]>hival_angle) hival_angle=tmpBuffer_angle[arpos]; tmpBuffer_iter[arpos] = maxiter - i; if (i != 0) { if (tmpBuffer_iter[arpos] > vmax_iter) { // System.out.println("vmax_iter changed from "+vmax_iter+" to "+tmpBuffer_iter[arpos]); int hist2[]=new int[tmpBuffer_iter[arpos]+1]; if (vmax_iter > 0) System.arraycopy(hist_iter, 0, hist2, 0, vmax_iter+1); hist_iter=hist2; for (int j=vmax_iter+1; j<=tmpBuffer_iter[arpos]; j++) hist_iter[j]=0; vmax_iter=tmpBuffer_iter[arpos]; } hist_iter[tmpBuffer_iter[arpos]]++; if (hist_iter[tmpBuffer_iter[arpos]] > 1 && tmpBuffer_iter[arpos]>hival_iter) hival_iter=tmpBuffer_iter[arpos]; } } } public void run() { Thread myThread = Thread.currentThread(); int n=0; for (int y=height-1; y >=0; y--) { for (int x=0; x < width; x++) { if (paintThread != myThread) return; double cx=gd_x * ((double)x/(double)width) + gc_x - (gd_x/2); double cy=gd_y * ((double)y/(double)height) + gc_y - (gd_y/2); int arpos=x + width * (height - 1 - y); mandel(cx, cy, arpos); maxpos=arpos; } if (n++ == 20) { n=0; repaint(); try {myThread.sleep(SLEEPTIME);} catch(InterruptedException e) {} } } repaint(); } public void stop() { paintThread = null; } public void update ( Graphics g ){ paint(g); } }


Recent comments
1 year 19 weeks ago
1 year 46 weeks ago
1 year 49 weeks ago
2 years 2 weeks ago
2 years 2 weeks ago
2 years 18 weeks ago
2 years 28 weeks ago
2 years 28 weeks ago
2 years 28 weeks ago
2 years 29 weeks ago