• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

GridSectorizer.cpp

Go to the documentation of this file.
00001 #include "RakAssert.h"
00002 #include "GridSectorizer.h"
00003 //#include <stdlib.h>
00004 #include <math.h>
00005 
00006 GridSectorizer::GridSectorizer()
00007 {
00008         grid=0;
00009 }
00010 GridSectorizer::~GridSectorizer()
00011 {
00012         if (grid)
00013                 RakNet::OP_DELETE_ARRAY(grid, __FILE__, __LINE__);
00014 }
00015 void GridSectorizer::Init(const float _maxCellWidth, const float _maxCellHeight, const float minX, const float minY, const float maxX, const float maxY)
00016 {
00017         RakAssert(_maxCellWidth > 0.0f && _maxCellHeight > 0.0f);
00018         if (grid)
00019                 RakNet::OP_DELETE_ARRAY(grid, __FILE__, __LINE__);
00020 
00021         cellOriginX=minX;
00022         cellOriginY=minY;
00023         gridWidth=maxX-minX;
00024         gridHeight=maxY-minY;
00025         gridCellWidthCount=(int) ceil(gridWidth/_maxCellWidth);
00026         gridCellHeightCount=(int) ceil(gridHeight/_maxCellHeight);
00027         // Make the cells slightly smaller, so we allocate an extra unneeded cell if on the edge.  This way we don't go outside the array on rounding errors.
00028         cellWidth=gridWidth/gridCellWidthCount;
00029         cellHeight=gridHeight/gridCellHeightCount;
00030         invCellWidth = 1.0f / cellWidth;
00031         invCellHeight = 1.0f / cellHeight;
00032 
00033 #ifdef _USE_ORDERED_LIST
00034         grid = RakNet::OP_NEW<DataStructures::OrderedList<void*, void*>>(gridCellWidthCount*gridCellHeightCount, __FILE__, __LINE__ );
00035         DataStructures::OrderedList<void*,void*>::IMPLEMENT_DEFAULT_COMPARISON();
00036 #else
00037         grid = RakNet::OP_NEW_ARRAY<DataStructures::List<void*> >(gridCellWidthCount*gridCellHeightCount, __FILE__, __LINE__ );
00038 #endif
00039 }
00040 void GridSectorizer::AddEntry(void *entry, const float minX, const float minY, const float maxX, const float maxY)
00041 {
00042         RakAssert(cellWidth>0.0f);
00043         RakAssert(minX < maxX && minY < maxY);
00044 
00045         int xStart, yStart, xEnd, yEnd, xCur, yCur;
00046         xStart=WorldToCellXOffsetAndClamped(minX);
00047         yStart=WorldToCellYOffsetAndClamped(minY);
00048         xEnd=WorldToCellXOffsetAndClamped(maxX);
00049         yEnd=WorldToCellYOffsetAndClamped(maxY);
00050 
00051         for (xCur=xStart; xCur <= xEnd; ++xCur)
00052         {
00053                 for (yCur=yStart; yCur <= yEnd; ++yCur)
00054                 {
00055 #ifdef _USE_ORDERED_LIST
00056                         grid[yCur*gridCellWidthCount+xCur].Insert(entry,entry, true);
00057 #else
00058                         grid[yCur*gridCellWidthCount+xCur].Insert(entry, __FILE__, __LINE__);
00059 #endif
00060                 }
00061         }
00062 }
00063 #ifdef _USE_ORDERED_LIST
00064 void GridSectorizer::RemoveEntry(void *entry, const float minX, const float minY, const float maxX, const float maxY)
00065 {
00066         RakAssert(cellWidth>0.0f);
00067         RakAssert(minX <= maxX && minY <= maxY);
00068 
00069         int xStart, yStart, xEnd, yEnd, xCur, yCur;
00070         xStart=WorldToCellXOffsetAndClamped(minX);
00071         yStart=WorldToCellYOffsetAndClamped(minY);
00072         xEnd=WorldToCellXOffsetAndClamped(maxX);
00073         yEnd=WorldToCellYOffsetAndClamped(maxY);
00074 
00075         for (xCur=xStart; xCur <= xEnd; ++xCur)
00076         {
00077                 for (yCur=yStart; yCur <= yEnd; ++yCur)
00078                 {
00079                         grid[yCur*gridCellWidthCount+xCur].RemoveIfExists(entry);
00080                 }
00081         }
00082 }
00083 void GridSectorizer::MoveEntry(void *entry, const float sourceMinX, const float sourceMinY, const float sourceMaxX, const float sourceMaxY,
00084                            const float destMinX, const float destMinY, const float destMaxX, const float destMaxY)
00085 {
00086         RakAssert(cellWidth>0.0f);
00087         RakAssert(sourceMinX < sourceMaxX && sourceMinY < sourceMaxY);
00088         RakAssert(destMinX < destMaxX && destMinY < destMaxY);
00089 
00090         if (PositionCrossesCells(sourceMinX, sourceMinY, destMinX, destMinY)==false &&
00091                 PositionCrossesCells(destMinX, destMinY, destMinX, destMinY)==false)
00092                 return;
00093 
00094         int xStartSource, yStartSource, xEndSource, yEndSource;
00095         int xStartDest, yStartDest, xEndDest, yEndDest;
00096         int xCur, yCur;
00097         xStartSource=WorldToCellXOffsetAndClamped(sourceMinX);
00098         yStartSource=WorldToCellYOffsetAndClamped(sourceMinY);
00099         xEndSource=WorldToCellXOffsetAndClamped(sourceMaxX);
00100         yEndSource=WorldToCellYOffsetAndClamped(sourceMaxY);
00101 
00102         xStartDest=WorldToCellXOffsetAndClamped(destMinX);
00103         yStartDest=WorldToCellYOffsetAndClamped(destMinY);
00104         xEndDest=WorldToCellXOffsetAndClamped(destMaxX);
00105         yEndDest=WorldToCellYOffsetAndClamped(destMaxY);
00106 
00107         // Remove source that is not in dest
00108         for (xCur=xStartSource; xCur <= xEndSource; ++xCur)
00109         {
00110                 for (yCur=yStartSource; yCur <= yEndSource; ++yCur)
00111                 {
00112                         if (xCur < xStartDest || xCur > xEndDest ||
00113                                 yCur < yStartDest || yCur > yEndDest)
00114                         {
00115                                 grid[yCur*gridCellWidthCount+xCur].RemoveIfExists(entry);
00116                         }
00117                 }
00118         }
00119 
00120         // Add dest that is not in source
00121         for (xCur=xStartDest; xCur <= xEndDest; ++xCur)
00122         {
00123                 for (yCur=yStartDest; yCur <= yEndDest; ++yCur)
00124                 {
00125                         if (xCur < xStartSource || xCur > xEndSource ||
00126                                 yCur < yStartSource || yCur > yEndSource)
00127                         {
00128                                 grid[yCur*gridCellWidthCount+xCur].Insert(entry,entry, true);
00129                         }
00130                 }
00131         }
00132 }
00133 #endif
00134 void GridSectorizer::GetEntries(DataStructures::List<void*>& intersectionList, const float minX, const float minY, const float maxX, const float maxY)
00135 {
00136 #ifdef _USE_ORDERED_LIST
00137         DataStructures::OrderedList<void*, void*>* cell;
00138 #else
00139         DataStructures::List<void*>* cell;
00140 #endif
00141         int xStart, yStart, xEnd, yEnd, xCur, yCur;
00142         unsigned index;
00143         xStart=WorldToCellXOffsetAndClamped(minX);
00144         yStart=WorldToCellYOffsetAndClamped(minY);
00145         xEnd=WorldToCellXOffsetAndClamped(maxX);
00146         yEnd=WorldToCellYOffsetAndClamped(maxY);
00147 
00148         intersectionList.Clear(true, __FILE__,__LINE__);
00149         for (xCur=xStart; xCur <= xEnd; ++xCur)
00150         {
00151                 for (yCur=yStart; yCur <= yEnd; ++yCur)
00152                 {
00153                         cell = grid+yCur*gridCellWidthCount+xCur;
00154                         for (index=0; index < cell->Size(); ++index)
00155                                 intersectionList.Insert(cell->operator [](index), __FILE__, __LINE__);
00156                 }
00157         }
00158 }
00159 bool GridSectorizer::PositionCrossesCells(const float originX, const float originY, const float destinationX, const float destinationY) const
00160 {
00161         return originX/cellWidth!=destinationX/cellWidth || originY/cellHeight!=destinationY/cellHeight;
00162 }
00163 int GridSectorizer::WorldToCellX(const float input) const
00164 {
00165         return (int)((input-cellOriginX)*invCellWidth);
00166 }
00167 int GridSectorizer::WorldToCellY(const float input) const
00168 {
00169         return (int)((input-cellOriginY)*invCellHeight);
00170 }
00171 int GridSectorizer::WorldToCellXOffsetAndClamped(const float input) const
00172 {
00173         int cell=WorldToCellX(input);
00174         cell = cell > 0 ? cell : 0; // __max(cell,0);
00175         cell = gridCellWidthCount-1 < cell ? gridCellWidthCount-1 : cell; // __min(gridCellWidthCount-1, cell);
00176         return cell;
00177 }
00178 int GridSectorizer::WorldToCellYOffsetAndClamped(const float input) const
00179 {
00180         int cell=WorldToCellY(input);
00181         cell = cell > 0 ? cell : 0; // __max(cell,0);
00182         cell = gridCellHeightCount-1 < cell ? gridCellHeightCount-1 : cell; // __min(gridCellHeightCount-1, cell);
00183         return cell;
00184 }
00185 void GridSectorizer::Clear(void)
00186 {
00187         int cur;
00188         int count = gridCellWidthCount*gridCellHeightCount;
00189         for (cur=0; cur<count;cur++)
00190                 grid[cur].Clear(true, __FILE__,__LINE__);
00191 }

Generated on Thu Sep 30 2010 01:27:24 for RakNet by  doxygen 1.7.1