@cornerstonejs/tools 1.32.3 → 1.33.0
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/eventListeners/index.d.ts +2 -2
- package/dist/cjs/eventListeners/index.js +2 -1
- package/dist/cjs/eventListeners/index.js.map +1 -1
- package/dist/cjs/eventListeners/segmentation/imageChangeEventListener.d.ts +5 -0
- package/dist/cjs/eventListeners/segmentation/imageChangeEventListener.js +143 -0
- package/dist/cjs/eventListeners/segmentation/imageChangeEventListener.js.map +1 -0
- package/dist/cjs/eventListeners/segmentation/index.d.ts +2 -1
- package/dist/cjs/eventListeners/segmentation/index.js +3 -1
- package/dist/cjs/eventListeners/segmentation/index.js.map +1 -1
- package/dist/cjs/eventListeners/segmentation/segmentationDataModifiedEventListener.js +31 -5
- package/dist/cjs/eventListeners/segmentation/segmentationDataModifiedEventListener.js.map +1 -1
- package/dist/cjs/store/addEnabledElement.js +1 -0
- package/dist/cjs/store/addEnabledElement.js.map +1 -1
- package/dist/cjs/store/removeEnabledElement.js +2 -0
- package/dist/cjs/store/removeEnabledElement.js.map +1 -1
- package/dist/cjs/tools/annotation/CircleROITool.js +3 -1
- package/dist/cjs/tools/annotation/CircleROITool.js.map +1 -1
- package/dist/cjs/tools/annotation/EllipticalROITool.js +1 -1
- package/dist/cjs/tools/annotation/EllipticalROITool.js.map +1 -1
- package/dist/cjs/tools/displayTools/Labelmap/addLabelmapToElement.d.ts +2 -1
- package/dist/cjs/tools/displayTools/Labelmap/addLabelmapToElement.js +23 -10
- package/dist/cjs/tools/displayTools/Labelmap/addLabelmapToElement.js.map +1 -1
- package/dist/cjs/tools/displayTools/Labelmap/labelmapDisplay.d.ts +1 -1
- package/dist/cjs/tools/displayTools/Labelmap/labelmapDisplay.js +36 -22
- package/dist/cjs/tools/displayTools/Labelmap/labelmapDisplay.js.map +1 -1
- package/dist/cjs/tools/displayTools/Labelmap/validateRepresentationData.js +6 -5
- package/dist/cjs/tools/displayTools/Labelmap/validateRepresentationData.js.map +1 -1
- package/dist/cjs/tools/segmentation/BrushTool.js +40 -45
- package/dist/cjs/tools/segmentation/BrushTool.js.map +1 -1
- package/dist/cjs/tools/segmentation/CircleScissorsTool.d.ts +4 -2
- package/dist/cjs/tools/segmentation/CircleScissorsTool.js +18 -17
- package/dist/cjs/tools/segmentation/CircleScissorsTool.js.map +1 -1
- package/dist/cjs/tools/segmentation/PaintFillTool.js +28 -5
- package/dist/cjs/tools/segmentation/PaintFillTool.js.map +1 -1
- package/dist/cjs/tools/segmentation/RectangleScissorsTool.d.ts +3 -1
- package/dist/cjs/tools/segmentation/RectangleScissorsTool.js +15 -16
- package/dist/cjs/tools/segmentation/RectangleScissorsTool.js.map +1 -1
- package/dist/cjs/tools/segmentation/SphereScissorsTool.d.ts +4 -2
- package/dist/cjs/tools/segmentation/SphereScissorsTool.js +20 -20
- package/dist/cjs/tools/segmentation/SphereScissorsTool.js.map +1 -1
- package/dist/cjs/tools/segmentation/strategies/eraseCircle.d.ts +2 -10
- package/dist/cjs/tools/segmentation/strategies/eraseCircle.js.map +1 -1
- package/dist/cjs/tools/segmentation/strategies/eraseRectangle.d.ts +4 -8
- package/dist/cjs/tools/segmentation/strategies/eraseRectangle.js +4 -20
- package/dist/cjs/tools/segmentation/strategies/eraseRectangle.js.map +1 -1
- package/dist/cjs/tools/segmentation/strategies/eraseSphere.d.ts +2 -10
- package/dist/cjs/tools/segmentation/strategies/eraseSphere.js.map +1 -1
- package/dist/cjs/tools/segmentation/strategies/fillCircle.d.ts +3 -11
- package/dist/cjs/tools/segmentation/strategies/fillCircle.js +57 -32
- package/dist/cjs/tools/segmentation/strategies/fillCircle.js.map +1 -1
- package/dist/cjs/tools/segmentation/strategies/fillRectangle.d.ts +2 -7
- package/dist/cjs/tools/segmentation/strategies/fillRectangle.js +16 -8
- package/dist/cjs/tools/segmentation/strategies/fillRectangle.js.map +1 -1
- package/dist/cjs/tools/segmentation/strategies/fillSphere.d.ts +2 -10
- package/dist/cjs/tools/segmentation/strategies/fillSphere.js +31 -17
- package/dist/cjs/tools/segmentation/strategies/fillSphere.js.map +1 -1
- package/dist/cjs/tools/segmentation/strategies/utils/getStrategyData.d.ts +9 -0
- package/dist/cjs/tools/segmentation/strategies/utils/getStrategyData.js +43 -0
- package/dist/cjs/tools/segmentation/strategies/utils/getStrategyData.js.map +1 -0
- package/dist/cjs/tools/segmentation/strategies/utils/isWithinThreshold.d.ts +2 -2
- package/dist/cjs/tools/segmentation/strategies/utils/isWithinThreshold.js +2 -2
- package/dist/cjs/tools/segmentation/strategies/utils/isWithinThreshold.js.map +1 -1
- package/dist/cjs/tools/segmentation/strategies/utils/stackVolumeCheck.d.ts +5 -0
- package/dist/cjs/tools/segmentation/strategies/utils/stackVolumeCheck.js +13 -0
- package/dist/cjs/tools/segmentation/strategies/utils/stackVolumeCheck.js.map +1 -0
- package/dist/cjs/types/LabelmapToolOperationData.d.ts +14 -0
- package/dist/cjs/types/LabelmapToolOperationData.js +3 -0
- package/dist/cjs/types/LabelmapToolOperationData.js.map +1 -0
- package/dist/cjs/types/LabelmapTypes.d.ts +5 -1
- package/dist/cjs/types/index.d.ts +2 -1
- package/dist/cjs/utilities/math/ellipse/pointInEllipse.d.ts +7 -9
- package/dist/cjs/utilities/math/ellipse/pointInEllipse.js +19 -11
- package/dist/cjs/utilities/math/ellipse/pointInEllipse.js.map +1 -1
- package/dist/esm/eventListeners/index.js +2 -2
- package/dist/esm/eventListeners/index.js.map +1 -1
- package/dist/esm/eventListeners/segmentation/imageChangeEventListener.js +115 -0
- package/dist/esm/eventListeners/segmentation/imageChangeEventListener.js.map +1 -0
- package/dist/esm/eventListeners/segmentation/index.js +2 -1
- package/dist/esm/eventListeners/segmentation/index.js.map +1 -1
- package/dist/esm/eventListeners/segmentation/segmentationDataModifiedEventListener.js +32 -6
- package/dist/esm/eventListeners/segmentation/segmentationDataModifiedEventListener.js.map +1 -1
- package/dist/esm/store/addEnabledElement.js +2 -1
- package/dist/esm/store/addEnabledElement.js.map +1 -1
- package/dist/esm/store/removeEnabledElement.js +2 -0
- package/dist/esm/store/removeEnabledElement.js.map +1 -1
- package/dist/esm/tools/annotation/CircleROITool.js +4 -2
- package/dist/esm/tools/annotation/CircleROITool.js.map +1 -1
- package/dist/esm/tools/annotation/EllipticalROITool.js +1 -1
- package/dist/esm/tools/annotation/EllipticalROITool.js.map +1 -1
- package/dist/esm/tools/displayTools/Labelmap/addLabelmapToElement.js +24 -11
- package/dist/esm/tools/displayTools/Labelmap/addLabelmapToElement.js.map +1 -1
- package/dist/esm/tools/displayTools/Labelmap/labelmapDisplay.js +36 -22
- package/dist/esm/tools/displayTools/Labelmap/labelmapDisplay.js.map +1 -1
- package/dist/esm/tools/displayTools/Labelmap/validateRepresentationData.js +6 -5
- package/dist/esm/tools/displayTools/Labelmap/validateRepresentationData.js.map +1 -1
- package/dist/esm/tools/segmentation/BrushTool.js +38 -29
- package/dist/esm/tools/segmentation/BrushTool.js.map +1 -1
- package/dist/esm/tools/segmentation/CircleScissorsTool.js +27 -15
- package/dist/esm/tools/segmentation/CircleScissorsTool.js.map +1 -1
- package/dist/esm/tools/segmentation/PaintFillTool.js +28 -5
- package/dist/esm/tools/segmentation/PaintFillTool.js.map +1 -1
- package/dist/esm/tools/segmentation/RectangleScissorsTool.js +26 -17
- package/dist/esm/tools/segmentation/RectangleScissorsTool.js.map +1 -1
- package/dist/esm/tools/segmentation/SphereScissorsTool.js +28 -17
- package/dist/esm/tools/segmentation/SphereScissorsTool.js.map +1 -1
- package/dist/esm/tools/segmentation/strategies/eraseCircle.js.map +1 -1
- package/dist/esm/tools/segmentation/strategies/eraseRectangle.js +4 -20
- package/dist/esm/tools/segmentation/strategies/eraseRectangle.js.map +1 -1
- package/dist/esm/tools/segmentation/strategies/eraseSphere.js.map +1 -1
- package/dist/esm/tools/segmentation/strategies/fillCircle.js +56 -31
- package/dist/esm/tools/segmentation/strategies/fillCircle.js.map +1 -1
- package/dist/esm/tools/segmentation/strategies/fillRectangle.js +16 -8
- package/dist/esm/tools/segmentation/strategies/fillRectangle.js.map +1 -1
- package/dist/esm/tools/segmentation/strategies/fillSphere.js +32 -18
- package/dist/esm/tools/segmentation/strategies/fillSphere.js.map +1 -1
- package/dist/esm/tools/segmentation/strategies/utils/getStrategyData.js +40 -0
- package/dist/esm/tools/segmentation/strategies/utils/getStrategyData.js.map +1 -0
- package/dist/esm/tools/segmentation/strategies/utils/isWithinThreshold.js +2 -2
- package/dist/esm/tools/segmentation/strategies/utils/isWithinThreshold.js.map +1 -1
- package/dist/esm/tools/segmentation/strategies/utils/stackVolumeCheck.js +9 -0
- package/dist/esm/tools/segmentation/strategies/utils/stackVolumeCheck.js.map +1 -0
- package/dist/esm/types/LabelmapToolOperationData.js +2 -0
- package/dist/esm/types/LabelmapToolOperationData.js.map +1 -0
- package/dist/esm/utilities/math/ellipse/pointInEllipse.js +19 -11
- package/dist/esm/utilities/math/ellipse/pointInEllipse.js.map +1 -1
- package/dist/types/eventListeners/index.d.ts +2 -2
- package/dist/types/eventListeners/index.d.ts.map +1 -1
- package/dist/types/eventListeners/segmentation/imageChangeEventListener.d.ts +6 -0
- package/dist/types/eventListeners/segmentation/imageChangeEventListener.d.ts.map +1 -0
- package/dist/types/eventListeners/segmentation/index.d.ts +2 -1
- package/dist/types/eventListeners/segmentation/index.d.ts.map +1 -1
- package/dist/types/eventListeners/segmentation/segmentationDataModifiedEventListener.d.ts.map +1 -1
- package/dist/types/store/addEnabledElement.d.ts.map +1 -1
- package/dist/types/store/removeEnabledElement.d.ts.map +1 -1
- package/dist/types/tools/annotation/CircleROITool.d.ts.map +1 -1
- package/dist/types/tools/displayTools/Labelmap/addLabelmapToElement.d.ts +2 -1
- package/dist/types/tools/displayTools/Labelmap/addLabelmapToElement.d.ts.map +1 -1
- package/dist/types/tools/displayTools/Labelmap/labelmapDisplay.d.ts +1 -1
- package/dist/types/tools/displayTools/Labelmap/labelmapDisplay.d.ts.map +1 -1
- package/dist/types/tools/displayTools/Labelmap/validateRepresentationData.d.ts.map +1 -1
- package/dist/types/tools/segmentation/BrushTool.d.ts.map +1 -1
- package/dist/types/tools/segmentation/CircleScissorsTool.d.ts +4 -2
- package/dist/types/tools/segmentation/CircleScissorsTool.d.ts.map +1 -1
- package/dist/types/tools/segmentation/PaintFillTool.d.ts.map +1 -1
- package/dist/types/tools/segmentation/RectangleScissorsTool.d.ts +3 -1
- package/dist/types/tools/segmentation/RectangleScissorsTool.d.ts.map +1 -1
- package/dist/types/tools/segmentation/SphereScissorsTool.d.ts +4 -2
- package/dist/types/tools/segmentation/SphereScissorsTool.d.ts.map +1 -1
- package/dist/types/tools/segmentation/strategies/eraseCircle.d.ts +2 -10
- package/dist/types/tools/segmentation/strategies/eraseCircle.d.ts.map +1 -1
- package/dist/types/tools/segmentation/strategies/eraseRectangle.d.ts +4 -8
- package/dist/types/tools/segmentation/strategies/eraseRectangle.d.ts.map +1 -1
- package/dist/types/tools/segmentation/strategies/eraseSphere.d.ts +2 -10
- package/dist/types/tools/segmentation/strategies/eraseSphere.d.ts.map +1 -1
- package/dist/types/tools/segmentation/strategies/fillCircle.d.ts +3 -11
- package/dist/types/tools/segmentation/strategies/fillCircle.d.ts.map +1 -1
- package/dist/types/tools/segmentation/strategies/fillRectangle.d.ts +2 -7
- package/dist/types/tools/segmentation/strategies/fillRectangle.d.ts.map +1 -1
- package/dist/types/tools/segmentation/strategies/fillSphere.d.ts +2 -10
- package/dist/types/tools/segmentation/strategies/fillSphere.d.ts.map +1 -1
- package/dist/types/tools/segmentation/strategies/utils/getStrategyData.d.ts +10 -0
- package/dist/types/tools/segmentation/strategies/utils/getStrategyData.d.ts.map +1 -0
- package/dist/types/tools/segmentation/strategies/utils/isWithinThreshold.d.ts +2 -2
- package/dist/types/tools/segmentation/strategies/utils/isWithinThreshold.d.ts.map +1 -1
- package/dist/types/tools/segmentation/strategies/utils/stackVolumeCheck.d.ts +6 -0
- package/dist/types/tools/segmentation/strategies/utils/stackVolumeCheck.d.ts.map +1 -0
- package/dist/types/types/LabelmapToolOperationData.d.ts +15 -0
- package/dist/types/types/LabelmapToolOperationData.d.ts.map +1 -0
- package/dist/types/types/LabelmapTypes.d.ts +5 -1
- package/dist/types/types/LabelmapTypes.d.ts.map +1 -1
- package/dist/types/types/index.d.ts +2 -1
- package/dist/types/types/index.d.ts.map +1 -1
- package/dist/types/utilities/math/ellipse/pointInEllipse.d.ts +7 -9
- package/dist/types/utilities/math/ellipse/pointInEllipse.d.ts.map +1 -1
- package/dist/umd/index.js +1 -1
- package/dist/umd/index.js.map +1 -1
- package/package.json +3 -3
- package/src/eventListeners/index.ts +2 -0
- package/src/eventListeners/segmentation/imageChangeEventListener.ts +215 -0
- package/src/eventListeners/segmentation/index.ts +2 -0
- package/src/eventListeners/segmentation/segmentationDataModifiedEventListener.ts +70 -9
- package/src/store/addEnabledElement.ts +2 -0
- package/src/store/removeEnabledElement.ts +3 -0
- package/src/tools/annotation/CircleROITool.ts +5 -5
- package/src/tools/annotation/EllipticalROITool.ts +1 -1
- package/src/tools/displayTools/Labelmap/addLabelmapToElement.ts +51 -22
- package/src/tools/displayTools/Labelmap/labelmapDisplay.ts +65 -35
- package/src/tools/displayTools/Labelmap/validateRepresentationData.ts +17 -11
- package/src/tools/segmentation/BrushTool.ts +78 -39
- package/src/tools/segmentation/CircleScissorsTool.ts +46 -29
- package/src/tools/segmentation/PaintFillTool.ts +45 -8
- package/src/tools/segmentation/RectangleScissorsTool.ts +41 -31
- package/src/tools/segmentation/SphereScissorsTool.ts +46 -28
- package/src/tools/segmentation/strategies/eraseCircle.ts +3 -11
- package/src/tools/segmentation/strategies/eraseRectangle.ts +13 -42
- package/src/tools/segmentation/strategies/eraseSphere.ts +2 -10
- package/src/tools/segmentation/strategies/fillCircle.ts +93 -61
- package/src/tools/segmentation/strategies/fillRectangle.ts +31 -22
- package/src/tools/segmentation/strategies/fillSphere.ts +51 -41
- package/src/tools/segmentation/strategies/utils/getStrategyData.ts +58 -0
- package/src/tools/segmentation/strategies/utils/isWithinThreshold.ts +3 -2
- package/src/tools/segmentation/strategies/utils/stackVolumeCheck.ts +33 -0
- package/src/types/LabelmapToolOperationData.ts +27 -0
- package/src/types/LabelmapTypes.ts +16 -1
- package/src/types/index.ts +8 -0
- package/src/utilities/math/ellipse/pointInEllipse.ts +43 -22
|
@@ -1,19 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { utilities as csUtils } from '@cornerstonejs/core';
|
|
2
2
|
import type { Types } from '@cornerstonejs/core';
|
|
3
3
|
|
|
4
4
|
import { getBoundingBoxAroundShape } from '../../../utilities/boundingBox';
|
|
5
5
|
import { pointInShapeCallback } from '../../../utilities';
|
|
6
6
|
import { triggerSegmentationDataModified } from '../../../stateManagement/segmentation/triggerSegmentationEvents';
|
|
7
|
+
import { LabelmapToolOperationData } from '../../../types';
|
|
8
|
+
import { getStrategyData } from './utils/getStrategyData';
|
|
7
9
|
|
|
8
10
|
const { transformWorldToIndex } = csUtils;
|
|
9
11
|
|
|
10
|
-
type OperationData = {
|
|
11
|
-
segmentationId: string;
|
|
12
|
+
type OperationData = LabelmapToolOperationData & {
|
|
12
13
|
points: [Types.Point3, Types.Point3, Types.Point3, Types.Point3];
|
|
13
|
-
volume: ImageVolume;
|
|
14
|
-
constraintFn: (x: [number, number, number]) => boolean;
|
|
15
|
-
segmentIndex: number;
|
|
16
|
-
segmentsLocked: number[];
|
|
17
14
|
};
|
|
18
15
|
|
|
19
16
|
/**
|
|
@@ -30,19 +27,23 @@ function fillRectangle(
|
|
|
30
27
|
operationData: OperationData,
|
|
31
28
|
inside = true
|
|
32
29
|
): void {
|
|
33
|
-
const {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
30
|
+
const { points, segmentsLocked, segmentIndex, segmentationId, constraintFn } =
|
|
31
|
+
operationData;
|
|
32
|
+
|
|
33
|
+
const strategyData = getStrategyData({
|
|
34
|
+
operationData,
|
|
35
|
+
viewport: enabledElement.viewport,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
if (!strategyData) {
|
|
39
|
+
console.warn('No data found for fillRectangle');
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const { segmentationImageData, segmentationScalarData } = strategyData;
|
|
43
44
|
|
|
44
45
|
let rectangleCornersIJK = points.map((world) => {
|
|
45
|
-
return transformWorldToIndex(
|
|
46
|
+
return transformWorldToIndex(segmentationImageData, world);
|
|
46
47
|
});
|
|
47
48
|
|
|
48
49
|
// math round
|
|
@@ -52,7 +53,10 @@ function fillRectangle(
|
|
|
52
53
|
});
|
|
53
54
|
});
|
|
54
55
|
|
|
55
|
-
const boundsIJK = getBoundingBoxAroundShape(
|
|
56
|
+
const boundsIJK = getBoundingBoxAroundShape(
|
|
57
|
+
rectangleCornersIJK,
|
|
58
|
+
segmentationImageData.getDimensions()
|
|
59
|
+
);
|
|
56
60
|
|
|
57
61
|
// Since always all points inside the boundsIJK is inside the rectangle...
|
|
58
62
|
const pointInRectangle = () => true;
|
|
@@ -63,16 +67,21 @@ function fillRectangle(
|
|
|
63
67
|
}
|
|
64
68
|
|
|
65
69
|
if (!constraintFn) {
|
|
66
|
-
|
|
70
|
+
segmentationScalarData[index] = segmentIndex;
|
|
67
71
|
return;
|
|
68
72
|
}
|
|
69
73
|
|
|
70
74
|
if (constraintFn(pointIJK)) {
|
|
71
|
-
|
|
75
|
+
segmentationScalarData[index] = segmentIndex;
|
|
72
76
|
}
|
|
73
77
|
};
|
|
74
78
|
|
|
75
|
-
pointInShapeCallback(
|
|
79
|
+
pointInShapeCallback(
|
|
80
|
+
segmentationImageData,
|
|
81
|
+
pointInRectangle,
|
|
82
|
+
callback,
|
|
83
|
+
boundsIJK
|
|
84
|
+
);
|
|
76
85
|
|
|
77
86
|
triggerSegmentationDataModified(segmentationId);
|
|
78
87
|
}
|
|
@@ -1,21 +1,15 @@
|
|
|
1
1
|
import type { Types } from '@cornerstonejs/core';
|
|
2
|
-
import { utilities as csUtils } from '@cornerstonejs/core';
|
|
2
|
+
import { cache, utilities as csUtils } from '@cornerstonejs/core';
|
|
3
3
|
|
|
4
4
|
import { triggerSegmentationDataModified } from '../../../stateManagement/segmentation/triggerSegmentationEvents';
|
|
5
5
|
import { pointInSurroundingSphereCallback } from '../../../utilities';
|
|
6
6
|
import isWithinThreshold from './utils/isWithinThreshold';
|
|
7
|
+
import { LabelmapToolOperationData } from '../../../types';
|
|
8
|
+
import { getStrategyData } from './utils/getStrategyData';
|
|
9
|
+
import { isVolumeSegmentation } from './utils/stackVolumeCheck';
|
|
7
10
|
|
|
8
|
-
type OperationData = {
|
|
11
|
+
type OperationData = LabelmapToolOperationData & {
|
|
9
12
|
points: [Types.Point3, Types.Point3, Types.Point3, Types.Point3];
|
|
10
|
-
volume: Types.IImageVolume;
|
|
11
|
-
imageVolume: Types.IImageVolume;
|
|
12
|
-
segmentIndex: number;
|
|
13
|
-
segmentationId: string;
|
|
14
|
-
segmentsLocked: number[];
|
|
15
|
-
viewPlaneNormal: Types.Point3;
|
|
16
|
-
viewUp: Types.Point3;
|
|
17
|
-
strategySpecificConfiguration: any;
|
|
18
|
-
constraintFn: () => boolean;
|
|
19
13
|
};
|
|
20
14
|
|
|
21
15
|
function fillSphere(
|
|
@@ -26,31 +20,36 @@ function fillSphere(
|
|
|
26
20
|
): void {
|
|
27
21
|
const { viewport } = enabledElement;
|
|
28
22
|
const {
|
|
29
|
-
volume: segmentation,
|
|
30
23
|
segmentsLocked,
|
|
31
24
|
segmentIndex,
|
|
32
|
-
imageVolume,
|
|
33
25
|
strategySpecificConfiguration,
|
|
34
|
-
segmentationId,
|
|
35
26
|
points,
|
|
36
27
|
} = operationData;
|
|
37
28
|
|
|
38
|
-
const {
|
|
39
|
-
|
|
29
|
+
const strategyData = getStrategyData({ operationData, viewport });
|
|
30
|
+
|
|
31
|
+
if (!strategyData) {
|
|
32
|
+
console.warn('No data found for fillSphere');
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const { imageScalarData, segmentationImageData, segmentationScalarData } =
|
|
37
|
+
strategyData;
|
|
38
|
+
|
|
40
39
|
const scalarIndex = [];
|
|
41
40
|
|
|
42
41
|
let callback;
|
|
43
42
|
|
|
44
43
|
if (threshold) {
|
|
45
|
-
callback = ({ value, index
|
|
44
|
+
callback = ({ value, index }) => {
|
|
46
45
|
if (segmentsLocked.includes(value)) {
|
|
47
46
|
return;
|
|
48
47
|
}
|
|
49
48
|
|
|
50
49
|
if (
|
|
51
|
-
isWithinThreshold(index,
|
|
50
|
+
isWithinThreshold(index, imageScalarData, strategySpecificConfiguration)
|
|
52
51
|
) {
|
|
53
|
-
|
|
52
|
+
segmentationScalarData[index] = segmentIndex;
|
|
54
53
|
scalarIndex.push(index);
|
|
55
54
|
}
|
|
56
55
|
};
|
|
@@ -59,30 +58,36 @@ function fillSphere(
|
|
|
59
58
|
if (segmentsLocked.includes(value)) {
|
|
60
59
|
return;
|
|
61
60
|
}
|
|
62
|
-
|
|
61
|
+
segmentationScalarData[index] = segmentIndex;
|
|
63
62
|
scalarIndex.push(index);
|
|
64
63
|
};
|
|
65
64
|
}
|
|
66
65
|
|
|
67
66
|
pointInSurroundingSphereCallback(
|
|
68
|
-
|
|
67
|
+
segmentationImageData,
|
|
69
68
|
[points[0], points[1]],
|
|
70
69
|
callback,
|
|
71
70
|
viewport as Types.IVolumeViewport
|
|
72
71
|
);
|
|
73
72
|
|
|
74
|
-
|
|
75
|
-
// slice that needs to be rendered can be calculated from the first mask coordinate
|
|
76
|
-
// divided by the zMultiple, as well as the last slice for the last coordinate
|
|
77
|
-
const zMultiple = dimensions[0] * dimensions[1];
|
|
78
|
-
const minSlice = Math.floor(scalarIndex[0] / zMultiple);
|
|
79
|
-
const maxSlice = Math.floor(scalarIndex[scalarIndex.length - 1] / zMultiple);
|
|
80
|
-
const sliceArray = Array.from(
|
|
81
|
-
{ length: maxSlice - minSlice + 1 },
|
|
82
|
-
(v, k) => k + minSlice
|
|
83
|
-
);
|
|
73
|
+
const dimensions = segmentationImageData.getDimensions();
|
|
84
74
|
|
|
85
|
-
|
|
75
|
+
let sliceArray;
|
|
76
|
+
if (isVolumeSegmentation(operationData)) {
|
|
77
|
+
// Since the scalar indexes start from the top left corner of the cube, the first
|
|
78
|
+
// slice that needs to be rendered can be calculated from the first mask coordinate
|
|
79
|
+
// divided by the zMultiple, as well as the last slice for the last coordinate
|
|
80
|
+
const zMultiple = dimensions[0] * dimensions[1];
|
|
81
|
+
const minSlice = Math.floor(scalarIndex[0] / zMultiple);
|
|
82
|
+
const maxSlice = Math.floor(
|
|
83
|
+
scalarIndex[scalarIndex.length - 1] / zMultiple
|
|
84
|
+
);
|
|
85
|
+
sliceArray = Array.from(
|
|
86
|
+
{ length: maxSlice - minSlice + 1 },
|
|
87
|
+
(v, k) => k + minSlice
|
|
88
|
+
);
|
|
89
|
+
triggerSegmentationDataModified(operationData.volumeId, sliceArray);
|
|
90
|
+
}
|
|
86
91
|
}
|
|
87
92
|
|
|
88
93
|
/**
|
|
@@ -108,15 +113,20 @@ export function thresholdInsideSphere(
|
|
|
108
113
|
enabledElement: Types.IEnabledElement,
|
|
109
114
|
operationData: OperationData
|
|
110
115
|
): void {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
116
|
+
if (isVolumeSegmentation(operationData)) {
|
|
117
|
+
const { referencedVolumeId, volumeId } = operationData;
|
|
118
|
+
|
|
119
|
+
const imageVolume = cache.getVolume(referencedVolumeId);
|
|
120
|
+
const segmentation = cache.getVolume(volumeId);
|
|
121
|
+
|
|
122
|
+
if (
|
|
123
|
+
!csUtils.isEqual(segmentation.dimensions, imageVolume.dimensions) ||
|
|
124
|
+
!csUtils.isEqual(segmentation.direction, imageVolume.direction)
|
|
125
|
+
) {
|
|
126
|
+
throw new Error(
|
|
127
|
+
'Only source data the same dimensions/size/orientation as the segmentation currently supported.'
|
|
128
|
+
);
|
|
129
|
+
}
|
|
120
130
|
}
|
|
121
131
|
|
|
122
132
|
fillSphere(enabledElement, operationData, true, true);
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { cache } from '@cornerstonejs/core';
|
|
2
|
+
import { isVolumeSegmentation } from './stackVolumeCheck';
|
|
3
|
+
import { LabelmapToolOperationDataStack } from '../../../../types';
|
|
4
|
+
|
|
5
|
+
function getStrategyData({ operationData, viewport }) {
|
|
6
|
+
let segmentationImageData, segmentationScalarData, imageScalarData;
|
|
7
|
+
if (isVolumeSegmentation(operationData)) {
|
|
8
|
+
const { volumeId, referencedVolumeId } = operationData;
|
|
9
|
+
|
|
10
|
+
const segmentationVolume = cache.getVolume(volumeId);
|
|
11
|
+
const imageVolume = cache.getVolume(referencedVolumeId);
|
|
12
|
+
|
|
13
|
+
if (!segmentationVolume || !imageVolume) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
({ imageData: segmentationImageData } = segmentationVolume);
|
|
18
|
+
segmentationScalarData = segmentationVolume.getScalarData();
|
|
19
|
+
imageScalarData = imageVolume.getScalarData();
|
|
20
|
+
} else {
|
|
21
|
+
const { imageIdReferenceMap, segmentationRepresentationUID } =
|
|
22
|
+
operationData as LabelmapToolOperationDataStack;
|
|
23
|
+
|
|
24
|
+
if (!imageIdReferenceMap) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const currentImageId = viewport.getCurrentImageId();
|
|
29
|
+
if (!currentImageId) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// we know that the segmentationRepresentationUID is the name of the actor always
|
|
34
|
+
// and always circle modifies the current imageId which in fact is the imageData
|
|
35
|
+
// of that actor at that moment so we have the imageData already
|
|
36
|
+
const actor = viewport.getActor(segmentationRepresentationUID);
|
|
37
|
+
segmentationImageData = actor.actor.getMapper().getInputData();
|
|
38
|
+
const currentSegmentationImageId = imageIdReferenceMap.get(currentImageId);
|
|
39
|
+
|
|
40
|
+
const segmentationImage = cache.getImage(currentSegmentationImageId);
|
|
41
|
+
segmentationScalarData = segmentationImage.getPixelData();
|
|
42
|
+
|
|
43
|
+
const image = cache.getImage(currentImageId);
|
|
44
|
+
|
|
45
|
+
// VERY IMPORTANT
|
|
46
|
+
// This is the pixel data of the image that is being segmented in the cache
|
|
47
|
+
// and we need to use this to for the modification
|
|
48
|
+
imageScalarData = image.getPixelData();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
segmentationImageData,
|
|
53
|
+
segmentationScalarData,
|
|
54
|
+
imageScalarData,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export { getStrategyData };
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { Types } from '@cornerstonejs/core';
|
|
2
|
+
import { TypedArray } from '@kitware/vtk.js/types';
|
|
2
3
|
|
|
3
4
|
function isWithinThreshold(
|
|
4
5
|
index: number,
|
|
5
|
-
|
|
6
|
+
imageScalarData: TypedArray,
|
|
6
7
|
strategySpecificConfiguration: any
|
|
7
8
|
) {
|
|
8
9
|
const { THRESHOLD_INSIDE_CIRCLE } = strategySpecificConfiguration;
|
|
9
10
|
|
|
10
|
-
const voxelValue =
|
|
11
|
+
const voxelValue = imageScalarData[index];
|
|
11
12
|
const { threshold } = THRESHOLD_INSIDE_CIRCLE;
|
|
12
13
|
|
|
13
14
|
return threshold[0] <= voxelValue && voxelValue <= threshold[1];
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LabelmapSegmentationData,
|
|
3
|
+
LabelmapSegmentationDataStack,
|
|
4
|
+
LabelmapSegmentationDataVolume,
|
|
5
|
+
} from '../../../../types/LabelmapTypes';
|
|
6
|
+
import {
|
|
7
|
+
LabelmapToolOperationData,
|
|
8
|
+
LabelmapToolOperationDataStack,
|
|
9
|
+
LabelmapToolOperationDataVolume,
|
|
10
|
+
} from '../../../../types';
|
|
11
|
+
|
|
12
|
+
function isStackSegmentation(
|
|
13
|
+
operationData: LabelmapToolOperationData | LabelmapSegmentationData
|
|
14
|
+
): operationData is
|
|
15
|
+
| LabelmapToolOperationDataStack
|
|
16
|
+
| LabelmapSegmentationDataStack {
|
|
17
|
+
return (
|
|
18
|
+
(operationData as LabelmapToolOperationDataStack).imageIdReferenceMap !==
|
|
19
|
+
undefined
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function isVolumeSegmentation(
|
|
24
|
+
operationData: LabelmapToolOperationData | LabelmapSegmentationData
|
|
25
|
+
): operationData is
|
|
26
|
+
| LabelmapToolOperationDataVolume
|
|
27
|
+
| LabelmapSegmentationDataVolume {
|
|
28
|
+
return (
|
|
29
|
+
(operationData as LabelmapToolOperationDataVolume).volumeId !== undefined
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export { isStackSegmentation, isVolumeSegmentation };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LabelmapSegmentationDataStack,
|
|
3
|
+
LabelmapSegmentationDataVolume,
|
|
4
|
+
} from './LabelmapTypes';
|
|
5
|
+
|
|
6
|
+
type LabelmapToolOperationData = {
|
|
7
|
+
segmentationId: string;
|
|
8
|
+
segmentIndex: number;
|
|
9
|
+
segmentsLocked: number[];
|
|
10
|
+
viewPlaneNormal: number[];
|
|
11
|
+
viewUp: number[];
|
|
12
|
+
strategySpecificConfiguration: any;
|
|
13
|
+
constraintFn: (pointIJK: number) => boolean;
|
|
14
|
+
segmentationRepresentationUID: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
type LabelmapToolOperationDataStack = LabelmapToolOperationData &
|
|
18
|
+
LabelmapSegmentationDataStack;
|
|
19
|
+
|
|
20
|
+
type LabelmapToolOperationDataVolume = LabelmapToolOperationData &
|
|
21
|
+
LabelmapSegmentationDataVolume;
|
|
22
|
+
|
|
23
|
+
export {
|
|
24
|
+
LabelmapToolOperationData,
|
|
25
|
+
LabelmapToolOperationDataStack,
|
|
26
|
+
LabelmapToolOperationDataVolume,
|
|
27
|
+
};
|
|
@@ -35,7 +35,22 @@ export type LabelmapRenderingConfig = {
|
|
|
35
35
|
ofun?: vtkPiecewiseFunction;
|
|
36
36
|
};
|
|
37
37
|
|
|
38
|
-
export type
|
|
38
|
+
export type LabelmapSegmentationDataVolume = {
|
|
39
39
|
volumeId: string;
|
|
40
40
|
referencedVolumeId?: string;
|
|
41
41
|
};
|
|
42
|
+
|
|
43
|
+
export type LabelmapSegmentationDataStack = {
|
|
44
|
+
/**
|
|
45
|
+
* This is a Map from referenced imageId to the segmentation (Derived) imageId that
|
|
46
|
+
* has been used to create the derived labelmap.
|
|
47
|
+
* Todo: later I guess we can have it as Record<string, metadata> where metadata
|
|
48
|
+
* can contain a derived image arbitrary information, for use cases such that the labelmap is
|
|
49
|
+
* derived from another image that is irrelevant to the current viewport.
|
|
50
|
+
*/
|
|
51
|
+
imageIdReferenceMap: Map<string, string>;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export type LabelmapSegmentationData =
|
|
55
|
+
| LabelmapSegmentationDataVolume
|
|
56
|
+
| LabelmapSegmentationDataStack;
|
package/src/types/index.ts
CHANGED
|
@@ -58,6 +58,11 @@ import type { ContourSegmentationData } from './ContourTypes';
|
|
|
58
58
|
import type IAnnotationManager from './IAnnotationManager';
|
|
59
59
|
import type AnnotationGroupSelector from './AnnotationGroupSelector';
|
|
60
60
|
import type { Statistics } from './CalculatorTypes';
|
|
61
|
+
import {
|
|
62
|
+
LabelmapToolOperationData,
|
|
63
|
+
LabelmapToolOperationDataStack,
|
|
64
|
+
LabelmapToolOperationDataVolume,
|
|
65
|
+
} from './LabelmapToolOperationData';
|
|
61
66
|
|
|
62
67
|
export type {
|
|
63
68
|
// AnnotationState
|
|
@@ -124,4 +129,7 @@ export type {
|
|
|
124
129
|
ContourSegmentationData,
|
|
125
130
|
//Statistics
|
|
126
131
|
Statistics,
|
|
132
|
+
LabelmapToolOperationData,
|
|
133
|
+
LabelmapToolOperationDataStack,
|
|
134
|
+
LabelmapToolOperationDataVolume,
|
|
127
135
|
};
|
|
@@ -1,39 +1,60 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
yRadius: number;
|
|
8
|
-
zRadius: number;
|
|
9
|
-
};
|
|
1
|
+
interface Inverts {
|
|
2
|
+
invXRadiusSq?: number;
|
|
3
|
+
invYRadiusSq?: number;
|
|
4
|
+
invZRadiusSq?: number;
|
|
5
|
+
fast?: boolean;
|
|
6
|
+
}
|
|
10
7
|
|
|
11
8
|
/**
|
|
12
9
|
* Given an ellipse and a point, return true if the point is inside the ellipse
|
|
13
10
|
* @param ellipse - The ellipse object to check against.
|
|
14
11
|
* @param pointLPS - The point in LPS space to test.
|
|
12
|
+
* @param inverts - An object to cache the inverted radius squared values, if you
|
|
13
|
+
* are testing multiple points against the same ellipse then it is recommended to
|
|
14
|
+
* pass in the same object to cache the values. However, there is a simpler way
|
|
15
|
+
* to do this by passing in the fast flag as true, then on the first iteration
|
|
16
|
+
* the values will be cached and on subsequent iterations the cached values will
|
|
17
|
+
* be used.
|
|
18
|
+
*
|
|
15
19
|
* @returns A boolean value.
|
|
16
20
|
*/
|
|
17
21
|
export default function pointInEllipse(
|
|
18
|
-
ellipse
|
|
19
|
-
pointLPS
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
const [x0, y0, z0] = circleCenterWorld;
|
|
22
|
+
ellipse,
|
|
23
|
+
pointLPS,
|
|
24
|
+
inverts: Inverts = {}
|
|
25
|
+
) {
|
|
26
|
+
const { center, xRadius, yRadius, zRadius } = ellipse;
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
// This will run only once since we are caching the values in the same
|
|
29
|
+
// object that is passed in.
|
|
30
|
+
if (
|
|
31
|
+
inverts.invXRadiusSq === undefined ||
|
|
32
|
+
inverts.invYRadiusSq === undefined ||
|
|
33
|
+
inverts.invZRadiusSq === undefined
|
|
34
|
+
) {
|
|
35
|
+
inverts.invXRadiusSq = xRadius !== 0 ? 1 / xRadius ** 2 : 0;
|
|
36
|
+
inverts.invYRadiusSq = yRadius !== 0 ? 1 / yRadius ** 2 : 0;
|
|
37
|
+
inverts.invZRadiusSq = zRadius !== 0 ? 1 / zRadius ** 2 : 0;
|
|
28
38
|
}
|
|
29
39
|
|
|
30
|
-
|
|
31
|
-
|
|
40
|
+
let inside = 0;
|
|
41
|
+
|
|
42
|
+
// Calculate the sum of normalized squared distances
|
|
43
|
+
const dx = pointLPS[0] - center[0];
|
|
44
|
+
inside += dx * dx * inverts.invXRadiusSq;
|
|
45
|
+
if (inside > 1) {
|
|
46
|
+
return false;
|
|
32
47
|
}
|
|
33
48
|
|
|
34
|
-
|
|
35
|
-
|
|
49
|
+
const dy = pointLPS[1] - center[1];
|
|
50
|
+
inside += dy * dy * inverts.invYRadiusSq;
|
|
51
|
+
if (inside > 1) {
|
|
52
|
+
return false;
|
|
36
53
|
}
|
|
37
54
|
|
|
55
|
+
const dz = pointLPS[2] - center[2];
|
|
56
|
+
inside += dz * dz * inverts.invZRadiusSq;
|
|
57
|
+
|
|
58
|
+
// Check if the point is inside the ellipse
|
|
38
59
|
return inside <= 1;
|
|
39
60
|
}
|