@niivue/niivue 0.44.2-dev.1 → 0.44.2-dev.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/index.d.ts +15 -71
- package/build/index.js +198 -460
- package/build/index.js.map +1 -1
- package/build/index.min.js +1 -1
- package/dist/index.d.ts +9 -2
- package/dist/index.js +200 -39
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/package.json +1 -1
- package/src/index_segment.html +79 -11
- package/src/index_sync.html +64 -20
- package/src/niivue/index.ts +261 -49
- package/src/niivue.css +0 -1
- package/src/nvdocument.ts +5 -1
- package/dist/niivue.umd.js +0 -1869
package/dist/index.d.ts
CHANGED
|
@@ -678,8 +678,10 @@ type NVConfigOptions = {
|
|
|
678
678
|
clickToSegmentIntensityMin: number;
|
|
679
679
|
clickToSegmentPercent: number;
|
|
680
680
|
clickToSegmentMaxDistanceMM: number;
|
|
681
|
+
clickToSegmentIs2D: boolean;
|
|
681
682
|
selectionBoxLineThickness: number;
|
|
682
683
|
selectionBoxIsOutline: boolean;
|
|
684
|
+
scrollRequiresFocus: boolean;
|
|
683
685
|
};
|
|
684
686
|
declare const DEFAULT_OPTIONS: NVConfigOptions;
|
|
685
687
|
type SceneData = {
|
|
@@ -1704,6 +1706,9 @@ declare class Niivue {
|
|
|
1704
1706
|
drawUndoBitmaps: Uint8Array[];
|
|
1705
1707
|
drawLut: LUT;
|
|
1706
1708
|
drawOpacity: number;
|
|
1709
|
+
clickToSegmentIsGrowing: boolean;
|
|
1710
|
+
clickToSegmentGrowingBitmap: Uint8Array | null;
|
|
1711
|
+
clickToSegmentXY: number[];
|
|
1707
1712
|
renderDrawAmbientOcclusion: number;
|
|
1708
1713
|
colorbarHeight: number;
|
|
1709
1714
|
drawPenLocation: number[];
|
|
@@ -2736,7 +2741,7 @@ declare class Niivue {
|
|
|
2736
2741
|
neighbors?: 6 | 18 | 26): void;
|
|
2737
2742
|
drawFloodFillCore(img: Uint8Array, seedVx: number, neighbors?: number): void;
|
|
2738
2743
|
drawFloodFill(seedXYZ: number[], newColor?: number, growSelectedCluster?: number, // if non-zero, growth based on background intensity POSITIVE_INFINITY for selected or bright, NEGATIVE_INFINITY for selected or darker
|
|
2739
|
-
forceMin?: number, forceMax?: number, neighbors?: number, maxDistanceMM?: number): void;
|
|
2744
|
+
forceMin?: number, forceMax?: number, neighbors?: number, maxDistanceMM?: number, is2D?: boolean): void;
|
|
2740
2745
|
drawPenFilled(): void;
|
|
2741
2746
|
/**
|
|
2742
2747
|
* close drawing: make sure you have saved any changes before calling this!
|
|
@@ -2750,7 +2755,7 @@ declare class Niivue {
|
|
|
2750
2755
|
* @example niivue.refreshDrawing();
|
|
2751
2756
|
* @see {@link https://niivue.github.io/niivue/features/cactus.html | live demo usage}
|
|
2752
2757
|
*/
|
|
2753
|
-
refreshDrawing(isForceRedraw?: boolean): void;
|
|
2758
|
+
refreshDrawing(isForceRedraw?: boolean, useClickToSegmentBitmap?: boolean): void;
|
|
2754
2759
|
r8Tex(texID: WebGLTexture | null, activeID: number, dims: number[], isInit?: boolean): WebGLTexture | null;
|
|
2755
2760
|
rgbaTex(texID: WebGLTexture | null, activeID: number, dims: number[], isInit?: boolean): WebGLTexture | null;
|
|
2756
2761
|
requestCORSIfNotSameOrigin(img: HTMLImageElement, url: string): void;
|
|
@@ -3009,6 +3014,8 @@ declare class Niivue {
|
|
|
3009
3014
|
sliceScroll3D(posChange?: number): void;
|
|
3010
3015
|
deleteThumbnail(): void;
|
|
3011
3016
|
inGraphTile(x: number, y: number): boolean;
|
|
3017
|
+
updateBitmapFromClickToSegment(): void;
|
|
3018
|
+
sumBitmap(img: Uint8Array): number;
|
|
3012
3019
|
mouseClick(x: number, y: number, posChange?: number, isDelta?: boolean): void;
|
|
3013
3020
|
drawRuler(): void;
|
|
3014
3021
|
drawRuler10cm(startXYendXY: number[]): void;
|
package/dist/index.js
CHANGED
|
@@ -119283,8 +119283,11 @@ var DEFAULT_OPTIONS = {
|
|
|
119283
119283
|
clickToSegmentPercent: 0,
|
|
119284
119284
|
clickToSegmentMaxDistanceMM: Number.POSITIVE_INFINITY,
|
|
119285
119285
|
// default value is infinity for backwards compatibility with flood fill routine.
|
|
119286
|
+
clickToSegmentIs2D: false,
|
|
119286
119287
|
selectionBoxLineThickness: 4,
|
|
119287
|
-
selectionBoxIsOutline: false
|
|
119288
|
+
selectionBoxIsOutline: false,
|
|
119289
|
+
scrollRequiresFocus: false
|
|
119290
|
+
// determines if the cavas need to be focused to scroll
|
|
119288
119291
|
};
|
|
119289
119292
|
var INITIAL_SCENE_DATA = {
|
|
119290
119293
|
gamma: 1,
|
|
@@ -121008,6 +121011,12 @@ var Niivue = class {
|
|
|
121008
121011
|
// the color lookup table for drawing
|
|
121009
121012
|
__publicField(this, "drawOpacity", 0.8);
|
|
121010
121013
|
// opacity of drawing (default)
|
|
121014
|
+
__publicField(this, "clickToSegmentIsGrowing", false);
|
|
121015
|
+
// flag to indicate if the clickToSegment flood fill growing is in progress with left mouse down + drag
|
|
121016
|
+
__publicField(this, "clickToSegmentGrowingBitmap", null);
|
|
121017
|
+
// the bitmap of the growing flood fill
|
|
121018
|
+
__publicField(this, "clickToSegmentXY", [0, 0]);
|
|
121019
|
+
// the x,y location of the clickToSegment flood fill
|
|
121011
121020
|
__publicField(this, "renderDrawAmbientOcclusion", 0.4);
|
|
121012
121021
|
__publicField(this, "colorbarHeight", 0);
|
|
121013
121022
|
// height in pixels, set when colorbar is drawn
|
|
@@ -121780,6 +121789,8 @@ var Niivue = class {
|
|
|
121780
121789
|
this.drawPenLocation = [NaN, NaN, NaN];
|
|
121781
121790
|
this.drawPenAxCorSag = -1;
|
|
121782
121791
|
this.uiData.mousedown = true;
|
|
121792
|
+
this.setDragStart(0, 0);
|
|
121793
|
+
this.setDragEnd(0, 0);
|
|
121783
121794
|
log.debug("mouse down");
|
|
121784
121795
|
log.debug(e);
|
|
121785
121796
|
const pos = this.getNoPaddingNoBorderCanvasRelativeMousePosition(e, this.gl.canvas);
|
|
@@ -121787,6 +121798,9 @@ var Niivue = class {
|
|
|
121787
121798
|
return;
|
|
121788
121799
|
}
|
|
121789
121800
|
const [x, y] = [pos.x * this.uiData.dpr, pos.y * this.uiData.dpr];
|
|
121801
|
+
if (this.opts.clickToSegment) {
|
|
121802
|
+
this.clickToSegmentXY = [x, y];
|
|
121803
|
+
}
|
|
121790
121804
|
const label = this.getLabelAtPoint([x, y]);
|
|
121791
121805
|
if (label) {
|
|
121792
121806
|
if (label.onClick) {
|
|
@@ -121987,8 +122001,15 @@ var Niivue = class {
|
|
|
121987
122001
|
if (this.drawPenFillPts.length > 0) {
|
|
121988
122002
|
this.drawPenFilled();
|
|
121989
122003
|
} else if (this.drawPenAxCorSag >= 0) {
|
|
121990
|
-
this.
|
|
122004
|
+
if (this.opts.clickToSegment) {
|
|
122005
|
+
const sumBitmap = this.sumBitmap(this.drawBitmap);
|
|
122006
|
+
const sumSeg = this.sumBitmap(this.clickToSegmentGrowingBitmap);
|
|
122007
|
+
if (sumSeg > sumBitmap) {
|
|
122008
|
+
this.updateBitmapFromClickToSegment();
|
|
122009
|
+
}
|
|
122010
|
+
}
|
|
121991
122011
|
}
|
|
122012
|
+
this.drawAddUndoBitmap();
|
|
121992
122013
|
this.drawPenLocation = [NaN, NaN, NaN];
|
|
121993
122014
|
this.drawPenAxCorSag = -1;
|
|
121994
122015
|
if (isFunction(this.onMouseUp)) {
|
|
@@ -122307,6 +122328,35 @@ var Niivue = class {
|
|
|
122307
122328
|
if (this.thumbnailVisible) {
|
|
122308
122329
|
return;
|
|
122309
122330
|
}
|
|
122331
|
+
const dragStartSum = this.uiData.dragStart.reduce((a, b) => a + b, 0);
|
|
122332
|
+
const dragEndSum = this.uiData.dragEnd.reduce((a, b) => a + b, 0);
|
|
122333
|
+
const validDrag = dragStartSum > 0 && dragEndSum > 0;
|
|
122334
|
+
if (this.opts.dragMode === 6 /* roiSelection */ && validDrag) {
|
|
122335
|
+
const delta = e.deltaY > 0 ? 1 : -1;
|
|
122336
|
+
if (this.uiData.dragStart[0] < this.uiData.dragEnd[0]) {
|
|
122337
|
+
this.uiData.dragStart[0] -= delta;
|
|
122338
|
+
this.uiData.dragEnd[0] += delta;
|
|
122339
|
+
} else {
|
|
122340
|
+
this.uiData.dragStart[0] += delta;
|
|
122341
|
+
this.uiData.dragEnd[0] -= delta;
|
|
122342
|
+
}
|
|
122343
|
+
if (this.uiData.dragStart[1] < this.uiData.dragEnd[1]) {
|
|
122344
|
+
this.uiData.dragStart[1] -= delta;
|
|
122345
|
+
this.uiData.dragEnd[1] += delta;
|
|
122346
|
+
} else {
|
|
122347
|
+
this.uiData.dragStart[1] += delta;
|
|
122348
|
+
this.uiData.dragEnd[1] -= delta;
|
|
122349
|
+
}
|
|
122350
|
+
this.uiData.isDragging = true;
|
|
122351
|
+
this.drawScene();
|
|
122352
|
+
this.uiData.isDragging = false;
|
|
122353
|
+
const tileIdx = this.tileIndex(this.uiData.dragStart[0], this.uiData.dragStart[1]);
|
|
122354
|
+
this.generateMouseUpCallback(
|
|
122355
|
+
this.screenXY2TextureFrac(this.uiData.dragStart[0], this.uiData.dragStart[1], tileIdx),
|
|
122356
|
+
this.screenXY2TextureFrac(this.uiData.dragEnd[0], this.uiData.dragEnd[1], tileIdx)
|
|
122357
|
+
);
|
|
122358
|
+
return;
|
|
122359
|
+
}
|
|
122310
122360
|
const rect = this.canvas.getBoundingClientRect();
|
|
122311
122361
|
if (e.deltaY < 0) {
|
|
122312
122362
|
this.sliceScroll2D(-0.01, e.clientX - rect.left, e.clientY - rect.top);
|
|
@@ -123739,6 +123789,10 @@ var Niivue = class {
|
|
|
123739
123789
|
}
|
|
123740
123790
|
// not included in public docs
|
|
123741
123791
|
sliceScroll2D(posChange, x, y, isDelta = true) {
|
|
123792
|
+
if (this.opts.scrollRequiresFocus && this.canvas !== document.activeElement) {
|
|
123793
|
+
log.warn("Canvas element does not have focus. Scroll events will not be processed.");
|
|
123794
|
+
return;
|
|
123795
|
+
}
|
|
123742
123796
|
if (this.inGraphTile(x, y)) {
|
|
123743
123797
|
let vol = this.volumes[0].frame4D;
|
|
123744
123798
|
if (posChange > 0) {
|
|
@@ -124403,6 +124457,7 @@ var Niivue = class {
|
|
|
124403
124457
|
}
|
|
124404
124458
|
const vx = this.back.dims[1] * this.back.dims[2] * this.back.dims[3];
|
|
124405
124459
|
this.drawBitmap = new Uint8Array(vx);
|
|
124460
|
+
this.clickToSegmentGrowingBitmap = new Uint8Array(vx);
|
|
124406
124461
|
this.drawClearAllUndoBitmaps();
|
|
124407
124462
|
this.drawAddUndoBitmap();
|
|
124408
124463
|
this.drawTexture = this.r8Tex(this.drawTexture, TEXTURE7_DRAW, this.back.dims, true);
|
|
@@ -124847,7 +124902,7 @@ var Niivue = class {
|
|
|
124847
124902
|
}
|
|
124848
124903
|
// not included in public docs
|
|
124849
124904
|
// set all connected voxels in drawing to new color
|
|
124850
|
-
drawFloodFill(seedXYZ, newColor = 0, growSelectedCluster = 0, forceMin = NaN, forceMax = NaN, neighbors = 6, maxDistanceMM = Number.POSITIVE_INFINITY) {
|
|
124905
|
+
drawFloodFill(seedXYZ, newColor = 0, growSelectedCluster = 0, forceMin = NaN, forceMax = NaN, neighbors = 6, maxDistanceMM = Number.POSITIVE_INFINITY, is2D = false) {
|
|
124851
124906
|
if (!this.drawBitmap) {
|
|
124852
124907
|
throw new Error("drawBitmap undefined");
|
|
124853
124908
|
}
|
|
@@ -124865,10 +124920,23 @@ var Niivue = class {
|
|
|
124865
124920
|
const nx = dims[0];
|
|
124866
124921
|
const nxy = nx * dims[1];
|
|
124867
124922
|
const nxyz = nxy * dims[2];
|
|
124868
|
-
|
|
124923
|
+
let img = this.drawBitmap.slice();
|
|
124924
|
+
let drawBitmap = this.drawBitmap;
|
|
124925
|
+
if (this.clickToSegmentIsGrowing) {
|
|
124926
|
+
img = this.clickToSegmentGrowingBitmap.slice();
|
|
124927
|
+
drawBitmap = this.clickToSegmentGrowingBitmap;
|
|
124928
|
+
}
|
|
124869
124929
|
if (img.length !== nxy * dims[2]) {
|
|
124870
124930
|
return;
|
|
124871
124931
|
}
|
|
124932
|
+
let constrainXYZ = -1;
|
|
124933
|
+
if (is2D && this.drawPenAxCorSag === 0 /* AXIAL */) {
|
|
124934
|
+
constrainXYZ = 2;
|
|
124935
|
+
} else if (is2D && this.drawPenAxCorSag === 1 /* CORONAL */) {
|
|
124936
|
+
constrainXYZ = 1;
|
|
124937
|
+
} else if (is2D && this.drawPenAxCorSag === 2 /* SAGITTAL */) {
|
|
124938
|
+
constrainXYZ = 0;
|
|
124939
|
+
}
|
|
124872
124940
|
function vx2xyz(vx) {
|
|
124873
124941
|
const Z = Math.floor(vx / nxy);
|
|
124874
124942
|
const Y = Math.floor((vx - Z * nxy) / nx);
|
|
@@ -124884,7 +124952,11 @@ var Niivue = class {
|
|
|
124884
124952
|
const seedMM = vx2mm(seedXYZ);
|
|
124885
124953
|
const maxDistanceMM2 = maxDistanceMM ** 2;
|
|
124886
124954
|
function isWithinDistance(vx) {
|
|
124887
|
-
const
|
|
124955
|
+
const xzyVox = vx2xyz(vx);
|
|
124956
|
+
if (constrainXYZ >= 0 && xzyVox[constrainXYZ] !== seedXYZ[constrainXYZ]) {
|
|
124957
|
+
return false;
|
|
124958
|
+
}
|
|
124959
|
+
const xyzMM = vx2mm(xzyVox);
|
|
124888
124960
|
const dist22 = (xyzMM[0] - seedMM[0]) ** 2 + (xyzMM[1] - seedMM[1]) ** 2 + (xyzMM[2] - seedMM[2]) ** 2;
|
|
124889
124961
|
return dist22 <= maxDistanceMM2;
|
|
124890
124962
|
}
|
|
@@ -124900,7 +124972,7 @@ var Niivue = class {
|
|
|
124900
124972
|
}
|
|
124901
124973
|
for (let i2 = 1; i2 < nxyz; i2++) {
|
|
124902
124974
|
img[i2] = 0;
|
|
124903
|
-
if (
|
|
124975
|
+
if (drawBitmap[i2] === seedColor) {
|
|
124904
124976
|
if (!isWithinDistance(i2)) {
|
|
124905
124977
|
continue;
|
|
124906
124978
|
}
|
|
@@ -124944,11 +125016,19 @@ var Niivue = class {
|
|
|
124944
125016
|
}
|
|
124945
125017
|
for (let i2 = 1; i2 < nxyz; i2++) {
|
|
124946
125018
|
if (img[i2] === 2) {
|
|
124947
|
-
|
|
125019
|
+
drawBitmap[i2] = newColor;
|
|
124948
125020
|
}
|
|
124949
125021
|
}
|
|
124950
|
-
this.
|
|
124951
|
-
|
|
125022
|
+
if (!this.clickToSegmentIsGrowing) {
|
|
125023
|
+
this.drawBitmap = drawBitmap.slice();
|
|
125024
|
+
if (!this.opts.clickToSegment) {
|
|
125025
|
+
this.drawAddUndoBitmap();
|
|
125026
|
+
}
|
|
125027
|
+
this.refreshDrawing(true, this.clickToSegmentIsGrowing);
|
|
125028
|
+
} else {
|
|
125029
|
+
this.clickToSegmentGrowingBitmap = drawBitmap;
|
|
125030
|
+
this.refreshDrawing(true, this.clickToSegmentIsGrowing);
|
|
125031
|
+
}
|
|
124952
125032
|
}
|
|
124953
125033
|
// not included in public docs
|
|
124954
125034
|
// given series of line segments, connect first and last
|
|
@@ -125108,6 +125188,7 @@ var Niivue = class {
|
|
|
125108
125188
|
this.drawClearAllUndoBitmaps();
|
|
125109
125189
|
this.rgbaTex(this.drawTexture, TEXTURE7_DRAW, [2, 2, 2, 2], true);
|
|
125110
125190
|
this.drawBitmap = null;
|
|
125191
|
+
this.clickToSegmentGrowingBitmap = null;
|
|
125111
125192
|
this.drawScene();
|
|
125112
125193
|
}
|
|
125113
125194
|
/**
|
|
@@ -125116,7 +125197,7 @@ var Niivue = class {
|
|
|
125116
125197
|
* @example niivue.refreshDrawing();
|
|
125117
125198
|
* @see {@link https://niivue.github.io/niivue/features/cactus.html | live demo usage}
|
|
125118
125199
|
*/
|
|
125119
|
-
refreshDrawing(isForceRedraw = true) {
|
|
125200
|
+
refreshDrawing(isForceRedraw = true, useClickToSegmentBitmap = false) {
|
|
125120
125201
|
if (!this.back?.dims) {
|
|
125121
125202
|
throw new Error("back.dims undefined");
|
|
125122
125203
|
}
|
|
@@ -125145,7 +125226,7 @@ var Niivue = class {
|
|
|
125145
125226
|
dims[3],
|
|
125146
125227
|
this.gl.RED,
|
|
125147
125228
|
this.gl.UNSIGNED_BYTE,
|
|
125148
|
-
this.drawBitmap
|
|
125229
|
+
useClickToSegmentBitmap ? this.clickToSegmentGrowingBitmap : this.drawBitmap
|
|
125149
125230
|
);
|
|
125150
125231
|
if (isForceRedraw) {
|
|
125151
125232
|
this.drawScene();
|
|
@@ -125783,33 +125864,61 @@ var Niivue = class {
|
|
|
125783
125864
|
mask.fill(0);
|
|
125784
125865
|
console.log("startVox", startVox);
|
|
125785
125866
|
console.log("endVox", endVox);
|
|
125786
|
-
|
|
125787
|
-
|
|
125788
|
-
|
|
125789
|
-
if (startVox[
|
|
125790
|
-
|
|
125791
|
-
} else if (startVox[
|
|
125792
|
-
|
|
125793
|
-
} else
|
|
125794
|
-
|
|
125867
|
+
let constantDim = -1;
|
|
125868
|
+
if (startVox[0] === endVox[0]) {
|
|
125869
|
+
constantDim = 0;
|
|
125870
|
+
} else if (startVox[1] === endVox[1]) {
|
|
125871
|
+
constantDim = 1;
|
|
125872
|
+
} else if (startVox[2] === endVox[2]) {
|
|
125873
|
+
constantDim = 2;
|
|
125874
|
+
} else {
|
|
125875
|
+
console.error("Error: No constant dimension found.");
|
|
125876
|
+
return;
|
|
125795
125877
|
}
|
|
125878
|
+
const dims = [0, 1, 2];
|
|
125879
|
+
const varDims = dims.filter((dim) => dim !== constantDim);
|
|
125880
|
+
const centerVox = [];
|
|
125881
|
+
centerVox[constantDim] = startVox[constantDim];
|
|
125882
|
+
centerVox[varDims[0]] = (startVox[varDims[0]] + endVox[varDims[0]]) / 2;
|
|
125883
|
+
centerVox[varDims[1]] = (startVox[varDims[1]] + endVox[varDims[1]]) / 2;
|
|
125884
|
+
const radiusX = Math.abs(endVox[varDims[0]] - startVox[varDims[0]]) / 2;
|
|
125885
|
+
const radiusY = Math.abs(endVox[varDims[1]] - startVox[varDims[1]]) / 2;
|
|
125796
125886
|
const xdim = hdr.dims[1];
|
|
125797
125887
|
const ydim = hdr.dims[2];
|
|
125798
|
-
|
|
125799
|
-
|
|
125800
|
-
|
|
125801
|
-
|
|
125802
|
-
|
|
125803
|
-
|
|
125888
|
+
const minVarDim0 = Math.max(0, Math.floor(centerVox[varDims[0]] - radiusX));
|
|
125889
|
+
const maxVarDim0 = Math.min(hdr.dims[varDims[0] + 1] - 1, Math.ceil(centerVox[varDims[0]] + radiusX));
|
|
125890
|
+
const minVarDim1 = Math.max(0, Math.floor(centerVox[varDims[1]] - radiusY));
|
|
125891
|
+
const maxVarDim1 = Math.min(hdr.dims[varDims[1] + 1] - 1, Math.ceil(centerVox[varDims[1]] + radiusY));
|
|
125892
|
+
const constDimVal = centerVox[constantDim];
|
|
125893
|
+
if (constDimVal < 0 || constDimVal >= hdr.dims[constantDim + 1]) {
|
|
125894
|
+
console.error("Error: Constant dimension value is out of bounds.");
|
|
125895
|
+
return;
|
|
125896
|
+
}
|
|
125897
|
+
for (let i2 = minVarDim0; i2 <= maxVarDim0; i2++) {
|
|
125898
|
+
for (let j = minVarDim1; j <= maxVarDim1; j++) {
|
|
125899
|
+
const voxel = [];
|
|
125900
|
+
voxel[constantDim] = constDimVal;
|
|
125901
|
+
voxel[varDims[0]] = i2;
|
|
125902
|
+
voxel[varDims[1]] = j;
|
|
125903
|
+
const di = (voxel[varDims[0]] - centerVox[varDims[0]]) / radiusX;
|
|
125904
|
+
const dj = (voxel[varDims[1]] - centerVox[varDims[1]]) / radiusY;
|
|
125905
|
+
const distSq = di * di + dj * dj;
|
|
125906
|
+
if (distSq <= 1) {
|
|
125907
|
+
const x = voxel[0];
|
|
125908
|
+
const y = voxel[1];
|
|
125909
|
+
const z = voxel[2];
|
|
125910
|
+
const index = z * xdim * ydim + y * xdim + x;
|
|
125804
125911
|
mask[index] = 1;
|
|
125805
125912
|
}
|
|
125806
125913
|
}
|
|
125807
125914
|
}
|
|
125808
|
-
const
|
|
125809
|
-
const
|
|
125810
|
-
|
|
125811
|
-
const
|
|
125812
|
-
|
|
125915
|
+
const voxelArea = pixDimsRAS[varDims[0] + 1] * pixDimsRAS[varDims[1] + 1];
|
|
125916
|
+
const numMaskedVoxels = mask.reduce((count, value) => count + (value === 1 ? 1 : 0), 0);
|
|
125917
|
+
area = numMaskedVoxels * voxelArea;
|
|
125918
|
+
const radiusX_mm = radiusX * pixDimsRAS[varDims[0] + 1];
|
|
125919
|
+
const radiusY_mm = radiusY * pixDimsRAS[varDims[1] + 1];
|
|
125920
|
+
const areaEllipse = Math.PI * radiusX_mm * radiusY_mm;
|
|
125921
|
+
area = areaEllipse;
|
|
125813
125922
|
}
|
|
125814
125923
|
let k = 0;
|
|
125815
125924
|
let M = 0;
|
|
@@ -127342,6 +127451,29 @@ var Niivue = class {
|
|
|
127342
127451
|
const pos = [(x - this.graph.LTWH[0]) / this.graph.LTWH[2], (y - this.graph.LTWH[1]) / this.graph.LTWH[3]];
|
|
127343
127452
|
return pos[0] > 0 && pos[1] > 0 && pos[0] <= 1 && pos[1] <= 1;
|
|
127344
127453
|
}
|
|
127454
|
+
// update drawBitmap if it differs from clickTosegmentBitmap
|
|
127455
|
+
updateBitmapFromClickToSegment() {
|
|
127456
|
+
if (this.clickToSegmentGrowingBitmap === null) {
|
|
127457
|
+
return;
|
|
127458
|
+
}
|
|
127459
|
+
if (this.drawBitmap === null) {
|
|
127460
|
+
return;
|
|
127461
|
+
}
|
|
127462
|
+
if (this.clickToSegmentGrowingBitmap.length !== this.drawBitmap.length) {
|
|
127463
|
+
return;
|
|
127464
|
+
}
|
|
127465
|
+
const nvx = this.drawBitmap.length;
|
|
127466
|
+
for (let i2 = 0; i2 < nvx; i2++) {
|
|
127467
|
+
this.drawBitmap[i2] = this.clickToSegmentGrowingBitmap[i2];
|
|
127468
|
+
}
|
|
127469
|
+
}
|
|
127470
|
+
sumBitmap(img) {
|
|
127471
|
+
let sum = 0;
|
|
127472
|
+
for (let i2 = 0; i2 < img.length; i2++) {
|
|
127473
|
+
sum += img[i2];
|
|
127474
|
+
}
|
|
127475
|
+
return sum;
|
|
127476
|
+
}
|
|
127345
127477
|
// not included in public docs
|
|
127346
127478
|
// handle mouse click event on canvas
|
|
127347
127479
|
mouseClick(x, y, posChange = 0, isDelta = true) {
|
|
@@ -127391,7 +127523,7 @@ var Niivue = class {
|
|
|
127391
127523
|
if (axCorSag > 2 /* SAGITTAL */) {
|
|
127392
127524
|
continue;
|
|
127393
127525
|
}
|
|
127394
|
-
|
|
127526
|
+
let texFrac = this.screenXY2TextureFrac(x, y, i2, false);
|
|
127395
127527
|
if (texFrac[0] < 0) {
|
|
127396
127528
|
continue;
|
|
127397
127529
|
}
|
|
@@ -127418,14 +127550,28 @@ var Niivue = class {
|
|
|
127418
127550
|
this.scene.crosshairPos = vec3_exports.clone(texFrac);
|
|
127419
127551
|
}
|
|
127420
127552
|
if (this.opts.drawingEnabled) {
|
|
127421
|
-
|
|
127553
|
+
let pt = this.frac2vox(this.scene.crosshairPos);
|
|
127422
127554
|
if (this.opts.clickToSegment) {
|
|
127423
|
-
|
|
127424
|
-
|
|
127425
|
-
|
|
127426
|
-
|
|
127427
|
-
|
|
127555
|
+
texFrac = this.screenXY2TextureFrac(this.clickToSegmentXY[0], this.clickToSegmentXY[1], i2, false);
|
|
127556
|
+
pt = this.frac2vox(texFrac);
|
|
127557
|
+
let diff = 0;
|
|
127558
|
+
let threshold = this.opts.clickToSegmentPercent + diff;
|
|
127559
|
+
if (this.uiData.mousedown) {
|
|
127560
|
+
const xDiff = (this.clickToSegmentXY[0] - x) / this.gl.canvas.width;
|
|
127561
|
+
const yDiff = (this.clickToSegmentXY[1] - y) / this.gl.canvas.height;
|
|
127562
|
+
diff = Math.max(Math.abs(xDiff), Math.abs(yDiff));
|
|
127563
|
+
diff *= Math.sign(Math.abs(xDiff) > Math.abs(yDiff) ? xDiff : yDiff);
|
|
127564
|
+
threshold = this.opts.clickToSegmentPercent + diff;
|
|
127565
|
+
}
|
|
127566
|
+
let voxelIntensity = this.back.getValue(pt[0], pt[1], pt[2]);
|
|
127428
127567
|
if (this.opts.clickToSegmentAutoIntensity) {
|
|
127568
|
+
if (threshold !== 0) {
|
|
127569
|
+
if (voxelIntensity === 0) {
|
|
127570
|
+
voxelIntensity = 0.01;
|
|
127571
|
+
}
|
|
127572
|
+
this.opts.clickToSegmentIntensityMax = voxelIntensity * (1 + threshold);
|
|
127573
|
+
this.opts.clickToSegmentIntensityMin = voxelIntensity * (1 - threshold);
|
|
127574
|
+
}
|
|
127429
127575
|
if (voxelIntensity > (this.back.cal_min + this.back.cal_max) * 0.5) {
|
|
127430
127576
|
this.opts.clickToSegmentBright = true;
|
|
127431
127577
|
} else {
|
|
@@ -127448,6 +127594,12 @@ var Niivue = class {
|
|
|
127448
127594
|
this.opts.penSize = Math.ceil(this.opts.clickToSegmentRadius / minPixDim);
|
|
127449
127595
|
}
|
|
127450
127596
|
this.drawPt(pt[0], pt[1], pt[2], this.opts.penValue);
|
|
127597
|
+
if (diff !== 0) {
|
|
127598
|
+
this.clickToSegmentIsGrowing = true;
|
|
127599
|
+
this.clickToSegmentGrowingBitmap = this.drawBitmap.slice();
|
|
127600
|
+
} else {
|
|
127601
|
+
this.clickToSegmentIsGrowing = false;
|
|
127602
|
+
}
|
|
127451
127603
|
this.drawFloodFill(
|
|
127452
127604
|
[pt[0], pt[1], pt[2]],
|
|
127453
127605
|
0,
|
|
@@ -127455,10 +127607,14 @@ var Niivue = class {
|
|
|
127455
127607
|
this.opts.clickToSegmentIntensityMin,
|
|
127456
127608
|
this.opts.clickToSegmentIntensityMax,
|
|
127457
127609
|
this.opts.floodFillNeighbors,
|
|
127458
|
-
this.opts.clickToSegmentMaxDistanceMM
|
|
127610
|
+
this.opts.clickToSegmentMaxDistanceMM,
|
|
127611
|
+
this.opts.clickToSegmentIs2D
|
|
127459
127612
|
);
|
|
127460
127613
|
this.drawScene();
|
|
127461
127614
|
this.createOnLocationChange(axCorSag);
|
|
127615
|
+
if (this.clickToSegmentIsGrowing) {
|
|
127616
|
+
return;
|
|
127617
|
+
}
|
|
127462
127618
|
const info = this.getDescriptives({
|
|
127463
127619
|
layer: 0,
|
|
127464
127620
|
masks: [],
|
|
@@ -127697,6 +127853,7 @@ var Niivue = class {
|
|
|
127697
127853
|
this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);
|
|
127698
127854
|
this.gl.bindVertexArray(this.unusedVAO);
|
|
127699
127855
|
} else {
|
|
127856
|
+
this.drawCircle(leftTopWidthHeight, lineColor, 0.1);
|
|
127700
127857
|
this.rectOutlineShader.use(this.gl);
|
|
127701
127858
|
this.gl.enable(this.gl.BLEND);
|
|
127702
127859
|
this.gl.uniform1f(this.rectOutlineShader.uniforms.thickness, this.opts.selectionBoxLineThickness);
|
|
@@ -127741,6 +127898,10 @@ var Niivue = class {
|
|
|
127741
127898
|
// not included in public docs
|
|
127742
127899
|
// draw a rectangle at desired location
|
|
127743
127900
|
drawSelectionBox(leftTopWidthHeight) {
|
|
127901
|
+
if (this.opts.dragMode === 6 /* roiSelection */) {
|
|
127902
|
+
this.drawCircle(leftTopWidthHeight, this.opts.selectionBoxColor, 0.1);
|
|
127903
|
+
return;
|
|
127904
|
+
}
|
|
127744
127905
|
this.drawRect(leftTopWidthHeight, this.opts.selectionBoxColor);
|
|
127745
127906
|
}
|
|
127746
127907
|
// not included in public docs
|