@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.
Files changed (360) hide show
  1. package/dist/cjs/tools/CrosshairsTool.d.ts +1 -0
  2. package/dist/cjs/tools/CrosshairsTool.js +4 -1
  3. package/dist/cjs/tools/CrosshairsTool.js.map +1 -1
  4. package/dist/esm/tools/CrosshairsTool.d.ts +1 -0
  5. package/dist/esm/tools/CrosshairsTool.js +4 -1
  6. package/dist/esm/tools/CrosshairsTool.js.map +1 -1
  7. package/dist/umd/index.js +1 -1
  8. package/dist/umd/index.js.map +1 -1
  9. package/package.json +5 -4
  10. package/src/constants/COLOR_LUT.ts +262 -0
  11. package/src/constants/index.ts +3 -0
  12. package/src/cursors/ImageMouseCursor.ts +39 -0
  13. package/src/cursors/MouseCursor.ts +114 -0
  14. package/src/cursors/SVGCursorDescriptor.ts +462 -0
  15. package/src/cursors/SVGMouseCursor.ts +145 -0
  16. package/src/cursors/elementCursor.ts +69 -0
  17. package/src/cursors/index.ts +24 -0
  18. package/src/cursors/setCursorForElement.ts +33 -0
  19. package/src/drawingSvg/_getHash.ts +9 -0
  20. package/src/drawingSvg/_setAttributesIfNecessary.ts +13 -0
  21. package/src/drawingSvg/_setNewAttributesIfValid.ts +10 -0
  22. package/src/drawingSvg/clearByToolType.ts +26 -0
  23. package/src/drawingSvg/draw.ts +16 -0
  24. package/src/drawingSvg/drawArrow.ts +82 -0
  25. package/src/drawingSvg/drawCircle.ts +62 -0
  26. package/src/drawingSvg/drawEllipse.ts +71 -0
  27. package/src/drawingSvg/drawHandles.ts +87 -0
  28. package/src/drawingSvg/drawLine.ts +70 -0
  29. package/src/drawingSvg/drawLink.ts +76 -0
  30. package/src/drawingSvg/drawLinkedTextBox.ts +64 -0
  31. package/src/drawingSvg/drawPolyline.ts +80 -0
  32. package/src/drawingSvg/drawRect.ts +70 -0
  33. package/src/drawingSvg/drawTextBox.ts +213 -0
  34. package/src/drawingSvg/getSvgDrawingHelper.ts +98 -0
  35. package/src/drawingSvg/index.ts +23 -0
  36. package/src/enums/AnnotationStyleStates.ts +22 -0
  37. package/src/enums/Events.ts +242 -0
  38. package/src/enums/SegmentationRepresentations.ts +12 -0
  39. package/src/enums/ToolBindings.ts +37 -0
  40. package/src/enums/ToolModes.ts +31 -0
  41. package/src/enums/Touch.ts +8 -0
  42. package/src/enums/index.js +16 -0
  43. package/src/eventDispatchers/annotationModifiedEventDispatcher.ts +41 -0
  44. package/src/eventDispatchers/cameraModifiedEventDispatcher.ts +41 -0
  45. package/src/eventDispatchers/imageRenderedEventDispatcher.ts +37 -0
  46. package/src/eventDispatchers/imageSpacingCalibratedEventDispatcher.ts +50 -0
  47. package/src/eventDispatchers/index.js +15 -0
  48. package/src/eventDispatchers/keyboardEventHandlers/index.js +4 -0
  49. package/src/eventDispatchers/keyboardEventHandlers/keyDown.ts +29 -0
  50. package/src/eventDispatchers/keyboardEventHandlers/keyUp.ts +33 -0
  51. package/src/eventDispatchers/keyboardToolEventDispatcher.ts +28 -0
  52. package/src/eventDispatchers/mouseEventHandlers/index.js +19 -0
  53. package/src/eventDispatchers/mouseEventHandlers/mouseClick.ts +13 -0
  54. package/src/eventDispatchers/mouseEventHandlers/mouseDoubleClick.ts +13 -0
  55. package/src/eventDispatchers/mouseEventHandlers/mouseDown.ts +196 -0
  56. package/src/eventDispatchers/mouseEventHandlers/mouseDownActivate.ts +35 -0
  57. package/src/eventDispatchers/mouseEventHandlers/mouseDrag.ts +25 -0
  58. package/src/eventDispatchers/mouseEventHandlers/mouseMove.ts +70 -0
  59. package/src/eventDispatchers/mouseEventHandlers/mouseUp.ts +9 -0
  60. package/src/eventDispatchers/mouseEventHandlers/mouseWheel.ts +13 -0
  61. package/src/eventDispatchers/mouseToolEventDispatcher.ts +64 -0
  62. package/src/eventDispatchers/shared/customCallbackHandler.ts +73 -0
  63. package/src/eventDispatchers/shared/getActiveToolForKeyboardEvent.ts +58 -0
  64. package/src/eventDispatchers/shared/getActiveToolForMouseEvent.ts +61 -0
  65. package/src/eventDispatchers/shared/getActiveToolForTouchEvent.ts +64 -0
  66. package/src/eventDispatchers/shared/getMouseModifier.ts +30 -0
  67. package/src/eventDispatchers/shared/getToolsWithModesForMouseEvent.ts +56 -0
  68. package/src/eventDispatchers/shared/getToolsWithModesForTouchEvent.ts +54 -0
  69. package/src/eventDispatchers/touchEventHandlers/index.js +15 -0
  70. package/src/eventDispatchers/touchEventHandlers/touchDrag.ts +23 -0
  71. package/src/eventDispatchers/touchEventHandlers/touchEnd.ts +9 -0
  72. package/src/eventDispatchers/touchEventHandlers/touchPress.ts +13 -0
  73. package/src/eventDispatchers/touchEventHandlers/touchStart.ts +174 -0
  74. package/src/eventDispatchers/touchEventHandlers/touchStartActivate.ts +36 -0
  75. package/src/eventDispatchers/touchEventHandlers/touchTap.ts +9 -0
  76. package/src/eventDispatchers/touchToolEventDispatcher.ts +51 -0
  77. package/src/eventListeners/annotations/annotationModifiedListener.ts +22 -0
  78. package/src/eventListeners/annotations/annotationSelectionListener.ts +29 -0
  79. package/src/eventListeners/annotations/index.ts +4 -0
  80. package/src/eventListeners/index.ts +28 -0
  81. package/src/eventListeners/keyboard/index.ts +16 -0
  82. package/src/eventListeners/keyboard/keyDownListener.ts +99 -0
  83. package/src/eventListeners/mouse/getMouseEventPoints.ts +66 -0
  84. package/src/eventListeners/mouse/index.ts +55 -0
  85. package/src/eventListeners/mouse/mouseDoubleClickListener.ts +55 -0
  86. package/src/eventListeners/mouse/mouseDownListener.ts +519 -0
  87. package/src/eventListeners/mouse/mouseMoveListener.ts +33 -0
  88. package/src/eventListeners/segmentation/index.ts +11 -0
  89. package/src/eventListeners/segmentation/segmentationDataModifiedEventListener.ts +61 -0
  90. package/src/eventListeners/segmentation/segmentationModifiedEventListener.ts +32 -0
  91. package/src/eventListeners/segmentation/segmentationRepresentationModifiedEventListener.ts +15 -0
  92. package/src/eventListeners/segmentation/segmentationRepresentationRemovedEventListener.ts +16 -0
  93. package/src/eventListeners/touch/getTouchEventPoints.ts +75 -0
  94. package/src/eventListeners/touch/index.ts +37 -0
  95. package/src/eventListeners/touch/preventGhostClick.js +72 -0
  96. package/src/eventListeners/touch/touchStartListener.ts +499 -0
  97. package/src/eventListeners/wheel/index.ts +27 -0
  98. package/src/eventListeners/wheel/normalizeWheel.ts +69 -0
  99. package/src/eventListeners/wheel/wheelListener.ts +51 -0
  100. package/src/index.ts +133 -0
  101. package/src/init.ts +187 -0
  102. package/src/stateManagement/annotation/FrameOfReferenceSpecificAnnotationManager.ts +399 -0
  103. package/src/stateManagement/annotation/annotationLocking.ts +178 -0
  104. package/src/stateManagement/annotation/annotationSelection.ts +163 -0
  105. package/src/stateManagement/annotation/annotationState.ts +180 -0
  106. package/src/stateManagement/annotation/annotationVisibility.ts +156 -0
  107. package/src/stateManagement/annotation/config/ToolStyle.ts +265 -0
  108. package/src/stateManagement/annotation/config/getFont.ts +36 -0
  109. package/src/stateManagement/annotation/config/getState.ts +26 -0
  110. package/src/stateManagement/annotation/config/helpers.ts +55 -0
  111. package/src/stateManagement/annotation/config/index.ts +5 -0
  112. package/src/stateManagement/annotation/helpers/state.ts +83 -0
  113. package/src/stateManagement/annotation/index.ts +15 -0
  114. package/src/stateManagement/index.js +40 -0
  115. package/src/stateManagement/segmentation/SegmentationStateManager.ts +491 -0
  116. package/src/stateManagement/segmentation/activeSegmentation.ts +60 -0
  117. package/src/stateManagement/segmentation/addSegmentationRepresentations.ts +77 -0
  118. package/src/stateManagement/segmentation/addSegmentations.ts +27 -0
  119. package/src/stateManagement/segmentation/config/index.ts +29 -0
  120. package/src/stateManagement/segmentation/config/segmentationColor.ts +132 -0
  121. package/src/stateManagement/segmentation/config/segmentationConfig.ts +195 -0
  122. package/src/stateManagement/segmentation/config/segmentationVisibility.ts +171 -0
  123. package/src/stateManagement/segmentation/helpers/index.ts +3 -0
  124. package/src/stateManagement/segmentation/helpers/normalizeSegmentationInput.ts +35 -0
  125. package/src/stateManagement/segmentation/helpers/validateSegmentationInput.ts +41 -0
  126. package/src/stateManagement/segmentation/index.ts +22 -0
  127. package/src/stateManagement/segmentation/removeSegmentationsFromToolGroup.ts +85 -0
  128. package/src/stateManagement/segmentation/segmentIndex.ts +38 -0
  129. package/src/stateManagement/segmentation/segmentLocking.ts +72 -0
  130. package/src/stateManagement/segmentation/segmentationState.ts +429 -0
  131. package/src/stateManagement/segmentation/triggerSegmentationEvents.ts +157 -0
  132. package/src/store/SynchronizerManager/Synchronizer.ts +344 -0
  133. package/src/store/SynchronizerManager/createSynchronizer.ts +41 -0
  134. package/src/store/SynchronizerManager/destroy.ts +14 -0
  135. package/src/store/SynchronizerManager/destroySynchronizer.ts +25 -0
  136. package/src/store/SynchronizerManager/getAllSynchronizers.ts +12 -0
  137. package/src/store/SynchronizerManager/getSynchronizer.ts +13 -0
  138. package/src/store/SynchronizerManager/getSynchronizersForViewport.ts +44 -0
  139. package/src/store/SynchronizerManager/index.js +15 -0
  140. package/src/store/ToolGroupManager/ToolGroup.ts +679 -0
  141. package/src/store/ToolGroupManager/createToolGroup.ts +33 -0
  142. package/src/store/ToolGroupManager/destroy.ts +24 -0
  143. package/src/store/ToolGroupManager/destroyToolGroup.ts +26 -0
  144. package/src/store/ToolGroupManager/getAllToolGroups.ts +12 -0
  145. package/src/store/ToolGroupManager/getToolGroup.ts +14 -0
  146. package/src/store/ToolGroupManager/getToolGroupForViewport.ts +44 -0
  147. package/src/store/ToolGroupManager/getToolGroupsWithToolName.ts +33 -0
  148. package/src/store/ToolGroupManager/index.ts +17 -0
  149. package/src/store/addEnabledElement.ts +137 -0
  150. package/src/store/addTool.ts +56 -0
  151. package/src/store/cancelActiveManipulations.ts +30 -0
  152. package/src/store/filterMoveableAnnotationTools.ts +61 -0
  153. package/src/store/filterToolsWithAnnotationsForElement.ts +51 -0
  154. package/src/store/filterToolsWithMoveableHandles.ts +51 -0
  155. package/src/store/index.ts +29 -0
  156. package/src/store/removeEnabledElement.ts +132 -0
  157. package/src/store/state.ts +57 -0
  158. package/src/store/svgNodeCache.ts +7 -0
  159. package/src/synchronizers/callbacks/areViewportsCoplanar .ts +12 -0
  160. package/src/synchronizers/callbacks/cameraSyncCallback.ts +33 -0
  161. package/src/synchronizers/callbacks/stackImageSyncCallback.ts +157 -0
  162. package/src/synchronizers/callbacks/voiSyncCallback.ts +51 -0
  163. package/src/synchronizers/callbacks/zoomPanSyncCallback.ts +43 -0
  164. package/src/synchronizers/index.ts +11 -0
  165. package/src/synchronizers/synchronizers/createCameraPositionSynchronizer.ts +25 -0
  166. package/src/synchronizers/synchronizers/createStackImageSynchronizer.ts +25 -0
  167. package/src/synchronizers/synchronizers/createVOISynchronizer.ts +24 -0
  168. package/src/synchronizers/synchronizers/createZoomPanSynchronizer.ts +25 -0
  169. package/src/synchronizers/synchronizers/index.ts +11 -0
  170. package/src/tools/CrosshairsTool.ts +2693 -0
  171. package/src/tools/MIPJumpToClickTool.ts +99 -0
  172. package/src/tools/MagnifyTool.ts +319 -0
  173. package/src/tools/PanTool.ts +58 -0
  174. package/src/tools/PlanarRotateTool.ts +77 -0
  175. package/src/tools/ReferenceCursors.ts +466 -0
  176. package/src/tools/ReferenceLinesTool.ts +279 -0
  177. package/src/tools/ScaleOverlayTool.ts +685 -0
  178. package/src/tools/StackScrollTool.ts +97 -0
  179. package/src/tools/StackScrollToolMouseWheelTool.ts +58 -0
  180. package/src/tools/TrackballRotateTool.ts +141 -0
  181. package/src/tools/VolumeRotateMouseWheelTool.ts +86 -0
  182. package/src/tools/WindowLevelTool.ts +260 -0
  183. package/src/tools/ZoomTool.ts +293 -0
  184. package/src/tools/annotation/AngleTool.ts +835 -0
  185. package/src/tools/annotation/ArrowAnnotateTool.ts +820 -0
  186. package/src/tools/annotation/BidirectionalTool.ts +1350 -0
  187. package/src/tools/annotation/CircleROITool.ts +1070 -0
  188. package/src/tools/annotation/CobbAngleTool.ts +815 -0
  189. package/src/tools/annotation/DragProbeTool.ts +213 -0
  190. package/src/tools/annotation/EllipticalROITool.ts +1223 -0
  191. package/src/tools/annotation/LengthTool.ts +861 -0
  192. package/src/tools/annotation/PlanarFreehandROITool.ts +636 -0
  193. package/src/tools/annotation/ProbeTool.ts +681 -0
  194. package/src/tools/annotation/RectangleROITool.ts +1028 -0
  195. package/src/tools/annotation/planarFreehandROITool/closedContourEditLoop.ts +488 -0
  196. package/src/tools/annotation/planarFreehandROITool/drawLoop.ts +462 -0
  197. package/src/tools/annotation/planarFreehandROITool/editLoopCommon.ts +331 -0
  198. package/src/tools/annotation/planarFreehandROITool/findOpenUShapedContourVectorToPeak.ts +74 -0
  199. package/src/tools/annotation/planarFreehandROITool/openContourEditLoop.ts +612 -0
  200. package/src/tools/annotation/planarFreehandROITool/openContourEndEditLoop.ts +74 -0
  201. package/src/tools/annotation/planarFreehandROITool/renderMethods.ts +407 -0
  202. package/src/tools/base/AnnotationDisplayTool.ts +228 -0
  203. package/src/tools/base/AnnotationTool.ts +307 -0
  204. package/src/tools/base/BaseTool.ts +215 -0
  205. package/src/tools/base/index.ts +4 -0
  206. package/src/tools/displayTools/Contour/addContourToElement.ts +135 -0
  207. package/src/tools/displayTools/Contour/contourDisplay.ts +252 -0
  208. package/src/tools/displayTools/Contour/index.ts +3 -0
  209. package/src/tools/displayTools/Contour/removeContourFromElement.ts +35 -0
  210. package/src/tools/displayTools/Labelmap/addLabelmapToElement.ts +57 -0
  211. package/src/tools/displayTools/Labelmap/index.ts +4 -0
  212. package/src/tools/displayTools/Labelmap/labelmapConfig.ts +37 -0
  213. package/src/tools/displayTools/Labelmap/labelmapDisplay.ts +461 -0
  214. package/src/tools/displayTools/Labelmap/removeLabelmapFromElement.ts +27 -0
  215. package/src/tools/displayTools/Labelmap/validateRepresentationData.ts +30 -0
  216. package/src/tools/displayTools/SegmentationDisplayTool.ts +198 -0
  217. package/src/tools/index.ts +84 -0
  218. package/src/tools/segmentation/BrushTool.ts +474 -0
  219. package/src/tools/segmentation/CircleScissorsTool.ts +365 -0
  220. package/src/tools/segmentation/PaintFillTool.ts +370 -0
  221. package/src/tools/segmentation/RectangleROIStartEndThresholdTool.ts +471 -0
  222. package/src/tools/segmentation/RectangleROIThresholdTool.ts +281 -0
  223. package/src/tools/segmentation/RectangleScissorsTool.ts +382 -0
  224. package/src/tools/segmentation/SphereScissorsTool.ts +368 -0
  225. package/src/tools/segmentation/strategies/eraseCircle.ts +30 -0
  226. package/src/tools/segmentation/strategies/eraseRectangle.ts +81 -0
  227. package/src/tools/segmentation/strategies/eraseSphere.ts +27 -0
  228. package/src/tools/segmentation/strategies/fillCircle.ts +185 -0
  229. package/src/tools/segmentation/strategies/fillRectangle.ts +110 -0
  230. package/src/tools/segmentation/strategies/fillSphere.ts +88 -0
  231. package/src/tools/segmentation/strategies/index.ts +9 -0
  232. package/src/types/AnnotationGroupSelector.ts +7 -0
  233. package/src/types/AnnotationStyle.ts +42 -0
  234. package/src/types/AnnotationTypes.ts +109 -0
  235. package/src/types/BoundsIJK.ts +5 -0
  236. package/src/types/CINETypes.ts +32 -0
  237. package/src/types/ContourTypes.ts +26 -0
  238. package/src/types/CursorTypes.ts +12 -0
  239. package/src/types/EventTypes.ts +657 -0
  240. package/src/types/FloodFillTypes.ts +19 -0
  241. package/src/types/IAnnotationManager.ts +89 -0
  242. package/src/types/IDistance.ts +16 -0
  243. package/src/types/IPoints.ts +18 -0
  244. package/src/types/ISetToolModeOptions.ts +29 -0
  245. package/src/types/ISynchronizerEventHandler.ts +11 -0
  246. package/src/types/IToolClassReference.ts +5 -0
  247. package/src/types/IToolGroup.ts +72 -0
  248. package/src/types/ITouchPoints.ts +14 -0
  249. package/src/types/InteractionTypes.ts +6 -0
  250. package/src/types/InternalToolTypes.ts +19 -0
  251. package/src/types/JumpToSliceOptions.ts +7 -0
  252. package/src/types/LabelmapTypes.ts +41 -0
  253. package/src/types/PlanarBoundingBox.ts +8 -0
  254. package/src/types/SVGDrawingHelper.ts +10 -0
  255. package/src/types/ScrollOptions.ts +9 -0
  256. package/src/types/SegmentationStateTypes.ts +248 -0
  257. package/src/types/ToolHandle.ts +26 -0
  258. package/src/types/ToolProps.ts +16 -0
  259. package/src/types/ToolSpecificAnnotationTypes.ts +311 -0
  260. package/src/types/index.ts +115 -0
  261. package/src/utilities/boundingBox/extend2DBoundingBoxInViewAxis.ts +29 -0
  262. package/src/utilities/boundingBox/getBoundingBoxAroundShape.ts +57 -0
  263. package/src/utilities/boundingBox/index.ts +4 -0
  264. package/src/utilities/calibrateImageSpacing.ts +46 -0
  265. package/src/utilities/cine/events.ts +9 -0
  266. package/src/utilities/cine/index.ts +5 -0
  267. package/src/utilities/cine/playClip.ts +435 -0
  268. package/src/utilities/cine/state.ts +18 -0
  269. package/src/utilities/clip.js +30 -0
  270. package/src/utilities/debounce.js +217 -0
  271. package/src/utilities/drawing/getTextBoxCoordsCanvas.ts +45 -0
  272. package/src/utilities/drawing/index.ts +3 -0
  273. package/src/utilities/dynamicVolume/getDataInTime.ts +110 -0
  274. package/src/utilities/dynamicVolume/index.ts +2 -0
  275. package/src/utilities/getAnnotationNearPoint.ts +130 -0
  276. package/src/utilities/getModalityUnit.ts +11 -0
  277. package/src/utilities/getToolsWithModesForElement.ts +52 -0
  278. package/src/utilities/index.ts +68 -0
  279. package/src/utilities/isObject.js +29 -0
  280. package/src/utilities/math/angle/angleBetweenLines.ts +29 -0
  281. package/src/utilities/math/circle/_types.ts +6 -0
  282. package/src/utilities/math/circle/getCanvasCircleCorners.ts +23 -0
  283. package/src/utilities/math/circle/getCanvasCircleRadius.ts +16 -0
  284. package/src/utilities/math/circle/index.ts +4 -0
  285. package/src/utilities/math/ellipse/getCanvasEllipseCorners.ts +26 -0
  286. package/src/utilities/math/ellipse/index.ts +4 -0
  287. package/src/utilities/math/ellipse/pointInEllipse.ts +38 -0
  288. package/src/utilities/math/ellipse/pointInEllipsoidWithConstraint.ts +35 -0
  289. package/src/utilities/math/index.ts +8 -0
  290. package/src/utilities/math/line/distanceToPoint.ts +24 -0
  291. package/src/utilities/math/line/distanceToPointSquared.ts +44 -0
  292. package/src/utilities/math/line/index.ts +5 -0
  293. package/src/utilities/math/line/intersectLine.ts +92 -0
  294. package/src/utilities/math/midPoint.ts +24 -0
  295. package/src/utilities/math/point/distanceToPoint.ts +22 -0
  296. package/src/utilities/math/point/index.ts +3 -0
  297. package/src/utilities/math/polyline/addCanvasPointsToArray.ts +62 -0
  298. package/src/utilities/math/polyline/calculateAreaOfPoints.ts +23 -0
  299. package/src/utilities/math/polyline/getIntersectionWithPolyline.ts +182 -0
  300. package/src/utilities/math/polyline/getSubPixelSpacingAndXYDirections.ts +99 -0
  301. package/src/utilities/math/polyline/index.ts +19 -0
  302. package/src/utilities/math/polyline/planarFreehandROIInternalTypes.ts +36 -0
  303. package/src/utilities/math/polyline/pointCanProjectOnLine.ts +57 -0
  304. package/src/utilities/math/polyline/pointsAreWithinCloseContourProximity.ts +15 -0
  305. package/src/utilities/math/rectangle/distanceToPoint.ts +82 -0
  306. package/src/utilities/math/rectangle/index.ts +3 -0
  307. package/src/utilities/math/sphere/index.ts +3 -0
  308. package/src/utilities/math/sphere/pointInSphere.ts +31 -0
  309. package/src/utilities/math/vec2/findClosestPoint.ts +40 -0
  310. package/src/utilities/math/vec2/index.ts +4 -0
  311. package/src/utilities/math/vec2/liangBarksyClip.ts +84 -0
  312. package/src/utilities/orientation/getOrientationStringLPS.ts +52 -0
  313. package/src/utilities/orientation/index.ts +4 -0
  314. package/src/utilities/orientation/invertOrientationStringLPS.ts +21 -0
  315. package/src/utilities/planar/filterAnnotationsForDisplay.ts +68 -0
  316. package/src/utilities/planar/filterAnnotationsWithinSlice.ts +85 -0
  317. package/src/utilities/planar/getPointInLineOfSightWithCriteria.ts +104 -0
  318. package/src/utilities/planar/getWorldWidthAndHeightFromCorners.ts +51 -0
  319. package/src/utilities/planar/getWorldWidthAndHeightFromTwoPoints.ts +51 -0
  320. package/src/utilities/planar/index.ts +18 -0
  321. package/src/utilities/planarFreehandROITool/index.ts +7 -0
  322. package/src/utilities/planarFreehandROITool/interpolateAnnotation.ts +87 -0
  323. package/src/utilities/planarFreehandROITool/interpolatePoints.ts +214 -0
  324. package/src/utilities/planarFreehandROITool/interpolation/algorithms/bspline.ts +55 -0
  325. package/src/utilities/planarFreehandROITool/interpolation/interpolateSegmentPoints.ts +90 -0
  326. package/src/utilities/pointInShapeCallback.ts +138 -0
  327. package/src/utilities/pointInSurroundingSphereCallback.ts +188 -0
  328. package/src/utilities/rectangleROITool/getBoundsIJKFromRectangleAnnotations.ts +76 -0
  329. package/src/utilities/rectangleROITool/index.ts +3 -0
  330. package/src/utilities/scroll.ts +62 -0
  331. package/src/utilities/segmentation/brushSizeForToolGroup.ts +72 -0
  332. package/src/utilities/segmentation/brushThresholdForToolGroup.ts +65 -0
  333. package/src/utilities/segmentation/createLabelmapVolumeForViewport.ts +74 -0
  334. package/src/utilities/segmentation/createMergedLabelmapForIndex.ts +65 -0
  335. package/src/utilities/segmentation/floodFill.ts +194 -0
  336. package/src/utilities/segmentation/getDefaultRepresentationConfig.ts +20 -0
  337. package/src/utilities/segmentation/index.ts +33 -0
  338. package/src/utilities/segmentation/isValidRepresentationConfig.ts +22 -0
  339. package/src/utilities/segmentation/rectangleROIThresholdVolumeByRange.ts +91 -0
  340. package/src/utilities/segmentation/thresholdSegmentationByRange.ts +129 -0
  341. package/src/utilities/segmentation/thresholdVolumeByRange.ts +150 -0
  342. package/src/utilities/segmentation/triggerSegmentationRender.ts +206 -0
  343. package/src/utilities/segmentation/utilities.ts +116 -0
  344. package/src/utilities/stackPrefetch/index.ts +8 -0
  345. package/src/utilities/stackPrefetch/stackPrefetch.ts +405 -0
  346. package/src/utilities/stackPrefetch/state.ts +17 -0
  347. package/src/utilities/throttle.js +69 -0
  348. package/src/utilities/touch/index.ts +246 -0
  349. package/src/utilities/triggerAnnotationRender.ts +237 -0
  350. package/src/utilities/triggerAnnotationRenderForViewportIds.ts +18 -0
  351. package/src/utilities/viewport/index.ts +5 -0
  352. package/src/utilities/viewport/isViewportPreScaled.ts +24 -0
  353. package/src/utilities/viewport/jumpToSlice.ts +73 -0
  354. package/src/utilities/viewport/jumpToWorld.ts +58 -0
  355. package/src/utilities/viewportFilters/filterViewportsWithFrameOfReferenceUID.ts +28 -0
  356. package/src/utilities/viewportFilters/filterViewportsWithParallelNormals.ts +26 -0
  357. package/src/utilities/viewportFilters/filterViewportsWithSameOrientation.ts +15 -0
  358. package/src/utilities/viewportFilters/filterViewportsWithToolEnabled.ts +72 -0
  359. package/src/utilities/viewportFilters/getViewportIdsWithToolToRender.ts +45 -0
  360. package/src/utilities/viewportFilters/index.ts +11 -0
@@ -0,0 +1,861 @@
1
+ import { Events } from '../../enums';
2
+ import {
3
+ getEnabledElement,
4
+ triggerEvent,
5
+ eventTarget,
6
+ utilities as csUtils,
7
+ } from '@cornerstonejs/core';
8
+ import type { Types } from '@cornerstonejs/core';
9
+
10
+ import { AnnotationTool } from '../base';
11
+ import throttle from '../../utilities/throttle';
12
+ import {
13
+ addAnnotation,
14
+ getAnnotations,
15
+ removeAnnotation,
16
+ } from '../../stateManagement/annotation/annotationState';
17
+ import { isAnnotationLocked } from '../../stateManagement/annotation/annotationLocking';
18
+ import { isAnnotationVisible } from '../../stateManagement/annotation/annotationVisibility';
19
+ import * as lineSegment from '../../utilities/math/line';
20
+
21
+ import {
22
+ drawHandles as drawHandlesSvg,
23
+ drawLine as drawLineSvg,
24
+ drawLinkedTextBox as drawLinkedTextBoxSvg,
25
+ } from '../../drawingSvg';
26
+ import { state } from '../../store';
27
+ import { getViewportIdsWithToolToRender } from '../../utilities/viewportFilters';
28
+ import { getTextBoxCoordsCanvas } from '../../utilities/drawing';
29
+ import triggerAnnotationRenderForViewportIds from '../../utilities/triggerAnnotationRenderForViewportIds';
30
+ import {
31
+ AnnotationCompletedEventDetail,
32
+ AnnotationModifiedEventDetail,
33
+ } from '../../types/EventTypes';
34
+
35
+ import {
36
+ resetElementCursor,
37
+ hideElementCursor,
38
+ } from '../../cursors/elementCursor';
39
+
40
+ import {
41
+ EventTypes,
42
+ ToolHandle,
43
+ TextBoxHandle,
44
+ PublicToolProps,
45
+ ToolProps,
46
+ InteractionTypes,
47
+ SVGDrawingHelper,
48
+ } from '../../types';
49
+ import { LengthAnnotation } from '../../types/ToolSpecificAnnotationTypes';
50
+ import { StyleSpecifier } from '../../types/AnnotationStyle';
51
+
52
+ const { transformWorldToIndex } = csUtils;
53
+
54
+ /**
55
+ * LengthTool let you draw annotations that measures the length of two drawing
56
+ * points on a slice. You can use the LengthTool in all imaging planes even in oblique
57
+ * reconstructed planes. Note: annotation tools in cornerstone3DTools exists in the exact location
58
+ * in the physical 3d space, as a result, by default, all annotations that are
59
+ * drawing in the same frameOfReference will get shared between viewports that
60
+ * are in the same frameOfReference.
61
+ *
62
+ * The resulting annotation's data (statistics) and metadata (the
63
+ * state of the viewport while drawing was happening) will get added to the
64
+ * ToolState manager and can be accessed from the ToolState by calling getAnnotations
65
+ * or similar methods.
66
+ *
67
+ * ```js
68
+ * cornerstoneTools.addTool(LengthTool)
69
+ *
70
+ * const toolGroup = ToolGroupManager.createToolGroup('toolGroupId')
71
+ *
72
+ * toolGroup.addTool(LengthTool.toolName)
73
+ *
74
+ * toolGroup.addViewport('viewportId', 'renderingEngineId')
75
+ *
76
+ * toolGroup.setToolActive(LengthTool.toolName, {
77
+ * bindings: [
78
+ * {
79
+ * mouseButton: MouseBindings.Primary, // Left Click
80
+ * },
81
+ * ],
82
+ * })
83
+ * ```
84
+ *
85
+ * Read more in the Docs section of the website.
86
+
87
+ */
88
+
89
+ class LengthTool extends AnnotationTool {
90
+ static toolName;
91
+
92
+ public touchDragCallback: any;
93
+ public mouseDragCallback: any;
94
+ _throttledCalculateCachedStats: any;
95
+ editData: {
96
+ annotation: any;
97
+ viewportIdsToRender: string[];
98
+ handleIndex?: number;
99
+ movingTextBox?: boolean;
100
+ newAnnotation?: boolean;
101
+ hasMoved?: boolean;
102
+ } | null;
103
+ isDrawing: boolean;
104
+ isHandleOutsideImage: boolean;
105
+
106
+ constructor(
107
+ toolProps: PublicToolProps = {},
108
+ defaultToolProps: ToolProps = {
109
+ supportedInteractionTypes: ['Mouse', 'Touch'],
110
+ configuration: {
111
+ preventHandleOutsideImage: false,
112
+ },
113
+ }
114
+ ) {
115
+ super(toolProps, defaultToolProps);
116
+
117
+ this._throttledCalculateCachedStats = throttle(
118
+ this._calculateCachedStats,
119
+ 100,
120
+ { trailing: true }
121
+ );
122
+ }
123
+
124
+ /**
125
+ * Based on the current position of the mouse and the current imageId to create
126
+ * a Length Annotation and stores it in the annotationManager
127
+ *
128
+ * @param evt - EventTypes.NormalizedMouseEventType
129
+ * @returns The annotation object.
130
+ *
131
+ */
132
+ addNewAnnotation = (
133
+ evt: EventTypes.InteractionEventType
134
+ ): LengthAnnotation => {
135
+ const eventDetail = evt.detail;
136
+ const { currentPoints, element } = eventDetail;
137
+ const worldPos = currentPoints.world;
138
+ const enabledElement = getEnabledElement(element);
139
+ const { viewport, renderingEngine } = enabledElement;
140
+
141
+ hideElementCursor(element);
142
+ this.isDrawing = true;
143
+
144
+ const camera = viewport.getCamera();
145
+ const { viewPlaneNormal, viewUp } = camera;
146
+
147
+ const referencedImageId = this.getReferencedImageId(
148
+ viewport,
149
+ worldPos,
150
+ viewPlaneNormal,
151
+ viewUp
152
+ );
153
+
154
+ const FrameOfReferenceUID = viewport.getFrameOfReferenceUID();
155
+
156
+ const annotation = {
157
+ highlighted: true,
158
+ invalidated: true,
159
+ metadata: {
160
+ toolName: this.getToolName(),
161
+ viewPlaneNormal: <Types.Point3>[...viewPlaneNormal],
162
+ viewUp: <Types.Point3>[...viewUp],
163
+ FrameOfReferenceUID,
164
+ referencedImageId,
165
+ },
166
+ data: {
167
+ handles: {
168
+ points: [<Types.Point3>[...worldPos], <Types.Point3>[...worldPos]],
169
+ activeHandleIndex: null,
170
+ textBox: {
171
+ hasMoved: false,
172
+ worldPosition: <Types.Point3>[0, 0, 0],
173
+ worldBoundingBox: {
174
+ topLeft: <Types.Point3>[0, 0, 0],
175
+ topRight: <Types.Point3>[0, 0, 0],
176
+ bottomLeft: <Types.Point3>[0, 0, 0],
177
+ bottomRight: <Types.Point3>[0, 0, 0],
178
+ },
179
+ },
180
+ },
181
+ label: '',
182
+ cachedStats: {},
183
+ },
184
+ };
185
+
186
+ addAnnotation(annotation, element);
187
+
188
+ const viewportIdsToRender = getViewportIdsWithToolToRender(
189
+ element,
190
+ this.getToolName()
191
+ );
192
+
193
+ this.editData = {
194
+ annotation,
195
+ viewportIdsToRender,
196
+ handleIndex: 1,
197
+ movingTextBox: false,
198
+ newAnnotation: true,
199
+ hasMoved: false,
200
+ };
201
+ this._activateDraw(element);
202
+
203
+ evt.preventDefault();
204
+
205
+ triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender);
206
+
207
+ return annotation;
208
+ };
209
+
210
+ /**
211
+ * It returns if the canvas point is near the provided length annotation in the provided
212
+ * element or not. A proximity is passed to the function to determine the
213
+ * proximity of the point to the annotation in number of pixels.
214
+ *
215
+ * @param element - HTML Element
216
+ * @param annotation - Annotation
217
+ * @param canvasCoords - Canvas coordinates
218
+ * @param proximity - Proximity to tool to consider
219
+ * @returns Boolean, whether the canvas point is near tool
220
+ */
221
+ isPointNearTool = (
222
+ element: HTMLDivElement,
223
+ annotation: LengthAnnotation,
224
+ canvasCoords: Types.Point2,
225
+ proximity: number
226
+ ): boolean => {
227
+ const enabledElement = getEnabledElement(element);
228
+ const { viewport } = enabledElement;
229
+ const { data } = annotation;
230
+ const [point1, point2] = data.handles.points;
231
+ const canvasPoint1 = viewport.worldToCanvas(point1);
232
+ const canvasPoint2 = viewport.worldToCanvas(point2);
233
+
234
+ const line = {
235
+ start: {
236
+ x: canvasPoint1[0],
237
+ y: canvasPoint1[1],
238
+ },
239
+ end: {
240
+ x: canvasPoint2[0],
241
+ y: canvasPoint2[1],
242
+ },
243
+ };
244
+
245
+ const distanceToPoint = lineSegment.distanceToPoint(
246
+ [line.start.x, line.start.y],
247
+ [line.end.x, line.end.y],
248
+ [canvasCoords[0], canvasCoords[1]]
249
+ );
250
+
251
+ if (distanceToPoint <= proximity) {
252
+ return true;
253
+ }
254
+
255
+ return false;
256
+ };
257
+
258
+ toolSelectedCallback = (
259
+ evt: EventTypes.InteractionEventType,
260
+ annotation: LengthAnnotation
261
+ ): void => {
262
+ const eventDetail = evt.detail;
263
+ const { element } = eventDetail;
264
+
265
+ annotation.highlighted = true;
266
+
267
+ const viewportIdsToRender = getViewportIdsWithToolToRender(
268
+ element,
269
+ this.getToolName()
270
+ );
271
+
272
+ this.editData = {
273
+ annotation,
274
+ viewportIdsToRender,
275
+ movingTextBox: false,
276
+ };
277
+
278
+ this._activateModify(element);
279
+
280
+ hideElementCursor(element);
281
+
282
+ const enabledElement = getEnabledElement(element);
283
+ const { renderingEngine } = enabledElement;
284
+
285
+ triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender);
286
+
287
+ evt.preventDefault();
288
+ };
289
+
290
+ handleSelectedCallback(
291
+ evt: EventTypes.InteractionEventType,
292
+ annotation: LengthAnnotation,
293
+ handle: ToolHandle
294
+ ): void {
295
+ const eventDetail = evt.detail;
296
+ const { element } = eventDetail;
297
+ const { data } = annotation;
298
+
299
+ annotation.highlighted = true;
300
+
301
+ let movingTextBox = false;
302
+ let handleIndex;
303
+
304
+ if ((handle as TextBoxHandle).worldPosition) {
305
+ movingTextBox = true;
306
+ } else {
307
+ handleIndex = data.handles.points.findIndex((p) => p === handle);
308
+ }
309
+
310
+ // Find viewports to render on drag.
311
+ const viewportIdsToRender = getViewportIdsWithToolToRender(
312
+ element,
313
+ this.getToolName()
314
+ );
315
+
316
+ this.editData = {
317
+ annotation,
318
+ viewportIdsToRender,
319
+ handleIndex,
320
+ movingTextBox,
321
+ };
322
+ this._activateModify(element);
323
+
324
+ hideElementCursor(element);
325
+
326
+ const enabledElement = getEnabledElement(element);
327
+ const { renderingEngine } = enabledElement;
328
+
329
+ triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender);
330
+
331
+ evt.preventDefault();
332
+ }
333
+
334
+ _endCallback = (evt: EventTypes.InteractionEventType): void => {
335
+ const eventDetail = evt.detail;
336
+ const { element } = eventDetail;
337
+
338
+ const { annotation, viewportIdsToRender, newAnnotation, hasMoved } =
339
+ this.editData;
340
+ const { data } = annotation;
341
+
342
+ if (newAnnotation && !hasMoved) {
343
+ // when user starts the drawing by click, and moving the mouse, instead
344
+ // of click and drag
345
+ return;
346
+ }
347
+
348
+ data.handles.activeHandleIndex = null;
349
+
350
+ this._deactivateModify(element);
351
+ this._deactivateDraw(element);
352
+ resetElementCursor(element);
353
+
354
+ const enabledElement = getEnabledElement(element);
355
+ const { renderingEngine } = enabledElement;
356
+
357
+ if (
358
+ this.isHandleOutsideImage &&
359
+ this.configuration.preventHandleOutsideImage
360
+ ) {
361
+ removeAnnotation(annotation.annotationUID);
362
+ }
363
+
364
+ triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender);
365
+
366
+ if (newAnnotation) {
367
+ const eventType = Events.ANNOTATION_COMPLETED;
368
+
369
+ const eventDetail: AnnotationCompletedEventDetail = {
370
+ annotation,
371
+ };
372
+
373
+ triggerEvent(eventTarget, eventType, eventDetail);
374
+ }
375
+
376
+ this.editData = null;
377
+ this.isDrawing = false;
378
+ };
379
+
380
+ _dragCallback = (evt: EventTypes.InteractionEventType): void => {
381
+ this.isDrawing = true;
382
+ const eventDetail = evt.detail;
383
+ const { element } = eventDetail;
384
+
385
+ const { annotation, viewportIdsToRender, handleIndex, movingTextBox } =
386
+ this.editData;
387
+ const { data } = annotation;
388
+
389
+ if (movingTextBox) {
390
+ // Drag mode - moving text box
391
+ const { deltaPoints } = eventDetail as EventTypes.MouseDragEventDetail;
392
+ const worldPosDelta = deltaPoints.world;
393
+
394
+ const { textBox } = data.handles;
395
+ const { worldPosition } = textBox;
396
+
397
+ worldPosition[0] += worldPosDelta[0];
398
+ worldPosition[1] += worldPosDelta[1];
399
+ worldPosition[2] += worldPosDelta[2];
400
+
401
+ textBox.hasMoved = true;
402
+ } else if (handleIndex === undefined) {
403
+ // Drag mode - moving handle
404
+ const { deltaPoints } = eventDetail as EventTypes.MouseDragEventDetail;
405
+ const worldPosDelta = deltaPoints.world;
406
+
407
+ const points = data.handles.points;
408
+
409
+ points.forEach((point) => {
410
+ point[0] += worldPosDelta[0];
411
+ point[1] += worldPosDelta[1];
412
+ point[2] += worldPosDelta[2];
413
+ });
414
+ annotation.invalidated = true;
415
+ } else {
416
+ // Move mode - after double click, and mouse move to draw
417
+ const { currentPoints } = eventDetail;
418
+ const worldPos = currentPoints.world;
419
+
420
+ data.handles.points[handleIndex] = [...worldPos];
421
+ annotation.invalidated = true;
422
+ }
423
+
424
+ this.editData.hasMoved = true;
425
+
426
+ const enabledElement = getEnabledElement(element);
427
+ const { renderingEngine } = enabledElement;
428
+
429
+ triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender);
430
+ };
431
+
432
+ cancel = (element: HTMLDivElement) => {
433
+ // If it is mid-draw or mid-modify
434
+ if (this.isDrawing) {
435
+ this.isDrawing = false;
436
+ this._deactivateDraw(element);
437
+ this._deactivateModify(element);
438
+ resetElementCursor(element);
439
+
440
+ const { annotation, viewportIdsToRender, newAnnotation } = this.editData;
441
+ const { data } = annotation;
442
+
443
+ annotation.highlighted = false;
444
+ data.handles.activeHandleIndex = null;
445
+
446
+ const enabledElement = getEnabledElement(element);
447
+ const { renderingEngine } = enabledElement;
448
+
449
+ triggerAnnotationRenderForViewportIds(
450
+ renderingEngine,
451
+ viewportIdsToRender
452
+ );
453
+
454
+ if (newAnnotation) {
455
+ const eventType = Events.ANNOTATION_COMPLETED;
456
+
457
+ const eventDetail: AnnotationCompletedEventDetail = {
458
+ annotation,
459
+ };
460
+
461
+ triggerEvent(eventTarget, eventType, eventDetail);
462
+ }
463
+
464
+ this.editData = null;
465
+ return annotation.annotationUID;
466
+ }
467
+ };
468
+
469
+ _activateModify = (element: HTMLDivElement) => {
470
+ state.isInteractingWithTool = true;
471
+
472
+ element.addEventListener(
473
+ Events.MOUSE_UP,
474
+ this._endCallback as EventListener
475
+ );
476
+ element.addEventListener(
477
+ Events.MOUSE_DRAG,
478
+ this._dragCallback as EventListener
479
+ );
480
+ element.addEventListener(
481
+ Events.MOUSE_CLICK,
482
+ this._endCallback as EventListener
483
+ );
484
+
485
+ element.addEventListener(
486
+ Events.TOUCH_END,
487
+ this._endCallback as EventListener
488
+ );
489
+ element.addEventListener(
490
+ Events.TOUCH_DRAG,
491
+ this._dragCallback as EventListener
492
+ );
493
+ element.addEventListener(
494
+ Events.TOUCH_TAP,
495
+ this._endCallback as EventListener
496
+ );
497
+ };
498
+
499
+ _deactivateModify = (element: HTMLDivElement) => {
500
+ state.isInteractingWithTool = false;
501
+
502
+ element.removeEventListener(
503
+ Events.MOUSE_UP,
504
+ this._endCallback as EventListener
505
+ );
506
+ element.removeEventListener(
507
+ Events.MOUSE_DRAG,
508
+ this._dragCallback as EventListener
509
+ );
510
+ element.removeEventListener(
511
+ Events.MOUSE_CLICK,
512
+ this._endCallback as EventListener
513
+ );
514
+
515
+ element.removeEventListener(
516
+ Events.TOUCH_END,
517
+ this._endCallback as EventListener
518
+ );
519
+ element.removeEventListener(
520
+ Events.TOUCH_DRAG,
521
+ this._dragCallback as EventListener
522
+ );
523
+ element.removeEventListener(
524
+ Events.TOUCH_TAP,
525
+ this._endCallback as EventListener
526
+ );
527
+ };
528
+
529
+ _activateDraw = (element: HTMLDivElement) => {
530
+ state.isInteractingWithTool = true;
531
+
532
+ element.addEventListener(
533
+ Events.MOUSE_UP,
534
+ this._endCallback as EventListener
535
+ );
536
+ element.addEventListener(
537
+ Events.MOUSE_DRAG,
538
+ this._dragCallback as EventListener
539
+ );
540
+ element.addEventListener(
541
+ Events.MOUSE_MOVE,
542
+ this._dragCallback as EventListener
543
+ );
544
+ element.addEventListener(
545
+ Events.MOUSE_CLICK,
546
+ this._endCallback as EventListener
547
+ );
548
+
549
+ element.addEventListener(
550
+ Events.TOUCH_END,
551
+ this._endCallback as EventListener
552
+ );
553
+ element.addEventListener(
554
+ Events.TOUCH_DRAG,
555
+ this._dragCallback as EventListener
556
+ );
557
+ element.addEventListener(
558
+ Events.TOUCH_TAP,
559
+ this._endCallback as EventListener
560
+ );
561
+ };
562
+
563
+ _deactivateDraw = (element: HTMLDivElement) => {
564
+ state.isInteractingWithTool = false;
565
+
566
+ element.removeEventListener(
567
+ Events.MOUSE_UP,
568
+ this._endCallback as EventListener
569
+ );
570
+ element.removeEventListener(
571
+ Events.MOUSE_DRAG,
572
+ this._dragCallback as EventListener
573
+ );
574
+ element.removeEventListener(
575
+ Events.MOUSE_MOVE,
576
+ this._dragCallback as EventListener
577
+ );
578
+ element.removeEventListener(
579
+ Events.MOUSE_CLICK,
580
+ this._endCallback as EventListener
581
+ );
582
+
583
+ element.removeEventListener(
584
+ Events.TOUCH_END,
585
+ this._endCallback as EventListener
586
+ );
587
+ element.removeEventListener(
588
+ Events.TOUCH_DRAG,
589
+ this._dragCallback as EventListener
590
+ );
591
+ element.removeEventListener(
592
+ Events.TOUCH_TAP,
593
+ this._endCallback as EventListener
594
+ );
595
+ };
596
+
597
+ /**
598
+ * it is used to draw the length annotation in each
599
+ * request animation frame. It calculates the updated cached statistics if
600
+ * data is invalidated and cache it.
601
+ *
602
+ * @param enabledElement - The Cornerstone's enabledElement.
603
+ * @param svgDrawingHelper - The svgDrawingHelper providing the context for drawing.
604
+ */
605
+ renderAnnotation = (
606
+ enabledElement: Types.IEnabledElement,
607
+ svgDrawingHelper: SVGDrawingHelper
608
+ ): boolean => {
609
+ let renderStatus = false;
610
+ const { viewport } = enabledElement;
611
+ const { element } = viewport;
612
+
613
+ let annotations = getAnnotations(this.getToolName(), element);
614
+
615
+ // Todo: We don't need this anymore, filtering happens in triggerAnnotationRender
616
+ if (!annotations?.length) {
617
+ return renderStatus;
618
+ }
619
+
620
+ annotations = this.filterInteractableAnnotationsForElement(
621
+ element,
622
+ annotations
623
+ );
624
+
625
+ if (!annotations?.length) {
626
+ return renderStatus;
627
+ }
628
+
629
+ const targetId = this.getTargetId(viewport);
630
+ const renderingEngine = viewport.getRenderingEngine();
631
+
632
+ const styleSpecifier: StyleSpecifier = {
633
+ toolGroupId: this.toolGroupId,
634
+ toolName: this.getToolName(),
635
+ viewportId: enabledElement.viewport.id,
636
+ };
637
+
638
+ // Draw SVG
639
+ for (let i = 0; i < annotations.length; i++) {
640
+ const annotation = annotations[i] as LengthAnnotation;
641
+ const { annotationUID, data } = annotation;
642
+ const { points, activeHandleIndex } = data.handles;
643
+
644
+ styleSpecifier.annotationUID = annotationUID;
645
+
646
+ // Todo: move these into annotationTool class
647
+ const lineWidth = this.getStyle('lineWidth', styleSpecifier, annotation);
648
+ const lineDash = this.getStyle('lineDash', styleSpecifier, annotation);
649
+ const color = this.getStyle('color', styleSpecifier, annotation);
650
+ const shadow = this.getStyle('shadow', styleSpecifier, annotation);
651
+
652
+ const canvasCoordinates = points.map((p) => viewport.worldToCanvas(p));
653
+
654
+ let activeHandleCanvasCoords;
655
+
656
+ // If cachedStats does not exist, or the unit is missing (as part of import/hydration etc.),
657
+ // force to recalculate the stats from the points
658
+ if (
659
+ !data.cachedStats[targetId] ||
660
+ data.cachedStats[targetId].unit === undefined
661
+ ) {
662
+ data.cachedStats[targetId] = {
663
+ length: null,
664
+ unit: null,
665
+ };
666
+
667
+ this._calculateCachedStats(annotation, renderingEngine, enabledElement);
668
+ } else if (annotation.invalidated) {
669
+ this._throttledCalculateCachedStats(
670
+ annotation,
671
+ renderingEngine,
672
+ enabledElement
673
+ );
674
+ }
675
+
676
+ if (!isAnnotationVisible(annotationUID)) {
677
+ continue;
678
+ }
679
+
680
+ if (
681
+ !isAnnotationLocked(annotation) &&
682
+ !this.editData &&
683
+ activeHandleIndex !== null
684
+ ) {
685
+ // Not locked or creating and hovering over handle, so render handle.
686
+ activeHandleCanvasCoords = [canvasCoordinates[activeHandleIndex]];
687
+ }
688
+
689
+ if (activeHandleCanvasCoords) {
690
+ const handleGroupUID = '0';
691
+
692
+ drawHandlesSvg(
693
+ svgDrawingHelper,
694
+ annotationUID,
695
+ handleGroupUID,
696
+ canvasCoordinates,
697
+ {
698
+ color,
699
+ lineDash,
700
+ lineWidth,
701
+ }
702
+ );
703
+ }
704
+
705
+ const dataId = `${annotationUID}-line`;
706
+ const lineUID = '1';
707
+ drawLineSvg(
708
+ svgDrawingHelper,
709
+ annotationUID,
710
+ lineUID,
711
+ canvasCoordinates[0],
712
+ canvasCoordinates[1],
713
+ {
714
+ color,
715
+ width: lineWidth,
716
+ lineDash,
717
+ shadow,
718
+ },
719
+ dataId
720
+ );
721
+
722
+ renderStatus = true;
723
+
724
+ // If rendering engine has been destroyed while rendering
725
+ if (!viewport.getRenderingEngine()) {
726
+ console.warn('Rendering Engine has been destroyed');
727
+ return renderStatus;
728
+ }
729
+
730
+ const textLines = this._getTextLines(data, targetId);
731
+
732
+ // Need to update to sync w/ annotation while unlinked/not moved
733
+ if (!data.handles.textBox.hasMoved) {
734
+ const canvasTextBoxCoords = getTextBoxCoordsCanvas(canvasCoordinates);
735
+
736
+ data.handles.textBox.worldPosition =
737
+ viewport.canvasToWorld(canvasTextBoxCoords);
738
+ }
739
+
740
+ const textBoxPosition = viewport.worldToCanvas(
741
+ data.handles.textBox.worldPosition
742
+ );
743
+
744
+ const textBoxUID = '1';
745
+ const boundingBox = drawLinkedTextBoxSvg(
746
+ svgDrawingHelper,
747
+ annotationUID,
748
+ textBoxUID,
749
+ textLines,
750
+ textBoxPosition,
751
+ canvasCoordinates,
752
+ {},
753
+ this.getLinkedTextBoxStyle(styleSpecifier, annotation)
754
+ );
755
+
756
+ const { x: left, y: top, width, height } = boundingBox;
757
+
758
+ data.handles.textBox.worldBoundingBox = {
759
+ topLeft: viewport.canvasToWorld([left, top]),
760
+ topRight: viewport.canvasToWorld([left + width, top]),
761
+ bottomLeft: viewport.canvasToWorld([left, top + height]),
762
+ bottomRight: viewport.canvasToWorld([left + width, top + height]),
763
+ };
764
+ }
765
+
766
+ return renderStatus;
767
+ };
768
+
769
+ // text line for the current active length annotation
770
+ _getTextLines(data, targetId) {
771
+ const cachedVolumeStats = data.cachedStats[targetId];
772
+ const { length, unit } = cachedVolumeStats;
773
+
774
+ // Can be null on load
775
+ if (length === undefined || length === null || isNaN(length)) {
776
+ return;
777
+ }
778
+
779
+ const textLines = [`${length.toFixed(2)} ${unit}`];
780
+
781
+ return textLines;
782
+ }
783
+
784
+ _calculateLength(pos1, pos2) {
785
+ const dx = pos1[0] - pos2[0];
786
+ const dy = pos1[1] - pos2[1];
787
+ const dz = pos1[2] - pos2[2];
788
+
789
+ return Math.sqrt(dx * dx + dy * dy + dz * dz);
790
+ }
791
+
792
+ _calculateCachedStats(annotation, renderingEngine, enabledElement) {
793
+ const data = annotation.data;
794
+ const { viewportId, renderingEngineId } = enabledElement;
795
+
796
+ const worldPos1 = data.handles.points[0];
797
+ const worldPos2 = data.handles.points[1];
798
+ const { cachedStats } = data;
799
+ const targetIds = Object.keys(cachedStats);
800
+
801
+ // TODO clean up, this doesn't need a length per volume, it has no stats derived from volumes.
802
+
803
+ for (let i = 0; i < targetIds.length; i++) {
804
+ const targetId = targetIds[i];
805
+
806
+ const image = this.getTargetIdImage(targetId, renderingEngine);
807
+
808
+ // If image does not exists for the targetId, skip. This can be due
809
+ // to various reasons such as if the target was a volumeViewport, and
810
+ // the volumeViewport has been decached in the meantime.
811
+ if (!image) {
812
+ continue;
813
+ }
814
+
815
+ const { imageData, dimensions, hasPixelSpacing } = image;
816
+
817
+ const length = this._calculateLength(worldPos1, worldPos2);
818
+
819
+ const index1 = transformWorldToIndex(imageData, worldPos1);
820
+ const index2 = transformWorldToIndex(imageData, worldPos2);
821
+
822
+ this._isInsideVolume(index1, index2, dimensions)
823
+ ? (this.isHandleOutsideImage = false)
824
+ : (this.isHandleOutsideImage = true);
825
+
826
+ // TODO -> Do we instead want to clip to the bounds of the volume and only include that portion?
827
+ // Seems like a lot of work for an unrealistic case. At the moment bail out of stat calculation if either
828
+ // corner is off the canvas.
829
+
830
+ // todo: add insideVolume calculation, for removing tool if outside
831
+ cachedStats[targetId] = {
832
+ length,
833
+ unit: hasPixelSpacing ? 'mm' : 'px',
834
+ };
835
+ }
836
+
837
+ annotation.invalidated = false;
838
+
839
+ // Dispatching annotation modified
840
+ const eventType = Events.ANNOTATION_MODIFIED;
841
+
842
+ const eventDetail: AnnotationModifiedEventDetail = {
843
+ annotation,
844
+ viewportId,
845
+ renderingEngineId,
846
+ };
847
+ triggerEvent(eventTarget, eventType, eventDetail);
848
+
849
+ return cachedStats;
850
+ }
851
+
852
+ _isInsideVolume(index1, index2, dimensions) {
853
+ return (
854
+ csUtils.indexWithinDimensions(index1, dimensions) &&
855
+ csUtils.indexWithinDimensions(index2, dimensions)
856
+ );
857
+ }
858
+ }
859
+
860
+ LengthTool.toolName = 'Length';
861
+ export default LengthTool;