

public class Julia3D {

	public boolean bitmap[][][] = null;

	public static boolean[][][] generateBitmap(double c1[], double c2[], int size[], double a, double b, int n) {
		double r = 3 + a * a + b * b;
		r *= r;

		boolean bitmap[][][] = new boolean[size[0]][size[1]][size[2]];

		double scale[] = new double[3];
		for(int i = 0; i < 3; i++)
			scale[i] = (c2[i] - c1[i]) / (double)size[i];

		for(int x = 0; x < size[0]; x++) {
			for(int y = 0; y < size[1]; y++) {
				for(int z = 0; z < size[2]; z++) {
					double px = (double)x * scale[0] + c1[0];
					double py = (double)y * scale[1] + c1[1];
					double pz = (double)z * scale[2] + c1[2];
					int c = 0;
					while((px * px + py * py + pz * pz < r) && (c < n)) {
						c++;
						double d0 = px * px - py * py - pz * pz + a;
						double d1 = 2.0 * px * py + b;
						pz = 2.0 * px * pz;
						py = d1;
						px = d0;
					}

					bitmap[x][y][z] = (c >= n);
				}
			}
		}
		return(bitmap);
	}

	public static boolean[][][] outlineBitmap(boolean[][][] bitmap) {

		int sx = bitmap.length;
		int sy = bitmap[0].length;
		int sz = bitmap[0][0].length;

		boolean bitmap2[][][] = new boolean[sx][sy][sz];
		for(int x = 0; x < 2; x++)
			for(int y = 0; y < 2; y++)
				for(int z = 0; z < 2; z++)
					bitmap2[x * (sx - 1)][y *( sy - 1)][z * (sz - 1)] = bitmap[x * (sx - 1)][y * (sy - 1)][z * (sz - 1)];

		for(int x = 1; x < sx - 1; x++) {
			for(int y = 1; y < sy - 1; y++) {
				for(int z = 1; z < sz - 1; z++) {
					if(bitmap[x][y][z]) {
						int c = 0;
						if(							bitmap[x-1][y][z] &&
													bitmap[x+1][y][z] &&
													bitmap[x][y-1][z] &&
													bitmap[x][y+1][z] &&
													bitmap[x][y][z-1] &&
													bitmap[x][y][z+1]) {
							// cleanup
							bitmap2[x][y][z] = false;
						} else {
							bitmap2[x][y][z] = true;
						}
					} else {
						bitmap2[x][y][z] = false;
					}
				}
			}
		}
		return(bitmap2);

	}

	public static void outputBitmap(double c1[], double c2[], boolean[][][] bitmap) {
		
		int sx = bitmap.length;
		int sy = bitmap[0].length;
		int sz = bitmap[0][0].length;

		double scale[] = new double[3];
		scale[0] = (c2[0] - c1[0]) / (double)sx;
		scale[1] = (c2[1] - c1[1]) / (double)sy;
		scale[2] = (c2[2] - c1[2]) / (double)sz;

		int c = 0;
		for(int x = 0; x < sx; x++) {
			double px = (double)x * scale[0] + c1[0];
			for(int y = 0; y < sy; y++) {
				double py = (double)y * scale[1] + c1[1];
				for(int z = 0; z < sz; z++) {
					if(bitmap[x][y][z]) {
						double pz = (double)z * scale[2] + c1[2];
						//System.out.println(px + " " + py + " " + pz);
						c++;
					}
				}
			}
		}
		System.out.println("dots = " + c);
	}


	public static void main(String args[]) {
		double c1[] = { -1.65, -0.75, -0.75 };
		double c2[] = { 1.65, 0.75, 0.75 };
		int size[] = { 330, 150, 150};
		double a = -1.0;
		double b = 0.0;
		int n = 100;

		long start = new java.util.Date().getTime();

		boolean[][][] bitmap1 = generateBitmap(c1, c2, size, a, b, n);
		boolean[][][] bitmap2 = outlineBitmap(bitmap1);
		outputBitmap(c1, c2, bitmap2);

		long end = new java.util.Date().getTime();

		float diff = (float)(end - start) / 1000.0f;

		System.out.println("runtime = " + diff + " seconds");
	}
}