@cornerstonejs/tools 5.0.0-beta.1 → 5.0.1

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 (290) hide show
  1. package/dist/esm/config.d.ts +4 -0
  2. package/dist/esm/drawingSvg/drawPath.d.ts +3 -0
  3. package/dist/esm/drawingSvg/drawPath.js +4 -1
  4. package/dist/esm/eventListeners/keyboard/keyDownListener.js +2 -2
  5. package/dist/esm/eventListeners/mouse/getMouseEventPoints.d.ts +1 -1
  6. package/dist/esm/eventListeners/mouse/getMouseEventPoints.js +19 -1
  7. package/dist/esm/eventListeners/mouse/mouseDoubleClickListener.js +8 -1
  8. package/dist/esm/eventListeners/mouse/mouseDownListener.js +37 -5
  9. package/dist/esm/eventListeners/mouse/mouseMoveListener.js +3 -0
  10. package/dist/esm/eventListeners/segmentation/imageChangeEventListener.js +60 -92
  11. package/dist/esm/eventListeners/segmentation/labelmap/onLabelmapSegmentationDataModified.js +49 -21
  12. package/dist/esm/eventListeners/segmentation/labelmap/performStackLabelmapUpdate.js +7 -13
  13. package/dist/esm/eventListeners/segmentation/labelmap/performVolumeLabelmapUpdate.js +44 -18
  14. package/dist/esm/eventListeners/touch/getTouchEventPoints.js +27 -4
  15. package/dist/esm/eventListeners/touch/touchStartListener.js +27 -9
  16. package/dist/esm/eventListeners/wheel/wheelListener.js +5 -1
  17. package/dist/esm/index.d.ts +2 -2
  18. package/dist/esm/index.js +2 -2
  19. package/dist/esm/init.js +2 -0
  20. package/dist/esm/stateManagement/annotation/FrameOfReferenceSpecificAnnotationManager.js +10 -4
  21. package/dist/esm/stateManagement/segmentation/SegmentationRenderingEngine.js +23 -20
  22. package/dist/esm/stateManagement/segmentation/SegmentationRepresentationDisplayRegistry.d.ts +12 -0
  23. package/dist/esm/stateManagement/segmentation/SegmentationRepresentationDisplayRegistry.js +7 -0
  24. package/dist/esm/stateManagement/segmentation/SegmentationStateManager.d.ts +1 -10
  25. package/dist/esm/stateManagement/segmentation/SegmentationStateManager.js +28 -149
  26. package/dist/esm/stateManagement/segmentation/addColorLUT.js +7 -1
  27. package/dist/esm/stateManagement/segmentation/getCurrentLabelmapImageIdForViewport.js +16 -1
  28. package/dist/esm/stateManagement/segmentation/helpers/clearSegmentValue.js +9 -7
  29. package/dist/esm/stateManagement/segmentation/helpers/getSegmentationActor.d.ts +1 -1
  30. package/dist/esm/stateManagement/segmentation/helpers/getSegmentationActor.js +3 -2
  31. package/dist/esm/stateManagement/segmentation/helpers/getViewportLabelmapRenderMode.d.ts +5 -0
  32. package/dist/esm/stateManagement/segmentation/helpers/getViewportLabelmapRenderMode.js +58 -0
  33. package/dist/esm/stateManagement/segmentation/helpers/labelmapImageMapperSupport.d.ts +52 -0
  34. package/dist/esm/stateManagement/segmentation/helpers/labelmapImageMapperSupport.js +246 -0
  35. package/dist/esm/stateManagement/segmentation/helpers/labelmapSegmentationState.d.ts +1 -0
  36. package/dist/esm/stateManagement/segmentation/helpers/labelmapSegmentationState.js +1 -0
  37. package/dist/esm/stateManagement/segmentation/helpers/normalizeSegmentationInput.js +12 -1
  38. package/dist/esm/stateManagement/segmentation/internalAddSegmentationRepresentation.js +3 -3
  39. package/dist/esm/stateManagement/segmentation/labelmapModel/index.d.ts +9 -0
  40. package/dist/esm/stateManagement/segmentation/labelmapModel/index.js +7 -0
  41. package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapEditTransaction.d.ts +54 -0
  42. package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapEditTransaction.js +224 -0
  43. package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapImageIdMapping.d.ts +6 -0
  44. package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapImageIdMapping.js +39 -0
  45. package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapImageReferenceResolver.d.ts +23 -0
  46. package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapImageReferenceResolver.js +269 -0
  47. package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapLayerStore.d.ts +15 -0
  48. package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapLayerStore.js +160 -0
  49. package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapLegacyAdapter.d.ts +4 -0
  50. package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapLegacyAdapter.js +42 -0
  51. package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapSegmentBindings.d.ts +11 -0
  52. package/dist/esm/stateManagement/segmentation/labelmapModel/labelmapSegmentBindings.js +73 -0
  53. package/dist/esm/stateManagement/segmentation/labelmapModel/normalizeLabelmapSegmentationData.d.ts +17 -0
  54. package/dist/esm/stateManagement/segmentation/labelmapModel/normalizeLabelmapSegmentationData.js +75 -0
  55. package/dist/esm/stateManagement/segmentation/labelmapModel/privateLabelmap.d.ts +5 -0
  56. package/dist/esm/stateManagement/segmentation/labelmapModel/privateLabelmap.js +106 -0
  57. package/dist/esm/stateManagement/segmentation/models/SegmentModel.d.ts +11 -0
  58. package/dist/esm/stateManagement/segmentation/models/SegmentModel.js +19 -0
  59. package/dist/esm/stateManagement/segmentation/models/SegmentationModel.d.ts +12 -0
  60. package/dist/esm/stateManagement/segmentation/models/SegmentationModel.js +23 -0
  61. package/dist/esm/stateManagement/segmentation/removeSegmentationRepresentations.js +6 -10
  62. package/dist/esm/stateManagement/segmentation/segmentIndex.js +24 -0
  63. package/dist/esm/stateManagement/segmentation/segmentationEventManager.js +2 -9
  64. package/dist/esm/stateManagement/segmentation/segmentationState.d.ts +2 -1
  65. package/dist/esm/stateManagement/segmentation/segmentationState.js +4 -1
  66. package/dist/esm/store/SynchronizerManager/Synchronizer.d.ts +3 -1
  67. package/dist/esm/store/state.js +2 -1
  68. package/dist/esm/synchronizers/callbacks/imageSliceSyncCallback.js +12 -3
  69. package/dist/esm/synchronizers/callbacks/presentationViewSyncCallback.js +5 -2
  70. package/dist/esm/synchronizers/callbacks/zoomPanSyncCallback.js +51 -3
  71. package/dist/esm/synchronizers/synchronizers/createPresentationViewSynchronizer.d.ts +1 -1
  72. package/dist/esm/tools/AdvancedMagnifyTool.js +4 -1
  73. package/dist/esm/tools/CrosshairsTool.d.ts +4 -0
  74. package/dist/esm/tools/CrosshairsTool.js +95 -41
  75. package/dist/esm/tools/MagnifyTool.js +3 -1
  76. package/dist/esm/tools/OrientationControllerTool.d.ts +45 -0
  77. package/dist/esm/tools/OrientationControllerTool.js +454 -0
  78. package/dist/esm/tools/OrientationMarkerTool.js +4 -4
  79. package/dist/esm/tools/PanTool.js +26 -3
  80. package/dist/esm/tools/PlanarRotateTool.js +19 -4
  81. package/dist/esm/tools/ReferenceCursors.js +7 -1
  82. package/dist/esm/tools/SculptorTool/CircleSculptCursor.js +1 -1
  83. package/dist/esm/tools/TrackballRotateTool.js +3 -2
  84. package/dist/esm/tools/VolumeCroppingControlTool.d.ts +10 -35
  85. package/dist/esm/tools/VolumeCroppingControlTool.js +179 -699
  86. package/dist/esm/tools/VolumeCroppingTool.d.ts +34 -32
  87. package/dist/esm/tools/VolumeCroppingTool.js +813 -532
  88. package/dist/esm/tools/WindowLevelTool.d.ts +2 -1
  89. package/dist/esm/tools/WindowLevelTool.js +48 -4
  90. package/dist/esm/tools/ZoomTool.d.ts +8 -0
  91. package/dist/esm/tools/ZoomTool.js +92 -11
  92. package/dist/esm/tools/annotation/AngleTool.js +38 -32
  93. package/dist/esm/tools/annotation/ArrowAnnotateTool.js +30 -28
  94. package/dist/esm/tools/annotation/BidirectionalTool.js +51 -49
  95. package/dist/esm/tools/annotation/CircleROITool.d.ts +1 -0
  96. package/dist/esm/tools/annotation/CircleROITool.js +89 -51
  97. package/dist/esm/tools/annotation/CobbAngleTool.js +1 -1
  98. package/dist/esm/tools/annotation/DragProbeTool.js +1 -1
  99. package/dist/esm/tools/annotation/ETDRSGridTool.js +1 -1
  100. package/dist/esm/tools/annotation/EllipticalROITool.js +46 -39
  101. package/dist/esm/tools/annotation/HeightTool.js +1 -1
  102. package/dist/esm/tools/annotation/KeyImageTool.js +11 -11
  103. package/dist/esm/tools/annotation/LabelTool.js +37 -35
  104. package/dist/esm/tools/annotation/LengthTool.js +35 -33
  105. package/dist/esm/tools/annotation/LivewireContourSegmentationTool.js +6 -4
  106. package/dist/esm/tools/annotation/LivewireContourTool.js +4 -8
  107. package/dist/esm/tools/annotation/PlanarFreehandContourSegmentationTool.js +6 -4
  108. package/dist/esm/tools/annotation/PlanarFreehandROITool.d.ts +2 -1
  109. package/dist/esm/tools/annotation/PlanarFreehandROITool.js +11 -8
  110. package/dist/esm/tools/annotation/ProbeTool.js +66 -56
  111. package/dist/esm/tools/annotation/RectangleROITool.js +48 -37
  112. package/dist/esm/tools/annotation/RegionSegmentPlusTool.js +1 -1
  113. package/dist/esm/tools/annotation/RegionSegmentTool.js +1 -1
  114. package/dist/esm/tools/annotation/SplineContourSegmentationTool.js +1 -1
  115. package/dist/esm/tools/annotation/SplineROITool.js +60 -56
  116. package/dist/esm/tools/annotation/UltrasoundDirectionalTool.js +1 -1
  117. package/dist/esm/tools/annotation/UltrasoundPleuraBLineTool/UltrasoundPleuraBLineTool.js +57 -55
  118. package/dist/esm/tools/annotation/VideoRedactionTool.js +1 -1
  119. package/dist/esm/tools/base/AnnotationDisplayTool.js +9 -6
  120. package/dist/esm/tools/base/AnnotationTool.js +2 -1
  121. package/dist/esm/tools/base/BaseTool.js +16 -10
  122. package/dist/esm/tools/base/ContourSegmentationBaseTool.js +1 -1
  123. package/dist/esm/tools/base/GrowCutBaseTool.js +2 -2
  124. package/dist/esm/tools/displayTools/Labelmap/addLabelmapToElement.d.ts +2 -4
  125. package/dist/esm/tools/displayTools/Labelmap/addLabelmapToElement.js +15 -85
  126. package/dist/esm/tools/displayTools/Labelmap/labelmapActorStyle.d.ts +5 -0
  127. package/dist/esm/tools/displayTools/Labelmap/labelmapActorStyle.js +191 -0
  128. package/dist/esm/tools/displayTools/Labelmap/labelmapDisplay.d.ts +4 -3
  129. package/dist/esm/tools/displayTools/Labelmap/labelmapDisplay.js +48 -209
  130. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/createLabelmapRenderPlan.d.ts +3 -0
  131. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/createLabelmapRenderPlan.js +51 -0
  132. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/index.d.ts +4 -0
  133. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/index.js +3 -0
  134. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/legacyVolumePlan.d.ts +14 -0
  135. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/legacyVolumePlan.js +143 -0
  136. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/planarGenericVolumeLabelmap.d.ts +40 -0
  137. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/planarGenericVolumeLabelmap.js +79 -0
  138. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/removeLabelmapRepresentationFromViewport.d.ts +3 -0
  139. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/removeLabelmapRepresentationFromViewport.js +18 -0
  140. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/resolveLabelmapRenderPlan.d.ts +9 -0
  141. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/resolveLabelmapRenderPlan.js +56 -0
  142. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/stackImagePlan.d.ts +11 -0
  143. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/stackImagePlan.js +35 -0
  144. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/types.d.ts +48 -0
  145. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/types.js +0 -0
  146. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/volumeSliceImageMapperPlan.d.ts +13 -0
  147. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/volumeSliceImageMapperPlan.js +34 -0
  148. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan.d.ts +2 -0
  149. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan.js +1 -0
  150. package/dist/esm/tools/displayTools/Labelmap/labelmapRepresentationUID.d.ts +8 -0
  151. package/dist/esm/tools/displayTools/Labelmap/labelmapRepresentationUID.js +18 -0
  152. package/dist/esm/tools/displayTools/Labelmap/removeLabelmapFromElement.js +2 -2
  153. package/dist/esm/tools/displayTools/Labelmap/removeLabelmapRepresentationData.d.ts +3 -0
  154. package/dist/esm/tools/displayTools/Labelmap/removeLabelmapRepresentationData.js +16 -0
  155. package/dist/esm/tools/displayTools/Labelmap/syncStackLabelmapActors.d.ts +2 -0
  156. package/dist/esm/tools/displayTools/Labelmap/syncStackLabelmapActors.js +135 -0
  157. package/dist/esm/tools/displayTools/Labelmap/volumeLabelmapImageMapper.d.ts +16 -0
  158. package/dist/esm/tools/displayTools/Labelmap/volumeLabelmapImageMapper.js +267 -0
  159. package/dist/esm/tools/displayTools/Labelmap/volumeLabelmapSliceData.d.ts +27 -0
  160. package/dist/esm/tools/displayTools/Labelmap/volumeLabelmapSliceData.js +185 -0
  161. package/dist/esm/tools/displayTools/registerBuiltInSegmentationRepresentationDisplays.d.ts +1 -0
  162. package/dist/esm/tools/displayTools/registerBuiltInSegmentationRepresentationDisplays.js +16 -0
  163. package/dist/esm/tools/index.d.ts +2 -1
  164. package/dist/esm/tools/index.js +2 -1
  165. package/dist/esm/tools/segmentation/BrushTool.d.ts +9 -2
  166. package/dist/esm/tools/segmentation/BrushTool.js +123 -26
  167. package/dist/esm/tools/segmentation/CircleScissorsTool.js +19 -36
  168. package/dist/esm/tools/segmentation/LabelmapBaseTool.d.ts +2 -3
  169. package/dist/esm/tools/segmentation/LabelmapBaseTool.js +77 -46
  170. package/dist/esm/tools/segmentation/LabelmapEditWithContour.js +3 -3
  171. package/dist/esm/tools/segmentation/PaintFillTool.js +11 -4
  172. package/dist/esm/tools/segmentation/RectangleROIStartEndThresholdTool.d.ts +2 -0
  173. package/dist/esm/tools/segmentation/RectangleROIStartEndThresholdTool.js +16 -8
  174. package/dist/esm/tools/segmentation/RectangleScissorsTool.js +13 -6
  175. package/dist/esm/tools/segmentation/SegmentBidirectionalTool.js +63 -61
  176. package/dist/esm/tools/segmentation/SegmentSelectTool.js +4 -4
  177. package/dist/esm/tools/segmentation/SphereScissorsTool.js +11 -31
  178. package/dist/esm/tools/segmentation/strategies/BrushStrategy.d.ts +7 -0
  179. package/dist/esm/tools/segmentation/strategies/BrushStrategy.js +47 -24
  180. package/dist/esm/tools/segmentation/strategies/compositions/circularCursor.js +49 -21
  181. package/dist/esm/tools/segmentation/strategies/compositions/determineSegmentIndex.js +2 -2
  182. package/dist/esm/tools/segmentation/strategies/compositions/dynamicThreshold.js +5 -1
  183. package/dist/esm/tools/segmentation/strategies/compositions/islandRemovalComposition.js +2 -2
  184. package/dist/esm/tools/segmentation/strategies/compositions/preview.js +2 -2
  185. package/dist/esm/tools/segmentation/strategies/compositions/setValue.js +14 -6
  186. package/dist/esm/tools/segmentation/strategies/fillCircle.d.ts +3 -1
  187. package/dist/esm/tools/segmentation/strategies/fillCircle.js +38 -31
  188. package/dist/esm/tools/segmentation/strategies/fillSphere.js +11 -3
  189. package/dist/esm/tools/segmentation/strategies/utils/crossLayerErase.d.ts +4 -0
  190. package/dist/esm/tools/segmentation/strategies/utils/crossLayerErase.js +23 -0
  191. package/dist/esm/tools/segmentation/strategies/utils/getStrategyData.js +1 -1
  192. package/dist/esm/tools/segmentation/strategies/utils/handleUseSegmentCenterIndex.js +12 -11
  193. package/dist/esm/tools/segmentation/strategies/utils/labelmapOverlap.d.ts +4 -0
  194. package/dist/esm/tools/segmentation/strategies/utils/labelmapOverlap.js +41 -0
  195. package/dist/esm/tools/segmentation/strategies/utils/overwritePolicy.d.ts +3 -0
  196. package/dist/esm/tools/segmentation/strategies/utils/overwritePolicy.js +31 -0
  197. package/dist/esm/tools/segmentation/strategies/utils/segmentSeparation.d.ts +3 -0
  198. package/dist/esm/tools/segmentation/strategies/utils/segmentSeparation.js +38 -0
  199. package/dist/esm/tools/segmentation/utils/LazyBrushEditController.d.ts +19 -0
  200. package/dist/esm/tools/segmentation/utils/LazyBrushEditController.js +55 -0
  201. package/dist/esm/tools/segmentation/utils/lazyBrushPreview.d.ts +3 -0
  202. package/dist/esm/tools/segmentation/utils/lazyBrushPreview.js +34 -0
  203. package/dist/esm/tools/segmentation/utils/shouldUseLazyLabelmapEditing.d.ts +3 -0
  204. package/dist/esm/tools/segmentation/utils/shouldUseLazyLabelmapEditing.js +42 -0
  205. package/dist/esm/types/ISynchronizerEventHandler.d.ts +2 -1
  206. package/dist/esm/types/LabelmapToolOperationData.d.ts +5 -0
  207. package/dist/esm/types/LabelmapTypes.d.ts +29 -6
  208. package/dist/esm/types/SegmentationStateTypes.d.ts +6 -0
  209. package/dist/esm/utilities/boundingBox/index.d.ts +2 -1
  210. package/dist/esm/utilities/boundingBox/index.js +2 -1
  211. package/dist/esm/utilities/boundingBox/snapIndexBounds.d.ts +3 -0
  212. package/dist/esm/utilities/boundingBox/snapIndexBounds.js +9 -0
  213. package/dist/esm/utilities/calibrateImageSpacing.js +17 -2
  214. package/dist/esm/utilities/contours/AnnotationToPointData.js +1 -1
  215. package/dist/esm/utilities/draw3D/addLine3DBetweenPoints.d.ts +7 -0
  216. package/dist/esm/utilities/draw3D/addLine3DBetweenPoints.js +34 -0
  217. package/dist/esm/utilities/draw3D/calculateAdaptiveSphereRadius.d.ts +6 -0
  218. package/dist/esm/utilities/draw3D/calculateAdaptiveSphereRadius.js +7 -0
  219. package/dist/esm/utilities/draw3D/index.d.ts +2 -0
  220. package/dist/esm/utilities/draw3D/index.js +2 -0
  221. package/dist/esm/utilities/drawing/getTextBoxCoordsCanvas.js +22 -14
  222. package/dist/esm/utilities/getCenterAndRadiusInCanvas.d.ts +6 -0
  223. package/dist/esm/utilities/getCenterAndRadiusInCanvas.js +26 -0
  224. package/dist/esm/utilities/getEllipseWorldCoordinates.d.ts +2 -0
  225. package/dist/esm/utilities/getEllipseWorldCoordinates.js +26 -0
  226. package/dist/esm/utilities/getSphereBoundsInfo.js +5 -1
  227. package/dist/esm/utilities/getViewportICamera.d.ts +4 -0
  228. package/dist/esm/utilities/getViewportICamera.js +23 -0
  229. package/dist/esm/utilities/getViewportsForAnnotation.js +5 -1
  230. package/dist/esm/utilities/index.d.ts +2 -1
  231. package/dist/esm/utilities/index.js +2 -1
  232. package/dist/esm/utilities/interactionDragCoordinator.d.ts +5 -0
  233. package/dist/esm/utilities/interactionDragCoordinator.js +16 -0
  234. package/dist/esm/utilities/math/basic/BasicStatsCalculator.js +9 -7
  235. package/dist/esm/utilities/pointInSurroundingSphereCallback.js +8 -1
  236. package/dist/esm/utilities/segmentation/InterpolationManager/InterpolationManager.js +121 -118
  237. package/dist/esm/utilities/segmentation/SegmentStatsCalculator.js +5 -4
  238. package/dist/esm/utilities/segmentation/VolumetricCalculator.js +1 -1
  239. package/dist/esm/utilities/segmentation/createLabelmapVolumeForViewport.js +1 -1
  240. package/dist/esm/utilities/segmentation/getReferenceVolumeForSegmentation.js +1 -1
  241. package/dist/esm/utilities/segmentation/getReferenceVolumeForSegmentationVolume.js +11 -2
  242. package/dist/esm/utilities/segmentation/getSegmentIndexAtLabelmapBorder.js +36 -17
  243. package/dist/esm/utilities/segmentation/getSegmentIndexAtWorldPoint.js +42 -25
  244. package/dist/esm/utilities/segmentation/getUniqueSegmentIndices.js +3 -30
  245. package/dist/esm/utilities/segmentation/index.d.ts +2 -1
  246. package/dist/esm/utilities/segmentation/index.js +2 -1
  247. package/dist/esm/utilities/segmentation/utilsForWorker.js +6 -2
  248. package/dist/esm/utilities/segmentation/validateLabelmap.js +1 -1
  249. package/dist/esm/utilities/stackPrefetch/stackPrefetch.js +0 -1
  250. package/dist/esm/utilities/touch/index.js +3 -2
  251. package/dist/esm/utilities/viewportCapabilities.d.ts +16 -0
  252. package/dist/esm/utilities/viewportCapabilities.js +18 -0
  253. package/dist/esm/utilities/viewportFilters/filterViewportsWithParallelNormals.d.ts +1 -1
  254. package/dist/esm/utilities/viewportFilters/filterViewportsWithParallelNormals.js +12 -4
  255. package/dist/esm/utilities/viewportFilters/filterViewportsWithSameOrientation.d.ts +1 -1
  256. package/dist/esm/utilities/viewportFilters/filterViewportsWithSameOrientation.js +11 -4
  257. package/dist/esm/utilities/viewportFilters/getViewportIdsWithToolToRender.js +1 -1
  258. package/dist/esm/utilities/viewportPresentation.d.ts +3 -0
  259. package/dist/esm/utilities/viewportPresentation.js +26 -0
  260. package/dist/esm/utilities/volumeCropping/computePlanePlaneIntersection.d.ts +6 -0
  261. package/dist/esm/utilities/volumeCropping/computePlanePlaneIntersection.js +37 -0
  262. package/dist/esm/utilities/volumeCropping/constants.d.ts +31 -0
  263. package/dist/esm/utilities/volumeCropping/constants.js +31 -0
  264. package/dist/esm/utilities/volumeCropping/copyClippingPlanes.d.ts +2 -0
  265. package/dist/esm/utilities/volumeCropping/copyClippingPlanes.js +6 -0
  266. package/dist/esm/utilities/volumeCropping/extractVolumeDirectionVectors.d.ts +9 -0
  267. package/dist/esm/utilities/volumeCropping/extractVolumeDirectionVectors.js +9 -0
  268. package/dist/esm/utilities/volumeCropping/findLineBoundsIntersection.d.ts +5 -0
  269. package/dist/esm/utilities/volumeCropping/findLineBoundsIntersection.js +50 -0
  270. package/dist/esm/utilities/volumeCropping/getColorKeyForPlaneIndex.d.ts +1 -0
  271. package/dist/esm/utilities/volumeCropping/getColorKeyForPlaneIndex.js +13 -0
  272. package/dist/esm/utilities/volumeCropping/getOrientationFromNormal.d.ts +2 -0
  273. package/dist/esm/utilities/volumeCropping/getOrientationFromNormal.js +19 -0
  274. package/dist/esm/utilities/volumeCropping/index.d.ts +9 -0
  275. package/dist/esm/utilities/volumeCropping/index.js +9 -0
  276. package/dist/esm/utilities/volumeCropping/parseCornerKey.d.ts +8 -0
  277. package/dist/esm/utilities/volumeCropping/parseCornerKey.js +11 -0
  278. package/dist/esm/utilities/volumeCropping/types.d.ts +5 -0
  279. package/dist/esm/utilities/volumeCropping/types.js +0 -0
  280. package/dist/esm/utilities/vtkjs/AnnotatedRhombicuboctahedronActor/index.d.ts +31 -0
  281. package/dist/esm/utilities/vtkjs/AnnotatedRhombicuboctahedronActor/index.js +391 -0
  282. package/dist/esm/utilities/vtkjs/OrientationControllerWidget/index.d.ts +69 -0
  283. package/dist/esm/utilities/vtkjs/OrientationControllerWidget/index.js +804 -0
  284. package/dist/esm/utilities/vtkjs/RhombicuboctahedronSource/index.d.ts +7 -0
  285. package/dist/esm/utilities/vtkjs/RhombicuboctahedronSource/index.js +144 -0
  286. package/dist/esm/utilities/vtkjs/index.d.ts +3 -0
  287. package/dist/esm/utilities/vtkjs/index.js +3 -0
  288. package/dist/esm/version.d.ts +1 -1
  289. package/dist/esm/version.js +1 -1
  290. package/package.json +10 -9
