@cornerstonejs/tools 1.56.1 → 1.56.2

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.
Files changed (81) hide show
  1. package/dist/cjs/eventListeners/annotations/annotationRemovedListener.d.ts +2 -0
  2. package/dist/cjs/eventListeners/annotations/annotationRemovedListener.js +35 -0
  3. package/dist/cjs/eventListeners/annotations/annotationRemovedListener.js.map +1 -0
  4. package/dist/cjs/eventListeners/annotations/contourSegmentation/contourSegmentationCompleted.js +27 -19
  5. package/dist/cjs/eventListeners/annotations/contourSegmentation/contourSegmentationCompleted.js.map +1 -1
  6. package/dist/cjs/eventListeners/annotations/contourSegmentation/contourSegmentationRemoved.d.ts +2 -0
  7. package/dist/cjs/eventListeners/annotations/contourSegmentation/contourSegmentationRemoved.js +9 -0
  8. package/dist/cjs/eventListeners/annotations/contourSegmentation/contourSegmentationRemoved.js.map +1 -0
  9. package/dist/cjs/eventListeners/annotations/contourSegmentation/index.d.ts +1 -0
  10. package/dist/cjs/eventListeners/annotations/contourSegmentation/index.js +3 -1
  11. package/dist/cjs/eventListeners/annotations/contourSegmentation/index.js.map +1 -1
  12. package/dist/cjs/eventListeners/annotations/index.d.ts +2 -1
  13. package/dist/cjs/eventListeners/annotations/index.js +3 -1
  14. package/dist/cjs/eventListeners/annotations/index.js.map +1 -1
  15. package/dist/cjs/eventListeners/index.d.ts +2 -2
  16. package/dist/cjs/eventListeners/index.js +2 -1
  17. package/dist/cjs/eventListeners/index.js.map +1 -1
  18. package/dist/cjs/init.js +1 -0
  19. package/dist/cjs/init.js.map +1 -1
  20. package/dist/cjs/tools/annotation/PlanarFreehandContourSegmentationTool.d.ts +2 -0
  21. package/dist/cjs/tools/annotation/PlanarFreehandContourSegmentationTool.js +11 -0
  22. package/dist/cjs/tools/annotation/PlanarFreehandContourSegmentationTool.js.map +1 -1
  23. package/dist/cjs/types/ContourSegmentationAnnotation.d.ts +1 -1
  24. package/dist/cjs/utilities/getViewportForAnnotation.js +6 -13
  25. package/dist/cjs/utilities/getViewportForAnnotation.js.map +1 -1
  26. package/dist/cjs/utilities/getViewportsForAnnotation.d.ts +2 -0
  27. package/dist/cjs/utilities/getViewportsForAnnotation.js +20 -0
  28. package/dist/cjs/utilities/getViewportsForAnnotation.js.map +1 -0
  29. package/dist/esm/eventListeners/annotations/annotationRemovedListener.js +9 -0
  30. package/dist/esm/eventListeners/annotations/annotationRemovedListener.js.map +1 -0
  31. package/dist/esm/eventListeners/annotations/contourSegmentation/contourSegmentationCompleted.js +25 -20
  32. package/dist/esm/eventListeners/annotations/contourSegmentation/contourSegmentationCompleted.js.map +1 -1
  33. package/dist/esm/eventListeners/annotations/contourSegmentation/contourSegmentationRemoved.js +6 -0
  34. package/dist/esm/eventListeners/annotations/contourSegmentation/contourSegmentationRemoved.js.map +1 -0
  35. package/dist/esm/eventListeners/annotations/contourSegmentation/index.js +1 -0
  36. package/dist/esm/eventListeners/annotations/contourSegmentation/index.js.map +1 -1
  37. package/dist/esm/eventListeners/annotations/index.js +2 -1
  38. package/dist/esm/eventListeners/annotations/index.js.map +1 -1
  39. package/dist/esm/eventListeners/index.js +2 -2
  40. package/dist/esm/eventListeners/index.js.map +1 -1
  41. package/dist/esm/init.js +2 -1
  42. package/dist/esm/init.js.map +1 -1
  43. package/dist/esm/tools/annotation/PlanarFreehandContourSegmentationTool.js +11 -0
  44. package/dist/esm/tools/annotation/PlanarFreehandContourSegmentationTool.js.map +1 -1
  45. package/dist/esm/utilities/getViewportForAnnotation.js +3 -13
  46. package/dist/esm/utilities/getViewportForAnnotation.js.map +1 -1
  47. package/dist/esm/utilities/getViewportsForAnnotation.js +17 -0
  48. package/dist/esm/utilities/getViewportsForAnnotation.js.map +1 -0
  49. package/dist/types/eventListeners/annotations/annotationRemovedListener.d.ts +3 -0
  50. package/dist/types/eventListeners/annotations/annotationRemovedListener.d.ts.map +1 -0
  51. package/dist/types/eventListeners/annotations/contourSegmentation/contourSegmentationCompleted.d.ts.map +1 -1
  52. package/dist/types/eventListeners/annotations/contourSegmentation/contourSegmentationRemoved.d.ts +3 -0
  53. package/dist/types/eventListeners/annotations/contourSegmentation/contourSegmentationRemoved.d.ts.map +1 -0
  54. package/dist/types/eventListeners/annotations/contourSegmentation/index.d.ts +1 -0
  55. package/dist/types/eventListeners/annotations/contourSegmentation/index.d.ts.map +1 -1
  56. package/dist/types/eventListeners/annotations/index.d.ts +2 -1
  57. package/dist/types/eventListeners/annotations/index.d.ts.map +1 -1
  58. package/dist/types/eventListeners/index.d.ts +2 -2
  59. package/dist/types/eventListeners/index.d.ts.map +1 -1
  60. package/dist/types/init.d.ts.map +1 -1
  61. package/dist/types/tools/annotation/PlanarFreehandContourSegmentationTool.d.ts +2 -0
  62. package/dist/types/tools/annotation/PlanarFreehandContourSegmentationTool.d.ts.map +1 -1
  63. package/dist/types/types/ContourSegmentationAnnotation.d.ts +1 -1
  64. package/dist/types/types/ContourSegmentationAnnotation.d.ts.map +1 -1
  65. package/dist/types/utilities/getViewportForAnnotation.d.ts.map +1 -1
  66. package/dist/types/utilities/getViewportsForAnnotation.d.ts +3 -0
  67. package/dist/types/utilities/getViewportsForAnnotation.d.ts.map +1 -0
  68. package/dist/umd/index.js +1 -1
  69. package/dist/umd/index.js.map +1 -1
  70. package/package.json +3 -3
  71. package/src/eventListeners/annotations/annotationRemovedListener.ts +13 -0
  72. package/src/eventListeners/annotations/contourSegmentation/contourSegmentationCompleted.ts +42 -24
  73. package/src/eventListeners/annotations/contourSegmentation/contourSegmentationRemoved.ts +11 -0
  74. package/src/eventListeners/annotations/contourSegmentation/index.ts +1 -0
  75. package/src/eventListeners/annotations/index.ts +2 -0
  76. package/src/eventListeners/index.ts +2 -0
  77. package/src/init.ts +6 -0
  78. package/src/tools/annotation/PlanarFreehandContourSegmentationTool.ts +25 -0
  79. package/src/types/ContourSegmentationAnnotation.ts +1 -1
  80. package/src/utilities/getViewportForAnnotation.ts +4 -16
  81. package/src/utilities/getViewportsForAnnotation.ts +31 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cornerstonejs/tools",
