Skip to content

Commit

Permalink
feat: added MIP option to StackScrollTool
Browse files Browse the repository at this point in the history
  • Loading branch information
Ouwen committed Apr 1, 2023
1 parent b21acf4 commit 76a2109
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 16 deletions.
4 changes: 4 additions & 0 deletions common/reviews/api/tools.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -4678,6 +4678,8 @@ export class StackScrollMouseWheelTool extends BaseTool {
export class StackScrollTool extends BaseTool {
constructor(toolProps?: PublicToolProps, defaultToolProps?: ToolProps);
// (undocumented)
deltaX: number;
// (undocumented)
deltaY: number;
// (undocumented)
_dragCallback(evt: EventTypes_2.InteractionEventType): void;
Expand All @@ -4691,6 +4693,8 @@ export class StackScrollTool extends BaseTool {
static toolName: any;
// (undocumented)
touchDragCallback(evt: EventTypes_2.InteractionEventType): void;
// (undocumented)
_triggerMIP(viewport: any, delta: any, invert: any): void;
}

// @public
Expand Down
44 changes: 41 additions & 3 deletions packages/tools/examples/volumeViewportSynchronization/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
createImageIdsAndCacheMetaData,
setTitleAndDescription,
addToggleButtonToToolbar,
addDropdownToToolbar,
} from '../../../../utils/demo/helpers';
import * as cornerstoneTools from '@cornerstonejs/tools';

Expand All @@ -24,6 +25,7 @@ const {
ZoomTool,
ToolGroupManager,
StackScrollMouseWheelTool,
StackScrollTool,
Enums: csToolsEnums,
synchronizers,
SynchronizerManager,
Expand Down Expand Up @@ -97,6 +99,33 @@ Toggle the controls to add viewports to the synchronization groups.

content.append(instructions);
// ============================= //
const toolGroupId = 'TOOL_GROUP_ID';
const leftClickTools = [WindowLevelTool.toolName, StackScrollTool.toolName];
const defaultLeftClickTool = leftClickTools[0];
let currentLeftClickTool = leftClickTools[0];
addDropdownToToolbar({
options: {
values: leftClickTools,
defaultValue: defaultLeftClickTool,
},
onSelectedValueChange: (selectedValue) => {
console.log('>>>>> selectedValue :: ', selectedValue);
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId);
console.log('>>>>> toolGroup :: ', toolGroup);

toolGroup.setToolPassive(currentLeftClickTool);

toolGroup.setToolActive(<string>selectedValue, {
bindings: [
{
mouseButton: MouseBindings.Primary, // Left Click
},
],
});

currentLeftClickTool = selectedValue;
},
});

const SynchronizerButtonInfo = [
{ viewportLabel: 'A', viewportId: viewportIds[0] },
Expand Down Expand Up @@ -151,23 +180,32 @@ async function run() {
// Init Cornerstone and related libraries
await initDemo();

const toolGroupId = 'TOOL_GROUP_ID';

// Add tools to Cornerstone3D
cornerstoneTools.addTool(PanTool);
cornerstoneTools.addTool(WindowLevelTool);
cornerstoneTools.addTool(StackScrollMouseWheelTool);
cornerstoneTools.addTool(StackScrollTool);
cornerstoneTools.addTool(ZoomTool);

// Define a tool group, which defines how mouse events map to tool commands for
// Any viewport using the group
const toolGroup = ToolGroupManager.createToolGroup(toolGroupId);

// Add tools to the tool group
toolGroup.addTool(WindowLevelTool.toolName, { volumeId });
toolGroup.addTool(WindowLevelTool.toolName);
toolGroup.addTool(PanTool.toolName);
toolGroup.addTool(ZoomTool.toolName);
toolGroup.addTool(StackScrollMouseWheelTool.toolName);
toolGroup.addTool(StackScrollTool.toolName, {
leftRightMode: false,
mipMode: {
enabled: true,
invert: false,
pixelsPerThickness: 5,
minSlabThickness: 5e-2,
maxSlabThickness: 30,
},
});

// Set the initial state of the tools, here all tools are active and bound to
// Different mouse inputs
Expand Down
108 changes: 95 additions & 13 deletions packages/tools/src/tools/StackScrollTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,30 @@ import { PublicToolProps, ToolProps, EventTypes } from '../types';
class StackScrollTool extends BaseTool {
static toolName;
deltaY: number;
deltaX: number;
constructor(
toolProps: PublicToolProps = {},
defaultToolProps: ToolProps = {
supportedInteractionTypes: ['Mouse', 'Touch'],
configuration: {
invert: false,
leftRightMode: false,
debounceIfNotLoaded: true,
loop: false
loop: false,
stackScrollEnabled: true,
mipMode: {
enabled: true,
invert: false,
pixelsPerThickness: 5,
minSlabThickness: 5e-2,
maxSlabThickness: 30,
},
},
}
) {
super(toolProps, defaultToolProps);
this.deltaY = 1;
this.deltaX = 1;
}

mouseDragCallback(evt: EventTypes.InteractionEventType) {
Expand All @@ -42,9 +53,16 @@ class StackScrollTool extends BaseTool {
const { viewport } = getEnabledElementByIds(viewportId, renderingEngineId);

const targetId = this.getTargetId(viewport);
const { debounceIfNotLoaded, invert, loop } = this.configuration;
const {
debounceIfNotLoaded,
invert,
loop,
leftRightMode,
stackScrollEnabled,
} = this.configuration;

const deltaPointY = deltaPoints.canvas[1];
const deltaPointX = deltaPoints.canvas[0];

let volumeId;
if (viewport instanceof VolumeViewport) {
Expand All @@ -53,24 +71,66 @@ class StackScrollTool extends BaseTool {

const pixelsPerImage = this._getPixelPerImage(viewport);
const deltaY = deltaPointY + this.deltaY;
const deltaX = deltaPointX + this.deltaX;

if (!pixelsPerImage) {
return;
}

if (Math.abs(deltaY) >= pixelsPerImage) {
const imageIdIndexOffset = Math.round(deltaY / pixelsPerImage);
if (stackScrollEnabled && !leftRightMode) {
if (Math.abs(deltaY) >= pixelsPerImage) {
const imageIdIndexOffset = Math.round(deltaY / pixelsPerImage);

scroll(viewport, {
delta: invert ? -imageIdIndexOffset : imageIdIndexOffset,
volumeId,
debounceLoading: debounceIfNotLoaded,
loop: loop
});
scroll(viewport, {
delta: invert ? -imageIdIndexOffset : imageIdIndexOffset,
volumeId,
debounceLoading: debounceIfNotLoaded,
loop: loop,
});

this.deltaY = deltaY % pixelsPerImage;
} else {
this.deltaY = deltaY;
this.deltaY = deltaY % pixelsPerImage;
} else {
this.deltaY = deltaY;
}
}

if (stackScrollEnabled && leftRightMode) {
if (Math.abs(deltaX) >= pixelsPerImage) {
const imageIdIndexOffset = Math.round(deltaX / pixelsPerImage);

scroll(viewport, {
delta: invert ? -imageIdIndexOffset : imageIdIndexOffset,
volumeId,
debounceLoading: debounceIfNotLoaded,
loop: loop,
});

this.deltaX = deltaX % pixelsPerImage;
} else {
this.deltaX = deltaX;
}
}

const { mipMode } = this.configuration;
if (!mipMode?.enabled) return;
const { pixelsPerThickness, mipModeInvert } = mipMode;

if (mipMode?.enabled && leftRightMode) {
if (Math.abs(deltaY) >= pixelsPerThickness) {
this._triggerMIP(viewport, deltaY > 0 ? -1 : 1, mipModeInvert);
this.deltaY = deltaY % pixelsPerThickness;
} else {
this.deltaY = deltaY;
}
}

if (mipMode?.enabled && !leftRightMode) {
if (Math.abs(deltaX) >= pixelsPerThickness) {
this._triggerMIP(viewport, deltaX > 0 ? 1 : -1, mipModeInvert);
this.deltaX = deltaX % pixelsPerThickness;
} else {
this.deltaX = deltaX;
}
}
}

Expand All @@ -91,6 +151,28 @@ class StackScrollTool extends BaseTool {
return viewport.getImageIds().length;
}
}

_triggerMIP(viewport, delta, invert) {
const inversionValue = invert ? -1 : 1;
const { minSlabThickness, maxSlabThickness } = this.configuration.mipMode;
if (viewport instanceof VolumeViewport) {
const slabThickness = Math.min(
maxSlabThickness,
viewport.getSlabThickness() + inversionValue * delta
);
if (slabThickness <= minSlabThickness) {
viewport.setBlendMode(0);
viewport.setSlabThickness(minSlabThickness);
viewport.render();
} else {
viewport.setBlendMode(1);
viewport.setSlabThickness(
slabThickness >= maxSlabThickness ? maxSlabThickness : slabThickness
);
viewport.render();
}
}
}
}

StackScrollTool.toolName = 'StackScroll';
Expand Down

0 comments on commit 76a2109

Please sign in to comment.