@niivue/niivue 0.43.6 → 0.44.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/build/index.d.ts +32 -2
- package/build/index.js +200 -45
- package/build/index.js.map +1 -1
- package/build/index.min.js +1 -1
- package/dist/index.d.ts +32 -2
- package/dist/index.js +200 -45
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/niivue.umd.js +35 -35
- package/package.json +1 -1
- package/src/index.html +43 -25
- package/src/niivue/index.ts +219 -48
- package/src/nvdocument.ts +21 -1
- package/src/nvimage/utils.ts +2 -0
package/build/index.d.ts
CHANGED
|
@@ -211,6 +211,7 @@ type ImageFromUrlOptions = {
|
|
|
211
211
|
useQFormNotSForm?: boolean;
|
|
212
212
|
alphaThreshold?: boolean;
|
|
213
213
|
colormapNegative?: string;
|
|
214
|
+
colorMapNegative?: string;
|
|
214
215
|
cal_minNeg?: number;
|
|
215
216
|
cal_maxNeg?: number;
|
|
216
217
|
colorbarVisible?: boolean;
|
|
@@ -558,6 +559,11 @@ declare enum SLICE_TYPE {
|
|
|
558
559
|
MULTIPLANAR = 3,
|
|
559
560
|
RENDER = 4
|
|
560
561
|
}
|
|
562
|
+
declare enum SHOW_RENDER {
|
|
563
|
+
NEVER = 0,
|
|
564
|
+
ALWAYS = 1,
|
|
565
|
+
AUTO = 2
|
|
566
|
+
}
|
|
561
567
|
/**
|
|
562
568
|
* Multi-planar layout
|
|
563
569
|
* @ignore
|
|
@@ -613,6 +619,7 @@ type NVConfigOptions = {
|
|
|
613
619
|
isOrientCube: boolean;
|
|
614
620
|
multiplanarPadPixels: number;
|
|
615
621
|
multiplanarForceRender: boolean;
|
|
622
|
+
multiplanarShowRender: SHOW_RENDER;
|
|
616
623
|
isRadiologicalConvention: boolean;
|
|
617
624
|
meshThicknessOn2D: number | string;
|
|
618
625
|
dragMode: DRAG_MODE;
|
|
@@ -645,6 +652,11 @@ type NVConfigOptions = {
|
|
|
645
652
|
multiplanarLayout: MULTIPLANAR_TYPE;
|
|
646
653
|
renderOverlayBlend: number;
|
|
647
654
|
sliceMosaicString: string;
|
|
655
|
+
centerMosaic: boolean;
|
|
656
|
+
clickToSegment: boolean;
|
|
657
|
+
clickToSegmentRadius: number;
|
|
658
|
+
clickToSegmentSteps: number;
|
|
659
|
+
clickToSegmentBright: boolean;
|
|
648
660
|
};
|
|
649
661
|
declare const DEFAULT_OPTIONS: NVConfigOptions;
|
|
650
662
|
type SceneData = {
|
|
@@ -1687,7 +1699,6 @@ declare class Niivue {
|
|
|
1687
1699
|
private resizeObserver;
|
|
1688
1700
|
syncOpts: Record<string, unknown>;
|
|
1689
1701
|
readyForSync: boolean;
|
|
1690
|
-
centerMosaic: boolean;
|
|
1691
1702
|
uiData: UIData;
|
|
1692
1703
|
back: NVImage | null;
|
|
1693
1704
|
overlays: NVImage[];
|
|
@@ -1773,6 +1784,19 @@ declare class Niivue {
|
|
|
1773
1784
|
* }
|
|
1774
1785
|
*/
|
|
1775
1786
|
onIntensityChange: (volume: NVImage) => void;
|
|
1787
|
+
/**
|
|
1788
|
+
* callback function when clickToSegment is enabled and the user clicks on the image. data contains the volume of the segmented region in mm3 and mL
|
|
1789
|
+
* @example
|
|
1790
|
+
* niivue.onClickToSegment = (data) => {
|
|
1791
|
+
* console.log('clicked to segment')
|
|
1792
|
+
* console.log('volume mm3: ', data.mm3)
|
|
1793
|
+
* console.log('volume mL: ', data.mL)
|
|
1794
|
+
* }
|
|
1795
|
+
*/
|
|
1796
|
+
onClickToSegment: (data: {
|
|
1797
|
+
mm3: number;
|
|
1798
|
+
mL: number;
|
|
1799
|
+
}) => void;
|
|
1776
1800
|
/**
|
|
1777
1801
|
* callback function to run when a new volume is loaded
|
|
1778
1802
|
* @example
|
|
@@ -2042,6 +2066,7 @@ declare class Niivue {
|
|
|
2042
2066
|
* @see {@link https://niivue.github.io/niivue/features/document.3d.html | live demo usage}
|
|
2043
2067
|
*/
|
|
2044
2068
|
addVolumeFromUrl(imageOptions: ImageFromUrlOptions): Promise<NVImage>;
|
|
2069
|
+
addVolumesFromUrl(imageOptionsArray: ImageFromUrlOptions[]): Promise<NVImage[]>;
|
|
2045
2070
|
/**
|
|
2046
2071
|
* Find media by url
|
|
2047
2072
|
*/
|
|
@@ -2555,6 +2580,11 @@ declare class Niivue {
|
|
|
2555
2580
|
* @see {@link https://niivue.github.io/niivue/features/multiuser.meshes.html | live demo usage}
|
|
2556
2581
|
*/
|
|
2557
2582
|
addMeshFromUrl(meshOptions: LoadFromUrlParams): Promise<NVMesh>;
|
|
2583
|
+
/**
|
|
2584
|
+
* Add mesh and notify subscribers
|
|
2585
|
+
* @see {@link https://niivue.github.io/niivue/features/multiuser.meshes.html | live demo usage}
|
|
2586
|
+
*/
|
|
2587
|
+
addMeshesFromUrl(meshOptions: LoadFromUrlParams[]): Promise<NVMesh[]>;
|
|
2558
2588
|
/**
|
|
2559
2589
|
* load an array of meshes
|
|
2560
2590
|
* @param meshList - the array of objects to load. each object must have a resolvable "url" property at a minimum
|
|
@@ -2979,4 +3009,4 @@ declare class Niivue {
|
|
|
2979
3009
|
set gl(gl: WebGL2RenderingContext | null);
|
|
2980
3010
|
}
|
|
2981
3011
|
|
|
2982
|
-
export { type Connectome, type ConnectomeOptions, DEFAULT_OPTIONS, DRAG_MODE, type DocumentData, type DragReleaseParams, type ExportDocumentData, INITIAL_SCENE_DATA, LabelLineTerminator, LabelTextAlignment, type LegacyConnectome, type LegacyNodes, MULTIPLANAR_TYPE, type NVConfigOptions, type NVConnectomeEdge, type NVConnectomeNode, NVController, NVDocument, NVImage, NVImageFromUrlOptions, NVLabel3D, NVLabel3DStyle, NVMesh, NVMeshFromUrlOptions, NVMeshLayerDefaults, NVMeshLoaders, NVUtilities, type NiftiHeader, type NiiVueLocation, type NiiVueLocationValue, Niivue, type Point, SLICE_TYPE, type Scene, type Volume, cmapper, ColorTables as colortables };
|
|
3012
|
+
export { type Connectome, type ConnectomeOptions, DEFAULT_OPTIONS, DRAG_MODE, type DocumentData, type DragReleaseParams, type ExportDocumentData, INITIAL_SCENE_DATA, LabelLineTerminator, LabelTextAlignment, type LegacyConnectome, type LegacyNodes, MULTIPLANAR_TYPE, type NVConfigOptions, type NVConnectomeEdge, type NVConnectomeNode, NVController, NVDocument, NVImage, NVImageFromUrlOptions, NVLabel3D, NVLabel3DStyle, NVMesh, NVMeshFromUrlOptions, NVMeshLayerDefaults, NVMeshLoaders, NVUtilities, type NiftiHeader, type NiiVueLocation, type NiiVueLocationValue, Niivue, type Point, SHOW_RENDER, SLICE_TYPE, type Scene, type Volume, cmapper, ColorTables as colortables };
|
package/build/index.js
CHANGED
|
@@ -13,7 +13,7 @@ var __publicField = (obj, key, value) => {
|
|
|
13
13
|
import { mat4 as mat46, vec2, vec3 as vec311, vec4 as vec48 } from "gl-matrix";
|
|
14
14
|
|
|
15
15
|
// package.json
|
|
16
|
-
var version = "0.
|
|
16
|
+
var version = "0.44.0";
|
|
17
17
|
|
|
18
18
|
// src/logger.ts
|
|
19
19
|
var _Log = class _Log {
|
|
@@ -21929,6 +21929,12 @@ var SLICE_TYPE = /* @__PURE__ */ ((SLICE_TYPE2) => {
|
|
|
21929
21929
|
SLICE_TYPE2[SLICE_TYPE2["RENDER"] = 4] = "RENDER";
|
|
21930
21930
|
return SLICE_TYPE2;
|
|
21931
21931
|
})(SLICE_TYPE || {});
|
|
21932
|
+
var SHOW_RENDER = /* @__PURE__ */ ((SHOW_RENDER2) => {
|
|
21933
|
+
SHOW_RENDER2[SHOW_RENDER2["NEVER"] = 0] = "NEVER";
|
|
21934
|
+
SHOW_RENDER2[SHOW_RENDER2["ALWAYS"] = 1] = "ALWAYS";
|
|
21935
|
+
SHOW_RENDER2[SHOW_RENDER2["AUTO"] = 2] = "AUTO";
|
|
21936
|
+
return SHOW_RENDER2;
|
|
21937
|
+
})(SHOW_RENDER || {});
|
|
21932
21938
|
var MULTIPLANAR_TYPE = /* @__PURE__ */ ((MULTIPLANAR_TYPE2) => {
|
|
21933
21939
|
MULTIPLANAR_TYPE2[MULTIPLANAR_TYPE2["AUTO"] = 0] = "AUTO";
|
|
21934
21940
|
MULTIPLANAR_TYPE2[MULTIPLANAR_TYPE2["COLUMN"] = 1] = "COLUMN";
|
|
@@ -21975,7 +21981,10 @@ var DEFAULT_OPTIONS = {
|
|
|
21975
21981
|
isColorbar: false,
|
|
21976
21982
|
isOrientCube: false,
|
|
21977
21983
|
multiplanarPadPixels: 0,
|
|
21984
|
+
// @deprecated
|
|
21978
21985
|
multiplanarForceRender: false,
|
|
21986
|
+
multiplanarShowRender: 2 /* AUTO */,
|
|
21987
|
+
// auto is the same behaviour as multiplanarForceRender: false
|
|
21979
21988
|
isRadiologicalConvention: false,
|
|
21980
21989
|
meshThicknessOn2D: Infinity,
|
|
21981
21990
|
dragMode: 1 /* contrast */,
|
|
@@ -22006,7 +22015,12 @@ var DEFAULT_OPTIONS = {
|
|
|
22006
22015
|
legendTextColor: [1, 1, 1, 1],
|
|
22007
22016
|
multiplanarLayout: 0 /* AUTO */,
|
|
22008
22017
|
renderOverlayBlend: 1,
|
|
22009
|
-
sliceMosaicString: ""
|
|
22018
|
+
sliceMosaicString: "",
|
|
22019
|
+
centerMosaic: false,
|
|
22020
|
+
clickToSegment: false,
|
|
22021
|
+
clickToSegmentRadius: 2,
|
|
22022
|
+
clickToSegmentSteps: 10,
|
|
22023
|
+
clickToSegmentBright: true
|
|
22010
22024
|
};
|
|
22011
22025
|
var INITIAL_SCENE_DATA = {
|
|
22012
22026
|
azimuth: 110,
|
|
@@ -23783,7 +23797,6 @@ var Niivue = class _Niivue {
|
|
|
23783
23797
|
__publicField(this, "resizeObserver", null);
|
|
23784
23798
|
__publicField(this, "syncOpts", {});
|
|
23785
23799
|
__publicField(this, "readyForSync", false);
|
|
23786
|
-
__publicField(this, "centerMosaic", false);
|
|
23787
23800
|
// UI Data
|
|
23788
23801
|
__publicField(this, "uiData", {
|
|
23789
23802
|
mousedown: false,
|
|
@@ -23947,6 +23960,17 @@ var Niivue = class _Niivue {
|
|
|
23947
23960
|
*/
|
|
23948
23961
|
__publicField(this, "onIntensityChange", () => {
|
|
23949
23962
|
});
|
|
23963
|
+
/**
|
|
23964
|
+
* callback function when clickToSegment is enabled and the user clicks on the image. data contains the volume of the segmented region in mm3 and mL
|
|
23965
|
+
* @example
|
|
23966
|
+
* niivue.onClickToSegment = (data) => {
|
|
23967
|
+
* console.log('clicked to segment')
|
|
23968
|
+
* console.log('volume mm3: ', data.mm3)
|
|
23969
|
+
* console.log('volume mL: ', data.mL)
|
|
23970
|
+
* }
|
|
23971
|
+
*/
|
|
23972
|
+
__publicField(this, "onClickToSegment", () => {
|
|
23973
|
+
});
|
|
23950
23974
|
/**
|
|
23951
23975
|
* callback function to run when a new volume is loaded
|
|
23952
23976
|
* @example
|
|
@@ -24982,6 +25006,39 @@ var Niivue = class _Niivue {
|
|
|
24982
25006
|
this.addVolume(volume);
|
|
24983
25007
|
return volume;
|
|
24984
25008
|
}
|
|
25009
|
+
async addVolumesFromUrl(imageOptionsArray) {
|
|
25010
|
+
const promises = imageOptionsArray.map(async (imageItem) => {
|
|
25011
|
+
const imageOptions = {
|
|
25012
|
+
url: imageItem.url,
|
|
25013
|
+
headers: imageItem.headers,
|
|
25014
|
+
name: imageItem.name,
|
|
25015
|
+
colormap: imageItem.colormap ? imageItem.colormap : imageItem.colorMap,
|
|
25016
|
+
colormapNegative: imageItem.colormapNegative ? imageItem.colormapNegative : imageItem.colorMapNegative,
|
|
25017
|
+
opacity: imageItem.opacity,
|
|
25018
|
+
urlImgData: imageItem.urlImgData,
|
|
25019
|
+
cal_min: imageItem.cal_min,
|
|
25020
|
+
cal_max: imageItem.cal_max,
|
|
25021
|
+
trustCalMinMax: this.opts.trustCalMinMax,
|
|
25022
|
+
isManifest: imageItem.isManifest,
|
|
25023
|
+
frame4D: imageItem.frame4D,
|
|
25024
|
+
limitFrames4D: imageItem.limitFrames4D || this.opts.limitFrames4D,
|
|
25025
|
+
colorbarVisible: imageItem.colorbarVisible
|
|
25026
|
+
};
|
|
25027
|
+
const volume = await NVImage.loadFromUrl(imageOptions);
|
|
25028
|
+
this.document.addImageOptions(volume, imageOptions);
|
|
25029
|
+
volume.onColormapChange = this.onColormapChange;
|
|
25030
|
+
this.mediaUrlMap.set(volume, imageOptions.url);
|
|
25031
|
+
if (this.onVolumeAddedFromUrl) {
|
|
25032
|
+
this.onVolumeAddedFromUrl(imageOptions, volume);
|
|
25033
|
+
}
|
|
25034
|
+
return volume;
|
|
25035
|
+
});
|
|
25036
|
+
const volumes = await Promise.all(promises);
|
|
25037
|
+
for (let i = 0; i < volumes.length; i++) {
|
|
25038
|
+
this.addVolume(volumes[i]);
|
|
25039
|
+
}
|
|
25040
|
+
return volumes;
|
|
25041
|
+
}
|
|
24985
25042
|
/**
|
|
24986
25043
|
* Find media by url
|
|
24987
25044
|
*/
|
|
@@ -25029,7 +25086,10 @@ var Niivue = class _Niivue {
|
|
|
25029
25086
|
// nothing
|
|
25030
25087
|
imageType: NVIMAGE_TYPE.DCM_FOLDER
|
|
25031
25088
|
// signify that this is a dicom directory
|
|
25032
|
-
}).then((volume) =>
|
|
25089
|
+
}).then((volume) => {
|
|
25090
|
+
this.addVolume(volume);
|
|
25091
|
+
this.setDrawingEnabled(true);
|
|
25092
|
+
}).catch((e) => {
|
|
25033
25093
|
throw e;
|
|
25034
25094
|
});
|
|
25035
25095
|
}).catch((e) => {
|
|
@@ -25215,6 +25275,7 @@ var Niivue = class _Niivue {
|
|
|
25215
25275
|
this.loadDrawing(volume);
|
|
25216
25276
|
} else {
|
|
25217
25277
|
this.addVolume(volume);
|
|
25278
|
+
this.setDrawingEnabled(true);
|
|
25218
25279
|
}
|
|
25219
25280
|
}).catch((e2) => {
|
|
25220
25281
|
throw e2;
|
|
@@ -25763,7 +25824,10 @@ var Niivue = class _Niivue {
|
|
|
25763
25824
|
* @see {@link https://niivue.github.io/niivue/features/draw.ui.html | live demo usage}
|
|
25764
25825
|
*/
|
|
25765
25826
|
saveImage(options = defaultSaveImageOptions) {
|
|
25766
|
-
const saveOptions = {
|
|
25827
|
+
const saveOptions = {
|
|
25828
|
+
...defaultSaveImageOptions,
|
|
25829
|
+
...options
|
|
25830
|
+
};
|
|
25767
25831
|
const { filename, isSaveDrawing, volumeByIndex } = saveOptions;
|
|
25768
25832
|
log.debug("saveImage", filename, isSaveDrawing, volumeByIndex);
|
|
25769
25833
|
if (this.back?.dims === void 0) {
|
|
@@ -26580,7 +26644,7 @@ var Niivue = class _Niivue {
|
|
|
26580
26644
|
* @param esm - bundled version of NiiVue
|
|
26581
26645
|
* @example
|
|
26582
26646
|
* const javascript = this.generateLoadDocumentJavaScript("gl1");
|
|
26583
|
-
* const html = `<html><body><canvas id="gl1"></canvas><script type="module" async>
|
|
26647
|
+
* const html = `<html><body><canvas id="gl1"></canvas><script type="module" async>
|
|
26584
26648
|
${javascript}</script></body></html>`;
|
|
26585
26649
|
*/
|
|
26586
26650
|
async generateLoadDocumentJavaScript(canvasId, esm) {
|
|
@@ -26588,26 +26652,26 @@ var Niivue = class _Niivue {
|
|
|
26588
26652
|
const base64 = await NVUtilities.compressToBase64String(JSON.stringify(json));
|
|
26589
26653
|
const javascript = `
|
|
26590
26654
|
${esm}
|
|
26591
|
-
|
|
26592
|
-
async function saveNiivueAsHtml(pageName) {
|
|
26655
|
+
|
|
26656
|
+
async function saveNiivueAsHtml(pageName) {
|
|
26593
26657
|
//get new docstring
|
|
26594
26658
|
const docString = nv1.json();
|
|
26595
|
-
const html =
|
|
26659
|
+
const html =
|
|
26596
26660
|
document.getElementsByTagName("html")[0]
|
|
26597
26661
|
.innerHTML.replace(base64, await NVUtilities.compressToBase64String(JSON.stringify(docString)));
|
|
26598
26662
|
NVUtilities.download(html, pageName, "application/html");
|
|
26599
26663
|
}
|
|
26600
|
-
|
|
26664
|
+
|
|
26601
26665
|
var nv1 = new Niivue();
|
|
26602
|
-
nv1.attachTo("${canvasId}");
|
|
26666
|
+
nv1.attachTo("${canvasId}");
|
|
26603
26667
|
var base64 = "${base64}";
|
|
26604
26668
|
NVUtilities.decompressBase64String(base64).then((jsonText) => {
|
|
26605
26669
|
var json = JSON.parse(jsonText); // string -> JSON
|
|
26606
|
-
var doc = NVDocument.loadFromJSON(json);
|
|
26670
|
+
var doc = NVDocument.loadFromJSON(json);
|
|
26607
26671
|
nv1.loadDocument(doc);
|
|
26608
26672
|
nv1.updateGLVolume();
|
|
26609
26673
|
});
|
|
26610
|
-
|
|
26674
|
+
|
|
26611
26675
|
`;
|
|
26612
26676
|
return javascript;
|
|
26613
26677
|
}
|
|
@@ -26681,14 +26745,14 @@ var Niivue = class _Niivue {
|
|
|
26681
26745
|
<main>
|
|
26682
26746
|
<canvas id="gl1"></canvas>
|
|
26683
26747
|
</main>
|
|
26684
|
-
<script type="module" async>
|
|
26748
|
+
<script type="module" async>
|
|
26685
26749
|
${javascript}
|
|
26686
26750
|
function saveAsHtml() {
|
|
26687
26751
|
saveNiivueAsHtml("page.html");
|
|
26688
|
-
}
|
|
26752
|
+
}
|
|
26689
26753
|
// assign our event handler
|
|
26690
26754
|
var button = document.getElementById("save");
|
|
26691
|
-
button.onclick = saveAsHtml;
|
|
26755
|
+
button.onclick = saveAsHtml;
|
|
26692
26756
|
</script>
|
|
26693
26757
|
</body>
|
|
26694
26758
|
</html>`;
|
|
@@ -26753,28 +26817,27 @@ var Niivue = class _Niivue {
|
|
|
26753
26817
|
this.volumes = [];
|
|
26754
26818
|
this.gl.clearColor(0, 0, 0, 1);
|
|
26755
26819
|
this.gl.clear(this.gl.COLOR_BUFFER_BIT);
|
|
26756
|
-
|
|
26757
|
-
|
|
26758
|
-
|
|
26759
|
-
}
|
|
26760
|
-
const imageOptions = {
|
|
26761
|
-
url: volumeList[i].url,
|
|
26762
|
-
headers: volumeList[i].headers,
|
|
26763
|
-
name: volumeList[i].name,
|
|
26764
|
-
colormap: volumeList[i].colormap,
|
|
26765
|
-
colormapNegative: volumeList[i].colormapNegative,
|
|
26766
|
-
opacity: volumeList[i].opacity,
|
|
26767
|
-
urlImgData: volumeList[i].urlImgData,
|
|
26768
|
-
cal_min: volumeList[i].cal_min,
|
|
26769
|
-
cal_max: volumeList[i].cal_max,
|
|
26770
|
-
trustCalMinMax: this.opts.trustCalMinMax,
|
|
26771
|
-
isManifest: volumeList[i].isManifest,
|
|
26772
|
-
frame4D: volumeList[i].frame4D,
|
|
26773
|
-
limitFrames4D: volumeList[i].limitFrames4D || this.opts.limitFrames4D,
|
|
26774
|
-
colorbarVisible: volumeList[i].colorbarVisible
|
|
26775
|
-
};
|
|
26776
|
-
await this.addVolumeFromUrl(imageOptions);
|
|
26820
|
+
if (volumeList.length > 1) {
|
|
26821
|
+
await this.addVolumesFromUrl(volumeList);
|
|
26822
|
+
return this;
|
|
26777
26823
|
}
|
|
26824
|
+
const imageOptions = {
|
|
26825
|
+
url: volumeList[0].url,
|
|
26826
|
+
headers: volumeList[0].headers,
|
|
26827
|
+
name: volumeList[0].name,
|
|
26828
|
+
colormap: volumeList[0].colormap ? volumeList[0].colormap : volumeList[0].colorMap,
|
|
26829
|
+
colormapNegative: volumeList[0].colormapNegative ? volumeList[0].colormapNegative : volumeList[0].colorMapNegative,
|
|
26830
|
+
opacity: volumeList[0].opacity,
|
|
26831
|
+
urlImgData: volumeList[0].urlImgData,
|
|
26832
|
+
cal_min: volumeList[0].cal_min,
|
|
26833
|
+
cal_max: volumeList[0].cal_max,
|
|
26834
|
+
trustCalMinMax: this.opts.trustCalMinMax,
|
|
26835
|
+
isManifest: volumeList[0].isManifest,
|
|
26836
|
+
frame4D: volumeList[0].frame4D,
|
|
26837
|
+
limitFrames4D: volumeList[0].limitFrames4D || this.opts.limitFrames4D,
|
|
26838
|
+
colorbarVisible: volumeList[0].colorbarVisible
|
|
26839
|
+
};
|
|
26840
|
+
await this.addVolumeFromUrl(imageOptions);
|
|
26778
26841
|
return this;
|
|
26779
26842
|
}
|
|
26780
26843
|
/**
|
|
@@ -26798,6 +26861,32 @@ var Niivue = class _Niivue {
|
|
|
26798
26861
|
this.addMesh(mesh);
|
|
26799
26862
|
return mesh;
|
|
26800
26863
|
}
|
|
26864
|
+
/**
|
|
26865
|
+
* Add mesh and notify subscribers
|
|
26866
|
+
* @see {@link https://niivue.github.io/niivue/features/multiuser.meshes.html | live demo usage}
|
|
26867
|
+
*/
|
|
26868
|
+
async addMeshesFromUrl(meshOptions) {
|
|
26869
|
+
const promises = meshOptions.map(async (meshItem) => {
|
|
26870
|
+
const ext = this.getFileExt(meshItem.url);
|
|
26871
|
+
if (ext === "JCON" || ext === "JSON") {
|
|
26872
|
+
const response = await fetch(meshItem.url, {});
|
|
26873
|
+
const json = await response.json();
|
|
26874
|
+
const mesh2 = this.loadConnectomeAsMesh(json);
|
|
26875
|
+
this.mediaUrlMap.set(mesh2, meshItem.url);
|
|
26876
|
+
this.onMeshAddedFromUrl(meshItem, mesh2);
|
|
26877
|
+
return mesh2;
|
|
26878
|
+
}
|
|
26879
|
+
const mesh = await NVMesh2.loadFromUrl({ ...meshItem, gl: this.gl });
|
|
26880
|
+
this.mediaUrlMap.set(mesh, meshItem.url);
|
|
26881
|
+
this.onMeshAddedFromUrl(meshItem, mesh);
|
|
26882
|
+
return mesh;
|
|
26883
|
+
});
|
|
26884
|
+
const meshes = await Promise.all(promises);
|
|
26885
|
+
for (let i = 0; i < meshes.length; i++) {
|
|
26886
|
+
this.addMesh(meshes[i]);
|
|
26887
|
+
}
|
|
26888
|
+
return meshes;
|
|
26889
|
+
}
|
|
26801
26890
|
/**
|
|
26802
26891
|
* load an array of meshes
|
|
26803
26892
|
* @param meshList - the array of objects to load. each object must have a resolvable "url" property at a minimum
|
|
@@ -26819,9 +26908,13 @@ var Niivue = class _Niivue {
|
|
|
26819
26908
|
this.meshes = [];
|
|
26820
26909
|
this.gl.clearColor(0, 0, 0, 1);
|
|
26821
26910
|
this.gl.clear(this.gl.COLOR_BUFFER_BIT);
|
|
26822
|
-
|
|
26823
|
-
await this.
|
|
26911
|
+
if (meshList.length > 1) {
|
|
26912
|
+
await this.addMeshesFromUrl(meshList);
|
|
26913
|
+
this.updateGLVolume();
|
|
26914
|
+
this.drawScene();
|
|
26915
|
+
return this;
|
|
26824
26916
|
}
|
|
26917
|
+
await this.addMeshFromUrl(meshList[0]);
|
|
26825
26918
|
this.updateGLVolume();
|
|
26826
26919
|
this.drawScene();
|
|
26827
26920
|
return this;
|
|
@@ -29747,11 +29840,43 @@ var Niivue = class _Niivue {
|
|
|
29747
29840
|
}
|
|
29748
29841
|
if (this.opts.drawingEnabled) {
|
|
29749
29842
|
const pt = this.frac2vox(this.scene.crosshairPos);
|
|
29843
|
+
if (this.opts.clickToSegment) {
|
|
29844
|
+
const radius = this.opts.clickToSegmentRadius;
|
|
29845
|
+
const steps = this.opts.clickToSegmentSteps;
|
|
29846
|
+
const brightOrDark = this.opts.clickToSegmentBright ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY;
|
|
29847
|
+
this.drawPenFillPts = [];
|
|
29848
|
+
this.drawPenAxCorSag = axCorSag;
|
|
29849
|
+
for (let i2 = 1; i2 <= steps; i2++) {
|
|
29850
|
+
const angle = i2 / steps * 2 * Math.PI;
|
|
29851
|
+
let xVox = pt[0] + radius * Math.cos(angle);
|
|
29852
|
+
let yVox = pt[1] + radius * Math.sin(angle);
|
|
29853
|
+
const zVox = pt[2];
|
|
29854
|
+
xVox = Math.round(xVox);
|
|
29855
|
+
yVox = Math.round(yVox);
|
|
29856
|
+
this.drawPt(xVox, yVox, zVox, this.opts.penValue);
|
|
29857
|
+
this.drawPenFillPts.push([xVox, yVox, pt[2]]);
|
|
29858
|
+
if (i2 === steps) {
|
|
29859
|
+
this.drawFloodFill([xVox, yVox, pt[2]], 0, brightOrDark, NaN, NaN, this.opts.floodFillNeighbors);
|
|
29860
|
+
}
|
|
29861
|
+
}
|
|
29862
|
+
this.drawScene();
|
|
29863
|
+
this.createOnLocationChange(axCorSag);
|
|
29864
|
+
const info = this.getDescriptives(0, [], true);
|
|
29865
|
+
this.onClickToSegment({ mL: info.volumeML, mm3: info.volumeMM3 });
|
|
29866
|
+
return;
|
|
29867
|
+
}
|
|
29750
29868
|
if (!isFinite(this.opts.penValue) || this.opts.penValue < 0 || Object.is(this.opts.penValue, -0)) {
|
|
29751
29869
|
if (!isFinite(this.opts.penValue)) {
|
|
29752
|
-
this.drawFloodFill(pt, 0, this.opts.penValue, this.opts.floodFillNeighbors);
|
|
29870
|
+
this.drawFloodFill(pt, 0, this.opts.penValue, NaN, NaN, this.opts.floodFillNeighbors);
|
|
29753
29871
|
} else {
|
|
29754
|
-
this.drawFloodFill(
|
|
29872
|
+
this.drawFloodFill(
|
|
29873
|
+
pt,
|
|
29874
|
+
Math.abs(this.opts.penValue),
|
|
29875
|
+
this.opts.penValue,
|
|
29876
|
+
NaN,
|
|
29877
|
+
NaN,
|
|
29878
|
+
this.opts.floodFillNeighbors
|
|
29879
|
+
);
|
|
29755
29880
|
}
|
|
29756
29881
|
return;
|
|
29757
29882
|
}
|
|
@@ -30050,6 +30175,9 @@ var Niivue = class _Niivue {
|
|
|
30050
30175
|
width = bulletMargin + longestTextLength;
|
|
30051
30176
|
width += horizontalMargin * 2;
|
|
30052
30177
|
}
|
|
30178
|
+
if (width >= this.gl.canvas.width) {
|
|
30179
|
+
return 0;
|
|
30180
|
+
}
|
|
30053
30181
|
return width;
|
|
30054
30182
|
}
|
|
30055
30183
|
getLegendPanelHeight() {
|
|
@@ -31319,7 +31447,13 @@ var Niivue = class _Niivue {
|
|
|
31319
31447
|
const mm2 = this.frac2mm(this.scene.crosshairPos, 0, true);
|
|
31320
31448
|
const vox = v.mm2vox(mm2);
|
|
31321
31449
|
const val = v.getValue(vox[0], vox[1], vox[2], v.frame4D);
|
|
31322
|
-
return {
|
|
31450
|
+
return {
|
|
31451
|
+
name: v.name,
|
|
31452
|
+
value: val,
|
|
31453
|
+
id: v.id,
|
|
31454
|
+
mm: mm2,
|
|
31455
|
+
vox
|
|
31456
|
+
};
|
|
31323
31457
|
}),
|
|
31324
31458
|
string: str
|
|
31325
31459
|
};
|
|
@@ -32254,7 +32388,7 @@ var Niivue = class _Niivue {
|
|
|
32254
32388
|
const scaleW = this.gl.canvas.width / mxRowWid;
|
|
32255
32389
|
const scaleH = this.effectiveCanvasHeight() / top;
|
|
32256
32390
|
scale = Math.min(scaleW, scaleH);
|
|
32257
|
-
if (this.centerMosaic) {
|
|
32391
|
+
if (this.opts.centerMosaic) {
|
|
32258
32392
|
marginLeft = Math.floor(0.5 * (this.gl.canvas.width - mxRowWid * scale));
|
|
32259
32393
|
marginTop = Math.floor(0.5 * (this.effectiveCanvasHeight() - top * scale));
|
|
32260
32394
|
}
|
|
@@ -32330,6 +32464,20 @@ var Niivue = class _Niivue {
|
|
|
32330
32464
|
} else if (this.opts.sliceType === 2 /* SAGITTAL */) {
|
|
32331
32465
|
this.draw2D([0, 0, 0, 0], 2);
|
|
32332
32466
|
} else {
|
|
32467
|
+
let isShowRender = false;
|
|
32468
|
+
if (this.opts.multiplanarForceRender) {
|
|
32469
|
+
isShowRender = true;
|
|
32470
|
+
if (this.opts.multiplanarForceRender) {
|
|
32471
|
+
this.opts.multiplanarShowRender = 1 /* ALWAYS */;
|
|
32472
|
+
} else {
|
|
32473
|
+
this.opts.multiplanarShowRender = 2 /* AUTO */;
|
|
32474
|
+
}
|
|
32475
|
+
delete this.opts.multiplanarForceRender;
|
|
32476
|
+
} else {
|
|
32477
|
+
if (this.opts.multiplanarShowRender === 1 /* ALWAYS */) {
|
|
32478
|
+
isShowRender = true;
|
|
32479
|
+
}
|
|
32480
|
+
}
|
|
32333
32481
|
const isDrawPenDown = isFinite(this.drawPenLocation[0]) && this.opts.drawingEnabled;
|
|
32334
32482
|
const { volScale } = this.sliceScale();
|
|
32335
32483
|
if (typeof this.opts.multiplanarPadPixels !== "number") {
|
|
@@ -32371,7 +32519,7 @@ var Niivue = class _Niivue {
|
|
|
32371
32519
|
}
|
|
32372
32520
|
if (isDrawColumn) {
|
|
32373
32521
|
let ltwh = ltwh1x3;
|
|
32374
|
-
if (this.opts.
|
|
32522
|
+
if (isShowRender || this.opts.multiplanarShowRender === 2 /* AUTO */ && ltwh1x4[4] >= ltwh1x3[4]) {
|
|
32375
32523
|
ltwh = ltwh1x4;
|
|
32376
32524
|
} else {
|
|
32377
32525
|
isDraw3D = false;
|
|
@@ -32388,7 +32536,7 @@ var Niivue = class _Niivue {
|
|
|
32388
32536
|
}
|
|
32389
32537
|
} else if (isDrawRow) {
|
|
32390
32538
|
let ltwh = ltwh3x1;
|
|
32391
|
-
if (this.opts.
|
|
32539
|
+
if (isShowRender || this.opts.multiplanarShowRender === 2 /* AUTO */ && ltwh4x1[4] >= ltwh3x1[4]) {
|
|
32392
32540
|
ltwh = ltwh4x1;
|
|
32393
32541
|
} else {
|
|
32394
32542
|
isDraw3D = false;
|
|
@@ -32403,6 +32551,12 @@ var Niivue = class _Niivue {
|
|
|
32403
32551
|
this.draw3D([ltwh[0] + sX + sX + sY + pad * 3, ltwh[1], ltwh[3], ltwh[3]]);
|
|
32404
32552
|
}
|
|
32405
32553
|
} else if (isDrawGrid) {
|
|
32554
|
+
if (!isShowRender) {
|
|
32555
|
+
isDraw3D = false;
|
|
32556
|
+
}
|
|
32557
|
+
if (this.opts.multiplanarShowRender === 2 /* AUTO */) {
|
|
32558
|
+
isDraw3D = true;
|
|
32559
|
+
}
|
|
32406
32560
|
const ltwh = ltwh2x2;
|
|
32407
32561
|
const sX = volScale[0] * ltwh[4];
|
|
32408
32562
|
const sY = volScale[1] * ltwh[4];
|
|
@@ -32527,6 +32681,7 @@ export {
|
|
|
32527
32681
|
NVMeshLoaders,
|
|
32528
32682
|
NVUtilities,
|
|
32529
32683
|
Niivue,
|
|
32684
|
+
SHOW_RENDER,
|
|
32530
32685
|
SLICE_TYPE,
|
|
32531
32686
|
cmapper,
|
|
32532
32687
|
ColorTables as colortables
|