From c0280e28ca18686c0f67dc23bb29ec4bc2ee58ca Mon Sep 17 00:00:00 2001 From: James Petts Date: Tue, 13 Oct 2020 14:00:01 +0100 Subject: [PATCH] Bring in rotatable crosshairs. (#2101) * Bring in rotatable crosshairs. * Pull in react-vtkjs-viewport 0.13.1 fix. --- extensions/vtk/package.json | 2 +- extensions/vtk/src/commandsModule.js | 67 +++++++++++++++++++++------- extensions/vtk/src/toolbarModule.js | 11 ++++- yarn.lock | 17 +++---- 4 files changed, 72 insertions(+), 25 deletions(-) diff --git a/extensions/vtk/package.json b/extensions/vtk/package.json index cb98b4172..1e41e71c3 100644 --- a/extensions/vtk/package.json +++ b/extensions/vtk/package.json @@ -50,7 +50,7 @@ "dependencies": { "@babel/runtime": "^7.5.5", "lodash.throttle": "^4.1.1", - "react-vtkjs-viewport": "^0.10.4" + "react-vtkjs-viewport": "^0.13.1" }, "devDependencies": { "@ohif/core": "^2.10.7", diff --git a/extensions/vtk/src/commandsModule.js b/extensions/vtk/src/commandsModule.js index e2b110c42..9e5100277 100644 --- a/extensions/vtk/src/commandsModule.js +++ b/extensions/vtk/src/commandsModule.js @@ -1,9 +1,9 @@ import throttle from 'lodash.throttle'; import { - vtkInteractorStyleMPRCrosshairs, vtkInteractorStyleMPRWindowLevel, + vtkInteractorStyleRotatableMPRCrosshairs, + vtkSVGRotatableCrosshairsWidget, vtkInteractorStyleMPRRotate, - vtkSVGCrosshairsWidget, } from 'react-vtkjs-viewport'; import { getImageData } from 'react-vtkjs-viewport'; import { vec3 } from 'gl-matrix'; @@ -11,7 +11,6 @@ import setMPRLayout from './utils/setMPRLayout.js'; import setViewportToVTK from './utils/setViewportToVTK.js'; import Constants from 'vtk.js/Sources/Rendering/Core/VolumeMapper/Constants.js'; import OHIFVTKViewport from './OHIFVTKViewport'; -import vtkCoordinate from 'vtk.js/Sources/Rendering/Core/Coordinate'; const { BlendMode } = Constants; @@ -119,6 +118,14 @@ const commandsModule = ({ commandsManager }) => { getVtkApis: ({ index }) => { return apis[index]; }, + resetMPRView() { + apis.forEach(api => { + api.resetOrientation(); + }); + + // Reset the crosshairs + apis[0].svgWidgets.rotatableCrosshairsWidget.resetCrosshairs(apis, 0); + }, axial: async ({ viewports }) => { const api = await _getActiveViewportVTKApi(viewports); @@ -165,7 +172,7 @@ const commandsModule = ({ commandsManager }) => { segmentNumber, frameIndex, frame, - done = () => { } + done = () => {}, }) => { let api = apis[viewports.activeViewportIndex]; @@ -180,10 +187,13 @@ const commandsModule = ({ commandsManager }) => { displaySetInstanceUID, SOPClassUID, SOPInstanceUID, - frameIndex, + frameIndex ); - const imageDataObject = getImageData(stack.imageIds, displaySetInstanceUID); + const imageDataObject = getImageData( + stack.imageIds, + displaySetInstanceUID + ); let pixelIndex = 0; let x = 0; @@ -209,9 +219,12 @@ const commandsModule = ({ commandsManager }) => { y /= count; const position = [x, y, frameIndex]; - const worldPos = _convertModelToWorldSpace(position, imageDataObject.vtkImageData); + const worldPos = _convertModelToWorldSpace( + position, + imageDataObject.vtkImageData + ); - api.svgWidgets.crosshairsWidget.moveCrosshairs(worldPos, apis); + api.svgWidgets.rotatableCrosshairsWidget.moveCrosshairs(worldPos, apis); done(); }, setSegmentationConfiguration: async ({ @@ -254,21 +267,35 @@ const commandsModule = ({ commandsManager }) => { await Promise.all(promises); }, enableRotateTool: () => { - apis.forEach(api => { + apis.forEach((api, apiIndex) => { const istyle = vtkInteractorStyleMPRRotate.newInstance(); - api.setInteractorStyle({ istyle }); + api.setInteractorStyle({ istyle, configuration: { apis, apiIndex } }); }); }, enableCrosshairsTool: () => { apis.forEach((api, apiIndex) => { - const istyle = vtkInteractorStyleMPRCrosshairs.newInstance(); + const istyle = vtkInteractorStyleRotatableMPRCrosshairs.newInstance(); api.setInteractorStyle({ istyle, - configuration: { apis, apiIndex }, + configuration: { + apis, + apiIndex, + uid: api.uid, + }, }); }); + + const rotatableCrosshairsWidget = + apis[0].svgWidgets.rotatableCrosshairsWidget; + + const referenceLines = rotatableCrosshairsWidget.getReferenceLines(); + + // Initilise crosshairs if not initialised. + if (!referenceLines) { + rotatableCrosshairsWidget.resetCrosshairs(apis, 0); + } }, enableLevelTool: () => { function updateVOI(apis, windowWidth, windowCenter) { @@ -391,18 +418,24 @@ const commandsModule = ({ commandsManager }) => { // Add widgets and set default interactorStyle of each viewport. apis.forEach((api, apiIndex) => { api.addSVGWidget( - vtkSVGCrosshairsWidget.newInstance(), - 'crosshairsWidget' + vtkSVGRotatableCrosshairsWidget.newInstance(), + 'rotatableCrosshairsWidget' ); const uid = api.uid; - const istyle = vtkInteractorStyleMPRCrosshairs.newInstance(); + const istyle = vtkInteractorStyleRotatableMPRCrosshairs.newInstance(); api.setInteractorStyle({ istyle, configuration: { apis, apiIndex, uid }, }); + + api.svgWidgets.rotatableCrosshairsWidget.setApiIndex(apiIndex); + api.svgWidgets.rotatableCrosshairsWidget.setApis(apis); }); + + // Initialise crosshairs + apis[0].svgWidgets.rotatableCrosshairsWidget.resetCrosshairs(apis, 0); }, }; @@ -456,6 +489,10 @@ const commandsModule = ({ commandsManager }) => { commandFn: actions.enableLevelTool, options: {}, }, + resetMPRView: { + commandFn: actions.resetMPRView, + options: {}, + }, setBlendModeToComposite: { commandFn: actions.setBlendModeToComposite, options: { blendMode: BlendMode.COMPOSITE_BLEND }, diff --git a/extensions/vtk/src/toolbarModule.js b/extensions/vtk/src/toolbarModule.js index 9cfa49f63..7cdfd5c38 100644 --- a/extensions/vtk/src/toolbarModule.js +++ b/extensions/vtk/src/toolbarModule.js @@ -25,6 +25,15 @@ const definitions = [ commandName: 'enableLevelTool', commandOptions: {}, }, + { + id: 'Reset', + label: 'Reset', + icon: 'reset', + // + type: TOOLBAR_BUTTON_TYPES.COMMAND, + commandName: 'resetMPRView', + commandOptions: {}, + }, { id: 'Rotate', label: 'Rotate', @@ -131,4 +140,4 @@ const definitions = [ export default { definitions, defaultContext: 'ACTIVE_VIEWPORT::VTK', -} +}; diff --git a/yarn.lock b/yarn.lock index dae2593c1..ab705ed9a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6539,13 +6539,14 @@ dateformat@^3.0.0: resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== -dcmjs@0.16.3: - version "0.16.3" - resolved "https://registry.yarnpkg.com/dcmjs/-/dcmjs-0.16.3.tgz#ef44ccc4988a473fd40e1601122c57f2babded11" - integrity sha512-pMQGifMpMW9i9ufCdUoEPHrLWnm6ilnpfLqUc+PPoWr7OnuBhiRVRunbv39oTtFDZOLhQ2Ampm7UrkidWAbqiA== +dcmjs@0.16.5: + version "0.16.5" + resolved "https://registry.yarnpkg.com/dcmjs/-/dcmjs-0.16.5.tgz#05aa0c8d539a4d5777f996b9b796932d1f848993" + integrity sha512-Y92KAx4JSfev79xjYhaukQZjWgyJlaHnXSTdbtkGkJAHERjIakgHcCIPmACuVmtW/nHViTu04zIGAB0pmZ4GaA== dependencies: "@babel/polyfill" "^7.8.3" "@babel/runtime" "^7.8.4" + gl-matrix "^3.1.0" loglevelnext "^3.0.1" ndarray "^1.0.19" @@ -16060,10 +16061,10 @@ react-transition-group@^4.1.1: loose-envify "^1.4.0" prop-types "^15.6.2" -react-vtkjs-viewport@^0.10.4: - version "0.10.4" - resolved "https://registry.yarnpkg.com/react-vtkjs-viewport/-/react-vtkjs-viewport-0.10.4.tgz#eb038b0bf5c384bd3b45f2a0a57f52c682607fea" - integrity sha512-J1WxwHbjlttEWvdkM33DJx8QxHr3J7HR6wFSDVBDKY7McK2lwDAdRN8wSqy2BVNILlyurUUVwg2tK2txiJ+tuw== +react-vtkjs-viewport@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/react-vtkjs-viewport/-/react-vtkjs-viewport-0.13.1.tgz#11b69873377cd66b6522079eb05d54317c2e8903" + integrity sha512-P2jmv0rZtas9+pZCzVBr0R/EqmXpWqPP8JA1DScwKgFoYj4ApqnQeLXSVz2VHXi58q87k2uay9k7xcchLiStrQ== dependencies: date-fns "^2.2.1" gl-matrix "^3.1.0"