@cornerstonejs/tools 0.56.1 → 0.56.3
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/tools/CrosshairsTool.d.ts +1 -0
- package/dist/cjs/tools/CrosshairsTool.js +4 -1
- package/dist/cjs/tools/CrosshairsTool.js.map +1 -1
- package/dist/esm/tools/CrosshairsTool.d.ts +1 -0
- package/dist/esm/tools/CrosshairsTool.js +4 -1
- package/dist/esm/tools/CrosshairsTool.js.map +1 -1
- package/dist/umd/index.js +1 -1
- package/dist/umd/index.js.map +1 -1
- package/package.json +5 -4
- package/src/constants/COLOR_LUT.ts +262 -0
- package/src/constants/index.ts +3 -0
- package/src/cursors/ImageMouseCursor.ts +39 -0
- package/src/cursors/MouseCursor.ts +114 -0
- package/src/cursors/SVGCursorDescriptor.ts +462 -0
- package/src/cursors/SVGMouseCursor.ts +145 -0
- package/src/cursors/elementCursor.ts +69 -0
- package/src/cursors/index.ts +24 -0
- package/src/cursors/setCursorForElement.ts +33 -0
- package/src/drawingSvg/_getHash.ts +9 -0
- package/src/drawingSvg/_setAttributesIfNecessary.ts +13 -0
- package/src/drawingSvg/_setNewAttributesIfValid.ts +10 -0
- package/src/drawingSvg/clearByToolType.ts +26 -0
- package/src/drawingSvg/draw.ts +16 -0
- package/src/drawingSvg/drawArrow.ts +82 -0
- package/src/drawingSvg/drawCircle.ts +62 -0
- package/src/drawingSvg/drawEllipse.ts +71 -0
- package/src/drawingSvg/drawHandles.ts +87 -0
- package/src/drawingSvg/drawLine.ts +70 -0
- package/src/drawingSvg/drawLink.ts +76 -0
- package/src/drawingSvg/drawLinkedTextBox.ts +64 -0
- package/src/drawingSvg/drawPolyline.ts +80 -0
- package/src/drawingSvg/drawRect.ts +70 -0
- package/src/drawingSvg/drawTextBox.ts +213 -0
- package/src/drawingSvg/getSvgDrawingHelper.ts +98 -0
- package/src/drawingSvg/index.ts +23 -0
- package/src/enums/AnnotationStyleStates.ts +22 -0
- package/src/enums/Events.ts +242 -0
- package/src/enums/SegmentationRepresentations.ts +12 -0
- package/src/enums/ToolBindings.ts +37 -0
- package/src/enums/ToolModes.ts +31 -0
- package/src/enums/Touch.ts +8 -0
- package/src/enums/index.js +16 -0
- package/src/eventDispatchers/annotationModifiedEventDispatcher.ts +41 -0
- package/src/eventDispatchers/cameraModifiedEventDispatcher.ts +41 -0
- package/src/eventDispatchers/imageRenderedEventDispatcher.ts +37 -0
- package/src/eventDispatchers/imageSpacingCalibratedEventDispatcher.ts +50 -0
- package/src/eventDispatchers/index.js +15 -0
- package/src/eventDispatchers/keyboardEventHandlers/index.js +4 -0
- package/src/eventDispatchers/keyboardEventHandlers/keyDown.ts +29 -0
- package/src/eventDispatchers/keyboardEventHandlers/keyUp.ts +33 -0
- package/src/eventDispatchers/keyboardToolEventDispatcher.ts +28 -0
- package/src/eventDispatchers/mouseEventHandlers/index.js +19 -0
- package/src/eventDispatchers/mouseEventHandlers/mouseClick.ts +13 -0
- package/src/eventDispatchers/mouseEventHandlers/mouseDoubleClick.ts +13 -0
- package/src/eventDispatchers/mouseEventHandlers/mouseDown.ts +196 -0
- package/src/eventDispatchers/mouseEventHandlers/mouseDownActivate.ts +35 -0
- package/src/eventDispatchers/mouseEventHandlers/mouseDrag.ts +25 -0
- package/src/eventDispatchers/mouseEventHandlers/mouseMove.ts +70 -0
- package/src/eventDispatchers/mouseEventHandlers/mouseUp.ts +9 -0
- package/src/eventDispatchers/mouseEventHandlers/mouseWheel.ts +13 -0
- package/src/eventDispatchers/mouseToolEventDispatcher.ts +64 -0
- package/src/eventDispatchers/shared/customCallbackHandler.ts +73 -0
- package/src/eventDispatchers/shared/getActiveToolForKeyboardEvent.ts +58 -0
- package/src/eventDispatchers/shared/getActiveToolForMouseEvent.ts +61 -0
- package/src/eventDispatchers/shared/getActiveToolForTouchEvent.ts +64 -0
- package/src/eventDispatchers/shared/getMouseModifier.ts +30 -0
- package/src/eventDispatchers/shared/getToolsWithModesForMouseEvent.ts +56 -0
- package/src/eventDispatchers/shared/getToolsWithModesForTouchEvent.ts +54 -0
- package/src/eventDispatchers/touchEventHandlers/index.js +15 -0
- package/src/eventDispatchers/touchEventHandlers/touchDrag.ts +23 -0
- package/src/eventDispatchers/touchEventHandlers/touchEnd.ts +9 -0
- package/src/eventDispatchers/touchEventHandlers/touchPress.ts +13 -0
- package/src/eventDispatchers/touchEventHandlers/touchStart.ts +174 -0
- package/src/eventDispatchers/touchEventHandlers/touchStartActivate.ts +36 -0
- package/src/eventDispatchers/touchEventHandlers/touchTap.ts +9 -0
- package/src/eventDispatchers/touchToolEventDispatcher.ts +51 -0
- package/src/eventListeners/annotations/annotationModifiedListener.ts +22 -0
- package/src/eventListeners/annotations/annotationSelectionListener.ts +29 -0
- package/src/eventListeners/annotations/index.ts +4 -0
- package/src/eventListeners/index.ts +28 -0
- package/src/eventListeners/keyboard/index.ts +16 -0
- package/src/eventListeners/keyboard/keyDownListener.ts +99 -0
- package/src/eventListeners/mouse/getMouseEventPoints.ts +66 -0
- package/src/eventListeners/mouse/index.ts +55 -0
- package/src/eventListeners/mouse/mouseDoubleClickListener.ts +55 -0
- package/src/eventListeners/mouse/mouseDownListener.ts +519 -0
- package/src/eventListeners/mouse/mouseMoveListener.ts +33 -0
- package/src/eventListeners/segmentation/index.ts +11 -0
- package/src/eventListeners/segmentation/segmentationDataModifiedEventListener.ts +61 -0
- package/src/eventListeners/segmentation/segmentationModifiedEventListener.ts +32 -0
- package/src/eventListeners/segmentation/segmentationRepresentationModifiedEventListener.ts +15 -0
- package/src/eventListeners/segmentation/segmentationRepresentationRemovedEventListener.ts +16 -0
- package/src/eventListeners/touch/getTouchEventPoints.ts +75 -0
- package/src/eventListeners/touch/index.ts +37 -0
- package/src/eventListeners/touch/preventGhostClick.js +72 -0
- package/src/eventListeners/touch/touchStartListener.ts +499 -0
- package/src/eventListeners/wheel/index.ts +27 -0
- package/src/eventListeners/wheel/normalizeWheel.ts +69 -0
- package/src/eventListeners/wheel/wheelListener.ts +51 -0
- package/src/index.ts +133 -0
- package/src/init.ts +187 -0
- package/src/stateManagement/annotation/FrameOfReferenceSpecificAnnotationManager.ts +399 -0
- package/src/stateManagement/annotation/annotationLocking.ts +178 -0
- package/src/stateManagement/annotation/annotationSelection.ts +163 -0
- package/src/stateManagement/annotation/annotationState.ts +180 -0
- package/src/stateManagement/annotation/annotationVisibility.ts +156 -0
- package/src/stateManagement/annotation/config/ToolStyle.ts +265 -0
- package/src/stateManagement/annotation/config/getFont.ts +36 -0
- package/src/stateManagement/annotation/config/getState.ts +26 -0
- package/src/stateManagement/annotation/config/helpers.ts +55 -0
- package/src/stateManagement/annotation/config/index.ts +5 -0
- package/src/stateManagement/annotation/helpers/state.ts +83 -0
- package/src/stateManagement/annotation/index.ts +15 -0
- package/src/stateManagement/index.js +40 -0
- package/src/stateManagement/segmentation/SegmentationStateManager.ts +491 -0
- package/src/stateManagement/segmentation/activeSegmentation.ts +60 -0
- package/src/stateManagement/segmentation/addSegmentationRepresentations.ts +77 -0
- package/src/stateManagement/segmentation/addSegmentations.ts +27 -0
- package/src/stateManagement/segmentation/config/index.ts +29 -0
- package/src/stateManagement/segmentation/config/segmentationColor.ts +132 -0
- package/src/stateManagement/segmentation/config/segmentationConfig.ts +195 -0
- package/src/stateManagement/segmentation/config/segmentationVisibility.ts +171 -0
- package/src/stateManagement/segmentation/helpers/index.ts +3 -0
- package/src/stateManagement/segmentation/helpers/normalizeSegmentationInput.ts +35 -0
- package/src/stateManagement/segmentation/helpers/validateSegmentationInput.ts +41 -0
- package/src/stateManagement/segmentation/index.ts +22 -0
- package/src/stateManagement/segmentation/removeSegmentationsFromToolGroup.ts +85 -0
- package/src/stateManagement/segmentation/segmentIndex.ts +38 -0
- package/src/stateManagement/segmentation/segmentLocking.ts +72 -0
- package/src/stateManagement/segmentation/segmentationState.ts +429 -0
- package/src/stateManagement/segmentation/triggerSegmentationEvents.ts +157 -0
- package/src/store/SynchronizerManager/Synchronizer.ts +344 -0
- package/src/store/SynchronizerManager/createSynchronizer.ts +41 -0
- package/src/store/SynchronizerManager/destroy.ts +14 -0
- package/src/store/SynchronizerManager/destroySynchronizer.ts +25 -0
- package/src/store/SynchronizerManager/getAllSynchronizers.ts +12 -0
- package/src/store/SynchronizerManager/getSynchronizer.ts +13 -0
- package/src/store/SynchronizerManager/getSynchronizersForViewport.ts +44 -0
- package/src/store/SynchronizerManager/index.js +15 -0
- package/src/store/ToolGroupManager/ToolGroup.ts +679 -0
- package/src/store/ToolGroupManager/createToolGroup.ts +33 -0
- package/src/store/ToolGroupManager/destroy.ts +24 -0
- package/src/store/ToolGroupManager/destroyToolGroup.ts +26 -0
- package/src/store/ToolGroupManager/getAllToolGroups.ts +12 -0
- package/src/store/ToolGroupManager/getToolGroup.ts +14 -0
- package/src/store/ToolGroupManager/getToolGroupForViewport.ts +44 -0
- package/src/store/ToolGroupManager/getToolGroupsWithToolName.ts +33 -0
- package/src/store/ToolGroupManager/index.ts +17 -0
- package/src/store/addEnabledElement.ts +137 -0
- package/src/store/addTool.ts +56 -0
- package/src/store/cancelActiveManipulations.ts +30 -0
- package/src/store/filterMoveableAnnotationTools.ts +61 -0
- package/src/store/filterToolsWithAnnotationsForElement.ts +51 -0
- package/src/store/filterToolsWithMoveableHandles.ts +51 -0
- package/src/store/index.ts +29 -0
- package/src/store/removeEnabledElement.ts +132 -0
- package/src/store/state.ts +57 -0
- package/src/store/svgNodeCache.ts +7 -0
- package/src/synchronizers/callbacks/areViewportsCoplanar .ts +12 -0
- package/src/synchronizers/callbacks/cameraSyncCallback.ts +33 -0
- package/src/synchronizers/callbacks/stackImageSyncCallback.ts +157 -0
- package/src/synchronizers/callbacks/voiSyncCallback.ts +51 -0
- package/src/synchronizers/callbacks/zoomPanSyncCallback.ts +43 -0
- package/src/synchronizers/index.ts +11 -0
- package/src/synchronizers/synchronizers/createCameraPositionSynchronizer.ts +25 -0
- package/src/synchronizers/synchronizers/createStackImageSynchronizer.ts +25 -0
- package/src/synchronizers/synchronizers/createVOISynchronizer.ts +24 -0
- package/src/synchronizers/synchronizers/createZoomPanSynchronizer.ts +25 -0
- package/src/synchronizers/synchronizers/index.ts +11 -0
- package/src/tools/CrosshairsTool.ts +2693 -0
- package/src/tools/MIPJumpToClickTool.ts +99 -0
- package/src/tools/MagnifyTool.ts +319 -0
- package/src/tools/PanTool.ts +58 -0
- package/src/tools/PlanarRotateTool.ts +77 -0
- package/src/tools/ReferenceCursors.ts +466 -0
- package/src/tools/ReferenceLinesTool.ts +279 -0
- package/src/tools/ScaleOverlayTool.ts +685 -0
- package/src/tools/StackScrollTool.ts +97 -0
- package/src/tools/StackScrollToolMouseWheelTool.ts +58 -0
- package/src/tools/TrackballRotateTool.ts +141 -0
- package/src/tools/VolumeRotateMouseWheelTool.ts +86 -0
- package/src/tools/WindowLevelTool.ts +260 -0
- package/src/tools/ZoomTool.ts +293 -0
- package/src/tools/annotation/AngleTool.ts +835 -0
- package/src/tools/annotation/ArrowAnnotateTool.ts +820 -0
- package/src/tools/annotation/BidirectionalTool.ts +1350 -0
- package/src/tools/annotation/CircleROITool.ts +1070 -0
- package/src/tools/annotation/CobbAngleTool.ts +815 -0
- package/src/tools/annotation/DragProbeTool.ts +213 -0
- package/src/tools/annotation/EllipticalROITool.ts +1223 -0
- package/src/tools/annotation/LengthTool.ts +861 -0
- package/src/tools/annotation/PlanarFreehandROITool.ts +636 -0
- package/src/tools/annotation/ProbeTool.ts +681 -0
- package/src/tools/annotation/RectangleROITool.ts +1028 -0
- package/src/tools/annotation/planarFreehandROITool/closedContourEditLoop.ts +488 -0
- package/src/tools/annotation/planarFreehandROITool/drawLoop.ts +462 -0
- package/src/tools/annotation/planarFreehandROITool/editLoopCommon.ts +331 -0
- package/src/tools/annotation/planarFreehandROITool/findOpenUShapedContourVectorToPeak.ts +74 -0
- package/src/tools/annotation/planarFreehandROITool/openContourEditLoop.ts +612 -0
- package/src/tools/annotation/planarFreehandROITool/openContourEndEditLoop.ts +74 -0
- package/src/tools/annotation/planarFreehandROITool/renderMethods.ts +407 -0
- package/src/tools/base/AnnotationDisplayTool.ts +228 -0
- package/src/tools/base/AnnotationTool.ts +307 -0
- package/src/tools/base/BaseTool.ts +215 -0
- package/src/tools/base/index.ts +4 -0
- package/src/tools/displayTools/Contour/addContourToElement.ts +135 -0
- package/src/tools/displayTools/Contour/contourDisplay.ts +252 -0
- package/src/tools/displayTools/Contour/index.ts +3 -0
- package/src/tools/displayTools/Contour/removeContourFromElement.ts +35 -0
- package/src/tools/displayTools/Labelmap/addLabelmapToElement.ts +57 -0
- package/src/tools/displayTools/Labelmap/index.ts +4 -0
- package/src/tools/displayTools/Labelmap/labelmapConfig.ts +37 -0
- package/src/tools/displayTools/Labelmap/labelmapDisplay.ts +461 -0
- package/src/tools/displayTools/Labelmap/removeLabelmapFromElement.ts +27 -0
- package/src/tools/displayTools/Labelmap/validateRepresentationData.ts +30 -0
- package/src/tools/displayTools/SegmentationDisplayTool.ts +198 -0
- package/src/tools/index.ts +84 -0
- package/src/tools/segmentation/BrushTool.ts +474 -0
- package/src/tools/segmentation/CircleScissorsTool.ts +365 -0
- package/src/tools/segmentation/PaintFillTool.ts +370 -0
- package/src/tools/segmentation/RectangleROIStartEndThresholdTool.ts +471 -0
- package/src/tools/segmentation/RectangleROIThresholdTool.ts +281 -0
- package/src/tools/segmentation/RectangleScissorsTool.ts +382 -0
- package/src/tools/segmentation/SphereScissorsTool.ts +368 -0
- package/src/tools/segmentation/strategies/eraseCircle.ts +30 -0
- package/src/tools/segmentation/strategies/eraseRectangle.ts +81 -0
- package/src/tools/segmentation/strategies/eraseSphere.ts +27 -0
- package/src/tools/segmentation/strategies/fillCircle.ts +185 -0
- package/src/tools/segmentation/strategies/fillRectangle.ts +110 -0
- package/src/tools/segmentation/strategies/fillSphere.ts +88 -0
- package/src/tools/segmentation/strategies/index.ts +9 -0
- package/src/types/AnnotationGroupSelector.ts +7 -0
- package/src/types/AnnotationStyle.ts +42 -0
- package/src/types/AnnotationTypes.ts +109 -0
- package/src/types/BoundsIJK.ts +5 -0
- package/src/types/CINETypes.ts +32 -0
- package/src/types/ContourTypes.ts +26 -0
- package/src/types/CursorTypes.ts +12 -0
- package/src/types/EventTypes.ts +657 -0
- package/src/types/FloodFillTypes.ts +19 -0
- package/src/types/IAnnotationManager.ts +89 -0
- package/src/types/IDistance.ts +16 -0
- package/src/types/IPoints.ts +18 -0
- package/src/types/ISetToolModeOptions.ts +29 -0
- package/src/types/ISynchronizerEventHandler.ts +11 -0
- package/src/types/IToolClassReference.ts +5 -0
- package/src/types/IToolGroup.ts +72 -0
- package/src/types/ITouchPoints.ts +14 -0
- package/src/types/InteractionTypes.ts +6 -0
- package/src/types/InternalToolTypes.ts +19 -0
- package/src/types/JumpToSliceOptions.ts +7 -0
- package/src/types/LabelmapTypes.ts +41 -0
- package/src/types/PlanarBoundingBox.ts +8 -0
- package/src/types/SVGDrawingHelper.ts +10 -0
- package/src/types/ScrollOptions.ts +9 -0
- package/src/types/SegmentationStateTypes.ts +248 -0
- package/src/types/ToolHandle.ts +26 -0
- package/src/types/ToolProps.ts +16 -0
- package/src/types/ToolSpecificAnnotationTypes.ts +311 -0
- package/src/types/index.ts +115 -0
- package/src/utilities/boundingBox/extend2DBoundingBoxInViewAxis.ts +29 -0
- package/src/utilities/boundingBox/getBoundingBoxAroundShape.ts +57 -0
- package/src/utilities/boundingBox/index.ts +4 -0
- package/src/utilities/calibrateImageSpacing.ts +46 -0
- package/src/utilities/cine/events.ts +9 -0
- package/src/utilities/cine/index.ts +5 -0
- package/src/utilities/cine/playClip.ts +435 -0
- package/src/utilities/cine/state.ts +18 -0
- package/src/utilities/clip.js +30 -0
- package/src/utilities/debounce.js +217 -0
- package/src/utilities/drawing/getTextBoxCoordsCanvas.ts +45 -0
- package/src/utilities/drawing/index.ts +3 -0
- package/src/utilities/dynamicVolume/getDataInTime.ts +110 -0
- package/src/utilities/dynamicVolume/index.ts +2 -0
- package/src/utilities/getAnnotationNearPoint.ts +130 -0
- package/src/utilities/getModalityUnit.ts +11 -0
- package/src/utilities/getToolsWithModesForElement.ts +52 -0
- package/src/utilities/index.ts +68 -0
- package/src/utilities/isObject.js +29 -0
- package/src/utilities/math/angle/angleBetweenLines.ts +29 -0
- package/src/utilities/math/circle/_types.ts +6 -0
- package/src/utilities/math/circle/getCanvasCircleCorners.ts +23 -0
- package/src/utilities/math/circle/getCanvasCircleRadius.ts +16 -0
- package/src/utilities/math/circle/index.ts +4 -0
- package/src/utilities/math/ellipse/getCanvasEllipseCorners.ts +26 -0
- package/src/utilities/math/ellipse/index.ts +4 -0
- package/src/utilities/math/ellipse/pointInEllipse.ts +38 -0
- package/src/utilities/math/ellipse/pointInEllipsoidWithConstraint.ts +35 -0
- package/src/utilities/math/index.ts +8 -0
- package/src/utilities/math/line/distanceToPoint.ts +24 -0
- package/src/utilities/math/line/distanceToPointSquared.ts +44 -0
- package/src/utilities/math/line/index.ts +5 -0
- package/src/utilities/math/line/intersectLine.ts +92 -0
- package/src/utilities/math/midPoint.ts +24 -0
- package/src/utilities/math/point/distanceToPoint.ts +22 -0
- package/src/utilities/math/point/index.ts +3 -0
- package/src/utilities/math/polyline/addCanvasPointsToArray.ts +62 -0
- package/src/utilities/math/polyline/calculateAreaOfPoints.ts +23 -0
- package/src/utilities/math/polyline/getIntersectionWithPolyline.ts +182 -0
- package/src/utilities/math/polyline/getSubPixelSpacingAndXYDirections.ts +99 -0
- package/src/utilities/math/polyline/index.ts +19 -0
- package/src/utilities/math/polyline/planarFreehandROIInternalTypes.ts +36 -0
- package/src/utilities/math/polyline/pointCanProjectOnLine.ts +57 -0
- package/src/utilities/math/polyline/pointsAreWithinCloseContourProximity.ts +15 -0
- package/src/utilities/math/rectangle/distanceToPoint.ts +82 -0
- package/src/utilities/math/rectangle/index.ts +3 -0
- package/src/utilities/math/sphere/index.ts +3 -0
- package/src/utilities/math/sphere/pointInSphere.ts +31 -0
- package/src/utilities/math/vec2/findClosestPoint.ts +40 -0
- package/src/utilities/math/vec2/index.ts +4 -0
- package/src/utilities/math/vec2/liangBarksyClip.ts +84 -0
- package/src/utilities/orientation/getOrientationStringLPS.ts +52 -0
- package/src/utilities/orientation/index.ts +4 -0
- package/src/utilities/orientation/invertOrientationStringLPS.ts +21 -0
- package/src/utilities/planar/filterAnnotationsForDisplay.ts +68 -0
- package/src/utilities/planar/filterAnnotationsWithinSlice.ts +85 -0
- package/src/utilities/planar/getPointInLineOfSightWithCriteria.ts +104 -0
- package/src/utilities/planar/getWorldWidthAndHeightFromCorners.ts +51 -0
- package/src/utilities/planar/getWorldWidthAndHeightFromTwoPoints.ts +51 -0
- package/src/utilities/planar/index.ts +18 -0
- package/src/utilities/planarFreehandROITool/index.ts +7 -0
- package/src/utilities/planarFreehandROITool/interpolateAnnotation.ts +87 -0
- package/src/utilities/planarFreehandROITool/interpolatePoints.ts +214 -0
- package/src/utilities/planarFreehandROITool/interpolation/algorithms/bspline.ts +55 -0
- package/src/utilities/planarFreehandROITool/interpolation/interpolateSegmentPoints.ts +90 -0
- package/src/utilities/pointInShapeCallback.ts +138 -0
- package/src/utilities/pointInSurroundingSphereCallback.ts +188 -0
- package/src/utilities/rectangleROITool/getBoundsIJKFromRectangleAnnotations.ts +76 -0
- package/src/utilities/rectangleROITool/index.ts +3 -0
- package/src/utilities/scroll.ts +62 -0
- package/src/utilities/segmentation/brushSizeForToolGroup.ts +72 -0
- package/src/utilities/segmentation/brushThresholdForToolGroup.ts +65 -0
- package/src/utilities/segmentation/createLabelmapVolumeForViewport.ts +74 -0
- package/src/utilities/segmentation/createMergedLabelmapForIndex.ts +65 -0
- package/src/utilities/segmentation/floodFill.ts +194 -0
- package/src/utilities/segmentation/getDefaultRepresentationConfig.ts +20 -0
- package/src/utilities/segmentation/index.ts +33 -0
- package/src/utilities/segmentation/isValidRepresentationConfig.ts +22 -0
- package/src/utilities/segmentation/rectangleROIThresholdVolumeByRange.ts +91 -0
- package/src/utilities/segmentation/thresholdSegmentationByRange.ts +129 -0
- package/src/utilities/segmentation/thresholdVolumeByRange.ts +150 -0
- package/src/utilities/segmentation/triggerSegmentationRender.ts +206 -0
- package/src/utilities/segmentation/utilities.ts +116 -0
- package/src/utilities/stackPrefetch/index.ts +8 -0
- package/src/utilities/stackPrefetch/stackPrefetch.ts +405 -0
- package/src/utilities/stackPrefetch/state.ts +17 -0
- package/src/utilities/throttle.js +69 -0
- package/src/utilities/touch/index.ts +246 -0
- package/src/utilities/triggerAnnotationRender.ts +237 -0
- package/src/utilities/triggerAnnotationRenderForViewportIds.ts +18 -0
- package/src/utilities/viewport/index.ts +5 -0
- package/src/utilities/viewport/isViewportPreScaled.ts +24 -0
- package/src/utilities/viewport/jumpToSlice.ts +73 -0
- package/src/utilities/viewport/jumpToWorld.ts +58 -0
- package/src/utilities/viewportFilters/filterViewportsWithFrameOfReferenceUID.ts +28 -0
- package/src/utilities/viewportFilters/filterViewportsWithParallelNormals.ts +26 -0
- package/src/utilities/viewportFilters/filterViewportsWithSameOrientation.ts +15 -0
- package/src/utilities/viewportFilters/filterViewportsWithToolEnabled.ts +72 -0
- package/src/utilities/viewportFilters/getViewportIdsWithToolToRender.ts +45 -0
- package/src/utilities/viewportFilters/index.ts +11 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { vec3 } from 'gl-matrix';
|
|
2
|
+
import type { Types } from '@cornerstonejs/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Given two world positions and an orthogonal view to an `imageVolume` defined by
|
|
6
|
+
* a `viewPlaneNormal` and a `viewUp`, get the width and height in world coordinates of the rectangle
|
|
7
|
+
* defined by the two points. The implementation works both with orthogonal
|
|
8
|
+
* non-orthogonal rectangles.
|
|
9
|
+
*
|
|
10
|
+
* @param viewPlaneNormal - The normal of the view.
|
|
11
|
+
* @param viewUp - The up direction of the view.
|
|
12
|
+
* @param imageVolume - The imageVolume to use to measure.
|
|
13
|
+
* @param worldPos1 - The first world position.
|
|
14
|
+
* @param worldPos2 - The second world position.
|
|
15
|
+
*
|
|
16
|
+
* @returns The `worldWidth` and `worldHeight`.
|
|
17
|
+
*/
|
|
18
|
+
export default function getWorldWidthAndHeightFromTwoPoints(
|
|
19
|
+
viewPlaneNormal: Types.Point3,
|
|
20
|
+
viewUp: Types.Point3,
|
|
21
|
+
worldPos1: Types.Point3,
|
|
22
|
+
worldPos2: Types.Point3
|
|
23
|
+
): { worldWidth: number; worldHeight: number } {
|
|
24
|
+
const viewRight = vec3.create();
|
|
25
|
+
|
|
26
|
+
vec3.cross(viewRight, <vec3>viewUp, <vec3>viewPlaneNormal);
|
|
27
|
+
|
|
28
|
+
const pos1 = vec3.fromValues(...worldPos1);
|
|
29
|
+
const pos2 = vec3.fromValues(...worldPos2);
|
|
30
|
+
|
|
31
|
+
const diagonal = vec3.create();
|
|
32
|
+
vec3.subtract(diagonal, pos1, pos2);
|
|
33
|
+
|
|
34
|
+
const diagonalLength = vec3.length(diagonal);
|
|
35
|
+
|
|
36
|
+
// When the two points are very close to each other return width as 0
|
|
37
|
+
// to avoid NaN the cosTheta formula calculation
|
|
38
|
+
if (diagonalLength < 0.0001) {
|
|
39
|
+
return { worldWidth: 0, worldHeight: 0 };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const cosTheta =
|
|
43
|
+
vec3.dot(diagonal, viewRight) / (diagonalLength * vec3.length(viewRight));
|
|
44
|
+
|
|
45
|
+
const sinTheta = Math.sqrt(1 - cosTheta * cosTheta);
|
|
46
|
+
|
|
47
|
+
const worldWidth = sinTheta * diagonalLength;
|
|
48
|
+
const worldHeight = cosTheta * diagonalLength;
|
|
49
|
+
|
|
50
|
+
return { worldWidth, worldHeight };
|
|
51
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import filterAnnotationsWithinSlice from './filterAnnotationsWithinSlice';
|
|
2
|
+
import getWorldWidthAndHeightFromCorners from './getWorldWidthAndHeightFromCorners';
|
|
3
|
+
import filterAnnotationsForDisplay from './filterAnnotationsForDisplay';
|
|
4
|
+
import getPointInLineOfSightWithCriteria from './getPointInLineOfSightWithCriteria';
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
filterAnnotationsWithinSlice,
|
|
8
|
+
getWorldWidthAndHeightFromCorners,
|
|
9
|
+
filterAnnotationsForDisplay,
|
|
10
|
+
getPointInLineOfSightWithCriteria,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export {
|
|
14
|
+
filterAnnotationsWithinSlice,
|
|
15
|
+
getWorldWidthAndHeightFromCorners,
|
|
16
|
+
filterAnnotationsForDisplay,
|
|
17
|
+
getPointInLineOfSightWithCriteria,
|
|
18
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { Types } from '@cornerstonejs/core';
|
|
2
|
+
import { PlanarFreehandROITool } from '../../tools';
|
|
3
|
+
import { ToolGroupManager } from '../../store';
|
|
4
|
+
import { PlanarFreehandROIAnnotation } from '../../types/ToolSpecificAnnotationTypes';
|
|
5
|
+
import interpolateSegmentPoints from './interpolation/interpolateSegmentPoints';
|
|
6
|
+
|
|
7
|
+
function shouldPreventInterpolation(
|
|
8
|
+
enabledElement: Types.IEnabledElement,
|
|
9
|
+
annotation: PlanarFreehandROIAnnotation,
|
|
10
|
+
knotsRatioPercentage: number
|
|
11
|
+
): boolean {
|
|
12
|
+
if (!annotation?.data?.polyline || knotsRatioPercentage <= 0) {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (!enabledElement.viewport) {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const { renderingEngineId, viewportId, FrameOfReferenceUID } = enabledElement;
|
|
21
|
+
const toolGroup = ToolGroupManager.getToolGroupForViewport(
|
|
22
|
+
viewportId,
|
|
23
|
+
renderingEngineId
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
if (annotation.metadata.FrameOfReferenceUID !== FrameOfReferenceUID) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (!toolGroup) {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const toolInstance = toolGroup.getToolInstance(annotation.metadata.toolName);
|
|
35
|
+
|
|
36
|
+
// strategy to prevent non PlanarFreehandTool
|
|
37
|
+
if (!(toolInstance instanceof PlanarFreehandROITool)) {
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
toolInstance.isDrawing ||
|
|
43
|
+
toolInstance.isEditingOpen ||
|
|
44
|
+
toolInstance.isEditingClosed
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Interpolates a given annotation from a given enabledElement.
|
|
49
|
+
* It mutates annotation param.
|
|
50
|
+
* The param knotsRatioPercentage defines the percentage of points to be considered as knots on the interpolation process.
|
|
51
|
+
* Interpolation will be skipped in case: annotation is not present in enabledElement (or there is no toolGroup associated with it), related tool is being modified.
|
|
52
|
+
*/
|
|
53
|
+
export default function interpolateAnnotation(
|
|
54
|
+
enabledElement: Types.IEnabledElement,
|
|
55
|
+
annotation: PlanarFreehandROIAnnotation,
|
|
56
|
+
knotsRatioPercentage: number
|
|
57
|
+
): boolean {
|
|
58
|
+
// prevent running while there is any tool annotation being modified
|
|
59
|
+
if (
|
|
60
|
+
shouldPreventInterpolation(enabledElement, annotation, knotsRatioPercentage)
|
|
61
|
+
) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const { viewport } = enabledElement;
|
|
66
|
+
// use only 2 dimensions on interpolation (what visually matters),
|
|
67
|
+
// otherwise a 3d interpolation might have a totally different output as it consider one more dimension.
|
|
68
|
+
const canvasPoints = annotation.data.polyline.map(viewport.worldToCanvas);
|
|
69
|
+
const interpolatedCanvasPoints = <Types.Point2[]>(
|
|
70
|
+
interpolateSegmentPoints(
|
|
71
|
+
canvasPoints,
|
|
72
|
+
0,
|
|
73
|
+
canvasPoints.length,
|
|
74
|
+
knotsRatioPercentage
|
|
75
|
+
)
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
if (interpolatedCanvasPoints === canvasPoints) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
annotation.data.polyline = interpolatedCanvasPoints.map(
|
|
83
|
+
viewport.canvasToWorld
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { Types } from '@cornerstonejs/core';
|
|
2
|
+
import { point } from '../math';
|
|
3
|
+
import interpolateSegmentPoints from './interpolation/interpolateSegmentPoints';
|
|
4
|
+
|
|
5
|
+
export function shouldInterpolate(configuration: Record<any, any>): boolean {
|
|
6
|
+
return (
|
|
7
|
+
configuration?.interpolation?.interpolateOnAdd === true ||
|
|
8
|
+
configuration?.interpolation?.interpolateOnEdit === true
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Tells whether two points are equal by proximity or not as far as interpolation goes.
|
|
14
|
+
*/
|
|
15
|
+
function isEqualByProximity(pointA, pointB) {
|
|
16
|
+
return point.distanceToPoint(pointA, pointB) < 0.001;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Tells whether two points are strictly equal or not as far as interpolation goes.
|
|
21
|
+
*/
|
|
22
|
+
function isEqual(pointA, pointB) {
|
|
23
|
+
return point.distanceToPoint(pointA, pointB) === 0;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Finds the indexes of points list and otherPoints list that points are identical.
|
|
28
|
+
*/
|
|
29
|
+
function findMatchIndexes(
|
|
30
|
+
points: Types.Point2[],
|
|
31
|
+
otherPoints: Types.Point2[]
|
|
32
|
+
): [number, number] | undefined {
|
|
33
|
+
for (let i = 0; i < points.length; i++) {
|
|
34
|
+
for (let j = 0; j < otherPoints.length; j++) {
|
|
35
|
+
if (isEqual(points[i], otherPoints[j])) {
|
|
36
|
+
return [i, j];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Returns the following index value (on circular basis) of index param on the given direction.
|
|
43
|
+
*/
|
|
44
|
+
function followingIndex(
|
|
45
|
+
index: number,
|
|
46
|
+
size: number,
|
|
47
|
+
direction: number
|
|
48
|
+
): number {
|
|
49
|
+
return (index + size + direction) % size;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Array of params to be used on circular find next index.
|
|
53
|
+
* The values respresent start index, indexDelimiter, list of points
|
|
54
|
+
*/
|
|
55
|
+
type ListParamsType = [number, number, Types.Point2[]];
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Circular finding that returns the next index for two list where the criteria is met.
|
|
59
|
+
*
|
|
60
|
+
* It can compare two lists out of sync considering it does a circular iteration over them.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
*
|
|
64
|
+
* ```
|
|
65
|
+
* const pointsA = [[0, 1], [1, 3], [1, 5], [1,2]];
|
|
66
|
+
* const pointsB = [[1, 2], [1, 5], [1, 3], [0,0]];
|
|
67
|
+
* let firstParam = [0, 0, pointsA]
|
|
68
|
+
* let secondParam = [1, 1, pointsB]
|
|
69
|
+
* const criteria = (pointA, pointB) => areSamePosition(pointA, pointB)
|
|
70
|
+
* const direction = 1;
|
|
71
|
+
* let result = circularFindNextIndexBy(firstParam, secondParam, criteria,direction);
|
|
72
|
+
* console.log(result);
|
|
73
|
+
* // prints [1, 2]
|
|
74
|
+
* // use this result and find again
|
|
75
|
+
* firstParam = [result[0]+1, result[0], pointsA]
|
|
76
|
+
* secondParam = [result[1]+1, result[1], pointsB]
|
|
77
|
+
* result = circularFindNextIndexBy(firstParam, secondParam, criteria,direction);
|
|
78
|
+
* * // prints [3, 0]
|
|
79
|
+
*
|
|
80
|
+
*/
|
|
81
|
+
function circularFindNextIndexBy(
|
|
82
|
+
listParams: ListParamsType,
|
|
83
|
+
otherListParams: ListParamsType,
|
|
84
|
+
criteria: (pointA: Types.Point2, pointB: Types.Point2) => boolean,
|
|
85
|
+
direction: number
|
|
86
|
+
): [number | undefined, number | undefined] {
|
|
87
|
+
const [, indexDelimiter, points] = listParams;
|
|
88
|
+
const [, otherIndexDelimiter, otherPoints] = otherListParams;
|
|
89
|
+
|
|
90
|
+
const pointsLength = points.length;
|
|
91
|
+
const otherPointsLength = otherPoints.length;
|
|
92
|
+
|
|
93
|
+
let startIndex = listParams[0];
|
|
94
|
+
let otherStartIndex = otherListParams[0];
|
|
95
|
+
|
|
96
|
+
if (
|
|
97
|
+
!points[startIndex] ||
|
|
98
|
+
!otherPoints[otherStartIndex] ||
|
|
99
|
+
!points[indexDelimiter] ||
|
|
100
|
+
!otherPoints[otherIndexDelimiter]
|
|
101
|
+
) {
|
|
102
|
+
return [undefined, undefined];
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
while (
|
|
106
|
+
startIndex !== indexDelimiter &&
|
|
107
|
+
otherStartIndex !== otherIndexDelimiter
|
|
108
|
+
) {
|
|
109
|
+
if (criteria(otherPoints[otherStartIndex], points[startIndex])) {
|
|
110
|
+
return [startIndex, otherStartIndex];
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
startIndex = followingIndex(startIndex, pointsLength, direction);
|
|
114
|
+
otherStartIndex = followingIndex(
|
|
115
|
+
otherStartIndex,
|
|
116
|
+
otherPointsLength,
|
|
117
|
+
direction
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return [undefined, undefined];
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Given two list it will find the first and last index of segment from points that diverges from previousPoints
|
|
126
|
+
*/
|
|
127
|
+
function findChangedSegment(
|
|
128
|
+
points: Types.Point2[],
|
|
129
|
+
previousPoints: Types.Point2[]
|
|
130
|
+
): [number, number] {
|
|
131
|
+
const [firstMatchIndex, previousFirstMatchIndex] =
|
|
132
|
+
findMatchIndexes(points, previousPoints) || [];
|
|
133
|
+
|
|
134
|
+
const toBeNotEqualCriteria = (pointA, pointB) =>
|
|
135
|
+
isEqualByProximity(pointA, pointB) === false;
|
|
136
|
+
|
|
137
|
+
const [lowDiffIndex, lowOtherDiffIndex] = circularFindNextIndexBy(
|
|
138
|
+
[
|
|
139
|
+
followingIndex(firstMatchIndex, points.length, 1),
|
|
140
|
+
firstMatchIndex,
|
|
141
|
+
points,
|
|
142
|
+
],
|
|
143
|
+
[
|
|
144
|
+
followingIndex(previousFirstMatchIndex, previousPoints.length, 1),
|
|
145
|
+
previousFirstMatchIndex,
|
|
146
|
+
previousPoints,
|
|
147
|
+
],
|
|
148
|
+
toBeNotEqualCriteria,
|
|
149
|
+
1
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
const [highIndex] = circularFindNextIndexBy(
|
|
153
|
+
[followingIndex(lowDiffIndex, points.length, -1), lowDiffIndex, points],
|
|
154
|
+
[
|
|
155
|
+
followingIndex(lowOtherDiffIndex, previousPoints.length, -1),
|
|
156
|
+
lowOtherDiffIndex,
|
|
157
|
+
previousPoints,
|
|
158
|
+
],
|
|
159
|
+
toBeNotEqualCriteria,
|
|
160
|
+
-1
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
return [lowDiffIndex, highIndex];
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Interpolates the given list of points. In case there is a pointsOfReference the interpolation will occur only on segment disjoint of two list. I.e list of points from param points that are not on list of points from param pointsOfReference.
|
|
168
|
+
*/
|
|
169
|
+
export function getInterpolatedPoints(
|
|
170
|
+
configuration: Record<any, any>,
|
|
171
|
+
points: Types.Point2[],
|
|
172
|
+
pointsOfReference?: Types.Point2[]
|
|
173
|
+
): Types.Point2[] {
|
|
174
|
+
const { interpolation } = configuration;
|
|
175
|
+
|
|
176
|
+
const result = points;
|
|
177
|
+
|
|
178
|
+
if (interpolation) {
|
|
179
|
+
const {
|
|
180
|
+
knotsRatioPercentageOnAdd,
|
|
181
|
+
knotsRatioPercentageOnEdit,
|
|
182
|
+
interpolateOnAdd = false,
|
|
183
|
+
interpolateOnEdit = false,
|
|
184
|
+
} = interpolation;
|
|
185
|
+
|
|
186
|
+
const knotsRatioPercentage = pointsOfReference
|
|
187
|
+
? knotsRatioPercentageOnEdit
|
|
188
|
+
: knotsRatioPercentageOnAdd;
|
|
189
|
+
const isEnabled = pointsOfReference ? interpolateOnEdit : interpolateOnAdd;
|
|
190
|
+
|
|
191
|
+
if (isEnabled) {
|
|
192
|
+
// partial or total interpolation
|
|
193
|
+
const [changedIniIndex, changedEndIndex] = pointsOfReference
|
|
194
|
+
? findChangedSegment(points, pointsOfReference)
|
|
195
|
+
: [0, points.length - 1];
|
|
196
|
+
|
|
197
|
+
// do not interpolate if there is no valid segment
|
|
198
|
+
if (!points[changedIniIndex] || !points[changedEndIndex]) {
|
|
199
|
+
return points;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return <Types.Point2[]>(
|
|
203
|
+
interpolateSegmentPoints(
|
|
204
|
+
points,
|
|
205
|
+
changedIniIndex,
|
|
206
|
+
changedEndIndex,
|
|
207
|
+
knotsRatioPercentage
|
|
208
|
+
)
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return result;
|
|
214
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import {
|
|
2
|
+
interpolateBasis as d3InterpolateBasis,
|
|
3
|
+
quantize as d3Quantize,
|
|
4
|
+
} from 'd3-interpolate';
|
|
5
|
+
import { zip as d3Zip } from 'd3-array';
|
|
6
|
+
import { Types } from '@cornerstonejs/core';
|
|
7
|
+
|
|
8
|
+
function isPoints3D(
|
|
9
|
+
points: (Types.Point2 | Types.Point3)[]
|
|
10
|
+
): points is Types.Point3[] {
|
|
11
|
+
return (points as Types.Point3[])[0]?.length === 3;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Returns an array of the originalPoints length containing the interpolated data.
|
|
16
|
+
* It interpolates a set of points indexed by knotsIndexes.
|
|
17
|
+
* That is, it DISCARDS all points except those in knotsIndexes. Then, a new set of points is created by using a b-spline on the remaining points, in order to re-create a new set of points.
|
|
18
|
+
*/
|
|
19
|
+
export function interpolatePoints(
|
|
20
|
+
originalPoints: (Types.Point2 | Types.Point3)[],
|
|
21
|
+
knotsIndexes: number[]
|
|
22
|
+
): (Types.Point2 | Types.Point3)[] {
|
|
23
|
+
if (
|
|
24
|
+
!knotsIndexes ||
|
|
25
|
+
knotsIndexes.length === 0 ||
|
|
26
|
+
knotsIndexes.length === originalPoints.length
|
|
27
|
+
) {
|
|
28
|
+
return originalPoints;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const n = knotsIndexes[knotsIndexes.length - 1] - knotsIndexes[0] + 1;
|
|
32
|
+
const xInterpolator = d3InterpolateBasis(
|
|
33
|
+
knotsIndexes.map((k) => originalPoints[k][0])
|
|
34
|
+
);
|
|
35
|
+
const yInterpolator = d3InterpolateBasis(
|
|
36
|
+
knotsIndexes.map((k) => originalPoints[k][1])
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
if (isPoints3D(originalPoints)) {
|
|
40
|
+
const zInterpolator = d3InterpolateBasis(
|
|
41
|
+
knotsIndexes.map((k) => originalPoints[k][2])
|
|
42
|
+
);
|
|
43
|
+
return <Types.Point3[]>(
|
|
44
|
+
d3Zip(
|
|
45
|
+
d3Quantize(xInterpolator, n),
|
|
46
|
+
d3Quantize(yInterpolator, n),
|
|
47
|
+
d3Quantize(zInterpolator, n)
|
|
48
|
+
)
|
|
49
|
+
);
|
|
50
|
+
} else {
|
|
51
|
+
return <Types.Point2[]>(
|
|
52
|
+
d3Zip(d3Quantize(xInterpolator, n), d3Quantize(yInterpolator, n))
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { Types } from '@cornerstonejs/core';
|
|
2
|
+
import { interpolatePoints } from './algorithms/bspline';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Returns a list of uniform distributed values. This list contains the max amount of values which has at least a minimum distance between two consecutive values.
|
|
6
|
+
* minDistributionDistance means the min distance between two consecutive distributed values.
|
|
7
|
+
* Closed interval contains the min/max values.
|
|
8
|
+
*
|
|
9
|
+
* Formula for reference
|
|
10
|
+
* For given {x ∈ R | x ≥ 0} and {minDis ∈ R | minDis ≥ 0}, ∃ D(x) where D(x) ≥ a and D(x) ≤ b =>
|
|
11
|
+
* |
|
|
12
|
+
* D(x) = | (b - a)
|
|
13
|
+
* | round( ------------------------ * x ) + a
|
|
14
|
+
* | (b - a + 1)
|
|
15
|
+
* | round( ----------- )
|
|
16
|
+
* | minDis
|
|
17
|
+
*/
|
|
18
|
+
function getContinuousUniformDistributionValues(
|
|
19
|
+
minDistributionDistance: number,
|
|
20
|
+
closedInterval: [number, number]
|
|
21
|
+
): number[] {
|
|
22
|
+
const result = [];
|
|
23
|
+
const [intervalIni, intervalEnd] = closedInterval;
|
|
24
|
+
|
|
25
|
+
const intervalSize = intervalEnd - intervalIni + 1;
|
|
26
|
+
const intensity = Math.floor(intervalSize / minDistributionDistance);
|
|
27
|
+
|
|
28
|
+
let x = 0;
|
|
29
|
+
let continuosDistributionValue =
|
|
30
|
+
Math.round(((intervalSize - 1) / (intensity - 1)) * x) + intervalIni;
|
|
31
|
+
|
|
32
|
+
while (continuosDistributionValue <= intervalEnd) {
|
|
33
|
+
result.push(continuosDistributionValue);
|
|
34
|
+
x++;
|
|
35
|
+
continuosDistributionValue =
|
|
36
|
+
Math.round(((intervalSize - 1) / (intensity - 1)) * x) + intervalIni;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Interpolates a segment of points from iniIndex until endIndex.
|
|
44
|
+
* The process of interpolation considers the param knotsRatioPercentage as being the percentage of points from Segment that are likely to be considered.
|
|
45
|
+
* By default it uses b-spline algorithm.
|
|
46
|
+
* The result total of points is equal to original points.
|
|
47
|
+
*/
|
|
48
|
+
export default function interpolateSegmentPoints(
|
|
49
|
+
points: (Types.Point2 | Types.Point3)[],
|
|
50
|
+
iniIndex: number,
|
|
51
|
+
endIndex: number,
|
|
52
|
+
knotsRatioPercentage: number
|
|
53
|
+
): (Types.Point2 | Types.Point3)[] {
|
|
54
|
+
const segmentSize = endIndex - iniIndex + 1;
|
|
55
|
+
|
|
56
|
+
const amountOfKnots =
|
|
57
|
+
Math.floor((knotsRatioPercentage / 100) * segmentSize) ?? 1;
|
|
58
|
+
const minKnotDistance = Math.floor(segmentSize / amountOfKnots) ?? 1;
|
|
59
|
+
|
|
60
|
+
if (isNaN(segmentSize) || !segmentSize || !minKnotDistance) {
|
|
61
|
+
return points;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// segment should be at least the double of desired minKnot distance. This will ensure at there will enough knots to interpolate.
|
|
65
|
+
if (segmentSize / minKnotDistance < 2) {
|
|
66
|
+
return points;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const interpolationIniIndex = Math.max(0, iniIndex);
|
|
70
|
+
const interpolationEndIndex = Math.min(points.length - 1, endIndex);
|
|
71
|
+
const segmentPointsUnchangedBeg = points.slice(0, interpolationIniIndex);
|
|
72
|
+
|
|
73
|
+
const segmentPointsUnchangedEnd = points.slice(
|
|
74
|
+
interpolationEndIndex + 1,
|
|
75
|
+
points.length
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
const knotsIndexes = getContinuousUniformDistributionValues(minKnotDistance, [
|
|
79
|
+
interpolationIniIndex,
|
|
80
|
+
interpolationEndIndex,
|
|
81
|
+
]);
|
|
82
|
+
|
|
83
|
+
const interpolatedPoints = interpolatePoints(points, knotsIndexes);
|
|
84
|
+
|
|
85
|
+
return [
|
|
86
|
+
...segmentPointsUnchangedBeg,
|
|
87
|
+
...interpolatedPoints,
|
|
88
|
+
...segmentPointsUnchangedEnd,
|
|
89
|
+
];
|
|
90
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { vec3 } from 'gl-matrix';
|
|
2
|
+
import type { Types } from '@cornerstonejs/core';
|
|
3
|
+
import type { vtkImageData } from '@kitware/vtk.js/Common/DataModel/ImageData';
|
|
4
|
+
import BoundsIJK from '../types/BoundsIJK';
|
|
5
|
+
|
|
6
|
+
export type PointInShapeCallback = ({
|
|
7
|
+
value,
|
|
8
|
+
index,
|
|
9
|
+
pointIJK,
|
|
10
|
+
pointLPS,
|
|
11
|
+
}: {
|
|
12
|
+
value: number;
|
|
13
|
+
index: number;
|
|
14
|
+
pointIJK: Types.Point3;
|
|
15
|
+
pointLPS: Types.Point3;
|
|
16
|
+
}) => void;
|
|
17
|
+
|
|
18
|
+
export type ShapeFnCriteria = (
|
|
19
|
+
pointIJK: Types.Point3,
|
|
20
|
+
pointLPS: Types.Point3
|
|
21
|
+
) => boolean;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* For each point in the image (If boundsIJK is not provided, otherwise, for each
|
|
25
|
+
* point in the provided bounding box), It runs the provided callback IF the point
|
|
26
|
+
* passes the provided criteria to be inside the shape (which is defined by the
|
|
27
|
+
* provided pointInShapeFn)
|
|
28
|
+
*
|
|
29
|
+
* @param imageData - The image data object.
|
|
30
|
+
* @param dimensions - The dimensions of the image.
|
|
31
|
+
* @param pointInShapeFn - A function that takes a point in LPS space and returns
|
|
32
|
+
* true if the point is in the shape and false if it is not.
|
|
33
|
+
* @param callback - A function that will be called for
|
|
34
|
+
* every point in the shape.
|
|
35
|
+
* @param boundsIJK - The bounds of the volume in IJK coordinates.
|
|
36
|
+
*/
|
|
37
|
+
export default function pointInShapeCallback(
|
|
38
|
+
imageData: vtkImageData | Types.CPUImageData,
|
|
39
|
+
pointInShapeFn: ShapeFnCriteria,
|
|
40
|
+
callback: PointInShapeCallback,
|
|
41
|
+
boundsIJK?: BoundsIJK
|
|
42
|
+
): void {
|
|
43
|
+
let iMin, iMax, jMin, jMax, kMin, kMax;
|
|
44
|
+
|
|
45
|
+
let scalarData;
|
|
46
|
+
|
|
47
|
+
// if getScalarData is a method on imageData
|
|
48
|
+
if ((imageData as Types.CPUImageData).getScalarData) {
|
|
49
|
+
scalarData = (imageData as Types.CPUImageData).getScalarData();
|
|
50
|
+
} else {
|
|
51
|
+
scalarData = (imageData as vtkImageData)
|
|
52
|
+
.getPointData()
|
|
53
|
+
.getScalars()
|
|
54
|
+
.getData();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const dimensions = imageData.getDimensions();
|
|
58
|
+
|
|
59
|
+
if (!boundsIJK) {
|
|
60
|
+
iMin = 0;
|
|
61
|
+
iMax = dimensions[0];
|
|
62
|
+
jMin = 0;
|
|
63
|
+
jMax = dimensions[1];
|
|
64
|
+
kMin = 0;
|
|
65
|
+
kMax = dimensions[2];
|
|
66
|
+
} else {
|
|
67
|
+
[[iMin, iMax], [jMin, jMax], [kMin, kMax]] = boundsIJK;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const start = vec3.fromValues(iMin, jMin, kMin);
|
|
71
|
+
|
|
72
|
+
const direction = imageData.getDirection();
|
|
73
|
+
const rowCosines = direction.slice(0, 3);
|
|
74
|
+
const columnCosines = direction.slice(3, 6);
|
|
75
|
+
const scanAxisNormal = direction.slice(6, 9);
|
|
76
|
+
|
|
77
|
+
const spacing = imageData.getSpacing();
|
|
78
|
+
const [rowSpacing, columnSpacing, scanAxisSpacing] = spacing;
|
|
79
|
+
|
|
80
|
+
// @ts-ignore will be fixed in vtk-master
|
|
81
|
+
const worldPosStart = imageData.indexToWorld(start);
|
|
82
|
+
|
|
83
|
+
const rowStep = vec3.fromValues(
|
|
84
|
+
rowCosines[0] * rowSpacing,
|
|
85
|
+
rowCosines[1] * rowSpacing,
|
|
86
|
+
rowCosines[2] * rowSpacing
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
const columnStep = vec3.fromValues(
|
|
90
|
+
columnCosines[0] * columnSpacing,
|
|
91
|
+
columnCosines[1] * columnSpacing,
|
|
92
|
+
columnCosines[2] * columnSpacing
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
const scanAxisStep = vec3.fromValues(
|
|
96
|
+
scanAxisNormal[0] * scanAxisSpacing,
|
|
97
|
+
scanAxisNormal[1] * scanAxisSpacing,
|
|
98
|
+
scanAxisNormal[2] * scanAxisSpacing
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
const yMultiple = dimensions[0];
|
|
102
|
+
const zMultiple = dimensions[0] * dimensions[1];
|
|
103
|
+
|
|
104
|
+
for (let k = kMin; k <= kMax; k++) {
|
|
105
|
+
for (let j = jMin; j <= jMax; j++) {
|
|
106
|
+
for (let i = iMin; i <= iMax; i++) {
|
|
107
|
+
const pointIJK: Types.Point3 = [i, j, k];
|
|
108
|
+
const dI = i - iMin;
|
|
109
|
+
const dJ = j - jMin;
|
|
110
|
+
const dK = k - kMin;
|
|
111
|
+
|
|
112
|
+
const startWorld = worldPosStart;
|
|
113
|
+
|
|
114
|
+
const pointLPS: Types.Point3 = [
|
|
115
|
+
startWorld[0] +
|
|
116
|
+
dI * rowStep[0] +
|
|
117
|
+
dJ * columnStep[0] +
|
|
118
|
+
dK * scanAxisStep[0],
|
|
119
|
+
startWorld[1] +
|
|
120
|
+
dI * rowStep[1] +
|
|
121
|
+
dJ * columnStep[1] +
|
|
122
|
+
dK * scanAxisStep[1],
|
|
123
|
+
startWorld[2] +
|
|
124
|
+
dI * rowStep[2] +
|
|
125
|
+
dJ * columnStep[2] +
|
|
126
|
+
dK * scanAxisStep[2],
|
|
127
|
+
];
|
|
128
|
+
|
|
129
|
+
if (pointInShapeFn(pointLPS, pointIJK)) {
|
|
130
|
+
const index = k * zMultiple + j * yMultiple + i;
|
|
131
|
+
const value = scalarData[index];
|
|
132
|
+
|
|
133
|
+
callback({ value, index, pointIJK, pointLPS });
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|