kruskals_generator.hxx
Go to the documentation of this file.
1 /*===========================================================================================================
2  *
3  * HUC - Hurna Core
4  *
5  * Copyright (c) Michael Jeulin-Lagarrigue
6  *
7  * Licensed under the MIT License, you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * https://github.com/Hurna/Hurna-Core/blob/master/LICENSE
11  *
12  * Unless required by applicable law or agreed to in writing, software distributed under the License is
13  * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and limitations under the License.
15  *
16  * The above copyright notice and this permission notice shall be included in all copies or
17  * substantial portions of the Software.
18  *
19  *=========================================================================================================*/
20 #ifndef MODULE_MAZE_KRUSKALSG_HXX
21 #define MODULE_MAZE_KRUSKALSG_HXX
22 
23 #include <DataStructures/grid.hxx>
24 
25 // STD
26 #include <random>
27 
28 namespace huc
29 {
30  namespace maze
31  {
51  {
52  public:
54  { uint64_t bucketId; }; // Precision should be above uint32_t * uint32_t - Limit on maze
55 
57  typedef Maze::Cell Cell;
58  typedef Maze::Edge Edge;
59  typedef Maze::Point Point;
60 
61  std::unique_ptr<Maze> operator()(const uint32_t width, const uint32_t height, const uint32_t seed = 0)
62  {
63  if (width < 1 || height < 1)
64  return nullptr;
65 
66  auto maze(std::unique_ptr<Maze>(new Maze(width, height)));
67  std::mt19937 mt(seed); // Random generator - Mersenne Twister algorithm
68  std::set<Edge> edges; // Big sac with all possible edges
69  std::vector<std::vector<std::shared_ptr<Cell>>> bucketCells; // List of all buckets
70 
71  // Fill big sac of edges and set the bucket ids to each cell
72  uint64_t nodeId = 0;
73  bucketCells.resize(height * width); // (height - 1) * width + (width - 1) * height);
74  for (uint32_t x = 0; x < maze->Width(); ++x)
75  for (uint32_t y = 0; y < maze->Height(); ++y, ++nodeId)
76  {
77  (*maze)[x][y]->info.bucketId = nodeId;
78  bucketCells[nodeId].push_back((*maze)[x][y]);
79 
80  // Insert Right edge
81  if (x + 1 < maze->Width())
82  edges.insert(Edge((*maze)[x][y], (*maze)[x+1][y]));
83  // Insert Bottom edge
84  if (y + 1 < maze->Height())
85  edges.insert(Edge((*maze)[x][y], (*maze)[x][y+1]));
86  }
87 
88  // While the set of edges is not empty randomly get an edge (connecting two cells):"
89  while (!edges.empty())
90  {
91  auto edgeIt = edges.begin();
92  std::advance(edgeIt, mt() % edges.size());
93  const auto firstBucket = edgeIt->first->info.bucketId;
94  const auto secondBucket = edgeIt->second->info.bucketId;
95 
96  // Add connection and merge buckets if not already in the same one
97  if (firstBucket != secondBucket)
98  {
99  maze->Connect(edgeIt->first, edgeIt->second);
100  MergeBucket(bucketCells, firstBucket, secondBucket);
101  }
102 
103  // Remove computed cell from the set
104  edges.erase(edgeIt);
105  }
106 
107  return maze;
108  }
109 
110  private:
118  static void MergeBucket(std::vector<std::vector<std::shared_ptr<Cell>>>& buckets,
119  uint32_t fromId, uint32_t ToId)
120  {
121  if (fromId == ToId)
122  return;
123 
124  // Set new bucket id for each melding cell
125  for (auto it = buckets[fromId].begin(); it != buckets[fromId].end(); ++it)
126  {
127  (*it)->info.bucketId = ToId;
128  buckets[ToId].push_back(*it);
129  }
130 
131  buckets[fromId].clear();
132  }
133  };
134  }
135 }
136 
137 #endif // MODULE_MAZE_KRUSKALSG_HXX
Edge struct is a convenient struct use to store two cell pointers connected by a link/edge.
Definition: grid.hxx:81
Point struct is a convenient struct use to represent a 2D point for a grid (index position)...
Definition: grid.hxx:56
std::unique_ptr< Maze > operator()(const uint32_t width, const uint32_t height, const uint32_t seed=0)
static void MergeBucket(std::vector< std::vector< std::shared_ptr< Cell >>> &buckets, uint32_t fromId, uint32_t ToId)