copper3d 3.0.1 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +197 -875
- package/dist/Utils/segmentation/CanvasState.d.ts +31 -0
- package/dist/Utils/segmentation/CanvasState.js +167 -0
- package/dist/Utils/segmentation/CanvasState.js.map +1 -0
- package/dist/Utils/segmentation/DragOperator.d.ts +10 -2
- package/dist/Utils/segmentation/DragOperator.js +16 -8
- package/dist/Utils/segmentation/DragOperator.js.map +1 -1
- package/dist/Utils/segmentation/DrawToolCore.d.ts +64 -35
- package/dist/Utils/segmentation/DrawToolCore.js +332 -584
- package/dist/Utils/segmentation/DrawToolCore.js.map +1 -1
- package/dist/Utils/segmentation/NrrdTools.d.ts +117 -353
- package/dist/Utils/segmentation/NrrdTools.js +622 -1081
- package/dist/Utils/segmentation/NrrdTools.js.map +1 -1
- package/dist/Utils/segmentation/RenderingUtils.d.ts +73 -0
- package/dist/Utils/segmentation/RenderingUtils.js +180 -0
- package/dist/Utils/segmentation/RenderingUtils.js.map +1 -0
- package/dist/Utils/segmentation/core/MaskVolume.js +23 -2
- 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 +1 -3
- 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.d.ts +384 -0
- package/dist/Utils/segmentation/core/types.js +25 -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/divControlTools.d.ts +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/ContrastTool.d.ts +3 -6
- package/dist/Utils/segmentation/tools/ContrastTool.js.map +1 -1
- package/dist/Utils/segmentation/tools/CrosshairTool.d.ts +11 -1
- package/dist/Utils/segmentation/tools/CrosshairTool.js +50 -25
- package/dist/Utils/segmentation/tools/CrosshairTool.js.map +1 -1
- package/dist/Utils/segmentation/tools/DataLoader.d.ts +33 -0
- package/dist/Utils/segmentation/tools/DataLoader.js +159 -0
- package/dist/Utils/segmentation/tools/DataLoader.js.map +1 -0
- package/dist/Utils/segmentation/tools/DragSliceTool.d.ts +3 -10
- 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 +85 -0
- package/dist/Utils/segmentation/tools/DrawingTool.js +270 -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 +13 -33
- package/dist/Utils/segmentation/tools/ImageStoreHelper.js +39 -82
- package/dist/Utils/segmentation/tools/ImageStoreHelper.js.map +1 -1
- package/dist/Utils/segmentation/tools/LayerChannelManager.d.ts +52 -0
- package/dist/Utils/segmentation/tools/LayerChannelManager.js +175 -0
- package/dist/Utils/segmentation/tools/LayerChannelManager.js.map +1 -0
- package/dist/Utils/segmentation/tools/PanTool.d.ts +47 -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/SliceRenderPipeline.d.ts +80 -0
- package/dist/Utils/segmentation/tools/SliceRenderPipeline.js +355 -0
- package/dist/Utils/segmentation/tools/SliceRenderPipeline.js.map +1 -0
- package/dist/Utils/segmentation/tools/SphereTool.d.ts +223 -10
- package/dist/Utils/segmentation/tools/SphereTool.js +512 -47
- package/dist/Utils/segmentation/tools/SphereTool.js.map +1 -1
- package/dist/Utils/segmentation/tools/ToolHost.d.ts +74 -0
- package/dist/Utils/segmentation/tools/ToolHost.js +10 -0
- package/dist/Utils/segmentation/tools/ToolHost.js.map +1 -0
- package/dist/Utils/segmentation/tools/ZoomTool.d.ts +2 -6
- 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 +8 -6
- package/dist/Utils/segmentation/tools/index.js +10 -1
- package/dist/Utils/segmentation/tools/index.js.map +1 -1
- package/dist/Utils/workers/reformatSaveDataWorker.d.ts +1 -1
- package/dist/bundle.esm.js +3729 -3017
- package/dist/bundle.umd.js +3729 -3017
- 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/CanvasState.d.ts +31 -0
- package/dist/types/Utils/segmentation/DragOperator.d.ts +10 -2
- package/dist/types/Utils/segmentation/DrawToolCore.d.ts +64 -35
- package/dist/types/Utils/segmentation/NrrdTools.d.ts +117 -353
- package/dist/types/Utils/segmentation/RenderingUtils.d.ts +73 -0
- package/dist/types/Utils/segmentation/core/UndoManager.d.ts +1 -1
- package/dist/types/Utils/segmentation/core/index.d.ts +1 -3
- package/dist/types/Utils/segmentation/core/types.d.ts +384 -0
- 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/divControlTools.d.ts +1 -1
- 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/ContrastTool.d.ts +3 -6
- package/dist/types/Utils/segmentation/tools/CrosshairTool.d.ts +11 -1
- package/dist/types/Utils/segmentation/tools/DataLoader.d.ts +33 -0
- package/dist/types/Utils/segmentation/tools/DragSliceTool.d.ts +3 -10
- package/dist/types/Utils/segmentation/tools/DrawingTool.d.ts +85 -0
- package/dist/types/Utils/segmentation/tools/ImageStoreHelper.d.ts +13 -33
- package/dist/types/Utils/segmentation/tools/LayerChannelManager.d.ts +52 -0
- package/dist/types/Utils/segmentation/tools/PanTool.d.ts +47 -0
- package/dist/types/Utils/segmentation/tools/SliceRenderPipeline.d.ts +80 -0
- package/dist/types/Utils/segmentation/tools/SphereTool.d.ts +223 -10
- package/dist/types/Utils/segmentation/tools/ToolHost.d.ts +74 -0
- package/dist/types/Utils/segmentation/tools/ZoomTool.d.ts +2 -6
- package/dist/types/Utils/segmentation/tools/index.d.ts +8 -6
- package/dist/types/Utils/workers/reformatSaveDataWorker.d.ts +1 -1
- package/dist/types/index.d.ts +6 -3
- package/package.json +1 -1
- package/dist/Utils/segmentation/CommToolsData.d.ts +0 -177
- package/dist/Utils/segmentation/CommToolsData.js +0 -548
- package/dist/Utils/segmentation/CommToolsData.js.map +0 -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/Utils/segmentation/coreTools/coreType.d.ts +0 -363
- package/dist/Utils/segmentation/coreTools/coreType.js +0 -3
- package/dist/Utils/segmentation/coreTools/coreType.js.map +0 -1
- package/dist/types/Utils/segmentation/CommToolsData.d.ts +0 -177
- package/dist/types/Utils/segmentation/core/MigrationUtils.d.ts +0 -97
- package/dist/types/Utils/segmentation/coreTools/coreType.d.ts +0 -363
|
@@ -23,16 +23,17 @@ export class DragSliceTool extends BaseTool {
|
|
|
23
23
|
updateIndex(move) {
|
|
24
24
|
let sliceModifyNum = 0;
|
|
25
25
|
let contrastModifyNum = 0;
|
|
26
|
-
const
|
|
27
|
-
|
|
26
|
+
const view = this.ctx.nrrd_states.view;
|
|
27
|
+
const image = this.ctx.nrrd_states.image;
|
|
28
|
+
if (view.showContrast) {
|
|
28
29
|
contrastModifyNum = move % this.ctx.protectedData.displaySlices.length;
|
|
29
|
-
|
|
30
|
+
view.contrastNum += contrastModifyNum;
|
|
30
31
|
if (move > 0) {
|
|
31
|
-
if (
|
|
32
|
+
if (view.currentSliceIndex <= view.maxIndex) {
|
|
32
33
|
sliceModifyNum = Math.floor(move / this.ctx.protectedData.displaySlices.length);
|
|
33
|
-
if (
|
|
34
|
+
if (view.contrastNum > this.ctx.protectedData.displaySlices.length - 1) {
|
|
34
35
|
sliceModifyNum += 1;
|
|
35
|
-
|
|
36
|
+
view.contrastNum -= this.ctx.protectedData.displaySlices.length;
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
39
|
else {
|
|
@@ -41,8 +42,8 @@ export class DragSliceTool extends BaseTool {
|
|
|
41
42
|
}
|
|
42
43
|
else {
|
|
43
44
|
sliceModifyNum = Math.ceil(move / this.ctx.protectedData.displaySlices.length);
|
|
44
|
-
if (
|
|
45
|
-
|
|
45
|
+
if (view.contrastNum < 0) {
|
|
46
|
+
view.contrastNum += this.ctx.protectedData.displaySlices.length;
|
|
46
47
|
sliceModifyNum -= 1;
|
|
47
48
|
}
|
|
48
49
|
}
|
|
@@ -50,65 +51,74 @@ export class DragSliceTool extends BaseTool {
|
|
|
50
51
|
else {
|
|
51
52
|
sliceModifyNum = move;
|
|
52
53
|
}
|
|
53
|
-
let newIndex =
|
|
54
|
-
if (newIndex !=
|
|
55
|
-
if (newIndex >
|
|
56
|
-
newIndex =
|
|
57
|
-
|
|
54
|
+
let newIndex = view.currentSliceIndex + sliceModifyNum;
|
|
55
|
+
if (newIndex != view.currentSliceIndex || view.showContrast) {
|
|
56
|
+
if (newIndex > view.maxIndex) {
|
|
57
|
+
newIndex = view.maxIndex;
|
|
58
|
+
view.contrastNum = this.ctx.protectedData.displaySlices.length - 1;
|
|
58
59
|
}
|
|
59
|
-
else if (newIndex <
|
|
60
|
-
newIndex =
|
|
61
|
-
|
|
60
|
+
else if (newIndex < view.minIndex) {
|
|
61
|
+
newIndex = view.minIndex;
|
|
62
|
+
view.contrastNum = 0;
|
|
62
63
|
}
|
|
63
64
|
else {
|
|
64
|
-
this.ctx.protectedData.mainPreSlices.index = newIndex *
|
|
65
|
+
this.ctx.protectedData.mainPreSlices.index = newIndex * image.RSARatio;
|
|
65
66
|
this.callbacks.setSyncsliceNum();
|
|
66
67
|
let isSameIndex = true;
|
|
67
|
-
if (newIndex !=
|
|
68
|
-
|
|
68
|
+
if (newIndex != view.currentSliceIndex) {
|
|
69
|
+
view.switchSliceFlag = true;
|
|
69
70
|
isSameIndex = false;
|
|
70
71
|
}
|
|
71
72
|
this.cleanCanvases(isSameIndex);
|
|
72
|
-
if (
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
if (view.changedWidth === 0) {
|
|
74
|
+
view.changedWidth = image.originWidth;
|
|
75
|
+
view.changedHeight = image.originHeight;
|
|
75
76
|
}
|
|
76
77
|
const needToUpdateSlice = this.updateCurrentContrastSlice();
|
|
77
78
|
needToUpdateSlice.repaint.call(needToUpdateSlice);
|
|
78
|
-
|
|
79
|
+
view.currentSliceIndex = newIndex;
|
|
79
80
|
this.drawDragSlice(needToUpdateSlice.canvas);
|
|
80
81
|
}
|
|
81
|
-
|
|
82
|
-
this.updateShowNumDiv(
|
|
82
|
+
view.preSliceIndex = newIndex * image.RSARatio;
|
|
83
|
+
this.updateShowNumDiv(view.contrastNum);
|
|
83
84
|
}
|
|
84
85
|
}
|
|
85
86
|
// ===== Draw Drag Slice =====
|
|
86
87
|
drawDragSlice(canvas) {
|
|
87
|
-
|
|
88
|
+
var _a, _b;
|
|
89
|
+
const view = this.ctx.nrrd_states.view;
|
|
88
90
|
// Draw base image (CT/MRI scan)
|
|
89
91
|
this.ctx.protectedData.ctxes.displayCtx.save();
|
|
90
92
|
this.callbacks.flipDisplayImageByAxis();
|
|
91
|
-
this.ctx.protectedData.ctxes.displayCtx.drawImage(canvas, 0, 0,
|
|
93
|
+
this.ctx.protectedData.ctxes.displayCtx.drawImage(canvas, 0, 0, view.changedWidth, view.changedHeight);
|
|
92
94
|
this.ctx.protectedData.ctxes.displayCtx.restore();
|
|
93
95
|
// Phase 3: Draw ALL layers from MaskVolume (multi-layer compositing)
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
96
|
+
// Skip layer mask rendering when sphere mode is active —
|
|
97
|
+
// layer masks should remain hidden until the user exits sphere mode.
|
|
98
|
+
if (view.switchSliceFlag) {
|
|
99
|
+
if (!this.ctx.gui_states.mode.sphere) {
|
|
100
|
+
const axis = this.ctx.protectedData.axis;
|
|
101
|
+
const sliceIndex = view.currentSliceIndex;
|
|
102
|
+
// Get a single reusable buffer — shared across all layer renders
|
|
103
|
+
const buffer = this.callbacks.getOrCreateSliceBuffer(axis);
|
|
104
|
+
if (buffer) {
|
|
105
|
+
const w = view.changedWidth;
|
|
106
|
+
const h = view.changedHeight;
|
|
107
|
+
for (const layerId of this.ctx.nrrd_states.image.layers) {
|
|
108
|
+
const target = this.ctx.protectedData.layerTargets.get(layerId);
|
|
109
|
+
if (target) {
|
|
110
|
+
this.callbacks.renderSliceToCanvas(layerId, axis, sliceIndex, buffer, target.ctx, w, h);
|
|
111
|
+
}
|
|
106
112
|
}
|
|
107
113
|
}
|
|
114
|
+
// Composite all layers to master canvas
|
|
115
|
+
this.compositeAllLayers();
|
|
108
116
|
}
|
|
109
|
-
//
|
|
110
|
-
this.
|
|
111
|
-
|
|
117
|
+
// Refresh sphere overlay from volume for the new slice
|
|
118
|
+
if (this.ctx.gui_states.mode.sphere) {
|
|
119
|
+
(_b = (_a = this.callbacks).refreshSphereOverlay) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
120
|
+
}
|
|
121
|
+
view.switchSliceFlag = false;
|
|
112
122
|
}
|
|
113
123
|
}
|
|
114
124
|
/**
|
|
@@ -116,12 +126,12 @@ export class DragSliceTool extends BaseTool {
|
|
|
116
126
|
*/
|
|
117
127
|
compositeAllLayers() {
|
|
118
128
|
const masterCtx = this.ctx.protectedData.ctxes.drawingLayerMasterCtx;
|
|
119
|
-
const width = this.ctx.nrrd_states.changedWidth;
|
|
120
|
-
const height = this.ctx.nrrd_states.changedHeight;
|
|
129
|
+
const width = this.ctx.nrrd_states.view.changedWidth;
|
|
130
|
+
const height = this.ctx.nrrd_states.view.changedHeight;
|
|
121
131
|
masterCtx.clearRect(0, 0, width, height);
|
|
122
132
|
// Master stores full-alpha composite; globalAlpha applied in start() render loop.
|
|
123
|
-
for (const layerId of this.ctx.nrrd_states.layers) {
|
|
124
|
-
if (!this.ctx.gui_states.layerVisibility[layerId])
|
|
133
|
+
for (const layerId of this.ctx.nrrd_states.image.layers) {
|
|
134
|
+
if (!this.ctx.gui_states.layerChannel.layerVisibility[layerId])
|
|
125
135
|
continue;
|
|
126
136
|
const target = this.ctx.protectedData.layerTargets.get(layerId);
|
|
127
137
|
if (target)
|
|
@@ -149,21 +159,21 @@ export class DragSliceTool extends BaseTool {
|
|
|
149
159
|
// ===== UI Updates =====
|
|
150
160
|
updateShowNumDiv(contrastNum) {
|
|
151
161
|
if (this.ctx.protectedData.mainPreSlices) {
|
|
152
|
-
const
|
|
153
|
-
if (
|
|
154
|
-
|
|
162
|
+
const view = this.ctx.nrrd_states.view;
|
|
163
|
+
if (view.currentSliceIndex > view.maxIndex) {
|
|
164
|
+
view.currentSliceIndex = view.maxIndex;
|
|
155
165
|
}
|
|
156
|
-
if (
|
|
157
|
-
this.showDragNumberDiv.innerHTML = `ContrastNum: ${contrastNum}/${this.ctx.protectedData.displaySlices.length - 1} SliceNum: ${
|
|
166
|
+
if (view.showContrast) {
|
|
167
|
+
this.showDragNumberDiv.innerHTML = `ContrastNum: ${contrastNum}/${this.ctx.protectedData.displaySlices.length - 1} SliceNum: ${view.currentSliceIndex}/${view.maxIndex}`;
|
|
158
168
|
}
|
|
159
169
|
else {
|
|
160
|
-
this.showDragNumberDiv.innerHTML = `SliceNum: ${
|
|
170
|
+
this.showDragNumberDiv.innerHTML = `SliceNum: ${view.currentSliceIndex}/${view.maxIndex}`;
|
|
161
171
|
}
|
|
162
172
|
}
|
|
163
173
|
}
|
|
164
174
|
updateCurrentContrastSlice() {
|
|
165
175
|
this.ctx.protectedData.currentShowingSlice =
|
|
166
|
-
this.ctx.protectedData.displaySlices[this.ctx.nrrd_states.contrastNum];
|
|
176
|
+
this.ctx.protectedData.displaySlices[this.ctx.nrrd_states.view.contrastNum];
|
|
167
177
|
return this.ctx.protectedData.currentShowingSlice;
|
|
168
178
|
}
|
|
169
179
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DragSliceTool.js","sourceRoot":"","sources":["../../../../src/Utils/segmentation/tools/DragSliceTool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"DragSliceTool.js","sourceRoot":"","sources":["../../../../src/Utils/segmentation/tools/DragSliceTool.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
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 type { ToolContext } from "./BaseTool";
|
|
10
|
+
import type { DrawingHostDeps } from "./ToolHost";
|
|
11
|
+
export declare class DrawingTool extends BaseTool {
|
|
12
|
+
/** Left mouse button currently held (draw mode) */
|
|
13
|
+
private leftClicked;
|
|
14
|
+
/** True while actively painting (between pointerdown and pointerup) */
|
|
15
|
+
private isPainting;
|
|
16
|
+
/** Accumulated pencil stroke points for fill-on-release */
|
|
17
|
+
private drawingLines;
|
|
18
|
+
/** Eraser arc function, assigned once per paintOnCanvas() call */
|
|
19
|
+
private clearArcFn;
|
|
20
|
+
/** Snapshot of the active layer's slice captured on mouse-down (before drawing) */
|
|
21
|
+
private preDrawSlice;
|
|
22
|
+
private preDrawAxis;
|
|
23
|
+
private preDrawSliceIndex;
|
|
24
|
+
private callbacks;
|
|
25
|
+
constructor(ctx: ToolContext, callbacks: DrawingHostDeps);
|
|
26
|
+
/** Whether a draw operation is currently active */
|
|
27
|
+
get isActive(): boolean;
|
|
28
|
+
/** Whether paint strokes are being recorded */
|
|
29
|
+
get painting(): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Reset drawing state. Called at start of each paintOnCanvas() cycle.
|
|
32
|
+
* @param clearArcFn - Eraser function for this paint cycle
|
|
33
|
+
*/
|
|
34
|
+
reset(clearArcFn: (x: number, y: number, size: number) => void): void;
|
|
35
|
+
/**
|
|
36
|
+
* Called on left-click pointerdown in draw mode.
|
|
37
|
+
* Sets up drawing state, cursor, undo snapshot, and start position.
|
|
38
|
+
*/
|
|
39
|
+
onPointerDown(e: MouseEvent): void;
|
|
40
|
+
/**
|
|
41
|
+
* Called on pointermove during an active drawing operation.
|
|
42
|
+
* Handles eraser clearing or brush/pencil stroke accumulation.
|
|
43
|
+
*/
|
|
44
|
+
onPointerMove(e: MouseEvent): void;
|
|
45
|
+
/**
|
|
46
|
+
* Called on pointerup in draw mode.
|
|
47
|
+
* Completes stroke, fills pencil path, syncs volume, pushes undo delta.
|
|
48
|
+
*/
|
|
49
|
+
onPointerUp(_e: MouseEvent): void;
|
|
50
|
+
/**
|
|
51
|
+
* Called on pointerleave during drawing.
|
|
52
|
+
* Resets painting state and cleans up leftClicked.
|
|
53
|
+
* @returns true if drawing was in progress when leave occurred
|
|
54
|
+
*/
|
|
55
|
+
onPointerLeave(): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Create a self-managing mouseover/mouseout/mousemove handler
|
|
58
|
+
* that tracks brush hover position for the preview circle.
|
|
59
|
+
*
|
|
60
|
+
* The returned function should be registered on drawingCanvas for
|
|
61
|
+
* "mouseover" and "mouseout" events. It adds/removes a "mousemove"
|
|
62
|
+
* listener on itself to keep mouseOverX/Y up-to-date while the
|
|
63
|
+
* cursor is inside the canvas.
|
|
64
|
+
*/
|
|
65
|
+
createBrushTrackingHandler(): (e: MouseEvent) => void;
|
|
66
|
+
/**
|
|
67
|
+
* Render brush circle preview on the drawing context.
|
|
68
|
+
* Called from the start() render loop when in draw mode and not
|
|
69
|
+
* actively painting. Skipped in pencil/eraser mode.
|
|
70
|
+
*/
|
|
71
|
+
renderBrushPreview(ctx: CanvasRenderingContext2D, width: number, height: number): void;
|
|
72
|
+
/** Capture pre-draw slice snapshot for undo */
|
|
73
|
+
private capturePreDrawSnapshot;
|
|
74
|
+
/** Push delta to UndoManager after drawing completes */
|
|
75
|
+
private pushUndoDelta;
|
|
76
|
+
/**
|
|
77
|
+
* Redraws persisted layer data onto ctx before new pencil fill.
|
|
78
|
+
* Extracted from DrawToolCore.
|
|
79
|
+
*/
|
|
80
|
+
private redrawPreviousImageToLayerCtx;
|
|
81
|
+
/** Draw a line segment on a layer canvas */
|
|
82
|
+
private drawLinesOnLayer;
|
|
83
|
+
/** Paint a segment on the current layer canvas and composite to master */
|
|
84
|
+
private paintOnCanvasLayer;
|
|
85
|
+
}
|
|
@@ -0,0 +1,270 @@
|
|
|
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
|
+
// ── Brush hover tracking & preview ──────────────────────────
|
|
137
|
+
/**
|
|
138
|
+
* Create a self-managing mouseover/mouseout/mousemove handler
|
|
139
|
+
* that tracks brush hover position for the preview circle.
|
|
140
|
+
*
|
|
141
|
+
* The returned function should be registered on drawingCanvas for
|
|
142
|
+
* "mouseover" and "mouseout" events. It adds/removes a "mousemove"
|
|
143
|
+
* listener on itself to keep mouseOverX/Y up-to-date while the
|
|
144
|
+
* cursor is inside the canvas.
|
|
145
|
+
*/
|
|
146
|
+
createBrushTrackingHandler() {
|
|
147
|
+
const handler = (e) => {
|
|
148
|
+
e.preventDefault();
|
|
149
|
+
this.ctx.nrrd_states.interaction.mouseOverX = e.offsetX;
|
|
150
|
+
this.ctx.nrrd_states.interaction.mouseOverY = e.offsetY;
|
|
151
|
+
if (this.ctx.nrrd_states.interaction.mouseOverX === undefined) {
|
|
152
|
+
this.ctx.nrrd_states.interaction.mouseOverX = e.clientX;
|
|
153
|
+
this.ctx.nrrd_states.interaction.mouseOverY = e.clientY;
|
|
154
|
+
}
|
|
155
|
+
if (e.type === "mouseout") {
|
|
156
|
+
this.ctx.nrrd_states.interaction.mouseOver = false;
|
|
157
|
+
this.ctx.protectedData.canvases.drawingCanvas.removeEventListener("mousemove", handler);
|
|
158
|
+
}
|
|
159
|
+
else if (e.type === "mouseover") {
|
|
160
|
+
this.ctx.nrrd_states.interaction.mouseOver = true;
|
|
161
|
+
this.ctx.protectedData.canvases.drawingCanvas.addEventListener("mousemove", handler);
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
return handler;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Render brush circle preview on the drawing context.
|
|
168
|
+
* Called from the start() render loop when in draw mode and not
|
|
169
|
+
* actively painting. Skipped in pencil/eraser mode.
|
|
170
|
+
*/
|
|
171
|
+
renderBrushPreview(ctx, width, height) {
|
|
172
|
+
if (this.ctx.gui_states.mode.pencil ||
|
|
173
|
+
this.ctx.gui_states.mode.eraser ||
|
|
174
|
+
!this.ctx.nrrd_states.interaction.mouseOver) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
ctx.clearRect(0, 0, width, height);
|
|
178
|
+
ctx.fillStyle = this.ctx.gui_states.drawing.brushColor;
|
|
179
|
+
ctx.beginPath();
|
|
180
|
+
ctx.arc(this.ctx.nrrd_states.interaction.mouseOverX, this.ctx.nrrd_states.interaction.mouseOverY, this.ctx.gui_states.drawing.brushAndEraserSize / 2 + 1, 0, Math.PI * 2);
|
|
181
|
+
ctx.strokeStyle = this.ctx.gui_states.drawing.brushColor;
|
|
182
|
+
ctx.stroke();
|
|
183
|
+
}
|
|
184
|
+
// ── Private helpers ────────────────────────────────────────
|
|
185
|
+
/** Capture pre-draw slice snapshot for undo */
|
|
186
|
+
capturePreDrawSnapshot() {
|
|
187
|
+
try {
|
|
188
|
+
this.preDrawAxis = this.ctx.protectedData.axis;
|
|
189
|
+
this.preDrawSliceIndex = this.ctx.nrrd_states.view.currentSliceIndex;
|
|
190
|
+
const vol = this.callbacks.getVolumeForLayer(this.ctx.gui_states.layerChannel.layer);
|
|
191
|
+
this.preDrawSlice = vol.getSliceUint8(this.preDrawSliceIndex, this.preDrawAxis).data.slice();
|
|
192
|
+
}
|
|
193
|
+
catch (_a) {
|
|
194
|
+
this.preDrawSlice = null;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/** Push delta to UndoManager after drawing completes */
|
|
198
|
+
pushUndoDelta() {
|
|
199
|
+
if (!this.preDrawSlice)
|
|
200
|
+
return;
|
|
201
|
+
try {
|
|
202
|
+
const vol = this.callbacks.getVolumeForLayer(this.ctx.gui_states.layerChannel.layer);
|
|
203
|
+
const { data: newSlice } = vol.getSliceUint8(this.preDrawSliceIndex, this.preDrawAxis);
|
|
204
|
+
const delta = {
|
|
205
|
+
layerId: this.ctx.gui_states.layerChannel.layer,
|
|
206
|
+
axis: this.preDrawAxis,
|
|
207
|
+
sliceIndex: this.preDrawSliceIndex,
|
|
208
|
+
oldSlice: this.preDrawSlice,
|
|
209
|
+
newSlice: newSlice.slice(),
|
|
210
|
+
};
|
|
211
|
+
this.callbacks.pushUndoDelta(delta);
|
|
212
|
+
}
|
|
213
|
+
catch (_a) {
|
|
214
|
+
// Volume not ready — skip
|
|
215
|
+
}
|
|
216
|
+
this.preDrawSlice = null;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Redraws persisted layer data onto ctx before new pencil fill.
|
|
220
|
+
* Extracted from DrawToolCore.
|
|
221
|
+
*/
|
|
222
|
+
redrawPreviousImageToLayerCtx(ctx) {
|
|
223
|
+
var _a;
|
|
224
|
+
const tempPreImg = (_a = this.callbacks.filterDrawedImage(this.ctx.protectedData.axis, this.ctx.nrrd_states.view.currentSliceIndex)) === null || _a === void 0 ? void 0 : _a.image;
|
|
225
|
+
this.ctx.protectedData.canvases.emptyCanvas.width =
|
|
226
|
+
this.ctx.protectedData.canvases.emptyCanvas.width;
|
|
227
|
+
this.ctx.protectedData.ctxes.emptyCtx.putImageData(tempPreImg, 0, 0);
|
|
228
|
+
ctx.imageSmoothingEnabled = false;
|
|
229
|
+
// Coronal (axis='y') Z-flip: same as renderSliceToCanvas.
|
|
230
|
+
if (this.ctx.protectedData.axis === 'y') {
|
|
231
|
+
ctx.save();
|
|
232
|
+
ctx.scale(1, -1);
|
|
233
|
+
ctx.translate(0, -this.ctx.nrrd_states.view.changedHeight);
|
|
234
|
+
}
|
|
235
|
+
ctx.drawImage(this.ctx.protectedData.canvases.emptyCanvas, 0, 0, this.ctx.nrrd_states.view.changedWidth, this.ctx.nrrd_states.view.changedHeight);
|
|
236
|
+
if (this.ctx.protectedData.axis === 'y') {
|
|
237
|
+
ctx.restore();
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
/** Draw a line segment on a layer canvas */
|
|
241
|
+
drawLinesOnLayer(ctx, x, y) {
|
|
242
|
+
ctx.beginPath();
|
|
243
|
+
ctx.moveTo(this.ctx.nrrd_states.interaction.drawStartPos.x, this.ctx.nrrd_states.interaction.drawStartPos.y);
|
|
244
|
+
if (this.ctx.gui_states.mode.pencil) {
|
|
245
|
+
ctx.strokeStyle = this.ctx.gui_states.drawing.color;
|
|
246
|
+
ctx.lineWidth = this.ctx.gui_states.drawing.lineWidth;
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
ctx.strokeStyle = this.ctx.gui_states.drawing.brushColor;
|
|
250
|
+
ctx.lineWidth = this.ctx.gui_states.drawing.brushAndEraserSize;
|
|
251
|
+
}
|
|
252
|
+
ctx.lineTo(x, y);
|
|
253
|
+
ctx.stroke();
|
|
254
|
+
ctx.closePath();
|
|
255
|
+
}
|
|
256
|
+
/** Paint a segment on the current layer canvas and composite to master */
|
|
257
|
+
paintOnCanvasLayer(x, y) {
|
|
258
|
+
const { ctx } = this.callbacks.setCurrentLayer();
|
|
259
|
+
// Draw only on the current layer canvas (not master directly)
|
|
260
|
+
this.drawLinesOnLayer(ctx, x, y);
|
|
261
|
+
// Composite all layers to master to preserve other layers' data
|
|
262
|
+
this.callbacks.compositeAllLayers();
|
|
263
|
+
// Reset drawing start position to current position
|
|
264
|
+
this.ctx.nrrd_states.interaction.drawStartPos.x = x;
|
|
265
|
+
this.ctx.nrrd_states.interaction.drawStartPos.y = y;
|
|
266
|
+
// Flag the map as needing updating
|
|
267
|
+
this.ctx.protectedData.mainPreSlices.mesh.material.map.needsUpdate = true;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
//# 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)
|