@cornerstonejs/core 0.36.2 → 0.36.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (233) hide show
  1. package/dist/cjs/loaders/volumeLoader.d.ts +1 -0
  2. package/dist/cjs/loaders/volumeLoader.js +5 -1
  3. package/dist/cjs/loaders/volumeLoader.js.map +1 -1
  4. package/dist/cjs/utilities/getSliceRange.js +3 -1
  5. package/dist/cjs/utilities/getSliceRange.js.map +1 -1
  6. package/dist/cjs/utilities/getTargetVolumeAndSpacingInNormalDir.js +7 -0
  7. package/dist/cjs/utilities/getTargetVolumeAndSpacingInNormalDir.js.map +1 -1
  8. package/dist/esm/loaders/volumeLoader.d.ts +1 -0
  9. package/dist/esm/loaders/volumeLoader.js +3 -0
  10. package/dist/esm/loaders/volumeLoader.js.map +1 -1
  11. package/dist/esm/utilities/getSliceRange.js +3 -1
  12. package/dist/esm/utilities/getSliceRange.js.map +1 -1
  13. package/dist/esm/utilities/getTargetVolumeAndSpacingInNormalDir.js +7 -0
  14. package/dist/esm/utilities/getTargetVolumeAndSpacingInNormalDir.js.map +1 -1
  15. package/dist/umd/index.js +1 -1
  16. package/dist/umd/index.js.map +1 -1
  17. package/package.json +4 -3
  18. package/src/RenderingEngine/BaseVolumeViewport.ts +847 -0
  19. package/src/RenderingEngine/RenderingEngine.ts +1364 -0
  20. package/src/RenderingEngine/StackViewport.ts +2690 -0
  21. package/src/RenderingEngine/Viewport.ts +1244 -0
  22. package/src/RenderingEngine/VolumeViewport.ts +420 -0
  23. package/src/RenderingEngine/VolumeViewport3D.ts +42 -0
  24. package/src/RenderingEngine/getRenderingEngine.ts +34 -0
  25. package/src/RenderingEngine/helpers/addVolumesToViewports.ts +52 -0
  26. package/src/RenderingEngine/helpers/cpuFallback/colors/colormap.ts +343 -0
  27. package/src/RenderingEngine/helpers/cpuFallback/colors/index.ts +4 -0
  28. package/src/RenderingEngine/helpers/cpuFallback/colors/lookupTable.ts +469 -0
  29. package/src/RenderingEngine/helpers/cpuFallback/drawImageSync.ts +58 -0
  30. package/src/RenderingEngine/helpers/cpuFallback/rendering/calculateTransform.ts +136 -0
  31. package/src/RenderingEngine/helpers/cpuFallback/rendering/canvasToPixel.ts +25 -0
  32. package/src/RenderingEngine/helpers/cpuFallback/rendering/computeAutoVoi.ts +47 -0
  33. package/src/RenderingEngine/helpers/cpuFallback/rendering/correctShift.ts +38 -0
  34. package/src/RenderingEngine/helpers/cpuFallback/rendering/createViewport.ts +64 -0
  35. package/src/RenderingEngine/helpers/cpuFallback/rendering/doesImageNeedToBeRendered.ts +36 -0
  36. package/src/RenderingEngine/helpers/cpuFallback/rendering/fitToWindow.ts +22 -0
  37. package/src/RenderingEngine/helpers/cpuFallback/rendering/generateColorLUT.ts +60 -0
  38. package/src/RenderingEngine/helpers/cpuFallback/rendering/generateLut.ts +83 -0
  39. package/src/RenderingEngine/helpers/cpuFallback/rendering/getDefaultViewport.ts +88 -0
  40. package/src/RenderingEngine/helpers/cpuFallback/rendering/getImageFitScale.ts +52 -0
  41. package/src/RenderingEngine/helpers/cpuFallback/rendering/getImageSize.ts +55 -0
  42. package/src/RenderingEngine/helpers/cpuFallback/rendering/getLut.ts +53 -0
  43. package/src/RenderingEngine/helpers/cpuFallback/rendering/getModalityLut.ts +55 -0
  44. package/src/RenderingEngine/helpers/cpuFallback/rendering/getTransform.ts +17 -0
  45. package/src/RenderingEngine/helpers/cpuFallback/rendering/getVOILut.ts +74 -0
  46. package/src/RenderingEngine/helpers/cpuFallback/rendering/initializeRenderCanvas.ts +37 -0
  47. package/src/RenderingEngine/helpers/cpuFallback/rendering/lutMatches.ts +21 -0
  48. package/src/RenderingEngine/helpers/cpuFallback/rendering/now.ts +13 -0
  49. package/src/RenderingEngine/helpers/cpuFallback/rendering/pixelToCanvas.ts +22 -0
  50. package/src/RenderingEngine/helpers/cpuFallback/rendering/renderColorImage.ts +193 -0
  51. package/src/RenderingEngine/helpers/cpuFallback/rendering/renderGrayscaleImage.ts +166 -0
  52. package/src/RenderingEngine/helpers/cpuFallback/rendering/renderPseudoColorImage.ts +203 -0
  53. package/src/RenderingEngine/helpers/cpuFallback/rendering/resetCamera.ts +32 -0
  54. package/src/RenderingEngine/helpers/cpuFallback/rendering/resize.ts +109 -0
  55. package/src/RenderingEngine/helpers/cpuFallback/rendering/saveLastRendered.ts +36 -0
  56. package/src/RenderingEngine/helpers/cpuFallback/rendering/setDefaultViewport.ts +17 -0
  57. package/src/RenderingEngine/helpers/cpuFallback/rendering/setToPixelCoordinateSystem.ts +32 -0
  58. package/src/RenderingEngine/helpers/cpuFallback/rendering/storedColorPixelDataToCanvasImageData.ts +58 -0
  59. package/src/RenderingEngine/helpers/cpuFallback/rendering/storedPixelDataToCanvasImageData.ts +76 -0
  60. package/src/RenderingEngine/helpers/cpuFallback/rendering/storedPixelDataToCanvasImageDataColorLUT.ts +60 -0
  61. package/src/RenderingEngine/helpers/cpuFallback/rendering/storedPixelDataToCanvasImageDataPET.ts +50 -0
  62. package/src/RenderingEngine/helpers/cpuFallback/rendering/storedPixelDataToCanvasImageDataPseudocolorLUT.ts +66 -0
  63. package/src/RenderingEngine/helpers/cpuFallback/rendering/storedPixelDataToCanvasImageDataPseudocolorLUTPET.ts +68 -0
  64. package/src/RenderingEngine/helpers/cpuFallback/rendering/storedPixelDataToCanvasImageDataRGBA.ts +81 -0
  65. package/src/RenderingEngine/helpers/cpuFallback/rendering/storedRGBAPixelDataToCanvasImageData.ts +56 -0
  66. package/src/RenderingEngine/helpers/cpuFallback/rendering/transform.ts +126 -0
  67. package/src/RenderingEngine/helpers/cpuFallback/rendering/validator.ts +31 -0
  68. package/src/RenderingEngine/helpers/createVolumeActor.ts +103 -0
  69. package/src/RenderingEngine/helpers/createVolumeMapper.ts +37 -0
  70. package/src/RenderingEngine/helpers/getOrCreateCanvas.ts +58 -0
  71. package/src/RenderingEngine/helpers/index.ts +15 -0
  72. package/src/RenderingEngine/helpers/isRgbaSourceRgbDest.ts +1 -0
  73. package/src/RenderingEngine/helpers/setDefaultVolumeVOI.ts +227 -0
  74. package/src/RenderingEngine/helpers/setVolumesForViewports.ts +52 -0
  75. package/src/RenderingEngine/helpers/viewportTypeToViewportClass.ts +14 -0
  76. package/src/RenderingEngine/helpers/viewportTypeUsesCustomRenderingPipeline.ts +7 -0
  77. package/src/RenderingEngine/helpers/volumeNewImageEventDispatcher.ts +75 -0
  78. package/src/RenderingEngine/index.ts +23 -0
  79. package/src/RenderingEngine/renderingEngineCache.ts +43 -0
  80. package/src/RenderingEngine/vtkClasses/index.js +11 -0
  81. package/src/RenderingEngine/vtkClasses/vtkOffscreenMultiRenderWindow.js +149 -0
  82. package/src/RenderingEngine/vtkClasses/vtkSharedVolumeMapper.js +52 -0
  83. package/src/RenderingEngine/vtkClasses/vtkSlabCamera.d.ts +781 -0
  84. package/src/RenderingEngine/vtkClasses/vtkSlabCamera.js +155 -0
  85. package/src/RenderingEngine/vtkClasses/vtkStreamingOpenGLRenderWindow.js +47 -0
  86. package/src/RenderingEngine/vtkClasses/vtkStreamingOpenGLTexture.js +272 -0
  87. package/src/RenderingEngine/vtkClasses/vtkStreamingOpenGLViewNodeFactory.js +159 -0
  88. package/src/RenderingEngine/vtkClasses/vtkStreamingOpenGLVolumeMapper.js +319 -0
  89. package/src/Settings.ts +294 -0
  90. package/src/cache/cache.ts +854 -0
  91. package/src/cache/classes/Contour.ts +70 -0
  92. package/src/cache/classes/ContourSet.ts +151 -0
  93. package/src/cache/classes/ImageVolume.ts +155 -0
  94. package/src/cache/index.ts +5 -0
  95. package/src/constants/cpuColormaps.ts +1537 -0
  96. package/src/constants/epsilon.ts +3 -0
  97. package/src/constants/index.ts +13 -0
  98. package/src/constants/mprCameraValues.ts +20 -0
  99. package/src/constants/rendering.ts +8 -0
  100. package/src/constants/viewportPresets.ts +357 -0
  101. package/src/enums/BlendModes.ts +23 -0
  102. package/src/enums/ContourType.ts +6 -0
  103. package/src/enums/Events.ts +196 -0
  104. package/src/enums/GeometryType.ts +5 -0
  105. package/src/enums/InterpolationType.ts +13 -0
  106. package/src/enums/OrientationAxis.ts +8 -0
  107. package/src/enums/RequestType.ts +13 -0
  108. package/src/enums/SharedArrayBufferModes.ts +11 -0
  109. package/src/enums/VOILUTFunctionType.ts +10 -0
  110. package/src/enums/ViewportType.ts +21 -0
  111. package/src/enums/index.ts +23 -0
  112. package/src/eventTarget.ts +67 -0
  113. package/src/getEnabledElement.ts +105 -0
  114. package/src/global.ts +8 -0
  115. package/src/index.ts +123 -0
  116. package/src/init.ts +247 -0
  117. package/src/loaders/geometryLoader.ts +108 -0
  118. package/src/loaders/imageLoader.ts +298 -0
  119. package/src/loaders/volumeLoader.ts +477 -0
  120. package/src/metaData.ts +84 -0
  121. package/src/requestPool/imageLoadPoolManager.ts +43 -0
  122. package/src/requestPool/imageRetrievalPoolManager.ts +25 -0
  123. package/src/requestPool/requestPoolManager.ts +329 -0
  124. package/src/types/ActorSliceRange.ts +17 -0
  125. package/src/types/CPUFallbackColormap.ts +23 -0
  126. package/src/types/CPUFallbackColormapData.ts +12 -0
  127. package/src/types/CPUFallbackColormapsData.ts +7 -0
  128. package/src/types/CPUFallbackEnabledElement.ts +71 -0
  129. package/src/types/CPUFallbackLUT.ts +5 -0
  130. package/src/types/CPUFallbackLookupTable.ts +17 -0
  131. package/src/types/CPUFallbackRenderingTools.ts +25 -0
  132. package/src/types/CPUFallbackTransform.ts +16 -0
  133. package/src/types/CPUFallbackViewport.ts +29 -0
  134. package/src/types/CPUFallbackViewportDisplayedArea.ts +15 -0
  135. package/src/types/CPUIImageData.ts +47 -0
  136. package/src/types/ContourData.ts +19 -0
  137. package/src/types/Cornerstone3DConfig.ts +31 -0
  138. package/src/types/CustomEventType.ts +14 -0
  139. package/src/types/EventTypes.ts +403 -0
  140. package/src/types/FlipDirection.ts +9 -0
  141. package/src/types/IActor.ts +23 -0
  142. package/src/types/ICache.ts +28 -0
  143. package/src/types/ICachedGeometry.ts +13 -0
  144. package/src/types/ICachedImage.ts +13 -0
  145. package/src/types/ICachedVolume.ts +12 -0
  146. package/src/types/ICamera.ts +36 -0
  147. package/src/types/IContour.ts +18 -0
  148. package/src/types/IContourSet.ts +56 -0
  149. package/src/types/IDynamicImageVolume.ts +18 -0
  150. package/src/types/IEnabledElement.ts +21 -0
  151. package/src/types/IGeometry.ts +12 -0
  152. package/src/types/IImage.ts +113 -0
  153. package/src/types/IImageData.ts +45 -0
  154. package/src/types/IImageVolume.ts +78 -0
  155. package/src/types/ILoadObject.ts +36 -0
  156. package/src/types/IRegisterImageLoader.ts +10 -0
  157. package/src/types/IRenderingEngine.ts +28 -0
  158. package/src/types/IStackViewport.ts +138 -0
  159. package/src/types/IStreamingImageVolume.ts +13 -0
  160. package/src/types/IStreamingVolumeProperties.ts +14 -0
  161. package/src/types/IViewport.ts +149 -0
  162. package/src/types/IViewportId.ts +9 -0
  163. package/src/types/IVolume.ts +45 -0
  164. package/src/types/IVolumeInput.ts +36 -0
  165. package/src/types/IVolumeViewport.ts +141 -0
  166. package/src/types/ImageLoaderFn.ts +16 -0
  167. package/src/types/ImageSliceData.ts +6 -0
  168. package/src/types/Mat3.ts +16 -0
  169. package/src/types/Metadata.ts +39 -0
  170. package/src/types/OrientationVectors.ts +36 -0
  171. package/src/types/Plane.ts +6 -0
  172. package/src/types/Point2.ts +6 -0
  173. package/src/types/Point3.ts +6 -0
  174. package/src/types/Point4.ts +6 -0
  175. package/src/types/ScalingParameters.ts +27 -0
  176. package/src/types/StackViewportProperties.ts +25 -0
  177. package/src/types/TransformMatrix2D.ts +4 -0
  178. package/src/types/ViewportInputOptions.ts +21 -0
  179. package/src/types/ViewportPreset.ts +14 -0
  180. package/src/types/VolumeLoaderFn.ts +18 -0
  181. package/src/types/VolumeViewportProperties.ts +14 -0
  182. package/src/types/index.ts +157 -0
  183. package/src/types/voi.ts +15 -0
  184. package/src/utilities/actorCheck.ts +24 -0
  185. package/src/utilities/applyPreset.ts +132 -0
  186. package/src/utilities/calculateViewportsSpatialRegistration.ts +74 -0
  187. package/src/utilities/calibratedPixelSpacingMetadataProvider.ts +38 -0
  188. package/src/utilities/createFloat32SharedArray.ts +45 -0
  189. package/src/utilities/createInt16SharedArray.ts +43 -0
  190. package/src/utilities/createLinearRGBTransferFunction.ts +22 -0
  191. package/src/utilities/createSigmoidRGBTransferFunction.ts +63 -0
  192. package/src/utilities/createUInt16SharedArray.ts +43 -0
  193. package/src/utilities/createUint8SharedArray.ts +45 -0
  194. package/src/utilities/deepFreeze.ts +19 -0
  195. package/src/utilities/deepMerge.ts +81 -0
  196. package/src/utilities/getClosestImageId.ts +80 -0
  197. package/src/utilities/getClosestStackImageIndexForPoint.ts +116 -0
  198. package/src/utilities/getImageSliceDataForVolumeViewport.ts +61 -0
  199. package/src/utilities/getMinMax.ts +31 -0
  200. package/src/utilities/getRuntimeId.ts +54 -0
  201. package/src/utilities/getScalarDataType.ts +31 -0
  202. package/src/utilities/getScalingParameters.ts +35 -0
  203. package/src/utilities/getSliceRange.ts +86 -0
  204. package/src/utilities/getSpacingInNormalDirection.ts +44 -0
  205. package/src/utilities/getTargetVolumeAndSpacingInNormalDir.ts +126 -0
  206. package/src/utilities/getViewportImageCornersInWorld.ts +102 -0
  207. package/src/utilities/getViewportsWithImageURI.ts +46 -0
  208. package/src/utilities/getViewportsWithVolumeId.ts +38 -0
  209. package/src/utilities/getVoiFromSigmoidRGBTransferFunction.ts +23 -0
  210. package/src/utilities/getVolumeActorCorners.ts +24 -0
  211. package/src/utilities/getVolumeSliceRangeInfo.ts +52 -0
  212. package/src/utilities/getVolumeViewportScrollInfo.ts +32 -0
  213. package/src/utilities/getVolumeViewportsContainingSameVolumes.ts +58 -0
  214. package/src/utilities/hasNaNValues.ts +12 -0
  215. package/src/utilities/imageIdToURI.ts +10 -0
  216. package/src/utilities/imageToWorldCoords.ts +54 -0
  217. package/src/utilities/index.ts +100 -0
  218. package/src/utilities/indexWithinDimensions.ts +27 -0
  219. package/src/utilities/invertRgbTransferFunction.ts +36 -0
  220. package/src/utilities/isEqual.ts +27 -0
  221. package/src/utilities/isOpposite.ts +23 -0
  222. package/src/utilities/isTypedArray.ts +20 -0
  223. package/src/utilities/loadImageToCanvas.ts +80 -0
  224. package/src/utilities/planar.ts +91 -0
  225. package/src/utilities/renderToCanvas.ts +32 -0
  226. package/src/utilities/scaleRgbTransferFunction.ts +37 -0
  227. package/src/utilities/snapFocalPointToSlice.ts +78 -0
  228. package/src/utilities/spatialRegistrationMetadataProvider.ts +50 -0
  229. package/src/utilities/transformWorldToIndex.ts +16 -0
  230. package/src/utilities/triggerEvent.ts +38 -0
  231. package/src/utilities/uuidv4.ts +13 -0
  232. package/src/utilities/windowLevel.ts +39 -0
  233. package/src/utilities/worldToImageCoords.ts +64 -0
