Salome HOME
Small source code improvement
[modules/visu.git] / src / PIPELINE / VISU_Extractor.cxx
index 575f787d4c33997cb086b1558fcce5bf6d5e0a76..20b64e1e79aa60df3bfa3d5533fbda7ccc86cfea 100644 (file)
@@ -1,24 +1,25 @@
-//  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2011  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
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
 //
-//  This library is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU Lesser General Public
-//  License as published by the Free Software Foundation; either
-//  version 2.1 of the License.
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
 //
-//  This library is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  Lesser General Public License for more details.
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
 //
-//  You should have received a copy of the GNU Lesser General Public
-//  License along with this library; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
-//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
+
 //  VISU OBJECT : interactive object for VISU entities implementation
 //  File   : VISU_Extractor.cxx
 //  Module : VISU
 #include "VISU_ConvertorUtils.hxx"
 #include "VISU_MeshValue.hxx"
 
+#include <SUIT_Session.h>
+#include <SUIT_ResourceMgr.h>
+
 #include <sstream>
+#include <cmath> // to use std::abs( int )
 
 #include <vtkObjectFactory.h>
 #include <vtkUnstructuredGrid.h>
 #include <vtkInformation.h>
 #include <vtkInformationVector.h>
 
-
+// Algorithm to cut values (see CutValue())
+// Use sprintf function
+#define USE_SPRINTF
+// Use new algorithm (works only when USE_SPRINTF is disabled)
+#define USE_NEW_ALGORITHM
 
 //----------------------------------------------------------------------------
 vtkStandardNewMacro(VISU_Extractor);
@@ -97,59 +106,145 @@ VISU_Extractor
   return myGaussMetric;
 }
 
+//----------------------------------------------------------------------------
+vtkFloatingPointType CutValue (vtkFloatingPointType theValue, int theDecimals)
+{
+  vtkFloatingPointType v = theValue;
+
+#if defined(USE_SPRINTF)
+  char aFormat[16];
+  sprintf(aFormat, "%%.%dg", theDecimals);
+  char aStr [256];
+  sprintf(aStr, aFormat, theValue);
+  v = atof(aStr);
+#elif defined(USE_NEW_ALGORITHM)
+  //
+  // VSR 19/10/2009: new algorithm does not use long long type
+  //
+  long n1 = 0;
+  // calculate order of the integral part
+  while ( v > 1. ) {
+    v = v / 10.;
+    n1++;
+  }
+  // calculate length of the fractional part
+  long n2 = theDecimals - n1;
+  v = theValue;
+  if ( n2 > 0 )
+    while ( n2-- > 0 ) v = v * 10.;
+  else
+    while ( n2++ < 0 ) v = v / 10.;
+  v = floor( (double) v );
+  n2 = theDecimals - n1;
+  if ( n2 > 0 )
+    while ( n2-- > 0 ) v = v / 10.;
+  else
+    while ( n2++ < 0 ) v = v * 10.;
+#else
+  //
+  // VSR 19/10/2009: old algorithm uses long long type -
+  // causes incompatibility with some platforms (Windows?)
+  //
+  vtkFloatingPointType aDegree = 0.0;
+  if (abs((long long)v) > 1)
+    aDegree = (long long)log10((double)abs((long long)v)) + 1;
+  aDegree = theDecimals - aDegree;
+  //printf("$$$ 1 v = %.20g , aDegree = %lld \n", v, (long long)aDegree);
+
+  aDegree = pow(10, aDegree);
+  v = ((vtkFloatingPointType)((long long)(v * aDegree))) / aDegree;
+  //printf("$$$ 2 v = %.20g , aDegree = %lld \n", v, (long long)aDegree);
+#endif
+
+  return v;
+}
 
 //----------------------------------------------------------------------------
-template<typename TValueType> 
+template<typename TValueType>
 void
 Module2Scalars(vtkDataArray *theInputDataArray,
-              TValueType* theOutputPtr,
-              vtkIdType theNbOfTuples)
+               TValueType* theOutputPtr,
+               vtkIdType theNbOfTuples)
 {
   vtkIdType aNbComp = theInputDataArray->GetNumberOfComponents();
   std::vector<vtkFloatingPointType> anArray(aNbComp < 3? 3: aNbComp);
   for(vtkIdType aTupleId = 0; aTupleId < theNbOfTuples; aTupleId++){
     theInputDataArray->GetTuple(aTupleId, &anArray[0]);
     vtkFloatingPointType aVector[3] = {anArray[0], anArray[1], anArray[2]};
-    vtkFloatingPointType aScalar = sqrt(aVector[0]*aVector[0] + 
-                                       aVector[1]*aVector[1] + 
-                                       aVector[2]*aVector[2]);
+    vtkFloatingPointType aScalar = sqrt(aVector[0]*aVector[0] +
+                                        aVector[1]*aVector[1] +
+                                        aVector[2]*aVector[2]);
     *theOutputPtr = TValueType(aScalar);
     theOutputPtr++;
   }
 }
 
