TrinityCore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc > Class Template Reference

#include <KDTree.h>

Classes

class  BoundsComparator
 
class  BoxIntersectionIterator
 
class  CenterComparator
 
class  Comparator
 
class  Handle
 
class  Iterator
 
class  Node
 

Public Member Functions

 KDTree ()
 
 KDTree (const KDTree &src)
 
KDTreeoperator= (const KDTree &src)
 
 ~KDTree ()
 
void clear ()
 
int size () const
 
void insert (const T &value)
 
void insert (const Array< T > &valueArray)
 
bool contains (const T &value)
 
void remove (const T &value)
 
void update (const T &value)
 
void balance (int valuesPerNode=5, int numMeanSplits=3)
 
void setContents (const Array< T > &array, int valuesPerNode=5, int numMeanSplits=3)
 
void getIntersectingMembers (const Array< Plane > &plane, Array< T * > &members) const
 
void getIntersectingMembers (const Array< Plane > &plane, Array< T > &members) const
 
void getIntersectingMembers (const Frustum &frustum, Array< T * > &members) const
 
void getIntersectingMembers (const Frustum &frustum, Array< T > &members) const
 
BoxIntersectionIterator beginBoxIntersection (const AABox &box) const
 
BoxIntersectionIterator endBoxIntersection () const
 
void getIntersectingMembers (const AABox &box, Array< T * > &members) const
 
void getIntersectingMembers (const AABox &box, Array< T > &members) const
 
template<typename RayCallback >
void intersectRay (const Ray &ray, RayCallback &intersectCallback, float &distance, bool intersectCallbackIsFast=false) const
 
void getIntersectingMembers (const Sphere &sphere, Array< T * > &members) const
 Finds all members whose bounding boxes intersect the sphere. The actual elements may not intersect the sphere. More...
 
void getIntersectingMembers (const Sphere &sphere, Array< T > &members) const
 
void serializeStructure (BinaryOutput &bo) const
 
void deserializeStructure (BinaryInput &bi)
 
void getMembers (Array< T > &members) const
 
const T * getPointer (const T &value) const
 
Iterator begin () const
 
Iterator end () const
 

Protected Types

typedef _internal::Indirector
< Handle
Member
 
typedef Table< Member, Node * > MemberTable
 

Protected Member Functions

NodemakeNode (Array< Handle * > &source, int valuesPerNode, int numMeanSplits, Array< Handle * > &temp)
 
NodecloneTree (Node *src)
 

Static Protected Member Functions

static AABox computeBounds (const Array< Handle * > &point, int beginIndex, int endIndex)
 
static void getIntersectingMembers (const Array< Plane > &plane, Array< T * > &members, Node *node, uint32 parentMask)
 

Protected Attributes

MemberTable memberTable
 
Noderoot
 

Detailed Description

template<class T, class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
class G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >

A set that supports spatial queries using a KD tree (axis-aligned BSP tree) for speed.

KDTree allows you to quickly find objects in 3D that lie within a box or along a ray. For large sets of objects it is much faster than testing each object for a collision.

KDTree is as powerful as but more general than a Quad Tree, Oct Tree, or regular KD tree that cycles through axes, but less general than an unconstrained BSP tree (which is much slower to create).

Internally, objects are arranged into a tree according to their axis-aligned bounds. This increases the cost of insertion to O(log n) but allows fast overlap queries.

Template Parameters

The template parameter T must be one for which the following functions are all overloaded:

 T::T(); // public constructor of no arguments
 template <> struct HashTrait<T> { static size_t hashCode(int key); };
 template<> struct BoundsTrait<T> { static void getBounds(const T& obj, G3D::AABox& out); };

G3D provides these for common classes like G3D::Vector3 and G3D::Sphere. If you use a custom class, or a pointer to a custom class, you will need to define those functions.

Moving Set Members

It is important that objects do not move without updating the KDTree. If the axis-aligned bounds of an object are about to change, KDTree::remove it before they change and KDTree::insert it again afterward. For objects where the hashCode and == operator are invariant with respect to the 3D position, you can use the KDTree::update method as a shortcut to insert/remove an object in one step after it has moved.

Note: Do not mutate any value once it has been inserted into KDTree. Values are copied interally. All KDTree iterators convert to pointers to constant values to reinforce this.

If you want to mutate the objects you intend to store in a KDTree simply insert pointers to your objects instead of the objects themselves, and ensure that the above operations are defined. (And actually, because values are copied, if your values are large you may want to insert pointers anyway, to save space and make the balance operation faster.)

Dimensions Although designed as a 3D-data structure, you can use the KDTree for data distributed along 2 or 1 axes by simply returning bounds that are always zero along one or more dimensions.

