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

#include <PointKDTree.h>

Classes

class  AxisComparator
 
class  BoxIntersectionIterator
 
class  Handle
 
class  Iterator
 
class  Node
 

Public Member Functions

 PointKDTree ()
 
 PointKDTree (const PointKDTree &src)
 
PointKDTreeoperator= (const PointKDTree &src)
 
 ~PointKDTree ()
 
void clear ()
 
void clearData ()
 
size_t 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=40, int numMeanSplits=3)
 
void getIntersectingMembers (const Array< Plane > &plane, 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 Sphere &sphere, Array< T > &members) const
 
void serializeStructure (BinaryOutput &bo) const
 
void deserializeStructure (BinaryInput &bi)
 
void getMembers (Array< T > &members) const
 
Iterator begin () const
 
Iterator end () const
 

Protected Types

typedef Table< T, Node
*, HashFunc, EqualsFunc > 
MemberTable
 

Protected Member Functions

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

Static Protected Member Functions

static AABox computeBounds (const Array< Handle > &point)
 

Protected Attributes

MemberTable memberTable
 
Noderoot
 

Static Private Member Functions

static void getIntersectingMembers (const Array< Plane > &plane, Array< T > &members, Node *node, uint32 parentMask)
 

Detailed Description

template<class T, class PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
class G3D::PointKDTree< T, PositionFunc, HashFunc, EqualsFunc >

A set data structure that supports spatial queries using an axis-aligned BSP tree for speed.

PointKDTree allows you to quickly find points in 3D that lie within a box or sphere. For large sets of objects it is much faster than testing each object for a collision. See also G3D::KDTree; this class is optimized for point sets, e.g.,for use in photon mapping and mesh processing.

Template Parameters



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

     T::T(); (public constructor of no arguments)
      template<> struct PositionTrait<class T> {
        static void getPosition(const T& v, G3D::Vector3& p);};
      template <> struct HashTrait<class T> {
        static size_t hashCode(const T& key);};
      template<> struct EqualsTrait<class T> {
          static bool equals(const T& a, const T& b); };
   

G3D provides these for the Vector2, Vector3, and Vector4 classes. 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 PointKDTree. If the position of an object is about to change, PointKDTree::remove it before they change and PointKDTree::insert it again afterward. For objects where the hashCode and == operator are invariant with respect to the 3D position, you can use the PointKDTree::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 PointKDTree. Values are copied interally. All PointKDTree iterators convert to pointers to constant values to reinforce this.

If you want to mutate the objects you intend to store in a PointKDTree 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 PointKDTree 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 PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
typedef Table<T, Node*, HashFunc, EqualsFunc> G3D::PointKDTree< T, PositionFunc, HashFunc, EqualsFunc >::MemberTable
protected

Maps members to the node containing them

Constructor & Destructor Documentation

template<class T , class PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
G3D::PointKDTree< T, PositionFunc, HashFunc, EqualsFunc >::PointKDTree ( )
inline

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

570 : root(NULL) {}
Node * root
Definition: PointKDTree.h:564
arena_t NULL
Definition: jemalloc_internal.h:624
template<class T , class PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
G3D::PointKDTree< T, PositionFunc, HashFunc, EqualsFunc >::PointKDTree ( const PointKDTree< T, PositionFunc, HashFunc, EqualsFunc > &  src)
inline
573  : root(NULL) {
574  *this = src;
575  }
Node * root
Definition: PointKDTree.h:564
arena_t NULL
Definition: jemalloc_internal.h:624
template<class T , class PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
G3D::PointKDTree< T, PositionFunc, HashFunc, EqualsFunc >::~PointKDTree ( )
inline
586  {
587  clear();
588  }
void clear()
Definition: PointKDTree.h:593

+ Here is the call graph for this function:

Member Function Documentation

