Salome HOME
Join modifications from BR_Dev_For_4_0 tag V4_1_1.
[modules/gui.git] / src / SVTK / SVTK_InteractorStyle.cxx
index 4f8dfaa60858dfd927dca36eefc5b98c17b6b831..1f662ca7b49c96f8c3a96011dfbb931b31968f3a 100644 (file)
@@ -36,6 +36,7 @@
 #include "SVTK_Event.h" 
 #include "SVTK_Selector.h"
 #include "SVTK_Functor.h"
+#include "SVTK_Actor.h"
 
 #include "VTKViewer_Algorithm.h"
 #include "SVTK_Functor.h"
 #include <vtkCommand.h>
 #include <vtkCamera.h>
 #include <vtkRenderer.h>
-#include <vtkPicker.h>
+#include <vtkPointPicker.h>
 #include <vtkRenderWindow.h>
 #include <vtkRenderWindowInteractor.h>
 #include <vtkCallbackCommand.h>
 #include <vtkRendererCollection.h>
+#include <vtkDataSet.h>
+#include <vtkPerspectiveTransform.h> 
+#include <vtkMatrix4x4.h>
 
 #include <qapplication.h>
 #include <qpixmap.h>
@@ -62,6 +66,8 @@
 //VRV: porting on Qt 3.0.5
 #include <algorithm>
 
+#include <iostream>
+
 using namespace std;
 
 namespace
@@ -75,44 +81,28 @@ namespace
     theInteractor->GetEventPosition(theX,theY);
     theY = theInteractor->GetSize()[1] - theY - 1;
   }
-
-  //==================================================================
-  // function : GetFirstSALOMEActor
-  // purpose  :
-  //==================================================================
-  struct THaveIO
-  {
-    bool
-    operator()(SALOME_Actor* theActor)
-    {
-      return theActor->hasIO();
-    }
-  };
-
-  inline
-  SALOME_Actor* 
-  GetFirstSALOMEActor(vtkPicker *thePicker)
-  {
-    return VTK::Find<SALOME_Actor>(thePicker->GetActors(),THaveIO());
-  }
 }
 
 
 vtkStandardNewMacro(SVTK_InteractorStyle);
 
+
 /*!
   Constructor
 */
 SVTK_InteractorStyle
 ::SVTK_InteractorStyle():
   mySelectionEvent(new SVTK_SelectionEvent()),
-  myPicker(vtkPicker::New()),
+  myPointPicker(vtkPointPicker::New()),
   myLastHighlitedActor(NULL),
   myLastPreHighlitedActor(NULL),
   myControllerIncrement(SVTK_ControllerIncrement::New()),