Member Typedef Documentation

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
typedef _internal::Indirector<Handle> G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::Member
protected

Wrapper for a Handle; used to create a memberTable that acts like Table<Handle, Node*> but stores only Handle* internally to avoid memory copies.

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
typedef Table<Member, Node*> G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::MemberTable
protected

Constructor & Destructor Documentation

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::KDTree ( )
inline

To construct a balanced tree, insert the elements and then call KDTree::balance().

888 : root(NULL) {}
Node * root
Definition: KDTree.h:882
arena_t NULL
Definition: jemalloc_internal.h:624
template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::KDTree ( const KDTree< T, BoundsFunc, HashFunc, EqualsFunc > &  src)
inline
891  : root(NULL) {
892  *this = src;
893  }
Node * root
Definition: KDTree.h:882
arena_t NULL
Definition: jemalloc_internal.h:624
template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::~KDTree ( )
inline
904  {
905  clear();
906  }
void clear()
Definition: KDTree.h:911

+ Here is the call graph for this function:

Member Function Documentation

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::balance ( int  valuesPerNode = 5,
int  numMeanSplits = 3 
)
inline

Rebalances the tree (slow). Call when objects have moved substantially from their original positions (which unbalances the tree and causes the spatial queries to be slow).

Parameters
valuesPerNodeMaximum number of elements to put at a node.
numMeanSplitsnumMeanSplits = 0 gives a fully axis aligned BSP-tree, where the balance operation attempts to balance the tree so that every splitting plane has an equal number of left and right children (i.e. it is a median split along that axis). This tends to maximize average performance.

You can override this behavior by setting a number of mean (average) splits. numMeanSplits = MAX_INT creates a full oct-tree, which tends to optimize peak performance at the expense of average performance. It tends to have better clustering behavior when members are not uniformly distributed.

1093  {
1094  if (root == NULL) {
1095  // Tree is empty
1096  return;
1097  }
1098 
1099  // Get all handles and delete the old tree structure
1100  Node* oldRoot = root;
1101  for (int c = 0; c < 2; ++c) {
1102  if (root->child[c] != NULL) {
1104 
1105  // Delete the child; this will delete all structure below it
1106  delete root->child[c];
1107  root->child[c] = NULL;
1108  }
1109  }
1110 
1111  Array<Handle*> temp;
1112  // Make a new root. Work with a copy of the value array because
1113  // makeNode clears the source array as it progresses
1114  Array<Handle*> copy(oldRoot->valueArray);
1115  root = makeNode(copy, valuesPerNode, numMeanSplits, temp);
1116 
1117  // Throw away the old root node
1118  delete oldRoot;
1119  oldRoot = NULL;
1120 
1121  // Walk the tree, assigning splitBounds. We start with unbounded
1122  // space. This will override the current member table.
1123  const AABox& LARGE = AABox::large();
1124  root->assignSplitBounds(LARGE);
1125 
1126 # ifdef _DEBUG
1127  {
1128  // Ensure that the balanced tree is still correct
1129  root->verifyNode(LARGE.low(), LARGE.high());
1130  }
1131 # endif
1132  }
Array< Handle * > valueArray
Definition: KDTree.h:361
Node * child[2]
Definition: KDTree.h:351
Node * makeNode(Array< Handle * > &source, int valuesPerNode, int numMeanSplits, Array< Handle * > &temp)
Definition: KDTree.h:711
Node * root
Definition: KDTree.h:882
arena_t NULL
Definition: jemalloc_internal.h:624
void assignSplitBounds(const AABox &myBounds)
Definition: KDTree.h:566
void verifyNode(const Vector3 &lo, const Vector3 &hi)
Definition: KDTree.h:434
void getHandles(Array< Handle * > &handleArray) const
Definition: KDTree.h:425
static const AABox & large()
Definition: AABox.cpp:74

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
Iterator G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::begin ( ) const
inline

C++ STL style iterator method. Returns the first member. Use preincrement (++entry) to get to the next element (iteration order is arbitrary). Do not modify the set while iterating.

1650  {
1651  return Iterator(memberTable.begin());
1652  }
Iterator begin() const
Definition: Table.h:562
MemberTable memberTable
Definition: KDTree.h:880

+ Here is the call graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
BoxIntersectionIterator G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::beginBoxIntersection ( const AABox box) const
inline

Iterates through the members that intersect the box

1421  {
1422  return BoxIntersectionIterator(box, root);
1423  }
Node * root
Definition: KDTree.h:882
template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::clear ( )
inline

Throws out all elements of the set.

