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.3 $");
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;
313 switch (this->SliceOrientation)
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);
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);
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);
336 //----------------------------------------------------------------------------
337 void wxvtkImageViewer2::UpdateDisplayExtent()
339 vtkImageData *input = this->GetInput();
340 if (!input || !this->ImageActor)
345 // std::cout << "--- wxvtkImageViewer2::UpdateDisplayExtent()"<<std::endl;
346 input->UpdateInformation();
347 int *w_ext = input->GetWholeExtent();
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]
354 // Is the slice in range ? If not, fix it
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)
360 this->Slice = static_cast<int>((slice_min + slice_max) * 0.5);
363 // Set the image actor
365 switch (this->SliceOrientation)
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);
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]);
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]);
383 // Figure out the correct clipping range
387 if (this->InteractorStyle &&
388 this->InteractorStyle->GetAutoAdjustCameraClippingRange())
390 this->Renderer->ResetCameraClippingRange();
394 vtkCamera *cam = this->Renderer->GetActiveCamera();
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();
404 //(spacing[0] + spacing[1] + spacing[2]) / 3.0;
406 cam->SetClippingRange(
407 range - avg_spacing * 3.0, range + avg_spacing * 3.0);
413 //----------------------------------------------------------------------------
414 void wxvtkImageViewer2::SetPosition(int a,int b)
416 this->RenderWindow->SetPosition(a, b);
419 //----------------------------------------------------------------------------
420 int* wxvtkImageViewer2::GetPosition()
422 return this->RenderWindow->GetPosition();
425 //----------------------------------------------------------------------------
426 void wxvtkImageViewer2::SetDisplayId(void *a)
428 this->RenderWindow->SetDisplayId(a);
431 //----------------------------------------------------------------------------
432 void wxvtkImageViewer2::SetWindowId(void *a)
434 this->RenderWindow->SetWindowId(a);
437 //----------------------------------------------------------------------------
438 void wxvtkImageViewer2::SetParentId(void *a)
440 this->RenderWindow->SetParentId(a);
443 //----------------------------------------------------------------------------
444 double wxvtkImageViewer2::GetColorWindow()
446 return this->WindowLevel->GetWindow();
449 //----------------------------------------------------------------------------
450 double wxvtkImageViewer2::GetColorLevel()
452 return this->WindowLevel->GetLevel();
455 //----------------------------------------------------------------------------
456 void wxvtkImageViewer2::SetColorWindow(double s)
458 this->WindowLevel->SetWindow(s);
461 //----------------------------------------------------------------------------
462 void wxvtkImageViewer2::SetColorLevel(double s)
464 this->WindowLevel->SetLevel(s);
467 //----------------------------------------------------------------------------
468 class wxvtkImageViewer2Callback : public vtkCommand
471 static wxvtkImageViewer2Callback *New() { return new wxvtkImageViewer2Callback; }
473 void Execute(vtkObject *caller,
475 void *vtkNotUsed(callData))
477 if (this->IV->GetInput() == NULL)
484 if (event == vtkCommand::ResetWindowLevelEvent)
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]));
499 if (event == vtkCommand::StartWindowLevelEvent)
501 this->InitialWindow = this->IV->GetColorWindow();
502 this->InitialLevel = this->IV->GetColorLevel();
506 // Adjust the window level here
508 vtkInteractorStyleImage *isi =
509 static_cast<vtkInteractorStyleImage *>(caller);
511 int *size = this->IV->GetRenderWindow()->GetSize();
512 double window = this->InitialWindow;
513 double level = this->InitialLevel;
515 // Compute normalized delta
518 (isi->GetWindowLevelCurrentPosition()[0] -
519 isi->GetWindowLevelStartPosition()[0]) / size[0];
521 (isi->GetWindowLevelStartPosition()[1] -
522 isi->GetWindowLevelCurrentPosition()[1]) / size[1];
524 // Scale by current values
526 if (fabs(window) > 0.01)
532 dx = dx * (window < 0 ? -0.01 : 0.01);
534 if (fabs(level) > 0.01)
540 dy = dy * (level < 0 ? -0.01 : 0.01);
543 // Abs so that direction does not flip
554 // Compute new window level
556 double newWindow = dx + window;
558 newLevel = level - dy;
560 // Stay away from zero and really
562 if (fabs(newWindow) < 0.01)
564 newWindow = 0.01*(newWindow < 0 ? -1 : 1);
566 if (fabs(newLevel) < 0.01)
568 newLevel = 0.01*(newLevel < 0 ? -1 : 1);
571 this->IV->SetColorWindow(newWindow);
572 this->IV->SetColorLevel(newLevel);
576 wxvtkImageViewer2 *IV;
577 double InitialWindow;
581 //----------------------------------------------------------------------------
582 void wxvtkImageViewer2::InstallPipeline()
584 if (this->RenderWindow && this->Renderer)
586 this->RenderWindow->AddRenderer(this->Renderer);
589 if (this->Interactor)
591 if (!this->InteractorStyle)
593 this->InteractorStyle = vtkInteractorStyleImage::New();
594 wxvtkImageViewer2Callback *cbk = wxvtkImageViewer2Callback::New();
596 this->InteractorStyle->AddObserver(
597 vtkCommand::WindowLevelEvent, cbk);
598 this->InteractorStyle->AddObserver(
599 vtkCommand::StartWindowLevelEvent, cbk);
600 this->InteractorStyle->AddObserver(
601 vtkCommand::ResetWindowLevelEvent, cbk);
605 this->Interactor->SetInteractorStyle(this->InteractorStyle);
606 this->Interactor->SetRenderWindow(this->RenderWindow);
609 if (this->Renderer && this->ImageActor)
611 this->Renderer->AddViewProp(this->ImageActor);
614 if (this->ImageActor && this->WindowLevel)
616 this->ImageActor->SetInput(this->WindowLevel->GetOutput());
620 //----------------------------------------------------------------------------
621 void wxvtkImageViewer2::UnInstallPipeline()
623 if (this->ImageActor)
625 this->ImageActor->SetInput(NULL);
628 if (this->Renderer && this->ImageActor)
630 this->Renderer->RemoveViewProp(this->ImageActor);
633 if (this->RenderWindow && this->Renderer)
635 this->RenderWindow->RemoveRenderer(this->Renderer);
638 if (this->Interactor)
640 this->Interactor->SetInteractorStyle(NULL);
641 this->Interactor->SetRenderWindow(NULL);
645 //----------------------------------------------------------------------------
646 void wxvtkImageViewer2::Render()
648 if (this->FirstRender)
650 // Initialize the size if not set yet
652 vtkImageData *input = this->GetInput();
653 if (this->RenderWindow->GetSize()[0] == 0 &&
657 input->UpdateInformation();
658 int *w_ext = input->GetWholeExtent();
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]
667 switch (this->SliceOrientation)
669 case wxvtkImageViewer2::SLICE_ORIENTATION_XY:
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;
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;
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;
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);
693 // std::cout << "wxvtkImageViewer2::Render() : "<<xs<<"-"<<ys<<std::endl;
696 this->Renderer->ResetCamera();
697 this->Renderer->GetActiveCamera()->SetParallelScale(
698 xs < 150 ? 75 : (xs - 1 ) / 2.0);
700 this->FirstRender = 0;
704 if (this->GetInput())
706 this->RenderWindow->Render();
710 //----------------------------------------------------------------------------
711 const char* wxvtkImageViewer2::GetWindowName()
713 return this->RenderWindow->GetWindowName();
716 //----------------------------------------------------------------------------
717 void wxvtkImageViewer2::SetOffScreenRendering(int i)
719 this->RenderWindow->SetOffScreenRendering(i);
722 //----------------------------------------------------------------------------
723 int wxvtkImageViewer2::GetOffScreenRendering()
725 return this->RenderWindow->GetOffScreenRendering();
728 //----------------------------------------------------------------------------
729 void wxvtkImageViewer2::SetInput(vtkImageData *in)
731 // std::cout << "### wxvtkImageViewer2::SetInput"<<std::endl;
732 this->WindowLevel->SetInput(in);
733 this->UpdateDisplayExtent();
737 //----------------------------------------------------------------------------
738 vtkImageData* wxvtkImageViewer2::GetInput()
740 return vtkImageData::SafeDownCast(this->WindowLevel->GetInput());
743 //----------------------------------------------------------------------------
744 void wxvtkImageViewer2::SetInputConnection(vtkAlgorithmOutput* input)
746 this->WindowLevel->SetInputConnection(input);
747 this->UpdateDisplayExtent();
750 //----------------------------------------------------------------------------
751 #ifndef VTK_LEGACY_REMOVE
752 int wxvtkImageViewer2::GetWholeZMin()
754 VTK_LEGACY_REPLACED_BODY(wxvtkImageViewer2::GetWholeZMin, "VTK 5.0",
755 wxvtkImageViewer2::GetSliceMin);
756 return this->GetSliceMin();
758 int wxvtkImageViewer2::GetWholeZMax()
760 VTK_LEGACY_REPLACED_BODY(wxvtkImageViewer2::GetWholeZMax, "VTK 5.0",
761 wxvtkImageViewer2::GetSliceMax);
762 return this->GetSliceMax();
764 int wxvtkImageViewer2::GetZSlice()
766 VTK_LEGACY_REPLACED_BODY(wxvtkImageViewer2::GetZSlice, "VTK 5.0",
767 wxvtkImageViewer2::GetSlice);
768 return this->GetSlice();
770 void wxvtkImageViewer2::SetZSlice(int s)
772 VTK_LEGACY_REPLACED_BODY(wxvtkImageViewer2::SetZSlice, "VTK 5.0",
773 wxvtkImageViewer2::SetSlice);
778 //----------------------------------------------------------------------------
779 void wxvtkImageViewer2::PrintSelf(ostream& os, vtkIndent indent)
781 this->Superclass::PrintSelf(os, indent);
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)
797 this->InteractorStyle->PrintSelf(os,indent.GetNextIndent());