- CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
===========================================================================**/
+#include <QMessageBox>
+#include <QString>
+
#include "vvSlicer.h"
#include "vvImage.h"
#include "vvSlicerManagerCommand.h"
#include <vtkImageReslice.h>
#if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION >= 10)
# include <vtkImageMapper3D.h>
+# include <vtkImageSliceMapper.h>
#endif
vtkCxxRevisionMacro(vvSlicer, "DummyRevision");
//------------------------------------------------------------------------------
vvSlicer::vvSlicer()
{
+ mFusionSequenceCode = -1;
this->UnInstallPipeline();
mImage = NULL;
mReducedExtent = new int[6];
this->InstallPipeline();
mLinkOverlayWindowLevel = true;
+ mImageVisibility = true;
#if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION >= 10)
this->GetImageActor()->GetMapper()->BorderOn();
mConcatenatedTransform = vtkSmartPointer<vtkTransform>::New();
mConcatenatedFusionTransform = vtkSmartPointer<vtkTransform>::New();
mConcatenatedOverlayTransform = vtkSmartPointer<vtkTransform>::New();
+ mFirstSetSliceOrientation = true;
}
//------------------------------------------------------------------------------
mCurrentBeforeSlicingTransform[1]=y;
mCurrentBeforeSlicingTransform[2]=z;
mSlicingTransform->GetInverse()->TransformPoint(mCurrentBeforeSlicingTransform,mCurrent);
- SetTSlice(t);
+ if (t>=0) SetTSlice(t);
}
//------------------------------------------------------------------------------
{
if (overlay->GetVTKImages().size()) {
mOverlay = overlay;
+ mOverlayVisibility = true;
if (!mOverlayReslice) {
mOverlayReslice = vtkSmartPointer<vtkImageReslice>::New();
//------------------------------------------------------------------------------
-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<vtkImageReslice>::New();
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;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
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();
{
if (vf->GetVTKImages().size()) {
mVF = vf;
+ mVFVisibility = true;
if (!mAAFilter) {
mAAFilter= vtkSmartPointer<vtkAssignAttribute>::New();
mOverlayActor = NULL;
mOverlayMapper = NULL;
}
- if (actor_type == "fusion") {
+ if ( (actor_type == "fusion") || (actor_type == "fusionSequence") ) {
Renderer->RemoveActor(mFusionActor);
mFusion = NULL;
mFusionActor = NULL;
//------------------------------------------------------------------------------
-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())
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)t) {
mCurrentOverlayTSlice = t;
mConcatenatedOverlayTransform->Concatenate(mSlicingTransform);
}
}
- if (mFusion && mFusionActor->GetVisibility()) {
+ //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]);
//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+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()
{
int t = mCurrentTSlice;
if(mOverlay)
t = std::max(t, mCurrentOverlayTSlice);
- if(mFusion)
+ 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;
}
// 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<int>((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<int>(sCursor);
}
-
-// int *range = this->GetSliceRange();
-// if (range)
-// this->Slice = static_cast<int>((range[0] + range[1]) * 0.5);
this->UpdateOrientation();
this->UpdateDisplayExtent();
// 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<double>(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<double>(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];
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<vtkImageSliceMapper *>(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<vtkImageSliceMapper *>(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<vtkImageSliceMapper *>(mFusionActor->GetMapper())->SetOrientation(this->GetOrientation());
+#endif
}
+ else if(mFusion)
+ mFusionActor->SetVisibility(false);
// Vector field actor
double* camera = Renderer->GetActiveCamera()->GetPosition();
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;
position[this->SliceOrientation] += offset;
mVFActor->SetPosition(position);
}
-
+ else if(mVF)
+ mVFActor->SetVisibility(false);
+
// Landmarks actor
if (mLandActor) {
if (mClipBox) {
}
}
}
-
}
//----------------------------------------------------------------------------
// 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<double>(dExtents[i]);
- targetExtent[i] = itk::Math::Floor<double>(dExtents[i]);
+ // Round to current slice or larger extent
+ if(i/2==this->GetOrientation())
+ targetExtent[i] = itk::Math::Round<double>(dExtents[i]);
+ else if(i%2==1)
+ targetExtent[i] = itk::Math::Ceil<double>(dExtents[i]);
+ else
+ targetExtent[i] = itk::Math::Floor<double>(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] ) {
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::SetDisplayMode(bool i)
{
- this->GetRenderer()->SetDraw(i);
- if (i)
- UpdateDisplayExtent();
+ this->GetRenderer()->SetDraw(i);
+ if (i) UpdateDisplayExtent();
}
//----------------------------------------------------------------------------
ix = lrint(X);
iy = lrint(Y);
iz = lrint(Z);
+
if (ix < image->GetWholeExtent()[0] ||
ix > image->GetWholeExtent()[1] ||
iy < image->GetWholeExtent()[2] ||