3
- "version": "1.56.1",
3
+ "version": "1.56.2",
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.56.1",
32
+ "@cornerstonejs/core": "^1.56.2",
33
33
  "@icr/polyseg-wasm": "0.4.0",
34
34
  "@types/offscreencanvas": "2019.7.3",
35
35
  "comlink": "^4.4.1",
@@ -59,5 +59,5 @@
59
59
  "type": "individual",
60
60
  "url": "https://ohif.org/donate"
61
61
  },
62
- "gitHead": "40ca5acdf263940c17768b36873e75d6616e8462"
62
+ "gitHead": "f0e02324b49825859090ffd7b92523680a6616ce"
63
63
  }
@@ -0,0 +1,13 @@
1
+ import { AnnotationRemovedEventType } from '../../types/EventTypes';
2
+ import * as contourSegUtils from '../../utilities/contourSegmentation';
3
+ import { contourSegmentationRemoved } from './contourSegmentation';
4
+
5
+ export default function annotationRemovedListener(
6
+ evt: AnnotationRemovedEventType
7
+ ) {
8
+ const annotation = evt.detail.annotation;
9
+
10
+ if (contourSegUtils.isContourSegmentationAnnotation(annotation)) {
11
+ contourSegmentationRemoved(evt);
12
+ }
13
+ }
@@ -4,8 +4,8 @@ import {
4
4
  Types,
5
5
  } from '@cornerstonejs/core';
6
6
  import { ContourSegmentationAnnotation } from '../../../types/ContourSegmentationAnnotation';
7
+ import getViewportsForAnnotation from '../../../utilities/getViewportsForAnnotation';
7
8
  import {
8
- getViewportForAnnotation,
9
9
  math,
10
10
  triggerAnnotationRenderForViewportIds,
11
11
  } from '../../../utilities';
@@ -26,6 +26,7 @@ import * as contourUtils from '../../../utilities/contours';
26
26
  import * as contourSegUtils from '../../../utilities/contourSegmentation';
27
27
  import { ToolGroupManager, hasTool as cstHasTool } from '../../../store';
28
28
  import { PlanarFreehandContourSegmentationTool } from '../../../tools';
29
+ import type { Annotation } from '../../../types';
29
30
  import type { ContourAnnotation } from '../../../types/ContourAnnotation';
30
31
  import { ContourWindingDirection } from '../../../types/ContourAnnotation';
31
32
 
@@ -41,7 +42,7 @@ export default async function contourSegmentationCompletedListener(
41
42
  return;
42
43
  }
43
44
 
44
- const viewport = getViewportForAnnotation(sourceAnnotation);
45
+ const viewport = getViewport(sourceAnnotation);
45
46
  const contourSegmentationAnnotations =
46
47
  getValidContourSegmentationAnnotations(sourceAnnotation);
47
48
 
@@ -64,10 +65,6 @@ export default async function contourSegmentationCompletedListener(
64
65
  return;
65
66
  }
66
67
 
67
- if (!isFreehandContourSegToolRegistered(viewport)) {
68
- return;
69
- }
70
-
71
68
  const { targetAnnotation, targetPolyline, isContourHole } =
72
69
  targetAnnotationInfo;
73
70
 
@@ -92,30 +89,43 @@ export default async function contourSegmentationCompletedListener(
92
89
  }
93
90
  }
94
91
 
