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