00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef GRID_3D_HH
00025 #define GRID_3D_HH
00026
00032 #include <iostream>
00033 #include <cassert>
00034 #include <climits>
00035
00036 #include "bounding-box.hh"
00037 #include "tools-win32.hh"
00038
00039 template <class T> class CGrid3dIterator;
00040
00041 template <class T>
00042 class CGrid3d
00043 {
00044 public:
00045
00050
00062 CGrid3d(int ASizeI, int ASizeJ, int ASizeK,
00063 const CBoundingBox & ABB = CBoundingBox());
00064
00069 virtual ~CGrid3d();
00070
00072
00077
00078 int getSizeI() const;
00079 int getSizeJ() const;
00080 int getSizeK() const;
00081
00082 const CBoundingBox & getBoundingBox() const;
00083
00084 T & getCell(int Ai, int Aj, int Ak) const;
00085 T & getCell(const CGrid3dIterator<T> & AIter) const;
00086
00087 CBoundingBox getCellBoundingBox(int Ai, int Aj, int Ak) const;
00088 CBoundingBox getCellBoundingBox(const CGrid3dIterator<T> & AIter) const;
00089
00090 bool getCellPosition(const CVertex & APoint,
00091 int * Ai, int * Aj, int * Ak) const;
00092
00093 bool getCellPosition(const CVertex & APoint,
00094 TCoordinate * Ai,
00095 TCoordinate * Aj,
00096 TCoordinate * Ak) const;
00097
00098 void setBoundingBox(const CBoundingBox & ABB);
00099
00100 void setCell(int Ai, int Aj, int Ak, const T & AObj);
00101 void setCell(const CGrid3dIterator<T> & AIter, const T & AObj);
00102
00103 void fillCellsWith(const CBoundingBox & ABB, const T & AObj);
00104
00106
00107 private:
00108
00113
00114 TCoordinate getCellI(TCoordinate Ax) const;
00115 TCoordinate getCellJ(TCoordinate Ay) const;
00116 TCoordinate getCellK(TCoordinate Az) const;
00117
00119
00120 private:
00121
00126
00130 T ***FGrid;
00131
00135 int FSizeI, FSizeJ, FSizeK;
00136
00140 CBoundingBox FBB;
00141
00143 };
00144
00145 template <class T>
00146 class CGrid3dIterator
00147 {
00148 public:
00149 CGrid3dIterator(const CGrid3d<T> & AGrid);
00150 CGrid3dIterator(const CGrid3d<T> & AGrid, const CBoundingBox & ABB);
00151 CGrid3dIterator(const CGrid3dIterator<T> & AI);
00152 virtual ~CGrid3dIterator();
00153
00154 virtual void reinit();
00155 virtual bool cont() const;
00156 virtual void next();
00157
00158 int getI() const { return Fi; }
00159 int getJ() const { return Fj; }
00160 int getK() const { return Fk; }
00161
00162 T & getCurrent() const { return FGrid.getCell(*this); }
00163 T & operator*() const { return getCurrent(); }
00164 T * operator->() const { return &(getCurrent()); }
00165
00166 CGrid3dIterator<T> & operator++()
00167 {
00168 next();
00169 return *this;
00170 }
00171
00172 CGrid3dIterator<T> operator++(int)
00173 {
00174 CGrid3dIterator<T> tmp = *this;
00175 next();
00176 return tmp;
00177 }
00178
00179 friend std::ostream & operator<<(std::ostream & AO,
00180 const CGrid3dIterator<T> & AI)
00181 {
00182 return (AO << "(" << AI.Fi << "," << AI.Fj << "," << AI.Fk << ")");
00183 }
00184
00185 protected:
00186 const CGrid3d<T> & FGrid;
00187 int Fi, Fj, Fk;
00188 int FMinI, FMinJ, FMinK, FMaxI, FMaxJ, FMaxK;
00189 };
00190
00191
00192
00193
00194
00195 template <class T>
00196 CGrid3d<T>::CGrid3d(int ASizeI, int ASizeJ, int ASizeK,
00197 const CBoundingBox & ABB)
00198 : FSizeI(ASizeI), FSizeJ(ASizeJ), FSizeK(ASizeK), FBB(ABB)
00199 {
00200 assert(ASizeI > 0);
00201 assert(ASizeJ > 0);
00202 assert(ASizeK > 0);
00203 assert(!ABB.isEmpty());
00204
00205 FGrid = new T**[ASizeI];
00206 for (int i=0 ; i<FSizeI ; i++) {
00207 FGrid[i] = new T*[ASizeJ];
00208 for (int j=0 ; j<FSizeJ ; j++)
00209 FGrid[i][j] = new T[ASizeK];
00210 }
00211 }
00212
00213 template <class T>
00214 CGrid3d<T>::~CGrid3d()
00215 {
00216 for (int i=0 ; i<FSizeI ; i++) {
00217 for (int j=0 ; j<FSizeJ ; j++)
00218 delete [] FGrid[i][j];
00219 delete [] FGrid[i];
00220 }
00221 delete [] FGrid;
00222 }
00223
00224 template <class T> inline
00225 int CGrid3d<T>::getSizeI() const
00226 {
00227 return FSizeI;
00228 }
00229
00230 template <class T> inline
00231 int CGrid3d<T>::getSizeJ() const
00232 {
00233 return FSizeJ;
00234 }
00235
00236 template <class T> inline
00237 int CGrid3d<T>::getSizeK() const
00238 {
00239 return FSizeK;
00240 }
00241
00242 template <class T> inline
00243 const CBoundingBox & CGrid3d<T>::getBoundingBox() const
00244 {
00245 return FBB;
00246 }
00247
00248 template <class T> inline
00249 T & CGrid3d<T>::getCell(int Ai, int Aj, int Ak) const
00250 {
00251
00252
00253
00254
00255
00256
00257 assert(Ai >= 0 && Ai < FSizeI);
00258 assert(Aj >= 0 && Aj < FSizeJ);
00259 assert(Ak >= 0 && Ak < FSizeK);
00260
00261 return FGrid[Ai][Aj][Ak];
00262 }
00263
00264 template <class T> inline
00265 T & CGrid3d<T>::getCell(const CGrid3dIterator<T> & AIter) const
00266 {
00267 return getCell(AIter.getI(), AIter.getJ(), AIter.getK());
00268 }
00269
00270 template <class T>
00271 CBoundingBox
00272 CGrid3d<T>::getCellBoundingBox(int Ai, int Aj, int Ak) const
00273 {
00274 assert(Ai >= 0 && Ai < FSizeI);
00275 assert(Aj >= 0 && Aj < FSizeJ);
00276 assert(Ak >= 0 && Ak < FSizeK);
00277
00278 CVertex diff = FBB.getMaxBound() - FBB.getMinBound();
00279
00280 diff.setX(diff.getX() / (TCoordinate)FSizeI);
00281 diff.setY(diff.getY() / (TCoordinate)FSizeJ);
00282 diff.setZ(diff.getZ() / (TCoordinate)FSizeK);
00283
00284 CVertex min = (FBB.getMinBound() +
00285 CVertex(diff.getX() * (TCoordinate)Ai,
00286 diff.getY() * (TCoordinate)Aj,
00287 diff.getZ() * (TCoordinate)Ak));
00288
00289 return CBoundingBox(min, min + diff);
00290 }
00291
00292 template <class T>
00293 CBoundingBox
00294 CGrid3d<T>::getCellBoundingBox(const CGrid3dIterator<T> & AIter) const
00295 {
00296 return getCellBoundingBox(AIter.getI(), AIter.getJ(), AIter.getK());
00297 }
00298
00299 template <class T>
00300 bool CGrid3d<T>::getCellPosition(const CVertex & APoint,
00301 int * Ai, int * Aj, int * Ak) const
00302 {
00303 TCoordinate i, j, k;
00304
00305 i = getCellI(APoint.getX());
00306 j = getCellJ(APoint.getY());
00307 k = getCellK(APoint.getZ());
00308
00309 *Ai = ((i >= (TCoordinate)INT_MAX) ? INT_MAX :
00310 (i <= (TCoordinate)INT_MIN) ? INT_MIN :
00311 (int)i);
00312 *Aj = ((j >= (TCoordinate)INT_MAX) ? INT_MAX :
00313 (j <= (TCoordinate)INT_MIN) ? INT_MIN :
00314 (int)j);
00315 *Ak = ((k >= (TCoordinate)INT_MAX) ? INT_MAX :
00316 (k <= (TCoordinate)INT_MIN) ? INT_MIN :
00317 (int)k);
00318
00319 return (*Ai >= 0 && *Ai < FSizeI &&
00320 *Aj >= 0 && *Aj < FSizeJ &&
00321 *Ak >= 0 && *Ak < FSizeK);
00322 }
00323
00324 template <class T>
00325 bool CGrid3d<T>::getCellPosition(const CVertex & APoint,
00326 TCoordinate * Ai,
00327 TCoordinate * Aj,
00328 TCoordinate * Ak) const
00329 {
00330 *Ai = getCellI(APoint.getX());
00331 *Aj = getCellJ(APoint.getY());
00332 *Ak = getCellK(APoint.getZ());
00333
00334 return (*Ai >= 0.0 && *Ai < (TCoordinate)FSizeI &&
00335 *Aj >= 0.0 && *Aj < (TCoordinate)FSizeJ &&
00336 *Ak >= 0.0 && *Ak < (TCoordinate)FSizeK);
00337 }
00338
00339 template <class T> inline
00340 void CGrid3d<T>::setBoundingBox(const CBoundingBox & ABB)
00341 {
00342 FBB = ABB;
00343 }
00344
00345 template <class T> inline
00346 void CGrid3d<T>::setCell(int Ai, int Aj, int Ak, const T & AObj)
00347 {
00348 assert(Ai >= 0 && Ai < FSizeI);
00349 assert(Aj >= 0 && Aj < FSizeJ);
00350 assert(Ak >= 0 && Ak < FSizeK);
00351
00352 FGrid[Ai][Aj][Ak] = AObj;
00353 }
00354
00355 template <class T> inline
00356 void CGrid3d<T>::setCell(const CGrid3dIterator<T> & AIter, const T & AObj)
00357 {
00358 setCell(AIter.getI(), AIter.getJ(), AIter.getK(), AObj);
00359 }
00360
00361 template <class T>
00362 void CGrid3d<T>::fillCellsWith(const CBoundingBox & ABB, const T & AObj)
00363 {
00364 assert(FBB.isInBox(ABB.getMinBound()) && FBB.isInBox(ABB.getMaxBound()));
00365
00366 int min_i, min_j, min_k, max_i, max_j, max_k;
00367
00368 getCellPosition(ABB.getEpsMinBound(), &min_i, &min_j, &min_k);
00369 getCellPosition(ABB.getEpsMaxBound(), &max_i, &max_j, &max_k);
00370
00371 if (min_i < 0) min_i = 0;
00372 if (min_j < 0) min_j = 0;
00373 if (min_k < 0) min_k = 0;
00374
00375 if (max_i >= FSizeI) max_i = FSizeI - 1;
00376 if (max_j >= FSizeJ) max_j = FSizeJ - 1;
00377 if (max_k >= FSizeK) max_k = FSizeK - 1;
00378
00379 for (int i=min_i ; i<=max_i ; i++)
00380 for (int j=min_j ; j<=max_j ; j++)
00381 for (int k=min_k ; k<=max_k ; k++)
00382 FGrid[i][j][k] = AObj;
00383 }
00384
00385 template <class T>
00386 TCoordinate CGrid3d<T>::getCellI(TCoordinate Ax) const
00387 {
00388 TCoordinate size = FBB.getMaxBound().getX() - FBB.getMinBound().getX();
00389
00390 if (size == 0.0)
00391 return 0.0;
00392 else
00393 return (((Ax - FBB.getMinBound().getX()) * FSizeI) / size);
00394 }
00395
00396 template <class T>
00397 TCoordinate CGrid3d<T>::getCellJ(TCoordinate Ay) const
00398 {
00399 TCoordinate size = FBB.getMaxBound().getY() - FBB.getMinBound().getY();
00400
00401 if (size == 0.0)
00402 return 0.0;
00403 else
00404 return (((Ay - FBB.getMinBound().getY()) * FSizeJ) / size);
00405 }
00406
00407 template <class T>
00408 TCoordinate CGrid3d<T>::getCellK(TCoordinate Az) const
00409 {
00410 TCoordinate size = FBB.getMaxBound().getZ() - FBB.getMinBound().getZ();
00411
00412 if (size == 0.0)
00413 return 0.0;
00414 else
00415 return (((Az - FBB.getMinBound().getZ()) * FSizeK) / size);
00416 }
00417
00418
00419
00420 template <class T> inline
00421 CGrid3dIterator<T>::CGrid3dIterator(const CGrid3d<T> & AGrid)
00422 : FGrid(AGrid),
00423 FMinI(0), FMinJ(0), FMinK(0),
00424 FMaxI(AGrid.getSizeI() - 1),
00425 FMaxJ(FGrid.getSizeJ() - 1),
00426 FMaxK(FGrid.getSizeK() - 1)
00427 {
00428 reinit();
00429 }
00430
00431 template <class T> inline
00432 CGrid3dIterator<T>::CGrid3dIterator(const CGrid3d<T> & AGrid,
00433 const CBoundingBox & ABB)
00434 : FGrid(AGrid)
00435 {
00436 FGrid.getCellPosition(ABB.getEpsMinBound(), &FMinI, &FMinJ, &FMinK);
00437 FGrid.getCellPosition(ABB.getEpsMaxBound(), &FMaxI, &FMaxJ, &FMaxK);
00438
00439 if (FMinI < 0) FMinI = 0;
00440 if (FMinJ < 0) FMinJ = 0;
00441 if (FMinK < 0) FMinK = 0;
00442
00443 if (FMaxI >= FGrid.getSizeI()) FMaxI = FGrid.getSizeI() - 1;
00444 if (FMaxJ >= FGrid.getSizeJ()) FMaxJ = FGrid.getSizeJ() - 1;
00445 if (FMaxK >= FGrid.getSizeK()) FMaxK = FGrid.getSizeK() - 1;
00446
00447 reinit();
00448 }
00449
00450 template <class T> inline
00451 CGrid3dIterator<T>::CGrid3dIterator(const CGrid3dIterator<T> & AI)
00452 : FGrid(AI.FGrid), Fi(AI.Fi), Fj(AI.Fj), Fk(AI.Fk),
00453 FMinI(AI.FMinI), FMinJ(AI.FMinJ), FMinK(AI.FMinK),
00454 FMaxI(AI.FMaxI), FMaxJ(AI.FMaxJ), FMaxK(AI.FMaxK)
00455 {
00456 }
00457
00458 template <class T> inline
00459 CGrid3dIterator<T>::~CGrid3dIterator()
00460 {
00461 }
00462
00463 template <class T> inline
00464 void CGrid3dIterator<T>::reinit()
00465 {
00466 Fi = FMinI;
00467 Fj = FMinJ;
00468 Fk = FMinK;
00469 }
00470
00471 template <class T> inline
00472 bool CGrid3dIterator<T>::cont() const
00473 {
00474 return (Fi <= FMaxI && Fj <= FMaxJ && Fk <= FMaxK);
00475 }
00476
00477 template <class T> inline
00478 void CGrid3dIterator<T>::next()
00479 {
00480 assert(cont());
00481
00482 if (Fi < FMaxI)
00483 Fi++;
00484 else {
00485 Fi = FMinI;
00486
00487 if (Fj < FMaxJ)
00488 Fj++;
00489 else {
00490 Fj = FMinJ;
00491
00492 if (Fk < FMaxK)
00493 Fk++;
00494 else {
00495 Fi = FMaxI + 1;
00496 Fj = FMaxJ + 1;
00497 Fk = FMaxK + 1;
00498 }
00499 }
00500 }
00501 }
00502
00503 #endif
00504