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 void cpExtensions::Visualization::ImageSliceActors::
87 SetInputActor( vtkProp* actor, int orientation )
89 auto real_actor = dynamic_cast< vtkImageActor* >( actor );
90 if( real_actor == NULL )
93 dynamic_cast< vtkImageSliceMapper* >( real_actor->GetMapper( ) );
94 if( real_mapper == NULL )
96 this->m_Mapper = real_mapper;
97 this->_ConfigureInput( orientation );
100 // -------------------------------------------------------------------------
101 vtkImageData* cpExtensions::Visualization::ImageSliceActors::
104 if( this->m_Mapper.GetPointer( ) != NULL )
105 return( this->m_Mapper->GetInput( ) );
110 // -------------------------------------------------------------------------
111 vtkImageActor* cpExtensions::Visualization::ImageSliceActors::
114 return( this->m_Actor.GetPointer( ) );
117 // -------------------------------------------------------------------------
118 const vtkImageActor* cpExtensions::Visualization::ImageSliceActors::
119 GetImageActor( ) const
121 return( this->m_Actor.GetPointer( ) );
124 // -------------------------------------------------------------------------
125 void cpExtensions::Visualization::ImageSliceActors::
126 AddMesh( vtkPolyData* mesh )
128 SourceActor< vtkCutter > a;
130 a.Source->SetInputData( mesh );
131 a.Source->SetCutFunction( this->m_Mapper->GetSlicePlane( ) );
132 a.Source->SetValue( 0, 0 );
133 a.Source->GenerateTrianglesOff( );
136 this->m_Meshes[ mesh ] = a;
137 this->AddItem( a.Actor );
139 auto ren = this->m_Style->GetCurrentRenderer( );
141 if( ren->HasViewProp( this->m_Actor ) )
142 ren->AddViewProp( a.Actor );
145 // -------------------------------------------------------------------------
146 void cpExtensions::Visualization::ImageSliceActors::
147 AssociateSlice( Self* slice )
149 this->m_AssociatedSlices.push_back( slice );
153 // -------------------------------------------------------------------------
154 void cpExtensions::Visualization::ImageSliceActors::
155 CleanAssociatedSlices( )
157 this->m_AssociatedSlices.clear( );
161 // -------------------------------------------------------------------------
162 cpExtensions::Interaction::ImageInteractorStyle*
163 cpExtensions::Visualization::ImageSliceActors::
166 return( dynamic_cast< TStyle* >( this->m_Style.GetPointer( ) ) );
169 // -------------------------------------------------------------------------
170 void cpExtensions::Visualization::ImageSliceActors::
171 SetStyle( vtkInteractorStyle* st )
177 // -------------------------------------------------------------------------
178 void cpExtensions::Visualization::ImageSliceActors::
179 PushInto( vtkRenderer* ren )
181 this->InitTraversal( );
183 while( ( prop = this->GetNextProp( ) ) != NULL )
184 ren->AddViewProp( prop );
187 // -------------------------------------------------------------------------
188 void cpExtensions::Visualization::ImageSliceActors::
189 PopFrom( vtkRenderer* ren )
191 this->InitTraversal( );
193 while( ( prop = this->GetNextProp( ) ) != NULL )
194 ren->RemoveViewProp( prop );
197 // -------------------------------------------------------------------------
198 long cpExtensions::Visualization::ImageSliceActors::
199 GetSliceNumber( ) const
201 if( this->m_Mapper.GetPointer( ) != NULL )
202 return( this->m_Mapper->GetSliceNumber( ) );
207 // -------------------------------------------------------------------------
208 void cpExtensions::Visualization::ImageSliceActors::
209 SetSliceNumber( long slice )
211 if( this->m_Mapper.GetPointer( ) == NULL )
215 int a = this->m_Mapper->GetOrientation( );
219 this->m_Mapper->GetInput( )->GetExtent( ext );
221 rs = ( rs > ext[ a << 1 ] )? rs: ext[ a << 1 ];
222 rs = ( rs < ext[ ( a << 1 ) + 1 ] )? rs: ext[ ( a << 1 ) + 1 ];
225 this->m_Mapper->SetSliceNumber( rs );
227 // Update display extent (this isn't done automatically)
228 ext[ a << 1 ] = ext[ ( a << 1 ) + 1 ] = rs;
229 this->m_Actor->SetDisplayExtent( ext );
231 this->m_Mapper->Modified( );
232 this->m_Actor->Modified( );
233 this->_ConfigureCursor( );
237 // -------------------------------------------------------------------------
238 void cpExtensions::Visualization::ImageSliceActors::
239 ShowPixelText( double* pos )
241 if( this->m_Mapper.GetPointer( ) != NULL )
244 int axId = this->m_Mapper->GetOrientation( );
245 if ( axId == 0 ) axis = 'X';
246 else if( axId == 1 ) axis = 'Y';
247 else if( axId == 2 ) axis = 'Z';
248 long slice = this->GetSliceNumber( );
250 vtkImageData* image = this->m_Actor->GetInput( );
253 image->ComputeStructuredCoordinates( pos, ijk, pcoords );
257 image->GetExtent( ext );
259 ext[ 0 ] <= ijk[ 0 ] && ijk[ 0 ] <= ext[ 1 ] &&
260 ext[ 2 ] <= ijk[ 1 ] && ijk[ 1 ] <= ext[ 3 ] &&
261 ext[ 4 ] <= ijk[ 2 ] && ijk[ 2 ] <= ext[ 5 ]
264 int nScl = image->GetNumberOfScalarComponents( );
265 std::stringstream str;
269 << "," << ijk[ 2 ] << "]=(";
271 image->GetScalarComponentAsFloat( ijk[ 0 ], ijk[ 1 ], ijk[ 2 ], 0 );
272 for( int n = 1; n < nScl; ++n )
275 << image->GetScalarComponentAsFloat(
276 ijk[ 0 ], ijk[ 1 ], ijk[ 2 ], n
282 this->m_TextBuffer, MAX_TEXT_BUFFER, "Axis: %c (%d)\nPixel %s",
283 axis, slice, str.str( ).c_str( )
285 #else // defined(WIN32)
287 this->m_TextBuffer, "Axis: %c (%ld)\nPixel %s",
288 axis, slice, str.str( ).c_str( )
290 #endif // defined(WIN32)
294 this->m_TextBuffer[ 0 ] = '\0';
295 this->m_TextActor->SetInput( this->m_TextBuffer );
296 this->m_TextActor->Modified( );
300 // -------------------------------------------------------------------------
301 void cpExtensions::Visualization::ImageSliceActors::
302 GetScalarRange( double r[ 2 ] ) const
304 r[ 0 ] = this->m_ScalarRange[ 0 ];
305 r[ 1 ] = this->m_ScalarRange[ 1 ];
308 // -------------------------------------------------------------------------
309 void cpExtensions::Visualization::ImageSliceActors::
310 SetScalarRange( const double& a, const double& b )
312 this->m_ManualScalarRange = true;
313 this->m_ScalarRange[ 0 ] = a;
314 this->m_ScalarRange[ 1 ] = b;
315 this->SetWindowLevel( 1, 0.5 );
318 // -------------------------------------------------------------------------
319 void cpExtensions::Visualization::ImageSliceActors::
322 auto image = this->m_Actor->GetInput( );
326 image->GetScalarRange( r );
327 this->SetScalarRange( r[ 0 ], r[ 1 ] );
330 this->m_ManualScalarRange = false;
333 // -------------------------------------------------------------------------
334 void cpExtensions::Visualization::ImageSliceActors::
335 SetWindowLevel( const double& w, const double& l )
337 static const double _0 = double( 0 );
338 static const double _1 = double( 1 );
340 double rw = ( w < _0 )? _0: ( ( w > _1 )? _1: w );
341 double rl = ( l < _0 )? _0: ( ( l > _1 )? _1: l );
343 double d = this->m_ScalarRange[ 1 ] - this->m_ScalarRange[ 0 ];
346 rl += this->m_ScalarRange[ 0 ];
348 if( this->m_Actor.GetPointer( ) != NULL )
350 this->m_Actor->GetProperty( )->SetColorWindow( rw );
351 this->m_Actor->GetProperty( )->SetColorLevel( rl );
357 // -------------------------------------------------------------------------
358 double cpExtensions::Visualization::ImageSliceActors::
361 if( this->m_Actor.GetPointer( ) != NULL )
362 return( this->m_Actor->GetProperty( )->GetColorWindow( ) );
364 return( double( 0 ) );
367 // -------------------------------------------------------------------------
368 double cpExtensions::Visualization::ImageSliceActors::
371 if( this->m_Actor.GetPointer( ) != NULL )
372 return( this->m_Actor->GetProperty( )->GetColorLevel( ) );
374 return( double( 0 ) );
377 // -------------------------------------------------------------------------
378 void cpExtensions::Visualization::ImageSliceActors::
381 auto ren = this->m_Style->GetCurrentRenderer( );
384 auto win = ren->GetRenderWindow( );
390 // -------------------------------------------------------------------------
391 cpExtensions::Visualization::ImageSliceActors::
394 m_ManualScalarRange( false )
399 // -------------------------------------------------------------------------
400 cpExtensions::Visualization::ImageSliceActors::
405 // -------------------------------------------------------------------------
406 void cpExtensions::Visualization::ImageSliceActors::
407 _ConfigureInput( int orientation )
409 // Prepare main image
410 this->m_Mapper->SetOrientation( orientation );
411 this->m_Mapper->Update( );
412 this->m_Actor->GetProperty( )->SetOpacity( 0.8 );
413 this->m_Actor->Modified( );
414 auto st = this->GetStyle( );
416 st->AssociateImageActor( this->m_Actor );
417 this->AddItem( this->m_Actor );
419 // Prepare main cursor
420 this->_ConfigureCursor( );
421 this->AddItem( this->m_Cursor.Actor );
423 // Prepare window/level
424 if( !( this->m_ManualScalarRange ) )
425 this->UnsetScalarRange( );
427 // Add all other actors
428 this->AddItem( this->m_TextActor );
430 // Put it in the first slice
431 auto image = this->m_Mapper->GetInput( );
433 image->GetExtent( ext );
434 this->SetSliceNumber( ext[ orientation << 1 ] );
437 if( this->m_Style.GetPointer( ) != NULL )
438 this->AddItem( this->m_Actor );
440 this->SetSliceNumber( this->GetSliceNumberMinValue( ) );
441 this->ResetCursor( );
445 this->ResetCursor( );
446 this->ResetAxesCursor( );
448 // Update window/level ranges
449 vtkImageData* data = this->GetInputImage( );
453 data->GetScalarRange( r );
454 this->m_WLRange[ 0 ] = double( 0 );
455 this->m_WLRange[ 1 ] = r[ 1 ] - r[ 0 ];
456 this->m_WLRange[ 2 ] = r[ 0 ];
457 this->m_WLRange[ 3 ] = r[ 1 ];
458 this->ResetWindowLevel( );
461 this->m_BlenderBase = vtkSmartPointer< vtkImageData >::New( );
462 this->m_BlenderBase->ShallowCopy( data );
463 this->m_BlenderBase->AllocateScalars( VTK_UNSIGNED_CHAR, 1 );
465 this->m_BlenderBase->GetScalarPointer( ), 0,
466 this->m_BlenderBase->GetActualMemorySize( )
468 this->m_Blender->AddInputData( this->m_BlenderBase );
474 // -------------------------------------------------------------------------
475 void cpExtensions::Visualization::ImageSliceActors::
478 int a = this->m_Mapper->GetOrientation( );
480 this->m_Actor->GetBounds( bounds );
481 bounds[ a << 1 ] += 1e-5;
482 bounds[ ( a << 1 ) + 1 ] += 1e-5;
484 this->m_Cursor.Source->SetModelBounds( bounds );
485 this->m_Cursor.Source->AllOn( );
486 this->m_Cursor.Actor->GetProperty( )->SetOpacity( 1 );
487 this->m_Cursor.Actor->GetProperty( )->SetLineWidth( 3 );
488 this->m_Cursor.Modified( );
491 // -------------------------------------------------------------------------
492 void cpExtensions::Visualization::ImageSliceActors::
495 const TStyle::ButtonID& btn,
496 int* idx, double* pos,
497 bool alt, bool ctr, bool sft
500 ImageSliceActors* self = reinterpret_cast< ImageSliceActors* >( data );
504 if( btn == TStyle::ButtonID_None )
506 self->ShowPixelText( pos );
507 self->m_Cursor.Source->SetFocalPoint( pos );
508 self->m_Cursor.Source->Modified( );
509 self->m_Cursor.Modified( );
512 else if( btn == TStyle::ButtonID_Right )
514 if( !alt && !ctr && sft )
516 int a0 = self->m_Mapper->GetOrientation( );
517 int a1 = ( a0 + 1 ) % 3;
518 int a2 = ( a0 + 2 ) % 3;
519 double dx = pos[ a1 ] - self->m_StartMouseEvent[ a1 ];
520 double dy = pos[ a2 ] - self->m_StartMouseEvent[ a2 ];
522 self->m_Actor->GetBounds( bounds );
523 dx /= bounds[ ( a1 << 1 ) + 1 ] - bounds[ a1 << 1 ];
524 dy /= bounds[ ( a2 << 1 ) + 1 ] - bounds[ a2 << 1 ];
525 double w = self->m_StartWindow + dx;
526 double l = self->m_StartLevel + dy;
528 self->SetWindowLevel( w, l );
531 auto aIt = self->m_AssociatedSlices.begin( );
532 aIt != self->m_AssociatedSlices.end( );
536 ( *aIt )->SetWindowLevel( w, l );
546 // -------------------------------------------------------------------------
547 void cpExtensions::Visualization::ImageSliceActors::
550 const TStyle::ButtonID& btn,
551 int* idx, double* pos,
552 bool alt, bool ctr, bool sft
555 ImageSliceActors* self = reinterpret_cast< ImageSliceActors* >( data );
559 self->m_StartMouseEvent[ 0 ] = pos[ 0 ];
560 self->m_StartMouseEvent[ 1 ] = pos[ 1 ];
561 self->m_StartMouseEvent[ 2 ] = pos[ 2 ];
563 if( btn == TStyle::ButtonID_Right )
565 if( !alt && !ctr && sft )
568 self->GetScalarRange( r );
569 double d = r[ 1 ] - r[ 0 ];
570 self->m_StartWindow = self->GetWindow( ) / d;
571 self->m_StartLevel = ( self->GetLevel( ) - r[ 0 ] ) / d;
578 // -------------------------------------------------------------------------
579 void cpExtensions::Visualization::ImageSliceActors::
582 const int& dir, bool alt, bool ctr, bool sft
585 ImageSliceActors* self = reinterpret_cast< ImageSliceActors* >( data );
588 auto ren = self->m_Style->GetCurrentRenderer( );
591 auto cam = ren->GetActiveCamera( );
594 auto win = ren->GetRenderWindow( );
598 // Get previous values
599 int a = self->m_Mapper->GetOrientation( );
601 self->m_Actor->GetBounds( bounds );
602 double prev_pos = bounds[ a << 1 ];
605 long slice = self->GetSliceNumber( ) + dir * ( ( sft )? 10: 1 );
606 self->SetSliceNumber( slice );
607 self->m_Actor->GetBounds( bounds );
611 cam->GetPosition( cam_pos );
612 cam_pos[ a ] += bounds[ a << 1 ] - prev_pos;
613 cam->SetPosition( cam_pos );
616 self->ShowPixelText( self->m_Cursor.Source->GetFocalPoint( ) );
621 auto aIt = self->m_AssociatedSlices.begin( );
622 aIt != self->m_AssociatedSlices.end( );
626 if( ( *aIt )->m_Mapper->GetOrientation( ) == a )
628 ( *aIt )->SetSliceNumber( slice );
636 // -------------------------------------------------------------------------
637 void cpExtensions::Visualization::ImageSliceActors::
645 // -------------------------------------------------------------------------
646 void cpExtensions::Visualization::ImageSliceActors::
647 _EnterCommand( void* data )
651 // -------------------------------------------------------------------------
652 void cpExtensions::Visualization::ImageSliceActors::
653 _LeaveCommand( void* data )