911  {
912  typedef typename Table<_internal::Indirector<Handle>, Node*>::Iterator It;
913 
914  // Delete all handles stored in the member table
915  It cur = memberTable.begin();
916  It end = memberTable.end();
917  while (cur != end) {
918  delete cur->key.handle;
919  cur->key.handle = NULL;
920  ++cur;
921  }
922  memberTable.clear();
923 
924  // Delete the tree structure itself
925  delete root;
926  root = NULL;
927  }
void clear()
Definition: Table.h:578
Node * root
Definition: KDTree.h:882
Iterator begin() const
Definition: Table.h:562
arena_t NULL
Definition: jemalloc_internal.h:624
MemberTable memberTable
Definition: KDTree.h:880
Iterator end() const
Definition: KDTree.h:1659
const Iterator end() const
Definition: Table.h:570

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
Node* G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::cloneTree ( Node src)
inlineprotected

Recursively clone the passed in node tree, setting pointers for members in the memberTable as appropriate. called by the assignment operator.

853  {
854  Node* dst = new Node(*src);
855 
856  // Make back pointers
857  for (int i = 0; i < dst->valueArray.size(); ++i) {
858  memberTable.set(Member(dst->valueArray[i]), dst);
859  }
860 
861  // Clone children
862  for (int i = 0; i < 2; ++i) {
863  if (src->child[i] != NULL) {
864  dst->child[i] = cloneTree(src->child[i]);
865  }
866  }
867 
868  return dst;
869  }
arena_t NULL
Definition: jemalloc_internal.h:624
void set(const Key &key, const Value &value)
Definition: Table.h:599
MemberTable memberTable
Definition: KDTree.h:880
Node * cloneTree(Node *src)
Definition: KDTree.h:853
_internal::Indirector< Handle > Member
Definition: KDTree.h:875

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
static AABox G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::computeBounds ( const Array< Handle * > &  point,
int  beginIndex,
int  endIndex 
)
inlinestaticprotected

Returns the bounds of the sub array. Used by makeNode.

237  {
238 
239  Vector3 lo = Vector3::inf();
240  Vector3 hi = -lo;
241 
242  debugAssertM(beginIndex <= endIndex, "No points");
243  for (int p = beginIndex; p <= endIndex; ++p) {
244  // This code is written with the vector min and max expanded
245  // because otherwise it compiles incorrectly with -O3 on
246  // gcc 3.4
247 
248  const Vector3& pLo = point[p]->bounds.low();
249  const Vector3& pHi = point[p]->bounds.high();
250  for (int a = 0; a < 3; ++a) {
251  lo[a] = G3D::min(lo[a], pLo[a]);
252  hi[a] = G3D::max(hi[a], pHi[a]);
253  }
254  }
255 
256  return AABox(lo, hi);
257  }
#define debugAssertM(exp, message)
Definition: debugAssert.h:161
T max(const T &x, const T &y)
Definition: g3dmath.h:320
T min(const T &x, const T &y)
Definition: g3dmath.h:305
static const Vector3 & inf()
Definition: Vector3.cpp:124

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
bool G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::contains ( const T &  value)
inline

Returns true if this object is in the set, otherwise returns false. O(1) time.

998  {
999  // Temporarily create a handle and member
1000  Handle h(value);
1001  return memberTable.containsKey(Member(&h));
1002  }
MemberTable memberTable
Definition: KDTree.h:880
const FieldDescriptor value
Definition: descriptor.h:1522
bool containsKey(const Key &key) const
Definition: Table.h:874
_internal::Indirector< Handle > Member
Definition: KDTree.h:875

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::deserializeStructure ( BinaryInput bi)
inline

Clears the member table

1553  {
1554  clear();
1556  }
Node * root
Definition: KDTree.h:882
void clear()
Definition: KDTree.h:911
static Node * deserializeStructure(BinaryInput &bi)
Definition: KDTree.h:495

+ Here is the call graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
Iterator G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::end ( ) const
inline

C++ STL style iterator method. Returns one after the last iterator element.

