Introduction
This simple application demonstrates how to create a simple realtime Mandelbrot zoom in a Win32 Console with Visual C++ 6.0. But before we begin, let's talk about complex numbers and the mathematics of the Mandelbrot set.
Complex Numbers
A complex number is a number consisting of a real and imaginary part and can be written in the form Z = X + iY
, where X
and Y
are real numbers, and i
is the standard imaginary unit with the property i<sup>2</sup> = -1
. The complex numbers contain the ordinary real numbers, but extend them by introducing i
, extra imaginary numbers.
Conformal Mapping
A conformal map is a function which preserves angles when transformations to a specific coordinate system are being made. Conformal maps preserve both angles and the shapes of infinitesimally small figures, but not necessarily their size. In the most common case, the function is between domains in the complex plane which brings us to the Mandelbrot set. We will map our Mandelbrot with conformal mapping on to a 2D coordinate system.
A rectangular grid function f (left) and its image under a conformal map function f (right).
It is seen that function f maps pairs of lines intersecting at 90° to pairs of curves still intersecting at 90°.
The Mandelbrot Set
In mathematics, the Mandelbrot set is a set of points in the complex plane the boundary of which forms a fractal. When computed and graphed on the complex plane, the Mandelbrot set is seen to have an elaborate boundary which does not simplify at any given magnification.
The area of the Mandelbrot set can be written exactly as:
where bn are the coefficients of the Laurent series about infinity of the conformal map of the exterior of the unit disk onto the exterior of the Mandelbrot set. Furthermore, the Mandelbrot sets are defined as a set of complex values of C
for which the orbit of 0
under iteration of the complex quadratic polynomial z<sub>n+1</sub> = Z<sup>2</sup><sub>n</sub> + C
remains bounded. For instance, a complex number, c
, is in the Mandelbrot set if, when starting with Z<sub>0</sub> = 0
and applying the iteration repeatedly, the absolute value of Z<sub>n</sub>
never exceeds a certain number, no matter how large n
gets.
To create a fractal, we have to find many numbers that are part of the Mandelbrot set.
To do this, we need a test that will determine if a given number is inside the Mandelbrot set or outside the set. The test is based on the equation z<sub>n+1</sub> = Z<sup>2</sup><sub>n</sub> + C.
C here represents a constant number, meaning that it does not change during the testing process and we're not really interested in the actual value of Z as it changes, we just look at its magnitude or its distance from zero and then we will set the color based on that magnitude and plot it on to a 2D coordinate system using conformal mapping.
How the Mandelbrot Zoom Works
- First we set the boundary values from which to calculate the Mandelbrot set.
- Then after that, we set initial values and calculate, and we set a color based on the magnitudes calculated from the Mandelbrot set and map it on to a 2D coordinate system using conformal mapping.
- After that step, we repetitively calculate and animate in realtime at 60 frames per second.
- That's it, we are done.
Class CMandelzoom
We begin as usual by creating project and a class. We name the class CMandelzoom
, then we continue further on by embodying the class with class members.
But we choose not to define and embody our member functions in the header file CMandelzoom.h, we will just put the function or method prototyes in CMandelzoom.h.The embodiment of the member functions will be done in CMandelzoom.cpp.
The Visual C++ 6.0 project files are:
CMandelzoom_main.cpp
| The main file |
CMandelzoom.cpp
| The class definition and method body file |
CMandelzoom.h
| The class declaration file |
CTextMode.h
| The Console textmode graphics class |
Our class CMandelzoom
inherits function methods from the class CTextMode
so we need to include this syntax:
CMandelzoom::CMandelzoom( int i) : CTextMode()
Now after the inheritance the function, methods in CTextMode.h have become "one" with
the function methods in our class CMandelzoom
. We can now treat those methods as if they were native to CMandelzoom
.
We have also placed function calls we want to be initialized at start up in the constructor
so that when our class is being instantized, those function methods get called and executed.
The initFractal() Method
The initFractal()
method sets the boundary from which to calculate the Mandelbrot set.
void CMandelzoom::initFractal(double x0,double y0,double x1,double y1)
{
xx++;
zoomcount =zoomcount+1;
xmin =x0;
ymin =y0;
xmax =x1;
ymax =y1;
zxmin =xmin-(0.0012)/1.666666;
zymin =ymin;
zxmax =xmax-(0.0012)/1.666666;
zymax =ymax;
if(zoomcount>150)
{
zoomcount=0;
xzoomfactor=-xzoomfactor;
yzoomfactor=-yzoomfactor;
xmin =-xmin;
ymin =-ymin;
xmax =-xmax;
ymax =-ymax;
}
}
The putpixel() Method
The putpixel()
method plots a single point onto the console window.
void CMandelzoom::putpixel (unsigned int x, unsigned int y, unsigned char c)
{
txtPlot(x,y,c);
}
The getFractalColor() Method
The getFractalColor()
method returns a color based on the magnitudes calculated from the Mandelbrot set.
int CMandelzoom::getFractalColor(int x,int y)
{
double p,q,r,i,prev_r,prev_i;
int n;
p =(x*widthfactor)+xmin;
q =(y*heightfactor)+ymin;
prev_i =0;
prev_r =0;
for (n=0;n<=numcolors;n++)
{
r =(prev_r*prev_r)-(prev_i*prev_i)+p;
i =2*(prev_r*prev_i)+q;
if (((r*r) + (i*i)) < cutoff)
{
prev_r =r;
prev_i =i;
}
else return n;
}
return n;
}
The calculateFractal() Method
The calculateFractal()
method simply conformal maps the Mandelbrot on a 2D coordinate system by plotting onto the console window using the putpixel()
method, with the color values calculated by getFractalColor()
.
void CMandelzoom::calculateFractal()
{
int x,y,tempcol=0;
heightfactor =(ymax-ymin)/Height;
widthfactor =(xmax-xmin)/Width;
for (y=0; y<=Height;y++)
{
for(x=0;x<=Width;x++)
{
putpixel(x+ (40-(Width /2)),y+(12-(Height /2)+2),
getFractalColor(x,y));
}
}
setcolor(15);
}
The zoom() Method
The zoom()
method simply increases or decreases the initial values and calculates a new Mandelbrot fractal.
void CMandelzoom::zoom()
{
zxmin =zxmin+xzoomfactor;
zymin =zymin+yzoomfactor;
zxmax =zxmax-xzoomfactor;
zymax =zymax-yzoomfactor;
initFractal(zxmin,zymin,zxmax,zymax);
calculateFractal();
delay(20);
}
Realtime Animation
The function Realtime_Animate_At_60_Frames_Per_Second()
continuously zooms in realtime and updates the image every 60 frames per second:
void CMandelzoom::Realtime_Animate_At_60_Frames_Per_Second()
{
NewTicksPerSecond=GetTickCount();
DeltaTicksPerSecond=NewTicksPerSecond-OldTicksPerSecond;
frames++;
if(DeltaTicksPerSecond>=PreferredFramesPerSecond)
{
key2();
zoom();
OldTicksPerSecond=NewTicksPerSecond;
InverseFramesPerSecond=1/((float)PreferredFramesPerSecond/1000.0f);
OneFramePerSecond=(float)frames*InverseFramesPerSecond;
fps+=OneFramePerSecond;
fps/=2;
setcolor(31);gotoxy(70,22);printf(" %d FPS ",DeltaTicksPerSecond );setcolor(15);
frames=0;
Refesh=60/fps;
}
Sleep(33);
}
The function call to Realtime_Animate_At_60_Frames_Per_Second()
is made in a while
loop. The application animates in realtime and awaits the user to press the "Escape" key,
when the "Escape" key is pressed down, the application exits.
while(ch!=27)
{
Realtime_Animate_At_60_Frames_Per_Second() }
The Main File
Finally the file CMandelzoom_main.cpp is where we create an instance for our class and run our application.
#include "CMandelzoom.h"
int main()
{
CMandelzoom *mandelZoom = new CMandelzoom(1);
return 0;
}
And that is how easy it is to create a Realtime animation of a Mandelbrot Zoom in a Win32 Console.
Thanks for reading.