template<class T , class PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::PointKDTree< T, PositionFunc, HashFunc, EqualsFunc >::balance ( int  valuesPerNode = 40,
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; all querries will return in the same amount of time.

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 (some areas of the scene will terminate after few recursive splits) at the expense of peak performance.

754  {
755  if (root == NULL) {
756  // Tree is empty
757  return;
758  }
759 
760  Array<Handle> handleArray;
761  root->getHandles(handleArray);
762 
763  // Delete the old tree
764  clear();
765 
766  Array<Handle> temp;
767  root = makeNode(handleArray, temp, valuesPerNode, numMeanSplits);
768  temp.fastClear();
769 
770  // Walk the tree, assigning splitBounds. We start with unbounded
771  // space.
773 
774 # ifdef _DEBUG
776 # endif
777  }
Node * root
Definition: PointKDTree.h:564
static const Vector3 & minFinite()
Definition: Vector3.cpp:126
void clear()
Definition: PointKDTree.h:593
arena_t NULL
Definition: jemalloc_internal.h:624
static const AABox & maxFinite()
Definition: AABox.cpp:67
void getHandles(Array< Handle > &handleArray) const
Definition: PointKDTree.h:227
static const Vector3 & maxFinite()
Definition: Vector3.cpp:127
Node * makeNode(Array< Handle > &source, Array< Handle > &temp, int valuesPerNode, int numMeanSplits)
Definition: PointKDTree.h:444
void verifyNode(const Vector3 &lo, const Vector3 &hi)
Definition: PointKDTree.h:237
void assignSplitBounds(const AABox &myBounds)
Definition: PointKDTree.h:397

+ Here is the call graph for this function:

template<class T , class PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
Iterator G3D::PointKDTree< T, PositionFunc, 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.

1171  {
1172  return Iterator(memberTable.begin());
1173  }
Iterator begin() const
Definition: Table.h:562
MemberTable memberTable
Definition: PointKDTree.h:562

+ Here is the call graph for this function:

template<class T , class PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
BoxIntersectionIterator G3D::PointKDTree< T, PositionFunc, HashFunc, EqualsFunc >::beginBoxIntersection ( const AABox box) const
inline

Iterates through the members that intersect the box

1051  {
1052  return BoxIntersectionIterator(box, root);
1053  }
Node * root
Definition: PointKDTree.h:564
template<class T , class PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::PointKDTree< T, PositionFunc, HashFunc, EqualsFunc >::clear ( )
inline

Throws out all elements of the set and erases the structure of the tree.

593  {
594  memberTable.clear();
595  delete root;
596  root = NULL;
597  }
Node * root
Definition: PointKDTree.h:564
void clear()
Definition: Table.h:578
arena_t NULL
Definition: jemalloc_internal.h:624
MemberTable memberTable
Definition: PointKDTree.h:562

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

template<class T , class PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::PointKDTree< T, PositionFunc, HashFunc, EqualsFunc >::clearData ( )
inline

Removes all elements of the set while maintaining the structure of the tree

600  {
601  memberTable.clear();
602  Array<Node*> stack;
603  stack.push(root);
604  while (stack.size() > 0) {
605  Node* node = stack.pop();
606  node->valueArray.fastClear();
607 
608  for (int i = 0; i < 2; ++i) {
609  if (node->child[i] != NULL) {
610  stack.push(node->child[i]);
611  }
612  }
613  }
614  }
Node * root
Definition: PointKDTree.h:564
void clear()
Definition: Table.h:578
arena_t NULL
Definition: jemalloc_internal.h:624
MemberTable memberTable
Definition: PointKDTree.h:562

+ Here is the call graph for this function:

template<class T , class PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
Node* G3D::PointKDTree< T, PositionFunc, 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.

542  {
543  Node* dst = new Node(*src);
544 
545  // Make back pointers
546  for (int i = 0; i < dst->valueArray.size(); ++i) {
547  memberTable.set(dst->valueArray[i].value, dst);
548  }
549 
550  // Clone children
551  for (int i = 0; i < 2; ++i) {
552  if (src->child[i] != NULL) {
553  dst->child[i] = cloneTree(src->child[i]);
554  }
555  }
556 
557  return dst;
558  }
arena_t NULL
Definition: jemalloc_internal.h:624
void set(const Key &key, const Value &value)
Definition: Table.h:599
MemberTable memberTable
Definition: PointKDTree.h:562
Node * cloneTree(Node *src)
Definition: PointKDTree.h:542

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

template<class T , class PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
static AABox G3D::PointKDTree< T, PositionFunc, HashFunc, EqualsFunc >::computeBounds ( const Array< Handle > &  point)
inlinestaticprotected

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

134  {
135 
136  if (point.size() == 0) {
137  return AABox(Vector3::inf(), Vector3::inf());
138  }
139 
140  AABox bounds(point[0].position());
141 
142  for (int p = 0; p < point.size(); ++p) {
143  bounds.merge(point[p].position());
144  }
145 
146  return bounds;
147  }
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 PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
bool G3D::PointKDTree< T, PositionFunc, HashFunc, EqualsFunc >::contains ( const T &  value)
inline

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

682  {
683  return memberTable.containsKey(value);
684  }
MemberTable memberTable
Definition: PointKDTree.h:562
const FieldDescriptor value
Definition: descriptor.h:1522
bool containsKey(const Key &key) const
Definition: Table.h:874

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

template<class T , class PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::PointKDTree< T, PositionFunc, HashFunc, EqualsFunc >::deserializeStructure ( BinaryInput bi)
inline

Clears the member table

1097  {
1098  clear();
1100  }
Node * root
Definition: PointKDTree.h:564
void clear()
Definition: PointKDTree.h:593
static Node * deserializeStructure(BinaryInput &bi)
Definition: PointKDTree.h:291

+ Here is the call graph for this function:

template<class T , class PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
Iterator G3D::PointKDTree< T, PositionFunc, HashFunc, EqualsFunc >::end ( ) const
inline

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

1180  {
1181  return Iterator(memberTable.end());
1182  }
MemberTable memberTable
Definition: PointKDTree.h:562
const Iterator end() const
Definition: Table.h:570

+ Here is the call graph for this function:

template<class T , class PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
BoxIntersectionIterator G3D::PointKDTree< T, PositionFunc, HashFunc, EqualsFunc >::endBoxIntersection ( ) const
inline
1055  {
1056  // The "end" iterator instance
1057  return BoxIntersectionIterator();
1058  }
template<class T , class PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
static void G3D::PointKDTree< T, PositionFunc, HashFunc, EqualsFunc >::getIntersectingMembers ( const Array< Plane > &  plane,
Array< T > &  members,
Node node,
uint32  parentMask 
)
inlinestaticprivate

Returns the elements

Parameters
parentMaskThe mask that this node returned from culledBy.
790  {
791 
792  int dummy;
793 
794  if (parentMask == 0) {
795  // None of these planes can cull anything
796  for (int v = node->valueArray.size() - 1; v >= 0; --v) {
797  members.append(node->valueArray[v].value);
798  }
799 
800  // Iterate through child nodes
801  for (int c = 0; c < 2; ++c) {
802  if (node->child[c]) {
803  getIntersectingMembers(plane, members, node->child[c], 0);
804  }
805  }
806  } else {
807 
808  if (node->valueArray.size() > 0) {
809  // This is a leaf; check the points
810  debugAssertM(node->child[0] == NULL, "Malformed Point tree");
811  debugAssertM(node->child[1] == NULL, "Malformed Point tree");
812 
813  // Test values at this node against remaining planes
814  for (int p = 0; p < plane.size(); ++p) {
815  if (((parentMask >> p) & 1) != 0) {
816  // Test against this plane
817  const Plane& curPlane = plane[p];
818  for (int v = node->valueArray.size() - 1; v >= 0; --v) {
819  if (curPlane.halfSpaceContains(node->valueArray[v].position())) {
820  members.append(node->valueArray[v].value);
821  }
822  }
823  }
824  }
825  } else {
826 
827  uint32 childMask = 0xFFFFFF;
828 
829  // Iterate through child nodes
830  for (int c = 0; c < 2; ++c) {
831  if (node->child[c] &&
832  ! node->child[c]->splitBounds.culledBy(plane, dummy, parentMask, childMask)) {
833  // This node was not culled
834  getIntersectingMembers(plane, members, node->child[c], childMask);
835  }
836  }
837  }
838  }
839  }
arena_t NULL
Definition: jemalloc_internal.h:624
#define debugAssertM(exp, message)
Definition: debugAssert.h:161
uint32_t uint32
Definition: Define.h:150
static void getIntersectingMembers(const Array< Plane > &plane, Array< T > &members, Node *node, uint32 parentMask)
Definition: PointKDTree.h:786
void append(const T &value)
Definition: Array.h:583

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

template<class T , class PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::PointKDTree< T, PositionFunc, 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.
847  {
848  if (root == NULL) {
849  return;
850  }
851 
852  getIntersectingMembers(plane, members, root, 0xFFFFFF);
853  }
Node * root
Definition: PointKDTree.h:564
arena_t NULL
Definition: jemalloc_internal.h:624
static void getIntersectingMembers(const Array< Plane > &plane, Array< T > &members, Node *node, uint32 parentMask)
Definition: PointKDTree.h:786

+ Here is the call graph for this function:

template<class T , class PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::PointKDTree< T, PositionFunc, 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.
868  {
869  Array<Plane> plane;
870 
871  for (int i = 0; i < frustum.faceArray.size(); ++i) {
872  plane.append(frustum.faceArray[i].plane);
873  }
874 
875  getIntersectingMembers(plane, members);
876  }
static void getIntersectingMembers(const Array< Plane > &plane, Array< T > &members, Node *node, uint32 parentMask)
Definition: PointKDTree.h:786

+ Here is the call graph for this function:

template<class T , class PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::PointKDTree< T, PositionFunc, HashFunc, EqualsFunc >::getIntersectingMembers ( const AABox box,
Array< T > &  members 
) const
inline

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

1064  {
1065  if (root == NULL) {
1066  return;
1067  }
1068  root->getIntersectingMembers(box, Sphere(Vector3::zero(), 0), members, false);
1069  }
Node * root
Definition: PointKDTree.h:564
arena_t NULL
Definition: jemalloc_internal.h:624
static const Vector3 & zero()
Definition: Vector3.cpp:119
void getIntersectingMembers(const AABox &sphereBounds, const Sphere &sphere, Array< T > &members) const
Definition: PointKDTree.h:331

+ Here is the call graph for this function:

template<class T , class PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::PointKDTree< T, PositionFunc, HashFunc, EqualsFunc >::getIntersectingMembers ( const Sphere sphere,
Array< T > &  members 
) const
inline
Parameters
membersThe results are appended to this array.
1075  {
1076  if (root == NULL) {
1077  return;
1078  }
1079 
1080  AABox box;
1081  sphere.getBounds(box);
1082  root->getIntersectingMembers(box, sphere, members);
1083 
1084  }
Node * root
Definition: PointKDTree.h:564
arena_t NULL
Definition: jemalloc_internal.h:624
void getIntersectingMembers(const AABox &sphereBounds, const Sphere &sphere, Array< T > &members) const
Definition: PointKDTree.h:331

+ Here is the call graph for this function:

template<class T , class PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::PointKDTree< T, PositionFunc, HashFunc, EqualsFunc >::getMembers ( Array< T > &  members) const
inline

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

1105  {
1106  memberTable.getKeys(members);
1107  }
MemberTable memberTable
Definition: PointKDTree.h:562
Array< Key > getKeys() const
Definition: Table.h:907

+ Here is the call graph for this function:

template<class T , class PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::PointKDTree< T, PositionFunc, 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.

626  {
627  if (contains(value)) {
628  // Already in the set
629  return;
630  }
631 
632  Handle h(value);
633 
634  if (root == NULL) {
635  // This is the first node; create a root node
636  root = new Node();
637  }
638 
639  Node* node = root->findDeepestContainingNode(h.position());
640 
641  // Insert into the node
642  node->valueArray.append(h);
643 
644  // Insert into the node table
645  memberTable.set(value, node);
646  }
Node * root
Definition: PointKDTree.h:564
Node * findDeepestContainingNode(const Vector3 &point)
Definition: PointKDTree.h:307
arena_t NULL
Definition: jemalloc_internal.h:624
void set(const Key &key, const Value &value)
Definition: Table.h:599
bool contains(const T &value)
Definition: PointKDTree.h:682
MemberTable memberTable
Definition: PointKDTree.h:562
const FieldDescriptor value
Definition: descriptor.h:1522
Array< Handle > valueArray
Definition: PointKDTree.h:173

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

template<class T , class PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::PointKDTree< T, PositionFunc, 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.

652  {
653  // Pre-size the member table to avoid multiple allocations
654  memberTable.setSizeHint(valueArray.size() + size());
655 
656  if (root == NULL) {
657  // Optimized case for an empty tree; don't bother
658  // searching or reallocating the root node's valueArray
659  // as we incrementally insert.
660  root = new Node();
661  root->valueArray.resize(valueArray.size());
662  for (int i = 0; i < valueArray.size(); ++i) {
663  // Insert in opposite order so that we have the exact same
664  // data structure as if we inserted each (i.e., order is reversed
665  // from array).
666  root->valueArray[valueArray.size() - i - 1] = Handle(valueArray[i]);
667  memberTable.set(valueArray[i], root);
668  }
669  } else {
670  // Insert at appropriate tree depth.
671  for (int i = 0; i < valueArray.size(); ++i) {
672  insert(valueArray[i]);
673  }
674  }
675  }
Node * root
Definition: PointKDTree.h:564
void setSizeHint(size_t n)
Definition: Table.h:318
arena_t NULL
Definition: jemalloc_internal.h:624
void set(const Key &key, const Value &value)
Definition: Table.h:599
MemberTable memberTable
Definition: PointKDTree.h:562
void insert(const T &value)
Definition: PointKDTree.h:626
int size() const
Definition: Array.h:430
size_t size() const
Definition: PointKDTree.h:617
Array< Handle > valueArray
Definition: PointKDTree.h:173

+ Here is the call graph for this function:

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

Recursively subdivides the subarray.

The source array will be cleared after it is used

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

448  {
449 
450  Node* node = NULL;
451 
452  if (source.size() <= valuesPerNode) {
453  // Make a new leaf node
454  node = new Node(source);
455 
456  // Set the pointers in the memberTable
457  for (int i = 0; i < source.size(); ++i) {
458  memberTable.set(source[i].value, node);
459  }
460 
461  } else {
462  // Make a new internal node
463  node = new Node();
464 
465  const AABox bounds = computeBounds(source);
466  const Vector3 extent = bounds.high() - bounds.low();
467 
468  Vector3::Axis splitAxis = extent.primaryAxis();
469 
470  float splitLocation;
471 
472  Array<Handle> lt, gt;
473 
474  if (numMeanSplits <= 0) {
475  source.medianPartition(lt, node->valueArray, gt, temp, AxisComparator(splitAxis));
476  splitLocation = node->valueArray[0].position()[splitAxis];
477 
478  if ((node->valueArray.size() > source.size() / 2) &&
479  (source.size() > 10)) {
480  // Our median split put an awful lot of points on the splitting plane. Try a mean
481  // split instead
482  numMeanSplits = 1;
483  }
484  }
485 
486  if (numMeanSplits > 0) {
487  // Compute the mean along the axis
488 
489  splitLocation = (bounds.high()[splitAxis] +
490  bounds.low()[splitAxis]) / 2.0f;
491 
492  Handle splitHandle;
493  Vector3 v;
494  v[splitAxis] = splitLocation;
495  splitHandle.setPosition(v);
496 
497  source.partition(splitHandle, lt, node->valueArray, gt, AxisComparator(splitAxis));
498  }
499 
500 # if defined(G3D_DEBUG) && defined(VERIFY_TREE)
501  for (int i = 0; i < lt.size(); ++i) {
502  const Vector3& v = lt[i].position();
503  debugAssert(v[splitAxis] < splitLocation);
504  }
505  for (int i = 0; i < gt.size(); ++i) {
506  debugAssert(gt[i].position()[splitAxis] > splitLocation);
507  }
508  for (int i = 0; i < node->valueArray.size(); ++i) {
509  debugAssert(node->valueArray[i].position()[splitAxis] == splitLocation);
510  }
511 # endif
512 
513  node->splitAxis = splitAxis;
514  node->splitLocation = splitLocation;
515 
516  // Throw away the source array to save memory
517  source.fastClear();
518 
519  if (lt.size() > 0) {
520  node->child[0] = makeNode(lt, temp, valuesPerNode, numMeanSplits - 1);
521  }
522 
523  if (gt.size() > 0) {
524  node->child[1] = makeNode(gt, temp, valuesPerNode, numMeanSplits - 1);
525  }
526 
527  // Add the values stored at this interior node to the member table
528  for(int i = 0; i < node->valueArray.size(); ++i) {
529  memberTable.set(node->valueArray[i].value, node);
530  }
531 
532  }
533 
534  return node;
535  }
arena_t NULL
Definition: jemalloc_internal.h:624
void set(const Key &key, const Value &value)
Definition: Table.h:599
Axis
Definition: Vector3.h:122
MemberTable memberTable
Definition: PointKDTree.h:562
#define debugAssert(exp)
Definition: debugAssert.h:160
Node * makeNode(Array< Handle > &source, Array< Handle > &temp, int valuesPerNode, int numMeanSplits)
Definition: PointKDTree.h:444
static AABox computeBounds(const Array< Handle > &point)
Definition: PointKDTree.h:133
const FieldDescriptor value
Definition: descriptor.h:1522

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

template<class T , class PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
PointKDTree& G3D::PointKDTree< T, PositionFunc, HashFunc, EqualsFunc >::operator= ( const PointKDTree< T, PositionFunc, HashFunc, EqualsFunc > &  src)
inline
578  {
579  delete root;
580  // Clone tree takes care of filling out the memberTable.
581  root = cloneTree(src.root);
582  return *this;
583  }
Node * root
Definition: PointKDTree.h:564
Node * cloneTree(Node *src)
Definition: PointKDTree.h:542

+ Here is the call graph for this function:

template<class T , class PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::PointKDTree< T, PositionFunc, 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.

697  {
699  "Tried to remove an element from a "
700  "PointKDTree that was not present");
701 
702  Array<Handle>& list = memberTable[value]->valueArray;
703 
704  // Find the element and remove it
705  for (int i = list.length() - 1; i >= 0; --i) {
706  if (list[i].value == value) {
707  list.fastRemove(i);
708  break;
709  }
710  }
712  }
bool contains(const T &value)
Definition: PointKDTree.h:682
#define debugAssertM(exp, message)
Definition: debugAssert.h:161
MemberTable memberTable
Definition: PointKDTree.h:562
bool remove(const Key &key, Key &removedKey, Value &removedValue, bool updateRemoved)
Definition: Table.h:606
const FieldDescriptor value
Definition: descriptor.h:1522

