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.2 $");
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;
405 cam->SetClippingRange(
406 range - avg_spacing * 3.0, range + avg_spacing * 3.0);
412 //----------------------------------------------------------------------------
413 void wxvtkImageViewer2::SetPosition(int a,int b)
415 this->RenderWindow->SetPosition(a, b);
418 //----------------------------------------------------------------------------
419 int* wxvtkImageViewer2::GetPosition()
421 return this->RenderWindow->GetPosition();
424 //----------------------------------------------------------------------------
425 void wxvtkImageViewer2::SetDisplayId(void *a)
427 this->RenderWindow->SetDisplayId(a);
430 //----------------------------------------------------------------------------
431 void wxvtkImageViewer2::SetWindowId(void *a)
433 this->RenderWindow->SetWindowId(a);
436 //----------------------------------------------------------------------------
437 void wxvtkImageViewer2::SetParentId(void *a)
439 this->RenderWindow->SetParentId(a);
442 //----------------------------------------------------------------------------
443 double wxvtkImageViewer2::GetColorWindow()
445 return this->WindowLevel->GetWindow();
448 //----------------------------------------------------------------------------
449 double wxvtkImageViewer2::GetColorLevel()
451 return this->WindowLevel->GetLevel();
454 //----------------------------------------------------------------------------
455 void wxvtkImageViewer2::SetColorWindow(double s)
457 this->WindowLevel->SetWindow(s);
460 //----------------------------------------------------------------------------
461 void wxvtkImageViewer2::SetColorLevel(double s)
463 this->WindowLevel->SetLevel(s);
466 //----------------------------------------------------------------------------
467 class wxvtkImageViewer2Callback : public vtkCommand
470 static wxvtkImageViewer2Callback *New() { return new wxvtkImageViewer2Callback; }
472 void Execute(vtkObject *caller,
474 void *vtkNotUsed(callData))
476 if (this->IV->GetInput() == NULL)
483 if (event == vtkCommand::ResetWindowLevelEvent)
485 this->IV->GetInput()->UpdateInformation();
486 this->IV->GetInput()->SetUpdateExtent
487 (this->IV->GetInput()->GetWholeExtent());
488 this->IV->GetInput()->Update();
489 double *range = this->IV->GetInput()->GetScalarRange();
490 this->IV->SetColorWindow(range[1] - range[0]);
491 this->IV->SetColorLevel(0.5 * (range[1] + range[0]));
498 if (event == vtkCommand::StartWindowLevelEvent)
500 this->InitialWindow = this->IV->GetColorWindow();
501 this->InitialLevel = this->IV->GetColorLevel();
505 // Adjust the window level here
507 vtkInteractorStyleImage *isi =
508 static_cast<vtkInteractorStyleImage *>(caller);
510 int *size = this->IV->GetRenderWindow()->GetSize();
511 double window = this->InitialWindow;
512 double level = this->InitialLevel;
514 // Compute normalized delta
517 (isi->GetWindowLevelCurrentPosition()[0] -
518 isi->GetWindowLevelStartPosition()[0]) / size[0];
520 (isi->GetWindowLevelStartPosition()[1] -
521 isi->GetWindowLevelCurrentPosition()[1]) / size[1];
523 // Scale by current values
525 if (fabs(window) > 0.01)
531 dx = dx * (window < 0 ? -0.01 : 0.01);
533 if (fabs(level) > 0.01)
539 dy = dy * (level < 0 ? -0.01 : 0.01);
542 // Abs so that direction does not flip
553 // Compute new window level
555 double newWindow = dx + window;
557 newLevel = level - dy;
559 // Stay away from zero and really
561 if (fabs(newWindow) < 0.01)
563 newWindow = 0.01*(newWindow < 0 ? -1 : 1);
565 if (fabs(newLevel) < 0.01)
567 newLevel = 0.01*(newLevel < 0 ? -1 : 1);
570 this->IV->SetColorWindow(newWindow);
571 this->IV->SetColorLevel(newLevel);
575 wxvtkImageViewer2 *IV;
576 double InitialWindow;
580 //----------------------------------------------------------------------------
581 void wxvtkImageViewer2::InstallPipeline()
583 if (this->RenderWindow && this->Renderer)
585 this->RenderWindow->AddRenderer(this->Renderer);
588 if (this->Interactor)
590 if (!this->InteractorStyle)
592 this->InteractorStyle = vtkInteractorStyleImage::New();
593 wxvtkImageViewer2Callback *cbk = wxvtkImageViewer2Callback::New();
595 this->InteractorStyle->AddObserver(
596 vtkCommand::WindowLevelEvent, cbk);
597 this->InteractorStyle->AddObserver(
598 vtkCommand::StartWindowLevelEvent, cbk);
599 this->InteractorStyle->AddObserver(
600 vtkCommand::ResetWindowLevelEvent, cbk);
604 this->Interactor->SetInteractorStyle(this->InteractorStyle);
605 this->Interactor->SetRenderWindow(this->RenderWindow);
608 if (this->Renderer && this->ImageActor)
610 this->Renderer->AddViewProp(this->ImageActor);
613 if (this->ImageActor && this->WindowLevel)
615 this->ImageActor->SetInput(this->WindowLevel->GetOutput());
619 //----------------------------------------------------------------------------
620 void wxvtkImageViewer2::UnInstallPipeline()
622 if (this->ImageActor)
624 this->ImageActor->SetInput(NULL);
627 if (this->Renderer && this->ImageActor)
629 this->Renderer->RemoveViewProp(this->ImageActor);
632 if (this->RenderWindow && this->Renderer)
634 this->RenderWindow->RemoveRenderer(this->Renderer);
637 if (this->Interactor)
639 this->Interactor->SetInteractorStyle(NULL);
640 this->Interactor->SetRenderWindow(NULL);
644 //----------------------------------------------------------------------------
645 void wxvtkImageViewer2::Render()
647 if (this->FirstRender)
649 // Initialize the size if not set yet
651 vtkImageData *input = this->GetInput();
652 if (this->RenderWindow->GetSize()[0] == 0 &&
656 input->UpdateInformation();
657 int *w_ext = input->GetWholeExtent();
660 // std::cout << "wxvtkImageViewer2::Render ext = "
661 // <<w_ext[0]<<" - "<<w_ext[1]<<" ; "
662 // <<w_ext[2]<<" - "<<w_ext[3]<<" ; "
663 // <<w_ext[4]<<" - "<<w_ext[5]
666 switch (this->SliceOrientation)
668 case wxvtkImageViewer2::SLICE_ORIENTATION_XY:
670 xs = w_ext[1] - w_ext[0] + 1;
671 ys = w_ext[3] - w_ext[2] + 1;
672 // std::cout << "SLICE_ORIENTATION_XY" << std::endl;
675 case wxvtkImageViewer2::SLICE_ORIENTATION_XZ:
676 xs = w_ext[1] - w_ext[0] + 1;
677 ys = w_ext[5] - w_ext[4] + 1;
678 // std::cout << "SLICE_ORIENTATION_XZ" << std::endl;
681 case wxvtkImageViewer2::SLICE_ORIENTATION_YZ:
682 xs = w_ext[3] - w_ext[2] + 1;
683 ys = w_ext[5] - w_ext[4] + 1;
684 // std::cout << "SLICE_ORIENTATION_YZ" << std::endl;
688 // if it would be smaller than 150 by 100 then limit to 150 by 100
689 this->RenderWindow->SetSize(
690 xs < 150 ? 150 : xs, ys < 100 ? 100 : ys);
692 // std::cout << "wxvtkImageViewer2::Render() : "<<xs<<"-"<<ys<<std::endl;
695 this->Renderer->ResetCamera();
696 this->Renderer->GetActiveCamera()->SetParallelScale(
697 xs < 150 ? 75 : (xs - 1 ) / 2.0);
699 this->FirstRender = 0;
703 if (this->GetInput())
705 this->RenderWindow->Render();
709 //----------------------------------------------------------------------------
710 const char* wxvtkImageViewer2::GetWindowName()
712 return this->RenderWindow->GetWindowName();
715 //----------------------------------------------------------------------------
716 void wxvtkImageViewer2::SetOffScreenRendering(int i)
718 this->RenderWindow->SetOffScreenRendering(i);
721 //----------------------------------------------------------------------------
722 int wxvtkImageViewer2::GetOffScreenRendering()
724 return this->RenderWindow->GetOffScreenRendering();
727 //----------------------------------------------------------------------------
728 void wxvtkImageViewer2::SetInput(vtkImageData *in)
730 // std::cout << "### wxvtkImageViewer2::SetInput"<<std::endl;
731 this->WindowLevel->SetInput(in);
732 this->UpdateDisplayExtent();
736 //----------------------------------------------------------------------------
737 vtkImageData* wxvtkImageViewer2::GetInput()
739 return vtkImageData::SafeDownCast(this->WindowLevel->GetInput());
742 //----------------------------------------------------------------------------
743 void wxvtkImageViewer2::SetInputConnection(vtkAlgorithmOutput* input)
745 this->WindowLevel->SetInputConnection(input);
746 this->UpdateDisplayExtent();
749 //----------------------------------------------------------------------------
750 #ifndef VTK_LEGACY_REMOVE
751 int wxvtkImageViewer2::GetWholeZMin()
753 VTK_LEGACY_REPLACED_BODY(wxvtkImageViewer2::GetWholeZMin, "VTK 5.0",
754 wxvtkImageViewer2::GetSliceMin);
755 return this->GetSliceMin();
757 int wxvtkImageViewer2::GetWholeZMax()
759 VTK_LEGACY_REPLACED_BODY(wxvtkImageViewer2::GetWholeZMax, "VTK 5.0",
760 wxvtkImageViewer2::GetSliceMax);
761 return this->GetSliceMax();
763 int wxvtkImageViewer2::GetZSlice()
765 VTK_LEGACY_REPLACED_BODY(wxvtkImageViewer2::GetZSlice, "VTK 5.0",
766 wxvtkImageViewer2::GetSlice);
767 return this->GetSlice();
769 void wxvtkImageViewer2::SetZSlice(int s)
771 VTK_LEGACY_REPLACED_BODY(wxvtkImageViewer2::SetZSlice, "VTK 5.0",
772 wxvtkImageViewer2::SetSlice);
777 //----------------------------------------------------------------------------
778 void wxvtkImageViewer2::PrintSelf(ostream& os, vtkIndent indent)
780 this->Superclass::PrintSelf(os, indent);
782 os << indent << "RenderWindow:\n";
783 this->RenderWindow->PrintSelf(os,indent.GetNextIndent());
784 os << indent << "Renderer:\n";
785 this->Renderer->PrintSelf(os,indent.GetNextIndent());
786 os << indent << "ImageActor:\n";
787 this->ImageActor->PrintSelf(os,indent.GetNextIndent());
788 os << indent << "WindowLevel:\n" << endl;
789 this->WindowLevel->PrintSelf(os,indent.GetNextIndent());
790 os << indent << "Slice: " << this->Slice << endl;
791 os << indent << "SliceOrientation: " << this->SliceOrientation << endl;
792 os << indent << "InteractorStyle: " << endl;
793 if (this->InteractorStyle)
796 this->InteractorStyle->PrintSelf(os,indent.GetNextIndent());