1659  {
1660  return Iterator(memberTable.end());
1661  }
MemberTable memberTable
Definition: KDTree.h:880
const Iterator end() const
Definition: Table.h:570

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
BoxIntersectionIterator G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::endBoxIntersection ( ) const
inline
1425  {
1426  // The "end" iterator instance
1427  return BoxIntersectionIterator();
1428  }
template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
static void G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::getIntersectingMembers ( const Array< Plane > &  plane,
Array< T * > &  members,
Node node,
uint32  parentMask 
)
inlinestaticprotected
Parameters
parentMaskThe mask that this node returned from culledBy.
1152  {
1153 
1154  int dummy;
1155 
1156  if (parentMask == 0) {
1157  // None of these planes can cull anything
1158  for (int v = node->valueArray.size() - 1; v >= 0; --v) {
1159  members.append(& (node->valueArray[v]->value));
1160  }
1161 
1162  // Iterate through child nodes
1163  for (int c = 0; c < 2; ++c) {
1164  if (node->child[c]) {
1165  getIntersectingMembers(plane, members, node->child[c], 0);
1166  }
1167  }
1168  } else {
1169 
1170  // Test values at this node against remaining planes
1171  for (int v = node->boundsArray.size() - 1; v >= 0; --v) {
1172  if (! node->boundsArray[v].culledBy(plane, dummy, parentMask)) {
1173  members.append(&(node->valueArray[v]->value));
1174  }
1175  }
1176 
1177  uint32 childMask = 0xFFFFFF;
1178 
1179  // Iterate through child nodes
1180  for (int c = 0; c < 2; ++c) {
1181  if (node->child[c] &&
1182  ! node->child[c]->splitBounds.culledBy(plane, dummy, parentMask, childMask)) {
1183  // This node was not culled
1184  getIntersectingMembers(plane, members, node->child[c], childMask);
1185  }
1186  }
1187  }
1188  }
static void getIntersectingMembers(const Array< Plane > &plane, Array< T * > &members, Node *node, uint32 parentMask)
Definition: KDTree.h:1148
uint32_t uint32
Definition: Define.h:150

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::getIntersectingMembers ( const Array< Plane > &  plane,
Array< T * > &  members 
) const
inline

Returns all members inside the set of planes.

Parameters
membersThe results are appended to this array.
1196  {
1197  if (root == NULL) {
1198  return;
1199  }
1200 
1201  getIntersectingMembers(plane, members, root, 0xFFFFFF);
1202  }
Node * root
Definition: KDTree.h:882
arena_t NULL
Definition: jemalloc_internal.h:624
static void getIntersectingMembers(const Array< Plane > &plane, Array< T * > &members, Node *node, uint32 parentMask)
Definition: KDTree.h:1148

+ Here is the call graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::getIntersectingMembers ( const Array< Plane > &  plane,
Array< T > &  members 
) const
inline
1204  {
1205  Array<T*> temp;
1206  getIntersectingMembers(plane, temp, root, 0xFFFFFF);
1207  for (int i = 0; i < temp.size(); ++i) {
1208  members.append(*temp[i]);
1209  }
1210  }
Node * root
Definition: KDTree.h:882
static void getIntersectingMembers(const Array< Plane > &plane, Array< T * > &members, Node *node, uint32 parentMask)
Definition: KDTree.h:1148
void append(const T &value)
Definition: Array.h:583

+ Here is the call graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::getIntersectingMembers ( const Frustum frustum,
Array< T * > &  members 
) const
inline

Typically used to find all visible objects inside the view frustum (see also Camera::getClipPlanes)... i.e. all objects not culled by frustum.

Example:

   Array<Object*>  visible;
   tree.getIntersectingMembers(camera.frustum(), visible);
   // ... Draw all objects in the visible array.
 
Parameters
membersThe results are appended to this array.
1225  {
1226  Array<Plane> plane;
1227 
1228  for (int i = 0; i < frustum.faceArray.size(); ++i) {
1229  plane.append(frustum.faceArray[i].plane);
1230  }
1231 
1232  getIntersectingMembers(plane, members);
1233  }
static void getIntersectingMembers(const Array< Plane > &plane, Array< T * > &members, Node *node, uint32 parentMask)
Definition: KDTree.h:1148

+ Here is the call graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::getIntersectingMembers ( const Frustum frustum,
Array< T > &  members 
) const
inline
1235  {
1236  Array<T*> temp;
1237  getIntersectingMembers(frustum, temp);
1238  for (int i = 0; i < temp.size(); ++i) {
1239  members.append(*temp[i]);
1240  }
1241  }
static void getIntersectingMembers(const Array< Plane > &plane, Array< T * > &members, Node *node, uint32 parentMask)
Definition: KDTree.h:1148
void append(const T &value)
Definition: Array.h:583

+ Here is the call graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::getIntersectingMembers ( const AABox box,
Array< T * > &  members 
) const
inline

Appends all members whose bounds intersect the box. See also KDTree::beginBoxIntersection.

1434  {
1435  if (root == NULL) {
1436  return;
1437  }
1438  root->getIntersectingMembers(box, Sphere(Vector3::zero(), 0), members, false);
1439  }
Node * root
Definition: KDTree.h:882
void getIntersectingMembers(const AABox &box, const Sphere &sphere, Array< T * > &members, bool useSphere) const
Definition: KDTree.h:537
arena_t NULL
Definition: jemalloc_internal.h:624
static const Vector3 & zero()
Definition: Vector3.cpp:119

