import java.applet.Applet;
import java.awt.*;
import java.awt.image.ColorModel;
import java.awt.image.MemoryImageSource;
/**
* Mandelbrot Set Java Applet,
* (c) 2004 <a href=http://fractals.nsu.ru/>http://fractals.nsu.ru/</a> <br>
* It's a heavily documented example of a simple java applet, which
* calculates the Mandebrot Set fractal image in memory, and displays it.
* @author Aleksey
*
* JavaDoc documentation can be generated by running command:
* javadoc -d doc Mandelbrot.java
*/
public class Mandelbrot extends Applet implements Runnable
{
Thread runner; // working thread, used to calculate the image
Image img; // the image to calculate
// The number of iterations. The greater it is,
// the more accurate image will be calculated
int iterations;
int method; // Method used to paint the image, see calcPointColor()
/**
* Called by the browser or applet viewer to inform this applet that it
* has been loaded into the system.
* The init() method reads applet parameters 'iterations' and 'method'
* from html APPLET tag.
* Then the working thread is created to start image calculation.
*/
public void init() {
iterations = 200;
method = 0;
// initialize applet parameters
try {
String param = getParameter("ITERATIONS");
if (param != null) {
iterations = Integer.parseInt(param, 10);
}
param = getParameter("METHOD");
if (param != null) {
method = Integer.parseInt(param, 10) & 1;
}
} catch (Exception e) {
e.printStackTrace();
}
// create working thread, the created thread will call run() method
runner = new Thread(this);
runner.start();
}
/**
* Called by the browser or applet viewer to inform this applet that it
* is being destroing and that it should free resources it has allocated.
*/
public void destroy() {
if(runner!=null && runner.isAlive()) {
Thread th = runner;
// notify working thread to stop
runner = null;
try {
th.join(100); // wait 100ms for the working thread to die.
} catch(InterruptedException e) {}
}
}
static String calcString = "Calculating...";
/**
* Called when applet window needs to be repainted
*/
public void paint(Graphics g) {
int w = getSize().width;
int h = getSize().height;
if (img == null) {
// if img image is not calculated yet, call parent's paint method
super.paint(g);
// and print the string "Calculating..."
g.setColor(Color.black);
FontMetrics fm = g.getFontMetrics();
int x = (w - fm.stringWidth(calcString))/2;
int y = h/2;
g.drawString(calcString, x, y);
} else {
g.drawImage(img, 0, 0, w, h, this);
}
}
/**
* The run() method is called by the working thread, just after
* the working thread is created in the {@link #init()} method
*/
public void run() {
// calculate the image of Mandelbrot set
img = calculateImage();
// and notify interface thread to repain th applet
if (img != null && runner == Thread.currentThread())
repaint();
}
/**
* Calculates and returns the Mandelbrot set image.
* Halts calculation and returns null if the Applet is stopped
*/
Image calculateImage() {
Thread me = Thread.currentThread();
int width = getSize().width;
int height = getSize().height;
int pixels[] = new int[width * height];
int index = 0;
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
// poll once per pixel to see if we've been told to stop.
if(runner!=me) return null;
double cx=3.5/width*(i-width/2)-.75;
double cy=3.5/width*(j-height/2);
// set pixel color
pixels[index++] = calcPointColor(cx,cy);
}
}
// convert array of pixels to the Image class
return createImage(new MemoryImageSource(width, height,
ColorModel.getRGBdefault(), pixels, 0, width));
}
/**
* Calculates the color of a complex point cx+i*cy.
* The color is white if the point belongs to the Mandelbrot set.
* @param cx - real part of the complex point
* @param cx - real imaginary part of the complex point
* @returns the point color
*/
int calcPointColor(double cx, double cy) {
double x=cx, y=cy, ex=cx, ey=cy;
for(int n=0; n<iterations && runner!=null; n++) {
// complex assigment Z1=Z^2+C
double x1=x*x-y*y+cx;
double y1=2*x*y+cy;
x=x1;
y=y1;
double r2=x*x+y*y; // abs(x+i*y)^2
if(r2>10000) {
// the point cx+i*cy found to be outside the Mandelbrot set,
// so we can calculate its color
x1=(ex*x+ey*y)/r2;
y1=(ey*x-ex*y)/r2;
ex=x1;
ey=y1;
// use arg(z) if method==1, or abs(z) otherwise
double hue = (method==1 ?
.69-Math.abs(Math.atan2(ey, ex))/18 : // arctan of ey/ex
.69-Math.sqrt(ex*ex+ey*ey)/10); // abs(ex+i*ey)
// calculate the color using continuous function HSBtoRGB()
return Color.HSBtoRGB( (float)hue, 0.9f, 0.7f );
}
x1=ex*x-ey*y;
y1=ey*x+ex*y;
ex=x1;
ey=y1;
}
// return white color if the point belongs to the Mandelbrot set
return 0xFFFFFFFF;
}
};
syntax highlighted by Code2HTML, v. 0.9.1