Parcourir la source

Merge remote branch 'origin/ctkVTKSliceView'

Jean-Christophe Fillion-Robin il y a 15 ans
Parent
commit
f644991c6c

+ 22 - 3
Libs/Visualization/VTK/Widgets/ctkVTKRenderView.cpp

@@ -176,12 +176,30 @@ void ctkVTKRenderView::setCornerAnnotationText(const QString& text)
   d->CornerAnnotation->SetText(2, text.toLatin1());
 }
 
+//----------------------------------------------------------------------------
+QString ctkVTKRenderView::cornerAnnotationText() const
+{
+  CTK_D(const ctkVTKRenderView);
+  return QLatin1String(d->CornerAnnotation->GetText(2));
+}
+
 // --------------------------------------------------------------------------
-void ctkVTKRenderView::setBackgroundColor(double r, double g, double b)
+void ctkVTKRenderView::setBackgroundColor(const QColor& newBackgroundColor)
 {
   CTK_D(ctkVTKRenderView);
-  double background_color[3] = {r, g, b};
-  d->Renderer->SetBackground(background_color);
+
+  d->Renderer->SetBackground(newBackgroundColor.redF(),
+                             newBackgroundColor.greenF(),
+                             newBackgroundColor.blueF());
+}
+
+//----------------------------------------------------------------------------
+QColor ctkVTKRenderView::backgroundColor() const
+{
+  CTK_D(const ctkVTKRenderView);
+  double color[3] = {0, 0, 0};
+  d->Renderer->GetBackground(color);
+  return QColor::fromRgbF(color[0], color[1], color[2]);
 }
 
 //----------------------------------------------------------------------------
@@ -210,3 +228,4 @@ CTK_GET_CXX(ctkVTKRenderView, vtkRenderer*, renderer, Renderer);
 
 //----------------------------------------------------------------------------
 CTK_SET_CXX(ctkVTKRenderView, bool, setRenderEnabled, RenderEnabled);
+CTK_GET_CXX(ctkVTKRenderView, bool, renderEnabled, RenderEnabled);

+ 11 - 3
Libs/Visualization/VTK/Widgets/ctkVTKRenderView.h

@@ -39,6 +39,9 @@ class vtkCamera;
 class CTK_VISUALIZATION_VTK_WIDGETS_EXPORT ctkVTKRenderView : public QWidget
 {
   Q_OBJECT
+  Q_PROPERTY(QString cornerAnnotationText READ cornerAnnotationText WRITE setCornerAnnotationText)
+  Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor)
+  Q_PROPERTY(bool renderEnabled READ renderEnabled WRITE setRenderEnabled)
 public:
   /// Constructors
   typedef QWidget   Superclass;
@@ -61,11 +64,13 @@ public:
   /// Get current interactor style
   vtkInteractorObserver* interactorStyle();
 
-  /// Set corner annotation text
+  /// Set/Get corner annotation \a text
   void setCornerAnnotationText(const QString& text);
+  QString cornerAnnotationText() const;
 
-  /// Set background color
-  void setBackgroundColor(double r, double g, double b);
+  /// Set/Get background color
+  void setBackgroundColor(const QColor& newBackgroundColor);
+  QColor backgroundColor() const;
 
   /// Get active camera
   vtkCamera* activeCamera();
@@ -76,6 +81,9 @@ public:
   /// Get a reference to the associated vtkRenderer
   vtkRenderer* renderer()const;
 
+  /// Return if rendering is enabled
+  bool renderEnabled() const;
+
   /// Enable/Disable rendering
   void setRenderEnabled(bool value);
   

+ 160 - 37
Libs/Visualization/VTK/Widgets/ctkVTKSliceView.cpp

@@ -21,6 +21,7 @@
 // Qt includes
 #include <QTimer>
 #include <QVBoxLayout>
+#include <QDebug>
 
 // CTK includes
 #include "ctkVTKSliceView.h"
