]> Creatis software - clitk.git/blobdiff - vv/vvSlicer.cxx
- improve (?) speed render for contours
[clitk.git] / vv / vvSlicer.cxx
index 66a62ed2372729986119b3b812996027bae76188..9a2eec41414a0a8193322717ed71bbf47dc7881d 100644 (file)
@@ -1,28 +1,22 @@
 /*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
 
-  Program:   vv
-  Language:  C++
-  Author :   Pierre Seroul (pierre.seroul@gmail.com)
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
 
-  Copyright (C) 2008
-  Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
-  CREATIS-LRMN http://www.creatis.insa-lyon.fr
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
 
-  This program is free software: you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation, version 3 of the License.
+  It is distributed under dual licence
 
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ======================================================================-====*/
 
-  You should have received a copy of the GNU General Public License
-  along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-  =========================================================================*/
 #include "vvSlicer.h"
-
 #include "vvImage.h"
 #include "vvSlicerManagerCommand.h"
 #include "vvGlyphSource.h"
 #include <vtkExtractVOI.h>
 #include <vtkSphereSource.h>
 #include <vtkCutter.h>
-#include <vtkPlane.h>
 #include <vtkAssignAttribute.h>
+#include <vtkImageAccumulate.h>
+#include <vtkImageReslice.h>
 
 vtkCxxRevisionMacro(vvSlicer, "DummyRevision");
 vtkStandardNewMacro(vvSlicer);
 
+//------------------------------------------------------------------------------
 vvSlicer::vvSlicer()
 {
   mImage = NULL;
@@ -92,11 +88,13 @@ vvSlicer::vvSlicer()
   mSubSampling = 5;
   mScale = 1;
   mVFLog = 0;
+  mVFWidth = 1;
 
   std::string text = "F1 = sagital; F2 = coronal; F3 = axial\n";
   text += "F5 = horizontal flip; F6 = vertical flip\n\n";
   text += "0,1,2,3,4,5 : preset windowing\n";
   text += "6,7,8,9 : preset colormap\n";
+  text += "z : local windowing\n";
   text += "r : reset view\n";
   text += "l : reload image\n";
   text += "f : fly to mouse position\n";
@@ -144,27 +142,52 @@ vvSlicer::vvSlicer()
   this->WindowLevel->Delete();
   this->WindowLevel = vvImageMapToWLColors::New();
   this->InstallPipeline();
+  
 }
+//------------------------------------------------------------------------------
+
 
+//------------------------------------------------------------------------------
 vtkImageMapToWindowLevelColors* vvSlicer::GetOverlayMapper() {
   return mOverlayMapper.GetPointer();
 }
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
 vtkImageActor* vvSlicer::GetOverlayActor() {
   return mOverlayActor.GetPointer();
 }
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
 vtkImageMapToWindowLevelColors* vvSlicer::GetFusionMapper() {
   return mFusionMapper.GetPointer();
 }
+//------------------------------------------------------------------------------
+
     
+//------------------------------------------------------------------------------
 vtkImageActor* vvSlicer::GetFusionActor() {
   return mFusionActor.GetPointer();
 }
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
 vtkActor* vvSlicer::GetVFActor() {
   return mVFActor.GetPointer();
 }
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
 vtkCornerAnnotation* vvSlicer::GetAnnotation() {
   return ca.GetPointer();
 }
+//------------------------------------------------------------------------------
+
 
 //------------------------------------------------------------------------------
 void vvSlicer::EnableReducedExtent(bool b) {
@@ -194,34 +217,54 @@ void vvSlicer::AddContour(vvMesh::Pointer contour,bool propagate)
 
   SetContourSlice();
 }
+//------------------------------------------------------------------------------
 
+
+//------------------------------------------------------------------------------
 void vvSlicer::ToggleContourSuperposition()
 {
   for (std::vector<vvMeshActor*>::iterator i=mSurfaceCutActors.begin();
        i!=mSurfaceCutActors.end();i++)
     (*i)->ToggleSuperposition();
 }
+//------------------------------------------------------------------------------
 
