@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.
- 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/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 -11
- package/dist/esm/stateManagement/segmentation/SegmentationStateManager.js +28 -166
- 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 +11 -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/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/tools/AdvancedMagnifyTool.js +1 -1
- package/dist/esm/tools/CrosshairsTool.js +5 -5
- package/dist/esm/tools/OrientationControllerTool.js +1 -1
- 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/VolumeCroppingTool.js +3 -2
- 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 +33 -31
- package/dist/esm/tools/annotation/ArrowAnnotateTool.js +30 -28
- package/dist/esm/tools/annotation/BidirectionalTool.js +51 -49
- package/dist/esm/tools/annotation/CircleROITool.js +49 -44
- 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 +42 -37
- 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 +1 -1
- package/dist/esm/tools/annotation/PlanarFreehandContourSegmentationTool.js +6 -4
- package/dist/esm/tools/annotation/PlanarFreehandROITool.js +1 -1
- package/dist/esm/tools/annotation/ProbeTool.js +51 -46
- package/dist/esm/tools/annotation/RectangleROITool.js +42 -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 +51 -49
- 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 -5
- 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/segmentation/BrushTool.d.ts +9 -2
- package/dist/esm/tools/segmentation/BrushTool.js +109 -25
- package/dist/esm/tools/segmentation/CircleScissorsTool.js +13 -6
- package/dist/esm/tools/segmentation/LabelmapBaseTool.d.ts +2 -3
- package/dist/esm/tools/segmentation/LabelmapBaseTool.js +77 -38
- 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 +5 -1
- 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 -15
- 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/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/LabelmapToolOperationData.d.ts +5 -0
- package/dist/esm/types/LabelmapTypes.d.ts +29 -6
- package/dist/esm/types/SegmentationStateTypes.d.ts +4 -0
- package/dist/esm/utilities/calibrateImageSpacing.js +17 -2
- package/dist/esm/utilities/contours/AnnotationToPointData.js +1 -1
- 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/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 +2 -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/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/package.json +10 -10
|
@@ -1,41 +1,31 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import addLabelmapToElement from './addLabelmapToElement';
|
|
3
|
-
import removeLabelmapFromElement from './removeLabelmapFromElement';
|
|
4
|
-
import { getActiveSegmentation } from '../../../stateManagement/segmentation/activeSegmentation';
|
|
5
|
-
import { getColorLUT } from '../../../stateManagement/segmentation/getColorLUT';
|
|
6
|
-
import { getCurrentLabelmapImageIdsForViewport } from '../../../stateManagement/segmentation/getCurrentLabelmapImageIdForViewport';
|
|
1
|
+
import { Enums as CoreEnums, eventTarget, getEnabledElementByViewportId, } from '@cornerstonejs/core';
|
|
7
2
|
import { getSegmentation } from '../../../stateManagement/segmentation/getSegmentation';
|
|
8
|
-
import { segmentationStyle } from '../../../stateManagement/segmentation/SegmentationStyle';
|
|
9
3
|
import SegmentationRepresentations from '../../../enums/SegmentationRepresentations';
|
|
10
|
-
import { internalGetHiddenSegmentIndices } from '../../../stateManagement/segmentation/helpers/internalGetHiddenSegmentIndices';
|
|
11
|
-
import { getActiveSegmentIndex } from '../../../stateManagement/segmentation/getActiveSegmentIndex';
|
|
12
4
|
import { getLabelmapActorEntries } from '../../../stateManagement/segmentation/helpers/getSegmentationActor';
|
|
13
5
|
import { getPolySeg } from '../../../config';
|
|
14
6
|
import { computeAndAddRepresentation } from '../../../utilities/segmentation/computeAndAddRepresentation';
|
|
15
7
|
import { triggerSegmentationDataModified } from '../../../stateManagement/segmentation/triggerSegmentationEvents';
|
|
16
8
|
import { defaultSegmentationStateManager } from '../../../stateManagement/segmentation/SegmentationStateManager';
|
|
17
|
-
|
|
18
|
-
|
|
9
|
+
import { removeLabelmapRepresentationFromViewport, resolveLabelmapRenderPlan, } from './labelmapRenderPlan';
|
|
10
|
+
import { MAX_NUMBER_COLORS, setLabelmapColorAndOpacity, } from './labelmapActorStyle';
|
|
11
|
+
export { MAX_NUMBER_COLORS };
|
|
12
|
+
const unsupportedImageMapperStates = new Map();
|
|
19
13
|
let polySegConversionInProgress = false;
|
|
20
14
|
function removeRepresentation(viewportId, segmentationId, renderImmediate = false) {
|
|
15
|
+
clearUnsupportedImageMapperError(viewportId, segmentationId);
|
|
21
16
|
const enabledElement = getEnabledElementByViewportId(viewportId);
|
|
22
|
-
labelMapConfigCache.forEach((value, key) => {
|
|
23
|
-
if (key.includes(segmentationId)) {
|
|
24
|
-
labelMapConfigCache.delete(key);
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
17
|
if (!enabledElement) {
|
|
28
18
|
return;
|
|
29
19
|
}
|
|
30
20
|
const { viewport } = enabledElement;
|
|
31
|
-
|
|
21
|
+
removeLabelmapRepresentationFromViewport(viewport, segmentationId);
|
|
32
22
|
if (!renderImmediate) {
|
|
33
23
|
return;
|
|
34
24
|
}
|
|
35
25
|
viewport.render();
|
|
36
26
|
}
|
|
37
27
|
async function render(viewport, representation) {
|
|
38
|
-
const { segmentationId
|
|
28
|
+
const { segmentationId } = representation;
|
|
39
29
|
const segmentation = getSegmentation(segmentationId);
|
|
40
30
|
if (!segmentation) {
|
|
41
31
|
console.warn('No segmentation found for segmentationId: ', segmentationId);
|
|
@@ -48,7 +38,9 @@ async function render(viewport, representation) {
|
|
|
48
38
|
!polySegConversionInProgress) {
|
|
49
39
|
polySegConversionInProgress = true;
|
|
50
40
|
const polySeg = getPolySeg();
|
|
51
|
-
labelmapData = await computeAndAddRepresentation(segmentationId, SegmentationRepresentations.Labelmap, () => polySeg.computeLabelmapData(segmentationId, {
|
|
41
|
+
labelmapData = await computeAndAddRepresentation(segmentationId, SegmentationRepresentations.Labelmap, () => polySeg.computeLabelmapData(segmentationId, {
|
|
42
|
+
viewport: viewport,
|
|
43
|
+
}), () => {
|
|
52
44
|
defaultSegmentationStateManager.processLabelmapRepresentationAddition(viewport.id, segmentationId);
|
|
53
45
|
setTimeout(() => {
|
|
54
46
|
triggerSegmentationDataModified(segmentationId);
|
|
@@ -65,208 +57,55 @@ async function render(viewport, representation) {
|
|
|
65
57
|
if (!labelmapData) {
|
|
66
58
|
return;
|
|
67
59
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if (!labelmapImageIds?.length) {
|
|
77
|
-
return;
|
|
60
|
+
const renderPlan = resolveLabelmapRenderPlan({
|
|
61
|
+
viewport,
|
|
62
|
+
segmentation,
|
|
63
|
+
representation,
|
|
64
|
+
});
|
|
65
|
+
if (renderPlan.kind === 'unsupported') {
|
|
66
|
+
if (labelmapActorEntries?.length) {
|
|
67
|
+
renderPlan.remove();
|
|
78
68
|
}
|
|
79
|
-
if (
|
|
80
|
-
|
|
69
|
+
if (renderPlan.unsupportedStateKey) {
|
|
70
|
+
reportUnsupportedImageMapperError(viewport.id, segmentationId, renderPlan.unsupportedStateKey);
|
|
81
71
|
}
|
|
82
|
-
|
|
72
|
+
return;
|
|
83
73
|
}
|
|
74
|
+
clearUnsupportedImageMapperError(viewport.id, segmentationId);
|
|
75
|
+
labelmapActorEntries = await renderPlan.reconcile({
|
|
76
|
+
actorEntries: labelmapActorEntries,
|
|
77
|
+
labelMapData: labelmapData,
|
|
78
|
+
});
|
|
84
79
|
if (!labelmapActorEntries?.length) {
|
|
85
80
|
return;
|
|
86
81
|
}
|
|
87
82
|
for (const labelmapActorEntry of labelmapActorEntries) {
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
function _setLabelmapColorAndOpacity(viewportId, labelmapActorEntry, segmentationRepresentation) {
|
|
92
|
-
const { segmentationId } = segmentationRepresentation;
|
|
93
|
-
const { cfun, ofun } = segmentationRepresentation.config;
|
|
94
|
-
const { colorLUTIndex } = segmentationRepresentation;
|
|
95
|
-
const activeSegmentation = getActiveSegmentation(viewportId);
|
|
96
|
-
const isActiveLabelmap = activeSegmentation?.segmentationId === segmentationId;
|
|
97
|
-
const labelmapStyle = segmentationStyle.getStyle({
|
|
98
|
-
viewportId,
|
|
99
|
-
type: SegmentationRepresentations.Labelmap,
|
|
100
|
-
segmentationId,
|
|
101
|
-
});
|
|
102
|
-
const renderInactiveSegmentations = segmentationStyle.getRenderInactiveSegmentations(viewportId);
|
|
103
|
-
const colorLUT = getColorLUT(colorLUTIndex);
|
|
104
|
-
const numColors = Math.min(256, colorLUT.length);
|
|
105
|
-
const { outlineWidth, renderOutline, outlineOpacity, activeSegmentOutlineWidthDelta, } = _getLabelmapConfig(labelmapStyle, isActiveLabelmap);
|
|
106
|
-
const segmentsHidden = internalGetHiddenSegmentIndices(viewportId, {
|
|
107
|
-
segmentationId,
|
|
108
|
-
type: SegmentationRepresentations.Labelmap,
|
|
109
|
-
});
|
|
110
|
-
for (let i = 0; i < numColors; i++) {
|
|
111
|
-
const segmentIndex = i;
|
|
112
|
-
const segmentColor = colorLUT[segmentIndex];
|
|
113
|
-
const perSegmentStyle = segmentationStyle.getStyle({
|
|
114
|
-
viewportId,
|
|
115
|
-
type: SegmentationRepresentations.Labelmap,
|
|
116
|
-
segmentationId,
|
|
117
|
-
segmentIndex,
|
|
118
|
-
});
|
|
119
|
-
const segmentSpecificLabelmapConfig = perSegmentStyle;
|
|
120
|
-
const { fillAlpha, outlineWidth, renderFill, renderOutline } = _getLabelmapConfig(labelmapStyle, isActiveLabelmap, segmentSpecificLabelmapConfig);
|
|
121
|
-
const { forceOpacityUpdate, forceColorUpdate } = _needsTransferFunctionUpdate(viewportId, segmentationId, segmentIndex, {
|
|
122
|
-
fillAlpha,
|
|
123
|
-
renderFill,
|
|
124
|
-
renderOutline,
|
|
125
|
-
segmentColor,
|
|
126
|
-
outlineWidth,
|
|
127
|
-
segmentsHidden: segmentsHidden,
|
|
128
|
-
cfun,
|
|
129
|
-
ofun,
|
|
130
|
-
});
|
|
131
|
-
if (forceColorUpdate) {
|
|
132
|
-
cfun.addRGBPoint(segmentIndex, segmentColor[0] / MAX_NUMBER_COLORS, segmentColor[1] / MAX_NUMBER_COLORS, segmentColor[2] / MAX_NUMBER_COLORS);
|
|
133
|
-
}
|
|
134
|
-
if (forceOpacityUpdate) {
|
|
135
|
-
if (renderFill) {
|
|
136
|
-
const segmentOpacity = segmentsHidden.has(segmentIndex)
|
|
137
|
-
? 0
|
|
138
|
-
: (segmentColor[3] / 255) * fillAlpha;
|
|
139
|
-
ofun.removePoint(segmentIndex);
|
|
140
|
-
ofun.addPointLong(segmentIndex, segmentOpacity, 0.5, 1.0);
|
|
141
|
-
}
|
|
142
|
-
else {
|
|
143
|
-
ofun.addPointLong(segmentIndex, 0.01, 0.5, 1.0);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
ofun.setClamping(false);
|
|
148
|
-
const labelmapActor = labelmapActorEntry.actor;
|
|
149
|
-
const { preLoad } = labelmapActor.get?.('preLoad') || { preLoad: null };
|
|
150
|
-
if (preLoad) {
|
|
151
|
-
preLoad({ cfun, ofun, actor: labelmapActor });
|
|
83
|
+
setLabelmapColorAndOpacity(viewport.id, labelmapActorEntry, representation);
|
|
152
84
|
}
|
|
153
|
-
else {
|
|
154
|
-
labelmapActor.getProperty().setRGBTransferFunction(0, cfun);
|
|
155
|
-
labelmapActor.getProperty().setScalarOpacity(0, ofun);
|
|
156
|
-
labelmapActor.getProperty().setInterpolationTypeToNearest();
|
|
157
|
-
}
|
|
158
|
-
if (renderOutline) {
|
|
159
|
-
labelmapActor.getProperty().setUseLabelOutline(renderOutline);
|
|
160
|
-
labelmapActor.getProperty().setLabelOutlineOpacity(outlineOpacity);
|
|
161
|
-
const activeSegmentIndex = getActiveSegmentIndex(segmentationRepresentation.segmentationId);
|
|
162
|
-
const outlineWidths = new Array(numColors - 1);
|
|
163
|
-
for (let i = 1; i < numColors; i++) {
|
|
164
|
-
const isHidden = segmentsHidden.has(i);
|
|
165
|
-
if (isHidden) {
|
|
166
|
-
outlineWidths[i - 1] = 0;
|
|
167
|
-
continue;
|
|
168
|
-
}
|
|
169
|
-
outlineWidths[i - 1] =
|
|
170
|
-
i === activeSegmentIndex
|
|
171
|
-
? outlineWidth + activeSegmentOutlineWidthDelta
|
|
172
|
-
: outlineWidth;
|
|
173
|
-
}
|
|
174
|
-
labelmapActor.getProperty().setLabelOutlineThickness(outlineWidths);
|
|
175
|
-
labelmapActor.modified();
|
|
176
|
-
labelmapActor.getProperty().modified();
|
|
177
|
-
labelmapActor.getMapper().modified();
|
|
178
|
-
}
|
|
179
|
-
else {
|
|
180
|
-
labelmapActor
|
|
181
|
-
.getProperty()
|
|
182
|
-
.setLabelOutlineThickness(new Array(numColors - 1).fill(0));
|
|
183
|
-
}
|
|
184
|
-
const visible = isActiveLabelmap || renderInactiveSegmentations;
|
|
185
|
-
labelmapActor.setVisibility(visible);
|
|
186
85
|
}
|
|
187
|
-
function
|
|
188
|
-
|
|
189
|
-
const configToUse = {
|
|
190
|
-
...labelmapConfig,
|
|
191
|
-
...segmentLabelmapConfig,
|
|
192
|
-
};
|
|
193
|
-
const fillAlpha = isActiveLabelmap
|
|
194
|
-
? configToUse.fillAlpha
|
|
195
|
-
: configToUse.fillAlphaInactive;
|
|
196
|
-
const outlineWidth = isActiveLabelmap
|
|
197
|
-
? configToUse.outlineWidth
|
|
198
|
-
: configToUse.outlineWidthInactive;
|
|
199
|
-
const renderFill = isActiveLabelmap
|
|
200
|
-
? configToUse.renderFill
|
|
201
|
-
: configToUse.renderFillInactive;
|
|
202
|
-
const renderOutline = isActiveLabelmap
|
|
203
|
-
? configToUse.renderOutline
|
|
204
|
-
: configToUse.renderOutlineInactive;
|
|
205
|
-
const outlineOpacity = isActiveLabelmap
|
|
206
|
-
? configToUse.outlineOpacity
|
|
207
|
-
: configToUse.outlineOpacityInactive;
|
|
208
|
-
const activeSegmentOutlineWidthDelta = configToUse.activeSegmentOutlineWidthDelta;
|
|
209
|
-
return {
|
|
210
|
-
fillAlpha,
|
|
211
|
-
outlineWidth,
|
|
212
|
-
renderFill,
|
|
213
|
-
renderOutline,
|
|
214
|
-
outlineOpacity,
|
|
215
|
-
activeSegmentOutlineWidthDelta,
|
|
216
|
-
};
|
|
86
|
+
function getUpdateFunction(_viewport) {
|
|
87
|
+
return;
|
|
217
88
|
}
|
|
218
|
-
function
|
|
219
|
-
|
|
220
|
-
const oldConfig = labelMapConfigCache.get(cacheUID);
|
|
221
|
-
if (!oldConfig) {
|
|
222
|
-
labelMapConfigCache.set(cacheUID, {
|
|
223
|
-
fillAlpha,
|
|
224
|
-
renderFill,
|
|
225
|
-
renderOutline,
|
|
226
|
-
outlineWidth,
|
|
227
|
-
segmentColor: segmentColor.slice(),
|
|
228
|
-
segmentsHidden: new Set(segmentsHidden),
|
|
229
|
-
cfunMTime: cfun.getMTime(),
|
|
230
|
-
ofunMTime: ofun.getMTime(),
|
|
231
|
-
});
|
|
232
|
-
return {
|
|
233
|
-
forceOpacityUpdate: true,
|
|
234
|
-
forceColorUpdate: true,
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
const { fillAlpha: oldFillAlpha, renderFill: oldRenderFill, renderOutline: oldRenderOutline, outlineWidth: oldOutlineWidth, segmentColor: oldSegmentColor, segmentsHidden: oldSegmentsHidden, cfunMTime: oldCfunMTime, ofunMTime: oldOfunMTime, } = oldConfig;
|
|
238
|
-
const forceColorUpdate = oldSegmentColor[0] !== segmentColor[0] ||
|
|
239
|
-
oldSegmentColor[1] !== segmentColor[1] ||
|
|
240
|
-
oldSegmentColor[2] !== segmentColor[2];
|
|
241
|
-
const forceOpacityUpdate = oldSegmentColor[3] !== segmentColor[3] ||
|
|
242
|
-
oldFillAlpha !== fillAlpha ||
|
|
243
|
-
oldRenderFill !== renderFill ||
|
|
244
|
-
oldRenderOutline !== renderOutline ||
|
|
245
|
-
oldOutlineWidth !== outlineWidth ||
|
|
246
|
-
oldSegmentsHidden !== segmentsHidden;
|
|
247
|
-
if (forceOpacityUpdate || forceColorUpdate) {
|
|
248
|
-
labelMapConfigCache.set(cacheUID, {
|
|
249
|
-
fillAlpha,
|
|
250
|
-
renderFill,
|
|
251
|
-
renderOutline,
|
|
252
|
-
outlineWidth,
|
|
253
|
-
segmentColor: segmentColor.slice(),
|
|
254
|
-
segmentsHidden: new Set(segmentsHidden),
|
|
255
|
-
cfunMTime: cfun.getMTime(),
|
|
256
|
-
ofunMTime: ofun.getMTime(),
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
return {
|
|
260
|
-
forceOpacityUpdate,
|
|
261
|
-
forceColorUpdate,
|
|
262
|
-
};
|
|
89
|
+
function getUnsupportedImageMapperStateKey(viewportId, segmentationId) {
|
|
90
|
+
return `${viewportId}:${segmentationId}`;
|
|
263
91
|
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
return result || undefined;
|
|
92
|
+
function clearUnsupportedImageMapperError(viewportId, segmentationId) {
|
|
93
|
+
unsupportedImageMapperStates.delete(getUnsupportedImageMapperStateKey(viewportId, segmentationId));
|
|
267
94
|
}
|
|
268
|
-
function
|
|
269
|
-
|
|
95
|
+
function reportUnsupportedImageMapperError(viewportId, segmentationId, stateKey) {
|
|
96
|
+
const cacheKey = getUnsupportedImageMapperStateKey(viewportId, segmentationId);
|
|
97
|
+
const previousStateKey = unsupportedImageMapperStates.get(cacheKey);
|
|
98
|
+
if (previousStateKey === stateKey) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
unsupportedImageMapperStates.set(cacheKey, stateKey);
|
|
102
|
+
eventTarget.dispatchEvent(new CustomEvent(CoreEnums.Events.ERROR_EVENT, {
|
|
103
|
+
detail: {
|
|
104
|
+
type: 'Segmentation',
|
|
105
|
+
message: 'Labelmap image-mapper rendering is only supported on legacy orthographic single-slice volume viewports.',
|
|
106
|
+
},
|
|
107
|
+
cancelable: true,
|
|
108
|
+
}));
|
|
270
109
|
}
|
|
271
110
|
export default {
|
|
272
111
|
getUpdateFunction,
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { CreateLabelmapRenderPlanArgs, LabelmapRenderPlan } from './types';
|
|
2
|
+
declare function createLabelmapRenderPlan({ isVolumeImageMapper, kind, renderMode, segmentationId, unsupportedStateKey, updateAfterMount, useSliceRendering, viewport, canRenderCurrentViewport, getExpectedRepresentationUIDs, mount, update, }: CreateLabelmapRenderPlanArgs): LabelmapRenderPlan;
|
|
3
|
+
export { createLabelmapRenderPlan };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { getLabelmapActorEntries } from '../../../../stateManagement/segmentation/helpers/getSegmentationActor';
|
|
2
|
+
import { removeLabelmapRepresentationFromViewport } from './removeLabelmapRepresentationFromViewport';
|
|
3
|
+
function createLabelmapRenderPlan({ isVolumeImageMapper, kind, renderMode, segmentationId, unsupportedStateKey, updateAfterMount = true, useSliceRendering, viewport, canRenderCurrentViewport = () => kind !== 'unsupported', getExpectedRepresentationUIDs = () => [], mount = async () => undefined, update = () => undefined, }) {
|
|
4
|
+
const remove = () => removeLabelmapRepresentationFromViewport(viewport, segmentationId);
|
|
5
|
+
const needsRemount = (actorEntries) => haveActorUIDsChanged(actorEntries, getExpectedRepresentationUIDs());
|
|
6
|
+
return {
|
|
7
|
+
kind,
|
|
8
|
+
renderMode,
|
|
9
|
+
useSliceRendering,
|
|
10
|
+
isVolumeImageMapper,
|
|
11
|
+
unsupportedStateKey,
|
|
12
|
+
getExpectedRepresentationUIDs,
|
|
13
|
+
mount,
|
|
14
|
+
needsRemount,
|
|
15
|
+
remove,
|
|
16
|
+
update,
|
|
17
|
+
reconcile: async ({ actorEntries, labelMapData }) => {
|
|
18
|
+
if (!canRenderCurrentViewport()) {
|
|
19
|
+
return actorEntries;
|
|
20
|
+
}
|
|
21
|
+
let nextActorEntries = actorEntries;
|
|
22
|
+
if (needsRemount(nextActorEntries) && nextActorEntries?.length) {
|
|
23
|
+
remove();
|
|
24
|
+
nextActorEntries = undefined;
|
|
25
|
+
}
|
|
26
|
+
const mounted = !nextActorEntries?.length;
|
|
27
|
+
if (mounted) {
|
|
28
|
+
await mount({ labelMapData });
|
|
29
|
+
}
|
|
30
|
+
nextActorEntries = getLabelmapActorEntries(viewport.id, segmentationId);
|
|
31
|
+
if (nextActorEntries?.length && (!mounted || updateAfterMount)) {
|
|
32
|
+
update({ actorEntries: nextActorEntries });
|
|
33
|
+
}
|
|
34
|
+
return nextActorEntries;
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function haveActorUIDsChanged(actorEntries, expectedRepresentationUIDs) {
|
|
39
|
+
const actualUIDs = new Set((actorEntries ?? []).map((entry) => entry.representationUID));
|
|
40
|
+
const expectedUIDs = new Set(expectedRepresentationUIDs);
|
|
41
|
+
if (actualUIDs.size !== expectedUIDs.size) {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
for (const expectedUID of expectedUIDs) {
|
|
45
|
+
if (!actualUIDs.has(expectedUID)) {
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
export { createLabelmapRenderPlan };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { createLabelmapRenderPlan } from './createLabelmapRenderPlan';
|
|
2
|
+
export { removeLabelmapRepresentationFromViewport } from './removeLabelmapRepresentationFromViewport';
|
|
3
|
+
export { resolveLabelmapRenderPlan } from './resolveLabelmapRenderPlan';
|
|
4
|
+
export type { LabelmapRenderPlan, LabelmapRenderPlanKind, LabelmapRenderPlanMountResult, } from './types';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type Types } from '@cornerstonejs/core';
|
|
2
|
+
import type { ViewportLabelmapRenderMode } from '../../../../stateManagement/segmentation/helpers/getViewportLabelmapRenderMode';
|
|
3
|
+
import type { LabelmapRenderingConfig, Segmentation } from '../../../../types/SegmentationStateTypes';
|
|
4
|
+
import type { LabelmapRenderPlan } from './types';
|
|
5
|
+
declare function createLegacyVolumeLabelmapPlan({ config, isVolumeImageMapper, renderMode, segmentation, segmentationId, useSliceRendering, viewport, }: {
|
|
6
|
+
config: LabelmapRenderingConfig;
|
|
7
|
+
isVolumeImageMapper: boolean;
|
|
8
|
+
renderMode: ViewportLabelmapRenderMode;
|
|
9
|
+
segmentation: Segmentation;
|
|
10
|
+
segmentationId: string;
|
|
11
|
+
useSliceRendering: boolean;
|
|
12
|
+
viewport: Types.IViewport;
|
|
13
|
+
}): LabelmapRenderPlan;
|
|
14
|
+
export { createLegacyVolumeLabelmapPlan };
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { addVolumesToViewports, Enums, cache, volumeLoader, utilities, } from '@cornerstonejs/core';
|
|
2
|
+
import { triggerSegmentationDataModified, triggerSegmentationModified, } from '../../../../stateManagement/segmentation/triggerSegmentationEvents';
|
|
3
|
+
import { getLabelmaps, getOrCreateLabelmapVolume, } from '../../../../stateManagement/segmentation/helpers/labelmapSegmentationState';
|
|
4
|
+
import { addVolumesAsIndependentComponents } from '../addVolumesAsIndependentComponents';
|
|
5
|
+
import { createLabelmapRepresentationUID } from '../labelmapRepresentationUID';
|
|
6
|
+
import { createLabelmapRenderPlan } from './createLabelmapRenderPlan';
|
|
7
|
+
import { addLabelmapToPlanarGenericViewport, isPlanarNextVolumeViewport, } from './planarGenericVolumeLabelmap';
|
|
8
|
+
const { uuidv4 } = utilities;
|
|
9
|
+
function createLegacyVolumeLabelmapPlan({ config, isVolumeImageMapper, renderMode, segmentation, segmentationId, useSliceRendering, viewport, }) {
|
|
10
|
+
return createLabelmapRenderPlan({
|
|
11
|
+
isVolumeImageMapper,
|
|
12
|
+
kind: 'legacy-volume',
|
|
13
|
+
renderMode,
|
|
14
|
+
segmentationId,
|
|
15
|
+
useSliceRendering,
|
|
16
|
+
viewport,
|
|
17
|
+
getExpectedRepresentationUIDs: () => getExpectedVolumeLabelmapRepresentationUIDs(segmentation, segmentationId),
|
|
18
|
+
mount: ({ labelMapData }) => mountLegacyVolumeLabelmap({
|
|
19
|
+
config,
|
|
20
|
+
labelMapData,
|
|
21
|
+
segmentation,
|
|
22
|
+
segmentationId,
|
|
23
|
+
viewport,
|
|
24
|
+
}),
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
function getExpectedVolumeLabelmapRepresentationUIDs(segmentation, segmentationId) {
|
|
28
|
+
return getLabelmaps(segmentation)
|
|
29
|
+
.filter(canResolveLayerAsVolume)
|
|
30
|
+
.map((layer) => createLabelmapRepresentationUID({
|
|
31
|
+
segmentationId,
|
|
32
|
+
referencedId: layer.labelmapId,
|
|
33
|
+
}));
|
|
34
|
+
}
|
|
35
|
+
async function mountLegacyVolumeLabelmap({ config, labelMapData, segmentation, segmentationId, viewport, }) {
|
|
36
|
+
const { id: viewportId } = viewport;
|
|
37
|
+
const visibility = true;
|
|
38
|
+
const immediateRender = false;
|
|
39
|
+
const suppressEvents = true;
|
|
40
|
+
const volumeCompatibleViewport = viewport;
|
|
41
|
+
const labelmapLayers = getVolumeBackedLabelmapLayers(segmentation);
|
|
42
|
+
if (!labelmapLayers.length) {
|
|
43
|
+
const volumeLabelMapData = labelMapData;
|
|
44
|
+
const volumeId = ensureVolumeHasVolumeId(volumeLabelMapData, segmentation);
|
|
45
|
+
if (!cache.getVolume(volumeId)) {
|
|
46
|
+
await handleMissingVolume(labelMapData);
|
|
47
|
+
}
|
|
48
|
+
labelmapLayers.push({
|
|
49
|
+
labelmapId: volumeId,
|
|
50
|
+
type: 'volume',
|
|
51
|
+
volumeId,
|
|
52
|
+
imageIds: cache.getVolume(volumeId)?.imageIds,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
let blendMode = config?.blendMode ?? Enums.BlendModes.MAXIMUM_INTENSITY_BLEND;
|
|
56
|
+
let useIndependentComponents = blendMode === Enums.BlendModes.LABELMAP_EDGE_PROJECTION_BLEND;
|
|
57
|
+
if (useIndependentComponents) {
|
|
58
|
+
const referenceVolumeId = volumeCompatibleViewport.getVolumeId?.();
|
|
59
|
+
const baseVolume = cache.getVolume(referenceVolumeId);
|
|
60
|
+
const segVolume = cache.getVolume(labelmapLayers[0]?.volumeId);
|
|
61
|
+
const segDims = segVolume.dimensions;
|
|
62
|
+
const refDims = baseVolume.dimensions;
|
|
63
|
+
if (segDims[0] !== refDims[0] ||
|
|
64
|
+
segDims[1] !== refDims[1] ||
|
|
65
|
+
segDims[2] !== refDims[2]) {
|
|
66
|
+
useIndependentComponents = false;
|
|
67
|
+
blendMode = Enums.BlendModes.MAXIMUM_INTENSITY_BLEND;
|
|
68
|
+
console.debug('Dimensions mismatch - falling back to regular volume addition');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const volumeInputs = labelmapLayers.map((layer) => ({
|
|
72
|
+
volumeId: layer.volumeId,
|
|
73
|
+
visibility,
|
|
74
|
+
representationUID: createLabelmapRepresentationUID({
|
|
75
|
+
segmentationId,
|
|
76
|
+
referencedId: layer.labelmapId,
|
|
77
|
+
}),
|
|
78
|
+
useIndependentComponents,
|
|
79
|
+
blendMode,
|
|
80
|
+
}));
|
|
81
|
+
if (isPlanarNextVolumeViewport(viewport)) {
|
|
82
|
+
return addLabelmapToPlanarGenericViewport({
|
|
83
|
+
blendMode,
|
|
84
|
+
labelmapLayers,
|
|
85
|
+
segmentationId,
|
|
86
|
+
viewport,
|
|
87
|
+
visibility,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
if (!volumeInputs[0].useIndependentComponents) {
|
|
91
|
+
await addVolumesToViewports(viewport.getRenderingEngine(), volumeInputs, [viewportId], immediateRender, suppressEvents);
|
|
92
|
+
triggerSegmentationDataModified(segmentationId);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
return addVolumesAsIndependentComponents({
|
|
96
|
+
viewport: volumeCompatibleViewport,
|
|
97
|
+
volumeInputs,
|
|
98
|
+
segmentationId,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
function canResolveLayerAsVolume(layer) {
|
|
102
|
+
return Boolean(layer.volumeId || layer.geometryVolumeId || layer.imageIds?.length);
|
|
103
|
+
}
|
|
104
|
+
function getVolumeBackedLabelmapLayers(segmentation) {
|
|
105
|
+
return getLabelmaps(segmentation)
|
|
106
|
+
.map((layer) => {
|
|
107
|
+
if (layer.volumeId) {
|
|
108
|
+
return layer;
|
|
109
|
+
}
|
|
110
|
+
const volume = getOrCreateLabelmapVolume(layer);
|
|
111
|
+
if (!volume?.volumeId) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
...layer,
|
|
116
|
+
volumeId: volume.volumeId,
|
|
117
|
+
};
|
|
118
|
+
})
|
|
119
|
+
.filter((layer) => Boolean(layer));
|
|
120
|
+
}
|
|
121
|
+
function ensureVolumeHasVolumeId(labelMapData, segmentation) {
|
|
122
|
+
let { volumeId } = labelMapData;
|
|
123
|
+
if (!volumeId) {
|
|
124
|
+
volumeId = uuidv4();
|
|
125
|
+
segmentation.representationData.Labelmap = {
|
|
126
|
+
...segmentation.representationData.Labelmap,
|
|
127
|
+
volumeId,
|
|
128
|
+
};
|
|
129
|
+
labelMapData.volumeId = volumeId;
|
|
130
|
+
triggerSegmentationModified(segmentation.segmentationId);
|
|
131
|
+
}
|
|
132
|
+
return volumeId;
|
|
133
|
+
}
|
|
134
|
+
async function handleMissingVolume(labelMapData) {
|
|
135
|
+
const stackData = labelMapData;
|
|
136
|
+
const hasImageIds = stackData.imageIds.length > 0;
|
|
137
|
+
if (!hasImageIds) {
|
|
138
|
+
throw new Error('cannot create labelmap, no imageIds found for the volume labelmap');
|
|
139
|
+
}
|
|
140
|
+
const volume = await volumeLoader.createAndCacheVolumeFromImages(labelMapData.volumeId ?? uuidv4(), stackData.imageIds);
|
|
141
|
+
return volume;
|
|
142
|
+
}
|
|
143
|
+
export { createLegacyVolumeLabelmapPlan };
|
package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/planarGenericVolumeLabelmap.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type Types, Enums } from '@cornerstonejs/core';
|
|
2
|
+
import type { LabelmapRenderPlanMountResult } from './types';
|
|
3
|
+
type PlanarNextVolumeViewport = Types.IViewport & {
|
|
4
|
+
getCurrentImageIdIndex?: () => number;
|
|
5
|
+
getDefaultActor?: () => (Types.ActorEntry & {
|
|
6
|
+
actorMapper?: {
|
|
7
|
+
renderMode?: Types.ActorRenderMode;
|
|
8
|
+
};
|
|
9
|
+
}) | undefined;
|
|
10
|
+
getVolumeId: () => string | undefined;
|
|
11
|
+
getViewReference: (specifier?: Types.ViewReferenceSpecifier) => Types.ViewReference;
|
|
12
|
+
getViewState: () => {
|
|
13
|
+
orientation?: unknown;
|
|
14
|
+
};
|
|
15
|
+
getActors?: () => Types.ActorEntry[];
|
|
16
|
+
render?: () => void;
|
|
17
|
+
addDisplaySet: (displaySetId: string, options: {
|
|
18
|
+
orientation?: unknown;
|
|
19
|
+
role?: 'source' | 'overlay';
|
|
20
|
+
}) => Promise<void>;
|
|
21
|
+
setDisplaySetPresentation: (dataId: string, props: {
|
|
22
|
+
blendMode?: Enums.BlendModes;
|
|
23
|
+
visible?: boolean;
|
|
24
|
+
}) => void;
|
|
25
|
+
setViewReference: (viewReference: Types.ViewReference) => void;
|
|
26
|
+
type: string;
|
|
27
|
+
};
|
|
28
|
+
declare function isPlanarNextVolumeViewport(viewport: Types.IViewport): viewport is PlanarNextVolumeViewport;
|
|
29
|
+
declare function addLabelmapToPlanarGenericViewport(args: {
|
|
30
|
+
blendMode: Enums.BlendModes;
|
|
31
|
+
labelmapLayers: Array<{
|
|
32
|
+
imageIds?: string[];
|
|
33
|
+
labelmapId: string;
|
|
34
|
+
volumeId?: string;
|
|
35
|
+
}>;
|
|
36
|
+
segmentationId: string;
|
|
37
|
+
viewport: PlanarNextVolumeViewport;
|
|
38
|
+
visibility: boolean;
|
|
39
|
+
}): Promise<LabelmapRenderPlanMountResult>;
|
|
40
|
+
export { addLabelmapToPlanarGenericViewport, isPlanarNextVolumeViewport, type PlanarNextVolumeViewport, };
|
package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/planarGenericVolumeLabelmap.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { ActorRenderMode, Enums, cache, utilities, } from '@cornerstonejs/core';
|
|
2
|
+
import { createLabelmapRepresentationUID } from '../labelmapRepresentationUID';
|
|
3
|
+
function isPlanarNextVolumeViewport(viewport) {
|
|
4
|
+
const genericViewport = viewport;
|
|
5
|
+
return (genericViewport.type === Enums.ViewportType.PLANAR_NEXT &&
|
|
6
|
+
typeof genericViewport.getVolumeId === 'function' &&
|
|
7
|
+
typeof genericViewport.getViewReference === 'function' &&
|
|
8
|
+
typeof genericViewport.getViewState === 'function' &&
|
|
9
|
+
typeof genericViewport.addDisplaySet === 'function' &&
|
|
10
|
+
typeof genericViewport.setDisplaySetPresentation === 'function' &&
|
|
11
|
+
typeof genericViewport.setViewReference === 'function');
|
|
12
|
+
}
|
|
13
|
+
async function addLabelmapToPlanarGenericViewport(args) {
|
|
14
|
+
const { blendMode, labelmapLayers, segmentationId, viewport, visibility } = args;
|
|
15
|
+
const sourceVolumeRenderMode = getPlanarNextVolumeRenderMode(viewport);
|
|
16
|
+
if (!sourceVolumeRenderMode) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const sourceVolumeId = viewport.getVolumeId();
|
|
20
|
+
const sourceViewReference = sourceVolumeId
|
|
21
|
+
? viewport.getViewReference({ volumeId: sourceVolumeId })
|
|
22
|
+
: viewport.getViewReference();
|
|
23
|
+
const requestedOrientation = viewport.getViewState().orientation;
|
|
24
|
+
const currentImageIdIndex = Math.max(0, viewport.getCurrentImageIdIndex?.() ?? 0);
|
|
25
|
+
let firstActorEntry;
|
|
26
|
+
for (const layer of labelmapLayers) {
|
|
27
|
+
if (!layer.volumeId) {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
const volume = cache.getVolume(layer.volumeId);
|
|
31
|
+
if (!volume) {
|
|
32
|
+
throw new Error(`imageVolume with id: ${layer.volumeId} does not exist, you need to create/allocate the volume first`);
|
|
33
|
+
}
|
|
34
|
+
const representationUID = createLabelmapRepresentationUID({
|
|
35
|
+
segmentationId,
|
|
36
|
+
referencedId: layer.labelmapId,
|
|
37
|
+
});
|
|
38
|
+
const dataId = representationUID;
|
|
39
|
+
utilities.genericViewportDataSetMetadataProvider.add(dataId, {
|
|
40
|
+
kind: 'planar',
|
|
41
|
+
imageIds: volume.imageIds,
|
|
42
|
+
initialImageIdIndex: Math.min(currentImageIdIndex, Math.max(volume.imageIds.length - 1, 0)),
|
|
43
|
+
reference: {
|
|
44
|
+
kind: 'segmentation',
|
|
45
|
+
segmentationId,
|
|
46
|
+
representationUID,
|
|
47
|
+
labelmapId: layer.labelmapId,
|
|
48
|
+
},
|
|
49
|
+
volumeId: layer.volumeId,
|
|
50
|
+
});
|
|
51
|
+
await viewport.addDisplaySet(dataId, {
|
|
52
|
+
orientation: requestedOrientation,
|
|
53
|
+
role: 'overlay',
|
|
54
|
+
});
|
|
55
|
+
viewport.setDisplaySetPresentation(dataId, {
|
|
56
|
+
blendMode,
|
|
57
|
+
visible: visibility,
|
|
58
|
+
});
|
|
59
|
+
firstActorEntry ||= viewport
|
|
60
|
+
.getActors?.()
|
|
61
|
+
.find((actorEntry) => actorEntry.representationUID === representationUID);
|
|
62
|
+
}
|
|
63
|
+
viewport.setViewReference(sourceViewReference);
|
|
64
|
+
viewport.render?.();
|
|
65
|
+
if (firstActorEntry) {
|
|
66
|
+
return {
|
|
67
|
+
uid: firstActorEntry.uid,
|
|
68
|
+
actor: firstActorEntry.actor,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function getPlanarNextVolumeRenderMode(viewport) {
|
|
73
|
+
const renderMode = viewport.getDefaultActor?.()?.actorMapper?.renderMode;
|
|
74
|
+
if (renderMode === ActorRenderMode.CPU_VOLUME ||
|
|
75
|
+
renderMode === ActorRenderMode.VTK_VOLUME_SLICE) {
|
|
76
|
+
return renderMode;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
export { addLabelmapToPlanarGenericViewport, isPlanarNextVolumeViewport, };
|