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_DecimationFilter.cxx
24 * \brief see MULTIPR_DecimationFilter.hxx
26 * \author Olivier LE ROUX - CS, Virtual Reality Dpt
31 //*****************************************************************************
33 //*****************************************************************************
35 #include "MULTIPR_DecimationFilter.hxx"
36 #include "MULTIPR_Field.hxx"
37 #include "MULTIPR_Mesh.hxx"
38 #include "MULTIPR_Nodes.hxx"
39 #include "MULTIPR_Elements.hxx"
40 #include "MULTIPR_Profil.hxx"
41 #include "MULTIPR_PointOfField.hxx"
42 #include "MULTIPR_DecimationAccel.hxx"
43 #include "MULTIPR_Exceptions.hxx"
54 //*****************************************************************************
55 // Class DecimationFilter implementation
56 //*****************************************************************************
58 // Factory used to build all filters from their name.
59 DecimationFilter* DecimationFilter::create(const char* pFilterName)
61 if (pFilterName == NULL) throw NullArgumentException("filter name should not be NULL", __FILE__, __LINE__);
63 if (strcmp(pFilterName, "Filtre_GradientMoyen") == 0)
65 return new DecimationFilterGradAvg();
67 else if (strcmp(pFilterName, "Filtre_Direct") == 0)
69 return new DecimationFilterTreshold();
73 throw IllegalArgumentException("unknown filter", __FILE__, __LINE__);
78 //*****************************************************************************
79 // Class DecimationFilterGradAvg
80 //*****************************************************************************
82 DecimationFilterGradAvg::DecimationFilterGradAvg()
88 DecimationFilterGradAvg::~DecimationFilterGradAvg()
94 Mesh* DecimationFilterGradAvg::apply(Mesh* pMesh, const char* pArgv, const char* pNameNewMesh)
96 //---------------------------------------------------------------------
97 // Retrieve and check parameters
98 //---------------------------------------------------------------------
99 if (pMesh == NULL) throw NullArgumentException("pMesh should not be NULL", __FILE__, __LINE__);
100 if (pArgv == NULL) throw NullArgumentException("pArgv should not be NULL", __FILE__, __LINE__);
101 if (pNameNewMesh == NULL) throw NullArgumentException("pNameNewMesh should not be NULL", __FILE__, __LINE__);
103 char fieldName[MED_TAILLE_NOM + 1];
108 int boxing; // number of cells along axis (if 100 then grid will have 100*100*100 = 10**6 cells)
109 set<med_int> elementsToKeep[eMaxMedMesh];
112 int ret = sscanf(pArgv, "%s %d %lf %lf %d",
118 if (ret != 5) throw IllegalArgumentException("wrong number of arguments for filter GradAvg; expected 5 parameters", __FILE__, __LINE__);
120 for (meshIt = 0; meshIt < eMaxMedMesh; ++meshIt)
123 //---------------------------------------------------------------------
124 // Retrieve field = for each point: get its coordinate and the value of the field
125 //---------------------------------------------------------------------
126 field = pMesh->getFieldByName(fieldName, (eMeshType)meshIt);
128 if (field == NULL) continue;
129 if ((fieldIt < 1) || (fieldIt > field->getNumberOfTimeSteps())) throw IllegalArgumentException("invalid field iteration", __FILE__, __LINE__);
131 vector<PointOfField> points;
132 pMesh->getAllPointsOfField(field, fieldIt, points, (eMeshType)meshIt);
134 //---------------------------------------------------------------------
135 // Creates acceleration structure used to compute gradient
136 //---------------------------------------------------------------------
137 DecimationAccel* accel = new DecimationAccelGrid();
138 char strCfg[256]; // a string is used for genericity
139 sprintf(strCfg, "%d %d %d", boxing, boxing, boxing);
140 accel->configure(strCfg);
141 accel->create(points);
143 //---------------------------------------------------------------------
144 // Collects elements of the mesh to be kept
145 //---------------------------------------------------------------------
147 if (field->isFieldOnNodes())
149 numElements = pMesh->getNodes()->getNumberOfNodes();
153 numElements = pMesh->getNumberOfElements((eMeshType)meshIt);
155 if (field->getProfil(fieldIt).size() != 0)
157 Profil* profil = pMesh->getProfil(field->getProfil(fieldIt));
158 if (profil == NULL) throw IllegalStateException("Can't find the profile in the mesh.", __FILE__, __LINE__);
159 numElements = profil->getSet().size();
162 int numGaussPointsByElt = 0;
163 if (field->isFieldOnNodes())
165 numGaussPointsByElt = 1;
169 numGaussPointsByElt = points.size() / numElements;
173 for (int itElt = 0 ; itElt < numElements ; itElt++)
175 bool keepElement = false;
177 // for each Gauss point of the current element
178 for (int itPtGauss = 0 ; itPtGauss < numGaussPointsByElt ; itPtGauss++)
180 const PointOfField& currentPt = points[itElt * numGaussPointsByElt + itPtGauss];
182 vector<PointOfField> neighbours = accel->findNeighbours(
188 // if no neighbours => keep element
189 if (neighbours.size() == 0)
195 // otherwise compute gradient...
196 med_float normGrad = computeNormGrad(currentPt, neighbours);
199 //cout << (itElt * numGaussPointsByElt + j) << ": " << normGrad << endl;
201 if ((normGrad >= threshold) || isnan(normGrad))
210 // add index of the element to keep (index must start at 1)
211 elementsToKeep[meshIt].insert(med_int(itElt + 1));
215 //---------------------------------------------------------------------
217 //---------------------------------------------------------------------
220 if (field->isFieldOnNodes())
226 //---------------------------------------------------------------------
227 // Create the final mesh by extracting elements to keep from the current mesh
228 //---------------------------------------------------------------------
229 Mesh* newMesh = NULL;
230 if (field && field->isFieldOnNodes())
232 std::set<med_int> setOfElts[eMaxMedMesh];
234 for (meshIt = 0; meshIt < eMaxMedMesh; ++meshIt)
236 if (pMesh->getElements(meshIt) != NULL)
238 pMesh->getElements(meshIt)->extractSubSetFromNodes(elementsToKeep[0], setOfElts[meshIt]);
241 newMesh = pMesh->createFromSetOfElements(setOfElts, pNameNewMesh);
245 newMesh = pMesh->createFromSetOfElements(elementsToKeep, pNameNewMesh);
252 void DecimationFilterGradAvg::getGradientInfo(
254 const char* pFieldName,
262 if (pMesh == NULL) throw NullArgumentException("pMesh should not be NULL", __FILE__, __LINE__);
263 if (pFieldName == NULL) throw NullArgumentException("pFieldName should not be NULL", __FILE__, __LINE__);
265 for (int meshIt = 0; meshIt < eMaxMedMesh; ++meshIt)
268 //---------------------------------------------------------------------
269 // Retrieve field = for each point: get its coordinate and the value of the field
270 //---------------------------------------------------------------------
271 Field* field = pMesh->getFieldByName(pFieldName, (eMeshType)meshIt);
273 if (field == NULL) continue;
274 if ((pFieldIt < 1) || (pFieldIt > field->getNumberOfTimeSteps())) throw IllegalArgumentException("invalid field iteration", __FILE__, __LINE__);
276 vector<PointOfField> points;
277 pMesh->getAllPointsOfField(field, pFieldIt, points, (eMeshType)meshIt);
279 //---------------------------------------------------------------------
280 // Creates acceleration structure used to compute gradient
281 //---------------------------------------------------------------------
282 DecimationAccel* accel = new DecimationAccelGrid();
283 char strCfg[256]; // a string is used for genericity
284 sprintf(strCfg, "%d %d %d", pBoxing, pBoxing, pBoxing);
285 accel->configure(strCfg);
286 accel->create(points);
288 //---------------------------------------------------------------------
289 // Collects elements of the mesh to be kept
290 //---------------------------------------------------------------------
292 if (field->isFieldOnNodes())
294 numElements = pMesh->getNodes()->getNumberOfNodes();
298 numElements = pMesh->getNumberOfElements((eMeshType)meshIt);
300 if (field->getProfil(pFieldIt).size() != 0)
302 Profil* profil = pMesh->getProfil(field->getProfil(pFieldIt));
303 if (profil == NULL) throw IllegalStateException("Can't find the profile in the mesh.", __FILE__, __LINE__);
304 numElements = profil->getSet().size();
307 int numGaussPointsByElt = 0;
308 if (field->isFieldOnNodes())
310 numGaussPointsByElt = 1;
314 numGaussPointsByElt = points.size() / numElements;
317 *pOutGradMax = -1e300;
318 *pOutGradMin = 1e300;
323 for (int itElt = 0 ; itElt < numElements ; itElt++)
325 // for each Gauss point of the current element
326 for (int itPtGauss = 0 ; itPtGauss < numGaussPointsByElt ; itPtGauss++)
328 const PointOfField& currentPt = points[itElt * numGaussPointsByElt + itPtGauss];
330 vector<PointOfField> neighbours = accel->findNeighbours(
336 // if no neighbours => keep element
337 if (neighbours.size() == 0)
342 // otherwise compute gradient...
343 med_float normGrad = computeNormGrad(currentPt, neighbours);
346 //cout << (itElt * numGaussPointsByElt + j) << ": " << normGrad << endl;
348 if (!isnan(normGrad))
350 if (normGrad > *pOutGradMax) *pOutGradMax = normGrad;
351 if (normGrad < *pOutGradMin) *pOutGradMin = normGrad;
352 *pOutGradAvg += normGrad;
358 if (count != 0) *pOutGradAvg /= double(count);
360 //---------------------------------------------------------------------
362 //---------------------------------------------------------------------
364 if (field->isFieldOnNodes())
372 med_float DecimationFilterGradAvg::computeNormGrad(const PointOfField& pPt, const std::vector<PointOfField>& pNeighbours) const
374 med_float gradX = 0.0;
375 med_float gradY = 0.0;
376 med_float gradZ = 0.0;
378 // for each neighbour
379 for (unsigned i = 0 ; i < pNeighbours.size() ; i++)
381 const PointOfField& neighbourPt = pNeighbours[i];
383 med_float vecX = neighbourPt.mXYZ[0] - pPt.mXYZ[0];
384 med_float vecY = neighbourPt.mXYZ[1] - pPt.mXYZ[1];
385 med_float vecZ = neighbourPt.mXYZ[2] - pPt.mXYZ[2];
387 med_float norm = med_float( sqrt( vecX*vecX + vecY*vecY + vecZ*vecZ ) );
388 med_float val = neighbourPt.mVal - pPt.mVal;
397 med_float invSize = 1.0 / med_float(pNeighbours.size());
403 med_float norm = med_float( sqrt( gradX*gradX + gradY*gradY + gradZ*gradZ ) );
409 //*****************************************************************************
410 // Class DecimationFilterGradAvg
411 //*****************************************************************************
413 DecimationFilterTreshold::DecimationFilterTreshold()
419 DecimationFilterTreshold::~DecimationFilterTreshold()
425 Mesh* DecimationFilterTreshold::apply(Mesh* pMesh, const char* pArgv, const char* pNameNewMesh)
427 if (pMesh == NULL) throw NullArgumentException("pMesh should not be NULL", __FILE__, __LINE__);
428 if (pArgv == NULL) throw NullArgumentException("pArgv should not be NULL", __FILE__, __LINE__);
429 if (pNameNewMesh == NULL) throw NullArgumentException("pNameNewMesh should not be NULL", __FILE__, __LINE__);
431 char fieldName[MED_TAILLE_NOM + 1];
435 set<med_int> elementsToKeep[eMaxMedMesh];
438 int ret = sscanf(pArgv, "%s %d %lf",
443 if (ret != 3) throw IllegalArgumentException("wrong number of arguments for filter Treshold; expected 3 parameters", __FILE__, __LINE__);
445 for (meshIt = 0; meshIt < eMaxMedMesh; ++meshIt)
447 //---------------------------------------------------------------------
448 // Retrieve field = for each point: get its coordinate and the value of the field
449 //---------------------------------------------------------------------
450 field = pMesh->getFieldByName(fieldName, (eMeshType)meshIt);
451 if (field == NULL) continue;
452 if ((fieldIt < 1) || (fieldIt > field->getNumberOfTimeSteps())) throw IllegalArgumentException("invalid field iteration", __FILE__, __LINE__);
454 vector<PointOfField> points;
455 pMesh->getAllPointsOfField(field, fieldIt, points, (eMeshType)meshIt);
457 //---------------------------------------------------------------------
458 // Collects elements of the mesh to be kept
459 //---------------------------------------------------------------------
461 if (field->isFieldOnNodes())
463 numElements = pMesh->getNodes()->getNumberOfNodes();
467 numElements = pMesh->getNumberOfElements((eMeshType)meshIt);
469 if (field->getProfil(fieldIt).size() != 0)
471 Profil* profil = pMesh->getProfil(field->getProfil(fieldIt));
472 if (profil == NULL) throw IllegalStateException("Can't find the profile in the mesh.", __FILE__, __LINE__);
473 numElements = profil->getSet().size();
476 int numGaussPointsByElt = 0;
477 if (field->isFieldOnNodes())
479 numGaussPointsByElt = 1;
483 numGaussPointsByElt = points.size() / numElements;
486 for (int itElt = 0 ; itElt < numElements ; itElt++)
488 bool keepElement = false;
490 // for each Gauss point of the current element
491 for (int itPtGauss = 0 ; itPtGauss < numGaussPointsByElt ; itPtGauss++)
493 const PointOfField& currentPt = points[itElt * numGaussPointsByElt + itPtGauss];
495 if (currentPt.mVal > threshold)
504 // add index of the element to keep (index must start at 1)
505 elementsToKeep[meshIt].insert(med_int(itElt + 1));
508 if (field->isFieldOnNodes())
513 //---------------------------------------------------------------------
514 // Create the final mesh by extracting elements to keep from the current mesh
515 //---------------------------------------------------------------------
516 Mesh* newMesh = NULL;
517 if (field && field->isFieldOnNodes())
519 std::set<med_int> setOfElts[eMaxMedMesh];
521 for (meshIt = 0; meshIt < eMaxMedMesh; ++meshIt)
523 if (pMesh->getElements(meshIt) != NULL)
525 pMesh->getElements(meshIt)->extractSubSetFromNodes(elementsToKeep[0], setOfElts[meshIt]);
528 newMesh = pMesh->createFromSetOfElements(setOfElts, pNameNewMesh);
532 newMesh = pMesh->createFromSetOfElements(elementsToKeep, pNameNewMesh);
538 } // namespace multipr