/** Copyright: Peter Cappello Feel free to use this code as is, provided that you leave these comments in place. Feel free to modify this code, provided that you explicitly indicate that your code is based on Peter Cappello's code A class of Mandelbrot Set objects */ import java.applet.*; import java.awt.*; import java.awt.image.*; public class MandelbrotSet { // MandelbrotSet state private double X, Y, // lower left corner of region edg; // edge lengthh of region private int clr, // # bits or red, green, blue lgR, // resolution: discretize region // into 2^lgRres X 2^lgRes squares lgA, // log of atom size // partition grid into atoms cnt[][], // iteration count for each square // derived values lim, res, atm; // internal variables private final static int MAXRES = 512, CODE = 255 << 24; private int[] p, // pixels used in MemoryImageSource // color table used to encode count as a pixel colors = new int[24]; private MemoryImageSource m; private Image imag; public MandelbrotSet(double x, double y, double e, int c, int r, int a) { X = x; Y = y; edg = e; clr = c; lgR = r; lgA = a; lim = (int) Math.pow(2, 3*c); res = (int) Math.pow(2,r); atm = (int) Math.pow(2,a); cnt = new int[res][res]; p = new int[atm*atm]; for (int i = 0; i < 24; i++) colors[i] = 1 << i; } /** partition region into atoms; compute counts for atom */ public void draw(Applet a, Graphics g) { int num = res/atm, // num sub-regions acnt[][] = new int[atm][atm], // count array for atom row, col, i, j; double dlta = edg/num; // edge of a sub-region for (i = 0; i < num; i++) for (j = 0; j < num; j++) { MandelbrotComplet t = new MandelbrotComplet(X + j*dlta, Y + i*dlta,dlta, atm, lim, acnt); t.compute(); for (row = 0; row < atm; row++) for (col = 0; col < atm; col++) { // copy atom counts in full counts array cnt[i*atm + row][j*atm + col] = acnt[row][col]; p[(atm - row - 1)*atm + col] = encodePixel(acnt[row][col]); } // create, display image MemoryImageSource m = new MemoryImageSource(atm, atm, p, 0, atm); Image imag = a.createImage(m); g.drawImage(imag, j*atm, (num - 1 - i)*atm + 50, null); } } private final int encodePixel(int count) { // Encode the count as a pixel int pixel = CODE, b, c, colr; if (count != lim) { for (b = 0; b < 3; b++) for (c = 0; c < clr; c++) { colr = ((count & 1) == 1) ? colors[8-clr + b*8 + c] : 0; pixel = pixel | colr; count = count >> 1; } } return pixel; } /* // morph into recolor. Must use a different p array for the full image public final void recolor(Applet a, Graphics g, int x, int y) { int count, b, colr, code = 255 << 24; for (int row = 0; row < res; row++) for (int col = 0; col < res; col++) { // Encode the count as a pixel // eliminate this code in favor of invoking encodePixel p[res*row + col] = code; if (cnt[row][col] != lim) { count = cnt[row][col]; for (b = 0; b < 3; b++) for (int c = 0; c < clr; c++) { colr = ((count & 1) == 1) ? colors[8-clr + b*8 + c] : 0; p[res*row + col] = p[res*row + col] | colr; count = count >> 1; } } } // create, display image m = new MemoryImageSource(res, res, p, 0, res); imag = a.createImage(m); g.drawImage(imag, x, y, null); } */ public void setRegion(double x, double y, double e) { X = x; Y = y; edg = e; } public int setClr(int c) { clr = rangeCheck(0, 8, c); lim = (int) Math.pow(2,3*clr); return clr; } public int setLgr(int r) { lgR = rangeCheck(0, 9, r); res = (int) Math.pow(2,lgR); return lgR; } public int setLga(int a) { lgA = rangeCheck(0, 9, a); atm = (int) Math.pow(2,lgA); return lgA; } private int rangeCheck(int min, int max, int actual) { return (int) Math.max(Math.min(max,actual),min); } public void zoom() { edg /= 2.0; X += edg/2.0; Y += edg/2.0; } public void unzoom() { edg *= 2.0; X -= edg/4.0; Y -= edg/4.0; } // Translate the center of the region to the mouse coordinates public void recenter(int x, int y, int iedge) { X += edg*((double) x/iedge - 0.5); Y += edg*((double) y/iedge - 0.5); } }