@cornerstonejs/tools 1.42.1 → 1.43.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 (205) hide show
  1. package/dist/cjs/index.d.ts +2 -2
  2. package/dist/cjs/index.js +2 -1
  3. package/dist/cjs/index.js.map +1 -1
  4. package/dist/cjs/stateManagement/segmentation/activeSegmentation.d.ts +2 -1
  5. package/dist/cjs/stateManagement/segmentation/activeSegmentation.js +10 -1
  6. package/dist/cjs/stateManagement/segmentation/activeSegmentation.js.map +1 -1
  7. package/dist/cjs/stateManagement/segmentation/segmentIndex.js +5 -0
  8. package/dist/cjs/stateManagement/segmentation/segmentIndex.js.map +1 -1
  9. package/dist/cjs/tools/displayTools/Labelmap/labelmapConfig.js +2 -0
  10. package/dist/cjs/tools/displayTools/Labelmap/labelmapConfig.js.map +1 -1
  11. package/dist/cjs/tools/displayTools/Labelmap/labelmapDisplay.js +10 -4
  12. package/dist/cjs/tools/displayTools/Labelmap/labelmapDisplay.js.map +1 -1
  13. package/dist/cjs/tools/index.d.ts +2 -1
  14. package/dist/cjs/tools/index.js +3 -1
  15. package/dist/cjs/tools/index.js.map +1 -1
  16. package/dist/cjs/tools/segmentation/BrushTool.d.ts +1 -0
  17. package/dist/cjs/tools/segmentation/BrushTool.js +32 -15
  18. package/dist/cjs/tools/segmentation/BrushTool.js.map +1 -1
  19. package/dist/cjs/tools/segmentation/CircleScissorsTool.js +5 -0
  20. package/dist/cjs/tools/segmentation/CircleScissorsTool.js.map +1 -1
  21. package/dist/cjs/tools/segmentation/RectangleScissorsTool.js +5 -0
  22. package/dist/cjs/tools/segmentation/RectangleScissorsTool.js.map +1 -1
  23. package/dist/cjs/tools/segmentation/SegmentSelectTool.d.ts +15 -0
  24. package/dist/cjs/tools/segmentation/SegmentSelectTool.js +105 -0
  25. package/dist/cjs/tools/segmentation/SegmentSelectTool.js.map +1 -0
  26. package/dist/cjs/tools/segmentation/SphereScissorsTool.js +5 -0
  27. package/dist/cjs/tools/segmentation/SphereScissorsTool.js.map +1 -1
  28. package/dist/cjs/tools/segmentation/strategies/BrushStrategy.d.ts +2 -1
  29. package/dist/cjs/tools/segmentation/strategies/BrushStrategy.js.map +1 -1
  30. package/dist/cjs/tools/segmentation/strategies/fillCircle.js +8 -9
  31. package/dist/cjs/tools/segmentation/strategies/fillCircle.js.map +1 -1
  32. package/dist/cjs/tools/segmentation/strategies/fillRectangle.js +30 -3
  33. package/dist/cjs/tools/segmentation/strategies/fillRectangle.js.map +1 -1
  34. package/dist/cjs/tools/segmentation/strategies/fillSphere.js +3 -20
  35. package/dist/cjs/tools/segmentation/strategies/fillSphere.js.map +1 -1
  36. package/dist/cjs/types/LabelmapTypes.d.ts +1 -0
  37. package/dist/cjs/utilities/boundingBox/getBoundingBoxAroundShape.d.ts +4 -2
  38. package/dist/cjs/utilities/boundingBox/getBoundingBoxAroundShape.js +45 -23
  39. package/dist/cjs/utilities/boundingBox/getBoundingBoxAroundShape.js.map +1 -1
  40. package/dist/cjs/utilities/boundingBox/index.d.ts +2 -2
  41. package/dist/cjs/utilities/boundingBox/index.js +5 -3
  42. package/dist/cjs/utilities/boundingBox/index.js.map +1 -1
  43. package/dist/cjs/utilities/getSphereBoundsInfo.d.ts +11 -0
  44. package/dist/cjs/utilities/getSphereBoundsInfo.js +45 -0
  45. package/dist/cjs/utilities/getSphereBoundsInfo.js.map +1 -0
  46. package/dist/cjs/utilities/index.d.ts +2 -2
  47. package/dist/cjs/utilities/index.js +3 -3
  48. package/dist/cjs/utilities/index.js.map +1 -1
  49. package/dist/cjs/utilities/pointInShapeCallback.d.ts +1 -1
  50. package/dist/cjs/utilities/pointInShapeCallback.js +1 -1
  51. package/dist/cjs/utilities/pointInShapeCallback.js.map +1 -1
  52. package/dist/cjs/utilities/rectangleROITool/getBoundsIJKFromRectangleAnnotations.js +2 -2
  53. package/dist/cjs/utilities/rectangleROITool/getBoundsIJKFromRectangleAnnotations.js.map +1 -1
  54. package/dist/cjs/utilities/rectangleROITool/index.d.ts +2 -1
  55. package/dist/cjs/utilities/rectangleROITool/index.js +3 -1
  56. package/dist/cjs/utilities/rectangleROITool/index.js.map +1 -1
  57. package/dist/cjs/utilities/rectangleROITool/isAxisAlignedRectangle.d.ts +2 -0
  58. package/dist/cjs/utilities/rectangleROITool/isAxisAlignedRectangle.js +26 -0
  59. package/dist/cjs/utilities/rectangleROITool/isAxisAlignedRectangle.js.map +1 -0
  60. package/dist/cjs/utilities/segmentation/createLabelmapVolumeForViewport.js +1 -1
  61. package/dist/cjs/utilities/segmentation/createLabelmapVolumeForViewport.js.map +1 -1
  62. package/dist/cjs/utilities/segmentation/index.d.ts +2 -1
  63. package/dist/cjs/utilities/segmentation/index.js +3 -1
  64. package/dist/cjs/utilities/segmentation/index.js.map +1 -1
  65. package/dist/cjs/utilities/segmentation/invalidateBrushCursor.d.ts +1 -0
  66. package/dist/cjs/utilities/segmentation/invalidateBrushCursor.js +31 -0
  67. package/dist/cjs/utilities/segmentation/invalidateBrushCursor.js.map +1 -0
  68. package/dist/cjs/utilities/segmentation/utilities.d.ts +1 -1
  69. package/dist/cjs/utilities/segmentation/utilities.js +2 -2
  70. package/dist/cjs/utilities/segmentation/utilities.js.map +1 -1
  71. package/dist/esm/index.js +2 -2
  72. package/dist/esm/index.js.map +1 -1
  73. package/dist/esm/stateManagement/segmentation/activeSegmentation.js +10 -2
  74. package/dist/esm/stateManagement/segmentation/activeSegmentation.js.map +1 -1
  75. package/dist/esm/stateManagement/segmentation/segmentIndex.js +6 -1
  76. package/dist/esm/stateManagement/segmentation/segmentIndex.js.map +1 -1
  77. package/dist/esm/tools/displayTools/Labelmap/labelmapConfig.js +2 -0
  78. package/dist/esm/tools/displayTools/Labelmap/labelmapConfig.js.map +1 -1
  79. package/dist/esm/tools/displayTools/Labelmap/labelmapDisplay.js +11 -5
  80. package/dist/esm/tools/displayTools/Labelmap/labelmapDisplay.js.map +1 -1
  81. package/dist/esm/tools/index.js +2 -1
  82. package/dist/esm/tools/index.js.map +1 -1
  83. package/dist/esm/tools/segmentation/BrushTool.js +31 -15
  84. package/dist/esm/tools/segmentation/BrushTool.js.map +1 -1
  85. package/dist/esm/tools/segmentation/CircleScissorsTool.js +5 -0
  86. package/dist/esm/tools/segmentation/CircleScissorsTool.js.map +1 -1
  87. package/dist/esm/tools/segmentation/RectangleScissorsTool.js +5 -0
  88. package/dist/esm/tools/segmentation/RectangleScissorsTool.js.map +1 -1
  89. package/dist/esm/tools/segmentation/SegmentSelectTool.js +100 -0
  90. package/dist/esm/tools/segmentation/SegmentSelectTool.js.map +1 -0
  91. package/dist/esm/tools/segmentation/SphereScissorsTool.js +5 -0
  92. package/dist/esm/tools/segmentation/SphereScissorsTool.js.map +1 -1
  93. package/dist/esm/tools/segmentation/strategies/BrushStrategy.js.map +1 -1
  94. package/dist/esm/tools/segmentation/strategies/fillCircle.js +8 -9
  95. package/dist/esm/tools/segmentation/strategies/fillCircle.js.map +1 -1
  96. package/dist/esm/tools/segmentation/strategies/fillRectangle.js +32 -5
  97. package/dist/esm/tools/segmentation/strategies/fillRectangle.js.map +1 -1
  98. package/dist/esm/tools/segmentation/strategies/fillSphere.js +3 -20
  99. package/dist/esm/tools/segmentation/strategies/fillSphere.js.map +1 -1
  100. package/dist/esm/utilities/boundingBox/getBoundingBoxAroundShape.js +40 -23
  101. package/dist/esm/utilities/boundingBox/getBoundingBoxAroundShape.js.map +1 -1
  102. package/dist/esm/utilities/boundingBox/index.js +2 -2
  103. package/dist/esm/utilities/boundingBox/index.js.map +1 -1
  104. package/dist/esm/utilities/getSphereBoundsInfo.js +42 -0
  105. package/dist/esm/utilities/getSphereBoundsInfo.js.map +1 -0
  106. package/dist/esm/utilities/index.js +2 -2
  107. package/dist/esm/utilities/index.js.map +1 -1
  108. package/dist/esm/utilities/pointInShapeCallback.js +1 -1
  109. package/dist/esm/utilities/pointInShapeCallback.js.map +1 -1
  110. package/dist/esm/utilities/rectangleROITool/getBoundsIJKFromRectangleAnnotations.js +2 -2
  111. package/dist/esm/utilities/rectangleROITool/getBoundsIJKFromRectangleAnnotations.js.map +1 -1
  112. package/dist/esm/utilities/rectangleROITool/index.js +2 -1
  113. package/dist/esm/utilities/rectangleROITool/index.js.map +1 -1
  114. package/dist/esm/utilities/rectangleROITool/isAxisAlignedRectangle.js +23 -0
  115. package/dist/esm/utilities/rectangleROITool/isAxisAlignedRectangle.js.map +1 -0
  116. package/dist/esm/utilities/segmentation/createLabelmapVolumeForViewport.js +1 -1
  117. package/dist/esm/utilities/segmentation/createLabelmapVolumeForViewport.js.map +1 -1
  118. package/dist/esm/utilities/segmentation/index.js +2 -1
  119. package/dist/esm/utilities/segmentation/index.js.map +1 -1
  120. package/dist/esm/utilities/segmentation/invalidateBrushCursor.js +24 -0
  121. package/dist/esm/utilities/segmentation/invalidateBrushCursor.js.map +1 -0
  122. package/dist/esm/utilities/segmentation/utilities.js +2 -2
  123. package/dist/esm/utilities/segmentation/utilities.js.map +1 -1
  124. package/dist/types/index.d.ts +2 -2
  125. package/dist/types/index.d.ts.map +1 -1
  126. package/dist/types/stateManagement/segmentation/activeSegmentation.d.ts +2 -1
  127. package/dist/types/stateManagement/segmentation/activeSegmentation.d.ts.map +1 -1
  128. package/dist/types/stateManagement/segmentation/segmentIndex.d.ts.map +1 -1
  129. package/dist/types/tools/displayTools/Labelmap/labelmapConfig.d.ts.map +1 -1
  130. package/dist/types/tools/displayTools/Labelmap/labelmapDisplay.d.ts.map +1 -1
  131. package/dist/types/tools/index.d.ts +2 -1
  132. package/dist/types/tools/index.d.ts.map +1 -1
  133. package/dist/types/tools/segmentation/BrushTool.d.ts +1 -0
  134. package/dist/types/tools/segmentation/BrushTool.d.ts.map +1 -1
  135. package/dist/types/tools/segmentation/CircleScissorsTool.d.ts.map +1 -1
  136. package/dist/types/tools/segmentation/RectangleScissorsTool.d.ts.map +1 -1
  137. package/dist/types/tools/segmentation/SegmentSelectTool.d.ts +16 -0
  138. package/dist/types/tools/segmentation/SegmentSelectTool.d.ts.map +1 -0
  139. package/dist/types/tools/segmentation/SphereScissorsTool.d.ts.map +1 -1
  140. package/dist/types/tools/segmentation/strategies/BrushStrategy.d.ts +2 -1
  141. package/dist/types/tools/segmentation/strategies/BrushStrategy.d.ts.map +1 -1
  142. package/dist/types/tools/segmentation/strategies/fillCircle.d.ts.map +1 -1
  143. package/dist/types/tools/segmentation/strategies/fillRectangle.d.ts.map +1 -1
  144. package/dist/types/tools/segmentation/strategies/fillSphere.d.ts.map +1 -1
  145. package/dist/types/types/LabelmapTypes.d.ts +1 -0
  146. package/dist/types/types/LabelmapTypes.d.ts.map +1 -1
  147. package/dist/types/utilities/boundingBox/getBoundingBoxAroundShape.d.ts +4 -2
  148. package/dist/types/utilities/boundingBox/getBoundingBoxAroundShape.d.ts.map +1 -1
  149. package/dist/types/utilities/boundingBox/index.d.ts +2 -2
  150. package/dist/types/utilities/boundingBox/index.d.ts.map +1 -1
  151. package/dist/types/utilities/getSphereBoundsInfo.d.ts +12 -0
  152. package/dist/types/utilities/getSphereBoundsInfo.d.ts.map +1 -0
  153. package/dist/types/utilities/index.d.ts +2 -2
  154. package/dist/types/utilities/index.d.ts.map +1 -1
  155. package/dist/types/utilities/pointInShapeCallback.d.ts +1 -1
  156. package/dist/types/utilities/rectangleROITool/getBoundsIJKFromRectangleAnnotations.d.ts.map +1 -1
  157. package/dist/types/utilities/rectangleROITool/index.d.ts +2 -1
  158. package/dist/types/utilities/rectangleROITool/index.d.ts.map +1 -1
  159. package/dist/types/utilities/rectangleROITool/isAxisAlignedRectangle.d.ts +3 -0
  160. package/dist/types/utilities/rectangleROITool/isAxisAlignedRectangle.d.ts.map +1 -0
  161. package/dist/types/utilities/segmentation/index.d.ts +2 -1
  162. package/dist/types/utilities/segmentation/index.d.ts.map +1 -1
  163. package/dist/types/utilities/segmentation/invalidateBrushCursor.d.ts +2 -0
  164. package/dist/types/utilities/segmentation/invalidateBrushCursor.d.ts.map +1 -0
  165. package/dist/types/utilities/segmentation/utilities.d.ts +1 -1
  166. package/dist/types/utilities/segmentation/utilities.d.ts.map +1 -1
  167. package/dist/umd/index.js +1 -1
  168. package/dist/umd/index.js.map +1 -1
  169. package/package.json +4 -4
  170. package/src/index.ts +2 -0
  171. package/src/stateManagement/segmentation/activeSegmentation.ts +24 -1
  172. package/src/stateManagement/segmentation/segmentIndex.ts +15 -2
  173. package/src/tools/displayTools/Labelmap/labelmapConfig.ts +2 -0
  174. package/src/tools/displayTools/Labelmap/labelmapDisplay.ts +23 -12
  175. package/src/tools/index.ts +2 -0
  176. package/src/tools/segmentation/BrushTool.ts +53 -26
  177. package/src/tools/segmentation/CircleScissorsTool.ts +9 -0
  178. package/src/tools/segmentation/RectangleScissorsTool.ts +10 -1
  179. package/src/tools/segmentation/SegmentSelectTool.ts +182 -0
  180. package/src/tools/segmentation/SphereScissorsTool.ts +9 -0
  181. package/src/tools/segmentation/strategies/BrushStrategy.ts +2 -1
  182. package/src/tools/segmentation/strategies/fillCircle.ts +15 -14
  183. package/src/tools/segmentation/strategies/fillRectangle.ts +51 -6
  184. package/src/tools/segmentation/strategies/fillSphere.ts +10 -38
  185. package/src/types/LabelmapTypes.ts +5 -2
  186. package/src/utilities/boundingBox/getBoundingBoxAroundShape.ts +88 -37
  187. package/src/utilities/boundingBox/index.ts +11 -2
  188. package/src/utilities/{pointInSurroundingSphereCallback.ts → getSphereBoundsInfo.ts} +39 -82
  189. package/src/utilities/index.ts +2 -2
  190. package/src/utilities/math/ellipse/pointInEllipse.ts +1 -1
  191. package/src/utilities/pointInShapeCallback.ts +2 -2
  192. package/src/utilities/rectangleROITool/getBoundsIJKFromRectangleAnnotations.ts +5 -2
  193. package/src/utilities/rectangleROITool/index.ts +2 -1
  194. package/src/utilities/rectangleROITool/isAxisAlignedRectangle.ts +53 -0
  195. package/src/utilities/segmentation/createLabelmapVolumeForViewport.ts +1 -1
  196. package/src/utilities/segmentation/index.ts +2 -0
  197. package/src/utilities/segmentation/invalidateBrushCursor.ts +48 -0
  198. package/src/utilities/segmentation/utilities.ts +5 -2
  199. package/dist/cjs/utilities/pointInSurroundingSphereCallback.d.ts +0 -4
  200. package/dist/cjs/utilities/pointInSurroundingSphereCallback.js +0 -70
  201. package/dist/cjs/utilities/pointInSurroundingSphereCallback.js.map +0 -1
  202. package/dist/esm/utilities/pointInSurroundingSphereCallback.js +0 -64
  203. package/dist/esm/utilities/pointInSurroundingSphereCallback.js.map +0 -1
  204. package/dist/types/utilities/pointInSurroundingSphereCallback.d.ts +0 -5
  205. package/dist/types/utilities/pointInSurroundingSphereCallback.d.ts.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cornerstonejs/tools",