+template<typename TValueType>
+void
+Module2ScalarsMOD(vtkDataArray *theInputDataArray,
+                  TValueType* theOutputPtr,
+                  vtkIdType theNbOfTuples,
+                  VISU::TGaussMetric theGaussMetric)
+{
+  vtkIdType aNbComp = theInputDataArray->GetNumberOfComponents();
+  if (aNbComp != 3) // Min, Max, Avg
+    return;
+  std::vector<vtkFloatingPointType> anArray (3);
+  for (vtkIdType aTupleId = 0; aTupleId < theNbOfTuples; aTupleId++) {
+    theInputDataArray->GetTuple(aTupleId, &anArray[0]);
+    switch (theGaussMetric) {
+      case VISU::MINIMUM_METRIC: *theOutputPtr = TValueType(anArray[0]); break;
+      case VISU::MAXIMUM_METRIC: *theOutputPtr = TValueType(anArray[1]); break;
+      case VISU::AVERAGE_METRIC: *theOutputPtr = TValueType(anArray[2]); break;
+    }
+    theOutputPtr++;
+  }
+}
+
 
 //----------------------------------------------------------------------------
-template<typename TValueType> 
+template<typename TValueType>
 void
 Component2Scalars(vtkDataArray *theInputDataArray,
-                 TValueType* theInputPtr,
-                 TValueType* theOutputPtr,
-                 vtkIdType theNbOfTuples,
-                 vtkIdType theComponentId)
+                  TValueType* theInputPtr,
+                  TValueType* theOutputPtr,
+                  vtkIdType theNbOfTuples,
+                  vtkIdType theComponentId)
 {
   vtkIdType aNbComp = theInputDataArray->GetNumberOfComponents();
-  for(vtkIdType aTupleId = 0; aTupleId < theNbOfTuples; aTupleId++){
+  for (vtkIdType aTupleId = 0; aTupleId < theNbOfTuples; aTupleId++) {
     *theOutputPtr = *(theInputPtr + theComponentId);
     theInputPtr += aNbComp;
     theOutputPtr++;
   }
 }
 
+//----------------------------------------------------------------------------
+template<typename TValueType>
+void
+CutScalarsTempl(TValueType* theDataPtr,
+                vtkIdType theNbOfTuples,
+                int theDecimals)
+{
+  for (vtkIdType aTupleId = 0; aTupleId < theNbOfTuples; aTupleId++) {
+    *theDataPtr = TValueType(CutValue(*theDataPtr, theDecimals));
+    theDataPtr++;
+  }
+}
 
 //----------------------------------------------------------------------------
 template<typename TDataSetAttributesType> void
-ExecuteScalars(vtkIdType theNbOfTuples, 
-              vtkIdType theScalarMode, 
-              VISU::TGaussMetric theGaussMetric, 
-              TDataSetAttributesType* theInputData, 
-              TDataSetAttributesType* theOutputData)
+ExecuteScalars(vtkIdType theNbOfTuples,
+               vtkIdType theScalarMode,
+               VISU::TGaussMetric theGaussMetric,
+               TDataSetAttributesType* theInputData,
+               TDataSetAttributesType* theOutputData)
 {
-  if(theNbOfTuples < 1)
+  if (theNbOfTuples < 1)
     return;
 
   vtkDataArray* aFieldArray = NULL;
-  switch( theGaussMetric ) {
+  switch (theGaussMetric) {
     case VISU::AVERAGE_METRIC: aFieldArray = theInputData->GetArray("VISU_FIELD"); break;
     case VISU::MINIMUM_METRIC: aFieldArray = theInputData->GetArray("VISU_FIELD_GAUSS_MIN"); break;
     case VISU::MAXIMUM_METRIC: aFieldArray = theInputData->GetArray("VISU_FIELD_GAUSS_MAX"); break;
@@ -165,39 +260,81 @@ ExecuteScalars(vtkIdType theNbOfTuples,
   void *anInputPtr = aFieldArray->GetVoidPointer(0);
   void *anOutputPtr = anOutputScalars->GetVoidPointer(0);
 
-  if(theScalarMode == 0){
-    switch(anInputDataType){
-      vtkTemplateMacro3(Module2Scalars,
-                       aFieldArray,
-                       (VTK_TT *)(anOutputPtr), 
-                       theNbOfTuples);
-    default:
-      break;
+  if (theScalarMode == 0) {
+    vtkDataArray* aFieldArrayMOD = theInputData->GetArray("VISU_FIELD_GAUSS_MOD");
+    if (aFieldArrayMOD) {
+      switch (anInputDataType) {
+        vtkTemplateMacro4(Module2ScalarsMOD,
+                          aFieldArrayMOD,
+                          (VTK_TT *)(anOutputPtr),
+                          theNbOfTuples,
+                          theGaussMetric);
+      default:
+        break;
+      }
+    }
+    else {
+      switch (anInputDataType) {
+        vtkTemplateMacro3(Module2Scalars,
+                          aFieldArray,
+                          (VTK_TT *)(anOutputPtr),
+                          theNbOfTuples);
+      default:
+        break;
+      }
     }
-  }else{
-    switch(anInputDataType){
+  } else {
+    switch (anInputDataType) {
       vtkTemplateMacro5(Component2Scalars,
-                       aFieldArray,
-                       (VTK_TT *)(anInputPtr), 
-                       (VTK_TT *)(anOutputPtr),
-                       theNbOfTuples,
-                       theScalarMode - 1);
+                        aFieldArray,
+                        (VTK_TT *)(anInputPtr),
+                        (VTK_TT *)(anOutputPtr),
+                        theNbOfTuples,
+                        theScalarMode - 1);
     default:
       break;
     }
   }
-  
+
   theOutputData->SetScalars(anOutputScalars);
   anOutputScalars->Delete();
 }
 
+//---------------------------------------------------------------
+template<typename TDataSetAttributesType> void
+CutScalars(vtkIdType theNbOfTuples,
+           TDataSetAttributesType* theData)
+{
+  if (theNbOfTuples < 1)
+    return;
+
+  vtkDataArray *aScalars = theData->GetScalars();
+  if (!aScalars)
+    return;
+
+  vtkIdType aDataType = aScalars->GetDataType();
+  void *aPtr = aScalars->GetVoidPointer(0);
+
+  SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
+  // san: precision can be negative - this is used by double spin boxes
+  int aDecimals = std::abs( aResourceMgr->integerValue("VISU", "visual_data_precision", 6) );
+
+  switch(aDataType) {
+    vtkTemplateMacro3(CutScalarsTempl,
+                      (VTK_TT *)(aPtr),
+                      theNbOfTuples,
+                      aDecimals);
+  default:
+    break;
+  }
+}
 
 //---------------------------------------------------------------
 int
 VISU_Extractor
 ::RequestData(vtkInformation *theRequest,
-             vtkInformationVector **theInputVector,
-             vtkInformationVector *theOutputVector)
+              vtkInformationVector **theInputVector,
+              vtkInformationVector *theOutputVector)
 {
   vtkDataSet *anInput = VISU::GetInput( theInputVector, 0 );
   vtkDataSet *anOutput = VISU::GetOutput( theOutputVector );
@@ -206,20 +343,22 @@ VISU_Extractor
 
   vtkPointData *anInputPointData = anInput->GetPointData();
   vtkPointData *anOutputPointData = anOutput->GetPointData();
-  anOutputPointData->PassData( anInputPointData ); 
+  anOutputPointData->PassData( anInputPointData );
   if ( VISU::IsDataOnPoints( anInput ) ) {
     int aNbElems = anInput->GetNumberOfPoints();
     if ( anInputPointData->GetAttribute( vtkDataSetAttributes::VECTORS ) )
       ExecuteScalars( aNbElems, myScalarMode, myGaussMetric, anInputPointData, anOutputPointData );
+    CutScalars( aNbElems, anOutputPointData );
   }
-  
+
   vtkCellData *anInputCellData = anInput->GetCellData();
   vtkCellData *anOutputCellData = anOutput->GetCellData();
-  anOutputCellData->PassData( anInputCellData ); 
+  anOutputCellData->PassData( anInputCellData );
   if ( VISU::IsDataOnCells( anInput ) ) {
     int aNbElems = anInput->GetNumberOfCells();
     if ( anInputCellData->GetAttribute( vtkDataSetAttributes::VECTORS ) )
       ExecuteScalars( aNbElems, myScalarMode, myGaussMetric, anInputCellData, anOutputCellData );
+    CutScalars( aNbElems, anOutputCellData );
   }
 
   return 1;