@3cr/viewer-browser 0.0.161 → 0.0.194

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 (229) hide show
  1. package/.circleci/config.yml +53 -0
  2. package/__tests__/index.spec.ts +31 -24
  3. package/components.d.ts +32 -0
  4. package/dist/Viewer3CR.js +44 -27
  5. package/dist/Viewer3CR.mjs +22734 -17747
  6. package/dist/Viewer3CR.umd.js +44 -27
  7. package/index.html +6 -8
  8. package/index.ts +9 -5
  9. package/package.json +5 -2
  10. package/playground/index.html +7 -10
  11. package/src/App.vue +12 -4
  12. package/src/__tests__/app.spec.ts +2 -13
  13. package/src/assets/magic_wand.svg +24 -0
  14. package/src/components/WebGL3DR.vue +53 -92
  15. package/src/components/__tests__/webgl3dr.spec.ts +29 -48
  16. package/src/{demo → components/demo}/DemoModal.vue +1 -1
  17. package/src/{demo → components/demo}/DemoPatientModal.vue +4 -1
  18. package/src/components/demo/__tests__/DemoModal.spec.ts +25 -0
  19. package/src/components/demo/__tests__/DemoPatientModal.spec.ts +37 -0
  20. package/src/components/demo/__tests__/options.spec.ts +25 -0
  21. package/src/components/demo/licence/DemoLicenceEnableCloudStorageModal.vue +64 -0
  22. package/src/{demo → components/demo}/licence/DemoLicenceInfoModal.vue +5 -4
  23. package/src/{demo → components/demo}/licence/DemoLicenceSendToPartyModal.vue +6 -4
  24. package/src/{demo → components/demo}/licence/DemoLicenceShareToMobileModal.vue +8 -6
  25. package/src/components/demo/licence/__tests__/DemoLicenceEnableCloudStorageModal.spec.ts +37 -0
  26. package/src/components/demo/licence/__tests__/DemoLicenceInfoModal.spec.ts +37 -0
  27. package/src/components/demo/licence/__tests__/DemoLicenceSendToPartyModal.spec.ts +36 -0
  28. package/src/components/demo/licence/__tests__/DemoLicenceShareToMobileModal.spec.ts +51 -0
  29. package/src/{demo → components/demo}/options.ts +18 -20
  30. package/src/components/demo/patient/DemoPatientEnableCloudStorageModal.vue +64 -0
  31. package/src/{demo → components/demo}/patient/DemoPatientInfoModal.vue +5 -4
  32. package/src/{demo → components/demo}/patient/DemoPatientSendToPartyModal.vue +4 -3
  33. package/src/{demo → components/demo}/patient/DemoPatientShareToMobileModal.vue +8 -6
  34. package/src/components/demo/patient/__tests__/DemoPatientEnableCloudStorageModal.spec.ts +37 -0
  35. package/src/components/demo/patient/__tests__/DemoPatientInfoModal.spec.ts +37 -0
  36. package/src/components/demo/patient/__tests__/DemoPatientSendToPartyModal.spec.ts +36 -0
  37. package/src/components/demo/patient/__tests__/DemoPatientShareToMobileModal.spec.ts +51 -0
  38. package/src/components/loading/LoadingSpinner.vue +1 -1
  39. package/src/components/modal/ActionRail.vue +96 -0
  40. package/src/components/modal/AskAI.vue +250 -0
  41. package/src/components/modal/CloseViewerModal.vue +104 -0
  42. package/src/components/modal/MftpWebGL3DRModal.vue +415 -834
  43. package/src/components/modal/ViewerActionRail.vue +123 -0
  44. package/src/components/modal/ViewerAnnotationModal.vue +115 -0
  45. package/src/components/modal/ViewerAnnotations.vue +283 -0
  46. package/src/components/modal/ViewerDisplaySettings.vue +102 -0
  47. package/src/components/modal/ViewerNavigationDrawer.vue +90 -0
  48. package/src/components/modal/ViewerNavigationDrawerContent.vue +126 -0
  49. package/src/components/modal/ViewerNavigationDrawerFooter.vue +111 -0
  50. package/src/components/modal/ViewerNavigationDrawerHeader.vue +63 -0
  51. package/src/components/modal/__tests__/CloseViewerModal.spec.ts +60 -0
  52. package/src/components/modal/__tests__/{mftp-webgl-3dr-modal.spec.ts → MftpWebGL3DRModal.spec.ts} +47 -298
  53. package/src/components/modal/__tests__/ViewerAnnotationModal.spec.ts +79 -0
  54. package/src/components/modal/__tests__/ViewerDisplaySettings.spec.ts +61 -0
  55. package/src/components/modal/__tests__/ViewerNavigationDrawer.spec.ts +32 -0
  56. package/src/components/modal/__tests__/ViewerNavigationDrawerContent.spec.ts +29 -0
  57. package/src/components/modal/__tests__/ViewerNavigationDrawerFooter.spec.ts +43 -0
  58. package/src/components/modal/__tests__/ViewerNavigationDrawerHeader.spec.ts +37 -0
  59. package/src/components/modal/actions/Action.vue +40 -0
  60. package/src/components/modal/actions/Flip3dAction.vue +79 -0
  61. package/src/components/modal/actions/FlipHorizontalAction.vue +36 -0
  62. package/src/components/modal/actions/FlipVerticalAction.vue +36 -0
  63. package/src/components/modal/actions/FullscreenAction.vue +47 -0
  64. package/src/components/modal/actions/NavigationCubeAction.vue +33 -0
  65. package/src/components/modal/actions/PanAction.vue +78 -0
  66. package/src/components/modal/actions/ResetViewAction.vue +29 -0
  67. package/src/components/modal/actions/Rotate2dAction.vue +78 -0
  68. package/src/components/modal/actions/Slice3dAction.vue +71 -0
  69. package/src/components/modal/actions/ZoomAction.vue +70 -0
  70. package/src/components/modal/actions/__tests__/Action.spec.ts +29 -0
  71. package/src/components/modal/actions/__tests__/Flip3dAction.spec.ts +48 -0
  72. package/src/components/modal/actions/__tests__/FlipHorizontalAction.spec.ts +17 -0
  73. package/src/components/modal/actions/__tests__/FlipVerticalAction.spec.ts +17 -0
  74. package/src/components/modal/actions/__tests__/FullscreenAction.spec.ts +28 -0
  75. package/src/components/modal/actions/__tests__/NavigationCubeAction.spec.ts +25 -0
  76. package/src/components/modal/actions/__tests__/PanAction.spec.ts +46 -0
  77. package/src/components/modal/actions/__tests__/ResetViewAction.spec.ts +17 -0
  78. package/src/components/modal/actions/__tests__/Rotate2dAction.spec.ts +23 -0
  79. package/src/components/modal/actions/__tests__/Slice3dAction.spec.ts +14 -0
  80. package/src/components/modal/actions/__tests__/ZoomAction.spec.ts +34 -0
  81. package/src/components/modal/composables/__tests__/useNavigationCubeObserver.spec.ts +56 -0
  82. package/src/components/modal/composables/useEventListener.ts +22 -0
  83. package/src/components/modal/composables/useNavigationCubeObserver.ts +104 -0
  84. package/src/components/selectors/ValueSelector.vue +30 -33
  85. package/src/components/selectors/__tests__/value-selector.spec.ts +1 -1
  86. package/src/components/sliders/DoubleSliderSelector.vue +79 -71
  87. package/src/components/sliders/VerticalSliderSelector.vue +12 -17
  88. package/src/components/sliders/__tests__/double-slider-selector.spec.ts +1 -1
  89. package/src/components/sliders/__tests__/vertical-slider-selector.spec.ts +1 -1
  90. package/src/dataLayer/__tests__/clamp.spec.ts +16 -0
  91. package/src/dataLayer/__tests__/eventHandlers.spec.ts +38 -0
  92. package/src/dataLayer/__tests__/getIconForPreset.spec.ts +40 -0
  93. package/src/dataLayer/__tests__/patchDataOverlay.spec.ts +88 -0
  94. package/src/dataLayer/__tests__/scanState.spec.ts +93 -0
  95. package/src/dataLayer/__tests__/useViewer3cr.spec.ts +10 -0
  96. package/src/dataLayer/__tests__/viewer3cr.spec.ts +331 -0
  97. package/src/dataLayer/clamp.ts +9 -0
  98. package/src/dataLayer/eventHandlers.ts +26 -0
  99. package/src/dataLayer/patchDataOverlay.ts +101 -0
  100. package/src/dataLayer/scanState.ts +105 -26
  101. package/src/dataLayer/useViewer3cr.ts +7 -0
  102. package/src/dataLayer/viewer3cr.ts +410 -0
  103. package/src/helpers/__tests__/layout-overlay-style.spec.ts +24 -22
  104. package/src/helpers/__tests__/model-helper.spec.ts +44 -13
  105. package/src/helpers/layoutOverlayStyle.ts +16 -27
  106. package/src/helpers/modelHelper.ts +62 -10
  107. package/src/models/Callbacks.ts +2 -2
  108. package/src/models/LoadViewerOptions.ts +2 -0
  109. package/src/models/LoadViewerPayload.ts +1 -0
  110. package/src/notifications/notification.ts +3 -4
  111. package/src/plugins/vuetify.ts +5 -0
  112. package/src/services/gpt/__tests__/gpt.service.spec.ts +27 -0
  113. package/src/services/gpt/gpt.service.ts +27 -0
  114. package/static/3cr-types-browser/index.ts +74 -0
  115. package/static/3cr-types-browser/types/Action.ts +6 -0
  116. package/static/3cr-types-browser/types/ActionData.ts +4 -0
  117. package/static/3cr-types-browser/types/AlphaKeys.ts +5 -0
  118. package/static/3cr-types-browser/types/AnchorPoint.ts +12 -0
  119. package/static/3cr-types-browser/types/CallToAction.ts +5 -0
  120. package/static/3cr-types-browser/types/ColourData.ts +7 -0
  121. package/static/3cr-types-browser/types/ColourPresetData.ts +9 -0
  122. package/static/3cr-types-browser/types/CurrentDataOverlayState.ts +6 -0
  123. package/static/3cr-types-browser/types/CurrentScanState.ts +22 -0
  124. package/static/3cr-types-browser/types/DataOverlay.ts +22 -0
  125. package/static/3cr-types-browser/types/DataOverlayActions.ts +14 -0
  126. package/static/3cr-types-browser/types/DataOverlayData.ts +8 -0
  127. package/static/3cr-types-browser/types/DataOverlayEvent.ts +8 -0
  128. package/static/3cr-types-browser/types/DecryptionKey.ts +4 -0
  129. package/static/3cr-types-browser/types/DisplaySettings.ts +10 -0
  130. package/static/3cr-types-browser/types/EmptyPayload.ts +3 -0
  131. package/static/3cr-types-browser/types/EnumPayload.ts +4 -0
  132. package/static/3cr-types-browser/types/FileManagementActions.ts +11 -0
  133. package/static/3cr-types-browser/types/FlipValue.ts +7 -0
  134. package/static/3cr-types-browser/types/FrontEndInterfaces.ts +14 -0
  135. package/static/3cr-types-browser/types/GradientKeys.ts +7 -0
  136. package/static/3cr-types-browser/types/GreyscalePresetData.ts +6 -0
  137. package/static/3cr-types-browser/types/InitialDataOverlayState.ts +6 -0
  138. package/static/3cr-types-browser/types/InitialScanState.ts +19 -0
  139. package/static/3cr-types-browser/types/InteractionType.ts +8 -0
  140. package/static/3cr-types-browser/types/InteractivityActions.ts +6 -0
  141. package/static/3cr-types-browser/types/InteractivityState.ts +4 -0
  142. package/static/3cr-types-browser/types/InvertTransformData.ts +6 -0
  143. package/static/3cr-types-browser/types/LayoutActions.ts +6 -0
  144. package/static/3cr-types-browser/types/LayoutData.ts +7 -0
  145. package/static/3cr-types-browser/types/LoadDataSet.ts +6 -0
  146. package/static/3cr-types-browser/types/LoadSessionState.ts +4 -0
  147. package/static/3cr-types-browser/types/LocalLoadDataset.ts +3 -0
  148. package/static/3cr-types-browser/types/MovementData.ts +7 -0
  149. package/static/3cr-types-browser/types/NavigationCubeActions.ts +8 -0
  150. package/static/3cr-types-browser/types/NavigationCubeData.ts +12 -0
  151. package/static/3cr-types-browser/types/NavigationCubeTransform.ts +9 -0
  152. package/static/3cr-types-browser/types/NotificationPayload.ts +7 -0
  153. package/static/3cr-types-browser/types/NotificationsActions.ts +6 -0
  154. package/static/3cr-types-browser/types/Object.ts +1 -0
  155. package/static/3cr-types-browser/types/ObjectColour.ts +7 -0
  156. package/static/3cr-types-browser/types/ObjectIcon.ts +5 -0
  157. package/static/3cr-types-browser/types/ObjectInvert.ts +7 -0
  158. package/static/3cr-types-browser/types/ObjectSize.ts +7 -0
  159. package/static/3cr-types-browser/types/ObjectSize2D.ts +7 -0
  160. package/static/3cr-types-browser/types/ObjectVisible.ts +5 -0
  161. package/static/3cr-types-browser/types/PositionData.ts +14 -0
  162. package/static/3cr-types-browser/types/PresetsActions.ts +4 -0
  163. package/static/3cr-types-browser/types/RotationValue.ts +7 -0
  164. package/static/3cr-types-browser/types/ScanMovementActions.ts +27 -0
  165. package/static/3cr-types-browser/types/ScanMovementData.ts +3 -0
  166. package/static/3cr-types-browser/types/ScanOrientationActions.ts +6 -0
  167. package/static/3cr-types-browser/types/ScanStateActions.ts +4 -0
  168. package/static/3cr-types-browser/types/ScanView.ts +6 -0
  169. package/static/3cr-types-browser/types/SettingsData.ts +12 -0
  170. package/static/3cr-types-browser/types/SlicerData.ts +9 -0
  171. package/static/3cr-types-browser/types/SliderValue.ts +4 -0
  172. package/static/3cr-types-browser/types/SlidersActions.ts +18 -0
  173. package/static/3cr-types-browser/types/Vector2Data.ts +5 -0
  174. package/static/3cr-types-browser/types/Vector3Data.ts +6 -0
  175. package/static/3cr-types-browser/types/VectorMovementData.ts +8 -0
  176. package/static/3cr-types-browser/types/ViewInteractiveMode.ts +5 -0
  177. package/static/3cr-types-browser/types/ViewOrientation.ts +8 -0
  178. package/static/3cr-types-browser/types/ViewOrientations.ts +10 -0
  179. package/static/3cr-types-browser/types/ViewSelectionActions.ts +9 -0
  180. package/static/3cr-types-browser/types/ViewToggleData.ts +7 -0
  181. package/static/3cr-types-browser/types/VolumeOrientation.ts +7 -0
  182. package/test/helper.ts +10 -1
  183. package/test/setup.ts +13 -0
  184. package/tsconfig.json +1 -0
  185. package/vite.config.mts +1 -0
  186. package/coverage/3cr-viewer-browser/index.html +0 -116
  187. package/coverage/3cr-viewer-browser/index.ts.html +0 -199
  188. package/coverage/3cr-viewer-browser/src/App.vue.html +0 -316
  189. package/coverage/3cr-viewer-browser/src/components/WebGL3DR.vue.html +0 -442
  190. package/coverage/3cr-viewer-browser/src/components/icons/index.html +0 -116
  191. package/coverage/3cr-viewer-browser/src/components/icons/liver.vue.html +0 -148
  192. package/coverage/3cr-viewer-browser/src/components/index.html +0 -116
  193. package/coverage/3cr-viewer-browser/src/components/loading/LoadingSpinner.vue.html +0 -622
  194. package/coverage/3cr-viewer-browser/src/components/loading/index.html +0 -116
  195. package/coverage/3cr-viewer-browser/src/components/modal/MftpWebGL3DRModal.vue.html +0 -3118
  196. package/coverage/3cr-viewer-browser/src/components/modal/index.html +0 -116
  197. package/coverage/3cr-viewer-browser/src/components/selectors/ValueSelector.vue.html +0 -358
  198. package/coverage/3cr-viewer-browser/src/components/selectors/index.html +0 -116
  199. package/coverage/3cr-viewer-browser/src/components/sliders/DoubleSliderSelector.vue.html +0 -487
  200. package/coverage/3cr-viewer-browser/src/components/sliders/VerticalSliderSelector.vue.html +0 -358
  201. package/coverage/3cr-viewer-browser/src/components/sliders/index.html +0 -131
  202. package/coverage/3cr-viewer-browser/src/dataLayer/iconData.ts.html +0 -118
  203. package/coverage/3cr-viewer-browser/src/dataLayer/index.html +0 -146
  204. package/coverage/3cr-viewer-browser/src/dataLayer/payloadHandler.ts.html +0 -463
  205. package/coverage/3cr-viewer-browser/src/dataLayer/scanState.ts.html +0 -598
  206. package/coverage/3cr-viewer-browser/src/helpers/index.html +0 -146
  207. package/coverage/3cr-viewer-browser/src/helpers/layoutOverlayStyle.ts.html +0 -406
  208. package/coverage/3cr-viewer-browser/src/helpers/modelHelper.ts.html +0 -412
  209. package/coverage/3cr-viewer-browser/src/helpers/utils.ts.html +0 -133
  210. package/coverage/3cr-viewer-browser/src/index.html +0 -131
  211. package/coverage/3cr-viewer-browser/src/main.ts.html +0 -124
  212. package/coverage/3cr-viewer-browser/src/models/LoadViewerOptions.ts.html +0 -166
  213. package/coverage/3cr-viewer-browser/src/models/index.html +0 -116
  214. package/coverage/3cr-viewer-browser/src/notifications/index.html +0 -116
  215. package/coverage/3cr-viewer-browser/src/notifications/notification.ts.html +0 -238
  216. package/coverage/3cr-viewer-browser/src/plugins/index.html +0 -131
  217. package/coverage/3cr-viewer-browser/src/plugins/index.ts.html +0 -136
  218. package/coverage/3cr-viewer-browser/src/plugins/vuetify.ts.html +0 -220
  219. package/coverage/base.css +0 -224
  220. package/coverage/block-navigation.js +0 -87
  221. package/coverage/favicon.png +0 -0
  222. package/coverage/index.html +0 -296
  223. package/coverage/prettify.css +0 -1
  224. package/coverage/prettify.js +0 -2
  225. package/coverage/sort-arrow-sprite.png +0 -0
  226. package/coverage/sorter.js +0 -196
  227. package/src/dataLayer/__tests__/payload-handler.spec.ts +0 -214
  228. package/src/dataLayer/payloadHandler.ts +0 -138
  229. /package/src/dataLayer/{iconData.ts → getIconForPreset.ts} +0 -0
