]> Creatis software - gdcm.git/blob - vtk/vtkImageColorViewer.cxx
Fix mistypings
[gdcm.git] / vtk / vtkImageColorViewer.cxx
1 /*=========================================================================
2
3   Program:   Visualization Toolkit
4   Module:    $RCSfile: vtkImageColorViewer.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 "vtkImageColorViewer.h"
16
17 #include "vtkCamera.h"
18 #include "vtkCommand.h"
19 #include "vtkImageActor.h"
20 #include "vtkImageData.h"
21 #include "vtkImageData.h"
22 #include "vtkImageMapToWindowLevelColors2.h"
23 #include "vtkInteractorStyleImage.h"
24 #include "vtkObjectFactory.h"
25 #include "vtkRenderWindow.h"
26 #include "vtkRenderWindowInteractor.h"
27 #include "vtkRenderer.h"
28
29 vtkCxxRevisionMacro(vtkImageColorViewer, "$Revision: 1.3 $")
30 vtkStandardNewMacro(vtkImageColorViewer)
31
32 //----------------------------------------------------------------------------
33 vtkImageColorViewer::vtkImageColorViewer()
34 {
35   this->RenderWindow    = NULL;
36   this->Renderer        = NULL;
37   this->ImageActor      = vtkImageActor::New();
38   this->WindowLevel     = vtkImageMapToWindowLevelColors2::New();
39   this->Interactor      = NULL;
40   this->InteractorStyle = NULL;
41
42   this->Slice = 0;
43   this->FirstRender = 1;
44   this->SliceOrientation = vtkImageColorViewer::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 vtkImageColorViewer::~vtkImageColorViewer()
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 vtkImageColorViewer::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 vtkImageColorViewer::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 vtkImageColorViewer::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 vtkImageColorViewer::SetSize(int a,int b) 
182 {
183   this->RenderWindow->SetSize(a, b);
184 }
185
186 //----------------------------------------------------------------------------
187 int* vtkImageColorViewer::GetSize() 
188 {
189   return this->RenderWindow->GetSize();
190 }
191
192 //----------------------------------------------------------------------------
193 void vtkImageColorViewer::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* vtkImageColorViewer::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 vtkImageColorViewer::GetSliceMin() 
219 {
220   int *range = this->GetSliceRange();
221   if (range)
222     {
223     return range[0];
224     }
225   return 0;
226 }
227
228 //----------------------------------------------------------------------------
229 int vtkImageColorViewer::GetSliceMax() 
230 {
231   int *range = this->GetSliceRange();
232   if (range)
233     {
234     return range[1];
235     }
236   return 0;
237 }
238
239 //----------------------------------------------------------------------------
240 void vtkImageColorViewer::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 vtkImageColorViewer::SetSliceOrientation(int orientation)
269 {
270   if (orientation < vtkImageColorViewer::SLICE_ORIENTATION_YZ ||
271       orientation > vtkImageColorViewer::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 vtkImageColorViewer::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 vtkImageColorViewer::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 vtkImageColorViewer::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 vtkImageColorViewer::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 vtkImageColorViewer::UpdateDisplayExtent()
338 {
339   vtkImageData *input = this->GetInput();
340   if (!input || !this->ImageActor)
341     {
342     return;
343     }
344
345   input->UpdateInformation();
346   int *w_ext = input->GetWholeExtent();
347
348   // Is the slice in range ? If not, fix it
349
350   int slice_min = w_ext[this->SliceOrientation * 2];
351   int slice_max = w_ext[this->SliceOrientation * 2 + 1];
352   if (this->Slice < slice_min || this->Slice > slice_max)
353     {
354     this->Slice = static_cast<int>((slice_min + slice_max) * 0.5);
355     }
356
357   // Set the image actor
358
359   switch (this->SliceOrientation)
360     {
361     case vtkImageColorViewer::SLICE_ORIENTATION_XY:
362       this->ImageActor->SetDisplayExtent(
363         w_ext[0], w_ext[1], w_ext[2], w_ext[3], this->Slice, this->Slice);
364       break;
365
366     case vtkImageColorViewer::SLICE_ORIENTATION_XZ:
367       this->ImageActor->SetDisplayExtent(
368         w_ext[0], w_ext[1], this->Slice, this->Slice, w_ext[4], w_ext[5]);
369       break;
370
371     case vtkImageColorViewer::SLICE_ORIENTATION_YZ:
372       this->ImageActor->SetDisplayExtent(
373         this->Slice, this->Slice, w_ext[2], w_ext[3], w_ext[4], w_ext[5]);
374       break;
375     }
376
377   // Figure out the correct clipping range
378
379   if (this->Renderer)
380     {
381     if (this->InteractorStyle && 
382         this->InteractorStyle->GetAutoAdjustCameraClippingRange())
383       {
384       this->Renderer->ResetCameraClippingRange();
385       }
386     else
387       {
388       vtkCamera *cam = this->Renderer->GetActiveCamera();
389       if (cam)
390         {
391         double bounds[6];
392         this->ImageActor->GetBounds(bounds);
393         double spos = (double)bounds[this->SliceOrientation * 2];
394         double cpos = (double)cam->GetPosition()[this->SliceOrientation];
395         double range = fabs(spos - cpos);
396         double *spacing = input->GetSpacing();
397         double avg_spacing = 
398           ((double)spacing[0] + (double)spacing[1] + (double)spacing[2]) / 3.0;
399         cam->SetClippingRange(
400           range - avg_spacing * 3.0, range + avg_spacing * 3.0);
401         }
402       }
403     }
404 }
405
406 //----------------------------------------------------------------------------
407 void vtkImageColorViewer::SetPosition(int a,int b) 
408 {
409   this->RenderWindow->SetPosition(a, b);
410 }
411
412 //----------------------------------------------------------------------------
413 int* vtkImageColorViewer::GetPosition() 
414 {
415   return this->RenderWindow->GetPosition();
416 }
417
418 //----------------------------------------------------------------------------
419 void vtkImageColorViewer::SetDisplayId(void *a) 
420 {
421   this->RenderWindow->SetDisplayId(a);
422 }
423
424 //----------------------------------------------------------------------------
425 void vtkImageColorViewer::SetWindowId(void *a) 
426 {
427   this->RenderWindow->SetWindowId(a);
428 }
429
430 //----------------------------------------------------------------------------
431 void vtkImageColorViewer::SetParentId(void *a) 
432 {
433   this->RenderWindow->SetParentId(a);
434 }
435
436 //----------------------------------------------------------------------------
437 double vtkImageColorViewer::GetColorWindow() 
438 {
439   return this->WindowLevel->GetWindow();
440 }
441
442 //----------------------------------------------------------------------------
443 double vtkImageColorViewer::GetColorLevel() 
444 {
445   return this->WindowLevel->GetLevel();
446 }
447
448 //----------------------------------------------------------------------------
449 void vtkImageColorViewer::SetColorWindow(double s) 
450 {
451   this->WindowLevel->SetWindow(s);
452 }
453
454 //----------------------------------------------------------------------------
455 void vtkImageColorViewer::SetColorLevel(double s) 
456 {
457   this->WindowLevel->SetLevel(s);
458 }
459
460 //----------------------------------------------------------------------------
461 class vtkImageColorViewerCallback : public vtkCommand
462 {
463 public:
464   static vtkImageColorViewerCallback *New() { return new vtkImageColorViewerCallback; }
465   
466   void Execute(vtkObject *caller, 
467                unsigned long event, 
468                void *vtkNotUsed(callData))
469     {
470       if (this->IV->GetInput() == NULL)
471         {
472         return;
473         }
474
475       // Reset
476
477       if (event == vtkCommand::ResetWindowLevelEvent)
478         {
479         this->IV->GetInput()->UpdateInformation();
480         this->IV->GetInput()->SetUpdateExtent
481           (this->IV->GetInput()->GetWholeExtent());
482         this->IV->GetInput()->Update();
483         double *range = this->IV->GetInput()->GetScalarRange();
484         this->IV->SetColorWindow(range[1] - range[0]);
485         this->IV->SetColorLevel(0.5 * (range[1] + range[0]));
486         this->IV->Render();
487         return;
488         }
489
490       // Start
491
492       if (event == vtkCommand::StartWindowLevelEvent)
493         {
494         this->InitialWindow = this->IV->GetColorWindow();
495         this->InitialLevel = this->IV->GetColorLevel();
496         return;
497         }
498       
499       // Adjust the window level here
500
501       vtkInteractorStyleImage *isi = 
502         static_cast<vtkInteractorStyleImage *>(caller);
503
504       int *size = this->IV->GetRenderWindow()->GetSize();
505       double window = this->InitialWindow;
506       double level = this->InitialLevel;
507       
508       // Compute normalized delta
509
510       double dx = 4.0 * 
511         (isi->GetWindowLevelCurrentPosition()[0] - 
512          isi->GetWindowLevelStartPosition()[0]) / size[0];
513       double dy = 4.0 * 
514         (isi->GetWindowLevelStartPosition()[1] - 
515          isi->GetWindowLevelCurrentPosition()[1]) / size[1];
516       
517       // Scale by current values
518
519       if (fabs(window) > 0.01)
520         {
521         dx = dx * window;
522         }
523       else
524         {
525         dx = dx * (window < 0 ? -0.01 : 0.01);
526         }
527       if (fabs(level) > 0.01)
528         {
529         dy = dy * level;
530         }
531       else
532         {
533         dy = dy * (level < 0 ? -0.01 : 0.01);
534         }
535       
536       // Abs so that direction does not flip
537
538       if (window < 0.0) 
539         {
540         dx = -1*dx;
541         }
542       if (level < 0.0) 
543         {
544         dy = -1*dy;
545         }
546       
547       // Compute new window level
548
549       double newWindow = dx + window;
550       double newLevel;
551       newLevel = level - dy;
552       
553       // Stay away from zero and really
554
555       if (fabs(newWindow) < 0.01)
556         {
557         newWindow = 0.01*(newWindow < 0 ? -1 : 1);
558         }
559       if (fabs(newLevel) < 0.01)
560         {
561         newLevel = 0.01*(newLevel < 0 ? -1 : 1);
562         }
563       
564       this->IV->SetColorWindow(newWindow);
565       this->IV->SetColorLevel(newLevel);
566       this->IV->Render();
567     }
568   
569   vtkImageColorViewer *IV;
570   double InitialWindow;
571   double InitialLevel;
572 };
573
574 //----------------------------------------------------------------------------
575 void vtkImageColorViewer::InstallPipeline()
576 {
577   if (this->RenderWindow && this->Renderer)
578     {
579     this->RenderWindow->AddRenderer(this->Renderer);
580     }
581
582   if (this->Interactor)
583     {
584     if (!this->InteractorStyle)
585       {
586       this->InteractorStyle = vtkInteractorStyleImage::New();
587       vtkImageColorViewerCallback *cbk = vtkImageColorViewerCallback::New();
588       cbk->IV = this;
589       this->InteractorStyle->AddObserver(
590         vtkCommand::WindowLevelEvent, cbk);
591       this->InteractorStyle->AddObserver(
592         vtkCommand::StartWindowLevelEvent, cbk);
593       this->InteractorStyle->AddObserver(
594         vtkCommand::ResetWindowLevelEvent, cbk);
595       cbk->Delete();
596       }
597     
598     this->Interactor->SetInteractorStyle(this->InteractorStyle);
599     this->Interactor->SetRenderWindow(this->RenderWindow);
600     }
601
602   if (this->Renderer && this->ImageActor)
603     {
604     this->Renderer->AddViewProp(this->ImageActor);
605     }
606
607   if (this->ImageActor && this->WindowLevel)
608     {
609     this->ImageActor->SetInput(this->WindowLevel->GetOutput());
610     }
611 }
612
613 //----------------------------------------------------------------------------
614 void vtkImageColorViewer::UnInstallPipeline()
615 {
616   if (this->ImageActor)
617     {
618     this->ImageActor->SetInput(NULL);
619     }
620
621   if (this->Renderer && this->ImageActor)
622     {
623     this->Renderer->RemoveViewProp(this->ImageActor);
624     }
625
626   if (this->RenderWindow && this->Renderer)
627     {
628     this->RenderWindow->RemoveRenderer(this->Renderer);
629     }
630
631   if (this->Interactor)
632     {
633     this->Interactor->SetInteractorStyle(NULL);
634     this->Interactor->SetRenderWindow(NULL);
635     }
636 }
637
638 //----------------------------------------------------------------------------
639 void vtkImageColorViewer::Render()
640 {
641   if (this->FirstRender)
642     {
643     // Initialize the size if not set yet
644
645     vtkImageData *input = this->GetInput();
646     if (this->RenderWindow->GetSize()[0] == 0 && input)
647       {
648       input->UpdateInformation();
649       int *w_ext = input->GetWholeExtent();
650       int xs = 0, ys = 0;
651
652       switch (this->SliceOrientation)
653         {
654         case vtkImageColorViewer::SLICE_ORIENTATION_XY:
655         default:
656           xs = w_ext[1] - w_ext[0] + 1;
657           ys = w_ext[3] - w_ext[2] + 1;
658           break;
659
660         case vtkImageColorViewer::SLICE_ORIENTATION_XZ:
661           xs = w_ext[1] - w_ext[0] + 1;
662           ys = w_ext[5] - w_ext[4] + 1;
663           break;
664
665         case vtkImageColorViewer::SLICE_ORIENTATION_YZ:
666           xs = w_ext[3] - w_ext[2] + 1;
667           ys = w_ext[5] - w_ext[4] + 1;
668           break;
669         }
670
671       // if it would be smaller than 150 by 100 then limit to 150 by 100
672       this->RenderWindow->SetSize(
673         xs < 150 ? 150 : xs, ys < 100 ? 100 : ys);
674
675       if (this->Renderer)
676         {
677         this->Renderer->ResetCamera();
678         this->Renderer->GetActiveCamera()->SetParallelScale(
679           xs < 150 ? 75 : (xs - 1 ) / 2.0);
680         }
681       this->FirstRender = 0;  
682       }
683     }
684   if (this->GetInput())
685     {
686     this->RenderWindow->Render();
687     }
688 }
689
690 //----------------------------------------------------------------------------
691 const char* vtkImageColorViewer::GetWindowName() 
692 {
693   return this->RenderWindow->GetWindowName();
694 }
695
696 //----------------------------------------------------------------------------
697 void vtkImageColorViewer::SetOffScreenRendering(int i)
698 {
699   this->RenderWindow->SetOffScreenRendering(i);
700 }
701
702 //----------------------------------------------------------------------------
703 int vtkImageColorViewer::GetOffScreenRendering()
704 {
705   return this->RenderWindow->GetOffScreenRendering();
706 }
707
708 //----------------------------------------------------------------------------
709 void vtkImageColorViewer::SetInput(vtkImageData *in) 
710 {
711   this->WindowLevel->SetInput(in);
712   this->UpdateDisplayExtent();
713 }
714 //----------------------------------------------------------------------------
715 vtkImageData* vtkImageColorViewer::GetInput()
716
717   return vtkImageData::SafeDownCast(this->WindowLevel->GetInput());
718 }
719
720 //----------------------------------------------------------------------------
721 void vtkImageColorViewer::SetInputConnection(vtkAlgorithmOutput* input) 
722 {
723   this->WindowLevel->SetInputConnection(input);
724   this->UpdateDisplayExtent();
725 }
726
727 //----------------------------------------------------------------------------
728 #ifndef VTK_LEGACY_REMOVE
729 int vtkImageColorViewer::GetWholeZMin()
730 {
731   VTK_LEGACY_REPLACED_BODY(vtkImageColorViewer::GetWholeZMin, "VTK 5.0",
732                            vtkImageColorViewer::GetSliceMin);
733   return this->GetSliceMin();
734 }
735 int vtkImageColorViewer::GetWholeZMax()
736 {
737   VTK_LEGACY_REPLACED_BODY(vtkImageColorViewer::GetWholeZMax, "VTK 5.0",
738                            vtkImageColorViewer::GetSliceMax);
739   return this->GetSliceMax();
740 }
741 int vtkImageColorViewer::GetZSlice()
742 {
743   VTK_LEGACY_REPLACED_BODY(vtkImageColorViewer::GetZSlice, "VTK 5.0",
744                            vtkImageColorViewer::GetSlice);
745   return this->GetSlice();
746 }
747 void vtkImageColorViewer::SetZSlice(int s)
748 {
749   VTK_LEGACY_REPLACED_BODY(vtkImageColorViewer::SetZSlice, "VTK 5.0",
750                            vtkImageColorViewer::SetSlice);
751   this->SetSlice(s);
752 }
753 #endif
754
755 //----------------------------------------------------------------------------
756 void vtkImageColorViewer::PrintSelf(ostream& os, vtkIndent indent)
757 {
758   this->Superclass::PrintSelf(os, indent);
759
760   os << indent << "RenderWindow:\n";
761   this->RenderWindow->PrintSelf(os,indent.GetNextIndent());
762   os << indent << "Renderer:\n";
763   this->Renderer->PrintSelf(os,indent.GetNextIndent());
764   os << indent << "ImageActor:\n";
765   this->ImageActor->PrintSelf(os,indent.GetNextIndent());
766   os << indent << "WindowLevel:\n" << endl;
767   this->WindowLevel->PrintSelf(os,indent.GetNextIndent());
768   os << indent << "Slice: " << this->Slice << endl;
769   os << indent << "SliceOrientation: " << this->SliceOrientation << endl;
770   os << indent << "InteractorStyle: " << endl;
771   if (this->InteractorStyle)
772     {
773     os << "\n";
774     this->InteractorStyle->PrintSelf(os,indent.GetNextIndent());
775     }
776   else
777     {
778     os << "None";
779     }
780 }