@@ -33,6 +34,14 @@
 #include <vtkProperty2D.h>
 #include <vtkCamera.h>
 #include <vtkImageData.h>
+#include <vtkCellArray.h>
+#include <vtkPoints.h>
+#include <vtkPolyData.h>
+#include <vtkPolyDataMapper2D.h>
+
+// Convenient macro
+#define VTK_CREATE(type, name) \
+  vtkSmartPointer<type> name = vtkSmartPointer<type>::New()
 
 // --------------------------------------------------------------------------
 // RenderWindowItem methods
@@ -41,24 +50,14 @@
 RenderWindowItem::RenderWindowItem(const QColor& rendererBackgroundColor,
                                    double colorWindow, double colorLevel)
 {
-  // Instanciate an image mapper
-  this->ImageMapper = vtkSmartPointer<vtkImageMapper>::New();
-  this->ImageMapper->SetColorWindow(colorWindow);
-  this->ImageMapper->SetColorLevel(colorLevel);
-
-  // .. and its corresponding 2D actor
-  vtkSmartPointer<vtkActor2D> actor2D =  vtkSmartPointer<vtkActor2D>::New();
-  actor2D->SetMapper(this->ImageMapper);
-  actor2D->GetProperty()->SetDisplayLocationToBackground();
-
   // Instanciate a renderer
   this->Renderer = vtkSmartPointer<vtkRenderer>::New();
   this->Renderer->SetBackground(rendererBackgroundColor.redF(),
                                 rendererBackgroundColor.greenF(),
                                 rendererBackgroundColor.blueF());
 
-  // .. and add it the 2D actor
-  this->Renderer->AddActor2D(actor2D);
+  this->setupImageMapperActor(colorWindow, colorLevel);
+  this->setupHighlightBoxActor();
 }
 
 //-----------------------------------------------------------------------------
@@ -69,15 +68,79 @@ void RenderWindowItem::setViewport(double xMin, double yMin,
   this->Renderer->SetViewport( xMin, yMin, (xMin + viewportWidth), (yMin + viewportHeight));
 }
 
