1 #include <cpExtensions/Visualization/ImageSliceActors.h>
5 #include <vtkAlgorithmOutput.h>
6 #include <vtkCellArray.h>
7 #include <vtkImageData.h>
8 #include <vtkInformation.h>
10 #include <vtkPoints.h>
11 #include <vtkProperty.h>
12 #include <vtkRenderer.h>
13 #include <vtkStreamingDemandDrivenPipeline.h>
14 #include <vtkTextProperty.h>
16 // -------------------------------------------------------------------------
17 cpExtensions::Visualization::ImageSliceActors*
18 cpExtensions::Visualization::ImageSliceActors::
21 return( new Self( ) );
24 // -------------------------------------------------------------------------
25 void cpExtensions::Visualization::ImageSliceActors::
26 AddInputConnection( vtkAlgorithmOutput* aout, int axis )
28 vtkSmartPointer< vtkImageSliceMapper > mapper =
29 vtkSmartPointer< vtkImageSliceMapper >::New( );
30 this->SliceMappers.push_back( mapper );
31 mapper->SetInputConnection( aout );
32 this->_ConfigureNewInput( axis );
35 // -------------------------------------------------------------------------
36 void cpExtensions::Visualization::ImageSliceActors::
37 AddInputData( vtkImageData* data, int axis )
39 vtkSmartPointer< vtkImageSliceMapper > mapper =
40 vtkSmartPointer< vtkImageSliceMapper >::New( );
41 this->SliceMappers.push_back( mapper );
42 mapper->SetInputData( data );
43 this->_ConfigureNewInput( axis );
46 // -------------------------------------------------------------------------
47 void cpExtensions::Visualization::ImageSliceActors::
50 // Unbind from container
51 this->RemoveAllItems( );
54 this->SliceMappers.clear( );
55 this->ImageActors.clear( );
56 this->AssociatedActors.clear( );
58 // Reconfigure unique objects
59 this->PlaneFunction = vtkSmartPointer< vtkPlane >::New( );
60 this->PlaneSource = vtkSmartPointer< vtkPolyData >::New( );
61 this->PlaneMapper = vtkSmartPointer< vtkPolyDataMapper >::New( );
62 this->TextActor = vtkSmartPointer< vtkTextActor >::New( );
63 this->PlaneActor = vtkSmartPointer< vtkActor >::New( );
64 this->TextBuffer[ 0 ] = '\0';
66 // Unique objects configuration
67 vtkSmartPointer< vtkPoints > plane_points =
68 vtkSmartPointer< vtkPoints >::New( );
69 vtkSmartPointer< vtkCellArray > plane_lines =
70 vtkSmartPointer< vtkCellArray >::New( );
72 plane_points->InsertNextPoint( 0, 0, 0 );
73 plane_points->InsertNextPoint( 0, 1, 0 );
74 plane_points->InsertNextPoint( 1, 1, 0 );
75 plane_points->InsertNextPoint( 1, 0, 0 );
76 plane_lines->InsertNextCell( 5 );
77 plane_lines->InsertCellPoint( 0 );
78 plane_lines->InsertCellPoint( 1 );
79 plane_lines->InsertCellPoint( 2 );
80 plane_lines->InsertCellPoint( 3 );
81 plane_lines->InsertCellPoint( 0 );
82 this->PlaneSource->SetPoints( plane_points );
83 this->PlaneSource->SetLines( plane_lines );
85 this->PlaneMapper->SetInputData( this->PlaneSource );
86 this->PlaneActor->SetMapper( this->PlaneMapper );
88 this->TextActor->SetTextScaleModeToNone( );
89 vtkTextProperty* textprop = this->TextActor->GetTextProperty( );
90 textprop->SetColor( 1, 1, 1 );
91 textprop->SetFontFamilyToCourier( );
92 textprop->SetFontSize( 18 );
94 textprop->ItalicOff( );
95 textprop->ShadowOff( );
96 textprop->SetJustificationToLeft( );
97 textprop->SetVerticalJustificationToBottom( );
98 vtkCoordinate* coord = this->TextActor->GetPositionCoordinate( );
99 coord->SetCoordinateSystemToNormalizedViewport( );
100 coord->SetValue( 0.01, 0.01 );
103 // -------------------------------------------------------------------------
104 vtkInteractorStyle* cpExtensions::Visualization::ImageSliceActors::
107 return( this->Style.GetPointer( ) );
110 // -------------------------------------------------------------------------
111 const vtkInteractorStyle* cpExtensions::Visualization::ImageSliceActors::
114 return( this->Style.GetPointer( ) );
117 // -------------------------------------------------------------------------
118 void cpExtensions::Visualization::ImageSliceActors::
119 PushActorsInto( vtkRenderer* renderer )
121 unsigned int N = this->GetNumberOfImageActors( );
122 for( unsigned int n = 0; n < N; ++n )
123 renderer->AddActor( this->GetImageActor( n ) );
124 renderer->AddActor( this->GetTextActor( ) );
125 renderer->AddActor( this->GetPlaneActor( ) );
126 renderer->Modified( );
129 // -------------------------------------------------------------------------
130 void cpExtensions::Visualization::ImageSliceActors::
131 PopActorsFrom( vtkRenderer* renderer )
133 unsigned int N = this->GetNumberOfImageActors( );
134 for( unsigned int n = 0; n < N; ++n )
135 renderer->RemoveActor( this->GetImageActor( n ) );
136 renderer->RemoveActor( this->GetTextActor( ) );
137 renderer->RemoveActor( this->GetPlaneActor( ) );
138 renderer->Modified( );
141 // -------------------------------------------------------------------------
142 unsigned int cpExtensions::Visualization::ImageSliceActors::
143 GetNumberOfImageActors( ) const
145 return( this->ImageActors.size( ) );
148 // -------------------------------------------------------------------------
149 vtkImageActor* cpExtensions::Visualization::ImageSliceActors::
150 GetImageActor( unsigned int id )
152 if( id < this->ImageActors.size( ) )
153 return( this->ImageActors[ id ] );
158 // -------------------------------------------------------------------------
159 const vtkImageActor* cpExtensions::Visualization::ImageSliceActors::
160 GetImageActor( unsigned int id ) const
162 if( id < this->ImageActors.size( ) )
163 return( this->ImageActors[ id ] );
168 // -------------------------------------------------------------------------
169 vtkTextActor* cpExtensions::Visualization::ImageSliceActors::
172 return( this->TextActor );
175 // -------------------------------------------------------------------------
176 const vtkTextActor* cpExtensions::Visualization::ImageSliceActors::
177 GetTextActor( ) const
179 return( this->TextActor );
182 // -------------------------------------------------------------------------
183 vtkActor* cpExtensions::Visualization::ImageSliceActors::
186 return( this->PlaneActor );
189 // -------------------------------------------------------------------------
190 const vtkActor* cpExtensions::Visualization::ImageSliceActors::
191 GetPlaneActor( ) const
193 return( this->PlaneActor );
196 // -------------------------------------------------------------------------
197 vtkPlane* cpExtensions::Visualization::ImageSliceActors::
200 return( this->PlaneFunction );
203 // -------------------------------------------------------------------------
204 const vtkPlane* cpExtensions::Visualization::ImageSliceActors::
205 GetPlaneFunction( ) const
207 return( this->PlaneFunction );
210 // -------------------------------------------------------------------------
211 void cpExtensions::Visualization::ImageSliceActors::
212 AddActor( vtkAlgorithm* algorithm, vtkActor* actor )
214 this->AssociatedActors.push_back( TAssociatedActor( algorithm, actor ) );
215 this->AddItem( actor );
218 // -------------------------------------------------------------------------
219 void cpExtensions::Visualization::ImageSliceActors::
220 AddActor( vtkActor* actor )
222 this->AddActor( NULL, actor );
225 // -------------------------------------------------------------------------
226 void cpExtensions::Visualization::ImageSliceActors::
227 SetInterpolate( bool v )
229 if( this->Interpolate != v )
231 for( unsigned int i = 0; i < this->ImageActors.size( ); ++i )
232 this->ImageActors[ i ]->SetInterpolate( v );
233 this->Interpolate = v;
239 // -------------------------------------------------------------------------
240 void cpExtensions::Visualization::ImageSliceActors::
243 this->SetInterpolate( true );
246 // -------------------------------------------------------------------------
247 void cpExtensions::Visualization::ImageSliceActors::
250 this->SetInterpolate( false );
253 // -------------------------------------------------------------------------
254 double* cpExtensions::Visualization::ImageSliceActors::
255 GetDisplayBounds( ) const
257 if( this->ImageActors.size( ) > 0 )
258 return( this->ImageActors[ 0 ]->GetDisplayBounds( ) );
263 // -------------------------------------------------------------------------
264 void cpExtensions::Visualization::ImageSliceActors::
265 GetDisplayBounds( double bounds[ 6 ] ) const
267 if( this->ImageActors.size( ) == 0 )
269 bounds[ 0 ] = bounds[ 2 ] = bounds[ 4 ] = double( -1 );
270 bounds[ 1 ] = bounds[ 3 ] = bounds[ 5 ] = double( -1 );
273 this->ImageActors[ 0 ]->GetDisplayBounds( bounds );
276 // -------------------------------------------------------------------------
277 int cpExtensions::Visualization::ImageSliceActors::
280 if( this->SliceMappers.size( ) > 0 )
281 return( this->SliceMappers[ 0 ]->GetOrientation( ) );
286 // -------------------------------------------------------------------------
287 int cpExtensions::Visualization::ImageSliceActors::
288 GetSliceNumber( ) const
290 if( this->SliceMappers.size( ) > 0 )
291 return( this->SliceMappers[ 0 ]->GetSliceNumber( ) );
296 // -------------------------------------------------------------------------
297 int cpExtensions::Visualization::ImageSliceActors::
298 GetSliceNumberMinValue( ) const
300 if( this->SliceMappers.size( ) > 0 )
301 return( this->SliceMappers[ 0 ]->GetSliceNumberMinValue( ) );
306 // -------------------------------------------------------------------------
307 int cpExtensions::Visualization::ImageSliceActors::
308 GetSliceNumberMaxValue( ) const
310 if( this->SliceMappers.size( ) > 0 )
311 return( this->SliceMappers[ 0 ]->GetSliceNumberMaxValue( ) );
316 // -------------------------------------------------------------------------
317 void cpExtensions::Visualization::ImageSliceActors::
318 SetSliceNumber( const int& slice )
320 unsigned int nImages = this->SliceMappers.size( );
324 // Change visualization extent
325 for( unsigned int i = 0; i < nImages; ++i )
327 this->SliceMappers[ i ]->SetSliceNumber( slice );
328 this->SliceMappers[ i ]->Modified( );
329 this->ImageActors[ i ]->Modified( );
330 this->SliceMappers[ i ]->Update( );
335 vtkAlgorithm* algo = this->SliceMappers[ 0 ]->GetInputAlgorithm( );
336 vtkInformation* info = algo->GetOutputInformation( 0 );
338 double ori[ 3 ], spac[ 3 ], pos[ 3 ];
339 info->Get( vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT( ), ext );
340 info->Get( vtkDataObject::ORIGIN( ), ori );
341 info->Get( vtkDataObject::SPACING( ), spac );
342 this->SliceMappers[ 0 ]->GetSlicePlane( )->GetOrigin( pos );
344 // Prevent obscuring voxels by offsetting the plane geometry
347 ori[ 0 ] + ( spac[ 0 ] * double( ext[ 0 ] ) ),
348 ori[ 0 ] + ( spac[ 0 ] * double( ext[ 1 ] ) )
352 ori[ 1 ] + ( spac[ 1 ] * double( ext[ 2 ] ) ),
353 ori[ 1 ] + ( spac[ 1 ] * double( ext[ 3 ] ) )
357 ori[ 2 ] + ( spac[ 2 ] * double( ext[ 4 ] ) ),
358 ori[ 2 ] + ( spac[ 2 ] * double( ext[ 5 ] ) )
361 if( spac[ 0 ] < double( 0 ) )
363 double t = xbnds[ 0 ];
364 xbnds[ 0 ] = xbnds[ 1 ];
368 if( spac[ 1 ] < double( 0 ) )
370 double t = ybnds[ 0 ];
371 ybnds[ 0 ] = ybnds[ 1 ];
375 if( spac[ 2 ] < double( 0 ) )
377 double t = zbnds[ 0 ];
378 zbnds[ 0 ] = zbnds[ 1 ];
383 // Plane function origin
384 this->PlaneFunction->SetOrigin( pos );
386 // Configure visualization and implicit plane orientation
387 int axis = this->SliceMappers[ 0 ]->GetOrientation( );
388 this->PlaneActor->GetProperty( )->SetRepresentationToWireframe( );
389 this->PlaneActor->GetProperty( )->SetLineWidth( 2 );
390 vtkPoints* plane_points = this->PlaneSource->GetPoints( );
391 if( axis == 0 ) // YZ, x-normal
393 this->PlaneFunction->SetNormal( 1, 0, 0 );
394 plane_points->SetPoint( 0, pos[ 0 ], ybnds[ 0 ], zbnds[ 0 ] );
395 plane_points->SetPoint( 1, pos[ 0 ], ybnds[ 1 ], zbnds[ 0 ] );
396 plane_points->SetPoint( 2, pos[ 0 ], ybnds[ 1 ], zbnds[ 1 ] );
397 plane_points->SetPoint( 3, pos[ 0 ], ybnds[ 0 ], zbnds[ 1 ] );
398 this->PlaneActor->GetProperty( )->SetColor( 1, 0, 0 );
400 else if( axis == 1 ) // ZX, y-normal
402 this->PlaneFunction->SetNormal( 0, 1, 0 );
403 plane_points->SetPoint( 0, xbnds[ 0 ], pos[ 1 ], zbnds[ 0 ] );
404 plane_points->SetPoint( 1, xbnds[ 0 ], pos[ 1 ], zbnds[ 1 ] );
405 plane_points->SetPoint( 2, xbnds[ 1 ], pos[ 1 ], zbnds[ 1 ] );
406 plane_points->SetPoint( 3, xbnds[ 1 ], pos[ 1 ], zbnds[ 0 ] );
407 this->PlaneActor->GetProperty( )->SetColor( 0, 1, 0 );
411 this->PlaneFunction->SetNormal( 0, 0, 1 );
412 plane_points->SetPoint( 0, xbnds[ 0 ], ybnds[ 0 ], pos[ 2 ] );
413 plane_points->SetPoint( 1, xbnds[ 1 ], ybnds[ 0 ], pos[ 2 ] );
414 plane_points->SetPoint( 2, xbnds[ 1 ], ybnds[ 1 ], pos[ 2 ] );
415 plane_points->SetPoint( 3, xbnds[ 0 ], ybnds[ 1 ], pos[ 2 ] );
416 this->PlaneActor->GetProperty( )->SetColor( 0, 0, 1 );
419 this->PlaneFunction->Modified( );
420 this->PlaneSource->Modified( );
421 this->PlaneMapper->Modified( );
422 this->PlaneActor->Modified( );
424 // Prepare other actors to update
426 for( unsigned int i = 0; i < this->OtherActors.size( ); ++i )
428 if( this->OtherActors[ i ].first.GetPointer( ) != NULL )
430 this->OtherActors[ i ].first->Modified( );
431 this->OtherActors[ i ].first->Update( );
435 if( this->OtherActors[ i ].second.GetPointer( ) != NULL )
437 this->OtherActors[ i ].second->GetMapper( )->Modified( );
438 this->OtherActors[ i ].second->Modified( );
444 if( this->m_UpdateCommand != NULL )
445 this->m_UpdateCommand( this->m_UpdateData );
452 // -------------------------------------------------------------------------
453 void cpExtensions::Visualization::ImageSliceActors::
456 if( this->SliceMappers.size( ) > 0 )
459 int axId = this->SliceMappers[ 0 ]->GetOrientation( );
460 if ( axId == 0 ) axis = 'X';
461 else if( axId == 1 ) axis = 'Y';
462 else if( axId == 2 ) axis = 'Z';
465 this->TextBuffer, "Axis: %c (%d)",
466 axis, this->SliceMappers[ 0 ]->GetSliceNumber( )
470 this->TextBuffer[ 0 ] = '\0';
471 this->TextActor->SetInput( this->TextBuffer );
472 this->TextActor->Modified( );
476 // -------------------------------------------------------------------------
477 void cpExtensions::Visualization::ImageSliceActors::
478 UpdateText( double pos[ 3 ] )
480 if( this->SliceMappers.size( ) > 0 )
483 int axId = this->SliceMappers[ 0 ]->GetOrientation( );
484 if ( axId == 0 ) axis = 'X';
485 else if( axId == 1 ) axis = 'Y';
486 else if( axId == 2 ) axis = 'Z';
488 vtkImageData* image = this->SliceMappers[ 0 ]->GetInput( );
492 image->ComputeStructuredCoordinates( pos, ijk, pcoords );
494 int nScl = image->GetNumberOfScalarComponents( );
495 std::stringstream str;
499 << "," << ijk[ 2 ] << "]=(";
501 image->GetScalarComponentAsFloat(
502 ijk[ 0 ], ijk[ 1 ], ijk[ 2 ], 0
504 for( int n = 1; n < nScl; ++n )
507 << image->GetScalarComponentAsFloat(
508 ijk[ 0 ], ijk[ 1 ], ijk[ 2 ], n
512 this->TextBuffer, "Axis: %c (%d) | Pixel %s",
514 this->SliceMappers[ 0 ]->GetSliceNumber( ),
521 this->TextBuffer[ 0 ] = '\0';
522 this->TextActor->SetInput( this->TextBuffer );
523 this->TextActor->Modified( );
527 // -------------------------------------------------------------------------
528 void cpExtensions::Visualization::ImageSliceActors::
529 UpdateText( const double& w, const double& l )
531 if( this->SliceMappers.size( ) > 0 )
534 int axId = this->SliceMappers[ 0 ]->GetOrientation( );
535 if ( axId == 0 ) axis = 'X';
536 else if( axId == 1 ) axis = 'Y';
537 else if( axId == 2 ) axis = 'Z';
540 this->TextBuffer, "Axis: %c (%d) | W/L (%.2f/%.2f)",
541 axis, this->SliceMappers[ 0 ]->GetSliceNumber( ), w, l
545 this->TextBuffer[ 0 ] = '\0';
546 this->TextActor->SetInput( this->TextBuffer );
547 this->TextActor->Modified( );
551 // -------------------------------------------------------------------------
552 cpExtensions::Visualization::ImageSliceActors::
557 // Connect this view with a controller
558 this->Style = vtkSmartPointer< ImageInteractorStyle >::New( );
559 this->Style->AssociateView( this );
560 this->Style->SetMouseMoveCommand( Self::_MouseMoveCommand );
561 this->Style->SetMouseClickCommand( Self::_MouseClickCommand );
562 this->Style->SetMouseDoubleClickCommand( Self::_MouseDoubleClickCommand );
563 this->Style->SetMouseWheelCommand( Self::_MouseWheelCommand );
564 this->Style->SetKeyCommand( Self::_KeyCommand );
569 // -------------------------------------------------------------------------
570 cpExtensions::Visualization::ImageSliceActors::
575 // -------------------------------------------------------------------------
576 void cpExtensions::Visualization::ImageSliceActors::
577 _ConfigureNewInput( int axis )
579 unsigned int nImages = this->ImageActors.size( );
582 vtkImageSliceMapper* mapper = this->SliceMappers[ nImages ];
584 mapper->SetOrientation( axis );
586 mapper->SetOrientation( this->SliceMappers[ 0 ]->GetOrientation( ) );
590 vtkSmartPointer< vtkImageActor > actor =
591 vtkSmartPointer< vtkImageActor >::New( );
592 this->ImageActors.push_back( actor );
593 actor->SetMapper( mapper );
594 actor->SetInterpolate( this->Interpolate );
599 this->AddItem( this->TextActor );
600 this->AddItem( this->PlaneActor );
601 this->Style->AssociateImageActor( actor );
604 this->AddItem( actor );
607 this->SetSliceNumber( this->GetSliceNumber( ) );
611 // -------------------------------------------------------------------------
612 void cpExtensions::Visualization::ImageSliceActors::
615 const ImageInteractorStyle::ButtonID& btn, double* pos,
616 bool alt, bool ctr, bool sft
619 ImageSliceActors* actors = reinterpret_cast< ImageSliceActors* >( data );
623 if( btn == ImageInteractorStyle::ButtonID_None )
625 actors->UpdateText( pos );
627 else if( btn == ImageInteractorStyle::ButtonID_Left )
630 else if( btn == ImageInteractorStyle::ButtonID_Middle )
633 else if( btn == ImageInteractorStyle::ButtonID_Right )
638 // -------------------------------------------------------------------------
639 void cpExtensions::Visualization::ImageSliceActors::
642 const ImageInteractorStyle::ButtonID& btn, double* pos,
643 bool alt, bool ctr, bool sft
648 // -------------------------------------------------------------------------
649 void cpExtensions::Visualization::ImageSliceActors::
650 _MouseDoubleClickCommand(
652 const ImageInteractorStyle::ButtonID& btn, double* pos,
653 bool alt, bool ctr, bool sft
658 // -------------------------------------------------------------------------
659 void cpExtensions::Visualization::ImageSliceActors::
662 const int& dir, bool alt, bool ctr, bool sft
667 // -------------------------------------------------------------------------
668 void cpExtensions::Visualization::ImageSliceActors::