[vtkusers] Subclassing vtkInteractorStyle in FourPainView Example

Panayiotis Georgiou ps.georgiou at gmail.com
Wed Sep 11 06:23:59 EDT 2013


Hello,

I am essentially trying to build on the FourPaneViewer example which you
can find from here:
https://github.com/Kitware/VTK/tree/master/Examples/GUI/Qt/FourPaneViewer

The major changes compared to the original code is the inclusion in
QtVTKRenderWindows.cxx of the subclass KeyPressInteractorStyle and the 3
lines of code where I apply the new style to view1. Both of these changes
were included in my first post.

Below I have including the code I am using which consists of 3 files:
QtVTKRenderWindows.cxx, QtVTKRenderWindows.h
and QtVTKRenderWindowsApp.cxx

You can download the .ui file from the above link.

Note: you may want to change the path to the Dicom files at
reader->SetDirectoryName(...)

Thanks for your help.

==================
QtVTKRenderWindows.h
==================

#ifndef QtVTKRenderWindows_H
#define QtVTKRenderWindows_H

#include "vtkSmartPointer.h"
#include "vtkResliceImageViewer.h"
#include "vtkImagePlaneWidget.h"
#include "vtkDistanceWidget.h"
#include "vtkResliceImageViewerMeasurements.h"
#include <QMainWindow>

// Forward Qt class declarations
class Ui_QtVTKRenderWindows;

class QtVTKRenderWindows : public QMainWindow
{
  Q_OBJECT
public:

  // Constructor/Destructor
  QtVTKRenderWindows(int argc, char *argv[]);
  ~QtVTKRenderWindows() {};

public slots:
  virtual void resliceMode(int);
  virtual void Render();

protected:
  vtkSmartPointer< vtkResliceImageViewer > riw[3];
  vtkSmartPointer< vtkImagePlaneWidget > planeWidget[3];
  vtkSmartPointer< vtkDistanceWidget > DistanceWidget[3];
  vtkSmartPointer< vtkResliceImageViewerMeasurements > ResliceMeasurements;

private:

  // Designer form
  Ui_QtVTKRenderWindows *ui;
};

#endif // QtVTKRenderWindows_H

====================
QtVTKRenderWindows.cxx
====================

#include "ui_QtVTKRenderWindows.h"
#include "QtVTKRenderWindows.h"

#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include "vtkResliceImageViewer.h"
#include "vtkResliceCursorLineRepresentation.h"
#include "vtkResliceCursorThickLineRepresentation.h"
#include "vtkResliceCursorWidget.h"
#include "vtkResliceCursorActor.h"
#include "vtkResliceCursorPolyDataAlgorithm.h"
#include "vtkResliceCursor.h"
#include "vtkDICOMImageReader.h"
#include "vtkCellPicker.h"
#include "vtkProperty.h"
#include "vtkPlane.h"
#include "vtkImageData.h"
#include "vtkCommand.h"
#include "vtkPlaneSource.h"
#include "vtkLookupTable.h"
#include "vtkImageMapToWindowLevelColors.h"
#include "vtkInteractorStyleImage.h"
#include "vtkImageSlabReslice.h"
#include "vtkBoundedPlanePointPlacer.h"
#include "vtkDistanceWidget.h"
#include "vtkDistanceRepresentation.h"
#include "vtkHandleRepresentation.h"
#include "vtkResliceImageViewerMeasurements.h"
#include "vtkDistanceRepresentation2D.h"
#include "vtkPointHandleRepresentation3D.h"
#include "vtkPointHandleRepresentation2D.h"
#include <qdebug.h>

#include <vtkPolyDataMapper.h>
#include <vtkObjectFactory.h>
#include <vtkActor.h>
#include <vtkSmartPointer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkPolyData.h>
#include <vtkSphereSource.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include "QVTKWidget.h"
#include <QKeyEvent>

