@ohif/app 3.8.0-beta.8 → 3.8.0-beta.80

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 (99) hide show
  1. package/dist/{220.bundle.f7e1c96c94245e70f2be.js → 109.bundle.b4fee2a22b622839baf5.js} +4466 -3715
  2. package/dist/{471.bundle.49c8d281adbae4a2c4df.js → 121.bundle.787f5a848ed632a4d5fc.js} +90 -112
  3. package/dist/141.bundle.556b4c1e4cab770417ac.js +8620 -0
  4. package/dist/{687.bundle.9065db35c01823286f08.js → 164.bundle.d4598e491783753a8b6b.js} +22 -38
  5. package/dist/17dd54813d5acc10bf8f.wasm +0 -0
  6. package/dist/183.bundle.72bf18ad23ee6624986d.js +30394 -0
  7. package/dist/{506.bundle.5731bb4349e266491225.js → 188.bundle.b80554ec7df7dcd435a5.js} +23 -28
  8. package/dist/{342.bundle.e7c3d500f86fdfcc62b5.js → 206.bundle.f957e0d1cdff66dbac69.js} +1963 -1142
  9. package/dist/20fc4c659b85ccd2a9c0.wasm +0 -0
  10. package/dist/217.bundle.be1cc412f8e26be87d21.js +115079 -0
  11. package/dist/{451.bundle.57c21db5d003c75e9d61.js → 295.bundle.6f734abf8fa85b1a310d.js} +107 -127
  12. package/dist/{125.bundle.253395f320b72180da63.js → 297.bundle.194d8985ab974839b5b6.js} +7 -8
  13. package/dist/{19.bundle.f77c5787b6d8ac0b638b.js → 325.bundle.84909a08305556e9f924.js} +479 -371
  14. package/dist/335.bundle.c39d4aefe33aecab958f.js +2590 -0
  15. package/dist/{202.bundle.d3490836f71e001dd30f.js → 342.bundle.e6d0bba29351b5650a8c.js} +566 -868
  16. package/dist/{776.bundle.a2dedb405a12ffd7699b.js → 41.bundle.7c943bb857ed37831905.js} +7295 -3536
  17. package/dist/422.bundle.bd6529c536f59807fbee.js +881 -0
  18. package/dist/{957.bundle.9ea4506963ef8b2d84ba.js → 433.bundle.4c77c1fe8fc90ac14218.js} +14737 -27555
  19. package/dist/445.bundle.38c6d2af64e41cd7c614.js +7835 -0
  20. package/dist/{126.bundle.6e7111d58bcc937ffd80.js → 448.bundle.deedeff5744e77510734.js} +362 -430
  21. package/dist/487.bundle.7890ca42826941ebcd60.js +1875 -0
  22. package/dist/{886.bundle.c8dd3ecc42a4253de278.js → 530.bundle.7c94543955552475c56a.js} +98 -127
  23. package/dist/{663.bundle.d7be28450db14266cdd0.js → 540.bundle.079d43a6717e95c24392.js} +225 -188
  24. package/dist/{250.bundle.aea3335667054bdefe36.js → 544.bundle.1c1f57118560046649c1.js} +37 -62
  25. package/dist/574.bundle.be075ac52fb52b442a8b.js +2641 -0
  26. package/dist/{181.css → 574.css} +1 -1
  27. package/dist/{410.bundle.15c855b0ff4a1a674fb8.js → 594.bundle.0b1165661dd638820082.js} +183 -221
  28. package/dist/{221.bundle.aef554202c58483cb34e.js → 633.bundle.c1658e76f104cbd14cab.js} +349 -552
  29. package/dist/{774.bundle.4b2dc46a35012b898e1a.js → 644.bundle.1e77691d2eeb96a423b0.js} +1852 -8945
  30. package/dist/699.bundle.4f01772e7ce6637de339.js +768 -0
  31. package/dist/702.bundle.963481fbf871984b646f.js +8426 -0
  32. package/dist/722.bundle.afab1fe6bfcd569130ac.js +1083 -0
  33. package/dist/{359.bundle.45ecb3d28e8c22142606.js → 724.bundle.e5794460c391ee9cba2c.js} +164 -259
  34. package/dist/{757.bundle.ec8301d8e70d2b990f65.js → 726.bundle.0b3d9277d22fe7e15b89.js} +512 -879
  35. package/dist/{530.bundle.a03b6f942ace3e1baa1e.js → 835.bundle.15aff0b7433bb0dd6d6d.js} +37 -30
  36. package/dist/{822.bundle.82cdc418f8f56da6060b.js → 862.bundle.c0ee6e1d4d97e1353213.js} +77 -96
  37. package/dist/{236.bundle.4e9924934a747afac132.js → 889.bundle.7858e4b7ca1a2b12b64f.js} +207 -199
  38. package/dist/{281.bundle.deb7492d143e7768d8bf.js → 905.bundle.170908fe660fc6b40649.js} +157 -124
  39. package/dist/{814.bundle.c8c951d20039b63b865a.js → 907.bundle.dee4e30420caf07caea6.js} +16 -30
  40. package/dist/{417.bundle.af0a207c29b109f84159.js → 931.bundle.d270a1fda9a2836c3cc5.js} +26 -26
  41. package/dist/{686.bundle.dccef1f36e4bc79bcc48.js → 939.bundle.9d93b2e47c52338747a2.js} +7 -8
  42. package/dist/94.bundle.c452d9b0645277c2cf4e.js +784 -0
  43. package/dist/{12.bundle.b5ca13e5363f170ecb3b.js → 961.bundle.aaaaaba0ec015a3b85d8.js} +20 -33
  44. package/dist/app-config.js +1 -0
  45. package/dist/{app.bundle.a978edc59b9d82f2eb22.js → app.bundle.6c090a2d6d3ccc97a81d.js} +183240 -87650
  46. package/dist/app.bundle.css +16 -13
  47. package/dist/assets/images/CT-AAA.png +0 -0
  48. package/dist/assets/images/CT-AAA2.png +0 -0
  49. package/dist/assets/images/CT-Air.png +0 -0
  50. package/dist/assets/images/CT-Bone.png +0 -0
  51. package/dist/assets/images/CT-Bones.png +0 -0
  52. package/dist/assets/images/CT-Cardiac.png +0 -0
  53. package/dist/assets/images/CT-Cardiac2.png +0 -0
  54. package/dist/assets/images/CT-Cardiac3.png +0 -0
  55. package/dist/assets/images/CT-Chest-Contrast-Enhanced.png +0 -0
  56. package/dist/assets/images/CT-Chest-Vessels.png +0 -0
  57. package/dist/assets/images/CT-Coronary-Arteries-2.png +0 -0
  58. package/dist/assets/images/CT-Coronary-Arteries-3.png +0 -0
  59. package/dist/assets/images/CT-Coronary-Arteries.png +0 -0
  60. package/dist/assets/images/CT-Cropped-Volume-Bone.png +0 -0
  61. package/dist/assets/images/CT-Fat.png +0 -0
  62. package/dist/assets/images/CT-Liver-Vasculature.png +0 -0
  63. package/dist/assets/images/CT-Lung.png +0 -0
  64. package/dist/assets/images/CT-MIP.png +0 -0
  65. package/dist/assets/images/CT-Muscle.png +0 -0
  66. package/dist/assets/images/CT-Pulmonary-Arteries.png +0 -0
  67. package/dist/assets/images/CT-Soft-Tissue.png +0 -0
  68. package/dist/assets/images/DTI-FA-Brain.png +0 -0
  69. package/dist/assets/images/MR-Angio.png +0 -0
  70. package/dist/assets/images/MR-Default.png +0 -0
  71. package/dist/assets/images/MR-MIP.png +0 -0
  72. package/dist/assets/images/MR-T2-Brain.png +0 -0
  73. package/dist/assets/images/VolumeRendering.png +0 -0
  74. package/dist/cornerstoneDICOMImageLoader.min.js +1 -1
  75. package/dist/cornerstoneDICOMImageLoader.min.js.map +1 -1
  76. package/dist/{dicom-microscopy-viewer.bundle.2c146384eb9466d02ff8.js → dicom-microscopy-viewer.bundle.d3a56dc9f62df5e11019.js} +3 -3
  77. package/dist/histogram-worker.bundle.829e14ec12c2b41a4323.js +359 -0
  78. package/dist/index.html +1 -1
  79. package/dist/{index.worker.e62ecca63f1a2e124230.worker.js → index.worker.64c896c4316fcd506666.worker.js} +2 -2
  80. package/dist/index.worker.64c896c4316fcd506666.worker.js.map +1 -0
  81. package/dist/polySeg.bundle.63011312c3c79e717ea9.js +249 -0
  82. package/dist/serve.json +12 -0
  83. package/dist/sw.js +1 -1
  84. package/package.json +26 -22
  85. package/dist/181.bundle.a62b9f0ec692299acb35.js +0 -1527
  86. package/dist/23.bundle.e008ad788170f2ed5569.js +0 -900
  87. package/dist/604.bundle.a51f83e64004bca5f497.js +0 -1848
  88. package/dist/613.bundle.9e7072e5b575354fe51e.js +0 -532
  89. package/dist/743.bundle.489f7df3a089d4d374e1.js +0 -78007
  90. package/dist/75788f12450d4c5ed494.wasm +0 -0
  91. package/dist/775.bundle.2285e7e0e67878948c0d.js +0 -1009
  92. package/dist/788.bundle.207ac23c0dfa70cbe3fb.js +0 -2682
  93. package/dist/82.bundle.d6fdcca0f67540bb226a.js +0 -1049
  94. package/dist/index.worker.e62ecca63f1a2e124230.worker.js.map +0 -1
  95. /package/dist/{19.css → 325.css} +0 -0
  96. /package/dist/{776.css → 41.css} +0 -0
  97. /package/dist/{579.css → 481.css} +0 -0
  98. /package/dist/{250.css → 544.css} +0 -0
  99. /package/dist/{221.css → 633.css} +0 -0
