X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=vv%2FvvSlicer.cxx;h=6651833f04c497bf3dfe98c828c3e73514d4b438;hb=653bd3d5014f39b318c8d66f2532dde2c7e1879e;hp=24a552b251486faffaf677ebf989f9174686c883;hpb=358b7d254e07d4eae0cb1350b580783a82c1638f;p=clitk.git diff --git a/vv/vvSlicer.cxx b/vv/vvSlicer.cxx index 24a552b..6651833 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,7 +14,7 @@ - BSD See included LICENSE.txt file - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html - ======================================================================-====*/ + ===========================================================================**/ #include "vvSlicer.h" #include "vvImage.h" @@ -69,12 +69,15 @@ 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() { this->UnInstallPipeline(); mImage = NULL; + mReducedExtent = new int[6]; mCurrentTSlice = 0; mUseReducedExtent = false; @@ -211,7 +214,7 @@ void vvSlicer::EnableReducedExtent(bool b) //------------------------------------------------------------------------------ void vvSlicer::SetReducedExtent(int * ext) { - mReducedExtent = ext; + copyExtent(ext, mReducedExtent); } //------------------------------------------------------------------------------ @@ -267,12 +270,29 @@ bool vvSlicer::GetCursorVisibility() //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +void vvSlicer::SetCornerAnnotationVisibility(bool s) +{ + ca->SetVisibility(s); +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +bool vvSlicer::GetCornerAnnotationVisibility() +{ + return ca->GetVisibility(); +} +//------------------------------------------------------------------------------ + + //------------------------------------------------------------------------------ vvSlicer::~vvSlicer() { for (std::vector::iterator i=mSurfaceCutActors.begin(); i!=mSurfaceCutActors.end(); i++) delete (*i); + delete [] mReducedExtent; } //------------------------------------------------------------------------------ @@ -293,21 +313,32 @@ 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); + } + mImageReslice->SetResliceTransform(mImage->GetTransform()); + mImageReslice->SetInput(0, mImage->GetFirstVTKImageData()); + mImageReslice->UpdateInformation(); + + this->Superclass::SetInput(mImageReslice->GetOutput()); int extent[6]; this->GetInput()->GetWholeExtent(extent); // 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(); + mImageReslice->GetOutput()->SetUpdateExtent(extent); + mImageReslice->GetOutput()->Update(); this->UpdateDisplayExtent(); @@ -323,10 +354,19 @@ void vvSlicer::SetOverlay(vvImage::Pointer overlay) { if (overlay->GetVTKImages().size()) { mOverlay = overlay; + + if (!mOverlayReslice) { + mOverlayReslice = vtkSmartPointer::New(); + mOverlayReslice->SetInterpolationModeToLinear(); + mOverlayReslice->AutoCropOutputOn(); + mOverlayReslice->SetBackgroundColor(-1000,-1000,-1000,1); + } + mOverlayReslice->SetResliceTransform(mOverlay->GetTransform()); + mOverlayReslice->SetInput(0, mOverlay->GetFirstVTKImageData()); if (!mOverlayMapper) mOverlayMapper = vtkSmartPointer::New(); - mOverlayMapper->SetInput(overlay->GetTransformedVTKImages()[0]); + mOverlayMapper->SetInput(mOverlayReslice->GetOutput()); if (!mOverlayActor) { mOverlayActor = vtkSmartPointer::New(); @@ -334,7 +374,6 @@ void vvSlicer::SetOverlay(vvImage::Pointer overlay) mOverlayActor->SetPickable(0); mOverlayActor->SetVisibility(false); mOverlayActor->SetOpacity(0.5); - this->UpdateDisplayExtent(); } //stupid but necessary : the Overlay need to be rendered before fusion @@ -345,8 +384,9 @@ void vvSlicer::SetOverlay(vvImage::Pointer overlay) } else this->GetRenderer()->AddActor(mOverlayActor); - //Synchronize slice - SetTSlice(mCurrentTSlice); + //Synchronize orientation and slice + this->SetSliceOrientation(this->SliceOrientation); + this->SetTSlice(mCurrentTSlice); } } //------------------------------------------------------------------------------ @@ -358,9 +398,18 @@ void vvSlicer::SetFusion(vvImage::Pointer fusion) if (fusion->GetVTKImages().size()) { mFusion = fusion; + if (!mFusionReslice) { + mFusionReslice = vtkSmartPointer::New(); + mFusionReslice->SetInterpolationModeToLinear(); + mFusionReslice->AutoCropOutputOn(); + mFusionReslice->SetBackgroundColor(-1000,-1000,-1000,1); + } + mFusionReslice->SetResliceTransform(mFusion->GetTransform()); + mFusionReslice->SetInput(0, mFusion->GetFirstVTKImageData()); + if (!mFusionMapper) mFusionMapper = vtkSmartPointer::New(); - mFusionMapper->SetInput(fusion->GetTransformedVTKImages()[0]); + mFusionMapper->SetInput(mFusionReslice->GetOutput()); if (!mFusionActor) { mFusionActor = vtkSmartPointer::New(); @@ -368,36 +417,61 @@ void vvSlicer::SetFusion(vvImage::Pointer fusion) mFusionActor->SetPickable(0); mFusionActor->SetVisibility(false); mFusionActor->SetOpacity(0.7); - this->UpdateDisplayExtent(); this->GetRenderer()->AddActor(mFusionActor); } - //Synchronize slice - SetTSlice(mCurrentTSlice); + //Synchronize orientation and slice + this->SetSliceOrientation(this->SliceOrientation); + this->SetTSlice(mCurrentTSlice); } } //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +bool vvSlicer::GetActorVisibility(const std::string& actor_type, int overlay_index) +{ + bool vis = false; + if (actor_type == "image") { + vis = this->ImageActor->GetVisibility(); + } + else if (actor_type == "vector") { + vis = this->mVFActor->GetVisibility(); + } + else if (actor_type == "overlay") { + vis = this->mOverlayActor->GetVisibility(); + } + else if (actor_type == "fusion") { + vis = this->mFusionActor->GetVisibility(); + } + 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") { + if (actor_type == "image") { + this->ImageActor->SetVisibility(vis); + } + else if (actor_type == "vector") { this->mVFActor->SetVisibility(vis); } - if (actor_type == "overlay") { + else if (actor_type == "overlay") { this->mOverlayActor->SetVisibility(vis); } - if (actor_type == "fusion") { + else if (actor_type == "fusion") { this->mFusionActor->SetVisibility(vis); } - if (actor_type == "contour") + else if (actor_type == "contour") this->mSurfaceCutActors[overlay_index]->GetActor()->SetVisibility(vis); UpdateDisplayExtent(); } //------------------------------------------------------------------------------ - //------------------------------------------------------------------------------ void vvSlicer::SetVF(vvImage::Pointer vf) { @@ -409,7 +483,7 @@ void vvSlicer::SetVF(vvImage::Pointer vf) mVOIFilter = vtkSmartPointer::New(); mVOIFilter->SetSampleRate(mSubSampling,mSubSampling,mSubSampling); } - mVOIFilter->SetInput(vf->GetTransformedVTKImages()[0]); + mVOIFilter->SetInput(vf->GetFirstVTKImageData()); mAAFilter->SetInput(mVOIFilter->GetOutput()); ///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); @@ -604,18 +678,18 @@ void vvSlicer::SetTSlice(int t) if (mCurrentTSlice == t) return; mCurrentTSlice = t; - this->SetInput(mImage->GetTransformedVTKImages()[t]); + mImageReslice->SetInput( mImage->GetVTKImages()[mCurrentTSlice] ); if (mVF && mVFActor->GetVisibility()) { if (mVF->GetVTKImages().size() > (unsigned int)mCurrentTSlice) - mVOIFilter->SetInput(mVF->GetTransformedVTKImages()[mCurrentTSlice]); + mVOIFilter->SetInput(mVF->GetVTKImages()[mCurrentTSlice]); } if (mOverlay && mOverlayActor->GetVisibility()) { - if (mOverlay->GetTransformedVTKImages().size() > (unsigned int)mCurrentTSlice) - mOverlayMapper->SetInput(mOverlay->GetTransformedVTKImages()[mCurrentTSlice]); + if (mOverlay->GetVTKImages().size() > (unsigned int)mCurrentTSlice) + mOverlayReslice->SetInput( mOverlay->GetVTKImages()[mCurrentTSlice] ); } if (mFusion && mFusionActor->GetVisibility()) { if (mFusion->GetVTKImages().size() > (unsigned int)mCurrentTSlice) - mFusionMapper->SetInput(mFusion->GetTransformedVTKImages()[mCurrentTSlice]); + mFusionReslice->SetInput( mFusion->GetVTKImages()[mCurrentTSlice]); } if (mSurfaceCutActors.size() > 0) for (std::vector::iterator i=mSurfaceCutActors.begin(); @@ -633,7 +707,6 @@ int vvSlicer::GetTSlice() } //------------------------------------------------------------------------------ - //------------------------------------------------------------------------------ void vvSlicer::SetSliceOrientation(int orientation) { @@ -641,16 +714,22 @@ void vvSlicer::SetSliceOrientation(int orientation) int extent[6]; this->GetInput()->GetWholeExtent(extent); 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; + if(mFusion) + AdjustResliceToSliceOrientation(mFusionReslice); + + if(mOverlay) + AdjustResliceToSliceOrientation(mOverlayReslice); + // Update the viewer int *range = this->GetSliceRange(); if (range) @@ -674,10 +753,44 @@ 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 + double origin[3] = {VTK_DOUBLE_MAX, VTK_DOUBLE_MAX, VTK_DOUBLE_MAX}; + double spacing[3] = {VTK_DOUBLE_MAX, VTK_DOUBLE_MAX, VTK_DOUBLE_MAX}; + reslice->SetOutputOrigin(origin); + reslice->SetOutputSpacing(spacing); + reslice->GetOutput()->UpdateInformation(); + 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 superior grid positionInc + origin[this->SliceOrientation] = itk::Math::Ceil(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(); +} +//------------------------------------------------------------------------------ //---------------------------------------------------------------------------- -int * vvSlicer::GetExtent() -{ +int * vvSlicer::GetExtent(){ int *w_ext; if (mUseReducedExtent) { w_ext = mReducedExtent; @@ -703,175 +816,85 @@ void vvSlicer::UpdateDisplayExtent() return; } input->UpdateInformation(); - int *w_ext;// = input->GetWholeExtent(); - 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); - } - 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); + // Local copy of extent + int w_ext[6]; + copyExtent(GetExtent(), w_ext); + // Set slice value + w_ext[ this->SliceOrientation*2 ] = this->Slice; + w_ext[ this->SliceOrientation*2+1 ] = this->Slice; + + // Image actor + this->ImageActor->SetDisplayExtent(w_ext); + + // Overlay image actor + if (mOverlay && mOverlayActor->GetVisibility()) { + int overExtent[6]; + mOverlayReslice->GetOutput()->UpdateInformation(); + this->ConvertImageToImageDisplayExtent(input, w_ext, mOverlayReslice->GetOutput(), overExtent); + ClipDisplayedExtent(overExtent, mOverlayMapper->GetInput()->GetWholeExtent()); + mOverlayActor->SetDisplayExtent( overExtent ); + } + + // Fusion image actor + if (mFusion && mFusionActor->GetVisibility()) { + int fusExtent[6]; + mFusionReslice->GetOutput()->UpdateInformation(); + this->ConvertImageToImageDisplayExtent(input, w_ext, mFusionReslice->GetOutput(), fusExtent); + ClipDisplayedExtent(fusExtent, mFusionMapper->GetInput()->GetWholeExtent()); + mFusionActor->SetDisplayExtent(fusExtent); + } + + // 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 && mVFActor->GetVisibility()) { + int vfExtent[6]; + mVF->GetVTKImages()[0]->UpdateInformation(); + this->ConvertImageToImageDisplayExtent(input, w_ext, mVF->GetVTKImages()[0], vfExtent); + ClipDisplayedExtent(vfExtent, mVOIFilter->GetInput()->GetWholeExtent()); + mVOIFilter->SetVOI(vfExtent); + int orientation[3] = {1,1,1}; + orientation[this->SliceOrientation] = 0; + mGlyphFilter->SetOrientation(orientation[0], orientation[1], orientation[2]); + mVFMapper->Update(); + + position[this->SliceOrientation] += offset; + mVFActor->SetPosition(position); + } + + // Landmarks actor + if (mLandActor) { + if (mClipBox) { + 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); + UpdateLandmarks(); } - break; + + position[this->SliceOrientation] = offset; + mLandActor->SetPosition(position); } // Figure out the correct clipping range - if (this->Renderer) { if (this->InteractorStyle && this->InteractorStyle->GetAutoAdjustCameraClippingRange()) { @@ -887,79 +910,32 @@ void vvSlicer::UpdateDisplayExtent() 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); + cam->SetClippingRange(range - avg_spacing * 3.0, range + avg_spacing * 3.0); } } } + } //---------------------------------------------------------------------------- - //---------------------------------------------------------------------------- -void vvSlicer::ComputeVFDisplayedExtent(int x1,int x2,int y1,int y2,int z1,int z2,int vfExtent[6]) +void vvSlicer::ConvertImageToImageDisplayExtent(vtkImageData *sourceImage, const int sourceExtent[6], + vtkImageData *targetImage, int targetExtent[6]) { - vtkImageData* image=this->GetInput(); - vfExtent[0] = (( image->GetOrigin()[0] + x1*image->GetSpacing()[0] ) - mVF->GetOrigin()[0]) / - mVF->GetSpacing()[0]; - vfExtent[1] = (( image->GetOrigin()[0] + x2*image->GetSpacing()[0] ) - mVF->GetOrigin()[0]) / - mVF->GetSpacing()[0]; - vfExtent[2] = (( image->GetOrigin()[1] + y1*image->GetSpacing()[1] ) - mVF->GetOrigin()[1]) / - mVF->GetSpacing()[1]; - vfExtent[3] = (( image->GetOrigin()[1] + y2*image->GetSpacing()[1] ) - mVF->GetOrigin()[1]) / - mVF->GetSpacing()[1]; - vfExtent[4] = (( image->GetOrigin()[2] + z1*image->GetSpacing()[2] ) - mVF->GetOrigin()[2]) / - mVF->GetSpacing()[2]; - vfExtent[5] = (( image->GetOrigin()[2] + z2*image->GetSpacing()[2] ) - mVF->GetOrigin()[2]) / - mVF->GetSpacing()[2]; - - ClipDisplayedExtent(vfExtent,mVOIFilter->GetInput()->GetWholeExtent()); -} -//---------------------------------------------------------------------------- - - -//---------------------------------------------------------------------------- -void vvSlicer::ComputeOverlayDisplayedExtent(int x1,int x2,int y1,int y2,int z1,int z2,int overExtent[6]) -{ - vtkImageData* image=this->GetInput(); - overExtent[0] = (( image->GetOrigin()[0] + x1*image->GetSpacing()[0] ) - mOverlay->GetOrigin()[0]) / - mOverlay->GetSpacing()[0]; - overExtent[1] = (( image->GetOrigin()[0] + x2*image->GetSpacing()[0] ) - mOverlay->GetOrigin()[0]) / - mOverlay->GetSpacing()[0]; - overExtent[2] = (( image->GetOrigin()[1] + y1*image->GetSpacing()[1] ) - mOverlay->GetOrigin()[1]) / - mOverlay->GetSpacing()[1]; - overExtent[3] = (( image->GetOrigin()[1] + y2*image->GetSpacing()[1] ) - mOverlay->GetOrigin()[1]) / - mOverlay->GetSpacing()[1]; - overExtent[4] = (( image->GetOrigin()[2] + z1*image->GetSpacing()[2] ) - mOverlay->GetOrigin()[2]) / - mOverlay->GetSpacing()[2]; - overExtent[5] = (( image->GetOrigin()[2] + z2*image->GetSpacing()[2] ) - mOverlay->GetOrigin()[2]) / - mOverlay->GetSpacing()[2]; - ClipDisplayedExtent(overExtent, mOverlayMapper->GetInput()->GetWholeExtent()); -} -//---------------------------------------------------------------------------- - - -//---------------------------------------------------------------------------- -void vvSlicer::ComputeFusionDisplayedExtent(int x1,int x2,int y1,int y2,int z1,int z2,int fusExtent[6]) -{ - vtkImageData* image=this->GetInput(); - fusExtent[0] = (( image->GetOrigin()[0] + x1*image->GetSpacing()[0] ) - mFusion->GetOrigin()[0]) / - mFusion->GetSpacing()[0]; - fusExtent[1] = (( image->GetOrigin()[0] + x2*image->GetSpacing()[0] ) - mFusion->GetOrigin()[0]) / - mFusion->GetSpacing()[0]; - fusExtent[2] = (( image->GetOrigin()[1] + y1*image->GetSpacing()[1] ) - mFusion->GetOrigin()[1]) / - mFusion->GetSpacing()[1]; - fusExtent[3] = (( image->GetOrigin()[1] + y2*image->GetSpacing()[1] ) - mFusion->GetOrigin()[1]) / - mFusion->GetSpacing()[1]; - fusExtent[4] = (( image->GetOrigin()[2] + z1*image->GetSpacing()[2] ) - mFusion->GetOrigin()[2]) / - mFusion->GetSpacing()[2]; - fusExtent[5] = (( image->GetOrigin()[2] + z2*image->GetSpacing()[2] ) - mFusion->GetOrigin()[2]) / - mFusion->GetSpacing()[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 nearest + targetExtent[i] = itk::Math::Round(dExtents[i]); + } } //---------------------------------------------------------------------------- - //---------------------------------------------------------------------------- void vvSlicer::ClipDisplayedExtent(int extent[6], int refExtent[6]) { @@ -1094,7 +1070,11 @@ 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; @@ -1106,7 +1086,8 @@ void vvSlicer::FlipHorizontalView() case vtkImageViewer2::SLICE_ORIENTATION_YZ: cam->SetPosition(-position[0],position[1],position[2]); break; - } + }*/ + this->Renderer->ResetCameraClippingRange(); this->UpdateDisplayExtent(); } @@ -1209,11 +1190,19 @@ 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 (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 std::numeric_limits::quiet_NaN(); + image->SetUpdateExtent(ix, ix, iy, iy, iz, iz); image->Update(); return image->GetScalarComponentAsDouble(ix, iy, iz, component); @@ -1229,42 +1218,17 @@ void vvSlicer::Render() } 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]; + std::stringstream worldPos; 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 (pdmA->GetVisibility()) { - double x = mCursor[0]; - double y = mCursor[1]; - double z = mCursor[2]; - 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 ) { - 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); - } + +// if (X < this->GetInput()->GetWholeExtent()[0]) X = this->GetInput()->GetWholeExtent()[0]; +// else if (X > this->GetInput()->GetWholeExtent()[1]) X = this->GetInput()->GetWholeExtent()[1]; +// if (Y < this->GetInput()->GetWholeExtent()[2]) Y = this->GetInput()->GetWholeExtent()[2]; +// else if (Y > this->GetInput()->GetWholeExtent()[3]) Y = this->GetInput()->GetWholeExtent()[3]; +// if (Z < this->GetInput()->GetWholeExtent()[4]) Z = this->GetInput()->GetWholeExtent()[4]; +// else if (Z > this->GetInput()->GetWholeExtent()[5]) Z = this->GetInput()->GetWholeExtent()[5]; if (X >= this->GetInput()->GetWholeExtent()[0] && X <= this->GetInput()->GetWholeExtent()[1] && @@ -1272,28 +1236,53 @@ void vvSlicer::Render() Y <= this->GetInput()->GetWholeExtent()[3] && Z >= this->GetInput()->GetWholeExtent()[4] && Z <= this->GetInput()->GetWholeExtent()[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(); + worldPos << "data value : " << value << std::endl; + worldPos << "mm : " << lrint(mCurrent[0]) << ' ' + << lrint(mCurrent[1]) << ' ' + << lrint(mCurrent[2]) << ' ' + << mCurrentTSlice + << std::endl; + worldPos << "pixel : " << ix << ' ' + << iy << ' ' + << iz << ' ' + << mCurrentTSlice + << std::endl; } - ca->SetText(1,worldPos.c_str()); + ca->SetText(1,worldPos.str().c_str()); + } + + if (pdmA->GetVisibility()) { + double x = mCursor[0]; + double y = mCursor[1]; + double z = mCursor[2]; + 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 ) { + 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); } + + if (mOverlay && mOverlayActor->GetVisibility()) { mOverlayMapper->SetWindow(this->GetColorWindow()); mOverlayMapper->SetLevel(this->GetColorLevel()); @@ -1303,7 +1292,7 @@ void vvSlicer::Render() } if (mLandMapper) UpdateLandmarks(); - //this->Superclass::Render(); + this->GetRenderWindow()->Render(); } //---------------------------------------------------------------------------- @@ -1363,7 +1352,7 @@ void vvSlicer::SetSlice(int slice) this->UpdateDisplayExtent(); // Seems to work without this line - // this->Render(); + //this->Render(); } //---------------------------------------------------------------------------- @@ -1373,9 +1362,12 @@ 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]); + } } //----------------------------------------------------------------------------