Gamedev Framework (gf)  0.6.0
A C++11 framework for 2D games
SpaceTree.h
1 /*
2  * Gamedev Framework (gf)
3  * Copyright (C) 2016-2017 Julien Bernard
4  *
5  * This software is provided 'as-is', without any express or implied
6  * warranty. In no event will the authors be held liable for any damages
7  * arising from the use of this software.
8  *
9  * Permission is granted to anyone to use this software for any purpose,
10  * including commercial applications, and to alter it and redistribute it
11  * freely, subject to the following restrictions:
12  *
13  * 1. The origin of this software must not be misrepresented; you must not
14  * claim that you wrote the original software. If you use this software
15  * in a product, an acknowledgment in the product documentation would be
16  * appreciated but is not required.
17  * 2. Altered source versions must be plainly marked as such, and must not be
18  * misrepresented as being the original software.
19  * 3. This notice may not be removed or altered from any source distribution.
20  *
21  * Part of this file comes from SFML, with the same license:
22  * Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
23  */
24 #ifndef GF_SPACE_TREE_H
25 #define GF_SPACE_TREE_H
26 
27 #include <functional>
28 #include <memory>
29 
30 #include "Portability.h"
31 #include "Random.h"
32 #include "Rect.h"
33 #include "Vector.h"
34 
35 namespace gf {
36 #ifndef DOXYGEN_SHOULD_SKIP_THIS
37 inline namespace v1 {
38 #endif
39 
40  /**
41  * @ingroup game
42  * @brief Binary space random partionning tree
43  *
44  * This class implements a random binary space partitioning tree. More
45  * precisely, this class is a node in the tree.
46  */
47  class GF_API SpaceTree {
48  public:
49  /**
50  * @brief A callback function for traversing the tree
51  *
52  * The function returns a boolean indicating if the traversal can
53  * continue.
54  */
55  using Callback = std::function<bool(const SpaceTree&)>;
56 
57  /**
58  * @brief Constructor
59  *
60  * @param area The area to split for this node
61  */
62  SpaceTree(const RectI& area);
63 
64  /**
65  * @brief Get the area of the node
66  *
67  * @return The area of the node
68  */
69  const RectI& getArea() const {
70  return m_area;
71  }
72 
73  /**
74  * @brief Get the level of the node in the tree
75  *
76  * The root of the tree is at level 0, its children at level 1, etc.
77  *
78  * @returns The level of the node
79  */
80  int getLevel() const {
81  return m_level;
82  }
83 
84  /**
85  * @brief Remove the children of the node
86  */
87  void removeChildren();
88 
89  /**
90  * @brief Split the node once
91  *
92  * This function may create two children if the conditions are met.
93  *
94  * @param random A random generator
95  * @param minSize The minimum size under which a node cannot be split
96  * @param maxRatio The maximum ratio between the width and height
97  * @returns True if the node has actually been split
98  */
99  bool splitOnce(Random& random, Vector2i minSize, float maxRatio = 1.5f);
100 
101  /**
102  * @brief Split a node recursively
103  *
104  * @param random A random generator
105  * @param levelMax The maximum level of a node
106  * @param minSize The minimum size under which a node cannot be split
107  * @param maxSize The maximum size over which a node must be split
108  * @param maxRatio The maximum ratio between the width and height
109  */
110  void splitRecursive(Random& random, int levelMax, Vector2i minSize, Vector2i maxSize, float maxRatio = 1.5f);
111 
112  /**
113  * @brief Check if a node is a leaf
114  *
115  * A leaf has no children.
116  *
117  * @returns True if the node is a leaf
118  */
119  bool isLeaf() const {
120  return !m_left && !m_right;
121  }
122 
123  /**
124  * @brief Get the left child
125  *
126  * @returns The left child if it exists or `nullptr`
127  */
128  const SpaceTree *getLeftChild() const {
129  return m_left.get();
130  }
131 
132  /**
133  * @brief Get the right child
134  *
135  * @returns The right child if it exists or `nullptr`
136  */
137  const SpaceTree *getRightChild() const {
138  return m_right.get();
139  }
140 
141  /**
142  * @brief Get the father of the node
143  *
144  * The root of the tree has no father.
145  *
146  * @returns The father of the node
147  */
148  const SpaceTree *getFather() const {
149  return m_father;
150  }
151 
152  /**
153  * @brief Check if the area of the node contains a position
154  *
155  * @param position The position to check
156  */
157  bool contains(Vector2i position) const;
158 
159  /**
160  * @brief Find the deepest node containing a position
161  *
162  * @param position The position to find
163  * @returns A node or `nullptr` if the position is outside the tree
164  */
165  const SpaceTree *find(Vector2i position) const;
166 
167  /**
168  * @brief Traverse the nodes in pre-order
169  *
170  * @param callback A function to call on each node
171  *
172  * @sa [Tree traversal - Wikipedia](https://en.wikipedia.org/wiki/Tree_traversal)
173  */
174  bool traversePreOrder(Callback callback) const;
175 
176  /**
177  * @brief Traverse the nodes in in-order
178  *
179  * @param callback A function to call on each node
180  *
181  * @sa [Tree traversal - Wikipedia](https://en.wikipedia.org/wiki/Tree_traversal)
182  */
183  bool traverseInOrder(Callback callback) const;
184 
185  /**
186  * @brief Traverse the nodes in post-order
187  *
188  * @param callback A function to call on each node
189  *
190  * @sa [Tree traversal - Wikipedia](https://en.wikipedia.org/wiki/Tree_traversal)
191  */
192  bool traversePostOrder(Callback callback) const;
193 
194  /**
195  * @brief Traverse the nodes in level-order
196  *
197  * Level-order is also known as breadth first search
198  *
199  * @param callback A function to call on each node
200  *
201  * @sa [Tree traversal - Wikipedia](https://en.wikipedia.org/wiki/Tree_traversal)
202  */
203  bool traverseLevelOrder(Callback callback) const;
204 
205  /**
206  * @brief Traverse the nodes in inverted level-order
207  *
208  * @param callback A function to call on each node
209  *
210  * @sa [Tree traversal - Wikipedia](https://en.wikipedia.org/wiki/Tree_traversal)
211  */
212  bool traverseInvertedLevelOrder(Callback callback) const;
213 
214  private:
215  enum class Split {
216  None,
217  Vertical,
218  Horizontal,
219  };
220 
221  RectI m_area;
222 
223  Split m_split;
224  int m_position;
225 
226  int m_level;
227 
228  std::unique_ptr<SpaceTree> m_left;
229  std::unique_ptr<SpaceTree> m_right;
230 
231  SpaceTree *m_father;
232  };
233 
234 #ifndef DOXYGEN_SHOULD_SKIP_THIS
235 }
236 #endif
237 }
238 
239 #endif // GF_SPACE_TREE_H
A random engine.
Definition: Random.h:43
bool splitOnce(Random &random, Vector2i minSize, float maxRatio=1.5f)
Split the node once.
const SpaceTree * getRightChild() const
Get the right child.
Definition: SpaceTree.h:137
void splitRecursive(Random &random, int levelMax, Vector2i minSize, Vector2i maxSize, float maxRatio=1.5f)
Split a node recursively.
The namespace for gf classes.
Definition: Action.h:34
bool traversePreOrder(Callback callback) const
Traverse the nodes in pre-order.
const SpaceTree * getFather() const
Get the father of the node.
Definition: SpaceTree.h:148
const SpaceTree * find(Vector2i position) const
Find the deepest node containing a position.
bool traverseInvertedLevelOrder(Callback callback) const
Traverse the nodes in inverted level-order.
void removeChildren()
Remove the children of the node.
bool traverseInOrder(Callback callback) const
Traverse the nodes in in-order.
bool isLeaf() const
Check if a node is a leaf.
Definition: SpaceTree.h:119
const RectI & getArea() const
Get the area of the node.
Definition: SpaceTree.h:69
#define GF_API
Definition: Portability.h:35
Binary space random partionning tree.
Definition: SpaceTree.h:47
bool traverseLevelOrder(Callback callback) const
Traverse the nodes in level-order.
int getLevel() const
Get the level of the node in the tree.
Definition: SpaceTree.h:80
bool contains(Vector2i position) const
Check if the area of the node contains a position.
SpaceTree(const RectI &area)
Constructor.
const SpaceTree * getLeftChild() const
Get the left child.
Definition: SpaceTree.h:128
bool traversePostOrder(Callback callback) const
Traverse the nodes in post-order.