1 // Copyright (C) 2007-2008 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Partitioning/decimation module for the SALOME v3.2 platform
22 * \file MULTIPR_DecimationAccel.cxx
24 * \brief see MULTIPR_DecimationAccel.hxx
26 * \author Olivier LE ROUX - CS, Virtual Reality Dpt
31 //*****************************************************************************
33 //*****************************************************************************
35 #include "MULTIPR_DecimationAccel.hxx"
36 #include "MULTIPR_PointOfField.hxx"
37 #include "MULTIPR_Exceptions.hxx"
49 //*****************************************************************************
50 // Class DecimationAccel implementation
51 //*****************************************************************************
54 ostream& operator<<(ostream& pOs, DecimationAccel& pA)
56 pOs << "DecimationAccel:" << endl;
61 //*****************************************************************************
62 // Class DecimationAccelGrid
63 //*****************************************************************************
65 DecimationAccelGrid::DecimationAccelGrid()
73 DecimationAccelGrid::~DecimationAccelGrid()
79 void DecimationAccelGrid::reset()
83 mMin[0] = numeric_limits<med_float>::quiet_NaN();
84 mMin[1] = numeric_limits<med_float>::quiet_NaN();
85 mMin[2] = numeric_limits<med_float>::quiet_NaN();
87 mMax[0] = numeric_limits<med_float>::quiet_NaN();
88 mMax[1] = numeric_limits<med_float>::quiet_NaN();
89 mMax[2] = numeric_limits<med_float>::quiet_NaN();
91 mInvLen[0] = numeric_limits<med_float>::quiet_NaN();
92 mInvLen[1] = numeric_limits<med_float>::quiet_NaN();
93 mInvLen[2] = numeric_limits<med_float>::quiet_NaN();
105 mFlagPrintAll = false;
109 void DecimationAccelGrid::create(const std::vector<PointOfField>& pPts)
111 // check if grid have been initialized
112 if (mSize[0] == 0) throw IllegalStateException("call setSize() before", __FILE__, __LINE__);
114 // compute bbox of the grid
118 int size = mSize[0] * mSize[1] * mSize[2];
119 mGrid = new vector<PointOfField>[size];
123 for (int i = 0 ; i < mNum ; i++)
125 vector<PointOfField>& cell = getCell(pPts[i]);
126 cell.push_back(pPts[i]);
131 void DecimationAccelGrid::configure(const char* pArgv)
134 if (pArgv == NULL) throw NullArgumentException("", __FILE__, __LINE__);
140 int ret = sscanf(pArgv, "%d %d %d", &sizeX, &sizeY, &sizeZ);
142 if (ret != 3) throw IllegalArgumentException("expected 3 parameters", __FILE__, __LINE__);
143 if (sizeX <= 0) throw IllegalArgumentException("number of cells along X-axis must be > 0", __FILE__, __LINE__);
144 if (sizeY <= 0) throw IllegalArgumentException("number of cells along Y-axis must be > 0", __FILE__, __LINE__);
145 if (sizeZ <= 0) throw IllegalArgumentException("number of cells along Z-axis must be > 0", __FILE__, __LINE__);
155 void DecimationAccelGrid::getCellCoord(
156 med_float pX, med_float pY, med_float pZ,
157 int* pIx, int* pIy, int* pIz) const
159 med_float cx = (pX - mMin[0]) * mInvLen[0];
160 med_float cy = (pY - mMin[1]) * mInvLen[1];
161 med_float cz = (pZ - mMin[2]) * mInvLen[2];
163 // clamp all indices to avoid overflow
165 if (*pIx >= mSize[0]) *pIx = mSize[0] - 1;
166 else if (*pIx < 0) *pIx = 0;
169 if (*pIy >= mSize[1]) *pIy = mSize[1] - 1;
170 else if (*pIy < 0) *pIy = 0;
173 if (*pIz >= mSize[2]) *pIz = mSize[2] - 1;
174 else if (*pIz < 0) *pIz = 0;
178 int DecimationAccelGrid::getCellIndex(int pI, int pJ, int pK) const
180 int index = pK * (mSize[0] * mSize[1]) + pJ * mSize[0] + pI;
186 vector<PointOfField>& DecimationAccelGrid::getCell(const PointOfField& pPt)
191 pPt.mXYZ[0], pPt.mXYZ[1], pPt.mXYZ[2],
194 int index = getCellIndex(ix, iy, iz);
200 vector<PointOfField> DecimationAccelGrid::findNeighbours(
204 med_float pRadius) const
206 //---------------------------------------------------------------------
207 // Determine the axis aligned bounding box of the sphere ((x, y, z), r)
208 //---------------------------------------------------------------------
209 med_float sphereBBoxMin[3];
210 med_float sphereBBoxMax[3];
212 sphereBBoxMin[0] = pCenterX - pRadius;
213 sphereBBoxMin[1] = pCenterY - pRadius;
214 sphereBBoxMin[2] = pCenterZ - pRadius;
216 sphereBBoxMax[0] = pCenterX + pRadius;
217 sphereBBoxMax[1] = pCenterY + pRadius;
218 sphereBBoxMax[2] = pCenterZ + pRadius;
220 //---------------------------------------------------------------------
221 // Determine the cells of the grid intersected by the sphere ((x, y, z), r)
222 // => range of cells are [iMinCell[0], iMaxCell[0]] x [iMinCell[1], iMaxCell[1]] x [iMinCell[2], iMaxCell[2]]
223 //---------------------------------------------------------------------
227 getCellCoord(sphereBBoxMin[0], sphereBBoxMin[1], sphereBBoxMin[2],
228 &iMinCell[0], &iMinCell[1], &iMinCell[2]);
230 getCellCoord(sphereBBoxMax[0], sphereBBoxMax[1], sphereBBoxMax[2],
231 &iMaxCell[0], &iMaxCell[1], &iMaxCell[2]);
233 //---------------------------------------------------------------------
234 // Collect points of the field which are in the sphere
235 //---------------------------------------------------------------------
236 vector<PointOfField> res;
238 if (isnan(pCenterX) || isnan(pCenterY) || isnan(pCenterZ))
243 // for all the cells in the grid intersected by the sphere ((x, y, z), r)
244 for (int i = iMinCell[0] ; i <= iMaxCell[0] ; i++)
246 for (int j = iMinCell[1] ; j <= iMaxCell[1] ; j++)
248 for (int k = iMinCell[2] ; k <= iMaxCell[2] ; k++)
250 int idCell = getCellIndex(i, j, k);
252 vector<PointOfField>& cell = mGrid[idCell];
254 // for all the points in the current cell
255 for (vector<PointOfField>::const_iterator itPoint = cell.begin() ; itPoint != cell.end() ; itPoint++)
257 const PointOfField& currentPt = *itPoint;
259 // test if currentPt is in the sphere ((x, y, z), r)
260 med_float vecX = currentPt.mXYZ[0] - pCenterX;
261 med_float vecY = currentPt.mXYZ[1] - pCenterY;
262 med_float vecZ = currentPt.mXYZ[2] - pCenterZ;
264 med_float norm = med_float( sqrt( vecX*vecX + vecY*vecY + vecZ*vecZ ) );
267 // only add the point if it is different from (x, y, z)
268 if ((currentPt.mXYZ[0] != pCenterX) ||
269 (currentPt.mXYZ[1] != pCenterY) ||
270 (currentPt.mXYZ[2] != pCenterZ))
272 res.push_back(currentPt);
284 void DecimationAccelGrid::computeBBox(const std::vector<PointOfField>& pPts)
286 for (int itDim = 0 ; itDim < 3 ; itDim++)
288 mMin[itDim] = numeric_limits<med_float>::max();
289 mMax[itDim] = -mMin[itDim];
292 for (unsigned i = 0 ; i < pPts.size() ; i++)
294 for (int itDim = 0 ; itDim < 3 ; itDim++)
296 med_float coord = pPts[i].mXYZ[itDim];
297 if (coord < mMin[itDim]) mMin[itDim] = coord;
298 if (coord > mMax[itDim]) mMax[itDim] = coord;
302 mInvLen[0] = med_float(mSize[0]) / (mMax[0] - mMin[0]);
303 mInvLen[1] = med_float(mSize[1]) / (mMax[1] - mMin[1]);
304 mInvLen[2] = med_float(mSize[2]) / (mMax[2] - mMin[2]);
308 ostream& operator<<(ostream& pOs, DecimationAccelGrid& pG)
310 pOs << "DecimationAccelGrid:" << endl;
311 pOs << " Num=" << pG.mNum << endl;
312 pOs << " Size=" << pG.mSize[0] << " x " << pG.mSize[1] << " x " << pG.mSize[2] << endl;
313 pOs << " BBox=[" << pG.mMin[0] << " ; " << pG.mMax[0] << "] x [" << pG.mMin[1] << " ; " << pG.mMax[1] << "] x [" << pG.mMin[2] << " ; " << pG.mMax[2] << "]" << endl;
314 pOs << " Inv len.=" << pG.mInvLen[0] << " ; " << pG.mInvLen[1] << " ; " << pG.mInvLen[2] << endl;
316 if (pG.mFlagPrintAll)
318 int checkNumCells = 0;
319 int numCells = pG.mSize[0] * pG.mSize[1] * pG.mSize[2];
320 for (int i = 0 ; i < numCells ; i++)
322 vector<PointOfField>& cell = pG.mGrid[i];
323 cout << " Cell " << i << ": #=" << cell.size() << ": " << endl;
324 for (unsigned j = 0 ; j < cell.size() ; j++)
326 cout << " " << cell[j] << endl;
328 checkNumCells += cell.size();
331 if (pG.mNum != checkNumCells) throw IllegalStateException("", __FILE__, __LINE__);
338 } // namespace multipr