1 #include <cpPlugins/Extensions/Visualization/ImageInteractorStyle.h>
6 #include <vtkAnnotatedCubeActor.h>
7 #include <vtkAxesActor.h>
8 #include <vtkCallbackCommand.h>
10 #include <vtkCellArray.h>
11 #include <vtkCommand.h>
12 #include <vtkMatrix4x4.h>
13 #include <vtkPropAssembly.h>
14 #include <vtkProperty.h>
15 #include <vtkRendererCollection.h>
16 #include <vtkRenderWindow.h>
17 #include <vtkRenderWindowInteractor.h>
19 #include <cpPlugins/Extensions/Visualization/ImageSliceActors.h>
20 #include <cpPlugins/Extensions/Visualization/MPRActors.h>
22 // -------------------------------------------------------------------------
23 const int cpPlugins::Extensions::Visualization::
24 ImageInteractorStyle::CursorEvent = vtkCommand::UserEvent + 1;
25 const int cpPlugins::Extensions::Visualization::
26 ImageInteractorStyle::RadiusEvent = vtkCommand::UserEvent + 2;
27 const int cpPlugins::Extensions::Visualization::
28 ImageInteractorStyle::DoubleClickEvent = vtkCommand::UserEvent + 3;
30 // -------------------------------------------------------------------------
31 cpPlugins::Extensions::Visualization::ImageInteractorStyle::
32 Self* cpPlugins::Extensions::Visualization::ImageInteractorStyle::
35 return( new Self( ) );
38 // -------------------------------------------------------------------------
39 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
40 Configure( ImageSliceActors* slice_actors, MPRActors* mpr_actors )
42 this->m_SliceActors = slice_actors;
43 this->m_MPRActors = mpr_actors;
44 this->SetModeToNavigation( );
45 this->PropPicker->AddPickList( slice_actors->GetImageActor( ) );
49 // -------------------------------------------------------------------------
50 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
51 AssociateInteractor( vtkRenderWindowInteractor* interactor )
53 if( interactor != NULL )
55 this->AssociatedInteractors.push_back( interactor );
61 // -------------------------------------------------------------------------
62 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
63 SetModeToNavigation( )
65 this->Mode = Self::NavigationMode;
68 // -------------------------------------------------------------------------
69 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
70 SetModeToDeformation( )
72 this->Mode = Self::DeformationMode;
75 // -------------------------------------------------------------------------
76 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
77 SetInteractor( vtkRenderWindowInteractor* interactor, const int& axis )
79 this->Superclass::SetInteractor( interactor );
80 this->OrientationWidget->SetInteractor( interactor );
81 interactor->SetInteractorStyle( this );
82 if( interactor == NULL )
85 // Get camera, avoiding segfaults
87 interactor->GetRenderWindow( )->GetRenderers( )->GetFirstRenderer( );
90 vtkCamera* cam = ren->GetActiveCamera( );
94 // Parallel projections are better when displaying 2D images
95 cam->ParallelProjectionOn( );
96 cam->SetFocalPoint( double( 0 ), double( 0 ), double( 0 ) );
99 cam->SetPosition( double( 1 ), double( 0 ), double( 0 ) );
100 cam->SetViewUp ( double( 0 ), double( 1 ), double( 0 ) );
104 cam->SetPosition( double( 0 ), double( 1 ), double( 0 ) );
105 cam->SetViewUp ( double( 0 ), double( 0 ), double( -1 ) );
107 else // if( axis == 2 )
109 cam->SetPosition( double( 0 ), double( 0 ), double( 1 ) );
110 cam->SetViewUp ( double( 0 ), double( 1 ), double( 0 ) );
115 // Enable 2D orientation widget
116 this->OrientationWidget->SetEnabled( 1 );
117 this->OrientationWidget->InteractiveOff( );
120 // -------------------------------------------------------------------------
121 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
124 if( this->m_MPRActors == NULL )
127 if( this->CursorMoving )
129 bool picked = this->_PickPosition( this->Cursor );
132 for( int i = 0; i < 3; ++i )
133 if( this->m_SliceActors->GetAxis( ) != i )
134 this->m_MPRActors->SetSlice( i, this->Cursor[ i ] );
135 this->InvokeEvent( Self::CursorEvent, this->Cursor );
136 this->Interactor->Render( );
137 this->_RenderAssociateInteractors( );
141 else if( this->RadiusMoving )
143 bool picked = this->_PickPosition( this->Radius );
146 this->InvokeEvent( Self::RadiusEvent, this->Radius );
147 this->_UpdateRadius( );
153 switch( this->State )
155 case VTKIS_WINDOW_LEVEL:
156 this->WindowLevel( );
169 // -------------------------------------------------------------------------
170 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
173 static double pnt[ 3 ];
175 this->Interactor->GetEventPosition( pos );
176 this->FindPokedRenderer( pos[ 0 ], pos[ 1 ] );
177 if( this->CurrentRenderer == NULL )
179 this->GrabFocus( this->EventCallbackCommand );
181 // TODO: check this code
182 // Manage double-click
183 static const long epsilon_time = 800;
184 static long last_click_time = -( epsilon_time << 1 );
185 long click_time = static_cast< long >( std::clock( ) );
186 if( ( click_time - last_click_time ) < epsilon_time )
188 last_click_time = -( epsilon_time << 1 );
189 if( this->_PickPosition( pnt ) )
190 this->InvokeEvent( Self::DoubleClickEvent, pnt );
194 last_click_time = click_time;
195 if( this->Interactor->GetControlKey( ) )
196 this->StartCursorMoving( );
201 // -------------------------------------------------------------------------
202 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
205 if( this->CursorMoving )
207 this->EndCursorMoving( );
208 if( this->Interactor )
209 this->ReleaseFocus( );
214 // -------------------------------------------------------------------------
215 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
216 OnMiddleButtonDown( )
218 int x = this->Interactor->GetEventPosition( )[ 0 ];
219 int y = this->Interactor->GetEventPosition( )[ 1 ];
221 this->FindPokedRenderer( x, y );
222 if( this->CurrentRenderer == NULL )
224 this->GrabFocus( this->EventCallbackCommand );
226 if( this->Interactor->GetAltKey( ) )
229 else if( this->Interactor->GetControlKey( ) )
231 this->StartRadiusMoving( );
233 else if( this->Interactor->GetShiftKey( ) )
240 // -------------------------------------------------------------------------
241 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
244 if( this->RadiusMoving )
246 this->EndRadiusMoving( );
247 if( this->Interactor )
248 this->ReleaseFocus( );
252 switch( this->State )
262 // -------------------------------------------------------------------------
263 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
266 int x = this->Interactor->GetEventPosition( )[ 0 ];
267 int y = this->Interactor->GetEventPosition( )[ 1 ];
269 this->FindPokedRenderer( x, y );
270 if( this->CurrentRenderer == NULL )
272 this->GrabFocus( this->EventCallbackCommand );
274 if( this->Interactor->GetControlKey( ) )
276 this->WindowLevelStartPosition[ 0 ] = x;
277 this->WindowLevelStartPosition[ 1 ] = y;
278 this->StartWindowLevel( );
287 // -------------------------------------------------------------------------
288 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
291 switch( this->State )
293 case VTKIS_WINDOW_LEVEL:
295 this->EndWindowLevel( );
296 if( this->Interactor )
297 this->ReleaseFocus( );
306 // -------------------------------------------------------------------------
307 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
308 OnMouseWheelForward( )
310 if( this->m_SliceActors == NULL || this->Interactor == NULL )
313 if( this->Interactor->GetShiftKey( ) == 1 )
315 int s = this->m_SliceActors->GetSliceNumber( ) + off;
316 int maxs = this->m_SliceActors->GetSliceNumberMaxValue( );
317 this->m_SliceActors->SetSliceNumber( ( s < maxs )? s: maxs );
318 this->Interactor->Render( );
319 this->_RenderAssociateInteractors( );
322 // -------------------------------------------------------------------------
323 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
324 OnMouseWheelBackward( )
326 if( this->m_SliceActors == NULL || this->Interactor == NULL )
329 if( this->Interactor->GetShiftKey( ) == 1 )
331 int s = this->m_SliceActors->GetSliceNumber( ) - off;
332 int mins = this->m_SliceActors->GetSliceNumberMinValue( );
333 this->m_SliceActors->SetSliceNumber( ( mins < s )? s: mins );
334 this->Interactor->Render( );
335 this->_RenderAssociateInteractors( );
338 // -------------------------------------------------------------------------
339 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
342 switch( this->Interactor->GetKeyCode( ) )
347 this->Interactor->GetRenderWindow( )->
348 GetRenderers( )->GetFirstRenderer( );
351 this->Interactor->Render( );
354 case 'w': case 'W': case 'l': case 'L':
356 if( this->m_MPRActors != NULL )
358 this->m_MPRActors->ResetWindowLevel( );
359 this->Interactor->Render( );
360 this->_RenderAssociateInteractors( );
368 // -------------------------------------------------------------------------
369 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
372 if( this->Mode == Self::NavigationMode )
374 if( this->Interactor == NULL )
377 this->Interactor->GetRenderWindow( )->
378 GetRenderers( )->GetFirstRenderer( );
383 this->WindowLevelCurrentPosition[ 0 ] =
384 this->Interactor->GetEventPosition( )[ 0 ];
385 this->WindowLevelCurrentPosition[ 1 ] =
386 this->Interactor->GetEventPosition( )[ 1 ];
387 int* size = ren->GetSize( );
389 this->WindowLevelCurrentPosition[ 0 ] -
390 this->WindowLevelStartPosition[ 0 ]
391 ) / double( size[ 0 ] );
393 this->WindowLevelStartPosition[ 1 ] -
394 this->WindowLevelCurrentPosition[ 1 ]
395 ) / double( size[ 1 ] );
397 double w = this->WindowLevelInitial[ 0 ] * ( double( 1 ) + sw );
398 double l = this->WindowLevelInitial[ 1 ] * ( double( 1 ) + sl );
399 double minw = this->m_MPRActors->GetMinWindow( );
400 double maxw = this->m_MPRActors->GetMaxWindow( );
401 double minl = this->m_MPRActors->GetMinLevel( );
402 double maxl = this->m_MPRActors->GetMaxLevel( );
404 if( w < minw ) w = minw;
405 if( maxw < w ) w = maxw;
406 if( l < minl ) l = minl;
407 if( maxl < l ) l = maxl;
409 this->m_MPRActors->SetWindowLevel( w, l );
410 this->Interactor->Render( );
411 this->_RenderAssociateInteractors( );
413 else if( this->Mode == Self::DeformationMode )
420 // -------------------------------------------------------------------------
421 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
424 if( this->State != VTKIS_NONE )
426 if( this->Mode == Self::NavigationMode )
428 this->StartState( VTKIS_WINDOW_LEVEL );
430 this->WindowLevelInitial[ 0 ] = this->m_MPRActors->GetWindow( );
431 this->WindowLevelInitial[ 1 ] = this->m_MPRActors->GetLevel( );
433 else if( this->Mode == Self::DeformationMode )
440 // -------------------------------------------------------------------------
441 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
444 if( this->Mode == Self::NavigationMode )
446 if( this->State != VTKIS_WINDOW_LEVEL )
457 // -------------------------------------------------------------------------
458 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
461 if( this->CursorMoving )
463 this->_PickPosition( this->Cursor );
464 this->CursorMoving = true;
467 // -------------------------------------------------------------------------
468 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
471 if( !( this->CursorMoving ) )
473 this->CursorMoving = false;
476 // -------------------------------------------------------------------------
477 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
480 if( this->RadiusMoving )
482 this->_PickPosition( this->Radius );
483 this->RadiusMoving = true;
484 this->_UpdateRadius( );
487 // -------------------------------------------------------------------------
488 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
491 if( !( this->RadiusMoving ) )
493 this->RadiusMoving = false;
494 this->_UpdateRadius( );
495 this->InvokeEvent( Self::RadiusEvent, NULL );
498 // -------------------------------------------------------------------------
499 cpPlugins::Extensions::Visualization::ImageInteractorStyle::
500 ImageInteractorStyle( )
502 Mode( Self::NavigationMode ),
503 m_SliceActors( NULL ),
505 CursorMoving( false ),
506 RadiusMoving( false )
509 vtkSmartPointer< vtkAnnotatedCubeActor > cube =
510 vtkSmartPointer< vtkAnnotatedCubeActor >::New( );
511 cube->GetCubeProperty( )->SetColor( 0.9, 0.7, 0.2 );
512 cube->GetTextEdgesProperty( )->SetLineWidth( 1 );
513 cube->GetTextEdgesProperty( )->SetDiffuse( 0 );
514 cube->GetTextEdgesProperty( )->SetAmbient( 1 );
515 cube->GetTextEdgesProperty( )->SetColor( 0.18, 0.28, 0.23 );
516 cube->GetXPlusFaceProperty( )->SetColor( 1, 0, 0 );
517 cube->GetXPlusFaceProperty( )->SetInterpolationToFlat( );
518 cube->GetXMinusFaceProperty( )->SetColor( 1, 0, 0 );
519 cube->GetXMinusFaceProperty( )->SetInterpolationToFlat( );
520 cube->GetYPlusFaceProperty( )->SetColor( 0, 1, 0 );
521 cube->GetYPlusFaceProperty( )->SetInterpolationToFlat( );
522 cube->GetYMinusFaceProperty( )->SetColor( 0, 1, 0 );
523 cube->GetYMinusFaceProperty( )->SetInterpolationToFlat( );
524 cube->GetZPlusFaceProperty( )->SetColor( 0, 0, 1 );
525 cube->GetZPlusFaceProperty( )->SetInterpolationToFlat( );
526 cube->GetZMinusFaceProperty( )->SetColor( 0, 0, 1 );
527 cube->GetZMinusFaceProperty( )->SetInterpolationToFlat( );
529 vtkSmartPointer< vtkAxesActor > axes =
530 vtkSmartPointer< vtkAxesActor >::New( );
531 axes->AxisLabelsOff( );
532 axes->SetShaftTypeToCylinder( );
533 axes->SetTotalLength( 2, 2, 2 );
535 vtkSmartPointer< vtkPropAssembly > actors =
536 vtkSmartPointer< vtkPropAssembly >::New( );
537 actors->AddPart( cube );
538 actors->AddPart( axes );
540 this->OrientationWidget =
541 vtkSmartPointer< vtkOrientationMarkerWidget >::New( );
542 this->OrientationWidget->SetOutlineColor( 0.93, 0.57, 0.13 );
543 this->OrientationWidget->SetOrientationMarker( actors );
544 this->OrientationWidget->SetViewport( 0.0, 0.0, 0.2, 0.2 );
547 unsigned long circle_samples = 1000;
548 this->Circle = vtkSmartPointer< vtkPolyData >::New( );
550 vtkSmartPointer< vtkPoints > circle_points =
551 vtkSmartPointer< vtkPoints >::New( );
552 vtkSmartPointer< vtkCellArray > circle_lines =
553 vtkSmartPointer< vtkCellArray >::New( );
554 for( unsigned long s = 0; s < circle_samples; ++s )
556 double t = double( 6.2832 ) * double( s ) / double( circle_samples );
557 circle_points->InsertNextPoint(
558 std::cos( t ), std::sin( t ), double( 0 )
561 circle_lines->InsertNextCell( 2 );
562 circle_lines->InsertCellPoint( s );
563 circle_lines->InsertCellPoint( ( s + 1 ) % circle_samples );
566 this->Circle->SetPoints( circle_points );
567 this->Circle->SetLines( circle_lines );
569 this->CircleMapper = vtkSmartPointer< vtkPolyDataMapper >::New( );
570 this->CircleMapper->SetInputData( this->Circle );
571 this->CircleActor = vtkSmartPointer< vtkActor >::New( );
572 this->CircleActor->SetMapper( this->CircleMapper );
573 this->CircleActor->GetProperty( )->SetColor( 1, 0, 1 );
574 this->CircleActor->GetProperty( )->SetLineWidth( 2 );
576 this->PropPicker = vtkSmartPointer< vtkPropPicker >::New( );
577 this->PropPicker->PickFromListOn( );
580 // -------------------------------------------------------------------------
581 cpPlugins::Extensions::Visualization::ImageInteractorStyle::
582 ~ImageInteractorStyle( )
586 // -------------------------------------------------------------------------
587 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
588 _RenderAssociateInteractors( )
590 std::vector< vtkRenderWindowInteractor* >::iterator rIt =
591 this->AssociatedInteractors.begin( );
592 for( ; rIt != this->AssociatedInteractors.end( ); ++rIt )
596 // -------------------------------------------------------------------------
597 bool cpPlugins::Extensions::Visualization::ImageInteractorStyle::
598 _PickPosition( double pos[ 3 ] )
600 if( this->m_SliceActors == NULL )
603 double x = double( this->Interactor->GetEventPosition( )[ 0 ] );
604 double y = double( this->Interactor->GetEventPosition( )[ 1 ] );
605 this->FindPokedRenderer( x, y );
607 this->PropPicker->Pick( x, y, double( 0 ), this->CurrentRenderer );
610 this->PropPicker->GetPickPosition( pos );
612 int axis = this->m_SliceActors->GetAxis( );
613 double* bounds = this->m_SliceActors->GetDisplayBounds( );
614 pos[ axis ] = bounds[ axis << 1 ];
619 // -------------------------------------------------------------------------
620 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
623 std::cout << "upcur" << std::endl;
626 // -------------------------------------------------------------------------
627 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
631 this->Interactor->GetRenderWindow( )->
632 GetRenderers( )->GetFirstRenderer( );
635 vtkCamera* cam = ren->GetActiveCamera( );
639 if( this->RadiusMoving )
641 double x = this->Cursor[ 0 ] - this->Radius[ 0 ];
642 double y = this->Cursor[ 1 ] - this->Radius[ 1 ];
643 double z = this->Cursor[ 2 ] - this->Radius[ 2 ];
644 double r = std::sqrt( ( x * x ) + ( y * y ) + ( z * z ) );
646 vtkMatrix4x4* cam_matrix = cam->GetModelViewTransformMatrix( );
647 vtkSmartPointer< vtkMatrix4x4 > circle_matrix =
648 this->CircleActor->GetUserMatrix( );
649 if( circle_matrix.GetPointer( ) == NULL )
651 circle_matrix = vtkSmartPointer< vtkMatrix4x4 >::New( );
652 this->CircleActor->SetUserMatrix( circle_matrix );
655 for( int i = 0; i < 4; ++i )
657 for( int j = 0; j < 4; ++j )
659 double v = cam_matrix->GetElement( i, j );
660 if( i < 3 && j == 3 )
661 v = this->Cursor[ i ];
664 circle_matrix->SetElement( i, j, v );
669 this->CircleActor->Modified( );
670 ren->AddActor( this->CircleActor );
673 ren->RemoveActor( this->CircleActor );
675 this->Interactor->Render( );