+//---------------------------------------------------------------------------
+void RenderWindowItem::setupImageMapperActor(double colorWindow, double colorLevel)
+{
+  Q_ASSERT(this->Renderer);
+  Q_ASSERT(!this->ImageMapper);
+
+  // Instanciate an image mapper
+  this->ImageMapper = vtkSmartPointer<vtkImageMapper>::New();
+  this->ImageMapper->SetColorWindow(colorWindow);
+  this->ImageMapper->SetColorLevel(colorLevel);
+
+  // .. and its corresponding 2D actor
+  VTK_CREATE(vtkActor2D, actor2D);
+  actor2D->SetMapper(this->ImageMapper);
+  actor2D->GetProperty()->SetDisplayLocationToBackground();
+
+  // .. and add it to the renderer
+  this->Renderer->AddActor2D(actor2D);
+}
+
+//---------------------------------------------------------------------------
+void RenderWindowItem::setupHighlightBoxActor(bool visible)
+{
+  Q_ASSERT(this->Renderer);
+  Q_ASSERT(!this->HighlightBoxActor);
+  
+  // Create a highlight actor (2D box around viewport)
+  VTK_CREATE(vtkPolyData, poly);
+  VTK_CREATE(vtkPoints, points);
+  double eps = 0.0;
+  points->InsertNextPoint(eps, eps, 0);
+  points->InsertNextPoint(1, eps, 0);
+  points->InsertNextPoint(1, 1, 0);
+  points->InsertNextPoint(eps, 1, 0);
+
+  VTK_CREATE(vtkCellArray, cells);
+  cells->InsertNextCell(5);
+  cells->InsertCellPoint(0);
+  cells->InsertCellPoint(1);
+  cells->InsertCellPoint(2);
+  cells->InsertCellPoint(3);
+  cells->InsertCellPoint(0);
+  poly->SetPoints(points);
+  poly->SetLines(cells);
+
+  VTK_CREATE(vtkCoordinate, coordinate);
+  coordinate->SetCoordinateSystemToNormalizedViewport();
+  coordinate->SetViewport(this->Renderer);
+
+  VTK_CREATE(vtkPolyDataMapper2D, polyDataMapper);
+  polyDataMapper->SetInput(poly);
+  polyDataMapper->SetTransformCoordinate(coordinate);
+
+  this->HighlightBoxActor = vtkSmartPointer<vtkActor2D>::New();
+  this->HighlightBoxActor->SetMapper(polyDataMapper);
+  this->HighlightBoxActor->GetProperty()->SetColor(1, 1, 0);
+  this->HighlightBoxActor->GetProperty()->SetDisplayLocationToForeground();
+  this->HighlightBoxActor->GetProperty()->SetLineWidth(3); // wide enough so not clipped
+  this->HighlightBoxActor->SetVisibility(visible);
+
+  this->Renderer->AddActor2D(this->HighlightBoxActor);
+}
+
 // --------------------------------------------------------------------------
 // ctkVTKSliceViewPrivate methods
 
 // --------------------------------------------------------------------------
 ctkVTKSliceViewPrivate::ctkVTKSliceViewPrivate()
 {
-  //this->Renderer = vtkSmartPointer<vtkRenderer>::New();
   this->RenderWindow = vtkSmartPointer<vtkRenderWindow>::New();
   this->Axes = vtkSmartPointer<vtkAxesActor>::New();
+  this->Orientation = vtkSmartPointer<vtkOrientationMarkerWidget>::New();
+  this->CornerAnnotation = vtkSmartPointer<vtkCornerAnnotation>::New();
   this->RenderPending = false;
   this->RenderEnabled = false;
   this->RenderWindowRowCount = 0;
@@ -86,8 +149,6 @@ ctkVTKSliceViewPrivate::ctkVTKSliceViewPrivate()
   this->ColorWindow = 255;
   this->ColorLevel = 127.5;
   this->RendererBackgroundColor = QColor(Qt::black);
-  //this->ActorCollection = vtkSmartPointer<vtkActor2DCollection>::New();
-  //this->PolyDataCollection = vtkSmartPointer<vtkPolyDataCollection>::New();
 }
 
 // --------------------------------------------------------------------------
@@ -117,7 +178,7 @@ void ctkVTKSliceViewPrivate::setupRendering()
   this->RenderWindow->StereoCapableWindowOn();
   
   this->RenderWindow->GetRenderers()->RemoveAllItems();
-  
+
   // Compute the width and height of each RenderWindowItem
   double viewportWidth  = 1.0 / static_cast<double>(this->RenderWindowColumnCount);
   double viewportHeight = 1.0 / static_cast<double>(this->RenderWindowRowCount);
@@ -125,7 +186,7 @@ void ctkVTKSliceViewPrivate::setupRendering()
   // Postion of the Top-Left corner of the RenderWindowItem
   float xMin, yMin;
 
-  // Loop through RenderWindowItem and set their respective viewport
+  // Loop through RenderWindowItem
   for ( int rowId = 0; rowId < this->RenderWindowRowCount; ++rowId )
     {
     yMin = (this->RenderWindowRowCount - 1 - rowId) * viewportHeight;
@@ -133,21 +194,18 @@ void ctkVTKSliceViewPrivate::setupRendering()
 
     for ( int columnId = 0; columnId < this->RenderWindowColumnCount; ++columnId )
       {
-      this->RenderWindowItemList.at(p->renderWindowItemId(rowId, columnId))->setViewport(
-          xMin, yMin, viewportWidth, viewportHeight);
-      }
-    }
+      // Get reference to the renderWindowItem
+      RenderWindowItem * item  =
+          this->RenderWindowItemList.at(p->renderWindowItemId(rowId, columnId)).data();
 