@@ -0,0 +1,847 @@
1
+ import vtkVolume from '@kitware/vtk.js/Rendering/Core/Volume';
2
+
3
+ import cache from '../cache';
4
+ import { MPR_CAMERA_VALUES, RENDERING_DEFAULTS } from '../constants';
5
+ import {
6
+ BlendModes,
7
+ Events,
8
+ OrientationAxis,
9
+ VOILUTFunctionType,
10
+ } from '../enums';
11
+ import ViewportType from '../enums/ViewportType';
12
+ import eventTarget from '../eventTarget';
13
+ import { getShouldUseCPURendering } from '../init';
14
+ import { loadVolume } from '../loaders/volumeLoader';
15
+ import type {
16
+ ActorEntry,
17
+ FlipDirection,
18
+ IImageData,
19
+ IVolumeInput,
20
+ OrientationVectors,
21
+ Point2,
22
+ Point3,
23
+ VOIRange,
24
+ VolumeViewportProperties,
25
+ } from '../types';
26
+ import { VoiModifiedEventDetail } from '../types/EventTypes';
27
+ import type { ViewportInput } from '../types/IViewport';
28
+ import type IVolumeViewport from '../types/IVolumeViewport';
29
+ import {
30
+ actorIsA,
31
+ createSigmoidRGBTransferFunction,
32
+ getVoiFromSigmoidRGBTransferFunction,
33
+ imageIdToURI,
34
+ triggerEvent,
35
+ } from '../utilities';
36
+ import { createVolumeActor } from './helpers';
37
+ import volumeNewImageEventDispatcher, {
38
+ resetVolumeNewImageState,
39
+ } from './helpers/volumeNewImageEventDispatcher';
40
+ import Viewport from './Viewport';
41
+ import type { vtkSlabCamera as vtkSlabCameraType } from './vtkClasses/vtkSlabCamera';
42
+ import vtkSlabCamera from './vtkClasses/vtkSlabCamera';
43
+
44
+ /**
45
+ * Abstract base class for volume viewports. VolumeViewports are used to render
46
+ * 3D volumes from which various orientations can be viewed. Since VolumeViewports
47
+ * use SharedVolumeMappers behind the scene, memory footprint of visualizations
48
+ * of the same volume in different orientations is very small.
49
+ *
50
+ * For setting volumes on viewports you need to use {@link addVolumesToViewports}
51
+ * which will add volumes to the specified viewports.
52
+ */
53
+ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
54
+ useCPURendering = false;
55
+ use16BitTexture = false;
56
+ private _FrameOfReferenceUID: string;
57
+
58
+ // Viewport Properties
59
+ // TODO: similar to setVoi, this is only applicable to first volume
60
+ private VOILUTFunction: VOILUTFunctionType;
61
+
62
+ constructor(props: ViewportInput) {
63
+ super(props);
64
+
65
+ this.useCPURendering = getShouldUseCPURendering();
66
+ this.use16BitTexture = this._shouldUse16BitTexture();
67
+
68
+ if (this.useCPURendering) {
69
+ throw new Error(
70
+ 'VolumeViewports cannot be used whilst CPU Fallback Rendering is enabled.'
71
+ );
72
+ }
73
+
74
+ const renderer = this.getRenderer();
75
+
76
+ const camera = vtkSlabCamera.newInstance();
77
+ renderer.setActiveCamera(camera);
78
+
79
+ switch (this.type) {
80
+ case ViewportType.ORTHOGRAPHIC:
81
+ camera.setParallelProjection(true);
82
+ break;
83
+ case ViewportType.VOLUME_3D:
84
+ camera.setParallelProjection(true);
85
+ break;
86
+ case ViewportType.PERSPECTIVE:
87
+ camera.setParallelProjection(false);
88
+ break;
89
+ default:
90
+ throw new Error(`Unrecognized viewport type: ${this.type}`);
91
+ }
92
+
93
+ this.initializeVolumeNewImageEventDispatcher();
94
+ }
95
+
96
+ static get useCustomRenderingPipeline(): boolean {
97
+ return false;
98
+ }
99
+
100
+ protected applyViewOrientation(
101
+ orientation: OrientationAxis | OrientationVectors
102
+ ) {
103
+ const { viewPlaneNormal, viewUp } =
104
+ this._getOrientationVectors(orientation);
105
+ const camera = this.getVtkActiveCamera();
106
+ camera.setDirectionOfProjection(
107
+ -viewPlaneNormal[0],
108
+ -viewPlaneNormal[1],
109
+ -viewPlaneNormal[2]
110
+ );
111
+ camera.setViewUpFrom(viewUp);
112
+
113
+ this.resetCamera();
114
+ }
115
+
116
+ private initializeVolumeNewImageEventDispatcher(): void {
117
+ const volumeNewImageHandlerBound = volumeNewImageHandler.bind(this);
118
+ const volumeNewImageCleanUpBound = volumeNewImageCleanUp.bind(this);
119
+
120
+ function volumeNewImageHandler(cameraEvent) {
121
+ const { viewportId } = cameraEvent.detail;
122
+
123
+ if (viewportId !== this.id || this.isDisabled) {
124
+ return;
125
+ }
126
+
127
+ const viewportImageData = this.getImageData();
128
+
129
+ if (!viewportImageData) {
130
+ return;
131
+ }
132
+
133
+ volumeNewImageEventDispatcher(cameraEvent);
134
+ }
135
+
136
+ function volumeNewImageCleanUp(evt) {
137
+ const { viewportId } = evt.detail;
138
+
139
+ if (viewportId !== this.id) {
140
+ return;
141
+ }
142
+
143
+ this.element.removeEventListener(
144
+ Events.CAMERA_MODIFIED,
145
+ volumeNewImageHandlerBound
146
+ );
147
+
148
+ eventTarget.removeEventListener(
149
+ Events.ELEMENT_DISABLED,
150
+ volumeNewImageCleanUpBound
151
+ );
152
+
153
+ resetVolumeNewImageState(viewportId);
154
+ }
155
+
156
+ this.element.removeEventListener(
157
+ Events.CAMERA_MODIFIED,
158
+ volumeNewImageHandlerBound
159
+ );
160
+ this.element.addEventListener(
161
+ Events.CAMERA_MODIFIED,
162
+ volumeNewImageHandlerBound
163
+ );
164
+
165
+ eventTarget.addEventListener(
166
+ Events.ELEMENT_DISABLED,
167
+ volumeNewImageCleanUpBound
168
+ );
169
+ }
170
+
171
+ protected resetVolumeViewportClippingRange() {
172
+ const activeCamera = this.getVtkActiveCamera();
173
+
174
+ if (activeCamera.getParallelProjection()) {
175
+ activeCamera.setClippingRange(
176
+ -RENDERING_DEFAULTS.MAXIMUM_RAY_DISTANCE,
177
+ RENDERING_DEFAULTS.MAXIMUM_RAY_DISTANCE
178
+ );
179
+ } else {
180
+ activeCamera.setClippingRange(
181
+ RENDERING_DEFAULTS.MINIMUM_SLAB_THICKNESS,
182
+ RENDERING_DEFAULTS.MAXIMUM_RAY_DISTANCE
183
+ );
184
+ }
185
+ }
186
+
187
+ /**
188
+ * Sets the properties for the volume viewport on the volume
189
+ * Sets the VOILUTFunction property for the volume viewport on the volume
190
+ *
191
+ * @param VOILUTFunction - Sets the voi mode (LINEAR or SAMPLED_SIGMOID)
192
+ * @param volumeId - The volume id to set the properties for (if undefined, the first volume)
193
+ * @param suppressEvents - If true, the viewport will not emit events
194
+ */
195
+ private setVOILUTFunction(
196
+ voiLUTFunction: VOILUTFunctionType,
197
+ volumeId?: string,
198
+ suppressEvents?: boolean
199
+ ): void {
200
+ // make sure the VOI LUT function is valid in the VOILUTFunctionType which is enum
201
+ if (Object.values(VOILUTFunctionType).indexOf(voiLUTFunction) === -1) {
202
+ voiLUTFunction = VOILUTFunctionType.LINEAR;
203
+ }
204
+ const { voiRange } = this.getProperties();
205
+ this.VOILUTFunction = voiLUTFunction;
206
+ this.setVOI(voiRange, volumeId, suppressEvents);
207
+ }
208
+
209
+ /**
210
+ * Sets the properties for the volume viewport on the volume
211
+ * (if fusion, it sets it for the first volume in the fusion)
212
+ *
213
+ * @param voiRange - Sets the lower and upper voi
214
+ * @param volumeId - The volume id to set the properties for (if undefined, the first volume)
215
+ * @param suppressEvents - If true, the viewport will not emit events
216
+ */
217
+ private setVOI(
218
+ voiRange: VOIRange,
219
+ volumeId?: string,
220
+ suppressEvents = false
221
+ ): void {
222
+ if (volumeId !== undefined && !this.getActor(volumeId)) {
223
+ return;
224
+ }
225
+
226
+ const actorEntries = this.getActors();
227
+
228
+ if (!actorEntries.length) {
229
+ return;
230
+ }
231
+
232
+ let volumeActor;
233
+
234
+ if (volumeId) {
235
+ volumeActor = this.getActor(volumeId)?.actor as vtkVolume;
236
+ }
237
+
238
+ // // set it for the first volume (if there are more than one - fusion)
239
+ if (!volumeActor) {
240
+ volumeActor = actorEntries[0].actor as vtkVolume;
241
+ volumeId = actorEntries[0].uid;
242
+ }
243
+
244
+ let voiRangeToUse = voiRange;
245
+ if (typeof voiRangeToUse === 'undefined') {
246
+ const imageData = volumeActor.getMapper().getInputData();
247
+ const range = imageData.getPointData().getScalars().getRange();
248
+ const maxVoiRange = { lower: range[0], upper: range[1] };
249
+ voiRangeToUse = maxVoiRange;
250
+ }
251
+
252
+ // scaling logic here
253
+ // https://github.com/Kitware/vtk-js/blob/c6f2e12cddfe5c0386a73f0793eb6d9ab20d573e/Sources/Rendering/OpenGL/VolumeMapper/index.js#L957-L972
254
+ if (this.VOILUTFunction === VOILUTFunctionType.SAMPLED_SIGMOID) {
255
+ const cfun = createSigmoidRGBTransferFunction(voiRangeToUse);
256
+ volumeActor.getProperty().setRGBTransferFunction(0, cfun);
257
+ } else {
258
+ // TODO: refactor and make it work for PET series (inverted/colormap)
259
+ // const cfun = createLinearRGBTransferFunction(voiRangeToUse);
260
+ // volumeActor.getProperty().setRGBTransferFunction(0, cfun);
261
+
262
+ // Todo: Moving from LINEAR to SIGMOID and back to LINEAR will not
263
+ // work until we implement it in a different way because the
264
+ // LINEAR transfer function is not recreated.
265
+ const { lower, upper } = voiRangeToUse;
266
+ volumeActor
267
+ .getProperty()
268
+ .getRGBTransferFunction(0)
269
+ .setRange(lower, upper);
270
+ }
271
+
272
+ if (!suppressEvents) {
273
+ const eventDetail: VoiModifiedEventDetail = {
274
+ viewportId: this.id,
275
+ range: voiRange,
276
+ volumeId: volumeId,
277
+ VOILUTFunction: this.VOILUTFunction,
278
+ };
279
+
280
+ triggerEvent(this.element, Events.VOI_MODIFIED, eventDetail);
281
+ }
282
+ }
283
+
284
+ /**
285
+ * Sets the properties for the volume viewport on the volume
286
+ * (if fusion, it sets it for the first volume in the fusion)
287
+ *
288
+ * @param voiRange - Sets the lower and upper voi
289
+ * @param VOILUTFunction - Sets the voi mode (LINEAR, or SAMPLED_SIGMOID)
290
+ * @param volumeId - The volume id to set the properties for (if undefined, the first volume)
291
+ * @param suppressEvents - If true, the viewport will not emit events
292
+ */
293
+ public setProperties(
294
+ { voiRange, VOILUTFunction }: VolumeViewportProperties = {},
295
+ volumeId?: string,
296
+ suppressEvents = false
297
+ ): void {
298
+ if (voiRange) {
299
+ this.setVOI(voiRange, volumeId, suppressEvents);
300
+ }
301
+
302
+ if (VOILUTFunction) {
303
+ this.setVOILUTFunction(VOILUTFunction, volumeId, suppressEvents);
304
+ }
305
+ }
306
+
307
+ /**
308
+ * Retrieve the viewport properties
309
+ * @returns viewport properties including voi, interpolation type: TODO: slabThickness, invert, rotation, flip
310
+ */
311
+ public getProperties = (): VolumeViewportProperties => {
312
+ const actorEntries = this.getActors();
313
+ const voiRanges = actorEntries.map((actorEntry) => {
314
+ const volumeActor = actorEntry.actor as vtkVolume;
315
+ const volumeId = actorEntry.uid;
316
+ const cfun = volumeActor.getProperty().getRGBTransferFunction(0);
317
+ let lower, upper;
318
+ if (this.VOILUTFunction === 'SIGMOID') {
319
+ [lower, upper] = getVoiFromSigmoidRGBTransferFunction(cfun);
320
+ } else {
321
+ // @ts-ignore: vtk d ts problem
322
+ [lower, upper] = cfun.getRange();
323
+ }
324
+ return {
325
+ volumeId,
326
+ voiRange: { lower, upper },
327
+ };
328
+ });
329
+ return {
330
+ voiRange: voiRanges[0].voiRange, // TODO: handle multiple actors instead of just first.
331
+ VOILUTFunction: this.VOILUTFunction,
332
+ };
333
+ };
334
+
335
+ /**
336
+ * Creates volume actors for all volumes defined in the `volumeInputArray`.
337
+ * For each entry, if a `callback` is supplied, it will be called with the new volume actor as input.
338
+ * For each entry, if a `blendMode` and/or `slabThickness` is defined, this will be set on the actor's
339
+ * `VolumeMapper`.
340
+ *
341
+ * @param volumeInputArray - The array of `VolumeInput`s which define the volumes to add.
342
+ * @param immediate - Whether the `Viewport` should be rendered as soon as volumes are added.
343
+ */
344
+ public async setVolumes(
345
+ volumeInputArray: Array<IVolumeInput>,
346
+ immediate = false,
347
+ suppressEvents = false
348
+ ): Promise<void> {
349
+ const firstImageVolume = cache.getVolume(volumeInputArray[0].volumeId);
350
+
351
+ if (!firstImageVolume) {
352
+ throw new Error(
353
+ `imageVolume with id: ${firstImageVolume.volumeId} does not exist`
354
+ );
355
+ }
356
+
357
+ const FrameOfReferenceUID = firstImageVolume.metadata.FrameOfReferenceUID;
358
+
359
+ await this._isValidVolumeInputArray(volumeInputArray, FrameOfReferenceUID);
360
+
361
+ this._FrameOfReferenceUID = FrameOfReferenceUID;
362
+
363
+ const volumeActors = [];
364
+
365
+ // One actor per volume
366
+ for (let i = 0; i < volumeInputArray.length; i++) {
367
+ const { volumeId, actorUID, slabThickness } = volumeInputArray[i];
368
+
369
+ const actor = await createVolumeActor(
370
+ volumeInputArray[i],
371
+ this.element,
372
+ this.id,
373
+ suppressEvents,
374
+ this.use16BitTexture
375
+ );
376
+
377
+ // We cannot use only volumeId since then we cannot have for instance more
378
+ // than one representation of the same volume (since actors would have the
379
+ // same name, and we don't allow that) AND We cannot use only any uid, since
380
+ // we rely on the volume in the cache for mapper. So we prefer actorUID if
381
+ // it is defined, otherwise we use volumeId for the actor name.
382
+ const uid = actorUID || volumeId;
383
+ volumeActors.push({
384
+ uid,
385
+ actor,
386
+ slabThickness,
387
+ referenceId: volumeId,
388
+ });
389
+ }
390
+
391
+ this._setVolumeActors(volumeActors);
392
+
393
+ triggerEvent(this.element, Events.VOLUME_VIEWPORT_NEW_VOLUME, {
394
+ viewportId: this.id,
395
+ volumeActors,
396
+ });
397
+
398
+ if (immediate) {
399
+ this.render();
400
+ }
401
+ }
402
+
403
+ /**
404
+ * Creates and adds volume actors for all volumes defined in the `volumeInputArray`.
405
+ * For each entry, if a `callback` is supplied, it will be called with the new volume actor as input.
406
+ *
407
+ * @param volumeInputArray - The array of `VolumeInput`s which define the volumes to add.
408
+ * @param immediate - Whether the `Viewport` should be rendered as soon as volumes are added.
409
+ */
410
+ public async addVolumes(
411
+ volumeInputArray: Array<IVolumeInput>,
412
+ immediate = false,
413
+ suppressEvents = false
414
+ ): Promise<void> {
415
+ const firstImageVolume = cache.getVolume(volumeInputArray[0].volumeId);
416
+
417
+ if (!firstImageVolume) {
418
+ throw new Error(
419
+ `imageVolume with id: ${firstImageVolume.volumeId} does not exist`
420
+ );
421
+ }
422
+
423
+ const volumeActors = [];
424
+
425
+ await this._isValidVolumeInputArray(
426
+ volumeInputArray,
427
+ this._FrameOfReferenceUID
428
+ );
429
+
430
+ // One actor per volume
431
+ for (let i = 0; i < volumeInputArray.length; i++) {
432
+ const { volumeId, visibility, actorUID, slabThickness } =
433
+ volumeInputArray[i];
434
+
435
+ const actor = await createVolumeActor(
436
+ volumeInputArray[i],
437
+ this.element,
438
+ this.id,
439
+ suppressEvents,
440
+ this.use16BitTexture
441
+ );
442
+
443
+ if (visibility === false) {
444
+ actor.setVisibility(false);
445
+ }
446
+
447
+ // We cannot use only volumeId since then we cannot have for instance more
448
+ // than one representation of the same volume (since actors would have the
449
+ // same name, and we don't allow that) AND We cannot use only any uid, since
450
+ // we rely on the volume in the cache for mapper. So we prefer actorUID if
451
+ // it is defined, otherwise we use volumeId for the actor name.
452
+ const uid = actorUID || volumeId;
453
+ volumeActors.push({
454
+ uid,
455
+ actor,
456
+ slabThickness,
457
+ // although the actor UID is defined, we need to use the volumeId for the
458
+ // referenceId, since the actor UID is used to reference the actor in the
459
+ // viewport, however, the actor is created from its volumeId
460
+ // and if later we need to grab the referenced volume from cache,
461
+ // we can use the referenceId to get the volume from the cache
462
+ referenceId: volumeId,
463
+ });
464
+ }
465
+
466
+ this.addActors(volumeActors);
467
+
468
+ if (immediate) {
469
+ // render
470
+ this.render();
471
+ }
472
+ }
473
+
474
+ /**
475
+ * It removes the volume actor from the Viewport. If the volume actor is not in
476
+ * the viewport, it does nothing.
477
+ * @param actorUIDs - Array of actor UIDs to remove. In case of simple volume it will
478
+ * be the volume Id, but in case of Segmentation it will be `{volumeId}-{representationType}`
479
+ * since the same volume can be rendered in multiple representations.
480
+ * @param immediate - If true, the Viewport will be rendered immediately
481
+ */
482
+ public removeVolumeActors(actorUIDs: Array<string>, immediate = false): void {
483
+ // Todo: This is actually removeActors
484
+ this.removeActors(actorUIDs);
485
+
486
+ if (immediate) {
487
+ this.render();
488
+ }
489
+ }
490
+
491
+ /**
492
+ * It sets the orientation for the camera, the orientation can be one of the
493
+ * following: axial, sagittal, coronal, default. Use the Enums.OrientationAxis
494
+ * to set the orientation. The "default" orientation is the orientation that
495
+ * the volume was acquired in (scan axis)
496
+ *
497
+ * @param orientation - The orientation to set the camera to.
498
+ * @param immediate - Whether the `Viewport` should be rendered as soon as the camera is set.
499
+ */
500
+ public setOrientation(orientation: OrientationAxis, immediate = true): void {
501
+ console.warn('Method "setOrientation" needs implementation');
502
+ }
503
+
504
+ private async _isValidVolumeInputArray(
505
+ volumeInputArray: Array<IVolumeInput>,
506
+ FrameOfReferenceUID: string
507
+ ): Promise<boolean> {
508
+ const numVolumes = volumeInputArray.length;
509
+
510
+ // Check all other volumes exist and have the same FrameOfReference
511
+ for (let i = 1; i < numVolumes; i++) {
512
+ const volumeInput = volumeInputArray[i];
513
+
514
+ const imageVolume = await loadVolume(volumeInput.volumeId);
515
+
516
+ if (!imageVolume) {
517
+ throw new Error(
518
+ `imageVolume with id: ${imageVolume.volumeId} does not exist`
519
+ );
520
+ }
521
+
522
+ if (FrameOfReferenceUID !== imageVolume.metadata.FrameOfReferenceUID) {
523
+ throw new Error(
524
+ `Volumes being added to viewport ${this.id} do not share the same FrameOfReferenceUID. This is not yet supported`
525
+ );
526
+ }
527
+ }
528
+
529
+ return true;
530
+ }
531
+
532
+ /**
533
+ * gets the visible bounds of the viewport in the world coordinate system
534
+ */
535
+ public getBounds(): number[] {
536
+ const renderer = this.getRenderer();
537
+ const bounds = renderer.computeVisiblePropBounds();
538
+ return bounds;
539
+ }
540
+
541
+ /**
542
+ * Flip the viewport along the desired axis
543
+ * @param flipDirection - FlipDirection
544
+ */
545
+ public flip(flipDirection: FlipDirection): void {
546
+ super.flip(flipDirection);
547
+ }
548
+
549
+ public getFrameOfReferenceUID = (): string => {
550
+ return this._FrameOfReferenceUID;
551
+ };
552
+
553
+ /**
554
+ * Checks if the viewport has a volume actor with the given volumeId
555
+ * @param volumeId - the volumeId to look for
556
+ * @returns Boolean indicating if the volume is present in the viewport
557
+ */
558
+ public hasVolumeId(volumeId: string): boolean {
559
+ // Note: this assumes that the uid of the volume is the same as the volumeId
560
+ // which is not guaranteed to be the case for SEG.
561
+ const actorEntries = this.getActors();
562
+ return actorEntries.some((actorEntry) => {
563
+ return actorEntry.uid === volumeId;
564
+ });
565
+ }
566
+
567
+ /**
568
+ * Returns the image and its properties that is being shown inside the
569
+ * stack viewport. It returns, the image dimensions, image direction,
570
+ * image scalar data, vtkImageData object, metadata, and scaling (e.g., PET suvbw)
571
+ * Note: since the volume viewport supports fusion, to get the
572
+ * image data for a specific volume, use the optional volumeId
573
+ * argument.
574
+ *
575
+ * @param volumeId - The volumeId of the volume to get the image for.
576
+ * @returns IImageData: {dimensions, direction, scalarData, vtkImageData, metadata, scaling}
577
+ */
578
+ public getImageData(volumeId?: string): IImageData | undefined {
579
+ const defaultActor = this.getDefaultActor();
580
+ if (!defaultActor) {
581
+ return;
582
+ }
583
+
584
+ const { uid: defaultActorUID } = defaultActor;
585
+ volumeId = volumeId ?? defaultActorUID;
586
+
587
+ const actorEntry = this.getActor(volumeId);
588
+
589
+ if (!actorIsA(actorEntry, 'vtkVolume')) {
590
+ return;
591
+ }
592
+
593
+ const actor = actorEntry.actor;
594
+ const volume = cache.getVolume(volumeId);
595
+
596
+ const vtkImageData = actor.getMapper().getInputData();
597
+ return {
598
+ dimensions: vtkImageData.getDimensions(),
599
+ spacing: vtkImageData.getSpacing(),
600
+ origin: vtkImageData.getOrigin(),
601
+ direction: vtkImageData.getDirection(),
602
+ scalarData: vtkImageData.getPointData().getScalars().getData(),
603
+ imageData: actor.getMapper().getInputData(),
604
+ metadata: {
605
+ Modality: volume?.metadata?.Modality,
606
+ },
607
+ scaling: volume?.scaling,
608
+ hasPixelSpacing: true,
609
+ };
610
+ }
611
+
612
+ /**
613
+ * Attaches the volume actors to the viewport.
614
+ *
615
+ * @param volumeActorEntries - The volume actors to add the viewport.
616
+ *
617
+ */
618
+ private _setVolumeActors(volumeActorEntries: Array<ActorEntry>): void {
619
+ this.setActors(volumeActorEntries);
620
+ }
621
+
622
+ /**
623
+ * canvasToWorld Returns the world coordinates of the given `canvasPos`
624
+ * projected onto the plane defined by the `Viewport`'s `vtkCamera`'s focal point
625
+ * and the direction of projection.
626
+ *
627
+ * @param canvasPos - The position in canvas coordinates.
628
+ * @returns The corresponding world coordinates.
629
+ * @public
630
+ */
631
+ public canvasToWorld = (canvasPos: Point2): Point3 => {
632
+ const vtkCamera = this.getVtkActiveCamera() as vtkSlabCameraType;
633
+
634
+ /**
635
+ * NOTE: this is necessary because we want the coordinate transformation
636
+ * respect to the view plane (plane orthogonal to the camera and passing to
637
+ * the focal point).
638
+ *
639
+ * When vtk.js computes the coordinate transformations, it simply uses the
640
+ * camera matrix (no ray casting).
641
+ *
642
+ * However for the volume viewport the clipping range is set to be
643
+ * (-RENDERING_DEFAULTS.MAXIMUM_RAY_DISTANCE, RENDERING_DEFAULTS.MAXIMUM_RAY_DISTANCE).
644
+ * The clipping range is used in the camera method getProjectionMatrix().
645
+ * The projection matrix is used then for viewToWorld/worldToView methods of
646
+ * the renderer. This means that vkt.js will not return the coordinates of
647
+ * the point on the view plane (i.e. the depth coordinate will correspond
648
+ * to the focal point).
649
+ *
650
+ * Therefore the clipping range has to be set to (distance, distance + 0.01),
651
+ * where now distance is the distance between the camera position and focal
652
+ * point. This is done internally, in our camera customization when the flag
653
+ * isPerformingCoordinateTransformation is set to true.
654
+ */
655
+
656
+ vtkCamera.setIsPerformingCoordinateTransformation?.(true);
657
+
658
+ const renderer = this.getRenderer();
659
+ const offscreenMultiRenderWindow =
660
+ this.getRenderingEngine().offscreenMultiRenderWindow;
661
+ const openGLRenderWindow =
662
+ offscreenMultiRenderWindow.getOpenGLRenderWindow();
663
+ const size = openGLRenderWindow.getSize();
664
+ const devicePixelRatio = window.devicePixelRatio || 1;
665
+ const canvasPosWithDPR = [
666
+ canvasPos[0] * devicePixelRatio,
667
+ canvasPos[1] * devicePixelRatio,
668
+ ];
669
+ const displayCoord = [
670
+ canvasPosWithDPR[0] + this.sx,
671
+ canvasPosWithDPR[1] + this.sy,
672
+ ];
673
+
674
+ // The y axis display coordinates are inverted with respect to canvas coords
675
+ displayCoord[1] = size[1] - displayCoord[1];
676
+
677
+ const worldCoord = openGLRenderWindow.displayToWorld(
678
+ displayCoord[0],
679
+ displayCoord[1],
680
+ 0,
681
+ renderer
682
+ );
683
+
684
+ vtkCamera.setIsPerformingCoordinateTransformation?.(false);
685
+
686
+ return [worldCoord[0], worldCoord[1], worldCoord[2]];
687
+ };
688
+
689
+ /**
690
+ * Returns the canvas coordinates of the given `worldPos`
691
+ * projected onto the `Viewport`'s `canvas`.
692
+ *
693
+ * @param worldPos - The position in world coordinates.
694
+ * @returns The corresponding canvas coordinates.
695
+ * @public
696
+ */
697
+ public worldToCanvas = (worldPos: Point3): Point2 => {
698
+ const vtkCamera = this.getVtkActiveCamera() as vtkSlabCameraType;
699
+
700
+ /**
701
+ * NOTE: this is necessary because we want the coordinate trasformation
702
+ * respect to the view plane (plane orthogonal to the camera and passing to
703
+ * the focal point).
704
+ *
705
+ * When vtk.js computes the coordinate transformations, it simply uses the
706
+ * camera matrix (no ray casting).
707
+ *
708
+ * However for the volume viewport the clipping range is set to be
709
+ * (-RENDERING_DEFAULTS.MAXIMUM_RAY_DISTANCE, RENDERING_DEFAULTS.MAXIMUM_RAY_DISTANCE).
710
+ * The clipping range is used in the camera method getProjectionMatrix().
711
+ * The projection matrix is used then for viewToWorld/worldToView methods of
712
+ * the renderer. This means that vkt.js will not return the coordinates of
713
+ * the point on the view plane (i.e. the depth coordinate will corresponded
714
+ * to the focal point).
715
+ *
716
+ * Therefore the clipping range has to be set to (distance, distance + 0.01),
717
+ * where now distance is the distance between the camera position and focal
718
+ * point. This is done internally, in our camera customization when the flag
719
+ * isPerformingCoordinateTransformation is set to true.
720
+ */
721
+
722
+ vtkCamera.setIsPerformingCoordinateTransformation?.(true);
723
+
724
+ const renderer = this.getRenderer();
725
+ const offscreenMultiRenderWindow =
726
+ this.getRenderingEngine().offscreenMultiRenderWindow;
727
+ const openGLRenderWindow =
728
+ offscreenMultiRenderWindow.getOpenGLRenderWindow();
729
+ const size = openGLRenderWindow.getSize();
730
+ const displayCoord = openGLRenderWindow.worldToDisplay(
731
+ ...worldPos,
732
+ renderer
733
+ );
734
+
735
+ // The y axis display coordinates are inverted with respect to canvas coords
736
+ displayCoord[1] = size[1] - displayCoord[1];
737
+
738
+ const canvasCoord = <Point2>[
739
+ displayCoord[0] - this.sx,
740
+ displayCoord[1] - this.sy,
741
+ ];
742
+
743
+ const devicePixelRatio = window.devicePixelRatio || 1;
744
+ const canvasCoordWithDPR = <Point2>[
745
+ canvasCoord[0] / devicePixelRatio,
746
+ canvasCoord[1] / devicePixelRatio,
747
+ ];
748
+
749
+ vtkCamera.setIsPerformingCoordinateTransformation?.(false);
750
+
751
+ return canvasCoordWithDPR;
752
+ };
753
+
754
+ /*
755
+ * Checking if the imageURI is in the volumes that are being
756
+ * rendered by the viewport. imageURI is the imageId without the schema
757
+ * for instance for the imageId of wadors:http://..., the http://... is the imageURI.
758
+ * Why we don't check the imageId is because the same image can be shown in
759
+ * another viewport (StackViewport) with a different schema
760
+ *
761
+ * @param imageURI - The imageURI to check
762
+ * @returns True if the imageURI is in the volumes that are being rendered by the viewport
763
+ */
764
+ public hasImageURI = (imageURI: string): boolean => {
765
+ const volumeActors = this.getActors().filter((actorEntry) =>
766
+ actorIsA(actorEntry, 'vtkVolume')
767
+ );
768
+
769
+ return volumeActors.some(({ uid }) => {
770
+ const volume = cache.getVolume(uid);
771
+
772
+ if (!volume || !volume.imageIds) {
773
+ return false;
774
+ }
775
+
776
+ const volumeImageURIs = volume.imageIds.map(imageIdToURI);
777
+
778
+ return volumeImageURIs.includes(imageURI);
779
+ });
780
+ };
781
+
782
+ protected _getOrientationVectors(
783
+ orientation: OrientationAxis | OrientationVectors
784
+ ): OrientationVectors {
785
+ if (typeof orientation === 'object') {
786
+ if (orientation.viewPlaneNormal && orientation.viewUp) {
787
+ return orientation;
788
+ } else {
789
+ throw new Error(
790
+ 'Invalid orientation object. It must contain viewPlaneNormal and viewUp'
791
+ );
792
+ }
793
+ } else if (
794
+ typeof orientation === 'string' &&
795
+ MPR_CAMERA_VALUES[orientation]
796
+ ) {
797
+ return MPR_CAMERA_VALUES[orientation];
798
+ } else {
799
+ throw new Error(
800
+ `Invalid orientation: ${orientation}. Valid orientations are: ${Object.keys(
801
+ MPR_CAMERA_VALUES
802
+ ).join(', ')}`
803
+ );
804
+ }
805
+ }
806
+
807
+ /**
808
+ * Reset the camera for the volume viewport
809
+ */
810
+ resetCamera(
811
+ resetPan?: boolean,
812
+ resetZoom?: boolean,
813
+ resetToCenter?: boolean
814
+ ): boolean {
815
+ return super.resetCamera(resetPan, resetZoom, resetToCenter);
816
+ }
817
+
818
+ getCurrentImageIdIndex = (): number => {
819
+ throw new Error('Method not implemented.');
820
+ };
821
+
822
+ getCurrentImageId = (): string => {
823
+ throw new Error('Method not implemented.');
824
+ };
825
+
826
+ getIntensityFromWorld(point: Point3): number {
827
+ throw new Error('Method not implemented.');
828
+ }
829
+
830
+ setBlendMode(
831
+ blendMode: BlendModes,
832
+ filterActorUIDs?: string[],
833
+ immediate?: boolean
834
+ ): void {
835
+ throw new Error('Method not implemented.');
836
+ }
837
+
838
+ setSlabThickness(slabThickness: number, filterActorUIDs?: string[]): void {
839
+ throw new Error('Method not implemented.');
840
+ }
841
+
842
+ getSlabThickness(): number {
843
+ throw new Error('Method not implemented.');
844
+ }
845
+ }
846
+
847
+ export default BaseVolumeViewport;