Advertisement
Guest User

Untitled

a guest
Feb 24th, 2018
182
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.62 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <string>
  4. #include <set>
  5. #include <map>
  6. #include <iomanip>
  7. #include <random>
  8. #include <memory>
  9. #include <chrono>
  10. #include "SDL2\SDL.h"
  11. #include "SDL2\SDL_ttf.h"
  12. using namespace std;
  13.  
  14. default_random_engine engine;
  15. SDL_Window* window1{ nullptr }, *window2{ nullptr };
  16. SDL_Renderer* renderer1{ nullptr }, *renderer2{ nullptr };
  17. TTF_Font* font{ nullptr };
  18. constexpr int winWidth{ 1100 };
  19. constexpr int winHeight{ 840 };
  20. constexpr int cellsN{ 20 };
  21. constexpr int cellsPixelSize{ 22 };
  22. constexpr int padding{ 1 };
  23. vector<SDL_Texture*>numbers;
  24.  
  25. struct Cell {
  26.     int row{};
  27.     int col{};
  28. };
  29.  
  30. struct TreeNode {
  31.     int parent;
  32.     vector<int> childrenList;
  33. };
  34.  
  35. class Union
  36. {
  37.     int cellsN;
  38.     vector<vector<bool>> state;
  39.     vector<TreeNode> tree;
  40.     vector<int> treeSize;
  41.     map<int, set<int>> treeDepth;
  42.     vector<int> offList;
  43.     set<int> startPoints;
  44.     map<int, SDL_Color> colors;
  45.  
  46.     Cell getRandomOffSite();
  47.     void connect(const Cell& first, const Cell& second);
  48.     TreeNode& root(const TreeNode& node);
  49.     int getIdDepth(int);
  50.     void updateDepthMap(int smallerNodeID, int biggerNodeID);
  51.     void _updateChildrenDepth(int smallerNodeID, int removeOffest, int AddOffset);
  52. public:
  53.     Union(int size)
  54.         :cellsN{ size },
  55.         state(cellsN, vector<bool>(cellsN, false)),
  56.         tree(cellsN*cellsN),
  57.         treeSize(cellsN*cellsN, 1),
  58.         offList(cellsN*cellsN)
  59.     {
  60.         for (int id = 0; id < tree.size(); id++) {
  61.             tree[id].parent = offList[id] = id;
  62.             treeDepth[0].insert(id);
  63.         }
  64.     }
  65.  
  66.     void drawState();
  67.     void drawUnionGraph();
  68.     void openSite();
  69.     void degubPrintUnionState();
  70.     void degubPrintDepthMap();
  71. };
  72.  
  73. void errorCheck(bool);
  74.  
  75. int main(int argc, char* argv[])
  76. {
  77.     engine.seed(chrono::steady_clock::now().time_since_epoch().count());
  78.  
  79.     errorCheck(!SDL_Init(SDL_INIT_EVERYTHING));
  80.  
  81.  
  82.     window1 = SDL_CreateWindow("Percolation Test",
  83.                                10, SDL_WINDOWPOS_CENTERED,
  84.                                winWidth, winHeight,
  85.                                SDL_WINDOW_SHOWN);
  86.     window2 = SDL_CreateWindow("UnionGraph Diplay",
  87.                                800, SDL_WINDOWPOS_CENTERED,
  88.                                winWidth, winHeight,
  89.                                SDL_WINDOW_SHOWN);
  90.     errorCheck(window1);
  91.     errorCheck(window2);
  92.  
  93.     renderer1 = SDL_CreateRenderer(window1, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
  94.     renderer2 = SDL_CreateRenderer(window2, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
  95.     errorCheck(renderer1);
  96.     errorCheck(renderer2);
  97.  
  98.     errorCheck(!TTF_Init());
  99.  
  100.  
  101.     ///////////////////////////////////////////////////////////
  102.     string fontPath = "Z:\\Asus\\Documenti\\Visual Studio 2017\\Percolation_Test\\Percolation_Test\\font\\arial.ttf";
  103.    
  104.     font = TTF_OpenFont(fontPath.c_str(), 10);
  105.     errorCheck(font);
  106.  
  107.     numbers.resize(cellsN*cellsN);
  108.     SDL_Color textColor{ 0,0,0,255 };
  109.     for (size_t i = 0; i < numbers.size(); i++)
  110.     {
  111.         numbers[i] = nullptr;
  112.         SDL_Surface* surface = TTF_RenderText_Blended(font, to_string(i).c_str(), textColor);
  113.         numbers[i] = SDL_CreateTextureFromSurface(renderer2, surface);
  114.         SDL_FreeSurface(surface);
  115.     }
  116.  
  117.     SDL_Event event;
  118.     auto myUnion = make_unique<Union>(cellsN);
  119.  
  120.     while (true)
  121.     {
  122.         SDL_PollEvent(&event);
  123.         switch (event.type)
  124.         {
  125.             case SDL_KEYDOWN:
  126.             {
  127.                 auto key = event.key.keysym.sym;
  128.                 if (key == SDLK_ESCAPE) {
  129.                     myUnion = make_unique<Union>(cellsN);
  130.                 }
  131.  
  132.                 if (key == SDLK_SPACE) {
  133.                     SDL_Event wait{};
  134.                     myUnion->degubPrintDepthMap();
  135.                     while (wait.key.keysym.sym != SDLK_SPACE) {
  136.                         SDL_PollEvent(&wait);
  137.                     }
  138.                 }
  139.             }
  140.         }
  141.  
  142.         //draw
  143.         SDL_SetRenderDrawColor(renderer1, 0, 0, 0, 255);
  144.         SDL_SetRenderDrawColor(renderer2, 111, 0, 0, 255);
  145.         SDL_RenderClear(renderer1);
  146.         SDL_RenderClear(renderer2);
  147.  
  148.         myUnion->drawState();
  149.         myUnion->drawUnionGraph();
  150.  
  151.         SDL_RenderPresent(renderer1);
  152.         SDL_RenderPresent(renderer2);
  153.  
  154.         //update
  155.         myUnion->openSite();
  156.  
  157.         //pause
  158.         //SDL_Delay(400);
  159.     }
  160.  
  161.     SDL_DestroyWindow(window1);
  162.     SDL_DestroyWindow(window2);
  163.     SDL_DestroyRenderer(renderer1);
  164.     SDL_DestroyRenderer(renderer2);
  165.     if (font) { TTF_CloseFont(font); }
  166.     if (TTF_WasInit())TTF_Quit();
  167.     for (auto p : numbers) {SDL_DestroyTexture(p);}
  168.     SDL_Quit();
  169.     return 0;
  170. }
  171. ///////////////////////////////////////////////////////////
  172.  
  173. void errorCheck(bool b) {
  174.     if (!b) {
  175.         cout << SDL_GetError() << endl;
  176.         exit(EXIT_FAILURE);
  177.     }
  178. }
  179.  
  180. void Union::drawState()
  181. {
  182.     int totalPadding = padding * (cellsN - 1);
  183.     int totalGridSize = cellsN * cellsPixelSize;
  184.     int offsetX = (winWidth - (totalGridSize + totalPadding)) / 2;
  185.     int offsetY = (winHeight - (totalGridSize + totalPadding)) / 2;
  186.     SDL_Rect rect{ offsetX ,offsetY, cellsPixelSize,cellsPixelSize };
  187.     SDL_Color white{ 255,255,255,255 }, lightBlue{ 30,120,220,255 }, clr{};
  188.  
  189.     for (size_t i = 0; i < tree.size(); i++)
  190.     {
  191.         int row = i / cellsN;
  192.         int col = i % cellsN;
  193.  
  194.         //is openSite?
  195.         if (state[row][col])
  196.         {
  197.             //calculate cell position on screen
  198.             int y = row * cellsPixelSize + row * padding;
  199.             int x = col * cellsPixelSize + col * padding;
  200.             rect.x = offsetX + x;
  201.             rect.y = offsetY + y;
  202.  
  203.             //has a way to reach the top line?
  204.             int rootOfID = root(tree[i]).parent;
  205.             if (startPoints.find(rootOfID) != startPoints.end()) { clr = colors[rootOfID]; }
  206.             else { clr = white; }
  207.  
  208.             SDL_SetRenderDrawColor(renderer1, clr.r, clr.g, clr.b, clr.a);
  209.             SDL_RenderFillRect(renderer1, &rect);
  210.         }
  211.     }
  212. }
  213.  
  214. void Union::drawUnionGraph()
  215. {
  216.     int borderH{ 20 }, borderV{ 20 };
  217.     int innerBorder{ 10 };
  218.     SDL_Rect client = { borderH, borderV, winWidth - borderH * 2, winHeight - borderV * 2 };
  219.  
  220.     //background
  221.     SDL_SetRenderDrawColor(renderer2, 90, 90, 90, 255);
  222.     SDL_RenderFillRect(renderer2, &client);
  223.  
  224.     int nodeWidth{ 30 }, nodeHeight{ 20 };
  225.     int halfNodeW{ nodeWidth / 2 }, halfNodeH{ nodeHeight / 2 };
  226.     SDL_Rect element{ 0,0,nodeWidth,nodeHeight };
  227.     int depth = treeDepth.size();
  228.  
  229.     int currDepth{};
  230.     for (auto&[Key, Set] : treeDepth)
  231.     {
  232.         int setSize = Set.size();
  233.         int strideX = (client.w - innerBorder * 2) / setSize;
  234.         int strideY = client.h / depth;
  235.         int x = (client.x + innerBorder + strideX / 2) - halfNodeW;
  236.         int y = (client.y + strideY / 2) - halfNodeH;
  237.  
  238.         element.x = x - strideX;
  239.         element.y = y + strideY * currDepth;
  240.         for (auto val : Set)
  241.         {
  242.             element.x += strideX;
  243.  
  244.             //element fill
  245.             SDL_SetRenderDrawColor(renderer2, 255, 255, 255, 255);
  246.             SDL_RenderFillRect(renderer2, &element);
  247.             //element border
  248.             SDL_SetRenderDrawColor(renderer2, 0, 0, 0, 255);
  249.             SDL_RenderDrawRect(renderer2, &element);
  250.             //number
  251.  
  252.             SDL_Rect textSize{ element.x + 7, element.y + 5, 0, 0 };
  253.             TTF_SizeText(font, to_string(val).c_str(), &textSize.w, &textSize.h);
  254.             SDL_RenderCopy(renderer2, numbers[val], NULL, &textSize);
  255.         }
  256.  
  257.         //connection line
  258.         if (currDepth != 0) {
  259.             float p1_x = x +halfNodeW;
  260.             float p1_y = element.y;
  261.             float upperRowStrideX = (client.w - innerBorder * 2) / treeDepth[currDepth - 1].size();
  262.             float upperRowX = (client.x + innerBorder + upperRowStrideX / 2) - halfNodeW;
  263.             float p2_x{};
  264.             float p2_y = y + nodeHeight + strideY * (currDepth - 1);
  265.            
  266.             for (auto val : Set)
  267.             {
  268.                 int position{};
  269.                 for (auto other : treeDepth[currDepth - 1]) {
  270.                     if (tree[val].parent == other) { break; }
  271.                     position++;
  272.                 }
  273.  
  274.                 p2_x = upperRowX + halfNodeW + (upperRowStrideX * position);
  275.                 SDL_RenderDrawLine(renderer2, p1_x, p1_y, p2_x, p2_y);
  276.                 p1_x += strideX;
  277.             }
  278.         }
  279.  
  280.  
  281.         element.y += strideY;
  282.         currDepth++;
  283.     }
  284.  
  285.  
  286. }
  287.  
  288. Cell Union::getRandomOffSite() {
  289.     Cell cell{};
  290.     if (!offList.empty())
  291.     {
  292.         uniform_int_distribution<int> distribution(0, offList.size() - 1);
  293.         int randomID = distribution(engine);
  294.         int site = offList[randomID];
  295.         offList.erase(offList.begin() + randomID);
  296.         cell.row = site / cellsN;
  297.         cell.col = site % cellsN;
  298.     }
  299.     return cell;
  300. }
  301.  
  302. void Union::openSite()
  303. {
  304.     Cell cell = getRandomOffSite();
  305.     state[cell.row][cell.col] = true;
  306.  
  307.     if (cell.row == 0) {
  308.         startPoints.insert(cell.col);
  309.         uniform_int_distribution<int> c(20, 220);
  310.         colors[cell.col] = SDL_Color{ (Uint8)c(engine), (Uint8)c(engine), (Uint8)c(engine), 255 };
  311.     }
  312.  
  313.     connect(cell, Cell{ cell.row - 1, cell.col });//UP
  314.     connect(cell, Cell{ cell.row    , cell.col + 1 });//RIGHT
  315.     connect(cell, Cell{ cell.row + 1, cell.col });//DOWN
  316.     connect(cell, Cell{ cell.row    , cell.col - 1 });//LEFT
  317. }
  318.  
  319. void Union::connect(const Cell& first, const Cell& second)
  320. {
  321.     //first is expected to be valid
  322.     if (second.row >= 0 && second.row < cellsN &&
  323.         second.col >= 0 && second.col < cellsN)
  324.     {
  325.         if (state[second.row][second.col])
  326.         {
  327.             int firstID = (first.row * cellsN) + first.col;
  328.             int secondID = (second.row * cellsN) + second.col;
  329.  
  330.             int rootA = root(tree[firstID]).parent;
  331.             int rootB = root(tree[secondID]).parent;
  332.             auto tempPair = minmax(rootA, rootB, [&](int lhs, int rhs) {return treeSize[lhs] < treeSize[rhs]; });
  333.  
  334.             TreeNode& rootSmaller = tree[tempPair.first];
  335.             TreeNode& rootBigger = tree[tempPair.second];
  336.  
  337.  
  338.             int& rootSmallerID = rootSmaller.parent;
  339.             int& rootBiggerID = rootBigger.parent;
  340.  
  341.             if (rootSmallerID != rootBiggerID)
  342.             {
  343.                 if (startPoints.find(rootSmallerID) != startPoints.end())
  344.                 {
  345.                     startPoints.erase(rootSmallerID);
  346.                     startPoints.insert(rootBiggerID);
  347.  
  348.                     //if rootBigger has no color, then is not connected to the top. Keep smaller color.
  349.                     if (colors.find(rootBiggerID) == colors.end())
  350.                     {
  351.                         colors[rootBiggerID] = colors[rootSmallerID];
  352.                     }
  353.                 }
  354.  
  355.                 rootBigger.childrenList.push_back(rootSmallerID);
  356.  
  357.                 updateDepthMap(rootSmallerID, rootBiggerID);
  358.  
  359.                 rootSmallerID = rootBiggerID;
  360.                 treeSize[rootBiggerID] += treeSize[rootSmallerID];
  361.             }
  362.         }
  363.     }
  364. }
  365. void Union::updateDepthMap(int smallerNodeID, int biggerNodeID)
  366. {
  367.     int smallerNodeDepth = getIdDepth(smallerNodeID);
  368.     int biggerNodeDepth = getIdDepth(biggerNodeID);
  369.     treeDepth[smallerNodeDepth].erase(smallerNodeID);
  370.     treeDepth[biggerNodeDepth + 1].insert(smallerNodeID);
  371.  
  372.     _updateChildrenDepth(smallerNodeID, smallerNodeDepth + 1, biggerNodeDepth + 2);
  373. }
  374. void Union::_updateChildrenDepth(int smallerNodeID, int removeOffest, int AddOffset)
  375. {
  376.     for (int children : tree[smallerNodeID].childrenList)
  377.     {
  378.         // true = recursion -  false = Base Case
  379.         if (!tree[children].childrenList.empty())
  380.         {
  381.             _updateChildrenDepth(children, removeOffest + 1, AddOffset + 1);
  382.         }
  383.         treeDepth[removeOffest].erase(children);
  384.         treeDepth[AddOffset].insert(children);
  385.     }
  386. }
  387.  
  388. TreeNode& Union::root(const TreeNode& node)
  389. {
  390.     int self = node.parent;
  391.     while (tree[self].parent != self) { self = tree[self].parent; }
  392.     return tree[self];
  393. }
  394.  
  395. int Union::getIdDepth(int ID)
  396. {
  397.     int depth{};
  398.     for (auto&[key, Set] : treeDepth)
  399.     {
  400.         for (auto val : Set) {
  401.             if (val == ID) { return depth; }
  402.         }
  403.         depth++;
  404.     }
  405.     return depth;
  406. }
  407.  
  408. void Union::degubPrintUnionState()
  409. {
  410.     cout << "\n\n\n\n\n\n\n\n\n" << endl;
  411.     int size = tree.size();
  412.     for (size_t i = 0; i < size; i++)
  413.     {
  414.         if (!tree[i].childrenList.empty())
  415.         {
  416.             std::cout << "Child of " << setw(4) << i << " {" << flush;
  417.             int count{};
  418.             for (int child : tree[i].childrenList)
  419.             {
  420.                 cout << setw(4) << child << " " << flush;
  421.  
  422.                 if (count > 10) {
  423.                     count = 0;
  424.                     cout << "\n" << flush;
  425.                     cout << setw(15) << '.';
  426.                 }
  427.                 count++;
  428.             }
  429.             cout << setw(4) << "}" << endl;
  430.         }
  431.     }
  432. }
  433.  
  434. void Union::degubPrintDepthMap()
  435. {
  436.     int depth{};
  437.     for (auto&[Key, Set] : treeDepth)
  438.     {
  439.         int  count{};
  440.         cout << "Depth " << setw(2) << depth << "{" << flush;
  441.         for (int val : Set)
  442.         {
  443.             cout << setw(3) << val << " " << flush;
  444.             if (count > 10) {
  445.                 count = 0;
  446.                 cout << "\n" << flush;
  447.                 cout << setw(9) << '.';
  448.             }
  449.             count++;
  450.         }
  451.         cout << setw(4) << "}" << endl;
  452.         depth++;
  453.     }
  454.  
  455. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement