@cornerstonejs/tools 1.32.2 → 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.
Files changed (226) hide show
  1. package/dist/cjs/eventListeners/index.d.ts +2 -2
  2. package/dist/cjs/eventListeners/index.js +2 -1
  3. package/dist/cjs/eventListeners/index.js.map +1 -1
  4. package/dist/cjs/eventListeners/segmentation/imageChangeEventListener.d.ts +5 -0
  5. package/dist/cjs/eventListeners/segmentation/imageChangeEventListener.js +143 -0
  6. package/dist/cjs/eventListeners/segmentation/imageChangeEventListener.js.map +1 -0
  7. package/dist/cjs/eventListeners/segmentation/index.d.ts +2 -1
  8. package/dist/cjs/eventListeners/segmentation/index.js +3 -1
  9. package/dist/cjs/eventListeners/segmentation/index.js.map +1 -1
  10. package/dist/cjs/eventListeners/segmentation/segmentationDataModifiedEventListener.js +31 -5
  11. package/dist/cjs/eventListeners/segmentation/segmentationDataModifiedEventListener.js.map +1 -1
  12. package/dist/cjs/store/addEnabledElement.js +1 -0
  13. package/dist/cjs/store/addEnabledElement.js.map +1 -1
  14. package/dist/cjs/store/removeEnabledElement.js +2 -0
  15. package/dist/cjs/store/removeEnabledElement.js.map +1 -1
  16. package/dist/cjs/tools/StackScrollToolMouseWheelTool.d.ts +1 -0
  17. package/dist/cjs/tools/StackScrollToolMouseWheelTool.js +2 -0
  18. package/dist/cjs/tools/StackScrollToolMouseWheelTool.js.map +1 -1
  19. package/dist/cjs/tools/annotation/CircleROITool.js +3 -1
  20. package/dist/cjs/tools/annotation/CircleROITool.js.map +1 -1
  21. package/dist/cjs/tools/annotation/EllipticalROITool.js +1 -1
  22. package/dist/cjs/tools/annotation/EllipticalROITool.js.map +1 -1
  23. package/dist/cjs/tools/displayTools/Labelmap/addLabelmapToElement.d.ts +2 -1
  24. package/dist/cjs/tools/displayTools/Labelmap/addLabelmapToElement.js +23 -10
  25. package/dist/cjs/tools/displayTools/Labelmap/addLabelmapToElement.js.map +1 -1
  26. package/dist/cjs/tools/displayTools/Labelmap/labelmapDisplay.d.ts +1 -1
  27. package/dist/cjs/tools/displayTools/Labelmap/labelmapDisplay.js +36 -22
  28. package/dist/cjs/tools/displayTools/Labelmap/labelmapDisplay.js.map +1 -1
  29. package/dist/cjs/tools/displayTools/Labelmap/validateRepresentationData.js +6 -5
  30. package/dist/cjs/tools/displayTools/Labelmap/validateRepresentationData.js.map +1 -1
  31. package/dist/cjs/tools/segmentation/BrushTool.js +40 -45
  32. package/dist/cjs/tools/segmentation/BrushTool.js.map +1 -1
  33. package/dist/cjs/tools/segmentation/CircleScissorsTool.d.ts +4 -2
  34. package/dist/cjs/tools/segmentation/CircleScissorsTool.js +18 -17
  35. package/dist/cjs/tools/segmentation/CircleScissorsTool.js.map +1 -1
  36. package/dist/cjs/tools/segmentation/PaintFillTool.js +28 -5
  37. package/dist/cjs/tools/segmentation/PaintFillTool.js.map +1 -1
  38. package/dist/cjs/tools/segmentation/RectangleScissorsTool.d.ts +3 -1
  39. package/dist/cjs/tools/segmentation/RectangleScissorsTool.js +15 -16
  40. package/dist/cjs/tools/segmentation/RectangleScissorsTool.js.map +1 -1
  41. package/dist/cjs/tools/segmentation/SphereScissorsTool.d.ts +4 -2
  42. package/dist/cjs/tools/segmentation/SphereScissorsTool.js +20 -20
  43. package/dist/cjs/tools/segmentation/SphereScissorsTool.js.map +1 -1
  44. package/dist/cjs/tools/segmentation/strategies/eraseCircle.d.ts +2 -10
  45. package/dist/cjs/tools/segmentation/strategies/eraseCircle.js.map +1 -1
  46. package/dist/cjs/tools/segmentation/strategies/eraseRectangle.d.ts +4 -8
  47. package/dist/cjs/tools/segmentation/strategies/eraseRectangle.js +4 -20
  48. package/dist/cjs/tools/segmentation/strategies/eraseRectangle.js.map +1 -1
  49. package/dist/cjs/tools/segmentation/strategies/eraseSphere.d.ts +2 -10
  50. package/dist/cjs/tools/segmentation/strategies/eraseSphere.js.map +1 -1
  51. package/dist/cjs/tools/segmentation/strategies/fillCircle.d.ts +3 -11
  52. package/dist/cjs/tools/segmentation/strategies/fillCircle.js +57 -32
  53. package/dist/cjs/tools/segmentation/strategies/fillCircle.js.map +1 -1
  54. package/dist/cjs/tools/segmentation/strategies/fillRectangle.d.ts +2 -7
  55. package/dist/cjs/tools/segmentation/strategies/fillRectangle.js +16 -8
  56. package/dist/cjs/tools/segmentation/strategies/fillRectangle.js.map +1 -1
  57. package/dist/cjs/tools/segmentation/strategies/fillSphere.d.ts +2 -10
  58. package/dist/cjs/tools/segmentation/strategies/fillSphere.js +31 -17
  59. package/dist/cjs/tools/segmentation/strategies/fillSphere.js.map +1 -1
  60. package/dist/cjs/tools/segmentation/strategies/utils/getStrategyData.d.ts +9 -0
  61. package/dist/cjs/tools/segmentation/strategies/utils/getStrategyData.js +43 -0
  62. package/dist/cjs/tools/segmentation/strategies/utils/getStrategyData.js.map +1 -0
  63. package/dist/cjs/tools/segmentation/strategies/utils/isWithinThreshold.d.ts +2 -2
  64. package/dist/cjs/tools/segmentation/strategies/utils/isWithinThreshold.js +2 -2
  65. package/dist/cjs/tools/segmentation/strategies/utils/isWithinThreshold.js.map +1 -1
  66. package/dist/cjs/tools/segmentation/strategies/utils/stackVolumeCheck.d.ts +5 -0
  67. package/dist/cjs/tools/segmentation/strategies/utils/stackVolumeCheck.js +13 -0
  68. package/dist/cjs/tools/segmentation/strategies/utils/stackVolumeCheck.js.map +1 -0
  69. package/dist/cjs/types/LabelmapToolOperationData.d.ts +14 -0
  70. package/dist/cjs/types/LabelmapToolOperationData.js +3 -0
  71. package/dist/cjs/types/LabelmapToolOperationData.js.map +1 -0
  72. package/dist/cjs/types/LabelmapTypes.d.ts +5 -1
  73. package/dist/cjs/types/ScrollOptions.d.ts +1 -0
  74. package/dist/cjs/types/index.d.ts +2 -1
  75. package/dist/cjs/utilities/math/ellipse/pointInEllipse.d.ts +7 -9
  76. package/dist/cjs/utilities/math/ellipse/pointInEllipse.js +19 -11
  77. package/dist/cjs/utilities/math/ellipse/pointInEllipse.js.map +1 -1
  78. package/dist/cjs/utilities/scroll.d.ts +1 -1
  79. package/dist/cjs/utilities/scroll.js +5 -4
  80. package/dist/cjs/utilities/scroll.js.map +1 -1
  81. package/dist/esm/eventListeners/index.js +2 -2
  82. package/dist/esm/eventListeners/index.js.map +1 -1
  83. package/dist/esm/eventListeners/segmentation/imageChangeEventListener.js +115 -0
  84. package/dist/esm/eventListeners/segmentation/imageChangeEventListener.js.map +1 -0
  85. package/dist/esm/eventListeners/segmentation/index.js +2 -1
  86. package/dist/esm/eventListeners/segmentation/index.js.map +1 -1
  87. package/dist/esm/eventListeners/segmentation/segmentationDataModifiedEventListener.js +32 -6
  88. package/dist/esm/eventListeners/segmentation/segmentationDataModifiedEventListener.js.map +1 -1
  89. package/dist/esm/store/addEnabledElement.js +2 -1
  90. package/dist/esm/store/addEnabledElement.js.map +1 -1
  91. package/dist/esm/store/removeEnabledElement.js +2 -0
  92. package/dist/esm/store/removeEnabledElement.js.map +1 -1
  93. package/dist/esm/tools/StackScrollToolMouseWheelTool.js +2 -0
  94. package/dist/esm/tools/StackScrollToolMouseWheelTool.js.map +1 -1
  95. package/dist/esm/tools/annotation/CircleROITool.js +4 -2
  96. package/dist/esm/tools/annotation/CircleROITool.js.map +1 -1
  97. package/dist/esm/tools/annotation/EllipticalROITool.js +1 -1
  98. package/dist/esm/tools/annotation/EllipticalROITool.js.map +1 -1
  99. package/dist/esm/tools/displayTools/Labelmap/addLabelmapToElement.js +24 -11
  100. package/dist/esm/tools/displayTools/Labelmap/addLabelmapToElement.js.map +1 -1
  101. package/dist/esm/tools/displayTools/Labelmap/labelmapDisplay.js +36 -22
  102. package/dist/esm/tools/displayTools/Labelmap/labelmapDisplay.js.map +1 -1
  103. package/dist/esm/tools/displayTools/Labelmap/validateRepresentationData.js +6 -5
  104. package/dist/esm/tools/displayTools/Labelmap/validateRepresentationData.js.map +1 -1
  105. package/dist/esm/tools/segmentation/BrushTool.js +38 -29
  106. package/dist/esm/tools/segmentation/BrushTool.js.map +1 -1
  107. package/dist/esm/tools/segmentation/CircleScissorsTool.js +27 -15
  108. package/dist/esm/tools/segmentation/CircleScissorsTool.js.map +1 -1
  109. package/dist/esm/tools/segmentation/PaintFillTool.js +28 -5
  110. package/dist/esm/tools/segmentation/PaintFillTool.js.map +1 -1
  111. package/dist/esm/tools/segmentation/RectangleScissorsTool.js +26 -17
  112. package/dist/esm/tools/segmentation/RectangleScissorsTool.js.map +1 -1
  113. package/dist/esm/tools/segmentation/SphereScissorsTool.js +28 -17
  114. package/dist/esm/tools/segmentation/SphereScissorsTool.js.map +1 -1
  115. package/dist/esm/tools/segmentation/strategies/eraseCircle.js.map +1 -1
  116. package/dist/esm/tools/segmentation/strategies/eraseRectangle.js +4 -20
  117. package/dist/esm/tools/segmentation/strategies/eraseRectangle.js.map +1 -1
  118. package/dist/esm/tools/segmentation/strategies/eraseSphere.js.map +1 -1
  119. package/dist/esm/tools/segmentation/strategies/fillCircle.js +56 -31
  120. package/dist/esm/tools/segmentation/strategies/fillCircle.js.map +1 -1
  121. package/dist/esm/tools/segmentation/strategies/fillRectangle.js +16 -8
  122. package/dist/esm/tools/segmentation/strategies/fillRectangle.js.map +1 -1
  123. package/dist/esm/tools/segmentation/strategies/fillSphere.js +32 -18
  124. package/dist/esm/tools/segmentation/strategies/fillSphere.js.map +1 -1
  125. package/dist/esm/tools/segmentation/strategies/utils/getStrategyData.js +40 -0
  126. package/dist/esm/tools/segmentation/strategies/utils/getStrategyData.js.map +1 -0
  127. package/dist/esm/tools/segmentation/strategies/utils/isWithinThreshold.js +2 -2
  128. package/dist/esm/tools/segmentation/strategies/utils/isWithinThreshold.js.map +1 -1
  129. package/dist/esm/tools/segmentation/strategies/utils/stackVolumeCheck.js +9 -0
  130. package/dist/esm/tools/segmentation/strategies/utils/stackVolumeCheck.js.map +1 -0
  131. package/dist/esm/types/LabelmapToolOperationData.js +2 -0
  132. package/dist/esm/types/LabelmapToolOperationData.js.map +1 -0
  133. package/dist/esm/utilities/math/ellipse/pointInEllipse.js +19 -11
  134. package/dist/esm/utilities/math/ellipse/pointInEllipse.js.map +1 -1
  135. package/dist/esm/utilities/scroll.js +5 -4
  136. package/dist/esm/utilities/scroll.js.map +1 -1
  137. package/dist/types/eventListeners/index.d.ts +2 -2
  138. package/dist/types/eventListeners/index.d.ts.map +1 -1
  139. package/dist/types/eventListeners/segmentation/imageChangeEventListener.d.ts +6 -0
  140. package/dist/types/eventListeners/segmentation/imageChangeEventListener.d.ts.map +1 -0
  141. package/dist/types/eventListeners/segmentation/index.d.ts +2 -1
  142. package/dist/types/eventListeners/segmentation/index.d.ts.map +1 -1
  143. package/dist/types/eventListeners/segmentation/segmentationDataModifiedEventListener.d.ts.map +1 -1
  144. package/dist/types/store/addEnabledElement.d.ts.map +1 -1
  145. package/dist/types/store/removeEnabledElement.d.ts.map +1 -1
  146. package/dist/types/tools/StackScrollToolMouseWheelTool.d.ts +1 -0
  147. package/dist/types/tools/StackScrollToolMouseWheelTool.d.ts.map +1 -1
  148. package/dist/types/tools/annotation/CircleROITool.d.ts.map +1 -1
  149. package/dist/types/tools/displayTools/Labelmap/addLabelmapToElement.d.ts +2 -1
  150. package/dist/types/tools/displayTools/Labelmap/addLabelmapToElement.d.ts.map +1 -1
  151. package/dist/types/tools/displayTools/Labelmap/labelmapDisplay.d.ts +1 -1
  152. package/dist/types/tools/displayTools/Labelmap/labelmapDisplay.d.ts.map +1 -1
  153. package/dist/types/tools/displayTools/Labelmap/validateRepresentationData.d.ts.map +1 -1
  154. package/dist/types/tools/segmentation/BrushTool.d.ts.map +1 -1
  155. package/dist/types/tools/segmentation/CircleScissorsTool.d.ts +4 -2
  156. package/dist/types/tools/segmentation/CircleScissorsTool.d.ts.map +1 -1
  157. package/dist/types/tools/segmentation/PaintFillTool.d.ts.map +1 -1
  158. package/dist/types/tools/segmentation/RectangleScissorsTool.d.ts +3 -1
  159. package/dist/types/tools/segmentation/RectangleScissorsTool.d.ts.map +1 -1
  160. package/dist/types/tools/segmentation/SphereScissorsTool.d.ts +4 -2
  161. package/dist/types/tools/segmentation/SphereScissorsTool.d.ts.map +1 -1
  162. package/dist/types/tools/segmentation/strategies/eraseCircle.d.ts +2 -10
  163. package/dist/types/tools/segmentation/strategies/eraseCircle.d.ts.map +1 -1
  164. package/dist/types/tools/segmentation/strategies/eraseRectangle.d.ts +4 -8
  165. package/dist/types/tools/segmentation/strategies/eraseRectangle.d.ts.map +1 -1
  166. package/dist/types/tools/segmentation/strategies/eraseSphere.d.ts +2 -10
  167. package/dist/types/tools/segmentation/strategies/eraseSphere.d.ts.map +1 -1
  168. package/dist/types/tools/segmentation/strategies/fillCircle.d.ts +3 -11
  169. package/dist/types/tools/segmentation/strategies/fillCircle.d.ts.map +1 -1
  170. package/dist/types/tools/segmentation/strategies/fillRectangle.d.ts +2 -7
  171. package/dist/types/tools/segmentation/strategies/fillRectangle.d.ts.map +1 -1
  172. package/dist/types/tools/segmentation/strategies/fillSphere.d.ts +2 -10
  173. package/dist/types/tools/segmentation/strategies/fillSphere.d.ts.map +1 -1
  174. package/dist/types/tools/segmentation/strategies/utils/getStrategyData.d.ts +10 -0
  175. package/dist/types/tools/segmentation/strategies/utils/getStrategyData.d.ts.map +1 -0
  176. package/dist/types/tools/segmentation/strategies/utils/isWithinThreshold.d.ts +2 -2
  177. package/dist/types/tools/segmentation/strategies/utils/isWithinThreshold.d.ts.map +1 -1
  178. package/dist/types/tools/segmentation/strategies/utils/stackVolumeCheck.d.ts +6 -0
  179. package/dist/types/tools/segmentation/strategies/utils/stackVolumeCheck.d.ts.map +1 -0
  180. package/dist/types/types/LabelmapToolOperationData.d.ts +15 -0
  181. package/dist/types/types/LabelmapToolOperationData.d.ts.map +1 -0
  182. package/dist/types/types/LabelmapTypes.d.ts +5 -1
  183. package/dist/types/types/LabelmapTypes.d.ts.map +1 -1
  184. package/dist/types/types/ScrollOptions.d.ts +1 -0
  185. package/dist/types/types/ScrollOptions.d.ts.map +1 -1
  186. package/dist/types/types/index.d.ts +2 -1
  187. package/dist/types/types/index.d.ts.map +1 -1
  188. package/dist/types/utilities/math/ellipse/pointInEllipse.d.ts +7 -9
  189. package/dist/types/utilities/math/ellipse/pointInEllipse.d.ts.map +1 -1
  190. package/dist/types/utilities/scroll.d.ts +1 -1
  191. package/dist/types/utilities/scroll.d.ts.map +1 -1
  192. package/dist/umd/index.js +1 -1
  193. package/dist/umd/index.js.map +1 -1
  194. package/package.json +3 -3
  195. package/src/eventListeners/index.ts +2 -0
  196. package/src/eventListeners/segmentation/imageChangeEventListener.ts +215 -0
  197. package/src/eventListeners/segmentation/index.ts +2 -0
  198. package/src/eventListeners/segmentation/segmentationDataModifiedEventListener.ts +70 -9
  199. package/src/store/addEnabledElement.ts +2 -0
  200. package/src/store/removeEnabledElement.ts +3 -0
  201. package/src/tools/StackScrollToolMouseWheelTool.ts +2 -0
  202. package/src/tools/annotation/CircleROITool.ts +5 -5
  203. package/src/tools/annotation/EllipticalROITool.ts +1 -1
  204. package/src/tools/displayTools/Labelmap/addLabelmapToElement.ts +51 -22
  205. package/src/tools/displayTools/Labelmap/labelmapDisplay.ts +65 -35
  206. package/src/tools/displayTools/Labelmap/validateRepresentationData.ts +17 -11
  207. package/src/tools/segmentation/BrushTool.ts +78 -39
  208. package/src/tools/segmentation/CircleScissorsTool.ts +46 -29
  209. package/src/tools/segmentation/PaintFillTool.ts +45 -8
  210. package/src/tools/segmentation/RectangleScissorsTool.ts +41 -31
  211. package/src/tools/segmentation/SphereScissorsTool.ts +46 -28
  212. package/src/tools/segmentation/strategies/eraseCircle.ts +3 -11
  213. package/src/tools/segmentation/strategies/eraseRectangle.ts +13 -42
  214. package/src/tools/segmentation/strategies/eraseSphere.ts +2 -10
  215. package/src/tools/segmentation/strategies/fillCircle.ts +93 -61
  216. package/src/tools/segmentation/strategies/fillRectangle.ts +31 -22
  217. package/src/tools/segmentation/strategies/fillSphere.ts +51 -41
  218. package/src/tools/segmentation/strategies/utils/getStrategyData.ts +58 -0
  219. package/src/tools/segmentation/strategies/utils/isWithinThreshold.ts +3 -2
  220. package/src/tools/segmentation/strategies/utils/stackVolumeCheck.ts +33 -0
  221. package/src/types/LabelmapToolOperationData.ts +27 -0
  222. package/src/types/LabelmapTypes.ts +16 -1
  223. package/src/types/ScrollOptions.ts +1 -0
  224. package/src/types/index.ts +8 -0
  225. package/src/utilities/math/ellipse/pointInEllipse.ts +43 -22
  226. package/src/utilities/scroll.ts +7 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cornerstonejs/tools",
