copper3d 1.15.23 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/README.md +2 -2
  2. package/dist/Loader/copperNrrdLoader.d.ts +1 -1
  3. package/dist/Renderer/baseRenderer.d.ts +2 -2
  4. package/dist/Renderer/baseRenderer.js +2 -2
  5. package/dist/Renderer/baseRenderer.js.map +1 -1
  6. package/dist/Renderer/copperMSceneRenderer.d.ts +2 -2
  7. package/dist/Renderer/copperMSceneRenderer.js +2 -2
  8. package/dist/Renderer/copperMSceneRenderer.js.map +1 -1
  9. package/dist/Renderer/copperRenderer.d.ts +4 -4
  10. package/dist/Renderer/copperRenderer.js +3 -3
  11. package/dist/Renderer/copperRenderer.js.map +1 -1
  12. package/dist/Renderer/copperRendererOnDemond.d.ts +4 -5
  13. package/dist/Renderer/copperRendererOnDemond.js +3 -3
  14. package/dist/Renderer/copperRendererOnDemond.js.map +1 -1
  15. package/dist/Scene/baseScene.d.ts +2 -2
  16. package/dist/Scene/baseScene.js +2 -2
  17. package/dist/Scene/baseScene.js.map +1 -1
  18. package/dist/Scene/commonSceneMethod.d.ts +1 -1
  19. package/dist/Scene/commonSceneMethod.js +1 -1
  20. package/dist/Scene/commonSceneMethod.js.map +1 -1
  21. package/dist/Scene/copperMScene.d.ts +2 -2
  22. package/dist/Scene/copperMScene.js +2 -2
  23. package/dist/Scene/copperMScene.js.map +1 -1
  24. package/dist/Scene/copperScene.d.ts +2 -2
  25. package/dist/Scene/copperScene.js +2 -2
  26. package/dist/Scene/copperScene.js.map +1 -1
  27. package/dist/Scene/copperSceneOnDemond.d.ts +2 -2
  28. package/dist/Scene/copperSceneOnDemond.js +2 -2
  29. package/dist/Scene/copperSceneOnDemond.js.map +1 -1
  30. package/dist/Utils/add3DLabel.d.ts +2 -2
  31. package/dist/Utils/segmentation/CommToolsData.d.ts +71 -0
  32. package/dist/Utils/segmentation/CommToolsData.js +267 -0
  33. package/dist/Utils/segmentation/CommToolsData.js.map +1 -0
  34. package/dist/Utils/segmentation/DragOperator.d.ts +30 -0
  35. package/dist/Utils/segmentation/DragOperator.js +243 -0
  36. package/dist/Utils/segmentation/DragOperator.js.map +1 -0
  37. package/dist/Utils/segmentation/DrawToolCore.d.ts +78 -0
  38. package/dist/Utils/segmentation/DrawToolCore.js +1083 -0
  39. package/dist/Utils/segmentation/DrawToolCore.js.map +1 -0
  40. package/dist/Utils/segmentation/NrrdTools.d.ts +178 -0
  41. package/dist/Utils/segmentation/NrrdTools.js +965 -0
  42. package/dist/Utils/segmentation/NrrdTools.js.map +1 -0
  43. package/dist/Utils/segmentation/coreTools/archive.d.ts +1 -0
  44. package/dist/Utils/segmentation/coreTools/archive.js +23 -0
  45. package/dist/Utils/segmentation/coreTools/archive.js.map +1 -0
  46. package/dist/Utils/segmentation/coreTools/coreType.d.ts +206 -0
  47. package/dist/Utils/segmentation/coreTools/coreType.js +2 -0
  48. package/dist/Utils/segmentation/coreTools/coreType.js.map +1 -0
  49. package/dist/Utils/segmentation/coreTools/divControlTools.d.ts +19 -0
  50. package/dist/Utils/segmentation/coreTools/divControlTools.js +48 -0
  51. package/dist/Utils/segmentation/coreTools/divControlTools.js.map +1 -0
  52. package/dist/Utils/segmentation/coreTools/gui.d.ts +123 -0
  53. package/dist/Utils/segmentation/coreTools/gui.js +306 -0
  54. package/dist/Utils/segmentation/coreTools/gui.js.map +1 -0
  55. package/dist/Utils/utils.d.ts +1 -1
  56. package/dist/Utils/utils.js +25 -10
  57. package/dist/Utils/utils.js.map +1 -1
  58. package/dist/Utils/workers/reformatSaveDataWorker.d.ts +3 -3
  59. package/dist/Utils/workers/reformatSaveDataWorker.js.map +1 -1
  60. package/dist/bundle.esm.js +2576 -2228
  61. package/dist/bundle.umd.js +2577 -2228
  62. package/dist/css/style.css +2 -18
  63. package/dist/index.d.ts +13 -11
  64. package/dist/index.js +11 -10
  65. package/dist/index.js.map +1 -1
  66. package/dist/types/Loader/copperNrrdLoader.d.ts +1 -1
  67. package/dist/types/Renderer/baseRenderer.d.ts +2 -2
  68. package/dist/types/Renderer/copperMSceneRenderer.d.ts +2 -2
  69. package/dist/types/Renderer/copperRenderer.d.ts +4 -4
  70. package/dist/types/Renderer/copperRendererOnDemond.d.ts +4 -5
  71. package/dist/types/Scene/baseScene.d.ts +2 -2
  72. package/dist/types/Scene/commonSceneMethod.d.ts +1 -1
  73. package/dist/types/Scene/copperMScene.d.ts +2 -2
  74. package/dist/types/Scene/copperScene.d.ts +2 -2
  75. package/dist/types/Scene/copperSceneOnDemond.d.ts +2 -2
  76. package/dist/types/Utils/add3DLabel.d.ts +2 -2
  77. package/dist/types/Utils/segmentation/CommToolsData.d.ts +71 -0
  78. package/dist/types/Utils/segmentation/DragOperator.d.ts +30 -0
  79. package/dist/types/Utils/segmentation/DrawToolCore.d.ts +78 -0
  80. package/dist/types/Utils/segmentation/NrrdTools.d.ts +178 -0
  81. package/dist/types/Utils/segmentation/coreTools/archive.d.ts +1 -0
  82. package/dist/types/Utils/segmentation/coreTools/coreType.d.ts +206 -0
  83. package/dist/types/Utils/segmentation/coreTools/divControlTools.d.ts +19 -0
  84. package/dist/types/Utils/segmentation/coreTools/gui.d.ts +123 -0
  85. package/dist/types/Utils/utils.d.ts +1 -1
  86. package/dist/types/Utils/workers/reformatSaveDataWorker.d.ts +3 -3
  87. package/dist/types/index.d.ts +13 -11
  88. package/dist/types/types/types.d.ts +4 -38
  89. package/dist/types/types.d.ts +4 -38
  90. package/package.json +1 -1
  91. package/dist/Utils/nrrd_tool.d.ts +0 -269
  92. package/dist/Utils/nrrd_tool.js +0 -2480
  93. package/dist/Utils/nrrd_tool.js.map +0 -1
  94. package/dist/types/Utils/nrrd_tool.d.ts +0 -269
