vrecko
virtual reality framework
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
DynamicTree.h
Go to the documentation of this file.
1 #ifndef DYNAMICTREE_H
2 #define DYNAMICTREE_H
3 
4 
5 template <class _Type>
6 class DynamicTree;
7 
8 
9 template <class _Type>
10 class DynTreeNode {
11 public:
12 // LPVOID lpUserData;
13  _Type *lpParent, *lpChild, *lpNext, *lpPrev; // pointers to the nearest objects
14  DynamicTree<_Type> *tree; // pointer to the owner tree
15 
16  unsigned long GetDepth(); // = get number of lpParent->lpParent->lpParent->... (0 for the root)
17 };
18 
19 
20 // In fact, it is not tree but it can be multiple trees (forest).
21 template <class _Type>
22 class DynamicTree {
23 public:
24 
27 
28  DynamicTree (void);
29  virtual ~DynamicTree (void);
30 
31  inline unsigned long GetCount (void) { return dwCount; };
32 
33  bool AddNode (_Type *lpParent, _Type *lpNode);
34  // !! The node will be inserted BEFORE any other children of the parent node !!
35  // [lpParent] == NULL => this will be the root node (or sibling to the root node)
36  bool AddNodeLast (_Type *lpParent, _Type *lpNode);
37  // !! The node will be inserted AFTER any other children of the parent node !!
38  // This function is slower than AddNode().
39  // [lpParent] == NULL => this will be the root node (or sibling to the root node)
40  bool InsertNode (_Type *lpParent, _Type *lpPrevSibling, _Type *lpNode);
41  // The node will be inserted AFTER the [lpPrevSibling]
42  // [lpParent] == NULL => this will be the root node (or sibling to the root node)
43  // [lpPrevSibling] == NULL => insert as a first child
44  bool DeleteNode (_Type *lpNode, bool bCallDelete = false);
45  // Deletes also subtree.
46  // If lpNode is NULL whole tree will be deleted.
47 
48  inline _Type* GetRoot (void) { return lpRoot; }
49 
50  bool Clear (bool bCallDelete = false);
51 
52 protected:
53  _Type *lpRoot;
54  unsigned long dwCount;
55 };
56 
57 
58 
59 // These flags are mostly mutualy exclusive:
60 #define DTI_EXCLUDEROOT 0x00000001 // root will be excluded from traversing
61 #define DTI_ONLYLEAVES 0x00000002 // traverse only leaves
62 #define DTI_ONELAYERTRAVERSAL 0x00000004
63  // Can not be specified together with DTI_ONLYLEAVES
64  // if DTI_EXCLUDEROOT is also specified:
65  // traverse root's nearest children
66  // if DTI_EXCLUDEROOT is NOT specified:
67  // traverse root and it's siblings
68 
69 
70 template <class _Type>
71 class DynamicTreeIterator { // depth-first style iterating through the tree
72 public:
73  DynamicTreeIterator (void) { cbNodeAllowed = NULL; cbSubTreeAllowed = NULL; bStarting = false; Reset (); }
74  inline void Reset (void) { nodePtr = (_Type*)0; tree = NULL; }
75 
78 
79  /* [dwFlags] is combination of DTI_*
80  [lpTravStart] is starting node to traverse form
81  (it will be something like temporary root).
82  WARNING: lpTravStart can be NULL ONLY IF SetTree is called before. */
83  void Start (_Type *lpTravStart, unsigned long dwFlags);
84  inline bool IsFinished (void) { return (0 == nodePtr); }
85 
86  inline bool operator== (
87  const DynamicTreeIterator<_Type>& iter)
88  {
89  return (nodePtr == iter.nodePtr);
90  };
91  inline friend bool operator!= (
92  const DynamicTreeIterator<_Type>& iter1,
93  const DynamicTreeIterator<_Type>& iter2)
94  {
95  return (iter1.nodePtr != iter2.nodePtr);
96  };
99 
100  _Type* GetNode (void) { return (nodePtr); };
101 
102  // This is only necessary when starting from the NULL object.
103  void SetTree (DynamicTree<_Type> *_tree) { tree = _tree; };
104 
105 // DynTreeNode& operator* (void) { return (*nodePtr); };
106 // DynTreeNode& operator-> (void) { return (*nodePtr); };
107 
108 protected:
110  _Type *nodePtr;
111  _Type *nodeStart;
112  unsigned long dwFlags;
115  bool bStarting; // The first node is to be found
116 
117  inline bool IsNodeAllowed (_Type *node)
118  {
119  if ((dwFlags & DTI_EXCLUDEROOT) && (node == nodeStart))
120  return false;
121  if ((dwFlags & DTI_ONLYLEAVES) && (node->lpChild))
122  return false;
123  if (!cbNodeAllowed)
124  return true;
125  return cbNodeAllowed (node);
126  };
127 
128  inline bool IsSubTreeAllowed (_Type *node)
129  {
130  if (!cbSubTreeAllowed)
131  return true;
132  return cbSubTreeAllowed (node);
133  };
134 };
135 
136 
137 template <class _Type>
139 {
140  _Type *tmp = lpParent;
141  unsigned long dw = 0;
142  while (tmp) {
143  tmp = tmp->lpParent;
144  dw++;
145  }
146  return dw;
147 }
148 
149 
150 template <class _Type>
152 {
153  lpRoot = NULL;
154  dwCount = 0;
155 }
156 
157 template <class _Type>
159 {
160  DeleteNode (NULL);
161 }
162 
163 
164 template <class _Type>
165 bool DynamicTree<_Type>::AddNode (_Type *lpParent, _Type *lpNode)
166 {
167  lpNode->tree = this;
168 
169  lpNode->lpParent = lpParent;
170  lpNode->lpChild = NULL;
171  lpNode->lpPrev = NULL;
172 
173  if (lpParent) {
174  lpNode->lpNext = lpParent->lpChild;
175  if (lpParent->lpChild)
176  lpParent->lpChild->lpPrev = lpNode;
177  lpParent->lpChild = lpNode;
178  } else {
179  lpNode->lpNext = lpRoot;
180  if (lpRoot)
181  lpRoot->lpPrev = lpNode;
182  lpRoot = lpNode;
183  }
184 
185  dwCount++;
186  return true;
187 }
188 
189 
190 template <class _Type>
191 bool DynamicTree<_Type>::AddNodeLast (_Type *lpParent, _Type *lpNode)
192 {
193  lpNode->tree = this;
194 
195  lpNode->lpParent = lpParent;
196  lpNode->lpChild = NULL;
197  lpNode->lpPrev = NULL;
198  lpNode->lpNext = NULL;
199 
200  if (lpParent) {
201  if (!lpParent->lpChild) {
202  lpParent->lpChild = lpNode;
203  } else {
204  _Type *child = lpParent->lpChild;
205  while (child->lpNext)
206  child = child->lpNext;
207  child->lpNext = lpNode;
208  lpNode->lpPrev = child;
209  }
210  } else {
211  if (!lpRoot) {
212  lpRoot = lpNode;
213  } else {
214  _Type *child = lpRoot;
215  while (child->lpNext)
216  child = child->lpNext;
217  child->lpNext = lpNode;
218  lpNode->lpPrev = child;
219  }
220  }
221 
222  dwCount++;
223  return true;
224 }
225 
226 
227 template <class _Type>
228 bool DynamicTree<_Type>::InsertNode (_Type *lpParent, _Type *lpPrevSibling, _Type *lpNode)
229 {
230  if (NULL == lpPrevSibling)
231  return AddNode (lpParent, lpNode);
232 
233  lpNode->tree = this;
234 
235  lpNode->lpParent = lpParent;
236  lpNode->lpChild = NULL;
237  lpNode->lpPrev = lpPrevSibling;
238  lpNode->lpNext = lpPrevSibling->lpNext;
239  if (lpPrevSibling->lpNext)
240  lpPrevSibling->lpNext->lpPrev = lpNode;
241  lpPrevSibling->lpNext = lpNode;
242 
243  dwCount++;
244  return true;
245 }
246 
247 
248 template <class _Type>
249 bool DynamicTree<_Type>::DeleteNode (_Type *lpNode, bool bCallDelete)
250 {
251  if (lpNode) {
252  if (lpNode->lpParent) {
253  if (lpNode->lpParent->lpChild == lpNode)
254  lpNode->lpParent->lpChild = lpNode->lpNext;
255  }
256 
257  while (lpNode->lpChild) {
258  if (!DeleteNode (lpNode->lpChild, bCallDelete))
259  return false;
260  }
261 
262  if (lpNode->lpPrev)
263  lpNode->lpPrev->lpNext = lpNode->lpNext;
264 
265  if (lpNode->lpNext)
266  lpNode->lpNext->lpPrev = lpNode->lpPrev;
267 
268  if (lpNode == lpRoot)
269  lpRoot = lpNode->lpNext;
270 
271  lpNode->tree = NULL;
272 
273  if (bCallDelete)
274  delete lpNode;
275 
276  dwCount--;
277  } else {
278  while (lpRoot) {
279  if (!DeleteNode (lpRoot, bCallDelete))
280  return false;
281  }
282 
283  lpRoot = NULL;
284  }
285 
286  return true;
287 }
288 
289 
290 template <class _Type>
291 bool DynamicTree<_Type>::Clear (bool bCallDelete)
292 {
293  return DeleteNode (NULL, bCallDelete);
294 }
295 
296 
297 template <class _Type>
298 void DynamicTreeIterator<_Type>::Start (_Type *_lpTravStart, unsigned long _dwFlags)
299 {
300  nodeStart = _lpTravStart;
301  dwFlags = _dwFlags;
302  nodePtr = NULL;
303 
304  bStarting = true;
305 
306  if (_lpTravStart) {
307  if (dwFlags & DTI_EXCLUDEROOT)
308  nodePtr = nodeStart->lpChild;
309  else if (nodeStart)
310  nodePtr = nodeStart;
311  } else {
312  if (tree)
313  nodePtr = tree->GetRoot ();
314  }
315 
316  ++*this;
317 
318  bStarting = false;
319 }
320 
321 
322 template <class _Type>
324 {
325  if (!bStarting && !nodePtr)
326  return *this;
327 
328  if (dwFlags & DTI_ONELAYERTRAVERSAL) {
329  if (!bStarting)
330  nodePtr = nodePtr->lpNext;
331 
332  while (nodePtr && !IsNodeAllowed (nodePtr))
333  nodePtr = nodePtr->lpNext;
334 
335  return *this;
336  }
337 
338  unsigned long dwState = 1;
339 
340  while (true) {
341  if (!bStarting) {
342  if (nodePtr->lpChild && IsSubTreeAllowed (nodePtr))
343  nodePtr = nodePtr->lpChild;
344  else {
345  while (nodePtr && !nodePtr->lpNext) {
346  if (nodePtr == nodeStart) {
347  nodePtr = NULL;
348  break;
349  }
350  nodePtr = nodePtr->lpParent;
351  }
352  if (nodePtr == nodeStart) {
353  nodePtr = NULL;
354  break;
355  }
356  if (nodePtr)
357  nodePtr = nodePtr->lpNext;
358  }
359  }
360 
361  if (!nodePtr)
362  break;
363 
364  if (IsNodeAllowed (nodePtr))
365  break;
366 
367  bStarting = false;
368  }
369 
370  return *this;
371 }
372 
373 
374 template <class _Type>
376 {
377  DynamicTreeIterator<_Type> *tmp = this;
378  ++*this;
379  return (*tmp);
380 }
381 
382 
383 #endif