Score: 4.3/5 (747 votes)

What is Sierpinski Triangle?

The Implementation

1

2

#include <SDL.h> #include <list>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

#ifndef _SIERPINSKI_TILE_ #define _SIERPINSKI_TILE_ class SierpinskiTile { public : SierpinskiTile( int scrW, int scrH, int w, int h) : scrW(scrW), scrH(scrH), tileW(w), tileH(h) {}; ~SierpinskiTile(); void setTile( int x_index, int y_index); bool isThereTile( int x_index, int y_index); void calculate( int y_index = -1); void draw(SDL_Renderer*& renderer, int r, int g, int b, int y_index); private : int scrW, scrH; int tileW, tileH; std::list<SDL_Rect*> rects; }; #endif

1

2

3

4

5

6

7

#include "SierpinskiTile.h" SierpinskiTile::~SierpinskiTile() //Deleting all resources in destructor { for ( auto itr : rects) delete itr; }

1

2

3

4

5

6

7

8

9

10

void SierpinskiTile::setTile( int x_index, int y_index) //Setting tile on the tile index position { SDL_Rect* rectToAdd = new SDL_Rect; rectToAdd->x = x_index * tileW; rectToAdd->y = y_index * tileH; rectToAdd->w = tileW; rectToAdd->h = tileH; rects.push_back(rectToAdd); }

1

2

3

4

5

6

7

8

9

bool SierpinskiTile::isThereTile( int x_index, int y_index) //Finding out whether a tile is here or not { for ( auto itr : rects) if (itr->x == tileW * x_index && itr->y == tileH * y_index) return true ; return false ; }

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

void SierpinskiTile::calculate( int y_index) //Calculating where to put tiles in the next row //by the tile arrangement present in the previous row { ///////////////////////////////////////////////// //Conditions for putting a tile below the upper tile (or tile space): // 1- Tile is at that spot, 0- Tile is not at that spot, X- Unknown (can be 0 or 1) ///////////////////////////////////////////////// // Case 1: 0 1 0, Case 2: 1 0 0, Case 3: 0 0 1, // Case 4: 1 1 0, Case 5: 1 0 1, Case 6: 0 1 1 // Output for Cases 1-6: X 1 X ///////////////////////////////////////////////// // Case 7: 0 0 0, Case 8: 1 1 1 // Output for Cases 7-8: X 0 X int y = 0; if (y_index > -1) { y = y_index; for ( int x = 0; x < scrW / tileW; x++) { if ((isThereTile(x, y) || isThereTile(x + 1, y) || isThereTile(x - 1, y)) && !(isThereTile(x, y) && isThereTile(x + 1, y) && isThereTile(x - 1, y)) ) setTile(x, y + 1); } } else { for (; y < scrH / tileH; y++) for ( int x = 0; x < scrW / tileW; x++) { if ((isThereTile(x, y) || isThereTile(x + 1, y) || isThereTile(x - 1, y)) && !(isThereTile(x, y) && isThereTile(x + 1, y) && isThereTile(x - 1, y)) ) setTile(x, y + 1); } } }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

void SierpinskiTile::draw(SDL_Renderer*& renderer, int r, int g, int b, int y_index) { SDL_SetRenderDrawColor(renderer, r, g, b, 255); //Setting renderer's color std::list<SDL_Rect*> deleteRects; //For getting a list of rectangles/tiles to be deleted for ( auto itr : rects) { SDL_RenderFillRect(renderer, itr); //Draw all tiles present in the rects which //will be just all tiles in the particular row if (itr->y <= tileH * y_index) //Put all tiles of rows before the given row //to deleteRects for deleting deleteRects.push_back(itr); } for ( auto itr : deleteRects) //Delete all collected tiles and clear them { rects.remove(itr); delete itr; } deleteRects.clear(); SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); //Resetting renderer's color }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

#include <SDL.h> #include "SierpinskiTile.h" #undef main //Solution to the problem: No entry point defined. const int SCR_W = 640; const int SCR_H = 480; const int TILE_W = 5; //Each tile's width const int TILE_H = 5; //Each tile's height SDL_Window* window = NULL; SDL_Renderer* renderer = NULL; SDL_Event event; bool quit = false ; SierpinskiTile* generator = NULL;

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

int main( int argc, char ** args) { SDL_Init(SDL_INIT_VIDEO); //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 generator = new SierpinskiTile(SCR_W, SCR_H, TILE_W, TILE_H); //Creating fractal generator generator->setTile((SCR_W / TILE_W) / 2, 0); //Setting a tile at the top middle of the screen int row = 0; while (!quit) { while (SDL_PollEvent(&event) > 0) //Minimal event polling for proper quitting if (event.type == SDL_QUIT) quit = true ; //***NOTE: Screen must not be cleaned as the draw() method draws a row only //and deletes all tiles of the previous rows*** //SDL_RenderClear(renderer); if (row < SCR_H / TILE_H) //Draw and calculate until the last row { generator->draw(renderer, 0, 255, 0, row-1); //Drawing the row in green color SDL_RenderPresent(renderer); //Updating screen generator->calculate(row++); //Calculating the next row } } delete generator; //Deallocating fractal generator SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); //Clearing all SDL resources return 0; }

The Results

The Randomness!

Sierpinski Triangle is a group of multiple(or infinite) triangles. Just see the Sierpinski Triangle below to find out how infinite it may look.The concept behind this is the fact that the filled triangle is filled by an empty equilateral triangle in the center in such a way that this triangular space is congruent to the three triangles being formed around it.If you see my previous article which is given here , you see that there was a triangle which I just break into further triangles without a base, in a kind of brute manner. This time it will be done in a technical manner! In other words, we don't make a triangle and then, break it into three, but we will do something else in order to produce randomness as well.The concept that we will use, is simple. It will have tiles! If there are one or more than one tiles and, not three tiles above the tile space then, we will put a tile in that space or else, no tiles!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 useto 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. This time, it will be multiple file project.main.cpp, SierpinskiTile.h, SierpinskiTile.cppWe need to include SDL.h for drawing and list to have a list of SDL_Rect* or tiles.Now, here's the class with preprocessor directives:Here's the implementation with some comments to have understanding:Destructor:setTile() method to set tile on the tile index position:isThereTile() method to find out whether given tile index position have a tile there or not:The most important -> calculate() method to find out tiles arrangement for the next row, default parameter is -1 which will cause calculate() method to calculate all the rows' tile arrangement:The ahhh... second most important -> draw() method which actually draws only a row and deletes all the tiles in all the previous rows:First, we need some necessary constants along withand. We also need a boolean as well.Time for action here, every thing is all fine and main() method is now, easy to implement!It's pretty much straight forward and I hope that you understand that...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 The detailing depends on the constants TILE_W and TILE_H. The lesser the values, the more detailing the fractal shows.Less details:-Average details:-More details:-Most details:-I ran it on PC as well. Here is another extremely detailed fractal:-With setting a tile at the top corner, we can see that the fractal produces confused and hardly understandable patterns of triangles which looks random in nature.The same code with different setTile() at start can produce this: