VR-Forces 4.2 Class Documentation
octree.h
Go to the documentation of this file.
1 /*******************************************************************************
2 ** Copyright (c) 2008 MAK Technologies, Inc.
3 ** All rights reserved.
4 *******************************************************************************/
5 /*******************************************************************************
6 ** $RCSfile: octree.h,v $ $Revision: 1.4 $ $State: Exp $
7 *******************************************************************************/
8 
11 
31 
32 #ifndef octree_H_
33 #define octree_H_
34 
35 #include <stdarg.h>
36 #include <map>
37 #include <vector>
38 
39 #include <cmdLine/cmdStdOutput.h>
40 
42 #include "geometry/tdbextent.h"
43 
44 template<class T> class DtOctreeNode;
45 
48 
49 #define OCTREE_DEBUG 0
50 
51 #if OCTREE_DEBUG
52 
53 static int octree_debug_level = 0;
54 
56 
57 static void DEBUG(const char* fmt, ...)
58 {
59  char buffer[8192];
60  va_list ap;
61  va_start(ap, fmt);
62  vsprintf(buffer, fmt, ap);
63  va_end(ap);
64 
65  DtInfo("OCT %*s%s\n", octree_debug_level*2, "", buffer);
66 }
67 
68 # define DEBUG_PUSH do { octree_debug_level++; } while(0)
69 # define DEBUG_POP do { octree_debug_level--; } while(0)
70 #else
71 
72 static inline void DEBUG(const char* fmt, ...)
73 { }
74 
75 # define DEBUG_PUSH do { } while(0)
76 # define DEBUG_POP do { } while(0)
77 #endif
78 
79 #define EXT_FMT "[%lf, %lf, %lf] - [%lf, %lf, %lf]"
80 #define EXT_ARGS(x) (x).minX(), (x).minY(), (x).minZ(), (x).maxX(), (x).maxY(), (x).maxZ()
81 #define OBJ_ARGS(x) ((const char*) (x)->objectName())
82 
88 
89 template<class T> class DtOctreeMember
90 {
91 public:
92  DtOctreeMember(T* object, const DtExtent& extent)
93  : myObject(object)
94  , myExtent(extent)
95  , boundNode(0)
96  {
97  }
98 
100  void bind(DtOctreeNode<T>* node);
101 
103  void unbind();
104 
105 public:
108 
110  DtExtent myExtent;
111 
114 
117  typename std::list<DtOctreeMember*>::iterator boundIterator;
118 };
119 
146 
147 template<class T> class DtOctreeNode
148 {
149 protected:
150 
151  typedef std::list<DtOctreeMember<T>*> MemberContainer;
152  typedef typename std::list<DtOctreeMember<T>*>::iterator MemberIterator;
153 
155  static const int NUM_BRANCHES = 8;
156 
158  static const int MAX_CHILD_MEMBERS = 10;
159 
161  DtOctreeNode(const DtExtent &region)
162  : myRegion(region)
163  , myCenter(region.center())
164  , myChildren(0)
165  {
166  DEBUG("Create node " EXT_FMT, EXT_ARGS(region));
167  }
168 
171  {
172  DEBUG("Destroy node " EXT_FMT, EXT_ARGS(myRegion));
173  DEBUG_PUSH;
174 
175  if (myChildren)
176  {
177  for(int i=0; i<NUM_BRANCHES; i++)
178  delete myChildren[i];
179  }
180  delete[] myChildren;
181 
182  DEBUG_POP;
183  }
184 
193 
194  virtual void visitObjects(const DtExtent& extent, DtSpatialSelectionFunctor &callback)
195  {
196  DEBUG(EXT_FMT "::visit(" EXT_FMT ", cb)", EXT_ARGS(myRegion), EXT_ARGS(extent));
197  DEBUG_PUSH;
198 
199  MemberIterator iter, end;
200 
201  for(iter = myMembers.begin(), end = myMembers.end(); iter != end; ++iter)
202  {
203  DEBUG("Member %s " EXT_FMT, OBJ_ARGS((*iter)->myObject), EXT_ARGS((*iter)->myExtent));
204  callback((*iter)->myObject);
205  }
206 
207  if (myChildren)
208  {
209  int mask = intersectionMask(extent);
210  for(int i=0; i<NUM_BRANCHES; i++)
211  {
212  if (myChildren[i] && (mask & (1<<i)))
213  myChildren[i]->visitObjects(extent, callback);
214  }
215  }
216 
217  DEBUG_POP;
218  }
219 
221  virtual void addMember(DtOctreeMember<T>* member)
222  {
223  DEBUG(EXT_FMT "::addMember(%s)", EXT_ARGS(myRegion), OBJ_ARGS(member->myObject));
224  DEBUG_PUSH;
225 
226 #if OCTREE_DEBUG
227  if (!myRegion.contains(member->myExtent))
228  {
229  DEBUG("FAIL! " EXT_FMT " does not contain " EXT_FMT, EXT_ARGS(myRegion), EXT_ARGS(member->myExtent));
230  }
231 #endif
232 
233  if (myChildren)
234  {
235  int mask = intersectionMask(member->myExtent);
236  int childIndex = childIndexFor(mask);
237 
238  if (childIndex == -1) {
239  DEBUG("add as member (children, but won't fit)");
240  member->bind(this);
241  } else {
242  addMemberToChild(member, childIndex);
243  }
244  } else {
245  DEBUG("add as child member (not enough child members yet)");
246 
247  member->bind(this);
248 
250  {
251  split();
252  }
253  }
254 
255  DEBUG_POP;
256  }
257 
261  {
262  DEBUG(EXT_FMT "::coalesceEmptyChildren()", EXT_ARGS(myRegion));
263  DEBUG_PUSH;
264 
265  bool retVal = (myMembers.size() == 0);
266 
267  if (myChildren)
268  {
269  for(int i=0; i<NUM_BRANCHES; i++)
270  {
271  if (myChildren[i])
272  {
274  {
275  DEBUG("Deleting child %d\n", i);
276  delete myChildren[i];
277  myChildren[i] = 0;
278  } else {
279  retVal = false;
280  }
281  }
282  }
283  }
284 
285  DEBUG_POP;
286 
287  return retVal;
288  }
289 
292  {
293  int retVal = 0;
294 
295  MemberIterator iter, end;
296  for(iter = myMembers.begin(), end = myMembers.end(); iter != end; ++iter)
297  {
298  if (childIndexFor(intersectionMask((*iter)->myExtent)) != -1)
299  {
300  retVal++;
301  }
302  }
303 
304  return retVal;
305  }
306 
312  int intersectionMask(const DtExtent &extent) const
313  {
314  int result = 0xff;
315 
316  if (extent.minX() >= myCenter.x())
317  result &= 0xf0;
318  if (extent.maxX() <= myCenter.x())
319  result &= 0x0f;
320 
321  if (extent.minY() >= myCenter.y())
322  result &= 0xcc;
323  if (extent.maxY() <= myCenter.y())
324  result &= 0x33;
325 
326  if (extent.minZ() >= myCenter.z())
327  result &= 0xaa;
328  if (extent.maxZ() <= myCenter.z())
329  result &= 0x55;
330 
331  if (result == 0)
332  {
333  DtWarn("Can't happen! Octree intersection mask is 0!");
334  }
335 
336  return result;
337  }
338 
342  int childIndexFor(int mask)
343  {
344  if (!mask || (mask & (mask-1)))
345  {
346  return -1;
347  }
348 
349  int childIndex;
350  for(childIndex=0; childIndex<NUM_BRANCHES; childIndex++)
351  {
352  if (mask & (1<<childIndex))
353  return childIndex;
354  }
355 
356  DtWarn("Can't happen: no valid child index in octree code.");
357  return -1;
358  }
359 
363 
364  void addMemberToChild(DtOctreeMember<T>* member, int childIndex)
365  {
366  DEBUG(EXT_FMT "::addMemberToChild(%s, %d)", EXT_ARGS(myRegion), OBJ_ARGS(member->myObject), childIndex);
367  DEBUG_PUSH;
368 
369  if (myChildren[childIndex] == 0)
370  {
371  DtPoint childCorner;
372 
373  if (childIndex & 4)
374  childCorner.setX(myRegion.maxX());
375  else
376  childCorner.setX(myRegion.minX());
377 
378  if (childIndex & 2)
379  childCorner.setY(myRegion.maxY());
380  else
381  childCorner.setY(myRegion.minY());
382 
383  if (childIndex & 1)
384  childCorner.setZ(myRegion.maxZ());
385  else
386  childCorner.setZ(myRegion.minZ());
387 
388  myChildren[childIndex] = new DtOctreeNode(DtExtent(childCorner, myCenter));
389  }
390 
391  myChildren[childIndex]->addMember(member);
392 
393  DEBUG_POP;
394  }
395 
398 
399  void split()
400  {
401  DEBUG(EXT_FMT "::split()", EXT_ARGS(myRegion));
402  DEBUG_PUSH;
403 
405 
406  for(int i=0; i<NUM_BRANCHES; i++)
407  {
408  myChildren[i] = 0;
409  }
410 
411  MemberIterator iter, next, end;
412  for(iter = myMembers.begin(), end = myMembers.end(); iter != end; iter = next)
413  {
414  next = iter;
415  ++next;
416 
417  DtOctreeMember<T>* member = *iter;
418  int childIndex = childIndexFor(intersectionMask(member->myExtent));
419 
420  if (childIndex != -1)
421  {
422  member->unbind();
423  addMemberToChild(member, childIndex);
424  }
425  }
426 
427  DEBUG_POP;
428  }
429 
431  const DtExtent myRegion;
432 
434  const DtPoint myCenter;
435 
440 
444 
445  template<class U> friend class DtOctree;
446  template<class U> friend class DtOctreeMember;
447  template<class U> friend class DtOctreeDebugger;
448 };
449 
461 
462 template<class T> class DtOctree
463 {
464 public:
465 
467  typedef std::map<T*, DtOctreeMember<T>*> MemberContainer;
468  typedef typename std::map<T*, DtOctreeMember<T>*>::iterator MemberIterator;
469 
470  typedef std::list<T*> OutsideAreaContainer;
471  typedef typename std::list<T*>::iterator OutsideAreaIterator;
472 
474  DtOctree(const DtExtent &region)
475  {
476  myRootNode = new DtOctreeNode<T>(region);
477  }
478 
480  virtual ~DtOctree()
481  {
482  delete myRootNode;
483 
484  MemberIterator iter, end;
485  for(iter = myMemberMap.begin(), end = myMemberMap.end(); iter != end; ++iter)
486  {
487  delete (*iter).second;
488  }
489  }
490 
494  virtual void visitObjects(const DtExtent& extent, DtSpatialSelectionFunctor &callback)
495  {
496  if (myRootNode->myRegion.intersects(extent))
497  {
498  myRootNode->visitObjects(extent, callback);
499  }
500 
501  OutsideAreaIterator iter, end;
502  for(iter = myObjectsOutsideArea.begin(), end = myObjectsOutsideArea.end(); iter != end; ++iter)
503  {
504  callback(*iter);
505  }
506  }
507 
509  virtual void addObject(T* object, const DtExtent& extent)
510  {
511  DEBUG("DtOctree::addObject(%s, " EXT_FMT ")", OBJ_ARGS(object), EXT_ARGS(extent));
512  DEBUG_PUSH;
513 
514  if (myRootNode->myRegion.contains(extent))
515  {
516  DtOctreeMember<T>* newMember = new DtOctreeMember<T>(object, extent);
517  myRootNode->addMember(newMember);
518  myMemberMap[object] = newMember;
519  } else {
520  DtWarn("Member %s (" EXT_FMT ") added outside octree (" EXT_FMT ")",
521  OBJ_ARGS(object), EXT_ARGS(extent), EXT_ARGS(myRootNode->myRegion));
522  myObjectsOutsideArea.push_back(object);
523  }
524 
525  DEBUG_POP;
526  }
527 
529  virtual void removeObject(T* object)
530  {
531  DEBUG("DtOctree::removeObject(%s)", OBJ_ARGS(object));
532  DEBUG_PUSH;
533 
534  MemberIterator iter;
535  iter = myMemberMap.find(object);
536  if (iter != myMemberMap.end())
537  {
538  DtOctreeMember<T>* member = (*iter).second;
539  member->unbind();
540  myMemberMap.erase(iter);
541  delete member;
542  } else if (!removeObjectOutsideArea(object)) {
546 
547  //DtWarn("Tried to remove %s from octree, but couldn't find!\n", OBJ_ARGS(object));
548  }
549 
550  DEBUG_POP;
551  }
552 
558  virtual void updatePositions()
559  {
560  MemberIterator iter, end;
561 
562  for(iter = myMemberMap.begin(), end = myMemberMap.end(); iter != end; ++iter)
563  {
564  T* object = (*iter).first;
565  DtOctreeMember<T>* member = (*iter).second;
566 
567  member->myExtent = object->extent();
568 
569  if (!myRootNode->myRegion.contains(member->myExtent))
570  {
572 
573  DtWarn("Object %s (" EXT_FMT ") moving outside octree (" EXT_FMT ")",
574  OBJ_ARGS(object), EXT_ARGS(member->myExtent), EXT_ARGS(myRootNode->myRegion));
575  removeObject(object);
576  myObjectsOutsideArea.push_back(object);
577  } else if (!member->boundNode->myRegion.contains(member->myExtent)) {
579 
580  member->unbind();
581  myRootNode->addMember(member);
582  } else {
584  }
585  }
586 
587  myRootNode->coalesceEmptyChildren();
588  }
589 
590  bool containsObject(T* object)
591  {
592  return myMemberMap.find(object) != myMemberMap.end();
593  }
594 
596  {
597  return myMemberMap.size();
598  }
599 
600 protected:
601  bool removeObjectOutsideArea(T* object)
602  {
603  OutsideAreaIterator iter, end;
604  for(iter = myObjectsOutsideArea.begin(), end = myObjectsOutsideArea.end(); iter != end; ++iter)
605  {
606  if (*iter == object)
607  {
608  myObjectsOutsideArea.erase(iter);
609  return true;
610  }
611  }
612 
613  return false;
614  }
615 
618 
621 
624 };
625 
629 
630 #if OCTREE_DEBUG
631 
632 class DtDebugOctreeFunctor : public DtSpatialSelectionFunctor
633 {
634 public:
635  DtDebugOctreeFunctor(DtSpatialSelectionFunctor& inner)
636  : myInner(inner)
637  {
638  }
639 
641  virtual bool operator()(const DtVrfObject* object)
642  {
643  mySeenObjects.insert(object);
644  return myInner(object);
645  }
646 
647  std::set<const DtVrfObject*> mySeenObjects;
648  DtSpatialSelectionFunctor& myInner;
649 };
650 
651 template<class T> class DtOctreeDebugger : public DtOctree<T>
652 {
653 public:
654  DtOctreeDebugger(const DtExtent& extent)
655  : DtOctree<T>(extent)
656  { }
657 
658  void addObject(T* object, const DtExtent& extent)
659  {
660  allObjects[object] = extent;
661  DtOctree<T>::addObject(object, extent);
662  }
663 
664  void removeObject(T* object)
665  {
666  allObjects.erase(object);
668  }
669 
670  void updatePositions()
671  {
672  std::map<T*, DtExtent>::iterator iter = allObjects.begin();
673  std::map<T*, DtExtent>::iterator end = allObjects.end();
674 
675  for(; iter != end; ++iter)
676  {
677  T* object = (*iter).first;
678  DtExtent& extent = (*iter).second;
679 
680  extent = object->extent();
681  }
682 
684  }
685 
686  void visitObjects(const DtExtent& extent, DtSpatialSelectionFunctor &callback)
687  {
688  DtDebugOctreeFunctor debugFunctor(callback);
689  DtOctree<T>::visitObjects(extent, debugFunctor);
690 
691  std::map<T*, DtExtent>::iterator iter = allObjects.begin();
692  std::map<T*, DtExtent>::iterator end = allObjects.end();
693 
694  for(; iter != end; ++iter)
695  {
696  T* object = (*iter).first;
697  const DtExtent& objectExtent = (*iter).second;
698 
699  if (objectExtent.intersects(extent) && debugFunctor.mySeenObjects.count(object) == 0)
700  {
701  DEBUG("FAILED to visit object %s", OBJ_ARGS(object));
702  DEBUG_PUSH;
703  DEBUG("Old extent is " EXT_FMT, EXT_ARGS(objectExtent));
704  DEBUG("New extent is " EXT_FMT, EXT_ARGS(object->extent()));
705  DEBUG_POP;
706  }
707  }
708  }
709 protected:
710  std::map<T*, DtExtent> allObjects;
711 };
712 
714 
715 static DtOctree<DtVrfObject>* createOctree(const DtExtent& extent)
716 {
717  return new DtOctreeDebugger<DtVrfObject>(extent);
718 }
719 
720 #else
721 
722 static DtOctree<DtVrfObject>* createOctree(const DtExtent& extent)
723 {
724  return new DtOctree<DtVrfObject>(extent);
725 }
726 
727 #endif
728 
730 
731 template<class T> void DtOctreeMember<T>::bind(DtOctreeNode<T>* node)
732 {
733  if (boundNode)
734  {
735  DtWarn("Octree binding node for %s when already bound!", OBJ_ARGS(myObject));
736  unbind();
737  }
738 
739  boundNode = node;
740  boundIterator = node->myMembers.insert(node->myMembers.end(), this);
741 }
742 
743 template<class T> void DtOctreeMember<T>::unbind()
744 {
745  if (boundNode)
746  {
747  boundNode->myMembers.erase(boundIterator);
748  boundNode = NULL;
749  }
750 }
751 
752 #endif

Document ID: Generated on Sun Nov 24 19:49:21 EST 2013 from SVN revision 133924
Copyright © 2005-2013 VT MÄK. All Rights Reserved (www.mak.com)