]> Creatis software - clitk.git/blob - vv/vvInteractorStyleNavigator.cxx
Merge branch 'master' of git://git.creatis.insa-lyon.fr/clitk
[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() && !this->Interactor->GetControlKey()) {
253     this->StartPick();
254   }
255
256   // The rest of the button + key combinations remain the same
257
258   else {
259     this->Superclass::OnLeftButtonDown();
260   }
261 }
262
263 //----------------------------------------------------------------------------
264 void vvInteractorStyleNavigator::OnLeftButtonUp()
265 {
266   //  DD("OnLeftButtonUp");
267   switch (this->State) {
268   case VTKIS_PICK:
269     this->EndPick();
270     if ( this->Interactor ) {
271       this->ReleaseFocus();
272     }
273     break;
274   }
275
276   // Call parent to handle all other states and perform additional work
277
278   this->Superclass::OnLeftButtonUp();
279 }
280
281 //----------------------------------------------------------------------------
282 void vvInteractorStyleNavigator::OnMiddleButtonDown()
283 {
284   this->FindPokedRenderer(this->Interactor->GetEventPosition()[0],
285                           this->Interactor->GetEventPosition()[1]);
286   if (this->CurrentRenderer == NULL) {
287     return;
288   }
289   this->CurrentRenderer->GetRenderWindow()->SetCurrentCursor(8);
290   this->GrabFocus(this->EventCallbackCommand);
291   this->StartPan();
292 }
293
294 //----------------------------------------------------------------------------
295 void vvInteractorStyleNavigator::OnMiddleButtonUp()
296 {
297   switch (this->State) {
298   case VTKIS_PAN:
299     this->EndPan();
300     if ( this->Interactor ) {
301       this->Interactor->GetRenderWindow()->SetCurrentCursor(0);
302       this->ReleaseFocus();
303     }
304     break;
305   }
306 }
307
308 //----------------------------------------------------------------------------
309 void vvInteractorStyleNavigator::OnChar()
310 {
311   vtkRenderWindowInteractor *rwi = this->Interactor;
312
313   switch (rwi->GetKeyCode()) {
314   case 'f' :
315   case 'F' : {
316     this->AnimState = VTKIS_ANIM_ON;
317     this->AnimState = VTKIS_ANIM_OFF;
318     break;
319   }
320
321   case 'o'  :
322   case 'O'  : {
323     this->FindPokedRenderer(this->Interactor->GetEventPosition()[0],
324                             this->Interactor->GetEventPosition()[1]);
325     if (this->CurrentRenderer == NULL) {
326       return;
327     }
328     this->GrabFocus(this->EventCallbackCommand);
329     this->StartDolly();
330     double factor = -2;
331     this->Dolly(pow((double)1.1, factor));
332     this->EndDolly();
333     this->ReleaseFocus();
334     break;
335   }
336   case 'i'  :
337   case 'I'  : {
338     this->FindPokedRenderer(rwi->GetEventPosition()[0],
339                             rwi->GetEventPosition()[1]);
340     if (this->CurrentRenderer == NULL) {
341       return;
342     }
343     this->GrabFocus(this->EventCallbackCommand);
344     this->StartDolly();
345     double factor = 2;
346     this->Dolly(pow((double)1.1, factor));
347     this->EndDolly();
348     this->ReleaseFocus();
349     break;
350   }
351   case '3' :
352     // Disable StereoVision
353     break;
354   case 'r' :
355   case 'R' :
356     //Do nothing, this is handled in vvSlicerManagerCommand
357     break;
358   default:
359     //SR: we don't use the default vtk keys => removed to avoid conflicts
360     //this->Superclass::OnChar();
361     break;
362   }
363 }
364
365 //----------------------------------------------------------------------------
366 void vvInteractorStyleNavigator::OnMouseWheelForward()
367 {
368   this->FindPokedRenderer(this->Interactor->GetEventPosition()[0],
369                           this->Interactor->GetEventPosition()[1]);
370   if (this->CurrentRenderer == NULL) {
371     return;
372   }
373   this->GrabFocus(this->EventCallbackCommand);
374   if (this->Interactor->GetControlKey()) {
375     this->StartDolly();
376     double factor = this->MotionFactor * 0.2 * this->MouseWheelMotionFactor;
377     this->Dolly(pow((double)1.1, factor));
378     this->EndDolly();
379   }
380   this->ReleaseFocus();
381   this->InvokeEvent(vtkCommand::MouseWheelForwardEvent, this);
382 }
383
384 //----------------------------------------------------------------------------
385 void vvInteractorStyleNavigator::OnMouseWheelBackward()
386 {
387   this->FindPokedRenderer(this->Interactor->GetEventPosition()[0],
388                           this->Interactor->GetEventPosition()[1]);
389   if (this->CurrentRenderer == NULL) {
390     return;
391   }
392
393   this->GrabFocus(this->EventCallbackCommand);
394   if (this->Interactor->GetControlKey()) {
395     this->StartDolly();
396     double factor = this->MotionFactor * -0.2 * this->MouseWheelMotionFactor;
397     this->Dolly(pow((double)1.1, factor));
398     this->EndDolly();
399   }
400   this->ReleaseFocus();
401   this->InvokeEvent(vtkCommand::MouseWheelBackwardEvent, this);
402 }
403
404
405 //----------------------------------------------------------------------------
406 void vvInteractorStyleNavigator::WindowLevel()
407 {
408   vtkRenderWindowInteractor *rwi = this->Interactor;
409
410   this->WindowLevelCurrentPosition[0] = rwi->GetEventPosition()[0];
411   this->WindowLevelCurrentPosition[1] = rwi->GetEventPosition()[1];
412
413   this->InvokeEvent(vtkCommand::WindowLevelEvent, this);
414 }
415
416 //----------------------------------------------------------------------------
417 void vvInteractorStyleNavigator::Pick()
418 {
419   this->InvokeEvent(vtkCommand::PickEvent, this);
420 }
421
422 //----------------------------------------------------------------------------
423 void vvInteractorStyleNavigator::Pan()
424 {
425   if (this->CurrentRenderer == NULL) {
426     return;
427   }
428
429   vtkRenderWindowInteractor *rwi = this->Interactor;
430
431   double viewFocus[4], focalDepth, viewPoint[3];
432   double newPickPoint[4], oldPickPoint[4], motionVector[3];
433
434   // Calculate the focal depth since we'll be using it a lot
435
436   vtkCamera *camera = this->CurrentRenderer->GetActiveCamera();
437   camera->GetFocalPoint(viewFocus);
438   this->ComputeWorldToDisplay(viewFocus[0], viewFocus[1], viewFocus[2],
439                               viewFocus);
440   focalDepth = viewFocus[2];
441
442   this->ComputeDisplayToWorld((double)rwi->GetEventPosition()[0],
443                               (double)rwi->GetEventPosition()[1],
444                               focalDepth,
445                               newPickPoint);
446
447   // Has to recalc old mouse point since the viewport has moved,
448   // so can't move it outside the loop
449
450   this->ComputeDisplayToWorld((double)rwi->GetLastEventPosition()[0],
451                               (double)rwi->GetLastEventPosition()[1],
452                               focalDepth,
453                               oldPickPoint);
454
455   // Camera motion is reversed
456
457   motionVector[0] = oldPickPoint[0] - newPickPoint[0];
458   motionVector[1] = oldPickPoint[1] - newPickPoint[1];
459   motionVector[2] = oldPickPoint[2] - newPickPoint[2];
460
461   camera->GetFocalPoint(viewFocus);
462   camera->GetPosition(viewPoint);
463   camera->SetFocalPoint(motionVector[0] + viewFocus[0],
464                         motionVector[1] + viewFocus[1],
465                         motionVector[2] + viewFocus[2]);
466
467   camera->SetPosition(motionVector[0] + viewPoint[0],
468                       motionVector[1] + viewPoint[1],
469                       motionVector[2] + viewPoint[2]);
470
471   if (rwi->GetLightFollowCamera()) {
472     this->CurrentRenderer->UpdateLightsGeometryToFollowCamera();
473   }
474
475   this->InvokeEvent(vtkCommand::EndInteractionEvent, this);
476
477 //  rwi->Render();
478 }
479
480 //----------------------------------------------------------------------------
481 void vvInteractorStyleNavigator::Dolly()
482 {
483   if (this->CurrentRenderer == NULL) {
484     return;
485   }
486
487   vtkRenderWindowInteractor *rwi = this->Interactor;
488   double *center = this->CurrentRenderer->GetCenter();
489   int dy = rwi->GetEventPosition()[1] - rwi->GetLastEventPosition()[1];
490   double dyf = this->MotionFactor * (double)(dy) / (double)(center[1]);
491   this->Dolly(pow((double)1.1, dyf));
492 }
493
494 //----------------------------------------------------------------------------
495 void vvInteractorStyleNavigator::Dolly(double factor)
496 {
497   if (this->CurrentRenderer == NULL) {
498     return;
499   }
500
501   double viewFocus[4],viewPoint[4],motionVector[3], focalDepth;
502   double oldPos[3], newPos[3], distance[2];
503   vtkCamera *camera = this->CurrentRenderer->GetActiveCamera();
504   camera->GetFocalPoint(viewFocus);
505   this->ComputeWorldToDisplay(viewFocus[0], viewFocus[1], viewFocus[2],
506                               viewFocus);
507   focalDepth = viewFocus[2];
508
509   oldPos[0] = this->CurrentRenderer->GetCenter()[0];
510   oldPos[1] = this->CurrentRenderer->GetCenter()[1];
511   oldPos[2] = focalDepth;
512
513   distance[0] = 1/factor*
514                 (this->Interactor->GetEventPosition()[0]-this->CurrentRenderer->GetCenter()[0]);
515   distance[1] = 1/factor*
516                 (this->Interactor->GetEventPosition()[1]-this->CurrentRenderer->GetCenter()[1]);
517
518   newPos[0] = this->Interactor->GetEventPosition()[0] - distance[0];
519   newPos[1] = this->Interactor->GetEventPosition()[1] - distance[1];
520   newPos[2] = focalDepth;
521
522   this->CurrentRenderer->DisplayToNormalizedDisplay(oldPos[0],oldPos[1]);
523   this->CurrentRenderer->NormalizedDisplayToViewport(oldPos[0],oldPos[1]);
524   this->CurrentRenderer->ViewportToNormalizedViewport(oldPos[0],oldPos[1]);
525   this->CurrentRenderer->NormalizedViewportToView(oldPos[0],oldPos[1],oldPos[2]);
526   this->CurrentRenderer->ViewToWorld(oldPos[0],oldPos[1],oldPos[2]);
527
528   this->CurrentRenderer->DisplayToNormalizedDisplay(newPos[0],newPos[1]);
529   this->CurrentRenderer->NormalizedDisplayToViewport(newPos[0],newPos[1]);
530   this->CurrentRenderer->ViewportToNormalizedViewport(newPos[0],newPos[1]);
531   this->CurrentRenderer->NormalizedViewportToView(newPos[0],newPos[1],newPos[2]);
532   this->CurrentRenderer->ViewToWorld(newPos[0],newPos[1],newPos[2]);
533
534   motionVector[0] = newPos[0] - oldPos[0];
535   motionVector[1] = newPos[1] - oldPos[1];
536   motionVector[2] = newPos[2] - oldPos[2];
537
538   camera->GetFocalPoint(viewFocus);
539   camera->GetPosition(viewPoint);
540   camera->SetFocalPoint(motionVector[0] + viewFocus[0],
541                         motionVector[1] + viewFocus[1],
542                         motionVector[2] + viewFocus[2]);
543
544   camera->SetPosition(motionVector[0] + viewPoint[0],
545                       motionVector[1] + viewPoint[1],
546                       motionVector[2] + viewPoint[2]);
547
548   if (camera->GetParallelProjection()) {
549     camera->SetParallelScale(camera->GetParallelScale() / factor);
550   } else {
551     camera->Dolly(factor);
552     if (this->AutoAdjustCameraClippingRange) {
553       this->CurrentRenderer->ResetCameraClippingRange();
554     }
555   }
556
557   if (this->Interactor->GetLightFollowCamera()) {
558     this->CurrentRenderer->UpdateLightsGeometryToFollowCamera();
559   }
560   this->CurrentRenderer->ResetCameraClippingRange();
561   //this->Interactor->Render();
562
563   this->InvokeEvent(vtkCommand::EndInteractionEvent, this);
564 }
565
566
567 //----------------------------------------------------------------------------
568 void vvInteractorStyleNavigator::PrintSelf(ostream& os, vtkIndent indent)
569 {
570   this->Superclass::PrintSelf(os, indent);
571
572   os << indent << "Window Level Current Position: ("
573      << this->WindowLevelCurrentPosition[0] << ", "
574      << this->WindowLevelCurrentPosition[1] << ")" << endl;
575
576   os << indent << "Window Level Start Position: ("
577      << this->WindowLevelStartPosition[0] << ", "
578      << this->WindowLevelStartPosition[1] << ")" << endl;
579 }