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