X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=vv%2FvvSlicer.cxx;h=dd585636c5a76227817ec14cc8ded56fd548f132;hb=9c5f0e4d3d6b33e09d0413439ed7a867e3d85faa;hp=2224a9ac9748dd6abb32b09a79185048f93137fc;hpb=b92ff4ecffb178ca84f9318b57003787dace56a6;p=clitk.git diff --git a/vv/vvSlicer.cxx b/vv/vvSlicer.cxx index 2224a9a..dd58563 100644 --- a/vv/vvSlicer.cxx +++ b/vv/vvSlicer.cxx @@ -16,12 +16,14 @@ - 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 @@ -41,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -66,6 +69,10 @@ #include #include #include +#if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION >= 10) +# include +# include +#endif vtkCxxRevisionMacro(vvSlicer, "DummyRevision"); vtkStandardNewMacro(vvSlicer); @@ -75,20 +82,23 @@ static void copyExtent(int* in, int* to){ //------------------------------------------------------------------------------ vvSlicer::vvSlicer() { + mFusionSequenceCode = -1; this->UnInstallPipeline(); mImage = NULL; mReducedExtent = new int[6]; 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; @@ -132,12 +142,20 @@ vvSlicer::vvSlicer() this->GetRenderer()->AddActor(legend); showFusionLegend = false; - this->WindowLevel->Delete(); - this->WindowLevel = vvImageMapToWLColors::New(); - 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; } //------------------------------------------------------------------------------ @@ -283,14 +301,21 @@ vvSlicer::~vvSlicer() } //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +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); } //------------------------------------------------------------------------------ @@ -307,7 +332,11 @@ void vvSlicer::SetImage(vvImage::Pointer image) mImageReslice->AutoCropOutputOn(); mImageReslice->SetBackgroundColor(-1000,-1000,-1000,1); } - mImageReslice->SetResliceTransform(mImage->GetTransform()); + + mConcatenatedTransform->Identity(); + mConcatenatedTransform->Concatenate(mImage->GetTransform()[0]); + mConcatenatedTransform->Concatenate(mSlicingTransform); + mImageReslice->SetResliceTransform(mConcatenatedTransform); mImageReslice->SetInput(0, mImage->GetFirstVTKImageData()); mImageReslice->UpdateInformation(); @@ -341,6 +370,7 @@ void vvSlicer::SetOverlay(vvImage::Pointer overlay) { if (overlay->GetVTKImages().size()) { mOverlay = overlay; + mOverlayVisibility = true; if (!mOverlayReslice) { mOverlayReslice = vtkSmartPointer::New(); @@ -348,8 +378,13 @@ void vvSlicer::SetOverlay(vvImage::Pointer overlay) mOverlayReslice->AutoCropOutputOn(); mOverlayReslice->SetBackgroundColor(-1000,-1000,-1000,1); } - mOverlayReslice->SetResliceTransform(mOverlay->GetTransform()); + + mConcatenatedOverlayTransform->Identity(); + mConcatenatedOverlayTransform->Concatenate(mOverlay->GetTransform()[0]); + mConcatenatedOverlayTransform->Concatenate(mSlicingTransform); + mOverlayReslice->SetResliceTransform(mConcatenatedOverlayTransform); mOverlayReslice->SetInput(0, mOverlay->GetFirstVTKImageData()); + mImageReslice->UpdateInformation(); if (!mOverlayMapper) mOverlayMapper = vtkSmartPointer::New(); @@ -361,7 +396,10 @@ void vvSlicer::SetOverlay(vvImage::Pointer overlay) mOverlayActor->SetPickable(0); mOverlayActor->SetVisibility(true); mOverlayActor->SetOpacity(0.5); - } +#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) { @@ -381,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(); @@ -392,12 +432,17 @@ void vvSlicer::SetFusion(vvImage::Pointer fusion) mFusionReslice->AutoCropOutputOn(); mFusionReslice->SetBackgroundColor(-1000,-1000,-1000,1); } - mFusionReslice->SetResliceTransform(mFusion->GetTransform()); + + mConcatenatedFusionTransform->Identity(); + mConcatenatedFusionTransform->Concatenate(mFusion->GetTransform()[0]); + mConcatenatedFusionTransform->Concatenate(mSlicingTransform); + mFusionReslice->SetResliceTransform(mConcatenatedFusionTransform); mFusionReslice->SetInput(0, mFusion->GetFirstVTKImageData()); + mFusionReslice->UpdateInformation(); if (!mFusionMapper) mFusionMapper = vtkSmartPointer::New(); - + vtkSmartPointer lut = vtkLookupTable::New(); lut->SetRange(0, 1); lut->SetValueRange(0, 1); @@ -412,6 +457,9 @@ void vvSlicer::SetFusion(vvImage::Pointer fusion) mFusionActor->SetPickable(0); mFusionActor->SetVisibility(true); mFusionActor->SetOpacity(0.7); +#if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION >= 10) + mFusionActor->GetMapper()->BorderOn(); +#endif this->GetRenderer()->AddActor(mFusionActor); } @@ -428,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") { - 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; } //------------------------------------------------------------------------------ @@ -450,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") { - 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(); @@ -473,6 +512,7 @@ void vvSlicer::SetVF(vvImage::Pointer vf) { if (vf->GetVTKImages().size()) { mVF = vf; + mVFVisibility = true; if (!mAAFilter) { mAAFilter= vtkSmartPointer::New(); @@ -539,36 +579,40 @@ void vvSlicer::SetLandmarks(vvLandmarks* 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(); + mLandClipper->SetInput(mLandmarks->GetOutput()); + mLandGlyph->SetSource(mCross->GetOutput()); - mLandGlyph->SetInput(landmarks->GetOutput()); + mLandGlyph->SetInput(mLandClipper->GetOutput()); //mLandGlyph->SetIndexModeToScalar(); - mLandGlyph->SetRange(0,1); - mLandGlyph->ScalingOff(); - - mLandGlyph->SetColorModeToColorByScalar(); + //mLandGlyph->SetRange(0,1); + //mLandGlyph->ScalingOff(); - if (!mClipBox) - mClipBox = vtkSmartPointer::New(); - if (!mLandClipper) - mLandClipper = vtkSmartPointer::New(); - mLandClipper->InsideOutOn(); - mLandClipper->SetInput(mLandGlyph->GetOutput()); - mLandClipper->SetClipFunction(mClipBox); + //mLandGlyph->SetColorModeToColorByScalar(); + + mLandGlyph->SetScaleModeToDataScalingOff(); + mLandGlyph->SetIndexModeToOff(); - 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()->SetColor(255,10,212); mLandActor->SetPickable(0); @@ -599,7 +643,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; @@ -664,28 +708,60 @@ 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) - t = 0; + mCurrentTSlice = 0; else if ((unsigned int)t >= mImage->GetVTKImages().size()) - t = mImage->GetVTKImages().size() -1; + mCurrentTSlice = mImage->GetVTKImages().size() -1; + else + mCurrentTSlice = t; - if (mCurrentTSlice == t) return; + // Update transform + mConcatenatedTransform->Identity(); + mConcatenatedTransform->Concatenate(mImage->GetTransform()[mCurrentTSlice]); + mConcatenatedTransform->Concatenate(mSlicingTransform); - mCurrentTSlice = t; + // Update image data mImageReslice->SetInput( mImage->GetVTKImages()[mCurrentTSlice] ); if (mVF && mVFActor->GetVisibility()) { if (mVF->GetVTKImages().size() > (unsigned int)mCurrentTSlice) mVOIFilter->SetInput(mVF->GetVTKImages()[mCurrentTSlice]); } + //update the overlay if (mOverlay && mOverlayActor->GetVisibility()) { - if (mOverlay->GetVTKImages().size() > (unsigned int)mCurrentTSlice) - mOverlayReslice->SetInput( mOverlay->GetVTKImages()[mCurrentTSlice] ); + if (mOverlay->GetVTKImages().size() > (unsigned int)t) { + mCurrentOverlayTSlice = t; + mOverlayReslice->SetInput( mOverlay->GetVTKImages()[mCurrentOverlayTSlice] ); + + // Update overlay transform + mConcatenatedOverlayTransform->Identity(); + mConcatenatedOverlayTransform->Concatenate(mOverlay->GetTransform()[mCurrentOverlayTSlice]); + mConcatenatedOverlayTransform->Concatenate(mSlicingTransform); + } } - if (mFusion && mFusionActor->GetVisibility()) { - if (mFusion->GetVTKImages().size() > (unsigned int)mCurrentTSlice) - mFusionReslice->SetInput( mFusion->GetVTKImages()[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; + 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(); @@ -696,6 +772,25 @@ 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; + mFusionReslice->SetInput( mFusion->GetVTKImages()[mCurrentFusionTSlice] ); + // Update fusion transform + mConcatenatedFusionTransform->Identity(); + mConcatenatedFusionTransform->Concatenate(mFusion->GetTransform()[mCurrentFusionTSlice]); //not really useful... + mConcatenatedFusionTransform->Concatenate(mSlicingTransform); + } + } + + UpdateDisplayExtent(); +} +//------------------------------------------------------------------------------ + + //------------------------------------------------------------------------------ int vvSlicer::GetTSlice() { @@ -703,6 +798,32 @@ int vvSlicer::GetTSlice() } //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +int vvSlicer::GetMaxCurrentTSlice() +{ + int t = mCurrentTSlice; + if(mOverlay) + t = std::max(t, mCurrentOverlayTSlice); + 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; +} +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +int vvSlicer::GetFusionTSlice() +{ + return mCurrentFusionTSlice; +} +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +int vvSlicer::GetOverlayTSlice() +{ + return mCurrentOverlayTSlice; +} +//------------------------------------------------------------------------------ + //------------------------------------------------------------------------------ void vvSlicer::SetSliceOrientation(int orientation) { @@ -727,15 +848,24 @@ void vvSlicer::SetSliceOrientation(int orientation) AdjustResliceToSliceOrientation(mOverlayReslice); // Update the viewer - int *range = this->GetSliceRange(); - if (range) - this->Slice = static_cast((range[0] + range[1]) * 0.5); - + // 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); + 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); + } + this->UpdateOrientation(); this->UpdateDisplayExtent(); @@ -774,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]; @@ -815,36 +950,55 @@ void vvSlicer::UpdateDisplayExtent() return; } input->UpdateInformation(); + this->SetSlice( this->GetSlice() ); //SR: make sure the update let the slice in extents // Local copy of extent int w_ext[6]; int* ext = GetExtent(); copyExtent(ext, w_ext); // Set slice value - int s = this->Slice > ext[this->SliceOrientation*2+1] ? ext[this->SliceOrientation*2 + 1] : this->Slice; - w_ext[ this->SliceOrientation*2 ] = s; - w_ext[ this->SliceOrientation*2+1 ] = s; + 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 && 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(); @@ -864,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; @@ -878,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) { @@ -909,13 +1066,11 @@ 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); } } } - } //---------------------------------------------------------------------------- @@ -931,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] ) { @@ -958,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; } //---------------------------------------------------------------------------- @@ -1017,7 +1170,6 @@ void vvSlicer::SetRenderWindow(int orientation, vtkRenderWindow * rw) this->SetupInteractor(rw->GetInteractor()); ca->SetImageActor(this->GetImageActor()); ca->SetWindowLevel(this->GetWindowLevel()); - ca->SetText(2, ""); ca->SetText(3, "\n"); double bounds[6]; @@ -1054,9 +1206,8 @@ void vvSlicer::ResetCamera() //---------------------------------------------------------------------------- void vvSlicer::SetDisplayMode(bool i) { - this->GetRenderer()->SetDraw(i); - if (i) - UpdateDisplayExtent(); + this->GetRenderer()->SetDraw(i); + if (i) UpdateDisplayExtent(); } //---------------------------------------------------------------------------- @@ -1155,19 +1306,21 @@ double vvSlicer::GetOverlayColorLevel() //---------------------------------------------------------------------------- void vvSlicer::SetOverlayColorWindow(double window) { - mOverlayMapper->SetWindow(window); + if(mOverlayMapper) + mOverlayMapper->SetWindow(window); } //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- void vvSlicer::SetOverlayColorLevel(double level) { - mOverlayMapper->SetLevel(level); + if(mOverlayMapper) + mOverlayMapper->SetLevel(level); } //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- -// Returns the min an the max value in a 41x41 region around the mouse pointer +// 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 @@ -1177,6 +1330,7 @@ void vvSlicer::GetExtremasAroundMousePointer(double & min, double & max, vtkImag corner1[i] = mCurrent[i]; corner2[i] = mCurrent[i]; } + this->Renderer->WorldToView(corner1[0], corner1[1], corner1[2]); this->Renderer->WorldToView(corner2[0], corner2[1], corner2[2]); @@ -1230,6 +1384,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] || @@ -1260,34 +1415,29 @@ void vvSlicer::Render() if (ca->GetVisibility()) { 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 (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] && - Y >= this->GetInput()->GetWholeExtent()[2] && - Y <= this->GetInput()->GetWholeExtent()[3] && - Z >= this->GetInput()->GetWholeExtent()[4] && - Z <= this->GetInput()->GetWholeExtent()[5]) { + 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 (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); + 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(mCurrent[0]) << ' ' - << lrint(mCurrent[1]) << ' ' - << lrint(mCurrent[2]) << ' ' + worldPos << "mm : " << lrint(mCurrentBeforeSlicingTransform[0]) << ' ' + << lrint(mCurrentBeforeSlicingTransform[1]) << ' ' + << lrint(mCurrentBeforeSlicingTransform[2]) << ' ' << mCurrentTSlice << std::endl; worldPos << "pixel : " << ix << ' ' @@ -1297,6 +1447,10 @@ void vvSlicer::Render() << std::endl; } ca->SetText(1,worldPos.str().c_str()); + + std::stringstream slicePos; + slicePos << "Slice: " << this->GetSlice(); + ca->SetText(2, slicePos.str().c_str()); } if (pdmA->GetVisibility()) { @@ -1307,12 +1461,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); @@ -1360,13 +1514,38 @@ void vvSlicer::UpdateLandmarks() { vtkPolyData *pd = static_cast(mLandClipper->GetInput()); if (pd->GetPoints()) { - mLandGlyph->SetRange(0,1); - mLandGlyph->Modified(); - mLandGlyph->Update(); + //mLandGlyph->SetRange(0,1); + //mLandGlyph->Modified(); + //mLandGlyph->Update(); mClipBox->Modified(); mLandClipper->Update(); mLandMapper->Update(); + //Let's add the captions + //First remove all captions: + for(unsigned int i=0;iRenderer->RemoveActor2D(mLandLabelActors[i]); + //allActors2D->Remove (mLandLabelActors[i]); + } + mLandLabelActors.clear(); + //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]); + } } } @@ -1399,6 +1578,14 @@ void vvSlicer::SetSlice(int slice) } //---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +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()