Salome HOME
Merge from V5_1_main 14/05/2010
[modules/visu.git] / src / PIPELINE / VISU_Extractor.cxx
index 82eec5dc8f20800ae485bb562de52e91caafd486..c8ecf191e2d7532675bdc2e3bcf9628ac371c226 100644 (file)
@@ -1,6 +1,6 @@
-//  VISU OBJECT : interactive object for VISU entities implementation
+//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
 //
-//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+//  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
 //  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_Extractor.hxx"
 #include "VISU_PipeLineUtils.hxx"
+#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 <vtkFloatArray.h>
 #include <vtkPointData.h>
 #include <vtkCellData.h>
 #include <vector>
+#include <vtkInformation.h>
+#include <vtkInformationVector.h>
 
-using namespace std;
-
+#define USE_SPRINTF 1
 
+//----------------------------------------------------------------------------
 vtkStandardNewMacro(VISU_Extractor);
 
-VISU_Extractor::VISU_Extractor()
+//----------------------------------------------------------------------------
+VISU_Extractor
+::VISU_Extractor():
+  myScalarMode(1),
+  myGaussMetric(VISU::AVERAGE_METRIC)
 {
-  myScalarMode = 1;
 }
 
-VISU_Extractor::~VISU_Extractor()
+
+//----------------------------------------------------------------------------
+VISU_Extractor
+::~VISU_Extractor()
 {}
 
-void VISU_Extractor::SetScalarMode(int theScalarMode)
+
+//----------------------------------------------------------------------------
+void
+VISU_Extractor
+::SetScalarMode(int theScalarMode)
 {
   if(myScalarMode != theScalarMode){
     myScalarMode = theScalarMode;
@@ -56,65 +74,292 @@ void VISU_Extractor::SetScalarMode(int theScalarMode)
   }
 }
 
