@cornerstonejs/tools 2.7.4 → 2.8.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/esm/enums/ChangeTypes.d.ts +2 -1
- package/dist/esm/enums/ChangeTypes.js +1 -0
- package/dist/esm/store/filterToolsWithAnnotationsForElement.js +1 -1
- package/dist/esm/tools/AnnotationEraserTool.js +8 -4
- package/dist/esm/tools/CrosshairsTool.js +1 -1
- package/dist/esm/tools/PanTool.d.ts +0 -1
- package/dist/esm/tools/PanTool.js +0 -5
- package/dist/esm/tools/ZoomTool.js +0 -2
- package/dist/esm/tools/annotation/ArrowAnnotateTool.js +4 -1
- package/dist/esm/tools/annotation/BidirectionalTool.js +6 -5
- package/dist/esm/tools/annotation/CircleROITool.js +6 -3
- package/dist/esm/tools/annotation/CobbAngleTool.d.ts +2 -2
- package/dist/esm/tools/annotation/CobbAngleTool.js +19 -19
- package/dist/esm/tools/annotation/EllipticalROITool.js +6 -6
- package/dist/esm/tools/annotation/KeyImageTool.d.ts +1 -2
- package/dist/esm/tools/annotation/KeyImageTool.js +5 -1
- package/dist/esm/tools/annotation/LengthTool.js +4 -1
- package/dist/esm/tools/annotation/LivewireContourTool.js +9 -5
- package/dist/esm/tools/annotation/ProbeTool.js +6 -5
- package/dist/esm/tools/annotation/RectangleROITool.js +3 -2
- package/dist/esm/tools/annotation/SplineROITool.js +4 -4
- package/dist/esm/tools/annotation/VideoRedactionTool.d.ts +2 -2
- package/dist/esm/tools/annotation/VideoRedactionTool.js +27 -29
- package/dist/esm/tools/annotation/planarFreehandROITool/closedContourEditLoop.js +7 -3
- package/dist/esm/tools/annotation/planarFreehandROITool/drawLoop.js +6 -2
- package/dist/esm/tools/annotation/planarFreehandROITool/openContourEditLoop.js +6 -2
- package/dist/esm/tools/base/AnnotationDisplayTool.d.ts +1 -1
- package/dist/esm/tools/base/AnnotationDisplayTool.js +2 -2
- package/dist/esm/tools/base/AnnotationTool.d.ts +30 -0
- package/dist/esm/tools/base/AnnotationTool.js +85 -1
- package/dist/esm/tools/base/BaseTool.d.ts +1 -0
- package/dist/esm/tools/base/BaseTool.js +7 -1
- package/dist/esm/tools/base/ContourSegmentationBaseTool.js +0 -4
- package/dist/esm/tools/segmentation/BrushTool.js +1 -0
- package/dist/esm/tools/segmentation/CircleScissorsTool.d.ts +4 -2
- package/dist/esm/tools/segmentation/CircleScissorsTool.js +4 -1
- package/dist/esm/tools/segmentation/LabelmapBaseTool.d.ts +6 -1
- package/dist/esm/tools/segmentation/LabelmapBaseTool.js +6 -1
- package/dist/esm/tools/segmentation/PaintFillTool.js +1 -1
- package/dist/esm/tools/segmentation/RectangleScissorsTool.d.ts +2 -2
- package/dist/esm/tools/segmentation/RectangleScissorsTool.js +6 -2
- package/dist/esm/tools/segmentation/SphereScissorsTool.d.ts +2 -2
- package/dist/esm/tools/segmentation/SphereScissorsTool.js +5 -1
- package/dist/esm/tools/segmentation/strategies/BrushStrategy.d.ts +2 -0
- package/dist/esm/tools/segmentation/strategies/compositions/preview.js +15 -13
- package/dist/esm/tools/segmentation/strategies/compositions/setValue.js +2 -1
- package/dist/esm/tools/segmentation/strategies/fillRectangle.d.ts +6 -8
- package/dist/esm/tools/segmentation/strategies/fillRectangle.js +29 -30
- package/dist/esm/tools/segmentation/strategies/index.d.ts +2 -2
- package/dist/esm/tools/segmentation/strategies/index.js +2 -2
- package/dist/esm/types/ContourAnnotation.d.ts +2 -0
- package/dist/esm/types/LabelmapToolOperationData.d.ts +2 -0
- package/dist/esm/utilities/math/polyline/planarFreehandROIInternalTypes.d.ts +1 -0
- package/dist/esm/utilities/planar/filterAnnotationsWithinSlice.js +4 -0
- package/dist/esm/utilities/segmentation/createLabelmapMemo.d.ts +44 -0
- package/dist/esm/utilities/segmentation/createLabelmapMemo.js +68 -0
- package/dist/esm/utilities/segmentation/index.d.ts +2 -1
- package/dist/esm/utilities/segmentation/index.js +2 -1
- package/package.json +3 -3
|
@@ -138,7 +138,7 @@ class VideoRedactionTool extends AnnotationTool {
|
|
|
138
138
|
triggerAnnotationRenderForViewportIds(viewportUIDsToRender);
|
|
139
139
|
evt.preventDefault();
|
|
140
140
|
};
|
|
141
|
-
this.
|
|
141
|
+
this._endCallback = (evt) => {
|
|
142
142
|
const eventData = evt.detail;
|
|
143
143
|
const { element } = eventData;
|
|
144
144
|
const { annotation, viewportUIDsToRender, newAnnotation, hasMoved } = this.editData;
|
|
@@ -146,12 +146,12 @@ class VideoRedactionTool extends AnnotationTool {
|
|
|
146
146
|
if (newAnnotation && !hasMoved) {
|
|
147
147
|
return;
|
|
148
148
|
}
|
|
149
|
+
this.doneEditMemo();
|
|
149
150
|
data.active = false;
|
|
150
151
|
data.handles.activeHandleIndex = null;
|
|
151
152
|
this._deactivateModify(element);
|
|
152
153
|
this._deactivateDraw(element);
|
|
153
154
|
resetElementCursor(element);
|
|
154
|
-
const enabledElement = getEnabledElement(element);
|
|
155
155
|
this.editData = null;
|
|
156
156
|
this.isDrawing = false;
|
|
157
157
|
if (this.isHandleOutsideImage &&
|
|
@@ -160,11 +160,12 @@ class VideoRedactionTool extends AnnotationTool {
|
|
|
160
160
|
}
|
|
161
161
|
triggerAnnotationRenderForViewportIds(viewportUIDsToRender);
|
|
162
162
|
};
|
|
163
|
-
this.
|
|
163
|
+
this._dragCallback = (evt) => {
|
|
164
164
|
this.isDrawing = true;
|
|
165
165
|
const eventData = evt.detail;
|
|
166
166
|
const { element } = eventData;
|
|
167
|
-
const { annotation, viewportUIDsToRender, handleIndex } = this.editData;
|
|
167
|
+
const { annotation, viewportUIDsToRender, handleIndex, newAnnotation } = this.editData;
|
|
168
|
+
this.createMemo(element, annotation, { newAnnotation });
|
|
168
169
|
const { data } = annotation;
|
|
169
170
|
if (handleIndex === undefined) {
|
|
170
171
|
const { deltaPoints } = eventData;
|
|
@@ -230,37 +231,37 @@ class VideoRedactionTool extends AnnotationTool {
|
|
|
230
231
|
};
|
|
231
232
|
this._activateDraw = (element) => {
|
|
232
233
|
state.isInteractingWithTool = true;
|
|
233
|
-
element.addEventListener(Events.MOUSE_UP, this.
|
|
234
|
-
element.addEventListener(Events.MOUSE_DRAG, this.
|
|
235
|
-
element.addEventListener(Events.MOUSE_MOVE, this.
|
|
236
|
-
element.addEventListener(Events.MOUSE_CLICK, this.
|
|
237
|
-
element.addEventListener(Events.TOUCH_END, this.
|
|
238
|
-
element.addEventListener(Events.TOUCH_DRAG, this.
|
|
234
|
+
element.addEventListener(Events.MOUSE_UP, this._endCallback);
|
|
235
|
+
element.addEventListener(Events.MOUSE_DRAG, this._dragCallback);
|
|
236
|
+
element.addEventListener(Events.MOUSE_MOVE, this._dragCallback);
|
|
237
|
+
element.addEventListener(Events.MOUSE_CLICK, this._endCallback);
|
|
238
|
+
element.addEventListener(Events.TOUCH_END, this._endCallback);
|
|
239
|
+
element.addEventListener(Events.TOUCH_DRAG, this._dragCallback);
|
|
239
240
|
};
|
|
240
241
|
this._deactivateDraw = (element) => {
|
|
241
242
|
state.isInteractingWithTool = false;
|
|
242
|
-
element.removeEventListener(Events.MOUSE_UP, this.
|
|
243
|
-
element.removeEventListener(Events.MOUSE_DRAG, this.
|
|
244
|
-
element.removeEventListener(Events.MOUSE_MOVE, this.
|
|
245
|
-
element.removeEventListener(Events.MOUSE_CLICK, this.
|
|
246
|
-
element.removeEventListener(Events.TOUCH_END, this.
|
|
247
|
-
element.removeEventListener(Events.TOUCH_DRAG, this.
|
|
243
|
+
element.removeEventListener(Events.MOUSE_UP, this._endCallback);
|
|
244
|
+
element.removeEventListener(Events.MOUSE_DRAG, this._dragCallback);
|
|
245
|
+
element.removeEventListener(Events.MOUSE_MOVE, this._dragCallback);
|
|
246
|
+
element.removeEventListener(Events.MOUSE_CLICK, this._endCallback);
|
|
247
|
+
element.removeEventListener(Events.TOUCH_END, this._endCallback);
|
|
248
|
+
element.removeEventListener(Events.TOUCH_DRAG, this._dragCallback);
|
|
248
249
|
};
|
|
249
250
|
this._activateModify = (element) => {
|
|
250
251
|
state.isInteractingWithTool = true;
|
|
251
|
-
element.addEventListener(Events.MOUSE_UP, this.
|
|
252
|
-
element.addEventListener(Events.MOUSE_DRAG, this.
|
|
253
|
-
element.addEventListener(Events.MOUSE_CLICK, this.
|
|
254
|
-
element.addEventListener(Events.TOUCH_END, this.
|
|
255
|
-
element.addEventListener(Events.TOUCH_DRAG, this.
|
|
252
|
+
element.addEventListener(Events.MOUSE_UP, this._endCallback);
|
|
253
|
+
element.addEventListener(Events.MOUSE_DRAG, this._dragCallback);
|
|
254
|
+
element.addEventListener(Events.MOUSE_CLICK, this._endCallback);
|
|
255
|
+
element.addEventListener(Events.TOUCH_END, this._endCallback);
|
|
256
|
+
element.addEventListener(Events.TOUCH_DRAG, this._dragCallback);
|
|
256
257
|
};
|
|
257
258
|
this._deactivateModify = (element) => {
|
|
258
259
|
state.isInteractingWithTool = false;
|
|
259
|
-
element.removeEventListener(Events.MOUSE_UP, this.
|
|
260
|
-
element.removeEventListener(Events.MOUSE_DRAG, this.
|
|
261
|
-
element.removeEventListener(Events.MOUSE_CLICK, this.
|
|
262
|
-
element.removeEventListener(Events.TOUCH_END, this.
|
|
263
|
-
element.removeEventListener(Events.TOUCH_DRAG, this.
|
|
260
|
+
element.removeEventListener(Events.MOUSE_UP, this._endCallback);
|
|
261
|
+
element.removeEventListener(Events.MOUSE_DRAG, this._dragCallback);
|
|
262
|
+
element.removeEventListener(Events.MOUSE_CLICK, this._endCallback);
|
|
263
|
+
element.removeEventListener(Events.TOUCH_END, this._endCallback);
|
|
264
|
+
element.removeEventListener(Events.TOUCH_DRAG, this._dragCallback);
|
|
264
265
|
};
|
|
265
266
|
this.renderAnnotation = (enabledElement, svgDrawingHelper) => {
|
|
266
267
|
const renderStatus = false;
|
|
@@ -274,8 +275,6 @@ class VideoRedactionTool extends AnnotationTool {
|
|
|
274
275
|
if (!annotations?.length) {
|
|
275
276
|
return renderStatus;
|
|
276
277
|
}
|
|
277
|
-
const targetId = this.getTargetId(viewport);
|
|
278
|
-
const renderingEngine = viewport.getRenderingEngine();
|
|
279
278
|
const styleSpecifier = {
|
|
280
279
|
toolGroupId: this.toolGroupId,
|
|
281
280
|
toolName: this.getToolName(),
|
|
@@ -284,7 +283,6 @@ class VideoRedactionTool extends AnnotationTool {
|
|
|
284
283
|
for (let i = 0; i < annotations.length; i++) {
|
|
285
284
|
const annotation = annotations[i];
|
|
286
285
|
const { annotationUID } = annotation;
|
|
287
|
-
const toolMetadata = annotation.metadata;
|
|
288
286
|
const data = annotation.data;
|
|
289
287
|
const { points, activeHandleIndex } = data.handles;
|
|
290
288
|
const canvasCoordinates = points.map((p) => viewport.worldToCanvas(p));
|
|
@@ -27,6 +27,7 @@ function activateClosedContourEdit(evt, annotation, viewportIdsToRender) {
|
|
|
27
27
|
editCanvasPoints: [canvasPos],
|
|
28
28
|
startCrossingIndex: undefined,
|
|
29
29
|
editIndex: 0,
|
|
30
|
+
annotation,
|
|
30
31
|
};
|
|
31
32
|
this.commonData = {
|
|
32
33
|
annotation,
|
|
@@ -61,9 +62,10 @@ function mouseDragClosedContourEditCallback(evt) {
|
|
|
61
62
|
const worldPos = currentPoints.world;
|
|
62
63
|
const canvasPos = currentPoints.canvas;
|
|
63
64
|
const enabledElement = getEnabledElement(element);
|
|
64
|
-
const {
|
|
65
|
+
const { viewport } = enabledElement;
|
|
65
66
|
const { viewportIdsToRender, xDir, yDir, spacing } = this.commonData;
|
|
66
|
-
const { editIndex, editCanvasPoints, startCrossingIndex } = this.editData;
|
|
67
|
+
const { editIndex, editCanvasPoints, startCrossingIndex, annotation } = this.editData;
|
|
68
|
+
this.createMemo(element, annotation);
|
|
67
69
|
const lastCanvasPoint = editCanvasPoints[editCanvasPoints.length - 1];
|
|
68
70
|
const lastWorldPoint = viewport.canvasToWorld(lastCanvasPoint);
|
|
69
71
|
const worldPosDiff = vec3.create();
|
|
@@ -118,6 +120,7 @@ function finishEditAndStartNewEdit(evt) {
|
|
|
118
120
|
startCrossingIndex: undefined,
|
|
119
121
|
editIndex: 0,
|
|
120
122
|
snapIndex: undefined,
|
|
123
|
+
annotation,
|
|
121
124
|
};
|
|
122
125
|
triggerAnnotationRenderForViewportIds(viewportIdsToRender);
|
|
123
126
|
}
|
|
@@ -203,8 +206,9 @@ function mouseUpClosedContourEditCallback(evt) {
|
|
|
203
206
|
}
|
|
204
207
|
function completeClosedContourEdit(element) {
|
|
205
208
|
const enabledElement = getEnabledElement(element);
|
|
206
|
-
const { viewport
|
|
209
|
+
const { viewport } = enabledElement;
|
|
207
210
|
const { annotation, viewportIdsToRender } = this.commonData;
|
|
211
|
+
this.doneEditMemo();
|
|
208
212
|
const { fusedCanvasPoints, prevCanvasPoints } = this.editData;
|
|
209
213
|
if (fusedCanvasPoints) {
|
|
210
214
|
const updatedPoints = shouldSmooth(this.configuration, annotation)
|
|
@@ -26,6 +26,7 @@ function activateDraw(evt, annotation, viewportIdsToRender) {
|
|
|
26
26
|
canvasPoints: [canvasPos],
|
|
27
27
|
polylineIndex: 0,
|
|
28
28
|
contourHoleProcessingEnabled,
|
|
29
|
+
newAnnotation: true,
|
|
29
30
|
};
|
|
30
31
|
this.commonData = {
|
|
31
32
|
annotation,
|
|
@@ -60,9 +61,10 @@ function mouseDragDrawCallback(evt) {
|
|
|
60
61
|
const worldPos = currentPoints.world;
|
|
61
62
|
const canvasPos = currentPoints.canvas;
|
|
62
63
|
const enabledElement = getEnabledElement(element);
|
|
63
|
-
const {
|
|
64
|
+
const { viewport } = enabledElement;
|
|
64
65
|
const { annotation, viewportIdsToRender, xDir, yDir, spacing, movingTextBox, } = this.commonData;
|
|
65
|
-
const { polylineIndex, canvasPoints } = this.drawData;
|
|
66
|
+
const { polylineIndex, canvasPoints, newAnnotation } = this.drawData;
|
|
67
|
+
this.createMemo(element, annotation, { newAnnotation });
|
|
66
68
|
const lastCanvasPoint = canvasPoints[canvasPoints.length - 1];
|
|
67
69
|
const lastWorldPoint = viewport.canvasToWorld(lastCanvasPoint);
|
|
68
70
|
const worldPosDiff = vec3.create();
|
|
@@ -102,6 +104,8 @@ function mouseUpDrawCallback(evt) {
|
|
|
102
104
|
const lastPoint = canvasPoints[canvasPoints.length - 1];
|
|
103
105
|
const eventDetail = evt.detail;
|
|
104
106
|
const { element } = eventDetail;
|
|
107
|
+
this.doneEditMemo();
|
|
108
|
+
this.drawData.newAnnotation = false;
|
|
105
109
|
if (allowOpenContours &&
|
|
106
110
|
!pointsAreWithinCloseContourProximity(firstPoint, lastPoint, this.configuration.closeContourProximity)) {
|
|
107
111
|
this.completeDrawOpenContour(element, { contourHoleProcessingEnabled });
|
|
@@ -17,6 +17,7 @@ function activateOpenContourEdit(evt, annotation, viewportIdsToRender) {
|
|
|
17
17
|
const canvasPos = currentPoints.canvas;
|
|
18
18
|
const enabledElement = getEnabledElement(element);
|
|
19
19
|
const { viewport } = enabledElement;
|
|
20
|
+
this.doneEditMemo();
|
|
20
21
|
const prevCanvasPoints = annotation.data.contour.polyline.map(viewport.worldToCanvas);
|
|
21
22
|
const { spacing, xDir, yDir } = getSubPixelSpacingAndXYDirections(viewport, this.configuration.subPixelResolution);
|
|
22
23
|
this.editData = {
|
|
@@ -58,12 +59,13 @@ function mouseDragOpenContourEditCallback(evt) {
|
|
|
58
59
|
const worldPos = currentPoints.world;
|
|
59
60
|
const canvasPos = currentPoints.canvas;
|
|
60
61
|
const enabledElement = getEnabledElement(element);
|
|
61
|
-
const {
|
|
62
|
+
const { viewport } = enabledElement;
|
|
62
63
|
const { viewportIdsToRender, xDir, yDir, spacing } = this.commonData;
|
|
63
64
|
const { editIndex, editCanvasPoints, startCrossingIndex } = this.editData;
|
|
64
65
|
const lastCanvasPoint = editCanvasPoints[editCanvasPoints.length - 1];
|
|
65
66
|
const lastWorldPoint = viewport.canvasToWorld(lastCanvasPoint);
|
|
66
67
|
const worldPosDiff = vec3.create();
|
|
68
|
+
this.createMemo(element, this.commonData.annotation);
|
|
67
69
|
vec3.subtract(worldPosDiff, worldPos, lastWorldPoint);
|
|
68
70
|
const xDist = Math.abs(vec3.dot(worldPosDiff, xDir));
|
|
69
71
|
const yDist = Math.abs(vec3.dot(worldPosDiff, yDir));
|
|
@@ -112,6 +114,7 @@ function openContourEditOverwriteEnd(evt) {
|
|
|
112
114
|
this.isEditingOpen = false;
|
|
113
115
|
this.editData = undefined;
|
|
114
116
|
this.commonData = undefined;
|
|
117
|
+
this.doneEditMemo();
|
|
115
118
|
this.deactivateOpenContourEdit(element);
|
|
116
119
|
this.activateOpenContourEndEdit(evt, annotation, viewportIdsToRender, null);
|
|
117
120
|
}
|
|
@@ -262,8 +265,9 @@ function mouseUpOpenContourEditCallback(evt) {
|
|
|
262
265
|
}
|
|
263
266
|
function completeOpenContourEdit(element) {
|
|
264
267
|
const enabledElement = getEnabledElement(element);
|
|
265
|
-
const { viewport
|
|
268
|
+
const { viewport } = enabledElement;
|
|
266
269
|
const { annotation, viewportIdsToRender } = this.commonData;
|
|
270
|
+
this.doneEditMemo();
|
|
267
271
|
const { fusedCanvasPoints, prevCanvasPoints } = this.editData;
|
|
268
272
|
if (fusedCanvasPoints) {
|
|
269
273
|
const updatedPoints = shouldSmooth(this.configuration)
|
|
@@ -5,7 +5,7 @@ import type { StyleSpecifier } from '../../types/AnnotationStyle';
|
|
|
5
5
|
declare abstract class AnnotationDisplayTool extends BaseTool {
|
|
6
6
|
static toolName: any;
|
|
7
7
|
abstract renderAnnotation(enabledElement: Types.IEnabledElement, svgDrawingHelper: SVGDrawingHelper): any;
|
|
8
|
-
filterInteractableAnnotationsForElement(element: HTMLDivElement, annotations: Annotations): Annotations
|
|
8
|
+
filterInteractableAnnotationsForElement(element: HTMLDivElement, annotations: Annotations): Annotations;
|
|
9
9
|
onImageSpacingCalibrated: (evt: Types.EventTypes.ImageSpacingCalibratedEvent) => void;
|
|
10
10
|
protected createAnnotation(evt: EventTypes.InteractionEventType): Annotation;
|
|
11
11
|
protected getReferencedImageId(viewport: Types.IViewport, worldPos: Types.Point3, viewPlaneNormal: Types.Point3, viewUp?: Types.Point3): string;
|
|
@@ -34,8 +34,8 @@ class AnnotationDisplayTool extends BaseTool {
|
|
|
34
34
|
};
|
|
35
35
|
}
|
|
36
36
|
filterInteractableAnnotationsForElement(element, annotations) {
|
|
37
|
-
if (!annotations
|
|
38
|
-
return;
|
|
37
|
+
if (!annotations?.length) {
|
|
38
|
+
return [];
|
|
39
39
|
}
|
|
40
40
|
const enabledElement = getEnabledElement(element);
|
|
41
41
|
const { viewport } = enabledElement;
|
|
@@ -22,5 +22,35 @@ declare abstract class AnnotationTool extends AnnotationDisplayTool {
|
|
|
22
22
|
styleSpecifier: StyleSpecifier;
|
|
23
23
|
}): AnnotationStyle;
|
|
24
24
|
private _imagePointNearToolOrHandle;
|
|
25
|
+
protected static createAnnotationState(annotation: Annotation, deleting?: boolean): {
|
|
26
|
+
annotationUID: string;
|
|
27
|
+
data: {
|
|
28
|
+
[key: string]: unknown;
|
|
29
|
+
handles?: {
|
|
30
|
+
points?: Types.Point3[];
|
|
31
|
+
activeHandleIndex?: number | null;
|
|
32
|
+
textBox?: {
|
|
33
|
+
hasMoved?: boolean;
|
|
34
|
+
worldPosition?: Types.Point3;
|
|
35
|
+
worldBoundingBox?: {
|
|
36
|
+
topLeft: Types.Point3;
|
|
37
|
+
topRight: Types.Point3;
|
|
38
|
+
bottomLeft: Types.Point3;
|
|
39
|
+
bottomRight: Types.Point3;
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
[key: string]: unknown;
|
|
43
|
+
};
|
|
44
|
+
cachedStats?: Record<string, unknown>;
|
|
45
|
+
};
|
|
46
|
+
deleting: boolean;
|
|
47
|
+
};
|
|
48
|
+
static createAnnotationMemo(element: any, annotation: Annotation, options?: {
|
|
49
|
+
newAnnotation?: boolean;
|
|
50
|
+
deleting?: boolean;
|
|
51
|
+
}): {
|
|
52
|
+
restoreMemo: () => void;
|
|
53
|
+
};
|
|
54
|
+
protected createMemo(element: any, annotation: any, options?: any): void;
|
|
25
55
|
}
|
|
26
56
|
export default AnnotationTool;
|
|
@@ -3,8 +3,13 @@ import { vec2 } from 'gl-matrix';
|
|
|
3
3
|
import AnnotationDisplayTool from './AnnotationDisplayTool';
|
|
4
4
|
import { isAnnotationLocked } from '../../stateManagement/annotation/annotationLocking';
|
|
5
5
|
import { isAnnotationVisible } from '../../stateManagement/annotation/annotationVisibility';
|
|
6
|
-
import { addAnnotation } from '../../stateManagement/annotation/annotationState';
|
|
6
|
+
import { addAnnotation, removeAnnotation, getAnnotation, } from '../../stateManagement/annotation/annotationState';
|
|
7
7
|
import { triggerAnnotationModified } from '../../stateManagement/annotation/helpers/state';
|
|
8
|
+
import ChangeTypes from '../../enums/ChangeTypes';
|
|
9
|
+
import { setAnnotationSelected } from '../../stateManagement/annotation/annotationSelection';
|
|
10
|
+
import { addContourSegmentationAnnotation } from '../../utilities/contourSegmentation';
|
|
11
|
+
const { DefaultHistoryMemo } = csUtils.HistoryMemo;
|
|
12
|
+
const { PointsManager } = csUtils;
|
|
8
13
|
class AnnotationTool extends AnnotationDisplayTool {
|
|
9
14
|
static createAnnotation(...annotationBaseData) {
|
|
10
15
|
let annotation = {
|
|
@@ -177,6 +182,85 @@ class AnnotationTool extends AnnotationDisplayTool {
|
|
|
177
182
|
return true;
|
|
178
183
|
}
|
|
179
184
|
}
|
|
185
|
+
static createAnnotationState(annotation, deleting) {
|
|
186
|
+
const { data, annotationUID } = annotation;
|
|
187
|
+
const cloneData = {
|
|
188
|
+
...data,
|
|
189
|
+
cachedStats: {},
|
|
190
|
+
};
|
|
191
|
+
delete cloneData.contour;
|
|
192
|
+
delete cloneData.spline;
|
|
193
|
+
const state = {
|
|
194
|
+
annotationUID,
|
|
195
|
+
data: structuredClone(cloneData),
|
|
196
|
+
deleting,
|
|
197
|
+
};
|
|
198
|
+
const contour = data.contour;
|
|
199
|
+
if (contour) {
|
|
200
|
+
state.data.contour = {
|
|
201
|
+
...contour,
|
|
202
|
+
polyline: null,
|
|
203
|
+
pointsManager: PointsManager.create3(contour.polyline.length, contour.polyline),
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
return state;
|
|
207
|
+
}
|
|
208
|
+
static createAnnotationMemo(element, annotation, options) {
|
|
209
|
+
if (!annotation) {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
const { newAnnotation, deleting = newAnnotation ? false : undefined } = options || {};
|
|
213
|
+
const { annotationUID } = annotation;
|
|
214
|
+
const state = AnnotationTool.createAnnotationState(annotation, deleting);
|
|
215
|
+
const annotationMemo = {
|
|
216
|
+
restoreMemo: () => {
|
|
217
|
+
const newState = AnnotationTool.createAnnotationState(annotation, deleting);
|
|
218
|
+
if (state.deleting === true) {
|
|
219
|
+
state.deleting = false;
|
|
220
|
+
Object.assign(annotation.data, state.data);
|
|
221
|
+
if (annotation.data.contour) {
|
|
222
|
+
const annotationData = annotation.data;
|
|
223
|
+
annotationData.contour.polyline = state.data.contour.pointsManager.points;
|
|
224
|
+
delete state.data.contour.pointsManager;
|
|
225
|
+
if (annotationData.segmentation) {
|
|
226
|
+
addContourSegmentationAnnotation(annotation);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
state.data = newState.data;
|
|
230
|
+
addAnnotation(annotation, element);
|
|
231
|
+
setAnnotationSelected(annotation.annotationUID, true);
|
|
232
|
+
getEnabledElement(element)?.viewport.render();
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
if (state.deleting === false) {
|
|
236
|
+
state.deleting = true;
|
|
237
|
+
state.data = newState.data;
|
|
238
|
+
setAnnotationSelected(annotation.annotationUID);
|
|
239
|
+
removeAnnotation(annotation.annotationUID);
|
|
240
|
+
getEnabledElement(element)?.viewport.render();
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
const currentAnnotation = getAnnotation(annotationUID);
|
|
244
|
+
if (!currentAnnotation) {
|
|
245
|
+
console.warn('No current annotation');
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
Object.assign(currentAnnotation.data, state.data);
|
|
249
|
+
if (currentAnnotation.data.contour) {
|
|
250
|
+
currentAnnotation.data
|
|
251
|
+
.contour.polyline = state.data.contour.pointsManager.points;
|
|
252
|
+
}
|
|
253
|
+
state.data = newState.data;
|
|
254
|
+
currentAnnotation.invalidated = true;
|
|
255
|
+
triggerAnnotationModified(currentAnnotation, element, ChangeTypes.History);
|
|
256
|
+
},
|
|
257
|
+
};
|
|
258
|
+
DefaultHistoryMemo.push(annotationMemo);
|
|
259
|
+
return annotationMemo;
|
|
260
|
+
}
|
|
261
|
+
createMemo(element, annotation, options) {
|
|
262
|
+
this.memo ||= AnnotationTool.createAnnotationMemo(element, annotation, options);
|
|
263
|
+
}
|
|
180
264
|
}
|
|
181
265
|
AnnotationTool.toolName = 'AnnotationTool';
|
|
182
266
|
export default AnnotationTool;
|
|
@@ -92,8 +92,8 @@ class BaseTool {
|
|
|
92
92
|
throw new Error('getTargetId: viewport must have a getViewReferenceId method');
|
|
93
93
|
}
|
|
94
94
|
undo() {
|
|
95
|
+
this.doneEditMemo();
|
|
95
96
|
DefaultHistoryMemo.undo();
|
|
96
|
-
this.memo = null;
|
|
97
97
|
}
|
|
98
98
|
redo() {
|
|
99
99
|
DefaultHistoryMemo.redo();
|
|
@@ -117,6 +117,12 @@ class BaseTool {
|
|
|
117
117
|
DefaultHistoryMemo.push(zoomPanMemo);
|
|
118
118
|
return zoomPanMemo;
|
|
119
119
|
}
|
|
120
|
+
doneEditMemo() {
|
|
121
|
+
if (this.memo?.commitMemo?.()) {
|
|
122
|
+
DefaultHistoryMemo.push(this.memo);
|
|
123
|
+
}
|
|
124
|
+
this.memo = null;
|
|
125
|
+
}
|
|
120
126
|
}
|
|
121
127
|
BaseTool.toolName = 'BaseTool';
|
|
122
128
|
export default BaseTool;
|
|
@@ -6,15 +6,11 @@ import InterpolationManager from '../../utilities/segmentation/InterpolationMana
|
|
|
6
6
|
import { addContourSegmentationAnnotation, removeContourSegmentationAnnotation, } from '../../utilities/contourSegmentation';
|
|
7
7
|
import { triggerAnnotationRenderForToolGroupIds } from '../../utilities/triggerAnnotationRenderForToolGroupIds';
|
|
8
8
|
import { getToolGroupForViewport } from '../../store/ToolGroupManager';
|
|
9
|
-
import { getSegmentIndexColor } from '../../stateManagement/segmentation/config/segmentationColor';
|
|
10
9
|
import { getSegmentationRepresentations } from '../../stateManagement/segmentation/getSegmentationRepresentation';
|
|
11
10
|
import { getActiveSegmentation } from '../../stateManagement/segmentation/getActiveSegmentation';
|
|
12
|
-
import { getSegmentationRepresentationVisibility } from '../../stateManagement/segmentation/getSegmentationRepresentationVisibility';
|
|
13
11
|
import { getViewportIdsWithSegmentation } from '../../stateManagement/segmentation/getViewportIdsWithSegmentation';
|
|
14
12
|
import { getActiveSegmentIndex } from '../../stateManagement/segmentation/getActiveSegmentIndex';
|
|
15
13
|
import { getLockedSegmentIndices } from '../../stateManagement/segmentation/segmentLocking';
|
|
16
|
-
import { segmentationStyle } from '../../stateManagement/segmentation/SegmentationStyle';
|
|
17
|
-
import { internalGetHiddenSegmentIndices } from '../../stateManagement/segmentation/helpers/internalGetHiddenSegmentIndices';
|
|
18
14
|
import { getSVGStyleForSegment } from '../../utilities/segmentation/getSVGStyleForSegment';
|
|
19
15
|
class ContourSegmentationBaseTool extends ContourBaseTool {
|
|
20
16
|
constructor(toolProps, defaultToolProps) {
|
|
@@ -146,6 +146,7 @@ class BrushTool extends LabelmapBaseTool {
|
|
|
146
146
|
if (!this._previewData.preview && !this._previewData.isDrag) {
|
|
147
147
|
this.applyActiveStrategy(enabledElement, operationData);
|
|
148
148
|
}
|
|
149
|
+
this.doneEditMemo();
|
|
149
150
|
this._deactivateDraw(element);
|
|
150
151
|
resetElementCursor(element);
|
|
151
152
|
this.updateCursor(evt);
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Types } from '@cornerstonejs/core';
|
|
2
|
-
import { BaseTool } from '../base';
|
|
3
2
|
import type { PublicToolProps, ToolProps, EventTypes, SVGDrawingHelper, Annotation } from '../../types';
|
|
4
|
-
|
|
3
|
+
import LabelmapBaseTool from './LabelmapBaseTool';
|
|
4
|
+
import type { LabelmapMemo } from '../../utilities/segmentation/createLabelmapMemo';
|
|
5
|
+
declare class CircleScissorsTool extends LabelmapBaseTool {
|
|
5
6
|
static toolName: any;
|
|
6
7
|
editData: {
|
|
7
8
|
annotation: Annotation;
|
|
@@ -18,6 +19,7 @@ declare class CircleScissorsTool extends BaseTool {
|
|
|
18
19
|
hasMoved?: boolean;
|
|
19
20
|
imageId: string;
|
|
20
21
|
centerCanvas?: Array<number>;
|
|
22
|
+
memo?: LabelmapMemo;
|
|
21
23
|
} | null;
|
|
22
24
|
isDrawing: boolean;
|
|
23
25
|
isHandleOutsideImage: boolean;
|
|
@@ -8,7 +8,8 @@ import { resetElementCursor, hideElementCursor, } from '../../cursors/elementCur
|
|
|
8
8
|
import triggerAnnotationRenderForViewportIds from '../../utilities/triggerAnnotationRenderForViewportIds';
|
|
9
9
|
import { segmentLocking, activeSegmentation, segmentIndex as segmentIndexController, config as segmentationConfig, } from '../../stateManagement/segmentation';
|
|
10
10
|
import { getCurrentLabelmapImageIdForViewport, getSegmentation, } from '../../stateManagement/segmentation/segmentationState';
|
|
11
|
-
|
|
11
|
+
import LabelmapBaseTool from './LabelmapBaseTool';
|
|
12
|
+
class CircleScissorsTool extends LabelmapBaseTool {
|
|
12
13
|
constructor(toolProps = {}, defaultToolProps = {
|
|
13
14
|
supportedInteractionTypes: ['Mouse', 'Touch'],
|
|
14
15
|
configuration: {
|
|
@@ -167,10 +168,12 @@ class CircleScissorsTool extends BaseTool {
|
|
|
167
168
|
viewPlaneNormal,
|
|
168
169
|
viewUp,
|
|
169
170
|
strategySpecificConfiguration: {},
|
|
171
|
+
createMemo: this.createMemo.bind(this),
|
|
170
172
|
};
|
|
171
173
|
this.editData = null;
|
|
172
174
|
this.isDrawing = false;
|
|
173
175
|
this.applyActiveStrategy(enabledElement, operationData);
|
|
176
|
+
this.doneEditMemo();
|
|
174
177
|
};
|
|
175
178
|
this._activateDraw = (element) => {
|
|
176
179
|
element.addEventListener(Events.MOUSE_UP, this._endCallback);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Types } from '@cornerstonejs/core';
|
|
2
2
|
import { BaseTool } from '../base';
|
|
3
3
|
import type vtkImageData from '@kitware/vtk.js/Common/DataModel/ImageData';
|
|
4
|
+
import * as LabelmapMemo from '../../utilities/segmentation/createLabelmapMemo';
|
|
4
5
|
export type PreviewData = {
|
|
5
6
|
preview: unknown;
|
|
6
7
|
timer?: number;
|
|
@@ -32,7 +33,7 @@ export default class LabelmapBaseTool extends BaseTool {
|
|
|
32
33
|
};
|
|
33
34
|
protected _previewData?: PreviewData;
|
|
34
35
|
constructor(toolProps: any, defaultToolProps: any);
|
|
35
|
-
createMemo(segmentId: string, segmentationVoxelManager: any, preview: any):
|
|
36
|
+
createMemo(segmentId: string, segmentationVoxelManager: any, preview: any): LabelmapMemo.LabelmapMemo;
|
|
36
37
|
createEditData(element: any): {
|
|
37
38
|
volumeId: string;
|
|
38
39
|
referencedVolumeId: any;
|
|
@@ -89,6 +90,7 @@ export default class LabelmapBaseTool extends BaseTool {
|
|
|
89
90
|
viewUp: any;
|
|
90
91
|
strategySpecificConfiguration: any;
|
|
91
92
|
preview: unknown;
|
|
93
|
+
createMemo: (segmentId: string, segmentationVoxelManager: any, preview: any) => LabelmapMemo.LabelmapMemo;
|
|
92
94
|
override: {
|
|
93
95
|
voxelManager: Types.IVoxelManager<number>;
|
|
94
96
|
imageData: vtkImageData;
|
|
@@ -108,6 +110,7 @@ export default class LabelmapBaseTool extends BaseTool {
|
|
|
108
110
|
viewUp: any;
|
|
109
111
|
strategySpecificConfiguration: any;
|
|
110
112
|
preview: unknown;
|
|
113
|
+
createMemo: (segmentId: string, segmentationVoxelManager: any, preview: any) => LabelmapMemo.LabelmapMemo;
|
|
111
114
|
volumeId: string;
|
|
112
115
|
referencedVolumeId: any;
|
|
113
116
|
segmentsLocked: number[] | [];
|
|
@@ -123,6 +126,7 @@ export default class LabelmapBaseTool extends BaseTool {
|
|
|
123
126
|
viewUp: any;
|
|
124
127
|
strategySpecificConfiguration: any;
|
|
125
128
|
preview: unknown;
|
|
129
|
+
createMemo: (segmentId: string, segmentationVoxelManager: any, preview: any) => LabelmapMemo.LabelmapMemo;
|
|
126
130
|
imageId: string;
|
|
127
131
|
segmentsLocked: number[] | [];
|
|
128
132
|
override: {
|
|
@@ -141,6 +145,7 @@ export default class LabelmapBaseTool extends BaseTool {
|
|
|
141
145
|
viewUp: any;
|
|
142
146
|
strategySpecificConfiguration: any;
|
|
143
147
|
preview: unknown;
|
|
148
|
+
createMemo: (segmentId: string, segmentationVoxelManager: any, preview: any) => LabelmapMemo.LabelmapMemo;
|
|
144
149
|
imageId: string;
|
|
145
150
|
segmentsLocked: number[] | [];
|
|
146
151
|
volumeId?: undefined;
|
|
@@ -10,6 +10,7 @@ import { getStackSegmentationImageIdsForViewport } from '../../stateManagement/s
|
|
|
10
10
|
import { getSegmentIndexColor } from '../../stateManagement/segmentation/config/segmentationColor';
|
|
11
11
|
import { getActiveSegmentIndex } from '../../stateManagement/segmentation/getActiveSegmentIndex';
|
|
12
12
|
import { StrategyCallbacks } from '../../enums';
|
|
13
|
+
import * as LabelmapMemo from '../../utilities/segmentation/createLabelmapMemo';
|
|
13
14
|
export default class LabelmapBaseTool extends BaseTool {
|
|
14
15
|
constructor(toolProps, defaultToolProps) {
|
|
15
16
|
super(toolProps, defaultToolProps);
|
|
@@ -23,7 +24,8 @@ export default class LabelmapBaseTool extends BaseTool {
|
|
|
23
24
|
};
|
|
24
25
|
}
|
|
25
26
|
createMemo(segmentId, segmentationVoxelManager, preview) {
|
|
26
|
-
|
|
27
|
+
this.memo ||= LabelmapMemo.createLabelmapMemo(segmentId, segmentationVoxelManager, preview);
|
|
28
|
+
return this.memo;
|
|
27
29
|
}
|
|
28
30
|
createEditData(element) {
|
|
29
31
|
const enabledElement = getEnabledElement(element);
|
|
@@ -181,6 +183,7 @@ export default class LabelmapBaseTool extends BaseTool {
|
|
|
181
183
|
viewUp,
|
|
182
184
|
strategySpecificConfiguration: this.configuration.strategySpecificConfiguration,
|
|
183
185
|
preview: this._previewData?.preview,
|
|
186
|
+
createMemo: this.createMemo.bind(this),
|
|
184
187
|
};
|
|
185
188
|
return operationData;
|
|
186
189
|
}
|
|
@@ -210,9 +213,11 @@ export default class LabelmapBaseTool extends BaseTool {
|
|
|
210
213
|
if (!element) {
|
|
211
214
|
return;
|
|
212
215
|
}
|
|
216
|
+
this.doneEditMemo();
|
|
213
217
|
const enabledElement = getEnabledElement(element);
|
|
214
218
|
this.applyActiveStrategyCallback(enabledElement, this.getOperationData(element), StrategyCallbacks.AcceptPreview);
|
|
215
219
|
this._previewData.isDrag = false;
|
|
216
220
|
this._previewData.preview = null;
|
|
221
|
+
this.doneEditMemo();
|
|
217
222
|
}
|
|
218
223
|
}
|
|
@@ -29,9 +29,9 @@ class PaintFillTool extends BaseTool {
|
|
|
29
29
|
const { representationData } = getSegmentation(segmentationId);
|
|
30
30
|
let dimensions;
|
|
31
31
|
let direction;
|
|
32
|
-
let scalarData;
|
|
33
32
|
let index;
|
|
34
33
|
let voxelManager;
|
|
34
|
+
this.doneEditMemo();
|
|
35
35
|
if (viewport instanceof BaseVolumeViewport) {
|
|
36
36
|
const { volumeId } = representationData[SegmentationRepresentations.Labelmap];
|
|
37
37
|
const segmentation = cache.getVolume(volumeId);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Types } from '@cornerstonejs/core';
|
|
2
|
-
import { BaseTool } from '../base';
|
|
3
2
|
import type { PublicToolProps, ToolProps, EventTypes, SVGDrawingHelper, Annotation } from '../../types';
|
|
4
|
-
|
|
3
|
+
import LabelmapBaseTool from './LabelmapBaseTool';
|
|
4
|
+
declare class RectangleScissorsTool extends LabelmapBaseTool {
|
|
5
5
|
static toolName: any;
|
|
6
6
|
_throttledCalculateCachedStats: Function;
|
|
7
7
|
editData: {
|
|
@@ -8,8 +8,9 @@ import { drawRect as drawRectSvg } from '../../drawingSvg';
|
|
|
8
8
|
import { resetElementCursor, hideElementCursor, } from '../../cursors/elementCursor';
|
|
9
9
|
import triggerAnnotationRenderForViewportIds from '../../utilities/triggerAnnotationRenderForViewportIds';
|
|
10
10
|
import { config as segmentationConfig, segmentLocking, segmentIndex as segmentIndexController, activeSegmentation, } from '../../stateManagement/segmentation';
|
|
11
|
-
import { getCurrentLabelmapImageIdForViewport, getSegmentation,
|
|
12
|
-
|
|
11
|
+
import { getCurrentLabelmapImageIdForViewport, getSegmentation, } from '../../stateManagement/segmentation/segmentationState';
|
|
12
|
+
import LabelmapBaseTool from './LabelmapBaseTool';
|
|
13
|
+
class RectangleScissorsTool extends LabelmapBaseTool {
|
|
13
14
|
constructor(toolProps = {}, defaultToolProps = {
|
|
14
15
|
supportedInteractionTypes: ['Mouse', 'Touch'],
|
|
15
16
|
configuration: {
|
|
@@ -171,10 +172,13 @@ class RectangleScissorsTool extends BaseTool {
|
|
|
171
172
|
const operationData = {
|
|
172
173
|
...this.editData,
|
|
173
174
|
points: data.handles.points,
|
|
175
|
+
strategySpecificConfiguration: {},
|
|
176
|
+
createMemo: this.createMemo.bind(this),
|
|
174
177
|
};
|
|
175
178
|
this.editData = null;
|
|
176
179
|
this.isDrawing = false;
|
|
177
180
|
this.applyActiveStrategy(enabledElement, operationData);
|
|
181
|
+
this.doneEditMemo();
|
|
178
182
|
};
|
|
179
183
|
this._activateDraw = (element) => {
|
|
180
184
|
element.addEventListener(Events.MOUSE_UP, this._endCallback);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Types } from '@cornerstonejs/core';
|
|
2
|
-
import { BaseTool } from '../base';
|
|
3
2
|
import type { PublicToolProps, ToolProps, EventTypes, SVGDrawingHelper, Annotation } from '../../types';
|
|
4
|
-
|
|
3
|
+
import LabelmapBaseTool from './LabelmapBaseTool';
|
|
4
|
+
declare class SphereScissorsTool extends LabelmapBaseTool {
|
|
5
5
|
static toolName: any;
|
|
6
6
|
editData: {
|
|
7
7
|
annotation: Annotation;
|