]> Creatis software - cpPlugins.git/blob - lib/cpExtensions/Visualization/ImageSliceActors.cxx
MPR-OpenGL integration: not yet finished, just one step to go. IT DOES NOT COMPILE.
[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->GetNumberOfInputPorts( ) - 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->GetNumberOfInputPorts( ) - 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   // Remove associated objects
133   this->m_AssociatedSlices.clear( );
134
135   // White cursor
136   vtkSmartPointer< vtkPoints > cursor_points =
137     vtkSmartPointer< vtkPoints >::New( );
138   vtkSmartPointer< vtkCellArray > cursor_lines =
139     vtkSmartPointer< vtkCellArray >::New( );
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_lines->InsertNextCell( 2 );
145   cursor_lines->InsertCellPoint( 0 );
146   cursor_lines->InsertCellPoint( 1 );
147   cursor_lines->InsertNextCell( 2 );
148   cursor_lines->InsertCellPoint( 2 );
149   cursor_lines->InsertCellPoint( 3 );
150
151   this->m_Cursor = vtkSmartPointer< vtkPolyData >::New( );
152   this->m_CursorMapper = vtkSmartPointer< vtkPolyDataMapper >::New( );
153   this->m_CursorActor = vtkSmartPointer< vtkActor >::New( );
154
155   this->m_Cursor->SetPoints( cursor_points );
156   this->m_Cursor->SetLines( cursor_lines );
157   this->m_CursorMapper->SetInputData( this->m_Cursor );
158   this->m_CursorActor->SetMapper( this->m_CursorMapper );
159   this->m_CursorActor->GetProperty( )->SetColor( 1, 1, 0 );
160   this->m_CursorActor->GetProperty( )->SetLineWidth( 2 );
161
162   // Plane intersections
163   this->m_Axis1       = vtkSmartPointer< vtkPolyData >::New( );
164   this->m_Axis1Mapper = vtkSmartPointer< vtkPolyDataMapper >::New( );
165   this->m_Axis1Actor  = vtkSmartPointer< vtkActor >::New( );
166
167   vtkSmartPointer< vtkPoints > h_points =
168     vtkSmartPointer< vtkPoints >::New( );
169   vtkSmartPointer< vtkCellArray > h_lines =
170     vtkSmartPointer< vtkCellArray >::New( );
171   h_points->InsertNextPoint( 0, 0, 0 );
172   h_points->InsertNextPoint( 0, 0, 0 );
173   h_lines->InsertNextCell( 2 );
174   h_lines->InsertCellPoint( 0 );
175   h_lines->InsertCellPoint( 1 );
176   this->m_Axis1->SetPoints( h_points );
177   this->m_Axis1->SetLines( h_lines );
178   this->m_Axis1Mapper->SetInputData( this->m_Axis1 );
179   this->m_Axis1Actor->SetMapper( this->m_Axis1Mapper );
180
181   this->m_Axis2       = vtkSmartPointer< vtkPolyData >::New( );
182   this->m_Axis2Mapper = vtkSmartPointer< vtkPolyDataMapper >::New( );
183   this->m_Axis2Actor  = vtkSmartPointer< vtkActor >::New( );
184
185   vtkSmartPointer< vtkPoints > v_points =
186     vtkSmartPointer< vtkPoints >::New( );
187   vtkSmartPointer< vtkCellArray > v_lines =
188     vtkSmartPointer< vtkCellArray >::New( );
189   v_points->InsertNextPoint( 0, 0, 0 );
190   v_points->InsertNextPoint( 0, 0, 0 );
191   v_lines->InsertNextCell( 2 );
192   v_lines->InsertCellPoint( 0 );
193   v_lines->InsertCellPoint( 1 );
194   this->m_Axis2->SetPoints( v_points );
195   this->m_Axis2->SetLines( v_lines );
196   this->m_Axis2Mapper->SetInputData( this->m_Axis2 );
197   this->m_Axis2Actor->SetMapper( this->m_Axis2Mapper );
198
199   // Plane
200   this->m_Plane       = vtkSmartPointer< vtkPolyData >::New( );
201   this->m_PlaneMapper = vtkSmartPointer< vtkPolyDataMapper >::New( );
202   this->m_PlaneActor  = vtkSmartPointer< vtkActor >::New( );
203
204   vtkSmartPointer< vtkPoints > plane_points =
205     vtkSmartPointer< vtkPoints >::New( );
206   vtkSmartPointer< vtkCellArray > plane_lines =
207     vtkSmartPointer< vtkCellArray >::New( );
208   plane_points->InsertNextPoint( 0, 0, 0 );
209   plane_points->InsertNextPoint( 0, 1, 0 );
210   plane_points->InsertNextPoint( 1, 1, 0 );
211   plane_points->InsertNextPoint( 1, 0, 0 );
212   plane_lines->InsertNextCell( 5 );
213   plane_lines->InsertCellPoint( 0 );
214   plane_lines->InsertCellPoint( 1 );
215   plane_lines->InsertCellPoint( 2 );
216   plane_lines->InsertCellPoint( 3 );
217   plane_lines->InsertCellPoint( 0 );
218   this->m_Plane->SetPoints( plane_points );
219   this->m_Plane->SetLines( plane_lines );
220
221   this->m_PlaneMapper->SetInputData( this->m_Plane );
222   this->m_PlaneActor->SetMapper( this->m_PlaneMapper );
223
224   // Text actor
225   this->m_TextActor = vtkSmartPointer< vtkTextActor >::New( );
226   this->m_TextBuffer[ 0 ] = '\0';
227   this->m_TextActor->SetTextScaleModeToNone( );
228   vtkTextProperty* textprop = this->m_TextActor->GetTextProperty( );
229   textprop->SetColor( 1, 1, 0 );
230   textprop->SetFontFamilyToCourier( );
231   textprop->SetFontSize( 18 );
232   textprop->BoldOff( );
233   textprop->ItalicOff( );
234   textprop->ShadowOff( );
235   textprop->SetJustificationToLeft( );
236   textprop->SetVerticalJustificationToBottom( );
237   vtkCoordinate* coord = this->m_TextActor->GetPositionCoordinate( );
238   coord->SetCoordinateSystemToNormalizedViewport( );
239   coord->SetValue( 0.01, 0.01 );
240 }
241
242 // -------------------------------------------------------------------------
243 void cpExtensions::Visualization::ImageSliceActors::
244 AssociateSlice( Self* slice )
245 {
246   this->m_AssociatedSlices.push_back( slice );
247   this->Modified( );
248 }
249
250 // -------------------------------------------------------------------------
251 vtkInteractorStyle* cpExtensions::Visualization::ImageSliceActors::
252 GetStyle( )
253 {
254   return( this->m_Style.GetPointer( ) );
255 }
256
257 // -------------------------------------------------------------------------
258 const vtkInteractorStyle* cpExtensions::Visualization::ImageSliceActors::
259 GetStyle( ) const
260 {
261   return( this->m_Style.GetPointer( ) );
262 }
263
264 // -------------------------------------------------------------------------
265 vtkImageData* cpExtensions::Visualization::ImageSliceActors::
266 GetInputImage( )
267 {
268   if( this->m_ImageMapper.GetPointer( ) != NULL )
269     return( this->m_ImageMapper->GetInput( ) );
270   else
271     return( NULL );
272 }
273
274 // -------------------------------------------------------------------------
275 const vtkImageData* cpExtensions::Visualization::ImageSliceActors::
276 GetInputImage( ) const
277 {
278   if( this->m_ImageMapper.GetPointer( ) != NULL )
279     return( this->m_ImageMapper->GetInput( ) );
280   else
281     return( NULL );
282 }
283
284 // -------------------------------------------------------------------------
285 void cpExtensions::Visualization::ImageSliceActors::
286 PushActorsInto( vtkRenderWindow* window, bool force_style )
287 {
288   this->m_Window = window;
289   if( window == NULL )
290     return;
291   vtkRenderWindowInteractor* rwi = window->GetInteractor( );
292   vtkRenderer* renderer = window->GetRenderers( )->GetFirstRenderer( );
293   if( rwi == NULL || renderer == NULL )
294     return;
295
296   // Update style
297   if( this->m_Style.GetPointer( ) != NULL && force_style )
298     rwi->SetInteractorStyle( this->m_Style );
299
300   // Update actors
301   renderer->AddViewProp( this->m_ImageActor );
302   renderer->AddViewProp( this->m_BlenderActor );
303   if( force_style )
304   {
305     renderer->AddViewProp( this->m_CursorActor );
306     renderer->AddViewProp( this->m_PlaneActor );
307     renderer->AddViewProp( this->m_TextActor );
308     renderer->AddViewProp( this->m_Axis1Actor );
309     renderer->AddViewProp( this->m_Axis2Actor );
310
311   } // fi
312
313   // Configure camera
314   vtkCamera* camera = renderer->GetActiveCamera( );
315   if( camera != NULL && force_style )
316   {
317     // Parallel projections are better when displaying 2D images
318     int axis = this->GetAxis( );
319     camera->ParallelProjectionOn( );
320     camera->SetFocalPoint( double( 0 ), double( 0 ), double( 0 ) );
321     if( axis == 0 )
322     {
323       camera->SetPosition( double( 1 ), double( 0 ), double( 0 ) );
324       camera->SetViewUp  ( double( 0 ), double( 0 ), double( 1 ) );
325     }
326     else if( axis == 1 )
327     {
328       camera->SetPosition( double( 0 ), double( -1 ), double( 0 ) );
329       camera->SetViewUp  ( double( 0 ), double(  0 ), double( 1 ) );
330     }
331     else // if( axis == 2 )
332     {
333       camera->SetPosition( double( 0 ), double(  0 ), double( 1 ) );
334       camera->SetViewUp  ( double( 0 ), double( -1 ), double( 0 ) );
335
336     } // fi
337
338   } // fi
339   renderer->ResetCamera( );
340 }
341
342 // -------------------------------------------------------------------------
343 void cpExtensions::Visualization::ImageSliceActors::
344 PopActorsFrom( vtkRenderWindow* window )
345 {
346   vtkRenderWindowInteractor* rwi = window->GetInteractor( );
347   vtkRenderer* renderer = window->GetRenderers( )->GetFirstRenderer( );
348   if( renderer != NULL )
349   {
350     renderer->RemoveViewProp( this->m_ImageActor );
351     renderer->RemoveViewProp( this->m_BlenderActor );
352     renderer->RemoveViewProp( this->m_CursorActor );
353     renderer->RemoveViewProp( this->m_PlaneActor );
354     renderer->RemoveViewProp( this->m_TextActor );
355     renderer->RemoveViewProp( this->m_Axis1Actor );
356     renderer->RemoveViewProp( this->m_Axis2Actor );
357
358   } // fi
359 }
360
361 // -------------------------------------------------------------------------
362 unsigned int cpExtensions::Visualization::ImageSliceActors::
363 GetNumberOfImages( ) const
364 {
365   return( this->m_Blender->GetNumberOfInputPorts( ) );
366 }
367
368 // -------------------------------------------------------------------------
369 vtkImageActor* cpExtensions::Visualization::ImageSliceActors::
370 GetImageActor( )
371 {
372   return( this->m_ImageActor );
373 }
374
375 // -------------------------------------------------------------------------
376 const vtkImageActor* cpExtensions::Visualization::ImageSliceActors::
377 GetImageActor( ) const
378 {
379   return( this->m_ImageActor );
380 }
381
382 // -------------------------------------------------------------------------
383 vtkImageActor* cpExtensions::Visualization::ImageSliceActors::
384 GetBinaryActor( )
385 {
386   return( this->m_BlenderActor );
387 }
388
389 // -------------------------------------------------------------------------
390 const vtkImageActor* cpExtensions::Visualization::ImageSliceActors::
391 GetBinaryActor( ) const
392 {
393   return( this->m_BlenderActor );
394 }
395
396 // -------------------------------------------------------------------------
397 vtkTextActor* cpExtensions::Visualization::ImageSliceActors::
398 GetTextActor( )
399 {
400   return( this->m_TextActor );
401 }
402
403 // -------------------------------------------------------------------------
404 const vtkTextActor* cpExtensions::Visualization::ImageSliceActors::
405 GetTextActor( ) const
406 {
407   return( this->m_TextActor );
408 }
409
410 // -------------------------------------------------------------------------
411 vtkActor* cpExtensions::Visualization::ImageSliceActors::
412 GetPlaneActor( )
413 {
414   return( this->m_PlaneActor );
415 }
416
417 // -------------------------------------------------------------------------
418 const vtkActor* cpExtensions::Visualization::ImageSliceActors::
419 GetPlaneActor( ) const
420 {
421   return( this->m_PlaneActor );
422 }
423
424 // -------------------------------------------------------------------------
425 vtkPlane* cpExtensions::Visualization::ImageSliceActors::
426 GetPlaneFunction( )
427 {
428   if( this->m_ImageMapper.GetPointer( ) != NULL )
429     return( this->m_ImageMapper->GetSlicePlane( ) );
430   else
431     return( NULL );
432 }
433
434 // -------------------------------------------------------------------------
435 const vtkPlane* cpExtensions::Visualization::ImageSliceActors::
436 GetPlaneFunction( ) const
437 {
438   if( this->m_ImageMapper.GetPointer( ) != NULL )
439     return( this->m_ImageMapper->GetSlicePlane( ) );
440   else
441     return( NULL );
442 }
443
444 // -------------------------------------------------------------------------
445 void cpExtensions::Visualization::ImageSliceActors::
446 SetInterpolate( bool v )
447 {
448   if( this->m_Interpolate != v )
449   {
450     this->m_ImageActor->SetInterpolate( v );
451     this->m_BlenderActor->SetInterpolate( v );
452     this->m_Interpolate = v;
453     this->Modified( );
454
455   } // fi
456 }
457
458 // -------------------------------------------------------------------------
459 void cpExtensions::Visualization::ImageSliceActors::
460 InterpolateOn( )
461 {
462   this->SetInterpolate( true );
463 }
464
465 // -------------------------------------------------------------------------
466 void cpExtensions::Visualization::ImageSliceActors::
467 InterpolateOff( )
468 {
469   this->SetInterpolate( false );
470 }
471
472 // -------------------------------------------------------------------------
473 double* cpExtensions::Visualization::ImageSliceActors::
474 GetDisplayBounds( ) const
475 {
476   if( this->m_ImageActor.GetPointer( ) != NULL )
477     return( this->m_ImageActor->GetDisplayBounds( ) );
478   else
479     return( NULL );
480 }
481
482 // -------------------------------------------------------------------------
483 void cpExtensions::Visualization::ImageSliceActors::
484 GetDisplayBounds( double bounds[ 6 ] ) const
485 {
486   if( this->m_ImageActor.GetPointer( ) == NULL )
487   {
488     bounds[ 0 ] = bounds[ 2 ] = bounds[ 4 ] = double(  0 );
489     bounds[ 1 ] = bounds[ 3 ] = bounds[ 5 ] = double( -1 );
490   }
491   else
492     this->m_ImageActor->GetDisplayBounds( bounds );
493 }
494
495 // -------------------------------------------------------------------------
496 void cpExtensions::Visualization::ImageSliceActors::
497 ResetCursor( )
498 {
499   if( this->m_ImageMapper.GetPointer( ) != NULL )
500   {
501     double pos[] =
502       {
503         this->m_VisibleBounds[ 0 ],
504         this->m_VisibleBounds[ 2 ],
505         this->m_VisibleBounds[ 4 ]
506       };
507     this->SetCursor( pos );
508   }
509   else
510   {
511     vtkPoints* points = this->m_Cursor->GetPoints( );
512     points->SetPoint( 0, 0, 0, 0 );
513     points->SetPoint( 1, 0, 0, 0 );
514     points->SetPoint( 2, 0, 0, 0 );
515     points->SetPoint( 3, 0, 0, 0 );
516     this->m_Cursor->Modified( );
517     this->m_CursorMapper->Modified( );
518     this->m_CursorActor->Modified( );
519
520   } // fi
521 }
522
523 // -------------------------------------------------------------------------
524 void cpExtensions::Visualization::ImageSliceActors::
525 SetCursor( double pos[ 3 ] )
526 {
527   if( this->m_ImageMapper.GetPointer( ) == NULL )
528     return;
529
530   // Get ordered axes
531   int a0 = this->GetAxis( );
532   int a1 = ( a0 + 1 ) % 3;
533   int a2 = ( a0 + 2 ) % 3;
534   int ma0 = a0 << 1;
535   int ma1 = a1 << 1;
536   int ma2 = a2 << 1;
537
538   // Update cross
539   double* bounds = this->m_VisibleBounds;
540   double p0[ 3 ], p1[ 3 ], p2[ 3 ], p3[ 3 ];
541
542   p0[ a2 ] = p1[ a2 ] = pos[ a2 ];
543   p2[ a1 ] = p3[ a1 ] = pos[ a1 ];
544   p0[ a0 ] = p1[ a0 ] = p2[ a0 ] = p3[ a0 ] = bounds[ ma0 ];
545   p0[ a1 ] = bounds[ ma1 ];
546   p1[ a1 ] = bounds[ ma1 + 1 ];
547   p2[ a2 ] = bounds[ ma2 ];
548   p3[ a2 ] = bounds[ ma2 + 1 ];
549
550   vtkPoints* points = this->m_Cursor->GetPoints( );
551   points->SetPoint( 0, p0 );
552   points->SetPoint( 1, p1 );
553   points->SetPoint( 2, p2 );
554   points->SetPoint( 3, p3 );
555   this->m_Cursor->Modified( );
556   this->m_CursorMapper->Modified( );
557   this->m_CursorActor->Modified( );
558 }
559
560 // -------------------------------------------------------------------------
561 void cpExtensions::Visualization::ImageSliceActors::
562 ResetAxesCursor( )
563 {
564   if( this->m_ImageMapper.GetPointer( ) != NULL )
565   {
566     double pos[] =
567       {
568         this->m_VisibleBounds[ 0 ],
569         this->m_VisibleBounds[ 2 ],
570         this->m_VisibleBounds[ 4 ]
571       };
572     this->SetAxesCursor( pos );
573   }
574   else
575   {
576     vtkPoints* points = this->m_Axis1->GetPoints( );
577     points->SetPoint( 0, 0, 0, 0 );
578     points->SetPoint( 1, 0, 0, 0 );
579     this->m_Axis1->Modified( );
580     this->m_Axis1Mapper->Modified( );
581     this->m_Axis1Actor->Modified( );
582
583     points = this->m_Axis2->GetPoints( );
584     points->SetPoint( 0, 0, 0, 0 );
585     points->SetPoint( 1, 0, 0, 0 );
586     this->m_Axis2->Modified( );
587     this->m_Axis2Mapper->Modified( );
588     this->m_Axis2Actor->Modified( );
589
590   } // fi
591 }
592
593 // -------------------------------------------------------------------------
594 void cpExtensions::Visualization::ImageSliceActors::
595 SetAxesCursor( double pos[ 3 ] )
596 {
597   if( this->m_ImageMapper.GetPointer( ) == NULL )
598     return;
599
600   // Get ordered axes
601   int a0 = this->GetAxis( );
602   int a1 = ( a0 + 1 ) % 3;
603   int a2 = ( a0 + 2 ) % 3;
604   int ma0 = a0 << 1;
605   int ma1 = a1 << 1;
606   int ma2 = a2 << 1;
607
608   // Update cross
609   double* bounds = this->m_VisibleBounds;
610   double p0[ 3 ], p1[ 3 ], p2[ 3 ], p3[ 3 ];
611
612   p0[ a2 ] = p1[ a2 ] = pos[ a2 ];
613   p2[ a1 ] = p3[ a1 ] = pos[ a1 ];
614   p0[ a0 ] = p1[ a0 ] = p2[ a0 ] = p3[ a0 ] = bounds[ ma0 ];
615   p0[ a1 ] = bounds[ ma1 ];
616   p1[ a1 ] = bounds[ ma1 + 1 ];
617   p2[ a2 ] = bounds[ ma2 ];
618   p3[ a2 ] = bounds[ ma2 + 1 ];
619
620   vtkPoints* points1 = this->m_Axis1->GetPoints( );
621   points1->SetPoint( 0, p2 );
622   points1->SetPoint( 1, p3 );
623
624   vtkPoints* points2 = this->m_Axis2->GetPoints( );
625   points2->SetPoint( 0, p0 );
626   points2->SetPoint( 1, p1 );
627
628   this->m_Axis1->Modified( );
629   this->m_Axis1Mapper->Modified( );
630   this->m_Axis1Actor->Modified( );
631
632   this->m_Axis2->Modified( );
633   this->m_Axis2Mapper->Modified( );
634   this->m_Axis2Actor->Modified( );
635 }
636
637 // -------------------------------------------------------------------------
638 double cpExtensions::Visualization::ImageSliceActors::
639 GetMinWindow( ) const
640 {
641   return( this->m_WLRange[ 0 ] );
642 }
643
644 // -------------------------------------------------------------------------
645 double cpExtensions::Visualization::ImageSliceActors::
646 GetMaxWindow( ) const
647 {
648   return( this->m_WLRange[ 1 ] );
649 }
650
651 // -------------------------------------------------------------------------
652 double cpExtensions::Visualization::ImageSliceActors::
653 GetMinLevel( ) const
654 {
655   return( this->m_WLRange[ 2 ] );
656 }
657
658 // -------------------------------------------------------------------------
659 double cpExtensions::Visualization::ImageSliceActors::
660 GetMaxLevel( ) const
661 {
662   return( this->m_WLRange[ 3 ] );
663 }
664
665 // -------------------------------------------------------------------------
666 double cpExtensions::Visualization::ImageSliceActors::
667 GetWindow( ) const
668 {
669   if( this->m_ImageActor.GetPointer( ) != NULL )
670     return( this->m_ImageActor->GetProperty( )->GetColorWindow( ) );
671   else
672     return( double( 0 ) );
673 }
674
675 // -------------------------------------------------------------------------
676 double cpExtensions::Visualization::ImageSliceActors::
677 GetLevel( ) const
678 {
679   if( this->m_ImageActor.GetPointer( ) != NULL )
680     return( this->m_ImageActor->GetProperty( )->GetColorLevel( ) );
681   else
682     return( double( 0 ) );
683 }
684
685 // -------------------------------------------------------------------------
686 void cpExtensions::Visualization::ImageSliceActors::
687 SetWindow( double w )
688 {
689   if( this->m_ImageActor.GetPointer( ) == NULL )
690     return;
691   double v = ( w < this->m_WLRange[ 0 ] )? this->m_WLRange[ 0 ]: w;
692   v        = ( v > this->m_WLRange[ 1 ] )? this->m_WLRange[ 1 ]: v;
693   this->m_ImageActor->GetProperty( )->SetColorWindow( v );
694 }
695
696 // -------------------------------------------------------------------------
697 void cpExtensions::Visualization::ImageSliceActors::
698 SetLevel( double l )
699 {
700   if( this->m_ImageActor.GetPointer( ) == NULL )
701     return;
702   double v = ( l < this->m_WLRange[ 2 ] )? this->m_WLRange[ 2 ]: l;
703   v        = ( v > this->m_WLRange[ 3 ] )? this->m_WLRange[ 3 ]: v;
704   this->m_ImageActor->GetProperty( )->SetColorLevel( v );
705 }
706
707 // -------------------------------------------------------------------------
708 void cpExtensions::Visualization::ImageSliceActors::
709 SetWindowLevel( double w, double l )
710 {
711   if( this->m_ImageActor.GetPointer( ) == NULL )
712     return;
713   double a = ( w < this->m_WLRange[ 0 ] )? this->m_WLRange[ 0 ]: w;
714   a        = ( a > this->m_WLRange[ 1 ] )? this->m_WLRange[ 1 ]: a;
715   double b = ( l < this->m_WLRange[ 2 ] )? this->m_WLRange[ 2 ]: l;
716   b        = ( b > this->m_WLRange[ 3 ] )? this->m_WLRange[ 3 ]: b;
717   this->m_ImageActor->GetProperty( )->SetColorWindow( a );
718   this->m_ImageActor->GetProperty( )->SetColorLevel( b );
719   this->UpdateText( a, b );
720 }
721
722 // -------------------------------------------------------------------------
723 void cpExtensions::Visualization::ImageSliceActors::
724 ResetWindowLevel( )
725 {
726   this->SetWindowLevel(
727     this->m_WLRange[ 1 ] * double( 0.5 ),
728     ( this->m_WLRange[ 3 ] + this->m_WLRange[ 2 ] ) * double( 0.5 )
729     );
730 }
731
732 // -------------------------------------------------------------------------
733 int cpExtensions::Visualization::ImageSliceActors::
734 GetAxis( ) const
735 {
736   if( this->m_ImageMapper.GetPointer( ) != NULL )
737     return( this->m_ImageMapper->GetOrientation( ) );
738   else
739     return( -1 );
740 }
741
742 // -------------------------------------------------------------------------
743 int cpExtensions::Visualization::ImageSliceActors::
744 GetSliceNumber( ) const
745 {
746   if( this->m_ImageMapper.GetPointer( ) != NULL )
747     return( this->m_ImageMapper->GetSliceNumber( ) );
748   else
749     return( -1 );
750 }
751
752 // -------------------------------------------------------------------------
753 int cpExtensions::Visualization::ImageSliceActors::
754 GetSliceNumberMinValue( ) const
755 {
756   if( this->m_ImageMapper.GetPointer( ) != NULL )
757     return( this->m_ImageMapper->GetSliceNumberMinValue( ) );
758   else
759     return( -1 );
760 }
761
762 // -------------------------------------------------------------------------
763 int cpExtensions::Visualization::ImageSliceActors::
764 GetSliceNumberMaxValue( ) const
765 {
766   if( this->m_ImageMapper.GetPointer( ) != NULL )
767     return( this->m_ImageMapper->GetSliceNumberMaxValue( ) );
768   else
769     return( -1 );
770 }
771
772 // -------------------------------------------------------------------------
773 void cpExtensions::Visualization::ImageSliceActors::
774 SetSliceNumber( const int& slice )
775 {
776   if( this->m_ImageMapper.GetPointer( ) == NULL )
777     return;
778
779   int axis = this->GetAxis( );
780   double prev_pos = this->m_VisibleBounds[ axis << 1 ];
781
782   // Update mappers and display bounds
783   this->m_ImageMapper->SetSliceNumber( slice );
784   this->m_BlenderMapper->SetSliceNumber( slice );
785   this->m_ImageMapper->Modified( );
786   this->m_BlenderMapper->Modified( );
787   this->m_ImageActor->Modified( );
788   this->m_BlenderActor->Modified( );
789
790   // Update display extent (this isn't done automatically)
791   this->m_ImageMapper->GetInput( )->GetExtent( this->m_VisibleExtent );
792   this->m_VisibleExtent[ axis << 1 ] = slice;
793   this->m_VisibleExtent[ ( axis << 1 ) + 1 ] = slice;
794   this->m_ImageActor->SetDisplayExtent( this->m_VisibleExtent );
795
796   // Prepare plane data
797   this->m_ImageMapper->GetBounds( this->m_VisibleBounds );
798   double x0[][ 3 ] =
799     {
800       {
801         this->m_VisibleBounds[ 0 ],
802         this->m_VisibleBounds[ 2 ],
803         this->m_VisibleBounds[ 4 ]
804       },
805       {
806         this->m_VisibleBounds[ 1 ],
807         this->m_VisibleBounds[ 3 ],
808         this->m_VisibleBounds[ 5 ]
809       }
810     };
811   double p0[ 2 ][ 3 ];
812
813   vtkPlane* plane = this->m_ImageMapper->GetSlicePlane( );
814   plane->GeneralizedProjectPoint( x0[ 0 ], p0[ 0 ] );
815   plane->GeneralizedProjectPoint( x0[ 1 ], p0[ 1 ] );
816
817   this->m_VisibleBounds[ 0 ] = p0[ 0 ][ 0 ];
818   this->m_VisibleBounds[ 1 ] = p0[ 1 ][ 0 ];
819   this->m_VisibleBounds[ 2 ] = p0[ 0 ][ 1 ];
820   this->m_VisibleBounds[ 3 ] = p0[ 1 ][ 1 ];
821   this->m_VisibleBounds[ 4 ] = p0[ 0 ][ 2 ];
822   this->m_VisibleBounds[ 5 ] = p0[ 1 ][ 2 ];
823   double* bnds = this->m_VisibleBounds;
824
825   // Configure visualization and implicit plane orientation
826   this->m_PlaneActor->GetProperty( )->SetRepresentationToWireframe( );
827   this->m_PlaneActor->GetProperty( )->SetLineWidth( 3 );
828   vtkPoints* plane_points = this->m_Plane->GetPoints( );
829   plane_points->SetPoint( 0, bnds[ 0 ], bnds[ 2 ], bnds[ 4 ] );
830   plane_points->SetPoint( 2, bnds[ 1 ], bnds[ 3 ], bnds[ 5 ] );
831   if( axis == 0 || axis == 2 ) // YZ, x-normal
832   {
833     plane_points->SetPoint( 1, bnds[ 1 ], bnds[ 2 ], bnds[ 5 ] );
834     plane_points->SetPoint( 3, bnds[ 0 ], bnds[ 3 ], bnds[ 4 ] );
835   }
836   else if( axis == 1 ) // ZX, y-normal
837   {
838     plane_points->SetPoint( 1, bnds[ 0 ], bnds[ 2 ], bnds[ 5 ] );
839     plane_points->SetPoint( 3, bnds[ 1 ], bnds[ 3 ], bnds[ 4 ] );
840
841   } // fi
842
843   // Set plane colors
844   this->m_PlaneActor->GetProperty( )->
845     SetColor( this->m_PlaneColors[ axis ] );
846   this->m_Axis1Actor->GetProperty( )->
847     SetColor( this->m_PlaneColors[ ( axis + 1 ) % 3 ] );
848   this->m_Axis2Actor->GetProperty( )->
849     SetColor( this->m_PlaneColors[ ( axis + 2 ) % 3 ] );
850
851   this->m_Plane->Modified( );
852   this->m_PlaneMapper->Modified( );
853   this->m_PlaneActor->Modified( );
854
855   this->m_Axis1->Modified( );
856   this->m_Axis1Mapper->Modified( );
857   this->m_Axis1Actor->Modified( );
858
859   this->m_Axis2->Modified( );
860   this->m_Axis2Mapper->Modified( );
861   this->m_Axis2Actor->Modified( );
862
863   // Update text
864   this->UpdateText( );
865
866   // Update lines from associated slices
867   /* TODO
868      auto sIt = this->m_AssociatedSlices.begin( );
869      for( ; sIt != this->m_AssociatedSlices.end( ); ++sIt )
870      {
871      Self* slice = *sIt;
872      for( unsigned int id = 0; id < slice->m_AssociatedSlices.size( ); ++id )
873      {
874      std::cout << id << std::endl;
875      if( slice->m_AssociatedSlices[ id ] != this )
876      continue;
877
878      std::cout << "id : " << id << std::endl;
879
880      } // rof
881
882      } // rof
883   */
884
885   // Update camera position
886   if( this->m_Window == NULL )
887     return;
888   vtkRenderer* renderer =
889     this->m_Window->GetRenderers( )->GetFirstRenderer( );
890   if( renderer == NULL )
891     return;
892   vtkCamera* camera = renderer->GetActiveCamera( );
893   if( camera == NULL )
894     return;
895   double cam_pos[ 3 ];
896   camera->GetPosition( cam_pos );
897   cam_pos[ axis ] += this->m_VisibleBounds[ axis << 1 ] - prev_pos;
898   camera->SetPosition( cam_pos );
899 }
900
901 // -------------------------------------------------------------------------
902 void cpExtensions::Visualization::ImageSliceActors::
903 SetSlice( double* pos )
904 {
905   vtkImageData* image = this->GetInputImage( );
906   if( image == NULL )
907     return;
908
909   int ijk[ 3 ];
910   double pcoords[ 3 ];
911   image->ComputeStructuredCoordinates( pos, ijk, pcoords );
912   this->SetSliceNumber( ijk[ this->GetAxis( ) ] );
913 }
914
915 // -------------------------------------------------------------------------
916 void cpExtensions::Visualization::ImageSliceActors::
917 UpdateText( )
918 {
919   if( this->m_ImageMapper.GetPointer( ) != NULL )
920   {
921     char axis;
922     int axId = this->m_ImageMapper->GetOrientation( );
923     if     ( axId == 0 ) axis = 'X';
924     else if( axId == 1 ) axis = 'Y';
925     else if( axId == 2 ) axis = 'Z';
926
927     std::sprintf(
928       this->m_TextBuffer, "Axis: %c (%d)",
929       axis, this->m_ImageMapper->GetSliceNumber( )
930       );
931   }
932   else
933     this->m_TextBuffer[ 0 ] = '\0';
934   this->m_TextActor->SetInput( this->m_TextBuffer );
935   this->m_TextActor->Modified( );
936   this->Modified( );
937 }
938
939 // -------------------------------------------------------------------------
940 void cpExtensions::Visualization::ImageSliceActors::
941 UpdateText( double pos[ 3 ] )
942 {
943   if( this->m_ImageMapper.GetPointer( ) != NULL )
944   {
945     char axis;
946     int axId = this->m_ImageMapper->GetOrientation( );
947     if     ( axId == 0 ) axis = 'X';
948     else if( axId == 1 ) axis = 'Y';
949     else if( axId == 2 ) axis = 'Z';
950     int slice = this->GetSliceNumber( );
951
952     vtkImageData* image = this->GetInputImage( );
953     int ijk[ 3 ];
954     double pcoords[ 3 ];
955     image->ComputeStructuredCoordinates( pos, ijk, pcoords );
956     ijk[ axId ] = slice;
957
958     int ext[ 6 ];
959     image->GetExtent( ext );
960     if(
961       ext[ 0 ] <= ijk[ 0 ] && ijk[ 0 ] <= ext[ 1 ] &&
962       ext[ 2 ] <= ijk[ 1 ] && ijk[ 1 ] <= ext[ 3 ] &&
963       ext[ 4 ] <= ijk[ 2 ] && ijk[ 2 ] <= ext[ 5 ]
964       )
965     {
966       int nScl = image->GetNumberOfScalarComponents( );
967       std::stringstream str;
968       str
969         << "[" << ijk[ 0 ]
970         << "," << ijk[ 1 ]
971         << "," << ijk[ 2 ] << "]=(";
972       str <<
973         image->GetScalarComponentAsFloat( ijk[ 0 ], ijk[ 1 ], ijk[ 2 ], 0 );
974       for( int n = 1; n < nScl; ++n )
975         str
976           << " "
977           << image->GetScalarComponentAsFloat(
978             ijk[ 0 ], ijk[ 1 ], ijk[ 2 ], n
979             );
980       str << ")";
981       std::sprintf(
982         this->m_TextBuffer, "Axis: %c (%d)\nPixel %s",
983         axis, slice, str.str( ).c_str( )
984         );
985
986     } // fi
987   }
988   else
989     this->m_TextBuffer[ 0 ] = '\0';
990   this->m_TextActor->SetInput( this->m_TextBuffer );
991   this->m_TextActor->Modified( );
992   this->Modified( );
993 }
994
995 // -------------------------------------------------------------------------
996 void cpExtensions::Visualization::ImageSliceActors::
997 UpdateText( const double& w, const double& l )
998 {
999   if( this->m_ImageMapper.GetPointer( ) != NULL )
1000   {
1001     char axis;
1002     int axId = this->m_ImageMapper->GetOrientation( );
1003     if     ( axId == 0 ) axis = 'X';
1004     else if( axId == 1 ) axis = 'Y';
1005     else if( axId == 2 ) axis = 'Z';
1006
1007     std::sprintf(
1008       this->m_TextBuffer, "Axis: %c (%d)\nW/L (%.2f/%.2f)",
1009       axis, this->m_ImageMapper->GetSliceNumber( ), w, l
1010       );
1011   }
1012   else
1013     this->m_TextBuffer[ 0 ] = '\0';
1014   this->m_TextActor->SetInput( this->m_TextBuffer );
1015   this->m_TextActor->Modified( );
1016   this->Modified( );
1017 }
1018
1019 // -------------------------------------------------------------------------
1020 cpExtensions::Visualization::ImageSliceActors::
1021 ImageSliceActors( )
1022   : Superclass( ),
1023     m_Window( NULL ),
1024     m_Interpolate( false )
1025 {
1026   this->Clear( );
1027   this->_ConfigureStyle( );
1028 }
1029
1030 // -------------------------------------------------------------------------
1031 cpExtensions::Visualization::ImageSliceActors::
1032 ~ImageSliceActors( )
1033 {
1034 }
1035
1036 // -------------------------------------------------------------------------
1037 void cpExtensions::Visualization::ImageSliceActors::
1038 _Render( )
1039 {
1040   if( this->m_Window == NULL )
1041     return;
1042   vtkRenderer* renderer =
1043     this->m_Window->GetRenderers( )->GetFirstRenderer( );
1044   if( renderer == NULL )
1045     return;
1046   renderer->SetAllocatedRenderTime( 1e-3 );
1047   this->m_Window->Render( );
1048 }
1049
1050 // -------------------------------------------------------------------------
1051 void cpExtensions::Visualization::ImageSliceActors::
1052 _ResetCamera( )
1053 {
1054   if( this->m_Window == NULL )
1055     return;
1056   vtkRenderer* renderer =
1057     this->m_Window->GetRenderers( )->GetFirstRenderer( );
1058   if( renderer == NULL )
1059     return;
1060   renderer->ResetCamera( );
1061 }
1062
1063 // -------------------------------------------------------------------------
1064 void cpExtensions::Visualization::ImageSliceActors::
1065 _ConfigureStyle( )
1066 {
1067   // Connect this view with a controller
1068   this->m_Style = vtkSmartPointer< TStyle >::New( );
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$