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