+
+//------------------------------------------------------------------------------
 void vvSlicer::SetCursorColor(int r,int g, int b)
 {
   pdmA->GetProperty()->SetColor(r,g,b);
 }
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
 void vvSlicer::SetCursorVisibility(bool s)
 {
   pdmA->SetVisibility(s);
 }
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
 bool vvSlicer::GetCursorVisibility()
 {
   return pdmA->GetVisibility();
 }
+//------------------------------------------------------------------------------
 
+
+//------------------------------------------------------------------------------
 vvSlicer::~vvSlicer()
 {
   for (std::vector<vvMeshActor*>::iterator i=mSurfaceCutActors.begin();
        i!=mSurfaceCutActors.end();i++)
     delete (*i);
 }
+//------------------------------------------------------------------------------
+
 
+//------------------------------------------------------------------------------
 void vvSlicer::SetCurrentPosition(double x, double y, double z, int t)
 {
   mCurrent[0] = x;
@@ -229,19 +272,45 @@ void vvSlicer::SetCurrentPosition(double x, double y, double z, int t)
   mCurrent[2] = z;
   mCurrentTSlice = t;
 }
+//------------------------------------------------------------------------------
+
 
+//------------------------------------------------------------------------------
 void vvSlicer::SetImage(vvImage::Pointer image)
 {
   if (image->GetVTKImages().size())
     {
       mImage = image;
       this->Superclass::SetInput(image->GetVTKImages()[0]);
+
+      // Prevent crash when reload -> change slice if outside extent
+      int extent[6];
+      this->GetInput()->GetWholeExtent(extent);
+      if (SliceOrientation == 0) {
+        if (Slice >= extent[1]) {
+          Slice = (extent[1]-extent[0])/2.0;
+        }
+      }
+      if (SliceOrientation == 1) {
+        if (Slice >= extent[3]) {
+          Slice = (extent[3]-extent[2])/2.0;
+        }
+      }
+      if (SliceOrientation == 2) {
+        if (Slice >= extent[5]) {
+          Slice = (extent[5]-extent[4])/2.0;
+        }
+      }
+
       this->UpdateDisplayExtent();
       mCurrentTSlice = 0;
       ca->SetText(0,mFileName.c_str());
     }
 }
+//------------------------------------------------------------------------------
+
 
+//------------------------------------------------------------------------------
 void vvSlicer::SetOverlay(vvImage::Pointer overlay)
 {
   if (overlay->GetVTKImages().size())
@@ -276,7 +345,10 @@ void vvSlicer::SetOverlay(vvImage::Pointer overlay)
       SetTSlice(mCurrentTSlice);
     }
 }
+//------------------------------------------------------------------------------
+
 
+//------------------------------------------------------------------------------
 void vvSlicer::SetFusion(vvImage::Pointer fusion)
 {
   if (fusion->GetVTKImages().size())
@@ -302,7 +374,10 @@ void vvSlicer::SetFusion(vvImage::Pointer fusion)
       SetTSlice(mCurrentTSlice);
     }
 }
+//------------------------------------------------------------------------------
+
 
+//------------------------------------------------------------------------------
 void vvSlicer::SetActorVisibility(const std::string& actor_type, int overlay_index ,bool vis)
 {
   if (actor_type == "vector")
@@ -321,7 +396,10 @@ void vvSlicer::SetActorVisibility(const std::string& actor_type, int overlay_ind
     this->mSurfaceCutActors[overlay_index]->GetActor()->SetVisibility(vis);
   UpdateDisplayExtent();
 }
+//------------------------------------------------------------------------------
+
 
+//------------------------------------------------------------------------------
 void vvSlicer::SetVF(vvImage::Pointer vf)
 {
   if (vf->GetVTKImages().size())
@@ -366,6 +444,7 @@ void vvSlicer::SetVF(vvImage::Pointer vf)
         mVFActor = vtkActor::New();
       mVFActor->SetMapper(mVFMapper);
       mVFActor->SetPickable(0);
+      mVFActor->GetProperty()->SetLineWidth(mVFWidth);
       this->UpdateDisplayExtent();
       this->GetRenderer()->AddActor(mVFActor);
 
@@ -373,7 +452,10 @@ void vvSlicer::SetVF(vvImage::Pointer vf)
       SetTSlice(mCurrentTSlice);
     }
 }
+//------------------------------------------------------------------------------
+
 
