@ohif/extension-vtk: Add basic MIP and Slab Thickness controls. UI to be updated later (#685)

This commit is contained in:
Erik Ziegler 2019-07-18 13:39:00 +02:00 committed by GitHub
parent 2fd60f3109
commit d8b4a4d4c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 162 additions and 37 deletions

View File

@ -1,6 +1,6 @@
{
"name": "@ohif/extension-vtk",
"version": "0.1.4",
"version": "0.1.5",
"description": "OHIF extension for VTK.js",
"author": "OHIF",
"license": "MIT",
@ -39,7 +39,7 @@
},
"dependencies": {
"@babel/runtime": "^7.4.5",
"react-vtkjs-viewport": "0.0.10",
"react-vtkjs-viewport": "0.0.11",
"vtk.js": "^8.13.0"
},
"devDependencies": {

View File

@ -1,7 +1,7 @@
import {
vtkInteractorStyleMPRCrosshairs,
vtkInteractorStyleMPRSlice,
vtkInteractorStyleMPRWindowLevel,
vtkInteractorStyleMPRSlice,
vtkSVGCrosshairsWidget,
vtkSVGWidgetManager,
} from 'react-vtkjs-viewport';
@ -11,9 +11,13 @@ import setViewportToVTK from './utils/setViewportToVTK.js';
import vtkCoordinate from 'vtk.js/Sources/Rendering/Core/Coordinate';
import vtkMath from 'vtk.js/Sources/Common/Core/Math';
import vtkMatrixBuilder from 'vtk.js/Sources/Common/Core/MatrixBuilder';
import Constants from 'vtk.js/Sources/Rendering/Core/VolumeMapper/Constants.js';
const { BlendMode } = Constants;
// TODO: Put this somewhere else
let apis = {};
let currentSlabThickness = 0.1;
function getCrosshairCallbackForIndex(index) {
return ({ worldPos }) => {
@ -96,26 +100,24 @@ function _setView(api, sliceNormal, viewUp) {
istyle.setSliceNormal(...sliceNormal);
camera.setViewUp(...viewUp);
api.volumes[0].getMapper().setSampleDistance(5.0);
api.volumes[0].getMapper().setMaximumSamplesPerRay(2000);
renderWindow.render();
}
function switchMPRInteractors(api, istyle) {
const renderWindow = api.genericRenderWindow.getRenderWindow();
const renderer = api.genericRenderWindow.getRenderer();
const camera = renderer.getActiveCamera();
const currentIStyle = renderWindow.getInteractor().getInteractorStyle();
let currentNormal;
if (istyle.getSliceNormal) {
currentNormal = istyle.getSliceNormal();
if (currentIStyle.getSliceNormal && istyle.getSliceNormal) {
currentNormal = currentIStyle.getSliceNormal();
}
// TODO: This is a hacky workaround because disabling the vtkInteractorStyleMPRSlice is currently
// broken. The camera.onModified is never removed. (https://github.com/Kitware/vtk-js/issues/1110)
renderWindow
.getInteractor()
.getInteractorStyle()
.setInteractor(null);
let currentSlabThickness;
if (currentIStyle.getSlabThickness && istyle.getSlabThickness) {
currentSlabThickness = currentIStyle.getSlabThickness();
}
renderWindow.getInteractor().setInteractorStyle(istyle);
@ -126,6 +128,11 @@ function switchMPRInteractors(api, istyle) {
if (currentNormal) {
istyle.setSliceNormal(currentNormal);
}
if (currentSlabThickness) {
istyle.setSlabThickness(currentSlabThickness);
}
istyle.setVolumeMapper(api.volumes[0]);
}
}
@ -152,14 +159,14 @@ const actions = {
_setView(api, [0, 1, 0], [0, 0, 1]);
},
enableRotateTool: async ({ viewports }) => {
enableRotateTool: () => {
apis.forEach(api => {
const istyle = vtkInteractorStyleMPRSlice.newInstance();
switchMPRInteractors(api, istyle);
});
},
enableCrosshairsTool: async ({ viewports }) => {
enableCrosshairsTool: () => {
apis.forEach((api, index) => {
const istyle = vtkInteractorStyleMPRCrosshairs.newInstance();
@ -168,13 +175,61 @@ const actions = {
istyle.setCallback(getCrosshairCallbackForIndex(index));
});
},
enableLevelTool: async ({ viewports }) => {
enableLevelTool: () => {
apis.forEach(api => {
const istyle = vtkInteractorStyleMPRWindowLevel.newInstance();
switchMPRInteractors(api, istyle);
});
},
setSlabThickness: slabThickness => {
currentSlabThickness = slabThickness;
apis.forEach(api => {
const renderWindow = api.genericRenderWindow.getRenderWindow();
const istyle = renderWindow.getInteractor().getInteractorStyle();
if (istyle.setSlabThickness) {
istyle.setSlabThickness(currentSlabThickness);
// TODO: Do this inside the interactors in a setSlabThickness function instead
const renderer = api.genericRenderWindow.getRenderer();
const camera = renderer.getActiveCamera();
const dist = camera.getDistance();
const near = dist - currentSlabThickness / 2;
const far = dist + currentSlabThickness / 2;
camera.setClippingRange(near, far);
}
renderWindow.render();
});
},
changeSlabThickness: ({ change }) => {
currentSlabThickness += change;
currentSlabThickness = Math.max(currentSlabThickness, 0.1);
apis.forEach(api => {
const renderWindow = api.genericRenderWindow.getRenderWindow();
const istyle = renderWindow.getInteractor().getInteractorStyle();
if (istyle.setSlabThickness) {
istyle.setSlabThickness(currentSlabThickness);
}
renderWindow.render();
});
},
setBlendMode: ({ blendMode }) => {
apis.forEach(api => {
const renderWindow = api.genericRenderWindow.getRenderWindow();
const istyle = renderWindow.getInteractor().getInteractorStyle();
api.volumes[0].getMapper().setBlendMode(blendMode);
renderWindow.render();
});
},
mpr2d: async ({ viewports }) => {
const displaySet =
viewports.viewportSpecificData[viewports.activeViewportIndex];
@ -199,20 +254,11 @@ const actions = {
});
});*/
apis[0].volumes[0].getMapper().setSampleDistance(1.5);
apiByViewport.forEach((api, index) => {
const renderWindow = api.genericRenderWindow.getRenderWindow();
const renderer = api.genericRenderWindow.getRenderer();
const camera = renderer.getActiveCamera();
// TODO: This is a hacky workaround because disabling the vtkInteractorStyleMPRSlice is currently
// broken. The camera.onModified is never removed. (https://github.com/Kitware/vtk-js/issues/1110)
renderWindow
.getInteractor()
.getInteractorStyle()
.setInteractor(null);
const istyle = vtkInteractorStyleMPRCrosshairs.newInstance();
renderWindow.getInteractor().setInteractorStyle(istyle);
@ -258,6 +304,8 @@ const actions = {
},
};
window.vtkActions = actions;
const definitions = {
axial: {
commandFn: actions.axial,
@ -276,19 +324,59 @@ const definitions = {
},
enableRotateTool: {
commandFn: actions.enableRotateTool,
storeContexts: ['viewports'],
storeContexts: [],
options: {},
},
enableCrosshairsTool: {
commandFn: actions.enableCrosshairsTool,
storeContexts: ['viewports'],
storeContexts: [],
options: {},
},
enableLevelTool: {
commandFn: actions.enableLevelTool,
storeContexts: ['viewports'],
storeContexts: [],
options: {},
},
setBlendModeToComposite: {
commandFn: actions.setBlendMode,
storeContexts: [],
options: { blendMode: BlendMode.COMPOSITE_BLEND },
},
setBlendModeToMaximumIntensity: {
commandFn: actions.setBlendMode,
storeContexts: [],
options: { blendMode: BlendMode.MAXIMUM_INTENSITY_BLEND },
},
setBlendModeToMinimumIntensity: {
commandFn: actions.setBlendMode,
storeContexts: [],
options: { blendMode: BlendMode.MINIMUM_INTENSITY_BLEND },
},
setBlendModeToAverageIntensity: {
commandFn: actions.setBlendMode,
storeContexts: [],
options: { blendMode: BlendMode.AVERAGE_INTENSITY_BLEND },
},
setSlabThickness: {
// TODO: How do we pass in a function argument?
commandFn: actions.setSlabThickness,
storeContexts: [],
options: {},
},
increaseSlabThickness: {
commandFn: actions.changeSlabThickness,
storeContexts: [],
options: {
change: 3,
},
},
decreaseSlabThickness: {
commandFn: actions.changeSlabThickness,
storeContexts: [],
options: {
change: -3,
},
},
mpr2d: {
commandFn: actions.mpr2d,
storeContexts: ['viewports'],

View File

@ -31,6 +31,43 @@ const definitions = [
commandName: 'enableRotateTool',
commandOptions: {},
},
{
id: 'setBlendModeToComposite',
label: 'Disable MIP',
icon: 'times',
//
type: TOOLBAR_BUTTON_TYPES.COMMAND,
commandName: 'setBlendModeToComposite',
commandOptions: {},
},
{
id: 'setBlendModeToMaximumIntensity',
label: 'Enable MIP',
icon: 'soft-tissue',
//
type: TOOLBAR_BUTTON_TYPES.COMMAND,
commandName: 'setBlendModeToMaximumIntensity',
commandOptions: {},
},
{
id: 'increaseSlabThickness',
label: 'Increase Slab Thickness',
icon: 'caret-up',
//
type: TOOLBAR_BUTTON_TYPES.COMMAND,
commandName: 'increaseSlabThickness',
commandOptions: {},
},
{
id: 'decreaseSlabThickness',
label: 'Decrease Slab Thickness',
icon: 'caret-down',
//
type: TOOLBAR_BUTTON_TYPES.COMMAND,
commandName: 'decreaseSlabThickness',
commandOptions: {},
},
];
export default {

View File

@ -5519,10 +5519,10 @@ react-viewerbase@^0.15.1:
react-i18next "^10.11.0"
react-with-direction "1.3.0"
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==
react-vtkjs-viewport@0.0.11:
version "0.0.11"
resolved "https://registry.yarnpkg.com/react-vtkjs-viewport/-/react-vtkjs-viewport-0.0.11.tgz#cedd993ca226502bf0417a3748a5b2f806522519"
integrity sha512-ttWw7bU/lL/nJuaaKdtAc8448vMJmlRQzpkpuP/J+3lTzIQbQPCPU40LqgONjr7LvL5++61N2GJ8m+PRgHyfxQ==
dependencies:
moment "^2.24.0"
@ -6974,10 +6974,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.11.0:
version "8.11.1"
resolved "https://registry.yarnpkg.com/vtk.js/-/vtk.js-8.11.1.tgz#cdf69705a72a2a3ce76d7442d1b3903e3de770d4"
integrity sha512-Y5ZCFtoMOuuJt44fyj91Gqeg9ZeCQovyoJlEHG1oUHLPehQTvq0oW09WqBcxVSdiv92x3aXYWtgZjm/s4EWw7Q==
vtk.js@^8.13.0:
version "8.13.0"
resolved "https://registry.yarnpkg.com/vtk.js/-/vtk.js-8.13.0.tgz#d22bbe3403d86f979703506f9be83ab8e5099248"
integrity sha512-uoq2U0Yu2XjuKeeduuGRXlphHR6cdIvtZ5useNMJ8FobK9dpeFTT4ncoyPXx77KvwOMSueT8W+ngm/e9+FGZtA==
dependencies:
base64-js "1.2.1"
blueimp-md5 "2.10.0"