@cornerstonejs/tools 1.31.0 → 1.32.1
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/index.d.ts +2 -2
- package/dist/cjs/index.js +3 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/stateManagement/annotation/AnnotationGroup.d.ts +18 -0
- package/dist/cjs/stateManagement/annotation/AnnotationGroup.js +73 -0
- package/dist/cjs/stateManagement/annotation/AnnotationGroup.js.map +1 -0
- package/dist/cjs/stateManagement/annotation/annotationState.js +1 -1
- package/dist/cjs/stateManagement/annotation/annotationState.js.map +1 -1
- package/dist/cjs/stateManagement/annotation/index.d.ts +2 -1
- package/dist/cjs/stateManagement/annotation/index.js +3 -1
- package/dist/cjs/stateManagement/annotation/index.js.map +1 -1
- package/dist/cjs/store/ToolGroupManager/ToolGroup.d.ts +1 -0
- package/dist/cjs/store/ToolGroupManager/ToolGroup.js +3 -1
- package/dist/cjs/store/ToolGroupManager/ToolGroup.js.map +1 -1
- package/dist/cjs/synchronizers/callbacks/stackImageSyncCallback.js +1 -1
- package/dist/cjs/synchronizers/callbacks/stackImageSyncCallback.js.map +1 -1
- package/dist/cjs/tools/annotation/KeyImageTool.d.ts +62 -0
- package/dist/cjs/tools/annotation/KeyImageTool.js +212 -0
- package/dist/cjs/tools/annotation/KeyImageTool.js.map +1 -0
- package/dist/cjs/tools/annotation/PlanarFreehandROITool.js +2 -5
- package/dist/cjs/tools/annotation/PlanarFreehandROITool.js.map +1 -1
- package/dist/cjs/tools/annotation/ProbeTool.js +15 -4
- package/dist/cjs/tools/annotation/ProbeTool.js.map +1 -1
- package/dist/cjs/tools/annotation/VideoRedactionTool.js +4 -1
- package/dist/cjs/tools/annotation/VideoRedactionTool.js.map +1 -1
- package/dist/cjs/tools/base/AnnotationDisplayTool.js +4 -2
- package/dist/cjs/tools/base/AnnotationDisplayTool.js.map +1 -1
- package/dist/cjs/tools/base/AnnotationTool.js +2 -7
- package/dist/cjs/tools/base/AnnotationTool.js.map +1 -1
- package/dist/cjs/tools/base/BaseTool.js +9 -1
- package/dist/cjs/tools/base/BaseTool.js.map +1 -1
- package/dist/cjs/tools/index.d.ts +5 -4
- package/dist/cjs/tools/index.js +9 -7
- package/dist/cjs/tools/index.js.map +1 -1
- package/dist/cjs/types/CalculatorTypes.d.ts +1 -1
- package/dist/cjs/utilities/annotationFrameRange.d.ts +13 -0
- package/dist/cjs/utilities/annotationFrameRange.js +46 -0
- package/dist/cjs/utilities/annotationFrameRange.js.map +1 -0
- package/dist/cjs/utilities/index.d.ts +2 -1
- package/dist/cjs/utilities/index.js +3 -1
- package/dist/cjs/utilities/index.js.map +1 -1
- package/dist/cjs/utilities/math/basic/BasicStatsCalculator.d.ts +0 -1
- package/dist/cjs/utilities/math/basic/BasicStatsCalculator.js +35 -22
- package/dist/cjs/utilities/math/basic/BasicStatsCalculator.js.map +1 -1
- package/dist/cjs/utilities/math/ellipse/pointInEllipse.d.ts +2 -1
- package/dist/cjs/utilities/math/ellipse/pointInEllipse.js.map +1 -1
- package/dist/cjs/utilities/math/sphere/pointInSphere.d.ts +1 -1
- package/dist/cjs/utilities/math/sphere/pointInSphere.js +3 -3
- package/dist/cjs/utilities/math/sphere/pointInSphere.js.map +1 -1
- package/dist/cjs/utilities/planar/filterAnnotationsForDisplay.js +19 -2
- package/dist/cjs/utilities/planar/filterAnnotationsForDisplay.js.map +1 -1
- package/dist/cjs/utilities/pointInShapeCallback.d.ts +6 -5
- package/dist/cjs/utilities/pointInShapeCallback.js +27 -26
- package/dist/cjs/utilities/pointInShapeCallback.js.map +1 -1
- package/dist/cjs/utilities/roundNumber.d.ts +1 -1
- package/dist/cjs/utilities/roundNumber.js +3 -0
- package/dist/cjs/utilities/roundNumber.js.map +1 -1
- package/dist/cjs/utilities/viewport/isViewportPreScaled.js +1 -1
- package/dist/cjs/utilities/viewport/isViewportPreScaled.js.map +1 -1
- package/dist/esm/index.js +2 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/stateManagement/annotation/AnnotationGroup.js +70 -0
- package/dist/esm/stateManagement/annotation/AnnotationGroup.js.map +1 -0
- package/dist/esm/stateManagement/annotation/annotationState.js +1 -1
- package/dist/esm/stateManagement/annotation/annotationState.js.map +1 -1
- package/dist/esm/stateManagement/annotation/index.js +2 -1
- package/dist/esm/stateManagement/annotation/index.js.map +1 -1
- package/dist/esm/store/ToolGroupManager/ToolGroup.js +3 -1
- package/dist/esm/store/ToolGroupManager/ToolGroup.js.map +1 -1
- package/dist/esm/synchronizers/callbacks/stackImageSyncCallback.js +1 -1
- package/dist/esm/synchronizers/callbacks/stackImageSyncCallback.js.map +1 -1
- package/dist/esm/tools/annotation/KeyImageTool.js +207 -0
- package/dist/esm/tools/annotation/KeyImageTool.js.map +1 -0
- package/dist/esm/tools/annotation/PlanarFreehandROITool.js +3 -6
- package/dist/esm/tools/annotation/PlanarFreehandROITool.js.map +1 -1
- package/dist/esm/tools/annotation/ProbeTool.js +17 -6
- package/dist/esm/tools/annotation/ProbeTool.js.map +1 -1
- package/dist/esm/tools/annotation/VideoRedactionTool.js +4 -1
- package/dist/esm/tools/annotation/VideoRedactionTool.js.map +1 -1
- package/dist/esm/tools/base/AnnotationDisplayTool.js +4 -2
- package/dist/esm/tools/base/AnnotationDisplayTool.js.map +1 -1
- package/dist/esm/tools/base/AnnotationTool.js +3 -8
- package/dist/esm/tools/base/AnnotationTool.js.map +1 -1
- package/dist/esm/tools/base/BaseTool.js +9 -1
- package/dist/esm/tools/base/BaseTool.js.map +1 -1
- package/dist/esm/tools/index.js +5 -4
- package/dist/esm/tools/index.js.map +1 -1
- package/dist/esm/utilities/annotationFrameRange.js +43 -0
- package/dist/esm/utilities/annotationFrameRange.js.map +1 -0
- package/dist/esm/utilities/index.js +2 -1
- package/dist/esm/utilities/index.js.map +1 -1
- package/dist/esm/utilities/math/basic/BasicStatsCalculator.js +35 -22
- package/dist/esm/utilities/math/basic/BasicStatsCalculator.js.map +1 -1
- package/dist/esm/utilities/math/ellipse/pointInEllipse.js.map +1 -1
- package/dist/esm/utilities/math/sphere/pointInSphere.js +3 -3
- package/dist/esm/utilities/math/sphere/pointInSphere.js.map +1 -1
- package/dist/esm/utilities/planar/filterAnnotationsForDisplay.js +19 -2
- package/dist/esm/utilities/planar/filterAnnotationsForDisplay.js.map +1 -1
- package/dist/esm/utilities/pointInShapeCallback.js +27 -26
- package/dist/esm/utilities/pointInShapeCallback.js.map +1 -1
- package/dist/esm/utilities/roundNumber.js +3 -0
- package/dist/esm/utilities/roundNumber.js.map +1 -1
- package/dist/esm/utilities/viewport/isViewportPreScaled.js +1 -1
- package/dist/esm/utilities/viewport/isViewportPreScaled.js.map +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/stateManagement/annotation/AnnotationGroup.d.ts +19 -0
- package/dist/types/stateManagement/annotation/AnnotationGroup.d.ts.map +1 -0
- package/dist/types/stateManagement/annotation/index.d.ts +2 -1
- package/dist/types/stateManagement/annotation/index.d.ts.map +1 -1
- package/dist/types/store/ToolGroupManager/ToolGroup.d.ts +1 -0
- package/dist/types/store/ToolGroupManager/ToolGroup.d.ts.map +1 -1
- package/dist/types/synchronizers/callbacks/stackImageSyncCallback.d.ts.map +1 -1
- package/dist/types/tools/annotation/KeyImageTool.d.ts +63 -0
- package/dist/types/tools/annotation/KeyImageTool.d.ts.map +1 -0
- package/dist/types/tools/annotation/PlanarFreehandROITool.d.ts.map +1 -1
- package/dist/types/tools/annotation/ProbeTool.d.ts.map +1 -1
- package/dist/types/tools/annotation/VideoRedactionTool.d.ts.map +1 -1
- package/dist/types/tools/base/AnnotationDisplayTool.d.ts.map +1 -1
- package/dist/types/tools/base/AnnotationTool.d.ts.map +1 -1
- package/dist/types/tools/base/BaseTool.d.ts.map +1 -1
- package/dist/types/tools/index.d.ts +5 -4
- package/dist/types/tools/index.d.ts.map +1 -1
- package/dist/types/types/CalculatorTypes.d.ts +1 -1
- package/dist/types/types/CalculatorTypes.d.ts.map +1 -1
- package/dist/types/utilities/annotationFrameRange.d.ts +14 -0
- package/dist/types/utilities/annotationFrameRange.d.ts.map +1 -0
- package/dist/types/utilities/index.d.ts +2 -1
- package/dist/types/utilities/index.d.ts.map +1 -1
- package/dist/types/utilities/math/basic/BasicStatsCalculator.d.ts +0 -1
- package/dist/types/utilities/math/basic/BasicStatsCalculator.d.ts.map +1 -1
- package/dist/types/utilities/math/ellipse/pointInEllipse.d.ts +2 -1
- package/dist/types/utilities/math/ellipse/pointInEllipse.d.ts.map +1 -1
- package/dist/types/utilities/math/sphere/pointInSphere.d.ts +1 -1
- package/dist/types/utilities/math/sphere/pointInSphere.d.ts.map +1 -1
- package/dist/types/utilities/planar/filterAnnotationsForDisplay.d.ts.map +1 -1
- package/dist/types/utilities/pointInShapeCallback.d.ts +6 -5
- package/dist/types/utilities/pointInShapeCallback.d.ts.map +1 -1
- package/dist/types/utilities/roundNumber.d.ts +1 -1
- package/dist/types/utilities/roundNumber.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/index.ts +2 -0
- package/src/stateManagement/annotation/AnnotationGroup.ts +120 -0
- package/src/stateManagement/annotation/annotationState.ts +1 -1
- package/src/stateManagement/annotation/index.ts +2 -0
- package/src/store/ToolGroupManager/ToolGroup.ts +10 -1
- package/src/synchronizers/callbacks/stackImageSyncCallback.ts +2 -1
- package/src/tools/annotation/KeyImageTool.ts +435 -0
- package/src/tools/annotation/PlanarFreehandROITool.ts +4 -6
- package/src/tools/annotation/ProbeTool.ts +19 -6
- package/src/tools/annotation/VideoRedactionTool.ts +10 -1
- package/src/tools/base/AnnotationDisplayTool.ts +3 -4
- package/src/tools/base/AnnotationTool.ts +3 -6
- package/src/tools/base/BaseTool.ts +18 -2
- package/src/tools/index.ts +8 -5
- package/src/types/CalculatorTypes.ts +1 -1
- package/src/utilities/annotationFrameRange.ts +78 -0
- package/src/utilities/index.ts +2 -0
- package/src/utilities/math/basic/BasicStatsCalculator.ts +51 -23
- package/src/utilities/math/ellipse/pointInEllipse.ts +2 -1
- package/src/utilities/math/sphere/pointInSphere.ts +4 -7
- package/src/utilities/planar/filterAnnotationsForDisplay.ts +29 -3
- package/src/utilities/pointInShapeCallback.ts +46 -38
- package/src/utilities/roundNumber.ts +7 -1
- package/src/utilities/viewport/isViewportPreScaled.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cornerstonejs/tools",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.32.1",
|
|
4
4
|
"description": "Cornerstone3D Tools",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "dist/types/index.d.ts",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"webpack:watch": "webpack --mode development --progress --watch --config ./.webpack/webpack.dev.js"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@cornerstonejs/core": "^1.
|
|
32
|
+
"@cornerstonejs/core": "^1.32.1",
|
|
33
33
|
"comlink": "^4.4.1",
|
|
34
34
|
"lodash.clonedeep": "4.5.0",
|
|
35
35
|
"lodash.get": "^4.4.2"
|
|
@@ -53,5 +53,5 @@
|
|
|
53
53
|
"type": "individual",
|
|
54
54
|
"url": "https://ohif.org/donate"
|
|
55
55
|
},
|
|
56
|
-
"gitHead": "
|
|
56
|
+
"gitHead": "bb586320e1b8c8d07ae7f695cc838ed529631050"
|
|
57
57
|
}
|
package/src/index.ts
CHANGED
|
@@ -42,6 +42,7 @@ import {
|
|
|
42
42
|
BidirectionalTool,
|
|
43
43
|
PlanarFreehandROITool,
|
|
44
44
|
ArrowAnnotateTool,
|
|
45
|
+
KeyImageTool,
|
|
45
46
|
CrosshairsTool,
|
|
46
47
|
ReferenceLinesTool,
|
|
47
48
|
RectangleScissorsTool,
|
|
@@ -106,6 +107,7 @@ export {
|
|
|
106
107
|
ArrowAnnotateTool,
|
|
107
108
|
AngleTool,
|
|
108
109
|
CobbAngleTool,
|
|
110
|
+
KeyImageTool,
|
|
109
111
|
MagnifyTool,
|
|
110
112
|
AdvancedMagnifyTool,
|
|
111
113
|
ReferenceCursors,
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { eventTarget, triggerEvent } from '@cornerstonejs/core';
|
|
2
|
+
import Events from '../../enums/Events';
|
|
3
|
+
import { getAnnotation } from './annotationState';
|
|
4
|
+
|
|
5
|
+
export type BaseEventDetail = {
|
|
6
|
+
viewportId: string;
|
|
7
|
+
renderingEngineId: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* An annotation group
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
export default class AnnotationGroup {
|
|
15
|
+
private annotationUIDs = new Set<string>();
|
|
16
|
+
private _isVisible = true;
|
|
17
|
+
|
|
18
|
+
public visibleFilter: (uid: string) => boolean;
|
|
19
|
+
|
|
20
|
+
constructor() {
|
|
21
|
+
this.visibleFilter = this.unboundVisibleFilter.bind(this);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Returns true if other groups are free to hide this annotation.
|
|
26
|
+
* That is, if the annotation is not a member or is hidden.
|
|
27
|
+
*/
|
|
28
|
+
protected unboundVisibleFilter(uid: string): boolean {
|
|
29
|
+
return !this._isVisible || !this.annotationUIDs.has(uid);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public has(uid: string): boolean {
|
|
33
|
+
return this.annotationUIDs.has(uid);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Sets whether annotations belonging to this group are visible or not.
|
|
37
|
+
* If there are multiple groups, then the set visible false should be called
|
|
38
|
+
* before before re-enabling the other groups with setVisible true.
|
|
39
|
+
*/
|
|
40
|
+
public setVisible(
|
|
41
|
+
isVisible = true,
|
|
42
|
+
baseEvent: BaseEventDetail,
|
|
43
|
+
filter?: (annotationUID: string) => boolean
|
|
44
|
+
) {
|
|
45
|
+
if (this._isVisible === isVisible) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
this._isVisible = isVisible;
|
|
49
|
+
this.annotationUIDs.forEach((uid) => {
|
|
50
|
+
const annotation = getAnnotation(uid);
|
|
51
|
+
if (!annotation) {
|
|
52
|
+
this.annotationUIDs.delete(uid);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (annotation.isVisible === isVisible) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (!isVisible && filter?.(uid) === false) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
annotation.isVisible = isVisible;
|
|
62
|
+
const eventDetail = {
|
|
63
|
+
...baseEvent,
|
|
64
|
+
annotation,
|
|
65
|
+
};
|
|
66
|
+
triggerEvent(eventTarget, Events.ANNOTATION_MODIFIED, eventDetail);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
public get isVisible() {
|
|
71
|
+
return this._isVisible;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Finds the nearby/next annotation in the given direction */
|
|
75
|
+
public findNearby(uid: string, direction: 1) {
|
|
76
|
+
const uids = [...this.annotationUIDs];
|
|
77
|
+
if (uids.length === 0) {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
if (!uid) {
|
|
81
|
+
return uids[direction === 1 ? 0 : uids.length - 1];
|
|
82
|
+
}
|
|
83
|
+
const index = uids.indexOf(uid);
|
|
84
|
+
if (
|
|
85
|
+
index === -1 ||
|
|
86
|
+
index + direction < 0 ||
|
|
87
|
+
index + direction >= uids.length
|
|
88
|
+
) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
return uids[index + direction];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Adds the annotation to the group
|
|
96
|
+
* Does NOT change the visibility status of the annotation.
|
|
97
|
+
*/
|
|
98
|
+
public add(...annotationUIDs: string[]) {
|
|
99
|
+
annotationUIDs.forEach((annotationUID) =>
|
|
100
|
+
this.annotationUIDs.add(annotationUID)
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Removes the annotation from the group.
|
|
106
|
+
* Does not affect the visibility status of the annotation.
|
|
107
|
+
*/
|
|
108
|
+
public remove(...annotationUIDs: string[]) {
|
|
109
|
+
annotationUIDs.forEach((annotationUID) =>
|
|
110
|
+
this.annotationUIDs.delete(annotationUID)
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Removes everything from the group.
|
|
116
|
+
*/
|
|
117
|
+
public clear() {
|
|
118
|
+
this.annotationUIDs.clear();
|
|
119
|
+
}
|
|
120
|
+
}
|
|
@@ -75,7 +75,7 @@ function addAnnotation(
|
|
|
75
75
|
annotation: Annotation,
|
|
76
76
|
annotationGroupSelector: AnnotationGroupSelector
|
|
77
77
|
): string {
|
|
78
|
-
if (annotation.annotationUID
|
|
78
|
+
if (!annotation.annotationUID) {
|
|
79
79
|
annotation.annotationUID = csUtils.uuidv4() as string;
|
|
80
80
|
}
|
|
81
81
|
|
|
@@ -4,6 +4,7 @@ import * as selection from './annotationSelection';
|
|
|
4
4
|
import * as state from './annotationState';
|
|
5
5
|
import * as visibility from './annotationVisibility';
|
|
6
6
|
import FrameOfReferenceSpecificAnnotationManager from './FrameOfReferenceSpecificAnnotationManager';
|
|
7
|
+
import AnnotationGroup from './AnnotationGroup';
|
|
7
8
|
|
|
8
9
|
export {
|
|
9
10
|
config,
|
|
@@ -12,4 +13,5 @@ export {
|
|
|
12
13
|
state,
|
|
13
14
|
visibility,
|
|
14
15
|
FrameOfReferenceSpecificAnnotationManager,
|
|
16
|
+
AnnotationGroup,
|
|
15
17
|
};
|
|
@@ -47,6 +47,10 @@ export default class ToolGroup implements IToolGroup {
|
|
|
47
47
|
id: string;
|
|
48
48
|
viewportsInfo = [];
|
|
49
49
|
toolOptions = {};
|
|
50
|
+
/**
|
|
51
|
+
* Options used for restoring a tool
|
|
52
|
+
*/
|
|
53
|
+
restoreToolOptions = {};
|
|
50
54
|
_toolInstances = {};
|
|
51
55
|
|
|
52
56
|
constructor(id: string) {
|
|
@@ -270,7 +274,10 @@ export default class ToolGroup implements IToolGroup {
|
|
|
270
274
|
}
|
|
271
275
|
|
|
272
276
|
if (mode === ToolModes.Active) {
|
|
273
|
-
this.setToolActive(
|
|
277
|
+
this.setToolActive(
|
|
278
|
+
toolName,
|
|
279
|
+
options || this.restoreToolOptions[toolName]
|
|
280
|
+
);
|
|
274
281
|
return;
|
|
275
282
|
}
|
|
276
283
|
|
|
@@ -510,6 +517,8 @@ export default class ToolGroup implements IToolGroup {
|
|
|
510
517
|
mode: Disabled,
|
|
511
518
|
};
|
|
512
519
|
|
|
520
|
+
this.restoreToolOptions[toolName] = this.toolOptions[toolName];
|
|
521
|
+
|
|
513
522
|
this.toolOptions[toolName] = toolOptions;
|
|
514
523
|
toolInstance.mode = Disabled;
|
|
515
524
|
|
|
@@ -12,7 +12,8 @@ import areViewportsCoplanar from './areViewportsCoplanar ';
|
|
|
12
12
|
const getSpatialRegistration = (targetId, sourceId) =>
|
|
13
13
|
utilities.spatialRegistrationMetadataProvider.get(
|
|
14
14
|
'spatialRegistrationModule',
|
|
15
|
-
|
|
15
|
+
targetId,
|
|
16
|
+
sourceId
|
|
16
17
|
);
|
|
17
18
|
|
|
18
19
|
/**
|
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
import { Events } from '../../enums';
|
|
2
|
+
import {
|
|
3
|
+
getEnabledElement,
|
|
4
|
+
triggerEvent,
|
|
5
|
+
eventTarget,
|
|
6
|
+
utilities as csUtils,
|
|
7
|
+
} from '@cornerstonejs/core';
|
|
8
|
+
import type { Types } from '@cornerstonejs/core';
|
|
9
|
+
|
|
10
|
+
import { AnnotationTool } from '../base';
|
|
11
|
+
import {
|
|
12
|
+
addAnnotation,
|
|
13
|
+
getAnnotations,
|
|
14
|
+
removeAnnotation,
|
|
15
|
+
} from '../../stateManagement/annotation/annotationState';
|
|
16
|
+
|
|
17
|
+
import { drawArrow as drawArrowSvg } from '../../drawingSvg';
|
|
18
|
+
import { state } from '../../store';
|
|
19
|
+
import { getViewportIdsWithToolToRender } from '../../utilities/viewportFilters';
|
|
20
|
+
import triggerAnnotationRenderForViewportIds from '../../utilities/triggerAnnotationRenderForViewportIds';
|
|
21
|
+
import { AnnotationCompletedEventDetail } from '../../types/EventTypes';
|
|
22
|
+
|
|
23
|
+
import { resetElementCursor } from '../../cursors/elementCursor';
|
|
24
|
+
|
|
25
|
+
import {
|
|
26
|
+
EventTypes,
|
|
27
|
+
ToolHandle,
|
|
28
|
+
PublicToolProps,
|
|
29
|
+
ToolProps,
|
|
30
|
+
SVGDrawingHelper,
|
|
31
|
+
} from '../../types';
|
|
32
|
+
import { StyleSpecifier } from '../../types/AnnotationStyle';
|
|
33
|
+
import { Annotation } from '../../types';
|
|
34
|
+
|
|
35
|
+
type Point2 = Types.Point2;
|
|
36
|
+
|
|
37
|
+
class KeyImageTool extends AnnotationTool {
|
|
38
|
+
static toolName;
|
|
39
|
+
|
|
40
|
+
public touchDragCallback: any;
|
|
41
|
+
public mouseDragCallback: any;
|
|
42
|
+
_throttledCalculateCachedStats: any;
|
|
43
|
+
editData: {
|
|
44
|
+
annotation: any;
|
|
45
|
+
viewportIdsToRender: string[];
|
|
46
|
+
handleIndex?: number;
|
|
47
|
+
movingTextBox?: boolean;
|
|
48
|
+
newAnnotation?: boolean;
|
|
49
|
+
hasMoved?: boolean;
|
|
50
|
+
} | null;
|
|
51
|
+
isDrawing: boolean;
|
|
52
|
+
isHandleOutsideImage: boolean;
|
|
53
|
+
|
|
54
|
+
constructor(
|
|
55
|
+
toolProps: PublicToolProps = {},
|
|
56
|
+
defaultToolProps: ToolProps = {
|
|
57
|
+
supportedInteractionTypes: ['Mouse', 'Touch'],
|
|
58
|
+
configuration: {
|
|
59
|
+
getTextCallback,
|
|
60
|
+
changeTextCallback,
|
|
61
|
+
canvasPosition: [10, 10],
|
|
62
|
+
canvasSize: 10,
|
|
63
|
+
},
|
|
64
|
+
}
|
|
65
|
+
) {
|
|
66
|
+
super(toolProps, defaultToolProps);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Based on the current position of the mouse and the current imageId to create
|
|
71
|
+
* a Length Annotation and stores it in the annotationManager
|
|
72
|
+
*
|
|
73
|
+
* @param evt - EventTypes.NormalizedMouseEventType
|
|
74
|
+
* @returns The annotation object.
|
|
75
|
+
*
|
|
76
|
+
*/
|
|
77
|
+
addNewAnnotation = (evt: EventTypes.InteractionEventType) => {
|
|
78
|
+
const eventDetail = evt.detail;
|
|
79
|
+
const { currentPoints, element } = eventDetail;
|
|
80
|
+
const worldPos = currentPoints.world;
|
|
81
|
+
const enabledElement = getEnabledElement(element);
|
|
82
|
+
const { viewport, renderingEngine } = enabledElement;
|
|
83
|
+
|
|
84
|
+
const camera = viewport.getCamera();
|
|
85
|
+
const { viewPlaneNormal, viewUp } = camera;
|
|
86
|
+
|
|
87
|
+
const referencedImageId = this.getReferencedImageId(
|
|
88
|
+
viewport,
|
|
89
|
+
worldPos,
|
|
90
|
+
viewPlaneNormal,
|
|
91
|
+
viewUp
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
const FrameOfReferenceUID = viewport.getFrameOfReferenceUID();
|
|
95
|
+
|
|
96
|
+
const annotation = {
|
|
97
|
+
annotationUID: null as string,
|
|
98
|
+
highlighted: true,
|
|
99
|
+
invalidated: true,
|
|
100
|
+
metadata: {
|
|
101
|
+
toolName: this.getToolName(),
|
|
102
|
+
viewPlaneNormal: <Types.Point3>[...viewPlaneNormal],
|
|
103
|
+
viewUp: <Types.Point3>[...viewUp],
|
|
104
|
+
FrameOfReferenceUID,
|
|
105
|
+
referencedImageId,
|
|
106
|
+
},
|
|
107
|
+
data: {
|
|
108
|
+
text: '',
|
|
109
|
+
handles: {
|
|
110
|
+
points: new Array<Types.Point3>(),
|
|
111
|
+
textBox: {
|
|
112
|
+
hasMoved: false,
|
|
113
|
+
worldPosition: <Types.Point3>[0, 0, 0],
|
|
114
|
+
worldBoundingBox: {
|
|
115
|
+
topLeft: <Types.Point3>[0, 0, 0],
|
|
116
|
+
topRight: <Types.Point3>[0, 0, 0],
|
|
117
|
+
bottomLeft: <Types.Point3>[0, 0, 0],
|
|
118
|
+
bottomRight: <Types.Point3>[0, 0, 0],
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
label: '',
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
addAnnotation(annotation, element);
|
|
127
|
+
|
|
128
|
+
const viewportIdsToRender = getViewportIdsWithToolToRender(
|
|
129
|
+
element,
|
|
130
|
+
this.getToolName()
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
evt.preventDefault();
|
|
134
|
+
|
|
135
|
+
triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender);
|
|
136
|
+
|
|
137
|
+
this.configuration.getTextCallback((text) => {
|
|
138
|
+
if (!text) {
|
|
139
|
+
removeAnnotation(annotation.annotationUID);
|
|
140
|
+
triggerAnnotationRenderForViewportIds(
|
|
141
|
+
renderingEngine,
|
|
142
|
+
viewportIdsToRender
|
|
143
|
+
);
|
|
144
|
+
this.isDrawing = false;
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
annotation.data.text = text;
|
|
148
|
+
|
|
149
|
+
const eventType = Events.ANNOTATION_COMPLETED;
|
|
150
|
+
|
|
151
|
+
const eventDetail: AnnotationCompletedEventDetail = {
|
|
152
|
+
annotation,
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
triggerEvent(eventTarget, eventType, eventDetail);
|
|
156
|
+
|
|
157
|
+
triggerAnnotationRenderForViewportIds(
|
|
158
|
+
renderingEngine,
|
|
159
|
+
viewportIdsToRender
|
|
160
|
+
);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
return annotation;
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
public cancel() {
|
|
167
|
+
// No op - the annotation can't be in a partial state
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* It returns if the canvas point is near the provided length annotation in the provided
|
|
172
|
+
* element or not. A proximity is passed to the function to determine the
|
|
173
|
+
* proximity of the point to the annotation in number of pixels.
|
|
174
|
+
*
|
|
175
|
+
* @param element - HTML Element
|
|
176
|
+
* @param annotation - Annotation
|
|
177
|
+
* @param canvasCoords - Canvas coordinates
|
|
178
|
+
* @param proximity - Proximity to tool to consider
|
|
179
|
+
* @returns Boolean, whether the canvas point is near tool
|
|
180
|
+
*/
|
|
181
|
+
isPointNearTool = (
|
|
182
|
+
element: HTMLDivElement,
|
|
183
|
+
annotation: Annotation,
|
|
184
|
+
canvasCoords: Types.Point2,
|
|
185
|
+
proximity: number
|
|
186
|
+
): boolean => {
|
|
187
|
+
const enabledElement = getEnabledElement(element);
|
|
188
|
+
const { viewport } = enabledElement;
|
|
189
|
+
const { data } = annotation;
|
|
190
|
+
|
|
191
|
+
const { canvasPosition, canvasSize } = this.configuration;
|
|
192
|
+
if (!canvasPosition?.length) {
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
if (
|
|
196
|
+
Math.abs(canvasCoords[0] - canvasPosition[0] + canvasSize / 2) <=
|
|
197
|
+
canvasSize / 2 &&
|
|
198
|
+
Math.abs(canvasCoords[1] - canvasPosition[1] + canvasSize / 2) <=
|
|
199
|
+
canvasSize / 2
|
|
200
|
+
) {
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
203
|
+
return false;
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
toolSelectedCallback = (
|
|
207
|
+
evt: EventTypes.InteractionEventType,
|
|
208
|
+
annotation: Annotation
|
|
209
|
+
): void => {
|
|
210
|
+
annotation.highlighted = true;
|
|
211
|
+
|
|
212
|
+
evt.preventDefault();
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
handleSelectedCallback(
|
|
216
|
+
evt: EventTypes.InteractionEventType,
|
|
217
|
+
annotation: Annotation,
|
|
218
|
+
handle: ToolHandle
|
|
219
|
+
): void {
|
|
220
|
+
// Nothing special to do here.
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
_endCallback = (evt: EventTypes.InteractionEventType): void => {
|
|
224
|
+
const eventDetail = evt.detail;
|
|
225
|
+
const { element } = eventDetail;
|
|
226
|
+
|
|
227
|
+
this._deactivateModify(element);
|
|
228
|
+
resetElementCursor(element);
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
doubleClickCallback = (evt: EventTypes.TouchTapEventType): void => {
|
|
232
|
+
const eventDetail = evt.detail;
|
|
233
|
+
const { element } = eventDetail;
|
|
234
|
+
let annotations = getAnnotations(this.getToolName(), element);
|
|
235
|
+
|
|
236
|
+
annotations = this.filterInteractableAnnotationsForElement(
|
|
237
|
+
element,
|
|
238
|
+
annotations
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
if (!annotations?.length) {
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const clickedAnnotation = annotations.find((annotation) =>
|
|
246
|
+
this.isPointNearTool(
|
|
247
|
+
element,
|
|
248
|
+
annotation as Annotation,
|
|
249
|
+
eventDetail.currentPoints.canvas,
|
|
250
|
+
6 // Todo: get from configuration
|
|
251
|
+
)
|
|
252
|
+
);
|
|
253
|
+
|
|
254
|
+
if (!clickedAnnotation) {
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const annotation = clickedAnnotation as Annotation;
|
|
259
|
+
|
|
260
|
+
this.configuration.changeTextCallback(
|
|
261
|
+
clickedAnnotation,
|
|
262
|
+
evt.detail,
|
|
263
|
+
this._doneChangingTextCallback.bind(this, element, annotation)
|
|
264
|
+
);
|
|
265
|
+
|
|
266
|
+
this.isDrawing = false;
|
|
267
|
+
|
|
268
|
+
// This double click was handled and the dialogue was displayed.
|
|
269
|
+
// No need for any other listener to handle it too - stopImmediatePropagation
|
|
270
|
+
// helps ensure this primarily so that no other listeners on the target element
|
|
271
|
+
// get called.
|
|
272
|
+
evt.stopImmediatePropagation();
|
|
273
|
+
evt.preventDefault();
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
_doneChangingTextCallback(element, annotation, updatedText): void {
|
|
277
|
+
annotation.data.text = updatedText;
|
|
278
|
+
|
|
279
|
+
const { renderingEngine, viewportId, renderingEngineId } =
|
|
280
|
+
getEnabledElement(element);
|
|
281
|
+
|
|
282
|
+
const viewportIdsToRender = getViewportIdsWithToolToRender(
|
|
283
|
+
element,
|
|
284
|
+
this.getToolName()
|
|
285
|
+
);
|
|
286
|
+
triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender);
|
|
287
|
+
|
|
288
|
+
// Dispatching annotation modified
|
|
289
|
+
const eventType = Events.ANNOTATION_MODIFIED;
|
|
290
|
+
|
|
291
|
+
triggerEvent(eventTarget, eventType, {
|
|
292
|
+
annotation,
|
|
293
|
+
viewportId,
|
|
294
|
+
renderingEngineId,
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
_activateModify = (element: HTMLDivElement) => {
|
|
299
|
+
state.isInteractingWithTool = true;
|
|
300
|
+
|
|
301
|
+
element.addEventListener(
|
|
302
|
+
Events.MOUSE_UP,
|
|
303
|
+
this._endCallback as EventListener
|
|
304
|
+
);
|
|
305
|
+
element.addEventListener(
|
|
306
|
+
Events.MOUSE_CLICK,
|
|
307
|
+
this._endCallback as EventListener
|
|
308
|
+
);
|
|
309
|
+
|
|
310
|
+
element.addEventListener(
|
|
311
|
+
Events.TOUCH_TAP,
|
|
312
|
+
this._endCallback as EventListener
|
|
313
|
+
);
|
|
314
|
+
element.addEventListener(
|
|
315
|
+
Events.TOUCH_END,
|
|
316
|
+
this._endCallback as EventListener
|
|
317
|
+
);
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
_deactivateModify = (element: HTMLDivElement) => {
|
|
321
|
+
state.isInteractingWithTool = false;
|
|
322
|
+
|
|
323
|
+
element.removeEventListener(
|
|
324
|
+
Events.MOUSE_UP,
|
|
325
|
+
this._endCallback as EventListener
|
|
326
|
+
);
|
|
327
|
+
element.removeEventListener(
|
|
328
|
+
Events.MOUSE_CLICK,
|
|
329
|
+
this._endCallback as EventListener
|
|
330
|
+
);
|
|
331
|
+
|
|
332
|
+
element.removeEventListener(
|
|
333
|
+
Events.TOUCH_TAP,
|
|
334
|
+
this._endCallback as EventListener
|
|
335
|
+
);
|
|
336
|
+
element.removeEventListener(
|
|
337
|
+
Events.TOUCH_END,
|
|
338
|
+
this._endCallback as EventListener
|
|
339
|
+
);
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* it is used to draw the length annotation in each
|
|
344
|
+
* request animation frame. It calculates the updated cached statistics if
|
|
345
|
+
* data is invalidated and cache it.
|
|
346
|
+
*
|
|
347
|
+
* @param enabledElement - The Cornerstone's enabledElement.
|
|
348
|
+
* @param svgDrawingHelper - The svgDrawingHelper providing the context for drawing.
|
|
349
|
+
*/
|
|
350
|
+
renderAnnotation = (
|
|
351
|
+
enabledElement: Types.IEnabledElement,
|
|
352
|
+
svgDrawingHelper: SVGDrawingHelper
|
|
353
|
+
): boolean => {
|
|
354
|
+
let renderStatus = false;
|
|
355
|
+
const { viewport } = enabledElement;
|
|
356
|
+
const { element } = viewport;
|
|
357
|
+
|
|
358
|
+
let annotations = getAnnotations(this.getToolName(), element);
|
|
359
|
+
|
|
360
|
+
// Todo: We don't need this anymore, filtering happens in triggerAnnotationRender
|
|
361
|
+
if (!annotations?.length) {
|
|
362
|
+
return renderStatus;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
annotations = this.filterInteractableAnnotationsForElement(
|
|
366
|
+
element,
|
|
367
|
+
annotations
|
|
368
|
+
);
|
|
369
|
+
|
|
370
|
+
if (!annotations?.length) {
|
|
371
|
+
return renderStatus;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
const styleSpecifier: StyleSpecifier = {
|
|
375
|
+
toolGroupId: this.toolGroupId,
|
|
376
|
+
toolName: this.getToolName(),
|
|
377
|
+
viewportId: enabledElement.viewport.id,
|
|
378
|
+
};
|
|
379
|
+
|
|
380
|
+
// Draw SVG
|
|
381
|
+
for (let i = 0; i < annotations.length; i++) {
|
|
382
|
+
const annotation = annotations[i];
|
|
383
|
+
const { annotationUID } = annotation;
|
|
384
|
+
|
|
385
|
+
styleSpecifier.annotationUID = annotationUID;
|
|
386
|
+
|
|
387
|
+
const color = this.getStyle('color', styleSpecifier, annotation);
|
|
388
|
+
|
|
389
|
+
const { canvasPosition, canvasSize } = this.configuration;
|
|
390
|
+
if (canvasPosition?.length) {
|
|
391
|
+
const arrowUID = '1';
|
|
392
|
+
drawArrowSvg(
|
|
393
|
+
svgDrawingHelper,
|
|
394
|
+
annotationUID,
|
|
395
|
+
arrowUID,
|
|
396
|
+
canvasPosition.map((it) => it + canvasSize) as Point2,
|
|
397
|
+
canvasPosition as Point2,
|
|
398
|
+
{
|
|
399
|
+
color,
|
|
400
|
+
width: 1,
|
|
401
|
+
}
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
renderStatus = true;
|
|
406
|
+
|
|
407
|
+
// If rendering engine has been destroyed while rendering
|
|
408
|
+
if (!viewport.getRenderingEngine()) {
|
|
409
|
+
console.warn('Rendering Engine has been destroyed');
|
|
410
|
+
return renderStatus;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
return renderStatus;
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
_isInsideVolume(index1, index2, dimensions) {
|
|
418
|
+
return (
|
|
419
|
+
csUtils.indexWithinDimensions(index1, dimensions) &&
|
|
420
|
+
csUtils.indexWithinDimensions(index2, dimensions)
|
|
421
|
+
);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
function getTextCallback(doneChangingTextCallback) {
|
|
426
|
+
return doneChangingTextCallback(prompt('Enter your annotation:'));
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
function changeTextCallback(data, eventData, doneChangingTextCallback) {
|
|
430
|
+
return doneChangingTextCallback(prompt('Enter your annotation:'));
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
KeyImageTool.toolName = 'KeyImage';
|
|
434
|
+
|
|
435
|
+
export default KeyImageTool;
|
|
@@ -492,11 +492,7 @@ class PlanarFreehandROITool extends AnnotationTool {
|
|
|
492
492
|
|
|
493
493
|
let annotationsToDisplay;
|
|
494
494
|
|
|
495
|
-
if (viewport instanceof
|
|
496
|
-
// Use the default `filterAnnotationsForDisplay` utility, as the stack
|
|
497
|
-
// path doesn't require handles.
|
|
498
|
-
annotationsToDisplay = filterAnnotationsForDisplay(viewport, annotations);
|
|
499
|
-
} else if (viewport instanceof VolumeViewport) {
|
|
495
|
+
if (viewport instanceof VolumeViewport) {
|
|
500
496
|
const camera = viewport.getCamera();
|
|
501
497
|
|
|
502
498
|
const { spacingInNormalDirection } =
|
|
@@ -509,7 +505,9 @@ class PlanarFreehandROITool extends AnnotationTool {
|
|
|
509
505
|
spacingInNormalDirection
|
|
510
506
|
);
|
|
511
507
|
} else {
|
|
512
|
-
|
|
508
|
+
// Use the default `filterAnnotationsForDisplay` utility, as the stack
|
|
509
|
+
// path doesn't require handles.
|
|
510
|
+
annotationsToDisplay = filterAnnotationsForDisplay(viewport, annotations);
|
|
513
511
|
}
|
|
514
512
|
|
|
515
513
|
return annotationsToDisplay;
|