+ Here is the call graph for this function:

template<class T , class PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::PointKDTree< T, PositionFunc, 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.

1092  {
1094  }
static void serializeStructure(const Node *n, BinaryOutput &bo)
Definition: PointKDTree.h:276
Node * root
Definition: PointKDTree.h:564

+ Here is the call graph for this function:

template<class T , class PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
size_t G3D::PointKDTree< T, PositionFunc, HashFunc, EqualsFunc >::size ( ) const
inline
617  {
618  return memberTable.size();
619  }
size_t size() const
Definition: Table.h:589
MemberTable memberTable
Definition: PointKDTree.h:562

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

template<class T , class PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::PointKDTree< T, PositionFunc, 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.

726  {
727  if (contains(value)) {
728  remove(value);
729  }
730  insert(value);
731  }
bool contains(const T &value)
Definition: PointKDTree.h:682
void insert(const T &value)
Definition: PointKDTree.h:626
const FieldDescriptor value
Definition: descriptor.h:1522

+ Here is the call graph for this function:

Member Data Documentation

template<class T , class PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
MemberTable G3D::PointKDTree< T, PositionFunc, HashFunc, EqualsFunc >::memberTable
protected
template<class T , class PositionFunc = PositionTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
Node* G3D::PointKDTree< T, PositionFunc, HashFunc, EqualsFunc >::root
protected

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