|
@@ -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;
|
|
|
}
|