VR-Forces Developer's Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
octree.h
Go to the documentation of this file.
1 /*******************************************************************************
2 ** Copyright (c) 2020 MAK Technologies, Inc.
3 ** All rights reserved.
4 *******************************************************************************/
5 
8 
28 
29 #pragma once
30 
32 #include <vrfutil/kinematicTools.h>
33 
35 #include <cmdLine/cmdStdOutput.h>
36 
38 #include <geometry/extent.h>
39 
41 #include <atomic>
42 #include <tbb/spin_rw_mutex.h>
43 
45 #include <cstdarg>
46 #include <map>
47 #include <unordered_map>
48 #include <vector>
49 
50 
51 template<class T> class DtOctreeNode;
52 
55 
56 #define OCTREE_DEBUG 0
57 
58 #if OCTREE_DEBUG
59 
60 static int octree_debug_level = 0;
61 
63 
64 static void DEBUG_OUTPUT(const char* fmt, ...)
65 {
66  char buffer[8192];
67  va_list ap;
68  va_start(ap, fmt);
69  vsprintf(buffer, fmt, ap);
70  va_end(ap);
71 
72  DtInfo("OCT %*s%s\n", octree_debug_level*2, "", buffer);
73 }
74 
75 # define DEBUG_PUSH do { octree_debug_level++; } while(0)
76 # define DEBUG_POP do { octree_debug_level--; } while(0)
77 #else
78 
79 static inline void DEBUG_OUTPUT(const char* fmt, ...)
80 { }
81 
82 # define DEBUG_PUSH do { } while(0)
83 # define DEBUG_POP do { } while(0)
84 #endif
85 
87 static const int NUM_BRANCHES = 8;
88 
89 static const int MAX_BRANCH_DEPTH = 12;
90 
92 static const int MAX_CHILD_MEMBERS = 16;
93 
95 static bool theBitmaskListCreated = false;
96 
97 #define EXT_FMT "[%lf, %lf, %lf] - [%lf, %lf, %lf]"
98 #define EXT_ARGS(x) (x).minX(), (x).minY(), (x).minZ(), (x).maxX(), (x).maxY(), (x).maxZ()
99 #define OBJ_ARGS(x) ((const char*) (x)->objectName())
100 
106 
107 template<class T> class DtOctreeMember
108 {
109 public:
110  DtOctreeMember(T* object, const DtExtent& extent)
111  : myObject(object)
112  , myExtent(extent)
113  {
114  }
115 
117  void bind(DtOctreeNode<T>* node);
118 
120  void unbind(DtOctreeNode<T>* node);
121 
123  void unbind();
124 
125  bool testKey(const unsigned int key)
126  {
127  unsigned int threadId = DtVRFGetThreadId();
128 
129  tbb::spin_rw_mutex::scoped_lock lock(mySearchKeysMutex, false);
130  std::unordered_map<unsigned int, unsigned int>::const_iterator iter = mySearchKeys.find(threadId);
131 
132  if ((iter != mySearchKeys.end()) && (key == iter->second))
133  {
134  return false;
135  }
136 
137  lock.upgrade_to_writer();
139  mySearchKeys[threadId] = key;
140 
141  return true;
142  }
143 
144 protected:
145  template<class U> friend class DtOctreeNode;
146  template<class U> friend class DtOctree;
147 
150 
153 
154  typedef std::pair<DtOctreeNode<T>*, typename std::list<DtOctreeMember*>::iterator> NodeBinding;
155 
158  std::list<NodeBinding> myBindings;
159 
161  std::unordered_map<unsigned int, unsigned int> mySearchKeys;
162  tbb::spin_rw_mutex mySearchKeysMutex;
163 };
164 
165 
166 template<class T>
168 {
169 public:
172 
174  virtual bool operator()(const T *object) = 0;
175 };
176 
203 
204 template<class T> class DtOctreeNode
205 {
206 protected:
207 
208  typedef std::list<DtOctreeMember<T>*> MemberContainer;
209  typedef typename std::list<DtOctreeMember<T>*>::iterator MemberIterator;
210 
211  static int sNumNodes;
212  static const int MAX_NUM_NODES = 1000;
213 
215  DtOctreeNode(const DtExtent &region, const unsigned int depth)
216  : myRegion(region)
217  , myDepth(depth)
218  , myCenter(region.center())
219  , myChildren(0)
220  {
221  DEBUG_OUTPUT("Create node " EXT_FMT, EXT_ARGS(region));
222 
223  ++sNumNodes;
224  }
225 
228  {
229  DEBUG_OUTPUT("Destroy node " EXT_FMT, EXT_ARGS(myRegion));
230  DEBUG_PUSH;
231 
232  if (myChildren)
233  {
234  for(int i=0; i<NUM_BRANCHES; i++)
235  delete myChildren[i];
236  }
237  delete[] myChildren;
238 
239  DEBUG_POP;
240 
241  --sNumNodes;
242  }
243 
252 
253  virtual void visitObjects(const unsigned int key, const DtExtent& extent, DtSpatialSelectionFunctorTemplate<T> &callback)
254  {
255  DEBUG_OUTPUT(EXT_FMT "::visit(" EXT_FMT ", cb)", EXT_ARGS(myRegion), EXT_ARGS(extent));
256  DEBUG_PUSH;
257 
258  MemberIterator iter, end;
259 
260  for(iter = myMembers.begin(), end = myMembers.end(); iter != end; ++iter)
261  {
262  DEBUG_OUTPUT("Member %s " EXT_FMT, OBJ_ARGS((*iter)->myObject), EXT_ARGS((*iter)->myExtent));
263  if ((*iter)->testKey(key))
264  {
265  if (!(*iter)->myObject->isDeleted() && callback((*iter)->myObject))
266  {
267  break;
268  }
269  }
270  else
271  {
273  return;
274  }
275  }
276 
277  if (myChildren)
278  {
279  int mask = intersectionMask(extent);
280  for(int i = 0; i < NUM_BRANCHES; ++i)
281  {
282  if (myChildren[i] && (mask & theBitmaskList[i]))
283  {
284  myChildren[i]->visitObjects(key, extent, callback);
285  }
286  }
287  }
288 
289  DEBUG_POP;
290  }
291 
293  virtual void addMember(DtOctreeMember<T>* member, int& depth)
294  {
295  depth++;
296 
297  DEBUG_OUTPUT(EXT_FMT "::addMember(%s)", EXT_ARGS(myRegion), OBJ_ARGS(member->myObject));
298  DEBUG_PUSH;
299 
300 #if OCTREE_DEBUG
301  if (!myRegion.contains(member->myExtent))
302  {
303  DEBUG_OUTPUT("FAIL! " EXT_FMT " does not contain " EXT_FMT, EXT_ARGS(myRegion), EXT_ARGS(member->myExtent));
304  }
305 #endif
306 
307  if (myChildren)
308  {
309  int mask = intersectionMask(member->myExtent);
310 
311  if (mask == 0xff)
312  {
314  member->bind(this);
315  }
316  else
317  {
318  for (int childIndex = 0; childIndex < NUM_BRANCHES; ++childIndex)
319  {
320  if (mask & theBitmaskList[childIndex])
321  {
322  addMemberToChild(member, childIndex, depth);
323  }
324  }
325  }
326  }
327  else
328  {
329  DEBUG_OUTPUT("add as child member (not enough child members yet)");
330 
331  member->bind(this);
332 
333  //if (numChildCandidates() >= MAX_CHILD_MEMBERS && myDepth < MAX_BRANCH_DEPTH)
334  if (numChildCandidates() >= MAX_CHILD_MEMBERS && sNumNodes < MAX_NUM_NODES - 8)
335  {
336  split(depth);
337  }
338  }
339 
340  DEBUG_POP;
341  }
342 
346  {
347  DEBUG_OUTPUT(EXT_FMT "::coalesceEmptyChildren()", EXT_ARGS(myRegion));
348  DEBUG_PUSH;
349 
350  bool retVal = (myMembers.size() == 0);
351 
352  if (myChildren)
353  {
354  for(int i=0; i<NUM_BRANCHES; i++)
355  {
356  if (myChildren[i])
357  {
359  {
360  DEBUG_OUTPUT("Deleting child %d\n", i);
361  delete myChildren[i];
362  myChildren[i] = 0;
363  } else {
364  retVal = false;
365  }
366  }
367  }
368  }
369 
370  DEBUG_POP;
371 
372  return retVal;
373  }
374 
377  {
378  double retVal = 0;
379  DtExtent matchExtent;
380 
381  MemberIterator iter, end;
382  for(iter = myMembers.begin(), end = myMembers.end(); iter != end; ++iter)
383  {
384  double numBuckets = 0;
385  int mask = intersectionMask((*iter)->myExtent);
386 
389  if ((*iter)->myExtent == matchExtent)
390  {
391  continue;
392  }
393 
394  matchExtent = (*iter)->myExtent;
395 
396  if (mask != 0xff)
397  {
398  for(int childIndex = 0; childIndex < NUM_BRANCHES; ++childIndex)
399  {
400  if (mask & theBitmaskList[childIndex])
401  {
402  numBuckets++;
403  }
404  }
405 
406  retVal += (1.0 / numBuckets);
407 
408  if (retVal >= MAX_CHILD_MEMBERS)
409  {
410  break;
411  }
412  }
413  }
414 
415  return retVal;
416  }
417 
423  int intersectionMask(const DtExtent &extent) const
424  {
425  int result = 0xff;
426 
427  if (extent.minX() >= myCenter.x())
428  result &= 0xf0;
429  if (extent.maxX() <= myCenter.x())
430  result &= 0x0f;
431 
432  if (extent.minY() >= myCenter.y())
433  result &= 0xcc;
434  if (extent.maxY() <= myCenter.y())
435  result &= 0x33;
436 
437  if (extent.minZ() >= myCenter.z())
438  result &= 0xaa;
439  if (extent.maxZ() <= myCenter.z())
440  result &= 0x55;
441 
442  if (result == 0)
443  {
447  return 0xff;
448  }
449 
450  return result;
451  }
452 
456  void addMemberToChild(DtOctreeMember<T>* member, int childIndex, int& depth)
457  {
458  DEBUG_OUTPUT(EXT_FMT "::addMemberToChild(%s, %d)", EXT_ARGS(myRegion), OBJ_ARGS(member->myObject), childIndex);
459  DEBUG_PUSH;
460 
461  if (myChildren[childIndex] == 0)
462  {
463  DtPoint childCorner;
464 
465  if (childIndex & 4)
466  childCorner.setX(myRegion.maxX());
467  else
468  childCorner.setX(myRegion.minX());
469 
470  if (childIndex & 2)
471  childCorner.setY(myRegion.maxY());
472  else
473  childCorner.setY(myRegion.minY());
474 
475  if (childIndex & 1)
476  childCorner.setZ(myRegion.maxZ());
477  else
478  childCorner.setZ(myRegion.minZ());
479 
480  myChildren[childIndex] = new DtOctreeNode(DtExtent(childCorner, myCenter), myDepth + 1);
481  }
482 
483  myChildren[childIndex]->addMember(member, depth);
484 
485  DEBUG_POP;
486  }
487 
490  void split(int& depth)
491  {
492  DEBUG_OUTPUT(EXT_FMT "::split()", EXT_ARGS(myRegion));
493  DEBUG_PUSH;
494 
496 
497  for(int i=0; i<NUM_BRANCHES; i++)
498  {
499  myChildren[i] = 0;
500  }
501 
502  MemberIterator iter, next, end;
503  for(iter = myMembers.begin(), end = myMembers.end(); iter != end; iter = next)
504  {
505  next = iter;
506  ++next;
507 
508  DtOctreeMember<T>* member = *iter;
509 
510  int mask = intersectionMask(member->myExtent);
511 
514  if (mask != 0xff)
515  {
516  member->unbind(this);
517 
518  for(int childIndex = 0; childIndex < NUM_BRANCHES; ++childIndex)
519  {
520  if (mask & theBitmaskList[childIndex])
521  {
522  addMemberToChild(member, childIndex, depth);
523  }
524  }
525  }
526  }
527 
528  DEBUG_POP;
529  }
530 
533 
536 
537 
538  unsigned int myDepth;
539 
544 
548 
549  template<class U> friend class DtOctree;
550  template<class U> friend class DtOctreeMember;
551  template<class U> friend class DtOctreeDebugger;
552 };
553 
554 template<class T> int DtOctreeNode<T>::sNumNodes = 0;
555 
567 
568 template<class T> class DtOctree
569 {
570 public:
571 
573  typedef std::map<T*, DtOctreeMember<T>*> MemberContainer;
574  typedef typename std::map<T*, DtOctreeMember<T>*>::iterator MemberIterator;
575 
576  typedef std::list<T*> OutsideAreaContainer;
577  typedef typename std::list<T*>::iterator OutsideAreaIterator;
578 
580 
582  DtOctree(const DtExtent &region) : mySearchKey(0)
583  {
584  myRootNode = new DtOctreeNode<T>(region, 0);
585 
586  if (!theBitmaskListCreated)
587  {
588  theBitmaskListCreated = true;
589  for (int childIndex = 0; childIndex < NUM_BRANCHES; ++childIndex)
590  {
591  theBitmaskList[childIndex] = (1 << childIndex);
592  }
593  }
594  }
595 
597  virtual ~DtOctree()
598  {
599  delete myRootNode;
600 
601  MemberIterator iter, end;
602  for(iter = myMemberMap.begin(), end = myMemberMap.end(); iter != end; ++iter)
603  {
604  delete (*iter).second;
605  }
606  }
607 
611  virtual void visitObjects(const DtExtent& extent, DtSpatialSelectionFunctorTemplate<T> &callback)
612  {
613  tbb::spin_rw_mutex::scoped_lock lock(myMutex, false);
614  ++mySearchKey;
615 
619  if (myRootNode->myRegion.intersects(extent))
620  {
621  myRootNode->visitObjects(mySearchKey, extent, callback);
622  }
623 
624  OutsideAreaIterator iter, end;
625  for(iter = myObjectsOutsideArea.begin(), end = myObjectsOutsideArea.end(); iter != end; ++iter)
626  {
627  callback(*iter);
628  }
629  }
630 
633 
635  virtual void addObject(T* object, const DtExtent& extent)
636  {
637  DEBUG_OUTPUT("DtOctree::addObject(%s, " EXT_FMT ")", OBJ_ARGS(object), EXT_ARGS(extent));
638  DEBUG_PUSH;
639 
640  tbb::spin_rw_mutex::scoped_lock lock(myMutex);
641  if (myRootNode->myRegion.contains(extent))
642  {
643  DtOctreeMember<T>* newMember = new DtOctreeMember<T>(object, extent);
644  int depth = 0;
645 
646  myRootNode->addMember(newMember, depth);
647  myMemberMap[object] = newMember;
648 
650  }
651  else
652  {
653  DtWarn("Member %s (" EXT_FMT ") added outside octree (" EXT_FMT ")\n",
654  OBJ_ARGS(object), EXT_ARGS(extent), EXT_ARGS(myRootNode->myRegion));
655  myObjectsOutsideArea.push_back(object);
656  }
657 
658  DEBUG_POP;
659  }
660 
662  virtual void removeObject(T* object, bool needsLock = true)
663  {
664  DEBUG_OUTPUT("DtOctree::removeObject(%s)", OBJ_ARGS(object));
665  DEBUG_PUSH;
666 
667  tbb::spin_rw_mutex::scoped_lock* lock = 0;
668 
669  if (needsLock)
670  {
671  lock = new tbb::spin_rw_mutex::scoped_lock(myMutex, true);
672  }
673 
674  MemberIterator iter;
675  iter = myMemberMap.find(object);
676  if (iter != myMemberMap.end())
677  {
678  DtOctreeMember<T>* member = (*iter).second;
679  member->unbind();
680  myMemberMap.erase(iter);
681  delete member;
682  }
683  else if (!removeObjectOutsideArea(object))
684  {
688 
689  //DtWarn("Tried to remove %s from octree, but couldn't find!\n", OBJ_ARGS(object));
690  }
691 
692  DEBUG_POP;
693 
694  if (lock)
695  {
696  delete lock;
697  }
698  }
699 
705  virtual void updatePositions()
706  {
707  tbb::spin_rw_mutex::scoped_lock lock(myMutex, false);
708  MemberIterator cur = myMemberMap.begin();
709  while (cur != myMemberMap.end())
710  {
711  MemberIterator iter = cur++;
712 
713  T* object = (*iter).first;
714 
715  if (object->isValid())
716  {
717  DtOctreeMember<T>* member = (*iter).second;
718  DtExtent roughExtent = object->extent();
719 
721  if (member->myExtent != roughExtent)
722  {
723  member->myExtent = roughExtent;
724 
725  if (!myRootNode->myRegion.contains(member->myExtent))
726  {
728 
729  DtWarn("Object %s (" EXT_FMT ") moving outside octree (" EXT_FMT ")\n",
730  OBJ_ARGS(object), EXT_ARGS(member->myExtent), EXT_ARGS(myRootNode->myRegion));
731  lock.upgrade_to_writer();
732  removeObject(object, false);
733  myObjectsOutsideArea.push_back(object);
734  lock.downgrade_to_reader();
735  }
736  else
737  {
739 
740  member->unbind();
741  int depth = 0;
742 
743  myRootNode->addMember(member, depth);
745  }
746  }
747  }
748  }
749 
750  myRootNode->coalesceEmptyChildren();
751  }
752 
753  bool containsObject(T* object)
754  {
755  tbb::spin_rw_mutex::scoped_lock lock(myMutex, false);
756  if (myMemberMap.find(object) != myMemberMap.end())
757  {
758  return true;
759  }
760  else
761  {
762  OutsideAreaIterator iter, end;
763  for(iter = myObjectsOutsideArea.begin(), end = myObjectsOutsideArea.end(); iter != end; ++iter)
764  {
765  if (*iter == object)
766  {
767  return true;
768  }
769  }
770  }
771  return false;
772  }
773 
775  {
776  return myMemberMap.size() + myObjectsOutsideArea.size();
777  }
778 
780  {
781  return myObjectsOutsideArea.size();
782  }
783 
784 protected:
785  bool removeObjectOutsideArea(T* object)
786  {
787  OutsideAreaIterator iter, end;
788  for(iter = myObjectsOutsideArea.begin(), end = myObjectsOutsideArea.end(); iter != end; ++iter)
789  {
790  if (*iter == object)
791  {
792  myObjectsOutsideArea.erase(iter);
793  return true;
794  }
795  }
796 
797  return false;
798  }
799 
800  tbb::spin_rw_mutex myMutex;
803 
806 
809 
811  std::atomic<unsigned int> mySearchKey;
812 };
813 
817 
818 #if OCTREE_DEBUG
819 
820 class DtDebugOctreeFunctor : public DtSpatialSelectionFunctor
821 {
822 public:
823  DtDebugOctreeFunctor(DtSpatialSelectionFunctor& inner)
824  : myInner(inner)
825  {
826  }
827 
829  virtual bool operator()(const DtSimObject* object)
830  {
831  mySeenObjects.insert(object);
832  return myInner(object);
833  }
834 
835  std::set<const DtSimObject*> mySeenObjects;
836  DtSpatialSelectionFunctor& myInner;
837 };
838 
839 template<class T> class DtOctreeDebugger : public DtOctree<T>
840 {
841 public:
842  DtOctreeDebugger(const DtExtent& extent)
843  : DtOctree<T>(extent)
844  { }
845 
846  void addObject(T* object, const DtExtent& extent)
847  {
848  allObjects[object] = extent;
849  DtOctree<T>::addObject(object, extent);
850  }
851 
852  void removeObject(T* object)
853  {
854  allObjects.erase(object);
856  }
857 
858  void updatePositions()
859  {
860  std::map<T*, DtExtent>::iterator iter = allObjects.begin();
861  std::map<T*, DtExtent>::iterator end = allObjects.end();
862 
863  for(; iter != end; ++iter)
864  {
865  T* object = (*iter).first;
866  DtExtent& extent = (*iter).second;
867 
868  extent = object->roughExtent();
869  }
870 
872  }
873 
874  void visitObjects(const DtExtent& extent, DtSpatialSelectionFunctor &callback)
875  {
876  DtDebugOctreeFunctor debugFunctor(callback);
877  DtOctree<T>::visitObjects(extent, debugFunctor);
878 
879  std::map<T*, DtExtent>::iterator iter = allObjects.begin();
880  std::map<T*, DtExtent>::iterator end = allObjects.end();
881 
882  for(; iter != end; ++iter)
883  {
884  T* object = (*iter).first;
885  const DtExtent& objectExtent = (*iter).second;
886 
887  if (objectExtent.intersects(extent) && debugFunctor.mySeenObjects.count(object) == 0)
888  {
889  DEBUG_OUTPUT("FAILED to visit object %s", OBJ_ARGS(object));
890  DEBUG_PUSH;
891  DEBUG_OUTPUT("Old extent is " EXT_FMT, EXT_ARGS(objectExtent));
892  DEBUG_OUTPUT("New extent is " EXT_FMT, EXT_ARGS(object->roughExtent()));
893  DEBUG_POP;
894  }
895  }
896  }
897 protected:
898  std::map<T*, DtExtent> allObjects;
899 };
900 
902 
903 static DtOctree<DtSimObject>* createOctree(const DtExtent& extent)
904 {
905  return new DtOctreeDebugger<DtSimObject>(extent);
906 }
907 
908 #else
909 
910 
911 
912 #endif
913 
915 
916 template<class T> void DtOctreeMember<T>::bind(DtOctreeNode<T>* node)
917 {
918  for (typename std::list<NodeBinding>::const_iterator it = myBindings.begin(); it != myBindings.end(); ++it)
919  {
920  if (node == (*it).first)
921  {
922  return;
923  }
924  }
925 
926  myBindings.push_back(NodeBinding(node, node->myMembers.insert(node->myMembers.end(), this)));
927 }
928 
929 template<class T> void DtOctreeMember<T>::unbind(DtOctreeNode<T>* node)
930 {
931  for (typename std::list<NodeBinding>::iterator it = myBindings.begin(); it != myBindings.end(); ++it)
932  {
933  if (node == (*it).first)
934  {
935  node->myMembers.erase((*it).second);
936  myBindings.erase(it);
937  return;
938  }
939  }
940 }
941 
942 template<class T> void DtOctreeMember<T>::unbind()
943 {
944  for (typename std::list<NodeBinding>::const_iterator it = myBindings.begin(); it != myBindings.end(); ++it)
945  {
946  (*it).first->myMembers.erase((*it).second);
947  }
948  myBindings.clear();
949 }
const double & x() const
Definition: point.h:188
static const int NUM_BRANCHES
The number of children of each node. Don&#39;t change this without rewriting everything.
Definition: octree.h:87
virtual bool contains(const DtExtent &otherExtent) const
Determine if another extents box is entirely contained by this one. On the border counts as &quot;containe...
virtual ~DtOctree()
Destructor. Deletes the octree and any members in it (though not the corresponding objects)...
Definition: octree.h:597
T * myObject
The object corresponding to this member.
Definition: octree.h:149
DtExtent myExtent
The extent of the member at the time it was added or last updated.
Definition: octree.h:152
void unbind()
Remove this member from all nodes.
Definition: octree.h:942
static bool theBitmaskListCreated
Definition: octree.h:95
bool coalesceEmptyChildren()
Look for any empty, childless nodes and coalesce them up to their parents. Returns true if this node ...
Definition: octree.h:345
void split(int &depth)
Create child nodes to hold all the members that can go into child nodes, and move those members into ...
Definition: octree.h:490
bool removeObjectOutsideArea(T *object)
Definition: octree.h:785
DtOctreeNode(const DtExtent &region, const unsigned int depth)
Constructor. The extent covered by an octree node may not be changed once the octree is created...
Definition: octree.h:215
friend class DtOctreeDebugger
Definition: octree.h:551
MemberContainer myMemberMap
Mapping of T* pointers to DtOctreeMember objects in the tree.
Definition: octree.h:808
DtOctreeNode< T > * myRootNode
Root node of the octree.
Definition: octree.h:802
DtSpatialSelectionFunctorTemplate< T > SpatialSelectionFunctor
Definition: octree.h:579
#define EXT_FMT
Definition: octree.h:97
tbb::spin_rw_mutex myMutex
Definition: octree.h:800
The DtSpatialVrfObjectManager is responsible for maintaining a spatial organization of all specified ...
Definition: spatialVrfObjectManager.h:31
DtOctree class.
Definition: octree.h:568
DtOctreeNode< T > ** myChildren
Child nodes of this node, if any. This is NULL for a childless node. For nodes with children...
Definition: octree.h:543
The DtExtent represents an axis-aligned 3d bounding box.
Definition: extent.h:43
virtual void addMember(DtOctreeMember< T > *member, int &depth)
Add a member to this node or one of its children (splitting the node if necessary).
Definition: octree.h:293
static const int MAX_BRANCH_DEPTH
Definition: octree.h:89
static void DEBUG_OUTPUT(const char *fmt,...)
Definition: octree.h:79
#define DEBUG_POP
Definition: octree.h:83
#define OBJ_ARGS(x)
Definition: octree.h:99
int numObjects()
Definition: octree.h:774
Octree support.
Definition: octree.h:51
double maxZ() const
Access and/or mutate individual values.
double minZ() const
Access and/or mutate individual values.
DtOctreeMember class.
Definition: octree.h:107
#define DEBUG_PUSH
Definition: octree.h:82
DT_DLL_vrfutil unsigned int DtVRFGetThreadId()
Gets the current thread id.
std::unordered_map< unsigned int, unsigned int > mySearchKeys
Definition: octree.h:161
virtual bool operator()(const T *object)=0
Abstract function call interface.
std::atomic< unsigned int > mySearchKey
Definition: octree.h:811
DtOctree(const DtExtent &region)
Constructor. The extent covered by an octree may not be changed once the octree is created...
Definition: octree.h:582
bool intersects(const DtExtent &otherExtent) const
Determine if the two extents overlap (either partially or fully). A shared &quot;wall&quot; counts as intersect...
virtual bool operator()(const DtSimObject *object) override=0
Abstract function call interface.
static const int MAX_NUM_NODES
Definition: octree.h:212
Definition: octree.h:167
int numObjectsOutside()
Definition: octree.h:779
bool containsObject(T *object)
Definition: octree.h:753
~DtOctreeNode()
Destructor. No DtOctreeMember objects are deleted.
Definition: octree.h:227
static DtOctree< const DtSimObject > * createOctree(const DtExtent &extent)
Definition: spatialVrfObjectManager.h:294
void bind(DtOctreeNode< T > *node)
Add this member to the specified node.
Definition: octree.h:916
double minX() const
Access and/or mutate individual values.
const DtExtent myRegion
The region intersecting members contained by this node (and this node&#39;s children).
Definition: octree.h:532
virtual void addObject(T *object, const DtExtent &extent)
TODO: Add search key to outside octree list so that objects which fall completely outside the octree ...
Definition: octree.h:635
std::list< NodeBinding > myBindings
A list of the nodes this member is bound to, if any, and iterators to this member&#39;s position in the b...
Definition: octree.h:158
double minY() const
Access and/or mutate individual values.
void setY(const double &y)
Definition: point.h:203
tbb::spin_rw_mutex mySearchKeysMutex
Definition: octree.h:162
std::pair< DtOctreeNode< T > *, typename std::list< DtOctreeMember * >::iterator > NodeBinding
Definition: octree.h:154
const DtPoint myCenter
The center of myRegion.
Definition: octree.h:535
virtual void visitObjects(const unsigned int key, const DtExtent &extent, DtSpatialSelectionFunctorTemplate< T > &callback)
Call the given functor for every member that shares a node with the specified extent. This does not test for exact intersection; it only returns a list of objects that might intersect the given extent.
Definition: octree.h:253
const double & y() const
Definition: point.h:198
virtual ~DtSpatialSelectionFunctorTemplate()
Virtual Destructor which does nothing.
Definition: octree.h:171
std::list< DtOctreeMember< T > * >::iterator MemberIterator
Definition: octree.h:209
bool testKey(const unsigned int key)
Definition: octree.h:125
Represents a single simulation object in the exercise. Object may be VRF simulation, or non-VRF simulated, and may be simulated by the local sim engine, or by a remote sim engine. Only public (external) state of the object is available. All data is read-only. All access to data of the object is thread safe within the simulation frame.
Definition: simObject.h:80
int numChildCandidates()
Return the number of members of this node that can go into child nodes.
Definition: octree.h:376
std::list< DtOctreeMember< T > * > MemberContainer
This class is only for use from DtOctree and DtOctreeDebugger.
Definition: octree.h:208
Contains the declaration of the DtExtent class.
static int theBitmaskList[NUM_BRANCHES]
Definition: octree.h:94
std::list< T * > OutsideAreaContainer
Definition: octree.h:576
MemberContainer myMembers
Members which are in this node. If myChildren is not NULL, then this must not contain any members tha...
Definition: octree.h:547
unsigned int myDepth
Definition: octree.h:538
virtual void visitObjects(const DtExtent &extent, DtSpatialSelectionFunctorTemplate< T > &callback)
Call the given functor for every member that shares a node with the specified extent. This does not test for exact intersection; it only iterates over any objects that might intersect the given extent (i.e. there may be extras).
Definition: octree.h:611
double maxX() const
Access and/or mutate individual values.
void setZ(const double &z)
Definition: point.h:213
virtual void updatePositions()
Process any updates to the objects&#39; positions that have happened since they were added to the octree...
Definition: octree.h:705
void setX(const double &x)
Definition: point.h:193
const double & z() const
Definition: point.h:208
double maxY() const
Access and/or mutate individual values.
virtual void removeObject(T *object, bool needsLock=true)
Remove a member from the octree.
Definition: octree.h:662
void addMemberToChild(DtOctreeMember< T > *member, int childIndex, int &depth)
Add a member to a child of this node, creating the child if necessary. This function will call addMem...
Definition: octree.h:456
std::map< T *, DtOctreeMember< T > * >::iterator MemberIterator
Definition: octree.h:574
std::map< T *, DtOctreeMember< T > * > MemberContainer
Container and iterator typedefs for the STL structures used.
Definition: octree.h:573
OutsideAreaContainer myObjectsOutsideArea
List of objects which are at least partially outside the octree&#39;s root extent.
Definition: octree.h:805
#define EXT_ARGS(x)
Definition: octree.h:98
std::list< T * >::iterator OutsideAreaIterator
Definition: octree.h:577
int intersectionMask(const DtExtent &extent) const
Returns a bit-mask where the ith bit is set iff the ith child of this node intersects the specified e...
Definition: octree.h:423
DtOctreeMember(T *object, const DtExtent &extent)
Definition: octree.h:110
Definition: point.h:34
static const int MAX_CHILD_MEMBERS
The maximum length of myChildMembers; see implementation notes at the top of the class.
Definition: octree.h:92
static int sNumNodes
Definition: octree.h:211
void unbind(DtOctreeNode< T > *node)
Remove this member from the specified node.
Definition: octree.h:929

Document ID: Generated on Thu Oct 23 22:29:17 EDT 2025 from SVN revision 280951
Copyright © 2005-2024 MAK Technologies. All Rights Reserved (www.mak.com)