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_PointOfField.hxx"
22 #include "MULTIPR_DecimationAccel.hxx"
23 #include "MULTIPR_Exceptions.hxx"
34 //*****************************************************************************
35 // Class DecimationFilter implementation
36 //*****************************************************************************
38 // Factory used to build all filters from their name.
39 DecimationFilter* DecimationFilter::create(const char* pFilterName)
41 if (pFilterName == NULL) throw NullArgumentException("filter name should not be NULL", __FILE__, __LINE__);
43 if (strcmp(pFilterName, "Filtre_GradientMoyen") == 0)
45 return new DecimationFilterGradAvg();
49 throw IllegalArgumentException("unknown filter", __FILE__, __LINE__);
54 //*****************************************************************************
55 // Class DecimationFilterGradAvg
56 //*****************************************************************************
58 DecimationFilterGradAvg::DecimationFilterGradAvg()
64 DecimationFilterGradAvg::~DecimationFilterGradAvg()
70 Mesh* DecimationFilterGradAvg::apply(Mesh* pMesh, const char* pArgv, const char* pNameNewMesh)
72 //---------------------------------------------------------------------
73 // Retrieve and check parameters
74 //---------------------------------------------------------------------
75 if (pMesh == NULL) throw NullArgumentException("pMesh should not be NULL", __FILE__, __LINE__);
76 if (pArgv == NULL) throw NullArgumentException("pArgv should not be NULL", __FILE__, __LINE__);
77 if (pNameNewMesh == NULL) throw NullArgumentException("pNameNewMesh should not be NULL", __FILE__, __LINE__);
79 char fieldName[MED_TAILLE_NOM + 1];
83 int boxing; // number of cells along axis (if 100 then grid will have 100*100*100 = 10**6 cells)
85 int ret = sscanf(pArgv, "%s %d %lf %lf %d",
92 if (ret != 5) throw IllegalArgumentException("wrong number of arguments for filter GradAvg; expected 5 parameters", __FILE__, __LINE__);
94 //---------------------------------------------------------------------
95 // Retrieve field = for each point: get its coordinate and the value of the field
96 //---------------------------------------------------------------------
97 Field* field = pMesh->getFieldByName(fieldName);
99 if (field == NULL) throw IllegalArgumentException("field not found", __FILE__, __LINE__);
100 if ((fieldIt < 1) || (fieldIt > field->getNumberOfTimeSteps())) throw IllegalArgumentException("invalid field iteration", __FILE__, __LINE__);
102 vector<PointOfField> points;
103 pMesh->getAllPointsOfField(field, fieldIt, points);
105 //---------------------------------------------------------------------
106 // Creates acceleration structure used to compute gradient
107 //---------------------------------------------------------------------
108 DecimationAccel* accel = new DecimationAccelGrid();
109 char strCfg[256]; // a string is used for genericity
110 sprintf(strCfg, "%d %d %d", boxing, boxing, boxing);
111 accel->configure(strCfg);
112 accel->create(points);
114 //---------------------------------------------------------------------
115 // Collects elements of the mesh to be kept
116 //---------------------------------------------------------------------
117 set<int> elementsToKeep;
119 int numElements = pMesh->getNumberOfElements();
120 int numGaussPointsByElt = points.size() / numElements; // for a TETRA10, should be 5 for a field of elements and 10 for a field of nodes
123 for (int itElt = 0 ; itElt < numElements ; itElt++)
125 bool keepElement = false;
127 // for each Gauss point of the current element
128 for (int itPtGauss = 0 ; itPtGauss < numGaussPointsByElt ; itPtGauss++)
130 const PointOfField& currentPt = points[itElt * numGaussPointsByElt + itPtGauss];
132 vector<PointOfField> neighbours = accel->findNeighbours(
138 // if no neighbours => keep element
139 if (neighbours.size() == 0)
145 // otherwise compute gradient...
146 med_float normGrad = computeNormGrad(currentPt, neighbours);
149 //cout << (itElt * numGaussPointsByElt + j) << ": " << normGrad << endl;
151 if ((normGrad >= threshold) || isnan(normGrad))
160 // add index of the element to keep (index must start at 1)
161 elementsToKeep.insert(itElt + 1);
165 //---------------------------------------------------------------------
167 //---------------------------------------------------------------------
170 //---------------------------------------------------------------------
171 // Create the final mesh by extracting elements to keep from the current mesh
172 //---------------------------------------------------------------------
173 Mesh* newMesh = pMesh->createFromSetOfElements(elementsToKeep, pNameNewMesh);
179 void DecimationFilterGradAvg::getGradientInfo(
181 const char* pFieldName,
189 if (pMesh == NULL) throw NullArgumentException("pMesh should not be NULL", __FILE__, __LINE__);
190 if (pFieldName == NULL) throw NullArgumentException("pFieldName should not be NULL", __FILE__, __LINE__);
192 Field* field = pMesh->getFieldByName(pFieldName);
194 if (field == NULL) throw IllegalArgumentException("field not found", __FILE__, __LINE__);
195 if ((pFieldIt < 1) || (pFieldIt > field->getNumberOfTimeSteps())) throw IllegalArgumentException("invalid field iteration", __FILE__, __LINE__);
197 vector<PointOfField> points;
198 pMesh->getAllPointsOfField(field, pFieldIt, points);
200 //---------------------------------------------------------------------
201 // Creates acceleration structure used to compute gradient
202 //---------------------------------------------------------------------
203 DecimationAccel* accel = new DecimationAccelGrid();
204 char strCfg[256]; // a string is used for genericity
205 sprintf(strCfg, "%d %d %d", pBoxing, pBoxing, pBoxing);
206 accel->configure(strCfg);
207 accel->create(points);
209 //---------------------------------------------------------------------
210 // Collects elements of the mesh to be kept
211 //---------------------------------------------------------------------
213 int numElements = pMesh->getNumberOfElements();
214 int numGaussPointsByElt = points.size() / numElements; // for a TETRA10, should be 5 for a field of elements and 10 for a field of nodes
216 *pOutGradMax = -1e300;
217 *pOutGradMin = 1e300;
221 //cout << "numElements=" << numElements << endl;
222 //cout << "num gauss pt by elt=" << numGaussPointsByElt << endl;
225 for (int itElt = 0 ; itElt < numElements ; itElt++)
227 // for each Gauss point of the current element
228 for (int itPtGauss = 0 ; itPtGauss < numGaussPointsByElt ; itPtGauss++)
230 const PointOfField& currentPt = points[itElt * numGaussPointsByElt + itPtGauss];
232 vector<PointOfField> neighbours = accel->findNeighbours(
238 // if no neighbours => keep element
239 if (neighbours.size() == 0)
244 // otherwise compute gradient...
245 med_float normGrad = computeNormGrad(currentPt, neighbours);
248 //cout << (itElt * numGaussPointsByElt + j) << ": " << normGrad << endl;
250 if (!isnan(normGrad))
252 if (normGrad > *pOutGradMax) *pOutGradMax = normGrad;
253 if (normGrad < *pOutGradMin) *pOutGradMin = normGrad;
254 *pOutGradAvg += normGrad;
260 if (count != 0) *pOutGradAvg /= double(count);
262 //---------------------------------------------------------------------
264 //---------------------------------------------------------------------
269 med_float DecimationFilterGradAvg::computeNormGrad(const PointOfField& pPt, const std::vector<PointOfField>& pNeighbours) const
271 med_float gradX = 0.0;
272 med_float gradY = 0.0;
273 med_float gradZ = 0.0;
275 // for each neighbour
276 for (unsigned i = 0 ; i < pNeighbours.size() ; i++)
278 const PointOfField& neighbourPt = pNeighbours[i];
280 med_float vecX = neighbourPt.mXYZ[0] - pPt.mXYZ[0];
281 med_float vecY = neighbourPt.mXYZ[1] - pPt.mXYZ[1];
282 med_float vecZ = neighbourPt.mXYZ[2] - pPt.mXYZ[2];
284 med_float norm = med_float( sqrt( vecX*vecX + vecY*vecY + vecZ*vecZ ) );
285 med_float val = neighbourPt.mVal - pPt.mVal;
294 med_float invSize = 1.0 / med_float(pNeighbours.size());
300 med_float norm = med_float( sqrt( gradX*gradX + gradY*gradY + gradZ*gradZ ) );
307 } // namespace multipr