The Mandelbrot set has been a favorite of mine for many years. I've successfully created it in Pascal years ago and more recently on a TI-83 graphing calculator (Java renders it juuuuust a bit faster).
Since complex numbers are involved, I took a version from a text that extends RecursiveAction
using a BufferedImage
and ForkJoinPool
(without understanding the those concepts and the overall implementation) and, using routines I developed a few months ago, modified (the heck out of) the code that does the point-plotting so that it looks more like complex numbers are involved.
Original:
public class MandelbrotTask extends RecursiveAction {
...
public void render() {
...
for (int x = xStart; x <= xEnd; x++) {
for (int y = yStart; y <= yEnd; y++) {
double r = x * zoomFactor / image.getWidth() - zoomFactor / 2 + offsetX;
double i = y * zoomFactor / image.getHeight() - zoomFactor / 2 + offsetY;
double zr = 0, zi = 0;
int iter;
for (iter = 0; iter < maxIter; iter++) {
double nzr = zr * zr - zi * zi + r;
double nzi = 2 * zr * zi + i;
if (nzr * nzr + nzi * nzi > escapeRadius * escapeRadius)
break;
zr = nzr;
zi = nzi;
}
image.setRGB(x, y, Color.HSBtoRGB(0.5f * iter / maxIter, 1.0f, 1.0f));
}
}
My revised, somewhat-cleaner code:
for (int x = xStart; x <= xEnd; x++) {
for (int y = yStart; y <= yEnd; y++) {
z1 = new ComplexNumber(x * dx - zoomFactor / 2 + offsetX,
y * dy - zoomFactor / 2 + offsetY);
z0 = new ComplexNumber(0,0);
int iter;
for (iter = 0; iter < maxIter; iter++) {
nz = cAdd(cMult(z0,z0),z1);
if (cAbs(nz) > escapeRadius )
break;
z0 = nz;
}
image.setRGB(x, y, Color.HSBtoRGB(0.5f * iter / maxIter, 1.0f, 1.0f));
}
}
My only question is how to get rid of "new" on the two lines defining z1 and z0. It seems like I'm wasting a ton of memory since the two objects get "newed" a total of 1,000,000+ times during the almost 25,000 executions of the above block of code, though there's no problem as is.
I know I need new
at least once inside the method, but if I put the statements (shown below) outside the loop (and either inside or outside render()
), if I omit new
from those two lines defining z1 and z0 in the block of code above, I get the error
"cannot find symbol: method ComplexNumber(double,double) location: class MandelbrotTask."
z1 = new ComplexNumber();
z0 = new ComplexNumber();
---- edit 10:21 12/26/13
Here is the part of the ComplexNumber class that is invovled. The constructor call ComplexNumber()
sets real
and imag
-inary parts to 0.
class ComplexNumber {
public double real;
public double imag;
public ComplexNumber() {
real = 0.0;
imag = 0.0;
}
public ComplexNumber(double r, double i) {
this.real = r;
this.imag = i;
}
public static ComplexNumber cAdd(ComplexNumber a, ComplexNumber b) {
return new ComplexNumber(a.real + b.real, a.imag + b.imag);
}
public static ComplexNumber cMult(ComplexNumber a, ComplexNumber b) {
return new ComplexNumber(a.real * b.real - a.imag * b.imag, a.real * b.imag + a.imag * b.real);
}
public static double sqr(double x) {
return x * x;
}
public static double cAbs(ComplexNumber z) {
return Math.sqrt(sqr(z.real) + sqr(z.imag));
}
}