00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 #if !defined(_XRB_ENGINE2_QUADTREEBASE_HPP_)
00012 #define _XRB_ENGINE2_QUADTREEBASE_HPP_
00013 
00014 #include "xrb.hpp"
00015 
00016 #include <set>
00017 
00018 #include "xrb_engine2_object.hpp"
00019 #include "xrb_engine2_enums.hpp"
00020 #include "xrb_vector.hpp"
00021 
00022 namespace Xrb
00023 {
00024 
00025 namespace Engine2
00026 {
00027 
00028 class Object;
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 class QuadTree
00037 {
00038 public:
00039 
00040     virtual ~QuadTree () = 0;
00041 
00042     inline QuadTreeType GetQuadTreeType () const { return m_quad_tree_type; }
00043     inline QuadTree *Parent () const { return m_parent; }
00044     inline bool HasChildren () const { return m_child[0] != NULL; }
00045     
00046     QuadTree const *RootNode () const;
00047     inline FloatVector2 const &Center () const { return m_center; }
00048     inline Float SideLength () const { return 2.0f * m_half_side_length; }
00049     inline Float HalfSideLength () const { return m_half_side_length; }
00050     inline Float Radius () const { return m_radius; }
00051     inline Uint32 SubordinateObjectCount () const { return m_subordinate_object_count; }
00052     inline Uint32 SubordinateStaticObjectCount () const { return m_subordinate_static_object_count; }
00053     Object *SmallestObjectTouchingPoint (FloatVector2 const &point);
00054     
00055     inline bool IsAllowableObjectRadius (Object const *object) const { return object->Radius(GetQuadTreeType()) / m_radius > 0.5f; }
00056 
00057     bool DoesAreaOverlapAnyObject (
00058         FloatVector2 const &area_center,
00059         Float area_radius) const;
00060     bool DoesAreaOverlapAnyObjectWrapped (
00061         FloatVector2 const &area_center,
00062         Float area_radius,
00063         Float object_layer_side_length,
00064         Float half_object_layer_side_length) const;
00065 
00066     
00067     void Clear ();
00068     
00069     
00070     
00071     
00072     bool AddObject (Object *object);
00073     
00074     bool RemoveObject (Object *object);
00075     
00076     
00077     bool ReAddObject (Object *object);
00078 
00079 protected:
00080 
00081     
00082     QuadTree (QuadTree *parent);
00083 
00084     template <typename QuadTreeClass>
00085     inline QuadTreeClass const *Child (Uint32 const index) const
00086     {
00087         ASSERT2(index < 4);
00088         ASSERT2(m_child[index] != NULL);
00089         return DStaticCast<QuadTreeClass const *>(m_child[index]);
00090     }
00091     template <typename QuadTreeClass>
00092     inline QuadTreeClass *Child (Uint32 const index)
00093     {
00094         ASSERT2(index < 4);
00095         ASSERT2(m_child[index] != NULL);
00096         return DStaticCast<QuadTreeClass *>(m_child[index]);
00097     }
00098     
00099     bool IsPointInsideQuad (FloatVector2 const &point) const;
00100     
00101     
00102     
00103     inline bool DoesAreaOverlapQuadBounds (
00104         FloatVector2 const &area_center,
00105         Float const area_radius) const
00106     {
00107         ASSERT1(area_radius > 0.0f);
00108         Float radius_sum = area_radius + 2.0f * Radius();
00109         return (area_center - m_center).LengthSquared() < radius_sum*radius_sum;
00110     }
00111     
00112     
00113     
00114     bool DoesAreaOverlapQuadBoundsWrapped (
00115         FloatVector2 area_center,
00116         Float area_radius,
00117         Float object_layer_side_length,
00118         Float half_object_layer_side_length) const;
00119 
00120     void SetQuadTreeType (QuadTreeType quad_tree_type);
00121 
00122     
00123     void IncrementSubordinateObjectCount ();
00124     
00125     void IncrementSubordinateStaticObjectCount ();
00126     
00127     void DecrementSubordinateObjectCount ();
00128     
00129     void DecrementSubordinateStaticObjectCount ();
00130 
00131     template <typename QuadTreeClass>
00132     void Initialize (
00133         FloatVector2 const ¢er,
00134         Float const half_side_length,
00135         Uint8 const depth)
00136     {
00137         ASSERT1(half_side_length > 0.0f);
00138         ASSERT1(depth != 0);
00139 
00140         m_parent = NULL;
00141         m_center = center;
00142         m_half_side_length = half_side_length;
00143         m_radius = Math::Sqrt(2.0f) * m_half_side_length;
00144         m_subordinate_object_count = 0;
00145         m_subordinate_static_object_count = 0;
00146         if (depth <= 1)
00147         {
00148             for (Uint8 i = 0; i < 4; ++i)
00149                 m_child[i] = NULL;
00150         }
00151         else
00152         {
00153             Float child_half_side_length = 0.5f * m_half_side_length;
00154 
00155             m_child[0] = new QuadTreeClass(
00156                 center + child_half_side_length * FloatVector2( 1.0f,  1.0f),
00157                 child_half_side_length,
00158                 depth - 1);
00159             m_child[1] = new QuadTreeClass(
00160                 center + child_half_side_length * FloatVector2(-1.0f,  1.0f),
00161                 child_half_side_length,
00162                 depth - 1);
00163             m_child[2] = new QuadTreeClass(
00164                 center + child_half_side_length * FloatVector2(-1.0f, -1.0f),
00165                 child_half_side_length,
00166                 depth - 1);
00167             m_child[3] = new QuadTreeClass(
00168                 center + child_half_side_length * FloatVector2( 1.0f, -1.0f),
00169                 child_half_side_length,
00170                 depth - 1);
00171 
00172             for (Uint8 i = 0; i < 4; ++i)
00173                 m_child[i]->m_parent = this;
00174         }
00175     }
00176 
00177     typedef std::set<Object *> ObjectSet;
00178 
00179     
00180     ObjectSet m_object_set;
00181     
00182     
00183     
00184     
00185     
00186     QuadTree *m_child[4];
00187     
00188     QuadTree *m_parent;
00189     
00190     FloatVector2 m_center;
00191     
00192     Float m_half_side_length;
00193     
00194     Float m_radius;
00195 
00196 private:
00197 
00198     void NonRecursiveAddObject (Object *object);
00199     void AddObjectIfNotAlreadyAdded (Object *object);
00200 
00201     
00202     Uint32 m_subordinate_object_count;
00203     
00204     Uint32 m_subordinate_static_object_count;
00205     
00206     
00207     
00208     QuadTreeType m_quad_tree_type;
00209 }; 
00210 
00211 } 
00212     
00213 } 
00214 
00215 #endif // !defined(_XRB_ENGINE2_QUADTREEBASE_HPP_)