@@ -3,22 +3,30 @@ import {
3
3
  AnchorPoint,
4
4
  ColourPresetData,
5
5
  CurrentScanState,
6
+ DataOverlayEvent,
7
+ InitialDataOverlayState,
6
8
  InitialScanState,
7
9
  LayoutActions,
10
+ PositionData,
11
+ ScanView,
8
12
  } from "@3cr/types-ts";
13
+ import { inflateInitialDataOverlayState, inflateInitialScanState, inflateScanState } from "@/helpers/modelHelper";
9
14
  import {
10
- inflateInitialScanState,
11
- inflateScanState,
12
- } from "@/helpers/modelHelper";
15
+ CurrentDataOverlayStateUnpatched,
16
+ DataOverlayEventUnpatched,
17
+ InitialDataOverlayStateUnpatched,
18
+ patchCurrentDataOverlay,
19
+ patchDataOverlayEvent,
20
+ patchInitialDataOverlay
21
+ } from "@/dataLayer/patchDataOverlay";
13
22
 
14
23
  export const currentColourPreset = ref<ColourPresetData | undefined>(undefined);
15
-
16
24
  export const transactionStarted = ref<boolean>(false);
17
25
  export const scanStateIncoming = ref<string>("");
18
26
  export const scanState = ref<CurrentScanState>(inflateScanState());
