]> Creatis software - bbtk.git/blob - packages/wxvtk/src/wxvtkImageViewer2.cxx
2fac472306cf414cbc8456f05246aa48ee5aa802
[bbtk.git] / packages / wxvtk / src / wxvtkImageViewer2.cxx
1 /*=========================================================================
2
3   Program:   Visualization Toolkit
4   Module:    $RCSfile: wxvtkImageViewer2.cxx,v $
5
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13
14 =========================================================================*/
15 #include "wxvtkImageViewer2.h"
16
17 #include "vtkCamera.h"
18 #include "vtkCommand.h"
19 #include "vtkImageActor.h"
20 #include "vtkImageData.h"
21 #include "vtkImageData.h"
22 #include "vtkImageMapToWindowLevelColors.h"
23 #include "vtkInteractorStyleImage.h"
24 #include "vtkObjectFactory.h"
25 #include "vtkRenderWindow.h"
26 #include "vtkRenderWindowInteractor.h"
27 #include "vtkRenderer.h"
28
29 vtkCxxRevisionMacro(wxvtkImageViewer2, "$Revision: 1.5 $");
30 vtkStandardNewMacro(wxvtkImageViewer2);
31
32 //----------------------------------------------------------------------------
33 wxvtkImageViewer2::wxvtkImageViewer2()
34 {
35   this->RenderWindow    = NULL;
36   this->Renderer        = NULL;
37   this->ImageActor      = vtkImageActor::New();
38   this->WindowLevel     = vtkImageMapToWindowLevelColors::New();
39   this->Interactor      = NULL;
40   this->InteractorStyle = NULL;
41
42   this->Slice = 0;
43   this->FirstRender = 1;
44   this->SliceOrientation = wxvtkImageViewer2::SLICE_ORIENTATION_XY;
45
46   // Setup the pipeline
47
48   vtkRenderWindow *renwin = vtkRenderWindow::New();
49   this->SetRenderWindow(renwin);
50   renwin->Delete();
51
52   vtkRenderer *ren = vtkRenderer::New();
53   this->SetRenderer(ren);
54   ren->Delete();
55
56   this->InstallPipeline();
57 }
58
59 //----------------------------------------------------------------------------
60 wxvtkImageViewer2::~wxvtkImageViewer2()
61 {
62   if (this->WindowLevel)
63     {
64     this->WindowLevel->Delete();
65     this->WindowLevel = NULL;
66     }
67
68   if (this->ImageActor)
69     {
70     this->ImageActor->Delete();
71     this->ImageActor = NULL;
72     }
73
74   if (this->Renderer)
75     {
76     this->Renderer->Delete();
77     this->Renderer = NULL;
78     }
79
80   if (this->RenderWindow)
81     {
82     this->RenderWindow->Delete();
83     this->RenderWindow = NULL;
84     }
85
86   if (this->Interactor)
87     {
88     this->Interactor->Delete();
89     this->Interactor = NULL;
90     }
91
92   if (this->InteractorStyle)
93     {
94     this->InteractorStyle->Delete();
95     this->InteractorStyle = NULL;
96     }
97 }
98
99 //----------------------------------------------------------------------------
100 void wxvtkImageViewer2::SetupInteractor(vtkRenderWindowInteractor *arg)
101 {
102   if (this->Interactor == arg)
103     {
104     return;
105     }
106
107   this->UnInstallPipeline();
108
109   if (this->Interactor)
110     {
111     this->Interactor->UnRegister(this);
112     }
113
114   this->Interactor = arg;
115
116   if (this->Interactor)
117     {
118     this->Interactor->Register(this);
119     }
120
121   this->InstallPipeline();
122
123   if (this->Renderer)
124     {
125     this->Renderer->GetActiveCamera()->ParallelProjectionOn();
126     }
127 }
128
129 //----------------------------------------------------------------------------
130 void wxvtkImageViewer2::SetRenderWindow(vtkRenderWindow *arg)
131 {
132   if (this->RenderWindow == arg)
133     {
134     return;
135     }
136
137   this->UnInstallPipeline();
138
139   if (this->RenderWindow)
140     {
141     this->RenderWindow->UnRegister(this);
142     }
143
144   this->RenderWindow = arg;
145
146   if (this->RenderWindow)
147     {
148     this->RenderWindow->Register(this);
149     }
150
151   this->InstallPipeline();
152 }
153
154 //----------------------------------------------------------------------------
155 void wxvtkImageViewer2::SetRenderer(vtkRenderer *arg)
156 {
157   if (this->Renderer == arg)
158     {
159     return;
160     }
161
162   this->UnInstallPipeline();
163
164   if (this->Renderer)
165     {
166     this->Renderer->UnRegister(this);
167     }
168
169   this->Renderer = arg;
170
171   if (this->Renderer)
172     {
173     this->Renderer->Register(this);
174     }
175
176   this->InstallPipeline();
177   this->UpdateOrientation();
178 }
179
180 //----------------------------------------------------------------------------
181 void wxvtkImageViewer2::SetSize(int a,int b)
182 {
183   this->RenderWindow->SetSize(a, b);
184 }
185
186 //----------------------------------------------------------------------------
187 int* wxvtkImageViewer2::GetSize()
188 {
189   return this->RenderWindow->GetSize();
190 }
191
192 //----------------------------------------------------------------------------
193 void wxvtkImageViewer2::GetSliceRange(int &min, int &max)
194 {
195   vtkImageData *input = this->GetInput();
196   if (input)
197     {
198     input->UpdateInformation();
199     int *w_ext = input->GetWholeExtent();
200     min = w_ext[this->SliceOrientation * 2];
201     max = w_ext[this->SliceOrientation * 2 + 1];
202     }
203 }
204
205 //----------------------------------------------------------------------------
206 int* wxvtkImageViewer2::GetSliceRange()
207 {
208   vtkImageData *input = this->GetInput();
209   if (input)
210     {
211     input->UpdateInformation();
212     return input->GetWholeExtent() + this->SliceOrientation * 2;
213     }
214   return NULL;
215 }
216
217 //----------------------------------------------------------------------------
218 int wxvtkImageViewer2::GetSliceMin()
219 {
220   int *range = this->GetSliceRange();
221   if (range)
222     {
223     return range[0];
224     }
225   return 0;
226 }
227
228 //----------------------------------------------------------------------------
229 int wxvtkImageViewer2::GetSliceMax()
230 {
231   int *range = this->GetSliceRange();
232   if (range)
233     {
234     return range[1];
235     }
236   return 0;
237 }
238
239 //----------------------------------------------------------------------------
240 void wxvtkImageViewer2::SetSlice(int slice)
241 {
242   int *range = this->GetSliceRange();
243   if (range)
244     {
245     if (slice < range[0])
246       {
247       slice = range[0];
248       }
249     else if (slice > range[1])
250       {
251       slice = range[1];
252       }
253     }
254
255   if (this->Slice == slice)
256     {
257     return;
258     }
259
260   this->Slice = slice;
261   this->Modified();
262
263   this->UpdateDisplayExtent();
264   this->Render();
265 }
266
267 //----------------------------------------------------------------------------
268 void wxvtkImageViewer2::SetSliceOrientation(int orientation)
269 {
270   if (orientation < wxvtkImageViewer2::SLICE_ORIENTATION_YZ ||
271       orientation > wxvtkImageViewer2::SLICE_ORIENTATION_XY)
272     {
273     vtkErrorMacro("Error - invalid slice orientation " << orientation);
274     return;
275     }
276
277   if (this->SliceOrientation == orientation)
278     {
279     return;
280     }
281
282   this->SliceOrientation = orientation;
283
284   // Update the viewer
285
286   int *range = this->GetSliceRange();
287   if (range)
288     {
289     this->Slice = static_cast<int>((range[0] + range[1]) * 0.5);
290     }
291
292   this->UpdateOrientation();
293   this->UpdateDisplayExtent();
294
295   if (this->Renderer && this->GetInput())
296     {
297     double scale = this->Renderer->GetActiveCamera()->GetParallelScale();
298     this->Renderer->ResetCamera();
299     this->Renderer->GetActiveCamera()->SetParallelScale(scale);
300     }
301
302   this->Render();
303 }
304
305 //----------------------------------------------------------------------------
306 void wxvtkImageViewer2::UpdateOrientation()
307 {
308   // Set the camera position
309
310   vtkCamera *cam = this->Renderer ? this->Renderer->GetActiveCamera() : NULL;
311   if (cam)
312     {
313     switch (this->SliceOrientation)
314       {
315       case wxvtkImageViewer2::SLICE_ORIENTATION_XY:
316         cam->SetFocalPoint(0,0,0);
317         cam->SetPosition(0,0,1); // -1 if medical ?
318         cam->SetViewUp(0,1,0);
319         break;
320
321       case wxvtkImageViewer2::SLICE_ORIENTATION_XZ:
322         cam->SetFocalPoint(0,0,0);
323         cam->SetPosition(0,-1,0); // 1 if medical ?
324         cam->SetViewUp(0,0,1);
325         break;
326
327       case wxvtkImageViewer2::SLICE_ORIENTATION_YZ:
328         cam->SetFocalPoint(0,0,0);
329         cam->SetPosition(1,0,0); // -1 if medical ?
330         cam->SetViewUp(0,0,1);
331         break;
332       }
333     }
334 }
335
336 //----------------------------------------------------------------------------
337 void wxvtkImageViewer2::UpdateDisplayExtent()
338 {
339   vtkImageData *input = this->GetInput();
340   if (!input || !this->ImageActor)
341     {
342     return;
343     }
344
345   //  std::cout << "--- wxvtkImageViewer2::UpdateDisplayExtent()"<<std::endl;
346   input->UpdateInformation();
347   int *w_ext = input->GetWholeExtent();
348
349   //    std::cout << "ext = "
350   //    <<w_ext[0]<<" - "<<w_ext[1]<<" ; "
351   //            <<w_ext[2]<<" - "<<w_ext[3]<<" ; "
352   //            <<w_ext[4]<<" - "<<w_ext[5]
353   //            <<std::endl;
354       // Is the slice in range ? If not, fix it
355
356   int slice_min = w_ext[this->SliceOrientation * 2];
357   int slice_max = w_ext[this->SliceOrientation * 2 + 1];
358   if (this->Slice < slice_min || this->Slice > slice_max)
359     {
360     this->Slice = static_cast<int>((slice_min + slice_max) * 0.5);
361     }
362
363   // Set the image actor
364
365   switch (this->SliceOrientation)
366     {
367     case wxvtkImageViewer2::SLICE_ORIENTATION_XY:
368       this->ImageActor->SetDisplayExtent(
369         w_ext[0], w_ext[1], w_ext[2], w_ext[3], this->Slice, this->Slice);
370       break;
371
372     case wxvtkImageViewer2::SLICE_ORIENTATION_XZ:
373       this->ImageActor->SetDisplayExtent(
374         w_ext[0], w_ext[1], this->Slice, this->Slice, w_ext[4], w_ext[5]);
375       break;
376
377     case wxvtkImageViewer2::SLICE_ORIENTATION_YZ:
378       this->ImageActor->SetDisplayExtent(
379         this->Slice, this->Slice, w_ext[2], w_ext[3], w_ext[4], w_ext[5]);
380       break;
381     }
382
383   // Figure out the correct clipping range
384
385   if (this->Renderer)
386     {
387     if (this->InteractorStyle &&
388         this->InteractorStyle->GetAutoAdjustCameraClippingRange())
389       {
390       this->Renderer->ResetCameraClippingRange();
391       }
392     else
393       {
394       vtkCamera *cam = this->Renderer->GetActiveCamera();
395       if (cam)
396         {
397         double bounds[6];
398         this->ImageActor->GetBounds(bounds);
399         double spos = bounds[this->SliceOrientation * 2];
400         double cpos = cam->GetPosition()[this->SliceOrientation];
401         double range = fabs(spos - cpos);
402         double *spacing = input->GetSpacing();
403         double avg_spacing =
404           //(spacing[0] + spacing[1] + spacing[2]) / 3.0;
405           spacing[2]; // JPR??
406         cam->SetClippingRange(
407           range - avg_spacing * 3.0, range + avg_spacing * 3.0);
408         }
409       }
410     }
411 }
412
413 //----------------------------------------------------------------------------
414 void wxvtkImageViewer2::SetPosition(int a,int b)
415 {
416   this->RenderWindow->SetPosition(a, b);
417 }
418
419 //----------------------------------------------------------------------------
420 int* wxvtkImageViewer2::GetPosition()
421 {
422   return this->RenderWindow->GetPosition();
423 }
424
425 //----------------------------------------------------------------------------
426 void wxvtkImageViewer2::SetDisplayId(void *a)
427 {
428   this->RenderWindow->SetDisplayId(a);
429 }
430
431 //----------------------------------------------------------------------------
432 void wxvtkImageViewer2::SetWindowId(void *a)
433 {
434   this->RenderWindow->SetWindowId(a);
435 }
436
437 //----------------------------------------------------------------------------
438 void wxvtkImageViewer2::SetParentId(void *a)
439 {
440   this->RenderWindow->SetParentId(a);
441 }
442
443 //----------------------------------------------------------------------------
444 double wxvtkImageViewer2::GetColorWindow()
445 {
446   return this->WindowLevel->GetWindow();
447 }
448
449 //----------------------------------------------------------------------------
450 double wxvtkImageViewer2::GetColorLevel()
451 {
452   return this->WindowLevel->GetLevel();
453 }
454
455 //----------------------------------------------------------------------------
456 void wxvtkImageViewer2::SetColorWindow(double s)
457 {
458   this->WindowLevel->SetWindow(s);
459 }
460
461 //----------------------------------------------------------------------------
462 void wxvtkImageViewer2::SetColorLevel(double s)
463 {
464   this->WindowLevel->SetLevel(s);
465 }
466
467 //----------------------------------------------------------------------------
468 class wxvtkImageViewer2Callback : public vtkCommand
469 {
470 public:
471   static wxvtkImageViewer2Callback *New() { return new wxvtkImageViewer2Callback; }
472
473   void Execute(vtkObject *caller,
474                unsigned long event,
475                void *vtkNotUsed(callData))
476     {
477       if (this->IV->GetInput() == NULL)
478         {
479         return;
480         }
481
482       // Reset
483
484       if (event == vtkCommand::ResetWindowLevelEvent)
485         {
486         this->IV->GetInput()->UpdateInformation();
487         this->IV->GetInput()->SetUpdateExtent
488           (this->IV->GetInput()->GetWholeExtent());
489         this->IV->GetInput()->Update();
490         double *range = this->IV->GetInput()->GetScalarRange();
491         this->IV->SetColorWindow(range[1] - range[0]);
492         this->IV->SetColorLevel(0.5 * (range[1] + range[0]));
493         this->IV->Render();
494         return;
495         }
496
497       // Start
498
499       if (event == vtkCommand::StartWindowLevelEvent)
500         {
501         this->InitialWindow = this->IV->GetColorWindow();
502         this->InitialLevel = this->IV->GetColorLevel();
503         return;
504         }
505
506       // Adjust the window level here
507
508       vtkInteractorStyleImage *isi =
509         static_cast<vtkInteractorStyleImage *>(caller);
510
511       int *size = this->IV->GetRenderWindow()->GetSize();
512       double window = this->InitialWindow;
513       double level = this->InitialLevel;
514
515       // Compute normalized delta
516
517       double dx = 4.0 *
518         (isi->GetWindowLevelCurrentPosition()[0] -
519          isi->GetWindowLevelStartPosition()[0]) / size[0];
520       double dy = 4.0 *
521         (isi->GetWindowLevelStartPosition()[1] -
522          isi->GetWindowLevelCurrentPosition()[1]) / size[1];
523
524       // Scale by current values
525
526       if (fabs(window) > 0.01)
527         {
528         dx = dx * window;
529         }
530       else
531         {
532         dx = dx * (window < 0 ? -0.01 : 0.01);
533         }
534       if (fabs(level) > 0.01)
535         {
536         dy = dy * level;
537         }
538       else
539         {
540         dy = dy * (level < 0 ? -0.01 : 0.01);
541         }
542
543       // Abs so that direction does not flip
544
545       if (window < 0.0)
546         {
547         dx = -1*dx;
548         }
549       if (level < 0.0)
550         {
551         dy = -1*dy;
552         }
553
554       // Compute new window level
555
556       double newWindow = dx + window;
557       double newLevel;
558       newLevel = level - dy;
559
560       // Stay away from zero and really
561
562       if (fabs(newWindow) < 0.01)
563         {
564         newWindow = 0.01*(newWindow < 0 ? -1 : 1);
565         }
566       if (fabs(newLevel) < 0.01)
567         {
568         newLevel = 0.01*(newLevel < 0 ? -1 : 1);
569         }
570
571       this->IV->SetColorWindow(newWindow);
572       this->IV->SetColorLevel(newLevel);
573       this->IV->Render();
574     }
575
576   wxvtkImageViewer2 *IV;
577   double InitialWindow;
578   double InitialLevel;
579 };
580
581 //----------------------------------------------------------------------------
582 void wxvtkImageViewer2::InstallPipeline()
583 {
584   if (this->RenderWindow && this->Renderer)
585     {
586     this->RenderWindow->AddRenderer(this->Renderer);
587     }
588
589   if (this->Interactor)
590     {
591     if (!this->InteractorStyle)
592       {
593       this->InteractorStyle = vtkInteractorStyleImage::New();
594       wxvtkImageViewer2Callback *cbk = wxvtkImageViewer2Callback::New();
595       cbk->IV = this;
596       this->InteractorStyle->AddObserver(
597         vtkCommand::WindowLevelEvent, cbk);
598       this->InteractorStyle->AddObserver(
599         vtkCommand::StartWindowLevelEvent, cbk);
600       this->InteractorStyle->AddObserver(
601         vtkCommand::ResetWindowLevelEvent, cbk);
602       cbk->Delete();
603       }
604
605     this->Interactor->SetInteractorStyle(this->InteractorStyle);
606     this->Interactor->SetRenderWindow(this->RenderWindow);
607     }
608
609   if (this->Renderer && this->ImageActor)
610     {
611     this->Renderer->AddViewProp(this->ImageActor);
612     }
613
614   if (this->ImageActor && this->WindowLevel)
615     {
616     this->ImageActor->SetInput(this->WindowLevel->GetOutput());
617     }
618 }
619
620 //----------------------------------------------------------------------------
621 void wxvtkImageViewer2::UnInstallPipeline()
622 {
623   if (this->ImageActor)
624     {
625     this->ImageActor->SetInput(NULL);
626     }
627
628   if (this->Renderer && this->ImageActor)
629     {
630     this->Renderer->RemoveViewProp(this->ImageActor);
631     }
632
633   if (this->RenderWindow && this->Renderer)
634     {
635     this->RenderWindow->RemoveRenderer(this->Renderer);
636     }
637
638   if (this->Interactor)
639     {
640     this->Interactor->SetInteractorStyle(NULL);
641     this->Interactor->SetRenderWindow(NULL);
642     }
643 }
644
645 //----------------------------------------------------------------------------
646 void wxvtkImageViewer2::Render()
647 {
648   if (this->FirstRender)
649     {
650     // Initialize the size if not set yet
651
652     vtkImageData *input = this->GetInput();
653     if (this->RenderWindow->GetSize()[0] == 0 &&
654         input)
655       {
656
657       input->UpdateInformation();
658       int *w_ext = input->GetWholeExtent();
659       int xs = 0, ys = 0;
660
661       //        std::cout << "wxvtkImageViewer2::Render ext = "
662       //        <<w_ext[0]<<" - "<<w_ext[1]<<" ; "
663       //                <<w_ext[2]<<" - "<<w_ext[3]<<" ; "
664       //                <<w_ext[4]<<" - "<<w_ext[5]
665       //                <<std::endl;
666
667       switch (this->SliceOrientation)
668         {
669         case wxvtkImageViewer2::SLICE_ORIENTATION_XY:
670         default:
671           xs = w_ext[1] - w_ext[0] + 1;
672           ys = w_ext[3] - w_ext[2] + 1;
673           //      std::cout << "SLICE_ORIENTATION_XY" << std::endl;
674           break;
675
676         case wxvtkImageViewer2::SLICE_ORIENTATION_XZ:
677           xs = w_ext[1] - w_ext[0] + 1;
678           ys = w_ext[5] - w_ext[4] + 1;
679           //      std::cout << "SLICE_ORIENTATION_XZ" << std::endl;
680           break;
681
682         case wxvtkImageViewer2::SLICE_ORIENTATION_YZ:
683           xs = w_ext[3] - w_ext[2] + 1;
684           ys = w_ext[5] - w_ext[4] + 1;
685           //      std::cout << "SLICE_ORIENTATION_YZ" << std::endl;
686           break;
687         }
688
689       // if it would be smaller than 150 by 100 then limit to 150 by 100
690       this->RenderWindow->SetSize(
691         xs < 150 ? 150 : xs, ys < 100 ? 100 : ys);
692
693       //      std::cout << "wxvtkImageViewer2::Render() : "<<xs<<"-"<<ys<<std::endl;
694       if (this->Renderer)
695         {
696         this->Renderer->ResetCamera();
697         this->Renderer->GetActiveCamera()->SetParallelScale(
698           xs < 150 ? 75 : (xs - 1 ) / 2.0);
699         }
700       this->FirstRender = 0;
701
702       }
703     }
704   if (this->GetInput())
705     {
706     this->RenderWindow->Render();
707     }
708 }
709
710 //----------------------------------------------------------------------------
711 const char* wxvtkImageViewer2::GetWindowName()
712 {
713   return this->RenderWindow->GetWindowName();
714 }
715
716 //----------------------------------------------------------------------------
717 void wxvtkImageViewer2::SetOffScreenRendering(int i)
718 {
719   this->RenderWindow->SetOffScreenRendering(i);
720 }
721
722 //----------------------------------------------------------------------------
723 int wxvtkImageViewer2::GetOffScreenRendering()
724 {
725   return this->RenderWindow->GetOffScreenRendering();
726 }
727
728 //----------------------------------------------------------------------------
729 void wxvtkImageViewer2::SetInput(vtkImageData *in)
730 {
731   //  std::cout << "### wxvtkImageViewer2::SetInput"<<std::endl;
732   this->WindowLevel->SetInput(in);
733   this->UpdateDisplayExtent();
734   // LG 03/12/08
735   //  FirstRender = 1;
736 }
737 //----------------------------------------------------------------------------
738 vtkImageData* wxvtkImageViewer2::GetInput()
739 {
740   return vtkImageData::SafeDownCast(this->WindowLevel->GetInput());
741 }
742
743 //----------------------------------------------------------------------------
744 void wxvtkImageViewer2::SetInputConnection(vtkAlgorithmOutput* input)
745 {
746   this->WindowLevel->SetInputConnection(input);
747   this->UpdateDisplayExtent();
748 }
749
750 //----------------------------------------------------------------------------
751 #ifndef VTK_LEGACY_REMOVE
752 int wxvtkImageViewer2::GetWholeZMin()
753 {
754   VTK_LEGACY_REPLACED_BODY(wxvtkImageViewer2::GetWholeZMin, "VTK 5.0",
755                            wxvtkImageViewer2::GetSliceMin);
756   return this->GetSliceMin();
757 }
758 int wxvtkImageViewer2::GetWholeZMax()
759 {
760   VTK_LEGACY_REPLACED_BODY(wxvtkImageViewer2::GetWholeZMax, "VTK 5.0",
761                            wxvtkImageViewer2::GetSliceMax);
762   return this->GetSliceMax();
763 }
764 int wxvtkImageViewer2::GetZSlice()
765 {
766   VTK_LEGACY_REPLACED_BODY(wxvtkImageViewer2::GetZSlice, "VTK 5.0",
767                            wxvtkImageViewer2::GetSlice);
768   return this->GetSlice();
769 }
770 void wxvtkImageViewer2::SetZSlice(int s)
771 {
772   VTK_LEGACY_REPLACED_BODY(wxvtkImageViewer2::SetZSlice, "VTK 5.0",
773                            wxvtkImageViewer2::SetSlice);
774   this->SetSlice(s);
775 }
776 #endif
777
778 //----------------------------------------------------------------------------
779 void wxvtkImageViewer2::PrintSelf(ostream& os, vtkIndent indent)
780 {
781   this->Superclass::PrintSelf(os, indent);
782
783   os << indent << "RenderWindow:\n";
784   this->RenderWindow->PrintSelf(os,indent.GetNextIndent());
785   os << indent << "Renderer:\n";
786   this->Renderer->PrintSelf(os,indent.GetNextIndent());
787   os << indent << "ImageActor:\n";
788   this->ImageActor->PrintSelf(os,indent.GetNextIndent());
789   os << indent << "WindowLevel:\n" << endl;
790   this->WindowLevel->PrintSelf(os,indent.GetNextIndent());
791   os << indent << "Slice: " << this->Slice << endl;
792   os << indent << "SliceOrientation: " << this->SliceOrientation << endl;
793   os << indent << "InteractorStyle: " << endl;
794   if (this->InteractorStyle)
795     {
796     os << "\n";
797     this->InteractorStyle->PrintSelf(os,indent.GetNextIndent());
798     }
799   else
800     {
801     os << "None";
802     }
803 }