<dfn id="lvnb7"></dfn>

    <dfn id="lvnb7"></dfn> <address id="lvnb7"></address>

          <ruby id="lvnb7"></ruby>

            <delect id="lvnb7"><strike id="lvnb7"></strike></delect>

              • Articles
              • Sierpinski Triangle Fractal - The easies
              Published by
              Oct 13, 2015 (last update: Oct 13, 2015)

              Sierpinski Triangle Fractal - The easiest way to produce randomness

              Score: 4.3/5 (795 votes)
              *****

              What is Sierpinski Triangle?


              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!

              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. This time, it will be multiple file project.

              Files: main.cpp, SierpinskiTile.h, SierpinskiTile.cpp

              In SierpinskiTile.h:
              We need to include SDL.h for drawing and list to have a list of SDL_Rect* or tiles.

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


              Now, here's the class with preprocessor directives:

              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 


              In SierpinskiTile.cpp:
              Here's the implementation with some comments to have understanding:

              Destructor:
              1
              2
              3
              4
              5
              6
              7
              #include "SierpinskiTile.h"
              
              SierpinskiTile::~SierpinskiTile() //Deleting all resources in destructor
              {
              	for (auto itr : rects)
              		delete itr;
              }


              setTile() method to set tile on the tile index position:
              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);
              }


              isThereTile() method to find out whether given tile index position have a tile there or not:
              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;
              }


              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:
              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);
              			}
              	}
              }


              The ahhh... second most important -> draw() method which actually draws only a row and deletes all the tiles in all the previous rows:
              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
              }


              In main.cpp:
              First, we need some necessary constants along with SDL_Window*, SDL_Renderer* and SDL_Event. We also need a boolean as well.

              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;


              Time for action here, every thing is all fine and main() method is now, easy to implement!
              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;
              }


              It's pretty much straight forward and I hope that you understand that...

              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.

              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:-


              The Randomness!

              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:

              最好看的2018中文字幕_亚洲欧美日韩一区_国产欧美亚洲综合第一区_欧美日韩视费观看视频