Salome HOME
Merge remote branch 'origin/akl/22379'
[modules/gui.git] / src / SVTK / SALOME_Actor.cxx
index f384effd6271ece4ca30665d73618984bbd178e2..20fafbeae10a3b3b7f4a144926496d6c871dcb29 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2014  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
@@ -6,7 +6,7 @@
 // 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.
+// version 2.1 of the License, or (at your option) any later version.
 //
 // This library is distributed in the hope that it will be useful,
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -38,7 +38,7 @@
 #include "VTKViewer_TransformFilter.h"
 #include "VTKViewer_GeometryFilter.h"
 #include "VTKViewer_FramedTextActor.h"
-#include "SVTK_RectPicker.h"
+#include "SVTK_AreaPicker.h"
 
 #include "SVTK_Actor.h"
 
@@ -48,6 +48,7 @@
 // VTK Includes
 #include <vtkCell.h>
 #include <vtkLine.h>
+#include <vtkQuadraticEdge.h>
 #include <vtkPicker.h>
 #include <vtkPointPicker.h>
 #include <vtkCellPicker.h>
@@ -58,6 +59,7 @@
 #include <vtkPolyDataMapper.h>
 #include <vtkProperty.h>
 #include <vtkOutlineSource.h>
+#include <vtkPolygon.h>
 
 #include <vtkInteractorStyle.h>
 #include <vtkRenderWindowInteractor.h>
 #include <TColStd_MapOfInteger.hxx>
 #include <TColStd_IndexedMapOfInteger.hxx>
 
+#include <math.h>
+#include <QPoint>
+#include <QVector>
+
 #if defined __GNUC__
   #if __GNUC__ == 2
     #define __GNUC_2__
@@ -87,11 +93,14 @@ namespace
       double aPickPosition[3];
       thePicker->GetPickPosition(aPickPosition);
       double aMinDist = 1000000.0, aDist = 0;
