@cornerstonejs/tools 1.65.2 → 1.65.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/enums/StrategyCallbacks.d.ts +2 -1
- package/dist/cjs/enums/StrategyCallbacks.js +1 -0
- package/dist/cjs/enums/StrategyCallbacks.js.map +1 -1
- package/dist/cjs/stateManagement/annotation/annotationSelection.js +2 -1
- package/dist/cjs/stateManagement/annotation/annotationSelection.js.map +1 -1
- package/dist/cjs/tools/MIPJumpToClickTool.js +2 -1
- package/dist/cjs/tools/MIPJumpToClickTool.js.map +1 -1
- package/dist/cjs/tools/StackScrollToolMouseWheelTool.js +2 -1
- package/dist/cjs/tools/StackScrollToolMouseWheelTool.js.map +1 -1
- package/dist/cjs/tools/base/AnnotationDisplayTool.js +2 -1
- package/dist/cjs/tools/base/AnnotationDisplayTool.js.map +1 -1
- package/dist/cjs/tools/base/AnnotationTool.js +2 -1
- package/dist/cjs/tools/base/AnnotationTool.js.map +1 -1
- package/dist/cjs/tools/base/BaseTool.js +2 -1
- package/dist/cjs/tools/base/BaseTool.js.map +1 -1
- package/dist/cjs/tools/segmentation/BrushTool.js +16 -4
- package/dist/cjs/tools/segmentation/BrushTool.js.map +1 -1
- package/dist/cjs/tools/segmentation/strategies/BrushStrategy.d.ts +3 -0
- package/dist/cjs/tools/segmentation/strategies/BrushStrategy.js +1 -0
- package/dist/cjs/tools/segmentation/strategies/BrushStrategy.js.map +1 -1
- package/dist/cjs/tools/segmentation/strategies/compositions/dynamicThreshold.d.ts +1 -0
- package/dist/cjs/tools/segmentation/strategies/compositions/dynamicThreshold.js +20 -0
- package/dist/cjs/tools/segmentation/strategies/compositions/dynamicThreshold.js.map +1 -1
- package/dist/cjs/tools/segmentation/strategies/compositions/index.d.ts +1 -0
- package/dist/cjs/utilities/getVolumeId.d.ts +1 -0
- package/dist/cjs/utilities/getVolumeId.js +16 -0
- package/dist/cjs/utilities/getVolumeId.js.map +1 -0
- package/dist/esm/enums/StrategyCallbacks.js +1 -0
- package/dist/esm/enums/StrategyCallbacks.js.map +1 -1
- package/dist/esm/stateManagement/annotation/annotationSelection.js +1 -1
- package/dist/esm/stateManagement/annotation/annotationSelection.js.map +1 -1
- package/dist/esm/tools/MIPJumpToClickTool.js +2 -1
- package/dist/esm/tools/MIPJumpToClickTool.js.map +1 -1
- package/dist/esm/tools/StackScrollToolMouseWheelTool.js +2 -1
- package/dist/esm/tools/StackScrollToolMouseWheelTool.js.map +1 -1
- package/dist/esm/tools/base/AnnotationDisplayTool.js +2 -1
- package/dist/esm/tools/base/AnnotationDisplayTool.js.map +1 -1
- package/dist/esm/tools/base/AnnotationTool.js +2 -1
- package/dist/esm/tools/base/AnnotationTool.js.map +1 -1
- package/dist/esm/tools/base/BaseTool.js +2 -1
- package/dist/esm/tools/base/BaseTool.js.map +1 -1
- package/dist/esm/tools/segmentation/BrushTool.js +16 -4
- package/dist/esm/tools/segmentation/BrushTool.js.map +1 -1
- package/dist/esm/tools/segmentation/strategies/BrushStrategy.js +1 -0
- package/dist/esm/tools/segmentation/strategies/BrushStrategy.js.map +1 -1
- package/dist/esm/tools/segmentation/strategies/compositions/dynamicThreshold.js +20 -0
- package/dist/esm/tools/segmentation/strategies/compositions/dynamicThreshold.js.map +1 -1
- package/dist/esm/utilities/getVolumeId.js +12 -0
- package/dist/esm/utilities/getVolumeId.js.map +1 -0
- package/dist/types/enums/StrategyCallbacks.d.ts +2 -1
- package/dist/types/enums/StrategyCallbacks.d.ts.map +1 -1
- package/dist/types/tools/MIPJumpToClickTool.d.ts.map +1 -1
- package/dist/types/tools/StackScrollToolMouseWheelTool.d.ts.map +1 -1
- package/dist/types/tools/base/AnnotationDisplayTool.d.ts.map +1 -1
- package/dist/types/tools/base/AnnotationTool.d.ts.map +1 -1
- package/dist/types/tools/base/BaseTool.d.ts.map +1 -1
- package/dist/types/tools/segmentation/BrushTool.d.ts.map +1 -1
- package/dist/types/tools/segmentation/strategies/BrushStrategy.d.ts +3 -0
- package/dist/types/tools/segmentation/strategies/BrushStrategy.d.ts.map +1 -1
- package/dist/types/tools/segmentation/strategies/compositions/dynamicThreshold.d.ts +1 -0
- package/dist/types/tools/segmentation/strategies/compositions/dynamicThreshold.d.ts.map +1 -1
- package/dist/types/tools/segmentation/strategies/compositions/index.d.ts +1 -0
- package/dist/types/tools/segmentation/strategies/compositions/index.d.ts.map +1 -1
- package/dist/types/utilities/getVolumeId.d.ts +2 -0
- package/dist/types/utilities/getVolumeId.d.ts.map +1 -0
- package/dist/umd/index.js +1 -1
- package/dist/umd/index.js.map +1 -1
- package/package.json +3 -3
- package/src/enums/StrategyCallbacks.ts +3 -0
- package/src/stateManagement/annotation/annotationSelection.ts +1 -1
- package/src/tools/MIPJumpToClickTool.ts +2 -1
- package/src/tools/StackScrollToolMouseWheelTool.ts +2 -1
- package/src/tools/base/AnnotationDisplayTool.ts +2 -1
- package/src/tools/base/AnnotationTool.ts +2 -1
- package/src/tools/base/BaseTool.ts +2 -1
- package/src/tools/segmentation/BrushTool.ts +21 -5
- package/src/tools/segmentation/strategies/BrushStrategy.ts +4 -0
- package/src/tools/segmentation/strategies/compositions/dynamicThreshold.ts +43 -0
- package/src/utilities/getVolumeId.ts +13 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cornerstonejs/tools",
|
|
3
|
-
"version": "1.65.
|
|
3
|
+
"version": "1.65.4",
|
|
4
4
|
"description": "Cornerstone3D Tools",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "dist/types/index.d.ts",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"webpack:watch": "webpack --mode development --progress --watch --config ./.webpack/webpack.dev.js"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@cornerstonejs/core": "^1.65.
|
|
32
|
+
"@cornerstonejs/core": "^1.65.4",
|
|
33
33
|
"@icr/polyseg-wasm": "0.4.0",
|
|
34
34
|
"@types/offscreencanvas": "2019.7.3",
|
|
35
35
|
"comlink": "^4.4.1",
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"type": "individual",
|
|
60
60
|
"url": "https://ohif.org/donate"
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "9f0c1e30b8bf4cfca1ca04186f377e2a2f3a2b54"
|
|
63
63
|
}
|
|
@@ -94,7 +94,7 @@ function getAnnotationsSelected(): Array<string> {
|
|
|
94
94
|
function getAnnotationsSelectedByToolName(toolName: string): Array<string> {
|
|
95
95
|
return getAnnotationsSelected().filter((annotationUID) => {
|
|
96
96
|
const annotation = getAnnotation(annotationUID);
|
|
97
|
-
return annotation
|
|
97
|
+
return annotation?.metadata?.toolName === toolName;
|
|
98
98
|
});
|
|
99
99
|
}
|
|
100
100
|
|
|
@@ -5,6 +5,7 @@ import { getPointInLineOfSightWithCriteria } from '../utilities/planar';
|
|
|
5
5
|
import jumpToWorld from '../utilities/viewport/jumpToWorld';
|
|
6
6
|
import { PublicToolProps, ToolProps } from '../types';
|
|
7
7
|
import { getToolGroupForViewport } from '../store/ToolGroupManager';
|
|
8
|
+
import { getVolumeId } from '../utilities/getVolumeId';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* On a Maximum Intensity Projection (MIP) viewport, MIPJumpToClickTool allows the
|
|
@@ -54,7 +55,7 @@ class MIPJumpToClickTool extends BaseTool {
|
|
|
54
55
|
);
|
|
55
56
|
}
|
|
56
57
|
|
|
57
|
-
const volumeId = targetId
|
|
58
|
+
const volumeId = getVolumeId(targetId);
|
|
58
59
|
|
|
59
60
|
// 3. Criteria function to search for the point (maximum intensity)
|
|
60
61
|
let maxIntensity = -Infinity;
|
|
@@ -2,6 +2,7 @@ import { getEnabledElement } from '@cornerstonejs/core';
|
|
|
2
2
|
import { BaseTool } from './base';
|
|
3
3
|
import { MouseWheelEventType } from '../types/EventTypes';
|
|
4
4
|
import scroll from '../utilities/scroll';
|
|
5
|
+
import { getVolumeId } from '../utilities/getVolumeId';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* The StackScrollMouseWheelTool is a tool that allows the user to scroll through a
|
|
@@ -35,7 +36,7 @@ class StackScrollMouseWheelTool extends BaseTool {
|
|
|
35
36
|
const delta = direction * (invert ? -1 : 1);
|
|
36
37
|
|
|
37
38
|
const targetId = this.getTargetId(viewport);
|
|
38
|
-
const volumeId = targetId
|
|
39
|
+
const volumeId = getVolumeId(targetId);
|
|
39
40
|
|
|
40
41
|
scroll(viewport, {
|
|
41
42
|
delta,
|
|
@@ -15,6 +15,7 @@ import filterAnnotationsForDisplay from '../../utilities/planar/filterAnnotation
|
|
|
15
15
|
import { getStyleProperty } from '../../stateManagement/annotation/config/helpers';
|
|
16
16
|
import { getState } from '../../stateManagement/annotation/config';
|
|
17
17
|
import { StyleSpecifier } from '../../types/AnnotationStyle';
|
|
18
|
+
import { getVolumeId } from '../../utilities/getVolumeId';
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* Abstract class for tools which create and display annotations on the
|
|
@@ -137,7 +138,7 @@ abstract class AnnotationDisplayTool extends BaseTool {
|
|
|
137
138
|
} else if (viewport instanceof VideoViewport) {
|
|
138
139
|
referencedImageId = targetId.split('videoId:')[1];
|
|
139
140
|
} else {
|
|
140
|
-
const volumeId = targetId
|
|
141
|
+
const volumeId = getVolumeId(targetId);
|
|
141
142
|
const imageVolume = cache.getVolume(volumeId);
|
|
142
143
|
|
|
143
144
|
referencedImageId = utilities.getClosestImageId(
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
import { addAnnotation } from '../../stateManagement/annotation/annotationState';
|
|
25
25
|
import { StyleSpecifier } from '../../types/AnnotationStyle';
|
|
26
26
|
import { triggerAnnotationModified } from '../../stateManagement/annotation/helpers/state';
|
|
27
|
+
import { getVolumeId } from '../../utilities/getVolumeId';
|
|
27
28
|
|
|
28
29
|
/**
|
|
29
30
|
* Abstract class for tools which create and display annotations on the
|
|
@@ -368,7 +369,7 @@ abstract class AnnotationTool extends AnnotationDisplayTool {
|
|
|
368
369
|
imageId?: string
|
|
369
370
|
): boolean {
|
|
370
371
|
if (viewport instanceof BaseVolumeViewport) {
|
|
371
|
-
const volumeId = targetId
|
|
372
|
+
const volumeId = getVolumeId(targetId);
|
|
372
373
|
const volume = cache.getVolume(volumeId);
|
|
373
374
|
return volume.scaling?.PT !== undefined;
|
|
374
375
|
}
|
|
@@ -3,6 +3,7 @@ import { Types } from '@cornerstonejs/core';
|
|
|
3
3
|
import ToolModes from '../../enums/ToolModes';
|
|
4
4
|
import StrategyCallbacks from '../../enums/StrategyCallbacks';
|
|
5
5
|
import { InteractionTypes, ToolProps, PublicToolProps } from '../../types';
|
|
6
|
+
import { getVolumeId } from '../../utilities/getVolumeId';
|
|
6
7
|
|
|
7
8
|
export interface IBaseTool {
|
|
8
9
|
/** ToolGroup ID the tool instance belongs to */
|
|
@@ -208,7 +209,7 @@ abstract class BaseTool implements IBaseTool {
|
|
|
208
209
|
|
|
209
210
|
return viewports[0].getImageData();
|
|
210
211
|
} else if (targetId.startsWith('volumeId:')) {
|
|
211
|
-
const volumeId = targetId
|
|
212
|
+
const volumeId = getVolumeId(targetId);
|
|
212
213
|
const viewports = utilities.getViewportsWithVolumeId(
|
|
213
214
|
volumeId,
|
|
214
215
|
renderingEngine.id
|
|
@@ -108,6 +108,7 @@ class BrushTool extends BaseTool {
|
|
|
108
108
|
strategySpecificConfiguration: {
|
|
109
109
|
THRESHOLD: {
|
|
110
110
|
threshold: [-150, -70], // E.g. CT Fat // Only used during threshold strategies.
|
|
111
|
+
dynamicRadius: 0, // in voxel counts in each direction, only used during dynamic threshold strategies.
|
|
111
112
|
},
|
|
112
113
|
},
|
|
113
114
|
defaultStrategy: 'FILL_INSIDE_CIRCLE',
|
|
@@ -126,8 +127,6 @@ class BrushTool extends BaseTool {
|
|
|
126
127
|
// The time to consider a mouse click a drag when moved less than dragMoveDistance
|
|
127
128
|
dragTimeMs: 500,
|
|
128
129
|
},
|
|
129
|
-
// Whether to show a center circle/position. Set to null to not show
|
|
130
|
-
centerRadius: 2,
|
|
131
130
|
actions: {
|
|
132
131
|
[StrategyCallbacks.AcceptPreview]: {
|
|
133
132
|
method: StrategyCallbacks.AcceptPreview,
|
|
@@ -584,6 +583,18 @@ class BrushTool extends BaseTool {
|
|
|
584
583
|
rightCursorInWorld,
|
|
585
584
|
];
|
|
586
585
|
|
|
586
|
+
const activeStrategy = this.configuration.activeStrategy;
|
|
587
|
+
const strategy = this.configuration.strategies[activeStrategy];
|
|
588
|
+
|
|
589
|
+
// Note: i don't think this is the best way to implement this
|
|
590
|
+
// but don't think we have a better way to do it for now
|
|
591
|
+
if (typeof strategy.computeInnerCircleRadius === 'function') {
|
|
592
|
+
strategy.computeInnerCircleRadius({
|
|
593
|
+
configuration: this.configuration,
|
|
594
|
+
viewport,
|
|
595
|
+
});
|
|
596
|
+
}
|
|
597
|
+
|
|
587
598
|
data.invalidated = false;
|
|
588
599
|
}
|
|
589
600
|
|
|
@@ -776,15 +787,20 @@ class BrushTool extends BaseTool {
|
|
|
776
787
|
}
|
|
777
788
|
);
|
|
778
789
|
|
|
779
|
-
const
|
|
780
|
-
|
|
790
|
+
const activeStrategy = this.configuration.activeStrategy;
|
|
791
|
+
const { dynamicRadiusInCanvas } = this.configuration
|
|
792
|
+
.strategySpecificConfiguration[activeStrategy] || {
|
|
793
|
+
dynamicRadiusInCanvas: 0,
|
|
794
|
+
};
|
|
795
|
+
|
|
796
|
+
if (dynamicRadiusInCanvas) {
|
|
781
797
|
const circleUID1 = '1';
|
|
782
798
|
drawCircleSvg(
|
|
783
799
|
svgDrawingHelper,
|
|
784
800
|
annotationUID,
|
|
785
801
|
circleUID1,
|
|
786
802
|
center as Types.Point2,
|
|
787
|
-
|
|
803
|
+
dynamicRadiusInCanvas,
|
|
788
804
|
{
|
|
789
805
|
color,
|
|
790
806
|
}
|
|
@@ -34,6 +34,7 @@ export type InitializedOperationData = LabelmapToolOperationDataAny & {
|
|
|
34
34
|
previewSegmentIndex?: number;
|
|
35
35
|
|
|
36
36
|
brushStrategy: BrushStrategy;
|
|
37
|
+
configuration?: Record<string, any>;
|
|
37
38
|
};
|
|
38
39
|
|
|
39
40
|
export type StrategyFunction = (
|
|
@@ -110,6 +111,9 @@ export default class BrushStrategy {
|
|
|
110
111
|
StrategyCallbacks.Preview,
|
|
111
112
|
false
|
|
112
113
|
),
|
|
114
|
+
[StrategyCallbacks.ComputeInnerCircleRadius]: addListMethod(
|
|
115
|
+
StrategyCallbacks.ComputeInnerCircleRadius
|
|
116
|
+
),
|
|
113
117
|
// Add other exposed fields below
|
|
114
118
|
// initializers is exposed on the function to allow extension of the composition object
|
|
115
119
|
compositions: null,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { vec3 } from 'gl-matrix';
|
|
2
|
+
import type { Types } from '@cornerstonejs/core';
|
|
2
3
|
import type { InitializedOperationData } from '../BrushStrategy';
|
|
3
4
|
import type BoundsIJK from '../../../../types/BoundsIJK';
|
|
4
5
|
import StrategyCallbacks from '../../../../enums/StrategyCallbacks';
|
|
@@ -65,4 +66,46 @@ export default {
|
|
|
65
66
|
}
|
|
66
67
|
strategySpecificConfiguration.THRESHOLD.threshold = null;
|
|
67
68
|
},
|
|
69
|
+
/**
|
|
70
|
+
* It computes the inner circle radius in canvas coordinates and stores it
|
|
71
|
+
* in the strategySpecificConfiguration. This is used to show the user
|
|
72
|
+
* the area that is used to compute the threshold.
|
|
73
|
+
*/
|
|
74
|
+
[StrategyCallbacks.ComputeInnerCircleRadius]: (
|
|
75
|
+
operationData: InitializedOperationData
|
|
76
|
+
) => {
|
|
77
|
+
const { configuration, viewport } = operationData;
|
|
78
|
+
const { THRESHOLD: { dynamicRadius = 0 } = {} } =
|
|
79
|
+
configuration.strategySpecificConfiguration || {};
|
|
80
|
+
const { spacing } = (
|
|
81
|
+
viewport as Types.IStackViewport | Types.IVolumeViewport
|
|
82
|
+
).getImageData();
|
|
83
|
+
const centerCanvas = [
|
|
84
|
+
viewport.element.clientWidth / 2,
|
|
85
|
+
viewport.element.clientHeight / 2,
|
|
86
|
+
] as Types.Point2;
|
|
87
|
+
const radiusInWorld = dynamicRadius * spacing[0];
|
|
88
|
+
const centerCursorInWorld = viewport.canvasToWorld(centerCanvas);
|
|
89
|
+
|
|
90
|
+
const offSetCenterInWorld = centerCursorInWorld.map(
|
|
91
|
+
(coord) => coord + radiusInWorld
|
|
92
|
+
) as Types.Point3;
|
|
93
|
+
|
|
94
|
+
const offSetCenterCanvas = viewport.worldToCanvas(offSetCenterInWorld);
|
|
95
|
+
const dynamicRadiusInCanvas = Math.abs(
|
|
96
|
+
centerCanvas[0] - offSetCenterCanvas[0]
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
// this is a bit of a hack, since we have switched to using THRESHOLD
|
|
100
|
+
// as strategy but really strategy names are CIRCLE_THRESHOLD and SPHERE_THRESHOLD
|
|
101
|
+
// and we can't really change the name of the strategy in the configuration
|
|
102
|
+
const { strategySpecificConfiguration, activeStrategy } = configuration;
|
|
103
|
+
|
|
104
|
+
if (!strategySpecificConfiguration[activeStrategy]) {
|
|
105
|
+
strategySpecificConfiguration[activeStrategy] = {};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
strategySpecificConfiguration[activeStrategy].dynamicRadiusInCanvas =
|
|
109
|
+
dynamicRadiusInCanvas;
|
|
110
|
+
},
|
|
68
111
|
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const getVolumeId = (targetId: string) => {
|
|
2
|
+
const prefix = 'volumeId:';
|
|
3
|
+
const str = targetId.includes(prefix)
|
|
4
|
+
? targetId.substring(prefix.length)
|
|
5
|
+
: targetId;
|
|
6
|
+
|
|
7
|
+
if (str.startsWith('nifti:')) {
|
|
8
|
+
return str;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const index = str.indexOf('?');
|
|
12
|
+
return index === -1 ? str : str.substring(0, index);
|
|
13
|
+
};
|