-template<typename TypeData> void
-execute(int theNbElems, 
-       int theScalarMode, 
-       TypeData* theInputData, 
-       TypeData* theOutputData)
+//----------------------------------------------------------------------------
+int
+VISU_Extractor
+::GetScalarMode()
+{
+  return myScalarMode;
+}
+
+
+//----------------------------------------------------------------------------
+void
+VISU_Extractor
+::SetGaussMetric(VISU::TGaussMetric theGaussMetric)
+{
+  if(myGaussMetric != theGaussMetric){
+    myGaussMetric = theGaussMetric;
+    Modified();
+  }
+}
+
+//----------------------------------------------------------------------------
+VISU::TGaussMetric
+VISU_Extractor
+::GetGaussMetric()
 {
-  if(theNbElems < 1 )
+  return myGaussMetric;
+}
+
+//----------------------------------------------------------------------------
+vtkFloatingPointType CutValue (vtkFloatingPointType theValue, int theDecimals)
+{
+  vtkFloatingPointType v = theValue;
+
+#ifdef USE_SPRINTF
+  char aFormat[16];
+  sprintf(aFormat, "%%.%dg", theDecimals);
+  char aStr [256];
+  sprintf(aStr, aFormat, theValue);
+  v = atof(aStr);
+#else
+
+#ifndef USE_OLD_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
+
+#endif
+
+  return v;
+}
+
+//----------------------------------------------------------------------------
+template<typename TValueType>
+void
+Module2Scalars(vtkDataArray *theInputDataArray,
+               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]);
+    *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;
-  vtkDataArray* aFieldArray = theInputData->GetArray("VISU_FIELD");
-  if(vtkFloatArray *aFloatArray = dynamic_cast<vtkFloatArray*>(aFieldArray)){
-    int aNbComp = aFloatArray->GetNumberOfComponents();
-    std::vector<vtkFloatingPointType> anArray(aNbComp < 3? 3: aNbComp);
-    //
-    vtkFloatArray *aScalars = vtkFloatArray::New();
-    aScalars->SetNumberOfTuples(theNbElems);
-    aScalars->SetNumberOfComponents(1);
-    //
-    if(!theScalarMode){
-      for(int anId = 0; anId < theNbElems; anId++){
-       aFloatArray->GetTuple(anId,&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]);
-       aScalars->SetTuple1(anId,aScalar);
+  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>
+void
+Component2Scalars(vtkDataArray *theInputDataArray,
+                  TValueType* theInputPtr,
+                  TValueType* theOutputPtr,
+                  vtkIdType theNbOfTuples,
+                  vtkIdType theComponentId)
+{
+  vtkIdType aNbComp = theInputDataArray->GetNumberOfComponents();
+  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)
+{
+  if (theNbOfTuples < 1)
+    return;
+
+  vtkDataArray* aFieldArray = NULL;
+  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;
+  }
+  if( !aFieldArray )
+    return;
+
+  vtkIdType anInputDataType = aFieldArray->GetDataType();
+  vtkDataArray *anOutputScalars = vtkDataArray::CreateDataArray(anInputDataType);
+  anOutputScalars->SetNumberOfComponents(1);
+  anOutputScalars->SetNumberOfTuples(theNbOfTuples);
+
+  void *anInputPtr = aFieldArray->GetVoidPointer(0);
+  void *anOutputPtr = anOutputScalars->GetVoidPointer(0);
+
+  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{
-      for(int anId = 0; anId < theNbElems; anId++){
-       aFloatArray->GetTuple(anId,&anArray[0]);
-       aScalars->SetTuple1(anId,anArray[theScalarMode - 1]);
+    }
+    else {
+      switch (anInputDataType) {
+        vtkTemplateMacro3(Module2Scalars,
+                          aFieldArray,
+                          (VTK_TT *)(anOutputPtr),
+                          theNbOfTuples);
+      default:
+        break;
       }
     }
-    theOutputData->SetScalars(aScalars);
-    aScalars->Delete();
+  } else {
+    switch (anInputDataType) {
+      vtkTemplateMacro5(Component2Scalars,
+                        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;
   }
 }
 
-void VISU_Extractor::Execute(){
-  vtkDataSet *input = this->GetInput(), *output = this->GetOutput();
-  output->CopyStructure(input);
-  output->GetPointData()->CopyAllOff();
-  output->GetCellData()->CopyAllOff();
-  if(input->GetPointData()->GetNumberOfArrays()){
-    output->GetPointData()->CopyVectorsOn();
-    int aNbElems = input->GetNumberOfPoints();
-    vtkPointData *inData = input->GetPointData(), *outData = output->GetPointData();
-    if(inData->GetAttribute(vtkDataSetAttributes::VECTORS))
-      execute(aNbElems,myScalarMode,inData,outData);
-    else
-      output->GetPointData()->CopyScalarsOn();
-    outData->PassData(inData);
-    outData->AddArray(inData->GetArray("VISU_FIELD"));
-  }else{
-    output->GetCellData()->CopyVectorsOn();
-    int aNbElems = input->GetNumberOfCells();
-    vtkCellData *inData = input->GetCellData(), *outData = output->GetCellData();
-    if(inData->GetAttribute(vtkDataSetAttributes::VECTORS))
-      execute(aNbElems,myScalarMode,inData,outData);
-    else
-      output->GetCellData()->CopyScalarsOn();
-    outData->PassData(inData);
-    outData->AddArray(inData->GetArray("VISU_FIELD"));
+//---------------------------------------------------------------
+int
+VISU_Extractor
+::RequestData(vtkInformation *theRequest,
+              vtkInformationVector **theInputVector,
+              vtkInformationVector *theOutputVector)
+{
+  vtkDataSet *anInput = VISU::GetInput( theInputVector, 0 );
+  vtkDataSet *anOutput = VISU::GetOutput( theOutputVector );
+
+  anOutput->CopyStructure( anInput );
+
+  vtkPointData *anInputPointData = anInput->GetPointData();
+  vtkPointData *anOutputPointData = anOutput->GetPointData();
+  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 );
+  if ( VISU::IsDataOnCells( anInput ) ) {
+    int aNbElems = anInput->GetNumberOfCells();
+    if ( anInputCellData->GetAttribute( vtkDataSetAttributes::VECTORS ) )
+      ExecuteScalars( aNbElems, myScalarMode, myGaussMetric, anInputCellData, anOutputCellData );
+    CutScalars( aNbElems, anOutputCellData );
   }
+
+  return 1;
 }