-  myControllerOnKeyDown(SVTK_ControllerOnKeyDown::New())
+  myControllerOnKeyDown(SVTK_ControllerOnKeyDown::New()),
+  myHighlightRotationPointActor(SVTK_Actor::New())
 {
-  myPicker->Delete();
+  myPointPicker->Delete();
+
+  myPointPicker->SetTolerance(0.025);
 
   this->MotionFactor = 10.0;
   this->State = VTK_INTERACTOR_STYLE_CAMERA_NONE;
@@ -131,6 +121,20 @@ SVTK_InteractorStyle
   //
   myControllerIncrement->Delete();
   myControllerOnKeyDown->Delete();
+
+  myCurrRotationPointType = SVTK::SetRotateGravity;
+  myPrevRotationPointType = myCurrRotationPointType;
+
+  myHighlightRotationPointActor->Delete();
+  myHighlightRotationPointActor->Initialize();
+  myHighlightRotationPointActor->PickableOff();
+  myHighlightRotationPointActor->SetVisibility( false );
+  
+  myHighlightRotationPointActor->GetProperty()->SetPointSize(SALOME_POINT_SIZE+2);
+  myHighlightRotationPointActor->GetProperty()->SetLineWidth(SALOME_LINE_WIDTH+2);
+  myHighlightRotationPointActor->GetProperty()->SetRepresentationToPoints();
+
+  myBBFirstCheck = true;
 }
 
 /*!
@@ -205,7 +209,7 @@ void
 SVTK_InteractorStyle
 ::RotateXY(int dx, int dy)
 {
-  if(GetCurrentRenderer() == NULL)
+  /*   if(GetCurrentRenderer() == NULL)
     return;
   
   int *size = GetCurrentRenderer()->GetRenderWindow()->GetSize();
@@ -222,6 +226,61 @@ SVTK_InteractorStyle
 
   GetCurrentRenderer()->ResetCameraClippingRange(); 
 
+  this->Render();*/
+
+  if(GetCurrentRenderer() == NULL)
+    return;
+  
+  vtkCamera *cam = GetCurrentRenderer()->GetActiveCamera();
+
+  double viewFP[3], viewPos[3];
+  cam->GetFocalPoint(viewFP);
+  cam->GetPosition(viewPos);
+
+  if ( myCurrRotationPointType == SVTK::SetRotateGravity )
+  {
+    vtkFloatingPointType aCenter[3];
+    if ( ComputeBBCenter(GetCurrentRenderer(),aCenter) ) 
+    {
+      myRotationPointX = aCenter[0];
+      myRotationPointY = aCenter[1];
+      myRotationPointZ = aCenter[2];
+    }
+  }
+
+  // Calculate corresponding transformation
+  vtkPerspectiveTransform* aTransform = vtkPerspectiveTransform::New();
+  aTransform->Identity();
+  aTransform->Translate(+myRotationPointX, +myRotationPointY, +myRotationPointZ);
+
+  // Azimuth transformation
+  int *size = GetCurrentRenderer()->GetRenderWindow()->GetSize();
+  double aDeltaAzimuth = -20.0 / size[0];
+  
+  double rxf = double(dx) * aDeltaAzimuth * this->MotionFactor;
+  aTransform->RotateWXYZ(rxf, cam->GetViewUp());
+
+  // Elevation transformation
+  double aDeltaElevation = -20.0 / size[1];
+
+  double ryf = double(dy) * aDeltaElevation * this->MotionFactor;
+  vtkMatrix4x4* aMatrix = cam->GetViewTransformMatrix();
+  const double anAxis[3] = {-aMatrix->GetElement(0,0), // mkr : 27.11.2006 : PAL14011 - Strange behaviour in rotation in VTK Viewer.
+                           -aMatrix->GetElement(0,1), 
+                           -aMatrix->GetElement(0,2)};
+  
+  aTransform->RotateWXYZ(ryf, anAxis);
+            
+  aTransform->Translate(-myRotationPointX, -myRotationPointY, -myRotationPointZ);
+
+  // To apply the transformation
+  cam->SetPosition(aTransform->TransformPoint(viewPos));
+  cam->SetFocalPoint(aTransform->TransformPoint(viewFP));
+
+  cam->OrthogonalizeViewUp();
+
+  GetCurrentRenderer()->ResetCameraClippingRange(); 
+
   this->Render();
 }
 
@@ -431,9 +490,53 @@ SVTK_InteractorStyle
   } else {
     if (ctrl)
       startOperation(VTK_INTERACTOR_STYLE_CAMERA_ZOOM);
+    else if ( myCurrRotationPointType == SVTK::StartPointSelection )
+    {
+      SVTK_SelectionEvent* aSelectionEvent = GetSelectionEventFlipY();
+
+      SALOME_Actor* anActor = GetSelector()->Pick(aSelectionEvent, GetCurrentRenderer());
+      
+      if ( anActor )
+      {
+       myPointPicker->Pick( aSelectionEvent->myX,
+                            aSelectionEvent->myY, 
+                            0.0, 
+                            GetCurrentRenderer() );
+       int aVtkId = myPointPicker->GetPointId();
+       if ( aVtkId >= 0 )
+       {
+         int anObjId = anActor->GetNodeObjId( aVtkId );
+         vtkFloatingPointType* aCoords = anActor->GetNodeCoord(anObjId);
+         
+         myCurrRotationPointType = SVTK::SetRotateSelected;
+         
+         // invoke event for update coordinates in SVTK_SetRotationPointDlg
+         InvokeEvent(SVTK::RotationPointChanged,(void*)aCoords);
+       }
+       else
+       {
+         // invoke event with no data (for SVTK_SetRotationPointDlg)
+         InvokeEvent(SVTK::RotationPointChanged,0);
+         myCurrRotationPointType = myPrevRotationPointType;
+       }
+      }
+      else
+      {
+       // invoke event with no data (for SVTK_SetRotationPointDlg)
+       InvokeEvent(SVTK::RotationPointChanged,0);
+       myCurrRotationPointType = myPrevRotationPointType;
+      }
+    
+      myHighlightRotationPointActor->SetVisibility( false );
+      if(GetCurrentRenderer() != NULL)
+       GetCurrentRenderer()->RemoveActor( myHighlightRotationPointActor.GetPointer() );
+
+      GetRenderWidget()->setCursor(myDefCursor); 
+    }
     else
       startOperation(VTK_INTERACTOR_STYLE_CAMERA_SELECT);
   }