+ Here is the call graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::getIntersectingMembers ( const AABox box,
Array< T > &  members 
) const
inline
1441  {
1442  Array<T*> temp;
1443  getIntersectingMembers(box, temp);
1444  for (int i = 0; i < temp.size(); ++i) {
1445  members.append(*temp[i]);
1446  }
1447  }
static void getIntersectingMembers(const Array< Plane > &plane, Array< T * > &members, Node *node, uint32 parentMask)
Definition: KDTree.h:1148
void append(const T &value)
Definition: Array.h:583

+ Here is the call graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::getIntersectingMembers ( const Sphere sphere,
Array< T * > &  members 
) const
inline

Finds all members whose bounding boxes intersect the sphere. The actual elements may not intersect the sphere.

Parameters
membersThe results are appended to this array.
1525  {
1526  if (root == NULL) {
1527  return;
1528  }
1529 
1530  AABox box;
1531  sphere.getBounds(box);
1532  root->getIntersectingMembers(box, sphere, members, true);
1533  }
Node * root
Definition: KDTree.h:882
void getIntersectingMembers(const AABox &box, const Sphere &sphere, Array< T * > &members, bool useSphere) const
Definition: KDTree.h:537
arena_t NULL
Definition: jemalloc_internal.h:624

+ Here is the call graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::getIntersectingMembers ( const Sphere sphere,
Array< T > &  members 
) const
inline
1535  {
1536  Array<T*> temp;
1537  getIntersectingMembers(sphere, temp);
1538  for (int i = 0; i < temp.size(); ++i) {
1539  members.append(*temp[i]);
1540  }
1541  }
static void getIntersectingMembers(const Array< Plane > &plane, Array< T * > &members, Node *node, uint32 parentMask)
Definition: KDTree.h:1148
void append(const T &value)
Definition: Array.h:583

+ Here is the call graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::getMembers ( Array< T > &  members) const
inline

Returns an array of all members of the set. See also KDTree::begin.

1561  {
1562  Array<Member> temp;
1563  memberTable.getKeys(temp);
1564  for (int i = 0; i < temp.size(); ++i) {
1565  members.append(*(temp.handle));
1566  }
1567  }
MemberTable memberTable
Definition: KDTree.h:880
Array< Key > getKeys() const
Definition: Table.h:907
void append(const T &value)
Definition: Array.h:583

+ Here is the call graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
const T* G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::getPointer ( const T &  value) const
inline

If a value that is EqualsFunc to value is present, returns a pointer to the version stored in the data structure, otherwise returns NULL.

1573  {
1574  // Temporarily create a handle and member
1575  Handle h(value);
1576  const Member* member = memberTable.getKeyPointer(Member(&h));
1577  if (member == NULL) {
1578  // Not found
1579  return NULL;
1580  } else {
1581  return &(member->handle->value);
1582  }
1583  }
arena_t NULL
Definition: jemalloc_internal.h:624
MemberTable memberTable
Definition: KDTree.h:880
const Key * getKeyPointer(const Key &key) const
Definition: Table.h:701
const FieldDescriptor value
Definition: descriptor.h:1522
_internal::Indirector< Handle > Member
Definition: KDTree.h:875

+ Here is the call graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::insert ( const T &  value)
inline

Inserts an object into the set if it is not already present. O(log n) time. Does not cause the tree to be balanced.

938  {
939  if (contains(value)) {
940  // Already in the set
941  return;
942  }
943 
944  Handle* h = new Handle(value);
945 
946  if (root == NULL) {
947  // This is the first node; create a root node
948  root = new Node();
949  }
950 
951  Node* node = root->findDeepestContainingNode(h->bounds);
952 
953  // Insert into the node
954  node->valueArray.append(h);
955  node->boundsArray.append(h->bounds);
956 
957  // Insert into the node table
958  Member m(h);
959  memberTable.set(m, node);
960  }
Array< Handle * > valueArray
Definition: KDTree.h:361
Node * findDeepestContainingNode(const AABox &bounds)
Definition: KDTree.h:511
bool contains(const T &value)
Definition: KDTree.h:998
Node * root
Definition: KDTree.h:882
arena_t NULL
Definition: jemalloc_internal.h:624
void set(const Key &key, const Value &value)
Definition: Table.h:599
MemberTable memberTable
Definition: KDTree.h:880
const FieldDescriptor value
Definition: descriptor.h:1522
_internal::Indirector< Handle > Member
Definition: KDTree.h:875

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::insert ( const Array< T > &  valueArray)
inline

