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