@@ -0,0 +1,804 @@
1
+ import vtkCellPicker from '@kitware/vtk.js/Rendering/Core/CellPicker';
2
+ import vtkActor from '@kitware/vtk.js/Rendering/Core/Actor';
3
+ import vtkCellArray from '@kitware/vtk.js/Common/Core/CellArray';
4
+ import vtkMapper from '@kitware/vtk.js/Rendering/Core/Mapper';
5
+ import vtkPoints from '@kitware/vtk.js/Common/Core/Points';
6
+ import vtkPolyData from '@kitware/vtk.js/Common/DataModel/PolyData';
7
+ import vtkRenderer from '@kitware/vtk.js/Rendering/Core/Renderer';
8
+ import { Enums } from '@cornerstonejs/core';
9
+ import vtkAnnotatedRhombicuboctahedronActor from '../AnnotatedRhombicuboctahedronActor';
10
+ import { beginOwnedDrag, endOwnedDrag } from '../../interactionDragCoordinator';
11
+ export class vtkOrientationControllerWidget {
12
+ constructor() {
13
+ this.actors = new Map();
14
+ this.pickers = new Map();
15
+ this.overlayRenderers = new Map();
16
+ this.renderWindows = new Map();
17
+ this.highlightedFace = null;
18
+ this.mouseHandlers = new Map();
19
+ this._highlightColor = [255, 255, 255];
20
+ this._restingAmbient = 1.0;
21
+ this._hoverAmbient = 1.0;
22
+ }
23
+ createActors(config) {
24
+ const rgbToHex = (rgb) => {
25
+ return `#${rgb
26
+ .map((x) => {
27
+ const hex = Math.round(x).toString(16);
28
+ return hex.length === 1 ? '0' + hex : hex;
29
+ })
30
+ .join('')}`;
31
+ };
32
+ const rgbToHexColor = (rgb) => {
33
+ return `rgb(${rgb[0]}, ${rgb[1]}, ${rgb[2]})`;
34
+ };
35
+ const actorFactory = vtkAnnotatedRhombicuboctahedronActor.newInstance({
36
+ edgeColor: config.edgeColor ?? [200, 200, 200],
37
+ cornerColor: config.cornerColor ?? [150, 150, 150],
38
+ });
39
+ const defaultStyle = {
40
+ fontStyle: 'bold',
41
+ fontFamily: 'Arial',
42
+ fontColor: 'black',
43
+ fontSizeScale: (res) => res / 2,
44
+ faceColor: rgbToHex(config.faceColors.topBottom),
45
+ edgeThickness: 0.1,
46
+ edgeColor: 'black',
47
+ resolution: 400,
48
+ };
49
+ actorFactory.setDefaultStyle(defaultStyle);
50
+ actorFactory.setXPlusFaceProperty({
51
+ text: 'L',
52
+ faceColor: rgbToHex(config.faceColors.leftRight),
53
+ fontColor: rgbToHexColor(config.letterColors.xPlus),
54
+ faceRotation: 0,
55
+ });
56
+ actorFactory.setXMinusFaceProperty({
57
+ text: 'R',
58
+ faceColor: rgbToHex(config.faceColors.leftRight),
59
+ fontColor: rgbToHexColor(config.letterColors.xMinus),
60
+ faceRotation: 0,
61
+ });
62
+ actorFactory.setYPlusFaceProperty({
63
+ text: 'P',
64
+ faceColor: rgbToHex(config.faceColors.frontBack),
65
+ fontColor: rgbToHexColor(config.letterColors.yPlus),
66
+ faceRotation: 180,
67
+ });
68
+ actorFactory.setYMinusFaceProperty({
69
+ text: 'A',
70
+ faceColor: rgbToHex(config.faceColors.frontBack),
71
+ fontColor: rgbToHexColor(config.letterColors.yMinus),
72
+ faceRotation: 0,
73
+ });
74
+ actorFactory.setZPlusFaceProperty({
75
+ text: 'S',
76
+ faceColor: rgbToHex(config.faceColors.topBottom),
77
+ fontColor: rgbToHexColor(config.letterColors.zPlus),
78
+ });
79
+ actorFactory.setZMinusFaceProperty({
80
+ text: 'I',
81
+ faceColor: rgbToHex(config.faceColors.topBottom),
82
+ fontColor: rgbToHexColor(config.letterColors.zMinus),
83
+ });
84
+ actorFactory.setShowMainFaces(true);
85
+ actorFactory.setShowEdgeFaces(config.showEdgeFaces);
86
+ actorFactory.setShowCornerFaces(config.showCornerFaces);
87
+ const actors = actorFactory.getActors();
88
+ this._highlightColor = config.highlightColor ?? [255, 255, 255];
89
+ this._restingAmbient = config.restingAmbient ?? 1.0;
90
+ this._hoverAmbient = config.hoverAmbient ?? 1.0;
91
+ actors.forEach((actor) => {
92
+ const property = actor.getProperty();
93
+ property.setOpacity(config.opacity);
94
+ property.setAmbient(this._restingAmbient);
95
+ actor.setVisibility(true);
96
+ });
97
+ return actors;
98
+ }
99
+ addActorsToViewport(viewportId, viewport, actors) {
100
+ const existingActors = this.actors.get(viewportId);
101
+ if (existingActors) {
102
+ this.removeActorsFromViewport(viewportId, viewport);
103
+ }
104
+ const renderWindow = viewport
105
+ .getRenderingEngine()
106
+ .getOffscreenMultiRenderWindow(viewport.id)
107
+ .getRenderWindow();
108
+ const mainRenderer = viewport
109
+ .getRenderingEngine()
110
+ ?.getRenderer(viewportId) ?? viewport.getRenderer();
111
+ const vtkMainRenderer = mainRenderer;
112
+ const overlayRenderer = vtkRenderer.newInstance();
113
+ overlayRenderer.setLayer(1);
114
+ overlayRenderer.setInteractive(false);
115
+ overlayRenderer.setPreserveColorBuffer(true);
116
+ overlayRenderer.setActiveCamera(vtkMainRenderer.getActiveCamera());
117
+ const vp = vtkMainRenderer.getViewport();
118
+ overlayRenderer.setViewport(...vp);
119
+ if (renderWindow.getNumberOfLayers() < 2) {
120
+ renderWindow.setNumberOfLayers(2);
121
+ }
122
+ renderWindow.addRenderer(overlayRenderer);
123
+ actors.forEach((actor) => {
124
+ overlayRenderer.addActor(actor);
125
+ });
126
+ this.actors.set(viewportId, actors);
127
+ this.overlayRenderers.set(viewportId, overlayRenderer);
128
+ this.renderWindows.set(viewportId, renderWindow);
129
+ }
130
+ removeActorsFromViewport(viewportId, _viewport) {
131
+ const actors = this.actors.get(viewportId);
132
+ const overlayRenderer = this.overlayRenderers.get(viewportId);
133
+ const renderWindow = this.renderWindows.get(viewportId);
134
+ if (actors && overlayRenderer) {
135
+ actors.forEach((actor) => {
136
+ overlayRenderer.removeActor(actor);
137
+ });
138
+ if (renderWindow) {
139
+ renderWindow.removeRenderer(overlayRenderer);
140
+ }
141
+ overlayRenderer.delete();
142
+ }
143
+ this.actors.delete(viewportId);
144
+ this.overlayRenderers.delete(viewportId);
145
+ this.renderWindows.delete(viewportId);
146
+ }
147
+ setupPicker(viewportId, actors) {
148
+ const picker = vtkCellPicker.newInstance({ opacityThreshold: 0.0001 });
149
+ picker.setPickFromList(true);
150
+ picker.setTolerance(0.001);
151
+ picker.initializePickList();
152
+ actors.forEach((actor) => {
153
+ picker.addPickList(actor);
154
+ });
155
+ this.pickers.set(viewportId, picker);
156
+ return picker;
157
+ }
158
+ pickAtPosition(evt, viewportId, viewport, element, actors) {
159
+ const picker = this.pickers.get(viewportId);
160
+ if (!picker) {
161
+ return null;
162
+ }
163
+ const renderer = this.overlayRenderers.get(viewportId) ??
164
+ viewport
165
+ .getRenderingEngine()
166
+ ?.getRenderer(viewportId) ??
167
+ viewport.getRenderer();
168
+ if (!renderer) {
169
+ return null;
170
+ }
171
+ const rect = element.getBoundingClientRect();
172
+ const x = evt.clientX - rect.left;
173
+ const y = evt.clientY - rect.top;
174
+ const devicePixelRatio = window.devicePixelRatio || 1;
175
+ const canvasPosWithDPR = [x * devicePixelRatio, y * devicePixelRatio];
176
+ const canvas = viewport.canvas;
177
+ const { width, height } = canvas;
178
+ const [xMin, yMin, xMax, yMax] = renderer.getViewport();
179
+ const viewportWidth = xMax - xMin;
180
+ const viewportHeight = yMax - yMin;
181
+ const scaledX = (canvasPosWithDPR[0] / width) * viewportWidth * width;
182
+ const scaledY = (canvasPosWithDPR[1] / height) * viewportHeight * height;
183
+ const displayCoord = [scaledX, viewportHeight * height - scaledY];
184
+ const displayCoords = [
185
+ displayCoord[0],
186
+ displayCoord[1],
187
+ 0,
188
+ ];
189
+ picker.pick(displayCoords, renderer);
190
+ const pickedActors = picker.getActors();
191
+ if (pickedActors.length === 0) {
192
+ return null;
193
+ }
194
+ const pickedActor = pickedActors[0];
195
+ const cellId = picker.getCellId();
196
+ if (actors.includes(pickedActor) && cellId !== -1) {
197
+ const actorIndex = actors.indexOf(pickedActor);
198
+ return { pickedActor, cellId, actorIndex };
199
+ }
200
+ return null;
201
+ }
202
+ calculateMarkerPosition(viewport, position, screenSizePixels) {
203
+ const canvas = viewport.canvas;
204
+ if (!canvas) {
205
+ return null;
206
+ }
207
+ const devicePixelRatio = window.devicePixelRatio || 1;
208
+ const canvasWidth = canvas.clientWidth || canvas.width / devicePixelRatio;
209
+ const canvasHeight = canvas.clientHeight || canvas.height / devicePixelRatio;
210
+ const marginRatio = viewport.type === Enums.ViewportType.VOLUME_3D ? 1.3 : 1.1;
211
+ const marginPxRaw = marginRatio * screenSizePixels;
212
+ const halfPx = screenSizePixels * 0.5;
213
+ const maxMarginX = Math.max(0, (canvasWidth - screenSizePixels) / 2);
214
+ const maxMarginY = Math.max(0, (canvasHeight - screenSizePixels) / 2);
215
+ const marginPx = Math.min(marginPxRaw, maxMarginX, maxMarginY);
216
+ let canvasX;
217
+ let canvasY;
218
+ switch (position) {
219
+ case 'top-left':
220
+ canvasX = marginPx + halfPx;
221
+ canvasY = marginPx + halfPx;
222
+ break;
223
+ case 'top-right':
224
+ canvasX = canvasWidth - marginPx - halfPx;
225
+ canvasY = marginPx + halfPx;
226
+ break;
227
+ case 'bottom-left':
228
+ canvasX = marginPx + halfPx;
229
+ canvasY = canvasHeight - marginPx - halfPx;
230
+ break;
231
+ default:
232
+ canvasX = canvasWidth - marginPx - halfPx;
233
+ canvasY = canvasHeight - marginPx - halfPx;
234
+ }
235
+ const canvasPos = [canvasX, canvasY];
236
+ const worldPos = viewport.canvasToWorld(canvasPos);
237
+ return [worldPos[0], worldPos[1], worldPos[2]];
238
+ }
239
+ positionActors(viewport, actors, config) {
240
+ const canvas = viewport.canvas;
241
+ if (!canvas) {
242
+ console.warn('OrientationControllerWidget: No canvas available');
243
+ return false;
244
+ }
245
+ const mainRenderer = viewport
246
+ .getRenderingEngine()
247
+ ?.getRenderer(viewport.id) ?? viewport.getRenderer();
248
+ const camera = mainRenderer?.getActiveCamera();
249
+ if (!camera) {
250
+ return false;
251
+ }
252
+ const parallelScale = camera.getParallelScale();
253
+ const worldHeight = parallelScale * 2;
254
+ const devicePixelRatio = window.devicePixelRatio || 1;
255
+ const canvasHeight = canvas.clientHeight || canvas.height / devicePixelRatio;
256
+ const canvasWidth = canvas.clientWidth || canvas.width / devicePixelRatio;
257
+ const worldUnitsPerPixel = worldHeight / canvasHeight;
258
+ const canvasSize = Math.min(canvasWidth, canvasHeight);
259
+ const screenSizePixels = canvasSize * config.size;
260
+ const markerSize = screenSizePixels * worldUnitsPerPixel;
261
+ actors.forEach((actor) => {
262
+ actor.setScale(markerSize, markerSize, markerSize);
263
+ const worldPos = this.calculateMarkerPosition(viewport, config.position, screenSizePixels);
264
+ if (!worldPos) {
265
+ console.warn('OrientationControllerWidget: Could not get world position');
266
+ return;
267
+ }
268
+ actor.setPosition(worldPos[0], worldPos[1], worldPos[2]);
269
+ actor.setOrientation(0, 0, 0);
270
+ });
271
+ return true;
272
+ }
273
+ highlightFace(actor, cellId, viewport, isMainFace = false) {
274
+ if (this.highlightedFace &&
275
+ this.highlightedFace.actor === actor &&
276
+ this.highlightedFace.cellId === cellId &&
277
+ this.highlightedFace.isMainFace === isMainFace) {
278
+ return;
279
+ }
280
+ this.clearHighlight();
281
+ if (isMainFace) {
282
+ const textureCollection = actor.getTextures?.();
283
+ const textureCandidate = Array.isArray(textureCollection)
284
+ ? textureCollection[0]
285
+ : textureCollection?.getItem?.(0);
286
+ const texture = textureCandidate;
287
+ const imageData = texture?.getInputData?.();
288
+ const scalars = imageData?.getPointData().getScalars();
289
+ const pixels = scalars?.getData();
290
+ const dims = imageData?.getDimensions();
291
+ if (!imageData ||
292
+ !scalars ||
293
+ !pixels ||
294
+ !dims ||
295
+ cellId < 0 ||
296
+ cellId > 5) {
297
+ const mapper = actor.getMapper();
298
+ const polyData = mapper.getInputData();
299
+ if (!polyData?.getCellPoints) {
300
+ return;
301
+ }
302
+ const { cellPointIds } = polyData.getCellPoints(cellId);
303
+ if (!cellPointIds || cellPointIds.length < 3) {
304
+ return;
305
+ }
306
+ const src = polyData.getPoints().getData();
307
+ const coords = [];
308
+ Array.from(cellPointIds).forEach((pid) => {
309
+ const o = pid * 3;
310
+ coords.push(src[o], src[o + 1], src[o + 2]);
311
+ });
312
+ const points = vtkPoints.newInstance();
313
+ points.setData(new Float32Array(coords), 3);
314
+ const polys = vtkCellArray.newInstance({
315
+ values: new Uint32Array([
316
+ cellPointIds.length,
317
+ ...Array.from(cellPointIds, (_, i) => i),
318
+ ]),
319
+ });
320
+ const poly = vtkPolyData.newInstance();
321
+ poly.setPoints(points);
322
+ poly.setPolys(polys);
323
+ const faceMapper = vtkMapper.newInstance();
324
+ faceMapper.setInputData(poly);
325
+ const faceActor = vtkActor.newInstance();
326
+ faceActor.setMapper(faceMapper);
327
+ const [sx, sy, sz] = actor.getScale();
328
+ const [px, py, pz] = actor.getPosition();
329
+ const [ox, oy, oz] = actor.getOrientation();
330
+ faceActor.setScale(sx, sy, sz);
331
+ faceActor.setPosition(px, py, pz);
332
+ faceActor.setOrientation(ox, oy, oz);
333
+ faceActor.setPickable(false);
334
+ const p = faceActor.getProperty();
335
+ p.setLighting(false);
336
+ p.setAmbient(1);
337
+ p.setDiffuse(0);
338
+ p.setColor(1, 1, 1);
339
+ p.setOpacity(0.58);
340
+ this.overlayRenderers.get(viewport.id)?.addActor(faceActor);
341
+ this.highlightedFace = {
342
+ actor,
343
+ cellId,
344
+ originalColor: [0, 0, 0, 0],
345
+ viewport,
346
+ isMainFace: true,
347
+ mainFaceHighlightActor: faceActor,
348
+ };
349
+ viewport.render();
350
+ return;
351
+ }
352
+ const [imageWidth, imageHeight] = dims;
353
+ const tileWidth = Math.floor(imageWidth / 3);
354
+ const tileHeight = Math.floor(imageHeight / 2);
355
+ const tileCol = cellId % 3;
356
+ const tileRow = Math.floor(cellId / 3);
357
+ const x0 = tileCol * tileWidth;
358
+ const y0 = tileRow * tileHeight;
359
+ const tileBackup = new Uint8Array(tileWidth * tileHeight * 4);
360
+ let b = 0;
361
+ for (let y = 0; y < tileHeight; y++) {
362
+ for (let x = 0; x < tileWidth; x++) {
363
+ const srcIndex = ((y0 + y) * imageWidth + (x0 + x)) * 4;
364
+ tileBackup[b++] = pixels[srcIndex];
365
+ tileBackup[b++] = pixels[srcIndex + 1];
366
+ tileBackup[b++] = pixels[srcIndex + 2];
367
+ tileBackup[b++] = pixels[srcIndex + 3];
368
+ }
369
+ }
370
+ const bgSampleIndices = [
371
+ ((y0 + 8) * imageWidth + (x0 + 8)) * 4,
372
+ ((y0 + 8) * imageWidth + (x0 + tileWidth - 9)) * 4,
373
+ ((y0 + tileHeight - 9) * imageWidth + (x0 + 8)) * 4,
374
+ ((y0 + tileHeight - 9) * imageWidth + (x0 + tileWidth - 9)) * 4,
375
+ ];
376
+ const bgColor = [0, 0, 0];
377
+ bgSampleIndices.forEach((idx) => {
378
+ bgColor[0] += pixels[idx];
379
+ bgColor[1] += pixels[idx + 1];
380
+ bgColor[2] += pixels[idx + 2];
381
+ });
382
+ bgColor[0] /= bgSampleIndices.length;
383
+ bgColor[1] /= bgSampleIndices.length;
384
+ bgColor[2] /= bgSampleIndices.length;
385
+ const glyphThreshold = 42;
386
+ const faceBrighten = 72;
387
+ const isGlyphPixel = (x, y) => {
388
+ if (x < 0 || x >= tileWidth || y < 0 || y >= tileHeight) {
389
+ return false;
390
+ }
391
+ const idx = ((y0 + y) * imageWidth + (x0 + x)) * 4;
392
+ const dr = pixels[idx] - bgColor[0];
393
+ const dg = pixels[idx + 1] - bgColor[1];
394
+ const db = pixels[idx + 2] - bgColor[2];
395
+ return Math.sqrt(dr * dr + dg * dg + db * db) >= glyphThreshold;
396
+ };
397
+ const borderWidth = Math.max(4, Math.floor(tileWidth * 0.035));
398
+ for (let y = 0; y < tileHeight; y++) {
399
+ for (let x = 0; x < tileWidth; x++) {
400
+ const onBorder = x < borderWidth ||
401
+ x >= tileWidth - borderWidth ||
402
+ y < borderWidth ||
403
+ y >= tileHeight - borderWidth;
404
+ if (onBorder || isGlyphPixel(x, y)) {
405
+ continue;
406
+ }
407
+ const idx = ((y0 + y) * imageWidth + (x0 + x)) * 4;
408
+ pixels[idx] = Math.min(255, pixels[idx] + faceBrighten);
409
+ pixels[idx + 1] = Math.min(255, pixels[idx + 1] + faceBrighten);
410
+ pixels[idx + 2] = Math.min(255, pixels[idx + 2] + faceBrighten);
411
+ }
412
+ }
413
+ for (let y = 0; y < tileHeight; y++) {
414
+ for (let x = 0; x < tileWidth; x++) {
415
+ const onBorder = x < borderWidth ||
416
+ x >= tileWidth - borderWidth ||
417
+ y < borderWidth ||
418
+ y >= tileHeight - borderWidth;
419
+ if (!onBorder) {
420
+ continue;
421
+ }
422
+ const idx = ((y0 + y) * imageWidth + (x0 + x)) * 4;
423
+ pixels[idx] = 0;
424
+ pixels[idx + 1] = 0;
425
+ pixels[idx + 2] = 0;
426
+ }
427
+ }
428
+ scalars.modified();
429
+ imageData.modified();
430
+ texture.modified?.();
431
+ actor.modified?.();
432
+ this.highlightedFace = {
433
+ actor,
434
+ cellId,
435
+ originalColor: [0, 0, 0, 0],
436
+ viewport,
437
+ isMainFace: true,
438
+ mainFaceTextureData: tileBackup,
439
+ mainFaceTile: {
440
+ x0,
441
+ y0,
442
+ width: tileWidth,
443
+ height: tileHeight,
444
+ imageWidth,
445
+ },
446
+ };
447
+ viewport.render();
448
+ return;
449
+ }
450
+ const mapper = actor.getMapper();
451
+ const inputData = mapper.getInputData();
452
+ if (!inputData) {
453
+ return;
454
+ }
455
+ const cellData = inputData.getCellData();
456
+ const colors = cellData.getScalars();
457
+ if (!colors) {
458
+ return;
459
+ }
460
+ const colorArray = colors.getData();
461
+ const offset = cellId * 4;
462
+ const originalColor = [
463
+ colorArray[offset],
464
+ colorArray[offset + 1],
465
+ colorArray[offset + 2],
466
+ colorArray[offset + 3],
467
+ ];
468
+ this.highlightedFace = {
469
+ actor,
470
+ cellId,
471
+ originalColor,
472
+ viewport,
473
+ isMainFace: false,
474
+ };
475
+ const hc = this._highlightColor;
476
+ colorArray[offset] = hc[0];
477
+ colorArray[offset + 1] = hc[1];
478
+ colorArray[offset + 2] = hc[2];
479
+ colorArray[offset + 3] = 255;
480
+ colors.modified();
481
+ inputData.modified();
482
+ viewport.render();
483
+ }
484
+ clearHighlight() {
485
+ if (!this.highlightedFace) {
486
+ return;
487
+ }
488
+ const { actor, cellId, originalColor, viewport, isMainFace } = this.highlightedFace;
489
+ if (isMainFace) {
490
+ const backup = this.highlightedFace.mainFaceTextureData;
491
+ const tile = this.highlightedFace.mainFaceTile;
492
+ const textures = actor.getTextures?.();
493
+ const texture = textures?.[0];
494
+ const imageData = texture?.getInputData?.();
495
+ const scalars = imageData?.getPointData().getScalars();
496
+ const pixels = scalars?.getData();
497
+ if (backup && tile && scalars && imageData && pixels) {
498
+ let b = 0;
499
+ for (let y = 0; y < tile.height; y++) {
500
+ for (let x = 0; x < tile.width; x++) {
501
+ const dstIndex = ((tile.y0 + y) * tile.imageWidth + (tile.x0 + x)) * 4;
502
+ pixels[dstIndex] = backup[b++];
503
+ pixels[dstIndex + 1] = backup[b++];
504
+ pixels[dstIndex + 2] = backup[b++];
505
+ pixels[dstIndex + 3] = backup[b++];
506
+ }
507
+ }
508
+ scalars.modified();
509
+ imageData.modified();
510
+ texture.modified?.();
511
+ actor.modified?.();
512
+ }
513
+ else if (this.highlightedFace.mainFaceHighlightActor) {
514
+ const overlayRenderer = this.overlayRenderers.get(viewport.id);
515
+ overlayRenderer?.removeActor(this.highlightedFace.mainFaceHighlightActor);
516
+ this.highlightedFace.mainFaceHighlightActor.delete();
517
+ }
518
+ viewport.render();
519
+ this.highlightedFace = null;
520
+ return;
521
+ }
522
+ const mapper = actor.getMapper();
523
+ const inputData = mapper.getInputData();
524
+ if (!inputData) {
525
+ this.highlightedFace = null;
526
+ return;
527
+ }
528
+ const cellData = inputData.getCellData();
529
+ const colors = cellData.getScalars();
530
+ if (!colors) {
531
+ this.highlightedFace = null;
532
+ return;
533
+ }
534
+ const colorArray = colors.getData();
535
+ const offset = cellId * 4;
536
+ colorArray[offset] = originalColor[0];
537
+ colorArray[offset + 1] = originalColor[1];
538
+ colorArray[offset + 2] = originalColor[2];
539
+ colorArray[offset + 3] = originalColor[3];
540
+ colors.modified();
541
+ inputData.modified();
542
+ viewport.render();
543
+ this.highlightedFace = null;
544
+ }
545
+ setupMouseHandlers(viewportId, element, viewport, actors, callbacks) {
546
+ let isMouseDown = false;
547
+ let isCubeHovered = false;
548
+ const setAmbient = (full) => {
549
+ actors.forEach((actor) => {
550
+ const property = actor.getProperty();
551
+ property.setAmbient(full ? this._hoverAmbient : this._restingAmbient);
552
+ });
553
+ viewport.render();
554
+ };
555
+ let didDrag = false;
556
+ let pendingPickResult = null;
557
+ let mouseDownCanvas = null;
558
+ const clickTolerancePx = 3;
559
+ const hoverHandler = (evt) => {
560
+ if (isMouseDown) {
561
+ if (mouseDownCanvas) {
562
+ const dx = evt.clientX - mouseDownCanvas.x;
563
+ const dy = evt.clientY - mouseDownCanvas.y;
564
+ if (dx * dx + dy * dy > clickTolerancePx * clickTolerancePx) {
565
+ didDrag = true;
566
+ }
567
+ }
568
+ return;
569
+ }
570
+ const pickResult = this.pickAtPosition(evt, viewportId, viewport, element, actors);
571
+ if (pickResult) {
572
+ if (!isCubeHovered) {
573
+ isCubeHovered = true;
574
+ setAmbient(true);
575
+ }
576
+ const { pickedActor, cellId, actorIndex } = pickResult;
577
+ this.highlightFace(pickedActor, cellId, viewport, actorIndex === 0);
578
+ if (callbacks.onFaceHover) {
579
+ callbacks.onFaceHover(pickResult);
580
+ }
581
+ }
582
+ else {
583
+ if (isCubeHovered) {
584
+ isCubeHovered = false;
585
+ setAmbient(false);
586
+ }
587
+ this.clearHighlight();
588
+ if (callbacks.onFaceHover) {
589
+ callbacks.onFaceHover(null);
590
+ }
591
+ }
592
+ };
593
+ const clickHandler = (evt) => {
594
+ if (evt.button !== 0) {
595
+ return;
596
+ }
597
+ const pickResult = this.pickAtPosition(evt, viewportId, viewport, element, actors);
598
+ if (!pickResult) {
599
+ return;
600
+ }
601
+ isMouseDown = true;
602
+ didDrag = false;
603
+ pendingPickResult = pickResult;
604
+ mouseDownCanvas = { x: evt.clientX, y: evt.clientY };
605
+ beginOwnedDrag(viewportId, 'orientation-controller');
606
+ };
607
+ const mouseUpHandler = (evt) => {
608
+ if (isMouseDown && !didDrag && pendingPickResult) {
609
+ let globalCellId = pendingPickResult.cellId;
610
+ if (pendingPickResult.actorIndex === 1) {
611
+ globalCellId = pendingPickResult.cellId + 6;
612
+ }
613
+ else if (pendingPickResult.actorIndex === 2) {
614
+ globalCellId = pendingPickResult.cellId + 18;
615
+ }
616
+ callbacks.onFacePicked({
617
+ ...pendingPickResult,
618
+ cellId: globalCellId,
619
+ });
620
+ evt.preventDefault();
621
+ evt.stopImmediatePropagation();
622
+ evt.stopPropagation();
623
+ }
624
+ isMouseDown = false;
625
+ if (isCubeHovered) {
626
+ isCubeHovered = false;
627
+ setAmbient(false);
628
+ }
629
+ didDrag = false;
630
+ pendingPickResult = null;
631
+ mouseDownCanvas = null;
632
+ endOwnedDrag(viewportId, 'orientation-controller');
633
+ this.clearHighlight();
634
+ };
635
+ const dblclickHandler = (evt) => {
636
+ const pickResult = this.pickAtPosition(evt, viewportId, viewport, element, actors);
637
+ if (pickResult) {
638
+ evt.preventDefault();
639
+ evt.stopImmediatePropagation();
640
+ }
641
+ };
642
+ element.addEventListener('mousemove', hoverHandler, true);
643
+ element.addEventListener('mousedown', clickHandler, true);
644
+ element.addEventListener('mouseup', mouseUpHandler);
645
+ element.addEventListener('mouseleave', mouseUpHandler);
646
+ element.addEventListener('dblclick', dblclickHandler, true);
647
+ const cleanup = () => {
648
+ element.removeEventListener('mousemove', hoverHandler, true);
649
+ element.removeEventListener('mousedown', clickHandler, true);
650
+ element.removeEventListener('mouseup', mouseUpHandler);
651
+ element.removeEventListener('mouseleave', mouseUpHandler);
652
+ element.removeEventListener('dblclick', dblclickHandler, true);
653
+ endOwnedDrag(viewportId, 'orientation-controller');
654
+ };
655
+ this.mouseHandlers.set(viewportId, { cleanup });
656
+ return { cleanup };
657
+ }
658
+ getActors(viewportId) {
659
+ return this.actors.get(viewportId);
660
+ }
661
+ syncOverlayViewport(viewportId, viewport) {
662
+ const overlayRenderer = this.overlayRenderers.get(viewportId);
663
+ if (!overlayRenderer) {
664
+ return;
665
+ }
666
+ const mainRenderer = viewport
667
+ .getRenderingEngine()
668
+ ?.getRenderer(viewportId) ?? viewport.getRenderer();
669
+ if (!mainRenderer) {
670
+ return;
671
+ }
672
+ const mainVp = mainRenderer.getViewport();
673
+ overlayRenderer.setViewport(...mainVp);
674
+ }
675
+ getOrientationForFace(cellId) {
676
+ const orientations = new Map();
677
+ orientations.set(0, { viewPlaneNormal: [0, 0, -1], viewUp: [0, -1, 0] });
678
+ orientations.set(1, { viewPlaneNormal: [0, 0, 1], viewUp: [0, 1, 0] });
679
+ orientations.set(2, { viewPlaneNormal: [0, -1, 0], viewUp: [0, 0, 1] });
680
+ orientations.set(3, { viewPlaneNormal: [0, 1, 0], viewUp: [0, 0, 1] });
681
+ orientations.set(4, { viewPlaneNormal: [-1, 0, 0], viewUp: [0, 0, 1] });
682
+ orientations.set(5, { viewPlaneNormal: [1, 0, 0], viewUp: [0, 0, 1] });
683
+ const sqrt2 = 1 / Math.sqrt(2);
684
+ orientations.set(6, {
685
+ viewPlaneNormal: [0, -sqrt2, -sqrt2],
686
+ viewUp: [0, -sqrt2, sqrt2],
687
+ });
688
+ orientations.set(7, {
689
+ viewPlaneNormal: [sqrt2, 0, -sqrt2],
690
+ viewUp: [0, 0, 1],
691
+ });
692
+ orientations.set(8, {
693
+ viewPlaneNormal: [0, sqrt2, -sqrt2],
694
+ viewUp: [0, -sqrt2, -sqrt2],
695
+ });
696
+ orientations.set(9, {
697
+ viewPlaneNormal: [-sqrt2, 0, -sqrt2],
698
+ viewUp: [0, 0, 1],
699
+ });
700
+ orientations.set(10, {
701
+ viewPlaneNormal: [0, -sqrt2, sqrt2],
702
+ viewUp: [0, sqrt2, sqrt2],
703
+ });
704
+ orientations.set(11, {
705
+ viewPlaneNormal: [sqrt2, 0, sqrt2],
706
+ viewUp: [0, 0, 1],
707
+ });
708
+ orientations.set(12, {
709
+ viewPlaneNormal: [0, sqrt2, sqrt2],
710
+ viewUp: [0, sqrt2, -sqrt2],
711
+ });
712
+ orientations.set(13, {
713
+ viewPlaneNormal: [-sqrt2, 0, sqrt2],
714
+ viewUp: [0, 0, 1],
715
+ });
716
+ orientations.set(14, {
717
+ viewPlaneNormal: [-sqrt2, -sqrt2, 0],
718
+ viewUp: [0, 0, 1],
719
+ });
720
+ orientations.set(15, {
721
+ viewPlaneNormal: [sqrt2, -sqrt2, 0],
722
+ viewUp: [0, 0, 1],
723
+ });
724
+ orientations.set(16, {
725
+ viewPlaneNormal: [sqrt2, sqrt2, 0],
726
+ viewUp: [0, 0, 1],
727
+ });
728
+ orientations.set(17, {
729
+ viewPlaneNormal: [-sqrt2, sqrt2, 0],
730
+ viewUp: [0, 0, 1],
731
+ });
732
+ const sqrt3 = 1 / Math.sqrt(3);
733
+ orientations.set(18, {
734
+ viewPlaneNormal: [-sqrt3, -sqrt3, -sqrt3],
735
+ viewUp: [0, 0, 1],
736
+ });
737
+ orientations.set(19, {
738
+ viewPlaneNormal: [sqrt3, -sqrt3, -sqrt3],
739
+ viewUp: [0, 0, 1],
740
+ });
741
+ orientations.set(20, {
742
+ viewPlaneNormal: [sqrt3, sqrt3, -sqrt3],
743
+ viewUp: [0, 0, 1],
744
+ });
745
+ orientations.set(21, {
746
+ viewPlaneNormal: [-sqrt3, sqrt3, -sqrt3],
747
+ viewUp: [0, 0, 1],
748
+ });
749
+ orientations.set(22, {
750
+ viewPlaneNormal: [-sqrt3, -sqrt3, sqrt3],
751
+ viewUp: [0, 0, 1],
752
+ });
753
+ orientations.set(23, {
754
+ viewPlaneNormal: [sqrt3, -sqrt3, sqrt3],
755
+ viewUp: [0, 0, 1],
756
+ });
757
+ orientations.set(24, {
758
+ viewPlaneNormal: [sqrt3, sqrt3, sqrt3],
759
+ viewUp: [0, 0, 1],
760
+ });
761
+ orientations.set(25, {
762
+ viewPlaneNormal: [-sqrt3, sqrt3, sqrt3],
763
+ viewUp: [0, 0, 1],
764
+ });
765
+ return orientations.get(cellId) || null;
766
+ }
767
+ cleanup(viewportId) {
768
+ if (viewportId) {
769
+ const handler = this.mouseHandlers.get(viewportId);
770
+ if (handler) {
771
+ handler.cleanup();
772
+ this.mouseHandlers.delete(viewportId);
773
+ }
774
+ const overlayRenderer = this.overlayRenderers.get(viewportId);
775
+ const renderWindow = this.renderWindows.get(viewportId);
776
+ if (overlayRenderer) {
777
+ if (renderWindow) {
778
+ renderWindow.removeRenderer(overlayRenderer);
779
+ }
780
+ overlayRenderer.delete();
781
+ }
782
+ this.actors.delete(viewportId);
783
+ this.pickers.delete(viewportId);
784
+ this.overlayRenderers.delete(viewportId);
785
+ this.renderWindows.delete(viewportId);
786
+ }
787
+ else {
788
+ this.mouseHandlers.forEach((handler) => handler.cleanup());
789
+ this.mouseHandlers.clear();
790
+ this.overlayRenderers.forEach((overlayRenderer, vpId) => {
791
+ const renderWindow = this.renderWindows.get(vpId);
792
+ if (renderWindow) {
793
+ renderWindow.removeRenderer(overlayRenderer);
794
+ }
795
+ overlayRenderer.delete();
796
+ });
797
+ this.overlayRenderers.clear();
798
+ this.renderWindows.clear();
799
+ this.actors.clear();
800
+ this.pickers.clear();
801
+ }
802
+ this.clearHighlight();
803
+ }
804
+ }