Inserts each elements in the array in turn. If the tree begins empty (no structure and no elements), this is faster than inserting each element in turn. You still need to balance the tree at the end.

966  {
967  if (root == NULL) {
968  // Optimized case for an empty tree; don't bother
969  // searching or reallocating the root node's valueArray
970  // as we incrementally insert.
971  root = new Node();
972  root->valueArray.resize(valueArray.size());
973  root->boundsArray.resize(root->valueArray.size());
974  for (int i = 0; i < valueArray.size(); ++i) {
975  // Insert in opposite order so that we have the exact same
976  // data structure as if we inserted each (i.e., order is reversed
977  // from array).
978  Handle* h = new Handle(valueArray[i]);
979  int j = valueArray.size() - i - 1;
980  root->valueArray[j] = h;
981  root->boundsArray[j] = h->bounds;
982  memberTable.set(Member(h), root);
983  }
984 
985  } else {
986  // Insert at appropriate tree depth.
987  for (int i = 0; i < valueArray.size(); ++i) {
988  insert(valueArray[i]);
989  }
990  }
991  }
Array< Handle * > valueArray
Definition: KDTree.h:361
Node * root
Definition: KDTree.h:882
arena_t NULL
Definition: jemalloc_internal.h:624
void set(const Key &key, const Value &value)
Definition: Table.h:599
Array< AABox > boundsArray
Definition: KDTree.h:369
MemberTable memberTable
Definition: KDTree.h:880
int size() const
Definition: Array.h:430
void insert(const T &value)
Definition: KDTree.h:938
_internal::Indirector< Handle > Member
Definition: KDTree.h:875

+ Here is the call graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
template<typename RayCallback >
void G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::intersectRay ( const Ray ray,
RayCallback &  intersectCallback,
float &  distance,
bool  intersectCallbackIsFast = false 
) const
inline

Invoke a callback for every member along a ray until the closest intersection is found.

Parameters
intersectCallbackEither a function or an instance of a class with an overloaded operator() of the form:
    void callback(const Ray& ray, const T& object, float& distance).
If the ray hits the object before travelling distance distance, updates distance with the new distance to the intersection, otherwise leaves it unmodified. A common example is:
class Entity {
public:
    void intersect(const Ray& ray, float& maxDist, Vector3& outLocation, Vector3& outNormal) {
        float d = maxDist;

        // ... search for intersection distance d

        if ((d > 0) && (d < maxDist)) {
            // Intersection occured
            maxDist = d;
            outLocation = ...;
            outNormal = ...;
        }
    }
};

// Finds the surface normal and location of the first intersection with the scene
class Intersection {
public:
    Entity*     closestEntity;
    Vector3     hitLocation;
    Vector3     hitNormal;

    void operator()(const Ray& ray, const Entity* entity, float& distance) {
        entity->intersect(ray, distance, hitLocation, hitNormal);
    }
};

KDTree scene;

Intersection intersection;
float distance = finf();
scene.intersectRay(camera.worldRay(x, y), intersection, distance);
distanceWhen the method is invoked, this is the maximum distance that the tree should search for an intersection. On return, this is set to the distance to the first intersection encountered.
intersectCallbackIsFastIf false, each object's bounds are tested before the intersectCallback is invoked. If the intersect callback runs at the same speed or faster than AABox-ray intersection, set this to true.
1513  {
1514 
1515  root->intersectRay(ray, intersectCallback, distance, intersectCallbackIsFast);
1516  }
Node * root
Definition: KDTree.h:882
double distance(double x, double y)
Definition: g3dmath.h:731
void intersectRay(const Ray &ray, RayCallback &intersectCallback, float &distance, bool intersectCallbackIsFast) const
Definition: KDTree.h:603

+ Here is the call graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
Node* G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::makeNode ( Array< Handle * > &  source,
int  valuesPerNode,
int  numMeanSplits,
Array< Handle * > &  temp 
)
inlineprotected

Recursively subdivides the subarray.

Clears the source array as soon as it is no longer needed.

Call assignSplitBounds() on the root node after making a tree.

