So how to generate such a beautiful fractal? In short:
for every pixel, iterate znew =
zold² + c on the complex plane until it leaves the circle
around the origin with radius 2. The number of iterations it the
color of the pixel.
The screen will be representing a part of the complex plane, inside the circle with radius 2 around the origin. For a pixel, the x coordinate will represent the real part of its complex coordinates, and the y coordinate will be the imaginary part.
For a julia set, for each pixel apply an iterated complex
function. This function is newz = oldz² + c, with z and c both
being complex numbers. Z is initially the coordinates of the pixel,
and will then constantly be updated through every iteration: each
iteration, the "newz" of the previous iteration is now used as
"oldz".
If you keep iterating this function, depending on the initial
condition (the pixel), z will either go to infinity, or remain in
the circle with radius 2 around the origin of the complex plane
forever. The points that remain in the circle forever, are the ones
that belong to the Julia Set. So keep iterating the function until
the distance of z to the origin (0,0) is greater than 2. Also give
a maximum number of iterations, for example 256, or the computer
would be stuck in an endless loop.
The color value of the pixel will then become the number of
times we had to iterate the function before the distance of z to
the origin got larger than 2. The constant c in the formula can be
anything really, as long as it's also inside the circle with radius
2. Different values of c give different Julia Sets. Some Julia Sets
are connected, others aren't. The Mandelbrot Set is the collection
of all points c that generate a connected Julia
Set.
First, you can choose a constant c for the function, which one
you choose will determinate the shape of the fractal. Let's take c
= (-0.5,0.5) in this example, so -0.5 is the real part and 0.5 the
imaginary part.
Imagine we're currently calculating the color of pixel (256,192) on a 256*256 screen. First, we transform the coordinates so it lies between -1 and 1 (if you zoom or move around in the fractal a different transformation is required): the coordinates become (1,0.5) so p = 1 + 0.5i.
Now we apply the function for the first time:
z = p² + cSo z = (0.25,1.5), and the distance of z to the origin =
sqrt(0.25*0.25 + 1.5*1.5) = 1.52069... is still smaller than
2.
Now you take this calculated z and put it in the function again
to calculate the next z, so now we get
The more iterations, the more detailed the Julia set will look
when zooming in deeply, but the more calculations are needed. The
higher the precision of the numbers, the longer you can zoom in
without encountering blocky pixels.
int main(int argc, char *argv[])
{
screen(400, 300, 0, "Julia Set"); //make larger to see more detail!
//each iteration, it calculates: new = old*old + c, where c is a constant and old starts at current pixel
double cRe, cIm; //real and imaginary part of the constant c, determinate shape of the Julia Set
double newRe, newIm, oldRe, oldIm; //real and imaginary parts of new and old
double zoom = 1, moveX = 0, moveY = 0; //you can change these to zoom and change position
ColorRGB color; //the RGB color value for the pixel
int maxIterations = 300; //after how much iterations the function should stop
//pick some values for the constant c, this determines the shape of the Julia Set
cRe = -0.7;
cIm = 0.27015;
//loop through every pixel
for(int y = 0; y < h; y++)
for(int x = 0; x < w; x++)
{
//calculate the initial real and imaginary part of z, based on the pixel location and zoom and position values
newRe = 1.5 * (x - w / 2) / (0.5 * zoom * w) + moveX;
newIm = (y - h / 2) / (0.5 * zoom * h) + moveY;
//i will represent the number of iterations
int i;
//start the iteration process
for(i = 0; i < maxIterations; i++)
{
//remember value of previous iteration
oldRe = newRe;
oldIm = newIm;
//the actual iteration, the real and imaginary part are calculated
newRe = oldRe * oldRe - oldIm * oldIm + cRe;
newIm = 2 * oldRe * oldIm + cIm;
//if the point is outside the circle with radius 2: stop
if((newRe * newRe + newIm * newIm) > 4) break;
}
//use color model conversion to get rainbow palette, make brightness black if maxIterations reached
color = HSVtoRGB(ColorHSV(i % 256, 255, 255 * (i < maxIterations)));
//draw the pixel
pset(x, y, color);
}
//make the Julia Set visible and wait to exit
redraw();
sleep();
return 0;
}
|
int main(int argc, char *argv[])
{
screen(320, 240, 0, "Julia Explorer");
//each iteration, it calculates: new = old*old + c, where c is a constant and old starts at current pixel
double cRe, cIm; //real and imaginary part of the constant c, determines shape of the Julia Set
double newRe, newIm, oldRe, oldIm; //real and imaginary parts of new and old
double zoom=1, moveX=0, moveY=0; //you can change these to zoom and change position
ColorRGB color; //the RGB color value for the pixel
int maxIterations=128; //after how much iterations the function should stop
double time, oldTime, frameTime; //current and old time, and their difference (for input)
int showText=0;
//pick some values for the constant c, this determines the shape of the Julia Set
cRe = -0.7;
cIm = 0.27015;
//begin the program loop
while(!done())
{
//draw the fractal
for(int y = 0; y < h; y++)
for(int x = 0; x < w; x++)
{
//calculate the initial real and imaginary part of z, based on the pixel location and zoom and position values
newRe = 1.5 * (x - w / 2) / (0.5 * zoom * w) + moveX;
newIm = (y - h / 2) / (0.5 * zoom * h) + moveY;
//i will represent the number of iterations
int i;
//start the iteration process
for(i = 0; i < maxIterations; i++)
{
//remember value of previous iteration
oldRe = newRe;
oldIm = newIm;
//the actual iteration, the real and imaginary part are calculated
newRe = oldRe * oldRe - oldIm * oldIm + cRe;
newIm = 2 * oldRe * oldIm + cIm;
//if the point is outside the circle with radius 2: stop
if((newRe * newRe + newIm * newIm) > 4) break;
}
//use color model conversion to get rainbow palette, make brightness black if maxIterations reached
color = HSVtoRGB(ColorHSV(i % 256, 255, 255 * (i < maxIterations)));
//draw the pixel
pset(x, y, color);
}
//print the values of all variables on screen if that option is enabled
if(showText <= 1)
{
print("X:", 1, 1, RGB_White, 1); print(moveX, 17, 1, RGB_White, 1);
print("Y:", 1, 9, RGB_White, 1); print(moveY, 17, 9, RGB_White, 1);
print("Z:", 1, 17, RGB_White, 1); print(zoom, 17, 17, RGB_White, 1);
print("R:", 1, 25, RGB_White, 1); print(cRe, 17, 25, RGB_White, 1);
print("I:", 1, 33, RGB_White, 1); print(cIm, 17, 33, RGB_White, 1);
print("N:", 1, 41, RGB_White, 1); print(maxIterations, 17, 41, RGB_White, 1);
}
//print the help text on screen if that option is enabled
if(showText == 0)
{
print("Arrows move (X,Y), Keypad +,- zooms (Z)", 1, h - 33, RGB_White, 1);
print("Keypad arrows change shape (R,I) ", 1, h - 25, RGB_White, 1);
print("Keypad *,/ changes iterations (N) ", 1, h - 17, RGB_White, 1);
print("a to z=presets (qwerty), F1=cycle texts", 1, h - 9, RGB_White, 1);
}
redraw();
//get the time and old time for time dependent input
oldTime = time;
time = getTicks();
frameTime = time - oldTime;
readKeys();
//ZOOM keys
if(keyDown(SDLK_KP_PLUS)) {zoom *= pow(1.001, frameTime);}
if(keyDown(SDLK_KP_MINUS)) {zoom /= pow(1.001, frameTime);}
//MOVE keys
if(keyDown(SDLK_DOWN)) {moveY += 0.0003 * frameTime / zoom;}
if(keyDown(SDLK_UP)) {moveY -= 0.0003 * frameTime / zoom;}
if(keyDown(SDLK_RIGHT)) {moveX += 0.0003 * frameTime / zoom;}
if(keyDown(SDLK_LEFT)) {moveX -= 0.0003 * frameTime / zoom;}
//CHANGE SHAPE keys
if(keyDown(SDLK_KP2)) {cIm += 0.0002 * frameTime / zoom;}
if(keyDown(SDLK_KP8)) {cIm -= 0.0002 * frameTime / zoom;}
if(keyDown(SDLK_KP6)) {cRe += 0.0002 * frameTime / zoom;}
if(keyDown(SDLK_KP4)) {cRe -= 0.0002 * frameTime / zoom;}
//keys to change number of iterations
if(keyPressed(SDLK_KP_MULTIPLY)) {maxIterations *= 2;}
if(keyPressed(SDLK_KP_DIVIDE)) {if(maxIterations > 2) maxIterations /= 2;}
//key to change the text options
if(keyPressed(SDLK_F1)) {showText++; showText %= 3;}
}
}
|
int main(int argc, char *argv[])
{
screen(400, 300, 0, "Mandelbrot Set"); //make larger to see more detail!
//each iteration, it calculates: newz = oldz*oldz + p, where p is the current pixel, and oldz stars at the origin
double pr, pi; //real and imaginary part of the pixel p
double newRe, newIm, oldRe, oldIm; //real and imaginary parts of new and old z
double zoom = 1, moveX = -0.5, moveY = 0; //you can change these to zoom and change position
ColorRGB color; //the RGB color value for the pixel
int maxIterations = 300;//after how much iterations the function should stop
//loop through every pixel
for(int y = 0; y < h; y++)
for(int x = 0; x < w; x++)
{
//calculate the initial real and imaginary part of z, based on the pixel location and zoom and position values
pr = 1.5 * (x - w / 2) / (0.5 * zoom * w) + moveX;
pi = (y - h / 2) / (0.5 * zoom * h) + moveY;
newRe = newIm = oldRe = oldIm = 0; //these should start at 0,0
//"i" will represent the number of iterations
int i;
//start the iteration process
for(i = 0; i < maxIterations; i++)
{
//remember value of previous iteration
oldRe = newRe;
oldIm = newIm;
//the actual iteration, the real and imaginary part are calculated
newRe = oldRe * oldRe - oldIm * oldIm + pr;
newIm = 2 * oldRe * oldIm + pi;
//if the point is outside the circle with radius 2: stop
if((newRe * newRe + newIm * newIm) > 4) break;
}
//use color model conversion to get rainbow palette, make brightness black if maxIterations reached
color = HSVtoRGB(ColorHSV(i % 256, 255, 255 * (i < maxIterations)));
//draw the pixel
pset(x, y, color);
}
//make the Mandelbrot Set visible and wait to exit
redraw();
sleep();
return 0;
}
|
int main(int argc, char *argv[])
{
screen(320, 240, 0, "Mandelbrot Explorer");
//each iteration, it calculates: new = old*old + c, where c is a constant and old starts at current pixel
double pr, pi; //real and imaginary part of the pixel p
double newRe, newIm, oldRe, oldIm; //real and imaginary parts of new and old
double zoom = 1, moveX = -0.5, moveY = 0; //you can change these to zoom and change position
ColorRGB color; //the RGB color value for the pixel
int maxIterations = 128; //after how much iterations the function should stop
double time, oldTime, frameTime; //current and old time, and their difference (for input)
int showText = 0;
//begin main program loop
while(!done())
{
//draw the fractal
for(int y = 0; y < h; y++)
for(int x = 0; x < w; x++)
{
//calculate the initial real and imaginary part of z, based on the pixel location and zoom and position values
pr = 1.5 * (x - w / 2) / (0.5 * zoom * w) + moveX;
pi = (y - h / 2) / (0.5 * zoom * h) + moveY;
newRe = newIm = oldRe = oldIm = 0; //these should start at 0,0
//i will represent the number of iterations
int i;
//start the iteration process
for(i = 0; i < maxIterations; i++)
{
//remember value of previous iteration
oldRe = newRe;
oldIm = newIm;
//the actual iteration, the real and imaginary part are calculated
newRe = oldRe * oldRe - oldIm * oldIm + pr;
newIm = 2 * oldRe * oldIm + pi;
//if the point is outside the circle with radius 2: stop
if((newRe * newRe + newIm * newIm) > 4) break;
}
//use color model conversion to get rainbow palette, make brightness black if maxIterations reached
color = HSVtoRGB(ColorHSV(i % 256, 255, 255 * (i < maxIterations)));
//draw the pixel
pset(x, y, color);
}
//print the values of all variables on screen if that option is enabled
if(showText <= 1)
{
print("X:", 1, 1, RGB_White, 1); print(moveX, 17, 1, RGB_White, 1);
print("Y:", 1, 9, RGB_White, 1); print(moveY, 17, 9, RGB_White, 1);
print("Z:", 1, 17, RGB_White, 1); print(zoom, 17, 17, RGB_White, 1);
print("N:", 1, 25, RGB_White, 1); print(maxIterations, 17, 25, RGB_White, 1);
}
//print the help text on screen if that option is enabled
if(showText == 0)
{
print("Arrows move (X,Y), Keypad +,- zooms (Z)", 1, h - 25, RGB_White, 1);
print("Keypad *,/ changes iterations (N) ", 1, h - 17, RGB_White, 1);
print("a to z=presets (qwerty), F1=cycle texts", 1, h - 9, RGB_White, 1);
}
redraw();
//get the time and old time for time dependent input
oldTime = time;
time = getTicks();
frameTime = time - oldTime;
readKeys();
//ZOOM keys
if(keyDown(SDLK_KP_PLUS)) {zoom *= pow(1.001, frameTime);}
if(keyDown(SDLK_KP_MINUS)) {zoom /= pow(1.001, frameTime);}
//MOVE keys
if(keyDown(SDLK_DOWN)) {moveY += 0.0003 * frameTime / zoom;}
if(keyDown(SDLK_UP)) {moveY -= 0.0003 * frameTime / zoom;}
if(keyDown(SDLK_RIGHT)) {moveX += 0.0003 * frameTime / zoom;}
if(keyDown(SDLK_LEFT)) {moveX -= 0.0003 * frameTime / zoom;}
//keys to change number of iterations
if(keyPressed(SDLK_KP_MULTIPLY)) {maxIterations *= 2;}
if(keyPressed(SDLK_KP_DIVIDE)) {if(maxIterations > 2) maxIterations /= 2;}
//key to change the text options
if(keyPressed(SDLK_F1)) {showText++; showText %= 3;}
}
return 0;
}
|