X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=vv%2FvvSlicer.cxx;h=7efaf2675c4caa351f090d1ce2de2a5d3e397972;hb=30133023f12212c84e7b4e9318f1055ec3176af1;hp=77f75356314da830272042bfd5754b23d4a8a6e4;hpb=559498f6da47f1d9e16d51c784645fed0962a201;p=clitk.git diff --git a/vv/vvSlicer.cxx b/vv/vvSlicer.cxx index 77f7535..7efaf26 100644 --- a/vv/vvSlicer.cxx +++ b/vv/vvSlicer.cxx @@ -3,7 +3,7 @@ Authors belong to: - University of LYON http://www.universite-lyon.fr/ - - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr + - Léon Bérard cancer center http://www.centreleonberard.fr - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr This software is distributed WITHOUT ANY WARRANTY; without even @@ -14,15 +14,23 @@ - BSD See included LICENSE.txt file - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html - ======================================================================-====*/ + ===========================================================================**/ + +#include +#include #include "vvSlicer.h" #include "vvImage.h" #include "vvSlicerManagerCommand.h" #include "vvGlyphSource.h" #include "vvGlyph2D.h" -#include "vvImageMapToWLColors.h" +#include +#include +#include +#include +#include +#include #include #include #include @@ -41,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -66,26 +75,40 @@ #include #include #include +#if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION >= 10) +# include +# include +# include +#endif -vtkCxxRevisionMacro(vvSlicer, "DummyRevision"); vtkStandardNewMacro(vvSlicer); - +static void copyExtent(int* in, int* to){ + for(int i=0; i<6; ++i) + { + to[i]=in[i]; + } +} //------------------------------------------------------------------------------ vvSlicer::vvSlicer() -{ +{ + mFusionSequenceCode = -1; this->UnInstallPipeline(); mImage = NULL; + mReducedExtent = new int[6]; + mRegisterExtent = NULL; mCurrentTSlice = 0; + mCurrentFusionTSlice = 0; + mCurrentOverlayTSlice = 0; mUseReducedExtent = false; mCurrent[0] = -VTK_DOUBLE_MAX; mCurrent[1] = -VTK_DOUBLE_MAX; mCurrent[2] = -VTK_DOUBLE_MAX; - mCursor[0] = -VTK_DOUBLE_MAX; - mCursor[1] = -VTK_DOUBLE_MAX; - mCursor[2] = -VTK_DOUBLE_MAX; - mCursor[3] = -VTK_DOUBLE_MAX; + mCursor[0] = 0;//-VTK_DOUBLE_MAX; + mCursor[1] = 0;//-VTK_DOUBLE_MAX; + mCursor[2] = 0;//-VTK_DOUBLE_MAX; + mCursor[3] = 0;//-VTK_DOUBLE_MAX; mSubSampling = 5; mScale = 1; @@ -95,22 +118,6 @@ vvSlicer::vvSlicer() mVFColor[1] = 1; mVFColor[2] = 0; - std::string text = "F1 = sagital; F2 = coronal; F3 = axial\n"; - text += "F5 = horizontal flip; F6 = vertical flip\n\n"; - text += "0,1,2,3,4,5 : preset windowing\n"; - text += "6,7,8,9 : preset colormap\n"; - text += "z : local windowing\n"; - text += "r : reset view\n"; - text += "l : reload image\n"; - text += "f : fly to mouse position\n"; - text += "g : go to cross hair position\n\n"; - text += "Up,down : change slice\n"; - text += "Left,right : change tenporal slice\n\n"; - text += "Scrollbar (or w/x) : zoom in/out\n"; - text += "left button : synchronize all views\n"; - text += "middle button : grab image\n"; - text += "right button : change windowing\n"; - crossCursor = vtkSmartPointer::New(); crossCursor->AllOff(); crossCursor->AxesOn(); @@ -118,7 +125,11 @@ vvSlicer::vvSlicer() crossCursor->SetRadius(2); pdm = vtkSmartPointer::New(); +#if VTK_MAJOR_VERSION <= 5 pdm->SetInput(crossCursor->GetOutput()); +#else + pdm->SetInputConnection(crossCursor->GetOutputPort(0)); +#endif pdmA = vtkSmartPointer::New(); pdmA->SetMapper(pdm); @@ -143,18 +154,29 @@ vvSlicer::vvSlicer() legend->SetVisibility(0); legend->SetLabelFormat("%.1f"); this->GetRenderer()->AddActor(legend); - - this->WindowLevel->Delete(); - this->WindowLevel = vvImageMapToWLColors::New(); + showFusionLegend = false; this->InstallPipeline(); + + mLinkOverlayWindowLevel = true; + mImageVisibility = true; + +#if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION >= 10) + this->GetImageActor()->GetMapper()->BorderOn(); +#endif + + mSlicingTransform = vtkSmartPointer::New(); + mConcatenatedTransform = vtkSmartPointer::New(); + mConcatenatedFusionTransform = vtkSmartPointer::New(); + mConcatenatedOverlayTransform = vtkSmartPointer::New(); + mFirstSetSliceOrientation = true; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ vtkImageMapToWindowLevelColors* vvSlicer::GetOverlayMapper() -{ +{ return mOverlayMapper.GetPointer(); } //------------------------------------------------------------------------------ @@ -162,15 +184,15 @@ vtkImageMapToWindowLevelColors* vvSlicer::GetOverlayMapper() //------------------------------------------------------------------------------ vvBlendImageActor* vvSlicer::GetOverlayActor() -{ +{ return mOverlayActor.GetPointer(); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ -vtkImageMapToWindowLevelColors* vvSlicer::GetFusionMapper() -{ +vtkImageMapToColors* vvSlicer::GetFusionMapper() +{ return mFusionMapper.GetPointer(); } //------------------------------------------------------------------------------ @@ -178,7 +200,7 @@ vtkImageMapToWindowLevelColors* vvSlicer::GetFusionMapper() //------------------------------------------------------------------------------ vtkImageActor* vvSlicer::GetFusionActor() -{ +{ return mFusionActor.GetPointer(); } //------------------------------------------------------------------------------ @@ -186,7 +208,7 @@ vtkImageActor* vvSlicer::GetFusionActor() //------------------------------------------------------------------------------ vtkActor* vvSlicer::GetVFActor() -{ +{ return mVFActor.GetPointer(); } //------------------------------------------------------------------------------ @@ -194,7 +216,7 @@ vtkActor* vvSlicer::GetVFActor() //------------------------------------------------------------------------------ vtkCornerAnnotation* vvSlicer::GetAnnotation() -{ +{ return ca.GetPointer(); } //------------------------------------------------------------------------------ @@ -202,7 +224,7 @@ vtkCornerAnnotation* vvSlicer::GetAnnotation() //------------------------------------------------------------------------------ void vvSlicer::EnableReducedExtent(bool b) -{ +{ mUseReducedExtent = b; } //------------------------------------------------------------------------------ @@ -210,15 +232,15 @@ void vvSlicer::EnableReducedExtent(bool b) //------------------------------------------------------------------------------ void vvSlicer::SetReducedExtent(int * ext) -{ - mReducedExtent = ext; +{ + copyExtent(ext, mReducedExtent); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ void vvSlicer::AddContour(vvMesh::Pointer contour,bool propagate) -{ +{ mSurfaceCutActors.push_back(new vvMeshActor()); if (propagate) @@ -235,7 +257,7 @@ void vvSlicer::AddContour(vvMesh::Pointer contour,bool propagate) //------------------------------------------------------------------------------ void vvSlicer::ToggleContourSuperposition() -{ +{ for (std::vector::iterator i=mSurfaceCutActors.begin(); i!=mSurfaceCutActors.end(); i++) (*i)->ToggleSuperposition(); @@ -245,7 +267,7 @@ void vvSlicer::ToggleContourSuperposition() //------------------------------------------------------------------------------ void vvSlicer::SetCursorColor(int r,int g, int b) -{ +{ pdmA->GetProperty()->SetColor(r,g,b); } //------------------------------------------------------------------------------ @@ -253,7 +275,7 @@ void vvSlicer::SetCursorColor(int r,int g, int b) //------------------------------------------------------------------------------ void vvSlicer::SetCursorVisibility(bool s) -{ +{ pdmA->SetVisibility(s); } //------------------------------------------------------------------------------ @@ -261,7 +283,7 @@ void vvSlicer::SetCursorVisibility(bool s) //------------------------------------------------------------------------------ bool vvSlicer::GetCursorVisibility() -{ +{ return pdmA->GetVisibility(); } //------------------------------------------------------------------------------ @@ -269,7 +291,7 @@ bool vvSlicer::GetCursorVisibility() //------------------------------------------------------------------------------ void vvSlicer::SetCornerAnnotationVisibility(bool s) -{ +{ ca->SetVisibility(s); } //------------------------------------------------------------------------------ @@ -277,7 +299,7 @@ void vvSlicer::SetCornerAnnotationVisibility(bool s) //------------------------------------------------------------------------------ bool vvSlicer::GetCornerAnnotationVisibility() -{ +{ return ca->GetVisibility(); } //------------------------------------------------------------------------------ @@ -285,45 +307,86 @@ bool vvSlicer::GetCornerAnnotationVisibility() //------------------------------------------------------------------------------ vvSlicer::~vvSlicer() -{ +{ for (std::vector::iterator i=mSurfaceCutActors.begin(); i!=mSurfaceCutActors.end(); i++) delete (*i); + delete [] mReducedExtent; } //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +double* vvSlicer::GetCurrentPosition() +{ + return mCurrentBeforeSlicingTransform; +} +//------------------------------------------------------------------------------ //------------------------------------------------------------------------------ void vvSlicer::SetCurrentPosition(double x, double y, double z, int t) -{ - mCurrent[0] = x; - mCurrent[1] = y; - mCurrent[2] = z; - mCurrentTSlice = t; +{ + mCurrentBeforeSlicingTransform[0]=x; + mCurrentBeforeSlicingTransform[1]=y; + mCurrentBeforeSlicingTransform[2]=z; + mSlicingTransform->GetInverse()->TransformPoint(mCurrentBeforeSlicingTransform,mCurrent); + if (t>=0) SetTSlice(t); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ void vvSlicer::SetImage(vvImage::Pointer image) -{ +{ if (image->GetVTKImages().size()) { mImage = image; - this->Superclass::SetInput(image->GetTransformedVTKImages()[0]); + + if (!mImageReslice) { + mImageReslice = vtkSmartPointer::New(); + mImageReslice->SetInterpolationModeToLinear(); + mImageReslice->AutoCropOutputOn(); + mImageReslice->SetBackgroundColor(-1000,-1000,-1000,1); + } + + mConcatenatedTransform->Identity(); + mConcatenatedTransform->Concatenate(mImage->GetTransform()[0]); + mConcatenatedTransform->Concatenate(mSlicingTransform); + mImageReslice->SetResliceTransform(mConcatenatedTransform); +#if VTK_MAJOR_VERSION <= 5 + mImageReslice->SetInput(0, mImage->GetFirstVTKImageData()); +#else + mImageReslice->SetInputData(0, mImage->GetFirstVTKImageData()); +#endif + mImageReslice->UpdateInformation(); + +#if VTK_MAJOR_VERSION <= 5 + this->Superclass::SetInput(mImageReslice->GetOutput()); +#else + this->Superclass::SetInputConnection(mImageReslice->GetOutputPort()); +#endif int extent[6]; +#if VTK_MAJOR_VERSION <= 5 this->GetInput()->GetWholeExtent(extent); +#else + int* ext = mImageReslice->GetInputInformation()->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + copyExtent(ext, extent); +#endif // Prevent crash when reload -> change slice if outside extent if (Slice < extent[SliceOrientation*2] || Slice>=extent[SliceOrientation*2+1]) { - Slice = (extent[SliceOrientation*2+1]-extent[SliceOrientation*2])/2.0; + Slice = (extent[SliceOrientation*2+1]+extent[SliceOrientation*2])/2.0; } // Make sure that the required part image has been computed extent[SliceOrientation*2] = Slice; - extent[SliceOrientation*2+1] = Slice; - image->GetTransformedVTKImages()[0]->SetUpdateExtent(extent); - image->GetTransformedVTKImages()[0]->Update(); + extent[SliceOrientation*2+1] = Slice; +#if VTK_MAJOR_VERSION <= 5 + mImageReslice->GetOutput()->SetUpdateExtent(extent); + mImageReslice->GetOutput()->Update(); +#else + //mImageReslice->SetUpdateExtent(extent); + mImageReslice->Update(); +#endif this->UpdateDisplayExtent(); @@ -336,22 +399,52 @@ void vvSlicer::SetImage(vvImage::Pointer image) //------------------------------------------------------------------------------ void vvSlicer::SetOverlay(vvImage::Pointer overlay) -{ +{ if (overlay->GetVTKImages().size()) { mOverlay = overlay; + mOverlayVisibility = true; + + if (!mOverlayReslice) { + mOverlayReslice = vtkSmartPointer::New(); + mOverlayReslice->SetInterpolationModeToLinear(); + mOverlayReslice->AutoCropOutputOn(); + mOverlayReslice->SetBackgroundColor(-1000,-1000,-1000,1); + } + + mConcatenatedOverlayTransform->Identity(); + mConcatenatedOverlayTransform->Concatenate(mOverlay->GetTransform()[0]); + mConcatenatedOverlayTransform->Concatenate(mSlicingTransform); + mOverlayReslice->SetResliceTransform(mConcatenatedOverlayTransform); +#if VTK_MAJOR_VERSION <= 5 + mOverlayReslice->SetInput(0, mOverlay->GetFirstVTKImageData()); + mImageReslice->UpdateInformation(); +#else + mOverlayReslice->SetInputData(0, mOverlay->GetFirstVTKImageData()); +#endif + mOverlayReslice->Update(); if (!mOverlayMapper) mOverlayMapper = vtkSmartPointer::New(); - mOverlayMapper->SetInput(overlay->GetTransformedVTKImages()[0]); +#if VTK_MAJOR_VERSION <= 5 + mOverlayMapper->SetInput(mOverlayReslice->GetOutput()); +#else + mOverlayMapper->SetInputConnection(mOverlayReslice->GetOutputPort(0)); +#endif if (!mOverlayActor) { mOverlayActor = vtkSmartPointer::New(); +#if VTK_MAJOR_VERSION <= 5 mOverlayActor->SetInput(mOverlayMapper->GetOutput()); +#else + mOverlayActor->GetMapper()->SetInputConnection(mOverlayMapper->GetOutputPort()); +#endif mOverlayActor->SetPickable(0); - mOverlayActor->SetVisibility(false); + mOverlayActor->SetVisibility(true); mOverlayActor->SetOpacity(0.5); - this->UpdateDisplayExtent(); - } +#if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION >= 10) + mOverlayActor->GetMapper()->BorderOn(); +#endif + } //stupid but necessary : the Overlay need to be rendered before fusion if (mFusionActor) { @@ -361,72 +454,137 @@ void vvSlicer::SetOverlay(vvImage::Pointer overlay) } else this->GetRenderer()->AddActor(mOverlayActor); - //Synchronize slice - SetTSlice(mCurrentTSlice); + //Synchronize orientation and slice + AdjustResliceToSliceOrientation(mOverlayReslice); + this->UpdateDisplayExtent(); + this->SetTSlice(mCurrentTSlice); } } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ -void vvSlicer::SetFusion(vvImage::Pointer fusion) -{ +void vvSlicer::SetFusion(vvImage::Pointer fusion, int fusionSequenceCode) +{ + mFusionSequenceCode = fusionSequenceCode; if (fusion->GetVTKImages().size()) { mFusion = fusion; + mFusionVisibility = true; - if (!mFusionMapper) - mFusionMapper = vtkSmartPointer::New(); - mFusionMapper->SetInput(fusion->GetTransformedVTKImages()[0]); + if (!mFusionReslice) { + mFusionReslice = vtkSmartPointer::New(); + mFusionReslice->SetInterpolationModeToLinear(); + mFusionReslice->AutoCropOutputOn(); + mFusionReslice->SetBackgroundColor(-1000,-1000,-1000,1); + } + mConcatenatedFusionTransform->Identity(); + mConcatenatedFusionTransform->Concatenate(mFusion->GetTransform()[0]); + mConcatenatedFusionTransform->Concatenate(mSlicingTransform); + mFusionReslice->SetResliceTransform(mConcatenatedFusionTransform); +#if VTK_MAJOR_VERSION <= 5 + mFusionReslice->SetInput(0, mFusion->GetFirstVTKImageData()); + mFusionReslice->UpdateInformation(); +#else + mFusionReslice->SetInputData(0, mFusion->GetFirstVTKImageData()); +#endif + mFusionReslice->Update(); + + if (!mFusionMapper) + mFusionMapper = vtkSmartPointer::New(); + + vtkSmartPointer lut = vtkLookupTable::New(); + lut->SetRange(0, 1); + lut->SetValueRange(0, 1); + lut->SetSaturationRange(0, 0); + lut->Build(); + mFusionMapper->SetLookupTable(lut); +#if VTK_MAJOR_VERSION <= 5 + mFusionMapper->SetInput(mFusionReslice->GetOutput()); +#else + mFusionMapper->SetInputConnection(mFusionReslice->GetOutputPort(0)); +#endif + if (!mFusionActor) { mFusionActor = vtkSmartPointer::New(); +#if VTK_MAJOR_VERSION <= 5 mFusionActor->SetInput(mFusionMapper->GetOutput()); +#else + mFusionActor->GetMapper()->SetInputConnection(mFusionMapper->GetOutputPort()); +#endif mFusionActor->SetPickable(0); - mFusionActor->SetVisibility(false); + mFusionActor->SetVisibility(true); mFusionActor->SetOpacity(0.7); - this->UpdateDisplayExtent(); +#if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION >= 10) + mFusionActor->GetMapper()->BorderOn(); +#endif + this->GetRenderer()->AddActor(mFusionActor); } - //Synchronize slice - SetTSlice(mCurrentTSlice); + //Synchronize orientation and slice + AdjustResliceToSliceOrientation(mFusionReslice); + this->UpdateDisplayExtent(); + this->SetTSlice(mCurrentTSlice); } } //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +bool vvSlicer::GetActorVisibility(const std::string& actor_type, int overlay_index) +{ + bool vis = false; + if (actor_type == "image") + vis = mImageVisibility; + else if (actor_type == "vector") + vis = mVFVisibility; + else if (actor_type == "overlay") + vis = mOverlayVisibility; + else if ( (actor_type == "fusion") || (actor_type == "fusionSequence") ) + vis = mFusionVisibility; + else if (actor_type == "contour") + vis = this->mSurfaceCutActors[overlay_index]->GetActor()->GetVisibility(); + return vis; +} +//------------------------------------------------------------------------------ + //------------------------------------------------------------------------------ void vvSlicer::SetActorVisibility(const std::string& actor_type, int overlay_index ,bool vis) -{ - if (actor_type == "vector") { - this->mVFActor->SetVisibility(vis); - } - if (actor_type == "overlay") { - this->mOverlayActor->SetVisibility(vis); - } - if (actor_type == "fusion") { - this->mFusionActor->SetVisibility(vis); - } - if (actor_type == "contour") +{ + if (actor_type == "image") + mImageVisibility = vis; + else if (actor_type == "vector") + mVFVisibility = vis; + else if (actor_type == "overlay") + mOverlayVisibility = vis; + else if ( (actor_type == "fusion") || (actor_type == "fusionSequence") ) + mFusionVisibility = vis; + else if (actor_type == "contour") this->mSurfaceCutActors[overlay_index]->GetActor()->SetVisibility(vis); UpdateDisplayExtent(); } //------------------------------------------------------------------------------ - //------------------------------------------------------------------------------ void vvSlicer::SetVF(vvImage::Pointer vf) -{ +{ if (vf->GetVTKImages().size()) { mVF = vf; + mVFVisibility = true; if (!mAAFilter) { mAAFilter= vtkSmartPointer::New(); mVOIFilter = vtkSmartPointer::New(); mVOIFilter->SetSampleRate(mSubSampling,mSubSampling,mSubSampling); } - mVOIFilter->SetInput(vf->GetTransformedVTKImages()[0]); +#if VTK_MAJOR_VERSION <= 5 + mVOIFilter->SetInput(vf->GetFirstVTKImageData()); mAAFilter->SetInput(mVOIFilter->GetOutput()); +#else + mVOIFilter->SetInputData(vf->GetFirstVTKImageData()); + mAAFilter->SetInputConnection(mVOIFilter->GetOutputPort()); +#endif ///This tells VTK to use the scalar (pixel) data of the image to draw the little arrows mAAFilter->Assign(vtkDataSetAttributes::SCALARS, vtkDataSetAttributes::VECTORS, vtkAssignAttribute::POINT_DATA); @@ -439,8 +597,13 @@ void vvSlicer::SetVF(vvImage::Pointer vf) // Glyph the gradient vector (with arrows) if (!mGlyphFilter) mGlyphFilter = vtkSmartPointer::New(); +#if VTK_MAJOR_VERSION <= 5 mGlyphFilter->SetInput(mAAFilter->GetOutput()); mGlyphFilter->SetSource(mArrow->GetOutput()); +#else + mGlyphFilter->SetInputConnection(mAAFilter->GetOutputPort()); + mGlyphFilter->SetSourceConnection(mArrow->GetOutputPort()); +#endif mGlyphFilter->ScalingOn(); mGlyphFilter->SetScaleModeToScaleByVector(); mGlyphFilter->OrientOn(); @@ -458,7 +621,11 @@ void vvSlicer::SetVF(vvImage::Pointer vf) if (!mVFMapper) mVFMapper = vtkSmartPointer::New(); +#if VTK_MAJOR_VERSION <= 5 mVFMapper->SetInput(mGlyphFilter->GetOutput()); +#else + mVFMapper->SetInputConnection(mGlyphFilter->GetOutputPort()); +#endif mVFMapper->ImmediateModeRenderingOn(); mVFMapper->SetLookupTable(mVFColorLUT); @@ -479,48 +646,71 @@ void vvSlicer::SetVF(vvImage::Pointer vf) //------------------------------------------------------------------------------ void vvSlicer::SetLandmarks(vvLandmarks* landmarks) -{ +{ mLandmarks = landmarks; if (landmarks) { if (!mCross) mCross = vtkSmartPointer::New(); + if (!mClipBox) + mClipBox = vtkSmartPointer::New(); + if (!mLandClipper) + mLandClipper = vtkSmartPointer::New(); + if (!mLandGlyph) + mLandGlyph = vtkSmartPointer::New(); + if (!mLandMapper) + mLandMapper = vtkSmartPointer::New(); + if (!mLandActor) + mLandActor = vtkSmartPointer::New(); + mCross->SetFocalPoint(0.0,0.0,0.0); mCross->SetModelBounds(-10,10,-10,10,-10,10); mCross->AllOff(); mCross->AxesOn(); - if (!mLandGlyph) - mLandGlyph = vtkSmartPointer::New(); + mLandClipper->SetClipFunction(mClipBox); + mLandClipper->InsideOutOn(); +#if VTK_MAJOR_VERSION <= 5 + mLandmarkTransform = vtkSmartPointer::New(); + mLandmarkTransform->SetInput(mLandmarks->GetOutput()); + mConcatenatedTransform->Identity(); + mConcatenatedTransform->Concatenate(mImage->GetTransform()[0]); + mConcatenatedTransform->Concatenate(mSlicingTransform); + mLandmarkTransform->SetTransform(mConcatenatedTransform->GetInverse()); + mLandClipper->SetInput(mLandmarkTransform->GetOutput()); + mLandGlyph->SetSource(mCross->GetOutput()); - mLandGlyph->SetInput(landmarks->GetOutput()); + mLandGlyph->SetInput(mLandClipper->GetOutput()); +#else + mLandmarkTransform = vtkSmartPointer::New(); + mLandmarkTransform->SetInputData(mLandmarks->GetOutput()); + mConcatenatedTransform->Identity(); + mConcatenatedTransform->Concatenate(mImage->GetTransform()[0]); + mConcatenatedTransform->Concatenate(mSlicingTransform); + mLandmarkTransform->SetTransform(mConcatenatedTransform->GetInverse()); + mLandClipper->SetInputConnection(mLandmarkTransform->GetOutputPort()); + + mLandGlyph->SetSourceConnection(mCross->GetOutputPort()); + mLandGlyph->SetInputConnection(mLandClipper->GetOutputPort()); +#endif //mLandGlyph->SetIndexModeToScalar(); - mLandGlyph->SetRange(0,1); - mLandGlyph->ScalingOff(); + //mLandGlyph->SetRange(0,1); + //mLandGlyph->ScalingOff(); - mLandGlyph->SetColorModeToColorByScalar(); + //mLandGlyph->SetColorModeToColorByScalar(); + + mLandGlyph->SetScaleModeToDataScalingOff(); + mLandGlyph->SetIndexModeToOff(); - if (!mClipBox) - mClipBox = vtkSmartPointer::New(); - if (!mLandClipper) - mLandClipper = vtkSmartPointer::New(); - mLandClipper->InsideOutOn(); - mLandClipper->SetInput(mLandGlyph->GetOutput()); - mLandClipper->SetClipFunction(mClipBox); - - if (!mLandMapper) - mLandMapper = vtkSmartPointer::New(); - mLandMapper->SetInputConnection(mLandClipper->GetOutputPort()); + mLandMapper->SetInputConnection(mLandGlyph->GetOutputPort()); //mLandMapper->ScalarVisibilityOff(); - if (!mLandActor) - mLandActor = vtkSmartPointer::New(); mLandActor->SetMapper(mLandMapper); + mLandActor->GetProperty()->SetOpacity(0.995); //in order to get VTK to turn on the alpha-blending in OpenGL mLandActor->GetProperty()->SetColor(255,10,212); mLandActor->SetPickable(0); mLandActor->SetVisibility(true); this->UpdateDisplayExtent(); - this->GetRenderer()->AddActor(mLandActor); } } //------------------------------------------------------------------------------ @@ -528,7 +718,7 @@ void vvSlicer::SetLandmarks(vvLandmarks* landmarks) //------------------------------------------------------------------------------ //FIXME: this function leaks memory, we should fix it someday :) void vvSlicer::RemoveActor(const std::string& actor_type, int overlay_index) -{ +{ if (actor_type == "vector") { Renderer->RemoveActor(mVFActor); mGlyphFilter=NULL; @@ -545,7 +735,7 @@ void vvSlicer::RemoveActor(const std::string& actor_type, int overlay_index) mOverlayActor = NULL; mOverlayMapper = NULL; } - if (actor_type == "fusion") { + if ( (actor_type == "fusion") || (actor_type == "fusionSequence") ) { Renderer->RemoveActor(mFusionActor); mFusion = NULL; mFusionActor = NULL; @@ -561,7 +751,7 @@ void vvSlicer::RemoveActor(const std::string& actor_type, int overlay_index) //------------------------------------------------------------------------------ void vvSlicer::SetVFSubSampling(int sub) -{ +{ if (mVOIFilter) { mVOIFilter->SetSampleRate(mSubSampling,mSubSampling,mSubSampling); mSubSampling = sub; @@ -574,7 +764,7 @@ void vvSlicer::SetVFSubSampling(int sub) //------------------------------------------------------------------------------ void vvSlicer::SetVFScale(int scale) -{ +{ mScale = scale; if (mArrow) mArrow->SetScale(mScale); @@ -585,7 +775,7 @@ void vvSlicer::SetVFScale(int scale) //------------------------------------------------------------------------------ void vvSlicer::SetVFWidth(int width) -{ +{ mVFWidth = width; if (mVFActor) mVFActor->GetProperty()->SetLineWidth(mVFWidth); @@ -597,7 +787,7 @@ void vvSlicer::SetVFWidth(int width) //------------------------------------------------------------------------------ void vvSlicer::SetVFLog(int log) -{ +{ mVFLog = log; if (mGlyphFilter) { mGlyphFilter->SetUseLog(mVFLog); @@ -610,28 +800,78 @@ void vvSlicer::SetVFLog(int log) //------------------------------------------------------------------------------ -void vvSlicer::SetTSlice(int t) -{ +void vvSlicer::SetTSlice(int t, bool updateLinkedImages) +{ + if (!updateLinkedImages) { + mCurrentTSlice = t; +#if VTK_MAJOR_VERSION <= 5 + mImageReslice->SetInput( mImage->GetVTKImages()[mCurrentTSlice] ); +#else + mImageReslice->SetInputData( mImage->GetVTKImages()[mCurrentTSlice] ); +#endif + // Update transform + mConcatenatedTransform->Identity(); + mConcatenatedTransform->Concatenate(mImage->GetTransform()[mCurrentTSlice]); + mConcatenatedTransform->Concatenate(mSlicingTransform); + UpdateDisplayExtent(); + return; + } if (t < 0) - t = 0; + mCurrentTSlice = 0; else if ((unsigned int)t >= mImage->GetVTKImages().size()) - t = mImage->GetVTKImages().size() -1; - - if (mCurrentTSlice == t) return; - - mCurrentTSlice = t; - this->SetInput(mImage->GetTransformedVTKImages()[t]); + mCurrentTSlice = mImage->GetVTKImages().size() -1; + else + mCurrentTSlice = t; + + // Update transform + mConcatenatedTransform->Identity(); + mConcatenatedTransform->Concatenate(mImage->GetTransform()[mCurrentTSlice]); + mConcatenatedTransform->Concatenate(mSlicingTransform); + + // Update image data +#if VTK_MAJOR_VERSION <= 5 + mImageReslice->SetInput( mImage->GetVTKImages()[mCurrentTSlice] ); +#else + mImageReslice->SetInputData( mImage->GetVTKImages()[mCurrentTSlice] ); +#endif if (mVF && mVFActor->GetVisibility()) { if (mVF->GetVTKImages().size() > (unsigned int)mCurrentTSlice) - mVOIFilter->SetInput(mVF->GetTransformedVTKImages()[mCurrentTSlice]); +#if VTK_MAJOR_VERSION <= 5 + mVOIFilter->SetInput(mVF->GetVTKImages()[mCurrentTSlice]); +#else + mVOIFilter->SetInputData(mVF->GetVTKImages()[mCurrentTSlice]); +#endif } + //update the overlay if (mOverlay && mOverlayActor->GetVisibility()) { - if (mOverlay->GetTransformedVTKImages().size() > (unsigned int)mCurrentTSlice) - mOverlayMapper->SetInput(mOverlay->GetTransformedVTKImages()[mCurrentTSlice]); + if (mOverlay->GetVTKImages().size() > (unsigned int)t) { + mCurrentOverlayTSlice = t; +#if VTK_MAJOR_VERSION <= 5 + mOverlayReslice->SetInput( mOverlay->GetVTKImages()[mCurrentOverlayTSlice] ); +#else + mOverlayReslice->SetInputData( mOverlay->GetVTKImages()[mCurrentOverlayTSlice] ); +#endif + // Update overlay transform + mConcatenatedOverlayTransform->Identity(); + mConcatenatedOverlayTransform->Concatenate(mOverlay->GetTransform()[mCurrentOverlayTSlice]); + mConcatenatedOverlayTransform->Concatenate(mSlicingTransform); + } } - if (mFusion && mFusionActor->GetVisibility()) { - if (mFusion->GetVTKImages().size() > (unsigned int)mCurrentTSlice) - mFusionMapper->SetInput(mFusion->GetTransformedVTKImages()[mCurrentTSlice]); + //update the fusion ; except in case this is a fusionSequence, in which case both 'times' should be independent. + if (mFusion && mFusionActor->GetVisibility() && (mFusionSequenceCode<0)) { + if (mFusion->GetVTKImages().size() > (unsigned int)t) { + mCurrentFusionTSlice = t; +#if VTK_MAJOR_VERSION <= 5 + mFusionReslice->SetInput( mFusion->GetVTKImages()[mCurrentFusionTSlice]); +#else + mFusionReslice->SetInputData( mFusion->GetVTKImages()[mCurrentFusionTSlice]); +#endif + + // Update fusion transform + mConcatenatedFusionTransform->Identity(); + mConcatenatedFusionTransform->Concatenate(mFusion->GetTransform()[mCurrentFusionTSlice]); + mConcatenatedFusionTransform->Concatenate(mSlicingTransform); + } } if (mSurfaceCutActors.size() > 0) for (std::vector::iterator i=mSurfaceCutActors.begin(); @@ -642,44 +882,120 @@ void vvSlicer::SetTSlice(int t) //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +void vvSlicer::SetFusionSequenceTSlice(int t) +{ + if (mFusion && mFusionActor->GetVisibility() && (mFusionSequenceCode>=0)) { + if (mFusion->GetVTKImages().size() > (unsigned int)t) { + mCurrentFusionTSlice = t; +#if VTK_MAJOR_VERSION <= 5 + mFusionReslice->SetInput( mFusion->GetVTKImages()[mCurrentFusionTSlice] ); +#else + mFusionReslice->SetInputData( mFusion->GetVTKImages()[mCurrentFusionTSlice] ); +#endif + // Update fusion transform + mConcatenatedFusionTransform->Identity(); + mConcatenatedFusionTransform->Concatenate(mFusion->GetTransform()[mCurrentFusionTSlice]); //not really useful... + mConcatenatedFusionTransform->Concatenate(mSlicingTransform); + } + } + + UpdateDisplayExtent(); +} +//------------------------------------------------------------------------------ + + //------------------------------------------------------------------------------ int vvSlicer::GetTSlice() -{ +{ return mCurrentTSlice; } //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +int vvSlicer::GetMaxCurrentTSlice() +{ + int t = mCurrentTSlice; + if(mOverlay && mOverlayActor->GetVisibility()) + t = std::max(t, mCurrentOverlayTSlice); + if(mFusion&& (mFusionSequenceCode<0) && mFusionActor->GetVisibility()) //ignore fusionSequence data: for these, the times are not to be related (this way) + t = std::max(t, mCurrentFusionTSlice); + return t; +} +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +int vvSlicer::GetFusionTSlice() +{ + return mCurrentFusionTSlice; +} +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +int vvSlicer::GetOverlayTSlice() +{ + return mCurrentOverlayTSlice; +} +//------------------------------------------------------------------------------ //------------------------------------------------------------------------------ void vvSlicer::SetSliceOrientation(int orientation) -{ +{ //if 2D image, force to watch in Axial View int extent[6]; - this->GetInput()->GetWholeExtent(extent); +#if VTK_MAJOR_VERSION <= 5 + this->GetInput()->GetWholeExtent(extent); +#else + int* ext = mImageReslice->GetInputInformation()->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + copyExtent(ext, extent); +#endif + if (extent[5]-extent[4] <= 2) - orientation=2; + orientation = vtkImageViewer2::SLICE_ORIENTATION_XY; if (orientation < vtkImageViewer2::SLICE_ORIENTATION_YZ || orientation > vtkImageViewer2::SLICE_ORIENTATION_XY) { vtkErrorMacro("Error - invalid slice orientation " << orientation); return; } - + this->SliceOrientation = orientation; - // Update the viewer - int *range = this->GetSliceRange(); - if (range) - this->Slice = static_cast((range[0] + range[1]) * 0.5); + if(mFusion) + AdjustResliceToSliceOrientation(mFusionReslice); + + if(mOverlay) + AdjustResliceToSliceOrientation(mOverlayReslice); + // Update the viewer + // Go to current cursor position // double* cursorPos = GetCursorPosition(); // DDV(cursorPos, 3); // SetCurrentPosition(cursorPos[0],cursorPos[1],cursorPos[2],cursorPos[3]); + if (mFirstSetSliceOrientation) { + int *range = this->GetSliceRange(); + if (range) + this->Slice = static_cast((range[0] + range[1]) * 0.5); +#if VTK_MAJOR_VERSION <= 5 + mFirstSetSliceOrientation = false; +#endif + } + else if (this->Renderer && this->GetInput()) { + double s = mCursor[orientation]; + double sCursor = (s - this->GetInput()->GetOrigin()[orientation])/this->GetInput()->GetSpacing()[orientation]; + this->Slice = static_cast(sCursor); + } + this->UpdateOrientation(); + this->UpdateDisplayExtent(); - + + if (mFirstSetSliceOrientation) { + mFirstSetSliceOrientation = false; + } + if (this->Renderer && this->GetInput()) { double scale = this->Renderer->GetActiveCamera()->GetParallelScale(); this->Renderer->ResetCamera(); @@ -690,14 +1006,70 @@ void vvSlicer::SetSliceOrientation(int orientation) } //---------------------------------------------------------------------------- +//------------------------------------------------------------------------------ +// This function ensures that we sample the slices of a vtkImageReslice filter +// in the direction of the slicer (SliceOrientation) similarly as mImageReslice. +// In other words, we change the grid of the reslice in the same way as the grid +// of the displayed image in the slicing direction. +void vvSlicer::AdjustResliceToSliceOrientation(vtkImageReslice *reslice) +{ + // Reset autocrop and update output information + reslice->SetOutputOriginToDefault(); + reslice->SetOutputSpacingToDefault(); +#if VTK_MAJOR_VERSION <= 5 + reslice->GetOutput()->UpdateInformation(); +#else + reslice->UpdateInformation(); +#endif + + // Ge new origin / spacing + double origin[3]; + double spacing[3]; + reslice->GetOutput()->GetOrigin(origin); + reslice->GetOutput()->GetSpacing(spacing); + + // Use similar spacing as the image in the direction SliceOrientation + spacing[this->SliceOrientation] = mImageReslice->GetOutput()->GetSpacing()[this->SliceOrientation]; + + // Modify origin to be on the image grid in the direction SliceOrientation in 3 steps + // Step 1: from world coordinates to image coordinates + origin[this->SliceOrientation] -= mImageReslice->GetOutput()->GetOrigin()[this->SliceOrientation]; + origin[this->SliceOrientation] /= mImageReslice->GetOutput()->GetSpacing()[this->SliceOrientation]; + + // Step 2: round to nearest grid positionInc. This has been validated as the only + // way to have something consistent with the thickness of a 2D slice visible on the + // other slices. The thickness is accounted for so if the 2D slice is to thin and + // between two slices, one will never be able to see this 2D slice (bug #1883). + origin[this->SliceOrientation] = itk::Math::Round(origin[this->SliceOrientation]); + + // Step 3: back to world coordinates + origin[this->SliceOrientation] *= mImageReslice->GetOutput()->GetSpacing()[this->SliceOrientation]; + origin[this->SliceOrientation] += mImageReslice->GetOutput()->GetOrigin()[this->SliceOrientation]; + + // Set new spacing and origin + reslice->SetOutputOrigin(origin); + reslice->SetOutputSpacing(spacing); + reslice->UpdateInformation(); +#if VTK_MAJOR_VERSION <= 5 + reslice->GetOutput()->UpdateInformation(); +#endif +} +//------------------------------------------------------------------------------ //---------------------------------------------------------------------------- int * vvSlicer::GetExtent() -{ +{ int *w_ext; if (mUseReducedExtent) { w_ext = mReducedExtent; - } else w_ext = GetInput()->GetWholeExtent(); + } + else { +#if VTK_MAJOR_VERSION <= 5 + w_ext = GetInput()->GetWholeExtent(); +#else + w_ext = mImageReslice->GetInputInformation()->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); +#endif + } return w_ext; } //---------------------------------------------------------------------------- @@ -705,7 +1077,7 @@ int * vvSlicer::GetExtent() //---------------------------------------------------------------------------- int vvSlicer::GetOrientation() -{ +{ return this->SliceOrientation; } //---------------------------------------------------------------------------- @@ -713,181 +1085,148 @@ int vvSlicer::GetOrientation() //---------------------------------------------------------------------------- void vvSlicer::UpdateDisplayExtent() -{ +{ + emit UpdateDisplayExtentBegin(mSlicerNumber); vtkImageData *input = this->GetInput(); if (!input || !this->ImageActor) { return; } - input->UpdateInformation(); - int *w_ext;// = input->GetWholeExtent(); +#if VTK_MAJOR_VERSION <= 5 + input->UpdateInformation(); +#else + mRegisterExtent = mImageReslice->GetOutputInformation(0)->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); +#endif + this->SetSlice( this->GetSlice() ); //SR: make sure the update let the slice in extents + + // Local copy of extent + int w_ext[6]; +#if VTK_MAJOR_VERSION <= 5 + int* ext = GetExtent(); +#else + int* ext = mImageReslice->GetOutputInformation(0)->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); +#endif + copyExtent(ext, w_ext); if (mUseReducedExtent) { - w_ext = mReducedExtent; - } else w_ext = input->GetWholeExtent(); - - switch (this->SliceOrientation) { - case vtkImageViewer2::SLICE_ORIENTATION_XY: - this->ImageActor->SetDisplayExtent( - w_ext[0], w_ext[1], w_ext[2], w_ext[3], this->Slice, this->Slice); - if (mVF && mVFActor->GetVisibility()) { - int vfExtent[6]; - ComputeVFDisplayedExtent(w_ext[0], w_ext[1], w_ext[2], w_ext[3], this->Slice, this->Slice,vfExtent); - mVOIFilter->SetVOI(vfExtent); - mGlyphFilter->SetOrientation(1,1,0); - mVFMapper->Update(); - // put the vector field between the image and the camera - if (Renderer->GetActiveCamera()->GetPosition()[2] > this->Slice) - mVFActor->SetPosition(0,0,ImageActor->GetBounds()[5]+2); - else - mVFActor->SetPosition(0,0,ImageActor->GetBounds()[4]-2); - } - if (mOverlay && mOverlayActor->GetVisibility()) { - int overExtent[6]; - ComputeOverlayDisplayedExtent(w_ext[0], w_ext[1], w_ext[2], w_ext[3], this->Slice, this->Slice,overExtent); - mOverlayActor->SetDisplayExtent(overExtent); - if (Renderer->GetActiveCamera()->GetPosition()[2] > this->Slice) - mOverlayActor->SetPosition(0,0,1); - else - mOverlayActor->SetPosition(0,0,-1); - } - if (mFusion && mFusionActor->GetVisibility()) { - int fusExtent[6]; - ComputeFusionDisplayedExtent(w_ext[0], w_ext[1], w_ext[2], w_ext[3], this->Slice, this->Slice,fusExtent); - mFusionActor->SetDisplayExtent(fusExtent); - if (Renderer->GetActiveCamera()->GetPosition()[2] > this->Slice) - mFusionActor->SetPosition(0,0,1.5); - else - mFusionActor->SetPosition(0,0,-1.5); - } - if (mLandActor) { - if (mClipBox) { - double bounds [6]; - bounds[0] = ImageActor->GetBounds()[0]; - bounds[1] = ImageActor->GetBounds()[1]; - bounds[2] = ImageActor->GetBounds()[2]; - bounds[3] = ImageActor->GetBounds()[3]; - bounds[4] = ImageActor->GetBounds()[4]-fabs(0.5/this->GetInput()->GetSpacing()[2]); - bounds[5] = ImageActor->GetBounds()[5]+fabs(0.5/this->GetInput()->GetSpacing()[2]); - mClipBox->SetBounds(bounds); - UpdateLandmarks(); - } - mLandActor->SetPosition(0,0,-1.5); - /* - if (Renderer->GetActiveCamera()->GetPosition()[2] > this->Slice) - mLandActor->SetPosition(0,0,1.5); - else - mLandActor->SetPosition(0,0,-1.5); - */ - } - break; - - case vtkImageViewer2::SLICE_ORIENTATION_XZ: - this->ImageActor->SetDisplayExtent( - w_ext[0], w_ext[1], this->Slice, this->Slice, w_ext[4], w_ext[5]); - if (mVF && mVFActor->GetVisibility()) { - int vfExtent[6]; - ComputeVFDisplayedExtent(w_ext[0], w_ext[1], this->Slice, this->Slice, w_ext[4], w_ext[5],vfExtent); - mVOIFilter->SetVOI(vfExtent); - mGlyphFilter->SetOrientation(1,0,1); - mVFMapper->Update(); - // put the vector field between the image aSpacingnd the camera - if (Renderer->GetActiveCamera()->GetPosition()[1] > this->Slice) - mVFActor->SetPosition(0,ImageActor->GetBounds()[3]+2,0); - else - mVFActor->SetPosition(0,ImageActor->GetBounds()[2]-2,0); - } - if (mOverlay && mOverlayActor->GetVisibility()) { - int overExtent[6]; - ComputeOverlayDisplayedExtent(w_ext[0], w_ext[1], this->Slice, this->Slice, w_ext[4], w_ext[5],overExtent); - mOverlayActor->SetDisplayExtent(overExtent); - if (Renderer->GetActiveCamera()->GetPosition()[1] > this->Slice) - mOverlayActor->SetPosition(0,1,0); - else - mOverlayActor->SetPosition(0,-1,0); - } - if (mFusion && mFusionActor->GetVisibility()) { - int fusExtent[6]; - ComputeFusionDisplayedExtent(w_ext[0], w_ext[1], this->Slice, this->Slice, w_ext[4], w_ext[5],fusExtent); - mFusionActor->SetDisplayExtent(fusExtent); - if (Renderer->GetActiveCamera()->GetPosition()[1] > this->Slice) - mFusionActor->SetPosition(0,1.5,0); - else - mFusionActor->SetPosition(0,-1.5,0); - } - if (mLandActor) { - if (mClipBox) { - double bounds [6]; - bounds[0] = ImageActor->GetBounds()[0]; - bounds[1] = ImageActor->GetBounds()[1]; - bounds[2] = ImageActor->GetBounds()[2]-fabs(0.5/this->GetInput()->GetSpacing()[1]); - bounds[3] = ImageActor->GetBounds()[3]+fabs(0.5/this->GetInput()->GetSpacing()[1]); - bounds[4] = ImageActor->GetBounds()[4]; - bounds[5] = ImageActor->GetBounds()[5]; - mClipBox->SetBounds(bounds); - UpdateLandmarks(); - } - if (Renderer->GetActiveCamera()->GetPosition()[1] > this->Slice) - mLandActor->SetPosition(0,1.5,0); - else - mLandActor->SetPosition(0,-1.5,0); - } - break; - - case vtkImageViewer2::SLICE_ORIENTATION_YZ: - this->ImageActor->SetDisplayExtent( - this->Slice, this->Slice, w_ext[2], w_ext[3], w_ext[4], w_ext[5]); - if (mVF && mVFActor->GetVisibility()) { - int vfExtent[6]; - ComputeVFDisplayedExtent(this->Slice, this->Slice, w_ext[2], w_ext[3], w_ext[4], w_ext[5],vfExtent); - mVOIFilter->SetVOI(vfExtent); - mGlyphFilter->SetOrientation(0,1,1); - mVFMapper->Update(); - // put the vector field between the image and the camera - if (Renderer->GetActiveCamera()->GetPosition()[0] > this->Slice) - mVFActor->SetPosition(ImageActor->GetBounds()[1]+2,0,0); - else - mVFActor->SetPosition(ImageActor->GetBounds()[0]-2,0,0); - } - if (mOverlay && mOverlayActor->GetVisibility()) { - int overExtent[6]; - ComputeOverlayDisplayedExtent(this->Slice, this->Slice, w_ext[2], w_ext[3], w_ext[4], w_ext[5],overExtent); - mOverlayActor->SetDisplayExtent(overExtent); - if (Renderer->GetActiveCamera()->GetPosition()[0] > this->Slice) - mOverlayActor->SetPosition(1,0,0); - else - mOverlayActor->SetPosition(-1,0,0); - } - if (mFusion && mFusionActor->GetVisibility()) { - int fusExtent[6]; - ComputeFusionDisplayedExtent(this->Slice, this->Slice, w_ext[2], w_ext[3], w_ext[4], w_ext[5],fusExtent); - mFusionActor->SetDisplayExtent(fusExtent); - if (Renderer->GetActiveCamera()->GetPosition()[0] > this->Slice) - mFusionActor->SetPosition(1.5,0,0); - else - mFusionActor->SetPosition(-1.5,0,0); + copyExtent(mReducedExtent, w_ext); } - if (mLandActor) { - if (mClipBox) { - double bounds [6]; - bounds[0] = ImageActor->GetBounds()[0]-fabs(0.5/this->GetInput()->GetSpacing()[0]); - bounds[1] = ImageActor->GetBounds()[1]+fabs(0.5/this->GetInput()->GetSpacing()[0]); - bounds[2] = ImageActor->GetBounds()[2]; - bounds[3] = ImageActor->GetBounds()[3]; - bounds[4] = ImageActor->GetBounds()[4]; - bounds[5] = ImageActor->GetBounds()[5]; - mClipBox->SetBounds(bounds); - UpdateLandmarks(); - } - if (Renderer->GetActiveCamera()->GetPosition()[0] > this->Slice) - mLandActor->SetPosition(1.5,0,0); - else - mLandActor->SetPosition(-1.5,0,0); + // Set slice value + + w_ext[ this->SliceOrientation*2 ] = this->Slice; + w_ext[ this->SliceOrientation*2+1 ] = this->Slice; + + // Image actor + this->ImageActor->SetVisibility(mImageVisibility); + this->ImageActor->SetDisplayExtent(w_ext); + +#if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION >= 10) + // Fix for bug #1882 + dynamic_cast(this->ImageActor->GetMapper())->SetOrientation(this->GetOrientation()); +#endif + + // Overlay image actor + if (mOverlay && mOverlayVisibility) { + AdjustResliceToSliceOrientation(mOverlayReslice); + int overExtent[6]; +#if VTK_MAJOR_VERSION <= 5 + this->ConvertImageToImageDisplayExtent(input, w_ext, mOverlayReslice->GetOutput(), overExtent); + bool out = ClipDisplayedExtent(overExtent, mOverlayMapper->GetInput()->GetWholeExtent()); +#else + this->ConvertImageToImageDisplayExtent(mImageReslice->GetOutputInformation(0), w_ext, mOverlayReslice->GetOutput(), overExtent); + bool out = ClipDisplayedExtent(overExtent, mOverlayMapper->GetInputInformation()->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT())); +#endif + mOverlayActor->SetVisibility(!out); + mOverlayActor->SetDisplayExtent( overExtent ); +#if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION >= 10) + // Fix for bug #1882 + dynamic_cast(mOverlayActor->GetMapper())->SetOrientation(this->GetOrientation()); +#endif + } + else if(mOverlay) + mOverlayActor->SetVisibility(false); + + // Fusion image actor + if (mFusion && mFusionVisibility) { + AdjustResliceToSliceOrientation(mFusionReslice); + int fusExtent[6]; +#if VTK_MAJOR_VERSION <= 5 + this->ConvertImageToImageDisplayExtent(input, w_ext, mFusionReslice->GetOutput(), fusExtent); + bool out = ClipDisplayedExtent(fusExtent, mFusionMapper->GetInput()->GetWholeExtent()); +#else + this->ConvertImageToImageDisplayExtent(mImageReslice->GetOutputInformation(0), w_ext, mFusionReslice->GetOutput(), fusExtent); + bool out = ClipDisplayedExtent(fusExtent, mFusionMapper->GetInputInformation()->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT())); +#endif + mFusionActor->SetVisibility(!out); + mFusionActor->SetDisplayExtent( fusExtent ); +#if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION >= 10) + // Fix for bug #1882 + dynamic_cast(mFusionActor->GetMapper())->SetOrientation(this->GetOrientation()); +#endif + } + else if(mFusion) + mFusionActor->SetVisibility(false); + // Vector field actor + double* camera = Renderer->GetActiveCamera()->GetPosition(); + double* image_bounds = ImageActor->GetBounds(); + double position[3] = {0, 0, 0}; + position[this->SliceOrientation] = image_bounds[this->SliceOrientation*2]; + + //print_vector("camera", camera); + //print_vector("image_bounds", image_bounds); + //print_vector("position", position); + + // find where to place the VF actor. to deal with + // z-buffer issues, the VF is placed right in front of the image, + // subject to a small offset. the position actually depends on the + // the location of the camera relative to the image. + double offset = 1; + if (camera[this->SliceOrientation] < image_bounds[this->SliceOrientation*2]) + offset = -1; + + if (mVF && mVFVisibility) { + int vfExtent[6]; +#if VTK_MAJOR_VERSION <= 5 + mVF->GetVTKImages()[0]->UpdateInformation(); + this->ConvertImageToImageDisplayExtent(input, w_ext, mVF->GetVTKImages()[0], vfExtent); + bool out = ClipDisplayedExtent(vfExtent, mVOIFilter->GetInput()->GetWholeExtent()); +#else + mVOIFilter->Update(); + this->ConvertImageToImageDisplayExtent(mImageReslice->GetOutputInformation(0), w_ext, mVF->GetVTKImages()[0], vfExtent); + bool out = ClipDisplayedExtent(vfExtent, mVOIFilter->GetInputInformation()->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT())); +#endif + mVFActor->SetVisibility(!out); + mVOIFilter->SetVOI(vfExtent); + int orientation[3] = {1,1,1}; + orientation[this->SliceOrientation] = 0; + mGlyphFilter->SetOrientation(orientation[0], orientation[1], orientation[2]); + position[this->SliceOrientation] += offset; + mVFActor->SetPosition(position); + mVFActor->GetProperty()->SetOpacity(0.995); //in order to get VTK to turn on the alpha-blending in OpenGL + mVFMapper->Update(); + + } + else if(mVF) + mVFActor->SetVisibility(false); + + + double boundsT [6]; + for(unsigned int i=0; i<6; i++) + boundsT[i] = ImageActor->GetBounds()[i]; + boundsT[ this->SliceOrientation*2 ] = ImageActor->GetBounds()[ this->SliceOrientation*2 ]-fabs(this->GetInput()->GetSpacing()[this->SliceOrientation]); + boundsT[ this->SliceOrientation*2+1 ] = ImageActor->GetBounds()[ this->SliceOrientation*2+1 ]+fabs(this->GetInput()->GetSpacing()[this->SliceOrientation]); + + + // Landmarks actor + if (mLandActor) { + if (mClipBox) { + RemoveLandmarks(); } - break; + + position[this->SliceOrientation] = offset; + mLandActor->SetPosition(position); } // Figure out the correct clipping range - if (this->Renderer) { if (this->InteractorStyle && this->InteractorStyle->GetAutoAdjustCameraClippingRange()) { @@ -901,96 +1240,76 @@ void vvSlicer::UpdateDisplayExtent() double cpos = (double)cam->GetPosition()[this->SliceOrientation]; double range = fabs(spos - cpos); double *spacing = input->GetSpacing(); - double avg_spacing = - ((double)spacing[0] + (double)spacing[1] + (double)spacing[2]) / 3.0; - cam->SetClippingRange( - range - avg_spacing * 3.0, range + avg_spacing * 3.0); + double sumSpacing = spacing[0] + spacing[1] + spacing[2]; + cam->SetClippingRange(range - sumSpacing, range + sumSpacing); } } + + if (mLandActor) { + if (mClipBox) { + DisplayLandmarks(); + } + } } + emit UpdateDisplayExtentEnd(mSlicerNumber); } //---------------------------------------------------------------------------- - -//---------------------------------------------------------------------------- -void vvSlicer::ComputeVFDisplayedExtent(int x1,int x2,int y1,int y2,int z1,int z2,int vfExtent[6]) -{ - double dVfExtent[6]; - vtkImageData* image = this->GetInput(); - dVfExtent[0] = image->GetOrigin()[0] + x1*image->GetSpacing()[0]; - dVfExtent[1] = image->GetOrigin()[0] + x2*image->GetSpacing()[0]; - dVfExtent[2] = image->GetOrigin()[1] + y1*image->GetSpacing()[1]; - dVfExtent[3] = image->GetOrigin()[1] + y2*image->GetSpacing()[1]; - dVfExtent[4] = image->GetOrigin()[2] + z1*image->GetSpacing()[2]; - dVfExtent[5] = image->GetOrigin()[2] + z2*image->GetSpacing()[2]; - - vtkImageData* vf = mVF->GetTransformedVTKImages()[0]; - vf->UpdateInformation(); - for(unsigned int i=0; i<6; i++) - vfExtent[i] = itk::Math::Round((dVfExtent[i]- vf->GetOrigin()[i/2]) / vf->GetSpacing()[i/2]); - - ClipDisplayedExtent(vfExtent,mVOIFilter->GetInput()->GetWholeExtent()); -} //---------------------------------------------------------------------------- - - -//---------------------------------------------------------------------------- -void vvSlicer::ComputeOverlayDisplayedExtent(int x1,int x2,int y1,int y2,int z1,int z2,int overExtent[6]) -{ - double dOverExtent[6]; - vtkImageData* image = this->GetInput(); - dOverExtent[0] = image->GetOrigin()[0] + x1*image->GetSpacing()[0]; - dOverExtent[1] = image->GetOrigin()[0] + x2*image->GetSpacing()[0]; - dOverExtent[2] = image->GetOrigin()[1] + y1*image->GetSpacing()[1]; - dOverExtent[3] = image->GetOrigin()[1] + y2*image->GetSpacing()[1]; - dOverExtent[4] = image->GetOrigin()[2] + z1*image->GetSpacing()[2]; - dOverExtent[5] = image->GetOrigin()[2] + z2*image->GetSpacing()[2]; - - vtkImageData* overlay = mOverlay->GetTransformedVTKImages()[0]; - overlay->UpdateInformation(); - for(unsigned int i=0; i<6; i++) - overExtent[i] = itk::Math::Round((dOverExtent[i]- overlay->GetOrigin()[i/2]) / overlay->GetSpacing()[i/2]); - - ClipDisplayedExtent(overExtent, mOverlayMapper->GetInput()->GetWholeExtent()); +void vvSlicer::ConvertImageToImageDisplayExtent(vtkInformation *sourceImage, const int sourceExtent[6], + vtkImageData *targetImage, int targetExtent[6]) +{ + double dExtents[6]; + double *origin, *spacing; + origin = sourceImage->Get(vtkDataObject::ORIGIN()); + spacing = sourceImage->Get(vtkDataObject::SPACING()); + for(unsigned int i=0; i<6; i++) { + // From source voxel coordinates to world coordinates + dExtents[i] = origin[i/2] + spacing[i/2] * sourceExtent[i]; + + // From world coordinates to floating point target voxel coordinates + dExtents[i] = (dExtents[i]- targetImage->GetOrigin()[i/2]) / targetImage->GetSpacing()[i/2]; + + // Round to current slice or larger extent + if(i/2==this->GetOrientation()) + targetExtent[i] = itk::Math::Round(dExtents[i]); + else if(i%2==1) + targetExtent[i] = itk::Math::Ceil(dExtents[i]); + else + targetExtent[i] = itk::Math::Floor(dExtents[i]); + } } //---------------------------------------------------------------------------- - //---------------------------------------------------------------------------- -void vvSlicer::ComputeFusionDisplayedExtent(int x1,int x2,int y1,int y2,int z1,int z2,int fusExtent[6]) +void vvSlicer::ConvertImageToImageDisplayExtent(vtkImageData *sourceImage, const int sourceExtent[6], + vtkImageData *targetImage, int targetExtent[6]) { - double dFusExtent[6]; - vtkImageData* image = this->GetInput(); - dFusExtent[0] = image->GetOrigin()[0] + x1*image->GetSpacing()[0]; - dFusExtent[1] = image->GetOrigin()[0] + x2*image->GetSpacing()[0]; - dFusExtent[2] = image->GetOrigin()[1] + y1*image->GetSpacing()[1]; - dFusExtent[3] = image->GetOrigin()[1] + y2*image->GetSpacing()[1]; - dFusExtent[4] = image->GetOrigin()[2] + z1*image->GetSpacing()[2]; - dFusExtent[5] = image->GetOrigin()[2] + z2*image->GetSpacing()[2]; - - vtkImageData* fusion = mFusion->GetTransformedVTKImages()[0]; - fusion->UpdateInformation(); - for(unsigned int i=0; i<6; i++) - fusExtent[i] = itk::Math::Round((dFusExtent[i]- fusion->GetOrigin()[i/2]) / fusion->GetSpacing()[i/2]); - - ClipDisplayedExtent(fusExtent, mFusionMapper->GetInput()->GetWholeExtent()); + double dExtents[6]; + for(unsigned int i=0; i<6; i++) { + // From source voxel coordinates to world coordinates + dExtents[i] = sourceImage->GetOrigin()[i/2] + sourceImage->GetSpacing()[i/2] * sourceExtent[i]; + + // From world coordinates to floating point target voxel coordinates + dExtents[i] = (dExtents[i]- targetImage->GetOrigin()[i/2]) / targetImage->GetSpacing()[i/2]; + + // Round to current slice or larger extent + if(i/2==this->GetOrientation()) + targetExtent[i] = itk::Math::Round(dExtents[i]); + else if(i%2==1) + targetExtent[i] = itk::Math::Ceil(dExtents[i]); + else + targetExtent[i] = itk::Math::Floor(dExtents[i]); + } } //---------------------------------------------------------------------------- - //---------------------------------------------------------------------------- -void vvSlicer::ClipDisplayedExtent(int extent[6], int refExtent[6]) -{ +bool vvSlicer::ClipDisplayedExtent(int extent[6], int refExtent[6]) +{ bool out = false; int maxBound = 6; - //2D overlay on 3D image specific case - if (refExtent[4] == refExtent[5]) { - maxBound = 4; - extent[4] = refExtent[4]; - extent[5] = refExtent[5]; - } - for (int i = 0; i < maxBound; i = i+2) { //if we are totally outside the image if ( extent[i] > refExtent[i+1] || extent[i+1] < refExtent[i] ) { @@ -998,23 +1317,24 @@ void vvSlicer::ClipDisplayedExtent(int extent[6], int refExtent[6]) break; } //crop to the limit of the image - extent[i] = (extent[i] > refExtent[i]) ? extent[i] : refExtent[i]; - extent[i] = (extent[i] < refExtent[i+1]) ? extent[i] : refExtent[i+1]; - extent[i+1] = (extent[i+1] > refExtent[i]) ? extent[i+1] : refExtent[i]; - extent[i+1] = (extent[i+1] < refExtent[i+1]) ? extent[i+1] : refExtent[i+1]; + extent[i] = std::max(extent[i], refExtent[i]); + extent[i] = std::min(extent[i], refExtent[i+1]);; + extent[i+1] = std::max(extent[i+1], refExtent[i]); + extent[i+1] = std::min(extent[i+1], refExtent[i+1]);; } if (out) for (int i = 0; i < maxBound; i = i+2) { extent[i] = refExtent[i]; extent[i+1] = refExtent[i]; } + return out; } //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- void vvSlicer::UpdateOrientation() -{ +{ // Set the camera position vtkCamera *cam = this->Renderer ? this->Renderer->GetActiveCamera() : NULL; if (cam) { @@ -1044,7 +1364,7 @@ void vvSlicer::UpdateOrientation() //---------------------------------------------------------------------------- void vvSlicer::SetOpacity(double s) -{ +{ this->GetImageActor()->SetOpacity(s); } //---------------------------------------------------------------------------- @@ -1052,12 +1372,11 @@ void vvSlicer::SetOpacity(double s) //---------------------------------------------------------------------------- void vvSlicer::SetRenderWindow(int orientation, vtkRenderWindow * rw) -{ +{ this->Superclass::SetRenderWindow(rw); this->SetupInteractor(rw->GetInteractor()); ca->SetImageActor(this->GetImageActor()); ca->SetWindowLevel(this->GetWindowLevel()); - ca->SetText(2, ""); ca->SetText(3, "\n"); double bounds[6]; @@ -1069,8 +1388,8 @@ void vvSlicer::SetRenderWindow(int orientation, vtkRenderWindow * rw) bounds[3] = max; bounds[4] = -max; bounds[5] = max; - crossCursor->SetModelBounds(bounds); + this->GetRenderer()->AddActor(pdmA); this->GetRenderer()->AddActor(ca); this->GetRenderer()->ResetCamera(); @@ -1085,7 +1404,7 @@ void vvSlicer::SetRenderWindow(int orientation, vtkRenderWindow * rw) //---------------------------------------------------------------------------- void vvSlicer::ResetCamera() -{ +{ this->GetRenderer()->ResetCamera(); } //---------------------------------------------------------------------------- @@ -1093,26 +1412,24 @@ void vvSlicer::ResetCamera() //---------------------------------------------------------------------------- void vvSlicer::SetDisplayMode(bool i) -{ - this->GetImageActor()->SetVisibility(i); - this->GetAnnotation()->SetVisibility(i); - this->GetRenderer()->SetDraw(i); - if (mLandActor) - mLandActor->SetVisibility(i); - pdmA->SetVisibility(i); - if (i) - UpdateDisplayExtent(); +{ + this->GetRenderer()->SetDraw(i); + if (i) UpdateDisplayExtent(); } //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- void vvSlicer::FlipHorizontalView() -{ +{ vtkCamera *cam = this->Renderer ? this->Renderer->GetActiveCamera() : NULL; if (cam) { double *position = cam->GetPosition(); - switch (this->SliceOrientation) { + double factor[3] = {1, 1, 1}; + factor[this->SliceOrientation] = -1; + cam->SetPosition(factor[0]*position[0],factor[1]*position[1],factor[2]*position[2]); + +/* switch (this->SliceOrientation) { case vtkImageViewer2::SLICE_ORIENTATION_XY: cam->SetPosition(position[0],position[1],-position[2]); break; @@ -1124,7 +1441,8 @@ void vvSlicer::FlipHorizontalView() case vtkImageViewer2::SLICE_ORIENTATION_YZ: cam->SetPosition(-position[0],position[1],position[2]); break; - } + }*/ + this->Renderer->ResetCameraClippingRange(); this->UpdateDisplayExtent(); } @@ -1134,7 +1452,7 @@ void vvSlicer::FlipHorizontalView() //---------------------------------------------------------------------------- void vvSlicer::FlipVerticalView() -{ +{ vtkCamera *cam = this->Renderer ? this->Renderer->GetActiveCamera() : NULL; if (cam) { FlipHorizontalView(); @@ -1148,25 +1466,24 @@ void vvSlicer::FlipVerticalView() //---------------------------------------------------------------------------- void vvSlicer::SetColorWindow(double window) -{ +{ vtkLookupTable* LUT = static_cast(this->GetWindowLevel()->GetLookupTable()); if ( LUT ) { double level = this->GetWindowLevel()->GetLevel(); - LUT->SetTableRange(level-fabs(window)/4,level+fabs(window)/4); + LUT->SetTableRange(level-fabs(window)/2,level+fabs(window)/2); LUT->Build(); } this->vtkImageViewer2::SetColorWindow(window); } //---------------------------------------------------------------------------- - //---------------------------------------------------------------------------- void vvSlicer::SetColorLevel(double level) -{ +{ vtkLookupTable* LUT = static_cast(this->GetWindowLevel()->GetLookupTable()); if ( LUT ) { double window = this->GetWindowLevel()->GetWindow(); - LUT->SetTableRange(level-fabs(window)/4,level+fabs(window)/4); + LUT->SetTableRange(level-fabs(window)/2,level+fabs(window)/2); LUT->Build(); } this->vtkImageViewer2::SetColorLevel(level); @@ -1174,41 +1491,97 @@ void vvSlicer::SetColorLevel(double level) //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- -// Returns the min an the max value in a 41x41 region around the mouse pointer -void vvSlicer::GetExtremasAroundMousePointer(double & min, double & max) -{ +double vvSlicer::GetOverlayColorWindow() +{ + if(mOverlayMapper) + return mOverlayMapper->GetWindow(); + else + return 0.; +} +//---------------------------------------------------------------------------- + +//---------------------------------------------------------------------------- +double vvSlicer::GetOverlayColorLevel() +{ + if(mOverlayMapper) + return mOverlayMapper->GetLevel(); + else + return 0.; +} +//---------------------------------------------------------------------------- + +//---------------------------------------------------------------------------- +void vvSlicer::SetOverlayColorWindow(double window) +{ + if(mOverlayMapper) + mOverlayMapper->SetWindow(window); +} +//---------------------------------------------------------------------------- + +//---------------------------------------------------------------------------- +void vvSlicer::SetOverlayColorLevel(double level) +{ + if(mOverlayMapper) + mOverlayMapper->SetLevel(level); +} +//---------------------------------------------------------------------------- + +//---------------------------------------------------------------------------- +// Returns the min an the max value in a 20%x20% region around the mouse pointer +void vvSlicer::GetExtremasAroundMousePointer(double & min, double & max, vtkImageData *image, vtkTransform *transform) +{ //Get mouse pointer position in view coordinates - double fLocalExtents[6]; - for(int i=0; i<3; i++) { - fLocalExtents[i*2 ] = mCurrent[i]; - fLocalExtents[i*2+1] = mCurrent[i]; - } - this->Renderer->WorldToView(fLocalExtents[0], fLocalExtents[2], fLocalExtents[4]); - this->Renderer->WorldToView(fLocalExtents[1], fLocalExtents[3], fLocalExtents[5]); + double corner1[3]; + double corner2[3]; for(int i=0; i<3; i++) { - if (i!=SliceOrientation) { //SR: assumes that SliceOrientation is valid in ViewCoordinates (???) - fLocalExtents[i*2 ] -= 0.2; - fLocalExtents[i*2+1] += 0.2; - } + corner1[i] = mCurrent[i]; + corner2[i] = mCurrent[i]; } - this->Renderer->ViewToWorld(fLocalExtents[0], fLocalExtents[2], fLocalExtents[4]); - this->Renderer->ViewToWorld(fLocalExtents[1], fLocalExtents[3], fLocalExtents[5]); + + this->Renderer->WorldToView(corner1[0], corner1[1], corner1[2]); + this->Renderer->WorldToView(corner2[0], corner2[1], corner2[2]); + + // In view coordinates, x is the slicer width and y is the slicer height are the in-plane axis + int w, h; + this->Renderer->GetTiledSize(&w, &h); + corner1[0] -= 0.2*h/(double)w; + corner2[0] += 0.2*h/(double)w; + corner1[1] -= 0.2; + corner2[1] += 0.2; + this->Renderer->ViewToWorld(corner1[0], corner1[1], corner1[2]); + this->Renderer->ViewToWorld(corner2[0], corner2[1], corner2[2]); //Convert to image pixel coordinates (rounded) + transform->TransformPoint(corner1, corner1); + transform->TransformPoint(corner2, corner2); int iLocalExtents[6]; for(int i=0; i<3; i++) { - fLocalExtents[i*2 ] = (fLocalExtents[i*2 ] - this->GetInput()->GetOrigin()[i])/this->GetInput()->GetSpacing()[i]; - fLocalExtents[i*2+1] = (fLocalExtents[i*2+1] - this->GetInput()->GetOrigin()[i])/this->GetInput()->GetSpacing()[i]; + corner1[i] = (corner1[i] - image->GetOrigin()[i])/image->GetSpacing()[i]; + corner2[i] = (corner2[i] - image->GetOrigin()[i])/image->GetSpacing()[i]; - iLocalExtents[i*2 ] = lrint(fLocalExtents[i*2 ]); - iLocalExtents[i*2+1] = lrint(fLocalExtents[i*2+1]); + iLocalExtents[i*2 ] = lrint(corner1[i]); + iLocalExtents[i*2+1] = lrint(corner2[i]); if(iLocalExtents[i*2 ]>iLocalExtents[i*2+1]) std::swap(iLocalExtents[i*2], iLocalExtents[i*2+1]); + +#if VTK_MAJOR_VERSION > 5 + for(int j=0;j<2; j++) { + if(iLocalExtents[i*2+j]< mImageReslice->GetInputInformation()->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT())[2*i]) + iLocalExtents[i*2+j] = mImageReslice->GetInputInformation()->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT())[2*i]; + + if(iLocalExtents[i*2+j]> mImageReslice->GetInputInformation()->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT())[2*i+1]) + iLocalExtents[i*2+j] = mImageReslice->GetInputInformation()->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT())[2*i+1]; + } +#endif } vtkSmartPointer voiFilter = vtkSmartPointer::New(); - voiFilter->SetInput(this->GetInput()); +#if VTK_MAJOR_VERSION <= 5 + voiFilter->SetInput(image); +#else + voiFilter->SetInputData(image); +#endif voiFilter->SetVOI(iLocalExtents); voiFilter->Update(); if (!voiFilter->GetOutput()->GetNumberOfPoints()) { @@ -1218,7 +1591,11 @@ void vvSlicer::GetExtremasAroundMousePointer(double & min, double & max) } vtkSmartPointer accFilter = vtkSmartPointer::New(); +#if VTK_MAJOR_VERSION <= 5 accFilter->SetInput(voiFilter->GetOutput()); +#else + accFilter->SetInputConnection(voiFilter->GetOutputPort(0)); +#endif accFilter->Update(); min = *(accFilter->GetMin()); @@ -1227,71 +1604,117 @@ void vvSlicer::GetExtremasAroundMousePointer(double & min, double & max) //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- -double vvSlicer::GetScalarComponentAsDouble(vtkImageData *image, int X, double Y, double Z, int &ix, int &iy, int &iz, int component) -{ +double vvSlicer::GetScalarComponentAsDouble(vtkImageData *image, double X, double Y, double Z, int &ix, int &iy, int &iz, int component) +{ ix = lrint(X); iy = lrint(Y); iz = lrint(Z); +#if VTK_MAJOR_VERSION <= 5 if (ix < image->GetWholeExtent()[0] || ix > image->GetWholeExtent()[1] || iy < image->GetWholeExtent()[2] || iy > image->GetWholeExtent()[3] || iz < image->GetWholeExtent()[4] || iz > image->GetWholeExtent()[5] ) - return sqrt(-1.); - + return std::numeric_limits::quiet_NaN(); image->SetUpdateExtent(ix, ix, iy, iy, iz, iz); image->Update(); +#else + if (ix < image->GetInformation()->Get(vtkDataObject::DATA_EXTENT())[0] || + ix > image->GetInformation()->Get(vtkDataObject::DATA_EXTENT())[1] || + iy < image->GetInformation()->Get(vtkDataObject::DATA_EXTENT())[2] || + iy > image->GetInformation()->Get(vtkDataObject::DATA_EXTENT())[3] || + iz < image->GetInformation()->Get(vtkDataObject::DATA_EXTENT())[4] || + iz > image->GetInformation()->Get(vtkDataObject::DATA_EXTENT())[5] ) + return std::numeric_limits::quiet_NaN(); + //image->SetUpdateExtent(ix, ix, iy, iy, iz, iz); + //image->Update(); +#endif + return image->GetScalarComponentAsDouble(ix, iy, iz, component); } //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- void vvSlicer::Render() -{ - if (this->GetWindowLevel()->GetLookupTable() && !this->mOverlay && !this->mFusion) { +{ + if (this->mFusion && mFusionActor->GetVisibility() && showFusionLegend) { + legend->SetLookupTable(this->GetFusionMapper()->GetLookupTable()); + legend->UseOpacityOn(); + legend->SetVisibility(1); + } + else if (this->GetWindowLevel()->GetLookupTable() && !this->mOverlay) { legend->SetLookupTable(this->GetWindowLevel()->GetLookupTable()); + legend->UseOpacityOff(); legend->SetVisibility(1); } else legend->SetVisibility(0); if (ca->GetVisibility()) { - std::string worldPos = ""; - std::stringstream world1; - std::stringstream world2; - std::stringstream world3; - world1 << (int)mCurrent[0]; - world2 << (int)mCurrent[1]; - world3 << (int)mCurrent[2]; - double X = (mCurrent[0] - this->GetInput()->GetOrigin()[0])/this->GetInput()->GetSpacing()[0]; - double Y = (mCurrent[1] - this->GetInput()->GetOrigin()[1])/this->GetInput()->GetSpacing()[1]; - double Z = (mCurrent[2] - this->GetInput()->GetOrigin()[2])/this->GetInput()->GetSpacing()[2]; - if (X >= this->GetInput()->GetWholeExtent()[0] && - X <= this->GetInput()->GetWholeExtent()[1] && - Y >= this->GetInput()->GetWholeExtent()[2] && - Y <= this->GetInput()->GetWholeExtent()[3] && - Z >= this->GetInput()->GetWholeExtent()[4] && - Z <= this->GetInput()->GetWholeExtent()[5]) { + + std::stringstream worldPos(" "); + double pt[3]; + mConcatenatedTransform->TransformPoint(mCurrent, pt); + double X = (pt[0] - mImage->GetVTKImages()[mCurrentTSlice]->GetOrigin()[0])/mImage->GetVTKImages()[mCurrentTSlice]->GetSpacing()[0]; + double Y = (pt[1] - mImage->GetVTKImages()[mCurrentTSlice]->GetOrigin()[1])/mImage->GetVTKImages()[mCurrentTSlice]->GetSpacing()[1]; + double Z = (pt[2] - mImage->GetVTKImages()[mCurrentTSlice]->GetOrigin()[2])/mImage->GetVTKImages()[mCurrentTSlice]->GetSpacing()[2]; +#if VTK_MAJOR_VERSION <= 5 + if (X >= mImage->GetVTKImages()[mCurrentTSlice]->GetWholeExtent()[0]-0.5 && + X <= mImage->GetVTKImages()[mCurrentTSlice]->GetWholeExtent()[1]+0.5 && + Y >= mImage->GetVTKImages()[mCurrentTSlice]->GetWholeExtent()[2]-0.5 && + Y <= mImage->GetVTKImages()[mCurrentTSlice]->GetWholeExtent()[3]+0.5 && + Z >= mImage->GetVTKImages()[mCurrentTSlice]->GetWholeExtent()[4]-0.5 && + Z <= mImage->GetVTKImages()[mCurrentTSlice]->GetWholeExtent()[5]+0.5) { + + int ix, iy, iz; - double value = this->GetScalarComponentAsDouble(this->GetInput(), X, Y, Z, ix, iy, iz); - - std::stringstream pixel1; - std::stringstream pixel2; - std::stringstream pixel3; - std::stringstream temps; - pixel1 << ix; - pixel2 << iy; - pixel3 << iz; - temps << mCurrentTSlice; - - std::stringstream val; - val << value; - worldPos += "data value : " + val.str(); - worldPos += "\n mm : " + world1.str() + " " + world2.str() + " " + - world3.str() + " " + temps.str(); - worldPos += "\n pixel : " + pixel1.str() + " " + pixel2.str() + " " + - pixel3.str() + " " + temps.str(); + double value = this->GetScalarComponentAsDouble(mImage->GetVTKImages()[mCurrentTSlice], X, Y, Z, ix, iy, iz); + + if(ImageActor->GetVisibility()) + worldPos << "data value : " << value << std::endl; + + worldPos << "mm : " << lrint(mCurrentBeforeSlicingTransform[0]) << ' ' + << lrint(mCurrentBeforeSlicingTransform[1]) << ' ' + << lrint(mCurrentBeforeSlicingTransform[2]) << ' ' + << mCurrentTSlice + << std::endl; + worldPos << "pixel : " << ix << ' ' + << iy << ' ' + << iz << ' ' + << mCurrentTSlice + << std::endl; } - ca->SetText(1,worldPos.c_str()); +#else + if (X >= mImage->GetVTKImages()[mCurrentTSlice]->GetInformation()->Get(vtkDataObject::DATA_EXTENT())[0]-0.5 && + X <= mImage->GetVTKImages()[mCurrentTSlice]->GetInformation()->Get(vtkDataObject::DATA_EXTENT())[1]+0.5 && + Y >= mImage->GetVTKImages()[mCurrentTSlice]->GetInformation()->Get(vtkDataObject::DATA_EXTENT())[2]-0.5 && + Y <= mImage->GetVTKImages()[mCurrentTSlice]->GetInformation()->Get(vtkDataObject::DATA_EXTENT())[3]+0.5 && + Z >= mImage->GetVTKImages()[mCurrentTSlice]->GetInformation()->Get(vtkDataObject::DATA_EXTENT())[4]-0.5 && + Z <= mImage->GetVTKImages()[mCurrentTSlice]->GetInformation()->Get(vtkDataObject::DATA_EXTENT())[5]+0.5) { + + int ix, iy, iz; + double value = this->GetScalarComponentAsDouble(mImage->GetVTKImages()[mCurrentTSlice], X, Y, Z, ix, iy, iz); + + if(ImageActor->GetVisibility()) + worldPos << "data value : " << value << std::endl; + + worldPos << "mm : " << lrint(mCurrentBeforeSlicingTransform[0]) << ' ' + << lrint(mCurrentBeforeSlicingTransform[1]) << ' ' + << lrint(mCurrentBeforeSlicingTransform[2]) << ' ' + << mCurrentTSlice + << std::endl; + worldPos << "pixel : " << ix << ' ' + << iy << ' ' + << iz << ' ' + << mCurrentTSlice + << std::endl; + + } +#endif + ca->SetText(1,worldPos.str().c_str()); + + std::stringstream slicePos; + slicePos << "Slice: " << this->GetSlice(); + ca->SetText(2, slicePos.str().c_str()); } if (pdmA->GetVisibility()) { @@ -1301,13 +1724,13 @@ void vvSlicer::Render() double xCursor = (x - this->GetInput()->GetOrigin()[0])/this->GetInput()->GetSpacing()[0]; double yCursor = (y - this->GetInput()->GetOrigin()[1])/this->GetInput()->GetSpacing()[1]; double zCursor = (z - this->GetInput()->GetOrigin()[2])/this->GetInput()->GetSpacing()[2]; - - if (xCursor >= this->GetImageActor()->GetDisplayExtent()[0] && - xCursor < this->GetImageActor()->GetDisplayExtent()[1]+1 && - yCursor >= this->GetImageActor()->GetDisplayExtent()[2] && - yCursor < this->GetImageActor()->GetDisplayExtent()[3]+1 && - zCursor >= this->GetImageActor()->GetDisplayExtent()[4] && - zCursor < this->GetImageActor()->GetDisplayExtent()[5]+1 ) { +#if VTK_MAJOR_VERSION <= 5 + if (xCursor >= this->GetImageActor()->GetDisplayExtent()[0]-0.5 && + xCursor < this->GetImageActor()->GetDisplayExtent()[1]+0.5 && + yCursor >= this->GetImageActor()->GetDisplayExtent()[2]-0.5 && + yCursor < this->GetImageActor()->GetDisplayExtent()[3]+0.5 && + zCursor >= this->GetImageActor()->GetDisplayExtent()[4]-0.5 && + zCursor < this->GetImageActor()->GetDisplayExtent()[5]+0.5 ) { vtkRenderer * renderer = this->Renderer; renderer->WorldToView(x,y,z); @@ -1318,50 +1741,136 @@ void vvSlicer::Render() crossCursor->SetFocalPoint(x,y,z); } else crossCursor->SetFocalPoint(-1,-1,z); + crossCursor->Update(); } +#else + vtkSmartPointer mapperOpenGL= vtkSmartPointer::New(); + try { + mapperOpenGL = dynamic_cast(GetImageActor()->GetMapper()); + } catch (const std::bad_cast& e) { + std::cerr << e.what() << std::endl; + std::cerr << "Conversion error" << std::endl; + return; + } + + if (xCursor >= mapperOpenGL->GetCroppingRegion()[0]-0.5 && + xCursor < mapperOpenGL->GetCroppingRegion()[1]+0.5 && + yCursor >= mapperOpenGL->GetCroppingRegion()[2]-0.5 && + yCursor < mapperOpenGL->GetCroppingRegion()[3]+0.5 && + zCursor >= mapperOpenGL->GetCroppingRegion()[4]-0.5 && + zCursor < mapperOpenGL->GetCroppingRegion()[5]+0.5 ) { + vtkRenderer * renderer = this->Renderer; + renderer->WorldToView(x,y,z); + renderer->ViewToNormalizedViewport(x,y,z); + renderer->NormalizedViewportToViewport(x,y); + renderer->ViewportToNormalizedDisplay(x,y); + renderer->NormalizedDisplayToDisplay(x,y); + crossCursor->SetFocalPoint(x,y,z); + } else + crossCursor->SetFocalPoint(-1,-1,z); + crossCursor->Update(); + } +#endif if (mOverlay && mOverlayActor->GetVisibility()) { - mOverlayMapper->SetWindow(this->GetColorWindow()); - mOverlayMapper->SetLevel(this->GetColorLevel()); + if(mLinkOverlayWindowLevel) { + mOverlayMapper->SetWindow(this->GetColorWindow()); + mOverlayMapper->SetLevel(this->GetColorLevel()); + } +#if VTK_MAJOR_VERSION <= 5 mOverlayMapper->GetOutput()->SetUpdateExtent(mOverlayActor->GetDisplayExtent()); - mOverlayMapper->GetOutput()->Update(); +#else + mOverlayMapper->SetUpdateExtent(mOverlayActor->GetDisplayExtent()); +#endif mOverlayMapper->Update(); } - if (mLandMapper) - UpdateLandmarks(); + if (mFusion && mFusionActor->GetVisibility()) { +#if VTK_MAJOR_VERSION <= 5 + mFusionMapper->GetOutput()->SetUpdateExtent(mFusionActor->GetDisplayExtent()); +#else + mFusionMapper->SetUpdateExtent(mFusionActor->GetDisplayExtent()); +#endif + mFusionMapper->Update(); + } + if (mLandMapper) { + RemoveLandmarks(); + DisplayLandmarks(); + } - this->GetRenderWindow()->Render(); + this->GetRenderWindow()->Render(); } //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- void vvSlicer::UpdateCursorPosition() -{ - if (this->GetImageActor()->GetVisibility()) { - pdmA->SetVisibility(true); - mCursor[0] = mCurrent[0]; - mCursor[1] = mCurrent[1]; - mCursor[2] = mCurrent[2]; - mCursor[3] = mCurrentTSlice; - } +{ + pdmA->SetVisibility(true); + mCursor[0] = mCurrent[0]; + mCursor[1] = mCurrent[1]; + mCursor[2] = mCurrent[2]; + mCursor[3] = mCurrentTSlice; } //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- -void vvSlicer::UpdateLandmarks() -{ - vtkPolyData *pd = static_cast(mLandClipper->GetInput()); +void vvSlicer::RemoveLandmarks() +{ + vtkPolyData *pd = static_cast(mLandmarks->GetOutput()); if (pd->GetPoints()) { - mLandGlyph->SetRange(0,1); - mLandGlyph->Modified(); - mLandGlyph->Update(); + //First remove all captions: + for(unsigned int i=0;iRenderer->RemoveActor2D(mLandLabelActors[i]); + //allActors2D->Remove (mLandLabelActors[i]); + } + mLandLabelActors.clear(); + } +} +//---------------------------------------------------------------------------- + + +//---------------------------------------------------------------------------- +void vvSlicer::DisplayLandmarks() +{ + + double bounds [6]; + for(unsigned int i=0; i<6; i++) + bounds[i] = ImageActor->GetBounds()[i]; + bounds[ this->SliceOrientation*2 ] = ImageActor->GetBounds()[ this->SliceOrientation*2 ]-fabs(this->GetInput()->GetSpacing()[this->SliceOrientation]); + bounds[ this->SliceOrientation*2+1 ] = ImageActor->GetBounds()[ this->SliceOrientation*2+1 ]+fabs(this->GetInput()->GetSpacing()[this->SliceOrientation]); + mClipBox->SetBounds(bounds); + + + vtkPolyData *pd = static_cast(mLandmarks->GetOutput()); + if (pd->GetPoints()) { + this->GetRenderer()->AddActor(mLandActor); + //mLandGlyph->SetRange(0,1); + //mLandGlyph->Modified(); + //mLandGlyph->Update(); mClipBox->Modified(); mLandClipper->Update(); mLandMapper->Update(); + //Next add the captions to the displayed points + for (vtkIdType id=0; idGetOutput()->GetNumberOfPoints(); id++) { + double *position = mLandClipper->GetOutput()->GetPoint(id); + vtkStdString label = static_cast(mLandClipper->GetOutput()->GetPointData()->GetAbstractArray("labels"))->GetValue(id); + vtkSmartPointer label_actor = vtkSmartPointer::New(); + label_actor->SetCaption(label); + label_actor->SetAttachmentPoint(position); + label_actor->GetCaptionTextProperty()->SetColor(1,0,0); + label_actor->GetCaptionTextProperty()->SetOrientation(33.333333); + label_actor->GetCaptionTextProperty()->SetFontFamilyToTimes(); + label_actor->GetCaptionTextProperty()->SetBold(0); + label_actor->GetCaptionTextProperty()->SetFontSize(6); + label_actor->BorderOff(); + label_actor->LeaderOff(); + label_actor->ThreeDimensionalLeaderOff(); + mLandLabelActors.push_back(label_actor); + this->Renderer->AddActor2D(mLandLabelActors[id]); + } } } @@ -1370,7 +1879,7 @@ void vvSlicer::UpdateLandmarks() //---------------------------------------------------------------------------- void vvSlicer::SetSlice(int slice) -{ +{ int *range = this->GetSliceRange(); if (range) { if (slice < range[0]) { @@ -1390,26 +1899,38 @@ void vvSlicer::SetSlice(int slice) this->UpdateDisplayExtent(); // Seems to work without this line - // this->Render(); + //this->Render(); } //---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +int vvSlicer::GetTMax() +{ + int tmax = (int)mImage->GetVTKImages().size() - 1; + if(mOverlay) + tmax = std::max(tmax, (int)mOverlay->GetVTKImages().size()-1); + return tmax; +} +//---------------------------------------------------------------------------- //---------------------------------------------------------------------------- void vvSlicer::SetContourSlice() -{ +{ if (mSurfaceCutActors.size() > 0) for (std::vector::iterator i=mSurfaceCutActors.begin(); - i!=mSurfaceCutActors.end(); i++) + i!=mSurfaceCutActors.end(); i++) { + + (*i)->SetSlicingOrientation(this->SliceOrientation); (*i)->SetCutSlice((this->Slice)*this->GetImage()->GetSpacing()[this->SliceOrientation]+ this->GetImage()->GetOrigin()[this->SliceOrientation]); + } } //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- void vvSlicer::ForceUpdateDisplayExtent() -{ +{ this->UpdateDisplayExtent(); } //---------------------------------------------------------------------------- @@ -1417,7 +1938,7 @@ void vvSlicer::ForceUpdateDisplayExtent() //---------------------------------------------------------------------------- int* vvSlicer::GetDisplayExtent() -{ +{ return this->GetImageActor()->GetDisplayExtent(); } //---------------------------------------------------------------------------- @@ -1425,14 +1946,15 @@ int* vvSlicer::GetDisplayExtent() //---------------------------------------------------------------------------- void vvSlicer::PrintSelf(ostream& os, vtkIndent indent) -{ +{ this->Superclass::PrintSelf(os, indent); } //---------------------------------------------------------------------------- + //---------------------------------------------------------------------------- void vvSlicer::SetVFColor(double r, double g, double b) -{ +{ double mVFColorHSV[3]; mVFColor[0] = r; mVFColor[1] = g; @@ -1445,4 +1967,21 @@ void vvSlicer::SetVFColor(double r, double g, double b) this->Render(); } +//---------------------------------------------------------------------------- + + +//---------------------------------------------------------------------------- +void vvSlicer::SetRegisterExtent(int ext[6]) +{ + copyExtent(ext, mRegisterExtent); +} +//---------------------------------------------------------------------------- + + +//---------------------------------------------------------------------------- +void vvSlicer::GetRegisterExtent(int ext[6]) +{ + copyExtent(mRegisterExtent, ext); +} +//----------------------------------------------------------------------------