@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
|
@@ -12,12 +12,16 @@ import { fillInsideRectangle } from './strategies/fillRectangle';
|
|
|
12
12
|
import { eraseInsideRectangle } from './strategies/eraseRectangle';
|
|
13
13
|
import { getViewportIdsWithToolToRender } from '../../utilities/viewportFilters';
|
|
14
14
|
|
|
15
|
-
import { Events } from '../../enums';
|
|
15
|
+
import { Events, SegmentationRepresentations } from '../../enums';
|
|
16
16
|
import { drawRect as drawRectSvg } from '../../drawingSvg';
|
|
17
17
|
import {
|
|
18
18
|
resetElementCursor,
|
|
19
19
|
hideElementCursor,
|
|
20
20
|
} from '../../cursors/elementCursor';
|
|
21
|
+
import {
|
|
22
|
+
LabelmapSegmentationDataStack,
|
|
23
|
+
LabelmapSegmentationDataVolume,
|
|
24
|
+
} from '../../types/LabelmapTypes';
|
|
21
25
|
|
|
22
26
|
import triggerAnnotationRenderForViewportIds from '../../utilities/triggerAnnotationRenderForViewportIds';
|
|
23
27
|
import {
|
|
@@ -29,6 +33,7 @@ import {
|
|
|
29
33
|
|
|
30
34
|
import { getSegmentation } from '../../stateManagement/segmentation/segmentationState';
|
|
31
35
|
import { LabelmapSegmentationData } from '../../types/LabelmapTypes';
|
|
36
|
+
import { isVolumeSegmentation } from './strategies/utils/stackVolumeCheck';
|
|
32
37
|
|
|
33
38
|
/**
|
|
34
39
|
* Tool for manipulating segmentation data by drawing a rectangle. It acts on the
|
|
@@ -41,9 +46,13 @@ class RectangleScissorsTool extends BaseTool {
|
|
|
41
46
|
static toolName;
|
|
42
47
|
_throttledCalculateCachedStats: any;
|
|
43
48
|
editData: {
|
|
49
|
+
//
|
|
50
|
+
imageIdReferenceMap: Map<string, string>;
|
|
51
|
+
volumeId: string;
|
|
52
|
+
referencedVolumeId: string;
|
|
53
|
+
//
|
|
44
54
|
annotation: any;
|
|
45
55
|
segmentationId: string;
|
|
46
|
-
segmentation: any;
|
|
47
56
|
segmentIndex: number;
|
|
48
57
|
segmentsLocked: number[];
|
|
49
58
|
segmentColor: [number, number, number, number];
|
|
@@ -116,10 +125,9 @@ class RectangleScissorsTool extends BaseTool {
|
|
|
116
125
|
);
|
|
117
126
|
|
|
118
127
|
const { representationData } = getSegmentation(segmentationId);
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
const segmentation = cache.getVolume(volumeId);
|
|
128
|
+
const labelmapData = representationData[
|
|
129
|
+
SegmentationRepresentations.Labelmap
|
|
130
|
+
] as LabelmapSegmentationData;
|
|
123
131
|
|
|
124
132
|
// Todo: Used for drawing the svg only, we might not need it at all
|
|
125
133
|
const annotation = {
|
|
@@ -150,20 +158,38 @@ class RectangleScissorsTool extends BaseTool {
|
|
|
150
158
|
element,
|
|
151
159
|
this.getToolName()
|
|
152
160
|
);
|
|
153
|
-
|
|
154
161
|
this.editData = {
|
|
155
162
|
annotation,
|
|
156
|
-
segmentation,
|
|
157
163
|
segmentIndex,
|
|
164
|
+
segmentationId,
|
|
158
165
|
segmentsLocked,
|
|
159
166
|
segmentColor,
|
|
160
|
-
segmentationId,
|
|
161
167
|
viewportIdsToRender,
|
|
162
168
|
handleIndex: 3,
|
|
163
169
|
movingTextBox: false,
|
|
164
170
|
newAnnotation: true,
|
|
165
171
|
hasMoved: false,
|
|
166
|
-
|
|
172
|
+
segmentationRepresentationUID,
|
|
173
|
+
} as any;
|
|
174
|
+
|
|
175
|
+
if (isVolumeSegmentation(labelmapData as LabelmapSegmentationData)) {
|
|
176
|
+
const { volumeId } = labelmapData as LabelmapSegmentationDataVolume;
|
|
177
|
+
const segmentation = cache.getVolume(volumeId);
|
|
178
|
+
|
|
179
|
+
this.editData = {
|
|
180
|
+
...this.editData,
|
|
181
|
+
volumeId,
|
|
182
|
+
referencedVolumeId: segmentation.referencedVolumeId,
|
|
183
|
+
};
|
|
184
|
+
} else {
|
|
185
|
+
const { imageIdReferenceMap } =
|
|
186
|
+
labelmapData as LabelmapSegmentationDataStack;
|
|
187
|
+
|
|
188
|
+
this.editData = {
|
|
189
|
+
...this.editData,
|
|
190
|
+
imageIdReferenceMap,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
167
193
|
|
|
168
194
|
this._activateDraw(element);
|
|
169
195
|
|
|
@@ -257,15 +283,7 @@ class RectangleScissorsTool extends BaseTool {
|
|
|
257
283
|
const eventDetail = evt.detail;
|
|
258
284
|
const { element } = eventDetail;
|
|
259
285
|
|
|
260
|
-
const {
|
|
261
|
-
annotation,
|
|
262
|
-
newAnnotation,
|
|
263
|
-
hasMoved,
|
|
264
|
-
segmentation,
|
|
265
|
-
segmentationId,
|
|
266
|
-
segmentIndex,
|
|
267
|
-
segmentsLocked,
|
|
268
|
-
} = this.editData;
|
|
286
|
+
const { annotation, newAnnotation, hasMoved } = this.editData;
|
|
269
287
|
const { data } = annotation;
|
|
270
288
|
|
|
271
289
|
if (newAnnotation && !hasMoved) {
|
|
@@ -279,23 +297,15 @@ class RectangleScissorsTool extends BaseTool {
|
|
|
279
297
|
resetElementCursor(element);
|
|
280
298
|
|
|
281
299
|
const enabledElement = getEnabledElement(element);
|
|
282
|
-
const { viewport } = enabledElement;
|
|
283
|
-
|
|
284
|
-
this.editData = null;
|
|
285
|
-
this.isDrawing = false;
|
|
286
|
-
|
|
287
|
-
if (viewport instanceof StackViewport) {
|
|
288
|
-
throw new Error('Not implemented yet');
|
|
289
|
-
}
|
|
290
300
|
|
|
291
301
|
const operationData = {
|
|
302
|
+
...this.editData,
|
|
292
303
|
points: data.handles.points,
|
|
293
|
-
volume: segmentation,
|
|
294
|
-
segmentationId,
|
|
295
|
-
segmentIndex,
|
|
296
|
-
segmentsLocked,
|
|
297
304
|
};
|
|
298
305
|
|
|
306
|
+
this.editData = null;
|
|
307
|
+
this.isDrawing = false;
|
|
308
|
+
|
|
299
309
|
this.applyActiveStrategy(enabledElement, operationData);
|
|
300
310
|
};
|
|
301
311
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { cache, getEnabledElement
|
|
1
|
+
import { cache, getEnabledElement } from '@cornerstonejs/core';
|
|
2
2
|
import type { Types } from '@cornerstonejs/core';
|
|
3
3
|
|
|
4
4
|
import { BaseTool } from '../base';
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from '../../types';
|
|
11
11
|
|
|
12
12
|
import { fillInsideSphere } from './strategies/fillSphere';
|
|
13
|
-
import { Events } from '../../enums';
|
|
13
|
+
import { Events, SegmentationRepresentations } from '../../enums';
|
|
14
14
|
import { drawCircle as drawCircleSvg } from '../../drawingSvg';
|
|
15
15
|
import {
|
|
16
16
|
resetElementCursor,
|
|
@@ -26,8 +26,12 @@ import {
|
|
|
26
26
|
} from '../../stateManagement/segmentation';
|
|
27
27
|
|
|
28
28
|
import { getSegmentation } from '../../stateManagement/segmentation/segmentationState';
|
|
29
|
-
import {
|
|
30
|
-
|
|
29
|
+
import {
|
|
30
|
+
LabelmapSegmentationData,
|
|
31
|
+
LabelmapSegmentationDataVolume,
|
|
32
|
+
LabelmapSegmentationDataStack,
|
|
33
|
+
} from '../../types/LabelmapTypes';
|
|
34
|
+
import { isVolumeSegmentation } from './strategies/utils/stackVolumeCheck';
|
|
31
35
|
/**
|
|
32
36
|
* Tool for manipulating segmentation data by drawing a sphere in 3d space. It acts on the
|
|
33
37
|
* active Segmentation on the viewport (enabled element) and requires an active
|
|
@@ -40,10 +44,14 @@ class SphereScissorsTool extends BaseTool {
|
|
|
40
44
|
static toolName;
|
|
41
45
|
editData: {
|
|
42
46
|
annotation: any;
|
|
43
|
-
segmentation: any;
|
|
44
47
|
segmentIndex: number;
|
|
45
48
|
segmentsLocked: number[];
|
|
46
|
-
|
|
49
|
+
segmentationRepresentationUID: string;
|
|
50
|
+
//
|
|
51
|
+
volumeId: string;
|
|
52
|
+
referencedVolumeId: string;
|
|
53
|
+
imageIdReferenceMap: Map<string, string>;
|
|
54
|
+
//
|
|
47
55
|
toolGroupId: string;
|
|
48
56
|
segmentColor: [number, number, number, number];
|
|
49
57
|
viewportIdsToRender: string[];
|
|
@@ -103,7 +111,7 @@ class SphereScissorsTool extends BaseTool {
|
|
|
103
111
|
);
|
|
104
112
|
}
|
|
105
113
|
|
|
106
|
-
const { segmentationRepresentationUID, segmentationId
|
|
114
|
+
const { segmentationRepresentationUID, segmentationId } =
|
|
107
115
|
activeSegmentationRepresentation;
|
|
108
116
|
const segmentIndex =
|
|
109
117
|
segmentIndexController.getActiveSegmentIndex(segmentationId);
|
|
@@ -115,12 +123,6 @@ class SphereScissorsTool extends BaseTool {
|
|
|
115
123
|
segmentIndex
|
|
116
124
|
);
|
|
117
125
|
|
|
118
|
-
const { representationData } = getSegmentation(segmentationId);
|
|
119
|
-
|
|
120
|
-
// Todo: are we going to support contour editing with rectangle scissors?
|
|
121
|
-
const { volumeId } = representationData[type] as LabelmapSegmentationData;
|
|
122
|
-
const segmentation = cache.getVolume(volumeId);
|
|
123
|
-
|
|
124
126
|
this.isDrawing = true;
|
|
125
127
|
|
|
126
128
|
// Used for drawing the svg only, we might not need it at all
|
|
@@ -148,19 +150,41 @@ class SphereScissorsTool extends BaseTool {
|
|
|
148
150
|
|
|
149
151
|
this.editData = {
|
|
150
152
|
annotation,
|
|
151
|
-
segmentation,
|
|
152
153
|
centerCanvas: canvasPos,
|
|
154
|
+
segmentationRepresentationUID,
|
|
153
155
|
segmentIndex,
|
|
154
156
|
segmentsLocked,
|
|
155
157
|
segmentColor,
|
|
156
|
-
segmentationId,
|
|
157
158
|
toolGroupId,
|
|
158
159
|
viewportIdsToRender,
|
|
159
160
|
handleIndex: 3,
|
|
160
161
|
movingTextBox: false,
|
|
161
162
|
newAnnotation: true,
|
|
162
163
|
hasMoved: false,
|
|
163
|
-
};
|
|
164
|
+
} as any;
|
|
165
|
+
|
|
166
|
+
const { representationData } = getSegmentation(segmentationId);
|
|
167
|
+
const labelmapData =
|
|
168
|
+
representationData[SegmentationRepresentations.Labelmap];
|
|
169
|
+
|
|
170
|
+
if (isVolumeSegmentation(labelmapData as LabelmapSegmentationData)) {
|
|
171
|
+
const { volumeId } = labelmapData as LabelmapSegmentationDataVolume;
|
|
172
|
+
const segmentation = cache.getVolume(volumeId);
|
|
173
|
+
|
|
174
|
+
this.editData = {
|
|
175
|
+
...this.editData,
|
|
176
|
+
volumeId,
|
|
177
|
+
referencedVolumeId: segmentation.referencedVolumeId,
|
|
178
|
+
};
|
|
179
|
+
} else {
|
|
180
|
+
const { imageIdReferenceMap } =
|
|
181
|
+
labelmapData as LabelmapSegmentationDataStack;
|
|
182
|
+
|
|
183
|
+
this.editData = {
|
|
184
|
+
...this.editData,
|
|
185
|
+
imageIdReferenceMap,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
164
188
|
|
|
165
189
|
this._activateDraw(element);
|
|
166
190
|
|
|
@@ -227,10 +251,9 @@ class SphereScissorsTool extends BaseTool {
|
|
|
227
251
|
annotation,
|
|
228
252
|
newAnnotation,
|
|
229
253
|
hasMoved,
|
|
230
|
-
segmentation,
|
|
231
254
|
segmentIndex,
|
|
255
|
+
segmentationRepresentationUID,
|
|
232
256
|
segmentsLocked,
|
|
233
|
-
segmentationId,
|
|
234
257
|
} = this.editData;
|
|
235
258
|
const { data } = annotation;
|
|
236
259
|
const { viewPlaneNormal, viewUp } = annotation.metadata;
|
|
@@ -246,25 +269,20 @@ class SphereScissorsTool extends BaseTool {
|
|
|
246
269
|
resetElementCursor(element);
|
|
247
270
|
|
|
248
271
|
const enabledElement = getEnabledElement(element);
|
|
249
|
-
const { viewport } = enabledElement;
|
|
250
|
-
|
|
251
|
-
this.editData = null;
|
|
252
|
-
this.isDrawing = false;
|
|
253
|
-
|
|
254
|
-
if (viewport instanceof StackViewport) {
|
|
255
|
-
throw new Error('Not implemented yet');
|
|
256
|
-
}
|
|
257
272
|
|
|
258
273
|
const operationData = {
|
|
274
|
+
...this.editData,
|
|
259
275
|
points: data.handles.points,
|
|
260
|
-
volume: segmentation,
|
|
261
276
|
segmentIndex,
|
|
277
|
+
segmentationRepresentationUID,
|
|
262
278
|
segmentsLocked,
|
|
263
|
-
segmentationId,
|
|
264
279
|
viewPlaneNormal,
|
|
265
280
|
viewUp,
|
|
266
281
|
};
|
|
267
282
|
|
|
283
|
+
this.editData = null;
|
|
284
|
+
this.isDrawing = false;
|
|
285
|
+
|
|
268
286
|
this.applyActiveStrategy(enabledElement, operationData);
|
|
269
287
|
};
|
|
270
288
|
|
|
@@ -1,18 +1,10 @@
|
|
|
1
1
|
import type { Types } from '@cornerstonejs/core';
|
|
2
2
|
|
|
3
3
|
import { fillInsideCircle } from './fillCircle';
|
|
4
|
+
import { LabelmapToolOperationData } from '../../../types';
|
|
4
5
|
|
|
5
|
-
type OperationData = {
|
|
6
|
-
|
|
7
|
-
imageVolume: Types.IImageVolume;
|
|
8
|
-
points: any; // Todo:fix
|
|
9
|
-
volume: Types.IImageVolume;
|
|
10
|
-
segmentIndex: number;
|
|
11
|
-
segmentsLocked: number[];
|
|
12
|
-
viewPlaneNormal: number[];
|
|
13
|
-
viewUp: number[];
|
|
14
|
-
strategySpecificConfiguration: any;
|
|
15
|
-
constraintFn: () => boolean;
|
|
6
|
+
type OperationData = LabelmapToolOperationData & {
|
|
7
|
+
points: any; // todo fix
|
|
16
8
|
};
|
|
17
9
|
|
|
18
10
|
export function eraseInsideCircle(
|
|
@@ -1,64 +1,35 @@
|
|
|
1
|
-
import { ImageVolume, utilities as csUtils } from '@cornerstonejs/core';
|
|
2
1
|
import type { Types } from '@cornerstonejs/core';
|
|
3
2
|
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { pointInShapeCallback } from '../../../utilities';
|
|
3
|
+
import { LabelmapToolOperationData } from '../../../types';
|
|
4
|
+
import { fillInsideRectangle } from './fillRectangle';
|
|
7
5
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
type EraseOperationData = {
|
|
11
|
-
segmentationId: string;
|
|
6
|
+
type OperationData = LabelmapToolOperationData & {
|
|
12
7
|
points: [Types.Point3, Types.Point3, Types.Point3, Types.Point3];
|
|
13
|
-
volume: ImageVolume;
|
|
14
|
-
constraintFn: (x: [number, number, number]) => boolean;
|
|
15
|
-
segmentsLocked: number[];
|
|
16
8
|
};
|
|
17
9
|
|
|
18
10
|
function eraseRectangle(
|
|
19
11
|
enabledElement: Types.IEnabledElement,
|
|
20
|
-
operationData:
|
|
12
|
+
operationData: OperationData,
|
|
21
13
|
inside = true
|
|
22
14
|
): void {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
segmentationId,
|
|
28
|
-
} = operationData;
|
|
29
|
-
const { imageData, dimensions } = segmentation;
|
|
30
|
-
const scalarData = segmentation.getScalarData();
|
|
31
|
-
|
|
32
|
-
const rectangleCornersIJK = points.map((world) => {
|
|
33
|
-
return transformWorldToIndex(imageData, world);
|
|
15
|
+
// Take the arguments and set the segmentIndex to 0,
|
|
16
|
+
// Then use existing fillRectangle functionality.
|
|
17
|
+
const eraseOperationData = Object.assign({}, operationData, {
|
|
18
|
+
segmentIndex: 0,
|
|
34
19
|
});
|
|
35
20
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
// Since always all points inside the boundsIJK is inside the rectangle...
|
|
39
|
-
const pointInShape = () => true;
|
|
40
|
-
|
|
41
|
-
const callback = ({ value, index }) => {
|
|
42
|
-
if (segmentsLocked.includes(value)) {
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
scalarData[index] = 0;
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
pointInShapeCallback(imageData, pointInShape, callback, boundsIJK);
|
|
49
|
-
|
|
50
|
-
triggerSegmentationDataModified(segmentationId);
|
|
21
|
+
fillInsideRectangle(enabledElement, eraseOperationData);
|
|
51
22
|
}
|
|
52
23
|
|
|
53
24
|
/**
|
|
54
25
|
* Erase the rectangle region segment inside the segmentation defined by the operationData.
|
|
55
26
|
* It erases the segmentation pixels inside the defined rectangle.
|
|
56
27
|
* @param enabledElement - The element for which the segment is being erased.
|
|
57
|
-
* @param operationData -
|
|
28
|
+
* @param operationData - OperationData
|
|
58
29
|
*/
|
|
59
30
|
export function eraseInsideRectangle(
|
|
60
31
|
enabledElement: Types.IEnabledElement,
|
|
61
|
-
operationData:
|
|
32
|
+
operationData: OperationData
|
|
62
33
|
): void {
|
|
63
34
|
eraseRectangle(enabledElement, operationData, true);
|
|
64
35
|
}
|
|
@@ -67,11 +38,11 @@ export function eraseInsideRectangle(
|
|
|
67
38
|
* Erase the rectangle region segment inside the segmentation defined by the operationData.
|
|
68
39
|
* It erases the segmentation pixels outside the defined rectangle.
|
|
69
40
|
* @param enabledElement - The element for which the segment is being erased.
|
|
70
|
-
* @param operationData -
|
|
41
|
+
* @param operationData - OperationData
|
|
71
42
|
*/
|
|
72
43
|
export function eraseOutsideRectangle(
|
|
73
44
|
enabledElement: Types.IEnabledElement,
|
|
74
|
-
operationData:
|
|
45
|
+
operationData: OperationData
|
|
75
46
|
): void {
|
|
76
47
|
eraseRectangle(enabledElement, operationData, false);
|
|
77
48
|
}
|
|
@@ -1,18 +1,10 @@
|
|
|
1
1
|
import type { Types } from '@cornerstonejs/core';
|
|
2
2
|
|
|
3
3
|
import { fillInsideSphere } from './fillSphere';
|
|
4
|
+
import { LabelmapToolOperationData } from '../../../types';
|
|
4
5
|
|
|
5
|
-
type OperationData = {
|
|
6
|
+
type OperationData = LabelmapToolOperationData & {
|
|
6
7
|
points: [Types.Point3, Types.Point3, Types.Point3, Types.Point3];
|
|
7
|
-
imageVolume: Types.IImageVolume;
|
|
8
|
-
volume: Types.IImageVolume;
|
|
9
|
-
segmentIndex: number;
|
|
10
|
-
segmentationId: string;
|
|
11
|
-
segmentsLocked: number[];
|
|
12
|
-
viewPlaneNormal: Types.Point3;
|
|
13
|
-
viewUp: Types.Point3;
|
|
14
|
-
constraintFn: () => boolean;
|
|
15
|
-
strategySpecificConfiguration: any;
|
|
16
8
|
};
|
|
17
9
|
|
|
18
10
|
export function eraseInsideSphere(
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { vec3 } from 'gl-matrix';
|
|
2
2
|
import type { Types } from '@cornerstonejs/core';
|
|
3
|
+
import { cache } from '@cornerstonejs/core';
|
|
3
4
|
import { utilities as csUtils } from '@cornerstonejs/core';
|
|
4
5
|
|
|
5
6
|
import {
|
|
@@ -10,20 +11,14 @@ import { getBoundingBoxAroundShape } from '../../../utilities/boundingBox';
|
|
|
10
11
|
import { triggerSegmentationDataModified } from '../../../stateManagement/segmentation/triggerSegmentationEvents';
|
|
11
12
|
import { pointInShapeCallback } from '../../../utilities';
|
|
12
13
|
import isWithinThreshold from './utils/isWithinThreshold';
|
|
14
|
+
import { LabelmapToolOperationData } from '../../../types';
|
|
15
|
+
import { getStrategyData } from './utils/getStrategyData';
|
|
16
|
+
import { isVolumeSegmentation } from './utils/stackVolumeCheck';
|
|
13
17
|
|
|
14
18
|
const { transformWorldToIndex } = csUtils;
|
|
15
19
|
|
|
16
|
-
type OperationData = {
|
|
17
|
-
|
|
18
|
-
imageVolume: Types.IImageVolume;
|
|
19
|
-
points: any; // Todo:fix
|
|
20
|
-
volume: Types.IImageVolume;
|
|
21
|
-
segmentIndex: number;
|
|
22
|
-
segmentsLocked: number[];
|
|
23
|
-
viewPlaneNormal: number[];
|
|
24
|
-
viewUp: number[];
|
|
25
|
-
strategySpecificConfiguration: any;
|
|
26
|
-
constraintFn: () => boolean;
|
|
20
|
+
type OperationData = LabelmapToolOperationData & {
|
|
21
|
+
points: [Types.Point3, Types.Point3, Types.Point3, Types.Point3];
|
|
27
22
|
};
|
|
28
23
|
|
|
29
24
|
function fillCircle(
|
|
@@ -32,50 +27,29 @@ function fillCircle(
|
|
|
32
27
|
threshold = false
|
|
33
28
|
): void {
|
|
34
29
|
const {
|
|
35
|
-
volume: segmentationVolume,
|
|
36
|
-
imageVolume,
|
|
37
30
|
points,
|
|
38
31
|
segmentsLocked,
|
|
39
32
|
segmentIndex,
|
|
40
33
|
segmentationId,
|
|
41
34
|
strategySpecificConfiguration,
|
|
42
35
|
} = operationData;
|
|
43
|
-
const { imageData, dimensions } = segmentationVolume;
|
|
44
|
-
const scalarData = segmentationVolume.getScalarData();
|
|
45
|
-
const { viewport } = enabledElement;
|
|
46
|
-
|
|
47
|
-
// Average the points to get the center of the ellipse
|
|
48
|
-
const center = vec3.fromValues(0, 0, 0);
|
|
49
|
-
points.forEach((point) => {
|
|
50
|
-
vec3.add(center, center, point);
|
|
51
|
-
});
|
|
52
|
-
vec3.scale(center, center, 1 / points.length);
|
|
53
|
-
|
|
54
|
-
const canvasCoordinates = points.map((p) => viewport.worldToCanvas(p));
|
|
55
36
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const [topLeftCanvas, bottomRightCanvas] =
|
|
59
|
-
getCanvasEllipseCorners(canvasCoordinates);
|
|
60
|
-
|
|
61
|
-
// 2. Find the extent of the ellipse (circle) in IJK index space of the image
|
|
62
|
-
const topLeftWorld = viewport.canvasToWorld(topLeftCanvas);
|
|
63
|
-
const bottomRightWorld = viewport.canvasToWorld(bottomRightCanvas);
|
|
37
|
+
const { viewport } = enabledElement;
|
|
38
|
+
const data = getStrategyData({ operationData, viewport });
|
|
64
39
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
40
|
+
if (!data) {
|
|
41
|
+
console.warn('No data found for fillCircle');
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
69
44
|
|
|
70
|
-
const
|
|
45
|
+
const { imageScalarData, segmentationImageData, segmentationScalarData } =
|
|
46
|
+
data;
|
|
71
47
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
zRadius: Math.abs(topLeftWorld[2] - bottomRightWorld[2]) / 2,
|
|
78
|
-
};
|
|
48
|
+
const { ellipseObj, boundsIJK } = getEllipse(
|
|
49
|
+
viewport,
|
|
50
|
+
segmentationImageData,
|
|
51
|
+
points
|
|
52
|
+
);
|
|
79
53
|
|
|
80
54
|
const modifiedSlicesToUse = new Set() as Set<number>;
|
|
81
55
|
|
|
@@ -88,9 +62,9 @@ function fillCircle(
|
|
|
88
62
|
}
|
|
89
63
|
|
|
90
64
|
if (
|
|
91
|
-
isWithinThreshold(index,
|
|
65
|
+
isWithinThreshold(index, imageScalarData, strategySpecificConfiguration)
|
|
92
66
|
) {
|
|
93
|
-
|
|
67
|
+
segmentationScalarData[index] = segmentIndex;
|
|
94
68
|
//Todo: I don't think this will always be index 2 in streamingImageVolume?
|
|
95
69
|
modifiedSlicesToUse.add(pointIJK[2]);
|
|
96
70
|
}
|
|
@@ -100,15 +74,17 @@ function fillCircle(
|
|
|
100
74
|
if (segmentsLocked.includes(value)) {
|
|
101
75
|
return;
|
|
102
76
|
}
|
|
103
|
-
|
|
104
|
-
//Todo: I don't think this will always be index 2 in streamingImageVolume?
|
|
77
|
+
segmentationScalarData[index] = segmentIndex;
|
|
105
78
|
modifiedSlicesToUse.add(pointIJK[2]);
|
|
106
79
|
};
|
|
107
80
|
}
|
|
108
81
|
|
|
109
82
|
pointInShapeCallback(
|
|
110
|
-
|
|
111
|
-
(pointLPS
|
|
83
|
+
segmentationImageData,
|
|
84
|
+
(pointLPS) =>
|
|
85
|
+
pointInEllipse(ellipseObj, pointLPS, {
|
|
86
|
+
fast: true,
|
|
87
|
+
}),
|
|
112
88
|
callback,
|
|
113
89
|
boundsIJK
|
|
114
90
|
);
|
|
@@ -141,15 +117,20 @@ export function thresholdInsideCircle(
|
|
|
141
117
|
enabledElement: Types.IEnabledElement,
|
|
142
118
|
operationData: OperationData
|
|
143
119
|
): void {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
120
|
+
if (isVolumeSegmentation(operationData)) {
|
|
121
|
+
const { referencedVolumeId, volumeId } = operationData;
|
|
122
|
+
|
|
123
|
+
const imageVolume = cache.getVolume(referencedVolumeId);
|
|
124
|
+
const segmentation = cache.getVolume(volumeId);
|
|
125
|
+
|
|
126
|
+
if (
|
|
127
|
+
!csUtils.isEqual(segmentation.dimensions, imageVolume.dimensions) ||
|
|
128
|
+
!csUtils.isEqual(segmentation.direction, imageVolume.direction)
|
|
129
|
+
) {
|
|
130
|
+
throw new Error(
|
|
131
|
+
'Only source data the same dimensions/size/orientation as the segmentation currently supported.'
|
|
132
|
+
);
|
|
133
|
+
}
|
|
153
134
|
}
|
|
154
135
|
|
|
155
136
|
fillCircle(enabledElement, operationData, true);
|
|
@@ -158,7 +139,7 @@ export function thresholdInsideCircle(
|
|
|
158
139
|
/**
|
|
159
140
|
* Fill outside the circular region segment inside the segmentation defined by the operationData.
|
|
160
141
|
* It fills the segmentation pixels outside the defined circle.
|
|
161
|
-
* @param enabledElement - The element for which the segment is being erased.
|
|
142
|
+
j * @param enabledElement - The element for which the segment is being erased.
|
|
162
143
|
* @param operationData - EraseOperationData
|
|
163
144
|
*/
|
|
164
145
|
export function fillOutsideCircle(
|
|
@@ -167,3 +148,54 @@ export function fillOutsideCircle(
|
|
|
167
148
|
): void {
|
|
168
149
|
throw new Error('Not yet implemented');
|
|
169
150
|
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Fill inside the circular region segment inside the segmentation defined by the operationData.
|
|
154
|
+
* It fills the segmentation pixels inside the defined circle.
|
|
155
|
+
* @param enabledElement - The element for which the segment is being erased.
|
|
156
|
+
* @param operationData - EraseOperationData
|
|
157
|
+
*/
|
|
158
|
+
function getCenter(points) {
|
|
159
|
+
// Average the points to get the center of the ellipse
|
|
160
|
+
const center = vec3.fromValues(0, 0, 0);
|
|
161
|
+
points.forEach((point) => {
|
|
162
|
+
vec3.add(center, center, point);
|
|
163
|
+
});
|
|
164
|
+
vec3.scale(center, center, 1 / points.length);
|
|
165
|
+
return center;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function getEllipse(viewport, imageData, points) {
|
|
169
|
+
const center = getCenter(points);
|
|
170
|
+
const canvasCoordinates = points.map((p) => viewport.worldToCanvas(p));
|
|
171
|
+
const dimensions = imageData.getDimensions();
|
|
172
|
+
|
|
173
|
+
// 1. From the drawn tool: Get the ellipse (circle) topLeft and bottomRight
|
|
174
|
+
// corners in canvas coordinates
|
|
175
|
+
const [topLeftCanvas, bottomRightCanvas] =
|
|
176
|
+
getCanvasEllipseCorners(canvasCoordinates);
|
|
177
|
+
|
|
178
|
+
// 2. Find the extent of the ellipse (circle) in IJK index space of the image
|
|
179
|
+
const topLeftWorld = viewport.canvasToWorld(topLeftCanvas);
|
|
180
|
+
const bottomRightWorld = viewport.canvasToWorld(bottomRightCanvas);
|
|
181
|
+
|
|
182
|
+
const ellipsoidCornersIJK = [
|
|
183
|
+
<Types.Point3>transformWorldToIndex(imageData, topLeftWorld),
|
|
184
|
+
<Types.Point3>transformWorldToIndex(imageData, bottomRightWorld),
|
|
185
|
+
];
|
|
186
|
+
|
|
187
|
+
const boundsIJK = getBoundingBoxAroundShape(ellipsoidCornersIJK, dimensions);
|
|
188
|
+
|
|
189
|
+
if (boundsIJK.every(([min, max]) => min !== max)) {
|
|
190
|
+
throw new Error('Oblique segmentation tools are not supported yet');
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// using circle as a form of ellipse
|
|
194
|
+
const ellipseObj = {
|
|
195
|
+
center: center as Types.Point3,
|
|
196
|
+
xRadius: Math.abs(topLeftWorld[0] - bottomRightWorld[0]) / 2,
|
|
197
|
+
yRadius: Math.abs(topLeftWorld[1] - bottomRightWorld[1]) / 2,
|
|
198
|
+
zRadius: Math.abs(topLeftWorld[2] - bottomRightWorld[2]) / 2,
|
|
199
|
+
};
|
|
200
|
+
return { ellipseObj, boundsIJK };
|
|
201
|
+
}
|