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( ) );
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( );
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( );
408 double maxw = this->m_MPRActors->GetMaxWindow( );
409 double minl = this->m_MPRActors->GetMinLevel( );
410 double maxl = this->m_MPRActors->GetMaxLevel( );
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->SetWindowLevel( w, l );
418 this->Interactor->Render( );
419 this->_RenderAssociateInteractors( );
421 else if( this->Mode == Self::DeformationMode )
428 // -------------------------------------------------------------------------
429 void cpExtensions::Visualization::ImageInteractorStyle::
432 if( this->State != VTKIS_NONE )
434 if( this->Mode == Self::NavigationMode )
436 this->StartState( VTKIS_WINDOW_LEVEL );
438 this->WindowLevelInitial[ 0 ] = this->m_MPRActors->GetWindow( );
439 this->WindowLevelInitial[ 1 ] = this->m_MPRActors->GetLevel( );
441 else if( this->Mode == Self::DeformationMode )
448 // -------------------------------------------------------------------------
449 void cpExtensions::Visualization::ImageInteractorStyle::
452 if( this->Mode == Self::NavigationMode )
454 if( this->State != VTKIS_WINDOW_LEVEL )
465 // -------------------------------------------------------------------------
466 void cpExtensions::Visualization::ImageInteractorStyle::
469 if( this->CursorMoving )
471 this->_PickPosition( this->Cursor );
472 this->CursorMoving = true;
475 // -------------------------------------------------------------------------
476 void cpExtensions::Visualization::ImageInteractorStyle::
479 if( !( this->CursorMoving ) )
481 this->CursorMoving = false;
484 // -------------------------------------------------------------------------
485 void cpExtensions::Visualization::ImageInteractorStyle::
488 if( this->RadiusMoving )
490 this->_PickPosition( this->Radius );
491 this->RadiusMoving = true;
492 this->_UpdateRadius( );
495 // -------------------------------------------------------------------------
496 void cpExtensions::Visualization::ImageInteractorStyle::
499 if( !( this->RadiusMoving ) )
501 this->RadiusMoving = false;
502 this->_UpdateRadius( );
503 this->InvokeEvent( Self::RadiusEvent, NULL );
506 // -------------------------------------------------------------------------
507 cpExtensions::Visualization::ImageInteractorStyle::
508 ImageInteractorStyle( )
510 Mode( Self::NavigationMode ),
511 m_SliceActors( NULL ),
513 CursorMoving( false ),
514 RadiusMoving( false )
517 vtkSmartPointer< vtkAnnotatedCubeActor > cube =
518 vtkSmartPointer< vtkAnnotatedCubeActor >::New( );
519 cube->GetCubeProperty( )->SetColor( 0.9, 0.7, 0.2 );
520 cube->GetTextEdgesProperty( )->SetLineWidth( 1 );
521 cube->GetTextEdgesProperty( )->SetDiffuse( 0 );
522 cube->GetTextEdgesProperty( )->SetAmbient( 1 );
523 cube->GetTextEdgesProperty( )->SetColor( 0.18, 0.28, 0.23 );
524 cube->GetXPlusFaceProperty( )->SetColor( 1, 0, 0 );
525 cube->GetXPlusFaceProperty( )->SetInterpolationToFlat( );
526 cube->GetXMinusFaceProperty( )->SetColor( 1, 0, 0 );
527 cube->GetXMinusFaceProperty( )->SetInterpolationToFlat( );
528 cube->GetYPlusFaceProperty( )->SetColor( 0, 1, 0 );
529 cube->GetYPlusFaceProperty( )->SetInterpolationToFlat( );
530 cube->GetYMinusFaceProperty( )->SetColor( 0, 1, 0 );
531 cube->GetYMinusFaceProperty( )->SetInterpolationToFlat( );
532 cube->GetZPlusFaceProperty( )->SetColor( 0, 0, 1 );
533 cube->GetZPlusFaceProperty( )->SetInterpolationToFlat( );
534 cube->GetZMinusFaceProperty( )->SetColor( 0, 0, 1 );
535 cube->GetZMinusFaceProperty( )->SetInterpolationToFlat( );
537 vtkSmartPointer< vtkAxesActor > axes =
538 vtkSmartPointer< vtkAxesActor >::New( );
539 axes->AxisLabelsOff( );
540 axes->SetShaftTypeToCylinder( );
541 axes->SetTotalLength( 2, 2, 2 );
543 vtkSmartPointer< vtkPropAssembly > actors =
544 vtkSmartPointer< vtkPropAssembly >::New( );
545 actors->AddPart( cube );
546 actors->AddPart( axes );
548 this->OrientationWidget =
549 vtkSmartPointer< vtkOrientationMarkerWidget >::New( );
550 this->OrientationWidget->SetOutlineColor( 0.93, 0.57, 0.13 );
551 this->OrientationWidget->SetOrientationMarker( actors );
552 this->OrientationWidget->SetViewport( 0.0, 0.0, 0.2, 0.2 );
555 unsigned long circle_samples = 1000;
556 this->Circle = vtkSmartPointer< vtkPolyData >::New( );
558 vtkSmartPointer< vtkPoints > circle_points =
559 vtkSmartPointer< vtkPoints >::New( );
560 vtkSmartPointer< vtkCellArray > circle_lines =
561 vtkSmartPointer< vtkCellArray >::New( );
562 for( unsigned long s = 0; s < circle_samples; ++s )
564 double t = double( 6.2832 ) * double( s ) / double( circle_samples );
565 circle_points->InsertNextPoint(
566 std::cos( t ), std::sin( t ), double( 0 )
569 circle_lines->InsertNextCell( 2 );
570 circle_lines->InsertCellPoint( s );
571 circle_lines->InsertCellPoint( ( s + 1 ) % circle_samples );
574 this->Circle->SetPoints( circle_points );
575 this->Circle->SetLines( circle_lines );
577 this->CircleMapper = vtkSmartPointer< vtkPolyDataMapper >::New( );
578 this->CircleMapper->SetInputData( this->Circle );
579 this->CircleActor = vtkSmartPointer< vtkActor >::New( );
580 this->CircleActor->SetMapper( this->CircleMapper );
581 this->CircleActor->GetProperty( )->SetColor( 1, 0, 1 );
582 this->CircleActor->GetProperty( )->SetLineWidth( 2 );
584 this->PropPicker = vtkSmartPointer< vtkPropPicker >::New( );
585 this->PropPicker->PickFromListOn( );
588 // -------------------------------------------------------------------------
589 cpExtensions::Visualization::ImageInteractorStyle::
590 ~ImageInteractorStyle( )
594 // -------------------------------------------------------------------------
595 void cpExtensions::Visualization::ImageInteractorStyle::
596 _RenderAssociateInteractors( )
598 std::vector< vtkRenderWindowInteractor* >::iterator rIt =
599 this->AssociatedInteractors.begin( );
600 for( ; rIt != this->AssociatedInteractors.end( ); ++rIt )
604 // -------------------------------------------------------------------------
605 bool cpExtensions::Visualization::ImageInteractorStyle::
606 _PickPosition( double pos[ 3 ] )
608 if( this->m_SliceActors == NULL )
611 double x = double( this->Interactor->GetEventPosition( )[ 0 ] );
612 double y = double( this->Interactor->GetEventPosition( )[ 1 ] );
613 this->FindPokedRenderer( x, y );
615 this->PropPicker->Pick( x, y, double( 0 ), this->CurrentRenderer );
618 this->PropPicker->GetPickPosition( pos );
620 int axis = this->m_SliceActors->GetAxis( );
621 double* bounds = this->m_SliceActors->GetDisplayBounds( );
622 pos[ axis ] = bounds[ axis << 1 ];
627 // -------------------------------------------------------------------------
628 void cpExtensions::Visualization::ImageInteractorStyle::
631 std::cout << "upcur" << std::endl;
634 // -------------------------------------------------------------------------
635 void cpExtensions::Visualization::ImageInteractorStyle::
639 this->Interactor->GetRenderWindow( )->
640 GetRenderers( )->GetFirstRenderer( );
643 vtkCamera* cam = ren->GetActiveCamera( );
647 if( this->RadiusMoving )
649 double x = this->Cursor[ 0 ] - this->Radius[ 0 ];
650 double y = this->Cursor[ 1 ] - this->Radius[ 1 ];
651 double z = this->Cursor[ 2 ] - this->Radius[ 2 ];
652 double r = std::sqrt( ( x * x ) + ( y * y ) + ( z * z ) );
654 vtkMatrix4x4* cam_matrix = cam->GetModelViewTransformMatrix( );
655 vtkSmartPointer< vtkMatrix4x4 > circle_matrix =
656 this->CircleActor->GetUserMatrix( );
657 if( circle_matrix.GetPointer( ) == NULL )
659 circle_matrix = vtkSmartPointer< vtkMatrix4x4 >::New( );
660 this->CircleActor->SetUserMatrix( circle_matrix );
663 for( int i = 0; i < 4; ++i )
665 for( int j = 0; j < 4; ++j )
667 double v = cam_matrix->GetElement( i, j );
668 if( i < 3 && j == 3 )
669 v = this->Cursor[ i ];
672 circle_matrix->SetElement( i, j, v );
677 this->CircleActor->Modified( );
678 ren->AddActor( this->CircleActor );
681 ren->RemoveActor( this->CircleActor );
683 this->Interactor->Render( );