@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
@@ -40,9 +40,13 @@ type ComputeWorkerConfig = {
40
40
  idleTimeThreshold?: number;
41
41
  };
42
42
  };
43
+ type SegmentationConfig = {
44
+ overwriteMode?: 'all' | 'visible' | 'none';
45
+ };
43
46
  export type Config = {
44
47
  addons: AddOns;
45
48
  computeWorker?: ComputeWorkerConfig;
49
+ segmentation?: SegmentationConfig;
46
50
  };
47
51
  export declare function getConfig(): Config;
48
52
  export declare function setConfig(newConfig: Config): void;
@@ -4,8 +4,11 @@ export default function drawPath(svgDrawingHelper: SVGDrawingHelper, annotationU
4
4
  color?: string;
5
5
  fillColor?: string;
6
6
  fillOpacity?: number;
7
+ strokeOpacity?: number;
7
8
  width?: number;
8
9
  lineWidth?: number;
9
10
  lineDash?: string;
11
+ lineCap?: 'butt' | 'round' | 'square';
12
+ lineJoin?: 'miter' | 'round' | 'bevel';
10
13
  closePath?: boolean;
11
14
  }): void;
@@ -4,7 +4,7 @@ import setAttributesIfNecessary from './setAttributesIfNecessary';
4
4
  export default function drawPath(svgDrawingHelper, annotationUID, pathUID, points, options) {
5
5
  const hasSubArrays = points.length && points[0].length && Array.isArray(points[0][0]);
6
6
  const pointsArrays = hasSubArrays ? points : [points];
7
- const { color = 'rgb(0, 255, 0)', width = 10, fillColor = 'none', fillOpacity = 0, lineWidth, lineDash, closePath = false, } = options;
7
+ const { color = 'rgb(0, 255, 0)', width = 10, fillColor = 'none', fillOpacity = 0, strokeOpacity = 1, lineWidth, lineDash, lineCap, lineJoin, closePath = false, } = options;
8
8
  const strokeWidth = lineWidth || width;
9
9
  const svgns = 'http://www.w3.org/2000/svg';
10
10
  const svgNodeHash = _getHash(annotationUID, 'path', pathUID);
@@ -33,8 +33,11 @@ export default function drawPath(svgDrawingHelper, annotationUID, pathUID, point
33
33
  stroke: color,
34
34
  fill: fillColor,
35
35
  'fill-opacity': fillOpacity,
36
+ 'stroke-opacity': strokeOpacity,
36
37
  'stroke-width': strokeWidth,
37
38
  'stroke-dasharray': lineDash,
39
+ 'stroke-linecap': lineCap,
40
+ 'stroke-linejoin': lineJoin,
38
41
  };
39
42
  if (existingNode) {
40
43
  setAttributesIfNecessary(attributes, existingNode);
@@ -1,4 +1,4 @@
1
- import { getEnabledElement, triggerEvent } from '@cornerstonejs/core';
1
+ import { getEnabledElement, triggerEvent, utilities, } from '@cornerstonejs/core';
2
2
  import Events from '../../enums/Events';
3
3
  const defaultState = {
4
4
  renderingEngineId: undefined,
@@ -52,7 +52,7 @@ function _onKeyUp(evt) {
52
52
  document.removeEventListener('keyup', _onKeyUp);
53
53
  document.removeEventListener('visibilitychange', _onVisibilityChange);
54
54
  state.element.addEventListener('keydown', keyListener);
55
- state = structuredClone(defaultState);
55
+ state = utilities.deepClone(defaultState);
56
56
  triggerEvent(eventDetail.element, Events.KEY_UP, eventDetail);
57
57
  }
58
58
  export function getModifierKey() {
@@ -1,2 +1,2 @@
1
1
  import type { IPoints } from '../../types';
2
- export default function getMouseEventPoints(evt: MouseEvent, element?: HTMLDivElement): IPoints;
2
+ export default function getMouseEventPoints(evt: MouseEvent, element?: HTMLDivElement): IPoints | undefined;
@@ -8,7 +8,10 @@ export default function getMouseEventPoints(evt, element) {
8
8
  const clientPoint = _clientToPoint(evt);
9
9
  const pagePoint = _pageToPoint(evt);
10
10
  const canvasPoint = _pagePointsToCanvasPoints(elementToUse, pagePoint);
11
- const worldPoint = viewport.canvasToWorld(canvasPoint);
11
+ const worldPoint = getWorldPoint(viewport, canvasPoint);
12
+ if (!worldPoint) {
13
+ return;
14
+ }
12
15
  return {
13
16
  page: pagePoint,
14
17
  client: clientPoint,
@@ -29,3 +32,18 @@ function _pageToPoint(evt) {
29
32
  function _clientToPoint(evt) {
30
33
  return [evt.clientX, evt.clientY];
31
34
  }
35
+ function getWorldPoint(viewport, canvasPoint) {
36
+ try {
37
+ return viewport.canvasToWorld(canvasPoint);
38
+ }
39
+ catch (error) {
40
+ if (isNoMountedDataError(error)) {
41
+ return;
42
+ }
43
+ throw error;
44
+ }
45
+ }
46
+ function isNoMountedDataError(error) {
47
+ return (error instanceof Error &&
48
+ error.message.includes('because no data is mounted'));
49
+ }
@@ -3,8 +3,15 @@ import Events from '../../enums/Events';
3
3
  import getMouseEventPoints from './getMouseEventPoints';
4
4
  function mouseDoubleClickListener(evt) {
5
5
  const element = evt.currentTarget;
6
- const { viewportId, renderingEngineId } = getEnabledElement(element);
6
+ const enabledElement = getEnabledElement(element);
7
+ if (!enabledElement) {
8
+ return;
9
+ }
10
+ const { viewportId, renderingEngineId } = enabledElement;
7
11
  const startPoints = getMouseEventPoints(evt, element);
12
+ if (!startPoints) {
13
+ return;
14
+ }
8
15
  const deltaPoints = {
9
16
  page: [0, 0],
10
17
  client: [0, 0],
@@ -1,4 +1,4 @@
1
- import { getEnabledElement, triggerEvent } from '@cornerstonejs/core';
1
+ import { getEnabledElement, triggerEvent, utilities, } from '@cornerstonejs/core';
2
2
  import Events from '../../enums/Events';
3
3
  import mouseMoveListener from './mouseMoveListener';
4
4
  import getMouseEventPoints from './getMouseEventPoints';
@@ -69,12 +69,21 @@ function mouseDownListener(evt) {
69
69
  state.element = evt.currentTarget;
70
70
  state.mouseButton = evt.buttons;
71
71
  const enabledElement = getEnabledElement(state.element);
72
+ if (!enabledElement) {
73
+ state = utilities.deepClone(defaultState);
74
+ return;
75
+ }
72
76
  const { renderingEngineId, viewportId } = enabledElement;
73
77
  state.renderingEngineId = renderingEngineId;
74
78
  state.viewportId = viewportId;
75
79
  state.preventClickTimeout = setTimeout(_preventClickHandler, state.clickDelay);
76
- state.element.removeEventListener('mousemove', mouseMoveListener);
77
80
  const startPoints = getMouseEventPoints(evt, state.element);
81
+ if (!startPoints) {
82
+ clearTimeout(state.preventClickTimeout);
83
+ state = utilities.deepClone(defaultState);
84
+ return;
85
+ }
86
+ state.element.removeEventListener('mousemove', mouseMoveListener);
78
87
  state.startPoints = _copyPoints(startPoints);
79
88
  state.lastPoints = _copyPoints(startPoints);
80
89
  document.addEventListener('mouseup', _onMouseUp);
@@ -107,6 +116,9 @@ function _onMouseDrag(evt) {
107
116
  return;
108
117
  }
109
118
  const currentPoints = getMouseEventPoints(evt, state.element);
119
+ if (!currentPoints) {
120
+ return;
121
+ }
110
122
  const lastPoints = _updateMouseEventsLastPoints(state.element, state.lastPoints);
111
123
  const deltaPoints = _getDeltaPoints(currentPoints, lastPoints);
112
124
  if (doubleClickState.doubleClickTimeout) {
@@ -151,6 +163,10 @@ function _onMouseUp(evt) {
151
163
  else {
152
164
  const eventName = state.isClickEvent ? MOUSE_CLICK : MOUSE_UP;
153
165
  const currentPoints = getMouseEventPoints(evt, state.element);
166
+ if (!currentPoints) {
167
+ _cleanUp();
168
+ return;
169
+ }
154
170
  const deltaPoints = _getDeltaPoints(currentPoints, state.lastPoints);
155
171
  const eventDetail = {
156
172
  event: evt,
@@ -172,6 +188,9 @@ function _onMouseUp(evt) {
172
188
  }
173
189
  function _onMouseMove(evt) {
174
190
  const currentPoints = getMouseEventPoints(evt, state.element);
191
+ if (!currentPoints) {
192
+ return;
193
+ }
175
194
  const lastPoints = _updateMouseEventsLastPoints(state.element, state.lastPoints);
176
195
  const deltaPoints = _getDeltaPoints(currentPoints, lastPoints);
177
196
  if (!_isDragPastDoubleClickTolerance(deltaPoints.canvas)) {
@@ -209,17 +228,26 @@ function _cleanUp() {
209
228
  state.element?.removeEventListener('mousemove', _onMouseMove);
210
229
  state.element?.addEventListener('mousemove', mouseMoveListener);
211
230
  _clearDoubleClickTimeoutAndEvents();
212
- state = JSON.parse(JSON.stringify(defaultState));
231
+ state = utilities.deepClone(defaultState);
213
232
  }
214
233
  function _copyPoints(points) {
215
- return JSON.parse(JSON.stringify(points));
234
+ return utilities.deepClone(points);
216
235
  }
217
236
  function _updateMouseEventsLastPoints(element, lastPoints) {
218
237
  const { viewport } = getEnabledElement(element) || {};
219
238
  if (!viewport) {
220
239
  return lastPoints;
221
240
  }
222
- const world = viewport.canvasToWorld(lastPoints.canvas);
241
+ let world;
242
+ try {
243
+ world = viewport.canvasToWorld(lastPoints.canvas);
244
+ }
245
+ catch (error) {
246
+ if (isNoMountedDataError(error)) {
247
+ return lastPoints;
248
+ }
249
+ throw error;
250
+ }
223
251
  return {
224
252
  page: lastPoints.page,
225
253
  client: lastPoints.client,
@@ -249,6 +277,10 @@ function _subtractPoints2D(point0, point1) {
249
277
  function _subtractPoints3D(point0, point1) {
250
278
  return [point0[0] - point1[0], point0[1] - point1[1], point0[2] - point1[2]];
251
279
  }
280
+ function isNoMountedDataError(error) {
281
+ return (error instanceof Error &&
282
+ error.message.includes('because no data is mounted'));
283
+ }
252
284
  export function getMouseButton() {
253
285
  return state.mouseButton;
254
286
  }
@@ -10,6 +10,9 @@ function mouseMoveListener(evt) {
10
10
  }
11
11
  const { renderingEngineId, viewportId } = enabledElement;
12
12
  const currentPoints = getMouseEventPoints(evt);
13
+ if (!currentPoints) {
14
+ return;
15
+ }
13
16
  const eventDetail = {
14
17
  renderingEngineId,
15
18
  viewportId,
@@ -1,12 +1,12 @@
1
- import vtkDataArray from '@kitware/vtk.js/Common/Core/DataArray';
2
- import vtkImageData from '@kitware/vtk.js/Common/DataModel/ImageData';
3
- import { BaseVolumeViewport, getEnabledElement, Enums, getEnabledElementByIds, cache, utilities, } from '@cornerstonejs/core';
1
+ import { BaseVolumeViewport } from '@cornerstonejs/core';
2
+ import { getEnabledElement, Enums, getEnabledElementByIds, } from '@cornerstonejs/core';
4
3
  import { triggerSegmentationRender } from '../../stateManagement/segmentation/SegmentationRenderingEngine';
5
- import { updateLabelmapSegmentationImageReferences } from '../../stateManagement/segmentation/updateLabelmapSegmentationImageReferences';
6
- import { getCurrentLabelmapImageIdsForViewport } from '../../stateManagement/segmentation/getCurrentLabelmapImageIdForViewport';
7
4
  import { SegmentationRepresentations } from '../../enums';
8
- import { getLabelmapActorEntries } from '../../stateManagement/segmentation/helpers/getSegmentationActor';
5
+ import getViewportLabelmapRenderMode from '../../stateManagement/segmentation/helpers/getViewportLabelmapRenderMode';
6
+ import { canRenderVolumeViewportLabelmapAsImage, getVolumeViewportLabelmapImageMapperState, shouldUseSliceRendering, } from '../../stateManagement/segmentation/helpers/labelmapImageMapperSupport';
9
7
  import { getSegmentationRepresentations } from '../../stateManagement/segmentation/getSegmentationRepresentation';
8
+ import { getSegmentation } from '../../stateManagement/segmentation/getSegmentation';
9
+ import { syncStackLabelmapActors } from '../../tools/displayTools/Labelmap/syncStackLabelmapActors';
10
10
  const enable = function (element) {
11
11
  if (!element) {
12
12
  return;
@@ -16,116 +16,84 @@ const enable = function (element) {
16
16
  return;
17
17
  }
18
18
  const { viewport } = enabledElement;
19
- if (viewport instanceof BaseVolumeViewport) {
19
+ const isVolumeViewport = viewport instanceof BaseVolumeViewport;
20
+ const isPlanarViewport = viewport.type === Enums.ViewportType.PLANAR_NEXT;
21
+ const canUseStackImageEvents = typeof viewport
22
+ .getCurrentImageId === 'function';
23
+ if (isVolumeViewport || isPlanarViewport) {
24
+ element.addEventListener(Enums.Events.CAMERA_MODIFIED, _imageChangeEventListener);
25
+ }
26
+ if (isVolumeViewport ||
27
+ !canUseStackImageEvents ||
28
+ getViewportLabelmapRenderMode(viewport) !== 'image') {
20
29
  return;
21
30
  }
22
31
  element.addEventListener(Enums.Events.PRE_STACK_NEW_IMAGE, _imageChangeEventListener);
23
32
  element.addEventListener(Enums.Events.IMAGE_RENDERED, _imageChangeEventListener);
24
33
  };
25
34
  const disable = function (element) {
35
+ const viewportId = getEnabledElement(element)?.viewport?.id;
26
36
  element.removeEventListener(Enums.Events.PRE_STACK_NEW_IMAGE, _imageChangeEventListener);
27
37
  element.removeEventListener(Enums.Events.IMAGE_RENDERED, _imageChangeEventListener);
38
+ element.removeEventListener(Enums.Events.CAMERA_MODIFIED, _imageChangeEventListener);
39
+ if (viewportId) {
40
+ perViewportManualTriggers.delete(viewportId);
41
+ }
28
42
  };
29
43
  const perViewportManualTriggers = new Map();
30
44
  function _imageChangeEventListener(evt) {
31
45
  const eventData = evt.detail;
32
46
  const { viewportId, renderingEngineId } = eventData;
33
- const { viewport } = getEnabledElementByIds(viewportId, renderingEngineId);
47
+ const enabledElement = getEnabledElementByIds(viewportId, renderingEngineId);
48
+ if (!enabledElement) {
49
+ return;
50
+ }
51
+ const { viewport } = enabledElement;
52
+ const isVolumeViewport = viewport instanceof BaseVolumeViewport;
34
53
  const representations = getSegmentationRepresentations(viewportId);
35
54
  if (!representations?.length) {
55
+ perViewportManualTriggers.delete(viewportId);
36
56
  return;
37
57
  }
38
58
  const labelmapRepresentations = representations.filter((representation) => representation.type === SegmentationRepresentations.Labelmap);
39
- const actors = viewport.getActors();
40
- labelmapRepresentations.forEach((representation) => {
41
- const { segmentationId } = representation;
42
- updateLabelmapSegmentationImageReferences(viewportId, segmentationId);
59
+ const hasVolumeImageMapperRepresentation = labelmapRepresentations.some((representation) => {
60
+ const segmentation = getSegmentation(representation.segmentationId);
61
+ return (canRenderVolumeViewportLabelmapAsImage(viewport) &&
62
+ shouldUseSliceRendering(segmentation, representation.config));
43
63
  });
44
- const labelmapActors = labelmapRepresentations
45
- .flatMap((representation) => {
46
- return getLabelmapActorEntries(viewportId, representation.segmentationId);
47
- })
48
- .filter((actor) => actor !== undefined);
49
- if (!labelmapActors.length) {
50
- return;
51
- }
52
- labelmapActors.forEach((actor) => {
53
- const validActor = labelmapRepresentations.find((representation) => {
54
- const derivedImageIds = getCurrentLabelmapImageIdsForViewport(viewportId, representation.segmentationId);
55
- return derivedImageIds?.includes(actor.referencedId);
56
- });
57
- if (!validActor) {
58
- viewport.removeActors([actor.uid]);
59
- }
60
- });
61
- labelmapRepresentations.forEach((representation) => {
62
- const { segmentationId } = representation;
63
- const currentImageId = viewport.getCurrentImageId();
64
- const derivedImageIds = getCurrentLabelmapImageIdsForViewport(viewportId, segmentationId);
65
- if (!derivedImageIds) {
66
- return;
67
- }
68
- let shouldTriggerSegmentationRender = false;
69
- const updateSegmentationActor = (derivedImageId) => {
70
- const derivedImage = cache.getImage(derivedImageId);
71
- if (!derivedImage) {
72
- console.warn('No derived image found in the cache for segmentation representation', representation);
64
+ if (evt.type === Enums.Events.CAMERA_MODIFIED) {
65
+ if (hasVolumeImageMapperRepresentation) {
66
+ const nextState = getVolumeViewportLabelmapImageMapperState(viewport);
67
+ const previousState = perViewportManualTriggers.get(viewportId);
68
+ if (previousState === nextState.key) {
73
69
  return;
74
70
  }
75
- const segmentationActorInput = actors.find((actor) => actor.referencedId === derivedImageId);
76
- if (!segmentationActorInput) {
77
- const { dimensions, spacing, direction } = viewport.getImageDataMetadata(derivedImage);
78
- const currentImage = cache.getImage(currentImageId) ||
79
- {
80
- imageId: currentImageId,
81
- };
82
- const { origin: currentOrigin } = viewport.getImageDataMetadata(currentImage);
83
- const originToUse = currentOrigin;
84
- const constructor = derivedImage.voxelManager.getConstructor();
85
- const newPixelData = derivedImage.voxelManager.getScalarData();
86
- const scalarArray = vtkDataArray.newInstance({
87
- name: 'Pixels',
88
- numberOfComponents: 1,
89
- values: new constructor(newPixelData),
90
- });
91
- const imageData = vtkImageData.newInstance();
92
- imageData.setDimensions(dimensions[0], dimensions[1], 1);
93
- imageData.setSpacing(spacing);
94
- imageData.setDirection(direction);
95
- imageData.setOrigin(originToUse);
96
- imageData.getPointData().setScalars(scalarArray);
97
- imageData.modified();
98
- viewport.addImages([
99
- {
100
- imageId: derivedImageId,
101
- representationUID: `${segmentationId}-${SegmentationRepresentations.Labelmap}-${derivedImage.imageId}`,
102
- callback: ({ imageActor }) => {
103
- imageActor.getMapper().setInputData(imageData);
104
- },
105
- },
106
- ]);
107
- shouldTriggerSegmentationRender = true;
108
- return;
109
- }
110
- else {
111
- const segmentationImageData = segmentationActorInput.actor
112
- .getMapper()
113
- .getInputData();
114
- if (segmentationImageData.setDerivedImage) {
115
- segmentationImageData.setDerivedImage(derivedImage);
116
- }
117
- else {
118
- utilities.updateVTKImageDataWithCornerstoneImage(segmentationImageData, derivedImage);
119
- }
120
- }
121
- };
122
- derivedImageIds.forEach(updateSegmentationActor);
123
- if (shouldTriggerSegmentationRender) {
71
+ perViewportManualTriggers.set(viewportId, nextState.key);
124
72
  triggerSegmentationRender(viewportId);
73
+ return;
125
74
  }
126
- viewport.render();
75
+ const isPlanarNext = viewport.type === Enums.ViewportType.PLANAR_NEXT;
76
+ if (!isPlanarNext) {
77
+ perViewportManualTriggers.delete(viewportId);
78
+ return;
79
+ }
80
+ }
81
+ if (getViewportLabelmapRenderMode(viewport) !== 'image') {
82
+ return;
83
+ }
84
+ if (canRenderVolumeViewportLabelmapAsImage(viewport)) {
85
+ return;
86
+ }
87
+ if (typeof viewport
88
+ .getCurrentImageId !== 'function') {
89
+ return;
90
+ }
91
+ const stackViewport = viewport;
92
+ labelmapRepresentations.forEach((representation) => {
93
+ const { segmentationId } = representation;
94
+ syncStackLabelmapActors(stackViewport, segmentationId);
127
95
  if (evt.type === Enums.Events.IMAGE_RENDERED) {
128
- viewport.element.removeEventListener(Enums.Events.IMAGE_RENDERED, _imageChangeEventListener);
96
+ stackViewport.element.removeEventListener(Enums.Events.IMAGE_RENDERED, _imageChangeEventListener);
129
97
  }
130
98
  });
131
99
  }
@@ -1,9 +1,13 @@
1
- import { VolumeViewport, getEnabledElementByViewportId, StackViewport, } from '@cornerstonejs/core';
1
+ import { getEnabledElementByViewportId } from '@cornerstonejs/core';
2
2
  import { SegmentationRepresentations } from '../../../enums';
3
3
  import { performVolumeLabelmapUpdate } from './performVolumeLabelmapUpdate';
4
4
  import { performStackLabelmapUpdate } from './performStackLabelmapUpdate';
5
5
  import { getSegmentation } from '../../../stateManagement/segmentation/getSegmentation';
6
6
  import { getViewportIdsWithSegmentation } from '../../../stateManagement/segmentation/getViewportIdsWithSegmentation';
7
+ import { getSegmentationRepresentations } from '../../../stateManagement/segmentation/getSegmentationRepresentation';
8
+ import getViewportLabelmapRenderMode from '../../../stateManagement/segmentation/helpers/getViewportLabelmapRenderMode';
9
+ import { triggerSegmentationRender } from '../../../stateManagement/segmentation/SegmentationRenderingEngine';
10
+ import { canRenderVolumeViewportLabelmapAsImage, shouldUseSliceRendering, } from '../../../stateManagement/segmentation/helpers/labelmapImageMapperSupport';
7
11
  const getViewportByViewportId = (viewportId) => {
8
12
  const enabledElement = getEnabledElementByViewportId(viewportId);
9
13
  return enabledElement?.viewport ?? undefined;
@@ -12,30 +16,54 @@ const onLabelmapSegmentationDataModified = function (evt) {
12
16
  const { segmentationId, modifiedSlicesToUse } = evt.detail;
13
17
  const { representationData } = getSegmentation(segmentationId);
14
18
  const viewportIds = getViewportIdsWithSegmentation(segmentationId);
15
- const hasVolumeViewport = viewportIds.some((viewportId) => {
16
- const viewport = getViewportByViewportId(viewportId);
17
- return viewport instanceof VolumeViewport;
18
- });
19
- const hasStackViewport = viewportIds.some((viewportId) => {
20
- const viewport = getViewportByViewportId(viewportId);
21
- return viewport instanceof StackViewport;
22
- });
23
- const hasBothStackAndVolume = hasVolumeViewport && hasStackViewport;
19
+ const volumeViewportIds = [];
20
+ const stackViewportIds = [];
21
+ const imageMapperViewportIds = [];
24
22
  viewportIds.forEach((viewportId) => {
25
23
  const viewport = getViewportByViewportId(viewportId);
26
- if (viewport instanceof VolumeViewport) {
27
- performVolumeLabelmapUpdate({
28
- modifiedSlicesToUse: hasBothStackAndVolume ? [] : modifiedSlicesToUse,
29
- representationData,
30
- type: SegmentationRepresentations.Labelmap,
31
- });
24
+ if (!viewport) {
25
+ return;
26
+ }
27
+ const labelmapRepresentation = getSegmentationRepresentations(viewportId, {
28
+ segmentationId,
29
+ type: SegmentationRepresentations.Labelmap,
30
+ })[0];
31
+ const useSliceRendering = shouldUseSliceRendering(getSegmentation(segmentationId), labelmapRepresentation?.config);
32
+ const renderMode = getViewportLabelmapRenderMode(viewport, {
33
+ useSliceRendering,
34
+ });
35
+ if (renderMode === 'volume') {
36
+ volumeViewportIds.push(viewportId);
37
+ return;
32
38
  }
33
- if (viewport instanceof StackViewport) {
34
- performStackLabelmapUpdate({
35
- viewportIds,
36
- segmentationId,
37
- });
39
+ if (renderMode === 'image') {
40
+ if (useSliceRendering &&
41
+ canRenderVolumeViewportLabelmapAsImage(viewport)) {
42
+ imageMapperViewportIds.push(viewportId);
43
+ }
44
+ else {
45
+ stackViewportIds.push(viewportId);
46
+ }
38
47
  }
39
48
  });
49
+ const hasVolumeViewport = volumeViewportIds.length > 0;
50
+ const hasStackViewport = stackViewportIds.length > 0;
51
+ const hasBothStackAndVolume = hasVolumeViewport && hasStackViewport;
52
+ if (hasVolumeViewport) {
53
+ performVolumeLabelmapUpdate({
54
+ modifiedSlicesToUse: hasBothStackAndVolume ? [] : modifiedSlicesToUse,
55
+ representationData,
56
+ type: SegmentationRepresentations.Labelmap,
57
+ });
58
+ }
59
+ if (hasStackViewport) {
60
+ performStackLabelmapUpdate({
61
+ viewportIds: stackViewportIds,
62
+ segmentationId,
63
+ });
64
+ }
65
+ imageMapperViewportIds.forEach((viewportId) => {
66
+ triggerSegmentationRender(viewportId);
67
+ });
40
68
  };
41
69
  export default onLabelmapSegmentationDataModified;
@@ -1,8 +1,8 @@
1
- import { cache, utilities as csUtils, VolumeViewport, getEnabledElementByViewportId, } from '@cornerstonejs/core';
1
+ import { getEnabledElementByViewportId } from '@cornerstonejs/core';
2
2
  import { SegmentationRepresentations } from '../../../enums';
3
- import { getLabelmapActorEntries } from '../../../stateManagement/segmentation/helpers/getSegmentationActor';
4
3
  import { getSegmentationRepresentations } from '../../../stateManagement/segmentation/getSegmentationRepresentation';
5
- import { getCurrentLabelmapImageIdsForViewport } from '../../../stateManagement/segmentation/getCurrentLabelmapImageIdForViewport';
4
+ import getViewportLabelmapRenderMode from '../../../stateManagement/segmentation/helpers/getViewportLabelmapRenderMode';
5
+ import { syncStackLabelmapActors } from '../../../tools/displayTools/Labelmap/syncStackLabelmapActors';
6
6
  export function performStackLabelmapUpdate({ viewportIds, segmentationId, }) {
7
7
  viewportIds.forEach((viewportId) => {
8
8
  let representations = getSegmentationRepresentations(viewportId, {
@@ -18,20 +18,14 @@ export function performStackLabelmapUpdate({ viewportIds, segmentationId, }) {
18
18
  return;
19
19
  }
20
20
  const { viewport } = enabledElement;
21
- if (viewport instanceof VolumeViewport) {
21
+ if (getViewportLabelmapRenderMode(viewport) !== 'image') {
22
22
  return;
23
23
  }
24
- const actorEntries = getLabelmapActorEntries(viewportId, segmentationId);
25
- if (!actorEntries?.length) {
24
+ if (typeof viewport
25
+ .getCurrentImageId !== 'function') {
26
26
  return;
27
27
  }
28
- actorEntries.forEach((actorEntry, i) => {
29
- const segImageData = actorEntry.actor.getMapper().getInputData();
30
- const currentSegmentationImageIds = getCurrentLabelmapImageIdsForViewport(viewportId, segmentationId);
31
- const segmentationImage = cache.getImage(currentSegmentationImageIds[i]);
32
- segImageData.modified();
33
- csUtils.updateVTKImageDataWithCornerstoneImage(segImageData, segmentationImage);
34
- });
28
+ syncStackLabelmapActors(viewport, segmentationId);
35
29
  });
36
30
  });
37
31
  }
@@ -1,21 +1,47 @@
1
- import { cache } from '@cornerstonejs/core';
1
+ import { cache, eventTarget, triggerEvent, Enums } from '@cornerstonejs/core';
2
+ import { getOrCreateLabelmapVolume } from '../../../stateManagement/segmentation/helpers/labelmapSegmentationState';
2
3
  export function performVolumeLabelmapUpdate({ modifiedSlicesToUse, representationData, type, }) {
3
- const segmentationVolume = cache.getVolume(representationData[type].volumeId);
4
- if (!segmentationVolume) {
5
- console.warn('segmentation not found in cache');
6
- return;
7
- }
8
- const { imageData, vtkOpenGLTexture } = segmentationVolume;
9
- let slicesToUpdate;
10
- if (modifiedSlicesToUse?.length > 0) {
11
- slicesToUpdate = modifiedSlicesToUse;
12
- }
13
- else {
14
- const numSlices = imageData.getDimensions()[2];
15
- slicesToUpdate = [...Array(numSlices).keys()];
16
- }
17
- slicesToUpdate.forEach((i) => {
18
- vtkOpenGLTexture.setUpdatedFrame(i);
4
+ const labelmapData = representationData[type];
5
+ const volumes = getVolumesToUpdate(labelmapData);
6
+ volumes.forEach((segmentationVolume) => {
7
+ const { imageData, vtkOpenGLTexture, voxelManager } = segmentationVolume;
8
+ let slicesToUpdate;
9
+ if (modifiedSlicesToUse?.length > 0) {
10
+ slicesToUpdate = modifiedSlicesToUse;
11
+ }
12
+ else {
13
+ const numSlices = imageData.getDimensions()[2];
14
+ slicesToUpdate = [...Array(numSlices).keys()];
15
+ }
16
+ vtkOpenGLTexture?.setUpdatedFrame &&
17
+ slicesToUpdate.forEach((i) => {
18
+ vtkOpenGLTexture.setUpdatedFrame(i);
19
+ });
20
+ voxelManager?.invalidateCache?.();
21
+ imageData.modified();
22
+ const numberOfFrames = segmentationVolume.imageIds?.length ?? imageData.getDimensions()[2] ?? 0;
23
+ const FrameOfReferenceUID = segmentationVolume.metadata?.FrameOfReferenceUID ?? '';
24
+ triggerEvent(eventTarget, Enums.Events.IMAGE_VOLUME_MODIFIED, {
25
+ volumeId: segmentationVolume.volumeId,
26
+ FrameOfReferenceUID,
27
+ numberOfFrames,
28
+ framesProcessed: numberOfFrames,
29
+ });
19
30
  });
20
- imageData.modified();
31
+ }
32
+ function getVolumesToUpdate(labelmapData) {
33
+ const volumes = [];
34
+ const seenVolumeIds = new Set();
35
+ const addVolume = (volume) => {
36
+ if (!volume?.volumeId || seenVolumeIds.has(volume.volumeId)) {
37
+ return;
38
+ }
39
+ seenVolumeIds.add(volume.volumeId);
40
+ volumes.push(volume);
41
+ };
42
+ Object.values(labelmapData?.labelmaps ?? {}).forEach((layer) => {
43
+ addVolume(getOrCreateLabelmapVolume(layer));
44
+ });
45
+ addVolume(labelmapData?.volumeId && cache.getVolume(labelmapData.volumeId));
46
+ return volumes;
21
47
  }