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( std::pair< vtkSmartPointer< vtkAlgorithm >, vtkSmartPointer< vtkActor > >( algorithm, actor ) );
174 this->AddItem( actor );
177 // -------------------------------------------------------------------------
178 void cpExtensions::Visualization::ImageSliceActors::
179 SetInterpolate( bool v )
181 if( this->Interpolate != v )
183 for( unsigned int i = 0; i < this->ImageActors.size( ); ++i )
184 this->ImageActors[ i ]->SetInterpolate( v );
185 this->Interpolate = v;
191 // -------------------------------------------------------------------------
192 void cpExtensions::Visualization::ImageSliceActors::
195 this->SetInterpolate( true );
198 // -------------------------------------------------------------------------
199 void cpExtensions::Visualization::ImageSliceActors::
202 this->SetInterpolate( false );
205 // -------------------------------------------------------------------------
206 double* cpExtensions::Visualization::ImageSliceActors::
207 GetDisplayBounds( ) const
209 if( this->ImageActors.size( ) > 0 )
210 return( this->ImageActors[ 0 ]->GetDisplayBounds( ) );
215 // -------------------------------------------------------------------------
216 void cpExtensions::Visualization::ImageSliceActors::
217 GetDisplayBounds( double bounds[ 6 ] ) const
219 if( this->ImageActors.size( ) == 0 )
221 bounds[ 0 ] = bounds[ 2 ] = bounds[ 4 ] = double( -1 );
222 bounds[ 1 ] = bounds[ 3 ] = bounds[ 5 ] = double( -1 );
225 this->ImageActors[ 0 ]->GetDisplayBounds( bounds );
228 // -------------------------------------------------------------------------
229 int cpExtensions::Visualization::ImageSliceActors::
232 if( this->SliceMappers.size( ) > 0 )
233 return( this->SliceMappers[ 0 ]->GetOrientation( ) );
238 // -------------------------------------------------------------------------
239 int cpExtensions::Visualization::ImageSliceActors::
240 GetSliceNumber( ) const
242 if( this->SliceMappers.size( ) > 0 )
243 return( this->SliceMappers[ 0 ]->GetSliceNumber( ) );
248 // -------------------------------------------------------------------------
249 int cpExtensions::Visualization::ImageSliceActors::
250 GetSliceNumberMinValue( ) const
252 if( this->SliceMappers.size( ) > 0 )
253 return( this->SliceMappers[ 0 ]->GetSliceNumberMinValue( ) );
258 // -------------------------------------------------------------------------
259 int cpExtensions::Visualization::ImageSliceActors::
260 GetSliceNumberMaxValue( ) const
262 if( this->SliceMappers.size( ) > 0 )
263 return( this->SliceMappers[ 0 ]->GetSliceNumberMaxValue( ) );
268 // -------------------------------------------------------------------------
269 void cpExtensions::Visualization::ImageSliceActors::
270 SetSliceNumber( const int& slice )
272 unsigned int nImages = this->SliceMappers.size( );
276 // Change visualization extent
277 for( unsigned int i = 0; i < nImages; ++i )
279 this->SliceMappers[ i ]->SetSliceNumber( slice );
280 this->SliceMappers[ i ]->Modified( );
281 this->ImageActors[ i ]->Modified( );
282 this->SliceMappers[ i ]->Update( );
287 vtkAlgorithm* algo = this->SliceMappers[ 0 ]->GetInputAlgorithm( );
288 vtkInformation* info = algo->GetOutputInformation( 0 );
290 double ori[ 3 ], spac[ 3 ], pos[ 3 ];
291 info->Get( vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT( ), ext );
292 info->Get( vtkDataObject::ORIGIN( ), ori );
293 info->Get( vtkDataObject::SPACING( ), spac );
294 this->SliceMappers[ 0 ]->GetSlicePlane( )->GetOrigin( pos );
296 // Prevent obscuring voxels by offsetting the plane geometry
299 ori[ 0 ] + ( spac[ 0 ] * double( ext[ 0 ] ) ),
300 ori[ 0 ] + ( spac[ 0 ] * double( ext[ 1 ] ) )
304 ori[ 1 ] + ( spac[ 1 ] * double( ext[ 2 ] ) ),
305 ori[ 1 ] + ( spac[ 1 ] * double( ext[ 3 ] ) )
309 ori[ 2 ] + ( spac[ 2 ] * double( ext[ 4 ] ) ),
310 ori[ 2 ] + ( spac[ 2 ] * double( ext[ 5 ] ) )
313 if( spac[ 0 ] < double( 0 ) )
315 double t = xbnds[ 0 ];
316 xbnds[ 0 ] = xbnds[ 1 ];
320 if( spac[ 1 ] < double( 0 ) )
322 double t = ybnds[ 0 ];
323 ybnds[ 0 ] = ybnds[ 1 ];
327 if( spac[ 2 ] < double( 0 ) )
329 double t = zbnds[ 0 ];
330 zbnds[ 0 ] = zbnds[ 1 ];
335 // Plane function origin
336 this->PlaneFunction->SetOrigin( pos );
338 // Configure visualization and implicit plane orientation
339 int axis = this->SliceMappers[ 0 ]->GetOrientation( );
340 this->PlaneActor->GetProperty( )->SetRepresentationToWireframe( );
341 this->PlaneActor->GetProperty( )->SetLineWidth( 2 );
342 vtkPoints* plane_points = this->PlaneSource->GetPoints( );
343 if( axis == 0 ) // YZ, x-normal
345 this->PlaneFunction->SetNormal( 1, 0, 0 );
346 plane_points->SetPoint( 0, pos[ 0 ], ybnds[ 0 ], zbnds[ 0 ] );
347 plane_points->SetPoint( 1, pos[ 0 ], ybnds[ 1 ], zbnds[ 0 ] );
348 plane_points->SetPoint( 2, pos[ 0 ], ybnds[ 1 ], zbnds[ 1 ] );
349 plane_points->SetPoint( 3, pos[ 0 ], ybnds[ 0 ], zbnds[ 1 ] );
350 this->PlaneActor->GetProperty( )->SetColor( 1, 0, 0 );
352 else if( axis == 1 ) // ZX, y-normal
354 this->PlaneFunction->SetNormal( 0, 1, 0 );
355 plane_points->SetPoint( 0, xbnds[ 0 ], pos[ 1 ], zbnds[ 0 ] );
356 plane_points->SetPoint( 1, xbnds[ 0 ], pos[ 1 ], zbnds[ 1 ] );
357 plane_points->SetPoint( 2, xbnds[ 1 ], pos[ 1 ], zbnds[ 1 ] );
358 plane_points->SetPoint( 3, xbnds[ 1 ], pos[ 1 ], zbnds[ 0 ] );
359 this->PlaneActor->GetProperty( )->SetColor( 0, 1, 0 );
363 this->PlaneFunction->SetNormal( 0, 0, 1 );
364 plane_points->SetPoint( 0, xbnds[ 0 ], ybnds[ 0 ], pos[ 2 ] );
365 plane_points->SetPoint( 1, xbnds[ 1 ], ybnds[ 0 ], pos[ 2 ] );
366 plane_points->SetPoint( 2, xbnds[ 1 ], ybnds[ 1 ], pos[ 2 ] );
367 plane_points->SetPoint( 3, xbnds[ 0 ], ybnds[ 1 ], pos[ 2 ] );
368 this->PlaneActor->GetProperty( )->SetColor( 0, 0, 1 );
371 this->PlaneFunction->Modified( );
372 this->PlaneSource->Modified( );
373 this->PlaneMapper->Modified( );
374 this->PlaneActor->Modified( );
376 // Prepare other actors to update
377 for( unsigned int i = 0; i < this->OtherActors.size( ); ++i )
379 #error CLEAN UP CODING STYLE AND NULL POINTER CHECK
381 this->OtherActors[ i ].first->Modified( );
382 this->OtherActors[ i ].first->Update( );
383 this->OtherActors[ i ].second->GetMapper( )->Modified( );
384 this->OtherActors[ i ].second->Modified( );
392 // -------------------------------------------------------------------------
393 void cpExtensions::Visualization::ImageSliceActors::
396 if( this->SliceMappers.size( ) > 0 )
399 int axId = this->SliceMappers[ 0 ]->GetOrientation( );
400 if ( axId == 0 ) axis = 'X';
401 else if( axId == 1 ) axis = 'Y';
402 else if( axId == 2 ) axis = 'Z';
405 this->TextBuffer, "Axis: %c (%d)",
406 axis, this->SliceMappers[ 0 ]->GetSliceNumber( )
410 this->TextBuffer[ 0 ] = '\0';
411 this->TextActor->SetInput( this->TextBuffer );
412 this->TextActor->Modified( );
416 // -------------------------------------------------------------------------
417 void cpExtensions::Visualization::ImageSliceActors::
418 UpdateText( const double& w, const double& l )
420 if( this->SliceMappers.size( ) > 0 )
423 int axId = this->SliceMappers[ 0 ]->GetOrientation( );
424 if ( axId == 0 ) axis = 'X';
425 else if( axId == 1 ) axis = 'Y';
426 else if( axId == 2 ) axis = 'Z';
429 this->TextBuffer, "Axis: %c (%d) | W/L (%.2f/%.2f)",
430 axis, this->SliceMappers[ 0 ]->GetSliceNumber( ), w, l
434 this->TextBuffer[ 0 ] = '\0';
435 this->TextActor->SetInput( this->TextBuffer );
436 this->TextActor->Modified( );
440 // -------------------------------------------------------------------------
441 cpExtensions::Visualization::ImageSliceActors::
449 // -------------------------------------------------------------------------
450 cpExtensions::Visualization::ImageSliceActors::
455 // -------------------------------------------------------------------------
456 void cpExtensions::Visualization::ImageSliceActors::
457 _ConfigureNewInput( int axis )
459 unsigned int nImages = this->ImageActors.size( );
462 vtkImageSliceMapper* mapper = this->SliceMappers[ nImages ];
464 mapper->SetOrientation( axis );
466 mapper->SetOrientation( this->SliceMappers[ 0 ]->GetOrientation( ) );
470 vtkSmartPointer< vtkImageActor > actor =
471 vtkSmartPointer< vtkImageActor >::New( );
472 this->ImageActors.push_back( actor );
473 actor->SetMapper( mapper );
474 actor->SetInterpolate( this->Interpolate );
479 this->AddItem( this->TextActor );
480 this->AddItem( this->PlaneActor );
483 this->AddItem( actor );
486 this->SetSliceNumber( this->GetSliceNumber( ) );