1 /*=========================================================================
3 Program: Visualization Toolkit
4 Module: $RCSfile: wxvtkImageViewer2.cxx,v $
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
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.
14 =========================================================================*/
15 #include "wxvtkImageViewer2.h"
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"
29 vtkCxxRevisionMacro(wxvtkImageViewer2, "$Revision: 1.6 $");
30 vtkStandardNewMacro(wxvtkImageViewer2);
32 //----------------------------------------------------------------------------
33 wxvtkImageViewer2::wxvtkImageViewer2()
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;
43 this->FirstRender = 1;
44 this->SliceOrientation = wxvtkImageViewer2::SLICE_ORIENTATION_XY;
48 vtkRenderWindow *renwin = vtkRenderWindow::New();
49 this->SetRenderWindow(renwin);
52 vtkRenderer *ren = vtkRenderer::New();
53 this->SetRenderer(ren);
56 this->InstallPipeline();
59 //----------------------------------------------------------------------------
60 wxvtkImageViewer2::~wxvtkImageViewer2()
62 if (this->WindowLevel)
64 this->WindowLevel->Delete();
65 this->WindowLevel = NULL;
70 this->ImageActor->Delete();
71 this->ImageActor = NULL;
76 this->Renderer->Delete();
77 this->Renderer = NULL;
80 if (this->RenderWindow)
82 this->RenderWindow->Delete();
83 this->RenderWindow = NULL;
88 this->Interactor->Delete();
89 this->Interactor = NULL;
92 if (this->InteractorStyle)
94 this->InteractorStyle->Delete();
95 this->InteractorStyle = NULL;
99 //----------------------------------------------------------------------------
100 void wxvtkImageViewer2::SetupInteractor(vtkRenderWindowInteractor *arg)
102 if (this->Interactor == arg)
107 this->UnInstallPipeline();
109 if (this->Interactor)
111 this->Interactor->UnRegister(this);
114 this->Interactor = arg;
116 if (this->Interactor)
118 this->Interactor->Register(this);
121 this->InstallPipeline();
125 this->Renderer->GetActiveCamera()->ParallelProjectionOn();
129 //----------------------------------------------------------------------------
130 void wxvtkImageViewer2::SetRenderWindow(vtkRenderWindow *arg)
132 if (this->RenderWindow == arg)
137 this->UnInstallPipeline();
139 if (this->RenderWindow)
141 this->RenderWindow->UnRegister(this);
144 this->RenderWindow = arg;
146 if (this->RenderWindow)
148 this->RenderWindow->Register(this);
151 this->InstallPipeline();
154 //----------------------------------------------------------------------------
155 void wxvtkImageViewer2::SetRenderer(vtkRenderer *arg)
157 if (this->Renderer == arg)
162 this->UnInstallPipeline();
166 this->Renderer->UnRegister(this);
169 this->Renderer = arg;
173 this->Renderer->Register(this);
176 this->InstallPipeline();
177 this->UpdateOrientation();
180 //----------------------------------------------------------------------------
181 void wxvtkImageViewer2::SetSize(int a,int b)
183 this->RenderWindow->SetSize(a, b);
186 //----------------------------------------------------------------------------
187 int* wxvtkImageViewer2::GetSize()
189 return this->RenderWindow->GetSize();
192 //----------------------------------------------------------------------------
193 void wxvtkImageViewer2::GetSliceRange(int &min, int &max)
195 vtkImageData *input = this->GetInput();
198 input->UpdateInformation();
199 int *w_ext = input->GetWholeExtent();
200 min = w_ext[this->SliceOrientation * 2];
201 max = w_ext[this->SliceOrientation * 2 + 1];
205 //----------------------------------------------------------------------------
206 int* wxvtkImageViewer2::GetSliceRange()
208 vtkImageData *input = this->GetInput();
211 input->UpdateInformation();
212 return input->GetWholeExtent() + this->SliceOrientation * 2;
217 //----------------------------------------------------------------------------
218 int wxvtkImageViewer2::GetSliceMin()
220 int *range = this->GetSliceRange();
228 //----------------------------------------------------------------------------
229 int wxvtkImageViewer2::GetSliceMax()
231 int *range = this->GetSliceRange();
239 //----------------------------------------------------------------------------
240 void wxvtkImageViewer2::SetSlice(int slice)
242 int *range = this->GetSliceRange();
245 if (slice < range[0])
249 else if (slice > range[1])
255 if (this->Slice == slice)
263 this->UpdateDisplayExtent();
267 //----------------------------------------------------------------------------
268 void wxvtkImageViewer2::SetSliceOrientation(int orientation)
270 if (orientation < wxvtkImageViewer2::SLICE_ORIENTATION_YZ ||
271 orientation > wxvtkImageViewer2::SLICE_ORIENTATION_XY)
273 vtkErrorMacro("Error - invalid slice orientation " << orientation);
277 if (this->SliceOrientation == orientation)
282 this->SliceOrientation = orientation;
286 int *range = this->GetSliceRange();
289 this->Slice = static_cast<int>((range[0] + range[1]) * 0.5);
292 this->UpdateOrientation();
293 this->UpdateDisplayExtent();
295 if (this->Renderer && this->GetInput())
297 double scale = this->Renderer->GetActiveCamera()->GetParallelScale();
298 this->Renderer->ResetCamera();
299 this->Renderer->GetActiveCamera()->SetParallelScale(scale);
305 //----------------------------------------------------------------------------
306 void wxvtkImageViewer2::UpdateOrientation()
308 // Set the camera position
310 vtkCamera *cam = this->Renderer ? this->Renderer->GetActiveCamera() : NULL;
314 // EED 21 mars FLIP problem ..PLOP..
315 switch (this->SliceOrientation)
317 case wxvtkImageViewer2::SLICE_ORIENTATION_YZ:
318 cam->SetViewUp(0,0,-1);
319 cam->SetPosition(-1,0,0); // -1 if medical ?
320 cam->SetFocalPoint(0,0,0);
323 case wxvtkImageViewer2::SLICE_ORIENTATION_XZ:
324 cam->SetViewUp(0,0,1);
325 cam->SetPosition(0,-1,0); // 1 if medical ?
326 cam->SetFocalPoint(0,0,0);
329 case wxvtkImageViewer2::SLICE_ORIENTATION_XY:
330 cam->SetViewUp(0,-1,0);
331 cam->SetPosition(0,0,-1);
332 cam->SetFocalPoint(0,0,0);
337 switch (this->SliceOrientation)
339 case wxvtkImageViewer2::SLICE_ORIENTATION_YZ:
340 cam->SetViewUp(0,0,1);
341 cam->SetPosition(1,0,0); // -1 if medical ?
342 cam->SetFocalPoint(0,0,0);
345 case wxvtkImageViewer2::SLICE_ORIENTATION_XZ:
346 cam->SetViewUp(0,0,1);
347 cam->SetPosition(0,-1,0); // 1 if medical ?
348 cam->SetFocalPoint(0,0,0);
351 case wxvtkImageViewer2::SLICE_ORIENTATION_XY:
352 cam->SetViewUp(0,1,0);
353 cam->SetPosition(0,0,1); // -1 if medical ?
354 cam->SetFocalPoint(0,0,0);
364 //----------------------------------------------------------------------------
365 void wxvtkImageViewer2::UpdateDisplayExtent()
367 vtkImageData *input = this->GetInput();
368 if (!input || !this->ImageActor)
373 // std::cout << "--- wxvtkImageViewer2::UpdateDisplayExtent()"<<std::endl;
374 input->UpdateInformation();
375 int *w_ext = input->GetWholeExtent();
377 // std::cout << "ext = "
378 // <<w_ext[0]<<" - "<<w_ext[1]<<" ; "
379 // <<w_ext[2]<<" - "<<w_ext[3]<<" ; "
380 // <<w_ext[4]<<" - "<<w_ext[5]
382 // Is the slice in range ? If not, fix it
384 int slice_min = w_ext[this->SliceOrientation * 2];
385 int slice_max = w_ext[this->SliceOrientation * 2 + 1];
386 if (this->Slice < slice_min || this->Slice > slice_max)
388 this->Slice = static_cast<int>((slice_min + slice_max) * 0.5);
391 // Set the image actor
393 switch (this->SliceOrientation)
395 case wxvtkImageViewer2::SLICE_ORIENTATION_XY:
396 this->ImageActor->SetDisplayExtent(
397 w_ext[0], w_ext[1], w_ext[2], w_ext[3], this->Slice, this->Slice);
400 case wxvtkImageViewer2::SLICE_ORIENTATION_XZ:
401 this->ImageActor->SetDisplayExtent(
402 w_ext[0], w_ext[1], this->Slice, this->Slice, w_ext[4], w_ext[5]);
405 case wxvtkImageViewer2::SLICE_ORIENTATION_YZ:
406 this->ImageActor->SetDisplayExtent(
407 this->Slice, this->Slice, w_ext[2], w_ext[3], w_ext[4], w_ext[5]);
411 // Figure out the correct clipping range
415 if (this->InteractorStyle &&
416 this->InteractorStyle->GetAutoAdjustCameraClippingRange())
418 this->Renderer->ResetCameraClippingRange();
422 vtkCamera *cam = this->Renderer->GetActiveCamera();
426 this->ImageActor->GetBounds(bounds);
427 double spos = bounds[this->SliceOrientation * 2];
428 double cpos = cam->GetPosition()[this->SliceOrientation];
429 double range = fabs(spos - cpos);
430 double *spacing = input->GetSpacing();
432 //(spacing[0] + spacing[1] + spacing[2]) / 3.0;
434 cam->SetClippingRange(
435 range - avg_spacing * 3.0, range + avg_spacing * 3.0);
441 //----------------------------------------------------------------------------
442 void wxvtkImageViewer2::SetPosition(int a,int b)
444 this->RenderWindow->SetPosition(a, b);
447 //----------------------------------------------------------------------------
448 int* wxvtkImageViewer2::GetPosition()
450 return this->RenderWindow->GetPosition();
453 //----------------------------------------------------------------------------
454 void wxvtkImageViewer2::SetDisplayId(void *a)
456 this->RenderWindow->SetDisplayId(a);
459 //----------------------------------------------------------------------------
460 void wxvtkImageViewer2::SetWindowId(void *a)
462 this->RenderWindow->SetWindowId(a);
465 //----------------------------------------------------------------------------
466 void wxvtkImageViewer2::SetParentId(void *a)
468 this->RenderWindow->SetParentId(a);
471 //----------------------------------------------------------------------------
472 double wxvtkImageViewer2::GetColorWindow()
474 return this->WindowLevel->GetWindow();
477 //----------------------------------------------------------------------------
478 double wxvtkImageViewer2::GetColorLevel()
480 return this->WindowLevel->GetLevel();
483 //----------------------------------------------------------------------------
484 void wxvtkImageViewer2::SetColorWindow(double s)
486 this->WindowLevel->SetWindow(s);
489 //----------------------------------------------------------------------------
490 void wxvtkImageViewer2::SetColorLevel(double s)
492 this->WindowLevel->SetLevel(s);
495 //----------------------------------------------------------------------------
496 class wxvtkImageViewer2Callback : public vtkCommand
499 static wxvtkImageViewer2Callback *New() { return new wxvtkImageViewer2Callback; }
501 void Execute(vtkObject *caller,
503 void *vtkNotUsed(callData))
505 if (this->IV->GetInput() == NULL)
512 if (event == vtkCommand::ResetWindowLevelEvent)
514 this->IV->GetInput()->UpdateInformation();
515 this->IV->GetInput()->SetUpdateExtent
516 (this->IV->GetInput()->GetWholeExtent());
517 this->IV->GetInput()->Update();
518 double *range = this->IV->GetInput()->GetScalarRange();
519 this->IV->SetColorWindow(range[1] - range[0]);
520 this->IV->SetColorLevel(0.5 * (range[1] + range[0]));
527 if (event == vtkCommand::StartWindowLevelEvent)
529 this->InitialWindow = this->IV->GetColorWindow();
530 this->InitialLevel = this->IV->GetColorLevel();
534 // Adjust the window level here
536 vtkInteractorStyleImage *isi =
537 static_cast<vtkInteractorStyleImage *>(caller);
539 int *size = this->IV->GetRenderWindow()->GetSize();
540 double window = this->InitialWindow;
541 double level = this->InitialLevel;
543 // Compute normalized delta
546 (isi->GetWindowLevelCurrentPosition()[0] -
547 isi->GetWindowLevelStartPosition()[0]) / size[0];
549 (isi->GetWindowLevelStartPosition()[1] -
550 isi->GetWindowLevelCurrentPosition()[1]) / size[1];
552 // Scale by current values
554 if (fabs(window) > 0.01)
560 dx = dx * (window < 0 ? -0.01 : 0.01);
562 if (fabs(level) > 0.01)
568 dy = dy * (level < 0 ? -0.01 : 0.01);
571 // Abs so that direction does not flip
582 // Compute new window level
584 double newWindow = dx + window;
586 newLevel = level - dy;
588 // Stay away from zero and really
590 if (fabs(newWindow) < 0.01)
592 newWindow = 0.01*(newWindow < 0 ? -1 : 1);
594 if (fabs(newLevel) < 0.01)
596 newLevel = 0.01*(newLevel < 0 ? -1 : 1);
599 this->IV->SetColorWindow(newWindow);
600 this->IV->SetColorLevel(newLevel);
604 wxvtkImageViewer2 *IV;
605 double InitialWindow;
609 //----------------------------------------------------------------------------
610 void wxvtkImageViewer2::InstallPipeline()
612 if (this->RenderWindow && this->Renderer)
614 this->RenderWindow->AddRenderer(this->Renderer);
617 if (this->Interactor)
619 if (!this->InteractorStyle)
621 this->InteractorStyle = vtkInteractorStyleImage::New();
622 wxvtkImageViewer2Callback *cbk = wxvtkImageViewer2Callback::New();
624 this->InteractorStyle->AddObserver(
625 vtkCommand::WindowLevelEvent, cbk);
626 this->InteractorStyle->AddObserver(
627 vtkCommand::StartWindowLevelEvent, cbk);
628 this->InteractorStyle->AddObserver(
629 vtkCommand::ResetWindowLevelEvent, cbk);
633 this->Interactor->SetInteractorStyle(this->InteractorStyle);
634 this->Interactor->SetRenderWindow(this->RenderWindow);
637 if (this->Renderer && this->ImageActor)
639 this->Renderer->AddViewProp(this->ImageActor);
642 if (this->ImageActor && this->WindowLevel)
644 this->ImageActor->SetInput(this->WindowLevel->GetOutput());
648 //----------------------------------------------------------------------------
649 void wxvtkImageViewer2::UnInstallPipeline()
651 if (this->ImageActor)
653 this->ImageActor->SetInput(NULL);
656 if (this->Renderer && this->ImageActor)
658 this->Renderer->RemoveViewProp(this->ImageActor);
661 if (this->RenderWindow && this->Renderer)
663 this->RenderWindow->RemoveRenderer(this->Renderer);
666 if (this->Interactor)
668 this->Interactor->SetInteractorStyle(NULL);
669 this->Interactor->SetRenderWindow(NULL);
673 //----------------------------------------------------------------------------
674 void wxvtkImageViewer2::Render()
676 if (this->FirstRender)
678 // Initialize the size if not set yet
680 vtkImageData *input = this->GetInput();
681 if (this->RenderWindow->GetSize()[0] == 0 &&
685 input->UpdateInformation();
686 int *w_ext = input->GetWholeExtent();
689 // std::cout << "wxvtkImageViewer2::Render ext = "
690 // <<w_ext[0]<<" - "<<w_ext[1]<<" ; "
691 // <<w_ext[2]<<" - "<<w_ext[3]<<" ; "
692 // <<w_ext[4]<<" - "<<w_ext[5]
695 switch (this->SliceOrientation)
697 case wxvtkImageViewer2::SLICE_ORIENTATION_XY:
699 xs = w_ext[1] - w_ext[0] + 1;
700 ys = w_ext[3] - w_ext[2] + 1;
701 // std::cout << "SLICE_ORIENTATION_XY" << std::endl;
704 case wxvtkImageViewer2::SLICE_ORIENTATION_XZ:
705 xs = w_ext[1] - w_ext[0] + 1;
706 ys = w_ext[5] - w_ext[4] + 1;
707 // std::cout << "SLICE_ORIENTATION_XZ" << std::endl;
710 case wxvtkImageViewer2::SLICE_ORIENTATION_YZ:
711 xs = w_ext[3] - w_ext[2] + 1;
712 ys = w_ext[5] - w_ext[4] + 1;
713 // std::cout << "SLICE_ORIENTATION_YZ" << std::endl;
717 // if it would be smaller than 150 by 100 then limit to 150 by 100
718 this->RenderWindow->SetSize(
719 xs < 150 ? 150 : xs, ys < 100 ? 100 : ys);
721 // std::cout << "wxvtkImageViewer2::Render() : "<<xs<<"-"<<ys<<std::endl;
724 this->Renderer->ResetCamera();
725 this->Renderer->GetActiveCamera()->SetParallelScale(
726 xs < 150 ? 75 : (xs - 1 ) / 2.0);
728 this->FirstRender = 0;
732 if (this->GetInput())
734 this->RenderWindow->Render();
738 //----------------------------------------------------------------------------
739 const char* wxvtkImageViewer2::GetWindowName()
741 return this->RenderWindow->GetWindowName();
744 //----------------------------------------------------------------------------
745 void wxvtkImageViewer2::SetOffScreenRendering(int i)
747 this->RenderWindow->SetOffScreenRendering(i);
750 //----------------------------------------------------------------------------
751 int wxvtkImageViewer2::GetOffScreenRendering()
753 return this->RenderWindow->GetOffScreenRendering();
756 //----------------------------------------------------------------------------
757 void wxvtkImageViewer2::SetInput(vtkImageData *in)
759 // std::cout << "### wxvtkImageViewer2::SetInput"<<std::endl;
760 this->WindowLevel->SetInput(in);
761 this->UpdateDisplayExtent();
765 //----------------------------------------------------------------------------
766 vtkImageData* wxvtkImageViewer2::GetInput()
768 return vtkImageData::SafeDownCast(this->WindowLevel->GetInput());
771 //----------------------------------------------------------------------------
772 void wxvtkImageViewer2::SetInputConnection(vtkAlgorithmOutput* input)
774 this->WindowLevel->SetInputConnection(input);
775 this->UpdateDisplayExtent();
778 //----------------------------------------------------------------------------
779 #ifndef VTK_LEGACY_REMOVE
780 int wxvtkImageViewer2::GetWholeZMin()
782 VTK_LEGACY_REPLACED_BODY(wxvtkImageViewer2::GetWholeZMin, "VTK 5.0",
783 wxvtkImageViewer2::GetSliceMin);
784 return this->GetSliceMin();
786 int wxvtkImageViewer2::GetWholeZMax()
788 VTK_LEGACY_REPLACED_BODY(wxvtkImageViewer2::GetWholeZMax, "VTK 5.0",
789 wxvtkImageViewer2::GetSliceMax);
790 return this->GetSliceMax();
792 int wxvtkImageViewer2::GetZSlice()
794 VTK_LEGACY_REPLACED_BODY(wxvtkImageViewer2::GetZSlice, "VTK 5.0",
795 wxvtkImageViewer2::GetSlice);
796 return this->GetSlice();
798 void wxvtkImageViewer2::SetZSlice(int s)
800 VTK_LEGACY_REPLACED_BODY(wxvtkImageViewer2::SetZSlice, "VTK 5.0",
801 wxvtkImageViewer2::SetSlice);
806 //----------------------------------------------------------------------------
807 void wxvtkImageViewer2::PrintSelf(ostream& os, vtkIndent indent)
809 this->Superclass::PrintSelf(os, indent);
811 os << indent << "RenderWindow:\n";
812 this->RenderWindow->PrintSelf(os,indent.GetNextIndent());
813 os << indent << "Renderer:\n";
814 this->Renderer->PrintSelf(os,indent.GetNextIndent());
815 os << indent << "ImageActor:\n";
816 this->ImageActor->PrintSelf(os,indent.GetNextIndent());
817 os << indent << "WindowLevel:\n" << endl;
818 this->WindowLevel->PrintSelf(os,indent.GetNextIndent());
819 os << indent << "Slice: " << this->Slice << endl;
820 os << indent << "SliceOrientation: " << this->SliceOrientation << endl;
821 os << indent << "InteractorStyle: " << endl;
822 if (this->InteractorStyle)
825 this->InteractorStyle->PrintSelf(os,indent.GetNextIndent());