@cornerstonejs/tools 1.41.0 → 1.42.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/cjs/eventDispatchers/keyboardEventHandlers/keyDown.js +2 -1
- package/dist/cjs/eventDispatchers/keyboardEventHandlers/keyDown.js.map +1 -1
- package/dist/cjs/eventListeners/segmentation/imageChangeEventListener.js +18 -5
- package/dist/cjs/eventListeners/segmentation/imageChangeEventListener.js.map +1 -1
- package/dist/cjs/stateManagement/annotation/annotationState.js +3 -0
- package/dist/cjs/stateManagement/annotation/annotationState.js.map +1 -1
- package/dist/cjs/stateManagement/segmentation/convertStackToVolumeSegmentation.d.ts +10 -0
- package/dist/cjs/stateManagement/segmentation/convertStackToVolumeSegmentation.js +65 -0
- package/dist/cjs/stateManagement/segmentation/convertStackToVolumeSegmentation.js.map +1 -0
- package/dist/cjs/stateManagement/segmentation/convertVolumeToStackSegmentation.d.ts +8 -0
- package/dist/cjs/stateManagement/segmentation/convertVolumeToStackSegmentation.js +92 -0
- package/dist/cjs/stateManagement/segmentation/convertVolumeToStackSegmentation.js.map +1 -0
- package/dist/cjs/stateManagement/segmentation/index.d.ts +3 -1
- package/dist/cjs/stateManagement/segmentation/index.js +5 -1
- package/dist/cjs/stateManagement/segmentation/index.js.map +1 -1
- package/dist/cjs/stateManagement/segmentation/segmentationState.d.ts +2 -1
- package/dist/cjs/stateManagement/segmentation/segmentationState.js +8 -1
- package/dist/cjs/stateManagement/segmentation/segmentationState.js.map +1 -1
- package/dist/cjs/store/ToolGroupManager/ToolGroup.js +3 -0
- package/dist/cjs/store/ToolGroupManager/ToolGroup.js.map +1 -1
- package/dist/cjs/tools/annotation/AngleTool.js +2 -2
- package/dist/cjs/tools/annotation/AngleTool.js.map +1 -1
- package/dist/cjs/tools/annotation/BidirectionalTool.js +8 -7
- package/dist/cjs/tools/annotation/BidirectionalTool.js.map +1 -1
- package/dist/cjs/tools/annotation/CircleROITool.js +8 -8
- package/dist/cjs/tools/annotation/CircleROITool.js.map +1 -1
- package/dist/cjs/tools/annotation/EllipticalROITool.js +7 -7
- package/dist/cjs/tools/annotation/EllipticalROITool.js.map +1 -1
- package/dist/cjs/tools/annotation/LengthTool.js +2 -2
- package/dist/cjs/tools/annotation/LengthTool.js.map +1 -1
- package/dist/cjs/tools/annotation/PlanarFreehandROITool.js +5 -5
- package/dist/cjs/tools/annotation/PlanarFreehandROITool.js.map +1 -1
- package/dist/cjs/tools/annotation/ProbeTool.js +3 -3
- package/dist/cjs/tools/annotation/ProbeTool.js.map +1 -1
- package/dist/cjs/tools/annotation/RectangleROITool.js +7 -7
- package/dist/cjs/tools/annotation/RectangleROITool.js.map +1 -1
- package/dist/cjs/tools/displayTools/Labelmap/labelmapDisplay.js +10 -0
- package/dist/cjs/tools/displayTools/Labelmap/labelmapDisplay.js.map +1 -1
- package/dist/cjs/tools/segmentation/BrushTool.js +8 -4
- package/dist/cjs/tools/segmentation/BrushTool.js.map +1 -1
- package/dist/cjs/tools/segmentation/strategies/fillCircle.js +4 -6
- package/dist/cjs/tools/segmentation/strategies/fillCircle.js.map +1 -1
- package/dist/cjs/tools/segmentation/strategies/utils/isWithinThreshold.d.ts +1 -1
- package/dist/cjs/tools/segmentation/strategies/utils/isWithinThreshold.js.map +1 -1
- package/dist/cjs/types/index.d.ts +2 -1
- package/dist/cjs/utilities/contours/AnnotationToPointData.d.ts +11 -0
- package/dist/cjs/utilities/contours/AnnotationToPointData.js +44 -0
- package/dist/cjs/utilities/contours/AnnotationToPointData.js.map +1 -0
- package/dist/cjs/utilities/contours/RectangleROIStartEndThreshold.d.ts +6 -0
- package/dist/cjs/utilities/contours/RectangleROIStartEndThreshold.js +43 -0
- package/dist/cjs/utilities/contours/RectangleROIStartEndThreshold.js.map +1 -0
- package/dist/cjs/utilities/contours/contourFinder.d.ts +7 -0
- package/dist/cjs/utilities/contours/contourFinder.js +68 -0
- package/dist/cjs/utilities/contours/contourFinder.js.map +1 -0
- package/dist/cjs/utilities/contours/detectContourHoles.d.ts +5 -0
- package/dist/cjs/utilities/contours/detectContourHoles.js +78 -0
- package/dist/cjs/utilities/contours/detectContourHoles.js.map +1 -0
- package/dist/cjs/utilities/contours/generateContourSetsFromLabelmap.d.ts +4 -0
- package/dist/cjs/utilities/contours/generateContourSetsFromLabelmap.js +124 -0
- package/dist/cjs/utilities/contours/generateContourSetsFromLabelmap.js.map +1 -0
- package/dist/cjs/utilities/contours/index.d.ts +6 -0
- package/dist/cjs/utilities/contours/index.js +17 -0
- package/dist/cjs/utilities/contours/index.js.map +1 -0
- package/dist/cjs/utilities/contours/mergePoints.d.ts +8 -0
- package/dist/cjs/utilities/contours/mergePoints.js +77 -0
- package/dist/cjs/utilities/contours/mergePoints.js.map +1 -0
- package/dist/cjs/utilities/index.d.ts +4 -2
- package/dist/cjs/utilities/index.js +8 -5
- package/dist/cjs/utilities/index.js.map +1 -1
- package/dist/cjs/utilities/segmentation/contourAndFindLargestBidirectional.d.ts +1 -0
- package/dist/cjs/utilities/segmentation/contourAndFindLargestBidirectional.js +31 -0
- package/dist/cjs/utilities/segmentation/contourAndFindLargestBidirectional.js.map +1 -0
- package/dist/cjs/utilities/segmentation/createBidirectionalToolData.d.ts +14 -0
- package/dist/cjs/utilities/segmentation/createBidirectionalToolData.js +43 -0
- package/dist/cjs/utilities/segmentation/createBidirectionalToolData.js.map +1 -0
- package/dist/cjs/utilities/segmentation/createImageIdReferenceMap.d.ts +2 -0
- package/dist/cjs/utilities/segmentation/createImageIdReferenceMap.js +11 -0
- package/dist/cjs/utilities/segmentation/createImageIdReferenceMap.js.map +1 -0
- package/dist/cjs/utilities/segmentation/findLargestBidirectional.d.ts +1 -0
- package/dist/cjs/utilities/segmentation/findLargestBidirectional.js +94 -0
- package/dist/cjs/utilities/segmentation/findLargestBidirectional.js.map +1 -0
- package/dist/cjs/utilities/segmentation/index.d.ts +5 -1
- package/dist/cjs/utilities/segmentation/index.js +9 -1
- package/dist/cjs/utilities/segmentation/index.js.map +1 -1
- package/dist/cjs/utilities/segmentation/isLineInSegment.d.ts +9 -0
- package/dist/cjs/utilities/segmentation/isLineInSegment.js +55 -0
- package/dist/cjs/utilities/segmentation/isLineInSegment.js.map +1 -0
- package/dist/cjs/utilities/segmentation/segmentContourAction.d.ts +17 -0
- package/dist/cjs/utilities/segmentation/segmentContourAction.js +122 -0
- package/dist/cjs/utilities/segmentation/segmentContourAction.js.map +1 -0
- package/dist/cjs/utilities/segmentation/thresholdSegmentationByRange.js.map +1 -1
- package/dist/cjs/utilities/segmentation/triggerSegmentationRender.js +8 -4
- package/dist/cjs/utilities/segmentation/triggerSegmentationRender.js.map +1 -1
- package/dist/cjs/utilities/stackPrefetch/stackContextPrefetch.js +2 -5
- package/dist/cjs/utilities/stackPrefetch/stackContextPrefetch.js.map +1 -1
- package/dist/cjs/utilities/stackPrefetch/stackPrefetchUtils.js +2 -1
- package/dist/cjs/utilities/stackPrefetch/stackPrefetchUtils.js.map +1 -1
- package/dist/esm/eventDispatchers/keyboardEventHandlers/keyDown.js +2 -1
- package/dist/esm/eventDispatchers/keyboardEventHandlers/keyDown.js.map +1 -1
- package/dist/esm/eventListeners/segmentation/imageChangeEventListener.js +18 -5
- package/dist/esm/eventListeners/segmentation/imageChangeEventListener.js.map +1 -1
- package/dist/esm/stateManagement/annotation/annotationState.js +3 -0
- package/dist/esm/stateManagement/annotation/annotationState.js.map +1 -1
- package/dist/esm/stateManagement/segmentation/convertStackToVolumeSegmentation.js +47 -0
- package/dist/esm/stateManagement/segmentation/convertStackToVolumeSegmentation.js.map +1 -0
- package/dist/esm/stateManagement/segmentation/convertVolumeToStackSegmentation.js +72 -0
- package/dist/esm/stateManagement/segmentation/convertVolumeToStackSegmentation.js.map +1 -0
- package/dist/esm/stateManagement/segmentation/index.js +3 -1
- package/dist/esm/stateManagement/segmentation/index.js.map +1 -1
- package/dist/esm/stateManagement/segmentation/segmentationState.js +7 -1
- package/dist/esm/stateManagement/segmentation/segmentationState.js.map +1 -1
- package/dist/esm/store/ToolGroupManager/ToolGroup.js +3 -0
- package/dist/esm/store/ToolGroupManager/ToolGroup.js.map +1 -1
- package/dist/esm/tools/annotation/AngleTool.js +1 -1
- package/dist/esm/tools/annotation/AngleTool.js.map +1 -1
- package/dist/esm/tools/annotation/BidirectionalTool.js +8 -7
- package/dist/esm/tools/annotation/BidirectionalTool.js.map +1 -1
- package/dist/esm/tools/annotation/CircleROITool.js +1 -1
- package/dist/esm/tools/annotation/CircleROITool.js.map +1 -1
- package/dist/esm/tools/annotation/EllipticalROITool.js +1 -1
- package/dist/esm/tools/annotation/EllipticalROITool.js.map +1 -1
- package/dist/esm/tools/annotation/LengthTool.js +1 -1
- package/dist/esm/tools/annotation/LengthTool.js.map +1 -1
- package/dist/esm/tools/annotation/PlanarFreehandROITool.js +1 -1
- package/dist/esm/tools/annotation/PlanarFreehandROITool.js.map +1 -1
- package/dist/esm/tools/annotation/ProbeTool.js +1 -1
- package/dist/esm/tools/annotation/ProbeTool.js.map +1 -1
- package/dist/esm/tools/annotation/RectangleROITool.js +1 -1
- package/dist/esm/tools/annotation/RectangleROITool.js.map +1 -1
- package/dist/esm/tools/displayTools/Labelmap/labelmapDisplay.js +11 -1
- package/dist/esm/tools/displayTools/Labelmap/labelmapDisplay.js.map +1 -1
- package/dist/esm/tools/segmentation/BrushTool.js +8 -4
- package/dist/esm/tools/segmentation/BrushTool.js.map +1 -1
- package/dist/esm/tools/segmentation/strategies/fillCircle.js +4 -6
- package/dist/esm/tools/segmentation/strategies/fillCircle.js.map +1 -1
- package/dist/esm/tools/segmentation/strategies/utils/isWithinThreshold.js.map +1 -1
- package/dist/esm/utilities/contours/AnnotationToPointData.js +39 -0
- package/dist/esm/utilities/contours/AnnotationToPointData.js.map +1 -0
- package/dist/esm/utilities/contours/RectangleROIStartEndThreshold.js +41 -0
- package/dist/esm/utilities/contours/RectangleROIStartEndThreshold.js.map +1 -0
- package/dist/esm/utilities/contours/contourFinder.js +63 -0
- package/dist/esm/utilities/contours/contourFinder.js.map +1 -0
- package/dist/esm/utilities/contours/detectContourHoles.js +74 -0
- package/dist/esm/utilities/contours/detectContourHoles.js.map +1 -0
- package/dist/esm/utilities/contours/generateContourSetsFromLabelmap.js +117 -0
- package/dist/esm/utilities/contours/generateContourSetsFromLabelmap.js.map +1 -0
- package/dist/esm/utilities/contours/index.js +7 -0
- package/dist/esm/utilities/contours/index.js.map +1 -0
- package/dist/esm/utilities/contours/mergePoints.js +73 -0
- package/dist/esm/utilities/contours/mergePoints.js.map +1 -0
- package/dist/esm/utilities/index.js +4 -2
- package/dist/esm/utilities/index.js.map +1 -1
- package/dist/esm/utilities/segmentation/contourAndFindLargestBidirectional.js +25 -0
- package/dist/esm/utilities/segmentation/contourAndFindLargestBidirectional.js.map +1 -0
- package/dist/esm/utilities/segmentation/createBidirectionalToolData.js +40 -0
- package/dist/esm/utilities/segmentation/createBidirectionalToolData.js.map +1 -0
- package/dist/esm/utilities/segmentation/createImageIdReferenceMap.js +8 -0
- package/dist/esm/utilities/segmentation/createImageIdReferenceMap.js.map +1 -0
- package/dist/esm/utilities/segmentation/findLargestBidirectional.js +96 -0
- package/dist/esm/utilities/segmentation/findLargestBidirectional.js.map +1 -0
- package/dist/esm/utilities/segmentation/index.js +5 -1
- package/dist/esm/utilities/segmentation/index.js.map +1 -1
- package/dist/esm/utilities/segmentation/isLineInSegment.js +50 -0
- package/dist/esm/utilities/segmentation/isLineInSegment.js.map +1 -0
- package/dist/esm/utilities/segmentation/segmentContourAction.js +98 -0
- package/dist/esm/utilities/segmentation/segmentContourAction.js.map +1 -0
- package/dist/esm/utilities/segmentation/thresholdSegmentationByRange.js.map +1 -1
- package/dist/esm/utilities/segmentation/triggerSegmentationRender.js +8 -4
- package/dist/esm/utilities/segmentation/triggerSegmentationRender.js.map +1 -1
- package/dist/esm/utilities/stackPrefetch/stackContextPrefetch.js +1 -1
- package/dist/esm/utilities/stackPrefetch/stackContextPrefetch.js.map +1 -1
- package/dist/esm/utilities/stackPrefetch/stackPrefetchUtils.js +2 -1
- package/dist/esm/utilities/stackPrefetch/stackPrefetchUtils.js.map +1 -1
- package/dist/types/eventDispatchers/keyboardEventHandlers/keyDown.d.ts.map +1 -1
- package/dist/types/eventListeners/segmentation/imageChangeEventListener.d.ts.map +1 -1
- package/dist/types/stateManagement/annotation/annotationState.d.ts.map +1 -1
- package/dist/types/stateManagement/segmentation/convertStackToVolumeSegmentation.d.ts +11 -0
- package/dist/types/stateManagement/segmentation/convertStackToVolumeSegmentation.d.ts.map +1 -0
- package/dist/types/stateManagement/segmentation/convertVolumeToStackSegmentation.d.ts +9 -0
- package/dist/types/stateManagement/segmentation/convertVolumeToStackSegmentation.d.ts.map +1 -0
- package/dist/types/stateManagement/segmentation/index.d.ts +3 -1
- package/dist/types/stateManagement/segmentation/index.d.ts.map +1 -1
- package/dist/types/stateManagement/segmentation/segmentationState.d.ts +2 -1
- package/dist/types/stateManagement/segmentation/segmentationState.d.ts.map +1 -1
- package/dist/types/store/ToolGroupManager/ToolGroup.d.ts.map +1 -1
- package/dist/types/tools/annotation/AngleTool.d.ts.map +1 -1
- package/dist/types/tools/annotation/BidirectionalTool.d.ts.map +1 -1
- package/dist/types/tools/annotation/PlanarFreehandROITool.d.ts.map +1 -1
- package/dist/types/tools/displayTools/Labelmap/labelmapDisplay.d.ts.map +1 -1
- package/dist/types/tools/segmentation/BrushTool.d.ts.map +1 -1
- package/dist/types/tools/segmentation/strategies/fillCircle.d.ts.map +1 -1
- package/dist/types/tools/segmentation/strategies/utils/isWithinThreshold.d.ts +1 -1
- package/dist/types/tools/segmentation/strategies/utils/isWithinThreshold.d.ts.map +1 -1
- package/dist/types/types/LabelmapTypes.d.ts.map +1 -1
- package/dist/types/types/index.d.ts +2 -1
- package/dist/types/types/index.d.ts.map +1 -1
- package/dist/types/utilities/contours/AnnotationToPointData.d.ts +12 -0
- package/dist/types/utilities/contours/AnnotationToPointData.d.ts.map +1 -0
- package/dist/types/utilities/contours/RectangleROIStartEndThreshold.d.ts +7 -0
- package/dist/types/utilities/contours/RectangleROIStartEndThreshold.d.ts.map +1 -0
- package/dist/types/utilities/contours/contourFinder.d.ts +8 -0
- package/dist/types/utilities/contours/contourFinder.d.ts.map +1 -0
- package/dist/types/utilities/contours/detectContourHoles.d.ts +6 -0
- package/dist/types/utilities/contours/detectContourHoles.d.ts.map +1 -0
- package/dist/types/utilities/contours/generateContourSetsFromLabelmap.d.ts +5 -0
- package/dist/types/utilities/contours/generateContourSetsFromLabelmap.d.ts.map +1 -0
- package/dist/types/utilities/contours/index.d.ts +7 -0
- package/dist/types/utilities/contours/index.d.ts.map +1 -0
- package/dist/types/utilities/contours/mergePoints.d.ts +9 -0
- package/dist/types/utilities/contours/mergePoints.d.ts.map +1 -0
- package/dist/types/utilities/index.d.ts +4 -2
- package/dist/types/utilities/index.d.ts.map +1 -1
- package/dist/types/utilities/segmentation/contourAndFindLargestBidirectional.d.ts +2 -0
- package/dist/types/utilities/segmentation/contourAndFindLargestBidirectional.d.ts.map +1 -0
- package/dist/types/utilities/segmentation/createBidirectionalToolData.d.ts +15 -0
- package/dist/types/utilities/segmentation/createBidirectionalToolData.d.ts.map +1 -0
- package/dist/types/utilities/segmentation/createImageIdReferenceMap.d.ts +3 -0
- package/dist/types/utilities/segmentation/createImageIdReferenceMap.d.ts.map +1 -0
- package/dist/types/utilities/segmentation/findLargestBidirectional.d.ts +2 -0
- package/dist/types/utilities/segmentation/findLargestBidirectional.d.ts.map +1 -0
- package/dist/types/utilities/segmentation/index.d.ts +5 -1
- package/dist/types/utilities/segmentation/index.d.ts.map +1 -1
- package/dist/types/utilities/segmentation/isLineInSegment.d.ts +10 -0
- package/dist/types/utilities/segmentation/isLineInSegment.d.ts.map +1 -0
- package/dist/types/utilities/segmentation/segmentContourAction.d.ts +18 -0
- package/dist/types/utilities/segmentation/segmentContourAction.d.ts.map +1 -0
- package/dist/types/utilities/segmentation/triggerSegmentationRender.d.ts.map +1 -1
- package/dist/types/utilities/stackPrefetch/stackPrefetchUtils.d.ts.map +1 -1
- package/dist/umd/index.js +1 -1
- package/dist/umd/index.js.map +1 -1
- package/package.json +3 -3
- package/src/eventDispatchers/keyboardEventHandlers/keyDown.ts +7 -1
- package/src/eventListeners/segmentation/imageChangeEventListener.ts +42 -6
- package/src/stateManagement/annotation/annotationState.ts +3 -0
- package/src/stateManagement/segmentation/convertStackToVolumeSegmentation.ts +98 -0
- package/src/stateManagement/segmentation/convertVolumeToStackSegmentation.ts +153 -0
- package/src/stateManagement/segmentation/index.ts +4 -0
- package/src/stateManagement/segmentation/segmentationState.ts +17 -0
- package/src/store/ToolGroupManager/ToolGroup.ts +4 -0
- package/src/tools/annotation/AngleTool.ts +1 -2
- package/src/tools/annotation/BidirectionalTool.ts +10 -6
- package/src/tools/annotation/CircleROITool.ts +1 -1
- package/src/tools/annotation/EllipticalROITool.ts +1 -1
- package/src/tools/annotation/LengthTool.ts +1 -1
- package/src/tools/annotation/PlanarFreehandROITool.ts +1 -2
- package/src/tools/annotation/ProbeTool.ts +1 -1
- package/src/tools/annotation/RectangleROITool.ts +1 -1
- package/src/tools/displayTools/Labelmap/labelmapDisplay.ts +16 -2
- package/src/tools/segmentation/BrushTool.ts +11 -7
- package/src/tools/segmentation/strategies/fillCircle.ts +4 -7
- package/src/tools/segmentation/strategies/utils/isWithinThreshold.ts +1 -1
- package/src/types/LabelmapTypes.ts +2 -5
- package/src/types/index.ts +2 -0
- package/src/utilities/contours/AnnotationToPointData.ts +61 -0
- package/src/utilities/contours/RectangleROIStartEndThreshold.ts +60 -0
- package/src/utilities/contours/contourFinder.ts +78 -0
- package/src/utilities/contours/detectContourHoles.ts +147 -0
- package/src/utilities/contours/generateContourSetsFromLabelmap.ts +160 -0
- package/src/utilities/contours/index.ts +14 -0
- package/src/utilities/contours/mergePoints.ts +108 -0
- package/src/utilities/index.ts +6 -1
- package/src/utilities/segmentation/contourAndFindLargestBidirectional.ts +46 -0
- package/src/utilities/segmentation/createBidirectionalToolData.ts +68 -0
- package/src/utilities/segmentation/createImageIdReferenceMap.ts +23 -0
- package/src/utilities/segmentation/findLargestBidirectional.ts +159 -0
- package/src/utilities/segmentation/index.ts +8 -0
- package/src/utilities/segmentation/isLineInSegment.ts +84 -0
- package/src/utilities/segmentation/segmentContourAction.ts +169 -0
- package/src/utilities/segmentation/thresholdSegmentationByRange.ts +2 -2
- package/src/utilities/segmentation/triggerSegmentationRender.ts +15 -10
- package/src/utilities/stackPrefetch/stackContextPrefetch.ts +1 -1
- package/src/utilities/stackPrefetch/stackPrefetchUtils.ts +5 -1
- package/dist/cjs/utilities/roundNumber.d.ts +0 -2
- package/dist/cjs/utilities/roundNumber.js +0 -30
- package/dist/cjs/utilities/roundNumber.js.map +0 -1
- package/dist/esm/utilities/roundNumber.js +0 -28
- package/dist/esm/utilities/roundNumber.js.map +0 -1
- package/dist/types/utilities/roundNumber.d.ts +0 -3
- package/dist/types/utilities/roundNumber.d.ts.map +0 -1
- package/src/utilities/roundNumber.ts +0 -44
|
@@ -171,7 +171,7 @@ class BrushTool extends BaseTool {
|
|
|
171
171
|
|
|
172
172
|
createEditData(element) {
|
|
173
173
|
const enabledElement = getEnabledElement(element);
|
|
174
|
-
const { viewport
|
|
174
|
+
const { viewport } = enabledElement;
|
|
175
175
|
|
|
176
176
|
const toolGroupId = this.toolGroupId;
|
|
177
177
|
|
|
@@ -198,8 +198,6 @@ class BrushTool extends BaseTool {
|
|
|
198
198
|
const labelmapData =
|
|
199
199
|
representationData[SegmentationRepresentations.Labelmap];
|
|
200
200
|
|
|
201
|
-
const viewportIdsToRender = [viewport.id];
|
|
202
|
-
|
|
203
201
|
if (isVolumeSegmentation(labelmapData)) {
|
|
204
202
|
const { volumeId } = representationData[
|
|
205
203
|
type
|
|
@@ -235,11 +233,9 @@ class BrushTool extends BaseTool {
|
|
|
235
233
|
// and should throw an error or maybe simply just allow circle manipulation
|
|
236
234
|
// and not sphere manipulation
|
|
237
235
|
if (this.configuration.activeStrategy.includes('SPHERE')) {
|
|
238
|
-
|
|
239
|
-
'Sphere manipulation is not supported for
|
|
236
|
+
throw new Error(
|
|
237
|
+
'Sphere manipulation is not supported for stacks of image segmentations yet'
|
|
240
238
|
);
|
|
241
|
-
return;
|
|
242
|
-
|
|
243
239
|
// Todo: add sphere (volumetric) manipulation support for stacks of images
|
|
244
240
|
// we should basically check if the stack constructs a valid volume
|
|
245
241
|
// meaning all the metadata is present and consistent
|
|
@@ -428,6 +424,10 @@ class BrushTool extends BaseTool {
|
|
|
428
424
|
|
|
429
425
|
this._calculateCursor(element, centerCanvas);
|
|
430
426
|
|
|
427
|
+
if (!this._hoverData) {
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
431
|
triggerAnnotationRenderForViewportUIDs(
|
|
432
432
|
getEnabledElement(element).renderingEngine,
|
|
433
433
|
this._hoverData.viewportIdsToRender
|
|
@@ -549,6 +549,10 @@ class BrushTool extends BaseTool {
|
|
|
549
549
|
rightCursorInWorld[i] = centerCursorInWorld[i] + viewRight[i] * brushSize;
|
|
550
550
|
}
|
|
551
551
|
|
|
552
|
+
if (!this._hoverData) {
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
|
|
552
556
|
const { brushCursor } = this._hoverData;
|
|
553
557
|
const { data } = brushCursor;
|
|
554
558
|
|
|
@@ -14,10 +14,7 @@ import type { CanvasCoordinates } from '../../../types';
|
|
|
14
14
|
import { StrategyCallbacks } from '../../../enums';
|
|
15
15
|
import compositions from './compositions';
|
|
16
16
|
|
|
17
|
-
const { transformWorldToIndex } = csUtils;
|
|
18
|
-
const EPSILON = 1e-4;
|
|
19
|
-
const nearOrZero = (testValue, nearValue) =>
|
|
20
|
-
Math.abs(testValue) < EPSILON || Math.abs(testValue - nearValue) < EPSILON;
|
|
17
|
+
const { transformWorldToIndex, isEqual } = csUtils;
|
|
21
18
|
|
|
22
19
|
const initializeCircle = {
|
|
23
20
|
[StrategyCallbacks.Initialize]: (operationData: InitializedOperationData) => {
|
|
@@ -98,9 +95,9 @@ function createPointInEllipse(worldInfo: {
|
|
|
98
95
|
|
|
99
96
|
const radius = Math.max(xRadius, yRadius, zRadius);
|
|
100
97
|
if (
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
98
|
+
isEqual(xRadius, radius) &&
|
|
99
|
+
isEqual(yRadius, radius) &&
|
|
100
|
+
isEqual(zRadius, radius)
|
|
104
101
|
) {
|
|
105
102
|
const sphereObj = {
|
|
106
103
|
center,
|
|
@@ -2,7 +2,7 @@ import { Types } from '@cornerstonejs/core';
|
|
|
2
2
|
|
|
3
3
|
function isWithinThreshold(
|
|
4
4
|
index: number,
|
|
5
|
-
imageScalarData: Types.
|
|
5
|
+
imageScalarData: Types.PixelDataTypedArray,
|
|
6
6
|
strategySpecificConfiguration: any
|
|
7
7
|
) {
|
|
8
8
|
const { THRESHOLD, THRESHOLD_INSIDE_CIRCLE } = strategySpecificConfiguration;
|
|
@@ -42,11 +42,8 @@ export type LabelmapSegmentationDataVolume = {
|
|
|
42
42
|
|
|
43
43
|
export type LabelmapSegmentationDataStack = {
|
|
44
44
|
/**
|
|
45
|
-
* This is a Map from referenced imageId to the segmentation (Derived)
|
|
46
|
-
*
|
|
47
|
-
* Todo: later I guess we can have it as Record<string, metadata> where metadata
|
|
48
|
-
* can contain a derived image arbitrary information, for use cases such that the labelmap is
|
|
49
|
-
* derived from another image that is irrelevant to the current viewport.
|
|
45
|
+
* This is a Map from referenced imageId to the segmentation (Derived) imageIds (can be
|
|
46
|
+
* multiple) that are associated with it.
|
|
50
47
|
*/
|
|
51
48
|
imageIdReferenceMap: Map<string, string>;
|
|
52
49
|
};
|
package/src/types/index.ts
CHANGED
|
@@ -73,11 +73,13 @@ import type { ISpline } from './ISpline';
|
|
|
73
73
|
import type { SplineCurveSegment } from './SplineCurveSegment';
|
|
74
74
|
import type { SplineLineSegment } from './SplineLineSegment';
|
|
75
75
|
import type { SplineProps } from './SplineProps';
|
|
76
|
+
import type { BidirectionalData } from '../utilities/segmentation/createBidirectionalToolData';
|
|
76
77
|
|
|
77
78
|
export type {
|
|
78
79
|
// AnnotationState
|
|
79
80
|
Annotation,
|
|
80
81
|
Annotations,
|
|
82
|
+
BidirectionalData,
|
|
81
83
|
CanvasCoordinates,
|
|
82
84
|
IAnnotationManager,
|
|
83
85
|
GroupSpecificAnnotations,
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import RectangleROIStartEndThreshold from './RectangleROIStartEndThreshold';
|
|
2
|
+
|
|
3
|
+
function validateAnnotation(annotation) {
|
|
4
|
+
if (!annotation?.data) {
|
|
5
|
+
throw new Error('Tool data is empty');
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
if (!annotation.metadata || annotation.metadata.referenceImageId) {
|
|
9
|
+
throw new Error('Tool data is not associated with any imageId');
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
class AnnotationToPointData {
|
|
14
|
+
static TOOL_NAMES: Record<string, any> = {};
|
|
15
|
+
|
|
16
|
+
constructor() {
|
|
17
|
+
// empty
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static convert(annotation, index, metadataProvider) {
|
|
21
|
+
validateAnnotation(annotation);
|
|
22
|
+
|
|
23
|
+
const { toolName } = annotation.metadata;
|
|
24
|
+
const toolClass = AnnotationToPointData.TOOL_NAMES[toolName];
|
|
25
|
+
|
|
26
|
+
if (!toolClass) {
|
|
27
|
+
throw new Error(
|
|
28
|
+
`Unknown tool type: ${toolName}, cannot convert to RTSSReport`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Each toolData should become a list of contours, ContourSequence
|
|
33
|
+
// contains a list of contours with their pointData, their geometry
|
|
34
|
+
// type and their length.
|
|
35
|
+
const ContourSequence = toolClass.getContourSequence(
|
|
36
|
+
annotation,
|
|
37
|
+
metadataProvider
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
// Todo: random rgb color for now, options should be passed in
|
|
41
|
+
const color = [
|
|
42
|
+
Math.floor(Math.random() * 255),
|
|
43
|
+
Math.floor(Math.random() * 255),
|
|
44
|
+
Math.floor(Math.random() * 255),
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
ReferencedROINumber: index + 1,
|
|
49
|
+
ROIDisplayColor: color,
|
|
50
|
+
ContourSequence,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
static register(toolClass) {
|
|
55
|
+
AnnotationToPointData.TOOL_NAMES[toolClass.toolName] = toolClass;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
AnnotationToPointData.register(RectangleROIStartEndThreshold);
|
|
60
|
+
|
|
61
|
+
export default AnnotationToPointData;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// comment
|
|
2
|
+
class RectangleROIStartEndThreshold {
|
|
3
|
+
static toolName: string;
|
|
4
|
+
|
|
5
|
+
constructor() {
|
|
6
|
+
// empty
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
static getContourSequence(toolData, metadataProvider) {
|
|
10
|
+
const { data } = toolData;
|
|
11
|
+
const { projectionPoints, projectionPointsImageIds } = data.cachedStats;
|
|
12
|
+
|
|
13
|
+
return projectionPoints.map((point, index) => {
|
|
14
|
+
const ContourData = getPointData(point);
|
|
15
|
+
const ContourImageSequence = getContourImageSequence(
|
|
16
|
+
projectionPointsImageIds[index],
|
|
17
|
+
metadataProvider
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
NumberOfContourPoints: ContourData.length / 3,
|
|
22
|
+
ContourImageSequence,
|
|
23
|
+
ContourGeometricType: 'CLOSED_PLANAR',
|
|
24
|
+
ContourData,
|
|
25
|
+
};
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
RectangleROIStartEndThreshold.toolName = 'RectangleROIStartEndThreshold';
|
|
31
|
+
|
|
32
|
+
function getPointData(points) {
|
|
33
|
+
// Since this is a closed contour, the order of the points is important.
|
|
34
|
+
// re-order the points to be in the correct order clockwise
|
|
35
|
+
// Spread to make sure Float32Arrays are converted to arrays
|
|
36
|
+
const orderedPoints = [
|
|
37
|
+
...points[0],
|
|
38
|
+
...points[1],
|
|
39
|
+
...points[3],
|
|
40
|
+
...points[2],
|
|
41
|
+
];
|
|
42
|
+
const pointsArray = orderedPoints.flat();
|
|
43
|
+
|
|
44
|
+
// reduce the precision of the points to 2 decimal places
|
|
45
|
+
const pointsArrayWithPrecision = pointsArray.map((point) => {
|
|
46
|
+
return point.toFixed(2);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
return pointsArrayWithPrecision;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function getContourImageSequence(imageId, metadataProvider) {
|
|
53
|
+
const sopCommon = metadataProvider.get('sopCommonModule', imageId);
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
ReferencedSOPClassUID: sopCommon.sopClassUID,
|
|
57
|
+
ReferencedSOPInstanceUID: sopCommon.sopInstanceUID,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export default RectangleROIStartEndThreshold;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
function findNextLink(line, lines, contourPoints) {
|
|
2
|
+
let index = -1;
|
|
3
|
+
lines.forEach((cell, i) => {
|
|
4
|
+
if (index >= 0) {
|
|
5
|
+
return;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
if (cell.a == line.b) {
|
|
9
|
+
index = i;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
if (index >= 0) {
|
|
14
|
+
const nextLine = lines[index];
|
|
15
|
+
lines.splice(index, 1);
|
|
16
|
+
|
|
17
|
+
contourPoints.push(nextLine.b);
|
|
18
|
+
|
|
19
|
+
if (contourPoints[0] == nextLine.b) {
|
|
20
|
+
return {
|
|
21
|
+
remainingLines: lines,
|
|
22
|
+
contourPoints,
|
|
23
|
+
type: 'CLOSED_PLANAR',
|
|
24
|
+
//type: 'CLOSEDPLANAR_XOR',
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return findNextLink(nextLine, lines, contourPoints);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
remainingLines: lines,
|
|
33
|
+
contourPoints,
|
|
34
|
+
type: 'OPEN_PLANAR',
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
*
|
|
40
|
+
* @param {*} lines
|
|
41
|
+
*/
|
|
42
|
+
export function findContours(lines) {
|
|
43
|
+
if (lines.length == 0) {
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const contourPoints = [];
|
|
48
|
+
|
|
49
|
+
const firstCell = lines.shift();
|
|
50
|
+
contourPoints.push(firstCell.a);
|
|
51
|
+
contourPoints.push(firstCell.b);
|
|
52
|
+
const result = findNextLink(firstCell, lines, contourPoints);
|
|
53
|
+
|
|
54
|
+
if (result.remainingLines.length == 0) {
|
|
55
|
+
return [
|
|
56
|
+
{
|
|
57
|
+
type: result.type,
|
|
58
|
+
contourPoints: result.contourPoints,
|
|
59
|
+
},
|
|
60
|
+
];
|
|
61
|
+
} else {
|
|
62
|
+
const extraContours = findContours(result.remainingLines);
|
|
63
|
+
extraContours.push({
|
|
64
|
+
type: result.type,
|
|
65
|
+
contourPoints: result.contourPoints,
|
|
66
|
+
});
|
|
67
|
+
return extraContours;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function findContoursFromReducedSet(lines) {
|
|
72
|
+
return findContours(lines);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export default {
|
|
76
|
+
findContours,
|
|
77
|
+
findContoursFromReducedSet,
|
|
78
|
+
};
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Functions for detecting and dealing with holes within contours.
|
|
3
|
+
* Expected Contour format:
|
|
4
|
+
* {
|
|
5
|
+
* type,
|
|
6
|
+
* contourPoints
|
|
7
|
+
* }
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Checks if point is inside polygon defined by vertices array
|
|
12
|
+
* Code from
|
|
13
|
+
* https://stackoverflow.com/questions/22521982/check-if-point-is-inside-a-polygon
|
|
14
|
+
* most original version based on:
|
|
15
|
+
* https://wrf.ecse.rpi.edu/Research/Short_Notes/pnpoly.html/pnpoly.html
|
|
16
|
+
* @param {*} point
|
|
17
|
+
* @param {*} vertices
|
|
18
|
+
* @returns
|
|
19
|
+
*/
|
|
20
|
+
const getIsPointInsidePolygon = (point, vertices) => {
|
|
21
|
+
const x = point[0];
|
|
22
|
+
const y = point[1];
|
|
23
|
+
|
|
24
|
+
let inside = false;
|
|
25
|
+
for (let i = 0, j = vertices.length - 1; i < vertices.length; j = i++) {
|
|
26
|
+
const xi = vertices[i][0],
|
|
27
|
+
yi = vertices[i][1];
|
|
28
|
+
const xj = vertices[j][0],
|
|
29
|
+
yj = vertices[j][1];
|
|
30
|
+
|
|
31
|
+
const intersect =
|
|
32
|
+
yi > y != yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi;
|
|
33
|
+
if (intersect) {
|
|
34
|
+
inside = !inside;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return inside;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Check if inner contour is completely surrounded by outer contour.
|
|
43
|
+
* @param {*} outerContour
|
|
44
|
+
* @param {*} innerContour
|
|
45
|
+
* @returns
|
|
46
|
+
*/
|
|
47
|
+
function checkEnclosed(outerContour, innerContour, points) {
|
|
48
|
+
const vertices = [];
|
|
49
|
+
outerContour.contourPoints.forEach((point) => {
|
|
50
|
+
vertices.push([points[point][0], points[point][1]]);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
let pointsNotEnclosed = 0;
|
|
54
|
+
innerContour.contourPoints.forEach((point) => {
|
|
55
|
+
const result = getIsPointInsidePolygon(
|
|
56
|
+
[points[point][0], points[point][1]],
|
|
57
|
+
vertices
|
|
58
|
+
);
|
|
59
|
+
//console.log(result);
|
|
60
|
+
|
|
61
|
+
if (!result) {
|
|
62
|
+
pointsNotEnclosed++;
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
return pointsNotEnclosed === 0;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Check if contours have holes, if so update contour accordingly
|
|
71
|
+
* @param {*} polyData
|
|
72
|
+
* @param {*} bypass
|
|
73
|
+
*/
|
|
74
|
+
export function processContourHoles(contours, points, useXOR = true) {
|
|
75
|
+
//console.log(points);
|
|
76
|
+
|
|
77
|
+
// Add non-closed planars to contour list
|
|
78
|
+
const retContours = contours.filter(
|
|
79
|
+
(contour) => contour.type !== 'CLOSED_PLANAR'
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
// Find closed planar contours
|
|
83
|
+
const closedContours = contours.filter(
|
|
84
|
+
(contour) => contour.type === 'CLOSED_PLANAR'
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
// Iterate through each contour in list check for contours that have holes
|
|
88
|
+
const contourWithHoles = [];
|
|
89
|
+
let contourWithoutHoles = [];
|
|
90
|
+
closedContours.forEach((contour, index) => {
|
|
91
|
+
const holes = [];
|
|
92
|
+
|
|
93
|
+
// Check if any other contour is a hole surrounded by current contour
|
|
94
|
+
closedContours.forEach((hContour, hIndex) => {
|
|
95
|
+
if (index != hIndex) {
|
|
96
|
+
// Check if inner loop contour is a hole of outer loop contour
|
|
97
|
+
if (checkEnclosed(contour, hContour, points)) {
|
|
98
|
+
holes.push(hIndex);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// Check if holes were found
|
|
104
|
+
if (holes.length > 0) {
|
|
105
|
+
// Note current contour and reference of its holes
|
|
106
|
+
contourWithHoles.push({
|
|
107
|
+
contour,
|
|
108
|
+
holes,
|
|
109
|
+
});
|
|
110
|
+
} else {
|
|
111
|
+
// Note contour index without holes
|
|
112
|
+
contourWithoutHoles.push(index);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
if (useXOR) {
|
|
117
|
+
// XOR method
|
|
118
|
+
contourWithHoles.forEach((contourHoleSet) => {
|
|
119
|
+
// Modify contour with hole to type CLOSEDPLANAR_XOR
|
|
120
|
+
contourHoleSet.contour.type = 'CLOSEDPLANAR_XOR';
|
|
121
|
+
retContours.push(contourHoleSet.contour);
|
|
122
|
+
|
|
123
|
+
contourHoleSet.holes.forEach((holeIndex) => {
|
|
124
|
+
// Modify hole type to CLOSEDPLANAR_XOR
|
|
125
|
+
// and add to contour list to be returned
|
|
126
|
+
closedContours[holeIndex].type = 'CLOSEDPLANAR_XOR';
|
|
127
|
+
retContours.push(closedContours[holeIndex]);
|
|
128
|
+
|
|
129
|
+
// Remove hole from list of contours without holes
|
|
130
|
+
contourWithoutHoles = contourWithoutHoles.filter((contourIndex) => {
|
|
131
|
+
return contourIndex !== holeIndex;
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// Add remaining contours to list (neither hole nor have holes)
|
|
137
|
+
contourWithoutHoles.forEach((contourIndex) => {
|
|
138
|
+
retContours.push(closedContours[contourIndex]);
|
|
139
|
+
});
|
|
140
|
+
} else {
|
|
141
|
+
// Keyhole method, not implemented
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return retContours;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export default { processContourHoles };
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { cache as cornerstoneCache } from '@cornerstonejs/core';
|
|
2
|
+
import vtkImageMarchingSquares from '@kitware/vtk.js/Filters/General/ImageMarchingSquares';
|
|
3
|
+
import vtkDataArray from '@kitware/vtk.js/Common/Core/DataArray';
|
|
4
|
+
import vtkImageData from '@kitware/vtk.js/Common/DataModel/ImageData';
|
|
5
|
+
|
|
6
|
+
import { removeDuplicatePoints } from './mergePoints';
|
|
7
|
+
import { findContoursFromReducedSet } from './contourFinder';
|
|
8
|
+
import SegmentationRepresentations from '../../enums/SegmentationRepresentations';
|
|
9
|
+
|
|
10
|
+
const { Labelmap } = SegmentationRepresentations;
|
|
11
|
+
|
|
12
|
+
function generateContourSetsFromLabelmap({ segmentations }) {
|
|
13
|
+
const { representationData, segments = [0, 1] } = segmentations;
|
|
14
|
+
const { volumeId: segVolumeId } = representationData[Labelmap];
|
|
15
|
+
|
|
16
|
+
// Get segmentation volume
|
|
17
|
+
const vol = cornerstoneCache.getVolume(segVolumeId);
|
|
18
|
+
if (!vol) {
|
|
19
|
+
console.warn(`No volume found for ${segVolumeId}`);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const numSlices = vol.dimensions[2];
|
|
24
|
+
|
|
25
|
+
// Get image volume segmentation references
|
|
26
|
+
const imageVol = cornerstoneCache.getVolume(vol.referencedVolumeId);
|
|
27
|
+
if (!imageVol) {
|
|
28
|
+
console.warn(`No volume found for ${vol.referencedVolumeId}`);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// NOTE: Workaround for marching squares not finding closed contours at
|
|
33
|
+
// boundary of image volume, clear pixels along x-y border of volume
|
|
34
|
+
const segData = vol.imageData.getPointData().getScalars().getData();
|
|
35
|
+
const pixelsPerSlice = vol.dimensions[0] * vol.dimensions[1];
|
|
36
|
+
|
|
37
|
+
for (let z = 0; z < numSlices; z++) {
|
|
38
|
+
for (let y = 0; y < vol.dimensions[1]; y++) {
|
|
39
|
+
const index = y * vol.dimensions[0] + z * pixelsPerSlice;
|
|
40
|
+
segData[index] = 0;
|
|
41
|
+
segData[index + vol.dimensions[0] - 1] = 0;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// end workaround
|
|
46
|
+
//
|
|
47
|
+
//
|
|
48
|
+
const ContourSets = [];
|
|
49
|
+
|
|
50
|
+
const { FrameOfReferenceUID } = imageVol.metadata;
|
|
51
|
+
// Iterate through all segments in current segmentation set
|
|
52
|
+
const numSegments = segments.length;
|
|
53
|
+
for (let segIndex = 0; segIndex < numSegments; segIndex++) {
|
|
54
|
+
const segment = segments[segIndex];
|
|
55
|
+
|
|
56
|
+
// Skip empty segments
|
|
57
|
+
if (!segment) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const sliceContours = [];
|
|
62
|
+
const scalars = vtkDataArray.newInstance({
|
|
63
|
+
name: 'Scalars',
|
|
64
|
+
numberOfComponents: 1,
|
|
65
|
+
size: pixelsPerSlice * numSlices,
|
|
66
|
+
dataType: 'Uint8Array',
|
|
67
|
+
});
|
|
68
|
+
const { containedSegmentIndices } = segment;
|
|
69
|
+
for (let sliceIndex = 0; sliceIndex < numSlices; sliceIndex++) {
|
|
70
|
+
// Check if the slice is empty before running marching cube
|
|
71
|
+
if (
|
|
72
|
+
isSliceEmptyForSegment(sliceIndex, segData, pixelsPerSlice, segIndex)
|
|
73
|
+
) {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
const frameStart = sliceIndex * pixelsPerSlice;
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
// Modify segData for this specific segment directly
|
|
80
|
+
for (let i = 0; i < pixelsPerSlice; i++) {
|
|
81
|
+
const value = segData[i + frameStart];
|
|
82
|
+
if (value === segIndex || containedSegmentIndices?.has(value)) {
|
|
83
|
+
(scalars as any).setValue(i + frameStart, 1);
|
|
84
|
+
} else {
|
|
85
|
+
(scalars as any).setValue(i, 0);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const mSquares = vtkImageMarchingSquares.newInstance({
|
|
90
|
+
slice: sliceIndex,
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// filter out the scalar data so that only it has background and
|
|
94
|
+
// the current segment index
|
|
95
|
+
const imageDataCopy = vtkImageData.newInstance();
|
|
96
|
+
|
|
97
|
+
imageDataCopy.shallowCopy(vol.imageData);
|
|
98
|
+
imageDataCopy.getPointData().setScalars(scalars);
|
|
99
|
+
|
|
100
|
+
// Connect pipeline
|
|
101
|
+
mSquares.setInputData(imageDataCopy);
|
|
102
|
+
const cValues = [1];
|
|
103
|
+
mSquares.setContourValues(cValues);
|
|
104
|
+
mSquares.setMergePoints(false);
|
|
105
|
+
|
|
106
|
+
// Perform marching squares
|
|
107
|
+
const msOutput = mSquares.getOutputData();
|
|
108
|
+
|
|
109
|
+
// Clean up output from marching squares
|
|
110
|
+
const reducedSet = removeDuplicatePoints(msOutput);
|
|
111
|
+
if (reducedSet.points?.length) {
|
|
112
|
+
const contours = findContoursFromReducedSet(reducedSet.lines);
|
|
113
|
+
|
|
114
|
+
sliceContours.push({
|
|
115
|
+
referencedImageId: imageVol.imageIds[sliceIndex],
|
|
116
|
+
contours,
|
|
117
|
+
polyData: reducedSet,
|
|
118
|
+
FrameNumber: sliceIndex + 1,
|
|
119
|
+
sliceIndex,
|
|
120
|
+
FrameOfReferenceUID,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
} catch (e) {
|
|
124
|
+
console.warn(sliceIndex);
|
|
125
|
+
console.warn(e);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const metadata = {
|
|
130
|
+
referencedImageId: imageVol.imageIds[0], // just use 0 for overall
|
|
131
|
+
FrameOfReferenceUID,
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const ContourSet = {
|
|
135
|
+
label: segment.label,
|
|
136
|
+
color: segment.color,
|
|
137
|
+
metadata,
|
|
138
|
+
sliceContours,
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
ContourSets.push(ContourSet);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return ContourSets;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function isSliceEmptyForSegment(sliceIndex, segData, pixelsPerSlice, segIndex) {
|
|
148
|
+
const startIdx = sliceIndex * pixelsPerSlice;
|
|
149
|
+
const endIdx = startIdx + pixelsPerSlice;
|
|
150
|
+
|
|
151
|
+
for (let i = startIdx; i < endIdx; i++) {
|
|
152
|
+
if (segData[i] === segIndex) {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export { generateContourSetsFromLabelmap };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import contourFinder from './contourFinder';
|
|
2
|
+
import mergePoints from './mergePoints';
|
|
3
|
+
import detectContourHoles from './detectContourHoles';
|
|
4
|
+
import { generateContourSetsFromLabelmap } from './generateContourSetsFromLabelmap';
|
|
5
|
+
|
|
6
|
+
import AnnotationToPointData from './AnnotationToPointData';
|
|
7
|
+
|
|
8
|
+
export {
|
|
9
|
+
contourFinder,
|
|
10
|
+
mergePoints,
|
|
11
|
+
detectContourHoles,
|
|
12
|
+
generateContourSetsFromLabelmap,
|
|
13
|
+
AnnotationToPointData,
|
|
14
|
+
};
|