Created
September 1, 2018 21:58
-
-
Save LeopoldTal/2aa79947c4cab728402c4054d6733254 to your computer and use it in GitHub Desktop.
Mandelbrot set ASCII art
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Mandelbrot set ascii art | |
*/ | |
#include <stdio.h> | |
#include <string.h> | |
/* Params */ | |
//TODO: these should be command line arguments | |
const int COLUMNS = 151, LINES = 53; | |
const float CENTRE_X = -0.6, CENTRE_Y = 0; | |
const float STEP = 0.045; // in y direction | |
// threshold to accept a point as in the set | |
// increase this when the step is small (high zoom) | |
const int MAX_ITERS = 200; | |
// points not in the set are shaded by how fast they diverge | |
// cyclic list of chars to use for different divergence speeds | |
const char palette[] = "Patrick!<3"; | |
/* | |
* Determines whether a point is in the Mandelbrot set | |
* params: float ptX, float ptY: x and y coords of the point | |
* returns: int number of iterations to reject the point (MAX_ITERS if accepted) | |
*/ | |
int getRejectionIters(const float ptX, const float ptY) | |
{ | |
float re = 0, im = 0, reSq = 0, imSq = 0; | |
int nbIters = 0; | |
// iterate z <- z^2 + pt | |
// until |z|>2 (diverging) or the point is accepted | |
while (imSq + reSq <= 4 && nbIters < MAX_ITERS) | |
{ | |
im = 2*re*im + ptY; | |
re = reSq - imSq + ptX; | |
imSq = im*im; | |
reSq = re*re; | |
nbIters++; | |
} | |
return nbIters; | |
} | |
/* | |
* Writes a single character representing a point | |
* params: float ptX, float ptY: x and y coords of the point | |
*/ | |
void drawPoint(const float ptX, const float ptY) | |
{ | |
int rejectionIters; | |
rejectionIters = getRejectionIters(ptX, ptY); | |
if (rejectionIters >= MAX_ITERS) // point in set | |
{ | |
printf(" "); | |
} | |
else // point not in set; shade by divergence speed | |
{ | |
printf("%c", palette[(rejectionIters - 1) % strlen(palette)]); | |
} | |
} | |
int main() | |
{ | |
// character aspect ratio is 2:1 on my terminal | |
const float STEP_X = STEP / 2, STEP_Y = STEP; | |
int curCol, curLine; | |
float ptX, ptY; | |
// iterating over point coords directly risks rounding errors | |
for (curLine = 0 ; curLine < LINES ; curLine++) // y-coord, decreasing | |
{ | |
ptY = CENTRE_Y + (0.5 * LINES - curLine - 0.5) * STEP_Y; | |
for (curCol = 0 ; curCol < COLUMNS ; curCol++) // x-coord, increasing | |
{ | |
ptX = CENTRE_X - (0.5 * COLUMNS - curCol - 0.5) * STEP_X; | |
drawPoint(ptX, ptY); | |
} | |
printf("\n"); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment