@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,835 @@
1
+ import { Events } from '../../enums';
2
+ import {
3
+ getEnabledElement,
4
+ triggerEvent,
5
+ eventTarget,
6
+ } from '@cornerstonejs/core';
7
+ import type { Types } from '@cornerstonejs/core';
8
+
9
+ import { AnnotationTool } from '../base';
10
+ import throttle from '../../utilities/throttle';
11
+ import {
12
+ addAnnotation,
13
+ getAnnotations,
14
+ removeAnnotation,
15
+ } from '../../stateManagement/annotation/annotationState';
16
+ import { isAnnotationLocked } from '../../stateManagement/annotation/annotationLocking';
17
+ import * as lineSegment from '../../utilities/math/line';
18
+ import angleBetweenLines from '../../utilities/math/angle/angleBetweenLines';
19
+
20
+ import {
21
+ drawHandles as drawHandlesSvg,
22
+ drawLine as drawLineSvg,
23
+ drawLinkedTextBox as drawLinkedTextBoxSvg,
24
+ } from '../../drawingSvg';
25
+ import { state } from '../../store';
26
+ import { getViewportIdsWithToolToRender } from '../../utilities/viewportFilters';
27
+ import { getTextBoxCoordsCanvas } from '../../utilities/drawing';
28
+ import triggerAnnotationRenderForViewportIds from '../../utilities/triggerAnnotationRenderForViewportIds';
29
+ import {
30
+ AnnotationCompletedEventDetail,
31
+ AnnotationModifiedEventDetail,
32
+ } from '../../types/EventTypes';
33
+
34
+ import {
35
+ resetElementCursor,
36
+ hideElementCursor,
37
+ } from '../../cursors/elementCursor';
38
+
39
+ import {
40
+ EventTypes,
41
+ ToolHandle,
42
+ TextBoxHandle,
43
+ PublicToolProps,
44
+ ToolProps,
45
+ InteractionTypes,
46
+ SVGDrawingHelper,
47
+ } from '../../types';
48
+ import { AngleAnnotation } from '../../types/ToolSpecificAnnotationTypes';
49
+ import { StyleSpecifier } from '../../types/AnnotationStyle';
50
+
51
+ class AngleTool extends AnnotationTool {
52
+ static toolName;
53
+
54
+ public touchDragCallback: any;
55
+ public mouseDragCallback: any;
56
+ angleStartedNotYetCompleted: boolean;
57
+ _throttledCalculateCachedStats: any;
58
+ editData: {
59
+ annotation: any;
60
+ viewportIdsToRender: string[];
61
+ handleIndex?: number;
62
+ movingTextBox?: boolean;
63
+ newAnnotation?: boolean;
64
+ hasMoved?: boolean;
65
+ } | null;
66
+ isDrawing: boolean;
67
+ isHandleOutsideImage: boolean;
68
+
69
+ constructor(
70
+ toolProps: PublicToolProps = {},
71
+ defaultToolProps: ToolProps = {
72
+ supportedInteractionTypes: ['Mouse', 'Touch'],
73
+ configuration: {
74
+ shadow: true,
75
+ preventHandleOutsideImage: false,
76
+ },
77
+ }
78
+ ) {
79
+ super(toolProps, defaultToolProps);
80
+
81
+ this._throttledCalculateCachedStats = throttle(
82
+ this._calculateCachedStats,
83
+ 100,
84
+ { trailing: true }
85
+ );
86
+ }
87
+
88
+ /**
89
+ * Based on the current position of the mouse and the current imageId to create
90
+ * a Length Annotation and stores it in the annotationManager
91
+ *
92
+ * @param evt - EventTypes.InteractionEventType
93
+ * @returns The annotation object.
94
+ *
95
+ */
96
+ addNewAnnotation = (
97
+ evt: EventTypes.InteractionEventType
98
+ ): AngleAnnotation => {
99
+ if (this.angleStartedNotYetCompleted) {
100
+ return;
101
+ }
102
+
103
+ this.angleStartedNotYetCompleted = true;
104
+ const eventDetail = evt.detail;
105
+ const { currentPoints, element } = eventDetail;
106
+
107
+ const worldPos = currentPoints.world;
108
+ const enabledElement = getEnabledElement(element);
109
+ const { viewport, renderingEngine } = enabledElement;
110
+
111
+ hideElementCursor(element);
112
+ this.isDrawing = true;
113
+
114
+ const camera = viewport.getCamera();
115
+ const { viewPlaneNormal, viewUp } = camera;
116
+
117
+ const referencedImageId = this.getReferencedImageId(
118
+ viewport,
119
+ worldPos,
120
+ viewPlaneNormal,
121
+ viewUp
122
+ );
123
+
124
+ const FrameOfReferenceUID = viewport.getFrameOfReferenceUID();
125
+
126
+ const annotation = {
127
+ highlighted: true,
128
+ invalidated: true,
129
+ metadata: {
130
+ toolName: this.getToolName(),
131
+ viewPlaneNormal: <Types.Point3>[...viewPlaneNormal],
132
+ viewUp: <Types.Point3>[...viewUp],
133
+ FrameOfReferenceUID,
134
+ referencedImageId,
135
+ },
136
+ data: {
137
+ handles: {
138
+ points: [<Types.Point3>[...worldPos], <Types.Point3>[...worldPos]],
139
+ activeHandleIndex: null,
140
+ textBox: {
141
+ hasMoved: false,
142
+ worldPosition: <Types.Point3>[0, 0, 0],
143
+ worldBoundingBox: {
144
+ topLeft: <Types.Point3>[0, 0, 0],
145
+ topRight: <Types.Point3>[0, 0, 0],
146
+ bottomLeft: <Types.Point3>[0, 0, 0],
147
+ bottomRight: <Types.Point3>[0, 0, 0],
148
+ },
149
+ },
150
+ },
151
+ label: '',
152
+ cachedStats: {},
153
+ },
154
+ };
155
+
156
+ addAnnotation(annotation, element);
157
+
158
+ const viewportIdsToRender = getViewportIdsWithToolToRender(
159
+ element,
160
+ this.getToolName()
161
+ );
162
+
163
+ this.editData = {
164
+ annotation,
165
+ viewportIdsToRender,
166
+ handleIndex: 1,
167
+ movingTextBox: false,
168
+ newAnnotation: true,
169
+ hasMoved: false,
170
+ };
171
+ this._activateDraw(element);
172
+
173
+ evt.preventDefault();
174
+
175
+ triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender);
176
+
177
+ return annotation;
178
+ };
179
+
180
+ /**
181
+ * It returns if the canvas point is near the provided length annotation in the provided
182
+ * element or not. A proximity is passed to the function to determine the
183
+ * proximity of the point to the annotation in number of pixels.
184
+ *
185
+ * @param element - HTML Element
186
+ * @param annotation - Annotation
187
+ * @param canvasCoords - Canvas coordinates
188
+ * @param proximity - Proximity to tool to consider
189
+ * @returns Boolean, whether the canvas point is near tool
190
+ */
191
+ isPointNearTool = (
192
+ element: HTMLDivElement,
193
+ annotation: AngleAnnotation,
194
+ canvasCoords: Types.Point2,
195
+ proximity: number
196
+ ): boolean => {
197
+ const enabledElement = getEnabledElement(element);
198
+ const { viewport } = enabledElement;
199
+ const { data } = annotation;
200
+ const [point1, point2, point3] = data.handles.points;
201
+ const canvasPoint1 = viewport.worldToCanvas(point1);
202
+ const canvasPoint2 = viewport.worldToCanvas(point2);
203
+ const canvasPoint3 = viewport.worldToCanvas(point3);
204
+
205
+ const line1 = {
206
+ start: {
207
+ x: canvasPoint1[0],
208
+ y: canvasPoint1[1],
209
+ },
210
+ end: {
211
+ x: canvasPoint2[0],
212
+ y: canvasPoint2[1],
213
+ },
214
+ };
215
+
216
+ const line2 = {
217
+ start: {
218
+ x: canvasPoint2[0],
219
+ y: canvasPoint2[1],
220
+ },
221
+ end: {
222
+ x: canvasPoint3[0],
223
+ y: canvasPoint3[1],
224
+ },
225
+ };
226
+
227
+ const distanceToPoint = lineSegment.distanceToPoint(
228
+ [line1.start.x, line1.start.y],
229
+ [line1.end.x, line1.end.y],
230
+ [canvasCoords[0], canvasCoords[1]]
231
+ );
232
+
233
+ const distanceToPoint2 = lineSegment.distanceToPoint(
234
+ [line2.start.x, line2.start.y],
235
+ [line2.end.x, line2.end.y],
236
+ [canvasCoords[0], canvasCoords[1]]
237
+ );
238
+
239
+ if (distanceToPoint <= proximity || distanceToPoint2 <= proximity) {
240
+ return true;
241
+ }
242
+
243
+ return false;
244
+ };
245
+
246
+ toolSelectedCallback = (
247
+ evt: EventTypes.InteractionEventType,
248
+ annotation: AngleAnnotation
249
+ ): void => {
250
+ const eventDetail = evt.detail;
251
+ const { element } = eventDetail;
252
+
253
+ annotation.highlighted = true;
254
+
255
+ const viewportIdsToRender = getViewportIdsWithToolToRender(
256
+ element,
257
+ this.getToolName()
258
+ );
259
+
260
+ this.editData = {
261
+ annotation,
262
+ viewportIdsToRender,
263
+ movingTextBox: false,
264
+ };
265
+
266
+ this._activateModify(element);
267
+
268
+ hideElementCursor(element);
269
+
270
+ const enabledElement = getEnabledElement(element);
271
+ const { renderingEngine } = enabledElement;
272
+
273
+ triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender);
274
+
275
+ evt.preventDefault();
276
+ };
277
+
278
+ handleSelectedCallback(
279
+ evt: EventTypes.InteractionEventType,
280
+ annotation: AngleAnnotation,
281
+ handle: ToolHandle
282
+ ): void {
283
+ const eventDetail = evt.detail;
284
+ const { element } = eventDetail;
285
+ const { data } = annotation;
286
+
287
+ annotation.highlighted = true;
288
+
289
+ let movingTextBox = false;
290
+ let handleIndex;
291
+
292
+ if ((handle as TextBoxHandle).worldPosition) {
293
+ movingTextBox = true;
294
+ } else {
295
+ handleIndex = data.handles.points.findIndex((p) => p === handle);
296
+ }
297
+
298
+ // Find viewports to render on drag.
299
+ const viewportIdsToRender = getViewportIdsWithToolToRender(
300
+ element,
301
+ this.getToolName()
302
+ );
303
+
304
+ this.editData = {
305
+ annotation,
306
+ viewportIdsToRender,
307
+ handleIndex,
308
+ movingTextBox,
309
+ };
310
+ this._activateModify(element);
311
+
312
+ hideElementCursor(element);
313
+
314
+ const enabledElement = getEnabledElement(element);
315
+ const { renderingEngine } = enabledElement;
316
+
317
+ triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender);
318
+
319
+ evt.preventDefault();
320
+ }
321
+
322
+ _endCallback = (evt: EventTypes.InteractionEventType): void => {
323
+ const eventDetail = evt.detail;
324
+ const { element } = eventDetail;
325
+
326
+ const { annotation, viewportIdsToRender, newAnnotation, hasMoved } =
327
+ this.editData;
328
+
329
+ const { data } = annotation;
330
+ if (newAnnotation && !hasMoved) {
331
+ // when user starts the drawing by click, and moving the mouse, instead
332
+ // of click and drag
333
+ return;
334
+ }
335
+
336
+ // If preventing new measurement means we are in the middle of an existing measurement
337
+ // we shouldn't deactivate modify or draw
338
+ if (this.angleStartedNotYetCompleted && data.handles.points.length === 2) {
339
+ // adds the last point to the measurement
340
+ this.editData.handleIndex = 2;
341
+ return;
342
+ }
343
+
344
+ this.angleStartedNotYetCompleted = false;
345
+ data.handles.activeHandleIndex = null;
346
+
347
+ this._deactivateModify(element);
348
+ this._deactivateDraw(element);
349
+ resetElementCursor(element);
350
+
351
+ const enabledElement = getEnabledElement(element);
352
+ const { renderingEngine } = enabledElement;
353
+
354
+ if (
355
+ this.isHandleOutsideImage &&
356
+ this.configuration.preventHandleOutsideImage
357
+ ) {
358
+ removeAnnotation(annotation.annotationUID);
359
+ }
360
+
361
+ triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender);
362
+
363
+ if (newAnnotation) {
364
+ const eventType = Events.ANNOTATION_COMPLETED;
365
+
366
+ const eventDetail: AnnotationCompletedEventDetail = {
367
+ annotation,
368
+ };
369
+
370
+ triggerEvent(eventTarget, eventType, eventDetail);
371
+ }
372
+
373
+ this.editData = null;
374
+ this.isDrawing = false;
375
+ };
376
+
377
+ _dragCallback = (evt: EventTypes.InteractionEventType): void => {
378
+ this.isDrawing = true;
379
+ const eventDetail = evt.detail;
380
+ const { element } = eventDetail;
381
+
382
+ const { annotation, viewportIdsToRender, handleIndex, movingTextBox } =
383
+ this.editData;
384
+ const { data } = annotation;
385
+
386
+ if (movingTextBox) {
387
+ // Drag mode - moving text box
388
+ const { deltaPoints } = eventDetail as EventTypes.MouseDragEventDetail;
389
+ const worldPosDelta = deltaPoints.world;
390
+
391
+ const { textBox } = data.handles;
392
+ const { worldPosition } = textBox;
393
+
394
+ worldPosition[0] += worldPosDelta[0];
395
+ worldPosition[1] += worldPosDelta[1];
396
+ worldPosition[2] += worldPosDelta[2];
397
+
398
+ textBox.hasMoved = true;
399
+ } else if (handleIndex === undefined) {
400
+ // Drag mode - moving handle
401
+ const { deltaPoints } = eventDetail as EventTypes.MouseDragEventDetail;
402
+ const worldPosDelta = deltaPoints.world;
403
+
404
+ const points = data.handles.points;
405
+
406
+ points.forEach((point) => {
407
+ point[0] += worldPosDelta[0];
408
+ point[1] += worldPosDelta[1];
409
+ point[2] += worldPosDelta[2];
410
+ });
411
+ annotation.invalidated = true;
412
+ } else {
413
+ // Move mode - after double click, and mouse move to draw
414
+ const { currentPoints } = eventDetail;
415
+ const worldPos = currentPoints.world;
416
+
417
+ data.handles.points[handleIndex] = [...worldPos];
418
+ annotation.invalidated = true;
419
+ }
420
+
421
+ this.editData.hasMoved = true;
422
+
423
+ const enabledElement = getEnabledElement(element);
424
+ const { renderingEngine } = enabledElement;
425
+
426
+ triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender);
427
+ };
428
+
429
+ cancel = (element: HTMLDivElement) => {
430
+ // If it is mid-draw or mid-modify
431
+ if (this.isDrawing) {
432
+ this.isDrawing = false;
433
+ this._deactivateDraw(element);
434
+ this._deactivateModify(element);
435
+ resetElementCursor(element);
436
+
437
+ const { annotation, viewportIdsToRender, newAnnotation } = this.editData;
438
+ const { data } = annotation;
439
+
440
+ annotation.highlighted = false;
441
+ data.handles.activeHandleIndex = null;
442
+
443
+ const enabledElement = getEnabledElement(element);
444
+ const { renderingEngine } = enabledElement;
445
+
446
+ triggerAnnotationRenderForViewportIds(
447
+ renderingEngine,
448
+ viewportIdsToRender
449
+ );
450
+
451
+ if (newAnnotation) {
452
+ const eventType = Events.ANNOTATION_COMPLETED;
453
+
454
+ const eventDetail: AnnotationCompletedEventDetail = {
455
+ annotation,
456
+ };
457
+
458
+ triggerEvent(eventTarget, eventType, eventDetail);
459
+ }
460
+
461
+ this.editData = null;
462
+ this.angleStartedNotYetCompleted = false;
463
+ return annotation.annotationUID;
464
+ }
465
+ };
466
+
467
+ _activateModify = (element: HTMLDivElement) => {
468
+ state.isInteractingWithTool = true;
469
+
470
+ element.addEventListener(
471
+ Events.MOUSE_UP,
472
+ this._endCallback as EventListener
473
+ );
474
+ element.addEventListener(
475
+ Events.MOUSE_DRAG,
476
+ this._dragCallback as EventListener
477
+ );
478
+ element.addEventListener(
479
+ Events.MOUSE_CLICK,
480
+ this._endCallback as EventListener
481
+ );
482
+
483
+ element.addEventListener(
484
+ Events.TOUCH_TAP,
485
+ this._endCallback as EventListener
486
+ );
487
+ element.addEventListener(
488
+ Events.TOUCH_END,
489
+ this._endCallback as EventListener
490
+ );
491
+ element.addEventListener(
492
+ Events.TOUCH_DRAG,
493
+ this._dragCallback as EventListener
494
+ );
495
+ };
496
+
497
+ _deactivateModify = (element: HTMLDivElement) => {
498
+ state.isInteractingWithTool = false;
499
+
500
+ element.removeEventListener(
501
+ Events.MOUSE_UP,
502
+ this._endCallback as EventListener
503
+ );
504
+ element.removeEventListener(
505
+ Events.MOUSE_DRAG,
506
+ this._dragCallback as EventListener
507
+ );
508
+ element.removeEventListener(
509
+ Events.MOUSE_CLICK,
510
+ this._endCallback as EventListener
511
+ );
512
+ element.removeEventListener(
513
+ Events.TOUCH_TAP,
514
+ this._endCallback as EventListener
515
+ );
516
+ element.removeEventListener(
517
+ Events.TOUCH_END,
518
+ this._endCallback as EventListener
519
+ );
520
+ element.removeEventListener(
521
+ Events.TOUCH_DRAG,
522
+ this._dragCallback as EventListener
523
+ );
524
+ };
525
+
526
+ _activateDraw = (element: HTMLDivElement) => {
527
+ state.isInteractingWithTool = true;
528
+
529
+ element.addEventListener(
530
+ Events.MOUSE_UP,
531
+ this._endCallback as EventListener
532
+ );
533
+ element.addEventListener(
534
+ Events.MOUSE_DRAG,
535
+ this._dragCallback as EventListener
536
+ );
537
+ element.addEventListener(
538
+ Events.MOUSE_MOVE,
539
+ this._dragCallback as EventListener
540
+ );
541
+ element.addEventListener(
542
+ Events.MOUSE_CLICK,
543
+ this._endCallback as EventListener
544
+ );
545
+
546
+ element.addEventListener(
547
+ Events.TOUCH_TAP,
548
+ this._endCallback as EventListener
549
+ );
550
+ element.addEventListener(
551
+ Events.TOUCH_END,
552
+ this._endCallback as EventListener
553
+ );
554
+ element.addEventListener(
555
+ Events.TOUCH_DRAG,
556
+ this._dragCallback as EventListener
557
+ );
558
+ };
559
+
560
+ _deactivateDraw = (element: HTMLDivElement) => {
561
+ state.isInteractingWithTool = false;
562
+
563
+ element.removeEventListener(
564
+ Events.MOUSE_UP,
565
+ this._endCallback as EventListener
566
+ );
567
+ element.removeEventListener(
568
+ Events.MOUSE_DRAG,
569
+ this._dragCallback as EventListener
570
+ );
571
+ element.removeEventListener(
572
+ Events.MOUSE_MOVE,
573
+ this._dragCallback as EventListener
574
+ );
575
+ element.removeEventListener(
576
+ Events.MOUSE_CLICK,
577
+ this._endCallback as EventListener
578
+ );
579
+
580
+ element.removeEventListener(
581
+ Events.TOUCH_TAP,
582
+ this._endCallback as EventListener
583
+ );
584
+ element.removeEventListener(
585
+ Events.TOUCH_END,
586
+ this._endCallback as EventListener
587
+ );
588
+ element.removeEventListener(
589
+ Events.TOUCH_DRAG,
590
+ this._dragCallback as EventListener
591
+ );
592
+ };
593
+
594
+ /**
595
+ * it is used to draw the length annotation in each
596
+ * request animation frame. It calculates the updated cached statistics if
597
+ * data is invalidated and cache it.
598
+ *
599
+ * @param enabledElement - The Cornerstone's enabledElement.
600
+ * @param svgDrawingHelper - The svgDrawingHelper providing the context for drawing.
601
+ */
602
+ renderAnnotation = (
603
+ enabledElement: Types.IEnabledElement,
604
+ svgDrawingHelper: SVGDrawingHelper
605
+ ): boolean => {
606
+ let renderStatus = false;
607
+
608
+ const { viewport } = enabledElement;
609
+ const { element } = viewport;
610
+
611
+ let annotations = getAnnotations(this.getToolName(), element);
612
+
613
+ // Todo: We don't need this anymore, filtering happens in triggerAnnotationRender
614
+ if (!annotations?.length) {
615
+ return renderStatus;
616
+ }
617
+
618
+ annotations = this.filterInteractableAnnotationsForElement(
619
+ element,
620
+ annotations
621
+ );
622
+
623
+ if (!annotations?.length) {
624
+ return renderStatus;
625
+ }
626
+
627
+ const targetId = this.getTargetId(viewport);
628
+ const renderingEngine = viewport.getRenderingEngine();
629
+
630
+ const styleSpecifier: StyleSpecifier = {
631
+ toolGroupId: this.toolGroupId,
632
+ toolName: this.getToolName(),
633
+ viewportId: enabledElement.viewport.id,
634
+ };
635
+
636
+ // Draw SVG
637
+ for (let i = 0; i < annotations.length; i++) {
638
+ const annotation = annotations[i] as AngleAnnotation;
639
+ const { annotationUID, data } = annotation;
640
+ const { points, activeHandleIndex } = data.handles;
641
+
642
+ styleSpecifier.annotationUID = annotationUID;
643
+
644
+ const lineWidth = this.getStyle('lineWidth', styleSpecifier, annotation);
645
+ const lineDash = this.getStyle('lineDash', styleSpecifier, annotation);
646
+ const color = this.getStyle('color', styleSpecifier, annotation);
647
+
648
+ const canvasCoordinates = points.map((p) => viewport.worldToCanvas(p));
649
+
650
+ // WE HAVE TO CACHE STATS BEFORE FETCHING TEXT
651
+ if (!data.cachedStats[targetId]) {
652
+ data.cachedStats[targetId] = {
653
+ angle: null,
654
+ };
655
+
656
+ this._calculateCachedStats(annotation, renderingEngine, enabledElement);
657
+ } else if (annotation.invalidated) {
658
+ this._throttledCalculateCachedStats(
659
+ annotation,
660
+ renderingEngine,
661
+ enabledElement
662
+ );
663
+ }
664
+
665
+ let activeHandleCanvasCoords;
666
+
667
+ if (
668
+ !isAnnotationLocked(annotation) &&
669
+ !this.editData &&
670
+ activeHandleIndex !== null
671
+ ) {
672
+ // Not locked or creating and hovering over handle, so render handle.
673
+ activeHandleCanvasCoords = [canvasCoordinates[activeHandleIndex]];
674
+ }
675
+
676
+ // If rendering engine has been destroyed while rendering
677
+ if (!viewport.getRenderingEngine()) {
678
+ console.warn('Rendering Engine has been destroyed');
679
+ return renderStatus;
680
+ }
681
+
682
+ if (activeHandleCanvasCoords) {
683
+ const handleGroupUID = '0';
684
+
685
+ drawHandlesSvg(
686
+ svgDrawingHelper,
687
+ annotationUID,
688
+ handleGroupUID,
689
+ canvasCoordinates,
690
+ {
691
+ color,
692
+ lineDash,
693
+ lineWidth,
694
+ }
695
+ );
696
+ }
697
+
698
+ let lineUID = '1';
699
+ drawLineSvg(
700
+ svgDrawingHelper,
701
+ annotationUID,
702
+ lineUID,
703
+ canvasCoordinates[0],
704
+ canvasCoordinates[1],
705
+ {
706
+ color,
707
+ width: lineWidth,
708
+ lineDash,
709
+ }
710
+ );
711
+
712
+ renderStatus = true;
713
+
714
+ // Don't add textBox until annotation has 3 anchor points (actually 4 because of the center point)
715
+ if (canvasCoordinates.length !== 3) {
716
+ return renderStatus;
717
+ }
718
+
719
+ lineUID = '2';
720
+
721
+ drawLineSvg(
722
+ svgDrawingHelper,
723
+ annotationUID,
724
+ lineUID,
725
+ canvasCoordinates[1],
726
+ canvasCoordinates[2],
727
+ {
728
+ color,
729
+ width: lineWidth,
730
+ lineDash,
731
+ }
732
+ );
733
+
734
+ if (!data.cachedStats[targetId]?.angle) {
735
+ continue;
736
+ }
737
+
738
+ const textLines = this._getTextLines(data, targetId);
739
+
740
+ if (!data.handles.textBox.hasMoved) {
741
+ const canvasTextBoxCoords = getTextBoxCoordsCanvas(canvasCoordinates);
742
+
743
+ data.handles.textBox.worldPosition =
744
+ viewport.canvasToWorld(canvasTextBoxCoords);
745
+ }
746
+
747
+ const textBoxPosition = viewport.worldToCanvas(
748
+ data.handles.textBox.worldPosition
749
+ );
750
+
751
+ const textBoxUID = '1';
752
+ const boundingBox = drawLinkedTextBoxSvg(
753
+ svgDrawingHelper,
754
+ annotationUID,
755
+ textBoxUID,
756
+ textLines,
757
+ textBoxPosition,
758
+ canvasCoordinates,
759
+ {},
760
+ this.getLinkedTextBoxStyle(styleSpecifier, annotation)
761
+ );
762
+
763
+ const { x: left, y: top, width, height } = boundingBox;
764
+
765
+ data.handles.textBox.worldBoundingBox = {
766
+ topLeft: viewport.canvasToWorld([left, top]),
767
+ topRight: viewport.canvasToWorld([left + width, top]),
768
+ bottomLeft: viewport.canvasToWorld([left, top + height]),
769
+ bottomRight: viewport.canvasToWorld([left + width, top + height]),
770
+ };
771
+ }
772
+
773
+ return renderStatus;
774
+ };
775
+
776
+ // text line for the current active angle annotation
777
+ _getTextLines(data, targetId) {
778
+ const cachedVolumeStats = data.cachedStats[targetId];
779
+ const { angle } = cachedVolumeStats;
780
+
781
+ if (angle === undefined) {
782
+ return;
783
+ }
784
+
785
+ const textLines = [`${angle.toFixed(2)} ${String.fromCharCode(176)}`];
786
+
787
+ return textLines;
788
+ }
789
+
790
+ _calculateCachedStats(annotation, renderingEngine, enabledElement) {
791
+ const data = annotation.data;
792
+ const { viewportId, renderingEngineId } = enabledElement;
793
+
794
+ // Until we have all three anchors bail out
795
+ if (data.handles.points.length !== 3) {
796
+ return;
797
+ }
798
+
799
+ const worldPos1 = data.handles.points[0];
800
+ const worldPos2 = data.handles.points[1];
801
+ const worldPos3 = data.handles.points[2];
802
+
803
+ const { cachedStats } = data;
804
+ const targetIds = Object.keys(cachedStats);
805
+
806
+ for (let i = 0; i < targetIds.length; i++) {
807
+ const targetId = targetIds[i];
808
+ const angle = angleBetweenLines(
809
+ [worldPos1, worldPos2],
810
+ [worldPos2, worldPos3]
811
+ );
812
+
813
+ cachedStats[targetId] = {
814
+ angle,
815
+ };
816
+ }
817
+
818
+ annotation.invalidated = false;
819
+
820
+ // Dispatching annotation modified
821
+ const eventType = Events.ANNOTATION_MODIFIED;
822
+
823
+ const eventDetail: AnnotationModifiedEventDetail = {
824
+ annotation,
825
+ viewportId,
826
+ renderingEngineId,
827
+ };
828
+ triggerEvent(eventTarget, eventType, eventDetail);
829
+
830
+ return cachedStats;
831
+ }
832
+ }
833
+
834
+ AngleTool.toolName = 'Angle';
835
+ export default AngleTool;