@@ -0,0 +1,1083 @@
1
+ import { CommToolsData } from "./CommToolsData";
2
+ import { switchEraserSize, switchPencilIcon } from "../utils";
3
+ export class DrawToolCore extends CommToolsData {
4
+ constructor(container) {
5
+ const mainAreaContainer = document.createElement("div");
6
+ super(container, mainAreaContainer);
7
+ this.drawingPrameters = {
8
+ handleOnDrawingMouseDown: (ev) => { },
9
+ handleOnDrawingMouseMove: (ev) => { },
10
+ handleOnPanMouseMove: (ev) => { },
11
+ handleOnDrawingMouseUp: (ev) => { },
12
+ handleOnDrawingMouseLeave: (ev) => { },
13
+ handleOnDrawingBrushCricleMove: (ev) => { },
14
+ handleZoomWheel: (e) => { },
15
+ handleSphereWheel: (e) => { },
16
+ };
17
+ this.eraserUrls = [];
18
+ this.pencilUrls = [];
19
+ this.undoArray = [];
20
+ // need to return to parent
21
+ this.start = () => { };
22
+ /*************************************May consider to move outside *******************************************/
23
+ this.drawLine = (x1, y1, x2, y2) => {
24
+ this.protectedData.ctxes.drawingCtx.beginPath();
25
+ this.protectedData.ctxes.drawingCtx.moveTo(x1, y1);
26
+ this.protectedData.ctxes.drawingCtx.lineTo(x2, y2);
27
+ this.protectedData.ctxes.drawingCtx.strokeStyle = this.gui_states.color;
28
+ this.protectedData.ctxes.drawingCtx.stroke();
29
+ };
30
+ this.container = container;
31
+ this.mainAreaContainer = mainAreaContainer;
32
+ this.initDrawToolCore();
33
+ }
34
+ initDrawToolCore() {
35
+ this.container.addEventListener("keydown", (ev) => {
36
+ if (ev.key === "Shift" && !this.gui_states.sphere) {
37
+ this.protectedData.Is_Shift_Pressed = true;
38
+ this.nrrd_states.enableCursorChoose = false;
39
+ }
40
+ if (ev.key === "s") {
41
+ this.protectedData.Is_Draw = false;
42
+ this.nrrd_states.enableCursorChoose =
43
+ !this.nrrd_states.enableCursorChoose;
44
+ }
45
+ });
46
+ this.container.addEventListener("keyup", (ev) => {
47
+ if (ev.key === "Shift") {
48
+ this.protectedData.Is_Shift_Pressed = false;
49
+ }
50
+ });
51
+ }
52
+ setEraserUrls(urls) {
53
+ this.eraserUrls = urls;
54
+ }
55
+ setPencilIconUrls(urls) {
56
+ this.pencilUrls = urls;
57
+ this.gui_states.defaultPaintCursor = switchPencilIcon("dot", this.pencilUrls);
58
+ this.protectedData.canvases.drawingCanvas.style.cursor =
59
+ this.gui_states.defaultPaintCursor;
60
+ }
61
+ setCurrentLayer() {
62
+ let ctx;
63
+ let canvas;
64
+ switch (this.gui_states.label) {
65
+ case "label1":
66
+ ctx = this.protectedData.ctxes.drawingLayerOneCtx;
67
+ canvas = this.protectedData.canvases.drawingCanvasLayerOne;
68
+ break;
69
+ case "label2":
70
+ ctx = this.protectedData.ctxes.drawingLayerTwoCtx;
71
+ canvas = this.protectedData.canvases.drawingCanvasLayerTwo;
72
+ break;
73
+ case "label3":
74
+ ctx = this.protectedData.ctxes.drawingLayerThreeCtx;
75
+ canvas = this.protectedData.canvases.drawingCanvasLayerThree;
76
+ break;
77
+ default:
78
+ ctx = this.protectedData.ctxes.drawingLayerOneCtx;
79
+ canvas = this.protectedData.canvases.drawingCanvasLayerOne;
80
+ break;
81
+ }
82
+ return { ctx, canvas };
83
+ }
84
+ draw(opts) {
85
+ if (!!opts) {
86
+ this.nrrd_states.getMask = opts === null || opts === void 0 ? void 0 : opts.getMaskData;
87
+ this.nrrd_states.getSphere = opts === null || opts === void 0 ? void 0 : opts.getSphereData;
88
+ }
89
+ this.paintOnCanvas();
90
+ }
91
+ paintOnCanvas() {
92
+ var _a, _b, _c;
93
+ /**
94
+ * drag paint panel
95
+ */
96
+ let leftclicked = false;
97
+ let rightclicked = false;
98
+ let panelMoveInnerX = 0;
99
+ let panelMoveInnerY = 0;
100
+ // todo
101
+ // let currentSliceIndex = this.protectedData.mainPreSlices.index;
102
+ let currentSliceIndex = this.protectedData.mainPreSlices.index;
103
+ // draw lines starts position
104
+ let Is_Painting = false;
105
+ let lines = [];
106
+ const clearArc = this.useEraser();
107
+ this.updateOriginAndChangedWH();
108
+ this.initAllCanvas();
109
+ (_a = this.protectedData.ctxes.displayCtx) === null || _a === void 0 ? void 0 : _a.save();
110
+ this.flipDisplayImageByAxis();
111
+ (_b = this.protectedData.ctxes.displayCtx) === null || _b === void 0 ? void 0 : _b.drawImage(this.protectedData.canvases.originCanvas, 0, 0, this.nrrd_states.changedWidth, this.nrrd_states.changedHeight);
112
+ (_c = this.protectedData.ctxes.displayCtx) === null || _c === void 0 ? void 0 : _c.restore();
113
+ this.protectedData.previousDrawingImage =
114
+ this.protectedData.ctxes.drawingCtx.getImageData(0, 0, this.protectedData.canvases.drawingCanvas.width, this.protectedData.canvases.drawingCanvas.height);
115
+ // let a global variable to store the wheel move event
116
+ this.drawingPrameters.handleZoomWheel = this.configMouseZoomWheel();
117
+ // init to add it
118
+ this.protectedData.canvases.drawingCanvas.addEventListener("wheel", this.drawingPrameters.handleZoomWheel, {
119
+ passive: false,
120
+ });
121
+ // sphere Wheel
122
+ this.drawingPrameters.handleSphereWheel = this.configMouseSphereWheel();
123
+ // pan move
124
+ this.drawingPrameters.handleOnPanMouseMove = (e) => {
125
+ this.protectedData.canvases.drawingCanvas.style.cursor = "grabbing";
126
+ this.nrrd_states.previousPanelL = e.clientX - panelMoveInnerX;
127
+ this.nrrd_states.previousPanelT = e.clientY - panelMoveInnerY;
128
+ this.protectedData.canvases.displayCanvas.style.left =
129
+ this.protectedData.canvases.drawingCanvas.style.left =
130
+ this.nrrd_states.previousPanelL + "px";
131
+ this.protectedData.canvases.displayCanvas.style.top =
132
+ this.protectedData.canvases.drawingCanvas.style.top =
133
+ this.nrrd_states.previousPanelT + "px";
134
+ };
135
+ // brush circle move
136
+ this.drawingPrameters.handleOnDrawingBrushCricleMove = (e) => {
137
+ e.preventDefault();
138
+ this.nrrd_states.Mouse_Over_x = e.offsetX;
139
+ this.nrrd_states.Mouse_Over_y = e.offsetY;
140
+ if (this.nrrd_states.Mouse_Over_x === undefined) {
141
+ this.nrrd_states.Mouse_Over_x = e.clientX;
142
+ this.nrrd_states.Mouse_Over_y = e.clientY;
143
+ }
144
+ if (e.type === "mouseout") {
145
+ this.nrrd_states.Mouse_Over = false;
146
+ this.protectedData.canvases.drawingCanvas.removeEventListener("mousemove", this.drawingPrameters.handleOnDrawingBrushCricleMove);
147
+ }
148
+ else if (e.type === "mouseover") {
149
+ this.nrrd_states.Mouse_Over = true;
150
+ this.protectedData.canvases.drawingCanvas.addEventListener("mousemove", this.drawingPrameters.handleOnDrawingBrushCricleMove);
151
+ }
152
+ };
153
+ // drawing move
154
+ this.drawingPrameters.handleOnDrawingMouseMove = (e) => {
155
+ this.protectedData.Is_Draw = true;
156
+ if (Is_Painting) {
157
+ if (this.gui_states.Eraser) {
158
+ this.nrrd_states.stepClear = 1;
159
+ // drawingCtx.clearRect(e.offsetX - 5, e.offsetY - 5, 25, 25);
160
+ clearArc(e.offsetX, e.offsetY, this.gui_states.brushAndEraserSize);
161
+ }
162
+ else {
163
+ lines.push({ x: e.offsetX, y: e.offsetY });
164
+ this.paintOnCanvasLayer(e.offsetX, e.offsetY);
165
+ }
166
+ }
167
+ };
168
+ this.drawingPrameters.handleOnDrawingMouseDown = (e) => {
169
+ if (leftclicked || rightclicked) {
170
+ this.protectedData.canvases.drawingCanvas.removeEventListener("pointerup", this.drawingPrameters.handleOnDrawingMouseUp);
171
+ this.protectedData.ctxes.drawingLayerMasterCtx.closePath();
172
+ return;
173
+ }
174
+ // when switch slice, clear previousDrawingImage
175
+ // todo
176
+ if (currentSliceIndex !== this.protectedData.mainPreSlices.index) {
177
+ this.protectedData.previousDrawingImage =
178
+ this.protectedData.ctxes.emptyCtx.createImageData(1, 1);
179
+ currentSliceIndex = this.protectedData.mainPreSlices.index;
180
+ }
181
+ // remove it when mouse click down
182
+ this.protectedData.canvases.drawingCanvas.removeEventListener("wheel", this.drawingPrameters.handleZoomWheel);
183
+ if (e.button === 0) {
184
+ if (this.protectedData.Is_Shift_Pressed) {
185
+ leftclicked = true;
186
+ lines = [];
187
+ Is_Painting = true;
188
+ this.protectedData.Is_Draw = true;
189
+ if (this.gui_states.Eraser) {
190
+ // this.protectedData.canvases.drawingCanvas.style.cursor =
191
+ // "url(https://raw.githubusercontent.com/LinkunGao/copper3d-datasets/main/icons/eraser/circular-cursor_48.png) 48 48, crosshair";
192
+ this.eraserUrls.length > 0
193
+ ? (this.protectedData.canvases.drawingCanvas.style.cursor =
194
+ switchEraserSize(this.gui_states.brushAndEraserSize, this.eraserUrls))
195
+ : (this.protectedData.canvases.drawingCanvas.style.cursor =
196
+ switchEraserSize(this.gui_states.brushAndEraserSize));
197
+ }
198
+ else {
199
+ this.protectedData.canvases.drawingCanvas.style.cursor =
200
+ this.gui_states.defaultPaintCursor;
201
+ }
202
+ this.nrrd_states.drawStartPos.x = e.offsetX;
203
+ this.nrrd_states.drawStartPos.y = e.offsetY;
204
+ this.protectedData.canvases.drawingCanvas.addEventListener("pointerup", this.drawingPrameters.handleOnDrawingMouseUp);
205
+ this.protectedData.canvases.drawingCanvas.addEventListener("pointermove", this.drawingPrameters.handleOnDrawingMouseMove);
206
+ }
207
+ else if (this.nrrd_states.enableCursorChoose) {
208
+ this.nrrd_states.cursorPageX =
209
+ e.offsetX / this.nrrd_states.sizeFoctor;
210
+ this.nrrd_states.cursorPageY =
211
+ e.offsetY / this.nrrd_states.sizeFoctor;
212
+ this.enableCrosshair();
213
+ }
214
+ else if (this.gui_states.sphere) {
215
+ let mouseX = e.offsetX;
216
+ let mouseY = e.offsetY;
217
+ // record mouseX,Y, and enable crosshair function
218
+ this.nrrd_states.sphereOrigin[this.protectedData.axis] = [
219
+ mouseX,
220
+ mouseY,
221
+ this.nrrd_states.currentIndex,
222
+ ];
223
+ this.setUpSphereOrigins(mouseX, mouseY);
224
+ this.nrrd_states.cursorPageX = mouseX;
225
+ this.nrrd_states.cursorPageY = mouseY;
226
+ this.enableCrosshair();
227
+ // draw circle setup width/height for sphere canvas
228
+ this.drawSphere(mouseX, mouseY, this.nrrd_states.sphereRadius);
229
+ this.protectedData.canvases.drawingCanvas.addEventListener("wheel", this.drawingPrameters.handleSphereWheel, true);
230
+ this.protectedData.canvases.drawingCanvas.addEventListener("pointerup", this.drawingPrameters.handleOnDrawingMouseUp);
231
+ }
232
+ }
233
+ else if (e.button === 2) {
234
+ rightclicked = true;
235
+ let offsetX = this.protectedData.canvases.drawingCanvas.offsetLeft;
236
+ let offsetY = this.protectedData.canvases.drawingCanvas.offsetTop;
237
+ panelMoveInnerX = e.clientX - offsetX;
238
+ panelMoveInnerY = e.clientY - offsetY;
239
+ this.protectedData.canvases.drawingCanvas.style.cursor = "grab";
240
+ this.protectedData.canvases.drawingCanvas.addEventListener("pointerup", this.drawingPrameters.handleOnDrawingMouseUp);
241
+ this.protectedData.canvases.drawingCanvas.addEventListener("pointermove", this.drawingPrameters.handleOnPanMouseMove);
242
+ }
243
+ else {
244
+ return;
245
+ }
246
+ };
247
+ // disable browser right click menu
248
+ this.protectedData.canvases.drawingCanvas.addEventListener("pointerdown", this.drawingPrameters.handleOnDrawingMouseDown, true);
249
+ const redrawPreviousImageToLabelCtx = (ctx, label = "default") => {
250
+ var _a;
251
+ let paintImages;
252
+ switch (label) {
253
+ case "label1":
254
+ paintImages = this.protectedData.maskData.paintImagesLabel1;
255
+ break;
256
+ case "label2":
257
+ paintImages = this.protectedData.maskData.paintImagesLabel2;
258
+ break;
259
+ case "label3":
260
+ paintImages = this.protectedData.maskData.paintImagesLabel3;
261
+ break;
262
+ default:
263
+ paintImages = this.protectedData.maskData.paintImages;
264
+ break;
265
+ }
266
+ const tempPreImg = (_a = this.filterDrawedImage(this.protectedData.axis, this.nrrd_states.currentIndex, paintImages)) === null || _a === void 0 ? void 0 : _a.image;
267
+ this.protectedData.canvases.emptyCanvas.width =
268
+ this.protectedData.canvases.emptyCanvas.width;
269
+ if (tempPreImg && label == "default") {
270
+ this.protectedData.previousDrawingImage = tempPreImg;
271
+ }
272
+ this.protectedData.ctxes.emptyCtx.putImageData(tempPreImg, 0, 0);
273
+ // draw privous image
274
+ ctx.drawImage(this.protectedData.canvases.emptyCanvas, 0, 0, this.nrrd_states.changedWidth, this.nrrd_states.changedHeight);
275
+ };
276
+ this.drawingPrameters.handleOnDrawingMouseUp = (e) => {
277
+ if (e.button === 0) {
278
+ if (this.protectedData.Is_Shift_Pressed || Is_Painting) {
279
+ leftclicked = false;
280
+ let { ctx, canvas } = this.setCurrentLayer();
281
+ ctx.closePath();
282
+ this.protectedData.canvases.drawingCanvas.removeEventListener("pointermove", this.drawingPrameters.handleOnDrawingMouseMove);
283
+ if (!this.gui_states.Eraser) {
284
+ if (this.gui_states.segmentation) {
285
+ this.protectedData.canvases.drawingCanvasLayerMaster.width =
286
+ this.protectedData.canvases.drawingCanvasLayerMaster.width;
287
+ canvas.width = canvas.width;
288
+ redrawPreviousImageToLabelCtx(this.protectedData.ctxes.drawingLayerMasterCtx);
289
+ redrawPreviousImageToLabelCtx(ctx, this.gui_states.label);
290
+ // draw new drawings
291
+ ctx.beginPath();
292
+ ctx.moveTo(lines[0].x, lines[0].y);
293
+ for (let i = 1; i < lines.length; i++) {
294
+ ctx.lineTo(lines[i].x, lines[i].y);
295
+ }
296
+ ctx.closePath();
297
+ ctx.lineWidth = 1;
298
+ ctx.fillStyle = this.gui_states.fillColor;
299
+ ctx.fill();
300
+ // draw layer to master layer
301
+ this.protectedData.ctxes.drawingLayerMasterCtx.drawImage(canvas, 0, 0, this.nrrd_states.changedWidth, this.nrrd_states.changedHeight);
302
+ }
303
+ }
304
+ this.protectedData.previousDrawingImage =
305
+ this.protectedData.ctxes.drawingLayerMasterCtx.getImageData(0, 0, this.protectedData.canvases.drawingCanvasLayerMaster.width, this.protectedData.canvases.drawingCanvasLayerMaster.height);
306
+ this.storeAllImages(this.nrrd_states.currentIndex, this.gui_states.label);
307
+ if (this.gui_states.Eraser) {
308
+ const restLabels = this.getRestLabel();
309
+ this.storeEachLayerImage(this.nrrd_states.currentIndex, restLabels[0]);
310
+ this.storeEachLayerImage(this.nrrd_states.currentIndex, restLabels[1]);
311
+ }
312
+ Is_Painting = false;
313
+ /**
314
+ * store undo array
315
+ */
316
+ const currentUndoObj = this.getCurrentUndo();
317
+ const src = this.protectedData.canvases.drawingCanvasLayerMaster.toDataURL();
318
+ const image = new Image();
319
+ image.src = src;
320
+ if (currentUndoObj.length > 0) {
321
+ currentUndoObj[0].layers[this.gui_states.label].push(image);
322
+ }
323
+ else {
324
+ const undoObj = {
325
+ sliceIndex: this.nrrd_states.currentIndex,
326
+ layers: { label1: [], label2: [], label3: [] },
327
+ };
328
+ undoObj.layers[this.gui_states.label].push(image);
329
+ this.undoArray.push(undoObj);
330
+ }
331
+ // add wheel after pointer up
332
+ this.protectedData.canvases.drawingCanvas.addEventListener("wheel", this.drawingPrameters.handleZoomWheel, {
333
+ passive: false,
334
+ });
335
+ }
336
+ else if (this.gui_states.sphere &&
337
+ !this.nrrd_states.enableCursorChoose) {
338
+ // plan B
339
+ // findout all index in the sphere radius range in Axial view
340
+ if (this.nrrd_states.spherePlanB) {
341
+ // clear stroe images
342
+ this.clearStoreImages();
343
+ for (let i = 0; i < this.nrrd_states.sphereRadius; i++) {
344
+ this.drawSphereOnEachViews(i, "x");
345
+ this.drawSphereOnEachViews(i, "y");
346
+ this.drawSphereOnEachViews(i, "z");
347
+ }
348
+ }
349
+ !!this.nrrd_states.getSphere &&
350
+ this.nrrd_states.getSphere(this.nrrd_states.sphereOrigin.z, this.nrrd_states.sphereRadius);
351
+ this.protectedData.canvases.drawingCanvas.removeEventListener("wheel", this.drawingPrameters.handleSphereWheel, true);
352
+ }
353
+ }
354
+ else if (e.button === 2) {
355
+ rightclicked = false;
356
+ this.protectedData.canvases.drawingCanvas.style.cursor = "grab";
357
+ this.protectedData.canvases.drawingCanvas.removeEventListener("pointermove", this.drawingPrameters.handleOnPanMouseMove);
358
+ }
359
+ else {
360
+ return;
361
+ }
362
+ if (!this.gui_states.segmentation) {
363
+ this.setIsDrawFalse(100);
364
+ }
365
+ };
366
+ this.protectedData.canvases.drawingCanvas.addEventListener("pointerleave", (e) => {
367
+ Is_Painting = false;
368
+ // (this.sceneIn as copperScene).controls.enabled = true;
369
+ if (leftclicked) {
370
+ leftclicked = false;
371
+ this.protectedData.ctxes.drawingLayerMasterCtx.closePath();
372
+ this.protectedData.canvases.drawingCanvas.removeEventListener("pointermove", this.drawingPrameters.handleOnDrawingMouseMove);
373
+ this.protectedData.canvases.drawingCanvas.removeEventListener("wheel", this.drawingPrameters.handleSphereWheel, true);
374
+ }
375
+ if (rightclicked) {
376
+ rightclicked = false;
377
+ this.protectedData.canvases.drawingCanvas.style.cursor = "grab";
378
+ this.protectedData.canvases.drawingCanvas.removeEventListener("pointermove", this.drawingPrameters.handleOnPanMouseMove);
379
+ }
380
+ this.setIsDrawFalse(100);
381
+ if (this.gui_states.segmentation) {
382
+ this.setIsDrawFalse(1000);
383
+ }
384
+ });
385
+ this.start = () => {
386
+ if (this.gui_states.readyToUpdate) {
387
+ this.protectedData.ctxes.drawingCtx.clearRect(0, 0, this.nrrd_states.changedWidth, this.nrrd_states.changedHeight);
388
+ this.protectedData.ctxes.drawingCtx.globalAlpha =
389
+ this.gui_states.globalAlpha;
390
+ if (this.protectedData.Is_Draw) {
391
+ this.protectedData.ctxes.drawingLayerMasterCtx.lineCap = "round";
392
+ this.protectedData.ctxes.drawingLayerMasterCtx.globalAlpha = 1;
393
+ this.protectedData.ctxes.drawingLayerOneCtx.lineCap = "round";
394
+ this.protectedData.ctxes.drawingLayerOneCtx.globalAlpha = 1;
395
+ this.protectedData.ctxes.drawingLayerTwoCtx.lineCap = "round";
396
+ this.protectedData.ctxes.drawingLayerTwoCtx.globalAlpha = 1;
397
+ this.protectedData.ctxes.drawingLayerThreeCtx.lineCap = "round";
398
+ this.protectedData.ctxes.drawingLayerThreeCtx.globalAlpha = 1;
399
+ }
400
+ else {
401
+ if (this.protectedData.Is_Shift_Pressed) {
402
+ if (!this.gui_states.segmentation &&
403
+ !this.gui_states.Eraser &&
404
+ this.nrrd_states.Mouse_Over) {
405
+ this.protectedData.ctxes.drawingCtx.clearRect(0, 0, this.nrrd_states.changedWidth, this.nrrd_states.changedHeight);
406
+ this.protectedData.ctxes.drawingCtx.fillStyle =
407
+ this.gui_states.brushColor;
408
+ this.protectedData.ctxes.drawingCtx.beginPath();
409
+ this.protectedData.ctxes.drawingCtx.arc(this.nrrd_states.Mouse_Over_x, this.nrrd_states.Mouse_Over_y, this.gui_states.brushAndEraserSize / 2 + 1, 0, Math.PI * 2);
410
+ this.protectedData.ctxes.drawingCtx.strokeStyle =
411
+ this.gui_states.brushColor;
412
+ this.protectedData.ctxes.drawingCtx.stroke();
413
+ }
414
+ }
415
+ if (this.nrrd_states.enableCursorChoose) {
416
+ this.protectedData.ctxes.drawingCtx.clearRect(0, 0, this.nrrd_states.changedWidth, this.nrrd_states.changedHeight);
417
+ const ex = this.nrrd_states.cursorPageX * this.nrrd_states.sizeFoctor;
418
+ const ey = this.nrrd_states.cursorPageY * this.nrrd_states.sizeFoctor;
419
+ this.drawLine(ex, 0, ex, this.protectedData.canvases.drawingCanvas.height);
420
+ this.drawLine(0, ey, this.protectedData.canvases.drawingCanvas.width, ey);
421
+ }
422
+ }
423
+ this.protectedData.ctxes.drawingCtx.drawImage(this.protectedData.canvases.drawingCanvasLayerMaster, 0, 0);
424
+ }
425
+ else {
426
+ this.redrawDisplayCanvas();
427
+ }
428
+ };
429
+ document.addEventListener("keydown", (e) => {
430
+ if ((e.ctrlKey || e.metaKey) && e.code === "KeyZ") {
431
+ this.undoLastPainting();
432
+ }
433
+ });
434
+ }
435
+ drawLinesOnLayer(ctx, x, y) {
436
+ ctx.beginPath();
437
+ ctx.moveTo(this.nrrd_states.drawStartPos.x, this.nrrd_states.drawStartPos.y);
438
+ if (this.gui_states.segmentation) {
439
+ ctx.strokeStyle = this.gui_states.color;
440
+ ctx.lineWidth = this.gui_states.lineWidth;
441
+ }
442
+ else {
443
+ ctx.strokeStyle = this.gui_states.brushColor;
444
+ ctx.lineWidth = this.gui_states.brushAndEraserSize;
445
+ }
446
+ ctx.lineTo(x, y);
447
+ ctx.stroke();
448
+ ctx.closePath();
449
+ }
450
+ paintOnCanvasLayer(x, y) {
451
+ let { ctx, canvas } = this.setCurrentLayer();
452
+ this.drawLinesOnLayer(ctx, x, y);
453
+ this.drawLinesOnLayer(this.protectedData.ctxes.drawingLayerMasterCtx, x, y);
454
+ // reset drawing start position to current position.
455
+ this.nrrd_states.drawStartPos.x = x;
456
+ this.nrrd_states.drawStartPos.y = y;
457
+ // need to flag the map as needing updating.
458
+ this.protectedData.mainPreSlices.mesh.material.map.needsUpdate = true;
459
+ }
460
+ initAllCanvas() {
461
+ /**
462
+ * display canvas
463
+ */
464
+ this.protectedData.canvases.displayCanvas.style.position = "absolute";
465
+ this.protectedData.canvases.displayCanvas.style.zIndex = "9";
466
+ this.protectedData.canvases.displayCanvas.width =
467
+ this.nrrd_states.changedWidth;
468
+ this.protectedData.canvases.displayCanvas.height =
469
+ this.nrrd_states.changedHeight;
470
+ /**
471
+ * drawing canvas
472
+ */
473
+ this.protectedData.canvases.drawingCanvas.style.zIndex = "10";
474
+ this.protectedData.canvases.drawingCanvas.style.position = "absolute";
475
+ this.protectedData.canvases.drawingCanvas.width =
476
+ this.nrrd_states.changedWidth;
477
+ this.protectedData.canvases.drawingCanvas.height =
478
+ this.nrrd_states.changedHeight;
479
+ this.protectedData.canvases.drawingCanvas.style.cursor =
480
+ this.gui_states.defaultPaintCursor;
481
+ this.protectedData.canvases.drawingCanvas.oncontextmenu = () => false;
482
+ /**
483
+ * layer1
484
+ * it should be hide, so we don't need to add it to mainAreaContainer
485
+ */
486
+ this.protectedData.canvases.drawingCanvasLayerMaster.width =
487
+ this.protectedData.canvases.drawingCanvasLayerOne.width =
488
+ this.protectedData.canvases.drawingCanvasLayerTwo.width =
489
+ this.protectedData.canvases.drawingCanvasLayerThree.width =
490
+ this.nrrd_states.changedWidth;
491
+ this.protectedData.canvases.drawingCanvasLayerMaster.height =
492
+ this.protectedData.canvases.drawingCanvasLayerOne.height =
493
+ this.protectedData.canvases.drawingCanvasLayerTwo.height =
494
+ this.protectedData.canvases.drawingCanvasLayerThree.height =
495
+ this.nrrd_states.changedHeight;
496
+ /**
497
+ * display and drawing canvas container
498
+ */
499
+ // this.mainAreaContainer.style.width = this.nrrd_states.changedWidth + "px";
500
+ // this.mainAreaContainer.style.height = this.nrrd_states.changedHeight + "px";
501
+ this.mainAreaContainer.style.width =
502
+ this.nrrd_states.originWidth * 8 + "px";
503
+ this.mainAreaContainer.style.height =
504
+ this.nrrd_states.originHeight * 8 + "px";
505
+ this.mainAreaContainer.appendChild(this.protectedData.canvases.displayCanvas);
506
+ this.mainAreaContainer.appendChild(this.protectedData.canvases.drawingCanvas);
507
+ }
508
+ useEraser() {
509
+ const clearArc = (x, y, radius) => {
510
+ var calcWidth = radius - this.nrrd_states.stepClear;
511
+ var calcHeight = Math.sqrt(radius * radius - calcWidth * calcWidth);
512
+ var posX = x - calcWidth;
513
+ var posY = y - calcHeight;
514
+ var widthX = 2 * calcWidth;
515
+ var heightY = 2 * calcHeight;
516
+ if (this.nrrd_states.stepClear <= radius) {
517
+ this.protectedData.ctxes.drawingLayerMasterCtx.clearRect(posX, posY, widthX, heightY);
518
+ this.protectedData.ctxes.drawingLayerOneCtx.clearRect(posX, posY, widthX, heightY);
519
+ this.protectedData.ctxes.drawingLayerTwoCtx.clearRect(posX, posY, widthX, heightY);
520
+ this.protectedData.ctxes.drawingLayerThreeCtx.clearRect(posX, posY, widthX, heightY);
521
+ this.nrrd_states.stepClear += 1;
522
+ clearArc(x, y, radius);
523
+ }
524
+ };
525
+ return clearArc;
526
+ }
527
+ // drawing canvas mouse zoom wheel
528
+ configMouseZoomWheel() {
529
+ let moveDistance = 1;
530
+ const handleZoomWheelMove = (e) => {
531
+ if (this.protectedData.Is_Shift_Pressed) {
532
+ return;
533
+ }
534
+ e.preventDefault();
535
+ // this.nrrd_states.originWidth;
536
+ const delta = e.detail ? e.detail > 0 : e.wheelDelta < 0;
537
+ this.protectedData.Is_Draw = true;
538
+ const ratioL = (e.clientX -
539
+ this.mainAreaContainer.offsetLeft -
540
+ this.protectedData.canvases.drawingCanvas.offsetLeft) /
541
+ this.protectedData.canvases.drawingCanvas.offsetWidth;
542
+ const ratioT = (e.clientY -
543
+ this.mainAreaContainer.offsetTop -
544
+ this.protectedData.canvases.drawingCanvas.offsetTop) /
545
+ this.protectedData.canvases.drawingCanvas.offsetHeight;
546
+ const ratioDelta = !delta ? 1 + 0.1 : 1 - 0.1;
547
+ const w = this.protectedData.canvases.drawingCanvas.offsetWidth * ratioDelta;
548
+ const h = this.protectedData.canvases.drawingCanvas.offsetHeight * ratioDelta;
549
+ const l = Math.round(e.clientX - this.mainAreaContainer.offsetLeft - w * ratioL);
550
+ const t = Math.round(e.clientY - this.mainAreaContainer.offsetTop - h * ratioT);
551
+ moveDistance = w / this.nrrd_states.originWidth;
552
+ if (moveDistance > 8) {
553
+ moveDistance = 8;
554
+ }
555
+ else if (moveDistance < 1) {
556
+ moveDistance = 1;
557
+ }
558
+ else {
559
+ this.resizePaintArea(moveDistance);
560
+ this.resetPaintAreaUIPosition(l, t);
561
+ this.setIsDrawFalse(1000);
562
+ }
563
+ this.nrrd_states.sizeFoctor = moveDistance;
564
+ };
565
+ return handleZoomWheelMove;
566
+ }
567
+ enableCrosshair() {
568
+ this.nrrd_states.isCursorSelect = true;
569
+ switch (this.protectedData.axis) {
570
+ case "x":
571
+ this.cursorPage.x.updated = true;
572
+ this.cursorPage.y.updated = false;
573
+ this.cursorPage.z.updated = false;
574
+ break;
575
+ case "y":
576
+ this.cursorPage.x.updated = false;
577
+ this.cursorPage.y.updated = true;
578
+ this.cursorPage.z.updated = false;
579
+ break;
580
+ case "z":
581
+ this.cursorPage.x.updated = false;
582
+ this.cursorPage.y.updated = false;
583
+ this.cursorPage.z.updated = true;
584
+ break;
585
+ }
586
+ }
587
+ drawImageOnEmptyImage(canvas) {
588
+ this.protectedData.ctxes.emptyCtx.drawImage(canvas, 0, 0, this.protectedData.canvases.emptyCanvas.width, this.protectedData.canvases.emptyCanvas.height);
589
+ }
590
+ /****************************Sphere functions****************************************************/
591
+ // for sphere
592
+ storeSphereImages(index, axis) {
593
+ this.setEmptyCanvasSize(axis);
594
+ this.drawImageOnEmptyImage(this.protectedData.canvases.drawingSphereCanvas);
595
+ let imageData = this.protectedData.ctxes.emptyCtx.getImageData(0, 0, this.protectedData.canvases.emptyCanvas.width, this.protectedData.canvases.emptyCanvas.height);
596
+ this.storeImageToAxis(index, this.protectedData.maskData.paintImages, imageData, axis);
597
+ }
598
+ drawSphereOnEachViews(decay, axis) {
599
+ // init sphere canvas width and height
600
+ this.setSphereCanvasSize(axis);
601
+ const mouseX = this.nrrd_states.sphereOrigin[axis][0];
602
+ const mouseY = this.nrrd_states.sphereOrigin[axis][1];
603
+ const originIndex = this.nrrd_states.sphereOrigin[axis][2];
604
+ const preIndex = originIndex - decay;
605
+ const nextIndex = originIndex + decay;
606
+ const ctx = this.protectedData.ctxes.drawingSphereCtx;
607
+ const canvas = this.protectedData.canvases.drawingSphereCanvas;
608
+ // if (
609
+ // preIndex < this.nrrd_states.minIndex ||
610
+ // nextIndex > this.nrrd_states.maxIndex
611
+ // )
612
+ // return;
613
+ if (preIndex === nextIndex) {
614
+ this.drawSphereCore(ctx, mouseX, mouseY, this.nrrd_states.sphereRadius);
615
+ this.storeSphereImages(preIndex, axis);
616
+ }
617
+ else {
618
+ this.drawSphereCore(ctx, mouseX, mouseY, this.nrrd_states.sphereRadius - decay);
619
+ this.drawImageOnEmptyImage(canvas);
620
+ this.storeSphereImages(preIndex, axis);
621
+ this.storeSphereImages(nextIndex, axis);
622
+ }
623
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
624
+ }
625
+ drawSphereCore(ctx, x, y, radius) {
626
+ ctx.beginPath();
627
+ ctx.arc(x, y, radius * this.nrrd_states.sizeFoctor, 0, 2 * Math.PI);
628
+ ctx.fillStyle = this.gui_states.fillColor;
629
+ ctx.fill();
630
+ ctx.closePath();
631
+ }
632
+ setSphereCanvasSize(axis) {
633
+ switch (!!axis ? axis : this.protectedData.axis) {
634
+ case "x":
635
+ this.protectedData.canvases.drawingSphereCanvas.width =
636
+ this.nrrd_states.nrrd_z_mm;
637
+ this.protectedData.canvases.drawingSphereCanvas.height =
638
+ this.nrrd_states.nrrd_y_mm;
639
+ break;
640
+ case "y":
641
+ this.protectedData.canvases.drawingSphereCanvas.width =
642
+ this.nrrd_states.nrrd_x_mm;
643
+ this.protectedData.canvases.drawingSphereCanvas.height =
644
+ this.nrrd_states.nrrd_z_mm;
645
+ break;
646
+ case "z":
647
+ this.protectedData.canvases.drawingSphereCanvas.width =
648
+ this.nrrd_states.nrrd_x_mm;
649
+ this.protectedData.canvases.drawingSphereCanvas.height =
650
+ this.nrrd_states.nrrd_y_mm;
651
+ break;
652
+ }
653
+ }
654
+ // drawing canvas mouse shpere wheel
655
+ configMouseSphereWheel() {
656
+ const sphereEvent = (e) => {
657
+ e.preventDefault();
658
+ if (e.deltaY < 0) {
659
+ this.nrrd_states.sphereRadius += 1;
660
+ }
661
+ else {
662
+ this.nrrd_states.sphereRadius -= 1;
663
+ }
664
+ // limited the radius max and min
665
+ this.nrrd_states.sphereRadius = Math.max(1, Math.min(this.nrrd_states.sphereRadius, 50));
666
+ // get mouse position
667
+ const mouseX = this.nrrd_states.sphereOrigin[this.protectedData.axis][0];
668
+ const mouseY = this.nrrd_states.sphereOrigin[this.protectedData.axis][1];
669
+ this.drawSphere(mouseX, mouseY, this.nrrd_states.sphereRadius);
670
+ };
671
+ return sphereEvent;
672
+ }
673
+ drawSphere(mouseX, mouseY, radius) {
674
+ // clear canvas
675
+ this.protectedData.canvases.drawingSphereCanvas.width =
676
+ this.protectedData.canvases.drawingCanvasLayerMaster.width;
677
+ this.protectedData.canvases.drawingSphereCanvas.height =
678
+ this.protectedData.canvases.drawingCanvasLayerMaster.height;
679
+ const canvas = this.protectedData.canvases.drawingSphereCanvas;
680
+ const ctx = this.protectedData.ctxes.drawingSphereCtx;
681
+ this.protectedData.ctxes.drawingLayerMasterCtx.clearRect(0, 0, canvas.width, canvas.height);
682
+ this.drawSphereCore(ctx, mouseX, mouseY, radius);
683
+ this.protectedData.ctxes.drawingLayerMasterCtx.drawImage(canvas, 0, 0, this.nrrd_states.changedWidth, this.nrrd_states.changedHeight);
684
+ }
685
+ setUpSphereOrigins(mouseX, mouseY) {
686
+ const convertCursor = (from, to) => {
687
+ const convertObj = this.convertCursorPoint(from, to, mouseX, mouseY, this.nrrd_states.currentIndex);
688
+ return {
689
+ convertCursorNumX: convertObj === null || convertObj === void 0 ? void 0 : convertObj.convertCursorNumX,
690
+ convertCursorNumY: convertObj === null || convertObj === void 0 ? void 0 : convertObj.convertCursorNumY,
691
+ currentIndex: convertObj === null || convertObj === void 0 ? void 0 : convertObj.currentIndex,
692
+ };
693
+ };
694
+ const axisConversions = {
695
+ x: { axisTo1: "y", axisTo2: "z" },
696
+ y: { axisTo1: "z", axisTo2: "x" },
697
+ z: { axisTo1: "x", axisTo2: "y" },
698
+ };
699
+ const { axisTo1, axisTo2 } = axisConversions[this.protectedData.axis];
700
+ this.nrrd_states.sphereOrigin[axisTo1] = [
701
+ convertCursor(this.protectedData.axis, axisTo1).convertCursorNumX,
702
+ convertCursor(this.protectedData.axis, axisTo1).convertCursorNumY,
703
+ convertCursor(this.protectedData.axis, axisTo1).currentIndex,
704
+ ];
705
+ this.nrrd_states.sphereOrigin[axisTo2] = [
706
+ convertCursor(this.protectedData.axis, axisTo2).convertCursorNumX,
707
+ convertCursor(this.protectedData.axis, axisTo2).convertCursorNumY,
708
+ convertCursor(this.protectedData.axis, axisTo2).currentIndex,
709
+ ];
710
+ }
711
+ /****************************label div controls****************************************************/
712
+ getRestLabel() {
713
+ const labels = this.nrrd_states.labels;
714
+ const restLabel = labels.filter((item) => {
715
+ return item !== this.gui_states.label;
716
+ });
717
+ return restLabel;
718
+ }
719
+ /**************************** Undo clear functions****************************************************/
720
+ getCurrentUndo() {
721
+ return this.undoArray.filter((item) => {
722
+ return item.sliceIndex === this.nrrd_states.currentIndex;
723
+ });
724
+ }
725
+ /**
726
+ * Clear mask on current slice canvas
727
+ */
728
+ clearPaint() {
729
+ this.protectedData.Is_Draw = true;
730
+ this.resetLayerCanvas();
731
+ this.protectedData.canvases.originCanvas.width =
732
+ this.protectedData.canvases.originCanvas.width;
733
+ this.protectedData.mainPreSlices.repaint.call(this.protectedData.mainPreSlices);
734
+ this.protectedData.previousDrawingImage =
735
+ this.protectedData.ctxes.emptyCtx.createImageData(1, 1);
736
+ this.storeAllImages(this.nrrd_states.currentIndex, this.gui_states.label);
737
+ const restLabels = this.getRestLabel();
738
+ this.storeEachLayerImage(this.nrrd_states.currentIndex, restLabels[0]);
739
+ this.storeEachLayerImage(this.nrrd_states.currentIndex, restLabels[1]);
740
+ this.setIsDrawFalse(1000);
741
+ }
742
+ // need to update
743
+ undoLastPainting() {
744
+ let { ctx, canvas } = this.setCurrentLayer();
745
+ this.protectedData.Is_Draw = true;
746
+ this.protectedData.canvases.drawingCanvasLayerMaster.width =
747
+ this.protectedData.canvases.drawingCanvasLayerMaster.width;
748
+ canvas.width = canvas.width;
749
+ this.protectedData.mainPreSlices.repaint.call(this.protectedData.mainPreSlices);
750
+ const currentUndoObj = this.getCurrentUndo();
751
+ if (currentUndoObj.length > 0) {
752
+ const undo = currentUndoObj[0];
753
+ const layerUndos = undo.layers[this.gui_states.label];
754
+ const layerLen = layerUndos.length;
755
+ // if (layerLen === 0) return;
756
+ layerUndos.pop();
757
+ if (layerLen > 0) {
758
+ // const imageSrc = undo.undos[undo.undos.length - 1];
759
+ const image = layerUndos[layerLen - 1];
760
+ if (!!image) {
761
+ ctx.drawImage(image, 0, 0, this.nrrd_states.changedWidth, this.nrrd_states.changedHeight);
762
+ }
763
+ }
764
+ if (undo.layers.label1.length > 0) {
765
+ const image = undo.layers.label1[undo.layers.label1.length - 1];
766
+ this.protectedData.ctxes.drawingLayerMasterCtx.drawImage(image, 0, 0, this.nrrd_states.changedWidth, this.nrrd_states.changedHeight);
767
+ }
768
+ if (undo.layers.label2.length > 0) {
769
+ const image = undo.layers.label2[undo.layers.label2.length - 1];
770
+ this.protectedData.ctxes.drawingLayerMasterCtx.drawImage(image, 0, 0, this.nrrd_states.changedWidth, this.nrrd_states.changedHeight);
771
+ }
772
+ if (undo.layers.label3.length > 0) {
773
+ const image = undo.layers.label3[undo.layers.label3.length - 1];
774
+ this.protectedData.ctxes.drawingLayerMasterCtx.drawImage(image, 0, 0, this.nrrd_states.changedWidth, this.nrrd_states.changedHeight);
775
+ }
776
+ this.protectedData.previousDrawingImage =
777
+ this.protectedData.ctxes.drawingLayerMasterCtx.getImageData(0, 0, this.protectedData.canvases.drawingCanvasLayerMaster.width, this.protectedData.canvases.drawingCanvasLayerMaster.height);
778
+ this.storeAllImages(this.nrrd_states.currentIndex, this.gui_states.label);
779
+ this.setIsDrawFalse(1000);
780
+ }
781
+ }
782
+ /****************************Store images****************************************************/
783
+ storeImageToAxis(index, paintedImages, imageData, axis) {
784
+ var _a, _b, _c;
785
+ let temp = {
786
+ index,
787
+ image: imageData,
788
+ };
789
+ let drawedImage;
790
+ switch (!!axis ? axis : this.protectedData.axis) {
791
+ case "x":
792
+ drawedImage = this.filterDrawedImage("x", index, paintedImages);
793
+ drawedImage
794
+ ? (drawedImage.image = imageData)
795
+ : (_a = paintedImages.x) === null || _a === void 0 ? void 0 : _a.push(temp);
796
+ break;
797
+ case "y":
798
+ drawedImage = this.filterDrawedImage("y", index, paintedImages);
799
+ drawedImage
800
+ ? (drawedImage.image = imageData)
801
+ : (_b = paintedImages.y) === null || _b === void 0 ? void 0 : _b.push(temp);
802
+ break;
803
+ case "z":
804
+ drawedImage = this.filterDrawedImage("z", index, paintedImages);
805
+ drawedImage
806
+ ? (drawedImage.image = imageData)
807
+ : (_c = paintedImages.z) === null || _c === void 0 ? void 0 : _c.push(temp);
808
+ break;
809
+ }
810
+ }
811
+ storeAllImages(index, label) {
812
+ // const image: HTMLImageElement = new Image();
813
+ // resize the drawing image data
814
+ if (!this.nrrd_states.loadMaskJson && !this.gui_states.sphere) {
815
+ this.setEmptyCanvasSize();
816
+ this.drawImageOnEmptyImage(this.protectedData.canvases.drawingCanvasLayerMaster);
817
+ }
818
+ let imageData = this.protectedData.ctxes.emptyCtx.getImageData(0, 0, this.protectedData.canvases.emptyCanvas.width, this.protectedData.canvases.emptyCanvas.height);
819
+ // 1.12.23
820
+ switch (this.protectedData.axis) {
821
+ case "x":
822
+ const maskData_x = this.checkSharedPlaceSlice(this.nrrd_states.nrrd_x_pixel, this.nrrd_states.nrrd_y_pixel, imageData);
823
+ const marked_a_x = this.sliceArrayV(maskData_x, this.nrrd_states.nrrd_y_pixel, this.nrrd_states.nrrd_z_pixel);
824
+ const marked_b_x = this.sliceArrayH(maskData_x, this.nrrd_states.nrrd_y_pixel, this.nrrd_states.nrrd_z_pixel);
825
+ // const ratio_a_x =
826
+ // this.nrrd_states.nrrd_z / this.nrrd_states.dimensions[2];
827
+ // const ratio_b_x =
828
+ // this.nrrd_states.nrrd_y / this.nrrd_states.dimensions[1];
829
+ const convertXIndex = index;
830
+ // from x the target z will replace the col pixel
831
+ this.replaceVerticalColPixels(this.protectedData.maskData.paintImages.z, this.nrrd_states.dimensions[2],
832
+ // this.nrrd_states.ratios.z,
833
+ 1, marked_a_x, this.nrrd_states.nrrd_x_pixel, convertXIndex);
834
+ // from x the target y will replace the col pixel
835
+ this.replaceVerticalColPixels(this.protectedData.maskData.paintImages.y, this.nrrd_states.dimensions[1],
836
+ // this.nrrd_states.ratios.y,
837
+ 1, marked_b_x, this.nrrd_states.nrrd_x_pixel, convertXIndex);
838
+ break;
839
+ case "y":
840
+ const maskData_y = this.checkSharedPlaceSlice(this.nrrd_states.nrrd_x_pixel, this.nrrd_states.nrrd_y_pixel, imageData);
841
+ const marked_a_y = this.sliceArrayV(maskData_y, this.nrrd_states.nrrd_z_pixel, this.nrrd_states.nrrd_x_pixel);
842
+ const marked_b_y = this.sliceArrayH(maskData_y, this.nrrd_states.nrrd_z_pixel, this.nrrd_states.nrrd_x_pixel);
843
+ // const ratio_a_y =
844
+ // this.nrrd_states.nrrd_x / this.nrrd_states.dimensions[0];
845
+ // const ratio_b_y =
846
+ // this.nrrd_states.nrrd_z / this.nrrd_states.dimensions[2];
847
+ const convertYIndex = index;
848
+ this.replaceHorizontalRowPixels(this.protectedData.maskData.paintImages.x, this.nrrd_states.dimensions[0],
849
+ // this.nrrd_states.ratios.x,
850
+ 1, marked_a_y, this.nrrd_states.nrrd_z_pixel, convertYIndex);
851
+ this.replaceHorizontalRowPixels(this.protectedData.maskData.paintImages.z, this.nrrd_states.dimensions[2],
852
+ // this.nrrd_states.ratios.z,
853
+ 1, marked_b_y, this.nrrd_states.nrrd_x_pixel, convertYIndex);
854
+ break;
855
+ case "z":
856
+ // for x slices get cols' pixels
857
+ // for y slices get rows' pixels
858
+ // 1. slice z 的 y轴对应了slice y的index,所以我们可以通过slice z 确定在y轴上那些行是有pixels的,我们就可以将它的y坐标(或者是行号)对应到slice y的index,并将该index下的marked image提取出来。
859
+ // 2. 接着我们可以通过当前slice z 的index,来确定marked image 需要替换或重组的 行 pixel array。
860
+ const maskData_z = this.checkSharedPlaceSlice(this.nrrd_states.nrrd_x_pixel, this.nrrd_states.nrrd_y_pixel, imageData);
861
+ // 1. get slice z's each row's and col's pixel as a 2d array.
862
+ // 1.1 get the cols' 2d array for slice x
863
+ const marked_a_z = this.sliceArrayV(maskData_z, this.nrrd_states.nrrd_y_pixel, this.nrrd_states.nrrd_x_pixel);
864
+ // 1.2 get the rows' 2d array for slice y
865
+ const marked_b_z = this.sliceArrayH(maskData_z, this.nrrd_states.nrrd_y_pixel, this.nrrd_states.nrrd_x_pixel);
866
+ // 1.3 get x axis ratio for converting, to match the number slice x with the slice z's x axis pixel number.
867
+ // const ratio_a_z =
868
+ // this.nrrd_states.nrrd_x / this.nrrd_states.dimensions[0];
869
+ // // 1.4 get y axis ratio for converting
870
+ // const ratio_b_z =
871
+ // this.nrrd_states.nrrd_y / this.nrrd_states.dimensions[1];
872
+ // 1.5 To identify which row/col data should be replace
873
+ const convertZIndex = index;
874
+ // 2. Mapping coordinates
875
+ // from z the target x will replace the col pixel
876
+ this.replaceVerticalColPixels(this.protectedData.maskData.paintImages.x, this.nrrd_states.dimensions[0],
877
+ // this.nrrd_states.ratios.x,
878
+ 1, marked_a_z, this.nrrd_states.nrrd_z_pixel, convertZIndex);
879
+ // from z the target y will replace row pixel
880
+ this.replaceHorizontalRowPixels(this.protectedData.maskData.paintImages.y, this.nrrd_states.dimensions[1],
881
+ // this.nrrd_states.ratios.y,
882
+ 1, marked_b_z, this.nrrd_states.nrrd_x_pixel, convertZIndex);
883
+ break;
884
+ }
885
+ this.storeImageToAxis(index, this.protectedData.maskData.paintImages, imageData);
886
+ if (!this.nrrd_states.loadMaskJson && !this.gui_states.sphere) {
887
+ this.storeEachLayerImage(index, label);
888
+ }
889
+ }
890
+ storeImageToLabel(index, canvas, paintedImages) {
891
+ if (!this.nrrd_states.loadMaskJson) {
892
+ this.setEmptyCanvasSize();
893
+ this.drawImageOnEmptyImage(canvas);
894
+ }
895
+ const imageData = this.protectedData.ctxes.emptyCtx.getImageData(0, 0, this.protectedData.canvases.emptyCanvas.width, this.protectedData.canvases.emptyCanvas.height);
896
+ this.storeImageToAxis(index, paintedImages, imageData);
897
+ // this.setEmptyCanvasSize()
898
+ return imageData;
899
+ }
900
+ storeEachLayerImage(index, label) {
901
+ if (!this.nrrd_states.loadMaskJson) {
902
+ this.setEmptyCanvasSize();
903
+ }
904
+ let imageData;
905
+ switch (label) {
906
+ case "label1":
907
+ imageData = this.storeImageToLabel(index, this.protectedData.canvases.drawingCanvasLayerOne, this.protectedData.maskData.paintImagesLabel1);
908
+ break;
909
+ case "label2":
910
+ imageData = this.storeImageToLabel(index, this.protectedData.canvases.drawingCanvasLayerTwo, this.protectedData.maskData.paintImagesLabel2);
911
+ break;
912
+ case "label3":
913
+ imageData = this.storeImageToLabel(index, this.protectedData.canvases.drawingCanvasLayerThree, this.protectedData.maskData.paintImagesLabel3);
914
+ break;
915
+ }
916
+ // callback function to return the painted image
917
+ if (!this.nrrd_states.loadMaskJson && this.protectedData.axis == "z") {
918
+ this.nrrd_states.getMask(imageData, this.nrrd_states.currentIndex, label, this.nrrd_states.nrrd_x_pixel, this.nrrd_states.nrrd_y_pixel, this.nrrd_states.clearAllFlag);
919
+ }
920
+ }
921
+ // slice array to 2d array
922
+ sliceArrayH(arr, row, col) {
923
+ const arr2D = [];
924
+ for (let i = 0; i < row; i++) {
925
+ const start = i * col * 4;
926
+ const end = (i + 1) * col * 4;
927
+ const temp = arr.slice(start, end);
928
+ arr2D.push(temp);
929
+ }
930
+ return arr2D;
931
+ }
932
+ sliceArrayV(arr, row, col) {
933
+ const arr2D = [];
934
+ const base = col * 4;
935
+ for (let i = 0; i < col; i++) {
936
+ const temp = [];
937
+ for (let j = 0; j < row; j++) {
938
+ const index = base * j + i * 4;
939
+ temp.push(arr[index]);
940
+ temp.push(arr[index + 1]);
941
+ temp.push(arr[index + 2]);
942
+ temp.push(arr[index + 3]);
943
+ }
944
+ arr2D.push(temp);
945
+ }
946
+ return arr2D;
947
+ }
948
+ /**
949
+ *
950
+ * @param paintImageArray : the target view slice's marked images array
951
+ * @param length : the target view slice's dimention (total slice index num)
952
+ * @param ratio : the target slice image's width/height ratio of its dimention length
953
+ * @param markedArr : current painted image's vertical 2d Array
954
+ * @param targetWidth : the target image width
955
+ * @param convertIndex : Mapping current image's index to target slice image's width/height pixel start point
956
+ */
957
+ replaceVerticalColPixels(paintImageArray, length, ratio, markedArr, targetWidth, convertIndex) {
958
+ for (let i = 0, len = length; i < len; i++) {
959
+ const index = Math.floor(i * ratio);
960
+ const convertImageArray = paintImageArray[i].image.data;
961
+ const mark_data = markedArr[index];
962
+ const base_a = targetWidth * 4;
963
+ for (let j = 0, len = mark_data.length; j < len; j += 4) {
964
+ const start = (j / 4) * base_a + convertIndex * 4;
965
+ convertImageArray[start] = mark_data[j];
966
+ convertImageArray[start + 1] = mark_data[j + 1];
967
+ convertImageArray[start + 2] = mark_data[j + 2];
968
+ convertImageArray[start + 3] = mark_data[j + 3];
969
+ }
970
+ }
971
+ }
972
+ /**
973
+ *
974
+ * @param paintImageArray : the target view slice's marked images array
975
+ * @param length : the target view slice's dimention (total slice index num)
976
+ * @param ratio : the target slice image's width/height ratio of its dimention length
977
+ * @param markedArr : current painted image's horizontal 2d Array
978
+ * @param targetWidth : the target image width
979
+ * @param convertIndex : Mapping current image's index to target slice image's width/height pixel start point
980
+ */
981
+ replaceHorizontalRowPixels(paintImageArray, length, ratio, markedArr, targetWidth, convertIndex) {
982
+ for (let i = 0, len = length; i < len; i++) {
983
+ const index = Math.floor(i * ratio);
984
+ const convertImageArray = paintImageArray[i].image.data;
985
+ const mark_data = markedArr[index];
986
+ const start = targetWidth * convertIndex * 4;
987
+ for (let j = 0, len = mark_data.length; j < len; j++) {
988
+ convertImageArray[start + j] = mark_data[j];
989
+ }
990
+ }
991
+ }
992
+ /****************************** Utils for store image and itksnap core **************************************/
993
+ checkSharedPlaceSlice(width, height, imageData) {
994
+ let maskData = this.protectedData.ctxes.emptyCtx.createImageData(width, height).data;
995
+ if (this.nrrd_states.sharedPlace.z.includes(this.nrrd_states.currentIndex)) {
996
+ const sharedPlaceArr = this.findSliceInSharedPlace();
997
+ sharedPlaceArr.push(imageData);
998
+ if (sharedPlaceArr.length > 0) {
999
+ for (let i = 0; i < sharedPlaceArr.length; i++) {
1000
+ this.replaceArray(maskData, sharedPlaceArr[i].data);
1001
+ }
1002
+ }
1003
+ }
1004
+ else {
1005
+ maskData = imageData.data;
1006
+ }
1007
+ return maskData;
1008
+ }
1009
+ // replace Array
1010
+ replaceArray(mainArr, replaceArr) {
1011
+ for (let i = 0, len = replaceArr.length; i < len; i++) {
1012
+ if (replaceArr[i] === 0 || mainArr[i] !== 0) {
1013
+ continue;
1014
+ }
1015
+ else {
1016
+ mainArr[i] = replaceArr[i];
1017
+ }
1018
+ }
1019
+ }
1020
+ findSliceInSharedPlace() {
1021
+ const sharedPlaceImages = [];
1022
+ const base = Math.floor(this.nrrd_states.currentIndex *
1023
+ this.nrrd_states.ratios[this.protectedData.axis]);
1024
+ for (let i = 1; i <= 3; i++) {
1025
+ const index = this.nrrd_states.currentIndex - i;
1026
+ if (index < this.nrrd_states.minIndex) {
1027
+ break;
1028
+ }
1029
+ else {
1030
+ const newIndex = Math.floor(index * this.nrrd_states.ratios[this.protectedData.axis]);
1031
+ if (newIndex === base) {
1032
+ sharedPlaceImages.push(this.protectedData.maskData.paintImages[this.protectedData.axis][index].image);
1033
+ }
1034
+ }
1035
+ }
1036
+ for (let i = 1; i <= 3; i++) {
1037
+ const index = this.nrrd_states.currentIndex + i;
1038
+ if (index > this.nrrd_states.maxIndex) {
1039
+ break;
1040
+ }
1041
+ else {
1042
+ const newIndex = Math.floor(index * this.nrrd_states.ratios[this.protectedData.axis]);
1043
+ if (newIndex === base) {
1044
+ sharedPlaceImages.push(this.protectedData.maskData.paintImages[this.protectedData.axis][index].image);
1045
+ }
1046
+ }
1047
+ }
1048
+ return sharedPlaceImages;
1049
+ }
1050
+ /******************************** Utils gui related functions ***************************************/
1051
+ updateSlicesContrast(value, flag) {
1052
+ switch (flag) {
1053
+ case "lowerThreshold":
1054
+ this.protectedData.displaySlices.forEach((slice, index) => {
1055
+ slice.volume.lowerThreshold = value;
1056
+ });
1057
+ break;
1058
+ case "upperThreshold":
1059
+ this.protectedData.displaySlices.forEach((slice, index) => {
1060
+ slice.volume.upperThreshold = value;
1061
+ });
1062
+ break;
1063
+ case "windowLow":
1064
+ this.protectedData.displaySlices.forEach((slice, index) => {
1065
+ slice.volume.windowLow = value;
1066
+ });
1067
+ break;
1068
+ case "windowHigh":
1069
+ this.protectedData.displaySlices.forEach((slice, index) => {
1070
+ slice.volume.windowHigh = value;
1071
+ });
1072
+ break;
1073
+ }
1074
+ this.repraintCurrentContrastSlice();
1075
+ }
1076
+ repraintCurrentContrastSlice() {
1077
+ this.setSyncsliceNum();
1078
+ this.protectedData.displaySlices.forEach((slice, index) => {
1079
+ slice.repaint.call(slice);
1080
+ });
1081
+ }
1082
+ }
1083
+ //# sourceMappingURL=DrawToolCore.js.map