@niivue/niivue 0.44.2 → 0.45.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 +9 -0
- package/build/index.d.ts +31 -6
- package/build/index.js +429 -86
- package/build/index.js.map +1 -1
- package/build/index.min.js +1 -1
- package/dist/index.d.ts +31 -6
- package/dist/index.js +429 -86
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/niivue.umd.js +30 -30
- package/package.json +1 -1
- package/src/cow.iwm.cbor +0 -0
- package/src/fslmean.iwi.cbor +0 -0
- package/src/index.html +47 -8
- package/src/niivue/index.ts +520 -96
- package/src/nvdocument.ts +11 -0
- package/src/nvimage/index.ts +4 -1
- package/src/nvlabel.ts +34 -1
- package/src/nvmesh-loaders.ts +24 -1
package/dist/index.js
CHANGED
|
@@ -95525,7 +95525,7 @@ var forEach3 = function() {
|
|
|
95525
95525
|
}();
|
|
95526
95526
|
|
|
95527
95527
|
// package.json
|
|
95528
|
-
var version = "0.
|
|
95528
|
+
var version = "0.45.0";
|
|
95529
95529
|
|
|
95530
95530
|
// src/logger.ts
|
|
95531
95531
|
var _Log = class _Log {
|
|
@@ -109109,6 +109109,12 @@ var NVMeshLoaders = class _NVMeshLoaders {
|
|
|
109109
109109
|
while (lines[pos].length < 1) {
|
|
109110
109110
|
pos++;
|
|
109111
109111
|
}
|
|
109112
|
+
if (lines[pos].startsWith("METADATA")) {
|
|
109113
|
+
while (lines[pos].length > 1) {
|
|
109114
|
+
pos++;
|
|
109115
|
+
}
|
|
109116
|
+
pos++;
|
|
109117
|
+
}
|
|
109112
109118
|
items = lines[pos].trim().split(/\s+/);
|
|
109113
109119
|
pos++;
|
|
109114
109120
|
if (items[0].includes("LINES")) {
|
|
@@ -109287,7 +109293,7 @@ var NVMeshLoaders = class _NVMeshLoaders {
|
|
|
109287
109293
|
layer.values = obj;
|
|
109288
109294
|
}
|
|
109289
109295
|
}
|
|
109290
|
-
} else if (ext === "CRV" || ext === "CURV") {
|
|
109296
|
+
} else if (ext === "CRV" || ext === "CURV" || ext === "THICKNESS" || ext === "AREA") {
|
|
109291
109297
|
layer.values = _NVMeshLoaders.readCURV(buffer2, n_vert);
|
|
109292
109298
|
layer.isTransparentBelowCalMin = false;
|
|
109293
109299
|
} else if (ext === "GII") {
|
|
@@ -109312,6 +109318,9 @@ var NVMeshLoaders = class _NVMeshLoaders {
|
|
|
109312
109318
|
layer.values = _NVMeshLoaders.readSMP(buffer2, n_vert);
|
|
109313
109319
|
} else if (ext === "STC") {
|
|
109314
109320
|
layer.values = _NVMeshLoaders.readSTC(buffer2, n_vert);
|
|
109321
|
+
} else if (_NVMeshLoaders.isCurv(buffer2)) {
|
|
109322
|
+
layer.values = _NVMeshLoaders.readCURV(buffer2, n_vert);
|
|
109323
|
+
layer.isTransparentBelowCalMin = false;
|
|
109315
109324
|
} else {
|
|
109316
109325
|
log.warn("Unknown layer overlay format " + name);
|
|
109317
109326
|
return layer;
|
|
@@ -109485,6 +109494,17 @@ var NVMeshLoaders = class _NVMeshLoaders {
|
|
|
109485
109494
|
return f32;
|
|
109486
109495
|
}
|
|
109487
109496
|
// readSTC()
|
|
109497
|
+
static isCurv(buffer2) {
|
|
109498
|
+
const view = new DataView(buffer2);
|
|
109499
|
+
const sig0 = view.getUint8(0);
|
|
109500
|
+
const sig1 = view.getUint8(1);
|
|
109501
|
+
const sig2 = view.getUint8(2);
|
|
109502
|
+
if (sig0 !== 255 || sig1 !== 255 || sig2 !== 255) {
|
|
109503
|
+
utiltiesLogger.debug("Unable to recognize file type: does not appear to be FreeSurfer format.");
|
|
109504
|
+
return false;
|
|
109505
|
+
}
|
|
109506
|
+
return true;
|
|
109507
|
+
}
|
|
109488
109508
|
// read freesurfer curv big-endian format
|
|
109489
109509
|
// https://github.com/bonilhamusclab/MRIcroS/blob/master/%2BfileUtils/%2Bpial/readPial.m
|
|
109490
109510
|
// http://www.grahamwideman.com/gw/brain/fs/surfacefileformats.htm
|
|
@@ -116936,7 +116956,7 @@ var NVImage = class _NVImage {
|
|
|
116936
116956
|
hdr.datatypeCode = 64 /* DT_FLOAT64 */;
|
|
116937
116957
|
break;
|
|
116938
116958
|
default:
|
|
116939
|
-
throw new Error("Unsupported
|
|
116959
|
+
throw new Error("Unsupported MHA data type: " + items[0]);
|
|
116940
116960
|
}
|
|
116941
116961
|
}
|
|
116942
116962
|
if (line.startsWith("ObjectType") && !items[0].includes("Image")) {
|
|
@@ -116958,6 +116978,9 @@ var NVImage = class _NVImage {
|
|
|
116958
116978
|
[mat33[2], mat33[5], mat33[8], offset[2]],
|
|
116959
116979
|
[0, 0, 0, 1]
|
|
116960
116980
|
];
|
|
116981
|
+
while (bytes[pos] === 10) {
|
|
116982
|
+
pos++;
|
|
116983
|
+
}
|
|
116961
116984
|
hdr.vox_offset = pos;
|
|
116962
116985
|
if (isDetached && pairedImgData) {
|
|
116963
116986
|
if (isGz) {
|
|
@@ -119165,6 +119188,7 @@ var DEFAULT_OPTIONS = {
|
|
|
119165
119188
|
multiplanarPadPixels: 0,
|
|
119166
119189
|
// @deprecated
|
|
119167
119190
|
multiplanarForceRender: false,
|
|
119191
|
+
multiplanarEqualSize: false,
|
|
119168
119192
|
multiplanarShowRender: 2 /* AUTO */,
|
|
119169
119193
|
// auto is the same behaviour as multiplanarForceRender: false
|
|
119170
119194
|
isRadiologicalConvention: false,
|
|
@@ -119205,6 +119229,7 @@ var DEFAULT_OPTIONS = {
|
|
|
119205
119229
|
clickToSegmentBright: true
|
|
119206
119230
|
};
|
|
119207
119231
|
var INITIAL_SCENE_DATA = {
|
|
119232
|
+
gamma: 1,
|
|
119208
119233
|
azimuth: 110,
|
|
119209
119234
|
elevation: 10,
|
|
119210
119235
|
crosshairPos: vec3_exports.create(),
|
|
@@ -119443,6 +119468,9 @@ var NVDocument = class _NVDocument {
|
|
|
119443
119468
|
data.opts.meshThicknessOn2D = "infinity";
|
|
119444
119469
|
}
|
|
119445
119470
|
data.labels = [...this.data.labels];
|
|
119471
|
+
for (const label of data.labels) {
|
|
119472
|
+
delete label.onClick;
|
|
119473
|
+
}
|
|
119446
119474
|
data.customData = this.customData;
|
|
119447
119475
|
if (this.volumes.length) {
|
|
119448
119476
|
let imageOptions = this.imageOptionsArray[0];
|
|
@@ -119698,6 +119726,19 @@ var LabelLineTerminator = /* @__PURE__ */ ((LabelLineTerminator2) => {
|
|
|
119698
119726
|
LabelLineTerminator2["RING"] = "ring";
|
|
119699
119727
|
return LabelLineTerminator2;
|
|
119700
119728
|
})(LabelLineTerminator || {});
|
|
119729
|
+
var LabelAnchorPoint = /* @__PURE__ */ ((LabelAnchorPoint2) => {
|
|
119730
|
+
LabelAnchorPoint2[LabelAnchorPoint2["NONE"] = 0 /* NONE */] = "NONE";
|
|
119731
|
+
LabelAnchorPoint2[LabelAnchorPoint2["TOPLEFT"] = 9] = "TOPLEFT";
|
|
119732
|
+
LabelAnchorPoint2[LabelAnchorPoint2["TOPCENTER"] = 10] = "TOPCENTER";
|
|
119733
|
+
LabelAnchorPoint2[LabelAnchorPoint2["TOPRIGHT"] = 12] = "TOPRIGHT";
|
|
119734
|
+
LabelAnchorPoint2[LabelAnchorPoint2["MIDDLELEFT"] = 17] = "MIDDLELEFT";
|
|
119735
|
+
LabelAnchorPoint2[LabelAnchorPoint2["MIDDLECENTER"] = 18] = "MIDDLECENTER";
|
|
119736
|
+
LabelAnchorPoint2[LabelAnchorPoint2["MIDDLERIGHT"] = 20] = "MIDDLERIGHT";
|
|
119737
|
+
LabelAnchorPoint2[LabelAnchorPoint2["BOTTOMLEFT"] = 33] = "BOTTOMLEFT";
|
|
119738
|
+
LabelAnchorPoint2[LabelAnchorPoint2["BOTTOMCENTER"] = 34] = "BOTTOMCENTER";
|
|
119739
|
+
LabelAnchorPoint2[LabelAnchorPoint2["BOTTOMRIGHT"] = 36] = "BOTTOMRIGHT";
|
|
119740
|
+
return LabelAnchorPoint2;
|
|
119741
|
+
})(LabelAnchorPoint || {});
|
|
119701
119742
|
var NVLabel3DStyle = class {
|
|
119702
119743
|
/**
|
|
119703
119744
|
* @param textColor - Color of text
|
|
@@ -119735,13 +119776,17 @@ var NVLabel3D = class {
|
|
|
119735
119776
|
* @param style - The style of the label
|
|
119736
119777
|
* @param points - An array of points label for label lines
|
|
119737
119778
|
*/
|
|
119738
|
-
constructor(text, style, points) {
|
|
119779
|
+
constructor(text, style, points, anchor, onClick) {
|
|
119739
119780
|
__publicField(this, "text");
|
|
119740
119781
|
__publicField(this, "style");
|
|
119741
119782
|
__publicField(this, "points");
|
|
119783
|
+
__publicField(this, "anchor");
|
|
119784
|
+
__publicField(this, "onClick");
|
|
119742
119785
|
this.text = text;
|
|
119743
119786
|
this.style = style;
|
|
119744
119787
|
this.points = points;
|
|
119788
|
+
this.anchor = anchor || 0 /* NONE */;
|
|
119789
|
+
this.onClick = onClick;
|
|
119745
119790
|
}
|
|
119746
119791
|
};
|
|
119747
119792
|
|
|
@@ -120880,6 +120925,7 @@ var Niivue = class _Niivue {
|
|
|
120880
120925
|
* @param options - options object to set modifiable Niivue properties
|
|
120881
120926
|
*/
|
|
120882
120927
|
constructor(options = DEFAULT_OPTIONS) {
|
|
120928
|
+
__publicField(this, "loaders", {});
|
|
120883
120929
|
__publicField(this, "canvas", null);
|
|
120884
120930
|
// the reference to the canvas element on the page
|
|
120885
120931
|
__publicField(this, "_gl", null);
|
|
@@ -121489,6 +121535,11 @@ var Niivue = class _Niivue {
|
|
|
121489
121535
|
}
|
|
121490
121536
|
const thisMM = this.frac2mm(this.scene.crosshairPos);
|
|
121491
121537
|
if (this.otherNV instanceof _Niivue) {
|
|
121538
|
+
const thisGamma = this.scene.gamma;
|
|
121539
|
+
const otherGamma = this.otherNV.scene.gamma;
|
|
121540
|
+
if (thisGamma !== otherGamma) {
|
|
121541
|
+
this.otherNV.setGamma(thisGamma);
|
|
121542
|
+
}
|
|
121492
121543
|
if (this.syncOpts["2d"]) {
|
|
121493
121544
|
this.otherNV.scene.crosshairPos = this.otherNV.mm2frac(thisMM);
|
|
121494
121545
|
this.otherNV.scene.pan2Dxyzmm = vec4_exports.clone(this.scene.pan2Dxyzmm);
|
|
@@ -121505,6 +121556,11 @@ var Niivue = class _Niivue {
|
|
|
121505
121556
|
if (this.otherNV[i2] === this) {
|
|
121506
121557
|
continue;
|
|
121507
121558
|
}
|
|
121559
|
+
const thisGamma = this.scene.gamma;
|
|
121560
|
+
const otherGamma = this.otherNV[i2].scene.gamma;
|
|
121561
|
+
if (thisGamma !== otherGamma) {
|
|
121562
|
+
this.otherNV[i2].setGamma(thisGamma);
|
|
121563
|
+
}
|
|
121508
121564
|
if (this.syncOpts["2d"]) {
|
|
121509
121565
|
this.otherNV[i2].scene.crosshairPos = this.otherNV[i2].mm2frac(thisMM);
|
|
121510
121566
|
this.otherNV[i2].scene.pan2Dxyzmm = vec4_exports.clone(this.scene.pan2Dxyzmm);
|
|
@@ -121620,6 +121676,10 @@ var Niivue = class _Niivue {
|
|
|
121620
121676
|
const [x, y] = [pos.x * this.uiData.dpr, pos.y * this.uiData.dpr];
|
|
121621
121677
|
const label = this.getLabelAtPoint([x, y]);
|
|
121622
121678
|
if (label) {
|
|
121679
|
+
if (label.onClick) {
|
|
121680
|
+
label.onClick(label);
|
|
121681
|
+
return;
|
|
121682
|
+
}
|
|
121623
121683
|
for (const mesh of this.meshes) {
|
|
121624
121684
|
if (mesh.type !== "connectome" /* CONNECTOME */) {
|
|
121625
121685
|
continue;
|
|
@@ -121934,6 +121994,15 @@ var Niivue = class _Niivue {
|
|
|
121934
121994
|
this.drawScene();
|
|
121935
121995
|
this.uiData.prevX = this.uiData.currX;
|
|
121936
121996
|
this.uiData.prevY = this.uiData.currY;
|
|
121997
|
+
} else if (!this.uiData.mousedown && this.opts.clickToSegment) {
|
|
121998
|
+
const pos = this.getNoPaddingNoBorderCanvasRelativeMousePosition(e, this.gl.canvas);
|
|
121999
|
+
if (!pos) {
|
|
122000
|
+
return;
|
|
122001
|
+
}
|
|
122002
|
+
const x = pos.x * this.uiData.dpr;
|
|
122003
|
+
const y = pos.y * this.uiData.dpr;
|
|
122004
|
+
this.mousePos = [x, y];
|
|
122005
|
+
this.drawScene();
|
|
121937
122006
|
}
|
|
121938
122007
|
}
|
|
121939
122008
|
// not included in public docs
|
|
@@ -122171,6 +122240,11 @@ var Niivue = class _Niivue {
|
|
|
122171
122240
|
if (ext === "GZ") {
|
|
122172
122241
|
ext = re.exec(fullname.slice(0, -3))[1];
|
|
122173
122242
|
ext = ext.toUpperCase();
|
|
122243
|
+
} else if (ext === "CBOR") {
|
|
122244
|
+
const endExt = ext;
|
|
122245
|
+
ext = re.exec(fullname.slice(0, -5))[1];
|
|
122246
|
+
ext = ext.toUpperCase();
|
|
122247
|
+
ext = `${ext}.${endExt}`;
|
|
122174
122248
|
}
|
|
122175
122249
|
return upperCase ? ext : ext.toLowerCase();
|
|
122176
122250
|
}
|
|
@@ -122191,6 +122265,28 @@ var Niivue = class _Niivue {
|
|
|
122191
122265
|
}
|
|
122192
122266
|
async addVolumesFromUrl(imageOptionsArray) {
|
|
122193
122267
|
const promises = imageOptionsArray.map(async (imageItem) => {
|
|
122268
|
+
const ext = this.getFileExt(imageItem.url);
|
|
122269
|
+
if (this.loaders[ext]) {
|
|
122270
|
+
let itemToLoad = imageItem.url;
|
|
122271
|
+
const toExt = this.loaders[ext].toExt;
|
|
122272
|
+
let name = imageItem.name || imageItem.url;
|
|
122273
|
+
name = name.split("/").pop();
|
|
122274
|
+
if (typeof imageItem.url === "string") {
|
|
122275
|
+
const url = imageItem.url;
|
|
122276
|
+
try {
|
|
122277
|
+
const response = await fetch(url);
|
|
122278
|
+
if (!response.ok) {
|
|
122279
|
+
throw new Error(`Failed to load file: ${response.statusText}`);
|
|
122280
|
+
}
|
|
122281
|
+
itemToLoad = await response.arrayBuffer();
|
|
122282
|
+
} catch (error) {
|
|
122283
|
+
throw new Error(`Failed to load url ${url}: ${error}`);
|
|
122284
|
+
}
|
|
122285
|
+
}
|
|
122286
|
+
const buffer2 = await this.loaders[ext].loader(itemToLoad);
|
|
122287
|
+
imageItem.url = buffer2;
|
|
122288
|
+
imageItem.name = `${name}.${toExt}`;
|
|
122289
|
+
}
|
|
122194
122290
|
const imageOptions = {
|
|
122195
122291
|
url: imageItem.url,
|
|
122196
122292
|
headers: imageItem.headers,
|
|
@@ -122330,6 +122426,40 @@ var Niivue = class _Niivue {
|
|
|
122330
122426
|
this.addVolume(volume);
|
|
122331
122427
|
});
|
|
122332
122428
|
}
|
|
122429
|
+
/* useLoader
|
|
122430
|
+
|
|
122431
|
+
registers an external file loader for niivue to use when reading files.
|
|
122432
|
+
|
|
122433
|
+
the loader must return an array buffer of the file contents for niivue
|
|
122434
|
+
to parse and the extension of the file so niivue can infer the file type to load.
|
|
122435
|
+
|
|
122436
|
+
example:
|
|
122437
|
+
|
|
122438
|
+
const myCustomLoader = (File) => {
|
|
122439
|
+
// ... do parsing here ...
|
|
122440
|
+
return {
|
|
122441
|
+
arrayBuffer: ArrayBuffer,
|
|
122442
|
+
fileExt: 'iwi.cbor',
|
|
122443
|
+
positions: Float32Array | [], // allows for mesh loading to mz3
|
|
122444
|
+
indices: Uint32Array | [], // allows for mesh loading to mz3
|
|
122445
|
+
}
|
|
122446
|
+
|
|
122447
|
+
nv.useLoader({
|
|
122448
|
+
loader: myCustomLoader,
|
|
122449
|
+
fileExt: 'iwi.cbor',
|
|
122450
|
+
toExt: 'nii'
|
|
122451
|
+
})
|
|
122452
|
+
|
|
122453
|
+
*/
|
|
122454
|
+
useLoader(loader, fileExt, toExt) {
|
|
122455
|
+
this.loaders = {
|
|
122456
|
+
...this.loaders,
|
|
122457
|
+
[fileExt.toUpperCase()]: {
|
|
122458
|
+
loader,
|
|
122459
|
+
toExt
|
|
122460
|
+
}
|
|
122461
|
+
};
|
|
122462
|
+
}
|
|
122333
122463
|
// not included in public docs
|
|
122334
122464
|
dropListener(e) {
|
|
122335
122465
|
e.stopPropagation();
|
|
@@ -124001,6 +124131,37 @@ var Niivue = class _Niivue {
|
|
|
124001
124131
|
this.document.meshes = this.meshes;
|
|
124002
124132
|
return this.document.download(fileName, compress);
|
|
124003
124133
|
}
|
|
124134
|
+
// generic loadImages that wraps loadVolumes and loadMeshes
|
|
124135
|
+
async loadImages(images) {
|
|
124136
|
+
const volumes = [];
|
|
124137
|
+
const meshes = [];
|
|
124138
|
+
for (const image of images) {
|
|
124139
|
+
if ("url" in image) {
|
|
124140
|
+
const ext = this.getFileExt(image.url);
|
|
124141
|
+
if (this.loaders[ext]) {
|
|
124142
|
+
const toExt = this.loaders[ext].toExt.toUpperCase();
|
|
124143
|
+
if (MESH_EXTENSIONS.includes(toExt)) {
|
|
124144
|
+
meshes.push(image);
|
|
124145
|
+
} else {
|
|
124146
|
+
volumes.push(image);
|
|
124147
|
+
}
|
|
124148
|
+
continue;
|
|
124149
|
+
}
|
|
124150
|
+
if (MESH_EXTENSIONS.includes(ext.toUpperCase())) {
|
|
124151
|
+
meshes.push(image);
|
|
124152
|
+
} else {
|
|
124153
|
+
volumes.push(image);
|
|
124154
|
+
}
|
|
124155
|
+
}
|
|
124156
|
+
}
|
|
124157
|
+
if (volumes.length > 0) {
|
|
124158
|
+
await this.loadVolumes(volumes);
|
|
124159
|
+
}
|
|
124160
|
+
if (meshes.length > 0) {
|
|
124161
|
+
await this.loadMeshes(meshes);
|
|
124162
|
+
}
|
|
124163
|
+
return this;
|
|
124164
|
+
}
|
|
124004
124165
|
/**
|
|
124005
124166
|
* load an array of volume objects
|
|
124006
124167
|
* @param volumeList - the array of objects to load. each object must have a resolvable "url" property at a minimum
|
|
@@ -124020,27 +124181,7 @@ var Niivue = class _Niivue {
|
|
|
124020
124181
|
this.volumes = [];
|
|
124021
124182
|
this.gl.clearColor(0, 0, 0, 1);
|
|
124022
124183
|
this.gl.clear(this.gl.COLOR_BUFFER_BIT);
|
|
124023
|
-
|
|
124024
|
-
await this.addVolumesFromUrl(volumeList);
|
|
124025
|
-
return this;
|
|
124026
|
-
}
|
|
124027
|
-
const imageOptions = {
|
|
124028
|
-
url: volumeList[0].url,
|
|
124029
|
-
headers: volumeList[0].headers,
|
|
124030
|
-
name: volumeList[0].name,
|
|
124031
|
-
colormap: volumeList[0].colormap ? volumeList[0].colormap : volumeList[0].colorMap,
|
|
124032
|
-
colormapNegative: volumeList[0].colormapNegative ? volumeList[0].colormapNegative : volumeList[0].colorMapNegative,
|
|
124033
|
-
opacity: volumeList[0].opacity,
|
|
124034
|
-
urlImgData: volumeList[0].urlImgData,
|
|
124035
|
-
cal_min: volumeList[0].cal_min,
|
|
124036
|
-
cal_max: volumeList[0].cal_max,
|
|
124037
|
-
trustCalMinMax: this.opts.trustCalMinMax,
|
|
124038
|
-
isManifest: volumeList[0].isManifest,
|
|
124039
|
-
frame4D: volumeList[0].frame4D,
|
|
124040
|
-
limitFrames4D: volumeList[0].limitFrames4D || this.opts.limitFrames4D,
|
|
124041
|
-
colorbarVisible: volumeList[0].colorbarVisible
|
|
124042
|
-
};
|
|
124043
|
-
await this.addVolumeFromUrl(imageOptions);
|
|
124184
|
+
await this.addVolumesFromUrl(volumeList);
|
|
124044
124185
|
return this;
|
|
124045
124186
|
}
|
|
124046
124187
|
/**
|
|
@@ -124071,6 +124212,28 @@ var Niivue = class _Niivue {
|
|
|
124071
124212
|
async addMeshesFromUrl(meshOptions) {
|
|
124072
124213
|
const promises = meshOptions.map(async (meshItem) => {
|
|
124073
124214
|
const ext = this.getFileExt(meshItem.url);
|
|
124215
|
+
if (this.loaders[ext]) {
|
|
124216
|
+
let itemToLoad = meshItem.url;
|
|
124217
|
+
const toExt = this.loaders[ext].toExt;
|
|
124218
|
+
let name = meshItem.name || meshItem.url;
|
|
124219
|
+
name = name.split("/").pop();
|
|
124220
|
+
if (typeof meshItem.url === "string") {
|
|
124221
|
+
const url = meshItem.url;
|
|
124222
|
+
try {
|
|
124223
|
+
const response = await fetch(url);
|
|
124224
|
+
if (!response.ok) {
|
|
124225
|
+
throw new Error(`Failed to load file: ${response.statusText}`);
|
|
124226
|
+
}
|
|
124227
|
+
itemToLoad = await response.arrayBuffer();
|
|
124228
|
+
} catch (error) {
|
|
124229
|
+
throw new Error(`Failed to load url ${url}: ${error}`);
|
|
124230
|
+
}
|
|
124231
|
+
}
|
|
124232
|
+
const { positions, indices } = await this.loaders[ext].loader(itemToLoad);
|
|
124233
|
+
meshItem.name = `${name}.${toExt}`;
|
|
124234
|
+
const mz3 = NVMeshUtilities.createMZ3(positions, indices, false);
|
|
124235
|
+
meshItem.buffer = mz3;
|
|
124236
|
+
}
|
|
124074
124237
|
if (ext === "JCON" || ext === "JSON") {
|
|
124075
124238
|
const response = await fetch(meshItem.url, {});
|
|
124076
124239
|
const json = await response.json();
|
|
@@ -124111,13 +124274,7 @@ var Niivue = class _Niivue {
|
|
|
124111
124274
|
this.meshes = [];
|
|
124112
124275
|
this.gl.clearColor(0, 0, 0, 1);
|
|
124113
124276
|
this.gl.clear(this.gl.COLOR_BUFFER_BIT);
|
|
124114
|
-
|
|
124115
|
-
await this.addMeshesFromUrl(meshList);
|
|
124116
|
-
this.updateGLVolume();
|
|
124117
|
-
this.drawScene();
|
|
124118
|
-
return this;
|
|
124119
|
-
}
|
|
124120
|
-
await this.addMeshFromUrl(meshList[0]);
|
|
124277
|
+
await this.addMeshesFromUrl(meshList);
|
|
124121
124278
|
this.updateGLVolume();
|
|
124122
124279
|
this.drawScene();
|
|
124123
124280
|
return this;
|
|
@@ -126682,6 +126839,7 @@ var Niivue = class _Niivue {
|
|
|
126682
126839
|
* @see {@link https://niivue.github.io/niivue/features/colormaps.html | live demo usage}
|
|
126683
126840
|
*/
|
|
126684
126841
|
setGamma(gamma = 1) {
|
|
126842
|
+
this.scene.gamma = gamma;
|
|
126685
126843
|
cmapper.gamma = gamma;
|
|
126686
126844
|
this.updateGLVolume();
|
|
126687
126845
|
}
|
|
@@ -127045,6 +127203,7 @@ var Niivue = class _Niivue {
|
|
|
127045
127203
|
}
|
|
127046
127204
|
if (this.opts.drawingEnabled) {
|
|
127047
127205
|
const pt = this.frac2vox(this.scene.crosshairPos);
|
|
127206
|
+
const ptMM = this.frac2mm(this.scene.crosshairPos);
|
|
127048
127207
|
if (this.opts.clickToSegment) {
|
|
127049
127208
|
const radius = this.opts.clickToSegmentRadius;
|
|
127050
127209
|
const steps = this.opts.clickToSegmentSteps;
|
|
@@ -127053,11 +127212,12 @@ var Niivue = class _Niivue {
|
|
|
127053
127212
|
this.drawPenAxCorSag = axCorSag;
|
|
127054
127213
|
for (let i3 = 1; i3 <= steps; i3++) {
|
|
127055
127214
|
const angle3 = i3 / steps * 2 * Math.PI;
|
|
127056
|
-
|
|
127057
|
-
|
|
127058
|
-
const
|
|
127059
|
-
xVox =
|
|
127060
|
-
yVox =
|
|
127215
|
+
const xMM = ptMM[0] + radius * Math.cos(angle3);
|
|
127216
|
+
const yMM = ptMM[1] + radius * Math.sin(angle3);
|
|
127217
|
+
const zMM = ptMM[2];
|
|
127218
|
+
const xVox = this.back.mm2vox([xMM, yMM, zMM])[0];
|
|
127219
|
+
const yVox = this.back.mm2vox([xMM, yMM, zMM])[1];
|
|
127220
|
+
const zVox = this.back.mm2vox([xMM, yMM, zMM])[2];
|
|
127061
127221
|
this.drawPt(xVox, yVox, zVox, this.opts.penValue);
|
|
127062
127222
|
this.drawPenFillPts.push([xVox, yVox, pt[2]]);
|
|
127063
127223
|
if (i3 === steps) {
|
|
@@ -127341,9 +127501,21 @@ var Niivue = class _Niivue {
|
|
|
127341
127501
|
const labels = [...this.document.labels, ...definedMeshLabels];
|
|
127342
127502
|
return labels;
|
|
127343
127503
|
}
|
|
127504
|
+
getConnectomeLabels() {
|
|
127505
|
+
const connectomes = this.meshes.filter((m) => m.type === "connectome" /* CONNECTOME */);
|
|
127506
|
+
const meshNodes = connectomes.flatMap((m) => m.nodes);
|
|
127507
|
+
const meshLabels = meshNodes.map((n) => n.label);
|
|
127508
|
+
const definedMeshLabels = meshLabels.filter((l) => l !== void 0);
|
|
127509
|
+
const nonAnchoredLabels = this.document.labels.filter((l) => l.anchor == null || l.anchor === 0 /* NONE */);
|
|
127510
|
+
const nonAnchoredLabelSet = new Set(definedMeshLabels);
|
|
127511
|
+
for (const label of nonAnchoredLabels) {
|
|
127512
|
+
nonAnchoredLabelSet.add(label);
|
|
127513
|
+
}
|
|
127514
|
+
return Array.from(nonAnchoredLabelSet);
|
|
127515
|
+
}
|
|
127344
127516
|
getBulletMarginWidth() {
|
|
127345
127517
|
let bulletMargin = 0;
|
|
127346
|
-
const labels = this.
|
|
127518
|
+
const labels = this.getConnectomeLabels();
|
|
127347
127519
|
if (labels.length === 0) {
|
|
127348
127520
|
return 0;
|
|
127349
127521
|
}
|
|
@@ -127360,7 +127532,7 @@ var Niivue = class _Niivue {
|
|
|
127360
127532
|
return bulletMargin;
|
|
127361
127533
|
}
|
|
127362
127534
|
getLegendPanelWidth() {
|
|
127363
|
-
const labels = this.
|
|
127535
|
+
const labels = this.getConnectomeLabels();
|
|
127364
127536
|
if (!this.opts.showLegend || labels.length === 0) {
|
|
127365
127537
|
return 0;
|
|
127366
127538
|
}
|
|
@@ -127386,7 +127558,7 @@ var Niivue = class _Niivue {
|
|
|
127386
127558
|
return width;
|
|
127387
127559
|
}
|
|
127388
127560
|
getLegendPanelHeight() {
|
|
127389
|
-
const labels = this.
|
|
127561
|
+
const labels = this.getConnectomeLabels();
|
|
127390
127562
|
let height = 0;
|
|
127391
127563
|
const scale6 = 1;
|
|
127392
127564
|
const verticalMargin = this.opts.textHeight * this.gl.canvas.height * scale6;
|
|
@@ -127828,7 +128000,7 @@ var Niivue = class _Niivue {
|
|
|
127828
128000
|
}
|
|
127829
128001
|
// not included in public docs
|
|
127830
128002
|
// show text labels for L/R, A/P, I/S dimensions
|
|
127831
|
-
drawSliceOrientationText(leftTopWidthHeight, axCorSag) {
|
|
128003
|
+
drawSliceOrientationText(leftTopWidthHeight, axCorSag, padLeftTop = [NaN, NaN]) {
|
|
127832
128004
|
this.gl.viewport(0, 0, this.gl.canvas.width, this.gl.canvas.height);
|
|
127833
128005
|
let topText = "S";
|
|
127834
128006
|
if (axCorSag === 0 /* AXIAL */) {
|
|
@@ -127842,8 +128014,32 @@ var Niivue = class _Niivue {
|
|
|
127842
128014
|
this.drawTextRightBelow([leftTopWidthHeight[0], leftTopWidthHeight[1]], leftText + topText);
|
|
127843
128015
|
return;
|
|
127844
128016
|
}
|
|
127845
|
-
|
|
127846
|
-
|
|
128017
|
+
let drawBelow = true;
|
|
128018
|
+
let drawRight = true;
|
|
128019
|
+
if (!isNaN(padLeftTop[0])) {
|
|
128020
|
+
const ht = this.opts.textHeight * this.gl.canvas.height + 2;
|
|
128021
|
+
if (padLeftTop[1] > ht) {
|
|
128022
|
+
this.drawTextBelow(
|
|
128023
|
+
[leftTopWidthHeight[0] + leftTopWidthHeight[2] * 0.5, leftTopWidthHeight[1] + padLeftTop[1] - ht],
|
|
128024
|
+
topText
|
|
128025
|
+
);
|
|
128026
|
+
drawBelow = false;
|
|
128027
|
+
}
|
|
128028
|
+
const wid = this.textWidth(ht, leftText) + 2;
|
|
128029
|
+
if (padLeftTop[0] > wid) {
|
|
128030
|
+
this.drawTextRight(
|
|
128031
|
+
[leftTopWidthHeight[0] + padLeftTop[0] - wid, leftTopWidthHeight[1] + leftTopWidthHeight[3] * 0.5],
|
|
128032
|
+
leftText
|
|
128033
|
+
);
|
|
128034
|
+
drawRight = false;
|
|
128035
|
+
}
|
|
128036
|
+
}
|
|
128037
|
+
if (drawBelow) {
|
|
128038
|
+
this.drawTextBelow([leftTopWidthHeight[0] + leftTopWidthHeight[2] * 0.5, leftTopWidthHeight[1]], topText);
|
|
128039
|
+
}
|
|
128040
|
+
if (drawRight) {
|
|
128041
|
+
this.drawTextRight([leftTopWidthHeight[0], leftTopWidthHeight[1] + leftTopWidthHeight[3] * 0.5], leftText);
|
|
128042
|
+
}
|
|
127847
128043
|
}
|
|
127848
128044
|
// not included in public docs
|
|
127849
128045
|
xyMM2xyzMM(axCorSag, sliceFrac) {
|
|
@@ -127881,7 +128077,7 @@ var Niivue = class _Niivue {
|
|
|
127881
128077
|
}
|
|
127882
128078
|
// not included in public docs
|
|
127883
128079
|
// draw 2D tile
|
|
127884
|
-
|
|
128080
|
+
draw2DMain(leftTopWidthHeight, axCorSag, customMM = NaN) {
|
|
127885
128081
|
let frac2mmTexture = this.volumes[0].frac2mm.slice();
|
|
127886
128082
|
let screen2 = this.screenFieldOfViewExtendedMM(axCorSag);
|
|
127887
128083
|
let mesh2ortho = mat4_exports.create();
|
|
@@ -127910,7 +128106,9 @@ var Niivue = class _Niivue {
|
|
|
127910
128106
|
elevation = isRadiolgical ? -90 : 90;
|
|
127911
128107
|
}
|
|
127912
128108
|
const gl = this.gl;
|
|
128109
|
+
let isStretchToScreen = false;
|
|
127913
128110
|
if (leftTopWidthHeight[2] === 0 || leftTopWidthHeight[3] === 0) {
|
|
128111
|
+
isStretchToScreen = true;
|
|
127914
128112
|
const pixPerMMw = gl.canvas.width / screen2.fovMM[0];
|
|
127915
128113
|
const pixPerMMh = gl.canvas.height / screen2.fovMM[1];
|
|
127916
128114
|
const pixPerMMmin = Math.min(pixPerMMw, pixPerMMh);
|
|
@@ -128057,9 +128255,32 @@ var Niivue = class _Niivue {
|
|
|
128057
128255
|
if (isNaN(customMM)) {
|
|
128058
128256
|
this.drawCrosshairs3D(false, 0.15, obj.modelViewProjectionMatrix, true, this.opts.isSliceMM);
|
|
128059
128257
|
}
|
|
128060
|
-
|
|
128258
|
+
if (isStretchToScreen) {
|
|
128259
|
+
this.drawSliceOrientationText(leftTopWidthHeight, axCorSag);
|
|
128260
|
+
}
|
|
128061
128261
|
this.readyForSync = true;
|
|
128062
128262
|
}
|
|
128263
|
+
draw2D(leftTopWidthHeight, axCorSag, customMM = NaN, imageWidthHeight = [NaN, NaN]) {
|
|
128264
|
+
const padLeftTop = [NaN, NaN];
|
|
128265
|
+
if (isNaN(imageWidthHeight[0])) {
|
|
128266
|
+
this.draw2DMain(leftTopWidthHeight, axCorSag, customMM);
|
|
128267
|
+
} else {
|
|
128268
|
+
const ltwh = leftTopWidthHeight.slice();
|
|
128269
|
+
padLeftTop[0] = Math.floor(0.5 * (ltwh[2] - imageWidthHeight[0]));
|
|
128270
|
+
padLeftTop[1] = Math.floor(0.5 * (ltwh[3] - imageWidthHeight[1]));
|
|
128271
|
+
ltwh[0] += padLeftTop[0];
|
|
128272
|
+
ltwh[1] += padLeftTop[1];
|
|
128273
|
+
ltwh[2] = imageWidthHeight[0];
|
|
128274
|
+
ltwh[3] = imageWidthHeight[1];
|
|
128275
|
+
this.draw2DMain(ltwh, axCorSag, customMM);
|
|
128276
|
+
}
|
|
128277
|
+
if (customMM === Infinity || customMM === -Infinity || axCorSag === 4 /* RENDER */) {
|
|
128278
|
+
return;
|
|
128279
|
+
}
|
|
128280
|
+
if (leftTopWidthHeight[2] !== 0 && leftTopWidthHeight[3] !== 0) {
|
|
128281
|
+
this.drawSliceOrientationText(leftTopWidthHeight, axCorSag, padLeftTop);
|
|
128282
|
+
}
|
|
128283
|
+
}
|
|
128063
128284
|
// not included in public docs
|
|
128064
128285
|
// determine 3D model view projection matrix
|
|
128065
128286
|
calculateMvpMatrix(_unused, leftTopWidthHeight = [0, 0, 0, 0], azimuth, elevation) {
|
|
@@ -128670,7 +128891,7 @@ var Niivue = class _Niivue {
|
|
|
128670
128891
|
* @param style - label style
|
|
128671
128892
|
* @param point - 3D point on the model
|
|
128672
128893
|
*/
|
|
128673
|
-
addLabel(text, style, points) {
|
|
128894
|
+
addLabel(text, style, points, anchor, onClick) {
|
|
128674
128895
|
const defaultStyle = {
|
|
128675
128896
|
textColor: this.opts.legendTextColor,
|
|
128676
128897
|
textScale: 1,
|
|
@@ -128682,7 +128903,7 @@ var Niivue = class _Niivue {
|
|
|
128682
128903
|
bulletColor: this.opts.legendTextColor
|
|
128683
128904
|
};
|
|
128684
128905
|
const labelStyle = style ? { ...defaultStyle, ...style } : { ...defaultStyle };
|
|
128685
|
-
const label = new NVLabel3D(text, labelStyle, points);
|
|
128906
|
+
const label = new NVLabel3D(text, { ...labelStyle }, points, anchor, onClick);
|
|
128686
128907
|
this.document.labels.push(label);
|
|
128687
128908
|
return label;
|
|
128688
128909
|
}
|
|
@@ -128700,6 +128921,60 @@ var Niivue = class _Niivue {
|
|
|
128700
128921
|
return screenPoint;
|
|
128701
128922
|
}
|
|
128702
128923
|
getLabelAtPoint(screenPoint) {
|
|
128924
|
+
const scale6 = 1;
|
|
128925
|
+
const size = this.opts.textHeight * Math.min(this.gl.canvas.height, this.gl.canvas.width) * scale6;
|
|
128926
|
+
const verticalMargin = this.opts.textHeight * this.gl.canvas.height * scale6;
|
|
128927
|
+
for (const label of this.document.labels) {
|
|
128928
|
+
if (label.anchor == null || label.anchor === 0 /* NONE */) {
|
|
128929
|
+
continue;
|
|
128930
|
+
}
|
|
128931
|
+
const labelSize = this.opts.textHeight * this.gl.canvas.height * label.style.textScale;
|
|
128932
|
+
const textHeight = this.textHeight(labelSize, label.text);
|
|
128933
|
+
const textWidth = this.textWidth(labelSize, label.text);
|
|
128934
|
+
if (label.anchor & 1 /* LEFT */) {
|
|
128935
|
+
if (screenPoint[0] > textWidth) {
|
|
128936
|
+
continue;
|
|
128937
|
+
}
|
|
128938
|
+
}
|
|
128939
|
+
if (label.anchor & 2 /* CENTER */) {
|
|
128940
|
+
if (screenPoint[0] < (this.gl.canvas.width - textWidth) / 2) {
|
|
128941
|
+
continue;
|
|
128942
|
+
}
|
|
128943
|
+
if (screenPoint[0] > (this.gl.canvas.width + textWidth) / 2) {
|
|
128944
|
+
continue;
|
|
128945
|
+
}
|
|
128946
|
+
}
|
|
128947
|
+
if (label.anchor & 4 /* RIGHT */) {
|
|
128948
|
+
if (screenPoint[0] < this.gl.canvas.width - textWidth) {
|
|
128949
|
+
continue;
|
|
128950
|
+
}
|
|
128951
|
+
}
|
|
128952
|
+
if (label.anchor & 8 /* TOP */) {
|
|
128953
|
+
if (screenPoint[1] < verticalMargin / 2) {
|
|
128954
|
+
continue;
|
|
128955
|
+
}
|
|
128956
|
+
if (screenPoint[1] > textHeight + verticalMargin / 2) {
|
|
128957
|
+
continue;
|
|
128958
|
+
}
|
|
128959
|
+
}
|
|
128960
|
+
if (label.anchor & 16 /* MIDDLE */) {
|
|
128961
|
+
if (screenPoint[1] < (this.gl.canvas.height - textHeight - verticalMargin) / 2) {
|
|
128962
|
+
continue;
|
|
128963
|
+
}
|
|
128964
|
+
if (screenPoint[1] > (this.gl.canvas.height + textHeight - verticalMargin / 2) / 2) {
|
|
128965
|
+
continue;
|
|
128966
|
+
}
|
|
128967
|
+
}
|
|
128968
|
+
if (label.anchor & 32 /* BOTTOM */) {
|
|
128969
|
+
if (screenPoint[1] < this.gl.canvas.height - textHeight - verticalMargin) {
|
|
128970
|
+
continue;
|
|
128971
|
+
}
|
|
128972
|
+
if (screenPoint[1] > this.gl.canvas.height - verticalMargin / 2) {
|
|
128973
|
+
continue;
|
|
128974
|
+
}
|
|
128975
|
+
}
|
|
128976
|
+
return label;
|
|
128977
|
+
}
|
|
128703
128978
|
log.debug("screenPoint", screenPoint);
|
|
128704
128979
|
const panelHeight = this.getLegendPanelHeight();
|
|
128705
128980
|
const panelWidth = this.getLegendPanelWidth();
|
|
@@ -128709,9 +128984,7 @@ var Niivue = class _Niivue {
|
|
|
128709
128984
|
if (screenPoint[0] < left || screenPoint[1] < top || screenPoint[0] > left + panelWidth || screenPoint[1] > top + panelHeight) {
|
|
128710
128985
|
return null;
|
|
128711
128986
|
}
|
|
128712
|
-
const
|
|
128713
|
-
const size = this.opts.textHeight * Math.min(this.gl.canvas.height, this.gl.canvas.width) * scale6;
|
|
128714
|
-
const labels = this.getAllLabels();
|
|
128987
|
+
const labels = this.getConnectomeLabels();
|
|
128715
128988
|
for (const label of labels) {
|
|
128716
128989
|
const labelSize = this.opts.textHeight * this.gl.canvas.height * label.style.textScale;
|
|
128717
128990
|
const textHeight = this.textHeight(labelSize, label.text);
|
|
@@ -128740,7 +129013,7 @@ var Niivue = class _Niivue {
|
|
|
128740
129013
|
}
|
|
128741
129014
|
}
|
|
128742
129015
|
// not included in public docs
|
|
128743
|
-
draw3DLabel(label, pos, mvpMatrix, leftTopWidthHeight, bulletMargin
|
|
129016
|
+
draw3DLabel(label, pos, mvpMatrix, leftTopWidthHeight, bulletMargin, legendWidth, secondPass) {
|
|
128744
129017
|
const text = label.text;
|
|
128745
129018
|
const left = pos[0];
|
|
128746
129019
|
const top = pos[1];
|
|
@@ -128757,22 +129030,24 @@ var Niivue = class _Niivue {
|
|
|
128757
129030
|
this.drawCircle([rectLeft, rectTop, bulletSize, bulletSize], label.style.bulletColor);
|
|
128758
129031
|
}
|
|
128759
129032
|
let textLeft = left;
|
|
128760
|
-
if (
|
|
128761
|
-
|
|
128762
|
-
|
|
128763
|
-
|
|
129033
|
+
if (legendWidth) {
|
|
129034
|
+
if (label.style.textAlignment !== "left" /* LEFT */) {
|
|
129035
|
+
const textWidth = this.textWidth(label.style.textScale, label.text) * size;
|
|
129036
|
+
if (label.style.textAlignment === "right" /* RIGHT */) {
|
|
129037
|
+
textLeft = left + legendWidth - size * 1.5 - textWidth;
|
|
129038
|
+
} else {
|
|
129039
|
+
const remaining = legendWidth - (bulletMargin || size);
|
|
129040
|
+
textLeft += (remaining - textWidth) / 2;
|
|
129041
|
+
}
|
|
128764
129042
|
} else {
|
|
128765
|
-
|
|
128766
|
-
textLeft += (remaining - textWidth) / 2;
|
|
129043
|
+
textLeft += bulletMargin;
|
|
128767
129044
|
}
|
|
128768
|
-
} else {
|
|
128769
|
-
textLeft += bulletMargin;
|
|
128770
129045
|
}
|
|
128771
129046
|
this.drawText([textLeft, top], text, label.style.textScale, label.style.textColor);
|
|
128772
129047
|
}
|
|
128773
129048
|
// not included in public docs
|
|
128774
129049
|
draw3DLabels(mvpMatrix, leftTopWidthHeight, secondPass = false) {
|
|
128775
|
-
const labels = this.
|
|
129050
|
+
const labels = this.getConnectomeLabels();
|
|
128776
129051
|
if (!this.opts.showLegend || labels.length === 0) {
|
|
128777
129052
|
return;
|
|
128778
129053
|
}
|
|
@@ -128810,6 +129085,51 @@ var Niivue = class _Niivue {
|
|
|
128810
129085
|
}
|
|
128811
129086
|
}
|
|
128812
129087
|
}
|
|
129088
|
+
drawAnchoredLabels() {
|
|
129089
|
+
const size = this.opts.textHeight * Math.min(this.gl.canvas.height, this.gl.canvas.width) * 1;
|
|
129090
|
+
const anchoredLabels = this.document.labels.filter((l) => l.anchor != null && l.anchor !== 0 /* NONE */);
|
|
129091
|
+
for (const label of anchoredLabels) {
|
|
129092
|
+
const text = label.text;
|
|
129093
|
+
const textHeight = this.textHeight(label.style.textScale, text) * size;
|
|
129094
|
+
const textWidth = this.textWidth(label.style.textScale, text) * size;
|
|
129095
|
+
let left;
|
|
129096
|
+
let top;
|
|
129097
|
+
const scale6 = 1;
|
|
129098
|
+
const verticalMargin = this.opts.textHeight * this.gl.canvas.height * scale6;
|
|
129099
|
+
const rectHeightDiff = verticalMargin;
|
|
129100
|
+
let rectWidthDiff = verticalMargin / 4;
|
|
129101
|
+
let rectHorizontalOffset = 0;
|
|
129102
|
+
let rectVerticalOffset = 0;
|
|
129103
|
+
if (label.anchor & 1 /* LEFT */) {
|
|
129104
|
+
left = 0;
|
|
129105
|
+
}
|
|
129106
|
+
if (label.anchor & 4 /* RIGHT */) {
|
|
129107
|
+
left = this.canvas.width - textWidth;
|
|
129108
|
+
rectHorizontalOffset -= verticalMargin / 4;
|
|
129109
|
+
}
|
|
129110
|
+
if (label.anchor & 2 /* CENTER */) {
|
|
129111
|
+
left = (this.canvas.width - textWidth) / 2;
|
|
129112
|
+
rectHorizontalOffset -= verticalMargin / 4;
|
|
129113
|
+
rectWidthDiff += verticalMargin / 4;
|
|
129114
|
+
}
|
|
129115
|
+
if (label.anchor & 8 /* TOP */) {
|
|
129116
|
+
top = 0;
|
|
129117
|
+
}
|
|
129118
|
+
if (label.anchor & 16 /* MIDDLE */) {
|
|
129119
|
+
top = (this.canvas.height - textHeight - verticalMargin) / 2;
|
|
129120
|
+
rectVerticalOffset -= verticalMargin / 4;
|
|
129121
|
+
}
|
|
129122
|
+
if (label.anchor & 32 /* BOTTOM */) {
|
|
129123
|
+
top = this.canvas.height - textHeight - verticalMargin;
|
|
129124
|
+
rectVerticalOffset -= verticalMargin / 4;
|
|
129125
|
+
}
|
|
129126
|
+
this.drawRect(
|
|
129127
|
+
[left + rectHorizontalOffset, top + rectVerticalOffset, textWidth + rectWidthDiff, textHeight + rectHeightDiff],
|
|
129128
|
+
label.style.backgroundColor
|
|
129129
|
+
);
|
|
129130
|
+
this.draw3DLabel(label, [left, top]);
|
|
129131
|
+
}
|
|
129132
|
+
}
|
|
128813
129133
|
// not included in public docs
|
|
128814
129134
|
draw3D(leftTopWidthHeight = [0, 0, 0, 0], mvpMatrix = null, modelMatrix = null, normalMatrix = null, azimuth = null, elevation = 0) {
|
|
128815
129135
|
const isMosaic = azimuth !== null;
|
|
@@ -129685,6 +130005,12 @@ var Niivue = class _Niivue {
|
|
|
129685
130005
|
}
|
|
129686
130006
|
const isDrawPenDown = isFinite(this.drawPenLocation[0]) && this.opts.drawingEnabled;
|
|
129687
130007
|
const { volScale } = this.sliceScale();
|
|
130008
|
+
const actualScale = volScale.slice();
|
|
130009
|
+
if (this.opts.multiplanarEqualSize) {
|
|
130010
|
+
volScale[0] = 1;
|
|
130011
|
+
volScale[1] = 1;
|
|
130012
|
+
volScale[2] = 1;
|
|
130013
|
+
}
|
|
129688
130014
|
if (typeof this.opts.multiplanarPadPixels !== "number") {
|
|
129689
130015
|
log.debug("multiplanarPadPixels must be numeric");
|
|
129690
130016
|
}
|
|
@@ -129722,38 +130048,43 @@ var Niivue = class _Niivue {
|
|
|
129722
130048
|
isDrawGrid = true;
|
|
129723
130049
|
}
|
|
129724
130050
|
}
|
|
130051
|
+
let ltwh = ltwh2x2;
|
|
129725
130052
|
if (isDrawColumn) {
|
|
129726
|
-
|
|
130053
|
+
ltwh = ltwh1x3;
|
|
129727
130054
|
if (isShowRender || this.opts.multiplanarShowRender === 2 /* AUTO */ && ltwh1x4[4] >= ltwh1x3[4]) {
|
|
129728
130055
|
ltwh = ltwh1x4;
|
|
129729
130056
|
} else {
|
|
129730
130057
|
isDraw3D = false;
|
|
129731
130058
|
}
|
|
129732
|
-
const sX = volScale[0] * ltwh[4];
|
|
129733
|
-
const sY = volScale[1] * ltwh[4];
|
|
129734
|
-
const sZ = volScale[2] * ltwh[4];
|
|
129735
|
-
const sMx = mx * ltwh[4];
|
|
129736
|
-
this.draw2D([ltwh[0], ltwh[1], sX, sY], 0);
|
|
129737
|
-
this.draw2D([ltwh[0], ltwh[1] + sY + pad, sX, sZ], 1);
|
|
129738
|
-
this.draw2D([ltwh[0], ltwh[1] + sY + pad + sZ + pad, sY, sZ], 2);
|
|
129739
|
-
if (isDraw3D) {
|
|
129740
|
-
this.draw3D([ltwh[0], ltwh[1] + sY + sZ + sZ + pad * 3, sMx, sMx]);
|
|
129741
|
-
}
|
|
129742
130059
|
} else if (isDrawRow) {
|
|
129743
|
-
|
|
130060
|
+
ltwh = ltwh3x1;
|
|
129744
130061
|
if (isShowRender || this.opts.multiplanarShowRender === 2 /* AUTO */ && ltwh4x1[4] >= ltwh3x1[4]) {
|
|
129745
130062
|
ltwh = ltwh4x1;
|
|
129746
130063
|
} else {
|
|
129747
130064
|
isDraw3D = false;
|
|
129748
130065
|
}
|
|
129749
|
-
|
|
129750
|
-
|
|
129751
|
-
|
|
129752
|
-
|
|
129753
|
-
|
|
129754
|
-
|
|
130066
|
+
}
|
|
130067
|
+
const sX = volScale[0] * ltwh[4];
|
|
130068
|
+
const sY = volScale[1] * ltwh[4];
|
|
130069
|
+
const sZ = volScale[2] * ltwh[4];
|
|
130070
|
+
const actualX = actualScale[0] * ltwh[4];
|
|
130071
|
+
const actualY = actualScale[1] * ltwh[4];
|
|
130072
|
+
const actualZ = actualScale[2] * ltwh[4];
|
|
130073
|
+
if (isDrawColumn) {
|
|
130074
|
+
this.draw2D([ltwh[0], ltwh[1], sX, sY], 0, NaN, [actualX, actualY]);
|
|
130075
|
+
this.draw2D([ltwh[0], ltwh[1] + sY + pad, sX, sZ], 1, NaN, [actualX, actualZ]);
|
|
130076
|
+
this.draw2D([ltwh[0], ltwh[1] + sY + pad + sZ + pad, sY, sZ], 2, NaN, [actualY, actualZ]);
|
|
129755
130077
|
if (isDraw3D) {
|
|
129756
|
-
|
|
130078
|
+
const sMx = mx * ltwh[4];
|
|
130079
|
+
this.draw3D([ltwh[0], ltwh[1] + sY + sZ + sZ + pad * 3, sMx, sMx]);
|
|
130080
|
+
}
|
|
130081
|
+
} else if (isDrawRow) {
|
|
130082
|
+
this.draw2D([ltwh[0], ltwh[1], sX, sY], 0, NaN, [actualX, actualY]);
|
|
130083
|
+
this.draw2D([ltwh[0] + sX + pad, ltwh[1], sX, sZ], 1, NaN, [actualX, actualZ]);
|
|
130084
|
+
this.draw2D([ltwh[0] + sX + sX + pad * 2, ltwh[1], sY, sZ], 2, NaN, [actualY, actualZ]);
|
|
130085
|
+
if (isDraw3D) {
|
|
130086
|
+
const sMx = mx * ltwh[4];
|
|
130087
|
+
this.draw3D([ltwh[0] + sX + sX + sY + pad * 3, ltwh[1], sMx, sMx]);
|
|
129757
130088
|
}
|
|
129758
130089
|
} else if (isDrawGrid) {
|
|
129759
130090
|
if (!isShowRender) {
|
|
@@ -129762,13 +130093,9 @@ var Niivue = class _Niivue {
|
|
|
129762
130093
|
if (this.opts.multiplanarShowRender === 2 /* AUTO */) {
|
|
129763
130094
|
isDraw3D = true;
|
|
129764
130095
|
}
|
|
129765
|
-
|
|
129766
|
-
|
|
129767
|
-
|
|
129768
|
-
const sZ = volScale[2] * ltwh[4];
|
|
129769
|
-
this.draw2D([ltwh[0], ltwh[1] + sZ + pad, sX, sY], 0);
|
|
129770
|
-
this.draw2D([ltwh[0], ltwh[1], sX, sZ], 1);
|
|
129771
|
-
this.draw2D([ltwh[0] + sX + pad, ltwh[1], sY, sZ], 2);
|
|
130096
|
+
this.draw2D([ltwh[0], ltwh[1] + sZ + pad, sX, sY], 0, NaN, [actualX, actualY]);
|
|
130097
|
+
this.draw2D([ltwh[0], ltwh[1], sX, sZ], 1, NaN, [actualX, actualZ]);
|
|
130098
|
+
this.draw2D([ltwh[0] + sX + pad, ltwh[1], sY, sZ], 2, NaN, [actualY, actualZ]);
|
|
129772
130099
|
if (isDraw3D) {
|
|
129773
130100
|
this.draw3D([ltwh[0] + sX + pad, ltwh[1] + sZ + pad, sY, sY]);
|
|
129774
130101
|
}
|
|
@@ -129833,10 +130160,25 @@ var Niivue = class _Niivue {
|
|
|
129833
130160
|
height
|
|
129834
130161
|
]);
|
|
129835
130162
|
}
|
|
130163
|
+
if (this.opts.clickToSegment) {
|
|
130164
|
+
const x = this.mousePos[0];
|
|
130165
|
+
const y = this.mousePos[1];
|
|
130166
|
+
const tileIdx = this.tileIndex(x, y);
|
|
130167
|
+
if (tileIdx > -1) {
|
|
130168
|
+
const fovMM = this.screenSlices[tileIdx].fovMM;
|
|
130169
|
+
const ltwh = this.screenSlices[tileIdx].leftTopWidthHeight;
|
|
130170
|
+
const pixPerMM = ltwh[2] / fovMM[0];
|
|
130171
|
+
const color = this.opts.crosshairColor;
|
|
130172
|
+
const segmentCursorColor = [color[0], color[1], color[2], 0.4];
|
|
130173
|
+
const radius = this.opts.clickToSegmentRadius * pixPerMM;
|
|
130174
|
+
this.drawCircle([x - radius, y - radius, radius * 2, radius * 2], segmentCursorColor, 1);
|
|
130175
|
+
}
|
|
130176
|
+
}
|
|
129836
130177
|
const pos = this.frac2mm([this.scene.crosshairPos[0], this.scene.crosshairPos[1], this.scene.crosshairPos[2]]);
|
|
129837
130178
|
posString = pos[0].toFixed(2) + "\xD7" + pos[1].toFixed(2) + "\xD7" + pos[2].toFixed(2);
|
|
129838
130179
|
this.readyForSync = true;
|
|
129839
130180
|
this.sync();
|
|
130181
|
+
this.drawAnchoredLabels();
|
|
129840
130182
|
return posString;
|
|
129841
130183
|
}
|
|
129842
130184
|
// not included in public docs
|
|
@@ -129871,6 +130213,7 @@ export {
|
|
|
129871
130213
|
DEFAULT_OPTIONS,
|
|
129872
130214
|
DRAG_MODE,
|
|
129873
130215
|
INITIAL_SCENE_DATA,
|
|
130216
|
+
LabelAnchorPoint,
|
|
129874
130217
|
LabelLineTerminator,
|
|
129875
130218
|
LabelTextAlignment,
|
|
129876
130219
|
MULTIPLANAR_TYPE,
|