@cornerstonejs/tools 0.56.2 → 0.56.4
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/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,82 @@
|
|
|
1
|
+
import type { Types } from '@cornerstonejs/core';
|
|
2
|
+
import * as lineSegment from '../line';
|
|
3
|
+
|
|
4
|
+
type rectLineSegments = {
|
|
5
|
+
top: Types.Point2[];
|
|
6
|
+
right: Types.Point2[];
|
|
7
|
+
bottom: Types.Point2[];
|
|
8
|
+
left: Types.Point2[];
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Given a rectangle left, top, width and height, return an object containing the
|
|
13
|
+
* line segments that make up the rectangle's four sides
|
|
14
|
+
* @param left - The x-coordinate of the left edge of the rectangle.
|
|
15
|
+
* @param top - The y-coordinate of the top edge of the rectangle.
|
|
16
|
+
* @param width - The width of the rectangle.
|
|
17
|
+
* @param height - The height of the rectangle.
|
|
18
|
+
* @returns An object with four keys, each of which contains an array of two
|
|
19
|
+
* points.
|
|
20
|
+
*/
|
|
21
|
+
function rectToLineSegments(
|
|
22
|
+
left: number,
|
|
23
|
+
top: number,
|
|
24
|
+
width: number,
|
|
25
|
+
height: number
|
|
26
|
+
): rectLineSegments {
|
|
27
|
+
const topLineStart: Types.Point2 = [left, top];
|
|
28
|
+
const topLineEnd: Types.Point2 = [left + width, top];
|
|
29
|
+
|
|
30
|
+
const rightLineStart: Types.Point2 = [left + width, top];
|
|
31
|
+
const rightLineEnd: Types.Point2 = [left + width, top + height];
|
|
32
|
+
|
|
33
|
+
const bottomLineStart: Types.Point2 = [left + width, top + height];
|
|
34
|
+
const bottomLineEnd: Types.Point2 = [left, top + height];
|
|
35
|
+
|
|
36
|
+
const leftLineStart: Types.Point2 = [left, top + height];
|
|
37
|
+
const leftLineEnd: Types.Point2 = [left, top];
|
|
38
|
+
|
|
39
|
+
const lineSegments = {
|
|
40
|
+
top: [topLineStart, topLineEnd],
|
|
41
|
+
right: [rightLineStart, rightLineEnd],
|
|
42
|
+
bottom: [bottomLineStart, bottomLineEnd],
|
|
43
|
+
left: [leftLineStart, leftLineEnd],
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
return lineSegments;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Calculates distance of the point to the rectangle. It calculates the minimum
|
|
51
|
+
* distance between the point and each line segment of the rectangle.
|
|
52
|
+
*
|
|
53
|
+
* @param rect - coordinates of the rectangle [left, top, width, height]
|
|
54
|
+
* @param point - [x,y] coordinates of a point
|
|
55
|
+
* @returns
|
|
56
|
+
*/
|
|
57
|
+
export default function distanceToPoint(
|
|
58
|
+
rect: number[],
|
|
59
|
+
point: Types.Point2
|
|
60
|
+
): number {
|
|
61
|
+
if (rect.length !== 4 || point.length !== 2) {
|
|
62
|
+
throw Error(
|
|
63
|
+
'rectangle:[left, top, width, height] or point: [x,y] not defined correctly'
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const [left, top, width, height] = rect;
|
|
68
|
+
|
|
69
|
+
let minDistance = 655535;
|
|
70
|
+
const lineSegments = rectToLineSegments(left, top, width, height);
|
|
71
|
+
|
|
72
|
+
Object.keys(lineSegments).forEach((segment) => {
|
|
73
|
+
const [lineStart, lineEnd] = lineSegments[segment];
|
|
74
|
+
const distance = lineSegment.distanceToPoint(lineStart, lineEnd, point);
|
|
75
|
+
|
|
76
|
+
if (distance < minDistance) {
|
|
77
|
+
minDistance = distance;
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
return minDistance;
|
|
82
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Types } from '@cornerstonejs/core';
|
|
2
|
+
import { vec3 } from 'gl-matrix';
|
|
3
|
+
|
|
4
|
+
type Sphere = {
|
|
5
|
+
center: Types.Point3 | vec3;
|
|
6
|
+
radius: number;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Checks if a point is inside a sphere. Note: this is similar to the
|
|
11
|
+
* `pointInEllipse` function, but since we don't need checks for the
|
|
12
|
+
* ellipse's rotation in different views, we can use a simpler equation
|
|
13
|
+
* which would be faster (no if statements).
|
|
14
|
+
*
|
|
15
|
+
* @param sphere - Sphere object with center and radius
|
|
16
|
+
* @param pointLPS - the point to check in world coordinates
|
|
17
|
+
* @returns boolean
|
|
18
|
+
*/
|
|
19
|
+
export default function pointInSphere(
|
|
20
|
+
sphere: Sphere,
|
|
21
|
+
pointLPS: Types.Point3
|
|
22
|
+
): boolean {
|
|
23
|
+
const { center, radius } = sphere;
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
(pointLPS[0] - center[0]) ** 2 +
|
|
27
|
+
(pointLPS[1] - center[1]) ** 2 +
|
|
28
|
+
(pointLPS[2] - center[2]) ** 2 <=
|
|
29
|
+
radius ** 2
|
|
30
|
+
);
|
|
31
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Types } from '@cornerstonejs/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Find the closest point to the target point
|
|
5
|
+
*
|
|
6
|
+
* @param sourcePoints - The potential source points.
|
|
7
|
+
* @param targetPoint - The target point, used to find the closest source.
|
|
8
|
+
* @returns The closest point in the array of point sources
|
|
9
|
+
*/
|
|
10
|
+
export default function findClosestPoint(
|
|
11
|
+
sourcePoints: Array<Types.Point2>,
|
|
12
|
+
targetPoint: Types.Point2
|
|
13
|
+
): Types.Point2 {
|
|
14
|
+
let minPoint = [0, 0];
|
|
15
|
+
let minDistance = Number.MAX_SAFE_INTEGER;
|
|
16
|
+
|
|
17
|
+
sourcePoints.forEach(function (sourcePoint) {
|
|
18
|
+
const distance = _distanceBetween(targetPoint, sourcePoint);
|
|
19
|
+
|
|
20
|
+
if (distance < minDistance) {
|
|
21
|
+
minDistance = distance;
|
|
22
|
+
minPoint = [...sourcePoint];
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
return minPoint as Types.Point2;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
*
|
|
31
|
+
* @private
|
|
32
|
+
* @param p1
|
|
33
|
+
* @param p2
|
|
34
|
+
*/
|
|
35
|
+
function _distanceBetween(p1: Types.Point2, p2: Types.Point2): number {
|
|
36
|
+
const [x1, y1] = p1;
|
|
37
|
+
const [x2, y2] = p2;
|
|
38
|
+
|
|
39
|
+
return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
|
|
40
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// Pulled from source: https://github.com/w8r/liang-barsky
|
|
2
|
+
// MIT Licensed.
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Fast, destructive implementation of Liang-Barsky line clipping algorithm.
|
|
6
|
+
* It clips a 2D segment by a rectangle.
|
|
7
|
+
* @author Alexander Milevski <info@w8r.name>
|
|
8
|
+
* @license MIT
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const EPSILON = 1e-6;
|
|
12
|
+
const INSIDE = 1;
|
|
13
|
+
const OUTSIDE = 0;
|
|
14
|
+
|
|
15
|
+
function clipT(num, denom, c) {
|
|
16
|
+
const [tE, tL] = c;
|
|
17
|
+
if (Math.abs(denom) < EPSILON) return num < 0;
|
|
18
|
+
const t = num / denom;
|
|
19
|
+
|
|
20
|
+
if (denom > 0) {
|
|
21
|
+
if (t > tL) return 0;
|
|
22
|
+
if (t > tE) c[0] = t;
|
|
23
|
+
} else {
|
|
24
|
+
if (t < tE) return 0;
|
|
25
|
+
if (t < tL) c[1] = t;
|
|
26
|
+
}
|
|
27
|
+
return 1;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @param {Point} a
|
|
32
|
+
* @param {Point} b
|
|
33
|
+
* @param {BoundingBox} box [xmin, ymin, xmax, ymax]
|
|
34
|
+
* @param {Point?} [da]
|
|
35
|
+
* @param {Point?} [db]
|
|
36
|
+
* @return {number}
|
|
37
|
+
*/
|
|
38
|
+
export default function clip(a, b, box, da?, db?) {
|
|
39
|
+
const [x1, y1] = a;
|
|
40
|
+
const [x2, y2] = b;
|
|
41
|
+
const dx = x2 - x1;
|
|
42
|
+
const dy = y2 - y1;
|
|
43
|
+
|
|
44
|
+
if (da === undefined || db === undefined) {
|
|
45
|
+
da = a;
|
|
46
|
+
db = b;
|
|
47
|
+
} else {
|
|
48
|
+
da[0] = a[0];
|
|
49
|
+
da[1] = a[1];
|
|
50
|
+
db[0] = b[0];
|
|
51
|
+
db[1] = b[1];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (
|
|
55
|
+
Math.abs(dx) < EPSILON &&
|
|
56
|
+
Math.abs(dy) < EPSILON &&
|
|
57
|
+
x1 >= box[0] &&
|
|
58
|
+
x1 <= box[2] &&
|
|
59
|
+
y1 >= box[1] &&
|
|
60
|
+
y1 <= box[3]
|
|
61
|
+
) {
|
|
62
|
+
return INSIDE;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const c = [0, 1];
|
|
66
|
+
if (
|
|
67
|
+
clipT(box[0] - x1, dx, c) &&
|
|
68
|
+
clipT(x1 - box[2], -dx, c) &&
|
|
69
|
+
clipT(box[1] - y1, dy, c) &&
|
|
70
|
+
clipT(y1 - box[3], -dy, c)
|
|
71
|
+
) {
|
|
72
|
+
const [tE, tL] = c;
|
|
73
|
+
if (tL < 1) {
|
|
74
|
+
db[0] = x1 + tL * dx;
|
|
75
|
+
db[1] = y1 + tL * dy;
|
|
76
|
+
}
|
|
77
|
+
if (tE > 0) {
|
|
78
|
+
da[0] += tE * dx;
|
|
79
|
+
da[1] += tE * dy;
|
|
80
|
+
}
|
|
81
|
+
return INSIDE;
|
|
82
|
+
}
|
|
83
|
+
return OUTSIDE;
|
|
84
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Types } from '@cornerstonejs/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Returns the orientation of the vector in the patient coordinate system.
|
|
5
|
+
* @public
|
|
6
|
+
*
|
|
7
|
+
* @param vector - Input array
|
|
8
|
+
* @returns The orientation in the patient coordinate system.
|
|
9
|
+
*/
|
|
10
|
+
export default function getOrientationStringLPS(vector: Types.Point3): string {
|
|
11
|
+
// Thanks to David Clunie
|
|
12
|
+
// https://sites.google.com/site/dicomnotes/
|
|
13
|
+
|
|
14
|
+
let orientation = '';
|
|
15
|
+
const orientationX = vector[0] < 0 ? 'R' : 'L';
|
|
16
|
+
const orientationY = vector[1] < 0 ? 'A' : 'P';
|
|
17
|
+
const orientationZ = vector[2] < 0 ? 'F' : 'H';
|
|
18
|
+
|
|
19
|
+
// Should probably make this a function vector3.abs
|
|
20
|
+
const abs = [Math.abs(vector[0]), Math.abs(vector[1]), Math.abs(vector[2])];
|
|
21
|
+
|
|
22
|
+
const MIN = 0.0001;
|
|
23
|
+
|
|
24
|
+
for (let i = 0; i < 3; i++) {
|
|
25
|
+
if (abs[0] > MIN && abs[0] > abs[1] && abs[0] > abs[2]) {
|
|
26
|
+
orientation += orientationX;
|
|
27
|
+
abs[0] = 0;
|
|
28
|
+
} else if (abs[1] > MIN && abs[1] > abs[0] && abs[1] > abs[2]) {
|
|
29
|
+
orientation += orientationY;
|
|
30
|
+
abs[1] = 0;
|
|
31
|
+
} else if (abs[2] > MIN && abs[2] > abs[0] && abs[2] > abs[1]) {
|
|
32
|
+
orientation += orientationZ;
|
|
33
|
+
abs[2] = 0;
|
|
34
|
+
} else if (abs[0] > MIN && abs[1] > MIN && abs[0] === abs[1]) {
|
|
35
|
+
orientation += orientationX + orientationY;
|
|
36
|
+
abs[0] = 0;
|
|
37
|
+
abs[1] = 0;
|
|
38
|
+
} else if (abs[0] > MIN && abs[2] > MIN && abs[0] === abs[2]) {
|
|
39
|
+
orientation += orientationX + orientationZ;
|
|
40
|
+
abs[0] = 0;
|
|
41
|
+
abs[2] = 0;
|
|
42
|
+
} else if (abs[1] > MIN && abs[2] > MIN && abs[1] === abs[2]) {
|
|
43
|
+
orientation += orientationY + orientationZ;
|
|
44
|
+
abs[1] = 0;
|
|
45
|
+
abs[2] = 0;
|
|
46
|
+
} else {
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return orientation;
|
|
52
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inverts an orientation string.
|
|
3
|
+
* @public
|
|
4
|
+
*
|
|
5
|
+
* @param orientationString - The orientation.
|
|
6
|
+
* @returns The inverted orientationString.
|
|
7
|
+
*/
|
|
8
|
+
export default function invertOrientationStringLPS(
|
|
9
|
+
orientationString: string
|
|
10
|
+
): string {
|
|
11
|
+
let inverted = orientationString.replace('H', 'f');
|
|
12
|
+
|
|
13
|
+
inverted = inverted.replace('F', 'h');
|
|
14
|
+
inverted = inverted.replace('R', 'l');
|
|
15
|
+
inverted = inverted.replace('L', 'r');
|
|
16
|
+
inverted = inverted.replace('A', 'p');
|
|
17
|
+
inverted = inverted.replace('P', 'a');
|
|
18
|
+
inverted = inverted.toUpperCase();
|
|
19
|
+
|
|
20
|
+
return inverted;
|
|
21
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import {
|
|
2
|
+
StackViewport,
|
|
3
|
+
VolumeViewport,
|
|
4
|
+
Types,
|
|
5
|
+
utilities as csUtils,
|
|
6
|
+
} from '@cornerstonejs/core';
|
|
7
|
+
|
|
8
|
+
import filterAnnotationsWithinSlice from './filterAnnotationsWithinSlice';
|
|
9
|
+
import { Annotations } from '../../types';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Given the viewport and the annotations, it filters the annotations array and only
|
|
13
|
+
* return those annotation that should be displayed on the viewport
|
|
14
|
+
* @param annotations - Annotations
|
|
15
|
+
* @returns A filtered version of the annotations.
|
|
16
|
+
*/
|
|
17
|
+
export default function filterAnnotationsForDisplay(
|
|
18
|
+
viewport: Types.IViewport,
|
|
19
|
+
annotations: Annotations
|
|
20
|
+
): Annotations {
|
|
21
|
+
if (viewport instanceof StackViewport) {
|
|
22
|
+
// 1. Get the currently displayed imageId from the StackViewport
|
|
23
|
+
const imageId = viewport.getCurrentImageId();
|
|
24
|
+
|
|
25
|
+
// 2. remove the dataLoader scheme since it might be an annotation that was
|
|
26
|
+
// created on the volumeViewport initially and has the volumeLoader scheme
|
|
27
|
+
// but shares the same imageId
|
|
28
|
+
const colonIndex = imageId.indexOf(':');
|
|
29
|
+
const imageURI = imageId.substring(colonIndex + 1);
|
|
30
|
+
|
|
31
|
+
// 3. Filter annotation in the frame of reference by the referenced image ID property
|
|
32
|
+
// Note: With the current implementation drawing on the stack (PT stack) will not
|
|
33
|
+
// show the annotation on a volume that does not share the same imageURIs (CT Volume),
|
|
34
|
+
// and we don't have a proper way to check distance either since a stack can be
|
|
35
|
+
// composed of multiple unrelated images
|
|
36
|
+
return annotations.filter((annotation) => {
|
|
37
|
+
if (!annotation.isVisible) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const imageId = annotation.metadata.referencedImageId;
|
|
42
|
+
|
|
43
|
+
if (imageId === undefined) {
|
|
44
|
+
// This annotation was not drawn on a non-coplanar reformat, and such does
|
|
45
|
+
// note have a referenced imageId.
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const colonIndex = imageId.indexOf(':');
|
|
50
|
+
const referenceImageURI = imageId.substring(colonIndex + 1);
|
|
51
|
+
return referenceImageURI === imageURI;
|
|
52
|
+
});
|
|
53
|
+
} else if (viewport instanceof VolumeViewport) {
|
|
54
|
+
const camera = viewport.getCamera();
|
|
55
|
+
|
|
56
|
+
const { spacingInNormalDirection } =
|
|
57
|
+
csUtils.getTargetVolumeAndSpacingInNormalDir(viewport, camera);
|
|
58
|
+
|
|
59
|
+
// Get data with same normal and within the same slice
|
|
60
|
+
return filterAnnotationsWithinSlice(
|
|
61
|
+
annotations,
|
|
62
|
+
camera,
|
|
63
|
+
spacingInNormalDirection
|
|
64
|
+
);
|
|
65
|
+
} else {
|
|
66
|
+
throw new Error(`Viewport Type ${viewport.type} not supported`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { vec3 } from 'gl-matrix';
|
|
2
|
+
import { CONSTANTS } from '@cornerstonejs/core';
|
|
3
|
+
import type { Types } from '@cornerstonejs/core';
|
|
4
|
+
import { Annotations, Annotation } from '../../types';
|
|
5
|
+
|
|
6
|
+
const { EPSILON } = CONSTANTS;
|
|
7
|
+
|
|
8
|
+
const PARALLEL_THRESHOLD = 1 - EPSILON;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* given some `Annotations`, and the slice defined by the camera's normal
|
|
12
|
+
* direction and the spacing in the normal, filter the `Annotations` which
|
|
13
|
+
* is within the slice.
|
|
14
|
+
*
|
|
15
|
+
* @param annotations - Annotations
|
|
16
|
+
* @param camera - The camera
|
|
17
|
+
* @param spacingInNormalDirection - The spacing in the normal direction
|
|
18
|
+
* @returns The filtered `Annotations`.
|
|
19
|
+
*/
|
|
20
|
+
export default function filterAnnotationsWithinSlice(
|
|
21
|
+
annotations: Annotations,
|
|
22
|
+
camera: Types.ICamera,
|
|
23
|
+
spacingInNormalDirection: number
|
|
24
|
+
): Annotations {
|
|
25
|
+
const { viewPlaneNormal } = camera;
|
|
26
|
+
|
|
27
|
+
// The reason we use parallel normals instead of actual orientation is that
|
|
28
|
+
// flipped action is done through camera API, so we can't rely on the
|
|
29
|
+
// orientation (viewplaneNormal and viewUp) since even the same image and
|
|
30
|
+
// same slice if flipped will have different orientation, but still rendering
|
|
31
|
+
// the same slice. Instead, we choose to use the parallel normals to filter
|
|
32
|
+
// the annotations and later we fine tune it with the annotation within slice
|
|
33
|
+
// logic down below.
|
|
34
|
+
const annotationsWithParallelNormals = annotations.filter(
|
|
35
|
+
(td: Annotation) => {
|
|
36
|
+
const annotationViewPlaneNormal = td.metadata.viewPlaneNormal;
|
|
37
|
+
|
|
38
|
+
const isParallel =
|
|
39
|
+
Math.abs(vec3.dot(viewPlaneNormal, annotationViewPlaneNormal)) >
|
|
40
|
+
PARALLEL_THRESHOLD;
|
|
41
|
+
|
|
42
|
+
return annotationViewPlaneNormal && isParallel;
|
|
43
|
+
}
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
// No in plane annotations.
|
|
47
|
+
if (!annotationsWithParallelNormals.length) {
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Annotation should be within the slice, which means that it should be between
|
|
52
|
+
// camera's focalPoint +/- spacingInNormalDirection.
|
|
53
|
+
|
|
54
|
+
const halfSpacingInNormalDirection = spacingInNormalDirection / 2;
|
|
55
|
+
const { focalPoint } = camera;
|
|
56
|
+
|
|
57
|
+
const annotationsWithinSlice = [];
|
|
58
|
+
|
|
59
|
+
for (const annotation of annotationsWithParallelNormals) {
|
|
60
|
+
const data = annotation.data;
|
|
61
|
+
const point = data.handles.points[0];
|
|
62
|
+
|
|
63
|
+
if (!annotation.isVisible) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
// A = point
|
|
67
|
+
// B = focal point
|
|
68
|
+
// P = normal
|
|
69
|
+
|
|
70
|
+
// B-A dot P => Distance in the view direction.
|
|
71
|
+
// this should be less than half the slice distance.
|
|
72
|
+
|
|
73
|
+
const dir = vec3.create();
|
|
74
|
+
|
|
75
|
+
vec3.sub(dir, focalPoint, point);
|
|
76
|
+
|
|
77
|
+
const dot = vec3.dot(dir, viewPlaneNormal);
|
|
78
|
+
|
|
79
|
+
if (Math.abs(dot) < halfSpacingInNormalDirection) {
|
|
80
|
+
annotationsWithinSlice.push(annotation);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return annotationsWithinSlice;
|
|
85
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import vtkMath from '@kitware/vtk.js/Common/Core/Math';
|
|
2
|
+
import { utilities as csUtils } from '@cornerstonejs/core';
|
|
3
|
+
import type { Types } from '@cornerstonejs/core';
|
|
4
|
+
/**
|
|
5
|
+
* Returns a point based on some criteria (e.g., minimum or maximum intensity) in
|
|
6
|
+
* the line of sight (on the line between the passed worldPosition and camera position).
|
|
7
|
+
* It iterated over the points with a step size on the line.
|
|
8
|
+
*
|
|
9
|
+
* @param viewport - Volume viewport
|
|
10
|
+
* @param worldPos - World coordinates of the clicked location
|
|
11
|
+
* @param targetVolumeId - target Volume ID in the viewport
|
|
12
|
+
* @param criteriaFunction - A function that returns the point if it passes a certain
|
|
13
|
+
* written logic, for instance, it can be a maxValue function that keeps the
|
|
14
|
+
* records of all intensity values, and only return the point if its intensity
|
|
15
|
+
* is greater than the maximum intensity of the points passed before.
|
|
16
|
+
* @param stepsSize - Percentage of the spacing in the normal direction, default value
|
|
17
|
+
* is 0.25 which means steps = 1/4 of the spacing in the normal direction.
|
|
18
|
+
* @returns the World pos of the point that passes the criteriaFunction
|
|
19
|
+
*/
|
|
20
|
+
export default function getPointInLineOfSightWithCriteria(
|
|
21
|
+
viewport: Types.IVolumeViewport,
|
|
22
|
+
worldPos: Types.Point3,
|
|
23
|
+
targetVolumeId: string,
|
|
24
|
+
criteriaFunction: (intensity: number, point: Types.Point3) => Types.Point3,
|
|
25
|
+
stepSize = 0.25
|
|
26
|
+
): Types.Point3 {
|
|
27
|
+
// 1. Getting the camera from the event details
|
|
28
|
+
const camera = viewport.getCamera();
|
|
29
|
+
const { position: cameraPosition } = camera;
|
|
30
|
+
|
|
31
|
+
// 2. Calculating the spacing in the normal direction, this will get
|
|
32
|
+
// used as the step size for iterating over the points in the line of sight
|
|
33
|
+
const { spacingInNormalDirection } =
|
|
34
|
+
csUtils.getTargetVolumeAndSpacingInNormalDir(
|
|
35
|
+
viewport,
|
|
36
|
+
camera,
|
|
37
|
+
targetVolumeId
|
|
38
|
+
);
|
|
39
|
+
// 2.1 Making sure, we are not missing any point
|
|
40
|
+
const step = spacingInNormalDirection * stepSize;
|
|
41
|
+
|
|
42
|
+
// 3. Getting the bounds of the viewports. Search for brightest point is
|
|
43
|
+
// limited to the visible bound
|
|
44
|
+
// Todo: this might be a problem since bounds will change to spatial bounds.
|
|
45
|
+
const bounds = viewport.getBounds();
|
|
46
|
+
const xMin = bounds[0];
|
|
47
|
+
const xMax = bounds[1];
|
|
48
|
+
|
|
49
|
+
// 5. Calculating the line, we use a parametric line definition
|
|
50
|
+
const vector = <Types.Point3>[0, 0, 0];
|
|
51
|
+
|
|
52
|
+
// 5.1 Point coordinate on the line
|
|
53
|
+
let point = <Types.Point3>[0, 0, 0];
|
|
54
|
+
|
|
55
|
+
// 5.2 Calculating the line direction, and storing in vector
|
|
56
|
+
vtkMath.subtract(worldPos, cameraPosition, vector);
|
|
57
|
+
|
|
58
|
+
let pickedPoint;
|
|
59
|
+
|
|
60
|
+
// 6. Iterating over the line from the lower bound to the upper bound, with the
|
|
61
|
+
// specified step size
|
|
62
|
+
for (let pointT = xMin; pointT <= xMax; pointT = pointT + step) {
|
|
63
|
+
// 6.1 Calculating the point x location
|
|
64
|
+
point = [pointT, 0, 0];
|
|
65
|
+
// 6.2 Calculating the point y,z location based on the line equation
|
|
66
|
+
const t = (pointT - cameraPosition[0]) / vector[0];
|
|
67
|
+
point[1] = t * vector[1] + cameraPosition[1];
|
|
68
|
+
point[2] = t * vector[2] + cameraPosition[2];
|
|
69
|
+
|
|
70
|
+
// 6.3 Checking if the points is inside the bounds
|
|
71
|
+
if (_inBounds(point, bounds)) {
|
|
72
|
+
// 6.4 Getting the intensity of the point
|
|
73
|
+
const intensity = viewport.getIntensityFromWorld(point);
|
|
74
|
+
// 6.5 Passing the intensity to the maximum value functions which decides
|
|
75
|
+
// whether the current point is of interest based on some criteria
|
|
76
|
+
const pointToPick = criteriaFunction(intensity, point);
|
|
77
|
+
if (pointToPick) {
|
|
78
|
+
pickedPoint = pointToPick;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return pickedPoint;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Returns whether the point in the world is inside the bounds of the viewport
|
|
88
|
+
* @param point - coordinates in the world
|
|
89
|
+
* @returns boolean
|
|
90
|
+
*/
|
|
91
|
+
const _inBounds = function (
|
|
92
|
+
point: Types.Point3,
|
|
93
|
+
bounds: Array<number>
|
|
94
|
+
): boolean {
|
|
95
|
+
const [xMin, xMax, yMin, yMax, zMin, zMax] = bounds;
|
|
96
|
+
return (
|
|
97
|
+
point[0] > xMin &&
|
|
98
|
+
point[0] < xMax &&
|
|
99
|
+
point[1] > yMin &&
|
|
100
|
+
point[1] < yMax &&
|
|
101
|
+
point[2] > zMin &&
|
|
102
|
+
point[2] < zMax
|
|
103
|
+
);
|
|
104
|
+
};
|
|
@@ -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
|
|
6
|
+
* by a `viewPlaneNormal` and a `viewUp`, get the width and height in world coordinates
|
|
7
|
+
* of the rectangle 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 topLeftWorld - The first world position.
|
|
14
|
+
* @param bottomRightWorld - The second world position.
|
|
15
|
+
*
|
|
16
|
+
* @returns The `worldWidth` and `worldHeight`.
|
|
17
|
+
*/
|
|
18
|
+
export default function getWorldWidthAndHeightFromCorners(
|
|
19
|
+
viewPlaneNormal: Types.Point3,
|
|
20
|
+
viewUp: Types.Point3,
|
|
21
|
+
topLeftWorld: Types.Point3,
|
|
22
|
+
bottomRightWorld: 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(...topLeftWorld);
|
|
29
|
+
const pos2 = vec3.fromValues(...bottomRightWorld);
|
|
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
|
+
}
|