3
- "version": "1.32.2",
3
+ "version": "1.33.0",
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.2",
32
+ "@cornerstonejs/core": "^1.33.0",
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": "c6c2dfdee7f3b1137fae77d9154809267076dc87"
56
+ "gitHead": "bcfcf24cacbc6d230a3ddc722823d5ecc05cbb6d"
57
57
  }
@@ -7,6 +7,7 @@ import {
7
7
  segmentationRepresentationModifiedEventListener,
8
8
  segmentationRepresentationRemovedEventListener,
9
9
  segmentationModifiedListener,
10
+ imageChangeEventListener,
10
11
  } from './segmentation';
11
12
  import {
12
13
  annotationSelectionListener,
@@ -23,6 +24,7 @@ export {
23
24
  segmentationModifiedListener,
24
25
  segmentationRepresentationRemovedEventListener,
25
26
  segmentationDataModifiedEventListener,
27
+ imageChangeEventListener,
26
28
  annotationSelectionListener,
27
29
  annotationModifiedListener,
28
30
  };
@@ -0,0 +1,215 @@
1
+ import {
2
+ StackViewport,
3
+ getEnabledElement,
4
+ Enums,
5
+ getEnabledElementByIds,
6
+ cache,
7
+ utilities,
8
+ Types,
9
+ metaData,
10
+ } from '@cornerstonejs/core';
11
+ import { getToolGroupForViewport } from '../../store/ToolGroupManager';
12
+ import Representations from '../../enums/SegmentationRepresentations';
13
+ import * as SegmentationState from '../../stateManagement/segmentation/segmentationState';
14
+ import { LabelmapSegmentationDataStack } from '../../types/LabelmapTypes';
15
+ import { isVolumeSegmentation } from '../../tools/segmentation/strategies/utils/stackVolumeCheck';
16
+ import vtkDataArray from '@kitware/vtk.js/Common/Core/DataArray';
17
+ import vtkImageData from '@kitware/vtk.js/Common/DataModel/ImageData';
18
+ import triggerSegmentationRender from '../../utilities/segmentation/triggerSegmentationRender';
19
+
20
+ const enable = function (element: HTMLDivElement): void {
21
+ const { viewport } = getEnabledElement(element);
22
+
23
+ if (!(viewport instanceof StackViewport)) {
24
+ return;
25
+ }
26
+
27
+ element.addEventListener(
28
+ Enums.Events.STACK_NEW_IMAGE,
29
+ _imageChangeEventListener as EventListener
30
+ );
31
+ // this listener handles the segmentation modifications
32
+ element.addEventListener(
33
+ Enums.Events.IMAGE_RENDERED,
34
+ _imageChangeEventListener as EventListener
35
+ );
36
+ };
37
+
38
+ const disable = function (element: HTMLDivElement): void {
39
+ const { viewport } = getEnabledElement(element);
40
+
41
+ if (!(viewport instanceof StackViewport)) {
42
+ return;
43
+ }
44
+
45
+ element.removeEventListener(
46
+ Enums.Events.STACK_NEW_IMAGE,
47
+ _imageChangeEventListener as EventListener
48
+ );
49
+ element.removeEventListener(
50
+ Enums.Events.IMAGE_RENDERED,
51
+ _imageChangeEventListener as EventListener
52
+ );
53
+ };
54
+
55
+ /**
56
+ * When the image is rendered, check what tools can be rendered for this element.
57
+ *
58
+ * - First we get all tools which are active, passive or enabled on the element.
59
+ * - If any of these tools have a `renderAnnotation` method, then we render them.
60
+ * - Note that these tools don't necessarily have to be instances of `AnnotationTool`,
61
+ * Any tool may register a `renderAnnotation` method (e.g. a tool that displays an overlay).
62
+ *
63
+ * @param evt - The normalized IMAGE_RENDERED event.
64
+ */
65
+ function _imageChangeEventListener(evt) {
66
+ const eventData = evt.detail;
67
+ const { viewportId, renderingEngineId } = eventData;
68
+ const { viewport } = getEnabledElementByIds(
69
+ viewportId,
70
+ renderingEngineId
71
+ ) as { viewport: Types.IStackViewport };
72
+
73
+ const toolGroup = getToolGroupForViewport(viewportId, renderingEngineId);
74
+ let toolGroupSegmentationRepresentations =
75
+ SegmentationState.getSegmentationRepresentations(toolGroup.id) || [];
76
+
77
+ toolGroupSegmentationRepresentations =
78
+ toolGroupSegmentationRepresentations.filter(
79
+ (representation) => representation.type === Representations.Labelmap
80
+ );
81
+
82
+ if (!toolGroupSegmentationRepresentations?.length) {
83
+ return;
84
+ }
85
+
86
+ const segmentationRepresentations = {};
87
+ toolGroupSegmentationRepresentations.forEach((representation) => {
88
+ const segmentation = SegmentationState.getSegmentation(
89
+ representation.segmentationId
90
+ );
91
+
92
+ if (!segmentation) {
93
+ return;
94
+ }
95
+
96
+ const labelmapData =
97
+ segmentation.representationData[Representations.Labelmap];
98
+
99
+ if (isVolumeSegmentation(labelmapData)) {
100
+ return;
101
+ }
102
+
103
+ const { imageIdReferenceMap } =
104
+ labelmapData as LabelmapSegmentationDataStack;
105
+
106
+ segmentationRepresentations[representation.segmentationRepresentationUID] =
107
+ {
108
+ imageIdReferenceMap,
109
+ };
110
+ });
111
+
112
+ const representationList = Object.keys(segmentationRepresentations);
113
+ const currentImageId = viewport.getCurrentImageId();
114
+ const actors = viewport.getActors();
115
+
116
+ actors.forEach((actor) => {
117
+ if (!representationList.includes(actor.uid)) {
118
+ return;
119
+ }
120
+ const segmentationActor = actor.actor;
121
+
122
+ const { imageIdReferenceMap } = segmentationRepresentations[actor.uid];
123
+
124
+ const derivedImageId = imageIdReferenceMap.get(currentImageId);
125
+
126
+ const segmentationImageData = segmentationActor.getMapper().getInputData();
127
+
128
+ if (!derivedImageId) {
129
+ // this means that this slice doesn't have a segmentation for this representation
130
+ // this can be a case where the segmentation was added to certain slices only
131
+ // so we can keep the actor but empty out the imageData
132
+ const scalarArray = vtkDataArray.newInstance({
133
+ name: 'Pixels',
134
+ numberOfComponents: 1,
135
+ values: new Uint8Array(segmentationImageData.getNumberOfPoints()),
136
+ });
137
+
138
+ const imageData = vtkImageData.newInstance();
139
+ imageData.getPointData().setScalars(scalarArray);
140
+ segmentationActor.getMapper().setInputData(imageData);
141
+ return;
142
+ }
143
+
144
+ const derivedImage = cache.getImage(derivedImageId);
145
+
146
+ const { origin, dimensions, spacing, direction } =
147
+ viewport.getImageDataMetadata(derivedImage);
148
+
149
+ segmentationImageData.setOrigin(origin);
150
+ segmentationImageData.modified();
151
+
152
+ if (
153
+ segmentationImageData.getDimensions()[0] !== dimensions[0] ||
154
+ segmentationImageData.getDimensions()[1] !== dimensions[1]
155
+ ) {
156
+ // IMPORTANT: Not sure why we can't just update the dimensions
157
+ // and the orientation of the image data and then call modified
158
+ // I tried calling modified on everything, but seems like we should remove
159
+ // and add the actor again below
160
+ viewport.removeActors([actor.uid]);
161
+ viewport.addImages(
162
+ [
163
+ {
164
+ imageId: derivedImageId,
165
+ actorUID: actor.uid,
166
+ callback: ({ imageActor }) => {
167
+ const scalarArray = vtkDataArray.newInstance({
168
+ name: 'Pixels',
169
+ numberOfComponents: 1,
170
+ values: [...derivedImage.getPixelData()],
171
+ });
172
+
173
+ const imageData = vtkImageData.newInstance();
174
+
175
+ imageData.setDimensions(dimensions[0], dimensions[1], 1);
176
+ imageData.setSpacing(spacing);
177
+ imageData.setDirection(direction);
178
+ imageData.setOrigin(origin);
179
+ imageData.getPointData().setScalars(scalarArray);
180
+
181
+ imageActor.getMapper().setInputData(imageData);
182
+ },
183
+ },
184
+ ],
185
+ true,
186
+ false
187
+ );
188
+
189
+ triggerSegmentationRender(toolGroup.id);
190
+ return;
191
+ }
192
+
193
+ utilities.updateVTKImageDataWithCornerstoneImage(
194
+ segmentationImageData,
195
+ derivedImage
196
+ );
197
+ viewport.render();
198
+
199
+ // This is put here to make sure that the segmentation is rendered
200
+ // for the initial image as well after that we don't need it since
201
+ // stack new image is called when changing slices
202
+ if (evt.type === Enums.Events.IMAGE_RENDERED) {
203
+ // unsubscribe after the initial render
204
+ viewport.element.removeEventListener(
205
+ Enums.Events.IMAGE_RENDERED,
206
+ _imageChangeEventListener as EventListener
207
+ );
208
+ }
209
+ });
210
+ }
211
+
212
+ export default {
213
+ enable,
214
+ disable,
215
+ };
@@ -2,10 +2,12 @@ import segmentationRepresentationModifiedEventListener from './segmentationRepre
2
2
  import segmentationDataModifiedEventListener from './segmentationDataModifiedEventListener';
3
3
  import segmentationRepresentationRemovedEventListener from './segmentationRepresentationRemovedEventListener';
4
4
  import segmentationModifiedListener from './segmentationModifiedEventListener';
5
+ import imageChangeEventListener from './imageChangeEventListener';
5
6
 
6
7
  export {
7
8
  segmentationRepresentationModifiedEventListener,
8
9
  segmentationDataModifiedEventListener,
9
10
  segmentationRepresentationRemovedEventListener,
10
11
  segmentationModifiedListener,
12
+ imageChangeEventListener,
11
13
  };
@@ -1,9 +1,19 @@
1
- import { cache } from '@cornerstonejs/core';
1
+ import {
2
+ cache,
3
+ getEnabledElementByIds,
4
+ utilities as csUtils,
5
+ } from '@cornerstonejs/core';
2
6
 
3
7
  import triggerSegmentationRender from '../../utilities/segmentation/triggerSegmentationRender';
4
8
  import SegmentationRepresentations from '../../enums/SegmentationRepresentations';
5
9
  import * as SegmentationState from '../../stateManagement/segmentation/segmentationState';
6
10
  import { SegmentationDataModifiedEventType } from '../../types/EventTypes';
11
+ import {
12
+ LabelmapSegmentationDataStack,
13
+ LabelmapSegmentationDataVolume,
14
+ } from '../../types/LabelmapTypes';
15
+ import { isVolumeSegmentation } from '../../tools/segmentation/strategies/utils/stackVolumeCheck';
16
+ import { getToolGroup } from '../../store/ToolGroupManager';
7
17
 
8
18
  /** A callback function that is called when the segmentation data is modified which
9
19
  * often is as a result of tool interactions e.g., scissors, eraser, etc.
@@ -16,11 +26,19 @@ const onSegmentationDataModified = function (
16
26
  const { representationData, type } =
17
27
  SegmentationState.getSegmentation(segmentationId);
18
28
 
19
- let toolGroupIds;
20
- if (type === SegmentationRepresentations.Labelmap) {
29
+ const toolGroupIds =
30
+ SegmentationState.getToolGroupIdsWithSegmentation(segmentationId);
31
+
32
+ if (type !== SegmentationRepresentations.Labelmap) {
33
+ throw new Error(
34
+ `onSegmentationDataModified: representationType ${type} not supported yet`
35
+ );
36
+ }
37
+
38
+ if (isVolumeSegmentation(representationData[type])) {
21
39
  // get the volume from cache, we need the openGLTexture to be updated to GPU
22
40
  const segmentationVolume = cache.getVolume(
23
- representationData[type].volumeId
41
+ (representationData[type] as LabelmapSegmentationDataVolume).volumeId
24
42
  );
25
43
 
26
44
  if (!segmentationVolume) {
@@ -45,12 +63,55 @@ const onSegmentationDataModified = function (
45
63
 
46
64
  // Trigger modified on the imageData to update the image
47
65
  imageData.modified();
48
- toolGroupIds =
49
- SegmentationState.getToolGroupIdsWithSegmentation(segmentationId);
50
66
  } else {
51
- throw new Error(
52
- `onSegmentationDataModified: representationType ${type} not supported yet`
53
- );
67
+ toolGroupIds.forEach((toolGroupId) => {
68
+ const toolGroupSegmentationRepresentations =
69
+ SegmentationState.getSegmentationRepresentations(toolGroupId);
70
+
71
+ const toolGroup = getToolGroup(toolGroupId);
72
+ const viewportsInfo = toolGroup.getViewportsInfo();
73
+
74
+ toolGroupSegmentationRepresentations.forEach((representation) => {
75
+ if (representation.segmentationId !== segmentationId) {
76
+ return;
77
+ }
78
+
79
+ viewportsInfo.forEach(({ viewportId, renderingEngineId }) => {
80
+ const viewport = getEnabledElementByIds(
81
+ viewportId,
82
+ renderingEngineId
83
+ ).viewport;
84
+
85
+ const actorEntry = viewport.getActor(
86
+ representation.segmentationRepresentationUID
87
+ );
88
+
89
+ if (!actorEntry) {
90
+ return;
91
+ }
92
+
93
+ const currentImageId = viewport.getCurrentImageId();
94
+
95
+ const segImageData = actorEntry.actor.getMapper().getInputData();
96
+
97
+ const { imageIdReferenceMap } = representationData[
98
+ type
99
+ ] as LabelmapSegmentationDataStack;
100
+
101
+ const currentSegmentationImageId =
102
+ imageIdReferenceMap.get(currentImageId);
103
+
104
+ const segmentationImage = cache.getImage(currentSegmentationImageId);
105
+ segImageData.modified();
106
+
107
+ // update the cache with the new image data
108
+ csUtils.updateVTKImageDataWithCornerstoneImage(
109
+ segImageData,
110
+ segmentationImage
111
+ );
112
+ });
113
+ });
114
+ });
54
115
  }
55
116
 
56
117
  toolGroupIds.forEach((toolGroupId) => {
@@ -4,6 +4,7 @@ import {
4
4
  wheelEventListener,
5
5
  touchEventListeners,
6
6
  keyEventListener,
7
+ imageChangeEventListener,
7
8
  } from '../eventListeners';
8
9
  import {
9
10
  imageRenderedEventDispatcher,
@@ -41,6 +42,7 @@ export default function addEnabledElement(
41
42
  wheelEventListener.enable(element);
42
43
  touchEventListeners.enable(element);
43
44
  keyEventListener.enable(element);
45
+ imageChangeEventListener.enable(element);
44
46
 
45
47
  // Dispatchers: renderer
46
48
  imageRenderedEventDispatcher.enable(element);
@@ -23,6 +23,7 @@ import { removeAnnotation } from '../stateManagement';
23
23
  import getSynchronizersForViewport from './SynchronizerManager/getSynchronizersForViewport';
24
24
  import getToolGroupForViewport from './ToolGroupManager/getToolGroupForViewport';
25
25
  import { annotationRenderingEngine } from '../utilities/triggerAnnotationRender';
26
+ import imageChangeEventListener from '../eventListeners/segmentation/imageChangeEventListener';
26
27
 
27
28
  const VIEWPORT_ELEMENT = 'viewport-element';
28
29
 
@@ -43,7 +44,9 @@ function removeEnabledElement(
43
44
  wheelEventListener.disable(element);
44
45
  touchEventListeners.disable(element);
45
46
  keyEventListener.disable(element);
47
+
46
48
  // labelmap
49
+ imageChangeEventListener.disable(element);
47
50
 
48
51
  // Dispatchers: renderer
49
52
  imageRenderedEventDispatcher.disable(element);
@@ -20,6 +20,7 @@ class StackScrollMouseWheelTool extends BaseTool {
20
20
  invert: false,
21
21
  debounceIfNotLoaded: true,
22
22
  loop: false,
23
+ scrollSlabs: false,
23
24
  },
24
25
  }
25
26
  ) {
@@ -41,6 +42,7 @@ class StackScrollMouseWheelTool extends BaseTool {
41
42
  debounceLoading: this.configuration.debounceIfNotLoaded,
42
43
  loop: this.configuration.loop,
43
44
  volumeId,
45
+ scrollSlabs: this.configuration.scrollSlabs,
44
46
  });
45
47
  }
46
48
  }
@@ -55,10 +55,7 @@ import {
55
55
  import triggerAnnotationRenderForViewportIds from '../../utilities/triggerAnnotationRenderForViewportIds';
56
56
  import { pointInShapeCallback } from '../../utilities';
57
57
  import { StyleSpecifier } from '../../types/AnnotationStyle';
58
- import {
59
- ModalityUnitOptions,
60
- getModalityUnit,
61
- } from '../../utilities/getModalityUnit';
58
+ import { getModalityUnit } from '../../utilities/getModalityUnit';
62
59
  import { isViewportPreScaled } from '../../utilities/viewport/isViewportPreScaled';
63
60
  import {
64
61
  getCanvasCircleCorners,
@@ -986,7 +983,10 @@ class CircleROITool extends AnnotationTool {
986
983
 
987
984
  const pointsInShape = pointInShapeCallback(
988
985
  imageData,
989
- (pointLPS, pointIJK) => pointInEllipse(ellipseObj, pointLPS),
986
+ (pointLPS) =>
987
+ pointInEllipse(ellipseObj, pointLPS, {
988
+ fast: true,
989
+ }),
990
990
  this.configuration.statsCalculator.statsCallback,
991
991
  boundsIJK
992
992
  );
@@ -1114,7 +1114,7 @@ class EllipticalROITool extends AnnotationTool {
1114
1114
 
1115
1115
  const pointsInShape = pointInShapeCallback(
1116
1116
  imageData,
1117
- (pointLPS, pointIJK) => pointInEllipse(ellipseObj, pointLPS),
1117
+ (pointLPS) => pointInEllipse(ellipseObj, pointLPS, { fast: true }),
1118
1118
  this.configuration.statsCalculator.statsCallback,
1119
1119
  boundsIJK
1120
1120
  );
@@ -1,10 +1,15 @@
1
1
  import {
2
2
  getEnabledElement,
3
3
  addVolumesToViewports,
4
+ addImageSlicesToViewports,
4
5
  Types,
5
6
  Enums,
6
7
  } from '@cornerstonejs/core';
7
-
8
+ import {
9
+ LabelmapSegmentationData,
10
+ LabelmapSegmentationDataStack,
11
+ } from '../../../types/LabelmapTypes';
12
+ import { isVolumeSegmentation } from '../../segmentation/strategies/utils/stackVolumeCheck';
8
13
  /**
9
14
  * It adds a labelmap segmentation representation of the viewport's HTML Element.
10
15
  * NOTE: This function should not be called directly.
@@ -17,7 +22,7 @@ import {
17
22
  */
18
23
  async function addLabelmapToElement(
19
24
  element: HTMLDivElement,
20
- volumeId: string,
25
+ labelMapData: LabelmapSegmentationData,
21
26
  segmentationRepresentationUID: string
22
27
  ): Promise<void> {
23
28
  const enabledElement = getEnabledElement(element);
@@ -31,27 +36,51 @@ async function addLabelmapToElement(
31
36
  const immediateRender = false;
32
37
  const suppressEvents = true;
33
38
 
34
- // Todo: Right now we use MIP blend mode for the labelmap, since the
35
- // composite blend mode has a non linear behavior regarding fill and line
36
- // opacity. This should be changed to a custom labelmap blendMode which does
37
- // what composite does, but with a linear behavior.
38
- const volumeInputs: Types.IVolumeInput[] = [
39
- {
40
- volumeId,
41
- actorUID: segmentationRepresentationUID,
42
- visibility,
43
- blendMode: Enums.BlendModes.MAXIMUM_INTENSITY_BLEND,
44
- },
45
- ];
39
+ if (isVolumeSegmentation(labelMapData)) {
40
+ // Todo: Right now we use MIP blend mode for the labelmap, since the
41
+ // composite blend mode has a non linear behavior regarding fill and line
42
+ // opacity. This should be changed to a custom labelmap blendMode which does
43
+ // what composite does, but with a linear behavior.
44
+ const volumeInputs: Types.IVolumeInput[] = [
45
+ {
46
+ volumeId: labelMapData.volumeId,
47
+ actorUID: segmentationRepresentationUID,
48
+ visibility,
49
+ blendMode: Enums.BlendModes.MAXIMUM_INTENSITY_BLEND,
50
+ },
51
+ ];
52
+
53
+ // Add labelmap volumes to the viewports to be be rendered, but not force the render
54
+ await addVolumesToViewports(
55
+ renderingEngine,
56
+ volumeInputs,
57
+ [viewportId],
58
+ immediateRender,
59
+ suppressEvents
60
+ );
61
+ } else {
62
+ // We can use the current imageId in the viewport to get the segmentation imageId
63
+ // which later is used to create the actor and mapper.
64
+ const segmentationImageId = (
65
+ labelMapData as LabelmapSegmentationDataStack
66
+ ).imageIdReferenceMap.get(viewport.getCurrentImageId());
67
+
68
+ const stackInputs: Types.IStackInput[] = [
69
+ {
70
+ imageId: segmentationImageId,
71
+ actorUID: segmentationRepresentationUID,
72
+ },
73
+ ];
46
74
 
47
- // Add labelmap volumes to the viewports to be be rendered, but not force the render
48
- await addVolumesToViewports(
49
- renderingEngine,
50
- volumeInputs,
51
- [viewportId],
52
- immediateRender,
53
- suppressEvents
54
- );
75
+ // Add labelmap volumes to the viewports to be be rendered, but not force the render
76
+ await addImageSlicesToViewports(
77
+ renderingEngine,
78
+ stackInputs,
79
+ [viewportId],
80
+ immediateRender,
81
+ suppressEvents
82
+ );
83
+ }
55
84
  }
56
85
 
57
86
  export default addLabelmapToElement;