• 谢尔平斯基三角形分形 - 产生随机性的最简方法


    1.什么是谢尔平斯基三角形? 

    谢尔平斯基三角形是一组多个(或无限)三角形。看看下面的谢尔平斯基三角形,看看它看起来有多无限

    这里的概念是,填充的三角形由中心的空等边三角形填充,使得这个三角形空间与围绕它形成的三个三角形一致。

     

    如下图所示 ,我们将要使用的概念很简单。如果有一个或多个图块,而不是在图块空间上方的三个图块,那么,我们将在该空间中放置一个图块,否则,就没有图块!

    也就是说我们只在黑三角里面放置白三角,其余地方不放。

     

    2.如何用代码实现谢尔平斯基三角形?

    文件有三个,分别是:main.cpp、SierpinskiTile.h、SierpinskiTile.cpp

    在 SierpinskiTile.h 中:
    我们需要包含 SDL.h 用于绘图和列表,以便包含SDL_Rect* 或图块的列表。 

    1. #include <SDL.h>
    2. #include <list>
    3. #ifndef _SIERPINSKI_TILE_
    4. #define _SIERPINSKI_TILE_
    5. class SierpinskiTile
    6. {
    7. public:
    8. SierpinskiTile(int scrW, int scrH, int w, int h)
    9. : scrW(scrW), scrH(scrH), tileW(w), tileH(h) {};
    10. ~SierpinskiTile();
    11. void setTile(int x_index, int y_index);
    12. bool isThereTile(int x_index, int y_index);
    13. void calculate(int y_index = -1);
    14. void draw(SDL_Renderer*& renderer, int r, int g, int b, int y_index);
    15. private:
    16. int scrW, scrH;
    17. int tileW, tileH;
    18. std::list<SDL_Rect*> rects;
    19. };
    20. #endif

     SierpinskiTile.cpp文件内容如下:

    1. #include "SierpinskiTile.h"
    2. SierpinskiTile::~SierpinskiTile() //Deleting all resources in destructor
    3. {
    4. for (auto itr : rects)
    5. delete itr;
    6. }
    7. //setTile() 方法在磁贴索引位置上设置小三角片:
    8. void SierpinskiTile::setTile(int x_index, int y_index) //Setting tile on the tile index position
    9. {
    10. SDL_Rect* rectToAdd = new SDL_Rect;
    11. rectToAdd->x = x_index * tileW;
    12. rectToAdd->y = y_index * tileH;
    13. rectToAdd->w = tileW;
    14. rectToAdd->h = tileH;
    15. rects.push_back(rectToAdd);
    16. }
    17. //isThereTile() 方法,用于找出给定的磁贴索引位置是否具有小三角片:
    18. bool SierpinskiTile::isThereTile(int x_index, int y_index) //Finding out whether a tile is here or not
    19. {
    20. for (auto itr : rects)
    21. if (itr->x == tileW * x_index
    22. && itr->y == tileH * y_index)
    23. return true;
    24. return false;
    25. }
    26. //compute() 方法找出下一行的小三角片排列,默认参数为 -1,这将导致 calculate()方法计算所有行的磁贴排列:
    27. void SierpinskiTile::calculate(int y_index) //Calculating where to put tiles in the next row
    28. //by the tile arrangement present in the previous row
    29. {
    30. /
    31. //Conditions for putting a tile below the upper tile (or tile space):
    32. // 1- Tile is at that spot, 0- Tile is not at that spot, X- Unknown (can be 0 or 1)
    33. /
    34. // Case 1: 0 1 0, Case 2: 1 0 0, Case 3: 0 0 1,
    35. // Case 4: 1 1 0, Case 5: 1 0 1, Case 6: 0 1 1
    36. // Output for Cases 1-6: X 1 X
    37. /
    38. // Case 7: 0 0 0, Case 8: 1 1 1
    39. // Output for Cases 7-8: X 0 X
    40. int y = 0;
    41. if (y_index > -1)
    42. {
    43. y = y_index;
    44. for (int x = 0; x < scrW / tileW; x++)
    45. {
    46. if ((isThereTile(x, y) || isThereTile(x + 1, y) || isThereTile(x - 1, y))
    47. && !(isThereTile(x, y) && isThereTile(x + 1, y) && isThereTile(x - 1, y))
    48. )
    49. setTile(x, y + 1);
    50. }
    51. }
    52. else
    53. {
    54. for (; y < scrH / tileH; y++)
    55. for (int x = 0; x < scrW / tileW; x++)
    56. {
    57. if ((isThereTile(x, y) || isThereTile(x + 1, y) || isThereTile(x - 1, y))
    58. && !(isThereTile(x, y) && isThereTile(x + 1, y) && isThereTile(x - 1, y))
    59. )
    60. setTile(x, y + 1);
    61. }
    62. }
    63. }
    64. // draw() 方法实际上只绘制一行并删除前面所有行中的所有小三角片:
    65. void SierpinskiTile::draw(SDL_Renderer*& renderer, int r, int g, int b, int y_index)
    66. {
    67. SDL_SetRenderDrawColor(renderer, r, g, b, 255); //Setting renderer's color
    68. std::list<SDL_Rect*> deleteRects; //For getting a list of rectangles/tiles to be deleted
    69. for (auto itr : rects)
    70. {
    71. SDL_RenderFillRect(renderer, itr); //Draw all tiles present in the rects which
    72. //will be just all tiles in the particular row
    73. if (itr->y <= tileH * y_index) //Put all tiles of rows before the given row
    74. //to deleteRects for deleting
    75. deleteRects.push_back(itr);
    76. }
    77. for (auto itr : deleteRects) //Delete all collected tiles and clear them
    78. {
    79. rects.remove(itr);
    80. delete itr;
    81. }
    82. deleteRects.clear();
    83. SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); //Resetting renderer's color
    84. }

     main.cpp文件,首先,我们需要一些必要的常量以及SDL_Window*SDL_Renderer*SDL_Event,此外我们还需要一个布尔值。

    1. #include <SDL.h>
    2. #include "SierpinskiTile.h"
    3. #undef main //Solution to the problem: No entry point defined.
    4. const int SCR_W = 640;
    5. const int SCR_H = 480;
    6. const int TILE_W = 5; //Each tile's width
    7. const int TILE_H = 5; //Each tile's height
    8. SDL_Window* window = NULL;
    9. SDL_Renderer* renderer = NULL;
    10. SDL_Event event;
    11. bool quit = false;
    12. SierpinskiTile* generator = NULL;
    13. int main(int argc, char** args)
    14. {
    15. SDL_Init(SDL_INIT_VIDEO); //Initializing SDL2
    16. window = SDL_CreateWindow("Koch Fractal", SDL_WINDOWPOS_UNDEFINED,
    17. SDL_WINDOWPOS_UNDEFINED, SCR_W, SCR_H, SDL_WINDOW_SHOWN); //Creating window
    18. renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); //Creating renderer
    19. SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); //Setting default screen color
    20. generator = new SierpinskiTile(SCR_W, SCR_H, TILE_W, TILE_H); //Creating fractal generator
    21. generator->setTile((SCR_W / TILE_W) / 2, 0); //Setting a tile at the top middle of the screen
    22. int row = 0;
    23. while (!quit)
    24. {
    25. while (SDL_PollEvent(&event) > 0) //Minimal event polling for proper quitting
    26. if (event.type == SDL_QUIT)
    27. quit = true;
    28. //***NOTE: Screen must not be cleaned as the draw() method draws a row only
    29. //and deletes all tiles of the previous rows***
    30. //SDL_RenderClear(renderer);
    31. if (row < SCR_H / TILE_H) //Draw and calculate until the last row
    32. {
    33. generator->draw(renderer, 0, 255, 0, row-1); //Drawing the row in green color
    34. SDL_RenderPresent(renderer); //Updating screen
    35. generator->calculate(row++); //Calculating the next row
    36. }
    37. }
    38. delete generator; //Deallocating fractal generator
    39. SDL_DestroyRenderer(renderer);
    40. SDL_DestroyWindow(window);
    41. SDL_Quit(); //Clearing all SDL resources
    42. return 0;
    43. }

    3. 运行结果如何?

    下图显示了结果,细节取决于常量TILE_W和TILE_H。值越小,分形显示的细节就越详细。

     

     

     

     

     

     

     

  • 相关阅读:
    Windows11 安装配置 JDK 和 Maven
    Pyton学习(5)--socket编程,一个简单的对话框
    一种基于多尺度密集递归融合网络的图像超分辨率新算法
    做自媒体短视频是如何赚钱的呢?
    价值驱动的数字化转型
    【计算思维题】少儿编程 蓝桥杯青少组计算思维 数学逻辑思维真题详细解析第10套
    如何为WPF应用程序制作一个虚拟键盘?这里有答案(Part 2)
    【数字IC验证快速入门】12、SystemVerilog TestBench(SVTB)入门
    springcloud: stream整合rocketmq
    AAC音视频编码详解
  • 原文地址:https://blog.csdn.net/xipengbozai/article/details/125611496