root/trunk/src/shared/vmap/AABSPTree.h

Revision 2, 53.0 kB (checked in by yumileroy, 17 years ago)

[svn] * Proper SVN structure

Original author: Neo2003
Date: 2008-10-02 16:23:55-05:00

Line 
1/**
2  @file AABSPTree.h
3 
4  @maintainer Morgan McGuire, matrix@graphics3d.com
5 
6  @created 2004-01-11
7  @edited  2007-02-16
8
9  Copyright 2000-2007, Morgan McGuire.
10  All rights reserved.
11 
12  */
13
14#ifndef G3D_AABSPTREE_H
15#define G3D_AABSPTREE_H
16
17#include "VMapTools.h"
18
19#include "G3D/platform.h"
20#include "G3D/Array.h"
21#include "G3D/Table.h"
22#include "G3D/Vector3.h"
23#include "G3D/AABox.h"
24#include "G3D/Sphere.h"
25#include "G3D/Box.h"
26#include "G3D/Triangle.h"
27#include "G3D/Ray.h"
28#include "G3D/GCamera.h"
29#if 0
30#include "G3D/BinaryInput.h"
31#include "G3D/BinaryOutput.h"
32#endif
33#include "G3D/CollisionDetection.h"
34#include "G3D/GCamera.h"
35#include <algorithm>
36
37// If defined, in debug mode the tree is checked for consistency
38// as a way of detecting corruption due to implementation bugs
39// #define VERIFY_TREE
40
41inline void getBounds(const G3D::Vector3& v, G3D::AABox& out) {
42    out = G3D::AABox(v);
43}
44
45
46inline void getBounds(const G3D::AABox& a, G3D::AABox& out) {
47    out = a;
48}
49
50inline void getBounds(const G3D::Sphere& s, G3D::AABox& out) {
51    s.getBounds(out);
52}
53
54
55inline void getBounds(const G3D::Box& b, G3D::AABox& out) {
56    b.getBounds(out);
57}
58
59
60inline void getBounds(const G3D::Triangle& t, G3D::AABox& out) {
61    t.getBounds(out);
62}
63
64
65
66inline void getBounds(const G3D::Vector3* v, G3D::AABox& out) {
67    out = G3D::AABox(*v);
68}
69
70
71inline void getBounds(const G3D::AABox* a, G3D::AABox& out) {
72    getBounds(*a, out);
73}
74
75inline void getBounds(const G3D::Sphere* s, G3D::AABox& out) {
76    s->getBounds(out);
77}
78
79
80inline void getBounds(const G3D::Box* b, G3D::AABox& out) {
81    b->getBounds(out);
82}
83
84inline void getBounds(const G3D::Triangle* t, G3D::AABox& out) {
85    t->getBounds(out);
86}
87namespace G3D {
88    namespace _internal {
89
90    /**
91     Wraps a pointer value so that it can be treated as the instance itself;
92     convenient for inserting pointers into a Table but using the
93     object equality instead of pointer equality.
94    */
95    template<class Type>
96    class Indirector {
97    public:
98        Type*         handle;
99
100        inline Indirector(Type* h) : handle(h) {}
101
102        inline Indirector() : handle(NULL) {}
103
104        /** Returns true iff the values referenced by the handles are equivalent. */
105        inline bool operator==(const Indirector& m) {
106            return *handle == *(m.handle);
107        }
108
109        inline bool operator==(const Type& m) {
110            return *handle == m;
111        }
112
113        inline size_t hashCode() const {
114            return handle->hashCode();
115        }
116    };
117 } // namespace internal
118} // namespace G3D
119
120template <class Handle>
121struct GHashCode< G3D::_internal::Indirector<Handle> >
122{
123    size_t operator()(const G3D::_internal::Indirector<Handle>& key) const { return key.hashCode(); }
124};
125
126namespace G3D {
127
128/**
129 A set that supports spatial queries using an axis-aligned
130 BSP tree for speed.
131
132 AABSPTree allows you to quickly find objects in 3D that lie within
133 a box or along a ray. For large sets of objects it is much faster
134 than testing each object for a collision.
135
136 AABSPTree is as powerful as but more general than a Quad Tree, Oct
137 Tree, or KD Tree, but less general than an unconstrained BSP tree
138 (which is much slower to create).
139 
140 Internally, objects
141 are arranged into an axis-aligned BSP-tree according to their
142 axis-aligned bounds.  This increases the cost of insertion to
143 O(log n) but allows fast overlap queries.
144
145 <B>Template Parameters</B>
146 <DT>The template parameter <I>T</I> must be one for which
147 the following functions are all overloaded:
148
149  <P><CODE>void ::getBounds(const T&, G3D::AABox&);</CODE>
150  <DT><CODE>bool ::operator==(const T&, const T&);</CODE>
151  <DT><CODE>unsigned int ::hashCode(const T&);</CODE>
152  <DT><CODE>T::T();</CODE> <I>(public constructor of no arguments)</I>
153
154 G3D provides these for common classes like G3D::Vector3 and G3D::Sphere.
155 If you use a custom class, or a pointer to a custom class, you will need
156 to define those functions.
157
158 <B>Moving %Set Members</B>
159 <DT>It is important that objects do not move without updating the
160 AABSPTree.  If the axis-aligned bounds of an object are about
161 to change, AABSPTree::remove it before they change and
162 AABSPTree::insert it again afterward.  For objects
163 where the hashCode and == operator are invariant with respect
164 to the 3D position,
165 you can use the AABSPTree::update method as a shortcut to
166 insert/remove an object in one step after it has moved.
167 
168
169 Note: Do not mutate any value once it has been inserted into AABSPTree. Values
170 are copied interally. All AABSPTree iterators convert to pointers to constant
171 values to reinforce this.
172
173 If you want to mutate the objects you intend to store in a AABSPTree
174 simply insert <I>pointers</I> to your objects instead of the objects
175 themselves, and ensure that the above operations are defined. (And
176 actually, because values are copied, if your values are large you may
177 want to insert pointers anyway, to save space and make the balance
178 operation faster.)
179
180 <B>Dimensions</B>
181 Although designed as a 3D-data structure, you can use the AABSPTree
182 for data distributed along 2 or 1 axes by simply returning bounds
183 that are always zero along one or more dimensions.
184
185*/
186namespace _AABSPTree {
187
188    /** Wrapper for a value that includes a cache of its bounds.
189        Except for the test value used in a set-query operation, there
190        is only ever one instance of the handle associated with any
191        value and the memberTable and Nodes maintain pointers to that
192        heap-allocated value.
193     */
194    template<class TValue>
195    class Handle {
196    public:
197        /** The bounds of each object are constrained to AABox::maxFinite */
198        AABox               bounds;
199
200        /** Center of bounds.  We cache this value to avoid recomputing it
201            during the median sort, and because MSVC 6 std::sort goes into
202            an infinite loop if we compute the midpoint on the fly (possibly
203            a floating point roundoff issue, where B<A and A<B both are true).*/
204        Vector3             center;
205
206        TValue              value;
207
208        Handle<TValue>() {}
209
210        inline Handle<TValue>(const TValue& v) : value(v) {
211            getBounds(v, bounds);
212            bounds = bounds.intersect(AABox::maxFinite());
213            center = bounds.center();
214        }
215
216        inline bool operator==(const Handle<TValue>& other) const {
217            return (*value).operator==(*other.value);
218        }
219
220        inline size_t hashCode() const {
221            return value->hashCode();
222        }
223    };
224
225    template<>
226    class Handle<Triangle> {
227    public:
228        /** The bounds of each object are constrained to AABox::maxFinite */
229        AABox          bounds;
230
231        /** Center of bounds.  We cache this value to avoid recomputing it
232            during the median sort, and because MSVC 6 std::sort goes into
233            an infinite loop if we compute the midpoint on the fly (possibly
234            a floating point roundoff issue, where B<A and A<B both are true).*/
235        Vector3        center;
236
237        Triangle       value;
238
239        Handle<Triangle>() {}
240
241        inline Handle<Triangle>(const Triangle& v) : value(v) {
242            getBounds(v, bounds);
243            bounds = bounds.intersect(AABox::maxFinite());
244            center = bounds.center();
245        }
246
247        inline bool operator==(const Handle<Triangle>& other) const {
248            return value.operator==(other.value);
249        }
250
251        inline size_t hashCode() const {
252            return value.hashCode();
253        }
254    };
255}
256
257template<class T> class AABSPTree {
258protected:
259public:
260
261
262    /** Returns the bounds of the sub array. Used by makeNode. */
263    static AABox computeBounds(
264    const Array<_AABSPTree::Handle<T>*>& point, 
265        int                   beginIndex,
266        int                   endIndex) {
267   
268        Vector3 lo = Vector3::inf();
269        Vector3 hi = -lo;
270
271        for (int p = beginIndex; p <= endIndex; ++p) {
272            lo = lo.min(point[p]->bounds.low());
273            hi = hi.max(point[p]->bounds.high());
274        }
275
276        return AABox(lo, hi);
277    }
278
279    /** Compares centers */
280    class CenterComparator {
281    public:
282            Vector3::Axis sortAxis;
283
284            CenterComparator(Vector3::Axis a) : sortAxis(a) {}
285
286            inline int operator()(_AABSPTree::Handle<T>* A, const _AABSPTree::Handle<T>* B) const {
287            float a = A->center[sortAxis];
288            float b = B->center[sortAxis];
289
290            if (a < b) {
291                return 1;
292            } else if (a > b) {
293                return -1;
294            } else {
295                return 0;
296            }
297            }
298    };
299
300
301    /** Compares bounds for strict >, <, or overlap*/
302    class BoundsComparator {
303    public:
304            Vector3::Axis sortAxis;
305
306            BoundsComparator(Vector3::Axis a) : sortAxis(a) {}
307
308            inline int operator()(_AABSPTree::Handle<T>* A, const _AABSPTree::Handle<T>* B) const {
309            const AABox& a = A->bounds;
310            const AABox& b = B->bounds;
311
312            if (a.high()[sortAxis] < b.low()[sortAxis]) {
313                return 1;
314            } else if (a.low()[sortAxis] > b.high()[sortAxis]) {
315                return -1;
316            } else {
317                return 0;
318            }
319            }
320    };
321
322
323    /** Compares bounds to the sort location */
324    class Comparator {
325    public:
326            Vector3::Axis sortAxis;
327            float sortLocation;
328
329            Comparator(Vector3::Axis a, float l) : sortAxis(a), sortLocation(l) {}
330
331            inline int operator()(_AABSPTree::Handle<T>* /*ignore*/, const _AABSPTree::Handle<T>* handle) const {
332            const AABox& box = handle->bounds;
333            debugAssert(ignore == NULL);
334
335                    if (box.high()[sortAxis] < sortLocation) {
336                // Box is strictly below the sort location
337                return -1;
338                    } else if (box.low()[sortAxis] > sortLocation) {
339                // Box is strictly above the sort location
340                            return 1;
341                    } else {
342                // Box overlaps the sort location
343                            return 0;
344                    }
345            }
346    };
347
348    // Using System::malloc with this class provided no speed improvement.
349    class Node {
350    public:
351
352        /** Spatial bounds on all values at this node and its children, based purely on
353            the parent's splitting planes.  May be infinite. */
354        AABox               splitBounds;
355
356        Vector3::Axis       splitAxis;
357
358        /** Location along the specified axis */
359        float               splitLocation;
360 
361        /** child[0] contains all values strictly
362            smaller than splitLocation along splitAxis.
363
364            child[1] contains all values strictly
365            larger.
366
367            Both may be NULL if there are not enough
368            values to bother recursing.
369        */
370        Node*               child[2];
371
372        /** Array of values at this node (i.e., values
373            straddling the split plane + all values if
374            this is a leaf node).
375
376            This is an array of pointers because that minimizes
377            data movement during tree building, which accounts
378            for about 15% of the time cost of tree building.
379          */
380        Array<_AABSPTree::Handle<T> * >      valueArray;
381
382        /** For each object in the value array, a copy of its bounds.
383            Packing these into an array at the node level
384            instead putting them in the valueArray improves
385            cache coherence, which is about a 3x performance
386            increase when performing intersection computations.
387          */
388        Array<AABox>        boundsArray;
389
390        /** Creates node with NULL children */
391        Node() {
392            splitAxis     = Vector3::X_AXIS;
393            splitLocation = 0;
394            splitBounds   = AABox(-Vector3::inf(), Vector3::inf());
395            for (int i = 0; i < 2; ++i) {
396                child[i] = NULL;
397            }
398        }
399
400        /**
401         Doesn't clone children.
402         */
403        Node(const Node& other) : valueArray(other.valueArray), boundsArray(other.boundsArray) {
404            splitAxis       = other.splitAxis;
405            splitLocation   = other.splitLocation;
406            splitBounds     = other.splitBounds;           
407            for (int i = 0; i < 2; ++i) {
408                child[i] = NULL;
409            }
410        }
411
412        /** Copies the specified subarray of pt into point, NULLs the children.
413            Assumes a second pass will set splitBounds. */
414        Node(const Array<_AABSPTree::Handle<T> * >& pt) : valueArray(pt) {
415            splitAxis     = Vector3::X_AXIS;
416            splitLocation = 0;
417            for (int i = 0; i < 2; ++i) {
418                child[i] = NULL;
419            }
420
421            boundsArray.resize(valueArray.size());
422            for (int i = 0; i < valueArray.size(); ++i) {
423                boundsArray[i] = valueArray[i]->bounds;
424            }
425        }
426
427        /** Deletes the children (but not the values) */
428        ~Node() {
429            for (int i = 0; i < 2; ++i) {
430                delete child[i];
431            }
432        }
433
434        /** Returns true if this node is a leaf (no children) */
435        inline bool isLeaf() const {
436            return (child[0] == NULL) && (child[1] == NULL);
437        }
438
439
440        /**
441         Recursively appends all handles and children's handles
442         to the array.
443         */
444        void getHandles(Array<_AABSPTree::Handle<T> * >& handleArray) const {
445            handleArray.append(valueArray);
446            for (int i = 0; i < 2; ++i) {
447                if (child[i] != NULL) {
448                    child[i]->getHandles(handleArray);
449                }
450            }
451        }
452
453            void verifyNode(const Vector3& lo, const Vector3& hi) {
454            //          debugPrintf("Verifying: split %d @ %f [%f, %f, %f], [%f, %f, %f]\n",
455            //                      splitAxis, splitLocation, lo.x, lo.y, lo.z, hi.x, hi.y, hi.z);
456
457            debugAssert(lo == splitBounds.low());
458            debugAssert(hi == splitBounds.high());
459
460                    for (int i = 0; i < valueArray.length(); ++i) {
461                            const AABox& b = valueArray[i]->bounds;
462                debugAssert(b == boundsArray[i]);
463
464                            for(int axis = 0; axis < 3; ++axis) {
465                                    debugAssert(b.low()[axis] <= b.high()[axis]);
466                                    debugAssert(b.low()[axis] >= lo[axis]);
467                                    debugAssert(b.high()[axis] <= hi[axis]);
468                            }
469                    }
470
471                    if (child[0] || child[1]) {
472                            debugAssert(lo[splitAxis] < splitLocation);
473                            debugAssert(hi[splitAxis] > splitLocation);
474                    }
475
476                    Vector3 newLo = lo;
477                    newLo[splitAxis] = splitLocation;
478                    Vector3 newHi = hi;
479                    newHi[splitAxis] = splitLocation;
480
481                    if (child[0] != NULL) {
482                            child[0]->verifyNode(lo, newHi);
483                    }
484
485                    if (child[1] != NULL) {
486                            child[1]->verifyNode(newLo, hi);
487                    }
488            }
489
490#if 0
491        /**
492          Stores the locations of the splitting planes (the structure but not the content)
493          so that the tree can be quickly rebuilt from a previous configuration without
494          calling balance.
495         */
496        static void serializeStructure(const Node* n, BinaryOutput& bo) {
497            if (n == NULL) {
498                bo.writeUInt8(0);
499            } else {
500                bo.writeUInt8(1);
501                n->splitBounds.serialize(bo);
502                serialize(n->splitAxis, bo);
503                bo.writeFloat32(n->splitLocation);
504                for (int c = 0; c < 2; ++c) {
505                    serializeStructure(n->child[c], bo);
506                }
507            }
508        }
509
510        /** Clears the member table */
511        static Node* deserializeStructure(BinaryInput& bi) {
512            if (bi.readUInt8() == 0) {
513                return NULL;
514            } else {
515                Node* n = new Node();
516                n->splitBounds.deserialize(bi);
517                deserialize(n->splitAxis, bi);
518                n->splitLocation = bi.readFloat32();
519                for (int c = 0; c < 2; ++c) {
520                    n->child[c] = deserializeStructure(bi);
521                }
522            }
523        }
524#endif
525        /** Returns the deepest node that completely contains bounds. */
526        Node* findDeepestContainingNode(const AABox& bounds) {
527
528            // See which side of the splitting plane the bounds are on
529            if (bounds.high()[splitAxis] < splitLocation) {
530                // Bounds are on the low side.  Recurse into the child
531                // if it exists.
532                if (child[0] != NULL) {
533                    return child[0]->findDeepestContainingNode(bounds);
534                }
535            } else if (bounds.low()[splitAxis] > splitLocation) {
536                // Bounds are on the high side, recurse into the child
537                // if it exists.
538                if (child[1] != NULL) {
539                    return child[1]->findDeepestContainingNode(bounds);
540                }
541            }
542
543            // There was no containing child, so this node is the
544            // deepest containing node.
545            return this;
546        }
547
548
549        /** Appends all members that intersect the box.
550            If useSphere is true, members that pass the box test
551            face a second test against the sphere. */
552        void getIntersectingMembers(
553            const AABox&        box,
554            const Sphere&       sphere,
555            Array<T>&           members,
556            bool                useSphere) const {
557
558            // Test all values at this node
559            for (int v = 0; v < boundsArray.size(); ++v) {
560                const AABox& bounds = boundsArray[v];
561                if (bounds.intersects(box) &&
562                    (! useSphere || bounds.intersects(sphere))) {
563                    members.append(valueArray[v]->value);
564                }
565            }
566
567            // If the left child overlaps the box, recurse into it
568            if ((child[0] != NULL) && (box.low()[splitAxis] < splitLocation)) {
569                child[0]->getIntersectingMembers(box, sphere, members, useSphere);
570            }
571
572            // If the right child overlaps the box, recurse into it
573            if ((child[1] != NULL) && (box.high()[splitAxis] > splitLocation)) {
574                child[1]->getIntersectingMembers(box, sphere, members, useSphere);
575            }
576        }
577
578        /**
579         Recurse through the tree, assigning splitBounds fields.
580         */
581        void assignSplitBounds(const AABox& myBounds) {
582            splitBounds = myBounds;
583
584            AABox childBounds[2];
585            myBounds.split(splitAxis, splitLocation, childBounds[0], childBounds[1]);
586
587#           if defined(G3D_DEBUG) && defined(VERIFY_TREE)
588                // Verify the split
589                for (int v = 0; v < boundsArray.size(); ++v) {
590                    const AABox& bounds = boundsArray[v];
591                    debugAssert(myBounds.contains(bounds));
592                }
593#           endif
594
595            for (int c = 0; c < 2; ++c) {
596                if (child[c]) {
597                    child[c]->assignSplitBounds(childBounds[c]);
598                }
599            }
600        }
601
602        /** Returns true if the ray intersects this node */
603        bool intersects(const Ray& ray, float distance) const {
604            // See if the ray will ever hit this node or its children
605            Vector3 location;
606            bool alreadyInsideBounds = false;
607            bool rayWillHitBounds = 
608                VMAP::MyCollisionDetection::collisionLocationForMovingPointFixedAABox(
609                    ray.origin, ray.direction, splitBounds, location, alreadyInsideBounds);
610           
611            bool canHitThisNode = (alreadyInsideBounds ||               
612                (rayWillHitBounds && ((location - ray.origin).squaredLength() < square(distance))));
613
614            return canHitThisNode;
615        }
616
617        template<typename RayCallback>
618        void intersectRay(
619            const Ray& ray, 
620            RayCallback& intersectCallback, 
621            float& distance,
622            bool pStopAtFirstHit,
623            bool intersectCallbackIsFast) const {
624                float enterDistance = distance;
625           
626            if (! intersects(ray, distance)) {
627                // The ray doesn't hit this node, so it can't hit the children of the node.
628                return;
629            }
630
631            // Test for intersection against every object at this node.
632            for (int v = 0; v < valueArray.size(); ++v) {       
633                bool canHitThisObject = true;
634
635                if (! intersectCallbackIsFast) {
636                    // See if
637                    Vector3 location;
638                    const AABox& bounds = boundsArray[v];
639                    bool alreadyInsideBounds = false;
640                    bool rayWillHitBounds = 
641                        VMAP::MyCollisionDetection::collisionLocationForMovingPointFixedAABox(
642                            ray.origin, ray.direction, bounds, location, alreadyInsideBounds);
643
644                    canHitThisObject = (alreadyInsideBounds ||               
645                        (rayWillHitBounds && ((location - ray.origin).squaredLength() < square(distance))));
646                }
647
648                if (canHitThisObject) {
649                    // It is possible that this ray hits this object.  Look for the intersection using the
650                    // callback.
651                    const T& value = valueArray[v]->value;
652                    intersectCallback(ray, value, pStopAtFirstHit, distance);
653                }
654                if(pStopAtFirstHit && distance < enterDistance)
655                    return;
656            }
657
658            // There are three cases to consider next:
659            //
660            //  1. the ray can start on one side of the splitting plane and never enter the other,
661            //  2. the ray can start on one side and enter the other, and
662            //  3. the ray can travel exactly down the splitting plane
663
664            enum {NONE = -1};
665            int firstChild = NONE;
666            int secondChild = NONE;
667
668            if (ray.origin[splitAxis] < splitLocation) {
669               
670                // The ray starts on the small side
671                firstChild = 0;
672
673                if (ray.direction[splitAxis] > 0) {
674                    // The ray will eventually reach the other side
675                    secondChild = 1;
676                }
677
678            } else if (ray.origin[splitAxis] > splitLocation) {
679
680                // The ray starts on the large side
681                firstChild = 1;
682
683                if (ray.direction[splitAxis] < 0) {
684                    secondChild = 0;
685                }
686            } else {
687                // The ray starts on the splitting plane
688                if (ray.direction[splitAxis] < 0) {
689                    // ...and goes to the small side
690                    firstChild = 0;
691                } else if (ray.direction[splitAxis] > 0) {
692                    // ...and goes to the large side
693                    firstChild = 1;
694                }
695            }
696
697            // Test on the side closer to the ray origin.
698            if ((firstChild != NONE) && child[firstChild]) {
699                child[firstChild]->intersectRay(ray, intersectCallback, distance, pStopAtFirstHit, intersectCallbackIsFast);
700                if(pStopAtFirstHit && distance < enterDistance)
701                    return;
702            }
703
704            if (ray.direction[splitAxis] != 0) {
705                // See if there was an intersection before hitting the splitting plane. 
706                // If so, there is no need to look on the far side and recursion terminates.
707                float distanceToSplittingPlane = (splitLocation - ray.origin[splitAxis]) / ray.direction[splitAxis];
708                if (distanceToSplittingPlane > distance) {
709                    // We aren't going to hit anything else before hitting the splitting plane,
710                    // so don't bother looking on the far side of the splitting plane at the other
711                    // child.
712                    return;
713                }
714            }
715
716            // Test on the side farther from the ray origin.
717            if ((secondChild != NONE) && child[secondChild]) {
718                child[secondChild]->intersectRay(ray, intersectCallback, distance, pStopAtFirstHit, intersectCallbackIsFast);
719            }
720
721        }
722    };
723
724
725    /**
726     Recursively subdivides the subarray.
727   
728     Clears the source array as soon as it is no longer needed.
729
730     Call assignSplitBounds() on the root node after making a tree.
731     */
732    Node* makeNode(
733        Array<_AABSPTree::Handle<T> * >& source, 
734        int valuesPerNode, 
735        int numMeanSplits,
736        Array<_AABSPTree::Handle<T> * >& temp)  {
737
738            Node* node = NULL;
739           
740            if (source.size() <= valuesPerNode) {
741                    // Make a new leaf node
742                    node = new Node(source);
743                   
744                    // Set the pointers in the memberTable
745                    for (int i = 0; i < source.size(); ++i) {
746                            memberTable.set(Member(source[i]), node);
747                    }
748            source.clear();
749                   
750        } else {
751                    // Make a new internal node
752                    node = new Node();
753                   
754            const AABox bounds = computeBounds(source, 0, source.size() - 1);
755                    const Vector3 extent = bounds.high() - bounds.low();
756                   
757                    Vector3::Axis splitAxis = extent.primaryAxis();
758                   
759            float splitLocation;
760
761            // Arrays for holding the children
762            Array<_AABSPTree::Handle<T> * > lt, gt;
763               
764            if (numMeanSplits <= 0) {
765
766                source.medianPartition(lt, node->valueArray, gt, temp, CenterComparator(splitAxis));
767
768                // Choose the split location to be the center of whatever fell in the center
769                splitLocation = node->valueArray[0]->center[splitAxis];
770
771                // Some of the elements in the lt or gt array might really overlap the split location.
772                // Move them as needed.
773                for (int i = 0; i < lt.size(); ++i) {
774                    const AABox& bounds = lt[i]->bounds;
775                    if ((bounds.low()[splitAxis] <= splitLocation) && (bounds.high()[splitAxis] >= splitLocation)) {
776                        node->valueArray.append(lt[i]);
777                        // Remove this element and process the new one that
778                        // is swapped in in its place.
779                        lt.fastRemove(i); --i;
780                    }
781                }
782
783                for (int i = 0; i < gt.size(); ++i) {
784                    const AABox& bounds = gt[i]->bounds;
785                    if ((bounds.low()[splitAxis] <= splitLocation) && (bounds.high()[splitAxis] >= splitLocation)) {
786                        node->valueArray.append(gt[i]);
787                        // Remove this element and process the new one that
788                        // is swapped in in its place.
789                        gt.fastRemove(i); --i;
790                    }
791                }           
792
793                if ((node->valueArray.size() > (source.size() / 2)) &&
794                    (source.size() > 6)) {
795                    // This was a bad partition; we ended up putting the splitting plane right in the middle of most of the
796                    // objects.  We could try to split on a different axis, or use a different partition (e.g., the extents mean,
797                    // or geometric mean).  This implementation falls back on the extents mean, since that case is already handled
798                    // below.
799                    numMeanSplits = 1;
800                }
801            }
802
803            // Note: numMeanSplits may have been increased by the code in the previous case above in order to
804            // force a re-partition.
805
806            if (numMeanSplits > 0) {
807                // Split along the mean
808                splitLocation = (bounds.high()[splitAxis] + 
809                                 bounds.low()[splitAxis]) / 2.0;
810               
811                source.partition(NULL, lt, node->valueArray, gt, Comparator(splitAxis, splitLocation));
812
813                // The Comparator ensures that elements are strictly on the correct side of the split
814            }
815
816
817#           if defined(G3D_DEBUG) && defined(VERIFY_TREE)
818                debugAssert(lt.size() + node->valueArray.size() + gt.size() == source.size());
819                // Verify that all objects ended up on the correct side of the split.
820                // (i.e., make sure that the Array partition was correct)
821                for (int i = 0; i < lt.size(); ++i) {
822                    const AABox& bounds  = lt[i]->bounds;
823                    debugAssert(bounds.high()[splitAxis] < splitLocation);
824                }
825
826                for (int i = 0; i < gt.size(); ++i) {
827                    const AABox& bounds  = gt[i]->bounds;
828                    debugAssert(bounds.low()[splitAxis] > splitLocation);
829                }
830
831                for (int i = 0; i < node->valueArray.size(); ++i) {
832                    const AABox& bounds  = node->valueArray[i]->bounds;
833                    debugAssert(bounds.high()[splitAxis] >= splitLocation);
834                    debugAssert(bounds.low()[splitAxis] <= splitLocation);
835                }
836#           endif
837
838            // The source array is no longer needed
839            source.clear();
840
841            node->splitAxis = splitAxis;
842            node->splitLocation = splitLocation;
843
844            // Update the bounds array and member table
845            node->boundsArray.resize(node->valueArray.size());
846            for (int i = 0; i < node->valueArray.size(); ++i) {
847                _AABSPTree::Handle<T> * v = node->valueArray[i];
848                node->boundsArray[i] = v->bounds;
849                            memberTable.set(Member(v), node);
850            }
851
852            if (lt.size() > 0) {                   
853                            node->child[0] = makeNode(lt, valuesPerNode, numMeanSplits - 1, temp);
854                    }
855                   
856                    if (gt.size() > 0) {
857                            node->child[1] = makeNode(gt, valuesPerNode, numMeanSplits - 1, temp);
858                    }
859                   
860            }
861           
862            return node;
863    }
864
865    /**
866     Recursively clone the passed in node tree, setting
867     pointers for members in the memberTable as appropriate.
868     called by the assignment operator.
869     */
870    Node* cloneTree(Node* src) {
871        Node* dst = new Node(*src);
872
873        // Make back pointers
874        for (int i = 0; i < dst->valueArray.size(); ++i) {
875            memberTable.set(Member(dst->valueArray[i]), dst);
876        }
877
878        // Clone children
879        for (int i = 0; i < 2; ++i) {
880            if (src->child[i] != NULL) {
881                dst->child[i] = cloneTree(src->child[i]);
882            }
883        }
884
885        return dst;
886    }
887
888   /**
889    Wrapper for a Handle; used to create a memberTable that acts like Table<Handle, Node*> but
890    stores only Handle* internally to avoid memory copies.
891    */
892    typedef _internal::Indirector<_AABSPTree::Handle<T> > Member;
893
894    typedef Table<Member, Node*> MemberTable;
895
896    /** Maps members to the node containing them */
897    MemberTable             memberTable;
898
899    Node*                   root;
900
901public:
902
903    /** To construct a balanced tree, insert the elements and then call
904      AABSPTree::balance(). */
905    AABSPTree() : root(NULL) {}
906
907
908    AABSPTree(const AABSPTree& src) : root(NULL) {
909        *this = src;
910    }
911
912
913    AABSPTree& operator=(const AABSPTree& src) {
914        delete root;
915        // Clone tree takes care of filling out the memberTable.
916        root = cloneTree(src.root);
917        return *this;
918    }
919
920
921    ~AABSPTree() {
922        clear();
923    }
924
925    /**
926     Throws out all elements of the set.
927     */
928    void clear() {
929        typedef typename Table<_internal::Indirector<_AABSPTree::Handle<T> >, Node* >::Iterator It;
930 
931        // Delete all handles stored in the member table
932        It cur = memberTable.begin();
933        It end = memberTable.end();
934        while (cur != end) {
935            delete cur->key.handle;
936            cur->key.handle = NULL;
937            ++cur;
938        }
939        memberTable.clear();
940
941        // Delete the tree structure itself
942        delete root;
943        root = NULL;
944    }
945
946    size_t size() const {
947        return memberTable.size();
948    }
949
950    /**
951     Inserts an object into the set if it is not
952     already present.  O(log n) time.  Does not
953     cause the tree to be balanced.
954     */
955    void insert(const T& value) {
956        if (contains(value)) {
957            // Already in the set
958            return;
959        }
960
961        _AABSPTree::Handle<T>* h = new _AABSPTree::Handle<T>(value);
962
963        if (root == NULL) {
964            // This is the first node; create a root node
965            root = new Node();
966        }
967
968        Node* node = root->findDeepestContainingNode(h->bounds);
969
970        // Insert into the node
971        node->valueArray.append(h);
972        node->boundsArray.append(h->bounds);
973       
974        // Insert into the node table
975        Member m(h);
976        memberTable.set(m, node);
977    }
978
979    /** Inserts each elements in the array in turn.  If the tree
980        begins empty (no structure and no elements), this is faster
981        than inserting each element in turn.  You still need to balance
982        the tree at the end.*/
983    void insert(const Array<T>& valueArray) {
984        if (root == NULL) {
985            // Optimized case for an empty tree; don't bother
986            // searching or reallocating the root node's valueArray
987            // as we incrementally insert.
988            root = new Node();
989            root->valueArray.resize(valueArray.size());
990            root->boundsArray.resize(root->valueArray.size());
991            for (int i = 0; i < valueArray.size(); ++i) {
992                // Insert in opposite order so that we have the exact same
993                // data structure as if we inserted each (i.e., order is reversed
994                // from array).
995                _AABSPTree::Handle<T>* h = new _AABSPTree::Handle<T>(valueArray[i]);
996                int j = valueArray.size() - i - 1;
997                root->valueArray[j] = h;
998                root->boundsArray[j] = h->bounds;
999                memberTable.set(Member(h), root);
1000            }
1001
1002        } else {
1003            // Insert at appropriate tree depth.
1004            for (int i = 0; i < valueArray.size(); ++i) {
1005                insert(valueArray[i]);
1006            }
1007        }
1008    }
1009
1010
1011    /**
1012     Returns true if this object is in the set, otherwise
1013     returns false.  O(1) time.
1014     */
1015    bool contains(const T& value) {
1016        // Temporarily create a handle and member
1017        _AABSPTree::Handle<T> h(value);
1018        return memberTable.containsKey(Member(&h));
1019    }
1020
1021
1022    /**
1023     Removes an object from the set in O(1) time.
1024     It is an error to remove members that are not already
1025     present.  May unbalance the tree. 
1026     
1027     Removing an element never causes a node (split plane) to be removed...
1028     nodes are only changed when the tree is rebalanced.  This behavior
1029     is desirable because it allows the split planes to be serialized,
1030     and then deserialized into an empty tree which can be repopulated.
1031    */
1032    void remove(const T& value) {
1033        debugAssertM(contains(value),
1034            "Tried to remove an element from a "
1035            "AABSPTree that was not present");
1036
1037        // Get the list of elements at the node
1038        _AABSPTree::Handle<T> h(value);
1039        Member m(&h);
1040
1041        Array<_AABSPTree::Handle<T> * >& list = memberTable[m]->valueArray;
1042
1043        _AABSPTree::Handle<T>* ptr = NULL;
1044
1045        // Find the element and remove it
1046        for (int i = list.length() - 1; i >= 0; --i) {
1047            if (list[i]->value == value) {
1048                // This was the element.  Grab the pointer so that
1049                // we can delete it below
1050                ptr = list[i];
1051
1052                // Remove the handle from the node
1053                list.fastRemove(i);
1054
1055                // Remove the corresponding bounds
1056                memberTable[m]->boundsArray.fastRemove(i);
1057                break;
1058            }
1059        }
1060
1061        // Remove the member
1062        memberTable.remove(m);
1063
1064        // Delete the handle data structure
1065        delete ptr;
1066        ptr = NULL;
1067    }
1068
1069
1070    /**
1071     If the element is in the set, it is removed.
1072     The element is then inserted.
1073
1074     This is useful when the == and hashCode methods
1075     on <I>T</I> are independent of the bounds.  In
1076     that case, you may call update(v) to insert an
1077     element for the first time and call update(v)
1078     again every time it moves to keep the tree
1079     up to date.
1080     */
1081    void update(const T& value) {
1082        if (contains(value)) {
1083            remove(value);
1084        }
1085        insert(value);
1086    }
1087
1088
1089    /**
1090     Rebalances the tree (slow).  Call when objects
1091     have moved substantially from their original positions
1092     (which unbalances the tree and causes the spatial
1093     queries to be slow).
1094     
1095     @param valuesPerNode Maximum number of elements to put at
1096     a node.
1097
1098     @param numMeanSplits numMeanSplits = 0 gives a
1099     fully axis aligned BSP-tree, where the balance operation attempts to balance
1100     the tree so that every splitting plane has an equal number of left
1101     and right children (i.e. it is a <B>median</B> split along that axis). 
1102     This tends to maximize average performance. 
1103
1104     You can override this behavior by
1105     setting a number of <B>mean</B> (average) splits.  numMeanSplits = MAX_INT
1106     creates a full oct-tree, which tends to optimize peak performance at the expense of
1107     average performance.  It tends to have better clustering behavior when
1108     members are not uniformly distributed.
1109     */
1110    void balance(int valuesPerNode = 5, int numMeanSplits = 3) {
1111        if (root == NULL) {
1112            // Tree is empty
1113            return;
1114        }
1115
1116        // Get all handles and delete the old tree structure
1117        Node* oldRoot = root;
1118        for (int c = 0; c < 2; ++c) {
1119            if (root->child[c] != NULL) {
1120                root->child[c]->getHandles(root->valueArray);
1121
1122                // Delete the child; this will delete all structure below it
1123                delete root->child[c];
1124                root->child[c] = NULL;
1125            }
1126        }
1127
1128        Array<_AABSPTree::Handle<T> * > temp;
1129        // Make a new root.  Work with a copy of the value array because
1130        // makeNode clears the source array as it progresses
1131        Array<_AABSPTree::Handle<T> * > copy(oldRoot->valueArray);
1132        root = makeNode(copy, valuesPerNode, numMeanSplits, temp);
1133
1134        // Throw away the old root node
1135        delete oldRoot;
1136        oldRoot = NULL;
1137
1138        // Walk the tree, assigning splitBounds.  We start with unbounded
1139        // space.  This will override the current member table.
1140        root->assignSplitBounds(AABox::maxFinite());
1141
1142#       ifdef _DEBUG
1143            // Ensure that the balanced tree is till correct
1144            root->verifyNode(Vector3::minFinite(), Vector3::maxFinite());
1145#       endif
1146    }
1147
1148protected:
1149
1150    /**
1151     @param parentMask The mask that this node returned from culledBy.
1152     */
1153    static void getIntersectingMembers(
1154        const Array<Plane>&         plane,
1155        Array<T>&                   members,
1156        Node*                       node,
1157        uint32                      parentMask) {
1158
1159        int dummy;
1160
1161        if (parentMask == 0) {
1162            // None of these planes can cull anything
1163            for (int v = node->valueArray.size() - 1; v >= 0; --v) {
1164                members.append(node->valueArray[v]->value);
1165            }
1166
1167            // Iterate through child nodes
1168            for (int c = 0; c < 2; ++c) {
1169                if (node->child[c]) {
1170                    getIntersectingMembers(plane, members, node->child[c], 0);
1171                }
1172            }
1173        } else {
1174
1175            // Test values at this node against remaining planes
1176            for (int v = node->boundsArray.size() - 1; v >= 0; --v) {
1177                if (! node->boundsArray[v].culledBy(plane, dummy, parentMask)) {
1178                    members.append(node->valueArray[v]->value);
1179                }
1180            }
1181
1182            uint32 childMask  = 0xFFFFFF;
1183
1184            // Iterate through child nodes
1185            for (int c = 0; c < 2; ++c) {
1186                if (node->child[c] &&
1187                    ! node->child[c]->splitBounds.culledBy(plane, dummy, parentMask, childMask)) {
1188                    // This node was not culled
1189                    getIntersectingMembers(plane, members, node->child[c], childMask);
1190                }
1191            }
1192        }
1193    }
1194
1195public:
1196
1197    /**
1198     Returns all members inside the set of planes. 
1199      @param members The results are appended to this array.
1200     */
1201    void getIntersectingMembers(const Array<Plane>& plane, Array<T>& members) const {
1202        if (root == NULL) {
1203            return;
1204        }
1205
1206        getIntersectingMembers(plane, members, root, 0xFFFFFF);
1207    }
1208
1209    /**
1210     Typically used to find all visible
1211     objects inside the view frustum (see also GCamera::getClipPlanes)... i.e. all objects
1212     <B>not<B> culled by frustum.
1213
1214     Example:
1215      <PRE>
1216        Array<Object*>  visible;
1217        tree.getIntersectingMembers(camera.frustum(), visible);
1218        // ... Draw all objects in the visible array.
1219      </PRE>
1220      @param members The results are appended to this array.
1221      */
1222    void getIntersectingMembers(const GCamera::Frustum& frustum, Array<T>& members) const {
1223        Array<Plane> plane;
1224       
1225        for (int i = 0; i < frustum.faceArray.size(); ++i) {
1226            plane.append(frustum.faceArray[i].plane);
1227        }
1228
1229        getIntersectingMembers(plane, members);
1230    }
1231
1232    /**
1233     C++ STL style iterator variable.  See beginBoxIntersection().
1234     The iterator overloads the -> (dereference) operator, so this
1235     acts like a pointer to the current member.
1236     */
1237    // This iterator turns Node::getIntersectingMembers into a
1238    // coroutine.  It first translates that method from recursive to
1239    // stack based, then captures the system state (analogous to a Scheme
1240    // continuation) after each element is appended to the member array,
1241    // and allowing the computation to be restarted.
1242    class BoxIntersectionIterator {
1243    private:
1244        friend class AABSPTree<T>;
1245
1246        /** True if this is the "end" iterator instance */
1247        bool            isEnd;
1248
1249        /** The box that we're testing against. */
1250        AABox           box;
1251
1252        /** Node that we're currently looking at.  Undefined if isEnd
1253            is true. */
1254        Node*           node;
1255
1256        /** Nodes waiting to be processed */
1257        // We could use backpointers within the tree and careful
1258        // state management to avoid ever storing the stack-- but
1259        // it is much easier this way and only inefficient if the
1260        // caller uses post increment (which they shouldn't!).
1261        Array<Node*>    stack;
1262
1263        /** The next index of current->valueArray to return.
1264            Undefined when isEnd is true.*/
1265        int             nextValueArrayIndex;
1266
1267        BoxIntersectionIterator() : isEnd(true) {}
1268       
1269        BoxIntersectionIterator(const AABox& b, const Node* root) : 
1270           isEnd(root == NULL), box(b), 
1271           node(const_cast<Node*>(root)), nextValueArrayIndex(-1) {
1272
1273           // We intentionally start at the "-1" index of the current
1274           // node so we can use the preincrement operator to move
1275           // ourselves to element 0 instead of repeating all of the
1276           // code from the preincrement method.  Note that this might
1277           // cause us to become the "end" instance.
1278           ++(*this);
1279        }
1280
1281    public:
1282
1283        inline bool operator!=(const BoxIntersectionIterator& other) const {
1284            return ! (*this == other);
1285        }
1286
1287        bool operator==(const BoxIntersectionIterator& other) const {
1288            if (isEnd) {
1289                return other.isEnd;
1290            } else if (other.isEnd) {
1291                return false;
1292            } else {
1293                // Two non-end iterators; see if they match.  This is kind of
1294                // silly; users shouldn't call == on iterators in general unless
1295                // one of them is the end iterator.
1296                if ((box != other.box) || (node != other.node) || 
1297                    (nextValueArrayIndex != other.nextValueArrayIndex) ||
1298                    (stack.length() != other.stack.length())) {
1299                    return false;
1300                }
1301
1302                // See if the stacks are the same
1303                for (int i = 0; i < stack.length(); ++i) {
1304                    if (stack[i] != other.stack[i]) {
1305                        return false;
1306                    }
1307                }
1308
1309                // We failed to find a difference; they must be the same
1310                return true;
1311            }
1312        }
1313
1314        /**
1315         Pre increment.
1316         */
1317        BoxIntersectionIterator& operator++() {
1318            ++nextValueArrayIndex;
1319
1320                        bool foundIntersection = false;
1321            while (! isEnd && ! foundIntersection) {
1322
1323                                // Search for the next node if we've exhausted this one
1324                while ((! isEnd) &&  (nextValueArrayIndex >= node->valueArray.length())) {
1325                                        // If we entered this loop, then the iterator has exhausted the elements at
1326                                        // node (possibly because it just switched to a child node with no members).
1327                                        // This loop continues until it finds a node with members or reaches
1328                                        // the end of the whole intersection search.
1329
1330                                        // If the right child overlaps the box, push it onto the stack for
1331                                        // processing.
1332                                        if ((node->child[1] != NULL) &&
1333                                                (box.high()[node->splitAxis] > node->splitLocation)) {
1334                                                stack.push(node->child[1]);
1335                                        }
1336               
1337                                        // If the left child overlaps the box, push it onto the stack for
1338                                        // processing.
1339                                        if ((node->child[0] != NULL) &&
1340                                                (box.low()[node->splitAxis] < node->splitLocation)) {
1341                                                stack.push(node->child[0]);
1342                                        }
1343
1344                                        if (stack.length() > 0) {
1345                                                // Go on to the next node (which may be either one of the ones we
1346                                                // just pushed, or one from farther back the tree).
1347                                                node = stack.pop();
1348                                                nextValueArrayIndex = 0;
1349                                        } else {
1350                                                // That was the last node; we're done iterating
1351                                                isEnd = true;
1352                                        }
1353                                }
1354
1355                                // Search for the next intersection at this node until we run out of children
1356                                while (! isEnd && ! foundIntersection && (nextValueArrayIndex < node->valueArray.length())) {
1357                                        if (box.intersects(node->boundsArray[nextValueArrayIndex])) {
1358                                                foundIntersection = true;
1359                                        } else {
1360                                                ++nextValueArrayIndex;
1361                                                // If we exhaust this node, we'll loop around the master loop
1362                                                // to find a new node.
1363                                        }
1364                                }
1365            }
1366
1367            return *this;
1368        }
1369
1370    private:
1371        /**
1372         Post increment (much slower than preincrement!).  Intentionally overloaded to preclude accidentally slow code.
1373         */
1374        BoxIntersectionIterator operator++(int);
1375        /*{
1376            BoxIntersectionIterator old = *this;
1377            ++this;
1378            return old;
1379        }*/
1380
1381    public:
1382
1383        /** Overloaded dereference operator so the iterator can masquerade as a pointer
1384            to a member */
1385        const T& operator*() const {
1386            alwaysAssertM(! isEnd, "Can't dereference the end element of an iterator");
1387            return node->valueArray[nextValueArrayIndex]->value;
1388        }
1389
1390        /** Overloaded dereference operator so the iterator can masquerade as a pointer
1391            to a member */
1392        T const * operator->() const {
1393            alwaysAssertM(! isEnd, "Can't dereference the end element of an iterator");
1394            return &(stack.last()->valueArray[nextValueArrayIndex]->value);
1395        }
1396
1397        /** Overloaded cast operator so the iterator can masquerade as a pointer
1398            to a member */
1399        operator T*() const {
1400            alwaysAssertM(! isEnd, "Can't dereference the end element of an iterator");
1401            return &(stack.last()->valueArray[nextValueArrayIndex]->value);
1402        }
1403    };
1404
1405
1406    /**
1407     Iterates through the members that intersect the box
1408     */
1409    BoxIntersectionIterator beginBoxIntersection(const AABox& box) const {
1410        return BoxIntersectionIterator(box, root);
1411    }
1412
1413    BoxIntersectionIterator endBoxIntersection() const {
1414        // The "end" iterator instance
1415        return BoxIntersectionIterator();
1416    }
1417
1418    /**
1419     Appends all members whose bounds intersect the box.
1420     See also AABSPTree::beginBoxIntersection.
1421     */
1422    void getIntersectingMembers(const AABox& box, Array<T>& members) const {
1423        if (root == NULL) {
1424            return;
1425        }
1426        root->getIntersectingMembers(box, Sphere(Vector3::zero(), 0), members, false);
1427    }
1428
1429
1430    /**
1431     Invoke a callback for every member along a ray until the closest intersection is found.
1432
1433     @param callback either a function or an instance of a class with an overloaded operator() of the form:
1434             
1435            <code>void callback(const Ray& ray, const T& object, float& distance)</code>.  If the ray hits the object
1436            before travelling distance <code>distance</code>, updates <code>distance</code> with the new distance to
1437            the intersection, otherwise leaves it unmodified.  A common example is:
1438
1439            <pre>
1440            class Entity {
1441            public:
1442
1443                void intersect(const Ray& ray, float& maxDist, Vector3& outLocation, Vector3& outNormal) {
1444                    float d = maxDist;
1445
1446                    // ... search for intersection distance d
1447
1448                    if ((d > 0) && (d < maxDist)) {
1449                        // Intersection occured
1450                        maxDist = d;
1451                        outLocation = ...;
1452                        outNormal = ...;
1453                    }
1454                }
1455            };
1456
1457            // Finds the surface normal and location of the first intersection with the scene
1458            class Intersection {
1459            public:
1460                Entity*     closestEntity;
1461                Vector3     hitLocation;
1462                Vector3     hitNormal;
1463
1464                void operator()(const Ray& ray, const Entity* entity, float& distance) {
1465                    entity->intersect(ray, distance, hitLocation, hitNormal);
1466                }
1467            };
1468
1469            AABSPTree<Entity*> scene;
1470
1471            Intersection intersection;
1472            float distance = inf();
1473            scene.intersectRay(camera.worldRay(x, y), intersection, distance);
1474          </pre>
1475
1476
1477     @param distance When the method is invoked, this is the maximum distance that the tree should search for an intersection.
1478     On return, this is set to the distance to the first intersection encountered.
1479
1480     @param intersectCallbackIsFast  If false, each object's bounds are tested before the intersectCallback is invoked.
1481      If the intersect callback runs at the same speed or faster than AABox-ray intersection, set this to true.
1482     */
1483    template<typename RayCallback>
1484    void intersectRay(
1485        const Ray& ray, 
1486        RayCallback& intersectCallback, 
1487        float& distance,
1488        bool pStopAtFirstHit,
1489        bool intersectCallbackIsFast = false) const {
1490       
1491        root->intersectRay(ray, intersectCallback, distance, pStopAtFirstHit, intersectCallbackIsFast);
1492
1493    }
1494
1495
1496    /**
1497      @param members The results are appended to this array.
1498     */
1499    void getIntersectingMembers(const Sphere& sphere, Array<T>& members) const {
1500        if (root == NULL) {
1501            return;
1502        }
1503
1504        AABox box;
1505        sphere.getBounds(box);
1506        root->getIntersectingMembers(box, sphere, members, true);
1507
1508    }
1509#if 0
1510    /**
1511      Stores the locations of the splitting planes (the structure but not the content)
1512      so that the tree can be quickly rebuilt from a previous configuration without
1513      calling balance.
1514     */
1515    void serializeStructure(BinaryOutput& bo) const {
1516        Node::serializeStructure(root, bo);
1517    }
1518
1519    /** Clears the member table */
1520    void deserializeStructure(BinaryInput& bi) {
1521        clear();
1522        root = Node::deserializeStructure(bi);
1523    }
1524#endif
1525    /**
1526     Returns an array of all members of the set.  See also AABSPTree::begin.
1527     */
1528    void getMembers(Array<T>& members) const {
1529        Array<Member> temp;
1530        memberTable.getKeys(temp);
1531        for (int i = 0; i < temp.size(); ++i) {
1532            members.append(temp[i].handle->value);
1533        }
1534    }
1535
1536
1537    /**
1538     C++ STL style iterator variable.  See begin().
1539     Overloads the -> (dereference) operator, so this acts like a pointer
1540     to the current member.
1541    */
1542    class Iterator {
1543    private:
1544        friend class AABSPTree<T>;
1545
1546        // Note: this is a Table iterator, we are currently defining
1547        // Set iterator
1548        typename Table<Member, Node*>::Iterator it;
1549
1550        Iterator(const typename Table<Member, Node*>::Iterator& it) : it(it) {}
1551
1552    public:
1553
1554        inline bool operator!=(const Iterator& other) const {
1555            return !(*this == other);
1556        }
1557
1558        bool operator==(const Iterator& other) const {
1559            return it == other.it;
1560        }
1561
1562        /**
1563         Pre increment.
1564         */
1565        Iterator& operator++() {
1566            ++it;
1567            return *this;
1568        }
1569
1570    private:
1571        /**
1572         Post increment (slower than preincrement).  Intentionally unimplemented to prevent slow code.
1573         */
1574        Iterator operator++(int);/* {
1575            Iterator old = *this;
1576            ++(*this);
1577            return old;
1578        }*/
1579    public:
1580
1581        const T& operator*() const {
1582            return it->key.handle->value;
1583        }
1584
1585        T* operator->() const {
1586            return &(it->key.handle->value);
1587        }
1588
1589        operator T*() const {
1590            return &(it->key.handle->value);
1591        }
1592    };
1593
1594
1595    /**
1596     C++ STL style iterator method.  Returns the first member. 
1597     Use preincrement (++entry) to get to the next element (iteration
1598     order is arbitrary). 
1599     Do not modify the set while iterating.
1600     */
1601    Iterator begin() const {
1602        return Iterator(memberTable.begin());
1603    }
1604
1605
1606    /**
1607     C++ STL style iterator method.  Returns one after the last iterator
1608     element.
1609     */
1610    Iterator end() const {
1611        return Iterator(memberTable.end());
1612    }
1613};
1614
1615}
1616
1617#endif
1618
1619
1620
Note: See TracBrowser for help on using the browser.