/* Mandelbrot Set V1.00 This program calculates a Mandelbrot Set and saves it as a PPM graphic file. Code and comments by David Grantham This is freeware, do what you want with it! */ // Include the fstream library // #include // ?! // using namespace std; /* main is the start of the program. argc is an integer(int) that contains the number of command line arguments. *argv[] is a pointer to a string array containing each argument. */ int main (int argc, char *argv[]) { /* Create the integer(int) variables with their default values. width is the final width of the image in pixels. height is the final height of the image in pixels. maxi is the maximum number of iterations, higher numbers are more accurate but slower. i is the iteration count, the initial value is always 0. plotx is the current x position in pixels, the initial value is always 0. ploty is the current y position in pixels, the initial value is always 0. */ int width=1024,height=768, maxi=4096, i=0, plotx=0, ploty=0; /* Create the double variables with their default values. x1 is the left hand side of the complex plane. x2 is the right hand side of the complex plane. y is the top of the complex plane. Here are some interesting x1 x2 y positions I have found. double x1=0.26462, x2=0.2648, y=-0.00337; double x1=-1.768612, x2=-1.7686032, y=-0.002226; double x1=0.3673, x2=0.3676, y=-0.10096; double x1=-1.067096873030511, x2=-1.067096872505631, y=0.26969975630849263; double x1=-1.2512200661551665, x2=-1.2512200661506456, y=0.40385506477582533; double x1=-0.69482502340366514, x2=-0.69482487749053334, y=0.33921447691623247; double x1=-0.599642486811046700, x2=-0.599642467312265230, y=0.447775654691900120; */ double x1=-2.00, x2=1.00, y=1.125; /* The command line arguments are used to override the program default values, the format is:- mandelbrot.exe width height maxi x1 x2 y with the default values as an example this would be:- mandelbrot.exe 1024 768 4096 -2.00 1.00 1.23 You need all 6 arguments (in order) or the default values will be used for all of the variables. The command line arguments are held in argv[1] to argv[6]. argv[0] contains the program name which is not needed here. This will be executed only if argc is equal to 7. (program name + 6 arguments) atoi converts a string to an integer. atof converts a string to double. */ if (argc==7){ width =atoi(argv[1]); height=atoi(argv[2]); maxi =atoi(argv[3]); x1 =atof(argv[4]); x2 =atof(argv[5]); y =atof(argv[6]); } /* Create the double that contains the step between one complex number and the next, this is xstep. To keep the correct aspect ratio the ystep is the same as the xstep. */ double xstep=(x2-x1)/width, ystep=xstep; /* Create double variables with their default values. a is the x coordinate of the complex plane, the initial value is always 0. bi is the y coordinate of the complex plane, the initial value is always 0. atemp is a temporary 'a' coordinate, the initial value is always 0. xorig is a copy of x1 as x1 is destroyed in the calculation and is needed again for each line. */ double a=0, bi=0, atemp=0, xorig=x1; // Create the ppmhead string with enough space (40) for storage. This is where the ppm header is constructed. // char ppmhead[40]; /* Create the integer(int) arrays that hold the RGB lookup table. 512 values in each. For example:- colour_r[10]=60 colour_g[10]=10 colour_b[10]=0 =RGB(3C0A00) The numbers here are a matter of personal choice. Keep colour_r[0] and colour_g[0] and colour_b[0] equal to 0 (Black). */ int colour_r[512]={0,15,20,25,30,35,40,45,50,55,60,65,70,75,80,90,92,95,100,105,110,115,120,125,130,135,140,150,160,170,180,190,200,210,220,230,240,250,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,250,240,230,220,210,200,190,180,170,160,150,140,130,120,100,90,80,75,70,65,60,55,50,45,40,35,30,25,20,18,16,14,12,10,9,8,7,6,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; int colour_g[512]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,255,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,228,226,224,222,220,218,216,214,212,210,208,206,204,202,200,198,196,194,192,190,188,186,184,182,180,178,176,174,172,170,168,166,164,162,160,158,156,154,152,150,148,146,144,142,140,138,136,134,132,130,128,126,124,122,120,118,116,114,112,110,108,106,104,102,100,98,96,94,92,90,88,86,84,82,80,78,76,74,72,70,68,66,64,62,60,58,56,54,52,50,48,46,44,42,40,38,36,34,32,30,28,26,24,22,20,18,16,14,12,10,9,8,7,6,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; int colour_b[512]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,12,14,17,20,25,30,35,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,35,30,25,20,15,10,9,8,7,6,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,82,84,86,88,90,92,94,96,98,100,102,104,106,108,110,112,114,116,118,120,122,124,126,128,130,132,134,136,138,140,142,144,146,148,150,152,154,156,158,160,162,164,166,168,170,172,174,176,178,180,182,184,186,188,190,192,194,196,198,200,202,204,206,208,210,212,214,216,218,220,222,224,226,228,230,232,234,236,238,240,242,244,246,248,250,252,254,255,255,253,251,249,247,245,243,241,239,237,235,233,231,229,227,225,223,221,219,217,215,213,211,209,207,205,203,201,199,197,195,193,191,189,187,185,183,181,179,177,175,173,171,169,167,165,163,161,159,157,155,153,151,149,147,145,143,141,139,137,135,133,131,129,127,125,123,121,119,117,115,113,111,109,107,105,103,101,99,97,95,93,91,89,87,85,83,81,79,77,75,73,71,69,67,65,63,61,59,57,55,53,51,49,47,45,43,41,39,37,35,33,31,29,27,25,23,21,19,17,15,13,11,9,7,5,3}; /* Displays the contents of the variables, width height maxi x1 x2 y. The formatting argument is automatically replaced with the corresponding variable value. %u is an unsigned decimal integer and is used for width, height and maxi. %.17g is a decimal floating point with a precision of 17, with the trailing zeros removed(g) and is used for x1, x2 and y \n is a new line. */ printf ("%u %u %u %.17g %.17g %.17g\n",width,height,maxi,x1,x2,y); /* Construct the PPM graphic file format header. The PPM format is as follows:- P6 width height maxvalue RGBRGBRGB... So using the default values the header would look like this:- "P6 1024 768 255 " Note the space at the end. sprintf copies a formatted string in to another string. The formatting argument is automatically replaced with the corresponding variable value. %u is an unsigned decimal integer and is used for the width and height variables. The maxvalue for us is always 255 (8 bits). The result is stored in the string ppmhead. ppmhead needs to be large enough to receive the result. This is why we created it with [40] (The RGB data is written during the calculation.) */ sprintf(ppmhead,"P6 %u %u 255 ",width,height); /* Create a file called mandelbrot.ppm, making sure you can write binary data. In future write operations this file will be accessed by its handle which is 'ppm' */ ofstream ppm ("mandelbrot.ppm", ios::out|ios::binary); /* Write the contents of the ppmhead string to the handle 'ppm'. The write command needs a length, this is obtained using strlen(ppmhead). */ ppm.write(ppmhead,strlen(ppmhead)); /* This counts from 0 to width, and adds 1 to the height. Then counts from 0 to width again. This continues until ploty equals height. So all positions for width and height are passed. */ for (ploty=0; ploty!=height; ploty++){ for (plotx=0; plotx!=width; plotx++){ // a,bi and i need to be zeroed, because they were changed during the previous calculation. // a=0; bi=0; i=0; /* For each loop 'i' increments by 1 (i++). and will loop until either 'i' is greater than 'maxi' or a^2+bi^2 is greater than 4. 'atemp' is used because we need 'a' unchanged for the 'bi' calculation. Afterwards 'atemp' is copied to 'a'. I do know how it works but I can't quite explain it coherently. So this is the point where you need to read up about Complex numbers, Iteration, z=z^2+c and the FOIL method. (I thought all numbers are imaginary until you write them down!) Using the FOIL method we multiply the complex numbers and add the constant(x1 and y). To make it easy to follow I have not simplified it. (a*a)+((bi*bi)*-1)+x1 and (a*bi)+(bi*a)+y The equation can be simplified to:- atemp=(a*a)-(bi*bi)+x1 bi=2*(a*bi)+y */ while (i