19
- export const initialScanState = ref<InitialScanState>(
20
- inflateInitialScanState()
21
- );
27
+ export const dataOverlayEvent = ref<DataOverlayEvent | null>(null);
28
+ export const dataOverlayState = ref<InitialDataOverlayState>(inflateInitialDataOverlayState());
29
+ export const initialScanState = ref<InitialScanState>(inflateInitialScanState());
22
30
  export const previousLayout = ref<LayoutActions>(LayoutActions.lo02);
23
31
 
24
32
  export const huMinMax = ref({
@@ -30,72 +38,77 @@ export const tMinMax = ref({
30
38
  min: 0,
31
39
  max: 999999,
32
40
  });
41
+
33
42
  export const sMinMax = ref({
34
43
  min: 0,
35
44
  max: 999999,
36
45
  });
46
+
37
47
  export const cMinMax = ref({
38
48
  min: 0,
39
49
  max: 999999,
40
50
  });
41
51
 
42
52
  export const windowSlider = computed({
43
- get() {
53
+ get(): [number, number] {
44
54
  return [
45
55
  unref(scanState).Display.WindowLower,
46
56
  unref(scanState).Display.WindowUpper,
47
57
  ];
48
58
  },
49
- set(value: Array<number>) {
59
+ set(value: [number, number]): void {
50
60
  scanState.value.Display.WindowLower = value[0];
51
61
  scanState.value.Display.WindowUpper = value[1];
52
62
  },
53
63
  });
64
+
54
65
  export const thresholdSlider = computed({
55
- get() {
66
+ get(): [number, number] {
56
67
  return [
57
68
  Math.trunc(unref(scanState).Display.ThresholdLower),
58
69
  Math.trunc(unref(scanState).Display.ThresholdUpper),
59
70
  ];
60
71
  },
61
- set(value: Array<number>) {
72
+ set(value: [number, number]): void {
62
73
  scanState.value.Display.ThresholdLower = value[0];
63
74
  scanState.value.Display.ThresholdUpper = value[1];
64
75
  },
65
76
  });
77
+
66
78
  export const tSlider = computed({
67
- get() {
79
+ get(): [number, number] {
68
80
  return [
69
81
  Math.trunc(unref(scanState).Slice.TransverseLower),
70
82
  Math.trunc(unref(scanState).Slice.TransverseUpper),
71
83
  ];
72
84
  },
73
- set(value: Array<number>) {
85
+ set(value: [number, number]): void {
74
86
  scanState.value.Slice.TransverseLower = value[0];
75
87
  scanState.value.Slice.TransverseUpper = value[1];
76
88
  },
77
89
  });
90
+
78
91
  export const sSlider = computed({
79
- get() {
92
+ get(): [number, number] {
80
93
  return [
81
94
  Math.trunc(unref(scanState).Slice.SagittalLower),
82
95
  Math.trunc(unref(scanState).Slice.SagittalUpper),
83
96
  ];
84
97
  },
85
- set(value: Array<number>) {
98
+ set(value: [number, number]): void {
86
99
  scanState.value.Slice.SagittalLower = value[0];
87
100
  scanState.value.Slice.SagittalUpper = value[1];
88
101
  },
89
102
  });
90
103
 
91
104
  export const cSlider = computed({
92
- get() {
105
+ get(): [number, number] {
93
106
  return [
94
107
  Math.trunc(unref(scanState).Slice.CoronalLower),
95
108
  Math.trunc(unref(scanState).Slice.CoronalUpper),
96
109
  ];
97
110
  },
98
- set(value: Array<number>) {
111
+ set(value: [number, number]): void {
99
112
  scanState.value.Slice.CoronalLower = value[0];
100
113
  scanState.value.Slice.CoronalUpper = value[1];
101
114
  },
@@ -111,6 +124,7 @@ export const isLayout2x2 = computed(() => {
111
124
  unref(scanState).Layout.PositionData[3].Anchor === AnchorPoint.BOTTOM_RIGHT
112
125
  );
113
126
  });
127
+
114
128
  export const isLayout1x3 = computed(() => {
115
129
  return (
116
130
  unref(scanState).Layout.PositionData.length > 1 &&
@@ -121,6 +135,14 @@ export const isLayout1x3 = computed(() => {
121
135
  );
122
136
  });
123
137
 
138
+ export const isFullscreen = computed(() => {
139
+ return unref(scanState).Layout.PositionData.length === 1;
140
+ });
141
+
142
+ export const isSessionLoaded = computed(() => {
143
+ return unref(dataOverlayState).DataOverlay.DataOverlay.length > 0;
144
+ });
145
+
124
146
  export const currentGreyscalePreset = computed(() => {
125
147
  for (const preset of unref(initialScanState).GreyscalePresets) {
126
148
  if (
@@ -133,29 +155,24 @@ export const currentGreyscalePreset = computed(() => {
133
155
  unref(scanState).Display.WindowUpper ===
134
156
  unref(initialScanState).HuUpper))
135
157
  ) {
136
- return preset.Name;
158
+ return preset;
137
159
  }
138
160
  }
139
161
  return undefined;
140
162
  });
141
163
 
142
- export async function setScanStateFromPayload(_: string, message: string) {
164
+ export async function setScanStateFromPayload(message: string) {
143
165
  transactionStarted.value = true;
144
166
  scanStateIncoming.value = JSON.stringify(JSON.parse(message), null, 2);
145
-
146
167
  setScanState(message);
147
168
  await nextTick();
148
169
  transactionStarted.value = false;
149
170
  }
150
- export async function setInitialScanStateFromPayload(
151
- _: string,
152
- message: string
153
- ) {
154
- transactionStarted.value = true;
155
171
 
172
+ export function setInitialScanStateFromPayload(message: string) {
173
+ transactionStarted.value = true;
156
174
  scanStateIncoming.value = JSON.stringify(JSON.parse(message), null, 2);
157
175
  const obj = JSON.parse(unref(scanStateIncoming)) as InitialScanState;
158
-
159
176
  setScanState(JSON.stringify(obj.DefaultDisplaySettings, null, 2));
160
177
  initialScanState.value = obj;
161
178
  huMinMax.value.max = obj.HuUpper;
@@ -169,3 +186,65 @@ export async function setInitialScanStateFromPayload(
169
186
  export function setScanState(message: string) {
170
187
  scanState.value = JSON.parse(message) as CurrentScanState;
171
188
  }
189
+
190
+ export function setInitialDataOverlayState(message: string) {
191
+ const data = JSON.parse(message) as InitialDataOverlayStateUnpatched;
192
+ dataOverlayState.value = patchInitialDataOverlay(data);
193
+ }
194
+
195
+ export function setDataOverlayState(message: string) {
196
+ const data = JSON.parse(message) as CurrentDataOverlayStateUnpatched;
197
+ dataOverlayState.value = { Version: '1.1.0', DataOverlay: patchCurrentDataOverlay(data) };
198
+ }
199
+
200
+ export function setActiveAnnotation(message: string): void {
201
+ const data = JSON.parse(message) as DataOverlayEventUnpatched;
202
+ dataOverlayEvent.value = patchDataOverlayEvent(data);
203
+ }
204
+
205
+ export function getCurrentView(position: PositionData): ScanView {
206
+ return unref(scanState).Layout.PositionData.length !== 1
207
+ ? position.DefaultView
208
+ : unref(scanState).CurrentView;
209
+ }
210
+
211
+ export function getViewName(view: ScanView): string {
212
+ switch (view) {
213
+ case ScanView.Coronal:
214
+ return "Coronal";
215
+ case ScanView.Sagittal:
216
+ return "Sagittal";
217
+ case ScanView.Transverse:
218
+ return "Transverse";
219
+ case ScanView.Volume:
220
+ return "3D Volume";
221
+ default:
222
+ return "";
223
+ }
224
+ }
225
+
226
+ export function isHorizontalFlip(view: ScanView): boolean {
227
+ switch (view) {
228
+ case ScanView.Coronal:
229
+ return scanState.value.Orientations.Coronal.HorizontalFlip;
230
+ case ScanView.Sagittal:
231
+ return scanState.value.Orientations.Sagittal.HorizontalFlip;
232
+ case ScanView.Transverse:
233
+ return scanState.value.Orientations.Transverse.HorizontalFlip;
234
+ default:
235
+ return false;
236
+ }
237
+ }
238
+
239
+ export function isVerticalFlip(view: ScanView): boolean {
240
+ switch (view) {
241
+ case ScanView.Coronal:
242
+ return scanState.value.Orientations.Coronal.VerticalFlip;
243
+ case ScanView.Sagittal:
244
+ return scanState.value.Orientations.Sagittal.VerticalFlip;
245
+ case ScanView.Transverse:
246
+ return scanState.value.Orientations.Transverse.VerticalFlip;
247
+ default:
248
+ return false;
249
+ }
250
+ }
@@ -0,0 +1,7 @@
1
+ import { Viewer3cr } from "@/dataLayer/viewer3cr";
2
+
3
+ const viewer3cr = new Viewer3cr();
4
+
5
+ export function useViewer3cr(): Viewer3cr {
6
+ return viewer3cr;
7
+ }
@@ -0,0 +1,410 @@
1
+ import { FrontEndPayload } from "@3cr/sdk-browser/types/payload";
2
+ import { createInstance, executePayload, registerOnPayloadHandler } from "@3cr/sdk-browser";
3
+ import { unref } from "vue";
4
+ import {
5
+ AnchorPoint,
6
+ DataOverlayActions,
7
+ FileManagementActions,
8
+ FrontEndInterfaces, InteractivityActions, LayoutActions, NavigationCubeActions, PresetsActions, ScanMovementActions,
9
+ ScanOrientationActions,
10
+ ScanView, SlidersActions, ViewSelectionActions
11
+ } from "@3cr/types-ts";
12
+ import { LoadViewerPayload } from "@/models/LoadViewerPayload";
13
+ import { currentColourPreset, previousLayout, transactionStarted } from "@/dataLayer/scanState";
14
+ import { toNumber } from "@/helpers/utils";
15
+ import { EventHandlers } from "@/dataLayer/eventHandlers";
16
+ import { clamp } from "@/dataLayer/clamp";
17
+
18
+ type InterfaceCallback = (message: string, action: string) => void | Promise<void>;
19
+
20
+ type ActionCallback = (message: string) => void | Promise<void>;
21
+
22
+ export const emptyPayload = { Version: "1.1.0" };
23
+
24
+ export class Viewer3cr {
25
+ private interfaceCallbacks = new EventHandlers<string, InterfaceCallback>();
26
+
27
+ private actionCallbacks = new EventHandlers<string, ActionCallback>();
28
+
29
+ async register(canvas: HTMLCanvasElement): Promise<void> {
30
+ await registerOnPayloadHandler(this.onPayload.bind(this));
31
+ await createInstance(canvas);
32
+ }
33
+
34
+ addInterfaceHandler(iface: string, callback: InterfaceCallback): void {
35
+ this.interfaceCallbacks.add(iface, callback);
36
+ }
37
+
38
+ removeInterfaceHandler(iface: string, callback: InterfaceCallback): void {
39
+ this.interfaceCallbacks.remove(iface, callback);
40
+ }
41
+
42
+ addActionHandler(action: string, callback: ActionCallback): void {
43
+ this.actionCallbacks.add(action, callback);
44
+ }
45
+
46
+ removeActionHandler(action: string, callback: ActionCallback): void {
47
+ this.actionCallbacks.remove(action, callback);
48
+ }
49
+
50
+ /**
51
+ * DO-02: Toggle 2D annotation visibility.
52
+ * @param id The annotation id.
53
+ * @param visibility The annotation visibility.
54
+ */
55
+ async toggle2dAnnotation(id: string, visibility: boolean): Promise<void> {
56
+ await this.sendPayload(FrontEndInterfaces.data_overlay, DataOverlayActions.do03, {
57
+ Version: '1.1.0',
58
+ Id: id,
59
+ Visibility: visibility
60
+ });
61
+ }
62
+
63
+ /**
64
+ * DO-11: Toggle 3D annotation visibility.
65
+ * @param id The annotation id.
66
+ * @param visibility The annotation visibility.
67
+ */
68
+ async toggle3dAnnotation(id: string, visibility: boolean): Promise<void> {
69
+ await this.sendPayload(FrontEndInterfaces.data_overlay, DataOverlayActions.do11, {
70
+ Version: '1.1.0',
71
+ Id: id,
72
+ Visibility: visibility
73
+ });
74
+ }
75
+
76
+ /**
77
+ * FM-01: Load scan.
78
+ * @param options The load scan options.
79
+ */
80
+ async loadScan(options: LoadViewerPayload): Promise<void> {
81
+ await this.sendPayload(FrontEndInterfaces.file_management, FileManagementActions.fm01, options);
82
+ }
83
+
84
+ /**
85
+ * FM-03: Load previous CurrentScanState values.
86
+ * @param url The URL to the file.
87
+ */
88
+ async loadScanSession(url: string): Promise<void> {
89
+ await this.sendPayload(FrontEndInterfaces.file_management, FileManagementActions.fm03, {
90
+ Version: '1.1.0',
91
+ Url: url
92
+ });
93
+ }
94
+
95
+ /**
96
+ * FM-05: Load separate data overlay file from external UI.
97
+ * @param url The URL to the file.
98
+ */
99
+ async loadDataOverlay(url: string): Promise<void> {
100
+ await this.sendPayload(FrontEndInterfaces.file_management, FileManagementActions.fm05, {
101
+ Version: '1.1.0',
102
+ Url: url
103
+ });
104
+ }
105
+
106
+ /**
107
+ * FM-09: Load separate MCAD file from external UI.
108
+ * @param url The URL to the file.
109
+ */
110
+ async loadMcad(url: string): Promise<void> {
111
+ await this.sendPayload(FrontEndInterfaces.file_management, 'fm_09', {
112
+ Version: '1.1.0',
113
+ Url: url
114
+ });
115
+ }
116
+
117
+ /**
118
+ * SO-01: Rotate 2D view by up to +-XXX degrees.
119
+ * @param view The 2D view.
120
+ * @param deg The degrees.
121
+ */
122
+ async rotateByDeg(view: ScanView, deg: number) {
123
+ await this.sendPayload(FrontEndInterfaces.scan_orientation, ScanOrientationActions.so01, {
124
+ Version: "0.0.1",
125
+ View: view,
126
+ Angle: deg,
127
+ });
128
+ }
129
+
130
+ /**
131
+ * SO-02: Flip 2D View Horizontally.
132
+ * @param view The scan view.
133
+ * @param flipped Whether to enable horizontal flip.
134
+ */
135
+ async flipHorizontally(view: ScanView, flipped: boolean): Promise<void> {
136
+ await this.sendPayload(FrontEndInterfaces.scan_orientation, ScanOrientationActions.so02, {
137
+ Version: "0.0.1",
138
+ View: view,
139
+ Flipped: flipped
140
+ })
141
+ }
142
+
143
+ /**
144
+ * SO-03: Flip 2D View Vertically.
145
+ * @param view The scan view.
146
+ * @param flipped Whether to enable vertical flip.
147
+ */
148
+ async flipVertically(view: ScanView, flipped: boolean): Promise<void> {
149
+ await this.sendPayload(FrontEndInterfaces.scan_orientation, ScanOrientationActions.so03, {
150
+ Version: "0.0.1",
151
+ View: view,
152
+ Flipped: flipped
153
+ });
154
+ }
155
+
156
+ /**
157
+ * SO-04: Invert Volume Rendering
158
+ * @param sagittal If the Sagittal axis is inverted.
159
+ * @param coronal If the Coronal axis is inverted.
160
+ * @param transverse If the Transverse axis is inverted.
161
+ */
162
+ async invertTransform(sagittal: boolean, coronal: boolean, transverse: boolean): Promise<void> {
163
+ // TODO: Replace so_04 with action type constant
164
+ await this.sendPayload(FrontEndInterfaces.scan_orientation, 'so_04', {
165
+ Version: "0.0.1",
166
+ InvertedSagittal: sagittal,
167
+ InvertedCoronal: coronal,
168
+ InvertedTransverse: transverse
169
+ });
170
+ }
171
+
172
+ async viewSelection(action: ViewSelectionActions) {
173
+ await this.sendPayload(FrontEndInterfaces.view_selection, action, emptyPayload);
174
+ }
175
+
176
+ async sliderHandler(action: SlidersActions, value: number) {
177
+ if (unref(transactionStarted)) return;
178
+ await this.slider(action, value);
179
+ }
180
+
181
+ async scanMovementHandler(action: ScanMovementActions, value: number) {
182
+ if (unref(transactionStarted)) return;
183
+ await this.scanMovement(action, value);
184
+ }
185
+
186
+ async layouts(action: LayoutActions) {
187
+ if (action !== LayoutActions.lo01) previousLayout.value = action;
188
+ await this.sendPayload(FrontEndInterfaces.layout, action, emptyPayload);
189
+ }
190
+
191
+ async setPreset(action: PresetsActions, preset: any) {
192
+ await this.sendPayload(FrontEndInterfaces.presets, action, preset);
193
+ if (action === PresetsActions.pr02) {
194
+ currentColourPreset.value = preset;
195
+ }
196
+ }
197
+
198
+ /**
199
+ * NC-01: Set Navigation Cube Co-ordinates and Size.
200
+ * @param anchorPoint The anchor point on the screen.
201
+ * @param x The x-axis offset.
202
+ * @param y The y-axis offset.
203
+ * @param width The navigation cube width.
204
+ * @param height The navigation cube height.
205
+ */
206
+ async setNavCubePositionSize(anchorPoint: AnchorPoint, x: number, y: number, width: number, height: number): Promise<void> {
207
+ await this.sendPayload(FrontEndInterfaces.navigation_cube, NavigationCubeActions.nc01, {
208
+ Version: '0.0.1',
209
+ AnchorPoint: anchorPoint,
210
+ Position: { Version: '0.0.1', X: x, Y: y },
211
+ Size: { Version: '0.0.1', X: width, Y: height }
212
+ });
213
+ }
214
+
215
+ /**
216
+ * NC-02: Set Navigation Cube Visibility.
217
+ * @param visibility If the navigation cube is visible.
218
+ */
219
+ async setNavCubeVisibility(visibility: boolean): Promise<void> {
220
+ await this.sendPayload(FrontEndInterfaces.navigation_cube, NavigationCubeActions.nc02, {
221
+ Version: "0.0.1",
222
+ Value: visibility,
223
+ });
224
+ }
225
+
226
+ /**
227
+ * NC-03: Set Navigation Cube Interactivity.
228
+ * @param interactivity If the navigation cube is interactive.
229
+ */
230
+ async setNavCubeInteractivity(interactivity: boolean): Promise<void> {
231
+ await this.sendPayload(FrontEndInterfaces.navigation_cube, NavigationCubeActions.nc03, {
232
+ Version: '0.0.1',
233
+ Value: interactivity
234
+ });
235
+ }
236
+
237
+ /**
238
+ * NC-04: Set Navigation Cube Perspective
239
+ * @param perspective If perspective shift is removed.
240
+ */
241
+ async setNavCubePerspective(perspective: boolean): Promise<void> {
242
+ await this.sendPayload(FrontEndInterfaces.navigation_cube, NavigationCubeActions.nc04, {
243
+ Version: '0.0.1',
244
+ Value: perspective
245
+ });
246
+ }
247
+
248
+ /**
249
+ * NC-05: Set Navigation Cube Colour and Opacity.
250
+ * All values must be floats between 0 and 255.
251
+ * @param r Red channel.
252
+ * @param g Green channel.
253
+ * @param b Blue channel.
254
+ * @param a Alpha channel.
255
+ */
256
+ async setNavCubeColourOpacity(r: number, g: number, b: number, a: number): Promise<void> {
257
+ // TODO: Replace nc_05 with action type constant
258
+ await this.sendPayload(FrontEndInterfaces.navigation_cube, 'nc_05', {
259
+ Version: '0.0.1',
260
+ R: clamp(r / 255, 0, 1),
261
+ G: clamp(g / 255, 0, 1),
262
+ B: clamp(b / 255, 0, 1),
263
+ A: clamp(a / 255, 0, 1)
264
+ });
265
+ }
266
+
267
+ /**
268
+ * NC-07: Set Navigation Cube Highlight Colour and Opacity.
269
+ * All values must be floats between 0 and 255.
270
+ * @param r Red channel.
271
+ * @param g Green channel.
272
+ * @param b Blue channel.
273
+ * @param a Alpha channel.
274
+ */
275
+ async setNavCubeHighlightColourOpacity(r: number, g: number, b: number, a: number): Promise<void> {
276
+ // TODO: Replace nc_07 with action type constant
277
+ await this.sendPayload(FrontEndInterfaces.navigation_cube, 'nc_07', {
278
+ Version: '0.0.1',
279
+ R: clamp(r / 255, 0, 1),
280
+ G: clamp(g / 255, 0, 1),
281
+ B: clamp(b / 255, 0, 1),
282
+ A: clamp(a / 255, 0, 1)
283
+ });
284
+ }
285
+
286
+ /**
287
+ * SM-13: Pan the selected view to the left.
288
+ * @param view The view.
289
+ * @param value The movement in mm.
290
+ */
291
+ async panLeft(view: ScanView, value: number): Promise<void> {
292
+ // TODO: Replace sm_13 with action type constant
293
+ await this.sendPayload(FrontEndInterfaces.scan_movement, "sm_13", {
294
+ Version: "0.0.1",
295
+ View: view,
296
+ Movement: value,
297
+ });
298
+ }
299
+
300
+ /**
301
+ * SM-14: Pan the selected view to the right.
302
+ * @param view The view.
303
+ * @param value The movement in mm.
304
+ */
305
+ async panRight(view: ScanView, value: number): Promise<void> {
306
+ // TODO: Replace sm_14 with action type constant
307
+ await this.sendPayload(FrontEndInterfaces.scan_movement, "sm_14", {
308
+ Version: "0.0.1",
309
+ View: view,
310
+ Movement: value,
311
+ });
312
+ }
313
+
314
+ /**
315
+ * SM-15: Pan the selected view upwards.
316
+ * @param view The view.
317
+ * @param value The movement in mm.
318
+ */
319
+ async panUp(view: ScanView, value: number): Promise<void> {
320
+ // TODO: Replace sm_15 with action type constant
321
+ await this.sendPayload(FrontEndInterfaces.scan_movement, "sm_15", {
322
+ Version: "0.0.1",
323
+ View: view,
324
+ Movement: value,
325
+ });
326
+ }
327
+
328
+ /**
329
+ * SM-16: Pan the selected view downwards.
330
+ * @param view The view.
331
+ * @param value The movement in mm.
332
+ */
333
+ async panDown(view: ScanView, value: number): Promise<void> {
334
+ // TODO: Replace sm_16 with action type constant
335
+ await this.sendPayload(FrontEndInterfaces.scan_movement, "sm_16", {
336
+ Version: "0.0.1",
337
+ View: view,
338
+ Movement: value,
339
+ });
340
+ }
341
+
342
+ /**
343
+ * SM-17: Zoom In.
344
+ * @param view The view.
345
+ * @param value The amount to zoom in.
346
+ */
347
+ async zoomIn(view: ScanView, value: number): Promise<void> {
348
+ await this.sendPayload(FrontEndInterfaces.scan_movement, "sm_17", {
349
+ Version: "0.0.1",
350
+ View: view,
351
+ Movement: value
352
+ });
353
+ }
354
+
355
+ /**
356
+ * SM-18: Zoom out.
357
+ * @param view The view.
358
+ * @param value The amount to zoom out.
359
+ */
360
+ async zoomOut(view: ScanView, value: number): Promise<void> {
361
+ await this.sendPayload(FrontEndInterfaces.scan_movement, "sm_18", {
362
+ Version: "0.0.1",
363
+ View: view,
364
+ Movement: value
365
+ });
366
+ }
367
+
368
+ /**
369
+ * IN-01, IN-02: Enable/Disable Unity input interactions.
370
+ * @param isHovering If the inputs should be enabled.
371
+ */
372
+ async hoverOverCanvas(isHovering: boolean) {
373
+ await this.sendPayload(FrontEndInterfaces.interactivity, InteractivityActions.in01, {
374
+ Version: "0.0.1",
375
+ Value: isHovering,
376
+ });
377
+ await this.sendPayload(FrontEndInterfaces.interactivity, InteractivityActions.in02, {
378
+ Version: "0.0.1",
379
+ Value: isHovering,
380
+ });
381
+ }
382
+
383
+ private async scanMovement(action: ScanMovementActions, value: number) {
384
+ await this.sendPayload(FrontEndInterfaces.scan_movement, action, {
385
+ Version: "0.0.1",
386
+ Value: toNumber(value),
387
+ });
388
+ }
389
+
390
+ private async slider(action: SlidersActions, value: number) {
391
+ await this.sendPayload(FrontEndInterfaces.sliders, action, {
392
+ Version: "0.0.1",
393
+ Value: toNumber(value),
394
+ });
395
+ }
396
+
397
+ async sendPayload(iface: string, action: string, message: any): Promise<void> {
398
+ await executePayload({
399
+ Version: "0.0.1",
400
+ Interface: iface as any,
401
+ Action: action as any,
402
+ Message: JSON.stringify(message),
403
+ });
404
+ }
405
+
406
+ private async onPayload(payload: FrontEndPayload): Promise<void> {
407
+ await this.interfaceCallbacks.call(payload.Interface, payload.Message, payload.Action);
408
+ await this.actionCallbacks.call(payload.Action, payload.Message);
409
+ }
410
+ }