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 void cpExtensions::Visualization::ImageSliceActors::
97 AddMesh( vtkPolyData* mesh )
99 SourceActor< vtkCutter > a;
101 a.Source->SetInputData( mesh );
102 a.Source->SetCutFunction( this->m_Mapper->GetSlicePlane( ) );
103 a.Source->SetValue( 0, 0 );
104 a.Source->GenerateTrianglesOff( );
107 this->m_Meshes[ mesh ] = a;
108 this->AddItem( a.Actor );
110 auto ren = this->m_Style->GetCurrentRenderer( );
112 if( ren->HasViewProp( this->m_Actor ) )
113 ren->AddViewProp( a.Actor );
116 // -------------------------------------------------------------------------
117 void cpExtensions::Visualization::ImageSliceActors::
118 AssociateSlice( Self* slice )
120 this->m_AssociatedSlices.push_back( slice );
124 // -------------------------------------------------------------------------
125 void cpExtensions::Visualization::ImageSliceActors::
126 CleanAssociatedSlices( )
128 this->m_AssociatedSlices.clear( );
132 // -------------------------------------------------------------------------
133 cpExtensions::Interaction::ImageInteractorStyle*
134 cpExtensions::Visualization::ImageSliceActors::
137 return( dynamic_cast< TStyle* >( this->m_Style.GetPointer( ) ) );
140 // -------------------------------------------------------------------------
141 void cpExtensions::Visualization::ImageSliceActors::
142 SetStyle( vtkInteractorStyle* st )
148 // -------------------------------------------------------------------------
149 void cpExtensions::Visualization::ImageSliceActors::
150 PushInto( vtkRenderer* ren )
152 this->InitTraversal( );
154 while( ( prop = this->GetNextProp( ) ) != NULL )
155 ren->AddViewProp( prop );
158 // -------------------------------------------------------------------------
159 void cpExtensions::Visualization::ImageSliceActors::
160 PopFrom( vtkRenderer* ren )
162 this->InitTraversal( );
164 while( ( prop = this->GetNextProp( ) ) != NULL )
165 ren->RemoveViewProp( prop );
168 // -------------------------------------------------------------------------
169 long cpExtensions::Visualization::ImageSliceActors::
170 GetSliceNumber( ) const
172 if( this->m_Mapper.GetPointer( ) != NULL )
173 return( this->m_Mapper->GetSliceNumber( ) );
178 // -------------------------------------------------------------------------
179 void cpExtensions::Visualization::ImageSliceActors::
180 SetSliceNumber( long slice )
182 if( this->m_Mapper.GetPointer( ) == NULL )
186 int a = this->m_Mapper->GetOrientation( );
190 this->m_Mapper->GetInput( )->GetExtent( ext );
192 rs = ( rs > ext[ a << 1 ] )? rs: ext[ a << 1 ];
193 rs = ( rs < ext[ ( a << 1 ) + 1 ] )? rs: ext[ ( a << 1 ) + 1 ];
196 this->m_Mapper->SetSliceNumber( rs );
198 // Update display extent (this isn't done automatically)
199 ext[ a << 1 ] = ext[ ( a << 1 ) + 1 ] = rs;
200 this->m_Actor->SetDisplayExtent( ext );
202 this->m_Mapper->Modified( );
203 this->m_Actor->Modified( );
204 this->_ConfigureCursor( );
208 // -------------------------------------------------------------------------
209 void cpExtensions::Visualization::ImageSliceActors::
210 ShowPixelText( double* pos )
212 if( this->m_Mapper.GetPointer( ) != NULL )
215 int axId = this->m_Mapper->GetOrientation( );
216 if ( axId == 0 ) axis = 'X';
217 else if( axId == 1 ) axis = 'Y';
218 else if( axId == 2 ) axis = 'Z';
219 long slice = this->GetSliceNumber( );
221 vtkImageData* image = this->m_Actor->GetInput( );
224 image->ComputeStructuredCoordinates( pos, ijk, pcoords );
228 image->GetExtent( ext );
230 ext[ 0 ] <= ijk[ 0 ] && ijk[ 0 ] <= ext[ 1 ] &&
231 ext[ 2 ] <= ijk[ 1 ] && ijk[ 1 ] <= ext[ 3 ] &&
232 ext[ 4 ] <= ijk[ 2 ] && ijk[ 2 ] <= ext[ 5 ]
235 int nScl = image->GetNumberOfScalarComponents( );
236 std::stringstream str;
240 << "," << ijk[ 2 ] << "]=(";
242 image->GetScalarComponentAsFloat( ijk[ 0 ], ijk[ 1 ], ijk[ 2 ], 0 );
243 for( int n = 1; n < nScl; ++n )
246 << image->GetScalarComponentAsFloat(
247 ijk[ 0 ], ijk[ 1 ], ijk[ 2 ], n
253 this->m_TextBuffer, MAX_TEXT_BUFFER, "Axis: %c (%d)\nPixel %s",
254 axis, slice, str.str( ).c_str( )
256 #else // defined(WIN32)
258 this->m_TextBuffer, "Axis: %c (%d)\nPixel %s",
259 axis, slice, str.str( ).c_str( )
261 #endif // defined(WIN32)
265 this->m_TextBuffer[ 0 ] = '\0';
266 this->m_TextActor->SetInput( this->m_TextBuffer );
267 this->m_TextActor->Modified( );
271 // -------------------------------------------------------------------------
272 void cpExtensions::Visualization::ImageSliceActors::
273 GetScalarRange( double r[ 2 ] ) const
275 r[ 0 ] = this->m_ScalarRange[ 0 ];
276 r[ 1 ] = this->m_ScalarRange[ 1 ];
279 // -------------------------------------------------------------------------
280 void cpExtensions::Visualization::ImageSliceActors::
281 SetScalarRange( const double& a, const double& b )
283 this->m_ManualScalarRange = true;
284 this->m_ScalarRange[ 0 ] = a;
285 this->m_ScalarRange[ 1 ] = b;
286 this->SetWindowLevel( 1, 0.5 );
289 // -------------------------------------------------------------------------
290 void cpExtensions::Visualization::ImageSliceActors::
293 auto image = this->m_Actor->GetInput( );
297 image->GetScalarRange( r );
298 this->SetScalarRange( r[ 0 ], r[ 1 ] );
301 this->m_ManualScalarRange = false;
304 // -------------------------------------------------------------------------
305 void cpExtensions::Visualization::ImageSliceActors::
306 SetWindowLevel( const double& w, const double& l )
308 static const double _0 = double( 0 );
309 static const double _1 = double( 1 );
311 double rw = ( w < _0 )? _0: ( ( w > _1 )? _1: w );
312 double rl = ( l < _0 )? _0: ( ( l > _1 )? _1: l );
314 double d = this->m_ScalarRange[ 1 ] - this->m_ScalarRange[ 0 ];
317 rl += this->m_ScalarRange[ 0 ];
319 if( this->m_Actor.GetPointer( ) != NULL )
321 this->m_Actor->GetProperty( )->SetColorWindow( rw );
322 this->m_Actor->GetProperty( )->SetColorLevel( rl );
328 // -------------------------------------------------------------------------
329 double cpExtensions::Visualization::ImageSliceActors::
332 if( this->m_Actor.GetPointer( ) != NULL )
333 return( this->m_Actor->GetProperty( )->GetColorWindow( ) );
335 return( double( 0 ) );
338 // -------------------------------------------------------------------------
339 double cpExtensions::Visualization::ImageSliceActors::
342 if( this->m_Actor.GetPointer( ) != NULL )
343 return( this->m_Actor->GetProperty( )->GetColorLevel( ) );
345 return( double( 0 ) );
348 // -------------------------------------------------------------------------
349 void cpExtensions::Visualization::ImageSliceActors::
352 auto ren = this->m_Style->GetCurrentRenderer( );
355 auto win = ren->GetRenderWindow( );
361 // -------------------------------------------------------------------------
362 cpExtensions::Visualization::ImageSliceActors::
365 m_ManualScalarRange( false )
370 // -------------------------------------------------------------------------
371 cpExtensions::Visualization::ImageSliceActors::
376 // -------------------------------------------------------------------------
377 void cpExtensions::Visualization::ImageSliceActors::
378 _ConfigureInput( int orientation )
380 // Prepare main image
381 this->m_Mapper->SetOrientation( orientation );
382 this->m_Mapper->Update( );
383 this->m_Actor->GetProperty( )->SetOpacity( 0.8 );
384 this->m_Actor->Modified( );
385 auto st = this->GetStyle( );
387 st->AssociateImageActor( this->m_Actor );
388 this->AddItem( this->m_Actor );
390 // Prepare main cursor
391 this->_ConfigureCursor( );
392 this->AddItem( this->m_Cursor.Actor );
394 // Prepare window/level
395 if( !( this->m_ManualScalarRange ) )
396 this->UnsetScalarRange( );
398 // Add all other actors
399 this->AddItem( this->m_TextActor );
401 // Put it in the first slice
402 auto image = this->m_Mapper->GetInput( );
404 image->GetExtent( ext );
405 this->SetSliceNumber( ext[ orientation << 1 ] );
408 if( this->m_Style.GetPointer( ) != NULL )
409 this->AddItem( this->m_Actor );
411 this->SetSliceNumber( this->GetSliceNumberMinValue( ) );
412 this->ResetCursor( );
416 this->ResetCursor( );
417 this->ResetAxesCursor( );
419 // Update window/level ranges
420 vtkImageData* data = this->GetInputImage( );
424 data->GetScalarRange( r );
425 this->m_WLRange[ 0 ] = double( 0 );
426 this->m_WLRange[ 1 ] = r[ 1 ] - r[ 0 ];
427 this->m_WLRange[ 2 ] = r[ 0 ];
428 this->m_WLRange[ 3 ] = r[ 1 ];
429 this->ResetWindowLevel( );
432 this->m_BlenderBase = vtkSmartPointer< vtkImageData >::New( );
433 this->m_BlenderBase->ShallowCopy( data );
434 this->m_BlenderBase->AllocateScalars( VTK_UNSIGNED_CHAR, 1 );
436 this->m_BlenderBase->GetScalarPointer( ), 0,
437 this->m_BlenderBase->GetActualMemorySize( )
439 this->m_Blender->AddInputData( this->m_BlenderBase );
445 // -------------------------------------------------------------------------
446 void cpExtensions::Visualization::ImageSliceActors::
449 int a = this->m_Mapper->GetOrientation( );
451 this->m_Actor->GetBounds( bounds );
452 bounds[ a << 1 ] += 1e-5;
453 bounds[ ( a << 1 ) + 1 ] += 1e-5;
455 this->m_Cursor.Source->SetModelBounds( bounds );
456 this->m_Cursor.Source->AllOn( );
457 this->m_Cursor.Actor->GetProperty( )->SetOpacity( 1 );
458 this->m_Cursor.Actor->GetProperty( )->SetLineWidth( 3 );
459 this->m_Cursor.Modified( );
462 // -------------------------------------------------------------------------
463 void cpExtensions::Visualization::ImageSliceActors::
466 const TStyle::ButtonID& btn,
467 int* idx, double* pos,
468 bool alt, bool ctr, bool sft
471 ImageSliceActors* self = reinterpret_cast< ImageSliceActors* >( data );
475 if( btn == TStyle::ButtonID_None )
477 self->ShowPixelText( pos );
478 self->m_Cursor.Source->SetFocalPoint( pos );
479 self->m_Cursor.Source->Modified( );
480 self->m_Cursor.Modified( );
483 else if( btn == TStyle::ButtonID_Right )
485 if( !alt && !ctr && sft )
487 int a0 = self->m_Mapper->GetOrientation( );
488 int a1 = ( a0 + 1 ) % 3;
489 int a2 = ( a0 + 2 ) % 3;
490 double dx = pos[ a1 ] - self->m_StartMouseEvent[ a1 ];
491 double dy = pos[ a2 ] - self->m_StartMouseEvent[ a2 ];
493 self->m_Actor->GetBounds( bounds );
494 dx /= bounds[ ( a1 << 1 ) + 1 ] - bounds[ a1 << 1 ];
495 dy /= bounds[ ( a2 << 1 ) + 1 ] - bounds[ a2 << 1 ];
496 double w = self->m_StartWindow + dx;
497 double l = self->m_StartLevel + dy;
499 self->SetWindowLevel( w, l );
502 auto aIt = self->m_AssociatedSlices.begin( );
503 aIt != self->m_AssociatedSlices.end( );
507 ( *aIt )->SetWindowLevel( w, l );
517 // -------------------------------------------------------------------------
518 void cpExtensions::Visualization::ImageSliceActors::
521 const TStyle::ButtonID& btn,
522 int* idx, double* pos,
523 bool alt, bool ctr, bool sft
526 ImageSliceActors* self = reinterpret_cast< ImageSliceActors* >( data );
530 self->m_StartMouseEvent[ 0 ] = pos[ 0 ];
531 self->m_StartMouseEvent[ 1 ] = pos[ 1 ];
532 self->m_StartMouseEvent[ 2 ] = pos[ 2 ];
534 if( btn == TStyle::ButtonID_Right )
536 if( !alt && !ctr && sft )
539 self->GetScalarRange( r );
540 double d = r[ 1 ] - r[ 0 ];
541 self->m_StartWindow = self->GetWindow( ) / d;
542 self->m_StartLevel = ( self->GetLevel( ) - r[ 0 ] ) / d;
549 // -------------------------------------------------------------------------
550 void cpExtensions::Visualization::ImageSliceActors::
553 const int& dir, bool alt, bool ctr, bool sft
556 ImageSliceActors* self = reinterpret_cast< ImageSliceActors* >( data );
559 auto ren = self->m_Style->GetCurrentRenderer( );
562 auto cam = ren->GetActiveCamera( );
565 auto win = ren->GetRenderWindow( );
569 // Get previous values
570 int a = self->m_Mapper->GetOrientation( );
572 self->m_Actor->GetBounds( bounds );
573 double prev_pos = bounds[ a << 1 ];
576 long slice = self->GetSliceNumber( ) + dir * ( ( sft )? 10: 1 );
577 self->SetSliceNumber( slice );
578 self->m_Actor->GetBounds( bounds );
582 cam->GetPosition( cam_pos );
583 cam_pos[ a ] += bounds[ a << 1 ] - prev_pos;
584 cam->SetPosition( cam_pos );
587 self->ShowPixelText( self->m_Cursor.Source->GetFocalPoint( ) );
592 auto aIt = self->m_AssociatedSlices.begin( );
593 aIt != self->m_AssociatedSlices.end( );
597 if( ( *aIt )->m_Mapper->GetOrientation( ) == a )
599 ( *aIt )->SetSliceNumber( slice );
607 // -------------------------------------------------------------------------
608 void cpExtensions::Visualization::ImageSliceActors::
616 // -------------------------------------------------------------------------
617 void cpExtensions::Visualization::ImageSliceActors::
618 _EnterCommand( void* data )
622 // -------------------------------------------------------------------------
623 void cpExtensions::Visualization::ImageSliceActors::
624 _LeaveCommand( void* data )