]> Creatis software - cpPlugins.git/blob - lib/cpExtensions/Visualization/ImageSliceActors.cxx
Widget integration (step 2/6). WARNING: IT DOES NOT COMPILE YETgit shortlog !
[cpPlugins.git] / lib / cpExtensions / Visualization / ImageSliceActors.cxx
1 #include <cpExtensions/Visualization/ImageSliceActors.h>
2
3 #include <vtkAlgorithmOutput.h>
4 #include <vtkCellArray.h>
5 #include <vtkImageData.h>
6 #include <vtkInformation.h>
7 #include <vtkPlane.h>
8 #include <vtkPoints.h>
9 #include <vtkProperty.h>
10 #include <vtkStreamingDemandDrivenPipeline.h>
11 #include <vtkTextProperty.h>
12
13 // -------------------------------------------------------------------------
14 cpExtensions::Visualization::ImageSliceActors*
15 cpExtensions::Visualization::ImageSliceActors::
16 New( )
17 {
18   return( new Self( ) );
19 }
20
21 // -------------------------------------------------------------------------
22 void cpExtensions::Visualization::ImageSliceActors::
23 AddInputConnection( vtkAlgorithmOutput* aout, int axis )
24 {
25   vtkSmartPointer< vtkImageSliceMapper > mapper =
26     vtkSmartPointer< vtkImageSliceMapper >::New( );
27   this->SliceMappers.push_back( mapper );
28   mapper->SetInputConnection( aout );
29   this->_ConfigureNewInput( axis );
30 }
31
32 // -------------------------------------------------------------------------
33 void cpExtensions::Visualization::ImageSliceActors::
34 AddInputData( vtkImageData* data, int axis )
35 {
36   vtkSmartPointer< vtkImageSliceMapper > mapper =
37     vtkSmartPointer< vtkImageSliceMapper >::New( );
38   this->SliceMappers.push_back( mapper );
39   mapper->SetInputData( data );
40   this->_ConfigureNewInput( axis );
41 }
42
43 // -------------------------------------------------------------------------
44 void cpExtensions::Visualization::ImageSliceActors::
45 Clear( )
46 {
47   // Unbind from container
48   this->RemoveAllItems( );
49
50   // Delete all images
51   this->SliceMappers.clear( );
52   this->ImageActors.clear( );
53   this->OtherActors.clear( );
54
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';
62
63   // Unique objects configuration
64   vtkSmartPointer< vtkPoints > plane_points =
65     vtkSmartPointer< vtkPoints >::New( );
66   vtkSmartPointer< vtkCellArray > plane_lines =
67     vtkSmartPointer< vtkCellArray >::New( );
68
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 );
81
82   this->PlaneMapper->SetInputData( this->PlaneSource );
83   this->PlaneActor->SetMapper( this->PlaneMapper );
84
85   this->TextActor->SetTextScaleModeToNone( );
86   vtkTextProperty* textprop = this->TextActor->GetTextProperty( );
87   textprop->SetColor( 1, 1, 1 );
88   textprop->SetFontFamilyToCourier( );
89   textprop->SetFontSize( 18 );
90   textprop->BoldOff( );
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 );
98 }
99
100 // -------------------------------------------------------------------------
101 unsigned int cpExtensions::Visualization::ImageSliceActors::
102 GetNumberOfImageActors( ) const
103 {
104   return( this->ImageActors.size( ) );
105 }
106
107 // -------------------------------------------------------------------------
108 vtkImageActor* cpExtensions::Visualization::ImageSliceActors::
109 GetImageActor( unsigned int id )
110 {
111   if( id < this->ImageActors.size( ) )
112     return( this->ImageActors[ id ] );
113   else
114     return( NULL );
115 }
116
117 // -------------------------------------------------------------------------
118 const vtkImageActor* cpExtensions::Visualization::ImageSliceActors::
119 GetImageActor( unsigned int id ) const
120 {
121   if( id < this->ImageActors.size( ) )
122     return( this->ImageActors[ id ] );
123   else
124     return( NULL );
125 }
126
127 // -------------------------------------------------------------------------
128 vtkTextActor* cpExtensions::Visualization::ImageSliceActors::
129 GetTextActor( )
130 {
131   return( this->TextActor );
132 }
133
134 // -------------------------------------------------------------------------
135 const vtkTextActor* cpExtensions::Visualization::ImageSliceActors::
136 GetTextActor( ) const
137 {
138   return( this->TextActor );
139 }
140
141 // -------------------------------------------------------------------------
142 vtkActor* cpExtensions::Visualization::ImageSliceActors::
143 GetPlaneActor( )
144 {
145   return( this->PlaneActor );
146 }
147
148 // -------------------------------------------------------------------------
149 const vtkActor* cpExtensions::Visualization::ImageSliceActors::
150 GetPlaneActor( ) const
151 {
152   return( this->PlaneActor );
153 }
154
155 // -------------------------------------------------------------------------
156 vtkPlane* cpExtensions::Visualization::ImageSliceActors::
157 GetPlaneFunction( )
158 {
159   return( this->PlaneFunction );
160 }
161
162 // -------------------------------------------------------------------------
163 const vtkPlane* cpExtensions::Visualization::ImageSliceActors::
164 GetPlaneFunction( ) const
165 {
166   return( this->PlaneFunction );
167 }
168
169 // -------------------------------------------------------------------------
170 void cpExtensions::Visualization::ImageSliceActors::
171 AddActor( vtkAlgorithm* algorithm, vtkActor* actor )
172 {
173   this->OtherActors.push_back( std::pair< vtkSmartPointer< vtkAlgorithm >, vtkSmartPointer< vtkActor > >( algorithm, actor ) );
174   this->AddItem( actor );
175 }
176
177 // -------------------------------------------------------------------------
178 void cpExtensions::Visualization::ImageSliceActors::
179 SetInterpolate( bool v )
180 {
181   if( this->Interpolate != v )
182   {
183     for( unsigned int i = 0; i < this->ImageActors.size( ); ++i )
184       this->ImageActors[ i ]->SetInterpolate( v );
185     this->Interpolate = v;
186     this->Modified( );
187
188   } // fi
189 }
190
191 // -------------------------------------------------------------------------
192 void cpExtensions::Visualization::ImageSliceActors::
193 InterpolateOn( )
194 {
195   this->SetInterpolate( true );
196 }
197
198 // -------------------------------------------------------------------------
199 void cpExtensions::Visualization::ImageSliceActors::
200 InterpolateOff( )
201 {
202   this->SetInterpolate( false );
203 }
204
205 // -------------------------------------------------------------------------
206 double* cpExtensions::Visualization::ImageSliceActors::
207 GetDisplayBounds( ) const
208 {
209   if( this->ImageActors.size( ) > 0 )
210     return( this->ImageActors[ 0 ]->GetDisplayBounds( ) );
211   else
212     return( NULL );
213 }
214
215 // -------------------------------------------------------------------------
216 void cpExtensions::Visualization::ImageSliceActors::
217 GetDisplayBounds( double bounds[ 6 ] ) const
218 {
219   if( this->ImageActors.size( ) == 0 )
220   {
221     bounds[ 0 ] = bounds[ 2 ] = bounds[ 4 ] = double( -1 );
222     bounds[ 1 ] = bounds[ 3 ] = bounds[ 5 ] = double( -1 );
223   }
224   else
225     this->ImageActors[ 0 ]->GetDisplayBounds( bounds );
226 }
227
228 // -------------------------------------------------------------------------
229 int cpExtensions::Visualization::ImageSliceActors::
230 GetAxis( ) const
231 {
232   if( this->SliceMappers.size( ) > 0 )
233     return( this->SliceMappers[ 0 ]->GetOrientation( ) );
234   else
235     return( -1 );
236 }
237
238 // -------------------------------------------------------------------------
239 int cpExtensions::Visualization::ImageSliceActors::
240 GetSliceNumber( ) const
241 {
242   if( this->SliceMappers.size( ) > 0 )
243     return( this->SliceMappers[ 0 ]->GetSliceNumber( ) );
244   else
245     return( -1 );
246 }
247
248 // -------------------------------------------------------------------------
249 int cpExtensions::Visualization::ImageSliceActors::
250 GetSliceNumberMinValue( ) const
251 {
252   if( this->SliceMappers.size( ) > 0 )
253     return( this->SliceMappers[ 0 ]->GetSliceNumberMinValue( ) );
254   else
255     return( -1 );
256 }
257
258 // -------------------------------------------------------------------------
259 int cpExtensions::Visualization::ImageSliceActors::
260 GetSliceNumberMaxValue( ) const
261 {
262   if( this->SliceMappers.size( ) > 0 )
263     return( this->SliceMappers[ 0 ]->GetSliceNumberMaxValue( ) );
264   else
265     return( -1 );
266 }
267
268 // -------------------------------------------------------------------------
269 void cpExtensions::Visualization::ImageSliceActors::
270 SetSliceNumber( const int& slice )
271 {
272   unsigned int nImages = this->SliceMappers.size( );
273   if( nImages == 0 )
274     return;
275
276   // Change visualization extent
277   for( unsigned int i = 0; i < nImages; ++i )
278   {
279     this->SliceMappers[ i ]->SetSliceNumber( slice );
280     this->SliceMappers[ i ]->Modified( );
281     this->ImageActors[ i ]->Modified( );
282     this->SliceMappers[ i ]->Update( );
283
284   } // rof
285
286   // Compute plane
287   vtkAlgorithm* algo = this->SliceMappers[ 0 ]->GetInputAlgorithm( );
288   vtkInformation* info = algo->GetOutputInformation( 0 );
289   int ext[ 6 ];
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 );
295
296   // Prevent obscuring voxels by offsetting the plane geometry
297   double xbnds[ ] =
298     {
299       ori[ 0 ] + ( spac[ 0 ] * double( ext[ 0 ] ) ),
300       ori[ 0 ] + ( spac[ 0 ] * double( ext[ 1 ] ) )
301     };
302   double ybnds[ ] =
303     {
304       ori[ 1 ] + ( spac[ 1 ] * double( ext[ 2 ] ) ),
305       ori[ 1 ] + ( spac[ 1 ] * double( ext[ 3 ] ) )
306     };
307   double zbnds[ ] =
308     {
309       ori[ 2 ] + ( spac[ 2 ] * double( ext[ 4 ] ) ),
310       ori[ 2 ] + ( spac[ 2 ] * double( ext[ 5 ] ) )
311     };
312
313   if( spac[ 0 ] < double( 0 ) )
314   {
315     double t = xbnds[ 0 ];
316     xbnds[ 0 ] = xbnds[ 1 ];
317     xbnds[ 1 ] = t;
318
319   } // fi
320   if( spac[ 1 ] < double( 0 ) )
321   {
322     double t = ybnds[ 0 ];
323     ybnds[ 0 ] = ybnds[ 1 ];
324     ybnds[ 1 ] = t;
325
326   } // fi
327   if( spac[ 2 ] < double( 0 ) )
328   {
329     double t = zbnds[ 0 ];
330     zbnds[ 0 ] = zbnds[ 1 ];
331     zbnds[ 1 ] = t;
332
333   } // fi
334
335   // Plane function origin
336   this->PlaneFunction->SetOrigin( pos );
337
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
344   {
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 );
351   }
352   else if( axis == 1 ) // ZX, y-normal
353   {
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 );
360   }
361   else // XY, z-normal
362   {
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 );
369
370   } // fi
371   this->PlaneFunction->Modified( );
372   this->PlaneSource->Modified( );
373   this->PlaneMapper->Modified( );
374   this->PlaneActor->Modified( );
375
376   // Prepare other actors to update
377   for( unsigned int i = 0; i < this->OtherActors.size( ); ++i )
378   {
379 #error CLEAN UP CODING STYLE AND NULL POINTER CHECK
380
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( );
385
386   } // rof
387
388   // Update text
389   this->UpdateText( );
390 }
391
392 // -------------------------------------------------------------------------
393 void cpExtensions::Visualization::ImageSliceActors::
394 UpdateText( )
395 {
396   if( this->SliceMappers.size( ) > 0 )
397   {
398     char axis;
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';
403
404     std::sprintf(
405       this->TextBuffer, "Axis: %c (%d)",
406       axis, this->SliceMappers[ 0 ]->GetSliceNumber( )
407       );
408   }
409   else
410     this->TextBuffer[ 0 ] = '\0';
411   this->TextActor->SetInput( this->TextBuffer );
412   this->TextActor->Modified( );
413   this->Modified( );
414 }
415
416 // -------------------------------------------------------------------------
417 void cpExtensions::Visualization::ImageSliceActors::
418 UpdateText( const double& w, const double& l )
419 {
420   if( this->SliceMappers.size( ) > 0 )
421   {
422     char axis;
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';
427
428     std::sprintf(
429       this->TextBuffer, "Axis: %c (%d) | W/L (%.2f/%.2f)",
430       axis, this->SliceMappers[ 0 ]->GetSliceNumber( ), w, l
431       );
432   }
433   else
434     this->TextBuffer[ 0 ] = '\0';
435   this->TextActor->SetInput( this->TextBuffer );
436   this->TextActor->Modified( );
437   this->Modified( );
438 }
439
440 // -------------------------------------------------------------------------
441 cpExtensions::Visualization::ImageSliceActors::
442 ImageSliceActors( )
443   : Superclass( ),
444     Interpolate( false )
445 {
446   this->Clear( );
447 }
448
449 // -------------------------------------------------------------------------
450 cpExtensions::Visualization::ImageSliceActors::
451 ~ImageSliceActors( )
452 {
453 }
454
455 // -------------------------------------------------------------------------
456 void cpExtensions::Visualization::ImageSliceActors::
457 _ConfigureNewInput( int axis )
458 {
459   unsigned int nImages = this->ImageActors.size( );
460
461   // Configure mapper
462   vtkImageSliceMapper* mapper = this->SliceMappers[ nImages ];
463   if( nImages == 0 )
464     mapper->SetOrientation( axis );
465   else
466     mapper->SetOrientation( this->SliceMappers[ 0 ]->GetOrientation( ) );
467   mapper->Update( );
468
469   // Create actor
470   vtkSmartPointer< vtkImageActor > actor =
471     vtkSmartPointer< vtkImageActor >::New( );
472   this->ImageActors.push_back( actor );
473   actor->SetMapper( mapper );
474   actor->SetInterpolate( this->Interpolate );
475   actor->Modified( );
476
477   if( nImages == 0 )
478   {
479     this->AddItem( this->TextActor );
480     this->AddItem( this->PlaneActor );
481
482   } // fi
483   this->AddItem( actor );
484
485   if( nImages > 1 )
486     this->SetSliceNumber( this->GetSliceNumber( ) );
487   this->Modified( );
488 }
489
490 // eof - $RCSfile$