quad_grid.h

Go to the documentation of this file.
00001 
00005 /* Copyright, 2000 Nevrax Ltd.
00006  *
00007  * This file is part of NEVRAX NEL.
00008  * NEVRAX NEL is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2, or (at your option)
00011  * any later version.
00012 
00013  * NEVRAX NEL is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00016  * General Public License for more details.
00017 
00018  * You should have received a copy of the GNU General Public License
00019  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00020  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00021  * MA 02111-1307, USA.
00022  */
00023 
00024 #ifndef NL_QUAD_GRID_H
00025 #define NL_QUAD_GRID_H
00026 
00027 #include "nel/misc/debug.h"
00028 #include "nel/misc/vector.h"
00029 #include "nel/misc/vector_2f.h"
00030 #include "nel/misc/plane.h"
00031 #include "nel/misc/matrix.h"
00032 #include "nel/misc/block_memory.h"
00033 #include "nel/misc/object_vector.h"
00034 #include "nel/misc/common.h"
00035 #include "nel/misc/polygon.h"
00036 #include "nel/misc/grid_traversal.h"
00037 
00038 #include <vector>
00039 #include <map>
00040 
00041 namespace NL3D
00042 {
00043 
00044 
00045 using NLMISC::CVector;
00046 
00047 // ***************************************************************************
00048 // Default Size of a block for allocation of elements and elements node list in the grid.
00049 #define NL3D_QUAD_GRID_ALLOC_BLOCKSIZE  16
00050 
00051 
00052 // base class containing structure common to all quad grids
00053 class CQuadGridBase
00054 {
00055 protected:
00056     static NLMISC::CPolygon2D               _ScaledPoly;        // for polygon selection
00057     static NLMISC::CPolygon2D::TRasterVect  _PolyBorders;       // for polygon selection
00058     static std::vector<uint>                _AlreadySelected;   // During some selection operations, mark the cells that have already been visited.
00059                                                                 // may happen if the selection shape can overlap itself due to the grid vrapiing.
00060                                                                 // A cell is known to be selected if its uint "timestamp" is equal to _SelectStamp.
00061     static uint                             _SelectStamp;       // Incremented at each selection, value used to mark selected cells.
00062 };
00063 
00064 // ***************************************************************************
00087 template<class T>   class   CQuadGrid : public CQuadGridBase
00088 {
00089 public:
00091     class   CIterator;
00092     friend class    CIterator;
00093 
00094 public:
00095     typedef std::vector<uint> TSelectionShape;
00096 
00098     CQuadGrid(uint memoryBlockSize= NL3D_QUAD_GRID_ALLOC_BLOCKSIZE);
00099 
00101     ~CQuadGrid();
00102 
00103     // operator= don't modify the block memory blocksize
00104     CQuadGrid<T>    &operator=(const CQuadGrid<T> &o);
00105 
00106     // Copy ctor
00107     CQuadGrid(const CQuadGrid<T> &o);
00108 
00110 
00111 
00126     void            changeBase(const NLMISC::CMatrix& base);
00127 
00134     void            create(uint size, float eltSize);
00135 
00136     // Get creation parameters.
00137     const NLMISC::CMatrix   &getBasis() const {return _ChangeBasis;}
00138     uint                    getSize() const {return _Size;}
00139     float                   getEltSize() const {return _EltSize;}
00141 
00143 
00144 
00147     void            clear();
00148 
00156     CIterator       erase(CIterator it);
00157 
00183     CIterator       insert(const NLMISC::CVector &bboxmin, const NLMISC::CVector &bboxmax, const T &val);
00185 
00186 
00188 
00189 
00192     void            clearSelection();
00193 
00197     void            selectAll();
00198 
00205     void            select(const NLMISC::CVector &bboxmin, const NLMISC::CVector &bboxmax);
00206 
00207     // Select element intersecting a ray. Clear the selection first.
00208     void            selectRay(const NLMISC::CVector &rayStart, const NLMISC::CVector &rayEnd);
00209 
00213     void            buildSelectionShape(TSelectionShape &dest, const NLMISC::CPolygon2D &poly) const;
00214 
00217     void            select(const TSelectionShape &shape);
00218 
00219 
00223     CIterator       begin();
00224 
00228     CIterator       end();
00230 
00231 
00232 // =================
00233 // =================
00234 // IMPLEMENTATION.
00235 // =================
00236 // =================
00237 private:// Classes.
00238     class CNode;
00239 
00243     class   CQuadNode
00244     {
00245     public:
00246         CQuadNode   *Prev,*Next;
00247         CNode       *Node;
00248 
00249         CQuadNode() : Prev(NULL), Next(NULL), Node(NULL) {}
00250 
00251         // can't call this at ctor since copied in array
00252         void    initRoot()
00253         {
00254             Prev= this;
00255             Next= this;
00256             Node= NULL;
00257         }
00258     };
00259 
00262     class   CBaseNode
00263     {
00264     public:
00265         CBaseNode   *Prev,*Next;    // For selection.
00266         bool        Selected;       // true if owned by _SelectedList, or by _UnSelectedList.
00267         CBaseNode() {Prev= Next= NULL;}
00268     };
00269 
00272     class   CNode : public CBaseNode
00273     {
00274     public:
00275         T       Elt;
00276         // A node can be contained in L*H squares. This vector is a place holder for each node of each quad list
00277         NLMISC::CObjectVector<CQuadNode>    QuadNodes;
00278     };
00279 
00280 private:// Atttributes.
00281     std::vector<CQuadNode>  _Grid;
00282     sint                _Size;
00283     sint                _SizePower;
00284     float               _EltSize;
00285     NLMISC::CMatrix     _ChangeBasis;
00286     // Selection. Elements are either in _SelectedList or in _UnSelectedList
00287     CBaseNode           _SelectedList;      // list of elements selected.
00288     CBaseNode           _UnSelectedList;    // circular list of elements not selected
00289     // The memory for nodes
00290     NLMISC::CBlockMemory<CNode>                 _NodeBlockMemory;
00291 
00292 
00293 private:// Methods.
00294 
00295 
00296     // default constor imp
00297     void        initCons();
00298 
00299     // link a node to a root: Selected or UnSelected list
00300     void        linkToRoot(CBaseNode &root, CBaseNode *ptr)
00301     {
00302         ptr->Prev= &root;
00303         ptr->Next= root.Next;
00304         ptr->Prev->Next= ptr;
00305         if(ptr->Next)
00306             ptr->Next->Prev= ptr;
00307     }
00308 
00309     void initSelectStamps() const
00310     {
00311         if (_AlreadySelected.size() < _Grid.size())
00312         {
00313             _AlreadySelected.resize(_Grid.size(), _SelectStamp);
00314         }
00315         ++ _SelectStamp;
00316         if (_SelectStamp == 0)
00317         {
00318             std::fill(_AlreadySelected.begin(), _AlreadySelected.end(), (uint) ~0);
00319         }
00320     }
00321 
00322     // return the coordinates on the grid of what include the bbox.
00323     void        selectQuads(CVector bmin, CVector bmax, sint &x0, sint &x1, sint &y0, sint &y1)
00324     {
00325         CVector     bminp, bmaxp;
00326         bminp= bmin;
00327         bmaxp= bmax;
00328         bmin.minof(bminp, bmaxp);
00329         bmax.maxof(bminp, bmaxp);
00330         bmin/= _EltSize;
00331         bmax/= _EltSize;
00332         x0= (sint)(floor(bmin.x));
00333         x1= (sint)(ceil(bmax.x));
00334         y0= (sint)(floor(bmin.y));
00335         y1= (sint)(ceil(bmax.y));
00336 
00337         // Very special case where the bbox.size==0 AND position is JUST on an edge of a case.
00338         if(x0==x1)
00339             x1++;
00340         if(y0==y1)
00341             y1++;
00342 
00343         // Manage tiling.
00344         if(x1-x0>=_Size)
00345             x0=0, x1= _Size;
00346         else
00347         {
00348             x0&= _Size-1;
00349             x1&= _Size-1;
00350             if(x1<=x0)
00351                 x1+=_Size;
00352         }
00353         if(y1-y0>=_Size)
00354             y0=0, y1= _Size;
00355         else
00356         {
00357             y0&= _Size-1;
00358             y1&= _Size-1;
00359             if(y1<=y0)
00360                 y1+=_Size;
00361         }
00362     }
00363 
00364     // If not done, add the node to the selection.
00365     void        addToSelection(CNode    *ptr)
00366     {
00367         // if not selected
00368         if(!ptr->Selected)
00369         {
00370             // remove from the unselected list.
00371             ptr->Prev->Next= ptr->Next;
00372             if(ptr->Next)
00373                 ptr->Next->Prev= ptr->Prev;
00374 
00375             // Append to front of the _Selected list.
00376             linkToRoot(_SelectedList, ptr);
00377 
00378             // mark it
00379             ptr->Selected= true;
00380         }
00381     }
00382 
00383     // Try to add each node of the quad node list.
00384     void        addQuadNodeToSelection(CQuadNode    &quad)
00385     {
00386         // NB: the root quadNode does not contains any Node
00387         nlassert(quad.Node==NULL);
00388         CQuadNode   *qn= quad.Next;
00389         // until we roll all the circular list
00390         while(qn!=&quad)
00391         {
00392             nlassert(qn->Node);
00393             addToSelection(qn->Node);
00394             qn= qn->Next;
00395         }
00396     }
00397 
00398 
00399 public:
00400     // CLASS const_iterator.
00401     class const_iterator
00402     {
00403     public:
00404         const_iterator()    {_Ptr=NULL;}
00405         const_iterator(CNode *p) : _Ptr(p) {}
00406         const_iterator(const CIterator& x) : _Ptr(x._Ptr) {}
00407 
00408         const T&    operator*() const
00409             {return _Ptr->Elt; }
00410         // Doesn't work...
00411         /*const T*  operator->() const
00412             {return (&**this); }*/
00413         const_iterator& operator++()
00414             {_Ptr = (CNode*)(_Ptr->Next); return (*this); }
00415         const_iterator operator++(int)
00416             {const_iterator tmp = *this; ++*this; return (tmp); }
00417         const_iterator& operator--()
00418             {_Ptr = (CNode*)(_Ptr->Prev); return (*this); }
00419         const_iterator operator--(int)
00420             {const_iterator tmp = *this; --*this; return (tmp); }
00421         bool operator==(const const_iterator& x) const
00422             {return (_Ptr == x._Ptr); }
00423         bool operator!=(const const_iterator& x) const
00424             {return (!(*this == x)); }
00425     protected:
00426         CNode   *_Ptr;
00427         friend class CQuadGrid<T>;
00428         friend class CIterator;
00429     };
00430 
00431     // CLASS CIterator
00432     class CIterator : public const_iterator
00433     {
00434     public:
00435         CIterator()         {this->_Ptr=NULL;}
00436         CIterator(CNode *p) : const_iterator(p) {}
00437         T&  operator*() const
00438             {return this->_Ptr->Elt; }
00439         // Doesn't work...
00440         /*T*    operator->() const
00441             {return (&**this); }*/
00442         CIterator& operator++()
00443             {this->_Ptr = (CNode*)(this->_Ptr->Next); return (*this); }
00444         CIterator operator++(int)
00445             {CIterator tmp = *this; ++*this; return (tmp); }
00446         CIterator& operator--()
00447             {this->_Ptr = (CNode*)(this->_Ptr->Prev); return (*this); }
00448         CIterator operator--(int)
00449             {CIterator tmp = *this; --*this; return (tmp); }
00450         bool operator==(const const_iterator& x) const
00451             {return (this->_Ptr == x._Ptr); }
00452         bool operator!=(const const_iterator& x) const
00453             {return (!(*this == x)); }
00454     protected:
00455         friend class CQuadGrid<T>;
00456     };
00457 
00458 
00459 };
00460 
00461 
00462 // ***************************************************************************
00463 // ***************************************************************************
00464 // ***************************************************************************
00465 // ***************************************************************************
00466 // Template CQuadGrid implementation.
00467 // ***************************************************************************
00468 // ***************************************************************************
00469 // ***************************************************************************
00470 // ***************************************************************************
00471 
00472 
00473 // ***************************************************************************
00474 // Init.
00475 // ***************************************************************************
00476 
00477 
00478 // ***************************************************************************
00479 template<class T>   CQuadGrid<T>::CQuadGrid(uint memoryBlockSize) :
00480     _NodeBlockMemory(memoryBlockSize)
00481 {
00482     initCons();
00483 }
00484 // ***************************************************************************
00485 template<class T>   CQuadGrid<T>::CQuadGrid(const CQuadGrid<T> &o) : _NodeBlockMemory(o._NodeBlockMemory)
00486 {
00487     // _NodeBlockMemory Copy ctor just init block memory setup (not data)
00488     // init default
00489     initCons();
00490     // copy
00491     operator=(o);
00492 }
00493 // ***************************************************************************
00494 template<class T>   void        CQuadGrid<T>::initCons()
00495 {
00496     _ChangeBasis.identity();
00497     // create a valid grid with default size
00498     create(16, 1);
00499 }
00500 // ***************************************************************************
00501 template<class T>   CQuadGrid<T> &CQuadGrid<T>::operator=(const CQuadGrid<T> &o)
00502 {
00503     // this==o test
00504     if(this==&o)
00505         return *this;
00506 
00507     // recreate (full cleared first)
00508     create(o._Size, o._EltSize);
00509     nlassert(_Grid.size()==o._Grid.size());
00510     nlassert(_SelectedList.Next==NULL);
00511     nlassert(_UnSelectedList.Next==NULL);
00512 
00513     // copy basis
00514     _ChangeBasis= o._ChangeBasis;
00515 
00516     // Fill with copy of elements of other grid. Complex copy...
00517     std::map<const CNode*, CNode *> srcNodeToDestNode;
00518     std::map<const CNode*, uint>        srcNodeToIndexInQuadNodes;
00519     // NB: the order of nodes in CNode::QuadNodes is not important (may be different from src to dst)
00520     for(uint i=0;i<_Grid.size();i++)
00521     {
00522         const CQuadNode     &quadSrcRoot= o._Grid[i];
00523         CQuadNode           &quadDstRoot= _Grid[i];
00524         const CQuadNode     *quadSrcCur= quadSrcRoot.Next;
00525         // until we roll all the circular list
00526         while(quadSrcCur!=&quadSrcRoot)
00527         {
00528             const CNode *srcNode= quadSrcCur->Node;
00529             nlassert(srcNode);
00530 
00531             // get the dest node created for this src node
00532             CNode   *dstNode= NULL;
00533             typename std::map<const CNode*, CNode *>::iterator  it= srcNodeToDestNode.find(srcNode);
00534             if(it!=srcNodeToDestNode.end())
00535             {
00536                 dstNode= it->second;
00537             }
00538             // else this src node had not already been created
00539             else
00540             {
00541                 // create a new node, copy content, and resize place holder
00542                 dstNode=_NodeBlockMemory.allocate();
00543                 dstNode->Elt= srcNode->Elt;
00544                 dstNode->QuadNodes.resize(srcNode->QuadNodes.size());
00545 
00546                 // Link to _Unselected list.
00547                 linkToRoot(_UnSelectedList, dstNode);
00548                 // mark as not selected.
00549                 dstNode->Selected= false;
00550 
00551                 // insert in the map
00552                 srcNodeToDestNode[srcNode]= dstNode;
00553 
00554                 // insert in the map of "index in quad node array"
00555                 srcNodeToIndexInQuadNodes[srcNode]= 0;
00556             }
00557 
00558             // get the quadnode to insert in, and increment index
00559             uint    index= srcNodeToIndexInQuadNodes[srcNode]++;
00560             nlassert(index<dstNode->QuadNodes.size());
00561             CQuadNode   &quadDstCur= dstNode->QuadNodes[index];
00562 
00563             // link
00564             quadDstCur.Node= dstNode;
00565             // insert in back of list
00566             quadDstCur.Next= &quadDstRoot;
00567             quadDstCur.Prev= quadDstRoot.Prev;
00568             quadDstRoot.Prev->Next= &quadDstCur;
00569             quadDstRoot.Prev= &quadDstCur;
00570 
00571 
00572             // next
00573             quadSrcCur= quadSrcCur->Next;
00574         }
00575     }
00576 
00577     return *this;
00578 }
00579 // ***************************************************************************
00580 template<class T>   CQuadGrid<T>::~CQuadGrid()
00581 {
00582     clear();
00583     _Grid.clear();
00584 }
00585 // ***************************************************************************
00586 template<class T>   void        CQuadGrid<T>::changeBase(const NLMISC::CMatrix& base)
00587 {
00588     _ChangeBasis= base;
00589 }
00590 // ***************************************************************************
00591 template<class T>   void        CQuadGrid<T>::create(uint size, float eltSize)
00592 {
00593     // full clear
00594     clear();
00595     _Grid.clear();
00596 
00597     // recreate
00598     nlassert(NLMISC::isPowerOf2(size));
00599     nlassert(size<=32768);
00600     _SizePower= NLMISC::getPowerOf2(size);
00601     _Size=1<<_SizePower;
00602     _Grid.resize(_Size*_Size);
00603     // Init QuadNode Root (can't be done in ctor() because of vector<> copy)
00604     for(uint i=0;i<_Grid.size();i++)
00605         _Grid[i].initRoot();
00606 
00607     nlassert(eltSize>0);
00608     _EltSize= eltSize;
00609 }
00610 
00611 
00612 // ***************************************************************************
00613 // insert/erase.
00614 // ***************************************************************************
00615 
00616 
00617 // ***************************************************************************
00618 template<class T>   void        CQuadGrid<T>::clear()
00619 {
00620     CIterator   it;
00621     selectAll();
00622     while( (it=begin())!=end())
00623     {
00624         erase(it);
00625     }
00626 
00627     // Clear the 2 selection...
00628     _SelectedList.Next= NULL;
00629     _UnSelectedList.Next= NULL;
00630 }
00631 // ***************************************************************************
00632 template<class T>   typename CQuadGrid<T>::CIterator    CQuadGrid<T>::erase(typename CQuadGrid<T>::CIterator it)
00633 {
00634     CNode   *ptr= it._Ptr;
00635 
00636     if(!ptr)
00637         return end();
00638 
00639     // First erase from all QuadNode list
00640     //==================================
00641     for(uint i=0;i<ptr->QuadNodes.size();i++)
00642     {
00643         CQuadNode   &qn= ptr->QuadNodes[i];
00644         // unlink from circular list
00645         qn.Next->Prev= qn.Prev;
00646         qn.Prev->Next= qn.Next;
00647     }
00648     ptr->QuadNodes.clear();
00649 
00650 
00651     // Then delete it..., and update selection linked list.
00652     //=====================================================
00653     // remove it from _SelectedList or _UnSelectedList
00654     CBaseNode   *next= NULL;
00655     next= ptr->Next;
00656     if(next)
00657         next->Prev=ptr->Prev;
00658     ptr->Prev->Next= next;
00659     // if not selected, then must return NULL
00660     if(!ptr->Selected)
00661         next= NULL;
00662     // delete the object.
00663     _NodeBlockMemory.free(ptr);
00664 
00665 
00666     return CIterator((CNode*)next);
00667 }
00668 // ***************************************************************************
00669 template<class T>   typename CQuadGrid<T>::CIterator    CQuadGrid<T>::insert(const NLMISC::CVector &bboxmin, const NLMISC::CVector &bboxmax, const T &val)
00670 {
00671     CVector     bmin,bmax;
00672     bmin= _ChangeBasis*bboxmin;
00673     bmax= _ChangeBasis*bboxmax;
00674 
00675     // init the object.
00676     CNode   *ptr= _NodeBlockMemory.allocate();
00677     ptr->Elt= val;
00678     // Link to _Unselected list.
00679     linkToRoot(_UnSelectedList, ptr);
00680     // mark as not selected.
00681     ptr->Selected= false;
00682 
00683 
00684     // Find which quad include the object.
00685     //===================================
00686     sint    x0,y0;
00687     sint    x1,y1;
00688     selectQuads(bmin, bmax, x0,x1, y0,y1);
00689 
00690     // must fit at lease in one quad
00691     sint    wn= x1-x0;
00692     sint    hn= y1-y0;
00693     nlassert(wn>0 && hn>0);
00694     // NB: this allocation may be slow (don't use BlockMemory system). But STLPort smallblock alloc
00695     // works quite well (if <128 bytes, ie a block of 10 squares)
00696     ptr->QuadNodes.resize(wn*hn);
00697 
00698     // Then for all of them, insert the node in their list.
00699     //=====================================================
00700     sint    x,y;
00701     for(y= y0;y<y1;y++)
00702     {
00703         sint    xg,yg;      // x,y in grid (_Grid[])
00704         sint    xn,yn;      // x,y in node array (ptr->QuadNodes[])
00705         yg= y &(_Size-1);
00706         yn= y-y0;
00707         for(x= x0;x<x1;x++)
00708         {
00709             xg= x &(_Size-1);
00710             xn= x-x0;
00711             CQuadNode   &quadRoot= _Grid[(yg<<_SizePower)+xg];
00712             CQuadNode   &quadNew= ptr->QuadNodes[yn*wn+xn];
00713             // let point on the node created
00714             quadNew.Node= ptr;
00715             // insert in back of list
00716             quadNew.Next= &quadRoot;
00717             quadNew.Prev= quadRoot.Prev;
00718             quadRoot.Prev->Next= &quadNew;
00719             quadRoot.Prev= &quadNew;
00720         }
00721     }
00722 
00723     return CIterator(ptr);
00724 }
00725 
00726 
00727 // ***************************************************************************
00728 // selection.
00729 // ***************************************************************************
00730 
00731 
00732 // ***************************************************************************
00733 template<class T>   void            CQuadGrid<T>::clearSelection()
00734 {
00735     CBaseNode   *ptr= _SelectedList.Next;
00736     while(ptr)
00737     {
00738         // next selected.
00739         CBaseNode   *nextSelected= ptr->Next;
00740 
00741         // Link to _Unselected list.
00742         linkToRoot(_UnSelectedList, ptr);
00743 
00744         // mark as not selected.
00745         ptr->Selected= false;
00746 
00747         // next.
00748         ptr= nextSelected;
00749     }
00750 
00751     // the selected list is now empty.
00752     _SelectedList.Next= NULL;
00753 }
00754 // ***************************************************************************
00755 template<class T>   void            CQuadGrid<T>::selectAll()
00756 {
00757     // This is the opposite of clearSelection(). get all that are in _UnSelectedList,
00758     // and put them in _SelectedList
00759     CBaseNode   *ptr= _UnSelectedList.Next;
00760     while(ptr)
00761     {
00762         // next selected.
00763         CBaseNode   *nextUnSelected= ptr->Next;
00764 
00765         // Link to _Selected list.
00766         linkToRoot(_SelectedList, ptr);
00767 
00768         // mark as selected.
00769         ptr->Selected= true;
00770 
00771         // next.
00772         ptr= nextUnSelected;
00773     }
00774 
00775     // the Unselected list is now empty.
00776     _UnSelectedList.Next= NULL;
00777 }
00778 // ***************************************************************************
00779 template<class T>   void            CQuadGrid<T>::select(const NLMISC::CVector &bboxmin, const NLMISC::CVector &bboxmax)
00780 {
00781     CVector     bmin,bmax;
00782     bmin= _ChangeBasis*bboxmin;
00783     bmax= _ChangeBasis*bboxmax;
00784 
00785     clearSelection();
00786 
00787     // What are the quads to access?
00788     sint    x0,y0;
00789     sint    x1,y1;
00790     selectQuads(bmin, bmax, x0,x1, y0,y1);
00791 
00792     sint    x,y;
00793     for(y= y0;y<y1;y++)
00794     {
00795         sint    xe,ye;
00796         ye= y &(_Size-1);
00797         for(x= x0;x<x1;x++)
00798         {
00799             xe= x &(_Size-1);
00800             CQuadNode   &quad= _Grid[(ye<<_SizePower)+xe];
00801             addQuadNodeToSelection(quad);
00802         }
00803     }
00804 
00805 }
00806 
00807 // ***************************************************************************
00808 template<class T> void  CQuadGrid<T>::buildSelectionShape(TSelectionShape &dest, const NLMISC::CPolygon2D &poly) const
00809 {
00810     dest.clear();
00811     sint minY;
00812     uint numVerts = poly.Vertices.size();
00813     _ScaledPoly.Vertices.resize(numVerts);
00814     nlassert(_EltSize != 0.f);
00815     float invScale = 1.f / _EltSize;
00816     for(uint k = 0; k < numVerts; ++k)
00817     {
00818         CVector xformPos = _ChangeBasis * CVector(poly.Vertices[k]);
00819         _ScaledPoly.Vertices[k].set(poly.Vertices[k].x * invScale, poly.Vertices[k].y * invScale);
00820     }
00821     _ScaledPoly.computeOuterBorders(_PolyBorders, minY);
00822     if (_PolyBorders.empty()) return;
00823     initSelectStamps();
00824     sint numSegs = _PolyBorders.size();
00825     for (sint y = 0; y < numSegs; ++y)
00826     {
00827         sint currIndex = ((minY + y) & (_Size - 1)) << _SizePower;
00828         for (sint x = _PolyBorders[y].first; x <= _PolyBorders[y].second; ++x)
00829         {
00830             sint currX = x & (_Size - 1);
00831             uint index = (uint) (currX + currIndex);
00832             if (_AlreadySelected[index] != _SelectStamp)
00833             {
00834                 _AlreadySelected[index] = _SelectStamp; // update stamp, so that won't be selected twice if
00835                                                 // there's an overlap
00836                 dest.push_back(index);
00837             }
00838         }
00839     }
00840 }
00841 
00842 // ***************************************************************************
00843 template<class T> void  CQuadGrid<T>::select(const TSelectionShape &shape)
00844 {
00845     clearSelection();
00846     for (TSelectionShape::const_iterator it = shape.begin(); it != shape.end(); ++it)
00847     {
00848         addQuadNodeToSelection(_Grid[*it]);
00849     }
00850 }
00851 
00852 // ***************************************************************************
00853 template<class T>
00854 void CQuadGrid<T>::selectRay(const NLMISC::CVector &rayStart, const NLMISC::CVector &rayEnd)
00855 {
00856     clearSelection();
00857     CVector localRayStart = _ChangeBasis * rayStart;
00858     CVector localRayEnd = _ChangeBasis * rayEnd;
00859     float invScale = 1.f / _EltSize;
00860     NLMISC::CVector2f localRayStart2f(localRayStart.x * invScale, localRayStart.y * invScale);
00861     NLMISC::CVector2f localRayEnd2f(localRayEnd.x * invScale, localRayEnd.y * invScale);
00862     NLMISC::CVector2f localRayDir = localRayEnd2f - localRayStart2f;
00863     initSelectStamps();
00864     sint x, y;
00865     NLMISC::CGridTraversal::startTraverse(localRayStart2f, x, y);
00866     do
00867     {
00868         uint index = (x & (_Size - 1)) + ((y & (_Size - 1))  << _SizePower);
00869         if (_AlreadySelected[index] != _SelectStamp)
00870         {
00871             _AlreadySelected[index] = _SelectStamp; // update stamp, so that won't be selected twice if
00872             addQuadNodeToSelection(_Grid[index]);
00873         }
00874     }
00875     while (NLMISC::CGridTraversal::traverse(localRayStart2f, localRayDir, x, y));
00876 }
00877 
00878 
00879 // ***************************************************************************
00880 template<class T>   typename CQuadGrid<T>::CIterator        CQuadGrid<T>::begin()
00881 {
00882     return CIterator((CNode*)(_SelectedList.Next));
00883 }
00884 // ***************************************************************************
00885 template<class T>   typename CQuadGrid<T>::CIterator        CQuadGrid<T>::end()
00886 {
00887     return CIterator(NULL);
00888 }
00889 
00890 
00891 } // NL3D
00892 
00893 
00894 #endif // NL_QUAD_GRID_H
00895 
00896 /* End of quad_grid.h */

Generated on Thu Jan 7 08:26:20 2010 for NeL by  doxygen 1.6.1