PointsGrid.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2004 Werner Mayer <wmayer[at]users.sourceforge.net>     *
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This library is free software; you can redistribute it and/or         *
00007  *   modify it under the terms of the GNU Library General Public           *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2 of the License, or (at your option) any later version.      *
00010  *                                                                         *
00011  *   This library  is distributed in the hope that it will be useful,      *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00014  *   GNU Library General Public License for more details.                  *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Library General Public     *
00017  *   License along with this library; see the file COPYING.LIB. If not,    *
00018  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00019  *   Suite 330, Boston, MA  02111-1307, USA                                *
00020  *                                                                         *
00021  ***************************************************************************/
00022 
00023 
00024 #include "PreCompiled.h"
00025 
00026 #ifndef _PreComp_
00027 # include <algorithm>
00028 #endif
00029 
00030 
00031 
00032 #include "PointsGrid.h"
00033 
00034 using namespace Points;
00035 
00036 PointsGrid::PointsGrid (const PointKernel &rclM)
00037 : _pclPoints(&rclM),
00038   _ulCtElements(0),
00039   _ulCtGridsX(0), _ulCtGridsY(0), _ulCtGridsZ(0),
00040   _fGridLenX(0.0f), _fGridLenY(0.0f), _fGridLenZ(0.0f),
00041   _fMinX(0.0f), _fMinY(0.0f), _fMinZ(0.0f)
00042 {
00043   RebuildGrid();
00044 }
00045 
00046 PointsGrid::PointsGrid (void)
00047 : _pclPoints(NULL),
00048   _ulCtElements(0),
00049   _ulCtGridsX(POINTS_CT_GRID), _ulCtGridsY(POINTS_CT_GRID), _ulCtGridsZ(POINTS_CT_GRID),
00050   _fGridLenX(0.0f), _fGridLenY(0.0f), _fGridLenZ(0.0f),
00051   _fMinX(0.0f), _fMinY(0.0f), _fMinZ(0.0f)
00052 {
00053 }
00054 
00055 PointsGrid::PointsGrid (const PointKernel &rclM, unsigned long ulX, unsigned long ulY, unsigned long ulZ)
00056 : _pclPoints(&rclM),
00057   _ulCtElements(0),
00058   _ulCtGridsX(0), _ulCtGridsY(0), _ulCtGridsZ(0),
00059   _fGridLenX(0.0f), _fGridLenY(0.0f), _fGridLenZ(0.0f),
00060   _fMinX(0.0f), _fMinY(0.0f), _fMinZ(0.0f)
00061 {
00062   Rebuild(ulX, ulY, ulZ);
00063 }
00064 
00065 PointsGrid::PointsGrid (const PointKernel &rclM, int   iCtGridPerAxis)
00066 : _pclPoints(&rclM),
00067   _ulCtElements(0),
00068   _ulCtGridsX(0), _ulCtGridsY(0), _ulCtGridsZ(0),
00069   _fGridLenX(0.0f), _fGridLenY(0.0f), _fGridLenZ(0.0f),
00070   _fMinX(0.0f), _fMinY(0.0f), _fMinZ(0.0f)
00071 {
00072   Rebuild(iCtGridPerAxis);
00073 }
00074 
00075 PointsGrid::PointsGrid (const PointKernel &rclM, double fGridLen)
00076 : _pclPoints(&rclM),
00077   _ulCtElements(0),
00078   _ulCtGridsX(0), _ulCtGridsY(0), _ulCtGridsZ(0),
00079   _fGridLenX(0.0f), _fGridLenY(0.0f), _fGridLenZ(0.0f),
00080   _fMinX(0.0f), _fMinY(0.0f), _fMinZ(0.0f)
00081 {
00082   Base::BoundBox3d clBBPts;// = _pclPoints->GetBoundBox();
00083   for (PointKernel::const_iterator it = _pclPoints->begin(); it != _pclPoints->end(); ++it )
00084     clBBPts &= (*it);
00085   Rebuild(std::max<unsigned long>((unsigned long)(clBBPts.LengthX() / fGridLen), 1),
00086           std::max<unsigned long>((unsigned long)(clBBPts.LengthY() / fGridLen), 1),
00087           std::max<unsigned long>((unsigned long)(clBBPts.LengthZ() / fGridLen), 1));
00088 }
00089 
00090 void PointsGrid::Attach (const PointKernel &rclM)
00091 {
00092   _pclPoints = &rclM;
00093   RebuildGrid();
00094 }
00095 
00096 void PointsGrid::Clear (void)
00097 {
00098   _aulGrid.clear();
00099   _pclPoints = NULL;  
00100 }
00101 
00102 void PointsGrid::Rebuild (unsigned long ulX, unsigned long ulY, unsigned long ulZ)
00103 {
00104   _ulCtGridsX = ulX;
00105   _ulCtGridsY = ulY;
00106   _ulCtGridsZ = ulZ;
00107   _ulCtElements = HasElements();
00108   RebuildGrid();
00109 }
00110 
00111 void PointsGrid::Rebuild (unsigned long ulPerGrid, unsigned long ulMaxGrid)
00112 {
00113   _ulCtElements = HasElements();
00114   CalculateGridLength(ulPerGrid, ulMaxGrid);
00115   RebuildGrid();
00116 }
00117 
00118 void PointsGrid::Rebuild (int iCtGridPerAxis)
00119 {
00120   _ulCtElements = HasElements();
00121   CalculateGridLength(iCtGridPerAxis);
00122   RebuildGrid();
00123 }
00124 
00125 void PointsGrid::InitGrid (void)
00126 {
00127   assert(_pclPoints != NULL);
00128 
00129   unsigned long i, j;
00130 
00131   // Grid Laengen berechnen wenn nicht initialisiert
00132   //
00133   if ((_ulCtGridsX == 0) || (_ulCtGridsX == 0) || (_ulCtGridsX == 0))
00134     CalculateGridLength(POINTS_CT_GRID, POINTS_MAX_GRIDS);
00135 
00136   // Grid Laengen und Offset bestimmen
00137   //
00138   {
00139   Base::BoundBox3d clBBPts;// = _pclPoints->GetBoundBox();
00140   for (PointKernel::const_iterator it = _pclPoints->begin(); it != _pclPoints->end(); ++it )
00141     clBBPts &= (*it);
00142 
00143   double fLengthX = clBBPts.LengthX(); 
00144   double fLengthY = clBBPts.LengthY();
00145   double fLengthZ = clBBPts.LengthZ();
00146 
00147   {
00148     // Offset fGridLen/2
00149     //
00150     _fGridLenX = (1.0f + fLengthX) / double(_ulCtGridsX);
00151     _fMinX = clBBPts.MinX - 0.5f;
00152   }
00153 
00154   {
00155     _fGridLenY = (1.0f + fLengthY) / double(_ulCtGridsY);
00156     _fMinY = clBBPts.MinY - 0.5f;
00157   }
00158 
00159   {
00160     _fGridLenZ = (1.0f + fLengthZ) / double(_ulCtGridsZ);
00161     _fMinZ = clBBPts.MinZ - 0.5f;
00162   }
00163   }
00164 
00165   // Daten-Struktur anlegen
00166   _aulGrid.clear();
00167   _aulGrid.resize(_ulCtGridsX);
00168   for (i = 0; i < _ulCtGridsX; i++)
00169   {
00170     _aulGrid[i].resize(_ulCtGridsY);
00171     for (j = 0; j < _ulCtGridsY; j++)
00172       _aulGrid[i][j].resize(_ulCtGridsZ);
00173   }
00174 }
00175 
00176 unsigned long PointsGrid::InSide (const Base::BoundBox3d &rclBB, std::vector<unsigned long> &raulElements, bool bDelDoubles) const
00177 {
00178   unsigned long i, j, k, ulMinX, ulMinY, ulMinZ,  ulMaxX, ulMaxY, ulMaxZ;
00179   
00180   raulElements.clear();
00181 
00182   // Grid-Boxen zur naehreren Auswahl
00183   Position(Base::Vector3d(rclBB.MinX, rclBB.MinY, rclBB.MinZ), ulMinX, ulMinY, ulMinZ);
00184   Position(Base::Vector3d(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         raulElements.insert(raulElements.end(), _aulGrid[i][j][k].begin(), _aulGrid[i][j][k].end());
00193       }
00194     }
00195   }  
00196 
00197   if (bDelDoubles == true)
00198   {
00199     // doppelte Nennungen entfernen
00200     std::sort(raulElements.begin(), raulElements.end());
00201     raulElements.erase(std::unique(raulElements.begin(), raulElements.end()), raulElements.end());  
00202   }
00203 
00204   return raulElements.size();
00205 }
00206 
00207 unsigned long PointsGrid::InSide (const Base::BoundBox3d &rclBB, std::vector<unsigned long> &raulElements, const Base::Vector3d &rclOrg, float fMaxDist, bool bDelDoubles) const
00208 {
00209   unsigned long i, j, k, ulMinX, ulMinY, ulMinZ,  ulMaxX, ulMaxY, ulMaxZ;
00210   double  fGridDiag  = GetBoundBox(0, 0, 0).CalcDiagonalLength();
00211   double  fMinDistP2 = (fGridDiag * fGridDiag) + (fMaxDist * fMaxDist);
00212 
00213   raulElements.clear();
00214 
00215   // Grid-Boxen zur naehreren Auswahl
00216   Position(Base::Vector3d(rclBB.MinX, rclBB.MinY, rclBB.MinZ), ulMinX, ulMinY, ulMinZ);
00217   Position(Base::Vector3d(rclBB.MaxX, rclBB.MaxY, rclBB.MaxZ), ulMaxX, ulMaxY, ulMaxZ);
00218 
00219   for (i = ulMinX; i <= ulMaxX; i++)
00220   {
00221     for (j = ulMinY; j <= ulMaxY; j++)
00222     {
00223       for (k = ulMinZ; k <= ulMaxZ; k++)
00224       {
00225         if (Base::DistanceP2(GetBoundBox(i, j, k).CalcCenter(), rclOrg) < fMinDistP2)
00226           raulElements.insert(raulElements.end(), _aulGrid[i][j][k].begin(), _aulGrid[i][j][k].end());
00227       }
00228     }
00229   }  
00230 
00231   if (bDelDoubles == true)
00232   {
00233     // doppelte Nennungen entfernen
00234     std::sort(raulElements.begin(), raulElements.end());
00235     raulElements.erase(std::unique(raulElements.begin(), raulElements.end()), raulElements.end());  
00236   }
00237 
00238   return raulElements.size();
00239 }
00240 
00241 unsigned long PointsGrid::InSide (const Base::BoundBox3d &rclBB, std::set<unsigned long> &raulElements) const
00242 {
00243   unsigned long i, j, k, ulMinX, ulMinY, ulMinZ,  ulMaxX, ulMaxY, ulMaxZ;
00244   
00245   raulElements.clear();
00246 
00247   // Grid-Boxen zur naehreren Auswahl
00248   Position(Base::Vector3d(rclBB.MinX, rclBB.MinY, rclBB.MinZ), ulMinX, ulMinY, ulMinZ);
00249   Position(Base::Vector3d(rclBB.MaxX, rclBB.MaxY, rclBB.MaxZ), ulMaxX, ulMaxY, ulMaxZ);
00250 
00251   for (i = ulMinX; i <= ulMaxX; i++)
00252   {
00253     for (j = ulMinY; j <= ulMaxY; j++)
00254     {
00255       for (k = ulMinZ; k <= ulMaxZ; k++)
00256       {
00257         raulElements.insert(_aulGrid[i][j][k].begin(), _aulGrid[i][j][k].end());
00258       }
00259     }
00260   }  
00261 
00262   return raulElements.size();
00263 }
00264 
00265 void PointsGrid::Position (const Base::Vector3d &rclPoint, unsigned long &rulX, unsigned long &rulY, unsigned long &rulZ) const
00266 {
00267   if (rclPoint.x <= _fMinX)
00268     rulX = 0;
00269   else
00270     rulX = std::min<unsigned long>((unsigned long)((rclPoint.x - _fMinX) / _fGridLenX), _ulCtGridsX - 1);
00271 
00272   if (rclPoint.y <= _fMinY)
00273     rulY = 0;
00274   else
00275     rulY = std::min<unsigned long>((unsigned long)((rclPoint.y - _fMinY) / _fGridLenY), _ulCtGridsY - 1);
00276 
00277   if (rclPoint.z <= _fMinZ)
00278     rulZ = 0;
00279   else
00280     rulZ = std::min<unsigned long>((unsigned long)((rclPoint.z - _fMinZ) / _fGridLenZ), _ulCtGridsZ - 1);
00281 }
00282 
00283 void PointsGrid::CalculateGridLength (unsigned long ulCtGrid, unsigned long ulMaxGrids)
00284 {
00285   // Grid Laengen bzw. Anzahl der Grids pro Dimension berechnen
00286   // pro Grid sollen ca. 10 (?!?!) Facets liegen
00287   // bzw. max Grids sollten 10000 nicht ueberschreiten
00288   Base::BoundBox3d clBBPtsEnlarged;// = _pclPoints->GetBoundBox();
00289   for (PointKernel::const_iterator it = _pclPoints->begin(); it != _pclPoints->end(); ++it )
00290     clBBPtsEnlarged &= (*it);
00291   double fVolElem;
00292 
00293   if (_ulCtElements > (ulMaxGrids * ulCtGrid))
00294     fVolElem = (clBBPtsEnlarged.LengthX() * clBBPtsEnlarged.LengthY() * clBBPtsEnlarged.LengthZ()) / float(ulMaxGrids * ulCtGrid);
00295   else
00296     fVolElem = (clBBPtsEnlarged.LengthX() * clBBPtsEnlarged.LengthY() * clBBPtsEnlarged.LengthZ()) / float(_ulCtElements);
00297 
00298   double fVol     = fVolElem * float(ulCtGrid);
00299   double fGridLen = float(pow((float)fVol,(float) 1.0f / 3.0f));
00300 
00301   _ulCtGridsX = std::max<unsigned long>((unsigned long)(clBBPtsEnlarged.LengthX() / fGridLen), 1);
00302   _ulCtGridsY = std::max<unsigned long>((unsigned long)(clBBPtsEnlarged.LengthY() / fGridLen), 1);
00303   _ulCtGridsZ = std::max<unsigned long>((unsigned long)(clBBPtsEnlarged.LengthZ() / fGridLen), 1);
00304 }
00305 
00306 void PointsGrid::CalculateGridLength (int iCtGridPerAxis)
00307 {
00308   if (iCtGridPerAxis<=0)
00309   {
00310     CalculateGridLength(POINTS_CT_GRID, POINTS_MAX_GRIDS);
00311     return;
00312   }
00313 
00314   // Grid Laengen bzw. Anzahl der Grids pro Dimension berechnen
00315   // pro Grid sollen ca. 10 (?!?!) Facets liegen
00316   // bzw. max Grids sollten 10000 nicht ueberschreiten
00317   Base::BoundBox3d clBBPts;// = _pclPoints->GetBoundBox();
00318   for (PointKernel::const_iterator it = _pclPoints->begin(); it != _pclPoints->end(); ++it )
00319     clBBPts &= (*it);
00320 
00321   double fLenghtX = clBBPts.LengthX();
00322   double fLenghtY = clBBPts.LengthY();
00323   double fLenghtZ = clBBPts.LengthZ();
00324 
00325   double fLenghtD = clBBPts.CalcDiagonalLength();
00326 
00327   double fLengthTol = 0.05f * fLenghtD;
00328 
00329   bool bLenghtXisZero = (fLenghtX <= fLengthTol);
00330   bool bLenghtYisZero = (fLenghtY <= fLengthTol);
00331   bool bLenghtZisZero = (fLenghtZ <= fLengthTol);
00332 
00333   int iFlag  = 0;
00334 
00335   int iMaxGrids = 1;
00336 
00337   if (bLenghtXisZero)  
00338     iFlag += 1; 
00339   else
00340     iMaxGrids *= iCtGridPerAxis;
00341 
00342   if (bLenghtYisZero) 
00343     iFlag += 2;
00344   else
00345     iMaxGrids *= iCtGridPerAxis;
00346 
00347   if (bLenghtZisZero)
00348     iFlag += 4; 
00349   else
00350     iMaxGrids *= iCtGridPerAxis;
00351   
00352   unsigned long ulGridsFacets =   10;
00353 
00354   double fFactorVolumen = 40.0;
00355   double fFactorArea    = 10.0;
00356 
00357   switch (iFlag)
00358   {
00359   case 0:
00360     {
00361       double fVolumen = fLenghtX * fLenghtY * fLenghtZ;
00362 
00363       double fVolumenGrid = (fVolumen * ulGridsFacets) / (fFactorVolumen * _ulCtElements);
00364 
00365       if ((fVolumenGrid * iMaxGrids) < fVolumen)
00366         fVolumenGrid = fVolumen / (float)iMaxGrids;
00367 
00368       double fLengthGrid = float(pow((float)fVolumenGrid,(float) 1.0f / 3.0f));
00369 
00370       _ulCtGridsX = std::max<unsigned long>((unsigned long)(fLenghtX / fLengthGrid), 1);
00371       _ulCtGridsY = std::max<unsigned long>((unsigned long)(fLenghtY / fLengthGrid), 1);
00372       _ulCtGridsZ = std::max<unsigned long>((unsigned long)(fLenghtZ / fLengthGrid), 1);
00373       
00374     } break;
00375   case 1:
00376     {
00377       _ulCtGridsX = 1; // bLenghtXisZero
00378       
00379       double fArea = fLenghtY * fLenghtZ;
00380 
00381       double fAreaGrid = (fArea * ulGridsFacets) / (fFactorArea * _ulCtElements);
00382 
00383       if ((fAreaGrid * iMaxGrids) < fArea)
00384         fAreaGrid = fArea / (double)iMaxGrids;
00385 
00386       double fLengthGrid = double(sqrt(fAreaGrid));
00387 
00388       _ulCtGridsY = std::max<unsigned long>((unsigned long)(fLenghtY / fLengthGrid), 1);
00389       _ulCtGridsZ = std::max<unsigned long>((unsigned long)(fLenghtZ / fLengthGrid), 1);
00390     } break;
00391   case 2:
00392     {
00393       _ulCtGridsY = 1; // bLenghtYisZero
00394   
00395       double fArea = fLenghtX * fLenghtZ;
00396 
00397       double fAreaGrid = (fArea * ulGridsFacets) / (fFactorArea * _ulCtElements);
00398 
00399       if ((fAreaGrid * iMaxGrids) < fArea)
00400         fAreaGrid = fArea / (double)iMaxGrids;
00401 
00402       double fLengthGrid = double(sqrt(fAreaGrid));
00403 
00404       _ulCtGridsX = std::max<unsigned long>((unsigned long)(fLenghtX / fLengthGrid), 1);
00405       _ulCtGridsZ = std::max<unsigned long>((unsigned long)(fLenghtZ / fLengthGrid), 1);
00406     } break;
00407   case 3:
00408     {
00409       _ulCtGridsX = 1; // bLenghtXisZero
00410       _ulCtGridsY = 1; // bLenghtYisZero
00411       _ulCtGridsZ = iMaxGrids; // bLenghtYisZero
00412     } break;
00413   case 4:
00414     {
00415       _ulCtGridsZ = 1; // bLenghtZisZero
00416       
00417       double fArea = fLenghtX * fLenghtY;
00418 
00419       double fAreaGrid = (fArea * ulGridsFacets) / (fFactorArea * _ulCtElements);
00420 
00421       if ((fAreaGrid * iMaxGrids) < fArea)
00422         fAreaGrid = fArea / (float)iMaxGrids;
00423 
00424       double fLengthGrid = double(sqrt(fAreaGrid));
00425 
00426       _ulCtGridsX = std::max<unsigned long>((unsigned long)(fLenghtX / fLengthGrid), 1);
00427       _ulCtGridsY = std::max<unsigned long>((unsigned long)(fLenghtY / fLengthGrid), 1);
00428     } break;
00429   case 5:
00430     {
00431       _ulCtGridsX = 1; // bLenghtXisZero
00432       _ulCtGridsZ = 1; // bLenghtZisZero
00433       _ulCtGridsY = iMaxGrids; // bLenghtYisZero
00434     } break;
00435   case 6:
00436     {
00437       _ulCtGridsY = 1; // bLenghtYisZero
00438       _ulCtGridsZ = 1; // bLenghtZisZero
00439       _ulCtGridsX = iMaxGrids; // bLenghtYisZero
00440     } break;
00441   case 7:
00442     {
00443       _ulCtGridsX = iMaxGrids; // bLenghtXisZero
00444       _ulCtGridsY = iMaxGrids; // bLenghtYisZero
00445       _ulCtGridsZ = iMaxGrids; // bLenghtZisZero
00446     } break;
00447   }
00448 }
00449 
00450 void PointsGrid::SearchNearestFromPoint (const Base::Vector3d &rclPt, std::set<unsigned long> &raclInd) const
00451 {
00452   raclInd.clear();
00453   Base::BoundBox3d  clBB = GetBoundBox();
00454 
00455   if (clBB.IsInBox(rclPt) == true)
00456   { // Punkt liegt innerhalb
00457     unsigned long ulX, ulY, ulZ;
00458     Position(rclPt, ulX, ulY, ulZ);
00459     //int nX = ulX, nY = ulY, nZ = ulZ;
00460     unsigned long ulLevel = 0;
00461     while (raclInd.size() == 0)
00462       GetHull(ulX, ulY, ulZ, ulLevel++, raclInd);
00463     GetHull(ulX, ulY, ulZ, ulLevel, raclInd);
00464   }
00465   else
00466   { // Punkt ausserhalb
00467     Base::BoundBox3d::SIDE tSide = clBB.GetSideFromRay(rclPt, clBB.CalcCenter() - rclPt);
00468     switch (tSide)
00469     {
00470       case Base::BoundBox3d::RIGHT:
00471       {
00472         int nX = 0;
00473         while (raclInd.size() == 0)
00474         {
00475           for (unsigned long i = 0; i < _ulCtGridsY; i++)
00476           {
00477             for (unsigned long j = 0; j < _ulCtGridsZ; j++)
00478               raclInd.insert(_aulGrid[nX][i][j].begin(), _aulGrid[nX][i][j].end());
00479           }
00480           nX++;
00481         }
00482         break;
00483       }
00484       case Base::BoundBox3d::LEFT:
00485       {
00486         int nX = _ulCtGridsX - 1;
00487         while (raclInd.size() == 0)
00488         {
00489           for (unsigned long i = 0; i < _ulCtGridsY; i++)
00490           {
00491             for (unsigned long j = 0; j < _ulCtGridsZ; j++)
00492               raclInd.insert(_aulGrid[nX][i][j].begin(), _aulGrid[nX][i][j].end());
00493           }
00494           nX++;
00495         }
00496         break;
00497       }
00498       case Base::BoundBox3d::TOP:
00499       {
00500         int nY = 0;
00501         while (raclInd.size() == 0)
00502         {
00503           for (unsigned long i = 0; i < _ulCtGridsX; i++)
00504           {
00505             for (unsigned long j = 0; j < _ulCtGridsZ; j++)
00506               raclInd.insert(_aulGrid[i][nY][j].begin(), _aulGrid[i][nY][j].end());
00507           }
00508           nY++;
00509         }
00510         break;
00511       }
00512       case Base::BoundBox3d::BOTTOM:
00513       {
00514         int nY = _ulCtGridsY - 1;
00515         while (raclInd.size() == 0)
00516         {
00517           for (unsigned long i = 0; i < _ulCtGridsX; i++)
00518           {
00519             for (unsigned long j = 0; j < _ulCtGridsZ; j++)
00520               raclInd.insert(_aulGrid[i][nY][j].begin(), _aulGrid[i][nY][j].end());
00521           }
00522           nY--;
00523         }
00524         break;
00525       }
00526       case Base::BoundBox3d::BACK:
00527       {
00528         int nZ = 0;
00529         while (raclInd.size() == 0)
00530         {
00531           for (unsigned long i = 0; i < _ulCtGridsX; i++)
00532           {
00533             for (unsigned long j = 0; j < _ulCtGridsY; j++)
00534               raclInd.insert(_aulGrid[i][j][nZ].begin(), _aulGrid[i][j][nZ].end());
00535           }
00536           nZ++;
00537         }
00538         break;
00539       }
00540       case Base::BoundBox3d::FRONT:
00541       {
00542         int nZ = _ulCtGridsZ - 1;
00543         while (raclInd.size() == 0)
00544         {
00545           for (unsigned long i = 0; i < _ulCtGridsX; i++)
00546           {
00547             for (unsigned long j = 0; j < _ulCtGridsY; j++)
00548               raclInd.insert(_aulGrid[i][j][nZ].begin(), _aulGrid[i][j][nZ].end());
00549           }
00550           nZ--;
00551         }
00552         break;
00553       }
00554 
00555       default:
00556         break;
00557     }
00558   }
00559 }
00560 
00561 void PointsGrid::GetHull (unsigned long ulX, unsigned long ulY, unsigned long ulZ, 
00562                         unsigned long ulDistance, std::set<unsigned long> &raclInd) const
00563 {
00564   int nX1 = std::max<int>(0, int(ulX) - int(ulDistance));
00565   int nY1 = std::max<int>(0, int(ulY) - int(ulDistance));
00566   int nZ1 = std::max<int>(0, int(ulZ) - int(ulDistance));
00567   int nX2 = std::min<int>(int(_ulCtGridsX) - 1, int(ulX) + int(ulDistance));
00568   int nY2 = std::min<int>(int(_ulCtGridsY) - 1, int(ulY) + int(ulDistance));
00569   int nZ2 = std::min<int>(int(_ulCtGridsZ) - 1, int(ulZ) + int(ulDistance));
00570 
00571   int i, j;
00572 
00573   // top plane
00574   for (i = nX1; i <= nX2; i++)
00575   {
00576     for (j = nY1; j <= nY2; j++)
00577       GetElements(i, j, nZ1, raclInd);
00578   }
00579   // bottom plane
00580   for (i = nX1; i <= nX2; i++)
00581   {
00582     for (j = nY1; j <= nY2; j++)
00583       GetElements(i, j, nZ2, raclInd);
00584   }
00585   // left plane
00586   for (i = nY1; i <= nY2; i++)
00587   {
00588     for (j = (nZ1+1); j <= (nZ2-1); j++)
00589       GetElements(nX1, i, j, raclInd);
00590   }
00591   // right plane
00592   for (i = nY1; i <= nY2; i++)
00593   {
00594     for (j = (nZ1+1); j <= (nZ2-1); j++)
00595       GetElements(nX2, i, j, raclInd);
00596   }
00597   // front plane
00598   for (i = (nX1+1); i <= (nX2-1); i++)
00599   {
00600     for (j = (nZ1+1); j <= (nZ2-1); j++)
00601       GetElements(i, nY1, j, raclInd);
00602   }
00603   // back plane
00604   for (i = (nX1+1); i <= (nX2-1); i++)
00605   {
00606     for (j = (nZ1+1); j <= (nZ2-1); j++)
00607       GetElements(i, nY2, j, raclInd);
00608   }
00609 }
00610 
00611 unsigned long PointsGrid::GetElements (unsigned long ulX, unsigned long ulY, unsigned long ulZ,  
00612                                      std::set<unsigned long> &raclInd) const
00613 {
00614   const std::set<unsigned long> &rclSet = _aulGrid[ulX][ulY][ulZ];
00615   if (rclSet.size() > 0)
00616   {
00617     raclInd.insert(rclSet.begin(), rclSet.end());
00618     return rclSet.size();
00619   }
00620 
00621   return 0;
00622 }
00623 
00624 void PointsGrid::AddPoint (const Base::Vector3d &rclPt, unsigned long ulPtIndex, float fEpsilon)
00625 {
00626   unsigned long ulX, ulY, ulZ;
00627   Pos(Base::Vector3d(rclPt.x, rclPt.y, rclPt.z), ulX, ulY, ulZ);
00628   if ( (ulX < _ulCtGridsX) && (ulY < _ulCtGridsY) && (ulZ < _ulCtGridsZ) )
00629     _aulGrid[ulX][ulY][ulZ].insert(ulPtIndex);
00630 }
00631 
00632 void PointsGrid::Validate (const PointKernel &rclPoints)
00633 {
00634   if (_pclPoints != &rclPoints)
00635     Attach(rclPoints);
00636   else if (rclPoints.size() != _ulCtElements)
00637     RebuildGrid();
00638 }
00639 
00640 void PointsGrid::Validate (void)
00641 {
00642   if (_pclPoints == NULL)
00643     return;
00644 
00645   if (_pclPoints->size() != _ulCtElements)
00646     RebuildGrid();
00647 }
00648 
00649 bool PointsGrid::Verify() const
00650 {
00651   if ( !_pclPoints ) 
00652     return false; // no point cloud attached
00653   if (_pclPoints->size() != _ulCtElements)
00654     return false; // not up-to-date
00655 
00656   PointsGridIterator it(*this);
00657   for ( it.Init(); it.More(); it.Next() )
00658   {
00659     std::vector<unsigned long> aulElements;
00660     it.GetElements( aulElements );
00661     for ( std::vector<unsigned long>::iterator itP = aulElements.begin(); itP != aulElements.end(); ++itP )
00662     {
00663       const Base::Vector3d& cP = _pclPoints->getPoint(*itP);
00664       if ( it.GetBoundBox().IsInBox( cP ) == false )
00665         return false; // point doesn't lie inside the grid element
00666     }
00667   }
00668 
00669   return true;
00670 }
00671 
00672 void PointsGrid::RebuildGrid (void)
00673 {
00674   _ulCtElements = _pclPoints->size();
00675 
00676   InitGrid();
00677  
00678   // Daten-Struktur fuellen
00679 
00680   unsigned long i = 0;
00681   for (PointKernel::const_iterator it = _pclPoints->begin(); it != _pclPoints->end(); ++it )
00682   {
00683     AddPoint(*it, i++);
00684   }
00685 }
00686 
00687 void PointsGrid::Pos (const Base::Vector3d &rclPoint, unsigned long &rulX, unsigned long &rulY, unsigned long &rulZ) const
00688 {
00689   rulX = (unsigned long)((rclPoint.x - _fMinX) / _fGridLenX);
00690   rulY = (unsigned long)((rclPoint.y - _fMinY) / _fGridLenY);
00691   rulZ = (unsigned long)((rclPoint.z - _fMinZ) / _fGridLenZ);
00692 }
00693 
00694 unsigned long PointsGrid::FindElements (const Base::Vector3d &rclPoint, std::set<unsigned long>& aulElements) const
00695 {
00696   unsigned long ulX, ulY, ulZ;
00697   Pos(rclPoint, ulX, ulY, ulZ);
00698 
00699   // check if the given point is inside the grid structure
00700   if ( (ulX < _ulCtGridsX) && (ulY < _ulCtGridsY) && (ulZ < _ulCtGridsZ) )
00701   {
00702     return GetElements(ulX, ulY, ulZ, aulElements);
00703   }
00704 
00705   return 0;
00706 }
00707 
00708 // ----------------------------------------------------------------
00709 
00710 PointsGridIterator::PointsGridIterator (const PointsGrid &rclG)
00711 : _rclGrid(rclG),
00712   _ulX(0), _ulY(0), _ulZ(0),
00713   _clPt(0.0f, 0.0f, 0.0f), _clDir(0.0f, 0.0f, 0.0f),
00714   _bValidRay(false),
00715   _fMaxSearchArea (FLOAT_MAX)
00716 
00717 {
00718 }
00719 
00720 bool PointsGridIterator::InitOnRay (const Base::Vector3d &rclPt, const Base::Vector3d &rclDir, float fMaxSearchArea,
00721                                   std::vector<unsigned long> &raulElements)
00722 {
00723   bool ret = InitOnRay (rclPt, rclDir, raulElements);
00724   _fMaxSearchArea = fMaxSearchArea;
00725   return ret;
00726 }
00727 
00728 bool PointsGridIterator::InitOnRay (const Base::Vector3d &rclPt, const Base::Vector3d &rclDir,
00729                                   std::vector<unsigned long> &raulElements)
00730 {
00731   // needed in NextOnRay() to avoid an infinite loop
00732   _cSearchPositions.clear();
00733 
00734   _fMaxSearchArea = FLOAT_MAX;
00735 
00736   raulElements.clear();        
00737 
00738   _clPt      = rclPt;
00739   _clDir     = rclDir;
00740   _bValidRay = false;
00741 
00742   // liegt Punkt innerhalb globalen BB
00743   if ((_rclGrid.GetBoundBox().IsInBox(rclPt)) == true)
00744   {  // Voxel bestimmen, indem der Startpunkt liegt
00745     _rclGrid.Position(rclPt, _ulX, _ulY, _ulZ);
00746     raulElements.insert(raulElements.end(), _rclGrid._aulGrid[_ulX][_ulY][_ulZ].begin(), _rclGrid._aulGrid[_ulX][_ulY][_ulZ].end());
00747     _bValidRay = true;
00748   }
00749   else
00750   { // Startpunkt ausserhalb
00751     Base::Vector3d cP0, cP1;
00752     if (_rclGrid.GetBoundBox().IntersectWithLine(rclPt, rclDir, cP0, cP1) == true)
00753     {  // naechsten Punkt bestimmen
00754       if ((cP0 - rclPt).Length() < (cP1 - rclPt).Length())
00755         _rclGrid.Position(cP0, _ulX, _ulY, _ulZ);
00756       else
00757         _rclGrid.Position(cP1, _ulX, _ulY, _ulZ);
00758 
00759       raulElements.insert(raulElements.end(), _rclGrid._aulGrid[_ulX][_ulY][_ulZ].begin(), _rclGrid._aulGrid[_ulX][_ulY][_ulZ].end());
00760       _bValidRay = true;
00761     }
00762   }
00763 
00764   return _bValidRay;
00765 }
00766 
00767 bool PointsGridIterator::NextOnRay (std::vector<unsigned long> &raulElements)
00768 {
00769   if (_bValidRay == false)
00770     return false;  // nicht initialisiert oder Strahl ausgetreten
00771   
00772   raulElements.clear();
00773 
00774   Base::Vector3d clIntersectPoint;
00775 
00776   // naechstes anliegende BB auf dem Suchstrahl suchen
00777   Base::BoundBox3d::SIDE tSide = _rclGrid.GetBoundBox(_ulX, _ulY, _ulZ).GetSideFromRay(_clPt, _clDir, clIntersectPoint);
00778 
00779   // Suchbereich
00780   //
00781   if ((_clPt-clIntersectPoint).Length() > _fMaxSearchArea)
00782   {
00783       _bValidRay = false;
00784   }
00785   else
00786   {
00787     switch (tSide)
00788     {
00789     case Base::BoundBox3d::LEFT:   _ulX--;  break;
00790     case Base::BoundBox3d::RIGHT:  _ulX++;  break;
00791     case Base::BoundBox3d::BOTTOM: _ulY--;  break;
00792     case Base::BoundBox3d::TOP:    _ulY++;  break;
00793     case Base::BoundBox3d::FRONT:  _ulZ--;  break;
00794     case Base::BoundBox3d::BACK:   _ulZ++;  break;
00795 
00796     default:
00797     case Base::BoundBox3d::INVALID:
00798       _bValidRay = false;
00799       break;
00800     }
00801 
00802     GridElement pos(_ulX, _ulY, _ulZ);
00803     if ( _cSearchPositions.find( pos ) != _cSearchPositions.end() )
00804       _bValidRay = false; // grid element already visited => result from GetSideFromRay invalid
00805   }
00806 
00807   if ((_bValidRay == true) && (_rclGrid.CheckPos(_ulX, _ulY, _ulZ) == true))
00808   {
00809     GridElement pos(_ulX, _ulY, _ulZ); _cSearchPositions.insert(pos);
00810     raulElements.insert(raulElements.end(), _rclGrid._aulGrid[_ulX][_ulY][_ulZ].begin(), _rclGrid._aulGrid[_ulX][_ulY][_ulZ].end()); 
00811   }
00812   else
00813     _bValidRay = false;  // Strahl ausgetreten
00814 
00815   return _bValidRay;
00816 }

Generated on Wed Nov 23 19:00:28 2011 for FreeCAD by  doxygen 1.6.1