From 9f67ecab550a0d443fe49e3855dcce37af84a609 Mon Sep 17 00:00:00 2001 From: Erik Ziegler Date: Mon, 17 Jun 2019 14:23:03 +0200 Subject: [PATCH] @ohif/extension-vtk: Enable crosshairs display on viewports (0.0.6) --- extensions/ohif-vtk-extension/package.json | 17 ++-- extensions/ohif-vtk-extension/src/commands.js | 70 ++++++++++----- extensions/ohif-vtk-extension/yarn.lock | 86 ++++++++++--------- 3 files changed, 104 insertions(+), 69 deletions(-) diff --git a/extensions/ohif-vtk-extension/package.json b/extensions/ohif-vtk-extension/package.json index 5ad4832d8..b1728497c 100644 --- a/extensions/ohif-vtk-extension/package.json +++ b/extensions/ohif-vtk-extension/package.json @@ -1,6 +1,6 @@ { "name": "@ohif/extension-vtk", - "version": "0.0.5", + "version": "0.0.6", "description": "OHIF extension for VTK.js", "author": "OHIF", "license": "MIT", @@ -21,17 +21,17 @@ }, "peerDependencies": { "@ohif/i18n": "0.0.4", - "i18next": "^17.0.3", - "i18next-browser-languagedetector": "^3.0.1", - "react-i18next": "^10.11.0", "cornerstone-core": "^2.2.8", "cornerstone-wado-image-loader": "^2.2.3", "dcmjs": "^0.4.7", "dicom-parser": "^1.8.3", + "i18next": "^17.0.3", + "i18next-browser-languagedetector": "^3.0.1", "ohif-core": "^0.5.9", "prop-types": "^15.7.2", "react": "^16.8.6", "react-dom": "^16.8.6", + "react-i18next": "^10.11.0", "react-redux": "^7.1.0", "react-resize-detector": "^4.2.0", "react-viewerbase": "^0.8.1", @@ -44,9 +44,6 @@ "@babel/plugin-transform-runtime": "^7.4.4", "@babel/preset-env": "^7.4.5", "@babel/preset-react": "^7.0.0", - "i18next": "^17.0.3", - "i18next-browser-languagedetector": "^3.0.1", - "react-i18next": "^10.11.0", "babel-eslint": "^10.0.1", "babel-loader": "^8.0.6", "cornerstone-tools": "^3.13.0", @@ -61,11 +58,14 @@ "eslint-plugin-react": "^7.13.0", "gh-pages": "^2.0.1", "husky": "^2.4.1", + "i18next": "^17.0.3", + "i18next-browser-languagedetector": "^3.0.1", "lint-staged": "^8.2.0", "ohif-core": "^0.5.9", "prettier": "^1.18.2", "react": "^16.6.3", "react-dom": "^16.6.3", + "react-i18next": "^10.11.0", "react-redux": "^7.1.0", "react-viewerbase": "^0.8.1", "redux": "^4.0.1", @@ -104,6 +104,7 @@ "dependencies": { "@babel/runtime": "^7.4.5", "@ohif/i18n": "0.0.4", - "react-vtkjs-viewport": "0.0.8" + "react-vtkjs-viewport": "0.0.9", + "vtk.js": "^8.9.1" } } diff --git a/extensions/ohif-vtk-extension/src/commands.js b/extensions/ohif-vtk-extension/src/commands.js index 52a7042aa..19cf396c8 100644 --- a/extensions/ohif-vtk-extension/src/commands.js +++ b/extensions/ohif-vtk-extension/src/commands.js @@ -1,13 +1,16 @@ import { vtkInteractorStyleMPRWindowLevel, vtkInteractorStyleMPRSlice, - vtkInteractorStyleMPRCrosshairs + vtkInteractorStyleMPRCrosshairs, + vtkSVGCrosshairsWidget, + vtkSVGWidgetManager } from 'react-vtkjs-viewport'; import setViewportToVTK from './utils/setViewportToVTK.js'; import setMPRLayout from './utils/setMPRLayout.js'; import vtkMath from 'vtk.js/Sources/Common/Core/Math'; import vtkMatrixBuilder from 'vtk.js/Sources/Common/Core/MatrixBuilder'; +import vtkCoordinate from 'vtk.js/Sources/Rendering/Core/Coordinate'; // TODO: Should be another way to get this const commandsManager = window.commandsManager; @@ -16,32 +19,41 @@ const commandsManager = window.commandsManager; let apis = {}; function getCrosshairCallbackForIndex(index) { - return worldPos => { + return ({worldPos}) => { // Set camera focal point to world coordinate for linked views apis.forEach((api, viewportIndex) => { - if (viewportIndex === index) { - return; + if (viewportIndex !== index) { + // We are basically doing the same as getSlice but with the world coordinate + // that we want to jump to instead of the camera focal point. + // I would rather do the camera adjustment directly but I keep + // doing it wrong and so this is good enough for now. + const renderWindow = api.genericRenderWindow.getRenderWindow(); + + const istyle = renderWindow.getInteractor().getInteractorStyle(); + const sliceNormal = istyle.getSliceNormal(); + const transform = vtkMatrixBuilder + .buildFromDegree() + .identity() + .rotateFromDirections(sliceNormal, [1, 0, 0]); + + const mutatedWorldPos = worldPos.slice(); + transform.apply(mutatedWorldPos); + const slice = mutatedWorldPos[0]; + + istyle.setSlice(slice); + + renderWindow.render(); } - // We are basically doing the same as getSlice but with the world coordinate - // that we want to jump to instead of the camera focal point. - // I would rather do the camera adjustment directly but I keep - // doing it wrong and so this is good enough for now. - const renderWindow = api.genericRenderWindow.getRenderWindow(); - const istyle = renderWindow.getInteractor().getInteractorStyle(); - const sliceNormal = istyle.getSliceNormal(); - const transform = vtkMatrixBuilder - .buildFromDegree() - .identity() - .rotateFromDirections(sliceNormal, [1, 0, 0]); + const renderer = api.genericRenderWindow.getRenderer(); + const wPos = vtkCoordinate.newInstance(); + wPos.setCoordinateSystemToWorld(); + wPos.setValue(worldPos); - const mutatedWorldPos = worldPos.slice(); - transform.apply(mutatedWorldPos); - const slice = mutatedWorldPos[0]; - - istyle.setSlice(slice); - - renderWindow.render(); + const displayPosition = wPos.getComputedDisplayValue(renderer); + const { svgWidgetManager } = api; + api.svgWidgets.crosshairsWidget.setPoint(displayPosition[0], displayPosition[1]); + svgWidgetManager.render(); }); }; } @@ -207,6 +219,20 @@ const actions = { istyle.setVolumeMapper(api.volumes[0]); istyle.setCallback(getCrosshairCallbackForIndex(index)); + const svgWidgetManager = vtkSVGWidgetManager.newInstance(); + svgWidgetManager.setRenderer(renderer); + svgWidgetManager.setScale(1); + + const crosshairsWidget = vtkSVGCrosshairsWidget.newInstance(); + + svgWidgetManager.addWidget(crosshairsWidget); + svgWidgetManager.render(); + + api.svgWidgetManager = svgWidgetManager; + api.svgWidgets = { + crosshairsWidget + }; + switch (index) { default: case 0: diff --git a/extensions/ohif-vtk-extension/yarn.lock b/extensions/ohif-vtk-extension/yarn.lock index 8098a6707..9051ced37 100644 --- a/extensions/ohif-vtk-extension/yarn.lock +++ b/extensions/ohif-vtk-extension/yarn.lock @@ -755,7 +755,7 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== -"@ohif/i18n@0.0.4": +"@ohif/i18n@0.0.4", "@ohif/i18n@^0.0.4": version "0.0.4" resolved "https://registry.yarnpkg.com/@ohif/i18n/-/i18n-0.0.4.tgz#e54176e7799e311dbaff37995f9d2745b58cbd0f" integrity sha512-lW+S9weZbJS300yCRR8Ygb1KTULbD1Qx5ZGcYUXyseJIWr5jeJ4V/6FdS30w8u8ejiIVwF8rYOguHsmueQrkdw== @@ -1843,21 +1843,11 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= -cornerstone-core@^2.2.8: - version "2.2.8" - resolved "https://registry.yarnpkg.com/cornerstone-core/-/cornerstone-core-2.2.8.tgz#5f10c65c80f8efa7623ee1dd5c9a9d4605f5467c" - integrity sha512-iJrmfXy1nvM4ZLTJawif2VYBPq8APQ1GYjRbUZAJPNqPYmfYfKWkToVyf9o/i8GMl81op7xLJ4ib3ZMSINKjjQ== - cornerstone-math@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/cornerstone-math/-/cornerstone-math-0.1.7.tgz#7c55536f02e7221b05fc49a4c780bb82c234ce39" integrity sha512-svsDSoqLNFM9niCV2AtV2DNmRkYztT1v80lVdbA5hkgdGdpWg5/h2On794zbqBK+aI3hNOHufERDsI4wdXGknA== -cornerstone-math@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/cornerstone-math/-/cornerstone-math-0.1.8.tgz#68ab1f9e4fdcd7c5cb23a0d2eb4263f9f894f1c5" - integrity sha512-x7NEQHBtVG7j1yeyj/aRoKTpXv1Vh2/H9zNLMyqYJDtJkNng8C4Q8M3CgZ1qer0Yr7eVq2x+Ynmj6kfOm5jXKw== - cornerstone-tools@^3.13.0: version "3.13.0" resolved "https://registry.yarnpkg.com/cornerstone-tools/-/cornerstone-tools-3.13.0.tgz#c198f7d1a500e76db5fb5b0bd2ddeaf1a9a09160" @@ -2151,6 +2141,15 @@ dnd-core@^7.0.2: invariant "^2.2.4" redux "^4.0.1" +dnd-core@^7.4.4: + version "7.6.0" + resolved "https://registry.yarnpkg.com/dnd-core/-/dnd-core-7.6.0.tgz#5907ca291bdcf6dce98322e4d0937efe1b167e85" + integrity sha512-JboJ8BKh5nsW2KXbhCY1SzYV+vV3TlQQzgOEtB4IyYbefkhSOwG8wOgcyTD95TyypPaCh8nqxrrRTEC1c8rVMA== + dependencies: + asap "^2.0.6" + invariant "^2.2.4" + redux "^4.0.1" + doctrine@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" @@ -4324,7 +4323,7 @@ mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0: dependencies: minimist "0.0.8" -moment@2.24.0, moment@>=1.6.0: +moment@2.24.0, moment@>=1.6.0, moment@^2.24.0: version "2.24.0" resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b" integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg== @@ -4664,10 +4663,10 @@ object.values@^1.0.4, object.values@^1.1.0: function-bind "^1.1.1" has "^1.0.3" -ohif-core@^0.5.8: - version "0.5.8" - resolved "https://registry.yarnpkg.com/ohif-core/-/ohif-core-0.5.8.tgz#d2feab1c2c8440464123318aca8d55e9f228d51e" - integrity sha512-yI4nq1Vxi8CVno6codLJttjiyPkmjjYIl12QcAGDGmpYcLt2LopOCLZ2M2eeJbxt8yfh5nwSYMcjC3cYIr6C9A== +ohif-core@^0.5.9: + version "0.5.9" + resolved "https://registry.yarnpkg.com/ohif-core/-/ohif-core-0.5.9.tgz#337835c82571bdc4935210273a6018c3af872adf" + integrity sha512-TvA/THiTpBnerRbv4FJlfwSMSyb4Tkn40ud14FP6JxLUQgCtLsTsaFhXIFBwZvBR/qVJwIlDluMxj/vqobCwkQ== dependencies: "@babel/runtime" "^7.2.0" ajv "^6.10.0" @@ -5341,13 +5340,13 @@ react-dates@18.4.1: react-with-styles "^3.2.0" react-with-styles-interface-css "^4.0.2" -react-dnd-html5-backend@7.0.2: - version "7.0.2" - resolved "https://registry.yarnpkg.com/react-dnd-html5-backend/-/react-dnd-html5-backend-7.0.2.tgz#f74181ca0ff05be13eb6094629c5ad560f558a7e" - integrity sha512-BPhmHeQjvhPXRykHvFLbM+TJFrrarcuf/mIArNEmXzZuNhLfbOnHtMSzR8lPwodABcDAYj7hEF7vTABXX298vA== +react-dnd-touch-backend@^0.8.3: + version "0.8.3" + resolved "https://registry.yarnpkg.com/react-dnd-touch-backend/-/react-dnd-touch-backend-0.8.3.tgz#85d961ec8578dc9efa5b78000ea904d37e01e60f" + integrity sha512-LLJlpeJftRreP9ixm3yfd1JEXf+6BeKo5dkfJFHvNSOEOu+FDSwNl5l8uAG0FeD4z2ZVi7RDQ/jUxdjkBV3zBg== dependencies: - dnd-core "^7.0.2" - lodash "^4.17.11" + dnd-core "^7.4.4" + invariant "^2.2.4" react-dnd@7.0.2: version "7.0.2" @@ -5448,30 +5447,32 @@ react-transition-group@^2.0.0, react-transition-group@^2.2.0: prop-types "^15.6.2" react-lifecycles-compat "^3.0.4" -react-viewerbase@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/react-viewerbase/-/react-viewerbase-0.7.0.tgz#b0f48a0f003b849c280b8ca67927d4780c68b0dc" - integrity sha512-1VQXREKSsqxtOSSHRou0gjBODrSOjE8SBJ6/dHG0gPgdmeotOg68xPMKYf9K7fYyGZ6CDA7oVCAmdTE4SVYP5Q== +react-viewerbase@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/react-viewerbase/-/react-viewerbase-0.8.1.tgz#bba780906e9eb6aff0cdf73728e61d348986643c" + integrity sha512-YTwcAAZE2zv6JATeEHOzAFsupzFYrvSp+HlrLs8AOQhZv1JkF8itjof0N3Os03jT5vh7lLhk3GHhInSE9wwYQw== dependencies: "@babel/runtime" "7.2.0" + "@ohif/i18n" "^0.0.4" classnames "2.2.6" + i18next "^17.0.3" + i18next-browser-languagedetector "^3.0.1" lodash.isequal "4.5.0" moment "2.24.0" prop-types "15.6.2" react-bootstrap-modal "4.2.0" react-dates "18.4.1" react-dnd "7.0.2" - react-dnd-html5-backend "7.0.2" + react-dnd-touch-backend "^0.8.3" + react-i18next "^10.11.0" react-with-direction "1.3.0" -react-vtkjs-viewport@^0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/react-vtkjs-viewport/-/react-vtkjs-viewport-0.0.7.tgz#8fcb3adfc6609d6e3fc6d5af94d59cb1ec4426c0" - integrity sha512-rlum/DCr5hwX4CcWXOG4HuMeD3c5ebU7eWhQRhetfcmljatCMt1oKctt+JLqllvSrpzr8lHpRG95Ek2KH12JEA== +react-vtkjs-viewport@0.0.9: + version "0.0.9" + resolved "https://registry.yarnpkg.com/react-vtkjs-viewport/-/react-vtkjs-viewport-0.0.9.tgz#da79aa66f52dcd731bcc5abd2587cbb120a25331" + integrity sha512-VwRCY2DPxWMhix4v3PAtdENp3U1p+Z9nKf1Ch5+KWRKF6fWeA+B2glYKMYNpPnP4bULzVz9iwV+Zeojt3gEibA== dependencies: - cornerstone-core "^2.2.8" - cornerstone-math "^0.1.8" - vtk.js "^8.3.11" + moment "^2.24.0" react-with-direction@1.3.0, react-with-direction@^1.3.0: version "1.3.0" @@ -5828,7 +5829,14 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.1.6, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.11.0, resolve@^1.3.2, resolve@^1.5.0, resolve@^1.8.1: +resolve@^1.1.6: + version "1.11.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.0.tgz#4014870ba296176b86343d50b60f3b50609ce232" + integrity sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw== + dependencies: + path-parse "^1.0.6" + +resolve@^1.10.0, resolve@^1.10.1, resolve@^1.11.0, resolve@^1.3.2, resolve@^1.5.0, resolve@^1.8.1: version "1.11.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.1.tgz#ea10d8110376982fef578df8fc30b9ac30a07a3e" integrity sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw== @@ -6945,10 +6953,10 @@ void-elements@^2.0.1: resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w= -vtk.js@^8.3.11: - version "8.6.2" - resolved "https://registry.yarnpkg.com/vtk.js/-/vtk.js-8.6.2.tgz#68ca868c5a349a6516e8ce8ef1d0bb740b4c92e1" - integrity sha512-9Ln72K9Tv+tEbEpSHx+UcGea2vTgNh0krHtOL9IGWeYVn9iXY1WGx/o8zzio0hTo6XIJ7Iam5tkR03Yn13URIg== +vtk.js@^8.9.1: + version "8.9.1" + resolved "https://registry.yarnpkg.com/vtk.js/-/vtk.js-8.9.1.tgz#db49e869fbf61e4d6ca71a8a61f9092bc5fa39f7" + integrity sha512-sxQ/kFXQTVp2bzRhnSwOXlODWL0vlBkZ3X+SKW+G3ZmGDmncFGkjS5yXhTJFLBp2LVvYnqQiA8z4AeE6XrhkSg== dependencies: base64-js "1.2.1" blueimp-md5 "2.10.0"