Salome HOME
Merge from V5_1_main 14/05/2010
[modules/visu.git] / src / PIPELINE / VISU_Extractor.cxx
index 683f8d6fc736b4bba25fb883ab78ccc87876757c..c8ecf191e2d7532675bdc2e3bcf9628ac371c226 100644 (file)
-//  VISU OBJECT : interactive object for VISU entities implementation
+//  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
+//
+//  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.
 //
-//  Copyright (C) 2003  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 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 
-// 
-//  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
+//  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
 //
+
+//  VISU OBJECT : interactive object for VISU entities implementation
 //  File   : VISU_Extractor.cxx
 //  Module : VISU
-
-#include "VISU_Extractor.hxx"   
+//
+#include "VISU_Extractor.hxx"
 #include "VISU_PipeLineUtils.hxx"
+#include "VISU_ConvertorUtils.hxx"
+#include "VISU_MeshValue.hxx"
 
-#include <sstream>     
+#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>
+
+#define USE_SPRINTF 1
+
+//----------------------------------------------------------------------------
+vtkStandardNewMacro(VISU_Extractor);
+
+//----------------------------------------------------------------------------
+VISU_Extractor
+::VISU_Extractor():
+  myScalarMode(1),
+  myGaussMetric(VISU::AVERAGE_METRIC)
+{
+}
+
+
+//----------------------------------------------------------------------------
+VISU_Extractor
+::~VISU_Extractor()
+{}
+
+
+//----------------------------------------------------------------------------
+void
+VISU_Extractor
+::SetScalarMode(int theScalarMode)
+{
+  if(myScalarMode != theScalarMode){
+    myScalarMode = theScalarMode;
+    Modified();
+  }
+}
+
+//----------------------------------------------------------------------------
+int
+VISU_Extractor
+::GetScalarMode()
+{
+  return myScalarMode;
+}
+
+
+//----------------------------------------------------------------------------
+void
+VISU_Extractor
+::SetGaussMetric(VISU::TGaussMetric theGaussMetric)
+{
+  if(myGaussMetric != theGaussMetric){
+    myGaussMetric = theGaussMetric;
+    Modified();
+  }
+}
+
+//----------------------------------------------------------------------------
+VISU::TGaussMetric
+VISU_Extractor
+::GetGaussMetric()
+{
+  return myGaussMetric;
+}
 
-using namespace std;
+//----------------------------------------------------------------------------
+vtkFloatingPointType CutValue (vtkFloatingPointType theValue, int theDecimals)
+{
+  vtkFloatingPointType v = theValue;
 
-#ifdef _DEBUG_
-static int MYDEBUG = 0;
+#ifdef USE_SPRINTF
+  char aFormat[16];
+  sprintf(aFormat, "%%.%dg", theDecimals);
+  char aStr [256];
+  sprintf(aStr, aFormat, theValue);
+  v = atof(aStr);
 #else
-static int MYDEBUG = 0;
+
+#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
 
-vtkStandardNewMacro(VISU_Extractor);
+  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++;
+  }
+}
 
-VISU_Extractor::VISU_Extractor(){
-  myScalarMode = 0;
+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++;
+  }
 }
 
-VISU_Extractor::~VISU_Extractor(){
+
+//----------------------------------------------------------------------------
+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++;
+  }
 }
 
-void VISU_Extractor::SetScalarMode(int theScalarMode){
-  if(myScalarMode != theScalarMode){
-    myScalarMode = theScalarMode;
-    Modified();
+//----------------------------------------------------------------------------
+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;
 
-template<typename TypeData> void
-execute(int theNbComp, int theScalarMode, TypeData* theInputData, TypeData* theOutputData){
-  vtkDataArray *inVectors = theInputData->GetVectors();
-  if ( !inVectors || theNbComp < 1 ) 
-    return; 
-  vtkFloatArray *newScalars = vtkFloatArray::New();
-  ostringstream aName;
-  aName<<inVectors->GetName();  aName<<", ";  aName<<theScalarMode;
-  newScalars->SetName(aName.str().c_str());
-  newScalars->SetNumberOfComponents(1);
-  newScalars->SetNumberOfTuples(theNbComp);
-  for (int ptId = 0; ptId < theNbComp; ptId++) {
-    float v[3], s;
-    inVectors->GetTuple(ptId,v);
-    if ( theScalarMode < 1 || theScalarMode > 3)
-      s = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
-    else
-      s = v[theScalarMode - 1];
-    newScalars->SetTuple1(ptId, s);
+  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 {
+      switch (anInputDataType) {
+        vtkTemplateMacro3(Module2Scalars,
+                          aFieldArray,
+                          (VTK_TT *)(anOutputPtr),
+                          theNbOfTuples);
+      default:
+        break;
+      }
+    }
+  } 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;
   }
-  theOutputData->SetScalars(newScalars);
-  //theOutputData->SetActiveScalars(newScalars->GetName());
-  newScalars->Delete();
 }
 
+//---------------------------------------------------------------
+int
+VISU_Extractor
+::RequestData(vtkInformation *theRequest,
+              vtkInformationVector **theInputVector,
+              vtkInformationVector *theOutputVector)
+{
+  vtkDataSet *anInput = VISU::GetInput( theInputVector, 0 );
+  vtkDataSet *anOutput = VISU::GetOutput( theOutputVector );
 
-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 nbComp = input->GetNumberOfPoints();
-    vtkPointData *inData = input->GetPointData(), *outData = output->GetPointData();
-    if(inData->GetAttribute(vtkDataSetAttributes::VECTORS))
-      execute(nbComp,myScalarMode,inData,outData);
-    else
-      output->GetPointData()->CopyScalarsOn();
-    outData->PassData(inData);
-  }else{
-    output->GetCellData()->CopyVectorsOn();
-    int nbComp = input->GetNumberOfCells();
-    vtkCellData *inData = input->GetCellData(), *outData = output->GetCellData();
-    if(inData->GetAttribute(vtkDataSetAttributes::VECTORS))
-      execute(nbComp,myScalarMode,inData,outData);
-    else
-      output->GetCellData()->CopyScalarsOn();
-    outData->PassData(inData);
+  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;
 }