1 // Project MULTIPR, IOLS WP1.2.1 - EDF/CS
2 // Partitioning/decimation module for the SALOME v3.2 platform
5 * \file MULTIPR_DecimationFilter.cxx
7 * \brief see MULTIPR_DecimationFilter.hxx
9 * \author Olivier LE ROUX - CS, Virtual Reality Dpt
14 //*****************************************************************************
16 //*****************************************************************************
18 #include "MULTIPR_DecimationFilter.hxx"
19 #include "MULTIPR_Field.hxx"
20 #include "MULTIPR_Mesh.hxx"
21 #include "MULTIPR_Nodes.hxx"
22 #include "MULTIPR_Elements.hxx"
23 #include "MULTIPR_Profil.hxx"
24 #include "MULTIPR_PointOfField.hxx"
25 #include "MULTIPR_DecimationAccel.hxx"
26 #include "MULTIPR_Exceptions.hxx"
37 //*****************************************************************************
38 // Class DecimationFilter implementation
39 //*****************************************************************************
41 // Factory used to build all filters from their name.
42 DecimationFilter* DecimationFilter::create(const char* pFilterName)
44 if (pFilterName == NULL) throw NullArgumentException("filter name should not be NULL", __FILE__, __LINE__);
46 if (strcmp(pFilterName, "Filtre_GradientMoyen") == 0)
48 return new DecimationFilterGradAvg();
50 else if (strcmp(pFilterName, "Filtre_Direct") == 0)
52 return new DecimationFilterTreshold();
56 throw IllegalArgumentException("unknown filter", __FILE__, __LINE__);
61 //*****************************************************************************
62 // Class DecimationFilterGradAvg
63 //*****************************************************************************
65 DecimationFilterGradAvg::DecimationFilterGradAvg()
71 DecimationFilterGradAvg::~DecimationFilterGradAvg()
77 Mesh* DecimationFilterGradAvg::apply(Mesh* pMesh, const char* pArgv, const char* pNameNewMesh)
79 //---------------------------------------------------------------------
80 // Retrieve and check parameters
81 //---------------------------------------------------------------------
82 if (pMesh == NULL) throw NullArgumentException("pMesh should not be NULL", __FILE__, __LINE__);
83 if (pArgv == NULL) throw NullArgumentException("pArgv should not be NULL", __FILE__, __LINE__);
84 if (pNameNewMesh == NULL) throw NullArgumentException("pNameNewMesh should not be NULL", __FILE__, __LINE__);
86 char fieldName[MED_TAILLE_NOM + 1];
91 int boxing; // number of cells along axis (if 100 then grid will have 100*100*100 = 10**6 cells)
92 set<med_int> elementsToKeep[eMaxMedMesh];
95 int ret = sscanf(pArgv, "%s %d %lf %lf %d",
101 if (ret != 5) throw IllegalArgumentException("wrong number of arguments for filter GradAvg; expected 5 parameters", __FILE__, __LINE__);
103 for (meshIt = 0; meshIt < eMaxMedMesh; ++meshIt)
106 //---------------------------------------------------------------------
107 // Retrieve field = for each point: get its coordinate and the value of the field
108 //---------------------------------------------------------------------
109 field = pMesh->getFieldByName(fieldName, (eMeshType)meshIt);
111 if (field == NULL) continue;
112 if ((fieldIt < 1) || (fieldIt > field->getNumberOfTimeSteps())) throw IllegalArgumentException("invalid field iteration", __FILE__, __LINE__);
114 vector<PointOfField> points;
115 pMesh->getAllPointsOfField(field, fieldIt, points, (eMeshType)meshIt);
117 //---------------------------------------------------------------------
118 // Creates acceleration structure used to compute gradient
119 //---------------------------------------------------------------------
120 DecimationAccel* accel = new DecimationAccelGrid();
121 char strCfg[256]; // a string is used for genericity
122 sprintf(strCfg, "%d %d %d", boxing, boxing, boxing);
123 accel->configure(strCfg);
124 accel->create(points);
126 //---------------------------------------------------------------------
127 // Collects elements of the mesh to be kept
128 //---------------------------------------------------------------------
130 if (field->isFieldOnNodes())
132 numElements = pMesh->getNodes()->getNumberOfNodes();
136 numElements = pMesh->getNumberOfElements((eMeshType)meshIt);
138 if (field->getProfil(fieldIt).size() != 0)
140 Profil* profil = pMesh->getProfil(field->getProfil(fieldIt));
141 if (profil == NULL) throw IllegalStateException("Can't find the profile in the mesh.", __FILE__, __LINE__);
142 numElements = profil->getSet().size();
145 int numGaussPointsByElt = 0;
146 if (field->isFieldOnNodes())
148 numGaussPointsByElt = 1;
152 numGaussPointsByElt = points.size() / numElements;
156 for (int itElt = 0 ; itElt < numElements ; itElt++)
158 bool keepElement = false;
160 // for each Gauss point of the current element
161 for (int itPtGauss = 0 ; itPtGauss < numGaussPointsByElt ; itPtGauss++)
163 const PointOfField& currentPt = points[itElt * numGaussPointsByElt + itPtGauss];
165 vector<PointOfField> neighbours = accel->findNeighbours(
171 // if no neighbours => keep element
172 if (neighbours.size() == 0)
178 // otherwise compute gradient...
179 med_float normGrad = computeNormGrad(currentPt, neighbours);
182 //cout << (itElt * numGaussPointsByElt + j) << ": " << normGrad << endl;
184 if ((normGrad >= threshold) || isnan(normGrad))
193 // add index of the element to keep (index must start at 1)
194 elementsToKeep[meshIt].insert(med_int(itElt + 1));
198 //---------------------------------------------------------------------
200 //---------------------------------------------------------------------
203 if (field->isFieldOnNodes())
209 //---------------------------------------------------------------------
210 // Create the final mesh by extracting elements to keep from the current mesh
211 //---------------------------------------------------------------------
212 Mesh* newMesh = NULL;
213 if (field && field->isFieldOnNodes())
215 std::set<med_int> setOfElts[eMaxMedMesh];
217 for (meshIt = 0; meshIt < eMaxMedMesh; ++meshIt)
219 if (pMesh->getElements(meshIt) != NULL)
221 pMesh->getElements(meshIt)->extractSubSetFromNodes(elementsToKeep[0], setOfElts[meshIt]);
224 newMesh = pMesh->createFromSetOfElements(setOfElts, pNameNewMesh);
228 newMesh = pMesh->createFromSetOfElements(elementsToKeep, pNameNewMesh);
235 void DecimationFilterGradAvg::getGradientInfo(
237 const char* pFieldName,
245 if (pMesh == NULL) throw NullArgumentException("pMesh should not be NULL", __FILE__, __LINE__);
246 if (pFieldName == NULL) throw NullArgumentException("pFieldName should not be NULL", __FILE__, __LINE__);
248 for (int meshIt = 0; meshIt < eMaxMedMesh; ++meshIt)
251 //---------------------------------------------------------------------
252 // Retrieve field = for each point: get its coordinate and the value of the field
253 //---------------------------------------------------------------------
254 Field* field = pMesh->getFieldByName(pFieldName, (eMeshType)meshIt);
256 if (field == NULL) continue;
257 if ((pFieldIt < 1) || (pFieldIt > field->getNumberOfTimeSteps())) throw IllegalArgumentException("invalid field iteration", __FILE__, __LINE__);
259 vector<PointOfField> points;
260 pMesh->getAllPointsOfField(field, pFieldIt, points, (eMeshType)meshIt);
262 //---------------------------------------------------------------------
263 // Creates acceleration structure used to compute gradient
264 //---------------------------------------------------------------------
265 DecimationAccel* accel = new DecimationAccelGrid();
266 char strCfg[256]; // a string is used for genericity
267 sprintf(strCfg, "%d %d %d", pBoxing, pBoxing, pBoxing);
268 accel->configure(strCfg);
269 accel->create(points);
271 //---------------------------------------------------------------------
272 // Collects elements of the mesh to be kept
273 //---------------------------------------------------------------------
275 if (field->isFieldOnNodes())
277 numElements = pMesh->getNodes()->getNumberOfNodes();
281 numElements = pMesh->getNumberOfElements((eMeshType)meshIt);
283 if (field->getProfil(pFieldIt).size() != 0)
285 Profil* profil = pMesh->getProfil(field->getProfil(pFieldIt));
286 if (profil == NULL) throw IllegalStateException("Can't find the profile in the mesh.", __FILE__, __LINE__);
287 numElements = profil->getSet().size();
290 int numGaussPointsByElt = 0;
291 if (field->isFieldOnNodes())
293 numGaussPointsByElt = 1;
297 numGaussPointsByElt = points.size() / numElements;
300 *pOutGradMax = -1e300;
301 *pOutGradMin = 1e300;
306 for (int itElt = 0 ; itElt < numElements ; itElt++)
308 // for each Gauss point of the current element
309 for (int itPtGauss = 0 ; itPtGauss < numGaussPointsByElt ; itPtGauss++)
311 const PointOfField& currentPt = points[itElt * numGaussPointsByElt + itPtGauss];
313 vector<PointOfField> neighbours = accel->findNeighbours(
319 // if no neighbours => keep element
320 if (neighbours.size() == 0)
325 // otherwise compute gradient...
326 med_float normGrad = computeNormGrad(currentPt, neighbours);
329 //cout << (itElt * numGaussPointsByElt + j) << ": " << normGrad << endl;
331 if (!isnan(normGrad))
333 if (normGrad > *pOutGradMax) *pOutGradMax = normGrad;
334 if (normGrad < *pOutGradMin) *pOutGradMin = normGrad;
335 *pOutGradAvg += normGrad;
341 if (count != 0) *pOutGradAvg /= double(count);
343 //---------------------------------------------------------------------
345 //---------------------------------------------------------------------
347 if (field->isFieldOnNodes())
355 med_float DecimationFilterGradAvg::computeNormGrad(const PointOfField& pPt, const std::vector<PointOfField>& pNeighbours) const
357 med_float gradX = 0.0;
358 med_float gradY = 0.0;
359 med_float gradZ = 0.0;
361 // for each neighbour
362 for (unsigned i = 0 ; i < pNeighbours.size() ; i++)
364 const PointOfField& neighbourPt = pNeighbours[i];
366 med_float vecX = neighbourPt.mXYZ[0] - pPt.mXYZ[0];
367 med_float vecY = neighbourPt.mXYZ[1] - pPt.mXYZ[1];
368 med_float vecZ = neighbourPt.mXYZ[2] - pPt.mXYZ[2];
370 med_float norm = med_float( sqrt( vecX*vecX + vecY*vecY + vecZ*vecZ ) );
371 med_float val = neighbourPt.mVal - pPt.mVal;
380 med_float invSize = 1.0 / med_float(pNeighbours.size());
386 med_float norm = med_float( sqrt( gradX*gradX + gradY*gradY + gradZ*gradZ ) );
392 //*****************************************************************************
393 // Class DecimationFilterGradAvg
394 //*****************************************************************************
396 DecimationFilterTreshold::DecimationFilterTreshold()
402 DecimationFilterTreshold::~DecimationFilterTreshold()
408 Mesh* DecimationFilterTreshold::apply(Mesh* pMesh, const char* pArgv, const char* pNameNewMesh)
410 if (pMesh == NULL) throw NullArgumentException("pMesh should not be NULL", __FILE__, __LINE__);
411 if (pArgv == NULL) throw NullArgumentException("pArgv should not be NULL", __FILE__, __LINE__);
412 if (pNameNewMesh == NULL) throw NullArgumentException("pNameNewMesh should not be NULL", __FILE__, __LINE__);
414 char fieldName[MED_TAILLE_NOM + 1];
418 set<med_int> elementsToKeep[eMaxMedMesh];
421 int ret = sscanf(pArgv, "%s %d %lf",
426 if (ret != 3) throw IllegalArgumentException("wrong number of arguments for filter Treshold; expected 3 parameters", __FILE__, __LINE__);
428 for (meshIt = 0; meshIt < eMaxMedMesh; ++meshIt)
430 //---------------------------------------------------------------------
431 // Retrieve field = for each point: get its coordinate and the value of the field
432 //---------------------------------------------------------------------
433 field = pMesh->getFieldByName(fieldName, (eMeshType)meshIt);
434 if (field == NULL) continue;
435 if ((fieldIt < 1) || (fieldIt > field->getNumberOfTimeSteps())) throw IllegalArgumentException("invalid field iteration", __FILE__, __LINE__);
437 vector<PointOfField> points;
438 pMesh->getAllPointsOfField(field, fieldIt, points, (eMeshType)meshIt);
440 //---------------------------------------------------------------------
441 // Collects elements of the mesh to be kept
442 //---------------------------------------------------------------------
444 if (field->isFieldOnNodes())
446 numElements = pMesh->getNodes()->getNumberOfNodes();
450 numElements = pMesh->getNumberOfElements((eMeshType)meshIt);
452 if (field->getProfil(fieldIt).size() != 0)
454 Profil* profil = pMesh->getProfil(field->getProfil(fieldIt));
455 if (profil == NULL) throw IllegalStateException("Can't find the profile in the mesh.", __FILE__, __LINE__);
456 numElements = profil->getSet().size();
459 int numGaussPointsByElt = 0;
460 if (field->isFieldOnNodes())
462 numGaussPointsByElt = 1;
466 numGaussPointsByElt = points.size() / numElements;
469 for (int itElt = 0 ; itElt < numElements ; itElt++)
471 bool keepElement = false;
473 // for each Gauss point of the current element
474 for (int itPtGauss = 0 ; itPtGauss < numGaussPointsByElt ; itPtGauss++)
476 const PointOfField& currentPt = points[itElt * numGaussPointsByElt + itPtGauss];
478 if (currentPt.mVal > threshold)
487 // add index of the element to keep (index must start at 1)
488 elementsToKeep[meshIt].insert(med_int(itElt + 1));
491 if (field->isFieldOnNodes())
496 //---------------------------------------------------------------------
497 // Create the final mesh by extracting elements to keep from the current mesh
498 //---------------------------------------------------------------------
499 Mesh* newMesh = NULL;
500 if (field && field->isFieldOnNodes())
502 std::set<med_int> setOfElts[eMaxMedMesh];
504 for (meshIt = 0; meshIt < eMaxMedMesh; ++meshIt)
506 if (pMesh->getElements(meshIt) != NULL)
508 pMesh->getElements(meshIt)->extractSubSetFromNodes(elementsToKeep[0], setOfElts[meshIt]);
511 newMesh = pMesh->createFromSetOfElements(setOfElts, pNameNewMesh);
515 newMesh = pMesh->createFromSetOfElements(elementsToKeep, pNameNewMesh);
521 } // namespace multipr