// //+---------------------------------------------------------------+ //+ Program MAGNETS.CPP + //+ Plots 18 magnet-like fractals in the x-plane for different q. + //+ (16 for Model I, 2 for Model II) + //+ + //+ By: Fausto Arinos de Almeida Barbuto + //+ E-mail: BJ06@C53000.PETROBRAS.ANRJ.BR + //+ Rio de Janeiro, BRAZIL, April 4th 1994 + //+ + //+ Modified by: Michael Sargent + //+ E-mail: msargent@moose.uvm.edu + //+ Essex Junction, Vermont, USA, May 15, 1994 + //+ + //+ Needs SVGA256.H and SVGA256.BGI, supports up to four screens. + //+ + //+ REFERENCE: Peitgen, H.-O. and Richter, P.H. + //+ "The Beauty of Fractals" (Springer-Verlag 1986) + //+ pp. 129-37, 194. + //+---------------------------------------------------------------+ // #include #include "svga256.h" #include #include #include #include #include void introscreen(void); void userinput(void); void parameters(void); void calculate(void); void preliminary(void); void setVGApalette(char *buffer); //void far initgraph(int far *,int far *,char far *); // Global variables // double xmin, xmax, ymin, ymax, fact=1.0, dist, xmag, ymag, zmag, ypy, x, y, r, deltap, deltaq; int maxiter, Model, insidecolor=1, plotflag=0, npix, npiy, k, np, nq, npy, ipen, graphdriver=DETECT, graphmode, Vid, index; complex c, z, q, a, b, ab, z2, secondz; char palette[256][3]={ { 0, 0, 0},{ 0, 17, 45},{ 0, 18, 45},{ 0, 19, 44}, { 0, 20, 43},{ 0, 20, 42},{ 0, 21, 42},{ 0, 22, 41}, { 0, 22, 40},{ 0, 23, 40},{ 0, 24, 39},{ 0, 25, 38}, { 0, 25, 37},{ 0, 26, 37},{ 0, 27, 36},{ 0, 28, 35}, { 0, 28, 34},{ 0, 29, 34},{ 0, 30, 33},{ 0, 31, 32}, { 0, 31, 31},{ 0, 32, 31},{ 0, 33, 30},{ 0, 34, 29}, { 0, 34, 28},{ 0, 35, 28},{ 0, 36, 27},{ 0, 37, 26}, { 0, 37, 25},{ 0, 38, 25},{ 0, 39, 24},{ 0, 40, 23}, { 0, 40, 22},{ 0, 41, 22},{ 0, 42, 21},{ 0, 42, 20}, { 0, 43, 20},{ 0, 44, 19},{ 0, 45, 18},{ 0, 45, 17}, { 0, 46, 17},{ 0, 47, 16},{ 0, 48, 15},{ 0, 48, 14}, { 0, 49, 14},{ 0, 50, 13},{ 0, 51, 12},{ 0, 51, 11}, { 0, 52, 11},{ 0, 53, 10},{ 0, 54, 9},{ 0, 54, 8}, { 0, 55, 8},{ 0, 56, 7},{ 0, 57, 6},{ 0, 57, 5}, { 0, 58, 5},{ 0, 59, 4},{ 0, 60, 3},{ 0, 60, 2}, { 0, 61, 2},{ 0, 62, 1},{ 0, 63, 0},{ 0, 63, 0}, { 1, 62, 0},{ 2, 61, 0},{ 2, 60, 0},{ 3, 60, 0}, { 4, 59, 0},{ 5, 58, 0},{ 5, 57, 0},{ 6, 57, 0}, { 7, 56, 0},{ 8, 55, 0},{ 8, 54, 0},{ 9, 54, 0}, { 10, 53, 0},{ 11, 52, 0},{ 11, 51, 0},{ 12, 51, 0}, { 13, 50, 0},{ 14, 49, 0},{ 14, 48, 0},{ 15, 48, 0}, { 16, 47, 0},{ 17, 46, 0},{ 17, 45, 0},{ 18, 45, 0}, { 19, 44, 0},{ 20, 43, 0},{ 20, 42, 0},{ 21, 42, 0}, { 22, 41, 0},{ 22, 40, 0},{ 23, 40, 0},{ 24, 39, 0}, { 25, 38, 0},{ 25, 37, 0},{ 26, 37, 0},{ 27, 36, 0}, { 28, 35, 0},{ 28, 34, 0},{ 29, 34, 0},{ 30, 33, 0}, { 31, 32, 0},{ 31, 31, 0},{ 32, 31, 0},{ 33, 30, 0}, { 34, 29, 0},{ 34, 28, 0},{ 35, 28, 0},{ 36, 27, 0}, { 37, 26, 0},{ 37, 25, 0},{ 38, 25, 0},{ 39, 24, 0}, { 40, 23, 0},{ 40, 22, 0},{ 41, 22, 0},{ 42, 21, 0}, { 42, 20, 0},{ 43, 20, 0},{ 44, 19, 0},{ 45, 18, 0}, { 45, 17, 0},{ 46, 17, 0},{ 47, 16, 0},{ 48, 15, 0}, { 48, 14, 0},{ 49, 14, 0},{ 50, 13, 0},{ 51, 12, 0}, { 51, 11, 0},{ 52, 11, 0},{ 53, 10, 0},{ 54, 9, 0}, { 54, 8, 0},{ 55, 8, 0},{ 56, 7, 0},{ 57, 6, 0}, { 57, 5, 0},{ 58, 5, 0},{ 59, 4, 0},{ 60, 3, 0}, { 60, 2, 0},{ 61, 2, 0},{ 62, 1, 0},{ 63, 0, 0}, { 63, 0, 0},{ 62, 0, 1},{ 61, 0, 2},{ 60, 0, 2}, { 60, 0, 3},{ 59, 0, 4},{ 58, 0, 5},{ 57, 0, 5}, { 57, 0, 6},{ 56, 0, 7},{ 55, 0, 8},{ 54, 0, 8}, { 54, 0, 9},{ 53, 0, 10},{ 52, 0, 11},{ 51, 0, 11}, { 51, 0, 12},{ 50, 0, 13},{ 49, 0, 14},{ 48, 0, 14}, { 48, 0, 15},{ 47, 0, 16},{ 46, 0, 17},{ 45, 0, 17}, { 45, 0, 18},{ 44, 0, 19},{ 43, 0, 20},{ 42, 0, 20}, { 42, 0, 21},{ 41, 0, 22},{ 40, 0, 22},{ 40, 0, 23}, { 39, 0, 24},{ 38, 0, 25},{ 37, 0, 25},{ 37, 0, 26}, { 36, 0, 27},{ 35, 0, 28},{ 34, 0, 28},{ 34, 0, 29}, { 33, 0, 30},{ 32, 0, 31},{ 31, 0, 31},{ 31, 0, 32}, { 30, 0, 33},{ 29, 0, 34},{ 28, 0, 34},{ 28, 0, 35}, { 27, 0, 36},{ 26, 0, 37},{ 25, 0, 37},{ 25, 0, 38}, { 24, 0, 39},{ 23, 0, 40},{ 22, 0, 40},{ 22, 0, 41}, { 21, 0, 42},{ 20, 0, 42},{ 20, 0, 43},{ 19, 0, 44}, { 18, 0, 45},{ 17, 0, 45},{ 17, 0, 46},{ 16, 0, 47}, { 15, 0, 48},{ 14, 0, 48},{ 14, 0, 49},{ 13, 0, 50}, { 12, 0, 51},{ 11, 0, 51},{ 11, 0, 52},{ 10, 0, 53}, { 9, 0, 54},{ 8, 0, 54},{ 8, 0, 55},{ 7, 0, 56}, { 6, 0, 57},{ 5, 0, 57},{ 5, 0, 58},{ 4, 0, 59}, { 3, 0, 60},{ 2, 0, 60},{ 2, 0, 61},{ 1, 0, 62}, { 0, 0, 63},{ 0, 0, 63},{ 0, 1, 62},{ 0, 2, 61}, { 0, 2, 60},{ 0, 3, 60},{ 0, 4, 59},{ 0, 5, 58}, { 0, 5, 57},{ 0, 6, 57},{ 0, 7, 56},{ 0, 8, 55}, { 0, 8, 54},{ 0, 9, 54},{ 0, 10, 53},{ 0, 11, 52}, { 0, 11, 51},{ 0, 12, 51},{ 0, 13, 50},{ 0, 14, 49}, { 0, 14, 48},{ 0, 15, 48},{ 0, 16, 47},{ 0, 17, 46} }; //=========================================================================== // Convoluted BGI stuff //=========================================================================== int huge DetectVGA256() { int mistake; char key; printf("\n\n Which video mode would you like to use? \n\n"); printf(" a: 640x400x256\n"); printf(" b: 640x480x256\n"); printf(" c: 800x600x256\n"); printf(" d: 1024x768x256\n\n"); printf(" > "); do { mistake = 0; key = getch(); Vid = ("%d",key) - 96; if (Vid < 1 || Vid > 4) { mistake = 1; printf("%c%c%c",7,7,7); gotoxy(25,10); printf(" "); gotoxy(25,10); } } while(mistake == 1); printf("%c",key); delay(500); return Vid; } //=========================================================================== // Main //=========================================================================== void main() { introscreen(); userinput(); parameters(); cleardevice(); setVGApalette(palette[0]); calculate(); closegraph(); } //=========================================================================== // Introduction & BOF credits //=========================================================================== void introscreen(void) { clrscr(); _setcursortype(_NOCURSOR); gotoxy(31,4); printf("MAGNET-LIKE MODELS"); gotoxy(15,6); printf("Reference: Peitgen, H.-O., and Richter, P.H."); gotoxy(15,7); printf("The Beauty of Fractals (Springer-Verlag 1986) pp. 129-37, 194"); gotoxy(15,9); printf("By Fausto A. A. Barbuto, April 4, 1994"); gotoxy(15,10); printf("E-mail: BJ06@C53000.PETROBRAS.ANRJ.BR"); gotoxy(15,12); printf("Modifications by Michael Sargent, May 15, 1994"); gotoxy(15,13); printf("E-mail: msargent@moose.uvm.edu\n\n\n"); getch(); } //=========================================================================== // Obtain input - who said user-proofing was fun? //=========================================================================== void userinput(void) { int i, mistake, status; char key; clrscr(); _setcursortype(_NORMALCURSOR); printf("\n\n SELECT A MODEL TYPE: \n\n\n"); printf(" %c (z%c + q - 1) %c%c\n",218,253,191,253); cprintf(" a: Model I: z %c",26); gotoxy(31,7); printf("%c ",179); for (i=0;i<12;i++) putchar(196); printf(" %c\n",179); printf(" %c (2z + q - 2) %c\n\n\n",192,217); printf(" %c (z^3 + 3az + ab) %c%c\n",218,191,253); cprintf(" b: Model II: z %c",26); gotoxy(25,12); printf("%c ",179); for (i=0;i<25;i++) putchar(196); printf(" %c\n",179); printf(" %c (3z%c + 3bz + q%c - 3q + 3) %c\n\n",192,253,253,217); printf(" (where a = q-1 and b = q-2) \n\n\n > "); do { mistake = 0; key = getch(); Model = ("%d",key) - 96; if (Model < 1 || Model > 2) { mistake = 1; printf("%c%c%c",7,7,7); gotoxy(8,18); printf(" "); gotoxy(8,18); } } while(mistake == 1); printf("%c",key); delay(500); clrscr(); if (Model == 1) { printf("\n Model I: Select a formulation: \n\n\n"); printf(" a: q = -1.0 -6<=Re(z)<=4 -5<=Im(z)<=5 [Fig. 53a]\n"); printf(" b: q = -0.1 -6<=Re(z)<=4 -5<=Im(z)<=5 [Fig. 53b]\n"); printf(" c: q = 0.0 -6<=Re(z)<=4 -5<=Im(z)<=5 [Fig. 53c]\n"); printf(" d: q = 1.0 -5<=Re(z)<=5 -5<=Im(z)<=5 [Fig. 53d]\n"); printf(" e: q = 1.2 -5<=Re(z)<=5 -5<=Im(z)<=5 [Fig. 53e]\n"); printf(" f: q = 1.6 -5<=Re(z)<=5 -5<=Im(z)<=5 [Fig. 53f]\n"); printf(" g: q = 2.0 -5<=Re(z)<=5 -5<=Im(z)<=5 [Fig. 53g]\n"); printf(" h: q = 2.5 -5<=Re(z)<=5 -5<=Im(z)<=5 [Fig. 53h]\n"); printf(" i: q = 2.9 -5<=Re(z)<=5 -5<=Im(z)<=5 [Fig. 53i]\n"); printf(" j: q = 3.0 -5<=Re(z)<=5 -5<=Im(z)<=5 [Fig. 53j]\n"); printf(" k: q = 3.1 -5<=Re(z)<=5 -5<=Im(z)<=5 [Fig. 53k]\n"); printf(" l: q = 4.0 -4<=Re(z)<=6 -5<=Im(z)<=5 [Fig. 53l]\n"); printf(" m: q = 4.0 -5.5<=Re(z)<=7.9 -5<=Im(z)<=5 [Map 3]\n"); printf(" n: q = -0.1 0.8<=Re(z)<=2.0 2.635<=Im(z)<=3.535 [Map 4]\n"); printf(" o: q=~1.1+2.07i -0.5<=Re(z)<=1.5 -1.45<=Im(z)<=0.7 [Map 5]\n"); printf(" p: q=1.21+0.01i -2.1<=Re(z)<=-0.3 -0.5<=Im(z)<=0.5625 [Map 6]"); printf("\n\n > "); do { mistake = 0; key = getch(); index = ("%d",key) - 96; if (index < 1 || index > 16) { mistake = 1; printf("%c%c%c",7,7,7); gotoxy(6,22); printf(" "); gotoxy(6,22); } } while(mistake == 1); printf("%c",key); delay(500); } else if (Model == 2) { printf("\n\n Model II: Select a formulation: \n\n\n"); printf(" a: q = 2.0 -15<=Re(z)<=15 -11<=Im(z)<=11 [Map 7]\n"); printf(" b: q = 1.2+2i -3.2<=Re(z)<=3.8 -3.3<=Im(z)<=1.9 [Map 8-10]\n\n > "); do { mistake = 0; key = getch(); index = ("%d",key) - 96; if (index < 1 || index > 2) { mistake = 1; printf("%c%c%c",7,7,7); gotoxy(6,9); printf(" "); gotoxy(6,9); } } while(mistake == 1); printf("%c",key); delay(500); } clrscr(); printf("\n\n Enter number of iterations:\n\n"); printf(" a: 16\n"); printf(" b: 64\n"); printf(" c: 128\n"); printf(" d: 256\n"); printf(" e: 512\n\n"); printf(" > "); do { mistake = 0; key = getch(); maxiter = ("%d",key) - 96; if (maxiter < 1 || maxiter > 5) { mistake = 1; printf("%c%c%c",7,7,7); gotoxy(25,11); printf(" "); gotoxy(25,11); } } while(mistake == 1); printf("%c",key); delay(500); if (maxiter == 1) maxiter = 16; if (maxiter == 2) maxiter = 64; if (maxiter == 3) maxiter = 128; if (maxiter == 4) maxiter = 256; if (maxiter == 5) maxiter = 512; if (Model == 1) { printf("\n\n Select an inside-coloring scheme:\n"); printf("\n a: Standard target set method for finite attractor"); printf("\n b: Alternate subtle gradient scheme\n\n"); printf(" > "); do { mistake = 0; key = getch(); insidecolor = ("%d",key) - 96; if (insidecolor < 1 || insidecolor > 2) { mistake = 1; printf("%c%c%c",7,7,7); gotoxy(25,18); printf(" "); gotoxy(25,18); } } while(mistake == 1); printf("%c",key); delay(500); } clrscr(); installuserdriver("Svga256",DetectVGA256); // // Change the directory below to fit your own .BGI requirements. // initgraph(&graphdriver, &graphmode, "C:\\BORLANDC\\BGI"); } //=========================================================================== // Initialize parameters //=========================================================================== void parameters(void) { if (Vid == 1) { npix = 640; npiy = 400;} if (Vid == 2) { npix = 640; npiy = 480;} if (Vid == 3) { npix = 800; npiy = 600;} if (Vid == 4) { npix =1024; npiy = 768;} // // Defaults for the plotting window. // xmin = -5.0; xmax = 5.0; ymin = -5.0; ymax = 5.0; if (Model == 1) { if (index == 1) {xmin=-6.0, xmax=4.0; q=complex(-1.0,0.0);} else if (index == 2) {xmin=-6.0, xmax=4.0; q=complex(-0.1,0.0);} else if (index == 3) {xmin=-6.0, xmax=4.0; q=complex(0.0,0.0);} else if (index == 4) q=complex(1.0,0.0); else if (index == 5) q=complex(1.2,0.0); else if (index == 6) q=complex(1.6,0.0); else if (index == 7) q=complex(2.0,0.0); else if (index == 8) q=complex(2.5,0.0); else if (index == 9) q=complex(2.9,0.0); else if (index ==10) q=complex(3.0,0.0); else if (index ==11) q=complex(3.1,0.0); else if (index ==12) {xmin=-4.0, xmax=6.0; q=complex(4.0,0.0);} else if (index ==13) {xmin=-5.5, xmax=7.9; q=complex(4.0,0.0);} else if (index ==14) {xmin=0.8, xmax=2.0; ymin=2.635; ymax=3.535; q=complex(-0.1,0.0);} else if (index ==15) {xmin=-0.5, xmax=1.5; ymin=-1.45; ymax=0.7; q=complex(1.09582,2.07142);} else if (index ==16) {xmin=-2.1, xmax=-0.3; ymin=-0.5; ymax=0.5625; q=complex(1.21,0.01);} else {q=complex(1.2,0.0);} } else if (Model == 2) { if (index ==1) {xmin=-15.0, xmax=15.0; ymin=-11.0; ymax=11.0; q=complex(2.0,0.0);} else if (index ==2) {xmin=-3.2, xmax=3.8; ymin=-3.3; ymax=1.9; q=complex(1.20,2.0);} else {xmin=-3.2, xmax=3.8; ymin=-3.3; ymax=1.9; q=complex(1.20,2.0);} } if(fact>=1.0 || fact <=0.0) fact = 1.0; else { npix = (int)(npix*fact); npiy = (int)(npiy*fact); } ypy = (double)npiy - 0.5; deltap = (xmax-xmin)/(npix-1); deltaq = (ymax-ymin)/(npiy-1); if(ymin==-ymax) npy = npiy/2; else npy = npiy; } //=========================================================================== // Do the calculations //=========================================================================== void calculate(void) { for (np=0; np<=npix-1; np++) { x = xmin + (double)np*deltap; for (nq=0; nq<=npy-1; nq++) { y = ymin + (double)nq*deltaq; k = 0; z = complex(x,y); // - - - Standard target set coloring scheme - - - - - - - - - - - - - - - if (insidecolor==1) { do { preliminary(); // // Points which escape towards infinity. // if (r >= maxiter) { ipen = ((5 * k)%255) + 1; if (ymin == -ymax) { putpixel(np,nq,ipen); putpixel(np,npiy-nq-1,ipen); } else putpixel(np,nq,ipen); } // // Points converging to (1,0). // else if (zmag<0.00001) { ipen = ((k << 2)%100) + 156; plotflag = 1; } // // Points converging to (0,0) (for Model 2). // else if (r<0.00001) { ipen = ((k << 2)%50)+206; plotflag = 1; } // // Any leftover points. // else if (k == maxiter) { ipen = ((k << 2)%100) + 156; plotflag = 1; } if (plotflag) { if (ymin == -ymax) { ypy = double(npiy) - nq - 0.5; putpixel(np,ypy,ipen); putpixel(np,nq,ipen); } else putpixel(np,nq,ipen); plotflag = 0; } } while (r<=maxiter && k=0.00001 && r>=0.00001); } // - - - Alternative inside-coloring scheme - - - - - - - - - - - - - - - - if (insidecolor==2) { do { preliminary(); if (k == 2) secondz = z; // // Points which escape towards infinity. // if (r >= maxiter) { ipen = ((5 * k)%255) + 1; if (ymin == -ymax) { putpixel(np,nq,ipen); putpixel(np,npiy-nq-1,ipen); } else putpixel(np,nq,ipen); } // // Converging points. // if (k == maxiter) { xmag = real(secondz) - 1; ymag = imag(secondz); zmag = sqrt(xmag * xmag + ymag * ymag); ipen = ((int)(16 * zmag)%86)+170; if (ymin == -ymax) { ypy = double(npiy) - nq - 0.5; putpixel(np,ypy,ipen); putpixel(np,nq,ipen); } else putpixel(np,nq,ipen); } } while (r <= maxiter && k<=maxiter); } // - - - End of inside coloring routines - - - - - - - - - - - - - - - - - } if(kbhit()) break; } getch(); } //========================================================================== // Preliminary calculations before plotting colors //========================================================================== void preliminary(void) { // Definition for Model I magnets. // if (Model == 1) z = (z*z + q - 1.0)/(2.0*z + q - 2.0); // // Definition for Model II magnets. // else if (Model == 2) { a = q - 1.0; b = q - 2.0; ab = a*b; z2 = z*z; z = (z*z2 + 3.0*a*z + ab)/(3.0*z2 + 3.0*b*z + ab + 1.0); } z = z*z; r = abs(z); xmag = real(z) - 1; ymag = imag(z); zmag = sqrt(xmag * xmag + ymag * ymag); k++; } //========================================================================== // Function to set all 256 color registers //========================================================================== #pragma warn -eff void setVGApalette(char *buffer) { int i, j; for (i=0;i<256;i++) { outp(0x3c8, i); for (j=0;j<3;j++) outp(0x3c9, *buffer++); } } #pragma warn +eff