]>
Commit | Line | Data |
---|---|---|
8356cc1d | 1 | //////////////////////////////////////////////////////////////////////////////// |
2 | // | |
3 | // Author: Artur Szostak | |
4 | // Email: artur@alice.phy.uct.ac.za | artursz@iafrica.com | |
5 | // | |
6 | //////////////////////////////////////////////////////////////////////////////// | |
7 | ||
8 | #ifndef dHLT_BUFFERS_QUAD_TREE_HPP | |
9 | #define dHLT_BUFFERS_QUAD_TREE_HPP | |
10 | ||
11 | #include "BasicTypes.hpp" | |
12 | #include "Utils.hpp" | |
13 | #include "new.hpp" | |
14 | ||
15 | namespace dHLT | |
16 | { | |
17 | namespace Buffers | |
18 | { | |
19 | ||
20 | ||
21 | template <typename DataType> | |
22 | class QuadTree | |
23 | { | |
24 | public: | |
25 | ||
26 | class Handler | |
27 | { | |
28 | public: | |
29 | ||
30 | /* Called when the specified node falls exactly within the region | |
31 | passed to ForAllOverlapping. | |
32 | */ | |
33 | inline void AddTo(QuadTree* /*node*/) {}; | |
34 | ||
35 | /* Called for the first node of a tree when the specified node has | |
36 | just been created and needs to be initialised. This method | |
37 | corresponds to FoundOverlapping except it is called when the node | |
38 | was not found and must be created. | |
39 | */ | |
40 | inline void InitialiseFirst(QuadTree* /*node*/) {}; | |
41 | ||
42 | /* Called when the specified node has just been created and needs to be | |
43 | initialised. The specified parent is the parent of the new node. This | |
44 | method corresponds to FoundOverlapping except it is called when the | |
45 | node was not found and must be created. | |
46 | */ | |
47 | inline void Initialise(QuadTree* /*node*/, QuadTree* /*parent*/) {}; | |
48 | ||
49 | /* Called when a node was found that partialy overlaps the region given | |
50 | to ForAllOverlapping. This method corresponds to Initialise(First) | |
51 | except it is called when the node has been found. | |
52 | */ | |
53 | inline void FoundOverlapping(QuadTree* /*node*/) {}; | |
54 | ||
55 | /* Called when a child node was found to be contained in the region | |
56 | given to the ForAllOverlapping method. | |
57 | */ | |
58 | inline void FoundContained(QuadTree* /*node*/) {}; | |
59 | }; | |
60 | ||
61 | ||
62 | QuadTree() | |
63 | { | |
64 | child[0][0] = child[0][1] = child[1][0] = child[1][1] = NULL; | |
65 | }; | |
66 | ||
67 | ||
68 | ~QuadTree() | |
69 | { | |
70 | // Perform a recursive delete of all children. | |
71 | if (child[0][0] != NULL) delete child[0][0]; | |
72 | if (child[0][1] != NULL) delete child[0][1]; | |
73 | if (child[1][0] != NULL) delete child[1][0]; | |
74 | if (child[1][1] != NULL) delete child[1][1]; | |
75 | }; | |
76 | ||
77 | ||
78 | /* Checks to see if the child node at grid position x, y on grid level 'level' | |
79 | exists or not. True is retured if it exists otherwise false is returned. | |
80 | */ | |
81 | bool Empty(const UInt x, const UInt y, const UChar level) const | |
82 | { | |
83 | return child[(x >> level) & 1][(y >> level) & 1] == NULL; | |
84 | }; | |
85 | ||
86 | ||
87 | /* Adds a new child node to this parent node at grid position x, y | |
88 | on grid level 'level'. | |
89 | */ | |
90 | QuadTree* Add(const UInt x, const UInt y, const UChar level) | |
91 | { | |
92 | Assert( Empty(x, y, level) ); | |
93 | QuadTree* newnode = new QuadTree(); | |
94 | child[(x >> level) & 1][(y >> level) & 1] = newnode; | |
95 | return newnode; | |
96 | }; | |
97 | ||
98 | ||
99 | /* Deletes the child subtree of this node at grid position x, y | |
100 | on grid level 'level'. | |
101 | */ | |
102 | void Remove(const UInt x, const UInt y, const UChar level) | |
103 | { | |
104 | Assert( not Empty(x, y, level) ); | |
105 | delete child[(x >> level) & 1][(y >> level) & 1]; | |
106 | child[(x >> level) & 1][(y >> level) & 1] = NULL; | |
107 | }; | |
108 | ||
109 | ||
110 | /* Gets the child of this node at grid position x, y on grid level 'level'. | |
111 | */ | |
112 | QuadTree* Child(const UInt x, const UInt y, const UChar level) | |
113 | { | |
114 | return child[(x >> level) & 1][(y >> level) & 1]; | |
115 | }; | |
116 | ||
117 | // Constant method version of Child above. | |
118 | const QuadTree* Child(const UInt x, const UInt y, const UChar level) const | |
119 | { | |
120 | return child[(x >> level) & 1][(y >> level) & 1]; | |
121 | }; | |
122 | ||
123 | ||
124 | /* Performs a depth first traversal to the specified level (tree depth), | |
125 | calling FoundOverlapping or Initialise method of the given event handler. | |
126 | Initialise is called if the node has to be created. | |
127 | When the given level is reached then the handlers AddTo method is called | |
128 | for all 4 nodes on that level, for grid positions: (left, bottom) ; | |
129 | (left+1, bottom) ; (left, bottom+1) ; (left+1, bottom+1). | |
130 | For all children nodes for levels i > 'level' the tree is traversed and | |
131 | FoundContained method is called for every child node found. | |
132 | */ | |
133 | template <class Handler> | |
134 | void ForAllOverlapping(const UInt left, const UInt bottom, const UChar level, Handler& handler) | |
135 | { | |
136 | UInt right = left + 1; | |
137 | UInt top = bottom + 1; | |
138 | ||
139 | QuadTree* current = this; | |
140 | ||
141 | UChar i; | |
142 | for (i = level; i > 0; i--) | |
143 | { | |
144 | if ( OnSameBranch(left, right, i) ) | |
145 | { | |
146 | if ( OnSameBranch(bottom, top, i) ) | |
147 | { | |
148 | if ( current->Empty(left, bottom, i) ) | |
149 | { | |
150 | QuadTree* parent = current; | |
151 | current = current->Add(left, bottom, i); | |
152 | handler.Initialise(current, parent); | |
153 | } | |
154 | else | |
155 | { | |
156 | current = current->Child(left, bottom, i); | |
157 | handler.FoundOverlapping(current); | |
158 | }; | |
159 | } | |
160 | else | |
161 | { | |
162 | ForAllOverlappingHorizontal(current, left, right, bottom, i, handler); | |
163 | ForAllOverlappingHorizontal(current, left, right, top, i, handler); | |
164 | return; | |
165 | }; | |
166 | } | |
167 | else | |
168 | { | |
169 | if ( OnSameBranch(bottom, top, i) ) | |
170 | { | |
171 | ForAllOverlappingVertical(current, left, bottom, top, i, handler); | |
172 | ForAllOverlappingVertical(current, right, bottom, top, i, handler); | |
173 | } | |
174 | else | |
175 | { | |
176 | ForAllOverlapping(current, left, bottom, i, handler); | |
177 | ForAllOverlapping(current, left, top, i, handler); | |
178 | ForAllOverlapping(current, right, bottom, i, handler); | |
179 | ForAllOverlapping(current, right, top, i, handler); | |
180 | }; | |
181 | return; | |
182 | }; | |
183 | }; | |
184 | ||
185 | QuadTree* leaf; | |
186 | if ( OnSameBranch(left, right, i) ) | |
187 | { | |
188 | leaf = current->Fetch(left, bottom, i, handler); | |
189 | handler.AddTo(leaf); | |
190 | leaf->Traverse(handler); | |
191 | if ( not OnSameBranch(bottom, top, i) ) | |
192 | { | |
193 | leaf = current->Fetch(left, top, i, handler); | |
194 | handler.AddTo(leaf); | |
195 | leaf->Traverse(handler); | |
196 | } | |
197 | } | |
198 | else | |
199 | { | |
200 | leaf = current->Fetch(left, bottom, i, handler); | |
201 | handler.AddTo(leaf); | |
202 | leaf->Traverse(handler); | |
203 | leaf = current->Fetch(right, bottom, i, handler); | |
204 | handler.AddTo(leaf); | |
205 | leaf->Traverse(handler); | |
206 | if ( not OnSameBranch(bottom, top, i) ) | |
207 | { | |
208 | leaf = current->Fetch(left, top, i, handler); | |
209 | handler.AddTo(leaf); | |
210 | leaf->Traverse(handler); | |
211 | leaf = current->Fetch(right, top, i, handler); | |
212 | handler.AddTo(leaf); | |
213 | leaf->Traverse(handler); | |
214 | }; | |
215 | }; | |
216 | }; | |
217 | ||
218 | ||
219 | /* | |
220 | template <class Function> | |
221 | void Traverse(Function process) | |
222 | { | |
223 | QuadTree* stack[14*4]; | |
224 | QuadTree** bottom = &stack[14*4]; | |
225 | QuadTree** top = &stack[14*4-1]; | |
226 | *top = this; | |
227 | do | |
228 | { | |
229 | QuadTree* current = *top++; // pop the stack; | |
230 | (*process)(current); | |
231 | // Push the children of the current node onto the stack. | |
232 | if (current->child[0][0] != NULL) *(--top) = current->child[0][0]; | |
233 | if (current->child[0][1] != NULL) *(--top) = current->child[0][1]; | |
234 | if (current->child[1][0] != NULL) *(--top) = current->child[1][0]; | |
235 | if (current->child[1][1] != NULL) *(--top) = current->child[1][1]; | |
236 | } | |
237 | while (top != bottom); | |
238 | }; | |
239 | */ | |
240 | ||
241 | /* Traverses the whole sub tree stopping at every child and calling the | |
242 | FoundContained method of the given event handler. | |
243 | */ | |
244 | template <class Handler> | |
245 | void Traverse(Handler& handler) | |
246 | { | |
247 | if (child[0][0] != NULL) | |
248 | { | |
249 | handler.FoundContained(child[0][0]); | |
250 | child[0][0]->Traverse(handler); | |
251 | }; | |
252 | if (child[0][1] != NULL) | |
253 | { | |
254 | handler.FoundContained(child[0][1]); | |
255 | child[0][1]->Traverse(handler); | |
256 | }; | |
257 | if (child[1][0] != NULL) | |
258 | { | |
259 | handler.FoundContained(child[1][0]); | |
260 | child[1][0]->Traverse(handler); | |
261 | }; | |
262 | if (child[1][1] != NULL) | |
263 | { | |
264 | handler.FoundContained(child[1][1]); | |
265 | child[1][1]->Traverse(handler); | |
266 | }; | |
267 | }; | |
268 | ||
269 | ||
270 | /* Finds the child that corresponds to the x, y grid position on the | |
271 | given grid level. (Level can also be though of as tree depth). | |
272 | */ | |
273 | QuadTree* Find(const UInt x, const UInt y, const UChar level) | |
274 | { | |
275 | QuadTree* current = this; | |
276 | for (Char i = level; i >= 0; i--) | |
277 | { | |
278 | current = current->Child(x, y, i); | |
279 | if (current == NULL) break; | |
280 | }; | |
281 | return current; | |
282 | }; | |
283 | ||
284 | // The constant version of Find above. | |
285 | const QuadTree* Find(const UInt x, const UInt y, const UChar level) const | |
286 | { | |
287 | QuadTree* current = this; | |
288 | for (Char i = level; i >= 0; i--) | |
289 | { | |
290 | current = current->Child(x, y, i); | |
291 | if (current == NULL) break; | |
292 | }; | |
293 | return current; | |
294 | }; | |
295 | ||
296 | ||
297 | DataType data; // The data stored in the tree. | |
298 | ||
299 | private: | |
300 | ||
301 | inline bool OnSameBranch(const UInt a, const UInt b, const UChar level) const | |
302 | { | |
303 | return a >> level == b >> level; | |
304 | }; | |
305 | ||
306 | ||
307 | template <class Handler> | |
308 | inline QuadTree* Fetch(const UInt x, const UInt y, const UChar level, Handler& handler) | |
309 | { | |
310 | QuadTree* node; | |
311 | if ( Empty(x, y, level) ) | |
312 | { | |
313 | node = Add(x, y, level); | |
314 | handler.Initialise(node, this); // use this as the parent | |
315 | } | |
316 | else | |
317 | { | |
318 | node = Child(x, y, level); | |
319 | handler.FoundContained(node); | |
320 | }; | |
321 | return node; | |
322 | }; | |
323 | ||
324 | ||
325 | template <class Handler> | |
326 | inline void ForAllOverlapping(QuadTree* current, const UInt x, const UInt y, const UChar level, Handler& handler) | |
327 | { | |
328 | UChar i; | |
329 | for (i = level; i > 0; i--) | |
330 | { | |
331 | if ( current->Empty(x, y, i) ) | |
332 | { | |
333 | QuadTree* parent = current; | |
334 | current = current->Add(x, y, i); | |
335 | handler.Initialise(current, parent); | |
336 | } | |
337 | else | |
338 | { | |
339 | current = current->Child(x, y, i); | |
340 | handler.FoundOverlapping(current); | |
341 | }; | |
342 | }; | |
343 | ||
344 | QuadTree* leaf = current->Fetch(x, y, i, handler); | |
345 | handler.AddTo(leaf); | |
346 | leaf->Traverse(handler); | |
347 | }; | |
348 | ||
349 | ||
350 | template <class Handler> | |
351 | inline void ForAllOverlappingHorizontal( | |
352 | QuadTree* current, const UInt left, const UInt right, const UInt bottom, const UChar level, Handler& handler | |
353 | ) | |
354 | { | |
355 | UChar i; | |
356 | for (i = level; i > 0; i--) | |
357 | { | |
358 | if ( OnSameBranch(left, right, i) ) | |
359 | { | |
360 | if ( current->Empty(left, bottom, i) ) | |
361 | { | |
362 | QuadTree* parent = current; | |
363 | current = current->Add(left, bottom, i); | |
364 | handler.Initialise(current, parent); | |
365 | } | |
366 | else | |
367 | { | |
368 | current = current->Child(left, bottom, i); | |
369 | handler.FoundOverlapping(current); | |
370 | }; | |
371 | } | |
372 | else | |
373 | { | |
374 | ForAllOverlapping(current, left, bottom, i, handler); | |
375 | ForAllOverlapping(current, right, bottom, i, handler); | |
376 | return; | |
377 | }; | |
378 | }; | |
379 | ||
380 | QuadTree* leaf = current->Fetch(left, bottom, i, handler); | |
381 | handler.AddTo(leaf); | |
382 | leaf->Traverse(handler); | |
383 | if ( not OnSameBranch(left, right, i) ) | |
384 | { | |
385 | leaf = current->Fetch(right, bottom, i, handler); | |
386 | handler.AddTo(leaf); | |
387 | leaf->Traverse(handler); | |
388 | }; | |
389 | }; | |
390 | ||
391 | ||
392 | template <class Handler> | |
393 | inline void ForAllOverlappingVertical( | |
394 | QuadTree* current, const UInt left, const UInt bottom, const UInt top, const UChar level, Handler& handler | |
395 | ) | |
396 | { | |
397 | UChar i; | |
398 | for (i = level; i > 0; i--) | |
399 | { | |
400 | if ( OnSameBranch(bottom, top, i) ) | |
401 | { | |
402 | if ( current->Empty(left, bottom, i) ) | |
403 | { | |
404 | QuadTree* parent = current; | |
405 | current = current->Add(left, bottom, i); | |
406 | handler.Initialise(current, parent); | |
407 | } | |
408 | else | |
409 | { | |
410 | current = current->Child(left, bottom, i); | |
411 | handler.FoundOverlapping(current); | |
412 | }; | |
413 | } | |
414 | else | |
415 | { | |
416 | ForAllOverlapping(current, left, bottom, i, handler); | |
417 | ForAllOverlapping(current, left, top, i, handler); | |
418 | return; | |
419 | }; | |
420 | }; | |
421 | ||
422 | QuadTree* leaf = current->Fetch(left, bottom, i, handler); | |
423 | handler.AddTo(leaf); | |
424 | leaf->Traverse(handler); | |
425 | if ( not OnSameBranch(bottom, top, i) ) | |
426 | { | |
427 | leaf = current->Fetch(left, top, i, handler); | |
428 | handler.AddTo(leaf); | |
429 | leaf->Traverse(handler); | |
430 | }; | |
431 | }; | |
432 | ||
433 | ||
434 | QuadTree* child[2][2]; | |
435 | }; | |
436 | ||
437 | ||
438 | } // Buffers | |
439 | } // dHLT | |
440 | ||
441 | #endif // dHLT_BUFFERS_QUAD_TREE_HPP |