]> Creatis software - cpPlugins.git/blob - lib/cpExtensions/Visualization/ImageSliceActors.cxx
Merge ssh://git.creatis.insa-lyon.fr/cpPlugins
[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   unsigned int nImages = this->SliceMappers.size( );
26
27   vtkSmartPointer< vtkImageSliceMapper > mapper =
28     vtkSmartPointer< vtkImageSliceMapper >::New( );
29   this->SliceMappers.push_back( mapper );
30   mapper->SetInputConnection( aout );
31   mapper->SetOrientation(
32     ( nImages == 0 )? axis: this->SliceMappers[ 0 ]->GetOrientation( )
33     );
34   mapper->Update( );
35   
36   this->SetSliceNumber( this->SliceMappers[ 0 ]->GetSliceNumber( ) );
37
38   vtkSmartPointer< vtkImageActor > actor =
39     vtkSmartPointer< vtkImageActor >::New( );
40   this->ImageActors.push_back( actor );
41   actor->SetMapper( mapper );
42   actor->Modified( );
43
44   if( nImages == 0 )
45   {
46     this->AddItem( this->TextActor );
47     this->AddItem( this->PlaneActor );
48
49   } // fi
50   this->AddItem( actor );
51   this->Modified( );
52 }
53
54 // -------------------------------------------------------------------------
55 void cpExtensions::Visualization::ImageSliceActors::
56 AddInputData( vtkImageData* data, int axis )
57 {
58   unsigned int nImages = this->SliceMappers.size( );
59
60   vtkSmartPointer< vtkImageSliceMapper > mapper =
61     vtkSmartPointer< vtkImageSliceMapper >::New( );
62   this->SliceMappers.push_back( mapper );
63   mapper->SetInputData( data );
64   mapper->SetOrientation(
65     ( nImages == 0 )? axis: this->SliceMappers[ 0 ]->GetOrientation( )
66     );
67   mapper->Update( );
68   
69   this->SetSliceNumber( this->SliceMappers[ 0 ]->GetSliceNumber( ) );
70
71   vtkSmartPointer< vtkImageActor > actor =
72     vtkSmartPointer< vtkImageActor >::New( );
73   this->ImageActors.push_back( actor );
74   actor->SetMapper( mapper );
75   actor->Modified( );
76
77   if( nImages == 0 )
78   {
79     this->AddItem( this->TextActor );
80     this->AddItem( this->PlaneActor );
81
82   } // fi
83   this->AddItem( actor );
84   this->Modified( );
85 }
86
87 // -------------------------------------------------------------------------
88 void cpExtensions::Visualization::ImageSliceActors::
89 Clear( )
90 {
91   // Unbind from container
92   this->RemoveAllItems( );
93
94   // Delete all images
95   this->SliceMappers.clear( );
96   this->ImageActors.clear( );
97
98   // Reconfigure unique objects
99   this->PlaneSource = vtkSmartPointer< vtkPolyData >::New( );
100   this->PlaneMapper = vtkSmartPointer< vtkPolyDataMapper >::New( );
101   this->TextActor   = vtkSmartPointer< vtkTextActor >::New( );
102   this->PlaneActor  = vtkSmartPointer< vtkActor >::New( );
103   this->TextBuffer[ 0 ] = '\0';
104
105   // Unique objects configuration
106   vtkSmartPointer< vtkPoints > plane_points =
107     vtkSmartPointer< vtkPoints >::New( );
108   vtkSmartPointer< vtkCellArray > plane_lines =
109     vtkSmartPointer< vtkCellArray >::New( );
110
111   plane_points->InsertNextPoint( 0, 0, 0 );
112   plane_points->InsertNextPoint( 0, 1, 0 );
113   plane_points->InsertNextPoint( 1, 1, 0 );
114   plane_points->InsertNextPoint( 1, 0, 0 );
115   plane_lines->InsertNextCell( 5 );
116   plane_lines->InsertCellPoint( 0 );
117   plane_lines->InsertCellPoint( 1 );
118   plane_lines->InsertCellPoint( 2 );
119   plane_lines->InsertCellPoint( 3 );
120   plane_lines->InsertCellPoint( 0 );
121   this->PlaneSource->SetPoints( plane_points );
122   this->PlaneSource->SetLines( plane_lines );
123
124   this->PlaneMapper->SetInputData( this->PlaneSource );
125   this->PlaneActor->SetMapper( this->PlaneMapper );
126
127   this->TextActor->SetTextScaleModeToNone( );
128   vtkTextProperty* textprop = this->TextActor->GetTextProperty( );
129   textprop->SetColor( 1, 1, 1 );
130   textprop->SetFontFamilyToCourier( );
131   textprop->SetFontSize( 18 );
132   textprop->BoldOff( );
133   textprop->ItalicOff( );
134   textprop->ShadowOff( );
135   textprop->SetJustificationToLeft( );
136   textprop->SetVerticalJustificationToBottom( );
137   vtkCoordinate* coord = this->TextActor->GetPositionCoordinate( );
138   coord->SetCoordinateSystemToNormalizedViewport( );
139   coord->SetValue( 0.01, 0.01 );
140 }
141
142 // -------------------------------------------------------------------------
143 unsigned int cpExtensions::Visualization::ImageSliceActors::
144 GetNumberOfImageActors( ) const
145 {
146   return( this->ImageActors.size( ) );
147 }
148
149 // -------------------------------------------------------------------------
150 vtkImageActor* cpExtensions::Visualization::ImageSliceActors::
151 GetImageActor( unsigned int id )
152 {
153   if( id < this->ImageActors.size( ) )
154     return( this->ImageActors[ id ] );
155   else
156     return( NULL );
157 }
158
159 // -------------------------------------------------------------------------
160 const vtkImageActor* cpExtensions::Visualization::ImageSliceActors::
161 GetImageActor( unsigned int id ) const
162 {
163   if( id < this->ImageActors.size( ) )
164     return( this->ImageActors[ id ] );
165   else
166     return( NULL );
167 }
168
169 // -------------------------------------------------------------------------
170 vtkTextActor* cpExtensions::Visualization::ImageSliceActors::
171 GetTextActor( )
172 {
173   return( this->TextActor );
174 }
175
176 // -------------------------------------------------------------------------
177 const vtkTextActor* cpExtensions::Visualization::ImageSliceActors::
178 GetTextActor( ) const
179 {
180   return( this->TextActor );
181 }
182
183 // -------------------------------------------------------------------------
184 vtkActor* cpExtensions::Visualization::ImageSliceActors::
185 GetPlaneActor( )
186 {
187   return( this->PlaneActor );
188 }
189
190 // -------------------------------------------------------------------------
191 const vtkActor* cpExtensions::Visualization::ImageSliceActors::
192 GetPlaneActor( ) const
193 {
194   return( this->PlaneActor );
195 }
196
197 // -------------------------------------------------------------------------
198 double* cpExtensions::Visualization::ImageSliceActors::
199 GetDisplayBounds( ) const
200 {
201   if( this->ImageActors.size( ) > 0 )
202     return( this->ImageActors[ 0 ]->GetDisplayBounds( ) );
203   else
204     return( NULL );
205 }
206
207 // -------------------------------------------------------------------------
208 void cpExtensions::Visualization::ImageSliceActors::
209 GetDisplayBounds( double bounds[ 6 ] ) const
210 {
211   if( this->ImageActors.size( ) > 0 )
212     this->ImageActors[ 0 ]->GetDisplayBounds( bounds );
213 }
214
215 // -------------------------------------------------------------------------
216 int cpExtensions::Visualization::ImageSliceActors::
217 GetAxis( ) const
218 {
219   if( this->SliceMappers.size( ) > 0 )
220     return( this->SliceMappers[ 0 ]->GetOrientation( ) );
221   else
222     return( -1 );
223 }
224
225 // -------------------------------------------------------------------------
226 int cpExtensions::Visualization::ImageSliceActors::
227 GetSliceNumber( ) const
228 {
229   if( this->SliceMappers.size( ) > 0 )
230     return( this->SliceMappers[ 0 ]->GetSliceNumber( ) );
231   else
232     return( -1 );
233 }
234
235 // -------------------------------------------------------------------------
236 int cpExtensions::Visualization::ImageSliceActors::
237 GetSliceNumberMinValue( ) const
238 {
239   if( this->SliceMappers.size( ) > 0 )
240     return( this->SliceMappers[ 0 ]->GetSliceNumberMinValue( ) );
241   else
242     return( -1 );
243 }
244
245 // -------------------------------------------------------------------------
246 int cpExtensions::Visualization::ImageSliceActors::
247 GetSliceNumberMaxValue( ) const
248 {
249   if( this->SliceMappers.size( ) > 0 )
250     return( this->SliceMappers[ 0 ]->GetSliceNumberMaxValue( ) );
251   else
252     return( -1 );
253 }
254
255 // -------------------------------------------------------------------------
256 void cpExtensions::Visualization::ImageSliceActors::
257 SetSliceNumber( const int& slice )
258 {
259   unsigned int nImages = this->SliceMappers.size( );
260   if( nImages == 0 )
261     return;
262
263   // Change visualization extent
264   for( unsigned int i = 0; i < nImages; ++i )
265   {
266     this->SliceMappers[ i ]->SetSliceNumber( slice );
267     this->SliceMappers[ i ]->Modified( );
268     this->ImageActors[ i ]->Modified( );
269     this->SliceMappers[ i ]->Update( );
270
271   } // rof
272
273   // Compute plane
274   vtkAlgorithm* algo = this->SliceMappers[ 0 ]->GetInputAlgorithm( );
275   vtkInformation* info = algo->GetOutputInformation( 0 );
276   int ext[ 6 ];
277   double ori[ 3 ], spac[ 3 ], pos[ 3 ];
278   info->Get( vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT( ), ext );
279   info->Get( vtkDataObject::ORIGIN( ), ori );
280   info->Get( vtkDataObject::SPACING( ), spac );
281   this->SliceMappers[ 0 ]->GetSlicePlane( )->GetOrigin( pos );
282
283   // Prevent obscuring voxels by offsetting the plane geometry
284   double xbnds[ ] =
285     {
286       ori[ 0 ] + ( spac[ 0 ] * double( ext[ 0 ] ) ),
287       ori[ 0 ] + ( spac[ 0 ] * double( ext[ 1 ] ) )
288     };
289   double ybnds[ ] =
290     {
291       ori[ 1 ] + ( spac[ 1 ] * double( ext[ 2 ] ) ),
292       ori[ 1 ] + ( spac[ 1 ] * double( ext[ 3 ] ) )
293     };
294   double zbnds[ ] =
295     {
296       ori[ 2 ] + ( spac[ 2 ] * double( ext[ 4 ] ) ),
297       ori[ 2 ] + ( spac[ 2 ] * double( ext[ 5 ] ) )
298     };
299
300   if( spac[ 0 ] < double( 0 ) )
301   {
302     double t = xbnds[ 0 ];
303     xbnds[ 0 ] = xbnds[ 1 ];
304     xbnds[ 1 ] = t;
305
306   } // fi
307   if( spac[ 1 ] < double( 0 ) )
308   {
309     double t = ybnds[ 0 ];
310     ybnds[ 0 ] = ybnds[ 1 ];
311     ybnds[ 1 ] = t;
312
313   } // fi
314   if( spac[ 2 ] < double( 0 ) )
315   {
316     double t = zbnds[ 0 ];
317     zbnds[ 0 ] = zbnds[ 1 ];
318     zbnds[ 1 ] = t;
319
320   } // fi
321
322   int axis = this->SliceMappers[ 0 ]->GetOrientation( );
323   this->PlaneActor->GetProperty( )->SetRepresentationToWireframe( );
324   this->PlaneActor->GetProperty( )->SetLineWidth( 2 );
325   vtkPoints* plane_points = this->PlaneSource->GetPoints( );
326   if( axis == 0 ) // YZ, x-normal
327   {
328     plane_points->SetPoint( 0, pos[ 0 ], ybnds[ 0 ], zbnds[ 0 ] );
329     plane_points->SetPoint( 1, pos[ 0 ], ybnds[ 1 ], zbnds[ 0 ] );
330     plane_points->SetPoint( 2, pos[ 0 ], ybnds[ 1 ], zbnds[ 1 ] );
331     plane_points->SetPoint( 3, pos[ 0 ], ybnds[ 0 ], zbnds[ 1 ] );
332     this->PlaneActor->GetProperty( )->SetColor( 1, 0, 0 );
333   }
334   else if( axis == 1 ) // ZX, y-normal
335   {
336     plane_points->SetPoint( 0, xbnds[ 0 ], pos[ 1 ], zbnds[ 0 ] );
337     plane_points->SetPoint( 1, xbnds[ 0 ], pos[ 1 ], zbnds[ 1 ] );
338     plane_points->SetPoint( 2, xbnds[ 1 ], pos[ 1 ], zbnds[ 1 ] );
339     plane_points->SetPoint( 3, xbnds[ 1 ], pos[ 1 ], zbnds[ 0 ] );
340     this->PlaneActor->GetProperty( )->SetColor( 0, 1, 0 );
341   }
342   else // XY, z-normal
343   {
344     plane_points->SetPoint( 0, xbnds[ 0 ], ybnds[ 0 ], pos[ 2 ] );
345     plane_points->SetPoint( 1, xbnds[ 1 ], ybnds[ 0 ], pos[ 2 ] );
346     plane_points->SetPoint( 2, xbnds[ 1 ], ybnds[ 1 ], pos[ 2 ] );
347     plane_points->SetPoint( 3, xbnds[ 0 ], ybnds[ 1 ], pos[ 2 ] );
348     this->PlaneActor->GetProperty( )->SetColor( 0, 0, 1 );
349
350   } // fi
351   this->PlaneSource->Modified( );
352   this->PlaneMapper->Modified( );
353   this->PlaneActor->Modified( );
354   this->Modified( );
355 }
356
357 // -------------------------------------------------------------------------
358 void cpExtensions::Visualization::ImageSliceActors::
359 UpdateText( )
360 {
361   if( this->SliceMappers.size( ) > 0 )
362   {
363     char axis;
364     int axId = this->SliceMappers[ 0 ]->GetOrientation( );
365     if     ( axId == 0 ) axis = 'X';
366     else if( axId == 1 ) axis = 'Y';
367     else if( axId == 2 ) axis = 'Z';
368
369     std::sprintf(
370       this->TextBuffer, "Axis: %c (%d)",
371       axis, this->SliceMappers[ 0 ]->GetSliceNumber( )
372       );
373   }
374   else
375     this->TextBuffer[ 0 ] = '\0';
376   this->TextActor->SetInput( this->TextBuffer );
377   this->TextActor->Modified( );
378   this->Modified( );
379 }
380
381 // -------------------------------------------------------------------------
382 cpExtensions::Visualization::ImageSliceActors::
383 ImageSliceActors( )
384   : Superclass( )
385 {
386   this->Clear( );
387 }
388
389 // -------------------------------------------------------------------------
390 cpExtensions::Visualization::ImageSliceActors::
391 ~ImageSliceActors( )
392 {
393 }
394
395 // eof - $RCSfile$