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