+//------------------------------------------------------------------------------
 void vvSlicer::SetLandmarks(vvLandmarks* landmarks)
 {
   mLandmarks = landmarks;
@@ -420,7 +502,9 @@ void vvSlicer::SetLandmarks(vvLandmarks* landmarks)
       this->GetRenderer()->AddActor(mLandActor);
     }
 }
+//------------------------------------------------------------------------------
 
+//------------------------------------------------------------------------------
 //FIXME: this function leaks memory, we should fix it someday :)
 void vvSlicer::RemoveActor(const std::string& actor_type, int overlay_index)
 {
@@ -455,7 +539,10 @@ void vvSlicer::RemoveActor(const std::string& actor_type, int overlay_index)
       mSurfaceCutActors.erase(mSurfaceCutActors.begin()+overlay_index);
     }
 }
+//------------------------------------------------------------------------------
+
 
+//------------------------------------------------------------------------------
 void vvSlicer::SetVFSubSampling(int sub)
 {
   if (mVOIFilter)
@@ -466,7 +553,10 @@ void vvSlicer::SetVFSubSampling(int sub)
   UpdateDisplayExtent();
   Render();
 }
+//------------------------------------------------------------------------------
+
 
+//------------------------------------------------------------------------------
 void vvSlicer::SetVFScale(int scale)
 {
   mScale = scale;
@@ -475,7 +565,21 @@ void vvSlicer::SetVFScale(int scale)
   UpdateDisplayExtent();
   Render();
 }
+//------------------------------------------------------------------------------
 
+//------------------------------------------------------------------------------
+void vvSlicer::SetVFWidth(int width)
+{
+  mVFWidth = width;
+  if (mVFActor)
+    mVFActor->GetProperty()->SetLineWidth(mVFWidth);
+  UpdateDisplayExtent();
+  Render();
+}
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
 void vvSlicer::SetVFLog(int log)
 {
   mVFLog = log;
@@ -487,13 +591,19 @@ void vvSlicer::SetVFLog(int log)
   UpdateDisplayExtent();
   Render();
 }
+//------------------------------------------------------------------------------
+
 
+//------------------------------------------------------------------------------
 void vvSlicer::SetTSlice(int t)
 {
   if (t < 0)
     t = 0;
   else if ((unsigned int)t >= mImage->GetVTKImages().size())
     t = mImage->GetVTKImages().size() -1;
+
+  if (mCurrentTSlice == t) return;
+
   mCurrentTSlice = t;
   this->SetInput(mImage->GetVTKImages()[t]);
   if (mVF && mVFActor->GetVisibility())
@@ -517,12 +627,18 @@ void vvSlicer::SetTSlice(int t)
       (*i)->SetTimeSlice(mCurrentTSlice);
   UpdateDisplayExtent();
 }
+//------------------------------------------------------------------------------
+
 
+//------------------------------------------------------------------------------
 int vvSlicer::GetTSlice()
 {
   return mCurrentTSlice;
 }
+//------------------------------------------------------------------------------
+
 
+//------------------------------------------------------------------------------
 void vvSlicer::SetSliceOrientation(int orientation)
 {
   //if 2D image, force to watch in Axial View
@@ -557,6 +673,27 @@ void vvSlicer::SetSliceOrientation(int orientation)
 
   SetContourSlice();
 }
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+int * vvSlicer::GetExtent() {
+  int *w_ext;
+  if (mUseReducedExtent) {
+    w_ext = mReducedExtent;
+  }
+  else w_ext = GetInput()->GetWholeExtent();
+  return w_ext;
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+int vvSlicer::GetOrientation() {
+  return this->SliceOrientation;
+}
+//----------------------------------------------------------------------------
+
 
 //----------------------------------------------------------------------------
 void vvSlicer::UpdateDisplayExtent()
@@ -574,10 +711,6 @@ void vvSlicer::UpdateDisplayExtent()
   }
   else w_ext = input->GetWholeExtent();
 
-  DD(w_ext[0]);
-  DD(w_ext[1]);
-  DD(w_ext[2]);
-
   switch (this->SliceOrientation)
     {
     case vtkImageViewer2::SLICE_ORIENTATION_XY:
@@ -780,7 +913,10 @@ void vvSlicer::UpdateDisplayExtent()
         }
     }
 }
