]> Creatis software - clitk.git/blob - vv/vvInteractorStyleNavigator.cxx
VV panning: middlebutton = left button + shift
[clitk.git] / vv / vvInteractorStyleNavigator.cxx
1 /*=========================================================================
2   Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
3
4   Authors belong to:
5   - University of LYON              http://www.universite-lyon.fr/
6   - Léon Bérard cancer center       http://www.centreleonberard.fr
7   - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
8
9   This software is distributed WITHOUT ANY WARRANTY; without even
10   the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11   PURPOSE.  See the copyright notices for more information.
12
13   It is distributed under dual licence
14
15   - BSD        See included LICENSE.txt file
16   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17 ===========================================================================**/
18 #include "vvInteractorStyleNavigator.h"
19
20 #include "vtkAbstractPropPicker.h"
21 #include "vtkAssemblyPath.h"
22 #include "vtkCallbackCommand.h"
23 #include "vtkMath.h"
24 #include "vtkObjectFactory.h"
25 #include "vtkCamera.h"
26 #include "vtkRenderWindow.h"
27 #include "vtkRenderWindowInteractor.h"
28 #include "vtkRenderer.h"
29 #include <vtkRendererCollection.h>
30 #include "clitkCommon.h"
31
32
33 vtkCxxRevisionMacro(vvInteractorStyleNavigator, "DummyRevision");
34 vtkStandardNewMacro(vvInteractorStyleNavigator);
35
36 //----------------------------------------------------------------------------
37 vvInteractorStyleNavigator::vvInteractorStyleNavigator()
38 {
39   this->WindowLevelStartPosition[0]   = 0;
40   this->WindowLevelStartPosition[1]   = 0;
41
42   this->WindowLevelCurrentPosition[0] = 0;
43   this->WindowLevelCurrentPosition[1] = 0;
44
45   this->MotionFactor   = 10.0;
46 }
47
48 //----------------------------------------------------------------------------
49 vvInteractorStyleNavigator::~vvInteractorStyleNavigator()
50 {
51   CurrentRenderer=NULL;
52 }
53
54 void vvInteractorStyleNavigator::FindPokedRenderer(int dummy1,int dummy2)
55 {
56   vtkRenderWindow * renwin=this->GetInteractor()->GetRenderWindow();
57   renwin->GetRenderers()->InitTraversal();
58   while (true) {
59     vtkRenderer* current = renwin->GetRenderers()->GetNextItem();
60     if (current==NULL || current->GetDraw()) {
61       CurrentRenderer=current;
62       return;
63     }
64   }
65 }
66
67 //----------------------------------------------------------------------------
68 void vvInteractorStyleNavigator::StartWindowLevel()
69 {
70   if (this->State != VTKIS_NONE) {
71     return;
72   }
73   this->StartState(VTKIS_WINDOW_LEVEL);
74   this->InvokeEvent(vtkCommand::StartWindowLevelEvent,this);
75 }
76
77 //----------------------------------------------------------------------------
78 void vvInteractorStyleNavigator::EndWindowLevel()
79 {
80   if (this->State != VTKIS_WINDOW_LEVEL) {
81     return;
82   }
83   this->InvokeEvent(vtkCommand::EndWindowLevelEvent, this);
84   this->StopState();
85 }
86
87 //----------------------------------------------------------------------------
88 void vvInteractorStyleNavigator::StartPick()
89 {
90   if (this->State != VTKIS_NONE) {
91     return;
92   }
93   this->StartState(VTKIS_PICK);
94   this->InvokeEvent(vtkCommand::StartPickEvent, this);
95 }
96
97 //----------------------------------------------------------------------------
98 void vvInteractorStyleNavigator::EndPick()
99 {
100   if (this->State != VTKIS_PICK) {
101     return;
102   }
103   this->InvokeEvent(vtkCommand::EndPickEvent, this);
104   this->StopState();
105 }
106
107 //----------------------------------------------------------------------------
108 void vvInteractorStyleNavigator::OnMouseMove()
109 {
110   int x = this->Interactor->GetEventPosition()[0];
111   int y = this->Interactor->GetEventPosition()[1];
112
113   switch (this->State) {
114   case VTKIS_WINDOW_LEVEL:
115     this->FindPokedRenderer(x, y);
116     this->WindowLevel();
117     this->InvokeEvent(vtkCommand::InteractionEvent, NULL);
118     break;
119
120   case VTKIS_PICK:
121     this->FindPokedRenderer(x, y);
122     this->Pick();
123     this->InvokeEvent(vtkCommand::InteractionEvent, NULL);
124     break;
125
126   case VTKIS_PAN:
127     this->FindPokedRenderer(x, y);
128     this->Pan();
129     this->InvokeEvent(vtkCommand::InteractionEvent, NULL);
130     break;
131
132   case VTKIS_DOLLY:
133     this->FindPokedRenderer(x, y);
134     this->Dolly();
135     this->InvokeEvent(vtkCommand::InteractionEvent, NULL);
136     break;
137
138   default:
139     this->InvokeEvent(vtkCommand::UserEvent, NULL);
140     break;
141   }
142
143   // Call parent to handle all other states and perform additional work
144
145 }
146
147 void vvInteractorStyleNavigator::OnEnter()
148 {
149   //  int x = this->Interactor->GetEventPosition()[0];
150   //int y = this->Interactor->GetEventPosition()[1];
151
152   switch (this->State) {
153   case VTKIS_WINDOW_LEVEL:
154     break;
155
156   case VTKIS_PICK:
157     break;
158
159   case VTKIS_PAN:
160     break;
161
162   default:
163     this->InvokeEvent(vtkCommand::EnterEvent, NULL);
164     break;
165   }
166
167   // Call parent to handle all other states and perform additional work
168
169 }
170
171 //----------------------------------------------------------------------------
172 void vvInteractorStyleNavigator::OnLeave()
173 {
174   //  int x = this->Interactor->GetEventPosition()[0];
175   //int y = this->Interactor->GetEventPosition()[1];
176
177   switch (this->State) {
178   case VTKIS_WINDOW_LEVEL:
179     break;
180
181   case VTKIS_PICK:
182     break;
183
184   case VTKIS_PAN:
185     break;
186
187   default:
188     this->InvokeEvent(vtkCommand::LeaveEvent, NULL);
189     break;
190   }
191
192   // Call parent to handle all other states and perform additional work
193
194 }
195
196 //----------------------------------------------------------------------------
197 void vvInteractorStyleNavigator::OnRightButtonDown()
198 {
199   int x = this->Interactor->GetEventPosition()[0];
200   int y = this->Interactor->GetEventPosition()[1];
201
202   this->FindPokedRenderer(x, y);
203   if (this->CurrentRenderer == NULL) {
204     return;
205   }
206
207   // Redefine this button to handle window/level
208   this->GrabFocus(this->EventCallbackCommand);
209   if (!this->Interactor->GetShiftKey() && !this->Interactor->GetControlKey()) {
210     this->WindowLevelStartPosition[0] = x;
211     this->WindowLevelStartPosition[1] = y;
212     this->StartWindowLevel();
213   }
214
215   // The rest of the button + key combinations remain the same
216
217   else {
218     this->Superclass::OnRightButtonDown();
219   }
220 }
221
222 //----------------------------------------------------------------------------
223 void vvInteractorStyleNavigator::OnRightButtonUp()
224 {
225   switch (this->State) {
226   case VTKIS_WINDOW_LEVEL:
227     this->EndWindowLevel();
228     if ( this->Interactor ) {
229       this->ReleaseFocus();
230     }
231     break;
232   }
233
234   // Call parent to handle all other states and perform additional work
235
236   this->Superclass::OnRightButtonUp();
237 }
238
239 //----------------------------------------------------------------------------
240 void vvInteractorStyleNavigator::OnLeftButtonDown()
241 {
242   int x = this->Interactor->GetEventPosition()[0];
243   int y = this->Interactor->GetEventPosition()[1];
244
245   this->FindPokedRenderer(x, y);
246   if (this->CurrentRenderer == NULL) {
247     return;
248   }
249
250   // Redefine this button to handle pick
251   this->GrabFocus(this->EventCallbackCommand);
252   if (this->Interactor->GetShiftKey()) {
253     this->OnMiddleButtonDown();
254   }
255   else if (!this->Interactor->GetControlKey()) {
256     this->StartPick();
257   }
258
259   // The rest of the button + key combinations remain the same
260
261   else {
262     this->Superclass::OnLeftButtonDown();
263   }
264 }
265
266 //----------------------------------------------------------------------------
267 void vvInteractorStyleNavigator::OnLeftButtonUp()
268 {
269   //  DD("OnLeftButtonUp");
270   switch (this->State) {
271   case VTKIS_PICK:
272     this->EndPick();
273     if ( this->Interactor ) {
274       this->ReleaseFocus();
275     }
276     break;
277   case VTKIS_PAN:
278     this->OnMiddleButtonUp();
279     break;
280   }
281
282   // Call parent to handle all other states and perform additional work
283
284   this->Superclass::OnLeftButtonUp();
285 }
286
287 //----------------------------------------------------------------------------
288 void vvInteractorStyleNavigator::OnMiddleButtonDown()
289 {
290   this->FindPokedRenderer(this->Interactor->GetEventPosition()[0],
291                           this->Interactor->GetEventPosition()[1]);
292   if (this->CurrentRenderer == NULL) {
293     return;
294   }
295   this->CurrentRenderer->GetRenderWindow()->SetCurrentCursor(8);
296   this->GrabFocus(this->EventCallbackCommand);
297   this->StartPan();
298 }
299
300 //----------------------------------------------------------------------------
301 void vvInteractorStyleNavigator::OnMiddleButtonUp()
302 {
303   switch (this->State) {
304   case VTKIS_PAN:
305     this->EndPan();
306     if ( this->Interactor ) {
307       this->Interactor->GetRenderWindow()->SetCurrentCursor(0);
308       this->ReleaseFocus();
309     }
310     break;
311   }
312 }
313
314 //----------------------------------------------------------------------------
315 void vvInteractorStyleNavigator::OnChar()
316 {
317   vtkRenderWindowInteractor *rwi = this->Interactor;
318
319   switch (rwi->GetKeyCode()) {
320   case 'f' :
321   case 'F' : {
322     this->AnimState = VTKIS_ANIM_ON;
323     this->AnimState = VTKIS_ANIM_OFF;
324     break;
325   }
326
327   case 'o'  :
328   case 'O'  : {
329     this->FindPokedRenderer(this->Interactor->GetEventPosition()[0],
330                             this->Interactor->GetEventPosition()[1]);
331     if (this->CurrentRenderer == NULL) {
332       return;
333     }
334     this->GrabFocus(this->EventCallbackCommand);
335     this->StartDolly();
336     double factor = -2;
337     this->Dolly(pow((double)1.1, factor));
338     this->EndDolly();
339     this->ReleaseFocus();
340     break;
341   }
342   case 'i'  :
343   case 'I'  : {
344     this->FindPokedRenderer(rwi->GetEventPosition()[0],
345                             rwi->GetEventPosition()[1]);
346     if (this->CurrentRenderer == NULL) {
347       return;
348     }
349     this->GrabFocus(this->EventCallbackCommand);
350     this->StartDolly();
351     double factor = 2;
352     this->Dolly(pow((double)1.1, factor));
353     this->EndDolly();
354     this->ReleaseFocus();
355     break;
356   }
357   case '3' :
358     // Disable StereoVision
359     break;
360   case 'r' :
361   case 'R' :
362     //Do nothing, this is handled in vvSlicerManagerCommand
363     break;
364   default:
365     //SR: we don't use the default vtk keys => removed to avoid conflicts
366     //this->Superclass::OnChar();
367     break;
368   }
369 }
370
371 //----------------------------------------------------------------------------
372 void vvInteractorStyleNavigator::OnMouseWheelForward()
373 {
374   this->FindPokedRenderer(this->Interactor->GetEventPosition()[0],
375                           this->Interactor->GetEventPosition()[1]);
376   if (this->CurrentRenderer == NULL) {
377     return;
378   }
379   this->GrabFocus(this->EventCallbackCommand);
380   if (this->Interactor->GetControlKey()) {
381     this->StartDolly();
382     double factor = this->MotionFactor * 0.2 * this->MouseWheelMotionFactor;
383     this->Dolly(pow((double)1.1, factor));
384     this->EndDolly();
385   }
386   this->ReleaseFocus();
387   this->InvokeEvent(vtkCommand::MouseWheelForwardEvent, this);
388 }
389
390 //----------------------------------------------------------------------------
391 void vvInteractorStyleNavigator::OnMouseWheelBackward()
392 {
393   this->FindPokedRenderer(this->Interactor->GetEventPosition()[0],
394                           this->Interactor->GetEventPosition()[1]);
395   if (this->CurrentRenderer == NULL) {
396     return;
397   }
398
399   this->GrabFocus(this->EventCallbackCommand);
400   if (this->Interactor->GetControlKey()) {
401     this->StartDolly();
402     double factor = this->MotionFactor * -0.2 * this->MouseWheelMotionFactor;
403     this->Dolly(pow((double)1.1, factor));
404     this->EndDolly();
405   }
406   this->ReleaseFocus();
407   this->InvokeEvent(vtkCommand::MouseWheelBackwardEvent, this);
408 }
409
410
411 //----------------------------------------------------------------------------
412 void vvInteractorStyleNavigator::WindowLevel()
413 {
414   vtkRenderWindowInteractor *rwi = this->Interactor;
415
416   this->WindowLevelCurrentPosition[0] = rwi->GetEventPosition()[0];
417   this->WindowLevelCurrentPosition[1] = rwi->GetEventPosition()[1];
418
419   this->InvokeEvent(vtkCommand::WindowLevelEvent, this);
420 }
421
422 //----------------------------------------------------------------------------
423 void vvInteractorStyleNavigator::Pick()
424 {
425   this->InvokeEvent(vtkCommand::PickEvent, this);
426 }
427
428 //----------------------------------------------------------------------------
429 void vvInteractorStyleNavigator::Pan()
430 {
431   if (this->CurrentRenderer == NULL) {
432     return;
433   }
434
435   vtkRenderWindowInteractor *rwi = this->Interactor;
436
437   double viewFocus[4], focalDepth, viewPoint[3];
438   double newPickPoint[4], oldPickPoint[4], motionVector[3];
439
440   // Calculate the focal depth since we'll be using it a lot
441
442   vtkCamera *camera = this->CurrentRenderer->GetActiveCamera();
443   camera->GetFocalPoint(viewFocus);
444   this->ComputeWorldToDisplay(viewFocus[0], viewFocus[1], viewFocus[2],
445                               viewFocus);
446   focalDepth = viewFocus[2];
447
448   this->ComputeDisplayToWorld((double)rwi->GetEventPosition()[0],
449                               (double)rwi->GetEventPosition()[1],
450                               focalDepth,
451                               newPickPoint);
452
453   // Has to recalc old mouse point since the viewport has moved,
454   // so can't move it outside the loop
455
456   this->ComputeDisplayToWorld((double)rwi->GetLastEventPosition()[0],
457                               (double)rwi->GetLastEventPosition()[1],
458                               focalDepth,
459                               oldPickPoint);
460
461   // Camera motion is reversed
462
463   motionVector[0] = oldPickPoint[0] - newPickPoint[0];
464   motionVector[1] = oldPickPoint[1] - newPickPoint[1];
465   motionVector[2] = oldPickPoint[2] - newPickPoint[2];
466
467   camera->GetFocalPoint(viewFocus);
468   camera->GetPosition(viewPoint);
469   camera->SetFocalPoint(motionVector[0] + viewFocus[0],
470                         motionVector[1] + viewFocus[1],
471                         motionVector[2] + viewFocus[2]);
472
473   camera->SetPosition(motionVector[0] + viewPoint[0],
474                       motionVector[1] + viewPoint[1],
475                       motionVector[2] + viewPoint[2]);
476
477   if (rwi->GetLightFollowCamera()) {
478     this->CurrentRenderer->UpdateLightsGeometryToFollowCamera();
479   }
480
481   this->InvokeEvent(vtkCommand::EndInteractionEvent, this);
482
483 //  rwi->Render();
484 }
485
486 //----------------------------------------------------------------------------
487 void vvInteractorStyleNavigator::Dolly()
488 {
489   if (this->CurrentRenderer == NULL) {
490     return;
491   }
492
493   vtkRenderWindowInteractor *rwi = this->Interactor;
494   double *center = this->CurrentRenderer->GetCenter();
495   int dy = rwi->GetEventPosition()[1] - rwi->GetLastEventPosition()[1];
496   double dyf = this->MotionFactor * (double)(dy) / (double)(center[1]);
497   this->Dolly(pow((double)1.1, dyf));
498 }
499
500 //----------------------------------------------------------------------------
501 void vvInteractorStyleNavigator::Dolly(double factor)
502 {
503   if (this->CurrentRenderer == NULL) {
504     return;
505   }
506
507   double viewFocus[4],viewPoint[4],motionVector[3], focalDepth;
508   double oldPos[3], newPos[3], distance[2];
509   vtkCamera *camera = this->CurrentRenderer->GetActiveCamera();
510   camera->GetFocalPoint(viewFocus);
511   this->ComputeWorldToDisplay(viewFocus[0], viewFocus[1], viewFocus[2],
512                               viewFocus);
513   focalDepth = viewFocus[2];
514
515   oldPos[0] = this->CurrentRenderer->GetCenter()[0];
516   oldPos[1] = this->CurrentRenderer->GetCenter()[1];
517   oldPos[2] = focalDepth;
518
519   distance[0] = 1/factor*
520                 (this->Interactor->GetEventPosition()[0]-this->CurrentRenderer->GetCenter()[0]);
521   distance[1] = 1/factor*
522                 (this->Interactor->GetEventPosition()[1]-this->CurrentRenderer->GetCenter()[1]);
523
524   newPos[0] = this->Interactor->GetEventPosition()[0] - distance[0];
525   newPos[1] = this->Interactor->GetEventPosition()[1] - distance[1];
526   newPos[2] = focalDepth;
527
528   this->CurrentRenderer->DisplayToNormalizedDisplay(oldPos[0],oldPos[1]);
529   this->CurrentRenderer->NormalizedDisplayToViewport(oldPos[0],oldPos[1]);
530   this->CurrentRenderer->ViewportToNormalizedViewport(oldPos[0],oldPos[1]);
531   this->CurrentRenderer->NormalizedViewportToView(oldPos[0],oldPos[1],oldPos[2]);
532   this->CurrentRenderer->ViewToWorld(oldPos[0],oldPos[1],oldPos[2]);
533
534   this->CurrentRenderer->DisplayToNormalizedDisplay(newPos[0],newPos[1]);
535   this->CurrentRenderer->NormalizedDisplayToViewport(newPos[0],newPos[1]);
536   this->CurrentRenderer->ViewportToNormalizedViewport(newPos[0],newPos[1]);
537   this->CurrentRenderer->NormalizedViewportToView(newPos[0],newPos[1],newPos[2]);
538   this->CurrentRenderer->ViewToWorld(newPos[0],newPos[1],newPos[2]);
539
540   motionVector[0] = newPos[0] - oldPos[0];
541   motionVector[1] = newPos[1] - oldPos[1];
542   motionVector[2] = newPos[2] - oldPos[2];
543
544   camera->GetFocalPoint(viewFocus);
545   camera->GetPosition(viewPoint);
546   camera->SetFocalPoint(motionVector[0] + viewFocus[0],
547                         motionVector[1] + viewFocus[1],
548                         motionVector[2] + viewFocus[2]);
549
550   camera->SetPosition(motionVector[0] + viewPoint[0],
551                       motionVector[1] + viewPoint[1],
552                       motionVector[2] + viewPoint[2]);
553
554   if (camera->GetParallelProjection()) {
555     camera->SetParallelScale(camera->GetParallelScale() / factor);
556   } else {
557     camera->Dolly(factor);
558     if (this->AutoAdjustCameraClippingRange) {
559       this->CurrentRenderer->ResetCameraClippingRange();
560     }
561   }
562
563   if (this->Interactor->GetLightFollowCamera()) {
564     this->CurrentRenderer->UpdateLightsGeometryToFollowCamera();
565   }
566   this->CurrentRenderer->ResetCameraClippingRange();
567   //this->Interactor->Render();
568
569   this->InvokeEvent(vtkCommand::EndInteractionEvent, this);
570 }
571
572
573 //----------------------------------------------------------------------------
574 void vvInteractorStyleNavigator::PrintSelf(ostream& os, vtkIndent indent)
575 {
576   this->Superclass::PrintSelf(os, indent);
577
578   os << indent << "Window Level Current Position: ("
579      << this->WindowLevelCurrentPosition[0] << ", "
580      << this->WindowLevelCurrentPosition[1] << ")" << endl;
581
582   os << indent << "Window Level Start Position: ("
583      << this->WindowLevelStartPosition[0] << ", "
584      << this->WindowLevelStartPosition[1] << ")" << endl;
585 }