1 #include <cpExtensions/Visualization/ImageSliceActors.h>
5 #include <vtkImageData.h>
6 #include <vtkImageProperty.h>
7 #include <vtkProperty.h>
8 #include <vtkRenderer.h>
9 #include <vtkRenderWindow.h>
10 #include <vtkTextProperty.h>
12 // -------------------------------------------------------------------------
13 cpExtensions::Visualization::ImageSliceActors::
14 Self* cpExtensions::Visualization::ImageSliceActors::
17 return( new Self( ) );
20 // -------------------------------------------------------------------------
21 void cpExtensions::Visualization::ImageSliceActors::
24 this->RemoveAllItems( );
27 this->m_Mapper = vtkSmartPointer< vtkImageSliceMapper >::New( );
28 this->m_Actor = vtkSmartPointer< vtkImageActor >::New( );
29 this->m_Actor->SetMapper( this->m_Mapper );
32 this->m_Cursor.Create( );
33 this->m_Cursor.Actor->GetProperty( )->SetColor( 1, 1, 0 );
36 this->m_TextBuffer[ 0 ] = '\0';
37 this->m_TextActor = vtkSmartPointer< vtkTextActor >::New( );
38 this->m_TextActor->SetTextScaleModeToNone( );
39 vtkTextProperty* textprop = this->m_TextActor->GetTextProperty( );
40 textprop->SetColor( 1, 1, 0 );
41 textprop->SetFontFamilyToCourier( );
42 textprop->SetFontSize( 18 );
44 textprop->ItalicOff( );
45 textprop->ShadowOff( );
46 textprop->SetJustificationToLeft( );
47 textprop->SetVerticalJustificationToBottom( );
48 vtkCoordinate* coord = this->m_TextActor->GetPositionCoordinate( );
49 coord->SetCoordinateSystemToNormalizedViewport( );
50 coord->SetValue( 0.01, 0.05 );
53 vtkSmartPointer< TStyle > st = vtkSmartPointer< TStyle >::New( );
54 st->SetAssociatedObject( this );
55 st->AddMouseMoveCommand( Self::_MouseMoveCommand, this );
56 st->AddMouseClickCommand( Self::_MouseClickCommand, this );
57 st->AddMouseWheelCommand( Self::_MouseWheelCommand, this );
58 st->AddKeyCommand( Self::_KeyCommand, this );
59 st->AddEnterCommand( Self::_EnterCommand, this );
60 st->AddLeaveCommand( Self::_LeaveCommand, this );
64 // -------------------------------------------------------------------------
65 void cpExtensions::Visualization::ImageSliceActors::
66 SetInputConnection( vtkAlgorithmOutput* aout, int orientation )
70 this->m_Mapper->SetInputConnection( aout );
71 this->_ConfigureInput( orientation );
74 // -------------------------------------------------------------------------
75 void cpExtensions::Visualization::ImageSliceActors::
76 SetInputData( vtkImageData* data, int orientation )
80 this->m_Mapper->SetInputData( data );
81 this->_ConfigureInput( orientation );
84 // -------------------------------------------------------------------------
85 void cpExtensions::Visualization::ImageSliceActors::
86 AssociateSlice( Self* slice )
88 this->m_AssociatedSlices.push_back( slice );
92 // -------------------------------------------------------------------------
93 void cpExtensions::Visualization::ImageSliceActors::
94 CleanAssociatedSlices( )
96 this->m_AssociatedSlices.clear( );
100 // -------------------------------------------------------------------------
101 cpExtensions::Interaction::ImageInteractorStyle*
102 cpExtensions::Visualization::ImageSliceActors::
105 return( dynamic_cast< TStyle* >( this->m_Style.GetPointer( ) ) );
108 // -------------------------------------------------------------------------
109 void cpExtensions::Visualization::ImageSliceActors::
110 SetStyle( vtkInteractorStyle* st )
116 // -------------------------------------------------------------------------
117 void cpExtensions::Visualization::ImageSliceActors::
118 PushInto( vtkRenderer* ren )
120 this->InitTraversal( );
122 while( ( prop = this->GetNextProp( ) ) != NULL )
123 ren->AddViewProp( prop );
126 // -------------------------------------------------------------------------
127 void cpExtensions::Visualization::ImageSliceActors::
128 PopFrom( vtkRenderer* ren )
130 this->InitTraversal( );
132 while( ( prop = this->GetNextProp( ) ) != NULL )
133 ren->RemoveViewProp( prop );
136 // -------------------------------------------------------------------------
137 long cpExtensions::Visualization::ImageSliceActors::
138 GetSliceNumber( ) const
140 if( this->m_Mapper.GetPointer( ) != NULL )
141 return( this->m_Mapper->GetSliceNumber( ) );
146 // -------------------------------------------------------------------------
147 void cpExtensions::Visualization::ImageSliceActors::
148 SetSliceNumber( long slice )
150 if( this->m_Mapper.GetPointer( ) == NULL )
154 int a = this->m_Mapper->GetOrientation( );
158 this->m_Mapper->GetInput( )->GetExtent( ext );
160 rs = ( rs > ext[ a << 1 ] )? rs: ext[ a << 1 ];
161 rs = ( rs < ext[ ( a << 1 ) + 1 ] )? rs: ext[ ( a << 1 ) + 1 ];
164 this->m_Mapper->SetSliceNumber( rs );
166 // Update display extent (this isn't done automatically)
167 ext[ a << 1 ] = ext[ ( a << 1 ) + 1 ] = rs;
168 this->m_Actor->SetDisplayExtent( ext );
170 this->m_Mapper->Modified( );
171 this->m_Actor->Modified( );
172 this->_ConfigureCursor( );
176 // -------------------------------------------------------------------------
177 void cpExtensions::Visualization::ImageSliceActors::
178 ShowPixelText( double* pos )
180 if( this->m_Mapper.GetPointer( ) != NULL )
183 int axId = this->m_Mapper->GetOrientation( );
184 if ( axId == 0 ) axis = 'X';
185 else if( axId == 1 ) axis = 'Y';
186 else if( axId == 2 ) axis = 'Z';
187 long slice = this->GetSliceNumber( );
189 vtkImageData* image = this->m_Actor->GetInput( );
192 image->ComputeStructuredCoordinates( pos, ijk, pcoords );
196 image->GetExtent( ext );
198 ext[ 0 ] <= ijk[ 0 ] && ijk[ 0 ] <= ext[ 1 ] &&
199 ext[ 2 ] <= ijk[ 1 ] && ijk[ 1 ] <= ext[ 3 ] &&
200 ext[ 4 ] <= ijk[ 2 ] && ijk[ 2 ] <= ext[ 5 ]
203 int nScl = image->GetNumberOfScalarComponents( );
204 std::stringstream str;
208 << "," << ijk[ 2 ] << "]=(";
210 image->GetScalarComponentAsFloat( ijk[ 0 ], ijk[ 1 ], ijk[ 2 ], 0 );
211 for( int n = 1; n < nScl; ++n )
214 << image->GetScalarComponentAsFloat(
215 ijk[ 0 ], ijk[ 1 ], ijk[ 2 ], n
221 this->m_TextBuffer, MAX_TEXT_BUFFER, "Axis: %c (%d)\nPixel %s",
222 axis, slice, str.str( ).c_str( )
224 #else // defined(WIN32)
226 this->m_TextBuffer, "Axis: %c (%d)\nPixel %s",
227 axis, slice, str.str( ).c_str( )
229 #endif // defined(WIN32)
233 this->m_TextBuffer[ 0 ] = '\0';
234 this->m_TextActor->SetInput( this->m_TextBuffer );
235 this->m_TextActor->Modified( );
239 // -------------------------------------------------------------------------
240 void cpExtensions::Visualization::ImageSliceActors::
241 GetScalarRange( double r[ 2 ] ) const
243 r[ 0 ] = this->m_ScalarRange[ 0 ];
244 r[ 1 ] = this->m_ScalarRange[ 1 ];
247 // -------------------------------------------------------------------------
248 void cpExtensions::Visualization::ImageSliceActors::
249 SetScalarRange( const double& a, const double& b )
251 this->m_ManualScalarRange = true;
252 this->m_ScalarRange[ 0 ] = a;
253 this->m_ScalarRange[ 1 ] = b;
254 this->SetWindowLevel( 1, 0.5 );
257 // -------------------------------------------------------------------------
258 void cpExtensions::Visualization::ImageSliceActors::
261 auto image = this->m_Actor->GetInput( );
265 image->GetScalarRange( r );
266 this->SetScalarRange( r[ 0 ], r[ 1 ] );
269 this->m_ManualScalarRange = false;
272 // -------------------------------------------------------------------------
273 void cpExtensions::Visualization::ImageSliceActors::
274 SetWindowLevel( const double& w, const double& l )
276 static const double _0 = double( 0 );
277 static const double _1 = double( 1 );
279 double rw = ( w < _0 )? _0: ( ( w > _1 )? _1: w );
280 double rl = ( l < _0 )? _0: ( ( l > _1 )? _1: l );
282 double d = this->m_ScalarRange[ 1 ] - this->m_ScalarRange[ 0 ];
285 rl += this->m_ScalarRange[ 0 ];
287 if( this->m_Actor.GetPointer( ) != NULL )
289 this->m_Actor->GetProperty( )->SetColorWindow( rw );
290 this->m_Actor->GetProperty( )->SetColorLevel( rl );
296 // -------------------------------------------------------------------------
297 double cpExtensions::Visualization::ImageSliceActors::
300 if( this->m_Actor.GetPointer( ) != NULL )
301 return( this->m_Actor->GetProperty( )->GetColorWindow( ) );
303 return( double( 0 ) );
306 // -------------------------------------------------------------------------
307 double cpExtensions::Visualization::ImageSliceActors::
310 if( this->m_Actor.GetPointer( ) != NULL )
311 return( this->m_Actor->GetProperty( )->GetColorLevel( ) );
313 return( double( 0 ) );
316 // -------------------------------------------------------------------------
317 void cpExtensions::Visualization::ImageSliceActors::
320 auto ren = this->m_Style->GetCurrentRenderer( );
323 auto win = ren->GetRenderWindow( );
329 // -------------------------------------------------------------------------
330 cpExtensions::Visualization::ImageSliceActors::
333 m_ManualScalarRange( false )
338 // -------------------------------------------------------------------------
339 cpExtensions::Visualization::ImageSliceActors::
344 // -------------------------------------------------------------------------
345 void cpExtensions::Visualization::ImageSliceActors::
346 _ConfigureInput( int orientation )
348 // Prepare main image
349 this->m_Mapper->SetOrientation( orientation );
350 this->m_Mapper->Update( );
351 this->m_Actor->GetProperty( )->SetOpacity( 0.8 );
352 this->m_Actor->Modified( );
353 auto st = this->GetStyle( );
355 st->AssociateImageActor( this->m_Actor );
356 this->AddItem( this->m_Actor );
358 // Prepare main cursor
359 this->_ConfigureCursor( );
360 this->AddItem( this->m_Cursor.Actor );
362 // Prepare window/level
363 if( !( this->m_ManualScalarRange ) )
364 this->UnsetScalarRange( );
366 // Add all other actors
367 this->AddItem( this->m_TextActor );
369 // Put it in the first slice
370 auto image = this->m_Mapper->GetInput( );
372 image->GetExtent( ext );
373 this->SetSliceNumber( ext[ orientation << 1 ] );
376 if( this->m_Style.GetPointer( ) != NULL )
377 this->AddItem( this->m_Actor );
379 this->SetSliceNumber( this->GetSliceNumberMinValue( ) );
380 this->ResetCursor( );
384 this->ResetCursor( );
385 this->ResetAxesCursor( );
387 // Update window/level ranges
388 vtkImageData* data = this->GetInputImage( );
392 data->GetScalarRange( r );
393 this->m_WLRange[ 0 ] = double( 0 );
394 this->m_WLRange[ 1 ] = r[ 1 ] - r[ 0 ];
395 this->m_WLRange[ 2 ] = r[ 0 ];
396 this->m_WLRange[ 3 ] = r[ 1 ];
397 this->ResetWindowLevel( );
400 this->m_BlenderBase = vtkSmartPointer< vtkImageData >::New( );
401 this->m_BlenderBase->ShallowCopy( data );
402 this->m_BlenderBase->AllocateScalars( VTK_UNSIGNED_CHAR, 1 );
404 this->m_BlenderBase->GetScalarPointer( ), 0,
405 this->m_BlenderBase->GetActualMemorySize( )
407 this->m_Blender->AddInputData( this->m_BlenderBase );
413 // -------------------------------------------------------------------------
414 void cpExtensions::Visualization::ImageSliceActors::
417 int a = this->m_Mapper->GetOrientation( );
419 this->m_Actor->GetBounds( bounds );
420 bounds[ a << 1 ] += 1e-5;
421 bounds[ ( a << 1 ) + 1 ] += 1e-5;
423 this->m_Cursor.Source->SetModelBounds( bounds );
424 this->m_Cursor.Source->AllOn( );
425 this->m_Cursor.Actor->GetProperty( )->SetOpacity( 1 );
426 this->m_Cursor.Actor->GetProperty( )->SetLineWidth( 3 );
427 this->m_Cursor.Modified( );
430 // -------------------------------------------------------------------------
431 void cpExtensions::Visualization::ImageSliceActors::
434 const TStyle::ButtonID& btn,
435 int* idx, double* pos,
436 bool alt, bool ctr, bool sft
439 ImageSliceActors* self = reinterpret_cast< ImageSliceActors* >( data );
443 if( btn == TStyle::ButtonID_None )
445 self->ShowPixelText( pos );
446 self->m_Cursor.Source->SetFocalPoint( pos );
447 self->m_Cursor.Source->Modified( );
448 self->m_Cursor.Modified( );
451 else if( btn == TStyle::ButtonID_Right )
453 if( !alt && !ctr && sft )
455 int a0 = self->m_Mapper->GetOrientation( );
456 int a1 = ( a0 + 1 ) % 3;
457 int a2 = ( a0 + 2 ) % 3;
458 double dx = pos[ a1 ] - self->m_StartMouseEvent[ a1 ];
459 double dy = pos[ a2 ] - self->m_StartMouseEvent[ a2 ];
461 self->m_Actor->GetBounds( bounds );
462 dx /= bounds[ ( a1 << 1 ) + 1 ] - bounds[ a1 << 1 ];
463 dy /= bounds[ ( a2 << 1 ) + 1 ] - bounds[ a2 << 1 ];
464 double w = self->m_StartWindow + dx;
465 double l = self->m_StartLevel + dy;
467 self->SetWindowLevel( w, l );
470 auto aIt = self->m_AssociatedSlices.begin( );
471 aIt != self->m_AssociatedSlices.end( );
475 ( *aIt )->SetWindowLevel( w, l );
485 // -------------------------------------------------------------------------
486 void cpExtensions::Visualization::ImageSliceActors::
489 const TStyle::ButtonID& btn,
490 int* idx, double* pos,
491 bool alt, bool ctr, bool sft
494 ImageSliceActors* self = reinterpret_cast< ImageSliceActors* >( data );
498 self->m_StartMouseEvent[ 0 ] = pos[ 0 ];
499 self->m_StartMouseEvent[ 1 ] = pos[ 1 ];
500 self->m_StartMouseEvent[ 2 ] = pos[ 2 ];
502 if( btn == TStyle::ButtonID_Right )
504 if( !alt && !ctr && sft )
507 self->GetScalarRange( r );
508 double d = r[ 1 ] - r[ 0 ];
509 self->m_StartWindow = self->GetWindow( ) / d;
510 self->m_StartLevel = ( self->GetLevel( ) - r[ 0 ] ) / d;
517 // -------------------------------------------------------------------------
518 void cpExtensions::Visualization::ImageSliceActors::
521 const int& dir, bool alt, bool ctr, bool sft
524 ImageSliceActors* self = reinterpret_cast< ImageSliceActors* >( data );
527 auto ren = self->m_Style->GetCurrentRenderer( );
530 auto cam = ren->GetActiveCamera( );
533 auto win = ren->GetRenderWindow( );
537 // Get previous values
538 int a = self->m_Mapper->GetOrientation( );
540 self->m_Actor->GetBounds( bounds );
541 double prev_pos = bounds[ a << 1 ];
544 long slice = self->GetSliceNumber( ) + dir * ( ( sft )? 10: 1 );
545 self->SetSliceNumber( slice );
546 self->m_Actor->GetBounds( bounds );
550 cam->GetPosition( cam_pos );
551 cam_pos[ a ] += bounds[ a << 1 ] - prev_pos;
552 cam->SetPosition( cam_pos );
555 self->ShowPixelText( self->m_Cursor.Source->GetFocalPoint( ) );
560 auto aIt = self->m_AssociatedSlices.begin( );
561 aIt != self->m_AssociatedSlices.end( );
565 if( ( *aIt )->m_Mapper->GetOrientation( ) == a )
567 ( *aIt )->SetSliceNumber( slice );
575 // -------------------------------------------------------------------------
576 void cpExtensions::Visualization::ImageSliceActors::
584 // -------------------------------------------------------------------------
585 void cpExtensions::Visualization::ImageSliceActors::
586 _EnterCommand( void* data )
590 // -------------------------------------------------------------------------
591 void cpExtensions::Visualization::ImageSliceActors::
592 _LeaveCommand( void* data )