-  // Get active camera
-  vtkCamera * activeCamera = p->activeCamera();
-  Q_ASSERT(activeCamera);
-  activeCamera->ParallelProjectionOn();
+      // Set viewport
+      item->setViewport(xMin, yMin, viewportWidth, viewportHeight);
 
-  // Add render(s) and set their respective active camera
-  foreach(const QSharedPointer<RenderWindowItem>& item, this->RenderWindowItemList)
-    {
-    this->RenderWindow->AddRenderer(item->Renderer);
-    item->Renderer->SetActiveCamera(activeCamera);
+      // Add to RenderWindow
+      this->RenderWindow->AddRenderer(item->Renderer);
+
+      xMin += viewportWidth;
+      }
     }
 
   this->VTKWidget->SetRenderWindow(this->RenderWindow);
@@ -161,7 +219,7 @@ void ctkVTKSliceViewPrivate::setupDefaultInteractor()
 }
 
 // --------------------------------------------------------------------------
-void ctkVTKSliceViewPrivate::updateRenderWindowItemZIndex(
+void ctkVTKSliceViewPrivate::updateRenderWindowItemsZIndex(
     ctkVTKSliceView::RenderWindowLayoutType layoutType)
 {
   CTK_P(ctkVTKSliceView);
@@ -205,7 +263,7 @@ ctkVTKSliceView::ctkVTKSliceView(QWidget* _parent) : Superclass(_parent)
   this->layout()->setSpacing(0);
   this->layout()->addWidget(d->VTKWidget);
 
-  d->setupRendering();
+  this->setRenderWindowLayout(1, 1);
   d->setupDefaultInteractor();
 }
 
@@ -218,6 +276,7 @@ ctkVTKSliceView::~ctkVTKSliceView()
 void ctkVTKSliceView::scheduleRender()
 {
   CTK_D(ctkVTKSliceView);
+
   if (!d->RenderEnabled)
     {
     return;
@@ -252,6 +311,10 @@ void ctkVTKSliceView::setInteractor(vtkRenderWindowInteractor* newInteractor)
 {
   CTK_D(ctkVTKSliceView);
   d->RenderWindow->SetInteractor(newInteractor);
+  //d->Orientation->SetOrientationMarker(d->Axes);
+  //d->Orientation->SetInteractor(newInteractor);
+  //d->Orientation->SetEnabled(1);
+  //d->Orientation->InteractiveOff();
   d->CurrentInteractor = newInteractor;
 }
 
@@ -278,7 +341,7 @@ void ctkVTKSliceView::setCornerAnnotationText(const QString& text)
 }
 
 //----------------------------------------------------------------------------
-QString ctkVTKSliceView::cornerAnnotationText()const
+QString ctkVTKSliceView::cornerAnnotationText() const
 {
   CTK_D(const ctkVTKSliceView);
   return QLatin1String(d->CornerAnnotation->GetText(2));
@@ -325,6 +388,24 @@ vtkCamera* ctkVTKSliceView::activeCamera()
 }
 
 //----------------------------------------------------------------------------
+void ctkVTKSliceView::setActiveCamera(vtkCamera* newActiveCamera)
+{
+  CTK_D(ctkVTKSliceView);
+
+  if (newActiveCamera == this->activeCamera())
+    {
+    return;
+    }
+
+  newActiveCamera->ParallelProjectionOn();
+
+  foreach(const QSharedPointer<RenderWindowItem>& item, d->RenderWindowItemList)
+    {
+    item->Renderer->SetActiveCamera(newActiveCamera);
+    }
+}
+
+//----------------------------------------------------------------------------
 void ctkVTKSliceView::resetCamera()
 {
   CTK_D(ctkVTKSliceView);
@@ -353,6 +434,12 @@ vtkRenderer* ctkVTKSliceView::renderer(int id)
 }
 
 //----------------------------------------------------------------------------
+vtkRenderer* ctkVTKSliceView::renderer(int rowId, int columnId)
+{
+  return this->renderer(this->renderWindowItemId(rowId, columnId));
+}
+
+//----------------------------------------------------------------------------
 CTK_SET_CXX(ctkVTKSliceView, bool, setRenderEnabled, RenderEnabled);
 CTK_GET_CXX(ctkVTKSliceView, bool, renderEnabled, RenderEnabled);
 
@@ -372,7 +459,10 @@ void ctkVTKSliceView::setRenderWindowLayoutType(ctkVTKSliceView::RenderWindowLay
     return;
     }
 
-  d->updateRenderWindowItemZIndex(layoutType);
+  if (d->ImageData)
+    {
+    d->updateRenderWindowItemsZIndex(layoutType);
+    }
 
   d->RenderWindowLayoutType = layoutType;
 }
@@ -385,6 +475,7 @@ CTK_GET_CXX(ctkVTKSliceView, ctkVTKSliceView::RenderWindowLayoutType,
 void ctkVTKSliceView::setRenderWindowLayout(int rowCount, int columnCount)
 {
   CTK_D(ctkVTKSliceView);
+  //qDebug() << "setRenderWindowLayout" << rowCount << columnCount;
 
   // Sanity checks
   Q_ASSERT(rowCount >= 0 && columnCount >= 0);
@@ -401,15 +492,22 @@ void ctkVTKSliceView::setRenderWindowLayout(int rowCount, int columnCount)
   int extraItem = (rowCount * columnCount) - d->RenderWindowItemList.size();
   if (extraItem > 0)
     {
+    //logger.debug(QString("Creating %1 RenderWindowItem").arg(extraItem));
+
     // Create extra RenderWindowItem(s)
     while(extraItem > 0)
       {
-      d->RenderWindowItemList.append(QSharedPointer<RenderWindowItem>(
-          new RenderWindowItem(d->RendererBackgroundColor, d->ColorWindow, d->ColorLevel)));
+      RenderWindowItem * item =
+          new RenderWindowItem(d->RendererBackgroundColor, d->ColorWindow, d->ColorLevel);
+      item->ImageMapper->SetInput(d->ImageData);
+      d->RenderWindowItemList.append(QSharedPointer<RenderWindowItem>(item));
+      --extraItem;
       }
     }
   else
     {
+    //logger.debug(QString("Removing %1 RenderWindowItem").arg(extraItem));
+
     // Remove extra RenderWindowItem(s)
     extraItem = qAbs(extraItem);
     while(extraItem > 0)
@@ -423,6 +521,28 @@ void ctkVTKSliceView::setRenderWindowLayout(int rowCount, int columnCount)
   d->RenderWindowColumnCount = columnCount;
 
   d->setupRendering();
+
+  if (d->ImageData)
+    {
+    d->updateRenderWindowItemsZIndex(d->RenderWindowLayoutType);
+    }
+}
+
+//----------------------------------------------------------------------------
+void ctkVTKSliceView::setHighlightedById(int id, bool value)
+{
+  CTK_D(ctkVTKSliceView);
+  if (id < 0 || id >= d->RenderWindowItemList.size())
+    {
+    return;
+    }
+  d->RenderWindowItemList.at(id)->HighlightBoxActor->SetVisibility(value);
+}
+
+//----------------------------------------------------------------------------
+void ctkVTKSliceView::setHighlighted(int rowId, int columnId, bool value)
+{
+  this->setHighlightedById(this->renderWindowItemId(rowId, columnId), value);
 }
 
 //----------------------------------------------------------------------------
@@ -439,7 +559,10 @@ void ctkVTKSliceView::setImageData(vtkImageData* imageDataToSet)
     item->ImageMapper->SetInput(imageDataToSet);
     }
 
-  d->updateRenderWindowItemZIndex(d->RenderWindowLayoutType);
+  if (imageDataToSet)
+    {
+    d->updateRenderWindowItemsZIndex(d->RenderWindowLayoutType);
+    }
 
   d->ImageData = imageDataToSet;
 }

+ 13 - 0
Libs/Visualization/VTK/Widgets/ctkVTKSliceView.h

@@ -83,6 +83,9 @@ public:
   /// Note that the same camera is used with all the renderWindowItem
   vtkCamera* activeCamera();
 
+  /// Set actice camera
+  void setActiveCamera(vtkCamera* newActiveCamera);
+
   /// Reset cameras associated with all renderWindowItem
   void resetCamera();
   
@@ -92,6 +95,9 @@ public:
   /// Get a reference to the associated vtkRenderer(s) identified by its \a id
   vtkRenderer* renderer(int id);
 
+  /// Get a reference to the associated vtkRenderer(s) given its posiion in the grid
+  /// \sa renderer(int)
+  vtkRenderer* renderer(int rowId, int columnId);
 
   /// The layout type determines how the image slices should be displayed
   /// within the different render view items.
@@ -107,6 +113,13 @@ public:
   /// Split the current vtkRenderWindow in \a rowCount per \a columnCount grid
   void setRenderWindowLayout(int rowCount, int columnCount);
 
+  /// Highlight / Unhighlight a render view item given its \a id
+  void setHighlightedById(int id, bool value);
+
+  ///  Highlight / Unhighlight a render view item given its position in the grid
+  /// \sa setHighlighted(int, bool)
+  void setHighlighted(int rowId, int columnId, bool value);
+
   /// Convenient function allowing to compute the renderWindowItemId
   /// given \a rowId and \a columnId.
   /// The following formula is used: ColumnCount * rowId + columnId

+ 11 - 1
Libs/Visualization/VTK/Widgets/ctkVTKSliceView_p.h

@@ -42,6 +42,8 @@
 #include <vtkWeakPointer.h>
 #include <vtkImageMapper.h>
 
+#include <vtkOrientationMarkerWidget.h>
+
 class vtkRenderWindowInteractor;
 
 
@@ -54,8 +56,15 @@ public:
   RenderWindowItem(const QColor& rendererBackgroundColor, double colorWindow, double colorLevel);
   void setViewport(double xMin, double yMin, double viewportWidth, double viewportHeight);
 
+  /// Create the actor supporing the image mapper
+  void setupImageMapperActor(double colorWindow, double colorLevel);
+
+  /// Create a box around the renderer.
+  void setupHighlightBoxActor(bool visible = false);
+
   vtkSmartPointer<vtkRenderer>     Renderer;
   vtkSmartPointer<vtkImageMapper>  ImageMapper;
+  vtkSmartPointer<vtkActor2D>      HighlightBoxActor;
 };
 
 //-----------------------------------------------------------------------------
@@ -73,7 +82,7 @@ public:
   void setupDefaultInteractor();
 
   /// Update render window ImageMapper Z slice according to \a layoutType
-  void updateRenderWindowItemZIndex(ctkVTKSliceView::RenderWindowLayoutType layoutType);
+  void updateRenderWindowItemsZIndex(ctkVTKSliceView::RenderWindowLayoutType layoutType);
 
   QVTKWidget*                                   VTKWidget;
   vtkSmartPointer<vtkRenderWindow>              RenderWindow;
@@ -85,6 +94,7 @@ public:
   ctkVTKSliceView::RenderWindowLayoutType       RenderWindowLayoutType;
   
   vtkSmartPointer<vtkAxesActor>                 Axes;
+  vtkSmartPointer<vtkOrientationMarkerWidget>   Orientation;
   vtkSmartPointer<vtkCornerAnnotation>          CornerAnnotation;
 
   vtkWeakPointer<vtkRenderWindowInteractor>     CurrentInteractor;