+  
   return;
 }
 
@@ -696,6 +799,26 @@ SVTK_InteractorStyle
   ForcedState = VTK_INTERACTOR_STYLE_CAMERA_ROTATE;
 }
 
+/*!
+  Set rotation point selected by user
+*/
+void 
+SVTK_InteractorStyle
+::startPointSelection()
+{
+  myCurrRotationPointType = SVTK::StartPointSelection;
+
+  if(GetCurrentRenderer() != NULL) {
+    GetCurrentRenderer()->AddActor( myHighlightRotationPointActor.GetPointer() );
+    vtkFloatingPointType aColor[3];
+    GetCurrentRenderer()->GetBackground( aColor );
+    myHighlightRotationPointActor->GetProperty()->SetColor(1. - aColor[0],
+                                                          1. - aColor[1],
+                                                          1. - aColor[2]);
+  }
+
+  setCursor(VTK_INTERACTOR_STYLE_CAMERA_NONE);
+}
 
 /*! 
   Starts Spin operation (e.g. through menu command)
@@ -863,7 +986,10 @@ SVTK_InteractorStyle
       break;
     case VTK_INTERACTOR_STYLE_CAMERA_NONE:
     default:
-      GetRenderWidget()->setCursor(myDefCursor); 
+      if ( myCurrRotationPointType == SVTK::StartPointSelection )
+       GetRenderWidget()->setCursor(myHandCursor);
+      else
+       GetRenderWidget()->setCursor(myDefCursor); 
       myCursorState = false;
       break;
   }
@@ -942,51 +1068,54 @@ SVTK_InteractorStyle
         fitRect(x1, y1, x2, y2);
       }
       else {
-        if (myPoint == myOtherPoint) {
-         // process point selection
-          this->FindPokedRenderer(aSelectionEvent->myX, aSelectionEvent->myY);
-         Interactor->StartPickCallback();
-
-          myPicker->Pick(aSelectionEvent->myX, 
-                        aSelectionEvent->myY, 
-                        0.0, 
-                        GetCurrentRenderer());
-         //
-         SALOME_Actor* anActor = GetFirstSALOMEActor(myPicker.GetPointer());
-         aSelectionEvent->myIsRectangle = false;
-
-         if(!myShiftState)
-           GetSelector()->ClearIObjects();
-
-         if(anActor){
-           anActor->Highlight( this, aSelectionEvent, true );
-         }else{
-           if(myLastHighlitedActor.GetPointer() && myLastHighlitedActor.GetPointer() != anActor)
-             myLastHighlitedActor->Highlight( this, aSelectionEvent, false );
-         }
-         myLastHighlitedActor = anActor;
-       } 
-       else {
-          //processing rectangle selection
-         Interactor->StartPickCallback();
-         GetSelector()->StartPickCallback();
-         aSelectionEvent->myIsRectangle = true;
-
-         if(!myShiftState)
-           GetSelector()->ClearIObjects();
-
-         vtkActorCollection* aListActors = GetCurrentRenderer()->GetActors();
-         aListActors->InitTraversal();
-         while(vtkActor* aActor = aListActors->GetNextActor()){
-           if(aActor->GetVisibility()){
-             if(SALOME_Actor* aSActor = SALOME_Actor::SafeDownCast(aActor)){
-               if(aSActor->hasIO()){
-                 aSActor->Highlight( this, aSelectionEvent, true );
-               }
+        if (myPoint == myOtherPoint)
+         {
+           // process point selection
+           this->FindPokedRenderer(aSelectionEvent->myX, aSelectionEvent->myY);
+           Interactor->StartPickCallback();
+           
+           SALOME_Actor* anActor = GetSelector()->Pick(aSelectionEvent, GetCurrentRenderer());
+           
+           aSelectionEvent->myIsRectangle = false;
+
+           if(!myShiftState)
+             GetSelector()->ClearIObjects();
+
+           if(anActor)
+             {
+               anActor->Highlight( this, aSelectionEvent, true );
+             }
+           else
+             {
+               if(myLastHighlitedActor.GetPointer() && myLastHighlitedActor.GetPointer() != anActor)
+                 myLastHighlitedActor->Highlight( this, aSelectionEvent, false );
+               myLastHighlitedActor = anActor;
+             }
+         } 
+       else 
+         {
+           //processing rectangle selection
+           Interactor->StartPickCallback();
+           GetSelector()->StartPickCallback();
+           aSelectionEvent->myIsRectangle = true;
+
+           if(!myShiftState)
+             GetSelector()->ClearIObjects();
+
+           vtkActorCollection* aListActors = GetCurrentRenderer()->GetActors();
+           aListActors->InitTraversal();
+           while(vtkActor* aActor = aListActors->GetNextActor())
+             {
+               if(aActor->GetVisibility())
+                 {
+                   if(SALOME_Actor* aSActor = SALOME_Actor::SafeDownCast(aActor))
+                     {
+                       if(aSActor->hasIO())
+                         aSActor->Highlight( this, aSelectionEvent, true );
+                     }
+                 }
              }
-           }
          }
-       }
        Interactor->EndPickCallback();
        GetSelector()->EndPickCallback();
       } 
@@ -1078,24 +1207,43 @@ SVTK_InteractorStyle
 ::onCursorMove(QPoint mousePos) 
 {
   // processing highlighting
-  SVTK_SelectionEvent* aSelectionEvent = GetSelectionEventFlipY();
+   SVTK_SelectionEvent* aSelectionEvent = GetSelectionEventFlipY();
   this->FindPokedRenderer(aSelectionEvent->myX,aSelectionEvent->myY);
 
   bool anIsChanged = false;
 
-  myPicker->Pick(aSelectionEvent->myX, 
-                aSelectionEvent->myY, 
-                0.0, 
-                GetCurrentRenderer());
+  SALOME_Actor *anActor = GetSelector()->Pick(aSelectionEvent, GetCurrentRenderer());
   
-  SALOME_Actor *anActor = GetFirstSALOMEActor(myPicker.GetPointer());
-  if (anActor){
-    anIsChanged |= anActor->PreHighlight( this, aSelectionEvent, true );
+  if ( myCurrRotationPointType == SVTK::StartPointSelection )
+  {
+    myHighlightRotationPointActor->SetVisibility( false );
+
+    if ( anActor )
+    {
+      myPointPicker->Pick( aSelectionEvent->myX, aSelectionEvent->myY, 0.0, GetCurrentRenderer() );
+      int aVtkId = myPointPicker->GetPointId();
+      if ( aVtkId >= 0 ) {
+       int anObjId = anActor->GetNodeObjId( aVtkId );
+
+       TColStd_IndexedMapOfInteger aMapIndex;
+       aMapIndex.Add( anObjId );
+       myHighlightRotationPointActor->MapPoints( anActor, aMapIndex );
+
+       myHighlightRotationPointActor->SetVisibility( true );
+       anIsChanged = true;
+      }
+    }
   }
+  else {
+    if (anActor){
+      anIsChanged |= anActor->PreHighlight( this, aSelectionEvent, true );
+    }
 
-  if(myLastPreHighlitedActor.GetPointer() && myLastPreHighlitedActor.GetPointer() != anActor)
-    anIsChanged |= myLastPreHighlitedActor->PreHighlight( this, aSelectionEvent, false );   
+    if(myLastPreHighlitedActor.GetPointer() && myLastPreHighlitedActor.GetPointer() != anActor)
+      anIsChanged |= myLastPreHighlitedActor->PreHighlight( this, aSelectionEvent, false );   
 
+  }
+  
   myLastPreHighlitedActor = anActor;
 
   if(anIsChanged)
@@ -1225,6 +1373,11 @@ SVTK_InteractorStyle
     theInteractor->AddObserver( SVTK::StartRotate, EventCallbackCommand, Priority );
     theInteractor->AddObserver( SVTK::StartGlobalPan, EventCallbackCommand, Priority );
     theInteractor->AddObserver( SVTK::StartFitArea, EventCallbackCommand, Priority );
+
+    theInteractor->AddObserver( SVTK::SetRotateGravity, EventCallbackCommand, Priority );
+    theInteractor->AddObserver( SVTK::StartPointSelection, EventCallbackCommand, Priority );
+
+    theInteractor->AddObserver( SVTK::ChangeRotationPoint, EventCallbackCommand, Priority );
   }
 }
 
@@ -1237,6 +1390,30 @@ SVTK_InteractorStyle
 {
   //vtkInteractorStyle::OnTimer();
   this->Interactor->Render();
+  // check if bounding box was changed
+  if ( GetCurrentRenderer() )
+  {
+    vtkFloatingPointType aCurrBBCenter[3];
+    if ( ComputeBBCenter(GetCurrentRenderer(),aCurrBBCenter) )
+    {
+      if ( !myBBFirstCheck )
+      {
+       if ( fabs(aCurrBBCenter[0]-myBBCenter[0]) > 1e-38 ||
+            fabs(aCurrBBCenter[1]-myBBCenter[1]) > 1e-38 ||
+            fabs(aCurrBBCenter[2]-myBBCenter[2]) > 1e-38 ) {
+         // bounding box was changed => send SVTK::RotationPointChanged event
+         // invoke event for update coordinates in SVTK_SetRotationPointDlg
+         InvokeEvent(SVTK::BBCenterChanged,(void*)aCurrBBCenter);
+         for ( int i =0; i < 3; i++) myBBCenter[i] = aCurrBBCenter[i];
+       }
+      }
+      else 
+      {
+       for ( int i =0; i < 3; i++) myBBCenter[i] = aCurrBBCenter[i];
+       myBBFirstCheck = false;
+      }
+    }
+  }
 }
 
 /*!
@@ -1299,6 +1476,8 @@ SVTK_InteractorStyle
     vtkObject* anObject = reinterpret_cast<vtkObject*>( clientData );
     SVTK_InteractorStyle* self = dynamic_cast<SVTK_InteractorStyle*>( anObject );
     int aSpeedIncrement=self->ControllerIncrement()->Current();
+    vtkFloatingPointType aCenter[3];
+    vtkFloatingPointType* aSelectedPoint;
     if ( self ) {
       switch ( event ) {
       case SVTK::SpaceMouseMoveEvent : 
@@ -1372,6 +1551,40 @@ SVTK_InteractorStyle
       case SVTK::StartFitArea:
        self->startFitArea();
        return;
+
+      case SVTK::SetRotateGravity:
+       if ( self->myCurrRotationPointType == SVTK::StartPointSelection )
+       {
+         self->myHighlightRotationPointActor->SetVisibility( false );
+         if( self->GetCurrentRenderer() != NULL )
+           self->GetCurrentRenderer()->RemoveActor( self->myHighlightRotationPointActor.GetPointer() );
+         self->GetRenderWidget()->setCursor(self->myDefCursor); 
+       }
+       self->myPrevRotationPointType = self->myCurrRotationPointType;
+       self->myCurrRotationPointType = SVTK::SetRotateGravity;
+       if ( ComputeBBCenter(self->GetCurrentRenderer(),aCenter) ) 
+         // invoke event for update coordinates in SVTK_SetRotationPointDlg
+         self->InvokeEvent(SVTK::BBCenterChanged,(void*)aCenter);
+       return;
+      case SVTK::StartPointSelection:
+       self->startPointSelection();
+       return;
+
+      case SVTK::ChangeRotationPoint:
+       if ( self->myCurrRotationPointType == SVTK::StartPointSelection )
+       {
+         self->myHighlightRotationPointActor->SetVisibility( false );
+         if( self->GetCurrentRenderer() != NULL )
+           self->GetCurrentRenderer()->RemoveActor( self->myHighlightRotationPointActor.GetPointer() );
+         self->GetRenderWidget()->setCursor(self->myDefCursor); 
+       }
+       self->myPrevRotationPointType = self->myCurrRotationPointType;
+       self->myCurrRotationPointType = SVTK::SetRotateSelected;
+       aSelectedPoint = (vtkFloatingPointType*)callData;
+       self->myRotationPointX = aSelectedPoint[0];
+       self->myRotationPointY = aSelectedPoint[1];
+       self->myRotationPointZ = aSelectedPoint[2];
+       return;
       }
     }
   }