@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,681 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-empty-function */
|
|
2
|
+
import { vec2 } from 'gl-matrix';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
getEnabledElement,
|
|
6
|
+
VolumeViewport,
|
|
7
|
+
triggerEvent,
|
|
8
|
+
eventTarget,
|
|
9
|
+
utilities as csUtils,
|
|
10
|
+
utilities,
|
|
11
|
+
} from '@cornerstonejs/core';
|
|
12
|
+
import type { Types } from '@cornerstonejs/core';
|
|
13
|
+
|
|
14
|
+
import { AnnotationTool } from '../base';
|
|
15
|
+
import {
|
|
16
|
+
addAnnotation,
|
|
17
|
+
getAnnotations,
|
|
18
|
+
removeAnnotation,
|
|
19
|
+
} from '../../stateManagement/annotation/annotationState';
|
|
20
|
+
import {
|
|
21
|
+
drawHandles as drawHandlesSvg,
|
|
22
|
+
drawTextBox as drawTextBoxSvg,
|
|
23
|
+
} from '../../drawingSvg';
|
|
24
|
+
import { state } from '../../store';
|
|
25
|
+
import { Events } from '../../enums';
|
|
26
|
+
import { getViewportIdsWithToolToRender } from '../../utilities/viewportFilters';
|
|
27
|
+
import {
|
|
28
|
+
resetElementCursor,
|
|
29
|
+
hideElementCursor,
|
|
30
|
+
} from '../../cursors/elementCursor';
|
|
31
|
+
import {
|
|
32
|
+
AnnotationCompletedEventDetail,
|
|
33
|
+
AnnotationModifiedEventDetail,
|
|
34
|
+
} from '../../types/EventTypes';
|
|
35
|
+
|
|
36
|
+
import triggerAnnotationRenderForViewportIds from '../../utilities/triggerAnnotationRenderForViewportIds';
|
|
37
|
+
|
|
38
|
+
import {
|
|
39
|
+
EventTypes,
|
|
40
|
+
ToolHandle,
|
|
41
|
+
PublicToolProps,
|
|
42
|
+
ToolProps,
|
|
43
|
+
SVGDrawingHelper,
|
|
44
|
+
} from '../../types';
|
|
45
|
+
import { ProbeAnnotation } from '../../types/ToolSpecificAnnotationTypes';
|
|
46
|
+
import { StyleSpecifier } from '../../types/AnnotationStyle';
|
|
47
|
+
import { getModalityUnit } from '../../utilities/getModalityUnit';
|
|
48
|
+
import { isViewportPreScaled } from '../../utilities/viewport/isViewportPreScaled';
|
|
49
|
+
|
|
50
|
+
const { transformWorldToIndex } = csUtils;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* ProbeTool let you get the underlying voxel value by putting a probe in that
|
|
54
|
+
* location. It will give index of the location and value of the voxel.
|
|
55
|
+
* You can use ProbeTool in all perpendicular views (axial, sagittal, coronal).
|
|
56
|
+
* Note: annotation tools in cornerstone3DTools exists in the exact location
|
|
57
|
+
* in the physical 3d space, as a result, by default, all annotations that are
|
|
58
|
+
* drawing in the same frameOfReference will get shared between viewports that
|
|
59
|
+
* are in the same frameOfReference. Probe tool's text box are dynamically
|
|
60
|
+
* generated based on the viewport's underlying Modality. For instance, if
|
|
61
|
+
* the viewport is displaying CT, the text box will shown the statistics in Hounsfield units,
|
|
62
|
+
* and if the viewport is displaying PET, the text box will show the statistics in
|
|
63
|
+
* SUV units.
|
|
64
|
+
*
|
|
65
|
+
* The resulting annotation's data (statistics) and metadata (the
|
|
66
|
+
* state of the viewport while drawing was happening) will get added to the
|
|
67
|
+
* ToolState manager and can be accessed from the ToolState by calling getAnnotations
|
|
68
|
+
* or similar methods.
|
|
69
|
+
*
|
|
70
|
+
* To use the ProbeTool, you first need to add it to cornerstoneTools, then create
|
|
71
|
+
* a toolGroup and add the ProbeTool to it. Finally, setToolActive on the toolGroup
|
|
72
|
+
*
|
|
73
|
+
* ```js
|
|
74
|
+
* cornerstoneTools.addTool(ProbeTool)
|
|
75
|
+
*
|
|
76
|
+
* const toolGroup = ToolGroupManager.createToolGroup('toolGroupId')
|
|
77
|
+
*
|
|
78
|
+
* toolGroup.addTool(ProbeTool.toolName)
|
|
79
|
+
*
|
|
80
|
+
* toolGroup.addViewport('viewportId', 'renderingEngineId')
|
|
81
|
+
*
|
|
82
|
+
* toolGroup.setToolActive(ProbeTool.toolName, {
|
|
83
|
+
* bindings: [
|
|
84
|
+
* {
|
|
85
|
+
* mouseButton: MouseBindings.Primary, // Left Click
|
|
86
|
+
* },
|
|
87
|
+
* ],
|
|
88
|
+
* })
|
|
89
|
+
* ```
|
|
90
|
+
*
|
|
91
|
+
* Read more in the Docs section of the website.
|
|
92
|
+
*
|
|
93
|
+
*/
|
|
94
|
+
class ProbeTool extends AnnotationTool {
|
|
95
|
+
static toolName;
|
|
96
|
+
|
|
97
|
+
touchDragCallback: any;
|
|
98
|
+
mouseDragCallback: any;
|
|
99
|
+
editData: {
|
|
100
|
+
annotation: any;
|
|
101
|
+
viewportIdsToRender: string[];
|
|
102
|
+
newAnnotation?: boolean;
|
|
103
|
+
} | null;
|
|
104
|
+
eventDispatchDetail: {
|
|
105
|
+
viewportId: string;
|
|
106
|
+
renderingEngineId: string;
|
|
107
|
+
};
|
|
108
|
+
isDrawing: boolean;
|
|
109
|
+
isHandleOutsideImage: boolean;
|
|
110
|
+
|
|
111
|
+
constructor(
|
|
112
|
+
toolProps: PublicToolProps = {},
|
|
113
|
+
defaultToolProps: ToolProps = {
|
|
114
|
+
supportedInteractionTypes: ['Mouse', 'Touch'],
|
|
115
|
+
configuration: {
|
|
116
|
+
shadow: true,
|
|
117
|
+
preventHandleOutsideImage: false,
|
|
118
|
+
},
|
|
119
|
+
}
|
|
120
|
+
) {
|
|
121
|
+
super(toolProps, defaultToolProps);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Not necessary for this tool but needs to be defined since it's an abstract
|
|
125
|
+
// method from the parent class.
|
|
126
|
+
isPointNearTool(): boolean {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
toolSelectedCallback() {}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Based on the current position of the mouse and the current imageId to create
|
|
134
|
+
* a Probe Annotation and stores it in the annotationManager
|
|
135
|
+
*
|
|
136
|
+
* @param evt - EventTypes.NormalizedMouseEventType
|
|
137
|
+
* @returns The annotation object.
|
|
138
|
+
*
|
|
139
|
+
*/
|
|
140
|
+
addNewAnnotation = (
|
|
141
|
+
evt: EventTypes.InteractionEventType
|
|
142
|
+
): ProbeAnnotation => {
|
|
143
|
+
const eventDetail = evt.detail;
|
|
144
|
+
const { currentPoints, element } = eventDetail;
|
|
145
|
+
const worldPos = currentPoints.world;
|
|
146
|
+
|
|
147
|
+
const enabledElement = getEnabledElement(element);
|
|
148
|
+
const { viewport, renderingEngine } = enabledElement;
|
|
149
|
+
|
|
150
|
+
this.isDrawing = true;
|
|
151
|
+
const camera = viewport.getCamera();
|
|
152
|
+
const { viewPlaneNormal, viewUp } = camera;
|
|
153
|
+
|
|
154
|
+
const referencedImageId = this.getReferencedImageId(
|
|
155
|
+
viewport,
|
|
156
|
+
worldPos,
|
|
157
|
+
viewPlaneNormal,
|
|
158
|
+
viewUp
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
const FrameOfReferenceUID = viewport.getFrameOfReferenceUID();
|
|
162
|
+
|
|
163
|
+
const annotation = {
|
|
164
|
+
invalidated: true,
|
|
165
|
+
highlighted: true,
|
|
166
|
+
metadata: {
|
|
167
|
+
toolName: this.getToolName(),
|
|
168
|
+
viewPlaneNormal: <Types.Point3>[...viewPlaneNormal],
|
|
169
|
+
viewUp: <Types.Point3>[...viewUp],
|
|
170
|
+
FrameOfReferenceUID,
|
|
171
|
+
referencedImageId,
|
|
172
|
+
},
|
|
173
|
+
data: {
|
|
174
|
+
label: '',
|
|
175
|
+
handles: { points: [<Types.Point3>[...worldPos]] },
|
|
176
|
+
cachedStats: {},
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
addAnnotation(annotation, element);
|
|
181
|
+
|
|
182
|
+
const viewportIdsToRender = getViewportIdsWithToolToRender(
|
|
183
|
+
element,
|
|
184
|
+
this.getToolName()
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
this.editData = {
|
|
188
|
+
annotation,
|
|
189
|
+
newAnnotation: true,
|
|
190
|
+
viewportIdsToRender,
|
|
191
|
+
};
|
|
192
|
+
this._activateModify(element);
|
|
193
|
+
|
|
194
|
+
hideElementCursor(element);
|
|
195
|
+
|
|
196
|
+
evt.preventDefault();
|
|
197
|
+
|
|
198
|
+
triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender);
|
|
199
|
+
|
|
200
|
+
return annotation;
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* It checks if the mouse click is near ProveTool, it overwrites the baseAnnotationTool
|
|
205
|
+
* getHandleNearImagePoint method.
|
|
206
|
+
*
|
|
207
|
+
* @param element - The element that the tool is attached to.
|
|
208
|
+
* @param annotation - The annotation object associated with the annotation
|
|
209
|
+
* @param canvasCoords - The coordinates of the mouse click on canvas
|
|
210
|
+
* @param proximity - The distance from the mouse cursor to the point
|
|
211
|
+
* that is considered "near".
|
|
212
|
+
* @returns The handle that is closest to the cursor, or null if the cursor
|
|
213
|
+
* is not near any of the handles.
|
|
214
|
+
*/
|
|
215
|
+
getHandleNearImagePoint(
|
|
216
|
+
element: HTMLDivElement,
|
|
217
|
+
annotation: ProbeAnnotation,
|
|
218
|
+
canvasCoords: Types.Point2,
|
|
219
|
+
proximity: number
|
|
220
|
+
): ToolHandle | undefined {
|
|
221
|
+
const enabledElement = getEnabledElement(element);
|
|
222
|
+
const { viewport } = enabledElement;
|
|
223
|
+
|
|
224
|
+
const { data } = annotation;
|
|
225
|
+
const point = data.handles.points[0];
|
|
226
|
+
const annotationCanvasCoordinate = viewport.worldToCanvas(point);
|
|
227
|
+
|
|
228
|
+
const near =
|
|
229
|
+
vec2.distance(canvasCoords, annotationCanvasCoordinate) < proximity;
|
|
230
|
+
|
|
231
|
+
if (near === true) {
|
|
232
|
+
return point;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
handleSelectedCallback(
|
|
237
|
+
evt: EventTypes.InteractionEventType,
|
|
238
|
+
annotation: ProbeAnnotation
|
|
239
|
+
): void {
|
|
240
|
+
const eventDetail = evt.detail;
|
|
241
|
+
const { element } = eventDetail;
|
|
242
|
+
|
|
243
|
+
annotation.highlighted = true;
|
|
244
|
+
|
|
245
|
+
const viewportIdsToRender = getViewportIdsWithToolToRender(
|
|
246
|
+
element,
|
|
247
|
+
this.getToolName()
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
// Find viewports to render on drag.
|
|
251
|
+
|
|
252
|
+
this.editData = {
|
|
253
|
+
//handle, // This would be useful for other tools with more than one handle
|
|
254
|
+
annotation,
|
|
255
|
+
viewportIdsToRender,
|
|
256
|
+
};
|
|
257
|
+
this._activateModify(element);
|
|
258
|
+
|
|
259
|
+
hideElementCursor(element);
|
|
260
|
+
|
|
261
|
+
const enabledElement = getEnabledElement(element);
|
|
262
|
+
const { renderingEngine } = enabledElement;
|
|
263
|
+
|
|
264
|
+
triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender);
|
|
265
|
+
|
|
266
|
+
evt.preventDefault();
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
_endCallback = (evt: EventTypes.InteractionEventType): void => {
|
|
270
|
+
const eventDetail = evt.detail;
|
|
271
|
+
const { element } = eventDetail;
|
|
272
|
+
|
|
273
|
+
const { annotation, viewportIdsToRender, newAnnotation } = this.editData;
|
|
274
|
+
|
|
275
|
+
const enabledElement = getEnabledElement(element);
|
|
276
|
+
const { renderingEngine } = enabledElement;
|
|
277
|
+
|
|
278
|
+
const { viewportId } = enabledElement;
|
|
279
|
+
this.eventDispatchDetail = {
|
|
280
|
+
viewportId,
|
|
281
|
+
renderingEngineId: renderingEngine.id,
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
this._deactivateModify(element);
|
|
285
|
+
|
|
286
|
+
resetElementCursor(element);
|
|
287
|
+
|
|
288
|
+
this.editData = null;
|
|
289
|
+
this.isDrawing = false;
|
|
290
|
+
|
|
291
|
+
if (
|
|
292
|
+
this.isHandleOutsideImage &&
|
|
293
|
+
this.configuration.preventHandleOutsideImage
|
|
294
|
+
) {
|
|
295
|
+
removeAnnotation(annotation.annotationUID);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender);
|
|
299
|
+
|
|
300
|
+
if (newAnnotation) {
|
|
301
|
+
const eventType = Events.ANNOTATION_COMPLETED;
|
|
302
|
+
|
|
303
|
+
const eventDetail: AnnotationCompletedEventDetail = {
|
|
304
|
+
annotation,
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
triggerEvent(eventTarget, eventType, eventDetail);
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
_dragCallback = (evt) => {
|
|
312
|
+
this.isDrawing = true;
|
|
313
|
+
const eventDetail = evt.detail;
|
|
314
|
+
const { currentPoints, element } = eventDetail;
|
|
315
|
+
const worldPos = currentPoints.world;
|
|
316
|
+
|
|
317
|
+
const { annotation, viewportIdsToRender } = this.editData;
|
|
318
|
+
const { data } = annotation;
|
|
319
|
+
|
|
320
|
+
data.handles.points[0] = [...worldPos];
|
|
321
|
+
annotation.invalidated = true;
|
|
322
|
+
|
|
323
|
+
const enabledElement = getEnabledElement(element);
|
|
324
|
+
const { renderingEngine } = enabledElement;
|
|
325
|
+
|
|
326
|
+
triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender);
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
cancel = (element: HTMLDivElement) => {
|
|
330
|
+
// If it is mid-draw or mid-modify
|
|
331
|
+
if (this.isDrawing) {
|
|
332
|
+
this.isDrawing = false;
|
|
333
|
+
this._deactivateModify(element);
|
|
334
|
+
resetElementCursor(element);
|
|
335
|
+
|
|
336
|
+
const { annotation, viewportIdsToRender, newAnnotation } = this.editData;
|
|
337
|
+
const { data } = annotation;
|
|
338
|
+
|
|
339
|
+
annotation.highlighted = false;
|
|
340
|
+
data.handles.activeHandleIndex = null;
|
|
341
|
+
|
|
342
|
+
const enabledElement = getEnabledElement(element);
|
|
343
|
+
const { renderingEngine } = enabledElement;
|
|
344
|
+
|
|
345
|
+
triggerAnnotationRenderForViewportIds(
|
|
346
|
+
renderingEngine,
|
|
347
|
+
viewportIdsToRender
|
|
348
|
+
);
|
|
349
|
+
|
|
350
|
+
if (newAnnotation) {
|
|
351
|
+
const eventType = Events.ANNOTATION_COMPLETED;
|
|
352
|
+
|
|
353
|
+
const eventDetail: AnnotationCompletedEventDetail = {
|
|
354
|
+
annotation,
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
triggerEvent(eventTarget, eventType, eventDetail);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
this.editData = null;
|
|
361
|
+
return annotation.annotationUID;
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
_activateModify = (element) => {
|
|
366
|
+
state.isInteractingWithTool = true;
|
|
367
|
+
|
|
368
|
+
element.addEventListener(Events.MOUSE_UP, this._endCallback);
|
|
369
|
+
element.addEventListener(Events.MOUSE_DRAG, this._dragCallback);
|
|
370
|
+
element.addEventListener(Events.MOUSE_CLICK, this._endCallback);
|
|
371
|
+
|
|
372
|
+
element.addEventListener(Events.TOUCH_END, this._endCallback);
|
|
373
|
+
element.addEventListener(Events.TOUCH_DRAG, this._dragCallback);
|
|
374
|
+
element.addEventListener(Events.TOUCH_TAP, this._endCallback);
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
_deactivateModify = (element) => {
|
|
378
|
+
state.isInteractingWithTool = false;
|
|
379
|
+
|
|
380
|
+
element.removeEventListener(Events.MOUSE_UP, this._endCallback);
|
|
381
|
+
element.removeEventListener(Events.MOUSE_DRAG, this._dragCallback);
|
|
382
|
+
element.removeEventListener(Events.MOUSE_CLICK, this._endCallback);
|
|
383
|
+
|
|
384
|
+
element.removeEventListener(Events.TOUCH_END, this._endCallback);
|
|
385
|
+
element.removeEventListener(Events.TOUCH_DRAG, this._dragCallback);
|
|
386
|
+
element.removeEventListener(Events.TOUCH_TAP, this._endCallback);
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* it is used to draw the probe annotation in each
|
|
391
|
+
* request animation frame. It calculates the updated cached statistics if
|
|
392
|
+
* data is invalidated and cache it.
|
|
393
|
+
*
|
|
394
|
+
* @param enabledElement - The Cornerstone's enabledElement.
|
|
395
|
+
* @param svgDrawingHelper - The svgDrawingHelper providing the context for drawing.
|
|
396
|
+
*/
|
|
397
|
+
renderAnnotation = (
|
|
398
|
+
enabledElement: Types.IEnabledElement,
|
|
399
|
+
svgDrawingHelper: SVGDrawingHelper
|
|
400
|
+
): boolean => {
|
|
401
|
+
let renderStatus = false;
|
|
402
|
+
const { viewport } = enabledElement;
|
|
403
|
+
const { element } = viewport;
|
|
404
|
+
|
|
405
|
+
let annotations = getAnnotations(this.getToolName(), element);
|
|
406
|
+
|
|
407
|
+
if (!annotations?.length) {
|
|
408
|
+
return renderStatus;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
annotations = this.filterInteractableAnnotationsForElement(
|
|
412
|
+
element,
|
|
413
|
+
annotations
|
|
414
|
+
);
|
|
415
|
+
|
|
416
|
+
if (!annotations?.length) {
|
|
417
|
+
return renderStatus;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
const targetId = this.getTargetId(viewport);
|
|
421
|
+
const renderingEngine = viewport.getRenderingEngine();
|
|
422
|
+
|
|
423
|
+
const styleSpecifier: StyleSpecifier = {
|
|
424
|
+
toolGroupId: this.toolGroupId,
|
|
425
|
+
toolName: this.getToolName(),
|
|
426
|
+
viewportId: enabledElement.viewport.id,
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
for (let i = 0; i < annotations.length; i++) {
|
|
430
|
+
const annotation = annotations[i] as ProbeAnnotation;
|
|
431
|
+
const annotationUID = annotation.annotationUID;
|
|
432
|
+
const data = annotation.data;
|
|
433
|
+
const point = data.handles.points[0];
|
|
434
|
+
const canvasCoordinates = viewport.worldToCanvas(point);
|
|
435
|
+
|
|
436
|
+
styleSpecifier.annotationUID = annotationUID;
|
|
437
|
+
|
|
438
|
+
const color = this.getStyle('color', styleSpecifier, annotation);
|
|
439
|
+
|
|
440
|
+
if (!data.cachedStats[targetId]) {
|
|
441
|
+
data.cachedStats[targetId] = {
|
|
442
|
+
Modality: null,
|
|
443
|
+
index: null,
|
|
444
|
+
value: null,
|
|
445
|
+
};
|
|
446
|
+
|
|
447
|
+
this._calculateCachedStats(annotation, renderingEngine, enabledElement);
|
|
448
|
+
} else if (annotation.invalidated) {
|
|
449
|
+
this._calculateCachedStats(annotation, renderingEngine, enabledElement);
|
|
450
|
+
|
|
451
|
+
// If the invalidated data is as a result of volumeViewport manipulation
|
|
452
|
+
// of the tools, we need to invalidate the related stackViewports data if
|
|
453
|
+
// they are not at the referencedImageId, so that
|
|
454
|
+
// when scrolling to the related slice in which the tool were manipulated
|
|
455
|
+
// we re-render the correct tool position. This is due to stackViewport
|
|
456
|
+
// which doesn't have the full volume at each time, and we are only working
|
|
457
|
+
// on one slice at a time.
|
|
458
|
+
if (viewport instanceof VolumeViewport) {
|
|
459
|
+
const { referencedImageId } = annotation.metadata;
|
|
460
|
+
|
|
461
|
+
// invalidate all the relevant stackViewports if they are not
|
|
462
|
+
// at the referencedImageId
|
|
463
|
+
for (const targetId in data.cachedStats) {
|
|
464
|
+
if (targetId.startsWith('imageId')) {
|
|
465
|
+
const viewports = renderingEngine.getStackViewports();
|
|
466
|
+
|
|
467
|
+
const invalidatedStack = viewports.find((vp) => {
|
|
468
|
+
// The stack viewport that contains the imageId but is not
|
|
469
|
+
// showing it currently
|
|
470
|
+
const referencedImageURI =
|
|
471
|
+
csUtils.imageIdToURI(referencedImageId);
|
|
472
|
+
const hasImageURI = vp.hasImageURI(referencedImageURI);
|
|
473
|
+
const currentImageURI = csUtils.imageIdToURI(
|
|
474
|
+
vp.getCurrentImageId()
|
|
475
|
+
);
|
|
476
|
+
return hasImageURI && currentImageURI !== referencedImageURI;
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
if (invalidatedStack) {
|
|
480
|
+
delete data.cachedStats[targetId];
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// If rendering engine has been destroyed while rendering
|
|
488
|
+
if (!viewport.getRenderingEngine()) {
|
|
489
|
+
console.warn('Rendering Engine has been destroyed');
|
|
490
|
+
return renderStatus;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
const handleGroupUID = '0';
|
|
494
|
+
|
|
495
|
+
drawHandlesSvg(
|
|
496
|
+
svgDrawingHelper,
|
|
497
|
+
annotationUID,
|
|
498
|
+
handleGroupUID,
|
|
499
|
+
[canvasCoordinates],
|
|
500
|
+
{ color }
|
|
501
|
+
);
|
|
502
|
+
|
|
503
|
+
renderStatus = true;
|
|
504
|
+
|
|
505
|
+
const isPreScaled = isViewportPreScaled(viewport, targetId);
|
|
506
|
+
|
|
507
|
+
const textLines = this._getTextLines(data, targetId, isPreScaled);
|
|
508
|
+
if (textLines) {
|
|
509
|
+
const textCanvasCoordinates = [
|
|
510
|
+
canvasCoordinates[0] + 6,
|
|
511
|
+
canvasCoordinates[1] - 6,
|
|
512
|
+
];
|
|
513
|
+
|
|
514
|
+
const textUID = '0';
|
|
515
|
+
drawTextBoxSvg(
|
|
516
|
+
svgDrawingHelper,
|
|
517
|
+
annotationUID,
|
|
518
|
+
textUID,
|
|
519
|
+
textLines,
|
|
520
|
+
[textCanvasCoordinates[0], textCanvasCoordinates[1]],
|
|
521
|
+
this.getLinkedTextBoxStyle(styleSpecifier, annotation)
|
|
522
|
+
);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
return renderStatus;
|
|
527
|
+
};
|
|
528
|
+
|
|
529
|
+
_getTextLines(
|
|
530
|
+
data,
|
|
531
|
+
targetId: string,
|
|
532
|
+
isPreScaled: boolean
|
|
533
|
+
): string[] | undefined {
|
|
534
|
+
const cachedVolumeStats = data.cachedStats[targetId];
|
|
535
|
+
const { index, Modality, value, SUVBw, SUVLbm, SUVBsa } = cachedVolumeStats;
|
|
536
|
+
|
|
537
|
+
if (value === undefined && SUVBw === undefined) {
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
const textLines = [];
|
|
542
|
+
const unit = getModalityUnit(Modality, isPreScaled);
|
|
543
|
+
|
|
544
|
+
textLines.push(`(${index[0]}, ${index[1]}, ${index[2]})`);
|
|
545
|
+
|
|
546
|
+
// Check if we have scaling for the other 2 SUV types for the PET.
|
|
547
|
+
if (Modality === 'PT' && isPreScaled === true && SUVBw !== undefined) {
|
|
548
|
+
textLines.push(`${SUVBw.toFixed(2)} SUV bw`);
|
|
549
|
+
if (SUVLbm) {
|
|
550
|
+
textLines.push(`${SUVLbm.toFixed(2)} SUV lbm`);
|
|
551
|
+
}
|
|
552
|
+
if (SUVBsa) {
|
|
553
|
+
textLines.push(`${SUVBsa.toFixed(2)} SUV bsa`);
|
|
554
|
+
}
|
|
555
|
+
} else {
|
|
556
|
+
textLines.push(`${value.toFixed(2)} ${unit}`);
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
return textLines;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
_getValueForModality(value, imageVolume, modality) {
|
|
563
|
+
const values = {};
|
|
564
|
+
|
|
565
|
+
values['value'] = value;
|
|
566
|
+
|
|
567
|
+
// Check if we have scaling for the other 2 SUV types for the PET.
|
|
568
|
+
if (
|
|
569
|
+
modality === 'PT' &&
|
|
570
|
+
imageVolume.scaling.PET &&
|
|
571
|
+
(imageVolume.scaling.PET.suvbwToSuvbsa ||
|
|
572
|
+
imageVolume.scaling.PET.suvbwToSuvlbm)
|
|
573
|
+
) {
|
|
574
|
+
const { suvbwToSuvlbm, suvbwToSuvbsa } = imageVolume.scaling.PET;
|
|
575
|
+
|
|
576
|
+
values['SUVBw'] = value;
|
|
577
|
+
|
|
578
|
+
if (suvbwToSuvlbm) {
|
|
579
|
+
const SUVLbm = value * suvbwToSuvlbm;
|
|
580
|
+
values['SUVLbm'] = SUVLbm;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
if (suvbwToSuvbsa) {
|
|
584
|
+
const SUVBsa = value * suvbwToSuvbsa;
|
|
585
|
+
values['SUVBsa'] = SUVBsa;
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
return values;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
_calculateCachedStats(annotation, renderingEngine, enabledElement) {
|
|
593
|
+
const data = annotation.data;
|
|
594
|
+
const { viewportId, renderingEngineId } = enabledElement;
|
|
595
|
+
|
|
596
|
+
const worldPos = data.handles.points[0];
|
|
597
|
+
const { cachedStats } = data;
|
|
598
|
+
|
|
599
|
+
const targetIds = Object.keys(cachedStats);
|
|
600
|
+
|
|
601
|
+
for (let i = 0; i < targetIds.length; i++) {
|
|
602
|
+
const targetId = targetIds[i];
|
|
603
|
+
|
|
604
|
+
const image = this.getTargetIdImage(targetId, renderingEngine);
|
|
605
|
+
|
|
606
|
+
// If image does not exists for the targetId, skip. This can be due
|
|
607
|
+
// to various reasons such as if the target was a volumeViewport, and
|
|
608
|
+
// the volumeViewport has been decached in the meantime.
|
|
609
|
+
if (!image) {
|
|
610
|
+
continue;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
const { dimensions, imageData, metadata } = image;
|
|
614
|
+
const scalarData =
|
|
615
|
+
'getScalarData' in image ? image.getScalarData() : image.scalarData;
|
|
616
|
+
|
|
617
|
+
const modality = metadata.Modality;
|
|
618
|
+
const index = transformWorldToIndex(imageData, worldPos);
|
|
619
|
+
|
|
620
|
+
index[0] = Math.round(index[0]);
|
|
621
|
+
index[1] = Math.round(index[1]);
|
|
622
|
+
index[2] = Math.round(index[2]);
|
|
623
|
+
|
|
624
|
+
if (csUtils.indexWithinDimensions(index, dimensions)) {
|
|
625
|
+
this.isHandleOutsideImage = false;
|
|
626
|
+
const yMultiple = dimensions[0];
|
|
627
|
+
const zMultiple = dimensions[0] * dimensions[1];
|
|
628
|
+
|
|
629
|
+
const value =
|
|
630
|
+
scalarData[index[2] * zMultiple + index[1] * yMultiple + index[0]];
|
|
631
|
+
|
|
632
|
+
// Index[2] for stackViewport is always 0, but for visualization
|
|
633
|
+
// we reset it to be imageId index
|
|
634
|
+
if (targetId.startsWith('imageId:')) {
|
|
635
|
+
const imageId = targetId.split('imageId:')[1];
|
|
636
|
+
const imageURI = csUtils.imageIdToURI(imageId);
|
|
637
|
+
const viewports = utilities.getViewportsWithImageURI(
|
|
638
|
+
imageURI,
|
|
639
|
+
renderingEngineId
|
|
640
|
+
);
|
|
641
|
+
|
|
642
|
+
const viewport = viewports[0];
|
|
643
|
+
|
|
644
|
+
index[2] = viewport.getCurrentImageIdIndex();
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
const values = this._getValueForModality(value, image, modality);
|
|
648
|
+
|
|
649
|
+
cachedStats[targetId] = {
|
|
650
|
+
index,
|
|
651
|
+
...values,
|
|
652
|
+
Modality: modality,
|
|
653
|
+
};
|
|
654
|
+
} else {
|
|
655
|
+
this.isHandleOutsideImage = true;
|
|
656
|
+
cachedStats[targetId] = {
|
|
657
|
+
index,
|
|
658
|
+
Modality: modality,
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
annotation.invalidated = false;
|
|
663
|
+
|
|
664
|
+
// Dispatching annotation modified
|
|
665
|
+
const eventType = Events.ANNOTATION_MODIFIED;
|
|
666
|
+
|
|
667
|
+
const eventDetail: AnnotationModifiedEventDetail = {
|
|
668
|
+
annotation,
|
|
669
|
+
viewportId,
|
|
670
|
+
renderingEngineId,
|
|
671
|
+
};
|
|
672
|
+
|
|
673
|
+
triggerEvent(eventTarget, eventType, eventDetail);
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
return cachedStats;
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
ProbeTool.toolName = 'Probe';
|
|
681
|
+
export default ProbeTool;
|