# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

quad_tree.h

Go to the documentation of this file.
00001 
00007 /* Copyright, 2000 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 
00027 #ifndef NL_QUAD_TREE_H
00028 #define NL_QUAD_TREE_H
00029 
00030 #include "nel/misc/debug.h"
00031 #include "nel/misc/vector.h"
00032 #include "nel/misc/plane.h"
00033 #include "nel/misc/matrix.h"
00034 #include <list>
00035 #include <vector>
00036 
00037 
00038 namespace       NL3D
00039 {
00040 
00041 
00042 
00096 template<class T>       class   CQuadTree
00097 {
00098 
00099 public:
00101         class   CIterator;
00102         friend class    CIterator;
00104         class   CConstIterator;
00105         friend class    CConstIterator;
00106 
00107 public:
00108 
00110         CQuadTree();
00111 
00113         ~CQuadTree();
00114 
00116 
00117 
00132         void changeBase(const NLMISC::CMatrix& base);
00133 
00140         void            create(uint DepthMax, const NLMISC::CVector& center, float size);
00142 
00143 
00145 
00146 
00147         void            clear();
00148 
00151         void            eraseAll();
00152 
00157         void            erase(CIterator it);
00158 
00165         CIterator       insert(const NLMISC::CVector &bboxmin, const NLMISC::CVector &bboxmax, const T &val);
00167 
00168 
00170 
00171 
00173         void            clearSelection();
00174 
00177         void            selectAll();
00178 
00184         void            select(const NLMISC::CVector &bboxmin, const NLMISC::CVector &bboxmax);
00185 
00191         void            select(const std::vector<NLMISC::CPlane> &BVolume);
00192 
00198         void            selectRay(const NLMISC::CVector& source, const NLMISC::CVector& dir);
00199 
00205         void            selectSegment(const NLMISC::CVector& source, const NLMISC::CVector& dest);
00206 
00209         CIterator       begin();
00210 
00213         CIterator       end();
00215 
00216 
00217 
00218 // =================
00219 // =================
00220 // IMPLEMENTATION.
00221 // =================
00222 // =================
00223 private:// Classes.
00224 
00225 
00226         // =================
00227         // =================
00228         // CBaseNode.
00229         // =================
00230         // =================
00231         // Links fo an element node class.
00232         class                   CBaseNode
00233         {
00234         public:
00235                 // for the Selection list.
00236                 CBaseNode       *Prev, *Next;
00237                 // for the quadnode list. A node MAY be pointed by 4 quad (each having the same level).
00238                 CBaseNode       *QuadPrevs[4];
00239                 CBaseNode       *QuadNexts[4];
00240 
00241 
00242         public:
00243                 CBaseNode()
00244                 {
00245                         Prev=Next=NULL;
00246                         QuadPrevs[0]= QuadPrevs[1]= QuadPrevs[2]= QuadPrevs[3]= NULL;
00247                         QuadNexts[0]= QuadNexts[1]= QuadNexts[2]= QuadNexts[3]= NULL;
00248                 }
00249                 virtual ~CBaseNode() {}         // Empty destructor, but declare it as virtual...
00250                 void    clear()                         // update links.
00251                 {
00252                         // On le retire de la selection.
00253                         if(Prev)        Prev->Next= Next;
00254                         if(Next)        Next->Prev= Prev;
00255                         Prev=Next=NULL;
00256                         // On le retire des listes dans les quads.
00257                         for(uint i=0;i<4;i++)
00258                         {
00259                                 if(QuadPrevs[i])        {nlassert(QuadPrevs[i]->QuadNexts[i]==this); QuadPrevs[i]->QuadNexts[i]= QuadNexts[i];}
00260                                 if(QuadNexts[i])        {nlassert(QuadNexts[i]->QuadPrevs[i]==this); QuadNexts[i]->QuadPrevs[i]= QuadPrevs[i];}
00261                                 QuadPrevs[i]=NULL;
00262                                 QuadNexts[i]=NULL;
00263                         }
00264                 }
00265                 bool    isSelected()    // return true if Prev is not NULL!!!
00266                 {
00267                         return Prev!=NULL;
00268                 }
00269         };
00270 
00271 
00272         // =================
00273         // =================
00274         // CNode.
00275         // =================
00276         // =================
00277         // An element node class.
00278         class                   CNode : public CBaseNode
00279         {
00280         public:
00281                 // A base node, plus the Value.
00282                 T                       Value;
00283                 CNode(const T &val) : Value(val) {}
00284         };
00285 
00286 
00287         // =================
00288         // =================
00289         // CQuadNode.
00290         // =================
00291         // =================
00292         class                           CQuadNode
00293         {
00294         public:
00295                 uint                    Level;
00296                 NLMISC::CVector                 BBoxMin, BBoxMax;
00297                 bool                    BBoxNeverRescale;
00298                 CQuadNode               *Sons[4];
00299                 CBaseNode               RootNode;               // First element of the element list in this quad.
00300                 uint                    ListIndex;              // [0,3]. index of wich list to follow in "Node.QuadNexts[]".
00301                 /* Topology of sons (top view: axe x/z):
00302                         0--1
00303                         |  |
00304                         2--3
00305                 */
00306                 
00307 
00308         public:
00309                 // ============================================================================================
00310                 CQuadNode()
00311                 {
00312                         Level=0; Sons[0]= Sons[1]= Sons[2]= Sons[3]= NULL;
00313                         ListIndex= 0;
00314                         BBoxNeverRescale=true;
00315                 }
00316                 // ============================================================================================
00317                 bool    isLeaf()
00318                 {
00319                         return Sons[0]==NULL;
00320                 }
00321                 // ============================================================================================
00322                 void    clear()
00323                 {
00324                         // Deletons les element dans ce quad node.
00325                         CBaseNode       *p;
00326                         while( (p=RootNode.QuadNexts[ListIndex]) )
00327                         {
00328                                 p->clear();     // On clear les links. => RootNode.QuadNexts[ListIndex] modifié implicitement.
00329                                 delete p;       // On delete cet element!!
00330                         }
00331 
00332                         // Deletons les quad fils.
00333                         for(uint i=0;i<4;i++)
00334                         {
00335                                 if(Sons[i])
00336                                 {
00337                                         Sons[i]->clear();
00338                                         delete Sons[i];
00339                                         Sons[i]= NULL;
00340                                 }
00341                         }
00342                 }
00343                 // ============================================================================================
00344                 void    split()
00345                 {
00346                         nlassert(isLeaf());
00347                         sint    i;
00348 
00349                         for(i=0;i<4;i++)
00350                         {
00351                                 Sons[i]= new CQuadNode;
00352                                 Sons[i]->Level= Level+1;
00353                                 Sons[i]->ListIndex= i;
00354                         }
00355                         // Middle compute.
00356                         NLMISC::CVector         MidLeft(0,0,0), MidRight(0,0,0), MidTop(0,0,0), MidBottom(0,0,0), Middle(0,0,0);
00357                         MidLeft.x  = BBoxMin.x; MidLeft.z       = (BBoxMin.z + BBoxMax.z)/2;
00358                         MidRight.x = BBoxMax.x; MidRight.z      = (BBoxMin.z + BBoxMax.z)/2;
00359                         MidTop.x   = (BBoxMin.x + BBoxMax.x)/2; MidTop.z   = BBoxMin.z;
00360                         MidBottom.x= (BBoxMin.x + BBoxMax.x)/2; MidBottom.z= BBoxMax.z;
00361                         Middle.x   = MidTop.x; Middle.z = MidLeft.z;
00362                         // Sons compute.
00363                         // Don't care of Y.
00364                         Sons[0]->BBoxMin = BBoxMin; Sons[0]->BBoxMax = Middle; 
00365                         Sons[1]->BBoxMin = MidTop ; Sons[1]->BBoxMax = MidRight; 
00366                         Sons[2]->BBoxMin = MidLeft; Sons[2]->BBoxMax = MidBottom; 
00367                         Sons[3]->BBoxMin = Middle;  Sons[3]->BBoxMax = BBoxMax;
00368 
00369                 }
00370 
00371 
00372                 // ============================================================================================
00373                 // This is a quadtree, so those tests just test against x/z. (the base of the box).
00374                 bool    includeBoxQuad(const NLMISC::CVector &boxmin, const NLMISC::CVector &boxmax)
00375                 {
00376                         if( BBoxMin.x<= boxmin.x && BBoxMax.x>= boxmax.x && 
00377                                 BBoxMin.z<= boxmin.z && BBoxMax.z>= boxmax.z)
00378                                 return true;
00379                         else
00380                                 return false;
00381                 }
00382                 // ============================================================================================
00383                 bool    intersectBoxQuad(const NLMISC::CVector &boxmin, const NLMISC::CVector &boxmax)
00384                 {
00385                         // inequality and equality is very important, to ensure that a element box will not fit in too many quad boxes.
00386                         if(boxmin.x > BBoxMax.x)        return false;
00387                         if(boxmin.z > BBoxMax.z)        return false;
00388                         if(boxmax.x <= BBoxMin.x)       return false;
00389                         if(boxmax.z <= BBoxMin.z)       return false;
00390                         return true;
00391                 }
00392                 // ============================================================================================
00393                 bool    intersectBox(const NLMISC::CVector &boxmin, const NLMISC::CVector &boxmax)
00394                 {
00395                         // inequality and equality is very important, to ensure that a element box will not fit in too many quad boxes.
00396                         if(boxmin.x > BBoxMax.x)        return false;
00397                         if(boxmin.y > BBoxMax.y)        return false;
00398                         if(boxmin.z > BBoxMax.z)        return false;
00399                         if(boxmax.x <= BBoxMin.x)       return false;
00400                         if(boxmax.y <= BBoxMin.y)       return false;
00401                         if(boxmax.z <= BBoxMin.z)       return false;
00402                         return true;
00403                 }
00404                 // ============================================================================================
00405                 bool    intersectBox(std::vector<NLMISC::CPlane> &BVolume)
00406                 {
00407                         const   NLMISC::CVector &b1=BBoxMin;
00408                         const   NLMISC::CVector &b2=BBoxMax;
00409 
00410                         for(sint i=0;i<(int)BVolume.size();i++)
00411                         {
00412                                 const   NLMISC::CPlane  &plane=BVolume[i];
00413                                 // If only one of the box vertex is IN the plane, then all the box is IN this plane.
00414                                 if(plane* NLMISC::CVector(b1.x, b1.y, b1.z)<=0) continue;
00415                                 if(plane* NLMISC::CVector(b1.x, b1.y, b2.z)<=0) continue;
00416                                 if(plane* NLMISC::CVector(b1.x, b2.y, b1.z)<=0) continue;
00417                                 if(plane* NLMISC::CVector(b1.x, b2.y, b2.z)<=0) continue;
00418                                 if(plane* NLMISC::CVector(b2.x, b1.y, b1.z)<=0) continue;
00419                                 if(plane* NLMISC::CVector(b2.x, b1.y, b2.z)<=0) continue;
00420                                 if(plane* NLMISC::CVector(b2.x, b2.y, b1.z)<=0) continue;
00421                                 if(plane* NLMISC::CVector(b2.x, b2.y, b2.z)<=0) continue;
00422                                 // If ALL box vertices are OUT of this plane, then the box is OUT of the entire volume.
00423                                 return false;
00424                         }
00425                         // TODO. This is a simple box detection. The box is not really clipped and sometimes, the box will said
00426                         // it intersect but it is not the case... Here, We should test the real box volume, against BVolume.
00427                         // But this is more expensive...
00428                         return true;
00429                 }
00430 
00431                 // ============================================================================================
00432                 void    addElement(CNode *newNode)
00433                 {
00434                         nlassert(newNode->QuadNexts[ListIndex]==NULL);
00435                         newNode->QuadPrevs[ListIndex]= &RootNode;
00436                         newNode->QuadNexts[ListIndex]= RootNode.QuadNexts[ListIndex];
00437                         if(RootNode.QuadNexts[ListIndex])
00438                                 RootNode.QuadNexts[ListIndex]->QuadPrevs[ListIndex]= newNode;
00439                         RootNode.QuadNexts[ListIndex]= newNode;
00440                 }
00441                 // ============================================================================================
00442                 // Insertion of a node in this quad node, or his sons...
00443                 void    insert(const NLMISC::CVector &boxmin, const NLMISC::CVector &boxmax, uint wantdepth, CNode *newNode)
00444                 {
00445                         if(Level==0)
00446                         {
00447                                 // Tous les elements qui sortent du quadtree sont forcément dans le noeud root.
00448                                 if(!includeBoxQuad(boxmin, boxmax))
00449                                 {
00450                                         // Il faut agrandir la BBox en Y du quadnode.
00451                                         if(BBoxNeverRescale)
00452                                         {
00453                                                 BBoxMin.y= boxmin.y;
00454                                                 BBoxMax.y= boxmax.y;
00455                                                 BBoxNeverRescale= false;
00456                                         }
00457                                         else
00458                                         {
00459                                                 BBoxMin.y= std::min(boxmin.y, BBoxMin.y);
00460                                                 BBoxMax.y= std::max(boxmax.y, BBoxMax.y);
00461                                         }
00462                                         addElement(newNode);
00463                                         return;
00464                                 }
00465                         }
00466 
00467                         // Si au moins une partie de l'element n'est pas dans le noeud de ce quad, exit.
00468                         if(!intersectBoxQuad(boxmin, boxmax))
00469                                 return;
00470 
00471                         // Que l'on insere ici ou dans les fils, il faut agrandir la BBox en Y du quadnode.
00472                         if(BBoxNeverRescale)
00473                         {
00474                                 BBoxMin.y= boxmin.y;
00475                                 BBoxMax.y= boxmax.y;
00476                                 BBoxNeverRescale= false;
00477                         }
00478                         else
00479                         {
00480                                 BBoxMin.y= std::min(boxmin.y, BBoxMin.y);
00481                                 BBoxMax.y= std::max(boxmax.y, BBoxMax.y);
00482                         }
00483 
00484                         // Si on est au bon, niveau, on a plus qu'à l'insérer dans ce node.
00485                         if(wantdepth==Level)
00486                         {
00487                                         addElement(newNode);
00488                         }
00489                         else
00490                         {
00491                                 // Si le quad est une feuille, il faut le splitter (car on est pas encore arrivé au bon niveau).
00492                                 if(isLeaf())
00493                                         split();
00494 
00495                                 // Et on cherche à mettre l'élément dans un de ces noeuds.
00496                                 Sons[0]->insert(boxmin, boxmax, wantdepth, newNode);
00497                                 Sons[1]->insert(boxmin, boxmax, wantdepth, newNode);
00498                                 Sons[2]->insert(boxmin, boxmax, wantdepth, newNode);
00499                                 Sons[3]->insert(boxmin, boxmax, wantdepth, newNode);
00500                         }
00501 
00502                 }
00503 
00504                 
00505                 // ============================================================================================
00506                 // Selection.
00507                 void    selectLocalNodes(CBaseNode      &selroot)
00508                 {
00509                         CBaseNode       *p= RootNode.QuadNexts[ListIndex];
00510                         while(p)
00511                         {
00512                                 if(!p->isSelected())
00513                                 {
00514                                         p->Prev= &selroot;
00515                                         p->Next= selroot.Next;
00516                                         if(selroot.Next)
00517                                                 selroot.Next->Prev= p;
00518                                         selroot.Next= p;
00519                                 }
00520                                 p=p->QuadNexts[ListIndex];
00521                         }
00522                 }
00523                 // ============================================================================================
00524                 void    selectAll(CBaseNode     &selroot)
00525                 {
00526                         selectLocalNodes(selroot);
00527                         if(!isLeaf())
00528                         {
00529                                 Sons[0]->selectAll(selroot);
00530                                 Sons[1]->selectAll(selroot);
00531                                 Sons[2]->selectAll(selroot);
00532                                 Sons[3]->selectAll(selroot);
00533                         }
00534                 }
00535                 // ============================================================================================
00536                 void    select(CBaseNode &selroot, const NLMISC::CVector &bboxmin, const NLMISC::CVector &bboxmax)
00537                 {
00538                         // TODO:
00539                         // ya un bug avec le level0: en effet la bbox n'a pas été agrandie pour contenir les elements.
00540                         if(!intersectBox(bboxmin, bboxmax))
00541                                 return;
00542                         selectLocalNodes(selroot);
00543                         if(!isLeaf())
00544                         {
00545                                 Sons[0]->select(selroot, bboxmin, bboxmax);
00546                                 Sons[1]->select(selroot, bboxmin, bboxmax);
00547                                 Sons[2]->select(selroot, bboxmin, bboxmax);
00548                                 Sons[3]->select(selroot, bboxmin, bboxmax);
00549                         }
00550                 }
00551                 // ============================================================================================
00552                 void            select(CBaseNode &selroot, std::vector<NLMISC::CPlane> &BVolume)
00553                 {
00554                         // TODO:
00555                         // ya un bug avec le level0: en effet la bbox n'a pas été agrandie pour contenir les elements.
00556                         if(!intersectBox(BVolume))
00557                                 return;
00558                         selectLocalNodes(selroot);
00559                         if(!isLeaf())
00560                         {
00561                                 Sons[0]->select(selroot, BVolume);
00562                                 Sons[1]->select(selroot, BVolume);
00563                                 Sons[2]->select(selroot, BVolume);
00564                                 Sons[3]->select(selroot, BVolume);
00565                         }
00566                 }
00567         };
00568 
00569 
00570 
00571 // =================
00572 // =================
00573 // Attributes/Methods/iterators..
00574 // =================
00575 // =================
00576 private:// Attributes.
00577         CQuadNode       _QuadRoot;
00578         CBaseNode       _Selection;
00579         uint            _DepthMax;
00580         float           _Size;
00581         NLMISC::CMatrix         _ChangeBasis;
00582 
00583 private:// Methods.
00584 
00585 
00586 
00587 public:
00588         // CLASS const_iterator.
00589         class const_iterator
00590         {
00591         public:
00592                 const_iterator()        {_Ptr=NULL;}
00593                 const_iterator(CNode *p) : _Ptr(p) {}
00594                 const_iterator(const CIterator& x) : _Ptr(x._Ptr) {}
00595 
00596                 const T&        operator*() const
00597                         {return _Ptr->Value; }
00598                 // Doesn't work...
00599                 /*const T*      operator->() const
00600                         {return (&**this); }*/
00601                 const_iterator& operator++()
00602                         {_Ptr = (CNode*)(_Ptr->Next); return (*this); }
00603                 const_iterator operator++(int)
00604                         {const_iterator tmp = *this; ++*this; return (tmp); }
00605                 const_iterator& operator--()
00606                         {_Ptr = (CNode*)(_Ptr->Prev); return (*this); }
00607                 const_iterator operator--(int)
00608                         {const_iterator tmp = *this; --*this; return (tmp); }
00609                 bool operator==(const const_iterator& x) const
00610                         {return (_Ptr == x._Ptr); }
00611                 bool operator!=(const const_iterator& x) const
00612                         {return (!(*this == x)); }
00613         protected:
00614                 CNode   *_Ptr;
00615                 friend class CQuadTree<T>;
00616                 friend class CIterator;
00617         };
00618 
00619         // CLASS CIterator
00620         class CIterator : public const_iterator
00621         {
00622         public:
00623                 CIterator()                     {_Ptr=NULL;}
00624                 CIterator(CNode *p) : const_iterator(p) {}
00625                 T&      operator*() const
00626                         {return _Ptr->Value; }
00627                 // Doesn't work...
00628                 /*T*    operator->() const
00629                         {return (&**this); }*/
00630                 CIterator& operator++()
00631                         {_Ptr = (CNode*)(_Ptr->Next); return (*this); }
00632                 CIterator operator++(int)
00633                         {CIterator tmp = *this; ++*this; return (tmp); }
00634                 CIterator& operator--()
00635                         {_Ptr = (CNode*)(_Ptr->Prev); return (*this); }
00636                 CIterator operator--(int)
00637                         {CIterator tmp = *this; --*this; return (tmp); }
00638                 bool operator==(const const_iterator& x) const
00639                         {return (_Ptr == x._Ptr); }
00640                 bool operator!=(const const_iterator& x) const
00641                         {return (!(*this == x)); }
00642         protected:
00643                 friend class CQuadTree<T>;
00644         };
00645 
00646 };
00647 
00648 
00649 
00650 // ============================================================================================
00651 // ============================================================================================
00652 // Template CQuadTree implementation. Construction/Destruction.
00653 // ============================================================================================
00654 // ============================================================================================
00655 
00656                 
00657 // ============================================================================================
00658 template<class T>       CQuadTree<T>::CQuadTree()
00659 {
00660         _Selection.Next= NULL;
00661         _DepthMax= 0;
00662         _QuadRoot.BBoxMin.set(-0.5, 0, -0.5);
00663         _QuadRoot.BBoxMax.set( 0.5, 0,  0.5);
00664         _Size=1;
00665 
00666         _ChangeBasis.identity();
00667 }
00668 // ============================================================================================
00669 template<class T>       void CQuadTree<T>::changeBase(const NLMISC::CMatrix& base)
00670 {
00671         _ChangeBasis=base;
00672 }
00673 // ============================================================================================
00674 template<class T>       CQuadTree<T>::~CQuadTree<T>()
00675 {
00676         clear();
00677 }
00678 // ============================================================================================
00679 template<class T>       void            CQuadTree<T>::clear()
00680 {
00681         _QuadRoot.clear();
00682         _Selection.Next= NULL;
00683 }
00684 // ============================================================================================
00685 template<class T>       void            CQuadTree<T>::create(uint DepthMax, const NLMISC::CVector& center, float size)
00686 {
00687         NLMISC::CVector mycenter=_ChangeBasis*center;
00688         clear();
00689         _DepthMax= DepthMax;
00690         _Size= size;
00691         _QuadRoot.BBoxMin= mycenter-NLMISC::CVector(size/2, 0 , size/2);
00692         _QuadRoot.BBoxMax= mycenter+NLMISC::CVector(size/2, 0 , size/2);
00693 }
00694 
00695 
00696 // ============================================================================================
00697 // ============================================================================================
00698 // Template CQuadTree implementation.  Element Insertion/Deletion.
00699 // ============================================================================================
00700 // ============================================================================================
00701 
00702 
00703 // ============================================================================================
00704 template<class T>       void            CQuadTree<T>::eraseAll()
00705 {
00706         CIterator                               it;
00707         std::vector<CIterator>  its;
00708 
00709         // First, make a copy of all elements.
00710         selectAll();
00711         for(it= begin();it!=end();it++)
00712         {
00713                 its.push_back(it);
00714         }
00715 
00716         // Then erase them. Must do it OUTSIDE the select loop.
00717         for(sint i=0;i<(sint)its.size();i++)
00718         {
00719                 erase(its[i]);
00720         }
00721 }
00722 // ============================================================================================
00723 template<class T>       void            CQuadTree<T>::erase(CIterator it)
00724 {
00725         CNode   *p=it._Ptr;
00726         if(p)
00727         {
00728                 // Clear links.
00729                 p->clear();
00730 
00731                 // delete it!!
00732                 delete p;
00733         }
00734 }
00735 // ============================================================================================
00736 template<class T>       CQuadTree<T>::CIterator CQuadTree<T>::insert(const NLMISC::CVector &bboxmin, const NLMISC::CVector &bboxmax, const T &val)
00737 {
00738         NLMISC::CVector myboxmin2=_ChangeBasis*bboxmin;
00739         NLMISC::CVector myboxmax2=_ChangeBasis*bboxmax;
00740         NLMISC::CVector myboxmin (std::min (myboxmin2.x, myboxmax2.x), std::min (myboxmin2.y, myboxmax2.y), std::min (myboxmin2.z, myboxmax2.z));
00741         NLMISC::CVector myboxmax (std::max (myboxmin2.x, myboxmax2.x), std::max (myboxmin2.y, myboxmax2.y), std::max (myboxmin2.z, myboxmax2.z));
00742 
00743         CNode   *newNode=new CNode(val);
00744 
00745         nlassert(myboxmax.x>=myboxmin.x);
00746         nlassert(myboxmax.y>=myboxmin.y);
00747         nlassert(myboxmax.z>=myboxmin.z);
00748 
00749         float   boxsize= std::max(myboxmax.x-myboxmin.x, myboxmax.z-myboxmin.z );
00750         // Prevent float precision problems. Increase bbox size a little.
00751         boxsize*=1.01f;
00752         // We must find the level quad which is just bigger.
00753         float   wantsize=_Size;
00754         uint    wantdepth=0;
00755         while(boxsize<wantsize/2 && wantdepth<_DepthMax)
00756         {
00757                 wantsize/=2;
00758                 wantdepth++;
00759         }
00760 
00761         _QuadRoot.insert(myboxmin, myboxmax, wantdepth, newNode);
00762 
00763         return CIterator(newNode);
00764 }
00765 
00766 
00767 // ============================================================================================
00768 // ============================================================================================
00769 // Template CQuadTree implementation. Quad Selection, element iteration.
00770 // ============================================================================================
00771 // ============================================================================================
00772 
00773 
00774 // ============================================================================================
00775 template<class T>       void            CQuadTree<T>::clearSelection()
00776 {
00777         CBaseNode       *p;
00778         while(p=_Selection.Next)
00779         {
00780                 // On retire ce noeud de la selection. Ce qui va modifier implicitement _Selection.Next.
00781                 if(p->Prev)     p->Prev->Next= p->Next;
00782                 if(p->Next)     p->Next->Prev= p->Prev;
00783                 p->Prev=p->Next=NULL;
00784         }
00785 }
00786 // ============================================================================================
00787 template<class T>       void            CQuadTree<T>::selectAll()
00788 {
00789         clearSelection();
00790         _QuadRoot.selectAll(_Selection);
00791 }
00792 // ============================================================================================
00793 template<class T>       void            CQuadTree<T>::select(const NLMISC::CVector &bboxmin, const NLMISC::CVector &bboxmax)
00794 {
00795         NLMISC::CVector myboxmin2=_ChangeBasis*bboxmin;
00796         NLMISC::CVector myboxmax2=_ChangeBasis*bboxmax;
00797         NLMISC::CVector bboxminCopy (std::min (myboxmin2.x, myboxmax2.x), std::min (myboxmin2.y, myboxmax2.y), std::min (myboxmin2.z, myboxmax2.z));
00798         NLMISC::CVector bboxmaxCopy (std::max (myboxmin2.x, myboxmax2.x), std::max (myboxmin2.y, myboxmax2.y), std::max (myboxmin2.z, myboxmax2.z));
00799 
00800         clearSelection();
00801         _QuadRoot.select(_Selection, bboxminCopy, bboxmaxCopy);
00802 }
00803 // ============================================================================================
00804 template<class T>       void            CQuadTree<T>::select(const std::vector<NLMISC::CPlane> &BVolume)
00805 {
00806         std::vector<NLMISC::CPlane> BVolumeCopy;
00807         BVolumeCopy.resize (BVolume.size());
00808         for (int i=0; i<(int)BVolumeCopy.size(); i++)
00809         {
00810                 BVolumeCopy[i]=BVolume[i]*((_ChangeBasis).inverted());
00811         }
00812 
00813         clearSelection();
00814         _QuadRoot.select(_Selection, BVolumeCopy);
00815 }
00816 // ============================================================================================
00817 template<class T>       void            CQuadTree<T>::selectRay(const NLMISC::CVector& source, const NLMISC::CVector& dir)
00818 {
00819         NLMISC::CMatrix mat;
00820         mat.identity ();
00821 
00822         // Set a wrong matrix
00823         NLMISC::CVector vTmp=dir^((fabs(vTmp*CVector(1,0,0))>0.f)?CVector(1,0,0):CVector(0,1,0));
00824         mat.setRot (dir, vTmp, dir^vTmp);
00825 
00826         // Normalize it Yoyo!
00827         mat.normalize (NLMISC::CMatrix::XYZ);
00828 
00829         // Get the planes..
00830         std::vector<NLMISC::CPlane> BVolume;
00831         BVolume.reserve (4);
00832         
00833         // Setup the planes
00834         NLMISC::CPlane plane;
00835         plane.make (mat.getJ(), source);
00836         BVolume.push_back (plane);
00837         plane.make (mat.getK(), source);
00838         BVolume.push_back (plane);
00839         plane.make (-mat.getJ(), source);
00840         BVolume.push_back (plane);
00841         plane.make (-mat.getK(), source);
00842         BVolume.push_back (plane);
00843 
00844         // Select the nodes
00845         select (BVolume);
00846 }
00847 // ============================================================================================
00848 template<class T>       void            CQuadTree<T>::selectSegment(const NLMISC::CVector& source, const NLMISC::CVector& dest)
00849 {
00850         NLMISC::CMatrix mat;
00851         mat.identity ();
00852 
00853         // Set a wrong matrix
00854         CVector dir=dest-source;
00855         NLMISC::CVector vTmp=dir^((fabs(vTmp*CVector(1,0,0))>0.f)?CVector(1,0,0):CVector(0,1,0));
00856         mat.setRot (dir, vTmp, dir^vTmp);
00857 
00858         // Normalize it Yoyo!
00859         mat.normalize (NLMISC::CMatrix::XYZ);
00860 
00861         // Get the planes..
00862         std::vector<NLMISC::CPlane> BVolume;
00863         BVolume.reserve (4);
00864         
00865         // Setup the planes
00866         NLMISC::CPlane plane;
00867         plane.make (mat.getJ(), source);
00868         BVolume.push_back (plane);
00869         plane.make (mat.getK(), source);
00870         BVolume.push_back (plane);
00871         plane.make (-mat.getJ(), source);
00872         BVolume.push_back (plane);
00873         plane.make (-mat.getK(), source);
00874         BVolume.push_back (plane);
00875         plane.make (mat.getI(), dest);
00876         BVolume.push_back (plane);
00877         plane.make (-mat.getI(), source);
00878         BVolume.push_back (plane);
00879 
00880         // Select the nodes
00881         select (BVolume);
00882 }
00883 // ============================================================================================
00884 template<class T>       CQuadTree<T>::CIterator CQuadTree<T>::begin()
00885 {
00886         return (CNode*)(_Selection.Next);
00887 }
00888 // ============================================================================================
00889 template<class T>       CQuadTree<T>::CIterator CQuadTree<T>::end()
00890 {
00891         return CIterator(NULL);
00892 }
00893 
00894 
00895 }
00896 
00897 #endif
00898