X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=vv%2FvvSlicer.cxx;h=ed53d2c83b138c600eeabf680da7edd775854cbc;hb=593ad2d23114d3ff50817a224e766a8cce624c78;hp=1ace5c2ee89bf3cfa6131f5c7a13263cc7fe0b52;hpb=1548a47199250d3819961adb37becac65bc72f3c;p=clitk.git diff --git a/vv/vvSlicer.cxx b/vv/vvSlicer.cxx index 1ace5c2..ed53d2c 100644 --- a/vv/vvSlicer.cxx +++ b/vv/vvSlicer.cxx @@ -16,6 +16,9 @@ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html ===========================================================================**/ +#include +#include + #include "vvSlicer.h" #include "vvImage.h" #include "vvSlicerManagerCommand.h" @@ -68,6 +71,7 @@ #include #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION >= 10) # include +# include #endif vtkCxxRevisionMacro(vvSlicer, "DummyRevision"); @@ -78,6 +82,7 @@ static void copyExtent(int* in, int* to){ //------------------------------------------------------------------------------ vvSlicer::vvSlicer() { + mFusionSequenceCode = -1; this->UnInstallPipeline(); mImage = NULL; mReducedExtent = new int[6]; @@ -140,6 +145,7 @@ vvSlicer::vvSlicer() this->InstallPipeline(); mLinkOverlayWindowLevel = true; + mImageVisibility = true; #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION >= 10) this->GetImageActor()->GetMapper()->BorderOn(); @@ -149,6 +155,7 @@ vvSlicer::vvSlicer() mConcatenatedTransform = vtkSmartPointer::New(); mConcatenatedFusionTransform = vtkSmartPointer::New(); mConcatenatedOverlayTransform = vtkSmartPointer::New(); + mFirstSetSliceOrientation = true; } //------------------------------------------------------------------------------ @@ -308,7 +315,7 @@ void vvSlicer::SetCurrentPosition(double x, double y, double z, int t) mCurrentBeforeSlicingTransform[1]=y; mCurrentBeforeSlicingTransform[2]=z; mSlicingTransform->GetInverse()->TransformPoint(mCurrentBeforeSlicingTransform,mCurrent); - SetTSlice(t); + if (t>=0) SetTSlice(t); } //------------------------------------------------------------------------------ @@ -363,6 +370,7 @@ void vvSlicer::SetOverlay(vvImage::Pointer overlay) { if (overlay->GetVTKImages().size()) { mOverlay = overlay; + mOverlayVisibility = true; if (!mOverlayReslice) { mOverlayReslice = vtkSmartPointer::New(); @@ -411,10 +419,12 @@ void vvSlicer::SetOverlay(vvImage::Pointer overlay) //------------------------------------------------------------------------------ -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 (!mFusionReslice) { mFusionReslice = vtkSmartPointer::New(); @@ -466,21 +476,16 @@ void vvSlicer::SetFusion(vvImage::Pointer fusion) 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") || (actor_type == "fusionSequence") ){ - vis = this->mFusionActor->GetVisibility(); - } + 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; } //------------------------------------------------------------------------------ @@ -488,18 +493,14 @@ bool vvSlicer::GetActorVisibility(const std::string& actor_type, int overlay_ind //------------------------------------------------------------------------------ void vvSlicer::SetActorVisibility(const std::string& actor_type, int overlay_index ,bool vis) { - if (actor_type == "image") { - this->ImageActor->SetVisibility(vis); - } - else if (actor_type == "vector") { - this->mVFActor->SetVisibility(vis); - } - else if (actor_type == "overlay") { - this->mOverlayActor->SetVisibility(vis); - } - else if ( (actor_type == "fusion") || (actor_type == "fusionSequence") ){ - this->mFusionActor->SetVisibility(vis); - } + 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(); @@ -511,6 +512,7 @@ void vvSlicer::SetVF(vvImage::Pointer vf) { if (vf->GetVTKImages().size()) { mVF = vf; + mVFVisibility = true; if (!mAAFilter) { mAAFilter= vtkSmartPointer::New(); @@ -706,8 +708,19 @@ void vvSlicer::SetVFLog(int log) //------------------------------------------------------------------------------ -void vvSlicer::SetTSlice(int t) +void vvSlicer::SetTSlice(int t, bool updateLinkedImages) { + if (!updateLinkedImages) { + mCurrentTSlice = t; + mImageReslice->SetInput( mImage->GetVTKImages()[mCurrentTSlice] ); + // Update transform + mConcatenatedTransform->Identity(); + mConcatenatedTransform->Concatenate(mImage->GetTransform()[mCurrentTSlice]); + mConcatenatedTransform->Concatenate(mSlicingTransform); + UpdateDisplayExtent(); + return; + } + if (t < 0) mCurrentTSlice = 0; else if ((unsigned int)t >= mImage->GetVTKImages().size()) @@ -726,7 +739,7 @@ void vvSlicer::SetTSlice(int t) if (mVF->GetVTKImages().size() > (unsigned int)mCurrentTSlice) mVOIFilter->SetInput(mVF->GetVTKImages()[mCurrentTSlice]); } -//also temporarilly disabled... + //update the overlay if (mOverlay && mOverlayActor->GetVisibility()) { if (mOverlay->GetVTKImages().size() > (unsigned int)t) { mCurrentOverlayTSlice = t; @@ -738,18 +751,18 @@ void vvSlicer::SetTSlice(int t) mConcatenatedOverlayTransform->Concatenate(mSlicingTransform); } } -//temporarilly disabled for testing fusionSequence - //if (mFusion && mFusionActor->GetVisibility()) { - // if (mFusion->GetVTKImages().size() > (unsigned int)t) { - // mCurrentFusionTSlice = t; - // mFusionReslice->SetInput( mFusion->GetVTKImages()[mCurrentFusionTSlice]); - - // // Update fusion transform - // mConcatenatedFusionTransform->Identity(); - // mConcatenatedFusionTransform->Concatenate(mFusion->GetTransform()[mCurrentFusionTSlice]); - // mConcatenatedFusionTransform->Concatenate(mSlicingTransform); - // } - //} + //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; + mFusionReslice->SetInput( mFusion->GetVTKImages()[mCurrentFusionTSlice]); + + // Update fusion transform + mConcatenatedFusionTransform->Identity(); + mConcatenatedFusionTransform->Concatenate(mFusion->GetTransform()[mCurrentFusionTSlice]); + mConcatenatedFusionTransform->Concatenate(mSlicingTransform); + } + } if (mSurfaceCutActors.size() > 0) for (std::vector::iterator i=mSurfaceCutActors.begin(); i!=mSurfaceCutActors.end(); i++) @@ -762,16 +775,13 @@ void vvSlicer::SetTSlice(int t) //------------------------------------------------------------------------------ void vvSlicer::SetFusionSequenceTSlice(int t) { -//QMessageBox::information(NULL, "vvSlicer::SetFusionSequenceTSlice", "ENTER, t = " + QString::number(t) + ", currentFusionTSlice = " + QString::number(mCurrentFusionTSlice)); - //fusionSequence data is stored behind standard fusion data... - if (mFusion && mFusionActor->GetVisibility()) { + if (mFusion && mFusionActor->GetVisibility() && (mFusionSequenceCode>=0)) { if (mFusion->GetVTKImages().size() > (unsigned int)t) { mCurrentFusionTSlice = t; - mFusionReslice->SetInput( mFusion->GetVTKImages()[mCurrentFusionTSlice]); - + mFusionReslice->SetInput( mFusion->GetVTKImages()[mCurrentFusionTSlice] ); // Update fusion transform mConcatenatedFusionTransform->Identity(); - mConcatenatedFusionTransform->Concatenate(mFusion->GetTransform()[mCurrentFusionTSlice]); + mConcatenatedFusionTransform->Concatenate(mFusion->GetTransform()[mCurrentFusionTSlice]); //not really useful... mConcatenatedFusionTransform->Concatenate(mSlicingTransform); } } @@ -794,9 +804,8 @@ int vvSlicer::GetMaxCurrentTSlice() int t = mCurrentTSlice; if(mOverlay) t = std::max(t, mCurrentOverlayTSlice); - //TODO temporarily desactivated... - //if(mFusion) - // t = std::max(t, mCurrentFusionTSlice); + if(mFusion&& (mFusionSequenceCode<0)) //ignore fusionSequence data: for these, the times are not to be related (this way) + t = std::max(t, mCurrentFusionTSlice); return t; } //------------------------------------------------------------------------------ @@ -845,15 +854,17 @@ void vvSlicer::SetSliceOrientation(int orientation) // DDV(cursorPos, 3); // SetCurrentPosition(cursorPos[0],cursorPos[1],cursorPos[2],cursorPos[3]); - if (this->Renderer && this->GetInput()) { + if (mFirstSetSliceOrientation) { + int *range = this->GetSliceRange(); + if (range) + this->Slice = static_cast((range[0] + range[1]) * 0.5); + mFirstSetSliceOrientation = false; + } + 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); } - -// int *range = this->GetSliceRange(); -// if (range) -// this->Slice = static_cast((range[0] + range[1]) * 0.5); this->UpdateOrientation(); this->UpdateDisplayExtent(); @@ -893,8 +904,13 @@ void vvSlicer::AdjustResliceToSliceOrientation(vtkImageReslice *reslice) // 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 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]; @@ -945,25 +961,44 @@ void vvSlicer::UpdateDisplayExtent() 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 && mOverlayActor->GetVisibility()) { + if (mOverlay && mOverlayVisibility) { AdjustResliceToSliceOrientation(mOverlayReslice); int overExtent[6]; this->ConvertImageToImageDisplayExtent(input, w_ext, mOverlayReslice->GetOutput(), overExtent); - ClipDisplayedExtent(overExtent, mOverlayMapper->GetInput()->GetWholeExtent()); + bool out = ClipDisplayedExtent(overExtent, mOverlayMapper->GetInput()->GetWholeExtent()); + 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 && mFusionActor->GetVisibility()) { + if (mFusion && mFusionVisibility) { AdjustResliceToSliceOrientation(mFusionReslice); int fusExtent[6]; this->ConvertImageToImageDisplayExtent(input, w_ext, mFusionReslice->GetOutput(), fusExtent); - ClipDisplayedExtent(fusExtent, mFusionMapper->GetInput()->GetWholeExtent()); - mFusionActor->SetDisplayExtent(fusExtent); + bool out = ClipDisplayedExtent(fusExtent, mFusionMapper->GetInput()->GetWholeExtent()); + 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(); @@ -983,11 +1018,12 @@ void vvSlicer::UpdateDisplayExtent() if (camera[this->SliceOrientation] < image_bounds[this->SliceOrientation*2]) offset = -1; - if (mVF && mVFActor->GetVisibility()) { + if (mVF && mVFVisibility) { int vfExtent[6]; mVF->GetVTKImages()[0]->UpdateInformation(); this->ConvertImageToImageDisplayExtent(input, w_ext, mVF->GetVTKImages()[0], vfExtent); - ClipDisplayedExtent(vfExtent, mVOIFilter->GetInput()->GetWholeExtent()); + bool out = ClipDisplayedExtent(vfExtent, mVOIFilter->GetInput()->GetWholeExtent()); + mVFActor->SetVisibility(!out); mVOIFilter->SetVOI(vfExtent); int orientation[3] = {1,1,1}; orientation[this->SliceOrientation] = 0; @@ -997,7 +1033,9 @@ void vvSlicer::UpdateDisplayExtent() position[this->SliceOrientation] += offset; mVFActor->SetPosition(position); } - + else if(mVF) + mVFActor->SetVisibility(false); + // Landmarks actor if (mLandActor) { if (mClipBox) { @@ -1048,26 +1086,23 @@ void vvSlicer::ConvertImageToImageDisplayExtent(vtkImageData *sourceImage, const // 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]); - targetExtent[i] = itk::Math::Floor(dExtents[i]); + // 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] ) { @@ -1075,16 +1110,17 @@ 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; } //---------------------------------------------------------------------------- @@ -1171,9 +1207,8 @@ void vvSlicer::ResetCamera() //---------------------------------------------------------------------------- void vvSlicer::SetDisplayMode(bool i) { - this->GetRenderer()->SetDraw(i); - if (i) - UpdateDisplayExtent(); + this->GetRenderer()->SetDraw(i); + if (i) UpdateDisplayExtent(); } //---------------------------------------------------------------------------- @@ -1348,6 +1383,7 @@ double vvSlicer::GetScalarComponentAsDouble(vtkImageData *image, double X, doubl ix = lrint(X); iy = lrint(Y); iz = lrint(Z); + if (ix < image->GetWholeExtent()[0] || ix > image->GetWholeExtent()[1] || iy < image->GetWholeExtent()[2] || @@ -1420,12 +1456,12 @@ void vvSlicer::Render() 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 (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);