95
- function isFreehandContourSegToolRegistered(viewport: Types.IViewport) {
92
+ function isFreehandContourSegToolRegisteredForViewport(
93
+ viewport: Types.IViewport,
94
+ silent = false
95
+ ) {
96
96
  const { toolName } = PlanarFreehandContourSegmentationTool;
97
97
 
98
- if (!cstHasTool(PlanarFreehandContourSegmentationTool)) {
99
- console.warn(`${toolName} is not registered in cornerstone`);
100
- return false;
101
- }
102
-
103
98
  const toolGroup = ToolGroupManager.getToolGroupForViewport(
104
99
  viewport.id,
105
100
  viewport.renderingEngineId
106
101
  );
107
102
 
103
+ let errorMessage;
104
+
108
105
  if (!toolGroup.hasTool(toolName)) {
109
- console.warn(`Tool ${toolName} not added to ${toolGroup.id} toolGroup`);
110
- return false;
106
+ errorMessage = `Tool ${toolName} not added to ${toolGroup.id} toolGroup`;
107
+ } else if (!toolGroup.getToolOptions(toolName)) {
108
+ errorMessage = `Tool ${toolName} must be in active/passive state`;
111
109
  }
112
110
 
113
- if (!toolGroup.getToolOptions(toolName)) {
114
- console.warn(`Tool ${toolName} must be in active/passive state`);
115
- return false;
111
+ if (errorMessage && !silent) {
112
+ console.warn(errorMessage);
116
113
  }
117
114
 
118
- return true;
115
+ return !errorMessage;
116
+ }
117
+
118
+ function getViewport(annotation: Annotation) {
119
+ const viewports = getViewportsForAnnotation(annotation);
120
+ const viewportWithToolRegistered = viewports.find((viewport) =>
121
+ isFreehandContourSegToolRegisteredForViewport(viewport, true)
122
+ );
123
+
124
+ // Returns the first viewport even if freehand contour segmentation is not
125
+ // registered because it can be used to project the polyline to create holes.
126
+ // Another verification is done before appending/removing contours which is
127
+ // possible only when the tool is registered.
128
+ return viewportWithToolRegistered ?? viewports[0];
119
129
  }
120
130
 
121
131
  function convertContourPolylineToCanvasSpace(
@@ -136,11 +146,6 @@ function getValidContourSegmentationAnnotations(
136
146
  sourceAnnotation: ContourSegmentationAnnotation
137
147
  ): ContourSegmentationAnnotation[] {
138
148
  const { annotationUID: sourceAnnotationUID } = sourceAnnotation;
139
- const { FrameOfReferenceUID } = sourceAnnotation.metadata;
140
-
141
- if (!FrameOfReferenceUID) {
142
- return [];
143
- }
144
149
 
145
150
  // Get all annotations and filter all contour segmentations locally
146
151
  const allAnnotations = getAllAnnotations();
@@ -249,6 +254,18 @@ function combinePolylines(
249
254
  sourceAnnotation: ContourSegmentationAnnotation,
250
255
  sourcePolyline: Types.Point2[]
251
256
  ) {
257
+ if (!cstHasTool(PlanarFreehandContourSegmentationTool)) {
258
+ console.warn(
259
+ `${PlanarFreehandContourSegmentationTool.toolName} is not registered in cornerstone`
260
+ );
261
+ return;
262
+ }
263
+
264
+ // Cannot append/remove an annotation if it will not be available on any viewport
265
+ if (!isFreehandContourSegToolRegisteredForViewport(viewport)) {
266
+ return;
267
+ }
268
+
252
269
  const sourceStartPoint = sourcePolyline[0];
253
270
  const mergePolylines = math.polyline.containsPoint(
254
271
  targetPolyline,
@@ -329,7 +346,7 @@ function combinePolylines(
329
346
  const polyline = newPolylines[i];
330
347
  const startPoint = viewport.canvasToWorld(polyline[0]);
331
348
  const endPoint = viewport.canvasToWorld(polyline[polyline.length - 1]);
332
- const newAnnotation: ContourAnnotation = {
349
+ const newAnnotation: ContourSegmentationAnnotation = {
333
350
  metadata: {
334
351
  ...metadata,
335
352
  toolName: DEFAULT_CONTOUR_SEG_TOOLNAME,
@@ -368,6 +385,7 @@ function combinePolylines(
368
385
  );
369
386
 
370
387
  addAnnotation(newAnnotation, element);
388
+ contourSegUtils.addContourSegmentationAnnotation(newAnnotation);
371
389
 
372
390
  reassignedContourHolesMap
373
391
  .get(polyline)
@@ -0,0 +1,11 @@
1
+ import type { AnnotationRemovedEventType } from '../../../types/EventTypes';
2
+ import type { ContourSegmentationAnnotation } from '../../../types/ContourSegmentationAnnotation';
3
+ import { removeContourSegmentationAnnotation } from '../../../utilities/contourSegmentation';
4
+
5
+ export default function contourSegmentationRemovedListener(
6
+ evt: AnnotationRemovedEventType
7
+ ) {
8
+ const annotation = evt.detail.annotation as ContourSegmentationAnnotation;
9
+
10
+ removeContourSegmentationAnnotation(annotation);
11
+ }
@@ -1 +1,2 @@
1
1
  export { default as contourSegmentationCompleted } from './contourSegmentationCompleted';
2
+ export { default as contourSegmentationRemoved } from './contourSegmentationRemoved';
@@ -1,9 +1,11 @@
1
1
  import annotationCompletedListener from './annotationCompletedListener';
2
2
  import annotationSelectionListener from './annotationSelectionListener';
3
3
  import annotationModifiedListener from './annotationModifiedListener';
4
+ import annotationRemovedListener from './annotationRemovedListener';
4
5
 
5
6
  export {
6
7
  annotationCompletedListener,
7
8
  annotationSelectionListener,
8
9
  annotationModifiedListener,
10
+ annotationRemovedListener,
9
11
  };
@@ -13,6 +13,7 @@ import {
13
13
  annotationCompletedListener,
14
14
  annotationSelectionListener,
15
15
  annotationModifiedListener,
16
+ annotationRemovedListener,
16
17
  } from './annotations';
17
18
  //import touchEventListeners from './touchEventListeners';
18
19
 
@@ -29,4 +30,5 @@ export {
29
30
  annotationCompletedListener,
30
31
  annotationSelectionListener,
31
32
  annotationModifiedListener,
33
+ annotationRemovedListener,
32
34
  };
package/src/init.ts CHANGED
@@ -6,6 +6,7 @@ import { addEnabledElement, removeEnabledElement } from './store';
6
6
  import { resetCornerstoneToolsState } from './store/state';
7
7
  import {
8
8
  annotationCompletedListener,
9
+ annotationRemovedListener,
9
10
  annotationSelectionListener,
10
11
  annotationModifiedListener,
11
12
  segmentationDataModifiedEventListener,
@@ -124,6 +125,11 @@ function _addCornerstoneToolsEventListeners() {
124
125
  annotationSelectionListener
125
126
  );
126
127
 
128
+ eventTarget.addEventListener(
129
+ TOOLS_EVENTS.ANNOTATION_REMOVED,
130
+ annotationRemovedListener
131
+ );
132
+
127
133
  /**
128
134
  * Segmentation
129
135
  */
@@ -1,5 +1,8 @@
1
1
  import { utilities } from '@cornerstonejs/core';
2
2
  import type { PublicToolProps } from '../../types';
3
+ import type { AnnotationRenderContext } from '../../types';
4
+ import { PlanarFreehandContourSegmentationAnnotation } from '../../types/ToolSpecificAnnotationTypes';
5
+ import { triggerSegmentationDataModified } from '../../stateManagement/segmentation/triggerSegmentationEvents';
3
6
  import PlanarFreehandROITool from './PlanarFreehandROITool';
4
7
 
5
8
  class PlanarFreehandContourSegmentationTool extends PlanarFreehandROITool {
@@ -28,6 +31,28 @@ class PlanarFreehandContourSegmentationTool extends PlanarFreehandROITool {
28
31
  // Re-enable contour segmentation behavior disabled by PlanarFreehandROITool
29
32
  return true;
30
33
  }
34
+
35
+ protected renderAnnotationInstance(
36
+ renderContext: AnnotationRenderContext
37
+ ): boolean {
38
+ const annotation =
39
+ renderContext.annotation as PlanarFreehandContourSegmentationAnnotation;
40
+ const { invalidated } = annotation;
41
+
42
+ // Render the annotation before triggering events
43
+ const renderResult = super.renderAnnotationInstance(renderContext);
44
+
45
+ if (invalidated) {
46
+ const { segmentationId } = annotation.data.segmentation;
47
+
48
+ // This event is trigged by ContourSegmentationBaseTool but PlanarFreehandROITool
49
+ // is the only contour class that does not call `renderAnnotationInstace` from
50
+ // its base class.
51
+ triggerSegmentationDataModified(segmentationId);
52
+ }
53
+
54
+ return renderResult;
55
+ }
31
56
  }
32
57
 
33
58
  PlanarFreehandContourSegmentationTool.toolName =
@@ -16,7 +16,7 @@ export type ContourSegmentationAnnotationData = {
16
16
  originalPolyline?: Types.Point3[];
17
17
  };
18
18
  };
19
- handles: {
19
+ handles?: {
20
20
  /**
21
21
  * Segmentation contours can be interpolated between slices to produce
22
22
  * intermediate data. The interpolation sources are source data for
@@ -1,7 +1,5 @@
1
- import { getEnabledElements, utilities as csUtils } from '@cornerstonejs/core';
2
1
  import type { Annotation } from '../types';
3
-
4
- const { isEqual } = csUtils;
2
+ import getViewportsForAnnotation from './getViewportsForAnnotation';
5
3
 
6
4
  /**
7
5
  * Finds a matching viewport in terms of the orientation of the annotation data
@@ -13,17 +11,7 @@ const { isEqual } = csUtils;
13
11
  * @returns The viewport to display in
14
12
  */
15
13
  export default function getViewportForAnnotation(annotation: Annotation) {
16
- const { metadata } = annotation;
17
- const enabledElement = getEnabledElements().find((enabledElement) => {
18
- if (enabledElement.FrameOfReferenceUID === metadata.FrameOfReferenceUID) {
19
- const viewport = enabledElement.viewport;
20
- const { viewPlaneNormal, viewUp } = viewport.getCamera();
21
- return (
22
- isEqual(viewPlaneNormal, metadata.viewPlaneNormal) &&
23
- (!metadata.viewUp || isEqual(viewUp, metadata.viewUp))
24
- );
25
- }
26
- return;
27
- });
28
- return enabledElement?.viewport;
14
+ const viewports = getViewportsForAnnotation(annotation);
15
+
16
+ return viewports.length ? viewports[0] : undefined;
29
17
  }
@@ -0,0 +1,31 @@
1
+ import { getEnabledElements, utilities as csUtils } from '@cornerstonejs/core';
2
+ import type { Annotation } from '../types';
3
+
4
+ const { isEqual } = csUtils;
5
+
6
+ /**
7
+ * Finds a all matching viewports in terms of the orientation of the annotation data
8
+ * and the frame of reference. This doesn't mean the annotation IS being displayed
9
+ * on these viewports, just that it could be by navigating the slice, and/or pan/zoom,
10
+ * without changing the orientation.
11
+ *
12
+ * @param annotation - Annotation to find the viewports that it could display in
13
+ * @returns All viewports to display in
14
+ */
15
+ export default function getViewportsForAnnotation(annotation: Annotation) {
16
+ const { metadata } = annotation;
17
+
18
+ return getEnabledElements()
19
+ .filter((enabledElement) => {
20
+ if (enabledElement.FrameOfReferenceUID === metadata.FrameOfReferenceUID) {
21
+ const viewport = enabledElement.viewport;
22
+ const { viewPlaneNormal, viewUp } = viewport.getCamera();
23
+ return (
24
+ isEqual(viewPlaneNormal, metadata.viewPlaneNormal) &&
25
+ (!metadata.viewUp || isEqual(viewUp, metadata.viewUp))
26
+ );
27
+ }
28
+ return;
29
+ })
30
+ .map((enabledElement) => enabledElement.viewport);
31
+ }