]> Creatis software - cpPlugins.git/blob - lib/cpPlugins/Extensions/Visualization/ImageInteractorStyle.cxx
67a271f58a058a71543c4cbb3c1b681ab5778bd6
[cpPlugins.git] / lib / cpPlugins / Extensions / Visualization / ImageInteractorStyle.cxx
1 #include <cpPlugins/Extensions/Visualization/ImageInteractorStyle.h>
2
3 #include <ctime>
4
5 #include <vtkAnnotatedCubeActor.h>
6 #include <vtkAxesActor.h>
7 #include <vtkCallbackCommand.h>
8 #include <vtkCamera.h>
9 #include <vtkCommand.h>
10 #include <vtkPropAssembly.h>
11 #include <vtkProperty.h>
12 #include <vtkRendererCollection.h>
13 #include <vtkRenderWindow.h>
14 #include <vtkRenderWindowInteractor.h>
15
16 #include <cpPlugins/Extensions/Visualization/ImageSliceActors.h>
17 #include <cpPlugins/Extensions/Visualization/MPRActors.h>
18
19 // -------------------------------------------------------------------------
20 const int cpPlugins::Extensions::Visualization::
21 ImageInteractorStyle::DoubleClickEvent = vtkCommand::UserEvent + 1;
22
23 // -------------------------------------------------------------------------
24 cpPlugins::Extensions::Visualization::ImageInteractorStyle::
25 Self* cpPlugins::Extensions::Visualization::ImageInteractorStyle::
26 New( )
27 {
28   return( new Self( ) );
29 }
30
31 // -------------------------------------------------------------------------
32 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
33 Configure( ImageSliceActors* slice_actors, MPRActors* mpr_actors )
34 {
35   this->m_SliceActors = slice_actors;
36   this->m_MPRActors = mpr_actors;
37   this->SetModeToNavigation( );
38   this->PropPicker->AddPickList( slice_actors->GetImageActor( ) );
39   this->Modified( );
40 }
41
42 // -------------------------------------------------------------------------
43 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
44 AssociateInteractor( vtkRenderWindowInteractor* interactor )
45 {
46   if( interactor != NULL )
47   {
48     this->AssociatedInteractors.push_back( interactor );
49     this->Modified( );
50
51   } // fi
52 }
53
54 // -------------------------------------------------------------------------
55 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
56 SetModeToNavigation( )
57 {
58   this->Mode = Self::NavigationMode;
59 }
60
61 // -------------------------------------------------------------------------
62 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
63 SetModeToDeformation( )
64 {
65   this->Mode = Self::DeformationMode;
66 }
67
68 // -------------------------------------------------------------------------
69 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
70 SetInteractor( vtkRenderWindowInteractor* interactor, const int& axis )
71 {
72   this->Superclass::SetInteractor( interactor );
73   this->OrientationWidget->SetInteractor( interactor );
74   interactor->SetInteractorStyle( this );
75   if( interactor == NULL )
76     return;
77
78   // TODO: interactor->SetPicker( this->PropPicker );
79
80   // Get camera, avoiding segfaults
81   vtkRenderer* ren =
82     interactor->GetRenderWindow( )->GetRenderers( )->GetFirstRenderer( );
83   if( ren == NULL )
84     return;
85   vtkCamera* cam = ren->GetActiveCamera( );
86   if( cam == NULL )
87     return;
88
89   // Parallel projections are better when displaying 2D images
90   cam->ParallelProjectionOn( );
91   cam->SetFocalPoint( double( 0 ), double( 0 ), double( 0 ) );
92   if( axis == 0 )
93   {
94     cam->SetPosition( double( 1 ), double( 0 ), double( 0 ) );
95     cam->SetViewUp  ( double( 0 ), double( 1 ), double( 0 ) );
96   }
97   else if( axis == 1 )
98   {
99     cam->SetPosition( double( 0 ), double( 1 ), double(  0 ) );
100     cam->SetViewUp  ( double( 0 ), double( 0 ), double( -1 ) );
101   }
102   else // if( axis == 2 )
103   {
104     cam->SetPosition( double( 0 ), double( 0 ), double( 1 ) );
105     cam->SetViewUp  ( double( 0 ), double( 1 ), double( 0 ) );
106
107   } // fi
108   ren->ResetCamera( );
109
110   // Enable 2D orientation widget
111   this->OrientationWidget->SetEnabled( 1 );
112   this->OrientationWidget->InteractiveOff( );
113 }
114
115 // -------------------------------------------------------------------------
116 unsigned long cpPlugins::Extensions::Visualization::ImageInteractorStyle::
117 AddDoubleClickObserver( vtkCommand* observer )
118 {
119   return( this->AddObserver( Self::DoubleClickEvent, observer ) );
120 }
121
122 // -------------------------------------------------------------------------
123 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
124 RemoveDoubleClickObserver( unsigned long tag )
125 {
126   this->RemoveObserver( tag );
127 }
128
129 // -------------------------------------------------------------------------
130 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
131 RemoveDoubleClickObserver( vtkCommand* observer )
132 {
133   this->RemoveObserver( observer );
134 }
135
136 // -------------------------------------------------------------------------
137 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
138 RemoveDoubleClickObservers( )
139 {
140   this->RemoveObservers( Self::DoubleClickEvent );
141 }
142
143 // -------------------------------------------------------------------------
144 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
145 OnMouseMove( )
146 {
147   if( this->m_MPRActors == NULL )
148     return;
149   
150   double pos[ 3 ];
151   if( this->CursorMoving )
152   {
153     bool picked = this->_PickPosition( pos );
154     if( picked )
155     {
156       for( int i = 0; i < 3; ++i )
157         if( this->m_SliceActors->GetAxis( ) != i )
158           this->m_MPRActors->SetSlice( i, pos[ i ] );
159       this->Interactor->Render( );
160       this->_RenderAssociateInteractors( );
161
162     } // fi
163   }
164   else
165   {
166     switch( this->State )
167     {
168     case VTKIS_WINDOW_LEVEL:
169       this->WindowLevel( );
170       break;
171     case VTKIS_DOLLY:
172       this->Dolly( );
173       break;
174     case VTKIS_PAN:
175       this->Pan( );
176       break;
177     } // hctiws
178
179   } // fi
180 }
181
182 // -------------------------------------------------------------------------
183 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
184 OnLeftButtonDown( )
185 {
186   static double pnt[ 3 ];
187   static int pos[ 2 ];
188   this->Interactor->GetEventPosition( pos );
189   this->FindPokedRenderer( pos[ 0 ], pos[ 1 ] );
190   if( this->CurrentRenderer == NULL )
191     return;
192   this->GrabFocus( this->EventCallbackCommand );
193
194   // TODO: check this code
195   // Manage double-click
196   static const long epsilon_time = 250;
197   static long last_click_time = -( epsilon_time << 1 );
198   long click_time = static_cast< long >( std::clock( ) );
199   if( ( click_time - last_click_time ) < epsilon_time )
200   {
201     last_click_time = -( epsilon_time << 1 );
202     if( this->_PickPosition( pnt ) )
203       this->InvokeEvent( Self::DoubleClickEvent, pnt );
204   }
205   else
206   {
207     last_click_time = click_time;
208     if( this->Interactor->GetControlKey( ) )
209       this->StartCursorMoving( );
210
211   } // fi
212 }
213
214 // -------------------------------------------------------------------------
215 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
216 OnLeftButtonUp( )
217 {
218   if( this->CursorMoving )
219   {
220     this->EndCursorMoving( );
221     if( this->Interactor )
222       this->ReleaseFocus( );
223
224   } // fi
225 }
226
227 // -------------------------------------------------------------------------
228 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
229 OnMiddleButtonDown( )
230 {
231   int x = this->Interactor->GetEventPosition( )[ 0 ];
232   int y = this->Interactor->GetEventPosition( )[ 1 ];
233
234   this->FindPokedRenderer( x, y );
235   if( this->CurrentRenderer == NULL )
236     return;
237   this->GrabFocus( this->EventCallbackCommand );
238
239   if( this->Interactor->GetAltKey( ) )
240   {
241   }
242   else if( this->Interactor->GetControlKey( ) )
243   {
244   }
245   else if( this->Interactor->GetShiftKey( ) )
246   {
247   }
248   else
249     this->StartPan( );
250 }
251
252 // -------------------------------------------------------------------------
253 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
254 OnMiddleButtonUp( )
255 {
256   switch( this->State )
257   {
258   case VTKIS_PAN:
259     this->EndPan( );
260     break;
261   } // hctiws
262 }
263
264 // -------------------------------------------------------------------------
265 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
266 OnRightButtonDown( )
267 {
268   int x = this->Interactor->GetEventPosition( )[ 0 ];
269   int y = this->Interactor->GetEventPosition( )[ 1 ];
270
271   this->FindPokedRenderer( x, y );
272   if( this->CurrentRenderer == NULL )
273     return;
274   this->GrabFocus( this->EventCallbackCommand );
275
276   if( this->Interactor->GetControlKey( ) )
277   {
278     this->WindowLevelStartPosition[ 0 ] = x;
279     this->WindowLevelStartPosition[ 1 ] = y;
280     this->StartWindowLevel( );
281   }
282   else
283   {
284     this->StartDolly( );
285   } // fi
286 }
287
288 // -------------------------------------------------------------------------
289 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
290 OnRightButtonUp( )
291 {
292   switch( this->State )
293   {
294   case VTKIS_WINDOW_LEVEL:
295   {
296     this->EndWindowLevel( );
297     if( this->Interactor )
298       this->ReleaseFocus( );
299   }
300   break;
301   case VTKIS_DOLLY:
302     this->EndDolly( );
303     break;
304   } // hctiws
305 }
306
307 // -------------------------------------------------------------------------
308 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
309 OnMouseWheelForward( )
310 {
311   if( this->m_SliceActors == NULL || this->Interactor == NULL )
312     return;
313   int off = 1;
314   if( this->Interactor->GetShiftKey( ) == 1 )
315     off *= 10;
316   int s = this->m_SliceActors->GetSliceNumber( ) + off;
317   int maxs = this->m_SliceActors->GetSliceNumberMaxValue( );
318   this->m_SliceActors->SetSliceNumber( ( s < maxs )? s: maxs );
319   this->Interactor->Render( );
320   this->_RenderAssociateInteractors( );
321 }
322
323 // -------------------------------------------------------------------------
324 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
325 OnMouseWheelBackward( )
326 {
327   if( this->m_SliceActors == NULL || this->Interactor == NULL )
328     return;
329   int off = 1;
330   if( this->Interactor->GetShiftKey( ) == 1 )
331     off *= 10;
332   int s = this->m_SliceActors->GetSliceNumber( ) - off;
333   int mins = this->m_SliceActors->GetSliceNumberMinValue( );
334   this->m_SliceActors->SetSliceNumber( ( mins < s )? s: mins );
335   this->Interactor->Render( );
336   this->_RenderAssociateInteractors( );
337 }
338
339 // -------------------------------------------------------------------------
340 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
341 OnChar( )
342 {
343   switch( this->Interactor->GetKeyCode( ) )
344   {
345   case 'r': case 'R':
346   {
347     vtkRenderer* ren =
348       this->Interactor->GetRenderWindow( )->
349       GetRenderers( )->GetFirstRenderer( );
350     if( ren != NULL )
351       ren->ResetCamera( );
352     this->Interactor->Render( );
353   }
354   break;
355   case 'w': case 'W': case 'l': case 'L':
356   {
357     if( this->m_MPRActors != NULL )
358     {
359       this->m_MPRActors->ResetWindowLevel( );
360       this->Interactor->Render( );
361       this->_RenderAssociateInteractors( );
362
363     } // fi
364   }
365   break;
366   } // hctiws
367 }
368
369 // -------------------------------------------------------------------------
370 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
371 WindowLevel( )
372 {
373   if( this->Mode == Self::NavigationMode )
374   {
375     if( this->Interactor == NULL )
376       return;
377     vtkRenderer* ren =
378       this->Interactor->GetRenderWindow( )->
379       GetRenderers( )->GetFirstRenderer( );
380     if( ren == NULL )
381       return;
382
383     // Compute scales
384     this->WindowLevelCurrentPosition[ 0 ] =
385       this->Interactor->GetEventPosition( )[ 0 ];
386     this->WindowLevelCurrentPosition[ 1 ] =
387       this->Interactor->GetEventPosition( )[ 1 ];
388     int* size = ren->GetSize( );
389     double sw = double(
390       this->WindowLevelCurrentPosition[ 0 ] -
391       this->WindowLevelStartPosition[ 0 ]
392       ) / double( size[ 0 ] );
393     double sl = (
394       this->WindowLevelStartPosition[ 1 ] -
395       this->WindowLevelCurrentPosition[ 1 ]
396       ) / double( size[ 1 ] );
397
398     double w = this->WindowLevelInitial[ 0 ] * ( double( 1 ) + sw );
399     double l = this->WindowLevelInitial[ 1 ] * ( double( 1 ) + sl );
400     double minw = this->m_MPRActors->GetMinWindow( );
401     double maxw = this->m_MPRActors->GetMaxWindow( );
402     double minl = this->m_MPRActors->GetMinLevel( );
403     double maxl = this->m_MPRActors->GetMaxLevel( );
404
405     if( w < minw ) w = minw;
406     if( maxw < w ) w = maxw;
407     if( l < minl ) l = minl;
408     if( maxl < l ) l = maxl;
409
410     this->m_MPRActors->SetWindowLevel( w, l );
411     this->Interactor->Render( );
412     this->_RenderAssociateInteractors( );
413   }
414   else if( this->Mode == Self::DeformationMode )
415   {
416     // TODO
417
418   } // fi
419 }
420
421 // -------------------------------------------------------------------------
422 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
423 StartWindowLevel( )
424 {
425   if( this->State != VTKIS_NONE )
426     return;
427   if( this->Mode == Self::NavigationMode )
428   {
429     this->StartState( VTKIS_WINDOW_LEVEL );
430
431     this->WindowLevelInitial[ 0 ] = this->m_MPRActors->GetWindow( );
432     this->WindowLevelInitial[ 1 ] = this->m_MPRActors->GetLevel( );
433   }
434   else if( this->Mode == Self::DeformationMode )
435   {
436     // TODO
437
438   } // fi
439 }
440
441 // -------------------------------------------------------------------------
442 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
443 EndWindowLevel( )
444 {
445   if( this->Mode == Self::NavigationMode )
446   {
447     if( this->State != VTKIS_WINDOW_LEVEL )
448       return;
449     this->StopState( );
450   }
451   else
452   {
453     // TODO
454
455   } // fi
456 }
457
458 // -------------------------------------------------------------------------
459 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
460 StartCursorMoving( )
461 {
462   if( this->CursorMoving )
463     return;
464   this->CursorMoving = true;
465 }
466
467 // -------------------------------------------------------------------------
468 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
469 EndCursorMoving( )
470 {
471   if( !( this->CursorMoving ) )
472     return;
473   this->CursorMoving = false;
474 }
475
476 // -------------------------------------------------------------------------
477 cpPlugins::Extensions::Visualization::ImageInteractorStyle::
478 ImageInteractorStyle( )
479   : Superclass( ),
480     Mode( Self::NavigationMode ),
481     m_SliceActors( NULL ),
482     m_MPRActors( NULL ),
483     CursorMoving( false )
484 {
485   // Orientation marks
486   vtkSmartPointer< vtkAnnotatedCubeActor > cube =
487     vtkSmartPointer< vtkAnnotatedCubeActor >::New( );
488   cube->GetCubeProperty( )->SetColor( 0.9, 0.7, 0.2 );
489   cube->GetTextEdgesProperty( )->SetLineWidth( 1 );
490   cube->GetTextEdgesProperty( )->SetDiffuse( 0 );
491   cube->GetTextEdgesProperty( )->SetAmbient( 1 );
492   cube->GetTextEdgesProperty( )->SetColor( 0.18, 0.28, 0.23 );
493   cube->GetXPlusFaceProperty( )->SetColor( 1, 0, 0 );
494   cube->GetXPlusFaceProperty( )->SetInterpolationToFlat( );
495   cube->GetXMinusFaceProperty( )->SetColor( 1, 0, 0 );
496   cube->GetXMinusFaceProperty( )->SetInterpolationToFlat( );
497   cube->GetYPlusFaceProperty( )->SetColor( 0, 1, 0 );
498   cube->GetYPlusFaceProperty( )->SetInterpolationToFlat( );
499   cube->GetYMinusFaceProperty( )->SetColor( 0, 1, 0 );
500   cube->GetYMinusFaceProperty( )->SetInterpolationToFlat( );
501   cube->GetZPlusFaceProperty( )->SetColor( 0, 0, 1 );
502   cube->GetZPlusFaceProperty( )->SetInterpolationToFlat( );
503   cube->GetZMinusFaceProperty( )->SetColor( 0, 0, 1 );
504   cube->GetZMinusFaceProperty( )->SetInterpolationToFlat( );
505
506   vtkSmartPointer< vtkAxesActor > axes =
507     vtkSmartPointer< vtkAxesActor >::New( );
508   axes->AxisLabelsOff( );
509   axes->SetShaftTypeToCylinder( );
510   axes->SetTotalLength( 2, 2, 2 );
511
512   vtkSmartPointer< vtkPropAssembly > actors =
513     vtkSmartPointer< vtkPropAssembly >::New( );
514   actors->AddPart( cube );
515   actors->AddPart( axes );
516
517   this->OrientationWidget =
518     vtkSmartPointer< vtkOrientationMarkerWidget >::New( );
519   this->OrientationWidget->SetOutlineColor( 0.93, 0.57, 0.13 );
520   this->OrientationWidget->SetOrientationMarker( actors );
521   this->OrientationWidget->SetViewport( 0.0, 0.0, 0.2, 0.2 );
522
523   this->PropPicker = vtkSmartPointer< vtkPropPicker >::New( );
524   this->PropPicker->PickFromListOn( );
525 }
526
527 // -------------------------------------------------------------------------
528 cpPlugins::Extensions::Visualization::ImageInteractorStyle::
529 ~ImageInteractorStyle( )
530 {
531 }
532
533 // -------------------------------------------------------------------------
534 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
535 _RenderAssociateInteractors( )
536 {
537   std::vector< vtkRenderWindowInteractor* >::iterator rIt =
538     this->AssociatedInteractors.begin( );
539   for( ; rIt != this->AssociatedInteractors.end( ); ++rIt )
540     ( *rIt )->Render( );
541 }
542
543 // -------------------------------------------------------------------------
544 bool cpPlugins::Extensions::Visualization::ImageInteractorStyle::
545 _PickPosition( double pos[ 3 ] )
546 {
547   if( this->m_SliceActors == NULL )
548     return( false );
549
550   double x = double( this->Interactor->GetEventPosition( )[ 0 ] );
551   double y = double( this->Interactor->GetEventPosition( )[ 1 ] );
552   this->FindPokedRenderer( x, y );
553   int success =
554     this->PropPicker->Pick( x, y, double( 0 ), this->CurrentRenderer );
555   if( success == 0 )
556     return( false );
557   this->PropPicker->GetPickPosition( pos );
558   return( true );
559 }
560
561 // -------------------------------------------------------------------------
562 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
563 _UpdateCursor( )
564 {
565   std::cout << "upcur" << std::endl;
566 }
567
568 // eof - $RCSfile$