#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // ------------------------------------------------------------------------- const int cpExtensions::Visualization:: ImageInteractorStyle::CursorEvent = vtkCommand::UserEvent + 1; const int cpExtensions::Visualization:: ImageInteractorStyle::RadiusEvent = vtkCommand::UserEvent + 2; const int cpExtensions::Visualization:: ImageInteractorStyle::DoubleClickEvent = vtkCommand::UserEvent + 3; // ------------------------------------------------------------------------- cpExtensions::Visualization::ImageInteractorStyle:: Self* cpExtensions::Visualization::ImageInteractorStyle:: New( ) { return( new Self( ) ); } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageInteractorStyle:: Configure( ImageSliceActors* slice_actors, MPRActors* mpr_actors ) { this->m_SliceActors = slice_actors; this->m_MPRActors = mpr_actors; this->SetModeToNavigation( ); this->PropPicker->AddPickList( slice_actors->GetImageActor( ) ); this->Modified( ); } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageInteractorStyle:: AssociateInteractor( vtkRenderWindowInteractor* interactor ) { if( interactor != NULL ) { this->AssociatedInteractors.push_back( interactor ); this->Modified( ); } // fi } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageInteractorStyle:: SetModeToNavigation( ) { this->Mode = Self::NavigationMode; } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageInteractorStyle:: SetModeToDeformation( ) { this->Mode = Self::DeformationMode; } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageInteractorStyle:: SetInteractor( vtkRenderWindowInteractor* interactor, const int& axis ) { this->Superclass::SetInteractor( interactor ); this->OrientationWidget->SetInteractor( interactor ); interactor->SetInteractorStyle( this ); if( interactor == NULL ) return; // Get camera, avoiding segfaults vtkRenderer* ren = interactor->GetRenderWindow( )->GetRenderers( )->GetFirstRenderer( ); if( ren == NULL ) return; vtkCamera* cam = ren->GetActiveCamera( ); if( cam == NULL ) return; // Parallel projections are better when displaying 2D images cam->ParallelProjectionOn( ); cam->SetFocalPoint( double( 0 ), double( 0 ), double( 0 ) ); if( axis == 0 ) { cam->SetPosition( double( 1 ), double( 0 ), double( 0 ) ); cam->SetViewUp ( double( 0 ), double( 1 ), double( 0 ) ); } else if( axis == 1 ) { cam->SetPosition( double( 0 ), double( 1 ), double( 0 ) ); cam->SetViewUp ( double( 0 ), double( 0 ), double( -1 ) ); } else // if( axis == 2 ) { cam->SetPosition( double( 0 ), double( 0 ), double( 1 ) ); cam->SetViewUp ( double( 0 ), double( 1 ), double( 0 ) ); } // fi ren->ResetCamera( ); // Enable 2D orientation widget this->OrientationWidget->SetEnabled( 1 ); this->OrientationWidget->InteractiveOff( ); } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageInteractorStyle:: OnMouseMove( ) { if( this->m_MPRActors == NULL ) return; if( this->CursorMoving ) { bool picked = this->_PickPosition( this->Cursor ); if( picked ) { for( int i = 0; i < 3; ++i ) if( this->m_SliceActors->GetAxis( ) != i ) this->m_MPRActors->SetSlice( i, this->Cursor[ i ] ); this->InvokeEvent( Self::CursorEvent, this->Cursor ); this->Interactor->Render( ); this->_RenderAssociateInteractors( ); } // fi } else if( this->RadiusMoving ) { bool picked = this->_PickPosition( this->Radius ); if( picked ) { this->InvokeEvent( Self::RadiusEvent, this->Radius ); this->_UpdateRadius( ); } // fi } else { switch( this->State ) { case VTKIS_WINDOW_LEVEL: this->WindowLevel( ); break; case VTKIS_DOLLY: this->Dolly( ); break; case VTKIS_PAN: this->Pan( ); break; } // hctiws } // fi } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageInteractorStyle:: OnLeftButtonDown( ) { static double pnt[ 3 ]; static int pos[ 2 ]; this->Interactor->GetEventPosition( pos ); this->FindPokedRenderer( pos[ 0 ], pos[ 1 ] ); if( this->CurrentRenderer == NULL ) return; this->GrabFocus( this->EventCallbackCommand ); // TODO: check this code // Manage double-click static const long epsilon_time = 800; static long last_click_time = -( epsilon_time << 1 ); long click_time = static_cast< long >( std::clock( ) ); if( ( click_time - last_click_time ) < epsilon_time ) { last_click_time = -( epsilon_time << 1 ); if( this->_PickPosition( pnt ) ) this->InvokeEvent( Self::DoubleClickEvent, pnt ); } else { last_click_time = click_time; if( this->Interactor->GetControlKey( ) ) this->StartCursorMoving( ); } // fi } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageInteractorStyle:: OnLeftButtonUp( ) { if( this->CursorMoving ) { this->EndCursorMoving( ); if( this->Interactor ) this->ReleaseFocus( ); } // fi } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageInteractorStyle:: OnMiddleButtonDown( ) { int x = this->Interactor->GetEventPosition( )[ 0 ]; int y = this->Interactor->GetEventPosition( )[ 1 ]; this->FindPokedRenderer( x, y ); if( this->CurrentRenderer == NULL ) return; this->GrabFocus( this->EventCallbackCommand ); if( this->Interactor->GetAltKey( ) ) { } else if( this->Interactor->GetControlKey( ) ) { this->StartRadiusMoving( ); } else if( this->Interactor->GetShiftKey( ) ) { } else this->StartPan( ); } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageInteractorStyle:: OnMiddleButtonUp( ) { if( this->RadiusMoving ) { this->EndRadiusMoving( ); if( this->Interactor ) this->ReleaseFocus( ); } else { switch( this->State ) { case VTKIS_PAN: this->EndPan( ); break; } // hctiws } // fi } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageInteractorStyle:: OnRightButtonDown( ) { int x = this->Interactor->GetEventPosition( )[ 0 ]; int y = this->Interactor->GetEventPosition( )[ 1 ]; this->FindPokedRenderer( x, y ); if( this->CurrentRenderer == NULL ) return; this->GrabFocus( this->EventCallbackCommand ); if( this->Interactor->GetControlKey( ) ) { this->WindowLevelStartPosition[ 0 ] = x; this->WindowLevelStartPosition[ 1 ] = y; this->StartWindowLevel( ); } else { this->StartDolly( ); } // fi } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageInteractorStyle:: OnRightButtonUp( ) { switch( this->State ) { case VTKIS_WINDOW_LEVEL: { this->EndWindowLevel( ); if( this->Interactor ) this->ReleaseFocus( ); } break; case VTKIS_DOLLY: this->EndDolly( ); break; } // hctiws } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageInteractorStyle:: OnMouseWheelForward( ) { if( this->m_SliceActors == NULL || this->Interactor == NULL ) return; int off = 1; if( this->Interactor->GetShiftKey( ) == 1 ) off *= 10; int s = this->m_SliceActors->GetSliceNumber( ) + off; int maxs = this->m_SliceActors->GetSliceNumberMaxValue( ); this->m_SliceActors->SetSliceNumber( ( s < maxs )? s: maxs ); this->Interactor->Render( ); this->_RenderAssociateInteractors( ); } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageInteractorStyle:: OnMouseWheelBackward( ) { if( this->m_SliceActors == NULL || this->Interactor == NULL ) return; int off = 1; if( this->Interactor->GetShiftKey( ) == 1 ) off *= 10; int s = this->m_SliceActors->GetSliceNumber( ) - off; int mins = this->m_SliceActors->GetSliceNumberMinValue( ); this->m_SliceActors->SetSliceNumber( ( mins < s )? s: mins ); this->Interactor->Render( ); this->_RenderAssociateInteractors( ); } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageInteractorStyle:: OnChar( ) { switch( this->Interactor->GetKeyCode( ) ) { case 'r': case 'R': { vtkRenderer* ren = this->Interactor->GetRenderWindow( )-> GetRenderers( )->GetFirstRenderer( ); if( ren != NULL ) ren->ResetCamera( ); this->Interactor->Render( ); } break; case 'w': case 'W': case 'l': case 'L': { if( this->m_MPRActors != NULL ) { this->m_MPRActors->ResetWindowLevel( ); this->Interactor->Render( ); this->_RenderAssociateInteractors( ); } // fi } break; } // hctiws } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageInteractorStyle:: WindowLevel( ) { if( this->Mode == Self::NavigationMode ) { if( this->Interactor == NULL ) return; vtkRenderer* ren = this->Interactor->GetRenderWindow( )-> GetRenderers( )->GetFirstRenderer( ); if( ren == NULL ) return; // Compute scales this->WindowLevelCurrentPosition[ 0 ] = this->Interactor->GetEventPosition( )[ 0 ]; this->WindowLevelCurrentPosition[ 1 ] = this->Interactor->GetEventPosition( )[ 1 ]; int* size = ren->GetSize( ); double sw = double( this->WindowLevelCurrentPosition[ 0 ] - this->WindowLevelStartPosition[ 0 ] ) / double( size[ 0 ] ); double sl = ( this->WindowLevelStartPosition[ 1 ] - this->WindowLevelCurrentPosition[ 1 ] ) / double( size[ 1 ] ); double w = this->WindowLevelInitial[ 0 ] * ( double( 1 ) + sw ); double l = this->WindowLevelInitial[ 1 ] * ( double( 1 ) + sl ); double minw = this->m_MPRActors->GetMinWindow( ); double maxw = this->m_MPRActors->GetMaxWindow( ); double minl = this->m_MPRActors->GetMinLevel( ); double maxl = this->m_MPRActors->GetMaxLevel( ); if( w < minw ) w = minw; if( maxw < w ) w = maxw; if( l < minl ) l = minl; if( maxl < l ) l = maxl; this->m_MPRActors->SetWindowLevel( w, l ); this->Interactor->Render( ); this->_RenderAssociateInteractors( ); } else if( this->Mode == Self::DeformationMode ) { // TODO } // fi } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageInteractorStyle:: StartWindowLevel( ) { if( this->State != VTKIS_NONE ) return; if( this->Mode == Self::NavigationMode ) { this->StartState( VTKIS_WINDOW_LEVEL ); this->WindowLevelInitial[ 0 ] = this->m_MPRActors->GetWindow( ); this->WindowLevelInitial[ 1 ] = this->m_MPRActors->GetLevel( ); } else if( this->Mode == Self::DeformationMode ) { // TODO } // fi } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageInteractorStyle:: EndWindowLevel( ) { if( this->Mode == Self::NavigationMode ) { if( this->State != VTKIS_WINDOW_LEVEL ) return; this->StopState( ); } else { // TODO } // fi } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageInteractorStyle:: StartCursorMoving( ) { if( this->CursorMoving ) return; this->_PickPosition( this->Cursor ); this->CursorMoving = true; } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageInteractorStyle:: EndCursorMoving( ) { if( !( this->CursorMoving ) ) return; this->CursorMoving = false; } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageInteractorStyle:: StartRadiusMoving( ) { if( this->RadiusMoving ) return; this->_PickPosition( this->Radius ); this->RadiusMoving = true; this->_UpdateRadius( ); } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageInteractorStyle:: EndRadiusMoving( ) { if( !( this->RadiusMoving ) ) return; this->RadiusMoving = false; this->_UpdateRadius( ); this->InvokeEvent( Self::RadiusEvent, NULL ); } // ------------------------------------------------------------------------- cpExtensions::Visualization::ImageInteractorStyle:: ImageInteractorStyle( ) : Superclass( ), Mode( Self::NavigationMode ), m_SliceActors( NULL ), m_MPRActors( NULL ), CursorMoving( false ), RadiusMoving( false ) { // Orientation marks vtkSmartPointer< vtkAnnotatedCubeActor > cube = vtkSmartPointer< vtkAnnotatedCubeActor >::New( ); cube->GetCubeProperty( )->SetColor( 0.9, 0.7, 0.2 ); cube->GetTextEdgesProperty( )->SetLineWidth( 1 ); cube->GetTextEdgesProperty( )->SetDiffuse( 0 ); cube->GetTextEdgesProperty( )->SetAmbient( 1 ); cube->GetTextEdgesProperty( )->SetColor( 0.18, 0.28, 0.23 ); cube->GetXPlusFaceProperty( )->SetColor( 1, 0, 0 ); cube->GetXPlusFaceProperty( )->SetInterpolationToFlat( ); cube->GetXMinusFaceProperty( )->SetColor( 1, 0, 0 ); cube->GetXMinusFaceProperty( )->SetInterpolationToFlat( ); cube->GetYPlusFaceProperty( )->SetColor( 0, 1, 0 ); cube->GetYPlusFaceProperty( )->SetInterpolationToFlat( ); cube->GetYMinusFaceProperty( )->SetColor( 0, 1, 0 ); cube->GetYMinusFaceProperty( )->SetInterpolationToFlat( ); cube->GetZPlusFaceProperty( )->SetColor( 0, 0, 1 ); cube->GetZPlusFaceProperty( )->SetInterpolationToFlat( ); cube->GetZMinusFaceProperty( )->SetColor( 0, 0, 1 ); cube->GetZMinusFaceProperty( )->SetInterpolationToFlat( ); vtkSmartPointer< vtkAxesActor > axes = vtkSmartPointer< vtkAxesActor >::New( ); axes->AxisLabelsOff( ); axes->SetShaftTypeToCylinder( ); axes->SetTotalLength( 2, 2, 2 ); vtkSmartPointer< vtkPropAssembly > actors = vtkSmartPointer< vtkPropAssembly >::New( ); actors->AddPart( cube ); actors->AddPart( axes ); this->OrientationWidget = vtkSmartPointer< vtkOrientationMarkerWidget >::New( ); this->OrientationWidget->SetOutlineColor( 0.93, 0.57, 0.13 ); this->OrientationWidget->SetOrientationMarker( actors ); this->OrientationWidget->SetViewport( 0.0, 0.0, 0.2, 0.2 ); // Circle unsigned long circle_samples = 1000; this->Circle = vtkSmartPointer< vtkPolyData >::New( ); vtkSmartPointer< vtkPoints > circle_points = vtkSmartPointer< vtkPoints >::New( ); vtkSmartPointer< vtkCellArray > circle_lines = vtkSmartPointer< vtkCellArray >::New( ); for( unsigned long s = 0; s < circle_samples; ++s ) { double t = double( 6.2832 ) * double( s ) / double( circle_samples ); circle_points->InsertNextPoint( std::cos( t ), std::sin( t ), double( 0 ) ); circle_lines->InsertNextCell( 2 ); circle_lines->InsertCellPoint( s ); circle_lines->InsertCellPoint( ( s + 1 ) % circle_samples ); } // rof this->Circle->SetPoints( circle_points ); this->Circle->SetLines( circle_lines ); this->CircleMapper = vtkSmartPointer< vtkPolyDataMapper >::New( ); this->CircleMapper->SetInputData( this->Circle ); this->CircleActor = vtkSmartPointer< vtkActor >::New( ); this->CircleActor->SetMapper( this->CircleMapper ); this->CircleActor->GetProperty( )->SetColor( 1, 0, 1 ); this->CircleActor->GetProperty( )->SetLineWidth( 2 ); this->PropPicker = vtkSmartPointer< vtkPropPicker >::New( ); this->PropPicker->PickFromListOn( ); } // ------------------------------------------------------------------------- cpExtensions::Visualization::ImageInteractorStyle:: ~ImageInteractorStyle( ) { } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageInteractorStyle:: _RenderAssociateInteractors( ) { std::vector< vtkRenderWindowInteractor* >::iterator rIt = this->AssociatedInteractors.begin( ); for( ; rIt != this->AssociatedInteractors.end( ); ++rIt ) ( *rIt )->Render( ); } // ------------------------------------------------------------------------- bool cpExtensions::Visualization::ImageInteractorStyle:: _PickPosition( double pos[ 3 ] ) { if( this->m_SliceActors == NULL ) return( false ); double x = double( this->Interactor->GetEventPosition( )[ 0 ] ); double y = double( this->Interactor->GetEventPosition( )[ 1 ] ); this->FindPokedRenderer( x, y ); int success = this->PropPicker->Pick( x, y, double( 0 ), this->CurrentRenderer ); if( success == 0 ) return( false ); this->PropPicker->GetPickPosition( pos ); int axis = this->m_SliceActors->GetAxis( ); double* bounds = this->m_SliceActors->GetDisplayBounds( ); pos[ axis ] = bounds[ axis << 1 ]; return( true ); } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageInteractorStyle:: _UpdateCursor( ) { std::cout << "upcur" << std::endl; } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageInteractorStyle:: _UpdateRadius( ) { vtkRenderer* ren = this->Interactor->GetRenderWindow( )-> GetRenderers( )->GetFirstRenderer( ); if( ren == NULL ) return; vtkCamera* cam = ren->GetActiveCamera( ); if( cam == NULL ) return; if( this->RadiusMoving ) { double x = this->Cursor[ 0 ] - this->Radius[ 0 ]; double y = this->Cursor[ 1 ] - this->Radius[ 1 ]; double z = this->Cursor[ 2 ] - this->Radius[ 2 ]; double r = std::sqrt( ( x * x ) + ( y * y ) + ( z * z ) ); vtkMatrix4x4* cam_matrix = cam->GetModelViewTransformMatrix( ); vtkSmartPointer< vtkMatrix4x4 > circle_matrix = this->CircleActor->GetUserMatrix( ); if( circle_matrix.GetPointer( ) == NULL ) { circle_matrix = vtkSmartPointer< vtkMatrix4x4 >::New( ); this->CircleActor->SetUserMatrix( circle_matrix ); } // fi for( int i = 0; i < 4; ++i ) { for( int j = 0; j < 4; ++j ) { double v = cam_matrix->GetElement( i, j ); if( i < 3 && j == 3 ) v = this->Cursor[ i ]; if( i < 3 && j < 3 ) v *= r; circle_matrix->SetElement( i, j, v ); } // rof } // rof this->CircleActor->Modified( ); ren->AddActor( this->CircleActor ); } else ren->RemoveActor( this->CircleActor ); this->Interactor->Render( ); } // eof - $RCSfile$