@cornerstonejs/tools 1.36.2 → 1.37.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 (283) hide show
  1. package/dist/cjs/drawingSvg/drawEllipse.js +1 -1
  2. package/dist/cjs/drawingSvg/drawEllipse.js.map +1 -1
  3. package/dist/cjs/drawingSvg/drawEllipseByCoordinates.js +2 -3
  4. package/dist/cjs/drawingSvg/drawEllipseByCoordinates.js.map +1 -1
  5. package/dist/cjs/enums/StrategyCallbacks.d.ts +13 -0
  6. package/dist/cjs/enums/StrategyCallbacks.js +17 -0
  7. package/dist/cjs/enums/StrategyCallbacks.js.map +1 -0
  8. package/dist/cjs/enums/index.d.ts +2 -1
  9. package/dist/cjs/enums/index.js +3 -1
  10. package/dist/cjs/enums/index.js.map +1 -1
  11. package/dist/cjs/eventDispatchers/keyboardEventHandlers/keyDown.js +17 -7
  12. package/dist/cjs/eventDispatchers/keyboardEventHandlers/keyDown.js.map +1 -1
  13. package/dist/cjs/eventDispatchers/shared/getActiveToolForKeyboardEvent.js +4 -1
  14. package/dist/cjs/eventDispatchers/shared/getActiveToolForKeyboardEvent.js.map +1 -1
  15. package/dist/cjs/eventDispatchers/shared/getToolsWithActionsForKeyboardEvents.d.ts +3 -0
  16. package/dist/cjs/eventDispatchers/shared/getToolsWithActionsForKeyboardEvents.js +33 -0
  17. package/dist/cjs/eventDispatchers/shared/getToolsWithActionsForKeyboardEvents.js.map +1 -0
  18. package/dist/cjs/eventDispatchers/shared/getToolsWithActionsForMouseEvent.js.map +1 -1
  19. package/dist/cjs/stateManagement/segmentation/config/segmentationColor.js +8 -1
  20. package/dist/cjs/stateManagement/segmentation/config/segmentationColor.js.map +1 -1
  21. package/dist/cjs/tools/annotation/EllipticalROITool.js +1 -2
  22. package/dist/cjs/tools/annotation/EllipticalROITool.js.map +1 -1
  23. package/dist/cjs/tools/base/AnnotationTool.js.map +1 -1
  24. package/dist/cjs/tools/base/BaseTool.d.ts +2 -0
  25. package/dist/cjs/tools/base/BaseTool.js +7 -1
  26. package/dist/cjs/tools/base/BaseTool.js.map +1 -1
  27. package/dist/cjs/tools/segmentation/BrushTool.d.ts +45 -3
  28. package/dist/cjs/tools/segmentation/BrushTool.js +197 -71
  29. package/dist/cjs/tools/segmentation/BrushTool.js.map +1 -1
  30. package/dist/cjs/tools/segmentation/CircleScissorsTool.js +3 -1
  31. package/dist/cjs/tools/segmentation/CircleScissorsTool.js.map +1 -1
  32. package/dist/cjs/tools/segmentation/SphereScissorsTool.js +3 -0
  33. package/dist/cjs/tools/segmentation/SphereScissorsTool.js.map +1 -1
  34. package/dist/cjs/tools/segmentation/strategies/BrushStrategy.d.ts +87 -0
  35. package/dist/cjs/tools/segmentation/strategies/BrushStrategy.js +137 -0
  36. package/dist/cjs/tools/segmentation/strategies/BrushStrategy.js.map +1 -0
  37. package/dist/cjs/tools/segmentation/strategies/compositions/determineSegmentIndex.d.ts +6 -0
  38. package/dist/cjs/tools/segmentation/strategies/compositions/determineSegmentIndex.js +53 -0
  39. package/dist/cjs/tools/segmentation/strategies/compositions/determineSegmentIndex.js.map +1 -0
  40. package/dist/cjs/tools/segmentation/strategies/compositions/dynamicThreshold.d.ts +6 -0
  41. package/dist/cjs/tools/segmentation/strategies/compositions/dynamicThreshold.js +41 -0
  42. package/dist/cjs/tools/segmentation/strategies/compositions/dynamicThreshold.js.map +1 -0
  43. package/dist/cjs/tools/segmentation/strategies/compositions/erase.d.ts +5 -0
  44. package/dist/cjs/tools/segmentation/strategies/compositions/erase.js +12 -0
  45. package/dist/cjs/tools/segmentation/strategies/compositions/erase.js.map +1 -0
  46. package/dist/cjs/tools/segmentation/strategies/compositions/index.d.ts +35 -0
  47. package/dist/cjs/tools/segmentation/strategies/compositions/index.js +24 -0
  48. package/dist/cjs/tools/segmentation/strategies/compositions/index.js.map +1 -0
  49. package/dist/cjs/tools/segmentation/strategies/compositions/islandRemoval.d.ts +5 -0
  50. package/dist/cjs/tools/segmentation/strategies/compositions/islandRemoval.js +129 -0
  51. package/dist/cjs/tools/segmentation/strategies/compositions/islandRemoval.js.map +1 -0
  52. package/dist/cjs/tools/segmentation/strategies/compositions/preview.d.ts +8 -0
  53. package/dist/cjs/tools/segmentation/strategies/compositions/preview.js +84 -0
  54. package/dist/cjs/tools/segmentation/strategies/compositions/preview.js.map +1 -0
  55. package/dist/cjs/tools/segmentation/strategies/compositions/regionFill.d.ts +5 -0
  56. package/dist/cjs/tools/segmentation/strategies/compositions/regionFill.js +27 -0
  57. package/dist/cjs/tools/segmentation/strategies/compositions/regionFill.js.map +1 -0
  58. package/dist/cjs/tools/segmentation/strategies/compositions/setValue.d.ts +8 -0
  59. package/dist/cjs/tools/segmentation/strategies/compositions/setValue.js +33 -0
  60. package/dist/cjs/tools/segmentation/strategies/compositions/setValue.js.map +1 -0
  61. package/dist/cjs/tools/segmentation/strategies/compositions/threshold.d.ts +5 -0
  62. package/dist/cjs/tools/segmentation/strategies/compositions/threshold.js +24 -0
  63. package/dist/cjs/tools/segmentation/strategies/compositions/threshold.js.map +1 -0
  64. package/dist/cjs/tools/segmentation/strategies/eraseCircle.d.ts +2 -7
  65. package/dist/cjs/tools/segmentation/strategies/eraseCircle.js +7 -4
  66. package/dist/cjs/tools/segmentation/strategies/eraseCircle.js.map +1 -1
  67. package/dist/cjs/tools/segmentation/strategies/eraseSphere.d.ts +2 -7
  68. package/dist/cjs/tools/segmentation/strategies/eraseSphere.js +7 -6
  69. package/dist/cjs/tools/segmentation/strategies/eraseSphere.js.map +1 -1
  70. package/dist/cjs/tools/segmentation/strategies/fillCircle.d.ts +13 -8
  71. package/dist/cjs/tools/segmentation/strategies/fillCircle.js +68 -90
  72. package/dist/cjs/tools/segmentation/strategies/fillCircle.js.map +1 -1
  73. package/dist/cjs/tools/segmentation/strategies/fillRectangle.js +3 -9
  74. package/dist/cjs/tools/segmentation/strategies/fillRectangle.js.map +1 -1
  75. package/dist/cjs/tools/segmentation/strategies/fillSphere.d.ts +6 -9
  76. package/dist/cjs/tools/segmentation/strategies/fillSphere.js +53 -64
  77. package/dist/cjs/tools/segmentation/strategies/fillSphere.js.map +1 -1
  78. package/dist/cjs/tools/segmentation/strategies/utils/getStrategyData.d.ts +3 -0
  79. package/dist/cjs/tools/segmentation/strategies/utils/getStrategyData.js +6 -0
  80. package/dist/cjs/tools/segmentation/strategies/utils/getStrategyData.js.map +1 -1
  81. package/dist/cjs/tools/segmentation/strategies/utils/isWithinThreshold.d.ts +2 -2
  82. package/dist/cjs/tools/segmentation/strategies/utils/isWithinThreshold.js +2 -2
  83. package/dist/cjs/tools/segmentation/strategies/utils/isWithinThreshold.js.map +1 -1
  84. package/dist/cjs/types/BoundsIJK.d.ts +1 -1
  85. package/dist/cjs/types/FloodFillTypes.d.ts +4 -4
  86. package/dist/cjs/types/LabelmapToolOperationData.d.ts +7 -2
  87. package/dist/cjs/types/index.d.ts +2 -1
  88. package/dist/cjs/utilities/math/ellipse/getCanvasEllipseCorners.d.ts +2 -3
  89. package/dist/cjs/utilities/math/ellipse/index.d.ts +2 -2
  90. package/dist/cjs/utilities/math/ellipse/index.js +26 -2
  91. package/dist/cjs/utilities/math/ellipse/index.js.map +1 -1
  92. package/dist/cjs/utilities/math/ellipse/pointInEllipse.d.ts +4 -1
  93. package/dist/cjs/utilities/math/ellipse/pointInEllipse.js +30 -17
  94. package/dist/cjs/utilities/math/ellipse/pointInEllipse.js.map +1 -1
  95. package/dist/cjs/utilities/math/sphere/pointInSphere.d.ts +1 -0
  96. package/dist/cjs/utilities/math/sphere/pointInSphere.js +2 -1
  97. package/dist/cjs/utilities/math/sphere/pointInSphere.js.map +1 -1
  98. package/dist/cjs/utilities/segmentation/brushThresholdForToolGroup.d.ts +1 -1
  99. package/dist/cjs/utilities/segmentation/brushThresholdForToolGroup.js +5 -5
  100. package/dist/cjs/utilities/segmentation/brushThresholdForToolGroup.js.map +1 -1
  101. package/dist/esm/drawingSvg/drawEllipse.js +1 -1
  102. package/dist/esm/drawingSvg/drawEllipse.js.map +1 -1
  103. package/dist/esm/drawingSvg/drawEllipseByCoordinates.js +2 -3
  104. package/dist/esm/drawingSvg/drawEllipseByCoordinates.js.map +1 -1
  105. package/dist/esm/enums/StrategyCallbacks.js +15 -0
  106. package/dist/esm/enums/StrategyCallbacks.js.map +1 -0
  107. package/dist/esm/enums/index.js +2 -1
  108. package/dist/esm/enums/index.js.map +1 -1
  109. package/dist/esm/eventDispatchers/keyboardEventHandlers/keyDown.js +17 -7
  110. package/dist/esm/eventDispatchers/keyboardEventHandlers/keyDown.js.map +1 -1
  111. package/dist/esm/eventDispatchers/shared/getActiveToolForKeyboardEvent.js +4 -1
  112. package/dist/esm/eventDispatchers/shared/getActiveToolForKeyboardEvent.js.map +1 -1
  113. package/dist/esm/eventDispatchers/shared/getToolsWithActionsForKeyboardEvents.js +29 -0
  114. package/dist/esm/eventDispatchers/shared/getToolsWithActionsForKeyboardEvents.js.map +1 -0
  115. package/dist/esm/eventDispatchers/shared/getToolsWithActionsForMouseEvent.js.map +1 -1
  116. package/dist/esm/stateManagement/segmentation/config/segmentationColor.js +8 -1
  117. package/dist/esm/stateManagement/segmentation/config/segmentationColor.js.map +1 -1
  118. package/dist/esm/tools/annotation/EllipticalROITool.js +1 -2
  119. package/dist/esm/tools/annotation/EllipticalROITool.js.map +1 -1
  120. package/dist/esm/tools/base/AnnotationTool.js.map +1 -1
  121. package/dist/esm/tools/base/BaseTool.js +5 -1
  122. package/dist/esm/tools/base/BaseTool.js.map +1 -1
  123. package/dist/esm/tools/segmentation/BrushTool.js +208 -87
  124. package/dist/esm/tools/segmentation/BrushTool.js.map +1 -1
  125. package/dist/esm/tools/segmentation/CircleScissorsTool.js +3 -0
  126. package/dist/esm/tools/segmentation/CircleScissorsTool.js.map +1 -1
  127. package/dist/esm/tools/segmentation/SphereScissorsTool.js +3 -0
  128. package/dist/esm/tools/segmentation/SphereScissorsTool.js.map +1 -1
  129. package/dist/esm/tools/segmentation/strategies/BrushStrategy.js +136 -0
  130. package/dist/esm/tools/segmentation/strategies/BrushStrategy.js.map +1 -0
  131. package/dist/esm/tools/segmentation/strategies/compositions/determineSegmentIndex.js +48 -0
  132. package/dist/esm/tools/segmentation/strategies/compositions/determineSegmentIndex.js.map +1 -0
  133. package/dist/esm/tools/segmentation/strategies/compositions/dynamicThreshold.js +35 -0
  134. package/dist/esm/tools/segmentation/strategies/compositions/dynamicThreshold.js.map +1 -0
  135. package/dist/esm/tools/segmentation/strategies/compositions/erase.js +7 -0
  136. package/dist/esm/tools/segmentation/strategies/compositions/erase.js.map +1 -0
  137. package/dist/esm/tools/segmentation/strategies/compositions/index.js +19 -0
  138. package/dist/esm/tools/segmentation/strategies/compositions/index.js.map +1 -0
  139. package/dist/esm/tools/segmentation/strategies/compositions/islandRemoval.js +124 -0
  140. package/dist/esm/tools/segmentation/strategies/compositions/islandRemoval.js.map +1 -0
  141. package/dist/esm/tools/segmentation/strategies/compositions/preview.js +77 -0
  142. package/dist/esm/tools/segmentation/strategies/compositions/preview.js.map +1 -0
  143. package/dist/esm/tools/segmentation/strategies/compositions/regionFill.js +21 -0
  144. package/dist/esm/tools/segmentation/strategies/compositions/regionFill.js.map +1 -0
  145. package/dist/esm/tools/segmentation/strategies/compositions/setValue.js +28 -0
  146. package/dist/esm/tools/segmentation/strategies/compositions/setValue.js.map +1 -0
  147. package/dist/esm/tools/segmentation/strategies/compositions/threshold.js +19 -0
  148. package/dist/esm/tools/segmentation/strategies/compositions/threshold.js.map +1 -0
  149. package/dist/esm/tools/segmentation/strategies/eraseCircle.js +6 -8
  150. package/dist/esm/tools/segmentation/strategies/eraseCircle.js.map +1 -1
  151. package/dist/esm/tools/segmentation/strategies/eraseSphere.js +6 -7
  152. package/dist/esm/tools/segmentation/strategies/eraseSphere.js.map +1 -1
  153. package/dist/esm/tools/segmentation/strategies/fillCircle.js +64 -88
  154. package/dist/esm/tools/segmentation/strategies/fillCircle.js.map +1 -1
  155. package/dist/esm/tools/segmentation/strategies/fillRectangle.js +3 -9
  156. package/dist/esm/tools/segmentation/strategies/fillRectangle.js.map +1 -1
  157. package/dist/esm/tools/segmentation/strategies/fillSphere.js +53 -64
  158. package/dist/esm/tools/segmentation/strategies/fillSphere.js.map +1 -1
  159. package/dist/esm/tools/segmentation/strategies/utils/getStrategyData.js +7 -1
  160. package/dist/esm/tools/segmentation/strategies/utils/getStrategyData.js.map +1 -1
  161. package/dist/esm/tools/segmentation/strategies/utils/isWithinThreshold.js +2 -2
  162. package/dist/esm/tools/segmentation/strategies/utils/isWithinThreshold.js.map +1 -1
  163. package/dist/esm/utilities/math/ellipse/index.js +2 -2
  164. package/dist/esm/utilities/math/ellipse/index.js.map +1 -1
  165. package/dist/esm/utilities/math/ellipse/pointInEllipse.js +28 -16
  166. package/dist/esm/utilities/math/ellipse/pointInEllipse.js.map +1 -1
  167. package/dist/esm/utilities/math/sphere/pointInSphere.js +2 -1
  168. package/dist/esm/utilities/math/sphere/pointInSphere.js.map +1 -1
  169. package/dist/esm/utilities/segmentation/brushThresholdForToolGroup.js +11 -5
  170. package/dist/esm/utilities/segmentation/brushThresholdForToolGroup.js.map +1 -1
  171. package/dist/types/drawingSvg/drawEllipseByCoordinates.d.ts.map +1 -1
  172. package/dist/types/enums/StrategyCallbacks.d.ts +14 -0
  173. package/dist/types/enums/StrategyCallbacks.d.ts.map +1 -0
  174. package/dist/types/enums/index.d.ts +2 -1
  175. package/dist/types/eventDispatchers/keyboardEventHandlers/keyDown.d.ts.map +1 -1
  176. package/dist/types/eventDispatchers/shared/getActiveToolForKeyboardEvent.d.ts.map +1 -1
  177. package/dist/types/eventDispatchers/shared/getToolsWithActionsForKeyboardEvents.d.ts +4 -0
  178. package/dist/types/eventDispatchers/shared/getToolsWithActionsForKeyboardEvents.d.ts.map +1 -0
  179. package/dist/types/eventDispatchers/shared/getToolsWithActionsForMouseEvent.d.ts.map +1 -1
  180. package/dist/types/stateManagement/segmentation/config/segmentationColor.d.ts.map +1 -1
  181. package/dist/types/tools/annotation/EllipticalROITool.d.ts.map +1 -1
  182. package/dist/types/tools/base/AnnotationTool.d.ts.map +1 -1
  183. package/dist/types/tools/base/BaseTool.d.ts +2 -0
  184. package/dist/types/tools/base/BaseTool.d.ts.map +1 -1
  185. package/dist/types/tools/segmentation/BrushTool.d.ts +45 -3
  186. package/dist/types/tools/segmentation/BrushTool.d.ts.map +1 -1
  187. package/dist/types/tools/segmentation/CircleScissorsTool.d.ts.map +1 -1
  188. package/dist/types/tools/segmentation/SphereScissorsTool.d.ts.map +1 -1
  189. package/dist/types/tools/segmentation/strategies/BrushStrategy.d.ts +88 -0
  190. package/dist/types/tools/segmentation/strategies/BrushStrategy.d.ts.map +1 -0
  191. package/dist/types/tools/segmentation/strategies/compositions/determineSegmentIndex.d.ts +7 -0
  192. package/dist/types/tools/segmentation/strategies/compositions/determineSegmentIndex.d.ts.map +1 -0
  193. package/dist/types/tools/segmentation/strategies/compositions/dynamicThreshold.d.ts +7 -0
  194. package/dist/types/tools/segmentation/strategies/compositions/dynamicThreshold.d.ts.map +1 -0
  195. package/dist/types/tools/segmentation/strategies/compositions/erase.d.ts +6 -0
  196. package/dist/types/tools/segmentation/strategies/compositions/erase.d.ts.map +1 -0
  197. package/dist/types/tools/segmentation/strategies/compositions/index.d.ts +36 -0
  198. package/dist/types/tools/segmentation/strategies/compositions/index.d.ts.map +1 -0
  199. package/dist/types/tools/segmentation/strategies/compositions/islandRemoval.d.ts +6 -0
  200. package/dist/types/tools/segmentation/strategies/compositions/islandRemoval.d.ts.map +1 -0
  201. package/dist/types/tools/segmentation/strategies/compositions/preview.d.ts +9 -0
  202. package/dist/types/tools/segmentation/strategies/compositions/preview.d.ts.map +1 -0
  203. package/dist/types/tools/segmentation/strategies/compositions/regionFill.d.ts +6 -0
  204. package/dist/types/tools/segmentation/strategies/compositions/regionFill.d.ts.map +1 -0
  205. package/dist/types/tools/segmentation/strategies/compositions/setValue.d.ts +9 -0
  206. package/dist/types/tools/segmentation/strategies/compositions/setValue.d.ts.map +1 -0
  207. package/dist/types/tools/segmentation/strategies/compositions/threshold.d.ts +6 -0
  208. package/dist/types/tools/segmentation/strategies/compositions/threshold.d.ts.map +1 -0
  209. package/dist/types/tools/segmentation/strategies/eraseCircle.d.ts +2 -7
  210. package/dist/types/tools/segmentation/strategies/eraseCircle.d.ts.map +1 -1
  211. package/dist/types/tools/segmentation/strategies/eraseSphere.d.ts +2 -7
  212. package/dist/types/tools/segmentation/strategies/eraseSphere.d.ts.map +1 -1
  213. package/dist/types/tools/segmentation/strategies/fillCircle.d.ts +13 -8
  214. package/dist/types/tools/segmentation/strategies/fillCircle.d.ts.map +1 -1
  215. package/dist/types/tools/segmentation/strategies/fillRectangle.d.ts.map +1 -1
  216. package/dist/types/tools/segmentation/strategies/fillSphere.d.ts +6 -9
  217. package/dist/types/tools/segmentation/strategies/fillSphere.d.ts.map +1 -1
  218. package/dist/types/tools/segmentation/strategies/utils/getStrategyData.d.ts +3 -0
  219. package/dist/types/tools/segmentation/strategies/utils/getStrategyData.d.ts.map +1 -1
  220. package/dist/types/tools/segmentation/strategies/utils/isWithinThreshold.d.ts +2 -2
  221. package/dist/types/tools/segmentation/strategies/utils/isWithinThreshold.d.ts.map +1 -1
  222. package/dist/types/types/BoundsIJK.d.ts +1 -1
  223. package/dist/types/types/BoundsIJK.d.ts.map +1 -1
  224. package/dist/types/types/FloodFillTypes.d.ts +4 -4
  225. package/dist/types/types/FloodFillTypes.d.ts.map +1 -1
  226. package/dist/types/types/LabelmapToolOperationData.d.ts +7 -2
  227. package/dist/types/types/LabelmapToolOperationData.d.ts.map +1 -1
  228. package/dist/types/types/index.d.ts +2 -1
  229. package/dist/types/types/index.d.ts.map +1 -1
  230. package/dist/types/utilities/math/ellipse/getCanvasEllipseCorners.d.ts +2 -3
  231. package/dist/types/utilities/math/ellipse/getCanvasEllipseCorners.d.ts.map +1 -1
  232. package/dist/types/utilities/math/ellipse/index.d.ts +2 -2
  233. package/dist/types/utilities/math/ellipse/index.d.ts.map +1 -1
  234. package/dist/types/utilities/math/ellipse/pointInEllipse.d.ts +4 -1
  235. package/dist/types/utilities/math/ellipse/pointInEllipse.d.ts.map +1 -1
  236. package/dist/types/utilities/math/sphere/pointInSphere.d.ts +1 -0
  237. package/dist/types/utilities/math/sphere/pointInSphere.d.ts.map +1 -1
  238. package/dist/types/utilities/segmentation/brushThresholdForToolGroup.d.ts +1 -1
  239. package/dist/types/utilities/segmentation/brushThresholdForToolGroup.d.ts.map +1 -1
  240. package/dist/umd/index.js +1 -1
  241. package/dist/umd/index.js.map +1 -1
  242. package/package.json +3 -3
  243. package/src/drawingSvg/drawEllipse.ts +8 -8
  244. package/src/drawingSvg/drawEllipseByCoordinates.ts +4 -4
  245. package/src/enums/StrategyCallbacks.ts +52 -0
  246. package/src/enums/index.js +2 -0
  247. package/src/eventDispatchers/keyboardEventHandlers/keyDown.ts +22 -11
  248. package/src/eventDispatchers/shared/getActiveToolForKeyboardEvent.ts +6 -2
  249. package/src/eventDispatchers/shared/getToolsWithActionsForKeyboardEvents.ts +53 -0
  250. package/src/eventDispatchers/shared/getToolsWithActionsForMouseEvent.ts +0 -2
  251. package/src/stateManagement/segmentation/config/segmentationColor.ts +8 -1
  252. package/src/tools/annotation/EllipticalROITool.ts +1 -3
  253. package/src/tools/base/AnnotationTool.ts +0 -1
  254. package/src/tools/base/BaseTool.ts +32 -2
  255. package/src/tools/segmentation/BrushTool.ts +298 -68
  256. package/src/tools/segmentation/CircleScissorsTool.ts +3 -1
  257. package/src/tools/segmentation/SphereScissorsTool.ts +3 -0
  258. package/src/tools/segmentation/strategies/BrushStrategy.ts +364 -0
  259. package/src/tools/segmentation/strategies/compositions/determineSegmentIndex.ts +86 -0
  260. package/src/tools/segmentation/strategies/compositions/dynamicThreshold.ts +58 -0
  261. package/src/tools/segmentation/strategies/compositions/erase.ts +11 -0
  262. package/src/tools/segmentation/strategies/compositions/index.ts +19 -0
  263. package/src/tools/segmentation/strategies/compositions/islandRemoval.ts +179 -0
  264. package/src/tools/segmentation/strategies/compositions/preview.ts +138 -0
  265. package/src/tools/segmentation/strategies/compositions/regionFill.ts +45 -0
  266. package/src/tools/segmentation/strategies/compositions/setValue.ts +50 -0
  267. package/src/tools/segmentation/strategies/compositions/threshold.ts +35 -0
  268. package/src/tools/segmentation/strategies/eraseCircle.ts +10 -19
  269. package/src/tools/segmentation/strategies/eraseSphere.ts +10 -18
  270. package/src/tools/segmentation/strategies/fillCircle.ts +141 -164
  271. package/src/tools/segmentation/strategies/fillRectangle.ts +3 -13
  272. package/src/tools/segmentation/strategies/fillSphere.ts +105 -120
  273. package/src/tools/segmentation/strategies/utils/getStrategyData.ts +15 -1
  274. package/src/tools/segmentation/strategies/utils/isWithinThreshold.ts +5 -5
  275. package/src/types/BoundsIJK.ts +1 -1
  276. package/src/types/FloodFillTypes.ts +4 -4
  277. package/src/types/LabelmapToolOperationData.ts +20 -1
  278. package/src/types/index.ts +2 -0
  279. package/src/utilities/math/ellipse/getCanvasEllipseCorners.ts +2 -2
  280. package/src/utilities/math/ellipse/index.ts +2 -2
  281. package/src/utilities/math/ellipse/pointInEllipse.ts +52 -18
  282. package/src/utilities/math/sphere/pointInSphere.ts +10 -2
  283. package/src/utilities/segmentation/brushThresholdForToolGroup.ts +12 -5