// Define interaction style
class KeyPressInteractorStyle : public vtkInteractorStyle
{
public:
static KeyPressInteractorStyle* New();
vtkTypeMacro(KeyPressInteractorStyle, vtkInteractorStyle);

virtual void OnKeyPress()
{
// Get the keypress
vtkRenderWindowInteractor *rwi = this->Interactor;
std::string key = rwi->GetKeySym();

// Output the key that was pressed
std::cout << "Pressed " << key << std::endl;
qDebug()<< "Pressed " << rwi->GetKeySym();

// Forward events
vtkInteractorStyle::OnKeyPress();
}

virtual void OnChar()
{

qDebug()<<"keeeey";
}

};
vtkStandardNewMacro(KeyPressInteractorStyle);


//----------------------------------------------------------------------------
class vtkResliceCursorCallback : public vtkCommand
{
public:

static vtkResliceCursorCallback *New()
{
return new vtkResliceCursorCallback; }

void Execute( vtkObject *caller, unsigned long ev,
void *callData )
{

if (ev == vtkCommand::KeyPressEvent)
{
QKeyEvent* keyPressed = static_cast<QKeyEvent*>(callData);
 qDebug()<<"key pressed: "<<keyPressed->text();
}

if (ev == vtkResliceCursorWidget::WindowLevelEvent ||
ev == vtkCommand::WindowLevelEvent ||
ev == vtkResliceCursorWidget::ResliceThicknessChangedEvent||
ev == vtkResliceCursorWidget::ResliceAxesChangedEvent||
ev == vtkResliceCursorWidget::ResetCursorEvent)
{
//do nothing
}

vtkImagePlaneWidget* ipw =
dynamic_cast< vtkImagePlaneWidget* >( caller );
if (ipw)
{
double* wl = static_cast<double*>( callData );

if ( ipw == this->IPW[0] )
{

this->IPW[1]->SetWindowLevel(wl[0],wl[1],1);
this->IPW[2]->SetWindowLevel(wl[0],wl[1],1);

}
else if( ipw == this->IPW[1] )
{
this->IPW[0]->SetWindowLevel(wl[0],wl[1],1);
this->IPW[2]->SetWindowLevel(wl[0],wl[1],1);
}
else if (ipw == this->IPW[2])
{
this->IPW[0]->SetWindowLevel(wl[0],wl[1],1);
this->IPW[1]->SetWindowLevel(wl[0],wl[1],1);
}
}

vtkResliceCursorWidget *rcw = dynamic_cast<
vtkResliceCursorWidget * >(caller);
if (rcw)
{
vtkResliceCursorLineRepresentation *rep = dynamic_cast<
vtkResliceCursorLineRepresentation * >(rcw->GetRepresentation());
// Although the return value is not used, we keep the get calls
// in case they had side-effects
rep->GetResliceCursorActor()->GetCursorAlgorithm()->GetResliceCursor();
for (int i = 0; i < 3; i++)
{
vtkPlaneSource *ps = static_cast< vtkPlaneSource * >(
this->IPW[i]->GetPolyDataAlgorithm());
ps->SetOrigin(this->RCW[i]->GetResliceCursorRepresentation()->
GetPlaneSource()->GetOrigin());
ps->SetPoint1(this->RCW[i]->GetResliceCursorRepresentation()->
GetPlaneSource()->GetPoint1());
ps->SetPoint2(this->RCW[i]->GetResliceCursorRepresentation()->
GetPlaneSource()->GetPoint2());

// If the reslice plane has modified, update it on the 3D widget
this->IPW[i]->UpdatePlacement();
}
}

if(ev == vtkResliceImageViewer::SliceChangedEvent)
{
for (int i = 0; i < 3; i++)
{
vtkPlaneSource *ps = static_cast< vtkPlaneSource * >(
this->IPW[i]->GetPolyDataAlgorithm());
ps->SetOrigin(this->RCW[i]->GetResliceCursorRepresentation()->
GetPlaneSource()->GetOrigin());
ps->SetPoint1(this->RCW[i]->GetResliceCursorRepresentation()->
GetPlaneSource()->GetPoint1());
ps->SetPoint2(this->RCW[i]->GetResliceCursorRepresentation()->
GetPlaneSource()->GetPoint2());

// If the reslice plane has modified, update it on the 3D widget
this->IPW[i]->UpdatePlacement();
}
}

// Render everything
for (int i = 0; i < 3; i++)
{
this->RCW[i]->Render();
}
this->IPW[0]->GetInteractor()->GetRenderWindow()->Render();
}

vtkResliceCursorCallback() {}
vtkImagePlaneWidget* IPW[3];
vtkResliceCursorWidget *RCW[3];
};


