+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageSliceActors::
+_ConfigureStyle( )
+{
+ // Connect this view with a controller
+ this->m_Style = vtkSmartPointer< TStyle >::New( );
+ this->m_Style->AddMouseMoveCommand( Self::_MouseMoveCommand, this );
+ this->m_Style->AddMouseClickCommand( Self::_MouseClickCommand, this );
+ this->m_Style->AddMouseWheelCommand( Self::_MouseWheelCommand, this );
+ this->m_Style->AddKeyCommand( Self::_KeyCommand, this );
+ this->m_Style->AddEnterCommand( Self::_EnterCommand, this );
+ this->m_Style->AddLeaveCommand( Self::_LeaveCommand, this );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageSliceActors::
+_ConfigureInputImage( )
+{
+ this->m_ImageMapper->SetOrientation( 0 );
+ this->m_ImageMapper->Update( );
+
+ // Create actor
+ this->m_ImageActor->SetInterpolate( this->m_Interpolate );
+ this->m_ImageActor->Modified( );
+
+ if( this->m_Style.GetPointer( ) != NULL )
+ this->m_Style->AssociateImageActor( this->m_ImageActor );
+ this->AddItem( this->m_ImageActor );
+
+ this->SetSliceNumber( this->GetSliceNumberMinValue( ) );
+ this->ResetCursor( );
+ this->Modified( );
+
+ // Reset cursors
+ this->ResetCursor( );
+ this->ResetAxesCursor( );
+
+ // Update window/level ranges
+ vtkImageData* data = this->GetInputImage( );
+ if( data != NULL )
+ {
+ double r[ 2 ];
+ data->GetScalarRange( r );
+ this->m_WLRange[ 0 ] = double( 0 );
+ this->m_WLRange[ 1 ] = r[ 1 ] - r[ 0 ];
+ this->m_WLRange[ 2 ] = r[ 0 ];
+ this->m_WLRange[ 3 ] = r[ 1 ];
+ this->ResetWindowLevel( );
+
+ // Configure blender
+ this->m_BlenderBase = vtkSmartPointer< vtkImageData >::New( );
+ this->m_BlenderBase->ShallowCopy( data );
+ this->m_BlenderBase->AllocateScalars( VTK_UNSIGNED_CHAR, 1 );
+ std::memset(
+ this->m_BlenderBase->GetScalarPointer( ), 0,
+ this->m_BlenderBase->GetActualMemorySize( )
+ );
+ this->m_Blender->AddInputData( this->m_BlenderBase );
+
+ } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageSliceActors::
+_ConfigureBinaryImage( const double& r, const double& g, const double& b )
+{
+ unsigned int nValues = this->m_BlenderLUT->GetNumberOfTableValues( );
+ this->m_BlenderLUT->SetNumberOfTableValues( nValues + 1 );
+ this->m_BlenderLUT->SetTableRange( 0, nValues );
+ this->m_BlenderLUT->SetTableValue( nValues, r, g, b, 0.5 );
+ this->m_BlenderLUT->Build( );
+
+ this->m_BlenderLUT->Modified( );
+ this->m_Blender->Modified( );
+ this->m_Blender->Update( );
+
+ this->m_BlenderMapper->Modified( );
+ this->m_BlenderActor->Modified( );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageSliceActors::
+_MouseMoveCommand(
+ void* data, const TStyle::ButtonID& btn, int* idx, double* pos,
+ bool alt, bool ctr, bool sft
+ )
+{
+ ImageSliceActors* actors = reinterpret_cast< ImageSliceActors* >( data );
+ if( actors == NULL )
+ return;
+
+ if( btn == TStyle::ButtonID_None )
+ {
+ // Just show the pixel information
+ actors->SetCursor( pos );
+ actors->UpdateText( pos );
+ actors->Render( 1e-3 );
+ }
+ else if( btn == TStyle::ButtonID_Left )
+ {
+ if( !alt && ctr && !sft )
+ {
+ // Show axes in current renderer
+ actors->SetAxesCursor( pos );
+
+ // Interactively move slices
+ auto i = actors->m_SlicesCommands.begin( );
+ for( ; i != actors->m_SlicesCommands.end( ); ++i )
+ i->first( pos, actors->GetAxis( ), i->second );
+ actors->Render( 1e-3 );
+
+ } // fi
+ }
+ else if( btn == TStyle::ButtonID_Right )
+ {
+ if( !alt && !ctr && sft )
+ {
+ // Change image window level
+ double bounds[ 6 ];
+ actors->m_ImageMapper->GetBounds( bounds );
+
+ int a0 = actors->GetAxis( );
+ int a1 = ( a0 + 1 ) % 3;
+ int a2 = ( a0 + 2 ) % 3;
+ double dx = pos[ a1 ] - actors->m_StartWindowLevelPos[ a1 ];
+ double dy = pos[ a2 ] - actors->m_StartWindowLevelPos[ a2 ];
+ dx /= bounds[ ( a1 << 1 ) + 1 ] - bounds[ a1 << 1 ];
+ dy /= bounds[ ( a2 << 1 ) + 1 ] - bounds[ a2 << 1 ];
+
+ dx *= actors->m_StartWindowLevel[ 0 ];
+ dy *= actors->m_StartWindowLevel[ 1 ];
+ dx += actors->m_StartWindowLevel[ 0 ];
+ dy += actors->m_StartWindowLevel[ 1 ];
+ actors->SetWindowLevel( dx, dy );
+ actors->Render( 1e-3 );
+
+ // Associate objects
+ auto i = actors->m_WindowLevelCommands.begin( );
+ for( ; i != actors->m_WindowLevelCommands.end( ); ++i )
+ i->first( dx, dy, i->second );
+
+ } // fi
+
+ } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageSliceActors::
+_MouseClickCommand(
+ void* data, const TStyle::ButtonID& btn, int* idx, double* pos,
+ bool alt, bool ctr, bool sft
+ )
+{
+ ImageSliceActors* actors = reinterpret_cast< ImageSliceActors* >( data );
+ if( actors == NULL )
+ return;
+
+ actors->m_StartWindowLevelPos[ 0 ] = pos[ 0 ];
+ actors->m_StartWindowLevelPos[ 1 ] = pos[ 1 ];
+ actors->m_StartWindowLevelPos[ 2 ] = pos[ 2 ];
+ actors->m_StartWindowLevel[ 0 ] = actors->GetWindow( );
+ actors->m_StartWindowLevel[ 1 ] = actors->GetLevel( );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageSliceActors::
+_MouseWheelCommand(
+ void* data, const int& dir,
+ bool alt, bool ctr, bool sft
+ )
+{
+ ImageSliceActors* actors = reinterpret_cast< ImageSliceActors* >( data );
+ if( actors == NULL )
+ return;
+
+ if( !alt && !ctr )
+ {
+ int slice = actors->GetSliceNumber( ) + ( dir * ( ( sft )? 10: 1 ) );
+ if( slice < actors->GetSliceNumberMinValue( ) )
+ slice = actors->GetSliceNumberMinValue( );
+ if( slice > actors->GetSliceNumberMaxValue( ) )
+ slice = actors->GetSliceNumberMaxValue( );
+ actors->SetSliceNumber( slice );
+
+ auto a = actors->m_AssociatedSlices.begin( );
+ for( ; a != actors->m_AssociatedSlices.end( ); ++a )
+ {
+ ( *a )->SetSliceNumber( slice );
+ ( *a )->Render( 1e-3 );
+
+ } // rof
+ actors->Render( 1e-3 );
+
+ // Associate objects
+ auto i = actors->m_RenderCommands.begin( );
+ for( ; i != actors->m_RenderCommands.end( ); ++i )
+ i->first( i->second );
+
+ } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageSliceActors::
+_KeyCommand( void* data, const char& key )
+{
+ ImageSliceActors* actors = reinterpret_cast< ImageSliceActors* >( data );
+ if( actors == NULL )
+ return;
+
+ switch( key )
+ {
+ case 'r': case 'R':
+ {
+ actors->ResetCamera( );
+ actors->Render( 1e-3 );
+
+ // Associate objects
+ auto i = actors->m_RenderCommands.begin( );
+ for( ; i != actors->m_RenderCommands.end( ); ++i )
+ i->first( i->second );
+ }
+ break;
+ case 'w': case 'W':
+ {
+ actors->ResetWindowLevel( );
+ actors->Render( 1e-3 );
+
+ // Associate objects
+ auto i = actors->m_RenderCommands.begin( );
+ for( ; i != actors->m_RenderCommands.end( ); ++i )
+ i->first( i->second );
+ }
+ break;
+ default:
+ break;
+ } // hctiws
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageSliceActors::
+_EnterCommand( void* data )
+{
+ ImageSliceActors* actors = reinterpret_cast< ImageSliceActors* >( data );
+ if( actors == NULL )
+ return;
+
+ actors->ResetCursor( );
+ actors->m_CursorActor->VisibilityOn( );
+ actors->Render( 1e-3 );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageSliceActors::
+_LeaveCommand( void* data )
+{
+ ImageSliceActors* actors = reinterpret_cast< ImageSliceActors* >( data );
+ if( actors == NULL )
+ return;
+
+ actors->ResetCursor( );
+ actors->m_CursorActor->VisibilityOff( );
+ actors->Render( 1e-3 );
+}
+