Salome HOME
Merge from V6_main 01/04/2013
[modules/visu.git] / src / PIPELINE / VISU_PipeLineUtils.cxx
index f60c2ccab5a269f1547ce8e352d6ad6c9460d487..ca2fa0d8a4fd27321c5f2b70a65ddf8afb853049 100644 (file)
-//  VISU OBJECT : interactive object for VISU entities implementation
+// Copyright (C) 2007-2013  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_PipeLine.hxx
 // Author:  Alexey PETROV
 // Module : VISU
-
+//
 #include "VISU_PipeLineUtils.hxx"
 
-void VISU::Mul(const float A[3], float b, float C[3]){ // A*b;
-  for(int i = 0; i < 3; i++)  C[i] = A[i]*b;
-}
+#include "VISU_OpenGLPointSpriteMapper.hxx"
 
-void VISU::Sub(const float A[3], const float B[3], float C[3]){ //A-B
-  for(int i = 0; i < 3; i++)  C[i] = A[i] - B[i];
-}
+#include <vtkCell.h>
+#include <vtkDataSetMapper.h>
+#include <vtkPolyDataMapper.h>
+
+namespace VISU
+{
+  //----------------------------------------------------------------------------
+  void
+  Mul(const double A[3], 
+      double b, 
+      double C[3])
+  { // A*b;
+    for(int i = 0; i < 3; i++)  
+      C[i] = A[i]*b;
+  }
+
+
+  //----------------------------------------------------------------------------
+  void
+  Sub(const double A[3], 
+            const double B[3], 
+            double C[3])
+  { //A-B
+    for(int i = 0; i < 3; i++)  
+      C[i] = A[i] - B[i];
+  }
+
+
+  //----------------------------------------------------------------------------
+  bool
+  CheckIsSameValue(double theTarget,
+                   double theSource)
+  {
+    static double TOL = 10.0 / VTK_LARGE_FLOAT;
+    if(fabs(theTarget - theSource)  < TOL)
+      return true;
+    return false;
+  }
+  
+
+  //----------------------------------------------------------------------------
+  bool
+  CheckIsSameRange(double* theTarget,
+                   double* theSource)
+  {
+    return CheckIsSameValue(theTarget[0], theSource[0]) &&
+      CheckIsSameValue(theTarget[1], theSource[1]);
+  }
+  
 
+  //----------------------------------------------------------------------------
+  void
+  CopyMapper(vtkMapper* theTarget, 
+             vtkMapper* theSource,
+             bool theIsCopyInput)
+  {
+    // To customize vtkMapper::ShallowCopy ...
+    theTarget->SetLookupTable(theSource->GetLookupTable());
+    theTarget->SetScalarVisibility(theSource->GetScalarVisibility());
+    if(theIsCopyInput){
+      double* aScalarRange = theSource->GetScalarRange();
+      if(!CheckIsSameRange(theTarget->GetScalarRange(), aScalarRange))
+        theTarget->SetScalarRange(aScalarRange);
+    }
+    theTarget->SetColorMode(theSource->GetColorMode());
+    theTarget->SetScalarMode(theSource->GetScalarMode());
+    theTarget->SetImmediateModeRendering(theSource->GetImmediateModeRendering());
+    theTarget->SetUseLookupTableScalarRange(theSource->GetUseLookupTableScalarRange());
+    theTarget->SetInterpolateScalarsBeforeMapping(theSource->GetInterpolateScalarsBeforeMapping());
+    if(theSource->GetArrayAccessMode() == VTK_GET_ARRAY_BY_ID)
+      theTarget->ColorByArrayComponent(theSource->GetArrayId(), theSource->GetArrayComponent());
+    else
+      theTarget->ColorByArrayComponent(theSource->GetArrayName(), theSource->GetArrayComponent());
+    
+    // To customize vtkAbstractMapper3D::ShallowCopy ...
+    theTarget->SetClippingPlanes(theSource->GetClippingPlanes());
+  }
+
+
+  //----------------------------------------------------------------------------
+  void
+  CopyDataSetMapper(vtkDataSetMapper* theTarget, 
+                    vtkDataSetMapper* theSource,
+                    bool theIsCopyInput)
+  {
+    // To customize vtkDataSetMapper::ShallowCopy ...
+    //theTarget->SetInput(theSource->GetInput());
+    CopyMapper(theTarget, theSource, theIsCopyInput);
+  }
+
+
+  //----------------------------------------------------------------------------
+  void
+  CopyPolyDataMapper(vtkPolyDataMapper* theTarget, 
+                     vtkPolyDataMapper* theSource,
+                     bool theIsCopyInput)
+  {
+    // To customize vtkPolyDataMapper::ShallowCopy ...
+    //theTarget->SetInput(theSource->GetInput());
+    theTarget->SetGhostLevel(theSource->GetGhostLevel());
+    theTarget->SetNumberOfPieces(theSource->GetNumberOfPieces());
+    theTarget->SetNumberOfSubPieces(theSource->GetNumberOfSubPieces());
+
+    CopyMapper(theTarget, theSource, theIsCopyInput);
+  }
+
+
+  //----------------------------------------------------------------------------
+  void
+  CopyPointSpriteDataMapper(VISU_OpenGLPointSpriteMapper* theTarget, 
+                            VISU_OpenGLPointSpriteMapper* theSource,
+                            bool theIsCopyInput)
+  {
+    // To customize VISU_OpenGLPointSpriteMapper::ShallowCopy ...
+    theTarget->SetPrimitiveType( theSource->GetPrimitiveType() );
+    
+    theTarget->SetPointSpriteMode( theSource->GetPointSpriteMode() );
+    
+    theTarget->SetPointSpriteClamp( theSource->GetPointSpriteClamp() );
+    theTarget->SetPointSpriteSize( theSource->GetPointSpriteSize() );
+    theTarget->SetPointSpriteMinSize( theSource->GetPointSpriteMinSize() );
+    theTarget->SetPointSpriteMaxSize( theSource->GetPointSpriteMaxSize() );
+    theTarget->SetPointSpriteMagnification( theSource->GetPointSpriteMagnification() );
+    
+    theTarget->SetImageData( theSource->GetImageData() );
+    theTarget->SetPointSpriteAlphaThreshold( theSource->GetPointSpriteAlphaThreshold() );
+
+    CopyPolyDataMapper(theTarget, theSource, theIsCopyInput);
+  }
+
+
+  //----------------------------------------------------------------------------
+  void
+  ComputeBoundsParam(double theBounds[6],
+                     double theDirection[3], 
+                     double theMinPnt[3],
+                     double& theMaxBoundPrj, 
+                     double& theMinBoundPrj)
+  {
+    double aBounds[6];
+    for(int i = 0; i < 6; i++) 
+      aBounds[i] = theBounds[i];
+    
+    //Enlarge bounds in order to avoid conflicts of precision
+    for(int i = 0; i < 6; i += 2){
+      static double EPS = 1.0E-3;
+      double aDelta = (aBounds[i+1] - aBounds[i])*EPS;
+      aBounds[i] -= aDelta;
+      aBounds[i+1] += aDelta;
+    }
+    
+    double aBoundPoints[8][3] = { {aBounds[0],aBounds[2],aBounds[4]},
+                                                {aBounds[1],aBounds[2],aBounds[4]},
+                                                {aBounds[0],aBounds[3],aBounds[4]},
+                                                {aBounds[1],aBounds[3],aBounds[4]},
+                                                {aBounds[0],aBounds[2],aBounds[5]},
+                                                {aBounds[1],aBounds[2],aBounds[5]},
+                                                {aBounds[0],aBounds[3],aBounds[5]},
+                                                {aBounds[1],aBounds[3],aBounds[5]}};
+    
+    int aMaxId = 0, aMinId = aMaxId;
+    theMaxBoundPrj = vtkMath::Dot(theDirection,aBoundPoints[aMaxId]);
+    theMinBoundPrj = theMaxBoundPrj;
+    for(int i = 1; i < 8; i++){
+      double aTmp = vtkMath::Dot(theDirection,aBoundPoints[i]);
+      if(theMaxBoundPrj < aTmp){
+        theMaxBoundPrj = aTmp;
+        aMaxId = i;
+      }
+      if(theMinBoundPrj > aTmp){
+        theMinBoundPrj = aTmp;
+        aMinId = i;
+      }
+    }
+    double *aMinPnt = aBoundPoints[aMaxId];
+    theMinPnt[0] = aMinPnt[0];
+    theMinPnt[1] = aMinPnt[1];
+    theMinPnt[2] = aMinPnt[2];
+  }
+
+
+  //----------------------------------------------------------------------------
+  void
+  DistanceToPosition(double theBounds[6],
+                     double theDirection[3], 
+                     double theDist, 
+                     double thePos[3])
+  {
+    double aMaxBoundPrj, aMinBoundPrj, aMinPnt[3];
+    ComputeBoundsParam(theBounds,
+                       theDirection,
+                       aMinPnt,
+                       aMaxBoundPrj,
+                       aMinBoundPrj);
+    double aLength = (aMaxBoundPrj-aMinBoundPrj)*theDist;
+    thePos[0] = aMinPnt[0] - theDirection[0] * aLength;
+    thePos[1] = aMinPnt[1] - theDirection[1] * aLength;
+    thePos[2] = aMinPnt[2] - theDirection[2] * aLength;
+  }
+  
+
+  //----------------------------------------------------------------------------
+  void
+  PositionToDistance(double theBounds[6],
+                     double theDirection[3], 
+                     double thePos[3], 
+                     double& theDist)
+  {
+    double aMaxBoundPrj, aMinBoundPrj, aMinPnt[3];
+    ComputeBoundsParam(theBounds,
+                       theDirection,
+                       aMinPnt,
+                       aMaxBoundPrj,
+                       aMinBoundPrj);
+    double aPrj = vtkMath::Dot(theDirection,thePos);
+    theDist = (aPrj-aMinBoundPrj)/(aMaxBoundPrj-aMinBoundPrj);
+  }
+  
+  //----------------------------------------------------------------------------
+  bool
+  IsQuadraticData(vtkDataSet* theDataSet)
+  {
+    for(int i = 0, n = theDataSet->GetNumberOfCells(); i < n; i++)
+      if(vtkCell* aCell = theDataSet->GetCell(i))
+        if(!aCell->IsLinear())
+          return true;
+    return false;
+  }
+
+  //----------------------------------------------------------------------------
+  //Compute bounds of the visible part of the dataset
+  void
+  ComputeVisibleBounds(vtkDataSet* theDataSet,  double theBounds[6]) {
+    int nbCells, i, j, minIdx, maxIdx;
+    double cellBounds[6];
+    
+    if( theDataSet && (nbCells = theDataSet->GetNumberOfCells()) ) {
+      theDataSet->GetCellBounds(0,theBounds);
+      for ( i = 1; i < nbCells;  i++ ) {
+       theDataSet->GetCellBounds(i, cellBounds);
+       for ( j = 0; j < 3; j++ ) {
+         minIdx = 2*j;
+         maxIdx = 2*j+1;
+         if ( cellBounds[minIdx] < theBounds[minIdx] ) {
+           theBounds[minIdx] = cellBounds[minIdx];
+         }     
+         if ( cellBounds[maxIdx] > theBounds[maxIdx] ) {
+           theBounds[maxIdx] = cellBounds[maxIdx];
+         }
+       }
+      } 
+    } else {
+      vtkMath::UninitializeBounds(theBounds);
+    }
+  }
+  
+  //----------------------------------------------------------------------------
+  //Compute center of the box, box defined as xmin, xmax, ymin, ymax, zmin, zmax
+  void
+  ComputeBoxCenter(double theBounds[6], double theCenter[3]) {
+    for (int i=0; i<3; i++) {
+      theCenter[i] = (theBounds[2*i+1] + theBounds[2*i]) / 2.0;
+    }
+  }
+  
+  //----------------------------------------------------------------------------
+  //Compute length of the box diagonal, box defined as xmin, xmax, ymin, ymax, zmin, zmax
+  double 
+  ComputeBoxDiagonal(double theBounds[6]) {
+    double diff, len=0.0;
+    int i;
+    for (i=0; i<3; i++) {
+      diff = (double)(theBounds[2*i+1]) - (double)(theBounds[2*i]);
+      len += diff * diff;
+    }
+    diff = sqrt(len);
+    return diff;
+  }
+}