@cornerstonejs/tools 4.22.13 → 5.0.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 (225) hide show
  1. package/dist/esm/config.d.ts +4 -0
  2. package/dist/esm/drawingSvg/drawPath.d.ts +3 -0
  3. package/dist/esm/drawingSvg/drawPath.js +4 -1
  4. package/dist/esm/eventListeners/keyboard/keyDownListener.js +2 -2
  5. package/dist/esm/eventListeners/mouse/getMouseEventPoints.d.ts +1 -1
  6. package/dist/esm/eventListeners/mouse/getMouseEventPoints.js +19 -1
  7. package/dist/esm/eventListeners/mouse/mouseDoubleClickListener.js +8 -1
  8. package/dist/esm/eventListeners/mouse/mouseDownListener.js +37 -5
  9. package/dist/esm/eventListeners/mouse/mouseMoveListener.js +3 -0
  10. package/dist/esm/eventListeners/segmentation/imageChangeEventListener.js +60 -92
  11. package/dist/esm/eventListeners/segmentation/labelmap/onLabelmapSegmentationDataModified.js +49 -21
  12. package/dist/esm/eventListeners/segmentation/labelmap/performStackLabelmapUpdate.js +7 -13
  13. package/dist/esm/eventListeners/segmentation/labelmap/performVolumeLabelmapUpdate.js +44 -18
  14. package/dist/esm/eventListeners/touch/getTouchEventPoints.js +27 -4
  15. package/dist/esm/eventListeners/touch/touchStartListener.js +27 -9
  16. package/dist/esm/eventListeners/wheel/wheelListener.js +5 -1
  17. package/dist/esm/init.js +2 -0
  18. package/dist/esm/stateManagement/annotation/FrameOfReferenceSpecificAnnotationManager.js +10 -4
  19. package/dist/esm/stateManagement/segmentation/SegmentationRenderingEngine.js +23 -20
  20. package/dist/esm/stateManagement/segmentation/SegmentationRepresentationDisplayRegistry.d.ts +12 -0
  21. package/dist/esm/stateManagement/segmentation/SegmentationRepresentationDisplayRegistry.js +7 -0
  22. package/dist/esm/stateManagement/segmentation/SegmentationStateManager.d.ts +1 -11
  23. package/dist/esm/stateManagement/segmentation/SegmentationStateManager.js +28 -166
  24. package/dist/esm/stateManagement/segmentation/addColorLUT.js +7 -1
  25. package/dist/esm/stateManagement/segmentation/getCurrentLabelmapImageIdForViewport.js +16 -1
  26. package/dist/esm/stateManagement/segmentation/helpers/clearSegmentValue.js +9 -7
  27. package/dist/esm/stateManagement/segmentation/helpers/getSegmentationActor.d.ts +1 -1
  28. package/dist/esm/stateManagement/segmentation/helpers/getSegmentationActor.js +3 -2
  29. package/dist/esm/stateManagement/segmentation/helpers/getViewportLabelmapRenderMode.d.ts +5 -0
  30. package/dist/esm/stateManagement/segmentation/helpers/getViewportLabelmapRenderMode.js +58 -0
  31. package/dist/esm/stateManagement/segmentation/helpers/labelmapImageMapperSupport.d.ts +52 -0
  32. package/dist/esm/stateManagement/segmentation/helpers/labelmapImageMapperSupport.js +246 -0
  33. package/dist/esm/stateManagement/segmentation/helpers/labelmapSegmentationState.d.ts +1 -0
  34. package/dist/esm/stateManagement/segmentation/helpers/labelmapSegmentationState.js +1 -0
  35. package/dist/esm/stateManagement/segmentation/helpers/normalizeSegmentationInput.js +11 -1
  36. package/dist/esm/stateManagement/segmentation/internalAddSegmentationRepresentation.js +3 -3
  37. package/dist/esm/stateManagement/segmentation/labelmapModel/index.d.ts +9 -0
  38. package/dist/esm/stateManagement/segmentation/labelmapModel/index.js +7 -0
  39. package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapEditTransaction.d.ts +54 -0
  40. package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapEditTransaction.js +224 -0
  41. package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapImageIdMapping.d.ts +6 -0
  42. package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapImageIdMapping.js +39 -0
  43. package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapImageReferenceResolver.d.ts +23 -0
  44. package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapImageReferenceResolver.js +269 -0
  45. package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapLayerStore.d.ts +15 -0
  46. package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapLayerStore.js +160 -0
  47. package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapLegacyAdapter.d.ts +4 -0
  48. package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapLegacyAdapter.js +42 -0
  49. package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapSegmentBindings.d.ts +11 -0
  50. package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapSegmentBindings.js +73 -0
  51. package/dist/esm/stateManagement/segmentation/labelmapModel/normalizeLabelmapSegmentationData.d.ts +17 -0
  52. package/dist/esm/stateManagement/segmentation/labelmapModel/normalizeLabelmapSegmentationData.js +75 -0
  53. package/dist/esm/stateManagement/segmentation/labelmapModel/privateLabelmap.d.ts +5 -0
  54. package/dist/esm/stateManagement/segmentation/labelmapModel/privateLabelmap.js +106 -0
  55. package/dist/esm/stateManagement/segmentation/models/SegmentModel.d.ts +11 -0
  56. package/dist/esm/stateManagement/segmentation/models/SegmentModel.js +19 -0
  57. package/dist/esm/stateManagement/segmentation/models/SegmentationModel.d.ts +12 -0
  58. package/dist/esm/stateManagement/segmentation/models/SegmentationModel.js +23 -0
  59. package/dist/esm/stateManagement/segmentation/removeSegmentationRepresentations.js +6 -10
  60. package/dist/esm/stateManagement/segmentation/segmentIndex.js +24 -0
  61. package/dist/esm/stateManagement/segmentation/segmentationEventManager.js +2 -9
  62. package/dist/esm/stateManagement/segmentation/segmentationState.d.ts +2 -1
  63. package/dist/esm/stateManagement/segmentation/segmentationState.js +4 -1
  64. package/dist/esm/store/state.js +2 -1
  65. package/dist/esm/synchronizers/callbacks/imageSliceSyncCallback.js +12 -3
  66. package/dist/esm/synchronizers/callbacks/presentationViewSyncCallback.js +5 -2
  67. package/dist/esm/synchronizers/callbacks/zoomPanSyncCallback.js +51 -3
  68. package/dist/esm/tools/AdvancedMagnifyTool.js +1 -1
  69. package/dist/esm/tools/CrosshairsTool.js +5 -5
  70. package/dist/esm/tools/OrientationControllerTool.js +1 -1
  71. package/dist/esm/tools/OrientationMarkerTool.js +4 -4
  72. package/dist/esm/tools/PanTool.js +26 -3
  73. package/dist/esm/tools/PlanarRotateTool.js +19 -4
  74. package/dist/esm/tools/ReferenceCursors.js +7 -1
  75. package/dist/esm/tools/SculptorTool/CircleSculptCursor.js +1 -1
  76. package/dist/esm/tools/TrackballRotateTool.js +3 -2
  77. package/dist/esm/tools/VolumeCroppingTool.js +3 -2
  78. package/dist/esm/tools/WindowLevelTool.d.ts +2 -1
  79. package/dist/esm/tools/WindowLevelTool.js +48 -4
  80. package/dist/esm/tools/ZoomTool.d.ts +8 -0
  81. package/dist/esm/tools/ZoomTool.js +92 -11
  82. package/dist/esm/tools/annotation/AngleTool.js +33 -31
  83. package/dist/esm/tools/annotation/ArrowAnnotateTool.js +30 -28
  84. package/dist/esm/tools/annotation/BidirectionalTool.js +51 -49
  85. package/dist/esm/tools/annotation/CircleROITool.js +49 -44
  86. package/dist/esm/tools/annotation/CobbAngleTool.js +1 -1
  87. package/dist/esm/tools/annotation/DragProbeTool.js +1 -1
  88. package/dist/esm/tools/annotation/ETDRSGridTool.js +1 -1
  89. package/dist/esm/tools/annotation/EllipticalROITool.js +42 -37
  90. package/dist/esm/tools/annotation/HeightTool.js +1 -1
  91. package/dist/esm/tools/annotation/KeyImageTool.js +11 -11
  92. package/dist/esm/tools/annotation/LabelTool.js +37 -35
  93. package/dist/esm/tools/annotation/LengthTool.js +35 -33
  94. package/dist/esm/tools/annotation/LivewireContourSegmentationTool.js +6 -4
  95. package/dist/esm/tools/annotation/LivewireContourTool.js +1 -1
  96. package/dist/esm/tools/annotation/PlanarFreehandContourSegmentationTool.js +6 -4
  97. package/dist/esm/tools/annotation/PlanarFreehandROITool.js +1 -1
  98. package/dist/esm/tools/annotation/ProbeTool.js +51 -46
  99. package/dist/esm/tools/annotation/RectangleROITool.js +42 -37
  100. package/dist/esm/tools/annotation/RegionSegmentPlusTool.js +1 -1
  101. package/dist/esm/tools/annotation/RegionSegmentTool.js +1 -1
  102. package/dist/esm/tools/annotation/SplineContourSegmentationTool.js +1 -1
  103. package/dist/esm/tools/annotation/SplineROITool.js +51 -49
  104. package/dist/esm/tools/annotation/UltrasoundDirectionalTool.js +1 -1
  105. package/dist/esm/tools/annotation/UltrasoundPleuraBLineTool/UltrasoundPleuraBLineTool.js +57 -55
  106. package/dist/esm/tools/annotation/VideoRedactionTool.js +1 -1
  107. package/dist/esm/tools/base/AnnotationDisplayTool.js +9 -6
  108. package/dist/esm/tools/base/AnnotationTool.js +2 -1
  109. package/dist/esm/tools/base/BaseTool.js +16 -10
  110. package/dist/esm/tools/base/ContourSegmentationBaseTool.js +1 -1
  111. package/dist/esm/tools/base/GrowCutBaseTool.js +2 -2
  112. package/dist/esm/tools/displayTools/Labelmap/addLabelmapToElement.d.ts +2 -4
  113. package/dist/esm/tools/displayTools/Labelmap/addLabelmapToElement.js +15 -85
  114. package/dist/esm/tools/displayTools/Labelmap/labelmapActorStyle.d.ts +5 -0
  115. package/dist/esm/tools/displayTools/Labelmap/labelmapActorStyle.js +191 -0
  116. package/dist/esm/tools/displayTools/Labelmap/labelmapDisplay.d.ts +4 -3
  117. package/dist/esm/tools/displayTools/Labelmap/labelmapDisplay.js +48 -209
  118. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/createLabelmapRenderPlan.d.ts +3 -0
  119. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/createLabelmapRenderPlan.js +51 -0
  120. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/index.d.ts +4 -0
  121. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/index.js +3 -0
  122. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/legacyVolumePlan.d.ts +14 -0
  123. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/legacyVolumePlan.js +143 -0
  124. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/planarGenericVolumeLabelmap.d.ts +40 -0
  125. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/planarGenericVolumeLabelmap.js +79 -0
  126. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/removeLabelmapRepresentationFromViewport.d.ts +3 -0
  127. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/removeLabelmapRepresentationFromViewport.js +18 -0
  128. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/resolveLabelmapRenderPlan.d.ts +9 -0
  129. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/resolveLabelmapRenderPlan.js +56 -0
  130. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/stackImagePlan.d.ts +11 -0
  131. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/stackImagePlan.js +35 -0
  132. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/types.d.ts +48 -0
  133. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/types.js +0 -0
  134. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/volumeSliceImageMapperPlan.d.ts +13 -0
  135. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/volumeSliceImageMapperPlan.js +34 -0
  136. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan.d.ts +2 -0
  137. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan.js +1 -0
  138. package/dist/esm/tools/displayTools/Labelmap/labelmapRepresentationUID.d.ts +8 -0
  139. package/dist/esm/tools/displayTools/Labelmap/labelmapRepresentationUID.js +18 -0
  140. package/dist/esm/tools/displayTools/Labelmap/removeLabelmapFromElement.js +2 -5
  141. package/dist/esm/tools/displayTools/Labelmap/removeLabelmapRepresentationData.d.ts +3 -0
  142. package/dist/esm/tools/displayTools/Labelmap/removeLabelmapRepresentationData.js +16 -0
  143. package/dist/esm/tools/displayTools/Labelmap/syncStackLabelmapActors.d.ts +2 -0
  144. package/dist/esm/tools/displayTools/Labelmap/syncStackLabelmapActors.js +135 -0
  145. package/dist/esm/tools/displayTools/Labelmap/volumeLabelmapImageMapper.d.ts +16 -0
  146. package/dist/esm/tools/displayTools/Labelmap/volumeLabelmapImageMapper.js +267 -0
  147. package/dist/esm/tools/displayTools/Labelmap/volumeLabelmapSliceData.d.ts +27 -0
  148. package/dist/esm/tools/displayTools/Labelmap/volumeLabelmapSliceData.js +185 -0
  149. package/dist/esm/tools/displayTools/registerBuiltInSegmentationRepresentationDisplays.d.ts +1 -0
  150. package/dist/esm/tools/displayTools/registerBuiltInSegmentationRepresentationDisplays.js +16 -0
  151. package/dist/esm/tools/segmentation/BrushTool.d.ts +9 -2
  152. package/dist/esm/tools/segmentation/BrushTool.js +109 -25
  153. package/dist/esm/tools/segmentation/CircleScissorsTool.js +13 -6
  154. package/dist/esm/tools/segmentation/LabelmapBaseTool.d.ts +2 -3
  155. package/dist/esm/tools/segmentation/LabelmapBaseTool.js +77 -38
  156. package/dist/esm/tools/segmentation/LabelmapEditWithContour.js +3 -3
  157. package/dist/esm/tools/segmentation/PaintFillTool.js +11 -4
  158. package/dist/esm/tools/segmentation/RectangleROIStartEndThresholdTool.d.ts +2 -0
  159. package/dist/esm/tools/segmentation/RectangleROIStartEndThresholdTool.js +16 -8
  160. package/dist/esm/tools/segmentation/RectangleScissorsTool.js +13 -6
  161. package/dist/esm/tools/segmentation/SegmentBidirectionalTool.js +63 -61
  162. package/dist/esm/tools/segmentation/SegmentSelectTool.js +4 -4
  163. package/dist/esm/tools/segmentation/SphereScissorsTool.js +5 -1
  164. package/dist/esm/tools/segmentation/strategies/BrushStrategy.d.ts +7 -0
  165. package/dist/esm/tools/segmentation/strategies/BrushStrategy.js +47 -24
  166. package/dist/esm/tools/segmentation/strategies/compositions/circularCursor.js +49 -15
  167. package/dist/esm/tools/segmentation/strategies/compositions/determineSegmentIndex.js +2 -2
  168. package/dist/esm/tools/segmentation/strategies/compositions/dynamicThreshold.js +5 -1
  169. package/dist/esm/tools/segmentation/strategies/compositions/islandRemovalComposition.js +2 -2
  170. package/dist/esm/tools/segmentation/strategies/compositions/preview.js +2 -2
  171. package/dist/esm/tools/segmentation/strategies/compositions/setValue.js +14 -6
  172. package/dist/esm/tools/segmentation/strategies/utils/crossLayerErase.d.ts +4 -0
  173. package/dist/esm/tools/segmentation/strategies/utils/crossLayerErase.js +23 -0
  174. package/dist/esm/tools/segmentation/strategies/utils/getStrategyData.js +1 -1
  175. package/dist/esm/tools/segmentation/strategies/utils/handleUseSegmentCenterIndex.js +12 -11
  176. package/dist/esm/tools/segmentation/strategies/utils/labelmapOverlap.d.ts +4 -0
  177. package/dist/esm/tools/segmentation/strategies/utils/labelmapOverlap.js +41 -0
  178. package/dist/esm/tools/segmentation/strategies/utils/overwritePolicy.d.ts +3 -0
  179. package/dist/esm/tools/segmentation/strategies/utils/overwritePolicy.js +31 -0
  180. package/dist/esm/tools/segmentation/strategies/utils/segmentSeparation.d.ts +3 -0
  181. package/dist/esm/tools/segmentation/strategies/utils/segmentSeparation.js +38 -0
  182. package/dist/esm/tools/segmentation/utils/LazyBrushEditController.d.ts +19 -0
  183. package/dist/esm/tools/segmentation/utils/LazyBrushEditController.js +55 -0
  184. package/dist/esm/tools/segmentation/utils/lazyBrushPreview.d.ts +3 -0
  185. package/dist/esm/tools/segmentation/utils/lazyBrushPreview.js +34 -0
  186. package/dist/esm/tools/segmentation/utils/shouldUseLazyLabelmapEditing.d.ts +3 -0
  187. package/dist/esm/tools/segmentation/utils/shouldUseLazyLabelmapEditing.js +42 -0
  188. package/dist/esm/types/LabelmapToolOperationData.d.ts +5 -0
  189. package/dist/esm/types/LabelmapTypes.d.ts +29 -6
  190. package/dist/esm/types/SegmentationStateTypes.d.ts +4 -0
  191. package/dist/esm/utilities/calibrateImageSpacing.js +17 -2
  192. package/dist/esm/utilities/contours/AnnotationToPointData.js +1 -1
  193. package/dist/esm/utilities/getSphereBoundsInfo.js +5 -1
  194. package/dist/esm/utilities/getViewportICamera.d.ts +4 -0
  195. package/dist/esm/utilities/getViewportICamera.js +23 -0
  196. package/dist/esm/utilities/getViewportsForAnnotation.js +5 -1
  197. package/dist/esm/utilities/math/basic/BasicStatsCalculator.js +9 -7
  198. package/dist/esm/utilities/pointInSurroundingSphereCallback.js +8 -1
  199. package/dist/esm/utilities/segmentation/InterpolationManager/InterpolationManager.js +121 -118
  200. package/dist/esm/utilities/segmentation/SegmentStatsCalculator.js +5 -4
  201. package/dist/esm/utilities/segmentation/VolumetricCalculator.js +1 -1
  202. package/dist/esm/utilities/segmentation/createLabelmapVolumeForViewport.js +1 -1
  203. package/dist/esm/utilities/segmentation/getReferenceVolumeForSegmentation.js +1 -1
  204. package/dist/esm/utilities/segmentation/getReferenceVolumeForSegmentationVolume.js +11 -2
  205. package/dist/esm/utilities/segmentation/getSegmentIndexAtLabelmapBorder.js +36 -17
  206. package/dist/esm/utilities/segmentation/getSegmentIndexAtWorldPoint.js +42 -25
  207. package/dist/esm/utilities/segmentation/getUniqueSegmentIndices.js +3 -30
  208. package/dist/esm/utilities/segmentation/index.d.ts +2 -1
  209. package/dist/esm/utilities/segmentation/index.js +2 -1
  210. package/dist/esm/utilities/segmentation/utilsForWorker.js +2 -2
  211. package/dist/esm/utilities/segmentation/validateLabelmap.js +1 -1
  212. package/dist/esm/utilities/stackPrefetch/stackPrefetch.js +0 -1
  213. package/dist/esm/utilities/touch/index.js +3 -2
  214. package/dist/esm/utilities/viewportCapabilities.d.ts +16 -0
  215. package/dist/esm/utilities/viewportCapabilities.js +18 -0
  216. package/dist/esm/utilities/viewportFilters/filterViewportsWithParallelNormals.d.ts +1 -1
  217. package/dist/esm/utilities/viewportFilters/filterViewportsWithParallelNormals.js +12 -4
  218. package/dist/esm/utilities/viewportFilters/filterViewportsWithSameOrientation.d.ts +1 -1
  219. package/dist/esm/utilities/viewportFilters/filterViewportsWithSameOrientation.js +11 -4
  220. package/dist/esm/utilities/viewportFilters/getViewportIdsWithToolToRender.js +1 -1
  221. package/dist/esm/utilities/viewportPresentation.d.ts +3 -0
  222. package/dist/esm/utilities/viewportPresentation.js +26 -0
  223. package/dist/esm/version.d.ts +1 -1
  224. package/dist/esm/version.js +1 -1
  225. package/package.json +10 -10
