View component refactoring

From IGSTK

Jump to: navigation, search

Contents

Introduction

This page presents a proposal for refactorization of the view component of the IGSTK toolkit.

Overview of view components

View classes encapsulate VTK classes into a restrictive API subjected to control of a state machine. Viewers aggregate graphical descriptions of spatial objects (spatial object representations) into a single coherent scene. Furthermore, the view classes handle GUI specific interactions.

Motivation for refactoring

Current implementation of the View class in the main CVS repository is FLTK-specific. Hence, IGSTK users have been forced to download and install FLTK library to run the example applications. Recently view classes for QT library have been implemented and added to the sandbox. These classes are totally independent of the FLTK-specific view classes even though most of the code is the same. The view classes for FLTK and QT library are not cleanly integrated making it difficult for users to switch easily between these libraries for application development. Furthermore, the current architecture is not suitable to extend the toolkit to handle other GUI libraries.

Old architecture

FTLK-specific view classes in CVS

QT specific view classes in the sandbox

New architecture

The fundamental design principle of the new architecture is separating the two main functions of the view components

  • Aggregating graphical representations of the spatial objects ( Function 1 )
  • Handling GUI interaction ( Function 2)


igstkView will contain implementations ONLY related to Function 1 ( representation aggregation ). All GUI related implementations will be moved to GUI specific class.



FLTK specific widget class :


QT specific widget class  :


The GUI specific widgets and igstkView class will have a "has a" object hierarchical relationship. The widgets will contain view object that will be set using public methods under a state machine control.

Object factory pattern mechanism will be used to create the appropriate widget instance based on a CMake option for a choice of a GUI library.

Miscellaneous issues with view components

There have been requests by users for methods to modify the camera parameters. Request set methods will be added for this purpose.

Implementation plan

  • Until the implementation of the new architecture is completed, the old view classes will be available. CMake configuration

will be provided to switch between the two architectures until code review is finalized and code is approved and moved to CVS.

  • Nightly dashboards with QT, FLTK and without a GUI library will be set up.
  • Example applications will be implemented using both QT and FLTK for demonstration purposes.

Comments

  1. Can there be a situation where the view needs to update the GUI? If so, will this be event driven, so that the GUI not only has a "has a" (no pun intended) relationship with the view it is also observing the view. (ZY)
  2. We might need to develop a new View class that can change the camera position, as described by Luis in Talk:ImageSliceRepresentation#About_Questions (PC)
  • Andinet: Having read the requirements and design specifications for ImageSliceRepresentation, I agree with you that having a separate view class that observes camera information from the representation class will be necessary

Suggestions by Torleif

I have gathered that you are working on refactoring the View components, and have some requests in that regard. My points are mostly feature requests, so they may not necessarily be tied to the view refactoring, but I wanted to make sure the new design at least doesn't rule out any of the functionality we desire.

Our application needs to display axial, sagittal and coronal representations of a spatial objects in igstkQView2d objects. Igstk provides this functionality but in addition to what is currently possible we want to:

1. Add a crosshair to an igstqview2d viewport for each view that shows and governs the slice index of the other two representations. I tried adding a 2d actor with an object/representation pair, but that resulted in a runtimefailure as igstk code relies on spatialobject representation actors to be subclasses of vtkActor3d. I now have a 3D actor generated fron vtkLineSource, but this suffers from other drawbacks: camera repositoning seems to clip the object so that it becomes invisible, the lines donot extend all the way across the viewport.

What I think we need is something along the lines of annotation2d, but this requires a methd in the view class as well. Could this be done or do you think there is another way to achieve this.

2. Be able to specify that the imagerepresentation should fill the whole view. Screen real-estate is expensive. The current situation in the view positions the camera in a postion that wastes space. Additionally, there is no way for clients to control the camera.

3. Have better camera control. When the slice of an imagerepresentation changes, it seems the representation goes beyond some clipping plane. To solve this, I do RequestResetCamera() each time I change slice. Can this be done in another way, or could the view class provide better control over the camera?

4. Generate transform events from Qt mousemove events for the continouous updating of our acs slices.

I implemented void mouseMoveEvent(QMouseEvent* e) in igstkQView like this:

  void QView::mouseMoveEvent(QMouseEvent *e)
  {
   vtkRenderWindowInteractor* iren = NULL;
   if(this->mRenWin)
   {
       iren = this->mRenWin->GetInteractor();
   }
   if(!iren || !iren->GetEnabled())
   {
       return;
   }
   // give vtk event information
   #if QT_VERSION < 0x040000
   iren->SetEventInformationFlipY(e->x(), e->y(),
                                  (e->state() & Qt::ControlButton)  > 0 ? 1 : 0,
                                  (e->state() & Qt::ShiftButton ) >  0 ? 1 : 0);
   #else
   iren->SetEventInformationFlipY(e->x(), e->y(),
                                  (e->modifiers() &  Qt::ControlModifier) > 0 ? 1 : 0,
                                  (e->modifiers() &  Qt::ShiftModifier ) > 0 ? 1 : 0);
   #endif
   if(e->buttons() == Qt::LeftButton)
   {
       iren->InvokeEvent(vtkCommand::MouseMoveEvent, e);
       // Get x,y,z in world coordinates from the clicked point
       m_PointPicker->Pick(e->x(), this->height() - e->y() - 1, 0,  m_Renderer);
       double data[3];
       m_PointPicker->GetPickPosition(data);
       igstk::Transform::VectorType pickedPoint;
       pickedPoint[0] = data[0];
       pickedPoint[1] = data[1];
       pickedPoint[2] = data[2];
       double validityTime = itk::NumericTraits<double>::max(); //  Valid unitl next click
       double errorValue = 1.0; // @TODO: Should be obtained from  picked object.
       igstk::Transform transform;
       transform.SetTranslation(pickedPoint, errorValue,  validityTime);
       igstk::TransformModifiedEvent transformEvent;
       transformEvent.Set(transform);
       m_Reporter->InvokeEvent(transformEvent);
   }
 }
Personal tools
TOOLBOX
LANGUAGES