1 /*=========================================================================
2 Program: vv http://www.creatis.insa-lyon.fr/rio/vv
5 - University of LYON http://www.universite-lyon.fr/
6 - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
7 - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
9 This software is distributed WITHOUT ANY WARRANTY; without even
10 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11 PURPOSE. See the copyright notices for more information.
13 It is distributed under dual licence
15 - BSD See included LICENSE.txt file
16 - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17 ======================================================================-====*/
21 #include "vvSlicerManagerCommand.h"
22 #include "vvGlyphSource.h"
23 #include "vvGlyph2D.h"
24 #include "vvImageMapToWLColors.h"
26 #include <vtkTextProperty.h>
27 #include <vtkTextActor.h>
28 #include <vtkTextSource.h>
29 #include <vtkActor2D.h>
30 #include <vtkCursor2D.h>
31 #include <vtkPolyDataMapper2D.h>
32 #include <vtkProperty2D.h>
33 #include <vtkCornerAnnotation.h>
34 #include <vtkImageMapToWindowLevelColors.h>
35 #include <vtkImageData.h>
36 #include <vtkImageActor.h>
37 #include <vvBlendImageActor.h>
38 #include <vtkToolkits.h>
39 #include <vtkObjectFactory.h>
40 #include <vtkPointData.h>
41 #include <vtkDataArray.h>
42 #include <vtkFloatArray.h>
43 #include <vtkClipPolyData.h>
44 #include <vtkGlyph3D.h>
46 #include <vtkCursor3D.h>
47 #include <vtkProperty.h>
49 #include <vtkLightCollection.h>
50 #include <vtkScalarBarActor.h>
51 #include <vtkLookupTable.h>
53 #include <vtkRenderer.h>
54 #include <vtkRendererCollection.h>
55 #include <vtkRenderWindow.h>
56 #include <vtkRenderWindowInteractor.h>
57 #include <vtkCamera.h>
58 #include <vtkCallbackCommand.h>
59 #include <vtkCommand.h>
60 #include <vtkPolyDataMapper.h>
63 #include <vtkExtractVOI.h>
64 #include <vtkSphereSource.h>
65 #include <vtkCutter.h>
66 #include <vtkAssignAttribute.h>
67 #include <vtkImageAccumulate.h>
68 #include <vtkImageReslice.h>
70 vtkCxxRevisionMacro(vvSlicer, "DummyRevision");
71 vtkStandardNewMacro(vvSlicer);
73 //------------------------------------------------------------------------------
76 this->UnInstallPipeline();
79 mUseReducedExtent = false;
81 mCurrent[0] = -VTK_DOUBLE_MAX;
82 mCurrent[1] = -VTK_DOUBLE_MAX;
83 mCurrent[2] = -VTK_DOUBLE_MAX;
85 mCursor[0] = -VTK_DOUBLE_MAX;
86 mCursor[1] = -VTK_DOUBLE_MAX;
87 mCursor[2] = -VTK_DOUBLE_MAX;
88 mCursor[3] = -VTK_DOUBLE_MAX;
98 std::string text = "F1 = sagital; F2 = coronal; F3 = axial\n";
99 text += "F5 = horizontal flip; F6 = vertical flip\n\n";
100 text += "0,1,2,3,4,5 : preset windowing\n";
101 text += "6,7,8,9 : preset colormap\n";
102 text += "z : local windowing\n";
103 text += "r : reset view\n";
104 text += "l : reload image\n";
105 text += "f : fly to mouse position\n";
106 text += "g : go to cross hair position\n\n";
107 text += "Up,down : change slice\n";
108 text += "Left,right : change tenporal slice\n\n";
109 text += "Scrollbar (or w/x) : zoom in/out\n";
110 text += "left button : synchronize all views\n";
111 text += "middle button : grab image\n";
112 text += "right button : change windowing\n";
114 crossCursor = vtkSmartPointer<vtkCursor2D>::New();
115 crossCursor->AllOff();
116 crossCursor->AxesOn();
117 crossCursor->SetTranslationMode(1);
118 crossCursor->SetRadius(2);
120 pdm = vtkSmartPointer<vtkPolyDataMapper2D>::New();
121 pdm->SetInput(crossCursor->GetOutput());
123 pdmA = vtkSmartPointer<vtkActor2D>::New();
124 pdmA->SetMapper(pdm);
125 pdmA->GetProperty()->SetColor(255,10,212);
126 pdmA->SetVisibility(0);
127 pdmA->SetPickable(0);
129 ca = vtkSmartPointer<vtkCornerAnnotation>::New();
130 ca->GetTextProperty()->SetColor(255,10,212);
131 ca->SetVisibility(1);
139 legend = vtkSmartPointer<vtkScalarBarActor>::New();
140 //legend->SetTitle("test!");
141 legend->SetPosition(0.82,0.18);
142 legend->SetWidth(0.1);
143 legend->SetVisibility(0);
144 legend->SetLabelFormat("%.1f");
145 this->GetRenderer()->AddActor(legend);
147 this->WindowLevel->Delete();
148 this->WindowLevel = vvImageMapToWLColors::New();
150 this->InstallPipeline();
152 //------------------------------------------------------------------------------
155 //------------------------------------------------------------------------------
156 vtkImageMapToWindowLevelColors* vvSlicer::GetOverlayMapper()
158 return mOverlayMapper.GetPointer();
160 //------------------------------------------------------------------------------
163 //------------------------------------------------------------------------------
164 vvBlendImageActor* vvSlicer::GetOverlayActor()
166 return mOverlayActor.GetPointer();
168 //------------------------------------------------------------------------------
171 //------------------------------------------------------------------------------
172 vtkImageMapToWindowLevelColors* vvSlicer::GetFusionMapper()
174 return mFusionMapper.GetPointer();
176 //------------------------------------------------------------------------------
179 //------------------------------------------------------------------------------
180 vtkImageActor* vvSlicer::GetFusionActor()
182 return mFusionActor.GetPointer();
184 //------------------------------------------------------------------------------
187 //------------------------------------------------------------------------------
188 vtkActor* vvSlicer::GetVFActor()
190 return mVFActor.GetPointer();
192 //------------------------------------------------------------------------------
195 //------------------------------------------------------------------------------
196 vtkCornerAnnotation* vvSlicer::GetAnnotation()
198 return ca.GetPointer();
200 //------------------------------------------------------------------------------
203 //------------------------------------------------------------------------------
204 void vvSlicer::EnableReducedExtent(bool b)
206 mUseReducedExtent = b;
208 //------------------------------------------------------------------------------
211 //------------------------------------------------------------------------------
212 void vvSlicer::SetReducedExtent(int * ext)
214 mReducedExtent = ext;
216 //------------------------------------------------------------------------------
219 //------------------------------------------------------------------------------
220 void vvSlicer::AddContour(vvMesh::Pointer contour,bool propagate)
223 mSurfaceCutActors.push_back(new vvMeshActor());
225 mSurfaceCutActors.back()->Init(contour,mCurrentTSlice,mVF);
227 mSurfaceCutActors.back()->Init(contour,mCurrentTSlice);
228 mSurfaceCutActors.back()->SetSlicingOrientation(SliceOrientation);
229 this->GetRenderer()->AddActor(mSurfaceCutActors.back()->GetActor());
233 //------------------------------------------------------------------------------
236 //------------------------------------------------------------------------------
237 void vvSlicer::ToggleContourSuperposition()
239 for (std::vector<vvMeshActor*>::iterator i=mSurfaceCutActors.begin();
240 i!=mSurfaceCutActors.end(); i++)
241 (*i)->ToggleSuperposition();
243 //------------------------------------------------------------------------------
246 //------------------------------------------------------------------------------
247 void vvSlicer::SetCursorColor(int r,int g, int b)
249 pdmA->GetProperty()->SetColor(r,g,b);
251 //------------------------------------------------------------------------------
254 //------------------------------------------------------------------------------
255 void vvSlicer::SetCursorVisibility(bool s)
257 pdmA->SetVisibility(s);
259 //------------------------------------------------------------------------------
262 //------------------------------------------------------------------------------
263 bool vvSlicer::GetCursorVisibility()
265 return pdmA->GetVisibility();
267 //------------------------------------------------------------------------------
270 //------------------------------------------------------------------------------
271 void vvSlicer::SetCornerAnnotationVisibility(bool s)
273 ca->SetVisibility(s);
275 //------------------------------------------------------------------------------
278 //------------------------------------------------------------------------------
279 bool vvSlicer::GetCornerAnnotationVisibility()
281 return ca->GetVisibility();
283 //------------------------------------------------------------------------------
286 //------------------------------------------------------------------------------
287 vvSlicer::~vvSlicer()
289 for (std::vector<vvMeshActor*>::iterator i=mSurfaceCutActors.begin();
290 i!=mSurfaceCutActors.end(); i++)
293 //------------------------------------------------------------------------------
296 //------------------------------------------------------------------------------
297 void vvSlicer::SetCurrentPosition(double x, double y, double z, int t)
304 //------------------------------------------------------------------------------
307 //------------------------------------------------------------------------------
308 void vvSlicer::SetImage(vvImage::Pointer image)
310 if (image->GetVTKImages().size()) {
312 this->Superclass::SetInput(image->GetTransformedVTKImages()[0]);
315 this->GetInput()->GetWholeExtent(extent);
317 // Prevent crash when reload -> change slice if outside extent
318 if (Slice < extent[SliceOrientation*2] || Slice>=extent[SliceOrientation*2+1]) {
319 Slice = (extent[SliceOrientation*2+1]-extent[SliceOrientation*2])/2.0;
322 // Make sure that the required part image has been computed
323 extent[SliceOrientation*2] = Slice;
324 extent[SliceOrientation*2+1] = Slice;
325 image->GetTransformedVTKImages()[0]->SetUpdateExtent(extent);
326 image->GetTransformedVTKImages()[0]->Update();
328 this->UpdateDisplayExtent();
331 ca->SetText(0,mFileName.c_str());
334 //------------------------------------------------------------------------------
337 //------------------------------------------------------------------------------
338 void vvSlicer::SetOverlay(vvImage::Pointer overlay)
340 if (overlay->GetVTKImages().size()) {
344 mOverlayMapper = vtkSmartPointer<vtkImageMapToWindowLevelColors>::New();
345 mOverlayMapper->SetInput(overlay->GetTransformedVTKImages()[0]);
347 if (!mOverlayActor) {
348 mOverlayActor = vtkSmartPointer<vvBlendImageActor>::New();
349 mOverlayActor->SetInput(mOverlayMapper->GetOutput());
350 mOverlayActor->SetPickable(0);
351 mOverlayActor->SetVisibility(false);
352 mOverlayActor->SetOpacity(0.5);
353 this->UpdateDisplayExtent();
356 //stupid but necessary : the Overlay need to be rendered before fusion
358 this->GetRenderer()->RemoveActor(mFusionActor);
359 this->GetRenderer()->AddActor(mOverlayActor);
360 this->GetRenderer()->AddActor(mFusionActor);
362 this->GetRenderer()->AddActor(mOverlayActor);
365 SetTSlice(mCurrentTSlice);
368 //------------------------------------------------------------------------------
371 //------------------------------------------------------------------------------
372 void vvSlicer::SetFusion(vvImage::Pointer fusion)
374 if (fusion->GetVTKImages().size()) {
378 mFusionMapper = vtkSmartPointer<vtkImageMapToWindowLevelColors>::New();
379 mFusionMapper->SetInput(fusion->GetTransformedVTKImages()[0]);
382 mFusionActor = vtkSmartPointer<vtkImageActor>::New();
383 mFusionActor->SetInput(mFusionMapper->GetOutput());
384 mFusionActor->SetPickable(0);
385 mFusionActor->SetVisibility(false);
386 mFusionActor->SetOpacity(0.7);
387 this->UpdateDisplayExtent();
388 this->GetRenderer()->AddActor(mFusionActor);
392 SetTSlice(mCurrentTSlice);
395 //------------------------------------------------------------------------------
398 //------------------------------------------------------------------------------
399 void vvSlicer::SetActorVisibility(const std::string& actor_type, int overlay_index ,bool vis)
401 if (actor_type == "vector") {
402 this->mVFActor->SetVisibility(vis);
404 if (actor_type == "overlay") {
405 this->mOverlayActor->SetVisibility(vis);
407 if (actor_type == "fusion") {
408 this->mFusionActor->SetVisibility(vis);
410 if (actor_type == "contour")
411 this->mSurfaceCutActors[overlay_index]->GetActor()->SetVisibility(vis);
412 UpdateDisplayExtent();
414 //------------------------------------------------------------------------------
417 //------------------------------------------------------------------------------
418 void vvSlicer::SetVF(vvImage::Pointer vf)
420 if (vf->GetVTKImages().size()) {
424 mAAFilter= vtkSmartPointer<vtkAssignAttribute>::New();
425 mVOIFilter = vtkSmartPointer<vtkExtractVOI>::New();
426 mVOIFilter->SetSampleRate(mSubSampling,mSubSampling,mSubSampling);
428 mVOIFilter->SetInput(vf->GetTransformedVTKImages()[0]);
429 mAAFilter->SetInput(mVOIFilter->GetOutput());
430 ///This tells VTK to use the scalar (pixel) data of the image to draw the little arrows
431 mAAFilter->Assign(vtkDataSetAttributes::SCALARS, vtkDataSetAttributes::VECTORS, vtkAssignAttribute::POINT_DATA);
434 mArrow = vtkSmartPointer<vvGlyphSource>::New();
435 mArrow->SetGlyphTypeToSpecificArrow();
436 mArrow->SetScale(mScale);
439 // Glyph the gradient vector (with arrows)
441 mGlyphFilter = vtkSmartPointer<vvGlyph2D>::New();
442 mGlyphFilter->SetInput(mAAFilter->GetOutput());
443 mGlyphFilter->SetSource(mArrow->GetOutput());
444 mGlyphFilter->ScalingOn();
445 mGlyphFilter->SetScaleModeToScaleByVector();
446 mGlyphFilter->OrientOn();
447 mGlyphFilter->SetVectorModeToUseVector();
448 mGlyphFilter->SetColorModeToColorByVector();
451 mVFColorLUT = vtkSmartPointer<vtkLookupTable>::New();
453 double mVFColorHSV[3];
454 vtkMath::RGBToHSV(mVFColor, mVFColorHSV);
455 mVFColorLUT->SetHueRange(mVFColorHSV[0], mVFColorHSV[0]);
456 mVFColorLUT->SetSaturationRange(mVFColorHSV[1],mVFColorHSV[1]);
457 mVFColorLUT->SetValueRange(mVFColorHSV[2], mVFColorHSV[2]);
460 mVFMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
461 mVFMapper->SetInput(mGlyphFilter->GetOutput());
462 mVFMapper->ImmediateModeRenderingOn();
463 mVFMapper->SetLookupTable(mVFColorLUT);
466 mVFActor = vtkSmartPointer<vtkActor>::New();
467 mVFActor->SetMapper(mVFMapper);
468 mVFActor->SetPickable(0);
469 mVFActor->GetProperty()->SetLineWidth(mVFWidth);
470 this->UpdateDisplayExtent();
471 this->GetRenderer()->AddActor(mVFActor);
474 SetTSlice(mCurrentTSlice);
477 //------------------------------------------------------------------------------
480 //------------------------------------------------------------------------------
481 void vvSlicer::SetLandmarks(vvLandmarks* landmarks)
483 mLandmarks = landmarks;
487 mCross = vtkSmartPointer<vtkCursor3D>::New();
488 mCross->SetFocalPoint(0.0,0.0,0.0);
489 mCross->SetModelBounds(-10,10,-10,10,-10,10);
494 mLandGlyph = vtkSmartPointer<vtkGlyph3D>::New();
495 mLandGlyph->SetSource(mCross->GetOutput());
496 mLandGlyph->SetInput(landmarks->GetOutput());
497 //mLandGlyph->SetIndexModeToScalar();
498 mLandGlyph->SetRange(0,1);
499 mLandGlyph->ScalingOff();
501 mLandGlyph->SetColorModeToColorByScalar();
504 mClipBox = vtkSmartPointer<vtkBox>::New();
506 mLandClipper = vtkSmartPointer<vtkClipPolyData>::New();
507 mLandClipper->InsideOutOn();
508 mLandClipper->SetInput(mLandGlyph->GetOutput());
509 mLandClipper->SetClipFunction(mClipBox);
512 mLandMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
513 mLandMapper->SetInputConnection(mLandClipper->GetOutputPort());
514 //mLandMapper->ScalarVisibilityOff();
517 mLandActor = vtkSmartPointer<vtkActor>::New();
518 mLandActor->SetMapper(mLandMapper);
519 mLandActor->GetProperty()->SetColor(255,10,212);
520 mLandActor->SetPickable(0);
521 mLandActor->SetVisibility(true);
522 this->UpdateDisplayExtent();
523 this->GetRenderer()->AddActor(mLandActor);
526 //------------------------------------------------------------------------------
528 //------------------------------------------------------------------------------
529 //FIXME: this function leaks memory, we should fix it someday :)
530 void vvSlicer::RemoveActor(const std::string& actor_type, int overlay_index)
532 if (actor_type == "vector") {
533 Renderer->RemoveActor(mVFActor);
542 if (actor_type == "overlay") {
543 Renderer->RemoveActor(mOverlayActor);
545 mOverlayActor = NULL;
546 mOverlayMapper = NULL;
548 if (actor_type == "fusion") {
549 Renderer->RemoveActor(mFusionActor);
552 mFusionMapper = NULL;
554 if (actor_type == "contour") {
555 Renderer->RemoveActor(this->mSurfaceCutActors[overlay_index]->GetActor());
556 mSurfaceCutActors.erase(mSurfaceCutActors.begin()+overlay_index);
559 //------------------------------------------------------------------------------
562 //------------------------------------------------------------------------------
563 void vvSlicer::SetVFSubSampling(int sub)
566 mVOIFilter->SetSampleRate(mSubSampling,mSubSampling,mSubSampling);
569 UpdateDisplayExtent();
572 //------------------------------------------------------------------------------
575 //------------------------------------------------------------------------------
576 void vvSlicer::SetVFScale(int scale)
580 mArrow->SetScale(mScale);
581 UpdateDisplayExtent();
584 //------------------------------------------------------------------------------
586 //------------------------------------------------------------------------------
587 void vvSlicer::SetVFWidth(int width)
591 mVFActor->GetProperty()->SetLineWidth(mVFWidth);
592 UpdateDisplayExtent();
595 //------------------------------------------------------------------------------
598 //------------------------------------------------------------------------------
599 void vvSlicer::SetVFLog(int log)
603 mGlyphFilter->SetUseLog(mVFLog);
604 mGlyphFilter->Modified();
606 UpdateDisplayExtent();
609 //------------------------------------------------------------------------------
612 //------------------------------------------------------------------------------
613 void vvSlicer::SetTSlice(int t)
617 else if ((unsigned int)t >= mImage->GetVTKImages().size())
618 t = mImage->GetVTKImages().size() -1;
620 if (mCurrentTSlice == t) return;
623 this->SetInput(mImage->GetTransformedVTKImages()[t]);
624 if (mVF && mVFActor->GetVisibility()) {
625 if (mVF->GetVTKImages().size() > (unsigned int)mCurrentTSlice)
626 mVOIFilter->SetInput(mVF->GetTransformedVTKImages()[mCurrentTSlice]);
628 if (mOverlay && mOverlayActor->GetVisibility()) {
629 if (mOverlay->GetTransformedVTKImages().size() > (unsigned int)mCurrentTSlice)
630 mOverlayMapper->SetInput(mOverlay->GetTransformedVTKImages()[mCurrentTSlice]);
632 if (mFusion && mFusionActor->GetVisibility()) {
633 if (mFusion->GetVTKImages().size() > (unsigned int)mCurrentTSlice)
634 mFusionMapper->SetInput(mFusion->GetTransformedVTKImages()[mCurrentTSlice]);
636 if (mSurfaceCutActors.size() > 0)
637 for (std::vector<vvMeshActor*>::iterator i=mSurfaceCutActors.begin();
638 i!=mSurfaceCutActors.end(); i++)
639 (*i)->SetTimeSlice(mCurrentTSlice);
640 UpdateDisplayExtent();
642 //------------------------------------------------------------------------------
645 //------------------------------------------------------------------------------
646 int vvSlicer::GetTSlice()
648 return mCurrentTSlice;
650 //------------------------------------------------------------------------------
653 //------------------------------------------------------------------------------
654 void vvSlicer::SetSliceOrientation(int orientation)
656 //if 2D image, force to watch in Axial View
658 this->GetInput()->GetWholeExtent(extent);
659 if (extent[5]-extent[4] <= 2)
662 if (orientation < vtkImageViewer2::SLICE_ORIENTATION_YZ ||
663 orientation > vtkImageViewer2::SLICE_ORIENTATION_XY) {
664 vtkErrorMacro("Error - invalid slice orientation " << orientation);
668 this->SliceOrientation = orientation;
671 int *range = this->GetSliceRange();
673 this->Slice = static_cast<int>((range[0] + range[1]) * 0.5);
675 // Go to current cursor position
676 // double* cursorPos = GetCursorPosition();
677 // DDV(cursorPos, 3);
678 // SetCurrentPosition(cursorPos[0],cursorPos[1],cursorPos[2],cursorPos[3]);
680 this->UpdateOrientation();
681 this->UpdateDisplayExtent();
683 if (this->Renderer && this->GetInput()) {
684 double scale = this->Renderer->GetActiveCamera()->GetParallelScale();
685 this->Renderer->ResetCamera();
686 this->Renderer->GetActiveCamera()->SetParallelScale(scale);
691 //----------------------------------------------------------------------------
694 //----------------------------------------------------------------------------
695 int * vvSlicer::GetExtent()
698 if (mUseReducedExtent) {
699 w_ext = mReducedExtent;
700 } else w_ext = GetInput()->GetWholeExtent();
703 //----------------------------------------------------------------------------
706 //----------------------------------------------------------------------------
707 int vvSlicer::GetOrientation()
709 return this->SliceOrientation;
711 //----------------------------------------------------------------------------
713 //----------------------------------------------------------------------------
714 void vvSlicer::UpdateDisplayExtent()
716 vtkImageData *input = this->GetInput();
717 if (!input || !this->ImageActor) {
720 input->UpdateInformation();
722 // Local copy of extent
724 for(unsigned int i=0; i<6; i++){
725 if (mUseReducedExtent)
726 w_ext[i] = mReducedExtent[i];
728 w_ext[i] = input->GetWholeExtent()[i];
732 w_ext[ this->SliceOrientation*2 ] = this->Slice;
733 w_ext[ this->SliceOrientation*2+1 ] = this->Slice;
736 this->ImageActor->SetDisplayExtent(w_ext);
739 double position[3] = {0.,0.,0.};
740 double positionInc = (Renderer->GetActiveCamera()->GetPosition()[this->SliceOrientation] > this->Slice)?10:-10;
741 position[this->SliceOrientation] += positionInc;
743 // Overlay image actor
744 if (mOverlay && mOverlayActor->GetVisibility()) {
746 mOverlay->GetTransformedVTKImages()[0]->UpdateInformation();
747 this->ConvertImageToImageDisplayExtent(input, w_ext, mOverlay->GetTransformedVTKImages()[0], overExtent);
748 ClipDisplayedExtent(overExtent, mOverlayMapper->GetInput()->GetWholeExtent());
749 mOverlayActor->SetDisplayExtent( overExtent );
750 mOverlayActor->SetPosition(position);
752 position[this->SliceOrientation] += positionInc;
754 // Fusion image actor
755 if (mFusion && mFusionActor->GetVisibility()) {
757 mFusion->GetTransformedVTKImages()[0]->UpdateInformation();
758 this->ConvertImageToImageDisplayExtent(input, w_ext, mFusion->GetTransformedVTKImages()[0], fusExtent);
759 ClipDisplayedExtent(fusExtent, mFusionMapper->GetInput()->GetWholeExtent());
760 mFusionActor->SetDisplayExtent(fusExtent);
761 mFusionActor->SetPosition(position);
763 position[this->SliceOrientation] += positionInc;
765 // Vector field actor
766 if (mVF && mVFActor->GetVisibility()) {
768 mVF->GetTransformedVTKImages()[0]->UpdateInformation();
769 this->ConvertImageToImageDisplayExtent(input, w_ext, mVF->GetTransformedVTKImages()[0], vfExtent);
770 ClipDisplayedExtent(vfExtent, mVOIFilter->GetInput()->GetWholeExtent());
771 mVOIFilter->SetVOI(vfExtent);
772 int orientation[3] = {1,1,1};
773 orientation[this->SliceOrientation] = 0;
774 mGlyphFilter->SetOrientation(orientation[0], orientation[1], orientation[2]);
776 mVFActor->SetPosition(position);
778 position[this->SliceOrientation] += positionInc;
784 for(unsigned int i=0; i<6; i++)
785 bounds[i] = ImageActor->GetBounds()[i];
786 bounds[ this->SliceOrientation*2 ] = ImageActor->GetBounds()[ this->SliceOrientation*2 ]-fabs(0.5/this->GetInput()->GetSpacing()[this->SliceOrientation]);
787 bounds[ this->SliceOrientation*2+1 ] = ImageActor->GetBounds()[ this->SliceOrientation*2+1 ]+fabs(0.5/this->GetInput()->GetSpacing()[this->SliceOrientation]);
788 mClipBox->SetBounds(bounds);
791 mLandActor->SetPosition(position);
794 // Figure out the correct clipping range
795 if (this->Renderer) {
796 if (this->InteractorStyle &&
797 this->InteractorStyle->GetAutoAdjustCameraClippingRange()) {
798 this->Renderer->ResetCameraClippingRange();
800 vtkCamera *cam = this->Renderer->GetActiveCamera();
803 this->ImageActor->GetBounds(bounds);
804 double spos = (double)bounds[this->SliceOrientation * 2];
805 double cpos = (double)cam->GetPosition()[this->SliceOrientation];
806 double range = fabs(spos - cpos);
807 double *spacing = input->GetSpacing();
809 ((double)spacing[0] + (double)spacing[1] + (double)spacing[2]) / 3.0;
810 cam->SetClippingRange(range - avg_spacing * 3.0, range + avg_spacing * 3.0);
815 //----------------------------------------------------------------------------
817 //----------------------------------------------------------------------------
818 void vvSlicer::ConvertImageToImageDisplayExtent(vtkImageData *sourceImage, const int sourceExtent[6],
819 vtkImageData *targetImage, int targetExtent[6])
822 for(unsigned int i=0; i<6; i++) {
823 // From source voxel coordinates to world coordinates
824 dExtents[i] = sourceImage->GetOrigin()[i/2] + sourceImage->GetSpacing()[i/2] * sourceExtent[i];
826 // From world coordinates to floating point target voxel coordinates
827 dExtents[i] = (dExtents[i]- targetImage->GetOrigin()[i/2]) / targetImage->GetSpacing()[i/2];
830 targetExtent[i] = itk::Math::Round(dExtents[i]);
833 //----------------------------------------------------------------------------
835 //----------------------------------------------------------------------------
836 void vvSlicer::ClipDisplayedExtent(int extent[6], int refExtent[6])
841 //2D overlay on 3D image specific case
842 if (refExtent[4] == refExtent[5]) {
844 extent[4] = refExtent[4];
845 extent[5] = refExtent[5];
848 for (int i = 0; i < maxBound; i = i+2) {
849 //if we are totally outside the image
850 if ( extent[i] > refExtent[i+1] || extent[i+1] < refExtent[i] ) {
854 //crop to the limit of the image
855 extent[i] = (extent[i] > refExtent[i]) ? extent[i] : refExtent[i];
856 extent[i] = (extent[i] < refExtent[i+1]) ? extent[i] : refExtent[i+1];
857 extent[i+1] = (extent[i+1] > refExtent[i]) ? extent[i+1] : refExtent[i];
858 extent[i+1] = (extent[i+1] < refExtent[i+1]) ? extent[i+1] : refExtent[i+1];
861 for (int i = 0; i < maxBound; i = i+2) {
862 extent[i] = refExtent[i];
863 extent[i+1] = refExtent[i];
866 //----------------------------------------------------------------------------
869 //----------------------------------------------------------------------------
870 void vvSlicer::UpdateOrientation()
872 // Set the camera position
873 vtkCamera *cam = this->Renderer ? this->Renderer->GetActiveCamera() : NULL;
875 switch (this->SliceOrientation) {
876 case vtkImageViewer2::SLICE_ORIENTATION_XY:
877 cam->SetFocalPoint(0,0,0);
878 cam->SetPosition(0,0,-1); // -1 if medical ?
879 cam->SetViewUp(0,-1,0);
882 case vtkImageViewer2::SLICE_ORIENTATION_XZ:
883 cam->SetFocalPoint(0,0,0);
884 cam->SetPosition(0,-1,0); // 1 if medical ?
885 cam->SetViewUp(0,0,1);
888 case vtkImageViewer2::SLICE_ORIENTATION_YZ:
889 cam->SetFocalPoint(0,0,0);
890 cam->SetPosition(-1,0,0); // -1 if medical ?
891 cam->SetViewUp(0,0,1);
896 //----------------------------------------------------------------------------
899 //----------------------------------------------------------------------------
900 void vvSlicer::SetOpacity(double s)
902 this->GetImageActor()->SetOpacity(s);
904 //----------------------------------------------------------------------------
907 //----------------------------------------------------------------------------
908 void vvSlicer::SetRenderWindow(int orientation, vtkRenderWindow * rw)
910 this->Superclass::SetRenderWindow(rw);
911 this->SetupInteractor(rw->GetInteractor());
912 ca->SetImageActor(this->GetImageActor());
913 ca->SetWindowLevel(this->GetWindowLevel());
914 ca->SetText(2, "<slice>");
915 ca->SetText(3, "<window>\n<level>");
927 crossCursor->SetModelBounds(bounds);
928 this->GetRenderer()->AddActor(pdmA);
929 this->GetRenderer()->AddActor(ca);
930 this->GetRenderer()->ResetCamera();
932 //this is just a mapping between the labeling of the orientations presented to the user and
933 //the one used by vtk
934 SetSliceOrientation(2-(orientation%3));
937 //----------------------------------------------------------------------------
940 //----------------------------------------------------------------------------
941 void vvSlicer::ResetCamera()
943 this->GetRenderer()->ResetCamera();
945 //----------------------------------------------------------------------------
948 //----------------------------------------------------------------------------
949 void vvSlicer::SetDisplayMode(bool i)
951 this->GetImageActor()->SetVisibility(i);
952 this->GetAnnotation()->SetVisibility(i);
953 this->GetRenderer()->SetDraw(i);
955 mLandActor->SetVisibility(i);
956 pdmA->SetVisibility(i);
958 UpdateDisplayExtent();
960 //----------------------------------------------------------------------------
963 //----------------------------------------------------------------------------
964 void vvSlicer::FlipHorizontalView()
966 vtkCamera *cam = this->Renderer ? this->Renderer->GetActiveCamera() : NULL;
968 double *position = cam->GetPosition();
969 switch (this->SliceOrientation) {
970 case vtkImageViewer2::SLICE_ORIENTATION_XY:
971 cam->SetPosition(position[0],position[1],-position[2]);
974 case vtkImageViewer2::SLICE_ORIENTATION_XZ:
975 cam->SetPosition(position[0],-position[1],position[2]);
978 case vtkImageViewer2::SLICE_ORIENTATION_YZ:
979 cam->SetPosition(-position[0],position[1],position[2]);
982 this->Renderer->ResetCameraClippingRange();
983 this->UpdateDisplayExtent();
986 //----------------------------------------------------------------------------
989 //----------------------------------------------------------------------------
990 void vvSlicer::FlipVerticalView()
992 vtkCamera *cam = this->Renderer ? this->Renderer->GetActiveCamera() : NULL;
994 FlipHorizontalView();
995 double *viewup = cam->GetViewUp();
996 cam->SetViewUp(-viewup[0],-viewup[1],-viewup[2]);
997 this->UpdateDisplayExtent();
1000 //----------------------------------------------------------------------------
1003 //----------------------------------------------------------------------------
1004 void vvSlicer::SetColorWindow(double window)
1006 vtkLookupTable* LUT = static_cast<vtkLookupTable*>(this->GetWindowLevel()->GetLookupTable());
1008 double level = this->GetWindowLevel()->GetLevel();
1009 LUT->SetTableRange(level-fabs(window)/4,level+fabs(window)/4);
1012 this->vtkImageViewer2::SetColorWindow(window);
1014 //----------------------------------------------------------------------------
1017 //----------------------------------------------------------------------------
1018 void vvSlicer::SetColorLevel(double level)
1020 vtkLookupTable* LUT = static_cast<vtkLookupTable*>(this->GetWindowLevel()->GetLookupTable());
1022 double window = this->GetWindowLevel()->GetWindow();
1023 LUT->SetTableRange(level-fabs(window)/4,level+fabs(window)/4);
1026 this->vtkImageViewer2::SetColorLevel(level);
1028 //----------------------------------------------------------------------------
1030 //----------------------------------------------------------------------------
1031 // Returns the min an the max value in a 41x41 region around the mouse pointer
1032 void vvSlicer::GetExtremasAroundMousePointer(double & min, double & max)
1034 //Get mouse pointer position in view coordinates
1035 double fLocalExtents[6];
1036 for(int i=0; i<3; i++) {
1037 fLocalExtents[i*2 ] = mCurrent[i];
1038 fLocalExtents[i*2+1] = mCurrent[i];
1040 this->Renderer->WorldToView(fLocalExtents[0], fLocalExtents[2], fLocalExtents[4]);
1041 this->Renderer->WorldToView(fLocalExtents[1], fLocalExtents[3], fLocalExtents[5]);
1042 for(int i=0; i<3; i++) {
1043 if (i!=SliceOrientation) { //SR: assumes that SliceOrientation is valid in ViewCoordinates (???)
1044 fLocalExtents[i*2 ] -= 0.2;
1045 fLocalExtents[i*2+1] += 0.2;
1048 this->Renderer->ViewToWorld(fLocalExtents[0], fLocalExtents[2], fLocalExtents[4]);
1049 this->Renderer->ViewToWorld(fLocalExtents[1], fLocalExtents[3], fLocalExtents[5]);
1051 //Convert to image pixel coordinates (rounded)
1052 int iLocalExtents[6];
1053 for(int i=0; i<3; i++) {
1054 fLocalExtents[i*2 ] = (fLocalExtents[i*2 ] - this->GetInput()->GetOrigin()[i])/this->GetInput()->GetSpacing()[i];
1055 fLocalExtents[i*2+1] = (fLocalExtents[i*2+1] - this->GetInput()->GetOrigin()[i])/this->GetInput()->GetSpacing()[i];
1057 iLocalExtents[i*2 ] = lrint(fLocalExtents[i*2 ]);
1058 iLocalExtents[i*2+1] = lrint(fLocalExtents[i*2+1]);
1060 if(iLocalExtents[i*2 ]>iLocalExtents[i*2+1])
1061 std::swap(iLocalExtents[i*2], iLocalExtents[i*2+1]);
1064 vtkSmartPointer<vtkExtractVOI> voiFilter = vtkSmartPointer<vtkExtractVOI>::New();
1065 voiFilter->SetInput(this->GetInput());
1066 voiFilter->SetVOI(iLocalExtents);
1067 voiFilter->Update();
1068 if (!voiFilter->GetOutput()->GetNumberOfPoints()) {
1074 vtkSmartPointer<vtkImageAccumulate> accFilter = vtkSmartPointer<vtkImageAccumulate>::New();
1075 accFilter->SetInput(voiFilter->GetOutput());
1076 accFilter->Update();
1078 min = *(accFilter->GetMin());
1079 max = *(accFilter->GetMax());
1081 //----------------------------------------------------------------------------
1083 //----------------------------------------------------------------------------
1084 double vvSlicer::GetScalarComponentAsDouble(vtkImageData *image, int X, double Y, double Z, int &ix, int &iy, int &iz, int component)
1089 if (ix < image->GetWholeExtent()[0] ||
1090 ix > image->GetWholeExtent()[1] ||
1091 iy < image->GetWholeExtent()[2] ||
1092 iy > image->GetWholeExtent()[3] ||
1093 iz < image->GetWholeExtent()[4] ||
1094 iz > image->GetWholeExtent()[5] )
1097 image->SetUpdateExtent(ix, ix, iy, iy, iz, iz);
1099 return image->GetScalarComponentAsDouble(ix, iy, iz, component);
1101 //----------------------------------------------------------------------------
1103 //----------------------------------------------------------------------------
1104 void vvSlicer::Render()
1106 if (this->GetWindowLevel()->GetLookupTable() && !this->mOverlay && !this->mFusion) {
1107 legend->SetLookupTable(this->GetWindowLevel()->GetLookupTable());
1108 legend->SetVisibility(1);
1109 } else legend->SetVisibility(0);
1111 if (ca->GetVisibility()) {
1112 std::string worldPos = "";
1113 std::stringstream world1;
1114 std::stringstream world2;
1115 std::stringstream world3;
1116 world1 << (int)mCurrent[0];
1117 world2 << (int)mCurrent[1];
1118 world3 << (int)mCurrent[2];
1119 double X = (mCurrent[0] - this->GetInput()->GetOrigin()[0])/this->GetInput()->GetSpacing()[0];
1120 double Y = (mCurrent[1] - this->GetInput()->GetOrigin()[1])/this->GetInput()->GetSpacing()[1];
1121 double Z = (mCurrent[2] - this->GetInput()->GetOrigin()[2])/this->GetInput()->GetSpacing()[2];
1123 // if (X < this->GetInput()->GetWholeExtent()[0]) X = this->GetInput()->GetWholeExtent()[0];
1124 // else if (X > this->GetInput()->GetWholeExtent()[1]) X = this->GetInput()->GetWholeExtent()[1];
1125 // if (Y < this->GetInput()->GetWholeExtent()[2]) Y = this->GetInput()->GetWholeExtent()[2];
1126 // else if (Y > this->GetInput()->GetWholeExtent()[3]) Y = this->GetInput()->GetWholeExtent()[3];
1127 // if (Z < this->GetInput()->GetWholeExtent()[4]) Z = this->GetInput()->GetWholeExtent()[4];
1128 // else if (Z > this->GetInput()->GetWholeExtent()[5]) Z = this->GetInput()->GetWholeExtent()[5];
1130 if (X >= this->GetInput()->GetWholeExtent()[0] &&
1131 X <= this->GetInput()->GetWholeExtent()[1] &&
1132 Y >= this->GetInput()->GetWholeExtent()[2] &&
1133 Y <= this->GetInput()->GetWholeExtent()[3] &&
1134 Z >= this->GetInput()->GetWholeExtent()[4] &&
1135 Z <= this->GetInput()->GetWholeExtent()[5]) {
1139 double value = this->GetScalarComponentAsDouble(this->GetInput(), X, Y, Z, ix, iy, iz);
1141 std::stringstream pixel1;
1142 std::stringstream pixel2;
1143 std::stringstream pixel3;
1144 std::stringstream temps;
1148 temps << mCurrentTSlice;
1150 std::stringstream val;
1152 worldPos += "data value : " + val.str();
1153 worldPos += "\n mm : " + world1.str() + " " + world2.str() + " " +
1154 world3.str() + " " + temps.str();
1155 worldPos += "\n pixel : " + pixel1.str() + " " + pixel2.str() + " " +
1156 pixel3.str() + " " + temps.str();
1158 ca->SetText(1,worldPos.c_str());
1161 if (pdmA->GetVisibility()) {
1162 double x = mCursor[0];
1163 double y = mCursor[1];
1164 double z = mCursor[2];
1165 double xCursor = (x - this->GetInput()->GetOrigin()[0])/this->GetInput()->GetSpacing()[0];
1166 double yCursor = (y - this->GetInput()->GetOrigin()[1])/this->GetInput()->GetSpacing()[1];
1167 double zCursor = (z - this->GetInput()->GetOrigin()[2])/this->GetInput()->GetSpacing()[2];
1169 if (xCursor >= this->GetImageActor()->GetDisplayExtent()[0] &&
1170 xCursor < this->GetImageActor()->GetDisplayExtent()[1]+1 &&
1171 yCursor >= this->GetImageActor()->GetDisplayExtent()[2] &&
1172 yCursor < this->GetImageActor()->GetDisplayExtent()[3]+1 &&
1173 zCursor >= this->GetImageActor()->GetDisplayExtent()[4] &&
1174 zCursor < this->GetImageActor()->GetDisplayExtent()[5]+1 ) {
1175 vtkRenderer * renderer = this->Renderer;
1177 renderer->WorldToView(x,y,z);
1178 renderer->ViewToNormalizedViewport(x,y,z);
1179 renderer->NormalizedViewportToViewport(x,y);
1180 renderer->ViewportToNormalizedDisplay(x,y);
1181 renderer->NormalizedDisplayToDisplay(x,y);
1182 crossCursor->SetFocalPoint(x,y,z);
1184 crossCursor->SetFocalPoint(-1,-1,z);
1188 if (mOverlay && mOverlayActor->GetVisibility()) {
1189 mOverlayMapper->SetWindow(this->GetColorWindow());
1190 mOverlayMapper->SetLevel(this->GetColorLevel());
1191 mOverlayMapper->GetOutput()->SetUpdateExtent(mOverlayActor->GetDisplayExtent());
1192 mOverlayMapper->GetOutput()->Update();
1193 mOverlayMapper->Update();
1198 this->GetRenderWindow()->Render();
1200 //----------------------------------------------------------------------------
1203 //----------------------------------------------------------------------------
1204 void vvSlicer::UpdateCursorPosition()
1206 if (this->GetImageActor()->GetVisibility()) {
1207 pdmA->SetVisibility(true);
1208 mCursor[0] = mCurrent[0];
1209 mCursor[1] = mCurrent[1];
1210 mCursor[2] = mCurrent[2];
1211 mCursor[3] = mCurrentTSlice;
1214 //----------------------------------------------------------------------------
1217 //----------------------------------------------------------------------------
1218 void vvSlicer::UpdateLandmarks()
1220 vtkPolyData *pd = static_cast<vtkPolyData*>(mLandClipper->GetInput());
1221 if (pd->GetPoints()) {
1222 mLandGlyph->SetRange(0,1);
1223 mLandGlyph->Modified();
1224 mLandGlyph->Update();
1226 mClipBox->Modified();
1227 mLandClipper->Update();
1228 mLandMapper->Update();
1232 //----------------------------------------------------------------------------
1235 //----------------------------------------------------------------------------
1236 void vvSlicer::SetSlice(int slice)
1238 int *range = this->GetSliceRange();
1240 if (slice < range[0]) {
1242 } else if (slice > range[1]) {
1247 if (this->Slice == slice) {
1251 this->Slice = slice;
1254 this->UpdateDisplayExtent();
1256 // Seems to work without this line
1259 //----------------------------------------------------------------------------
1262 //----------------------------------------------------------------------------
1263 void vvSlicer::SetContourSlice()
1265 if (mSurfaceCutActors.size() > 0)
1266 for (std::vector<vvMeshActor*>::iterator i=mSurfaceCutActors.begin();
1267 i!=mSurfaceCutActors.end(); i++)
1268 (*i)->SetCutSlice((this->Slice)*this->GetImage()->GetSpacing()[this->SliceOrientation]+
1269 this->GetImage()->GetOrigin()[this->SliceOrientation]);
1271 //----------------------------------------------------------------------------
1274 //----------------------------------------------------------------------------
1275 void vvSlicer::ForceUpdateDisplayExtent()
1277 this->UpdateDisplayExtent();
1279 //----------------------------------------------------------------------------
1282 //----------------------------------------------------------------------------
1283 int* vvSlicer::GetDisplayExtent()
1285 return this->GetImageActor()->GetDisplayExtent();
1287 //----------------------------------------------------------------------------
1290 //----------------------------------------------------------------------------
1291 void vvSlicer::PrintSelf(ostream& os, vtkIndent indent)
1293 this->Superclass::PrintSelf(os, indent);
1295 //----------------------------------------------------------------------------
1297 //----------------------------------------------------------------------------
1298 void vvSlicer::SetVFColor(double r, double g, double b)
1300 double mVFColorHSV[3];
1305 vtkMath::RGBToHSV(mVFColor, mVFColorHSV);
1306 mVFColorLUT->SetHueRange(mVFColorHSV[0], mVFColorHSV[0]);
1307 mVFColorLUT->SetSaturationRange(mVFColorHSV[1],mVFColorHSV[1]);
1308 mVFColorLUT->SetValueRange(mVFColorHSV[2], mVFColorHSV[2]);