Fractale triangulaire de Sierpinski - Le moyen le plus simple de générer du hasard

1. Qu'est-ce qu'un triangle de Sierpinski ? 

Un triangle de Sierpinski est un ensemble de plusieurs (ou infinis ) triangles. Jetez un œil au triangle de Sierpinski ci-dessous pour voir à quel point il semble infini .

Le concept ici est que le triangle rempli est rempli par le triangle équilatéral central vide de sorte que cet espace triangulaire coïncide avec les trois triangles formés autour de lui.

 

Comme le montre l'image ci-dessous, le concept que nous allons utiliser est simple. S'il y a une ou plusieurs tuiles, mais pas trois tuiles au-dessus de l'espace de tuiles, alors, nous placerons une tuile dans cet espace, sinon, pas de tuiles !

C'est-à-dire que nous ne plaçons que le triangle blanc à l'intérieur du triangle noir et le laissons seul dans le reste.

 

2. Comment implémenter le triangle de Sierpinski avec du code ?

Il existe trois fichiers, à savoir : main.cpp, SierpinskiTile.h, SierpinskiTile.cpp

Dans SierpinskiTile.h :
nous devons inclure SDL.h pour les tracés et les listes afin d'inclure  des listes de  SDL_Rect* ou de tuiles.

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

#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 

 Le contenu du fichier SierpinskiTile.cpp est le suivant :

#include "SierpinskiTile.h"

SierpinskiTile::~SierpinskiTile() //Deleting all resources in destructor
{
	for (auto itr : rects)
		delete itr;
}

//setTile() 方法在磁贴索引位置上设置小三角片:
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() 方法,用于找出给定的磁贴索引位置是否具有小三角片:
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;
}



//compute() 方法找出下一行的小三角片排列,默认参数为 -1,这将导致 calculate()方法计算所有行的磁贴排列:
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);
			}
	}
}


// draw() 方法实际上只绘制一行并删除前面所有行中的所有小三角片:
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
}

 main.cpp, d'abord, nous avons besoin de certaines constantes nécessaires ainsi que de SDL_Window* , SDL_Renderer* et SDL_Event, en plus nous avons besoin d'une valeur booléenne.

#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;

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

3. Quel est le résultat courant ?

La figure ci-dessous montre le résultat, les détails dépendent des constantes TILE_W et TILE_H. Plus la valeur est petite, plus la fractale affiche de détails.

 

 

 

 

 

 

 

Je suppose que tu aimes

Origine blog.csdn.net/xipengbozai/article/details/125611496
conseillé
Classement