3
- "version": "1.42.1",
3
+ "version": "1.43.0",
4
4
  "description": "Cornerstone3D Tools",
5
5
  "main": "src/index.ts",
6
6
  "types": "dist/types/index.d.ts",
@@ -29,13 +29,13 @@
29
29
  "webpack:watch": "webpack --mode development --progress --watch --config ./.webpack/webpack.dev.js"
30
30
  },
31
31
  "dependencies": {
32
- "@cornerstonejs/core": "^1.42.1",
32
+ "@cornerstonejs/core": "^1.43.0",
33
33
  "comlink": "^4.4.1",
34
34
  "lodash.clonedeep": "4.5.0",
35
35
  "lodash.get": "^4.4.2"
36
36
  },
37
37
  "peerDependencies": {
38
- "@kitware/vtk.js": "27.3.1",
38
+ "@kitware/vtk.js": "29.3.0",
39
39
  "@types/d3-array": "^3.0.4",
40
40
  "@types/d3-interpolate": "^3.0.1",
41
41
  "d3-array": "^3.2.3",
@@ -53,5 +53,5 @@
53
53
  "type": "individual",
54
54
  "url": "https://ohif.org/donate"
55
55
  },
56
- "gitHead": "14a1bff3ba983b6664529e8e829a655cc4ffda89"
56
+ "gitHead": "1681f72fb2df75001f844a2e1728f2e9b79b6985"
57
57
  }
