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( );
286 // -------------------------------------------------------------------------
287 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
290 switch( this->State )
292 case VTKIS_WINDOW_LEVEL:
294 this->EndWindowLevel( );
295 if( this->Interactor )
296 this->ReleaseFocus( );
305 // -------------------------------------------------------------------------
306 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
307 OnMouseWheelForward( )
309 if( this->m_SliceActors == NULL || this->Interactor == NULL )
312 if( this->Interactor->GetShiftKey( ) == 1 )
314 int s = this->m_SliceActors->GetSliceNumber( ) + off;
315 int maxs = this->m_SliceActors->GetSliceNumberMaxValue( );
316 this->m_SliceActors->SetSliceNumber( ( s < maxs )? s: maxs );
317 this->Interactor->Render( );
318 this->_RenderAssociateInteractors( );
321 // -------------------------------------------------------------------------
322 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
323 OnMouseWheelBackward( )
325 if( this->m_SliceActors == NULL || this->Interactor == NULL )
328 if( this->Interactor->GetShiftKey( ) == 1 )
330 int s = this->m_SliceActors->GetSliceNumber( ) - off;
331 int mins = this->m_SliceActors->GetSliceNumberMinValue( );
332 this->m_SliceActors->SetSliceNumber( ( mins < s )? s: mins );
333 this->Interactor->Render( );
334 this->_RenderAssociateInteractors( );
337 // -------------------------------------------------------------------------
338 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
341 switch( this->Interactor->GetKeyCode( ) )
346 this->Interactor->GetRenderWindow( )->
347 GetRenderers( )->GetFirstRenderer( );
350 this->Interactor->Render( );
353 case 'w': case 'W': case 'l': case 'L':
355 if( this->m_MPRActors != NULL )
357 this->m_MPRActors->ResetWindowLevel( );
358 this->Interactor->Render( );
359 this->_RenderAssociateInteractors( );
367 // -------------------------------------------------------------------------
368 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
371 if( this->Mode == Self::NavigationMode )
373 if( this->Interactor == NULL )
376 this->Interactor->GetRenderWindow( )->
377 GetRenderers( )->GetFirstRenderer( );
382 this->WindowLevelCurrentPosition[ 0 ] =
383 this->Interactor->GetEventPosition( )[ 0 ];
384 this->WindowLevelCurrentPosition[ 1 ] =
385 this->Interactor->GetEventPosition( )[ 1 ];
386 int* size = ren->GetSize( );
388 this->WindowLevelCurrentPosition[ 0 ] -
389 this->WindowLevelStartPosition[ 0 ]
390 ) / double( size[ 0 ] );
392 this->WindowLevelStartPosition[ 1 ] -
393 this->WindowLevelCurrentPosition[ 1 ]
394 ) / double( size[ 1 ] );
396 double w = this->WindowLevelInitial[ 0 ] * ( double( 1 ) + sw );
397 double l = this->WindowLevelInitial[ 1 ] * ( double( 1 ) + sl );
398 double minw = this->m_MPRActors->GetMinWindow( );
399 double maxw = this->m_MPRActors->GetMaxWindow( );
400 double minl = this->m_MPRActors->GetMinLevel( );
401 double maxl = this->m_MPRActors->GetMaxLevel( );
403 if( w < minw ) w = minw;
404 if( maxw < w ) w = maxw;
405 if( l < minl ) l = minl;
406 if( maxl < l ) l = maxl;
408 this->m_MPRActors->SetWindowLevel( w, l );
409 this->Interactor->Render( );
410 this->_RenderAssociateInteractors( );
412 else if( this->Mode == Self::DeformationMode )
419 // -------------------------------------------------------------------------
420 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
423 if( this->State != VTKIS_NONE )
425 if( this->Mode == Self::NavigationMode )
427 this->StartState( VTKIS_WINDOW_LEVEL );
429 this->WindowLevelInitial[ 0 ] = this->m_MPRActors->GetWindow( );
430 this->WindowLevelInitial[ 1 ] = this->m_MPRActors->GetLevel( );
432 else if( this->Mode == Self::DeformationMode )
439 // -------------------------------------------------------------------------
440 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
443 if( this->Mode == Self::NavigationMode )
445 if( this->State != VTKIS_WINDOW_LEVEL )
456 // -------------------------------------------------------------------------
457 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
460 if( this->CursorMoving )
462 this->_PickPosition( this->Cursor );
463 this->CursorMoving = true;
466 // -------------------------------------------------------------------------
467 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
470 if( !( this->CursorMoving ) )
472 this->CursorMoving = false;
475 // -------------------------------------------------------------------------
476 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
479 if( this->RadiusMoving )
481 this->_PickPosition( this->Radius );
482 this->RadiusMoving = true;
483 this->_UpdateRadius( );
486 // -------------------------------------------------------------------------
487 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
490 if( !( this->RadiusMoving ) )
492 this->RadiusMoving = false;
493 this->_UpdateRadius( );
494 this->InvokeEvent( Self::RadiusEvent, NULL );
497 // -------------------------------------------------------------------------
498 cpPlugins::Extensions::Visualization::ImageInteractorStyle::
499 ImageInteractorStyle( )
501 Mode( Self::NavigationMode ),
502 m_SliceActors( NULL ),
504 CursorMoving( false ),
505 RadiusMoving( false )
508 vtkSmartPointer< vtkAnnotatedCubeActor > cube =
509 vtkSmartPointer< vtkAnnotatedCubeActor >::New( );
510 cube->GetCubeProperty( )->SetColor( 0.9, 0.7, 0.2 );
511 cube->GetTextEdgesProperty( )->SetLineWidth( 1 );
512 cube->GetTextEdgesProperty( )->SetDiffuse( 0 );
513 cube->GetTextEdgesProperty( )->SetAmbient( 1 );
514 cube->GetTextEdgesProperty( )->SetColor( 0.18, 0.28, 0.23 );
515 cube->GetXPlusFaceProperty( )->SetColor( 1, 0, 0 );
516 cube->GetXPlusFaceProperty( )->SetInterpolationToFlat( );
517 cube->GetXMinusFaceProperty( )->SetColor( 1, 0, 0 );
518 cube->GetXMinusFaceProperty( )->SetInterpolationToFlat( );
519 cube->GetYPlusFaceProperty( )->SetColor( 0, 1, 0 );
520 cube->GetYPlusFaceProperty( )->SetInterpolationToFlat( );
521 cube->GetYMinusFaceProperty( )->SetColor( 0, 1, 0 );
522 cube->GetYMinusFaceProperty( )->SetInterpolationToFlat( );
523 cube->GetZPlusFaceProperty( )->SetColor( 0, 0, 1 );
524 cube->GetZPlusFaceProperty( )->SetInterpolationToFlat( );
525 cube->GetZMinusFaceProperty( )->SetColor( 0, 0, 1 );
526 cube->GetZMinusFaceProperty( )->SetInterpolationToFlat( );
528 vtkSmartPointer< vtkAxesActor > axes =
529 vtkSmartPointer< vtkAxesActor >::New( );
530 axes->AxisLabelsOff( );
531 axes->SetShaftTypeToCylinder( );
532 axes->SetTotalLength( 2, 2, 2 );
534 vtkSmartPointer< vtkPropAssembly > actors =
535 vtkSmartPointer< vtkPropAssembly >::New( );
536 actors->AddPart( cube );
537 actors->AddPart( axes );
539 this->OrientationWidget =
540 vtkSmartPointer< vtkOrientationMarkerWidget >::New( );
541 this->OrientationWidget->SetOutlineColor( 0.93, 0.57, 0.13 );
542 this->OrientationWidget->SetOrientationMarker( actors );
543 this->OrientationWidget->SetViewport( 0.0, 0.0, 0.2, 0.2 );
546 unsigned long circle_samples = 1000;
547 this->Circle = vtkSmartPointer< vtkPolyData >::New( );
549 vtkSmartPointer< vtkPoints > circle_points =
550 vtkSmartPointer< vtkPoints >::New( );
551 vtkSmartPointer< vtkCellArray > circle_lines =
552 vtkSmartPointer< vtkCellArray >::New( );
553 for( unsigned long s = 0; s < circle_samples; ++s )
555 double t = double( 6.2832 ) * double( s ) / double( circle_samples );
556 circle_points->InsertNextPoint(
557 std::cos( t ), std::sin( t ), double( 0 )
560 circle_lines->InsertNextCell( 2 );
561 circle_lines->InsertCellPoint( s );
562 circle_lines->InsertCellPoint( ( s + 1 ) % circle_samples );
565 this->Circle->SetPoints( circle_points );
566 this->Circle->SetLines( circle_lines );
568 this->CircleMapper = vtkSmartPointer< vtkPolyDataMapper >::New( );
569 this->CircleMapper->SetInputData( this->Circle );
570 this->CircleActor = vtkSmartPointer< vtkActor >::New( );
571 this->CircleActor->SetMapper( this->CircleMapper );
572 this->CircleActor->GetProperty( )->SetColor( 1, 0, 1 );
573 this->CircleActor->GetProperty( )->SetLineWidth( 2 );
575 this->PropPicker = vtkSmartPointer< vtkPropPicker >::New( );
576 this->PropPicker->PickFromListOn( );
579 // -------------------------------------------------------------------------
580 cpPlugins::Extensions::Visualization::ImageInteractorStyle::
581 ~ImageInteractorStyle( )
585 // -------------------------------------------------------------------------
586 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
587 _RenderAssociateInteractors( )
589 std::vector< vtkRenderWindowInteractor* >::iterator rIt =
590 this->AssociatedInteractors.begin( );
591 for( ; rIt != this->AssociatedInteractors.end( ); ++rIt )
595 // -------------------------------------------------------------------------
596 bool cpPlugins::Extensions::Visualization::ImageInteractorStyle::
597 _PickPosition( double pos[ 3 ] )
599 if( this->m_SliceActors == NULL )
602 double x = double( this->Interactor->GetEventPosition( )[ 0 ] );
603 double y = double( this->Interactor->GetEventPosition( )[ 1 ] );
604 this->FindPokedRenderer( x, y );
606 this->PropPicker->Pick( x, y, double( 0 ), this->CurrentRenderer );
609 this->PropPicker->GetPickPosition( pos );
611 int axis = this->m_SliceActors->GetAxis( );
612 double* bounds = this->m_SliceActors->GetDisplayBounds( );
613 pos[ axis ] = bounds[ axis << 1 ];
618 // -------------------------------------------------------------------------
619 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
622 std::cout << "upcur" << std::endl;
625 // -------------------------------------------------------------------------
626 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
630 this->Interactor->GetRenderWindow( )->
631 GetRenderers( )->GetFirstRenderer( );
634 vtkCamera* cam = ren->GetActiveCamera( );
638 if( this->RadiusMoving )
640 double x = this->Cursor[ 0 ] - this->Radius[ 0 ];
641 double y = this->Cursor[ 1 ] - this->Radius[ 1 ];
642 double z = this->Cursor[ 2 ] - this->Radius[ 2 ];
643 double r = std::sqrt( ( x * x ) + ( y * y ) + ( z * z ) );
645 vtkMatrix4x4* cam_matrix = cam->GetModelViewTransformMatrix( );
646 vtkSmartPointer< vtkMatrix4x4 > circle_matrix =
647 this->CircleActor->GetUserMatrix( );
648 if( circle_matrix.GetPointer( ) == NULL )
650 circle_matrix = vtkSmartPointer< vtkMatrix4x4 >::New( );
651 this->CircleActor->SetUserMatrix( circle_matrix );
654 for( int i = 0; i < 4; ++i )
656 for( int j = 0; j < 4; ++j )
658 double v = cam_matrix->GetElement( i, j );
659 if( i < 3 && j == 3 )
660 v = this->Cursor[ i ];
663 circle_matrix->SetElement( i, j, v );
668 this->CircleActor->Modified( );
669 ren->AddActor( this->CircleActor );
672 ren->RemoveActor( this->CircleActor );
674 this->Interactor->Render( );