]> Creatis software - cpPlugins.git/blob - lib/cpExtensions/Visualization/MPRActors.cxx
54e689afab091f6f9317c2f3e708c223ce8f3687
[cpPlugins.git] / lib / cpExtensions / Visualization / MPRActors.cxx
1 #include <cpExtensions/Visualization/MPRActors.h>
2
3 #include <cmath>
4
5 #include <vtkAlgorithmOutput.h>
6 #include <vtkImageData.h>
7 #include <vtkInformation.h>
8 #include <vtkLookupTable.h>
9 #include <vtkOutlineSource.h>
10 #include <vtkProperty.h>
11 #include <vtkRenderer.h>
12 #include <vtkWindowLevelLookupTable.h>
13
14 // -------------------------------------------------------------------------
15 cpExtensions::Visualization::MPRActors*
16 cpExtensions::Visualization::MPRActors::
17 New( )
18 {
19   return( new Self( ) );
20 }
21
22 // -------------------------------------------------------------------------
23 cpExtensions::Visualization::
24 ImageSliceActors* cpExtensions::Visualization::MPRActors::
25 GetSliceActors( const int& i ) const
26 {
27   if( i < 3 )
28     return( this->Slices[ 0 ][ i ] );
29   else
30     return( NULL );
31 }
32
33 // -------------------------------------------------------------------------
34 int cpExtensions::Visualization::MPRActors::
35 AddInputConnection( vtkAlgorithmOutput* aout )
36 {
37   int N = this->ImageMaps.size( );
38   if( N == 0 )
39   {
40     this->ImageMaps.push_back(
41       vtkSmartPointer< vtkImageMapToColors >::New( )
42       );
43     this->ImageMaps[ 0 ]->SetInputConnection( aout );
44     this->SetLookupTableToWindowLevel( 0 );
45     this->_Update( 0 );
46     this->ResetWindowLevel( 0 );
47     return( 0 );
48   }
49   else
50   {
51     // Check if the image share the same space
52     vtkImageData* ref_image = this->_Image( 0 );
53     vtkImageData* new_image =
54       vtkImageData::SafeDownCast(
55         aout->GetProducer( )->GetOutputInformation( 0 )->
56         Get( vtkDataObject::DATA_OBJECT( ) )
57         );
58     int ref_ext[ 6 ], new_ext[ 6 ];
59     ref_image->GetExtent( ref_ext );
60     new_image->GetExtent( new_ext );
61     if(
62       ref_ext[ 0 ] == new_ext[ 0 ] && ref_ext[ 1 ] == new_ext[ 1 ] &&
63       ref_ext[ 2 ] == new_ext[ 2 ] && ref_ext[ 3 ] == new_ext[ 3 ] &&
64       ref_ext[ 4 ] == new_ext[ 4 ] && ref_ext[ 5 ] == new_ext[ 5 ]
65       )
66     {
67       this->ImageMaps.push_back(
68         vtkSmartPointer< vtkImageMapToColors >::New( )
69         );
70       this->ImageMaps[ N ]->SetInputConnection( aout );
71       this->SetLookupTableToColor(
72         N, double( 1 ), double( 0 ), double( 0 )
73         );
74       this->_Update( N );
75       return( N );
76     }
77     else
78       return( -1 );
79
80   } // fi
81 }
82
83 // -------------------------------------------------------------------------
84 int cpExtensions::Visualization::MPRActors::
85 AddInputData( vtkImageData* image )
86 {
87   int N = this->ImageMaps.size( );
88   if( N == 0 )
89   {
90     this->ImageMaps.push_back(
91       vtkSmartPointer< vtkImageMapToColors >::New( )
92       );
93     this->ImageMaps[ 0 ]->SetInputData( image );
94     this->SetLookupTableToWindowLevel( 0 );
95     this->_Update( 0 );
96     this->ResetWindowLevel( 0 );
97     return( 0 );
98   }
99   else
100   {
101     // Check if the image share the same space
102     vtkImageData* ref_image = this->_Image( 0 );
103     vtkImageData* new_image = image;
104     int ref_ext[ 6 ], new_ext[ 6 ];
105     ref_image->GetExtent( ref_ext );
106     new_image->GetExtent( new_ext );
107     if(
108       ref_ext[ 0 ] == new_ext[ 0 ] && ref_ext[ 1 ] == new_ext[ 1 ] &&
109       ref_ext[ 2 ] == new_ext[ 2 ] && ref_ext[ 3 ] == new_ext[ 3 ] &&
110       ref_ext[ 4 ] == new_ext[ 4 ] && ref_ext[ 5 ] == new_ext[ 5 ]
111       )
112     {
113       this->ImageMaps.push_back(
114         vtkSmartPointer< vtkImageMapToColors >::New( )
115         );
116       this->ImageMaps[ N ]->SetInputData( image );
117       this->SetLookupTableToColor(
118         N, double( 1 ), double( 0 ), double( 0 )
119         );
120       this->_Update( N );
121       return( N );
122     }
123     else
124       return( -1 );
125
126   } // fi
127 }
128
129 // -------------------------------------------------------------------------
130 void cpExtensions::Visualization::MPRActors::
131 PushDataInto( vtkRenderer* x, vtkRenderer* y, vtkRenderer* z, vtkRenderer* w )
132 {
133   vtkRenderer* rends[] = { x, y, z };
134   for( int i = 0; i < 3; ++i )
135   {
136     if( rends[ i ] != NULL )
137     {
138       for(
139         unsigned int k = 0;
140         k < this->Slices[ 0 ][ i ]->GetNumberOfImageActors( );
141         ++k
142         )
143         rends[ i ]->AddActor( this->Slices[ 0 ][ i ]->GetImageActor( k ) );
144       rends[ i ]->AddActor( this->Slices[ 0 ][ i ]->GetTextActor( ) );
145       for( int j = 0; j < 3; ++j )
146         rends[ i ]->AddActor( this->Slices[ 0 ][ j ]->GetPlaneActor( ) );
147
148     } // fi
149     if( w != NULL )
150     {
151       for(
152         unsigned int k = 0;
153         k < this->Slices[ 1 ][ i ]->GetNumberOfImageActors( );
154         ++k
155         )
156         w->AddActor( this->Slices[ 1 ][ i ]->GetImageActor( k ) );
157       w->AddActor( this->Slices[ 1 ][ i ]->GetPlaneActor( ) );
158
159     } // fi
160
161   } // rof
162   if( w != NULL )
163     w->AddActor( this->ImageOutlineActor );
164 }
165
166 // -------------------------------------------------------------------------
167 void cpExtensions::Visualization::MPRActors::
168 PopDataFrom(
169   vtkRenderer* x,
170   vtkRenderer* y,
171   vtkRenderer* z,
172   vtkRenderer* w
173   )
174 {
175   vtkRenderer* rends[] = { x, y, z };
176   for( int i = 0; i < 3; ++i )
177   {
178     if( rends[ i ] != NULL )
179     {
180       for(
181         unsigned int k = 0;
182         k < this->Slices[ 0 ][ i ]->GetNumberOfImageActors( );
183         ++k
184         )
185         rends[ i ]->RemoveActor( this->Slices[ 0 ][ i ]->GetImageActor( k ) );
186       rends[ i ]->RemoveActor( this->Slices[ 0 ][ i ]->GetTextActor( ) );
187       for( int j = 0; j < 3; ++j )
188         rends[ i ]->RemoveActor( this->Slices[ 0 ][ j ]->GetPlaneActor( ) );
189
190     } // fi
191     if( w != NULL )
192     {
193       for(
194         unsigned int k = 0;
195         k < this->Slices[ 1 ][ i ]->GetNumberOfImageActors( );
196         ++k
197         )
198         w->RemoveActor( this->Slices[ 1 ][ i ]->GetImageActor( k ) );
199       w->RemoveActor( this->Slices[ 1 ][ i ]->GetPlaneActor( ) );
200
201     } // fi
202
203   } // rof
204   if( w != NULL )
205     w->RemoveActor( this->ImageOutlineActor );
206 }
207
208 // -------------------------------------------------------------------------
209 void cpExtensions::Visualization::MPRActors::
210 LinkInteractors( )
211 {
212   this->_Update( 0 );
213   this->_Update( 1 );
214   this->_Update( 2 );
215 }
216
217 // -------------------------------------------------------------------------
218 void cpExtensions::Visualization::MPRActors::
219 SetLookupTable( unsigned int i, vtkScalarsToColors* lut )
220 {
221   if( i < this->ImageMaps.size( ) )
222   {
223     this->ImageMaps[ i ]->SetLookupTable( lut );
224     this->ImageMaps[ i ]->Update( );
225     this->Modified( );
226
227   } // fi
228 }
229
230 // -------------------------------------------------------------------------
231 vtkScalarsToColors* cpExtensions::Visualization::MPRActors::
232 GetLookupTable( unsigned int i ) const
233 {
234   if( i < this->ImageMaps.size( ) )
235     return( this->ImageMaps[ i ]->GetLookupTable( ) );
236   else
237     return( NULL );
238 }
239
240 // -------------------------------------------------------------------------
241 void cpExtensions::Visualization::MPRActors::
242 SetLookupTableToWindowLevel( unsigned int i )
243 {
244   // Check if the input has been configured
245   vtkImageData* image = this->_Image( i );
246   if( image == NULL )
247     return;
248
249   double r[ 2 ];
250   image->GetScalarRange( r );
251
252   vtkSmartPointer< vtkWindowLevelLookupTable > lut =
253     vtkSmartPointer< vtkWindowLevelLookupTable >::New( );
254   lut->SetScaleToLinear( );
255   lut->SetTableRange( r );
256   lut->Build( );
257
258   this->SetLookupTable( i, lut );
259 }
260
261 // -------------------------------------------------------------------------
262 double cpExtensions::Visualization::MPRActors::
263 GetMinWindow( unsigned int i ) const
264 {
265   return( 0 );
266 }
267
268 // -------------------------------------------------------------------------
269 double cpExtensions::Visualization::MPRActors::
270 GetMaxWindow( unsigned int i ) const
271 {
272   // Check if the input has been configured
273   vtkImageData* image = this->_Image( i );
274   if( image == NULL )
275     return( double( 0 ) );
276
277   double r[ 2 ];
278   image->GetScalarRange( r );
279   return( r[ 1 ] - r[ 0 ] );
280 }
281
282 // -------------------------------------------------------------------------
283 double cpExtensions::Visualization::MPRActors::
284 GetMinLevel( unsigned int i ) const
285 {
286   // Check if the input has been configured
287   vtkImageData* image = this->_Image( i );
288   if( image == NULL )
289     return( double( 0 ) );
290
291   double r[ 2 ];
292   image->GetScalarRange( r );
293   return( r[ 0 ] );
294 }
295
296 // -------------------------------------------------------------------------
297 double cpExtensions::Visualization::MPRActors::
298 GetMaxLevel( unsigned int i ) const
299 {
300   // Check if the input has been configured
301   vtkImageData* image = this->_Image( i );
302   if( image == NULL )
303     return( double( 0 ) );
304
305   double r[ 2 ];
306   image->GetScalarRange( r );
307   return( r[ 1 ] );
308 }
309
310 // -------------------------------------------------------------------------
311 double cpExtensions::Visualization::MPRActors::
312 GetWindow( unsigned int i ) const
313 {
314   vtkWindowLevelLookupTable* lut =
315     dynamic_cast< vtkWindowLevelLookupTable* >( this->GetLookupTable( i ) );
316   if( lut != NULL )
317     return( lut->GetWindow( ) );
318   else
319     return( double( 0 ) );
320 }
321
322 // -------------------------------------------------------------------------
323 double cpExtensions::Visualization::MPRActors::
324 GetLevel( unsigned int i ) const
325 {
326   vtkWindowLevelLookupTable* lut =
327     dynamic_cast< vtkWindowLevelLookupTable* >( this->GetLookupTable( i ) );
328   if( lut != NULL )
329     return( lut->GetLevel( ) );
330   else
331     return( double( 0 ) );
332 }
333
334 // -------------------------------------------------------------------------
335 void cpExtensions::Visualization::MPRActors::
336 SetWindow( unsigned int i, const double& w )
337 {
338   vtkWindowLevelLookupTable* lut =
339     dynamic_cast< vtkWindowLevelLookupTable* >( this->GetLookupTable( i ) );
340   if( lut != NULL )
341   {
342     lut->SetWindow( w );
343     lut->Build( );
344     this->ImageMaps[ i ]->Modified( );
345     this->Modified( );
346
347   } // fi
348 }
349
350 // -------------------------------------------------------------------------
351 void cpExtensions::Visualization::MPRActors::
352 SetLevel( unsigned int i, const double& l )
353 {
354   vtkWindowLevelLookupTable* lut =
355     dynamic_cast< vtkWindowLevelLookupTable* >( this->GetLookupTable( i ) );
356   if( lut != NULL )
357   {
358     lut->SetLevel( l );
359     lut->Build( );
360     this->ImageMaps[ i ]->Modified( );
361     this->Modified( );
362
363   } // fi
364 }
365
366 // -------------------------------------------------------------------------
367 void cpExtensions::Visualization::MPRActors::
368 SetWindowLevel( unsigned int i, const double& w, const double& l )
369 {
370   vtkWindowLevelLookupTable* lut =
371     dynamic_cast< vtkWindowLevelLookupTable* >( this->GetLookupTable( i ) );
372   if( lut != NULL )
373   {
374     lut->SetWindow( w );
375     lut->SetLevel( l );
376     lut->Build( );
377     this->ImageMaps[ i ]->Modified( );
378
379     for( unsigned int j = 0; j < 3; ++j )
380       this->Slices[ 0 ][ j ]->UpdateText( w, l );
381
382     this->Modified( );
383
384   } // fi
385 }
386
387 // -------------------------------------------------------------------------
388 void cpExtensions::Visualization::MPRActors::
389 ResetWindowLevel( unsigned int i )
390 {
391   vtkImageData* image = this->_Image( i );
392   vtkWindowLevelLookupTable* lut =
393     dynamic_cast< vtkWindowLevelLookupTable* >( this->GetLookupTable( i ) );
394   if( image != NULL && lut != NULL )
395   {
396     double r[ 2 ];
397     image->GetScalarRange( r );
398     lut->SetTableRange( r );
399     lut->SetWindow( r[ 1 ] - r[ 0 ] );
400     lut->SetLevel( ( r[ 1 ] + r[ 0 ] ) / double( 2 ) );
401     lut->Build( );
402     this->ImageMaps[ i ]->Modified( );
403     this->Modified( );
404
405   } // fi
406 }
407
408 // -------------------------------------------------------------------------
409 void cpExtensions::Visualization::MPRActors::
410 SetLookupTableToColor(
411   unsigned int i, const double& r, const double& g, const double& b
412   )
413 {
414   static const double _0 = double( 0 );
415   static const double _1 = double( 1 );
416   static const double _2 = double( 2 );
417   static const double _4 = double( 4 );
418   static const double _6 = double( 6 );
419   static const double _OPACITY = double( 0.6 );
420
421   // Check if the input has been configured
422   vtkImageData* image = this->_Image( i );
423   if( image == NULL )
424     return;
425
426   double range[ 2 ];
427   image->GetScalarRange( range );
428
429   // Get HSV from display color
430   double cmax = ( r > g )? r: g; cmax = ( b > cmax )? b: cmax;
431   double cmin = ( r < g )? r: g; cmin = ( b < cmin )? b: cmin;
432   double d = cmax - cmin;
433
434   double saturation = ( std::fabs( cmax ) > _0 )? d / cmax: _0;
435   double value = cmax;
436   double hue = _0;
437   if( d > _0 )
438   {
439     if( r == cmax )
440       hue = std::fmod( ( g - b ) / d, _6 );
441     else if( g == cmax )
442       hue = ( ( b - r ) / d ) + _2;
443     else if( b == cmax )
444       hue = ( ( r - g ) / d ) + _4;
445     hue *= _1 / _6;
446     
447   } // fi
448
449   // Define new lookup table
450   vtkSmartPointer< vtkLookupTable > lut =
451     vtkSmartPointer< vtkLookupTable >::New( );
452   lut->SetScaleToLinear( );
453   lut->SetAboveRangeColor( _0, _0, _0, _0 );
454   lut->SetBelowRangeColor( _0, _0, _0, _0 );
455   lut->SetNanColor( _0, _0, _0, _0 );
456   lut->SetTableRange( range[ 0 ], range[ 1 ] );
457   lut->SetAlphaRange( _0, _OPACITY );
458   lut->SetHueRange( _0, hue );
459   lut->SetSaturationRange( _0, saturation );
460   lut->SetValueRange( _0, value );
461   lut->Build( );
462
463   this->SetLookupTable( i, lut );
464 }
465
466 // -------------------------------------------------------------------------
467 int cpExtensions::Visualization::MPRActors::
468 GetSliceNumberMinValue( const int& axis ) const
469 {
470   return( this->Slices[ 0 ][ axis ]->GetSliceNumberMinValue( ) );
471 }
472
473 // -------------------------------------------------------------------------
474 int cpExtensions::Visualization::MPRActors::
475 GetSliceNumberMaxValue( const int& axis ) const
476 {
477   return( this->Slices[ 0 ][ axis ]->GetSliceNumberMaxValue( ) );
478 }
479
480 // -------------------------------------------------------------------------
481 int cpExtensions::Visualization::MPRActors::
482 GetSlice( const int& axis ) const
483 {
484   return( this->Slices[ 0 ][ axis ]->GetSliceNumber( ) );
485 }
486
487 // -------------------------------------------------------------------------
488 void cpExtensions::Visualization::MPRActors::
489 SetSlice( const int& axis, const int& slice )
490 {
491   vtkImageData* image = this->_Image( 0 );
492   if( image == NULL )
493     return;
494
495   // Get image data extent
496   int ext[ 6 ];
497   image->GetExtent( ext );
498
499   // Check if the slice is valid
500   int real = slice;
501   if( slice < ext[ axis << 1 ] )
502     real = ext[ axis << 1 ];
503   if( ext[ ( axis << 1 ) + 1 ] < slice )
504     real = ext[ ( axis << 1 ) + 1 ];
505
506   // Change slice
507   this->Slices[ 0 ][ axis ]->SetSliceNumber( real );
508   this->Slices[ 1 ][ axis ]->SetSliceNumber( real );
509   this->Modified( );
510 }
511
512 // -------------------------------------------------------------------------
513 void cpExtensions::Visualization::MPRActors::
514 SetSlice( const int& axis, const double& slice )
515 {
516   vtkImageData* image = this->_Image( 0 );
517   if( image == NULL )
518     return;
519
520   double x[ 3 ] = { double( 0 ) };
521   double pcoords[ 3 ];
522   int ijk[ 3 ];
523
524   x[ axis ] = slice;
525   image->ComputeStructuredCoordinates( x, ijk, pcoords );
526   this->SetSlice( axis, ijk[ axis ] );
527 }
528
529 // -------------------------------------------------------------------------
530 void cpExtensions::Visualization::MPRActors::
531 ResetSlices( )
532 {
533   for( unsigned int i = 0; i < 2; ++i )
534     for( unsigned int j = 0; j < 3; ++j )
535       this->Slices[ i ][ j ]->SetSliceNumber(
536         this->Slices[ i ][ j ]->GetSliceNumberMinValue( )
537         );
538 }
539
540 // -------------------------------------------------------------------------
541 cpExtensions::Visualization::MPRActors::
542 MPRActors( )
543   : Superclass( )
544 {
545   this->ImageOutlineActor = vtkSmartPointer< vtkActor >::New( );
546   for( unsigned int i = 0; i < 2; ++i )
547     for( unsigned int j = 0; j < 3; ++j )
548       this->Slices[ i ][ j ] = vtkSmartPointer< ImageSliceActors >::New( );
549 }
550
551 // -------------------------------------------------------------------------
552 cpExtensions::Visualization::MPRActors::
553 ~MPRActors( )
554 {
555 }
556
557 // -------------------------------------------------------------------------
558 vtkImageData* cpExtensions::Visualization::MPRActors::
559 _Image( unsigned int i ) const
560 {
561   if( i < this->ImageMaps.size( ) )
562   {
563     vtkAlgorithm* algo = this->ImageMaps[ i ]->GetInputAlgorithm( );
564     vtkInformation* info = algo->GetOutputInformation( 0 );
565     return(
566       vtkImageData::SafeDownCast(
567         info->Get( vtkDataObject::DATA_OBJECT( ) )
568         )
569       );
570   }
571   else
572     return( NULL );
573 }
574
575 // -------------------------------------------------------------------------
576 void cpExtensions::Visualization::MPRActors::
577 _Update( unsigned int i )
578 {
579   // Check if the input has been configured
580   vtkImageData* image = this->_Image( i );
581   if( image == NULL )
582     return;
583   this->ImageMaps[ i ]->Update( );
584
585   for( int j = 0; j < 2; ++j )
586   {
587     for( int k = 0; k < 3; ++k )
588     {
589       this->Slices[ j ][ k ]->AddInputConnection(
590         this->ImageMaps[ i ]->GetOutputPort( ), k
591         );
592       this->Slices[ j ][ k ]->UpdateText( );
593
594       // Add all of slice's props
595       this->Slices[ j ][ k ]->InitTraversal( );
596       vtkProp* prop = this->Slices[ j ][ k ]->GetNextProp( );
597       while( prop != NULL )
598       {
599         this->AddItem( prop );
600         prop = this->Slices[ j ][ k ]->GetNextProp( );
601
602       } // elihw
603
604     } // rof
605
606   } // rof
607
608   if( i == 0 )
609   {
610     // Create 3D outline
611     double bb[ 6 ];
612     image->GetBounds( bb );
613
614     vtkSmartPointer< vtkOutlineSource > img_ol =
615       vtkSmartPointer< vtkOutlineSource >::New( );
616     img_ol->SetBounds( bb );
617
618     vtkSmartPointer< vtkPolyDataMapper > img_ol_mapper =
619       vtkSmartPointer< vtkPolyDataMapper >::New( );
620     img_ol_mapper->SetInputConnection( img_ol->GetOutputPort( ) );
621     this->ImageOutlineActor->SetMapper( img_ol_mapper );
622     this->ImageOutlineActor->GetProperty( )->SetColor( 1, 1, 1 );
623     this->ImageOutlineActor->GetProperty( )->SetLineWidth( 1 );
624
625     this->AddItem( this->ImageOutlineActor );
626
627   } // fi
628 }
629
630 // eof - $RCSfile$