QtVTKRenderWindows::QtVTKRenderWindows( int vtkNotUsed(argc), char *argv[])
{
this->ui = new Ui_QtVTKRenderWindows;
this->ui->setupUi(this);

vtkSmartPointer< vtkDICOMImageReader > reader =
vtkSmartPointer< vtkDICOMImageReader >::New();
//reader->SetDirectoryName(argv[1]);
reader->SetDirectoryName("C:/Users/Panayiotis/DentalCEsse/qt_interface/build/Release/temp_dental/2/dicom");
reader->Update();
int imageDims[3];
reader->GetOutput()->GetDimensions(imageDims);


for (int i = 0; i < 3; i++)
{
riw[i] = vtkSmartPointer< vtkResliceImageViewer >::New();
}

vtkSmartPointer<KeyPressInteractorStyle> style =
vtkSmartPointer<KeyPressInteractorStyle>::New();

this->ui->view1->GetInteractor()->SetInteractorStyle(style);
//this->ui->view1->GetRenderWindow()->GetInteractor()->SetInteractorStyle(style);
//this->ui->view1->GetRenderWindow()->AddRenderer(riw[0]->GetRenderer());
style->SetCurrentRenderer(riw[0]->GetRenderer());

this->ui->view1->SetRenderWindow(riw[0]->GetRenderWindow());
riw[0]->SetupInteractor(
this->ui->view1->GetRenderWindow()->GetInteractor());
 this->ui->view2->SetRenderWindow(riw[1]->GetRenderWindow());
riw[1]->SetupInteractor(
this->ui->view2->GetRenderWindow()->GetInteractor());

this->ui->view3->SetRenderWindow(riw[2]->GetRenderWindow());
riw[2]->SetupInteractor(
this->ui->view3->GetRenderWindow()->GetInteractor());

for (int i = 0; i < 3; i++)
{
// make them all share the same reslice cursor object.
vtkResliceCursorLineRepresentation *rep =
vtkResliceCursorLineRepresentation::SafeDownCast(
riw[i]->GetResliceCursorWidget()->GetRepresentation());
riw[i]->SetResliceCursor(riw[0]->GetResliceCursor());

rep->GetResliceCursorActor()->
GetCursorAlgorithm()->SetReslicePlaneNormal(i);

riw[i]->SetInput(reader->GetOutput());
riw[i]->SetSliceOrientation(i);
riw[i]->SetResliceModeToAxisAligned();
}

vtkSmartPointer<vtkCellPicker> picker =
vtkSmartPointer<vtkCellPicker>::New();
picker->SetTolerance(0.005);

vtkSmartPointer<vtkProperty> ipwProp =
vtkSmartPointer<vtkProperty>::New();

vtkSmartPointer< vtkRenderer > ren =
vtkSmartPointer< vtkRenderer >::New();

this->ui->view4->GetRenderWindow()->AddRenderer(ren);
vtkRenderWindowInteractor *iren = this->ui->view4->GetInteractor();
//commenting out the following code succesfully applies the
//'style' to view4
//iren->SetInteractorStyle(style);
//style->SetCurrentRenderer(ren);

for (int i = 0; i < 3; i++)
{
planeWidget[i] = vtkSmartPointer<vtkImagePlaneWidget>::New();
planeWidget[i]->SetInteractor( iren );
planeWidget[i]->SetPicker(picker);
planeWidget[i]->RestrictPlaneToVolumeOn();
double color[3] = {0, 0, 0};
color[i] = 1;
planeWidget[i]->GetPlaneProperty()->SetColor(color);

color[i] = 0.25;
riw[i]->GetRenderer()->SetBackground( color );

planeWidget[i]->SetTexturePlaneProperty(ipwProp);
planeWidget[i]->TextureInterpolateOff();
planeWidget[i]->SetResliceInterpolateToCubic();
planeWidget[i]->SetInput(reader->GetOutput());
planeWidget[i]->SetPlaneOrientation(i);
planeWidget[i]->SetSliceIndex(imageDims[i]/2);
planeWidget[i]->DisplayTextOn();
planeWidget[i]->SetDefaultRenderer(ren);
planeWidget[i]->On();
planeWidget[i]->InteractionOn();
planeWidget[i]->SetTextureVisibility(0);
}

vtkSmartPointer<vtkResliceCursorCallback> cbk =
vtkSmartPointer<vtkResliceCursorCallback>::New();

for (int i = 0; i < 3; i++)
{
cbk->IPW[i] = planeWidget[i];
cbk->RCW[i] = riw[i]->GetResliceCursorWidget();
riw[i]->GetResliceCursorWidget()->AddObserver(
vtkResliceCursorWidget::ResliceAxesChangedEvent, cbk );

riw[i]->GetResliceCursorWidget()->AddObserver(
vtkResliceCursorWidget::WindowLevelEvent, cbk );

riw[i]->GetResliceCursorWidget()->AddObserver(
vtkResliceCursorWidget::ResliceThicknessChangedEvent, cbk );

riw[i]->GetResliceCursorWidget()->AddObserver(
vtkResliceCursorWidget::ResetCursorEvent, cbk );

riw[i]->GetInteractorStyle()->AddObserver(
vtkCommand::WindowLevelEvent, cbk );

riw[i]->AddObserver(vtkResliceImageViewer::SliceChangedEvent,cbk);

// Make them all share the same color map.
riw[i]->SetLookupTable(riw[0]->GetLookupTable());
planeWidget[i]->GetColorMap()->SetLookupTable(riw[0]->GetLookupTable());
planeWidget[i]->SetColorMap(riw[i]->GetResliceCursorWidget()->GetResliceCursorRepresentation()->GetColorMap());

}

//riw[0]->GetRenderWindow()->GetInteractor()->AddObserver(vtkCommand::KeyPressEvent,cbk);

resliceMode(1);
this->ui->resliceModeCheckBox->setChecked(true);

this->ui->view1->show();
this->ui->view2->show();
this->ui->view3->show();

// Set up action signals and slots
this->ui->thickModeCheckBox->setEnabled(0);
this->ui->resliceModeCheckBox->setEnabled(0);

this->ui->blendModeGroupBox->setEnabled(0);
this->ui->resetButton->setEnabled(0);
this->ui->AddDistance1Button->setEnabled(0);
};

