1 #include <cpExtensions/Visualization/ImageSliceActors.h>
5 #include <vtkImageData.h>
6 #include <vtkImageProperty.h>
8 #include <vtkProperty.h>
9 #include <vtkRenderer.h>
10 #include <vtkRenderWindow.h>
11 #include <vtkTextProperty.h>
13 // -------------------------------------------------------------------------
14 cpExtensions::Visualization::ImageSliceActors::
15 Self* cpExtensions::Visualization::ImageSliceActors::
18 return( new Self( ) );
21 // -------------------------------------------------------------------------
22 void cpExtensions::Visualization::ImageSliceActors::
25 this->RemoveAllItems( );
28 this->m_Mapper = vtkSmartPointer< vtkImageSliceMapper >::New( );
29 this->m_Actor = vtkSmartPointer< vtkImageActor >::New( );
30 this->m_Actor->SetMapper( this->m_Mapper );
33 this->m_Cursor.Create( );
34 this->m_Cursor.Actor->GetProperty( )->SetColor( 1, 1, 0 );
37 this->m_TextBuffer[ 0 ] = '\0';
38 this->m_TextActor = vtkSmartPointer< vtkTextActor >::New( );
39 this->m_TextActor->SetTextScaleModeToNone( );
40 vtkTextProperty* textprop = this->m_TextActor->GetTextProperty( );
41 textprop->SetColor( 1, 1, 0 );
42 textprop->SetFontFamilyToCourier( );
43 textprop->SetFontSize( 18 );
45 textprop->ItalicOff( );
46 textprop->ShadowOff( );
47 textprop->SetJustificationToLeft( );
48 textprop->SetVerticalJustificationToBottom( );
49 vtkCoordinate* coord = this->m_TextActor->GetPositionCoordinate( );
50 coord->SetCoordinateSystemToNormalizedViewport( );
51 coord->SetValue( 0.01, 0.05 );
54 vtkSmartPointer< TStyle > st = vtkSmartPointer< TStyle >::New( );
55 st->SetAssociatedObject( this );
56 st->AddMouseMoveCommand( Self::_MouseMoveCommand, this );
57 st->AddMouseClickCommand( Self::_MouseClickCommand, this );
58 st->AddMouseWheelCommand( Self::_MouseWheelCommand, this );
59 st->AddKeyCommand( Self::_KeyCommand, this );
60 st->AddEnterCommand( Self::_EnterCommand, this );
61 st->AddLeaveCommand( Self::_LeaveCommand, this );
65 // -------------------------------------------------------------------------
66 void cpExtensions::Visualization::ImageSliceActors::
67 SetInputConnection( vtkAlgorithmOutput* aout, int orientation )
71 this->m_Mapper->SetInputConnection( aout );
72 this->_ConfigureInput( orientation );
75 // -------------------------------------------------------------------------
76 void cpExtensions::Visualization::ImageSliceActors::
77 SetInputData( vtkImageData* data, int orientation )
81 this->m_Mapper->SetInputData( data );
82 this->_ConfigureInput( orientation );
85 // -------------------------------------------------------------------------
86 vtkImageData* cpExtensions::Visualization::ImageSliceActors::
89 if( this->m_Mapper.GetPointer( ) != NULL )
90 return( this->m_Mapper->GetInput( ) );
95 // -------------------------------------------------------------------------
96 vtkImageActor* cpExtensions::Visualization::ImageSliceActors::
99 return( this->m_Actor.GetPointer( ) );
102 // -------------------------------------------------------------------------
103 const vtkImageActor* cpExtensions::Visualization::ImageSliceActors::
104 GetImageActor( ) const
106 return( this->m_Actor.GetPointer( ) );
109 // -------------------------------------------------------------------------
110 void cpExtensions::Visualization::ImageSliceActors::
111 AddMesh( vtkPolyData* mesh )
113 SourceActor< vtkCutter > a;
115 a.Source->SetInputData( mesh );
116 a.Source->SetCutFunction( this->m_Mapper->GetSlicePlane( ) );
117 a.Source->SetValue( 0, 0 );
118 a.Source->GenerateTrianglesOff( );
121 this->m_Meshes[ mesh ] = a;
122 this->AddItem( a.Actor );
124 auto ren = this->m_Style->GetCurrentRenderer( );
126 if( ren->HasViewProp( this->m_Actor ) )
127 ren->AddViewProp( a.Actor );
130 // -------------------------------------------------------------------------
131 void cpExtensions::Visualization::ImageSliceActors::
132 AssociateSlice( Self* slice )
134 this->m_AssociatedSlices.push_back( slice );
138 // -------------------------------------------------------------------------
139 void cpExtensions::Visualization::ImageSliceActors::
140 CleanAssociatedSlices( )
142 this->m_AssociatedSlices.clear( );
146 // -------------------------------------------------------------------------
147 cpExtensions::Interaction::ImageInteractorStyle*
148 cpExtensions::Visualization::ImageSliceActors::
151 return( dynamic_cast< TStyle* >( this->m_Style.GetPointer( ) ) );
154 // -------------------------------------------------------------------------
155 void cpExtensions::Visualization::ImageSliceActors::
156 SetStyle( vtkInteractorStyle* st )
162 // -------------------------------------------------------------------------
163 void cpExtensions::Visualization::ImageSliceActors::
164 PushInto( vtkRenderer* ren )
166 this->InitTraversal( );
168 while( ( prop = this->GetNextProp( ) ) != NULL )
169 ren->AddViewProp( prop );
172 // -------------------------------------------------------------------------
173 void cpExtensions::Visualization::ImageSliceActors::
174 PopFrom( vtkRenderer* ren )
176 this->InitTraversal( );
178 while( ( prop = this->GetNextProp( ) ) != NULL )
179 ren->RemoveViewProp( prop );
182 // -------------------------------------------------------------------------
183 long cpExtensions::Visualization::ImageSliceActors::
184 GetSliceNumber( ) const
186 if( this->m_Mapper.GetPointer( ) != NULL )
187 return( this->m_Mapper->GetSliceNumber( ) );
192 // -------------------------------------------------------------------------
193 void cpExtensions::Visualization::ImageSliceActors::
194 SetSliceNumber( long slice )
196 if( this->m_Mapper.GetPointer( ) == NULL )
200 int a = this->m_Mapper->GetOrientation( );
204 this->m_Mapper->GetInput( )->GetExtent( ext );
206 rs = ( rs > ext[ a << 1 ] )? rs: ext[ a << 1 ];
207 rs = ( rs < ext[ ( a << 1 ) + 1 ] )? rs: ext[ ( a << 1 ) + 1 ];
210 this->m_Mapper->SetSliceNumber( rs );
212 // Update display extent (this isn't done automatically)
213 ext[ a << 1 ] = ext[ ( a << 1 ) + 1 ] = rs;
214 this->m_Actor->SetDisplayExtent( ext );
216 this->m_Mapper->Modified( );
217 this->m_Actor->Modified( );
218 this->_ConfigureCursor( );
222 // -------------------------------------------------------------------------
223 void cpExtensions::Visualization::ImageSliceActors::
224 ShowPixelText( double* pos )
226 if( this->m_Mapper.GetPointer( ) != NULL )
229 int axId = this->m_Mapper->GetOrientation( );
230 if ( axId == 0 ) axis = 'X';
231 else if( axId == 1 ) axis = 'Y';
232 else if( axId == 2 ) axis = 'Z';
233 long slice = this->GetSliceNumber( );
235 vtkImageData* image = this->m_Actor->GetInput( );
238 image->ComputeStructuredCoordinates( pos, ijk, pcoords );
242 image->GetExtent( ext );
244 ext[ 0 ] <= ijk[ 0 ] && ijk[ 0 ] <= ext[ 1 ] &&
245 ext[ 2 ] <= ijk[ 1 ] && ijk[ 1 ] <= ext[ 3 ] &&
246 ext[ 4 ] <= ijk[ 2 ] && ijk[ 2 ] <= ext[ 5 ]
249 int nScl = image->GetNumberOfScalarComponents( );
250 std::stringstream str;
254 << "," << ijk[ 2 ] << "]=(";
256 image->GetScalarComponentAsFloat( ijk[ 0 ], ijk[ 1 ], ijk[ 2 ], 0 );
257 for( int n = 1; n < nScl; ++n )
260 << image->GetScalarComponentAsFloat(
261 ijk[ 0 ], ijk[ 1 ], ijk[ 2 ], n
267 this->m_TextBuffer, MAX_TEXT_BUFFER, "Axis: %c (%d)\nPixel %s",
268 axis, slice, str.str( ).c_str( )
270 #else // defined(WIN32)
272 this->m_TextBuffer, "Axis: %c (%ld)\nPixel %s",
273 axis, slice, str.str( ).c_str( )
275 #endif // defined(WIN32)
279 this->m_TextBuffer[ 0 ] = '\0';
280 this->m_TextActor->SetInput( this->m_TextBuffer );
281 this->m_TextActor->Modified( );
285 // -------------------------------------------------------------------------
286 void cpExtensions::Visualization::ImageSliceActors::
287 GetScalarRange( double r[ 2 ] ) const
289 r[ 0 ] = this->m_ScalarRange[ 0 ];
290 r[ 1 ] = this->m_ScalarRange[ 1 ];
293 // -------------------------------------------------------------------------
294 void cpExtensions::Visualization::ImageSliceActors::
295 SetScalarRange( const double& a, const double& b )
297 this->m_ManualScalarRange = true;
298 this->m_ScalarRange[ 0 ] = a;
299 this->m_ScalarRange[ 1 ] = b;
300 this->SetWindowLevel( 1, 0.5 );
303 // -------------------------------------------------------------------------
304 void cpExtensions::Visualization::ImageSliceActors::
307 auto image = this->m_Actor->GetInput( );
311 image->GetScalarRange( r );
312 this->SetScalarRange( r[ 0 ], r[ 1 ] );
315 this->m_ManualScalarRange = false;
318 // -------------------------------------------------------------------------
319 void cpExtensions::Visualization::ImageSliceActors::
320 SetWindowLevel( const double& w, const double& l )
322 static const double _0 = double( 0 );
323 static const double _1 = double( 1 );
325 double rw = ( w < _0 )? _0: ( ( w > _1 )? _1: w );
326 double rl = ( l < _0 )? _0: ( ( l > _1 )? _1: l );
328 double d = this->m_ScalarRange[ 1 ] - this->m_ScalarRange[ 0 ];
331 rl += this->m_ScalarRange[ 0 ];
333 if( this->m_Actor.GetPointer( ) != NULL )
335 this->m_Actor->GetProperty( )->SetColorWindow( rw );
336 this->m_Actor->GetProperty( )->SetColorLevel( rl );
342 // -------------------------------------------------------------------------
343 double cpExtensions::Visualization::ImageSliceActors::
346 if( this->m_Actor.GetPointer( ) != NULL )
347 return( this->m_Actor->GetProperty( )->GetColorWindow( ) );
349 return( double( 0 ) );
352 // -------------------------------------------------------------------------
353 double cpExtensions::Visualization::ImageSliceActors::
356 if( this->m_Actor.GetPointer( ) != NULL )
357 return( this->m_Actor->GetProperty( )->GetColorLevel( ) );
359 return( double( 0 ) );
362 // -------------------------------------------------------------------------
363 void cpExtensions::Visualization::ImageSliceActors::
366 auto ren = this->m_Style->GetCurrentRenderer( );
369 auto win = ren->GetRenderWindow( );
375 // -------------------------------------------------------------------------
376 cpExtensions::Visualization::ImageSliceActors::
379 m_ManualScalarRange( false )
384 // -------------------------------------------------------------------------
385 cpExtensions::Visualization::ImageSliceActors::
390 // -------------------------------------------------------------------------
391 void cpExtensions::Visualization::ImageSliceActors::
392 _ConfigureInput( int orientation )
394 // Prepare main image
395 this->m_Mapper->SetOrientation( orientation );
396 this->m_Mapper->Update( );
397 this->m_Actor->GetProperty( )->SetOpacity( 0.8 );
398 this->m_Actor->Modified( );
399 auto st = this->GetStyle( );
401 st->AssociateImageActor( this->m_Actor );
402 this->AddItem( this->m_Actor );
404 // Prepare main cursor
405 this->_ConfigureCursor( );
406 this->AddItem( this->m_Cursor.Actor );
408 // Prepare window/level
409 if( !( this->m_ManualScalarRange ) )
410 this->UnsetScalarRange( );
412 // Add all other actors
413 this->AddItem( this->m_TextActor );
415 // Put it in the first slice
416 auto image = this->m_Mapper->GetInput( );
418 image->GetExtent( ext );
419 this->SetSliceNumber( ext[ orientation << 1 ] );
422 if( this->m_Style.GetPointer( ) != NULL )
423 this->AddItem( this->m_Actor );
425 this->SetSliceNumber( this->GetSliceNumberMinValue( ) );
426 this->ResetCursor( );
430 this->ResetCursor( );
431 this->ResetAxesCursor( );
433 // Update window/level ranges
434 vtkImageData* data = this->GetInputImage( );
438 data->GetScalarRange( r );
439 this->m_WLRange[ 0 ] = double( 0 );
440 this->m_WLRange[ 1 ] = r[ 1 ] - r[ 0 ];
441 this->m_WLRange[ 2 ] = r[ 0 ];
442 this->m_WLRange[ 3 ] = r[ 1 ];
443 this->ResetWindowLevel( );
446 this->m_BlenderBase = vtkSmartPointer< vtkImageData >::New( );
447 this->m_BlenderBase->ShallowCopy( data );
448 this->m_BlenderBase->AllocateScalars( VTK_UNSIGNED_CHAR, 1 );
450 this->m_BlenderBase->GetScalarPointer( ), 0,
451 this->m_BlenderBase->GetActualMemorySize( )
453 this->m_Blender->AddInputData( this->m_BlenderBase );
459 // -------------------------------------------------------------------------
460 void cpExtensions::Visualization::ImageSliceActors::
463 int a = this->m_Mapper->GetOrientation( );
465 this->m_Actor->GetBounds( bounds );
466 bounds[ a << 1 ] += 1e-5;
467 bounds[ ( a << 1 ) + 1 ] += 1e-5;
469 this->m_Cursor.Source->SetModelBounds( bounds );
470 this->m_Cursor.Source->AllOn( );
471 this->m_Cursor.Actor->GetProperty( )->SetOpacity( 1 );
472 this->m_Cursor.Actor->GetProperty( )->SetLineWidth( 3 );
473 this->m_Cursor.Modified( );
476 // -------------------------------------------------------------------------
477 void cpExtensions::Visualization::ImageSliceActors::
480 const TStyle::ButtonID& btn,
481 int* idx, double* pos,
482 bool alt, bool ctr, bool sft
485 ImageSliceActors* self = reinterpret_cast< ImageSliceActors* >( data );
489 if( btn == TStyle::ButtonID_None )
491 self->ShowPixelText( pos );
492 self->m_Cursor.Source->SetFocalPoint( pos );
493 self->m_Cursor.Source->Modified( );
494 self->m_Cursor.Modified( );
497 else if( btn == TStyle::ButtonID_Right )
499 if( !alt && !ctr && sft )
501 int a0 = self->m_Mapper->GetOrientation( );
502 int a1 = ( a0 + 1 ) % 3;
503 int a2 = ( a0 + 2 ) % 3;
504 double dx = pos[ a1 ] - self->m_StartMouseEvent[ a1 ];
505 double dy = pos[ a2 ] - self->m_StartMouseEvent[ a2 ];
507 self->m_Actor->GetBounds( bounds );
508 dx /= bounds[ ( a1 << 1 ) + 1 ] - bounds[ a1 << 1 ];
509 dy /= bounds[ ( a2 << 1 ) + 1 ] - bounds[ a2 << 1 ];
510 double w = self->m_StartWindow + dx;
511 double l = self->m_StartLevel + dy;
513 self->SetWindowLevel( w, l );
516 auto aIt = self->m_AssociatedSlices.begin( );
517 aIt != self->m_AssociatedSlices.end( );
521 ( *aIt )->SetWindowLevel( w, l );
531 // -------------------------------------------------------------------------
532 void cpExtensions::Visualization::ImageSliceActors::
535 const TStyle::ButtonID& btn,
536 int* idx, double* pos,
537 bool alt, bool ctr, bool sft
540 ImageSliceActors* self = reinterpret_cast< ImageSliceActors* >( data );
544 self->m_StartMouseEvent[ 0 ] = pos[ 0 ];
545 self->m_StartMouseEvent[ 1 ] = pos[ 1 ];
546 self->m_StartMouseEvent[ 2 ] = pos[ 2 ];
548 if( btn == TStyle::ButtonID_Right )
550 if( !alt && !ctr && sft )
553 self->GetScalarRange( r );
554 double d = r[ 1 ] - r[ 0 ];
555 self->m_StartWindow = self->GetWindow( ) / d;
556 self->m_StartLevel = ( self->GetLevel( ) - r[ 0 ] ) / d;
563 // -------------------------------------------------------------------------
564 void cpExtensions::Visualization::ImageSliceActors::
567 const int& dir, bool alt, bool ctr, bool sft
570 ImageSliceActors* self = reinterpret_cast< ImageSliceActors* >( data );
573 auto ren = self->m_Style->GetCurrentRenderer( );
576 auto cam = ren->GetActiveCamera( );
579 auto win = ren->GetRenderWindow( );
583 // Get previous values
584 int a = self->m_Mapper->GetOrientation( );
586 self->m_Actor->GetBounds( bounds );
587 double prev_pos = bounds[ a << 1 ];
590 long slice = self->GetSliceNumber( ) + dir * ( ( sft )? 10: 1 );
591 self->SetSliceNumber( slice );
592 self->m_Actor->GetBounds( bounds );
596 cam->GetPosition( cam_pos );
597 cam_pos[ a ] += bounds[ a << 1 ] - prev_pos;
598 cam->SetPosition( cam_pos );
601 self->ShowPixelText( self->m_Cursor.Source->GetFocalPoint( ) );
606 auto aIt = self->m_AssociatedSlices.begin( );
607 aIt != self->m_AssociatedSlices.end( );
611 if( ( *aIt )->m_Mapper->GetOrientation( ) == a )
613 ( *aIt )->SetSliceNumber( slice );
621 // -------------------------------------------------------------------------
622 void cpExtensions::Visualization::ImageSliceActors::
630 // -------------------------------------------------------------------------
631 void cpExtensions::Visualization::ImageSliceActors::
632 _EnterCommand( void* data )
636 // -------------------------------------------------------------------------
637 void cpExtensions::Visualization::ImageSliceActors::
638 _LeaveCommand( void* data )