00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "PreCompiled.h"
00025
00026 #ifndef _PreComp_
00027 # include <algorithm>
00028 #endif
00029
00030 #include "Grid.h"
00031 #include "Iterator.h"
00032
00033 #include "MeshKernel.h"
00034 #include "Algorithm.h"
00035 #include "Tools.h"
00036
00037 using namespace MeshCore;
00038
00039 MeshGrid::MeshGrid (const MeshKernel &rclM)
00040 : _pclMesh(&rclM),
00041 _ulCtElements(0),
00042 _ulCtGridsX(0), _ulCtGridsY(0), _ulCtGridsZ(0),
00043 _fGridLenX(0.0f), _fGridLenY(0.0f), _fGridLenZ(0.0f),
00044 _fMinX(0.0f), _fMinY(0.0f), _fMinZ(0.0f)
00045 {
00046 }
00047
00048 MeshGrid::MeshGrid (void)
00049 : _pclMesh(NULL),
00050 _ulCtElements(0),
00051 _ulCtGridsX(MESH_CT_GRID), _ulCtGridsY(MESH_CT_GRID), _ulCtGridsZ(MESH_CT_GRID),
00052 _fGridLenX(0.0f), _fGridLenY(0.0f), _fGridLenZ(0.0f),
00053 _fMinX(0.0f), _fMinY(0.0f), _fMinZ(0.0f)
00054 {
00055 }
00056
00057 void MeshGrid::Attach (const MeshKernel &rclM)
00058 {
00059 _pclMesh = &rclM;
00060 RebuildGrid();
00061 }
00062
00063 void MeshGrid::Clear (void)
00064 {
00065 _aulGrid.clear();
00066 _pclMesh = NULL;
00067 }
00068
00069 void MeshGrid::Rebuild (unsigned long ulX, unsigned long ulY, unsigned long ulZ)
00070 {
00071 _ulCtGridsX = ulX;
00072 _ulCtGridsY = ulY;
00073 _ulCtGridsZ = ulZ;
00074 _ulCtElements = HasElements();
00075 RebuildGrid();
00076 }
00077
00078 void MeshGrid::Rebuild (unsigned long ulPerGrid, unsigned long ulMaxGrid)
00079 {
00080 _ulCtElements = HasElements();
00081 CalculateGridLength(ulPerGrid, ulMaxGrid);
00082 RebuildGrid();
00083 }
00084
00085 void MeshGrid::Rebuild (int iCtGridPerAxis)
00086 {
00087 _ulCtElements = HasElements();
00088 CalculateGridLength(iCtGridPerAxis);
00089 RebuildGrid();
00090 }
00091
00092 void MeshGrid::InitGrid (void)
00093 {
00094 assert(_pclMesh != NULL);
00095
00096 unsigned long i, j;
00097
00098
00099
00100 if ((_ulCtGridsX == 0) || (_ulCtGridsX == 0) || (_ulCtGridsX == 0))
00101 CalculateGridLength(MESH_CT_GRID, MESH_MAX_GRIDS);
00102
00103
00104
00105 {
00106 Base::BoundBox3f clBBMesh = _pclMesh->GetBoundBox();
00107
00108 float fLengthX = clBBMesh.LengthX();
00109 float fLengthY = clBBMesh.LengthY();
00110 float fLengthZ = clBBMesh.LengthZ();
00111
00112 {
00113
00114
00115 _fGridLenX = (1.0f + fLengthX) / float(_ulCtGridsX);
00116 _fMinX = clBBMesh.MinX - 0.5f;
00117 }
00118
00119 {
00120 _fGridLenY = (1.0f + fLengthY) / float(_ulCtGridsY);
00121 _fMinY = clBBMesh.MinY - 0.5f;
00122 }
00123
00124 {
00125 _fGridLenZ = (1.0f + fLengthZ) / float(_ulCtGridsZ);
00126 _fMinZ = clBBMesh.MinZ - 0.5f;
00127 }
00128 }
00129
00130
00131 _aulGrid.clear();
00132 _aulGrid.resize(_ulCtGridsX);
00133 for (i = 0; i < _ulCtGridsX; i++)
00134 {
00135 _aulGrid[i].resize(_ulCtGridsY);
00136 for (j = 0; j < _ulCtGridsY; j++)
00137 _aulGrid[i][j].resize(_ulCtGridsZ);
00138 }
00139 }
00140
00141 unsigned long MeshGrid::Inside (const Base::BoundBox3f &rclBB, std::vector<unsigned long> &raulElements,
00142 bool bDelDoubles) const
00143 {
00144 unsigned long i, j, k, ulMinX, ulMinY, ulMinZ, ulMaxX, ulMaxY, ulMaxZ;
00145
00146 raulElements.clear();
00147
00148
00149 Position(Base::Vector3f(rclBB.MinX, rclBB.MinY, rclBB.MinZ), ulMinX, ulMinY, ulMinZ);
00150 Position(Base::Vector3f(rclBB.MaxX, rclBB.MaxY, rclBB.MaxZ), ulMaxX, ulMaxY, ulMaxZ);
00151
00152 for (i = ulMinX; i <= ulMaxX; i++)
00153 {
00154 for (j = ulMinY; j <= ulMaxY; j++)
00155 {
00156 for (k = ulMinZ; k <= ulMaxZ; k++)
00157 {
00158 raulElements.insert(raulElements.end(), _aulGrid[i][j][k].begin(), _aulGrid[i][j][k].end());
00159 }
00160 }
00161 }
00162
00163 if (bDelDoubles == true)
00164 {
00165
00166 std::sort(raulElements.begin(), raulElements.end());
00167 raulElements.erase(std::unique(raulElements.begin(), raulElements.end()), raulElements.end());
00168 }
00169
00170 return raulElements.size();
00171 }
00172
00173 unsigned long MeshGrid::Inside (const Base::BoundBox3f &rclBB, std::vector<unsigned long> &raulElements,
00174 const Base::Vector3f &rclOrg, float fMaxDist, bool bDelDoubles) const
00175 {
00176 unsigned long i, j, k, ulMinX, ulMinY, ulMinZ, ulMaxX, ulMaxY, ulMaxZ;
00177 float fGridDiag = GetBoundBox(0, 0, 0).CalcDiagonalLength();
00178 float fMinDistP2 = (fGridDiag * fGridDiag) + (fMaxDist * fMaxDist);
00179
00180 raulElements.clear();
00181
00182
00183 Position(Base::Vector3f(rclBB.MinX, rclBB.MinY, rclBB.MinZ), ulMinX, ulMinY, ulMinZ);
00184 Position(Base::Vector3f(rclBB.MaxX, rclBB.MaxY, rclBB.MaxZ), ulMaxX, ulMaxY, ulMaxZ);
00185
00186 for (i = ulMinX; i <= ulMaxX; i++)
00187 {
00188 for (j = ulMinY; j <= ulMaxY; j++)
00189 {
00190 for (k = ulMinZ; k <= ulMaxZ; k++)
00191 {
00192 if (Base::DistanceP2(GetBoundBox(i, j, k).CalcCenter(), rclOrg) < fMinDistP2)
00193 raulElements.insert(raulElements.end(), _aulGrid[i][j][k].begin(), _aulGrid[i][j][k].end());
00194 }
00195 }
00196 }
00197
00198 if (bDelDoubles == true)
00199 {
00200
00201 std::sort(raulElements.begin(), raulElements.end());
00202 raulElements.erase(std::unique(raulElements.begin(), raulElements.end()), raulElements.end());
00203 }
00204
00205 return raulElements.size();
00206 }
00207
00208 unsigned long MeshGrid::Inside (const Base::BoundBox3f &rclBB, std::set<unsigned long> &raulElements) const
00209 {
00210 unsigned long i, j, k, ulMinX, ulMinY, ulMinZ, ulMaxX, ulMaxY, ulMaxZ;
00211
00212 raulElements.clear();
00213
00214
00215 Position(Base::Vector3f(rclBB.MinX, rclBB.MinY, rclBB.MinZ), ulMinX, ulMinY, ulMinZ);
00216 Position(Base::Vector3f(rclBB.MaxX, rclBB.MaxY, rclBB.MaxZ), ulMaxX, ulMaxY, ulMaxZ);
00217
00218 for (i = ulMinX; i <= ulMaxX; i++)
00219 {
00220 for (j = ulMinY; j <= ulMaxY; j++)
00221 {
00222 for (k = ulMinZ; k <= ulMaxZ; k++)
00223 {
00224 raulElements.insert(_aulGrid[i][j][k].begin(), _aulGrid[i][j][k].end());
00225 }
00226 }
00227 }
00228
00229 return raulElements.size();
00230 }
00231
00232 bool MeshGrid::CheckPosition (const Base::Vector3f &rclPoint, unsigned long &rulX, unsigned long &rulY, unsigned long &rulZ) const
00233 {
00234 rulX = (unsigned long)((rclPoint.x - _fMinX) / _fGridLenX);
00235 rulY = (unsigned long)((rclPoint.y - _fMinY) / _fGridLenY);
00236 rulZ = (unsigned long)((rclPoint.z - _fMinZ) / _fGridLenZ);
00237
00238 if ( (rulX < _ulCtGridsX) && (rulY < _ulCtGridsY) && (rulZ < _ulCtGridsZ) )
00239 return true;
00240
00241 return false;
00242 }
00243
00244 void MeshGrid::Position (const Base::Vector3f &rclPoint, unsigned long &rulX, unsigned long &rulY, unsigned long &rulZ) const
00245 {
00246 if (rclPoint.x <= _fMinX)
00247 rulX = 0;
00248 else
00249 rulX = std::min<unsigned long>((unsigned long)((rclPoint.x - _fMinX) / _fGridLenX), _ulCtGridsX - 1);
00250
00251 if (rclPoint.y <= _fMinY)
00252 rulY = 0;
00253 else
00254 rulY = std::min<unsigned long>((unsigned long)((rclPoint.y - _fMinY) / _fGridLenY), _ulCtGridsY - 1);
00255
00256 if (rclPoint.z <= _fMinZ)
00257 rulZ = 0;
00258 else
00259 rulZ = std::min<unsigned long>((unsigned long)((rclPoint.z - _fMinZ) / _fGridLenZ), _ulCtGridsZ - 1);
00260 }
00261
00262 void MeshGrid::CalculateGridLength (unsigned long ulCtGrid, unsigned long ulMaxGrids)
00263 {
00264
00265
00266
00267 Base::BoundBox3f clBBMeshEnlarged = _pclMesh->GetBoundBox();
00268 float fVolElem;
00269
00270 if (_ulCtElements > (ulMaxGrids * ulCtGrid))
00271 fVolElem = (clBBMeshEnlarged.LengthX() * clBBMeshEnlarged.LengthY() * clBBMeshEnlarged.LengthZ()) / float(ulMaxGrids * ulCtGrid);
00272 else
00273 fVolElem = (clBBMeshEnlarged.LengthX() * clBBMeshEnlarged.LengthY() * clBBMeshEnlarged.LengthZ()) / float(_ulCtElements);
00274
00275 float fVol = fVolElem * float(ulCtGrid);
00276 float fGridLen = float(pow((float)fVol,(float) 1.0f / 3.0f));
00277
00278 _ulCtGridsX = std::max<unsigned long>((unsigned long)(clBBMeshEnlarged.LengthX() / fGridLen), 1);
00279 _ulCtGridsY = std::max<unsigned long>((unsigned long)(clBBMeshEnlarged.LengthY() / fGridLen), 1);
00280 _ulCtGridsZ = std::max<unsigned long>((unsigned long)(clBBMeshEnlarged.LengthZ() / fGridLen), 1);
00281 }
00282
00283 void MeshGrid::CalculateGridLength (int iCtGridPerAxis)
00284 {
00285 if (iCtGridPerAxis<=0)
00286 {
00287 CalculateGridLength(MESH_CT_GRID, MESH_MAX_GRIDS);
00288 return;
00289 }
00290
00291
00292
00293
00294 Base::BoundBox3f clBBMesh = _pclMesh->GetBoundBox();
00295
00296 float fLenghtX = clBBMesh.LengthX();
00297 float fLenghtY = clBBMesh.LengthY();
00298 float fLenghtZ = clBBMesh.LengthZ();
00299
00300 float fLenghtD = clBBMesh.CalcDiagonalLength();
00301
00302 float fLengthTol = 0.05f * fLenghtD;
00303
00304 bool bLenghtXisZero = (fLenghtX <= fLengthTol);
00305 bool bLenghtYisZero = (fLenghtY <= fLengthTol);
00306 bool bLenghtZisZero = (fLenghtZ <= fLengthTol);
00307
00308 int iFlag = 0;
00309
00310 int iMaxGrids = 1;
00311
00312 if (bLenghtXisZero)
00313 iFlag += 1;
00314 else
00315 iMaxGrids *= iCtGridPerAxis;
00316
00317 if (bLenghtYisZero)
00318 iFlag += 2;
00319 else
00320 iMaxGrids *= iCtGridPerAxis;
00321
00322 if (bLenghtZisZero)
00323 iFlag += 4;
00324 else
00325 iMaxGrids *= iCtGridPerAxis;
00326
00327 unsigned long ulGridsFacets = 10;
00328
00329 float fFactorVolumen = 40.0;
00330 float fFactorArea = 10.0;
00331
00332 switch (iFlag)
00333 {
00334 case 0:
00335 {
00336 float fVolumen = fLenghtX * fLenghtY * fLenghtZ;
00337
00338 float fVolumenGrid = (fVolumen * ulGridsFacets) / (fFactorVolumen * _ulCtElements);
00339
00340 if ((fVolumenGrid * iMaxGrids) < fVolumen)
00341 fVolumenGrid = fVolumen / (float)iMaxGrids;
00342
00343 float fLengthGrid = float(pow((float)fVolumenGrid,(float) 1.0f / 3.0f));
00344
00345 _ulCtGridsX = std::max<unsigned long>((unsigned long)(fLenghtX / fLengthGrid), 1);
00346 _ulCtGridsY = std::max<unsigned long>((unsigned long)(fLenghtY / fLengthGrid), 1);
00347 _ulCtGridsZ = std::max<unsigned long>((unsigned long)(fLenghtZ / fLengthGrid), 1);
00348
00349 } break;
00350 case 1:
00351 {
00352 _ulCtGridsX = 1;
00353
00354 float fArea = fLenghtY * fLenghtZ;
00355
00356 float fAreaGrid = (fArea * ulGridsFacets) / (fFactorArea * _ulCtElements);
00357
00358 if ((fAreaGrid * iMaxGrids) < fArea)
00359 fAreaGrid = fArea / (float)iMaxGrids;
00360
00361 float fLengthGrid = float(sqrt(fAreaGrid));
00362
00363 _ulCtGridsY = std::max<unsigned long>((unsigned long)(fLenghtY / fLengthGrid), 1);
00364 _ulCtGridsZ = std::max<unsigned long>((unsigned long)(fLenghtZ / fLengthGrid), 1);
00365 } break;
00366 case 2:
00367 {
00368 _ulCtGridsY = 1;
00369
00370 float fArea = fLenghtX * fLenghtZ;
00371
00372 float fAreaGrid = (fArea * ulGridsFacets) / (fFactorArea * _ulCtElements);
00373
00374 if ((fAreaGrid * iMaxGrids) < fArea)
00375 fAreaGrid = fArea / (float)iMaxGrids;
00376
00377 float fLengthGrid = float(sqrt(fAreaGrid));
00378
00379 _ulCtGridsX = std::max<unsigned long>((unsigned long)(fLenghtX / fLengthGrid), 1);
00380 _ulCtGridsZ = std::max<unsigned long>((unsigned long)(fLenghtZ / fLengthGrid), 1);
00381 } break;
00382 case 3:
00383 {
00384 _ulCtGridsX = 1;
00385 _ulCtGridsY = 1;
00386 _ulCtGridsZ = iMaxGrids;
00387 } break;
00388 case 4:
00389 {
00390 _ulCtGridsZ = 1;
00391
00392 float fArea = fLenghtX * fLenghtY;
00393
00394 float fAreaGrid = (fArea * ulGridsFacets) / (fFactorArea * _ulCtElements);
00395
00396 if ((fAreaGrid * iMaxGrids) < fArea)
00397 fAreaGrid = fArea / (float)iMaxGrids;
00398
00399 float fLengthGrid = float(sqrt(fAreaGrid));
00400
00401 _ulCtGridsX = std::max<unsigned long>((unsigned long)(fLenghtX / fLengthGrid), 1);
00402 _ulCtGridsY = std::max<unsigned long>((unsigned long)(fLenghtY / fLengthGrid), 1);
00403 } break;
00404 case 5:
00405 {
00406 _ulCtGridsX = 1;
00407 _ulCtGridsZ = 1;
00408 _ulCtGridsY = iMaxGrids;
00409 } break;
00410 case 6:
00411 {
00412 _ulCtGridsY = 1;
00413 _ulCtGridsZ = 1;
00414 _ulCtGridsX = iMaxGrids;
00415 } break;
00416 case 7:
00417 {
00418 _ulCtGridsX = iMaxGrids;
00419 _ulCtGridsY = iMaxGrids;
00420 _ulCtGridsZ = iMaxGrids;
00421 } break;
00422 }
00423 }
00424
00425 void MeshGrid::SearchNearestFromPoint (const Base::Vector3f &rclPt, std::set<unsigned long> &raclInd) const
00426 {
00427 raclInd.clear();
00428 Base::BoundBox3f clBB = GetBoundBox();
00429
00430 if (clBB.IsInBox(rclPt) == true)
00431 {
00432 unsigned long ulX, ulY, ulZ;
00433 Position(rclPt, ulX, ulY, ulZ);
00434
00435 unsigned long ulLevel = 0;
00436 while (raclInd.size() == 0)
00437 GetHull(ulX, ulY, ulZ, ulLevel++, raclInd);
00438 GetHull(ulX, ulY, ulZ, ulLevel, raclInd);
00439 }
00440 else
00441 {
00442 Base::BoundBox3f::SIDE tSide = clBB.GetSideFromRay(rclPt, clBB.CalcCenter() - rclPt);
00443 switch (tSide)
00444 {
00445 case Base::BoundBox3f::RIGHT:
00446 {
00447 int nX = 0;
00448 while (raclInd.size() == 0)
00449 {
00450 for (unsigned long i = 0; i < _ulCtGridsY; i++)
00451 {
00452 for (unsigned long j = 0; j < _ulCtGridsZ; j++)
00453 raclInd.insert(_aulGrid[nX][i][j].begin(), _aulGrid[nX][i][j].end());
00454 }
00455 nX++;
00456 }
00457 break;
00458 }
00459 case Base::BoundBox3f::LEFT:
00460 {
00461 int nX = _ulCtGridsX - 1;
00462 while (raclInd.size() == 0)
00463 {
00464 for (unsigned long i = 0; i < _ulCtGridsY; i++)
00465 {
00466 for (unsigned long j = 0; j < _ulCtGridsZ; j++)
00467 raclInd.insert(_aulGrid[nX][i][j].begin(), _aulGrid[nX][i][j].end());
00468 }
00469 nX++;
00470 }
00471 break;
00472 }
00473 case Base::BoundBox3f::TOP:
00474 {
00475 int nY = 0;
00476 while (raclInd.size() == 0)
00477 {
00478 for (unsigned long i = 0; i < _ulCtGridsX; i++)
00479 {
00480 for (unsigned long j = 0; j < _ulCtGridsZ; j++)
00481 raclInd.insert(_aulGrid[i][nY][j].begin(), _aulGrid[i][nY][j].end());
00482 }
00483 nY++;
00484 }
00485 break;
00486 }
00487 case Base::BoundBox3f::BOTTOM:
00488 {
00489 int nY = _ulCtGridsY - 1;
00490 while (raclInd.size() == 0)
00491 {
00492 for (unsigned long i = 0; i < _ulCtGridsX; i++)
00493 {
00494 for (unsigned long j = 0; j < _ulCtGridsZ; j++)
00495 raclInd.insert(_aulGrid[i][nY][j].begin(), _aulGrid[i][nY][j].end());
00496 }
00497 nY--;
00498 }
00499 break;
00500 }
00501 case Base::BoundBox3f::BACK:
00502 {
00503 int nZ = 0;
00504 while (raclInd.size() == 0)
00505 {
00506 for (unsigned long i = 0; i < _ulCtGridsX; i++)
00507 {
00508 for (unsigned long j = 0; j < _ulCtGridsY; j++)
00509 raclInd.insert(_aulGrid[i][j][nZ].begin(), _aulGrid[i][j][nZ].end());
00510 }
00511 nZ++;
00512 }
00513 break;
00514 }
00515 case Base::BoundBox3f::FRONT:
00516 {
00517 int nZ = _ulCtGridsZ - 1;
00518 while (raclInd.size() == 0)
00519 {
00520 for (unsigned long i = 0; i < _ulCtGridsX; i++)
00521 {
00522 for (unsigned long j = 0; j < _ulCtGridsY; j++)
00523 raclInd.insert(_aulGrid[i][j][nZ].begin(), _aulGrid[i][j][nZ].end());
00524 }
00525 nZ--;
00526 }
00527 break;
00528 }
00529
00530 default:
00531 break;
00532 }
00533 }
00534 }
00535
00536 void MeshGrid::GetHull (unsigned long ulX, unsigned long ulY, unsigned long ulZ,
00537 unsigned long ulDistance, std::set<unsigned long> &raclInd) const
00538 {
00539 int nX1 = std::max<int>(0, int(ulX) - int(ulDistance));
00540 int nY1 = std::max<int>(0, int(ulY) - int(ulDistance));
00541 int nZ1 = std::max<int>(0, int(ulZ) - int(ulDistance));
00542 int nX2 = std::min<int>(int(_ulCtGridsX) - 1, int(ulX) + int(ulDistance));
00543 int nY2 = std::min<int>(int(_ulCtGridsY) - 1, int(ulY) + int(ulDistance));
00544 int nZ2 = std::min<int>(int(_ulCtGridsZ) - 1, int(ulZ) + int(ulDistance));
00545
00546 int i, j;
00547
00548
00549 for (i = nX1; i <= nX2; i++)
00550 {
00551 for (j = nY1; j <= nY2; j++)
00552 GetElements(i, j, nZ1, raclInd);
00553 }
00554
00555 for (i = nX1; i <= nX2; i++)
00556 {
00557 for (j = nY1; j <= nY2; j++)
00558 GetElements(i, j, nZ2, raclInd);
00559 }
00560
00561 for (i = nY1; i <= nY2; i++)
00562 {
00563 for (j = (nZ1+1); j <= (nZ2-1); j++)
00564 GetElements(nX1, i, j, raclInd);
00565 }
00566
00567 for (i = nY1; i <= nY2; i++)
00568 {
00569 for (j = (nZ1+1); j <= (nZ2-1); j++)
00570 GetElements(nX2, i, j, raclInd);
00571 }
00572
00573 for (i = (nX1+1); i <= (nX2-1); i++)
00574 {
00575 for (j = (nZ1+1); j <= (nZ2-1); j++)
00576 GetElements(i, nY1, j, raclInd);
00577 }
00578
00579 for (i = (nX1+1); i <= (nX2-1); i++)
00580 {
00581 for (j = (nZ1+1); j <= (nZ2-1); j++)
00582 GetElements(i, nY2, j, raclInd);
00583 }
00584 }
00585
00586 unsigned long MeshGrid::GetElements (unsigned long ulX, unsigned long ulY, unsigned long ulZ,
00587 std::set<unsigned long> &raclInd) const
00588 {
00589 const std::set<unsigned long> &rclSet = _aulGrid[ulX][ulY][ulZ];
00590 if (rclSet.size() > 0)
00591 {
00592 raclInd.insert(rclSet.begin(), rclSet.end());
00593 return rclSet.size();
00594 }
00595
00596 return 0;
00597 }
00598
00599 unsigned long MeshGrid::GetElements(const Base::Vector3f &rclPoint, std::vector<unsigned long>& aulFacets) const
00600 {
00601 unsigned long ulX, ulY, ulZ;
00602 if (!CheckPosition(rclPoint, ulX, ulY, ulZ))
00603 return 0;
00604
00605 aulFacets.resize(_aulGrid[ulX][ulY][ulZ].size());
00606
00607 std::copy(_aulGrid[ulX][ulY][ulZ].begin(), _aulGrid[ulX][ulY][ulZ].end(), aulFacets.begin());
00608 return aulFacets.size();
00609 }
00610
00611 unsigned long MeshGrid::GetIndexToPosition(unsigned long ulX, unsigned long ulY, unsigned long ulZ) const
00612 {
00613 if ( !CheckPos(ulX, ulY, ulZ) )
00614 return ULONG_MAX;
00615 return (ulZ * _ulCtGridsY + ulY) * _ulCtGridsX + ulX;
00616 }
00617
00618 bool MeshGrid::GetPositionToIndex(unsigned long id, unsigned long& ulX, unsigned long& ulY, unsigned long& ulZ) const
00619 {
00620 ulX = id % _ulCtGridsX;
00621 ulY = (id/_ulCtGridsX)%_ulCtGridsY;
00622 ulZ = id/(_ulCtGridsX*_ulCtGridsY);
00623
00624 if ( !CheckPos(ulX, ulY, ulZ) )
00625 {
00626 ulX = ULONG_MAX;
00627 ulY = ULONG_MAX;
00628 ulZ = ULONG_MAX;
00629 return false;
00630 }
00631
00632 return true;
00633 }
00634
00635
00636
00637 MeshFacetGrid::MeshFacetGrid (const MeshKernel &rclM)
00638 : MeshGrid(rclM)
00639 {
00640 RebuildGrid();
00641 }
00642
00643 MeshFacetGrid::MeshFacetGrid (const MeshKernel &rclM, int iCtGridPerAxis)
00644 : MeshGrid(rclM)
00645 {
00646 Rebuild(iCtGridPerAxis);
00647 }
00648
00649 MeshFacetGrid::MeshFacetGrid (const MeshKernel &rclM, unsigned long ulX, unsigned long ulY, unsigned long ulZ)
00650 : MeshGrid(rclM)
00651 {
00652 Rebuild(ulX, ulY, ulZ);
00653 }
00654
00655 MeshFacetGrid::MeshFacetGrid (const MeshKernel &rclM, float fGridLen)
00656 : MeshGrid(rclM)
00657 {
00658 Base::BoundBox3f clBBMesh = _pclMesh->GetBoundBox();
00659 Rebuild(std::max<unsigned long>((unsigned long)(clBBMesh.LengthX() / fGridLen), 1),
00660 std::max<unsigned long>((unsigned long)(clBBMesh.LengthY() / fGridLen), 1),
00661 std::max<unsigned long>((unsigned long)(clBBMesh.LengthZ() / fGridLen), 1));
00662 }
00663
00664 void MeshFacetGrid::Validate (const MeshKernel &rclMesh)
00665 {
00666 if (_pclMesh != &rclMesh)
00667 Attach(rclMesh);
00668 else if (rclMesh.CountFacets() != _ulCtElements)
00669 RebuildGrid();
00670 }
00671
00672 void MeshFacetGrid::Validate (void)
00673 {
00674 if (_pclMesh == NULL)
00675 return;
00676
00677 if (_pclMesh->CountFacets() != _ulCtElements)
00678 RebuildGrid();
00679 }
00680
00681 bool MeshFacetGrid::Verify() const
00682 {
00683 if ( !_pclMesh )
00684 return false;
00685 if (_pclMesh->CountFacets() != _ulCtElements)
00686 return false;
00687
00688 MeshGridIterator it(*this);
00689 MeshFacetIterator cF(*_pclMesh);
00690 for ( it.Init(); it.More(); it.Next() )
00691 {
00692 std::vector<unsigned long> aulElements;
00693 it.GetElements( aulElements );
00694 for ( std::vector<unsigned long>::iterator itF = aulElements.begin(); itF != aulElements.end(); ++itF )
00695 {
00696 cF.Set( *itF );
00697 if ( cF->IntersectBoundingBox( it.GetBoundBox() ) == false )
00698 return false;
00699 }
00700 }
00701
00702 return true;
00703 }
00704
00705 void MeshFacetGrid::RebuildGrid (void)
00706 {
00707 _ulCtElements = _pclMesh->CountFacets();
00708
00709 InitGrid();
00710
00711
00712 MeshFacetIterator clFIter(*_pclMesh);
00713
00714 unsigned long i = 0;
00715 for (clFIter.Init(); clFIter.More(); clFIter.Next())
00716 {
00717
00718 AddFacet(*clFIter, i++);
00719 }
00720
00721 }
00722
00723 unsigned long MeshFacetGrid::SearchNearestFromPoint (const Base::Vector3f &rclPt) const
00724 {
00725 unsigned long ulFacetInd = ULONG_MAX;
00726 float fMinDist = FLOAT_MAX;
00727 Base::BoundBox3f clBB = GetBoundBox();
00728
00729 if (clBB.IsInBox(rclPt) == true)
00730 {
00731 unsigned long ulX, ulY, ulZ;
00732 Position(rclPt, ulX, ulY, ulZ);
00733 float fMinGridDist = std::min<float>(std::min<float>(_fGridLenX, _fGridLenY), _fGridLenZ);
00734 unsigned long ulDistance = 0;
00735 while (fMinDist > (fMinGridDist * float(ulDistance)))
00736 {
00737 SearchNearestFacetInHull(ulX, ulY, ulZ, ulDistance, rclPt, ulFacetInd, fMinDist);
00738 ulDistance++;
00739 }
00740 SearchNearestFacetInHull(ulX, ulY, ulZ, ulDistance, rclPt, ulFacetInd, fMinDist);
00741 }
00742 else
00743 {
00744 Base::BoundBox3f::SIDE tSide = clBB.GetSideFromRay(rclPt, clBB.CalcCenter() - rclPt);
00745 switch (tSide)
00746 {
00747 case Base::BoundBox3f::RIGHT:
00748 {
00749 int nX = 0;
00750 while ((fMinDist > ((clBB.MinX - rclPt.x) + ((float)(nX) * _fGridLenX))) && ((unsigned long)(nX) < _ulCtGridsX))
00751 {
00752 for (unsigned long i = 0; i < _ulCtGridsY; i++)
00753 {
00754 for (unsigned long j = 0; j < _ulCtGridsZ; j++)
00755 SearchNearestFacetInGrid(nX, i, j, rclPt, fMinDist, ulFacetInd);
00756 }
00757 nX++;
00758 }
00759 break;
00760 }
00761 case Base::BoundBox3f::LEFT:
00762 {
00763 int nX = _ulCtGridsX - 1;
00764 while ((fMinDist > ((rclPt.x - clBB.MinX) + (float(nX) * _fGridLenX))) && (nX >= 0))
00765 {
00766 for (unsigned long i = 0; i < _ulCtGridsY; i++)
00767 {
00768 for (unsigned long j = 0; j < _ulCtGridsZ; j++)
00769 SearchNearestFacetInGrid(nX, i, j, rclPt, fMinDist, ulFacetInd);
00770 }
00771 nX--;
00772 }
00773 break;
00774 }
00775 case Base::BoundBox3f::TOP:
00776 {
00777 int nY = 0;
00778 while ((fMinDist > ((clBB.MinY - rclPt.y) + ((float)(nY) * _fGridLenY))) && ((unsigned long)(nY) < _ulCtGridsY))
00779 {
00780 for (unsigned long i = 0; i < _ulCtGridsX; i++)
00781 {
00782 for (unsigned long j = 0; j < _ulCtGridsZ; j++)
00783 SearchNearestFacetInGrid(i, nY, j, rclPt, fMinDist, ulFacetInd);
00784 }
00785 nY++;
00786 }
00787 break;
00788 }
00789 case Base::BoundBox3f::BOTTOM:
00790 {
00791 int nY = _ulCtGridsY - 1;
00792 while ((fMinDist > ((rclPt.y - clBB.MinY) + (float(nY) * _fGridLenY))) && (nY >= 0))
00793 {
00794 for (unsigned long i = 0; i < _ulCtGridsX; i++)
00795 {
00796 for (unsigned long j = 0; j < _ulCtGridsZ; j++)
00797 SearchNearestFacetInGrid(i, nY, j, rclPt, fMinDist, ulFacetInd);
00798 }
00799 nY--;
00800 }
00801 break;
00802 }
00803 case Base::BoundBox3f::BACK:
00804 {
00805 int nZ = 0;
00806 while ((fMinDist > ((clBB.MinZ - rclPt.z) + ((float)(nZ) * _fGridLenZ))) && ((unsigned long)(nZ) < _ulCtGridsZ))
00807 {
00808 for (unsigned long i = 0; i < _ulCtGridsX; i++)
00809 {
00810 for (unsigned long j = 0; j < _ulCtGridsY; j++)
00811 SearchNearestFacetInGrid(i, j, nZ, rclPt, fMinDist, ulFacetInd);
00812 }
00813 nZ++;
00814 }
00815 break;
00816 }
00817 case Base::BoundBox3f::FRONT:
00818 {
00819 int nZ = _ulCtGridsZ - 1;
00820 while ((fMinDist > ((rclPt.z - clBB.MinZ) + ((float)(nZ) * _fGridLenZ))) && (nZ >= 0))
00821 {
00822 for (unsigned long i = 0; i < _ulCtGridsX; i++)
00823 {
00824 for (unsigned long j = 0; j < _ulCtGridsY; j++)
00825 SearchNearestFacetInGrid(i, j, nZ, rclPt, fMinDist, ulFacetInd);
00826 }
00827 nZ--;
00828 }
00829 break;
00830 }
00831 default:
00832 break;
00833 }
00834 }
00835
00836 return ulFacetInd;
00837 }
00838
00839 unsigned long MeshFacetGrid::SearchNearestFromPoint (const Base::Vector3f &rclPt, float fMaxSearchArea) const
00840 {
00841 std::vector<unsigned long> aulFacets;
00842 unsigned long ulFacetInd = ULONG_MAX;
00843 float fMinDist = fMaxSearchArea;
00844
00845 MeshAlgorithm clFTool(*_pclMesh);
00846
00847 Base::BoundBox3f clBB(rclPt.x - fMaxSearchArea, rclPt.y - fMaxSearchArea, rclPt.z - fMaxSearchArea,
00848 rclPt.x + fMaxSearchArea, rclPt.y + fMaxSearchArea, rclPt.z + fMaxSearchArea);
00849
00850 Inside(clBB, aulFacets, rclPt, fMaxSearchArea, true);
00851
00852 for (std::vector<unsigned long>::const_iterator pI = aulFacets.begin(); pI != aulFacets.end(); pI++)
00853 {
00854 float fDist;
00855
00856 if (clFTool.Distance(rclPt, *pI, fMinDist, fDist) == true)
00857 {
00858 fMinDist = fDist;
00859 ulFacetInd = *pI;
00860 }
00861 }
00862
00863 return ulFacetInd;
00864 }
00865
00866 void MeshFacetGrid::SearchNearestFacetInHull (unsigned long ulX, unsigned long ulY, unsigned long ulZ,
00867 unsigned long ulDistance, const Base::Vector3f &rclPt,
00868 unsigned long &rulFacetInd, float &rfMinDist) const
00869 {
00870 int nX1 = std::max<int>(0, int(ulX) - int(ulDistance));
00871 int nY1 = std::max<int>(0, int(ulY) - int(ulDistance));
00872 int nZ1 = std::max<int>(0, int(ulZ) - int(ulDistance));
00873 int nX2 = std::min<int>(int(_ulCtGridsX) - 1, int(ulX) + int(ulDistance));
00874 int nY2 = std::min<int>(int(_ulCtGridsY) - 1, int(ulY) + int(ulDistance));
00875 int nZ2 = std::min<int>(int(_ulCtGridsZ) - 1, int(ulZ) + int(ulDistance));
00876
00877 int i, j;
00878
00879
00880 for (i = nX1; i <= nX2; i++)
00881 {
00882 for (j = nY1; j <= nY2; j++)
00883 SearchNearestFacetInGrid(i, j, nZ1, rclPt, rfMinDist, rulFacetInd);
00884 }
00885
00886 for (i = nX1; i <= nX2; i++)
00887 {
00888 for (j = nY1; j <= nY2; j++)
00889 SearchNearestFacetInGrid(i, j, nZ2, rclPt, rfMinDist, rulFacetInd);
00890 }
00891
00892 for (i = nY1; i <= nY2; i++)
00893 {
00894 for (j = (nZ1+1); j <= (nZ2-1); j++)
00895 SearchNearestFacetInGrid(nX1, i, j, rclPt, rfMinDist, rulFacetInd);
00896 }
00897
00898 for (i = nY1; i <= nY2; i++)
00899 {
00900 for (j = (nZ1+1); j <= (nZ2-1); j++)
00901 SearchNearestFacetInGrid(nX2, i, j, rclPt, rfMinDist, rulFacetInd);
00902 }
00903
00904 for (i = (nX1+1); i <= (nX2-1); i++)
00905 {
00906 for (j = (nZ1+1); j <= (nZ2-1); j++)
00907 SearchNearestFacetInGrid(i, nY1, j, rclPt, rfMinDist, rulFacetInd);
00908 }
00909
00910 for (i = (nX1+1); i <= (nX2-1); i++)
00911 {
00912 for (j = (nZ1+1); j <= (nZ2-1); j++)
00913 SearchNearestFacetInGrid(i, nY2, j, rclPt, rfMinDist, rulFacetInd);
00914 }
00915 }
00916
00917 void MeshFacetGrid::SearchNearestFacetInGrid(unsigned long ulX, unsigned long ulY, unsigned long ulZ,
00918 const Base::Vector3f &rclPt, float &rfMinDist,
00919 unsigned long &rulFacetInd) const
00920 {
00921 const std::set<unsigned long> &rclSet = _aulGrid[ulX][ulY][ulZ];
00922 for (std::set<unsigned long>::const_iterator pI = rclSet.begin(); pI != rclSet.end(); pI++)
00923 {
00924 float fDist = _pclMesh->GetFacet(*pI).DistanceToPoint(rclPt);
00925 if (fDist < rfMinDist)
00926 {
00927 rfMinDist = fDist;
00928 rulFacetInd = *pI;
00929 }
00930 }
00931 }
00932
00933
00934
00935 MeshPointGrid::MeshPointGrid (const MeshKernel &rclM)
00936 : MeshGrid(rclM)
00937 {
00938 RebuildGrid();
00939 }
00940
00941 MeshPointGrid::MeshPointGrid (void)
00942 : MeshGrid()
00943 {
00944 }
00945
00946 MeshPointGrid::MeshPointGrid (const MeshKernel &rclM, unsigned long ulX, unsigned long ulY, unsigned long ulZ)
00947 : MeshGrid(rclM)
00948 {
00949 Rebuild(ulX, ulY, ulZ);
00950 }
00951
00952 MeshPointGrid::MeshPointGrid (const MeshKernel &rclM, int iCtGridPerAxis)
00953 : MeshGrid(rclM)
00954 {
00955 Rebuild(iCtGridPerAxis);
00956 }
00957
00958 MeshPointGrid::MeshPointGrid (const MeshKernel &rclM, float fGridLen)
00959 : MeshGrid(rclM)
00960 {
00961 Base::BoundBox3f clBBMesh = _pclMesh->GetBoundBox();
00962 Rebuild(std::max<unsigned long>((unsigned long)(clBBMesh.LengthX() / fGridLen), 1),
00963 std::max<unsigned long>((unsigned long)(clBBMesh.LengthY() / fGridLen), 1),
00964 std::max<unsigned long>((unsigned long)(clBBMesh.LengthZ() / fGridLen), 1));
00965 }
00966
00967 void MeshPointGrid::AddPoint (const MeshPoint &rclPt, unsigned long ulPtIndex, float fEpsilon)
00968 {
00969 unsigned long ulX, ulY, ulZ;
00970 Pos(Base::Vector3f(rclPt.x, rclPt.y, rclPt.z), ulX, ulY, ulZ);
00971 if ( (ulX < _ulCtGridsX) && (ulY < _ulCtGridsY) && (ulZ < _ulCtGridsZ) )
00972 _aulGrid[ulX][ulY][ulZ].insert(ulPtIndex);
00973 }
00974
00975 void MeshPointGrid::Validate (const MeshKernel &rclMesh)
00976 {
00977 if (_pclMesh != &rclMesh)
00978 Attach(rclMesh);
00979 else if (rclMesh.CountPoints() != _ulCtElements)
00980 RebuildGrid();
00981 }
00982
00983 void MeshPointGrid::Validate (void)
00984 {
00985 if (_pclMesh == NULL)
00986 return;
00987
00988 if (_pclMesh->CountPoints() != _ulCtElements)
00989 RebuildGrid();
00990 }
00991
00992 bool MeshPointGrid::Verify() const
00993 {
00994 if ( !_pclMesh )
00995 return false;
00996 if (_pclMesh->CountFacets() != _ulCtElements)
00997 return false;
00998
00999 MeshGridIterator it(*this);
01000 MeshPointIterator cP(*_pclMesh);
01001 for ( it.Init(); it.More(); it.Next() )
01002 {
01003 std::vector<unsigned long> aulElements;
01004 it.GetElements( aulElements );
01005 for ( std::vector<unsigned long>::iterator itP = aulElements.begin(); itP != aulElements.end(); ++itP )
01006 {
01007 cP.Set( *itP );
01008 if ( it.GetBoundBox().IsInBox( *cP ) == false )
01009 return false;
01010 }
01011 }
01012
01013 return true;
01014 }
01015
01016 void MeshPointGrid::RebuildGrid (void)
01017 {
01018 _ulCtElements = _pclMesh->CountPoints();
01019
01020 InitGrid();
01021
01022
01023
01024 MeshPointIterator cPIter(*_pclMesh);
01025
01026 unsigned long i = 0;
01027 for (cPIter.Init(); cPIter.More(); cPIter.Next())
01028 {
01029 AddPoint(*cPIter, i++);
01030 }
01031 }
01032
01033 void MeshPointGrid::Pos (const Base::Vector3f &rclPoint, unsigned long &rulX, unsigned long &rulY, unsigned long &rulZ) const
01034 {
01035 rulX = (unsigned long)((rclPoint.x - _fMinX) / _fGridLenX);
01036 rulY = (unsigned long)((rclPoint.y - _fMinY) / _fGridLenY);
01037 rulZ = (unsigned long)((rclPoint.z - _fMinZ) / _fGridLenZ);
01038 }
01039
01040 unsigned long MeshPointGrid::FindElements (const Base::Vector3f &rclPoint, std::set<unsigned long>& aulElements) const
01041 {
01042 unsigned long ulX, ulY, ulZ;
01043 Pos(rclPoint, ulX, ulY, ulZ);
01044
01045
01046 if ( (ulX < _ulCtGridsX) && (ulY < _ulCtGridsY) && (ulZ < _ulCtGridsZ) )
01047 {
01048 return GetElements(ulX, ulY, ulZ, aulElements);
01049 }
01050
01051 return 0;
01052 }
01053
01054
01055
01056 MeshGridIterator::MeshGridIterator (const MeshGrid &rclG)
01057 : _rclGrid(rclG),
01058 _ulX(0), _ulY(0), _ulZ(0),
01059 _clPt(0.0f, 0.0f, 0.0f), _clDir(0.0f, 0.0f, 0.0f),
01060 _bValidRay(false),
01061 _fMaxSearchArea (FLOAT_MAX)
01062
01063 {
01064 }
01065
01066 bool MeshGridIterator::InitOnRay (const Base::Vector3f &rclPt, const Base::Vector3f &rclDir, float fMaxSearchArea,
01067 std::vector<unsigned long> &raulElements)
01068 {
01069 bool ret = InitOnRay (rclPt, rclDir, raulElements);
01070 _fMaxSearchArea = fMaxSearchArea;
01071 return ret;
01072 }
01073
01074 bool MeshGridIterator::InitOnRay (const Base::Vector3f &rclPt, const Base::Vector3f &rclDir,
01075 std::vector<unsigned long> &raulElements)
01076 {
01077
01078 _cSearchPositions.clear();
01079
01080 _fMaxSearchArea = FLOAT_MAX;
01081
01082 raulElements.clear();
01083
01084 _clPt = rclPt;
01085 _clDir = rclDir;
01086 _bValidRay = false;
01087
01088
01089 if ((_rclGrid.GetBoundBox().IsInBox(rclPt)) == true)
01090 {
01091 _rclGrid.Position(rclPt, _ulX, _ulY, _ulZ);
01092 raulElements.insert(raulElements.end(), _rclGrid._aulGrid[_ulX][_ulY][_ulZ].begin(), _rclGrid._aulGrid[_ulX][_ulY][_ulZ].end());
01093 _bValidRay = true;
01094 }
01095 else
01096 {
01097 Base::Vector3f cP0, cP1;
01098 if (_rclGrid.GetBoundBox().IntersectWithLine(rclPt, rclDir, cP0, cP1) == true)
01099 {
01100 if ((cP0 - rclPt).Length() < (cP1 - rclPt).Length())
01101 _rclGrid.Position(cP0, _ulX, _ulY, _ulZ);
01102 else
01103 _rclGrid.Position(cP1, _ulX, _ulY, _ulZ);
01104
01105 raulElements.insert(raulElements.end(), _rclGrid._aulGrid[_ulX][_ulY][_ulZ].begin(), _rclGrid._aulGrid[_ulX][_ulY][_ulZ].end());
01106 _bValidRay = true;
01107 }
01108 }
01109
01110 return _bValidRay;
01111 }
01112
01113 bool MeshGridIterator::NextOnRay (std::vector<unsigned long> &raulElements)
01114 {
01115 if (_bValidRay == false)
01116 return false;
01117
01118 raulElements.clear();
01119
01120 Base::Vector3f clIntersectPoint;
01121
01122
01123 Base::BoundBox3f::SIDE tSide = _rclGrid.GetBoundBox(_ulX, _ulY, _ulZ).GetSideFromRay(_clPt, _clDir, clIntersectPoint);
01124
01125
01126
01127 if ((_clPt-clIntersectPoint).Length() > _fMaxSearchArea)
01128 {
01129 _bValidRay = false;
01130 }
01131 else
01132 {
01133 switch (tSide)
01134 {
01135 case Base::BoundBox3f::LEFT: _ulX--; break;
01136 case Base::BoundBox3f::RIGHT: _ulX++; break;
01137 case Base::BoundBox3f::BOTTOM: _ulY--; break;
01138 case Base::BoundBox3f::TOP: _ulY++; break;
01139 case Base::BoundBox3f::FRONT: _ulZ--; break;
01140 case Base::BoundBox3f::BACK: _ulZ++; break;
01141
01142 default:
01143 case Base::BoundBox3f::INVALID:
01144 _bValidRay = false;
01145 break;
01146 }
01147
01148 GridElement pos(_ulX, _ulY, _ulZ);
01149 if ( _cSearchPositions.find( pos ) != _cSearchPositions.end() )
01150 _bValidRay = false;
01151 }
01152
01153 if ((_bValidRay == true) && (_rclGrid.CheckPos(_ulX, _ulY, _ulZ) == true))
01154 {
01155 GridElement pos(_ulX, _ulY, _ulZ); _cSearchPositions.insert(pos);
01156 raulElements.insert(raulElements.end(), _rclGrid._aulGrid[_ulX][_ulY][_ulZ].begin(), _rclGrid._aulGrid[_ulX][_ulY][_ulZ].end());
01157 }
01158 else
01159 _bValidRay = false;
01160
01161 return _bValidRay;
01162 }