1 #include <cpExtensions/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 <cpExtensions/Visualization/ImageSliceActors.h>
20 #include <cpExtensions/Visualization/MPRActors.h>
22 // -------------------------------------------------------------------------
23 const int cpExtensions::Visualization::
24 ImageInteractorStyle::CursorEvent = vtkCommand::UserEvent + 1;
25 const int cpExtensions::Visualization::
26 ImageInteractorStyle::RadiusEvent = vtkCommand::UserEvent + 2;
27 const int cpExtensions::Visualization::
28 ImageInteractorStyle::DoubleClickEvent = vtkCommand::UserEvent + 3;
30 // -------------------------------------------------------------------------
31 cpExtensions::Visualization::ImageInteractorStyle::
32 Self* cpExtensions::Visualization::ImageInteractorStyle::
35 return( new Self( ) );
38 // -------------------------------------------------------------------------
39 void cpExtensions::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( 0 ) );
49 // -------------------------------------------------------------------------
50 void cpExtensions::Visualization::ImageInteractorStyle::
51 AssociateInteractor( vtkRenderWindowInteractor* interactor )
53 if( interactor != NULL )
55 this->AssociatedInteractors.push_back( interactor );
61 // -------------------------------------------------------------------------
62 void cpExtensions::Visualization::ImageInteractorStyle::
63 SetModeToNavigation( )
65 this->Mode = Self::NavigationMode;
68 // -------------------------------------------------------------------------
69 void cpExtensions::Visualization::ImageInteractorStyle::
70 SetModeToDeformation( )
72 this->Mode = Self::DeformationMode;
75 // -------------------------------------------------------------------------
76 void cpExtensions::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 cpExtensions::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 cpExtensions::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 cpExtensions::Visualization::ImageInteractorStyle::
205 if( this->CursorMoving )
207 this->EndCursorMoving( );
208 if( this->Interactor )
209 this->ReleaseFocus( );
214 // -------------------------------------------------------------------------
215 void cpExtensions::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 cpExtensions::Visualization::ImageInteractorStyle::
244 if( this->RadiusMoving )
246 this->EndRadiusMoving( );
247 if( this->Interactor )
248 this->ReleaseFocus( );
252 switch( this->State )
262 // -------------------------------------------------------------------------
263 void cpExtensions::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 cpExtensions::Visualization::ImageInteractorStyle::
291 switch( this->State )
293 case VTKIS_WINDOW_LEVEL:
295 this->EndWindowLevel( );
296 if( this->Interactor )
297 this->ReleaseFocus( );
306 // -------------------------------------------------------------------------
307 void cpExtensions::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->m_MPRActors->SetSlice(
319 this->m_SliceActors->GetAxis( ),
320 this->m_SliceActors->GetSliceNumber( )
322 this->Interactor->Render( );
323 this->_RenderAssociateInteractors( );
326 // -------------------------------------------------------------------------
327 void cpExtensions::Visualization::ImageInteractorStyle::
328 OnMouseWheelBackward( )
330 if( this->m_SliceActors == NULL || this->Interactor == NULL )
333 if( this->Interactor->GetShiftKey( ) == 1 )
335 int s = this->m_SliceActors->GetSliceNumber( ) - off;
336 int mins = this->m_SliceActors->GetSliceNumberMinValue( );
337 this->m_SliceActors->SetSliceNumber( ( mins < s )? s: mins );
338 this->m_MPRActors->SetSlice(
339 this->m_SliceActors->GetAxis( ),
340 this->m_SliceActors->GetSliceNumber( )
342 this->Interactor->Render( );
343 this->_RenderAssociateInteractors( );
346 // -------------------------------------------------------------------------
347 void cpExtensions::Visualization::ImageInteractorStyle::
350 switch( this->Interactor->GetKeyCode( ) )
355 this->Interactor->GetRenderWindow( )->
356 GetRenderers( )->GetFirstRenderer( );
359 this->Interactor->Render( );
362 case 'w': case 'W': case 'l': case 'L':
364 if( this->m_MPRActors != NULL )
366 this->m_MPRActors->ResetWindowLevel( 0 );
367 this->Interactor->Render( );
368 this->_RenderAssociateInteractors( );
376 // -------------------------------------------------------------------------
377 void cpExtensions::Visualization::ImageInteractorStyle::
380 if( this->Mode == Self::NavigationMode )
382 if( this->Interactor == NULL )
385 this->Interactor->GetRenderWindow( )->
386 GetRenderers( )->GetFirstRenderer( );
391 this->WindowLevelCurrentPosition[ 0 ] =
392 this->Interactor->GetEventPosition( )[ 0 ];
393 this->WindowLevelCurrentPosition[ 1 ] =
394 this->Interactor->GetEventPosition( )[ 1 ];
395 int* size = ren->GetSize( );
397 this->WindowLevelCurrentPosition[ 0 ] -
398 this->WindowLevelStartPosition[ 0 ]
399 ) / double( size[ 0 ] );
401 this->WindowLevelStartPosition[ 1 ] -
402 this->WindowLevelCurrentPosition[ 1 ]
403 ) / double( size[ 1 ] );
405 double w = this->WindowLevelInitial[ 0 ] * ( double( 1 ) + sw );
406 double l = this->WindowLevelInitial[ 1 ] * ( double( 1 ) + sl );
407 double minw = this->m_MPRActors->GetMinWindow( 0 );
408 double maxw = this->m_MPRActors->GetMaxWindow( 0 );
409 double minl = this->m_MPRActors->GetMinLevel( 0 );
410 double maxl = this->m_MPRActors->GetMaxLevel( 0 );
412 if( w < minw ) w = minw;
413 if( maxw < w ) w = maxw;
414 if( l < minl ) l = minl;
415 if( maxl < l ) l = maxl;
417 this->m_MPRActors->SetWindow( 0, w );
418 this->m_MPRActors->SetLevel( 0, l );
419 this->Interactor->Render( );
420 this->_RenderAssociateInteractors( );
422 else if( this->Mode == Self::DeformationMode )
429 // -------------------------------------------------------------------------
430 void cpExtensions::Visualization::ImageInteractorStyle::
433 if( this->State != VTKIS_NONE )
435 if( this->Mode == Self::NavigationMode )
437 this->StartState( VTKIS_WINDOW_LEVEL );
439 this->WindowLevelInitial[ 0 ] = this->m_MPRActors->GetWindow( 0 );
440 this->WindowLevelInitial[ 1 ] = this->m_MPRActors->GetLevel( 0 );
442 else if( this->Mode == Self::DeformationMode )
449 // -------------------------------------------------------------------------
450 void cpExtensions::Visualization::ImageInteractorStyle::
453 if( this->Mode == Self::NavigationMode )
455 if( this->State != VTKIS_WINDOW_LEVEL )
466 // -------------------------------------------------------------------------
467 void cpExtensions::Visualization::ImageInteractorStyle::
470 if( this->CursorMoving )
472 this->_PickPosition( this->Cursor );
473 this->CursorMoving = true;
476 // -------------------------------------------------------------------------
477 void cpExtensions::Visualization::ImageInteractorStyle::
480 if( !( this->CursorMoving ) )
482 this->CursorMoving = false;
485 // -------------------------------------------------------------------------
486 void cpExtensions::Visualization::ImageInteractorStyle::
489 if( this->RadiusMoving )
491 this->_PickPosition( this->Radius );
492 this->RadiusMoving = true;
493 this->_UpdateRadius( );
496 // -------------------------------------------------------------------------
497 void cpExtensions::Visualization::ImageInteractorStyle::
500 if( !( this->RadiusMoving ) )
502 this->RadiusMoving = false;
503 this->_UpdateRadius( );
504 this->InvokeEvent( Self::RadiusEvent, NULL );
507 // -------------------------------------------------------------------------
508 cpExtensions::Visualization::ImageInteractorStyle::
509 ImageInteractorStyle( )
511 Mode( Self::NavigationMode ),
512 m_SliceActors( NULL ),
514 CursorMoving( false ),
515 RadiusMoving( false )
518 vtkSmartPointer< vtkAnnotatedCubeActor > cube =
519 vtkSmartPointer< vtkAnnotatedCubeActor >::New( );
520 cube->GetCubeProperty( )->SetColor( 0.9, 0.7, 0.2 );
521 cube->GetTextEdgesProperty( )->SetLineWidth( 1 );
522 cube->GetTextEdgesProperty( )->SetDiffuse( 0 );
523 cube->GetTextEdgesProperty( )->SetAmbient( 1 );
524 cube->GetTextEdgesProperty( )->SetColor( 0.18, 0.28, 0.23 );
525 cube->GetXPlusFaceProperty( )->SetColor( 1, 0, 0 );
526 cube->GetXPlusFaceProperty( )->SetInterpolationToFlat( );
527 cube->GetXMinusFaceProperty( )->SetColor( 1, 0, 0 );
528 cube->GetXMinusFaceProperty( )->SetInterpolationToFlat( );
529 cube->GetYPlusFaceProperty( )->SetColor( 0, 1, 0 );
530 cube->GetYPlusFaceProperty( )->SetInterpolationToFlat( );
531 cube->GetYMinusFaceProperty( )->SetColor( 0, 1, 0 );
532 cube->GetYMinusFaceProperty( )->SetInterpolationToFlat( );
533 cube->GetZPlusFaceProperty( )->SetColor( 0, 0, 1 );
534 cube->GetZPlusFaceProperty( )->SetInterpolationToFlat( );
535 cube->GetZMinusFaceProperty( )->SetColor( 0, 0, 1 );
536 cube->GetZMinusFaceProperty( )->SetInterpolationToFlat( );
538 vtkSmartPointer< vtkAxesActor > axes =
539 vtkSmartPointer< vtkAxesActor >::New( );
540 axes->AxisLabelsOff( );
541 axes->SetShaftTypeToCylinder( );
542 axes->SetTotalLength( 2, 2, 2 );
544 vtkSmartPointer< vtkPropAssembly > actors =
545 vtkSmartPointer< vtkPropAssembly >::New( );
546 actors->AddPart( cube );
547 actors->AddPart( axes );
549 this->OrientationWidget =
550 vtkSmartPointer< vtkOrientationMarkerWidget >::New( );
551 this->OrientationWidget->SetOutlineColor( 0.93, 0.57, 0.13 );
552 this->OrientationWidget->SetOrientationMarker( actors );
553 this->OrientationWidget->SetViewport( 0.0, 0.0, 0.2, 0.2 );
556 unsigned long circle_samples = 1000;
557 this->Circle = vtkSmartPointer< vtkPolyData >::New( );
559 vtkSmartPointer< vtkPoints > circle_points =
560 vtkSmartPointer< vtkPoints >::New( );
561 vtkSmartPointer< vtkCellArray > circle_lines =
562 vtkSmartPointer< vtkCellArray >::New( );
563 for( unsigned long s = 0; s < circle_samples; ++s )
565 double t = double( 6.2832 ) * double( s ) / double( circle_samples );
566 circle_points->InsertNextPoint(
567 std::cos( t ), std::sin( t ), double( 0 )
570 circle_lines->InsertNextCell( 2 );
571 circle_lines->InsertCellPoint( s );
572 circle_lines->InsertCellPoint( ( s + 1 ) % circle_samples );
575 this->Circle->SetPoints( circle_points );
576 this->Circle->SetLines( circle_lines );
578 this->CircleMapper = vtkSmartPointer< vtkPolyDataMapper >::New( );
579 this->CircleMapper->SetInputData( this->Circle );
580 this->CircleActor = vtkSmartPointer< vtkActor >::New( );
581 this->CircleActor->SetMapper( this->CircleMapper );
582 this->CircleActor->GetProperty( )->SetColor( 1, 0, 1 );
583 this->CircleActor->GetProperty( )->SetLineWidth( 2 );
585 this->PropPicker = vtkSmartPointer< vtkPropPicker >::New( );
586 this->PropPicker->PickFromListOn( );
589 // -------------------------------------------------------------------------
590 cpExtensions::Visualization::ImageInteractorStyle::
591 ~ImageInteractorStyle( )
595 // -------------------------------------------------------------------------
596 void cpExtensions::Visualization::ImageInteractorStyle::
597 _RenderAssociateInteractors( )
599 std::vector< vtkRenderWindowInteractor* >::iterator rIt =
600 this->AssociatedInteractors.begin( );
601 for( ; rIt != this->AssociatedInteractors.end( ); ++rIt )
605 // -------------------------------------------------------------------------
606 bool cpExtensions::Visualization::ImageInteractorStyle::
607 _PickPosition( double pos[ 3 ] )
609 if( this->m_SliceActors == NULL )
612 double x = double( this->Interactor->GetEventPosition( )[ 0 ] );
613 double y = double( this->Interactor->GetEventPosition( )[ 1 ] );
614 this->FindPokedRenderer( x, y );
616 this->PropPicker->Pick( x, y, double( 0 ), this->CurrentRenderer );
619 this->PropPicker->GetPickPosition( pos );
621 int axis = this->m_SliceActors->GetAxis( );
622 double* bounds = this->m_SliceActors->GetDisplayBounds( );
623 pos[ axis ] = bounds[ axis << 1 ];
628 // -------------------------------------------------------------------------
629 void cpExtensions::Visualization::ImageInteractorStyle::
632 std::cout << "upcur" << std::endl;
635 // -------------------------------------------------------------------------
636 void cpExtensions::Visualization::ImageInteractorStyle::
640 this->Interactor->GetRenderWindow( )->
641 GetRenderers( )->GetFirstRenderer( );
644 vtkCamera* cam = ren->GetActiveCamera( );
648 if( this->RadiusMoving )
650 double x = this->Cursor[ 0 ] - this->Radius[ 0 ];
651 double y = this->Cursor[ 1 ] - this->Radius[ 1 ];
652 double z = this->Cursor[ 2 ] - this->Radius[ 2 ];
653 double r = std::sqrt( ( x * x ) + ( y * y ) + ( z * z ) );
655 vtkMatrix4x4* cam_matrix = cam->GetModelViewTransformMatrix( );
656 vtkSmartPointer< vtkMatrix4x4 > circle_matrix =
657 this->CircleActor->GetUserMatrix( );
658 if( circle_matrix.GetPointer( ) == NULL )
660 circle_matrix = vtkSmartPointer< vtkMatrix4x4 >::New( );
661 this->CircleActor->SetUserMatrix( circle_matrix );
664 for( int i = 0; i < 4; ++i )
666 for( int j = 0; j < 4; ++j )
668 double v = cam_matrix->GetElement( i, j );
669 if( i < 3 && j == 3 )
670 v = this->Cursor[ i ];
673 circle_matrix->SetElement( i, j, v );
678 this->CircleActor->Modified( );
679 ren->AddActor( this->CircleActor );
682 ren->RemoveActor( this->CircleActor );
684 this->Interactor->Render( );