What is Koch Fractal?
Koch Fractal is a simple algorithm which produces snowflake from a triangle. The concept behind this, is to break a line into two while leaving one third of the space between them where we fit two more lines forming an equilateral triangle without the base. This process is, then repeated to all lines again and again!
The Implementation
First thing, you should know basics of C++ as well as a bit of SDL2 and basic trigonometry to understand it.
We are going to use
SDL2 to have some graphics. We will only use some of its basic primitive drawing methods for drawing lines. So, we are going to include only SDL2 header. We are also going to include list.h to have a list of lines.
1 2
| #include <list> #include <SDL2/SDL.h> // or #include <SDL.h>
|
Now, we need an
SDL_Window*, an
SDL_Renderer* and an
SDL_Event instance to have the image on screen and to handle events.
1 2 3 4 5 6 7
| SDL_Window* window = NULL; SDL_Renderer* renderer = NULL; bool quit = false; SDL_Event in; const int SCR_W = 640; // Width of the window const int SCR_H = 480; // Height of the window
|
Previously, I said that there will be a list of lines. That means, we need to define line as a struct or a class. You can use struct as well but I am using class for that.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| class Line { public: double x, y, length, angle; // Members Line(double x, double y, double length, double angle) : x(x), y(y), length(length), angle(angle) {} double getX2() // Getting the second x coordinate based on the angle and length { return x+cos(angle*(M_PI/180.0))*length; } double getY2() // Getting the second y coordinate based on the angle and length { return y+sin(angle*(M_PI/180.0))*length; } void draw() { SDL_SetRenderDrawColor(renderer, 100,255,100,255); // Setting the color of the line SDL_RenderDrawLine(renderer,x,y, getX2(),getY2()); // Drawing the line SDL_SetRenderDrawColor(renderer, 0,0,0,255); // Resetting the color } };
|
Now, we need to have a list of lines.
| std::list<Line*> lines; //Note that we do not take Line, we take Line*
|
Finally, the Koch algorithm implementation, all in one function which takes list of Line* as a parameter.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| //Worth noting: It's a heavy function! void kochFractal( std::list<Line*> & lines ) { std::list<Line*> newLines; //For getting new Line*(s) std::list<Line*> delLines; //For getting Line*(s) to be deleted for(auto itr = lines.begin(); itr != lines.end(); itr++) { double x_l1 = (*itr)->x; double y_l1 = (*itr)->y; double len_l1 = (*itr)->length/3; double ang_l1 = (*itr)->angle; double x_l2 = (*itr)->x + (cos((*itr)->angle*(M_PI/180.0))*(*itr)->length/1.5); double y_l2 = (*itr)->y + (sin((*itr)->angle*(M_PI/180.0))*(*itr)->length/1.5); double len_l2 = (*itr)->length/3; double ang_l2 = (*itr)->angle; double x_l3 = (*itr)->x + (cos((*itr)->angle*(M_PI/180.0))*(*itr)->length/3.0); double y_l3 = (*itr)->y + (sin((*itr)->angle*(M_PI/180.0))*(*itr)->length/3.0); double len_l3 = (*itr)->length/3.0; double ang_l3 = (*itr)->angle - 300.0; double x_l4 = (*itr)->x + (cos((*itr)->angle*(M_PI/180.0))*((*itr)->length/1.5)); double y_l4 = (*itr)->y + (sin((*itr)->angle*(M_PI/180.0))*((*itr)->length/1.5)); double len_l4 = (*itr)->length/3.0; double ang_l4 = (*itr)->angle - 240.0; //All four lines properties are setted above! //Fixing bug - Changing Triangle Forming Orientation x_l4 = x_l4 + cos(ang_l4*(M_PI/180.0))*len_l4; y_l4 = y_l4 + sin(ang_l4*(M_PI/180.0))*len_l4; ang_l4 -= 180.0; //Each line forms four new lines... newLines.push_back( new Line( x_l1, y_l1, len_l1, ang_l1 ) ); newLines.push_back( new Line( x_l2, y_l2, len_l2, ang_l2 ) ); newLines.push_back( new Line( x_l3, y_l3, len_l3, ang_l3 ) ); newLines.push_back( new Line( x_l4, y_l4, len_l4, ang_l4 ) ); //...for deleting itself! delLines.push_back( (*itr) ); } for(auto itr = newLines.begin(); itr != newLines.end(); itr++) lines.push_back( (*itr) ); //Adding new Line*(s) for(auto itr = delLines.begin(); itr != delLines.end(); itr++) { lines.remove( (*itr) ); //Deleting new Line*(s) delete (*itr); } }
|
Phew! A big implementation really! Now, time for the action in the
int main():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| int main( int argc, char** args ) { SDL_Init(SDL_INIT_EVERYTHING); //Initializing SDL2 window = SDL_CreateWindow( "Koch Fractal", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCR_W, SCR_H, SDL_WINDOW_SHOWN ); //Creating window renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED ); //Creating renderer SDL_SetRenderDrawColor(renderer,0,0,0,255); //Setting default screen color //Horizontal line //lines.push_back( new Line(SCR_W-10,SCR_H/2.0, SCR_W-20,180.0) ); //Vertical line //lines.push_back( new Line(SCR_W/1.5,10, SCR_H-20,90.0) ); //Equilateral Triangle for forming Koch Snowflake lines.push_back( new Line( SCR_W-100, 150, SCR_W-200, 180.0) ); lines.push_back( new Line( 100, 150, SCR_W-200, 60.0) ); Line* lineS = new Line( SCR_W-100, 150, SCR_W-200, 120.0); lineS->x += cos(lineS->angle *(M_PI/180.0))*lineS->length; lineS->y += sin(lineS->angle *(M_PI/180.0))*lineS->length; lineS->angle -= 180.0; lines.push_back( lineS ); while(!quit) //The loop { while(SDL_PollEvent(&in)) //Polling Events { if(in.type == SDL_QUIT) quit = true; } SDL_RenderClear(renderer); //Clearing renderer for(auto itr = lines.begin(); itr != lines.end(); itr++) (*itr)->draw(); //Drawing all lines SDL_RenderPresent(renderer); //Updating screen SDL_Delay(2500); //Delay to show each iteration kochFractal(lines); //Applying Koch Fractal } for(auto itr = lines.begin(); itr != lines.end(); itr++) delete (*itr); //Deleting all lines at the end of a program SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); //Clearing all SDL resources return 0; }
|
The Results!
Following images show the result. It was executed on a mobile device using C4Droid, a program for running C++ programs on Android.
I hope that this excites you for more programming, algorithms and fractals. For more such things, visit my blog
bacprogramming.wordpress.com.