@cornerstonejs/tools 1.36.3 → 1.37.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/drawingSvg/drawEllipse.js +1 -1
- package/dist/cjs/drawingSvg/drawEllipse.js.map +1 -1
- package/dist/cjs/drawingSvg/drawEllipseByCoordinates.js +2 -3
- package/dist/cjs/drawingSvg/drawEllipseByCoordinates.js.map +1 -1
- package/dist/cjs/enums/StrategyCallbacks.d.ts +13 -0
- package/dist/cjs/enums/StrategyCallbacks.js +17 -0
- package/dist/cjs/enums/StrategyCallbacks.js.map +1 -0
- package/dist/cjs/enums/index.d.ts +2 -1
- package/dist/cjs/enums/index.js +3 -1
- package/dist/cjs/enums/index.js.map +1 -1
- package/dist/cjs/eventDispatchers/keyboardEventHandlers/keyDown.js +17 -7
- package/dist/cjs/eventDispatchers/keyboardEventHandlers/keyDown.js.map +1 -1
- package/dist/cjs/eventDispatchers/shared/getActiveToolForKeyboardEvent.js +4 -1
- package/dist/cjs/eventDispatchers/shared/getActiveToolForKeyboardEvent.js.map +1 -1
- package/dist/cjs/eventDispatchers/shared/getToolsWithActionsForKeyboardEvents.d.ts +3 -0
- package/dist/cjs/eventDispatchers/shared/getToolsWithActionsForKeyboardEvents.js +33 -0
- package/dist/cjs/eventDispatchers/shared/getToolsWithActionsForKeyboardEvents.js.map +1 -0
- package/dist/cjs/eventDispatchers/shared/getToolsWithActionsForMouseEvent.js.map +1 -1
- package/dist/cjs/stateManagement/segmentation/config/segmentationColor.js +8 -1
- package/dist/cjs/stateManagement/segmentation/config/segmentationColor.js.map +1 -1
- package/dist/cjs/tools/annotation/EllipticalROITool.js +1 -2
- package/dist/cjs/tools/annotation/EllipticalROITool.js.map +1 -1
- package/dist/cjs/tools/base/AnnotationTool.js.map +1 -1
- package/dist/cjs/tools/base/BaseTool.d.ts +2 -0
- package/dist/cjs/tools/base/BaseTool.js +7 -1
- package/dist/cjs/tools/base/BaseTool.js.map +1 -1
- package/dist/cjs/tools/segmentation/BrushTool.d.ts +45 -3
- package/dist/cjs/tools/segmentation/BrushTool.js +197 -71
- package/dist/cjs/tools/segmentation/BrushTool.js.map +1 -1
- package/dist/cjs/tools/segmentation/CircleScissorsTool.js +3 -1
- package/dist/cjs/tools/segmentation/CircleScissorsTool.js.map +1 -1
- package/dist/cjs/tools/segmentation/SphereScissorsTool.js +3 -0
- package/dist/cjs/tools/segmentation/SphereScissorsTool.js.map +1 -1
- package/dist/cjs/tools/segmentation/strategies/BrushStrategy.d.ts +87 -0
- package/dist/cjs/tools/segmentation/strategies/BrushStrategy.js +137 -0
- package/dist/cjs/tools/segmentation/strategies/BrushStrategy.js.map +1 -0
- package/dist/cjs/tools/segmentation/strategies/compositions/determineSegmentIndex.d.ts +6 -0
- package/dist/cjs/tools/segmentation/strategies/compositions/determineSegmentIndex.js +53 -0
- package/dist/cjs/tools/segmentation/strategies/compositions/determineSegmentIndex.js.map +1 -0
- package/dist/cjs/tools/segmentation/strategies/compositions/dynamicThreshold.d.ts +6 -0
- package/dist/cjs/tools/segmentation/strategies/compositions/dynamicThreshold.js +41 -0
- package/dist/cjs/tools/segmentation/strategies/compositions/dynamicThreshold.js.map +1 -0
- package/dist/cjs/tools/segmentation/strategies/compositions/erase.d.ts +5 -0
- package/dist/cjs/tools/segmentation/strategies/compositions/erase.js +12 -0
- package/dist/cjs/tools/segmentation/strategies/compositions/erase.js.map +1 -0
- package/dist/cjs/tools/segmentation/strategies/compositions/index.d.ts +35 -0
- package/dist/cjs/tools/segmentation/strategies/compositions/index.js +24 -0
- package/dist/cjs/tools/segmentation/strategies/compositions/index.js.map +1 -0
- package/dist/cjs/tools/segmentation/strategies/compositions/islandRemoval.d.ts +5 -0
- package/dist/cjs/tools/segmentation/strategies/compositions/islandRemoval.js +129 -0
- package/dist/cjs/tools/segmentation/strategies/compositions/islandRemoval.js.map +1 -0
- package/dist/cjs/tools/segmentation/strategies/compositions/preview.d.ts +8 -0
- package/dist/cjs/tools/segmentation/strategies/compositions/preview.js +84 -0
- package/dist/cjs/tools/segmentation/strategies/compositions/preview.js.map +1 -0
- package/dist/cjs/tools/segmentation/strategies/compositions/regionFill.d.ts +5 -0
- package/dist/cjs/tools/segmentation/strategies/compositions/regionFill.js +27 -0
- package/dist/cjs/tools/segmentation/strategies/compositions/regionFill.js.map +1 -0
- package/dist/cjs/tools/segmentation/strategies/compositions/setValue.d.ts +8 -0
- package/dist/cjs/tools/segmentation/strategies/compositions/setValue.js +33 -0
- package/dist/cjs/tools/segmentation/strategies/compositions/setValue.js.map +1 -0
- package/dist/cjs/tools/segmentation/strategies/compositions/threshold.d.ts +5 -0
- package/dist/cjs/tools/segmentation/strategies/compositions/threshold.js +24 -0
- package/dist/cjs/tools/segmentation/strategies/compositions/threshold.js.map +1 -0
- package/dist/cjs/tools/segmentation/strategies/eraseCircle.d.ts +2 -7
- package/dist/cjs/tools/segmentation/strategies/eraseCircle.js +7 -4
- package/dist/cjs/tools/segmentation/strategies/eraseCircle.js.map +1 -1
- package/dist/cjs/tools/segmentation/strategies/eraseSphere.d.ts +2 -7
- package/dist/cjs/tools/segmentation/strategies/eraseSphere.js +7 -6
- package/dist/cjs/tools/segmentation/strategies/eraseSphere.js.map +1 -1
- package/dist/cjs/tools/segmentation/strategies/fillCircle.d.ts +13 -8
- package/dist/cjs/tools/segmentation/strategies/fillCircle.js +68 -90
- package/dist/cjs/tools/segmentation/strategies/fillCircle.js.map +1 -1
- package/dist/cjs/tools/segmentation/strategies/fillRectangle.js +3 -9
- package/dist/cjs/tools/segmentation/strategies/fillRectangle.js.map +1 -1
- package/dist/cjs/tools/segmentation/strategies/fillSphere.d.ts +6 -9
- package/dist/cjs/tools/segmentation/strategies/fillSphere.js +53 -64
- package/dist/cjs/tools/segmentation/strategies/fillSphere.js.map +1 -1
- package/dist/cjs/tools/segmentation/strategies/utils/getStrategyData.d.ts +3 -0
- package/dist/cjs/tools/segmentation/strategies/utils/getStrategyData.js +6 -0
- package/dist/cjs/tools/segmentation/strategies/utils/getStrategyData.js.map +1 -1
- package/dist/cjs/tools/segmentation/strategies/utils/isWithinThreshold.d.ts +2 -2
- package/dist/cjs/tools/segmentation/strategies/utils/isWithinThreshold.js +2 -2
- package/dist/cjs/tools/segmentation/strategies/utils/isWithinThreshold.js.map +1 -1
- package/dist/cjs/types/BoundsIJK.d.ts +1 -1
- package/dist/cjs/types/FloodFillTypes.d.ts +4 -4
- package/dist/cjs/types/LabelmapToolOperationData.d.ts +7 -2
- package/dist/cjs/types/index.d.ts +2 -1
- package/dist/cjs/utilities/math/ellipse/getCanvasEllipseCorners.d.ts +2 -3
- package/dist/cjs/utilities/math/ellipse/index.d.ts +2 -2
- package/dist/cjs/utilities/math/ellipse/index.js +26 -2
- package/dist/cjs/utilities/math/ellipse/index.js.map +1 -1
- package/dist/cjs/utilities/math/ellipse/pointInEllipse.d.ts +4 -1
- package/dist/cjs/utilities/math/ellipse/pointInEllipse.js +30 -17
- package/dist/cjs/utilities/math/ellipse/pointInEllipse.js.map +1 -1
- package/dist/cjs/utilities/math/sphere/pointInSphere.d.ts +1 -0
- package/dist/cjs/utilities/math/sphere/pointInSphere.js +2 -1
- package/dist/cjs/utilities/math/sphere/pointInSphere.js.map +1 -1
- package/dist/cjs/utilities/segmentation/brushThresholdForToolGroup.d.ts +1 -1
- package/dist/cjs/utilities/segmentation/brushThresholdForToolGroup.js +5 -5
- package/dist/cjs/utilities/segmentation/brushThresholdForToolGroup.js.map +1 -1
- package/dist/esm/drawingSvg/drawEllipse.js +1 -1
- package/dist/esm/drawingSvg/drawEllipse.js.map +1 -1
- package/dist/esm/drawingSvg/drawEllipseByCoordinates.js +2 -3
- package/dist/esm/drawingSvg/drawEllipseByCoordinates.js.map +1 -1
- package/dist/esm/enums/StrategyCallbacks.js +15 -0
- package/dist/esm/enums/StrategyCallbacks.js.map +1 -0
- package/dist/esm/enums/index.js +2 -1
- package/dist/esm/enums/index.js.map +1 -1
- package/dist/esm/eventDispatchers/keyboardEventHandlers/keyDown.js +17 -7
- package/dist/esm/eventDispatchers/keyboardEventHandlers/keyDown.js.map +1 -1
- package/dist/esm/eventDispatchers/shared/getActiveToolForKeyboardEvent.js +4 -1
- package/dist/esm/eventDispatchers/shared/getActiveToolForKeyboardEvent.js.map +1 -1
- package/dist/esm/eventDispatchers/shared/getToolsWithActionsForKeyboardEvents.js +29 -0
- package/dist/esm/eventDispatchers/shared/getToolsWithActionsForKeyboardEvents.js.map +1 -0
- package/dist/esm/eventDispatchers/shared/getToolsWithActionsForMouseEvent.js.map +1 -1
- package/dist/esm/stateManagement/segmentation/config/segmentationColor.js +8 -1
- package/dist/esm/stateManagement/segmentation/config/segmentationColor.js.map +1 -1
- package/dist/esm/tools/annotation/EllipticalROITool.js +1 -2
- package/dist/esm/tools/annotation/EllipticalROITool.js.map +1 -1
- package/dist/esm/tools/base/AnnotationTool.js.map +1 -1
- package/dist/esm/tools/base/BaseTool.js +5 -1
- package/dist/esm/tools/base/BaseTool.js.map +1 -1
- package/dist/esm/tools/segmentation/BrushTool.js +208 -87
- package/dist/esm/tools/segmentation/BrushTool.js.map +1 -1
- package/dist/esm/tools/segmentation/CircleScissorsTool.js +3 -0
- package/dist/esm/tools/segmentation/CircleScissorsTool.js.map +1 -1
- package/dist/esm/tools/segmentation/SphereScissorsTool.js +3 -0
- package/dist/esm/tools/segmentation/SphereScissorsTool.js.map +1 -1
- package/dist/esm/tools/segmentation/strategies/BrushStrategy.js +136 -0
- package/dist/esm/tools/segmentation/strategies/BrushStrategy.js.map +1 -0
- package/dist/esm/tools/segmentation/strategies/compositions/determineSegmentIndex.js +48 -0
- package/dist/esm/tools/segmentation/strategies/compositions/determineSegmentIndex.js.map +1 -0
- package/dist/esm/tools/segmentation/strategies/compositions/dynamicThreshold.js +35 -0
- package/dist/esm/tools/segmentation/strategies/compositions/dynamicThreshold.js.map +1 -0
- package/dist/esm/tools/segmentation/strategies/compositions/erase.js +7 -0
- package/dist/esm/tools/segmentation/strategies/compositions/erase.js.map +1 -0
- package/dist/esm/tools/segmentation/strategies/compositions/index.js +19 -0
- package/dist/esm/tools/segmentation/strategies/compositions/index.js.map +1 -0
- package/dist/esm/tools/segmentation/strategies/compositions/islandRemoval.js +124 -0
- package/dist/esm/tools/segmentation/strategies/compositions/islandRemoval.js.map +1 -0
- package/dist/esm/tools/segmentation/strategies/compositions/preview.js +77 -0
- package/dist/esm/tools/segmentation/strategies/compositions/preview.js.map +1 -0
- package/dist/esm/tools/segmentation/strategies/compositions/regionFill.js +21 -0
- package/dist/esm/tools/segmentation/strategies/compositions/regionFill.js.map +1 -0
- package/dist/esm/tools/segmentation/strategies/compositions/setValue.js +28 -0
- package/dist/esm/tools/segmentation/strategies/compositions/setValue.js.map +1 -0
- package/dist/esm/tools/segmentation/strategies/compositions/threshold.js +19 -0
- package/dist/esm/tools/segmentation/strategies/compositions/threshold.js.map +1 -0
- package/dist/esm/tools/segmentation/strategies/eraseCircle.js +6 -8
- package/dist/esm/tools/segmentation/strategies/eraseCircle.js.map +1 -1
- package/dist/esm/tools/segmentation/strategies/eraseSphere.js +6 -7
- package/dist/esm/tools/segmentation/strategies/eraseSphere.js.map +1 -1
- package/dist/esm/tools/segmentation/strategies/fillCircle.js +64 -88
- package/dist/esm/tools/segmentation/strategies/fillCircle.js.map +1 -1
- package/dist/esm/tools/segmentation/strategies/fillRectangle.js +3 -9
- package/dist/esm/tools/segmentation/strategies/fillRectangle.js.map +1 -1
- package/dist/esm/tools/segmentation/strategies/fillSphere.js +53 -64
- package/dist/esm/tools/segmentation/strategies/fillSphere.js.map +1 -1
- package/dist/esm/tools/segmentation/strategies/utils/getStrategyData.js +7 -1
- package/dist/esm/tools/segmentation/strategies/utils/getStrategyData.js.map +1 -1
- package/dist/esm/tools/segmentation/strategies/utils/isWithinThreshold.js +2 -2
- package/dist/esm/tools/segmentation/strategies/utils/isWithinThreshold.js.map +1 -1
- package/dist/esm/utilities/math/ellipse/index.js +2 -2
- package/dist/esm/utilities/math/ellipse/index.js.map +1 -1
- package/dist/esm/utilities/math/ellipse/pointInEllipse.js +28 -16
- package/dist/esm/utilities/math/ellipse/pointInEllipse.js.map +1 -1
- package/dist/esm/utilities/math/sphere/pointInSphere.js +2 -1
- package/dist/esm/utilities/math/sphere/pointInSphere.js.map +1 -1
- package/dist/esm/utilities/segmentation/brushThresholdForToolGroup.js +11 -5
- package/dist/esm/utilities/segmentation/brushThresholdForToolGroup.js.map +1 -1
- package/dist/types/drawingSvg/drawEllipseByCoordinates.d.ts.map +1 -1
- package/dist/types/enums/StrategyCallbacks.d.ts +14 -0
- package/dist/types/enums/StrategyCallbacks.d.ts.map +1 -0
- package/dist/types/enums/index.d.ts +2 -1
- package/dist/types/eventDispatchers/keyboardEventHandlers/keyDown.d.ts.map +1 -1
- package/dist/types/eventDispatchers/shared/getActiveToolForKeyboardEvent.d.ts.map +1 -1
- package/dist/types/eventDispatchers/shared/getToolsWithActionsForKeyboardEvents.d.ts +4 -0
- package/dist/types/eventDispatchers/shared/getToolsWithActionsForKeyboardEvents.d.ts.map +1 -0
- package/dist/types/eventDispatchers/shared/getToolsWithActionsForMouseEvent.d.ts.map +1 -1
- package/dist/types/stateManagement/segmentation/config/segmentationColor.d.ts.map +1 -1
- package/dist/types/tools/annotation/EllipticalROITool.d.ts.map +1 -1
- package/dist/types/tools/base/AnnotationTool.d.ts.map +1 -1
- package/dist/types/tools/base/BaseTool.d.ts +2 -0
- package/dist/types/tools/base/BaseTool.d.ts.map +1 -1
- package/dist/types/tools/segmentation/BrushTool.d.ts +45 -3
- package/dist/types/tools/segmentation/BrushTool.d.ts.map +1 -1
- package/dist/types/tools/segmentation/CircleScissorsTool.d.ts.map +1 -1
- package/dist/types/tools/segmentation/SphereScissorsTool.d.ts.map +1 -1
- package/dist/types/tools/segmentation/strategies/BrushStrategy.d.ts +88 -0
- package/dist/types/tools/segmentation/strategies/BrushStrategy.d.ts.map +1 -0
- package/dist/types/tools/segmentation/strategies/compositions/determineSegmentIndex.d.ts +7 -0
- package/dist/types/tools/segmentation/strategies/compositions/determineSegmentIndex.d.ts.map +1 -0
- package/dist/types/tools/segmentation/strategies/compositions/dynamicThreshold.d.ts +7 -0
- package/dist/types/tools/segmentation/strategies/compositions/dynamicThreshold.d.ts.map +1 -0
- package/dist/types/tools/segmentation/strategies/compositions/erase.d.ts +6 -0
- package/dist/types/tools/segmentation/strategies/compositions/erase.d.ts.map +1 -0
- package/dist/types/tools/segmentation/strategies/compositions/index.d.ts +36 -0
- package/dist/types/tools/segmentation/strategies/compositions/index.d.ts.map +1 -0
- package/dist/types/tools/segmentation/strategies/compositions/islandRemoval.d.ts +6 -0
- package/dist/types/tools/segmentation/strategies/compositions/islandRemoval.d.ts.map +1 -0
- package/dist/types/tools/segmentation/strategies/compositions/preview.d.ts +9 -0
- package/dist/types/tools/segmentation/strategies/compositions/preview.d.ts.map +1 -0
- package/dist/types/tools/segmentation/strategies/compositions/regionFill.d.ts +6 -0
- package/dist/types/tools/segmentation/strategies/compositions/regionFill.d.ts.map +1 -0
- package/dist/types/tools/segmentation/strategies/compositions/setValue.d.ts +9 -0
- package/dist/types/tools/segmentation/strategies/compositions/setValue.d.ts.map +1 -0
- package/dist/types/tools/segmentation/strategies/compositions/threshold.d.ts +6 -0
- package/dist/types/tools/segmentation/strategies/compositions/threshold.d.ts.map +1 -0
- package/dist/types/tools/segmentation/strategies/eraseCircle.d.ts +2 -7
- package/dist/types/tools/segmentation/strategies/eraseCircle.d.ts.map +1 -1
- package/dist/types/tools/segmentation/strategies/eraseSphere.d.ts +2 -7
- package/dist/types/tools/segmentation/strategies/eraseSphere.d.ts.map +1 -1
- package/dist/types/tools/segmentation/strategies/fillCircle.d.ts +13 -8
- package/dist/types/tools/segmentation/strategies/fillCircle.d.ts.map +1 -1
- package/dist/types/tools/segmentation/strategies/fillRectangle.d.ts.map +1 -1
- package/dist/types/tools/segmentation/strategies/fillSphere.d.ts +6 -9
- package/dist/types/tools/segmentation/strategies/fillSphere.d.ts.map +1 -1
- package/dist/types/tools/segmentation/strategies/utils/getStrategyData.d.ts +3 -0
- package/dist/types/tools/segmentation/strategies/utils/getStrategyData.d.ts.map +1 -1
- package/dist/types/tools/segmentation/strategies/utils/isWithinThreshold.d.ts +2 -2
- package/dist/types/tools/segmentation/strategies/utils/isWithinThreshold.d.ts.map +1 -1
- package/dist/types/types/BoundsIJK.d.ts +1 -1
- package/dist/types/types/BoundsIJK.d.ts.map +1 -1
- package/dist/types/types/FloodFillTypes.d.ts +4 -4
- package/dist/types/types/FloodFillTypes.d.ts.map +1 -1
- package/dist/types/types/LabelmapToolOperationData.d.ts +7 -2
- package/dist/types/types/LabelmapToolOperationData.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/math/ellipse/getCanvasEllipseCorners.d.ts +2 -3
- package/dist/types/utilities/math/ellipse/getCanvasEllipseCorners.d.ts.map +1 -1
- package/dist/types/utilities/math/ellipse/index.d.ts +2 -2
- package/dist/types/utilities/math/ellipse/index.d.ts.map +1 -1
- package/dist/types/utilities/math/ellipse/pointInEllipse.d.ts +4 -1
- package/dist/types/utilities/math/ellipse/pointInEllipse.d.ts.map +1 -1
- package/dist/types/utilities/math/sphere/pointInSphere.d.ts +1 -0
- package/dist/types/utilities/math/sphere/pointInSphere.d.ts.map +1 -1
- package/dist/types/utilities/segmentation/brushThresholdForToolGroup.d.ts +1 -1
- package/dist/types/utilities/segmentation/brushThresholdForToolGroup.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/drawingSvg/drawEllipse.ts +8 -8
- package/src/drawingSvg/drawEllipseByCoordinates.ts +4 -4
- package/src/enums/StrategyCallbacks.ts +52 -0
- package/src/enums/index.js +2 -0
- package/src/eventDispatchers/keyboardEventHandlers/keyDown.ts +22 -11
- package/src/eventDispatchers/shared/getActiveToolForKeyboardEvent.ts +6 -2
- package/src/eventDispatchers/shared/getToolsWithActionsForKeyboardEvents.ts +53 -0
- package/src/eventDispatchers/shared/getToolsWithActionsForMouseEvent.ts +0 -2
- package/src/stateManagement/segmentation/config/segmentationColor.ts +8 -1
- package/src/tools/annotation/EllipticalROITool.ts +1 -3
- package/src/tools/base/AnnotationTool.ts +0 -1
- package/src/tools/base/BaseTool.ts +32 -2
- package/src/tools/segmentation/BrushTool.ts +298 -68
- package/src/tools/segmentation/CircleScissorsTool.ts +3 -1
- package/src/tools/segmentation/SphereScissorsTool.ts +3 -0
- package/src/tools/segmentation/strategies/BrushStrategy.ts +364 -0
- package/src/tools/segmentation/strategies/compositions/determineSegmentIndex.ts +86 -0
- package/src/tools/segmentation/strategies/compositions/dynamicThreshold.ts +58 -0
- package/src/tools/segmentation/strategies/compositions/erase.ts +11 -0
- package/src/tools/segmentation/strategies/compositions/index.ts +19 -0
- package/src/tools/segmentation/strategies/compositions/islandRemoval.ts +179 -0
- package/src/tools/segmentation/strategies/compositions/preview.ts +138 -0
- package/src/tools/segmentation/strategies/compositions/regionFill.ts +45 -0
- package/src/tools/segmentation/strategies/compositions/setValue.ts +50 -0
- package/src/tools/segmentation/strategies/compositions/threshold.ts +35 -0
- package/src/tools/segmentation/strategies/eraseCircle.ts +10 -19
- package/src/tools/segmentation/strategies/eraseSphere.ts +10 -18
- package/src/tools/segmentation/strategies/fillCircle.ts +141 -164
- package/src/tools/segmentation/strategies/fillRectangle.ts +3 -13
- package/src/tools/segmentation/strategies/fillSphere.ts +105 -120
- package/src/tools/segmentation/strategies/utils/getStrategyData.ts +15 -1
- package/src/tools/segmentation/strategies/utils/isWithinThreshold.ts +5 -5
- package/src/types/BoundsIJK.ts +1 -1
- package/src/types/FloodFillTypes.ts +4 -4
- package/src/types/LabelmapToolOperationData.ts +20 -1
- package/src/types/index.ts +2 -0
- package/src/utilities/math/ellipse/getCanvasEllipseCorners.ts +2 -2
- package/src/utilities/math/ellipse/index.ts +2 -2
- package/src/utilities/math/ellipse/pointInEllipse.ts +52 -18
- package/src/utilities/math/sphere/pointInSphere.ts +10 -2
- package/src/utilities/segmentation/brushThresholdForToolGroup.ts +12 -5
|
@@ -1,111 +1,155 @@
|
|
|
1
1
|
import { vec3 } from 'gl-matrix';
|
|
2
|
-
import type { Types } from '@cornerstonejs/core';
|
|
3
|
-
import { cache } from '@cornerstonejs/core';
|
|
4
2
|
import { utilities as csUtils } from '@cornerstonejs/core';
|
|
3
|
+
import type { Types } from '@cornerstonejs/core';
|
|
5
4
|
|
|
6
5
|
import {
|
|
7
6
|
getCanvasEllipseCorners,
|
|
8
|
-
|
|
7
|
+
precalculatePointInEllipse,
|
|
9
8
|
} from '../../../utilities/math/ellipse';
|
|
9
|
+
import pointInSphere from '../../../utilities/math/sphere/pointInSphere';
|
|
10
10
|
import { getBoundingBoxAroundShape } from '../../../utilities/boundingBox';
|
|
11
|
-
import
|
|
12
|
-
import {
|
|
13
|
-
import
|
|
14
|
-
import {
|
|
15
|
-
import
|
|
16
|
-
import { isVolumeSegmentation } from './utils/stackVolumeCheck';
|
|
11
|
+
import BrushStrategy from './BrushStrategy';
|
|
12
|
+
import type { Composition, InitializedOperationData } from './BrushStrategy';
|
|
13
|
+
import type { CanvasCoordinates } from '../../../types';
|
|
14
|
+
import { StrategyCallbacks } from '../../../enums';
|
|
15
|
+
import compositions from './compositions';
|
|
17
16
|
|
|
18
17
|
const { transformWorldToIndex } = csUtils;
|
|
18
|
+
const EPSILON = 1e-4;
|
|
19
|
+
const nearOrZero = (testValue, nearValue) =>
|
|
20
|
+
Math.abs(testValue) < EPSILON || Math.abs(testValue - nearValue) < EPSILON;
|
|
21
|
+
|
|
22
|
+
const initializeCircle = {
|
|
23
|
+
[StrategyCallbacks.Initialize]: (operationData: InitializedOperationData) => {
|
|
24
|
+
const {
|
|
25
|
+
points,
|
|
26
|
+
imageVoxelManager: imageVoxelManager,
|
|
27
|
+
viewport,
|
|
28
|
+
segmentationImageData,
|
|
29
|
+
segmentationVoxelManager: segmentationVoxelManager,
|
|
30
|
+
} = operationData;
|
|
31
|
+
|
|
32
|
+
// Happens on a preview setup
|
|
33
|
+
if (!points) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
// Average the points to get the center of the ellipse
|
|
37
|
+
const center = vec3.fromValues(0, 0, 0);
|
|
38
|
+
points.forEach((point) => {
|
|
39
|
+
vec3.add(center, center, point);
|
|
40
|
+
});
|
|
41
|
+
vec3.scale(center, center, 1 / points.length);
|
|
42
|
+
|
|
43
|
+
operationData.centerWorld = center as Types.Point3;
|
|
44
|
+
operationData.centerIJK = transformWorldToIndex(
|
|
45
|
+
segmentationImageData,
|
|
46
|
+
center as Types.Point3
|
|
47
|
+
);
|
|
48
|
+
const canvasCoordinates = points.map((p) =>
|
|
49
|
+
viewport.worldToCanvas(p)
|
|
50
|
+
) as CanvasCoordinates;
|
|
51
|
+
|
|
52
|
+
// 1. From the drawn tool: Get the ellipse (circle) topLeft and bottomRight
|
|
53
|
+
// corners in canvas coordinates
|
|
54
|
+
const [topLeftCanvas, bottomRightCanvas] =
|
|
55
|
+
getCanvasEllipseCorners(canvasCoordinates);
|
|
56
|
+
|
|
57
|
+
// 2. Find the extent of the ellipse (circle) in IJK index space of the image
|
|
58
|
+
const topLeftWorld = viewport.canvasToWorld(topLeftCanvas);
|
|
59
|
+
const bottomRightWorld = viewport.canvasToWorld(bottomRightCanvas);
|
|
60
|
+
|
|
61
|
+
const ellipsoidCornersIJK = [
|
|
62
|
+
<Types.Point3>transformWorldToIndex(segmentationImageData, topLeftWorld),
|
|
63
|
+
<Types.Point3>(
|
|
64
|
+
transformWorldToIndex(segmentationImageData, bottomRightWorld)
|
|
65
|
+
),
|
|
66
|
+
];
|
|
67
|
+
|
|
68
|
+
segmentationVoxelManager.boundsIJK = getBoundingBoxAroundShape(
|
|
69
|
+
ellipsoidCornersIJK,
|
|
70
|
+
segmentationVoxelManager.dimensions
|
|
71
|
+
);
|
|
72
|
+
imageVoxelManager.isInObject = createPointInEllipse({
|
|
73
|
+
topLeftWorld,
|
|
74
|
+
bottomRightWorld,
|
|
75
|
+
center,
|
|
76
|
+
});
|
|
77
|
+
},
|
|
78
|
+
} as Composition;
|
|
19
79
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
function
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if (
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
viewport,
|
|
50
|
-
segmentationImageData,
|
|
51
|
-
points
|
|
52
|
-
);
|
|
53
|
-
|
|
54
|
-
const modifiedSlicesToUse = new Set() as Set<number>;
|
|
55
|
-
|
|
56
|
-
let callback;
|
|
57
|
-
|
|
58
|
-
if (threshold) {
|
|
59
|
-
callback = ({ value, index, pointIJK }) => {
|
|
60
|
-
if (segmentsLocked.includes(value)) {
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (
|
|
65
|
-
isWithinThreshold(index, imageScalarData, strategySpecificConfiguration)
|
|
66
|
-
) {
|
|
67
|
-
segmentationScalarData[index] = segmentIndex;
|
|
68
|
-
//Todo: I don't think this will always be index 2 in streamingImageVolume?
|
|
69
|
-
modifiedSlicesToUse.add(pointIJK[2]);
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
} else {
|
|
73
|
-
callback = ({ value, index, pointIJK }) => {
|
|
74
|
-
if (segmentsLocked.includes(value)) {
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
segmentationScalarData[index] = segmentIndex;
|
|
78
|
-
modifiedSlicesToUse.add(pointIJK[2]);
|
|
80
|
+
/**
|
|
81
|
+
* Creates a function that tells the user if the provided point in LPS space
|
|
82
|
+
* is inside the ellipse.
|
|
83
|
+
*
|
|
84
|
+
* This will return a sphere test function if the bounds are a circle or
|
|
85
|
+
* sphere shape (same radius in two or three dimensions), or an elliptical shape
|
|
86
|
+
* if they differ.
|
|
87
|
+
*/
|
|
88
|
+
function createPointInEllipse(worldInfo: {
|
|
89
|
+
topLeftWorld: Types.Point3;
|
|
90
|
+
bottomRightWorld: Types.Point3;
|
|
91
|
+
center: Types.Point3 | vec3;
|
|
92
|
+
}) {
|
|
93
|
+
const { topLeftWorld, bottomRightWorld, center } = worldInfo;
|
|
94
|
+
|
|
95
|
+
const xRadius = Math.abs(topLeftWorld[0] - bottomRightWorld[0]) / 2;
|
|
96
|
+
const yRadius = Math.abs(topLeftWorld[1] - bottomRightWorld[1]) / 2;
|
|
97
|
+
const zRadius = Math.abs(topLeftWorld[2] - bottomRightWorld[2]) / 2;
|
|
98
|
+
|
|
99
|
+
const radius = Math.max(xRadius, yRadius, zRadius);
|
|
100
|
+
if (
|
|
101
|
+
nearOrZero(xRadius, radius) &&
|
|
102
|
+
nearOrZero(yRadius, radius) &&
|
|
103
|
+
nearOrZero(zRadius, radius)
|
|
104
|
+
) {
|
|
105
|
+
const sphereObj = {
|
|
106
|
+
center,
|
|
107
|
+
radius,
|
|
108
|
+
radius2: radius * radius,
|
|
79
109
|
};
|
|
110
|
+
return (pointLPS) => pointInSphere(sphereObj, pointLPS);
|
|
80
111
|
}
|
|
112
|
+
// using circle as a form of ellipse
|
|
113
|
+
const ellipseObj = {
|
|
114
|
+
center: center as Types.Point3,
|
|
115
|
+
xRadius,
|
|
116
|
+
yRadius,
|
|
117
|
+
zRadius,
|
|
118
|
+
};
|
|
119
|
+
const inverts = precalculatePointInEllipse(ellipseObj);
|
|
120
|
+
const { precalculated } = inverts;
|
|
81
121
|
|
|
82
|
-
|
|
83
|
-
segmentationImageData,
|
|
84
|
-
(pointLPS) =>
|
|
85
|
-
pointInEllipse(ellipseObj, pointLPS, {
|
|
86
|
-
fast: true,
|
|
87
|
-
}),
|
|
88
|
-
callback,
|
|
89
|
-
boundsIJK
|
|
90
|
-
);
|
|
91
|
-
|
|
92
|
-
const arrayOfSlices: number[] = Array.from(modifiedSlicesToUse);
|
|
93
|
-
|
|
94
|
-
triggerSegmentationDataModified(segmentationId, arrayOfSlices);
|
|
122
|
+
return precalculated;
|
|
95
123
|
}
|
|
96
124
|
|
|
125
|
+
const CIRCLE_STRATEGY = new BrushStrategy(
|
|
126
|
+
'Circle',
|
|
127
|
+
compositions.regionFill,
|
|
128
|
+
compositions.setValue,
|
|
129
|
+
initializeCircle,
|
|
130
|
+
compositions.determineSegmentIndex,
|
|
131
|
+
compositions.preview
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
const CIRCLE_THRESHOLD_STRATEGY = new BrushStrategy(
|
|
135
|
+
'CircleThreshold',
|
|
136
|
+
compositions.regionFill,
|
|
137
|
+
compositions.setValue,
|
|
138
|
+
initializeCircle,
|
|
139
|
+
compositions.determineSegmentIndex,
|
|
140
|
+
compositions.dynamicThreshold,
|
|
141
|
+
compositions.threshold,
|
|
142
|
+
compositions.preview,
|
|
143
|
+
compositions.islandRemoval
|
|
144
|
+
);
|
|
145
|
+
|
|
97
146
|
/**
|
|
98
147
|
* Fill inside the circular region segment inside the segmentation defined by the operationData.
|
|
99
148
|
* It fills the segmentation pixels inside the defined circle.
|
|
100
149
|
* @param enabledElement - The element for which the segment is being erased.
|
|
101
150
|
* @param operationData - EraseOperationData
|
|
102
151
|
*/
|
|
103
|
-
|
|
104
|
-
enabledElement: Types.IEnabledElement,
|
|
105
|
-
operationData: OperationData
|
|
106
|
-
): void {
|
|
107
|
-
fillCircle(enabledElement, operationData, false);
|
|
108
|
-
}
|
|
152
|
+
const fillInsideCircle = CIRCLE_STRATEGY.strategyFunction;
|
|
109
153
|
|
|
110
154
|
/**
|
|
111
155
|
* Fill inside the circular region segment inside the segmentation defined by the operationData.
|
|
@@ -113,89 +157,22 @@ export function fillInsideCircle(
|
|
|
113
157
|
* @param enabledElement - The element for which the segment is being erased.
|
|
114
158
|
* @param operationData - EraseOperationData
|
|
115
159
|
*/
|
|
116
|
-
|
|
117
|
-
enabledElement: Types.IEnabledElement,
|
|
118
|
-
operationData: OperationData
|
|
119
|
-
): void {
|
|
120
|
-
if (isVolumeSegmentation(operationData)) {
|
|
121
|
-
const { referencedVolumeId, volumeId } = operationData;
|
|
122
|
-
|
|
123
|
-
const imageVolume = cache.getVolume(referencedVolumeId);
|
|
124
|
-
const segmentation = cache.getVolume(volumeId);
|
|
125
|
-
|
|
126
|
-
if (
|
|
127
|
-
!csUtils.isEqual(segmentation.dimensions, imageVolume.dimensions) ||
|
|
128
|
-
!csUtils.isEqual(segmentation.direction, imageVolume.direction)
|
|
129
|
-
) {
|
|
130
|
-
throw new Error(
|
|
131
|
-
'Only source data the same dimensions/size/orientation as the segmentation currently supported.'
|
|
132
|
-
);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
fillCircle(enabledElement, operationData, true);
|
|
137
|
-
}
|
|
160
|
+
const thresholdInsideCircle = CIRCLE_THRESHOLD_STRATEGY.strategyFunction;
|
|
138
161
|
|
|
139
162
|
/**
|
|
140
163
|
* Fill outside the circular region segment inside the segmentation defined by the operationData.
|
|
141
164
|
* It fills the segmentation pixels outside the defined circle.
|
|
142
|
-
j * @param enabledElement - The element for which the segment is being erased.
|
|
143
|
-
* @param operationData - EraseOperationData
|
|
144
|
-
*/
|
|
145
|
-
export function fillOutsideCircle(
|
|
146
|
-
enabledElement: Types.IEnabledElement,
|
|
147
|
-
operationData: OperationData
|
|
148
|
-
): void {
|
|
149
|
-
throw new Error('Not yet implemented');
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Fill inside the circular region segment inside the segmentation defined by the operationData.
|
|
154
|
-
* It fills the segmentation pixels inside the defined circle.
|
|
155
165
|
* @param enabledElement - The element for which the segment is being erased.
|
|
156
166
|
* @param operationData - EraseOperationData
|
|
157
167
|
*/
|
|
158
|
-
function
|
|
159
|
-
|
|
160
|
-
const center = vec3.fromValues(0, 0, 0);
|
|
161
|
-
points.forEach((point) => {
|
|
162
|
-
vec3.add(center, center, point);
|
|
163
|
-
});
|
|
164
|
-
vec3.scale(center, center, 1 / points.length);
|
|
165
|
-
return center;
|
|
168
|
+
export function fillOutsideCircle(): void {
|
|
169
|
+
throw new Error('Not yet implemented');
|
|
166
170
|
}
|
|
167
171
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
const [topLeftCanvas, bottomRightCanvas] =
|
|
176
|
-
getCanvasEllipseCorners(canvasCoordinates);
|
|
177
|
-
|
|
178
|
-
// 2. Find the extent of the ellipse (circle) in IJK index space of the image
|
|
179
|
-
const topLeftWorld = viewport.canvasToWorld(topLeftCanvas);
|
|
180
|
-
const bottomRightWorld = viewport.canvasToWorld(bottomRightCanvas);
|
|
181
|
-
|
|
182
|
-
const ellipsoidCornersIJK = [
|
|
183
|
-
<Types.Point3>transformWorldToIndex(imageData, topLeftWorld),
|
|
184
|
-
<Types.Point3>transformWorldToIndex(imageData, bottomRightWorld),
|
|
185
|
-
];
|
|
186
|
-
|
|
187
|
-
const boundsIJK = getBoundingBoxAroundShape(ellipsoidCornersIJK, dimensions);
|
|
188
|
-
|
|
189
|
-
if (boundsIJK.every(([min, max]) => min !== max)) {
|
|
190
|
-
throw new Error('Oblique segmentation tools are not supported yet');
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// using circle as a form of ellipse
|
|
194
|
-
const ellipseObj = {
|
|
195
|
-
center: center as Types.Point3,
|
|
196
|
-
xRadius: Math.abs(topLeftWorld[0] - bottomRightWorld[0]) / 2,
|
|
197
|
-
yRadius: Math.abs(topLeftWorld[1] - bottomRightWorld[1]) / 2,
|
|
198
|
-
zRadius: Math.abs(topLeftWorld[2] - bottomRightWorld[2]) / 2,
|
|
199
|
-
};
|
|
200
|
-
return { ellipseObj, boundsIJK };
|
|
201
|
-
}
|
|
172
|
+
export {
|
|
173
|
+
CIRCLE_STRATEGY,
|
|
174
|
+
CIRCLE_THRESHOLD_STRATEGY,
|
|
175
|
+
fillInsideCircle,
|
|
176
|
+
thresholdInsideCircle,
|
|
177
|
+
createPointInEllipse as createEllipseInPoint,
|
|
178
|
+
};
|
|
@@ -18,7 +18,6 @@ type OperationData = LabelmapToolOperationData & {
|
|
|
18
18
|
* the rectangle, set the scalar value to the segmentIndex
|
|
19
19
|
* @param toolGroupId - string
|
|
20
20
|
* @param operationData - OperationData
|
|
21
|
-
* @param constraintFn - can be used to perform threshold segmentation
|
|
22
21
|
* @param inside - boolean
|
|
23
22
|
*/
|
|
24
23
|
// Todo: why we have another constraintFn? in addition to the one in the operationData?
|
|
@@ -27,7 +26,7 @@ function fillRectangle(
|
|
|
27
26
|
operationData: OperationData,
|
|
28
27
|
inside = true
|
|
29
28
|
): void {
|
|
30
|
-
const { points, segmentsLocked, segmentIndex, segmentationId
|
|
29
|
+
const { points, segmentsLocked, segmentIndex, segmentationId } =
|
|
31
30
|
operationData;
|
|
32
31
|
|
|
33
32
|
const strategyData = getStrategyData({
|
|
@@ -61,19 +60,12 @@ function fillRectangle(
|
|
|
61
60
|
// Since always all points inside the boundsIJK is inside the rectangle...
|
|
62
61
|
const pointInRectangle = () => true;
|
|
63
62
|
|
|
64
|
-
const callback = ({ value, index
|
|
63
|
+
const callback = ({ value, index }) => {
|
|
65
64
|
if (segmentsLocked.includes(value)) {
|
|
66
65
|
return;
|
|
67
66
|
}
|
|
68
67
|
|
|
69
|
-
|
|
70
|
-
segmentationScalarData[index] = segmentIndex;
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (constraintFn(pointIJK)) {
|
|
75
|
-
segmentationScalarData[index] = segmentIndex;
|
|
76
|
-
}
|
|
68
|
+
segmentationScalarData[index] = segmentIndex;
|
|
77
69
|
};
|
|
78
70
|
|
|
79
71
|
pointInShapeCallback(
|
|
@@ -91,7 +83,6 @@ function fillRectangle(
|
|
|
91
83
|
* @param toolGroupId - The unique identifier of the tool group.
|
|
92
84
|
* @param operationData - The data that will be used to create the
|
|
93
85
|
* new rectangle.
|
|
94
|
-
* @param constraintFn - can be used to perform threshold segmentation
|
|
95
86
|
*/
|
|
96
87
|
export function fillInsideRectangle(
|
|
97
88
|
enabledElement: Types.IEnabledElement,
|
|
@@ -105,7 +96,6 @@ export function fillInsideRectangle(
|
|
|
105
96
|
* @param toolGroupId - The unique identifier of the tool group.
|
|
106
97
|
* @param operationData - The data that will be used to create the
|
|
107
98
|
* new rectangle.
|
|
108
|
-
* @param constraintFn - can be used to perform threshold segmentation
|
|
109
99
|
*/
|
|
110
100
|
export function fillOutsideRectangle(
|
|
111
101
|
enabledElement: Types.IEnabledElement,
|
|
@@ -1,94 +1,97 @@
|
|
|
1
1
|
import type { Types } from '@cornerstonejs/core';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
points
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
let callback;
|
|
42
|
-
|
|
43
|
-
if (threshold) {
|
|
44
|
-
callback = ({ value, index }) => {
|
|
45
|
-
if (segmentsLocked.includes(value)) {
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if (
|
|
50
|
-
isWithinThreshold(index, imageScalarData, strategySpecificConfiguration)
|
|
51
|
-
) {
|
|
52
|
-
segmentationScalarData[index] = segmentIndex;
|
|
53
|
-
scalarIndex.push(index);
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
} else {
|
|
57
|
-
callback = ({ index, value }) => {
|
|
58
|
-
if (segmentsLocked.includes(value)) {
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
segmentationScalarData[index] = segmentIndex;
|
|
62
|
-
scalarIndex.push(index);
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
pointInSurroundingSphereCallback(
|
|
67
|
-
segmentationImageData,
|
|
68
|
-
[points[0], points[1]],
|
|
69
|
-
callback,
|
|
70
|
-
viewport as Types.IVolumeViewport
|
|
71
|
-
);
|
|
72
|
-
|
|
73
|
-
const dimensions = segmentationImageData.getDimensions();
|
|
74
|
-
|
|
75
|
-
let sliceArray;
|
|
76
|
-
if (isVolumeSegmentation(operationData)) {
|
|
77
|
-
// Since the scalar indexes start from the top left corner of the cube, the first
|
|
78
|
-
// slice that needs to be rendered can be calculated from the first mask coordinate
|
|
79
|
-
// divided by the zMultiple, as well as the last slice for the last coordinate
|
|
80
|
-
const zMultiple = dimensions[0] * dimensions[1];
|
|
81
|
-
const minSlice = Math.floor(scalarIndex[0] / zMultiple);
|
|
82
|
-
const maxSlice = Math.floor(
|
|
83
|
-
scalarIndex[scalarIndex.length - 1] / zMultiple
|
|
2
|
+
import { utilities as csUtils } from '@cornerstonejs/core';
|
|
3
|
+
import { vec3 } from 'gl-matrix';
|
|
4
|
+
|
|
5
|
+
import { getCanvasEllipseCorners } from '../../../utilities/math/ellipse';
|
|
6
|
+
import { getBoundingBoxAroundShape } from '../../../utilities/boundingBox';
|
|
7
|
+
import BrushStrategy from './BrushStrategy';
|
|
8
|
+
import type { InitializedOperationData, Composition } from './BrushStrategy';
|
|
9
|
+
import type { CanvasCoordinates } from '../../../types';
|
|
10
|
+
import compositions from './compositions';
|
|
11
|
+
import StrategyCallbacks from '../../../enums/StrategyCallbacks';
|
|
12
|
+
import { createEllipseInPoint } from './fillCircle';
|
|
13
|
+
const { transformWorldToIndex } = csUtils;
|
|
14
|
+
|
|
15
|
+
const sphereComposition = {
|
|
16
|
+
[StrategyCallbacks.Initialize]: (operationData: InitializedOperationData) => {
|
|
17
|
+
const {
|
|
18
|
+
points,
|
|
19
|
+
imageVoxelManager: imageVoxelManager,
|
|
20
|
+
viewport,
|
|
21
|
+
segmentationImageData,
|
|
22
|
+
segmentationVoxelManager: segmentationVoxelManager,
|
|
23
|
+
} = operationData;
|
|
24
|
+
|
|
25
|
+
// Happens on a preview setup
|
|
26
|
+
if (!points) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
// Average the points to get the center of the ellipse
|
|
30
|
+
const center = vec3.fromValues(0, 0, 0);
|
|
31
|
+
points.forEach((point) => {
|
|
32
|
+
vec3.add(center, center, point);
|
|
33
|
+
});
|
|
34
|
+
vec3.scale(center, center, 1 / points.length);
|
|
35
|
+
|
|
36
|
+
operationData.centerWorld = center as Types.Point3;
|
|
37
|
+
operationData.centerIJK = transformWorldToIndex(
|
|
38
|
+
segmentationImageData,
|
|
39
|
+
center as Types.Point3
|
|
84
40
|
);
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
41
|
+
const canvasCoordinates = points.map((p) =>
|
|
42
|
+
viewport.worldToCanvas(p)
|
|
43
|
+
) as CanvasCoordinates;
|
|
44
|
+
|
|
45
|
+
// 1. From the drawn tool: Get the ellipse (circle) topLeft and bottomRight
|
|
46
|
+
// corners in canvas coordinates
|
|
47
|
+
const [topLeftCanvas, bottomRightCanvas] =
|
|
48
|
+
getCanvasEllipseCorners(canvasCoordinates);
|
|
49
|
+
|
|
50
|
+
// 2. Find the extent of the ellipse (circle) in IJK index space of the image
|
|
51
|
+
const topLeftWorld = viewport.canvasToWorld(topLeftCanvas);
|
|
52
|
+
const bottomRightWorld = viewport.canvasToWorld(bottomRightCanvas);
|
|
53
|
+
// This will be 2d, now expand to 3d
|
|
54
|
+
const diameters = topLeftWorld.map((left, index) =>
|
|
55
|
+
Math.abs(bottomRightWorld[index] - left)
|
|
88
56
|
);
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
57
|
+
const radius = Math.max(...diameters) / 2;
|
|
58
|
+
// Make 3d sphere
|
|
59
|
+
topLeftWorld.forEach((left, index) => {
|
|
60
|
+
const right = bottomRightWorld[index];
|
|
61
|
+
if (left === right) {
|
|
62
|
+
topLeftWorld[index] = left - radius;
|
|
63
|
+
bottomRightWorld[index] = left + radius;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const ellipsoidCornersIJK = [
|
|
68
|
+
<Types.Point3>transformWorldToIndex(segmentationImageData, topLeftWorld),
|
|
69
|
+
<Types.Point3>(
|
|
70
|
+
transformWorldToIndex(segmentationImageData, bottomRightWorld)
|
|
71
|
+
),
|
|
72
|
+
];
|
|
73
|
+
|
|
74
|
+
segmentationVoxelManager.boundsIJK = getBoundingBoxAroundShape(
|
|
75
|
+
ellipsoidCornersIJK,
|
|
76
|
+
segmentationVoxelManager.dimensions
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
imageVoxelManager.isInObject = createEllipseInPoint({
|
|
80
|
+
topLeftWorld,
|
|
81
|
+
bottomRightWorld,
|
|
82
|
+
center,
|
|
83
|
+
});
|
|
84
|
+
},
|
|
85
|
+
} as Composition;
|
|
86
|
+
|
|
87
|
+
const SPHERE_STRATEGY = new BrushStrategy(
|
|
88
|
+
'Sphere',
|
|
89
|
+
compositions.regionFill,
|
|
90
|
+
compositions.setValue,
|
|
91
|
+
sphereComposition,
|
|
92
|
+
compositions.determineSegmentIndex,
|
|
93
|
+
compositions.preview
|
|
94
|
+
);
|
|
92
95
|
|
|
93
96
|
/**
|
|
94
97
|
* Fill inside a sphere with the given segment index in the given operation data. The
|
|
@@ -96,12 +99,15 @@ function fillSphere(
|
|
|
96
99
|
* @param enabledElement - The element that is enabled and selected.
|
|
97
100
|
* @param operationData - OperationData
|
|
98
101
|
*/
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
102
|
+
const fillInsideSphere = SPHERE_STRATEGY.strategyFunction;
|
|
103
|
+
|
|
104
|
+
const SPHERE_THRESHOLD_STRATEGY = new BrushStrategy(
|
|
105
|
+
'SphereThreshold',
|
|
106
|
+
...SPHERE_STRATEGY.compositions,
|
|
107
|
+
compositions.dynamicThreshold,
|
|
108
|
+
compositions.threshold,
|
|
109
|
+
compositions.islandRemoval
|
|
110
|
+
);
|
|
105
111
|
|
|
106
112
|
/**
|
|
107
113
|
* Fill inside the circular region segment inside the segmentation defined by the operationData.
|
|
@@ -109,28 +115,8 @@ export function fillInsideSphere(
|
|
|
109
115
|
* @param enabledElement - The element for which the segment is being filled.
|
|
110
116
|
* @param operationData - EraseOperationData
|
|
111
117
|
*/
|
|
112
|
-
export function thresholdInsideSphere(
|
|
113
|
-
enabledElement: Types.IEnabledElement,
|
|
114
|
-
operationData: OperationData
|
|
115
|
-
): void {
|
|
116
|
-
if (isVolumeSegmentation(operationData)) {
|
|
117
|
-
const { referencedVolumeId, volumeId } = operationData;
|
|
118
|
-
|
|
119
|
-
const imageVolume = cache.getVolume(referencedVolumeId);
|
|
120
|
-
const segmentation = cache.getVolume(volumeId);
|
|
121
|
-
|
|
122
|
-
if (
|
|
123
|
-
!csUtils.isEqual(segmentation.dimensions, imageVolume.dimensions) ||
|
|
124
|
-
!csUtils.isEqual(segmentation.direction, imageVolume.direction)
|
|
125
|
-
) {
|
|
126
|
-
throw new Error(
|
|
127
|
-
'Only source data the same dimensions/size/orientation as the segmentation currently supported.'
|
|
128
|
-
);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
118
|
|
|
132
|
-
|
|
133
|
-
}
|
|
119
|
+
const thresholdInsideSphere = SPHERE_THRESHOLD_STRATEGY.strategyFunction;
|
|
134
120
|
|
|
135
121
|
/**
|
|
136
122
|
* Fill outside a sphere with the given segment index in the given operation data. The
|
|
@@ -138,9 +124,8 @@ export function thresholdInsideSphere(
|
|
|
138
124
|
* @param enabledElement - The element that is enabled and selected.
|
|
139
125
|
* @param operationData - OperationData
|
|
140
126
|
*/
|
|
141
|
-
export function fillOutsideSphere(
|
|
142
|
-
|
|
143
|
-
operationData: OperationData
|
|
144
|
-
): void {
|
|
145
|
-
fillSphere(enabledElement, operationData, false);
|
|
127
|
+
export function fillOutsideSphere(): void {
|
|
128
|
+
throw new Error('fill outside sphere not implemented');
|
|
146
129
|
}
|
|
130
|
+
|
|
131
|
+
export { fillInsideSphere, thresholdInsideSphere, SPHERE_STRATEGY };
|