1 #include <cpExtensions/Visualization/ImageSliceActors.h>
3 #include <vtkAlgorithmOutput.h>
4 #include <vtkCellArray.h>
5 #include <vtkImageData.h>
6 #include <vtkInformation.h>
9 #include <vtkProperty.h>
10 #include <vtkStreamingDemandDrivenPipeline.h>
11 #include <vtkTextProperty.h>
13 // -------------------------------------------------------------------------
14 cpExtensions::Visualization::ImageSliceActors*
15 cpExtensions::Visualization::ImageSliceActors::
18 return( new Self( ) );
21 // -------------------------------------------------------------------------
22 void cpExtensions::Visualization::ImageSliceActors::
23 AddInputConnection( vtkAlgorithmOutput* aout, int axis )
25 vtkSmartPointer< vtkImageSliceMapper > mapper =
26 vtkSmartPointer< vtkImageSliceMapper >::New( );
27 this->SliceMappers.push_back( mapper );
28 mapper->SetInputConnection( aout );
29 this->_ConfigureNewInput( axis );
32 // -------------------------------------------------------------------------
33 void cpExtensions::Visualization::ImageSliceActors::
34 AddInputData( vtkImageData* data, int axis )
36 vtkSmartPointer< vtkImageSliceMapper > mapper =
37 vtkSmartPointer< vtkImageSliceMapper >::New( );
38 this->SliceMappers.push_back( mapper );
39 mapper->SetInputData( data );
40 this->_ConfigureNewInput( axis );
43 // -------------------------------------------------------------------------
44 void cpExtensions::Visualization::ImageSliceActors::
47 // Unbind from container
48 this->RemoveAllItems( );
51 this->SliceMappers.clear( );
52 this->ImageActors.clear( );
53 this->OtherActors.clear( );
55 // Reconfigure unique objects
56 this->PlaneFunction = vtkSmartPointer< vtkPlane >::New( );
57 this->PlaneSource = vtkSmartPointer< vtkPolyData >::New( );
58 this->PlaneMapper = vtkSmartPointer< vtkPolyDataMapper >::New( );
59 this->TextActor = vtkSmartPointer< vtkTextActor >::New( );
60 this->PlaneActor = vtkSmartPointer< vtkActor >::New( );
61 this->TextBuffer[ 0 ] = '\0';
63 // Unique objects configuration
64 vtkSmartPointer< vtkPoints > plane_points =
65 vtkSmartPointer< vtkPoints >::New( );
66 vtkSmartPointer< vtkCellArray > plane_lines =
67 vtkSmartPointer< vtkCellArray >::New( );
69 plane_points->InsertNextPoint( 0, 0, 0 );
70 plane_points->InsertNextPoint( 0, 1, 0 );
71 plane_points->InsertNextPoint( 1, 1, 0 );
72 plane_points->InsertNextPoint( 1, 0, 0 );
73 plane_lines->InsertNextCell( 5 );
74 plane_lines->InsertCellPoint( 0 );
75 plane_lines->InsertCellPoint( 1 );
76 plane_lines->InsertCellPoint( 2 );
77 plane_lines->InsertCellPoint( 3 );
78 plane_lines->InsertCellPoint( 0 );
79 this->PlaneSource->SetPoints( plane_points );
80 this->PlaneSource->SetLines( plane_lines );
82 this->PlaneMapper->SetInputData( this->PlaneSource );
83 this->PlaneActor->SetMapper( this->PlaneMapper );
85 this->TextActor->SetTextScaleModeToNone( );
86 vtkTextProperty* textprop = this->TextActor->GetTextProperty( );
87 textprop->SetColor( 1, 1, 1 );
88 textprop->SetFontFamilyToCourier( );
89 textprop->SetFontSize( 18 );
91 textprop->ItalicOff( );
92 textprop->ShadowOff( );
93 textprop->SetJustificationToLeft( );
94 textprop->SetVerticalJustificationToBottom( );
95 vtkCoordinate* coord = this->TextActor->GetPositionCoordinate( );
96 coord->SetCoordinateSystemToNormalizedViewport( );
97 coord->SetValue( 0.01, 0.01 );
100 // -------------------------------------------------------------------------
101 unsigned int cpExtensions::Visualization::ImageSliceActors::
102 GetNumberOfImageActors( ) const
104 return( this->ImageActors.size( ) );
107 // -------------------------------------------------------------------------
108 vtkImageActor* cpExtensions::Visualization::ImageSliceActors::
109 GetImageActor( unsigned int id )
111 if( id < this->ImageActors.size( ) )
112 return( this->ImageActors[ id ] );
117 // -------------------------------------------------------------------------
118 const vtkImageActor* cpExtensions::Visualization::ImageSliceActors::
119 GetImageActor( unsigned int id ) const
121 if( id < this->ImageActors.size( ) )
122 return( this->ImageActors[ id ] );
127 // -------------------------------------------------------------------------
128 vtkTextActor* cpExtensions::Visualization::ImageSliceActors::
131 return( this->TextActor );
134 // -------------------------------------------------------------------------
135 const vtkTextActor* cpExtensions::Visualization::ImageSliceActors::
136 GetTextActor( ) const
138 return( this->TextActor );
141 // -------------------------------------------------------------------------
142 vtkActor* cpExtensions::Visualization::ImageSliceActors::
145 return( this->PlaneActor );
148 // -------------------------------------------------------------------------
149 const vtkActor* cpExtensions::Visualization::ImageSliceActors::
150 GetPlaneActor( ) const
152 return( this->PlaneActor );
155 // -------------------------------------------------------------------------
156 vtkPlane* cpExtensions::Visualization::ImageSliceActors::
159 return( this->PlaneFunction );
162 // -------------------------------------------------------------------------
163 const vtkPlane* cpExtensions::Visualization::ImageSliceActors::
164 GetPlaneFunction( ) const
166 return( this->PlaneFunction );
169 // -------------------------------------------------------------------------
170 void cpExtensions::Visualization::ImageSliceActors::
171 AddActor( vtkAlgorithm* algorithm, vtkActor* actor )
173 this->OtherActors.push_back( TActorPair( algorithm, actor ) );
174 this->AddItem( actor );
177 // -------------------------------------------------------------------------
178 void cpExtensions::Visualization::ImageSliceActors::
179 AddActor( vtkActor* actor )
181 this->AddActor( NULL, actor );
184 // -------------------------------------------------------------------------
185 void cpExtensions::Visualization::ImageSliceActors::
186 SetInterpolate( bool v )
188 if( this->Interpolate != v )
190 for( unsigned int i = 0; i < this->ImageActors.size( ); ++i )
191 this->ImageActors[ i ]->SetInterpolate( v );
192 this->Interpolate = v;
198 // -------------------------------------------------------------------------
199 void cpExtensions::Visualization::ImageSliceActors::
202 this->SetInterpolate( true );
205 // -------------------------------------------------------------------------
206 void cpExtensions::Visualization::ImageSliceActors::
209 this->SetInterpolate( false );
212 // -------------------------------------------------------------------------
213 double* cpExtensions::Visualization::ImageSliceActors::
214 GetDisplayBounds( ) const
216 if( this->ImageActors.size( ) > 0 )
217 return( this->ImageActors[ 0 ]->GetDisplayBounds( ) );
222 // -------------------------------------------------------------------------
223 void cpExtensions::Visualization::ImageSliceActors::
224 GetDisplayBounds( double bounds[ 6 ] ) const
226 if( this->ImageActors.size( ) == 0 )
228 bounds[ 0 ] = bounds[ 2 ] = bounds[ 4 ] = double( -1 );
229 bounds[ 1 ] = bounds[ 3 ] = bounds[ 5 ] = double( -1 );
232 this->ImageActors[ 0 ]->GetDisplayBounds( bounds );
235 // -------------------------------------------------------------------------
236 int cpExtensions::Visualization::ImageSliceActors::
239 if( this->SliceMappers.size( ) > 0 )
240 return( this->SliceMappers[ 0 ]->GetOrientation( ) );
245 // -------------------------------------------------------------------------
246 int cpExtensions::Visualization::ImageSliceActors::
247 GetSliceNumber( ) const
249 if( this->SliceMappers.size( ) > 0 )
250 return( this->SliceMappers[ 0 ]->GetSliceNumber( ) );
255 // -------------------------------------------------------------------------
256 int cpExtensions::Visualization::ImageSliceActors::
257 GetSliceNumberMinValue( ) const
259 if( this->SliceMappers.size( ) > 0 )
260 return( this->SliceMappers[ 0 ]->GetSliceNumberMinValue( ) );
265 // -------------------------------------------------------------------------
266 int cpExtensions::Visualization::ImageSliceActors::
267 GetSliceNumberMaxValue( ) const
269 if( this->SliceMappers.size( ) > 0 )
270 return( this->SliceMappers[ 0 ]->GetSliceNumberMaxValue( ) );
275 // -------------------------------------------------------------------------
276 void cpExtensions::Visualization::ImageSliceActors::
277 SetSliceNumber( const int& slice )
279 unsigned int nImages = this->SliceMappers.size( );
283 // Change visualization extent
284 for( unsigned int i = 0; i < nImages; ++i )
286 this->SliceMappers[ i ]->SetSliceNumber( slice );
287 this->SliceMappers[ i ]->Modified( );
288 this->ImageActors[ i ]->Modified( );
289 this->SliceMappers[ i ]->Update( );
294 vtkAlgorithm* algo = this->SliceMappers[ 0 ]->GetInputAlgorithm( );
295 vtkInformation* info = algo->GetOutputInformation( 0 );
297 double ori[ 3 ], spac[ 3 ], pos[ 3 ];
298 info->Get( vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT( ), ext );
299 info->Get( vtkDataObject::ORIGIN( ), ori );
300 info->Get( vtkDataObject::SPACING( ), spac );
301 this->SliceMappers[ 0 ]->GetSlicePlane( )->GetOrigin( pos );
303 // Prevent obscuring voxels by offsetting the plane geometry
306 ori[ 0 ] + ( spac[ 0 ] * double( ext[ 0 ] ) ),
307 ori[ 0 ] + ( spac[ 0 ] * double( ext[ 1 ] ) )
311 ori[ 1 ] + ( spac[ 1 ] * double( ext[ 2 ] ) ),
312 ori[ 1 ] + ( spac[ 1 ] * double( ext[ 3 ] ) )
316 ori[ 2 ] + ( spac[ 2 ] * double( ext[ 4 ] ) ),
317 ori[ 2 ] + ( spac[ 2 ] * double( ext[ 5 ] ) )
320 if( spac[ 0 ] < double( 0 ) )
322 double t = xbnds[ 0 ];
323 xbnds[ 0 ] = xbnds[ 1 ];
327 if( spac[ 1 ] < double( 0 ) )
329 double t = ybnds[ 0 ];
330 ybnds[ 0 ] = ybnds[ 1 ];
334 if( spac[ 2 ] < double( 0 ) )
336 double t = zbnds[ 0 ];
337 zbnds[ 0 ] = zbnds[ 1 ];
342 // Plane function origin
343 this->PlaneFunction->SetOrigin( pos );
345 // Configure visualization and implicit plane orientation
346 int axis = this->SliceMappers[ 0 ]->GetOrientation( );
347 this->PlaneActor->GetProperty( )->SetRepresentationToWireframe( );
348 this->PlaneActor->GetProperty( )->SetLineWidth( 2 );
349 vtkPoints* plane_points = this->PlaneSource->GetPoints( );
350 if( axis == 0 ) // YZ, x-normal
352 this->PlaneFunction->SetNormal( 1, 0, 0 );
353 plane_points->SetPoint( 0, pos[ 0 ], ybnds[ 0 ], zbnds[ 0 ] );
354 plane_points->SetPoint( 1, pos[ 0 ], ybnds[ 1 ], zbnds[ 0 ] );
355 plane_points->SetPoint( 2, pos[ 0 ], ybnds[ 1 ], zbnds[ 1 ] );
356 plane_points->SetPoint( 3, pos[ 0 ], ybnds[ 0 ], zbnds[ 1 ] );
357 this->PlaneActor->GetProperty( )->SetColor( 1, 0, 0 );
359 else if( axis == 1 ) // ZX, y-normal
361 this->PlaneFunction->SetNormal( 0, 1, 0 );
362 plane_points->SetPoint( 0, xbnds[ 0 ], pos[ 1 ], zbnds[ 0 ] );
363 plane_points->SetPoint( 1, xbnds[ 0 ], pos[ 1 ], zbnds[ 1 ] );
364 plane_points->SetPoint( 2, xbnds[ 1 ], pos[ 1 ], zbnds[ 1 ] );
365 plane_points->SetPoint( 3, xbnds[ 1 ], pos[ 1 ], zbnds[ 0 ] );
366 this->PlaneActor->GetProperty( )->SetColor( 0, 1, 0 );
370 this->PlaneFunction->SetNormal( 0, 0, 1 );
371 plane_points->SetPoint( 0, xbnds[ 0 ], ybnds[ 0 ], pos[ 2 ] );
372 plane_points->SetPoint( 1, xbnds[ 1 ], ybnds[ 0 ], pos[ 2 ] );
373 plane_points->SetPoint( 2, xbnds[ 1 ], ybnds[ 1 ], pos[ 2 ] );
374 plane_points->SetPoint( 3, xbnds[ 0 ], ybnds[ 1 ], pos[ 2 ] );
375 this->PlaneActor->GetProperty( )->SetColor( 0, 0, 1 );
378 this->PlaneFunction->Modified( );
379 this->PlaneSource->Modified( );
380 this->PlaneMapper->Modified( );
381 this->PlaneActor->Modified( );
383 // Prepare other actors to update
384 for( unsigned int i = 0; i < this->OtherActors.size( ); ++i )
386 if( this->OtherActors[ i ].first.GetPointer( ) != NULL )
388 this->OtherActors[ i ].first->Modified( );
389 this->OtherActors[ i ].first->Update( );
393 if( this->OtherActors[ i ].second.GetPointer( ) != NULL )
395 this->OtherActors[ i ].second->GetMapper( )->Modified( );
396 this->OtherActors[ i ].second->Modified( );
406 // -------------------------------------------------------------------------
407 void cpExtensions::Visualization::ImageSliceActors::
410 if( this->SliceMappers.size( ) > 0 )
413 int axId = this->SliceMappers[ 0 ]->GetOrientation( );
414 if ( axId == 0 ) axis = 'X';
415 else if( axId == 1 ) axis = 'Y';
416 else if( axId == 2 ) axis = 'Z';
419 this->TextBuffer, "Axis: %c (%d)",
420 axis, this->SliceMappers[ 0 ]->GetSliceNumber( )
424 this->TextBuffer[ 0 ] = '\0';
425 this->TextActor->SetInput( this->TextBuffer );
426 this->TextActor->Modified( );
430 // -------------------------------------------------------------------------
431 void cpExtensions::Visualization::ImageSliceActors::
432 UpdateText( const double& w, const double& l )
434 if( this->SliceMappers.size( ) > 0 )
437 int axId = this->SliceMappers[ 0 ]->GetOrientation( );
438 if ( axId == 0 ) axis = 'X';
439 else if( axId == 1 ) axis = 'Y';
440 else if( axId == 2 ) axis = 'Z';
443 this->TextBuffer, "Axis: %c (%d) | W/L (%.2f/%.2f)",
444 axis, this->SliceMappers[ 0 ]->GetSliceNumber( ), w, l
448 this->TextBuffer[ 0 ] = '\0';
449 this->TextActor->SetInput( this->TextBuffer );
450 this->TextActor->Modified( );
454 // -------------------------------------------------------------------------
455 cpExtensions::Visualization::ImageSliceActors::
463 // -------------------------------------------------------------------------
464 cpExtensions::Visualization::ImageSliceActors::
469 // -------------------------------------------------------------------------
470 void cpExtensions::Visualization::ImageSliceActors::
471 _ConfigureNewInput( int axis )
473 unsigned int nImages = this->ImageActors.size( );
476 vtkImageSliceMapper* mapper = this->SliceMappers[ nImages ];
478 mapper->SetOrientation( axis );
480 mapper->SetOrientation( this->SliceMappers[ 0 ]->GetOrientation( ) );
484 vtkSmartPointer< vtkImageActor > actor =
485 vtkSmartPointer< vtkImageActor >::New( );
486 this->ImageActors.push_back( actor );
487 actor->SetMapper( mapper );
488 actor->SetInterpolate( this->Interpolate );
493 this->AddItem( this->TextActor );
494 this->AddItem( this->PlaneActor );
497 this->AddItem( actor );
500 this->SetSliceNumber( this->GetSliceNumber( ) );