// File: mandelbrot-16.cxx // Written by: Michael and Dmitry // This is a start on a program to draw Mandelbrot's fractal. //---------------------------------------------------------------------------- #include // All the graphics functions #include // In case I want to debug with cout using namespace std; //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- const int S = 400; // Size of a square graphics window //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Function prototypes // double distance(double x0, double y0, double x1, double y1); // Returns the distance between (x0, y0) and (x1, y1) double distance(double x0, double y0, double x1, double y1); // draw_fractal will draw a portion of Mandelbrot's fractal centered on // (midx, midy) with the specified width and height. void draw_fractal(double midx, double midy, double width, double height); // int mandelbrot_color(double wx, double wy); // Compute the number of jumps that are required to leave the circle of radius // 2 that is centered around the origin when we: // -- start at location (wx, wy) // -- jump to a new location according to Mandelbrot's equations // If we hit the LIMIT (declared as a constant) without leaving the circle, // then we just return the number LIMIT rather than continuing to jump! int mandelbrot_color(double wx, double wy); // The shift_mid function checks whether there has been a left mouse // click. If so, then the location of that click is calculated // in world coordinates, and (midx, midy) is moved to that spot. void shift_mid(double& midx, double& midy, double width, double height); // This function waits until there is a left mouse click or keyboard hit. void wait_for_input( ); // world(p, v0, v1, pmax) converts p from an interval that ranges from 0 to // pmax into a double number interval that ranges from v0 to v1. double world(int p, double v0, double v1, int pmax); // The zoom function checks whether the + or - key has been pressed. // If so, then the width and height are cut in half (for the + key) or // doubled (for the - key). void zoom(double& width, double& height); //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- int main() { double midx, midy, width, height; // To define world coordinates // Open a graphics window and set the initial world coordinates: initwindow(S, S, "Mandelbrot's Fractal"); midx = midy = 0.0; width = height = 4.0; // Fill each pixel with a color that depends on Mandelbrot's fractal. for (;;) { // Draw the current fractal draw_fractal(midx, midy, width, height); // Wait for some input: wait_for_input( ); // Process the input: shift_mid(midx, midy, width, height); zoom(width, height); } delay(200000); return EXIT_SUCCESS; } //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- double distance(double x0, double y0, double x1, double y1) { double dx = x1 - x0; double dy = y1 - y0; return sqrt(dx*dx + dy*dy); } //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- void draw_fractal(double midx, double midy, double width, double height) { int px, py; // Pixel coordinates on the screen double wx, wy; // world coordinates int color; // Color depends on px and py for (px = 0; px < S; ++px) { for (py = 0; py < S; ++py) { // convert px and py wx = world(px, midx - width/2, midx + width/2, S); wy = world(py, midy + height/2, midy - height/2, S); color = mandelbrot_color(wx, wy); // Draw the pixel with that color putpixel(px, py, color); } } } //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- int mandelbrot_color(double wx, double wy) { const int LIMIT = 15; // Maximum number of jumps const double sx = wx, sy = wy; // Where we started jumping double wx_new, wy_new; // The next spot to jump to int jumps = 0; // How many jumps we've taken while ((distance(wx, wy, 0, 0) < 2) && (jumps < LIMIT)) { wx_new = wx*wx - wy*wy + sx; wy_new = 2*wx*wy + sy; ++jumps; wx = wx_new; wy = wy_new; } return jumps; } //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- void shift_mid(double& midx, double& midy, double width, double height) { int px, py; if (ismouseclick(WM_LBUTTONDOWN)) { getmouseclick(WM_LBUTTONDOWN, px, py); midx = world(px, midx - width/2, midx + width/2, S); midy = world(py, midy + height/2, midy - height/2, S); } } //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- void wait_for_input( ) { while (!kbhit() && !ismouseclick(WM_LBUTTONDOWN)) { delay(100); } } //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- double world(int p, double v0, double v1, int pmax) { double fraction = double(p)/double(pmax); double distance_from_v0 = fraction*(v1 - v0); return v0 + distance_from_v0; } //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- void zoom(double& width, double& height) { char key; if (kbhit()) { key = getch(); if (key == '+') { width = width/2; height = height/2; } else if (key == '-') { width = width*2; height = height*2; } } } //----------------------------------------------------------------------------