+      vtkCell* aSelEdge;
       for (int i = 0, iEnd = aPickedCell->GetNumberOfEdges(); i < iEnd; i++){
-        if(vtkLine* aLine = vtkLine::SafeDownCast(aPickedCell->GetEdge(i))){
+       aSelEdge = aPickedCell->GetEdge(i);
+        if(vtkLine::SafeDownCast(aPickedCell->GetEdge(i)) || 
+          vtkQuadraticEdge::SafeDownCast(aPickedCell->GetEdge(i))){
           int subId;  
           double pcoords[3], closestPoint[3], weights[3];
-          aLine->EvaluatePosition(aPickPosition,closestPoint,subId,pcoords,aDist,weights);
+          aSelEdge->EvaluatePosition(aPickPosition,closestPoint,subId,pcoords,aDist,weights);
           if (aDist < aMinDist) {
             aMinDist = aDist;
             anEdgeId = -1 - i;
@@ -422,7 +431,7 @@ SALOME_Actor
 {
   mySelector = theSelector;
 }
-
+  
 /*!
   To map current selection to VTK representation
 */
@@ -491,7 +500,7 @@ SALOME_Actor
                SVTK_SelectionEvent* theSelectionEvent,
                bool theIsHighlight)
 {
-  if ( !GetPickable() )
+  if ( !GetPickable() || !mySelector || !mySelector->IsPreSelectionEnabled() )
     return false;
       
   vtkRenderer *aRenderer = theInteractorStyle->GetCurrentRenderer();
@@ -515,9 +524,9 @@ SALOME_Actor
       vtkActorCollection* theActors = aCopy.GetActors();
       theActors->InitTraversal();
       while( vtkActor *ac = theActors->GetNextActor() )
-       if( SALOME_Actor* anActor = SALOME_Actor::SafeDownCast( ac ) )
-         if( anActor->hasIO() && myIO->isSame( anActor->getIO() ) )
-           anActor->SetPreSelected( false );
+        if( SALOME_Actor* anActor = SALOME_Actor::SafeDownCast( ac ) )
+          if( anActor->hasIO() && myIO->isSame( anActor->getIO() ) )
+            anActor->SetPreSelected( false );
     }
   }else{
     switch(aSelectionMode) {
@@ -613,17 +622,17 @@ SALOME_Actor
       if( !mySelector->IsSelected( myIO ) ) {
         SetPreSelected( true );
 
-       if ( hasIO() ) {
-         VTK::ActorCollectionCopy aCopy(aRenderer->GetActors());
-         vtkActorCollection* theActors = aCopy.GetActors();
-         theActors->InitTraversal();
-         while( vtkActor *anAct = theActors->GetNextActor() ) {
-           if( anAct != this )
-             if( SALOME_Actor* anActor = SALOME_Actor::SafeDownCast( anAct ) )
-               if( anActor->hasIO() && myIO->isSame( anActor->getIO() ) )
-                 anActor->SetPreSelected( true );
-         }
-       }
+        if ( hasIO() ) {
+          VTK::ActorCollectionCopy aCopy(aRenderer->GetActors());
+          vtkActorCollection* theActors = aCopy.GetActors();
+          theActors->InitTraversal();
+          while( vtkActor *anAct = theActors->GetNextActor() ) {
+            if( anAct != this )
+              if( SALOME_Actor* anActor = SALOME_Actor::SafeDownCast( anAct ) )
+                if( anActor->hasIO() && myIO->isSame( anActor->getIO() ) )
+                  anActor->SetPreSelected( true );
+          }
+        }
       }
     }
     default:
@@ -646,7 +655,7 @@ SALOME_Actor
             SVTK_SelectionEvent* theSelectionEvent,
             bool theIsHighlight)
 {
-  if ( !GetPickable() || !mySelector )
+  if ( !GetPickable() || !mySelector || !mySelector->IsSelectionEnabled() )
     return false;
 
   myOutlineActor->SetVisibility( false );
@@ -667,102 +676,30 @@ SALOME_Actor
 
   double x = theSelectionEvent->myX;
   double y = theSelectionEvent->myY;
-  double z = 0.0;
-
-  if( !theSelectionEvent->myIsRectangle ) {
-    switch(aSelectionMode){
-    case NodeSelection: {
-      SVTK::TPickLimiter aPickLimiter( myPointPicker, this );
-      myPointPicker->Pick( x, y, z, aRenderer );
 
-      int aVtkId = myPointPicker->GetPointId();
-      if( aVtkId >= 0 && mySelector->IsValid( this, aVtkId, true ) ) {
-        int anObjId = GetNodeObjId( aVtkId );
-        if( hasIO() && anObjId >= 0 ) {
-          mySelector->AddOrRemoveIndex( myIO, anObjId, anIsShift );
-          mySelector->AddIObject( this );
-        }
-      }
-      break;
-    }
-    case CellSelection: 
-    case EdgeSelection:
-    case FaceSelection:
-    case VolumeSelection: 
-    case Elem0DSelection:        
-    case BallSelection: 
-    {
-      SVTK::TPickLimiter aPickLimiter( myCellPicker, this );
-      myCellPicker->Pick( x, y, z, aRenderer );
-    
-      int aVtkId = myCellPicker->GetCellId();
-      if( aVtkId >= 0 && mySelector->IsValid( this, aVtkId ) ) {
-        int anObjId = GetElemObjId( aVtkId );
-        if( anObjId >= 0 ) {
-          if ( hasIO() && CheckDimensionId(aSelectionMode,this,anObjId) ) {
-            mySelector->AddOrRemoveIndex( myIO, anObjId, anIsShift );
-            mySelector->AddIObject( this );
-          }
-        }
-      }
-      break;
-    }
-    case EdgeOfCellSelection: 
-    {
-      SVTK::TPickLimiter aPickLimiter( myCellPicker, this );
-      myCellPicker->Pick( x, y, z, aRenderer );
-    
-      int aVtkId = myCellPicker->GetCellId();
-      if( aVtkId >= 0 && mySelector->IsValid( this, aVtkId ) ) {
-        int anObjId = GetElemObjId( aVtkId );
-        if( anObjId >= 0 ) {
-          int anEdgeId = GetEdgeId(this,myCellPicker.GetPointer(),anObjId);
-          if( hasIO() && anEdgeId < 0 ) {
-            mySelector->AddOrRemoveIndex( myIO, anObjId, false );
-            mySelector->AddOrRemoveIndex( myIO, anEdgeId, true );
-            mySelector->AddIObject( this );
-          } 
-        }
-      }
-      break;
-    }
-    case ActorSelection : 
-    {
-      if ( hasIO() ) {
-       if( mySelector->IsSelected( myIO ) && anIsShift )
-         mySelector->RemoveIObject( this );
-       else {
-         mySelector->AddIObject( this );
-       }
-      }
-      break;
-    }
-    default:
-      break;
-    }
-  }else{
+  if( theSelectionEvent->myIsRectangle || theSelectionEvent->myIsPolygon ) {
     double xLast = theSelectionEvent->myLastX;
     double yLast = theSelectionEvent->myLastY;
-    double zLast = 0.0;
 
     double x1 = x < xLast ? x : xLast;
     double y1 = y < yLast ? y : yLast;
-    double z1 = z < zLast ? z : zLast;
     double x2 = x > xLast ? x : xLast;
     double y2 = y > yLast ? y : yLast;
-    double z2 = z > zLast ? z : zLast;
 
     switch(aSelectionMode){
     case NodeSelection: {
 
-      SVTK::TPickLimiter aPickLimiter( myPointRectPicker, this );
-      myPointRectPicker->Pick( x1, y1, z1, x2, y2, z2, aRenderer );
+      SVTK::TPickLimiter aPickLimiter( myPointAreaPicker, this );
+      if ( theSelectionEvent->myIsRectangle )
+        myPointAreaPicker->Pick( x1, y1, x2, y2, aRenderer, SVTK_AreaPicker::RectangleMode );
+      else if( theSelectionEvent->myIsPolygon )
+        myPointAreaPicker->Pick( theSelectionEvent->myPolygonPoints, aRenderer, SVTK_AreaPicker::PolygonMode );
 
-      const SVTK_RectPicker::TVectorIdsMap& aVectorIdsMap = myPointRectPicker->GetPointIdsMap();
-      SVTK_RectPicker::TVectorIdsMap::const_iterator aMapIter = aVectorIdsMap.find(this);
+      const SVTK_AreaPicker::TVectorIdsMap& aVectorIdsMap = myPointAreaPicker->GetPointIdsMap();
+      SVTK_AreaPicker::TVectorIdsMap::const_iterator aMapIter = aVectorIdsMap.find(this);
       TColStd_MapOfInteger anIndexes;
       if(aMapIter != aVectorIdsMap.end()){
-        const SVTK_RectPicker::TVectorIds& aVectorIds = aMapIter->second;
+        const SVTK_AreaPicker::TVectorIds& aVectorIds = aMapIter->second;
         vtkIdType anEnd = aVectorIds.size();
         for(vtkIdType anId = 0; anId < anEnd; anId++ ) {
           int aPointId = aVectorIds[anId];
@@ -774,13 +711,13 @@ SALOME_Actor
       }
       
       if ( hasIO() ) {
-       if( !anIndexes.IsEmpty() ) {
-         mySelector->AddOrRemoveIndex( myIO, anIndexes, anIsShift );
-         mySelector->AddIObject( this );
-         anIndexes.Clear();
-       }
-       else if ( !anIsShift )
-         mySelector->RemoveIObject( this );
+        if( !anIndexes.IsEmpty() ) {
+          mySelector->AddOrRemoveIndex( myIO, anIndexes, anIsShift );
+          mySelector->AddIObject( this );
+          anIndexes.Clear();
+        }
+        else if ( !anIsShift )
+          mySelector->RemoveIObject( this );
       }
       break;
     }
@@ -796,17 +733,28 @@ SALOME_Actor
             aRenderer->SetWorldPoint( aBounds[ i ], aBounds[ j ], aBounds[ k ], 1.0 );
             aRenderer->WorldToDisplay();
             aRenderer->GetDisplayPoint( aPnt );
-
-            if( aPnt[0] < x1 || aPnt[0] > x2 || aPnt[1] < y1 || aPnt[1] > y2 ) {
-              anIsPicked = false;
-              break;
+            bool anIsPointInSelection;
+            if( theSelectionEvent->myIsRectangle )
+              anIsPointInSelection =  aPnt[0] > x1 && aPnt[0] < x2 && aPnt[1] > y1 && aPnt[1] < y2;
+            else if( theSelectionEvent->myIsPolygon )
+              anIsPointInSelection = myPointAreaPicker->isPointInPolygon( QPoint( aPnt[0], aPnt[1] ),
+                                                                          theSelectionEvent->myPolygonPoints );
+
+            if( !anIsPointInSelection ) {
+                anIsPicked = false;
+                break;
             }
           }
         }
       }
 
-      if( anIsPicked )
-        mySelector->AddIObject(this);
+      if ( hasIO() ) {
+        if( anIsPicked && mySelector->IsSelected( myIO ) && anIsShift )
+          mySelector->RemoveIObject( this );
+        else if ( anIsPicked ){
+          mySelector->AddIObject( this );
+        }
+      }
 
       break;
     }
@@ -817,14 +765,17 @@ SALOME_Actor
     case Elem0DSelection:        
     case BallSelection: 
     {
-      SVTK::TPickLimiter aPickLimiter( myCellRectPicker, this );
-      myCellRectPicker->Pick( x1, y1, z1, x2, y2, z2, aRenderer );
-
-      const SVTK_RectPicker::TVectorIdsMap& aVectorIdsMap = myCellRectPicker->GetCellIdsMap();
-      SVTK_RectPicker::TVectorIdsMap::const_iterator aMapIter = aVectorIdsMap.find(this);
+      SVTK::TPickLimiter aPickLimiter( myCellAreaPicker, this );
+      if( theSelectionEvent->myIsRectangle )
+        myCellAreaPicker->Pick( x1, y1, x2, y2, aRenderer, SVTK_AreaPicker::RectangleMode );
+      else if( theSelectionEvent->myIsPolygon )
+        myCellAreaPicker->Pick( theSelectionEvent->myPolygonPoints, aRenderer, SVTK_AreaPicker::PolygonMode );
+
+      const SVTK_AreaPicker::TVectorIdsMap& aVectorIdsMap = myCellAreaPicker->GetCellIdsMap();
+      SVTK_AreaPicker::TVectorIdsMap::const_iterator aMapIter = aVectorIdsMap.find(this);
       TColStd_MapOfInteger anIndexes;
       if(aMapIter != aVectorIdsMap.end()){
-        const SVTK_RectPicker::TVectorIds& aVectorIds = aMapIter->second;
+        const SVTK_AreaPicker::TVectorIds& aVectorIds = aMapIter->second;
         vtkIdType anEnd = aVectorIds.size();
         for(vtkIdType anId = 0; anId < anEnd; anId++ ) {
           int aCellId = aVectorIds[anId];
@@ -840,19 +791,91 @@ SALOME_Actor
       }
       
       if ( hasIO() ) {
-       if( !anIndexes.IsEmpty() ) {
-         mySelector->AddOrRemoveIndex( myIO, anIndexes, anIsShift );
-         mySelector->AddIObject( this );
-         anIndexes.Clear();
-       }
-       else if ( !anIsShift )
-         mySelector->RemoveIObject( this );
+        if( !anIndexes.IsEmpty() ) {
+          mySelector->AddOrRemoveIndex( myIO, anIndexes, anIsShift );
+          mySelector->AddIObject( this );
+          anIndexes.Clear();
+        }
+        else if ( !anIsShift )
+          mySelector->RemoveIObject( this );
       }
     }
     default:
       break;
     }
   }
+  else {
+    switch(aSelectionMode){
+    case NodeSelection: {
+      SVTK::TPickLimiter aPickLimiter( myPointPicker, this );
+      myPointPicker->Pick( x, y, 0.0, aRenderer );
+
+      int aVtkId = myPointPicker->GetPointId();
+      if( aVtkId >= 0 && mySelector->IsValid( this, aVtkId, true ) ) {
+        int anObjId = GetNodeObjId( aVtkId );
+        if( hasIO() && anObjId >= 0 ) {
+          mySelector->AddOrRemoveIndex( myIO, anObjId, anIsShift );
+          mySelector->AddIObject( this );
+        }
+      }
+      break;
+    }
+    case CellSelection:
+    case EdgeSelection:
+    case FaceSelection:
+    case VolumeSelection:
+    case Elem0DSelection:
+    case BallSelection:
+    {
+      SVTK::TPickLimiter aPickLimiter( myCellPicker, this );
+      myCellPicker->Pick( x, y, 0.0, aRenderer );
+
+      int aVtkId = myCellPicker->GetCellId();
+      if( aVtkId >= 0 && mySelector->IsValid( this, aVtkId ) ) {
+        int anObjId = GetElemObjId( aVtkId );
+        if( anObjId >= 0 ) {
+          if ( hasIO() && CheckDimensionId(aSelectionMode,this,anObjId) ) {
+            mySelector->AddOrRemoveIndex( myIO, anObjId, anIsShift );
+            mySelector->AddIObject( this );
+          }
+        }
+      }
+      break;
+    }
+    case EdgeOfCellSelection:
+    {
+      SVTK::TPickLimiter aPickLimiter( myCellPicker, this );
+      myCellPicker->Pick( x, y, 0.0, aRenderer );
+
+      int aVtkId = myCellPicker->GetCellId();
+      if( aVtkId >= 0 && mySelector->IsValid( this, aVtkId ) ) {
+        int anObjId = GetElemObjId( aVtkId );
+        if( anObjId >= 0 ) {
+          int anEdgeId = GetEdgeId(this,myCellPicker.GetPointer(),anObjId);
+          if( hasIO() && anEdgeId < 0 ) {
+            mySelector->AddOrRemoveIndex( myIO, anObjId, false );
+            mySelector->AddOrRemoveIndex( myIO, anEdgeId, true );
+            mySelector->AddIObject( this );
+          }
+        }
+      }
+      break;
+    }
+    case ActorSelection :
+    {
+      if ( hasIO() ) {
+        if( mySelector->IsSelected( myIO ) && anIsShift )
+          mySelector->RemoveIObject( this );
+        else {
+          mySelector->AddIObject( this );
+        }
+      }
+      break;
+    }
+    default:
+      break;
+    }
+  }
 
   mySelectionMode = aSelectionMode;
 
@@ -901,7 +924,7 @@ SALOME_Actor
 */
 void
 SALOME_Actor
-::SetNameActorOffset(int theOffset[2])
+::SetNameActorOffset(double theOffset[2])
 {
   myNameActor->SetOffset(theOffset);
 }
@@ -913,7 +936,7 @@ SALOME_Actor
 */
 void
 SALOME_Actor
-::GetNameActorSize(vtkRenderer* theRenderer, int theSize[2]) const
+::GetNameActorSize(vtkRenderer* theRenderer, double theSize[2]) const
 {
   myNameActor->GetSize(theRenderer, theSize);
 }
@@ -927,7 +950,7 @@ SALOME_Actor
 {
   if( vtkRenderer* aRenderer = GetRenderer() )
   {
-    int anOffset[2] = { 0, 0 };
+    double anOffset[2] = { 0, 0 };
     VTK::ActorCollectionCopy aCopy(aRenderer->GetActors());
     vtkActorCollection* aCollection = aCopy.GetActors();
     for( int anIndex = 0, aNbItems = aCollection->GetNumberOfItems(); anIndex < aNbItems; anIndex++ )
@@ -939,7 +962,7 @@ SALOME_Actor
           anActor->SetNameActorOffset( anOffset );
           if( anActor->GetVisibility() )
           {
-            int aSize[2];
+            double aSize[2];
             anActor->GetNameActorSize( aRenderer, aSize );
             anOffset[0] = anOffset[0] + aSize[0];
             anOffset[1] = anOffset[1] + aSize[1];
@@ -974,25 +997,57 @@ SALOME_Actor
 }
 
 /*!
-  To set up a picker for point rectangle selection (initialized by SVTK_Renderer::AddActor)
-  \param theRectPicker - new picker
+  To set up a picker for point rectangle or polygonal selection (initialized by SVTK_Renderer::AddActor)
+  \param theAreaPicker - new picker
 */
 void
 SALOME_Actor
-::SetPointRectPicker(SVTK_RectPicker* theRectPicker) 
+::SetPointAreaPicker(SVTK_AreaPicker* theAreaPicker)
 {
-  myPointRectPicker = theRectPicker;
+  myPointAreaPicker = theAreaPicker;
 }
 
 /*!
-  To set up a picker for cell rectangle selection (initialized by SVTK_Renderer::AddActor)
-  \param theRectPicker - new picker
+  To set up a picker for cell rectangle of polygonal selection (initialized by SVTK_Renderer::AddActor)
+  \param theAreaPicker - new picker
 */
 void
 SALOME_Actor
-::SetCellRectPicker(SVTK_RectPicker* theRectPicker) 
+::SetCellAreaPicker(SVTK_AreaPicker* theAreaPicker)
 {
-  myCellRectPicker = theRectPicker;
+  myCellAreaPicker = theAreaPicker;
+}
+
+/*!
+  To find a gravity center of object
+  \param theObjId - identification of object
+*/
+double*
+SALOME_Actor
+::GetGravityCenter( int theObjId )
+{
+  double* result = new double[3];
+  for( int i = 0; i < 3; i++ )
+    result[i]= 0.0;
+
+  vtkPoints* points = GetElemCell( theObjId )->GetPoints();
+  int nbPoints = points->GetNumberOfPoints();
+
+  if( nbPoints <= 0 )
+    return NULL;
+
+  for( int i = 0; i < nbPoints; i++ )
+  {
+    double* aPoint = points->GetPoint(i);
+    result[0] += aPoint[0];
+    result[1] += aPoint[1];
+    result[2] += aPoint[2];
+  }
+  result[0] = result[0] / nbPoints;
+  result[1] = result[1] / nbPoints;
+  result[2] = result[2] / nbPoints;
+
+  return result;
 }
 
 /*!