void QtVTKRenderWindows::resliceMode(int mode)
{
for (int i = 0; i < 3; i++)
{
riw[i]->SetResliceMode(mode ? 1 : 0);
riw[i]->GetRenderer()->ResetCamera();
riw[i]->Render();
}
}

void QtVTKRenderWindows::Render()
{
for (int i = 0; i < 3; i++)
{
riw[i]->Render();
}
this->ui->view3->GetRenderWindow()->Render();
}

=======================
QtVTKRenderWindowsApp.cxx
=======================

#include <QApplication>
#include "QtVTKRenderWindows.h"

int main( int argc, char** argv )
{
  // QT Stuff
  QApplication app( argc, argv );

  QtVTKRenderWindows myQtVTKRenderWindows(argc, argv);
  myQtVTKRenderWindows.show();

  return app.exec();
}



On Tue, Sep 10, 2013 at 8:14 PM, Alex Malyushytskyy <alexmalvtk at gmail.com>wrote:

> It might be time to attach compilable code.
>
> Alex
>
>
> On Mon, Sep 9, 2013 at 4:53 PM, Panayiotis Georgiou <ps.georgiou at gmail.com
> > wrote:
>
>> Thanks for your reply Alex.
>>
>> I have tried what you have suggested but it sill doesn't work. I believe
>> the problem is on how I apply the new style on the three views. As I have
>> noted in my original post, when I apply the customised style on the 4th
>> view it works. The way I did that for the 4th view is:
>>
>> vtkSmartPointer< vtkRenderer > ren = vtkSmartPointer< vtkRenderer
>> >::New();
>>
>>  this->ui->view4->GetRenderWindow()->AddRenderer(ren);
>> vtkRenderWindowInteractor *iren = this->ui->view4->GetInteractor();
>>  iren->SetInteractorStyle(style);
>> style->SetCurrentRenderer(ren);
>>
>> Any other suggestions?
>>
>> Thanks.
>>
>>
>> On Mon, Sep 9, 2013 at 9:25 PM, Alex Malyushytskyy <alexmalvtk at gmail.com>wrote:
>>
>>> Override  vtkInteractorStyle::OnChar ( )
>>>
>>> Make it do nothing.
>>>
>>> Alex
>>>
>>>
>>>
>>> On Mon, Sep 9, 2013 at 9:37 AM, Panayiotis Georgiou <
>>> ps.georgiou at gmail.com> wrote:
>>>
>>>> Dear vtk users,
>>>>
>>>> I am trying to customize the FourPaneViewer example from the provided
>>>> VTK examples. The full code of the example can be found in
>>>> VTK_DIR/Examples/GUI/Qt/FourPaneViewer.
>>>>
>>>> The example embeds in Qt 4 QVTKWidget views and performs reslicing. One
>>>> of the views renders (3) vtkImagePlaneWidgets and each of the other 3 views
>>>> renders a vtkResliceImageViewer.
>>>>
>>>> What I am trying to achieve is disable in the 3 vtkResliceImageViewers
>>>> any events triggered by pressing keys on the keyboard, i.e. I want to
>>>> restrict the user and allow him to interact with these widgets using only
>>>> the mouse.
>>>>
>>>> The way I have tried to do this is by subclassing the
>>>> vtkInteractorStyle class as follows:
>>>>
>>>>     // Define interaction style
>>>>     class KeyPressInteractorStyle : public vtkInteractorStyle
>>>>     {
>>>>     public:
>>>>     static KeyPressInteractorStyle* New();
>>>>     vtkTypeMacro(KeyPressInteractorStyle, vtkInteractorStyle);
>>>>
>>>>     virtual void OnKeyPress()
>>>>     {
>>>>     // Get the keypress
>>>>     vtkRenderWindowInteractor *rwi = this->Interactor;
>>>>     std::string key = rwi->GetKeySym();
>>>>
>>>>     // Output the key that was pressed
>>>>     std::cout << "Pressed " << key << std::endl;
>>>>     qDebug()<< "Pressed " << rwi->GetKeySym();
>>>>
>>>>     // Forward events
>>>>     vtkInteractorStyle::OnKeyPress();
>>>>     }
>>>>
>>>>     };
>>>>     vtkStandardNewMacro(KeyPressInteractorStyle);
>>>>
>>>> and then for each of the 3 views, the customised interaction style is
>>>> applied as follows:
>>>>
>>>>         vtkSmartPointer<KeyPressInteractorStyle> style =
>>>>     vtkSmartPointer<KeyPressInteractorStyle>::New();
>>>>
>>>>
>>>> this->ui->view1->GetRenderWindow()->GetInteractor()->SetInteractorStyle(style);
>>>>         style->SetCurrentRenderer(riw[0]->GetRenderer());
>>>>
>>>>         this->ui->view1->SetRenderWindow(riw[0]->GetRenderWindow());
>>>>
>>>> riw[0]->SetupInteractor(this->ui->view1->GetRenderWindow()->GetInteractor());
>>>>
>>>> where view1 is of type QVTKWidget  and riw[i] of type
>>>> vtkResliceImageViewer.
>>>>
>>>> Unfortunately the approach I am using has no effect. The keyboard
>>>> events are not captured at all by the interaction style. Nothing is printed
>>>> in the console. It should be noted that if I apply the customised style on
>>>> the 4th view for vtkImagePlaneWidgets, then it works.
>>>>
>>>> Can someone help me to fix this? I am new to VTK and any help will be
>>>> much appreciated.
>>>>
>>>> Thanks for your help,
>>>>
>>>> _______________________________________________
>>>> Powered by www.kitware.com
>>>>
>>>> Visit other Kitware open-source projects at
>>>> http://www.kitware.com/opensource/opensource.html
>>>>
>>>> Please keep messages on-topic and check the VTK FAQ at:
>>>> http://www.vtk.org/Wiki/VTK_FAQ
>>>>
>>>> Follow this link to subscribe/unsubscribe:
>>>> http://www.vtk.org/mailman/listinfo/vtkusers
>>>>
>>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.vtk.org/pipermail/vtkusers/attachments/20130911/2d1e1a6a/attachment.htm>


More information about the vtkusers mailing list