+//----------------------------------------------------------------------------
+
 
+//----------------------------------------------------------------------------
 void vvSlicer::ComputeVFDisplayedExtent(int x1,int x2,int y1,int y2,int z1,int z2,int vfExtent[6])
 {
   vtkImageData* image=this->GetInput();
@@ -799,7 +935,10 @@ void vvSlicer::ComputeVFDisplayedExtent(int x1,int x2,int y1,int y2,int z1,int z
 
   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();
@@ -817,7 +956,10 @@ void vvSlicer::ComputeOverlayDisplayedExtent(int x1,int x2,int y1,int y2,int z1,
     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();
@@ -835,7 +977,10 @@ void vvSlicer::ComputeFusionDisplayedExtent(int x1,int x2,int y1,int y2,int z1,i
     mFusion->GetSpacing()[2];
   ClipDisplayedExtent(fusExtent, mFusionMapper->GetInput()->GetWholeExtent());
 }
+//----------------------------------------------------------------------------
 
+
+//----------------------------------------------------------------------------
 void vvSlicer::ClipDisplayedExtent(int extent[6], int refExtent[6])
 {
   bool out = false;
@@ -870,7 +1015,10 @@ void vvSlicer::ClipDisplayedExtent(int extent[6], int refExtent[6])
         extent[i+1] = refExtent[i];
       }
 }
+//----------------------------------------------------------------------------
+
 
+//----------------------------------------------------------------------------
 void vvSlicer::UpdateOrientation()
 {
   // Set the camera position
@@ -899,12 +1047,18 @@ void vvSlicer::UpdateOrientation()
         }
     }
 }
+//----------------------------------------------------------------------------
+
 
+//----------------------------------------------------------------------------
 void vvSlicer::SetOpacity(double s)
 {
   this->GetImageActor()->SetOpacity(s);
 }
+//----------------------------------------------------------------------------
+
 
+//----------------------------------------------------------------------------
 void vvSlicer::SetRenderWindow(int orientation, vtkRenderWindow * rw)
 {
   this->Superclass::SetRenderWindow(rw);
@@ -934,7 +1088,10 @@ void vvSlicer::SetRenderWindow(int orientation, vtkRenderWindow * rw)
   SetSliceOrientation(2-(orientation%3));
   ResetCamera();
 }
+//----------------------------------------------------------------------------
+
 
+//----------------------------------------------------------------------------
 void vvSlicer::ResetCamera()
 {
   if (this->GetInput())
@@ -947,7 +1104,10 @@ void vvSlicer::ResetCamera()
       this->GetRenderer()->GetActiveCamera()->SetParallelScale(bmax/2);
     }
 }
+//----------------------------------------------------------------------------
+
 
+//----------------------------------------------------------------------------
 void vvSlicer::SetDisplayMode(bool i)
 {
   this->GetImageActor()->SetVisibility(i);
@@ -1034,10 +1194,69 @@ void vvSlicer::SetColorLevel(double level)
 }
 //----------------------------------------------------------------------------
 