@@ -1,1527 +0,0 @@
1
- "use strict";
2
- (self["webpackChunk"] = self["webpackChunk"] || []).push([[181],{
3
-
4
- /***/ 86181:
5
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
6
-
7
- // ESM COMPAT FLAG
8
- __webpack_require__.r(__webpack_exports__);
9
-
10
- // EXPORTS
11
- __webpack_require__.d(__webpack_exports__, {
12
- "default": () => (/* binding */ Viewport_OHIFCornerstoneViewport)
13
- });
14
-
15
- // EXTERNAL MODULE: ../../../node_modules/react/index.js
16
- var react = __webpack_require__(43001);
17
- // EXTERNAL MODULE: ../../../node_modules/react-resize-detector/build/index.esm.js
18
- var index_esm = __webpack_require__(7023);
19
- // EXTERNAL MODULE: ../../../node_modules/prop-types/index.js
20
- var prop_types = __webpack_require__(3827);
21
- var prop_types_default = /*#__PURE__*/__webpack_require__.n(prop_types);
22
- // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/index.js + 348 modules
23
- var esm = __webpack_require__(14957);
24
- // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/index.js + 331 modules
25
- var dist_esm = __webpack_require__(3743);
26
- // EXTERNAL MODULE: ../../core/src/index.ts + 65 modules
27
- var src = __webpack_require__(71771);
28
- // EXTERNAL MODULE: ../../ui/src/index.js + 486 modules
29
- var ui_src = __webpack_require__(22582);
30
- // EXTERNAL MODULE: ../../../extensions/cornerstone/src/state.ts
31
- var state = __webpack_require__(73704);
32
- ;// CONCATENATED MODULE: ../../../extensions/cornerstone/src/Viewport/OHIFCornerstoneViewport.css
33
- // extracted by mini-css-extract-plugin
34
-
35
- ;// CONCATENATED MODULE: ../../../extensions/cornerstone/src/Viewport/Overlays/ViewportImageScrollbar.tsx
36
-
37
-
38
-
39
-
40
-
41
- function CornerstoneImageScrollbar(_ref) {
42
- let {
43
- viewportData,
44
- viewportId,
45
- element,
46
- imageSliceData,
47
- setImageSliceData,
48
- scrollbarHeight,
49
- servicesManager
50
- } = _ref;
51
- const {
52
- cineService,
53
- cornerstoneViewportService
54
- } = servicesManager.services;
55
- const onImageScrollbarChange = (imageIndex, viewportId) => {
56
- const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
57
- const {
58
- isCineEnabled
59
- } = cineService.getState();
60
- if (isCineEnabled) {
61
- // on image scrollbar change, stop the CINE if it is playing
62
- cineService.stopClip(element);
63
- cineService.setCine({
64
- id: viewportId,
65
- isPlaying: false
66
- });
67
- }
68
- esm.utilities.jumpToSlice(viewport.element, {
69
- imageIndex,
70
- debounceLoading: true
71
- });
72
- };
73
- (0,react.useEffect)(() => {
74
- if (!viewportData) {
75
- return;
76
- }
77
- const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
78
- if (!viewport) {
79
- return;
80
- }
81
- if (viewportData.viewportType === dist_esm.Enums.ViewportType.STACK) {
82
- const imageIndex = viewport.getCurrentImageIdIndex();
83
- setImageSliceData({
84
- imageIndex: imageIndex,
85
- numberOfSlices: viewportData.data.imageIds.length
86
- });
87
- return;
88
- }
89
- if (viewportData.viewportType === dist_esm.Enums.ViewportType.ORTHOGRAPHIC) {
90
- const sliceData = dist_esm.utilities.getImageSliceDataForVolumeViewport(viewport);
91
- if (!sliceData) {
92
- return;
93
- }
94
- const {
95
- imageIndex,
96
- numberOfSlices
97
- } = sliceData;
98
- setImageSliceData({
99
- imageIndex,
100
- numberOfSlices
101
- });
102
- }
103
- }, [viewportId, viewportData]);
104
- (0,react.useEffect)(() => {
105
- if (viewportData?.viewportType !== dist_esm.Enums.ViewportType.STACK) {
106
- return;
107
- }
108
- const updateStackIndex = event => {
109
- const {
110
- newImageIdIndex
111
- } = event.detail;
112
- // find the index of imageId in the imageIds
113
- setImageSliceData({
114
- imageIndex: newImageIdIndex,
115
- numberOfSlices: viewportData.data.imageIds.length
116
- });
117
- };
118
- element.addEventListener(dist_esm.Enums.Events.STACK_VIEWPORT_SCROLL, updateStackIndex);
119
- return () => {
120
- element.removeEventListener(dist_esm.Enums.Events.STACK_VIEWPORT_SCROLL, updateStackIndex);
121
- };
122
- }, [viewportData, element]);
123
- (0,react.useEffect)(() => {
124
- if (viewportData?.viewportType !== dist_esm.Enums.ViewportType.ORTHOGRAPHIC) {
125
- return;
126
- }
127
- const updateVolumeIndex = event => {
128
- const {
129
- imageIndex,
130
- numberOfSlices
131
- } = event.detail;
132
- // find the index of imageId in the imageIds
133
- setImageSliceData({
134
- imageIndex,
135
- numberOfSlices
136
- });
137
- };
138
- element.addEventListener(dist_esm.Enums.Events.VOLUME_NEW_IMAGE, updateVolumeIndex);
139
- return () => {
140
- element.removeEventListener(dist_esm.Enums.Events.VOLUME_NEW_IMAGE, updateVolumeIndex);
141
- };
142
- }, [viewportData, element]);
143
- return /*#__PURE__*/react.createElement(ui_src/* ImageScrollbar */.Ln, {
144
- onChange: evt => onImageScrollbarChange(evt, viewportId),
145
- max: imageSliceData.numberOfSlices ? imageSliceData.numberOfSlices - 1 : 0,
146
- height: scrollbarHeight,
147
- value: imageSliceData.imageIndex
148
- });
149
- }
150
- CornerstoneImageScrollbar.propTypes = {
151
- viewportData: (prop_types_default()).object,
152
- viewportId: (prop_types_default()).string.isRequired,
153
- element: prop_types_default().instanceOf(Element),
154
- scrollbarHeight: (prop_types_default()).string,
155
- imageSliceData: (prop_types_default()).object.isRequired,
156
- setImageSliceData: (prop_types_default()).func.isRequired,
157
- servicesManager: (prop_types_default()).object.isRequired
158
- };
159
- /* harmony default export */ const ViewportImageScrollbar = (CornerstoneImageScrollbar);
160
- // EXTERNAL MODULE: ../../../node_modules/gl-matrix/esm/index.js + 10 modules
161
- var gl_matrix_esm = __webpack_require__(45451);
162
- // EXTERNAL MODULE: ../../../node_modules/moment/moment.js
163
- var moment = __webpack_require__(71271);
164
- var moment_default = /*#__PURE__*/__webpack_require__.n(moment);
165
- ;// CONCATENATED MODULE: ../../../extensions/cornerstone/src/Viewport/Overlays/utils.ts
166
-
167
-
168
-
169
- /**
170
- * Checks if value is valid.
171
- *
172
- * @param {number} value
173
- * @returns {boolean} is valid.
174
- */
175
- function isValidNumber(value) {
176
- return typeof value === 'number' && !isNaN(value);
177
- }
178
-
179
- /**
180
- * Formats number precision.
181
- *
182
- * @param {number} number
183
- * @param {number} precision
184
- * @returns {number} formatted number.
185
- */
186
- function formatNumberPrecision(number) {
187
- let precision = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
188
- if (number !== null) {
189
- return parseFloat(number).toFixed(precision);
190
- }
191
- }
192
-
193
- /**
194
- * Formats DICOM date.
195
- *
196
- * @param {string} date
197
- * @param {string} strFormat
198
- * @returns {string} formatted date.
199
- */
200
- function formatDICOMDate(date) {
201
- let strFormat = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'MMM D, YYYY';
202
- return moment_default()(date, 'YYYYMMDD').format(strFormat);
203
- }
204
-
205
- /**
206
- * DICOM Time is stored as HHmmss.SSS, where:
207
- * HH 24 hour time:
208
- * m mm 0..59 Minutes
209
- * s ss 0..59 Seconds
210
- * S SS SSS 0..999 Fractional seconds
211
- *
212
- * Goal: '24:12:12'
213
- *
214
- * @param {*} time
215
- * @param {string} strFormat
216
- * @returns {string} formatted name.
217
- */
218
- function formatDICOMTime(time) {
219
- let strFormat = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'HH:mm:ss';
220
- return moment_default()(time, 'HH:mm:ss').format(strFormat);
221
- }
222
-
223
- /**
224
- * Formats a patient name for display purposes
225
- *
226
- * @param {string} name
227
- * @returns {string} formatted name.
228
- */
229
- function formatPN(name) {
230
- if (!name) {
231
- return '';
232
- }
233
- const cleaned = name.split('^').filter(s => !!s).join(', ').trim();
234
- return cleaned === ',' || cleaned === '' ? '' : cleaned;
235
- }
236
-
237
- /**
238
- * Gets compression type
239
- *
240
- * @param {number} imageId
241
- * @returns {string} compression type.
242
- */
243
- function getCompression(imageId) {
244
- const generalImageModule = metaData.get('generalImageModule', imageId) || {};
245
- const {
246
- lossyImageCompression,
247
- lossyImageCompressionRatio,
248
- lossyImageCompressionMethod
249
- } = generalImageModule;
250
- if (lossyImageCompression === '01' && lossyImageCompressionRatio !== '') {
251
- const compressionMethod = lossyImageCompressionMethod || 'Lossy: ';
252
- const compressionRatio = formatNumberPrecision(lossyImageCompressionRatio, 2);
253
- return compressionMethod + compressionRatio + ' : 1';
254
- }
255
- return 'Lossless / Uncompressed';
256
- }
257
- ;// CONCATENATED MODULE: ../../../extensions/cornerstone/src/Viewport/Overlays/CustomizableViewportOverlay.css
258
- // extracted by mini-css-extract-plugin
259
-
260
- ;// CONCATENATED MODULE: ../../../extensions/cornerstone/src/Viewport/Overlays/CustomizableViewportOverlay.tsx
261
-
262
-
263
-
264
-
265
-
266
-
267
-
268
- const EPSILON = 1e-4;
269
- /**
270
- * Window Level / Center Overlay item
271
- */
272
- function VOIOverlayItem(_ref) {
273
- let {
274
- voi,
275
- customization
276
- } = _ref;
277
- const {
278
- windowWidth,
279
- windowCenter
280
- } = voi;
281
- if (typeof windowCenter !== 'number' || typeof windowWidth !== 'number') {
282
- return null;
283
- }
284
- return /*#__PURE__*/react.createElement("div", {
285
- className: "overlay-item flex flex-row",
286
- style: {
287
- color: customization && customization.color || undefined
288
- }
289
- }, /*#__PURE__*/react.createElement("span", {
290
- className: "mr-1 shrink-0"
291
- }, "W:"), /*#__PURE__*/react.createElement("span", {
292
- className: "ml-1 mr-2 shrink-0 font-light"
293
- }, windowWidth.toFixed(0)), /*#__PURE__*/react.createElement("span", {
294
- className: "mr-1 shrink-0"
295
- }, "L:"), /*#__PURE__*/react.createElement("span", {
296
- className: "ml-1 shrink-0 font-light"
297
- }, windowCenter.toFixed(0)));
298
- }
299
-
300
- /**
301
- * Zoom Level Overlay item
302
- */
303
- function ZoomOverlayItem(_ref2) {
304
- let {
305
- scale,
306
- customization
307
- } = _ref2;
308
- return /*#__PURE__*/react.createElement("div", {
309
- className: "overlay-item flex flex-row",
310
- style: {
311
- color: customization && customization.color || undefined
312
- }
313
- }, /*#__PURE__*/react.createElement("span", {
314
- className: "mr-1 shrink-0"
315
- }, "Zoom:"), /*#__PURE__*/react.createElement("span", {
316
- className: "font-light"
317
- }, scale.toFixed(2), "x"));
318
- }
319
-
320
- /**
321
- * Instance Number Overlay Item
322
- */
323
- function InstanceNumberOverlayItem(_ref3) {
324
- let {
325
- instanceNumber,
326
- imageSliceData,
327
- customization
328
- } = _ref3;
329
- const {
330
- imageIndex,
331
- numberOfSlices
332
- } = imageSliceData;
333
- return /*#__PURE__*/react.createElement("div", {
334
- className: "overlay-item flex flex-row",
335
- style: {
336
- color: customization && customization.color || undefined
337
- }
338
- }, /*#__PURE__*/react.createElement("span", {
339
- className: "mr-1 shrink-0"
340
- }, "I:"), /*#__PURE__*/react.createElement("span", {
341
- className: "font-light"
342
- }, instanceNumber !== undefined && instanceNumber !== null ? `${instanceNumber} (${imageIndex + 1}/${numberOfSlices})` : `${imageIndex + 1}/${numberOfSlices}`));
343
- }
344
-
345
- /**
346
- * Customizable Viewport Overlay
347
- */
348
- function CustomizableViewportOverlay(_ref4) {
349
- let {
350
- element,
351
- viewportData,
352
- imageSliceData,
353
- viewportId,
354
- servicesManager
355
- } = _ref4;
356
- const {
357
- toolbarService,
358
- cornerstoneViewportService,
359
- customizationService
360
- } = servicesManager.services;
361
- const [voi, setVOI] = (0,react.useState)({
362
- windowCenter: null,
363
- windowWidth: null
364
- });
365
- const [scale, setScale] = (0,react.useState)(1);
366
- const [activeTools, setActiveTools] = (0,react.useState)([]);
367
- const {
368
- imageIndex
369
- } = imageSliceData;
370
- const topLeftCustomization = customizationService.getModeCustomization('cornerstoneOverlayTopLeft');
371
- const topRightCustomization = customizationService.getModeCustomization('cornerstoneOverlayTopRight');
372
- const bottomLeftCustomization = customizationService.getModeCustomization('cornerstoneOverlayBottomLeft');
373
- const bottomRightCustomization = customizationService.getModeCustomization('cornerstoneOverlayBottomRight');
374
- const instance = (0,react.useMemo)(() => {
375
- if (viewportData != null) {
376
- return _getViewportInstance(viewportData, imageIndex);
377
- } else {
378
- return null;
379
- }
380
- }, [viewportData, imageIndex]);
381
- const instanceNumber = (0,react.useMemo)(() => {
382
- if (viewportData != null) {
383
- return _getInstanceNumber(viewportData, viewportId, imageIndex, cornerstoneViewportService);
384
- }
385
- return null;
386
- }, [viewportData, viewportId, imageIndex, cornerstoneViewportService]);
387
-
388
- /**
389
- * Initial toolbar state
390
- */
391
- (0,react.useEffect)(() => {
392
- setActiveTools(toolbarService.getActiveTools());
393
- }, []);
394
-
395
- /**
396
- * Updating the VOI when the viewport changes its voi
397
- */
398
- (0,react.useEffect)(() => {
399
- const updateVOI = eventDetail => {
400
- const {
401
- range
402
- } = eventDetail.detail;
403
- if (!range) {
404
- return;
405
- }
406
- const {
407
- lower,
408
- upper
409
- } = range;
410
- const {
411
- windowWidth,
412
- windowCenter
413
- } = dist_esm.utilities.windowLevel.toWindowLevel(lower, upper);
414
- setVOI({
415
- windowCenter,
416
- windowWidth
417
- });
418
- };
419
- element.addEventListener(dist_esm.Enums.Events.VOI_MODIFIED, updateVOI);
420
- return () => {
421
- element.removeEventListener(dist_esm.Enums.Events.VOI_MODIFIED, updateVOI);
422
- };
423
- }, [viewportId, viewportData, voi, element]);
424
-
425
- /**
426
- * Updating the scale when the viewport changes its zoom
427
- */
428
- (0,react.useEffect)(() => {
429
- const updateScale = eventDetail => {
430
- const {
431
- previousCamera,
432
- camera
433
- } = eventDetail.detail;
434
- if (previousCamera.parallelScale !== camera.parallelScale || previousCamera.scale !== camera.scale) {
435
- const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
436
- if (!viewport) {
437
- return;
438
- }
439
- const imageData = viewport.getImageData();
440
- if (!imageData) {
441
- return;
442
- }
443
- if (camera.scale) {
444
- setScale(camera.scale);
445
- return;
446
- }
447
- const {
448
- spacing
449
- } = imageData;
450
- // convert parallel scale to scale
451
- const scale = element.clientHeight * spacing[0] * 0.5 / camera.parallelScale;
452
- setScale(scale);
453
- }
454
- };
455
- element.addEventListener(dist_esm.Enums.Events.CAMERA_MODIFIED, updateScale);
456
- return () => {
457
- element.removeEventListener(dist_esm.Enums.Events.CAMERA_MODIFIED, updateScale);
458
- };
459
- }, [viewportId, viewportData, cornerstoneViewportService, element]);
460
-
461
- /**
462
- * Updating the active tools when the toolbar changes
463
- */
464
- // Todo: this should act on the toolGroups instead of the toolbar state
465
- (0,react.useEffect)(() => {
466
- const {
467
- unsubscribe
468
- } = toolbarService.subscribe(toolbarService.EVENTS.TOOL_BAR_STATE_MODIFIED, () => {
469
- setActiveTools(toolbarService.getActiveTools());
470
- });
471
- return () => {
472
- unsubscribe();
473
- };
474
- }, [toolbarService]);
475
- const _renderOverlayItem = (0,react.useCallback)(item => {
476
- const overlayItemProps = {
477
- element,
478
- viewportData,
479
- imageSliceData,
480
- viewportId,
481
- servicesManager,
482
- customization: item,
483
- formatters: {
484
- formatPN: formatPN,
485
- formatDate: formatDICOMDate,
486
- formatTime: formatDICOMTime,
487
- formatNumberPrecision: formatNumberPrecision
488
- },
489
- instance,
490
- // calculated
491
- voi,
492
- scale,
493
- instanceNumber
494
- };
495
- if (item.customizationType === 'ohif.overlayItem.windowLevel') {
496
- return /*#__PURE__*/react.createElement(VOIOverlayItem, overlayItemProps);
497
- } else if (item.customizationType === 'ohif.overlayItem.zoomLevel') {
498
- return /*#__PURE__*/react.createElement(ZoomOverlayItem, overlayItemProps);
499
- } else if (item.customizationType === 'ohif.overlayItem.instanceNumber') {
500
- return /*#__PURE__*/react.createElement(InstanceNumberOverlayItem, overlayItemProps);
501
- } else {
502
- const renderItem = customizationService.transform(item);
503
- if (typeof renderItem.content === 'function') {
504
- return renderItem.content(overlayItemProps);
505
- }
506
- }
507
- }, [element, viewportData, imageSliceData, viewportId, servicesManager, customizationService, instance, voi, scale, instanceNumber]);
508
- const getTopLeftContent = (0,react.useCallback)(() => {
509
- const items = topLeftCustomization?.items || [{
510
- id: 'WindowLevel',
511
- customizationType: 'ohif.overlayItem.windowLevel'
512
- }];
513
- return /*#__PURE__*/react.createElement(react.Fragment, null, items.map((item, i) => /*#__PURE__*/react.createElement("div", {
514
- key: `topLeftOverlayItem_${i}`
515
- }, _renderOverlayItem(item))));
516
- }, [topLeftCustomization, _renderOverlayItem]);
517
- const getTopRightContent = (0,react.useCallback)(() => {
518
- const items = topRightCustomization?.items || [{
519
- id: 'InstanceNmber',
520
- customizationType: 'ohif.overlayItem.instanceNumber'
521
- }];
522
- return /*#__PURE__*/react.createElement(react.Fragment, null, items.map((item, i) => /*#__PURE__*/react.createElement("div", {
523
- key: `topRightOverlayItem_${i}`
524
- }, _renderOverlayItem(item))));
525
- }, [topRightCustomization, _renderOverlayItem]);
526
- const getBottomLeftContent = (0,react.useCallback)(() => {
527
- const items = bottomLeftCustomization?.items || [];
528
- return /*#__PURE__*/react.createElement(react.Fragment, null, items.map((item, i) => /*#__PURE__*/react.createElement("div", {
529
- key: `bottomLeftOverlayItem_${i}`
530
- }, _renderOverlayItem(item))));
531
- }, [bottomLeftCustomization, _renderOverlayItem]);
532
- const getBottomRightContent = (0,react.useCallback)(() => {
533
- const items = bottomRightCustomization?.items || [];
534
- return /*#__PURE__*/react.createElement(react.Fragment, null, items.map((item, i) => /*#__PURE__*/react.createElement("div", {
535
- key: `bottomRightOverlayItem_${i}`
536
- }, _renderOverlayItem(item))));
537
- }, [bottomRightCustomization, _renderOverlayItem]);
538
- return /*#__PURE__*/react.createElement(ui_src/* ViewportOverlay */.No, {
539
- topLeft: getTopLeftContent(),
540
- topRight: getTopRightContent(),
541
- bottomLeft: getBottomLeftContent(),
542
- bottomRight: getBottomRightContent()
543
- });
544
- }
545
- function _getViewportInstance(viewportData, imageIndex) {
546
- let imageId = null;
547
- if (viewportData.viewportType === dist_esm.Enums.ViewportType.STACK) {
548
- imageId = viewportData.data.imageIds[imageIndex];
549
- } else if (viewportData.viewportType === dist_esm.Enums.ViewportType.ORTHOGRAPHIC) {
550
- const volumes = viewportData.data;
551
- if (volumes && volumes.length == 1) {
552
- const volume = volumes[0];
553
- imageId = volume.imageIds[imageIndex];
554
- }
555
- }
556
- return imageId ? dist_esm.metaData.get('instance', imageId) || {} : {};
557
- }
558
- function _getInstanceNumber(viewportData, viewportId, imageIndex, cornerstoneViewportService) {
559
- let instanceNumber;
560
- if (viewportData.viewportType === dist_esm.Enums.ViewportType.STACK) {
561
- instanceNumber = _getInstanceNumberFromStack(viewportData, imageIndex);
562
- if (!instanceNumber && instanceNumber !== 0) {
563
- return null;
564
- }
565
- } else if (viewportData.viewportType === dist_esm.Enums.ViewportType.ORTHOGRAPHIC) {
566
- instanceNumber = _getInstanceNumberFromVolume(viewportData, imageIndex, viewportId, cornerstoneViewportService);
567
- }
568
- return instanceNumber;
569
- }
570
- function _getInstanceNumberFromStack(viewportData, imageIndex) {
571
- const imageIds = viewportData.data.imageIds;
572
- const imageId = imageIds[imageIndex];
573
- if (!imageId) {
574
- return;
575
- }
576
- const generalImageModule = dist_esm.metaData.get('generalImageModule', imageId) || {};
577
- const {
578
- instanceNumber
579
- } = generalImageModule;
580
- const stackSize = imageIds.length;
581
- if (stackSize <= 1) {
582
- return;
583
- }
584
- return parseInt(instanceNumber);
585
- }
586
-
587
- // Since volume viewports can be in any view direction, they can render
588
- // a reconstructed image which don't have imageIds; therefore, no instance and instanceNumber
589
- // Here we check if viewport is in the acquisition direction and if so, we get the instanceNumber
590
- function _getInstanceNumberFromVolume(viewportData, viewportId, cornerstoneViewportService) {
591
- const volumes = viewportData.volumes;
592
-
593
- // Todo: support fusion of acquisition plane which has instanceNumber
594
- if (!volumes || volumes.length > 1) {
595
- return;
596
- }
597
- const volume = volumes[0];
598
- const {
599
- direction,
600
- imageIds
601
- } = volume;
602
- const cornerstoneViewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
603
- if (!cornerstoneViewport) {
604
- return;
605
- }
606
- const camera = cornerstoneViewport.getCamera();
607
- const {
608
- viewPlaneNormal
609
- } = camera;
610
- // checking if camera is looking at the acquisition plane (defined by the direction on the volume)
611
-
612
- const scanAxisNormal = direction.slice(6, 9);
613
-
614
- // check if viewPlaneNormal is parallel to scanAxisNormal
615
- const cross = gl_matrix_esm/* vec3.cross */.R3.cross(gl_matrix_esm/* vec3.create */.R3.create(), viewPlaneNormal, scanAxisNormal);
616
- const isAcquisitionPlane = gl_matrix_esm/* vec3.length */.R3.length(cross) < EPSILON;
617
- if (isAcquisitionPlane) {
618
- const imageId = imageIds[imageIndex];
619
- if (!imageId) {
620
- return {};
621
- }
622
- const {
623
- instanceNumber
624
- } = dist_esm.metaData.get('generalImageModule', imageId) || {};
625
- return parseInt(instanceNumber);
626
- }
627
- }
628
- CustomizableViewportOverlay.propTypes = {
629
- viewportData: (prop_types_default()).object,
630
- imageIndex: (prop_types_default()).number,
631
- viewportId: (prop_types_default()).string
632
- };
633
- /* harmony default export */ const Overlays_CustomizableViewportOverlay = (CustomizableViewportOverlay);
634
- // EXTERNAL MODULE: ../../../node_modules/classnames/index.js
635
- var classnames = __webpack_require__(44921);
636
- var classnames_default = /*#__PURE__*/__webpack_require__.n(classnames);
637
- ;// CONCATENATED MODULE: ../../../extensions/cornerstone/src/Viewport/Overlays/ViewportOrientationMarkers.css
638
- // extracted by mini-css-extract-plugin
639
-
640
- ;// CONCATENATED MODULE: ../../../extensions/cornerstone/src/Viewport/Overlays/ViewportOrientationMarkers.tsx
641
-
642
-
643
-
644
-
645
-
646
-
647
-
648
- const {
649
- getOrientationStringLPS,
650
- invertOrientationStringLPS
651
- } = esm.utilities.orientation;
652
- function ViewportOrientationMarkers(_ref) {
653
- let {
654
- element,
655
- viewportData,
656
- imageSliceData,
657
- viewportId,
658
- servicesManager,
659
- orientationMarkers = ['top', 'left']
660
- } = _ref;
661
- // Rotation is in degrees
662
- const [rotation, setRotation] = (0,react.useState)(0);
663
- const [flipHorizontal, setFlipHorizontal] = (0,react.useState)(false);
664
- const [flipVertical, setFlipVertical] = (0,react.useState)(false);
665
- const {
666
- cornerstoneViewportService
667
- } = servicesManager.services;
668
- (0,react.useEffect)(() => {
669
- const cameraModifiedListener = evt => {
670
- const {
671
- rotation,
672
- previousCamera,
673
- camera
674
- } = evt.detail;
675
- if (rotation !== undefined) {
676
- setRotation(rotation);
677
- }
678
- if (camera.flipHorizontal !== undefined && previousCamera.flipHorizontal !== camera.flipHorizontal) {
679
- setFlipHorizontal(camera.flipHorizontal);
680
- }
681
- if (camera.flipVertical !== undefined && previousCamera.flipVertical !== camera.flipVertical) {
682
- setFlipVertical(camera.flipVertical);
683
- }
684
- };
685
- element.addEventListener(dist_esm.Enums.Events.CAMERA_MODIFIED, cameraModifiedListener);
686
- return () => {
687
- element.removeEventListener(dist_esm.Enums.Events.CAMERA_MODIFIED, cameraModifiedListener);
688
- };
689
- }, []);
690
- const markers = (0,react.useMemo)(() => {
691
- if (!viewportData) {
692
- return '';
693
- }
694
- let rowCosines, columnCosines;
695
- if (viewportData.viewportType === 'stack') {
696
- const imageIndex = imageSliceData.imageIndex;
697
- const imageId = viewportData.data.imageIds?.[imageIndex];
698
-
699
- // Workaround for below TODO stub
700
- if (!imageId) {
701
- return false;
702
- }
703
- ({
704
- rowCosines,
705
- columnCosines
706
- } = dist_esm.metaData.get('imagePlaneModule', imageId) || {});
707
- } else {
708
- if (!element || !(0,dist_esm.getEnabledElement)(element)) {
709
- return '';
710
- }
711
- const {
712
- viewport
713
- } = (0,dist_esm.getEnabledElement)(element);
714
- const {
715
- viewUp,
716
- viewPlaneNormal
717
- } = viewport.getCamera();
718
- const viewRight = gl_matrix_esm/* vec3.create */.R3.create();
719
- gl_matrix_esm/* vec3.cross */.R3.cross(viewRight, viewUp, viewPlaneNormal);
720
- columnCosines = [-viewUp[0], -viewUp[1], -viewUp[2]];
721
- rowCosines = viewRight;
722
- }
723
- if (!rowCosines || !columnCosines || rotation === undefined) {
724
- return '';
725
- }
726
- const markers = _getOrientationMarkers(rowCosines, columnCosines, rotation, flipVertical, flipHorizontal);
727
- const ohifViewport = cornerstoneViewportService.getViewportInfo(viewportId);
728
- if (!ohifViewport) {
729
- console.log('ViewportOrientationMarkers::No viewport');
730
- return null;
731
- }
732
- const backgroundColor = ohifViewport.getViewportOptions().background;
733
-
734
- // Todo: probably this can be done in a better way in which we identify bright
735
- // background
736
- const isLight = backgroundColor ? dist_esm.utilities.isEqual(backgroundColor, [1, 1, 1]) : false;
737
- return orientationMarkers.map((m, index) => /*#__PURE__*/react.createElement("div", {
738
- className: classnames_default()(`${m}-mid orientation-marker`, isLight ? 'text-[#726F7E]' : 'text-[#ccc]'),
739
- key: `${m}-mid orientation-marker`
740
- }, /*#__PURE__*/react.createElement("div", {
741
- className: "orientation-marker-value"
742
- }, markers[m])));
743
- }, [viewportData, imageSliceData, rotation, flipVertical, flipHorizontal, orientationMarkers, element]);
744
- return /*#__PURE__*/react.createElement("div", {
745
- className: "ViewportOrientationMarkers noselect"
746
- }, markers);
747
- }
748
- ViewportOrientationMarkers.propTypes = {
749
- percentComplete: (prop_types_default()).number,
750
- error: (prop_types_default()).object
751
- };
752
- ViewportOrientationMarkers.defaultProps = {
753
- percentComplete: 0,
754
- error: null
755
- };
756
-
757
- /**
758
- *
759
- * Computes the orientation labels on a Cornerstone-enabled Viewport element
760
- * when the viewport settings change (e.g. when a horizontal flip or a rotation occurs)
761
- *
762
- * @param {*} rowCosines
763
- * @param {*} columnCosines
764
- * @param {*} rotation in degrees
765
- * @returns
766
- */
767
- function _getOrientationMarkers(rowCosines, columnCosines, rotation, flipVertical, flipHorizontal) {
768
- const rowString = getOrientationStringLPS(rowCosines);
769
- const columnString = getOrientationStringLPS(columnCosines);
770
- const oppositeRowString = invertOrientationStringLPS(rowString);
771
- const oppositeColumnString = invertOrientationStringLPS(columnString);
772
- const markers = {
773
- top: oppositeColumnString,
774
- left: oppositeRowString,
775
- right: rowString,
776
- bottom: columnString
777
- };
778
-
779
- // If any vertical or horizontal flips are applied, change the orientation strings ahead of
780
- // the rotation applications
781
- if (flipVertical) {
782
- markers.top = invertOrientationStringLPS(markers.top);
783
- markers.bottom = invertOrientationStringLPS(markers.bottom);
784
- }
785
- if (flipHorizontal) {
786
- markers.left = invertOrientationStringLPS(markers.left);
787
- markers.right = invertOrientationStringLPS(markers.right);
788
- }
789
-
790
- // Swap the labels accordingly if the viewport has been rotated
791
- // This could be done in a more complex way for intermediate rotation values (e.g. 45 degrees)
792
- if (rotation === 90 || rotation === -270) {
793
- return {
794
- top: markers.left,
795
- left: invertOrientationStringLPS(markers.top),
796
- right: invertOrientationStringLPS(markers.bottom),
797
- bottom: markers.right // left
798
- };
799
- } else if (rotation === -90 || rotation === 270) {
800
- return {
801
- top: invertOrientationStringLPS(markers.left),
802
- left: markers.top,
803
- bottom: markers.left,
804
- right: markers.bottom
805
- };
806
- } else if (rotation === 180 || rotation === -180) {
807
- return {
808
- top: invertOrientationStringLPS(markers.top),
809
- left: invertOrientationStringLPS(markers.left),
810
- bottom: invertOrientationStringLPS(markers.bottom),
811
- right: invertOrientationStringLPS(markers.right)
812
- };
813
- }
814
- return markers;
815
- }
816
- /* harmony default export */ const Overlays_ViewportOrientationMarkers = (ViewportOrientationMarkers);
817
- ;// CONCATENATED MODULE: ../../../extensions/cornerstone/src/Viewport/Overlays/ViewportImageSliceLoadingIndicator.tsx
818
-
819
-
820
-
821
- function ViewportImageSliceLoadingIndicator(_ref) {
822
- let {
823
- viewportData,
824
- element
825
- } = _ref;
826
- const [loading, setLoading] = (0,react.useState)(false);
827
- const [error, setError] = (0,react.useState)(false);
828
- const loadIndicatorRef = (0,react.useRef)(null);
829
- const imageIdToBeLoaded = (0,react.useRef)(null);
830
- const setLoadingState = evt => {
831
- clearTimeout(loadIndicatorRef.current);
832
- loadIndicatorRef.current = setTimeout(() => {
833
- setLoading(true);
834
- }, 50);
835
- };
836
- const setFinishLoadingState = evt => {
837
- clearTimeout(loadIndicatorRef.current);
838
- setLoading(false);
839
- };
840
- const setErrorState = evt => {
841
- clearTimeout(loadIndicatorRef.current);
842
- if (imageIdToBeLoaded.current === evt.detail.imageId) {
843
- setError(evt.detail.error);
844
- imageIdToBeLoaded.current = null;
845
- }
846
- };
847
- (0,react.useEffect)(() => {
848
- element.addEventListener(dist_esm.Enums.Events.STACK_VIEWPORT_SCROLL, setLoadingState);
849
- element.addEventListener(dist_esm.Enums.Events.IMAGE_LOAD_ERROR, setErrorState);
850
- element.addEventListener(dist_esm.Enums.Events.STACK_NEW_IMAGE, setFinishLoadingState);
851
- return () => {
852
- element.removeEventListener(dist_esm.Enums.Events.STACK_VIEWPORT_SCROLL, setLoadingState);
853
- element.removeEventListener(dist_esm.Enums.Events.STACK_NEW_IMAGE, setFinishLoadingState);
854
- element.removeEventListener(dist_esm.Enums.Events.IMAGE_LOAD_ERROR, setErrorState);
855
- };
856
- }, [element, viewportData]);
857
- if (error) {
858
- return /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement("div", {
859
- className: "absolute top-0 left-0 h-full w-full bg-black opacity-50"
860
- }, /*#__PURE__*/react.createElement("div", {
861
- className: "transparent flex h-full w-full items-center justify-center"
862
- }, /*#__PURE__*/react.createElement("p", {
863
- className: "text-primary-light text-xl font-light"
864
- }, /*#__PURE__*/react.createElement("h4", null, "Error Loading Image"), /*#__PURE__*/react.createElement("p", null, "An error has occurred."), /*#__PURE__*/react.createElement("p", null, error)))));
865
- }
866
- if (loading) {
867
- return (
868
- /*#__PURE__*/
869
- // IMPORTANT: we need to use the pointer-events-none class to prevent the loading indicator from
870
- // interacting with the mouse, since scrolling should propagate to the viewport underneath
871
- react.createElement("div", {
872
- className: "pointer-events-none absolute top-0 left-0 h-full w-full bg-black opacity-50"
873
- }, /*#__PURE__*/react.createElement("div", {
874
- className: "transparent flex h-full w-full items-center justify-center"
875
- }, /*#__PURE__*/react.createElement("p", {
876
- className: "text-primary-light text-xl font-light"
877
- }, "Loading...")))
878
- );
879
- }
880
- return null;
881
- }
882
- ViewportImageSliceLoadingIndicator.propTypes = {
883
- percentComplete: (prop_types_default()).number,
884
- error: (prop_types_default()).object,
885
- element: (prop_types_default()).object
886
- };
887
- ViewportImageSliceLoadingIndicator.defaultProps = {
888
- percentComplete: 0,
889
- error: null
890
- };
891
- /* harmony default export */ const Overlays_ViewportImageSliceLoadingIndicator = (ViewportImageSliceLoadingIndicator);
892
- ;// CONCATENATED MODULE: ../../../extensions/cornerstone/src/Viewport/Overlays/CornerstoneOverlays.tsx
893
-
894
-
895
-
896
-
897
-
898
- function CornerstoneOverlays(props) {
899
- const {
900
- viewportId,
901
- element,
902
- scrollbarHeight,
903
- servicesManager
904
- } = props;
905
- const {
906
- cornerstoneViewportService
907
- } = servicesManager.services;
908
- const [imageSliceData, setImageSliceData] = (0,react.useState)({
909
- imageIndex: 0,
910
- numberOfSlices: 0
911
- });
912
- const [viewportData, setViewportData] = (0,react.useState)(null);
913
- (0,react.useEffect)(() => {
914
- const {
915
- unsubscribe
916
- } = cornerstoneViewportService.subscribe(cornerstoneViewportService.EVENTS.VIEWPORT_DATA_CHANGED, props => {
917
- if (props.viewportId !== viewportId) {
918
- return;
919
- }
920
- setViewportData(props.viewportData);
921
- });
922
- return () => {
923
- unsubscribe();
924
- };
925
- }, [viewportId]);
926
- if (!element) {
927
- return null;
928
- }
929
- if (viewportData) {
930
- const viewportInfo = cornerstoneViewportService.getViewportInfo(viewportId);
931
- if (viewportInfo?.viewportOptions?.customViewportProps?.hideOverlays) {
932
- return null;
933
- }
934
- }
935
- return /*#__PURE__*/react.createElement("div", {
936
- className: "noselect"
937
- }, /*#__PURE__*/react.createElement(ViewportImageScrollbar, {
938
- viewportId: viewportId,
939
- viewportData: viewportData,
940
- element: element,
941
- imageSliceData: imageSliceData,
942
- setImageSliceData: setImageSliceData,
943
- scrollbarHeight: scrollbarHeight,
944
- servicesManager: servicesManager
945
- }), /*#__PURE__*/react.createElement(Overlays_CustomizableViewportOverlay, {
946
- imageSliceData: imageSliceData,
947
- viewportData: viewportData,
948
- viewportId: viewportId,
949
- servicesManager: servicesManager,
950
- element: element
951
- }), /*#__PURE__*/react.createElement(Overlays_ViewportImageSliceLoadingIndicator, {
952
- viewportData: viewportData,
953
- element: element
954
- }), /*#__PURE__*/react.createElement(Overlays_ViewportOrientationMarkers, {
955
- imageSliceData: imageSliceData,
956
- element: element,
957
- viewportData: viewportData,
958
- servicesManager: servicesManager,
959
- viewportId: viewportId
960
- }));
961
- }
962
- /* harmony default export */ const Overlays_CornerstoneOverlays = (CornerstoneOverlays);
963
- // EXTERNAL MODULE: ../../../extensions/cornerstone/src/utils/measurementServiceMappings/utils/getSOPInstanceAttributes.js
964
- var getSOPInstanceAttributes = __webpack_require__(87172);
965
- // EXTERNAL MODULE: ./state/index.js + 1 modules
966
- var state_0 = __webpack_require__(62657);
967
- ;// CONCATENATED MODULE: ../../../extensions/cornerstone/src/components/CinePlayer/CinePlayer.tsx
968
-
969
-
970
-
971
-
972
- function WrappedCinePlayer(_ref) {
973
- let {
974
- enabledVPElement,
975
- viewportId,
976
- servicesManager
977
- } = _ref;
978
- const {
979
- toolbarService,
980
- customizationService,
981
- displaySetService,
982
- viewportGridService,
983
- cineService
984
- } = servicesManager.services;
985
- const [{
986
- isCineEnabled,
987
- cines
988
- }] = (0,ui_src/* useCine */.vQ)();
989
- const [newStackFrameRate, setNewStackFrameRate] = (0,react.useState)(24);
990
- const [appConfig] = (0,state_0/* useAppConfig */.M)();
991
- const {
992
- component: CinePlayerComponent = ui_src/* CinePlayer */.H6
993
- } = customizationService.get('cinePlayer') ?? {};
994
- const handleCineClose = () => {
995
- toolbarService.recordInteraction({
996
- groupId: 'MoreTools',
997
- interactionType: 'toggle',
998
- commands: [{
999
- commandName: 'toggleCine',
1000
- commandOptions: {},
1001
- toolName: 'cine',
1002
- context: 'CORNERSTONE'
1003
- }]
1004
- });
1005
- };
1006
- const cineHandler = () => {
1007
- if (!cines || !cines[viewportId] || !enabledVPElement) {
1008
- return;
1009
- }
1010
- const cine = cines[viewportId];
1011
- const isPlaying = cine.isPlaying || false;
1012
- const frameRate = cine.frameRate || 24;
1013
- const validFrameRate = Math.max(frameRate, 1);
1014
- if (isPlaying) {
1015
- cineService.playClip(enabledVPElement, {
1016
- framesPerSecond: validFrameRate
1017
- });
1018
- } else {
1019
- cineService.stopClip(enabledVPElement);
1020
- }
1021
- };
1022
- const newStackCineHandler = (0,react.useCallback)(() => {
1023
- const {
1024
- viewports
1025
- } = viewportGridService.getState();
1026
- const {
1027
- displaySetInstanceUIDs
1028
- } = viewports.get(viewportId);
1029
- let frameRate = 24;
1030
- let isPlaying = cines[viewportId].isPlaying;
1031
- displaySetInstanceUIDs.forEach(displaySetInstanceUID => {
1032
- const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);
1033
- if (displaySet.FrameRate) {
1034
- // displaySet.FrameRate corresponds to DICOM tag (0018,1063) which is defined as the the frame time in milliseconds
1035
- // So a bit of math to get the actual frame rate.
1036
- frameRate = Math.round(1000 / displaySet.FrameRate);
1037
- isPlaying ||= !!appConfig.autoPlayCine;
1038
- }
1039
- });
1040
- if (isPlaying) {
1041
- cineService.setIsCineEnabled(isPlaying);
1042
- }
1043
- cineService.setCine({
1044
- id: viewportId,
1045
- isPlaying,
1046
- frameRate
1047
- });
1048
- setNewStackFrameRate(frameRate);
1049
- }, [cineService, displaySetService, viewportId, viewportGridService, cines]);
1050
- (0,react.useEffect)(() => {
1051
- dist_esm.eventTarget.addEventListener(dist_esm.Enums.Events.STACK_VIEWPORT_NEW_STACK, newStackCineHandler);
1052
- return () => {
1053
- cineService.setCine({
1054
- id: viewportId,
1055
- isPlaying: false
1056
- });
1057
- dist_esm.eventTarget.removeEventListener(dist_esm.Enums.Events.STACK_VIEWPORT_NEW_STACK, newStackCineHandler);
1058
- };
1059
- }, [enabledVPElement, newStackCineHandler]);
1060
- (0,react.useEffect)(() => {
1061
- if (!cines || !cines[viewportId] || !enabledVPElement) {
1062
- return;
1063
- }
1064
- cineHandler();
1065
- return () => {
1066
- if (enabledVPElement && cines?.[viewportId]?.isPlaying) {
1067
- cineService.stopClip(enabledVPElement);
1068
- }
1069
- };
1070
- }, [cines, viewportId, cineService, enabledVPElement, cineHandler]);
1071
- const cine = cines[viewportId];
1072
- const isPlaying = cine && cine.isPlaying || false;
1073
- return isCineEnabled && /*#__PURE__*/react.createElement(CinePlayerComponent, {
1074
- className: "absolute left-1/2 bottom-3 -translate-x-1/2",
1075
- frameRate: newStackFrameRate,
1076
- isPlaying: isPlaying,
1077
- onClose: handleCineClose,
1078
- onPlayPauseChange: isPlaying => cineService.setCine({
1079
- id: viewportId,
1080
- isPlaying
1081
- }),
1082
- onFrameRateChange: frameRate => cineService.setCine({
1083
- id: viewportId,
1084
- frameRate
1085
- })
1086
- });
1087
- }
1088
- /* harmony default export */ const CinePlayer = (WrappedCinePlayer);
1089
- ;// CONCATENATED MODULE: ../../../extensions/cornerstone/src/components/CinePlayer/index.ts
1090
-
1091
- /* harmony default export */ const components_CinePlayer = (CinePlayer);
1092
- ;// CONCATENATED MODULE: ../../../extensions/cornerstone/src/Viewport/OHIFCornerstoneViewport.tsx
1093
-
1094
-
1095
-
1096
-
1097
-
1098
-
1099
-
1100
-
1101
-
1102
-
1103
-
1104
-
1105
- const STACK = 'stack';
1106
-
1107
- /**
1108
- * Caches the jump to measurement operation, so that if display set is shown,
1109
- * it can jump to the measurement.
1110
- */
1111
- let cacheJumpToMeasurementEvent;
1112
- function areEqual(prevProps, nextProps) {
1113
- if (nextProps.needsRerendering) {
1114
- return false;
1115
- }
1116
- if (prevProps.displaySets.length !== nextProps.displaySets.length) {
1117
- return false;
1118
- }
1119
- if (prevProps.viewportOptions.orientation !== nextProps.viewportOptions.orientation) {
1120
- return false;
1121
- }
1122
- if (prevProps.viewportOptions.toolGroupId !== nextProps.viewportOptions.toolGroupId) {
1123
- return false;
1124
- }
1125
- if (prevProps.viewportOptions.viewportType !== nextProps.viewportOptions.viewportType) {
1126
- return false;
1127
- }
1128
- if (nextProps.viewportOptions.needsRerendering) {
1129
- return false;
1130
- }
1131
- const prevDisplaySets = prevProps.displaySets;
1132
- const nextDisplaySets = nextProps.displaySets;
1133
- if (prevDisplaySets.length !== nextDisplaySets.length) {
1134
- return false;
1135
- }
1136
- for (let i = 0; i < prevDisplaySets.length; i++) {
1137
- const prevDisplaySet = prevDisplaySets[i];
1138
- const foundDisplaySet = nextDisplaySets.find(nextDisplaySet => nextDisplaySet.displaySetInstanceUID === prevDisplaySet.displaySetInstanceUID);
1139
- if (!foundDisplaySet) {
1140
- return false;
1141
- }
1142
-
1143
- // check they contain the same image
1144
- if (foundDisplaySet.images?.length !== prevDisplaySet.images?.length) {
1145
- return false;
1146
- }
1147
-
1148
- // check if their imageIds are the same
1149
- if (foundDisplaySet.images?.length) {
1150
- for (let j = 0; j < foundDisplaySet.images.length; j++) {
1151
- if (foundDisplaySet.images[j].imageId !== prevDisplaySet.images[j].imageId) {
1152
- return false;
1153
- }
1154
- }
1155
- }
1156
- }
1157
- return true;
1158
- }
1159
-
1160
- // Todo: This should be done with expose of internal API similar to react-vtkjs-viewport
1161
- // Then we don't need to worry about the re-renders if the props change.
1162
- const OHIFCornerstoneViewport = /*#__PURE__*/react.memo(props => {
1163
- const {
1164
- displaySets,
1165
- dataSource,
1166
- viewportOptions,
1167
- displaySetOptions,
1168
- servicesManager,
1169
- commandsManager,
1170
- onElementEnabled,
1171
- onElementDisabled,
1172
- isJumpToMeasurementDisabled,
1173
- // Note: you SHOULD NOT use the initialImageIdOrIndex for manipulation
1174
- // of the imageData in the OHIFCornerstoneViewport. This prop is used
1175
- // to set the initial state of the viewport's first image to render
1176
- initialImageIndex
1177
- } = props;
1178
- const viewportId = viewportOptions.viewportId;
1179
- const [scrollbarHeight, setScrollbarHeight] = (0,react.useState)('100px');
1180
- const [enabledVPElement, setEnabledVPElement] = (0,react.useState)(null);
1181
- const elementRef = (0,react.useRef)();
1182
- const {
1183
- measurementService,
1184
- displaySetService,
1185
- toolbarService,
1186
- toolGroupService,
1187
- syncGroupService,
1188
- cornerstoneViewportService,
1189
- cornerstoneCacheService,
1190
- viewportGridService,
1191
- stateSyncService
1192
- } = servicesManager.services;
1193
- const [viewportDialogState] = (0,ui_src/* useViewportDialog */.en)();
1194
- // useCallback for scroll bar height calculation
1195
- const setImageScrollBarHeight = (0,react.useCallback)(() => {
1196
- const scrollbarHeight = `${elementRef.current.clientHeight - 20}px`;
1197
- setScrollbarHeight(scrollbarHeight);
1198
- }, [elementRef]);
1199
-
1200
- // useCallback for onResize
1201
- const onResize = (0,react.useCallback)(() => {
1202
- if (elementRef.current) {
1203
- cornerstoneViewportService.resize();
1204
- setImageScrollBarHeight();
1205
- }
1206
- }, [elementRef]);
1207
- const cleanUpServices = (0,react.useCallback)(viewportInfo => {
1208
- const renderingEngineId = viewportInfo.getRenderingEngineId();
1209
- const syncGroups = viewportInfo.getSyncGroups();
1210
- toolGroupService.removeViewportFromToolGroup(viewportId, renderingEngineId);
1211
- syncGroupService.removeViewportFromSyncGroup(viewportId, renderingEngineId, syncGroups);
1212
- }, [viewportId]);
1213
- const elementEnabledHandler = (0,react.useCallback)(evt => {
1214
- // check this is this element reference and return early if doesn't match
1215
- if (evt.detail.element !== elementRef.current) {
1216
- return;
1217
- }
1218
- const {
1219
- viewportId,
1220
- element
1221
- } = evt.detail;
1222
- const viewportInfo = cornerstoneViewportService.getViewportInfo(viewportId);
1223
- (0,state/* setEnabledElement */.Yc)(viewportId, element);
1224
- setEnabledVPElement(element);
1225
- const renderingEngineId = viewportInfo.getRenderingEngineId();
1226
- const toolGroupId = viewportInfo.getToolGroupId();
1227
- const syncGroups = viewportInfo.getSyncGroups();
1228
- toolGroupService.addViewportToToolGroup(viewportId, renderingEngineId, toolGroupId);
1229
- syncGroupService.addViewportToSyncGroup(viewportId, renderingEngineId, syncGroups);
1230
- if (onElementEnabled) {
1231
- onElementEnabled(evt);
1232
- }
1233
- }, [viewportId, onElementEnabled, toolGroupService]);
1234
-
1235
- // disable the element upon unmounting
1236
- (0,react.useEffect)(() => {
1237
- cornerstoneViewportService.enableViewport(viewportId, elementRef.current);
1238
- dist_esm.eventTarget.addEventListener(dist_esm.Enums.Events.ELEMENT_ENABLED, elementEnabledHandler);
1239
- setImageScrollBarHeight();
1240
- return () => {
1241
- const viewportInfo = cornerstoneViewportService.getViewportInfo(viewportId);
1242
- if (!viewportInfo) {
1243
- return;
1244
- }
1245
- cleanUpServices(viewportInfo);
1246
- cornerstoneViewportService.storePresentation({
1247
- viewportId
1248
- });
1249
- if (onElementDisabled) {
1250
- onElementDisabled(viewportInfo);
1251
- }
1252
- dist_esm.eventTarget.removeEventListener(dist_esm.Enums.Events.ELEMENT_ENABLED, elementEnabledHandler);
1253
- };
1254
- }, []);
1255
-
1256
- // subscribe to displaySet metadata invalidation (updates)
1257
- // Currently, if the metadata changes we need to re-render the display set
1258
- // for it to take effect in the viewport. As we deal with scaling in the loading,
1259
- // we need to remove the old volume from the cache, and let the
1260
- // viewport to re-add it which will use the new metadata. Otherwise, the
1261
- // viewport will use the cached volume and the new metadata will not be used.
1262
- // Note: this approach does not actually end of sending network requests
1263
- // and it uses the network cache
1264
- (0,react.useEffect)(() => {
1265
- const {
1266
- unsubscribe
1267
- } = displaySetService.subscribe(displaySetService.EVENTS.DISPLAY_SET_SERIES_METADATA_INVALIDATED, async _ref => {
1268
- let {
1269
- displaySetInstanceUID: invalidatedDisplaySetInstanceUID,
1270
- invalidateData
1271
- } = _ref;
1272
- if (!invalidateData) {
1273
- return;
1274
- }
1275
- const viewportInfo = cornerstoneViewportService.getViewportInfo(viewportId);
1276
- if (viewportInfo.hasDisplaySet(invalidatedDisplaySetInstanceUID)) {
1277
- const viewportData = viewportInfo.getViewportData();
1278
- const newViewportData = await cornerstoneCacheService.invalidateViewportData(viewportData, invalidatedDisplaySetInstanceUID, dataSource, displaySetService);
1279
- const keepCamera = true;
1280
- cornerstoneViewportService.updateViewport(viewportId, newViewportData, keepCamera);
1281
- }
1282
- });
1283
- return () => {
1284
- unsubscribe();
1285
- };
1286
- }, [viewportId]);
1287
- (0,react.useEffect)(() => {
1288
- // handle the default viewportType to be stack
1289
- if (!viewportOptions.viewportType) {
1290
- viewportOptions.viewportType = STACK;
1291
- }
1292
- const loadViewportData = async () => {
1293
- const viewportData = await cornerstoneCacheService.createViewportData(displaySets, viewportOptions, dataSource, initialImageIndex);
1294
-
1295
- // The presentation state will have been stored previously by closing
1296
- // a viewport. Otherwise, this viewport will be unchanged and the
1297
- // presentation information will be directly carried over.
1298
- const {
1299
- lutPresentationStore,
1300
- positionPresentationStore
1301
- } = stateSyncService.getState();
1302
- const {
1303
- presentationIds
1304
- } = viewportOptions;
1305
- const presentations = {
1306
- positionPresentation: positionPresentationStore[presentationIds?.positionPresentationId],
1307
- lutPresentation: lutPresentationStore[presentationIds?.lutPresentationId]
1308
- };
1309
- let measurement;
1310
- if (cacheJumpToMeasurementEvent?.viewportId === viewportId) {
1311
- measurement = cacheJumpToMeasurementEvent.measurement;
1312
- // Delete the position presentation so that viewport navigates direct
1313
- presentations.positionPresentation = null;
1314
- cacheJumpToMeasurementEvent = null;
1315
- }
1316
-
1317
- // Note: This is a hack to get the grid to re-render the OHIFCornerstoneViewport component
1318
- // Used for segmentation hydration right now, since the logic to decide whether
1319
- // a viewport needs to render a segmentation lives inside the CornerstoneViewportService
1320
- // so we need to re-render (force update via change of the needsRerendering) so that React
1321
- // does the diffing and decides we should render this again (although the id and element has not changed)
1322
- // so that the CornerstoneViewportService can decide whether to render the segmentation or not. Not that we reached here we can turn it off.
1323
- if (viewportOptions.needsRerendering) {
1324
- viewportOptions.needsRerendering = false;
1325
- }
1326
- cornerstoneViewportService.setViewportData(viewportId, viewportData, viewportOptions, displaySetOptions, presentations);
1327
- if (measurement) {
1328
- esm.annotation.selection.setAnnotationSelected(measurement.uid);
1329
- }
1330
- };
1331
- loadViewportData();
1332
- }, [viewportOptions, displaySets, dataSource]);
1333
-
1334
- /**
1335
- * There are two scenarios for jump to click
1336
- * 1. Current viewports contain the displaySet that the annotation was drawn on
1337
- * 2. Current viewports don't contain the displaySet that the annotation was drawn on
1338
- * and we need to change the viewports displaySet for jumping.
1339
- * Since measurement_jump happens via events and listeners, the former case is handled
1340
- * by the measurement_jump direct callback, but the latter case is handled first by
1341
- * the viewportGrid to set the correct displaySet on the viewport, AND THEN we check
1342
- * the cache for jumping to see if there is any jump queued, then we jump to the correct slice.
1343
- */
1344
- (0,react.useEffect)(() => {
1345
- if (isJumpToMeasurementDisabled) {
1346
- return;
1347
- }
1348
- const unsubscribeFromJumpToMeasurementEvents = _subscribeToJumpToMeasurementEvents(measurementService, displaySetService, elementRef, viewportId, displaySets, viewportGridService, cornerstoneViewportService);
1349
- _checkForCachedJumpToMeasurementEvents(measurementService, displaySetService, elementRef, viewportId, displaySets, viewportGridService, cornerstoneViewportService);
1350
- return () => {
1351
- unsubscribeFromJumpToMeasurementEvents();
1352
- };
1353
- }, [displaySets, elementRef, viewportId]);
1354
- return /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement("div", {
1355
- className: "viewport-wrapper"
1356
- }, /*#__PURE__*/react.createElement(index_esm/* default */.ZP, {
1357
- refreshMode: "debounce",
1358
- refreshRate: 50 // Wait 50 ms after last move to render
1359
- ,
1360
- onResize: onResize,
1361
- targetRef: elementRef.current
1362
- }), /*#__PURE__*/react.createElement("div", {
1363
- className: "cornerstone-viewport-element",
1364
- style: {
1365
- height: '100%',
1366
- width: '100%'
1367
- },
1368
- onContextMenu: e => e.preventDefault(),
1369
- onMouseDown: e => e.preventDefault(),
1370
- ref: elementRef
1371
- }), /*#__PURE__*/react.createElement(Overlays_CornerstoneOverlays, {
1372
- viewportId: viewportId,
1373
- toolBarService: toolbarService,
1374
- element: elementRef.current,
1375
- scrollbarHeight: scrollbarHeight,
1376
- servicesManager: servicesManager
1377
- }), /*#__PURE__*/react.createElement(components_CinePlayer, {
1378
- enabledVPElement: enabledVPElement,
1379
- viewportId: viewportId,
1380
- servicesManager: servicesManager
1381
- })), /*#__PURE__*/react.createElement("div", {
1382
- className: "absolute w-full"
1383
- }, viewportDialogState.viewportId === viewportId && /*#__PURE__*/react.createElement(ui_src/* Notification */.P_, {
1384
- id: "viewport-notification",
1385
- message: viewportDialogState.message,
1386
- type: viewportDialogState.type,
1387
- actions: viewportDialogState.actions,
1388
- onSubmit: viewportDialogState.onSubmit,
1389
- onOutsideClick: viewportDialogState.onOutsideClick
1390
- })));
1391
- }, areEqual);
1392
- function _subscribeToJumpToMeasurementEvents(measurementService, displaySetService, elementRef, viewportId, displaySets, viewportGridService, cornerstoneViewportService) {
1393
- const {
1394
- unsubscribe
1395
- } = measurementService.subscribe(src.MeasurementService.EVENTS.JUMP_TO_MEASUREMENT_VIEWPORT, props => {
1396
- cacheJumpToMeasurementEvent = props;
1397
- const {
1398
- viewportId: jumpId,
1399
- measurement,
1400
- isConsumed
1401
- } = props;
1402
- if (!measurement || isConsumed) {
1403
- return;
1404
- }
1405
- if (cacheJumpToMeasurementEvent.cornerstoneViewport === undefined) {
1406
- // Decide on which viewport should handle this
1407
- cacheJumpToMeasurementEvent.cornerstoneViewport = cornerstoneViewportService.getViewportIdToJump(jumpId, measurement.displaySetInstanceUID, {
1408
- referencedImageId: measurement.referencedImageId
1409
- });
1410
- }
1411
- if (cacheJumpToMeasurementEvent.cornerstoneViewport !== viewportId) {
1412
- return;
1413
- }
1414
- _jumpToMeasurement(measurement, elementRef, viewportId, measurementService, displaySetService, viewportGridService, cornerstoneViewportService);
1415
- });
1416
- return unsubscribe;
1417
- }
1418
-
1419
- // Check if there is a queued jumpToMeasurement event
1420
- function _checkForCachedJumpToMeasurementEvents(measurementService, displaySetService, elementRef, viewportId, displaySets, viewportGridService, cornerstoneViewportService) {
1421
- if (!cacheJumpToMeasurementEvent) {
1422
- return;
1423
- }
1424
- if (cacheJumpToMeasurementEvent.isConsumed) {
1425
- cacheJumpToMeasurementEvent = null;
1426
- return;
1427
- }
1428
- const displaysUIDs = displaySets.map(displaySet => displaySet.displaySetInstanceUID);
1429
- if (!displaysUIDs?.length) {
1430
- return;
1431
- }
1432
-
1433
- // Jump to measurement if the measurement exists
1434
- const {
1435
- measurement
1436
- } = cacheJumpToMeasurementEvent;
1437
- if (measurement && elementRef) {
1438
- if (displaysUIDs.includes(measurement?.displaySetInstanceUID)) {
1439
- _jumpToMeasurement(measurement, elementRef, viewportId, measurementService, displaySetService, viewportGridService, cornerstoneViewportService);
1440
- }
1441
- }
1442
- }
1443
- function _jumpToMeasurement(measurement, targetElementRef, viewportId, measurementService, displaySetService, viewportGridService, cornerstoneViewportService) {
1444
- const targetElement = targetElementRef.current;
1445
- const {
1446
- displaySetInstanceUID,
1447
- SOPInstanceUID,
1448
- frameNumber
1449
- } = measurement;
1450
- if (!SOPInstanceUID) {
1451
- console.warn('cannot jump in a non-acquisition plane measurements yet');
1452
- return;
1453
- }
1454
- const referencedDisplaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);
1455
-
1456
- // Todo: setCornerstoneMeasurementActive should be handled by the toolGroupManager
1457
- // to set it properly
1458
- // setCornerstoneMeasurementActive(measurement);
1459
-
1460
- viewportGridService.setActiveViewportId(viewportId);
1461
- const enabledElement = (0,dist_esm.getEnabledElement)(targetElement);
1462
- if (enabledElement) {
1463
- // See how the jumpToSlice() of Cornerstone3D deals with imageIdx param.
1464
- const viewport = enabledElement.viewport;
1465
- let imageIdIndex = 0;
1466
- let viewportCameraDirectionMatch = true;
1467
- if (viewport instanceof dist_esm.StackViewport) {
1468
- const imageIds = viewport.getImageIds();
1469
- imageIdIndex = imageIds.findIndex(imageId => {
1470
- const {
1471
- SOPInstanceUID: aSOPInstanceUID,
1472
- frameNumber: aFrameNumber
1473
- } = (0,getSOPInstanceAttributes/* default */.Z)(imageId);
1474
- return aSOPInstanceUID === SOPInstanceUID && (!frameNumber || frameNumber === aFrameNumber);
1475
- });
1476
- } else {
1477
- // for volume viewport we can't rely on the imageIdIndex since it can be
1478
- // a reconstructed view that doesn't match the original slice numbers etc.
1479
- const {
1480
- viewPlaneNormal: measurementViewPlane
1481
- } = measurement.metadata;
1482
- imageIdIndex = referencedDisplaySet.images.findIndex(i => i.SOPInstanceUID === SOPInstanceUID);
1483
- const {
1484
- viewPlaneNormal: viewportViewPlane
1485
- } = viewport.getCamera();
1486
-
1487
- // should compare abs for both planes since the direction can be flipped
1488
- if (measurementViewPlane && !dist_esm.utilities.isEqual(measurementViewPlane.map(Math.abs), viewportViewPlane.map(Math.abs))) {
1489
- viewportCameraDirectionMatch = false;
1490
- }
1491
- }
1492
- if (!viewportCameraDirectionMatch || imageIdIndex === -1) {
1493
- return;
1494
- }
1495
- esm.utilities.jumpToSlice(targetElement, {
1496
- imageIndex: imageIdIndex
1497
- });
1498
- esm.annotation.selection.setAnnotationSelected(measurement.uid);
1499
- // Jump to measurement consumed, remove.
1500
- cacheJumpToMeasurementEvent?.consume?.();
1501
- cacheJumpToMeasurementEvent = null;
1502
- }
1503
- }
1504
-
1505
- // Component displayName
1506
- OHIFCornerstoneViewport.displayName = 'OHIFCornerstoneViewport';
1507
- OHIFCornerstoneViewport.defaultProps = {
1508
- isJumpToMeasurementDisabled: false
1509
- };
1510
- OHIFCornerstoneViewport.propTypes = {
1511
- displaySets: (prop_types_default()).array.isRequired,
1512
- dataSource: (prop_types_default()).object.isRequired,
1513
- viewportOptions: (prop_types_default()).object,
1514
- displaySetOptions: prop_types_default().arrayOf((prop_types_default()).any),
1515
- servicesManager: (prop_types_default()).object.isRequired,
1516
- onElementEnabled: (prop_types_default()).func,
1517
- isJumpToMeasurementDisabled: (prop_types_default()).bool,
1518
- // Note: you SHOULD NOT use the initialImageIdOrIndex for manipulation
1519
- // of the imageData in the OHIFCornerstoneViewport. This prop is used
1520
- // to set the initial state of the viewport's first image to render
1521
- initialImageIdOrIndex: prop_types_default().oneOfType([(prop_types_default()).string, (prop_types_default()).number])
1522
- };
1523
- /* harmony default export */ const Viewport_OHIFCornerstoneViewport = (OHIFCornerstoneViewport);
1524
-
1525
- /***/ })
1526
-
1527
- }]);