Salome HOME
0020948: EDF 1468 SMESH: Histogram of the quality controls
[modules/smesh.git] / src / Controls / SMESH_Controls.cxx
index a9a3df7f88429a8dee179c6249490b2f9c5fe418..8e943469cbc237f7f9bcae60dcff62711bb28de1 100644 (file)
@@ -1,4 +1,4 @@
-//  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
+//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
@@ -19,6 +19,7 @@
 //
 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
+
 #include "SMESH_ControlsDef.hxx"
 
 #include <set>
@@ -276,6 +277,62 @@ double NumericalFunctor::GetValue( long theId )
   return 0.;
 }
 
+//================================================================================
+/*!
+ * \brief Return histogram of functor values
+ *  \param nbIntervals - number of intervals
+ *  \param nbEvents - number of mesh elements having values within i-th interval
+ *  \param funValues - boundaries of intervals
+ */
+//================================================================================
+
+void NumericalFunctor::GetHistogram(int                  nbIntervals,
+                                    std::vector<int>&    nbEvents,
+                                    std::vector<double>& funValues)
+{
+  if ( nbIntervals < 1 ||
+       !myMesh ||
+       !myMesh->GetMeshInfo().NbElements( GetType() ))
+    return;
+  nbEvents.resize( nbIntervals, 0 );
+  funValues.resize( nbIntervals+1 );
+
+  // get all values sorted
+  std::multiset< double > values;
+  SMDS_ElemIteratorPtr elemIt = myMesh->elementsIterator(GetType());
+  while ( elemIt->more() )
+    values.insert( GetValue( elemIt->next()->GetID() ));
+
+  // case nbIntervals == 1
+  funValues[0] = *values.begin();
+  funValues[nbIntervals] = *values.rbegin();
+  if ( nbIntervals == 1 )
+  {
+    nbEvents[0] = values.size();
+    return;
+  }
+  // case of 1 value
+  if (funValues.front() == funValues.back())
+  {
+    nbIntervals = 1;
+    nbEvents.resize( nbIntervals, values.size() );
+    funValues.resize( nbIntervals+1);
+  }
+  // generic case
+  std::multiset< double >::iterator min = values.begin(), max;
+  for ( int i = 0; i < nbIntervals; ++i )
+  {
+    double r = (i+1) / double( nbIntervals );
+    funValues[i+1] = funValues.front() * (1-r) + funValues.back() * r;
+    if ( min != values.end() && *min <= funValues[i+1] )
+    {
+      max = values.upper_bound( funValues[i+1] ); // greater than funValues[i+1], or end()
+      nbEvents[i] = std::distance( min, max );
+      min = max;
+    }
+  }
+}
+
 //=======================================================================
 //function : GetValue
 //purpose  : 
@@ -427,7 +484,7 @@ double AspectRatio::GetValue( const TSequenceOfXYZ& P )
 
     return ar;
   }
-  else { // nbNodes==8 - quadratic quadrangle
+  else if( nbNodes == 8 ){ // nbNodes==8 - quadratic quadrangle
     // return aspect ratio of the worst triange which can be built
     // taking three nodes of the quadrangle
     TSequenceOfXYZ triaPnts(3);
@@ -448,6 +505,7 @@ double AspectRatio::GetValue( const TSequenceOfXYZ& P )
 
     return ar;
   }
+  return 0;
 }
 
 double AspectRatio::GetBadRate( double Value, int /*nbNodes*/ ) const
@@ -963,16 +1021,20 @@ SMDSAbs_ElementType Skew::GetType() const
 */
 double Area::GetValue( const TSequenceOfXYZ& P )
 {
-  gp_Vec aVec1( P(2) - P(1) );
-  gp_Vec aVec2( P(3) - P(1) );
-  gp_Vec SumVec = aVec1 ^ aVec2;
-  for (int i=4; i<=P.size(); i++) {
-    gp_Vec aVec1( P(i-1) - P(1) );
-    gp_Vec aVec2( P(i) - P(1) );
-    gp_Vec tmp = aVec1 ^ aVec2;
-    SumVec.Add(tmp);
+  double val = 0.0;
+  if ( P.size() > 2 ) {
+    gp_Vec aVec1( P(2) - P(1) );
+    gp_Vec aVec2( P(3) - P(1) );
+    gp_Vec SumVec = aVec1 ^ aVec2;
+    for (int i=4; i<=P.size(); i++) {
+      gp_Vec aVec1( P(i-1) - P(1) );
+      gp_Vec aVec2( P(i) - P(1) );
+      gp_Vec tmp = aVec1 ^ aVec2;
+      SumVec.Add(tmp);
+    }
+    val = SumVec.Magnitude() * 0.5;
   }
-  return SumVec.Magnitude() * 0.5;
+  return val;
 }
 
 double Area::GetBadRate( double Value, int /*nbNodes*/ ) const