@@ -0,0 +1,364 @@
1
+ import type { Types } from '@cornerstonejs/core';
2
+ import { cache, utilities as csUtils } from '@cornerstonejs/core';
3
+
4
+ import { triggerSegmentationDataModified } from '../../../stateManagement/segmentation/triggerSegmentationEvents';
5
+ import compositions from './compositions';
6
+ import { getStrategyData } from './utils/getStrategyData';
7
+ import { isVolumeSegmentation } from './utils/stackVolumeCheck';
8
+ import { StrategyCallbacks } from '../../../enums';
9
+ import type {
10
+ LabelmapToolOperationDataAny,
11
+ LabelmapToolOperationDataVolume,
12
+ } from '../../../types/LabelmapToolOperationData';
13
+
14
+ const { VoxelManager } = csUtils;
15
+
16
+ export type InitializedOperationData = LabelmapToolOperationDataAny & {
17
+ // Additional data for performing the strategy
18
+ enabledElement: Types.IEnabledElement;
19
+ centerIJK?: Types.Point3;
20
+ centerWorld: Types.Point3;
21
+ viewport: Types.IViewport;
22
+ imageVoxelManager: csUtils.VoxelManager<number>;
23
+ segmentationVoxelManager: csUtils.VoxelManager<number>;
24
+ segmentationImageData: ImageData;
25
+ previewVoxelManager: csUtils.VoxelManager<number>;
26
+ // The index to use for the preview segment. Currently always undefined or 255
27
+ // but define it here for future expansion of LUT tables
28
+ previewSegmentIndex?: number;
29
+
30
+ brushStrategy: BrushStrategy;
31
+ };
32
+
33
+ export type StrategyFunction = (
34
+ operationData: InitializedOperationData,
35
+ ...args
36
+ ) => unknown;
37
+
38
+ export type CompositionInstance = {
39
+ [callback in StrategyCallbacks]?: StrategyFunction;
40
+ };
41
+
42
+ export type CompositionFunction = () => CompositionInstance;
43
+
44
+ export type Composition = CompositionFunction | CompositionInstance;
45
+
46
+ /**
47
+ * A brush strategy is a composition of individual parts which together form
48
+ * the strategy for a brush tool.
49
+ *
50
+ * Parts of a strategy:
51
+ * 1. Fill strategy - how the fill gets done (left/right, 3d, paint fill etc)
52
+ * 2. Set value strategy - can clear values or set them, or something else?
53
+ * 3. In object strategy - how to tell if a point is contained in the object
54
+ * * Bounding box getter for the object strategy
55
+ * 4. threshold - how to determine if a point is within a threshold value
56
+ * 5. preview - how to display preview information
57
+ * 6. Various strategy customizations such as erase
58
+ *
59
+ * These combine to form an actual brush:
60
+ *
61
+ * Circle - convexFill, defaultSetValue, inEllipse/boundingbox ellipse, empty threshold
62
+ * Rectangle - - convexFill, defaultSetValue, inRectangle/boundingbox rectangle, empty threshold
63
+ * might also get parameter values from input, init for setup of convexFill
64
+ *
65
+ * The pieces are combined to generate a strategyFunction, which performs
66
+ * the actual strategy operation, as well as various callbacks for the strategy
67
+ * to allow more control over behaviour in the specific strategy (such as displaying
68
+ * preview)
69
+ */
70
+
71
+ export default class BrushStrategy {
72
+ /**
73
+ * Provide some default initializers for various situations, mostly for
74
+ * external use to allow defining new brushes
75
+ */
76
+ public static COMPOSITIONS = compositions;
77
+
78
+ protected static childFunctions = {
79
+ [StrategyCallbacks.OnInteractionStart]: addListMethod(
80
+ StrategyCallbacks.OnInteractionStart,
81
+ StrategyCallbacks.Initialize
82
+ ),
83
+ [StrategyCallbacks.OnInteractionEnd]: addListMethod(
84
+ StrategyCallbacks.OnInteractionEnd,
85
+ StrategyCallbacks.Initialize
86
+ ),
87
+ [StrategyCallbacks.Fill]: addListMethod(StrategyCallbacks.Fill),
88
+ [StrategyCallbacks.Initialize]: addListMethod(StrategyCallbacks.Initialize),
89
+ [StrategyCallbacks.CreateIsInThreshold]: addSingletonMethod(
90
+ StrategyCallbacks.CreateIsInThreshold
91
+ ),
92
+ [StrategyCallbacks.AcceptPreview]: addListMethod(
93
+ StrategyCallbacks.AcceptPreview,
94
+ StrategyCallbacks.Initialize
95
+ ),
96
+ [StrategyCallbacks.RejectPreview]: addListMethod(
97
+ StrategyCallbacks.RejectPreview,
98
+ StrategyCallbacks.Initialize
99
+ ),
100
+ [StrategyCallbacks.INTERNAL_setValue]: addSingletonMethod(
101
+ StrategyCallbacks.INTERNAL_setValue
102
+ ),
103
+ [StrategyCallbacks.Preview]: addSingletonMethod(
104
+ StrategyCallbacks.Preview,
105
+ false
106
+ ),
107
+ // Add other exposed fields below
108
+ // initializers is exposed on the function to allow extension of the composition object
109
+ compositions: null,
110
+ };
111
+
112
+ public compositions: Composition[];
113
+ public strategyFunction: (enabledElement, operationData) => unknown;
114
+
115
+ protected configurationName: string;
116
+ protected _initialize = [];
117
+ protected _fill = [];
118
+ protected _acceptPreview: [];
119
+ protected _onInteractionStart = [];
120
+
121
+ constructor(name, ...initializers: Composition[]) {
122
+ this.configurationName = name;
123
+ this.compositions = initializers;
124
+ initializers.forEach((initializer) => {
125
+ const result =
126
+ typeof initializer === 'function' ? initializer() : initializer;
127
+ if (!result) {
128
+ return;
129
+ }
130
+ for (const key in result) {
131
+ if (!BrushStrategy.childFunctions[key]) {
132
+ throw new Error(`Didn't find ${key} as a brush strategy`);
133
+ }
134
+ BrushStrategy.childFunctions[key](this, result[key]);
135
+ }
136
+ });
137
+ this.strategyFunction = (enabledElement, operationData) =>
138
+ this.fill(enabledElement, operationData);
139
+
140
+ for (const key of Object.keys(BrushStrategy.childFunctions)) {
141
+ this.strategyFunction[key] = this[key];
142
+ }
143
+ }
144
+
145
+ /**
146
+ * Performs a fill of the given region.
147
+ * Returns the preview data if the fill performs a preview, and otherwise
148
+ * returns null.
149
+ */
150
+ public fill = (
151
+ enabledElement: Types.IEnabledElement,
152
+ operationData: LabelmapToolOperationDataAny
153
+ ) => {
154
+ const initializedData = this.initialize(enabledElement, operationData);
155
+
156
+ const { strategySpecificConfiguration = {}, centerIJK } = initializedData;
157
+ // Store the center IJK location so that we can skip an immediate same-point update
158
+ // TODO - move this to the BrushTool
159
+ if (csUtils.isEqual(centerIJK, strategySpecificConfiguration.centerIJK)) {
160
+ return operationData.preview;
161
+ } else {
162
+ strategySpecificConfiguration.centerIJK = centerIJK;
163
+ }
164
+
165
+ this._fill.forEach((func) => func(initializedData));
166
+
167
+ const {
168
+ segmentationVoxelManager,
169
+ previewVoxelManager,
170
+ previewSegmentIndex,
171
+ } = initializedData;
172
+
173
+ triggerSegmentationDataModified(
174
+ initializedData.segmentationId,
175
+ segmentationVoxelManager.getArrayOfSlices()
176
+ );
177
+ // We are only previewing if there is a preview index, and there is at
178
+ // least one slice modified
179
+ if (!previewSegmentIndex || !previewVoxelManager.modifiedSlices.size) {
180
+ return null;
181
+ }
182
+ // Use the original initialized data set to preserve preview info
183
+ return initializedData.preview || initializedData;
184
+ };
185
+
186
+ protected initialize(
187
+ enabledElement: Types.IEnabledElement,
188
+ operationData: LabelmapToolOperationDataAny
189
+ ): InitializedOperationData {
190
+ const { viewport } = enabledElement;
191
+ const data = getStrategyData({ operationData, viewport });
192
+
193
+ if (!data) {
194
+ console.warn('No data found for BrushStrategy');
195
+ return operationData.preview;
196
+ }
197
+
198
+ if (isVolumeSegmentation(operationData)) {
199
+ const { referencedVolumeId, volumeId } =
200
+ operationData as LabelmapToolOperationDataVolume;
201
+
202
+ const imageVolume = cache.getVolume(referencedVolumeId);
203
+ const segmentation = cache.getVolume(volumeId);
204
+
205
+ if (
206
+ !csUtils.isEqual(segmentation.dimensions, imageVolume.dimensions) ||
207
+ !csUtils.isEqual(segmentation.direction, imageVolume.direction)
208
+ ) {
209
+ throw new Error(
210
+ 'Only source data the same dimensions/size/orientation as the segmentation currently supported.'
211
+ );
212
+ }
213
+ }
214
+
215
+ const {
216
+ imageVoxelManager,
217
+ segmentationVoxelManager,
218
+ segmentationImageData,
219
+ } = data;
220
+ const previewVoxelManager =
221
+ operationData.preview?.previewVoxelManager ||
222
+ VoxelManager.createHistoryVoxelManager(segmentationVoxelManager);
223
+ const previewEnabled = !!operationData.previewColors;
224
+ const previewSegmentIndex = previewEnabled ? 255 : undefined;
225
+
226
+ const initializedData: InitializedOperationData = {
227
+ previewSegmentIndex,
228
+ ...operationData,
229
+ enabledElement,
230
+ imageVoxelManager,
231
+ segmentationVoxelManager,
232
+ segmentationImageData,
233
+ previewVoxelManager,
234
+ viewport,
235
+
236
+ centerWorld: null,
237
+ brushStrategy: this,
238
+ };
239
+
240
+ this._initialize.forEach((func) => func(initializedData));
241
+
242
+ return initializedData;
243
+ }
244
+
245
+ /**
246
+ * Function called to initialize the start of the strategy. Often this is
247
+ * on mouse down, so calling this initDown.
248
+ * Over-written by the strategy composition.
249
+ */
250
+ public onInteractionStart = (
251
+ enabledElement: Types.IEnabledElement,
252
+ operationData: LabelmapToolOperationDataAny
253
+ ) => {
254
+ const { preview } = operationData;
255
+ // Need to skip the init down if it has already occurred in teh preview
256
+ // That prevents resetting values which were used to determine the preview
257
+ if (preview?.isPreviewFromHover) {
258
+ preview.isPreviewFromHover = false;
259
+ return;
260
+ }
261
+ const initializedData = this.initialize(enabledElement, operationData);
262
+ this._onInteractionStart.forEach((func) =>
263
+ func.call(this, initializedData)
264
+ );
265
+ };
266
+
267
+ /**
268
+ * Function called when a strategy is complete in some way.
269
+ * Often called on mouse up, hence the name.
270
+ *
271
+ * Over-written by the strategy composition.
272
+ */
273
+ public onInteractionEnd: (
274
+ enabledElement: Types.IEnabledElement,
275
+ operationData: LabelmapToolOperationDataAny
276
+ ) => void;
277
+
278
+ /**
279
+ * Reject the preview.
280
+ * Over-written by the strategy composition.
281
+ */
282
+ public rejectPreview: (
283
+ enabledElement: Types.IEnabledElement,
284
+ operationData: LabelmapToolOperationDataAny
285
+ ) => void;
286
+
287
+ /**
288
+ * Accept the preview, making it part of the overall segmentation
289
+ *
290
+ * Over-written by the strategy composition.
291
+ */
292
+ public acceptPreview: (
293
+ enabledElement: Types.IEnabledElement,
294
+ operationData: LabelmapToolOperationDataAny
295
+ ) => void;
296
+
297
+ /**
298
+ * Display a preview at the current position. This will typically
299
+ * using the onInteractionStart, fill and onInteractionEnd methods,
300
+ * plus optional use of a preview.
301
+ *
302
+ * Over-written by the strategy composition.
303
+ * @returns preview data if a preview is displayed.
304
+ */
305
+ public preview: (
306
+ enabledElement: Types.IEnabledElement,
307
+ operationData: LabelmapToolOperationDataAny
308
+ ) => unknown;
309
+
310
+ /**
311
+ * Over-written by the strategy composition.
312
+ */
313
+ public setValue: (operationData: InitializedOperationData, data) => void;
314
+
315
+ /**
316
+ * Over-written by the strategy composition.
317
+ */
318
+ public createIsInThreshold: (operationData: InitializedOperationData) => any;
319
+ }
320
+
321
+ /**
322
+ * Adds a list method to the set of defined methods.
323
+ */
324
+ function addListMethod(name: string, createInitialized?: string) {
325
+ const listName = `_${name}`;
326
+ return (brushStrategy, func) => {
327
+ brushStrategy[listName] ||= [];
328
+ brushStrategy[listName].push(func);
329
+ brushStrategy[name] ||= createInitialized
330
+ ? (enabledElement, operationData) => {
331
+ const initializedData = brushStrategy[createInitialized](
332
+ enabledElement,
333
+ operationData
334
+ );
335
+ brushStrategy[listName].forEach((func) =>
336
+ func.call(brushStrategy, initializedData)
337
+ );
338
+ }
339
+ : (operationData) => {
340
+ brushStrategy[listName].forEach((func) =>
341
+ func.call(brushStrategy, operationData)
342
+ );
343
+ };
344
+ };
345
+ }
346
+
347
+ /**
348
+ * Adds a singleton method, throwing an exception if it is already defined
349
+ */
350
+ function addSingletonMethod(name: string, isInitialized = true) {
351
+ return (brushStrategy, func) => {
352
+ if (brushStrategy[name]) {
353
+ throw new Error(`The singleton method ${name} already exists`);
354
+ }
355
+ brushStrategy[name] = isInitialized
356
+ ? func
357
+ : (enabledElement, operationData) => {
358
+ // Store the enabled element in the operation data so we can use single
359
+ // argument calls
360
+ operationData.enabledElement = enabledElement;
361
+ return func.call(brushStrategy, operationData);
362
+ };
363
+ };
364
+ }
@@ -0,0 +1,86 @@
1
+ import type { InitializedOperationData } from '../BrushStrategy';
2
+ import pointInShapeCallback from '../../../../utilities/pointInShapeCallback';
3
+ import StrategyCallbacks from '../../../../enums/StrategyCallbacks';
4
+
5
+ /**
6
+ * This function determines whether to fill or erase based on what the user
7
+ * initially clicks on. The behaviour is:
8
+ * 1. If the user clicks on an area that has no active segment index in it,
9
+ * then assume the user using the active segment index for filling
10
+ * 2. Find the segment index of the pixel the user clicked on, and assume they
11
+ * want to fill with that segment index. Use the given segment index for
12
+ * the fill colour.
13
+ * a. If the user clicks on the active segment index, then they will fill
14
+ * with the active segment
15
+ * b. If the user clicks on the 0 segment index, they will clear the segment
16
+ * index, erasing the segment.
17
+ * c. If the user clicks on another segment index, they will "restore" that
18
+ * segment index, so that they can push back the segment area.
19
+ *
20
+ */
21
+ export default {
22
+ [StrategyCallbacks.Initialize]: (operationData: InitializedOperationData) => {
23
+ const { strategySpecificConfiguration } = operationData;
24
+ if (!strategySpecificConfiguration) {
25
+ return;
26
+ }
27
+ const { centerSegmentIndex } = strategySpecificConfiguration;
28
+ if (centerSegmentIndex) {
29
+ operationData.segmentIndex = centerSegmentIndex.segmentIndex;
30
+ }
31
+ },
32
+
33
+ [StrategyCallbacks.OnInteractionStart]: (
34
+ operationData: InitializedOperationData
35
+ ) => {
36
+ const {
37
+ segmentIndex,
38
+ previewSegmentIndex,
39
+ segmentationVoxelManager: segmentationVoxelManager,
40
+ centerIJK,
41
+ strategySpecificConfiguration,
42
+ imageVoxelManager: imageVoxelManager,
43
+ segmentationImageData,
44
+ preview,
45
+ } = operationData;
46
+ if (!strategySpecificConfiguration?.useCenterSegmentIndex) {
47
+ return;
48
+ }
49
+ // Get rid of the previous data
50
+ delete strategySpecificConfiguration.centerSegmentIndex;
51
+
52
+ let hasSegmentIndex = false;
53
+ let hasPreviewIndex = false;
54
+ const callback = ({ value }) => {
55
+ hasSegmentIndex ||= value === segmentIndex;
56
+ hasPreviewIndex ||= value === previewSegmentIndex;
57
+ };
58
+
59
+ pointInShapeCallback(
60
+ segmentationImageData as unknown,
61
+ imageVoxelManager.isInObject,
62
+ callback,
63
+ segmentationVoxelManager.boundsIJK
64
+ );
65
+
66
+ if (!hasSegmentIndex && !hasPreviewIndex) {
67
+ return;
68
+ }
69
+
70
+ let existingValue = segmentationVoxelManager.getAtIJKPoint(centerIJK);
71
+ if (existingValue === previewSegmentIndex) {
72
+ if (preview) {
73
+ existingValue = preview.segmentIndex;
74
+ } else {
75
+ return;
76
+ }
77
+ } else if (hasPreviewIndex) {
78
+ // Clear the preview area
79
+ existingValue = null;
80
+ }
81
+ operationData.segmentIndex = existingValue;
82
+ strategySpecificConfiguration.centerSegmentIndex = {
83
+ segmentIndex: existingValue,
84
+ };
85
+ },
86
+ };
@@ -0,0 +1,58 @@
1
+ import type { InitializedOperationData } from '../BrushStrategy';
2
+ import type BoundsIJK from '../../../../types/BoundsIJK';
3
+ import StrategyCallbacks from '../../../../enums/StrategyCallbacks';
4
+
5
+ /**
6
+ * Initializes the threshold values for the dynamic threshold.
7
+ * If the threshold is undefined/null, the threshold will be set
8
+ * by looking at the area centered on the centerIJK, with a delta radius,
9
+ * and taking the range of those pixel values.
10
+ * If the threshold is already set, then the range will be extended by just the
11
+ * center voxel at centerIJK.
12
+ */
13
+ export default {
14
+ [StrategyCallbacks.Initialize]: (operationData: InitializedOperationData) => {
15
+ const {
16
+ centerIJK,
17
+ strategySpecificConfiguration,
18
+ segmentationVoxelManager: segmentationVoxelManager,
19
+ imageVoxelManager: imageVoxelManager,
20
+ segmentIndex,
21
+ } = operationData;
22
+ const { THRESHOLD } = strategySpecificConfiguration;
23
+
24
+ if (!THRESHOLD?.isDynamic || !centerIJK || !segmentIndex) {
25
+ return;
26
+ }
27
+
28
+ const { boundsIJK } = segmentationVoxelManager;
29
+ const { threshold: oldThreshold, dynamicRadius = 0 } = THRESHOLD;
30
+ const useDelta = oldThreshold ? 0 : dynamicRadius;
31
+ const nestedBounds = boundsIJK.map((ijk, idx) => {
32
+ const [min, max] = ijk;
33
+ return [
34
+ Math.max(min, centerIJK[idx] - useDelta),
35
+ Math.min(max, centerIJK[idx] + useDelta),
36
+ ];
37
+ }) as BoundsIJK;
38
+
39
+ const threshold = oldThreshold || [Infinity, -Infinity];
40
+ const callback = ({ value }) => {
41
+ threshold[0] = Math.min(value, threshold[0]);
42
+ threshold[1] = Math.max(value, threshold[1]);
43
+ };
44
+ imageVoxelManager.forEach(callback, { boundsIJK: nestedBounds });
45
+
46
+ operationData.strategySpecificConfiguration.THRESHOLD.threshold = threshold;
47
+ },
48
+ // Setup a clear threshold value on mouse/touch down
49
+ [StrategyCallbacks.OnInteractionStart]: (
50
+ operationData: InitializedOperationData
51
+ ) => {
52
+ const { strategySpecificConfiguration, preview } = operationData;
53
+ if (!strategySpecificConfiguration?.THRESHOLD?.isDynamic && !preview) {
54
+ return;
55
+ }
56
+ strategySpecificConfiguration.THRESHOLD.threshold = null;
57
+ },
58
+ };
@@ -0,0 +1,11 @@
1
+ import type { InitializedOperationData } from '../BrushStrategy';
2
+ import StrategyCallbacks from '../../../../enums/StrategyCallbacks';
3
+
4
+ /**
5
+ * Sets up a preview to erase/clear the segment values.
6
+ */
7
+ export default {
8
+ [StrategyCallbacks.Initialize]: (operationData: InitializedOperationData) => {
9
+ operationData.segmentIndex = 0;
10
+ },
11
+ };
@@ -0,0 +1,19 @@
1
+ import determineSegmentIndex from './determineSegmentIndex';
2
+ import dynamicThreshold from './dynamicThreshold';
3
+ import erase from './erase';
4
+ import islandRemoval from './islandRemoval';
5
+ import preview from './preview';
6
+ import regionFill from './regionFill';
7
+ import setValue from './setValue';
8
+ import threshold from './threshold';
9
+
10
+ export default {
11
+ determineSegmentIndex,
12
+ dynamicThreshold,
13
+ erase,
14
+ islandRemoval,
15
+ preview,
16
+ regionFill,
17
+ setValue,
18
+ threshold,
19
+ };