Back to Projects List
Tool Framework for react-vtkjs-viewport.
- James A Petts (Radical Imaging, Ovela Solutions)
- Danny Brown (Radical Imaging) - Remote
- Erik Ziegler (Radical Imaging)
The react-vtkjs-viewport
library is a wrapper around vtk.js
with the idea that it should become a really simple way to get quickly get past the boilerplate required to use vtk-js in a react application.
There have been improvements to loading, rendering and segmentation display, but an extensible tool framework in the vein of cornerstoneTools is severly lacking.
Clear objectives:
- Refactor the current
interactorStyle
s to a set of manipulators and a single configurableinteractorStyle
, where "tool load-outs" can be set via configuration in the constructor (See this)[https://kitware.github.io/vtk-js/examples/InteractorStyleManipulator.html]. - Refactor the crosshairs to be less of "annotation" and more of reference line tool that is calculated every render based on a single world position as its centre.
Open questions:
- How do we deal with 2D annotations?
a) Can we shoehorn the
cornerstoneTools
canvas over thevtk.js
viewport and rewrite the rendering routine.- Annotations would be 2D, project them onto the screen?
- When do we render them?
b) Annotations exist as 3D objects in
vtk.js
, and we write a render hook to re-render all of these as SVG projected onto the display coordinates of the device, with a similar "invalidated" pattern tocornerstoneTools
.
- Should "
vtkjs-tools
" be its own repo? Are we shovelling too much into react-vtkjs-viewport that could be used elsewhere? Is this important enough to be formalized in vtk.js itself?
- Discuss the above open questions.
- Work on the clear objectives.
- Work on any objectives derived from (1.).
Progress:
- Prior to this week we had one interactor style called
vtkInteractorStyleMPRSlice
with hard-coded key bindings. Two classes inherited from this class and overrode some functionality:vtkInteractorStyleMPRRotate
andvtkInteractorStyleMPRCrosshairs
. These classes were non extensible. - Refactor all common private functionality to a base class
vtkjsToolsBaseInteractorStyle
. - Refactor each seperate "tool" into a manipulator that can easily be registered to any binding of the interactorStyle.
- vtkjsToolsMPRPanManipulator
- vtkjsToolsMPRRotateManipulator
- vtkjsToolsMPRScrollManipulator
- vtkjsToolsMPRWindowLevelManipulator
- vtkjsToolsMPRZoomManipulator
-
Make appropriate events fire to an eventWindow on the viewport. The eventWindow can be interacted with internally or accessed through the react-vtkjs-viewport's API, allowing a parent application to consume and react to these events.
-
Most importantly an imageRendered event is fired when the viewport changes in a way that means the theoretical annotation layer (TBC) knows when to trigger an update.
-
Also fixed a texture generation issue on painting segmentations in 3D in apps sharing data between cornerstone and vtkjs. cornerstonejs/cornerstoneTools#1167
Next Steps:
- Build an event dispatcher to call re-render events on any SVG annotations introduced by widgets.
- Tie svg widgets to specific manipualtors, building an analog to
BaseAnnotationTool
fromcornerstoneTools
. - Reimplement crosshairs as a manipulator + svgWidget pair as the first example of the above.
The tool loadouts can be switched by instantiating an interactorStyle with a new loadout, in the example:
// Layout 1:
const istyle = vtkjsToolsInteractorStyleManipulator.newInstance({
manipulators: [
{
vtkManipulatorMixin: vtkMPRWindowLevelManipulatorMixin,
type: INTERACTION_TYPES.MOUSE,
configuration: { button: 1 },
},
{
vtkManipulatorMixin: vtkMPRPanManipulatorMixin,
type: INTERACTION_TYPES.MOUSE,
configuration: { button: 2 },
},
{
vtkManipulatorMixin: vtkMPRZoomManipulatorMixin,
type: INTERACTION_TYPES.MOUSE,
configuration: { button: 3 },
},
{
vtkManipulatorMixin: vtkMPRScrollManipulatorMixin,
type: INTERACTION_TYPES.MOUSE,
configuration: {
scrollEnabled: true,
dragEnabled: false,
},
},
],
});
api.setInteractorStyle({ istyle });
// Layout 2
const istyle = vtkjsToolsInteractorStyleManipulator.newInstance({
manipulators: [
{
vtkManipulatorMixin: vtkMPRRotateManipulatorMixin,
type: INTERACTION_TYPES.MOUSE,
configuration: { button: 1 },
},
{
vtkManipulatorMixin: vtkMPRScrollManipulatorMixin,
type: INTERACTION_TYPES.MOUSE,
configuration: {
scrollEnabled: true,
dragEnabled: false,
},
},
],
});
api.setInteractorStyle({ istyle });