copper3d 3.0.1 → 3.0.2
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.
- package/README.md +195 -28
- package/dist/Utils/segmentation/CommToolsData.d.ts +24 -9
- package/dist/Utils/segmentation/CommToolsData.js +65 -139
- package/dist/Utils/segmentation/CommToolsData.js.map +1 -1
- package/dist/Utils/segmentation/DragOperator.d.ts +10 -2
- package/dist/Utils/segmentation/DragOperator.js +14 -4
- package/dist/Utils/segmentation/DragOperator.js.map +1 -1
- package/dist/Utils/segmentation/DrawToolCore.d.ts +23 -16
- package/dist/Utils/segmentation/DrawToolCore.js +218 -401
- package/dist/Utils/segmentation/DrawToolCore.js.map +1 -1
- package/dist/Utils/segmentation/NrrdTools.d.ts +152 -10
- package/dist/Utils/segmentation/NrrdTools.js +599 -202
- package/dist/Utils/segmentation/NrrdTools.js.map +1 -1
- package/dist/Utils/segmentation/core/MaskVolume.d.ts +1 -1
- package/dist/Utils/segmentation/core/MaskVolume.js +24 -3
- package/dist/Utils/segmentation/core/MaskVolume.js.map +1 -1
- package/dist/Utils/segmentation/core/UndoManager.d.ts +1 -1
- package/dist/Utils/segmentation/core/UndoManager.js +1 -1
- package/dist/Utils/segmentation/core/index.d.ts +0 -2
- package/dist/Utils/segmentation/core/index.js +0 -1
- package/dist/Utils/segmentation/core/index.js.map +1 -1
- package/dist/Utils/segmentation/core/types.js +24 -24
- package/dist/Utils/segmentation/core/types.js.map +1 -1
- package/dist/Utils/segmentation/coreTools/GuiState.d.ts +22 -0
- package/dist/Utils/segmentation/coreTools/GuiState.js +48 -0
- package/dist/Utils/segmentation/coreTools/GuiState.js.map +1 -0
- package/dist/Utils/segmentation/coreTools/NrrdState.d.ts +25 -0
- package/dist/Utils/segmentation/coreTools/NrrdState.js +85 -0
- package/dist/Utils/segmentation/coreTools/NrrdState.js.map +1 -0
- package/dist/Utils/segmentation/coreTools/coreType.d.ts +88 -62
- package/dist/Utils/segmentation/coreTools/coreType.js.map +1 -1
- package/dist/Utils/segmentation/coreTools/divControlTools.js +1 -1
- package/dist/Utils/segmentation/coreTools/divControlTools.js.map +1 -1
- package/dist/Utils/segmentation/coreTools/gui.d.ts +12 -12
- package/dist/Utils/segmentation/coreTools/gui.js +81 -107
- package/dist/Utils/segmentation/coreTools/gui.js.map +1 -1
- package/dist/Utils/segmentation/eventRouter/EventRouter.d.ts +2 -1
- package/dist/Utils/segmentation/eventRouter/EventRouter.js +15 -10
- package/dist/Utils/segmentation/eventRouter/EventRouter.js.map +1 -1
- package/dist/Utils/segmentation/eventRouter/types.d.ts +3 -3
- package/dist/Utils/segmentation/tools/BaseTool.d.ts +8 -5
- package/dist/Utils/segmentation/tools/BaseTool.js +1 -2
- package/dist/Utils/segmentation/tools/BaseTool.js.map +1 -1
- package/dist/Utils/segmentation/tools/CrosshairTool.js +25 -25
- package/dist/Utils/segmentation/tools/CrosshairTool.js.map +1 -1
- package/dist/Utils/segmentation/tools/DragSliceTool.d.ts +2 -0
- package/dist/Utils/segmentation/tools/DragSliceTool.js +63 -53
- package/dist/Utils/segmentation/tools/DragSliceTool.js.map +1 -1
- package/dist/Utils/segmentation/tools/DrawingTool.d.ts +93 -0
- package/dist/Utils/segmentation/tools/DrawingTool.js +222 -0
- package/dist/Utils/segmentation/tools/DrawingTool.js.map +1 -0
- package/dist/Utils/segmentation/tools/EraserTool.js +8 -8
- package/dist/Utils/segmentation/tools/EraserTool.js.map +1 -1
- package/dist/Utils/segmentation/tools/ImageStoreHelper.d.ts +11 -28
- package/dist/Utils/segmentation/tools/ImageStoreHelper.js +39 -82
- package/dist/Utils/segmentation/tools/ImageStoreHelper.js.map +1 -1
- package/dist/Utils/segmentation/tools/PanTool.d.ts +53 -0
- package/dist/Utils/segmentation/tools/PanTool.js +90 -0
- package/dist/Utils/segmentation/tools/PanTool.js.map +1 -0
- package/dist/Utils/segmentation/tools/SphereTool.d.ts +208 -1
- package/dist/Utils/segmentation/tools/SphereTool.js +456 -45
- package/dist/Utils/segmentation/tools/SphereTool.js.map +1 -1
- package/dist/Utils/segmentation/tools/ZoomTool.js +3 -3
- package/dist/Utils/segmentation/tools/ZoomTool.js.map +1 -1
- package/dist/Utils/segmentation/tools/index.d.ts +6 -2
- package/dist/Utils/segmentation/tools/index.js +4 -1
- package/dist/Utils/segmentation/tools/index.js.map +1 -1
- package/dist/bundle.esm.js +2452 -1492
- package/dist/bundle.umd.js +2452 -1492
- package/dist/index.d.ts +6 -3
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/types/Utils/segmentation/CommToolsData.d.ts +24 -9
- package/dist/types/Utils/segmentation/DragOperator.d.ts +10 -2
- package/dist/types/Utils/segmentation/DrawToolCore.d.ts +23 -16
- package/dist/types/Utils/segmentation/NrrdTools.d.ts +152 -10
- package/dist/types/Utils/segmentation/core/MaskVolume.d.ts +1 -1
- package/dist/types/Utils/segmentation/core/UndoManager.d.ts +1 -1
- package/dist/types/Utils/segmentation/core/index.d.ts +0 -2
- package/dist/types/Utils/segmentation/coreTools/GuiState.d.ts +22 -0
- package/dist/types/Utils/segmentation/coreTools/NrrdState.d.ts +25 -0
- package/dist/types/Utils/segmentation/coreTools/coreType.d.ts +88 -62
- package/dist/types/Utils/segmentation/coreTools/gui.d.ts +12 -12
- package/dist/types/Utils/segmentation/eventRouter/EventRouter.d.ts +2 -1
- package/dist/types/Utils/segmentation/eventRouter/types.d.ts +3 -3
- package/dist/types/Utils/segmentation/tools/BaseTool.d.ts +8 -5
- package/dist/types/Utils/segmentation/tools/DragSliceTool.d.ts +2 -0
- package/dist/types/Utils/segmentation/tools/DrawingTool.d.ts +93 -0
- package/dist/types/Utils/segmentation/tools/ImageStoreHelper.d.ts +11 -28
- package/dist/types/Utils/segmentation/tools/PanTool.d.ts +53 -0
- package/dist/types/Utils/segmentation/tools/SphereTool.d.ts +208 -1
- package/dist/types/Utils/segmentation/tools/index.d.ts +6 -2
- package/dist/types/index.d.ts +6 -3
- package/package.json +1 -1
- package/dist/Utils/segmentation/core/MigrationUtils.d.ts +0 -97
- package/dist/Utils/segmentation/core/MigrationUtils.js +0 -163
- package/dist/Utils/segmentation/core/MigrationUtils.js.map +0 -1
- package/dist/types/Utils/segmentation/core/MigrationUtils.d.ts +0 -97
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { CommToolsData } from "./CommToolsData";
|
|
2
|
-
import {
|
|
2
|
+
import { switchPencilIcon } from "../utils";
|
|
3
3
|
import { EventRouter } from "./eventRouter";
|
|
4
4
|
import { SphereTool } from "./tools/SphereTool";
|
|
5
5
|
import { CrosshairTool } from "./tools/CrosshairTool";
|
|
6
6
|
import { ContrastTool } from "./tools/ContrastTool";
|
|
7
7
|
import { ZoomTool } from "./tools/ZoomTool";
|
|
8
8
|
import { EraserTool } from "./tools/EraserTool";
|
|
9
|
+
import { PanTool } from "./tools/PanTool";
|
|
10
|
+
import { DrawingTool } from "./tools/DrawingTool";
|
|
9
11
|
import { ImageStoreHelper } from "./tools/ImageStoreHelper";
|
|
10
12
|
import { UndoManager } from "./core";
|
|
11
13
|
export class DrawToolCore extends CommToolsData {
|
|
@@ -37,12 +39,10 @@ export class DrawToolCore extends CommToolsData {
|
|
|
37
39
|
this.eraserUrls = [];
|
|
38
40
|
this.pencilUrls = [];
|
|
39
41
|
this.undoManager = new UndoManager();
|
|
40
|
-
/** Snapshot of the active layer's slice captured on mouse-down (before drawing). */
|
|
41
|
-
this.preDrawSlice = null;
|
|
42
|
-
this.preDrawAxis = "z";
|
|
43
|
-
this.preDrawSliceIndex = 0;
|
|
44
42
|
// Centralized event router
|
|
45
43
|
this.eventRouter = null;
|
|
44
|
+
/** Slice index recorded when paintOnCanvas() starts, guards stale-click */
|
|
45
|
+
this.paintSliceIndex = 0;
|
|
46
46
|
// need to return to parent
|
|
47
47
|
this.start = () => { };
|
|
48
48
|
/*************************************May consider to move outside *******************************************/
|
|
@@ -50,7 +50,7 @@ export class DrawToolCore extends CommToolsData {
|
|
|
50
50
|
this.protectedData.ctxes.drawingCtx.beginPath();
|
|
51
51
|
this.protectedData.ctxes.drawingCtx.moveTo(x1, y1);
|
|
52
52
|
this.protectedData.ctxes.drawingCtx.lineTo(x2, y2);
|
|
53
|
-
this.protectedData.ctxes.drawingCtx.strokeStyle = this.gui_states.color;
|
|
53
|
+
this.protectedData.ctxes.drawingCtx.strokeStyle = this.gui_states.drawing.color;
|
|
54
54
|
this.protectedData.ctxes.drawingCtx.stroke();
|
|
55
55
|
};
|
|
56
56
|
this.configContrastDragMode = () => {
|
|
@@ -76,6 +76,7 @@ export class DrawToolCore extends CommToolsData {
|
|
|
76
76
|
gui_states: this.gui_states,
|
|
77
77
|
protectedData: this.protectedData,
|
|
78
78
|
cursorPage: this.cursorPage,
|
|
79
|
+
callbacks: this.annotationCallbacks,
|
|
79
80
|
};
|
|
80
81
|
this.imageStoreHelper = new ImageStoreHelper(toolCtx, {
|
|
81
82
|
setEmptyCanvasSize: (axis) => this.setEmptyCanvasSize(axis),
|
|
@@ -84,7 +85,6 @@ export class DrawToolCore extends CommToolsData {
|
|
|
84
85
|
this.sphereTool = new SphereTool(toolCtx, {
|
|
85
86
|
setEmptyCanvasSize: (axis) => this.setEmptyCanvasSize(axis),
|
|
86
87
|
drawImageOnEmptyImage: (canvas) => this.drawImageOnEmptyImage(canvas),
|
|
87
|
-
storeImageToAxis: (index, imageData, axis) => this.imageStoreHelper.storeImageToAxis(index, imageData, axis),
|
|
88
88
|
});
|
|
89
89
|
this.crosshairTool = new CrosshairTool(toolCtx);
|
|
90
90
|
this.contrastTool = new ContrastTool(toolCtx, this.container, this.contrastEventPrameters, {
|
|
@@ -97,6 +97,18 @@ export class DrawToolCore extends CommToolsData {
|
|
|
97
97
|
setIsDrawFalse: (target) => this.setIsDrawFalse(target),
|
|
98
98
|
});
|
|
99
99
|
this.eraserTool = new EraserTool(toolCtx);
|
|
100
|
+
this.panTool = new PanTool(toolCtx, {
|
|
101
|
+
zoomActionAfterDrawSphere: () => this.zoomActionAfterDrawSphere(),
|
|
102
|
+
});
|
|
103
|
+
this.drawingTool = new DrawingTool(toolCtx, {
|
|
104
|
+
setCurrentLayer: () => this.setCurrentLayer(),
|
|
105
|
+
compositeAllLayers: () => this.compositeAllLayers(),
|
|
106
|
+
syncLayerSliceData: (index, layer) => this.syncLayerSliceData(index, layer),
|
|
107
|
+
filterDrawedImage: (axis, index) => this.filterDrawedImage(axis, index),
|
|
108
|
+
getVolumeForLayer: (layer) => this.getVolumeForLayer(layer),
|
|
109
|
+
pushUndoDelta: (delta) => this.undoManager.push(delta),
|
|
110
|
+
getEraserUrls: () => this.eraserUrls,
|
|
111
|
+
});
|
|
100
112
|
}
|
|
101
113
|
initDrawToolCore() {
|
|
102
114
|
// Initialize EventRouter for centralized event handling
|
|
@@ -112,10 +124,10 @@ export class DrawToolCore extends CommToolsData {
|
|
|
112
124
|
}
|
|
113
125
|
else if (prev === 'contrast') {
|
|
114
126
|
this.removeContrastDragMode();
|
|
115
|
-
this.gui_states.readyToUpdate = true;
|
|
127
|
+
this.gui_states.viewConfig.readyToUpdate = true;
|
|
116
128
|
}
|
|
117
129
|
if (next === 'crosshair') {
|
|
118
|
-
this.protectedData.
|
|
130
|
+
this.protectedData.isDrawing = false;
|
|
119
131
|
}
|
|
120
132
|
}
|
|
121
133
|
});
|
|
@@ -128,7 +140,7 @@ export class DrawToolCore extends CommToolsData {
|
|
|
128
140
|
let undoFlag = false;
|
|
129
141
|
// Register keyboard handlers with EventRouter
|
|
130
142
|
this.eventRouter.setKeydownHandler((ev) => {
|
|
131
|
-
var _a, _b;
|
|
143
|
+
var _a, _b, _c, _d;
|
|
132
144
|
if (this._configKeyBoard)
|
|
133
145
|
return;
|
|
134
146
|
// Handle undo (Ctrl+Z)
|
|
@@ -142,20 +154,32 @@ export class DrawToolCore extends CommToolsData {
|
|
|
142
154
|
if ((ev.ctrlKey || ev.metaKey) && (ev.key === redoKey || (ev.shiftKey && ev.key === undoKeyUpper))) {
|
|
143
155
|
this.redoLastPainting();
|
|
144
156
|
}
|
|
145
|
-
// Handle crosshair toggle
|
|
157
|
+
// Handle crosshair toggle (allowed in drawing tools AND sphere mode)
|
|
146
158
|
if (ev.key === this._keyboardSettings.crosshair) {
|
|
147
|
-
|
|
148
|
-
(_a = this.eventRouter) === null || _a === void 0 ? void 0 : _a.toggleCrosshair();
|
|
149
|
-
}
|
|
159
|
+
(_a = this.eventRouter) === null || _a === void 0 ? void 0 : _a.toggleCrosshair();
|
|
150
160
|
}
|
|
151
161
|
// Handle draw mode (Shift key) - EventRouter already tracks this
|
|
152
162
|
// EventRouter's handleKeyDown will enforce mutual exclusion
|
|
153
|
-
if (ev.key === this._keyboardSettings.draw && !this.gui_states.sphere
|
|
163
|
+
if (ev.key === this._keyboardSettings.draw && !this.gui_states.mode.sphere) {
|
|
154
164
|
if ((_b = this.eventRouter) === null || _b === void 0 ? void 0 : _b.isCtrlHeld()) {
|
|
155
165
|
return; // Ctrl takes priority
|
|
156
166
|
}
|
|
157
167
|
// EventRouter will set mode to 'draw' via internal handler
|
|
158
168
|
}
|
|
169
|
+
// Handle sphere mode toggle
|
|
170
|
+
if (ev.key === this._keyboardSettings.sphere) {
|
|
171
|
+
// Block during draw mode or contrast mode
|
|
172
|
+
if (((_c = this.eventRouter) === null || _c === void 0 ? void 0 : _c.isShiftHeld()) || ((_d = this.eventRouter) === null || _d === void 0 ? void 0 : _d.isCtrlHeld())) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
this.gui_states.mode.sphere = !this.gui_states.mode.sphere;
|
|
176
|
+
if (this.gui_states.mode.sphere) {
|
|
177
|
+
this.enterSphereMode();
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
this.exitSphereMode();
|
|
181
|
+
}
|
|
182
|
+
}
|
|
159
183
|
});
|
|
160
184
|
this.eventRouter.setKeyupHandler((ev) => {
|
|
161
185
|
var _a, _b, _c, _d, _e, _f;
|
|
@@ -164,16 +188,18 @@ export class DrawToolCore extends CommToolsData {
|
|
|
164
188
|
// Handle Ctrl key release (contrast mode toggle)
|
|
165
189
|
if (this._keyboardSettings.contrast.includes(ev.key)) {
|
|
166
190
|
if (undoFlag) {
|
|
167
|
-
this.gui_states.readyToUpdate = true;
|
|
191
|
+
this.gui_states.viewConfig.readyToUpdate = true;
|
|
168
192
|
undoFlag = false;
|
|
169
193
|
return;
|
|
170
194
|
}
|
|
171
195
|
// Skip mode toggle when contrast shortcut is disabled
|
|
172
196
|
if (!((_a = this.eventRouter) === null || _a === void 0 ? void 0 : _a.isContrastEnabled()))
|
|
173
197
|
return;
|
|
174
|
-
// Block contrast toggle during crosshair or
|
|
198
|
+
// Block contrast toggle during crosshair, draw, or sphere (mutual exclusion)
|
|
175
199
|
if (((_b = this.eventRouter) === null || _b === void 0 ? void 0 : _b.isCrosshairEnabled()) || ((_c = this.eventRouter) === null || _c === void 0 ? void 0 : _c.getMode()) === 'draw')
|
|
176
200
|
return;
|
|
201
|
+
if (this.gui_states.mode.sphere)
|
|
202
|
+
return;
|
|
177
203
|
// Toggle contrast mode manually since it's on keyup
|
|
178
204
|
if (((_d = this.eventRouter) === null || _d === void 0 ? void 0 : _d.getMode()) !== 'contrast') {
|
|
179
205
|
(_e = this.eventRouter) === null || _e === void 0 ? void 0 : _e.setMode('contrast');
|
|
@@ -191,78 +217,38 @@ export class DrawToolCore extends CommToolsData {
|
|
|
191
217
|
}
|
|
192
218
|
setPencilIconUrls(urls) {
|
|
193
219
|
this.pencilUrls = urls;
|
|
194
|
-
this.gui_states.defaultPaintCursor = switchPencilIcon("dot", this.pencilUrls);
|
|
220
|
+
this.gui_states.viewConfig.defaultPaintCursor = switchPencilIcon("dot", this.pencilUrls);
|
|
195
221
|
this.protectedData.canvases.drawingCanvas.style.cursor =
|
|
196
|
-
this.gui_states.defaultPaintCursor;
|
|
222
|
+
this.gui_states.viewConfig.defaultPaintCursor;
|
|
197
223
|
}
|
|
198
224
|
setCurrentLayer() {
|
|
199
|
-
const layer = this.gui_states.layer;
|
|
225
|
+
const layer = this.gui_states.layerChannel.layer;
|
|
200
226
|
let target = this.protectedData.layerTargets.get(layer);
|
|
201
227
|
if (!target) {
|
|
202
228
|
// Fallback to first layer
|
|
203
|
-
const firstId = this.nrrd_states.layers[0];
|
|
229
|
+
const firstId = this.nrrd_states.image.layers[0];
|
|
204
230
|
target = this.protectedData.layerTargets.get(firstId);
|
|
205
231
|
}
|
|
206
232
|
return { ctx: target.ctx, canvas: target.canvas };
|
|
207
233
|
}
|
|
208
234
|
draw(opts) {
|
|
209
235
|
if (!!opts) {
|
|
210
|
-
|
|
211
|
-
if (opts
|
|
212
|
-
this.
|
|
236
|
+
// Phase 2: Store callbacks in annotationCallbacks instead of nrrd_states
|
|
237
|
+
if (opts.getMaskData) {
|
|
238
|
+
this.annotationCallbacks.onMaskChanged = opts.getMaskData;
|
|
239
|
+
}
|
|
240
|
+
if (opts.onClearLayerVolume) {
|
|
241
|
+
this.annotationCallbacks.onLayerVolumeCleared = opts.onClearLayerVolume;
|
|
242
|
+
}
|
|
243
|
+
if (opts.getSphereData) {
|
|
244
|
+
this.annotationCallbacks.onSphereChanged = opts.getSphereData;
|
|
245
|
+
}
|
|
246
|
+
if (opts.getCalculateSpherePositionsData) {
|
|
247
|
+
this.annotationCallbacks.onCalculatorPositionsChanged = opts.getCalculateSpherePositionsData;
|
|
213
248
|
}
|
|
214
|
-
this.nrrd_states.getSphere = opts === null || opts === void 0 ? void 0 : opts.getSphereData;
|
|
215
|
-
this.nrrd_states.getCalculateSpherePositions = opts === null || opts === void 0 ? void 0 : opts.getCalculateSpherePositionsData;
|
|
216
249
|
}
|
|
217
250
|
this.paintOnCanvas();
|
|
218
251
|
}
|
|
219
|
-
drawCalSphereDown(x, y, sliceIndex, cal_position) {
|
|
220
|
-
this.nrrd_states.sphereRadius = 5;
|
|
221
|
-
this.protectedData.canvases.drawingCanvas.removeEventListener("wheel", this.drawingPrameters.handleMouseZoomSliceWheel);
|
|
222
|
-
let mouseX = x / this.nrrd_states.sizeFoctor;
|
|
223
|
-
let mouseY = y / this.nrrd_states.sizeFoctor;
|
|
224
|
-
// record mouseX,Y, and enable crosshair function
|
|
225
|
-
this.nrrd_states.sphereOrigin[this.protectedData.axis] = [
|
|
226
|
-
mouseX,
|
|
227
|
-
mouseY,
|
|
228
|
-
sliceIndex,
|
|
229
|
-
];
|
|
230
|
-
this.setUpSphereOrigins(mouseX, mouseY, sliceIndex);
|
|
231
|
-
// Note the sphere origin here is x, y, z
|
|
232
|
-
// x: pixel x, y: pixel y, z: slice index (mm)
|
|
233
|
-
switch (cal_position) {
|
|
234
|
-
case "tumour":
|
|
235
|
-
this.nrrd_states.tumourSphereOrigin = JSON.parse(JSON.stringify(this.nrrd_states.sphereOrigin));
|
|
236
|
-
break;
|
|
237
|
-
case "skin":
|
|
238
|
-
this.nrrd_states.skinSphereOrigin = JSON.parse(JSON.stringify(this.nrrd_states.sphereOrigin));
|
|
239
|
-
break;
|
|
240
|
-
case "nipple":
|
|
241
|
-
this.nrrd_states.nippleSphereOrigin = JSON.parse(JSON.stringify(this.nrrd_states.sphereOrigin));
|
|
242
|
-
break;
|
|
243
|
-
case "ribcage":
|
|
244
|
-
this.nrrd_states.ribSphereOrigin = JSON.parse(JSON.stringify(this.nrrd_states.sphereOrigin));
|
|
245
|
-
break;
|
|
246
|
-
}
|
|
247
|
-
this.nrrd_states.cursorPageX = mouseX;
|
|
248
|
-
this.nrrd_states.cursorPageY = mouseY;
|
|
249
|
-
this.enableCrosshair();
|
|
250
|
-
// draw circle setup width/height for sphere canvas
|
|
251
|
-
this.drawCalculatorSphere(this.nrrd_states.sphereRadius);
|
|
252
|
-
this.protectedData.canvases.drawingCanvas.addEventListener("pointerup", this.drawingPrameters.handleOnDrawingMouseUp);
|
|
253
|
-
}
|
|
254
|
-
drawCalSphereUp() {
|
|
255
|
-
// TODO send data to outside
|
|
256
|
-
// this.clearStoreImages();
|
|
257
|
-
this.clearSpherePrintStoreImages();
|
|
258
|
-
this.drawCalculatorSphereOnEachViews("x");
|
|
259
|
-
this.drawCalculatorSphereOnEachViews("y");
|
|
260
|
-
this.drawCalculatorSphereOnEachViews("z");
|
|
261
|
-
!!this.nrrd_states.getCalculateSpherePositions &&
|
|
262
|
-
this.nrrd_states.getCalculateSpherePositions(this.nrrd_states.tumourSphereOrigin, this.nrrd_states.skinSphereOrigin, this.nrrd_states.ribSphereOrigin, this.nrrd_states.nippleSphereOrigin, this.protectedData.axis);
|
|
263
|
-
this.zoomActionAfterDrawSphere();
|
|
264
|
-
this.protectedData.canvases.drawingCanvas.removeEventListener("pointerup", this.drawingPrameters.handleOnDrawingMouseUp);
|
|
265
|
-
}
|
|
266
252
|
zoomActionAfterDrawSphere() {
|
|
267
253
|
this.protectedData.canvases.drawingCanvas.addEventListener("wheel", this.drawingPrameters.handleMouseZoomSliceWheel);
|
|
268
254
|
}
|
|
@@ -271,28 +257,16 @@ export class DrawToolCore extends CommToolsData {
|
|
|
271
257
|
}
|
|
272
258
|
paintOnCanvas() {
|
|
273
259
|
var _a, _b, _c;
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
let rightclicked = false;
|
|
279
|
-
let panelMoveInnerX = 0;
|
|
280
|
-
let panelMoveInnerY = 0;
|
|
281
|
-
// todo
|
|
282
|
-
// let currentSliceIndex = this.protectedData.mainPreSlices.index;
|
|
283
|
-
let currentSliceIndex = this.protectedData.mainPreSlices.index;
|
|
284
|
-
// draw lines starts position
|
|
285
|
-
let Is_Painting = false;
|
|
286
|
-
let lines = [];
|
|
287
|
-
const clearArc = this.useEraser();
|
|
260
|
+
// Initialize tools for this paint cycle
|
|
261
|
+
this.drawingTool.reset(this.useEraser());
|
|
262
|
+
this.panTool.reset();
|
|
263
|
+
this.paintSliceIndex = this.protectedData.mainPreSlices.index;
|
|
288
264
|
this.updateOriginAndChangedWH();
|
|
289
265
|
this.initAllCanvas();
|
|
290
266
|
(_a = this.protectedData.ctxes.displayCtx) === null || _a === void 0 ? void 0 : _a.save();
|
|
291
267
|
this.flipDisplayImageByAxis();
|
|
292
|
-
(_b = this.protectedData.ctxes.displayCtx) === null || _b === void 0 ? void 0 : _b.drawImage(this.protectedData.canvases.originCanvas, 0, 0, this.nrrd_states.changedWidth, this.nrrd_states.changedHeight);
|
|
268
|
+
(_b = this.protectedData.ctxes.displayCtx) === null || _b === void 0 ? void 0 : _b.drawImage(this.protectedData.canvases.originCanvas, 0, 0, this.nrrd_states.view.changedWidth, this.nrrd_states.view.changedHeight);
|
|
293
269
|
(_c = this.protectedData.ctxes.displayCtx) === null || _c === void 0 ? void 0 : _c.restore();
|
|
294
|
-
this.protectedData.previousDrawingImage =
|
|
295
|
-
this.protectedData.ctxes.drawingCtx.getImageData(0, 0, this.protectedData.canvases.drawingCanvas.width, this.protectedData.canvases.drawingCanvas.height);
|
|
296
270
|
// let a global variable to store the wheel move event
|
|
297
271
|
// Remove existing listener before creating a new one to prevent leaks
|
|
298
272
|
this.protectedData.canvases.drawingCanvas.removeEventListener("wheel", this.drawingPrameters.handleMouseZoomSliceWheel);
|
|
@@ -309,125 +283,62 @@ export class DrawToolCore extends CommToolsData {
|
|
|
309
283
|
});
|
|
310
284
|
// sphere Wheel
|
|
311
285
|
this.drawingPrameters.handleSphereWheel = this.configMouseSphereWheel();
|
|
312
|
-
// pan move
|
|
313
|
-
this.drawingPrameters.handleOnPanMouseMove = (e) => {
|
|
314
|
-
this.protectedData.canvases.drawingCanvas.style.cursor = "grabbing";
|
|
315
|
-
this.nrrd_states.previousPanelL = e.clientX - panelMoveInnerX;
|
|
316
|
-
this.nrrd_states.previousPanelT = e.clientY - panelMoveInnerY;
|
|
317
|
-
this.protectedData.canvases.displayCanvas.style.left =
|
|
318
|
-
this.protectedData.canvases.drawingCanvas.style.left =
|
|
319
|
-
this.nrrd_states.previousPanelL + "px";
|
|
320
|
-
this.protectedData.canvases.displayCanvas.style.top =
|
|
321
|
-
this.protectedData.canvases.drawingCanvas.style.top =
|
|
322
|
-
this.nrrd_states.previousPanelT + "px";
|
|
323
|
-
};
|
|
286
|
+
// pan move — now handled by PanTool (listeners managed internally)
|
|
324
287
|
// brush circle move
|
|
325
288
|
this.drawingPrameters.handleOnDrawingBrushCricleMove = (e) => {
|
|
326
289
|
e.preventDefault();
|
|
327
|
-
this.nrrd_states.
|
|
328
|
-
this.nrrd_states.
|
|
329
|
-
if (this.nrrd_states.
|
|
330
|
-
this.nrrd_states.
|
|
331
|
-
this.nrrd_states.
|
|
290
|
+
this.nrrd_states.interaction.mouseOverX = e.offsetX;
|
|
291
|
+
this.nrrd_states.interaction.mouseOverY = e.offsetY;
|
|
292
|
+
if (this.nrrd_states.interaction.mouseOverX === undefined) {
|
|
293
|
+
this.nrrd_states.interaction.mouseOverX = e.clientX;
|
|
294
|
+
this.nrrd_states.interaction.mouseOverY = e.clientY;
|
|
332
295
|
}
|
|
333
296
|
if (e.type === "mouseout") {
|
|
334
|
-
this.nrrd_states.
|
|
297
|
+
this.nrrd_states.interaction.mouseOver = false;
|
|
335
298
|
this.protectedData.canvases.drawingCanvas.removeEventListener("mousemove", this.drawingPrameters.handleOnDrawingBrushCricleMove);
|
|
336
299
|
}
|
|
337
300
|
else if (e.type === "mouseover") {
|
|
338
|
-
this.nrrd_states.
|
|
301
|
+
this.nrrd_states.interaction.mouseOver = true;
|
|
339
302
|
this.protectedData.canvases.drawingCanvas.addEventListener("mousemove", this.drawingPrameters.handleOnDrawingBrushCricleMove);
|
|
340
303
|
}
|
|
341
304
|
};
|
|
342
|
-
// drawing move
|
|
305
|
+
// drawing move — delegated to DrawingTool
|
|
343
306
|
this.drawingPrameters.handleOnDrawingMouseMove = (e) => {
|
|
344
|
-
this.
|
|
345
|
-
if (Is_Painting) {
|
|
346
|
-
if (this.gui_states.Eraser) {
|
|
347
|
-
this.nrrd_states.stepClear = 1;
|
|
348
|
-
// drawingCtx.clearRect(e.offsetX - 5, e.offsetY - 5, 25, 25);
|
|
349
|
-
clearArc(e.offsetX, e.offsetY, this.gui_states.brushAndEraserSize);
|
|
350
|
-
}
|
|
351
|
-
else {
|
|
352
|
-
lines.push({ x: e.offsetX, y: e.offsetY });
|
|
353
|
-
this.paintOnCanvasLayer(e.offsetX, e.offsetY);
|
|
354
|
-
}
|
|
355
|
-
}
|
|
307
|
+
this.drawingTool.onPointerMove(e);
|
|
356
308
|
};
|
|
357
309
|
this.drawingPrameters.handleOnDrawingMouseDown = (e) => {
|
|
358
|
-
var _a, _b, _c
|
|
359
|
-
if (
|
|
310
|
+
var _a, _b, _c;
|
|
311
|
+
if (this.drawingTool.isActive || this.panTool.isActive) {
|
|
360
312
|
this.protectedData.canvases.drawingCanvas.removeEventListener("pointerup", this.drawingPrameters.handleOnDrawingMouseUp);
|
|
361
313
|
this.protectedData.ctxes.drawingLayerMasterCtx.closePath();
|
|
362
314
|
return;
|
|
363
315
|
}
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
if (currentSliceIndex !== this.protectedData.mainPreSlices.index) {
|
|
367
|
-
this.protectedData.previousDrawingImage =
|
|
368
|
-
this.protectedData.ctxes.emptyCtx.createImageData(1, 1);
|
|
369
|
-
currentSliceIndex = this.protectedData.mainPreSlices.index;
|
|
316
|
+
if (this.paintSliceIndex !== this.protectedData.mainPreSlices.index) {
|
|
317
|
+
this.paintSliceIndex = this.protectedData.mainPreSlices.index;
|
|
370
318
|
}
|
|
371
319
|
// remove it when mouse click down
|
|
372
320
|
this.protectedData.canvases.drawingCanvas.removeEventListener("wheel", this.drawingPrameters.handleMouseZoomSliceWheel);
|
|
373
321
|
if (e.button === 0) {
|
|
374
322
|
if (((_a = this.eventRouter) === null || _a === void 0 ? void 0 : _a.getMode()) === 'draw') {
|
|
375
|
-
|
|
376
|
-
lines = [];
|
|
377
|
-
Is_Painting = true;
|
|
378
|
-
this.protectedData.Is_Draw = true;
|
|
379
|
-
if (this.gui_states.Eraser) {
|
|
380
|
-
// this.protectedData.canvases.drawingCanvas.style.cursor =
|
|
381
|
-
// "url(https://raw.githubusercontent.com/LinkunGao/copper3d-datasets/main/icons/eraser/circular-cursor_48.png) 48 48, crosshair";
|
|
382
|
-
this.eraserUrls.length > 0
|
|
383
|
-
? (this.protectedData.canvases.drawingCanvas.style.cursor =
|
|
384
|
-
switchEraserSize(this.gui_states.brushAndEraserSize, this.eraserUrls))
|
|
385
|
-
: (this.protectedData.canvases.drawingCanvas.style.cursor =
|
|
386
|
-
switchEraserSize(this.gui_states.brushAndEraserSize));
|
|
387
|
-
}
|
|
388
|
-
else {
|
|
389
|
-
this.protectedData.canvases.drawingCanvas.style.cursor =
|
|
390
|
-
this.gui_states.defaultPaintCursor;
|
|
391
|
-
}
|
|
392
|
-
this.nrrd_states.drawStartPos.x = e.offsetX;
|
|
393
|
-
this.nrrd_states.drawStartPos.y = e.offsetY;
|
|
394
|
-
// Capture pre-draw slice snapshot for undo
|
|
395
|
-
try {
|
|
396
|
-
this.preDrawAxis = this.protectedData.axis;
|
|
397
|
-
this.preDrawSliceIndex = this.nrrd_states.currentIndex;
|
|
398
|
-
const vol = this.getVolumeForLayer(this.gui_states.layer);
|
|
399
|
-
this.preDrawSlice = vol.getSliceUint8(this.preDrawSliceIndex, this.preDrawAxis).data.slice();
|
|
400
|
-
}
|
|
401
|
-
catch (_e) {
|
|
402
|
-
this.preDrawSlice = null;
|
|
403
|
-
}
|
|
323
|
+
this.drawingTool.onPointerDown(e);
|
|
404
324
|
this.protectedData.canvases.drawingCanvas.addEventListener("pointerup", this.drawingPrameters.handleOnDrawingMouseUp);
|
|
405
325
|
this.protectedData.canvases.drawingCanvas.addEventListener("pointermove", this.drawingPrameters.handleOnDrawingMouseMove);
|
|
406
326
|
}
|
|
407
327
|
else if ((_b = this.eventRouter) === null || _b === void 0 ? void 0 : _b.isCrosshairEnabled()) {
|
|
408
|
-
this.nrrd_states.cursorPageX =
|
|
409
|
-
e.offsetX / this.nrrd_states.
|
|
410
|
-
this.nrrd_states.cursorPageY =
|
|
411
|
-
e.offsetY / this.nrrd_states.
|
|
328
|
+
this.nrrd_states.interaction.cursorPageX =
|
|
329
|
+
e.offsetX / this.nrrd_states.view.sizeFactor;
|
|
330
|
+
this.nrrd_states.interaction.cursorPageY =
|
|
331
|
+
e.offsetY / this.nrrd_states.view.sizeFactor;
|
|
412
332
|
this.enableCrosshair();
|
|
413
333
|
this.protectedData.canvases.drawingCanvas.addEventListener("pointerup", this.drawingPrameters.handleOnDrawingMouseUp);
|
|
414
334
|
}
|
|
415
|
-
else if (this.gui_states.sphere && !((_c = this.eventRouter) === null || _c === void 0 ? void 0 : _c.isCrosshairEnabled())) {
|
|
416
|
-
|
|
417
|
-
}
|
|
418
|
-
else if (this.gui_states.calculator && !((_d = this.eventRouter) === null || _d === void 0 ? void 0 : _d.isCrosshairEnabled())) {
|
|
419
|
-
this.drawCalSphereDown(e.offsetX, e.offsetY, this.nrrd_states.currentIndex, this.gui_states.cal_distance);
|
|
335
|
+
else if (this.gui_states.mode.sphere && !((_c = this.eventRouter) === null || _c === void 0 ? void 0 : _c.isCrosshairEnabled())) {
|
|
336
|
+
this.handleSphereClick(e);
|
|
420
337
|
}
|
|
421
338
|
}
|
|
422
339
|
else if (e.button === 2) {
|
|
423
|
-
|
|
424
|
-
let offsetX = this.protectedData.canvases.drawingCanvas.offsetLeft;
|
|
425
|
-
let offsetY = this.protectedData.canvases.drawingCanvas.offsetTop;
|
|
426
|
-
panelMoveInnerX = e.clientX - offsetX;
|
|
427
|
-
panelMoveInnerY = e.clientY - offsetY;
|
|
428
|
-
this.protectedData.canvases.drawingCanvas.style.cursor = "grab";
|
|
340
|
+
this.panTool.onPointerDown(e);
|
|
429
341
|
this.protectedData.canvases.drawingCanvas.addEventListener("pointerup", this.drawingPrameters.handleOnDrawingMouseUp);
|
|
430
|
-
this.protectedData.canvases.drawingCanvas.addEventListener("pointermove", this.drawingPrameters.handleOnPanMouseMove);
|
|
431
342
|
}
|
|
432
343
|
else {
|
|
433
344
|
return;
|
|
@@ -444,176 +355,65 @@ export class DrawToolCore extends CommToolsData {
|
|
|
444
355
|
// Fallback for legacy mode without EventRouter
|
|
445
356
|
this.protectedData.canvases.drawingCanvas.addEventListener("pointerdown", this.drawingPrameters.handleOnDrawingMouseDown, true);
|
|
446
357
|
}
|
|
447
|
-
const sphere = (e) => {
|
|
448
|
-
// set sphere size
|
|
449
|
-
this.protectedData.canvases.drawingCanvas.removeEventListener("wheel", this.drawingPrameters.handleMouseZoomSliceWheel);
|
|
450
|
-
let mouseX = e.offsetX / this.nrrd_states.sizeFoctor;
|
|
451
|
-
let mouseY = e.offsetY / this.nrrd_states.sizeFoctor;
|
|
452
|
-
// record mouseX,Y, and enable crosshair function
|
|
453
|
-
this.nrrd_states.sphereOrigin[this.protectedData.axis] = [
|
|
454
|
-
mouseX,
|
|
455
|
-
mouseY,
|
|
456
|
-
this.nrrd_states.currentIndex,
|
|
457
|
-
];
|
|
458
|
-
this.setUpSphereOrigins(mouseX, mouseY, this.nrrd_states.currentIndex);
|
|
459
|
-
this.nrrd_states.cursorPageX = mouseX;
|
|
460
|
-
this.nrrd_states.cursorPageY = mouseY;
|
|
461
|
-
this.enableCrosshair();
|
|
462
|
-
// draw circle setup width/height for sphere canvas
|
|
463
|
-
this.drawSphere(mouseX, mouseY, this.nrrd_states.sphereRadius);
|
|
464
|
-
this.protectedData.canvases.drawingCanvas.addEventListener("wheel", this.drawingPrameters.handleSphereWheel, true);
|
|
465
|
-
this.protectedData.canvases.drawingCanvas.addEventListener("pointerup", this.drawingPrameters.handleOnDrawingMouseUp);
|
|
466
|
-
};
|
|
467
|
-
const redrawPreviousImageToLayerCtx = (ctx) => {
|
|
468
|
-
var _a;
|
|
469
|
-
const tempPreImg = (_a = this.filterDrawedImage(this.protectedData.axis, this.nrrd_states.currentIndex)) === null || _a === void 0 ? void 0 : _a.image;
|
|
470
|
-
this.protectedData.canvases.emptyCanvas.width =
|
|
471
|
-
this.protectedData.canvases.emptyCanvas.width;
|
|
472
|
-
if (tempPreImg) {
|
|
473
|
-
this.protectedData.previousDrawingImage = tempPreImg;
|
|
474
|
-
}
|
|
475
|
-
this.protectedData.ctxes.emptyCtx.putImageData(tempPreImg, 0, 0);
|
|
476
|
-
// No flip needed: MaskVolume stores in source coordinates (matching the
|
|
477
|
-
// Three.js / layer canvas convention). The layer canvas is in screen
|
|
478
|
-
// coordinates, which already match the source coordinate system.
|
|
479
|
-
ctx.imageSmoothingEnabled = false;
|
|
480
|
-
ctx.drawImage(this.protectedData.canvases.emptyCanvas, 0, 0, this.nrrd_states.changedWidth, this.nrrd_states.changedHeight);
|
|
481
|
-
};
|
|
482
358
|
this.drawingPrameters.handleOnDrawingMouseUp = (e) => {
|
|
483
|
-
var _a, _b, _c
|
|
359
|
+
var _a, _b, _c;
|
|
484
360
|
if (e.button === 0) {
|
|
485
|
-
if (((_a = this.eventRouter) === null || _a === void 0 ? void 0 : _a.getMode()) === 'draw' ||
|
|
486
|
-
|
|
487
|
-
let { ctx, canvas } = this.setCurrentLayer();
|
|
488
|
-
ctx.closePath();
|
|
361
|
+
if (((_a = this.eventRouter) === null || _a === void 0 ? void 0 : _a.getMode()) === 'draw' || this.drawingTool.painting) {
|
|
362
|
+
this.drawingTool.onPointerUp(e);
|
|
489
363
|
this.protectedData.canvases.drawingCanvas.removeEventListener("pointermove", this.drawingPrameters.handleOnDrawingMouseMove);
|
|
490
|
-
if (!this.gui_states.Eraser) {
|
|
491
|
-
if (this.gui_states.pencil) {
|
|
492
|
-
// Clear only the current layer canvas (NOT master)
|
|
493
|
-
canvas.width = canvas.width;
|
|
494
|
-
// Redraw previous layer data from volume
|
|
495
|
-
redrawPreviousImageToLayerCtx(ctx);
|
|
496
|
-
// Draw new pencil strokes on current layer canvas
|
|
497
|
-
ctx.beginPath();
|
|
498
|
-
ctx.moveTo(lines[0].x, lines[0].y);
|
|
499
|
-
for (let i = 1; i < lines.length; i++) {
|
|
500
|
-
ctx.lineTo(lines[i].x, lines[i].y);
|
|
501
|
-
}
|
|
502
|
-
ctx.closePath();
|
|
503
|
-
ctx.lineWidth = 1;
|
|
504
|
-
ctx.fillStyle = this.gui_states.fillColor;
|
|
505
|
-
ctx.fill();
|
|
506
|
-
// Composite ALL layers to master (not just current layer)
|
|
507
|
-
this.compositeAllLayers();
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
this.protectedData.previousDrawingImage =
|
|
511
|
-
this.protectedData.ctxes.drawingLayerMasterCtx.getImageData(0, 0, this.protectedData.canvases.drawingCanvasLayerMaster.width, this.protectedData.canvases.drawingCanvasLayerMaster.height);
|
|
512
|
-
this.storeAllImages(this.nrrd_states.currentIndex, this.gui_states.layer);
|
|
513
|
-
if (this.gui_states.Eraser) {
|
|
514
|
-
const restLayers = this.getRestLayer();
|
|
515
|
-
this.storeEachLayerImage(this.nrrd_states.currentIndex, restLayers[0]);
|
|
516
|
-
this.storeEachLayerImage(this.nrrd_states.currentIndex, restLayers[1]);
|
|
517
|
-
}
|
|
518
|
-
Is_Painting = false;
|
|
519
|
-
// Push delta to UndoManager (new Delta-based undo system)
|
|
520
|
-
if (this.preDrawSlice) {
|
|
521
|
-
try {
|
|
522
|
-
const vol = this.getVolumeForLayer(this.gui_states.layer);
|
|
523
|
-
const { data: newSlice } = vol.getSliceUint8(this.preDrawSliceIndex, this.preDrawAxis);
|
|
524
|
-
const delta = {
|
|
525
|
-
layerId: this.gui_states.layer,
|
|
526
|
-
axis: this.preDrawAxis,
|
|
527
|
-
sliceIndex: this.preDrawSliceIndex,
|
|
528
|
-
oldSlice: this.preDrawSlice,
|
|
529
|
-
newSlice: newSlice.slice(),
|
|
530
|
-
};
|
|
531
|
-
this.undoManager.push(delta);
|
|
532
|
-
}
|
|
533
|
-
catch (_e) {
|
|
534
|
-
// Volume not ready — skip
|
|
535
|
-
}
|
|
536
|
-
this.preDrawSlice = null;
|
|
537
|
-
}
|
|
538
364
|
// add wheel after pointer up
|
|
539
365
|
this.protectedData.canvases.drawingCanvas.addEventListener("wheel", this.drawingPrameters.handleMouseZoomSliceWheel, {
|
|
540
366
|
passive: false,
|
|
541
367
|
});
|
|
542
368
|
}
|
|
543
|
-
else if (this.gui_states.sphere &&
|
|
369
|
+
else if (this.gui_states.mode.sphere &&
|
|
544
370
|
!((_b = this.eventRouter) === null || _b === void 0 ? void 0 : _b.isCrosshairEnabled())) {
|
|
545
|
-
//
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
for (let i = 0; i < this.nrrd_states.sphereRadius; i++) {
|
|
552
|
-
this.drawSphereOnEachViews(i, "x");
|
|
553
|
-
this.drawSphereOnEachViews(i, "y");
|
|
554
|
-
this.drawSphereOnEachViews(i, "z");
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
!!this.nrrd_states.getSphere &&
|
|
558
|
-
this.nrrd_states.getSphere(this.nrrd_states.sphereOrigin.z, this.nrrd_states.sphereRadius / this.nrrd_states.sizeFoctor);
|
|
371
|
+
// Write all placed calculator spheres to volume
|
|
372
|
+
this.sphereTool.writeAllCalculatorSpheresToVolume();
|
|
373
|
+
// Render current slice from volume to sphere canvas
|
|
374
|
+
this.sphereTool.refreshSphereCanvas();
|
|
375
|
+
this.annotationCallbacks.onSphereChanged(this.nrrd_states.sphere.sphereOrigin.z, this.nrrd_states.sphere.sphereRadius / this.nrrd_states.view.sizeFactor);
|
|
376
|
+
this.annotationCallbacks.onCalculatorPositionsChanged(this.nrrd_states.sphere.tumourSphereOrigin, this.nrrd_states.sphere.skinSphereOrigin, this.nrrd_states.sphere.ribSphereOrigin, this.nrrd_states.sphere.nippleSphereOrigin, this.protectedData.axis);
|
|
559
377
|
this.protectedData.canvases.drawingCanvas.removeEventListener("wheel", this.drawingPrameters.handleSphereWheel, true);
|
|
560
378
|
this.protectedData.canvases.drawingCanvas.addEventListener("wheel", this.drawingPrameters.handleMouseZoomSliceWheel);
|
|
561
379
|
this.protectedData.canvases.drawingCanvas.removeEventListener("pointerup", this.drawingPrameters.handleOnDrawingMouseUp);
|
|
380
|
+
this.zoomActionAfterDrawSphere();
|
|
562
381
|
}
|
|
563
|
-
else if (
|
|
382
|
+
else if (this.gui_states.mode.sphere &&
|
|
564
383
|
((_c = this.eventRouter) === null || _c === void 0 ? void 0 : _c.isCrosshairEnabled())) {
|
|
565
384
|
this.protectedData.canvases.drawingCanvas.addEventListener("wheel", this.drawingPrameters.handleMouseZoomSliceWheel);
|
|
566
385
|
this.protectedData.canvases.drawingCanvas.removeEventListener("pointerup", this.drawingPrameters.handleOnDrawingMouseUp);
|
|
567
386
|
}
|
|
568
|
-
else if (this.gui_states.calculator &&
|
|
569
|
-
!((_d = this.eventRouter) === null || _d === void 0 ? void 0 : _d.isCrosshairEnabled())) {
|
|
570
|
-
// When mouse up
|
|
571
|
-
this.drawCalSphereUp();
|
|
572
|
-
}
|
|
573
387
|
}
|
|
574
388
|
else if (e.button === 2) {
|
|
575
|
-
|
|
576
|
-
this.protectedData.canvases.drawingCanvas.style.cursor = "grab";
|
|
577
|
-
setTimeout(() => {
|
|
578
|
-
this.protectedData.canvases.drawingCanvas.style.cursor = this.gui_states.defaultPaintCursor;
|
|
579
|
-
}, 2000);
|
|
580
|
-
this.protectedData.canvases.drawingCanvas.removeEventListener("pointermove", this.drawingPrameters.handleOnPanMouseMove);
|
|
581
|
-
if (this.gui_states.sphere || this.gui_states.calculator) {
|
|
582
|
-
this.zoomActionAfterDrawSphere();
|
|
583
|
-
}
|
|
389
|
+
this.panTool.onPointerUp(e, this.gui_states.viewConfig.defaultPaintCursor);
|
|
584
390
|
}
|
|
585
391
|
else {
|
|
586
392
|
return;
|
|
587
393
|
}
|
|
588
|
-
if (!this.gui_states.pencil) {
|
|
394
|
+
if (!this.gui_states.mode.pencil) {
|
|
589
395
|
this.setIsDrawFalse(100);
|
|
590
396
|
}
|
|
591
397
|
};
|
|
592
|
-
this.protectedData.canvases.drawingCanvas.addEventListener("pointerleave", (
|
|
593
|
-
|
|
594
|
-
if (
|
|
595
|
-
leftclicked = false;
|
|
596
|
-
this.protectedData.ctxes.drawingLayerMasterCtx.closePath();
|
|
398
|
+
this.protectedData.canvases.drawingCanvas.addEventListener("pointerleave", () => {
|
|
399
|
+
const wasDrawing = this.drawingTool.onPointerLeave();
|
|
400
|
+
if (wasDrawing) {
|
|
597
401
|
this.protectedData.canvases.drawingCanvas.removeEventListener("pointermove", this.drawingPrameters.handleOnDrawingMouseMove);
|
|
598
402
|
this.protectedData.canvases.drawingCanvas.removeEventListener("wheel", this.drawingPrameters.handleSphereWheel, true);
|
|
599
403
|
}
|
|
600
|
-
|
|
601
|
-
rightclicked = false;
|
|
602
|
-
this.protectedData.canvases.drawingCanvas.style.cursor = "grab";
|
|
603
|
-
this.protectedData.canvases.drawingCanvas.removeEventListener("pointermove", this.drawingPrameters.handleOnPanMouseMove);
|
|
604
|
-
}
|
|
404
|
+
this.panTool.onPointerLeave();
|
|
605
405
|
this.setIsDrawFalse(100);
|
|
606
|
-
if (this.gui_states.pencil) {
|
|
406
|
+
if (this.gui_states.mode.pencil) {
|
|
607
407
|
this.setIsDrawFalse(1000);
|
|
608
408
|
}
|
|
609
409
|
});
|
|
610
410
|
this.start = () => {
|
|
611
411
|
var _a, _b;
|
|
612
|
-
if (this.gui_states.readyToUpdate) {
|
|
613
|
-
this.protectedData.ctxes.drawingCtx.clearRect(0, 0, this.nrrd_states.changedWidth, this.nrrd_states.changedHeight);
|
|
412
|
+
if (this.gui_states.viewConfig.readyToUpdate) {
|
|
413
|
+
this.protectedData.ctxes.drawingCtx.clearRect(0, 0, this.nrrd_states.view.changedWidth, this.nrrd_states.view.changedHeight);
|
|
614
414
|
this.protectedData.ctxes.drawingCtx.globalAlpha =
|
|
615
|
-
this.gui_states.globalAlpha;
|
|
616
|
-
if (this.protectedData.
|
|
415
|
+
this.gui_states.drawing.globalAlpha;
|
|
416
|
+
if (this.protectedData.isDrawing) {
|
|
617
417
|
this.protectedData.ctxes.drawingLayerMasterCtx.lineCap = "round";
|
|
618
418
|
this.protectedData.ctxes.drawingLayerMasterCtx.globalAlpha = 1;
|
|
619
419
|
for (const [, target] of this.protectedData.layerTargets) {
|
|
@@ -626,63 +426,78 @@ export class DrawToolCore extends CommToolsData {
|
|
|
626
426
|
const currentMode = (_a = this.eventRouter) === null || _a === void 0 ? void 0 : _a.getMode();
|
|
627
427
|
if (currentMode === 'draw') {
|
|
628
428
|
// Draw mode: show brush circle preview
|
|
629
|
-
if (!this.gui_states.pencil &&
|
|
630
|
-
!this.gui_states.
|
|
631
|
-
this.nrrd_states.
|
|
632
|
-
this.protectedData.ctxes.drawingCtx.clearRect(0, 0, this.nrrd_states.changedWidth, this.nrrd_states.changedHeight);
|
|
429
|
+
if (!this.gui_states.mode.pencil &&
|
|
430
|
+
!this.gui_states.mode.eraser &&
|
|
431
|
+
this.nrrd_states.interaction.mouseOver) {
|
|
432
|
+
this.protectedData.ctxes.drawingCtx.clearRect(0, 0, this.nrrd_states.view.changedWidth, this.nrrd_states.view.changedHeight);
|
|
633
433
|
this.protectedData.ctxes.drawingCtx.fillStyle =
|
|
634
|
-
this.gui_states.brushColor;
|
|
434
|
+
this.gui_states.drawing.brushColor;
|
|
635
435
|
this.protectedData.ctxes.drawingCtx.beginPath();
|
|
636
|
-
this.protectedData.ctxes.drawingCtx.arc(this.nrrd_states.
|
|
436
|
+
this.protectedData.ctxes.drawingCtx.arc(this.nrrd_states.interaction.mouseOverX, this.nrrd_states.interaction.mouseOverY, this.gui_states.drawing.brushAndEraserSize / 2 + 1, 0, Math.PI * 2);
|
|
637
437
|
this.protectedData.ctxes.drawingCtx.strokeStyle =
|
|
638
|
-
this.gui_states.brushColor;
|
|
438
|
+
this.gui_states.drawing.brushColor;
|
|
639
439
|
this.protectedData.ctxes.drawingCtx.stroke();
|
|
640
440
|
}
|
|
641
441
|
}
|
|
642
442
|
else if (currentMode === 'crosshair' || ((_b = this.eventRouter) === null || _b === void 0 ? void 0 : _b.isCrosshairEnabled())) {
|
|
643
443
|
// Crosshair mode: show red cross lines (mutually exclusive with draw)
|
|
644
|
-
this.protectedData.ctxes.drawingCtx.clearRect(0, 0, this.nrrd_states.changedWidth, this.nrrd_states.changedHeight);
|
|
645
|
-
const ex = this.nrrd_states.cursorPageX * this.nrrd_states.
|
|
646
|
-
const ey = this.nrrd_states.cursorPageY * this.nrrd_states.
|
|
647
|
-
this.drawLine(ex, 0, ex, this.nrrd_states.changedWidth);
|
|
648
|
-
this.drawLine(0, ey, this.nrrd_states.changedHeight, ey);
|
|
444
|
+
this.protectedData.ctxes.drawingCtx.clearRect(0, 0, this.nrrd_states.view.changedWidth, this.nrrd_states.view.changedHeight);
|
|
445
|
+
const ex = this.nrrd_states.interaction.cursorPageX * this.nrrd_states.view.sizeFactor;
|
|
446
|
+
const ey = this.nrrd_states.interaction.cursorPageY * this.nrrd_states.view.sizeFactor;
|
|
447
|
+
this.drawLine(ex, 0, ex, this.nrrd_states.view.changedWidth);
|
|
448
|
+
this.drawLine(0, ey, this.nrrd_states.view.changedHeight, ey);
|
|
649
449
|
}
|
|
650
450
|
}
|
|
651
|
-
// globalAlpha was set to gui_states.globalAlpha at the top of start().
|
|
451
|
+
// globalAlpha was set to gui_states.drawing.globalAlpha at the top of start().
|
|
652
452
|
// Master stores full-alpha pixels; transparency applied here only.
|
|
653
453
|
this.protectedData.ctxes.drawingCtx.drawImage(this.protectedData.canvases.drawingCanvasLayerMaster, 0, 0);
|
|
454
|
+
// Draw sphere overlay from cached sphere canvas (separate from master).
|
|
455
|
+
// During preview: drawSphere/drawCalculatorSphere update the sphere canvas.
|
|
456
|
+
// After placement: refreshSphereCanvas renders from sphereMaskVolume.
|
|
457
|
+
if (this.gui_states.mode.sphere) {
|
|
458
|
+
this.protectedData.ctxes.drawingCtx.drawImage(this.protectedData.canvases.drawingSphereCanvas, 0, 0, this.nrrd_states.view.changedWidth, this.nrrd_states.view.changedHeight);
|
|
459
|
+
}
|
|
654
460
|
}
|
|
655
461
|
else {
|
|
656
462
|
this.redrawDisplayCanvas();
|
|
657
463
|
}
|
|
658
464
|
};
|
|
659
465
|
}
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
466
|
+
/** Extracted from paintOnCanvas() — handles sphere placement on left-click */
|
|
467
|
+
handleSphereClick(e) {
|
|
468
|
+
this.protectedData.canvases.drawingCanvas.removeEventListener("wheel", this.drawingPrameters.handleMouseZoomSliceWheel);
|
|
469
|
+
let mouseX = e.offsetX / this.nrrd_states.view.sizeFactor;
|
|
470
|
+
let mouseY = e.offsetY / this.nrrd_states.view.sizeFactor;
|
|
471
|
+
// record mouseX,Y, and enable crosshair function
|
|
472
|
+
this.nrrd_states.sphere.sphereOrigin[this.protectedData.axis] = [
|
|
473
|
+
mouseX,
|
|
474
|
+
mouseY,
|
|
475
|
+
this.nrrd_states.view.currentSliceIndex,
|
|
476
|
+
];
|
|
477
|
+
this.setUpSphereOrigins(mouseX, mouseY, this.nrrd_states.view.currentSliceIndex);
|
|
478
|
+
// Store origin for the active sphere type
|
|
479
|
+
const calPos = this.gui_states.mode.activeSphereType;
|
|
480
|
+
switch (calPos) {
|
|
481
|
+
case "tumour":
|
|
482
|
+
this.nrrd_states.sphere.tumourSphereOrigin = JSON.parse(JSON.stringify(this.nrrd_states.sphere.sphereOrigin));
|
|
483
|
+
break;
|
|
484
|
+
case "skin":
|
|
485
|
+
this.nrrd_states.sphere.skinSphereOrigin = JSON.parse(JSON.stringify(this.nrrd_states.sphere.sphereOrigin));
|
|
486
|
+
break;
|
|
487
|
+
case "nipple":
|
|
488
|
+
this.nrrd_states.sphere.nippleSphereOrigin = JSON.parse(JSON.stringify(this.nrrd_states.sphere.sphereOrigin));
|
|
489
|
+
break;
|
|
490
|
+
case "ribcage":
|
|
491
|
+
this.nrrd_states.sphere.ribSphereOrigin = JSON.parse(JSON.stringify(this.nrrd_states.sphere.sphereOrigin));
|
|
492
|
+
break;
|
|
670
493
|
}
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
this.drawLinesOnLayer(ctx, x, y);
|
|
679
|
-
// Composite all layers to master to preserve other layers' data
|
|
680
|
-
this.compositeAllLayers();
|
|
681
|
-
// reset drawing start position to current position.
|
|
682
|
-
this.nrrd_states.drawStartPos.x = x;
|
|
683
|
-
this.nrrd_states.drawStartPos.y = y;
|
|
684
|
-
// need to flag the map as needing updating.
|
|
685
|
-
this.protectedData.mainPreSlices.mesh.material.map.needsUpdate = true;
|
|
494
|
+
this.nrrd_states.interaction.cursorPageX = mouseX;
|
|
495
|
+
this.nrrd_states.interaction.cursorPageY = mouseY;
|
|
496
|
+
this.enableCrosshair();
|
|
497
|
+
// draw circle setup width/height for sphere canvas
|
|
498
|
+
this.drawCalculatorSphere(this.nrrd_states.sphere.sphereRadius);
|
|
499
|
+
this.protectedData.canvases.drawingCanvas.addEventListener("wheel", this.drawingPrameters.handleSphereWheel, true);
|
|
500
|
+
this.protectedData.canvases.drawingCanvas.addEventListener("pointerup", this.drawingPrameters.handleOnDrawingMouseUp);
|
|
686
501
|
}
|
|
687
502
|
initAllCanvas() {
|
|
688
503
|
/**
|
|
@@ -691,42 +506,42 @@ export class DrawToolCore extends CommToolsData {
|
|
|
691
506
|
this.protectedData.canvases.displayCanvas.style.position = "absolute";
|
|
692
507
|
this.protectedData.canvases.displayCanvas.style.zIndex = "9";
|
|
693
508
|
this.protectedData.canvases.displayCanvas.width =
|
|
694
|
-
this.nrrd_states.changedWidth;
|
|
509
|
+
this.nrrd_states.view.changedWidth;
|
|
695
510
|
this.protectedData.canvases.displayCanvas.height =
|
|
696
|
-
this.nrrd_states.changedHeight;
|
|
511
|
+
this.nrrd_states.view.changedHeight;
|
|
697
512
|
/**
|
|
698
513
|
* drawing canvas
|
|
699
514
|
*/
|
|
700
515
|
this.protectedData.canvases.drawingCanvas.style.zIndex = "10";
|
|
701
516
|
this.protectedData.canvases.drawingCanvas.style.position = "absolute";
|
|
702
517
|
this.protectedData.canvases.drawingCanvas.width =
|
|
703
|
-
this.nrrd_states.changedWidth;
|
|
518
|
+
this.nrrd_states.view.changedWidth;
|
|
704
519
|
this.protectedData.canvases.drawingCanvas.height =
|
|
705
|
-
this.nrrd_states.changedHeight;
|
|
520
|
+
this.nrrd_states.view.changedHeight;
|
|
706
521
|
this.protectedData.canvases.drawingCanvas.style.cursor =
|
|
707
|
-
this.gui_states.defaultPaintCursor;
|
|
522
|
+
this.gui_states.viewConfig.defaultPaintCursor;
|
|
708
523
|
this.protectedData.canvases.drawingCanvas.oncontextmenu = () => false;
|
|
709
524
|
/**
|
|
710
525
|
* layer1
|
|
711
526
|
* it should be hide, so we don't need to add it to mainAreaContainer
|
|
712
527
|
*/
|
|
713
528
|
this.protectedData.canvases.drawingCanvasLayerMaster.width =
|
|
714
|
-
this.nrrd_states.changedWidth;
|
|
529
|
+
this.nrrd_states.view.changedWidth;
|
|
715
530
|
this.protectedData.canvases.drawingCanvasLayerMaster.height =
|
|
716
|
-
this.nrrd_states.changedHeight;
|
|
531
|
+
this.nrrd_states.view.changedHeight;
|
|
717
532
|
for (const [, target] of this.protectedData.layerTargets) {
|
|
718
|
-
target.canvas.width = this.nrrd_states.changedWidth;
|
|
719
|
-
target.canvas.height = this.nrrd_states.changedHeight;
|
|
533
|
+
target.canvas.width = this.nrrd_states.view.changedWidth;
|
|
534
|
+
target.canvas.height = this.nrrd_states.view.changedHeight;
|
|
720
535
|
}
|
|
721
536
|
/**
|
|
722
537
|
* display and drawing canvas container
|
|
723
538
|
*/
|
|
724
|
-
// this.mainAreaContainer.style.width = this.nrrd_states.changedWidth + "px";
|
|
725
|
-
// this.mainAreaContainer.style.height = this.nrrd_states.changedHeight + "px";
|
|
539
|
+
// this.mainAreaContainer.style.width = this.nrrd_states.view.changedWidth + "px";
|
|
540
|
+
// this.mainAreaContainer.style.height = this.nrrd_states.view.changedHeight + "px";
|
|
726
541
|
this.mainAreaContainer.style.width =
|
|
727
|
-
this.nrrd_states.originWidth * 8 + "px";
|
|
542
|
+
this.nrrd_states.image.originWidth * 8 + "px";
|
|
728
543
|
this.mainAreaContainer.style.height =
|
|
729
|
-
this.nrrd_states.originHeight * 8 + "px";
|
|
544
|
+
this.nrrd_states.image.originHeight * 8 + "px";
|
|
730
545
|
this.mainAreaContainer.appendChild(this.protectedData.canvases.displayCanvas);
|
|
731
546
|
this.mainAreaContainer.appendChild(this.protectedData.canvases.drawingCanvas);
|
|
732
547
|
}
|
|
@@ -774,6 +589,15 @@ export class DrawToolCore extends CommToolsData {
|
|
|
774
589
|
drawSphere(mouseX, mouseY, radius) {
|
|
775
590
|
this.sphereTool.drawSphere(mouseX, mouseY, radius);
|
|
776
591
|
}
|
|
592
|
+
/**
|
|
593
|
+
* Refresh sphere canvas from sphereMaskVolume for the current slice/axis.
|
|
594
|
+
* Called after view changes (slice switch, zoom, contrast, axis switch).
|
|
595
|
+
*/
|
|
596
|
+
refreshSphereOverlay() {
|
|
597
|
+
if (this.gui_states.mode.sphere) {
|
|
598
|
+
this.sphereTool.refreshSphereCanvas();
|
|
599
|
+
}
|
|
600
|
+
}
|
|
777
601
|
/**
|
|
778
602
|
* Convert cursor point between axis views.
|
|
779
603
|
* Delegated to CrosshairTool.
|
|
@@ -786,32 +610,34 @@ export class DrawToolCore extends CommToolsData {
|
|
|
786
610
|
}
|
|
787
611
|
/****************************layer div controls****************************************************/
|
|
788
612
|
getRestLayer() {
|
|
789
|
-
const layers = this.nrrd_states.layers;
|
|
613
|
+
const layers = this.nrrd_states.image.layers;
|
|
790
614
|
const restLayer = layers.filter((item) => {
|
|
791
|
-
return item !== this.gui_states.layer;
|
|
615
|
+
return item !== this.gui_states.layerChannel.layer;
|
|
792
616
|
});
|
|
793
617
|
return restLayer;
|
|
794
618
|
}
|
|
795
619
|
/**************************** Undo/Redo functions (Phase 6 — Delta-based) ****************************/
|
|
796
620
|
/**
|
|
797
|
-
* Clear mask on current slice canvas.
|
|
621
|
+
* Clear the mask on the current slice canvas for the active layer ONLY.
|
|
622
|
+
*
|
|
623
|
+
* This method only clears the active layer's MaskVolume slice data for the
|
|
624
|
+
* currently viewed slice index. Other slices in the same layer remain intact.
|
|
625
|
+
* Other background layers are also left untouched.
|
|
626
|
+
* After clearing, all layer canvases are re-rendered from the `MaskVolume`
|
|
627
|
+
* to keep the visuals in sync.
|
|
798
628
|
*
|
|
799
|
-
*
|
|
800
|
-
* Other layers are left untouched. After clearing, all layer canvases
|
|
801
|
-
* are re-rendered from MaskVolume to keep visuals in sync.
|
|
629
|
+
* The operation is recorded to the UndoManager to allow for user rollback.
|
|
802
630
|
*/
|
|
803
|
-
|
|
804
|
-
this.protectedData.
|
|
631
|
+
clearActiveSlice() {
|
|
632
|
+
this.protectedData.isDrawing = true;
|
|
805
633
|
this.protectedData.canvases.originCanvas.width =
|
|
806
634
|
this.protectedData.canvases.originCanvas.width;
|
|
807
635
|
this.protectedData.mainPreSlices.repaint.call(this.protectedData.mainPreSlices);
|
|
808
|
-
this.protectedData.previousDrawingImage =
|
|
809
|
-
this.protectedData.ctxes.emptyCtx.createImageData(1, 1);
|
|
810
636
|
// Clear only the active layer's MaskVolume slice and record undo delta
|
|
811
637
|
try {
|
|
812
638
|
const axis = this.protectedData.axis;
|
|
813
|
-
const idx = this.nrrd_states.
|
|
814
|
-
const activeLayer = this.gui_states.layer;
|
|
639
|
+
const idx = this.nrrd_states.view.currentSliceIndex;
|
|
640
|
+
const activeLayer = this.gui_states.layerChannel.layer;
|
|
815
641
|
const vol = this.getVolumeForLayer(activeLayer);
|
|
816
642
|
// Capture old slice for undo before clearing
|
|
817
643
|
const oldSlice = vol.getSliceUint8(idx, axis).data.slice();
|
|
@@ -819,7 +645,7 @@ export class DrawToolCore extends CommToolsData {
|
|
|
819
645
|
vol.clearSlice(idx, axis);
|
|
820
646
|
// New (all-zero) slice for undo newSlice
|
|
821
647
|
const { data: newSlice, width, height } = vol.getSliceUint8(idx, axis);
|
|
822
|
-
// Push
|
|
648
|
+
// Push clearActiveSlice delta to UndoManager (supports undo)
|
|
823
649
|
this.undoManager.push({
|
|
824
650
|
layerId: activeLayer,
|
|
825
651
|
axis,
|
|
@@ -828,9 +654,9 @@ export class DrawToolCore extends CommToolsData {
|
|
|
828
654
|
newSlice: newSlice.slice(),
|
|
829
655
|
});
|
|
830
656
|
// Notify external that slice was cleared
|
|
831
|
-
if (!this.nrrd_states.
|
|
832
|
-
const activeChannel = this.gui_states.activeChannel || 1;
|
|
833
|
-
this.
|
|
657
|
+
if (!this.nrrd_states.flags.loadingMaskData && !this.gui_states.mode.sphere) {
|
|
658
|
+
const activeChannel = this.gui_states.layerChannel.activeChannel || 1;
|
|
659
|
+
this.annotationCallbacks.onMaskChanged(newSlice, activeLayer, activeChannel, idx, axis, width, height, true // clearFlag = true
|
|
834
660
|
);
|
|
835
661
|
}
|
|
836
662
|
}
|
|
@@ -841,14 +667,14 @@ export class DrawToolCore extends CommToolsData {
|
|
|
841
667
|
this.resetLayerCanvas();
|
|
842
668
|
const buffer = this.getOrCreateSliceBuffer(this.protectedData.axis);
|
|
843
669
|
if (buffer) {
|
|
844
|
-
const w = this.nrrd_states.changedWidth;
|
|
845
|
-
const h = this.nrrd_states.changedHeight;
|
|
846
|
-
for (const layerId of this.nrrd_states.layers) {
|
|
670
|
+
const w = this.nrrd_states.view.changedWidth;
|
|
671
|
+
const h = this.nrrd_states.view.changedHeight;
|
|
672
|
+
for (const layerId of this.nrrd_states.image.layers) {
|
|
847
673
|
const target = this.protectedData.layerTargets.get(layerId);
|
|
848
674
|
if (!target)
|
|
849
675
|
continue;
|
|
850
676
|
target.ctx.clearRect(0, 0, w, h);
|
|
851
|
-
this.renderSliceToCanvas(layerId, this.protectedData.axis, this.nrrd_states.
|
|
677
|
+
this.renderSliceToCanvas(layerId, this.protectedData.axis, this.nrrd_states.view.currentSliceIndex, buffer, target.ctx, w, h);
|
|
852
678
|
}
|
|
853
679
|
}
|
|
854
680
|
this.compositeAllLayers();
|
|
@@ -870,14 +696,14 @@ export class DrawToolCore extends CommToolsData {
|
|
|
870
696
|
catch (_a) {
|
|
871
697
|
return; // Volume not ready
|
|
872
698
|
}
|
|
873
|
-
this.protectedData.
|
|
874
|
-
if (delta.axis === this.protectedData.axis && delta.sliceIndex === this.nrrd_states.
|
|
699
|
+
this.protectedData.isDrawing = true;
|
|
700
|
+
if (delta.axis === this.protectedData.axis && delta.sliceIndex === this.nrrd_states.view.currentSliceIndex) {
|
|
875
701
|
this.applyUndoRedoToCanvas(delta.layerId);
|
|
876
702
|
}
|
|
877
|
-
if (!this.nrrd_states.
|
|
703
|
+
if (!this.nrrd_states.flags.loadingMaskData) {
|
|
878
704
|
const { data: sliceData, width, height } = this.getVolumeForLayer(delta.layerId)
|
|
879
705
|
.getSliceUint8(delta.sliceIndex, delta.axis);
|
|
880
|
-
this.
|
|
706
|
+
this.annotationCallbacks.onMaskChanged(sliceData, delta.layerId, this.gui_states.layerChannel.activeChannel || 1, delta.sliceIndex, delta.axis, width, height, false);
|
|
881
707
|
}
|
|
882
708
|
this.setIsDrawFalse(1000);
|
|
883
709
|
}
|
|
@@ -897,14 +723,14 @@ export class DrawToolCore extends CommToolsData {
|
|
|
897
723
|
catch (_a) {
|
|
898
724
|
return; // Volume not ready
|
|
899
725
|
}
|
|
900
|
-
this.protectedData.
|
|
901
|
-
if (delta.axis === this.protectedData.axis && delta.sliceIndex === this.nrrd_states.
|
|
726
|
+
this.protectedData.isDrawing = true;
|
|
727
|
+
if (delta.axis === this.protectedData.axis && delta.sliceIndex === this.nrrd_states.view.currentSliceIndex) {
|
|
902
728
|
this.applyUndoRedoToCanvas(delta.layerId);
|
|
903
729
|
}
|
|
904
|
-
if (!this.nrrd_states.
|
|
730
|
+
if (!this.nrrd_states.flags.loadingMaskData) {
|
|
905
731
|
const { data: sliceData, width, height } = this.getVolumeForLayer(delta.layerId)
|
|
906
732
|
.getSliceUint8(delta.sliceIndex, delta.axis);
|
|
907
|
-
this.
|
|
733
|
+
this.annotationCallbacks.onMaskChanged(sliceData, delta.layerId, this.gui_states.layerChannel.activeChannel || 1, delta.sliceIndex, delta.axis, width, height, false);
|
|
908
734
|
}
|
|
909
735
|
this.setIsDrawFalse(1000);
|
|
910
736
|
}
|
|
@@ -915,7 +741,7 @@ export class DrawToolCore extends CommToolsData {
|
|
|
915
741
|
applyUndoRedoToCanvas(layerId) {
|
|
916
742
|
let target = this.protectedData.layerTargets.get(layerId);
|
|
917
743
|
if (!target) {
|
|
918
|
-
const firstId = this.nrrd_states.layers[0];
|
|
744
|
+
const firstId = this.nrrd_states.image.layers[0];
|
|
919
745
|
target = this.protectedData.layerTargets.get(firstId);
|
|
920
746
|
}
|
|
921
747
|
const { ctx, canvas } = target;
|
|
@@ -923,23 +749,14 @@ export class DrawToolCore extends CommToolsData {
|
|
|
923
749
|
canvas.width = canvas.width;
|
|
924
750
|
const buffer = this.getOrCreateSliceBuffer(this.protectedData.axis);
|
|
925
751
|
if (buffer) {
|
|
926
|
-
this.renderSliceToCanvas(layerId, this.protectedData.axis, this.nrrd_states.
|
|
752
|
+
this.renderSliceToCanvas(layerId, this.protectedData.axis, this.nrrd_states.view.currentSliceIndex, buffer, ctx, this.nrrd_states.view.changedWidth, this.nrrd_states.view.changedHeight);
|
|
927
753
|
}
|
|
928
754
|
// Re-composite all layers to master
|
|
929
755
|
this.compositeAllLayers();
|
|
930
|
-
// Update previousDrawingImage from master
|
|
931
|
-
this.protectedData.previousDrawingImage =
|
|
932
|
-
this.protectedData.ctxes.drawingLayerMasterCtx.getImageData(0, 0, this.protectedData.canvases.drawingCanvasLayerMaster.width, this.protectedData.canvases.drawingCanvasLayerMaster.height);
|
|
933
756
|
}
|
|
934
757
|
/****************************Store images (delegated to ImageStoreHelper)****************************************************/
|
|
935
|
-
|
|
936
|
-
this.imageStoreHelper.
|
|
937
|
-
}
|
|
938
|
-
storeImageToLayer(index, canvas) {
|
|
939
|
-
return this.imageStoreHelper.storeImageToLayer(index, canvas);
|
|
940
|
-
}
|
|
941
|
-
storeEachLayerImage(index, layer) {
|
|
942
|
-
this.imageStoreHelper.storeEachLayerImage(index, layer);
|
|
758
|
+
syncLayerSliceData(index, layer) {
|
|
759
|
+
this.imageStoreHelper.syncLayerSliceData(index, layer);
|
|
943
760
|
}
|
|
944
761
|
/******************************** Utils gui related functions (delegated to ContrastTool) ***************************************/
|
|
945
762
|
setupConrastEvents(callback) {
|