copper3d 3.0.2 → 3.1.0

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 (104) hide show
  1. package/README.md +183 -1028
  2. package/dist/Utils/segmentation/CanvasState.d.ts +31 -0
  3. package/dist/Utils/segmentation/CanvasState.js +167 -0
  4. package/dist/Utils/segmentation/CanvasState.js.map +1 -0
  5. package/dist/Utils/segmentation/DragOperator.d.ts +1 -1
  6. package/dist/Utils/segmentation/DragOperator.js +2 -4
  7. package/dist/Utils/segmentation/DragOperator.js.map +1 -1
  8. package/dist/Utils/segmentation/DrawToolCore.d.ts +49 -27
  9. package/dist/Utils/segmentation/DrawToolCore.js +275 -344
  10. package/dist/Utils/segmentation/DrawToolCore.js.map +1 -1
  11. package/dist/Utils/segmentation/NrrdTools.d.ts +89 -467
  12. package/dist/Utils/segmentation/NrrdTools.js +479 -1335
  13. package/dist/Utils/segmentation/NrrdTools.js.map +1 -1
  14. package/dist/Utils/segmentation/RenderingUtils.d.ts +73 -0
  15. package/dist/Utils/segmentation/RenderingUtils.js +180 -0
  16. package/dist/Utils/segmentation/RenderingUtils.js.map +1 -0
  17. package/dist/Utils/segmentation/core/MaskVolume.d.ts +1 -1
  18. package/dist/Utils/segmentation/core/MaskVolume.js +1 -1
  19. package/dist/Utils/segmentation/core/index.d.ts +1 -1
  20. package/dist/Utils/segmentation/core/index.js.map +1 -1
  21. package/dist/Utils/segmentation/core/types.d.ts +384 -0
  22. package/dist/Utils/segmentation/core/types.js +1 -0
  23. package/dist/Utils/segmentation/core/types.js.map +1 -1
  24. package/dist/Utils/segmentation/coreTools/GuiState.d.ts +1 -1
  25. package/dist/Utils/segmentation/coreTools/NrrdState.d.ts +1 -1
  26. package/dist/Utils/segmentation/coreTools/divControlTools.d.ts +1 -1
  27. package/dist/Utils/segmentation/coreTools/gui.d.ts +1 -1
  28. package/dist/Utils/segmentation/tools/BaseTool.d.ts +1 -1
  29. package/dist/Utils/segmentation/tools/ContrastTool.d.ts +3 -6
  30. package/dist/Utils/segmentation/tools/ContrastTool.js.map +1 -1
  31. package/dist/Utils/segmentation/tools/CrosshairTool.d.ts +11 -1
  32. package/dist/Utils/segmentation/tools/CrosshairTool.js +25 -0
  33. package/dist/Utils/segmentation/tools/CrosshairTool.js.map +1 -1
  34. package/dist/Utils/segmentation/tools/DataLoader.d.ts +33 -0
  35. package/dist/Utils/segmentation/tools/DataLoader.js +159 -0
  36. package/dist/Utils/segmentation/tools/DataLoader.js.map +1 -0
  37. package/dist/Utils/segmentation/tools/DragSliceTool.d.ts +3 -12
  38. package/dist/Utils/segmentation/tools/DragSliceTool.js.map +1 -1
  39. package/dist/Utils/segmentation/tools/DrawingTool.d.ts +18 -26
  40. package/dist/Utils/segmentation/tools/DrawingTool.js +48 -0
  41. package/dist/Utils/segmentation/tools/DrawingTool.js.map +1 -1
  42. package/dist/Utils/segmentation/tools/ImageStoreHelper.d.ts +2 -5
  43. package/dist/Utils/segmentation/tools/ImageStoreHelper.js.map +1 -1
  44. package/dist/Utils/segmentation/tools/LayerChannelManager.d.ts +52 -0
  45. package/dist/Utils/segmentation/tools/LayerChannelManager.js +175 -0
  46. package/dist/Utils/segmentation/tools/LayerChannelManager.js.map +1 -0
  47. package/dist/Utils/segmentation/tools/PanTool.d.ts +2 -8
  48. package/dist/Utils/segmentation/tools/PanTool.js.map +1 -1
  49. package/dist/Utils/segmentation/tools/SliceRenderPipeline.d.ts +80 -0
  50. package/dist/Utils/segmentation/tools/SliceRenderPipeline.js +355 -0
  51. package/dist/Utils/segmentation/tools/SliceRenderPipeline.js.map +1 -0
  52. package/dist/Utils/segmentation/tools/SphereTool.d.ts +25 -19
  53. package/dist/Utils/segmentation/tools/SphereTool.js +61 -7
  54. package/dist/Utils/segmentation/tools/SphereTool.js.map +1 -1
  55. package/dist/Utils/segmentation/tools/ToolHost.d.ts +74 -0
  56. package/dist/Utils/segmentation/tools/ToolHost.js +10 -0
  57. package/dist/Utils/segmentation/tools/ToolHost.js.map +1 -0
  58. package/dist/Utils/segmentation/tools/ZoomTool.d.ts +2 -6
  59. package/dist/Utils/segmentation/tools/ZoomTool.js.map +1 -1
  60. package/dist/Utils/segmentation/tools/index.d.ts +5 -7
  61. package/dist/Utils/segmentation/tools/index.js +6 -0
  62. package/dist/Utils/segmentation/tools/index.js.map +1 -1
  63. package/dist/Utils/workers/reformatSaveDataWorker.d.ts +1 -1
  64. package/dist/bundle.esm.js +2109 -2357
  65. package/dist/bundle.umd.js +2109 -2357
  66. package/dist/index.d.ts +3 -3
  67. package/dist/index.js +1 -1
  68. package/dist/types/Utils/segmentation/CanvasState.d.ts +31 -0
  69. package/dist/types/Utils/segmentation/DragOperator.d.ts +1 -1
  70. package/dist/types/Utils/segmentation/DrawToolCore.d.ts +49 -27
  71. package/dist/types/Utils/segmentation/NrrdTools.d.ts +89 -467
  72. package/dist/types/Utils/segmentation/RenderingUtils.d.ts +73 -0
  73. package/dist/types/Utils/segmentation/core/MaskVolume.d.ts +1 -1
  74. package/dist/types/Utils/segmentation/core/index.d.ts +1 -1
  75. package/dist/types/Utils/segmentation/core/types.d.ts +384 -0
  76. package/dist/types/Utils/segmentation/coreTools/GuiState.d.ts +1 -1
  77. package/dist/types/Utils/segmentation/coreTools/NrrdState.d.ts +1 -1
  78. package/dist/types/Utils/segmentation/coreTools/divControlTools.d.ts +1 -1
  79. package/dist/types/Utils/segmentation/coreTools/gui.d.ts +1 -1
  80. package/dist/types/Utils/segmentation/tools/BaseTool.d.ts +1 -1
  81. package/dist/types/Utils/segmentation/tools/ContrastTool.d.ts +3 -6
  82. package/dist/types/Utils/segmentation/tools/CrosshairTool.d.ts +11 -1
  83. package/dist/types/Utils/segmentation/tools/DataLoader.d.ts +33 -0
  84. package/dist/types/Utils/segmentation/tools/DragSliceTool.d.ts +3 -12
  85. package/dist/types/Utils/segmentation/tools/DrawingTool.d.ts +18 -26
  86. package/dist/types/Utils/segmentation/tools/ImageStoreHelper.d.ts +2 -5
  87. package/dist/types/Utils/segmentation/tools/LayerChannelManager.d.ts +52 -0
  88. package/dist/types/Utils/segmentation/tools/PanTool.d.ts +2 -8
  89. package/dist/types/Utils/segmentation/tools/SliceRenderPipeline.d.ts +80 -0
  90. package/dist/types/Utils/segmentation/tools/SphereTool.d.ts +25 -19
  91. package/dist/types/Utils/segmentation/tools/ToolHost.d.ts +74 -0
  92. package/dist/types/Utils/segmentation/tools/ZoomTool.d.ts +2 -6
  93. package/dist/types/Utils/segmentation/tools/index.d.ts +5 -7
  94. package/dist/types/Utils/workers/reformatSaveDataWorker.d.ts +1 -1
  95. package/dist/types/index.d.ts +3 -3
  96. package/package.json +1 -1
  97. package/dist/Utils/segmentation/CommToolsData.d.ts +0 -192
  98. package/dist/Utils/segmentation/CommToolsData.js +0 -474
  99. package/dist/Utils/segmentation/CommToolsData.js.map +0 -1
  100. package/dist/Utils/segmentation/coreTools/coreType.d.ts +0 -389
  101. package/dist/Utils/segmentation/coreTools/coreType.js +0 -3
  102. package/dist/Utils/segmentation/coreTools/coreType.js.map +0 -1
  103. package/dist/types/Utils/segmentation/CommToolsData.d.ts +0 -192
  104. package/dist/types/Utils/segmentation/coreTools/coreType.d.ts +0 -389
@@ -0,0 +1,175 @@
1
+ import { BaseTool } from "./BaseTool";
2
+ import { CHANNEL_HEX_COLORS, rgbaToHex, rgbaToCss } from "../core";
3
+ import { SPHERE_CHANNEL_MAP } from "./SphereTool";
4
+ /**
5
+ * Manages layer/channel state: active selection, visibility, and channel colors.
6
+ *
7
+ * Extracted from NrrdTools.ts to reduce its size.
8
+ * Follows the same BaseTool + ToolContext + Callbacks pattern as other tools.
9
+ */
10
+ export class LayerChannelManager extends BaseTool {
11
+ constructor(ctx, callbacks) {
12
+ super(ctx);
13
+ this.callbacks = callbacks;
14
+ }
15
+ /****************************Active Layer/Channel****************************************************/
16
+ setActiveLayer(layerId) {
17
+ this.ctx.gui_states.layerChannel.layer = layerId;
18
+ this.syncBrushColor();
19
+ }
20
+ getActiveLayer() {
21
+ return this.ctx.gui_states.layerChannel.layer;
22
+ }
23
+ setActiveChannel(channel) {
24
+ this.ctx.gui_states.layerChannel.activeChannel = channel;
25
+ this.syncBrushColor();
26
+ }
27
+ getActiveChannel() {
28
+ return this.ctx.gui_states.layerChannel.activeChannel;
29
+ }
30
+ /**
31
+ * Set the active sphere type and sync brush/fill color.
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * nrrdTools.setActiveSphereType('nipple');
36
+ * ```
37
+ */
38
+ setActiveSphereType(type) {
39
+ this.ctx.gui_states.mode.activeSphereType = type;
40
+ // Apply color side-effect: update fillColor/brushColor from sphere channel map
41
+ const mapping = SPHERE_CHANNEL_MAP[type];
42
+ if (mapping) {
43
+ const volume = this.callbacks.getVolumeForLayer(mapping.layer);
44
+ const color = volume
45
+ ? rgbaToHex(volume.getChannelColor(mapping.channel))
46
+ : (CHANNEL_HEX_COLORS[mapping.channel] || '#00ff00');
47
+ this.ctx.gui_states.drawing.fillColor = color;
48
+ this.ctx.gui_states.drawing.brushColor = color;
49
+ }
50
+ }
51
+ getActiveSphereType() {
52
+ return this.ctx.gui_states.mode.activeSphereType;
53
+ }
54
+ /****************************Visibility****************************************************/
55
+ setLayerVisible(layerId, visible) {
56
+ this.ctx.gui_states.layerChannel.layerVisibility[layerId] = visible;
57
+ this.callbacks.reloadMasksFromVolume();
58
+ }
59
+ isLayerVisible(layerId) {
60
+ var _a;
61
+ return (_a = this.ctx.gui_states.layerChannel.layerVisibility[layerId]) !== null && _a !== void 0 ? _a : true;
62
+ }
63
+ setChannelVisible(layerId, channel, visible) {
64
+ if (this.ctx.gui_states.layerChannel.channelVisibility[layerId]) {
65
+ this.ctx.gui_states.layerChannel.channelVisibility[layerId][channel] = visible;
66
+ }
67
+ this.callbacks.reloadMasksFromVolume();
68
+ }
69
+ isChannelVisible(layerId, channel) {
70
+ var _a, _b;
71
+ return (_b = (_a = this.ctx.gui_states.layerChannel.channelVisibility[layerId]) === null || _a === void 0 ? void 0 : _a[channel]) !== null && _b !== void 0 ? _b : true;
72
+ }
73
+ getLayerVisibility() {
74
+ return Object.assign({}, this.ctx.gui_states.layerChannel.layerVisibility);
75
+ }
76
+ getChannelVisibility() {
77
+ const result = {};
78
+ for (const layerId of this.ctx.nrrd_states.image.layers) {
79
+ result[layerId] = Object.assign({}, this.ctx.gui_states.layerChannel.channelVisibility[layerId]);
80
+ }
81
+ return result;
82
+ }
83
+ hasLayerData(layerId) {
84
+ const volume = this.ctx.protectedData.maskData.volumes[layerId];
85
+ if (!volume) {
86
+ return false;
87
+ }
88
+ return volume.hasData();
89
+ }
90
+ /****************************Channel Colors****************************************************/
91
+ setChannelColor(layerId, channel, color) {
92
+ const volume = this.ctx.protectedData.maskData.volumes[layerId];
93
+ if (!volume) {
94
+ console.warn(`setChannelColor: unknown layer "${layerId}"`);
95
+ return;
96
+ }
97
+ volume.setChannelColor(channel, color);
98
+ if (layerId === this.ctx.gui_states.layerChannel.layer && channel === this.ctx.gui_states.layerChannel.activeChannel) {
99
+ this.syncBrushColor();
100
+ }
101
+ this.callbacks.reloadMasksFromVolume();
102
+ this.callbacks.onChannelColorChanged(layerId, channel, color);
103
+ }
104
+ getChannelColor(layerId, channel) {
105
+ const volume = this.ctx.protectedData.maskData.volumes[layerId];
106
+ if (!volume) {
107
+ return { r: 0, g: 255, b: 0, a: 255 };
108
+ }
109
+ return volume.getChannelColor(channel);
110
+ }
111
+ getChannelHexColor(layerId, channel) {
112
+ return rgbaToHex(this.getChannelColor(layerId, channel));
113
+ }
114
+ getChannelCssColor(layerId, channel) {
115
+ return rgbaToCss(this.getChannelColor(layerId, channel));
116
+ }
117
+ setChannelColors(layerId, colorMap) {
118
+ const volume = this.ctx.protectedData.maskData.volumes[layerId];
119
+ if (!volume) {
120
+ console.warn(`setChannelColors: unknown layer "${layerId}"`);
121
+ return;
122
+ }
123
+ for (const [ch, color] of Object.entries(colorMap)) {
124
+ volume.setChannelColor(Number(ch), color);
125
+ }
126
+ if (layerId === this.ctx.gui_states.layerChannel.layer) {
127
+ this.syncBrushColor();
128
+ }
129
+ this.callbacks.reloadMasksFromVolume();
130
+ }
131
+ setAllLayersChannelColor(channel, color) {
132
+ for (const layerId of this.ctx.nrrd_states.image.layers) {
133
+ const volume = this.ctx.protectedData.maskData.volumes[layerId];
134
+ if (volume) {
135
+ volume.setChannelColor(channel, color);
136
+ }
137
+ }
138
+ if (channel === this.ctx.gui_states.layerChannel.activeChannel) {
139
+ this.syncBrushColor();
140
+ }
141
+ this.callbacks.reloadMasksFromVolume();
142
+ }
143
+ resetChannelColors(layerId, channel) {
144
+ const layers = layerId ? [layerId] : this.ctx.nrrd_states.image.layers;
145
+ for (const lid of layers) {
146
+ const volume = this.ctx.protectedData.maskData.volumes[lid];
147
+ if (volume) {
148
+ volume.resetChannelColors(channel);
149
+ }
150
+ }
151
+ this.syncBrushColor();
152
+ this.callbacks.reloadMasksFromVolume();
153
+ }
154
+ /****************************Private Helpers****************************************************/
155
+ /**
156
+ * Sync brush/fill color from the active layer's volume channel color.
157
+ * Falls back to global CHANNEL_HEX_COLORS if volume not available.
158
+ */
159
+ syncBrushColor() {
160
+ const channel = this.ctx.gui_states.layerChannel.activeChannel || 1;
161
+ const layer = this.ctx.gui_states.layerChannel.layer;
162
+ const volume = this.ctx.protectedData.maskData.volumes[layer];
163
+ if (volume) {
164
+ const hex = rgbaToHex(volume.getChannelColor(channel));
165
+ this.ctx.gui_states.drawing.fillColor = hex;
166
+ this.ctx.gui_states.drawing.brushColor = hex;
167
+ }
168
+ else {
169
+ const hex = CHANNEL_HEX_COLORS[channel] || '#00ff00';
170
+ this.ctx.gui_states.drawing.fillColor = hex;
171
+ this.ctx.gui_states.drawing.brushColor = hex;
172
+ }
173
+ }
174
+ }
175
+ //# sourceMappingURL=LayerChannelManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LayerChannelManager.js","sourceRoot":"","sources":["../../../../src/Utils/segmentation/tools/LayerChannelManager.ts"],"names":[],"mappings":"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"}
@@ -6,13 +6,7 @@
6
6
  */
7
7
  import { BaseTool } from "./BaseTool";
8
8
  import type { ToolContext } from "./BaseTool";
9
- /**
10
- * Callbacks PanTool needs from its host (DrawToolCore).
11
- */
12
- export interface PanCallbacks {
13
- /** Re-enable zoom wheel after pan ends in sphere mode */
14
- zoomActionAfterDrawSphere: () => void;
15
- }
9
+ import type { PanHostDeps } from "./ToolHost";
16
10
  export declare class PanTool extends BaseTool {
17
11
  /** Right mouse button currently held */
18
12
  private rightClicked;
@@ -26,7 +20,7 @@ export declare class PanTool extends BaseTool {
26
20
  * Arrow function preserves `this` binding.
27
21
  */
28
22
  private readonly boundPointerMove;
29
- constructor(ctx: ToolContext, callbacks: PanCallbacks);
23
+ constructor(ctx: ToolContext, callbacks: PanHostDeps);
30
24
  /** Whether a pan drag is currently active */
31
25
  get isActive(): boolean;
32
26
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"PanTool.js","sourceRoot":"","sources":["../../../../src/Utils/segmentation/tools/PanTool.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PanTool.js","sourceRoot":"","sources":["../../../../src/Utils/segmentation/tools/PanTool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ import { BaseTool } from "./BaseTool";
2
+ import type { ToolContext } from "./BaseTool";
3
+ import type { SliceRenderHostDeps } from "./ToolHost";
4
+ /**
5
+ * Manages slice rendering pipeline: slice setup, canvas rendering, and view helpers.
6
+ *
7
+ * Extracted from NrrdTools.ts to reduce its size.
8
+ * Follows the same BaseTool + ToolContext + Callbacks pattern as other tools.
9
+ */
10
+ export declare class SliceRenderPipeline extends BaseTool {
11
+ private callbacks;
12
+ private initState;
13
+ constructor(ctx: ToolContext, callbacks: SliceRenderHostDeps);
14
+ /**
15
+ * Reset initState to true (called from NrrdTools.reset() when switching datasets).
16
+ */
17
+ resetInitState(): void;
18
+ /****************************Slice Setup****************************************************/
19
+ setDisplaySlicesBaseOnAxis(): void;
20
+ private loadDisplaySlicesArray;
21
+ resetDisplaySlicesStatus(): void;
22
+ private setupConfigs;
23
+ private setMainPreSlice;
24
+ private setOriginCanvasAndPre;
25
+ afterLoadSlice(): void;
26
+ private updateMaxIndex;
27
+ /****************************Rendering****************************************************/
28
+ /**
29
+ * Phase 3: Reload all mask layers from MaskVolume using buffer reuse
30
+ * Replaces the old reloadMaskToLayer approach
31
+ */
32
+ reloadMasksFromVolume(): void;
33
+ /******************************** redraw display canvas ***************************************/
34
+ /**
35
+ * Redraw current contrast image to display canvas.
36
+ * It is more related to change the contrast slice image's window width or center.
37
+ */
38
+ redrawDisplayCanvas(): void;
39
+ redrawMianPreOnDisplayCanvas(): void;
40
+ /**
41
+ * flip the canvas to a correct position.
42
+ * This is because the slice canvas from threejs is not in a correct 2D postion.
43
+ * Thus, everytime when we redraw the display canvas, we need to flip to draw the origin canvas from threejs.
44
+ * Under different axis(sagittal, Axial, Coronal), the flip orientation is different.
45
+ */
46
+ flipDisplayImageByAxis(): void;
47
+ /**
48
+ * Set the empty canvas width and height based on the axis (pixel distance not the mm), to reduce duplicate codes.
49
+ *
50
+ * @param axis
51
+ */
52
+ setEmptyCanvasSize(axis?: "x" | "y" | "z"): void;
53
+ /**
54
+ * Clear masks on drawingCanvas layers.
55
+ */
56
+ resetLayerCanvas(): void;
57
+ /****************************View/Canvas Helpers****************************************************/
58
+ /**
59
+ * Resize the draw and display canvas size based on the input size factor number.
60
+ * @param factor number
61
+ */
62
+ resizePaintArea(factor: number): void;
63
+ /**
64
+ * Reset the draw and display canvases layout after mouse pan.
65
+ * If no params in, then center the draw and display canvases.
66
+ * @param l number, Offset to the left
67
+ * @param t number, Offset to the top
68
+ */
69
+ resetPaintAreaUIPosition(l?: number, t?: number): void;
70
+ /**
71
+ * Update the original canvas size, allow set to threejs load one (pixel distance not the mm).
72
+ * Then update the changedWidth and changedHeight based on the sizeFactor.
73
+ */
74
+ updateOriginAndChangedWH(): void;
75
+ /**
76
+ * Keep all contrast slice index to same.
77
+ * Synchronize the slice indexes of all the contrasts so that they are consistent with the main slice's index.
78
+ */
79
+ setSyncsliceNum(): void;
80
+ }
@@ -0,0 +1,355 @@
1
+ import { BaseTool } from "./BaseTool";
2
+ /**
3
+ * Manages slice rendering pipeline: slice setup, canvas rendering, and view helpers.
4
+ *
5
+ * Extracted from NrrdTools.ts to reduce its size.
6
+ * Follows the same BaseTool + ToolContext + Callbacks pattern as other tools.
7
+ */
8
+ export class SliceRenderPipeline extends BaseTool {
9
+ constructor(ctx, callbacks) {
10
+ super(ctx);
11
+ this.initState = true;
12
+ this.callbacks = callbacks;
13
+ }
14
+ /**
15
+ * Reset initState to true (called from NrrdTools.reset() when switching datasets).
16
+ */
17
+ resetInitState() {
18
+ this.initState = true;
19
+ }
20
+ /****************************Slice Setup****************************************************/
21
+ setDisplaySlicesBaseOnAxis() {
22
+ this.ctx.protectedData.displaySlices.length = 0;
23
+ this.ctx.protectedData.backUpDisplaySlices.length = 0;
24
+ this.ctx.protectedData.allSlicesArray.forEach((slices) => {
25
+ this.ctx.protectedData.backUpDisplaySlices.push(slices[this.ctx.protectedData.axis]);
26
+ });
27
+ this.loadDisplaySlicesArray();
28
+ }
29
+ loadDisplaySlicesArray() {
30
+ const remainSlices = Object.values(this.ctx.protectedData.skipSlicesDic);
31
+ if (remainSlices.length === 0) {
32
+ // load all display slices
33
+ this.ctx.protectedData.backUpDisplaySlices.forEach((slice, index) => {
34
+ this.ctx.protectedData.skipSlicesDic[index] = slice;
35
+ this.ctx.protectedData.displaySlices.push(slice);
36
+ });
37
+ }
38
+ else {
39
+ remainSlices.forEach((slice, index) => {
40
+ if (!!slice) {
41
+ this.ctx.protectedData.displaySlices.push(this.ctx.protectedData.backUpDisplaySlices[index]);
42
+ this.ctx.protectedData.skipSlicesDic[index] =
43
+ this.ctx.protectedData.backUpDisplaySlices[index];
44
+ }
45
+ });
46
+ }
47
+ }
48
+ resetDisplaySlicesStatus() {
49
+ // reload slice data
50
+ this.setDisplaySlicesBaseOnAxis();
51
+ // reset canvas attribute for drag and draw
52
+ this.setupConfigs();
53
+ }
54
+ setupConfigs() {
55
+ // reset main slice
56
+ this.setMainPreSlice();
57
+ // update the max index for drag and slider
58
+ this.updateMaxIndex();
59
+ // reset origin canvas and the nrrd_states origin Width/height
60
+ // reset the current index
61
+ // (also calls resizePaintArea → reloads masks, resizes canvases)
62
+ this.setOriginCanvasAndPre();
63
+ // update the show number div on top area
64
+ this.callbacks.updateShowNumDiv(this.ctx.nrrd_states.view.contrastNum);
65
+ // repaint all contrast images
66
+ this.callbacks.repraintCurrentContrastSlice();
67
+ // Refresh display after contrast repaint (no need for full resizePaintArea
68
+ // since canvases were already resized in setOriginCanvasAndPre above)
69
+ this.redrawDisplayCanvas();
70
+ this.callbacks.compositeAllLayers();
71
+ // Sync slider metadata with current volume (replaces old getGuiSettings() side-effect)
72
+ this.callbacks.syncGuiParameterSettings();
73
+ }
74
+ setMainPreSlice() {
75
+ this.ctx.protectedData.mainPreSlices = this.ctx.protectedData.displaySlices[0];
76
+ if (this.ctx.protectedData.mainPreSlices) {
77
+ this.ctx.nrrd_states.image.RSARatio = this.ctx.protectedData.mainPreSlices.RSARatio;
78
+ }
79
+ }
80
+ setOriginCanvasAndPre() {
81
+ if (this.ctx.protectedData.mainPreSlices) {
82
+ if (this.ctx.nrrd_states.view.preSliceIndex > this.ctx.nrrd_states.view.maxIndex)
83
+ this.ctx.nrrd_states.view.preSliceIndex = this.ctx.nrrd_states.view.maxIndex;
84
+ if (this.initState) {
85
+ this.ctx.nrrd_states.view.preSliceIndex =
86
+ this.ctx.protectedData.mainPreSlices.initIndex *
87
+ this.ctx.nrrd_states.image.RSARatio;
88
+ this.ctx.nrrd_states.view.currentSliceIndex =
89
+ this.ctx.protectedData.mainPreSlices.initIndex;
90
+ }
91
+ else {
92
+ // !need to change
93
+ // todo
94
+ this.ctx.protectedData.mainPreSlices.index = this.ctx.nrrd_states.view.preSliceIndex;
95
+ }
96
+ this.ctx.protectedData.canvases.originCanvas =
97
+ this.ctx.protectedData.mainPreSlices.canvas;
98
+ this.updateOriginAndChangedWH();
99
+ }
100
+ }
101
+ afterLoadSlice() {
102
+ this.setMainPreSlice();
103
+ this.setOriginCanvasAndPre();
104
+ this.ctx.protectedData.currentShowingSlice = this.ctx.protectedData.mainPreSlices;
105
+ this.ctx.nrrd_states.view.preSliceIndex =
106
+ this.ctx.protectedData.mainPreSlices.initIndex * this.ctx.nrrd_states.image.RSARatio;
107
+ this.ctx.nrrd_states.view.currentSliceIndex = this.ctx.protectedData.mainPreSlices.initIndex;
108
+ // Phase 6: Reset undo/redo stacks on new dataset load
109
+ this.callbacks.clearUndoHistory();
110
+ // compute max index
111
+ this.updateMaxIndex();
112
+ this.callbacks.updateShowNumDiv(this.ctx.nrrd_states.view.contrastNum);
113
+ this.callbacks.syncGuiParameterSettings();
114
+ this.initState = false;
115
+ }
116
+ updateMaxIndex() {
117
+ if (this.ctx.protectedData.mainPreSlices) {
118
+ this.ctx.nrrd_states.view.maxIndex = this.ctx.protectedData.mainPreSlices.MaxIndex;
119
+ }
120
+ }
121
+ /****************************Rendering****************************************************/
122
+ /**
123
+ * Phase 3: Reload all mask layers from MaskVolume using buffer reuse
124
+ * Replaces the old reloadMaskToLayer approach
125
+ */
126
+ reloadMasksFromVolume() {
127
+ // When sphere mode is active, do NOT redraw layer masks.
128
+ // Layer mask data should remain hidden until the user exits sphere mode.
129
+ if (this.ctx.gui_states.mode.sphere) {
130
+ return;
131
+ }
132
+ const axis = this.ctx.protectedData.axis;
133
+ let sliceIndex = this.ctx.nrrd_states.view.currentSliceIndex;
134
+ // Clamp sliceIndex to valid range for current axis
135
+ // (currentSliceIndex may not be updated yet when switching axes)
136
+ try {
137
+ const vol = this.callbacks.getVolumeForLayer(this.ctx.nrrd_states.image.layers[0]);
138
+ const dims = vol.getDimensions();
139
+ const maxSlice = axis === "x" ? dims.width : axis === "y" ? dims.height : dims.depth;
140
+ if (sliceIndex >= maxSlice)
141
+ sliceIndex = maxSlice - 1;
142
+ if (sliceIndex < 0)
143
+ sliceIndex = 0;
144
+ }
145
+ catch ( /* volume not ready */_a) { /* volume not ready */ }
146
+ // Get a single reusable buffer shared across all layer renders
147
+ const buffer = this.callbacks.getOrCreateSliceBuffer(axis);
148
+ if (!buffer)
149
+ return;
150
+ const w = this.ctx.nrrd_states.view.changedWidth;
151
+ const h = this.ctx.nrrd_states.view.changedHeight;
152
+ // Clear and render each layer using the shared buffer
153
+ for (const layerId of this.ctx.nrrd_states.image.layers) {
154
+ const target = this.ctx.protectedData.layerTargets.get(layerId);
155
+ if (!target)
156
+ continue;
157
+ target.ctx.clearRect(0, 0, w, h);
158
+ this.callbacks.renderSliceToCanvas(layerId, axis, sliceIndex, buffer, target.ctx, w, h);
159
+ }
160
+ // Composite all layers to master canvas
161
+ this.callbacks.compositeAllLayers();
162
+ }
163
+ /******************************** redraw display canvas ***************************************/
164
+ /**
165
+ * Redraw current contrast image to display canvas.
166
+ * It is more related to change the contrast slice image's window width or center.
167
+ */
168
+ redrawDisplayCanvas() {
169
+ var _a, _b, _c;
170
+ this.callbacks.updateCurrentContrastSlice();
171
+ this.ctx.protectedData.canvases.displayCanvas.width =
172
+ this.ctx.protectedData.canvases.displayCanvas.width;
173
+ this.ctx.protectedData.canvases.displayCanvas.height =
174
+ this.ctx.protectedData.canvases.displayCanvas.height;
175
+ this.ctx.protectedData.canvases.originCanvas.width =
176
+ this.ctx.protectedData.canvases.originCanvas.width;
177
+ if (this.ctx.protectedData.currentShowingSlice) {
178
+ this.ctx.protectedData.currentShowingSlice.repaint.call(this.ctx.protectedData.currentShowingSlice);
179
+ (_a = this.ctx.protectedData.ctxes.displayCtx) === null || _a === void 0 ? void 0 : _a.save();
180
+ this.flipDisplayImageByAxis();
181
+ (_b = this.ctx.protectedData.ctxes.displayCtx) === null || _b === void 0 ? void 0 : _b.drawImage(this.ctx.protectedData.currentShowingSlice.canvas, 0, 0, this.ctx.nrrd_states.view.changedWidth, this.ctx.nrrd_states.view.changedHeight);
182
+ (_c = this.ctx.protectedData.ctxes.displayCtx) === null || _c === void 0 ? void 0 : _c.restore();
183
+ }
184
+ }
185
+ redrawMianPreOnDisplayCanvas() {
186
+ var _a;
187
+ this.ctx.protectedData.canvases.displayCanvas.width =
188
+ this.ctx.protectedData.canvases.displayCanvas.width;
189
+ this.ctx.protectedData.canvases.displayCanvas.height =
190
+ this.ctx.protectedData.canvases.displayCanvas.height;
191
+ this.ctx.protectedData.canvases.originCanvas.width =
192
+ this.ctx.protectedData.canvases.originCanvas.width;
193
+ if (this.ctx.protectedData.mainPreSlices) {
194
+ this.ctx.protectedData.mainPreSlices.repaint.call(this.ctx.protectedData.mainPreSlices);
195
+ this.flipDisplayImageByAxis();
196
+ (_a = this.ctx.protectedData.ctxes.displayCtx) === null || _a === void 0 ? void 0 : _a.drawImage(this.ctx.protectedData.canvases.originCanvas, 0, 0, this.ctx.nrrd_states.view.changedWidth, this.ctx.nrrd_states.view.changedHeight);
197
+ this.resizePaintArea(this.ctx.nrrd_states.view.sizeFactor);
198
+ }
199
+ }
200
+ /**
201
+ * flip the canvas to a correct position.
202
+ * This is because the slice canvas from threejs is not in a correct 2D postion.
203
+ * Thus, everytime when we redraw the display canvas, we need to flip to draw the origin canvas from threejs.
204
+ * Under different axis(sagittal, Axial, Coronal), the flip orientation is different.
205
+ */
206
+ flipDisplayImageByAxis() {
207
+ var _a, _b, _c, _d, _e, _f;
208
+ if (this.ctx.protectedData.axis === "x") {
209
+ (_a = this.ctx.protectedData.ctxes.displayCtx) === null || _a === void 0 ? void 0 : _a.scale(-1, -1);
210
+ (_b = this.ctx.protectedData.ctxes.displayCtx) === null || _b === void 0 ? void 0 : _b.translate(-this.ctx.nrrd_states.view.changedWidth, -this.ctx.nrrd_states.view.changedHeight);
211
+ }
212
+ else if (this.ctx.protectedData.axis === "z") {
213
+ (_c = this.ctx.protectedData.ctxes.displayCtx) === null || _c === void 0 ? void 0 : _c.scale(1, -1);
214
+ (_d = this.ctx.protectedData.ctxes.displayCtx) === null || _d === void 0 ? void 0 : _d.translate(0, -this.ctx.nrrd_states.view.changedHeight);
215
+ }
216
+ else if (this.ctx.protectedData.axis === "y") {
217
+ (_e = this.ctx.protectedData.ctxes.displayCtx) === null || _e === void 0 ? void 0 : _e.scale(1, -1);
218
+ (_f = this.ctx.protectedData.ctxes.displayCtx) === null || _f === void 0 ? void 0 : _f.translate(0, -this.ctx.nrrd_states.view.changedHeight);
219
+ }
220
+ }
221
+ /**
222
+ * Set the empty canvas width and height based on the axis (pixel distance not the mm), to reduce duplicate codes.
223
+ *
224
+ * @param axis
225
+ */
226
+ setEmptyCanvasSize(axis) {
227
+ switch (!!axis ? axis : this.ctx.protectedData.axis) {
228
+ case "x":
229
+ this.ctx.protectedData.canvases.emptyCanvas.width =
230
+ this.ctx.nrrd_states.image.nrrd_z_pixel;
231
+ this.ctx.protectedData.canvases.emptyCanvas.height =
232
+ this.ctx.nrrd_states.image.nrrd_y_pixel;
233
+ break;
234
+ case "y":
235
+ this.ctx.protectedData.canvases.emptyCanvas.width =
236
+ this.ctx.nrrd_states.image.nrrd_x_pixel;
237
+ this.ctx.protectedData.canvases.emptyCanvas.height =
238
+ this.ctx.nrrd_states.image.nrrd_z_pixel;
239
+ break;
240
+ case "z":
241
+ this.ctx.protectedData.canvases.emptyCanvas.width =
242
+ this.ctx.nrrd_states.image.nrrd_x_pixel;
243
+ this.ctx.protectedData.canvases.emptyCanvas.height =
244
+ this.ctx.nrrd_states.image.nrrd_y_pixel;
245
+ break;
246
+ }
247
+ }
248
+ /**
249
+ * Clear masks on drawingCanvas layers.
250
+ */
251
+ resetLayerCanvas() {
252
+ this.ctx.protectedData.canvases.drawingCanvasLayerMaster.width =
253
+ this.ctx.protectedData.canvases.drawingCanvasLayerMaster.width;
254
+ for (const [, target] of this.ctx.protectedData.layerTargets) {
255
+ target.canvas.width = target.canvas.width;
256
+ }
257
+ }
258
+ /****************************View/Canvas Helpers****************************************************/
259
+ /**
260
+ * Resize the draw and display canvas size based on the input size factor number.
261
+ * @param factor number
262
+ */
263
+ resizePaintArea(factor) {
264
+ const newWidth = Math.floor(this.ctx.nrrd_states.image.originWidth * factor);
265
+ const newHeight = Math.floor(this.ctx.nrrd_states.image.originHeight * factor);
266
+ const sizeChanged = newWidth !== this.ctx.nrrd_states.view.changedWidth ||
267
+ newHeight !== this.ctx.nrrd_states.view.changedHeight;
268
+ // Always clear display/drawing/origin canvases (needed for contrast updates)
269
+ this.ctx.protectedData.canvases.originCanvas.width =
270
+ this.ctx.protectedData.canvases.originCanvas.width;
271
+ this.ctx.protectedData.canvases.displayCanvas.width =
272
+ this.ctx.protectedData.canvases.displayCanvas.width;
273
+ this.ctx.protectedData.canvases.drawingCanvas.width =
274
+ this.ctx.protectedData.canvases.drawingCanvas.width;
275
+ if (sizeChanged) {
276
+ // Only clear and resize layer canvases when size actually changes.
277
+ // Skipping this avoids the expensive reloadMasksFromVolume() call
278
+ // during contrast toggle (where size stays the same).
279
+ this.resetLayerCanvas();
280
+ this.ctx.nrrd_states.view.changedWidth = newWidth;
281
+ this.ctx.nrrd_states.view.changedHeight = newHeight;
282
+ this.ctx.protectedData.canvases.displayCanvas.width = newWidth;
283
+ this.ctx.protectedData.canvases.displayCanvas.height = newHeight;
284
+ this.ctx.protectedData.canvases.drawingCanvas.width = newWidth;
285
+ this.ctx.protectedData.canvases.drawingCanvas.height = newHeight;
286
+ this.ctx.protectedData.canvases.drawingCanvasLayerMaster.width = newWidth;
287
+ this.ctx.protectedData.canvases.drawingCanvasLayerMaster.height = newHeight;
288
+ for (const [, target] of this.ctx.protectedData.layerTargets) {
289
+ target.canvas.width = newWidth;
290
+ target.canvas.height = newHeight;
291
+ }
292
+ }
293
+ this.redrawDisplayCanvas();
294
+ if (sizeChanged) {
295
+ // Phase 3: Reload masks from MaskVolume only when canvas size changed
296
+ this.reloadMasksFromVolume();
297
+ }
298
+ else {
299
+ // Size unchanged (e.g. contrast toggle): layer canvases still have
300
+ // valid data, just recomposite to master for the start() render loop.
301
+ this.callbacks.compositeAllLayers();
302
+ }
303
+ // Refresh sphere overlay from volume after resize/contrast change
304
+ this.callbacks.refreshSphereOverlay();
305
+ }
306
+ /**
307
+ * Reset the draw and display canvases layout after mouse pan.
308
+ * If no params in, then center the draw and display canvases.
309
+ * @param l number, Offset to the left
310
+ * @param t number, Offset to the top
311
+ */
312
+ resetPaintAreaUIPosition(l, t) {
313
+ if (l && t) {
314
+ this.ctx.protectedData.canvases.displayCanvas.style.left =
315
+ this.ctx.protectedData.canvases.drawingCanvas.style.left = l + "px";
316
+ this.ctx.protectedData.canvases.displayCanvas.style.top =
317
+ this.ctx.protectedData.canvases.drawingCanvas.style.top = t + "px";
318
+ }
319
+ else {
320
+ this.ctx.protectedData.canvases.displayCanvas.style.left =
321
+ this.ctx.protectedData.canvases.drawingCanvas.style.left = "";
322
+ this.ctx.protectedData.canvases.displayCanvas.style.top =
323
+ this.ctx.protectedData.canvases.drawingCanvas.style.top = "";
324
+ this.ctx.protectedData.mainAreaContainer.style.justifyContent = "center";
325
+ this.ctx.protectedData.mainAreaContainer.style.alignItems = "center";
326
+ }
327
+ }
328
+ /**
329
+ * Update the original canvas size, allow set to threejs load one (pixel distance not the mm).
330
+ * Then update the changedWidth and changedHeight based on the sizeFactor.
331
+ */
332
+ updateOriginAndChangedWH() {
333
+ this.ctx.nrrd_states.image.originWidth =
334
+ this.ctx.protectedData.canvases.originCanvas.width;
335
+ this.ctx.nrrd_states.image.originHeight =
336
+ this.ctx.protectedData.canvases.originCanvas.height;
337
+ // Let resizePaintArea be the sole setter of changedWidth/changedHeight.
338
+ // Setting them here would defeat the sizeChanged detection in resizePaintArea,
339
+ // causing canvas elements to keep stale dimensions after axis switches.
340
+ this.resizePaintArea(this.ctx.nrrd_states.view.sizeFactor);
341
+ this.resetPaintAreaUIPosition();
342
+ }
343
+ /**
344
+ * Keep all contrast slice index to same.
345
+ * Synchronize the slice indexes of all the contrasts so that they are consistent with the main slice's index.
346
+ */
347
+ setSyncsliceNum() {
348
+ this.ctx.protectedData.displaySlices.forEach((slice, index) => {
349
+ if (index !== 0) {
350
+ slice.index = this.ctx.protectedData.mainPreSlices.index;
351
+ }
352
+ });
353
+ }
354
+ }
355
+ //# sourceMappingURL=SliceRenderPipeline.js.map