@@ -9,6 +9,8 @@ import { resetElementCursor, hideElementCursor, } from '../../cursors/elementCur
9
9
  import triggerAnnotationRenderForViewportUIDs from '../../utilities/triggerAnnotationRenderForViewportIds';
10
10
  import LabelmapBaseTool from './LabelmapBaseTool';
11
11
  import { getStrategyData } from './strategies/utils/getStrategyData';
12
+ import LazyBrushEditController from './utils/LazyBrushEditController';
13
+ import { shouldUseLazyLabelmapEditing } from './utils/shouldUseLazyLabelmapEditing';
12
14
  import { getActiveSegmentation } from '../../stateManagement/segmentation/getActiveSegmentation';
13
15
  class BrushTool extends LabelmapBaseTool {
14
16
  constructor(toolProps = {}, defaultToolProps = {
@@ -81,13 +83,14 @@ class BrushTool extends LabelmapBaseTool {
81
83
  }) {
82
84
  super(toolProps, defaultToolProps);
83
85
  this._lastDragInfo = null;
84
- this.onSetToolPassive = (evt) => {
86
+ this._lazyEdit = new LazyBrushEditController();
87
+ this.onSetToolPassive = (_evt) => {
85
88
  this.disableCursor();
86
89
  };
87
90
  this.onSetToolEnabled = () => {
88
91
  this.disableCursor();
89
92
  };
90
- this.onSetToolDisabled = (evt) => {
93
+ this.onSetToolDisabled = (_evt) => {
91
94
  this.disableCursor();
92
95
  };
93
96
  this.preMouseDownCallback = (evt) => {
@@ -122,8 +125,14 @@ class BrushTool extends LabelmapBaseTool {
122
125
  canvas: canvasPoint,
123
126
  world: vec3.clone(worldPoint),
124
127
  };
125
- const hoverData = this._hoverData || this.createHoverData(element);
126
- triggerAnnotationRenderForViewportUIDs(hoverData.viewportIdsToRender);
128
+ this._hoverData = this.createHoverData(element, canvasPoint);
129
+ this._calculateCursor(element, canvasPoint);
130
+ this._resetLazyEditState();
131
+ if (this._isLazyLabelmapEditingEnabled(this._hoverData.viewport)) {
132
+ this._lazyEdit.appendStrokePoint(worldPoint);
133
+ this._captureLazyPreviewCircle();
134
+ }
135
+ triggerAnnotationRenderForViewportUIDs(this._hoverData.viewportIdsToRender);
127
136
  const operationData = this.getOperationData(element);
128
137
  if (!operationData) {
129
138
  return false;
@@ -177,6 +186,9 @@ class BrushTool extends LabelmapBaseTool {
177
186
  }
178
187
  this._previewData.timer = null;
179
188
  const operationData = this.getOperationData(this._previewData.element);
189
+ if (!operationData) {
190
+ return;
191
+ }
180
192
  const enabledElement = getEnabledElement(this._previewData.element);
181
193
  if (!enabledElement) {
182
194
  return;
@@ -204,6 +216,9 @@ class BrushTool extends LabelmapBaseTool {
204
216
  const enabledElement = getEnabledElement(element);
205
217
  const { viewport } = enabledElement;
206
218
  this.updateCursor(evt);
219
+ if (!this._hoverData) {
220
+ return;
221
+ }
207
222
  const { viewportIdsToRender } = this._hoverData;
208
223
  triggerAnnotationRenderForViewportUIDs(viewportIdsToRender);
209
224
  const delta = vec2.distance(currentPoints.canvas, this._previewData.startPoint);
@@ -234,16 +249,26 @@ class BrushTool extends LabelmapBaseTool {
234
249
  currentCanvas[1],
235
250
  ]);
236
251
  this._hoverData = this.createHoverData(element, currentCanvas);
237
- this._calculateCursor(element, currentCanvas);
238
- const operationData = this.getOperationData(element);
239
- if (!operationData) {
252
+ if (!this._hoverData) {
240
253
  return;
241
254
  }
242
- operationData.strokePointsWorld = [
243
- vec3.clone(this._lastDragInfo.world),
244
- vec3.clone(currentWorld),
245
- ];
246
- this._previewData.preview = this.applyActiveStrategy(enabledElement, operationData);
255
+ this._calculateCursor(element, currentCanvas);
256
+ if (this._isLazyLabelmapEditingEnabled(this._hoverData.viewport)) {
257
+ this._lazyEdit.appendStrokePoint(currentWorld);
258
+ this._captureLazyPreviewCircle();
259
+ this._previewData.preview = null;
260
+ }
261
+ else {
262
+ const operationData = this.getOperationData(element);
263
+ if (!operationData) {
264
+ return;
265
+ }
266
+ operationData.strokePointsWorld = [
267
+ vec3.clone(this._lastDragInfo.world),
268
+ vec3.clone(currentWorld),
269
+ ];
270
+ this._previewData.preview = this.applyActiveStrategy(enabledElement, operationData);
271
+ }
247
272
  const currentCanvasClone = vec2.clone(currentCanvas);
248
273
  this._lastDragInfo = {
249
274
  canvas: currentCanvasClone,
@@ -262,15 +287,29 @@ class BrushTool extends LabelmapBaseTool {
262
287
  if (!operationData) {
263
288
  return;
264
289
  }
265
- if (!this._previewData.preview && !this._previewData.isDrag) {
290
+ const isLazyLabelmapEditing = this._isLazyLabelmapEditingEnabled(this._hoverData?.viewport);
291
+ if (isLazyLabelmapEditing && this._previewData.isDrag) {
292
+ operationData.strokePointsWorld = this._lazyEdit
293
+ .getStrokePointsWorld()
294
+ .map((point) => vec3.clone(point));
295
+ this.applyActiveStrategy(enabledElement, operationData);
296
+ }
297
+ else if (!this._previewData.preview && !this._previewData.isDrag) {
266
298
  this.applyActiveStrategy(enabledElement, operationData);
267
299
  }
268
300
  this.doneEditMemo();
269
301
  this._deactivateDraw(element);
270
302
  resetElementCursor(element);
271
- this.updateCursor(evt);
272
303
  this._editData = null;
273
304
  this._lastDragInfo = null;
305
+ if (isLazyLabelmapEditing && this._previewData.isDrag) {
306
+ this._scheduleLazyPreviewCleanup(element, evt.detail.currentPoints.canvas, enabledElement.viewport.id, operationData.segmentationId);
307
+ triggerAnnotationRenderForViewportUIDs(this._hoverData.viewportIdsToRender);
308
+ }
309
+ else {
310
+ this._resetLazyEditState();
311
+ this.updateCursor(evt);
312
+ }
274
313
  this.applyActiveStrategyCallback(enabledElement, operationData, StrategyCallbacks.OnInteractionEnd);
275
314
  if (!this._previewData.isDrag) {
276
315
  this.acceptPreview(element);
@@ -288,32 +327,69 @@ class BrushTool extends LabelmapBaseTool {
288
327
  };
289
328
  }
290
329
  disableCursor() {
330
+ this._clearPendingLazyPreviewCleanup();
291
331
  this._hoverData = undefined;
332
+ this._resetLazyEditState();
292
333
  this.rejectPreview();
293
334
  }
294
- updateCursor(evt) {
295
- const eventData = evt.detail;
296
- const { element } = eventData;
297
- const { currentPoints } = eventData;
298
- const centerCanvas = currentPoints.canvas;
335
+ _isLazyLabelmapEditingEnabled(viewport) {
336
+ return shouldUseLazyLabelmapEditing(viewport ?? this._hoverData?.viewport);
337
+ }
338
+ _resetLazyEditState() {
339
+ this._lazyEdit.reset();
340
+ }
341
+ _clearPendingLazyPreviewCleanup() {
342
+ this._lazyEdit.clearPendingCleanup();
343
+ }
344
+ _refreshCursor(element, centerCanvas) {
299
345
  this._hoverData = this.createHoverData(element, centerCanvas);
300
- this._calculateCursor(element, centerCanvas);
301
346
  if (!this._hoverData) {
302
347
  return;
303
348
  }
349
+ this._calculateCursor(element, centerCanvas);
304
350
  BrushTool.activeCursorTool = this;
305
351
  triggerAnnotationRenderForViewportUIDs(this._hoverData.viewportIdsToRender);
306
352
  }
307
- _calculateCursor(element, centerCanvas) {
353
+ _scheduleLazyPreviewCleanup(element, centerCanvas, viewportId, segmentationId) {
354
+ this._lazyEdit.scheduleCleanup({
355
+ element,
356
+ centerCanvas,
357
+ viewportId,
358
+ segmentationId,
359
+ refreshCursor: this._refreshCursor.bind(this),
360
+ });
361
+ }
362
+ _captureLazyPreviewCircle() {
363
+ if (!this._isLazyLabelmapEditingEnabled() || !this._hoverData) {
364
+ return;
365
+ }
366
+ this._lazyEdit.capturePreviewCircle(this._hoverData);
367
+ }
368
+ updateCursor(evt) {
369
+ const eventData = evt.detail;
370
+ const { element } = eventData;
371
+ const { currentPoints } = eventData;
372
+ const centerCanvas = currentPoints.canvas;
373
+ this._refreshCursor(element, centerCanvas);
374
+ }
375
+ _calculateCursor(element, _centerCanvas) {
308
376
  const enabledElement = getEnabledElement(element);
309
- this.applyActiveStrategyCallback(enabledElement, this.getOperationData(element), StrategyCallbacks.CalculateCursorGeometry);
377
+ const operationData = this.getOperationData(element);
378
+ if (!enabledElement || !operationData) {
379
+ return;
380
+ }
381
+ this.applyActiveStrategyCallback(enabledElement, operationData, StrategyCallbacks.CalculateCursorGeometry);
310
382
  }
311
383
  getStatistics(element, segmentIndices) {
312
384
  if (!element) {
313
385
  return;
314
386
  }
315
387
  const enabledElement = getEnabledElement(element);
316
- const stats = this.applyActiveStrategyCallback(enabledElement, this.getOperationData(element), StrategyCallbacks.GetStatistics, segmentIndices);
388
+ const operationData = this.getOperationData(element);
389
+ if (!enabledElement || !operationData) {
390
+ return;
391
+ }
392
+ const stats = this.applyActiveStrategyCallback(enabledElement, operationData, StrategyCallbacks.GetStatistics, segmentIndices);
317
393
  return stats;
318
394
  }
319
395
  rejectPreview(element = this._previewData.element) {
@@ -325,7 +401,11 @@ class BrushTool extends LabelmapBaseTool {
325
401
  if (!enabledElement) {
326
402
  return;
327
403
  }
328
- this.applyActiveStrategyCallback(enabledElement, this.getOperationData(element), StrategyCallbacks.RejectPreview);
404
+ const operationData = this.getOperationData(element);
405
+ if (!operationData) {
406
+ return;
407
+ }
408
+ this.applyActiveStrategyCallback(enabledElement, operationData, StrategyCallbacks.RejectPreview);
329
409
  this._previewData.preview = null;
330
410
  this._previewData.isDrag = false;
331
411
  }
@@ -340,7 +420,11 @@ class BrushTool extends LabelmapBaseTool {
340
420
  return;
341
421
  }
342
422
  const enabledElement = getEnabledElement(element);
343
- this._previewData.preview = this.applyActiveStrategyCallback(enabledElement, this.getOperationData(element), StrategyCallbacks.Interpolate, config.configuration);
423
+ const operationData = this.getOperationData(element);
424
+ if (!enabledElement || !operationData) {
425
+ return;
426
+ }
427
+ this._previewData.preview = this.applyActiveStrategyCallback(enabledElement, operationData, StrategyCallbacks.Interpolate, config.configuration);
344
428
  this._previewData.isDrag = true;
345
429
  }
346
430
  invalidateBrushCursor() {
@@ -1,4 +1,4 @@
1
- import { BaseVolumeViewport, cache, getEnabledElement, } from '@cornerstonejs/core';
1
+ import { BaseVolumeViewport, getEnabledElement } from '@cornerstonejs/core';
2
2
  import { BaseTool } from '../base';
3
3
  import { fillInsideCircle } from './strategies/fillCircle';
4
4
  import { eraseInsideCircle } from './strategies/eraseCircle';
@@ -8,7 +8,9 @@ import { resetElementCursor, hideElementCursor, } from '../../cursors/elementCur
8
8
  import triggerAnnotationRenderForViewportIds from '../../utilities/triggerAnnotationRenderForViewportIds';
9
9
  import { segmentLocking, activeSegmentation, segmentIndex as segmentIndexController, config as segmentationConfig, } from '../../stateManagement/segmentation';
10
10
  import { getCurrentLabelmapImageIdForViewport, getSegmentation, } from '../../stateManagement/segmentation/segmentationState';
11
+ import getViewportLabelmapRenderMode from '../../stateManagement/segmentation/helpers/getViewportLabelmapRenderMode';
11
12
  import LabelmapBaseTool from './LabelmapBaseTool';
13
+ import { getOrCreateLabelmapVolume, resolveLabelmapForSegment, } from '../../stateManagement/segmentation/helpers/labelmapSegmentationState';
12
14
  import getEllipseWorldCoordinates from '../../utilities/getEllipseWorldCoordinates';
13
15
  import getCenterAndRadiusInCanvas from '../../utilities/getCenterAndRadiusInCanvas';
14
16
  class CircleScissorsTool extends LabelmapBaseTool {
@@ -92,13 +94,18 @@ class CircleScissorsTool extends LabelmapBaseTool {
92
94
  referencedVolumeId: null,
93
95
  imageId: null,
94
96
  };
95
- if (viewport instanceof BaseVolumeViewport) {
96
- const { volumeId } = labelmapData;
97
- const segmentation = cache.getVolume(volumeId);
97
+ const viewportRenderMode = getViewportLabelmapRenderMode(viewport);
98
+ if (viewportRenderMode === 'volume' ||
99
+ viewport instanceof BaseVolumeViewport) {
100
+ const layer = resolveLabelmapForSegment(getSegmentation(segmentationId), segmentIndex);
101
+ const segmentation = layer ? getOrCreateLabelmapVolume(layer) : undefined;
102
+ if (!segmentation) {
103
+ return;
104
+ }
98
105
  this.editData = {
99
106
  ...this.editData,
100
- volumeId,
101
- referencedVolumeId: segmentation.referencedVolumeId,
107
+ volumeId: segmentation.volumeId,
108
+ referencedVolumeId: layer?.referencedVolumeId ?? segmentation.referencedVolumeId,
102
109
  };
103
110
  }
104
111
  else {
@@ -1,4 +1,3 @@
1
- import { StackViewport } from '@cornerstonejs/core';
2
1
  import type { Types } from '@cornerstonejs/core';
3
2
  import { BaseTool } from '../base';
4
3
  import type vtkImageData from '@kitware/vtk.js/Common/DataModel/ImageData';
@@ -92,7 +91,7 @@ export default class LabelmapBaseTool extends BaseTool {
92
91
  };
93
92
  centerCanvas: any;
94
93
  segmentIndex: number;
95
- viewport: StackViewport | import("@cornerstonejs/core").VolumeViewport;
94
+ viewport: Types.IStackViewport | import("@cornerstonejs/core").VolumeViewport;
96
95
  segmentationId: string;
97
96
  segmentColor: Types.Color;
98
97
  viewportIdsToRender: string[];
@@ -102,7 +101,7 @@ export default class LabelmapBaseTool extends BaseTool {
102
101
  segmentationId: string;
103
102
  segmentColor: Types.Color;
104
103
  };
105
- protected getOperationData(element?: any): ModifiedLabelmapToolOperationData;
104
+ protected getOperationData(element?: any): ModifiedLabelmapToolOperationData | undefined;
106
105
  addPreview(element?: HTMLDivElement, options?: {
107
106
  acceptReject: boolean;
108
107
  }): any;
@@ -1,4 +1,4 @@
1
- import { getEnabledElement, cache, utilities as csUtils, Enums, eventTarget, BaseVolumeViewport, StackViewport, } from '@cornerstonejs/core';
1
+ import { getEnabledElement, cache, utilities as csUtils, Enums, eventTarget, BaseVolumeViewport, } from '@cornerstonejs/core';
2
2
  import { BaseTool } from '../base';
3
3
  import SegmentationRepresentations from '../../enums/SegmentationRepresentations';
4
4
  import { getActiveSegmentation } from '../../stateManagement/segmentation/getActiveSegmentation';
@@ -14,15 +14,10 @@ import { filterAnnotationsForDisplay } from '../../utilities/planar';
14
14
  import { isPointInsidePolyline3D } from '../../utilities/math/polyline';
15
15
  import { triggerSegmentationDataModified } from '../../stateManagement/segmentation/triggerSegmentationEvents';
16
16
  import { fillInsideCircle } from './strategies';
17
- export default class LabelmapBaseTool extends BaseTool {
18
- static { this.previewData = {
19
- preview: null,
20
- element: null,
21
- timerStart: 0,
22
- timer: null,
23
- startPoint: [NaN, NaN],
24
- isDrag: false,
25
- }; }
17
+ import getViewportLabelmapRenderMode from '../../stateManagement/segmentation/helpers/getViewportLabelmapRenderMode';
18
+ import { getOrCreateLabelmapVolume, resolveLabelmapForSegment, } from '../../stateManagement/segmentation/helpers/labelmapSegmentationState';
19
+ import getViewportICamera from '../../utilities/getViewportICamera';
20
+ class LabelmapBaseTool extends BaseTool {
26
21
  constructor(toolProps, defaultToolProps) {
27
22
  super(toolProps, defaultToolProps);
28
23
  this.memoMap = new Map();
@@ -44,6 +39,9 @@ export default class LabelmapBaseTool extends BaseTool {
44
39
  const memoData = this.acceptedMemoIds.get(id);
45
40
  const element = memoData?.element;
46
41
  const operationData = this.getOperationData(element);
42
+ if (!operationData) {
43
+ return;
44
+ }
47
45
  operationData.segmentIndex = memoData?.segmentIndex;
48
46
  if (element) {
49
47
  this.applyActiveStrategyCallback(getEnabledElement(element), operationData, StrategyCallbacks.AcceptPreview);
@@ -100,40 +98,37 @@ export default class LabelmapBaseTool extends BaseTool {
100
98
  return editData;
101
99
  }
102
100
  getEditData({ viewport, representationData, segmentsLocked, segmentationId, }) {
103
- if (viewport instanceof BaseVolumeViewport) {
104
- if (!representationData[SegmentationRepresentations.Labelmap]) {
105
- return;
106
- }
107
- const { volumeId } = representationData[SegmentationRepresentations.Labelmap];
108
- if (!volumeId) {
101
+ const viewportRenderMode = getViewportLabelmapRenderMode(viewport);
102
+ const activeSegmentIndex = getActiveSegmentIndex(segmentationId);
103
+ const segmentation = getSegmentation(segmentationId);
104
+ const layerForEdit = activeSegmentIndex
105
+ ? resolveLabelmapForSegment(segmentation, activeSegmentIndex)
106
+ : undefined;
107
+ if (viewportRenderMode === 'volume' ||
108
+ viewport instanceof BaseVolumeViewport) {
109
+ const segmentationVolume = layerForEdit
110
+ ? getOrCreateLabelmapVolume(layerForEdit)
111
+ : undefined;
112
+ const volumeId = layerForEdit?.volumeId ?? segmentationVolume?.volumeId;
113
+ if (!segmentationVolume || !volumeId) {
109
114
  return;
110
115
  }
111
116
  const actors = viewport.getActors();
112
- const isStackViewport = viewport instanceof StackViewport;
113
- if (isStackViewport) {
114
- const event = new CustomEvent(Enums.Events.ERROR_EVENT, {
115
- detail: {
116
- type: 'Segmentation',
117
- message: 'Cannot perform brush operation on the selected viewport',
118
- },
119
- cancelable: true,
120
- });
121
- eventTarget.dispatchEvent(event);
122
- return null;
123
- }
124
117
  const volumes = actors
125
118
  .filter((actorEntry) => actorEntry.referencedId)
126
- .map((actorEntry) => cache.getVolume(actorEntry.referencedId));
127
- const segmentationVolume = cache.getVolume(volumeId);
119
+ .map((actorEntry) => cache.getVolume(actorEntry.referencedId))
120
+ .filter((volume) => !!volume);
128
121
  const referencedVolumeIdToThreshold = volumes.find((volume) => csUtils.isEqual(volume.dimensions, segmentationVolume.dimensions))?.volumeId || volumes[0]?.volumeId;
129
122
  return {
130
123
  volumeId,
131
124
  referencedVolumeId: this.configuration.threshold?.volumeId ??
125
+ layerForEdit?.referencedVolumeId ??
126
+ segmentationVolume.referencedVolumeId ??
132
127
  referencedVolumeIdToThreshold,
133
128
  segmentsLocked,
134
129
  };
135
130
  }
136
- else {
131
+ if (viewportRenderMode === 'image') {
137
132
  const segmentationImageId = getCurrentLabelmapImageIdForViewport(viewport.id, segmentationId);
138
133
  if (!segmentationImageId) {
139
134
  return;
@@ -143,14 +138,30 @@ export default class LabelmapBaseTool extends BaseTool {
143
138
  segmentsLocked,
144
139
  };
145
140
  }
141
+ const event = new CustomEvent(Enums.Events.ERROR_EVENT, {
142
+ detail: {
143
+ type: 'Segmentation',
144
+ message: 'Cannot perform brush operation on the selected viewport',
145
+ },
146
+ cancelable: true,
147
+ });
148
+ eventTarget.dispatchEvent(event);
149
+ return null;
146
150
  }
147
151
  createHoverData(element, centerCanvas) {
148
152
  const enabledElement = getEnabledElement(element);
149
153
  const { viewport } = enabledElement;
150
- const camera = viewport.getCamera();
154
+ const camera = getViewportICamera(viewport);
151
155
  const { viewPlaneNormal, viewUp } = camera;
156
+ if (!viewPlaneNormal || !viewUp) {
157
+ return;
158
+ }
152
159
  const viewportIdsToRender = [viewport.id];
153
- const { segmentIndex, segmentationId, segmentColor } = this.getActiveSegmentationData(viewport) || {};
160
+ const activeSegmentationData = this.getActiveSegmentationData(viewport);
161
+ if (!activeSegmentationData) {
162
+ return;
163
+ }
164
+ const { segmentIndex, segmentationId, segmentColor } = activeSegmentationData;
154
165
  const brushCursor = {
155
166
  metadata: {
156
167
  viewPlaneNormal: [...viewPlaneNormal],
@@ -192,11 +203,19 @@ export default class LabelmapBaseTool extends BaseTool {
192
203
  }
193
204
  getOperationData(element) {
194
205
  const editData = this._editData || this.createEditData(element);
195
- const { segmentIndex, segmentationId, brushCursor } = this._hoverData || this.createHoverData(element);
206
+ const hoverData = this._hoverData || this.createHoverData(element);
207
+ if (!editData || !hoverData) {
208
+ return;
209
+ }
210
+ const { segmentIndex, segmentationId, brushCursor } = hoverData;
196
211
  const { data, metadata = {} } = brushCursor || {};
197
212
  const { viewPlaneNormal, viewUp } = metadata;
213
+ const points = data?.editPoints || data?.handles?.points;
198
214
  const configColor = this.configuration.preview?.previewColors?.[segmentIndex];
199
- const { viewport } = getEnabledElement(element);
215
+ const { viewport } = getEnabledElement(element) || {};
216
+ if (!viewport || !segmentIndex || !segmentationId) {
217
+ return;
218
+ }
200
219
  const segmentColor = getSegmentIndexColor(viewport.id, segmentationId, segmentIndex);
201
220
  if (!configColor && !segmentColor) {
202
221
  return;
@@ -208,7 +227,7 @@ export default class LabelmapBaseTool extends BaseTool {
208
227
  }
209
228
  const operationData = {
210
229
  ...editData,
211
- points: data?.handles?.points,
230
+ points,
212
231
  segmentIndex,
213
232
  viewPlaneNormal,
214
233
  previewOnHover: !this._previewData.isDrag,
@@ -235,7 +254,11 @@ export default class LabelmapBaseTool extends BaseTool {
235
254
  this.rejectPreview(element);
236
255
  }
237
256
  const enabledElement = getEnabledElement(element);
238
- const results = this.applyActiveStrategyCallback(enabledElement, this.getOperationData(element), StrategyCallbacks.AddPreview);
257
+ const operationData = this.getOperationData(element);
258
+ if (!enabledElement || !operationData) {
259
+ return;
260
+ }
261
+ const results = this.applyActiveStrategyCallback(enabledElement, operationData, StrategyCallbacks.AddPreview);
239
262
  _previewData.isDrag = true;
240
263
  if (results?.modified) {
241
264
  _previewData.preview = results;
@@ -249,7 +272,11 @@ export default class LabelmapBaseTool extends BaseTool {
249
272
  }
250
273
  this.doneEditMemo();
251
274
  const enabledElement = getEnabledElement(element);
252
- this.applyActiveStrategyCallback(enabledElement, this.getOperationData(element), StrategyCallbacks.RejectPreview);
275
+ const operationData = this.getOperationData(element);
276
+ if (!enabledElement || !operationData) {
277
+ return;
278
+ }
279
+ this.applyActiveStrategyCallback(enabledElement, operationData, StrategyCallbacks.RejectPreview);
253
280
  this._previewData.preview = null;
254
281
  this._previewData.isDrag = false;
255
282
  }
@@ -258,6 +285,9 @@ export default class LabelmapBaseTool extends BaseTool {
258
285
  return;
259
286
  }
260
287
  const operationData = this.getOperationData(element);
288
+ if (!operationData) {
289
+ return;
290
+ }
261
291
  if (this.memo && this.memo.id) {
262
292
  this.acceptedMemoIds.set(this.memo.id, {
263
293
  element,
@@ -357,6 +387,15 @@ export default class LabelmapBaseTool extends BaseTool {
357
387
  triggerSegmentationDataModified(segmentationId, slices);
358
388
  }
359
389
  }
390
+ LabelmapBaseTool.previewData = {
391
+ preview: null,
392
+ element: null,
393
+ timerStart: 0,
394
+ timer: null,
395
+ startPoint: [NaN, NaN],
396
+ isDrag: false,
397
+ };
398
+ export default LabelmapBaseTool;
360
399
  function lightenColor(r, g, b, a, factor = 0.4) {
361
400
  return [
362
401
  Math.round(r + (255 - r) * factor),
@@ -5,9 +5,6 @@ import BrushTool from './BrushTool';
5
5
  import * as segmentation from '../../stateManagement/segmentation';
6
6
  import { getSegmentationRepresentationsBySegmentationId } from '../../stateManagement/segmentation/getSegmentationRepresentation';
7
7
  class LabelMapEditWithContourTool extends PlanarFreehandContourSegmentationTool {
8
- static { this.toolName = 'LabelMapEditWithContour'; }
9
- static { this.annotationsToViewportMap = new Map(); }
10
- static { this.viewportIdsChecked = []; }
11
8
  constructor(toolProps = {}) {
12
9
  const initialProps = utilities.deepMerge({
13
10
  configuration: {
@@ -119,4 +116,7 @@ class LabelMapEditWithContourTool extends PlanarFreehandContourSegmentationTool
119
116
  }
120
117
  }
121
118
  }
119
+ LabelMapEditWithContourTool.toolName = 'LabelMapEditWithContour';
120
+ LabelMapEditWithContourTool.annotationsToViewportMap = new Map();
121
+ LabelMapEditWithContourTool.viewportIdsChecked = [];
122
122
  export default LabelMapEditWithContourTool;
@@ -1,10 +1,12 @@
1
- import { cache, getEnabledElement, utilities as csUtils, BaseVolumeViewport, } from '@cornerstonejs/core';
1
+ import { BaseVolumeViewport, cache, getEnabledElement, utilities as csUtils, } from '@cornerstonejs/core';
2
2
  import { BaseTool } from '../base';
3
3
  import { SegmentationRepresentations } from '../../enums';
4
4
  import { triggerSegmentationDataModified } from '../../stateManagement/segmentation/triggerSegmentationEvents';
5
5
  import { segmentLocking, activeSegmentation, segmentIndex as segmentIndexController, } from '../../stateManagement/segmentation';
6
6
  import floodFill from '../../utilities/segmentation/floodFill';
7
7
  import { getCurrentLabelmapImageIdForViewport, getSegmentation, } from '../../stateManagement/segmentation/segmentationState';
8
+ import getViewportLabelmapRenderMode from '../../stateManagement/segmentation/helpers/getViewportLabelmapRenderMode';
9
+ import { getOrCreateLabelmapVolume, resolveLabelmapForSegment, } from '../../stateManagement/segmentation/helpers/labelmapSegmentationState';
8
10
  const { transformWorldToIndex, isEqual } = csUtils;
9
11
  class PaintFillTool extends BaseTool {
10
12
  constructor(toolProps = {}, defaultToolProps = {
@@ -32,9 +34,14 @@ class PaintFillTool extends BaseTool {
32
34
  let index;
33
35
  let voxelManager;
34
36
  this.doneEditMemo();
35
- if (viewport instanceof BaseVolumeViewport) {
36
- const { volumeId } = representationData[SegmentationRepresentations.Labelmap];
37
- const segmentation = cache.getVolume(volumeId);
37
+ const viewportRenderMode = getViewportLabelmapRenderMode(viewport);
38
+ if (viewportRenderMode === 'volume' ||
39
+ viewport instanceof BaseVolumeViewport) {
40
+ const layer = resolveLabelmapForSegment(getSegmentation(segmentationId), segmentIndex);
41
+ const segmentation = layer ? getOrCreateLabelmapVolume(layer) : undefined;
42
+ if (!segmentation) {
43
+ return;
44
+ }
38
45
  ({ dimensions, direction } = segmentation);
39
46
  voxelManager = segmentation.voxelManager;
40
47
  index = transformWorldToIndex(segmentation.imageData, worldPos);
@@ -16,6 +16,8 @@ declare class RectangleROIStartEndThresholdTool extends RectangleROITool {
16
16
  isDrawing: boolean;
17
17
  isHandleOutsideImage: boolean;
18
18
  constructor(toolProps?: PublicToolProps, defaultToolProps?: ToolProps);
19
+ private _isCoordinateTuple;
20
+ private _resolveViewPlaneCoordinate;
19
21
  addNewAnnotation: (evt: EventTypes.InteractionEventType) => {
20
22
  highlighted: boolean;
21
23
  invalidated: boolean;
@@ -137,6 +137,7 @@ class RectangleROIStartEndThresholdTool extends RectangleROITool {
137
137
  }
138
138
  const targetId = this.getTargetId(enabledElement.viewport);
139
139
  const imageVolume = cache.getVolume(targetId.split(/volumeId:|\?/)[1]);
140
+ this._computeProjectionPoints(annotation, imageVolume);
140
141
  this._computePointsInsideVolume(annotation, targetId, imageVolume, enabledElement);
141
142
  triggerAnnotationRenderForViewportIds(viewportIdsToRender);
142
143
  if (newAnnotation) {
@@ -172,19 +173,16 @@ class RectangleROIStartEndThresholdTool extends RectangleROITool {
172
173
  const color = this.getStyle('color', styleSpecifier, annotation);
173
174
  const focalPoint = viewport.getCamera().focalPoint;
174
175
  const viewplaneNormal = viewport.getCamera().viewPlaneNormal;
175
- let startCoord = startCoordinate;
176
- let endCoord = endCoordinate;
177
- if (Array.isArray(startCoordinate)) {
178
- startCoord = this._getCoordinateForViewplaneNormal(startCoord, viewplaneNormal);
176
+ let startCoord = this._resolveViewPlaneCoordinate(startCoordinate, viewplaneNormal);
177
+ let endCoord = this._resolveViewPlaneCoordinate(endCoordinate, viewplaneNormal);
178
+ if (this._isCoordinateTuple(startCoordinate)) {
179
179
  const indexOfDirection = this._getIndexOfCoordinatesForViewplaneNormal(viewplaneNormal);
180
180
  data.handles.points.forEach((point) => {
181
181
  point[indexOfDirection] = startCoord;
182
182
  });
183
183
  data.startCoordinate = startCoord;
184
184
  }
185
- if (Array.isArray(endCoordinate)) {
186
- endCoord = this._getCoordinateForViewplaneNormal(endCoord, viewplaneNormal);
187
- data.endCoordinate = endCoord;
185
+ if (this._isCoordinateTuple(endCoordinate)) {
188
186
  data.endCoordinate = endCoord;
189
187
  }
190
188
  const roundedStartCoord = csUtils.roundToPrecision(startCoord);
@@ -264,11 +262,21 @@ class RectangleROIStartEndThresholdTool extends RectangleROITool {
264
262
  this._throttledCalculateCachedStats = debounce(this._calculateCachedStatsTool, this.configuration.throttleTimeout);
265
263
  }
266
264
  }
265
+ _isCoordinateTuple(value) {
266
+ return Array.isArray(value) || ArrayBuffer.isView(value);
267
+ }
268
+ _resolveViewPlaneCoordinate(coordinate, viewPlaneNormal) {
269
+ if (this._isCoordinateTuple(coordinate)) {
270
+ return this._getCoordinateForViewplaneNormal(coordinate, viewPlaneNormal);
271
+ }
272
+ return coordinate;
273
+ }
267
274
  _computeProjectionPoints(annotation, imageVolume) {
268
275
  const { data, metadata } = annotation;
269
276
  const { viewPlaneNormal, spacingInNormal } = metadata;
270
277
  const { imageData } = imageVolume;
271
- const { startCoordinate, endCoordinate } = data;
278
+ const startCoordinate = this._resolveViewPlaneCoordinate(data.startCoordinate, viewPlaneNormal);
279
+ const endCoordinate = this._resolveViewPlaneCoordinate(data.endCoordinate, viewPlaneNormal);
272
280
  const { points } = data.handles;
273
281
  const startIJK = transformWorldToIndex(imageData, points[0]);
274
282
  const endIJK = transformWorldToIndex(imageData, points[0]);