+//----------------------------------------------------------------------------
+// Returns the min an the max value in a 41x41 region around the mouse pointer
+void vvSlicer::GetExtremasAroundMousePointer(double & min, double & max)
+{
+  //Get mouse pointer position in view coordinates
+  double fLocalExtents[6];
+  for(int i=0; i<3; i++)
+    {
+      fLocalExtents[i*2  ] = mCurrent[i];
+      fLocalExtents[i*2+1] = mCurrent[i];
+    }
+  this->Renderer->WorldToView(fLocalExtents[0], fLocalExtents[2], fLocalExtents[4]);
+  this->Renderer->WorldToView(fLocalExtents[1], fLocalExtents[3], fLocalExtents[5]);
+  for(int i=0; i<3; i++)
+    {
+      if (i!=SliceOrientation) //SR: assumes that SliceOrientation is valid in ViewCoordinates (???)
+        {
+             fLocalExtents[i*2  ] -= 0.2;
+             fLocalExtents[i*2+1] += 0.2;
+        }
+    }
+  this->Renderer->ViewToWorld(fLocalExtents[0], fLocalExtents[2], fLocalExtents[4]);
+  this->Renderer->ViewToWorld(fLocalExtents[1], fLocalExtents[3], fLocalExtents[5]);
+
+  //Convert to image pixel coordinates (rounded)
+  int iLocalExtents[6];
+  for(int i=0; i<3; i++)
+    {
+      fLocalExtents[i*2  ] = (fLocalExtents[i*2  ] - this->GetInput()->GetOrigin()[i])/this->GetInput()->GetSpacing()[i];
+      fLocalExtents[i*2+1] = (fLocalExtents[i*2+1] - this->GetInput()->GetOrigin()[i])/this->GetInput()->GetSpacing()[i];
+    
+      iLocalExtents[i*2  ] = lrint(fLocalExtents[i*2  ]);
+      iLocalExtents[i*2+1] = lrint(fLocalExtents[i*2+1]);
+
+      if(iLocalExtents[i*2  ]>iLocalExtents[i*2+1])
+         std::swap(iLocalExtents[i*2], iLocalExtents[i*2+1]);
+    }
+
+  vtkSmartPointer<vtkExtractVOI> voiFilter = vtkExtractVOI::New();
+  voiFilter->SetInput(this->GetInput());
+  voiFilter->SetVOI(iLocalExtents);
+  voiFilter->Update();
+  if (!voiFilter->GetOutput()->GetNumberOfPoints())
+    {
+      min = 0;
+      max = 0;
+      return;
+    }
+
+  vtkSmartPointer<vtkImageAccumulate> accFilter = vtkImageAccumulate::New();
+  accFilter->SetInput(voiFilter->GetOutput());
+  accFilter->Update();
+  
+  min = *(accFilter->GetMin());
+  max = *(accFilter->GetMax());
+}
+//----------------------------------------------------------------------------
 
 //----------------------------------------------------------------------------
 void vvSlicer::Render()
 {
+  //  DD("vvSlicer::Render");
+  // DD(SliceOrientation);
   if (this->GetWindowLevel()->GetLookupTable() && !this->mOverlay && !this->mFusion)
     {
       legend->SetLookupTable(this->GetWindowLevel()->GetLookupTable());
@@ -1102,16 +1321,17 @@ void vvSlicer::Render()
           pixel2 << (int)Y;
           pixel3 << (int)Z;
           temps << mCurrentTSlice;
-          double value = this->GetInput()->GetScalarComponentAsDouble(
-                                                                      (int)X,
-                                                                      (int)Y,
-                                                                      (int)Z,0);
+          double value = this->GetInput()->GetScalarComponentAsDouble(lrint(X),
+                                                                      lrint(Y),
+                                                                      lrint(Z),0);
 
           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 += "\n mm : " + world1.str() + " " + world2.str() + " " + 
+            world3.str() + " " + temps.str();
+          worldPos += "\n pixel : " + pixel1.str() + " " + pixel2.str() + " " + 
+            pixel3.str() + " " + temps.str();
         }
       ca->SetText(1,worldPos.c_str());
     }
@@ -1143,6 +1363,7 @@ void vvSlicer::UpdateCursorPosition()
 }
 //----------------------------------------------------------------------------
 
+
 //----------------------------------------------------------------------------
 void vvSlicer::UpdateLandmarks()
 {
@@ -1165,11 +1386,7 @@ void vvSlicer::UpdateLandmarks()
 //----------------------------------------------------------------------------
 void vvSlicer::SetSlice(int slice)
 {
-  DD("vvSlicer::SetSlice");
-  DD(slice);
   int *range = this->GetSliceRange();
-  DD(range[0]);
-  DD(range[1]);
   if (range)
     {
       if (slice < range[0])
@@ -1191,7 +1408,11 @@ void vvSlicer::SetSlice(int slice)
   SetContourSlice();
   this->Modified();
   this->UpdateDisplayExtent();
-  this->Render();
+
+  //  DD("SetSlice de slicer = Render");
+
+  // Seems to work without this line
+  //  this->Render();
 }
 //----------------------------------------------------------------------------
 
@@ -1230,3 +1451,10 @@ void vvSlicer::PrintSelf(ostream& os, vtkIndent indent)
   this->Superclass::PrintSelf(os, indent);
 }
 //----------------------------------------------------------------------------
+
+
+   
+   
+
+
+