/* © Conor McCarthy 2001..... except for the bits which I didn't write.... This program takes numbers from the complex plane and uses them as an initial estimate for finding the cubed root of 1 using the Newton Raphson method. It draws a different colored dot on the screen depending on which of the 4 roots it tends to. The source code is in a bit of a mess, I'm sure many parts of it aren't needed. Feel free to mess around with it. If you think you have made an improvement to it(admittedly not hard), please send me a copy. If you have any questions about the code(or anything) please email me: flibble@esatclear.ie. http://www.esatclear.ie/~flibble/chaos/index.html */ #include #include #include #include #include #include /* Constants */ #define BallWidth 1 // Size of dot #define BallHeight 1 #define BobSize 9 // Text size - of coords #define EDGE1 0 //gap of window to left/right of screen #define EDGE2 0 //gap of window to top/bottom of screen #define ACCURACY 100 // number of iteraiions to decide if inside Mandlebrot set long int newLeft=512, //starting point x newTop=384, //starting point y count2=0; complex one, // variable used in Equation iterations two, // variable used in Equation iterations number, // number of which to find the cubed root num4, // = (4,0) - used in eq ComplexnumberA,ComplexnumberB,ComplexnumberC,ComplexnumberD; // A is used, = (1,0). others temps long double incrementRe, // amount the real part is incremented each time incrementIm, // amount the imag part is incremented each time SrealInit=-2, SimagInit=-2, SrealFinal=2, SimagFinal=2, Sreal, Simag, Attractor = 5, XvalueCount=0, // array num YvalueCount=0, // array num Xvalue[2000], // X Screen coords -> real values Yvalue[2000]; // Y Screen coords -> imag values int colcounter=0, // color darkness - counts iteritions before an attractor is found textcounterX=1, // used for writing coords textcounterY=1; // used for writing coords typedef complex dcomp; /* Globals */ Rect windRect; // Some global variables WindowPtr gWindowPtr; RGBColor gWhiteColour = { 0xFFFF, 0xFFFF, 0xFFFF }; RGBColor gBlackColour = { 0x0000, 0x0000, 0x0000 }; RGBColor gRedColour = { 0xAAAA, 0x0000, 0x0000 }; RGBColor gRedColourD1 = { 0x7777, 0x0000, 0x0000 }; RGBColor gRedColourB1 = { 0xFFFF, 0x0000, 0x0000 }; RGBColor gYellowColour = { 0xFFFF, 0xCCCC, 0x0000 }; RGBColor gGreenColour = { 0x0000, 0x9999, 0x0000 }; RGBColor gBlueColour = { 0x6666, 0x6666, 0x9999 }; /* Prototypes */ void Initialize(void); void ColorBG(void); void Equation(void); float OutPix(float Attractor); void Completed(void); float TextX(float Sreal, float Simag); // to bring cr and ci to TextX and write the coords on screen float TextY(float Sreal, float Simag); // to bring cr and ci to TextY and write the coords on screen void Grid(void); // draw grid on screen void ResetValues(void); // resets some values to initial states before next magnification void escape (void); void comm (void); void MouseExit(void); void MouseCont(void); void RubberBand(void); void endofprogramcredits(void); Point p; void main(void) { ResetValues(); Initialize(); ColorBG(); Equation(); do { EventRecord event; WaitNextEvent(everyEvent, &event, 30,0); }while(!Button()); RubberBand(); do { EventRecord event; WaitNextEvent(everyEvent, &event, 30,0); }while(Button()); } // // Initialize everything for the program, make sure we can run // //MW specified argument and return type. void Initialize(void) { WindowPtr mainPtr; OSErr error; SysEnvRec theWorld; // // Test the computer to be sure we can do color. // If not we would crash, which would be bad. // If we canąt run, just beep and exit. // error = SysEnvirons(1, &theWorld); if (theWorld.hasColorQD == false) { SysBeep(50); ExitToShell(); /* If no color QD, we must leave. */ } /* Initialize all the needed managers. */ InitGraf(&qd.thePort); InitFonts(); InitWindows(); InitMenus(); TEInit(); InitDialogs(nil); InitCursor(); GetDateTime((unsigned long*) &qd.randSeed); // Make a new window for drawing in, and it must be a color window. // The window is full screen size, made smaller to make it more visible. windRect = qd.screenBits.bounds; InsetRect(&windRect, EDGE1, EDGE2); mainPtr = NewCWindow(nil, &windRect, "\pNewtRaph^4 v2", true, documentProc, (WindowPtr) -1, false, 0); SetPort(mainPtr); /* set window to current graf port */ TextSize(BobSize); /* smaller font for drawing. */ } void Equation(void) { long double tempnum = 0.000000000008; newLeft = 70; newTop = 50; Sreal = SrealInit; // starting point Real X axis Simag = SimagInit; // starting point Imag Y axis incrementRe = (-(SrealInit - SrealFinal)/(920/1));//**change this number to change the size of the picture // numericial increment for each calculation Real axis - ending point incrementIm = (-(SimagInit - SimagFinal)/(714/1));//**change this number to change the size of the picture // numericial increment for each calculation Imaginary axis - ending point num4 = dcomp(4,0); number = 1; // number to find cubed root of one = dcomp(Sreal,Simag); // starting point ComplexnumberA = dcomp(1,0); ComplexnumberB = dcomp(0,-1); ComplexnumberC = dcomp(-1,0); ComplexnumberD = dcomp(0.47177589515418,-0.47177589515418); do { do { one = dcomp(Sreal,Simag); do { colcounter++; // counts iterations before loop is broken - color depth two = (one -(((one*one*one*one) - number) / (num4*(one*one*one)))); // eq for X^4 - number = 0 one = two; if ( (two == ComplexnumberA) ) {Attractor = 1; count2=ACCURACY;} // Attractor = 1 for (1,0) if ( (two == ComplexnumberB) ) {Attractor = 2; count2=ACCURACY;} // Attractor = 2 for (0,-1) if ( (two == ComplexnumberC) ) {Attractor = 3; count2=ACCURACY;} // Attractor = 3 for (-1,0) if ( (two.imag() < -0.471775894) && (two.imag() > -0.471775896) ) {Attractor = 4; count2=ACCURACY;} // Attractor = 4 for (-0.5, -0.866...) count2++; if (count2>=ACCURACY){break;} //MouseExit(); }while (1==1); count2 = 0; Sreal = Sreal + incrementRe; // Increment for real part for next calc textcounterX++; Xvalue[newLeft] = Sreal; Yvalue[newTop] = Simag; if (Button()) { RubberBand(); main(); } if (((textcounterX%150==0) && (textcounterX < 1000)) | (textcounterX == 2)) // Calls TextX() to draw X values { //TextX(Sreal, Simag); } newLeft++; OutPix(Attractor); }while ( (Sreal < SrealFinal) && (!Button()) ); Sreal = SrealInit; newLeft = 70; Simag = Simag + incrementIm; // Increment for real part for next calc newTop++; textcounterY++; // increment Y counter - to write Y coords if ((textcounterY%12==0)) // Calls TextY() to draw Y values { TextY(Sreal, Simag); } } while (Simag < SimagFinal); Completed(); } float OutPix(float Attractor) { RGBColor ballColor; Rect ballRect; if (Attractor == 1) { ballColor.red = (0xFFFF*3000*colcounter); ballColor.green = (0xFFFF*3000*colcounter); ballColor.blue = (0); } if (Attractor == 2) { ballColor.red = (0xFFFF*3000*colcounter); ballColor.green = (0); ballColor.blue = (0xFFFF*3000*colcounter); } if (Attractor == 3) { ballColor.red = (0); ballColor.green = (0xFFFF*3000*colcounter); ballColor.blue = (0xFFFF*3000*colcounter); } if (Attractor == 4) { ballColor.red = (0xFFFF*3000*colcounter); ballColor.green = (0); ballColor.blue = (0); } if (Attractor == 5) { ballColor.red = (0); ballColor.green = (0); ballColor.blue = (0); } RGBForeColor (&ballColor); SetRect(&ballRect, newLeft, newTop, newLeft+BallWidth, newTop+BallHeight); MoveTo(newLeft, newTop); PaintOval (&ballRect); colcounter=0; if ((newTop==60)&&(newLeft == 100)) { comm(); } } void ColorBG(void) { RGBColor ballColor; Rect ballRect; long int newLeft, newTop; // // Make a random new color for the ball. // ballColor.red = 1; ballColor.green = 1; ballColor.blue = 1; // // Set that color as the new color to use in drawing. // RGBForeColor (&ballColor); // // Make a Random new location for the ball, that is normalized to the window size. // This makes the Integer from Random into a number that is 0..windRect.bottom // and 0..windRect.right. They are normalized so that we don't spend most of our // time drawing in places outside of the window. // // newTop = Random(); newLeft = Random(); // newTop = ((newTop+32767) * windRect.bottom)/65536; // newLeft = (((newLeft+32767) * windRect.right)/65536)-50; SetRect(&ballRect, -200, -200, 1200, 1000); // // Move pen to the new location, and paint the colored ball. // // MoveTo(100, 100); PaintOval (&ballRect); // // Move the pen to the middle of the new ball position, for the text // MoveTo(ballRect.left + BallWidth/2 - BobSize, ballRect.top + BallHeight/2 + BobSize/2 -1); } // Write X value along top of screen float TextX(float Sreal, float Simag) // takes cr and ci from NewBall { MoveTo(newLeft, newTop - 3); char Xchar[5]; RGBColor ballColor; Rect ballRect; ballColor.red = 0xFFFF;//Random(); ballColor.green = 0;//Random(); ballColor.blue = 0;//Random(); sprintf(Xchar,"%.5f",Sreal); // int to char InvertColor(&ballColor); RGBForeColor(&ballColor); DrawText(Xchar,short (0),short (7)); } // Write Y value along side of screen float TextY(float Sreal, float Simag) // takes cr and ci from NewBall { TextSize(BobSize); MoveTo(newLeft-65, newTop); char Xchar[8],Ychar[8]; RGBColor ballColor; Rect ballRect; ballColor.red = 0xFFFF;//Random(); ballColor.green = 0;//Random(); ballColor.blue = 0;//Random(); sprintf(Ychar,"%.7fi",Simag); // int to char InvertColor(&ballColor); RGBForeColor(&ballColor); DrawText(Ychar,short (0),short (11)); } void Grid(void) { int x=55,y=55; // coords used for lines RGBColor ballColor; Rect ballRect; ballColor.red = 0; ballColor.green = 0xFFFF; ballColor.blue = 0xFFFF; RGBForeColor (&ballColor); do{ MoveTo(x+20,y); LineTo(x+20,1000); x = x + 20; }while(x<1100); x=55; do{ MoveTo(x,y+20); LineTo(1100,y+20); y = y + 20; }while (y<800); } void Completed(void) { RGBColor ballColor; Rect ballRect; ballColor.red = Random(); ballColor.green = Random(); ballColor.blue = Random(); TextSize(14); SetRect(&ballRect, 5, 35, 80, 80); MoveTo(ballRect.left, ballRect.top); // // Invert the color and draw the text there. This wonąt look quite right in 1 bit // mode, since the foreground and background colors will be the same. // Color QuickDraw special cases this to not invert the color, to avoid // invisible drawing. // // InvertColor(&ballColor); RGBForeColor(&ballColor); DrawString("\p Finished"); //DrawText(const void *textBuf,short firstByte,short byteCount); //DrawString("\pBob"); comm(); escape(); } void ResetValues(void) { newLeft = 70; newTop = 50; textcounterY = 0; textcounterX = 0; count2=0; XvalueCount=0; // array num YvalueCount=0; // array num } void RubberBand(void) { escape(); long double SRItmp,SIItmp; // temp varbs - make sure srealfinal > sreal init etc do { PixPatHandle pixpatHdl=0; Point initialMouse, previousMouse, currentMouse; Rect drawRect; UInt16 randomNumber; RGBBackColor(&gWhiteColour); FillRect(&gWindowPtr->portRect,&qd.white); PenPixPat(pixpatHdl); PenSize(2,2); PenMode(patXor); GetMouse(&initialMouse); drawRect.left = drawRect.right = initialMouse.h; drawRect.top = drawRect.bottom = initialMouse.v; SrealInit = Xvalue[initialMouse.h]; SimagInit = Yvalue[initialMouse.v]; GetMouse(&previousMouse); while(StillDown()) { GetMouse(¤tMouse); if(currentMouse.v != previousMouse.v || currentMouse.h != previousMouse.h) { FrameRect(&drawRect); if(currentMouse.h >= initialMouse.h) drawRect.right = currentMouse.h; if(currentMouse.v >= initialMouse.v) drawRect.bottom = currentMouse.v; if(currentMouse.h <= initialMouse.h) drawRect.left = currentMouse.h; if(currentMouse.v <= initialMouse.v) drawRect.top = currentMouse.v; FrameRect(&drawRect); } previousMouse.v = currentMouse.v; previousMouse.h = currentMouse.h; } FrameRect(&drawRect); //MouseExit(); EventRecord event; WaitNextEvent(everyEvent, &event, 30,0); SrealFinal = Xvalue[currentMouse.h]; SimagFinal = Yvalue[currentMouse.v]; if(SrealInit>SrealFinal) { SRItmp = SrealInit; SrealInit = SrealFinal; SrealFinal = SRItmp; } if(SimagInit>SimagFinal) { SIItmp = SimagInit; SimagInit = SimagFinal; SimagFinal = SIItmp; } }while(Button()); main(); } void MouseExit(void) // quits program is p.h = 0 { GetMouse (&p); GlobalToLocal(&p); if (p.h == 0){ExitToShell();} } void comm(void) { RGBColor ballColor; Rect ballRect; RGBForeColor (&gRedColourD1); SetRect(&ballRect, windRect.right-200+2-EDGE1, windRect.bottom-100+2-EDGE1, windRect.right-50+2-EDGE2,windRect.bottom-70+2-EDGE2); PaintRect (&ballRect); RGBForeColor (&gRedColourB1); SetRect(&ballRect, windRect.right-200-EDGE1, windRect.bottom-100-EDGE1, windRect.right-50-EDGE2,windRect.bottom-70-EDGE2); PaintRect (&ballRect); TextFace(bold); TextSize(14); RGBForeColor (&gBlackColour); MoveTo(windRect.right-197-EDGE1, windRect.bottom - 80-EDGE2); DrawString("\pClick here to quit"); TextFace(normal); } void escape (void) { int time; GetMouse (&p); //GlobalToLocal(&p); if ((p.h > windRect.right-200-EDGE1)&&(p.h < windRect.right-50-EDGE1) && (p.v > windRect.bottom-100-EDGE2)&&(p.v