Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

grid.hpp

Go to the documentation of this file.
00001 #ifndef _GRID_HPP
00002 #define _GRID_HPP
00003 
00004 #include <assert.h>
00005 #include <list>
00006 #include "geometry.hpp"
00007 
00008 namespace Arak {
00009 
00017   template <class ItemType>
00018   class Grid {
00019 
00020   public:
00021 
00030     class Cell : public Geometry::Rectangle {
00031 
00032       friend class Grid;
00033       friend class Grid::LineCellIterator;
00034       friend class Grid::ConstLineCellIterator;
00035       friend class Grid::RectangleCellIterator;
00036       friend class Grid::ConstRectangleCellIterator;
00037       friend class Grid::TriangleCellIterator;
00038       friend class Grid::ConstTriangleCellIterator;
00039       friend class Grid::ConvexPolygonCellIterator;
00040       friend class Grid::ConstConvexPolygonCellIterator;
00041       
00042     public:
00043 
00047       typedef std::list<ItemType> ItemList;
00048 
00049     protected:
00050 
00054       typedef typename ItemList::iterator ItemIterator;
00055 
00059       int r;
00060 
00064       int c;
00065 
00069       ItemList items;
00070       
00075       ItemList unused;
00076       
00081       Cell* up;
00082 
00087       Cell* down;
00088 
00093       Cell* right;
00094 
00099       Cell* left;
00100 
00101     public:
00102 
00107       class Entry {
00108 
00109       private:
00110 
00114   Cell* cell;
00115 
00119   ItemIterator it;
00120 
00121       public:
00122 
00126   Entry() : cell(NULL), it() { }
00127 
00131   Entry(Cell* cell, ItemIterator it) : cell(cell), it(it) { }
00132 
00136   bool valid() const { return (cell != NULL); }
00137 
00143   void remove() {
00144     assert(valid());
00145     // Move the item to the unused list.
00146     cell->unused.splice(cell->unused.begin(), cell->items, it);
00147     cell = NULL;
00148   }
00149 
00153   const Cell& getCell() const { return *cell; }
00154 
00155       }; // end of class: Grid::Cell::Entry
00156 
00164       Cell(const Geometry::Rectangle& r, int row, int col) : 
00165   Geometry::Rectangle(r), r(row), c(col), items(),
00166   up(NULL), down(NULL), right(NULL), left(NULL) { }
00167 
00175       inline Entry add(const ItemType& e) {
00176   if (unused.empty()) {
00177     // We have run out of unused items.  Use a simple insertion.
00178     return Entry(this, items.insert(items.begin(), e));
00179   } else {
00180     // The unused list is not empty; reuse its first element.
00181     ItemIterator it = unused.begin();
00182     *it = e;
00183     items.splice(items.begin(), unused, it);
00184     return Entry(this, items.begin());
00185   }
00186       }
00187 
00191       inline const ItemList& getItemList() const {
00192   return items;
00193       }
00194 
00198       inline ItemList& getItemList() {
00199   return items;
00200       }
00201 
00205       int row() const { return r; }
00206 
00210       int col() const { return c; }
00211 
00215       bool operator==(const Cell& other) const { return (this == &other); }
00216       bool operator!=(const Cell& other) const { return (this != &other); }
00217 
00221       Geometry::Point center() const {
00222   return CGAL::midpoint((*this)[0], (*this)[2]);
00223       }
00224 
00225     }; // end of class: Grid::Cell
00226 
00234     template <class GridType, class CellType>
00235     class LineCellIteratorBase {
00236 
00237     protected:
00238       
00242       Geometry::Line line;
00243 
00247       enum CompassDirection {
00248   NORTH,      
00249   NORTH_EAST, 
00250   EAST,       
00251   SOUTH_EAST, 
00252   SOUTH,      
00253   SOUTH_WEST, 
00254   WEST,       
00255   NORTH_WEST  
00256       };
00257 
00261       CompassDirection dir;
00262 
00266       CellType* curCell;
00267 
00272       CellType* lastCell;
00273 
00281       inline CompassDirection direction(const Geometry::Point& p,
00282           const Geometry::Point& q) {
00283   CGAL::Comparison_result xc = CGAL::compare_x(p, q);
00284   CGAL::Comparison_result yc = CGAL::compare_y(p, q);
00285   switch (xc) {
00286   case CGAL::SMALLER:
00287     switch (yc) {
00288     case CGAL::SMALLER:
00289       return NORTH_EAST; 
00290     case CGAL::LARGER:
00291       return SOUTH_EAST; 
00292     case CGAL::EQUAL:
00293     default:
00294       return EAST;
00295     }
00296   case CGAL::LARGER:
00297     switch (yc) {
00298     case CGAL::SMALLER:
00299       return NORTH_WEST;
00300     case CGAL::LARGER:
00301       return SOUTH_WEST;
00302     case CGAL::EQUAL:
00303     default:
00304       return WEST;
00305     }
00306   case CGAL::EQUAL:
00307   default:
00308     switch (yc) {
00309     case CGAL::SMALLER:
00310       return NORTH;
00311     case CGAL::LARGER:
00312       return SOUTH;
00313     case CGAL::EQUAL:
00314     default:
00315       assert(false);
00316     }
00317   }
00318       }
00319 
00320     public:
00321 
00326       struct SEGMENT { };
00327 
00332       struct RAY { };
00333 
00343       LineCellIteratorBase(GridType& g, 
00344          const Geometry::Point &p,
00345          const Geometry::Point &q,
00346          SEGMENT) : line(p, q) {
00347   dir = direction(p, q);
00348   if (g.boundary().has_on_unbounded_side(p) ||
00349       g.boundary().has_on_unbounded_side(q)) {
00350     Geometry::Segment s(p, q);
00351     Geometry::Point r;
00352     CGAL::Object intersection = CGAL::intersection(s, g.boundary());
00353     if (CGAL::assign(s, intersection)) {
00354       curCell = &g.getCell(Geometry::project(s.source(), g.boundary()));
00355       lastCell = &g.getCell(Geometry::project(s.target(), g.boundary()));
00356     } else if (CGAL::assign(r, intersection)) {
00357       curCell = lastCell = &g.getCell(Geometry::project(r, g.boundary()));
00358     } else {
00359       curCell = lastCell = NULL;
00360     }
00361   } else {
00362     curCell = &g.getCell(p);
00363     lastCell = &g.getCell(q);
00364   }
00365       }
00366 
00375       LineCellIteratorBase(GridType& g, 
00376          const Geometry::Point &p,
00377          const Geometry::Point &q,
00378          RAY) : line(p, q) {
00379   dir = direction(p, q);
00380   if (g.boundary().has_on_unbounded_side(p) ||
00381       g.boundary().has_on_unbounded_side(q)) {
00382     Geometry::Segment s(p, q);
00383     Geometry::Point r;
00384     CGAL::Object intersection = CGAL::intersection(s, g.boundary());
00385     if (CGAL::assign(s, intersection)) {
00386       curCell = &g.getCell(Geometry::project(s.source(), g.boundary()));
00387       lastCell = &g.getCell(Geometry::project(s.target(), g.boundary()));
00388     } else if (CGAL::assign(r, intersection)) {
00389       curCell = lastCell = &g.getCell(Geometry::project(r, g.boundary()));
00390     } else {
00391       curCell = lastCell = NULL;
00392     }
00393   } else {
00394     curCell = &g.getCell(p);
00395     lastCell = NULL;
00396   }
00397       }
00398 
00402       LineCellIteratorBase() 
00403   : line(1, 0, 0),
00404     curCell(NULL), 
00405     lastCell(NULL) { }
00406 
00410       inline bool 
00411       operator==(const LineCellIteratorBase<GridType,CellType>& other) const
00412       { return (curCell == other.curCell); }
00413       inline bool 
00414       operator!=(const LineCellIteratorBase<GridType,CellType>& other) const 
00415       { return !(*this == other); }
00416 
00420       inline LineCellIteratorBase<GridType,CellType>& operator++(int) {
00421   LineCellIteratorBase<GridType,CellType> tmp(*this);
00422   ++(*this);
00423   return tmp;
00424       }
00425       inline LineCellIteratorBase<GridType,CellType>& operator++() {
00426   using namespace Arak::Geometry;
00427   assert(curCell != NULL);
00428   if (curCell == lastCell) {
00429     curCell = NULL;
00430     return *this;
00431   }
00432   switch (dir) {
00433   case NORTH_EAST:
00434     switch (CGAL::compare_y_at_x(curCell->vertex(2), line)) {
00435     case CGAL::SMALLER:
00436       curCell = curCell->up; break;
00437     case CGAL::LARGER:
00438       curCell = curCell->right; break;
00439     case CGAL::EQUAL:
00440       curCell = curCell->right;
00441       if (curCell != NULL)
00442         curCell = curCell->up; 
00443       break;
00444     }
00445     break;
00446   case SOUTH_EAST:
00447     switch (CGAL::compare_y_at_x(curCell->vertex(1), line)) {
00448     case CGAL::LARGER:
00449       curCell = curCell->down; break;
00450     case CGAL::SMALLER:
00451       curCell = curCell->right; break;
00452     case CGAL::EQUAL:
00453       curCell = curCell->right;
00454       if (curCell != NULL)
00455         curCell = curCell->down; 
00456       break;
00457     }
00458     break;
00459   case SOUTH_WEST:
00460     switch (CGAL::compare_y_at_x(curCell->vertex(0), line)) {
00461     case CGAL::LARGER:
00462       curCell = curCell->down; break;
00463     case CGAL::SMALLER:
00464       curCell = curCell->left; break;
00465     case CGAL::EQUAL:
00466       curCell = curCell->left; 
00467       if (curCell != NULL)
00468         curCell = curCell->down; 
00469       break;
00470     }
00471     break;
00472   case NORTH_WEST:
00473     switch (CGAL::compare_y_at_x(curCell->vertex(3), line)) {
00474     case CGAL::SMALLER:
00475       curCell = curCell->up; break;
00476     case CGAL::LARGER:
00477       curCell = curCell->left; break;
00478     case CGAL::EQUAL:
00479       curCell = curCell->left; 
00480       if (curCell != NULL)
00481         curCell = curCell->up; 
00482       break;
00483     }
00484     break;
00485   case NORTH:
00486     curCell = curCell->up; 
00487     break;
00488   case SOUTH:
00489     curCell = curCell->down; 
00490     break;
00491   case EAST:
00492     curCell = curCell->right; 
00493     break;
00494   case WEST:
00495     curCell = curCell->left; 
00496     break;
00497   }
00498   return *this;
00499       }
00500 
00504       inline CellType* operator->() const {return curCell;}
00505       inline CellType& operator*() const { return *curCell;}
00506 
00507     }; // end of class: Grid::LineCellIteratorBase
00508 
00513     typedef LineCellIteratorBase<Grid, Cell> LineCellIterator;
00514 
00519     typedef LineCellIteratorBase<const Grid, const Cell> ConstLineCellIterator;
00520 
00525     template <class GridType, class CellType>
00526     class RectangleCellIteratorBase {
00527 
00528     protected:
00529       
00533       int i;
00534 
00538       int imax;
00539 
00543       int j;
00544 
00548       int jmin;
00549 
00553       int jmax;
00554 
00558       CellType* curCell;
00559 
00563       GridType* grid;
00564 
00565     public:
00566 
00574       RectangleCellIteratorBase(GridType& g, Geometry::Rectangle r)
00575   : curCell(NULL), grid(&g) { 
00576   if (CGAL::assign(r, CGAL::intersection(g.boundary(), r))) {
00577     assert(g.getCellCoords(r.min(), i, jmin));
00578     j = jmin;
00579     assert(g.getCellCoords(r.max(), imax, jmax));
00580     curCell = &g.getCell(i, j);
00581   } else {
00582     curCell = NULL;
00583   }
00584       }
00585 
00589       RectangleCellIteratorBase() : curCell(NULL), grid(NULL) { }
00590 
00594       inline bool operator==(const RectangleCellIteratorBase<GridType,CellType>& other) const
00595       { return (curCell == other.curCell); }
00596       inline bool operator!=(const RectangleCellIteratorBase<GridType,CellType>& other) const 
00597       { return !(*this == other); }
00598 
00602       inline RectangleCellIteratorBase<GridType,CellType>& operator++(int) {
00603   RectangleCellIteratorBase<GridType,CellType> tmp(*this);
00604   ++(*this);
00605   return tmp;
00606       }
00607       inline RectangleCellIteratorBase<GridType,CellType>& operator++() {
00608   using namespace Arak::Geometry;
00609   assert(curCell != NULL);
00610   if ((i == imax) && (j == jmax)) {
00611     curCell = NULL;
00612     return *this;
00613   } else if (j == jmax) {
00614     i++;
00615     j = jmin;
00616     curCell = &(grid->getCell(i, j));
00617   } else {
00618     j++;
00619     curCell = curCell->right;
00620   }
00621   return *this;
00622       }
00623 
00627       inline CellType* operator->() const { return curCell; }
00628       inline CellType& operator*() const { return *curCell; }
00629 
00630     }; // end of class: Grid::RectangleCellIteratorBase
00631 
00636     typedef RectangleCellIteratorBase<Grid, Cell> 
00637     RectangleCellIterator;
00638 
00643     typedef RectangleCellIteratorBase<const Grid, const Cell> 
00644     ConstRectangleCellIterator;
00645 
00650     template <class GridType, class CellType>
00651     class TriangleCellIteratorBase {
00652 
00653     protected:
00654       
00658       CellType* curCell;
00659 
00663       GridType* grid;
00664 
00668       int imin;
00669 
00673       int imax;
00674 
00680       std::vector<int> jmins;
00681 
00687       std::vector<int> jmaxs;
00688 
00689     public:
00690 
00698       TriangleCellIteratorBase(GridType& g, Geometry::Triangle t)
00699   : curCell(NULL), grid(&g) { 
00700   // Compute the smallest rectangle that covers the intersection
00701   // of the triangle and the grid's closure.
00702   Geometry::Rectangle r = Geometry::boundingRectangle(t[0], t[1], t[2]);
00703   if (!CGAL::assign(r, CGAL::intersection(g.boundary(), r))) {
00704     // The triangle does not intersect the grid's closure.
00705     curCell = NULL; 
00706     return;
00707   }
00708   // Compute the columns crossed by the triangle.
00709   int jmin, jmax;
00710   assert(g.getCellCoords(r.min(), imin, jmin));
00711   assert(g.getCellCoords(r.max(), imax, jmax));
00712   assert(imin <= imax);
00713   assert(jmin <= jmax);
00714   // Compute the values of jmins and jmaxs using line searches
00715   // along the boundary of the triangle.
00716   jmins.insert(jmins.end(), imax - imin + 1, 
00717          std::numeric_limits<int>::max());
00718   jmaxs.insert(jmaxs.end(), imax - imin + 1, 
00719          std::numeric_limits<int>::min());
00720   for (int v = 0; v < 3; v++) {
00721     ConstLineCellIterator it(g, t[v], t[v + 1], 
00722            ConstLineCellIterator::SEGMENT()), end;
00723     while (it != end) {
00724       const Cell& cell = *it;
00725       int i = cell.row();
00726       int j = cell.col();
00727       int k = i - imin;
00728       jmins[k] = std::min<int>(jmins[k], j);
00729       jmaxs[k] = std::max<int>(jmaxs[k], j);
00730       ++it;
00731     }
00732   }
00733   // Replace any unset limits using the bounding rectangle.
00734   std::replace(jmins.begin(), jmins.end(),
00735          std::numeric_limits<int>::max(), jmin);
00736   std::replace(jmaxs.begin(), jmaxs.end(),
00737          std::numeric_limits<int>::min(), jmax);
00738   // Initialize the iterator at the first cell.
00739   curCell = &g.getCell(imin, jmins[0]);
00740       }
00741 
00745       TriangleCellIteratorBase() : curCell(NULL), grid(NULL) { }
00746 
00750       inline bool operator==(const TriangleCellIteratorBase<GridType,CellType>& other) const
00751       { return (curCell == other.curCell); }
00752       inline bool operator!=(const TriangleCellIteratorBase<GridType,CellType>& other) const 
00753       { return !(*this == other); }
00754 
00758       inline TriangleCellIteratorBase<GridType,CellType>& operator++(int) {
00759   TriangleCellIterator tmp(*this);
00760   ++(*this);
00761   return tmp;
00762       }
00763       inline TriangleCellIteratorBase<GridType,CellType>& operator++() {
00764   using namespace Arak::Geometry;
00765   assert(curCell != NULL);
00766   int i = curCell->row();
00767   int j = curCell->col();
00768   int k = i - imin;
00769   if ((i == imax) && (j == jmaxs[k])) {
00770     // We are at the last cell; the iterator is finished.
00771     curCell = NULL;
00772     return *this;
00773   } else if (j == jmaxs[k])
00774     // We are at the last column but not the last row; wrap
00775     // around.
00776     curCell = &(grid->getCell(i + 1, jmins[k + 1]));
00777   else 
00778     // We have not reached the end of the current row; move
00779     // right.
00780     curCell = curCell->right;
00781   return *this;
00782       }
00783 
00787       inline CellType* operator->() const { return curCell; }
00788       inline CellType& operator*() const { return *curCell; }
00789       
00790     }; // end of class: Grid::TriangleCellIteratorBase
00791 
00796     typedef TriangleCellIteratorBase<Grid, Cell> 
00797     TriangleCellIterator;
00798 
00803     typedef TriangleCellIteratorBase<const Grid, const Cell> 
00804     ConstTriangleCellIterator;
00805 
00810     template <class GridType, class CellType>
00811     class ConvexPolygonCellIteratorBase {
00812 
00813     protected:
00814       
00818       CellType* curCell;
00819 
00823       GridType* grid;
00824 
00829       int imin;
00830 
00835       int imax;
00836 
00842       std::vector<int> jmins;
00843 
00849       std::vector<int> jmaxs;
00850 
00851     public:
00852 
00860       ConvexPolygonCellIteratorBase(GridType& g, const Geometry::Polygon& p)
00861   : curCell(NULL), grid(&g) { 
00862   // Compute the smallest rectangle that covers the intersection
00863   // of the triangle and the grid's closure.
00864   Geometry::Rectangle r(*(p.left_vertex()),
00865             *(p.right_vertex()),
00866             *(p.bottom_vertex()),
00867             *(p.top_vertex()));
00868   if (!CGAL::assign(r, CGAL::intersection(g.boundary(), r))) {
00869     // The polygon does not intersect the grid's closure.
00870     curCell = NULL; 
00871     return;
00872   }
00873   // Compute the columns crossed by the triangle.
00874   int jmin, jmax;
00875   assert(g.getCellCoords(r.min(), imin, jmin));
00876   assert(g.getCellCoords(r.max(), imax, jmax));
00877   assert(imin <= imax);
00878   assert(jmin <= jmax);
00879   // Compute the values of jmins and jmaxs using line searches
00880   // along the boundary of the polygon.
00881   jmins.insert(jmins.end(), imax - imin + 1, 
00882          std::numeric_limits<int>::max());
00883   jmaxs.insert(jmaxs.end(), imax - imin + 1, 
00884          std::numeric_limits<int>::min());
00885   const int size = p.size();
00886   for (int v = 0; v < size; v++) {
00887     ConstLineCellIterator it(g, p[v], p[(v + 1) % size], 
00888            ConstLineCellIterator::SEGMENT()), end;
00889     while (it != end) {
00890       const Cell& cell = *it;
00891       int i = cell.row();
00892       int j = cell.col();
00893       int k = i - imin;
00894       jmins[k] = std::min<int>(jmins[k], j);
00895       jmaxs[k] = std::max<int>(jmaxs[k], j);
00896       ++it;
00897     }
00898   }
00899   // Replace any unset limits using the bounding rectangle.
00900   std::replace(jmins.begin(), jmins.end(),
00901          std::numeric_limits<int>::max(), jmin);
00902   std::replace(jmaxs.begin(), jmaxs.end(),
00903          std::numeric_limits<int>::min(), jmax);
00904   // Initialize the iterator at the first cell.
00905   curCell = &g.getCell(imin, jmins[0]);
00906       }
00907 
00911       ConvexPolygonCellIteratorBase() : curCell(NULL), grid(NULL) { }
00912 
00916       inline bool operator==(const ConvexPolygonCellIteratorBase<GridType,CellType>& other) const
00917       { return (curCell == other.curCell); }
00918       inline bool operator!=(const ConvexPolygonCellIteratorBase<GridType,CellType>& other) const 
00919       { return !(*this == other); }
00920 
00924       inline ConvexPolygonCellIteratorBase<GridType,CellType>& operator++(int) {
00925   ConvexPolygonCellIterator tmp(*this);
00926   ++(*this);
00927   return tmp;
00928       }
00929       inline ConvexPolygonCellIteratorBase<GridType,CellType>& operator++() {
00930   using namespace Arak::Geometry;
00931   assert(curCell != NULL);
00932   int i = curCell->row();
00933   int j = curCell->col();
00934   int k = i - imin;
00935   if ((i == imax) && (j == jmaxs[k])) {
00936     // We are at the last cell; the iterator is finished.
00937     curCell = NULL;
00938     return *this;
00939   } else if (j == jmaxs[k])
00940     // We are at the last column but not the last row; wrap
00941     // around.
00942     curCell = &(grid->getCell(i + 1, jmins[k + 1]));
00943   else 
00944     // We have not reached the end of the current row; move
00945     // right.
00946     curCell = curCell->right;
00947   return *this;
00948       }
00949 
00953       inline CellType* operator->() const { return curCell; }
00954       inline CellType& operator*() const { return *curCell; }
00955       
00956     }; // end of class: Grid::ConvexPolygonCellIteratorBase
00957 
00962     typedef ConvexPolygonCellIteratorBase<Grid, Cell> 
00963     ConvexPolygonCellIterator;
00964 
00969     typedef ConvexPolygonCellIteratorBase<const Grid, const Cell> 
00970     ConstConvexPolygonCellIterator;
00971 
00972   protected:
00973 
00977     const Geometry::Rectangle bd;
00978 
00982     std::vector< std::vector<Cell*> > cells;
00983 
00987     const int rows;
00988 
00992     const int cols;
00993 
00997     Geometry::Kernel::FT cellWidth;
00998     
01002     Geometry::Kernel::FT cellHeight;
01003 
01012     std::vector<Geometry::Kernel::FT> xvals;
01013 
01022     std::vector<Geometry::Kernel::FT> yvals;
01023 
01024   public:
01025     
01034     Grid(const Geometry::Rectangle& boundary, int rows, int cols)
01035       : bd(boundary), rows(rows), cols(cols) {
01036       using namespace Arak::Geometry;
01037       // Compute the cell size.
01038       Kernel::FT xmin = bd.xmin();
01039       Kernel::FT xmax = bd.xmax();
01040       Kernel::FT ymin = bd.ymin();
01041       Kernel::FT ymax = bd.ymax();
01042       this->cellWidth = (xmax - xmin) / Kernel::FT(cols);
01043       this->cellHeight = (ymax - ymin) / Kernel::FT(rows);
01044       // Compute the grid lines.
01045       xvals.reserve(cols + 1);
01046       Kernel::FT x = xmin;
01047       for (int i = 0; i < cols; i++) {
01048   xvals.push_back(x);
01049   x += cellWidth;
01050       }
01051       xvals.push_back(xmax);
01052       yvals.reserve(rows + 1);
01053       Kernel::FT y = ymin;
01054       for (int i = 0; i < rows; i++) {
01055   yvals.push_back(y);
01056   y += cellHeight;
01057       }
01058       yvals.push_back(ymax);
01059       // Create the cells.
01060       cells.reserve(rows);
01061       for (int i = 0; i < rows; i++) {
01062   cells.push_back(std::vector<Cell*>());
01063   cells[i].reserve(cols);
01064   for (int j = 0; j < cols; j++) {
01065     Geometry::Rectangle r(xvals[j], yvals[i], 
01066         xvals[j + 1], yvals[i + 1]);
01067     cells[i][j] = new Cell(r, i, j);
01068     if (i > 0) {
01069       cells[i][j]->down = cells[i - 1][j];
01070       cells[i - 1][j]->up = cells[i][j];
01071     }
01072     if (j > 0) {
01073       cells[i][j]->left = cells[i][j - 1];
01074       cells[i][j - 1]->right = cells[i][j];
01075     }
01076   }
01077       }
01078     }
01079   
01083     ~Grid() {
01084       
01085     }
01086 
01092     inline int numRows() const { return rows; }
01093 
01099     inline int numCols() const { return cols; }
01100 
01108     const Geometry::Rectangle& boundary() const { return bd; }
01109 
01119     bool getCellCoords(const Geometry::Point& p, int& i, int& j) const {
01120       if (bd.has_on_unbounded_side(p)) return false;
01121       // First we use a simple computation to estimate the correct
01122       // cell.  This may be only approximate, though, due to floating
01123       // point error.  Then we shift the indexes as needed to compute
01124       // the exact cell.
01125       if (p.y() == bd.ymax()) 
01126   i = rows - 1;
01127       else {
01128   i = int(floor(CGAL::to_double((p.y() - bd.ymin()) / cellHeight)));
01129   while (p.y() < yvals[i]) i--;
01130   while (p.y() >= yvals[i + 1]) i++;
01131       }
01132       if (p.x() == bd.xmax()) 
01133   j = cols - 1;
01134       else {
01135   j = int(floor(CGAL::to_double((p.x() - bd.xmin()) / cellWidth)));
01136   while (p.x() < xvals[j]) j--;
01137   while (p.x() >= xvals[j + 1]) j++;
01138       }
01139       return true;
01140     }
01141     
01149     inline const Cell& getCell(const int i, const int j) const {
01150       return *(cells[i][j]);
01151     }
01152 
01160     inline Cell& getCell(const int i, const int j) {
01161       return *(cells[i][j]);
01162     }
01163 
01168     const Cell& getCell(const Geometry::Point& p) const {
01169       int i = -1, j = -1;
01170       assert(getCellCoords(p, i, j));
01171       return getCell(i, j);
01172     }
01173 
01178     Cell& getCell(const Geometry::Point& p) {
01179       int i = -1, j = -1;
01180       assert(getCellCoords(p, i, j));
01181       return *(cells[i][j]);
01182     }
01183 
01184   };  // end of class: Grid
01185 
01186 }
01187 
01188 #endif

Generated on Wed May 25 14:39:16 2005 for Arak by doxygen 1.3.6