copper3d 3.1.2 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Utils/segmentation/DragOperator.js +3 -1
- package/dist/Utils/segmentation/DragOperator.js.map +1 -1
- package/dist/Utils/segmentation/DrawToolCore.d.ts +6 -0
- package/dist/Utils/segmentation/DrawToolCore.js +107 -35
- package/dist/Utils/segmentation/DrawToolCore.js.map +1 -1
- package/dist/Utils/segmentation/NrrdTools.d.ts +2 -0
- package/dist/Utils/segmentation/NrrdTools.js +41 -1
- package/dist/Utils/segmentation/NrrdTools.js.map +1 -1
- package/dist/Utils/segmentation/core/UndoManager.d.ts +9 -5
- package/dist/Utils/segmentation/core/UndoManager.js +21 -14
- package/dist/Utils/segmentation/core/UndoManager.js.map +1 -1
- package/dist/Utils/segmentation/core/index.d.ts +1 -1
- package/dist/Utils/segmentation/core/types.d.ts +5 -1
- package/dist/Utils/segmentation/core/types.js.map +1 -1
- package/dist/Utils/segmentation/coreTools/GuiState.js +2 -0
- package/dist/Utils/segmentation/coreTools/GuiState.js.map +1 -1
- package/dist/Utils/segmentation/coreTools/NrrdState.js +2 -0
- package/dist/Utils/segmentation/coreTools/NrrdState.js.map +1 -1
- package/dist/Utils/segmentation/eventRouter/EventRouter.js +1 -0
- package/dist/Utils/segmentation/eventRouter/EventRouter.js.map +1 -1
- package/dist/Utils/segmentation/eventRouter/types.d.ts +1 -1
- package/dist/Utils/segmentation/tools/SphereBrushTool.d.ts +127 -0
- package/dist/Utils/segmentation/tools/SphereBrushTool.js +489 -0
- package/dist/Utils/segmentation/tools/SphereBrushTool.js.map +1 -0
- package/dist/Utils/segmentation/tools/ToolHost.d.ts +3 -0
- package/dist/Utils/segmentation/tools/ZoomTool.js +6 -1
- package/dist/Utils/segmentation/tools/ZoomTool.js.map +1 -1
- package/dist/Utils/segmentation/tools/index.d.ts +2 -1
- package/dist/Utils/segmentation/tools/index.js +1 -0
- package/dist/Utils/segmentation/tools/index.js.map +1 -1
- package/dist/bundle.esm.js +670 -53
- package/dist/bundle.umd.js +670 -53
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/types/Utils/segmentation/DrawToolCore.d.ts +6 -0
- package/dist/types/Utils/segmentation/NrrdTools.d.ts +2 -0
- package/dist/types/Utils/segmentation/core/UndoManager.d.ts +9 -5
- package/dist/types/Utils/segmentation/core/index.d.ts +1 -1
- package/dist/types/Utils/segmentation/core/types.d.ts +5 -1
- package/dist/types/Utils/segmentation/eventRouter/types.d.ts +1 -1
- package/dist/types/Utils/segmentation/tools/SphereBrushTool.d.ts +127 -0
- package/dist/types/Utils/segmentation/tools/ToolHost.d.ts +3 -0
- package/dist/types/Utils/segmentation/tools/index.d.ts +2 -1
- package/dist/types/index.d.ts +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SphereBrushTool — 3D sphere brush and eraser on layer MaskVolume.
|
|
3
|
+
*
|
|
4
|
+
* Unlike SphereTool (which uses its own isolated sphereMaskVolume),
|
|
5
|
+
* this tool writes/erases directly in the active layer's shared MaskVolume —
|
|
6
|
+
* the same volume used by pencil/brush/eraser tools.
|
|
7
|
+
*
|
|
8
|
+
* Two operation modes handled by one class:
|
|
9
|
+
* - **sphereBrush**: Direct click to paint a 3D sphere of the active channel label.
|
|
10
|
+
* - **sphereEraser**: Shift+click to erase a 3D sphere (only voxels matching active channel).
|
|
11
|
+
*
|
|
12
|
+
* Interaction:
|
|
13
|
+
* 1. Pointer-down records sphere center, switches wheel to radius mode.
|
|
14
|
+
* 2. Scroll wheel adjusts sphereBrushRadius [1, 50].
|
|
15
|
+
* 3. Pointer-up writes/erases sphere to volume, captures grouped undo, refreshes canvas.
|
|
16
|
+
*/
|
|
17
|
+
import { BaseTool } from "./BaseTool";
|
|
18
|
+
import { CHANNEL_HEX_COLORS } from "../core";
|
|
19
|
+
export class SphereBrushTool extends BaseTool {
|
|
20
|
+
constructor(ctx, callbacks) {
|
|
21
|
+
super(ctx);
|
|
22
|
+
/** Recorded sphere center in canvas mm-space */
|
|
23
|
+
this.centerX = 0;
|
|
24
|
+
this.centerY = 0;
|
|
25
|
+
this.centerSlice = 0;
|
|
26
|
+
/** Whether a sphere placement is in progress */
|
|
27
|
+
this.active = false;
|
|
28
|
+
/** Current operation mode for the active placement */
|
|
29
|
+
this.mode = "brush";
|
|
30
|
+
/** Cumulative "before" snapshots for drag-erase undo (z-index → slice data) */
|
|
31
|
+
this.dragBeforeSnapshots = new Map();
|
|
32
|
+
/** Whether a drag-erase has actually moved (vs. simple click-release) */
|
|
33
|
+
this.dragMoved = false;
|
|
34
|
+
this.callbacks = callbacks;
|
|
35
|
+
}
|
|
36
|
+
setCallbacks(callbacks) {
|
|
37
|
+
this.callbacks = callbacks;
|
|
38
|
+
}
|
|
39
|
+
// ── Geometry (ported from SphereTool) ──────────────────────────
|
|
40
|
+
/**
|
|
41
|
+
* Convert canvas mm-space coordinates to 3D voxel coordinates.
|
|
42
|
+
*/
|
|
43
|
+
canvasToVoxelCenter(canvasX, canvasY, sliceIndex, axis) {
|
|
44
|
+
const nrrd = this.ctx.nrrd_states;
|
|
45
|
+
switch (axis) {
|
|
46
|
+
case 'z':
|
|
47
|
+
return {
|
|
48
|
+
x: canvasX * nrrd.image.nrrd_x_pixel / nrrd.image.nrrd_x_mm,
|
|
49
|
+
y: canvasY * nrrd.image.nrrd_y_pixel / nrrd.image.nrrd_y_mm,
|
|
50
|
+
z: sliceIndex,
|
|
51
|
+
};
|
|
52
|
+
case 'y':
|
|
53
|
+
return {
|
|
54
|
+
x: canvasX * nrrd.image.nrrd_x_pixel / nrrd.image.nrrd_x_mm,
|
|
55
|
+
y: sliceIndex,
|
|
56
|
+
z: (nrrd.image.nrrd_z_mm - canvasY) * nrrd.image.nrrd_z_pixel / nrrd.image.nrrd_z_mm,
|
|
57
|
+
};
|
|
58
|
+
case 'x':
|
|
59
|
+
return {
|
|
60
|
+
x: sliceIndex,
|
|
61
|
+
y: canvasY * nrrd.image.nrrd_y_pixel / nrrd.image.nrrd_y_mm,
|
|
62
|
+
z: canvasX * nrrd.image.nrrd_z_pixel / nrrd.image.nrrd_z_mm,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Convert mm radius to per-axis voxel radii.
|
|
68
|
+
*/
|
|
69
|
+
getVoxelRadii(radius) {
|
|
70
|
+
const nrrd = this.ctx.nrrd_states;
|
|
71
|
+
return {
|
|
72
|
+
rx: radius * nrrd.image.nrrd_x_pixel / nrrd.image.nrrd_x_mm,
|
|
73
|
+
ry: radius * nrrd.image.nrrd_y_pixel / nrrd.image.nrrd_y_mm,
|
|
74
|
+
rz: radius * nrrd.image.nrrd_z_pixel / nrrd.image.nrrd_z_mm,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Compute clamped bounding box for an ellipsoid in voxel space.
|
|
79
|
+
*/
|
|
80
|
+
getBoundingBox(center, radii, dims) {
|
|
81
|
+
return {
|
|
82
|
+
minX: Math.max(0, Math.floor(center.x - radii.rx)),
|
|
83
|
+
maxX: Math.min(dims.width - 1, Math.ceil(center.x + radii.rx)),
|
|
84
|
+
minY: Math.max(0, Math.floor(center.y - radii.ry)),
|
|
85
|
+
maxY: Math.min(dims.height - 1, Math.ceil(center.y + radii.ry)),
|
|
86
|
+
minZ: Math.max(0, Math.floor(center.z - radii.rz)),
|
|
87
|
+
maxZ: Math.min(dims.depth - 1, Math.ceil(center.z + radii.rz)),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
// ── 3D Volume Write / Erase ────────────────────────────────────
|
|
91
|
+
/**
|
|
92
|
+
* Write a 3D sphere of the active channel label into the layer's MaskVolume.
|
|
93
|
+
*/
|
|
94
|
+
write3DSphereToBrush(vol, center, radii, bb, label) {
|
|
95
|
+
const { rx, ry, rz } = radii;
|
|
96
|
+
for (let z = bb.minZ; z <= bb.maxZ; z++) {
|
|
97
|
+
for (let y = bb.minY; y <= bb.maxY; y++) {
|
|
98
|
+
for (let x = bb.minX; x <= bb.maxX; x++) {
|
|
99
|
+
const dx = rx > 0 ? (x - center.x) / rx : 0;
|
|
100
|
+
const dy = ry > 0 ? (y - center.y) / ry : 0;
|
|
101
|
+
const dz = rz > 0 ? (z - center.z) / rz : 0;
|
|
102
|
+
if (dx * dx + dy * dy + dz * dz <= 1.0) {
|
|
103
|
+
vol.setVoxel(x, y, z, label);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Erase a 3D sphere from the layer's MaskVolume.
|
|
111
|
+
* Only clears voxels whose current value equals the active channel label.
|
|
112
|
+
*/
|
|
113
|
+
erase3DSphereFromVolume(vol, center, radii, bb, label) {
|
|
114
|
+
const { rx, ry, rz } = radii;
|
|
115
|
+
for (let z = bb.minZ; z <= bb.maxZ; z++) {
|
|
116
|
+
for (let y = bb.minY; y <= bb.maxY; y++) {
|
|
117
|
+
for (let x = bb.minX; x <= bb.maxX; x++) {
|
|
118
|
+
const dx = rx > 0 ? (x - center.x) / rx : 0;
|
|
119
|
+
const dy = ry > 0 ? (y - center.y) / ry : 0;
|
|
120
|
+
const dz = rz > 0 ? (z - center.z) / rz : 0;
|
|
121
|
+
if (dx * dx + dy * dy + dz * dz <= 1.0) {
|
|
122
|
+
if (vol.getVoxel(x, y, z) === label) {
|
|
123
|
+
vol.setVoxel(x, y, z, 0);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// ── Undo Capture ───────────────────────────────────────────────
|
|
131
|
+
/**
|
|
132
|
+
* Capture slice snapshots for all Z-slices in the bounding box.
|
|
133
|
+
* Used before and after the sphere operation to build MaskDelta groups.
|
|
134
|
+
*
|
|
135
|
+
* We always capture along the Z axis since the 3D sphere spans Z slices.
|
|
136
|
+
*/
|
|
137
|
+
captureSliceSnapshots(vol, minZ, maxZ) {
|
|
138
|
+
const snapshots = new Map();
|
|
139
|
+
for (let z = minZ; z <= maxZ; z++) {
|
|
140
|
+
try {
|
|
141
|
+
const { data } = vol.getSliceUint8(z, 'z');
|
|
142
|
+
snapshots.set(z, data.slice());
|
|
143
|
+
}
|
|
144
|
+
catch (_a) {
|
|
145
|
+
// slice out of bounds — skip
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return snapshots;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Build MaskDelta group from before/after snapshots.
|
|
152
|
+
*/
|
|
153
|
+
buildUndoGroup(layerId, before, after) {
|
|
154
|
+
const deltas = [];
|
|
155
|
+
for (const [sliceIndex, oldSlice] of before) {
|
|
156
|
+
const newSlice = after.get(sliceIndex);
|
|
157
|
+
if (!newSlice)
|
|
158
|
+
continue;
|
|
159
|
+
// Only include slices that actually changed
|
|
160
|
+
let changed = false;
|
|
161
|
+
for (let i = 0; i < oldSlice.length; i++) {
|
|
162
|
+
if (oldSlice[i] !== newSlice[i]) {
|
|
163
|
+
changed = true;
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (changed) {
|
|
168
|
+
deltas.push({ layerId, axis: 'z', sliceIndex, oldSlice, newSlice });
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return deltas;
|
|
172
|
+
}
|
|
173
|
+
// ── Preview Rendering ──────────────────────────────────────────
|
|
174
|
+
/**
|
|
175
|
+
* Draw a preview circle on the sphere canvas during sphere placement.
|
|
176
|
+
*/
|
|
177
|
+
drawPreview(mouseX, mouseY, radius, isEraser) {
|
|
178
|
+
const sphereCanvas = this.ctx.protectedData.canvases.drawingSphereCanvas;
|
|
179
|
+
const sphereCtx = this.ctx.protectedData.ctxes.drawingSphereCtx;
|
|
180
|
+
// Clear and resize sphere canvas
|
|
181
|
+
sphereCanvas.width = this.ctx.protectedData.canvases.originCanvas.width;
|
|
182
|
+
sphereCanvas.height = this.ctx.protectedData.canvases.originCanvas.height;
|
|
183
|
+
sphereCtx.beginPath();
|
|
184
|
+
sphereCtx.arc(mouseX, mouseY, radius, 0, 2 * Math.PI);
|
|
185
|
+
if (isEraser) {
|
|
186
|
+
// Eraser preview: dashed outline
|
|
187
|
+
sphereCtx.strokeStyle = "#ff4444";
|
|
188
|
+
sphereCtx.lineWidth = 2;
|
|
189
|
+
sphereCtx.setLineDash([4, 4]);
|
|
190
|
+
sphereCtx.stroke();
|
|
191
|
+
sphereCtx.setLineDash([]);
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
// Brush preview: semi-transparent fill with active channel color
|
|
195
|
+
const channel = this.ctx.gui_states.layerChannel.activeChannel || 1;
|
|
196
|
+
const color = this.getActiveChannelColor(channel);
|
|
197
|
+
sphereCtx.fillStyle = color;
|
|
198
|
+
sphereCtx.globalAlpha = 0.5;
|
|
199
|
+
sphereCtx.fill();
|
|
200
|
+
sphereCtx.globalAlpha = 1.0;
|
|
201
|
+
}
|
|
202
|
+
sphereCtx.closePath();
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Clear the sphere preview canvas.
|
|
206
|
+
*/
|
|
207
|
+
clearPreview() {
|
|
208
|
+
const sphereCanvas = this.ctx.protectedData.canvases.drawingSphereCanvas;
|
|
209
|
+
sphereCanvas.width = sphereCanvas.width;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Get the hex color for the active channel from the layer's MaskVolume.
|
|
213
|
+
*/
|
|
214
|
+
getActiveChannelColor(channel) {
|
|
215
|
+
var _a;
|
|
216
|
+
const layer = this.ctx.gui_states.layerChannel.layer;
|
|
217
|
+
const volumes = this.ctx.protectedData.maskData.volumes;
|
|
218
|
+
const vol = volumes[layer];
|
|
219
|
+
if (vol) {
|
|
220
|
+
const rgba = vol.getChannelColor(channel);
|
|
221
|
+
const r = rgba.r.toString(16).padStart(2, '0');
|
|
222
|
+
const g = rgba.g.toString(16).padStart(2, '0');
|
|
223
|
+
const b = rgba.b.toString(16).padStart(2, '0');
|
|
224
|
+
return `#${r}${g}${b}`;
|
|
225
|
+
}
|
|
226
|
+
return (_a = CHANNEL_HEX_COLORS[channel]) !== null && _a !== void 0 ? _a : "#ff0000";
|
|
227
|
+
}
|
|
228
|
+
// ── Wheel Handler ──────────────────────────────────────────────
|
|
229
|
+
/**
|
|
230
|
+
* Returns a wheel event handler for adjusting sphereBrushRadius.
|
|
231
|
+
* Used in both sphereBrush and sphereEraser modes.
|
|
232
|
+
*/
|
|
233
|
+
configSphereBrushWheel() {
|
|
234
|
+
return (e) => {
|
|
235
|
+
e.preventDefault();
|
|
236
|
+
const sphere = this.ctx.nrrd_states.sphere;
|
|
237
|
+
if (e.deltaY < 0) {
|
|
238
|
+
sphere.sphereBrushRadius += 1;
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
sphere.sphereBrushRadius -= 1;
|
|
242
|
+
}
|
|
243
|
+
sphere.sphereBrushRadius = Math.max(1, Math.min(sphere.sphereBrushRadius, 50));
|
|
244
|
+
// Redraw preview
|
|
245
|
+
if (this.active) {
|
|
246
|
+
this.drawPreview(this.centerX, this.centerY, sphere.sphereBrushRadius, this.mode === "eraser");
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
// ── Sphere Brush Click/PointerUp ───────────────────────────────
|
|
251
|
+
/**
|
|
252
|
+
* Handle pointer-down in sphereBrush mode (direct click, no Shift needed).
|
|
253
|
+
*/
|
|
254
|
+
onSphereBrushClick(e) {
|
|
255
|
+
this.centerX = e.offsetX / this.ctx.nrrd_states.view.sizeFactor;
|
|
256
|
+
this.centerY = e.offsetY / this.ctx.nrrd_states.view.sizeFactor;
|
|
257
|
+
this.centerSlice = this.ctx.nrrd_states.view.currentSliceIndex;
|
|
258
|
+
this.active = true;
|
|
259
|
+
this.mode = "brush";
|
|
260
|
+
this.drawPreview(this.centerX, this.centerY, this.ctx.nrrd_states.sphere.sphereBrushRadius, false);
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Handle pointer-up in sphereBrush mode — write sphere to volume.
|
|
264
|
+
*/
|
|
265
|
+
onSphereBrushPointerUp() {
|
|
266
|
+
if (!this.active || this.mode !== "brush")
|
|
267
|
+
return;
|
|
268
|
+
this.active = false;
|
|
269
|
+
const layer = this.ctx.gui_states.layerChannel.layer;
|
|
270
|
+
const channel = this.ctx.gui_states.layerChannel.activeChannel || 1;
|
|
271
|
+
const axis = this.ctx.protectedData.axis;
|
|
272
|
+
const radius = this.ctx.nrrd_states.sphere.sphereBrushRadius;
|
|
273
|
+
let vol;
|
|
274
|
+
try {
|
|
275
|
+
vol = this.callbacks.getVolumeForLayer(layer);
|
|
276
|
+
}
|
|
277
|
+
catch (_a) {
|
|
278
|
+
this.clearPreview();
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
const dims = vol.getDimensions();
|
|
282
|
+
const center = this.canvasToVoxelCenter(this.centerX, this.centerY, this.centerSlice, axis);
|
|
283
|
+
const radii = this.getVoxelRadii(radius);
|
|
284
|
+
const bb = this.getBoundingBox(center, radii, dims);
|
|
285
|
+
// Capture pre-write snapshots
|
|
286
|
+
const before = this.captureSliceSnapshots(vol, bb.minZ, bb.maxZ);
|
|
287
|
+
// Write sphere
|
|
288
|
+
this.write3DSphereToBrush(vol, center, radii, bb, channel);
|
|
289
|
+
// Capture post-write snapshots and push undo group
|
|
290
|
+
const after = this.captureSliceSnapshots(vol, bb.minZ, bb.maxZ);
|
|
291
|
+
const deltas = this.buildUndoGroup(layer, before, after);
|
|
292
|
+
if (deltas.length > 0) {
|
|
293
|
+
this.callbacks.pushUndoGroup(deltas);
|
|
294
|
+
}
|
|
295
|
+
// Refresh display and notify backend of ALL changed slices
|
|
296
|
+
this.refreshDisplay(layer, deltas);
|
|
297
|
+
this.clearPreview();
|
|
298
|
+
}
|
|
299
|
+
// ── Sphere Eraser Click/PointerUp ──────────────────────────────
|
|
300
|
+
/**
|
|
301
|
+
* Handle pointer-down in sphereEraser mode.
|
|
302
|
+
* Initializes drag tracking for cumulative undo.
|
|
303
|
+
*/
|
|
304
|
+
onSphereEraserClick(e) {
|
|
305
|
+
this.centerX = e.offsetX / this.ctx.nrrd_states.view.sizeFactor;
|
|
306
|
+
this.centerY = e.offsetY / this.ctx.nrrd_states.view.sizeFactor;
|
|
307
|
+
this.centerSlice = this.ctx.nrrd_states.view.currentSliceIndex;
|
|
308
|
+
this.active = true;
|
|
309
|
+
this.mode = "eraser";
|
|
310
|
+
this.dragMoved = false;
|
|
311
|
+
this.dragBeforeSnapshots.clear();
|
|
312
|
+
// Capture initial "before" snapshots for the first sphere position
|
|
313
|
+
const layer = this.ctx.gui_states.layerChannel.layer;
|
|
314
|
+
const radius = this.ctx.nrrd_states.sphere.sphereBrushRadius;
|
|
315
|
+
try {
|
|
316
|
+
const vol = this.callbacks.getVolumeForLayer(layer);
|
|
317
|
+
const dims = vol.getDimensions();
|
|
318
|
+
const axis = this.ctx.protectedData.axis;
|
|
319
|
+
const center = this.canvasToVoxelCenter(this.centerX, this.centerY, this.centerSlice, axis);
|
|
320
|
+
const radii = this.getVoxelRadii(radius);
|
|
321
|
+
const bb = this.getBoundingBox(center, radii, dims);
|
|
322
|
+
this.expandDragBeforeSnapshots(vol, bb.minZ, bb.maxZ);
|
|
323
|
+
}
|
|
324
|
+
catch (_a) {
|
|
325
|
+
// Volume not ready
|
|
326
|
+
}
|
|
327
|
+
this.drawPreview(this.centerX, this.centerY, radius, true);
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Handle pointer-move in sphereEraser mode — drag to continuously erase.
|
|
331
|
+
*/
|
|
332
|
+
onSphereEraserMove(e) {
|
|
333
|
+
if (!this.active || this.mode !== "eraser")
|
|
334
|
+
return;
|
|
335
|
+
this.dragMoved = true;
|
|
336
|
+
const mouseX = e.offsetX / this.ctx.nrrd_states.view.sizeFactor;
|
|
337
|
+
const mouseY = e.offsetY / this.ctx.nrrd_states.view.sizeFactor;
|
|
338
|
+
const sliceIndex = this.ctx.nrrd_states.view.currentSliceIndex;
|
|
339
|
+
const layer = this.ctx.gui_states.layerChannel.layer;
|
|
340
|
+
const channel = this.ctx.gui_states.layerChannel.activeChannel || 1;
|
|
341
|
+
const axis = this.ctx.protectedData.axis;
|
|
342
|
+
const radius = this.ctx.nrrd_states.sphere.sphereBrushRadius;
|
|
343
|
+
let vol;
|
|
344
|
+
try {
|
|
345
|
+
vol = this.callbacks.getVolumeForLayer(layer);
|
|
346
|
+
}
|
|
347
|
+
catch (_a) {
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
const dims = vol.getDimensions();
|
|
351
|
+
const center = this.canvasToVoxelCenter(mouseX, mouseY, sliceIndex, axis);
|
|
352
|
+
const radii = this.getVoxelRadii(radius);
|
|
353
|
+
const bb = this.getBoundingBox(center, radii, dims);
|
|
354
|
+
// Expand "before" snapshots to cover any new Z slices
|
|
355
|
+
this.expandDragBeforeSnapshots(vol, bb.minZ, bb.maxZ);
|
|
356
|
+
// Erase sphere at current position
|
|
357
|
+
this.erase3DSphereFromVolume(vol, center, radii, bb, channel);
|
|
358
|
+
// Update preview position
|
|
359
|
+
this.drawPreview(mouseX, mouseY, radius, true);
|
|
360
|
+
// Refresh display so user sees the erase in real-time
|
|
361
|
+
this.refreshDisplay(layer);
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Handle pointer-up in sphereEraser mode — finalize erase + push undo group.
|
|
365
|
+
* Works for both click-release and drag-release.
|
|
366
|
+
*/
|
|
367
|
+
onSphereEraserPointerUp() {
|
|
368
|
+
if (!this.active || this.mode !== "eraser")
|
|
369
|
+
return;
|
|
370
|
+
this.active = false;
|
|
371
|
+
const layer = this.ctx.gui_states.layerChannel.layer;
|
|
372
|
+
const channel = this.ctx.gui_states.layerChannel.activeChannel || 1;
|
|
373
|
+
const axis = this.ctx.protectedData.axis;
|
|
374
|
+
const radius = this.ctx.nrrd_states.sphere.sphereBrushRadius;
|
|
375
|
+
let vol;
|
|
376
|
+
try {
|
|
377
|
+
vol = this.callbacks.getVolumeForLayer(layer);
|
|
378
|
+
}
|
|
379
|
+
catch (_a) {
|
|
380
|
+
this.clearPreview();
|
|
381
|
+
this.dragBeforeSnapshots.clear();
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
// If no drag occurred, erase at the click position (original click-release behavior)
|
|
385
|
+
if (!this.dragMoved) {
|
|
386
|
+
const dims = vol.getDimensions();
|
|
387
|
+
const center = this.canvasToVoxelCenter(this.centerX, this.centerY, this.centerSlice, axis);
|
|
388
|
+
const radii = this.getVoxelRadii(radius);
|
|
389
|
+
const bb = this.getBoundingBox(center, radii, dims);
|
|
390
|
+
this.erase3DSphereFromVolume(vol, center, radii, bb, channel);
|
|
391
|
+
}
|
|
392
|
+
// Build undo group from cumulative "before" snapshots vs current state
|
|
393
|
+
const after = this.captureSliceSnapshots(vol, this.dragMinZ(), this.dragMaxZ());
|
|
394
|
+
const deltas = this.buildUndoGroup(layer, this.dragBeforeSnapshots, after);
|
|
395
|
+
if (deltas.length > 0) {
|
|
396
|
+
this.callbacks.pushUndoGroup(deltas);
|
|
397
|
+
}
|
|
398
|
+
// Refresh display and notify backend of ALL changed slices
|
|
399
|
+
this.refreshDisplay(layer, deltas);
|
|
400
|
+
this.clearPreview();
|
|
401
|
+
this.dragBeforeSnapshots.clear();
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Expand cumulative "before" snapshots to cover z range [minZ, maxZ].
|
|
405
|
+
* Only captures slices not yet in the map (preserves original state).
|
|
406
|
+
*/
|
|
407
|
+
expandDragBeforeSnapshots(vol, minZ, maxZ) {
|
|
408
|
+
for (let z = minZ; z <= maxZ; z++) {
|
|
409
|
+
if (!this.dragBeforeSnapshots.has(z)) {
|
|
410
|
+
try {
|
|
411
|
+
const { data } = vol.getSliceUint8(z, 'z');
|
|
412
|
+
this.dragBeforeSnapshots.set(z, data.slice());
|
|
413
|
+
}
|
|
414
|
+
catch (_a) {
|
|
415
|
+
// slice out of bounds
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
/** Get minimum Z index from drag snapshots */
|
|
421
|
+
dragMinZ() {
|
|
422
|
+
let min = Infinity;
|
|
423
|
+
for (const z of this.dragBeforeSnapshots.keys()) {
|
|
424
|
+
if (z < min)
|
|
425
|
+
min = z;
|
|
426
|
+
}
|
|
427
|
+
return min === Infinity ? 0 : min;
|
|
428
|
+
}
|
|
429
|
+
/** Get maximum Z index from drag snapshots */
|
|
430
|
+
dragMaxZ() {
|
|
431
|
+
let max = -Infinity;
|
|
432
|
+
for (const z of this.dragBeforeSnapshots.keys()) {
|
|
433
|
+
if (z > max)
|
|
434
|
+
max = z;
|
|
435
|
+
}
|
|
436
|
+
return max === -Infinity ? 0 : max;
|
|
437
|
+
}
|
|
438
|
+
// ── Post-write Display Refresh ─────────────────────────────────
|
|
439
|
+
/**
|
|
440
|
+
* After writing/erasing the sphere in the volume, re-render the current
|
|
441
|
+
* slice's layer canvas and composite all layers to master.
|
|
442
|
+
*
|
|
443
|
+
* @param changedDeltas - If provided, fire onMaskChanged for ALL changed
|
|
444
|
+
* slices (not just the current view slice) so the backend receives the
|
|
445
|
+
* full 3D sphere data for NII/GLTF export.
|
|
446
|
+
*/
|
|
447
|
+
refreshDisplay(layerId, changedDeltas) {
|
|
448
|
+
// Re-render layer canvas from volume for the current slice
|
|
449
|
+
const target = this.ctx.protectedData.layerTargets.get(layerId);
|
|
450
|
+
if (target) {
|
|
451
|
+
const { ctx, canvas } = target;
|
|
452
|
+
canvas.width = canvas.width; // clear
|
|
453
|
+
const buffer = this.callbacks.getOrCreateSliceBuffer(this.ctx.protectedData.axis);
|
|
454
|
+
if (buffer) {
|
|
455
|
+
this.callbacks.renderSliceToCanvas(layerId, this.ctx.protectedData.axis, this.ctx.nrrd_states.view.currentSliceIndex, buffer, ctx, this.ctx.nrrd_states.view.changedWidth, this.ctx.nrrd_states.view.changedHeight);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
// Composite all layers to master canvas
|
|
459
|
+
this.callbacks.compositeAllLayers();
|
|
460
|
+
// Fire onMaskChanged for ALL changed slices (not just the current view slice)
|
|
461
|
+
// This ensures the backend receives the full 3D sphere data for export.
|
|
462
|
+
try {
|
|
463
|
+
const vol = this.callbacks.getVolumeForLayer(layerId);
|
|
464
|
+
const channel = this.ctx.gui_states.layerChannel.activeChannel || 1;
|
|
465
|
+
if (changedDeltas && changedDeltas.length > 0) {
|
|
466
|
+
// Report every changed Z slice
|
|
467
|
+
for (const delta of changedDeltas) {
|
|
468
|
+
const { data: sliceData, width, height } = vol.getSliceUint8(delta.sliceIndex, delta.axis);
|
|
469
|
+
this.ctx.callbacks.onMaskChanged(sliceData, layerId, channel, delta.sliceIndex, delta.axis, width, height, false);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
else {
|
|
473
|
+
// Fallback: report only the current slice
|
|
474
|
+
const axis = this.ctx.protectedData.axis;
|
|
475
|
+
const sliceIndex = this.ctx.nrrd_states.view.currentSliceIndex;
|
|
476
|
+
const { data: sliceData, width, height } = vol.getSliceUint8(sliceIndex, axis);
|
|
477
|
+
this.ctx.callbacks.onMaskChanged(sliceData, layerId, channel, sliceIndex, axis, width, height, false);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
catch (_a) {
|
|
481
|
+
// Volume not ready
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
/** Whether a sphere placement is currently in progress */
|
|
485
|
+
get isActive() {
|
|
486
|
+
return this.active;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
//# sourceMappingURL=SphereBrushTool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SphereBrushTool.js","sourceRoot":"","sources":["../../../../src/Utils/segmentation/tools/SphereBrushTool.ts"],"names":[],"mappings":"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"}
|
|
@@ -40,6 +40,7 @@ export interface ToolHost {
|
|
|
40
40
|
image: ImageData;
|
|
41
41
|
} | undefined;
|
|
42
42
|
pushUndoDelta(delta: MaskDelta): void;
|
|
43
|
+
pushUndoGroup(deltas: MaskDelta[]): void;
|
|
43
44
|
getEraserUrls(): string[];
|
|
44
45
|
enableCrosshair(): void;
|
|
45
46
|
setUpSphereOrigins(mouseX: number, mouseY: number, sliceIndex: number): void;
|
|
@@ -72,3 +73,5 @@ export type LayerChannelHostDeps = Pick<ToolHost, 'reloadMasksFromVolume' | 'get
|
|
|
72
73
|
export type SliceRenderHostDeps = Pick<ToolHost, 'compositeAllLayers' | 'getOrCreateSliceBuffer' | 'renderSliceToCanvas' | 'getVolumeForLayer' | 'refreshSphereOverlay' | 'syncGuiParameterSettings' | 'repraintCurrentContrastSlice' | 'clearUndoHistory' | 'updateShowNumDiv' | 'updateCurrentContrastSlice'>;
|
|
73
74
|
/** DataLoader host dependencies */
|
|
74
75
|
export type DataLoaderHostDeps = Pick<ToolHost, 'invalidateSliceBuffer' | 'setDisplaySlicesBaseOnAxis' | 'afterLoadSlice' | 'setEmptyCanvasSize' | 'syncLayerSliceData' | 'reloadMasksFromVolume' | 'resetZoom'>;
|
|
76
|
+
/** SphereBrushTool host dependencies */
|
|
77
|
+
export type SphereBrushHostDeps = Pick<ToolHost, 'getVolumeForLayer' | 'compositeAllLayers' | 'pushUndoGroup' | 'renderSliceToCanvas' | 'getOrCreateSliceBuffer' | 'setEmptyCanvasSize' | 'reloadMasksFromVolume' | 'getEraserUrls'>;
|
|
@@ -16,10 +16,15 @@ export class ZoomTool extends BaseTool {
|
|
|
16
16
|
configMouseZoomWheel() {
|
|
17
17
|
let moveDistance = 1;
|
|
18
18
|
return (e) => {
|
|
19
|
-
var _a;
|
|
19
|
+
var _a, _b;
|
|
20
20
|
if ((_a = this.ctx.eventRouter) === null || _a === void 0 ? void 0 : _a.isShiftHeld()) {
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
|
+
// Block zoom wheel when sphereBrush/sphereEraser is actively placing (left button held)
|
|
24
|
+
if ((this.ctx.gui_states.mode.sphereBrush || this.ctx.gui_states.mode.sphereEraser)
|
|
25
|
+
&& ((_b = this.ctx.eventRouter) === null || _b === void 0 ? void 0 : _b.isLeftButtonDown())) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
23
28
|
e.preventDefault();
|
|
24
29
|
const delta = e.detail ? e.detail > 0 : e.wheelDelta < 0;
|
|
25
30
|
this.ctx.protectedData.isDrawing = true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ZoomTool.js","sourceRoot":"","sources":["../../../../src/Utils/segmentation/tools/ZoomTool.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ZoomTool.js","sourceRoot":"","sources":["../../../../src/Utils/segmentation/tools/ZoomTool.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,13 +8,14 @@
|
|
|
8
8
|
*/
|
|
9
9
|
export { BaseTool } from "./BaseTool";
|
|
10
10
|
export type { ToolContext } from "./BaseTool";
|
|
11
|
-
export type { ToolHost, ImageStoreHostDeps, PanHostDeps, ContrastHostDeps, ZoomHostDeps, SphereHostDeps, DrawingHostDeps, DragSliceHostDeps, LayerChannelHostDeps, SliceRenderHostDeps, DataLoaderHostDeps, } from "./ToolHost";
|
|
11
|
+
export type { ToolHost, ImageStoreHostDeps, PanHostDeps, ContrastHostDeps, ZoomHostDeps, SphereHostDeps, SphereBrushHostDeps, DrawingHostDeps, DragSliceHostDeps, LayerChannelHostDeps, SliceRenderHostDeps, DataLoaderHostDeps, } from "./ToolHost";
|
|
12
12
|
export { EraserTool } from "./EraserTool";
|
|
13
13
|
export { DrawingTool } from "./DrawingTool";
|
|
14
14
|
export { PanTool } from "./PanTool";
|
|
15
15
|
export { ZoomTool } from "./ZoomTool";
|
|
16
16
|
export { SphereTool, SPHERE_CHANNEL_MAP } from "./SphereTool";
|
|
17
17
|
export type { SphereType } from "./SphereTool";
|
|
18
|
+
export { SphereBrushTool } from "./SphereBrushTool";
|
|
18
19
|
export { CrosshairTool } from "./CrosshairTool";
|
|
19
20
|
export { ContrastTool } from "./ContrastTool";
|
|
20
21
|
export { ImageStoreHelper } from "./ImageStoreHelper";
|
|
@@ -17,6 +17,7 @@ export { PanTool } from "./PanTool";
|
|
|
17
17
|
export { ZoomTool } from "./ZoomTool";
|
|
18
18
|
// Specialty Tools
|
|
19
19
|
export { SphereTool, SPHERE_CHANNEL_MAP } from "./SphereTool";
|
|
20
|
+
export { SphereBrushTool } from "./SphereBrushTool";
|
|
20
21
|
export { CrosshairTool } from "./CrosshairTool";
|
|
21
22
|
export { ContrastTool } from "./ContrastTool";
|
|
22
23
|
// Image Storage
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/Utils/segmentation/tools/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO;AACP,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/Utils/segmentation/tools/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO;AACP,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAmBtC,gBAAgB;AAChB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,mBAAmB;AACnB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,qBAAqB;AACrB,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,kBAAkB;AAClB,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAE9D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,gBAAgB;AAChB,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,wBAAwB;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,6BAA6B;AAC7B,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,wBAAwB;AACxB,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,eAAe;AACf,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC"}
|