@cornerstonejs/tools 5.0.0-beta.1 → 5.0.1
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.
- package/dist/esm/config.d.ts +4 -0
- package/dist/esm/drawingSvg/drawPath.d.ts +3 -0
- package/dist/esm/drawingSvg/drawPath.js +4 -1
- package/dist/esm/eventListeners/keyboard/keyDownListener.js +2 -2
- package/dist/esm/eventListeners/mouse/getMouseEventPoints.d.ts +1 -1
- package/dist/esm/eventListeners/mouse/getMouseEventPoints.js +19 -1
- package/dist/esm/eventListeners/mouse/mouseDoubleClickListener.js +8 -1
- package/dist/esm/eventListeners/mouse/mouseDownListener.js +37 -5
- package/dist/esm/eventListeners/mouse/mouseMoveListener.js +3 -0
- package/dist/esm/eventListeners/segmentation/imageChangeEventListener.js +60 -92
- package/dist/esm/eventListeners/segmentation/labelmap/onLabelmapSegmentationDataModified.js +49 -21
- package/dist/esm/eventListeners/segmentation/labelmap/performStackLabelmapUpdate.js +7 -13
- package/dist/esm/eventListeners/segmentation/labelmap/performVolumeLabelmapUpdate.js +44 -18
- package/dist/esm/eventListeners/touch/getTouchEventPoints.js +27 -4
- package/dist/esm/eventListeners/touch/touchStartListener.js +27 -9
- package/dist/esm/eventListeners/wheel/wheelListener.js +5 -1
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js +2 -2
- package/dist/esm/init.js +2 -0
- package/dist/esm/stateManagement/annotation/FrameOfReferenceSpecificAnnotationManager.js +10 -4
- package/dist/esm/stateManagement/segmentation/SegmentationRenderingEngine.js +23 -20
- package/dist/esm/stateManagement/segmentation/SegmentationRepresentationDisplayRegistry.d.ts +12 -0
- package/dist/esm/stateManagement/segmentation/SegmentationRepresentationDisplayRegistry.js +7 -0
- package/dist/esm/stateManagement/segmentation/SegmentationStateManager.d.ts +1 -10
- package/dist/esm/stateManagement/segmentation/SegmentationStateManager.js +28 -149
- package/dist/esm/stateManagement/segmentation/addColorLUT.js +7 -1
- package/dist/esm/stateManagement/segmentation/getCurrentLabelmapImageIdForViewport.js +16 -1
- package/dist/esm/stateManagement/segmentation/helpers/clearSegmentValue.js +9 -7
- package/dist/esm/stateManagement/segmentation/helpers/getSegmentationActor.d.ts +1 -1
- package/dist/esm/stateManagement/segmentation/helpers/getSegmentationActor.js +3 -2
- package/dist/esm/stateManagement/segmentation/helpers/getViewportLabelmapRenderMode.d.ts +5 -0
- package/dist/esm/stateManagement/segmentation/helpers/getViewportLabelmapRenderMode.js +58 -0
- package/dist/esm/stateManagement/segmentation/helpers/labelmapImageMapperSupport.d.ts +52 -0
- package/dist/esm/stateManagement/segmentation/helpers/labelmapImageMapperSupport.js +246 -0
- package/dist/esm/stateManagement/segmentation/helpers/labelmapSegmentationState.d.ts +1 -0
- package/dist/esm/stateManagement/segmentation/helpers/labelmapSegmentationState.js +1 -0
- package/dist/esm/stateManagement/segmentation/helpers/normalizeSegmentationInput.js +12 -1
- package/dist/esm/stateManagement/segmentation/internalAddSegmentationRepresentation.js +3 -3
- package/dist/esm/stateManagement/segmentation/labelmapModel/index.d.ts +9 -0
- package/dist/esm/stateManagement/segmentation/labelmapModel/index.js +7 -0
- package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapEditTransaction.d.ts +54 -0
- package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapEditTransaction.js +224 -0
- package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapImageIdMapping.d.ts +6 -0
- package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapImageIdMapping.js +39 -0
- package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapImageReferenceResolver.d.ts +23 -0
- package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapImageReferenceResolver.js +269 -0
- package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapLayerStore.d.ts +15 -0
- package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapLayerStore.js +160 -0
- package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapLegacyAdapter.d.ts +4 -0
- package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapLegacyAdapter.js +42 -0
- package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapSegmentBindings.d.ts +11 -0
- package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapSegmentBindings.js +73 -0
- package/dist/esm/stateManagement/segmentation/labelmapModel/normalizeLabelmapSegmentationData.d.ts +17 -0
- package/dist/esm/stateManagement/segmentation/labelmapModel/normalizeLabelmapSegmentationData.js +75 -0
- package/dist/esm/stateManagement/segmentation/labelmapModel/privateLabelmap.d.ts +5 -0
- package/dist/esm/stateManagement/segmentation/labelmapModel/privateLabelmap.js +106 -0
- package/dist/esm/stateManagement/segmentation/models/SegmentModel.d.ts +11 -0
- package/dist/esm/stateManagement/segmentation/models/SegmentModel.js +19 -0
- package/dist/esm/stateManagement/segmentation/models/SegmentationModel.d.ts +12 -0
- package/dist/esm/stateManagement/segmentation/models/SegmentationModel.js +23 -0
- package/dist/esm/stateManagement/segmentation/removeSegmentationRepresentations.js +6 -10
- package/dist/esm/stateManagement/segmentation/segmentIndex.js +24 -0
- package/dist/esm/stateManagement/segmentation/segmentationEventManager.js +2 -9
- package/dist/esm/stateManagement/segmentation/segmentationState.d.ts +2 -1
- package/dist/esm/stateManagement/segmentation/segmentationState.js +4 -1
- package/dist/esm/store/SynchronizerManager/Synchronizer.d.ts +3 -1
- package/dist/esm/store/state.js +2 -1
- package/dist/esm/synchronizers/callbacks/imageSliceSyncCallback.js +12 -3
- package/dist/esm/synchronizers/callbacks/presentationViewSyncCallback.js +5 -2
- package/dist/esm/synchronizers/callbacks/zoomPanSyncCallback.js +51 -3
- package/dist/esm/synchronizers/synchronizers/createPresentationViewSynchronizer.d.ts +1 -1
- package/dist/esm/tools/AdvancedMagnifyTool.js +4 -1
- package/dist/esm/tools/CrosshairsTool.d.ts +4 -0
- package/dist/esm/tools/CrosshairsTool.js +95 -41
- package/dist/esm/tools/MagnifyTool.js +3 -1
- package/dist/esm/tools/OrientationControllerTool.d.ts +45 -0
- package/dist/esm/tools/OrientationControllerTool.js +454 -0
- package/dist/esm/tools/OrientationMarkerTool.js +4 -4
- package/dist/esm/tools/PanTool.js +26 -3
- package/dist/esm/tools/PlanarRotateTool.js +19 -4
- package/dist/esm/tools/ReferenceCursors.js +7 -1
- package/dist/esm/tools/SculptorTool/CircleSculptCursor.js +1 -1
- package/dist/esm/tools/TrackballRotateTool.js +3 -2
- package/dist/esm/tools/VolumeCroppingControlTool.d.ts +10 -35
- package/dist/esm/tools/VolumeCroppingControlTool.js +179 -699
- package/dist/esm/tools/VolumeCroppingTool.d.ts +34 -32
- package/dist/esm/tools/VolumeCroppingTool.js +813 -532
- package/dist/esm/tools/WindowLevelTool.d.ts +2 -1
- package/dist/esm/tools/WindowLevelTool.js +48 -4
- package/dist/esm/tools/ZoomTool.d.ts +8 -0
- package/dist/esm/tools/ZoomTool.js +92 -11
- package/dist/esm/tools/annotation/AngleTool.js +38 -32
- package/dist/esm/tools/annotation/ArrowAnnotateTool.js +30 -28
- package/dist/esm/tools/annotation/BidirectionalTool.js +51 -49
- package/dist/esm/tools/annotation/CircleROITool.d.ts +1 -0
- package/dist/esm/tools/annotation/CircleROITool.js +89 -51
- package/dist/esm/tools/annotation/CobbAngleTool.js +1 -1
- package/dist/esm/tools/annotation/DragProbeTool.js +1 -1
- package/dist/esm/tools/annotation/ETDRSGridTool.js +1 -1
- package/dist/esm/tools/annotation/EllipticalROITool.js +46 -39
- package/dist/esm/tools/annotation/HeightTool.js +1 -1
- package/dist/esm/tools/annotation/KeyImageTool.js +11 -11
- package/dist/esm/tools/annotation/LabelTool.js +37 -35
- package/dist/esm/tools/annotation/LengthTool.js +35 -33
- package/dist/esm/tools/annotation/LivewireContourSegmentationTool.js +6 -4
- package/dist/esm/tools/annotation/LivewireContourTool.js +4 -8
- package/dist/esm/tools/annotation/PlanarFreehandContourSegmentationTool.js +6 -4
- package/dist/esm/tools/annotation/PlanarFreehandROITool.d.ts +2 -1
- package/dist/esm/tools/annotation/PlanarFreehandROITool.js +11 -8
- package/dist/esm/tools/annotation/ProbeTool.js +66 -56
- package/dist/esm/tools/annotation/RectangleROITool.js +48 -37
- package/dist/esm/tools/annotation/RegionSegmentPlusTool.js +1 -1
- package/dist/esm/tools/annotation/RegionSegmentTool.js +1 -1
- package/dist/esm/tools/annotation/SplineContourSegmentationTool.js +1 -1
- package/dist/esm/tools/annotation/SplineROITool.js +60 -56
- package/dist/esm/tools/annotation/UltrasoundDirectionalTool.js +1 -1
- package/dist/esm/tools/annotation/UltrasoundPleuraBLineTool/UltrasoundPleuraBLineTool.js +57 -55
- package/dist/esm/tools/annotation/VideoRedactionTool.js +1 -1
- package/dist/esm/tools/base/AnnotationDisplayTool.js +9 -6
- package/dist/esm/tools/base/AnnotationTool.js +2 -1
- package/dist/esm/tools/base/BaseTool.js +16 -10
- package/dist/esm/tools/base/ContourSegmentationBaseTool.js +1 -1
- package/dist/esm/tools/base/GrowCutBaseTool.js +2 -2
- package/dist/esm/tools/displayTools/Labelmap/addLabelmapToElement.d.ts +2 -4
- package/dist/esm/tools/displayTools/Labelmap/addLabelmapToElement.js +15 -85
- package/dist/esm/tools/displayTools/Labelmap/labelmapActorStyle.d.ts +5 -0
- package/dist/esm/tools/displayTools/Labelmap/labelmapActorStyle.js +191 -0
- package/dist/esm/tools/displayTools/Labelmap/labelmapDisplay.d.ts +4 -3
- package/dist/esm/tools/displayTools/Labelmap/labelmapDisplay.js +48 -209
- package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/createLabelmapRenderPlan.d.ts +3 -0
- package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/createLabelmapRenderPlan.js +51 -0
- package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/index.d.ts +4 -0
- package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/index.js +3 -0
- package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/legacyVolumePlan.d.ts +14 -0
- package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/legacyVolumePlan.js +143 -0
- package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/planarGenericVolumeLabelmap.d.ts +40 -0
- package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/planarGenericVolumeLabelmap.js +79 -0
- package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/removeLabelmapRepresentationFromViewport.d.ts +3 -0
- package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/removeLabelmapRepresentationFromViewport.js +18 -0
- package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/resolveLabelmapRenderPlan.d.ts +9 -0
- package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/resolveLabelmapRenderPlan.js +56 -0
- package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/stackImagePlan.d.ts +11 -0
- package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/stackImagePlan.js +35 -0
- package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/types.d.ts +48 -0
- package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/types.js +0 -0
- package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/volumeSliceImageMapperPlan.d.ts +13 -0
- package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/volumeSliceImageMapperPlan.js +34 -0
- package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan.d.ts +2 -0
- package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan.js +1 -0
- package/dist/esm/tools/displayTools/Labelmap/labelmapRepresentationUID.d.ts +8 -0
- package/dist/esm/tools/displayTools/Labelmap/labelmapRepresentationUID.js +18 -0
- package/dist/esm/tools/displayTools/Labelmap/removeLabelmapFromElement.js +2 -2
- package/dist/esm/tools/displayTools/Labelmap/removeLabelmapRepresentationData.d.ts +3 -0
- package/dist/esm/tools/displayTools/Labelmap/removeLabelmapRepresentationData.js +16 -0
- package/dist/esm/tools/displayTools/Labelmap/syncStackLabelmapActors.d.ts +2 -0
- package/dist/esm/tools/displayTools/Labelmap/syncStackLabelmapActors.js +135 -0
- package/dist/esm/tools/displayTools/Labelmap/volumeLabelmapImageMapper.d.ts +16 -0
- package/dist/esm/tools/displayTools/Labelmap/volumeLabelmapImageMapper.js +267 -0
- package/dist/esm/tools/displayTools/Labelmap/volumeLabelmapSliceData.d.ts +27 -0
- package/dist/esm/tools/displayTools/Labelmap/volumeLabelmapSliceData.js +185 -0
- package/dist/esm/tools/displayTools/registerBuiltInSegmentationRepresentationDisplays.d.ts +1 -0
- package/dist/esm/tools/displayTools/registerBuiltInSegmentationRepresentationDisplays.js +16 -0
- package/dist/esm/tools/index.d.ts +2 -1
- package/dist/esm/tools/index.js +2 -1
- package/dist/esm/tools/segmentation/BrushTool.d.ts +9 -2
- package/dist/esm/tools/segmentation/BrushTool.js +123 -26
- package/dist/esm/tools/segmentation/CircleScissorsTool.js +19 -36
- package/dist/esm/tools/segmentation/LabelmapBaseTool.d.ts +2 -3
- package/dist/esm/tools/segmentation/LabelmapBaseTool.js +77 -46
- package/dist/esm/tools/segmentation/LabelmapEditWithContour.js +3 -3
- package/dist/esm/tools/segmentation/PaintFillTool.js +11 -4
- package/dist/esm/tools/segmentation/RectangleROIStartEndThresholdTool.d.ts +2 -0
- package/dist/esm/tools/segmentation/RectangleROIStartEndThresholdTool.js +16 -8
- package/dist/esm/tools/segmentation/RectangleScissorsTool.js +13 -6
- package/dist/esm/tools/segmentation/SegmentBidirectionalTool.js +63 -61
- package/dist/esm/tools/segmentation/SegmentSelectTool.js +4 -4
- package/dist/esm/tools/segmentation/SphereScissorsTool.js +11 -31
- package/dist/esm/tools/segmentation/strategies/BrushStrategy.d.ts +7 -0
- package/dist/esm/tools/segmentation/strategies/BrushStrategy.js +47 -24
- package/dist/esm/tools/segmentation/strategies/compositions/circularCursor.js +49 -21
- package/dist/esm/tools/segmentation/strategies/compositions/determineSegmentIndex.js +2 -2
- package/dist/esm/tools/segmentation/strategies/compositions/dynamicThreshold.js +5 -1
- package/dist/esm/tools/segmentation/strategies/compositions/islandRemovalComposition.js +2 -2
- package/dist/esm/tools/segmentation/strategies/compositions/preview.js +2 -2
- package/dist/esm/tools/segmentation/strategies/compositions/setValue.js +14 -6
- package/dist/esm/tools/segmentation/strategies/fillCircle.d.ts +3 -1
- package/dist/esm/tools/segmentation/strategies/fillCircle.js +38 -31
- package/dist/esm/tools/segmentation/strategies/fillSphere.js +11 -3
- package/dist/esm/tools/segmentation/strategies/utils/crossLayerErase.d.ts +4 -0
- package/dist/esm/tools/segmentation/strategies/utils/crossLayerErase.js +23 -0
- package/dist/esm/tools/segmentation/strategies/utils/getStrategyData.js +1 -1
- package/dist/esm/tools/segmentation/strategies/utils/handleUseSegmentCenterIndex.js +12 -11
- package/dist/esm/tools/segmentation/strategies/utils/labelmapOverlap.d.ts +4 -0
- package/dist/esm/tools/segmentation/strategies/utils/labelmapOverlap.js +41 -0
- package/dist/esm/tools/segmentation/strategies/utils/overwritePolicy.d.ts +3 -0
- package/dist/esm/tools/segmentation/strategies/utils/overwritePolicy.js +31 -0
- package/dist/esm/tools/segmentation/strategies/utils/segmentSeparation.d.ts +3 -0
- package/dist/esm/tools/segmentation/strategies/utils/segmentSeparation.js +38 -0
- package/dist/esm/tools/segmentation/utils/LazyBrushEditController.d.ts +19 -0
- package/dist/esm/tools/segmentation/utils/LazyBrushEditController.js +55 -0
- package/dist/esm/tools/segmentation/utils/lazyBrushPreview.d.ts +3 -0
- package/dist/esm/tools/segmentation/utils/lazyBrushPreview.js +34 -0
- package/dist/esm/tools/segmentation/utils/shouldUseLazyLabelmapEditing.d.ts +3 -0
- package/dist/esm/tools/segmentation/utils/shouldUseLazyLabelmapEditing.js +42 -0
- package/dist/esm/types/ISynchronizerEventHandler.d.ts +2 -1
- package/dist/esm/types/LabelmapToolOperationData.d.ts +5 -0
- package/dist/esm/types/LabelmapTypes.d.ts +29 -6
- package/dist/esm/types/SegmentationStateTypes.d.ts +6 -0
- package/dist/esm/utilities/boundingBox/index.d.ts +2 -1
- package/dist/esm/utilities/boundingBox/index.js +2 -1
- package/dist/esm/utilities/boundingBox/snapIndexBounds.d.ts +3 -0
- package/dist/esm/utilities/boundingBox/snapIndexBounds.js +9 -0
- package/dist/esm/utilities/calibrateImageSpacing.js +17 -2
- package/dist/esm/utilities/contours/AnnotationToPointData.js +1 -1
- package/dist/esm/utilities/draw3D/addLine3DBetweenPoints.d.ts +7 -0
- package/dist/esm/utilities/draw3D/addLine3DBetweenPoints.js +34 -0
- package/dist/esm/utilities/draw3D/calculateAdaptiveSphereRadius.d.ts +6 -0
- package/dist/esm/utilities/draw3D/calculateAdaptiveSphereRadius.js +7 -0
- package/dist/esm/utilities/draw3D/index.d.ts +2 -0
- package/dist/esm/utilities/draw3D/index.js +2 -0
- package/dist/esm/utilities/drawing/getTextBoxCoordsCanvas.js +22 -14
- package/dist/esm/utilities/getCenterAndRadiusInCanvas.d.ts +6 -0
- package/dist/esm/utilities/getCenterAndRadiusInCanvas.js +26 -0
- package/dist/esm/utilities/getEllipseWorldCoordinates.d.ts +2 -0
- package/dist/esm/utilities/getEllipseWorldCoordinates.js +26 -0
- package/dist/esm/utilities/getSphereBoundsInfo.js +5 -1
- package/dist/esm/utilities/getViewportICamera.d.ts +4 -0
- package/dist/esm/utilities/getViewportICamera.js +23 -0
- package/dist/esm/utilities/getViewportsForAnnotation.js +5 -1
- package/dist/esm/utilities/index.d.ts +2 -1
- package/dist/esm/utilities/index.js +2 -1
- package/dist/esm/utilities/interactionDragCoordinator.d.ts +5 -0
- package/dist/esm/utilities/interactionDragCoordinator.js +16 -0
- package/dist/esm/utilities/math/basic/BasicStatsCalculator.js +9 -7
- package/dist/esm/utilities/pointInSurroundingSphereCallback.js +8 -1
- package/dist/esm/utilities/segmentation/InterpolationManager/InterpolationManager.js +121 -118
- package/dist/esm/utilities/segmentation/SegmentStatsCalculator.js +5 -4
- package/dist/esm/utilities/segmentation/VolumetricCalculator.js +1 -1
- package/dist/esm/utilities/segmentation/createLabelmapVolumeForViewport.js +1 -1
- package/dist/esm/utilities/segmentation/getReferenceVolumeForSegmentation.js +1 -1
- package/dist/esm/utilities/segmentation/getReferenceVolumeForSegmentationVolume.js +11 -2
- package/dist/esm/utilities/segmentation/getSegmentIndexAtLabelmapBorder.js +36 -17
- package/dist/esm/utilities/segmentation/getSegmentIndexAtWorldPoint.js +42 -25
- package/dist/esm/utilities/segmentation/getUniqueSegmentIndices.js +3 -30
- package/dist/esm/utilities/segmentation/index.d.ts +2 -1
- package/dist/esm/utilities/segmentation/index.js +2 -1
- package/dist/esm/utilities/segmentation/utilsForWorker.js +6 -2
- package/dist/esm/utilities/segmentation/validateLabelmap.js +1 -1
- package/dist/esm/utilities/stackPrefetch/stackPrefetch.js +0 -1
- package/dist/esm/utilities/touch/index.js +3 -2
- package/dist/esm/utilities/viewportCapabilities.d.ts +16 -0
- package/dist/esm/utilities/viewportCapabilities.js +18 -0
- package/dist/esm/utilities/viewportFilters/filterViewportsWithParallelNormals.d.ts +1 -1
- package/dist/esm/utilities/viewportFilters/filterViewportsWithParallelNormals.js +12 -4
- package/dist/esm/utilities/viewportFilters/filterViewportsWithSameOrientation.d.ts +1 -1
- package/dist/esm/utilities/viewportFilters/filterViewportsWithSameOrientation.js +11 -4
- package/dist/esm/utilities/viewportFilters/getViewportIdsWithToolToRender.js +1 -1
- package/dist/esm/utilities/viewportPresentation.d.ts +3 -0
- package/dist/esm/utilities/viewportPresentation.js +26 -0
- package/dist/esm/utilities/volumeCropping/computePlanePlaneIntersection.d.ts +6 -0
- package/dist/esm/utilities/volumeCropping/computePlanePlaneIntersection.js +37 -0
- package/dist/esm/utilities/volumeCropping/constants.d.ts +31 -0
- package/dist/esm/utilities/volumeCropping/constants.js +31 -0
- package/dist/esm/utilities/volumeCropping/copyClippingPlanes.d.ts +2 -0
- package/dist/esm/utilities/volumeCropping/copyClippingPlanes.js +6 -0
- package/dist/esm/utilities/volumeCropping/extractVolumeDirectionVectors.d.ts +9 -0
- package/dist/esm/utilities/volumeCropping/extractVolumeDirectionVectors.js +9 -0
- package/dist/esm/utilities/volumeCropping/findLineBoundsIntersection.d.ts +5 -0
- package/dist/esm/utilities/volumeCropping/findLineBoundsIntersection.js +50 -0
- package/dist/esm/utilities/volumeCropping/getColorKeyForPlaneIndex.d.ts +1 -0
- package/dist/esm/utilities/volumeCropping/getColorKeyForPlaneIndex.js +13 -0
- package/dist/esm/utilities/volumeCropping/getOrientationFromNormal.d.ts +2 -0
- package/dist/esm/utilities/volumeCropping/getOrientationFromNormal.js +19 -0
- package/dist/esm/utilities/volumeCropping/index.d.ts +9 -0
- package/dist/esm/utilities/volumeCropping/index.js +9 -0
- package/dist/esm/utilities/volumeCropping/parseCornerKey.d.ts +8 -0
- package/dist/esm/utilities/volumeCropping/parseCornerKey.js +11 -0
- package/dist/esm/utilities/volumeCropping/types.d.ts +5 -0
- package/dist/esm/utilities/volumeCropping/types.js +0 -0
- package/dist/esm/utilities/vtkjs/AnnotatedRhombicuboctahedronActor/index.d.ts +31 -0
- package/dist/esm/utilities/vtkjs/AnnotatedRhombicuboctahedronActor/index.js +391 -0
- package/dist/esm/utilities/vtkjs/OrientationControllerWidget/index.d.ts +69 -0
- package/dist/esm/utilities/vtkjs/OrientationControllerWidget/index.js +804 -0
- package/dist/esm/utilities/vtkjs/RhombicuboctahedronSource/index.d.ts +7 -0
- package/dist/esm/utilities/vtkjs/RhombicuboctahedronSource/index.js +144 -0
- package/dist/esm/utilities/vtkjs/index.d.ts +3 -0
- package/dist/esm/utilities/vtkjs/index.js +3 -0
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/package.json +10 -9
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { ActorRenderMode, Enums, VolumeViewport, } from '@cornerstonejs/core';
|
|
2
|
+
import { vec3 } from 'gl-matrix';
|
|
3
|
+
import { getLabelmaps } from '../labelmapModel/labelmapLayerStore';
|
|
4
|
+
const DIRECTION_ALIGNMENT_TOLERANCE = 0.999;
|
|
5
|
+
const MINIMUM_SLAB_THICKNESS = 0.1;
|
|
6
|
+
const SLAB_THICKNESS_EPSILON = 1e-3;
|
|
7
|
+
export const LABELMAP_IMAGE_MAPPER_URL_PARAM = 'labelmapImageMapper';
|
|
8
|
+
function isSupportedImageMapperBlendMode(blendMode) {
|
|
9
|
+
return (blendMode === Enums.BlendModes.COMPOSITE ||
|
|
10
|
+
blendMode === Enums.BlendModes.AVERAGE_INTENSITY_BLEND);
|
|
11
|
+
}
|
|
12
|
+
function isPlanarGpuVolumeSliceViewport(viewport) {
|
|
13
|
+
const compatibilityViewport = viewport;
|
|
14
|
+
if (compatibilityViewport.type !== Enums.ViewportType.PLANAR_NEXT) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
return (getPlanarPrimaryRenderMode(compatibilityViewport) ===
|
|
18
|
+
ActorRenderMode.VTK_VOLUME_SLICE);
|
|
19
|
+
}
|
|
20
|
+
function getPlanarPrimaryRenderMode(viewport) {
|
|
21
|
+
const primaryDataId = getPlanarPrimaryDataId(viewport);
|
|
22
|
+
if (primaryDataId) {
|
|
23
|
+
const renderMode = viewport.getDisplaySetRenderMode?.(primaryDataId);
|
|
24
|
+
if (renderMode) {
|
|
25
|
+
return renderMode;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return viewport.getDefaultActor?.()?.actorMapper?.renderMode;
|
|
29
|
+
}
|
|
30
|
+
function getPlanarVolumeSliceMapper(viewport) {
|
|
31
|
+
const defaultActor = viewport.getDefaultActor?.();
|
|
32
|
+
return (defaultActor?.actorMapper?.mapper ??
|
|
33
|
+
defaultActor?.actorMapper?.actor?.getMapper?.());
|
|
34
|
+
}
|
|
35
|
+
function getPlanarPrimaryDataId(viewport) {
|
|
36
|
+
const sourceDataId = viewport.getSourceDataId?.();
|
|
37
|
+
if (sourceDataId) {
|
|
38
|
+
return sourceDataId;
|
|
39
|
+
}
|
|
40
|
+
const renderModes = viewport._debug?.renderModes;
|
|
41
|
+
if (!renderModes) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
return (Object.entries(renderModes).find(([dataId, renderMode]) => viewport.getDisplaySetRole?.(dataId) === 'source' &&
|
|
45
|
+
renderMode === ActorRenderMode.VTK_VOLUME_SLICE)?.[0] ??
|
|
46
|
+
Object.entries(renderModes).find(([, renderMode]) => renderMode === ActorRenderMode.VTK_VOLUME_SLICE)?.[0]);
|
|
47
|
+
}
|
|
48
|
+
function getLabelmapImageMapperCamera(viewport) {
|
|
49
|
+
const compatibilityViewport = viewport;
|
|
50
|
+
const resolvedCamera = compatibilityViewport
|
|
51
|
+
.getResolvedView?.()
|
|
52
|
+
?.toICamera?.();
|
|
53
|
+
if (isLabelmapImageMapperCamera(resolvedCamera)) {
|
|
54
|
+
return resolvedCamera;
|
|
55
|
+
}
|
|
56
|
+
const legacyCamera = compatibilityViewport.getCamera?.();
|
|
57
|
+
return isLabelmapImageMapperCamera(legacyCamera) ? legacyCamera : undefined;
|
|
58
|
+
}
|
|
59
|
+
function isLabelmapImageMapperCamera(camera) {
|
|
60
|
+
const candidate = camera;
|
|
61
|
+
return Boolean(candidate &&
|
|
62
|
+
isPoint3Like(candidate.viewPlaneNormal) &&
|
|
63
|
+
isPoint3Like(candidate.viewUp));
|
|
64
|
+
}
|
|
65
|
+
function isPoint3Like(value) {
|
|
66
|
+
const candidate = value;
|
|
67
|
+
return Boolean(candidate &&
|
|
68
|
+
typeof candidate.length === 'number' &&
|
|
69
|
+
candidate.length >= 3 &&
|
|
70
|
+
Number.isFinite(Number(candidate[0])) &&
|
|
71
|
+
Number.isFinite(Number(candidate[1])) &&
|
|
72
|
+
Number.isFinite(Number(candidate[2])));
|
|
73
|
+
}
|
|
74
|
+
function getPlanarVolumeDataPresentation(viewport) {
|
|
75
|
+
if (!viewport.getDisplaySetPresentation) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const primaryDataId = getPlanarPrimaryDataId(viewport);
|
|
79
|
+
return primaryDataId
|
|
80
|
+
? viewport.getDisplaySetPresentation(primaryDataId)
|
|
81
|
+
: undefined;
|
|
82
|
+
}
|
|
83
|
+
function getCompatibilityBlendMode(viewport) {
|
|
84
|
+
if (viewport instanceof VolumeViewport) {
|
|
85
|
+
return viewport.getBlendMode?.();
|
|
86
|
+
}
|
|
87
|
+
if (!isPlanarGpuVolumeSliceViewport(viewport)) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const presentationBlendMode = getPlanarVolumeDataPresentation(viewport)?.blendMode;
|
|
91
|
+
if (presentationBlendMode !== undefined) {
|
|
92
|
+
return presentationBlendMode;
|
|
93
|
+
}
|
|
94
|
+
return Enums.BlendModes.AVERAGE_INTENSITY_BLEND;
|
|
95
|
+
}
|
|
96
|
+
function getCompatibilitySlabThickness(viewport) {
|
|
97
|
+
if (viewport instanceof VolumeViewport) {
|
|
98
|
+
return viewport.getSlabThickness?.() ?? MINIMUM_SLAB_THICKNESS;
|
|
99
|
+
}
|
|
100
|
+
if (!isPlanarGpuVolumeSliceViewport(viewport)) {
|
|
101
|
+
return MINIMUM_SLAB_THICKNESS;
|
|
102
|
+
}
|
|
103
|
+
const mapperSlabThickness = getPlanarVolumeSliceMapper(viewport)?.getSlabThickness?.();
|
|
104
|
+
if (typeof mapperSlabThickness === 'number') {
|
|
105
|
+
return mapperSlabThickness;
|
|
106
|
+
}
|
|
107
|
+
return (getPlanarVolumeDataPresentation(viewport)?.slabThickness ??
|
|
108
|
+
MINIMUM_SLAB_THICKNESS);
|
|
109
|
+
}
|
|
110
|
+
export function isSliceRenderingEnabled(options) {
|
|
111
|
+
if (options?.useSliceRendering) {
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
if (typeof window === 'undefined') {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
const params = new URLSearchParams(window.location.search);
|
|
118
|
+
if (!params.has(LABELMAP_IMAGE_MAPPER_URL_PARAM)) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
const value = params.get(LABELMAP_IMAGE_MAPPER_URL_PARAM);
|
|
122
|
+
if (value === null || value === '') {
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
const normalizedValue = value.trim().toLowerCase();
|
|
126
|
+
return (normalizedValue !== '0' &&
|
|
127
|
+
normalizedValue !== 'false' &&
|
|
128
|
+
normalizedValue !== 'off');
|
|
129
|
+
}
|
|
130
|
+
export function shouldUseSliceRendering(segmentation, options) {
|
|
131
|
+
if (isSliceRenderingEnabled(options)) {
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
if (!segmentation?.representationData?.Labelmap) {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
const layers = getLabelmaps(segmentation);
|
|
138
|
+
return layers.length > 1 && layers.some((layer) => layer.type === 'stack');
|
|
139
|
+
}
|
|
140
|
+
export function canRenderVolumeViewportLabelmapAsImage(viewport) {
|
|
141
|
+
const isLegacyVolumeViewport = viewport instanceof VolumeViewport;
|
|
142
|
+
const isNextPlanarViewport = isPlanarGpuVolumeSliceViewport(viewport);
|
|
143
|
+
if (!isLegacyVolumeViewport && !isNextPlanarViewport) {
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
const blendMode = getCompatibilityBlendMode(viewport);
|
|
147
|
+
if (isLegacyVolumeViewport && !isSupportedImageMapperBlendMode(blendMode)) {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
const slabThickness = getCompatibilitySlabThickness(viewport);
|
|
151
|
+
if (slabThickness > MINIMUM_SLAB_THICKNESS + SLAB_THICKNESS_EPSILON) {
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
if (isLegacyVolumeViewport) {
|
|
155
|
+
try {
|
|
156
|
+
viewport.getSliceViewInfo();
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
export function getVolumeViewportLabelmapImageMapperState(viewport) {
|
|
166
|
+
const compatibilityViewport = viewport;
|
|
167
|
+
const isLegacyVolumeViewport = viewport instanceof VolumeViewport;
|
|
168
|
+
const isNextPlanarViewport = isPlanarGpuVolumeSliceViewport(viewport);
|
|
169
|
+
if (!isLegacyVolumeViewport && !isNextPlanarViewport) {
|
|
170
|
+
return {
|
|
171
|
+
key: 'unsupported:viewport',
|
|
172
|
+
sliceIndex: NaN,
|
|
173
|
+
supported: false,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
const camera = getLabelmapImageMapperCamera(viewport);
|
|
177
|
+
if (!camera) {
|
|
178
|
+
return {
|
|
179
|
+
key: 'unsupported:camera',
|
|
180
|
+
sliceIndex: NaN,
|
|
181
|
+
supported: false,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
const { viewPlaneNormal, viewUp } = camera;
|
|
185
|
+
const normalizedNormal = vec3.normalize(vec3.create(), viewPlaneNormal);
|
|
186
|
+
const normalizedViewUp = vec3.normalize(vec3.create(), viewUp);
|
|
187
|
+
let sliceIndex;
|
|
188
|
+
if (isLegacyVolumeViewport) {
|
|
189
|
+
try {
|
|
190
|
+
sliceIndex = viewport.getSliceViewInfo().sliceIndex;
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
sliceIndex = undefined;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
sliceIndex = compatibilityViewport.getCurrentImageIdIndex?.();
|
|
198
|
+
}
|
|
199
|
+
const blendMode = getCompatibilityBlendMode(viewport);
|
|
200
|
+
const slabThickness = getCompatibilitySlabThickness(viewport);
|
|
201
|
+
const orientationKey = [
|
|
202
|
+
normalizedNormal.map((value) => value.toFixed(3)).join(','),
|
|
203
|
+
normalizedViewUp.map((value) => value.toFixed(3)).join(','),
|
|
204
|
+
].join('|');
|
|
205
|
+
if (isLegacyVolumeViewport && !isSupportedImageMapperBlendMode(blendMode)) {
|
|
206
|
+
return {
|
|
207
|
+
key: `unsupported:blend:${blendMode}:${orientationKey}`,
|
|
208
|
+
sliceIndex: sliceIndex ?? NaN,
|
|
209
|
+
supported: false,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
if (slabThickness > MINIMUM_SLAB_THICKNESS + SLAB_THICKNESS_EPSILON) {
|
|
213
|
+
return {
|
|
214
|
+
key: `unsupported:slab:${slabThickness.toFixed(3)}:${orientationKey}`,
|
|
215
|
+
sliceIndex: sliceIndex ?? NaN,
|
|
216
|
+
supported: false,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
if (isLegacyVolumeViewport) {
|
|
220
|
+
try {
|
|
221
|
+
viewport.getSliceViewInfo();
|
|
222
|
+
}
|
|
223
|
+
catch {
|
|
224
|
+
return {
|
|
225
|
+
key: `unsupported:oblique:${orientationKey}`,
|
|
226
|
+
sliceIndex: sliceIndex ?? NaN,
|
|
227
|
+
supported: false,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if (isNextPlanarViewport &&
|
|
232
|
+
getPlanarPrimaryRenderMode(compatibilityViewport) !==
|
|
233
|
+
ActorRenderMode.VTK_VOLUME_SLICE) {
|
|
234
|
+
return {
|
|
235
|
+
key: `unsupported:renderMode:${orientationKey}`,
|
|
236
|
+
sliceIndex: sliceIndex ?? NaN,
|
|
237
|
+
supported: false,
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
return {
|
|
241
|
+
key: `supported:${orientationKey}:${sliceIndex ?? 0}`,
|
|
242
|
+
sliceIndex: sliceIndex ?? NaN,
|
|
243
|
+
supported: true,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
export { DIRECTION_ALIGNMENT_TOLERANCE };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../labelmapModel';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../labelmapModel';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SegmentationRepresentations } from '../../../enums';
|
|
2
2
|
import { cache } from '@cornerstonejs/core';
|
|
3
|
+
import { ensureLabelmapState, syncLegacyLabelmapData, } from './labelmapSegmentationState';
|
|
3
4
|
function normalizeSegmentationInput(segmentationInput) {
|
|
4
5
|
const { segmentationId, representation, config } = segmentationInput;
|
|
5
6
|
const { type, data: inputData } = representation;
|
|
@@ -12,17 +13,27 @@ function normalizeSegmentationInput(segmentationInput) {
|
|
|
12
13
|
}
|
|
13
14
|
const normalizedSegments = normalizeSegments(config?.segments, type, data);
|
|
14
15
|
delete config?.segments;
|
|
15
|
-
|
|
16
|
+
const segmentation = {
|
|
16
17
|
segmentationId,
|
|
17
18
|
label: config?.label ?? null,
|
|
19
|
+
fallbackLabel: config?.fallbackLabel ?? null,
|
|
18
20
|
cachedStats: config?.cachedStats ?? {},
|
|
19
21
|
segments: normalizedSegments,
|
|
22
|
+
segmentOrder: config?.segmentOrder ??
|
|
23
|
+
Object.keys(normalizedSegments)
|
|
24
|
+
.map(Number)
|
|
25
|
+
.sort((a, b) => a - b),
|
|
20
26
|
representationData: {
|
|
21
27
|
[type]: {
|
|
22
28
|
...data,
|
|
23
29
|
},
|
|
24
30
|
},
|
|
25
31
|
};
|
|
32
|
+
if (type === SegmentationRepresentations.Labelmap) {
|
|
33
|
+
ensureLabelmapState(segmentation);
|
|
34
|
+
syncLegacyLabelmapData(segmentation);
|
|
35
|
+
}
|
|
36
|
+
return segmentation;
|
|
26
37
|
}
|
|
27
38
|
function normalizeContourData(contourData) {
|
|
28
39
|
contourData.geometryIds = contourData.geometryIds ?? [];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getEnabledElementByViewportId } from '@cornerstonejs/core';
|
|
1
|
+
import { getEnabledElementByViewportId, utilities } from '@cornerstonejs/core';
|
|
2
2
|
import CORNERSTONE_COLOR_LUT from '../../constants/COLOR_LUT';
|
|
3
3
|
import { triggerAnnotationRenderForViewportIds } from '../../utilities/triggerAnnotationRenderForViewportIds';
|
|
4
4
|
import { SegmentationRepresentations } from '../../enums';
|
|
@@ -40,7 +40,7 @@ function internalAddSegmentationRepresentation(viewportId, representationInput)
|
|
|
40
40
|
function getColorLUTIndex(config) {
|
|
41
41
|
const { colorLUTOrIndex } = config || {};
|
|
42
42
|
if (colorLUTOrIndex === undefined) {
|
|
43
|
-
const index = addColorLUT(
|
|
43
|
+
const index = addColorLUT(utilities.deepClone(CORNERSTONE_COLOR_LUT));
|
|
44
44
|
return index;
|
|
45
45
|
}
|
|
46
46
|
if (typeof colorLUTOrIndex === 'number') {
|
|
@@ -51,7 +51,7 @@ function getColorLUTIndex(config) {
|
|
|
51
51
|
const index = addColorLUT(colorLUTOrIndex);
|
|
52
52
|
return index;
|
|
53
53
|
}
|
|
54
|
-
const index = addColorLUT(
|
|
54
|
+
const index = addColorLUT(utilities.deepClone(CORNERSTONE_COLOR_LUT));
|
|
55
55
|
return index;
|
|
56
56
|
}
|
|
57
57
|
export { internalAddSegmentationRepresentation };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { SOURCE_REPRESENTATION_NAME, ensureLabelmapState, getPrimaryLabelmapId, getSegmentOrder, } from './normalizeLabelmapSegmentationData';
|
|
2
|
+
export type { LabelmapSegmentationWithState } from './normalizeLabelmapSegmentationData';
|
|
3
|
+
export { getConstructorNameForLabelmap, getLabelmap, getLabelmapDataById, getLabelmapForImageId, getLabelmapForVolumeId, getLabelmapIds, getLabelmaps, getOrCreateLabelmapVolume, getScalarArrayLengthFromLabelmap, registerLabelmap, removeLabelmap, } from './labelmapLayerStore';
|
|
4
|
+
export { getReferencedImageIdToCurrentImageIdMap, syncLegacyLabelmapData, } from './labelmapLegacyAdapter';
|
|
5
|
+
export { getLabelmapForSegment, getLabelValueForSegment, getSegmentBinding, getSegmentIndexForLabelValue, getSegmentsOnLabelmap, removeSegmentBinding, resolveLabelmapForSegment, setSegmentBinding, } from './labelmapSegmentBindings';
|
|
6
|
+
export { createPrivateLabelmap, moveSegmentToPrivateLabelmap, } from './privateLabelmap';
|
|
7
|
+
export { beginLabelmapEditTransaction, collectCrossLayerEraseBindings, eraseLabelmapEditTransactionOverwrites, getLabelmapLayerImageId, getProtectedSegmentIndicesForLayer, hasProtectedSegmentOverwrite, resolveLabelmapLayerEditTarget, } from './labelmapEditTransaction';
|
|
8
|
+
export type { BeginLabelmapEditTransactionOptions, EraseLabelmapEditTransactionOptions, LabelmapEditTransaction, LabelmapLayerEditTarget, ResolveLabelmapLayerEditTargetOptions, } from './labelmapEditTransaction';
|
|
9
|
+
export { default as LabelmapImageReferenceResolver } from './labelmapImageReferenceResolver';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { SOURCE_REPRESENTATION_NAME, ensureLabelmapState, getPrimaryLabelmapId, getSegmentOrder, } from './normalizeLabelmapSegmentationData';
|
|
2
|
+
export { getConstructorNameForLabelmap, getLabelmap, getLabelmapDataById, getLabelmapForImageId, getLabelmapForVolumeId, getLabelmapIds, getLabelmaps, getOrCreateLabelmapVolume, getScalarArrayLengthFromLabelmap, registerLabelmap, removeLabelmap, } from './labelmapLayerStore';
|
|
3
|
+
export { getReferencedImageIdToCurrentImageIdMap, syncLegacyLabelmapData, } from './labelmapLegacyAdapter';
|
|
4
|
+
export { getLabelmapForSegment, getLabelValueForSegment, getSegmentBinding, getSegmentIndexForLabelValue, getSegmentsOnLabelmap, removeSegmentBinding, resolveLabelmapForSegment, setSegmentBinding, } from './labelmapSegmentBindings';
|
|
5
|
+
export { createPrivateLabelmap, moveSegmentToPrivateLabelmap, } from './privateLabelmap';
|
|
6
|
+
export { beginLabelmapEditTransaction, collectCrossLayerEraseBindings, eraseLabelmapEditTransactionOverwrites, getLabelmapLayerImageId, getProtectedSegmentIndicesForLayer, hasProtectedSegmentOverwrite, resolveLabelmapLayerEditTarget, } from './labelmapEditTransaction';
|
|
7
|
+
export { default as LabelmapImageReferenceResolver } from './labelmapImageReferenceResolver';
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { Types } from '@cornerstonejs/core';
|
|
2
|
+
import type vtkImageData from '@kitware/vtk.js/Common/DataModel/ImageData';
|
|
3
|
+
import type { Segmentation } from '../../../types/SegmentationStateTypes';
|
|
4
|
+
import type { LabelmapLayer, SegmentLabelmapBindingState } from '../../../types/LabelmapTypes';
|
|
5
|
+
type MoveSegmentToPrivateLabelmap = (segmentation: Segmentation, segmentIndex: number) => LabelmapLayer | undefined;
|
|
6
|
+
type BeginLabelmapEditTransactionOptions = {
|
|
7
|
+
segmentIndex: number;
|
|
8
|
+
overwriteSegmentIndices?: number[];
|
|
9
|
+
segmentationVoxelManager?: Types.IVoxelManager<number>;
|
|
10
|
+
segmentationImageData?: vtkImageData;
|
|
11
|
+
isInObject?: (point: Types.Point3) => boolean;
|
|
12
|
+
isInObjectBoundsIJK?: Types.BoundsIJK;
|
|
13
|
+
moveSegmentToPrivateLabelmap?: MoveSegmentToPrivateLabelmap;
|
|
14
|
+
};
|
|
15
|
+
type LabelmapEditTransaction = {
|
|
16
|
+
segmentIndex: number;
|
|
17
|
+
labelmapId?: string;
|
|
18
|
+
labelValue: number;
|
|
19
|
+
sourceLayer?: LabelmapLayer;
|
|
20
|
+
activeLayer?: LabelmapLayer;
|
|
21
|
+
overwriteSegmentIndices: number[];
|
|
22
|
+
protectedSegmentIndices: number[];
|
|
23
|
+
crossLayerEraseBindings: SegmentLabelmapBindingState[];
|
|
24
|
+
movedSegment: boolean;
|
|
25
|
+
};
|
|
26
|
+
type ResolveLabelmapLayerEditTargetOptions = {
|
|
27
|
+
viewport?: Types.IViewport;
|
|
28
|
+
imageId?: string;
|
|
29
|
+
sourceLayer?: LabelmapLayer;
|
|
30
|
+
preferVolume?: boolean;
|
|
31
|
+
};
|
|
32
|
+
type LabelmapLayerEditTarget = {
|
|
33
|
+
imageId?: string;
|
|
34
|
+
imageData?: vtkImageData;
|
|
35
|
+
voxelManager?: Types.IVoxelManager<number>;
|
|
36
|
+
volume?: Types.IImageVolume;
|
|
37
|
+
image?: Types.IImage;
|
|
38
|
+
};
|
|
39
|
+
type EraseLabelmapEditTransactionOptions = {
|
|
40
|
+
viewport: Types.IViewport;
|
|
41
|
+
referenceImageData: vtkImageData;
|
|
42
|
+
isInObject: (point: Types.Point3) => boolean;
|
|
43
|
+
isInObjectBoundsIJK?: Types.BoundsIJK;
|
|
44
|
+
imageId?: string;
|
|
45
|
+
};
|
|
46
|
+
declare function getProtectedSegmentIndicesForLayer(segmentation: Segmentation, labelmapId: string, segmentIndex: number, overwriteSegmentIndices?: number[]): number[];
|
|
47
|
+
declare function hasProtectedSegmentOverwrite(segmentation: Segmentation, labelmapId: string, protectedSegmentIndices: number[], voxelManager?: Types.IVoxelManager<number>, options?: Pick<BeginLabelmapEditTransactionOptions, 'segmentationImageData' | 'isInObject' | 'isInObjectBoundsIJK'>): boolean;
|
|
48
|
+
declare function collectCrossLayerEraseBindings(segmentation: Segmentation, labelmapId: string | undefined, overwriteSegmentIndices?: number[]): SegmentLabelmapBindingState[];
|
|
49
|
+
declare function beginLabelmapEditTransaction(segmentation: Segmentation, options: BeginLabelmapEditTransactionOptions): LabelmapEditTransaction;
|
|
50
|
+
declare function getLabelmapLayerImageId(layer: LabelmapLayer, options?: ResolveLabelmapLayerEditTargetOptions): string | undefined;
|
|
51
|
+
declare function resolveLabelmapLayerEditTarget(layer: LabelmapLayer, options?: ResolveLabelmapLayerEditTargetOptions): LabelmapLayerEditTarget;
|
|
52
|
+
declare function eraseLabelmapEditTransactionOverwrites(segmentation: Segmentation, transaction: LabelmapEditTransaction | undefined, options: EraseLabelmapEditTransactionOptions): number[];
|
|
53
|
+
export { beginLabelmapEditTransaction, collectCrossLayerEraseBindings, eraseLabelmapEditTransactionOverwrites, getLabelmapLayerImageId, getProtectedSegmentIndicesForLayer, hasProtectedSegmentOverwrite, resolveLabelmapLayerEditTarget, };
|
|
54
|
+
export type { BeginLabelmapEditTransactionOptions, EraseLabelmapEditTransactionOptions, LabelmapEditTransaction, LabelmapLayerEditTarget, ResolveLabelmapLayerEditTargetOptions, };
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { BaseVolumeViewport, cache } from '@cornerstonejs/core';
|
|
2
|
+
import { getLabelmap, getOrCreateLabelmapVolume } from './labelmapLayerStore';
|
|
3
|
+
import { getSegmentBinding, getSegmentIndexForLabelValue, getSegmentsOnLabelmap, } from './labelmapSegmentBindings';
|
|
4
|
+
import { moveSegmentToPrivateLabelmap as defaultMoveSegmentToPrivateLabelmap } from './privateLabelmap';
|
|
5
|
+
function getProtectedSegmentIndicesForLayer(segmentation, labelmapId, segmentIndex, overwriteSegmentIndices = []) {
|
|
6
|
+
return getSegmentsOnLabelmap(segmentation, labelmapId).filter((candidateSegmentIndex) => candidateSegmentIndex !== segmentIndex &&
|
|
7
|
+
!overwriteSegmentIndices.includes(candidateSegmentIndex));
|
|
8
|
+
}
|
|
9
|
+
function hasProtectedSegmentOverwrite(segmentation, labelmapId, protectedSegmentIndices, voxelManager, options = {}) {
|
|
10
|
+
if (!voxelManager || !protectedSegmentIndices.length) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
const protectedSet = new Set(protectedSegmentIndices);
|
|
14
|
+
let hasConflict = false;
|
|
15
|
+
voxelManager.forEach(({ value }) => {
|
|
16
|
+
if (!value || hasConflict) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const candidateSegmentIndex = getSegmentIndexForLabelValue(segmentation, labelmapId, Number(value));
|
|
20
|
+
if (candidateSegmentIndex && protectedSet.has(candidateSegmentIndex)) {
|
|
21
|
+
hasConflict = true;
|
|
22
|
+
}
|
|
23
|
+
}, {
|
|
24
|
+
imageData: options.segmentationImageData,
|
|
25
|
+
isInObject: options.isInObject,
|
|
26
|
+
boundsIJK: options.isInObjectBoundsIJK,
|
|
27
|
+
});
|
|
28
|
+
return hasConflict;
|
|
29
|
+
}
|
|
30
|
+
function collectCrossLayerEraseBindings(segmentation, labelmapId, overwriteSegmentIndices = []) {
|
|
31
|
+
if (!labelmapId || !overwriteSegmentIndices.length) {
|
|
32
|
+
return [];
|
|
33
|
+
}
|
|
34
|
+
return overwriteSegmentIndices
|
|
35
|
+
.map((overwriteSegmentIndex) => getSegmentBinding(segmentation, overwriteSegmentIndex))
|
|
36
|
+
.filter((binding) => !!binding && binding.labelmapId !== labelmapId);
|
|
37
|
+
}
|
|
38
|
+
function beginLabelmapEditTransaction(segmentation, options) {
|
|
39
|
+
const { segmentIndex } = options;
|
|
40
|
+
const overwriteSegmentIndices = options.overwriteSegmentIndices ?? [];
|
|
41
|
+
if (!segmentIndex) {
|
|
42
|
+
return {
|
|
43
|
+
segmentIndex,
|
|
44
|
+
labelValue: 0,
|
|
45
|
+
overwriteSegmentIndices,
|
|
46
|
+
protectedSegmentIndices: [],
|
|
47
|
+
crossLayerEraseBindings: [],
|
|
48
|
+
movedSegment: false,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
const binding = getSegmentBinding(segmentation, segmentIndex);
|
|
52
|
+
const sourceLayer = binding
|
|
53
|
+
? getLabelmap(segmentation, binding.labelmapId)
|
|
54
|
+
: undefined;
|
|
55
|
+
if (!binding || !sourceLayer) {
|
|
56
|
+
return {
|
|
57
|
+
segmentIndex,
|
|
58
|
+
labelValue: segmentIndex,
|
|
59
|
+
overwriteSegmentIndices,
|
|
60
|
+
protectedSegmentIndices: [],
|
|
61
|
+
crossLayerEraseBindings: [],
|
|
62
|
+
movedSegment: false,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
let activeLayer = sourceLayer;
|
|
66
|
+
let labelmapId = binding.labelmapId;
|
|
67
|
+
let labelValue = binding.labelValue;
|
|
68
|
+
let movedSegment = false;
|
|
69
|
+
const protectedSegmentIndices = getProtectedSegmentIndicesForLayer(segmentation, labelmapId, segmentIndex, overwriteSegmentIndices);
|
|
70
|
+
const shouldMoveSegment = hasProtectedSegmentOverwrite(segmentation, labelmapId, protectedSegmentIndices, options.segmentationVoxelManager, {
|
|
71
|
+
segmentationImageData: options.segmentationImageData,
|
|
72
|
+
isInObject: options.isInObject,
|
|
73
|
+
isInObjectBoundsIJK: options.isInObjectBoundsIJK,
|
|
74
|
+
});
|
|
75
|
+
if (shouldMoveSegment) {
|
|
76
|
+
const moveSegmentToPrivateLabelmap = options.moveSegmentToPrivateLabelmap ??
|
|
77
|
+
defaultMoveSegmentToPrivateLabelmap;
|
|
78
|
+
const privateLayer = moveSegmentToPrivateLabelmap(segmentation, segmentIndex);
|
|
79
|
+
const privateBinding = getSegmentBinding(segmentation, segmentIndex);
|
|
80
|
+
if (privateLayer && privateBinding) {
|
|
81
|
+
activeLayer = privateLayer;
|
|
82
|
+
labelmapId = privateBinding.labelmapId;
|
|
83
|
+
labelValue = privateBinding.labelValue;
|
|
84
|
+
movedSegment = privateLayer.labelmapId !== sourceLayer.labelmapId;
|
|
85
|
+
}
|
|
86
|
+
else if (privateLayer) {
|
|
87
|
+
activeLayer = privateLayer;
|
|
88
|
+
labelmapId = privateLayer.labelmapId;
|
|
89
|
+
labelValue = 1;
|
|
90
|
+
movedSegment = privateLayer.labelmapId !== sourceLayer.labelmapId;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
segmentIndex,
|
|
95
|
+
labelmapId,
|
|
96
|
+
labelValue,
|
|
97
|
+
sourceLayer,
|
|
98
|
+
activeLayer,
|
|
99
|
+
overwriteSegmentIndices,
|
|
100
|
+
protectedSegmentIndices,
|
|
101
|
+
crossLayerEraseBindings: collectCrossLayerEraseBindings(segmentation, labelmapId, overwriteSegmentIndices),
|
|
102
|
+
movedSegment,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function getViewportImageIds(viewport) {
|
|
106
|
+
const stackViewport = viewport;
|
|
107
|
+
return typeof stackViewport?.getImageIds === 'function'
|
|
108
|
+
? stackViewport.getImageIds()
|
|
109
|
+
: [];
|
|
110
|
+
}
|
|
111
|
+
function getCurrentViewportImageId(viewport) {
|
|
112
|
+
const stackViewport = viewport;
|
|
113
|
+
return typeof stackViewport?.getCurrentImageId === 'function'
|
|
114
|
+
? stackViewport.getCurrentImageId()
|
|
115
|
+
: undefined;
|
|
116
|
+
}
|
|
117
|
+
function getLayerImageIndex(layer, options) {
|
|
118
|
+
const currentImageId = options.imageId ?? getCurrentViewportImageId(options.viewport);
|
|
119
|
+
if (!currentImageId) {
|
|
120
|
+
return -1;
|
|
121
|
+
}
|
|
122
|
+
const sourceImageIndex = options.sourceLayer?.imageIds?.indexOf(currentImageId) ?? -1;
|
|
123
|
+
if (sourceImageIndex >= 0) {
|
|
124
|
+
return sourceImageIndex;
|
|
125
|
+
}
|
|
126
|
+
const layerImageIndex = layer.imageIds?.indexOf(currentImageId) ?? -1;
|
|
127
|
+
if (layerImageIndex >= 0) {
|
|
128
|
+
return layerImageIndex;
|
|
129
|
+
}
|
|
130
|
+
return getViewportImageIds(options.viewport).indexOf(currentImageId);
|
|
131
|
+
}
|
|
132
|
+
function getLabelmapLayerImageId(layer, options = {}) {
|
|
133
|
+
const targetIndex = getLayerImageIndex(layer, options);
|
|
134
|
+
return targetIndex >= 0 ? layer.imageIds?.[targetIndex] : layer.imageIds?.[0];
|
|
135
|
+
}
|
|
136
|
+
function resolveLabelmapLayerEditTarget(layer, options = {}) {
|
|
137
|
+
const imageId = getLabelmapLayerImageId(layer, options);
|
|
138
|
+
if (options.preferVolume ||
|
|
139
|
+
layer.volumeId ||
|
|
140
|
+
options.viewport instanceof BaseVolumeViewport) {
|
|
141
|
+
const volume = getOrCreateLabelmapVolume(layer);
|
|
142
|
+
return {
|
|
143
|
+
imageId,
|
|
144
|
+
imageData: volume?.imageData,
|
|
145
|
+
voxelManager: volume?.voxelManager,
|
|
146
|
+
volume,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
const image = imageId ? cache.getImage(imageId) : undefined;
|
|
150
|
+
return {
|
|
151
|
+
imageId,
|
|
152
|
+
voxelManager: image?.voxelManager,
|
|
153
|
+
image,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
function eraseVolumeLayer(layer, binding, options, modifiedSlices) {
|
|
157
|
+
const volume = getOrCreateLabelmapVolume(layer);
|
|
158
|
+
if (!volume) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
volume.voxelManager.forEach(({ value, index, pointIJK }) => {
|
|
162
|
+
if (value !== binding.labelValue) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const worldPoint = volume.imageData.indexToWorld(pointIJK);
|
|
166
|
+
if (!options.isInObject(worldPoint)) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
volume.voxelManager.setAtIndex(index, 0);
|
|
170
|
+
}, {
|
|
171
|
+
imageData: volume.imageData,
|
|
172
|
+
boundsIJK: options.isInObjectBoundsIJK,
|
|
173
|
+
});
|
|
174
|
+
volume.voxelManager
|
|
175
|
+
?.getArrayOfModifiedSlices?.()
|
|
176
|
+
?.forEach((sliceIndex) => modifiedSlices.add(sliceIndex));
|
|
177
|
+
}
|
|
178
|
+
function eraseStackLayer(layer, binding, options, modifiedSlices) {
|
|
179
|
+
const stackViewport = options.viewport;
|
|
180
|
+
const currentImageId = getCurrentViewportImageId(options.viewport) ?? options.imageId;
|
|
181
|
+
const { image, voxelManager } = resolveLabelmapLayerEditTarget(layer, {
|
|
182
|
+
viewport: options.viewport,
|
|
183
|
+
imageId: currentImageId,
|
|
184
|
+
});
|
|
185
|
+
if (!image || !voxelManager) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
voxelManager.forEach(({ value, index, pointIJK }) => {
|
|
189
|
+
if (value !== binding.labelValue) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
const worldPoint = options.referenceImageData.indexToWorld(pointIJK);
|
|
193
|
+
if (!options.isInObject(worldPoint)) {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
voxelManager.setAtIndex(index, 0);
|
|
197
|
+
}, {
|
|
198
|
+
imageData: options.referenceImageData,
|
|
199
|
+
boundsIJK: options.isInObjectBoundsIJK,
|
|
200
|
+
});
|
|
201
|
+
const currentSlice = stackViewport.getCurrentImageIdIndex?.();
|
|
202
|
+
if (typeof currentSlice === 'number') {
|
|
203
|
+
modifiedSlices.add(currentSlice);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
function eraseLabelmapEditTransactionOverwrites(segmentation, transaction, options) {
|
|
207
|
+
if (!transaction?.crossLayerEraseBindings?.length) {
|
|
208
|
+
return [];
|
|
209
|
+
}
|
|
210
|
+
const modifiedSlices = new Set();
|
|
211
|
+
transaction.crossLayerEraseBindings.forEach((binding) => {
|
|
212
|
+
const layer = getLabelmap(segmentation, binding.labelmapId);
|
|
213
|
+
if (!layer) {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
if (options.viewport instanceof BaseVolumeViewport || layer.volumeId) {
|
|
217
|
+
eraseVolumeLayer(layer, binding, options, modifiedSlices);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
eraseStackLayer(layer, binding, options, modifiedSlices);
|
|
221
|
+
});
|
|
222
|
+
return Array.from(modifiedSlices);
|
|
223
|
+
}
|
|
224
|
+
export { beginLabelmapEditTransaction, collectCrossLayerEraseBindings, eraseLabelmapEditTransactionOverwrites, getLabelmapLayerImageId, getProtectedSegmentIndicesForLayer, hasProtectedSegmentOverwrite, resolveLabelmapLayerEditTarget, };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { LabelmapLayer } from '../../../types/LabelmapTypes';
|
|
2
|
+
declare function getReferencedImageIdForImageIndex(layer: LabelmapLayer, imageIndex: number): string | undefined;
|
|
3
|
+
declare function forEachLabelmapImageReference(layer: LabelmapLayer, callback: (referencedImageId: string, labelmapImageId: string, imageIndex: number) => void): void;
|
|
4
|
+
declare function getLabelmapImageIdsForReferencedImageId(layer: LabelmapLayer, referencedImageId: string): string[];
|
|
5
|
+
declare function hasMultipleLabelmapImagesPerReferencedImageId(layer: LabelmapLayer): boolean;
|
|
6
|
+
export { forEachLabelmapImageReference, getLabelmapImageIdsForReferencedImageId, getReferencedImageIdForImageIndex, hasMultipleLabelmapImagesPerReferencedImageId, };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
function getReferencedImageIdForImageIndex(layer, imageIndex) {
|
|
2
|
+
const imageIds = layer.imageIds ?? [];
|
|
3
|
+
const referencedImageIds = layer.referencedImageIds ?? imageIds;
|
|
4
|
+
if (!referencedImageIds.length) {
|
|
5
|
+
return;
|
|
6
|
+
}
|
|
7
|
+
if (layer.referencedImageIds?.length &&
|
|
8
|
+
imageIds.length > referencedImageIds.length &&
|
|
9
|
+
imageIds.length % referencedImageIds.length === 0) {
|
|
10
|
+
return referencedImageIds[imageIndex % referencedImageIds.length];
|
|
11
|
+
}
|
|
12
|
+
return referencedImageIds[imageIndex];
|
|
13
|
+
}
|
|
14
|
+
function forEachLabelmapImageReference(layer, callback) {
|
|
15
|
+
layer.imageIds?.forEach((labelmapImageId, imageIndex) => {
|
|
16
|
+
const referencedImageId = getReferencedImageIdForImageIndex(layer, imageIndex);
|
|
17
|
+
if (!referencedImageId || !labelmapImageId) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
callback(referencedImageId, labelmapImageId, imageIndex);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
function getLabelmapImageIdsForReferencedImageId(layer, referencedImageId) {
|
|
24
|
+
const imageIds = [];
|
|
25
|
+
forEachLabelmapImageReference(layer, (candidateReference, imageId) => {
|
|
26
|
+
if (candidateReference === referencedImageId) {
|
|
27
|
+
imageIds.push(imageId);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
return imageIds;
|
|
31
|
+
}
|
|
32
|
+
function hasMultipleLabelmapImagesPerReferencedImageId(layer) {
|
|
33
|
+
const imageIdsByReference = new Map();
|
|
34
|
+
forEachLabelmapImageReference(layer, (referencedImageId) => {
|
|
35
|
+
imageIdsByReference.set(referencedImageId, (imageIdsByReference.get(referencedImageId) ?? 0) + 1);
|
|
36
|
+
});
|
|
37
|
+
return Array.from(imageIdsByReference.values()).some((count) => count > 1);
|
|
38
|
+
}
|
|
39
|
+
export { forEachLabelmapImageReference, getLabelmapImageIdsForReferencedImageId, getReferencedImageIdForImageIndex, hasMultipleLabelmapImagesPerReferencedImageId, };
|