715  {
716 
717  Node* node = NULL;
718 
719  if (source.size() <= valuesPerNode) {
720  // Make a new leaf node
721  node = new Node(source);
722 
723  // Set the pointers in the memberTable
724  for (int i = 0; i < source.size(); ++i) {
725  memberTable.set(Member(source[i]), node);
726  }
727  source.clear();
728 
729  } else {
730  // Make a new internal node
731  node = new Node();
732 
733  const AABox& bounds = computeBounds(source, 0, source.size() - 1);
734  const Vector3& extent = bounds.high() - bounds.low();
735 
736  Vector3::Axis splitAxis = extent.primaryAxis();
737 
738  float splitLocation;
739 
740  // Arrays for holding the children
741  Array<Handle*> lt, gt;
742 
743  if (numMeanSplits <= 0) {
744 
745  source.medianPartition(lt, node->valueArray, gt, temp, CenterComparator(splitAxis));
746 
747  // Choose the split location to be the center of whatever fell in the center
748  splitLocation = node->valueArray[0]->center[splitAxis];
749 
750  // Some of the elements in the lt or gt array might really overlap the split location.
751  // Move them as needed.
752  for (int i = 0; i < lt.size(); ++i) {
753  const AABox& bounds = lt[i]->bounds;
754  if ((bounds.low()[splitAxis] <= splitLocation) && (bounds.high()[splitAxis] >= splitLocation)) {
755  node->valueArray.append(lt[i]);
756  // Remove this element and process the new one that
757  // is swapped in in its place.
758  lt.fastRemove(i); --i;
759  }
760  }
761 
762  for (int i = 0; i < gt.size(); ++i) {
763  const AABox& bounds = gt[i]->bounds;
764  if ((bounds.low()[splitAxis] <= splitLocation) && (bounds.high()[splitAxis] >= splitLocation)) {
765  node->valueArray.append(gt[i]);
766  // Remove this element and process the new one that
767  // is swapped in in its place.
768  gt.fastRemove(i); --i;
769  }
770  }
771 
772  if ((node->valueArray.size() > (source.size() / 2)) &&
773  (source.size() > 6)) {
774  // This was a bad partition; we ended up putting the splitting plane right in the middle of most of the
775  // objects. We could try to split on a different axis, or use a different partition (e.g., the extents mean,
776  // or geometric mean). This implementation falls back on the extents mean, since that case is already handled
777  // below.
778  numMeanSplits = 1;
779  }
780  }
781 
782  // Note: numMeanSplits may have been increased by the code in the previous case above in order to
783  // force a re-partition.
784 
785  if (numMeanSplits > 0) {
786  // Split along the mean
787  splitLocation =
788  bounds.high()[splitAxis] * 0.5f +
789  bounds.low()[splitAxis] * 0.5f;
790 
791  debugAssertM(isFinite(splitLocation),
792  "Internal error: split location must be finite.");
793 
794  source.partition(NULL, lt, node->valueArray, gt, Comparator(splitAxis, splitLocation));
795 
796  // The Comparator ensures that elements are strictly on the correct side of the split
797  }
798 
799 
800 # if defined(G3D_DEBUG) && defined(VERIFY_TREE)
801  debugAssert(lt.size() + node->valueArray.size() + gt.size() == source.size());
802  // Verify that all objects ended up on the correct side of the split.
803  // (i.e., make sure that the Array partition was correct)
804  for (int i = 0; i < lt.size(); ++i) {
805  const AABox& bounds = lt[i]->bounds;
806  debugAssert(bounds.high()[splitAxis] < splitLocation);
807  }
808 
809  for (int i = 0; i < gt.size(); ++i) {
810  const AABox& bounds = gt[i]->bounds;
811  debugAssert(bounds.low()[splitAxis] > splitLocation);
812  }
813 
814  for (int i = 0; i < node->valueArray.size(); ++i) {
815  const AABox& bounds = node->valueArray[i]->bounds;
816  debugAssert(bounds.high()[splitAxis] >= splitLocation);
817  debugAssert(bounds.low()[splitAxis] <= splitLocation);
818  }
819 # endif
820 
821  // The source array is no longer needed
822  source.clear();
823 
824  node->splitAxis = splitAxis;
825  node->splitLocation = splitLocation;
826 
827  // Update the bounds array and member table
828  node->boundsArray.resize(node->valueArray.size());
829  for (int i = 0; i < node->valueArray.size(); ++i) {
830  Handle* v = node->valueArray[i];
831  node->boundsArray[i] = v->bounds;
832  memberTable.set(Member(v), node);
833  }
834 
835  if (lt.size() > 0) {
836  node->child[0] = makeNode(lt, valuesPerNode, numMeanSplits - 1, temp);
837  }
838 
839  if (gt.size() > 0) {
840  node->child[1] = makeNode(gt, valuesPerNode, numMeanSplits - 1, temp);
841  }
842 
843  }
844 
845  return node;
846  }
Node * makeNode(Array< Handle * > &source, int valuesPerNode, int numMeanSplits, Array< Handle * > &temp)
Definition: KDTree.h:711
arena_t NULL
Definition: jemalloc_internal.h:624
static AABox computeBounds(const Array< Handle * > &point, int beginIndex, int endIndex)
Definition: KDTree.h:234
void set(const Key &key, const Value &value)
Definition: Table.h:599
Axis
Definition: Vector3.h:122
#define debugAssertM(exp, message)
Definition: debugAssert.h:161
#define debugAssert(exp)
Definition: debugAssert.h:160
MemberTable memberTable
Definition: KDTree.h:880
const Point3 & high() const
Definition: AABox.h:141
bool isFinite(double x)
Definition: g3dmath.h:525
_internal::Indirector< Handle > Member
Definition: KDTree.h:875

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
KDTree& G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::operator= ( const KDTree< T, BoundsFunc, HashFunc, EqualsFunc > &  src)
inline
896  {
897  delete root;
898  // Clone tree takes care of filling out the memberTable.
899  root = cloneTree(src.root);
900  return *this;
901  }
Node * root
Definition: KDTree.h:882
Node * cloneTree(Node *src)
Definition: KDTree.h:853