package/src/index.ts CHANGED
@@ -66,6 +66,7 @@ import {
66
66
  OrientationMarkerTool,
67
67
  OverlayGridTool,
68
68
  SegmentationIntersectionTool,
69
+ SegmentSelectTool,
69
70
  } from './tools';
70
71
 
71
72
  import VideoRedactionTool from './tools/annotation/VideoRedactionTool';
@@ -129,6 +130,7 @@ export {
129
130
  RectangleROIStartEndThresholdTool,
130
131
  BrushTool,
131
132
  OrientationMarkerTool,
133
+ SegmentSelectTool,
132
134
  // Synchronizers
133
135
  synchronizers,
134
136
  Synchronizer,
@@ -1,5 +1,8 @@
1
1
  import { ToolGroupSpecificRepresentation } from '../../types/SegmentationStateTypes';
2
- import { getDefaultSegmentationStateManager } from './segmentationState';
2
+ import {
3
+ getDefaultSegmentationStateManager,
4
+ getSegmentation,
5
+ } from './segmentationState';
3
6
  import { triggerSegmentationRepresentationModified } from './triggerSegmentationEvents';
4
7
 
5
8
  /**
@@ -27,6 +30,25 @@ function getActiveSegmentationRepresentation(
27
30
  return activeRepresentation;
28
31
  }
29
32
 
33
+ /**
34
+ * Retrieves the active segmentation for a given tool group.
35
+ * @param toolGroupId - The ID of the tool group.
36
+ * @returns The active segmentation Id, or undefined if no active segmentation is found.
37
+ */
38
+ function getActiveSegmentation(toolGroupId: string) {
39
+ const activeRepresentation = getActiveSegmentationRepresentation(toolGroupId);
40
+
41
+ if (!activeRepresentation) {
42
+ return;
43
+ }
44
+
45
+ const activeSegmentation = getSegmentation(
46
+ activeRepresentation.segmentationId
47
+ );
48
+
49
+ return activeSegmentation;
50
+ }
51
+
30
52
  /**
31
53
  * Set the active segmentation for the given tool group for all its viewports
32
54
  *
@@ -55,6 +77,7 @@ function setActiveSegmentationRepresentation(
55
77
  export {
56
78
  // get
57
79
  getActiveSegmentationRepresentation,
80
+ getActiveSegmentation,
58
81
  // set
59
82
  setActiveSegmentationRepresentation,
60
83
  };
@@ -1,9 +1,15 @@
1
- import { getSegmentation } from './segmentationState';
1
+ import { invalidateBrushCursor } from '../../utilities/segmentation/';
2
+ import {
3
+ getSegmentation,
4
+ getToolGroupIdsWithSegmentation,
5
+ } from './segmentationState';
2
6
  import { triggerSegmentationModified } from './triggerSegmentationEvents';
3
7
 
4
8
  /**
5
9
  * Set the active segment index for a segmentation Id. It fires a global state
6
- * modified event.
10
+ * modified event. Also it invalidates the brush cursor for all toolGroups that
11
+ * has the segmentationId as active segment (since the brush cursor color
12
+ * should change as well)
7
13
  *
8
14
  * @triggers SEGMENTATION_MODIFIED
9
15
  * @param segmentationId - The id of the segmentation that the segment belongs to.
@@ -20,6 +26,13 @@ function setActiveSegmentIndex(
20
26
 
21
27
  triggerSegmentationModified(segmentationId);
22
28
  }
29
+
30
+ // get all toolGroups that has the segmentationId as active
31
+ // segment and call invalidateBrushCursor on them
32
+ const toolGroups = getToolGroupIdsWithSegmentation(segmentationId);
33
+ toolGroups.forEach((toolGroupId) => {
34
+ invalidateBrushCursor(toolGroupId);
35
+ });
23
36
  }
24
37
 
25
38
  /**
@@ -4,6 +4,7 @@ const defaultLabelmapConfig: LabelmapConfig = {
4
4
  renderOutline: true,
5
5
  outlineWidthActive: 3,
6
6
  outlineWidthInactive: 2,
7
+ activeSegmentOutlineWidthDelta: 0,
7
8
  renderFill: true,
8
9
  renderFillInactive: true,
9
10
  fillAlpha: 0.7,
@@ -24,6 +25,7 @@ function isValidLabelmapConfig(config): boolean {
24
25
  typeof config.renderOutline === 'boolean' &&
25
26
  typeof config.outlineWidthActive === 'number' &&
26
27
  typeof config.outlineWidthInactive === 'number' &&
28
+ typeof config.activeSegmentOutlineWidthDelta === 'number' &&
27
29
  typeof config.renderFill === 'boolean' &&
28
30
  typeof config.renderFillInactive === 'boolean' &&
29
31
  typeof config.fillAlpha === 'number' &&
@@ -6,7 +6,6 @@ import {
6
6
  getEnabledElementByIds,
7
7
  StackViewport,
8
8
  Types,
9
- utilities,
10
9
  VolumeViewport,
11
10
  } from '@cornerstonejs/core';
12
11
 
@@ -302,27 +301,39 @@ function _setLabelmapColorAndOpacity(
302
301
  }
303
302
  }
304
303
 
305
- const actor = actorEntry.actor as Types.Actor;
304
+ const actor = actorEntry.actor as Types.VolumeActor;
306
305
 
307
- // @ts-ignore
308
306
  actor.getProperty().setRGBTransferFunction(0, cfun);
309
307
 
310
308
  ofun.setClamping(false);
311
309
 
312
- // @ts-ignore
313
310
  actor.getProperty().setScalarOpacity(0, ofun);
314
- // @ts-ignore
315
311
  actor.getProperty().setInterpolationTypeToNearest();
312
+ actor.getProperty().setUseLabelOutline(renderOutline);
316
313
 
317
- if (utilities.actorIsA(actorEntry, 'vtkVolume')) {
318
- // @ts-ignore
319
- actor.getProperty().setUseLabelOutline(renderOutline);
320
- // @ts-ignore
321
- actor.getProperty().setLabelOutlineOpacity(outlineOpacity);
322
- // @ts-ignore
323
- actor.getProperty().setLabelOutlineThickness(outlineWidth);
314
+ // @ts-ignore - fix type in vtk
315
+ actor.getProperty().setLabelOutlineOpacity(outlineOpacity);
316
+
317
+ const { activeSegmentIndex } = SegmentationState.getSegmentation(
318
+ segmentationRepresentation.segmentationId
319
+ );
320
+
321
+ // create an array that contains all the segment indices and for the active
322
+ // segment index, use the activeSegmentOutlineWidthDelta, otherwise use the
323
+ // outlineWidth
324
+ // Pre-allocate the array with the required size to avoid dynamic resizing.
325
+ const outlineWidths = new Array(numColors - 1);
326
+
327
+ for (let i = 1; i < numColors; i++) {
328
+ // Start from 1 to skip the background segment index.
329
+ outlineWidths[i - 1] =
330
+ i === activeSegmentIndex
331
+ ? outlineWidth + toolGroupLabelmapConfig.activeSegmentOutlineWidthDelta
332
+ : outlineWidth;
324
333
  }
325
334
 
335
+ actor.getProperty().setLabelOutlineThickness(outlineWidths);
336
+
326
337
  // Set visibility based on whether actor visibility is specifically asked
327
338
  // to be turned on/off (on by default) AND whether is is in active but
328
339
  // we are rendering inactive labelmap
@@ -47,6 +47,7 @@ import RectangleROIStartEndThresholdTool from './segmentation/RectangleROIStartE
47
47
  import BrushTool from './segmentation/BrushTool';
48
48
  import PaintFillTool from './segmentation/PaintFillTool';
49
49
  import OrientationMarkerTool from './OrientationMarkerTool';
50
+ import SegmentSelectTool from './segmentation/SegmentSelectTool';
50
51
 
51
52
  export {
52
53
  // ~~ BASE
@@ -99,4 +100,5 @@ export {
99
100
  PaintFillTool,
100
101
  ScaleOverlayTool,
101
102
  OrientationMarkerTool,
103
+ SegmentSelectTool,
102
104
  };
@@ -179,7 +179,7 @@ class BrushTool extends BaseTool {
179
179
  activeSegmentation.getActiveSegmentationRepresentation(toolGroupId);
180
180
  if (!activeSegmentationRepresentation) {
181
181
  throw new Error(
182
- 'No active segmentation detected, create one before using the brush tool'
182
+ 'No active segmentation detected, create a segmentation representation before using the brush tool'
183
183
  );
184
184
  }
185
185
 
@@ -271,9 +271,11 @@ class BrushTool extends BaseTool {
271
271
  this._previewData.isDrag = false;
272
272
  this._previewData.timerStart = Date.now();
273
273
 
274
+ const hoverData = this._hoverData || this.createHoverData(element);
275
+
274
276
  triggerAnnotationRenderForViewportUIDs(
275
277
  renderingEngine,
276
- this._hoverData.viewportIdsToRender
278
+ hoverData.viewportIdsToRender
277
279
  );
278
280
 
279
281
  this.applyActiveStrategyCallback(
@@ -362,6 +364,40 @@ class BrushTool extends BaseTool {
362
364
  const camera = viewport.getCamera();
363
365
  const { viewPlaneNormal, viewUp } = camera;
364
366
 
367
+ const viewportIdsToRender = [viewport.id];
368
+
369
+ const {
370
+ segmentIndex,
371
+ segmentationId,
372
+ segmentationRepresentationUID,
373
+ segmentColor,
374
+ } = this.getActiveSegmentationData() || {};
375
+
376
+ // Center of circle in canvas Coordinates
377
+ const brushCursor = {
378
+ metadata: {
379
+ viewPlaneNormal: <Types.Point3>[...viewPlaneNormal],
380
+ viewUp: <Types.Point3>[...viewUp],
381
+ FrameOfReferenceUID: viewport.getFrameOfReferenceUID(),
382
+ referencedImageId: '',
383
+ toolName: this.getToolName(),
384
+ segmentColor,
385
+ },
386
+ data: {},
387
+ };
388
+
389
+ return {
390
+ brushCursor,
391
+ centerCanvas,
392
+ segmentIndex,
393
+ segmentationId,
394
+ segmentationRepresentationUID,
395
+ segmentColor,
396
+ viewportIdsToRender,
397
+ };
398
+ }
399
+
400
+ private getActiveSegmentationData() {
365
401
  const toolGroupId = this.toolGroupId;
366
402
 
367
403
  const activeSegmentationRepresentation =
@@ -384,30 +420,11 @@ class BrushTool extends BaseTool {
384
420
  segmentIndex
385
421
  );
386
422
 
387
- const viewportIdsToRender = [viewport.id];
388
-
389
- // Center of circle in canvas Coordinates
390
-
391
- const brushCursor = {
392
- metadata: {
393
- viewPlaneNormal: <Types.Point3>[...viewPlaneNormal],
394
- viewUp: <Types.Point3>[...viewUp],
395
- FrameOfReferenceUID: viewport.getFrameOfReferenceUID(),
396
- referencedImageId: '',
397
- toolName: this.getToolName(),
398
- segmentColor,
399
- },
400
- data: {},
401
- };
402
-
403
423
  return {
404
- brushCursor,
405
- centerCanvas,
406
424
  segmentIndex,
407
425
  segmentationId,
408
426
  segmentationRepresentationUID,
409
427
  segmentColor,
410
- viewportIdsToRender,
411
428
  };
412
429
  }
413
430
 
@@ -678,11 +695,17 @@ class BrushTool extends BaseTool {
678
695
  };
679
696
 
680
697
  public invalidateBrushCursor() {
681
- if (this._hoverData !== undefined) {
682
- const { data } = this._hoverData.brushCursor;
683
-
684
- data.invalidated = true;
698
+ if (this._hoverData === undefined) {
699
+ return;
685
700
  }
701
+ const { data } = this._hoverData.brushCursor;
702
+
703
+ data.invalidated = true;
704
+
705
+ // Todo: figure out if other brush metadata (other than segment color) should get updated
706
+ // during the brush cursor invalidation
707
+ const { segmentColor } = this.getActiveSegmentationData() || {};
708
+ this._hoverData.brushCursor.metadata.segmentColor = segmentColor;
686
709
  }
687
710
 
688
711
  renderAnnotation(
@@ -713,6 +736,10 @@ class BrushTool extends BaseTool {
713
736
  }
714
737
 
715
738
  const toolMetadata = brushCursor.metadata;
739
+ if (!toolMetadata) {
740
+ return;
741
+ }
742
+
716
743
  const annotationUID = toolMetadata.brushCursorUID;
717
744
 
718
745
  const data = brushCursor.data;
@@ -729,7 +756,7 @@ class BrushTool extends BaseTool {
729
756
 
730
757
  const radius = Math.abs(bottom[1] - Math.floor((bottom[1] + top[1]) / 2));
731
758
 
732
- const color = `rgb(${toolMetadata.segmentColor.slice(0, 3)})`;
759
+ const color = `rgb(${toolMetadata.segmentColor?.slice(0, 3) || [0, 0, 0]})`;
733
760
 
734
761
  // If rendering engine has been destroyed while rendering
735
762
  if (!viewport.getRenderingEngine()) {
@@ -89,6 +89,13 @@ class CircleScissorsTool extends BaseTool {
89
89
  *
90
90
  */
91
91
  preMouseDownCallback = (evt: EventTypes.InteractionEventType): boolean => {
92
+ // if we are already drawing, means we have started with a click, and now we
93
+ // are moving the mouse (not dragging) so the final click should not
94
+ // be handled by this preMouseDownCallback but rather the endCallback
95
+ if (this.isDrawing === true) {
96
+ return;
97
+ }
98
+
92
99
  const eventDetail = evt.detail;
93
100
  const { currentPoints, element } = eventDetail;
94
101
  const worldPos = currentPoints.world;
@@ -292,6 +299,7 @@ class CircleScissorsTool extends BaseTool {
292
299
  element.addEventListener(Events.MOUSE_UP, this._endCallback);
293
300
  element.addEventListener(Events.MOUSE_DRAG, this._dragCallback);
294
301
  element.addEventListener(Events.MOUSE_CLICK, this._endCallback);
302
+ element.addEventListener(Events.MOUSE_MOVE, this._dragCallback);
295
303
 
296
304
  element.addEventListener(Events.TOUCH_TAP, this._endCallback);
297
305
  element.addEventListener(Events.TOUCH_DRAG, this._dragCallback);
@@ -305,6 +313,7 @@ class CircleScissorsTool extends BaseTool {
305
313
  element.removeEventListener(Events.MOUSE_UP, this._endCallback);
306
314
  element.removeEventListener(Events.MOUSE_DRAG, this._dragCallback);
307
315
  element.removeEventListener(Events.MOUSE_CLICK, this._endCallback);
316
+ element.removeEventListener(Events.MOUSE_MOVE, this._dragCallback);
308
317
 
309
318
  element.removeEventListener(Events.TOUCH_END, this._endCallback);
310
319
  element.removeEventListener(Events.TOUCH_DRAG, this._dragCallback);
@@ -91,6 +91,13 @@ class RectangleScissorsTool extends BaseTool {
91
91
  *
92
92
  */
93
93
  preMouseDownCallback = (evt: EventTypes.InteractionEventType): boolean => {
94
+ // if we are already drawing, means we have started with a click, and now we
95
+ // are moving the mouse (not dragging) so the final click should not
96
+ // be handled by this preMouseDownCallback but rather the endCallback
97
+ if (this.isDrawing === true) {
98
+ return;
99
+ }
100
+
94
101
  const eventDetail = evt.detail;
95
102
  const { currentPoints, element } = eventDetail;
96
103
  const worldPos = currentPoints.world;
@@ -315,6 +322,7 @@ class RectangleScissorsTool extends BaseTool {
315
322
  _activateDraw = (element) => {
316
323
  element.addEventListener(Events.MOUSE_UP, this._endCallback);
317
324
  element.addEventListener(Events.MOUSE_DRAG, this._dragCallback);
325
+ element.addEventListener(Events.MOUSE_MOVE, this._dragCallback);
318
326
  element.addEventListener(Events.MOUSE_CLICK, this._endCallback);
319
327
 
320
328
  element.addEventListener(Events.TOUCH_END, this._endCallback);
@@ -328,9 +336,10 @@ class RectangleScissorsTool extends BaseTool {
328
336
  _deactivateDraw = (element) => {
329
337
  element.removeEventListener(Events.MOUSE_UP, this._endCallback);
330
338
  element.removeEventListener(Events.MOUSE_DRAG, this._dragCallback);
339
+ element.removeEventListener(Events.MOUSE_MOVE, this._dragCallback);
331
340
  element.removeEventListener(Events.MOUSE_CLICK, this._endCallback);
332
- element.removeEventListener(Events.TOUCH_TAP, this._endCallback);
333
341
 
342
+ element.removeEventListener(Events.TOUCH_TAP, this._endCallback);
334
343
  element.removeEventListener(Events.TOUCH_END, this._endCallback);
335
344
  element.removeEventListener(Events.TOUCH_DRAG, this._dragCallback);
336
345
  };
@@ -0,0 +1,182 @@
1
+ import {
2
+ cache,
3
+ getEnabledElement,
4
+ utilities as csUtils,
5
+ } from '@cornerstonejs/core';
6
+ import type { Types } from '@cornerstonejs/core';
7
+
8
+ import { BaseTool } from '../base';
9
+ import {
10
+ PublicToolProps,
11
+ ToolProps,
12
+ EventTypes,
13
+ Segmentation,
14
+ } from '../../types';
15
+ import { triggerSegmentationModified } from '../../stateManagement/segmentation/triggerSegmentationEvents';
16
+ import triggerAnnotationRenderForViewportIds from '../../utilities/triggerAnnotationRenderForViewportIds';
17
+ import {
18
+ LabelmapSegmentationDataStack,
19
+ LabelmapSegmentationDataVolume,
20
+ } from '../../types/LabelmapTypes';
21
+ import { isVolumeSegmentation } from './strategies/utils/stackVolumeCheck';
22
+ import {
23
+ getActiveSegmentation,
24
+ getActiveSegmentationRepresentation,
25
+ } from '../../stateManagement/segmentation/activeSegmentation';
26
+ import RepresentationTypes from '../../enums/SegmentationRepresentations';
27
+ import { setActiveSegmentIndex } from '../../stateManagement/segmentation/segmentIndex';
28
+
29
+ /**
30
+ * Represents a tool used for segment selection. It is used to select a segment
31
+ * by hovering over it.
32
+ *
33
+ */
34
+ class SegmentSelectTool extends BaseTool {
35
+ static toolName;
36
+ private hoverTimer: ReturnType<typeof setTimeout> | null;
37
+
38
+ constructor(
39
+ toolProps: PublicToolProps = {},
40
+ defaultToolProps: ToolProps = {
41
+ supportedInteractionTypes: ['Mouse', 'Touch'],
42
+ configuration: {
43
+ hoverTimeout: 750,
44
+ },
45
+ }
46
+ ) {
47
+ super(toolProps, defaultToolProps);
48
+ this.hoverTimer = null;
49
+ }
50
+
51
+ mouseMoveCallback = (evt: EventTypes.InteractionEventType): boolean => {
52
+ if (this.hoverTimer) {
53
+ clearTimeout(this.hoverTimer);
54
+ }
55
+
56
+ this.hoverTimer = setTimeout(() => {
57
+ this._setActiveSegment(evt);
58
+ this.hoverTimer = null;
59
+ }, this.configuration.hoverTimeout);
60
+
61
+ return true;
62
+ };
63
+
64
+ onSetToolEnabled = (): void => {
65
+ this.onSetToolActive();
66
+ };
67
+
68
+ onSetToolActive = (): void => {
69
+ this.hoverTimer = null;
70
+ };
71
+
72
+ onSetToolDisabled = (): void => {
73
+ this.hoverTimer = null;
74
+ };
75
+
76
+ _setActiveSegment(evt = {} as EventTypes.InteractionEventType): void {
77
+ const { element, currentPoints } = evt.detail;
78
+
79
+ const worldPoint = currentPoints.world;
80
+
81
+ const enabledElement = getEnabledElement(element);
82
+
83
+ if (!enabledElement) {
84
+ return;
85
+ }
86
+
87
+ const { viewport } = enabledElement;
88
+
89
+ const activeSegmentation = getActiveSegmentation(this.toolGroupId);
90
+
91
+ if (activeSegmentation.type === RepresentationTypes.Labelmap) {
92
+ this._setActiveSegmentLabelmap(activeSegmentation, worldPoint, viewport);
93
+ } else {
94
+ throw Error('non-labelmap segmentation not supported yet');
95
+ }
96
+ }
97
+
98
+ _setActiveSegmentLabelmap(
99
+ activeSegmentation: Segmentation,
100
+ worldPoint: Types.Point3,
101
+ viewport: Types.IStackViewport | Types.IVolumeViewport
102
+ ): void {
103
+ const imageDataInfo = viewport.getImageData();
104
+
105
+ if (!imageDataInfo) {
106
+ return;
107
+ }
108
+
109
+ const labelmapData = activeSegmentation.representationData.LABELMAP;
110
+
111
+ let hoveredSegmentIndex;
112
+
113
+ if (isVolumeSegmentation(activeSegmentation.representationData.LABELMAP)) {
114
+ const { volumeId } = labelmapData as LabelmapSegmentationDataVolume;
115
+
116
+ const segmentationVolume = cache.getVolume(volumeId);
117
+
118
+ if (!segmentationVolume) {
119
+ return;
120
+ }
121
+
122
+ hoveredSegmentIndex =
123
+ segmentationVolume.imageData.getScalarValueFromWorld(worldPoint);
124
+ } else {
125
+ const { imageIdReferenceMap } =
126
+ labelmapData as LabelmapSegmentationDataStack;
127
+
128
+ const currentImageId = viewport.getCurrentImageId();
129
+ const segmentationImageId = imageIdReferenceMap.get(currentImageId);
130
+
131
+ const image = cache.getImage(segmentationImageId);
132
+
133
+ if (!image) {
134
+ return;
135
+ }
136
+
137
+ const activeSegmentationRepresentation =
138
+ getActiveSegmentationRepresentation(this.toolGroupId);
139
+
140
+ if (!activeSegmentationRepresentation) {
141
+ return;
142
+ }
143
+
144
+ const segmentationActor = viewport.getActor(
145
+ activeSegmentationRepresentation.segmentationRepresentationUID
146
+ );
147
+
148
+ const imageData = segmentationActor?.actor.getMapper().getInputData();
149
+
150
+ const indexIJK = csUtils.transformWorldToIndex(imageData, worldPoint);
151
+
152
+ // since it is a stack we don't need to check the z
153
+ const flattenedIndex = indexIJK[0] + indexIJK[1] * image.columns;
154
+
155
+ const scalars = imageData.getPointData().getScalars().getData();
156
+
157
+ hoveredSegmentIndex = scalars[flattenedIndex];
158
+ }
159
+
160
+ // No need to select background
161
+ if (!hoveredSegmentIndex || hoveredSegmentIndex === 0) {
162
+ return;
163
+ }
164
+
165
+ setActiveSegmentIndex(
166
+ activeSegmentation.segmentationId,
167
+ hoveredSegmentIndex
168
+ );
169
+
170
+ const renderingEngine = viewport.getRenderingEngine();
171
+
172
+ // update states
173
+ triggerSegmentationModified(activeSegmentation.segmentationId);
174
+ triggerAnnotationRenderForViewportIds(
175
+ renderingEngine,
176
+ renderingEngine.getViewports().map((v) => v.id)
177
+ );
178
+ }
179
+ }
180
+
181
+ SegmentSelectTool.toolName = 'SegmentSelectTool';
182
+ export default SegmentSelectTool;
@@ -91,6 +91,13 @@ class SphereScissorsTool extends BaseTool {
91
91
  *
92
92
  */
93
93
  preMouseDownCallback = (evt: EventTypes.InteractionEventType): true => {
94
+ // if we are already drawing, means we have started with a click, and now we
95
+ // are moving the mouse (not dragging) so the final click should not
96
+ // be handled by this preMouseDownCallback but rather the endCallback
97
+ if (this.isDrawing === true) {
98
+ return;
99
+ }
100
+
94
101
  const eventDetail = evt.detail;
95
102
  const { currentPoints, element } = eventDetail;
96
103
  const worldPos = currentPoints.world;
@@ -296,6 +303,7 @@ class SphereScissorsTool extends BaseTool {
296
303
  element.addEventListener(Events.MOUSE_UP, this._endCallback);
297
304
  element.addEventListener(Events.MOUSE_DRAG, this._dragCallback);
298
305
  element.addEventListener(Events.MOUSE_CLICK, this._endCallback);
306
+ element.addEventListener(Events.MOUSE_MOVE, this._dragCallback);
299
307
 
300
308
  element.addEventListener(Events.TOUCH_END, this._endCallback);
301
309
  element.addEventListener(Events.TOUCH_TAP, this._endCallback);
@@ -309,6 +317,7 @@ class SphereScissorsTool extends BaseTool {
309
317
  element.removeEventListener(Events.MOUSE_UP, this._endCallback);
310
318
  element.removeEventListener(Events.MOUSE_DRAG, this._dragCallback);
311
319
  element.removeEventListener(Events.MOUSE_CLICK, this._endCallback);
320
+ element.removeEventListener(Events.MOUSE_MOVE, this._dragCallback);
312
321
 
313
322
  element.removeEventListener(Events.TOUCH_END, this._endCallback);
314
323
  element.removeEventListener(Events.TOUCH_DRAG, this._dragCallback);
@@ -10,6 +10,7 @@ import type {
10
10
  LabelmapToolOperationDataAny,
11
11
  LabelmapToolOperationDataVolume,
12
12
  } from '../../../types/LabelmapToolOperationData';
13
+ import vtkImageData from '@kitware/vtk.js/Common/DataModel/ImageData';
13
14
 
14
15
  const { VoxelManager } = csUtils;
15
16
 
@@ -21,7 +22,7 @@ export type InitializedOperationData = LabelmapToolOperationDataAny & {
21
22
  viewport: Types.IViewport;
22
23
  imageVoxelManager: csUtils.VoxelManager<number>;
23
24
  segmentationVoxelManager: csUtils.VoxelManager<number>;
24
- segmentationImageData: ImageData;
25
+ segmentationImageData: vtkImageData;
25
26
  previewVoxelManager: csUtils.VoxelManager<number>;
26
27
  // The index to use for the preview segment. Currently always undefined or 255
27
28
  // but define it here for future expansion of LUT tables