]> Creatis software - cpPlugins.git/blob - lib/cpExtensions/Visualization/ImageSliceActors.cxx
Minor refactoring and errors solved
[cpPlugins.git] / lib / cpExtensions / Visualization / ImageSliceActors.cxx
1 #include <cpExtensions/Visualization/ImageSliceActors.h>
2
3 #include <cmath>
4 #include <sstream>
5
6 #include <vtkAlgorithmOutput.h>
7 #include <vtkCamera.h>
8 #include <vtkCellArray.h>
9 #include <vtkImageData.h>
10 #include <vtkInformation.h>
11 #include <vtkPlane.h>
12 #include <vtkPoints.h>
13 #include <vtkProperty.h>
14 #include <vtkRenderer.h>
15 #include <vtkRendererCollection.h>
16 #include <vtkRenderWindow.h>
17 #include <vtkRenderWindowInteractor.h>
18 #include <vtkStreamingDemandDrivenPipeline.h>
19 #include <vtkTextProperty.h>
20 #include <vtkWindowLevelLookupTable.h>
21
22 // -------------------------------------------------------------------------
23 cpExtensions::Visualization::ImageSliceActors*
24 cpExtensions::Visualization::ImageSliceActors::
25 New( )
26 {
27   return( new Self( ) );
28 }
29
30 // -------------------------------------------------------------------------
31 void cpExtensions::Visualization::ImageSliceActors::
32 AddSlicesCommand( TCursorCommand command, void* data )
33 {
34   this->m_SlicesCommands.push_back(
35     std::pair< TCursorCommand, void* >( command, data )
36     );
37   this->Modified( );
38 }
39
40 // -------------------------------------------------------------------------
41 void cpExtensions::Visualization::ImageSliceActors::
42 AddSeedCommand( TCursorCommand command, void* data )
43 {
44   this->m_SeedCommands.push_back(
45     std::pair< TCursorCommand, void* >( command, data )
46     );
47   this->Modified( );
48 }
49
50 // -------------------------------------------------------------------------
51 void cpExtensions::Visualization::ImageSliceActors::
52 AddInputConnection( vtkAlgorithmOutput* aout, int axis )
53 {
54   // Get input vtkImageData
55   if( aout == NULL )
56     return;
57   vtkAlgorithm* producer = aout->GetProducer( );
58   vtkImageData* data = dynamic_cast< vtkImageData* >(
59     producer->GetOutputDataObject( aout->GetIndex( ) )
60     );
61   if( data == NULL )
62     return;
63
64   // Try to infere if input comes from a color mapping filter
65   vtkImageMapToColors* new_map =
66     dynamic_cast< vtkImageMapToColors* >( producer );
67   if( new_map == NULL )
68   {
69     // Configure LUT, if possible (NULL is returned if not)
70     this->_ConfigureNewLUT( data );
71     new_map = *( this->m_ImageMaps.rbegin( ) );
72     if( new_map != NULL )
73     {
74       new_map->SetInputConnection( aout );
75       new_map->Update( );
76
77     } // fi
78   }
79   else
80     this->m_ImageMaps.push_back( new_map );
81   
82   // Create mapper and actors
83   vtkSmartPointer< vtkImageSliceMapper > mapper =
84     vtkSmartPointer< vtkImageSliceMapper >::New( );
85   if( new_map != NULL )
86     mapper->SetInputConnection( new_map->GetOutputPort( ) );
87   else
88     mapper->SetInputConnection( aout );
89   this->m_SliceMappers.push_back( mapper );
90   this->_ConfigureNewInput( axis );
91 }
92
93 // -------------------------------------------------------------------------
94 void cpExtensions::Visualization::ImageSliceActors::
95 AddInputData( vtkImageData* data, int axis )
96 {
97   // Configure LUT, if possible (NULL is returned if not)
98   this->_ConfigureNewLUT( data );
99   vtkImageMapToColors* new_map = *( this->m_ImageMaps.rbegin( ) );
100   if( new_map != NULL )
101   {
102     new_map->SetInputData( data );
103     new_map->Update( );
104
105   } // fi
106
107   // Create mapper and actors
108   vtkSmartPointer< vtkImageSliceMapper > mapper =
109     vtkSmartPointer< vtkImageSliceMapper >::New( );
110   if( new_map != NULL )
111     mapper->SetInputConnection( new_map->GetOutputPort( ) );
112   else
113     mapper->SetInputData( data );
114   this->m_SliceMappers.push_back( mapper );
115   this->_ConfigureNewInput( axis );
116 }
117
118 // -------------------------------------------------------------------------
119 void cpExtensions::Visualization::ImageSliceActors::
120 Clear( )
121 {
122   // Unbind from container
123   this->RemoveAllItems( );
124
125   // Delete all images
126   this->m_ImageMaps.clear( );
127   this->m_SliceMappers.clear( );
128   this->m_ImageActors.clear( );
129   this->m_AssociatedSlices.clear( );
130   this->m_AssociatedActors.clear( );
131
132   // Reconfigure unique objects
133   this->m_Cursor        = vtkSmartPointer< vtkPolyData >::New( );
134   this->m_CursorMapper  = vtkSmartPointer< vtkPolyDataMapper >::New( );
135   this->m_CursorActor   = vtkSmartPointer< vtkActor >::New( );
136   this->m_PlaneFunction = vtkSmartPointer< vtkPlane >::New( );
137   this->m_Plane         = vtkSmartPointer< vtkPolyData >::New( );
138   this->m_PlaneMapper   = vtkSmartPointer< vtkPolyDataMapper >::New( );
139   this->m_TextActor     = vtkSmartPointer< vtkTextActor >::New( );
140   this->m_PlaneActor    = vtkSmartPointer< vtkActor >::New( );
141   this->m_TextBuffer[ 0 ] = '\0';
142
143   // Unique objects configuration
144   vtkSmartPointer< vtkPoints > cursor_points =
145     vtkSmartPointer< vtkPoints >::New( );
146   vtkSmartPointer< vtkCellArray > cursor_lines =
147     vtkSmartPointer< vtkCellArray >::New( );
148   cursor_points->InsertNextPoint( 0, 0, 0 );
149   cursor_points->InsertNextPoint( 0, 0, 0 );
150   cursor_points->InsertNextPoint( 0, 0, 0 );
151   cursor_points->InsertNextPoint( 0, 0, 0 );
152   cursor_points->InsertNextPoint( 0, 0, 0 );
153   cursor_points->InsertNextPoint( 0, 0, 0 );
154   cursor_points->InsertNextPoint( 0, 0, 0 );
155   cursor_points->InsertNextPoint( 0, 0, 0 );
156   cursor_lines->InsertNextCell( 2 );
157   cursor_lines->InsertCellPoint( 0 );
158   cursor_lines->InsertCellPoint( 1 );
159   cursor_lines->InsertNextCell( 2 );
160   cursor_lines->InsertCellPoint( 2 );
161   cursor_lines->InsertCellPoint( 3 );
162   cursor_lines->InsertNextCell( 2 );
163   cursor_lines->InsertCellPoint( 4 );
164   cursor_lines->InsertCellPoint( 5 );
165   cursor_lines->InsertNextCell( 2 );
166   cursor_lines->InsertCellPoint( 6 );
167   cursor_lines->InsertCellPoint( 7 );
168   this->m_Cursor->SetPoints( cursor_points );
169   this->m_Cursor->SetLines( cursor_lines );
170   this->m_CursorMapper->SetInputData( this->m_Cursor );
171   this->m_CursorActor->SetMapper( this->m_CursorMapper );
172
173   vtkSmartPointer< vtkPoints > plane_points =
174     vtkSmartPointer< vtkPoints >::New( );
175   vtkSmartPointer< vtkCellArray > plane_lines =
176     vtkSmartPointer< vtkCellArray >::New( );
177
178   plane_points->InsertNextPoint( 0, 0, 0 );
179   plane_points->InsertNextPoint( 0, 1, 0 );
180   plane_points->InsertNextPoint( 1, 1, 0 );
181   plane_points->InsertNextPoint( 1, 0, 0 );
182   plane_lines->InsertNextCell( 5 );
183   plane_lines->InsertCellPoint( 0 );
184   plane_lines->InsertCellPoint( 1 );
185   plane_lines->InsertCellPoint( 2 );
186   plane_lines->InsertCellPoint( 3 );
187   plane_lines->InsertCellPoint( 0 );
188   this->m_Plane->SetPoints( plane_points );
189   this->m_Plane->SetLines( plane_lines );
190
191   this->m_PlaneMapper->SetInputData( this->m_Plane );
192   this->m_PlaneActor->SetMapper( this->m_PlaneMapper );
193
194   this->m_TextActor->SetTextScaleModeToNone( );
195   vtkTextProperty* textprop = this->m_TextActor->GetTextProperty( );
196   textprop->SetColor( 1, 1, 1 );
197   textprop->SetFontFamilyToCourier( );
198   textprop->SetFontSize( 18 );
199   textprop->BoldOff( );
200   textprop->ItalicOff( );
201   textprop->ShadowOff( );
202   textprop->SetJustificationToLeft( );
203   textprop->SetVerticalJustificationToBottom( );
204   vtkCoordinate* coord = this->m_TextActor->GetPositionCoordinate( );
205   coord->SetCoordinateSystemToNormalizedViewport( );
206   coord->SetValue( 0.01, 0.01 );
207
208   // Update actor collection
209   this->AddItem( this->m_CursorActor );
210   this->AddItem( this->m_TextActor );
211   this->AddItem( this->m_PlaneActor );
212 }
213
214 // -------------------------------------------------------------------------
215 void cpExtensions::Visualization::ImageSliceActors::
216 AssociateSlice( Self* other )
217 {
218   this->m_AssociatedSlices.push_back( other );
219   this->Modified( );
220 }
221
222 // -------------------------------------------------------------------------
223 vtkInteractorStyle* cpExtensions::Visualization::ImageSliceActors::
224 GetStyle( )
225 {
226   return( this->m_Style.GetPointer( ) );
227 }
228
229 // -------------------------------------------------------------------------
230 const vtkInteractorStyle* cpExtensions::Visualization::ImageSliceActors::
231 GetStyle( ) const
232 {
233   return( this->m_Style.GetPointer( ) );
234 }
235
236 // -------------------------------------------------------------------------
237 void cpExtensions::Visualization::ImageSliceActors::
238 PushActorsInto( vtkRenderWindow* window, bool force_style )
239 {
240   if( window == NULL )
241     return;
242   vtkRenderWindowInteractor* rwi = window->GetInteractor( );
243   vtkRenderer* renderer = window->GetRenderers( )->GetFirstRenderer( );
244   if( rwi == NULL || renderer == NULL )
245     return;
246   
247   // Update style
248   if( this->m_Style.GetPointer( ) != NULL && force_style )
249     rwi->SetInteractorStyle( this->m_Style );
250
251   // Update actors
252   vtkProp* prop;
253   this->InitTraversal( );
254   while( prop = this->GetNextProp( ) )
255     renderer->AddViewProp( prop );
256   renderer->Modified( );
257
258   // Configure camera
259   vtkCamera* camera = renderer->GetActiveCamera( );
260   if( camera != NULL && force_style )
261   {
262     // Parallel projections are better when displaying 2D images
263     int axis = this->GetAxis( );
264     camera->ParallelProjectionOn( );
265     camera->SetFocalPoint( double( 0 ), double( 0 ), double( 0 ) );
266     if( axis == 0 )
267     {
268       camera->SetPosition( double( 1 ), double( 0 ), double( 0 ) );
269       camera->SetViewUp  ( double( 0 ), double( 1 ), double( 0 ) );
270     }
271     else if( axis == 1 )
272     {
273       camera->SetPosition( double( 0 ), double( 1 ), double(  0 ) );
274       camera->SetViewUp  ( double( 0 ), double( 0 ), double( -1 ) );
275     }
276     else // if( axis == 2 )
277     {
278       camera->SetPosition( double( 0 ), double( 0 ), double( 1 ) );
279       camera->SetViewUp  ( double( 0 ), double( 1 ), double( 0 ) );
280
281     } // fi
282
283   } // fi
284   renderer->ResetCamera( );
285   rwi->Render( );
286 }
287
288 // -------------------------------------------------------------------------
289 void cpExtensions::Visualization::ImageSliceActors::
290 PopActorsFrom( vtkRenderWindow* window )
291 {
292   vtkRenderWindowInteractor* rwi = window->GetInteractor( );
293   vtkRenderer* renderer = window->GetRenderers( )->GetFirstRenderer( );
294
295   if( renderer != NULL )
296   {
297     // Update actors
298     vtkProp* prop;
299     this->InitTraversal( );
300     while( prop = this->GetNextProp( ) )
301       renderer->RemoveViewProp( prop );
302     renderer->Modified( );
303
304   } // fi
305   if( rwi != NULL )
306     rwi->Render( );
307 }
308
309 // -------------------------------------------------------------------------
310 unsigned int cpExtensions::Visualization::ImageSliceActors::
311 GetNumberOfImageActors( ) const
312 {
313   return( this->m_ImageActors.size( ) );
314 }
315
316 // -------------------------------------------------------------------------
317 vtkImageActor* cpExtensions::Visualization::ImageSliceActors::
318 GetImageActor( unsigned int id )
319 {
320   if( id < this->m_ImageActors.size( ) )
321     return( this->m_ImageActors[ id ] );
322   else
323     return( NULL );
324 }
325
326 // -------------------------------------------------------------------------
327 const vtkImageActor* cpExtensions::Visualization::ImageSliceActors::
328 GetImageActor( unsigned int id ) const
329 {
330   if( id < this->m_ImageActors.size( ) )
331     return( this->m_ImageActors[ id ] );
332   else
333     return( NULL );
334 }
335
336 // -------------------------------------------------------------------------
337 vtkTextActor* cpExtensions::Visualization::ImageSliceActors::
338 GetTextActor( )
339 {
340   return( this->m_TextActor );
341 }
342
343 // -------------------------------------------------------------------------
344 const vtkTextActor* cpExtensions::Visualization::ImageSliceActors::
345 GetTextActor( ) const
346 {
347   return( this->m_TextActor );
348 }
349
350 // -------------------------------------------------------------------------
351 vtkActor* cpExtensions::Visualization::ImageSliceActors::
352 GetPlaneActor( )
353 {
354   return( this->m_PlaneActor );
355 }
356
357 // -------------------------------------------------------------------------
358 const vtkActor* cpExtensions::Visualization::ImageSliceActors::
359 GetPlaneActor( ) const
360 {
361   return( this->m_PlaneActor );
362 }
363
364 // -------------------------------------------------------------------------
365 vtkPlane* cpExtensions::Visualization::ImageSliceActors::
366 GetPlaneFunction( )
367 {
368   return( this->m_PlaneFunction );
369 }
370
371 // -------------------------------------------------------------------------
372 const vtkPlane* cpExtensions::Visualization::ImageSliceActors::
373 GetPlaneFunction( ) const
374 {
375   return( this->m_PlaneFunction );
376 }
377
378 // -------------------------------------------------------------------------
379 void cpExtensions::Visualization::ImageSliceActors::
380 AddActor( vtkAlgorithm* algorithm, vtkActor* actor )
381 {
382   this->m_AssociatedActors.push_back( TAssociatedActor( algorithm, actor ) );
383   this->AddItem( actor );
384 }
385
386 // -------------------------------------------------------------------------
387 void cpExtensions::Visualization::ImageSliceActors::
388 AddActor( vtkActor* actor )
389 {
390   this->AddActor( NULL, actor );
391 }
392
393 // -------------------------------------------------------------------------
394 void cpExtensions::Visualization::ImageSliceActors::
395 SetInterpolate( bool v )
396 {
397   if( this->m_Interpolate != v )
398   {
399     for( unsigned int i = 0; i < this->m_ImageActors.size( ); ++i )
400       this->m_ImageActors[ i ]->SetInterpolate( v );
401     this->m_Interpolate = v;
402     this->Modified( );
403
404   } // fi
405 }
406
407 // -------------------------------------------------------------------------
408 void cpExtensions::Visualization::ImageSliceActors::
409 InterpolateOn( )
410 {
411   this->SetInterpolate( true );
412 }
413
414 // -------------------------------------------------------------------------
415 void cpExtensions::Visualization::ImageSliceActors::
416 InterpolateOff( )
417 {
418   this->SetInterpolate( false );
419 }
420
421 // -------------------------------------------------------------------------
422 double* cpExtensions::Visualization::ImageSliceActors::
423 GetDisplayBounds( ) const
424 {
425   if( this->m_ImageActors.size( ) > 0 )
426     return( this->m_ImageActors[ 0 ]->GetDisplayBounds( ) );
427   else
428     return( NULL );
429 }
430
431 // -------------------------------------------------------------------------
432 void cpExtensions::Visualization::ImageSliceActors::
433 GetDisplayBounds( double bounds[ 6 ] ) const
434 {
435   if( this->m_ImageActors.size( ) == 0 )
436   {
437     bounds[ 0 ] = bounds[ 2 ] = bounds[ 4 ] = double( -1 );
438     bounds[ 1 ] = bounds[ 3 ] = bounds[ 5 ] = double( -1 );
439   }
440   else
441     this->m_ImageActors[ 0 ]->GetDisplayBounds( bounds );
442 }
443
444 // -------------------------------------------------------------------------
445 void cpExtensions::Visualization::ImageSliceActors::
446 ResetCursor( )
447 {
448   vtkPoints* points = this->m_Cursor->GetPoints( );
449   points->SetPoint( 0, 0, 0, 0 );
450   points->SetPoint( 1, 0, 0, 0 );
451   points->SetPoint( 2, 0, 0, 0 );
452   points->SetPoint( 3, 0, 0, 0 );
453   points->SetPoint( 4, 0, 0, 0 );
454   points->SetPoint( 5, 0, 0, 0 );
455   points->SetPoint( 6, 0, 0, 0 );
456   points->SetPoint( 7, 0, 0, 0 );
457   this->m_Cursor->Modified( );
458   this->m_CursorMapper->Modified( );
459   this->m_CursorActor->Modified( );
460 }
461
462 // -------------------------------------------------------------------------
463 void cpExtensions::Visualization::ImageSliceActors::
464 SetCursor( double pos[ 3 ] )
465 {
466   if( this->m_SliceMappers.size( ) == 0 )
467     return;
468
469   // Get ordered axes
470   int a0 = this->GetAxis( );
471   int a1 = ( a0 + 1 ) % 3;
472   int a2 = ( a0 + 2 ) % 3;
473   int ma0 = a0 << 1;
474   int ma1 = a1 << 1;
475   int ma2 = a2 << 1;
476
477   double bounds[ 6 ];
478   this->m_SliceMappers[ 0 ]->GetInput( )->GetBounds( bounds );
479
480   double
481     p0[ 3 ], p1[ 3 ], p2[ 3 ], p3[ 3 ],
482     p4[ 3 ], p5[ 3 ], p6[ 3 ], p7[ 3 ];
483
484   p0[ a2 ] = p1[ a2 ] = p4[ a2 ] = p5[ a2 ] = pos[ a2 ];
485   p2[ a1 ] = p3[ a1 ] = p6[ a1 ] = p7[ a1 ] = pos[ a1 ];
486   p0[ a0 ] = p1[ a0 ] = p2[ a0 ] = p3[ a0 ] = bounds[ ma0 ];
487   p4[ a0 ] = p5[ a0 ] = p6[ a0 ] = p7[ a0 ] = bounds[ ma0 + 1 ];
488   p0[ a1 ] = p4[ a1 ] = bounds[ ma1 ];
489   p1[ a1 ] = p5[ a1 ] = bounds[ ma1 + 1 ];
490   p2[ a2 ] = p6[ a2 ] = bounds[ ma2 ];
491   p3[ a2 ] = p7[ a2 ] = bounds[ ma2 + 1 ];
492
493   vtkPoints* points = this->m_Cursor->GetPoints( );
494   points->SetPoint( 0, p0 );
495   points->SetPoint( 1, p1 );
496   points->SetPoint( 2, p2 );
497   points->SetPoint( 3, p3 );
498   points->SetPoint( 4, p4 );
499   points->SetPoint( 5, p5 );
500   points->SetPoint( 6, p6 );
501   points->SetPoint( 7, p7 );
502   this->m_Cursor->Modified( );
503   this->m_CursorMapper->Modified( );
504   this->m_CursorActor->Modified( );
505 }
506
507 // -------------------------------------------------------------------------
508 vtkImageMapToColors* cpExtensions::Visualization::ImageSliceActors::
509 GetImageMap( unsigned int id )
510 {
511   if( id < this->m_ImageMaps.size( ) )
512     return( this->m_ImageMaps[ id ].GetPointer( ) );
513   else
514     return( NULL );
515 }
516
517 // -------------------------------------------------------------------------
518 const vtkImageMapToColors* cpExtensions::Visualization::ImageSliceActors::
519 GetImageMap( unsigned int id ) const
520 {
521   if( id < this->m_ImageMaps.size( ) )
522     return( this->m_ImageMaps[ id ].GetPointer( ) );
523   else
524     return( NULL );
525 }
526
527 // -------------------------------------------------------------------------
528 double cpExtensions::Visualization::ImageSliceActors::
529 GetMinWindow( ) const
530 {
531   return( this->m_MinWindow );
532 }
533
534 // -------------------------------------------------------------------------
535 double cpExtensions::Visualization::ImageSliceActors::
536 GetMaxWindow( ) const
537 {
538   return( this->m_MaxWindow );
539 }
540
541 // -------------------------------------------------------------------------
542 double cpExtensions::Visualization::ImageSliceActors::
543 GetMinLevel( ) const
544 {
545   return( this->m_MinLevel );
546 }
547
548 // -------------------------------------------------------------------------
549 double cpExtensions::Visualization::ImageSliceActors::
550 GetMaxLevel( ) const
551 {
552   return( this->m_MaxLevel );
553 }
554
555 // -------------------------------------------------------------------------
556 double cpExtensions::Visualization::ImageSliceActors::
557 GetWindow( ) const
558 {
559   if( this->m_ImageMaps.size( ) == 0 )
560     return( double( 0 ) );
561   if( this->m_ImageMaps[ 0 ].GetPointer( ) == NULL )
562     return( double( 0 ) );
563
564   vtkWindowLevelLookupTable* lut =
565     dynamic_cast< vtkWindowLevelLookupTable* >(
566       this->m_ImageMaps[ 0 ]->GetLookupTable( )
567       );
568   if( lut != NULL )
569     return( lut->GetWindow( ) );
570   else
571     return( double( 0 ) );
572 }
573
574 // -------------------------------------------------------------------------
575 double cpExtensions::Visualization::ImageSliceActors::
576 GetLevel( ) const
577 {
578   if( this->m_ImageMaps.size( ) == 0 )
579     return( double( 0 ) );
580   if( this->m_ImageMaps[ 0 ].GetPointer( ) == NULL )
581     return( double( 0 ) );
582
583   vtkWindowLevelLookupTable* lut =
584     dynamic_cast< vtkWindowLevelLookupTable* >(
585       this->m_ImageMaps[ 0 ]->GetLookupTable( )
586       );
587   if( lut != NULL )
588     return( lut->GetLevel( ) );
589   else
590     return( double( 0 ) );
591 }
592
593 // -------------------------------------------------------------------------
594 void cpExtensions::Visualization::ImageSliceActors::
595 SetWindow( double w )
596 {
597   if( this->m_ImageMaps.size( ) == 0 )
598     return;
599   if( this->m_ImageMaps[ 0 ].GetPointer( ) == NULL )
600     return;
601   vtkWindowLevelLookupTable* lut =
602     dynamic_cast< vtkWindowLevelLookupTable* >(
603       this->m_ImageMaps[ 0 ]->GetLookupTable( )
604       );
605   if( lut == NULL )
606     return;
607
608   /* TODO: Min and Max values are assigned 0!!!
609      if( w < this->MinWindow )
610      w = this->MinWindow;
611      if( w > this->MaxWindow )
612      w = this->MaxWindow;
613   */
614   lut->SetWindow( w );
615   lut->Build( );
616   this->m_ImageMaps[ 0 ]->Modified( );
617   this->Modified( );
618 }
619
620 // -------------------------------------------------------------------------
621 void cpExtensions::Visualization::ImageSliceActors::
622 SetLevel( double l )
623 {
624   if( this->m_ImageMaps.size( ) == 0 )
625     return;
626   if( this->m_ImageMaps[ 0 ].GetPointer( ) == NULL )
627     return;
628   vtkWindowLevelLookupTable* lut =
629     dynamic_cast< vtkWindowLevelLookupTable* >(
630       this->m_ImageMaps[ 0 ]->GetLookupTable( )
631       );
632   if( lut == NULL )
633     return;
634
635   /* TODO: Min and Max values are assigned 0!!!
636      if( l < this->MinLevel )
637      l = this->MinLevel;
638      if( l > this->MaxLevel )
639      l = this->MaxLevel;
640   */
641   lut->SetLevel( l );
642   lut->Build( );
643   this->m_ImageMaps[ 0 ]->Modified( );
644   this->Modified( );
645 }
646
647 // -------------------------------------------------------------------------
648 void cpExtensions::Visualization::ImageSliceActors::
649 SetWindowLevel( double w, double l )
650 {
651   if( this->m_ImageMaps.size( ) == 0 )
652     return;
653   if( this->m_ImageMaps[ 0 ].GetPointer( ) == NULL )
654     return;
655   vtkWindowLevelLookupTable* lut =
656     dynamic_cast< vtkWindowLevelLookupTable* >(
657       this->m_ImageMaps[ 0 ]->GetLookupTable( )
658       );
659   if( lut == NULL )
660     return;
661
662   /* TODO: Min and Max values are assigned 0!!!
663      if( w < this->MinWindow )
664      w = this->MinWindow;
665      if( w > this->MaxWindow )
666      w = this->MaxWindow;
667      if( l < this->MinLevel )
668      l = this->MinLevel;
669      if( l > this->MaxLevel )
670      l = this->MaxLevel;
671   */
672   lut->SetWindow( w );
673   lut->SetLevel( l );
674   lut->Build( );
675   this->m_ImageMaps[ 0 ]->Modified( );
676   this->UpdateText( w, l );
677   this->Modified( );
678 }
679
680 // -------------------------------------------------------------------------
681 void cpExtensions::Visualization::ImageSliceActors::
682 ResetWindowLevel( )
683 {
684   static const double _2 = double( 2 );
685   this->SetWindowLevel(
686     this->m_MaxWindow, ( this->m_MaxLevel + this->m_MinLevel ) / _2
687     );
688 }
689
690 // -------------------------------------------------------------------------
691 void cpExtensions::Visualization::ImageSliceActors::
692 SetLookupTable( unsigned int id, vtkLookupTable* lut )
693 {
694   if( id < this->m_ImageMaps.size( ) && id > 0 )
695   {
696     if( this->m_ImageMaps[ id ].GetPointer( ) != NULL )
697     {
698       this->m_ImageMaps[ id ]->SetLookupTable( lut );
699       this->m_ImageMaps[ id ]->Modified( );
700       this->Modified( );
701
702     } // fi
703
704   } // fi
705 }
706
707 // -------------------------------------------------------------------------
708 void cpExtensions::Visualization::ImageSliceActors::
709 SetLookupTableAsColor( unsigned int id, double r, double g, double b )
710 {
711   static const double _0 = double( 0 );
712   static const double _2 = double( 2 );
713   static const double _4 = double( 4 );
714   static const double _6 = double( 6 );
715   static const double _OPACITY = double( 0.6 );
716
717   // Check ID consistency
718   if( id == 0 || id >= this->m_ImageMaps.size( ) )
719     return;
720
721   // Get image scalar range
722   vtkAlgorithmOutput* aout = this->m_ImageMaps[ id ]->GetOutputPort( );
723   vtkImageData* image = dynamic_cast< vtkImageData* >(
724     aout->GetProducer( )->GetOutputDataObject( aout->GetIndex( ) )
725     );
726   double range[ 2 ];
727   image->GetScalarRange( range );
728
729   // Get HSV from display color
730   double cmax = ( r > g )? r: g; cmax = ( b > cmax )? b: cmax;
731   double cmin = ( r < g )? r: g; cmin = ( b < cmin )? b: cmin;
732   double d = cmax - cmin;
733
734   double saturation = ( std::fabs( cmax ) > _0 )? d / cmax: _0;
735   double value = cmax;
736   double hue = _0;
737   if( d > _0 )
738   {
739     if( r == cmax )
740       hue = std::fmod( ( g - b ) / d, _6 );
741     else if( g == cmax )
742       hue = ( ( b - r ) / d ) + _2;
743     else if( b == cmax )
744       hue = ( ( r - g ) / d ) + _4;
745     hue /= _6;
746
747   } // fi
748
749   // Define new lookup table
750   vtkSmartPointer< vtkLookupTable > lut =
751     vtkSmartPointer< vtkLookupTable >::New( );
752   lut->SetScaleToLinear( );
753   lut->SetNanColor( _0, _0, _0, _0 );
754   lut->SetTableRange( range[ 0 ], range[ 1 ] );
755   lut->SetAlphaRange( _0, _OPACITY );
756   lut->SetHueRange( _0, hue );
757   lut->SetSaturationRange( _0, saturation );
758   lut->SetValueRange( _0, value );
759   lut->Build( );
760   this->SetLookupTable( id, lut );
761 }
762
763 // -------------------------------------------------------------------------
764 int cpExtensions::Visualization::ImageSliceActors::
765 GetAxis( ) const
766 {
767   if( this->m_SliceMappers.size( ) > 0 )
768     return( this->m_SliceMappers[ 0 ]->GetOrientation( ) );
769   else
770     return( -1 );
771 }
772
773 // -------------------------------------------------------------------------
774 int cpExtensions::Visualization::ImageSliceActors::
775 GetSliceNumber( ) const
776 {
777   if( this->m_SliceMappers.size( ) > 0 )
778     return( this->m_SliceMappers[ 0 ]->GetSliceNumber( ) );
779   else
780     return( -1 );
781 }
782
783 // -------------------------------------------------------------------------
784 int cpExtensions::Visualization::ImageSliceActors::
785 GetSliceNumberMinValue( ) const
786 {
787   if( this->m_SliceMappers.size( ) > 0 )
788     return( this->m_SliceMappers[ 0 ]->GetSliceNumberMinValue( ) );
789   else
790     return( -1 );
791 }
792
793 // -------------------------------------------------------------------------
794 int cpExtensions::Visualization::ImageSliceActors::
795 GetSliceNumberMaxValue( ) const
796 {
797   if( this->m_SliceMappers.size( ) > 0 )
798     return( this->m_SliceMappers[ 0 ]->GetSliceNumberMaxValue( ) );
799   else
800     return( -1 );
801 }
802
803 // -------------------------------------------------------------------------
804 void cpExtensions::Visualization::ImageSliceActors::
805 SetSliceNumber( const int& slice )
806 {
807   unsigned int nImages = this->m_SliceMappers.size( );
808   if( nImages == 0 )
809     return;
810
811   // Change visualization extent
812   for( unsigned int i = 0; i < nImages; ++i )
813   {
814     this->m_SliceMappers[ i ]->SetSliceNumber( slice );
815     this->m_SliceMappers[ i ]->Modified( );
816     this->m_ImageActors[ i ]->Modified( );
817     this->m_SliceMappers[ i ]->Update( );
818
819   } // rof
820
821   // Compute plane
822   vtkAlgorithm* algo = this->m_SliceMappers[ 0 ]->GetInputAlgorithm( );
823   vtkInformation* info = algo->GetOutputInformation( 0 );
824   int ext[ 6 ];
825   double ori[ 3 ], spac[ 3 ], pos[ 3 ];
826   info->Get( vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT( ), ext );
827   info->Get( vtkDataObject::ORIGIN( ), ori );
828   info->Get( vtkDataObject::SPACING( ), spac );
829   this->m_SliceMappers[ 0 ]->GetSlicePlane( )->GetOrigin( pos );
830
831   // Prevent obscuring voxels by offsetting the plane geometry
832   double xbnds[ ] =
833     {
834       ori[ 0 ] + ( spac[ 0 ] * double( ext[ 0 ] ) ),
835       ori[ 0 ] + ( spac[ 0 ] * double( ext[ 1 ] ) )
836     };
837   double ybnds[ ] =
838     {
839       ori[ 1 ] + ( spac[ 1 ] * double( ext[ 2 ] ) ),
840       ori[ 1 ] + ( spac[ 1 ] * double( ext[ 3 ] ) )
841     };
842   double zbnds[ ] =
843     {
844       ori[ 2 ] + ( spac[ 2 ] * double( ext[ 4 ] ) ),
845       ori[ 2 ] + ( spac[ 2 ] * double( ext[ 5 ] ) )
846     };
847
848   if( spac[ 0 ] < double( 0 ) )
849   {
850     double t = xbnds[ 0 ];
851     xbnds[ 0 ] = xbnds[ 1 ];
852     xbnds[ 1 ] = t;
853
854   } // fi
855   if( spac[ 1 ] < double( 0 ) )
856   {
857     double t = ybnds[ 0 ];
858     ybnds[ 0 ] = ybnds[ 1 ];
859     ybnds[ 1 ] = t;
860
861   } // fi
862   if( spac[ 2 ] < double( 0 ) )
863   {
864     double t = zbnds[ 0 ];
865     zbnds[ 0 ] = zbnds[ 1 ];
866     zbnds[ 1 ] = t;
867
868   } // fi
869
870   // Plane function origin
871   this->m_PlaneFunction->SetOrigin( pos );
872
873   // Configure visualization and implicit plane orientation
874   int axis = this->m_SliceMappers[ 0 ]->GetOrientation( );
875   this->m_PlaneActor->GetProperty( )->SetRepresentationToWireframe( );
876   this->m_PlaneActor->GetProperty( )->SetLineWidth( 2 );
877   vtkPoints* plane_points = this->m_Plane->GetPoints( );
878   if( axis == 0 ) // YZ, x-normal
879   {
880     this->m_PlaneFunction->SetNormal( 1, 0, 0 );
881     plane_points->SetPoint( 0, pos[ 0 ], ybnds[ 0 ], zbnds[ 0 ] );
882     plane_points->SetPoint( 1, pos[ 0 ], ybnds[ 1 ], zbnds[ 0 ] );
883     plane_points->SetPoint( 2, pos[ 0 ], ybnds[ 1 ], zbnds[ 1 ] );
884     plane_points->SetPoint( 3, pos[ 0 ], ybnds[ 0 ], zbnds[ 1 ] );
885     this->m_PlaneActor->GetProperty( )->SetColor( 1, 0, 0 );
886   }
887   else if( axis == 1 ) // ZX, y-normal
888   {
889     this->m_PlaneFunction->SetNormal( 0, 1, 0 );
890     plane_points->SetPoint( 0, xbnds[ 0 ], pos[ 1 ], zbnds[ 0 ] );
891     plane_points->SetPoint( 1, xbnds[ 0 ], pos[ 1 ], zbnds[ 1 ] );
892     plane_points->SetPoint( 2, xbnds[ 1 ], pos[ 1 ], zbnds[ 1 ] );
893     plane_points->SetPoint( 3, xbnds[ 1 ], pos[ 1 ], zbnds[ 0 ] );
894     this->m_PlaneActor->GetProperty( )->SetColor( 0, 1, 0 );
895   }
896   else // XY, z-normal
897   {
898     this->m_PlaneFunction->SetNormal( 0, 0, 1 );
899     plane_points->SetPoint( 0, xbnds[ 0 ], ybnds[ 0 ], pos[ 2 ] );
900     plane_points->SetPoint( 1, xbnds[ 1 ], ybnds[ 0 ], pos[ 2 ] );
901     plane_points->SetPoint( 2, xbnds[ 1 ], ybnds[ 1 ], pos[ 2 ] );
902     plane_points->SetPoint( 3, xbnds[ 0 ], ybnds[ 1 ], pos[ 2 ] );
903     this->m_PlaneActor->GetProperty( )->SetColor( 0, 0, 1 );
904
905   } // fi
906   this->m_PlaneFunction->Modified( );
907   this->m_Plane->Modified( );
908   this->m_PlaneMapper->Modified( );
909   this->m_PlaneActor->Modified( );
910
911   // Prepare other actors to update
912   /* TODO
913      for( unsigned int i = 0; i < this->OtherActors.size( ); ++i )
914      {
915      if( this->OtherActors[ i ].first.GetPointer( ) != NULL )
916      {
917      this->OtherActors[ i ].first->Modified( );
918      this->OtherActors[ i ].first->Update( );
919
920      } // fi
921
922      if( this->OtherActors[ i ].second.GetPointer( ) != NULL )
923      {
924      this->OtherActors[ i ].second->GetMapper( )->Modified( );
925      this->OtherActors[ i ].second->Modified( );
926
927      } // fi
928
929      } // rof
930
931      if( this->m_UpdateCommand != NULL )
932      this->m_UpdateCommand( this->m_UpdateData );
933   */
934
935   // Update text
936   this->UpdateText( );
937
938   // Associated slices
939   for( unsigned int i = 0; i < this->m_AssociatedSlices.size( ); ++i )
940     if( this->m_AssociatedSlices[ i ]->GetAxis( ) == this->GetAxis( ) )
941       this->m_AssociatedSlices[ i ]->SetSliceNumber( slice );
942 }
943
944 // -------------------------------------------------------------------------
945 void cpExtensions::Visualization::ImageSliceActors::
946 SetSlice( double* pos )
947 {
948   vtkImageData* image;
949   if( this->m_ImageMaps[ 0 ] != NULL )
950     image =
951       dynamic_cast< vtkImageData* >( this->m_ImageMaps[ 0 ]->GetInput( ) );
952   else
953     image = this->m_SliceMappers[ 0 ]->GetInput( );
954
955   int ijk[ 3 ];
956   double pcoords[ 3 ];
957   image->ComputeStructuredCoordinates( pos, ijk, pcoords );
958   this->SetSliceNumber( ijk[ this->GetAxis( ) ] );
959 }
960
961 // -------------------------------------------------------------------------
962 void cpExtensions::Visualization::ImageSliceActors::
963 UpdateText( )
964 {
965   if( this->m_SliceMappers.size( ) > 0 )
966   {
967     char axis;
968     int axId = this->m_SliceMappers[ 0 ]->GetOrientation( );
969     if     ( axId == 0 ) axis = 'X';
970     else if( axId == 1 ) axis = 'Y';
971     else if( axId == 2 ) axis = 'Z';
972
973     std::sprintf(
974       this->m_TextBuffer, "Axis: %c (%d)",
975       axis, this->m_SliceMappers[ 0 ]->GetSliceNumber( )
976       );
977   }
978   else
979     this->m_TextBuffer[ 0 ] = '\0';
980   this->m_TextActor->SetInput( this->m_TextBuffer );
981   this->m_TextActor->Modified( );
982   this->Modified( );
983 }
984
985 // -------------------------------------------------------------------------
986 void cpExtensions::Visualization::ImageSliceActors::
987 UpdateText( double pos[ 3 ] )
988 {
989   if( this->m_SliceMappers.size( ) > 0 )
990   {
991     char axis;
992     int axId = this->m_SliceMappers[ 0 ]->GetOrientation( );
993     if     ( axId == 0 ) axis = 'X';
994     else if( axId == 1 ) axis = 'Y';
995     else if( axId == 2 ) axis = 'Z';
996     int slice = this->GetSliceNumber( );
997
998     vtkImageData* image;
999     if( this->m_ImageMaps[ 0 ] != NULL )
1000       image =
1001         dynamic_cast< vtkImageData* >( this->m_ImageMaps[ 0 ]->GetInput( ) );
1002     else
1003       image = this->m_SliceMappers[ 0 ]->GetInput( );
1004
1005     int ijk[ 3 ];
1006     double pcoords[ 3 ];
1007     image->ComputeStructuredCoordinates( pos, ijk, pcoords );
1008     ijk[ axId ] = slice;
1009
1010     int ext[ 6 ];
1011     image->GetExtent( ext );
1012     if(
1013       ext[ 0 ] <= ijk[ 0 ] && ijk[ 0 ] <= ext[ 1 ] &&
1014       ext[ 2 ] <= ijk[ 1 ] && ijk[ 1 ] <= ext[ 3 ] &&
1015       ext[ 4 ] <= ijk[ 2 ] && ijk[ 2 ] <= ext[ 5 ]
1016       )
1017     {
1018       int nScl = image->GetNumberOfScalarComponents( );
1019       std::stringstream str;
1020       str
1021         << "[" << ijk[ 0 ]
1022         << "," << ijk[ 1 ]
1023         << "," << ijk[ 2 ] << "]=(";
1024       str <<
1025         image->GetScalarComponentAsFloat( ijk[ 0 ], ijk[ 1 ], ijk[ 2 ], 0 );
1026       for( int n = 1; n < nScl; ++n )
1027         str
1028           << " "
1029           << image->GetScalarComponentAsFloat(
1030             ijk[ 0 ], ijk[ 1 ], ijk[ 2 ], n
1031             );
1032       str << ")";
1033       std::sprintf(
1034         this->m_TextBuffer, "Axis: %c (%d)\nPixel %s",
1035         axis, slice, str.str( ).c_str( )
1036         );
1037
1038     } // fi
1039   }
1040   else
1041     this->m_TextBuffer[ 0 ] = '\0';
1042   this->m_TextActor->SetInput( this->m_TextBuffer );
1043   this->m_TextActor->Modified( );
1044   this->Modified( );
1045 }
1046
1047 // -------------------------------------------------------------------------
1048 void cpExtensions::Visualization::ImageSliceActors::
1049 UpdateText( const double& w, const double& l )
1050 {
1051   if( this->m_SliceMappers.size( ) > 0 )
1052   {
1053     char axis;
1054     int axId = this->m_SliceMappers[ 0 ]->GetOrientation( );
1055     if     ( axId == 0 ) axis = 'X';
1056     else if( axId == 1 ) axis = 'Y';
1057     else if( axId == 2 ) axis = 'Z';
1058
1059     std::sprintf(
1060       this->m_TextBuffer, "Axis: %c (%d)\nW/L (%.2f/%.2f)",
1061       axis, this->m_SliceMappers[ 0 ]->GetSliceNumber( ), w, l
1062       );
1063   }
1064   else
1065     this->m_TextBuffer[ 0 ] = '\0';
1066   this->m_TextActor->SetInput( this->m_TextBuffer );
1067   this->m_TextActor->Modified( );
1068   this->Modified( );
1069 }
1070
1071 // -------------------------------------------------------------------------
1072 cpExtensions::Visualization::ImageSliceActors::
1073 ImageSliceActors( )
1074   : Superclass( ),
1075     m_Interpolate( false )
1076 {
1077   this->Clear( );
1078   this->_ConfigureStyle( );
1079 }
1080
1081 // -------------------------------------------------------------------------
1082 cpExtensions::Visualization::ImageSliceActors::
1083 ~ImageSliceActors( )
1084 {
1085 }
1086
1087 // -------------------------------------------------------------------------
1088 void cpExtensions::Visualization::ImageSliceActors::
1089 _ConfigureStyle( )
1090 {
1091   // Connect this view with a controller
1092   this->m_Style = vtkSmartPointer< ImageInteractorStyle >::New( );
1093   this->m_Style->AddMouseMoveCommand( Self::_MouseMoveCommand, this );
1094   this->m_Style->AddMouseClickCommand( Self::_MouseClickCommand, this );
1095   this->m_Style->AddMouseDoubleClickCommand(
1096     Self::_MouseDoubleClickCommand, this
1097     );
1098   this->m_Style->AddMouseWheelCommand( Self::_MouseWheelCommand, this );
1099   this->m_Style->AddKeyCommand( Self::_KeyCommand, this );
1100 }
1101
1102 // -------------------------------------------------------------------------
1103 void cpExtensions::Visualization::ImageSliceActors::
1104 _ConfigureNewLUT( vtkImageData* data )
1105 {
1106   // Does the new LUT is a window-level one?
1107   unsigned int nImgs = this->m_ImageMaps.size( );
1108   unsigned int nCmps = data->GetNumberOfScalarComponents( );
1109
1110   if( nCmps > 1 )
1111   {
1112     this->m_ImageMaps.push_back( NULL );
1113     return;
1114
1115   } // fi
1116
1117   // Create LUT filter
1118   this->m_ImageMaps.push_back( vtkSmartPointer< vtkImageMapToColors >::New( ) );
1119   if( nImgs == 0 )
1120   {
1121     double range[ 2 ];
1122     data->GetScalarRange( range );
1123     vtkSmartPointer< vtkWindowLevelLookupTable > lut =
1124       vtkSmartPointer< vtkWindowLevelLookupTable >::New( );
1125     lut->SetScaleToLinear( );
1126     lut->SetTableRange( range );
1127     lut->SetWindow( range[ 1 ] - range[ 0 ] );
1128     lut->SetLevel( ( range[ 1 ] + range[ 0 ] ) / double( 2 ) );
1129     lut->Build( );
1130     this->m_ImageMaps[ 0 ]->SetLookupTable( lut );
1131
1132     this->m_MinWindow = double( 0 );
1133     this->m_MaxWindow = range[ 1 ] - range[ 0 ];
1134     this->m_MinLevel = range[ 0 ];
1135     this->m_MaxLevel = range[ 1 ];
1136   }
1137   else
1138     this->SetLookupTableAsColor( nImgs, 1, 0, 0 );
1139 }
1140
1141 // -------------------------------------------------------------------------
1142 void cpExtensions::Visualization::ImageSliceActors::
1143 _ConfigureNewInput( int axis )
1144 {
1145   unsigned int nImages = this->m_ImageActors.size( );
1146
1147   // Configure mapper
1148   vtkImageSliceMapper* mapper = this->m_SliceMappers[ nImages ];
1149   if( nImages == 0 )
1150     mapper->SetOrientation( axis );
1151   else
1152     mapper->SetOrientation( this->m_SliceMappers[ 0 ]->GetOrientation( ) );
1153   mapper->Update( );
1154
1155   // Create actor
1156   vtkSmartPointer< vtkImageActor > actor =
1157     vtkSmartPointer< vtkImageActor >::New( );
1158   this->m_ImageActors.push_back( actor );
1159   actor->SetMapper( mapper );
1160   actor->SetInterpolate( this->m_Interpolate );
1161   actor->Modified( );
1162
1163   if( nImages == 0 )
1164     this->m_Style->AssociateImageActor( actor );
1165   this->AddItem( actor );
1166
1167   if( nImages > 1 )
1168     this->SetSliceNumber( this->GetSliceNumber( ) );
1169   else
1170     this->SetSliceNumber( this->GetSliceNumberMaxValue( ) );
1171   this->Modified( );
1172 }
1173
1174 // -------------------------------------------------------------------------
1175 void cpExtensions::Visualization::ImageSliceActors::
1176 _MouseMoveCommand(
1177   void* data,
1178   const ImageInteractorStyle::ButtonID& btn, double* pos,
1179   bool alt, bool ctr, bool sft
1180   )
1181 {
1182   ImageSliceActors* actors = reinterpret_cast< ImageSliceActors* >( data );
1183   if( actors == NULL )
1184     return;
1185
1186   if( btn == ImageInteractorStyle::ButtonID_None )
1187   {
1188     actors->SetCursor( pos );
1189     actors->UpdateText( pos );
1190     actors->GetStyle( )->GetInteractor( )->Render( );
1191   }
1192   else if( btn == ImageInteractorStyle::ButtonID_Left )
1193   {
1194     unsigned int nC = actors->m_SlicesCommands.size( );
1195     if( !alt && ctr && !sft && nC > 0 )
1196     {
1197       for( unsigned int i = 0; i < nC; ++i )
1198         actors->m_SlicesCommands[ i ].first(
1199           pos, actors->GetAxis( ), actors->m_SlicesCommands[ i ].second
1200           );
1201       actors->GetStyle( )->GetInteractor( )->Render( );
1202
1203     } // fi
1204   }
1205   else if( btn == ImageInteractorStyle::ButtonID_Middle )
1206   {
1207   }
1208   else if( btn == ImageInteractorStyle::ButtonID_Right )
1209   {
1210     if( !alt && !ctr && sft )
1211     {
1212       double bounds[ 6 ];
1213       actors->m_SliceMappers[ 0 ]->GetBounds( bounds );
1214
1215       int a0 = actors->GetAxis( );
1216       int a1 = ( a0 + 1 ) % 3;
1217       int a2 = ( a0 + 2 ) % 3;
1218       double dx = pos[ a1 ] - actors->m_StartWindowLevelPos[ a1 ];
1219       double dy = pos[ a2 ] - actors->m_StartWindowLevelPos[ a2 ];
1220       dx /= bounds[ ( a1 << 1 ) + 1 ] - bounds[ a1 << 1 ];
1221       dy /= bounds[ ( a2 << 1 ) + 1 ] - bounds[ a2 << 1 ];
1222
1223       dx *= actors->m_StartWindowLevel[ 0 ];
1224       dy *= actors->m_StartWindowLevel[ 1 ];
1225       actors->SetWindowLevel(
1226         actors->m_StartWindowLevel[ 0 ] + dx,
1227         actors->m_StartWindowLevel[ 1 ] + dy
1228         );
1229       actors->GetStyle( )->GetInteractor( )->Render( );
1230
1231     } // fi
1232
1233   } // fi
1234 }
1235
1236 // -------------------------------------------------------------------------
1237 void cpExtensions::Visualization::ImageSliceActors::
1238 _MouseClickCommand(
1239   void* data,
1240   const ImageInteractorStyle::ButtonID& btn, double* pos,
1241   bool alt, bool ctr, bool sft
1242   )
1243 {
1244   ImageSliceActors* actors = reinterpret_cast< ImageSliceActors* >( data );
1245   if( actors == NULL )
1246     return;
1247
1248   actors->m_StartWindowLevelPos[ 0 ] = pos[ 0 ];
1249   actors->m_StartWindowLevelPos[ 1 ] = pos[ 1 ];
1250   actors->m_StartWindowLevelPos[ 2 ] = pos[ 2 ];
1251   actors->m_StartWindowLevel[ 0 ] = actors->GetWindow( );
1252   actors->m_StartWindowLevel[ 1 ] = actors->GetLevel( );
1253 }
1254
1255 // -------------------------------------------------------------------------
1256 void cpExtensions::Visualization::ImageSliceActors::
1257 _MouseDoubleClickCommand(
1258   void* data,
1259   const ImageInteractorStyle::ButtonID& btn, double* pos,
1260   bool alt, bool ctr, bool sft
1261   )
1262 {
1263   ImageSliceActors* actors = reinterpret_cast< ImageSliceActors* >( data );
1264   if( actors == NULL )
1265     return;
1266
1267   if( btn == ImageInteractorStyle::ButtonID_Left )
1268   {
1269     unsigned int nC = actors->m_SeedCommands.size( );
1270     if( !alt && ctr && !sft && nC > 0 )
1271     {
1272       for( unsigned int i = 0; i < nC; ++i )
1273         actors->m_SeedCommands[ i ].first(
1274           pos, actors->GetAxis( ), actors->m_SeedCommands[ i ].second
1275           );
1276       actors->GetStyle( )->GetInteractor( )->Render( );
1277
1278     } // fi
1279   }
1280   else if( btn == ImageInteractorStyle::ButtonID_Middle )
1281   {
1282   }
1283   else if( btn == ImageInteractorStyle::ButtonID_Right )
1284   {
1285   } // fi
1286 }
1287
1288 // -------------------------------------------------------------------------
1289 void cpExtensions::Visualization::ImageSliceActors::
1290 _MouseWheelCommand(
1291   void* data,
1292   const int& dir, bool alt, bool ctr, bool sft
1293   )
1294 {
1295   ImageSliceActors* actors = reinterpret_cast< ImageSliceActors* >( data );
1296   if( actors == NULL )
1297     return;
1298
1299   if( !alt && !ctr && !sft )
1300   {
1301     actors->SetSliceNumber( actors->GetSliceNumber( ) + dir );
1302     actors->GetStyle( )->GetInteractor( )->Render( );
1303   }
1304   else if( !alt && !ctr && sft )
1305   {
1306     actors->SetSliceNumber( actors->GetSliceNumber( ) + ( dir * 10 ) );
1307     actors->GetStyle( )->GetInteractor( )->Render( );
1308
1309   } // fi
1310 }
1311
1312 // -------------------------------------------------------------------------
1313 void cpExtensions::Visualization::ImageSliceActors::
1314 _KeyCommand( void* data, const char& key )
1315 {
1316 }
1317
1318 // eof - $RCSfile$