+ Here is the call graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::remove ( const T &  value)
inline

Removes an object from the set in O(1) time. It is an error to remove members that are not already present. May unbalance the tree.

Removing an element never causes a node (split plane) to be removed... nodes are only changed when the tree is rebalanced. This behavior is desirable because it allows the split planes to be serialized, and then deserialized into an empty tree which can be repopulated.

1015  {
1017  "Tried to remove an element from a "
1018  "KDTree that was not present");
1019 
1020  // Get the list of elements at the node
1021  Handle h(value);
1022  Member m(&h);
1023 
1024  Array<Handle*>& list = memberTable[m]->valueArray;
1025 
1026  Handle* ptr = NULL;
1027 
1028  // Find the element and remove it
1029  for (int i = list.length() - 1; i >= 0; --i) {
1030  if (list[i]->value == value) {
1031  // This was the element. Grab the pointer so that
1032  // we can delete it below
1033  ptr = list[i];
1034 
1035  // Remove the handle from the node
1036  list.fastRemove(i);
1037 
1038  // Remove the corresponding bounds
1039  memberTable[m]->boundsArray.fastRemove(i);
1040  break;
1041  }
1042  }
1043 
1044  // Remove the member
1045  memberTable.remove(m);
1046 
1047  // Delete the handle data structure
1048  delete ptr;
1049  ptr = NULL;
1050  }
bool contains(const T &value)
Definition: KDTree.h:998
arena_t NULL
Definition: jemalloc_internal.h:624
#define debugAssertM(exp, message)
Definition: debugAssert.h:161
bool remove(const Key &key, Key &removedKey, Value &removedValue, bool updateRemoved)
Definition: Table.h:606
MemberTable memberTable
Definition: KDTree.h:880
const FieldDescriptor value
Definition: descriptor.h:1522
_internal::Indirector< Handle > Member
Definition: KDTree.h:875

+ Here is the call graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::serializeStructure ( BinaryOutput bo) const
inline

Stores the locations of the splitting planes (the structure but not the content) so that the tree can be quickly rebuilt from a previous configuration without calling balance.

1548  {
1550  }
Node * root
Definition: KDTree.h:882
static void serializeStructure(const Node *n, BinaryOutput &bo)
Definition: KDTree.h:480

+ Here is the call graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::setContents ( const Array< T > &  array,
int  valuesPerNode = 5,
int  numMeanSplits = 3 
)
inline

Clear, set the contents to the values in the array, and then balance

1136  {
1137  clear();
1138  insert(array);
1139  balance(valuesPerNode, numMeanSplits);
1140  }
void balance(int valuesPerNode=5, int numMeanSplits=3)
Definition: KDTree.h:1093
void clear()
Definition: KDTree.h:911
void insert(const T &value)
Definition: KDTree.h:938

+ Here is the call graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
int G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::size ( ) const
inline
929  {
930  return memberTable.size();
931  }
size_t size() const
Definition: Table.h:589
MemberTable memberTable
Definition: KDTree.h:880

+ Here is the call graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::update ( const T &  value)
inline

If the element is in the set, it is removed. The element is then inserted.

This is useful when the == and hashCode methods on T are independent of the bounds. In that case, you may call update(v) to insert an element for the first time and call update(v) again every time it moves to keep the tree up to date.

1064  {
1065  if (contains(value)) {
1066  remove(value);
1067  }
1068  insert(value);
1069  }
bool contains(const T &value)
Definition: KDTree.h:998
const FieldDescriptor value
Definition: descriptor.h:1522
void insert(const T &value)
Definition: KDTree.h:938

+ Here is the call graph for this function:

Member Data Documentation

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
MemberTable G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::memberTable
protected

Maps members to the node containing them

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
Node* G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::root
protected

The documentation for this class was generated from the following file: