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
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DrawingTool - Pencil/Brush/Eraser drawing on canvas layers
|
|
3
|
+
*
|
|
4
|
+
* Extracted from DrawToolCore.paintOnCanvas() closure (Phase 3).
|
|
5
|
+
* Handles left-click drawing operations: pencil stroke + fill, brush strokes,
|
|
6
|
+
* eraser, and undo snapshot capture/push.
|
|
7
|
+
*/
|
|
8
|
+
import { BaseTool } from "./BaseTool";
|
|
9
|
+
import { switchEraserSize } from "../../utils";
|
|
10
|
+
export class DrawingTool extends BaseTool {
|
|
11
|
+
constructor(ctx, callbacks) {
|
|
12
|
+
super(ctx);
|
|
13
|
+
/** Left mouse button currently held (draw mode) */
|
|
14
|
+
this.leftClicked = false;
|
|
15
|
+
/** True while actively painting (between pointerdown and pointerup) */
|
|
16
|
+
this.isPainting = false;
|
|
17
|
+
/** Accumulated pencil stroke points for fill-on-release */
|
|
18
|
+
this.drawingLines = [];
|
|
19
|
+
/** Eraser arc function, assigned once per paintOnCanvas() call */
|
|
20
|
+
this.clearArcFn = null;
|
|
21
|
+
/** Snapshot of the active layer's slice captured on mouse-down (before drawing) */
|
|
22
|
+
this.preDrawSlice = null;
|
|
23
|
+
this.preDrawAxis = "z";
|
|
24
|
+
this.preDrawSliceIndex = 0;
|
|
25
|
+
this.callbacks = callbacks;
|
|
26
|
+
}
|
|
27
|
+
/** Whether a draw operation is currently active */
|
|
28
|
+
get isActive() {
|
|
29
|
+
return this.leftClicked;
|
|
30
|
+
}
|
|
31
|
+
/** Whether paint strokes are being recorded */
|
|
32
|
+
get painting() {
|
|
33
|
+
return this.isPainting;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Reset drawing state. Called at start of each paintOnCanvas() cycle.
|
|
37
|
+
* @param clearArcFn - Eraser function for this paint cycle
|
|
38
|
+
*/
|
|
39
|
+
reset(clearArcFn) {
|
|
40
|
+
this.leftClicked = false;
|
|
41
|
+
this.isPainting = false;
|
|
42
|
+
this.drawingLines = [];
|
|
43
|
+
this.clearArcFn = clearArcFn;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Called on left-click pointerdown in draw mode.
|
|
47
|
+
* Sets up drawing state, cursor, undo snapshot, and start position.
|
|
48
|
+
*/
|
|
49
|
+
onPointerDown(e) {
|
|
50
|
+
this.leftClicked = true;
|
|
51
|
+
this.drawingLines = [];
|
|
52
|
+
this.isPainting = true;
|
|
53
|
+
this.ctx.protectedData.isDrawing = true;
|
|
54
|
+
// Set cursor based on mode
|
|
55
|
+
if (this.ctx.gui_states.mode.eraser) {
|
|
56
|
+
const urls = this.callbacks.getEraserUrls();
|
|
57
|
+
this.ctx.protectedData.canvases.drawingCanvas.style.cursor =
|
|
58
|
+
urls.length > 0
|
|
59
|
+
? switchEraserSize(this.ctx.gui_states.drawing.brushAndEraserSize, urls)
|
|
60
|
+
: switchEraserSize(this.ctx.gui_states.drawing.brushAndEraserSize);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
this.ctx.protectedData.canvases.drawingCanvas.style.cursor =
|
|
64
|
+
this.ctx.gui_states.viewConfig.defaultPaintCursor;
|
|
65
|
+
}
|
|
66
|
+
// Record draw start position
|
|
67
|
+
this.ctx.nrrd_states.interaction.drawStartPos.x = e.offsetX;
|
|
68
|
+
this.ctx.nrrd_states.interaction.drawStartPos.y = e.offsetY;
|
|
69
|
+
// Capture pre-draw slice snapshot for undo
|
|
70
|
+
this.capturePreDrawSnapshot();
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Called on pointermove during an active drawing operation.
|
|
74
|
+
* Handles eraser clearing or brush/pencil stroke accumulation.
|
|
75
|
+
*/
|
|
76
|
+
onPointerMove(e) {
|
|
77
|
+
var _a;
|
|
78
|
+
this.ctx.protectedData.isDrawing = true;
|
|
79
|
+
if (this.isPainting) {
|
|
80
|
+
if (this.ctx.gui_states.mode.eraser) {
|
|
81
|
+
this.ctx.nrrd_states.flags.stepClear = 1;
|
|
82
|
+
(_a = this.clearArcFn) === null || _a === void 0 ? void 0 : _a.call(this, e.offsetX, e.offsetY, this.ctx.gui_states.drawing.brushAndEraserSize);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
this.drawingLines.push({ x: e.offsetX, y: e.offsetY });
|
|
86
|
+
this.paintOnCanvasLayer(e.offsetX, e.offsetY);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Called on pointerup in draw mode.
|
|
92
|
+
* Completes stroke, fills pencil path, syncs volume, pushes undo delta.
|
|
93
|
+
*/
|
|
94
|
+
onPointerUp(_e) {
|
|
95
|
+
this.leftClicked = false;
|
|
96
|
+
const { ctx, canvas } = this.callbacks.setCurrentLayer();
|
|
97
|
+
ctx.closePath();
|
|
98
|
+
if (!this.ctx.gui_states.mode.eraser) {
|
|
99
|
+
if (this.ctx.gui_states.mode.pencil) {
|
|
100
|
+
// Clear only the current layer canvas (NOT master)
|
|
101
|
+
canvas.width = canvas.width;
|
|
102
|
+
// Redraw previous layer data from volume
|
|
103
|
+
this.redrawPreviousImageToLayerCtx(ctx);
|
|
104
|
+
// Draw new pencil strokes on current layer canvas
|
|
105
|
+
ctx.beginPath();
|
|
106
|
+
ctx.moveTo(this.drawingLines[0].x, this.drawingLines[0].y);
|
|
107
|
+
for (let i = 1; i < this.drawingLines.length; i++) {
|
|
108
|
+
ctx.lineTo(this.drawingLines[i].x, this.drawingLines[i].y);
|
|
109
|
+
}
|
|
110
|
+
ctx.closePath();
|
|
111
|
+
ctx.lineWidth = 1;
|
|
112
|
+
ctx.fillStyle = this.ctx.gui_states.drawing.fillColor;
|
|
113
|
+
ctx.fill();
|
|
114
|
+
// Composite ALL layers to master (not just current layer)
|
|
115
|
+
this.callbacks.compositeAllLayers();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
this.callbacks.syncLayerSliceData(this.ctx.nrrd_states.view.currentSliceIndex, this.ctx.gui_states.layerChannel.layer);
|
|
119
|
+
this.isPainting = false;
|
|
120
|
+
// Push undo delta
|
|
121
|
+
this.pushUndoDelta();
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Called on pointerleave during drawing.
|
|
125
|
+
* Resets painting state and cleans up leftClicked.
|
|
126
|
+
* @returns true if drawing was in progress when leave occurred
|
|
127
|
+
*/
|
|
128
|
+
onPointerLeave() {
|
|
129
|
+
this.isPainting = false;
|
|
130
|
+
if (!this.leftClicked)
|
|
131
|
+
return false;
|
|
132
|
+
this.leftClicked = false;
|
|
133
|
+
this.ctx.protectedData.ctxes.drawingLayerMasterCtx.closePath();
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
// ── Private helpers ────────────────────────────────────────
|
|
137
|
+
/** Capture pre-draw slice snapshot for undo */
|
|
138
|
+
capturePreDrawSnapshot() {
|
|
139
|
+
try {
|
|
140
|
+
this.preDrawAxis = this.ctx.protectedData.axis;
|
|
141
|
+
this.preDrawSliceIndex = this.ctx.nrrd_states.view.currentSliceIndex;
|
|
142
|
+
const vol = this.callbacks.getVolumeForLayer(this.ctx.gui_states.layerChannel.layer);
|
|
143
|
+
this.preDrawSlice = vol.getSliceUint8(this.preDrawSliceIndex, this.preDrawAxis).data.slice();
|
|
144
|
+
}
|
|
145
|
+
catch (_a) {
|
|
146
|
+
this.preDrawSlice = null;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/** Push delta to UndoManager after drawing completes */
|
|
150
|
+
pushUndoDelta() {
|
|
151
|
+
if (!this.preDrawSlice)
|
|
152
|
+
return;
|
|
153
|
+
try {
|
|
154
|
+
const vol = this.callbacks.getVolumeForLayer(this.ctx.gui_states.layerChannel.layer);
|
|
155
|
+
const { data: newSlice } = vol.getSliceUint8(this.preDrawSliceIndex, this.preDrawAxis);
|
|
156
|
+
const delta = {
|
|
157
|
+
layerId: this.ctx.gui_states.layerChannel.layer,
|
|
158
|
+
axis: this.preDrawAxis,
|
|
159
|
+
sliceIndex: this.preDrawSliceIndex,
|
|
160
|
+
oldSlice: this.preDrawSlice,
|
|
161
|
+
newSlice: newSlice.slice(),
|
|
162
|
+
};
|
|
163
|
+
this.callbacks.pushUndoDelta(delta);
|
|
164
|
+
}
|
|
165
|
+
catch (_a) {
|
|
166
|
+
// Volume not ready — skip
|
|
167
|
+
}
|
|
168
|
+
this.preDrawSlice = null;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Redraws persisted layer data onto ctx before new pencil fill.
|
|
172
|
+
* Extracted from DrawToolCore.
|
|
173
|
+
*/
|
|
174
|
+
redrawPreviousImageToLayerCtx(ctx) {
|
|
175
|
+
var _a;
|
|
176
|
+
const tempPreImg = (_a = this.callbacks.filterDrawedImage(this.ctx.protectedData.axis, this.ctx.nrrd_states.view.currentSliceIndex)) === null || _a === void 0 ? void 0 : _a.image;
|
|
177
|
+
this.ctx.protectedData.canvases.emptyCanvas.width =
|
|
178
|
+
this.ctx.protectedData.canvases.emptyCanvas.width;
|
|
179
|
+
this.ctx.protectedData.ctxes.emptyCtx.putImageData(tempPreImg, 0, 0);
|
|
180
|
+
ctx.imageSmoothingEnabled = false;
|
|
181
|
+
// Coronal (axis='y') Z-flip: same as renderSliceToCanvas.
|
|
182
|
+
if (this.ctx.protectedData.axis === 'y') {
|
|
183
|
+
ctx.save();
|
|
184
|
+
ctx.scale(1, -1);
|
|
185
|
+
ctx.translate(0, -this.ctx.nrrd_states.view.changedHeight);
|
|
186
|
+
}
|
|
187
|
+
ctx.drawImage(this.ctx.protectedData.canvases.emptyCanvas, 0, 0, this.ctx.nrrd_states.view.changedWidth, this.ctx.nrrd_states.view.changedHeight);
|
|
188
|
+
if (this.ctx.protectedData.axis === 'y') {
|
|
189
|
+
ctx.restore();
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/** Draw a line segment on a layer canvas */
|
|
193
|
+
drawLinesOnLayer(ctx, x, y) {
|
|
194
|
+
ctx.beginPath();
|
|
195
|
+
ctx.moveTo(this.ctx.nrrd_states.interaction.drawStartPos.x, this.ctx.nrrd_states.interaction.drawStartPos.y);
|
|
196
|
+
if (this.ctx.gui_states.mode.pencil) {
|
|
197
|
+
ctx.strokeStyle = this.ctx.gui_states.drawing.color;
|
|
198
|
+
ctx.lineWidth = this.ctx.gui_states.drawing.lineWidth;
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
ctx.strokeStyle = this.ctx.gui_states.drawing.brushColor;
|
|
202
|
+
ctx.lineWidth = this.ctx.gui_states.drawing.brushAndEraserSize;
|
|
203
|
+
}
|
|
204
|
+
ctx.lineTo(x, y);
|
|
205
|
+
ctx.stroke();
|
|
206
|
+
ctx.closePath();
|
|
207
|
+
}
|
|
208
|
+
/** Paint a segment on the current layer canvas and composite to master */
|
|
209
|
+
paintOnCanvasLayer(x, y) {
|
|
210
|
+
const { ctx } = this.callbacks.setCurrentLayer();
|
|
211
|
+
// Draw only on the current layer canvas (not master directly)
|
|
212
|
+
this.drawLinesOnLayer(ctx, x, y);
|
|
213
|
+
// Composite all layers to master to preserve other layers' data
|
|
214
|
+
this.callbacks.compositeAllLayers();
|
|
215
|
+
// Reset drawing start position to current position
|
|
216
|
+
this.ctx.nrrd_states.interaction.drawStartPos.x = x;
|
|
217
|
+
this.ctx.nrrd_states.interaction.drawStartPos.y = y;
|
|
218
|
+
// Flag the map as needing updating
|
|
219
|
+
this.ctx.protectedData.mainPreSlices.mesh.material.map.needsUpdate = true;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
//# sourceMappingURL=DrawingTool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DrawingTool.js","sourceRoot":"","sources":["../../../../src/Utils/segmentation/tools/DrawingTool.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,9 +16,9 @@ export class EraserTool extends BaseTool {
|
|
|
16
16
|
createClearArc() {
|
|
17
17
|
const clearArc = (x, y, radius) => {
|
|
18
18
|
var _a;
|
|
19
|
-
const activeChannel = this.ctx.gui_states.activeChannel || 1;
|
|
19
|
+
const activeChannel = this.ctx.gui_states.layerChannel.activeChannel || 1;
|
|
20
20
|
// Get color from current layer's volume (respects custom per-layer colors)
|
|
21
|
-
const layer = this.ctx.gui_states.layer;
|
|
21
|
+
const layer = this.ctx.gui_states.layerChannel.layer;
|
|
22
22
|
const volume = this.ctx.protectedData.maskData.volumes[layer];
|
|
23
23
|
const channelColor = volume
|
|
24
24
|
? volume.getChannelColor(activeChannel)
|
|
@@ -31,8 +31,8 @@ export class EraserTool extends BaseTool {
|
|
|
31
31
|
// Calculate bounding box of the eraser circle
|
|
32
32
|
const x0 = Math.max(0, Math.floor(x - radius));
|
|
33
33
|
const y0 = Math.max(0, Math.floor(y - radius));
|
|
34
|
-
const x1 = Math.min(this.ctx.nrrd_states.changedWidth, Math.ceil(x + radius));
|
|
35
|
-
const y1 = Math.min(this.ctx.nrrd_states.changedHeight, Math.ceil(y + radius));
|
|
34
|
+
const x1 = Math.min(this.ctx.nrrd_states.view.changedWidth, Math.ceil(x + radius));
|
|
35
|
+
const y1 = Math.min(this.ctx.nrrd_states.view.changedHeight, Math.ceil(y + radius));
|
|
36
36
|
const w = x1 - x0;
|
|
37
37
|
const h = y1 - y0;
|
|
38
38
|
if (w <= 0 || h <= 0)
|
|
@@ -75,11 +75,11 @@ export class EraserTool extends BaseTool {
|
|
|
75
75
|
// Recomposite master from all layer canvases (full alpha;
|
|
76
76
|
// globalAlpha applied in start() render loop).
|
|
77
77
|
const masterCtx = this.ctx.protectedData.ctxes.drawingLayerMasterCtx;
|
|
78
|
-
const fullW = this.ctx.nrrd_states.changedWidth;
|
|
79
|
-
const fullH = this.ctx.nrrd_states.changedHeight;
|
|
78
|
+
const fullW = this.ctx.nrrd_states.view.changedWidth;
|
|
79
|
+
const fullH = this.ctx.nrrd_states.view.changedHeight;
|
|
80
80
|
masterCtx.clearRect(0, 0, fullW, fullH);
|
|
81
|
-
for (const layerId of this.ctx.nrrd_states.layers) {
|
|
82
|
-
if (!this.ctx.gui_states.layerVisibility[layerId])
|
|
81
|
+
for (const layerId of this.ctx.nrrd_states.image.layers) {
|
|
82
|
+
if (!this.ctx.gui_states.layerChannel.layerVisibility[layerId])
|
|
83
83
|
continue;
|
|
84
84
|
const lt = this.ctx.protectedData.layerTargets.get(layerId);
|
|
85
85
|
if (lt)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EraserTool.js","sourceRoot":"","sources":["../../../../src/Utils/segmentation/tools/EraserTool.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAE9C,MAAM,OAAO,UAAW,SAAQ,QAAQ;IAEtC;;;;;OAKG;IACH,cAAc;QACZ,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAE,CAAS,EAAE,MAAc,EAAE,EAAE;;YACxD,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,aAAa,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"EraserTool.js","sourceRoot":"","sources":["../../../../src/Utils/segmentation/tools/EraserTool.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* ImageStoreHelper - Cross-axis image storage
|
|
3
3
|
*
|
|
4
4
|
* Extracted from DrawToolCore.ts:
|
|
5
|
-
* -
|
|
5
|
+
* - syncLayerSliceData
|
|
6
6
|
*
|
|
7
7
|
* Phase 3: MaskVolume is the sole storage backend. All IPaintImages params removed.
|
|
8
8
|
*/
|
|
@@ -23,40 +23,23 @@ export declare class ImageStoreHelper extends BaseTool {
|
|
|
23
23
|
* @returns MaskVolume for the given layer, or layer1 as fallback
|
|
24
24
|
*/
|
|
25
25
|
private getVolumeForLayer;
|
|
26
|
-
/**
|
|
27
|
-
* Get MaskVolume for the currently active layer.
|
|
28
|
-
*/
|
|
29
|
-
private getCurrentVolume;
|
|
30
26
|
/**
|
|
31
27
|
* Get the canvas element for a specific layer.
|
|
32
28
|
*/
|
|
33
29
|
private getCanvasForLayer;
|
|
34
30
|
/**
|
|
35
|
-
*
|
|
36
|
-
*/
|
|
37
|
-
storeImageToAxis(_index: number, _imageData: ImageData, _axis?: "x" | "y" | "z"): void;
|
|
38
|
-
/**
|
|
39
|
-
* Retrieve the drawn image for a given axis and slice.
|
|
31
|
+
* Vertically flip an ImageData buffer in-place (swap rows top↔bottom).
|
|
40
32
|
*
|
|
41
|
-
*
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
} | undefined;
|
|
47
|
-
/**
|
|
48
|
-
* Store all layer images for the current slice (cross-axis sync).
|
|
49
|
-
*
|
|
50
|
-
* Phase 2: Also writes into the current layer's MaskVolume.
|
|
51
|
-
*/
|
|
52
|
-
storeAllImages(index: number, layer: string): void;
|
|
53
|
-
/**
|
|
54
|
-
* Store a single layer's canvas data to its MaskVolume.
|
|
55
|
-
* Reads from the individual layer canvas (not master) and uses RGB→channel reverse lookup.
|
|
33
|
+
* Used to compensate for the Z-axis direction reversal between sagittal
|
|
34
|
+
* and coronal views. On coronal, Z runs along the canvas j-axis (vertical),
|
|
35
|
+
* and the display flip (scale(1,-1)) reverses Z relative to sagittal's
|
|
36
|
+
* horizontal Z mapping. This row-swap aligns the Z ordering so that
|
|
37
|
+
* MaskVolume stores data in a consistent coordinate system.
|
|
56
38
|
*/
|
|
57
|
-
|
|
39
|
+
private flipImageDataVertically;
|
|
58
40
|
/**
|
|
59
|
-
*
|
|
41
|
+
* Sync the current layer canvas to its MaskVolume slice and notify the parent
|
|
42
|
+
* via getMask. This is the primary write path after any draw/erase operation.
|
|
60
43
|
*/
|
|
61
|
-
|
|
44
|
+
syncLayerSliceData(index: number, layer: string): void;
|
|
62
45
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* ImageStoreHelper - Cross-axis image storage
|
|
3
3
|
*
|
|
4
4
|
* Extracted from DrawToolCore.ts:
|
|
5
|
-
* -
|
|
5
|
+
* - syncLayerSliceData
|
|
6
6
|
*
|
|
7
7
|
* Phase 3: MaskVolume is the sole storage backend. All IPaintImages params removed.
|
|
8
8
|
*/
|
|
@@ -25,16 +25,10 @@ export class ImageStoreHelper extends BaseTool {
|
|
|
25
25
|
const vol = volumes[layer];
|
|
26
26
|
if (vol)
|
|
27
27
|
return vol;
|
|
28
|
-
const firstLayerId = this.ctx.nrrd_states.layers[0];
|
|
28
|
+
const firstLayerId = this.ctx.nrrd_states.image.layers[0];
|
|
29
29
|
console.warn(`ImageStoreHelper: unknown layer "${layer}", falling back to "${firstLayerId}"`);
|
|
30
30
|
return volumes[firstLayerId];
|
|
31
31
|
}
|
|
32
|
-
/**
|
|
33
|
-
* Get MaskVolume for the currently active layer.
|
|
34
|
-
*/
|
|
35
|
-
getCurrentVolume() {
|
|
36
|
-
return this.getVolumeForLayer(this.ctx.gui_states.layer);
|
|
37
|
-
}
|
|
38
32
|
/**
|
|
39
33
|
* Get the canvas element for a specific layer.
|
|
40
34
|
*/
|
|
@@ -44,76 +38,74 @@ export class ImageStoreHelper extends BaseTool {
|
|
|
44
38
|
return target.canvas;
|
|
45
39
|
return this.ctx.protectedData.canvases.drawingCanvasLayerMaster;
|
|
46
40
|
}
|
|
47
|
-
// =====
|
|
41
|
+
// ===== ImageData Flip Helpers =====
|
|
48
42
|
/**
|
|
49
|
-
*
|
|
50
|
-
*/
|
|
51
|
-
storeImageToAxis(_index, _imageData, _axis) {
|
|
52
|
-
// No-op: MaskVolume is the primary storage, updated in storeAllImages
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Retrieve the drawn image for a given axis and slice.
|
|
43
|
+
* Vertically flip an ImageData buffer in-place (swap rows top↔bottom).
|
|
56
44
|
*
|
|
57
|
-
*
|
|
45
|
+
* Used to compensate for the Z-axis direction reversal between sagittal
|
|
46
|
+
* and coronal views. On coronal, Z runs along the canvas j-axis (vertical),
|
|
47
|
+
* and the display flip (scale(1,-1)) reverses Z relative to sagittal's
|
|
48
|
+
* horizontal Z mapping. This row-swap aligns the Z ordering so that
|
|
49
|
+
* MaskVolume stores data in a consistent coordinate system.
|
|
58
50
|
*/
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
volume.renderLabelSliceInto(sliceIndex, axis, imageData, channelVis);
|
|
71
|
-
return { index: sliceIndex, image: imageData };
|
|
72
|
-
}
|
|
51
|
+
flipImageDataVertically(imageData) {
|
|
52
|
+
const { width, height, data } = imageData;
|
|
53
|
+
const rowSize = width * 4; // RGBA = 4 bytes per pixel
|
|
54
|
+
const temp = new Uint8ClampedArray(rowSize);
|
|
55
|
+
for (let y = 0; y < Math.floor(height / 2); y++) {
|
|
56
|
+
const topOffset = y * rowSize;
|
|
57
|
+
const bottomOffset = (height - 1 - y) * rowSize;
|
|
58
|
+
// Swap top row and bottom row
|
|
59
|
+
temp.set(data.subarray(topOffset, topOffset + rowSize));
|
|
60
|
+
data.copyWithin(topOffset, bottomOffset, bottomOffset + rowSize);
|
|
61
|
+
data.set(temp, bottomOffset);
|
|
73
62
|
}
|
|
74
|
-
catch (err) {
|
|
75
|
-
console.warn(`filterDrawedImage: Failed to read slice ${sliceIndex} on ${axis}:`, err);
|
|
76
|
-
}
|
|
77
|
-
return undefined;
|
|
78
63
|
}
|
|
79
|
-
// =====
|
|
64
|
+
// ===== Sync Layer Slice Data =====
|
|
80
65
|
/**
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
* Phase 2: Also writes into the current layer's MaskVolume.
|
|
66
|
+
* Sync the current layer canvas to its MaskVolume slice and notify the parent
|
|
67
|
+
* via getMask. This is the primary write path after any draw/erase operation.
|
|
84
68
|
*/
|
|
85
|
-
|
|
69
|
+
syncLayerSliceData(index, layer) {
|
|
86
70
|
const nrrd = this.ctx.nrrd_states;
|
|
87
71
|
// Read from the individual layer canvas (NOT master) to preserve layer isolation
|
|
88
72
|
const layerCanvas = this.getCanvasForLayer(layer);
|
|
89
|
-
if (!nrrd.
|
|
73
|
+
if (!nrrd.flags.loadingMaskData && !this.ctx.gui_states.mode.sphere) {
|
|
90
74
|
this.callbacks.setEmptyCanvasSize();
|
|
91
75
|
this.callbacks.drawImageOnEmptyImage(layerCanvas);
|
|
92
76
|
}
|
|
93
77
|
const imageData = this.ctx.protectedData.ctxes.emptyCtx.getImageData(0, 0, this.ctx.protectedData.canvases.emptyCanvas.width, this.ctx.protectedData.canvases.emptyCanvas.height);
|
|
78
|
+
// Coronal (axis='y') Z-flip: the Z dimension runs vertically on coronal
|
|
79
|
+
// but horizontally on sagittal, with opposite screen directions.
|
|
80
|
+
// Flip ImageData vertically before writing to MaskVolume so that
|
|
81
|
+
// cross-view rendering (sagittal↔coronal) is consistent.
|
|
82
|
+
// Same pattern as SphereTool.canvasToVoxelCenter('y') Z-flip.
|
|
83
|
+
if (this.ctx.protectedData.axis === 'y') {
|
|
84
|
+
this.flipImageDataVertically(imageData);
|
|
85
|
+
}
|
|
94
86
|
// Write label data into 1-channel MaskVolume with RGB→channel reverse lookup
|
|
95
87
|
try {
|
|
96
88
|
const volume = this.getVolumeForLayer(layer);
|
|
97
89
|
if (volume) {
|
|
98
|
-
const activeChannel = this.ctx.gui_states.activeChannel || 1;
|
|
90
|
+
const activeChannel = this.ctx.gui_states.layerChannel.activeChannel || 1;
|
|
99
91
|
// Phase 4 Fix: Pass channel visibility map to preserve hidden channels
|
|
100
|
-
const channelVis = this.ctx.gui_states.channelVisibility[layer];
|
|
92
|
+
const channelVis = this.ctx.gui_states.layerChannel.channelVisibility[layer];
|
|
101
93
|
volume.setSliceLabelsFromImageData(index, imageData, this.ctx.protectedData.axis, activeChannel, channelVis);
|
|
102
94
|
}
|
|
103
95
|
}
|
|
104
96
|
catch (err) {
|
|
105
97
|
// Volume not ready — skip
|
|
106
98
|
}
|
|
107
|
-
if (!nrrd.
|
|
99
|
+
if (!nrrd.flags.loadingMaskData && !this.ctx.gui_states.mode.sphere) {
|
|
108
100
|
// Extract raw slice data from MaskVolume and notify parent
|
|
109
101
|
try {
|
|
110
102
|
const volume = this.getVolumeForLayer(layer);
|
|
111
103
|
if (volume) {
|
|
112
104
|
const axis = this.ctx.protectedData.axis;
|
|
113
|
-
const sliceIndex = this.ctx.nrrd_states.
|
|
105
|
+
const sliceIndex = this.ctx.nrrd_states.view.currentSliceIndex;
|
|
114
106
|
const { data: sliceData, width, height } = volume.getSliceUint8(sliceIndex, axis);
|
|
115
|
-
const activeChannel = this.ctx.gui_states.activeChannel || 1;
|
|
116
|
-
this.ctx.
|
|
107
|
+
const activeChannel = this.ctx.gui_states.layerChannel.activeChannel || 1;
|
|
108
|
+
this.ctx.callbacks.onMaskChanged(sliceData, layer, activeChannel, sliceIndex, axis, width, height, this.ctx.nrrd_states.flags.clearAllFlag);
|
|
117
109
|
}
|
|
118
110
|
}
|
|
119
111
|
catch (_a) {
|
|
@@ -121,40 +113,5 @@ export class ImageStoreHelper extends BaseTool {
|
|
|
121
113
|
}
|
|
122
114
|
}
|
|
123
115
|
}
|
|
124
|
-
// ===== Store Per-Layer Images =====
|
|
125
|
-
/**
|
|
126
|
-
* Store a single layer's canvas data to its MaskVolume.
|
|
127
|
-
* Reads from the individual layer canvas (not master) and uses RGB→channel reverse lookup.
|
|
128
|
-
*/
|
|
129
|
-
storeEachLayerImage(index, layer) {
|
|
130
|
-
const layerCanvas = this.getCanvasForLayer(layer);
|
|
131
|
-
this.callbacks.setEmptyCanvasSize();
|
|
132
|
-
this.callbacks.drawImageOnEmptyImage(layerCanvas);
|
|
133
|
-
const imageData = this.ctx.protectedData.ctxes.emptyCtx.getImageData(0, 0, this.ctx.protectedData.canvases.emptyCanvas.width, this.ctx.protectedData.canvases.emptyCanvas.height);
|
|
134
|
-
try {
|
|
135
|
-
const volume = this.getVolumeForLayer(layer);
|
|
136
|
-
if (volume) {
|
|
137
|
-
const activeChannel = this.ctx.gui_states.activeChannel || 1;
|
|
138
|
-
// Phase 4 Fix: Pass channel visibility map to preserve hidden channels
|
|
139
|
-
const channelVis = this.ctx.gui_states.channelVisibility[layer];
|
|
140
|
-
volume.setSliceLabelsFromImageData(index, imageData, this.ctx.protectedData.axis, activeChannel, channelVis);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
catch (_a) {
|
|
144
|
-
// Volume not ready — skip
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* Extract ImageData from canvas (MaskVolume storage is handled in storeAllImages).
|
|
149
|
-
*/
|
|
150
|
-
storeImageToLayer(_index, canvas) {
|
|
151
|
-
if (!this.ctx.nrrd_states.loadMaskJson) {
|
|
152
|
-
this.callbacks.setEmptyCanvasSize();
|
|
153
|
-
this.callbacks.drawImageOnEmptyImage(canvas);
|
|
154
|
-
}
|
|
155
|
-
const imageData = this.ctx.protectedData.ctxes.emptyCtx.getImageData(0, 0, this.ctx.protectedData.canvases.emptyCanvas.width, this.ctx.protectedData.canvases.emptyCanvas.height);
|
|
156
|
-
// No longer stores to paintedImages - MaskVolume is primary storage
|
|
157
|
-
return imageData;
|
|
158
|
-
}
|
|
159
116
|
}
|
|
160
117
|
//# sourceMappingURL=ImageStoreHelper.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageStoreHelper.js","sourceRoot":"","sources":["../../../../src/Utils/segmentation/tools/ImageStoreHelper.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAStC,MAAM,OAAO,gBAAiB,SAAQ,QAAQ;IAG5C,YAAY,GAAgB,EAAE,SAA8B;QAC1D,KAAK,CAAC,GAAG,CAAC,CAAC;QACX,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IAED,gDAAgD;IAEhD;;;;;;OAMG;IACK,iBAAiB,CAAC,KAAa;QACrC,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,QAAQ,CAAC;QACpD,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;QAC3B,IAAI,GAAG;YAAE,OAAO,GAAG,CAAC;QACpB,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"ImageStoreHelper.js","sourceRoot":"","sources":["../../../../src/Utils/segmentation/tools/ImageStoreHelper.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PanTool - Right-click pan/drag navigation
|
|
3
|
+
*
|
|
4
|
+
* Extracted from DrawToolCore.paintOnCanvas() closure.
|
|
5
|
+
* Handles right-click drag to reposition the canvas view.
|
|
6
|
+
*/
|
|
7
|
+
import { BaseTool } from "./BaseTool";
|
|
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
|
+
}
|
|
16
|
+
export declare class PanTool extends BaseTool {
|
|
17
|
+
/** Right mouse button currently held */
|
|
18
|
+
private rightClicked;
|
|
19
|
+
/** Pan drag offset X (clientX − canvas.offsetLeft at drag start) */
|
|
20
|
+
private panMoveInnerX;
|
|
21
|
+
/** Pan drag offset Y (clientY − canvas.offsetTop at drag start) */
|
|
22
|
+
private panMoveInnerY;
|
|
23
|
+
private callbacks;
|
|
24
|
+
/**
|
|
25
|
+
* Bound handler reference for pointermove so we can add/remove it.
|
|
26
|
+
* Arrow function preserves `this` binding.
|
|
27
|
+
*/
|
|
28
|
+
private readonly boundPointerMove;
|
|
29
|
+
constructor(ctx: ToolContext, callbacks: PanCallbacks);
|
|
30
|
+
/** Whether a pan drag is currently active */
|
|
31
|
+
get isActive(): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Called on right-click pointerdown.
|
|
34
|
+
* Captures initial offsets and registers pointermove listener.
|
|
35
|
+
*/
|
|
36
|
+
onPointerDown(e: MouseEvent): void;
|
|
37
|
+
/**
|
|
38
|
+
* Called on pointerup (button === 2).
|
|
39
|
+
* Cleans up listeners and restores cursor.
|
|
40
|
+
*/
|
|
41
|
+
onPointerUp(e: MouseEvent, defaultCursor: string): void;
|
|
42
|
+
/**
|
|
43
|
+
* Called on pointerleave while pan is active.
|
|
44
|
+
* Resets state and removes listener.
|
|
45
|
+
*/
|
|
46
|
+
onPointerLeave(): void;
|
|
47
|
+
/** Reset pan state (called when paintOnCanvas re-initializes) */
|
|
48
|
+
reset(): void;
|
|
49
|
+
/**
|
|
50
|
+
* Pointermove handler — updates canvas position during drag.
|
|
51
|
+
*/
|
|
52
|
+
private handlePointerMove;
|
|
53
|
+
}
|