PageSourceSearch

https://niivue.com/assets/js/254482fe.504c88ba.js

js niivue.com collected 2026-10-03 23:19:49 UTC 835,916 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunk_niivue_docs=self.webpackChunk_niivue_docs||[]).push([[157],{1184:(t,e,i)=>{i.d(e,{R:()=>s,x:()=>o});var n=i(4041);const r={},a=n.createContext(r);function s(t){const e=n.useContext(a);return n.useMemo((function(){return"function"==typeof t?t(e):{...e,...t}}),[e,t])}function o(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(r):t.components||r:s(t.components),n.createElement(a.Provider,{value:e},t.children)}},2261:(t,e,i)=>{i.d(e,{A:()=>a});var n=i(7565),r=i(1085);const a=t=>{let{children:e}=t;return(0,r.jsx)(n.A,{fallback:(0,r.jsx)("div",{children:"Loading..."}),children:()=>e})}},2891:(t,e,i)=>{i.r(e),i.d(e,{assets:()=>f,contentTitle:()=>m,default:()=>p,frontMatter:()=>u,metadata:()=>n,toc:()=>g});const n=JSON.parse('{"id":"clip","title":"Clip Planes","description":"NiiVue supports up to six simultaneous clip planes for revealing internal structures in 3D volumes. Users can interactively adjust the orientation and depth of the active plane using mouse (drag to rotate, scroll to move) or touch gestures (drag and pinch). When multiple planes are displayed, pressing the p key cycles through them to select the active plane. Shading can be applied to the clipped surfaces, and the clipped region can be inverted to create cutaway views that expose the interior of the volume.","source":"@site/docs/clip.mdx","sourceDirName":".","slug":"/clip","permalink":"/docs/clip","draft":false,"unlisted":false,"tags":[],"version":"current","sidebarPosition":6,"frontMatter":{"title":"Clip Planes","sidebar_position":6},"sidebar":"tutorialSidebar","previous":{"title":"Custom Colormaps","permalink":"/docs/colormaps2"},"next":{"title":"Layouts and Slice Types","permalink":"/docs/layouts"}}');var r=i(1085),a=i(1184),s=i(8e3),o=i(4041);const l=[{url:"https://niivue.com/demos/images/mni152.nii.gz",colormap:"gray",opacity:1,visible:!0}],c={multiplanarShowRender:s.dq.ALWAYS,show3Dcrosshair:!0,backColor:[.2,.2,.2,1]},h=t=>{let{images:e=l,nvOpts:i={}}=t;const n=(0,o.useRef)(null),a=(0,o.useRef)(null),[h,d]=(0,o.useState)("2"),[u,m]=(0,o.useState)("2"),[f,g]=(0,o.useState)(!1),A={...c,...i};(0,o.useEffect)((()=>((async()=>{if(!a.current&&n.current){console.log("Initializing Niivue...");const i=new s.FM(A);a.current=i,i.setSliceType(i.sliceTypeRender),await i.attachToCanvas(n.current),console.log("Niivue attached to canvas.");try{console.log("Loading volumes:",e),await i.loadVolumes(e),console.log("Volumes loaded."),p({target:{value:h}}),v({target:{value:u}}),i.volumes.length}catch(t){console.error("Error loading volumes:",t)}}})(),()=>{console.log("Cleaning up Niivue instance..."),a.current=null})),[]);const p=t=>{const e=t.target.value;if(a.current&&a.current.volumes.length>0){const t=parseInt(e);console.log(`Setting clip planes to: ${e}`);a.current.opts.clipPlaneColor.slice();let i=[[2,180,20]];switch(t){case 1:i=[[.1,180,20]];break;case 2:i=[[.1,180,20],[.1,0,-20]];break;case 3:i=[[0,90,0],[0,0,-20],[.1,0,-90]];break;case 4:i=[[.3,270,0],[.3,90,0],[0,180,0],[.1,0,0]];break;case 5:i=[[.4,270,0],[.3,90,0],[.4,180,0],[.3,0,0],[.1,0,-90]];break;case 6:i=[[.4,270,0],[-.1,90,0],[.4,180,0],[.2,0,0],[.1,0,-90],[.3,0,90]]}a.current.setClipPlanes(i),d(e)}},v=t=>{const e=t.target.value;if(a.current&&a.current.volumes.length>0){const t=parseInt(e);console.log(`Setting clip shade to: ${e}`);let i=a.current.opts.clipPlaneColor.slice();switch(t){case 0:i[3]=0;break;case 1:i[3]=.5;break;case 2:i[3]=-.5}a.current.setClipPlaneColor(i),m(e)}};return(0,r.jsxs)("div",{style:{display:"flex",flexDirection:"column",alignItems:"center",gap:"10px",padding:"10px",border:"1px solid #ccc",borderRadius:"8px",marginBottom:"15px"},children:[(0,r.jsx)("div",{style:{borderRadius:"8px",overflow:"hidden"},children:(0,r.jsx)("canvas",{ref:n,style:{display:"block",minWidth:"384px",minHeight:"384px",width:"100%"}})}),(0,r.jsxs)("div",{style:{display:"flex",flexWrap:"wrap",justifyContent:"center",gap:"15px",alignItems:"center"},children:[(0,r.jsxs)("div",{children:[(0,r.jsx)("label",{htmlFor:"clipSelect",style:{marginRight:"5px"},children:"Clip Planes:"}),(0,r.jsxs)("select",{id:"clipSelect",value:h,onChange:p,children:[(0,r.jsx)("option",{value:"0",children:"0"}),(0,r.jsx)("option",{value:"1",children:"1"}),(0,r.jsx)("option",{value:"2",children:"2"}),(0,r.jsx)("option",{value:"3",children:"3"}),(0,r.jsx)("option",{value:"4",children:"4"}),(0,r.jsx)("option",{value:"5",children:"5"}),(0,r.jsx)("option",{value:"6",children:"6"})]})]}),(0,r.jsxs)("div",{children:[(0,r.jsx)("label",{htmlFor:"shadeSelect",style:{marginRight:"5px"},children:"Shade:"}),(0,r.jsxs)("select",{id:"shadeSelect",value:u,onChange:v,children:[(0,r.jsx)("option",{value:"0",children:"Transparent"}),(0,r.jsx)("option",{value:"1",children:"Shade Outside"}),(0,r.jsx)("option",{value:"2",children:"Shade Inside"})]})]}),(0,r.jsxs)("div",{children:[(0,r.jsx)("label",{htmlFor:"cutawayCheck",style:{marginLeft:"5px"},children:"Cutaway"}),(0,r.jsx)("input",{type:"checkbox",id:"cutawayCheck",checked:f,onChange:t=>{const e=t.target.checked;a.current&&a.current.volumes.length>0&&(console.log(`Setting isCutaway to: ${e}`),a.current.opts.isClipPlanesCutaway=e,a.current.drawScene(),g(e))}})]})]})]})};var d=i(2261);const u={title:"Clip Planes",sidebar_position:6}
1,m="Clip planes",f={},g=[];function A(t){const e={code:"code",h1:"h1",header:"header",p:"p",...(0,a.R)(),...t.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(e.header,{children:(0,r.jsx)(e.h1,{id:"clip-planes",children:"Clip planes"})}),"\n",(0,r.jsxs)(e.p,{children:["NiiVue supports up to six simultaneous clip planes for revealing internal structures in 3D volumes. Users can interactively adjust the orientation and depth of the active plane using mouse (drag to rotate, scroll to move) or touch gestures (drag and pinch). When multiple planes are displayed, pressing the ",(0,r.jsx)(e.code,{children:"p"})," key cycles through them to select the active plane. Shading can be applied to the clipped surfaces, and the clipped region can be inverted to create cutaway views that expose the interior of the volume."]}),"\n",(0,r.jsx)(d.A,{children:(0,r.jsx)(h,{})})]})}function p(t={}){const{wrapper:e}={...(0,a.R)(),...t.components};return e?(0,r.jsx)(e,{...t,children:(0,r.jsx)(A,{...t})}):A(t)}},8e3:(t,e,i)=>{i.d(e,{D2:()=>Li,FM:()=>ds,dq:()=>an,gS:()=>rn,v6:()=>sn});var n=i(911),r=i(4062),a=i(9095),s=i(333),o=i(9659),l=i(5806),c=i(8044),h=i(2859),d=i(4990),u=i(5878),m=i(9302),f=i(1959),g=i(9247),A=i(7687),p=i(6428),v=i(543),x=i(5446),w=Object.defineProperty,y=t=>{throw TypeError(t)},b=(t,e)=>{for(var i in e)w(t,i,{get:e[i],enumerable:!0})},C=(t,e,i)=>((t,e,i)=>e in t?w(t,e,{enumerable:!0,configurable:!0,writable:!0,value:i}):t[e]=i)(t,"symbol"!=typeof e?e+"":e,i),M=(t,e,i)=>e.has(t)||y("Cannot "+i),D=(t,e,i)=>(M(t,e,"read from private field"),i?i.call(t):e.get(t)),T=(t,e,i)=>e.has(t)?y("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(t):e.set(t,i),I=(t,e,i,n)=>(M(t,e,"write to private field"),n?n.call(t,i):e.set(t,i),i),S=33984,E=33985,F=33986,B=33987,V=33989,U=33990,R=33991,P=33992,N=33994,L=33993,k=33995,O=33996,z=33997,Y=33998,G=33999,W=new Float32Array([-1,-1,-1,.28,.28,.28,-1,-1,-1,.28,.28,.28,-1,1,-1,.28,.28,.28,1,-1,-1,.28,.28,.28,1,1,-1,.28,.28,.28,1,1,-1,.28,.28,.28,-1,-1,1,.8,.8,.8,-1,-1,1,.8,.8,.8,1,-1,1,.8,.8,.8,-1,1,1,.8,.8,.8,1,1,1,.8,.8,.8,1,1,1,.8,.8,.8,-1,1,-1,0,0,.74,-1,1,-1,0,0,.74,-1,1,1,0,0,.74,1,1,-1,0,0,.74,1,1,1,0,0,.74,1,1,1,0,0,.74,-1,-1,-1,.42,0,.42,-1,-1,-1,.42,0,.42,1,-1,-1,.42,0,.42,-1,-1,1,.42,0,.42,1,-1,1,.42,0,.42,1,-1,1,.42,0,.42,-1,-1,-1,.64,0,0,-1,-1,-1,.64,0,0,-1,-1,1,.64,0,0,-1,1,-1,.64,0,0,-1,1,1,.64,0,0,-1,1,1,.64,0,0,1,-1,-1,0,.5,0,1,-1,-1,0,.5,0,1,1,-1,0,.5,0,1,-1,1,0,.5,0,1,1,1,0,.5,0,1,1,1,0,.5,0,-.45,1,-.8,0,0,0,-.45,1,-.8,0,0,0,-.45,1,.8,0,0,0,-.25,1,-.8,0,0,0,-.25,1,.8,0,0,0,-.25,1,.8,0,0,0,-.25,1,.6,0,0,0,-.25,1,.6,0,0,0,-.25,1,.8,0,0,0,.45,1,.6,0,0,0,.25,1,.8,0,0,0,.25,1,.8,0,0,0,.25,1,.1,0,0,0,.25,1,.1,0,0,0,.25,1,.6,0,0,0,.45,1,.1,0,0,0,.45,1,.6,0,0,0,.45,1,.6,0,0,0,-.25,1,-.1,0,0,0,-.25,1,-.1,0,0,0,-.25,1,.1,0,0,0,.25,1,-.1,0,0,0,.45,1,.1,0,0,0,.45,1,.1,0,0,0,.45,-1,-.8,0,0,0,.45,-1,-.8,0,0,0,.05,-1,.8,0,0,0,.25,-1,-.8,0,0,0,-.15,-1,.8,0,0,0,-.15,-1,.8,0,0,0,-.25,-1,-.8,0,0,0,-.25,-1,-.8,0,0,0,.05,-1,.8,0,0,0,-.45,-1,-.8,0,0,0,-.15,-1,.8,0,0,0,-.15,-1,.8,0,0,0,.13,-1,-.3,0,0,0,.13,-1,-.3,0,0,0,.07,-1,-.1,0,0,0,-.33,-1,-.3,0,0,0,-.27,-1,-.1,0,0,0,-.27,-1,-.1,0,0,0,-.45,.6,1,0,0,0,-.45,.6,1,0,0,0,-.45,.4,1,0,0,0,-.25,.8,1,0,0,0,-.25,.4,1,0,0,0,-.25,.4,1,0,0,0,-.25,.8,1,0,0,0,-.25,.8,1,0,0,0,-.25,.6,1,0,0,0,.25,.8,1,0,0,0,.45,.6,1,0,0,0,.45,.6,1,0,0,0,.25,.8,1,0,0,0,.25,.8,1,0,0,0,.25,-.1,1,0,0,0,.45,.6,1,0,0,0,.45,.1,1,0,0,0,.45,.1,1,0,0,0,-.25,.1,1,0,0,0,-.25,.1,1,0,0,0,-.45,-.1,1,0,0,0,.25,.1,1,0,0,0,.25,-.1,1,0,0,0,.25,-.1,1,0,0,0,-.45,-.1,1,0,0,0,-.45,-.1,1,0,0,0,-.45,-.6,1,0,0,0,-.25,-.1,1,0,0,0,-.25,-.8,1,0,0,0,-.25,-.8,1,0,0,0,-.25,-.6,1,0,0,0,-.25,-.6,1,0,0,0,-.25,-.8,1,0,0,0,.45,-.6,1,0,0,0,.25,-.8,1,0,0,0,.25,-.8,1,0,0,0,.25,-.4,1,0,0,0,.25,-.4,1,0,0,0,.25,-.6,1,0,0,0,.45,-.4,1,0,0,0,.45,-.6,1,0,0,0,.45,-.6,1,0,0,0,-.1,-.8,-1,0,0,0,-.1,-.8,-1,0,0,0,-.1,.8,-1,0,0,0,.1,-.8,-1,0,0,0,.1,.8,-1,0,0,0,.1,.8,-1,0,0,0,-1,-.45,-.8,0,0,0,-1,-.45,-.8,0,0,0,-1,-.45,.8,0,0,0,-1,-.25,-.8,0,0,0,-1,-.25,.8,0,0,0,-1,-.25,.8,0,0,0,-1,-.25,-.8,0,0,0,-1,-.25,-.8,0,0,0,-1,-.25,-.6,0,0,0,-1,.45,-.8,0,0,0,-1,.45,-.6,0,0,0,-1,.45,-.6,0,0,0,1,.45,-.8,0,0,0,1,.45,-.8,0,0,0,1,.45,.8,0,0,0,1,.25,-.8,0,0,0,1,.25,.8,0,0,0,1,.25,.8,0,0,0,1,.25,.6,0,0,0,1,.25,.6,0,0,0,1,.25,.8,0,0,0,1,-.45,.6,0,0,0,1,-.25,.8,0,0,0,1,-.25,.8,0,0,0,1,-.25,.1,0,0,0,1,-.25,.1,0,0,0,1,-.25,.6,0,0,0,1,-.45,.1,0,0,0,1,-.45,.6,0,0,0,1,-.45,.6,0,0,0,1,.25,-.1,0,0,0,1,.25,-.1,0,0,0,1,.25,.1,0,0,0,1,-.25,-.1,0,0,0,1,-.45,.1,0,0,0,1,-.45,.1,0,0,0,1,-.25,-.8,0,0,0,1,-.25,-.8,0,0,0,1,-.05,-.1,0,0,0,1,-.45,-.8,0,0,0,1,-.25,-.1,0,0,0,1,-.25,-.1,0,0,0]),X=class{constructor(t,e,i,n,r,s){void 0===r&&(r=null),void 0===s&&(s=null),C(this,"sphereIdx",[]),C(this,"sphereVtx",[]),C(this,"renderShaders",[]),C(this,"isVisible",!0),C(this,"isPickable",!0),C(this,"vertexBuffer"),C(this,"indexCount"),C(this,"indexBuffer"),C(this,"vao"),C(this,"mode"),C(this,"glFlags",0),C(this,"id"),C(this,"colorId"),C(this,"modelMatrix",a.vt()),C(this,"scale",[1,1,1]),C(this,"position",[0,0,0]),C(this,"rotation",[0,0,0]),C(this,"rotationRadians",0),C(this,"extentsMin",[]),C(this,"extentsMax",[]),C(this,"furthestVertexFromOrigin"),C(this,"originNegate"),C(this,"fieldOfViewDeObliqueMM"),C(this,"mm"),this.vertexBuffer=e,this.indexCount=n,this.indexBuffer=r,this.vao=s,this.mode=i,this.id=t,this.colorId=[(255&t)/255,(t>>8&255)/255,(t>>16&255)/255,(t>>24&255)/255]}};C(X,"BLEND",1),C(X,"CULL_FACE",2),C(X,"CULL_FRONT",4),C(X,"CULL_BACK",8),C(X,"ENABLE_DEPTH_TEST",16),C(X,"generateCrosshairs",(function(t,e,
1i,n,r,a,s,o){void 0===s&&(s=20),void 0===o&&(o=0);const l=X.generateCrosshairsGeometry(t,i,n,r,a,s,o);return new X(e,l.vertexBuffer,t.TRIANGLES,l.indexCount,l.indexBuffer,l.vao)})),C(X,"generateCrosshairsGeometry",(function(t,e,i,n,a,s,o){void 0===s&&(s=20),void 0===o&&(o=0);const l=[],c=[],h=a*o;if(h<=0){let t=r.fA(i[0],e[1],e[2]),o=r.fA(n[0],e[1],e[2]);X.makeCylinder(l,c,t,o,a,s),t=r.fA(e[0],i[1],e[2]),o=r.fA(e[0],n[1],e[2]),X.makeCylinder(l,c,t,o,a,s),t=r.fA(e[0],e[1],i[2]),o=r.fA(e[0],e[1],n[2]),X.makeCylinder(l,c,t,o,a,s)}else{let t=r.fA(i[0],e[1],e[2]),o=r.fA(e[0]-h,e[1],e[2]);X.makeCylinder(l,c,t,o,a,s,!1),t=r.fA(e[0]+h,e[1],e[2]),o=r.fA(n[0],e[1],e[2]),X.makeCylinder(l,c,t,o,a,s,!1),t=r.fA(e[0],i[1],e[2]),o=r.fA(e[0],e[1]-h,e[2]),X.makeCylinder(l,c,t,o,a,s,!1),t=r.fA(e[0],e[1]+h,e[2]),o=r.fA(e[0],n[1],e[2]),X.makeCylinder(l,c,t,o,a,s,!1),t=r.fA(e[0],e[1],i[2]),o=r.fA(e[0],e[1],e[2]-h),X.makeCylinder(l,c,t,o,a,s,!1),t=r.fA(e[0],e[1],e[2]+h),o=r.fA(e[0],e[1],n[2]),X.makeCylinder(l,c,t,o,a,s,!1)}const d=t.createBuffer();if(null===d)throw new Error("could not instantiate vertex buffer");t.bindBuffer(t.ARRAY_BUFFER,d),t.bufferData(t.ARRAY_BUFFER,new Float32Array(l),t.STATIC_DRAW);const u=t.createBuffer();if(null===u)throw new Error("could not instantiate index buffer");t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,u),t.bufferData(t.ELEMENT_ARRAY_BUFFER,new Uint32Array(c),t.STATIC_DRAW);const m=t.createVertexArray();return t.bindVertexArray(m),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,u),t.bindBuffer(t.ARRAY_BUFFER,d),t.enableVertexAttribArray(0),t.vertexAttribPointer(0,3,t.FLOAT,!1,0,0),t.bindVertexArray(null),{vertexBuffer:d,indexBuffer:u,indexCount:c.length,vao:m}})),C(X,"getFirstPerpVector",(function(t){const e=r.fA(0,0,0);return 0===t[0]?e[0]=1:0===t[1]?e[1]=1:0===t[2]?e[2]=1:(e[0]=t[2],e[1]=t[2],e[2]=-(t[0]+t[1]),r.S8(e,e)),e})),C(X,"subdivide",(function(t,e){let i=t.length/3,n=e.length/3;const a=n,s=r.vt(),o=r.vt();for(let l=0;l<a;l++){const a=e[3*l+0],c=e[3*l+1],h=e[3*l+2],d=r.fA(t[3*a+0],t[3*a+1],t[3*a+2]),u=r.fA(t[3*c+0],t[3*c+1],t[3*c+2]),m=r.fA(t[3*h+0],t[3*h+1],t[3*h+2]);r.WQ(s,d,u),r.S8(o,s),t.push(...o),r.WQ(s,u,m),r.S8(o,s),t.push(...o),r.WQ(s,d,m),r.S8(o,s),t.push(...o);let f=[i,i+1,i+2];e.push(...f),f=[a,i,i+2],e.push(...f),f=[i,c,i+1],e.push(...f),e[3*l+0]=i+2,e[3*l+1]=i+1,e[3*l+2]=h,n+=3,i+=3}})),C(X,"weldVertices",(function(t,e){const i=t.length/3;let n=0;const r=new Int32Array(i);for(let o=0;o<i-1;o++){if(0!==r[o])continue;r[o]=n;let e=3*o;const a=t[e],s=t[e+1],l=t[e+2];for(let c=o+1;c<i;c++)e+=3,a===t[e]&&s===t[e+1]&&l===t[e+2]&&(r[c]=n);n++}if(n===i)return t;const a=e.length;for(let o=0;o<a;o++)e[o]=r[e[o]];const s=t.slice(0,3*n-1);for(let o=0;o<i-1;o++){const e=3*o,i=3*r[o];s[i]=t[e],s[i+1]=t[e+1],s[i+2]=t[e+2]}return s})),C(X,"makeSphere",(function(t,e,i,n){void 0===n&&(n=[0,0,0]);let r=[0,0,1,.894,0,.447,.276,.851,.447,-.724,.526,.447,-.724,-.526,.447,.276,-.851,.447,.724,.526,-.447,-.276,.851,-.447,-.894,0,-.447,-.276,-.851,-.447,.724,-.526,-.447,0,0,-1];const a=[0,1,2,0,2,3,0,3,4,0,4,5,0,5,1,7,6,11,8,7,11,9,8,11,10,9,11,6,10,11,6,2,1,7,3,2,8,4,3,9,5,4,10,1,5,6,7,2,7,8,3,8,9,4,9,10,5,10,6,1];X.subdivide(r,a),X.subdivide(r,a),r=X.weldVertices(r,a);for(let c=0;c<r.length;c++)r[c]=r[c]*i;const s=r.length/3;let o=0;for(let c=0;c<s;c++)r[o]=r[o]+n[0],o++,r[o]=r[o]+n[1],o++,r[o]=r[o]+n[2],o++;const l=Math.floor(t.length/3);for(let c=0;c<a.length;c++)a[c]=a[c]+l;e.push(...a),t.push(...r)})),C(X,"makeCylinder",(function(t,e,i,n,a,s,o){void 0===s&&(s=20),void 0===o&&(o=!0),s<3&&(s=3);const l=r.vt();r.Re(l,n,i),r.S8(l,l);const c=X.getFirstPerpVector(l),h=r.vt();r.$A(h,l,c),r.S8(h,h);let d=2*s,u=2*s;o&&(u+=2*s,d+=2);const m=Math.floor(t.length/3),f=new Uint32Array(3*u),g=new Float32Array(3*d);function A(t,e){g[3*t+0]=e[0],g[3*t+1]=e[1],g[3*t+2]=e[2]}function p(t,e,i,n){f[3*t+0]=e+m,f[3*t+1]=i+m,f[3*t+2]=n+m}const v=2*s,x=v+1;o&&(A(v,i),A(x,n));const w=r.vt(),y=r.vt();for(let b=0;b<s;b++){const t=Math.cos(b/s*2*Math.PI),e=Math.sin(b/s*2*Math.PI);w[0]=a*(t*c[0]+e*h[0]),w[1]=a*(t*c[1]+e*h[1]),w[2]=a*(t*c[2]+e*h[2]),r.WQ(y,i,w),A(b,y),r.WQ(y,n,w),A(b+s,y);let l=0;b<s-1&&(l=b+1),p(2*b,b,l,b+s),p(2*b+1,l,l+s,b+s),o&&(p(2*s+b,b,v,l),p(2*s+b+s,x,b+s,l+s))}e.push(...f),t.push(...g)}
1)),C(X,"makeColoredCylinder",(function(t,e,i,n,r,a,s,o,l){void 0===s&&(s=[192,0,0,255]),void 0===o&&(o=20),void 0===l&&(l=!1);let c=t.length/3;X.makeCylinder(t,e,n,r,a,o,l),c=t.length/3-c;const h=[];for(let d=0;d<4*c-1;d+=4)h[d]=s[0],h[d+1]=s[1],h[d+2]=s[2],h[d+3]=s[3];i.push(...h)})),C(X,"makeColoredSphere",(function(t,e,i,n,r,a){void 0===r&&(r=[0,0,0]),void 0===a&&(a=[0,0,192,255]);let s=t.length/3;X.makeSphere(t,e,n,r),s=t.length/3-s;const o=[];for(let l=0;l<4*s-1;l+=4)o[l]=a[0],o[l+1]=a[1],o[l+2]=a[2],o[l+3]=a[3];i.push(...o)}));var K=X,H=class t{constructor(t){let{name:e="niivue",level:i="info"}=void 0===t?{}:t;C(this,"level"),C(this,"name"),this.name=`${e}`,this.level=i}debug(){if(!(t.levels[this.level]>t.levels.debug)){for(var e=arguments.length,i=new Array(e),n=0;n<e;n++)i[n]=arguments[n];console.debug(`${this.name}-debug`,...i)}}info(){if(!(t.levels[this.level]>t.levels.info)){for(var e=arguments.length,i=new Array(e),n=0;n<e;n++)i[n]=arguments[n];console.info(`${this.name}-info`,...i)}}warn(){if(!(t.levels[this.level]>t.levels.warn)){for(var e=arguments.length,i=new Array(e),n=0;n<e;n++)i[n]=arguments[n];console.warn(`${this.name}-warn`,...i)}}error(){if(!(t.levels[this.level]>t.levels.error)){for(var e=arguments.length,i=new Array(e),n=0;n<e;n++)i[n]=arguments[n];console.error(`${this.name}-error`,...i)}}fatal(){if(!(t.levels[this.level]>t.levels.fatal)){for(var e=arguments.length,i=new Array(e),n=0;n<e;n++)i[n]=arguments[n];console.error(`${this.name}-fatal`,...i)}}setLogLevel(t){this.level=t}setName(t){this.name=t}};C(H,"levels",{debug:0,info:1,warn:2,error:3,fatal:4,silent:1/0});var Q=new H({name:"niivue",level:"info"}),q={};b(q,{$itksnap:()=>tt,$slicer3d:()=>et,actc:()=>it,afni_blues_inv:()=>ge,afni_reds_inv:()=>Ae,batlow:()=>nt,bcgwhw:()=>at,bcgwhw_dark:()=>rt,blue:()=>ht,blue2cyan:()=>lt,blue2magenta:()=>ot,blue2red:()=>st,bluegrn:()=>ct,bone:()=>dt,bronze:()=>ut,cet_l17:()=>mt,cividis:()=>ft,cool:()=>gt,copper:()=>pt,copper2:()=>At,ct_airways:()=>vt,ct_artery:()=>xt,ct_bones:()=>wt,ct_brain:()=>bt,ct_brain_gray:()=>yt,ct_cardiac:()=>Ct,ct_head:()=>Mt,ct_kidneys:()=>Dt,ct_liver:()=>Tt,ct_muscles:()=>It,ct_scalp:()=>St,ct_skull:()=>Et,ct_soft:()=>Ft,ct_soft_tissue:()=>Bt,ct_surface:()=>Vt,ct_vessels:()=>Ut,ct_w_contrast:()=>Rt,cubehelix:()=>Pt,electric_blue:()=>Nt,freesurfer:()=>Lt,ge_color:()=>kt,gold:()=>Ot,gray:()=>zt,green:()=>Yt,green2cyan:()=>Gt,green2orange:()=>Wt,hot:()=>Kt,hotiron:()=>Xt,hsv:()=>Ht,inferno:()=>Qt,jet:()=>qt,kry:()=>Zt,linspecer:()=>jt,lipari:()=>Jt,magma:()=>_t,mako:()=>$t,navia:()=>te,nih:()=>ee,plasma:()=>ie,random:()=>ne,red:()=>re,redyell:()=>ae,rocket:()=>se,roi_i256:()=>pe,surface:()=>oe,thermal:()=>le,turbo:()=>ce,violet:()=>he,viridis:()=>de,warm:()=>ue,winter:()=>me,x_rain:()=>fe});var Z,j,J,_,$,tt={R:[0,255,0,0,255,0,255,255,0,205,210,102,0,0,46,255,106,221,233,165,255,147,218,75,255,60,255,255,218,0,188,255,255,222,127,139,124,255,70,0,238,238,240,245,184,32,255,25,112,34,248,245,255,144,173,65,255,250,128,50,244,255,123,255,173,255,127,255,143,220,253,255,0,0,128,255,250,148,178,255,135,100,240,250,255,107,135,0,139,245,186,255,255,0,210,255,47,72,175,128,176,255,139,240,255,216,119,219,72,255,199,154,189,240,230,0,85,64,153,205,250,95,0,255,224,176,138,30,240,152,160],G:[0,0,255,0,255,255,0,239,0,133,180,205,0,139,139,228,90,160,150,42,250,112,112,0,182,179,235,228,165,128,143,105,218,184,255,69,252,255,130,100,130,232,255,222,134,178,20,25,128,139,248,255,160,238,255,105,99,240,0,205,164,255,104,165,216,192,255,140,188,20,245,250,206,255,0,250,128,0,34,127,206,149,230,235,245,142,206,0,0,245,85,228,222,191,105,248,79,61,238,128,224,240,0,255,215,191,136,112,209,0,21,205,183,248,230,250,107,224,50,92,250,158,128,69,255,196,43,144,128,251,82],B:[0,0,0,255,0,255,255,213,205,63,140,170,128,139,87,225,205,221,122,42,250,219,214,130,193,113,205,196,32,128,143,180,185,135,0,19,0,224,180,0,238,170,240,179,11,170,147,112,144,34,255,250,122,144,47,225,71,230,0,50,96,240,238,0,230,203,212,0,143,60,230,240,209,127,128,205,114,211,34,80,235,237,140,215,238,35,250,139,139,220,211,181,173,255,30,220,79,139,238,0,230,245,0,255,0,216,153,147,204,255,133,50,107,255,250,154,47,208,204,92,210,160,0,0,255,222,226,255,128,152,45],A:[0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255],I:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130]},et={labels:["background","tissue","bone","skin","connective tissue","blood","organ","mass","muscle","foreign object","waste","teeth","fat","gray matter","white matter","nerve","vein","artery","capillary","ligament","tendon","cartilage","meniscus","lymph node","lymphatic vessel","cerebro-spinal fluid","bile","urine","feces","gas","fluid","edema","bleeding","necrosis","clot","embolism","head","central nervous system","brain","gray matter of brain","telencephalon","cerebral cortex","right frontal lobe","left frontal lobe","right temporal lobe","left temporal lobe","right parietal lobe","left parietal lobe","right occipital lobe","left occipital lobe","right insular lobe","left insular lobe","right limbic lobe","left limbic lobe","right striatum","left striatum","right caudate nucleus","left caudate nucleus","right putamen","left putamen","right pallidum","left pallidum","right amygdaloid complex","left amygdaloid complex","diencephalon","thalamus","right thalamus","left thalamus","pineal gland","midbrain","substantia nigra","right substantia nigra","left substantia nigra","cerebral white matter","right superior longitudinal fasciculus","left superior longitudinal fasciculus","right inferior longitudinal fasciculus","left inferior longitudinal fasciculus","right arcuate fasciculus","left arcuate fasciculus","right uncinate fasciculus","left uncinate fasciculus","right cingulum bundle","left cingulum bundle","projection fibers","right corticospinal tract","left corticospinal tract","right optic radiation","left optic radiation","right medial lemniscus","left medial lemniscus","right superior cerebellar peduncle","left superior cerebellar peduncle","right middle cerebellar peduncle","left middle cerebellar peduncle","right inferior cerebellar peduncle","left inferior cerebellar peduncle","optic chiasm","right optic tract","left optic tract","right fornix","left fornix","commissural fiber
1s","corpus callosum","posterior commissure","cerebellar white matter","CSF space","ventricles of brain","right lateral ventricle","left lateral ventricle","right third ventricle","left third ventricle","cerebral aqueduct","fourth ventricle","subarachnoid space","spinal cord","gray matter of spinal cord","white matter of spinal cord","endocrine system of brain","pituitary gland","adenohypophysis","neurohypophysis","meninges","dura mater","arachnoid","pia mater","muscles of head","salivary glands","lips","nose","tongue","soft palate","right inner ear","left inner ear","right external ear","left external ear","right middle ear","left middle ear","right eyeball","left eyeball","skull","right frontal bone","left frontal bone","right parietal bone","left parietal bone","right temporal bone","left temporal bone","right sphenoid bone","left sphenoid bone","right ethmoid bone","left ethmoid bone","occipital bone","maxilla","right zygomatic bone","right lacrimal bone","vomer bone","right palatine bone","left palatine bone","mandible","neck","muscles of neck","pharynx","larynx","thyroid gland","right parathyroid glands","left parathyroid glands","skeleton of neck","hyoid bone","cervical vertebral column","thorax","trachea","bronchi","right lung","left lung","superior lobe of right lung","superior lobe of left lung","middle lobe of right lung","inferior lobe of right lung","inferior lobe of left lung","pleura","heart","right atrium","left atrium","atrial septum","ventricular septum","right ventricle of heart","left ventricle of heart","mitral valve","tricuspid valve","aortic valve","pulmonary valve","aorta","pericardium","pericardial cavity","esophagus","thymus","mediastinum","skin of thoracic wall","muscles of thoracic wall","skeleton of thorax","thoracic vertebral column","ribs","sternum","right clavicle","left clavicle","abdominal cavity","abdomen","peritoneum","omentum","peritoneal cavity","retroperitoneal space","stomach","duodenum","small bowel","colon","anus","liver","biliary tree","gallbladder","pancreas","spleen","urinary system","right kidney","left kidney","right ureter","left ureter","urinary bladder","urethra","right adrenal gland","left adrenal gland","female internal genitalia","uterus","right fallopian tube","left fallopian tube","right ovary","left ovary","vagina","male internal genitalia","prostate","right seminal vesicle","left seminal vesicle","right deferent duct","left deferent duct","skin of abdominal wall","muscles of abdominal wall","skeleton of abdomen","lumbar vertebral column","female external genitalia","male external genitalia","skeleton of upper limb","muscles of upper limb","right upper limb","left upper limb","right shoulder","left shoulder","right arm"],R:[0,128,241,177,111,216,221,144,192,220,78,255,230,200,250,244,0,216,183,183,152,111,178,68,111,85,0,214,78,218,170,140,188,216,145,150,177,244,250,200,68,128,83,83,162,162,141,141,182,182,188,188,154,154,177,177,30,30,210,210,48,48,98,98,69,166,122,122,253,145,46,0,0,250,127,127,159,159,125,125,106,106,154,154,126,201,201,78,78,174,174,139,139,148,148,186,186,99,156,156,64,64,138,97,126,194,85,88,88,88,88,88,88,88,88,244,200,250,82,57,60,92,255,255,255,255,201,70,188,177,166,182,229,229,174,174,201,201,194,194,241,203,203,229,229,255,255,209,209,248,248,255,196,255,255,255,242,242,222,177,213,184,150,62,62,62,242,250,255,177,182,175,197,197,172,172,202,224,224,255,206,210,203,233,195,181,152,159,166,218,225,224,255,184,211,47,255,173,188,255,226,253,244,205,205,186,177,255,234,204,180,216,255,205,204,255,221,0,139,249,157,203,185,185,247,247,222,124,249,249,244,255,255,227,213,213,193,216,230,245,245,241,241,177,171,217,212,185,185,198,194,177,177,177,177,177],G:[0,174,214,122,184,101,130,238,104,245,63,250,220,200,250,214,151,101,156,214,189,184,212,172,197,188,145,230,63,255,250,224,65,191,60,98,122,214,250,200,131,174,146,146,115,115,93,93,166,166,135,135,150,150,140,140,111,111,157,157,129,129,153,153,110,113,101,101,135,92,101,108,108,250,150,150,116,116,102,102,174,174,146,146,126,160,160,152,152,140,140,126,126,120,120,135,135,106,171,171,123,123,95,113,161,195,188,106,106,106,106,106,106,106,106,214,200,250,174,157,143,162,244,244,244,244,121,163,91,122,84,105,147,147,122,122,112,112,142,142,213,179,179,204,204,243,243,185,185,223,223,230,172,255,250,237,217,217,198,122,124,105,208,162,162,162,206,210,255,122,228,216,165,165,138,138,164,186,186,245,110,115,108,138,100,85,55,63,70,123,130,97,244,122,171,150,244,121,95,239,202,232,217,179,179,124,122,255,234,142,119,132,253,167,168,224,130,145,150,180,108,136,102,102,182,182,154,186,186,186,170,181,190,153,141,141,123,146,158,172,172,172,172,124,85,198,188,135,135,175,98,122,122,122,122,122],B:[0,128,145,101,210,79,101,144,88,20,0,220,70,235,210,49,206,79,220,211,207,210,242,100,131,255,30,130,0,255,250,228,28,216,66,83,101,49,225,215,98,128,164,164,105,105,137,137,110,110,166,166,201,201,190,190,85,85,166,166,126,126,112,112,53,137,38,38,192,109,131,112,112,225,88,88,163,163,154,154,155,155,83,83,55,133,133,141,141,103,103,177,177,72,72,135,135,24,108,108,147,147,74,158,197,164,255,215,215,215,215,215,215,215,215,49,215,225,
1128,110,83,109,209,209,209,209,77,117,95,101,94,107,118,118,90,90,73,73,0,0,144,77,77,109,109,152,152,85,85,131,131,138,68,167,160,145,123,123,101,101,109,108,243,114,114,114,142,139,207,101,255,244,145,145,115,115,140,162,162,217,84,89,81,112,73,57,13,27,38,97,104,76,209,154,143,103,209,88,76,172,134,158,154,108,108,161,101,220,194,178,153,105,229,142,143,199,101,30,98,111,162,116,83,83,164,164,132,223,150,150,147,158,165,130,113,113,103,127,140,147,147,151,151,92,68,131,102,134,134,125,79,101,101,101,101,101],A:[0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255],I:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255]},it={R:[0,0,24,248,255],G:[0,0,177,254,0],B:[0,136,0,0,0],A:[0,32,64,78,128],I:[0,64,128,156,255]},nt={R:[1,10,15,17,21,27,36,49,65,82,99,118,140,161,183,203,222,238,248,253,253,253,252,250],G:[25,42,56,68,79,88,97,105,111,116,122,127,133,138,142,146,150,155,162,170,178,186,195,204],B:[89,92,95,96,98,98,96,91,83,74,64,55,46,43,49,62,79,100,126,151,175,199,223,250],A:[0,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64],I:[0,11,22,33,44,55,66,77,88,99,110,121,133,144,155,166,177,188,199,210,221,232,243,255]},rt={R:[0,248,242,235,229,222,212,202,193,183,173,145,117,78,39,0,0,0,0,0,0,64,128,191,255,255,255,255,255,238,221,204,214,224,235,245,255,249,242,236,229,223,217,210,204,197,191,184,176,169,161,154,146,139,132,124,117,109,102,0],G:[0,251,247,243,239,235,235,235,235,235,235,216,197,174,150,127,153,178,204,229,255,255,255,255,255,220,185,150,115,77,38,0,31,61,92,122,153,138,122,107,92,77,61,46,31,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0],B:[0,254,253,252,251,250,251,252,253,254,255,226,198,132,66,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,40,80,120,160,200,199,198,197,196,196,195,194,193,192,191,184,176,169,161,154,146,139,132,124,117,109,102,0],A:[256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256],I:[0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172,176,180,184,188,192,196,200,204,208,212,216,220,224,228,232,236,240,244,248,255]},at={R:[255,248,242,235,229,222,212,202,193,183,173,145,117,78,39,0,0,0,0,0,0,64,128,191,255,255,255,255,255,238,221,204,214,224,235,245,255,249,242,236,229,223,217,210,204,197,191,184,176,169,161,154,146,139,132,124,117,109,102,0],G:[255,251,247,243,239,235,235,235,235,235,235,216,197,174,150,127,153,178,204,229,255,255,255,255,255,220,185,150,115,77,38,0,31,61,92,122,153,138,122,107,92,77,61,46,31,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0],B:[255,254,253,252,251,250,251,252,253,254,255,226,198,132,66,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,40,80,120,160,200,199,198,197,196,196,195,194,193,192,191,184,176,169,161,154,146,139,132,124,117,109,102,0],A:[256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256],I:[0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172,176,180,184,188,192,196,200,204,208,212,216,220,224,228,232,236,240,244,248,255]},st={R:[0,0,0,0,196,255],G:[0,32,128,128,128,32],B:[0,255,196,0,0,0],A:[0,128,64,64,64,128],I:[0,1,64,128,192,255]},ot={R:[0,255],G:[0,0],B:[255,255],A:[0,128],I:[0,255]},lt={R:[0,0],G:[0,255],B:[255,255],A:[0,128],I:[0,255]}
1,ct={R:[0,0,0,0],G:[0,1,128,255],B:[0,222,127,32],A:[0,0,64,128],I:[0,1,128,255]},ht={R:[0,0,0],G:[0,0,0],B:[0,128,255],A:[0,64,128],I:[0,128,255]},dt={R:[0,103,255],G:[0,126,255],B:[0,165,255],A:[0,76,128],I:[0,153,255]},ut={R:[0,43,103,199,216,255],G:[0,0,37,155,213,255],B:[0,0,20,97,201,255],A:[0,44,48,54,56,56],I:[0,64,128,196,240,255]},mt={R:[0,9,24,33,40,46,52,57,62,66,70,74,78,81,85,88,91,94,98,101,103,106,109,112,114,117,119,121,124,126,128,130,133,135,137,139,141,143,145,147,149,151,153,155,157,159,161,163,164,166,168,169,171,172,174,175,177,178,180,181,183,184,186,187,189,190,191,193,194,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,222,223,224,224,225,226,226,227,228,228,229,229,230,231,231,232,233,233,234,234,235,235,236,236,236,237,237,237,238,238,238,239,239,239,240,240,240,241,241,241,242,242,242,243,243,243,243,243,243,243,243,244,244,244,244,244,244,244,244,244,244,244,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,243,243,243,243,243,243,243,243,243,243,243,243,242,242,242,242,242,242,242,242,241,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,243,243,244,244,245,246,246,247,247,248,249,249,250,250,251,251,252,252,253,253,254,254,254],G:[42,41,41,41,40,40,40,39,39,39,38,38,37,37,36,36,35,35,34,34,33,32,32,31,30,30,30,30,29,29,29,29,28,28,28,27,27,27,26,26,26,25,25,25,24,24,24,24,24,25,25,26,27,27,28,28,29,30,30,31,31,32,33,33,34,34,35,36,36,37,38,39,40,42,43,44,45,47,48,49,50,51,53,54,55,56,57,58,59,60,62,63,64,65,66,68,69,71,72,73,75,76,77,79,80,81,83,84,85,87,88,89,90,92,93,94,95,97,98,100,101,102,104,105,107,108,109,111,112,113,115,116,117,119,120,121,122,124,125,126,128,129,130,132,133,134,136,137,138,140,141,142,144,145,146,147,149,150,151,153,154,155,156,158,159,160,161,163,164,165,167,168,169,170,172,173,174,175,176,178,179,180,181,183,184,185,186,187,189,190,191,192,193,194,196,197,198,199,200,201,203,204,205,206,207,208,209,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,228,229,230,231,232,233,234,235,236,237,238,238,239,240,241,241,242,243,244,244,245,246,247,248,248,249,250,251,251,252,253,254,255],B:[167,167,166,166,166,165,165,165,164,164,164,163,163,162,162,162,161,161,161,160,160,160,159,159,158,158,157,157,156,155,155,154,154,153,153,152,151,151,150,150,149,149,148,147,147,146,146,145,144,144,143,143,142,141,141,140,139,139,138,137,137,136,135,135,134,133,133,132,131,131,130,130,129,128,128,127,127,126,125,125,124,124,123,123,122,121,121,120,119,119,118,118,117,116,116,116,115,115,114,114,113,113,113,112,112,111,111,110,110,109,109,109,108,108,107,107,106,106,106,106,106,105,105,105,105,105,105,105,104,104,104,104,104,103,103,103,103,103,102,102,102,103,103,103,103,104,104,104,104,104,105,105,105,105,106,106,106,106,106,107,107,107,107,108,108,109,110,111,111,112,113,113,114,115,115,116,117,117,118,119,120,120,121,122,122,123,124,125,126,128,129,130,131,132,134,135,136,137,138,140,141,142,143,144,146,147,148,149,150,152,153,155,157,158,160,162,163,165,167,168,170,172,173,175,177,178,180,182,183,185,187,188,190,193,196,199,201,204,207,210,212,215,218,221,224,226,229,232,235,238,240,243,246,249,252,255],A:[0,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64],I:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255]},ft={R:[0,86,166,255],G:[32,92,156,233],B:[76,108,117,69],A:[0,56,80,88],I:[0,64,192,255]},gt={R:[0,0,0],G:[127,196,254],B:[255,255,255],A:[0,64,128],I:[0,128,25
15]},At={R:[0,61,122,183,244,255],G:[0,41,81,122,163,255],B:[0,25,51,76,102,255],A:[0,25,51,71,102,128],I:[0,51,102,153,204,255]},pt={R:[0,61,122,183,244,255],G:[0,41,81,122,163,203],B:[0,25,51,76,102,127],A:[0,25,51,71,102,128],I:[0,51,102,153,204,255]},vt={min:-643,max:-235,R:[0,0,0],G:[154,154,154],B:[179,179,101],A:[0,32,0],I:[0,163,255]},xt={min:114,max:800,R:[0,255,255,255],G:[0,0,129,255],B:[0,0,0,255],A:[0,64,88,228],I:[0,80,160,255]},wt={min:180,max:600,R:[0,0,113,255],G:[0,0,109,250],B:[0,0,101,245],A:[0,0,100,160],I:[0,1,128,255]},yt={min:-10,max:110,R:[0,127,255],G:[0,127,255],B:[0,127,255],A:[0,48,128],I:[0,124,255]},bt={min:-10,max:110,R:[0,199,255],G:[0,127,255],B:[0,127,255],A:[0,48,128],I:[0,124,255]},Ct={min:-80,max:1e3,R:[0,189,150,150,150,150,255],G:[0,169,54,54,54,54,240],B:[0,153,52,52,52,52,242],A:[0,32,64,0,0,64,64],I:[0,1,82,92,234,242,255]},Mt={min:-590,max:600,R:[0,241,241,248,248,178,178,232,255,255,255],G:[0,156,156,222,222,36,36,51,255,255,255],B:[0,130,130,169,169,24,24,37,255,255,255],A:[0,8,0,0,0,64,64,0,0,222,222],I:[0,2,3,64,122,142,172,182,252,253,255]},Dt={min:114,max:302,R:[0,255,255],G:[0,129,255],B:[0,0,255],A:[0,88,228],I:[0,103,255]},Tt={min:-23,max:246,R:[0,44,255,255,255],G:[0,128,90,255,255],B:[0,0,70,0,255],A:[0,0,82,184,228],I:[0,64,131,196,255]},It={min:-100,max:246,R:[0,128,159,255,255,255,255],G:[0,0,56,90,0,255,255],B:[0,0,41,70,0,0,255],A:[0,63,105,135,167,184,228],I:[0,100,128,155,180,209,255]},St={min:-590,max:600,R:[0,241,241,248,248,178,232,255,255],G:[0,156,156,222,222,36,51,255,255],B:[0,130,130,169,169,24,37,255,255],A:[0,63,105,135,167,184,228,228,228],I:[0,1,52,127,137,162,172,252,255]},Et={min:140,max:1024,R:[0,2,113,255],G:[0,1,109,250],B:[0,1,101,245],A:[0,1,96,168],I:[0,1,128,25
15]},Ft={min:-923,max:679,R:[0,0,0,0,0,255,255,255],G:[154,154,154,154,0,0,254,255],B:[179,179,179,179,0,0,0,255],A:[0,3,8,0,0,10,15,20],I:[0,30,62,88,170,200,232,255]},Bt={min:-10,max:110,R:[0,199,255],G:[0,127,255],B:[0,127,255],A:[0,48,128],I:[0,124,255]},Vt={min:-600,max:100,R:[0,134,255],G:[0,109,250],B:[0,101,245],A:[0,60,148],I:[0,128,255]},Ut={min:114,max:246,R:[0,255,255],G:[0,128,255],B:[0,128,255],A:[0,64,96],I:[0,87,255]},Rt={min:50,max:1e3,R:[98,210,169,128,255],G:[94,26,77,128,255],B:[45,21,74,128,255],A:[0,25,0,4,168],I:[0,41,87,154,255]},Pt={R:[0,13,21,26,27,25,22,21,22,28,39,54,75,98,124,148,171,189,202,210,213,211,206,200,195,193,195,201,211,225,240,255],G:[0,5,11,20,31,44,58,72,86,99,109,116,120,122,122,122,121,121,124,129,137,147,161,175,190,205,218,229,238,245,251,255],B:[0,14,30,46,61,71,77,78,75,68,60,52,48,47,53,65,83,105,131,157,183,205,222,235,241,243,242,240,239,240,245,255],A:[0,4,8,12,17,21,25,29,33,37,41,45,50,54,58,62,66,70,74,78,83,87,91,95,99,103,107,111,116,120,124,128],I:[0,8,16,25,33,41,49,58,66,74,82,90,99,107,115,123,132,140,148,156,165,173,181,189,197,206,214,222,230,239,247,255]},Nt={R:[0,10,136,255],G:[0,39,220,255],B:[0,223,253,255],A:[0,48,64,70],I:[0,92,192,255]},Lt={R:[0,245,205,120,196,220,230,0,122,236,12,204,42,119,220,103,60,255,165,160,0,245,205,120,196,220,230,0,122,236,13,220,103,255,165,160,0,120,200,255,255,164,164,164,234,0,0,0,0,0],G:[0,245,62,18,58,248,148,118,186,13,48,182,204,159,216,255,60,165,42,32,200,245,62,18,58,248,148,118,186,13,48,216,255,165,42,32,200,190,70,
1148,148,108,108,108,169,0,0,0,0,0],B:[0,245,78,134,250,164,34,14,220,176,255,142,164,176,20,255,60,0,42,240,200,245,78,134,250,164,34,14,220,176,255,20,255,0,42,240,221,150,255,10,10,226,226,226,30,64,112,160,208,255],A:[0,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64],I:[0,2,3,4,5,7,8,10,11,12,13,14,15,16,17,18,24,26,28,30,31,41,42,43,44,46,47,49,50,51,52,53,54,58,60,62,63,72,77,78,79,80,81,82,85,251,252,253,254,255]},kt={R:[0,0,128,255,255],G:[0,128,0,128,255],B:[0,125,255,0,255],A:[0,32,64,96,128],I:[0,63,128,192,255]},Ot={R:[0,142,227,255],G:[0,85,170,255],B:[0,14,76,255],A:[0,42,84,128],I:[0,85,170,255]},zt={R:[0,255],G:[0,255],B:[0,255],A:[0,128],I:[0,255]},Yt={R:[0,0,0],G:[0,128,255],B:[0,0,0],A:[0,64,128],I:[0,128,255]},Gt={R:[0,0,0],G:[72,72,255],B:[0,255,255],A:[0,64,128],I:[0,88,255]},Wt={R:[0,255,255],G:[72,88,255],B:[0,0,0],A:[0,64,128],I:[0,88,255]},Xt={R:[0,255,255,255],G:[0,0,126,255],B:[0,0,0,255],A:[0,64,96,128],I:[0,128,191,255]},Kt={R:[3,255,255,255],G:[0,0,255,255],B:[0,0,0,255],A:[0,48,96,128],I:[0,95,191,255]},Ht={R:[255,255,0,0,0,255,255],G:[0,255,255,255,0,0,0],B:[0,0,0,255,255,255,0],A:[0,14,28,43,57,71,85],I:[0,43,85,128,170,213,255]},Qt={R:[0,120,237,240],G:[0,28,105,249],B:[4,109,37,33],A:[0,56,80,88],I:[0,64,192,255]},qt={R:[0,0,127,255,127],G:[0,127,255,127,0],B:[127,255,127,0,0],A:[0,32,64,96,128],I:[0,63,128,192,255]},Zt={R:[0,255,255],G:[0,0,255],B:[0,0,0],A:[0,64,64],I:[0,86,255]},jt={R:[94,50,90,152,215,238,249,254,252,241,209,158],G:[79,131,186,214,240,244,237,210,157,100,57,1],B:[162,189,167,164,155,169,168,123,86,68,79,66],A:[0,12,23,35,47,58,70,81,93,105,116,128],I:[0,23,46,70,93,116,139,162,185,209,232,255]},Jt={R:[3,7,13,25,45,67,84,98,110,124,138,154,173,191,210,225,233,233,231,229,230,235,243,253],G:[19,33,48,63,77,87,92,94,95,96,96,97,99,101,106,118,133,149,163,177,192,208,225,245],B:[38,58,79,99,114,122,122,120,117,113,110,105,101,97,94,96,103,112,122,134,149,169,192,218],A:[0,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64],I:[0,11,22,33,44,55,66,77,88,99,110,121,133,144,155,166,177,188,199,210,221,232,243,255]},_t={R:[0,148,183,223,247,252],G:[0,44,55,74,112,253],B:[4,128,121,104,92,191],A:[0,44,53,64,75,107],I:[0,107,128,154,179,255]},$t={R:[11,59,55,222],G:[4,45,165,245],B:[5,91,172,229],A:[0,23,70,107],I:[0,56,167,255]},te={R:[3,5,6,8,12,19,28,36,42,48,54,61,68,76,86,96,110,129,154,181,205,224,239,252],G:[19,32,44,58,72,86,98,108,116,122,128,134,141,149,157,167,178,191,204,216,225,232,239,244],B:[39,60,82,104,123,137,144,145,142,138,134,130,126,121,116,110,105,104,112,131,155,178,198,217],A:[0,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64],I:[0,11,22,33,44,55,66,77,88,99,110,121,133,144,155,166,177,188,199,210,221,232,243,255]},ee={R:[0,85,0,0,0,0,0,0,85,255,255,255,172],G:[0,0,0,0,85,170,255,255,255,255,85,0,0],B:[0,170,85,255,255,170,170,0,85,0,0,0,0],A:[0,5,10,21,26,32,37,42,48,53,64,72,85],I:[0,15,31,63,79,95,111,127,143,159,191,217,255]},ie={R:[13,156,237,240],G:[8,23,121,249],B:[135,158,83,33],A:[0,56,80,88],I:[0,64,192,255]},ne={R:[208,71,33,192,32,195,208,173,233,202,25,210,145,89,87,245,246,38,3,25,57,167,245,86,227,208,81,64,90,199,140,48,212,180,70,120,9,192,245,177,65,157,9,193,100,181,125,145,62,8,108,36,140,237,242,248,161,189,41,114,65,121,97,50,238,149,44,214,124,167,40,167,127,178,231,30,173,244,193,203,204,238,139,135,71,234,234,217,66,14,129,19,97,165,112,244,35,73,192,12,149,71,33,192,32,195,208,173,233,202,25,210,145,89,87,245,246,38,3,25,57,167,245,86,227,208,81,64,90,199,140,48,212,180,70,120,9,192,245,177,65,157,9,193,100,181,125,145,62,8,108,36,140,237,242,248,161,189,41,114,65,121,97,50,238,149,44,214,124,167,40,167,127,178,231,30,173,244,193,203,204,238,139,135,71,234,234,217,66,14,129,19,97,165,112,244,35,73,192,12,149,71,33,192,32,195,208,173,233,202,25,210,145,89,87,245,246,38,3,25,57,167,245,86,227,208,81,64,90,199,140,48,212,180,70,120,9,192,245,177,65,157,9,193,100,181,125,145,62,8,108,36,140,237,242,248],G:[182,46,78,199,79,89,41,208,135,20,154,35,21,43,230,113,191,147,208,37,28,27,86,203,25,209,148,187,139,111,48,102,76,110,106,130,37,160,34,222,90,165,245,222,102,47,19,130,4,232,137,211,240,11,140,21,42,22,241,61,99,115,199,166,114,190,204,60,233,66,115,230,125,103,203,125,13,176,94,131,39,198,167,124,67,175,254,1,15,198,62,237,159,31,218,58,244,47,61,67,94,46,78,199,79,89,41,208,135,20,154,35,21,43,230,113,191,147,208,37,28,27,86,203,25,209,148,187,139,111,48,102,76,110,106,130,37,160,34,222,90,165,245,222,102,47,19,130,4,232,137,211,240,11,140,21,42,22,241,61,99,115,199,166,114,190,204,60,233,66,115,230,125,103,203,125,13,176,94,131,39,198,167,124,67,175,254,1,15,198,62,237,159,31,218,58,244,47,61,67,94,46,78,199,79,89,41,208,135,20,154,35,21,43,230,113,191,147,208,37,28,27,86,203,25,209,148,187,139,111,48,102,76,110,106,130,37,160,34,222,90,165,245,222,102,47,19,130,4,232,137,211,240,11,140,21],B:[191,154,43,10,207,204,164,231,136,58,239,30,147,230,101,111,150,35,128,57,252,79,173,120,25,126,81,85,8,7,122,237,190,152,246,182,130,219,67,76,167,178,235,250,28,61,186,250,199,67,58,50,86,182,108,77,89,112,59,125,226,50,205,227,125,128,104,27,59,66,53,133,159,203,97,125,139,159,158,7,215,47,140,226,223,231,44,110,184,61,233,47,67,148,22,120,173,156,117,181,94,154,43,10,207,204,164,231,136,58,239,30,147,230,101,111,150,35,128,57,252,79,173,120,25,126,81,85,8,7,122,237,190,152,246,182,130,219,67,76,167,178,235,250,28,61,186,250,199,67,58,50,86,182,108,77,89,112,59,125,226,50,205,227,125,128,104,27,59,66,53,133,159,203,97,125,139,159,158,7,215,47,140,226,223,231,44,110,184,61,233,47,67,148,22,120,173,156,117,181,94,154,43,10,207,204,164,231,136,58,239,30,147,230,101,111,150,35,128,57,252,79,173,120,25,126,81,85,8,7,122,237,190,152,246,182,130,219,67,76,167,178,235,250,28,61,186,250,199,67,58,50,86,182,108,77],A:[0,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64],I:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255]}
1,re={R:[0,128,255],G:[0,0,0],B:[0,0,0],A:[0,64,128],I:[0,128,255]},ae={R:[192,224,255],G:[1,128,255],B:[0,0,0],A:[0,64,128],I:[0,128,255]},se={R:[3,112,144,188,236,246,255],G:[5,31,29,22,76,158,250],B:[26,87,91,86,62,117,235],A:[0,30,38,49,67,85,107],I:[0,73,92,118,160,205,255]},oe={R:[1,240,255],G:[1,128,255],B:[1,128,255],A:[0,76,128],I:[0,153,255]},le={R:[0,5,18,34,53,72,90,107,126,144,161,178,194,209,222,233,242,248,251,251,249,244,241,252],G:[0,4,10,11,9,11,17,23,30,36,43,50,59,70,83,98,117,136,157,177,199,220,240,254],B:[3,24,50,76,96,106,109,110,108,104,97,89,79,67,55,42,26,12,6,22,47,79,121,164],A:[0,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64],I:[0,11,22,33,44,55,66,77,88,99,110,121,133,144,155,166,177,188,199,210,221,232,243,255]},ce={R:[48,48,64,70,65,25,132,195,244,254,218,122],G:[18,18,64,107,150,226,255,241,199,158,57,4],B:[59,59,162,227,255,187,81,52,58,47,7,3],A:[0,22,26,30,34,43,52,57,63,67,77,86],I:[0,1,16,32,49,83,118,140,164,181,219,255]},he={R:[0,128,255],G:[0,0,0],B:[0,128,255],A:[0,64,128],I:[0,128,255]},de={R:[68,49,53,253],G:[1,104,183,231],B:[84,142,121,37],A:[0,56,80,88],I:[0,64,192,255]},ue={R:[255,255,255],G:[127,196,254],B:[0,0,0],A:[0,64,128],I:[0,128,255]},me={R:[0,0,0],G:[0,128,255],B:[255,196,128],A:[0,64,128],I:[0,128,255]},fe={R:[3,64,0,0,255,255,255],G:[0,0,0,255,255,192,3],B:[0,32,48,56,64,96,128],A:[0,8,16,24,32,52,80],I:[0,32,64,96,160,192,255]},ge={min:0,max:0,R:[0,37],G:[242,0],B:[255,255],A:[0,64],I:[0,255]},Ae={R:[255,255],G:[255,11],B:[0,0],A:[0,64],I:[0,255]},pe={min:0,max:0,R:[65,10,223,120,216,207,251,93,252,217,21,253,131,165,173,143,144,217,86,89,63,254,172,1,142,107,42,78,221,8,222,71,127,126,167,33,104,2,208,216,0,251,7,105,2,101,248,190,253,62,255,224,166,37,110,138,45,34,6,37,69,201,43,122,199,37,173,194,103,211,75,159,96,4,239,98,110,193,253,166,40,255,48,130,140,243,101,9,177,220,133,32,4,81,48,48,210,109,60,132,1,119,1,159,247,33,212,187,253,144,196,254,168,79,64,196,39,97,73,173,104,216,217,43,101,119,254,5,237,103,203,122,57,87,251,164,19,75,200,2,252,150,66,0,255,157,23,254,55,16,240,161,69,253,207,195,5,60,255,251,200,217,134,123,253,180,27,246,130,136,250,232,4,125,140,22,253,255,13,180,123,61,254,111,10,185,76,192,255,223,186,61,198,5,172,13,83,172,171,6,23,73,134,133,109,61,213,55,57,132,36,209,2,144,1,253,68,155,3,160,2,77,121,70,67,176,223,131,4,162,232,255,150,94,235,191,207,10,246,0,225,4,209,116,57,112,172,253,1,6,92,227,73,62,135,223],G:[162,50,112,245,4,124,176,243,56,125,183,139,182,68,189,4,225,10,20,223,7,46,31,193,225,250,219,41,2,100,83,181,34,150,72,223,168,248,80,253,7,117,214,2,248,10,3,59,179,160,90,244,146,4,207,4,125,255,96,100,1,208,130,51,116,181,236,53,244,5,165,28,181,86,96,42,254,1,134,194,214,92,41,204,137,86,207,3,143,3,100,239,164,94,65,251,131,244,173,57,143,107,217,53,210,0,148,250,45,198,81,40,61,218,252,88,171,0,248,24,248,4,41,100,187,46,208,145,43,168,121,46,175,250,125,107,233,112,207,231,174,215,53,9,43,153,52,124,128,65,210,147,255,147,63,200,148,254,0,179,241,42,239,2,230,8,82,135,87,16,3,87,86,151,254,8,255,86,53,19,7,192,171,201,253,247,197,103,251,126,0,149,54,183,61,126,79,113,10,103,184,75,11,195,222,136,149,131,8,99,240,177,252,255,198,16,7,68,178,66,191,150,73,26,211,109,78,209,240,254,1,166,247,131,2,0,167,127,133,10,43,99,235,3,214,142,176,82,132,38,10,249,255,215,44,81],B:[176,182,248,37,117,35,96,69,32,152,108,20,237,250,2,89,141,216,111,251,211,149,10,44,214,103,31,251,3,32,252,246,97,1,219,167,197,4,36,116,206,118,106,43,205,204,114,69,127,205,87,80,41,251,145,204,253,161,247,1,149,9,43,253,97,72,136,161,171,181,26,255,108,80,218,214,231,255,84,31,109,4,218,3,217,36,68,85,241,39,221,2,240,2,173,42,206,5,110,46,103,27,212,184,2,207,246,45,116,72,110,253,38,105,248,159,243,81,192,93,141,145,24,157,234,131,57,178,62,75,65,176,148,40,253,66,76,240,51,154,17,251,139,253,207,9,114,49,200,254,96,73,138,118,204,102,137,89,145,161,4,112,66,234,147,178,212,205,185,11,203,131,2,250,118,169,1,185,154,53,171,197,61,175,249,96,15,254,95,5,222,75,246,194,2,61,180,25,133,165,15,233,59,35,221,140,109,7,114,255,198,0,115,168,252,23,242,80,75,142,137,255,12,182,68,201,4,111,37,228,83,248,24,192,249,5,54,223,160,122,160,114,145,119,252,31,253,250,10,214,8,47,0,142,222,70],A:[0,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64],I:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255]},ve=new class{constructor(){C(this,"gamma",1),C(this,"version",.1),C(this,"cluts",{});const t=Object.keys(q).filter((t=>!t.startsWith("$"))).sort(new Intl.Collator("en").compare);for(const e of t)this.cluts[e]=q[e]}addColormap(t,e){this.cluts[t]=e}colormaps(){return Object.keys(this.cluts)}colorMaps(){return this.colormaps()}colormapFromKey(t){let e=this.cluts[t];return void 0!==e?e:(e=this.cluts[t.toLowerCase()],void 0!==e?e:(t.length>0&&Q.warn("No color map named "+t),{min:0,max:0,R:[0,255],G:[0,255],B:[0,255],A:[0,255],I:[0,255]}))}colormap(t,e){void 0===t&&(t=""),void 0===e&&(e=!1);const i=this.colormapFromKey(t);return this.makeLut(i.R,i.G,i.B,i.A,i.I,e)}makeLabelLut(t,e,i){if(void 0===e&&(e=255),void 0===i&&(i=1/0),void 0===t.R||void 0===t.G||void 0===t.B)throw new Error(`Invalid colormap table: ${t}`);const n=t.R.length,r=t.I??[...Array(n).keys()];let a=!1;for(let m=0;m<r.length;m++)r[m]>i&&(a=!0,r[m]=i);if(a&&Q.warn("Some colormap indices clamped to match label range."),n!==t.G.length||n!==t.B.length||n!==r.length)throw new Error(`colormap does not make sense: ${t} Rs ${t.R.length} Gs ${t.G.length} Bs ${t.B.length} Is ${r.length}`);let s=new Uint8ClampedArray(n).fill(e);const o=r.indexOf(0);o>=0&&(s[o]=0),void 0!==t.A&&(s=Uint8ClampedArray.from(t.A));const l=Math.min(...r),c=Math.max(...r),h=c-l+1,d=new Uint8ClampedArray(4*h).fill(0);for(let m=0;m<n;m++){let e=4*(r[m]-l);d[e++]=t.R[m],d[e++]=t.G[m],d[e++]=t.B[m],d[e++]=s[m]}const u={lut:d,min:l,max:c};if(t.labels){const e=t.labels.length;if(e===h)u.labels=t.labels;else if(e===n){u.labels=Array(h).fill("?");for(let e=0;e<n;e++)u.labels[r[e]-l]=t.labels[e]}}return u}async makeLabelLutFromUrl(t,e,i){void 0===e&&(e=255),void 0===i&&(i=1/0);const n=await fetch(t),r=await n.json();return this.makeLabelLut(r,e,i)}makeDrawLut(t){let e="object"==typeof t?t:q[t];void 0===e&&(Q.warn("colormap undefined ",t),e=this.colormapFromKey(""));const i=this.makeLabelLut(e,255);if(void 0===i.labels&&(i.labels=[]),i.labels.length<256){for(let t=i.labels.length;t<256;t++)i.labels.push(t.toString())}const n=new Uint8ClampedArray(1024);let r=0;for(let s=0;s<256;s++)n[r++]=255,n[r++]=0,n[r++]=0,n[r++]=255;n[3]=0;const a=Math.min(i.lut.length,1024);if(a>0)for(let s=0;s<a;s++)n[s]=i.lut[s];return{lut:n,labels:i.labels}}makeLut(t,e,i,n,r,a){const s=t.length,o=[...t],l=[...e],c=[...i];if(!r){r=new Array(s);for(let t=0;t<s;t++)r[t]=t/(s-1)*255}n||((n=new Array(s).fill(64))[0]=0);let h=Uint8ClampedArray.from(n),d=Uint8ClampedArray.from(r);
1if(a)for(let m=0;m<s;m++)o[m]=t[s-1-m],l[m]=e[s-1-m],c[m]=i[s-1-m],h[m]=255-n[s-1-m],d[m]=255-r[s-1-m];const u=new Uint8ClampedArray(1024);if(void 0===d){d=new Uint8ClampedArray(s).fill(0);for(let t=0;t<s;t++)d[t]=Math.round(255*t/(s-1))}void 0===h&&(h=new Uint8ClampedArray(s).fill(64),h[0]=0);for(let m=0;m<s-1;m++){const t=d[m];let e=d[m+1];0===m&&0!==t&&Q.warn("colormap issue: indices expected to start with 0 not ",t),m===d.length-2&&255!==e&&(Q.warn("padding colormap: indices expected end with 255 not ",e),e=255);const i=e-t;let n=4*t;for(let r=t;r<=e;r++){const e=(r-t)/i;u[n++]=o[m]+e*(o[m+1]-o[m]),u[n++]=l[m]+e*(l[m+1]-l[m]),u[n++]=c[m]+e*(c[m+1]-c[m]),u[n++]=h[m]+e*(h[m+1]-h[m])}}if(1===this.gamma)return u;for(let m=0;m<1020;m++)m%4!=3&&(u[m]=255*Math.pow(u[m]/255,1/this.gamma));return u}},xe=class{static getClusterBoundaryU8(t,e){const i=new Array(t.length).fill(!1),n=new Array(t.length).fill(!1);for(let s=0;s<t.length;s++)t[s]>0&&(n[s]=!0);const r=e.length/3;let a=0;for(let s=0;s<r;s++){const t=e[a],r=e[a+1],s=e[a+2];a+=3,n[t]===n[r]&&n[t]===n[s]&&n[r]===n[s]||(i[t]=!0,i[r]=!0,i[s]=!0)}return i}static async gzip(t){const e=new CompressionStream("gzip"),i=e.writable.getWriter();i.write(t).catch(console.error);const n=i.close().catch(console.error),r=new Response(e.readable),a=new Uint8Array(await r.arrayBuffer());return await n,a}static createMZ3(t,e,i,n,r,a){void 0===i&&(i=!1),void 0===n&&(n=null),void 0===r&&(r=null),void 0===a&&(a=null);const s=e?e.length/3:0,o=t?t.length/3:0;if(!Number.isInteger(s)||s<0)throw new Error("indices length must be a multiple of 3");if(!Number.isInteger(o)||o<0)throw new Error("vertices length must be a multiple of 3");const l=e&&e.length>0,c=t&&t.length>0,h=n instanceof Uint8Array&&n.length===4*o;let d=null,u=0;if(null!=a){const t="string"==typeof a?a:JSON.stringify(a);d=(new TextEncoder).encode(t),u=d.byteLength}let m=!1,f=0;if(null!=r){if(!(r instanceof Float32Array))throw new Error("scalars must be a Float32Array or null/undefined");if(0===o)throw new Error("cannot have scalars without vertices (nvert === 0)");if(!(r.length>0&&r.length%o==0))throw new Error(`scalars.length (${r.length}) must be a positive integer multiple of nvert (${o})`);m=!0,f=r.length/o}let g=0;l&&(g|=1),c&&(g|=2),h&&(g|=4),m&&(g|=8),d&&(g|=64);const A=l?3*s*4:0,p=c?3*o*4:0,v=h?4*o:0,x=m?f*o*4:0,w=16+u+A+p+v+x,y=new ArrayBuffer(w),b=new DataView(y);let C=0;b.setUint16(C,23117,!0),C+=2,b.setUint16(C,g,!0),C+=2,b.setUint32(C,s,!0),C+=4,b.setUint32(C,o,!0),C+=4,b.setUint32(C,u,!0),C+=4;let M=16;if(u>0&&d&&(new Uint8Array(y,M,d.length).set(d),M+=u),l&&(new Uint32Array(y,M,e.length).set(e),M+=A),c&&(new Float32Array(y,M,t.length).set(t),M+=p),h&&(new Uint8Array(y,M,n.length).set(n),M+=v),m&&(new Float32Array(y,M,r.length).set(r),M+=x),M!==w)throw new Error(`mz3 internal size mismatch: offset ${M} !== totalSize ${w}`);if(i)throw new Error("Call async createMZ3Async() for compression");return y}static async createMZ3Async(t,e,i,n,r,a){void 0===i&&(i=!1),void 0===n&&(n=null),void 0===r&&(r=null),void 0===a&&(a=null);const s=this.createMZ3(t,e,i,n,r,a);return i?await this.gzip(new Uint8Array(s)):s}static createOBJ(t,e){let i="";for(let n=0;n<t.length;n+=3)i+=`v ${t[n]} ${t[n+1]} ${t[n+2]}\n`;for(let n=0;n<e.length;n+=3)i+=`f ${e[n]+1} ${e[n+1]+1} ${e[n+2]+1}\n`;return(new TextEncoder).encode(i).buffer}static createSTL(t,e){const i=e.length/3,n=new ArrayBuffer(84+50*i),r=new DataView(n);for(let s=0;s<80;s++)r.setUint8(s,0);r.setUint32(80,i,!0);let a=84;for(let s=0;s<e.length;s+=3){const i=3*e[s],n=3*e[s+1],o=3*e[s+2];r.setFloat32(a,0,!0),r.setFloat32(a+4,0,!0),r.setFloat32(a+8,0,!0),a+=12,r.setFloat32(a,t[i],!0),r.setFloat32(a+4,t[i+1],!0),r.setFloat32(a+8,t[i+2],!0),a+=12,r.setFloat32(a,t[n],!0),r.setFloat32(a+4,t[n+1],!0),r.setFloat32(a+8,t[n+2],!0),a+=12,r.setFloat32(a,t[o],!0),r.setFloat32(a+4,t[o+1],!0),r.setFloat32(a+8,t[o+2],!0),a+=12,r.setUint16(a,0,!0),a+=2}return n}static downloadArrayBuffer(t,e){const i=new Blob([t],{type:"application/octet-stream"}),n=URL.createObjectURL(i),r=document.createElement("a");r.href=n,r.download=e,document.body.appendChild(r),r.style.display="none",r.click(),setTimeout((()=>{document.body.removeChild(r),URL.revokeObjectURL(n)}),0)}static async saveMesh(t,e,i,n){void 0===i&&(i=".mz3"),void 0===n&&(n=!1);let r=new ArrayBuffer(0);return/\.obj$/i.test(i)?r=this.createOBJ(t,e):/\.stl$/i.test(i)?r=this.createSTL(t,e):(/\.mz3$/i.test(i)||(i+=".mz3"),r=await this.createMZ3Async(t,e,n)),i.length>4&&this.downloadArrayBuffer(r,i),r}static getClusterBoundary(t,e){const i=new Uint32Array(t.buffer),n=new Array(i.length).fill(!1),r=e.length/3;let a=0;for(let s=0;s<r;s++){const t=e[a],r=e[a+1],s=e[a+2];a+=3,i[t]===i[r]&&i[t]===i[s]&&i[r]===i[s]||(n[t]=!0,n[r]=!0,n[s]=!0)}return n}static getExtents(t){if(!ArrayBuffer.isView(t)&&!Array.isArray(t)||t.length<3)return{mxDx:0,extentsMin:0,extentsMax:0};let e=0;const i=r.fA(t[0],t[1],t[2]),n=r.fA(t[0],t[1],t[2]);for(let a=0;a<t.length;a+=3){const s=r.fA(t[a],t[a+1],t[a+2]);e=Math.max(e,r.Il(s)),r.jk(i,i,s),r.T9(n,n,s)}return{mxDx:e,extentsMin:[i[0],i[1],i[2]],extentsMax:[n[0],n[1],n[2]]}}static generateNormals(t,e){const i=[];let n;const r=t.length;let a,s,o,l,c,h,d,u,m;const f=new Float32Array(r),g=e.length;for(n=0;n<g;n+=3){d=3*e[n],u=3*e[n+1],m=3*e[n+2];const r=[t[d],t[d+1],t[d+2]],g=[t[u],t[u+1],t[u+2]],A=[t[m],t[m+1],t[m+2]];a=g[0]-r[0],s=g[1]-r[1],o=g[2]-r[2],l=A[0]-r[0],c=A[1]-r[1],h=A[2]-r[2],i[0]=c*o-h*s,i[1]=h*a-l*o,i[2]=l*s-c*a,f[d]+=i[0],f[d+1]+=i[1],f[d+2]+=i[2],f[u]+=i[0],f[u+1]+=i[1],f[u+2]+=i[2],f[m]+=i[0],f[m+1]+=i[1],f[m+2]+=i[2]}for(n=0;n<r;n+=3){i[0]=-1*f[n],i[1]=-1*f[n+1],i[2]=-1*f[n+2];let t=i[0]*i[0]+i[1]*i[1]+i[2]*i[2];t>0&&(t=1/Math.sqrt(t),i[0]*=t,i[1]*=t,i[2]*=t),f[n]=i[0],f[n+1]=i[1],f[n+2]=i[2]}return f}},we=class{constructor(t){T(this,Z),T(this,j,0),T(this,J,[]),T(this,_,[]),T(this,$),I(this,Z,new DataView(t)),this.read()}async extract(t){const e=new Uint8Array(D(this,Z).buffer.slice(t.startsAt,t.startsAt+t.compressedSize));if(0===t.compressionMethod)return e;if(8===t.compressionMethod){const t=new DecompressionStream("deflate-raw"),i=t.writable.getWriter();i.write(e).catch(console.error);
1const n=i.close().catch(console.error),r=new Response(t.readable),a=new Uint8Array(await r.arrayBuffer());return await n,a}throw new Error(`Unsupported compression method: ${t.compressionMethod}`)}read(){for(;!D(this,$)&&D(this,j)<D(this,Z).byteLength;){const t=D(this,Z).getUint32(D(this,j),!0);if(67324752===t){const t=this.readLocalFile(D(this,j));t.extract=this.extract.bind(this,t),D(this,J).push(t);const e=!!(8&t.generalPurpose);if(t.startsAt=D(this,j)+30+t.fileNameLength+t.extraLength,0===t.compressedSize&&e){let e=t.startsAt;for(;e+20<=D(this,Z).byteLength;){if(134695760===D(this,Z).getUint32(e,!0)){if(19280===D(this,Z).getUint16(e+16,!0)){e+=4;break}}e++}t.crc=D(this,Z).getUint32(e,!0),t.compressedSize=D(this,Z).getUint32(e+4,!0),t.uncompressedSize=D(this,Z).getUint32(e+8,!0),I(this,j,e+12)}else I(this,j,t.startsAt+t.compressedSize)}else{if(33639248!==t){if(101010256===t){I(this,$,this.readEndCentralDirectory(D(this,j)));break}if(101075792===t){I(this,$,this.readEndCentralDirectory64(D(this,j)));break}console.error(`Unexpected ZIP signature 0x${t.toString(16).padStart(8,"0")} at index ${D(this,j)}`);break}{const t=this.readCentralDirectory(D(this,j));D(this,_).push(t),I(this,j,D(this,j)+(46+t.fileNameLength+t.extraLength+t.fileCommentLength))}}}}readLocalFile(t){let e=D(this,Z).getUint32(t+18,!0),i=D(this,Z).getUint32(t+22,!0);const n=D(this,Z).getUint16(t+26,!0),r=D(this,Z).getUint16(t+28,!0),a=t+30+n;this.readString(a,r);if(4294967295===e&&4294967295===i){let t=a,n=!1;for(;t<a+r-4;){const r=D(this,Z).getUint16(t,!0),a=D(this,Z).getUint16(t+2,!0);if(t+=4,1===r){if(a>=16){i=Number(D(this,Z).getBigUint64(t,!0)),t+=8,e=Number(D(this,Z).getBigUint64(t,!0)),n=!0;break}throw new Error(`ZIP64 extra field found but is too small (expected at least 16 bytes, got ${a}).`)}t+=a}if(!n)throw new Error("ZIP64 format missing extra field with signature 0x0001.")}return{signature:this.readString(t,4),version:D(this,Z).getUint16(t+4,!0),generalPurpose:D(this,Z).getUint16(t+6,!0),compressionMethod:D(this,Z).getUint16(t+8,!0),lastModifiedTime:D(this,Z).getUint16(t+10,!0),lastModifiedDate:D(this,Z).getUint16(t+12,!0),crc:D(this,Z).getUint32(t+14,!0),compressedSize:e,uncompressedSize:i,fileNameLength:n,extraLength:r,fileName:this.readString(t+30,n),extra:this.readString(t+30+n,r)}}readCentralDirectory(t){return{versionCreated:D(this,Z).getUint16(t+4,!0),versionNeeded:D(this,Z).getUint16(t+6,!0),fileNameLength:D(this,Z).getUint16(t+28,!0),extraLength:D(this,Z).getUint16(t+30,!0),fileCommentLength:D(this,Z).getUint16(t+32,!0),diskNumber:D(this,Z).getUint16(t+34,!0),internalAttributes:D(this,Z).getUint16(t+36,!0),externalAttributes:D(this,Z).getUint32(t+38,!0),offset:D(this,Z).getUint32(t+42,!0),comments:this.readString(t+46,D(this,Z).getUint16(t+32,!0))}}readEndCentralDirectory(t){const e=D(this,Z).getUint16(t+20,!0);return{numberOfDisks:D(this,Z).getUint16(t+4,!0),centralDirectoryStartDisk:D(this,Z).getUint16(t+6,!0),numberCentralDirectoryRecordsOnThisDisk:D(this,Z).getUint16(t+8,!0),numberCentralDirectoryRecords:D(this,Z).getUint16(t+10,!0),centralDirectorySize:D(this,Z).getUint32(t+12,!0),centralDirectoryOffset:D(this,Z).getUint32(t+16,!0),commentLength:e,comment:this.readString(t+22,e)}}readEndCentralDirectory64(t){const e=Number(D(this,Z).getBigUint64(t+0,!0));return{numberOfDisks:D(this,Z).getUint32(t+16,!0),centralDirectoryStartDisk:D(this,Z).getUint32(t+20,!0),numberCentralDirectoryRecordsOnThisDisk:Number(D(this,Z).getBigUint64(t+24,!0)),numberCentralDirectoryRecords:Number(D(this,Z).getBigUint64(t+32,!0)),centralDirectorySize:Number(D(this,Z).getBigUint64(t+40,!0)),centralDirectoryOffset:Number(D(this,Z).getBigUint64(t+48,!0)),commentLength:e,comment:""}}readString(t,e){return Array.from({length:e},((e,i)=>String.fromCharCode(D(this,Z).getUint8(t+i)))).join("")}get entries(){return D(this,J)}};Z=new WeakMap,j=new WeakMap,J=new WeakMap,_=new WeakMap,$=new WeakMap;var ye=class t{static arrayBufferToBase64(e){const i=new Uint8Array(e);return t.uint8tob64(i)}static async decompress(t){const e=31===t[0]&&139===t[1]&&8===t[2]?"gzip":120!==t[0]||1!==t[1]&&94!==t[1]&&156!==t[1]&&218!==t[1]?"deflate-raw":"deflate",i=new DecompressionStream(e),n=i.writable.getWriter();n.write(t).catch(console.error);const r=n.close().catch(console.error),a=new Response(i.readable),s=new Uint8Array(await a.arrayBuffer());return await r,s}static async decompressToBuffer(e){const i=await t.decompress(e);return i.buffer.slice(i.byteOffset,i.byteOffset+i.byteLength)}static async readMatV4(t,e){void 0===e&&(e=!1);let i=t.byteLength;if(i<40)throw new Error("File too small to be MAT v4: bytes = "+t.byteLength);let n=new DataView(t),r=n.getUint16(0,!0),a=t;if(35615===r||8075===r){const e=await this.decompress(new Uint8Array(t));n=new DataView(e.buffer),r=n.getUint16(0,!0),a=e.buffer,i=a.byteLength}const s=new TextDecoder("utf-8"),o=new Uint8Array(a);let l=0;const c={};function h(){const t=n.getUint32(l,!0),i=n.getUint32(l+4,!0),r=n.getUint32(l+8,!0),a=n.getUint32(l+12,!0),h=n.getUint32(l+16,!0);if(l+=20,0!==a)throw new Error("Matlab V4 reader does not support imaginary numbers");const d=i*r;if(d<1)throw new Error("mrows * ncols must be greater than one");const u=new Uint8Array(o.subarray(l,l+h));let m=s.decode(u).trim().replaceAll("\0","");e&&(m=m.replaceAll(".","_"));const f=(g=t,Math.floor(g/10)%10);var g;let A=8;if(f>=1&&f<=2)A=4;else if(f>=3&&f<=4)A=2;else if(5===f)A=1;else if(0!==f)throw new Error("impossible Matlab v4 datatype");if(l+=h,t>50)throw new Error("Does not appear to be little-endian V4 Matlab file");const p=l+d*A;
1c[m]=function(t,e,i){const n=new Uint8Array(o.subarray(e,i));return 1===t?new Float32Array(n.buffer):2===t?new Int32Array(n.buffer):3===t?new Int16Array(n.buffer):4===t?new Uint16Array(n.buffer):5===t?new Uint8Array(n.buffer):new Float64Array(n.buffer)}(f,l,p),l=p}for(;l+20<i;)h();return c}static b64toUint8(t){const e=atob(t),i=e.length,n=new Uint8Array(i);for(let r=0;r<i;r++)n[r]=e.charCodeAt(r);return n}static uint8tob64(t){let e="";const i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",n=t.byteLength,r=n%3,a=n-r;let s,o,l,c,h;for(let d=0;d<a;d+=3)h=t[d]<<16|t[d+1]<<8|t[d+2],s=(16515072&h)>>18,o=(258048&h)>>12,l=(4032&h)>>6,c=63&h,e+=i[s]+i[o]+i[l]+i[c];return 1===r?(h=t[a],s=(252&h)>>2,o=(3&h)<<4,e+=i[s]+i[o]+"=="):2===r&&(h=t[a]<<8|t[a+1],s=(64512&h)>>10,o=(1008&h)>>4,l=(15&h)<<2,e+=i[s]+i[o]+i[l]+"="),e}static download(t,e,i){const n=document.createElement("a"),r=Array.isArray(t)?t:[t],a=new Blob(r,{type:i});n.href=URL.createObjectURL(a),n.download=e,n.click()}static readFileAsync(t){return new Promise(((e,i)=>{const n=new FileReader;n.onload=()=>{e(n.result)},n.onerror=i,n.readAsArrayBuffer(t)}))}static blobToBase64(t){return new Promise((e=>{const i=new FileReader;i.onloadend=()=>e(i.result),i.readAsDataURL(t)}))}static async decompressBase64String(e){const i=atob(e),n=new ArrayBuffer(i.length),r=new 
1Uint8Array(n);for(let t=0;t<i.length;t++)r[t]=i.charCodeAt(t);return t.decompressArrayBuffer(r)}static async compressToBase64String(e){const i=await t.compressStringToArrayBuffer(e);return t.uint8tob64(new Uint8Array(i))}static strToU8(t,e){if(e){const e=new Uint8Array(t.length);for(let i=0;i<t.length;++i)e[i]=t.charCodeAt(i);return e}const i=t.length;let n=new Uint8Array(t.length+(t.length>>1)),r=0;const a=t=>{n[r++]=t};for(let c=0;c<i;++c){if(r+5>n.length){const t=new Uint8Array(r+8+(i-c<<1));t.set(n),n=t}let s=t.charCodeAt(c);s<128||e?a(s):s<2048?(a(192|s>>6),a(128|63&s)):(s=65536+(1047552&s)|1023&t.charCodeAt(++c),a(240|s>>18),a(128|s>>12&63),a(128|s>>6&63),a(128|63&s))}return s=n,(null==(o=0)||o<0)&&(o=0),(null==(l=r)||l>s.length)&&(l=s.length),new Uint8Array(s.subarray(o,l));var s,o,l}static async compress(t,e){void 0===e&&(e="gzip");const i=new CompressionStream(e),n=i.writable.getWriter();n.write(t).catch(console.error);const r=n.close().catch(console.error),a=new Response(i.readable),s=await a.arrayBuffer();return await r,s}static async compressStringToArrayBuffer(t){const e=this.strToU8(t);return await this.compress(e)}static isArrayBufferCompressed(t){if(t&&t.byteLength){const e=new Uint8Array(t);return 8075===(e[0]<<8|e[1])}return!1}static strFromU8(t,e){if(e){let e="";for(let i=0;i<t.length;i+=16384)e+=String.fromCharCode.apply(null,t.subarray(i,i+16384));return e}{const e=(t,e,i)=>((null==e||e<0)&&(e=0),(null==i||i>t.length)&&(i=t.length),new Uint8Array(t.subarray(e,i))),i=t=>{for(let i="",n=0;;){let r=t[n++];const a=(r>127)+(r>223)+(r>239);if(n+a>t.length)return{s:i,r:e(t,n-1)};a?3===a?(r=((15&r)<<18|(63&t[n++])<<12|(63&t[n++])<<6|63&t[n++])-65536,i+=String.fromCharCode(55296|r>>10,56320|1023&r)):i+=1&a?String.fromCharCode((31&r)<<6|63&t[n++]):String.fromCharCode((15&r)<<12|(63&t[n++])<<6|63&t[n++]):i+=String.fromCharCode(r)}},{s:n,r:r}=i(t);if(r.length)throw new Error("Unexpected trailing bytes in UTF-8 decoding");return n}}static async decompressArrayBuffer(t){const e=await this.decompress(new Uint8Array(t));return this.strFromU8(e)}static arraysAreEqual(t,e){return l(t,e)}static range(t,e,i){return Array.from({length:(e-t)/i+1},((e,n)=>t+n*i))}static sph2cartDeg(t,e){const i=-e*(Math.PI/180),n=(t-90)%360*(Math.PI/180),r=[Math.cos(i)*Math.cos(n),Math.cos(i)*Math.sin(n),Math.sin(i)],a=Math.sqrt(r[0]*r[0]+r[1]*r[1]+r[2]*r[2]);return a<=0||(r[0]/=a,r[1]/=a,r[2]/=a),r}static vox2mm(t,e){const i=a.o8(e);a.mg(i,i);const s=n.fA(t[0],t[1],t[2],1);n.Z0(s,s,i);return r.fA(s[0],s[1],s[2])}},be=Q,Ce=class t{static readTRACT(t){const e=t.byteLength;if(e<20)throw new Error("File too small to be niml.tract: bytes = "+e);const i=new DataView(t),n=new Uint8Array(t);let r=0;function a(){for(;r<e&&60!==n[r];)r++;const i=r;for(;r<e&&62!==n[r];)r++;return r++,r-i<1?"":(new TextDecoder).decode(t.slice(i,r-1)).trim()}let s=a();function o(t){const e=s.indexOf(t);if(e<0)return 0;const i=s.indexOf('"',e)+1,n=s.indexOf('"',i),r=s.slice(i,n);return parseInt(r)}const l=o("N_tracts=");(!s.startsWith("<network")||l<1)&&Q.warn("This is not a valid niml.tract file "+s);let c=0;const h=[];h.push(c);const d=[],u=[];for(let f=0;f<l;f++){s=a();const t=o("ni_dimen="),e=o("Bundle_Tag="),n=s.includes("binary.lsbfirst");for(let a=0;a<t;a++){r+=4;const t=i.getUint32(r,n)/3;r+=4;for(let e=0;e<t;e++)d.push(i.getFloat32(r,n)),r+=4,d.push(-i.getFloat32(r,n)),r+=4,d.push(i.getFloat32(r,n)),r+=4;c+=t,h.push(c),u.push(e)}s=a()}const m=[];return m.push({id:"tract",vals:Float32Array.from(u)}),{pts:new Float32Array(d),offsetPt0:new Uint32Array(h),dps:m}}static async readTT(t){let e=new Uint32Array(0),i=new Float32Array(0);const r=await ye.readMatV4(t);if(!("trans_to_mni"in r))throw new Error("TT format file must have 'trans_to_mni'");if(!("voxel_size"in r))throw new Error("TT format file must have 'voxel_size'");if(!("track"in r))throw new Error("TT format file must have 'track'");let s=a.vt();const o=r.trans_to_mni;return s=a.fA(o[0],o[1],o[2],o[3],o[4],o[5],o[6],o[7],o[8],o[9],o[10],o[11],o[12],o[13],o[14],o[15]),a.mg(s,s),function(t){const r=new DataView(t.buffer),a=[];let o=0,l=0;for(;l<t.length;){a.push(l);const t=r.getUint32(l,!0);l=l+t+13,o+=t}
1e=new Uint32Array(a.length+1),i=new Float32Array(o);let c=0;for(let n=0;n<a.length;n++){e[n]=c/3;let t=a[n];const s=r.getUint32(t,!0)/3;let o=r.getInt32(t+4,!0),l=r.getInt32(t+8,!0),h=r.getInt32(t+12,!0);t+=16,i[c++]=o,i[c++]=l,i[c++]=h;for(let e=2;e<=s;e++)o+=r.getInt8(t++),l+=r.getInt8(t++),h+=r.getInt8(t++),i[c++]=o,i[c++]=l,i[c++]=h}for(let e=0;e<c;e++)i[e]=i[e]/32;let h=0;for(let e=0;e<c/3;e++){const t=n.fA(i[h],i[h+1],i[h+2],1);n.Z0(t,t,s),i[h++]=t[0],i[h++]=t[1],i[h++]=t[2]}e[a.length]=c/3}(r.track),{pts:i,offsetPt0:e}}static assembleDpgFromMap(t,e){if(!Array.isArray(e)||0===e.length)throw new Error('assembleDpgFromMap: "groups" is empty or missing; cannot assemble dpg.');const i=new Set;for(const r in t)t[r].forEach((t=>i.add(t.id)));const n=[];for(const r of i){const i=[];let a=0;for(let n=0;n<e.length;n++){const s=(t[String(e[n].id)]||[]).find((t=>t.id===r));if(s){const t=s.vals instanceof Float32Array?s.vals:Float32Array.from(s.vals);i.push(t),a+=t.length}else{const t=new Float32Array([NaN]);i.push(t),a+=t.length}}const s=new Float32Array(a);let o=0;for(const t of i)s.set(t,o),o+=t.length;n.push({id:r,vals:s})}return n}static async readTRX(t){function e(t){const e=(31744&t)>>10,i=1023&t;return(t>>15?-1:1)*(e?31===e?i?NaN:1/0:Math.pow(2,e-15)*(1+i/1024):i/1024*6103515625e-14)}let i=0,n=0,r=new Float32Array([]);const a=[],s={},o=[],l=[],c=[];let h=[],d=!1;const u=new we(t);for(let f=0;f<u.entries.length;f++){const t=u.entries[f];if(0===t.uncompressedSize)continue;const m=t.fileName.split("/"),g=m.slice(-1)[0];if(g.startsWith("."))continue;const A=m.slice(-3)[0],p=m.slice(-2)[0],v=g.split(".")[0],x=await t.extract();if(g.includes("header.json")){const t=(new TextDecoder).decode(x);h=JSON.parse(t);continue}let w=0,y=[];
1if(g.endsWith(".uint64")||g.endsWith(".int64")){w=x.length/8,y=new Uint32Array(w);const t=new Uint32Array(x.buffer);let e=0;for(let i=0;i<w;i++)y[i]=t[e],0!==t[e+1]&&(d=!0),e+=2}else if(g.endsWith(".uint32"))y=new Uint32Array(x.buffer);else if(g.endsWith(".uint16"))y=new Uint16Array(x.buffer);else if(g.endsWith(".uint8"))y=new Uint8Array(x.buffer);else if(g.endsWith(".int32"))y=new Int32Array(x.buffer);else if(g.endsWith(".int16"))y=new Int16Array(x.buffer);else if(g.endsWith(".int8"))y=new Int8Array(x.buffer);else if(g.endsWith(".float64"))y=new Float64Array(x.buffer);else if(g.endsWith(".float32"))y=new Float32Array(x.buffer);else{if(!g.endsWith(".float16"))continue;{w=x.length/2,y=new Float32Array(w);const t=new Uint16Array(x.buffer),i=new Float32Array(65536);for(let n=0;n<65536;n++)i[n]=e(n);for(let e=0;e<w;e++)y[e]=i[t[e]]}}if(w=y.length,p.includes("groups"))o.push({id:v,vals:Float32Array.from(y.slice())});else if(A.includes("dpg")){const t=String(p);s[t]||(s[t]=[]),s[t].push({id:v,vals:Float32Array.from(y.slice())})}else if(p.includes("dpv"))c.push({id:v,vals:Float32Array.from(y.slice())});else if(p.includes("dps"))l.push({id:v,vals:Float32Array.from(y.slice())});else{if(g.startsWith("offsets.")){i=w;for(let t=0;t<w;t++)a[t]=y[t]}g.startsWith("positions.3.")&&(n=w,r=new Float32Array(y))}}if(0===i||0===n)throw new Error("Failure reading TRX format (no offsets or points).");if(d)throw new Error("Too many vertices: JavaScript does not support 64 bit integers");let m=[];return o.length>0&&s&&Object.keys(s).length>0&&(m=this.assembleDpgFromMap(s,o)),a[i]=n/3,{pts:r,offsetPt0:new Uint32Array(a),dpg:m,dps:l,dpv:c,groups:o,header:h}}static readTXT(t,e){void 0===e&&(e=0);const i=new TextDecoder("utf-8").decode(t).split(/\r?\n|\r/).filter((t=>t.trim().length>0));e<=0&&(e=i.length);const n=new Float32Array(e);for(let r=0;r<e&&r<i.length;r++){const t=parseFloat(i[r].trim());n[r]=Number.isFinite(t)?t:0}return n}static readTSF(t,e){void 0===e&&(e=0);const i=new Float32Array(e),n=t.byteLength;if(n<20)throw new Error("File too small to be TSF: bytes = "+n);const r=new Uint8Array(t);let a=0;function s(){for(;a<n&&10===r[a];)a++;const e=a;for(;a<n&&10!==r[a];)a++;return a++,a-e<1?"":(new TextDecoder).decode(t.slice(e,a-1))}let o=s();if(!o.includes("mrtrix track scalars"))throw new Error("Not a valid TSF file");let l=-1;for(;a<n&&!o.includes("END");)if(o=s(),o.toLowerCase().startsWith("file:")&&(l=parseInt(o.split(" ").pop())),o.toLowerCase().startsWith("datatype:")&&!o.endsWith("Float32LE"))throw new Error("Only supports TSF files with Float32LE");if(l<20)throw new Error("Not a valid TSF file (missing file offset)");a=l;const c=new DataView(t);let h=0;for(;a+4<=n&&h<e;){const t=c.getFloat32(a,!0);if(a+=4,isFinite(t))i[h++]=t;else if(!isNaN(t))break}return i}static readTCK(t){const e=t.byteLength;if(e<20)throw new Error("File too small to be TCK: bytes = "+e);const i=new Uint8Array(t);let n=0;function r(){for(;n<e&&10===i[n];)n++;const r=n;for(;n<e&&10!==i[n];)n++;return n++,n-r<1?"":(new TextDecoder).decode(t.slice(r,n-1))}let a=r();if(!a.includes("mrtrix tracks"))throw new Error("Not a valid TCK file");let s=-1;for(;n<e&&!a.includes("END");)a=r(),a.toLowerCase().startsWith("file:")&&(s=parseInt(a.split(" ").pop()));if(s<20)throw new Error("Not a valid TCK file (missing file offset)");n=s;const o=new DataView(t);let l=0,c=new Uint32Array(e/16),h=0,d=0,u=new Float32Array(e/4);for(c[0]=0;n+12<e;){const t=o.getFloat32(n,!0);n+=4;const e=o.getFloat32(n,!0);n+=4;const i=o.getFloat32(n,!0);if(n+=4,isFinite(t))u[d++]=t,u[d++]=e,u[d++]=i,l++;else if(c[h++]=l,!isNaN(t))break}return u=u.slice(0,d),c=c.slice(0,h),{pts:u,offsetPt0:c}}static async readTRK(t){let e=new DataView(t),i=e.getUint32(0,!0);if(1128354388!==i){let n;if(4247762216===i)throw new Error("zstd TRK decompression is not supported");n=await ye.decompress(new Uint8Array(t)),t=n.buffer,e=new DataView(t),i=e.getUint32(0,!0)}const n=e.getUint32(992,!0),r=e.getUint32(996,!0);if(n>3||1e3!==r||1128354388!==i)throw new Error(`Not a valid TRK file expected version \u22643 (${n}), header size 1000 (${r}) and magic of 1128354388 (${i})`);const s=e.getInt16(36,!0),o=[];for(let a=0;a<s;a++){const e=new Uint8Array(t.slice(38+20*a,58+20*a)),i=(new TextDecoder).decode(e).split("\0").shift();o.push({id:i.trim(),vals:[]})}const l=e.getFloat32(12,!0),c=e.getFloat32(16,!0),h=e.getFloat32(20,!0),d=a.fA(1/l,0,0,-.5,0,1/c,0,-.5,0,0,1/h,-.5,0,0,0,1),u=e.getInt16(238,!0),m=[];for(let a=0;a<u;a++){const e=new Uint8Array(t.slice(240+20*a,260+20*a)),i=(new TextDecoder).decode(e).split("\0").shift();m.push({id:i.trim(),vals:[]})}const f=a.vt();for(let a=0;a<16;a++)f[a]=e.getFloat32(440+4*a,!0);0===f[15]&&(Q.warn("TRK vox_to_ras not set"),a.D_(f));const g=a.vt();a.lK(g,d,f);let A=null,p=null;A=new Int32Array(t.slice(r)),p=new Float32Array(A.buffer);const v=A.length;if(v<1)throw new Error("Empty TRK file.");let x=0,w=0,y=new Uint32Array(A.length/4),b=0,C=new Float32Array(A.length),M=0;for(;x<v;){const t=A[x];x+=1,y[b++]=w;for(let e=0;e<t;e++){const t=p[x+0],e=p[x+1],i=p[x+2];if(x+=3,C[M++]=t*g[0]+e*g[1]+i*g[2]+g[3],C[M++]=t*g[4]+e*g[5]+i*g[6]+g[7],C[M++]=t*g[8]+e*g[9]+i*g[10]+g[11],s>0)for(let n=0;n<s;n++)o[n].vals.push(p[x]),x++;w++}if(u>0)for(let e=0;e<u;e++)m[e].vals.push(p[x]),x++}const D=[];for(let a=0;a<m.length;a++)D.push({id:m[a].id,vals:Float32Array.from(m[a].vals)});const T=[];for(let a=0;a<o.length;a++)T.push({id:o[a].id,vals:Float32Array.from(o[a].vals)});return y[b++]=w,C=C.slice(0,M),y=y.slice(0,b),{pts:C,offsetPt0:y,dps:D,dpv:T}}static readTxtVTK(t){const e=new TextDecoder("utf-8").decode(t).split("\n");if(e.length<7||!e[0].startsWith("# vtk DataFile"))throw new Error("Invalid VTK image");if(!e[2].startsWith("ASCII"))throw new Error("Not ASCII VTK mesh");let i=3;for(;e[i].length<1;)i++;if(!e[i].includes("POLYDATA"))throw new Error("Not ASCII VTK polydata");for(i++;e[i].length<1;)i++;if(!e[i].startsWith("POINTS"))throw new Error("Not VTK POINTS");let n=e[i].trim().split(/\s+/);const r=parseInt(n[1]),a=3*r,s=new Float32Array(3*r);let o=0;for(;o<3*r;){i++;const t=e[i].trim().trim().split(/\s+/);for(let e=0;e<t.length&&!(o>=a);
1e++)s[o]=parseFloat(t[e]),o++}const l=[];for(i++;e[i].length<1;)i++;if(e[i].startsWith("METADATA")){for(;e[i].length>1;)i++;i++}if(n=e[i].trim().split(/\s+/),i++,n[0].includes("LINES")){const t=parseInt(n[1]);if(t<1)throw new Error("Corrupted VTK ASCII");let r=e[i].trim();const a=[];let o=[];if(r.startsWith("OFFSETS")){i++;let n=0;for(;n<t;){r=e[i].trim(),i++;const s=r.trim().split(/\s+/);for(let e=0;e<s.length&&(a[n]=parseInt(s[e]),n++,!(n>=t));e++);}o=Array.from(s)}else{let n=function(){r=e[i].trim();const t=r.trim().split(/\s+/);c=[];for(let e=0;e<t.length;e++)c.push(parseInt(t[e]));h=0,i++},l=0;a[0]=0;let c=[],h=0;n();for(let e=0;e<t;e++){h>=c.length&&n();const t=c[h++];l+=t,a[e+1]=l;for(let e=0;e<t;e++){h>=c.length&&n();const t=3*c[h++];o.push(s[t+0]),o.push(s[t+1]),o.push(s[t+2])}}}return{pts:Float32Array.from(o),offsetPt0:Uint32Array.from(a)}}if(n[0].includes("TRIANGLE_STRIPS")){const t=parseInt(n[1]);for(let n=0;n<t;n++){const t=e[i].trim();i++;const n=t.trim().split(/\s+/),r=parseInt(n[0])-2;let a=1;for(let e=0;e<r;e++)e%2?(l.push(parseInt(n[a+2])),l.push(parseInt(n[a+1])),l.push(parseInt(n[a]))):(l.push(parseInt(n[a])),l.push(parseInt(n[a+1])),l.push(parseInt(n[a+2]))),a+=1}}else{if(!n[0].includes("POLYGONS"))throw new Error("Unsupported ASCII VTK datatype "+n[0]);{const t=parseInt(n[1]);for(let n=0;n<t;n++){const t=e[i].trim();i++;const n=t.trim().split(/\s+/),r=parseInt(n[0])-2,a=parseInt(n[1]);let s=parseInt(n[2]);for(let e=0;e<r;e++){const t=parseInt(n[3+e]);l.push(a),l.push(s),l.push(t),s=t}}}}return{positions:s,indices:new Uint32Array(l)}}static async readLayer(e,i,n,r,a,s,o,l,c,h){void 0===e&&(e=""),void 0===r&&(r=.5),void 0===a&&(a="warm"),void 0===s&&(s="winter"),void 0===o&&(o=!1),void 0===l&&(l=null),void 0===c&&(c=null),void 0===h&&(h=0);const d={...De,colormapInvert:!1,colormapType:0,isTransparentBelowCalMin:!0,isAdditiveBlend:!1,colorbarVisible:!0,colormapLabel:null},u=/(?:\.([^.]+))?$/;let m=u.exec(e)[1];m=m.toUpperCase(),"GZ"===m&&(m=u.exec(e.slice(0,-3))[1],m=m.toUpperCase());const f=n.vertexCount/3;if(n.offsetPt0){const r=e.split("/");let a="Unknown";if(r.length>1){r.pop()&&(a=a.split(".").slice(0,-1).join("."))}if("TXT"===m){const e=n.offsetPt0.length-1,r=t.readTXT(i,e);if(r.length!==e)throw new Error(`TXT file has ${r.length} items, expected one per streamline (${e}).`);n.dps||(n.dps=[]);const s=r.reduce(((t,e)=>Math.min(t,e))),o=r.reduce(((t,e)=>Math.max(t,e)));return n.dps.push({id:a,vals:Float32Array.from(r.slice()),global_min:s,global_max:o,cal_min:s,cal_max:o}),d}if("NII"===m){const e=await t.readNII(i,n.pts,""),r=e.reduce(((t,e)=>Math.min(t,e))),s=e.reduce(((t,e)=>Math.max(t,e)));return n.dpv.push({id:a,vals:Float32Array.from(e.slice()),global_min:r,global_max:s,cal_min:r,cal_max:s}),d}if("TSF"!==m)throw new Error("readLayer for streamlines only supports TSF and TXT files.");const s=n.pts.length/3,o=t.readTSF(i,s);n.dpv||(n.dpv=[]);const l=o.reduce(((t,e)=>Math.min(t,e))),c=o.reduce(((t,e)=>Math.max(t,e)));return n.dpv.push({id:a,vals:Float32Array.from(o.slice()),global_min:l,global_max:c,cal_min:l,cal_max:c}),d}if(f<3)return void Q.error("n_vert < 3 in layer");if("MZ3"===m){const e=await t.readMZ3(i,f);d.values=e.scalars,"colormapLabel"in e&&(d.colormapLabel=e.colormapLabel)}else if("ANNOT"===m){const e=t.readANNOT(i,f,!0);e instanceof Uint32Array?d.values=e:(d.values=e.scalars,d.colormapLabel=e.colormapLabel)}else if("CRV"===m||"CURV"===m||"THICKNESS"===m||"AREA"===m)d.values=t.readCURV(i,f),d.isTransparentBelowCalMin=!1;else if("GII"===m){const e=await t.readGII(i,f);d.values=e.scalars,d.colormapLabel=e.colormapLabel}else if("MGH"===m||"MGZ"===m){const e=await t.readMGH(i,f,!0);"scalars"in e?(d.values=e.scalars,d.colormapLabel=e.colormapLabel):d.values=e}else if("NII"===m)d.values=await t.readNII(i,n.pts,n.anatomicalStructurePrimary);else if("SMP"===m)d.values=await t.readSMP(i,f);else if("STC"===m)d.values=t.readSTC(i,f);else{if(!t.isCurv(i))return Q.warn("Unknown layer overlay format "+e),d;d.values=t.readCURV(i,f),d.isTransparentBelowCalMin=!1}if(!d.values)return void Q.error("no values in layer");d.nFrame4D=d.values.length/f,d.frame4D=0,d.outlineBorder=h;let g=d.values[0],A=d.values[0];for(let t=0;t<d.values.length;
1t++)g=Math.min(g,d.values[t]),A=Math.max(A,d.values[t]);return d.global_min=g,d.global_max=A,d.cal_min=l||0,l||(d.cal_min=g),d.cal_max=c||0,c||(d.cal_max=A),d.cal_minNeg=NaN,d.cal_maxNeg=NaN,d.opacity=r,d.colormap=a,d.colormapNegative=s,d.useNegativeCmap=o,d}static async readSMP(t,e){const i=t.byteLength;let n=new DataView(t),r=n.getUint16(0,!0);if(r>5){const e=await ye.decompress(new Uint8Array(t));n=new DataView(e.buffer),r=n.getUint16(0,!0),t=e.buffer}r>5&&Q.error("Unsupported or invalid BrainVoyager SMP version "+r);const a=n.getUint32(2,!0);a!==e&&Q.error("SMP file has "+a+" vertices, background mesh has "+e);const s=n.getUint16(6,!0),o=new Float32Array(a*s),l=[];let c=9;function h(){const e=c;for(;c<i&&0!==n.getUint8(c);)c++;return c++,(new TextDecoder).decode(t.slice(e,c-1))}h();for(let d=0;d<s;d++){const e={};e.mapType=n.getUint32(c,!0),c+=4,r>=3&&3===e.mapType&&(e.nLags=n.getUint32(c,!0),c+=4,e.mnLag=n.getUint32(c,!0),c+=4,e.mxLag=n.getUint32(c,!0),c+=4,e.ccOverlay=n.getUint32(c,!0),c+=4),e.clusterSize=n.getUint32(c,!0),c+=4,e.clusterCheck=n.getUint8(c),c+=1,e.critThresh=n.getFloat32(c,!0),c+=4,e.maxThresh=n.getFloat32(c,!0),c+=4,r>=4&&(e.includeValuesGreaterThreshMax=n.getUint32(c,!0),c+=4),e.df1=n.getUint32(c,!0),c+=4,e.df2=n.getUint32(c,!0),c+=4,r>=5?(e.posNegFlag=n.getUint32(c,!0),c+=4):e.posNegFlag=3,e.cortexBonferroni=n.getUint32(c,!0),c+=4,e.posMinRGB=[0,0,0],e.posMaxRGB=[0,0,0],e.negMinRGB=[0,0,0],e.negMaxRGB=[0,0,0],r>=2&&(e.posMinRGB[0]=n.getUint8(c),c++,e.posMinRGB[1]=n.getUint8(c),c++,e.posMinRGB[2]=n.getUint8(c),c++,e.posMaxRGB[0]=n.getUint8(c),c++,e.posMaxRGB[1]=n.getUint8(c),c++,e.posMaxRGB[2]=n.getUint8(c),c++,r>=4&&(e.negMinRGB[0]=n.getUint8(c),c++,e.negMinRGB[1]=n.getUint8(c),c++,e.negMinRGB[2]=n.getUint8(c),c++,e.negMaxRGB[0]=n.getUint8(c),c++,e.negMaxRGB[1]=n.getUint8(c),c++,e.negMaxRGB[2]=n.getUint8(c),c++),e.enableSMPColor=n.getUint8(c),c++,r>=4&&(e.lut=h()),e.colorAlpha=n.getFloat32(c,!0),c+=4),e.name=h();const i=new Float32Array(t,c,a);o.set(i,d*a),c+=4*a,l.push(e)}return o}static readSTC(t,e){const i=new DataView(t),n=i.getInt32(8,!1);if(n!==e)throw new Error("Overlay has "+n+" vertices, expected "+e);let r=12+4*n;const a=i.getUint32(r,!1);r+=4;const s=new Float32Array(a*n);for(let o=0;o<a*n;o++)s[o]=i.getFloat32(r,!1),r+=4;return s}static isCurv(t){const e=new DataView(t),i=e.getUint8(0),n=e.getUint8(1),r=e.getUint8(2);return 255===i&&255===n&&255===r||(be.debug("Unable to recognize file type: does not appear to be FreeSurfer format."),!1)}static readCURV(t,e){const i=new DataView(t),n=i.getUint8(0),r=i.getUint8(1),a=i.getUint8(2),s=i.getUint32(3,!1),o=i.getUint32(11,!1);if(255===n&&255===r&&255===a||be.debug("Unable to recognize file type: does not appear to be FreeSurfer format."),e!==s)throw new Error("CURV file has different number of vertices ( "+s+")than mesh ("+e+")");if(t.byteLength<15+4*s*o)throw new Error("CURV file smaller than specified");const l=new Float32Array(o*s);let c=15;for(let m=0;m<o*s;m++)l[m]=i.getFloat32(c,!1),c+=4;let h=l[0],d=l[0];for(let m=0;m<l.length;m++)h=Math.min(h,l[m]),d=Math.max(d,l[m]);const u=1/(d-h);for(let m=0;m<l.length;m++)l[m]=1-(l[m]-h)*u;return l}static readANNOT(t,e,i){void 0===i&&(i=!1);const n=new DataView(t),r=n.getUint32(0,!1);if(e!==this.decimateLayerVertices(r,e))throw new Error("ANNOT file has different number of vertices than mesh");if(t.byteLength<4+8*r)throw new Error("ANNOT file smaller than specified");let a=0;const s=new Uint32Array(r);for(let A=0;A<r;A++){s[n.getUint32(a+=4,!1)]=n.getUint32(a+=4,!1)}if(!i)return s;let o=0;try{o=n.getInt32(a+=4,!1)}catch(g){return s}if(1!==o)return s;if(n.getInt32(a+=4,!1)>0)return s;const l=n.getInt32(a+=4,!1),c=n.getInt32(a+=4,!1);a+=c;const h=n.getInt32(a+=4,!1);if(h<1)return s;const d={R:Array(l).fill(0),G:Array(l).fill(0),B:Array(l).fill(0),A:Array(l).fill(0),I:Array(l).fill(0),labels:Array(l).fill("")};for(let A=0;A<h;A++){const t=n.getInt32(a+=4,!1),e=n.getInt32(a+=4,!1);a+=4;let i="";for(let l=0;l<e;l++){const t=n.getUint8(a++);if(0===t)break;i+=String.fromCharCode(t)}a-=4;const r=n.getInt32(a+=4,!1),s=n.getInt32(a+=4,!1),o=n.getInt32(a+=4,!1),c=n.getInt32(a+=4,!1);t<0||t>=l?Q.warn("annot entry out of range"):(d.R[t]=r,d.G[t]=s,d.B[t]=o,d.A[t]=c,d.I[t]=(c<<24)+(o<<16)+(s<<8)+r,d.labels[t]=i)}let u=!0;for(let A=0;A<l;A++)d.A[A]>0&&(u=!1);if(u)for(let A=0;A<l;A++)d.A[A]=255;const m=new Float32Array(r);m.fill(-1);let f=0;for(let A=0;A<e;A++){const t=s[A];for(let e=0;e<l;e++)if(d.I[e]===t){m[A]=e;break}m[A]<0&&(f++,m[A]=0)}f>0&&Q.error(`annot vertex colors do not match ${f} of ${r} vertices.`);for(let A=0;A<l;A++)d.I[A]=A;return{scalars:m,colormapLabel:ve.makeLabelLut(d)}}static readNV(t){const e=t.byteLength,i=new Uint8Array(t);let n=0;function r(){for(;n<e&&10===i[n];)n++;const r=n;for(;n<e&&10!==i[n];)n++;return n++,n-r<1?"":(new TextDecoder).decode(t.slice(r,n-1))}let a,s,o=0,l=0,c=0,h=0;for(;n<e;){const t=r();if(t.startsWith("#"))continue;const e=t.trim().split(/\s+/);if(o<1)o=parseInt(e[0]),a=new Float32Array(3*o);else if(c<3*o)a[c]=parseFloat(e[0]),a[c+1]=parseFloat(e[1]),a[c+2]=parseFloat(e[2]),c+=3;else if(l<1)l=parseInt(e[0]),s=new Uint32Array(3*l);else{if(h>=3*l)break;s[h+2]=parseInt(e[0])-1,s[h+1]=parseInt(e[1])-1,s[h+0]=parseInt(e[2])-1,h+=3}}return{positions:a,indices:s}}static readASC(t){const e=t.byteLength,i=new Uint8Array(t);let n=0;function r(){for(;n<e&&10===i[n];)n++;const r=n;for(;n<e&&10!==i[n];)n++;return n++,n-r<1?"":(new TextDecoder).decode(t.slice(r,n-1))}let a=r();
1a.startsWith("#!ascii")||Q.warn("Invalid ASC mesh"),a=r();let s=a.trim().split(/\s+/);const o=parseInt(s[0]),l=parseInt(s[1]),c=new Float32Array(3*o);let h=0;for(let u=0;u<o;u++)a=r(),s=a.trim().split(/\s+/),c[h]=parseFloat(s[0]),c[h+1]=parseFloat(s[1]),c[h+2]=parseFloat(s[2]),h+=3;const d=new Uint32Array(3*l);h=0;for(let u=0;u<l;u++)a=r(),s=a.trim().split(/\s+/),d[h]=parseInt(s[0]),d[h+1]=parseInt(s[1]),d[h+2]=parseInt(s[2]),h+=3;return{positions:c,indices:d}}static readVTK(e){const i=e.byteLength;if(i<20)throw new Error("File too small to be VTK: bytes = "+e.byteLength);const n=new Uint8Array(e);let r=0;function a(t){if(void 0===t&&(t=!0),t)for(;r<i&&10===n[r];)r++;const a=r;for(;r<i&&10!==n[r];)r++;return r++,r-a<1?"":(new TextDecoder).decode(e.slice(a,r-1))}let s=a();if(!s.startsWith("# vtk DataFile"))throw new Error("Invalid VTK mesh");if(s=a(!1),s=a(),s.startsWith("ASCII"))return t.readTxtVTK(e);if(!s.startsWith("BINARY"))throw new Error("Invalid VTK image, expected ASCII or BINARY "+s);if(s=a(),!s.includes("POLYDATA"))throw new Error("Only able to read VTK POLYDATA "+s);s=a(),s.includes("POINTS")&&(s.includes("double")||s.includes("float"))||Q.warn("Only able to read VTK float or double POINTS"+s);const o=s.includes("double");let l=s.trim().split(/\s+/);const c=3*parseInt(l[1]),h=new Float32Array(c),d=new DataView(e);if(o)for(let t=0;t<c;t++)h[t]=d.getFloat64(r,!1),r+=8;else for(let t=0;t<c;t++)h[t]=d.getFloat32(r,!1),r+=4;s=a(),l=s.trim().split(/\s+/);const u=[];if(l[0].includes("LINES")){const t=parseInt(l[1]),e=r;if(s=a(),s.startsWith("OFFSETS")){let e=!1;s.includes("int64")&&(e=!0);const i=new Uint32Array(t);if(e){let e=!1;for(let n=0;n<t;n++){let t=d.getInt32(r,!1);0!==t&&(e=!0),r+=4,t=d.getInt32(r,!1),r+=4,i[n]=t}e&&Q.warn("int32 overflow: JavaScript does not support int64")}else for(let n=0;n<t;n++){const t=d.getInt32(r,!1);r+=4,i[n]=t}return{pts:h,offsetPt0:i}}r=e;let i=0;const n=[],o=[];n.push(i);for(let a=0;a<t;a++){const t=d.getInt32(r,!1);r+=4,i+=t,n.push(i);for(let e=0;e<t;e++){const t=3*d.getInt32(r,!1);r+=4,o.push(h[t+0]),o.push(h[t+1]),o.push(h[t+2])}}return{pts:Float32Array.from(o),offsetPt0:Uint32Array.from(n)}}if(l[0].includes("TRIANGLE_STRIPS")){const t=parseInt(l[1]);for(let e=0;e<t;e++){const t=d.getInt32(r,!1)-2;r+=4;for(let e=0;e<t;e++)e%2?(u.push(d.getInt32(r+8,!1)),u.push(d.getInt32(r+4,!1)),u.push(d.getInt32(r,!1))):(u.push(d.getInt32(r,!1)),u.push(d.getInt32(r+4,!1)),u.push(d.getInt32(r+8,!1))),r+=4;r+=8}}else{if(!l[0].includes("POLYGONS"))throw new Error("Unsupported binary VTK datatype "+l[0]);{const t=parseInt(l[1]),e=r,i=a();if(i.startsWith("OFFSETS")){let e=i.includes("int64");const n=new Uint32Array(t);let s=!1;for(let i=0;i<t;i++)e&&(0!==d.getInt32(r,!1)&&(s=!0),r+=4),n[i]=d.getInt32(r,!1),r+=4;if(!Number.isSafeInteger(t)||t>=2147483648||s)throw new Error("values exceed 2GB limit");const o=a();if(!o.startsWith("CONNECTIVITY"))throw new Error("Expected CONNECTIVITY after OFFSETS");e=o.includes("int64");const l=n[t-1],c=new Uint32Array(l);for(let t=0;t<l;t++)e&&(r+=4),c[t]=d.getInt32(r,!1),r+=4;for(let i=0;i<t;i++){const t=0===i?0:n[i-1],e=n[i];for(let i=1;i<e-t-1;i++)u.push(c[t]),u.push(c[t+i]),u.push(c[t+i+1])}}else{r=e;for(let e=0;e<t;e++){const t=d.getInt32(r,!1)-2;if(0===e&&t>65535)throw new Error("Invalid VTK binary polygons using little-endian data (MRtrix)");r+=4;const i=d.getInt32(r,!1);r+=4;let n=d.getInt32(r,!1);r+=4;for(let e=0;e<t;e++){const t=d.getInt32(r,!1);r+=4,u.push(i,n,t),n=t}}}}}return{positions:h,indices:new Uint32Array(u)}}static readWRL(t){const e=new TextDecoder("utf-8").decode(t),i=/coord\s+Coordinate\s*\{\s*point\s*\[([\s\S]*?)\]/.exec(e),n=/coordIndex\s*\[([\s\S]*?)\]/.exec(e),r=/color\s+Color\s*\{\s*color\s*\[([\s\S]*?)\]/.exec(e);if(!i||!n)throw new Error("Invalid WRL file: Could not find vertices or indices.");const a=new Float32Array(i[1].trim().split(/[\s,]+/).map(Number));let s=null;if(r){s=new Float32Array(r[1].trim().split(/[\s,]+/).map(Number));const t=a.length/3;s.length!==3*t&&(console.warn(`Unexpected color count: expected ${3*t}, got ${s.length}`),s=null)}return{positions:a,indices:new Uint32Array(n[1].trim().split(/[\s,]+/).map(Number).filter((t=>-1!==t))),colors:s}}static readDFS(t){const e=new DataView(t),i=e.getUint32(0,!0),n=e.getUint16(4,!0);1599292996===i&&17740===n||Q.warn("Not a little-endian brainsuite DFS mesh");const r=e.getUint32(12,!0),a=e.getUint32(24,!0),s=e.getUint32(28,!0),o=e.getUint32(48,!0);let l=r;const c=new Uint32Array(t,l,3*a);l+=3*a*4;const h=new Float32Array(t,l,3*s);for(let u=0;u<3*s;u+=3){const t=h[u];h[u]=h[u+1],h[u+1]=t}let d;return o>=0&&(d=new Float32Array(t,o,3*s)),{positions:h,indices:c,colors:d}}static async readMZ3(t,e){if(void 0===e&&(e=0),t.byteLength<20)throw new Error("File too small to be mz3: bytes = "+t.byteLength);let i=new DataView(t),n=t,r=i.getUint16(0,!0);if(35615===r||8075===r){const e=await ye.decompress(new Uint8Array(t));i=new DataView(e.buffer),r=i.getUint16(0,!0),n=e.buffer}const a=i.getUint16(2,!0),s=i.getUint32(4,!0);let o=i.getUint32(8,!0);const l=i.getUint32(12,!0);if(be.debug("MZ3 magic %d attr %d face %d vert %d skip %d",r,a,s,o,l),23117!==r)throw new Error("Invalid MZ3 file");const c=!!(1&a),h=!!(2&a),d=!!(4&a);let u=!!(8&a);const m=!!(16&a),f=!!(32&a),g=!!(64&a);if(be.debug(`isFace=${c} isVert=${h} isRGBA=${d} isSCALAR=${u} isDOUBLE=${m} isAOMAP=${f} isLOOKUP=${g}`),a>127)throw new Error("Unsupported future version of MZ3 file");let A=4;m&&(A=8);let p=0;if(e>0&&!c&&s<1&&!d&&(u=!0),u){const t=e||o,i=16+l+(c?12*s:0)+(h?12*t:0)+(d?4*t:0),r=Math.floor((n.byteLength-i)/A);o!==e&&r%e==0&&(o=e),p=Math.floor(r/o),p<1&&(Q.warn("Corrupt MZ3: file reports NSCALAR but not enough bytes"),u=!1)}if(o<3&&e<3)throw new Error("Not a mesh MZ3 file (maybe scalar)");e>0&&e!==o&&Q.warn("Layer has "+o+"vertices, but background mesh has "+e);let v=16+l;const x=new DataView(n);let w=null;if(c){w=new Uint32Array(3*s);for(let t=0;t<3*s;t++)w[t]=x.getUint32(v,!0),v+=4}let y=null;if(h){y=new Float32Array(3*o);for(let t=0;t<3*o;t++)y[t]=x.getFloat32(v,!0),v+=4}let b=null;if(d){b=new Float32Array(3*o);for(let t=0;t<o;t++){for(let e=0;e<3;e++)b[3*t+e]=x.getUint8(v++)/255;v++}}let C=new Float32Array;
1if(u&&p>0)if(m){const t=new Float64Array(p*o);for(let e=0;e<p*o;e++)t[e]=x.getFloat64(v,!0),v+=8;C=Float32Array.from(t)}else{C=new Float32Array(p*o);for(let t=0;t<p*o;t++)C[t]=x.getFloat32(v,!0),v+=4}if(e>0&&g&&u){const t=new TextDecoder("utf-8"),e=new Uint8Array(n,16,l),i=t.decode(e),r=JSON.parse(i);return{scalars:C,colormapLabel:ve.makeLabelLut(r)}}if(e>0&&d&&u){let t=C[0];for(let i=0;i<o;i++)t=Math.max(t,C[i]);const e={R:[],G:[],B:[],A:[],I:[],labels:[]};for(let i=0;i<=t;i++)for(let t=0;t<o;t++)if(i===C[t]){const n=3*t;e.I.push(i),e.R.push(255*b[n]),e.G.push(255*b[n+1]),e.B.push(255*b[n+2]),e.A.push(255),e.labels.push(`${i}`);break}return{scalars:C,colormapLabel:ve.makeLabelLut(e)}}return e>0?{scalars:C}:{positions:y,indices:w,scalars:C,colors:b}}static readPLY(t){const e=t.byteLength,i=new Uint8Array(t);let n=0;function r(){for(;n<e&&10===i[n];)n++;const r=n;for(;n<e&&10!==i[n];)n++;return n++,n-r<1?"":(new TextDecoder).decode(t.slice(r,n-1))}let a=r();if(!a.startsWith("ply"))throw new Error("Not a valid PLY file");a=r();const s=a.includes("ascii");function o(t){if("char"===t||"uchar"===t||"int8"===t||"uint8"===t)return 1;if("short"===t||"ushort"===t||"int16"===t||"uint16"===t)return 2;if("int"===t||"uint"===t||"int32"===t||"uint32"===t||"float"===t||"float32"===t)return 4;if("double"===t)return 8;throw new Error("Unknown data type: "+t)}const l=a.includes("binary_little_endian");let c=0,h=!1,d=0,u=0,m=0,f=0,g=0,A=0,p=0;const v=[];let x=0,w=-1,y=-1,b=-1,C=!1;for(;n<e&&!a.startsWith("end_header");){if(a=r(),a.startsWith("comment"))continue;let t=a.split(/\s/);if(a.startsWith("element vertex"))for(c=parseInt(t[t.length-1]),a=r(),t=a.split(/\s/),x=0,v.length=0;a.startsWith("property");){const e=t[1],i=t[2];v.push(i),"red"===i?(w=x,C=!0):"green"===i?(y=x,C=!0):"blue"===i&&(b=x,C=!0),"x"===i&&e.startsWith("double")?h=!0:"x"!==i||e.startsWith("float")||Q.error("Error: expect ply xyz to be float or double: "+a);const n=o(e);d+=n,x+=n,a=r(),t=a.split(/\s/)}if(a.startsWith("element face"))for(p=parseInt(t[t.length-1]),a=r(),t=a.split(/\s/);a.startsWith("property");){if("list"===t[1])m=o(t[2]),f=o(t[3]),u+=m+3*f;else{const e=o(t[1]);u+=e,0===f&&(g+=e,A++)}a=r(),t=a.split(/\s/)}}if(s){p<1&&Q.error(`Malformed ply format: faces ${p} `);const t=new Float32Array(3*c);let e;const i=v.indexOf("x"),n=v.indexOf("y"),s=v.indexOf("z"),o=v.indexOf("red"),l=v.indexOf("green"),h=v.indexOf("blue");-1!==o&&-1!==l&&-1!==h&&(e=new Float32Array(3*c),C=!0);let d=0;for(let g=0;g<c;g++){a=r();const c=a.split(/\s/),u=i>=0?parseFloat(c[i]):parseFloat(c[0]),m=n>=0?parseFloat(c[n]):parseFloat(c[1]),f=s>=0?parseFloat(c[s]):parseFloat(c[2]);if(t[d]=u,t[d+1]=m,t[d+2]=f,C&&e){const t=o>=0?parseInt(c[o]):0,i=l>=0?parseInt(c[l]):0,n=h>=0?parseInt(c[h]):0,r=3*g;e[r]=t/255,e[r+1]=i/255,e[r+2]=n/255}d+=3}let u=new Uint32Array(3*p),m=0;for(let c=0;c<p;c++){a=r();const t=a.split(/\s/),e=parseInt(t[A])-2;if(e<1)break;if(m+3*e>u.length){const t=new Uint32Array(u.length+u.length);t.set(u),u=t.slice()}const i=parseInt(t[A+1]);let n=parseInt(t[A+2]);for(let r=0;r<e;r++){const e=parseInt(t[A+3+r]);u[m+0]=i,u[m+1]=n,u[m+2]=e,n=e,m+=3}}u.length!==m&&(u=u.slice(0,m));const f={positions:t,indices:u};return C&&(f.colors=void 0!==e?e:void 0),f}(d<12||m<1||f<1||p<1)&&Q.warn(`Malformed ply format: stride ${d} count ${m} iBytes ${f} iStrideBytes ${u} iPadBytes ${g} faces ${p}`);const M=new DataView(t);let D,T;if(C&&(T=new Float32Array(3*c)),n%4==0&&12===d&&l)D=new Float32Array(t,n,3*c),n+=c*d;else{D=new Float32Array(3*c);let t=0;for(let e=0;e<c;e++){if(h?(D[t]=M.getFloat64(n,l),D[t+1]=M.getFloat64(n+8,l),D[t+2]=M.getFloat64(n+16,l)):(D[t]=M.getFloat32(n,l),D[t+1]=M.getFloat32(n+4,l),D[t+2]=M.getFloat32(n+8,l)),C&&T){const t=n,i=w>=0?M.getUint8(t+w):0,r=y>=0?M.getUint8(t+y):0,a=b>=0?M.getUint8(t+b):0,s=3*e;T[s]=i/255,T[s+1]=r/255,T[s+2]=a/255}t+=3,n+=d}}const I=new Uint32Array(3*p);let S=!0,E=0;if(1===m&&4===f&&13===u)for(let B=0;B<p;B++){const t=M.getUint8(n);n+=m,3!==t&&(S=!1),I[E]=M.getUint32(n,l),n+=4,I[E+1]=M.getUint32(n,l),n+=4,I[E+2]=M.getUint32(n,l),n+=4,E+=3}else{let t=n;for(let e=0;e<p;e++){n=t+g;let e=0;
11===m?e=M.getUint8(n):2===m?e=M.getUint16(n,l):4===m&&(e=M.getUint32(n,l)),n+=m,3!==e&&(S=!1);for(let t=0;t<3;t++)1===f?I[E]=M.getUint8(n):2===f?I[E]=M.getUint16(n,l):4===f&&(I[E]=M.getUint32(n,l)),E++,n+=f;t+=u}}S||Q.warn("Only able to read PLY meshes limited to triangles.");const F={positions:D,indices:I};return C&&void 0!==T&&(F.colors=T),F}static readICO(t){const e=new TextDecoder("utf-8").decode(t).split("\n");let i=e[0].trim().split(/\s+/);i.length>1&&Q.warn("This is not a valid FreeSurfer ICO/TRI mesh.");const n=parseInt(i[0]),r=new Float32Array(3*n);let a=1;for(let l=0;l<n;l++){const t=e[a].trim().split(/\s+/);a++;let i=parseInt(t[0])-1;const s=parseFloat(t[1]),o=parseFloat(t[2]),l=parseFloat(t[3]);if(i<0||i>=n){Q.error("ICO vertices corrupted");break}i*=3,r[i]=s,r[i+1]=o,r[i+2]=l}i=e[a].trim().split(/\s+/),a++;const s=parseInt(i[0]),o=new Uint32Array(3*s);for(let l=0;l<s;l++){const t=e[a].trim().split(/\s+/);a++;let i=parseInt(t[0])-1;const n=parseInt(t[1])-1,r=parseInt(t[2])-1,l=parseInt(t[3])-1;if(i<0||i>=s){Q.error("ICO indices corrupted");break}i*=3,o[i]=n,o[i+1]=r,o[i+2]=l}for(let l=0;l<o.length;l+=3){const t=o[l];o[l]=o[l+1],o[l+1]=t}return{positions:r,indices:o}}static readGEO(t,e){void 0===e&&(e=!1);const i=new TextDecoder("utf-8").decode(t).split("\n"),n=i[0].trim().split(/\s+/),r=parseInt(n[0]);let a=parseInt(n[1]),s=parseInt(n[2]);const o=parseInt(n[3]);(r>1||o!==3*s)&&Q.warn("Multi-part BYU/GEO header or not a triangular mesh.");const l=[];a*=3;let c=0,h=2;for(;c<a;){const t=i[h].trim().split(/\s+/);h++;for(let e=0;e<t.length&&(l.push(parseFloat(t[e])),c++,!(c>=a));e++);}const d=[];s*=3;let u=0;for(;u<s;){const t=i[h].trim().split(/\s+/);h++;for(let e=0;e<t.length&&(d.push(Math.abs(parseInt(t[e]))-1),u++,!(u>=s));e++);}if(e)for(let m=0;m<d.length;m+=3){const t=d[m];d[m]=d[m+1],d[m+1]=t}return{positions:new Float32Array(l),indices:new Uint32Array(d)}}static readOFF(t){const e=new TextDecoder("utf-8").decode(t).split("\n"),i=[],n=[];let r=0;e[r].includes("OFF")?r++:Q.warn("File does not start with OFF");let a=e[r].trim().split(/\s+/);const s=parseInt(a[0]),o=parseInt(a[1]);r++;for(let l=0;l<s;l++){a=e[r].trim().split(/\s+/),i.push(parseFloat(a[0])),i.push(parseFloat(a[1])),i.push(parseFloat(a[2])),r++}for(let l=0;l<o;l++){a=e[r].trim().split(/\s+/);3!==parseInt(a[0])&&Q.warn("Only able to read OFF files with triangular meshes"),n.push(parseInt(a[1])),n.push(parseInt(a[2])),n.push(parseInt(a[3])),r++}return{positions:new Float32Array(i),indices:new Uint32Array(n)}}static readOBJMNI(t){const e=new TextDecoder("utf-8").decode(t).trim().split(/\s*,\s*|\s+/);(e.length<1||"P"!==e[0])&&Q.warn("This is not a valid MNI OBJ mesh.");let i=6;const n=parseInt(e[i++]),r=3*n,a=new Float32Array(r);for(let d=0;d<r;d++)a[d]=parseFloat(e[i++]);i+=r;const s=parseInt(e[i++]),o=parseInt(e[i++]);(s<1||o<0||o>2)&&Q.warn("This is not a valid MNI OBJ mesh.");let l=1;1===o?l=s:1===o&&(l=n),i+=4*l,i+=s;const c=3*s,h=new Uint32Array(c);for(let d=0;d<c;d++)h[d]=parseInt(e[i++]);return{positions:a,indices:h}}static async readOBJ(t){const e=new Uint8Array(t,0,2);31===e[0]&&139===e[1]&&(t=await ye.decompressToBuffer(new Uint8Array(t)));const i=new TextDecoder("utf-8").decode(t);if("P"===i[0])return this.readOBJMNI(t);const n=i.split("\n"),r=n.length,a=[],s=[];for(let d=0;d<r;d++){const t=n[d];if("v"===t[0]&&" "===t[1]){const e=t.trim().split(/\s+/);a.push(parseFloat(e[1])),a.push(parseFloat(e[2])),a.push(parseFloat(e[3]))}if("f"===t[0]){const e=t.trim().split(/\s+/),i=e.length-3;if(i<1)break;let n=e[1].split("/");const r=parseInt(n[0])-1;n=e[2].split("/");let a=parseInt(n[0])-1;for(let t=0;t<i;t++){n=e[3+t].split("/");const i=parseInt(n[0])-1;s.push(r),s.push(a),s.push(i),a=i}}}const o=new Float32Array(a),l=new Uint32Array(s);let c=l[0],h=l[0];for(let d=1;d<l.length;d++)l[d]<c&&(c=l[d]),l[d]>h&&(h=l[d]);if(h-c+1>o.length/3)throw new Error("Not a valid OBJ file");for(let d=0;d<l.length;d++)l[d]-=c;return{positions:o,indices:l}}static readFreeSurfer(e){const i=new Uint8Array(e);if(35===i[0]&&33===i[1]&&97===i[2])return t.readASC(e);const n=new DataView(e),r=n.getUint32(0,!1),a=n.getUint32(4,!1);
14294966883===r&&1919246708===a||be.debug("Unable to recognize file type: does not appear to be FreeSurfer format.");let s=0;for(;10!==n.getUint8(s);)s++;s+=2;let o=n.getUint32(s,!1);s+=4;let l=n.getUint32(s,!1);s+=4,o*=3;const c=new Float32Array(o);for(let t=0;t<o;t++)c[t]=n.getFloat32(s,!1),s+=4;l*=3;const h=new Uint32Array(l);for(let t=0;t<l;t++)h[t]=n.getUint32(s,!1),s+=4;const d=n.getUint32(s,!1);s+=4;let u=20===d;if(!u){const t=n.getUint32(s,!1);s+=4;const e=n.getUint32(s,!1);s+=4,u=2===d&&0===t&&20===e}if(u){const t=(new TextDecoder).decode(e.slice(s)).trim().split("\n");for(let e=0;e<t.length;e++){if(!t[e].startsWith("cras"))continue;const i=t[e].split("=")[1].trim().split(" ").map(Number),n=Math.floor(c.length/3);let r=0;for(let t=0;t<n;t++)c[r]+=i[0],r++,c[r]+=i[1],r++,c[r]+=i[2],r++}}else Q.warn("Unknown FreeSurfer Mesh extension code.");return{positions:c,indices:h}}static async readSRF(e){const i=new Uint8Array(e);if(35===i[0]&&33===i[1]&&97===i[2])return t.readASC(e);if(31===i[0]&&139===i[1]){e=(await ye.decompress(new Uint8Array(e))).buffer}const n=new DataView(e),r=n.getFloat32(0,!0),a=n.getUint32(8,!0),s=n.getUint32(12,!0),o=n.getFloat32(16,!0),l=n.getFloat32(20,!0),c=n.getFloat32(24,!0),h=new Float32Array(3*a);let d=28,u=1;for(let t=0;t<a;t++)h[u]=-n.getFloat32(d,!0)+o,u+=3,d+=4;u=2;for(let t=0;t<a;t++)h[u]=-n.getFloat32(d,!0)+l,u+=3,d+=4;u=0;for(let t=0;t<a;t++)h[u]=-n.getFloat32(d,!0)+c,u+=3,d+=4;d=28+24*a;const m=n.getFloat32(d,!0),f=n.getFloat32(d+4,!0),g=n.getFloat32(d+8,!0),A=n.getFloat32(d+16,!0),p=n.getFloat32(d+20,!0),v=n.getFloat32(d+24,!0);d+=32;const x=new Float32Array(3*a),w=new Uint32Array(e,d,a);u=0;for(let t=0;t<a;t++){const e=w[t];e>1056964608&&(x[u+0]=(e>>16&255)/255,x[u+1]=(e>>8&255)/255,x[u+2]=(255&e)/255),0===e&&(x[u+0]=m,x[u+1]=f,x[u+2]=g),1===e&&(x[u+0]=A,x[u+1]=p,x[u+2]=v),u+=3}d+=4*a;for(let t=0;t<a;t++){d+=4+4*n.getUint32(d,!0)}const y=new Uint32Array(3*s);for(let t=0;t<3*s;t++)y[t]=n.getInt32(d,!0),d+=4;return 4!==r&&Q.warn("Not valid SRF"),{positions:h,indices:y,colors:x}}static readTxtSTL(t){const e=new TextDecoder("utf-8").decode(t).split("\n");if(!e[0].startsWith("solid"))throw new Error("Not a valid STL file");const i=[];for(let s=1;s<e.length;s++){if(!e[s].includes("vertex"))continue;const t=e[s].trim().split(/\s+/);for(let e=1;e<t.length;e++)i.push(parseFloat(t[e]))}const n=Math.floor(i.length/3);if(3*n!==i.length)throw new Error("Unable to parse ASCII STL file.");const r=new Float32Array(i),a=new Uint32Array(n);for(let s=0;s<n;s++)a[s]=s;return{positions:r,indices:a}}static readSTL(e){if(e.byteLength<134)throw new Error("File too small to be STL: bytes = "+e.byteLength);const i=new DataView(e);if(1768714099===i.getUint32(0,!0))return t.readTxtSTL(e);const n=i.getUint32(80,!0),r=3*n;if(e.byteLength<84+50*n)throw new Error("STL file too small to store triangles = "+n);const a=new Uint32Array(r),s=new Float32Array(3*r);let o=96,l=0;for(let t=0;t<n;t++){for(let t=0;t<9;t++)s[l]=i.getFloat32(o,!0),l+=1,o+=4;o+=14}for(let t=0;t<r;t++)a[t]=t;return{positions:s,indices:a}}static decimateLayerVertices(t,e){if(t%e==0)return t;const i=Math.round(Math.log((t-2)/10)/Math.log(4)),n=Math.round(Math.log((e-2)/10)/Math.log(4)),r=10*Math.pow(4,i)+2,a=10*Math.pow(4,n)+2;return r!==t||a!==e?t:e}static async readNII2(t,e,i){void 0===e&&(e=0),void 0===i&&(i="");let n=new Float32Array;const r=t.byteLength;let a=!0;const s=new DataView(t);let o=s.getUint16(0,a);if(469893120===o&&(a=!1,o=s.getUint16(0,a)),540!==o)throw new Error("Not a valid NIfTI-2 dataset");const l=Number(s.getBigInt64(168,a)),c=s.getFloat64(176,a),h=s.getFloat64(184,a);1===c&&0===h||Q.warn("ignoring scale slope and intercept");const d=s.getUint32(504,a),u=s.getUint16(12,a);if(2!==u&&4!==u&&8!==u&&16!==u)throw new Error("Unsupported NIfTI datatype "+u);let m=1;const f=[1,1,1,1,1,1,1,1];for(let g=1;g<8;g++)f[g]=Math.max(Number(s.getBigInt64(16+8*g,a)),1),m*=f[g];if(d>=3e3&&d<=3099&&l>580){let n=function(){for(;x<r&&10===p[x];)x++;const e=x;for(;x<r&&10!==p[x];)x++;return x++,x-e<1?"":(new TextDecoder).decode(t.slice(e,x-1)).trim()},o=function(){let t=n();if(!t.startsWith("<")||t.endsWith(">"))return t;for(;x<r&&!t.endsWith(">");)t+=n();return t},c=function(t,e){void 0===e&&(e=!1);const i=v.indexOf(t);if(i<0)return 1;const n=v.indexOf('"',i)+1,r=v.indexOf('"',n),a=v.slice(n,r);return e?a:parseInt(a)},h=0,d=0,m=0,g="",A=new Uint32Array;const p=new Uint8Array(t);let v,x=552;
1const w=f[5],y=new Float32Array(e*w);for(;x<r&&(v=o(),!v.includes("</CIFTI>"));)if(v.includes("<BrainModel")){const t=c("SurfaceNumberOfVertices="),n=c("BrainStructure=",!0).toUpperCase();if(t%e!=0)continue;let r=!1;if(i.includes("CORTEX")&&n.includes("CORTEX")&&(r=!0),!r)continue;if(r=!1,i.includes("LEFT")&&n.includes("LEFT")&&(r=!0),i.includes("RIGHT")&&n.includes("RIGHT")&&(r=!0),!r)continue;if(m=t,h=c("IndexOffset="),d=c("IndexCount="),g=n,v.includes("<VertexIndices>")||(v=o()),!v.startsWith("<VertexIndices>")||!v.endsWith("</VertexIndices>"))return Q.warn("Unable to find CIfTI <VertexIndices>"),y;v=v.slice(15,-16);const a=v.trim().split(/\s+/);a.length<d&&Q.error("Error parsing VertexIndices"),A=new Uint32Array(d);for(let e=0;e<d;e++)A[e]=parseInt(a[e])}if(0===m||0===A.length)return Q.warn("Unable to find CIfTI structure that matches the mesh."),y;if(16!==u)return Q.warn("Only able to read float32 CIfTI (only known datatype)."),y;const b=new Float32Array(d*w),C=l+w*h*4;for(let t=0;t<d*w;t++)b[t]=s.getFloat32(C+4*t,a);let M=0;for(let t=0;t<d;t++)for(let i=0;i<w;i++)y[A[t]+i*e]=b[M],M++;return Q.debug("CIfTI diagnostics",m,g,h,d,h,i),y}if(m=this.decimateLayerVertices(m,e),m%e!=0)throw new Error("Vertices in layer ("+m+") is not a multiple of number of vertices ("+e+")");if(a)16===u?n=new Float32Array(t,l,m):8===u?n=new Int32Array(t,l,m):4===u&&(n=new Int16Array(t,l,m));else if(16===u){n=new Float32Array(m);for(let t=0;t<m;t++)n[t]=s.getFloat32(l+4*t,a)}else if(8===u){n=new Int32Array(m);for(let t=0;t<m;t++)n[t]=s.getInt32(l+4*t,a)}else if(4===u){n=new Int16Array(m);for(let t=0;t<m;t++)n[t]=s.getInt16(l+2*t,a)}return 2===u&&(n=new Uint8Array(t,l,m)),n}static async readNII(e,i,n){void 0===n&&(n="");const r=i.length/3;let s=new Float32Array,o=!0,l=new DataView(e),c=l.getUint16(0,o);if(540===c||469893120===c)return t.readNII2(e,r,n);if(23553===c&&(o=!1,c=l.getUint16(0,o)),348!==c){const i=await ye.decompress(new Uint8Array(e));if(l=new DataView(i.buffer),e=i.buffer,c=l.getUint16(0,o),540===c||469893120===c)return t.readNII2(e,r,n);23553===c&&(o=!1,c=l.getUint16(0,o))}348!==c&&Q.error("Not a valid NIfTI image.");const h=l.getFloat32(108,o),d=l.getFloat32(112,o),u=l.getFloat32(116,o),m=l.getUint16(252,o),f=l.getUint16(254,o),g=l.getUint16(70,o);if(2!==g&&4!==g&&8!==g&&16!==g)throw new Error("Unsupported NIfTI datatype "+g);const A=a.vt();for(let t=0;t<12;t++)A[t]=l.getFloat32(280+4*t,o);let p=1;const v=new Array(8);for(let t=0;t<8;t++)v[t]=l.getUint16(40+2*t,o),t<1||(p*=v[t]||1);let x=!1,w=this.decimateLayerVertices(p,r);if(w%r!=0){if(!(v[0]>=3&&v[1]>1&&v[2]>1&&v[3]>1))throw new Error("Voxels in layer ("+p+") is not a multiple of number of vertices ("+r+")");x=!0,w=v[1]*v[2]*v[3]}if(p=w,o)16===g?s=new Float32Array(e,h,p):8===g?s=new Int32Array(e,h,p):4===g&&(s=new Int16Array(e,h,p));else if(16===g){s=new Float32Array(p);for(let t=0;t<p;t++)s[t]=l.getFloat32(h+4*t,o)}else if(8===g){s=new Int32Array(p);for(let t=0;t<p;t++)s[t]=l.getInt32(h+4*t,o)}else if(4===g){s=new Int16Array(p);for(let t=0;t<p;t++)s[t]=l.getInt16(h+2*t,o)}if(2===g&&(s=new Uint8Array(e,h,p)),Number.isFinite(d)&&Number.isFinite(u)&&0!==d&&(1!==d||0!==u)){const t=new Float32Array(p);for(let e=0;e<p;e++)t[e]=s[e]*d+u;s=t}let y=s[0],b=y;for(let t=0;t<p;t++)isNaN(s[t])&&(s[t]=0),y=Math.min(y,s[t]),b=Math.max(b,s[t]);if(Q.debug(`Layer Range ${y}..${b} slope ${d} inter ${u}`),x){let t=function(t,e){const i=[0,0,0];return i[0]=e[0]*t[0]+e[1]*t[1]+e[2]*t[2]+e[3],i[1]=e[4]*t[0]+e[5]*t[1]+e[6]*t[2]+e[7],i[2]=e[8]*t[0]+e[9]*t[1]+e[10]*t[2]+e[11],i};const e=new Float32Array(r);Q.warn("Sampling voxel intensities at mesh vertices (assumes precise alignment)."),(m>f||f<=0)&&Q.warn(`Requires valid sform (sform_code = ${f})`);const n=a.vt();a.B8(n,A);const o=v[1],l=v[2],c=v[3],h=o*l;let d=0,u=0,g=0;for(;u<r;){const r=t([i[d],i[d+1],i[d+2]],n);d+=3,u+=1;const a=Math.floor(r[0]),m=Math.floor(r[1]),f=Math.floor(r[2]),A=Math.ceil(r[0]),p=Math.ceil(r[1]),v=Math.ceil(r[2]);if(a<0||A>=o||m<0||p>=l||f<0||v>=c)continue;const x=a+m*o+f*h,w=new Float32Array(8);w[0]=s[x],w[1]=s[x+1],w[2]=s[x+o],w[3]=s[x+o+1],w[4]=s[x+h],w[5]=s[x+h+1],w[6]=s[x+h+o],w[7]=s[x+h+o+1];let y=w[0],b=y;for(let t=1;t<8;t++)y=Math.max(y,w[t]),b=Math.min(b,w[t]);Math.abs(b)>y&&(y=b),e[u-1]=y,g++}const p=g/r;p<.1&&Q.warn(`${g} of ${r} vertices in range (${(100*p).toFixed(1)}%)`),s=e}return s}static async readMGH(t,e,i){void 0===e&&(e=0),void 0===i&&(i=!1);let n=new DataView(t),r=t;if(31===n.getUint8(0)&&139===n.getUint8(1)){const e=await ye.decompress(new Uint8Array(t));r=new ArrayBuffer(e.byteLength),new Uint8Array(r).set(new Uint8Array(e)),n=new DataView(e.buffer)}const a=n.getInt32(0,!1),s=Math.max(1,n.getInt32(4,!1)),o=Math.max(1,n.getInt32(8,!1)),l=Math.max(1,n.getInt32(12,!1)),c=Math.max(1,n.getInt32(16,!1)),h=n.getInt32(20,!1);let d=284;const u=!1;(1!==a||h<0||h>4)&&Q.warn("Not a valid MGH file");let m=s*o*l*c,f=[];if(m=this.decimateLayerVertices(m,e),m%e!=0)return Q.warn("Vertices in layer ("+m+") is not a multiple of number of vertices ("+e+")"),f;if(3===h){f=new Float32Array(m);for(let t=0;t<m;t++)f[t]=n.getFloat32(d+4*t,u)}else if(1===h){f=new Int32Array(m);for(let t=0;t<m;t++)f[t]=n.getInt32(d+4*t,u)}else if(4===h){f=new Int16Array(m);for(let t=0;t<m;t++)f[t]=n.getInt16(d+2*t,u)}else 0===h&&(f=new Uint8Array(t,d,m));if(!i)return f;let g=4;4===h&&(g=2),0===h&&(g=1),d+=g*m,d+=16;const A=r.byteLength;let p;for(;d<A-8;){let t=0;switch(n.getInt32(d+=4,u)){case 30:t=n.getInt32(d+=4,u)-1;break;case 20:case 2:t=0;break;case 1:t=0;{let t=n.getInt32(d+=4,u);if(t>0)return Q.warn("unsupported CTABreadFromBinaryV1"),f;if(t=-t,2!==t)return Q.warn("CTABreadFromBinary: unknown version"),f;const e=n.getInt32(d+=4,u);if(e<0)return Q.warn("CTABreadFromBinaryV2: nentries was ",e),f;const i=n.getInt32(d+=4,u);d+=i;const r=n.getInt32(d+=4,u);if(r<0)return f;const a={R:[],G:[],B:[],A:[],I:[],labels:[]};for(let s=0;s<r;s++){const t=n.getInt32(d+=4,u),e=n.getInt32(d+=4,u);let i=d+4,r="";for(let a=0;a<e;a++){const t=n.getUint8(i++);if(0===t)break;r+=String.fromCharCode(t)}d+=e;const s=n.getInt32(d+=4,u),o=n.getInt32(d+=4,u),l=n.getInt32(d+=4,u),c=255-n.getInt32(d+=4,u);a.I.push(t),a.R.push(s),a.G.push(o),a.B.push(l),a.A.push(c),a.labels.push(r)}
1p=ve.makeLabelLut(a)}break;default:t=n.getInt32(d+=8,u)}d+=t}return{scalars:f,colormapLabel:p}}static readX3D(t){const e=t.byteLength;if(e<20)throw new Error("File too small to be X3D: bytes = "+e);const i=new Uint8Array(t);let s=0;function o(){for(;s<e&&60!==i[s];)s++;const n=s;for(;s<e&&62!==i[s];)s++;const r=s;return(new TextDecoder).decode(t.slice(n,r+1)).trim()}let l=o();function c(t){const e=l.indexOf(t+"=");if(e<0)return"";const i=l[e+t.length+1],n=l.indexOf(i,e)+1,r=l.indexOf(i,n);return l.slice(n,r)}function h(t){const e=l.indexOf(t+"=");if(e<0)return 1;const i=l[e+t.length+1],n=l.indexOf(i,e)+1,r=l.indexOf(i,n);let a=l.slice(n,r).trim();a=a.replace(/,\s*$/,"");const s=a.trim().split(/\s*,\s*|\s+/);if(s.length<2)return parseFloat(a);let o=new Array(s.length),c=0;for(let l=0;l<s.length;l++){const t=parseFloat(s[l]);isFinite(t)&&(o[c]=t,c++)}return o=o.slice(0,c),o}l.includes("xml version")||Q.warn("Not a X3D image");let d=[],u=[],m=[],f=[],g=[0,0,0,0],A=[0,0,0,0],p=[255,255,255,255],v=[255,255,255,255];const x={};function w(){if(!l.endsWith("/>"))if(l.startsWith("<Appearance>"))for(;s<e&&!l.endsWith("</Appearance>");)l+=o();else for(;s<e&&!l.endsWith("/>");)l+=o();const t=c("USE");if(t.length>1)return void(t in x?p=x[t]:Q.warn("Unable to find DEF for "+t));const i=h("diffuseColor");if(i.length<3)return;p[0]=Math.round(255*i[0]),p[1]=Math.round(255*i[1]),p[2]=Math.round(255*i[2]);const n=c("DEF");n.length<1||(x[n]=p)}for(;s<e;)if(l=o(),p=v.slice(),l.startsWith("<Transform")&&(g=h("translation"),A=h("rotation")),l.startsWith("<Appearance")&&(w(),v=p.slice()),l.startsWith("<Shape")){let t=1,i=1,c=[],v=[];for(;s<e&&(l=o(),l.startsWith("<Appearance")&&w(),!l.startsWith("</Shape"));){if(l.startsWith("<Sphere")&&(t=h("radius"),i=-1),l.startsWith("<Cylinder")&&(t=h("radius"),i=h("height")),l.startsWith("<IndexedFaceSet")&&(i=-2,c=h("coordIndex")),l.startsWith("<IndexedTriangleSet")&&(i=-7,c=h("index")),l.startsWith("<IndexedTriangleStripSet")&&(i=-3,c=h("index")),l.startsWith("<Coordinate")){v=h("point");const t=v.length%3;0!==t&&(v=v.slice(0,-t))}l.startsWith("<Color")&&(f=h("color")),l.startsWith("<Box")&&(i=-4,Q.warn("Unsupported x3d shape: Box")),l.startsWith("<Cone")&&(i=-5,Q.warn("Unsupported x3d shape: Cone")),l.startsWith("<ElevationGrid")&&(i=-6,Q.warn("Unsupported x3d shape: ElevationGrid"))}if(i<-3&&-7!==i);else if(i<-1){if(c.length<1||v.length<3||void 0===v.length){Q.warn("Indexed mesh must specify indices and points");break}const t=Math.floor(d.length/3);let e=2;if(-7===i)u=[...u,...c];else if(-2===i){let i=0;for(;e<c.length;)c[e]>=0?(u.push(c[i]+t),u.push(c[e-1]+t),u.push(c[e-0]+t),e+=1):(e+=3,i=e-2)}else for(;e<c.length;)c[e]>=0?(u.push(c[e-2]+t),u.push(c[e-1]+t),u.push(c[e-0]+t),e+=1):e+=3;d=[...d,...v];const n=Math.floor(v.length/3),r=Array(n).fill(p).flat();if(f.length===3*n){let t=0,e=0;for(let i=0;i<n;i++){for(let i=0;i<3;i++)r[e]=Math.round(255*f[t]),t++,e++;e++}}m=[...m,...r]}else if(i<0)K.makeColoredSphere(d,u,m,t,g,p);else{const e=a.vt();a.$0(e,A[3],[A[0],A[1],A[2]]);const s=n.fA(0,.5*-i,0,1),o=n.fA(0,.5*+i,0,1);n.Z0(s,s,e),n.Z0(o,o,e),n.WQ(s,s,g),n.WQ(o,o,g);const l=r.fA(s[0],s[1],s[2]),c=r.fA(o[0],o[1],o[2]);K.makeColoredCylinder(d,u,m,l,c,t,p)}}return{positions:Float32Array.from(d),indices:Uint32Array.from(u),rgba255:Uint8Array.from(m)}}static async readGII(t,e){void 0===e&&(e=0);let i=t.byteLength;if(i<20)throw new Error("File too small to be GII: bytes = "+i);let n=new TextDecoder("ascii").decode(t);if(31===n[0].charCodeAt(0)){const e=await ye.decompress(new Uint8Array(t));t=e.buffer,n=new TextDecoder("ascii").decode(e.buffer)}let r=0;function a(){let e=!0,a=r;for(;e;){for(;r<i&&"<"!==n[r];)r++;for(a=r;r<i&&">"!==n[r];)r++;if(e="/"===n[r-1],a+1<i&&"/"===n[a+1]&&(r+=1,e=!0),r>=i)break}const s=(new TextDecoder).decode(t.slice(a+1,r)).trim(),o=s.split(" ")[0].trim(),l=r;let c=r,h=r;if("?"!==n[a+1]&&"!"!==n[a+1]){const t="</"+o+">";c=n.indexOf(t,l),h=c+t.length-1}return{name:s,startPos:a,contentStartPos:l,contentEndPos:c,endPos:h}}let s=a();if(!s.name.startsWith("?xml"))throw new Error("readGII: Invalid XML file");for(;!s.name.startsWith("GIFTI")&&s.endPos<i;)s=a();if(!s.name.startsWith("GIFTI")||s.contentStartPos===s.contentEndPos)throw new Error("readGII: XML file does not include GIFTI tag");i=s.contentEndPos;let o=new Float32Array,l=new Uint32Array,c=new Float32Array,h="",d=!1,u=!1,m=!1,f=!1,g=[1,1,1];const A=[0,0,0];let p=0,v=!1,x=!1,w=0,y=!1;s.endPos=s.contentStartPos;let b="";function C(t,e){void 0===e&&(e=!1);const i=b.indexOf(t);if(i<0)return 1;const n=b.indexOf('"',i)+1,r=b.indexOf('"',n),a=b.slice(n,r);return e?parseFloat(a):parseInt(a)}function M(t){const e=b.indexOf(t);if(e<0)return"";const i=e+t.length,n=b.indexOf("]",i);return b.slice(i,n)}const D={R:[],G:[],B:[],A:[],I:[],labels:[]};for(;s.endPos<i&&s.name.length>1;)if(s=a(),s.name.startsWith("Label Key")&&(b=s.name,D.I.push(C("Key=")),D.R.push(Math.round(255*C("Red=",!0))),D.G.pu
1sh(Math.round(255*C("Green=",!0))),D.B.push(Math.round(255*C("Blue=",!0))),D.A.push(Math.round(255*C("Alpha",!0))),b=(new TextDecoder).decode(t.slice(s.contentStartPos+1,s.contentEndPos)).trim(),D.labels.push(M("<![CDATA["))),"Data"!==s.name.trim()){if("DataSpace"===s.name.trim()&&(b=(new TextDecoder).decode(t.slice(s.contentStartPos+1,s.contentEndPos)).trim(),b.includes("NIFTI_XFORM_SCANNER_ANAT")&&(y=!0)),"MD"===s.name.trim()&&(b=(new TextDecoder).decode(t.slice(s.contentStartPos+1,s.contentEndPos)).trim(),b.includes("AnatomicalStructurePrimary")&&b.includes("CDATA[")&&(h=M("<Value><![CDATA[").toUpperCase()),b.includes("VolGeom")&&b.includes("CDATA["))){let t=-1;if(b.includes("VolGeomC_R")&&(t=0),b.includes("VolGeomC_A")&&(t=1),b.includes("VolGeomC_S")&&(t=2),t<0)continue;A[t]=parseFloat(M("<Value><![CDATA["))}s.name.startsWith("DataArray")&&(b=s.name,g=[1,1,1],v=b.includes('Encoding="GZipBase64Binary"'),x=b.includes('Encoding="ASCII"'),d=b.includes('Intent="NIFTI_INTENT_TRIANGLE"'),u=b.includes('Intent="NIFTI_INTENT_POINTSET"'),m=b.includes('Intent="NIFTI_INTENT_VECTOR"'),f=b.includes('ArrayIndexingOrder="ColumnMajorOrder"'),b.includes('DataType="NIFTI_TYPE_UINT8"')&&(p=2),b.includes('DataType="NIFTI_TYPE_INT32"')&&(p=8),b.includes('DataType="NIFTI_TYPE_FLOAT32"')&&(p=16),b.includes('DataType="NIFTI_TYPE_FLOAT64"')&&(p=32),g[0]=C("Dim0="),g[1]=C("Dim1="),g[2]=C("Dim2="))}else{if(m)continue;let i;if(b=(new TextDecoder).decode(t.slice(s.contentStartPos+1,s.contentEndPos)).trim(),x){const t=g[0]*g[1]*g[2],e=b.split(/\s+/);if(t!==e.length)throw new Error("Unable to parse ASCII GIfTI");if(2===p&&(p=8),32===p&&(p=16),8===p){i=new Int32Array(t);for(let n=0;n<t;n++)i[n]=parseInt(e[n])}if(16===p){i=new Float32Array(t);for(let n=0;n<t;n++)i[n]=parseFloat(e[n])}}else if("undefined"==typeof Buffer){let t=function(t){const e=atob(t),i=e.length,n=new Uint8Array(i);for(let r=0;r<i;r++)n[r]=e.charCodeAt(r);return n};if(v){const e=t(b.slice());i=await ye.decompress(new Uint8Array(e))}else i=t(b.slice())}else if(v){const t=Buffer.from(b.slice(),"base64");i=await ye.decompress(new Uint8Array(t))}else i=Buffer.from(b.slice(),"base64");if(u){if(16!==p&&Q.warn("expect positions as FLOAT32"),o=new Float32Array(i.buffer),f){const t=o.slice(),e=t.length/3;let i=0;for(let n=0;n<e;n++)for(let r=0;r<3;r++)o[i]=t[r*e+n],i++}}else if(d){if(8!==p&&Q.warn("expect indices as INT32"),l=new Uint32Array(i.buffer),f){const t=l.slice(),e=t.length/3;let i=0;for(let n=0;n<e;n++)for(let r=0;r<3;r++)l[i]=t[r*e+n],i++}}else{let t,n=function(t,e){const i=t.length,n=new Float32Array(i+e.length);return n.set(t),n.set(e,i),n};if(w=g[0]*g[1]*g[2],0!==e&&w%e!=0&&Q.warn("Number of vertices in scalar overlay ("+w+") does not match mesh ("+e+")"),2===p){const e=new Uint8Array(i.buffer);t=Float32Array.from(e)}else if(8===p){const e=new Int32Array(i.buffer);t=Float32Array.from(e)}else if(16===p)t=new Float32Array(i.buffer);else{if(32!==p)throw new Error(`Invalid dataType: ${p}`);{const e=new Float64Array(i.buffer);t=Float32Array.from(e)}}c=n(c,t)}}let T;if(D.I.length>1){D.A.some((t=>t>0))||D.A.fill(255),T=ve.makeLabelLut(D)}if(e>0)return{scalars:c,colormapLabel:T,anatomicalStructurePrimary:h};if(o.length>2&&!y&&(0!==A[0]||0!==A[1]||0!==A[2])){w=Math.floor(o.length/3);let t=0;for(let e=0;e<w;e++)o[t]+=A[0],t++,o[t]+=A[1],t++,o[t]+=A[2],t++}return{positions:o,indices:l,scalars:c,colormapLabel:T,anatomicalStructurePrimary:h}}},Me=class{constructor(t,e,i,n,r){C(this,"text"),C(this,"style"),C(this,"points"),C(this,"anchor"),C(this,"onClick"),this.text=t,this.style=e,this.points=i,this.anchor=n||0,this.onClick=r}},De={colormap:"gray",opacity:0,nFrame4D:0,frame4D:0,outlineBorder:0,cal_min:0,cal_max:0,cal_minNeg:0,cal_maxNeg:0,colormapType:0,values:new Array,useNegativeCmap:!1,showLegend:!0},Te=class t{constructor(t,e,i,n,r,a,s,l,c,h,d,u,m,f){void 0===i&&(i=""),void 0===n&&(n=new Uint8Array([255,255,255,255])),void 0===r&&(r=1),void 0===a&&(a=!0),void 0===l&&(l=null),void 0===c&&(c=null),void 0===h&&(h=null),void 0===d&&(d=null),void 0===u&&(u=null),void 0===m&&(m=!0),void 0===f&&(f=""),C(this,"id"),C(this,"name"),C(this,"anatomicalStructurePrimary"),C(this,"colorbarVisible"),C(this,"furthestVertexFromOrigin"),C(this,"extentsMin"),C(this,"extentsMax"),C(this,"opacity"),C(this,"visible"),C(this,"meshShaderIndex",0),C(this,"offsetPt0",null),C(this,"colormapInvert",!1),C(this,"fiberGroupColormap",null),C(this,"indexBuffer"),C(this,"vertexBuffer"),C(this,"vao"),C(this,"vaoFiber"),C(this,"pts"),C(this,"tris"),C(this,"layers"),C(this,"type","mesh"),C(this,"data_type"),C(this,"rgba255"),C(this,"fiberLength"),C(this,"fiberLengths"),C(this,"fiberDensity"),C(this,"fiberDither",.1),C(this,"fiberColor","Global"),C(this,"fiberDecimationStride",1),C(this,"fiberSides",5),C(this,"fiberRadius",0),C(this,"fiberOcclusion",0),C(this,"f32PerVertex",5),C(this,"dpsThreshold",NaN),C(this,"fiberMask"),C(this,"colormap"),C(this,"dpg"),C(this,"dps"),C(this,"dpv"),C(this,"groups"),C(this,"hasConnectome",!1),C(this,"connectome"),C(this,"indexCount"),C(this,"vertexCount",1),C(this,"nodeScale",4),C(this,"edgeScale",1),C(this,"legendLineThickness",0),C(this,"showLegend",!0),C(this,"nodeColormap","warm"),C(this,"edgeColormap","warm"),C(this,"nodeColormapNegative"),C(this,"edgeColormapNegative"),C(this,"nodeMinColor"),C(this,"nodeMaxColor"),C(this,"edgeMin"),C(this,"edgeMax"),C(this,"nodes"),C(this,"edges"),C(this,"points"),this.anatomicalStructurePrimary=f,this.name=i,this.colorbarVisible=m,this.id=(0,o.v4)();const g=xe.getExtents(t);this.furthestVertexFromOrigin=g.mxDx,this.extentsMin=g.extentsMin,this.extentsMax=g.extentsMax,this.opacity=r>1?1:r,this.visible=a,this.meshShaderIndex=0,this.indexBuffer=s.createBuffer(),this.vertexBuffer=s.createBuffer(),this.vao=s.createVertexArray(),s.bindVertexArray(this.vao),s.bindBuffer(s.ELEMENT_ARRAY_BUFFER,this.indexBuffer),s.bindBuffer(s.ARRAY_BUFFER,this.vertexBuffer),s.enableVertexAttribArray(0),s.enableVertexAttribArray(1);if(7!==this.f32PerVertex?(s.vertexAttribPointer(0,3,s.FLOAT,!1,20,0),s.vertexAttribPointer(1,4,s.BYTE,!0,20,12),s.enableVertexAttribArray(2),s.vertexAttribPointer(2,4,s.UNSIGNED_BYTE,!0,20,16)):(s.vertexAttribPointer(0,3,s.FLOAT,!1,28,0),s.vertexAttribPointer(1,3,s.FLOAT,!1,28,12),s.enableVertexAttribArray(2),s.vertexAttribPointer(2,4,s.UNSIGNED_BYTE,!0,28,24)),s.bindVertexArray(null),this.vaoFiber=s.createVertexArray(),this.offsetPt0=null,this.hasConnectome=!1,this.colormapInvert=!1,this.fiberGroupColormap=null,this.pts=t,this.layers=[],this.type="mesh",this.tris=e,n[3]<1)return this.rgba255=n,this.fiberLength=2,this.fiberDither=.1,this.fiberColor="Global",this.fiberDecimationStride=1,this.fiberMask=[],this.colormap=l,this.dpg=c,this.dps=h,this.dpv=d,this.groups=u,c&&this.initValuesArray(c),h&&this.initValuesArray(h),d&&this.initValuesArray(d),u&&this.initValuesArray(u),this.offsetPt0=new Uint32Array(e),this.tris=new Uint32Array(0),this.updateFibers(s),s.bindVertexArray(this.vaoFiber),s.bindBuffer(s.ELEMENT_ARRAY_BUFFER,this.indexBuffer),s.bindBuffer(s.ARRAY_BUFFER,this.vertexBuffer),s.enableVertexAttribArray(0),s.vertexAttribPointer(0,3,s.FLOAT,!1,16,0),s.enableVertexAttribArray(1),s.vertexAttribPointer(1,4,s.UNSIGNED_BYTE,!0,16,12),void s.bindVertexArray(null);if(l){this.connectome=l,this.hasConnectome=!0;const t=Object.keys(l);for(let e=0,i=t.length;e<i;e++)this[t[e]]=l[t[e]]}this.rgba255=n,this.updateMesh(s)}initValuesArray(t){for(let e=0;e<t.length;e++){const i=t[e].vals.reduce(((t,e)=>Math.min(t,e))),n=t[e].vals.reduce(((t,e)=>Math.max(t,e)));t[e].global_min=i,t[e].global_max=n,t[e].cal_min=i,t[e].cal_max=n}return t}linesToCylinders(t,e,i){function a(t){return r.fA(t[0],t[1],t[2])}const s=Math.pow(2,32)-1,o=i.length;let l=0,c=0;for(let n=0;n<o;n++)i[n]!==s?l++:c++;const h=this.fiberSides,d=h*l,u=this.f32PerVertex;if(5!==u)throw Error("fiberSides > 1 requires f32PerVertex == 5");const m=new Float32Array(d*u),f=new Uint8Array(m.buffer);let g=0,A=n.vt(),p=n.vt(),v=n.vt();const x=r.vt();let w=r.vt(),y=0;const b=this.fiberRadius;for(let T=0;T<o;T++){const t=i[T]===s;if(t&&y<1)continue;let l=4*i[T];if(y++,y<=1){A=n.fA(e[l+0],e[l+1],e[l+2],e[l+3]),p=n.o8(A),T+1<o&&i[T+1]!==s&&(l=4*i[T+1],v=n.fA(e[l+0],e[l+1],e[l+2],e[l+3]),r.Re(x,a(A),a(v)),r.S8(x,x),w=K.getFirstPerpVector(x));continue}v=t?n.o8(p):n.fA(e[l+0],e[l+1],e[l+2],e[l+3]),r.Re(x,a(A),a(v)),r.S8(x,x);const c=r.vt();r.$A(c,w,x);const d=r.vt();r.$A(d,x,c),w=r.o8(w);const C=r.vt();r.$A(C,x,d),r.S8(C,C);const M=r.vt();for(let e=0;e<h;e++){const t=Math.cos(e/h*2*Math.PI),i=Math.sin(e/h*2*Math.PI);M[0]=b*(t*d[0]+i*C[0]),M[1]=b*(t*d[1]+i*C[1]),M[2]=b*(t*d[2]+i*C[2]),r.WQ(M,a(p),M);const n=g*u;m[n+0]=M[0],m[n+1]=M[1],m[n+2]=M[2];const s=r.vt();r.Re(s,M,a(p)),r.S8(s,s);const o=4*(n+3);f[o+0]=127*s[0],f[o+1]=127*s[1],f[o+2]=127*s[2],m[n+4]=p[3],g++}A=n.o8(p),p=n.o8(v),t&&(y=0)}const C=(l-c)*h*2*3,M=new Uint32Array(C);let D=0;g=0;for(let n=1;n<o;n++){if(i[n]===s){g+=h;continue}if(i[n-1]===s)continue;let t=g,e=g+h;const r=e,a=e+h;for(let i=0;i<h;i++)M[D++]=t,M[D++]=e++,e===a&&(e=a-h),M[D++]=e,M[D++]=t++,t===r&&(t=r-h),M[D++]=e,M[D++]=t;g+=h}t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer),t.bufferData(t.ELEMENT_ARRAY_BUFFER,Uint32Array.from(M),t.STATIC_DRAW),t.bindBuffer(t.ARRAY_BUFFER,this.vertexBuffer),t.bufferData(t.ARRAY_BUFFER,f,t.STATIC_DRAW),this.indexCount=C}createFiberDensityMap(){if(this.fiberDensity)return;const t=this.pts,e=t.length/3;let i=0;for(let f=0;f<3;f++){const t=this.extentsMax[f]-this.extentsMin[f];i=Math.max(i,t)}if(this.fiberDensity=new Float32Array(e),0===i)return;const n=64,r=i/63/2,a=63/i;let s=new Float32Array(262144);const o=[this.extentsMin[0]-r,this.extentsMin[1]-r,this.extentsMin[2]-r],l=[0,0,0];let c=0;for(let f=0;f<e;f++){l[0]=Math.round((t[c++]-o[0])*a),l[1]=Math.round((t[c++]-o[1])*a),l[2]=Math.round((t[c++]-o[2])*a);const e=l[0]+l[1]*n+4096*l[2];-1!==e&&s[e]++}function h(t,e){let i=t.slice(),n=-1;const r=e-1;for(let s=0;s<e;s++)for(let a=0;a<e;a++)for(let s=0;s<e;s++)n++,s<1||s>=r||(t[n]=i[n-1]+i[n]+i[n]+i[n+1]);n=-1,i=t.slice();for(let s=0;s<e;s++)for(let a=0;a<e;a++)for(let s=0;s<e;s++)n++,a<1||a>=r||(t[n]=i[n-e]+i[n]+i[n]+i[n+e]);const a=e*e;n=-1,i=t.slice();for(let s=0;s<e;s++)for(let o=0;o<e;o++)for(let l=0;l<e;l++)n++,s<1||s>=r||(t[n]=i[n-a]+i[n]+i[n]+i[a]);return t}s=h(s,n),s=h(s,n);let d=0,u=1/0;const m=262144;for(let f=0;f<m;
1f++)s[f]<=0||(d=Math.max(d,s[f]),u=Math.min(u,s[f]));if(!(d<=1||d<=u)){c=0;for(let t=0;t<m;t++)s[t]=Math.max(0,s[t]-u);d-=u;for(let i=0;i<e;i++){l[0]=Math.round((t[c++]-o[0])*a),l[1]=Math.round((t[c++]-o[1])*a),l[2]=Math.round((t[c++]-o[2])*a);const e=l[0]+l[1]*n+4096*l[2];this.fiberDensity[i]=s[e]/d}}}updateFibers(t){if(!this.offsetPt0||!this.fiberLength)return;const e=this.pts,i=this.offsetPt0,n=i.length-1,a=e.length/3;if(!this.fiberLengths){this.fiberLengths=new Uint32Array(n);for(let t=0;t<n;t++){const n=3*i[t],a=3*(i[t+1]-1);let s=0;for(let t=n;t<a;t+=3){const i=r.fA(e[t+0]-e[t+3],e[t+1]-e[t+4],e[t+2]-e[t+5]);s+=r.Il(i)}this.fiberLengths[t]=s}}const s=new Float32Array(4*a),o=new Uint32Array(s.buffer);let l=0,c=0;for(let r=0;r<a;r++)s[c+0]=e[l+0],s[c+1]=e[l+1],s[c+2]=e[l+2],l+=3,c+=4;const h=this.fiberDither,d=.5*h;function u(t,e,i){const n=255*(h*Math.random()-d);return(t=Math.max(Math.min(t+n,255),0))+((e=Math.max(Math.min(e+n,255),0))<<8)+((i=Math.max(Math.min(i+n,255),0))<<16)}function m(t,e,i,n,a,s,o){const l=r.fA(Math.abs(t-n),Math.abs(e-a),Math.abs(i-s));r.S8(l,l);const c=o-d;for(let r=0;r<3;r++)l[r]=255*Math.max(Math.min(Math.abs(l[r])+c,1),0);return l[0]+(l[1]<<8)+(l[2]<<16)}const f=this.fiberColor.toLowerCase();let g=null,A=null;if(f.startsWith("dps")&&this.dps&&this.dps.length>0){const t=parseInt(f.substring(3));t<this.dps.length&&this.dps[t].vals.length===n&&(g=this.dps[t].vals)}if(f.startsWith("dpv")&&this.dpv&&this.dpv.length>0){const t=parseInt(f.substring(3));t<this.dpv.length&&this.dpv[t].vals.length===a&&(A=this.dpv[t])}const p=new Int16Array(n);if(this.groups&&null!==this.fiberGroupColormap||f.startsWith("dpg")&&this.dpg.length>0){const t=new Uint8ClampedArray(4*this.groups.length),e=new Array(this.groups.length).fill(!1);if(this.fiberGroupColormap){const i=this.fiberGroupColormap;void 0===i.A&&(i.A=Array.from(new Uint8ClampedArray(i.I.length).fill(255)));for(let n=0;n<i.I.length;n++){let r=i.I[n];r<0||r>=this.groups.length||(i.A[n]<1||(e[r]=!0,r*=4,t[r]=i.R[n],t[r+1]=i.G[n],t[r+2]=i.B[n],t[r+3]=255))}}else if(f.startsWith("dpg")&&this.dpg.length>0){const i=parseInt(f.substring(3)),n=i<this.dpg.length?this.dpg[i]:this.dpg[0],r=ve.colormap(this.colormap,this.colormapInvert),a=n.cal_min,s=n.cal_max,o=this.groups.length;for(let l=0;l<o;l++){const i=n.vals[l];if(i<a)continue;let o=Math.round(255*Math.min(Math.max((i-a)/(s-a),0),1));e[l]=!0;const c=4*l;o*=4,t[c]=r[o+0],t[c+1]=r[o+1],t[c+2]=r[o+2],t[c+3]=255}}p.fill(-1);for(let i=0;i<this.groups.length;i++){if(!e[i])continue;const t=this.groups[i];for(let e=0;e<t.vals.length;e++)p[t.vals[e]]=i}for(let r=0;r<n;r++){if(p[r]<0)continue;const e=p[r]%256*4,n=u(t[e],t[e+1],t[e+2]),a=i[r],s=4*(i[r+1]-1)+3;for(let t=4*a+3;t<=s;t+=4)o[t]=n}}else if(A){const t=ve.colormap(this.colormap,this.colormapInvert),e=A.cal_min,i=A.cal_max;let n=3;for(let r=0;r<a;r++){let a=Math.min(Math.max((A.vals[r]-e)/(i-e),0),1);a=4*Math.round(Math.max(Math.min(255,255*a)));const s=t[a]+(t[a+1]<<8)+(t[a+2]<<16);o[n]=s,n+=4}}else if(g){const t=ve.colormap(this.colormap,this.colormapInvert);let e=g[0],r=g[0];for(let i=0;i<n;i++)e=Math.min(e,g[i]),r=Math.max(r,g[i]);r===e&&(e-=1);for(let a=0;a<n;a++){let n=(g[a]-e)/(r-e);n=4*Math.round(Math.max(Math.min(255,255*n)));const s=t[n]+(t[n+1]<<8)+(t[n+2]<<16),l=i[a],c=4*(i[a+1]-1)+3;for(let t=4*l+3;t<=c;t+=4)o[t]=s}}else if(f.includes("fixed"))if(0===h){const t=this.rgba255[0]+(this.rgba255[1]<<8)+(this.rgba255[2]<<16);let e=3;for(let i=0;i<a;i++)o[e]=t,e+=4}else for(let r=0;r<n;r++){const t=u(this.rgba255[0],this.rgba255[1],this.rgba255[2]),e=i[r],n=4*(i[r+1]-1)+3;for(let i=4*e+3;i<=n;i+=4)o[i]=t}else if(f.includes("local"))for(let r=0;r<n;r++){const t=i[r];let n=3*t;const a=3*(i[r+1]-1),s=h*Math.random();let l=m(e[n],e[n+1],e[n+2],e[n+4],e[n+5],e[n+6],s),c=4*t+3;for(;n<a;)o[c]=l,c+=4,n+=3,l=m(e[n-3],e[n-2],e[n-1],e[n+3],e[n+4],e[n+5],s);o[c]=o[c-4]}else for(let r=0;r<n;r++){const t=i[r],n=i[r+1]-1,a=3*t,s=3*n,l=m(e[a],e[a+1],e[a+2],e[s],e[s+1],e[s+2],h*Math.random()),c=4*n+3;for(let e=4*t+3;e<=c;e+=4)o[e]=l}if(this.fiberOcclusion>0){let t=function(t,e){return e*(255&t)+(e*(t>>8&255)<<8)+(e*(t>>16&255)<<16)};this.createFiberDensityMap();for(let e=0;e<n;e++){const n=i[e],r=4*n+3,a=4*(i[e+1]-1)+3;let s=n;const l=Math.min(this.fiberOcclusion,.99);for(let e=r;e<=a;e+=4){let i=this.fiberDensity[s++];if(i<=0)continue;i/=(1/l-2)*(1-i)+1;const n=1-Math.min(i,.9);let r=o[e];r=t(r,n),o[e]=r}}}if(Number.isFinite(this.dpsThreshold)&&this.dps){if(!g){const t=0;this.dps[t].vals.length===n&&(g=this.dps[t].vals)}if(g)for(let t=0;t<n;t++)g[t]<this.dpsThreshold&&(p[t]=-1)}const v=this.fiberLength,x=Math.pow(2,32)-1,w=[];let y=-1;for(let r=0;r<n;r++)if(!(p[r]<0||this.fiberLengths[r]<v||(y++,y%this.fiberDecimationStride!=0))){for(let t=i[r];t<i[r+1];t++)w.push(t);w.push(x)}this.fiberSides>2&&this.fiberRadius>0?this.linesToCylinders(t,s,w):(this.indexCount=w.length,t.bindBuffer(t.ARRAY_BUFFER,this.vertexBuffer),t.bufferData(t.ARRAY_BUFFER,Uint32Array.from(o),t.STATIC_DRAW),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer),t.bufferData(t.ELEMENT_ARRAY_BUFFER,Uint32Array.from(w),t.STATIC_DRAW))}indexNearestXYZmm(t,e,i){const n=this.pts,r=this.pts.length/3;let a=0,s=1/0,o=0;for(let l=0;l<r;l++){const r=Math.pow(n[a]-t,2)+Math.pow(n[a+1]-e,2)+Math.pow(n[a+2]-i,2);r<s&&(s=r,o=l),a+=3}return s=Math.sqrt(s),[o,s]}unloadMesh(t){if(t.bindBuffer(t.ARRAY_BUFFER,null),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,null),t.bindVertexArray(null),t.deleteBuffer(this.vertexBuffer),t.deleteBuffer(this.indexBuffer),t.deleteVertexArray(this.vao),t.deleteVertexArray(this.vaoFiber),this.offsetPt0=null,this.tris=null,this.pts=null,this.layers&&this.layers.length>0)for(let e=0;e<this.layers.length;e++)this.layers[e].values=null;if(this.dpg&&this.dpg.length>0)for(let e=0;e<this.dpg.length;e++)this.dpg[e].vals=null;if(this.dps&&this.dps.length>0)for(let e=0;e<this.dps.length;e++)this.dps[e].vals=null}scalars2RGBA(t,e,i,n){void 0===n&&(n=!1);const r=i.length;if(4*r<t.length)return Q.error(`colormap2RGBA incorrectly specified ${r}*4 != ${t.length}`),t;const a=Math.round(255*e.opacity);let s=e.cal_min,o=e.cal_max,l=ve.colormap(e.colormap,this.colormapInvert),c=1;if(n){if(!e.useNegativeCmap)return t;c=-1,l=ve.colormap(e.colormapNegative,e.colormapInvert),s=e.cal_min,o=e.cal_max,isFinite(e.cal_minNeg)&&isFinite(e.cal_minNeg)&&(s=-e.cal_minNeg,o=-e.cal_maxNeg)}let h=s;e.isTransparentBelowCalMin||(h=Number.NEGATIVE_INFINITY);const d=2===e.colormapType;0!==e.colormapType&&(s=Math.min(s,0));const u=255/(o-s);for(let m=0;m<r;m++){let n=i[m]*c;if(isNaN(n))continue;let r=a;if(n<h){if(!(n>0&&d))continue;r=Math.round(255*e.opacity*Math.pow(n/h,2))}if(n=(n-s)*u,n<0&&e.isTransparentBelowCalMin)continue;n=4*Math.min(255,Math.max(0,Math.round(n)));const o=4*m;t[o+0]=l[n+0],t[o+1]=l[n+1],t[o+2]=l[n+2],t[o+3]=r}return t}blendColormap(t,e,i,n,r,a,s){void 0===s&&(s=!1);const o=this.pts.length/3,l=Math.min(i.opacity,1);function c(t,e,i){return t*(1-i)+e*i}function h(t,e){return Math.min(t+e,255)}const d=s?-1:1,u=o*Math.min(Math.max(i.frame4D,0),i.nFrame4D-1);let m=n;i.isTransparentBelowCalMin||(m=Number.NEGATIVE_INFINITY),0!==i.colormapType&&(n=Math.min(n,0));const f=255/(r-n);let g=new Array(o).fill(!1);if(0!==i.outlineBorder){const t=new Uint8Array(o).fill(0);for(let e=0;e<o;e++){d*i.values[e+u]>=m&&(t[e]=1)}g=xe.getClusterBoundaryU8(t,this.tris);for(let e=0;e<o;e++){d*i.values[e+u]<m&&(g[e]=!1)}}const A=new Float32Array(256).fill(l);
1if(m>n&&2===i.colormapType){let t=Math.round((m-n)*f);t=Math.max(t,1);for(let e=1;e<t;e++)A[e]=l*Math.pow(e/t,2);A[0]=0,m=n+Number.EPSILON}for(let p=0;p<o;p++){const r=d*i.values[p+u];if(r<m)continue;let s=Math.round((r-n)*f);if(s<0&&i.isTransparentBelowCalMin)continue;s=Math.max(0,s),s=Math.min(255,s);let o=A[s];s*=4;let l=28*p+24;if(7!==this.f32PerVertex&&(l=20*p+16),i.isAdditiveBlend){const t=4*p;e[t+0]=h(e[t+0],a[s+0]),e[t+1]=h(e[t+1],a[s+1]),e[t+2]=h(e[t+2],a[s+2]),e[t+3]=h(e[t+3],255)}else{if(g[p]&&(o=i.outlineBorder,i.outlineBorder<0)){t[l+0]=0,t[l+1]=0,t[l+2]=0;continue}t[l+0]=c(t[l+0],a[s+0],o),t[l+1]=c(t[l+1],a[s+1],o),t[l+2]=c(t[l+2],a[s+2],o)}}}updateMesh(t){if(this.offsetPt0)return void this.updateFibers(t);if(this.hasConnectome)return;if(!this.pts||!this.tris||!this.rgba255)return void Q.warn("underspecified mesh");function e(t,e,i){return t*(1-i)+e*i}const i=this.generatePosNormClr(this.pts,this.tris,this.rgba255),n=this.pts.length/3,r=new Uint8Array(i.buffer);let a=0;const s=new Uint8Array(4*n);let o=this.tris;if(this.layers&&this.layers.length>0)for(let l=0;l<this.layers.length;l++){const t=this.layers[l],i=t.opacity;if(i<=0||t.cal_min>t.cal_max)continue;if(void 0===t.outlineBorder&&(t.outlineBorder=0),void 0===t.isAdditiveBlend&&(t.isAdditiveBlend=!1),t.colormapLabel&&t.colormapLabel.R&&!t.colormapLabel.lut&&(t.colormapLabel=ve.makeLabelLut(t.colormapLabel,255,t.global_max)),t.colormapLabel&&t.colormapLabel.lut){const i=t.colormapLabel;let a=0;t.colormapLabel.min&&(a=t.colormapLabel.min);let s=i.lut;const l=Math.floor(s.length/4);if(t.atlasValues&&l>0&&l===t.atlasValues.length&&t.colormap){const e=t.atlasValues;let i=!1,r=!0;for(let t=0;t<l;t++)isNaN(e[t])?i=!0:r=!1;if(r)return void Q.debug("invisible mesh: all atlasValues are NaN.");if(i){Q.debug("some vertices have NaN atlasValues (mesh will be decimated).");const i=new Array(n).fill(!1);for(let o=0;o<n;o++){const n=Math.round(t.values[o])-a;isNaN(e[n])&&(i[o]=!0)}const r=new Array(o.length).fill(!1);for(let t=0;t<o.length;t++)i[o[t]]&&(r[t]=!0);const s=this.tris;let l=0;for(let t=0;t<s.length;t+=3)r[t]||r[t+1]||r[t+2]||l++;0===l&&Q.debug("invisible mesh: all triangles of a vertex with a NaN atlasValue."),o=new Uint32Array(3*l);let c=0;for(let t=0;t<s.length;t+=3)r[t]||r[t+1]||r[t+2]||(o[c++]=s[t],o[c++]=s[t+1],o[c++]=s[t+2])}s.fill(0),s=this.scalars2RGBA(s,t,e),t.useNegativeCmap&&(s=this.scalars2RGBA(s,t,e,!0))}else t.atlasValues&&Q.warn(`Expected ${l} atlasValues but got ${t.atlasValues.length} for mesh layer`);if(t.showLegend&&l===t.colormapLabel.labels.length){t.labels=[];for(let e=0;e<l;e++){const i=Array.from(s.slice(4*e,4*e+4)).map((t=>t/255)),r=t.colormapLabel.labels[e],a=[0,0,0];let o=0;for(let s=0;s<n;s++)if(t.values[s]===e){const t=3*s;a[0]+=this.pts[t],a[1]+=this.pts[t+1],a[2]+=this.pts[t+2],o++}if(o>0&&(a[0]/=o,a[1]/=o,a[2]/=o),0===i[3]||!r||r.startsWith("_"))continue;i[3]=1;const l=new Me(r,{textColor:i,bulletScale:1,bulletColor:i,lineWidth:0,lineColor:i,textScale:1,textAlignment:"left",lineTerminator:"none"},a);t.labels.push(l),Q.debug("label for mesh layer:",l)}}else delete t.labels;const c=n*Math.min(Math.max(t.frame4D,0),t.nFrame4D-1),h=new Uint8Array(4*n);let d=0;for(let e=0;e<n;e++){const i=t.values[e+c]-a,n=4*Math.min(Math.max(i,0),l-1);h[d+0]=s[n+0],h[d+1]=s[n+1],h[d+2]=s[n+2],h[d+3]=Math.round(s[n+3]/255*t.opacity*255),d+=4}let u=new Array(n).fill(!1);0!==t.outlineBorder&&(u=xe.getClusterBoundary(h,this.tris)),d=0;for(let o=0;o<n;o++){let i=28*o+24;7!==this.f32PerVertex&&(i=20*o+16);let n=h[d+3]/255;u[o]&&(n=t.outlineBorder,t.outlineBorder<0)?(r[i+0]=0,r[i+1]=0,r[i+2]=0,d+=4):(r[i+0]=e(r[i+0],h[d+0],n),r[i+1]=e(r[i+1],h[d+1],n),r[i+2]=e(r[i+2],h[d+2],n),d+=4)}continue}if(t.values instanceof Uint8Array){const a=new Uint8Array(t.values.buffer);let s=new Array(n).fill(!0);0!==t.outlineBorder&&(s=xe.getClusterBoundary(a,this.tris));let o=0;for(let n=0;n<t.values.length;n++){let l=28*n+24;7!==this.f32PerVertex&&(l=20*n+16);let c=i;s[n]&&(c=t.outlineBorder,t.outlineBorder<0)?(r[l+0]=0,r[l+1]=0,r[l+2]=0,o+=4):(r[l+0]=e(r[l+0],a[o+0],c),r[l+1]=e(r[l+1],a[o+1],c),r[l+2]=e(r[l+2],a[o+2],c),o+=4)}continue}t.useNegativeCmap&&(t.cal_min=Math.max(Number.EPSILON,t.cal_min),t.cal_max=Math.max(t.cal_min+1e-6,t.cal_max)),void 0===t.isTransparentBelowCalMin&&(t.isTransparentBelowCalMin=!0);const c=ve.colormap(t.colormap,t.colormapInvert);if(t.isAdditiveBlend&&a++,this.blendColormap(r,s,t,t.cal_min,t.cal_max,c),t.useNegativeCmap){const e=ve.colormap(t.colormapNegative,t.colormapInvert);let i=t.cal_min,n=t.cal_max;isFinite(t.cal_minNeg)&&isFinite(t.cal_minNeg)&&(i=-t.cal_minNeg,n=-t.cal_maxNeg),this.blendColormap(r,s,t,i,n,e,!0)}}if(a>0)for(let l=0;l<n;l++){let t=function(t,e){return Math.min(t*e*(1/255),255)},i=28*l+24;7!==this.f32PerVertex&&(i=20*l+16);const n=4*l,o=Math.min(a,s[n+3]/255);o<=0||(r[i+0]=t(r[i+0],s[n+0]),r[i+1]=t(r[i+1],s[n+1]),r[i+2]=t(r[i+2],s[n+2]),r[i+0]=e(r[i+0],s[n+0],o),r[i+1]=e(r[i+1],s[n+1],o),r[i+2]=e(r[i+2],s[n+2],o))}t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer),t.bufferData(t.ELEMENT_ARRAY_BUFFER,Uint32Array.from(o),t.STATIC_DRAW),t.bindBuffer(t.ARRAY_BUFFER,this.vertexBuffer),t.bufferData(t.ARRAY_BUFFER,r,t.STATIC_DRAW),this.indexCount=o.length,this.vertexCount=this.pts.length}reverseFaces(t){if(this.offsetPt0)return;if(this.hasConnectome)return;const e=this.tris||[];for(let i=0;i<e.length;i+=3){const t=e[i];e[i]=e[i+1],e[i+1]=t}this.updateMesh(t)}hierarchicalOrder(){const t=this.tris.length/3,e=Math.log(t/20)/Math.log(4);if(t!==20*Math.pow(4,e))return NaN;if(this.pts.length/3!==10*Math.pow(4,e)+2)return NaN;for(let i=0;i<15;i+=3)if(0!==this.tris[i])return NaN;for(let i=15;i<24;i+=3)if(3!==this.tris[i])return NaN;for(let i=24;i<30;i+=3)if(4!==this.tris[i])return NaN;return e}decimateFaces(t,e){let i=this.tris;for(let n=t-1;n>=e;n--){const t=10*Math.pow(4,n+1)+2,e=10*Math.pow(4,n)+2,r=i.length/3,a=20*Math.pow(4,n);Q.info(`order ${n+1} -> ${n} vertices ${t} -> ${e} faces ${r} -> ${a}`);const s=Array.from({length:t},((t,e)=>e+1));for(let n=0;n<r;n++){const t=i[3*n],e=i[3*n+1],r=i[3*n+2];s[t-1]=Math.min(s[t-1],e,r)}const o=new Uint32Array(3*a);for(let n=0;n<a;n++)o[3*n]=s[i[3*n]-1],o[3*n+1]=s[i[3*n+1]-1],o[3*n+2]=s[i[3*n+2]-1];i=o}this.tris=new Uint32Array(i)}decimateHierarchicalMesh(t,e){void 0===e&&(e=4);const i=this.hierarchicalOrder();if(isNaN(i))return Q.warn("Unable to decimate mesh: it does not have a hierarchical structure"),!1;if(e>=i)return Q.warn(`Unable to decimate mesh: input order (${i}) must be larger than downsampled order (${e})`),!1;const n=this.pts.length/3,r=10*Math.pow(4,e)+2;if(this.pts=new Float32Array(this.pts.slice(0,3*r)),this.decimateFaces(i,e),this.layers&&this.layers.length>0)for(let a=0;a<this.layers.length;a++){const t=this.layers[a];t.values instanceof Float32Array||t.values.length!==n?t.values=new Float32Array(t.values.slice(0,r)):Q.warn("decimation logic needs to be updated")}return this.updateMesh(t),!0}async setLayerProperty(t,e,i,n){const r=this.layers[t];
1if(r&&e in r){if("colormapLabel"===e)if("object"==typeof i)r[e]=ve.makeLabelLut(i,255,r.global_max);else{if("string"==typeof i){const t=await ve.makeLabelLutFromUrl(i);return r[e]=t,void this.updateMesh(n)}Q.error("colormapLabel requires a string or object")}else r[e]=i;this.updateMesh(n)}else Q.warn("mesh does not have property ",e," for layer ",r)}setProperty(t,e,i){t in this?(this[t]=e,this.updateMesh(i)):console.warn("Mesh does not have property:",t,this)}generatePosNormClr(t,e,i){(t.length<3||i.length<4)&&(Q.error("Catastrophic failure generatePosNormClr()"),Q.debug("this",this),Q.debug("pts",t),Q.debug("rgba",i));const n=xe.generateNormals(t,e),r=t.length/3,a=r===i.length/4,s=this.f32PerVertex,o=new Float32Array(r*s),l=new Uint8Array(o.buffer);let c=0,h=0,d=0,u=4*(s-1);for(let m=0;m<r;m++)o[d+0]=t[c+0],o[d+1]=t[c+1],o[d+2]=t[c+2],7!==s?(l[u-4]=127*n[c+0],l[u-3]=127*n[c+1],l[u-2]=127*n[c+2]):(o[d+3]=n[c+0],o[d+4]=n[c+1],o[d+5]=n[c+2]),l[u]=i[h+0],l[u+1]=i[h+1],l[u+2]=i[h+2],l[u+3]=i[h+3],a&&(h+=4),c+=3,d+=s,u+=4*s;return o}static async readMesh(e,i,n,r,a,s){void 0===r&&(r=1),void 0===a&&(a=new Uint8Array([255,255,255,255])),void 0===s&&(s=!0);let o,l=new Uint32Array([]),c=new Float32Array([]),h="";const d=/(?:\.([^.]+))?$/;let u=d.exec(i)[1];if(u=u.toUpperCase(),"GZ"===u&&(u=d.exec(i.slice(0,-3))[1],u=u.toUpperCase()),"JCON"===u&&Q.error("you should never see this message: load using nvconnectome not nvmesh"),"JSON"===u&&Q.error("you should never see this message: load using nvconnectome not nvmesh"),a[3]=Math.max(1,a[3]),"TCK"===u||"TRK"===u||"TT"===u||"TRX"===u||"TRACT"===u){if(o="TCK"===u?Ce.readTCK(e):"TRACT"===u?Ce.readTRACT(e):"TT"===u?await Ce.readTT(e):"TRX"===u?await Ce.readTRX(e):await Ce.readTRK(e),void 0===o){o={pts:new Float32Array([0,0,0,0,0,0]),offsetPt0:new Uint32Array([0])},Q.error("Creating empty tracts")}return a[3]=0,new t(o.pts,o.offsetPt0,i,a,r,s,n,"inferno",o.dpg||null,o.dps||null,o.dpv||null,o.groups)}if("GII"===u)o=await Ce.readGII(e);else if("MZ3"===u)o=await Ce.readMZ3(e),"positions"in o||Q.warn("MZ3 does not have positions (statistical overlay?)");else if("ASC"===u)o=Ce.readASC(e);else if("DFS"===u)o=Ce.readDFS(e);else if("BYU"===u||"G"===u)o=Ce.readGEO(e);else if("GEO"===u)o=Ce.readGEO(e,!0);else if("ICO"===u||"TRI"===u)o=Ce.readICO(e);else if("OFF"===u)o=Ce.readOFF(e);else if("NV"===u)o=Ce.readNV(e);else if("OBJ"===u)o=await Ce.readOBJ(e);else if("PLY"===u)o=Ce.readPLY(e);else if("WRL"===u)o=Ce.readWRL(e);else if("X3D"===u)o=Ce.readX3D(e);else if("FIB"===u||"VTK"===u){if(o=Ce.readVTK(e),"offsetPt0"in o)return a[3]=0,new t(o.pts,o.offsetPt0,i,a,r,s,n,"inferno")}else o="SRF"===u?await Ce.readSRF(e):"STL"===u?Ce.readSTL(e):Ce.readFreeSurfer(e);if(o.anatomicalStructurePrimary&&(h=o.anatomicalStructurePrimary),o instanceof Float32Array)throw new Error("fatal: unknown mesh type loaded");if(!("positions"in o))throw new Error("positions not loaded");if(!o.indices)throw new Error("indices not loaded");if(c=o.positions,l=o.indices,"rgba255"in o&&o.rgba255.length>0&&(a=o.rgba255),"colors"in o&&o.colors&&o.colors.length===c.length){const t=c.length/3;a=new Uint8Array(4*t);let e=0,i=0;for(let n=0;n<t;n++)a[i++]=255*o.colors[e],a[i++]=255*o.colors[e+1],a[i++]=255*o.colors[e+2],a[i++]=255,e+=3}const m=c.length/3;if(l.length/3<1||m<3)throw new Error("Mesh should have at least one triangle and three vertices");a[3]=Math.max(1,a[3]);const f=new t(c,l,i,a,r,s,n,null,null,null,null,null,!0,h);if("scalars"in o&&o.scalars.length>0){const t=await Ce.readLayer(i,e,f,r,"gray");void 0===t?Q.warn("readLayer() failed to convert scalars"):(f.layers.push(t),f.updateMesh(n))}return f}static async loadLayer(t,e){let i,n=(new Uint8Array).buffer;if(void 0!==t.base64)n=function(t){const e=window.atob(t),i=e.length,n=new Uint8Array(i);for(let r=0;r<i;r++)n[r]=e.charCodeAt(r);return n.buffer}(t.base64);else{if(!t.url)throw new Error("layer: missing url");const e=await fetch(t.url,{headers:t.headers});if(!e.ok)throw Error(e.statusText);n=await e.arrayBuffer()}let r=[];if(t.name&&""!==t.name)i=t.name;else{if(!t.url)throw new Error("layer: missing url");try{r=new URL(t.url).pathname.split("/")}
1catch(u){r=t.url.split("/")}finally{i=r.slice(-1)[0]}}i.indexOf("?")>-1&&(i=i.slice(0,i.indexOf("?")));let a=.5;"opacity"in t&&(a=t.opacity);let s="warm";"colormap"in t&&(s=t.colormap);let o="winter";"colormapNegative"in t&&(o=t.colormapNegative);let l=!1;"useNegativeCmap"in t&&(l=t.useNegativeCmap);let c=null;"cal_min"in t&&(c=t.cal_min);let h=null;"cal_max"in t&&(h=t.cal_max);const d=await Ce.readLayer(i,n,e,a,s,o,l,c,h);d&&e.layers.push(d)}static async loadFromUrl(e){let i,{url:n="",headers:r={},gl:a,name:s="",opacity:o=1,rgba255:l=[255,255,255,255],visible:c=!0,layers:h=[],buffer:d=new ArrayBuffer(0),meshShaderIndex:u=0}=void 0===e?{}:e,m=n.split("/");if(""===s){try{m=new URL(n).pathname.split("/")}catch(g){m=n.split("/")}s=m.slice(-1)[0],s.indexOf("?")>-1&&(s=s.slice(0,s.indexOf("?")))}if(""===n)throw Error("url must not be empty");if(!a)throw Error("gl context is null");if(d.byteLength>0)i=d;else{const t=await fetch(n,{headers:r});if(!t.ok)throw Error(t.statusText);i=await t.arrayBuffer()}const f=await this.readMesh(i,s,a,o,new Uint8Array(l),c);if(void 0!==u&&(f.meshShaderIndex=u),!h||h.length<1)return f;for(let A=0;A<h.length;A++)await t.loadLayer(h[A],f);return f.updateMesh(a),f}static async readFileAsync(t){return new Promise(((e,i)=>{const n=new FileReader;n.onload=()=>{e(n.result)},n.onerror=i,n.readAsArrayBuffer(t)}))}static async loadFromFile(e){let{file:i,gl:n,name:r="",opacity:a=1,rgba255:s=[255,255,255,255],visible:o=!0,layers:l=[]}=void 0===e?{}:e;if(!i)throw new Error("file must be set");if(!n)throw new Error("rendering context must be set");const c=await t.readFileAsync(i),h=await t.readMesh(c,r,n,a,new Uint8Array(s),o);if(!l||l.length<1)return h;for(let d=0;d<l.length;d++)await t.loadLayer(l[d],h);return h.updateMesh(n),h}async loadFromBase64(e){let{base64:i,gl:n,name:r="",opacity:a=1,rgba255:s=[255,255,255,255],visible:o=!0,layers:l=[]}=void 0===e?{}:e;if(!i)throw new Error("base64 must bet set");if(!n)throw new Error("rendering context must be set");const c=function(t){const e=window.atob(t),i=e.length,n=new Uint8Array(i);for(let r=0;r<i;r++)n[r]=e.charCodeAt(r);return n.buffer}(i),h=await t.readMesh(c,r,n,a,new Uint8Array(s),o);if(!l||l.length<1)return h;for(let d=0;d<l.length;d++)await t.loadLayer(l[d],h);return h.updateMesh(n),h}},Ie="data:image/png;base64,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",Se={atlas:{type:"msdf",distanceRange:2,size:59.65625,width:512,height:256,yOrigin:"bottom"},metrics:{emSize:1,lineHeight:1.171875,ascender:.927734375,descender:-.244140625,underlineY:-.09765625,underlineThickness:.048828125},glyphs:[{unicode:32,advance:.24755859375},{unicode:33,advance:.25732421875,planeBounds:{left:.056159633438645884,bottom:-.02437761405677056,right:.20702396031135412,top:.7299440203067705},atlasBounds:{left:488.5,bottom:145.5,right:497.5,top:190.5}},{unicode:34,advance:.31982421875,planeBounds:{left:.049409125974004715,bottom:.48691155587022,right:.2840869677759953,top:.77187750662978},atlasBounds:{left:486.5,bottom:213.5,right:500.5,top:230.5}},{unicode:35,advance:.61572265625,planeBounds:{left:.037219103997511785,bottom:-.02169206718177056,right:.6239137085024882,top:.7326295671817705},atlasBounds:{left:66.5,bottom:51.5,right:101.5,top:96.5}},{unicode:36,advance:.5615234375,planeBounds:{left:.02956531458715296,bottom:-.12381369908983761,right:.5324464041628472,top:.8484230740898377},atlasBounds:{left:109.5,bottom:197.5,right:139.5,top:255.5}},{unicode:37,advance:.732421875,planeBounds:{left:.026481776289942378,bottom:-.030073418674698794,right:.7137525987100576,top:.7410109186746989},atlasBounds:{left:88.5,bottom:144.5,right:129.5,top:190.5}}
1,{unicode:38,advance:.62158203125,planeBounds:{left:.03225572125458355,bottom:-.030073418674698794,right:.6357130287454166,top:.7410109186746989},atlasBounds:{left:130.5,bottom:144.5,right:166.5,top:190.5}},{unicode:39,advance:.17431640625,planeBounds:{left:.028244602049502358,bottom:.49895501673814824,right:.14558352295049765,top:.7671582645118518},atlasBounds:{left:498.5,bottom:62.5,right:505.5,top:78.5}},{unicode:40,advance:.341796875,planeBounds:{left:.042983329377291775,bottom:-.250029542422407,right:.34471198312270823,top:.8227834486724072},atlasBounds:{left:.5,bottom:191.5,right:18.5,top:255.5}},{unicode:41,advance:.34765625,planeBounds:{left:-.003159248747708225,bottom:-.250029542422407,right:.29856940499770823,top:.8227834486724072},atlasBounds:{left:19.5,bottom:191.5,right:37.5,top:255.5}},{unicode:42,advance:.4306640625,planeBounds:{left:-.011208599684062338,bottom:.27785390031593765,right:.44138438093406235,top:.7304468809340623},atlasBounds:{left:449.5,bottom:23.5,right:476.5,top:50.5}},{unicode:43,advance:.56689453125,planeBounds:{left:.01353503347629649,bottom:.053493525733368255,right:.5499415290237036,top:.6066627242666317},atlasBounds:{left:361.5,bottom:17.5,right:393.5,top:50.5}},{unicode:44,advance:.1962890625,planeBounds:{left:-.009919475797210583,bottom:-.15981695975478,right:.1744702570472106,top:.12514899100478},atlasBounds:{left:498.5,bottom:79.5,right:509.5,top:96.5}},{unicode:45,advance:.27587890625,planeBounds:{left:-.00527594412977999,bottom:.24333249267450235,right:.27969000662978,top:.36067141357549765},atlasBounds:{left:52.5,bottom:7.5,right:69.5,top:14.5}},{unicode:46,advance:.26318359375,planeBounds:{left:.051032680313645884,bottom:-.027092319686354116,right:.20189700718635412,top:.12377200718635412},atlasBounds:{left:501.5,bottom:221.5,right:510.5,top:230.5}},{unicode:47,advance:.412109375,planeBounds:{left:-.013733006073205867,bottom:-.08573505127848349,right:.4053345685732059,top:.7356373950284835},atlasBounds:{left:252.5,bottom:206.5,right:277.5,top:255.5}},{unicode:48,advance:.5615234375,planeBounds:{left:.037458384830081196,bottom:-.030073418674698794,right:.5235767714199189,top:.7410109186746989},atlasBounds:{left:167.5,bottom:144.5,right:196.5,top:190.5}},{unicode:49,advance:.5615234375,planeBounds:{left:.06023674350936354,bottom:-.01998308280677056,right:.37872810024063647,top:.7343385515567705},atlasBounds:{left:488.5,bottom:97.5,right:507.5,top:142.5}},{unicode:50,advance:.5615234375,planeBounds:{left:.025334353719224725,bottom:-.01680925468177056,right:.5449781462807752,top:.7375123796817705},atlasBounds:{left:278.5,bottom:51.5,right:309.5,top:96.5}},{unicode:51,advance:.5615234375,planeBounds:{left:.028181041080081196,bottom:-.030073418674698794,right:.5142994276699189,top:.7410109186746989},atlasBounds:{left:197.5,bottom:144.5,right:226.5,top:190.5}},{unicode:52,advance:.5615234375,planeBounds:{left:.005886103858368255,bottom:-.02169206718177056,right:.5590553023916317,top:.7326295671817705},atlasBounds:{left:310.5,bottom:51.5,right:343.5,top:96.5}},{unicode:53,advance:.5615234375,planeBounds:{left:.055524791080081196,bottom:-.02657487968177056,right:.5416431776699189,top:.7277467546817705},atlasBounds:{left:344.5,bottom:51.5,right:373.5,top:96.5}},{unicode:54,advance:.5615234375,planeBounds:{left:.046003306705081196,bottom:-.034712090549698794,right:.5321216932949189,top:.7363722467996989},atlasBounds:{left:227.5,bottom:144.5,right:256.5,top:190.5}},{unicode:55,advance:.5615234375,planeBounds:{left:.018010134969224725,bottom:-.02169206718177056,right:.5376539275307752,top:.7326295671817705},atlasBounds:{left:374.5,bottom:51.5,right:405.5,top:96.5}},{unicode:56,advance:.5615234375,planeBounds:{left:.037702525455081196,bottom:-.030073418674698794,right:.5238209120449189,top:.7410109186746989},atlasBounds:{left:257.5,bottom:144.5,right:286.5,top:190.5}},{unicode:57,advance:.5615234375,planeBounds:{left:.029401744205081196,bottom:-.025434746799698794,right:.5155201307949189,top:.7456495905496989},atlasBounds:{left:287.5,bottom:144.5,right:316.5,top:190.5}},{unicode:58,advance:.2421875,planeBounds:{left:.046394008438645884,bottom:-.029431286627488215,right:.19725833531135412,top:.5572633178774882},atlasBounds:{left:439.5,bottom:61.5,right:448.5,top:96.5}},{unicode:59,advance:.21142578125,planeBounds:{left:.001066852327789419,bottom:-.16459733294591408,right:.1854565851722106,top:.556198895445914},atlasBounds:{left:406.5,bottom:53.5,right:417.5,top:96.5}},{unicode:60,advance:.50830078125,planeBounds:{left:.016948142433865897,bottom:.0726146348300812,right:.4527784200661341,top:.5587330214199189},atlasBounds:{left:394.5,bottom:21.5,right:420.5,top:50.5}},{unicode:61,advance:.548828125,planeBounds:{left:.051535540940937666,bottom:.17620354038436353,right:.5041285215590624,top:.49469489711563647},atlasBounds:{left:477.5,bottom:31.5,right:504.5,top:50.5}},{unicode:62,advance:.5224609375,planeBounds:{left:.047629290940937666,bottom:.0731029160800812,right:.5002222715590624,top:.5592213026699189},atlasBounds:{left:421.5,bottom:21.5,right:448.5,top:50.5}},{unicode:63,advance:.47216796875,planeBounds:{left:.016704001808865897,bottom:-.027876153049698794,right:.4525342794411341,top:.743208184299
16989},atlasBounds:{left:317.5,bottom:144.5,right:343.5,top:190.5}},{unicode:64,advance:.89794921875,planeBounds:{left:.034064457306783605,bottom:-.23896750384690937,right:.8721996065996072,top:.7165065663469093},atlasBounds:{left:155.5,bottom:198.5,right:205.5,top:255.5}},{unicode:65,advance:.65234375,planeBounds:{left:-.008838044092129387,bottom:-.02169206718177056,right:.6616700753421295,top:.7326295671817705},atlasBounds:{left:237.5,bottom:51.5,right:277.5,top:96.5}},{unicode:66,advance:.62255859375,planeBounds:{left:.06464099434422473,bottom:-.02169206718177056,right:.5842847869057752,top:.7326295671817705},atlasBounds:{left:205.5,bottom:51.5,right:236.5,top:96.5}},{unicode:67,advance:.65087890625,planeBounds:{left:.038439807122511785,bottom:-.030073418674698794,right:.6251344116274882,top:.7410109186746989},atlasBounds:{left:344.5,bottom:144.5,right:379.5,top:190.5}},{unicode:68,advance:.65576171875,planeBounds:{left:.06301501010836826,bottom:-.02169206718177056,right:.6161842086416317,top:.7326295671817705},atlasBounds:{left:162.5,bottom:51.5,right:195.5,top:96.5}},{unicode:69,advance:.568359375,planeBounds:{left:.0652904160800812,bottom:-.02169206718177056,right:.5514088026699189,top:.7326295671817705},atlasBounds:{left:132.5,bottom:51.5,right:161.5,top:96.5}},{unicode:70,advance:.552734375,planeBounds:{left:.059675181705081196,bottom:-.02169206718177056,right:.5457935682949189,top:.7326295671817705},atlasBounds:{left:102.5,bottom:51.5,right:131.5,top:96.5}},{unicode:71,advance:.68115234375,planeBounds:{left:.040148791497511785,bottom:-.030073418674698794,right:.6268433960024882,top:.7410109186746989},atlasBounds:{left:380.5,bottom:144.5,right:415.5,top:190.5}},{unicode:72,advance:.712890625,planeBounds:{left:.062365588372511785,bottom:-.02169206718177056,right:.6490601928774882,top:.7326295671817705},atlasBounds:{left:30.5,bottom:51.5,right:65.5,top:96.5}},{unicode:73,advance:.27197265625,planeBounds:{left:.06917965680657412,bottom:-.02169206718177056,right:.20328128069342588,top:.7326295671817705},atlasBounds:{left:196.5,bottom:51.5,right:204.5,top:96.5}},{unicode:74,advance:.5517578125,planeBounds:{left:.007184947330081194,bottom:-.02657487968177056,right:.4933033339199188,top:.7277467546817705},atlasBounds:{left:.5,bottom:51.5,right:29.5,top:96.5}},{unicode:75,advance:.626953125,planeBounds:{left:.061633166497511785,bottom:-.02169206718177056,right:.6483277710024882,top:.7326295671817705},atlasBounds:{left:452.5,bottom:97.5,right:487.5,top:142.5}},{unicode:76,advance:.5380859375,planeBounds:{left:.06341786132300943,bottom:-.02169206718177056,right:.5327735449269906,top:.7326295671817705},atlasBounds:{left:423.5,bottom:97.5,right:451.5,top:142.5}},{unicode:77,advance:.873046875,planeBounds:{left:.05911847969322944,bottom:-.02169206718177056,right:.8134401140567705,top:.7326295671817705},atlasBounds:{left:377.5,bottom:97.5,right:422.5,top:142.5}},{unicode:78,advance:.712890625,planeBounds:{left:.062365588372511785,bottom:-.02169206718177056,right:.6490601928774882,top:.7326295671817705},atlasBounds:{left:341.5,bottom:97.5,right:376.5,top:142.5}},{unicode:79,advance:.6875,planeBounds:{left:.033395854136655315,bottom:-.030073418674698794,right:.6536158646133446,top:.7410109186746989},atlasBounds:{left:416.5,bottom:144.5,right:453.5,top:190.5}},{unicode:80,advance:.630859375,planeBounds:{left:.061550166358368255,bottom:-.02169206718177056,right:.6147193648916317,top:.7326295671817705},atlasBounds:{left:273.5,bottom:97.5,right:306.5,top:142.5}},{unicode:81,advance:.6875,planeBounds:{left:.030466166636655315,bottom:-.14391866037519643,right:.6506861771133446,top:.7445045978751964},atlasBounds:{left:214.5,bottom:202.5,right:251.5,top:255.5}},{unicode:82,advance:.61572265625,planeBounds:{left:.06350329135836826,bottom:-.02169206718177056,right:.6166724898916317,top:.7326295671817705},atlasBounds:{left:186.5,bottom:97.5,right:219.5,top:142.5}},{unicode:83,advance:.59326171875,planeBounds:{left:.020778681983368255,bottom:-.030073418674698794,right:.5739478805166317,top:.7410109186746989},atlasBounds:{left:454.5,bottom:144.5,right:487.5,top:190.5}},{unicode:84,advance:.5966796875,planeBounds:{left:.005480822747511787,bottom:-.02169206718177056,right:.5921754272524882,top:.7326295671817705},atlasBounds:{left:112.5,bottom:97.5,right:147.5,top:142.5}},{unicode:85,advance:.6484375,planeBounds:{left:.049098994483368255,bottom:-.02657487968177056,right:.6022681930166317,top:.7277467546817705},atlasBounds:{left:78.5,bottom:97.5,right:111.5,top:142.5}},{unicode:86,advance:.63623046875,planeBounds:{left:-.008269192599201152,bottom:-.02169206718177056,right:.6454762238492011,top:.7326295671817705},atlasBounds:{left:38.5,bottom:97.5,right:77.5,top:142.5}},{unicode:87,advance:.88720703125,planeBounds:{left:.011923628617731797,bottom:-.02169206718177056,right:.8835841838822683,to
1p:.7326295671817705},atlasBounds:{left:220.5,bottom:97.5,right:272.5,top:142.5}},{unicode:88,advance:.626953125,planeBounds:{left:.004098979136655316,bottom:-.02169206718177056,right:.6243189896133446,top:.7326295671817705},atlasBounds:{left:.5,bottom:97.5,right:37.5,top:142.5}},{unicode:89,advance:.6005859375,planeBounds:{left:-.010793598988344685,bottom:-.02169206718177056,right:.6094264114883446,top:.7326295671817705},atlasBounds:{left:148.5,bottom:97.5,right:185.5,top:142.5}},{unicode:90,advance:.5986328125,planeBounds:{left:.024196650733368255,bottom:-.02169206718177056,right:.5773658492666317,top:.7326295671817705},atlasBounds:{left:307.5,bottom:97.5,right:340.5,top:142.5}},{unicode:91,advance:.26513671875,planeBounds:{left:.05437250871693295,bottom:-.17280296457569408,right:.27228764753306706,top:.8329592145756942},atlasBounds:{left:59.5,bottom:195.5,right:72.5,top:255.5}},{unicode:92,advance:.41015625,planeBounds:{left:.0014037126767941326,bottom:-.08573505127848349,right:.4204712873232059,top:.7356373950284835},atlasBounds:{left:278.5,bottom:206.5,right:303.5,top:255.5}},{unicode:93,advance:.26513671875,planeBounds:{left:-.020659233400995285,bottom:-.17280296457569408,right:.2140186084009953,top:.8329592145756942},atlasBounds:{left:94.5,bottom:195.5,right:108.5,top:255.5}},{unicode:94,advance:.41796875,planeBounds:{left:.006855376669722368,bottom:.33229482979472236,right:.40916024833027764,top:.7345997014552776},atlasBounds:{left:486.5,bottom:231.5,right:510.5,top:255.5}},{unicode:95,advance:.451171875,planeBounds:{left:-.017473255794918804,bottom:-.09553469482549765,right:.4686451307949188,top:.021804226075497646},atlasBounds:{left:70.5,bottom:7.5,right:99.5,top:14.5}},{unicode:96,advance:.30908203125,planeBounds:{left:.00391839948107648,bottom:.5860277898277895,right:.2553589442689235,top:.7704175226722105},atlasBounds:{left:36.5,bottom:3.5,right:51.5,top:14.5}},{unicode:97,advance:.5439453125,planeBounds:{left:.028181041080081196,bottom:-.029187146002488215,right:.5142994276699189,top:.5575074585024882},atlasBounds:{left:30.5,bottom:15.5,right:59.5,top:50.5}},{unicode:98,advance:.56103515625,planeBounds:{left:.048932994205081196,bottom:-.032187684160555265,right:.5350513807949189,top:.7724220591605554},atlasBounds:{left:304.5,bottom:207.5,right:333.5,top:255.5}},{unicode:99,advance:.5234375,planeBounds:{left:.024518931705081196,bottom:-.029187146002488215,right:.5106373182949189,top:.5575074585024882},atlasBounds:{left:.5,bottom:15.5,right:29.5,top:50.5}},{unicode:100,advance:.56396484375,planeBounds:{left:.026227916080081196,bottom:-.032187684160555265,right:.5123463026699189,top:.7724220591605554},atlasBounds:{left:334.5,bottom:207.5,right:363.5,top:255.5}},{unicode:101,advance:.52978515625,planeBounds:{left:.026472056705081196,bottom:-.029187146002488215,right:.5125904432949189,top:.5575074585024882},atlasBounds:{left:468.5,bottom:61.5,right:497.5,top:96.5}},{unicode:102,advance:.34716796875,planeBounds:{left:.004575110905578838,bottom:-.022177918535555265,right:.3733545765944212,top:.7824318247855554},atlasBounds:{left:364.5,bottom:207.5,right:386.5,top:255.5}},{unicode:103,advance:.56103515625,planeBounds:{left:.026960337955081196,bottom:-.22888445766762702,right:.5130787245449189,top:.558962582667627},atlasBounds:{left:28.5,bottom:143.5,right:57.5,top:190.5}},{unicode:104,advance:.55078125,planeBounds:{left:.049826556565937666,bottom:-.01892352016762703,right:.5024195371840624,top:.768923520167627},atlasBounds:{left:.5,bottom:143.5,right:27.5,top:190.5}},{unicode:105,advance:.24267578125,planeBounds:{left:.046882289688645884,bottom:-.01680925468177056,right:.19774661656135412,top:.7375123796817705},atlasBounds:{left:498.5,bottom:145.5,right:507.5,top:190.5}},{unicode:106,advance:.23876953125,planeBounds:{left:-.048979545900995285,bottom:-.2324562772148376,right:.1856982959009953,top:.7397804959648377},atlasBounds:{left:140.5,bottom:197.5,right:154.5,top:255.5}},{unicode:107,advance:.5068359375,planeBounds:{left:.044294322330081196,bottom:-.01892352016762703,right:.5304127089199189,top:.768923520167627},atlasBounds:{left:58.5,bottom:143.5,right:87.5,top:190.5}},{unicode:108,advance:.24267578125,planeBounds:{left:.05428707868157412,bottom:-.01892352016762703,right:.18838870256842588,top:.768923520167627},atlasBounds:{left:477.5,bottom:208.5,right:485.5,top:255.5}},{unicode:109,advance:.87646484375,planeBounds:{left:.04430890170737297,bottom:-.024304333502488215,right:.832155942042627,top:.5623902710024882},atlasBounds:{left:116.5,bottom:15.5,right:163.5,top:50.5}},{unicode:110,advance:.5517578125,planeBounds:{left:.049826556565937666,bottom:-.024304333502488215,right:.5024195371840624,top:.5623902710024882},atlasBounds:{left:60.5,bottom:15.5,right:87.5,top:50.5}},{unicode:111,advance:.5703125,planeBounds:{left:.025090213094224725,bottom:-.029187146002488215,right:.5447340056557752,top:.5575074585024882},atlasBounds:{left:193.5,bottom:15.5,right:224.5,top:50.5}},{unicode:112,advance:.56103515625,planeBounds:{left:.048444712955081196,bottom:-.22644305141762702,right:.5345630995449189,top:.561403988917627},atlasBounds:{left:447.5,bottom:208.5,right:476.5,top:255.5}},{unicode:113,advance:.568359375,planeBounds:{left:.025983775455081196,bottom:-.22644305141762702,right:.5121021620449189,top:.561403988917627},atlasBounds:{left:417.5,bottom:208.5,right:446.5,top:255.5}},{unicode:114,advance:.33837890625,planeBounds:{left:.045180595002291775,bottom:-.024304333502488215,right:.34690924874770823,top:.5623902710024882},atlasBounds:{left:449.5,bottom:61.5,right:467.5,top:96.5}},{unicode:115,advance:.515625,planeBounds:{left:.021669814448009427,bottom:-.029187146002488215,right:.4910254980519906,top:.5575074585024882},atlasBounds:{left:164.5,bottom:15.5,right:192.5,top:50.5}},{unicode:116,advance:.32666015625,planeBounds:{left:-.019433670483564695,bottom:-.02877457520298586,right:.3158203892335647,top:.675258950202986},atlasBounds:{left:418.5,bottom:54.5,right:438.5,top:96.5}},{unicode:117,advance:.55126953125,planeBounds:{left:.048117572190937666,bottom:-.034069958502488215,right:.5007105528090624,top:.5526246460024882},atlasBounds:{left:88.5,bottom:15.5,right:115.5,top:50.5}},{unicode:118,advance:.484375,planeBounds:{left:-.002092396419918806,bottom:-.02080579450955998,right:.4840259901699188,top:.5491261070095601}
1,atlasBounds:{left:331.5,bottom:16.5,right:360.5,top:50.5}},{unicode:119,advance:.75146484375,planeBounds:{left:-.002649098431770561,bottom:-.02080579450955998,right:.7516725359317705,top:.5491261070095601},atlasBounds:{left:225.5,bottom:16.5,right:270.5,top:50.5}},{unicode:120,advance:.49560546875,planeBounds:{left:-.0046143729128470395,bottom:-.02080579450955998,right:.4982667166628471,top:.5491261070095601},atlasBounds:{left:300.5,bottom:16.5,right:330.5,top:50.5}},{unicode:121,advance:.47314453125,planeBounds:{left:-.007219349544918806,bottom:-.23645281704262702,right:.4788990370449188,top:.551394223292627},atlasBounds:{left:387.5,bottom:208.5,right:416.5,top:255.5}},{unicode:122,advance:.49560546875,planeBounds:{left:.018007705073009427,bottom:-.02080579450955998,right:.4873633886769906,top:.5491261070095601},atlasBounds:{left:271.5,bottom:16.5,right:299.5,top:50.5}},{unicode:123,advance:.33837890625,planeBounds:{left:.011572188891435306,bottom:-.20234398020069408,right:.3468262486085647,top:.8034181989506942},atlasBounds:{left:73.5,bottom:195.5,right:93.5,top:255.5}},{unicode:124,advance:.24365234375,planeBounds:{left:.06315671142450235,bottom:-.15466084787519643,right:.18049563232549765,top:.7337624103751964},atlasBounds:{left:206.5,bottom:202.5,right:213.5,top:255.5}},{unicode:125,advance:.33837890625,planeBounds:{left:-.010156326733564695,bottom:-.20234398020069408,right:.3250977329835647,top:.8034181989506942},atlasBounds:{left:38.5,bottom:195.5,right:58.5,top:255.5}},{unicode:126,advance:.68017578125,planeBounds:{left:.046984728997511785,bottom:.1766063915990047,right:.6336793335024882,top:.4112842334009953},atlasBounds:{left:.5,bottom:.5,right:35.5,top:14.5}}],kerning:[]};function Ee(t,e){new URL(e,window.location.href).origin!==window.location.origin&&(t.crossOrigin="")}var Fe=()=>{const t=new ArrayBuffer(2);return new DataView(t).setInt16(0,256,!0),256===new Int16Array(t)[0]},Be=(t=>(t[t.UNKNOWN=0]="UNKNOWN",t[t.NII=1]="NII",t[t.DCM=2]="DCM",t[t.DCM_MANIFEST=3]="DCM_MANIFEST",t[t.MIH=4]="MIH",t[t.MIF=5]="MIF",t[t.NHDR=6]="NHDR",t[t.NRRD=7]="NRRD",t[t.MHD=8]="MHD",t[t.MHA=9]="MHA",t[t.MGH=10]="MGH",t[t.MGZ=11]="MGZ",t[t.V=12]="V",t[t.V16=13]="V16",t[t.VMR=14]="VMR",t[t.HEAD=15]="HEAD",t[t.DCM_FOLDER=16]="DCM_FOLDER",t[t.SRC=17]="SRC",t[t.FIB=18]="FIB",t[t.BMP=19]="BMP",t[t.ZARR=20]="ZARR",t[t.NPY=21]="NPY",t[t.NPZ=22]="NPZ",t[t.HDR=23]="HDR",t))(Be||{}),Ve=Object.freeze({...Be,parse:t=>{let e=0;switch(t.toUpperCase()){case"":case"DCM":e=2;break;case"TXT":e=3;break;case"FZ":case"GQI":case"QSDR":case"FIB":e=18;break;case"HDR":case"NII":e=1;break;case"MIH":e=4;break;case"MIF":e=5;break;case"NHDR":e=6;break;case"NRRD":e=7;break;case"MHD":e=8;break;case"MHA":e=9;break;case"MGH":e=10;break;case"MGZ":e=11;break;case"NPY":e=21;break;case"NPZ":e=22;break;case"SRC":e=17;break;case"V":e=12;break;case"V16":e=13;break;case"VMR":e=14;break;case"HEAD":e=15;break;case"PNG":case"BMP":case"GIF":case"JPG":case"JPEG":e=19;break;case"ZARR":e=20}return e}}),Ue=function(t,e,i,n,r,a,s,o,l,c,h,d,u,m,f,g,A,p,v){return void 0===e&&(e=""),void 0===i&&(i=""),void 0===n&&(n="gray"),void 0===r&&(r=1),void 0===a&&(a=NaN),void 0===s&&(s=NaN),void 0===o&&(o=!0),void 0===l&&(l=.02),void 0===c&&(c=!1),void 0===h&&(h=!1),void 0===d&&(d=""),void 0===u&&(u=0),void 0===m&&(m=Ve.UNKNOWN),void 0===f&&(f=NaN),void 0===g&&(g=NaN),void 0===A&&(A=!0),void 0===p&&(p=!1),void 0===v&&(v=null),{url:t,urlImageData:e,name:i,colormap:n,colorMap:n,opacity:r,cal_min:a,cal_max:s,trustCalMinMax:o,percentileFrac:l,ignoreZeroVoxels:c,useQFormNotSForm:h,colormapNegative:d,imageType:m,cal_minNeg:f,cal_maxNeg:g,colorbarVisible:A,frame4D:u,alphaThreshold:p,colormapLabel:v}};function Re(t,e){void 0===e&&(e=80),t=t.replace(/[`$]/g,"");const i=[],n=Math.min(e,t.length);for(let r=0;r<n;r++){const e=t.charCodeAt(r);i.push(255&e)}return i}function Pe(t,e,i){void 0===e&&(e=!1),void 0===i&&(i=!1);let n=!0;i&&(n=t.littleEndian);const r=new Uint8Array(348),a=new DataView(r.buffer);a.setInt32(0,348,n),a.setUint8(38,114),a.setUint8(39,t.dim_info);for(let o=0;o<8;o++)a.setUint16(40+2*o,t.dims[o],n);a.setFloat32(56,t.intent_p1,n),a.setFloat32(60,t.intent_p2,n),a.setFloat32(64,t.intent_p3,n),a.setInt16(68,t.intent_code,n),e?(a.setInt16(70,2,n),a.setInt16(72,8,n)):(a.setInt16(70,t.datatypeCode,n),a.setInt16(72,t.numBitsPerVoxel,n)),a.setInt16(74,t.slice_start,n);for(let o=0;o<8;o++)a.setFloat32(76+4*o,t.pixDims[o],n);e?(a.setFloat32(108,352,n),a.setFloat32(112,1,n),a.setFloat32(116,0,n)):(a.setFloat32(108,t.vox_offset,n),a.setFloat32(112,t.scl_slope,n),a.setFloat32(116,t.scl_inter,n
1)),a.setInt16(120,t.slice_end,n),a.setUint8(122,t.slice_code),0===t.xyzt_units?a.setUint8(123,10):a.setUint8(123,t.xyzt_units),e?(a.setFloat32(124,0,n),a.setFloat32(128,0,n)):(a.setFloat32(124,t.cal_max,n),a.setFloat32(128,t.cal_min,n)),a.setFloat32(132,t.slice_duration,n),a.setFloat32(136,t.toffset,n),r.set(Re(t.description),148),r.set(Re(t.aux_file),228),a.setInt16(252,t.qform_code,n),t.sform_code<1||t.sform_code<1?a.setInt16(254,1,n):a.setInt16(254,t.sform_code,n),a.setFloat32(256,t.quatern_b,n),a.setFloat32(260,t.quatern_c,n),a.setFloat32(264,t.quatern_d,n),a.setFloat32(268,t.qoffset_x,n),a.setFloat32(272,t.qoffset_y,n),a.setFloat32(276,t.qoffset_z,n);const s=t.affine.flat();for(let o=0;o<12;o++)a.setFloat32(280+4*o,s[o],n);return a.setInt32(344,3222382,!0),r}function Ne(t){const e=[!1,!1,!1,!1],i=[!1,!1,!1,!1];for(let n=0;n<4;n++)for(let e=0;e<4;e++)if(isNaN(t[n][e]))return!1;for(let n=0;n<3;n++)for(let r=0;r<3;r++)0!==t[n][r]&&(e[n]=!0,i[r]=!0);for(let n=0;n<3;n++){if(!e[n])return!1;if(!i[n])return!1}return!0}async function Le(t){const e=t.getReader(),{done:i,value:n}=await e.read();if(i)return e.releaseLock(),new ReadableStream({start(t){t.close()}});if(!n||n.length<2)return e.releaseLock(),new ReadableStream({start(t){n&&t.enqueue(n),t.close()}});const r=31===n[0]&&139===n[1],a=new ReadableStream({async start(t){try{for(t.enqueue(n);;){const{done:i,value:n}=await e.read();if(i){t.close(),e.releaseLock();break}t.enqueue(n)}}catch(i){t.error(i),e.releaseLock()}}});return r?a.pipeThrough(new DecompressionStream("gzip")):a}function ke(t,e,i,n){void 0===t&&(t=[256,256,256]),void 0===e&&(e=[1,1,1]),void 0===i&&(i=[1,0,0,-128,0,1,0,-128,0,0,1,-128,0,0,0,1]),void 0===n&&(n=2);const r=new h.a;r.littleEndian=!0,r.dims=[3,1,1,1,0,0,0,0],r.dims[0]=Math.max(3,t.length);for(let s=0;s<t.length;s++)r.dims[s+1]=t[s];r.pixDims=[1,1,1,1,1,0,0,0];for(let s=0;s<t.length;s++)r.pixDims[s+1]=e[s];if(16===i.length){let t=0;for(let e=0;e<4;e++)for(let n=0;n<4;n++)r.affine[e][n]=i[t],t++}let a=8;return 256===n||2===n?a=8:512===n||4===n?a=16:16===n||768===n||8===n||2304===n?a=32:64===n?a=64:Q.warn("Unsupported NIfTI datatypeCode for header creation: "+n),r.datatypeCode=n,r.numBitsPerVoxel=a,r.scl_inter=0,r.scl_slope=1,r.sform_code=2,r.magic="n+1",r.vox_offset=352,r}function Oe(t,e){if(void 0===e&&(e=null),!t.hdr)throw new Error("NVImage header is not defined for toUint8Array");if(!t.img&&null===e)throw new Error("NVImage image data is not defined for toUint8Array");const i=null!==e,n=JSON.parse(JSON.stringify(t.hdr)),r=t.extensions&&t.extensions.length>0,a=new Uint8Array(4);a[0]=r?1:0;let s=new Uint8Array(0);if(r){const e=[];let i=0;for(const r of t.extensions){const t=new Uint8Array(r.edata),n=new Uint8Array(8+t.length),a=new DataView(n.buffer);a.setInt32(0,r.esize,!0),a.setInt32(4,r.ecode,!0),n.set(t,8),e.push(n),i+=n.length}s=new Uint8Array(i);let n=0;for(const t of e)s.set(t,n),n+=t.length}n.vox_offset=Math.max(352,348+a.length+s.length),i&&(n.datatypeCode=2,n.numBitsPerVoxel=8,n.scl_slope=1,n.scl_inter=0);const o=Pe(n,i);let l;if(i){const i=e,n=t.permRAS;if(!n||1===n[0]&&2===n[1]&&3===n[2])l=i;else{Q.debug("Reorienting drawing bytes back to native space for saving...");const e=t.hdr.dims,n=e[1]*e[2]*e[3],r=t.dimsRAS?t.dimsRAS[1]*t.dimsRAS[2]*t.dimsRAS[3]:n;if(i.length!==r)console.warn(`Drawing length (${i.length}) does not match expected RAS voxel count (${r}). Cannot reorient drawing reliably.`),l=i;else if(t.img2RASstep&&t.img2RASstart&&t.dimsRAS){const e=t.img2RASstep,r=t.img2RASstart,a=t.dimsRAS,s=new Uint8Array(n);s.fill(0);const o=i;let c=0;for(let t=0;t<a[3];t++){const i=r[2]+t*e[2];for(let t=0;t<a[2];t++){const l=r[1]+t*e[1];for(let t=0;t<a[1];t++){const a=r[0]+t*e[0]+l+i;a>=0&&a<n?s[a]=o[c]:c<o.length&&console.warn(`Calculated native index ${a} is out of bounds [0..${n-1}] during drawing reorientation.`),c++}}}l=s}else console.warn("Missing RAS transformation info (img2RASstep, img2RASstart, dimsRAS). Cannot reorient drawing reliably."),l=i}}else{if(!t.img)throw new Error("NVImage image data is null when trying to save non-drawing.");l=new Uint8Array(t.img.buffer,t.img.byteOffset,t.img.byteLength)}const c=o.length+a.length+s.length,h=Math.max(0,n.vox_offset-c),d=new Uint8Array(h),u=n.vox_offset+l.length,m=new Uint8Array(u);let f=0;return m.set(o,f),f+=o.length,m.set(a,f),f+=a.length,m.set(s,f),f+=s.length,m.set(d,f),f+=d.length,m.set(l,n.vox_offset),m}async function ze(t,e,i){void 0===i&&(i=null);const n=Oe(t,i);if(!e.toLowerCase().endsWith(".gz"))return n;try{const t=await ye.compress(n,"gzip");return new Uint8Array(t)}catch(r){return Q.error("Compression failed:",r),Q.warn("Returning uncompressed data due to compression error."),n}}function Ye(t,e,i,r,a,s){if(void 0===a&&(a=0),void 0===s&&(s=!1),!t.hdr)throw new Error("getValue: NVImage header is not defined.");if(!s&&!t.img)throw new Error("getValue: NVImage image data is not defined.");if(s&&!t.imaginary)return Q.warn("getValue: Attempted to read imaginary data, but none exists."),[0];const o=t.hdr.dims[1],l=t.hdr.dims[2],c=t.hdr.dims[3],h=t.permRAS.slice();if(1!==h[0]||2!==h[1]||3!==h[2]){const a=n.fA(e,i,r,1);n.Z0(a,a,t.toRASvox),e=a[0],i=a[1],r=a[2]}e=Math.max(0,Math.min(Math.round(e),o-1)),i=Math.max(0,Math.min(Math.round(i),l-1)),r=Math.max(0,Math.min(Math.round(r),c-1)),a=Math.max(0,a);let d=e+i*o+r*o*l;if(2304===t.hdr.datatypeCode)return t.img?(d*=4,d+3>=t.img.length?(Q.warn(`getValue: Calculated index ${d} out of bounds for RGBA data.`),[0]):[t.img[d],t.img[d+1],t.img[d+2],t.img[d+3]]):[0];if(128===t.hdr.datatypeCode)return t.img?(d*=3,d+2>=t.img.length?(Q.warn(`getValue: Calculated index ${d} out of bounds for RGB data.`),[0]):[t.img[d],t.img[d+1],t.img[d+2]]):[0];const u=d+a*(o*l*c),m=s?t.imaginary:t.img;if(u<0||u>=m.length)return[0];const f=m[u];
1return[(isNaN(t.hdr.scl_slope)||0===t.hdr.scl_slope?1:t.hdr.scl_slope)*f+(isNaN(t.hdr.scl_inter)?0:t.hdr.scl_inter)]}var Ge={};function We(t,e){const i=a.o8(e);a.mg(i,i);const s=n.fA(t[0],t[1],t[2],1);n.Z0(s,s,i);return r.fA(s[0],s[1],s[2])}async function Xe(t,e,i){t.hdr=new h.a;const n=t.hdr;n.dims[0]=3,n.pixDims=[1,1,1,1,1,0,0,0];let s=[0,0,0],o=[0,0,0],l=[1,1,1];const c=(new TextDecoder).decode(e).split(/\r?\n/),u=(e.byteLength+8)%16,m=e.byteLength+(16-u);Q.debug(e.byteLength,"len",m);const f=new ArrayBuffer(m);new Uint8Array(f).set(new Uint8Array(e));const g=new d.s(m+8,42,f,!0);n.addExtension(g),n.extensionCode=42,n.extensionFlag[0]=1,n.extensionSize=m+8;const A=c.length;let p=0,v=!1;for(;p<A;){let t=c[p];if(p++,!t.startsWith("type"))continue;const e=t.includes("integer-attribute"),i=t.includes("float-attribute");if(t=c[p],p++,!t.startsWith("name"))continue;let r=t.split("= ");const a=r[1];t=c[p],p++,r=t.split("= ");let h=parseInt(r[1]);if(!(h<1)){if(t=c[p],p++,r=t.trim().split(/\s+/),i||e){for(;r.length<h;){t=c[p],p++;const e=t.trim().split(/\s+/);r.push(...e)}for(let t=0;t<h;t++)r[t]=parseFloat(r[t])}switch(a){case"BYTEORDER_STRING":r[0].includes("LSB_FIRST")?n.littleEndian=!0:r[0].includes("MSB_FIRST")&&(n.littleEndian=!1);break;case"BRICK_TYPES":{n.dims[4]=h;const t=parseInt(r[0]);0===t?(n.numBitsPerVoxel=8,n.datatypeCode=2):1===t?(n.numBitsPerVoxel=16,n.datatypeCode=4):3===t?(n.numBitsPerVoxel=32,n.datatypeCode=16):Q.warn("Unknown BRICK_TYPES ",t)}break;case"IJK_TO_DICOM_REAL":if(h<12)break;v=!0,n.sform_code=2,n.affine=[[-r[0],-r[1],-r[2],-r[3]],[-r[4],-r[5],-r[6],-r[7]],[r[8],r[9],r[10],r[11]],[0,0,0,1]];break;case"DATASET_DIMENSIONS":h=Math.max(h,3);for(let t=0;t<h;t++)n.dims[t+1]=r[t];break;case"ORIENT_SPECIFIC":s=r;break;case"ORIGIN":o=r;break;case"DELTA":l=r;break;case"TAXIS_FLOATS":n.pixDims[4]=r[0];break;default:Q.warn("Unknown:",a)}}}v?function(t){if(!t.hdr)throw new Error("hdr not defined");const e=t.hdr.affine,i=a.fA(e[0][0],e[0][1],e[0][2],e[0][3],e[1][0],e[1][1],e[1][2],e[1][3],e[2][0],e[2][1],e[2][2],e[2][3],e[3][0],e[3][1],e[3][2],e[3][3]),n=We([0,0,0],i),s=We([1,0,0],i);r.Re(s,s,n);const o=We([0,1,0],i);r.Re(o,o,n);const l=We([0,0,1],i);r.Re(l,l,n),t.hdr.pixDims[1]=r.Bw(s),t.hdr.pixDims[2]=r.Bw(o),t.hdr.pixDims[3]=r.Bw(l)}(t):function(t,e,i,n){const r=t.hdr;if(null===r)throw new Error("HDR is not set");r.sform_code=2;const a="xxyyzzg";let s=-1,o=-1,l=-1;const c=["x","y","z"];c[0]=a[n[0]],c[1]=a[n[1]],c[2]=a[n[2]];const h=e.slice(0,3),d=i.slice(0,3);for(let u=0;u<3;u++)"x"===c[u]?s=u:"y"===c[u]?o=u:l=u;s<0||o<0||l<0||s!==o&&s!==l&&o!==l&&(r.pixDims[1]=Math.abs(h[0]),r.pixDims[2]=Math.abs(h[1]),r.pixDims[3]=Math.abs(h[2]),r.affine=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],r.affine[0][s]=-h[s],r.affine[1][o]=-h[o],r.affine[2][l]=h[l],r.affine[0][3]=-d[s],r.affine[1][3]=-d[o],r.affine[2][3]=d[l])}(t,l,o,s);const x=n.numBitsPerVoxel/8*n.dims[1]*n.dims[2]*n.dims[3]*n.dims[4];if(!i)throw new Error("pairedImgData not set");return i.byteLength<x?await ye.decompressToBuffer(new Uint8Array(i)):i.slice(0)}b(Ge,{readHEAD:()=>Xe});var Ke={};function He(t,e){t.hdr=new h.a;const i=t.hdr;i.dims=[3,1,1,1,0,0,0,0],i.pixDims=[1,1,1,1,1,0,0,0];const n=new DataView(e);i.dims[1]=n.getUint16(0,!0),i.dims[2]=n.getUint16(2,!0),i.dims[3]=n.getUint16(4,!0);return 2*i.dims[1]*i.dims[2]*i.dims[3]+6!==e.byteLength&&Q.warn("This does not look like a valid BrainVoyager V16 file"),i.numBitsPerVoxel=16,i.datatypeCode=512,Q.warn("Warning: V16 files have no spatial transforms"),i.affine=[[0,0,-i.pixDims[1],.5*(i.dims[1]-2)*i.pixDims[1]],[-i.pixDims[2],0,0,.5*(i.dims[2]-2)*i.pixDims[2]],[0,-i.pixDims[3],0,.5*(i.dims[3]-2)*i.pixDims[3]],[0,0,0,1]],i.littleEndian=!0,e.slice(6)}function Qe(t,e){t.hdr=new h.a;const i=t.hdr;i.dims=[3,1,1,1,0,0,0,0],i.pixDims=[1,1,1,1,1,0,0,0];const n=new DataView(e),r=n.getUint16(0,!0);4!==r&&Q.warn("Not a valid version 4 VMR image"),i.dims[1]=n.getUint16(2,!0),i.dims[2]=n.getUint16(4,!0),i.dims[3]=n.getUint16(6,!0);const a=i.dims[1]*i.dims[2]*i.dims[3];if(r>=4){let t=8+a;const r=n.getUint32(t+88,!0);if(t+=92,r>0){const i=e.byteLength;for(let e=0;e<r;e++){for(;t<i&&0!==n.getUint8(t);)t++;for(t++,t+=4;t<i&&0!==n.getUint8(t);)t++;t++;const e=n.getUint32(t,!0);t+=4;for(let i=0;i<e;i++)t+=4}}i.pixDims[1]=n.getFloat32(t+2,!0),i.pixDims[2]=n.getFloat32(t+6,!0),i.pixDims[3]=n.getFloat32(t+10,!0)}return Q.warn("Warning: VMR spatial transform not implemented"),i.affine=[[0,0,-i.pixDims[1],.5*(i.dims[1]-2)*i.pixDims[1]],[-i.pixDims[2],0,0,.5*(i.dims[2]-2)*i.pixDims[2]],[0,-i.pixDims[3],0,.5*(i.dims[3]-2)*i.pixDims[3]],[0,0,0,1]],Q.debug(i),i.numBitsPerVoxel=8,i.datatypeCode=2,e.slice(8,8+a)}b(Ke,{readV16:()=>He,readVMR:()=>Qe});var qe={};async function Ze(t,e){t.hdr=new h.a;const i=t.hdr;i.littleEndian=!1,i.dims=[3,1,1,1,0,0,0,0],i.pixDims=[1,1,1,1,1,0,0,0];const n=await ye.readMatV4(e,!0);if(!("dimension"in n)||!("dti_fa"in n))throw new Error("Not a valid DSIstudio FIB file");const r="index0"in n&&"index1"in n&&"index2"in n&&"odf_vertices"in n;i.numBitsPerVoxel=32,i.datatypeCode=16,i.dims[1]=n.dimension[0],i.dims[2]=n.dimension[1],i.dims[3]=n.dimension[2],i.dims[4]=1,i.pixDims[1]=n.voxel_size[0],i.pixDims[2]=n.voxel_size[1],i.pixDims[3]=n.voxel_size[2],i.sform_code=1;const a=.5*(i.dims[1]-1)*i.pixDims[1],s=.5*(i.dims[2]-1)*i.pixDims[2],o=.5*(i.dims[3]-1)*i.pixDims[3];i.affine=[[i.pixDims[1],0,0,-a],[0,-i.pixDims[2],0,s],[0,0,i.pixDims[2],-o],[0,0,0,1]],i.littleEndian=!0;const l=i.dims[1]*i.dims[2]*i.dims[3],c=l*Math.ceil(i.numBitsPerVoxel/8),d=c*i.dims[4],u=new Uint8Array(new ArrayBuffer(4*l*3));if(r){const t=i.dims[1]*i.dims[2]*i.dims[3],e=new Float32Array(t),r=new Float32Array(t),a=new Float32Array(t),s=n.index0,o=n.odf_vertices;for(let i=0;i<t;i++){const t=3*s[i];e[i]=o[t+0],r[i]=o[t+1],a[i]=-o[t+2]}u.set(new Uint8Array(e.buffer,e.byteOffset,e.byteLength),0*c),u.set(new Uint8Array(r.buffer,r.byteOffset,r.byteLength),1*c),u.set(new Uint8Array(a.buffer,a.byteOffset,a.byteLength),2*c)}"report"in n&&(i.description=(new TextDecoder).decode(n.report.subarray(0,Math.min(79,n.report.byteLength))));const m=new Uint8Array(new ArrayBuffer(d)),f=Float32Array.from(n.dti_fa);if("mask"in n){let t=1;"dti_fa_slope"in n&&(t=n.dti_fa_slope[0]);let e=1;"dti_fa_inter"in n&&(e=n.dti_fa_inter[0]);const r=i.dims[1]*i.dims[2]*i.dims[3],a=n.mask,s=new Float32Array(r);let o=0;for(let i=0;i<r;i++)0!==a[i]&&(s[i]=f[o]*t+e,o++);return[s.buffer,new Float32Array(u.buffer)]}const g=new Uint8Array(f.buffer,f.byteOffset,f.byteLength);return m.set(g,0),[m.buffer,new Float32Array(u.buffer)]}async function je(t,e){t.hdr=new h.a;const i=t.hdr;i.littleEndian=!1,i.dims=[3,1,1,1,0,0,0,0],i.pixDims=[1,1,1,1,1,0,0,0];const n=await ye.readMatV4(e);if(!("dimension"in n)||!("image0"in n))throw new Error("Not a valid DSIstudio SRC file");let r=0,a=0;for(const[h,f]of Object.entries(n))if(h.startsWith("image")){if(0===r?a=f.length:a!==f.length&&(a=-1),f.constructor!==Uint16Array)throw new Error("DSIstudio SRC files always use Uint16 datatype");r++}if(a<1||r<1)throw new Error("SRC file not valid DSI Studio data. The image(s) should have the same length");i.numBitsPerVoxel=16,i.datatypeCode=512,i.dims[1]=n.dimension[0],i.dims[2]=n.dimension[1],i.dims[3]=n.dimension[2],i.dims[4]=r,i.dims[4]>
11&&(i.dims[0]=4),i.pixDims[1]=n.voxel_size[0],i.pixDims[2]=n.voxel_size[1],i.pixDims[3]=n.voxel_size[2],i.sform_code=1;const s=.5*(i.dims[1]-1)*i.pixDims[1],o=.5*(i.dims[2]-1)*i.pixDims[2],l=.5*(i.dims[3]-1)*i.pixDims[3];i.affine=[[i.pixDims[1],0,0,-s],[0,-i.pixDims[2],0,o],[0,0,i.pixDims[2],-l],[0,0,0,1]],i.littleEndian=!0;const c=i.dims[1]*i.dims[2]*i.dims[3]*(i.numBitsPerVoxel/8),d=c*i.dims[4],u=new Uint8Array(new ArrayBuffer(d));let m=0;for(let h=0;h<r;h++){const t=n[`image${h}`],e=new Uint8Array(t.buffer,t.byteOffset,t.byteLength);u.set(e,m),m+=c}return"report"in n&&(i.description=(new TextDecoder).decode(n.report.subarray(0,Math.min(79,n.report.byteLength)))),u.buffer}b(qe,{readFIB:()=>Ze,readSRC:()=>je});var Je={};function _e(t,e){t.hdr=new h.a;const i=t.hdr;i.dims=[3,1,1,1,0,0,0,0],i.pixDims=[1,1,1,1,1,0,0,0];const n=new DataView(e),r=n.getInt32(0,!1),a=n.getInt16(50,!1);if(1296127058!==r||a<1||a>14)throw new Error("Not a valid ECAT file");let s=512,o=0;const l=[];let c=new Float32Array;for(;;){if(n.getInt32(s,!1)+n.getInt32(s+12,!1)!==31)break;let t=s+20,e=0,r=0;for(;e<31&&(r=n.getInt32(t,!1),t+=16,0!==r);){e++;let t=512*r;const a=t-512,s=n.getUint16(a,!1);i.dims[1]=n.getUint16(a+4,!1),i.dims[2]=n.getUint16(a+6,!1),i.dims[3]=n.getUint16(a+8,!1);const h=n.getFloat32(a+26,!1);i.pixDims[1]=10*n.getFloat32(a+34,!1),i.pixDims[2]=10*n.getFloat32(a+38,!1),i.pixDims[3]=10*n.getFloat32(a+42,!1),i.pixDims[4]=n.getUint32(a+46,!1)/1e3,l.push(i.pixDims[4]);const d=i.dims[1]*i.dims[2]*i.dims[3],u=new Float32Array(d);if(1===s)for(let e=0;e<d;e++)u[e]=n.getUint8(t)*h,t++;else if(6===s)for(let e=0;e<d;e++)u[e]=n.getUint16(t,!1)*h,t+=2;else if(7===s)for(let e=0;e<d;e++)u[e]=n.getUint32(t,!1)*h,t+=4;else Q.warn("Unknown ECAT data type "+s);const m=c.slice(0);c=new Float32Array(m.length+u.length),c.set(m),c.set(u,m.length),o++}if(0===r)break;s+=512}if(i.dims[4]=o,i.pixDims[4]=l[0],o>1){i.dims[0]=4;let t=!1;for(let e=0;e<o;e++)l[e]!==l[0]&&(t=!0);t&&Q.warn("Frame durations vary")}return i.sform_code=1,i.affine=[[-i.pixDims[1],0,0,.5*(i.dims[1]-2)*i.pixDims[1]],[0,-i.pixDims[2],0,.5*(i.dims[2]-2)*i.pixDims[2]],[0,0,-i.pixDims[3],.5*(i.dims[3]-2)*i.pixDims[3]],[0,0,0,1]],i.numBitsPerVoxel=32,i.datatypeCode=16,c.buffer}b(Je,{readECAT:()=>_e});var $e={};async function ti(t){return new Promise(((e,i)=>{const n=new Blob([t]),r=URL.createObjectURL(n),a=new Image;a.crossOrigin="Anonymous",a.src=r,a.onload=()=>{URL.revokeObjectURL(r);const t=document.createElement("canvas");t.width=a.width,t.height=a.height;const n=t.getContext("2d");n?(n.drawImage(a,0,0),e(n.getImageData(0,0,a.width,a.height))):i(new Error("Failed to get 2D context"))},a.onerror=t=>{URL.revokeObjectURL(r),i(t)}}))}async function ei(t,e){const i=await ti(e),{width:n,height:r,data:a}=i;t.hdr=new h.a;const s=t.hdr;s.dims=[3,n,r,1,0,0,0,0],s.pixDims=[1,1,1,1,1,0,0,0],s.affine=[[s.pixDims[1],0,0,.5*-(s.dims[1]-2)*s.pixDims[1]],[0,-s.pixDims[2],0,.5*(s.dims[2]-2)*s.pixDims[2]],[0,0,-s.pixDims[3],.5*(s.dims[3]-2)*s.pixDims[3]],[0,0,0,1]],s.numBitsPerVoxel=8,s.datatypeCode=2304;let o=!0;for(let l=0;l<a.length;l+=4)if(a[l]!==a[l+1]||a[l]!==a[l+2]){o=!1;break}if(o){s.datatypeCode=2;const t=new Uint8Array(n*r);for(let e=0,i=0;e<a.length;e+=4,i++)t[i]=a[e];return t.buffer}return a.buffer}b($e,{imageDataFromArrayBuffer:()=>ti,readBMP:()=>ei});var ii={};async function ni(t,e,i){const n=e.byteLength;if(n<20)throw new Error("File too small to be VTK: bytes = "+e.byteLength);const a=new Uint8Array(e);let s=0;function o(t){return 10===t||13===t}function l(){for(;s<n&&o(a[s]);)s++;const t=s;for(;s<n&&!o(a[s]);)s++;return s-t<2?"":(new TextDecoder).decode(e.slice(t,s))}let c=l();t.hdr=new h.a;const d=t.hdr;d.pixDims=[1,1,1,1,1,0,0,0],d.dims=[1,1,1,1,1,1,1,1],d.littleEndian=!0;let m=!1,f=!1;const g=u.fA(NaN,0,0,0,1,0,0,0,1),A=r.fA(0,0,0);for(;""!==c;){let t=c.split(" ");if(t.length>2&&(t=t.slice(2)),c.startsWith("BinaryDataByteOrderMSB")&&t[0].includes("False")&&(d.littleEndian=!0),c.startsWith("BinaryDataByteOrderMSB")&&t[0].includes("True")&&(d.littleEndian=!1),c.startsWith("CompressedData")&&t[0].includes("True")&&(m=!0),c.startsWith("TransformMatrix"))for(let e=0;e<9;e++)g[e]=parseFloat(t[e]);if(c.startsWith("Offset"))for(let e=0;e<Math.min(t.length,3);e++)A[e]=parseFloat(t[e]);if(c.startsWith("ElementSpacing"))for(let e=0;e<t.length;e++)d.pixDims[e+1]=parseFloat(t[e]);if(c.startsWith("DimSize")){d.dims[0]=t.length;for(let e=0;e<t.length;e++)d.dims[e+1]=parseInt(t[e])}if(c.startsWith("ElementType"))switch(t[0]){case"MET_UCHAR":d.numBitsPerVoxel=8,d.datatypeCode=2;break;case"MET_CHAR":d.numBitsPerVoxel=8,d.datatypeCode=256;break;case"MET_SHORT":d.numBitsPerVoxel=16,d.datatypeCode=4;break;case"MET_USHORT":d.numBitsPerVoxel=16,d.datatypeCode=512;break;case"MET_INT":d.numBitsPerVoxel=32,d.datatypeCode=8;break;case"MET_UINT":d.numBitsPerVoxel=32,d.datatypeCode=768;break;case"MET_FLOAT":d.numBitsPerVoxel=32,d.datatypeCode=16;break;case"MET_DOUBLE":d.numBitsPerVoxel=64,d.datatypeCode=64;break;default:throw new Error("Unsupported MHA data type: "+t[0])}if(c.startsWith("ObjectType")&&!t[0].includes("Image")&&Q.warn("Only able to read ObjectType = Image, not "+c),c.startsWith("ElementDataFile")){"LOCAL"!==t[0]&&(f=!0);break}c=l()}const p=u.fA(d.pixDims[1],0,0,0,d.pixDims[2],0,0,0,d.pixDims[3]);for(u.lw(g,g,p),d.affine=[[-g[0],-g[3],-g[6],-A[0]],[-g[1],-g[4],-g[7],-A[1]],[g[2],g[5],g[8],A[2]],[0,0,0,1]];10===a[s];)s++;return d.vox_offset=s,f&&i?m?await ye.decompressToBuffer(new Uint8Array(i.slice(0))):i.slice(0):m?await ye.decompressToBuffer(new Uint8Array(e.slice(d.vox_offset))):e.slice(d.vox_offset)}b(ii,{readMHA:()=>ni});var ri={};function ai(t,e,i,n){void 0===n&&(n=1);const r=e+i;let a=e;const s=[];for(;a+12<=r;){const e=t.getInt32(a,!1),i=t.getInt32(a+8,!1);if(a+=12,i<=0||a+i>r)break;
1if(e!==n){a+=i;continue}let o=i,l=a;if(1===n){if(a+4>r)break;o=t.getInt32(a,!1),l+=4}if(o>1&&l+o<=r){const e=new Uint8Array(t.buffer,l,o),i=new TextDecoder("utf-8").decode(e.slice(0,-1));s.push(i)}a+=i}return s.join("\n\n")}function si(t,e){if(t.intent_code=1002,16!==t.datatypeCode&&8!==t.datatypeCode)return e;let i=new Float32Array(e);if(8===t.datatypeCode&&(i=new Int32Array(e)),Fe()){const t=new Uint32Array(e);for(let e=0;e<t.length;e++){const i=t[e];t[e]=(255&i)<<24|(65280&i)<<8|(16711680&i)>>>8|(4278190080&i)>>>24}}t.littleEndian=Fe();let n=!0,r=1/0,a=-1/0;for(let s=0;s<i.length;s++){const t=i[s];Number.isFinite(t)&&(Number.isInteger(t)||(n=!1),t<r&&(r=t),t>a&&(a=t))}if(!n||r<0||a>2147483647)return Q.warn(`FreeSurfer Labels must be integers in INT32 range. range ${r}..${a}`),e;if(a>32767){t.datatypeCode=8;const e=new Int32Array(i.length);for(let t=0;t<i.length;t++)e[t]=Math.trunc(i[t]);return e.buffer}if(a>255){t.datatypeCode=4,t.numBitsPerVoxel=16;const e=new Int16Array(i.length);for(let t=0;t<i.length;t++)e[t]=Math.trunc(i[t]);return e.buffer}{t.datatypeCode=2,t.numBitsPerVoxel=8;const e=new Uint8Array(i.length);for(let t=0;t<i.length;t++)e[t]=Math.trunc(i[t]);return e.buffer}}function oi(t,e,i){const n=t.byteLength-e.vox_offset;if(n<i)return Q.error(`MGH image data size mismatch: expected ${i}, found ${n}`),!1;if(n===i)return!1;const r=e.vox_offset+i+20,a=t.byteLength-r;if(a<=12)return!1;if(ai(new DataView(t),r,a).toLowerCase().endsWith("lut.txt"))return!0;return ai(new DataView(t),r,a,3).includes("mri_label2vol")}async function li(t,e,i){void 0===i&&(i=""),t.hdr||(Q.debug("readMgh called before nvImage.hdr was initialized. Creating default."),t.hdr=new h.a);const n=t.hdr;n.littleEndian=!1;let r=e,s=new DataView(r);if(r.byteLength>=2&&31===s.getUint8(0)&&139===s.getUint8(1))try{r=await ye.decompressToBuffer(new Uint8Array(e)),s=new DataView(r)}catch(N){return Q.error("Failed to decompress MGZ file.",N),null}if(r.byteLength<284)return Q.error("File too small to be a valid MGH/MGZ header."),null;const o=s.getInt32(0,!1),l=s.getInt32(4,!1),c=s.getInt32(8,!1),d=s.getInt32(12,!1),u=s.getInt32(16,!1),m=s.getInt32(20,!1),f=s.getFloat32(30,!1),g=s.getFloat32(34,!1),A=s.getFloat32(38,!1),p=s.getFloat32(42,!1),v=s.getFloat32(46,!1),x=s.getFloat32(50,!1),w=s.getFloat32(54,!1),y=s.getFloat32(58,!1),b=s.getFloat32(62,!1),C=s.getFloat32(66,!1),M=s.getFloat32(70,!1),D=s.getFloat32(74,!1),T=s.getFloat32(78,!1),I=s.getFloat32(82,!1),S=s.getFloat32(86,!1);if(1!==o&&257!==o&&Q.warn(`Unexpected MGH version: ${o}.`),l<=0||c<=0||d<=0)return Q.error(`Invalid MGH dimensions: ${l}x${c}x${d}`),null;switch(m){case 0:n.numBitsPerVoxel=8,n.datatypeCode=2;break;case 4:n.numBitsPerVoxel=16,n.datatypeCode=4;break;case 1:n.numBitsPerVoxel=32,n.datatypeCode=8;break;case 3:n.numBitsPerVoxel=32,n.datatypeCode=16;break;default:return Q.error(`Unsupported MGH data type: ${m}`),null}n.dims[1]=l,n.dims[2]=c,n.dims[3]=d,n.dims[4]=Math.max(1,u),n.dims[0]=n.dims[4]>1?4:3,n.pixDims[0]=1,n.pixDims[1]=Math.abs(f),n.pixDims[2]=Math.abs(g),n.pixDims[3]=Math.abs(A),n.pixDims[4]=0,n.sform_code=1,n.qform_code=0,n.sform_code=1;const E=a.fA(p*n.pixDims[1],w*n.pixDims[2],C*n.pixDims[3],0,v*n.pixDims[1],y*n.pixDims[2],M*n.pixDims[3],0,x*n.pixDims[1],b*n.pixDims[2],D*n.pixDims[3],0,0,0,0,1),F=[n.dims[1]/2,n.dims[2]/2,n.dims[3]/2,1],B=[0,0,0,0];for(let a=0;a<3;a++){B[a]=0;for(let t=0;t<3;t++)B[a]=B[a]+E[t+4*a]*F[t]}n.affine=[[E[0],E[1],E[2],T-B[0]],[E[4],E[5],E[6],I-B[1]],[E[8],E[9],E[10],S-B[2]],[0,0,0,1]],n.vox_offset=284,n.magic="n+1";const V=n.numBitsPerVoxel/8,U=l*c*d*n.dims[4]*V,R=r.slice(n.vox_offset,n.vox_offset+U);let P=257===o;if(!P){P=["aparc.DKTatlas+aseg.deep.mg","aparc+aseg.mg","aparc.DKTatlas+aseg.mg","aparc.a2005s+aseg.mg","aparc.a2009s+aseg.mg","apas+head.mg","apas+head.samseg.mg","aseg.auto.mg","aseg.auto_noCCseg.mg","aseg.mg","aseg.presurf.hypos.mg","aseg.presurf.mg","brainstemSsLabels.v13.FSvoxelSpace.mg","brainstemSsLabels.v13.mg","ctrl_pts.mg","filled.auto.mg","filled.mg","gtmseg.mg","hypothalamic_subunits_seg.v1.mg","lh.hippoAmygLabels-T1.v22.CA.FSvoxelSpace.mg","lh.hi
1ppoAmygLabels-T1.v22.CA.mg","lh.hippoAmygLabels-T1.v22.FS60.FSvoxelSpace.mg","lh.hippoAmygLabels-T1.v22.FS60.mg","lh.hippoAmygLabels-T1.v22.FSvoxelSpace.mg","lh.hippoAmygLabels-T1.v22.HBT.FSvoxelSpace.mg","lh.hippoAmygLabels-T1.v22.HBT.mg","lh.hippoAmygLabels-T1.v22.mg","lh.ribbon.mg","mca-dura.mg","rh.hippoAmygLabels-T1.v22.CA.FSvoxelSpace.mg","rh.hippoAmygLabels-T1.v22.CA.mg","rh.hippoAmygLabels-T1.v22.FS60.FSvoxelSpace.mg","rh.hippoAmygLabels-T1.v22.FS60.mg","rh.hippoAmygLabels-T1.v22.FSvoxelSpace.mg","rh.hippoAmygLabels-T1.v22.HBT.FSvoxelSpace.mg","rh.hippoAmygLabels-T1.v22.HBT.mg","rh.hippoAmygLabels-T1.v22.mg","rh.ribbon.mg","ribbon.mg","synthseg.mg","synthseg.rca.mg","vsinus.mg","subcort.mask.1mm.mg","subcort.mask.mg","surface.defects.mg","ThalamicNuclei.v13.T1.FSvoxelSpace.mg","ThalamicNuclei.v13.T1.mg","wm.asegedit.mg","wmparc.mg"].some((t=>i.includes(t)))}return P||(P=oi(r,n,U)),P?si(n,R):R}b(ri,{isFreeSurferLabelImage:()=>oi,optimizeFreeSurferLabels:()=>si,readMgh:()=>li});var ci={};async function hi(t,e,i){t.hdr=new h.a;const n=t.hdr;n.pixDims=[1,1,1,1,1,0,0,0],n.dims=[1,1,1,1,1,1,1,1];let r=e.byteLength;if(r<20)throw new Error("File too small to be MIF: bytes = "+r);let a=new Uint8Array(e);31===a[0]&&139===a[1]&&(Q.debug("MIF with GZ decompression"),e=await ye.decompressToBuffer(new Uint8Array(e)),r=e.byteLength,a=new Uint8Array(e));let s=0;function o(){for(;s<r&&10===a[s];)s++;const t=s;for(;s<r&&10!==a[s];)s++;return s++,s-t<1?"":(new TextDecoder).decode(e.slice(t,s-1))}let l=o();if(!l.startsWith("mrtrix image"))throw new Error("Not a valid MIF file");const c=[];let d=!1,u=0,m=0,f=!1;for(l=o();s<r&&!l.startsWith("END");){let t=l.split(":");if(l=o(),t.length<2)break;const e=t[0];t=t[1].split(",");for(let i=0;i<t.length;i++)t[i]=t[i].trim();switch(e){case"dim":n.dims[0]=t.length;for(let e=0;e<t.length;e++)n.dims[e+1]=parseInt(t[e]);break;case"vox":for(let e=0;e<t.length;e++)n.pixDims[e+1]=parseFloat(t[e]),isNaN(n.pixDims[e+1])&&(n.pixDims[e+1]=0);break;case"layout":for(let e=0;e<t.length;e++)c.push(parseInt(t[e]));break;case"datatype":{const e=t[0];e.startsWith("Bit")?(d=!0,n.datatypeCode=2):e.startsWith("Int8")?n.datatypeCode=256:e.startsWith("UInt8")?n.datatypeCode=2:e.startsWith("Int16")?n.datatypeCode=4:e.startsWith("UInt16")?n.datatypeCode=512:e.startsWith("Int32")?n.datatypeCode=8:e.startsWith("UInt32")?n.datatypeCode=768:e.startsWith("Float32")?n.datatypeCode=16:e.startsWith("Float64")?n.datatypeCode=64:Q.warn("Unsupported datatype "+e),e.includes("8")?n.numBitsPerVoxel=8:e.includes("16")?n.numBitsPerVoxel=16:e.includes("32")?n.numBitsPerVoxel=32:e.includes("64")&&(n.numBitsPerVoxel=64),n.littleEndian=!0,e.endsWith("LE")&&(n.littleEndian=!0),e.endsWith("BE")&&(n.littleEndian=!1)}break;case"transform":if(u>2||4!==t.length)break;n.affine[u][0]=parseFloat(t[0]),n.affine[u][1]=parseFloat(t[1]),n.affine[u][2]=parseFloat(t[2]),n.affine[u][3]=parseFloat(t[3]),u++;break;case"comments":n.description=t[0].substring(0,Math.min(79,t[0].length));break;case"RepetitionTime":m=parseFloat(t[0]);break;case"file":f=!t[0].startsWith(". "),f||(t=t[0].split(" "),n.vox_offset=parseInt(t[1]))}}const g=n.dims[0];g>5&&Q.warn("reader only designed for a maximum of 5 dimensions (XYZTD)");let A,p=1;for(let h=0;h<g;h++)p*=Math.max(n.dims[h+1],1);for(let h=0;h<3;h++)for(let t=0;t<3;t++)n.affine[h][t]*=n.pixDims[t+1];if(Q.debug("mif affine:"+n.affine[0]),m>0&&(n.pixDims[4]=m),f&&!i&&Q.warn("MIH header provided without paired image data"),i&&f)A=i.slice(0);else if(d){n.numBitsPerVoxel=8;const t=new Uint8Array(p),i=e.slice(n.vox_offset,n.vox_offset+Math.ceil(p/8)),r=new Uint8Array(i);let a=0;for(let e=0;e<p;e++){const i=e%8;t[e]=r[a]>>7-i&1,7===i&&a++}A=t.buffer}else A=e.slice(n.vox_offset,n.vox_offset+p*(n.numBitsPerVoxel/8));c.length!==n.dims[0]&&Q.warn("dims does not match layout");let v=1;const x=[1,1,1,1,1],w=[!1,!1,!1,!1,!1];for(let h=0;h<c.length;h++)for(let t=0;t<c.length;t++){Math.abs(c[t])===h&&(x[t]=v,(c[t]<0||Object.is(c[t],-0))&&(w[t]=!0),v*=n.dims[t+1])}let y=ye.range(0,n.dims[1]-1,1);w[0]&&(y=ye.range(n.dims[1]-1,0,-1));for(let h=0;h<n.dims[1];h++)y[h]*=x[0];let b=ye.range(0,n.dims[2]-1,1);w[1]&&(b=ye.range(n.dims[2]-1,0,-1));for(let h=0;h<n.dims[2];h++)b[h]*=x[1];let C=ye.range(0,n.dims[3]-1,1);w[2]&&(C=ye.range(n.dims[3]-1,0,-1));for(let h=0;h<n.dims[3];h++)C[h]*=x[2];let M=ye.range(0,n.dims[4]-1,1);w[3]&&(M=ye.range(n.dims[4]-1,0,-1));for(let h=0;h<n.dims[4];h++)M[h]*=x[3];let D=ye.range(0,n.dims[5]-1,1);w[4]&&(D=ye.range(n.dims[5]-1,0,-1));for(let h=0;h<n.dims[5];h++)D[h]*=x[4];let T,I,S=0;switch(n.datatypeCode){case 256:T=new Int8Array(A),I=new Int8Array(p);break;case 2:T=new Uint8Array(A),I=new Uint8Array(p);break;case 4:T=new Int16Array(A),I=new Int16Array(p);break;case 512:T=new Uint16Array(A),I=new Uint16Array(p);break;case 8:T=new Int32Array(A),I=new Int32Array(p);break;case 768:T=new Uint32Array(A),I=new Uint32Array(p);break;case 16:T=new Float32Array(A),I=new Float32Array(p);break;case 64:T=new Float64Array(A),I=new Float64Array(p);break;default:throw new Error("unknown datatypeCode")}for(let h=0;h<n.dims[5];h++)for(let t=0;t<n.dims[4];t++)for(let e=0;e<n.dims[3];e++)for(let i=0;i<n.dims[2];i++)for(let r=0;r<n.dims[1];r++)I[S]=T[y[r]+b[i]+C[e]+M[t]+D[h]],S++;return I.buffer}b(ci,{readMIF:()=>hi});var di={};async function ui(t,e,i){let n=e,r=null;try{if((0,c.cx)(n)&&(Q.debug(`Decompressing NIfTI file: ${t.name}`),n=await(0,c.Sz)(n),Q.debug(`Decompression complete for: ${t.name}`)),!n||0===n.byteLength)throw new Error("Buffer became invalid after decompression attempt.");if(t.hdr=await(0,c.Ad)(n,null!=i),(0,c.Ql)(t.hdr)&&(t.extensions=t.hdr.extensions),null===t.hdr)throw new Error(`Failed to read NIfTI header: ${t.name}`);if(0===t.hdr.cal_min&&255===t.hdr.cal_max&&2!==t.hdr.datatypeCode&&(Q.debug(`Resetting suspicious cal_min/max (0/255) for non-uint8 NIfTI: ${t.name}`),t.hdr.cal_min=0,t.hdr.cal_max=0),r=i?(0,c.AM)(t.hdr,i):(0,c.AM)(t.hdr,n),null===r)throw new Error(`nifti-reader-js readImage returned null for ${t.name}`);return r}catch(a){return Q.error(`Error processing NIfTI file ${t.name}:`,a),t.hdr=null,null}}b(di,{readNifti:()=>ui});var mi={};async function fi(t,e,i){void 0===i&&(i=null),t.hdr||(Q.warn("readNrrd called before nvImage.hdr was initialized. Creating default."),t.hdr=new h.a);const n=t.hdr;n.pixDims=[1,1,1,1,1,0,0,0],n.dims=[0,0,0,0,0,0,0,0];const s=e.byteLength;let o=null;const l=new Uint8Array(e);for(let r=1;r<s;r++)if(10===l[r-1]&&10===l[r]){const t=e.slice(0,r-1);o=(new TextDecoder).decode(t),n.vox_offset=r+1;break}if(null===o)return Q.error("readNrrd: could not extract txt"),null;const c=o.split("\n");if(!c[0].startsWith("NRRD"))return Q.error("Invalid NRRD image (magic signature missing)"),null;const d=c.length;let m=!1,f=!1,g=!1;const A=u.fA(NaN,0,0,0,1,0,0,0,1),p=r.fA(0,0,0);let v=u.vt();for(let r=1;r<d;r++){let t=c[r];if(0===t.length||"#"===t[0]){if(t.startsWith("#"))continue;if(0===t.trim().length)continue}t=t.toLowerCase();const e=t.split(":");if(e.length<2)continue;const i=e[0].trim();let a=e[1].trim();switch(a=a.replaceAll(")"," "),a=a.replaceAll("("," "),a=a.trim(),i){case"data file":g=!0;break;case"encoding":if(a.includes("raw"))m=!1;else{if(!a.includes("gz"))return Q.error(`Unsupported NRRD encoding : ${a}`),null;m=!0}break;case"type":switch(a){case"uchar":case"unsigned char":case"uint8":case"uint8_t":n.numBitsPerVoxel=8,n.datatypeCode=2;break;case"signed char":case"int8":case"int8_t":n.numBitsPerVoxel=8,n.datatypeCode=256;break;case"short":case"short int":case"signed short":case"signed short int":case"int16":case"int16_t":n.numBitsPerVoxel=16,n.datatypeCode=4;break;case"ushort":case"unsigned short":case"unsigned short int":case"uint16":case"uint16_t":n.numBitsPerVoxel=16,n.datatypeCode=512;break;case"int":case"signed int":case"int32":case"int32_t":n.numBitsPerVoxel=32,n.datatypeCode=8;break;case"uint":case"unsigned int":case"uint32":case"uint32_t":n.numBitsPerVoxel=32,n.datatypeCode=768;break;case"float":n.numBitsPerVoxel=32,n.datatypeCode=16;break;case"double":n.numBitsPerVoxel=64,n.datatypeCode=64;break;default:return Q.error("Unsupported NRRD data type: "+a),null}break;case"spacings":{const t=a.split(/[ ,]+/);for(let e=0;e<t.length;e++)n.pixDims[e+1]=parseFloat(t[e])}break;case"sizes":{const t=a.split(/[ ,]+/);n.dims[0]=t.length;for(let e=0;e<t.length;e++)n.dims[e+1]=parseInt(t[e])}break;case"endian":a.includes("little")?n.littleEndian=!0:a.includes("big")&&(n.littleEndian=!1);break;case"space directions":{const t=a.split(/[ ,]+/);if(9===t.length)for(let e=0;e<9;e++)A[e]=parseFloat(t[e])}break;case"space origin":{const t=a.split(/[ ,]+/);3===t.length&&(p[0]=parseFloat(t[0]),p[1]=parseFloat(t[1]),p[2]=parseFloat(t[2]))}break;case"space units":a.includes("microns")&&(f=!0);break;case"space":a.includes("right-anterior-superior")||a.includes("ras")?v=u.fA(1,0,0,0,1,0,0,0,1):a.includes("left-anterior-superior")||a.includes("las")?v=u.fA(-1,0,0,0,1,0,0,0,1):a.includes("left-posterior-superior")||a.includes("lps")?v=u.fA(-1,0,0,0,-1,0,0,0,1):Q.warn("Unsupported NRRD space value:",a);break;default:Q.warn("Unknown:",i)}}
1if(!isNaN(A[0])){n.sform_code=2,f&&(a.Ny(A,A,.001),p[0]*=.001,p[1]*=.001,p[2]*=.001),v[0]<0&&(p[0]=-p[0]),v[4]<0&&(p[1]=-p[1]),v[8]<0&&(p[2]=-p[2]),u.lw(A,v,A);const e=a.fA(A[0],A[3],A[6],p[0],A[1],A[4],A[7],p[1],A[2],A[5],A[8],p[2],0,0,0,1);if(!t.vox2mm)return null;const i=t.vox2mm([0,0,0],e),s=t.vox2mm([1,0,0],e);r.Re(s,s,i);const o=t.vox2mm([0,1,0],e);r.Re(o,o,i);const l=t.vox2mm([0,0,1],e);r.Re(l,l,i),n.pixDims[0]=1,n.pixDims[1]=r.Bw(s),n.pixDims[2]=r.Bw(o),n.pixDims[3]=r.Bw(l),n.affine=[[e[0],e[1],e[2],e[3]],[e[4],e[5],e[6],e[7]],[e[8],e[9],e[10],e[11]],[0,0,0,1]]}let x=null;const w=g?i:e,y=g?0:n.vox_offset;if(g&&!w)return Q.warn("Missing data: NRRD header describes detached data file but only one URL provided"),null;if(!w||y>=w.byteLength)return Q.error(`NRRD data offset (${y}) invalid for buffer length (${w?.byteLength??0})`),null;let b=w.slice(y);if(m)try{Q.debug("Decompressing NRRD data..."),b=await ye.decompressToBuffer(new Uint8Array(b)),Q.debug("Decompression complete.")}catch(D){return Q.error("Failed to decompress NRRD data.",D),null}const C=n.numBitsPerVoxel/8,M=n.dims.slice(1,n.dims[0]+1).reduce(((t,e)=>t*Math.max(1,e)),1)*C;return b.byteLength<M?(Q.error(`NRRD image data size mismatch: expected ${M}, found ${b.byteLength}`),null):(b.byteLength>M&&(Q.warn(`NRRD has extra ${b.byteLength-M} bytes after expected image data. Truncating.`),b=b.slice(0,M)),x=b,n.datatypeCode?n.numBitsPerVoxel?x:(Q.error("NRRD parsing failed to set numBitsPerVoxel."),null):(Q.error("NRRD parsing failed to set datatypeCode."),null))}b(mi,{readNrrd:()=>fi});var gi={};async function Ai(t,e){const i=new DataView(e),n=[i.getUint8(0),i.getUint8(1),i.getUint8(2),i.getUint8(3),i.getUint8(4),i.getUint8(5)],r=[147,78,85,77,80,89];if(!n.every(((t,e)=>t===r[e])))throw new Error("Not a valid NPY file: Magic number mismatch");const a=i.getUint8(6),s=i.getUint8(7);let o,l,c;if(1===a)o=i.getUint16(8,!0),l=10,c="latin1";else{if(2!==a&&3!==a)throw new Error(`Unsupported NPY version: ${a}.${s}`);o=i.getUint32(8,!0),l=12,c=3===a?"utf-8":"latin1"}const d=l+o;if(d>e.byteLength)throw new Error("Invalid NPY file: Header length exceeds buffer size");const u=new TextDecoder(c).decode(e.slice(l,d)),m=u.match(/'shape': \((.*?)\)/);if(!m)throw new Error("Invalid NPY header: Shape not found");const f=m[1].split(",").map((t=>t.trim())).filter((t=>""!==t)).map(Number);if(0===f.length||f.some((t=>!Number.isInteger(t)||t<=0)))throw new Error(`Invalid NPY header: invalid shape (${m[1]})`);if(f.length<2||f.length>4)throw new Error(`Unsupported NPY shape: expected 2D, 3D, or 4D array, got (${f.join(", ")})`);const g=u.match(/'descr': '([^']+)'/);if(!g)throw new Error("Invalid NPY header: Data type not found");const A=g[1],p=A[0],v=1===new Uint8Array(new Uint16Array([1]).buffer)[0];if(!["<",">","|","="].includes(p))throw new Error(`Invalid NPY dtype endian prefix: ${A}`);const x=f.reduce(((t,e)=>t*e),1),w=function(t){if(t.length<2)throw new Error(`Invalid NPY dtype: ${t}`);const e={b1:1,i1:1,u1:1,i2:2,u2:2,i4:4,u4:4,f4:4,f8:8}[t.slice(1)];if(void 0===e)throw new Error(`Unsupported NPY dtype: ${t}`);return e}(A),y=x*w;if(e.byteLength-d<y)throw new Error("Invalid .npy file: not enough data bytes for specified shape and data type");const b=e.slice(d,d+y),C=f.length,M=f[f.length-1],D=f[f.length-2],T=f.length>=3?f[f.length-3]:1,I=4===f.length?f[0]:1;t.hdr=new h.a;const S=t.hdr;return S.dims=[C,M,D,T,I,1,1,1],S.pixDims=[1,1,1,1,1,1,1,1],S.affine=[[S.pixDims[1],0,0,.5*-(S.dims[1]-2)*S.pixDims[1]],[0,-S.pixDims[2],0,.5*(S.dims[2]-2)*S.pixDims[2]],[0,0,-S.pixDims[3],.5*(S.dims[3]-2)*S.pixDims[3]],[0,0,0,1]],S.numBitsPerVoxel=8*w,S.datatypeCode=function(t){if(t.length<2)throw new Error(`Invalid NPY dtype: ${t}`);const e={b1:2,i1:256,u1:2,i2:4,u2:512,i4:8,u4:768,f4:16,f8:64}[t.slice(1)];if(void 0===e)throw new Error(`Unsupported NPY dtype: ${t}`);return e}(A),S.littleEndian="<"===p||"|"===p||"="===p&&v,b}async function pi(t,e){const i=new we(e);for(let n=0;n<i.entries.length;n++){const e=i.entries[n];if(e.fileName.toLowerCase().endsWith(".npy")){const i=await e.extract(),n=i.buffer.slice(i.byteOffset,i.byteOffset+i.byteLength);return await Ai(t,n)}}}b(gi,{readNPY:()=>Ai,readNPZ:()=>pi});var vi={};async function xi(t,e,i){let{width:n,height:r,depth:a=1,data:s}=i??{},o=n*r*a*3,l=o===s.length;if(l||(o=n*r*a,3===a&&(l=!0,a=1)),o!==s.length)throw new Error(`Expected RGB ${n}\xd7${r}\xd7${a}\xd73 =  ${o}, but ZARR length ${s.length}`);t.hdr=new h.a;const c=t.hdr;if(c.dims=[3,n,r,a,1,1,1,1],c.pixDims=[1,1,1,1,0,0,0,0],c.affine=[[c.pixDims[1],0,0,.5*-(c.dims[1]-2)*c.pixDims[1]],[0,-c.pixDims[2],0,.5*(c.dims[2]-2)*c.pixDims[2]],[0,0,-c.pixDims[3],.5*(c.dims[3]-2)*c.pixDims[3]],[0,0,0,1]],!l){if(c.numBitsPerVoxel=8,c.datatypeCode=2,s instanceof Uint8Array){const t=new ArrayBuffer(s.length);return new Uint8Array(t).set(s),t}return s}c.numBitsPerVoxel=24,c.datatypeCode=128;
1const d=function(t,e,i,n){const r=e*i,a=new Uint8Array(r*n*3),s=new Array(n);for(let c=0;c<n;c++)s[c]=3*r*c;let o=0,l=0;for(let c=0;c<r;c++){for(let e=0;e<n;e++)a[s[e]+l]=t[o++],a[s[e]+l+1]=t[o++],a[s[e]+l+2]=t[o++];l+=3}return a}(s,c.dims[1],c.dims[2],c.dims[3]),u=new ArrayBuffer(d.length);return new Uint8Array(u).set(d),u}function wi(t,e,i){const s=a.o8(i);a.mg(s,s);const o=n.fA(e[0],e[1],e[2],1);n.Z0(o,o,s);return r.fA(o[0],o[1],o[2])}function yi(t,e,i){if(void 0===i&&(i=!1),!t.matRAS)throw new Error("matRAS undefined");const s=a.o8(t.matRAS),o=a.o8(s);a.mg(o,s),a.B8(o,o);const l=n.fA(e[0],e[1],e[2],1);n.Z0(l,l,o);const c=r.fA(l[0],l[1],l[2]);return i?c:new Float32Array([Math.round(c[0]),Math.round(c[1]),Math.round(c[2])])}function bi(t,e){return Array.isArray(t)&&Array.isArray(e)&&t.length===e.length&&t.every(((t,i)=>t===e[i]))}function Ci(t){const e=a.o8(t);a.mg(e,t);const i=Math.sqrt(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]),n=Math.max(Math.max(Math.abs(e[0]),Math.abs(e[1])),Math.abs(e[2]))/i,r=Math.sqrt(e[4]*e[4]+e[5]*e[5]+e[6]*e[6]),s=Math.max(Math.max(Math.abs(e[4]),Math.abs(e[5])),Math.abs(e[6]))/r,o=Math.sqrt(e[8]*e[8]+e[9]*e[9]+e[10]*e[10]),l=Math.max(Math.max(Math.abs(e[8]),Math.abs(e[9])),Math.abs(e[10]))/o,c=Math.min(Math.min(n,s),l);let h=Math.abs(180*Math.acos(c)/3.141592653);return h>.01?Q.warn("Warning voxels not aligned with world space: "+h+" degrees from plumb.\n"):h=0,h}function Mi(t){if(!t.matRAS)throw new Error("matRAS not defined");if(void 0===t.pixDimsRAS)throw new Error("pixDimsRAS not defined");if(!t.dimsRAS)throw new Error("dimsRAS not defined");t.oblique_angle=Ci(t.matRAS);const e=wi(0,[0,0,0],t.matRAS),i=wi(0,[1/t.pixDimsRAS[1],0,0],t.matRAS),s=wi(0,[0,1/t.pixDimsRAS[2],0],t.matRAS),o=wi(0,[0,0,1/t.pixDimsRAS[3]],t.matRAS);r.Re(i,i,e),r.Re(s,s,e),r.Re(o,o,e);const l=a.fA(i[0],i[1],i[2],0,s[0],s[1],s[2],0,o[0],o[1],o[2],0,0,0,0,1);t.obliqueRAS=a.o8(l);const c=Math.abs(90-r.g7(i,s)*(180/Math.PI)),h=Math.abs(90-r.g7(i,o)*(180/Math.PI)),d=Math.abs(90-r.g7(s,o)*(180/Math.PI));t.maxShearDeg=Math.max(Math.max(c,h),d),t.maxShearDeg>.1&&Q.warn("Warning: voxels are rhomboidal, maximum shear is %f degrees.",t.maxShearDeg);const u=n.fA(t.dimsRAS[1],t.dimsRAS[2],t.dimsRAS[3],1),m=a.o8(t.matRAS);a.mg(m,m);const f=n.fA(-.5,-.5,-.5,0);a.Tl(m,m,r.fA(f[0],f[1],f[2])),m[0]*=u[0],m[1]*=u[0],m[2]*=u[0],m[4]*=u[1],m[5]*=u[1],m[6]*=u[1],m[8]*=u[2],m[9]*=u[2],m[10]*=u[2],t.frac2mm=a.o8(m);const g=t.pixDimsRAS[1],A=t.pixDimsRAS[2],p=t.pixDimsRAS[3],v=a.o8(m);v[0]=g*u[0],v[1]=0,v[2]=0,v[4]=0,v[5]=A*u[1],v[6]=0,v[8]=0,v[9]=0,v[10]=p*u[2];const x=yi(t,[0,0,0],!0);v[12]=(-x[0]-.5)*g,v[13]=(-x[1]-.5)*A,v[14]=(-x[2]-.5)*p,t.frac2mmOrtho=a.o8(v),t.extentsMinOrtho=[v[12],v[13],v[14]],t.extentsMaxOrtho=[v[0]+v[12],v[5]+v[13],v[10]+v[14]],t.mm2ortho=a.vt(),a.B8(t.mm2ortho,l)}function Di(t,e){e.length!==3*t.nVox3D&&Q.warn("float32V1asRGBA() expects "+3*t.nVox3D+"voxels, got ",+e.length);const i=e.slice();t.hdr.datatypeCode=2304,t.nFrame4D=1;for(let l=4;l<7;l++)t.hdr.dims[l]=1;t.hdr.dims[0]=3;const n=new Uint8Array(4*t.nVox3D);let r=1;for(let l=0;l<3*t.nVox3D;l++)isNaN(i[l])||(r=Math.max(r,Math.abs(i[l])));const a=255/r,s=2*t.nVox3D;let o=0;for(let l=0;l<t.nVox3D;l++){const e=i[l],r=i[l+t.nVox3D],c=i[l+s];n[o]=Math.abs(e*a),n[o+1]=Math.abs(r*a),n[o+2]=Math.abs(c*a);let h=248+1*Number(e>0)+2*Number(r>0)+4*Number(c>0);Math.abs(e)+Math.abs(r)+Math.abs(c)<.1&&(h=0),n[o+3]=h,o+=4}return n}function Ti(t,e){if(!t.hdr)throw new Error("hdr undefined");return 0===t.hdr.scl_slope&&(t.hdr.scl_slope=1),e*t.hdr.scl_slope+t.hdr.scl_inter}function Ii(t,e,i){if(void 0===e&&(e=Number.POSITIVE_INFINITY),void 0===i&&(i=!0),!t.hdr)throw new Error("hdr undefined");if(!t.img)throw new Error("img undefined");let n=Number.POSITIVE_INFINITY,r=Number.NEGATIVE_INFINITY,a=0,s=0,o=t.hdr.dims[1]*t.hdr.dims[2]*t.hdr.dims[3];const l=Math.floor(t.img.length/o);e>=l&&(e=t.frame4D);const c=(e=Math.min(e,l-1))*o;let h=[];if(i){const e=.25,i=[Math.floor(e*t.hdr.dims[1]),Math.floor(e*t.hdr.dims[2]),Math.floor(e*t.hdr.dims[3])],n=[t.hdr.dims[1]-2*i[0],t.hdr.dims[2]-2*i[1],t.hdr.dims[3]-2*i[2]],r=[n[0]+i[0],n[1]+i[1],n[2]+i[2]];o=n[0]*n[1]*n[2],h=new t.img.constructor(o);let a=-1,s=0;for(let o=0;o<t.hdr.dims[3];o++)for(let e=0;e<t.hdr.dims[2];e++)for(let n=0;n<t.hdr.dims[1];n++)a++,n<i[0]||e<i[1]||o<i[2]||n>=r[0]||e>=r[1]||o>=r[2]||(h[s]=t.img[a+c],s++)}else{h=new t.img.constructor(o);for(let e=0;e<o;e++)h[e]=t.img[e+c]}const d=h.constructor!==Float64Array&&h.constructor!==Float32Array&&t.ignoreZeroVoxels;if(d)for(let S=0;S<o;S++)n=Math.min(h[S],n),r=Math.max(h[S],r),0===h[S]&&a++;else for(let S=0;S<o;S++)isNaN(h[S])?s++:0===h[S]&&(a++,t.ignoreZeroVoxels)||(n=Math.min(h[S],n),r=Math.max(h[S],r));t.ignoreZeroVoxels&&n===r&&a>0&&(n=0);const u=Ti(t,n),m=Ti(t,r),f=ve.colormapFromKey(t._colormap);let g=0,A=0;if(void 0!==f.min&&(g=f.min),void 0!==f.max&&(A=f.max),g===A&&t.trustCalMinMax&&isFinite(t.hdr.cal_min)&&isFinite(t.hdr.cal_max)&&t.hdr.cal_max>t.hdr.cal_min)return t.cal_min=t.hdr.cal_min,t.cal_max=t.hdr.cal_max,t.robust_min=t.cal_min,t.robust_max=t.cal_max,t.global_min=u,t.global_max=m,[t.hdr.cal_min,t.hdr.cal_max,t.hdr.cal_min,t.hdr.cal_max];if(g!==A)return t.cal_min=g,t.cal_max=A,t.robust_min=t.cal_min,t.robust_max=t.cal_max,[g,A,g,A];const p=100*a/(o-0);let v=!1;p>60&&!t.ignoreZeroVoxels&&(Q.warn(`${Math.round(p)}% of voxels are zero: ignoring zeros for cal_max`),v=!0,t.ignoreZeroVoxels=!0),t.ignoreZeroVoxels||(a=0),a+=s;const x=Math.round((o-0-a)*t.percentileFrac);if(x<1||n===r)return i?Ii(t,e,!1):(Q.debug("no variability in image intensity?"),t.cal_min=u,t.cal_max=m,t.robust_min=t.cal_min,t.robust_max=t.cal_max,t.global_min=u,t.global_max=m,[u,m,u,m]);const w=1001,y=1e3/(r-n),b=new Array(w);for(let S=0;S<w;S++)b[S]=0;if(d)for(let S=0;S<o;S++)b[Math.round((h[S]-n)*y)]++;else if(t.ignoreZeroVoxels)for(let S=0;S<o;S++)0!==h[S]&&(isNaN(h[S])||b[Math.round((h[S]-n)*y)]++);else for(let S=0;S<o;S++)isNaN(h[S])||b[Math.round((h[S]-n)*y)]++;let C=0,M=0;for(;C<x;)C+=b[M],M++;M--,C=0;let D=w;for(;C<x;)D--,C+=b[D];if(M===D){let t=-1;for(;0!==t;)M>0&&(M--,b[M]>0&&(t=0)),0!==t&&D<1e3&&(D++,b[D]>0&&(t=0)),0===M&&1e3===D&&(t=0)}
1let T=Ti(t,M/y+n),I=Ti(t,D/y+n);return t.hdr.cal_min<t.hdr.cal_max&&t.hdr.cal_min>=u&&t.hdr.cal_max<=m&&(T=t.hdr.cal_min,I=t.hdr.cal_max),v&&(T=Math.min(T,0)),t.cal_min=T,t.cal_max=I,1002===t.hdr.intent_code&&(t.cal_min=u,t.cal_max=m),t.robust_min=t.cal_min,t.robust_max=t.cal_max,t.global_min=u,t.global_max=m,[T,I,u,m]}function Si(t,e){t._colormap=e,Ii(t),t.onColormapChange&&t.onColormapChange(t)}function Ei(t){return t._colormap}async function Fi(t,e){const i=t.getReader(),n=new m.as,r=[];let a,s,o=0,l=!1;const c=new Promise(((t,e)=>{a=t,s=e}));return n.ondata=t=>{r.push(t),o+=t.length,o>=e&&(l=!0,i.cancel().catch((()=>{})),function(){const t=new Uint8Array(o);let e=0;for(const i of r)t.set(i,e),e+=i.length;a(t)}())},(async()=>{try{for(;!l;){const{done:t,value:e}=await i.read();if(t)return l=!0,void n.push(new Uint8Array,!0);n.push(e,!1)}}catch(t){s(t)}})().catch((()=>{})),c}async function Bi(t,e,i){if(void 0===t&&(t=""),void 0===e&&(e={}),void 0===i&&(i=NaN),isNaN(i))return null;const n=await fetch(t,{headers:e,cache:"force-cache"});let r=352,a=await Fi(n.body,r);const s=new DataView(a.buffer,a.byteOffset,a.byteLength),o=s.getUint16(0,!0),l=348===o;if(!l&&!(23553===o))return null;a.length>111&&(r=s.getFloat32(108,l)),r>a.length&&(a=await Fi(n.body,r));if(!(92===a[0]&&1===a[1]||92===a[1]&&1===a[0]))return null;const h=await(0,c.Ad)(a.buffer);if(!h)throw new Error("Could not read NIfTI header");const d=h.numBitsPerVoxel/8,u=[1,2,3].reduce(((t,e)=>t*(h.dims[e]>1?h.dims[e]:1)),1),m=[4,5,6].reduce(((t,e)=>t*(h.dims[e]>1?h.dims[e]:1)),1),f=Math.max(Math.min(i,m),1),g=h.vox_offset+f*u*d;if(f===m)return null;const A=await fetch(t,{headers:e,cache:"force-cache"});return(await Fi(A.body,g)).buffer.slice(0,g)}function Vi(t){const e=t.match(/\.([^.]+)(?:\.gz|\.bz2|\.xz)?$/);return e?e[1]:""}function Ui(t,e){!function(t){0!==t.pixDims[1]&&0!==t.pixDims[2]&&0!==t.pixDims[3]||Q.error("pixDims not plausible",t)}(t),function(t){(isNaN(t.scl_slope)||0===t.scl_slope)&&(t.scl_slope=1),isNaN(t.scl_inter)&&(t.scl_inter=0)}(t),function(t,e){const i=Ne(t.affine);if(!e&&i&&t.qform_code<=t.sform_code)return;Q.debug("spatial transform based on QForm");const n=t.quatern_b,r=t.quatern_c,a=t.quatern_d,s=Math.sqrt(1-(Math.pow(n,2)+Math.pow(r,2)+Math.pow(a,2))),o=0===t.pixDims[0]?1:t.pixDims[0],l=[[s*s+n*n-r*r-a*
1a,2*n*r-2*s*a,2*n*a+2*s*r],[2*n*r+2*s*a,s*s+r*r-n*n-a*a,2*r*a-2*s*n],[2*n*a-2*s*r,2*r*a+2*s*n,s*s+a*a-r*r-n*n]],c=t.affine;for(let h=0;h<3;h+=1)for(let e=0;e<3;e+=1)c[h][e]=l[h][e]*t.pixDims[e+1],2===e&&(c[h][e]*=o);c[0][3]=t.qoffset_x,c[1][3]=t.qoffset_y,c[2][3]=t.qoffset_z,t.affine=c}(t,e),function(t){if(Ne(t.affine))return;Q.debug("Defective NIfTI: spatial transform does not make sense");let e=t.pixDims[1],i=t.pixDims[2],n=t.pixDims[3];(isNaN(e)||0===e)&&(e=1),(isNaN(i)||0===i)&&(i=1),(isNaN(n)||0===n)&&(n=1),t.pixDims[1]=e,t.pixDims[2]=i,t.pixDims[3]=n;const r=[[e,0,0,0],[0,i,0,0],[0,0,n,0],[0,0,0,1]];t.affine=r}(t)}b(vi,{readZARR:()=>xi});function Ri(t){return t*Math.PI/180}function Pi(t){const e=a.vt();a.Tl(e,e,t.translation);const i=function(t,e,i){const n=a.vt(),r=Ri(t),s=Ri(e),o=Ri(i);return a.eL(n,n,r),a.Z8(n,n,s),a.Qr(n,n,o),n}(t.rotation[0],t.rotation[1],t.rotation[2]);return a.lw(e,e,i),a.hs(e,e,t.scale),e}function Ni(t,e){const i=(n=t,a.fA(n[0][0],n[1][0],n[2][0],n[3][0],n[0][1],n[1][1],n[2][1],n[3][1],n[0][2],n[1][2],n[2][2],n[3][2],n[0][3],n[1][3],n[2][3],n[3][3]));var n;const r=a.vt();return a.lw(r,e,i),[[(s=r)[0],s[4],s[8],s[12]],[s[1],s[5],s[9],s[13]],[s[2],s[6],s[10],s[14]],[s[3],s[7],s[11],s[15]]];var s}function Li(t){return t.map((t=>[...t]))}var ki=class{constructor(t){C(this,"store"),C(this,"baseUrl"),C(this,"arrays",new Map),C(this,"levelPaths",new Map),C(this,"axisMapping",null),this.baseUrl=t.baseUrl,this.store=new g.A(t.baseUrl)}async fetchInfo(){const t=A.zr(this.store),e=[];let i=null,n=null;try{const i=await p.h(t,{kind:"array"});e.push({index:0,path:"/",shape:[...i.shape],chunks:[...i.chunks],dtype:i.dtype}),this.arrays.set(0,i),this.levelPaths.set(0,"/")}catch{try{const e=(await p.h(t,{kind:"group"})).attrs;if(e.ome&&"object"==typeof e.ome){const t=e.ome;t.multiscales&&Array.isArray(t.multiscales)&&t.multiscales.length>0&&(n=t.multiscales[0])}else e.multiscales&&Array.isArray(e.multiscales)&&e.multiscales.length>0&&(n=e.multiscales[0])}catch{}if(n?.axes&&Array.isArray(n.axes)&&(i=n.axes),n&&n.datasets&&n.datasets.length>0)for(let i=0;i<n.datasets.length;i++){const r=n.datasets[i],a=r.path.startsWith("/")?r.path:`/${r.path}`;try{const n=t.resolve(a),r=await p.h(n,{kind:"array"});e.push({index:i,path:a,shape:[...r.shape],chunks:[...r.chunks],dtype:r.dtype}),this.arrays.set(i,r),this.levelPaths.set(i,a)}catch(h){console.warn(`Failed to open array at path ${a}:`,h)}}else for(let i=0;i<20;i++){const n=`/${i}`;try{const r=t.resolve(n),a=await p.h(r,{kind:"array"});e.push({index:i,path:n,shape:[...a.shape],chunks:[...a.chunks],dtype:a.dtype}),this.arrays.set(i,a),this.levelPaths.set(i,n)}catch{break}}}if(0===e.length)throw new Error(`No zarr arrays found at ${this.baseUrl}`);const r=e[0].shape.length,a=this.buildAxisMapping(r,e[0].chunks,i);let s;this.axisMapping=a,i&&(s=a.spatialIndices.map((t=>i[t]?.unit??"")));const o=e.map((t=>{const e={index:t.index,path:t.path,shape:a.spatialIndices.map((e=>t.shape[e])),chunks:a.spatialIndices.map((e=>t.chunks[e])),dtype:t.dtype};if(n?.datasets?.[t.index]?.coordinateTransformations){const i=n.datasets[t.index].coordinateTransformations,r=i.find((t=>"scale"===t.type&&t.scale));r?.scale&&(e.scales=a.spatialIndices.map((t=>r.scale[t])));const s=i.find((t=>"translation"===t.type&&t.translation));s?.translation&&(e.translations=a.spatialIndices.map((t=>s.translation[t])))}return e})),l=a.spatialIndices.length,c=l>=3;return console.log(`Zarr axis mapping: original ndim=${r}, spatial ndim=${l}, spatial indices=${JSON.stringify(a.spatialIndices)}, non-spatial=${JSON.stringify(a.nonSpatialAxes.map((t=>t.name)))}`),{name:this.baseUrl,levels:o,is3D:c,ndim:l,axisMapping:a,spatialUnits:s}}buildAxisMapping(t,e,i){const n=[],r=[],a=[];if(i&&i.length===t)for(let s=0;s<i.length;s++){const t=i[s];"space"===t.type?(n.push(s),r.push(t.name.toLowerCase())):a.push({index:s,name:t.name,chunkSize:e[s],defaultChunkCoord:0})}else if(null===i&&console.warn("No OME axes metadata found \u2014 inferring axis layout from array dimensions"),t<=3){const e=2===t?["y","x"]:["z","y","x"].slice(3-t);for(let i=0;i<t;i++)n.push(i),r.push(e[i])}else if(4===t)a.push({index:0,name:"c",chunkSize:e[0],defaultChunkCoord:0}),n.push(1,2,3),r.push("z","y","x");else if(5===t)a.push({index:0,name:"t",chunkSize:e[0],defaultChunkCoord:0}),a.push({index:1,name:"c",chunkSize:e[1],defaultChunkCoord:0}),n.push(2,3,4),r.push("z","y","x");else{for(let i=0;i<t-3;i++)a.push({index:i,name:`dim${i}`,chunkSize:e[i],defaultChunkCoord:0});for(let e=t-3;e<t;e++)n.push(e),r.push(["z","y","x"][e-(t-3)])}return{originalNdim:t,spatialIndices:n,spatialAxisNames:r,nonSpatialAxes:a}}async openLevel(t){if(this.arrays.has(t))return this.arrays.get(t);const e=A.zr(this.store),i=this.levelPaths.get(t)??(0===t?"/":`/${t}`);try{const n=e.resolve(i),r=await p.h(n,{kind:"array"});return this.arrays.set(t,r),this.levelPaths.set(t,i),r}catch{if(0===t){const i=await p.h(e,{kind:"array"});return this.arrays.set(t,i),this.levelPaths.set(t,"/"),i}throw new Error(`Cannot open zarr array at level ${t}`)}}async fetchChunk(t,e,i,n,r,a){try{const s=await this.openLevel(t),o=this.axisMapping;let l;if(o&&o.originalNdim>
1o.spatialIndices.length){l=new Array(o.originalNdim).fill(0);for(const e of o.nonSpatialAxes)l[e.index]=r?.[e.name]??e.defaultChunkCoord;const t=void 0!==n&&o.spatialIndices.length>=3?[n,i,e]:[i,e];for(let e=0;e<t.length&&e<o.spatialIndices.length;e++)l[o.spatialIndices[e]]=t[e]}else l=void 0!==n&&s.shape.length>=3?[n,i,e]:[i,e];let c=(await s.getChunk(l,{signal:a})).data;if(o&&o.nonSpatialAxes.length>0){const t=o.spatialIndices.reduce(((t,e)=>t*s.chunks[e]),1);if(c.length>t){let e=0,i=c.length;for(let t=0;t<o.originalNdim;t++){i=Math.floor(i/s.chunks[t]);o.spatialIndices.includes(t)||(e+=0*i)}c=c.subarray(e,e+t)}}return c}catch(s){return console.warn(`Failed to fetch chunk at level ${t}, x=${e}, y=${i}, z=${n}:`,s),null}}async fetchChunks(t,e,i){const n=new Map,r=i.map((async i=>{const r=await this.fetchChunk(e,i.x,i.y,i.z);if(r){const a=void 0!==i.z?`${t}:${e}/${i.x}/${i.y}/${i.z}`:`${t}:${e}/${i.x}/${i.y}`;n.set(a,r)}}));return await Promise.all(r),n}async fetchRegion(t,e){try{const i=await this.openLevel(t),n=this.axisMapping,r=[];if(n&&n.originalNdim>n.spatialIndices.length)for(let t=0;t<n.originalNdim;t++){const a=n.spatialIndices.indexOf(t);-1===a?r.push(0):n.spatialIndices.length>=3?0===a&&void 0!==e.zStart&&void 0!==e.zEnd?r.push(f.di(e.zStart,e.zEnd)):1===a?r.push(f.di(e.yStart,e.yEnd)):2===a?r.push(f.di(e.xStart,e.xEnd)):r.push(f.di(0,i.shape[t])):0===a?r.push(f.di(e.yStart,e.yEnd)):r.push(f.di(e.xStart,e.xEnd))}else void 0!==e.zStart&&void 0!==e.zEnd&&i.shape.length>=3?(r.push(f.di(e.zStart,e.zEnd)),r.push(f.di(e.yStart,e.yEnd)),r.push(f.di(e.xStart,e.xEnd))):(r.push(f.di(e.yStart,e.yEnd)),r.push(f.di(e.xStart,e.xEnd)));const a=await v.Jt(i,r);return{data:a.data,shape:a.shape}}catch(i){return console.warn(`Failed to fetch region at level ${t}:`,i),null}}getUrl(){return this.baseUrl}clearArrayCache(){this.arrays.clear(),this.levelPaths.clear()}},Oi=class{constructor(t){void 0===t&&(t=500),C(this,"cache"),C(this,"loadingSet"),C(this,"maxChunks"),this.cache=new Map,this.loadingSet=new Set,this.maxChunks=t}static getKey(t,e,i,n,r){return void 0!==r?`${t}:${e}/${i}/${n}/${r}`:`${t}:${e}/${i}/${n}`}has(t){return this.cache.has(t)}get(t){const e=this.cache.get(t);return e&&(this.cache.delete(t),this.cache.set(t,e)),e}set(t,e){for(this.cache.has(t)&&this.cache.delete(t);this.cache.size>=this.maxChunks;){const t=this.cache.keys().next().value;if(!t)break;this.cache.delete(t)}this.cache.set(t,e)}isLoading(t){return this.loadingSet.has(t)}startLoading(t){this.loadingSet.add(t)}doneLoading(t){this.loadingSet.delete(t)}get size(){return this.cache.size}get loadingCount(){return this.loadingSet.size}clear(){this.cache.clear(),this.loadingSet.clear()}delete(t){return this.loadingSet.delete(t),this.cache.delete(t)}keys(){return this.cache.keys()}};function zi(t,e){if(!e)return t;switch(e.toLowerCase()){case"micrometer":case"um":case"\xb5m":return t/1e3;case"nanometer":case"nm":return t/1e6;case"millimeter":case"mm":default:return t;case"centimeter":case"cm":return 10*t;case"meter":case"m":return 1e3*t}}var Yi=class t{constructor(t){C(this,"hostImage"),C(this,"chunkClient"),C(this,"chunkCache"),C(this,"pyramidInfo"),C(this,"datatypeCode"),C(this,"pyramidLevel"),C(this,"levelDims"),C(this,"volumeDims"),C(this,"chunkSize"),C(this,"voxelScales"),C(this,"voxelTranslations"),C(this,"hasTranslations"),C(this,"convertUnitsToMm"),C(this,"worldOffsetMM",[0,0,0]),C(this,"centerX"),C(this,"centerY"),C(this,"centerZ"),C(this,"channel"),C(this,"nonSpatialCoords",{}),C(this,"isUpdating",!1),C(this,"needsUpdate",!1),C(this,"currentAbortController",null),C(this,"runningMin",1/0),C(this,"runningMax",-1/0),C(this,"calibrationDone",!1),C(this,"updateDebounceTimer",null),C(this,"UPDATE_DEBOUNCE_MS",50),C(this,"pendingChunkCount",0),C(this,"lastRenderedChunkCount",0),C(this,"centerAtDragStart",null),C(this,"onChunksUpdated"),C(this,"onAllChunksLoaded"),this.hostImage=t,this.chunkClient=null,this.chunkCache=null,this.pyramidInfo=null,this.datatypeCode=2,this.pyramidLevel=0,this.levelDims={width:0,height:0,depth:0},this.volumeDims={width:0,height:0,depth:0},this.chunkSize={width:0,height:0,depth:0},this.voxelScales={width:1,height:1,depth:1},this.voxelTranslations={width:0,height:0,depth:0},this.hasTranslations=!1,this.convertUnitsToMm=!0,this.centerX=0,this.centerY=0,this.centerZ=0,this.channel=0}static async create(e,i,n){const r=new t(e);r.chunkClient=new ki({baseUrl:i}),r.pyramidInfo=await r.chunkClient.fetchInfo(),r.chunkCache=new Oi(n.cacheSize??500);const a=n.maxTextureSize??2048,s=n.maxVolumeSize??256,o=r.pyramidInfo.levels[0].shape;o.every((t=>t<=s&&t<=a))?r.pyramidInfo.is3D&&o.length>
1=3?r.volumeDims={depth:o[0],height:o[1],width:o[2]}:r.volumeDims={height:o[0],width:o[1],depth:1}:r.volumeDims={width:Math.min(s,a),height:Math.min(s,a),depth:Math.min(s,a)},r.datatypeCode=function(t){const e=t.toLowerCase().replace(/[<>|]/g,"");return"u1"===e||"uint8"===e?2:"i1"===e||"int8"===e?256:"u2"===e||"uint16"===e?512:"i2"===e||"int16"===e?4:"u4"===e||"uint32"===e?768:"i4"===e||"int32"===e?8:"f4"===e||"float32"===e?16:"f8"===e||"float64"===e?64:(console.warn(`Unknown zarr dtype: ${t}, defaulting to uint8`),2)}(r.pyramidInfo.levels[0].dtype),r.convertUnitsToMm=n.convertUnitsToMm??!0,r.channel=n.channel??0;const l=r.pyramidInfo.axisMapping;for(const t of l.nonSpatialAxes)"c"===t.name&&(r.nonSpatialCoords[t.name]=r.channel);const c=Math.max(0,Math.min(n.level,r.pyramidInfo.levels.length-1));return r.pyramidLevel=c,r.updateLevelInfo(),r.centerX=r.levelDims.width/2,r.centerY=r.levelDims.height/2,r.centerZ=r.levelDims.depth/2,r.configureHostImage(),r}async loadInitialChunks(){await this.updateVolume()}updateLevelInfo(){const t=this.pyramidInfo.levels[this.pyramidLevel],e=t.shape;this.pyramidInfo.is3D&&e.length>=3?this.levelDims={depth:e[0],height:e[1],width:e[2]}:this.levelDims={height:e[0],width:e[1],depth:1};const i=t.chunks;this.pyramidInfo.is3D&&i.length>=3?this.chunkSize={depth:i[0],height:i[1],width:i[2]}:this.chunkSize={height:i[0],width:i[1],depth:1},t.scales?this.pyramidInfo.is3D&&t.scales.length>=3?this.voxelScales={depth:t.scales[0],height:t.scales[1],width:t.scales[2]}:t.scales.length>=2&&(this.voxelScales={height:t.scales[0],width:t.scales[1],depth:1}):this.voxelScales={width:1,height:1,depth:1},t.translations?(this.pyramidInfo.is3D&&t.translations.length>=3?this.voxelTranslations={depth:t.translations[0],height:t.translations[1],width:t.translations[2]}:t.translations.length>=2&&(this.voxelTranslations={height:t.translations[0],width:t.translations[1],depth:0}),this.hasTranslations=!0):(this.voxelTranslations={width:0,height:0,depth:0},this.hasTranslations=!1)}configureHostImage(){const{width:t,height:e,depth:i}=this.volumeDims,n=function(t){switch(t){case 2:case 256:default:return 1;case 512:case 4:return 2;case 768:case 8:case 16:return 4;case 64:return 8}}(this.datatypeCode),{scaleW:r,scaleH:a,scaleD:s}=this.getConvertedScales(),l=new h.a;l.littleEndian=!0,l.dims=[3,t,e,i,1,0,0,0],l.pixDims=[1,r,a,s,1,0,0,0],l.datatypeCode=this.datatypeCode,l.numBitsPerVoxel=8*n,l.scl_inter=0,l.scl_slope=1,l.sform_code=2,l.magic="n+1",l.vox_offset=352,l.affine=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]];const c=this.hostImage;c.name=`zarr:${this.pyramidInfo.name}`,c.id=(0,o.v4)(),c._colormap="gray",c._opacity=1,c.hdr=l,c.nFrame4D=1,c.frame4D=0,c.nTotalFrame4D=1,c.nVox3D=t*e*i,c.dims=[t,e,i],c.pixDims=[r,a,s],c.img=function(t,e){switch(t){case 2:case 256:default:return new Uint8Array(e);case 512:return new Uint16Array(e);case 4:return new Int16Array(e);case 8:return new Int32Array(e);case 768:return new Uint32Array(e);case 16:return new Float32Array(e);case 64:return new Float64Array(e)}}(this.datatypeCode,t*e*i),this.updateAffine(),c.originalAffine=Li(l.affine),c.cal_min=0,c.cal_max=0,c.robust_min=0,c.robust_max=0,c.global_min=0,c.global_max=0}getConvertedScales(){const t=this.pyramidInfo.spatialUnits;let e=this.voxelScales.depth,i=this.voxelScales.height,n=this.voxelScales.width;return this.convertUnitsToMm&&t&&(t.length>=3?(e=zi(e,t[0]),i=zi(i,t[1]),n=zi(n,t[2])):t.length>=2&&(i=zi(i,t[0]),n=zi(n,t[1]))),{scaleW:n,scaleH:i,scaleD:e}}getConvertedTranslations(){const t=this.pyramidInfo.spatialUnits;let e=this.voxelTranslations.depth,i=this.voxelTranslations.height,n=this.voxelTranslations.width;return this.convertUnitsToMm&&t&&(t.length>=3?(e=zi(e,t[0]),i=zi(i,t[1]),n=zi(n,t[2])):t.length>=2&&(i=zi(i,t[0]),n=zi(n,t[1]))),{transW:n,transH:i,transD:e}}updateAffine(){const t=this.hostImage.hdr;if(!t)return;const{width:e,height:i,depth:n}=this.volumeDims,r=this.pyramidInfo.axisMapping.spatialAxisNames;if(this.hasTranslations&&r.length>=3){const{scaleW:a,scaleH:s,scaleD:o}=this.getConvertedScales(),{transW:l,transH:c,transD:h}=this.getConvertedTranslations(),d=this.centerX-e/2,u=this.centerY-i/2,m=this.centerZ-n/2,f=[{name:r[r.length-1],scale:a,trans:l+d*a},{name:r[r.length-2],scale:s,trans:c+u*s},{name:r[r.length-3],scale:o,trans:h+m*o}],g=[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,1]];for(let t=0;t<3;t++){const e="x"===f[t].name?0:"y"===f[t].name?1:2;g[e][t]=f[t].scale,g[e][3]=f[t].trans}g[0][3]+=this.worldOffsetMM[0],g[1][3]+=this.worldOffsetMM[1],g[2][3]+=this.worldOffsetMM[2],t.affine=g}else{const{scaleW:a,scaleH:s,scaleD:o}=this.getConvertedScales(),l=this.centerX-e/2,c=this.centerY-i/2,h=this.centerZ-n/2;if(r.length>=2){const e=[{name:r[r.length-1],scale:a,trans:l*a},{name:r[r.length-2],scale:s,trans:c*s},{name:"z",scale:o,trans:h*o}],i=[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,1]];for(let t=0;t<3;t++){const n="x"===e[t].name?0:"y"===e[t].name?1:2;i[n][t]=e[t].scale,i[n][3]=e[t].trans}i[0][3]+=this.worldOffsetMM[0],i[1][3]+=this.worldOffsetMM[1],i[2][3]+=this.worldOffsetMM[2],t.affine=i}else t.affine=[[a,0,0,l*a+this.worldOffsetMM[0]],[0,-s,0,c*s+this.worldOffsetMM[1]],[0,0,-o,h*o+this.worldOffsetMM[2]],[0,0,0,1]]}this.hostImage.calculateRAS(),this.hostImage.originalAffine=Li(this.hostImage.hdr.affine)}beginDrag(){this.centerAtDragStart={x:this.centerX,y:this.centerY,z:this.centerZ}}endDrag(){this.centerAtDragStart=null}
1async panBy(t,e,i){void 0===i&&(i=0),this.centerX-=t,this.centerY-=e,this.centerZ-=i,this.clampCenter(),this.updateAffine(),await this.updateVolume()}async panTo(t,e,i){const n=this.centerX,r=this.centerY,a=this.centerZ;this.centerX=t,this.centerY=e,void 0!==i&&(this.centerZ=i),this.clampCenter(),Math.abs(this.centerX-n)<.001&&Math.abs(this.centerY-r)<.001&&Math.abs(this.centerZ-a)<.001||(this.updateAffine(),await this.updateVolume())}async setPyramidLevel(t){const e=Math.max(0,Math.min(this.pyramidInfo.levels.length-1,t));if(e===this.pyramidLevel)return;const i=this.levelDims;this.pyramidLevel=e,this.updateLevelInfo();const n=this.levelDims;this.centerX=this.centerX/i.width*n.width,this.centerY=this.centerY/i.height*n.height,this.centerZ=this.centerZ/i.depth*n.depth,this.clampCenter(),this.updateAffine(),await this.updateVolume()}getViewportState(){return{centerX:this.centerX,centerY:this.centerY,centerZ:this.centerZ,level:this.pyramidLevel}}getPyramidInfo(){return this.pyramidInfo}getPyramidLevel(){return this.pyramidLevel}getLevelDims(){return{...this.levelDims}}getVolumeDims(){return{...this.volumeDims}}getWorldOffset(){return[...this.worldOffsetMM]}setWorldCenter(t){const{scaleW:e,scaleH:i,scaleD:n}=this.getConvertedScales(),{transW:r,transH:a,transD:s}=this.getConvertedTranslations(),o=this.pyramidInfo.axisMapping.spatialAxisNames,l=this.levelDims.width/2*e+r,c=this.levelDims.height/2*i+a,h=this.levelDims.depth/2*n+s,d=[0,0,0],u=[{name:o[o.length-1],phys:l},{name:o[o.length-2],phys:c},{name:o.length>=3?o[o.length-3]:"z",phys:h}];for(const m of u){d["x"===m.name?0:"y"===m.name?1:2]=m.phys}this.worldOffsetMM=[t[0]-d[0],t[1]-d[1],t[2]-d[2]],this.centerX=this.levelDims.width/2,this.centerY=this.levelDims.height/2,this.centerZ=this.levelDims.depth/2,this.clampCenter(),this.updateAffine()}mmToLevelCoords(t,e,i){t-=this.worldOffsetMM[0],e-=this.worldOffsetMM[1],i-=this.worldOffsetMM[2];const{scaleW:n,scaleH:r,scaleD:a}=this.getConvertedScales(),s=this.pyramidInfo.axisMapping.spatialAxisNames,o={x:t,y:e,z:i};let l=0,c=0,h=0;if(s.length>=2){const d=s[s.length-1],u=s[s.length-2],m=s.length>=3?s[s.length-3]:"z",f=o[d]??t,g=o[u]??e,A=o[m]??i;if(this.hasTranslations){const{transW:t,transH:e,transD:i}=this.getConvertedTranslations();l=0!==n?(f-t)/n:0,c=0!==r?(g-e)/r:0,h=0!==a?(A-i)/a:0}else l=0!==n?f/n:0,c=0!==r?g/r:0,h=0!==a?A/a:0}else if(this.hasTranslations){const{transW:s,transH:o,transD:d}=this.getConvertedTranslations();l=0!==n?(t-s)/n:0,c=0!==r?(e-o)/r:0,h=0!==a?(i-d)/a:0}else l=0!==n?t/n:0,c=0!==r?e/r:0,h=0!==a?i/a:0;return{width:Math.round(l),height:Math.round(c),depth:Math.round(h),level:this.pyramidLevel,levelDims:{...this.levelDims}}}clampCenter(){const t=this.volumeDims.width/2,e=this.volumeDims.height/2,i=this.volumeDims.depth/2;this.centerX=Math.max(-t,Math.min(this.levelDims.width+t,this.centerX)),this.centerY=Math.max(-e,Math.min(this.levelDims.height+e,this.centerY)),this.centerZ=Math.max(-i,Math.min(this.levelDims.depth+i,this.centerZ))}getVisibleChunks(){const t=1e3,{width:e,height:i,depth:n}=this.volumeDims,r=this.pyramidLevel,a=Math.max(0,Math.floor(this.centerX-e/2)),s=Math.min(this.levelDims.width,Math.ceil(this.centerX+e/2)),o=Math.max(0,Math.floor(this.centerY-i/2)),l=Math.min(this.levelDims.height,Math.ceil(this.centerY+i/2)),c=Math.max(0,Math.floor(this.centerZ-n/2)),h=Math.min(this.levelDims.depth,Math.ceil(this.centerZ+n/2)),d=Math.max(0,Math.floor(a/this.chunkSize.width)),u=Math.max(0,Math.floor(o/this.chunkSize.height)),m=Math.max(0,Math.floor(c/this.chunkSize.depth)),f=Math.min(Math.ceil(this.levelDims.width/this.chunkSize.width),Math.ceil(s/this.chunkSize.width)),g=Math.min(Math.ceil(this.levelDims.height/this.chunkSize.height),Math.ceil(l/this.chunkSize.height)),A=Math.min(Math.ceil(this.levelDims.depth/this.chunkSize.depth),Math.ceil(h/this.chunkSize.depth)),p=[];for(let y=m;y<A;y++){for(let e=u;e<g;e++){for(let i=d;i<f&&(this.pyramidInfo.is3D?p.push({level:r,x:i,y:e,z:y}):p.push({level:r,x:i,y:e}),!(p.length>=t));i++);if(p.length>=t)break}if(p.length>=t)break}const v=(d+f)/2,x=(u+g)/2,w=(m+A)/2;return p.sort(((t,e)=>(t.x-v)**2+(t.y-x)**2+((t.z??0)-w)**2-((e.x-v)**2+(e.y-x)**2+((e.z??0)-w)**2))),p}async updateVolume(){if(this.isUpdating)return this.needsUpdate=!0,void this.currentAbortController?.abort();this.isUpdating=!0;try{do{this.needsUpdate=!1,this.currentAbortController?.abort();const t=new AbortController;this.currentAbortController=t,await new Promise((t=>{requestAnimationFrame((()=>t()))})),this.needsUpdate||(this.clearVolumeData(),await this.assembleVisibleChunks(t.signal))}while(this.needsUpdate)}finally{this.isUpdating=!1}}clearVolumeData(){const t=this.hostImage.img;if(t.fill)t.fill(0);else for(let e=0;e<t.length;e++)t[e]=0;this.pendingChunkCount=0,this.lastRenderedChunkCount=0,null!==this.updateDebounceTimer&&(clearTimeout(this.updateDebounceTimer),this.updateDebounceTimer=null)}async assembleVisibleChunks(t){const e=this.getVisibleChunks(),i=this.pyramidInfo.name,n=this.pyramidLevel,r=[],a=[];for(const s of e){const t=Oi.getKey(i,s.level,s.x,s.y,s.z);this.chunkCache.has(t)?r.push(s):this.chunkCache.isLoading(t)||a.push(s)}for(const s of r){const t=Oi.getKey(i,s.level,s.x,s.y,s.z),e=this.chunkCache.get(t);
1e&&(this.assembleChunkIntoVolume(s,e),this.pendingChunkCount++)}if(r.length>0&&(this.updateCalibration(),this.onChunksUpdated?.()),a.length>0){const e=a.map((async e=>{const r=Oi.getKey(i,e.level,e.x,e.y,e.z);this.chunkCache.startLoading(r);try{const i=await this.chunkClient.fetchChunk(e.level,e.x,e.y,e.z,this.nonSpatialCoords,t);if(this.chunkCache.doneLoading(r),t?.aborted)return;i&&(this.chunkCache.set(r,i),this.pyramidLevel===n&&(this.assembleChunkIntoVolume(e,i),this.pendingChunkCount++,this.scheduleChunksUpdated()))}catch(a){if(this.chunkCache.doneLoading(r),a instanceof DOMException&&"AbortError"===a.name)return;console.warn(`Failed to fetch chunk ${r}:`,a)}}));await Promise.all(e),null!==this.updateDebounceTimer&&(clearTimeout(this.updateDebounceTimer),this.updateDebounceTimer=null),this.pendingChunkCount>this.lastRenderedChunkCount&&(this.lastRenderedChunkCount=this.pendingChunkCount,this.updateCalibration(),this.onChunksUpdated?.()),this.onAllChunksLoaded?.()}}assembleChunkIntoVolume(t,e){const{width:i,height:n,depth:r}=this.volumeDims,a=this.hostImage.img,s=t.x*this.chunkSize.width,o=t.y*this.chunkSize.height,l=(t.z??0)*this.chunkSize.depth,c=this.centerX-i/2,h=this.centerY-n/2,d=this.centerZ-r/2,u=Math.round(s-c),m=Math.round(o-h),f=Math.round(l-d),g=Math.min(this.chunkSize.width,this.levelDims.width-s),A=Math.min(this.chunkSize.height,this.levelDims.height-o),p=Math.min(this.chunkSize.depth,this.levelDims.depth-l);if(g<=0||A<=0||p<=0)return;if(!this.calibrationDone){const t=Math.max(1,Math.floor(e.length/2e3));for(let i=0;i<e.length;i+=t){const t=e[i];t<this.runningMin&&(this.runningMin=t),t>this.runningMax&&(this.runningMax=t)}}const v=this.chunkSize.width*this.chunkSize.height*this.chunkSize.depth,x=e.length>=v?this.chunkSize.width:g,w=e.length>=v?this.chunkSize.height:A;for(let y=0;y<p;y++){const t=f+y;if(!(t<0||t>=r))for(let r=0;r<A;r++){const s=m+r;if(!(s<0||s>=n))for(let o=0;o<g;o++){const l=u+o;if(l<0||l>=i)continue;const c=y*w*x+r*x+o,h=l+s*i+t*i*n;c>=0&&c<e.length&&h>=0&&h<a.length&&(a[h]=e[c])}}}}updateCalibration(){this.calibrationDone||this.runningMin<1/0&&this.runningMax>-1/0&&(this.hostImage.cal_min=this.runningMin,this.hostImage.cal_max=this.runningMax,this.hostImage.robust_min=this.runningMin,this.hostImage.robust_max=this.runningMax,this.hostImage.global_min=this.runningMin,this.hostImage.global_max=this.runningMax,this.calibrationDone=!0)}scheduleChunksUpdated(){this.pendingChunkCount!==this.lastRenderedChunkCount&&(null!==this.updateDebounceTimer&&clearTimeout(this.updateDebounceTimer),this.updateDebounceTimer=setTimeout((()=>{this.updateDebounceTimer=null,this.lastRenderedChunkCount=this.pendingChunkCount,this.updateCalibration(),this.onChunksUpdated?.()}),this.UPDATE_DEBOUNCE_MS))}clearCache(){this.chunkCache.clear()}async refresh(){await this.updateVolume()}},Gi=class t{constructor(t,e,i,n,r,a,s,o,l,c,h,d,u,m,f,g,A,p,v){void 0===t&&(t=null),void 0===e&&(e=""),void 0===i&&(i="gray"),void 0===n&&(n=1),void 0===r&&(r=null),void 0===a&&(a=NaN),void 0===s&&(s=NaN),void 0===o&&(o=!0),void 0===l&&(l=.02),void 0===c&&(c=!1),void 0===h&&(h=!1),void 0===d&&(d=""),void 0===u&&(u=0),void 0===m&&(m=Ve.UNKNOWN),void 0===f&&(f=NaN),void 0===g&&(g=NaN),void 0===A&&(A=!0),void 0===p&&(p=null),void 0===v&&(v=0),C(this,"name"),C(this,"id"),C(this,"url"),C(this,"headers"),C(this,"_colormap"),C(this,"_opacity"),C(this,"percentileFrac"),C(this,"ignoreZeroVoxels"),C(this,"trustCalMinMax"),C(this,"colormapNegative"),C(this,"colormapLabel"),C(this,"colormapInvert"),C(this,"nFrame4D"),C(this,"frame4D"),C(this,"nTotalFrame4D"),C(this,"cal_minNeg"),C(this,"cal_maxNeg"),C(this,"colorbarVisible",!0),C(this,"modulationImage",null),C(this,"modulateAlpha",0),C(this,"series",[]),C(this,"nVox3D"),C(this,"oblique_angle"),C(this,"maxShearDeg"),C(this,"useQFormNotSForm"),C(this,"colormapType"),C(this,"pixDims"),C(this,"matRAS"),C(this,"pixDimsRAS"),C(this,"obliqueRAS"),C(this,"dimsRAS"),C(this,"permRAS"),C(this,"img2RASstep"),C(this,"img2RASstart"),C(this,"toRAS"),C(this,"toRASvox"),C(this,"frac2mm"),C(this,"frac2mmOrtho"),C(this,"extentsMinOrtho"),C(this,"extentsMaxOrtho"),C(this,"mm2ortho"),C(this,"hdr",null),C(this,"extensions"),C(this,"imageType"),C(this,"img"),C(this,"imaginary"),C(this,"v1"),C(this,"fileObject"),C(this,"dims"),C(this,"onColormapChange",(()=>{})),C(this,"onOpacityChange",(()=>{})),C(this,"zarrHelper",null),C(this,"_hasExplicitZarrCenter",!1),C(this,"mm000"),C(this,"mm100"),C(this,"mm010"),C(this,"mm001"),C(this,"cal_min"),C(this,"cal_max"),C(this,"robust_min"),C(this,"robust_max"),C(this,"global_min"),C(this,"global_max"),C(this,"urlImgData"),C(this,"isManifest"),C(this,"limitFrames4D"),C(this,"originalAffine"),this.init(t,e,i,n,r,a,s,o,l,c,h,d,u,m,f,g,A,p,v)}init(t,e,i,n,r,a,s,l,c,h,d,u,m,f,g,A,p,v,x,w){void 0===t&&(t=null),void 0===e&&(e=""),void 0===i&&(i=""),void 0===n&&(n=1),void 0===r&&(r=null),void 0===a&&(a=NaN),void 0===s&&(s=NaN),void 0===l&&(l=!0),void 0===c&&(c=.02),void 0===h&&(h=!1),void 0===d&&(d=!1),void 0===u&&(u=""),void 0===m&&(m=0),void 0===f&&(f=Ve.UNKNOWN),void 0===g&&(g=NaN),void 0===A&&(A=NaN),void 0===p&&(p=!0),void 0===v&&(v=null),void 0===x&&(x=0),void 0===w&&(w=null);const y=""===i;if(y&&(i="gray"),this.name=e,this.imageType=f,this.id=(0,o.v4)(),this._colormap=i,this._opacity=n>1?1:n,this.percentileFrac=c,this.ignoreZeroVoxels=h,this.trustCalMinMax=l,this.colormapNegative=u,this.colormapLabel=v,this.frame4D=m,this.cal_minNeg
1=g,this.cal_maxNeg=A,this.colorbarVisible=p,this.colormapType=x,this.useQFormNotSForm=d,!t)return;if(y&&this.hdr&&1002===this.hdr.intent_code&&(i="random",this._colormap=i),this.hdr&&"number"==typeof this.hdr.magic&&(this.hdr.magic="n+1"),this.nFrame4D=1,this.hdr)for(let o=4;o<7;o++)this.hdr.dims[o]>1&&(this.nFrame4D*=this.hdr.dims[o]);if(this.frame4D=Math.min(this.frame4D,this.nFrame4D-1),this.nTotalFrame4D=this.nFrame4D,!this.hdr||!w)return;0===this.hdr.dims[1]&&0===this.hdr.dims[2]&&0===this.hdr.dims[3]&&Q.warn("Invalid volume: First three dimensions are all zero"),this.hdr.dims[1]=Math.max(this.hdr.dims[1],1),this.hdr.dims[2]=Math.max(this.hdr.dims[2],1),this.hdr.dims[3]=Math.max(this.hdr.dims[3],1),this.nVox3D=this.hdr.dims[1]*this.hdr.dims[2]*this.hdr.dims[3];const b=this.nVox3D*(this.hdr.numBitsPerVoxel/8),C=w.byteLength/b;C!==this.nFrame4D&&(C>0&&C*b===w.byteLength?Q.debug("Loading the first "+C+" of "+this.nFrame4D+" volumes"):Q.warn("This header does not match voxel data",this.hdr,w.byteLength),this.nFrame4D=C),1007!==this.hdr.intent_code&&2003!==this.hdr.intent_code||3!==this.nFrame4D||16!==this.hdr.datatypeCode||(w=this.float32V1asRGBA(new Float32Array(w)).buffer),Ui(this.hdr,d),function(t,e){if(!(128===e.datatypeCode||2304===e.datatypeCode||e.littleEndian===Fe()||e.numBitsPerVoxel<=8))if(16===e.numBitsPerVoxel){const e=new Uint16Array(t);for(let t=0;t<e.length;t++){const i=e[t];e[t]=((255&i)<<8|i>>8&255)<<16>>16}}else if(32===e.numBitsPerVoxel){const e=new Uint32Array(t);for(let t=0;t<e.length;t++){const i=e[t];e[t]=(255&i)<<24|(65280&i)<<8|i>>8&65280|i>>24&255}}else if(64===e.numBitsPerVoxel){const i=e.numBitsPerVoxel/8,n=new Uint8Array(t);for(let t=0;t<n.length;t+=i){let e=i-1;for(let i=0;i<e;i++){const r=n[t+i];n[t+i]=n[t+e],n[t+e]=r,e--}}}}(w,this.hdr);const M=function(t,e){switch(e.datatypeCode){case 2:case 128:case 2304:return{img:new Uint8Array(t)};case 4:return{img:new Int16Array(t)};case 16:return{img:new Float32Array(t)};case 64:return{img:new Float64Array(t)};case 512:return{img:new Uint16Array(t)};case 256:{const e=new Int8Array(t),i=e.length,n=new Int16Array(i);for(let t=0;t<i;t++)n[t]=e[t];return{img:n,updatedDatatypeCode:4,updatedNumBitsPerVoxel:16}}case 1:{const i=e.dims[1]*e.dims[2]*Math.max(1,e.dims[3])*Math.max(1,e.dims[4]),n=new Uint8Array(t),r=new Uint8Array(i),a=new Uint8Array(8);for(let t=0;t<8;t++)a[t]=Math.pow(2,t);let s=-1;for(let t=0;t<i;t++){const e=t%8;0===e&&s++,n[s]&a[e]&&(r[t]=1)}return{img:r,updatedDatatypeCode:2,updatedNumBitsPerVoxel:8}}case 768:{const e=new Uint32Array(t),i=e.length,n=new Float64Array(i);for(let t=0;t<i-1;t++)n[t]=e[t];return{img:n,updatedDatatypeCode:64}}case 8:{const e=new Int32Array(t),i=e.length,n=new Float64Array(i);for(let t=0;t<i-1;t++)n[t]=e[t];return{img:n,updatedDatatypeCode:64}}case 1024:{const e=new BigInt64Array(t),i=e.length,n=new Float64Array(i);for(let t=0;t<i-1;t++)n[t]=Number(e[t]);return{img:n,updatedDatatypeCode:64}}case 32:{const e=new Float32Array(t),i=Math.floor(e.length/2),n=new Float32Array(i),r=new Float32Array(i);let a=0;for(let t=0;t<i-1;t++)r[t]=e[a],n[t]=e[a+1],a+=2;return{img:r,imaginary:n,updatedDatatypeCode:16}}default:throw new Error("datatype "+e.datatypeCode+" not supported")}}(w,this.hdr);this.img=M.img,M.imaginary&&(this.imaginary=M.imaginary),void 0!==M.updatedDatatypeCode&&(this.hdr.datatypeCode=M.updatedDatatypeCode),void 0!==M.updatedNumBitsPerVoxel&&(this.hdr.numBitsPerVoxel=M.updatedNumBitsPerVoxel),this.calculateRAS(),this.originalAffine=Li(this.hdr.affine),isNaN(a)||(this.hdr.cal_min=a),isNaN(s)||(this.hdr.cal_max=s),this.calMinMax()}static async new(e,i,n,r,a,s,o,l,c,h,d,u,m,f,g,A,p,v,x,w){void 0===e&&(e=null),void 0===i&&(i=""),void 0===n&&(n=""),void 0===r&&(r=1),void 0===a&&(a=null),void 0===s&&(s=NaN),void 0===o&&(o=NaN),void 0===l&&(l=!0),void 0===c&&(c=.02),void 0===h&&(h=!1),void 0===d&&(d=!1),void 0===u&&(u=""),void 0===m&&(m=0),void 0===f&&(f=Ve.UNKNOWN),void 0===g&&(g=NaN),void 0===A&&(A=NaN),void 0===p&&(p=!0),void 0===v&&(v=null),void 0===x&&(x=0);const y=new t,b=/(?:\.([^.]+))?$/;let C=b.exec(i)[1]||"";C=C.toUpperCase(),"GZ"===C&&(C=b.exec(i.slice(0,-3))[1],C=C.toUpperCase());let M=null;if(f===Ve.UNKNOWN&&(f=Ve.parse(C)),e instanceof ArrayBuffer&&e.byteLength>=2&&f===Ve.DCM){const t=new Uint8Array(e);(92===t[0]&&1===t[1]||92===t[1]&&1===t[0])&&(f=Ve.NII)}switch(y.imageType=f,f){case Ve.DCM_FOLDER:case Ve.DCM_MANIFEST:case Ve.DCM:return;case Ve.FIB:[M,y.v1]=await qe.readFIB(y,e);break;case Ve.MIH:case Ve.MIF:M=await ci.readMIF(y,e,a);break;case Ve.NHDR:case Ve.NRRD:if(M=await mi.readNrrd(y,e),null===M)throw new Error(`Failed to parse NHDR/NRRD file ${i}`);break;case Ve.MHD:case Ve.MHA:M=await ii.readMHA(y,e,a);break;case Ve.MGH:case Ve.MGZ:if(M=await ri.readMgh(y,e,i),null===M)throw new Error(`Failed to parse MGH/MGZ file ${i}`);break;case Ve.SRC:M=await qe.readSRC(y,e);break;case Ve.V:M=Je.readECAT(y,e);break;case Ve.V16:M=Ke.readV16(y,e);break;case Ve.VMR:M=Ke.readVMR(y,e);break;case Ve.HEAD:M=await Ge.readHEAD(y,e,a);break;case Ve.BMP:M=await $e.readBMP(y,e);break;case Ve.NPY:M=await gi.readNPY(y,e);break;case Ve.NPZ:M=await gi.readNPZ(y,e);break;case Ve.ZARR:M=await vi.readZARR(y,e,w);break;case Ve.NII:if(M=await di.readNifti(y,e,a),null===M)throw new Error(`Failed to parse NIfTI file ${i}.`);break;default:throw new Error("Image type not supported")}return y.init(e,i,n,r,a,s,o,l,c,h,d,u,m,f,g,A,p,v,x,M),y}computeObliqueAngle(t){return Ci(t)}float32V1asRGBA(t){return Di(this,t)}loadImgV1(t,e,i){return void 0===t&&(t=!1),void 0===e&&(e=!1),void 0===i&&(i=!1),function(t,e,
1i,n){void 0===e&&(e=!1),void 0===i&&(i=!1),void 0===n&&(n=!1);let r=t.v1;if(r||3!==t.nFrame4D||t.img.constructor!==Float32Array||(r=t.img.slice()),!r)return Q.warn("Image does not have V1 data"),!1;if(e)for(let a=0;a<t.nVox3D;a++)r[a]=-r[a];if(i)for(let a=t.nVox3D;a<2*t.nVox3D;a++)r[a]=-r[a];if(n)for(let a=2*t.nVox3D;a<3*t.nVox3D;a++)r[a]=-r[a];return t.img=Di(t,r),!0}(this,t,e,i)}calculateOblique(){Mi(this)}readECAT(t){return Je.readECAT(this,t)}readV16(t){return Ke.readV16(this,t)}async readNPY(t){return gi.readNPY(this,t)}async readNPZ(t){return gi.readNPZ(this,t)}async imageDataFromArrayBuffer(t){return $e.imageDataFromArrayBuffer(t)}async readBMP(t){return $e.readBMP(this,t)}async readZARR(t,e){return vi.readZARR(this,t,e)}readVMR(t){return Ke.readVMR(this,t)}async readFIB(t){return qe.readFIB(this,t)}async readSRC(t){return qe.readSRC(this,t)}async readHEAD(t,e){return Ge.readHEAD(this,t,e)}async readMHA(t,e){return ii.readMHA(this,t,e)}async readMIF(t,e){return ci.readMIF(this,t,e)}calculateRAS(){!function(t){if(!t.hdr)throw new Error("hdr not set");const e=t.hdr.affine,i=t.hdr,n=u.fA(Math.abs(e[0][0]),Math.abs(e[0][1]),Math.abs(e[0][2]),Math.abs(e[1][0]),Math.abs(e[1][1]),Math.abs(e[1][2]),Math.abs(e[2][0]),Math.abs(e[2][1]),Math.abs(e[2][2])),r=[1,1,1];n[3]>n[0]&&(r[0]=2),n[6]>n[0]&&n[6]>n[3]&&(r[0]=3),r[1]=1,1===r[0]?n[4]>n[7]?r[1]=2:r[1]=3:2===r[0]?n[1]>n[7]?r[1]=1:r[1]=3:n[1]>n[4]?r[1]=1:r[1]=2,r[2]=6-r[1]-r[0];let s=[1,2,3];s[r[0]-1]=1,s[r[1]-1]=2,s[r[2]-1]=3;let o=a.fA(e[0][0],e[0][1],e[0][2],e[0][3],e[1][0],e[1][1],e[1][2],e[1][3],e[2][0],e[2][1],e[2][2],e[2][3],0,0,0,1);t.mm000=wi(0,[-.5,-.5,-.5],o),t.mm100=wi(0,[i.dims[1]-.5,-.5,-.5],o),t.mm010=wi(0,[-.5,i.dims[2]-.5,-.5],o),t.mm001=wi(0,[-.5,-.5,i.dims[3]-.5],o);const l=a.vt();a.C(l,o);for(let a=0;a<3;a++)for(let t=0;t<3;t++)l[4*a+t]=o[4*a+s[t]-1];const c=[0,0,0];l[0]<0&&(c[0]=1),l[5]<0&&(c[1]=1),l[10]<0&&(c[2]=1),t.dimsRAS=[i.dims[0],i.dims[s[0]],i.dims[s[1]],i.dims[s[2]]],t.pixDimsRAS=[i.pixDims[0],i.pixDims[s[0]],i.pixDims[s[1]],i.pixDims[s[2]]],t.permRAS=s.slice();for(let a=0;a<3;a++)1===c[a]&&(t.permRAS[a]=-t.permRAS[a]);if(bi(s,[1,2,3])&&bi(c,[0,0,0]))return t.toRAS=a.vt(),t.matRAS=a.o8(o),Mi(t),t.img2RASstep=[1,t.dimsRAS[1],t.dimsRAS[1]*t.dimsRAS[2]],void(t.img2RASstart=[0,0,0]);a.D_(o),o[0]=1-2*c[0],o[5]=1-2*c[1],o[10]=1-2*c[2],o[3]=(i.dims[s[0]]-1)*c[0],o[7]=(i.dims[s[1]]-1)*c[1],o[11]=(i.dims[s[2]]-1)*c[2];const h=a.vt();a.B8(h,o),a.lw(h,h,l),t.matRAS=a.o8(h),o=a.fA(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),o[s[0]-1+0]=2*-c[0]+1,o[s[1]-1+4]=2*-c[1]+1,o[s[2]-1+8]=2*-c[2]+1,o[3]=c[0],o[7]=c[1],o[11]=c[2],t.toRAS=a.o8(o),o[3]=0,o[7]=0,o[11]=0,o[12]=0,-1!==t.permRAS[0]&&-1!==t.permRAS[1]&&-1!==t.permRAS[2]||(o[12]=i.dims[1]-1),o[13]=0,-2!==t.permRAS[0]&&-2!==t.permRAS[1]&&-2!==t.permRAS[2]||(o[13]=i.dims[2]-1),o[14]=0,-3!==t.permRAS[0]&&-3!==t.permRAS[1]&&-3!==t.permRAS[2]||(o[14]=i.dims[3]-1),t.toRASvox=a.o8(o),Q.debug(t.hdr.dims),Q.debug(t.dimsRAS);const d=t.hdr;s=t.permRAS;const m=[Math.abs(s[0]),Math.abs(s[1]),Math.abs(s[2])],f=[d.dims[m[0]],d.dims[m[1]],d.dims[m[2]]],g=[1,d.dims[1],d.dims[1]*d.dims[2]],A=[g[m[0]-1],g[m[1]-1],g[m[2]-1]],p=[0,0,0];for(let a=0;a<3;a++)s[a]<0&&(p[a]=A[a]*(f[a]-1),A[a]=-A[a]);t.img2RASstep=A,t.img2RASstart=p,Mi(t)}(this)}getAffine(){if(!this.hdr)throw new Error("Image header not loaded");return Li(this.hdr.affine)}setAffine(t){if(!this.hdr)throw new Error("Image header not loaded");this.hdr.affine=Li(t),this.calculateRAS()}applyTransform(t){if(!this.hdr)throw new Error("Image header not loaded");const e=Pi(t),i=Ni(this.hdr.affine,e);this.hdr.affine=i,this.calculateRAS()}resetAffine(){if(!this.hdr)throw new Error("Image header not loaded");if(!this.originalAffine)throw new Error("Original affine not stored");this.hdr.affine=Li(this.originalAffine),this.calculateRAS()}async hdr2RAS(t){return void 0===t&&(t=1),async function(t,e){if(void 0===e&&(e=1),!t.permRAS)throw new Error("permRAS undefined");if(!t.hdr)throw new Error("hdr undefined");const i=Pe({...t.hdr,vox_offset:352},!1),n=await(0,c.Ad)(i.buffer,!0);1===e?(n.dims[0]=3,n.dims[4]=1):e>
11&&(n.dims[0]=4,n.dims[4]=e);const r=t.permRAS.slice();if(1===r[0]&&2===r[1]&&3===r[2])return n;n.qform_code=0;for(let s=1;s<4;s++)n.dims[s]=t.dimsRAS[s];for(let s=0;s<t.pixDimsRAS.length;s++)n.pixDims[s]=t.pixDimsRAS[s];let a=0;for(let s=0;s<4;s++)for(let e=0;e<4;e++)n.affine[s][e]=t.matRAS[a],a++;return n}(this,t)}img2RAS(t){return void 0===t&&(t=0),function(t,e){if(void 0===e&&(e=0),!t.permRAS)throw new Error("permRAS undefined");if(!t.img)throw new Error("img undefined");if(!t.hdr)throw new Error("hdr undefined");const i=t.permRAS.slice();if(1===i[0]&&2===i[1]&&3===i[2])return t.img;const n=t.hdr,r=n.dims[1]*n.dims[2]*n.dims[3];let a=e*r;(a+r>t.img.length||a<0)&&(a=0,Q.warn(`img2RAS nVolume (${e}) out of bounds (${e}+1)\xd7${r} > ${t.img.length}`));const s=t.img.slice(0,r),o=[Math.abs(i[0]),Math.abs(i[1]),Math.abs(i[2])],l=[n.dims[o[0]],n.dims[o[1]],n.dims[o[2]]],c=[1,n.dims[1],n.dims[1]*n.dims[2]],h=[c[o[0]-1],c[o[1]-1],c[o[2]-1]],d=[0,0,0];for(let m=0;m<3;m++)i[m]<0&&(d[m]=h[m]*(l[m]-1),h[m]=-h[m]);let u=0;for(let m=0;m<l[2];m++){const e=d[2]+m*h[2];for(let i=0;i<l[1];i++){const n=d[1]+i*h[1];for(let i=0;i<l[0];i++){const r=d[0]+i*h[0];s[u]=t.img[r+n+e+a],u++}}}return s}(this,t)}vox2mm(t,e){return wi(0,t,e)}mm2vox(t,e){return void 0===e&&(e=!1),yi(this,t,e)}arrayEquals(t,e){return bi(t,e)}setColormap(t){Si(this,t)}setColormapLabel(t){!function(t,e){t.colormapLabel=ve.makeLabelLut(e)}(this,t)}async setColormapLabelFromUrl(t){return async function(t,e){t.colormapLabel=await ve.makeLabelLutFromUrl(e)}(this,t)}get colormap(){return Ei(this)}get colorMap(){return Ei(this)}set colormap(t){Si(this,t)}set colorMap(t){Si(this,t)}get opacity(){return this._opacity}set opacity(t){!function(t,e){t._opacity=e,t.onOpacityChange&&t.onOpacityChange(t)}(this,t)}calMinMax(t,e){return void 0===t&&(t=Number.POSITIVE_INFINITY),void 0===e&&(e=!0),Ii(this,t,e)}intensityRaw2Scaled(t){return Ti(this,t)}intensityScaled2Raw(t){return function(t,e){if(!t.hdr)throw new Error("hdr undefined");return 0===t.hdr.scl_slope&&(t.hdr.scl_slope=1),(e-t.hdr.scl_inter)/t.hdr.scl_slope}(this,t)}async saveToUint8Array(t,e){return void 0===e&&(e=null),ze(this,t,e)}async saveToDisk(t,e){return void 0===t&&(t=""),void 0===e&&(e=null),async function(t,e,i){void 0===e&&(e=""),void 0===i&&(i=null);const n=await ze(t,e,i);if(!e)return Q.debug("saveToDisk: empty file name, returning data as Uint8Array rather than triggering download"),n;try{const t=new Blob([n.buffer],{type:"application/octet-stream"}),i=URL.createObjectURL(t),r=document.createElement("a");r.setAttribute("href",i),r.setAttribute("download",e),r.style.visibility="hidden",document.body.appendChild(r),r.click(),document.body.removeChild(r),setTimeout((()=>URL.revokeObjectURL(i)),100)}catch(r){Q.error("Failed to trigger download:",r)}return n}(this,t,e)}static async fetchDicomData(t,e){return void 0===e&&(e={}),async function(t,e){if(void 0===e&&(e={}),""===t)throw Error("url must not be empty");let i=/^(?:[a-z+]+:)?\/\//i.test(t)?t:new URL(t,window.location.href);/(?:.([^.]+))?$/.exec(i.pathname)||(i=new URL("niivue-manifest.txt",t));let n=await fetch(i,{headers:e});if(!n.ok)throw Error(n.statusText);const r=(await n.text()).split("\n"),a=/(.*\/).*/.exec(i)[0],s=[];for(const o of r){const t=new URL(o,a);if(n=await fetch(t,{headers:e}),!n.ok)throw Error(n.statusText);const i=await n.arrayBuffer();s.push({name:o,data:i})}return s}(t,e)}static async readFirstDecompressedBytes(t,e){return Fi(t,e)}static extractFilenameFromUrl(t){return function(t){const e=new URL(t).searchParams.get("response-content-disposition");if(e){const t=e.match(/filename\*?=(?:UTF-8'')?"?([^";]+)"?/);if(t)return decodeURIComponent(t[1])}return t.split("/").pop().split("?")[0]}(t)}static async loadInitialVolumesGz(t,e,i){return void 0===t&&(t=""),void 0===e&&(e={}),void 0===i&&(i=NaN),Bi(t,e,i)}static async loadInitialVolumes(t,e,i){return void 0===t&&(t=""),void 0===e&&(e={}),void 0===i&&(i=NaN),async function(t,e,i){if(void 0===t&&(t=""),void 0===e&&(e={}),void 0===i&&(i=NaN),isNaN(i))return null;const n=(await fetch(t,{headers:e,cache:"force-cache"})).body.getReader(),{value:r,done:a}=await n.read();let s=r;if(a||!s||s.length<2)throw new Error("Not enough data to determine compression");const o=new DataView(s.buffer,s.byteOffset,s.byteLength),l=o.getUint16(0,!0);if(35615===l)return await n.cancel(),Bi(t,e,i);const h=348===l;if(!h&&23553!==l)return await n.cancel(),null;let d=352;
1for(s.length>111&&(d=o.getFloat32(108,h));s.length<d;){let t=function(t,e){const i=new Uint8Array(t.length+e.length);return i.set(t,0),i.set(e,t.length),i};const{value:e,done:i}=await n.read();if(i||!e)break;s=t(s,e)}const u=await(0,c.Ad)(s.buffer);if(!u)throw new Error("Could not read NIfTI header");const m=u.numBitsPerVoxel/8,f=[1,2,3].reduce(((t,e)=>t*(u.dims[e]>1?u.dims[e]:1)),1),g=[4,5,6].reduce(((t,e)=>t*(u.dims[e]>1?u.dims[e]:1)),1),A=Math.max(Math.min(i,g),1),p=u.vox_offset+A*f*m,v=new Uint8Array(p),x=Math.min(s.length,p);v.set(s.subarray(0,x),0);let w=x;for(;w<p;){const{value:t,done:e}=await n.read();if(e||!t)return await n.cancel(),null;const i=Math.min(t.length,p-w);v.set(t.subarray(0,i),w),w+=i}return await n.cancel(),v.buffer}(t,e,i)}static async loadFromUrl(e){let{url:i="",urlImgData:n="",headers:r={},name:a="",colormap:s="",opacity:o=1,cal_min:l=NaN,cal_max:c=NaN,trustCalMinMax:h=!0,percentileFrac:d=.02,ignoreZeroVoxels:u=!1,useQFormNotSForm:m=!1,colormapNegative:x="",frame4D:w=0,isManifest:y=!1,limitFrames4D:b=NaN,imageType:C=Ve.UNKNOWN,colorbarVisible:M=!0,buffer:D=new ArrayBuffer(0),zarrLevel:T,zarrMaxVolumeSize:I,zarrChannel:S,zarrConvertUnits:E,zarrCenterMM:F}=void 0===e?{}:e;if(""===i)throw Error("url must not be empty");let B=null,V=null,U=null;if(i instanceof Uint8Array&&(i=i.slice().buffer),D.byteLength>0&&(i=D),i instanceof ArrayBuffer)if(V=i,""!==a)i=a;else{const t=new Uint8Array(V);i=31===t[0]&&139===t[1]?"array.nii.gz":"array.nii"}let R="";if(R=Vi(""===a?i:a),C===Ve.UNKNOWN&&(C=Ve.parse(R)),C===Ve.UNKNOWN&&"string"==typeof i){const t=await fetch(i,{});if(t.redirected){const e=this.extractFilenameFromUrl(t.url);e&&e.length>0&&""===a&&(a=e,R=Vi(a),C=Ve.parse(R))}}if(C===Ve.ZARR){if(void 0!==T)return await t.createChunkedZarr(i,{level:T,maxVolumeSize:I,channel:S,convertUnitsToMm:E,colormap:s,opacity:o,zarrCenterMM:F});const e=await async function(t){const e=new URL(t).searchParams,i=e.get("z"),n=e.get("y"),r=e.get("x"),a=i?f.di(parseInt(i),parseInt(i)+1):null,s=n?f.di(parseInt(n),parseInt(n)+1):null,o=r?f.di(parseInt(r),parseInt(r)+1):null,l=t.split("?")[0],c=new g.A(l),h=A.zr(c);let d,u;try{d=await p.h(h.resolve(t),{kind:"array"})}catch(C){d=await p.h(h,{kind:"array"})}if(4===d.shape.length){const t=null,e=d.shape[2],i=d.shape[1],n=d.shape[0];a&&a[0]>=e&&(a[0]=e-1),s&&s[0]>=i&&(s[0]=i-1),o&&o[0]>=n&&(o[0]=n-1),u=await v.Jt(d,[o,s,a,t])}else u=await v.Jt(d,[o,s,a]);const m=u.data,[x,w,y,b]=u.shape;return{dataBuffer:m,zarrData:{data:m,width:w,height:x,depth:y,channels:b}}}(i);V=e.dataBuffer,U=e.zarrData}const P=C===Ve.DCM||Ve.NII;!V&&P&&(V=await this.loadInitialVolumes(i,r,b)),V||(y?(V=await t.fetchDicomData(i,r),C=Ve.DCM_MANIFEST):V=await async function(t,e){void 0===e&&(e={});const i=await fetch(t,{headers:e});if(!i.ok)throw Error(i.statusText);if(!i.body)throw new Error("No readable stream available");const n=[],r=(await Le(i.body)).getReader();for(;;){const{done:t,value:e}=await r.read();if(t)break;n.push(e)}const a=n.reduce(((t,e)=>t+e.length),0),s=new ArrayBuffer(a),o=new Uint8Array(s);let l=0;for(const c of n)o.set(c,l),l+=c.length;return s}(i,r));const N=function(t,e,i){return""!==i?i:"HEAD"===e.toUpperCase()?t.substring(0,t.lastIndexOf("HEAD"))+"BRIK":"HDR"===e.toUpperCase()?t.substring(0,t.lastIndexOf("HDR"))+"IMG":null}(i,R.toUpperCase(),n);let L=null;if(N&&(L=await async function(t,e){void 0===e&&(e={});try{let i=await fetch(t,{headers:e});if(404===i.status&&(t.includes("BRIK")||t.includes("IMG"))&&(i=await fetch(`${t}.gz`,{headers:e})),!i.ok||!i.body)return null;const n=await Le(i.body),r=[],a=n.getReader();for(;;){const{done:t,value:e}=await a.read();if(t)break;r.push(e)}const s=r.reduce(((t,e)=>t+e.length),0),o=new ArrayBuffer(s),l=new Uint8Array(o);let c=0;for(const t of r)l.set(t,c),c+=t.length;return o}catch(i){return console.error("Error loading paired image data:",i),null}}(N,r)),!V)throw new Error("Unable to load buffer properly from volume");if(!a){let t;try{t=new URL(i).pathname.split("/")}catch(k){t=i.split("/")}a=t.slice(-1)[0],a.indexOf("?")>-1&&(a=a.slice(0,a.indexOf("?")))}return B=await this.new(V,a,s,o,L,l,c,h,d,u,m,x,w,C,NaN,NaN,!0,null,0,U),B.url=i,B.colorbarVisible=M,B}static async createChunkedZarr(e,i){const n=new t;return n.zarrHelper=await Yi.create(n,e,{url:e,level:i.level,maxVolumeSize:i.maxVolumeSize,maxTextureSize:i.maxTextureSize,channel:i.channel,cacheSize:i.cacheSize,convertUnitsToMm:i.convertUnitsToMm}),i.zarrCenterMM&&(n.zarrHelper.setWorldCenter(i.zarrCenterMM),n._hasExplicitZarrCenter=!0),i.colormap&&(n._colormap=i.colormap),void 0!==i.opacity&&(n._opacity=i.opacity),n.url=e,n}static async readFileAsync(t,e){return void 0===e&&(e=NaN),async function(t,e){void 0===e&&(e=NaN);let i=t.stream();if(!isNaN(e)){let t=0;
1const n=new TransformStream({transform(i,n){if(t>=e)return void n.terminate();const r=e-t;i.length>r?(n.enqueue(i.slice(0,r)),n.terminate()):n.enqueue(i),t+=i.length}});i=i.pipeThrough(n)}const n=[],r=(await Le(i)).getReader();for(;;){const{done:t,value:e}=await r.read();if(t)break;n.push(e)}const a=n.reduce(((t,e)=>t+e.length),0),s=new ArrayBuffer(a),o=new Uint8Array(s);let l=0;for(const c of n)o.set(c,l),l+=c.length;return s}(t,e)}static async loadFromFile(t){let{file:e,name:i="",colormap:n="",opacity:r=1,urlImgData:a=null,cal_min:s=NaN,cal_max:o=NaN,trustCalMinMax:l=!0,percentileFrac:h=.02,ignoreZeroVoxels:d=!1,useQFormNotSForm:u=!1,colormapNegative:m="",frame4D:f=0,limitFrames4D:g=NaN,imageType:A=Ve.UNKNOWN}=t,p=null,v=[];try{if(Array.isArray(e))v=await Promise.all(e.map((t=>this.readFileAsync(t))));else{if(isNaN(g))v=await this.readFileAsync(e);else{const t=await this.readFileAsync(e,512),i=new Uint8Array(t);if(92===i[0]&&1===i[1]||92===i[1]&&1===i[0]){const i=await(0,c.Ad)(t);if(!i)throw new Error("could not read nifti header");const n=i.numBitsPerVoxel/8,r=[1,2,3].reduce(((t,e)=>t*(i.dims[e]>1?i.dims[e]:1)),1),a=[4,5,6].reduce(((t,e)=>t*(i.dims[e]>1?i.dims[e]:1)),1),s=Math.max(Math.min(g,a),1),o=i.vox_offset+s*r*n;v=await this.readFileAsync(e,o)}else v=await this.readFileAsync(e)}i=e.name}let t=null;a&&(t=await this.readFileAsync(a)),p=await this.new(v,i,n,r,t,s,o,l,h,d,u,m,f,A,NaN,NaN,!0,null,0,null),p.fileObject=e}catch(x){throw Q.error(x),new Error("could not build NVImage")}if(null===p)throw new Error("could not build NVImage");return p}static createNiftiArray(t,e,i,n,r){return void 0===t&&(t=[256,256,256]),void 0===e&&(e=[1,1,1]),void 0===i&&(i=[1,0,0,-128,0,1,0,-128,0,0,1,-128,0,0,0,1]),void 0===n&&(n=2),void 0===r&&(r=new Uint8Array),function(t,e,i,n,r){void 0===t&&(t=[256,256,256]),void 0===e&&(e=[1,1,1]),void 0===i&&(i=[1,0,0,-128,0,1,0,-128,0,0,1,-128,0,0,0,1]),void 0===n&&(n=2),void 0===r&&(r=new Uint8Array);const a=ke(t,e,i,n),s=Pe(a,!1);a.vox_offset=Math.max(352,s.length);const o=Pe(a,!1);if(r.length<1)return o;const l=Math.max(0,a.vox_offset-o.length),c=new Uint8Array(l),h=new Uint8Array(r.buffer,r.byteOffset,r.byteLength),d=a.vox_offset+h.length,u=new Uint8Array(d);return u.set(o,0),u.set(c,o.length),u.set(h,a.vox_offset),u}(t,e,i,n,r)}static createNiftiHeader(t,e,i,n){return void 0===t&&(t=[256,256,256]),void 0===e&&(e=[1,1,1]),void 0===i&&(i=[1,0,0,-128,0,1,0,-128,0,0,1,-128,0,0,0,1]),void 0===n&&(n=2),ke(t,e,i,n)}getVolumeData(t,e,i){return void 0===t&&(t=[-1,0,0]),void 0===e&&(e=[0,0,0]),void 0===i&&(i="same"),function(t,e,i,n){void 0===e&&(e=[-1,0,0]),void 0===i&&(i=[0,0,0]),void 0===n&&(n="same");const r=[new Uint8Array,[0,0,0]];if(!(t.hdr&&t.img&&t.dimsRAS&&t.img2RASstep&&t.img2RASstart))return Q.error("getVolumeData: Missing required NVImage properties (hdr, img, dimsRAS, img2RASstep/start)."),r;if(e=e.slice(0,3),i=i.slice(0,3),Math.min(...e)<0||Math.min(...i)<0)return Q.warn("getVolumeData: Invalid start or end coordinates provided."),r;const a=t.dimsRAS.slice(1,4);for(let p=0;p<3;p++)if(e[p]=Math.max(0,Math.min(Math.round(e[p]),a[p]-1)),i[p]=Math.max(0,Math.min(Math.round(i[p]),a[p]-1)),i[p]<e[p]){const t=i[p];i[p]=e[p],e[p]=t}const s=[i[0]-e[0]+1,i[1]-e[1]+1,i[2]-e[2]+1],o=s[0]*s[1]*s[2];if(o<=0)return Q.warn("getVolumeData: Calculated slab size is zero or negative."),r;let l,c=t.img.constructor;"uint8"===n?c=Uint8Array:"int16"===n?c=Int16Array:"uint16"===n?c=Uint16Array:"float32"===n||"scaled"===n||"normalized"===n||"windowed"===n?c=Float32Array:"float64"===n?c=Float64Array:"same"!==n&&Q.warn(`getVolumeData: Unsupported dataType '${n}'. Using 'same'.`);try{l=new c(o)}catch(A){return Q.error(`getVolumeData: Failed to create output array for dataType '${n}'.`,A),r}const h=t.img2RASstep,d=t.img2RASstart,u=t.img;let m=0;for(let p=e[2];p<=i[2];p++){const t=d[2]+p*h[2];for(let n=e[1];n<=i[1];n++){const r=d[1]+n*h[1];for(let n=e[0];n<=i[0];n++){const e=d[0]+n*h[0]+r+t;let i=0;e>=0&&e<u.length&&(i=u[e]),l[m++]=i}}}const f=isNaN(t.hdr.scl_slope)||0===t.hdr.scl_slope?1:t.hdr.scl_slope,g=isNaN(t.hdr.scl_inter)?0:t.hdr.scl_inter;if("scaled"===n||"normalized"===n||"windowed"===n){l instanceof Float32Array||(Q.warn(`getVolumeData: Convert
1ing output to Float32 for scaling type '${n}'.`),l=Float32Array.from(l));for(let t=0;t<l.length;t++)l[t]=l[t]*f+g}if("normalized"===n||"windowed"===n){let e=t.cal_min,i=t.cal_max;"normalized"===n&&(e=t.global_min,i=t.global_max);const r=i-e,a=0===r?0:1/r;for(let t=0;t<l.length;t++)l[t]=(l[t]-e)*a,l[t]=Math.max(0,Math.min(l[t],1))}return[l,s]}(this,t,e,i)}setVolumeData(t,e,i){void 0===t&&(t=[-1,0,0]),void 0===e&&(e=[0,0,0]),void 0===i&&(i=new Uint8Array),function(t,e,i,n){if(void 0===e&&(e=[-1,0,0]),void 0===i&&(i=[0,0,0]),void 0===n&&(n=new Uint8Array),!(t.hdr&&t.img&&t.dimsRAS&&t.img2RASstep&&t.img2RASstart))return void Q.error("setVolumeData: Missing required NVImage properties (hdr, img, dimsRAS, img2RASstep/start).");if(n.length<1)return void Q.warn("setVolumeData: Input slabData is empty.");if(e=e.slice(0,3),i=i.slice(0,3),Math.min(...e)<0||Math.min(...i)<0)return void Q.warn("setVolumeData: Invalid start or end coordinates provided.");const r=t.dimsRAS.slice(1,4);for(let d=0;d<3;d++)if(e[d]=Math.max(0,Math.min(Math.round(e[d]),r[d]-1)),i[d]=Math.max(0,Math.min(Math.round(i[d]),r[d]-1)),i[d]<e[d]){const t=i[d];i[d]=e[d],e[d]=t}const a=[i[0]-e[0]+1,i[1]-e[1]+1,i[2]-e[2]+1],s=a[0]*a[1]*a[2];if(s<=0)return void Q.warn("setVolumeData: Calculated slab size is zero or negative.");if(n.length<s)return void Q.error(`setVolumeData: Input slabData length (${n.length}) is less than the calculated slab size (${s}).`);const o=t.img2RASstep,l=t.img2RASstart,c=t.img;let h=0;for(let d=e[2];d<=i[2];d++){const t=l[2]+d*o[2];for(let r=e[1];r<=i[1];r++){const a=l[1]+r*o[1];for(let r=e[0];r<=i[0];r++){const e=l[0]+r*o[0]+a+t;e>=0&&e<c.length&&(c[e]=n[h]),h++}}}}(this,t,e,i)}static async loadFromBase64(t){let{base64:e,name:i="",colormap:n="",opacity:r=1,cal_min:a=NaN,cal_max:s=NaN,trustCalMinMax:o=!0,percentileFrac:l=.02,ignoreZeroVoxels:c=!1,useQFormNotSForm:h=!1,colormapNegative:d="",frame4D:u=0,imageType:m=Ve.UNKNOWN,cal_minNeg:f=NaN,cal_maxNeg:g=NaN,colorbarVisible:A=!0,colormapLabel:p=null}=t,v=null;try{const t=function(t){const e=window.atob(t),i=e.length,n=new Uint8Array(i);for(let r=0;r<i;r++)n[r]=e.charCodeAt(r);return n.buffer}(e),x=null;v=await this.new(t,i,n,r,x,a,s,o,l,c,h,d,u,m,f,g,A,p,0,null)}catch(x){Q.debug(x)}if(null===v)throw new Error("could not load NVImage");return v}clone(){const e=new t;return e.id=(0,o.v4)(),e.hdr=Object.assign({},this.hdr),e.img=this.img.slice(),e.calculateRAS(),e.calMinMax(),e}zeroImage(){this.img.fill(0)}getImageMetadata(){return function(t){if(!t.hdr)throw new Error("hdr undefined");const e=t.id,i=t.hdr.datatypeCode,n=t.hdr.dims,r=n[1],a=n[2],s=n[3],o=Math.max(1,n[4]),l=t.hdr.pixDims;return{id:e,datatypeCode:i,nx:r,ny:a,nz:s,nt:o,dx:l[1],dy:l[2],dz:l[3],dt:l[4],bpv:Math.floor(t.hdr.numBitsPerVoxel/8)}}(this)}static zerosLike(t,e){void 0===e&&(e="same");const i=t.clone();return i.zeroImage(),"uint8"===e&&(i.img=Uint8Array.from(i.img),i.hdr.datatypeCode=2,i.hdr.numBitsPerVoxel=8),"float32"===e&&(i.img=Float32Array.from(i.img),i.hdr.datatypeCode=16,i.hdr.numBitsPerVoxel=32),i}getValue(t,e,i,n,r){return void 0===n&&(n=0),void 0===r&&(r=!1),function(t,e,i,n,r,a){void 0===r&&(r=0),void 0===a&&(a=!1);const s=Ye(t,e,i,n,r,a);return s.length<3?s[0]:.2126*s[0]+.7152*s[1]+.0722*s[2]}(this,t,e,i,n,r)}getValues(t,e,i,n,r){return void 0===n&&(n=0),void 0===r&&(r=!1),Ye(this,t,e,i,n,r)}applyOptionsUpdate(t){!function(t,e){t.hdr.cal_min=e.cal_min,t.hdr.cal_max=e.cal_max,Object.assign(t,e)}(this,t)}getImageOptions(){return Ue("","",(t=this).name,t._colormap,t.opacity,t.cal_min,t.cal_max,t.trustCalMinMax,t.percentileFrac,t.ignoreZeroVoxels,t.useQFormNotSForm,t.colormapNegative,t.frame4D,t.imageType,t.cal_minNeg,t.cal_maxNeg,t.colorbarVisible);var t}toUint8Array(t){return void 0===t&&(t=null),Oe(this,t)}convertVox2Frac(t){return function(t,e){return r.fA((e[0]+.5)/t.dimsRAS[1],(e[1]+.5)/t.dimsRAS[2],(e[2]+.5)/t.dimsRAS[3])}(this,t)}
1convertFrac2Vox(t){return function(t,e){return r.fA(Math.round(e[0]*t.dims[1]-.5),Math.round(e[1]*t.dims[2]-.5),Math.round(e[2]*t.dims[3]-.5))}(this,t)}convertFrac2MM(t,e){return void 0===e&&(e=!1),function(t,e,i){void 0===i&&(i=!1);const r=n.fA(e[0],e[1],e[2],1);return i?n.Z0(r,r,t.frac2mm):n.Z0(r,r,t.frac2mmOrtho),r}(this,t,e)}convertMM2Frac(t,e){return void 0===e&&(e=!1),function(t,e,i){void 0===i&&(i=!1);const s=n.fA(e[0],e[1],e[2],1),o=t.dimsRAS,l=r.fA(0,0,0);if(void 0===o)return l;if(!i){const e=a.o8(t.frac2mmOrtho);return a.B8(e,e),n.Z0(s,s,e),l[0]=s[0],l[1]=s[1],l[2]=s[2],l}if(o[1]<1||o[2]<1||o[3]<1)return l;const c=a.o8(t.matRAS);return a.B8(c,c),a.mg(c,c),n.Z0(s,s,c),l[0]=(s[0]+.5)/o[1],l[1]=(s[1]+.5)/o[2],l[2]=(s[2]+.5)/o[3],l}(this,t,e)}};function Wi(t){return"number"==typeof t&&Number.isFinite(t)}function Xi(t,e){return void 0===e&&(e=12),t.map((t=>Array.isArray(t)?Xi(t,e):Wi(t)?function(t,e){if(void 0===e&&(e=12),!Wi(t))return t;const i=1e-9*Math.max(1,Math.abs(t)),n=Number(t.toFixed(e));return Math.abs(t-n)<=i?n:t}(t,e):t))}function Ki(t,e){return"number"==typeof e?Number.isNaN(e)?"NaN":e===1/0?"infinity":e===-1/0?"-infinity":e:e}function Hi(t){if(null!=t){if(Array.isArray(t))return t.slice();if(ArrayBuffer.isView(t))try{return Array.from(t)}catch(e){}if("object"==typeof t){if(Array.isArray(t.data))return t.data.slice();if(t.buffer&&Array.isArray(t.buffer.data))return t.buffer.data.slice();const i=Object.keys(t).filter((t=>/^\d+$/.test(t))).map((t=>Number(t))).sort(((t,e)=>t-e));if(i.length>0)try{return i.map((e=>t[String(e)]))}catch(e){}for(const e of["_data","source","values","elements","items"])if(Array.isArray(t[e]))return t[e].slice()}try{const e=Array.from(t);if(Array.isArray(e))return e}catch(e){}}}function Qi(t){if(!t||"object"!=typeof t)return t;const e={...t||{}};if(void 0!==e.pts&&null!==e.pts||void 0===e.vertices&&void 0===e.positions&&void 0===e.verts)if(null!=e.pts&&!Array.isArray(e.pts)&&ArrayBuffer.isView(e.pts)){const t=Hi(e.pts);t&&(e.pts=Xi(t))}else Array.isArray(e.pts)&&(e.pts=Xi(e.pts));else{const t=[e.vertices,e.positions,e.verts];for(const i of t){const t=Hi(i);if(t&&t.length>0){e.pts=Xi(t);break}}}if(void 0!==e.tris&&null!==e.tris||void 0===e.indices&&void 0===e.faces&&void 0===e.cells){if(null!=e.tris&&!Array.isArray(e.tris)&&ArrayBuffer.isView(e.tris)){const t=Hi(e.tris);t&&(e.tris=t)}}else{const t=[e.indices,e.faces,e.cells];for(const i of t){const t=Hi(i);if(t&&t.length>0){e.tris=t;break}}}if(void 0!==e.rgba255&&null!==e.rgba255||void 0===e.rgba&&void 0===e.color&&void 0===e.colors){if(null!=e.rgba255&&!Array.isArray(e.rgba255)&&ArrayBuffer.isView(e.rgba255)){const t=Hi(e.rgba255);t&&(e.rgba255=t)}}else{const t=[e.rgba,e.color,e.colors];for(const i of t){const t=Hi(i);if(t&&t.length>0){e.rgba255=t;break}}}if(null!=e.offsetPt0&&!Array.isArray(e.offsetPt0)){const t=Hi(e.offsetPt0);t&&(e.offsetPt0=t)}return Array.isArray(e.nodes)&&(e.nodes=e.nodes.length>0&&"object"==typeof e.nodes[0]?e.nodes.map((t=>({...t}))):e.nodes.slice()),Array.isArray(e.edges)&&(e.edges=e.edges.length>0&&"object"==typeof e.edges[0]?e.edges.map((t=>({...t}))):e.edges.slice()),Array.isArray(e.layers)&&(e.layers=e.layers.map((t=>{if(!t||"object"!=typeof t)return t;const e={...t||{}};"colorMap"in e&&("colormap"in e||(e.colormap=e.colorMap),delete e.colorMap),"colorMapNegative"in e&&("colormapNegative"in e||(e.colormapNegative=e.colorMapNegative),delete e.colorMapNegative);for(const i of["global_min","global_max","cal_min","cal_max","cal_minNeg","cal_maxNeg"])if("string"==typeof e[i]){const t=e[i];if("infinity"===t)e[i]=1/0;else if("-infinity"===t)e[i]=-1/0;else if("NaN"===t)e[i]=NaN;else{const n=Number(t);Number.isNaN(n)||(e[i]=n)}}if(null==e.values||Array.isArray(e.values))Array.isArray(e.values)&&(e.values=Xi(e.values));else{const t=Hi(e.values);t&&(e.values=Xi(t))}if(null!=e.atlasValues&&!Array.isArray(e.atlasValues)){const t=Hi(e.atlasValues);t&&(e.atlasValues=t)}return e}))),e}function qi(t){if(!t||"object"!=typeof t)return t;const e={...t||{}};if("colorMap"in e&&!("colormap"in e)&&(e.colormap=e.colorMap),"colorMapNegative"in e&&!("colormapNegative"in e)&&(e.colormapNegative=e.colorMapNegative),Array.isArray(e.imageOptionsArray)&&(e.imageOptionsArray=e.imageOptionsArray.map((t=>{if(!t||"object"!=typeof t)return t;const e={...t||{}};for(const i of["cal_min","cal_max","cal_minNeg","cal_maxNeg"])if("string"==typeof e[i])if("infinity"===e[i])e[i]=1/0;else if("-infinity"===e[i])e[i]=-1/0;else if("NaN"===e[i])e[i]=NaN;else{const t=Number(e[i]);Number.isNaN(t)||(e[i]=t)}if(e.colormap&&"string"!=typeof e.colormap&&!Array.isArray(e.colormap)){const t=Hi(e.colormap);t&&(e.colormap=t)}if(e.colormapNegative&&"string"!=typeof e.colormapNegative&&!Array.isArray(e.colormapNegative)){const t=Hi(e.colormapNegative);t&&(e.colormapNegative=t)}return e}))),"string"==typeof e.meshesString&&e.meshesString.trim().length>0){const t=function(t){if("string"!=typeof t)return;if(0===t.trim().length)return t;try{const i=JSON.parse(t);if(Array.isArray(i)&&i.length>0&&"object"==typeof i[0]&&null!==i[0]&&"0"in i[0]&&"1"in i[0])try{const t=(0,x.i)(i);if(Array.isArray(t)){const e=t.map((t=>Qi(t)));return JSON.stringify(e,Ki)}}catch(e){console.warn("legacy-migrate: structured-clone deserialize failed",e)}if(!Array.isArray(i)){const e=["value","data","0"];for(const t of e)if(i&&Array.isArray(i[t])){const e=i[t].map((t=>Qi(t)));return JSON.stringify(e,Ki)}return t}const n=i.map((t=>Qi(t)));return JSON.stringify(n,Ki)}catch(i){return t}}(e.meshesString);"string"==typeof t&&(e.meshesString=t)}if(e.labels&&!Array.isArray(e.labels))try{e.labels=Array.from(e.labels)}catch(i){}if(e.connectomes&&!Array.isArray(e.connectomes))try{e.connectomes=Array.from(e.connectomes)}catch(i){}if(e.encodedImageBlobs&&!Array.isArray(e.encodedImageBlobs))try{e.encodedImageBlobs=Array.from(e.encodedImageBlobs)}catch(i){}return e}function Zi(t){if(void 0!==t)return null===t?null:Number.isFinite(t)?t:t===1/0?"infinity":t===-1/0?"-infinity":"NaN"}function ji(t){if(void 0===t)return;if(null===t)return null;if("number"==typeof t)return t;if("NaN"===t)return NaN;if("infinity"===t)return 1/0;if("-infinity"===t)return-1/0;const e=Number(t);return Number.isNaN(e)?NaN:e}function Ji(t){if(null!=t){if(t instanceof Float32Array)return t;if(Array.isArray(t))return new Float32Array(t);if(ArrayBuffer.isView(t))return new Float32Array(Array.from(t));try{return new Float32Array(Array.from(t))}catch(e){return}}}function _i(t){if(null!=t){if(t instanceof Uint32Array)return t;if(Array.isArray(t))return new Uint32Array(t);if(ArrayBuffer.isView(t))return new Uint32Array(Array.from(t));try{return new Uint32Array(Array.from(t))}catch(e){return}}}function $i(t){if(null!=t){if(t instanceof Uint8Array)return t;if(Array.isArray(t))return new Uint8Array(t);if(ArrayBuffer.isView(t))return new Uint8Array(Array.from(t));try{return new Uint8Array(Array.from(t))}catch(e){return}}}function tn(t,e){if("function"!=typeof e&&"symbol"!=typeof e)return ArrayBuffer.isView(e)?e instanceof DataView?Array.from(new Uint8Array(e.buffer,e.byteOffset,e.byteLength)):Array.from(e):e instanceof ArrayBuffer?Array.from(new Uint8Array(e)):e}var en=class t{static decodeOptsFromJSON(t){if(null==t)return;const e=t=>{if(void 0!==t){if(null===t)return null;if("number"==typeof t)return t;if("string"==typeof t)return"NaN"===t?NaN:"infinity"===t?1/0:"-infinity"===t?-1/0:t;if(Array.isArray(t))return t.map((t=>e(t)));if("object"==typeof t){const i={};for(const n of Object.keys(t))i[n]=e(t[n]);return i}return t}},i={};for(const n of Object.keys(t)){const r=t[n];void 0!==r&&(i[n]=e(r))}return i}static serializeDocument(t,e,i){void 0===e&&(e=!0),void 0===i&&(i=!0);const n={encodedImageBlobs:[],previewImageDataURL:t.previewImageDataURL??"",imageOptionsMap:new Map};
1n.sceneData={...t.scene?.sceneData??{}},n.opts=t.opts??{},n.labels=Array.isArray(t.labels)?t.labels.map((t=>{const e={...t||{}};return delete e.onClick,e})):[],n.customData=t.customData??"",n.completedMeasurements=t.completedMeasurements?t.completedMeasurements.slice():[],n.completedAngles=t.completedAngles?t.completedAngles.slice():[];const r=[],a=t.volumes??[];if(a.length)for(let h=0;h<a.length;h++){const i=a[h];let s=t.getImageOptions?t.getImageOptions(i):null;if(null===s?s={name:i?.name??"",colormap:i?._colormap??"gray",opacity:i?._opacity??1,cal_min:i?.cal_min??NaN,cal_max:i?.cal_max??NaN,trustCalMinMax:i?.trustCalMinMax??!0,percentileFrac:i?.percentileFrac??.02,ignoreZeroVoxels:i?.ignoreZeroVoxels??!1,imageType:i?.imageType??Ve.NII,frame4D:i?.frame4D??0,limitFrames4D:i?.limitFrames4D??NaN,url:i?.url??"",urlImageData:i?.urlImgData??"",cal_minNeg:i?.cal_minNeg??NaN,cal_maxNeg:i?.cal_maxNeg??NaN,colorbarVisible:i?.colorbarVisible??!0,colormapNegative:i?.colormapNegative??"",colormapType:i?.colormapType??0}:"imageType"in s||(s.imageType=Ve.NII),s.colormap=i.colormap,s.colormapLabel=i.colormapLabel,s.opacity=i.opacity,s.cal_max=i.cal_max??NaN,s.cal_min=i.cal_min??NaN,s.colormapNegative=i.colormapNegative??"",s.cal_minNeg=i.cal_minNeg??NaN,s.cal_maxNeg=i.cal_maxNeg??NaN,s.colorbarVisible=i.colorbarVisible??!0,s.colormapType=i.colormapType??0,r.push(s),e){const t=ye.uint8tob64(i.toUint8Array());n.encodedImageBlobs.push(t)}n.imageOptionsMap.set(i.id,h)}n.imageOptionsArray=r;const s=[],o=t.meshes||[];n.connectomes=[];for(const h of o){if(!h||"object"!=typeof h)continue;if("connectome"===h.type){try{n.connectomes.push(JSON.stringify(h.json()))}catch(l){Q.warn("serializeDocument: failed connectome export",l)}continue}const t=(h.layers||[]).map((t=>{const e={name:t?.name,key:t?.key,url:t?.url,headers:t?.headers,opacity:t?.opacity,colormap:t?.colorMap??t?.colormap,colormapNegative:t?.colorMapNegative??t?.colormapNegative,colormapInvert:t?.colormapInvert,colormapLabel:t?.colormapLabel,useNegativeCmap:t?.useNegativeCmap,global_min:Zi(t?.global_min),global_max:Zi(t?.global_max),cal_min:Zi(t?.cal_min),cal_max:Zi(t?.cal_max),cal_minNeg:Zi(t?.cal_minNeg),cal_maxNeg:Zi(t?.cal_maxNeg),isAdditiveBlend:t?.isAdditiveBlend,frame4D:t?.frame4D,nFrame4D:t?.nFrame4D,outlineBorder:t?.outlineBorder,isTransparentBelowCalMin:t?.isTransparentBelowCalMin,colormapType:t?.colormapType,base64:t?.base64,colorbarVisible:t?.colorbarVisible,showLegend:t?.showLegend};if(null!=t?.values){const i=Array.isArray(t.values)?t.values.slice():Array.from(t.values||[]);e.values=i.map((t=>{const e=Number(t);return Number.isFinite(e)?Math.round(1e12*e)/1e12:e}))}return null!=t?.atlasValues&&(e.atlasValues=Array.isArray(t.atlasValues)?t.atlasValues.slice():Array.from(t.atlasValues||[])),Array.isArray(t?.labels)?e.labels=t.labels.map((t=>({...t||{}}))):null!=t?.labels&&(e.labels=Array.from(t.labels||[])),e})),e={...Object.assign({},h||{}),rgba255:Array.from(h.rgba255||[]),layers:t,edges:Array.isArray(h?.edges)?h.edges.map((t=>({...t||{}}))):[],nodes:Array.isArray(h?.nodes)?h.nodes.map((t=>({...t||{}}))):h?.nodes,offsetPt0:Array.isArray(h?.offsetPt0)?[...h.offsetPt0]:h?.offsetPt0};Array.isArray(h.offsetPt0)&&h.offsetPt0.length>0&&(e.offsetPt0=Array.isArray(h.offsetPt0)?[...h.offsetPt0]:h.offsetPt0,Array.isArray(h.fiberGroupColormap)&&(e.fiberGroupColormap=[...h.fiberGroupColormap]),Array.isArray(h.fiberColor)&&(e.fiberColor=Array.from(h.fiberColor)),e.fiberDither=h.fiberDither,e.fiberRadius=h.fiberRadius,e.colormap=h.colormap),s.push(e)}try{n.meshesString=JSON.stringify(s,tn)}catch(c){Q.warn("serializeDocument: JSON.stringify failed for meshes",c);const t=[];for(let e=0;e<s.length;e++)try{t.push(JSON.stringify(s[e],tn))}catch(l){Q.error("serializeDocument: failed to serialize mesh at index",e,l,s[e]),t.push(JSON.stringify({name:s[e]?.name??"unknown",id:s[e]?.id??null}))}n.meshesString=`[${t.join(",")}]`}return i&&t.drawBitmap?n.encodedDrawingBlob=ye.uint8tob64(t.drawBitmap):n.encodedDrawingBlob=t.encodedDrawingBlob??"",n.title=t.title??"untitled",n.customData=t.customData??"",n.labels=Array.isArray(t.labels)?t.labels.map((t=>{const e={...t||{}};return delete e.onClick,e})):[],n.completedMeasurements=(t.completedMeasurements||[]).map((t=>({...t,startMM:Array.isArray(t.startMM)?[...t.startMM]:t.startMM,endMM:Array.isArray(t.endMM)?[...t.endMM]:t.endMM}))),n.completedAngles=(t.completedAngles||[]).map((t=>({...t,firstLineMM:{start:Array.isArray(t.firstLineMM?.start)?[...t.firstLineMM.start]:t.firstLineMM?.start,end:Array.isArray(t.firstLineMM?.end)?[...t.firstLineMM.end]:t.firstLineMM?.end},secondLineMM:{start:Array.isArray(t.secondLineMM?.start)?[...t.secondLineMM.start]:t.secondLineMM?.start,end:Array.isArray(t.secondLineMM?.end)?[...t.secondLineMM.end]:t.secondLineMM?.end}}
1))),n.sceneData=n.sceneData??{...t.scene?.sceneData??{}},n.opts=n.opts??(t.opts?{...t.opts}:{}),n}static async rehydrateImages(t){const e=[],i=await qi(t),n=i.encodedImageBlobs??[],r=i.imageOptionsArray??[];for(let s=0;s<r.length;s++){const t={...r[s]||{}};try{const i=n[s];if(!i){Q.debug("NVSerializer.rehydrateImages: no blob for index",s);continue}const r=await ye.b64toUint8(i);if(!r){Q.warn("NVSerializer.rehydrateImages: b64toUint8 returned empty for index",s);continue}const a=t.name??t.url??`image-${s}`;let o=t.colormap??t.colorMap??"";"string"!=typeof o&&(o="string"==typeof t.colorMap?t.colorMap:"");const l=t.opacity??1,c=t.pairedImgData?"string"==typeof t.pairedImgData?(await ye.b64toUint8(t.pairedImgData)).buffer:t.pairedImgData:null,h=ji(t.cal_min),d=ji(t.cal_max),u=t.trustCalMinMax??!0,m=t.percentileFrac??.02,f=t.ignoreZeroVoxels??!1,g=t.useQFormNotSForm??!1,A=t.colormapNegative??"",p=t.frame4D??0,v="imageType"in t&&"number"==typeof t.imageType?t.imageType:t.imageType??Ve.UNKNOWN,x=ji(t.cal_minNeg),w=ji(t.cal_maxNeg),y=t.colorbarVisible??!0,b=t.colormapLabel??null,C=t.colormapType??0,M=t.zarrData??null;console.log(`Image ${s} buffer length: ${r.byteLength}`);!r.some((t=>0!==t))&&console.error(`CRITICAL: Base64 decoding for ${a} resulted in an all-zero array!`);const D=r.slice().buffer,T=await Gi.new(D,a,o,l,c,h,d,u,m,f,g,A,p,v,x,w,y,b,C,M);e.push(T)}catch(a){Q.warn("NVSerializer.rehydrateImages: failed for index",s,a)}}return e}static async rehydrateMeshes(t,e,i){void 0===i&&(i=!1);const n=[],r=(await qi(t)).meshesString??"[]";let a=[];try{a=JSON.parse(r)}catch(s){console.warn("NVSerializer.rehydrateMeshes: failed to parse meshesString",s),a=[]}for(let l=0;l<a.length;l++){let t=a[l]||{};try{if(t=Qi(t),Array.isArray(t.layers))for(const e of t.layers)if(e){if("colorMap"in e&&!("colormap"in e)&&(e.colormap=e.colorMap,delete e.colorMap),"colorMapNegative"in e&&!("colormapNegative"in e)&&(e.colormapNegative=e.colorMapNegative,delete e.colorMapNegative),e.global_min=ji(e.global_min),e.global_max=ji(e.global_max),e.cal_min=ji(e.cal_min),e.cal_max=ji(e.cal_max),e.cal_minNeg=ji(e.cal_minNeg),e.cal_maxNeg=ji(e.cal_maxNeg),null!=e.values&&!Array.isArray(e.values))try{e.values=Array.from(e.values)}catch(s){}if(null!=e.atlasValues&&!Array.isArray(e.atlasValues))try{e.atlasValues=Array.from(e.atlasValues)}catch(s){}}const r=$i(t.rgba255)??new Uint8Array([255,255,255,255]),a=Ji(t.pts);let o=_i(t.tris);Array.isArray(t.nodes)&&(t.nodes=t.nodes.length>0&&"object"==typeof t.nodes[0]?t.nodes.map((t=>({...t}))):t.nodes.slice()),Array.isArray(t.edges)&&(t.edges=t.edges.length>0&&"object"==typeof t.edges[0]?t.edges.map((t=>({...t}))):t.edges.slice());const c=void 0!==t.id?t.id:null;if(!e){n.push(t);continue}Array.isArray(t.offsetPt0)&&t.offsetPt0.length>0&&(o=new Uint32Array(t.offsetPt0),r&&(r[3]=0));const h=new Uint8Array(Array.isArray(r)?r:Array.from(r)),d=new Te(a,o,t.name,h,t.opacity,t.visible,e,t.connectome,t.dpg,t.dps,t.dpv);if(null!==c&&(d.id=c),Array.isArray(t.offsetPt0)&&t.offsetPt0.length>0&&(d.fiberGroupColormap=t.fiberGroupColormap,d.fiberColor=t.fiberColor?t.fiberColor:void 0,d.fiberDither=t.fiberDither,d.fiberRadius=t.fiberRadius,d.colormap=t.colormap),d.meshShaderIndex=t.meshShaderIndex,d.layers=t.layers||[],i)try{d.updateMesh(e)}catch(s){console.warn("NVSerializer.rehydrateMeshes: updateMesh failed for idx",l,s)}n.push(d)}catch(o){console.warn("NVSerializer.rehydrateMeshes: failed idx",l,o),n.push(t)}}try{return Array.isArray(n)?n:(console.warn("NVSerializer.rehydrateMeshes: unexpected non-array output, coercing to array",{typeofOut:typeof n,isArray:Array.isArray(n),outPreview:n&&("object"==typeof n?Object.keys(n).slice(0,10):n)}),n?[n]:[])}catch(o){return console.error("NVSerializer.rehydrateMeshes: final-return error",o),[]}}static async deserializeDocument(e){const i=await qi(e),n=new hn;Object.assign(n.data,{...i,imageOptionsArray:i.imageOptionsArray??[],encodedImageBlobs:i.encodedImageBlobs??[],labels:i.labels??[],meshOptionsArray:i.meshOptionsArray??[],connectomes:i.connectomes??[],encodedDrawingBlob:i.encodedDrawingBlob??"",previewImageDataURL:i.previewImageDataURL??"",customData:i.customData??"",title:i.title??"untitled"});const a=t.decodeOptsFromJSON(i.opts);n.data.opts={...ln,...a||{}},"infinity"===n.data.opts.meshThicknessOn2D&&(n.data.opts.meshThicknessOn2D=1/0),n.scene.sceneData={...cn,...i.sceneData||{}};const s=i.sceneData||{};return s.clipPlane&&!s.clipPlanes&&(n.scene.sceneData.clipPlanes=[s.clipPlane]),s.clipPlaneDepthAziElev&&!s.clipPlaneDepthAziElevs&&(n.scene.sceneData.clipPlaneDepthAziElevs=[s.clipPlaneDepthAziElev]),i.completedMeasurements&&(n.completedMeasurements=i.completedMeasurements.map((t=>({...t,startMM:r.o8(t.startMM),endMM:r.o8(t.endMM)}
1)))),i.completedAngles&&(n.completedAngles=i.completedAngles.map((t=>({...t,firstLineMM:{start:r.o8(t.firstLineMM.start),end:r.o8(t.firstLineMM.end)},secondLineMM:{start:r.o8(t.secondLineMM.start),end:r.o8(t.secondLineMM.end)}})))),n.data.connectomes=i.connectomes??[],n.data.encodedDrawingBlob=i.encodedDrawingBlob??"",n.data.previewImageDataURL=i.previewImageDataURL??"",n}},nn=en,rn=(t=>(t[t.AXIAL=0]="AXIAL",t[t.CORONAL=1]="CORONAL",t[t.SAGITTAL=2]="SAGITTAL",t[t.MULTIPLANAR=3]="MULTIPLANAR",t[t.RENDER=4]="RENDER",t))(rn||{}),an=(t=>(t[t.NEVER=0]="NEVER",t[t.ALWAYS=1]="ALWAYS",t[t.AUTO=2]="AUTO",t))(an||{}),sn=(t=>(t[t.AUTO=0]="AUTO",t[t.COLUMN=1]="COLUMN",t[t.GRID=2]="GRID",t[t.ROW=3]="ROW",t))(sn||{}),on=(t=>(t[t.none=0]="none",t[t.contrast=1]="contrast",t[t.measurement=2]="measurement",t[t.pan=3]="pan",t[t.slicer3D=4]="slicer3D",t[t.callbackOnly=5]="callbackOnly",t[t.roiSelection=6]="roiSelection",t[t.angle=7]="angle",t[t.crosshair=8]="crosshair",t[t.windowing=9]="windowing",t))(on||{}),ln={textHeight:-1,fontSizeScaling:.4,fontMinPx:13,colorbarHeight:.05,colorbarWidth:-1,showColorbarBorder:!0,crosshairWidth:1,crosshairWidthUnit:"voxels",crosshairGap:0,rulerWidth:4,show3Dcrosshair:!1,backColor:[0,0,0,1],crosshairColor:[1,0,0,1],fontColor:[.5,.5,.5,1],selectionBoxColor:[1,1,1,.5],clipPlaneColor:[.7,0,.7,.5],isClipPlanesCutaway:!1,isClipAllVolumes:!1,paqdUniforms:[.3,.5,.5,1],rulerColor:[1,0,0,.8],colorbarMargin:.05,trustCalMinMax:!0,clipPlaneHotKey:"KeyC",cycleClipPlaneHotKey:"KeyP",viewModeHotKey:"KeyV",doubleTouchTimeout:500,longTouchTimeout:1e3,keyDebounceTime:50,isNearestInterpolation:!1,isResizeCanvas:!0,atlasOutline:0,atlasActiveIndex:0,isRuler:!1,isColorbar:!1,isOrientCube:!1,tileMargin:0,multiplanarPadPixels:0,multiplanarForceRender:!1,multiplanarEqualSize:!1,multiplanarShowRender:2,isRadiologicalConvention:!1,meshThicknessOn2D:1/0,dragMode:1,dragModePrimary:8,mouseEventConfig:void 0,touchEventConfig:void 0,yoke3Dto2DZoom:!1,isDepthPickMesh:!1,isCornerOrientationText:!1,isOrientationTextVisible:!0,showAllOrientationMarkers:!1,heroImageFraction:0,heroSliceType:4,sagittalNoseLeft:!1,isSliceMM:!1,isV1SliceShader:!1,forceDevicePixelRatio:0,logLevel:"info",loadingText:"loading ...",isForceMouseClickToVoxelCenters:!1,dragAndDropEnabled:!0,drawingEnabled:!1,penValue:1,penType:0,floodFillNeighbors:6,isFilledPen:!1,thumbnail:"",maxDrawUndoBitmaps:8,sliceType:3,meshXRay:0,isAntiAlias:null,limitFrames4D:NaN,isAdditiveBlend:!1,showLegend:!0,legendBackgroundColor:[.3,.3,.3,.5],legendTextColor:[1,1,1,1],multiplanarLayout:0,renderOverlayBlend:1,sliceMosaicString:"",centerMosaic:!1,penSize:1,interactive:!0,clickToSegment:!1,clickToSegmentRadius:3,clickToSegmentBright:!0,clickToSegmentAutoIntensity:!1,clickToSegmentIntensityMax:NaN,clickToSegmentIntensityMin:NaN,clickToSegmentPercent:0,clickToSegmentMaxDistanceMM:Number.POSITIVE_INFINITY,clickToSegmentIs2D:!1,selectionBoxLineThickness:4,selectionBoxIsOutline:!1,scrollRequiresFocus:!1,showMeasureUnits:!0,measureTextJustify:"center",measureTextColor:[1,0,0,1],measureLineColor:[1,0,0,1],measureTextHeight:.06,isAlphaClipDark:!1,gradientOrder:1,gradientOpacity:0,renderSilhouette:0,gradientAmount:0,invertScrollDirection:!1,is2DSliceShader:!1,bounds:null,showBoundsBorder:!1,boundsBorderColor:[1,1,1,1],windowingGainFactor:2,zarrCacheSize:1e3,zarrPrefetchRings:10,smoothDrawing:0},cn={gamma:1,azimuth:110,elevation:10,crosshairPos:r.fA(.5,.5,.5),clipPlanes:[[0,0,0,0]],clipPlaneDepthAziElevs:[[2,0,0]],volScaleMultiplier:1,pan2Dxyzmm:n.fA(0,0,0,1)},hn=class t{constructor(){C(this,"data",{title:"Untitled document",imageOptionsArray:[],meshOptionsArray:[],opts:{...ln},previewImageDataURL:"",labels:[],encodedImageBlobs:[],encodedDrawingBlob:""}),C(this,"scene"),C(this,"volumes",[]),C(this,"meshDataObjects"),C(this,"meshes",[]),C(this,"drawBitmap",null),C(this,"imageOptionsMap",new Map),C(this,"meshOptionsMap",new Map),C(this,"completedMeasurements",[]),C(this,"completedAngles",[]),C(this,"_optsProxy",null),C(this,"_optsChangeCallback",null),this.scene={onAzimuthElevationChange:()=>{},onZoom3DChange:()=>{},sceneData:{...cn,pan2Dxyzmm:n.fA(0,0,0,1),crosshairPos:r.fA(.5,.5,.5)},get renderAzimuth(){return this.sceneData.azimuth},set renderAzimuth(t){this.sceneData.azimuth=t,this.onAzimuthElevationChange&&this.onAzimuthElevationChange(this.sceneData.azimuth,this.sceneData.elevation)},get renderElevation(){return this.sceneData.elevation},set renderElevation(t){this.sceneData.elevation=t,this.onAzimuthElevationChange&&this.onAzimuthElevationChange(this.sceneData.azimuth,this.sceneData.elevation)},get volScaleMultiplier(){return this.sceneData.volScaleMultiplier},set volScaleMultiplier(t){this.sceneData.volScaleMultiplier=t,this.onZoom3DChange(t)}
1,get crosshairPos(){return this.sceneData.crosshairPos},set crosshairPos(t){this.sceneData.crosshairPos=t},get clipPlane(){return this.sceneData.clipPlanes[0]??[]},set clipPlane(t){this.sceneData.clipPlanes[0]=t},get clipPlanes(){return this.sceneData.clipPlanes},set clipPlanes(t){this.sceneData.clipPlanes=t},get clipPlaneDepthAziElevs(){return this.sceneData.clipPlaneDepthAziElevs},set clipPlaneDepthAziElevs(t){this.sceneData.clipPlaneDepthAziElevs=t},get pan2Dxyzmm(){return this.sceneData.pan2Dxyzmm},set pan2Dxyzmm(t){this.sceneData.pan2Dxyzmm=t},get gamma(){return this.sceneData.gamma},set gamma(t){this.sceneData.gamma=t}}}get title(){return this.data.title}get previewImageDataURL(){return this.data.previewImageDataURL}set previewImageDataURL(t){this.data.previewImageDataURL=t}set title(t){this.data.title=t}get imageOptionsArray(){return this.data.imageOptionsArray}get encodedImageBlobs(){return this.data.encodedImageBlobs}get encodedDrawingBlob(){return this.data.encodedDrawingBlob}get opts(){return this._optsProxy||this._createOptsProxy(),this._optsProxy}set opts(t){this.data.opts={...t},this._optsProxy=null}get labels(){return this.data.labels}set labels(t){this.data.labels=t}get customData(){return this.data.customData}set customData(t){this.data.customData=t}hasImage(t){return void 0!==this.volumes.find((e=>e.id===t.id))}hasImageFromUrl(t){return void 0!==this.data.imageOptionsArray.find((e=>e.url===t))}addImageOptions(t,e){if(!this.hasImage(t)&&!e.name)if(e.url){const t=/^(?:[a-z+]+:)?\/\//i.test(e.url)?new URL(e.url):new URL(e.url,window.location.href);e.name=t.pathname.split("/").pop(),e.name.toLowerCase().endsWith(".gz")&&(e.name=e.name.slice(0,-3)),e.name.toLowerCase().endsWith(".nii")||(e.name+=".nii")}else e.name="untitled.nii";e.imageType=Ve.NII,this.data.imageOptionsArray.push(e),this.imageOptionsMap.set(t.id,this.data.imageOptionsArray.length-1)}removeImage(t){if(this.imageOptionsMap.has(t.id)){const e=this.imageOptionsMap.get(t.id);this.data.imageOptionsArray.length>e&&this.data.imageOptionsArray.splice(e,1),this.imageOptionsMap.delete(t.id)}this.volumes=this.volumes.filter((e=>e.id!==t.id))}async fetchLinkedData(){if(this.data.encodedImageBlobs=[],this.imageOptionsArray?.length)for(const e of this.imageOptionsArray)if(e.url)try{const t=await fetch(e.url);if(!t.ok){console.warn("Failed to fetch image:",e.url);continue}const i=await t.arrayBuffer(),n=new Uint8Array(i),r=ye.uint8tob64(n);this.data.encodedImageBlobs.push(r),console.info("fetch linked data fetched from ",e.url)}catch(t){console.warn(`Failed to fetch/encode image from ${e.url}:`,t)}}getImageOptions(t){return this.imageOptionsMap.has(t.id)?this.data.imageOptionsArray[this.imageOptionsMap.get(t.id)]:null}json(t,e){return void 0===t&&(t=!0),void 0===e&&(e=!0),en.serializeDocument(this,t,e)}async download(t,e,i){void 0===i&&(i={embedImages:!0});const n=this.json(i.embedImages),r=JSON.stringify(n),a=e?"application/gzip":"application/json",s=e?await ye.compressStringToArrayBuffer(r):r;ye.download(s,t,a)}static async loadFromUrl(e){const i=await fetch(e),n=await i.arrayBuffer();let r;if(ye.isArrayBufferCompressed(n)){const t=await ye.decompressArrayBuffer(n);r=JSON.parse(t)}else{const t=new TextDecoder;r=JSON.parse(t.decode(n))}return t.loadFromJSON(r)}static async loadFromFile(e){const i=await ye.readFileAsync(e);let n;if(ye.isArrayBufferCompressed(i))n=await ye.decompressArrayBuffer(i);else{n=(new TextDecoder).decode(i)}const r=JSON.parse(n);return t.loadFromJSON(r)}static async loadFromJSON(t){return await en.deserializeDocument(t)}setOptsChangeCallback(t){this._optsChangeCallback=t,this._optsProxy=null}removeOptsChangeCallback(){this._optsChangeCallback=null,this._optsProxy=null}_createOptsProxy(){const t=this.data.opts;this._optsProxy=new Proxy(t,{set:(t,e,i)=>{const n=t[e];return n!==i&&(t[e]=i,this._optsChangeCallback&&"string"==typeof e&&e in ln&&this._optsChangeCallback(e,i,n)),!0},get:(t,e)=>t[e]})}},dn=(t,e)=>{const i=Math.floor(Math.log(t)/Math.log(10)),n=t/Math.pow(10,i);let r;return r=e?n<1.5?1:n<3?2:n<7?5:10:n<=1?1:n<=2?2:n<=5?5:10,r*Math.pow(10,i)};function un(t,e){return 0===t.scl_slope&&(t.scl_slope=1),e*t.scl_slope+t.scl_inter}function mn(t,e,i){void 0===i&&(i=4);const n=dn(e-t,!1),r=dn(n/(i-1),!0),a=Math.floor(t/r)*r,s=Math.ceil(e/r)*r;return[r,a,s,a===t&&s===e]}function fn(t,e){let i=mn(t,e,3);return i[3]||(i=mn(t,e,5)),i[3]||(i=mn(t,e,4)),i[3]||(i=mn(t,e,3)),i[3]||(i=mn(t,e,5)),[i[0],i[1],i[2]]}function gn(t){return t*(Math.PI/180)}function An(t,e,i,n){let r=-t,a=-e;return isFinite(i)&&isFinite(n)&&(r=i,a=n),r>a&&([r,a]=[a,r]),[r,a]}function pn(t,e){void 0===e&&(e=[0,1,2]);const i=r.vt();return i[0]=t[e[0]],i[1]=t[e[1]],i[2]=t[e[2]],i}function vn(t){const e=n.fA(1,0,0,0),i=n.vt();return n.Z0(i,e,t),i[0]}function xn(t,e){void 0===e&&(e=!0);const{volumes:i,meshes:n,volumeObject3D:a}=t;let s=r.fA(0,0,0),o=r.fA(0,0,0);if(i.length>0){if(!a)throw new Error("volumeObject3D undefined");s=r.fA(a.extentsMin[0],a.extentsMin[1],a.extentsMin[2]),o=r.fA(a.extentsMax[0],a.extentsMax[1],a.extentsMax[2]),e||(s=r.fA(i[0].extentsMinOrtho[0],i[0].extentsMinOrtho[1],i[0].extentsMinOrtho[2]),o=r.fA(i[0].extentsMaxOrtho[0],i[0].extentsMaxOrtho[1],i[0].extentsMaxOrtho[2]))}if(n.length>0){if(i.length<1){const t=n[0].extentsMin,e=n[0].extentsMax;s=r.fA(t[0],t[1],t[2]),o=r.fA(e[0],e[1],e[2])}for(let t=0;t<n.length;t++){const e=n[t].extentsMin,i=n[t].extentsMax,a=r.fA(e[0],e[1],e[2]);r.jk(s,s,a);const l=r.fA(i[0],i[1],i[2]);r.T9(o,o,l)}}const l=r.vt();return r.Re(l,o,s),[s,o,l]}function wn(t,e){const{volumes:i,meshes:n,volumeObject3D:a,volIdx:s=0,isSliceMM:o=!1}=e;if(i.length<1){const e=r.fA(.1,.5,.5),[s,l,c]=xn({volumes:i,meshes:n,volumeObject3D:a},o);return e[0]=(t[0]-s[0])/c[0],e[1]=(t[1]-s[1])/c[1],e[2]=(t[2]-s[2])/c[2],isFinite(e[0])||(e[0]=.5),isFinite(e[1])||(e[1]=.5),isFinite(e[2])||(e[2]=.5),e}return i[s].convertMM2Frac(t,o)}function yn(t,e){const{volumes:i,meshes:r,volumeObject3D:a,volIdx:s=0,isSliceMM:o=!1}=e,l=n.fA(t[0],t[1],t[2],1);if(i.length>0)return i[s].convertFrac2MM(t,o);{const[e,n]=xn({volumes:i,meshes:r,volumeObject3D:a},o),s=(t,e,i)=>t*(1-i)+e*i;l[0]=s(e[0],n[0],t[0]),l[1]=s(e[1],n[1],t[1]),l[2]=s(e[2],n[2],t[2])}return l}function bn(t,e,i,n,a){const{volumes:s,meshes:o,volumeObject3D:l,isSliceMM:c=!1,restrict0to1:h=!0}=a,d=r.fA(-1,-1,-1),u=i[n],m=u.axCorSag;if(m>2)return d;const f=u.leftTopWidthHeight.slice();let g=!1;f[2]<0&&(g=!0,f[0]+=f[2],f[2]=-f[2]);let A=(t-f[0])/f[2];g&&(A=1-A);const p=1-(e-f[1])/f[3];if(A<0||A>1||p<0||p>1)return d;if(u.AxyzMxy.length<4)return d;let v=r.fA(0,0,0);v[0]=u.leftTopMM[0]+A*u.fovMM[0],v[1]=u.leftTopMM[1]+p*u.fovMM[1];const x=u.AxyzMxy;v[2]=x[2]+x[4]*(v[1]-x[1])-x[3]*(v[0]-x[0]),1===m&&(v=pn(v,[0,2,1])
1),2===m&&(v=pn(v,[2,0,1]));const w=wn(v,{volumes:s,meshes:o,volumeObject3D:l,isSliceMM:c});return h&&(w[0]<0||w[0]>1||w[1]<0||w[1]>1||w[2]<0||w[2]>1)?d:w}var Cn=class{constructor(t,e,i){C(this,"program"),C(this,"uniforms",{}),C(this,"isMatcap"),C(this,"isCrosscut"),this.program=function(t,e,i){const n=t.createShader(t.VERTEX_SHADER);t.shaderSource(n,e),t.compileShader(n);const r=t.createShader(t.FRAGMENT_SHADER);t.shaderSource(r,i),t.compileShader(r);const a=t.createProgram();if(t.attachShader(a,n),t.attachShader(a,r),t.linkProgram(a),!t.getProgramParameter(a,t.LINK_STATUS))throw console.log(t.getProgramInfoLog(a)),t.getShaderParameter(n,t.COMPILE_STATUS)||console.log("Vertex shader compilation error:",t.getShaderInfoLog(n)),t.getShaderParameter(r,t.COMPILE_STATUS)||console.log("Fragment shader compilation error:",t.getShaderInfoLog(r)),Q.error(t.getProgramInfoLog(a)),new Error("Shader failed to link, see console for log");return a}(t,e,i);const n=/uniform[^;]+[ ](\w+);/g,r=/uniform[^;]+[ ](\w+);/,a=e.match(n),s=i.match(n);a&&a.forEach((t=>{const e=t.match(r);this.uniforms[e[1]]=-1})),s&&s.forEach((t=>{const e=t.match(r);this.uniforms[e[1]]=-1}));for(const o in this.uniforms)this.uniforms[o]=t.getUniformLocation(this.program,o)}use(t){t.useProgram(this.program)}},Mn="#version 300 es\n#line 4\nlayout(location=0) in vec3 pos;\nlayout(location=1) in vec3 texCoords;\nuniform mat4 mvpMtx;\nout vec3 vColor;\nvoid main(void) {\n\tgl_Position = mvpMtx * vec4(pos, 1.0);\n\tvColor = texCoords;\n}",Dn="\n\tvec4 drawColor(float scalar, float drawOpacity) {\n\t\tfloat nlayer = float(textureSize(colormap, 0).y);\n\t\tfloat layer = (nlayer - 0.5) / nlayer;\n\t\tvec4 dcolor = texture(colormap, vec2((scalar * 255.0)/256.0 + 0.5/256.0, layer)).rgba;\n\t\tdcolor.a *= drawOpacity;\n\t\treturn dcolor;\n}",Tn='vec3 GetBackPosition(vec3 startPositionTex) {\n\tvec3 startPosition = startPositionTex * volScale;\n\tvec3 invR = 1.0 / rayDir;\n\tvec3 tbot = invR * (vec3(0.0)-startPosition);\n\tvec3 ttop = invR * (volScale-startPosition);\n\tvec3 tmax = max(ttop, tbot);\n\tvec2 t = min(tmax.xx, tmax.yz);\n\tvec3 endPosition = startPosition + (rayDir * min(t.x, t.y));\n\t//convert world position back to texture position:\n\tendPosition = endPosition / volScale;\n\treturn endPosition;\n}\n\nfloat distance2Plane(in vec4 samplePos, in vec4 clipPlane) {\n\t// treat clipPlane.a > 1 as "no clip" sentinel (keeps existing behavior)\n\tif (clipPlane.a > 1.0) {\n\t\t\treturn 1000.0; // sentinel large distance\n\t}\n\tvec3 n = clipPlane.xyz;\n\tconst float EPS = 1e-6;\n\tfloat nlen = length(n);\n\tif (nlen < EPS) {\n\t\t\treturn 1000.0; // invalid plane normal\n\t}\n\t// signed plane value: dot(n, p-0.5) + a\n\tfloat signedDist = dot(n, samplePos.xyz - 0.5) + clipPlane.a;\n\t// perpendicular (Euclidean) distance is |signedDist| / |n|\n\treturn abs(signedDist) / nlen;\n}\n\n// see if clip plane trims ray sampling range sampleStartEnd.x..y\nvoid clipSampleRange(in vec3 dir, in vec4 rayStart, in vec4 clipPlane, inout vec2 sampleStartEnd, inout bool hasClip) {\n\tconst float CSR_EPS = 1e-6;\n\t// quick exit: no clip plane\n\tif (clipPlane.a > 1.0)\n\t\t\treturn;\n\thasClip = true;\n\t// quick exit: empty range\n\tif ((sampleStartEnd.y - sampleStartEnd.x) <= CSR_EPS)\n\t\t\treturn;\n\t// Which side does the ray start on? (plane eqn: dot(n, p-0.5) + a = 0)\n\tfloat sampleSide = dot(clipPlane.xyz, rayStart.xyz - 0.5) + clipPlane.a;\n\tbool startsFront = (sampleSide < 0.0);\n\tfloat dis = - 1.0;\n\t// plane normal dot ray direction\n\tfloat cdot = dot(dir, clipPlane.xyz);\n\t// avoid division by 0 for near-parallel plne\n\tif (abs(cdot) >= CSR_EPS)\n\t\tdis = (-clipPlane.a - dot(clipPlane.xyz, rayStart.xyz - 0.5)) / cdot;\n\tif (dis < 0.0 || dis > sampleStartEnd.y + CSR_EPS) {\n\t\t\tif (startsFront)\n\t\t\t\tsampleStartEnd = vec2(0.0, 0.0);\n\t\t\treturn;\n\t}\n\tbool frontface = (cdot > 0.0);\n\tif (frontface)\n\t\tsampleStartEnd.x = max(sampleStartEnd.x, dis);\n\telse\n\t\tsampleStartEnd.y = min(sampleStartEnd.y, dis);\n\t// if nothing remains, mark empty\n\tif (sampleStartEnd.y - sampleStartEnd.x <= CSR_EPS)\n\t\tsampleStartEnd = vec2(0.0, 0.0);\n}\n\nbool skipSample (float pos, vec2 sampleRange) {\n\treturn (pos < sampleRange.x || pos > sampleRange.y);\n}\n\nfloat frac2ndc(vec3 frac) {\n//https://stackoverflow.com/questions/7777913/how-to-render-depth-linearly-in-modern-opengl-with-gl-fragcoord-z-in-fragment-sh\n\tvec4 pos = vec4(frac.xyz, 1.0); //fraction\n\tvec4 dim = vec4(vec3(textureSize(volume, 0)), 1.0);\n\tpos = pos * dim;\n\tvec4 shim = vec4(-0.5, -0.5, -0.5, 0.0);\n\tpos += shim;\n\tvec4 mm = transpose(matRAS) * pos;\n\tfloat z_ndc = (mvpMtx * vec4(mm.xyz, 1.0)).z;\n\treturn (z_ndc + 1.0) / 2.0;\n}'+Dn,In="void main() {\n\tif (fColor.x > 2.0) {\n\t\tfColor = vec4(1.0, 0.0, 0.0, 0.5);\n\t\treturn;\n\t}\n\tfColor = vec4(0.0,0.0,0.0,0.0);\n\tvec4 clipPlaneColorX = clipPlaneColor;\n\t//if (clipPlaneColor.a < 0.0)\n\t//\tclipPlaneColorX.a = - 1.0;\n\tbool isColorPlaneInVolume = false;\n\tif (clipPlaneColorX.a < 0.0) {\n\t\tisColorPlaneInVolume = true;\n\t\tclipPlaneColorX.a = 0.0;\n\t}\n\t//fColor = vec4(vColor.rgb, 1.0); return;\n\tvec3 start = vColor;\n\tgl_FragDepth = 1.0;\n\tvec3 backPosition = GetBackPosition(start);
1\n\t// fColor = vec4(backPosition, 1.0); return;\n\tvec3 dir = normalize(backPosition - start);\n\t//clipVolumeStart(start, backPosition);\n\tdir = normalize(dir);\n\tfloat len = length(backPosition - start);\n\tfloat lenVox = length((texVox * start) - (texVox * backPosition));\n\tif ((lenVox < 0.5) || (len > 3.0)) { //length limit for parallel rays\n\t\treturn;\n\t}\n\tfloat sliceSize = len / lenVox; //e.g. if ray length is 1.0 and traverses 50 voxels, each voxel is 0.02 in unit cube\n\tfloat stepSize = sliceSize; //quality: larger step is faster traversal, but fewer samples\n\tfloat opacityCorrection = stepSize/sliceSize;\n\tvec4 deltaDir = vec4(dir.xyz * stepSize, stepSize);\n\tvec4 samplePos = vec4(start.xyz, 0.0); //ray position\n\n\tvec2 sampleRange = vec2(0.0, len);\n\tbool hasClip = false;\n\tfor (int i = 0; i < MAX_CLIP_PLANES; i++)\n\t\tclipSampleRange(dir, samplePos, clipPlanes[i], sampleRange, hasClip);\n\tbool isClip = (sampleRange.x > 0.0) || ((sampleRange.y < len) && (sampleRange.y > 0.0));\n\tfloat stepSizeFast = sliceSize * 1.9;\n\tvec4 deltaDirFast = vec4(dir.xyz * stepSizeFast, stepSizeFast);\n\tif ((isClipCutaway) && (sampleRange.x <= 0.0) && (sampleRange.y >= len)) {\n\t\t//completely clipped, but ray does not intersect plane\n\t\tif (hasClip)\n\t\t\tsamplePos.a = len + 1.0;\n\t\telse\n\t\t\tsampleRange = vec2(0.0, 0.0);\n\t}\n\tif ((!isClipCutaway) && (sampleRange.x >= sampleRange.y))\n\t\tsamplePos.a = len + 1.0;\n\twhile (samplePos.a <= len) {\n\t\tif (skipSample(samplePos.a, sampleRange) ^^ isClipCutaway) {\n\t\t\tsamplePos += deltaDirFast;\n\t\t\tcontinue;\n\t\t}\n\t\tfloat val = texture(volume, samplePos.xyz).a;\n\t\tif (val > 0.01)\n\t\t\tbreak;\n\t\tsamplePos += deltaDirFast; //advance ray position\n\t}\n\tfloat drawOpacityA = renderDrawAmbientOcclusionXY.y;\n\tif ((samplePos.a >= len) && (((overlays < 1.0) && (drawOpacityA <= 0.0) ) || (backgroundMasksOverlays > 0)))  {\n\t\tif (isClip)\n\t\t\tfColor += clipPlaneColorX;\n\t\treturn;\n\t}\n\tfColor = vec4(1.0, 1.0, 1.0, 1.0);\n\t//gl_FragDepth = frac2ndc(samplePos.xyz); //crude due to fast pass resolution\n\tif (samplePos.a > deltaDirFast.a )\n\t\tsamplePos -= deltaDirFast;\n\t//end: fast pass\n\tvec4 colAcc = vec4(0.0,0.0,0.0,0.0);\n\tvec4 firstHit = vec4(0.0,0.0,0.0,2.0 * len);\n\tconst float earlyTermination = 0.95;\n\tfloat backNearest = len; //assume no hit\n\tfloat ran = fract(sin(gl_FragCoord.x * 12.9898 + gl_FragCoord.y * 78.233) * 43758.5453);\n\t// clip planes create steep gradients: reduce aliasing with more jitter\n\tif (isClip)\n\t\tsamplePos += deltaDir * ran * 1.41; //jitter ray\n\telse\n\t\tsamplePos += deltaDir * ran; //jitter ray\n\tvec2 overlaySampleRange = isClipAllVolumes ? sampleRange : vec2(0.0, len);\n\tbool overlayIsClipCutaway = isClipAllVolumes && isClipCutaway;\n",Sn="\n\tif (firstHit.a < len) {\n\t\tgl_FragDepth = frac2ndc(firstHit.xyz);\n\t\tvec4 paqdSample = texture(paqd, samplePos.xyz);\n\t\tif (paqdSample.a > 0.0) {\n\t\t\t//colAcc.rgb = paqdSample.rgb;\n\t\t\tfloat a = max(abs(paqdUniforms[2]), abs(paqdUniforms[3]));\n\t\t\tcolAcc.rgb = mix(colAcc.rgb, paqdSample.rgb, 0.5 * paqdSample.a * a);\n\t\t}\n\t\tif (isClip) {\n\t\t\t//shade voxels with clip color\n\t\t\tif (clipPlaneColor.a < 0.0) {\n\t\t\t\t\tfloat thresh = 4.0 * sliceSize;\n\t\t\t\t\tfloat firstHit1 = firstHit.a + deltaDir.a;\n\t\t\t\tif (isClipCutaway) {\n\t\t\t\t\tfloat min1 = abs(firstHit1 - sampleRange.y);
1\n\t\t\t\t\tfloat dx = samplePos.a - firstHit1;\n\t\t\t\t\tif (min1 < thresh)\n\t\t\t\t\t\tcolAcc.rgb = mix(colAcc.rgb, clipPlaneColorX.rgb, abs(clipPlaneColor.a));\n\t\t\t\t\telse if (( colAcc.a > earlyTermination ) && (dx > thresh)) {\n\t\t\t\t\t\tmin1 = abs(firstHit1 - sampleRange.x);\n\t\t\t\t\t\tif (min1 < (thresh * 0.5)) {\n\t\t\t\t\t\t\tcolAcc.rgb = mix(colAcc.rgb , clipPlaneColorX.rgb, abs(clipPlaneColor.a)*0.5);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (abs(firstHit1 - sampleRange.x) < thresh)\n\t\t\t\t\t\tcolAcc.rgb = mix(colAcc.rgb, clipPlaneColorX.rgb, abs(clipPlaneColor.a));\n\t\t\t\t} // clipPlaneColor.a < 0.0\n\t\t\t}\n\t\t\t//ambient occlusion: make creases dark\n\t\t\tfloat min1 = 1000.0;\n\t\t\tfloat min2 = 1000.0;\n\t\t\t// find smallest and second-smallest distances\n\t\t\tvec4 firstHit1 = firstHit - deltaDir;\n\t\t\tfor (int i = 0; i < MAX_CLIP_PLANES; i++) {\n\t\t\t\tfloat d = distance2Plane(firstHit1, clipPlanes[i]);\n\t\t\t\tif (d < min1) {\n\t\t\t\t\t\tmin2 = min1;\n\t\t\t\t\t\tmin1 = d;\n\t\t\t\t} else if (d < min2) {\n\t\t\t\t\t\tmin2 = d;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfloat thresh = 1.2 * sliceSize;\n\t\t\tif ((isClipCutaway) && (min2 < thresh) && (sampleRange.x > 0.0)) {\n\t\t\t\tif ((abs(sampleRange.x - firstHit.a) > ( 2.0 * thresh)) && ((abs(sampleRange.y - firstHit.a) > (2.0 * thresh))))\n\t\t\t\t\tmin2 = thresh; \n\t\t\t}\n\t\t\t// if second is 0 -> factor 0 (black), if second >= sliceSize -> factor 1 (unchanged)\n\t\t\tconst float aoFrac = 0.5;\n\t\t\tfloat factor = (1.0 - aoFrac) + aoFrac * clamp(min2 / thresh, 0.0, 1.0);\n\t\t\t// linear darkening: multiply color by factor (or use mix(vec3(0), colAcc.rgb, factor))\n\t\t\tcolAcc.rgb *= factor;\n\t\t}\n\t}\n\tcolAcc.a = (colAcc.a / earlyTermination) * backOpacity;\n\tfColor = colAcc;\n\tfloat renderDrawAmbientOcclusionX = renderDrawAmbientOcclusionXY.x;\n\tfloat drawOpacity = renderDrawAmbientOcclusionXY.y;\n\tif ((overlays < 1.0) && (drawOpacity <= 0.0))\n\t\treturn;\n\t//overlay pass\n\tsamplePos = vec4(start.xyz, 0.0); //ray position\n\t//start: OPTIONAL fast pass: rapid traversal until first hit\n\tstepSizeFast = sliceSize * 1.0;\n\tdeltaDirFast = vec4(dir.xyz * stepSizeFast, stepSizeFast);\n\twhile (samplePos.a <= len) {\n\t\tif (skipSample(samplePos.a, overlaySampleRange) ^^ overlayIsClipCutaway) {\n\t\t\tsamplePos += deltaDirFast;\n\t\t\tcontinue;\n\t\t}\n\t\tfloat val = texture(overlay, samplePos.xyz).a;\n\t\tif (drawOpacity > 0.0) {\n\t\t\tif (smoothDrawing > 0.0) {\n\t\t\t\tif (!isClipAllVolumes || !(skipSample(samplePos.a, sampleRange) ^^ isClipCutaway))\n\t\t\t\t\tval = max(val, texture(drawSmoothed, samplePos.xyz).r * 2.0);\n\t\t\t} else\n\t\t\t\tval = max(val, texture(drawing, samplePos.xyz).r);\n\t\t}\n\t\tif (val > 0.001)\n\t\t\tbreak;\n\t\tsamplePos += deltaDirFast; //advance ray position\n\t}\n\tif (samplePos.a >= len) {\n\t\tif (isClip && (fColor.a == 0.0))\n\t\t\t\tfColor += clipPlaneColorX;\n\t\t\treturn;\n\t}\n\tsamplePos -= deltaDirFast;\n\tif (samplePos.a < 0.0)\n\t\tvec4 samplePos = vec4(start.xyz, 0.0); //ray position\n\t//end: fast pass\n\tfloat overFarthest = len;\n\tcolAcc = vec4(0.0, 0.0, 0.0, 0.0);\n\n\tsamplePos += deltaDir * ran; //jitter ray\n\tvec4 overFirstHit = vec4(0.0,0.0,0.0,2.0 * len);\n\tif (backgroundMasksOverlays > 0)\n\t\tsamplePos = firstHit;\n\tbool firstDraw = true;\n\t// Hoist per-ray constants used by the smooth drawing path.\n\tvec3 vxSize = 1.0 / vec3(textureSize(drawing, 0));\n\tvec3 nRayDir = normalize(rayDir);\n\t// For smooth drawing with a clip plane: if the ray enters the unclipped region\n\t// already inside the drawn volume, start with prevSmoothOut=false so no\n\t// outside\u2192inside transition is detected, suppressing the clip-plane cap face.\n\tbool prevSmoothOut = true;\n\tbool enteredFromOutside = false;\n\tvec4 cachedSmoothColor = vec4(0.0);\n\tif (isClipAllVolumes && isClip && !isClipCutaway && smoothDrawing > 0.0) {\n\t\tvec3 clipEntry = start.xyz + dir * sampleRange.x;\n\t\tif (texture(drawSmoothed, clipEntry).r >= 0.5)\n\t\t\tprevSmoothOut = false;\n\t}\n\twhile (samplePos.a <= len) {\n\t\tif (skipSample(samplePos.a, overlaySampleRange) ^^ overlayIsClipCutaway) {\
1n\t\t\tsamplePos += deltaDirFast;\n\t\t\tcontinue;\n\t\t}\n\t\tvec4 colorSample = texture(overlay, samplePos.xyz);\n\t\tif ((colorSample.a < 0.01) && (drawOpacity > 0.0)) {\n\t\t\tif (smoothDrawing > 0.0) {\n\t\t\t\t// Smooth drawing: isosurface rendering with gradient-based shading\n\t\t\t\t// Clip the smooth surface only when isClipAllVolumes is set\n\t\t\t\tif (isClipAllVolumes && (skipSample(samplePos.a, sampleRange) ^^ isClipCutaway)) {\n\t\t\t\t\tsamplePos += deltaDir;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tfloat smoothVal = texture(drawSmoothed, samplePos.xyz).r;\n\t\t\t\tbool nowSmoothInside = (smoothVal > 0.5);\n\t\t\t\t// Track entry transitions: only mark enteredFromOutside on a genuine\n\t\t\t\t// outside\u2192inside crossing; clear it when we exit.\n\t\t\t\tif (!nowSmoothInside) {\n\t\t\t\t\tprevSmoothOut = true;\n\t\t\t\t\tenteredFromOutside = false;\n\t\t\t\t} else if (prevSmoothOut) {\n\t\t\t\t\t// First inside sample: compute gradient, pen color, and Phong shading\n\t\t\t\t\t// once and cache the result for all subsequent interior steps.\n\t\t\t\t\tprevSmoothOut = false;\n\t\t\t\t\tenteredFromOutside = true;\n\t\t\t\t\tfloat gx = texture(drawSmoothed, samplePos.xyz + vec3(vxSize.x, 0.0, 0.0)).r\n\t\t\t\t\t         - texture(drawSmoothed, samplePos.xyz - vec3(vxSize.x, 0.0, 0.0)).r;\n\t\t\t\t\tfloat gy = texture(drawSmoothed, samplePos.xyz + vec3(0.0, vxSize.y, 0.0)).r\n\t\t\t\t\t         - texture(drawSmoothed, samplePos.xyz - vec3(0.0, vxSize.y, 0.0)).r;\n\t\t\t\t\tfloat gz = texture(drawSmoothed, samplePos.xyz + vec3(0.0, 0.0, vxSize.z)).r\n\t\t\t\t\t         - texture(drawSmoothed, samplePos.xyz - vec3(0.0, 0.0, vxSize.z)).r;\n\t\t\t\t\tvec3 grad = vec3(gx, gy, gz);\n\t\t\t\t\tfloat gradLen = length(grad);\n\t\t\t\t\tvec3 normal = gradLen > 0.001 ? normalize(grad) : vec3(0.0, 0.0, 1.0);\n\t\t\t\t\t// Get pen color from original drawing texture.\n\t\t\t\t\tfloat drawVal = texture(drawing, samplePos.xyz).r;\n\t\t\t\t\tif (drawVal == 0.0) {\n\t\t\t\t\t\t// Between painted voxels: step inward along the gradient\n\t\t\t\t\t\t// to find the nearest painted voxel's pen color.\n\t\t\t\t\t\t// (normal points inward toward higher smooth values)\n\t\t\t\t\t\tfor (int k = 1; k <= 8; k++) {\n\t\t\t\t\t\t\tdrawVal = texture(drawing, samplePos.xyz + normal * vxSize * float(k)).r;\n\t\t\t\t\t\t\tif (drawVal > 0.0) break;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tvec4 draw = drawColor(max(drawVal, 1.0 / 255.0), drawOpacity);\n\t\t\t\t\t// Phong shading with two-sided lighting.\n\t\t\t\t\tfloat NdotL = abs(dot(normal, nRayDir));\n\t\t\t\t\tvec3 reflected = reflect(nRayDir, normal);\n\t\t\t\t\tfloat spec = pow(max(dot(reflected, -nRayDir), 0.0), 20.0);\n\t\t\t\t\tdraw.rgb *= (0.4 + 0.6 * NdotL);\n\t\t\t\t\tdraw.rgb += vec3(0.2 * spec);\n\t\t\t\t\tcachedSmoothColor = draw;\n\t\t\t\t}\n\t\t\t\t// Use the cached shaded color for every interior step.\n\t\t\t\tif (nowSmoothInside && enteredFromOutside) {\n\t\t\t\t\tcolorSample = cachedSmoothColor;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Original discrete drawing path\n\t\t\t\tfloat val = texture(drawing, samplePos.xyz).r;\n\t\t\t\tvec4 draw = drawColor(val, drawOpacity);\n\t\t\t\tif ((draw.a > 0.0) && (firstDraw)) {\n\t\t\t\tfirstDraw = false;\n\t\t\t\tfloat sum = 0.0;\n\t\t\t\tconst float mn = 1.0 / 256.0;\n\t\t\t\tconst float sampleRadius = 1.1;\n\t\t\t\tfloat dx = sliceSize * sampleRadius;\n\t\t\t\tvec3 center = samplePos.xyz;\n\t\t\t\t//six neighbors that share a face\n\t\t\t\tsum += min(texture(drawing, center.xyz + cross(vec3(0.0,0.0,+
1dx), dir)).r, mn);\n\t\t\t\tsum += min(texture(drawing, center.xyz + cross(vec3(0.0,0.0,-dx), dir)).r, mn);\n\t\t\t\tsum += min(texture(drawing, center.xyz + cross(vec3(0.0,+dx,0.0), dir)).r, mn);\n\t\t\t\tsum += min(texture(drawing, center.xyz + cross(vec3(0.0,-dx,0.0), dir)).r, mn);\n\t\t\t\tsum += min(texture(drawing, center.xyz + cross(vec3(+dx,0.0,0.0), dir)).r, mn);\n\t\t\t\tsum += min(texture(drawing, center.xyz + cross(vec3(-dx,0.0,0.0), dir)).r, mn);\n\t\t\t\t//float proportion = (sum / mn) / 6.0;\n\t\t\t\t\n\t\t\t\t//12 neighbors that share an edge\n\t\t\t\tdx = sliceSize * sampleRadius * sqrt(2.0) * 0.5;\n\t\t\t\tsum += min(texture(drawing, center.xyz + cross(vec3(0.0,+dx,+dx), dir)).r, mn);\n\t\t\t\tsum += min(texture(drawing, center.xyz + cross(vec3(+dx,0.0,+dx), dir)).r, mn);\n\t\t\t\tsum += min(texture(drawing, center.xyz + cross(vec3(+dx,+dx,0.0), dir)).r, mn);\n\t\t\t\tsum += min(texture(drawing, center.xyz + cross(vec3(0.0,-dx,-dx), dir)).r, mn);\n\t\t\t\tsum += min(texture(drawing, center.xyz + cross(vec3(-dx,0.0,-dx), dir)).r, mn);\n\t\t\t\tsum += min(texture(drawing, center.xyz + cross(vec3(-dx,-dx,0.0), dir)).r, mn);\n\n\t\t\t\tsum += min(texture(drawing, center.xyz + cross(vec3(0.0,+dx,-dx), dir)).r, mn);\n\t\t\t\tsum += min(texture(drawing, center.xyz + cross(vec3(+dx,0.0,-dx), dir)).r, mn);\n\t\t\t\tsum += min(texture(drawing, center.xyz + cross(vec3(+dx,-dx,0.0), dir)).r, mn);\n\t\t\t\t\n\t\t\t\tsum += min(texture(drawing, center.xyz + cross(vec3(0.0,-dx,+dx), dir)).r, mn);\n\t\t\t\tsum += min(texture(drawing, center.xyz + cross(vec3(-dx,0.0,+dx), dir)).r, mn);\n\t\t\t\tsum += min(texture(drawing, center.xyz + cross(vec3(-dx,+dx,0.0), dir)).r, mn);\n\t\t\t\tfloat proportion = (sum / mn) / 18.0; //proportion of six neighbors is non-zero\n\t\t\t\t\n\t\t\t\t//a high proportion of hits means crevice\n\t\t\t\t//since the AO term adds shadows that darken most voxels, it will result in dark surfaces\n\t\t\t\t//the term brighten adds a little illumination to balance this\n\t\t\t\t// without brighten, only the most extreme ridges will not be darker\n\t\t\t\tconst float brighten = 1.2;\n\t\t\t\tvec3 ao = draw.rgb * (1.0 - proportion) * brighten;\n\t\t\t\tdraw.rgb = mix (draw.rgb, ao , renderDrawAmbientOcclusionX);\n\t\t\t}\n\t\t\tcolorSample = draw;\n\t\t\t} // end else (discrete drawing path)\n\t\t}\n\t\tsamplePos += deltaDir; //advance ray position\n\t\tif (colorSample.a >= 0.01) {\n\t\t\tif (overFirstHit.a > len)\n\t\t\t\toverFirstHit = samplePos;\n\t\t\tcolorSample.a *= renderOverlayBlend;\n\t\t\tcolorSample.a = 1.0-pow((1.0 - colorSample.a), opacityCorrection);\n\t\t\tcolorSample.rgb *= colorSample.a;\n\t\t\tcolAcc= (1.0 - colAcc.a) * colorSample + colAcc;\n\t\t\toverFarthest = samplePos.a;\n\t\t\tif ( colAcc.a > earlyTermination )\n\t\t\t\tbreak;\n\t\t}\n\t}\n\t//if (samplePos.a >= len) {\n\tif (colAcc.a <= 0.0) {\n\t\tif (isClip && (fColor.a == 0.0))\n\t\t\tfColor += clipPlaneColorX;\n\t\treturn;\n\t}\n\tif (overFirstHit.a < firstHit.a)\n\t\tgl_FragDepth = frac2ndc(overFirstHit.xyz);\n\tfloat overMix = colAcc.a;\n\tfloat overlayDepth = 0.3;\n\tif (fColor.a <= 0.0)\n\t\toverMix = 1.0;\n\telse if (((overFarthest) > backNearest)) {\n\t\tfloat dx = (overFarthest - backNearest)/1.73;\n\t\tdx = fColor.a * pow(dx, overlayDepth);\n\t\toverMix *= 1.0 - dx;\n\t}\n\tfColor.rgb = mix(fColor.rgb, colAcc.rgb, overMix);\n\tfColor.a = max(fColor.a, colAcc.a);\n}",En="#version 300 es\n#line 215\n#define MAX_CLIP_PLANES 6\nprecision highp int;\nprecision highp float;\nuniform vec3 rayDir;\nuniform vec3 texVox;\nuniform int backgroundMasksOverlays;\nuniform vec3 volScale;\nuniform vec4 clipPlane;\nuniform vec4 clipPlanes[MAX_CLIP_PLANES];\nuniform highp sampler3D volume, overlay;\nuniform highp sampler3D paqd;\nuniform vec4 paqdUniforms;\nuniform float overlays;\nuniform float backOpacity;\nuniform mat4 mvpMtx;\nuniform mat4 matRAS;\nuniform vec4 clipPlaneColor;\nuniform float renderOverlayBlend;\nuniform highp sampler3D drawing;\nuniform highp sampler3D drawSmoothed;\nuniform float smoothDrawing;\nuniform highp sampler2D colormap;\nuniform vec2 renderDrawAmbientOcclusionXY;\nuniform bool isClipAllVolumes;\nin vec3 vColor;\nout vec4 fColor;\n"+Tn+"\n\tvoid main() {\n\tvec3 start = vColor;\n\tgl_FragDepth = 1.0;\n\tvec3 backPosition = GetBackPosition(start);\n\tvec3 dir = normalize(backPosition - start);\n\t//clipVolumeStart(start, backPosition);\n\tfloat len = length(backPosition - start);\n\tfloat lenVox = length((texVox * start) - (texVox * backPosition));\n\tif ((lenVox < 0.5) || (len > 3.0)) { //length limit for parallel rays\n\t\tfColor = vec4(0.0,0.0,0.0,0.0);\n\t\treturn;\n\t}\n\tfloat sliceSize = len / lenVox; //e.g. if ray length is 1.0 and traverses 50 voxels, each voxel is 0.02 in unit cube\n\tfloat stepSize = sliceSize; //quality: larger step is faster traversal, but fewer samples\n\tfloat opacityCorrection = stepSize/sliceSize;\n\tvec4 deltaDir = vec4(dir.xyz * stepSize, stepSize);\n\tvec4 samplePos = vec4(start.xyz, 0.0); //ray position\n\tvec4 colAcc = vec4(0.0,0.0,0.0,0.0);\n\tvec4 firstHit = vec4(0.0,0.0,0.0,2.0 * len);\n\tconst float earlyTermination = 0.95;\n\tfloat backNearest = len; //assume no hit\n\tfloat dis = len;\n\t//check if axial plane is closest\n\tvec4 aClip = vec4(0.0, 0.0, 1.0, (1.0- clipPlane.z) - 0.5);\n\tfloat adis = (-aClip.a - dot(aClip.xyz, samplePos.xyz-0.5)) / dot(dir,aClip.xyz);\n\tif (adis > 0.0)\n\t\tdis = min(adis, dis);\n\t//check of coronal plane is closest\n\tvec4 cClip = vec4(0.0, 1.0, 0.0, (1.0- clipPlane.y) - 0.5);\n\tfloat cdis = (-cClip.a - dot(cClip.xyz, samplePos.xyz-0.5)) / dot(dir,cClip.xyz);\n\tif (cdis > 0.0)\n\t\tdis = min(cdis, dis);\n\t//check if coronal slice is closest\n\tvec4 sClip = vec4(1.0, 0.0, 0.0, (1.0- clipPlane.x) - 0.5);\n\tfloat sdis = (-sClip.a - dot(sClip.xyz, samplePos.xyz-0.5)) / dot(dir,sClip.xyz);\n\tif (sdis > 0.0)\n\t\tdis = min(sdis, dis);\n\tif ((dis > 0.0) && (dis < len)) {\n\t\tsamplePos = vec4(samplePos.xyz+dir * dis, dis);\n\t\tcolAcc = texture(volume, samplePos.xyz);\n\t\tcolAcc.a = earlyTermination;\n\t\tfirstHit = samplePos;\n\t\tbackNearest = min(backNearest, samplePos.a);\n\t}\n\t//the following are only used by overlays\n\tvec4 clipPlaneColorX = clipPlaneColor;\n\tbool isColorPlaneInVolume = false;\n\tbool isClip = false;\n\tbool isClipCutaway = false;\n\tvec2 sampleRange = vec2(0.0, len);\n\t// vec4 clipPos = applyClip(dir, samplePos, len, isClip);\n\tfloat stepSizeFast = sliceSize * 1.9;\n\tvec4 deltaDirFast = vec4(dir.xyz * stepSizeFast, stepSizeFast);\n\tvec2 overlaySampleRange = vec2(0.0, len);\n\tbool overlayIsClipCutaway = false;\n\tif (samplePos.a < 0.0)\n\t\tvec4 samplePos = vec4(start.xyz, 0.0); //ray position\n\tfloat ran = fract(sin(gl_FragCoord.x * 12.9898 
1+ gl_FragCoord.y * 78.233) * 43758.5453);\n\tsamplePos += deltaDir * ran; //jitter ray\n"+Sn,Fn="#version 300 es\n#line 215\n#define MAX_CLIP_PLANES 6\nprecision highp int;\nprecision highp float;\nuniform vec3 rayDir;\nuniform vec3 texVox;\nuniform int backgroundMasksOverlays;\nuniform vec3 volScale;\nuniform vec4 clipPlane;\nuniform vec4 clipPlanes[MAX_CLIP_PLANES];\nuniform bool isClipCutaway;\nuniform highp sampler3D volume, overlay;\nuniform highp sampler3D paqd;\nuniform vec4 paqdUniforms;\nuniform float overlays;\nuniform float backOpacity;\nuniform mat4 mvpMtx;\nuniform mat4 matRAS;\nuniform vec4 clipPlaneColor;\nuniform float renderOverlayBlend;\nuniform highp sampler3D drawing;\nuniform highp sampler3D drawSmoothed;\nuniform float smoothDrawing;\nuniform highp sampler2D colormap;\nuniform vec2 renderDrawAmbientOcclusionXY;\nuniform bool isClipAllVolumes;\nin vec3 vColor;\nout vec4 fColor;\n"+Tn+In+"while (samplePos.a <= len) {\n\t\tif (skipSample(samplePos.a, sampleRange) ^^ isClipCutaway) {\n\t\t\tsamplePos += deltaDirFast;\n\t\t\tcontinue;\n\t\t}\n\t\tvec4 colorSample = texture(volume, samplePos.xyz);\n\t\tsamplePos += deltaDir; //advance ray position\n\t\tif (colorSample.a >= 0.01) {\n\t\t\tif (firstHit.a > len)\n\t\t\t\tfirstHit = samplePos;\n\t\t\t// backNearest = min(backNearest, samplePos.a);\n\t\t\tcolorSample.a = 1.0-pow((1.0 - colorSample.a), opacityCorrection);\n\t\t\tcolorSample.rgb *= colorSample.a;\n\t\t\tcolAcc= (1.0 - colAcc.a) * colorSample + colAcc;\n\t\t\tif ( colAcc.a > earlyTermination )\n\t\t\t\tbreak;\n\t\t}\n\t}\n\tif (firstHit.a < len)\n\t\tbackNearest = firstHit.a;\n"+Sn,Bn=192,Vn="#version 300 es\n#line 215\n#define MAX_CLIP_PLANES 6\nprecision highp int;\nprecision highp float;\nuniform vec3 rayDir;\nuniform vec3 texVox;\nuniform int backgroundMasksOverlays;\nuniform vec3 volScale;\nuniform vec4 clipPlane;\nuniform vec4 clipPlanes[MAX_CLIP_PLANES];\nuniform bool isClipCutaway;\nuniform highp sampler3D volume, overlay;\nuniform highp sampler3D paqd;\nuniform vec4 paqdUniforms;\nuniform float overlays;\nuniform float backOpacity;\nuniform mat4 mvpMtx;\nuniform mat4 normMtx;\nuniform mat4 matRAS;\nuniform vec4 clipPlaneColor;\nuniform float renderOverlayBlend;\nuniform highp sampler3D drawing, gradient;\nuniform highp sampler3D drawSmoothed;\nuniform float smoothDrawing;\nuniform highp sampler2D colormap;\nuniform highp sampler2D matCap;\nuniform vec2 renderDrawAmbientOcclusionXY;\nuniform float gradientAmount;\nuniform float silhouettePower;\nuniform float gradientOpacity[192];\nuniform bool isClipAllVolumes;\nin vec3 vColor;\nout vec4 fColor;\n",Un=Vn+Tn+In+'\n\tfloat startPos = samplePos.a;\n\tfloat clipCloseThresh = 5.0 * deltaDir.a;\n\tfloat clipClose = sampleRange.x;\n\tif (isClipCutaway)\n\t\tclipClose = sampleRange.y;\n\tif (!isClip)\n\t\tclipClose = -1.0;\n\tfloat brighten = 2.0; //modulating makes average intensity darker 0.5 * 0.5 = 0.25\n\t//vec4 prevGrad = vec4(0.0);\n\tfloat silhouetteThreshold = 1.0 - silhouettePower;\n\twhile (samplePos.a <= len) {\n\t\tif (skipSample(samplePos.a, sampleRange) ^^ isClipCutaway) {\n\t\t\tsamplePos += deltaDirFast;\n\t\t\tcontinue;\n\t\t}\n\t\tvec4 colorSample = texture(volume, samplePos.xyz);\n\t\tif (colorSample.a >= 0.0) {\n\t\t\tvec4 grad = texture(gradient, samplePos.xyz);\n\t\t\tgrad.rgb = grad.rgb*2.0 - 1.0;\n\t\t\tif (grad.a > 0.0)\n\t\t\t\tgrad.rgb = normalize(grad.rgb);\n\t\t\t//if (grad.a < prevGrad.a)\n\t\t\t//\tgrad.rgb = prevGrad.rgb;\n\t\t\t//prevGrad = grad;\n\t\t\tvec3 n = mat3(normMtx) * grad.rgb;\n\t\t\tn.y = - n.y;\n\t\t\tvec4 mc = vec4(texture(matCap, n.xy * 0.5 + 0.5).rgb, 1.0) * brighten;\n\t\t\tmc = mix(vec4(1.0), mc, gradientAmount);\n\t\t\tif (abs(samplePos.a - clipClose) > clipCloseThresh)\n\t\t\t\tcolorSample.rgb *= mc.rgb;\n\t\t\tif (firstHit.a > len)\n\t\t\t\tfirstHit = samplePos;\n\t\t\tbackNearest = min(backNearest, samplePos.a);\n\t\t\tcolorSample.a = 1.0-pow((1.0 - colorSample.a), opacityCorrection);\n\t\t\tint gradIdx = int(grad.a * 192.0);\n\t\t\tcolorSample.a *= gradientOpacity[gradIdx];\n\t\t\tfloat lightNormDot = dot(grad.rgb, rayDir);\n\t\t\t// n.b. "lightNormDor" is cosTheta, "silhouettePower" is Fresnel effect exponent\n \t\t\tcolorSample.a *= pow(1.0 - abs(lightNormDot), silhouettePower);\n \t\t\tfloat viewAlign = abs(lightNormDot); // 0 = perpendicular, 1 = aligned\n \t\t\t// linearly map silhouettePower (0..1) to a threshold range, e.g., [1.0, 0.0]\n \t\t\t// Cull voxels that are too aligned with the view direction\n \t\t\tif (viewAlign > silhouetteThreshold)\n \t\t\t\tcolorSample.a = 0.0;\n\t\t\tcolorSample.rgb *= colorSample.a;\n\t\t\tcolAcc= (1.0 - colAcc.a) * colorSample + colAcc;\n\t\t\tif ( colAcc.a > earlyTermination )\n\t\t\t\tbreak;\n\t\t}\n\t\tsamplePos += deltaDir; //advance ray position\n\t}\n'+Sn,Rn=Vn+Tn+In+"\n\tfloat startPos = samplePos.a;\n\t//float clipClose = clipPos.a + 3.0 * deltaDir.a; //do not apply gradients near clip plane\n\tfloat brighten = 2.0; //modulating makes average intensity darker 0.5 * 0.5 = 0.25\n\t//vec4 prevGrad = vec4(0.0);\n\twhile (samplePos.a <= len) {\n\t\tvec4 colorSample = texture(volume, samplePos.xyz);\n\t\tif (colorSample.a >= 0.0) {\n\t\t\tvec4 grad = texture(gradient, samplePos.xyz);\n\t\t\tgrad.rgb = grad.rgb*2.0 - 1.0;\n\t\t\tif (grad.a > 0.0)\n\t\t\t\tgrad.rgb = normalize(grad.rgb);\n\t\t\tcolorSample.rgb = abs(grad.rgb);\n\t\t\tif (firstHit.a > len)\n\t\t\t\tfirstHit = samplePos;\n\t\t\tbackNearest = min(backNearest, samplePos.a);\n\t\t\tcolorSample.a = 1.0-pow((1.0 - colorSample.a), opacityCorrection);\n\t\t\tcolorSample.rgb *= colorSample.a;\n\t\t\tcolAcc= (1.0 - colAcc.a) * colorSample + colAcc;\n\t\t\tif ( colAcc.a > earlyTermination )\n\t\t\t\tbreak;\n\t\t}\n\t\tsamplePos += deltaDir; //advance ray position\n\t}\n"+Sn,Pn="#version 300 es\n#line 392\nlayout(location=0) in vec3 pos;\nuniform int axCorSag;\nuniform mat4 mvpMtx;\nuniform mat4 frac2mm;\nuniform float slice;\nout vec3 texPos;\nvoid main(void) {\n\ttexPos = vec3(pos.x, pos.y, slice);\n\tif (axCorSag >
1 1)\n\t\ttexPos = vec3(slice, pos.x, pos.y);\n\telse if (axCorSag > 0)\n\t\ttexPos = vec3(pos.x, slice, pos.y);\n\tvec4 mm = frac2mm * vec4(texPos, 1.0);\n\tgl_Position = mvpMtx * mm;\n}",Nn="#version 300 es\n#line 411\nprecision highp int;\nprecision highp float;\nuniform highp sampler3D volume, overlay;\nuniform highp sampler3D paqd;\nuniform vec4 paqdUniforms;\nuniform int backgroundMasksOverlays;\nuniform float overlayOutlineWidth;\nuniform float overlayAlphaShader;\nuniform int axCorSag;\nuniform float overlays;\nuniform float opacity;\nuniform float drawOpacity;\nuniform float drawRimOpacity;\nuniform bool isAlphaClipDark;\nuniform highp sampler3D drawing;\nuniform highp sampler2D colormap;\nin vec3 texPos;\nout vec4 color;\n"+Dn+'\nvec4 blendRGBA(vec4 foreground, vec4 background) {\n  float alphaOut = foreground.a + background.a * (1.0 - foreground.a);\n  vec3 colorOut = (foreground.rgb * foreground.a + background.rgb * background.a * (1.0 - foreground.a)) / alphaOut;\n  return vec4(colorOut, alphaOut);\n}\nfloat paqdEaseAlpha(float alpha) {\n  // t are alpha transitions\n  // <t0 -> y0\n  // t0..t1  -> mix between y0..y1\n  // t1..t2 -> mix between y1..y2\n  // >t2 -> y2\n  float t0 = paqdUniforms[0]; // 0.3;\n  float t1 = 0.5 * (paqdUniforms[0] + paqdUniforms[1]); // 0.4;\n  float t2 = paqdUniforms[1]; // 0.9;\n  float y0 = 0.0;\n  float y1 = abs(paqdUniforms[2]); // 1.0;\n  float y2 = abs(paqdUniforms[3]); //0.25;\n  if (alpha <= t0) {\n    return y0;\n  } else if (alpha <= t1) {\n    return mix(y0, y1, (alpha - t0) / (t1 - t0)); // LERP 0.0 \u2192 1.0\n  } else if (alpha <= t2) {\n    return mix(y1, y2, (alpha - t1) / (t2 - t1)); // LERP 1.0 \u2192 0.2\n  } else {\n    return y2;\n  }\n}\n\nvoid main() {\n\t//color = vec4(1.0, 0.0, 1.0, 1.0);return;\n\tvec4 background = texture(volume, texPos);\n\tcolor = vec4(background.rgb, opacity);\n\tif ((isAlphaClipDark) && (background.a == 0.0)) color.a = 0.0; //FSLeyes clipping range\n\tvec4 ocolor = vec4(0.0);\n\tfloat overlayAlpha = overlayAlphaShader;\n\tif (overlays > 0.0) {\n\t\tocolor = texture(overlay, texPos);\n\t\t//dFdx for "boxing" issue 435 has aliasing on some implementations (coarse vs fine)\n\t\t//however, this only identifies 50% of the edges due to aliasing effects\n\t\t// http://www.aclockworkberry.com/shader-derivative-functions/\n\t\t// https://bgolus.medium.com/distinctive-derivative-differences-cce38d36797b\n\t\t//if ((ocolor.a >= 1.0) && ((dFdx(ocolor.a) != 0.0) || (dFdy(ocolor.a) != 0.0)  ))\n\t\t//\tocolor.rbg = vec3(0.0, 0.0, 0.0);\n\t\tbool isOutlineBelowNotAboveThreshold = true;\n\t\tif (isOutlineBelowNotAboveThreshold) {\n\t\t\tif ((overlayOutlineWidth > 0.0) && (ocolor.a < 1.0)) { //check voxel neighbors for edge\n\t\t\t\tvec3 vx = (overlayOutlineWidth ) / vec3(textureSize(overlay, 0));\n\t\t\t\t//6 voxel neighbors that share a face\n\t\t\t\tvec3 vxR = vec3(texPos.x+vx.x, texPos.y, texPos.z);\n\t\t\t\tvec3 vxL = vec3(texPos.x-vx.x, texPos.y, texPos.z);\n\t\t\t\tvec3 vxA = vec3(texPos.x, texPos.y+vx.y, texPos.z);\n\t\t\t\tvec3 vxP = vec3(texPos.x, texPos.y-vx.y, texPos.z);\n\t\t\t\tvec3 vxS = vec3(texPos.x, texPos.y, texPos.z+vx.z);\n\t\t\t\tvec3 vxI = vec3(texPos.x, texPos.y, texPos.z-vx.z);\n\t\t\t\tfloat a = 0.0;\n\t\t\t\tif (axCorSag != 2) {\n\t\t\t\t\ta = max(a, texture(overlay, vxR).a);\n\t\t\t\t\ta = max(a, texture(overlay, vxL).a);\n\t\t\t\t}\n\t\t\t\tif (axCorSag != 1) {\n\t\t\t\t\ta = max(a, texture(overlay, vxA).a);\n\t\t\t\t\ta = max(a, texture(overlay, vxP).a);\n\t\t\t\t}\n\t\t\t\tif (axCorSag != 0) {\n\t\t\t\t\ta = max(a, texture(overlay, vxS).a);\n\t\t\t\t\ta = max(a, texture(overlay, vxI).a);\n\t\t\t\t}\n\t\t\t\tbool isCheckCorners = true;\n\t\t\t\tif (isCheckCorners) {\n\t\t\t\t\t//12 voxel neighbors that share an edge\n\t\t\t\t\tvec3 vxRA = vec3(texPos.x+vx.x, texPos.y+vx.y, texPos.z);\n\t\t\t\t\tvec3 vxLA = vec3(texPos.x-vx.x, texPos.y+vx.y, texPos.z);\n\t\t\t\t\tvec3 vxRP = vec3(texPos.x+vx.x, texPos.y-vx.y, texPos.z);\n\t\t\t\t\tvec3 vxLP = vec3(texPos.x-vx.x, texPos.y-vx.y, texPos.z);\n\t\t\t\t\tvec3 vxRS = vec3(texPos.x+vx.x, texPos.y, texPos.z+vx.z);\n\t\t\t\t\tvec3 vxLS = vec3(texPos.x-vx.x, texPos.y, texPos.z+vx.z);\n\t\t\t\t\tvec3 vxRI = vec3(texPos.x+vx.x, texPos.y, texPos.z-vx.z);\n\t\t\t\t\tvec3 vxLI = vec3(texPos.x-vx.x, texPos.y, texPos.z-vx.z);\n\t\t\t\t\tvec3 vxAS = vec3(texPos.x, texPos.y+vx.y, texPos.z+vx.z);\n\t\t\t\t\tvec3 vxPS = vec3(texPos.x, texPos.y-vx.y, texPos.z+vx.z);\n\t\t\t\t\tvec3 vxAI = vec3(texPos.x, texPos.y+vx.y, texPos.z-vx.z);\n\t\t\t\t\tvec3 vxPI = vec3(texPos.x, texPos.y-vx.y, texPos.z-vx.z);\n\n\t\t\t\t\tif (axCorSag == 0) { //axial corners\n\t\t\t\t\t\ta = max(a, texture(overlay, vxRA).a);\n\t\t\t\t\t\ta = max(a, texture(overlay, vxLA).a);\n\t\t\t\t\t\ta = max(a, texture(overlay, vxRP).a);\n\t\t\t\t\t\ta = max(a, texture(overlay, vxLP).a);\n\t\t\t\t\t}\n\t\t\t\t\tif (axCorSag == 1) { //coronal corners\n\t\t\t\t\t\ta = max(a, texture(overlay, vxRS).a);\n\t\t\t\t\t\ta = max(a, texture(overlay, vxLS).a);\n\t\t\t\t\t\ta = max(a, texture(overlay, vxRI).a);\n\t\t\t\t\t\ta = max(a, texture(overlay, vxLI).a);\n\t\t\t\t\t}\n\t\t\t\t\tif (axCorSag == 2) { //sagittal corners\n\t\t\t\t\t\ta = max(a, texture(overlay, vxAS).a);\n\t\t\t\t\t\ta = max(a, texture(overlay, vxPS).a);\n\t\t\t\t\t\ta = max(a, texture(overlay, vxAI).a);\n\t\t\t\t\t\ta = max(a, texture(overlay, vxPI).a);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (a >= 1.0) {\n\t\t\t\t\tocolor = vec4(0.0, 0.0, 0.0, 1.0);\n\t\t\t\t\toverlayAlpha = 1.0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tif ((overlayOutlineWidth > 0.0) && (ocolor.a >= 1.0)) { //check voxel neighbors for edge\n\t\t\t\tvec3 vx = (overlayOutlineWidth ) / vec3(textureSize(overlay, 0));\n\t\t\t\tvec3 vxR = vec3(texPos.x+vx.x, texPos.y, texPos.z);\n\t\t\t\tvec3 vxL = vec3(texPos.x-vx.x, texPos.y, texPos.z);\n\t\t\t\tvec3 vxA = vec3(texPos.x, texPos.y+vx.y, texPos.z);\n\t\t\t\tvec3 vxP = vec3(texPos.x, texPos.y-vx.y, texPos.z);
1\n\t\t\t\tvec3 vxS = vec3(texPos.x, texPos.y, texPos.z+vx.z);\n\t\t\t\tvec3 vxI = vec3(texPos.x, texPos.y, texPos.z-vx.z);\n\t\t\t\tfloat a = 1.0;\n\t\t\t\tif (axCorSag != 2) {\n\t\t\t\t\ta = min(a, texture(overlay, vxR).a);\n\t\t\t\t\ta = min(a, texture(overlay, vxL).a);\n\t\t\t\t}\n\t\t\t\tif (axCorSag != 1) {\n\t\t\t\t\ta = min(a, texture(overlay, vxA).a);\n\t\t\t\t\ta = min(a, texture(overlay, vxP).a);\n\t\t\t\t}\n\t\t\t\tif (axCorSag != 0) {\n\t\t\t\t\ta = min(a, texture(overlay, vxS).a);\n\t\t\t\t\ta = min(a, texture(overlay, vxI).a);\n\t\t\t\t}\n\t\t\t\tif (a < 1.0) {\n\t\t\t\t\tocolor = vec4(0.0, 0.0, 0.0, 1.0);\n\t\t\t\t\toverlayAlpha = 1.0;\n\t\t\t\t}\n\t\t\t}\n\t\t} //outline above threshold\n\t}\n\n',Ln="#version 300 es\n#line 411\nprecision highp int;\nprecision highp float;\nuniform highp sampler2D volume, overlay;\nuniform int backgroundMasksOverlays;\nuniform float overlayOutlineWidth;\nuniform float overlayAlphaShader;\nuniform int axCorSag;\nuniform float overlays;\nuniform float opacity;\nuniform float drawOpacity;\nuniform bool isAlphaClipDark;\nuniform highp sampler2D drawing;\nuniform highp sampler2D colormap;\nin vec3 texPos;\nout vec4 color;"+Dn+"void main() {\n\t//color = vec4(1.0, 0.0, 1.0, 1.0);return;\n\tvec4 background = texture(volume, texPos.xy);\n\tcolor = vec4(background.rgb, opacity);\n\tif ((isAlphaClipDark) && (background.a == 0.0)) color.a = 0.0; //FSLeyes clipping range\n\tvec4 dcolor = drawColor(texture(drawing, texPos.xy).r, drawOpacity);\n\tif (dcolor.a > 0.0) {\n\t\tcolor.rgb = mix(color.rgb, dcolor.rgb, dcolor.a);\n\t\tcolor.a = max(drawOpacity, color.a);\n\t}\n}",kn="\tocolor.a *= overlayAlpha;\n\tfloat drawV = texture(drawing, texPos).r;\n\tvec4 dcolor = drawColor(drawV, drawOpacity);\n\tif (dcolor.a > 0.0) {\n\t\tif (drawRimOpacity >= 0.0) {\n\t\t\tvec3 vx = 1.0 / vec3(textureSize(drawing, 0));\n\t\t\t//6 voxel neighbors that share a face\n\t\t\tvec3 offsetX = dFdx(texPos); // left-right spacing\n\t\t\tvec3 offsetY = dFdy(texPos); // up-down spacing\n\t\t\tfloat L = texture(drawing, texPos - offsetX).r;\n\t\t\tfloat R = texture(drawing, texPos + offsetX).r;\n\t\t\tfloat T = texture(drawing, texPos - offsetY).r;\n\t\t\tfloat B = texture(drawing, texPos + offsetY).r;\n\t\t\tif (L != drawV || R != drawV || T != drawV || B != drawV)\n\t\t\t\tdcolor.a = drawRimOpacity;\n\t\t}\n\t\tcolor.rgb = mix(color.rgb, dcolor.rgb, dcolor.a);\n\t\tcolor.a = max(drawOpacity, color.a);\n\t}\n\tvec4 pcolor = texture(paqd, texPos);\n\tif (pcolor.a > 0.0) {\n\t\tpcolor.a = paqdEaseAlpha(pcolor.a);\n\t\tif (pcolor.a > 0.0) {\n\t\t\tif (paqdUniforms[3] < 0.0)\n\t\t\t\tocolor = blendRGBA(pcolor, ocolor);\n\t\t\telse\n\t\t\t\tocolor = blendRGBA(ocolor, pcolor);\n\t\t}\n\t}\n\tif ((backgroundMasksOverlays > 0) && (background.a == 0.0))\n\t\treturn;\n\tfloat a = color.a + ocolor.a * (1.0 - color.a); // premultiplied alpha\n\tif (a == 0.0) return;\n\tcolor.rgb = mix(color.rgb, ocolor.rgb, ocolor.a / a);\n\tcolor.a = a;\n}",On=Nn+kn,zn=Nn+"\tif (ocolor.a > 0.0) {\n\t\t//https://gamedev.stackexchange.com/questions/102889/is-it-possible-to-convert-vec4-to-int-in-glsl-using-opengl-es\n\t\tuint alpha = uint(ocolor.a * 255.0);\n\t\tvec3 xyzFlip = vec3(float((uint(1) & alpha) > uint(0)), float((uint(2) & alpha) > uint(0)), float((uint(4) & alpha) > uint(0)));\n\t\t//convert from 0 and 1 to -1 and 1\n\t\txyzFlip = (xyzFlip * 2.0) - 1.0;\n\t\t//https://math.stackexchange.com/questions/1905533/find-perpendicular-distance-from-point-to-line-in-3d\n\t\t//v1 principle direction of tensor for this voxel\n\t\tvec3 v1 = ocolor.rgb;\n\t\t//flips encode polarity to convert from 0..1 to -1..1 (27 bits vs 24 bit precision)\n\t\tv1 = normalize( v1 * xyzFlip);\n\t\tvec3 vxl = fract(texPos * vec3(textureSize(volume, 0))) - 0.5;\n\t\t//vxl coordinates now -0.5..+0.5 so 0,0,0 is origin\n\t\tvxl.x = -vxl.x;\n\t\tfloat t = dot(vxl,v1);\n\t\tvec3 P = t * v1;\n\t\tfloat dx = length(P-vxl);\n\t\tocolor.a = 1.0 - smoothstep(0.2,0.25, dx);\n\t\t//if modulation was applied, use that to scale alpha not color:\n\t\tocolor.a *= length(ocolor.rgb);\n\t\tocolor.rgb = normalize(ocolor.rgb);\n\t\t//compute distance one half voxel closer to viewer:\n\t\tfloat pan = 0.5;\n\t\tif (axCorSag == 0)\n\t\t\tvxl.z -= pan;\n\t\tif (axCorSag == 1)\n\t\t\tvxl.y -= pan;\n\t\tif (axCorSag == 2)\n\t\t\tvxl.x += pan;\n\t\tt = dot(vxl,v1);\n\t\tP = t * v1;\n\t\tfloat dx2 = length(P-vxl);\n\t\tocolor.rgb += (dx2-dx-(0.5 * pan)) * 1.0;\n\t}\n"+kn,Yn="#version 300 es\n#line 480\nprecision highp int;\nprecision highp float;\nuniform vec4 lineColor;\nout vec4 color;\nvoid main() {\n\tcolor = lineColor;\n}",Gn="#version 300 es\n#line 520\nlayout(location=0) in vec3 pos;\nuniform vec2 canvasWidthHeight;\nuniform vec4 leftTopWidthHeight;\nvoid main(void) {\n\t//convert pixel x,y space 1..canvasWidth,1..canvasHeight to WebGL 1..-1,-1..1\n\tvec2 frac;\n\tfrac.x = (leftTopWidthHeight.x + (pos.x * leftTopWidthHeight.z)) / canvasWidthHeight.x; //0..1\n\tfrac.y = 1.0 - ((leftTopWidthHeight.y + ((1.0 - pos.y) * leftTopWidthHeight.w)) / canvasWidthHeight.y); //1..0\n\tfrac = (frac * 2.0) - 1.0;\n\tgl_Position = vec4(frac, 0.0, 1.0);\n}",Wn="#version 300 es\n#line 613\nprecision highp int;\nprecision highp float;\nin vec3 vPos;\nout vec2 TexCoord;\nvoid main() {\n\tTexCoord = vPos.xy;\n\tgl_Position = vec4( (vPos.xy-vec2(0.5,0.5)) * 2.0, 0.0, 1.0);\n}",Xn="#version 300 es\nuniform highp usampler3D intensityVol;\n",Kn="#version 300 es\nuniform highp isampler3D intensityVol;\n",Hn="#version 300 es\nuniform highp sampler3D intensityVol;\n",Qn="#line 1042\nprecision highp int;\nprecision highp float;\nin vec2 TexCoord;\nout vec4 FragColor;\nuniform bool isAdditiveBlend;\nuniform float coordZ;\nuniform float layer;\nuniform highp sampler2D colormap;\nuniform lowp sampler3D blend3D;\nuniform float opacity;\nuniform uint activeIndex;\nuniform vec4 xyzaFrac;\nuniform mat4 mtx;\nfloat textureWidth;\nfloat nlayer;\nfloat layerY;\n\nvec4 scalar2color(uint idx) {\n\tfloat fx = (float(idx) + 0.5) / textureWidth;\n\tvec4 clr = texture(colormap, vec2(fx, layerY)).rgba;\n\tif (clr.a > 0.0)\n\t\tclr.a = 1.0;\n\tclr.a *= opacity;\n\treturn clr;\n}\nvoid main(void) {\n\tvec4 vx = vec4(TexCoord.x, TexCoord.y, coordZ, 1.0) * mtx;\n\tuint idx = uint(texture(intensityVol, vx.xyz).r);\n\tif (idx == uint(0)) {\n\t\tif (layer < 1.0) {\n\t\t\tFragColor = vec4(0.0, 0.0, 0.0, 0.0);\n\t\t\treturn;\n\t\t}\n\t\tFragColor = texture(blend3D, vec3(TexCoord.xy, coordZ));\n\t\treturn;\n\t}\n\ttextureWidth = float(textureSize(colormap, 0).x);\n\tnlayer = float(textureSize(colormap, 0).y);\n\tlayerY = ((2.0 * layer) + 1.5) / nlayer;\n\t//idx = ((idx - uint(1)) % uint(100))+uint(1);\n\tFragColor = scalar2color(idx);\n\tbool isBorder = false;\n\tvx = vec4(TexCoord.x+xyzaFrac.x, TexCoord.y, coordZ, 1.0) * mtx;\n\tuint R = uint(texture(intensityVol, vx.xyz).r);\n\tvx = vec4(TexCoord.x-xyzaFrac.x, TexCoord.y, coordZ, 1.0) * mtx;\n\tuint L = uint(texture(intensityVol, vx.xyz).r);\n\tvx = vec4(TexCoord.x, TexCoord.y+xyzaFrac.y, coordZ, 1.0) * mtx;\n\tuint A = uint(texture(intensityVol, vx.xyz).r);\n\tvx = vec4(TexCoord.x, TexCoord.y-xyzaFrac.y, coordZ, 1.0) * mtx;\n\tuint P = uint(texture(intensityVol, vx.xyz).r);\n\tvx = vec4(TexCoord.x, TexCoord.y, coordZ+xyzaFrac.z, 1.0) * mtx;\n\tuint S = uint(texture(intensityVol, vx.xyz).r);\n\tvx = vec4(TexCoord.x, TexCoord.y, coordZ-xyzaFrac.z, 1.0) * mtx;\n\tuint I = uint(texture(intensityVol, vx.xyz).r);\n\tvec4 centerColor = FragColor;\n\tFragColor.a += scalar2color(R).a;\n\tFragColor.a += scalar2color(L).a;\n\tFragColor.a += scalar2color(A).a;\n\tFragColor.a += scalar2color(P).a;\n\tFragColor.a += scalar2color(S).a;\n\tFragColor.a += scalar2color(I).a;\n\tFragColor.a /= 7.0;\n\tif ((!isBorder) &&(idx == activeIndex)) {\n\t\tif (centerColor.a > 0.5)\n\t\t\tFragColor.a *= 0.4;\n\t\telse\n\t\t\tFragColor.a =0.8;\n\t}\n\tif (xyzaFrac.a != 0.0) { //outline\n\t\tif ((idx != R) || (idx != L) || (idx != A) || (idx != P) || (idx != S) || (idx != I)) {\n\t\t\tisBorder = true;\n\t\t\tif (xyzaFrac.a > 0.0)\n\t\t\t\tFragColor.a = xyzaFrac.a;\n\t\t\telse\n\t\t\t\tFragColor = vec4(0.0, 0.0, 0.0, 1.0);\n\t\t}\n\t}\n\tif (layer < 1.0) return;\n\t\tvec4 prevColor = texture(blend3D, vec3(TexCoord.xy, coordZ));\n\t\t// https://en.wikipedia.org/wiki/Alpha_compositing\n\t\tfloat aout = FragColor.a + (1.0 - FragColor.a) * prevColor.a;\n\t\tif (aout <= 0.0) return;\n\t\tif (isAdditiveBlend)\n\t\t\tFragColor.rgb = ((FragColor.rgb * FragColor.a) + (prevColor.rgb * prevColor.a)) / aout;\n\t\telse\n\t\t\tFragColor.rgb = ((FragColor.rgb * FragColor.a) + (prevColor.rgb * prevColor.a * (1.0 - FragColor.a))) / aout;\n\t\tFragColor.a = aout;\n}",qn="#line 691\nprecision highp int;\nprecision highp float;\nin vec2 TexCoord;\nout vec4 FragColor;\nuniform float coordZ;\nuniform float layer;\nuniform float scl_slope;\nuniform float scl_inter;\nuniform float cal_max;\nuniform float cal_min;\nuniform float cal_maxNeg;\nuniform float cal_minNeg;\nuniform bool isAlphaThreshold;\nuniform bool isColorbarFromZero;\nuniform bool isAdditiveBlend;\nuniform highp sampler2D colormap;\nuniform lowp sampler3D blend3D;\nuniform int modulation;\nuniform highp sampler3D modulationVol;\nuniform float opacity;\nuniform mat4 mtx;\nvoid main(void) {\n\tvec4 vx = vec4(TexCoord.xy, coordZ, 1.0) * mtx;\n\tif ((vx.x < 0.0) || (vx.x > 1.0) || (vx.y < 0.0) || (vx.y > 1.0) || (vx.z < 0.0) || (vx.z > 1.0)) {\n\t\t//set transparent if out of range\n\t\t//https://webglfundamentals.org/webgl/webgl-3d-textures-repeat-clamp.html\n\t\tFragColor = texture(blend3D, vec3(TexCoord.xy, coordZ));\n\t\treturn;\n\t}\n\tfloat f = (scl_slope * float(texture(intensityVol, vx.xyz).r)) + scl_inter;\n\tfloat mn = cal_min;\n\tfloat mx = cal_max;\n\tif ((isAlphaThreshold) || (isColorbarFromZero))\n\t\tmn = 0.0;\n\tfloat r = max(0.00001, abs(mx - mn));\n\tmn = min(mn, mx);\n\tfloat txl = mix(0.0, 1.0, (f - mn) / r);\n\tif (f > mn) { //issue1139: survives threshold, so round up to opaque voxel\n\t\ttxl = max(txl, 2.0/256.0);\n\t}\n\t//https://stackoverflow.com/questions/5879403/opengl-texture-coordinates-in-pixel-space\n\tfloat nlayer = float(textureSize(colormap, 0).y);\n\t//each volume has two color maps:\n\t// (layer*2) = negative and (layer * 2) + 1 = positive\n\tfloat y = ((2.0 * layer) + 1.5)/nlayer;\n\tFragColor = texture(colormap, vec2(txl, y)).rgba;\n\t//negative colors\n\tmn = cal_minNeg;\n\tmx = cal_maxNeg;\n\tif ((isAlphaThreshold) || (isColorbarFromZero))\n\t\tmx = 0.0;\n\t//if ((!isnan(cal_minNeg)) && ( f < mx)) {\n\tif ((cal_minNeg < cal_maxNeg) && ( f < mx)) {\n\t\tr = max(0.00001, abs(mx - mn));\n\t\tmn = min(mn, mx);\n\t\ttxl = 1.0 - mix(0.0, 1.0, (f - mn) / r);\n\t\t//issue1139: survives threshold, so round up to opaque voxel\n\t\ttxl = max(txl, 2.0/256.0);\n\t\ty = ((2.0 * layer) + 0.5)/nlayer;\n\t\tFragColor = texture(colormap, vec2(txl, y));\n\t}\n\tif (layer > 0.7)\n\t\tFragColor.a = step(0.00001, FragColor.a);\n\t//if (modulation > 10)\n\t//\tFragColor.a *= texture(modulationVol, vx.xyz).r;\n\t//\tFragColor.rgb *= texture(modulationVol, vx.xyz).r;\n\tif (isAlphaThreshold) {\n\t\tif ((cal_minNeg != cal_maxNeg) && ( f < 0.0) && (f > cal_maxNeg))\n\t\t\tFragColor.a = pow(-f / -cal_maxNeg, 2.0);\n\t\telse if ((f > 0.0) && (cal_min > 0.0))\n\t\t\tFragColor.a *= pow(f / cal_min, 2.0); //issue435:  A = (V/X)**2\n\t\t//FragColor.g = 0.0;\n\t} else if (isColorbarFromZero) {\n\t\tif ((cal_minNeg != cal_maxNeg) && ( f < 0.0) && (f > cal_maxNeg))\n\t\t\tFragColor.a = 0.0;\n\t\telse if ((f > 0.0) && (cal_min > 0.0) && (f < cal_min))\n\t\t\tFragColor.a *= 0.0;\n\n\t}\n\tif (modulation == 1) {\n\t\tFragColor.rgb *= texture(modulationVol, vx.xyz).r;\n\t} else if (modulation == 2) {\n\t\tFragColor.a = texture(modulationVol, vx.xyz).r;\n\t}\n\tFragColor.a *= opacity;\n\tif (layer < 1.0) return;\n\tvec4 prevColor = texture(blend3D, vec3(TexCoord.xy, coordZ));\n\t// https://en.wikipedia.org/wiki/Alpha_compositing\n\tfloat aout = FragColor.a + (1.0 - FragColor.a) * prevColor.a;\n\tif (aout <= 0.0) return;\n\tif (isAdditiveBlend)\n\t\tFragColor.rgb = ((FragColor.rgb * FragColor.a) + (prevColor.rgb * prevColor.a)) / aout;\n\telse\n\t\tFragColor.rgb = ((FragColor.rgb * FragColor.a) + (prevColor.rgb * prevColor.a * (1.0 - FragColor.a))) / aout;\n\tFragColor.a = aout;\n}",Zn="#version 300 es\nlayout(location=0) in vec3 pos;\nlayout(location=1) in vec4 norm;\nlayout(location=2) in vec4 clr;\nuniform mat4 mvpMtx;\n//uniform mat4 modelMtx;\nuniform mat4 normMtx;\nout vec4 vClr;\nout vec3 vN;\nout vec4 vP;\nout vec4 vPc;\nvoid main(void) {\n\tvec3 lightPosition = vec3(0.0, 0.0, -10.0);
1\n\tvP = vec4(pos, 1.0);\n\tvPc = mvpMtx * vec4(pos, 1.0);\n\tgl_Position = vPc;\n\tvN = normalize((normMtx * vec4(norm.xyz,1.0)).xyz);\n\t//vV = -vec3(modelMtx*vec4(pos,1.0));\n\tvClr = clr;\n}",jn="#version 300 es\nprecision highp int;\nprecision highp float;\nuniform float opacity;\nin vec4 vClr;\nflat in vec3 vN;\nout vec4 color;\nvoid main() {\n\tvec3 r = vec3(0.0, 0.0, 1.0); //rayDir: for orthographic projections moving in Z direction (no need for normal matrix)\n\tfloat ambient = 0.35;\n\tfloat diffuse = 0.5;\n\tfloat specular = 0.2;\n\tfloat shininess = 10.0;\n\tvec3 n = normalize(vN);\n\tvec3 lightPosition = vec3(0.0, 10.0, -5.0);\n\tvec3 l = normalize(lightPosition);\n\tfloat lightNormDot = dot(n, l);\n\tvec3 a = vClr.rgb * ambient;\n\tvec3 d = max(lightNormDot, 0.0) * vClr.rgb * diffuse;\n\tfloat s = specular * pow(max(dot(reflect(l, n), r), 0.0), shininess);\n\tcolor = vec4(a + d + s, opacity);\n}",Jn="#version 300 es\n#line 1260\n#define MAX_CLIP_PLANES 6\n//precision highp int;\nprecision highp float;\nuniform vec3 rayDir;\nuniform vec3 volScale;\nuniform vec3 texVox;\nuniform vec4 clipPlane;\nuniform vec4 clipPlanes[MAX_CLIP_PLANES];\nuniform bool isClipCutaway;\nuniform highp sampler3D volume, overlay;\nuniform highp sampler3D paqd;\nuniform vec4 paqdUniforms;\nuniform float overlays;\nuniform mat4 matRAS;\nuniform mat4 mvpMtx;\nuniform float drawOpacity, renderOverlayBlend;\nuniform highp sampler3D drawing;\nuniform highp sampler2D colormap;\nuniform int backgroundMasksOverlays;\nin vec3 vColor;\nout vec4 fColor;\n"+Tn+"\nvoid main() {\n\tint id = 254;\n\tvec3 start = vColor;\n\tgl_FragDepth = 1.0;\n\tfColor = vec4(0.0, 0.0, 0.0, 0.0); //assume no hit: ID = 0\n\tfloat fid = float(id & 255)/ 255.0;\n\tvec3 backPosition = GetBackPosition(start);\n\tvec3 dir = normalize(backPosition - start);\n\t//clipVolumeStart(start, backPosition);\n\tfloat len = length(backPosition - start);\n\tfloat lenVox = length((texVox * start) - (texVox * backPosition));\n\tif ((lenVox < 0.5) || (len > 3.0)) return;//discard; //length limit for parallel rays\n\tfloat sliceSize = len / lenVox; //e.g. if ray length is 1.0 and traverses 50 voxels, each voxel is 0.02 in unit cube\n\tfloat stepSize = sliceSize; //quality: larger step is faster traversal, but fewer samples\n\tfloat opacityCorrection = stepSize/sliceSize;\n\tdir = normalize(dir);\n\tvec4 samplePos = vec4(start.xyz, 0.0); //ray position\n\tbool hasClip = false;\n\tvec2 sampleRange = vec2(0.0, len);\n\tfor (int i = 0; i < MAX_CLIP_PLANES; i++)\n\t\tclipSampleRange(dir, samplePos, clipPlanes[i], sampleRange, hasClip);\n\tbool isClip = (sampleRange.x > 0.0) || ((sampleRange.y < len) && (sampleRange.y > 0.0));\n\t//vec4 clipPos = applyClip(dir, samplePos, len, isClip);\n\tif (isClip) fColor = vec4(samplePos.xyz, 253.0 / 255.0); //assume no hit: ID = 0\n\tif ((isClipCutaway) && (sampleRange.x <= 0.0) && (sampleRange.y >= len)) {\n\t\t//completely clipped, but ray does not intersect plane\n\t\tif (hasClip)\n\t\t\tsamplePos.a = len + 1.0;\n\t\telse\n\t\t\tsampleRange = vec2(0.0, 0.0);\n\t}\n\t//start: OPTIONAL fast pass: rapid traversal until first hit\n\tfloat stepSizeFast = sliceSize * 1.9;\n\tvec4 deltaDirFast = vec4(dir.xyz * stepSizeFast, stepSizeFast);\n\twhile (samplePos.a <= len) {\n\t\tif (skipSample(samplePos.a, sampleRange) ^^ isClipCutaway) {\n\t\t\tsamplePos += deltaDirFast;\n\t\t\tcontinue;\n\t\t}\n\t\tfloat val = texture(volume, samplePos.xyz).a;\n\t\tif (val > 0.01) {\n\t\t\tfColor = vec4(samplePos.rgb, fid);\n\t\t\tgl_FragDepth = frac2ndc(samplePos.xyz);\n\t\t\tbreak;\n\t\t}\n\t\tsamplePos += deltaDirFast; //advance ray position\n\t}\n\t//end: fast pass\n\tif ((overlays < 1.0) || (backgroundMasksOverlays > 0)) {\n\t\treturn; //background hit, no overlays\n\t}\n\t//overlay pass\n\tlen = min(len, samplePos.a); //only find overlay closer than background\n\tsamplePos = vec4(start.xyz, 0.0); //ray position\n\twhile (samplePos.a <= len) {\n\t\tfloat val = texture(overlay, samplePos.xyz).a;\n\t\tif (val > 0.01) {\n\t\t\tfColor = vec4(samplePos.rgb, fid);\n\t\t\tgl_FragDepth = frac2ndc(samplePos.xyz);\n\t\t\treturn;\n\t\t}\n\t\tsamplePos += deltaDirFast; //advance ray position\n\t}\n\t//if (fColor.a == 0.0) discard; //no hit in either background or overlays\n\t//you only get here if there is a hit with the background that is closer than any overlay\n}",_n="#version 300 es\n#line 286\nprecision highp int;\nprecision highp float;\nin vec3 vPos;\nout vec2 TexCoord;\nvoid main() {\n    TexCoord = vPos.xy;\n    gl_Position = vec4( (vPos.xy-vec2(0.5,0.5))* 2.0, 0.0, 1.0);\n}",$n="\n  gradientSample.a = log2(gradientSample.r*gradientSample.r + gradientSample.g*gradientSample.g + gradientSample.b*gradientSample.b + 1.922337562475971e-06) + 18.988706873717717;\n",tr=`#version 300 es\n#line 323\nprecision highp int;\nprecision highp float;\nin vec2 TexCoord;\nout vec4 FragColor;\nuniform float coordZ;\nuniform float dX;\nuniform float dY;\nuniform float dZ;\nuniform highp sampler3D intensityVol;\nvoid main(void) {\n  vec3 vx = vec3(TexCoord.xy, coordZ);\n  //Neighboring voxels 'T'op/'B'ottom, 'A'nterior/'P'osterior, 'R'ight/'L'eft\n  float TAR = texture(intensityVol,vx+vec3(+dX,+dY,+dZ)).a;\n  float TAL = texture(intensityVol,vx+vec3(+dX,+dY,-dZ)).a;\n  float TPR = texture(intensityVol,vx+vec3(+dX,-dY,+dZ)).a;\n  float TPL = texture(intensityVol,vx+vec3(+dX,-dY,-dZ)).a;\n  float BAR = texture(intensityVol,vx+vec3(-dX,+dY,+dZ)).a;\n  float BAL = texture(intensityVol,vx+vec3(-dX,+dY,-dZ)).a;\n  float BPR = texture(intensityVol,vx+vec3(-dX,-dY,+dZ)).a;\n  float BPL = texture(intensityVol,vx+vec3(-dX,-dY,-dZ)).a;\n  vec4 gradientSample = vec4 (0.0, 0.0, 0.0, 0.0);\n  gradientSample.r = BAR+BAL+BPR+BPL -TAR-TAL-TPR-TPL;\n  gradientSample.g = TPR+TPL+BPR+BPL -TAR-TAL-BAR-BAL;\n  gradientSample.b = TAL+TPL+BAL+BPL -TAR-TPR-BAR-BPR;\n${$n}\n\t// 0.04242020977371934 = 1/(log2(3*8) - log2(1/(255**2*8))) // 3*8 -> max for 1st order gradient\n\tgradientSample.a *= 0.04242020977371934;\n  float gradLen = length(gradientSample.rgb);\n  gradientSample.rgb = gradLen > 0.001 ? gradientSample.rgb / gradLen : vec3(0.0);\n  gradientSample.rgb = (gradientSample.rgb * 0.5)+0.5;\n  FragColor = gradientSample;\n}`,er=`#version 300 es\n#line 323\nprecision highp int;\nprecision highp float;\nin vec2 TexCoord;\nout vec4 FragColor;\nuniform float coordZ;\nuniform float dX;\nuniform float dY;\nuniform float dZ;\nuniform float dX2;\nuniform float dY2;\nuniform float dZ2;\nuniform highp sampler3D intensityVol;\nvoid main(void) {\n  vec3 vx = vec3(TexCoord.xy, coordZ);\n  //Neighboring voxels 'T'op/'B'ottom, 'A'nterior/'P'osterior, 'R'ight/'L'eft\n  vec4 TAR = texture(intensityVol,vx+vec3(+dX,+dY,+dZ));\n  vec4 TAL = texture(intensityVol,vx+vec3(+dX,+dY,-dZ));\n  vec4 TPR = texture(intensityVol,vx+vec3(+dX,-dY,+dZ));\n  vec4 TPL = texture(intensityVol,vx+vec3(+dX,-dY,-dZ));\n  vec4 BAR = texture(intensityVol,vx+vec3(-dX,+dY,+dZ));\n  vec4 BAL = texture(intensityVol,vx+vec3(-dX,+dY,-dZ));\n  vec4 BPR = texture(intensityVol,vx+vec3(-dX,-dY,+dZ));\n  vec4 BPL = texture(intensityVol,vx+vec3(-dX,-dY,-dZ));
1\n  vec4 T = texture(intensityVol,vx+vec3(+dX2,0.0,0.0));\n  vec4 A = texture(intensityVol,vx+vec3(0.0,+dY2,0.0));\n  vec4 R = texture(intensityVol,vx+vec3(0.0,0.0,+dZ2));\n  vec4 B = texture(intensityVol,vx+vec3(-dX2,0.0,0.0));\n  vec4 P = texture(intensityVol,vx+vec3(0.0,-dY2,0.0));\n  vec4 L = texture(intensityVol,vx+vec3(0.0,0.0,-dZ2));\n  vec4 gradientSample = vec4 (0.0, 0.0, 0.0, 0.0);\n  gradientSample.x = -4.0*B.x +8.0*(BAR.x+BAL.x+BPR.x+BPL.x) -8.0*(TAR.x+TAL.x+TPR.x+TPL.x) +4.0*T.x;\n  gradientSample.y = -4.0*P.y +8.0*(TPR.y+TPL.y+BPR.y+BPL.y) -8.0*(TAR.y+TAL.y+BAR.y+BAL.y) +4.0*A.y;\n  gradientSample.z = -4.0*L.z +8.0*(TAL.z+TPL.z+BAL.z+BPL.z) -8.0*(TAR.z+TPR.z+BAR.z+BPR.z) +4.0*R.z;\n${$n}\n\tgradientSample.a *= 0.0325;\n  float gradLen = length(gradientSample.xyz);\n  gradientSample.xyz = gradLen > 0.001 ? gradientSample.xyz / gradLen : vec3(0.0);\n  gradientSample.xyz =  (gradientSample.xyz * 0.5)+0.5;\n  FragColor = gradientSample;\n}`;function ir(t){const{gl:e,shader:i,gradientAmount:n=0,renderDrawAmbientOcclusion:r,renderSilhouette:a,gradientOpacity:s}=t;i.use(e),e.uniform1i(i.uniforms.volume,0),e.uniform1i(i.uniforms.colormap,1),e.uniform1i(i.uniforms.overlay,2),e.uniform1i(i.uniforms.drawing,7),e.uniform1i(i.uniforms.drawSmoothed,10),e.uniform1f(i.uniforms.smoothDrawing,0),e.uniform1i(i.uniforms.paqd,8),e.uniform1fv(i.uniforms.renderDrawAmbientOcclusion,[r,1]),e.uniform1f(i.uniforms.gradientAmount,n),e.uniform1f(i.uniforms.silhouettePower,a);const o=new Float32Array(Bn);for(let l=0;l<Bn;l++)o[l]=0===s?1:Math.pow(l/191,8*s);e.uniform1fv(e.getUniformLocation(i.program,"gradientOpacity"),o),i.uniforms.clipPlanes=e.getUniformLocation(i.program,"clipPlanes[0]")}function nr(t,e){const i=t.toLowerCase();for(let n=0;n<e.length;n++)if(e[n].Name.toLowerCase()===i)return n}function rr(t,e){for(let i=0;i<t.length;i++)if(t[i].id===e)return i;return-1}function ar(t,e,i){void 0===i&&(i=0);if(i>t.length)return{volumes:t,back:t.length>0?t[0]:null,overlays:t.slice(1)};const n=rr(t,e.id),r=[...t];return 0===i?(r.splice(n,1),r.unshift(e)):i<0?r.splice(n,1):(r.splice(n,1),r.splice(i,0,e)),{volumes:r,back:r.length>0?r[0]:null,overlays:r.slice(1)}}function sr(t,e){return{volumes:ar(t,e,-1).volumes,removed:e}}function or(t,e,i){if(!(t.dimsRAS&&t.matRAS&&t.pixDimsRAS&&t.vox2mm))throw new Error("Cannot create NiivueObject3D: Missing required RAS properties or vox2mm access on NVImage.");const n=t.dimsRAS,a=t.matRAS,s=t.pixDimsRAS,o=-.5,l=-.5,c=-.5,h=n[1]-1+.5,d=n[2]-1+.5,u=n[3]-1+.5,m=t.vox2mm,f=m.call(t,[o,l,c],a),g=m.call(t,[o,d,c],a),A=m.call(t,[o,l,u],a),p=m.call(t,[o,d,u],a),v=m.call(t,[h,l,c],a),x=m.call(t,[h,d,c],a),w=m.call(t,[h,l,u],a),y=m.call(t,[h,d,u],a),b=[...A,0,0,1,...w,1,0,1,...y,1,1,1,...p,0,1,1,...f,0,0,0,...g,0,1,0,...x,1,1,0,...v,1,0,0],C=i.createBuffer();if(!C)throw new Error("Failed to create GL index buffer");i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,C);const M=[0,3,2,2,1,0,4,7,6,6,5,4,5,6,2,2,3,5,4,0,1,1,7,4,7,1,2,2,6,7,4,5,3,3,0,4];i.bufferData(i.ELEMENT_ARRAY_BUFFER,new Uint16Array(M),i.STATIC_DRAW);const D=i.createBuffer();if(!D)throw new Error("Failed to create GL vertex buffer");i.bindBuffer(i.ARRAY_BUFFER,D),i.bufferData(i.ARRAY_BUFFER,new Float32Array(b),i.STATIC_DRAW);const T=i.createVertexArray();if(!T)throw new Error("Failed to create GL VAO");i.bindVertexArray(T),i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,C),i.bindBuffer(i.ARRAY_BUFFER,D);i.enableVertexAttribArray(0),i.vertexAttribPointer(0,3,i.FLOAT,!1,24,0),i.enableVertexAttribArray(1),i.vertexAttribPointer(1,3,i.FLOAT,!1,24,12),i.bindVertexArray(null);const I=new K(e,D,i.TRIANGLES,M.length,C,T),S=function(t,e){void 0===e&&(e=!0);const i=Math.round(t.length/3),n=r.fA(0,0,0),a=r.vt(),s=r.vt();let o=0,l=1;e&&(l=2);for(let c=0;c<l;c++){o=0;for(let l=0;l<i;l++){const e=r.fA(t[3*l],t[3*l+1],t[3*l+2]);0===l&&(r.C(a,e),r.C(s,e)),r.jk(a,a,e),r.T9(s,s,e),r.Re(e,e,n);const i=r.Il(e);o=Math.max(o,i)}if(c+1>=l)break;let e=!0;for(let t=0;t<3;++t)a[t]>n[t]&&(e=!1),s[t]<n[t]&&(e=!1);if(e)break;r.Cc(n,a,s,.5),Q.debug("origin moved inside volume: ",n)}return{min:[a[0],a[1],a[2]],max:[s[0],s[1],s[2]],furthestVertexFromOrigin:o,origin:n}}([...A,...w,...y,...p,...f,...g,...x,...v]);return I.extentsMin=S.min.slice(),I.extentsMax=S.max.slice(),I.furthestVertexFromOrigin=S.furthestVertexFromOrigin,I.originNegate=r.o8(S.origin),r.ze(I.originNegate,I.originNegate),I.fieldOfViewDeObliqueMM=[n[1]*s[1],n[2]*s[2],n[3]*s[3]],I}var lr=1002;function cr(t,e){if("number"==typeof e)return e>=t.length?-1:e;for(let i=0;i<t.length;i++)if(t[i].id===e)return i;return-1}
1var hr={name:"untitled connectome",nodeColormap:"warm",nodeColormapNegative:"winter",nodeMinColor:0,nodeMaxColor:4,nodeScale:3,edgeColormap:"warm",edgeColormapNegative:"winter",edgeMin:2,edgeMax:6,edgeScale:1,legendLineThickness:0,showLegend:!0},dr=class t extends Te{constructor(t,e){super(new Float32Array([]),new Uint32Array([]),e.name,new Uint8Array([]),1,!0,t,e),C(this,"gl"),C(this,"nodesChanged"),this.gl=t,this.type="connectome",this.nodes&&this.updateLabels(),this.nodesChanged=new EventTarget}static convertLegacyConnectome(t){const e={nodes:[],edges:[],...hr};for(const n in t)if(n in hr){const i=n;e[i]=t[i]}const i=t.nodes;for(let n=0;n<i.names.length;n++)e.nodes.push({name:i.names[n],x:i.X[n],y:i.Y[n],z:i.Z[n],colorValue:i.Color[n],sizeValue:i.Size[n]});for(let n=0;n<i.names.length-1;n++)for(let r=n+1;r<i.names.length;r++){const a=t.edges[n*i.names.length+r];e.edges.push({first:n,second:r,colorValue:a})}return e}static convertFreeSurferConnectome(t,e){void 0===e&&(e="warm");let i=!0;if("data_type"in t?"fs_pointset"!==t.data_type&&(i=!1):i=!1,"points"in t||(i=!1),!i)throw Error("not a valid FreeSurfer json pointset");const n=t.points.map((t=>({name:Array.isArray(t.comments)&&t.comments.length>0&&"text"in t.comments[0]?t.comments[0].text:"",x:t.coordinates.x,y:t.coordinates.y,z:t.coordinates.z,colorValue:1,sizeValue:1,metadata:t.comments})));return{...hr,nodeColormap:e,edgeColormap:e,nodes:n,edges:[]}}updateLabels(){const t=this.nodes;if(t&&t.length>0){const e=t.reduce(((t,e)=>t.sizeValue>e.sizeValue?t:e)).sizeValue;let i,n;if(void 0!==this.nodeMinColor&&isFinite(this.nodeMinColor))i=this.nodeMinColor;else{i=t[0].colorValue;for(let e=1;e<t.length;e++)t[e].colorValue<i&&(i=t[e].colorValue)}if(void 0!==this.nodeMaxColor&&isFinite(this.nodeMaxColor))n=this.nodeMaxColor;else{n=t[0].colorValue;for(let e=1;e<t.length;e++)t[e].colorValue>n&&(n=t[e].colorValue)}const r=ve.colormap(this.nodeColormap,this.colormapInvert),a=ve.colormap(this.nodeColormapNegative,this.colormapInvert),s="nodeColormapNegative"in this;let o=this.legendLineThickness?this.legendLineThickness:0;!1===this.showLegend&&(o=0);for(let l=0;l<t.length;l++){let c=t[l].colorValue,h=!1;if(s&&c<0&&(h=!0,c=-c),i<n){if(c<i){Q.warn("color value lower than min");continue}c=(c-i)/(n-i)}else c=1;c=4*Math.round(Math.max(Math.min(255,255*c)));let d=[r[c],r[c+1],r[c+2],255];h&&(d=[a[c],a[c+1],a[c+2],255]),d=d.map((t=>t/255)),Q.debug("adding label for ",t[l]),t[l].label=new Me(t[l].name,{textColor:d,bulletScale:t[l].sizeValue/e,bulletColor:d,lineWidth:o,lineColor:d,textScale:1,textAlignment:"left",lineTerminator:"none"},[t[l].x,t[l].y,t[l].z]),Q.debug("label for node:",t[l].label)}}}addConnectomeNode(t){if(Q.debug("adding node",t),!this.nodes)throw new Error("nodes not defined");this.nodes.push(t),this.updateLabels(),this.nodesChanged.dispatchEvent(new CustomEvent("nodeAdded",{detail:{node:t}}))}deleteConnectomeNode(t){const e=this.nodes.indexOf(t),i=this.edges;i&&(this.edges=i.filter((t=>t.first!==e&&t.second!==e))),this.nodes=this.nodes.filter((e=>e!==t)),this.updateLabels(),this.updateConnectome(this.gl),this.nodesChanged.dispatchEvent(new CustomEvent("nodeDeleted",{detail:{node:t}}))}updateConnectomeNodeByIndex(t,e){this.nodes[t]=e,this.updateLabels(),this.updateConnectome(this.gl),this.nodesChanged.dispatchEvent(new CustomEvent("nodeChanged",{detail:{node:e}}))}updateConnectomeNodeByPoint(t,e){const i=this.nodes;if(!i)throw new Error("Node to update does not exist");const n=i.find((e=>ye.arraysAreEqual([e.x,e.y,e.z],t)));if(!n)throw new Error(`Node with point ${t} to update does not exist`);const r=i.findIndex((t=>t===n));this.updateConnectomeNodeByIndex(r,e)}addConnectomeEdge(t,e,i){const n=this.edges;let r=n.find((i=>(i.first===t||i.second===t)&&i.first+i.second===t+e));return r||(r={first:t,second:e,colorValue:i},n.push(r),this.updateConnectome(this.gl),r)}deleteConnectomeEdge(t,e){const i=this.edges,n=i.find((i=>(i.first===t||i.first===e)&&i.first+i.second===t+e));if(!n)throw new Error(`edge between ${t} and ${e} not found`);return this.edges=i.filter((t=>t!==n)),this.updateConnectome(this.gl),n}findClosestConnectomeNode(t,e){const i=this.nodes;if(!i||0===i.length)return null;const n=i.map(((e,i)=>
1({node:e,distance:Math.sqrt(Math.pow(e.x-t[0],2)+Math.pow(e.y-t[1],2)+Math.pow(e.z-t[2],2)),index:i}))).filter((t=>t.distance<e)).sort(((t,e)=>t.distance-e.distance));return n.length>0?n[0].node:null}updateConnectome(t){const e=[],i=[],n=[];let a=ve.colormap(this.nodeColormap,this.colormapInvert),s=ve.colormap(this.nodeColormapNegative,this.colormapInvert),o="nodeColormapNegative"in this;void 0===this.nodeMinColor&&(this.nodeMinColor=NaN),void 0===this.nodeMaxColor&&(this.nodeMaxColor=NaN),void 0===this.edgeMin&&(this.edgeMin=NaN),void 0===this.edgeMax&&(this.edgeMax=NaN);let l=this.nodeMinColor,c=this.nodeMaxColor;if(!isFinite(l)||!isFinite(l)){const t=this.nodes;l=t[0].colorValue,c=t[0].colorValue;for(let e=0;e<t.length;e++)l=Math.min(l,t[e].colorValue),c=Math.max(c,t[e].colorValue)}const h=this.nodes,d=h.length;for(let p=0;p<d;p++){const t=h[p].sizeValue*this.nodeScale;if(t<=0)continue;let d=h[p].colorValue,u=!1;if(o&&d<0&&(u=!0,d=-d),l<c){if(d<l)continue;d=(d-l)/(c-l)}else d=1;d=4*Math.round(Math.max(Math.min(255,255*d)));let m=[a[d],a[d+1],a[d+2],255];u&&(m=[s[d],s[d+1],s[d+2],255]);const f=r.fA(h[p].x,h[p].y,h[p].z);K.makeColoredSphere(i,e,n,t,f,m)}a=ve.colormap(this.edgeColormap,this.colormapInvert),s=ve.colormap(this.edgeColormapNegative,this.colormapInvert),o="edgeColormapNegative"in this;const u=this.edges;if(void 0!==u&&u.length>0){if(l=this.edgeMin,c=this.edgeMax,!isFinite(l)||!isFinite(l)){l=u[0].colorValue,c=u[0].colorValue;for(let t=0;t<u.length;t++)l=Math.min(l,u[t].colorValue),c=Math.max(c,u[t].colorValue)}for(const t of u){let d=t.colorValue;const u=o&&d<0;u&&(d=-d);const m=d*this.edgeScale;if(m<=0)continue;if(l<c){if(d<l)continue;d=(d-l)/(c-l)}else d=1;d=4*Math.round(Math.max(Math.min(255,255*d)));let f=[a[d],a[d+1],a[d+2],255];u&&(f=[s[d],s[d+1],s[d+2],255]);const g=r.fA(h[t.first].x,h[t.first].y,h[t.first].z),A=r.fA(h[t.second].x,h[t.second].y,h[t.second].z);K.makeColoredCylinder(i,e,n,g,A,m,f)}}const m=new Float32Array(i),f=new Uint32Array(e),g=xe.getExtents(m);this.furthestVertexFromOrigin=g.mxDx,this.extentsMin=g.extentsMin,this.extentsMax=g.extentsMax;const A=this.generatePosNormClr(m,f,new Uint8Array(n));t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer),t.bufferData(t.ELEMENT_ARRAY_BUFFER,Uint32Array.from(f),t.STATIC_DRAW),t.bindBuffer(t.ARRAY_BUFFER,this.vertexBuffer),t.bufferData(t.ARRAY_BUFFER,Float32Array.from(A),t.STATIC_DRAW),this.indexCount=e.length}updateMesh(t){this.updateConnectome(t),this.updateLabels()}json(){const t={};for(const e in this)(e in hr||"nodes"===e||"edges"===e)&&(t[e]=this[e]);return t}static async loadConnectomeFromUrl(e,i){const n=await fetch(i),r=await n.json();return new t(e,r)}};var ur={};b(ur,{MESH_EXTENSIONS:()=>mr,getFileExt:()=>fr,getLoader:()=>vr,getMediaByUrl:()=>Ar,handleDragEnter:()=>Cr,handleDragOver:()=>Mr,isDicomExtension:()=>xr,isMeshExt:()=>gr,readDirectory:()=>yr,readFileAsDataURL:()=>br,registerLoader:()=>pr,traverseFileTree:()=>wr});var mr=["ASC","BYU","DFS","FSM","PIAL","ORIG","INFLATED","SMOOTHWM","SPHERE","WHITE","G","GEO","GII","ICO","MZ3","NV","OBJ","OFF","PLY","SRF","STL","TCK","TRACT","TRI","TRK","TT","TRX","VTK","WRL","X3D","JCON","JSON"];function fr(t,e){let i;void 0===e&&(e=!0),"object"==typeof t?(i=t.fullname,e=t.upperCase??!0):i=t,Q.debug("fullname: ",i);const n=/(?:\.([^.]+))?$/;let r=n.exec(i)[1];if(r=r.toUpperCase(),"GZ"===r)r=n.exec(i.slice(0,-3))[1],r=r.toUpperCase();else if("CBOR"===r){const t=r;r=n.exec(i.slice(0,-5))[1],r=r.toUpperCase(),r=`${r}.${t}`}return e?r:r.toLowerCase()}function gr(t){const e=fr(t);return Q.debug("checking mesh ext:",e),mr.includes(e)}function Ar(t,e){return[...e.entries()].filter((e=>e[1]===t)).map((t=>t[0])).pop()}function pr(t){const{loaders:e,loader:i,fileExt:n,toExt:r}=t;return{...e,[n.toUpperCase()]:{loader:i,toExt:r}}}function vr(t,e){return t[e.toUpperCase()]}function xr(t){return"DCM"===t.toUpperCase()}async function wr(t,e,i){return void 0===e&&(e=""),new Promise((n=>{if(t.isFile)t.file((t=>{t.fullPath=e+t.name,t._webkitRelativePath=e+t.name,i.push(t),n(i)}));else if(t.isDirectory){const r=t.createReader(),a=()=>{r.readEntries((r=>{if(r.length>0){const n=r.map((n=>wr(n,e+t.name+"/",i)));Promise.all(n).then(a).catch((t=>{throw t}))}else n(i)}))};a()}}))}function yr(t){const e=t.createReader();let i=[];const n=()=>{e.readEntries((t=>{t.length?(i=i.concat(t),n()):(async t=>{const e=[],i=async t=>new Promise(((e,i)=>t.file(e,i)));for(let n=0;n<t.length;n++)e.push(await i(t[n]));return e})(i).then((async()=>{})).catch((t=>{throw t}))}))};return n(),i}function br(t){return new Promise(((e,i)=>{t.file((t=>{const n=new FileReader;n.onload=()=>e(n.result),n.onerror=()=>i(new Error("Failed to read file as data URL")),n.readAsDataURL(t)}),(t=>i(t)))}))}function Cr(t){t.stopPropagation(),t.preventDefault()}function Mr(t){t.stopPropagation(),t.preventDefault()}function Dr(t,e,i,n){let r=i.slice(),a=n.slice();return 1===t&&(r=e.slice()),2===t&&(r=e.slice(),a=i.slice()),{linesH:r,linesV:a}}var Tr=33990;function Ir(t,e){const i=-e*(Math.PI/180),n=(t-90)%360*(Math.PI/180),r=[Math.cos(i)*Math.cos(n),Math.cos(i)*Math.sin(n),Math.sin(i)],a=Math.sqrt(r[0]*r[0]+r[1]*r[1]+r[2]*r[2]);return a<=0||(r[0]/=a,r[1]/=a,r[2]/=a),r}function Sr(t){const{azimuth:e,elevation:i,obliqueRAS:n}=t,r=a.vt();if(r[0]=-1,a.eL(r,r,gn(270-i)),a.Qr(r,r,gn(e-180)),n){const t=a.o8(n);a.lw(r,r,t)}return r}function Er(t){const{azimuth:e,elevation:i,obliqueRAS:n}=t,a=r.fA(0,0,-1),s=Sr({azimuth:e,elevation:i,obliqueRAS:n}),o=u.fA(1,0,0,0,-1,0,0,0,-1),l=r.vt();r.ei(l,a,o);const c=u.vt();u.z0(c,s);const h=u.vt();if(!u.B8(h,c))return r.fA(0,0,1);const d=r.vt();r.ei(d,l,h),r.S8(d,d);const m=5e-5;for(let r=0;r<3;r++)Math.abs(d[r])<m&&(d[r]=Math.sign(d[r])*m||m);return d}function Fr(t){const{gl:e,hdr:i,genericVAO:n,unusedVAO:r,volumeTexture:a,paqdTexture:s,gradientOrder:o,blurShader:l,gradientPrePassShader:c,sobelFirstOrderShader:h,sobelSecondOrderShader:d,rgbaTex:u}=t;let{gradientTexture:m}=t;e.bindVertexArray(n);const f=e.createFramebuffer();e.bindFramebuffer(e.FRAMEBUFFER,f),e.viewport(0,0,i.dims[1],i.dims[2]),e.disable(e.BLEND);const g=u(null,33992,i.dims,!0),A=2===o?c:l;A.use(e),e.activeTexture(33984),e.bindTexture(e.TEXTURE_3D,a),e.texParameteri(e.TEXTURE_3D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_3D,e.TEXTURE_MAG_FILTER,e.LINEAR);e.uniform1i(A.uniforms.intensityVol,0),e.uniform1f(A.uniforms.dX,.7/i.dims[1]),e.uniform1f(A.uniforms.dY,.7/i.dims[2]),e.uniform1f(A.uniforms.dZ,.7/i.dims[3]),A.uniforms.kernelRadius&&e.uniform1i(A.uniforms.kernelRadius,0),A.uniforms.binarize&&e.uniform1i(A.uniforms.binarize,0);for(let x=0;x<i.dims[3];x++){const t=1/i.dims[3]*(x+.5);e.uniform1f(A.uniforms.coordZ,t),e.framebufferTextureLayer(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,g,0,x);const n=e.checkFramebufferStatus(e.FRAMEBUFFER);n!==e.FRAMEBUFFER_COMPLETE&&Q.error("blur shader: ",n),e.drawArrays(e.TRIANGLE_STRIP,0,4)}const p=2===o?d:h;p.use(e),e.activeTexture(33992),e.bindTexture(e.TEXTURE_3D,g),e.texParameteri(e.TEXTURE_3D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_3D,e.TEXTURE_MAG_FILTER,e.LINEAR),e.uniform1i(p.uniforms.intensityVol,8);const v=.7;e.uniform1f(p.uniforms.dX,v/i.dims[1]),e.uniform1f(p.uniforms.dY,v/i.dims[2]),e.uniform1f(p.uniforms.dZ,v/i.dims[3]),2===o&&(e.uniform1f(p.uniforms.dX2,1.4/i.dims[1]),e.uniform1f(p.uniforms.dY2,1.4/i.dims[2]),e.uniform1f(p.uniforms.dZ2,1.4/i.dims[3])),e.uniform1f(p.uniforms.coordZ,.5),null!==m&&e.deleteTexture(m),m=u(m,Tr,i.dims);for(let x=0;x<i.dims[3];x++){const t=1/i.dims[3]*(x+.5);e.uniform1f(p.uniforms.coordZ,t),e.framebufferTextureLayer(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,m,0,x);const n=e.checkFramebufferStatus(e.FRAMEBUFFER);n!==e.FRAMEBUFFER_COMPLETE&&Q.error("sobel shader: ",n),e.drawArrays(e.TRIANGLE_STRIP,0,4)}return e.deleteFramebuffer(f),e.deleteTexture(g),e.bindFramebuffer(e.FRAMEBUFFER,null),e.activeTexture(33992),e.bindTexture(e.TEXTURE_3D,s),e.bindVertexArray(r),m}function Br(t){const{visible:e,opacity:i,indexCount:n}=t;return e&&i>0&&n>=3}function Vr(t){const{meshShaderIndex:e,meshShaders:i,pickingMeshShader:n,mouseDepthPicker:r}=t;return r?n:i[e]?.shader??null}function Ur(t){const{meshOpacity:e,globalAlpha:i}=t;return e*i}function Rr(t){const{offsetPt0:e,fiberSides:i,fiberRadius:n}=t;return!!e&&(i<3||n<=0)}function Pr(t){const{modelMtx:e,crosshairMM:i,is2D:n}=t,r=1e9,a=[i[0],i[1],i[2]];return n&&(Math.abs(e[2])+Math.abs(e[4])+Math.abs(e[9])>=2.95&&(a[1]=r,a[2]=r),Math.abs(e[0])+Math.abs(e[6])+Math.abs(e[9])>=2.95&&(a[0]=r,a[2]=r),Math.abs(e[0])+Math.abs(e[5])+Math.abs(e[10])>=2.95&&(a[0]=r,a[1]=r)),a}function Nr(t){let e=Number(t);return Number.isFinite(e)||(e=1),e}function Lr(t){const{gl:e,shader:i,modelMtx:n,sliceMM:r,meshThickness:a}=t;e.disable(e.DEPTH_TEST),e.disable(e.CULL_FACE),e.uniformMatrix4fv(i.uniforms.modelMtx,!1,n),e.uniform4fv(i.uniforms.sliceMM,[r[0],r[1],r[2],a])}function kr(t){const{gl:e,shader:i,mvpMtx:n,normMtx:r,opacity:a}=t;e.uniformMatrix4fv(i.uniforms.mvpMtx,!1,n),e.uniformMatrix4fv(i.uniforms.normMtx,!1,r),e.uniform1f(i.uniforms.opacity,a)}function Or(t){const{gl:e,matCapTexture:i}=t;e.activeTexture(33989),e.bindTexture(e.TEXTURE_2D,i)}function zr(t){const{gl:e,mesh:i,unusedVAO:n}=t;e.bindVertexArray(i.vao),e.drawElements(e.TRIANGLES,i.indexCount,e.UNSIGNED_INT,0),e.bindVertexArray(n)}function Yr(t){const{gl:e,mesh:i,unusedVAO:n}=t;e.bindVertexArray(i.vaoFiber),e.drawElements(e.LINE_STRIP,i.indexCount,e.UNSIGNED_INT,0),e.bindVertexArray(n)}function Gr(t,e){const i=e||t.target;if(!i)return;const n=i;if("function"!=typeof n.getBoundingClientRect)return;const r=n.getBoundingClientRect();return{x:t.clientX-r.left,y:t.clientY-r.top}}function Wr(t){const{canvas:e,isResizeCanvas:i,forceDevicePixelRatio:n}=t;if(!i)return{dpr:1,width:e.width,height:e.height,shouldDraw:!0};const r=function(t){const{forceDevicePixelRatio:e}=t;return 0===e?window.devicePixelRatio||1:e<0?1:e}({forceDevicePixelRatio:n});let a,s;const o=e.parentElement;return o&&"width"in o?(a=o.width*r,s=o.height*r):(a=e.offsetWidth*r,s=e.offsetHeight*r),{dpr:r,width:a,height:s,shouldDraw:!0}}function Xr(t){t.style.width="100%",t.style.height="100%",t.style.display="block"}var Kr={};b(Kr,{CENTER_MOUSE_BUTTON:()=>Qr,LEFT_MOUSE_BUTTON:()=>Hr,RIGHT_MOUSE_BUTTON:()=>qr,calculateMouseDownPosition:()=>Jr,calculateMouseMovePosition:()=>_r,calculateWindowingValues:()=>ra,createOffCanvasPosition:()=>na,createResetButtonState:()=>ta,determineButtonState:()=>jr,getMouseButtonDragMode:()=>Zr,getNextAngleState:()=>aa,hasDragMoved:()=>ea,initializeDragState:()=>$r,isAngleMeasurementInProgress:()=>sa,isFunction:()=>la,isOffCanvas:()=>ia,shouldTrackDrag:()=>
1oa});var Hr=0,Qr=1,qr=2;function Zr(t){const{button:e,shiftKey:i,ctrlKey:n,mouseConfig:r,dragMode:a,dragModePrimary:s}=t;return e===Hr?r?.leftButton?i&&void 0!==r.leftButton.withShift?r.leftButton.withShift:n&&void 0!==r.leftButton.withCtrl?r.leftButton.withCtrl:r.leftButton.primary:n?8:s:e===qr?void 0!==r?.rightButton?r.rightButton:a:e===Qr&&void 0!==r?.centerButton?r.centerButton:a}function jr(t){const{button:e,shiftKey:i}=t;return e===Hr&&i?{mouseButtonCenterDown:!0}:e===Hr?{mouseButtonLeftDown:!0}:e===qr?{mouseButtonRightDown:!0}:e===Qr?{mouseButtonCenterDown:!0}:{}}function Jr(t){const{x:e,y:i,dpr:n}=t,r=e*n,a=i*n;return{scaledX:r,scaledY:a,mousePos:[r,a]}}function _r(t){const{x:e,y:i,dpr:n,currentMousePos:r}=t,a=e*n,s=i*n;return{scaledX:a,scaledY:s,dx:(a-r[0])/n,dy:(s-r[1])/n,mousePos:[a,s]}}function $r(t){const{posX:e,posY:i,pan2Dxyzmm:r,clipPlaneDepthAziElev:a}=t;return{dragStart:[e,i],pan2DxyzmmAtMouseDown:n.o8(r),isDragging:!0,dragClipPlaneStartDepthAziElev:[...a]}}function ta(){return{mousedown:!1,mouseButtonLeftDown:!1,mouseButtonCenterDown:!1,mouseButtonRightDown:!1}}function ea(t,e){return t[0]!==e[0]||t[1]!==e[1]}function ia(t){return t[0]<0||t[1]<0}function na(){return[-1,-1]}function ra(t){const{currentX:e,currentY:i,windowX:n,windowY:r,calMin:a,calMax:s,robustMin:o,robustMax:l,windowRangeMultiplier:c}=t,h=(l-o)*c/100;let d=a,u=s;return i<r?(d=a-h,u=s-h):i>r&&(d=a+h,u=s+h),e>n?(d-=h,u+=h):e<n&&(d+=h,u-=h),{newCalMin:d,newCalMax:u,newWindowX:e,newWindowY:i}}function aa(t){const{currentState:e,dragMode:i}=t;if(7!==i)return e;switch(e){case"none":case"complete":return"drawing_first_line";case"drawing_first_line":return"drawing_second_line";case"drawing_second_line":return"complete";default:return"none"}}function sa(t){return"drawing_first_line"===t||"drawing_second_line"===t}function oa(t){return 8!==t&&9!==t&&0!==t}function la(t){return Object.prototype.toString.call(t).indexOf("Function")>-1}function ca(t){const{touch:e,canvasRect:i}=t;return{x:e.clientX-i.left,y:e.clientY-i.top}}function ha(t,e){return t&&e<2}var da=[[2,0,0],[0,270,0],[0,90,0],[0,0,0],[0,180,0],[0,0,-90],[0,0,90]];function ua(t,e){return t===e}var ma={none:0,contrast:1,measurement:2,angle:7,pan:3,slicer3D:4,callbackOnly:5,roiSelection:6,crosshair:8,windowing:9};function fa(t,e,i){return[t*i,e*i]}function ga(t){return mr.includes(t)?"mesh":"NVD"===t?"document":"volume"}function Aa(t,e){const i=function(t,e){const i=t.name.lastIndexOf("HEAD");if(-1===i)return null;const n=t.name.substring(0,i);for(const r of Array.from(e)){const t=r.webkitGetAsEntry();if(!t)continue;const e=t.name.lastIndexOf("BRIK");if(-1!==e&&n===t.name.substring(0,e))return t}return null}(t,e);return i||function(t,e){const i=t.name.toUpperCase().lastIndexOf("HDR");if(-1===i)return null;const n=t.name.substring(0,i);for(const r of Array.from(e)){const t=r.webkitGetAsEntry();if(!t)continue;const e=t.name.toUpperCase().lastIndexOf("IMG");if(-1===e)continue;const i=t.name.substring(0,e);if(n.toUpperCase()===i.toUpperCase())return t}return null}(t,e)}function pa(t){return new Promise(((e,i)=>{t.file(e,i)}))}function va(t){const{x:e,y:i,screenSlices:n}=t;for(let r=0;r<n.length;r++){const t=n[r].leftTopWidthHeight;if(e>t[0]&&i>t[1]&&e<t[0]+t[2]&&i<t[1]+t[3])return r}return-1}function xa(t){const{sliceType:e,crosshairPos:i}=t;return 0===e?i[2]:1===e?i[1]:2===e?i[0]:0}var wa=[0,0,0,2],ya=[2,0,0];function ba(t){const{depth:e,azimuth:i,elevation:n}=t,r=Ir(i+180,n);return[r[0],r[1],r[2],e]}function Ca(t){const{depth:e,azimuth:i,elevation:n}=t,r=Ir(i,n);return[r[0],r[1],r[2],-e]}function Ma(t){const{index:e,depthAzimuthElevation:i}=t,{clipPlanes:n,clipPlaneDepthAziElevs:r}=function(t){const{index:e}=t,i=t.clipPlanes?[...t.clipPlanes]:[],n=t.clipPlaneDepthAziElevs?[...t.clipPlaneDepthAziElevs]:[];for(;i.length<=e;)i.push([...wa]);for(;n.length<=e;)n.push([...ya]);return{clipPlanes:i,clipPlaneDepthAziElevs:n}}({clipPlanes:t.clipPlanes,clipPlaneDepthAziElevs:t.clipPlaneDepthAziElevs,index:e}),a=ba({depth:i[0],azimuth:i[1],elevation:i[2]});return n[e]=a,r[e]=[...i],{clipPlanes:n,clipPlaneDepthAziElevs:r,clipPlane:a}}function Da(t,e){const i=new Uint8Array(t.buffer),n=new Int8Array(i.buffer);let r=0;const a=new Uint8Array(e);let s=0;for(;r<i.length;){const t=n[r];if(r++,t<0){const e=n[r];r++;for(let i=0;i<1-t;i++)a[s]=e,s++}else for(let e=0;e<t+1;e++)a[s]=n[r],r++,s++}return a}
1function Ta(t,e,i,n){const{dimX:r,dimY:a,dimZ:s}=n;let o;if(0===e){o=new Float32Array(r*a);const e=t*r*a;for(let t=0;t<r*a;t++)o[t]=i[e+t]}else if(1===e){o=new Float32Array(r*s);for(let e=0;e<s;e++)for(let n=0;n<r;n++){const s=n+t*r+e*r*a;o[n+e*r]=i[s]}}else{if(2!==e)throw new Error("Invalid slice type");o=new Float32Array(a*s);for(let e=0;e<s;e++)for(let n=0;n<a;n++){const s=t+n*r+e*r*a;o[n+e*a]=i[s]}}return o}function Ia(t,e,i,n,r){const{dimX:a,dimY:s,dimZ:o}=n;let l;if(0===e){l=new Float32Array(a*s);const e=t*a*s;for(let t=0;t<a*s;t++)l[t]=i[e+t]/r}else if(1===e){l=new Float32Array(a*o);for(let e=0;e<o;e++)for(let n=0;n<a;n++){const o=n+t*a+e*a*s;l[n+e*a]=i[o]/r}}else{if(2!==e)throw new Error("Invalid slice type");l=new Float32Array(s*o);for(let e=0;e<o;e++)for(let n=0;n<s;n++){const o=t+n*a+e*a*s;l[n+e*s]=i[o]/r}}return l}function Sa(t,e,i,n,r,a,s){const{dimX:o,dimY:l,dimZ:c}=r;if(0===i){const i=e*o*l;for(let e=0;e<t.length;e++)t[e]>=a&&(n[i+e]=s)}else if(1===i)for(let h=0;h<c;h++)for(let i=0;i<o;i++){const r=i+e*o+h*o*l;t[i+h*o]>=a&&(n[r]=s)}else{if(2!==i)throw new Error("Invalid slice type");for(let i=0;i<c;i++)for(let r=0;r<l;r++){const c=e+r*o+i*o*l;t[r+i*l]>=a&&(n[c]=s)}}}function Ea(t,e,i){if(e<3||i<3)return;const n=new Float32Array(t.length);for(let r=0;r<i;r++)for(let i=0;i<e;i++){const a=i+r*e;n[a]=0===i||i===e-1?t[a]:.25*(t[a-1]+2*t[a]+t[a+1])}for(let r=0;r<i;r++)for(let a=0;a<e;a++){const s=a+r*e;t[s]=0===r||r===i-1?n[s]:.25*(n[s-e]+2*n[s]+n[s+e])}}function Fa(t,e,i,n){const r=Math.abs(i-t),a=Math.abs(i-e),s=Math.exp(-r*r/(2*n*n)),o=s+Math.exp(-a*a/(2*n*n));return o<1e-6?.5:s/o}function Ba(t,e,i,n,r,a){const s=(i-n)/(r-n),o=1-s;for(let l=0;l<t.length;l++)a[l]=t[l]*o+e[l]*s}function Va(t,e,i,n,r,a,s,o,l,c){const h=(i-n)/(r-n),d=1-h;for(let u=0;u<t.length;u++)if(t[u]>0||e[u]>0){const i=Fa(o[u],l[u],c[u],s.intensitySigma),n=s.intensityWeight,r=n*i+(1-n)*d,h=1-r;a[u]=t[u]*r+e[u]*h}else a[u]=t[u]*d+e[u]*h}function Ua(t){const{drawBitmap:e,drawUndoBitmaps:i,currentDrawUndoBitmap:n,maxDrawUndoBitmaps:r,drawFillOverwrites:a}=t;if(!e||e.length<1)return Q.debug("addUndoBitmap error: No drawing open"),{drawBitmap:e,drawUndoBitmaps:i,currentDrawUndoBitmap:n,needsRefresh:!1};const s=[...i];let o=e,l=!1;if(!a&&s.length>0){const t=e.length,i=Da(s[n],t);o=new Uint8Array(e);for(let e=0;e<t;e++)i[e]>0&&(o[e]=i[e]);l=!0}let c=n+1;return c>=r&&(c=0),s[c]=function(t){const e=t.length;let i=0;const n=new Uint8Array(e+Math.ceil(.01*e)),r=new Int8Array(n.buffer);let a=0;for(;i<e;){let s=t[i];i++;let o=1;for(;o<129&&i<e&&t[i]===s;)i++,o++;if(o>1)r[a]=1-o,a++,n[a]=s,a++;else{for(;i<e&&!(o>127)&&!(i+2<e&&s!==t[i]&&t[i+2]===t[i]&&t[i+1]===t[i]);)s=t[i],i++,o++;n[a]=o-1,a++;for(let e=0;e<o;e++)n[a]=t[i-o+e],a++}}return Q.debug("PackBits "+e+" -> "+a+" bytes (x"+e/a+")"),n.slice(0,a)}(o),{drawBitmap:o,drawUndoBitmaps:s,currentDrawUndoBitmap:c,needsRefresh:l}}function Ra(t,e,i){const n=new Array(t);if(i)for(let r=0;r<t;r++)n[r]=(t-1-r)*e;else for(let r=0;r<t;r++)n[r]=r*e;return n}function Pa(t){return!t||t.length<4?0:t[1]*t[2]*t[3]}function Na(t){return new Uint8Array(t)}function La(t,e,i,n,r){return t+e*n+i*n*r}function ka(t,e){return Math.min(Math.max(t,0),e-1)}function Oa(t){const{x:e,y:i,z:n,penValue:r,drawBitmap:a,dims:s,penSize:o,penAxCorSag:l}=t,c=s[1],h=s[2],d=s[3],u=ka(e,c),m=ka(i,h),f=ka(n,d);if(a[La(u,m,f,c,h)]=r,o>1){const t=Math.floor(o/2),e=0===l,i=1===l,n=2===l;for(let s=-t;s<=t;s++)for(let o=-t;o<=t;o++){let t,l,g;if(e)t=ka(u+s,c),l=ka(m+o,h),g=f;else if(i)t=ka(u+s,c),l=m,g=ka(f+o,d);else{if(!n)continue;t=u,l=ka(m+o,h),g=ka(f+s,d)}a[La(t,l,g,c,h)]=r}}}function za(t){const{img2D:e,dims2D:i,minPt:n,maxPt:r}=t,a=i[0],[s,o]=n,[l,c]=r,h=new Int32Array(2*(4*(l-s+c-o+2)));let d,u=0,m=0;function f(t,i){if(t<s||t>l||i<o||i>c)return;const n=t+i*a;0===e[n]&&(e[n]=2,h[m]=t,h[m+1]=i,m=(m+2)%h.length)}function g(){if(u===m)return null;const t=h[u],e=h[u+1];return u=(u+2)%h.length,[t,e]}for(let A=s;A<=l;A++)f(A,o),f(A,c);for(let A=o+1;A<=c-1;A++)f(s,A),f(l,A);for(;null!==(d=g());){const[t,e]=d;f(t-1,e),f(t+1,e),f(t,e-1),f(t,e+1)}}function Ya(t,e,i,n,r){const a=Math.abs(i[0]-n[0]),s=Math.abs(i[1]-n[1]);t[i[0]+i[1]*e[0]]=r,t[n[0]+n[1]*e[0]]=r;const o=n[0]>i[0]?1:-1,l=n[1]>i[1]?1:-1;let c=i[0],h=i[1];const d=n[0],u=n[1];if(a>=s){let i=2*s-a;for(;c!==d;)c+=o,i>=0&&(h+=l,i-=2*a),i+=2*s,t[c+h*e[0]]=r}else{let i=2*a-s;for(;h!==u;)h+=l,i>=0&&(c+=o,i-=2*s),i+=2*a,t[c+h*e[0]]=r}}function Ga(t,e){return[Math.min(Math.max(t[0],0),e[0]-1),Math.min(Math.max(t[1],0),e[1]-1)]}function Wa(t){const{ptA:e,ptB:i,dims:n}=t,r=n[1],a=n[2],s=n[3];return{x1:Math.min(Math.max(Math.min(e[0],i[0]),0),r-1),y1:Math.min(Math.max(Math.min(e[1],i[1]),0),a-1),z1:Math.min(Math.max(Math.min(e[2],i[2]),0),s-1),x2:Math.min(Math.max(Math.max(e[0],i[0]),0),r-1),y2:Math.min(Math.max(Math.max(e[1],i[1]),0),a-1),z2:Math.min(Math.max(Math.max(e[2],i[2]),0),s-1)}}function Xa(t,e,i,n){const{centerX:r,centerY:a,centerZ:s,radiusX:o,radiusY:l,radiusZ:c}=n,h=(t-r)/(o+.5),d=(e-a)/(l+.5),u=(i-s)/(c+.5);
1return h*h+d*d+u*u<=1}function Ka(t){const{ptA:e,ptB:i,penValue:n,drawBitmap:r,dims:a,penSize:s,penAxCorSag:o}=t,l=Wa({ptA:e,ptB:i,dims:a}),{x1:c,y1:h,z1:d,x2:u,y2:m,z2:f}=l,g=function(t){const{x1:e,y1:i,z1:n,x2:r,y2:a,z2:s}=t;return{centerX:(e+r)/2,centerY:(i+a)/2,centerZ:(n+s)/2,radiusX:Math.abs(r-e)/2,radiusY:Math.abs(a-i)/2,radiusZ:Math.abs(s-n)/2}}(l),A={x:0,y:0,z:0,penValue:n,drawBitmap:r,dims:a,penSize:s,penAxCorSag:o};for(let p=d;p<=f;p++)for(let t=h;t<=m;t++)for(let e=c;e<=u;e++)Xa(e,t,p,g)&&(A.x=e,A.y=t,A.z=p,Oa(A))}function Ha(t){const e=t[0],i=e*t[1],n=i*t[2];return{xyz2vx:t=>function(t,e,i){return t[0]+t[1]*e+t[2]*i}(t,e,i),vx2xyz:t=>function(t,e,i){const n=Math.floor(t/i),r=Math.floor((t-n*i)/e);return[Math.floor(t%e),r,n]}(t,e,i),nx:e,nxy:i,nxyz:n}}var Qa={face:[[0,0,-1],[0,0,1],[0,-1,0],[0,1,0],[-1,0,0],[1,0,0]],edge:[[-1,-1,0],[1,-1,0],[-1,1,0],[1,1,0],[0,-1,-1],[0,1,-1],[-1,0,-1],[1,0,-1],[0,-1,1],[0,1,1],[-1,0,1],[1,0,1]],corner:[[-1,-1,-1],[1,-1,-1],[-1,1,-1],[1,1,-1],[-1,-1,1],[1,-1,1],[-1,1,1],[1,1,1]]};function qa(t,e,i,n){return isFinite(i)&&isFinite(n)?[i,n]:t===Number.POSITIVE_INFINITY?[e,1/0]:t===Number.NEGATIVE_INFINITY?[-1/0,e]:[-1/0,1/0]}function Za(t,e,i,n){return i*n[0]*n[1]+e*n[0]+t}function ja(t,e,i){let n=0;const r=new Uint32Array(i+5).fill(0);let a=2147483647;for(let s=0;s<i;s++){let i=e[s];for(n=0;t[i-1]!==i;)if(i=t[i-1],n++,n>100){Q.info("\nOoh no!!");break}r[s]=i,a=Math.min(a,i)}for(let s=0;s<i;s++)t[r[s]-1]=a}function Ja(t,e,i,n,r,a,s,o){const l=new Uint32Array(27);let c=0;if(!r)return 0;const h=t[Za(i,n,r,a)];if(s>=6){const s=Za(i,n,r-1,a);h===t[s]&&(l[c++]=e[s])}if(s>=18){if(i){const s=Za(i-1,n,r-1,a);h===t[s]&&(l[c++]=e[s])}if(n){const s=Za(i,n-1,r-1,a);h===t[s]&&(l[c++]=e[s])}if(i<a[0]-1){const s=Za(i+1,n,r-1,a);h===t[s]&&(l[c++]=e[s])}if(n<a[1]-1){const s=Za(i,n+1,r-1,a);h===t[s]&&(l[c++]=e[s])}}if(26===s){if(i&&n){const s=Za(i-1,n-1,r-1,a);h===t[s]&&(l[c++]=e[s])}if(i<a[0]-1&&n){const s=Za(i+1,n-1,r-1,a);h===t[s]&&(l[c++]=e[s])}if(i&&n<a[1]-1){const s=Za(i-1,n+1,r-1,a);h===t[s]&&(l[c++]=e[s])}if(i<a[0]-1&&n<a[1]-1){const s=Za(i+1,n+1,r-1,a);h===t[s]&&(l[c++]=e[s])}}return c?(ja(o,l,c),l[0]):0}function _a(t,e,i){let n=1;let r=8192,a=new Uint32Array(r).fill(0);const s=new Uint32Array(e[0]*e[1]*e[2]).fill(0),o=new Uint32Array(27);for(let l=0;l<e[2];l++)for(let c=0;c<e[1];c++)for(let h=0;h<e[0];h++){let d=0;const u=t[Za(h,c,l,e)];if(0!==u){if(o[0]=Ja(t,s,h,c,l,e,i,a),o[0]&&(d+=1),i>=6){if(h){const i=Za(h-1,c,l,e);u===t[i]&&(o[d++]=s[i])}if(c){const i=Za(h,c-1,l,e);u===t[i]&&(o[d++]=s[i])}}if(i>=18){if(c&&h){const i=Za(h-1,c-1,l,e);u===t[i]&&(o[d++]=s[i])}if(c&&h<e[0]-1){const i=Za(h+1,c-1,l,e);u===t[i]&&(o[d++]=s[i])}}if(d)s[Za(h,c,l,e)]=o[0],ja(a,o,d);else{if(s[Za(h,c,l,e)]=n,n>=r){r+=8192;const t=new Uint32Array(r);t.set(a),a=t}a[n-1]=n,n++}}}for(let l=0;l<n-1;l++){let t=l;for(;a[t]!==t+1;)t=a[t]-1;a[l]=t+1}return{labelCount:n-1,translationTable:a,initialLabels:s}}function $a(t,e,i,n){const r=e[0]*e[1]*e[2];let a=0;const s=new Uint32Array(r).fill(0);for(let c=0;c<n;c++)a=Math.max(a,i[c]);const o=new Uint32Array(a).fill(0);let l=0;for(let c=0;c<r;c++)t[c]&&(o[i[t[c]-1]-1]||(l+=1,o[i[t[c]-1]-1]=l),s[c]=o[i[t[c]-1]-1]);return{clusterCount:l,labels:s}}function ts(t,e,i){const n=t.length,r=new Uint32Array(e+1).fill(0),a=new Uint32Array(e+1).fill(0);for(let l=0;l<n;l++){const e=t[l],n=i[l];r[n]=e,a[n]++}let s=0;for(let l=0;l<e+1;l++){const t=r[l];s=Math.max(s,t);for(let i=0;i<e+1;i++)i!==l&&t===r[i]&&(a[l]<a[i]||a[l]===a[i]&&l<i)&&(r[l]=0)}const o=new Uint32Array(n).fill(0);for(let l=0;l<n;l++)o[l]=r[i[l]];return{maxValue:s,voxels:o}}function es(t){const{img:e,dims:i,global_min:n,global_max:r,datatypeCode:a,scl_slope:s,scl_inter:o,cal_min:l,cal_max:c,dst_min:h=0,dst_max:d=255,f_low:u=0,f_high:m=.999}=t;let f=n,g=r;if(2===a)return[f,1];if((!isFinite(u)||!isFinite(m))&&isFinite(l)&&isFinite(c)&&c>l){f=l,g=c;const t=(d-h)/(g-f);return Q.info(" Robust Rescale:  min: "+f+"  max: "+g+" scale: "+t),[f,t]}const A=i[1]*i[2]*i[3];let p=e;if(1!==s||0!==o){const t=new Float32Array(A);for(let i=0;i<A;i++)t[i]=e[i]*s+o;p=t}if(f<0&&Q.warn("WARNING: Input image has value(s) below 0.0 !"),Q.info(" Input:    min: "+f+"  max: "+g),0===u&&1===m)return[f,1];let v=0;for(let I=0;I<A;I++)Math.abs(p[I])>=1e-15&&v++;const x=1e3,w=(g-f)/x,y=new Array(x).fill(0);for(let I=0;I<A;I++){const t=p[I];let e=Math.floor((t-f)/w);e=Math.min(e,999),y[e]++}const b=new Array(x).fill(0);b[0]=y[0];for(let I=1;I<x;I++)b[I]=b[I-1]+y[I];let C=Math.floor(u*A),M=0;for(;M<x&&!(b[M]>=C);)M++;const D=f;
1for(f=M*w+D,C=A-Math.floor((1-m)*v),M=0;M<999&&!(b[M+1]>=C);)M++;g=M*w+D;let T=1;return f!==g&&(T=(d-h)/(g-f)),Q.info(" Rescale:  min: "+f+"  max: "+g+" scale: "+T),[f,T]}function is(t){const{nv:e,maskImages:i,drawBitmap:n,drawingIsMask:r,roiIsMask:a,startVox:s,endVox:o,hdr:l,pixDimsRAS:c}=t,h=new Uint8Array(e);h.fill(1);if(i&&i.length>0){for(const d of i)if(d.length===e)for(let t=0;t<e;t++)(0===d[t]||isNaN(d[t]))&&(h[t]=0)}else if(r&&n)for(let d=0;d<e;d++)(0===n[d]||isNaN(n[d]))&&(h[d]=0);else if(a&&s&&o&&l&&c){const t=function(t,e,i,n,r){const a=new Uint8Array(t);a.fill(0);let s=-1;if(e[0]===i[0])s=0;else if(e[1]===i[1])s=1;else{if(e[2]!==i[2])return console.error("Error: No constant dimension found."),null;s=2}const o=[0,1,2].filter((t=>t!==s)),l=[];l[s]=e[s],l[o[0]]=(e[o[0]]+i[o[0]])/2,l[o[1]]=(e[o[1]]+i[o[1]])/2;const c=Math.abs(i[o[0]]-e[o[0]])/2,h=Math.abs(i[o[1]]-e[o[1]])/2,d=n.dims[1],u=n.dims[2],m=Math.max(0,Math.floor(l[o[0]]-c)),f=Math.min(n.dims[o[0]+1]-1,Math.ceil(l[o[0]]+c)),g=Math.max(0,Math.floor(l[o[1]]-h)),A=Math.min(n.dims[o[1]+1]-1,Math.ceil(l[o[1]]+h)),p=l[s];if(p<0||p>=n.dims[s+1])return console.error("Error: Constant dimension value is out of bounds."),null;for(let w=m;w<=f;w++)for(let t=g;t<=A;t++){const e=[];e[s]=p,e[o[0]]=w,e[o[1]]=t;const i=(e[o[0]]-l[o[0]])/c,n=(e[o[1]]-l[o[1]])/h;if(i*i+n*n<=1){const t=e[0],i=e[1];a[e[2]*d*u+i*d+t]=1}}const v=c*r[o[0]+1],x=h*r[o[1]+1];return{mask:a,area:Math.PI*v*x}}(e,s,o,l,c);return t?{mask:t.mask,area:t.area}:{mask:h,area:null}}return{mask:h,area:null}}var ns,rs=class extends CustomEvent{constructor(t,e){super(t,{detail:e})}},{version:as}={name:"@niivue/niivue",version:"0.69.0",description:"minimal webgl2 nifti image viewer",types:"./build/niivue/index.d.ts",main:"./build/niivue/index.js",type:"module",unpkg:"./dist/index.min.js",module:"./build/niivue/index.js",exports:{".":{import:"./build/niivue/index.js",types:"./build/niivue/index.d.ts"},"./drawing":{import:"./build/drawing/index.js",types:"./build/drawing/index.d.ts"},"./utils":{import:"./build/utils/index.js",types:"./build/utils/index.d.ts"},"./min":{import:"./build/index.min.js"}},scripts:{dev:"vite","build:umd":"vite build --config vite.config.js --base=./ && vite build --config vite.config_inject.js --base=./",build:"tsup --config tsup.config.ts && npm run build:forTests && npm run build:min && npm run build:umd","build:forTests":"tsup --config tsup.config.tests.ts && npm run build:mindemos","build:min":"node bundle.js","build:mindemos":"node bundleForDemos.js",demo:"npm run build:forTests && rm -rf demos/dist && cp -r dist demos/dist && npx http-server demos/ --cors","demo-win":"npm run build && npx http-server demos/",test:"npm run build:forTests && npm run test:unit && jest --maxWorkers=1","test-win":"npm run build-win && jest","test-playwright":'npx playwright test --grep-invert "niivue demo file:"',"test-demos":"npx playwright test playwright/e2e/test.demos.spec.ts",docs:"typedoc && rm -rf ../docs/docs/api && cp -r devdocs ../docs/docs/api","test:unit":"vitest --run --coverage","serve-docs":"npx http-server devdocs",pub:"npm run build && npm publish --access public",lint:"eslint . --ext .ts","lint:ts":"tsc --noEmit","lint:fix":"eslint --fix . --ext .ts","lint:debug":"DEBUG=eslint:cli-engine eslint . --ext .ts","pretest-playwright":"npm run build:forTests && node preplaywrighttest.cjs && tsc --incremental -p playwright/e2e/tsconfig.json","pretest-demos":"npm run build:forTests && node preplaywrighttest.cjs && tsc --incremental -p playwright/e2e/tsconfig.json"},files:["src","build","dist"],repository:{type:"git",url:"git+https://github.com/niivue/niivue.git"},keywords:["niivue","webgl2","nifti","image","viewer"],author:"niivue authors",license:"BSD-2-Clause",bugs:{url:"https://github.com/niivue/niivue/issues"},homepage:"https://github.com/niivue/niivue#readme",dependencies:{"@lukeed/uuid":"^2.0.1","@ungap/structured-clone":"^1.2.0","array-equal":"^1.0.2",fflate:"^0.8.2","gl-matrix":"^3.4.3","nifti-reader-js":"^0.8.0",zarrita:"^0.5.0"},devDependencies:{"@playwright/test":"^1.45.2","@rollup/plugin-commonjs":"^26.0.1","@types/array-equal":"^1.0.2","@types/node":"^20.14.11","@types/ungap__structured-clone":"^1.2.0","@typescript-eslint/eslint-plugin":"^7.16.1","@typescript-eslint/parser":"^7.16.1","@vitest/coverage-v8":"^3.1.3",esbuild:"^0.25.12",eslint:"^8.57.0","eslint-config-prettier":"^9.1.0","eslint-config-standard":"^17.1.0","eslint-plugin-import":"^2.32.0","eslint-plugin-n":"^16.6.2","eslint-plugin-
1prettier":"^5.2.1","eslint-plugin-promise":"^6.6.0","eslint-plugin-tsdoc":"^0.3.0",express:"^4.19.2","happy-dom":"^20.0.11","http-server":"^14.1.1",prettier:"^3.3.3","regenerator-runtime":"^0.14.1",terser:"^5.31.3",tsup:"^8.1.2",typedoc:"^0.28.5","typedoc-docusaurus-theme":"^1.4.0","typedoc-plugin-markdown":"^4.7.0",typescript:"^5.5.3",vite:"^7.2.7",vitest:"^3.1.3"},optionalDependencies:{"@rollup/rollup-linux-x64-gnu":"^4.18.1"}},{MESH_EXTENSIONS:ss}=ur,{LEFT_MOUSE_BUTTON:os,CENTER_MOUSE_BUTTON:ls,RIGHT_MOUSE_BUTTON:cs}=Kr,hs={filename:"",isSaveDrawing:!1,volumeByIndex:0},ds=class extends EventTarget{constructor(t){void 0===t&&(t=ln),super(),C(this,"loaders",{}),C(this,"dicomLoader",null),C(this,"canvas",null),C(this,"_gl",null),C(this,"isBusy",!1),C(this,"needsRefresh",!1),C(this,"colormapTexture",null),C(this,"colormapLists",[]),C(this,"volumeTexture",null),C(this,"gradientTexture",null),C(this,"gradientTextureAmount",0),C(this,"useCustomGradientTexture",!1),C(this,"renderGradientValues",!1),C(this,"drawTexture",null),C(this,"drawSmoothedTexture",null),C(this,"paqdTexture",null),C(this,"drawUndoBitmaps",[]),C(this,"drawLut",ve.makeDrawLut("$itksnap")),C(this,"drawOpacity",.8),C(this,"drawRimOpacity",-1),C(this,"clickToSegmentIsGrowing",!1),C(this,"clickToSegmentGrowingBitmap",null),C(this,"clickToSegmentXY",[0,0]),C(this,"renderDrawAmbientOcclusion",.4),C(this,"colorbarHeight",0),C(this,"drawPenLocation",[NaN,NaN,NaN]),C(this,"drawPenAxCorSag",-1),C(this,"drawFillOverwrites",!0),C(this,"drawPenFillPts",[]),C(this,"drawShapeStartLocation",[NaN,NaN,NaN]),C(this,"drawShapePreviewBitmap",null),C(this,"overlayTexture",null),C(this,"overlayTextureID",null),C(this,"sliceMMShader"),C(this,"slice2DShader"),C(this,"sliceV1Shader"),C(this,"orientCubeShader"),C(this,"orientCubeShaderVAO",null),C(this,"rectShader"),C(this,"rectOutlineShader"),C(this,"renderShader"),C(this,"lineShader"),C(this,"line3DShader"),C(this,"passThroughShader"),C(this,"renderGradientShader"),C(this,"renderGradientValuesShader"),C(this,"renderSliceShader"),C(this,"renderVolumeShader"),C(this,"pickingMeshShader"),C(this,"pickingImageShader"),C(this,"colorbarShader"),C(this,"customSliceShader",null),C(this,"fontShader",null),C(this,"fiberShader"),C(this,"fontTexture",null),C(this,"circleShader"),C(this,"matCapTexture",null),C(this,"bmpShader",null),C(this,"bmpTexture",null),C(this,"thumbnailVisible",!1),C(this,"bmpTextureWH",1),C(this,"growCutShader"),C(this,"orientShaderAtlasU",null),C(this,"orientShaderAtlasI",null),C(this,"orientShaderU",null),C(this,"orientShaderI",null),C(this,"orientShaderF",null),C(this,"orientShaderRGBU",null),C(this,"orientShaderPAQD",null),C(this,"surfaceShader",null),C(this,"blurShader",null),C(this,"gradientPrePassShader",null),C(this,"sobelFirstOrderShader",null),C(this,"sobelSecondOrderShader",null),C(this,"genericVAO",null),C(this,"unusedVAO",null),C(this,"crosshairs3D",null),C(this,"DEFAULT_FONT_GLYPH_SHEET",Ie),C(this,"DEFAULT_FONT_METRICS",Se),C(this,"fontMetrics"),C(this,"fontMets",null),C(this,"fontPx",12),C(this,"legendFontScaling",1),C(this,"backgroundMasksOverlays",0),C(this,"overlayOutlineWidth",0),C(this,"overlayAlphaShader",1),C(this,"position"),C(this,"extentsMin"),C(this,"extentsMax"),C(this,"resizeObserver",null),C(this,"resizeEventListener",null),C(this,"canvasObserver",null),C(this,"syncOpts",{"3d":!1,"2d":!1,zoomPan:!1,cal_min:!1,cal_max:!1,clipPlane:!1,gamma:!1,sliceType:!1,crosshair:!1}),C(this,"readyForSync",!1),C(this,"_skipDragInDraw",!1),C(this,"uiData",{mousedown:!1,touchdown:!1,mouseButtonLeftDown:!1,mouseButtonCenterDown:!1,mouseButtonRightDown:!1,mouseDepthPicker:!1,clickedTile:-1,pan2DxyzmmAtMouseDown:[0,0,0,1],prevX:0,prevY:0,currX:0,currY:0,currentTouchTime:0,lastTouchTime:0,touchTimer:null,doubleTouch:!1,isDragging:!1,dragStart:[0,0],dragEnd:[0,0],dragClipPlaneStartDepthAziElev:[0,0,0],lastTwoTouchDistance:0,multiTouchGesture:!1,windowX:0,windowY:0,activeDragMode:null,activeDragButton:null,angleFirstLine:[0,0,0,0],angleState:"none",activeClipPlaneIndex:0}),T(this,ns,null),C(this,"back",null),C(this,"overlays",[]),C(this,"deferredVolumes",[]),C(this,"deferredMeshes",[]),C(this,"furthestVertexFromOrigin",100),C(this,"volScale",[]),C(this,"vox",[]),C(this,"mousePos",[0,0]),C(this,"screenSlices",[]),C(this,"cuboidVertexBuffer"),C(this,"otherNV",null),C(this,"volumeObject3D",null),C(this,"pivot3D",[0,0,0]),C(this,"furthestFromPivot",10),C(this,"currentClipPlaneIndex",0),C(this,"lastCalled",(new Date).getTime()),C(this,"selectedObjectId",-1),C(this,"CLIP_PLANE_ID",1),C(this,"VOLUME_ID",254),C(this,"DISTANCE_FROM_CAMERA",-.54),C(this,"graph",{LTWH:[0,0,640,480],opacity:0,vols:[0],autoSizeMultiplanar:!1,normalizeValues:!1,isRangeCalMinMax:!1}),C(this,"customLayout",[]),C(this,"meshShaders",[{Name:"Phong",Frag:"#version 300 es\nprecision highp int;\nprecision highp float;\nuniform float opacity;\nin vec4 vClr;\nin vec3 vN;\nout vec4 color;\nvoid main() {\n\tvec3 r = vec3(0.0, 0.0, 1.0); //rayDir: for orthographic projections moving in Z direction (no need for normal matrix
1)\n\tfloat ambient = 0.35;\n\tfloat diffuse = 0.5;\n\tfloat specular = 0.2;\n\tfloat shininess = 10.0;\n\tvec3 n = normalize(vN);\n\tvec3 lightPosition = vec3(0.0, 10.0, -5.0);\n\tvec3 l = normalize(lightPosition);\n\tfloat lightNormDot = dot(n, l);\n\tvec3 a = vClr.rgb * ambient;\n\tvec3 d = max(lightNormDot, 0.0) * vClr.rgb * diffuse;\n\tfloat s = specular * pow(max(dot(reflect(l, n), r), 0.0), shininess);\n\tcolor = vec4(a + d + s, opacity);\n}"},{Name:"Matte",Frag:"#version 300 es\nprecision highp int;\nprecision highp float;\nuniform float opacity;\nin vec4 vClr;\nin vec3 vN;\nout vec4 color;\nvoid main() {\n\tfloat ambient = 0.35;\n\tfloat diffuse = 0.6;\n\tvec3 n = normalize(vN);\n\tvec3 lightPosition = vec3(0.0, 10.0, -5.0);\n\tvec3 l = normalize(lightPosition);\n\tfloat lightNormDot = dot(n, l);\n\tvec3 a = vClr.rgb * ambient;\n\tvec3 d = max(lightNormDot, 0.0) * vClr.rgb * diffuse;\n\tcolor = vec4(a + d, opacity);\n}"},{Name:"Harmonic",Frag:'#version 300 es\nprecision highp int;\nprecision highp float;\nuniform float opacity;\nin vec4 vClr;\nin vec3 vN;\nout vec4 color;\n//Spherical harmonics constants\nconst float C1 = 0.429043;\nconst float C2 = 0.511664;\nconst float C3 = 0.743125;\nconst float C4 = 0.886227;\nconst float C5 = 0.247708;\n//Spherical harmonics coefficients\n// Ramamoorthi, R., and P. Hanrahan. 2001b. "An Efficient Representation for Irradiance Environment Maps." In Proceedings of SIGGRAPH 2001, pp. 497\u2013500.\n// https://github.com/eskimoblood/processingSketches/blob/master/data/shader/shinyvert.glsl\n// https://github.com/eskimoblood/processingSketches/blob/master/data/shader/shinyvert.glsl\n// Constants for Eucalyptus Grove lighting\nconst vec3 L00  = vec3( 0.3783264,  0.4260425,  0.4504587);\nconst vec3 L1m1 = vec3( 0.2887813,  0.3586803,  0.4147053);\nconst vec3 L10  = vec3( 0.0379030,  0.0295216,  0.0098567);\nconst vec3 L11  = vec3(-0.1033028, -0.1031690, -0.0884924);\nconst vec3 L2m2 = vec3(-0.0621750, -0.0554432, -0.0396779);\nconst vec3 L2m1 = vec3( 0.0077820, -0.0148312, -0.0471301);\nconst vec3 L20  = vec3(-0.0935561, -0.1254260, -0.1525629);\nconst vec3 L21  = vec3(-0.0572703, -0.0502192, -0.0363410);\nconst vec3 L22  = vec3( 0.0203348, -0.0044201, -0.0452180);\nvec3 SH(vec3 vNormal) {\n\tvNormal = vec3(vNormal.x,vNormal.z,vNormal.y);\n\tvec3 diffuseColor = C1 * L22 * (vNormal.x * vNormal.x - vNormal.y * vNormal.y) +\n\tC3 * L20 * vNormal.z * vNormal.z +\n\tC4 * L00 -\n\tC5 * L20 +\n\t2.0 * C1 * L2m2 * vNormal.x * vNormal.y +\n\t2.0 * C1 * L21  * vNormal.x * vNormal.z +\n\t2.0 * C1 * L2m1 * vNormal.y * vNormal.z +\n\t2.0 * C2 * L11  * vNormal.x +\n\t2.0 * C2 * L1m1 * vNormal.y +\n\t2.0 * C2 * L10  * vNormal.z;\n\treturn diffuseColor;\n}\nvoid main() {\n\tvec3 r = vec3(0.0, 0.0, 1.0); //rayDir: for orthographic projections moving in Z direction (no need for normal matrix)\n\tfloat ambient = 0.3;\n\tfloat diffuse = 0.6;\n\tfloat specular = 0.1;\n\tfloat shininess = 10.0;\n\tvec3 n = normalize(vN);\n\tvec3 lightPosition = vec3(0.0, 10.0, -5.0);\n\tvec3 l = normalize(lightPosition);\n\tfloat s = specular * pow(max(dot(reflect(l, n), r), 0.0), shininess);\n\tvec3 a = vClr.rgb * ambient;\n\tvec3 d = vClr.rgb * diffuse * SH(-reflect(n, vec3(l.x, l.y, -l.z)) );\n\tcolor = vec4(a + d + s, opacity);\n}'},{Name:"Hemispheric",Frag:"#version 300 es\nprecision highp int;\nprecision highp float;\nuniform float opacity;\nin vec4 vClr;\nin vec3 vN;\nout vec4 color;\nvoid main() {\n\tvec3 r = vec3(0.0, 0.0, 1.0); //rayDir: for orthographic projections moving in Z direction (no need for normal matrix)\n\tfloat ambient = 0.35;\n\tfloat diffuse = 0.5;\n\tfloat specular = 0.2;\n\tfloat shininess = 10.0;\n\tvec3 n = normalize(vN);\n\tvec3 lightPosition = vec3(0.0, 10.0, -5.0);\n\tvec3 l = normalize(lightPosition);\n\tfloat lightNormDot = dot(n, l);\n\tvec3 up = vec3(0.0, 1.0, 0.0);\n\tfloat ax = dot(n, up) * 0.5 + 0.5;  //Shreiner et al. (2013) OpenGL Programming Guide, 8th Ed., p 388. ISBN-10: 0321773039\n\tvec3 upClr = vec3(1.0, 1.0, 0.95);\n\tvec3 downClr = vec3(0.4, 0.4, 0.6);\n\tvec3 a = vClr.rgb * ambient;\n\ta *= mix(downClr, upClr, ax);\n\tvec3 d = max(lightNormDot, 0.0) * vClr.rgb * diffuse;\n\tfloat s = specular * pow(max(dot(reflect(l, n), r), 0.0), shininess);\n\tcolor = vec4(a + d + s, opacity);\n}"},{Name:"Crevice",Frag:"#version 300 es\nprecision highp int;\nprecision highp float;\nuniform float opacity;\nin vec4 vClr;\nin vec3 vN;\nin vec4 vPc;\nout vec4 color;\nvoid main() {\n\tvec3 n = normalize(vN);\n\t// Compute curvature\n\tvec3 dx = dFdx(n);\n\tvec3 dy = dFdy(n);\n\tvec3 xneg = n - dx;\n\tvec3 xpos = n + dx;\n\tvec3 yneg = n - dy;\n\tvec3 ypos = n + dy;\n\tfloat depth = length(vPc.xyz);\n\tfloat curv = (cross(xneg, xpos).y - cross(yneg, ypos).x) / depth;\n\t//at this stage 0.5 for flat, with valleys dark and ridges bright\n\tcurv = 1.0 - (curv + 0.5);\n\t//clamp\n\tcurv =  min(max(curv, 0.0), 1.0);\n\t// easing function\n\tcurv = pow(curv, 0.5);\n\t//modulate ambient and diffuse with curvature\n\tvec3 r = vec3(0.0, 0.0, 1.0); //rayDir: for orthographic projections moving in Z direction (no need for normal matrix
1)\n\tfloat ambient = 0.6;\n\tfloat diffuse = 0.6;\n\tfloat specular = 0.2;\n\tfloat shininess = 10.0;\n\tvec3 lightPosition = vec3(0.0, 10.0, -2.0);\n\tvec3 l = normalize(lightPosition);\n\tfloat lightNormDot = dot(n, l);\n\tvec3 a = vClr.rgb * ambient * curv;\n\tvec3 d = max(lightNormDot, 0.0) * vClr.rgb * diffuse;\n\tfloat s = specular * pow(max(dot(reflect(l, n), r), 0.0), shininess);\n\tcolor = vec4(a + d + s, opacity);\n}"},{Name:"Edge",Frag:"#version 300 es\nprecision highp int;\nprecision highp float;\nuniform float opacity;\nin vec4 vClr;\nin vec3 vN;\nout vec4 color;\nvoid main() {\n\tvec3 r = vec3(0.0, 0.0, 1.0); //rayDir: for orthographic projections moving in Z direction (no need for normal matrix)\n\tfloat diffuse = 1.0;\n\tfloat specular = 0.2;\n\tfloat shininess = 10.0;\n\tvec3 n = normalize(vN);\n\tvec3 lightPosition = vec3(0.0, 0.0, -5.0);\n\tvec3 l = normalize(lightPosition);\n\tfloat lightNormDot = max(dot(n, l), 0.0);\n\tvec3 d = lightNormDot * vClr.rgb * diffuse;\n\tfloat s = specular * pow(max(dot(reflect(l, n), r), 0.0), shininess);\n\tcolor = vec4(d + s, opacity);\n}"},{Name:"Diffuse",Frag:"#version 300 es\nprecision highp int;\nprecision highp float;\nuniform float opacity;\nin vec4 vClr;\nin vec3 vN;\nout vec4 color;\nvoid main() {\n\tfloat diffuse = 1.4;\n\tvec3 l = vec3(0.0, 0.0, -1.0);\n\tfloat lightNormDot = max(dot(normalize(vN), l), 0.0);\n\tcolor = vec4(lightNormDot * vClr.rgb * diffuse, opacity);\n}"},{Name:"Outline",Frag:"#version 300 es\nprecision highp int;\nprecision highp float;\nuniform float opacity;\nin vec4 vClr;\nin vec3 vN;\nout vec4 color;\nvoid main() {\n\tvec3 r = vec3(0.0, 0.0, 1.0); //rayDir: for orthographic projections moving in Z direction (no need for normal matrix)\n\tfloat ambient = 0.3;\n\tfloat diffuse = 0.6;\n\tfloat specular = 0.25;\n\tfloat shininess = 10.0;\n\tfloat PenWidth = 0.6;\n\tvec3 n = normalize(vN);\n\tvec3 lightPosition = vec3(0.0, 10.0, -5.0);\n\tvec3 l = normalize(lightPosition);\n\tfloat lightNormDot = dot(n, l);\n\tfloat view = abs(dot(n,r)); //with respect to viewer\n\tif (PenWidth < view) discard;\n\tvec3 a = vClr.rgb * ambient;\n\tvec3 d = max(lightNormDot, 0.0) * vClr.rgb * diffuse;\n\tfloat s = specular * pow(max(dot(reflect(l, n), r), 0.0), shininess);\n\tcolor.rgb = a + d + s;\n\tcolor.a = opacity;\n}"},{Name:"Specular",Frag:"#version 300 es\nprecision highp int;\nprecision highp float;\nuniform float opacity;\nin vec4 vClr;\nin vec3 vN;\nout vec4 color;\nvoid main() {\n\tfloat specularRGB = 0.7;\n\tfloat specularWhite = 0.3;\n\tfloat shininess = 10.0;\n\tfloat diffuse = 1.0;\n\tvec3 r = vec3(0.0, 0.0, 1.0); //rayDir: for orthographic projections moving in Z direction (no need for normal matrix)\n\tvec3 n = normalize(vN);\n\tvec3 l = vec3(0.0, 0.0, -1.0);\n\tfloat lightNormDot = max(dot(n, l), 0.0);\n\tvec3 d3 = lightNormDot * vClr.rgb * diffuse;\n\tfloat s = pow(max(dot(reflect(l, n), r), 0.0), shininess);\n\tvec3 s3 = specularRGB * s * vClr.rgb;\n\ts *= specularWhite;\n\tcolor = vec4(d3 + s3 + s, opacity);\n}"},{Name:"Toon",Frag:"#version 300 es\nprecision highp int;\nprecision highp float;\nuniform float opacity;\nin vec4 vClr;\nin vec3 vN;\nout vec4 color;\nfloat stepmix(float edge0, float edge1, float E, float x){\n\tfloat T = clamp(0.5 * (x - edge0 + E) / E, 0.0, 1.0);\n\treturn mix(edge0, edge1, T);\n}\nvoid main() {\n\tvec3 r = vec3(0.0, 0.0, 1.0);\n\tfloat ambient = 0.3;\n\tfloat diffuse = 0.6;\n\tfloat specular = 0.5;\n\tfloat shininess = 50.0;\n\tvec3 n = normalize(vN);\n\tvec3 lightPosition = vec3(0.0, 10.0, -5.0);\n\tvec3 l = normalize(lightPosition);\n\tfloat df = max(0.0, dot(n, l));\n\tfloat sf = pow(max(dot(reflect(l, n), r), 0.0), shininess);\n\tconst float A = 0.1;\n\tconst float B = 0.3;\n\tconst float C = 0.6;\n\tconst float D = 1.0;\n\tfloat E = fwidth(df);\n\tif (df > A - E && df < A + E) df = stepmix(A, B, E, df);\n\telse if (df > B - E && df < B + E) df = stepmix(B, C, E, df);\n\telse if (df > C - E && df < C + E) df = stepmix(C, D, E, df);\n\telse if (df < A) df = 0.0;\n\telse if (df < B) df = B;\n\telse if (df < C) df = C;\n\telse df = D;\n\tE = fwidth(sf);\n\tif (sf > 0.5 - E && sf < 0.5 + E)\n\t\tsf = smoothstep(0.5 - E, 0.5 + E, sf);\n\telse\n\t\tsf = step(0.5, sf);\n\tvec3 a = vClr.rgb * ambient;\n\tvec3 d = max(df, 0.0) * vClr.rgb * diffuse;\n\tcolor.rgb = a + d + (specular * sf);\n\tcolor.a = opacity;\n}"},{Name:"Flat",Frag:jn},{Name:"Matcap",Frag:"#version 300 es\nprecision highp int;\nprecision highp float;\nuniform float opacity;\nin vec4 vClr;\nin vec3 vN;\nuniform sampler2D matCap;\nout vec4 color;\nvoid main() {\n\tvec3 n = normalize(vN);\n\tvec2 uv = n.xy * 0.5 + 0.5;\n\tuv.y = 1.0 - uv.y;\n\tvec3 clr = texture(matCap,uv.xy).rgb * vClr.rgb;\n\tcolor = vec4(clr, opacity);\n}"},{Name:"Rim",Frag:"#version 300 es\nprecision highp int;\nprecision highp float;\nuniform float opacity;\nin vec4 vClr;\nin vec3 vN;\nout vec4 color;\nvoid main() {\n\tconst float thresh = 0.4;\n\tconst vec3 viewDir = vec3(0.0, 0.0, -1.0);\n\tvec3 n = normalize(vN);\n\t// use abs() for two-sided lighting, max() for one sided\n\tfloat cosTheta = abs(dot(n, viewDir));\n\t// float cosTheta = max(dot(n, viewDir), 0.0);\n\t// optional fresnel equation - adjust exponent\n\t// cosTheta = 1.0 - pow(1.0 - cosTheta, 2.0);\n\t// use step for binary edges, smoothstep for feathered edges\n\t// vec3 d = step(thresh, cosTheta) * vClr.rgb;\n\tvec3 d = smoothstep(thresh - 0.05, thresh + 0.05, cosTheta) * vClr.rgb;\n\tcolor = vec4(d, opacity);\n}"},{Name:"Silhouette",Frag:"#version 300 es\nprecision highp int;\nprecision highp float;\nuniform float opacity;\nin vec4 vClr;\nin vec3 vN;\nout vec4 color;\nvoid main() {\n  const float edge0 = 0.1;\n  const float edge1 = 0.25;\n  const vec3 viewDir = vec3(0.0, 0.0, -1.0);\n  vec3 n = normalize(vN);\n  float cosTheta = abs(dot(n, viewDir));\n  float alpha = 1.0 - smoothstep(edge0, edge1, cosTheta);\n  if (alpha <= 0.0) {\n    discard;\n  }\n  color = vec4(0.0, 0.0, 0.0, opacity * alpha);\n}"},{Name:"Crosscut",Frag:"#version 300 es\nprecision highp int;\nprecision highp float;\nuniform vec4 sliceMM;\nuniform float thickMM ;\nin vec4 vClr;\nin vec4 vP;  // vertex position in mm\nout vec4 color;\nvoid main() {\n    const float LINE_WIDTH_PX = 4.0;   // target thickness in pixels\n    //const float LINE_THRESH_MM = 1.5;   // target thickness in pixels\n    const float TILT_STRENGTH = 1.0;   // >0 shrinks ribbon for oblique triangles\n    // --- signed distances to each orthogonal plane (object space) ---\n    vec3 d = vP.xyz - sliceMM.xyz;\n    vec3 ad = abs(d);\n    // --- derivatives to get pixel-consistent widths (per-axis) ---\n    vec3 fd = fwidth(vP.xyz);\n    //minDist is in mm not pixels\n    float minDist = min(ad.x, min(ad.y, ad.z));\n    if (minDist >  sliceMM.w) discard;\n    // --- per-plane obliqueness: use the two in-plane components' fwidth ---\n    float tiltX = length(fd.yz); // for plane with normal X\n    float tiltY = length(fd.xz); // for plane with normal Y\n    float tiltZ = length(fd.xy); // for plane with normal Z\n    float tfX = clamp(1.0 / (1.0 + TILT_STRENGTH * tiltX), 0.0, 1.0);\n    float tfY = clamp(1.0 / (1.0 + TILT_STRENGTH * tiltY), 0.0, 1.0);\n    float tfZ = clamp(1.0 / (1.0 + TILT_STRENGTH * tiltZ), 0.0, 1.0);\n    // --- half-widths for each plane (apply per-axis tilt factor) ---\n    vec3 halfWidth;\n    halfWidth.x = (LINE_WIDTH_PX * 0.5) * fd.x * tfX;\n    halfWidth.y = (LINE_WIDTH_PX * 0.5) * fd.y * tfY;\n    halfWidth.z = (LINE_WIDTH_PX * 0.5) * fd.z * tfZ;\n    // --- smooth alpha for each plane ---\n    vec3 edgeA = 1.0 - smoothstep(vec3(0.0), halfWidth, ad);
1\n    // combine planes (max of X,Y,Z ribbons)\n    float edgeAlpha = max(edgeA.x, max(edgeA.y, edgeA.z));\n    if (edgeAlpha <= 1e-4) discard; // outside ribbons\n    color = vec4(vClr.rgb, vClr.a * edgeAlpha);\n}"}]),C(this,"dragModes",{contrast:1,measurement:2,angle:7,none:0,pan:3,slicer3D:4,callbackOnly:5}),C(this,"sliceTypeAxial",0),C(this,"sliceTypeCoronal",1),C(this,"sliceTypeSagittal",2),C(this,"sliceTypeMultiplanar",3),C(this,"sliceTypeRender",4),C(this,"onDragRelease",(()=>{})),C(this,"onMouseUp",(()=>{})),C(this,"onLocationChange",(()=>{})),C(this,"onIntensityChange",(()=>{})),C(this,"onClickToSegment",(()=>{})),C(this,"onImageLoaded",(()=>{})),C(this,"onMeshLoaded",(()=>{})),C(this,"onFrameChange",(()=>{})),C(this,"onError",(()=>{})),C(this,"onColormapChange",(()=>{})),C(this,"onInfo",(()=>{})),C(this,"onWarn",(()=>{})),C(this,"onDebug",(()=>{})),C(this,"onVolumeAddedFromUrl",(()=>{})),C(this,"onVolumeWithUrlRemoved",(()=>{})),C(this,"onVolumeUpdated",(()=>{})),C(this,"onMeshAddedFromUrl",(()=>{})),C(this,"onMeshAdded",(()=>{})),C(this,"onMeshWithUrlRemoved",(()=>{})),C(this,"onZoom3DChange",(()=>{})),C(this,"onAzimuthElevationChange",(()=>{})),C(this,"onClipPlaneChange",(()=>{})),C(this,"onCustomMeshShaderAdded",(()=>{})),C(this,"onMeshShaderChanged",(()=>{})),C(this,"onMeshPropertyChanged",(()=>{})),C(this,"onDicomLoaderFinishedWithImages",(()=>{})),C(this,"onDocumentLoaded",(()=>{})),C(this,"onOptsChange",(()=>{})),C(this,"onMeasurementCompleted",(()=>{})),C(this,"onAngleCompleted",(()=>{})),C(this,"onPenValueChanged",(()=>{})),C(this,"onDrawingToolChanged",(()=>{})),C(this,"onVolumeRemoved",(()=>{})),C(this,"onMeshRemoved",(()=>{})),C(this,"onSliceTypeChange",(()=>{})),C(this,"onDrawingChanged",(()=>{})),C(this,"onDrawingEnabled",(()=>{})),C(this,"onVolumeOrderChanged",(()=>{})),C(this,"document",new hn),C(this,"mediaUrlMap",new Map),C(this,"initialized",!1),C(this,"currentDrawUndoBitmap");for(const e in t)"function"==typeof t[e]?this[e]=t[e]:this.opts[e]=void 0===ln[e]?ln[e]:t[e];0===this.opts.forceDevicePixelRatio?this.uiData.dpr=window.devicePixelRatio||1:this.opts.forceDevicePixelRatio<0?this.uiData.dpr=1:this.uiData.dpr=this.opts.forceDevicePixelRatio,this.currentDrawUndoBitmap=this.opts.maxDrawUndoBitmaps,this.opts.drawingEnabled&&this.createEmptyDrawing(),this.opts.thumbnail.length>0&&(this.thumbnailVisible=!0),Q.setLogLevel(this.opts.logLevel),this.document.setOptsChangeCallback(((t,e,i)=>{this._emitEvent("optsChange",{propertyName:t,newValue:e,oldValue:i}),this.onOptsChange(t,e,i)})),this.scene.onZoom3DChange=t=>{this._emitEvent("zoom3DChange",{zoom:t}),this.onZoom3DChange(t)}}get scene(){return this.document.scene}get opts(){return this.document.opts}get sliceMosaicString(){return this.document.opts.sliceMosaicString||""}set sliceMosaicString(t){this.document.opts.sliceMosaicString=t}get isAlphaClipDark(){return this.document.opts.isAlphaClipDark}set isAlphaClipDark(t){this.document.opts.isAlphaClipDark=t}addEventListener(t,e,i){super.addEventListener(t,e,i)}removeEventListener(t,e,i){super.removeEventListener(t,e,i)}_emitEvent(t,e){try{const i=new rs(t,e);this.dispatchEvent(i)}catch(i){console.error(`Error in ${t} event listener:`,i)}}cleanup(){var t,e,i,n;t=this.resizeObserver,e=this.canvasObserver,(i=this.resizeEventListener)&&window.removeEventListener("resize",i),t&&t.disconnect(),e&&e.disconnect(),this.resizeEventListener=null,this.resizeObserver=null,this.canvasObserver=null,(n=D(this,ns))&&n.abort(),I(this,ns,null),this.document.removeOptsChangeCallback()}get volumes(){return this.document.volumes}set volumes(t){this.document.volumes=t}get meshes(){return this.document.meshes}set meshes(t){this.document.meshes=t}get drawBitmap(){return this.document.drawBitmap}set drawBitmap(t){this.document.drawBitmap=t}get volScaleMultiplier(){return this.scene.volScaleMultiplier}set volScaleMultiplier(t){this.setScale(t)}async saveScene(t){void 0===t&&(t="niivue.png");const e=this.canvas;if(!e)throw new Error("canvas not defined");this.drawScene(),e.toBlob((e=>{e&&(""===t&&(t=(t=`niivue-screenshot-${(new Date).toString()}.png`).replace(/\s/g,"_")),function(t,e){const i=document.createElement("a");document.body.appendChild(i),i.style.display="none";const n=window.URL.createObjectURL(t);
1i.href=n,i.download=e,i.click(),i.remove()}(e,t))}))}async attachTo(t,e){return void 0===e&&(e=null),await this.attachToCanvas(document.getElementById(t),e),Q.debug("attached to element with id: ",t),this}async attachToCanvas(t,e){void 0===e&&(e=null),this.canvas=t,null===e&&(e=navigator.hardwareConcurrency>6,Q.debug("AntiAlias ",e," Threads ",navigator.hardwareConcurrency));const{gl:i,max2D:n,max3D:r}=function(t,e){const i=t.getContext("webgl2",{alpha:!0,antialias:e});if(!i)throw new Error("Unable to initialize WebGL2. Your browser may not support it.");return{gl:i,max2D:i.getParameter(i.MAX_TEXTURE_SIZE),max3D:i.getParameter(i.MAX_3D_TEXTURE_SIZE)}}(this.canvas,e);var a;return this.gl=i,this.uiData.max2D=n,this.uiData.max3D=r,Q.info("NIIVUE VERSION ",as),Q.debug(`Max texture size 2D: ${this.uiData.max2D} 3D: ${this.uiData.max3D}`),this.canvas.parentElement.style.backgroundColor="black",this.opts.isResizeCanvas&&(Xr(this.canvas),this.canvas.width=this.canvas.offsetWidth,this.canvas.height=this.canvas.offsetHeight,this.resizeEventListener=(a=()=>this.resizeListener(),()=>{requestAnimationFrame((()=>{a()}))}),window.addEventListener("resize",this.resizeEventListener),this.resizeObserver=function(t){return new ResizeObserver((()=>{requestAnimationFrame((()=>{t()}))}))}((()=>this.resizeListener())),this.resizeObserver.observe(this.canvas.parentElement),this.canvasObserver=function(t){return new MutationObserver(t)}((t=>{for(const e of t)if("childList"===e.type&&e.removedNodes.length>0&&Array.from(e.removedNodes).includes(this.canvas)){this.cleanup();break}})),this.canvasObserver.observe(this.canvas.parentElement,{childList:!0})),this.opts.interactive&&this.registerInteractions(),await this.init(),this.drawScene(),this}syncWith(t,e){void 0===e&&(e={"2d":!0,"3d":!0}),t instanceof Array||(t=[t]),this.otherNV=t,this.syncOpts={...e}}broadcastTo(t,e){void 0===e&&(e={"2d":!0,"3d":!0}),t instanceof Array||(t=[t]),this.otherNV=t,this.syncOpts=e}doSync3d(t){t.scene.renderAzimuth=this.scene.renderAzimuth,t.scene.renderElevation=this.scene.renderElevation,t.scene.volScaleMultiplier=this.scene.volScaleMultiplier}doSync2d(t){const e=this.frac2mm(this.scene.crosshairPos);t.scene.crosshairPos=t.mm2frac(e),t.scene.pan2Dxyzmm=n.o8(this.scene.pan2Dxyzmm)}doSyncGamma(t){const e=this.scene.gamma;e!==t.scene.gamma&&t.setGamma(e)}doSyncZoomPan(t){t.scene.pan2Dxyzmm=n.o8(this.scene.pan2Dxyzmm)}doSyncCrosshair(t){const e=this.frac2mm(this.scene.crosshairPos);t.scene.crosshairPos=t.mm2frac(e)}doSyncCalMin(t){this.volumes[0].cal_min!==t.volumes[0].cal_min&&(t.volumes[0].cal_min=this.volumes[0].cal_min,t.updateGLVolume())}doSyncCalMax(t){this.volumes[0].cal_max!==t.volumes[0].cal_max&&(t.volumes[0].cal_max=this.volumes[0].cal_max,t.updateGLVolume())}doSyncSliceType(t){t.setSliceType(this.opts.sliceType)}doSyncClipPlane(t){t.setClipPlane(this.scene.clipPlaneDepthAziElevs[this.uiData.activeClipPlaneIndex])}sync(){if(this.gl&&this.otherNV&&void 0!==this.otherNV&&this.gl.canvas.matches(":focus"))for(let t=0;t<this.otherNV.length;t++)this.otherNV[t]!==this&&(this.syncOpts.gamma&&this.doSyncGamma(this.otherNV[t]),this.syncOpts.crosshair&&this.doSyncCrosshair(this.otherNV[t]),this.syncOpts.zoomPan&&this.doSyncZoomPan(this.otherNV[t]),this.syncOpts.sliceType&&this.doSyncSliceType(this.otherNV[t]),this.syncOpts.cal_min&&this.doSyncCalMin(this.otherNV[t]),this.syncOpts.cal_max&&this.doSyncCalMax(this.otherNV[t]),this.syncOpts.clipPlane&&this.doSyncClipPlane(this.otherNV[t]),this.syncOpts["2d"]&&this.doSync2d(this.otherNV[t]),this.syncOpts["3d"]&&this.doSync3d(this.otherNV[t]),this.otherNV[t].canvas!==this.canvas&&this.otherNV[t].drawScene(),this.otherNV[t].createOnLocationChange())}arrayEquals(t,e){return Array.isArray(t)&&Array.isArray(e)&&t.length===e.length&&t.every(((t,i)=>t===e[i]))}textSizePoints(){this.opts.textHeight>=0&&(Q.warn("textHeight is deprecated (use fontMinPx and fontSizeScaling)"),this.opts.fontMinPx=217*this.opts.textHeight,this.opts.fontSizeScaling=.4,this.opts.textHeight=-1);const t=this.uiData.dpr||1,e=this.opts.fontMinPx,i=this.gl.canvas.width/t,n=this.gl.canvas.height/t,r=i*n,a=Math.max(r/48e4,1),s=Math.pow(a,this.opts.fontSizeScaling),o=e*s*t;this.fontPx=o,Q.debug(`${i.toFixed(0)}x${n.toFixed(0)} pts (dpi=${t}) => areaScale=${a.toFixed(2)}, scale=${s.toFixed(2)}, minPx=${this.opts.fontMinPx} fontScale=${this.opts.fontSizeScaling} fontPx=${o.toFixed(2)}`)}
1resizeListener(){if(t=this.canvas,e=this._gl,null===t||null===e)return;var t,e;if(!this.opts.isResizeCanvas)return this.opts.forceDevicePixelRatio>=0&&Q.warn("this.opts.forceDevicePixelRatio requires isResizeCanvas"),void this.drawScene();Xr(this.canvas);const i=Wr({canvas:this.canvas,gl:this.gl,isResizeCanvas:this.opts.isResizeCanvas,forceDevicePixelRatio:this.opts.forceDevicePixelRatio});this.uiData.dpr=i.dpr,Q.debug("devicePixelRatio: "+this.uiData.dpr),this.canvas.width=i.width,this.canvas.height=i.height,this.gl.viewport(0,0,this.gl.canvas.width,this.gl.canvas.height),this.textSizePoints(),this.drawScene()}getRelativeMousePosition(t,e){return Gr(t,e)}getNoPaddingNoBorderCanvasRelativeMousePosition(t,e){return function(t,e){return Gr(t,e||t.target)}(t,e)}mouseContextMenuListener(t){t.preventDefault()}mouseDownListener(t){if(this.uiData.mousedown=!0,!this.eventInBounds(t))return this.opts.showBoundsBorder=!1,void this.drawScene();this.opts.bounds&&(this.opts.showBoundsBorder=!0),t.preventDefault(),this.drawPenLocation=[NaN,NaN,NaN],this.drawPenAxCorSag=-1,this.drawShapeStartLocation=[NaN,NaN,NaN];const e=this.getNoPaddingNoBorderCanvasRelativeMousePosition(t,this.gl.canvas);if(7===this.opts.dragMode&&"drawing_second_line"===this.uiData.angleState||(this.setDragStart(e.x,e.y),this.setDragEnd(e.x,e.y)),Q.debug("mouse down"),Q.debug(t),!e)return;const[i,n]=[e.x*this.uiData.dpr,e.y*this.uiData.dpr];this.opts.clickToSegment&&(this.clickToSegmentXY=[i,n]);const r=this.getLabelAtPoint([i,n]);if(r){if(r.onClick)return void r.onClick(r,t);for(const t of this.meshes)if("connectome"===t.type)for(const e of t.nodes)e.label===r&&(this.scene.crosshairPos=this.mm2frac([e.x,e.y,e.z]),this.updateGLVolume());else if(Array.isArray(r.points)&&3===r.points.length&&r.points.every(Number.isFinite)){const[t,e,i]=r.points;this.scene.crosshairPos=this.mm2frac([t,e,i]),this.updateGLVolume()}}this.uiData.clickedTile=this.tileIndex(i,n),t.button===os&&t.shiftKey?(this.uiData.mouseButtonCenterDown=!0,this.setActiveDragMode(os,!0,t.ctrlKey),this.handleMouseAction(this.uiData.activeDragMode,t,e)):t.button===os?(this.uiData.mouseButtonLeftDown=!0,this.setActiveDragMode(os,!1,t.ctrlKey),this.handleMouseAction(this.uiData.activeDragMode,t,e)):t.button===cs?(this.uiData.mouseButtonRightDown=!0,this.setActiveDragMode(cs,t.shiftKey,t.ctrlKey),this.handleMouseAction(this.uiData.activeDragMode,t,e)):t.button===ls&&(this.uiData.mouseButtonCenterDown=!0,this.setActiveDragMode(ls,t.shiftKey,t.ctrlKey),this.handleMouseAction(this.uiData.activeDragMode,t,e)),this.drawScene()}getMouseButtonDragMode(t,e,i){return Zr({button:t,shiftKey:e,ctrlKey:i,mouseConfig:this.opts.mouseEventConfig,dragMode:this.opts.dragMode,dragModePrimary:this.opts.dragModePrimary})}getTouchDragMode(t){return function(t){const{isDoubleTouch:e,touchConfig:i,dragMode:n,dragModePrimary:r}=t;return e?i?.doubleTouch??n:i?.singleTouch??r}({isDoubleTouch:t,touchConfig:this.opts.touchEventConfig,dragMode:this.opts.dragMode,dragModePrimary:this.opts.dragModePrimary})}setActiveDragMode(t,e,i){const n=function(t,e){return{activeDragMode:t,activeDragButton:e}}(this.getMouseButtonDragMode(t,e,i),t);this.uiData.activeDragMode=n.activeDragMode,this.uiData.activeDragButton=n.activeDragButton}getCurrentDragMode(){return function(t){const{activeDragMode:e,fallbackDragMode:i}=t;return null!==e?e:i}({activeDragMode:this.uiData.activeDragMode,fallbackDragMode:this.opts.dragMode})}clearActiveDragMode(){const t={activeDragMode:null,activeDragButton:null};this.uiData.activeDragMode=t.activeDragMode,this.uiData.activeDragButton=t.activeDragButton}handleMouseAction(t,e,i){if(8===t)this.mouseDown(i.x,i.y),this.mouseClick(i.x,i.y);else if(9===t)this.uiData.windowX=i.x,this.uiData.windowY=i.y;else{if(this.mousePos=[i.x*this.uiData.dpr,i.y*this.uiData.dpr],0===t)return;if(7===t)if("none"===this.uiData.angleState)this.uiData.angleState="drawing_first_line";else{if("drawing_second_line"===this.uiData.angleState){const t=[i.x*this.uiData.dpr,i.y*this.uiData.dpr],e=this.tileIndex(t[0],t[1]);let n={sliceIndex:-1,sliceType:0,slicePosition:0};if(e>=0&&e<this.screenSlices.length){const t=this.screenSlices[e].axCorSag;let i=0;0===t?i=this.scene.crosshairPos[2]:1===t?i=this.scene.crosshairPos[1]:2===t&&(i=this.scene.crosshairPos[0]),n={sliceIndex:e,sliceType:t,slicePosition:i}}const a=[this.uiData.angleFirstLine[2],this.uiData.angleFirstLine[3],t[0],t[1]],s=this.canvasPos2frac([this.uiData.angleFirstLine[0],this.uiData.angleFirstLine[1]]),o=this.canvasPos2frac([this.uiData.angleFirstLine[2],this.uiData.angleFirstLine[3]]),l=this.canvasPos2frac([a[0],a[1]]),c=this.canvasPos2frac([a[2],a[3]]);if(s[0]>=0&&o[0]>=0&&l[0]>=0&&c[0]>=0){const t=this.frac2mm(s),e=this.frac2mm(o),i=this.frac2mm(l),h=this.frac2mm(c),d={firstLineMM:{start:r.fA(t[0],t[1],t[2]),end:r.fA(e[0],e[1],e[2])},secondLineMM:{start:r.fA(i[0],i[1],i[2]),end:r.fA(h[0],h[1],h[2])},sliceIndex:n.sliceIndex,sliceType:n.sliceType,slicePosition:n.slicePosition,angle:this.calculateAngleBet
1weenLines(this.uiData.angleFirstLine,a)};this.document.completedAngles.push(d),this._emitEvent("angleCompleted",d),this.onAngleCompleted(d)}return this.resetAngleMeasurement(),this.uiData.angleState="complete",void this.drawScene()}"complete"===this.uiData.angleState&&(this.resetAngleMeasurement(),this.uiData.angleState="drawing_first_line")}if(this.setDragStart(i.x,i.y),!this.uiData.isDragging){this.uiData.pan2DxyzmmAtMouseDown=n.o8(this.scene.pan2Dxyzmm);for(const t of this.getZarrVolumes())t.zarrHelper?.beginDrag()}this.uiData.isDragging=!0,this.uiData.dragClipPlaneStartDepthAziElev=this.scene.clipPlaneDepthAziElevs[this.uiData.activeClipPlaneIndex]}}calculateMinMaxVoxIdx(t){return function(t){if(t.length>2)throw new Error("array must not contain more than two values");return[Math.floor(Math.min(t[0],t[1])),Math.floor(Math.max(t[0],t[1]))]}(t)}calculateNewRange(t){let{volIdx:e=0}=void 0===t?{}:t;if(4===this.opts.sliceType&&this.sliceMosaicString.length<1)return;if(!ea(this.uiData.dragStart,this.uiData.dragEnd))return;let i=this.canvasPos2frac([this.uiData.dragStart[0],this.uiData.dragStart[1]]);if(i[0]<0)return;const n=this.frac2vox(i,e);if(i=this.canvasPos2frac([this.uiData.dragEnd[0],this.uiData.dragEnd[1]]),i[0]<0)return;const r=this.frac2vox(i,e),a=function(t,e,i,n,r){const a=[...i],s=[...n],o=[...r];return t[0]-e[0]==0?a[1]=t[0]+1:t[1]-e[1]==0?s[1]=t[1]+1:t[2]-e[2]==0&&(o[1]=t[2]+1),{xrange:a,yrange:s,zrange:o}}(n,r,this.calculateMinMaxVoxIdx([n[0],r[0]]),this.calculateMinMaxVoxIdx([n[1],r[1]]),this.calculateMinMaxVoxIdx([n[2],r[2]])),s=this.volumes[e].hdr,o=this.volumes[e].img;if(!s||!o)return;const l=function(t){const{xrange:e,yrange:i,zrange:n,dims:r,img:a}=t;let s=-Number.MAX_VALUE,o=Number.MAX_VALUE;const l=r[1],c=r[2];for(let h=n[0];h<n[1];h++){const t=h*l*c;for(let n=i[0];n<i[1];n++){const i=n*l;for(let n=e[0];n<e[1];n++){const e=t+i+n;o>a[e]&&(o=a[e]),s<a[e]&&(s=a[e])}}}return{lo:o,hi:s,hasVariation:o<s}}({xrange:a.xrange,yrange:a.yrange,zrange:a.zrange,dims:s.dims,img:o});if(!l.hasVariation)return;const c=un(s,l.lo),h=un(s,l.hi);this.volumes[e].cal_min=c,this.volumes[e].cal_max=h,this._emitEvent("intensityChange",this.volumes[e]),this.onIntensityChange(this.volumes[e])}generateMouseUpCallback(t,e){const i=this.tileIndex(this.uiData.dragStart[0],this.uiData.dragStart[1]),n=this.tileIndex(this.uiData.dragEnd[0],this.uiData.dragEnd[1]);let a=-1;i===n&&(a=n);let s=-1;a>
1=0&&(s=this.screenSlices[a].axCorSag);const o=this.frac2mm(t),l=this.frac2mm(e),c=r.vt();r.jb(c,r.fA(o[0],o[1],o[2]),r.fA(l[0],l[1],l[2]));const h=r.Il(c),d={fracStart:t,fracEnd:e,voxStart:this.frac2vox(t),voxEnd:this.frac2vox(e),mmStart:o,mmEnd:l,mmLength:h,tileIdx:a,axCorSag:s};this._emitEvent("dragRelease",d),this.onDragRelease(d)}mouseUpListener(){this.uiData.mousedown=!1;const t={mouseButtonRightDown:this.uiData.mouseButtonRightDown,mouseButtonCenterDown:this.uiData.mouseButtonCenterDown,isDragging:this.uiData.isDragging,mousePos:this.mousePos,fracPos:this.canvasPos2frac(this.mousePos)};this.uiData.mouseButtonRightDown=!1;const e=this.uiData.mouseButtonCenterDown;this.uiData.mouseButtonCenterDown=!1,this.uiData.mouseButtonLeftDown=!1;const i=this.getCurrentDragMode();if(this.drawPenFillPts.length>0?this.drawPenFilled():this.opts.drawingEnabled&&!isNaN(this.drawPenLocation[0])?(this.drawAddUndoBitmap(),this._emitEvent("drawingChanged",{action:"draw"}),this.onDrawingChanged("draw")):!this.opts.drawingEnabled||isNaN(this.drawShapeStartLocation[0])||1!==this.opts.penType&&2!==this.opts.penType||(0===this.opts.penValue?this.drawAddUndoBitmap():this.drawAddUndoBitmap(this.drawFillOverwrites),this.drawShapePreviewBitmap=null,this._emitEvent("drawingChanged",{action:"draw"}),this.onDrawingChanged("draw")),this.drawPenLocation=[NaN,NaN,NaN],this.drawPenAxCorSag=-1,this.drawShapeStartLocation=[NaN,NaN,NaN],this.drawShapePreviewBitmap&&(this.drawBitmap=this.drawShapePreviewBitmap,this.drawShapePreviewBitmap=null,this.refreshDrawing(!0,!1)),this._emitEvent("mouseUp",t),la(this.onMouseUp)&&this.onMouseUp(t),this.uiData.isDragging){this.uiData.isDragging=!1;
1for(const e of this.getZarrVolumes())e.zarrHelper?.endDrag();if(7===i){if("drawing_first_line"===this.uiData.angleState)return this.uiData.angleFirstLine=[this.uiData.dragStart[0],this.uiData.dragStart[1],this.uiData.dragEnd[0],this.uiData.dragEnd[1]],this.uiData.angleState="drawing_second_line",this.uiData.isDragging=!0,void this.drawScene();if("drawing_second_line"===this.uiData.angleState)return this.uiData.angleState="complete",this.clearActiveDragMode(),void this.drawScene()}5===i&&this.drawScene();const t=this.canvasPos2frac([this.uiData.dragStart[0],this.uiData.dragStart[1]]),n=this.canvasPos2frac([this.uiData.dragEnd[0],this.uiData.dragEnd[1]]);if(this.generateMouseUpCallback(t,n),6===i)return void this.clearActiveDragMode();if(1===i){if(e)return void this.clearActiveDragMode();if(!ea(this.uiData.dragStart,this.uiData.dragEnd))return void this.clearActiveDragMode();this.calculateNewRange({volIdx:0}),this.refreshLayers(this.volumes[0],0)}if(2===i){const t=this.getCurrentSliceInfo(),e=this.canvasPos2frac([this.uiData.dragStart[0],this.uiData.dragStart[1]]),i=this.canvasPos2frac([this.uiData.dragEnd[0],this.uiData.dragEnd[1]]);if(e[0]>=0&&i[0]>=0){const n=this.frac2mm(e),a=this.frac2mm(i),s={startMM:r.fA(n[0],n[1],n[2]),endMM:r.fA(a[0],a[1],a[2]),sliceIndex:t.sliceIndex,sliceType:t.sliceType,slicePosition:t.slicePosition,distance:r.Io(r.fA(n[0],n[1],n[2]),r.fA(a[0],a[1],a[2]))};this.document.completedMeasurements.push(s),this._emitEvent("measurementCompleted",s),this.onMeasurementCompleted(s)}return this.clearActiveDragMode(),void this.drawScene()}}this.clearActiveDragMode(),this.drawScene()}checkMultitouch(t){if(function(t){const{touchdown:e,multiTouchGesture:i}=t;return e&&!i}({touchdown:this.uiData.touchdown,multiTouchGesture:this.uiData.multiTouchGesture})){const e=this.canvas.getBoundingClientRect(),i=ca({touch:t.touches[0],canvasRect:e});this.mouseDown(i.x,i.y),this.mouseClick(i.x,i.y)}}touchStartListener(t){t.preventDefault(),null===this.uiData.touchTimer&&(this.uiData.touchTimer=setTimeout((()=>{this.resetBriCon(t)}),this.opts.longTouchTimeout));const e=(new Date).getTime(),i=function(t){const{currentTime:e,touchCount:i,isTouchdown:n}=t;return{touchdown:!0,currentTouchTime:e,multiTouchGesture:n&&i>=2}}({currentTime:e,touchCount:t.touches.length,isTouchdown:this.uiData.touchdown});this.uiData.touchdown=i.touchdown,this.uiData.currentTouchTime=i.currentTouchTime;const n=function(t){const{currentTime:e,lastTouchTime:i,doubleTouchTimeout:n}=t,r=e-i;return{isDoubleTap:r<n&&r>0,timeSinceTouch:r}}({currentTime:e,lastTouchTime:this.uiData.lastTouchTime,doubleTouchTimeout:this.opts.doubleTouchTimeout});if(n.isDoubleTap){const i=function(t){return{doubleTouch:!0,lastTouchTime:t}}(e);this.uiData.doubleTouch=i.doubleTouch,this.uiData.lastTouchTime=i.lastTouchTime;const n=t.target.getBoundingClientRect(),r=ca({touch:t.targetTouches[0],canvasRect:n});return this.setDragStart(r.x,r.y),void this.resetBriCon(t)}{const t=function(t){return{doubleTouch:!1,lastTouchTime:t}}(e);this.uiData.doubleTouch=t.doubleTouch??!1,this.uiData.lastTouchTime=t.lastTouchTime,this.setDragStart(0,0),this.setDragEnd(0,0)}ha(this.uiData.touchdown,t.touches.length)?this.uiData.multiTouchGesture=!1:this.uiData.multiTouchGesture=!0,setTimeout(this.checkMultitouch.bind(this),1,t)}touchEndListener(t){t.preventDefault();const e={touchdown:!1,lastTwoTouchDistance:0,multiTouchGesture:!1};if(this.uiData.touchdown=e.touchdown,this.uiData.lastTwoTouchDistance=e.lastTwoTouchDistance,this.uiData.multiTouchGesture=e.multiTouchGesture,this.uiData.touchTimer&&(clearTimeout(this.uiData.touchTimer),this.uiData.touchTimer=null),this.uiData.isDragging){this.uiData.isDragging=!1;
1for(const i of this.getZarrVolumes())i.zarrHelper?.endDrag();1===this.getCurrentDragMode()&&(this.calculateNewRange(),this.refreshLayers(this.volumes[0],0));const t=this.canvasPos2frac([this.uiData.dragStart[0],this.uiData.dragStart[1]]),e=this.canvasPos2frac([this.uiData.dragEnd[0],this.uiData.dragEnd[1]]);this.generateMouseUpCallback(t,e)}this.mouseUpListener()}windowingHandler(t,e,i){void 0===i&&(i=0);Math.sqrt((t-this.uiData.windowX)**2+(e-this.uiData.windowY)**2)>100&&(this.uiData.windowX=t,this.uiData.windowY=e);const n=function(t){const{x:e,y:i,windowX:n,windowY:r,currentCalMin:a,currentCalMax:s,globalMin:o,globalMax:l,gainFactor:c}=t;let h=Number.isFinite(c)?c:.5;h<0&&(h=0);let d=a,u=s;const m=(i-r)*h,f=(e-n)*h;return m<0?(d+=Math.abs(m),u+=Math.abs(m)):m>0&&(d-=m,u-=m),f>0?(d-=f,u+=f):f<0&&(d+=Math.abs(f),u-=Math.abs(f)),u-d<1&&(u=d+1),d<o&&(d=o),u>l&&(u=l),d>u&&(d=u-1),{calMin:d,calMax:u,windowX:e,windowY:i}}({x:t,y:e,windowX:this.uiData.windowX,windowY:this.uiData.windowY,currentCalMin:this.volumes[i].cal_min,currentCalMax:this.volumes[i].cal_max,globalMin:this.volumes[i].global_min,globalMax:this.volumes[i].global_max,gainFactor:this.opts.windowingGainFactor??2});this.volumes[i].cal_min=n.calMin,this.volumes[i].cal_max=n.calMax,this.refreshLayers(this.volumes[i],0),this.uiData.windowX=n.windowX,this.uiData.windowY=n.windowY}mouseLeaveListener(){if(this.clickToSegmentIsGrowing&&(Q.debug("Mouse left canvas, stopping clickToSegment preview."),this.clickToSegmentIsGrowing=!1,this.refreshDrawing(!0,!1)),this.opts.drawingEnabled&&!isNaN(this.drawPenLocation[0])&&(Q.debug("Mouse left canvas during drawing, resetting pen state."),this.drawPenLocation=[NaN,NaN,NaN],this.drawPenAxCorSag=-1,this.drawPenFillPts=[]),this.opts.drawingEnabled&&!isNaN(this.drawShapeStartLocation[0])&&(Q.debug("Mouse left canvas during shape drawing, resetting shape state."),this.drawShapeStartLocation=[NaN,NaN,NaN],this.drawShapePreviewBitmap&&(this.drawBitmap=this.drawShapePreviewBitmap,this.drawShapePreviewBitmap=null,this.refreshDrawing(!0,!1))),this.uiData.isDragging||this.uiData.mousedown){Q.debug("Mouse left canvas during drag, resetting drag state."),this.uiData.isDragging=!1;
1for(const e of this.getZarrVolumes())e.zarrHelper?.endDrag();const t={mousedown:!1,mouseButtonLeftDown:!1,mouseButtonCenterDown:!1,mouseButtonRightDown:!1};this.uiData.mouseButtonLeftDown=t.mouseButtonLeftDown,this.uiData.mouseButtonCenterDown=t.mouseButtonCenterDown,this.uiData.mouseButtonRightDown=t.mouseButtonRightDown,this.uiData.mousedown=t.mousedown,this.drawScene()}this.mousePos=[-1,-1]}mouseMoveListener(t){this.uiData.mousedown&&this.drawScene();const e=this.getNoPaddingNoBorderCanvasRelativeMousePosition(t,this.gl.canvas);if(e)if(this.eventInBounds(t)){if(this.uiData.mousedown){this.canvas.focus();const t=e.x*this.uiData.dpr,i=e.y*this.uiData.dpr;if(this.tileIndex(t,i)!==this.uiData.clickedTile)return;const n=this.getCurrentDragMode();if(8===n){this.mouseMove(e.x,e.y);if(!!this.mouseClick(e.x,e.y)&&this.uiData.prevX===this.uiData.currX&&this.uiData.prevY===this.uiData.currY)return;return this.mouseClick(e.x,e.y),this.drawScene(),this.uiData.prevX=this.uiData.currX,void(this.uiData.prevY=this.uiData.currY)}if(9===n)return this.windowingHandler(e.x,e.y),this.drawScene(),this.uiData.prevX=this.uiData.currX,void(this.uiData.prevY=this.uiData.currY);this.setDragEnd(e.x,e.y),this.drawScene(),this.uiData.prevX=this.uiData.currX,this.uiData.prevY=this.uiData.currY}else if(7===this.getCurrentDragMode()&&"drawing_second_line"===this.uiData.angleState){const e=this.getNoPaddingNoBorderCanvasRelativeMousePosition(t,this.gl.canvas);if(!e)return;this.setDragEnd(e.x,e.y),this.drawScene()}else if(!this.uiData.mousedown&&this.opts.clickToSegment){const e=this.getNoPaddingNoBorderCanvasRelativeMousePosition(t,this.gl.canvas);if(!e)return;const i=e.x*this.uiData.dpr,n=e.y*this.uiData.dpr;this.mousePos=[i,n];const r=this.tileIndex(i,n);if(r>=0&&this.opts.drawingEnabled){this.screenSlices[r].axCorSag<=2&&(this.clickToSegmentXY=[i,n],this.clickToSegmentIsGrowing=!0,this.doClickToSegment({x:i,y:n,tileIndex:r}))}}}else this.updateMousePos(e.x,e.y)}resetBriCon(t){if(void 0===t&&(t=null),this.uiData.isDragging)return;if(!this.eventInBounds(t))return void(this.opts.showBoundsBorder=!1);let e=!1;4===this.opts.sliceType&&(e=!0);let i=0,n=0;if(null!==t&&("targetTouches"in t?(i=t.targetTouches[0].clientX-t.target.getBoundingClientRect().left,n=t.targetTouches[0].clientY-t.target.getBoundingClientRect().top):(i=t.offsetX,n=t.offsetY),i*=this.uiData.dpr,n*=this.uiData.dpr,this.inRenderTile(i,n)>=0&&(e=!0)),e)return this.uiData.mouseDepthPicker=!0,this.drawScene(),void this.drawScene();4!==this.getCurrentDragMode()&&(this.volumes.length<1||this.uiData.doubleTouch||(this.volumes[0].cal_min=this.volumes[0].robust_min,this.volumes[0].cal_max=this.volumes[0].robust_max,this._emitEvent("intensityChange",this.volumes[0]),this.onIntensityChange(this.volumes[0]),this.refreshLayers(this.volumes[0],0),this.drawScene()))}setDragStart(t,e){const[i,n]=fa(t,e,this.uiData.dpr);this.uiData.dragStart[0]=i,this.uiData.dragStart[1]=n}setDragEnd(t,e){const[i,n]=fa(t,e,this.uiData.dpr);this.uiData.dragEnd[0]=i,this.uiData.dragEnd[1]=n}touchMoveListener(t){if(ha(this.uiData.touchdown,t.touches.length)){const e=this.canvas.getBoundingClientRect();if(!this.uiData.isDragging){this.uiData.pan2DxyzmmAtMouseDown=n.o8(this.scene.pan2Dxyzmm);for(const t of this.getZarrVolumes())t.zarrHelper?.beginDrag()}if(this.uiData.isDragging=!0,function(t){const{doubleTouch:e,isDragging:i}=t;return e&&i}({doubleTouch:this.uiData.doubleTouch,isDragging:this.uiData.isDragging})){const e=ca({touch:t.targetTouches[0],canvasRect:t.target.getBoundingClientRect()});return this.setDragEnd(e.x,e.y),void this.drawScene()}const i=this.getTouchDragMode(!1),r=function(t){const{touch:e,canvasRect:i}=t;return{x:e.clientX-i.left,y:e.clientY-i.top,pageX:e.pageX,pageY:e.pageY}}({touch:t.touches[0],canvasRect:e});8===i?(this.mouseClick(r.x,r.y),this.mouseMove(r.x,r.y)):9===i&&(this.windowingHandler(r.x,r.y),this.drawScene())}else this.handlePinchZoom(t)}handlePinchZoom(t){if(e=t.targetTouches.length,i=t.changedTouches.length,2===e&&2===i){const e=this.canvas.getBoundingClientRect(),i=function(t){const{touch1:e,touch2:i,lastTwoTouchDistance:n}=t,r=Math.hypot(e.pageX-i.pageX,e.pageY-i.pageY);let a;return a=0===n?0:r<n?-.01:.01,{distance:r,scrollDelta:a,centerPosition:{x:(e.clientX+i.clientX)/2,y:(e.clientY+i.clientY)/2}}}({touch1:t.touches[0],touch2:t.touches[1],lastTwoTouchDistance:this.uiData.lastTwoTouchDistance}),n=function(t){const{touch:e,canvasRect:i}=t;return[e.clientX-i.left,e.clientY-i.top]}({touch:t.touches[0],canvasRect:e});this.mousePos=n,this.uiData.lastTwoTouchDistance>0&&this.sliceScroll2D(i.scrollDelta,n[0],n[1]),this.uiData.lastTwoTouchDistance=i.distance}var e,i}cycleActiveClipPlane(){const t=function(t){const{currentIndex:e,clipPlanesLength:i}=t;let n;return n=null==e?0:(e+1)%(i||6),{newIndex:n,defaultClipPlane:[0,0,0,2],defaultDepthAziElev:[2,0,0]}}({currentIndex:this.uiData.activeClipPlaneIndex,clipPlanesLength:this.scene.clipPlanes.length});this.uiData.activeClipPlaneIndex=t.newIndex;const e=t.newIndex;return this.scene.clipPlanes[e]||(this.scene.clipPlanes[e]=t.defaultClipPlane),this.scene.clipPlaneDepthAziElevs[e]||(this.scene.clipPlaneDepthAziElevs[e]=t.defaultDepthAziElev),e}keyUpListener(t){if(!this.cursorInBounds())return this.opts.showBoundsBorder=!1,void this.drawScene();const e=(new Date).getTime(),i=function(t){const{currentTime:e,lastCalledTime:i,debounceTime:n}=t;return e-i>n}({currentTime:e,lastCalledTime:this.lastCalled,debounceTime:this.opts.keyDebounceTime});if(ua(t.code,this.opts.cycleClipPlaneHotKey)&&i){const t=this.cycleActiveClipPlane();console.log("Active clip plane cycled to:",t),console.log("clip plane
1s",this.scene.clipPlanes),this.lastCalled=e}if(ua(t.code,this.opts.clipPlaneHotKey)){if(i){const t=function(t){const{currentClipPlaneIndex:e}=t,i=(e+1)%7;return{newIndex:i,depthAziElev:da[i]}}({currentClipPlaneIndex:this.currentClipPlaneIndex});this.currentClipPlaneIndex=t.newIndex,this.scene.clipPlaneDepthAziElevs[this.uiData.activeClipPlaneIndex]=t.depthAziElev,this.setClipPlane(this.scene.clipPlaneDepthAziElevs[this.uiData.activeClipPlaneIndex])}this.lastCalled=e}else if(ua(t.code,this.opts.viewModeHotKey)&&i){const t=function(t){const{currentSliceType:e,totalSliceTypes:i}=t;return(e+1)%i}({currentSliceType:this.opts.sliceType,totalSliceTypes:5});this.setSliceType(t),this.lastCalled=e}this.drawScene()}keyDownListener(t){if(!this.cursorInBounds())return this.opts.showBoundsBorder=!1,void this.drawScene();const{action:e}=function(t){const{code:e,ctrlKey:i,shiftKey:n,sliceType:r}=t,a=4===r;return"KeyH"===e&&a?{action:"render_azimuth_decrease"}:"KeyL"===e&&a?{action:"render_azimuth_increase"}:"KeyJ"===e&&a?{action:"render_elevation_increase"}:"KeyK"===e&&a?{action:"render_elevation_decrease"}:"KeyH"!==e||a?"KeyL"!==e||a?"KeyU"===e&&!a&&i?{action:"crosshair_forward"}:"KeyD"===e&&!a&&i?{action:"crosshair_backward"}:"KeyJ"!==e||a?"KeyK"!==e||a?"KeyM"!==e||a?"ArrowLeft"===e?{action:"frame_previous"}:"ArrowRight"===e?{action:"frame_next"}:"Slash"===e&&n?{action:"show_version"}:{action:"none"}:{action:"cycle_drag_mode"}:{action:"crosshair_up"}:{action:"crosshair_down"}:{action:"crosshair_right"}:{action:"crosshair_left"}}({code:t.code,ctrlKey:t.ctrlKey,shiftKey:t.shiftKey,sliceType:this.opts.sliceType});switch(e){case"render_azimuth_decrease":this.setRenderAzimuthElevation(this.scene.renderAzimuth-1,this.scene.renderElevation);break;case"render_azimuth_increase":this.setRenderAzimuthElevation(this.scene.renderAzimuth+1,this.scene.renderElevation);break;case"render_elevation_increase":this.setRenderAzimuthElevation(this.scene.renderAzimuth,this.scene.renderElevation+1);break;case"render_elevation_decrease":this.setRenderAzimuthElevation(this.scene.renderAzimuth,this.scene.renderElevation-1);break;case"crosshair_left":this.moveCrosshairInVox(-1,0,0);break;case"crosshair_right":this.moveCrosshairInVox(1,0,0);break;case"crosshair_up":this.moveCrosshairInVox(0,1,0);break;case"crosshair_down":this.moveCrosshairInVox(0,-1,0);break;case"crosshair_forward":this.moveCrosshairInVox(0,0,1);break;case"crosshair_backward":this.moveCrosshairInVox(0,0,-1);break;case"cycle_drag_mode":this.opts.dragMode=function(t){const e=t+1;return e>=4?0:e}(this.opts.dragMode),Q.info("drag mode changed to ",on[this.opts.dragMode]);break;case"frame_previous":this.setFrame4D(this.volumes[0].id,this.volumes[0].frame4D-1);break;case"frame_next":this.setFrame4D(this.volumes[0].id,this.volumes[0].frame4D+1);break;case"show_version":alert(`NIIVUE VERSION: ${as}`)}this.drawScene()}wheelListener(t){const e=function(t){const{thumbnailVisible:e,mosaicStringLength:i,eventInBounds:n,hasBounds:r}=t;return e||i>0?{shouldProcess:!1,showBoundsBorder:!1}:n?{shouldProcess:!0,showBoundsBorder:r}:{shouldProcess:!1,showBoundsBorder:!1}}({thumbnailVisible:this.thumbnailVisible,mosaicStringLength:this.opts.sliceMosaicString.length,eventInBounds:this.eventInBounds(t),hasBounds:null!==this.opts.bounds});if(!e.shouldProcess)return void(this.eventInBounds(t)||(this.opts.showBoundsBorder=!1,this.drawScene()));if(this.opts.showBoundsBorder=e.showBoundsBorder,t.preventDefault(),t.stopPropagation(),function(t){const{dragMode:e,dragStart:i,dragEnd:n}=t;if(6!==e)return!1;const r=i.reduce(((t,e)=>t+e),0),a=n.reduce(((t,e)=>t+e),0);return r>0&&a>0}({dragMode:this.getCurrentDragMode(),dragStart:this.uiData.dragStart,dragEnd:this.uiData.dragEnd})){const e=t.deltaY>0?1:-1,i=function(t){const{dragStart:e,dragEnd:i,delta:n}=t,r=[...e],a=[...i];return e[0]<i[0]?(r[0]=e[0]-n,a[0]=i[0]+n):(r[0]=e[0]+n,a[0]=i[0]-n),e[1]<i[1]?(r[1]=e[1]-n,a[1]=i[1]+n):(r[1]=e[1]+n,a[1]=i[1]-n),{newDragStart:r,newDragEnd:a}}({dragStart:this.uiData.dragStart,dragEnd:this.uiData.dragEnd,delta:e});this.uiData.dragStart[0]=i.newDragStart[0],this.uiData.dragStart[1]=i.newDragStart[1],this.uiData.dragEnd[0]=i.newDragEnd[0],this.uiData.dragEnd[1]=i.newDragEnd[1],this.uiData.isDragging=!0,this.drawScene(),this.uiData.isDragging=!1;const n=this.tileIndex(this.uiData.dragStart[0],this.uiData.dragStart[1]);return void(n>=0?this.generateMouseUpCallback(this.screenXY2TextureFrac(this.uiData.dragStart[0],this.uiData.dragStart[1],n),this.screenXY2TextureFrac(this.uiData.dragEnd[0],this.uiData.dragEnd[1],n)):Q.warn("Could not generate drag release callback for ROI selection: Invalid tile index."))}const i=function(t){const{deltaY:e,invertScrollDirection:i}=t;let n=e<0?-.01:.01;return i&&(n=-n),n}({deltaY:t.deltaY,invertScrollDirection:this.opts.invertScrollDirection});if(this.opts.clickToSegment){this.opts.clickToSegmentPercent=function(t){const{currentPercent:e,scrollAmount:i}=t;let n=e;
1return i<0?(n-=.01,n=Math.max(n,0)):(n+=.01,n=Math.min(n,1)),n}({currentPercent:this.opts.clickToSegmentPercent,scrollAmount:i});const t=this.clickToSegmentXY[0],e=this.clickToSegmentXY[1],n=this.tileIndex(t,e);return void(n>=0&&this.screenSlices[n].axCorSag<=2&&(Q.debug(`Adjusting clickToSegment threshold: ${this.opts.clickToSegmentPercent.toFixed(3)}`),this.clickToSegmentIsGrowing=!0,this.doClickToSegment({x:t,y:e,tileIndex:n})))}const n=this.canvas.getBoundingClientRect(),[r,a]=(s=t.clientX,o=t.clientY,[s-(l=n).left,o-l.top]);var s,o,l;const c=-1!==this.inRenderTile(this.uiData.dpr*r,this.uiData.dpr*a);if(function(t){const{dragMode:e,isInRenderTile:i}=t;return 3===e&&!i}({dragMode:this.getCurrentDragMode(),isInRenderTile:c})){const t=function(t){const{currentZoom:e,scrollAmount:i}=t;let n=e*(1+.01*(i<0?1:-1)*10);return n=Math.round(10*n)/10,{newZoom:n,zoomChange:e-n}}({currentZoom:this.scene.pan2Dxyzmm[3],scrollAmount:i});this.opts.yoke3Dto2DZoom&&(this.scene.volScaleMultiplier=t.newZoom),this.scene.pan2Dxyzmm[3]=t.newZoom;const e=this.frac2mm(this.scene.crosshairPos),n=function(t){const{currentPan:e,zoomChange:i,crosshairMM:n}=t;return[e[0]+i*n[0],e[1]+i*n[1],e[2]+i*n[2]]}({currentPan:[this.scene.pan2Dxyzmm[0],this.scene.pan2Dxyzmm[1],this.scene.pan2Dxyzmm[2]],zoomChange:t.zoomChange,crosshairMM:[e[0],e[1],e[2]]});return this.scene.pan2Dxyzmm[0]=n[0],this.scene.pan2Dxyzmm[1]=n[1],this.scene.pan2Dxyzmm[2]=n[2],this.drawScene(),this.canvas.focus(),void this.sync()}this.sliceScroll2D(i,r,a)}registerInteractions(){if(!this.canvas)throw new Error("canvas undefined");I(this,ns,new AbortController);const{signal:t}=D(this,ns);this.canvas.addEventListener("mousedown",this.mouseDownListener.bind(this),{signal:t}),this.canvas.addEventListener("mouseup",this.mouseUpListener.bind(this),{signal:t}),this.canvas.addEventListener("mousemove",this.mouseMoveListener.bind(this),{signal:t}),this.canvas.addEventListener("mouseleave",this.mouseLeaveListener.bind(this),{signal:t}),this.canvas.addEventListener("touchstart",this.touchStartListener.bind(this),{signal:t}),this.canvas.addEventListener("touchend",this.touchEndListener.bind(this),{signal:t}),this.canvas.addEventListener("touchmove",this.touchMoveListener.bind(this),{signal:t}),this.canvas.addEventListener("wheel",this.wheelListener.bind(this),{signal:t}),this.canvas.addEventListener("contextmenu",this.mouseContextMenuListener.bind(this),{signal:t}),this.canvas.addEventListener("dblclick",this.resetBriCon.bind(this),{signal:t}),this.canvas.addEventListener("dragenter",this.dragEnterListener.bind(this),{signal:t}),this.canvas.addEventListener("dragover",this.dragOverListener.bind(this),{signal:t}),this.canvas.addEventListener("drop",(t=>{this.dropListener(t).catch(console.error)}),{signal:t}),this.canvas.setAttribute("tabindex","0"),this.canvas.addEventListener("keyup",this.keyUpListener.bind(this),{signal:t}),this.canvas.addEventListener("keydown",this.keyDownListener.bind(this),{signal:t})}dragEnterListener(t){Cr(t)}dragOverListener(t){Mr(t)}getFileExt(t,e){return void 0===e&&(e=!0),fr(t,e)}async addVolumeFromUrl(t){const e=await Gi.loadFromUrl(t);return this.document.addImageOptions(e,t),e.onColormapChange=this.onColormapChange,this.mediaUrlMap.set(e,t.url),this._emitEvent("volumeAddedFromUrl",{imageOptions:t,volume:e}),this.onVolumeAddedFromUrl&&this.onVolumeAddedFromUrl(t,e),this.addVolume(e),e}async addVolumesFromUrl(t){const e=t.map((async t=>{const e=this.getFileExt(t.name||t.url);if("DCM"===e)throw new Error("DICOM files must be loaded using useDicomLoader");if(this.loaders[e]){let i=t.url;const n=this.loaders[e].toExt;let a=t.name||t.url;if(a=a.split("/").pop(),"string"==typeof t.url){const e=t.url;try{const t=await fetch(e);if(!t.ok)throw new Error(`Failed to load file: ${t.statusText}`);i=await t.arrayBuffer()}catch(r){throw new Error(`Failed to load url ${e}: ${r}`)}}const s=await this.loaders[e].loader(i);t.url=s,t.name=`${a}.${n}`}const i={url:t.url,headers:t.headers,name:t.name,colormap:t.colormap?t.colormap:t.colorMap,colormapNegative:t.colormapNegative?t.colormapNegative:t.colorMapNegative,opacity:t.opacity,urlImgData:t.urlImgData,cal_min:t.cal_min,cal_max:t.cal_max,trustCalMinMax:this.opts.trustCalMinMax,isManifest:t.isManifest,frame4D:t.frame4D,limitFrames4D:t.limitFrames4D||this.opts.limitFrames4D,colorbarVisible:t.colorbarVisible,zarrLevel:t.zarrLevel,zarrMaxVolumeSize:t.zarrMaxVolumeSize,zarrChannel:t.zarrChannel,zarrConvertUnits:t.zarrConvertUnits,zarrCenterMM:t.zarrCenterMM},n=await Gi.loadFromUrl(i);return this.document.addImageOptions(n,i),n.onColormapChange=this.onColormapChange,this.mediaUrlMap.set(n,i.url),this._emitEvent("volumeAddedFromUrl",{imageOptions:i,volume:n}),this.onVolumeAddedFromUrl&&this.onVolumeAddedFromUrl(i,n),n})),i=await Promise.all(e);for(let n=0;n<i.length;n++)this.addVolume(i[n]);return i}getMediaByUrl(t){return Ar(t,this.mediaUrlMap)}removeVolumeByUrl(t){const e=this.getMediaByUrl(t);if(!e)throw new Error("No volume with URL present");this.removeVolume(e)}async traverseFileTree(t,e,i){return void 0===e&&(e=""),wr(t,e,i)}readDirectory(t){return yr(t)}isMeshExt(t){return gr(t)}async loadFromArrayBuffer(t,e){const i=this.getFileExt(e);
1if(ss.includes(i))return void await this.addMeshFromUrl({url:e,buffer:t});const n=Ue(e);n.buffer=t,n.name=e,await this.addVolumeFromUrl(n)}async loadFromFile(t){const e=this.getFileExt(t.name);ss.includes(e)?await Te.loadFromFile({file:t,gl:this.gl,name:t.name}).then((t=>{this.addMesh(t)})):await Gi.loadFromFile({file:t,name:t.name}).then((t=>{this.addVolume(t)}))}useLoader(t,e,i){this.loaders=pr({loaders:this.loaders,loader:t,fileExt:e,toExt:i})}useDicomLoader(t){this.dicomLoader=t}getDicomLoader(){return this.dicomLoader}async dropListener(t){if(!this.eventInBounds(t))return void(this.opts.showBoundsBorder=!1);if(this.opts.bounds&&(this.opts.showBoundsBorder=!0),t.stopPropagation(),t.preventDefault(),!this.opts.dragAndDropEnabled)return;const e=t.dataTransfer;if(!e)return;const i=e.getData("text/uri-list")||null;i?await this.handleUrlDrop(i):function(t){return t.items.length>0}(e)&&await this.handleFilesDrop(e.items,t.shiftKey,t.altKey),this.drawScene()}async handleUrlDrop(t){const e=this.getFileExt(t);Q.debug("dropped ext:",e);switch(ga(e)){case"mesh":await this.addMeshFromUrl({url:t});break;case"document":await this.loadDocumentFromUrl(t);break;default:await this.addVolumeFromUrl(Ue(t))}}async handleFilesDrop(t,e,i){e||i||(this.volumes=[],this.overlays=[],this.meshes=[]),this.closeDrawing(),this.closePAQD();const n=function(t){const e=[];for(const n of Array.from(t)){const r=n.webkitGetAsEntry();if(r){if(r.isFile){if(-1!==(i=r.name).lastIndexOf("BRIK")||-1!==i.toUpperCase().lastIndexOf("IMG"))continue;const n=Aa(r,t);e.push({entry:r,pairedEntry:n})}}else Q.warn("could not get entry from dropped item")}var i;return e}(t);for(const{entry:a,pairedEntry:s}of n)await this.handleFileEntry(a,s,i);const r=function(t){const e=[];for(const i of Array.from(t)){const t=i.webkitGetAsEntry();t?.isDirectory&&e.push(t)}return e}(t);for(const a of r)await this.handleDirectoryDrop(a)}async handleFileEntry(t,e,i){const n=this.getFileExt(t.name);if(this.loaders[n]){const e=await(r=t,new Promise(((t,e)=>{let i;i=r instanceof File?Promise.resolve(r):new Promise(((t,e)=>{r.file(t,e)})),i.then((i=>{const n=new FileReader;n.onload=()=>{"string"==typeof n.result?t(n.result):e(new Error("Expected a string from FileReader.result"))},n.onerror=()=>{e(n.error??new Error("Unknown FileReader error"))},n.readAsDataURL(i)})).catch((t=>e(t)))})));return void await this.loadImages([{url:e,name:t.name}])}var r;const a=await pa(t);switch(ga(n)){case"mesh":await this.handleMeshFileDrop(a);break;case"document":await this.handleDocumentFileDrop(a);break;default:await this.handleVolumeFileDrop(a,e,i)}}async handleMeshFileDrop(t){try{const e=await Te.loadFromFile({file:t,gl:this.gl,name:t.name});this.addMesh(e)}catch(e){console.error("Error loading mesh:",e)}}async handleDocumentFileDrop(t){try{const e=await hn.loadFromFile(t);await this.loadDocument(e),Q.debug("loaded document")}catch(e){console.error("Error loading document:",e)}}async handleVolumeFileDrop(t,e,i){try{let n;e&&(n=await pa(e));const r=await Gi.loadFromFile({file:t,urlImgData:n,limitFrames4D:this.opts.limitFrames4D});i?(Q.debug("alt key detected: assuming this is a drawing overlay"),this.drawClearAllUndoBitmaps(),this.loadDrawing(r)):this.addVolume(r)}catch(n){console.error("Error loading volume:",n)}}async handleDirectoryDrop(t){try{const e=await this.traverseFileTree(t,"",[]),i=this.getDicomLoader().loader;if(!i)throw new Error("No loader for DICOM files");const n=(await i(e)).map((t=>Gi.loadFromUrl({url:t.data,name:t.name,limitFrames4D:this.opts.limitFrames4D}))),r=await Promise.all(n);this._emitEvent("dicomLoaderFinished",{files:r}),await this.onDicomLoaderFinishedWithImages(r)}catch(e){console.error("Error loading DICOM files:",e)}}setMultiplanarPadPixels(t){this.opts.multiplanarPadPixels=t,this.drawScene()}setMultiplanarLayout(t){"string"==typeof t&&(t=parseInt(t)),this.opts.multiplanarLayout=t,this.drawScene()}setCornerOrientationText(t){this.opts.isCornerOrientationText=t,this.updateGLVolume()}setIsOrientationTextVisible(t){this.opts.isOrientationTextVisible=t,this.drawScene()}setShowAllOrientationMarkers(t){this.opts.showAllOrientationMarkers=t,this.drawScene()}setHeroImage(t){this.opts.heroImageFraction=t,this.drawScene()}setCustomLayout(t){const e=function(t){const{layout:e}=t;for(let i=0;i<e.length;i++){const[t,n,r,a]=e[i].position,s=t+r,o=n+a;for(let l=i+1;l<e.length;l++){const[r,a,c,h]=e[l].position;if(t<r+c&&s>r&&n<a+h&&o>
1a)return{valid:!1,error:`Custom layout is invalid. Tile ${i} overlaps with tile ${l}.`,overlappingTiles:[i,l]}}}return{valid:!0}}({layout:t});if(!e.valid&&e.error)throw new Error(e.error);this.customLayout=t,this.drawScene()}clearCustomLayout(){this.customLayout=null,this.drawScene()}getCustomLayout(){return this.customLayout}setRadiologicalConvention(t){this.opts.isRadiologicalConvention=t,this.updateGLVolume()}setDefaults(t,e){void 0===t&&(t={}),void 0===e&&(e=!1),this.document.opts={...ln},this.scene.sceneData={...cn};for(const i in t)"function"==typeof t[i]?this[i]=t[i]:this.opts[i]=void 0===ln[i]?ln[i]:t[i];if(this.scene.pan2Dxyzmm=[0,0,0,1],e&&this.volumes&&this.volumes.length>0)for(let i=0;i<this.volumes.length;i++)this.volumes[i].cal_min=this.volumes[i].robust_min,this.volumes[i].cal_max=this.volumes[i].robust_max;this.updateGLVolume()}setMeshThicknessOn2D(t){this.opts.meshThicknessOn2D=t,this.updateGLVolume()}setSliceMosaicString(t){this.sliceMosaicString=t,this.updateGLVolume()}setSliceMM(t){this.opts.isSliceMM=t,this.updateGLVolume()}setAdditiveBlend(t){this.opts.isAdditiveBlend=t,this.updateGLVolume()}getRadiologicalConvention(){return this.opts.isRadiologicalConvention}setHighResolutionCapable(t){"boolean"==typeof t&&(t=t?0:-1),this.opts.forceDevicePixelRatio=t,this.resizeListener(),this.drawScene()}watchOptsChanges(t){this.onOptsChange=t}unwatchOptsChanges(){this.onOptsChange=()=>{}}addVolume(t){const e=function(t,e){const i=[...t,e];return{volumes:i,index:1===i.length?0:i.length-1}}(this.volumes,t);if(this.volumes=e.volumes,this.setVolume(t,e.index),this._emitEvent("imageLoaded",t),this.onImageLoaded(t),t.zarrHelper){if(!t._hasExplicitZarrCenter&&this.back&&this.back!==t&&this.back.hdr?.dims){const e=this.back,i=e.hdr.dims,n=e.hdr.affine,r=(i[1]-1)/2,a=(i[2]-1)/2,s=(i[3]-1)/2,o=[n[0][0]*r+n[0][1]*a+n[0][2]*s+n[0][3],n[1][0]*r+n[1][1]*a+n[1][2]*s+n[1][3],n[2][0]*r+n[2][1]*a+n[2][2]*s+n[2][3]];t.zarrHelper.setWorldCenter(o)}t.zarrHelper.onChunksUpdated=()=>{this.updateGLVolume(),this._skipDragInDraw=!0,this.drawScene(),this._skipDragInDraw=!1},t.zarrHelper.loadInitialChunks().catch((t=>Q.error("Failed to load initial zarr chunks",t)))}Q.debug("loaded volume",t.name),Q.debug(t)}addMesh(t){const e=function(t,e){const i=[...t,e];return{meshes:i,index:1===i.length?0:i.length-1}}(this.meshes,t);this.meshes=e.meshes,this.setMesh(t,e.index),this._emitEvent("meshLoaded",t),this.onMeshLoaded(t)}getVolumeIndexByID(t){return rr(this.volumes,t)}drawAddUndoBitmap(t){void 0===t&&(t=!0);const e=Ua({drawBitmap:this.drawBitmap,drawUndoBitmaps:this.drawUndoBitmaps,currentDrawUndoBitmap:this.currentDrawUndoBitmap,maxDrawUndoBitmaps:this.opts.maxDrawUndoBitmaps,drawFillOverwrites:t});this.drawBitmap=e.drawBitmap,this.drawUndoBitmaps=e.drawUndoBitmaps,this.currentDrawUndoBitmap=e.currentDrawUndoBitmap,e.needsRefresh&&this.refreshDrawing(!1)}drawClearAllUndoBitmaps(){const t=function(t,e){const i=[...t],n=e;if(!i||i.length<1)return{drawUndoBitmaps:i,currentDrawUndoBitmap:n};for(let r=i.length-1;r>=0;r--)i[r]=new Uint8Array;return{drawUndoBitmaps:i,currentDrawUndoBitmap:n}}(this.drawUndoBitmaps,this.opts.maxDrawUndoBitmaps);this.drawUndoBitmaps=t.drawUndoBitmaps,this.currentDrawUndoBitmap=t.currentDrawUndoBitmap}drawUndo(){const{drawBitmap:t,currentDrawUndoBitmap:e}=(t=>{let{drawUndoBitmaps:e,currentDrawUndoBitmap:i,drawBitmap:n}=t;const r=e.length;if(r<1)Q.debug("undo bitmaps not loaded");else{if(i--,i<0&&(i=r-1),i>=r&&(i=0),!(e[i].length<2))return n=Da(e[i],n.length),{drawBitmap:n,currentDrawUndoBitmap:i};Q.debug("drawUndo is misbehaving")}})({drawUndoBitmaps:this.drawUndoBitmaps,currentDrawUndoBitmap:this.currentDrawUndoBitmap,drawBitmap:this.drawBitmap});this.drawBitmap=t,this.currentDrawUndoBitmap=e,this.refreshDrawing(!0),this._emitEvent("drawingChanged",{action:"undo"}),this.onDrawingChanged("undo")}loadDrawing(t){if(this.drawBitmap&&Q.debug("Overwriting open drawing!"),!this.back)throw new Error("back undefined");this.drawClearAllUndoBitmaps();const e=t.hdr.dims;if(!function(t){const{drawingDims:e,backgroundDims:i}=t;return e[1]===i[1]&&e[2]===i[2]&&e[3]===i[3]}({drawingDims:e,backgroundDims:this.back.hdr.dims}))return Q.debug("drawing dimensions do not match background image"),!1;t.img.constructor!==Uint8Array&&Q.debug("Drawings should be UINT8");const i=t.permRAS,n=Pa(e);this.drawBitmap=Na(n),this.opts.is2DSliceShader?this.drawTexture=this.r8Tex2D(this.drawTexture,R,this.back.dims,!0):this.drawTexture=this.r8Tex(this.drawTexture,R,this.back.dims,!0);const r=function(t){const{permRAS:e,dims:i}=t,n=[0,0,0];for(let o=0;o<3;o++)for(let t=0;t<3;t++)Math.abs(e[o])-1===t&&(n[t]=o*Math.sign(e[o]));let r=1;
1const a=[1,1,1],s=[!1,!1,!1];for(let o=0;o<n.length;o++)for(let t=0;t<n.length;t++)Math.abs(n[t])===o&&(a[t]=r,(n[t]<0||Object.is(n[t],-0))&&(s[t]=!0),r*=i[t+1]);return{instride:a,inflip:s,xlut:Ra(i[1],a[0],s[0]),ylut:Ra(i[2],a[1],s[1]),zlut:Ra(i[3],a[2],s[2])}}({permRAS:i,dims:e});return this.drawBitmap=function(t){const{inputData:e,dims:i,xlut:n,ylut:r,zlut:a}=t,s=i[1]*i[2]*i[3],o=new Uint8Array(s);let l=0;for(let c=0;c<i[3];c++)for(let t=0;t<i[2];t++)for(let s=0;s<i[1];s++)o[n[s]+r[t]+a[c]]=e[l],l++;return o}({inputData:t.img,dims:e,xlut:r.xlut,ylut:r.ylut,zlut:r.zlut}),this.drawAddUndoBitmap(),this.refreshDrawing(!1),this._emitEvent("drawingChanged",{action:"load"}),this.onDrawingChanged("load"),this.drawScene(),!0}binarize(t){const e=function(t){const{img:e,dims:i}=t,n=i[1]*i[2]*i[3],r=new Uint8Array(n);for(let a=0;a<n;a++)0!==e[a]&&(r[a]=1);return{img:r,datatypeCode:2,cal_min:0,cal_max:1}}({img:t.img,dims:t.hdr.dims});t.img=e.img,t.hdr.datatypeCode=e.datatypeCode,t.hdr.cal_min=e.cal_min,t.hdr.cal_max=e.cal_max}async loadDrawingFromUrl(t,e){void 0===e&&(e=!1),this.drawBitmap&&Q.debug("Overwriting open drawing!"),this.drawClearAllUndoBitmaps();let i=!1;try{const n=await Gi.loadFromUrl(Ue(t));e&&await this.binarize(n),i=this.loadDrawing(n)}catch(n){Q.error("loadDrawingFromUrl() failed to load "+t),this.drawClearAllUndoBitmaps()}return i}findOtsu(t){return void 0===t&&(t=2),this.volumes.length<1?[]:function(t){const{img:e,cal_min:i,cal_max:n,scl_inter:r,scl_slope:a,mlevel:s=2}=t,o=e.length;if(o<1)return[];const l=256,c=new Array(l).fill(0),h=i,d=n;if(d<=h)return[];const u=(d-h)/l;function m(t){return t*u+h}const f=255/Math.abs(d-h);for(let x=0;x<o;x++){let t=e[x]*a+r;t=Math.min(Math.max(t,h),d),t=Math.round((t-h)*f),c[t]++}const g=Array(l).fill(0).map((()=>Array(l).fill(0))),A=Array(l).fill(0).map((()=>Array(l).fill(0)));for(let x=1;x<l;++x)g[x][x]=c[x],A[x][x]=x*c[x];for(let x=1;x<255;++x)g[1][x+1]=g[1][x]+c[x+1],A[1][x+1]=A[1][x]+(x+1)*c[x+1];for(let x=2;x<l;x++)for(let t=x+1;t<l;t++)g[x][t]=g[1][t]-g[1][x-1],A[x][t]=A[1][t]-A[1][x-1];for(let x=1;x<l;++x)for(let t=x+1;t<l;t++)0!==g[x][t]&&(g[x][t]=A[x][t]*A[x][t]/g[x][t]);let p=0;const v=[1/0,1/0,1/0];if(s>3)for(let x=0;x<253;x++)for(let t=x+1;t<254;t++)for(let e=t+1;e<255;e++){const i=g[0][x]+g[x+1][t]+g[t+1][e]+g[e+1][255];i>p&&(v[0]=x,v[1]=t,v[2]=e,p=i)}else if(3===s)for(let x=0;x<254;x++)for(let t=x+1;t<255;t++){const e=g[0][x]+g[x+1][t]+g[t+1][255];e>p&&(v[0]=x,v[1]=t,p=e)}else for(let x=0;x<255;x++){const t=g[0][x]+g[x+1][255];t>p&&(v[0]=x,p=t)}return[m(v[0]),m(v[1]),m(v[2])]}({img:this.volumes[0].img,cal_min:this.volumes[0].cal_min,cal_max:this.volumes[0].cal_max,scl_inter:this.volumes[0].hdr.scl_inter,scl_slope:this.volumes[0].hdr.scl_slope,mlevel:t})}drawOtsu(t){if(void 0===t&&(t=2),0===this.volumes.length)return;const e=this.findOtsu(t);if(e.length<3)return;this.drawBitmap||this.createEmptyDrawing();const i=function(t){const{img:e,drawBitmap:i,thresholds:n}=t,r=e.length,a=new Uint8Array(i);for(let s=0;s<r;s++){if(0!==a[s])continue;const t=e[s];t>n[0]&&(a[s]=1),t>n[1]&&(a[s]=2),t>n[2]&&(a[s]=3)}return a}({img:this.volumes[0].img2RAS(),drawBitmap:this.drawBitmap,thresholds:e});this.drawBitmap.set(i),this.drawAddUndoBitmap(),this.refreshDrawing(!0)}removeHaze(t,e){void 0===t&&(t=5),void 0===e&&(e=0);const i=this.volumes[e].img,n=this.volumes[e].hdr,r=function(t){const{level:e}=t;return 5===e||1===e?4:4===e||2===e?3:2}({level:t}),a=this.findOtsu(r);if(a.length<3)return;const s=function(t){const{level:e,thresholds:i}=t;return 1===e?i[2]:2===e?i[1]:i[0]}({level:t,thresholds:a});!function(t){const{img:e,scl_inter:i,scl_slope:n,global_min:r,threshold:a}=t,s=e.length;for(let o=0;o<s;o++)e[o]*n+i<a&&(e[o]=r)}({img:i,scl_inter:n.scl_inter,scl_slope:n.scl_slope,global_min:this.volumes[e].global_min,threshold:s}),this.refreshLayers(this.volumes[e],0),this.drawScene()}async saveImage(t){void 0===t&&(t=hs);const e={...hs,...t},{filename:i,isSaveDrawing:n,volumeByIndex:r}=e;if(Q.debug("saveImage",i,n,r),void 0===this.back?.dims)return Q.debug("No voxelwise image open"),!1;if(n){if(!this.drawBitmap)return Q.debug("No drawing open"),!1;return await this.volumes[0].saveToDisk(i,this.drawBitmap)}Q.debug("saving image");return this.volumes[r].saveToDisk(i)}getMeshIndexByID(t){return cr(this.meshes,t)}setMeshProperty(t,e,i){const n=function(t){const{meshes:e,id:i,key:n,val:r,gl:a}=t,s=cr(e,i);return s<0?(Q.warn("setMeshProperty() id not loaded",i),-1):(e[s].setProperty(n,r,a),s)}({meshes:this.meshes,id:t,key:e,val:i,gl:this.gl});n<0||(this.updateGLVolume(),this._emitEvent("meshPropertyChanged",{meshIndex:n,key:e,value:i}),this.onMeshPropertyChanged(n,e,i))}indexNearestXYZmm(t,e,i,n){return function(t){const{meshes:e,meshId:i,Xmm:n,Ymm:r,Zmm:a}=t,s=cr(e,i);return s<0?(Q.warn("indexNearestXYZmm() id not loaded",i),[NaN,NaN]):e[s].indexNearestXYZmm(n,r,a)}({meshes:this.meshes,meshId:t,Xmm:e,Ymm:i,Zmm:n})}decimateHierarchicalMesh(t,e){void 0===e&&(e=3);const i=function(t){const{meshes:e,meshId:i,gl:n,order:r=3}=t,a=cr(e,i);return a<0?(Q.warn("decimateHierarchicalMesh() id not loaded",i),!1):e[a].decimateHierarchicalMesh(n,r)}({meshes:this.meshes,meshId:t,gl:this.gl,order:e});return i&&this.updateGLVolume(),i}reverseFaces(t){(function(t){const{meshes:e,meshId:i,gl:n}=t,r=cr(e,i);return r<0?(Q.warn("reverseFaces() id not loaded",i),!1):(e[r].reverseFaces(n),!0)})({meshes:this.meshes,meshId:t,gl:this.gl})&&this.updateGLVolume()}async setMeshLayerProperty(t,e,i,n){const r=await async function(t){const{meshes:e,meshId:i,layer:n,key:r,val:a,gl:s}=t,o=cr(e,i);return o<0?(Q.warn("setMeshLayerProperty() id not loaded",i),!1):(await e[o].setLayerProperty(n,r,a,s),!0)}
1({meshes:this.meshes,meshId:t,layer:e,key:i,val:n,gl:this.gl});r&&this.updateGLVolume()}setPan2Dxyzmm(t){this.scene.pan2Dxyzmm=t,this.opts.yoke3Dto2DZoom&&(this.scene.volScaleMultiplier=t[3]),this.drawScene()}setRenderAzimuthElevation(t,e){this.scene.renderAzimuth=t,this.scene.renderElevation=e,this._emitEvent("azimuthElevationChange",{azimuth:t,elevation:e}),this.onAzimuthElevationChange(t,e),this.drawScene()}getOverlayIndexByID(t){return function(t,e){const i=t.slice(1);for(let n=0;n<i.length;n++)if(i[n].id===e)return n;return-1}(this.volumes,t)}setVolume(t,e){void 0===e&&(e=0);const i=ar(this.volumes,t,e);this.volumes=i.volumes,this.back=i.back,this.overlays=i.overlays,this.updateGLVolume()}setMesh(t,e){void 0===e&&(e=0),this.meshes.forEach((t=>{Q.debug("MESH: ",t.name)}));const i=function(t,e,i){if(void 0===i&&(i=0),i>t.length)return{meshes:t};const n=cr(t,e.id);if(n<0)return{meshes:t};const r=[...t];return 0===i?(r.splice(n,1),r.unshift(e)):i<0?r.splice(n,1):(r.splice(n,1),r.splice(i,0,e)),{meshes:r}}(this.meshes,t,e);this.meshes=i.meshes,this.updateGLVolume(),this.meshes.forEach((t=>{Q.debug(t.name)}))}removeVolume(t){const e=this.volumes.indexOf(t),i=sr(this.volumes,t);if(this.volumes=i.volumes,this.back=this.volumes.length>0?this.volumes[0]:null,this.overlays=this.volumes.slice(1),this._emitEvent("volumeRemoved",{volume:t,index:e}),this.onVolumeRemoved(t,e),this.mediaUrlMap.has(t)){const e=this.mediaUrlMap.get(t);this._emitEvent("volumeWithUrlRemoved",{url:e}),this.onVolumeWithUrlRemoved(e),this.mediaUrlMap.delete(t)}this.updateGLVolume(),this.drawScene()}removeVolumeByIndex(t){const e=function(t,e){if(e>=t.length)throw new Error("Index of volume out of bounds");return sr(t,t[e])}(this.volumes,t);e.removed&&this.removeVolume(e.removed)}removeMesh(t){if(this._emitEvent("meshRemoved",{mesh:t}),this.onMeshRemoved(t),t.unloadMesh(this.gl),this.setMesh(t,-1),this.mediaUrlMap.has(t)){const e=this.mediaUrlMap.get(t);this._emitEvent("meshWithUrlRemoved",{url:e}),this.onMeshWithUrlRemoved(e),this.mediaUrlMap.delete(t)}}removeMeshByUrl(t){const e=this.getMediaByUrl(t);e&&(this.removeMesh(e),this.mediaUrlMap.delete(e),this._emitEvent("meshWithUrlRemoved",{url:t}),this.onMeshWithUrlRemoved(t))}moveVolumeToBottom(t){const e=function(t,e){return ar(t,e,0)}(this.volumes,t);this.volumes=e.volumes,this.back=e.back,this.overlays=e.overlays,this.updateGLVolume(),this._emitEvent("volumeOrderChanged",{volumes:this.volumes}),this.onVolumeOrderChanged(this.volumes)}moveVolumeUp(t){const e=function(t,e){return ar(t,e,rr(t,e.id)+1)}(this.volumes,t);this.volumes=e.volumes,this.back=e.back,this.overlays=e.overlays,this.updateGLVolume(),this._emitEvent("volumeOrderChanged",{volumes:this.volumes}),this.onVolumeOrderChanged(this.volumes)}moveVolumeDown(t){const e=function(t,e){return ar(t,e,rr(t,e.id)-1)}(this.volumes,t);this.volumes=e.volumes,this.back=e.back,this.overlays=e.overlays,this.updateGLVolume(),this._emitEvent("volumeOrderChanged",{volumes:this.volumes}),this.onVolumeOrderChanged(this.volumes)}moveVolumeToTop(t){const e=function(t,e){return ar(t,e,t.length-1)}(this.volumes,t);this.volumes=e.volumes,this.back=e.back,this.overlays=e.overlays,this.updateGLVolume(),this._emitEvent("volumeOrderChanged",{volumes:this.volumes}),this.onVolumeOrderChanged(this.volumes)}mouseDown(t,e){const i=Jr({x:t,y:e,dpr:this.uiData.dpr});this.mousePos=i.mousePos}updateMousePos(t,e){const i=Jr({x:t,y:e,dpr:this.uiData.dpr});return this.mousePos=i.mousePos,i.mousePos}mouseMove(t,e){const i=_r({x:t,y:e,dpr:this.uiData.dpr,currentMousePos:this.mousePos});if(this.mousePos=i.mousePos,this.inRenderTile(i.scaledX,i.scaledY)<0)return;if(!function(t){const{dx:e,dy:i,threshold:n=1}=t;return Math.abs(e)>=n||Math.abs(i)>=n}({dx:i.dx,dy:i.dy}))return;const n=function(t){const{currentAzimuth:e,currentElevation:i,deltaX:n,deltaY:r}=t;return{azimuth:function(t){let e=t%360;return e<0&&(e+=360),e}(e+n),elevation:i+r}}({currentAzimuth:this.scene.renderAzimuth,currentElevation:this.scene.renderElevation,deltaX:i.dx,deltaY:i.dy});this.scene.renderAzimuth===n.azimuth&&this.scene.renderElevation===n.elevation||this.setRenderAzimuthElevation(n.azimuth,n.elevation)}sph2cartDeg(t,e){return Ir(t,e)}setClipPlanes(t){const e=function(t){const{depthAziElevs:e}=t,i=[],n=[];for(const r of e){const t=Ca({depth:r[0],azimuth:r[1],elevation:r[2]});i.push(t),n.push([...r])}return{clipPlanes:i,clipPlaneDepthAziElevs:n}}({depthAziElevs:t});this.scene.clipPlanes=e.clipPlanes,this.scene.clipPlaneDepthAziElevs=e.clipPlaneDepthAziElevs,this.drawScene()}setClipPlane(t){if(!function(t){return!!t&&t.length>0}(t))return;const e=this.uiData.activeClipPlaneIndex??0,i=Ma({clipPlanes:this.scene.clipPlanes,clipPlaneDepthAziElevs:this.scene.clipPlaneDepthAziElevs,index:e,depthAzimuthElevation:t});this.scene.clipPlanes=i.clipPlanes,this.scene.clipPlaneDepthAziElevs=i.clipPlaneDepthAziElevs,this._emitEvent("clipPlaneChange",{clipPlane:i.clipPlane}),this.onClipPlaneChange(i.clipPlane),this.drawScene()}setCrosshairColor(t){this.opts.crosshairColor=t,this.drawScene()}setCrosshairWidth(t){this.opts.crosshairWidth=t,this.crosshairs3D&&(this.crosshairs3D.mm[0]=NaN),this.drawScene()}setDrawColormap(t){this.drawLut=ve.makeDrawLut(t),this.updateGLVolume()}setDrawingEnabled(t){if(this.opts.drawingEnabled=t,this._emitEvent("drawingEnabled",{enabled:t}),this.onDrawingEnabled(t),this.opts.drawingEnabled)this.drawBitmap||this.createEmptyDrawing();else{const t=function(t){const{clickToSegmentIsGrowing:e,drawShapePreviewBitmap:i,drawBitmap:n}=t;let r=n,a=!1;return e&&(a=!0),i&&(r=i),{clickToSegmentIsGrowing:!1,drawPenLocation:[NaN,NaN,NaN],drawPenAxCorSag:-1,drawPenFillPts:[],drawShapeStartLocation:[NaN,NaN,NaN],drawShapePreviewBitmap:null,drawBitmap:r,needsRefresh:a}}({clickToSegmentIsGrowing:this.clickToSegmentIsGrowing,drawPenLocation:this.drawPenLocation,drawPenAxCorSag:this.drawPenAxCorSag,drawPenFillPts:this.drawPenFillPts,drawShapeStartLocation:this.drawShapeStartLocation,drawShapePreviewBitmap:this.drawShapePreviewBitmap,drawBitmap:this.drawBitmap});this.clickToSegmentIsGrowing=t.clickToSegmentIsGrowing,this.drawPenLocation=t.drawPenLocation,this.drawPenAxCorSag=t.drawPenAxCorSag,this.drawPenFillPts=t.drawPenFillPts,this.drawShapeStartLocation=t.drawShapeStartLocation,this.drawShapePreviewBitmap=t.drawShapePreviewBitmap,this.drawBitmap=t.drawBitmap,t.needsRefresh&&this.refreshDrawing(!0,!1);const e=this._deriveDrawingTool(this.opts.penValue);this._emitEvent("drawingToolChanged",{tool:e,penValue:this.opts.penValue,isFilledPen:this.opts.isFilledPen}),this.onDrawingToolChanged(e,this.opts.penValue,this.opts.isFilledPen)}this.drawScene()}setPenValue(t,e){void 0===e&&(e=!1),this.opts.penValue=t,this.opts.isFilledPen=e,this._emitEvent("penValueChanged",{penValue:t,
1isFilledPen:e}),this.onPenValueChanged(t,e);const i=this._deriveDrawingTool(t);this._emitEvent("drawingToolChanged",{tool:i,penValue:t,isFilledPen:e}),this.onDrawingToolChanged(i,t,e),this.drawScene()}_deriveDrawingTool(t){return this.opts.drawingEnabled?this.opts.clickToSegment?"clickToSegment":Object.is(t,-0)?"eraseCluster":isNaN(t)?"growCluster":t===Number.POSITIVE_INFINITY?"growClusterBright":t===Number.NEGATIVE_INFINITY?"growClusterDark":0===t?"erase":"draw":"off"}setDrawOpacity(t){this.drawOpacity=t,this.drawScene()}setSelectionBoxColor(t){this.opts.selectionBoxColor=t}setBounds(t){if(!Array.isArray(t)||4!==t.length)throw new Error("setBounds: expected [x1,y1,x2,y2] array");this.opts.bounds=[[t[0],t[1]],[t[2],t[3]]],this.gl&&this.drawScene()}sliceScroll2D(t,e,i,n){if(void 0===n&&(n=!0),!function(t){const{scrollRequiresFocus:e,canvasHasFocus:i}=t;return!e||i}({scrollRequiresFocus:this.opts.scrollRequiresFocus,canvasHasFocus:this.canvas===document.activeElement}))return void Q.warn("Canvas element does not have focus. Scroll events will not be processed.");if(this.inGraphTile(e,i)){let e=this.volumes[0].frame4D;return t>0&&e++,t<0&&e--,void this.setFrame4D(this.volumes[0].id,e)}const r=-1!==this.inRenderTile(this.uiData.dpr*e,this.uiData.dpr*i);if(function(t){const{posChange:e,dragMode:i,isInRenderTile:n}=t;return 0!==e&&3===i&&!n}({posChange:t,dragMode:this.opts.dragMode,isInRenderTile:r})){const e=this.frac2mm(this.scene.crosshairPos),i=function(t){const{posChange:e,currentZoom:i,yoke3Dto2DZoom:n,crosshairMM:r}=t;let a=i*(1+10*e);a=Math.round(10*a)/10;const s=i-a;return{newZoom:a,zoomChange:s,panOffsetX:s*r[0],panOffsetY:s*r[1],panOffsetZ:s*r[2],newVolScaleMultiplier:n?a:void 0}}({posChange:t,currentZoom:this.scene.pan2Dxyzmm[3],yoke3Dto2DZoom:this.opts.yoke3Dto2DZoom,crosshairMM:e});return void 0!==i.newVolScaleMultiplier&&(this.scene.volScaleMultiplier=i.newVolScaleMultiplier),this.scene.pan2Dxyzmm[3]=i.newZoom,this.scene.pan2Dxyzmm[0]+=i.panOffsetX,this.scene.pan2Dxyzmm[1]+=i.panOffsetY,this.scene.pan2Dxyzmm[2]+=i.panOffsetZ,this.drawScene(),this.canvas.focus(),void this.sync()}this.mouseClick(e,i,t,n)}setSliceType(t){return this.opts.sliceType=t,this._emitEvent("sliceTypeChange",{sliceType:t}),this.onSliceTypeChange(t),this.drawScene(),this}setOpacity(t,e){!function(t,e,i){t[e].opacity=i}(this.volumes,t,e),this.updateGLVolume()}getVolumeAffine(t){if(t<0||t>=this.volumes.length)throw new Error(`Volume index ${t} out of range`);return this.volumes[t].getAffine()}setVolumeAffine(t,e){if(t<0||t>=this.volumes.length)throw new Error(`Volume index ${t} out of range`);this.volumes[t].setAffine(e),this.updateGLVolume()}applyVolumeTransform(t,e){if(t<0||t>=this.volumes.length)throw new Error(`Volume index ${t} out of range`);this.volumes[t].applyTransform(e),this.updateGLVolume()}resetVolumeAffine(t){if(t<0||t>=this.volumes.length)throw new Error(`Volume index ${t} out of range`);this.volumes[t].resetAffine(),this.updateGLVolume()}setScale(t){this.scene.volScaleMultiplier=t,this.drawScene()}setClipPlaneColor(t){this.opts.clipPlaneColor=t,this.renderShader.use(this.gl),this.gl.uniform4fv(this.renderShader.uniforms.clipPlaneColor,this.opts.clipPlaneColor),this.drawScene()}setClipPlaneThick(t){Q.warn("setClipPlaneThick() has been removed. use setClipPlanes() instead.")}setClipVolume(t,e){Q.warn("setClipVolume() has been removed. use setClipPlanes() instead.")}async setVolumeRenderIllumination(t){void 0===t&&(t=0),this.renderGradientValues=Number.isNaN(t),this.renderShader=this.renderVolumeShader,this.renderGradientValues?this.renderShader=this.renderGradientValuesShader:(this.opts.gradientAmount=t,t>0||this.opts.gradientOpacity>0?this.renderShader=this.renderGradientShader:t<0&&(this.renderShader=this.renderSliceShader)),this.initRenderShader(this.renderShader,t),this.renderShader.use(this.gl),this.setClipPlaneColor(this.opts.clipPlaneColor),Number.isNaN(t)?this.gradientTextureAmount=1:this.gradientTextureAmount=t,this.volumes.length<1||(await this.refreshLayers(this.volumes[0],0),this.drawScene())}async setGradientOpacity(t,e){void 0===t&&(t=0),void 0===e&&(e=0),this.opts.gradientOpacity=t,this.opts.renderSilhouette=e,this.renderGradientValues?this.renderShader=this.renderGradientValuesShader:this.gradientTextureAmount>0||t>0?this.renderShader=this.renderGradientShader:this.gradientTextureAmount<0&&(this.renderShader=this.renderSliceShader),this.initRenderShader(this.renderShader,this.gradientTextureAmount),this.renderShader.use(this.gl),this.gradientTextureAmount>0&&this.refreshLayers(this.volumes[0],0),this.drawScene()}overlayRGBA(t){return function(t){const e=t.hdr,i=e.dims[1]*e.dims[2]*e.dims[3],n=new Uint8ClampedArray(4*i),r=.2*Math.min(Math.min(e.dims[1],e.dims[2]),e.dims[3]),a=.5*e.dims[1],s=.5*e.dims[2],o=.5*e.dims[3];let l=0;for(let c=0;c<e.dims[3];c++)for(let t=0;t<e.dims[2];t++)for(let i=0;i<e.dims[1];i++){const e=Math.abs(i-a),h=Math.abs(t-s),d=Math.abs(c-o);let u=0;Math.sqrt(e*e+h*h+d*d)<r&&(u=255),n[l++]=0,n[l++]=u,n[l++]=0,n[l++]=.5*u}return n}(t)}vox2mm(t,e){return function(t,e){return ye.vox2mm(t,e)}(t,e)}cloneVolume(t){return function(t,e){return t[e].clone()}(this.volumes,t)}async loadDocumentFromUrl(t){const e=await hn.loadFromUrl(t);await this.loadDocument(e)}async loadDocument(t){try{if(!t)throw new Error("loadDocument called with fal
1sy document");if(!t.scene||"object"!=typeof t.scene){const e=new hn;t.scene=e.scene}t.scene.sceneData={...cn,...t.scene.sceneData||{}},t.scene.sceneData.pan2Dxyzmm||(t.scene.sceneData.pan2Dxyzmm=n.fA(0,0,0,1)),t.scene.sceneData.crosshairPos||(t.scene.sceneData.crosshairPos=r.fA(.5,.5,.5)),t.data={...t.data||{},imageOptionsArray:t.data?.imageOptionsArray??[],encodedImageBlobs:t.data?.encodedImageBlobs??[],labels:t.data?.labels??[],meshOptionsArray:t.data?.meshOptionsArray??[],connectomes:t.data?.connectomes??[],encodedDrawingBlob:t.data?.encodedDrawingBlob??"",previewImageDataURL:t.data?.previewImageDataURL??"",customData:t.data?.customData??"",title:t.data?.title??t.title??"untitled"}}catch(a){console.warn("loadDocument: defensive initialization failed",a)}this.volumes=[],this.meshes=[],this.document=t,this.document.labels=this.document.labels?this.document.labels:[];const e={...ln,...t.opts||{}};this.scene.pan2Dxyzmm=t.scene.sceneData?.pan2Dxyzmm??[0,0,0,1],this.document.opts=e,this.scene.clipPlaneDepthAziElevs&&this.setClipPlane(this.scene.clipPlaneDepthAziElevs[this.uiData.activeClipPlaneIndex??0]),Q.debug("load document",t),this.mediaUrlMap.clear(),this.createEmptyDrawing();try{const e=await nn.rehydrateImages(t.data);for(const t of e||[])try{this.addVolume(t)}catch(s){console.warn("Failed to add rehydrated image:",s,t)}}catch(o){console.warn("NVSerializer.rehydrateImages failed:",o)}this.volumes&&this.volumes.length>0?this.back=this.volumes[0]:this.volumes=[];try{const e=await nn.rehydrateMeshes(t.data,this.gl,!0);for(const t of e||[])try{"function"==typeof t.updateMesh&&t.updateMesh(this.gl),this.addMesh(t)}catch(l){console.error("Failed to add rehydrated mesh:",l,t)}}catch(l){console.warn("NVSerializer.rehydrateMeshes failed:",l)}if(t.data.connectomes)for(const n of t.data.connectomes)try{const t=JSON.parse(n),e=this.loadConnectomeAsMesh(t);e.updateMesh(this.gl),this.addMesh(e)}catch(c){console.warn("Failed to rehydrate connectome:",c)}this.createEmptyDrawing();const i=t.encodedDrawingBlob;if(i)try{const t=await ye.b64toUint8(i);if(t){const e=this.back?.dims;if(e){let i=e[1]*e[2]*e[3];if(t.length-352===i&&(i+=352),t.length!==i)throw new Error(`drawBitmap size does not match the texture dimensions (${e[1]}\xd7${e[2]}\xd7${e[3]}) ${i} != ${e[1]*e[2]*e[3]}.`);this.drawBitmap=t,this.refreshDrawing()}else console.warn("No back image available; cannot validate drawBitmap size."),this.drawBitmap=t}}catch(h){console.warn("Failed to decode drawBitmap:",h)}return await this.setGradientOpacity(this.opts.gradientOpacity),await this.setVolumeRenderIllumination(this.opts.gradientAmount),this.updateGLVolume(),this.drawScene(),this._emitEvent("documentLoaded",t),this.onDocumentLoaded(t),this}async generateLoadDocumentJavaScript(t,e){const i=this.json();return`\n        ${e}\n\n        async function saveNiivueAsHtml(pageName) {\n          //get new docstring\n          const docString = nv1.json();\n          const html =\n          document.getElementsByTagName("html")[0]\n              .innerHTML.replace(base64, await NVUtilities.compressToBase64String(JSON.stringify(docString)));\n          NVUtilities.download(html, pageName, "application/html");\n        }\n\n        var nv1 = new Niivue();\n        await nv1.attachTo("${t}");\n        var base64 = "${await ye.compressToBase64String(JSON.stringify(i))}";\n        NVUtilities.decompressBase64String(base64).then((jsonText) => {\n          var json = JSON.parse(jsonText); // string -> JSON\n          var doc = NVDocument.loadFromJSON(json);\n          nv1.loadDocument(doc);\n          nv1.updateGLVolume();\n        });\n\n      `}async generateHTML(t,e){void 0===t&&(t="gl1");return`<!DOCTYPE html>\n        <html lang="en">\n          <head>\n            <meta charset="utf-8" />\n            <meta http-equiv="X-UA-Compatible" content="IE=edge" />\n            <meta name="viewport" content="width=device-width,initial-scale=1.0" />\n            <title>Save as HTML</title>\n            <style>\n            html {\n              height: auto;\n              min-height: 100%;\n              margin: 0;\n            }\n            body {\n              display: flex;\n              flex-direction: column;\n              margin: 0;\n              min-height: 100%;\n              width: 100%;\n              position: absolute;\n              font-family: system-ui, Arial, Helvetica, sans-serif;\n              background: #ffffff;\n              color: black;\n              user-select: none; /* Standard syntax */\n            }\n            header {\n              margin: 10px;\n            }\n            main {\n              flex: 1;\n              background: #000000;\n              position: relative;\n            }\n            footer {\n              margin: 10px;\n            }\n            canvas {\n              position: absolute;\n              cursor: crosshair;\n            }\n            canvas:focus {\n              outline: 0px;\n            }\n            div {\n              display: table-row;\n              background-color: blue;\n            }\n            </style>\n          </head>\n          <body>\n            <noscript>niivue requires JavaScript.</noscript>\n            <header>\n            Save the current scene as HTML\n            <button id="save">Save as HTML</button>\n            </header>\n            <main>
1\n              <canvas id="gl1"></canvas>\n            </main>\n            <script type="module" async>\n              ${await this.generateLoadDocumentJavaScript(t,e)}\n              function saveAsHtml() {\n                saveNiivueAsHtml("page.html");\n              }\n              // assign our event handler\n              var button = document.getElementById("save");\n              button.onclick = saveAsHtml;\n            <\/script>\n          </body>\n        </html>`}async saveHTML(t,e,i){void 0===t&&(t="untitled.html"),void 0===e&&(e="gl1");const n=await this.generateHTML(e,i);return ye.download(n,t,"application/html")}json(){this.document.opts=this.opts,this.document.scene=this.scene,this.document.volumes=this.volumes,this.document.meshes=this.meshes,this.drawScene(),this.document.previewImageDataURL=this.canvas.toDataURL();return this.document.json()}async saveDocument(t,e,i){void 0===t&&(t="untitled.nvd"),void 0===e&&(e=!0),void 0===i&&(i={});const{embedImages:n=!0,embedPreview:r=!0}=i;this.document.title=t,this.document.volumes=this.volumes,this.document.meshes=this.meshes,r?(this.drawScene(),this.document.previewImageDataURL=this.canvas.toDataURL()):this.document.previewImageDataURL="",await this.document.download(t,e,{embedImages:n})}async loadImages(t){const e=[],i=[];for(const n of t)if("url"in n){const t=this.getFileExt(n.name?n.name:n.url);if(this.loaders[t]){const r=this.loaders[t].toExt.toUpperCase();ss.includes(r)?i.push(n):e.push(n);continue}ss.includes(t.toUpperCase())?i.push(n):e.push(n)}return e.length>0&&await this.loadVolumes(e),i.length>0&&await this.loadMeshes(i),this}async loadDicoms(t){if(!this.getDicomLoader())throw new Error("No dicom loader set. Please set a dicom loader before loading dicoms");this.drawScene(),this.volumes=[];const e=t.map((async t=>{let e=null;if(t.isManifest)e=await Gi.fetchDicomData(t.url);else{const i=await fetch(t.url);if(!i.ok)throw new Error(`Failed to load file: ${i.statusText}`);const n=await i.arrayBuffer();e=[{name:t.url.split("/").pop(),data:n}]}const i=this.getDicomLoader().loader,n=await i(e),r=n[0].name,a=n[0].data;return await Gi.loadFromUrl({url:a,name:r})})),i=await Promise.all(e);return 1===i.length?this.addVolume(i[0]):(this._emitEvent("dicomLoaderFinished",{files:i}),this.onDicomLoaderFinishedWithImages(i)),this}async loadVolumes(t){return this.drawScene(),this.thumbnailVisible?(this.deferredVolumes=t,this):(this.volumes=[],this.closePAQD(),await this.addVolumesFromUrl(t),this)}async addMeshFromUrl(t){const e=this.getFileExt(t.url);if("JCON"===e||"JSON"===e){let e;if(t.buffer){const i=ArrayBuffer.isView(t.buffer)?t.buffer:new Uint8Array(t.buffer),n=new TextDecoder("utf-8").decode(i);e=JSON.parse(n)}else{const i=await fetch(t.url);e=await i.json()}const i=this.loadConnectomeAsMesh(e);return this.mediaUrlMap.set(i,t.url),this._emitEvent("meshAddedFromUrl",{meshOptions:t,mesh:i}),this.onMeshAddedFromUrl(t,i),this.addMesh(i),i}const i=await Te.loadFromUrl({...t,gl:this.gl});return this.mediaUrlMap.set(i,t.url),this._emitEvent("meshAddedFromUrl",{meshOptions:t,mesh:i}),this.onMeshAddedFromUrl(t,i),this.addMesh(i),i}async addMeshesFromUrl(t){const e=t.map((async t=>{const e=this.getFileExt(t.name||t.url);if(this.loaders[e]){let i=t.url;const r=this.loaders[e].toExt;let a=t.name||t.url;if(a=a.split("/").pop(),"string"==typeof t.url){const e=t.url;try{const t=await fetch(e);if(!t.ok)throw new Error(`Failed to load file: ${t.statusText}`);i=await t.arrayBuffer()}catch(n){throw new Error(`Failed to load url ${e}: ${n}`)}}const{positions:s,indices:o,colors:l=null,scalars:c=null,colormapLabel:h=null}=await this.loaders[e].loader(i);t.name=`${a}.${r}`;const d=await xe.createMZ3Async(s,o,!1,l,c,h);t.buffer=d}if("JCON"===e||"JSON"===e){const e=await fetch(t.url,{}),i=await e.json(),n=this.loadConnectomeAsMesh(i);return this.mediaUrlMap.set(n,t.url),this._emitEvent("meshAddedFromUrl",{meshOptions:t,mesh:n}),this.onMeshAddedFromUrl(t,n),n}const i=await Te.loadFromUrl({...t,gl:this.gl});return this.mediaUrlMap.set(i,t.url),this._emitEvent("meshAddedFromUrl",{meshOptions:t,mesh:i}),this.onMeshAddedFromUrl(t,i),i})),i=await Promise.all(e);for(let n=0;n<i.length;n++)this.addMesh(i[n]);return i}async loadMeshes(t){return this.drawScene(),this.thumbnailVisible?(this.deferredMeshes=t,this):(this.initialized,this.meshes=[],await this.addMeshesFromUrl(t),this.updateGLVolume(),this.drawScene(),this)}async loadConnectomeFromUrl(t,e){void 0===e&&(e={});const i=await fetch(t,{headers:e}),n=await i.json();return this.loadConnectome(n)}async loadFreeSurferConnectomeFromUrl(t,e){void 0===e&&(e={});const i=await fetch(t,{headers:e}),n=await i.json();return this.loadFreeSurferConnectome(n)}async loadFreeSurferConnectome(t){const e=dr.convertFreeSurferConnectome(t);return this.loadConnectome(e)}handleNodeAdded(t){const e=function(t,e){void 0===e&&(e="none");const i=[1,1,1,1];return{text:t.name,style:{textColor:i,bulletScale:1,bulletColor:i,lineWidth:0,lineColor:i,lineTerminator:e,textScale:1},position:[t.x,t.y,t.z]}}(t.detail.node);this.addLabel(e.text,e.style,e.position),this.drawScene()}loadConnectomeAsMesh(t){return function(t){const{gl:e,json:i}=t;let n=i;if("data_type"in i&&"fs_pointset"===i.data_type)n=dr.convertFreeSurferConnectome(i),Q.warn("converted FreeSurfer connectome",n);else{if(!("nodes"in i))throw new Error("not a known connectome format");{const t=i.nodes;"names"in t&&"X"in t&&"Y"in t&&"Z"in t&&"Color"in t&&"Size"in t&&(n=dr.convertLegacyConnectome(i))}}return new dr(e,n)}({gl:this.gl,json:t})}loadConnectome(t){this.drawScene(),this.meshes=[];const e=this.loadConnectomeAsMesh(t);return this.addMesh(e),this.drawScene(),this}createEmptyDrawing(){if(null===this.back||!this.back.dims)return;if(Math.min(Math.min(this.back.dims[1],this.back.dims[2]),this.back.dims[3])<1)return;const t=Pa(this.back.dims);this.drawBitmap=Na(t),this.clickToSegmentGrowingBitmap=Na(t),this.drawClearAllUndoBitmaps(),this.drawAddUndoBitmap(),this.opts.is2DSliceShader?this.drawTexture=this.r8Tex2D(this.drawTexture,R,this.back.dims):this.drawTexture=this.r8Tex(this.drawTexture,R,this.back.dims,!0),this.refreshDrawing(!1)}drawGrowCut(){if(!this.back||!this.back.dims)throw new Error("back not defined");const t=this.back.hdr,e=this.gl,i=t.dims[1]*t.dims[2]*t.dims[3];if(!this.drawBitmap||this.drawBitmap.length!==i)return void Q.debug("bitmap dims are wrong");const n=e.createFramebuffer();e.bindFramebuffer(e.FRAMEBUFFER,n),e.disable(e.CULL_FACE),e.viewport(0,0,this.back.dims[1],this.back.dims[2]),e.disable(e.BLEND);let r=function(t){const e=t.hdr.dims,i=t.permRAS,n=e[1]*e[2]*e[3],r=new Int16Array(n),a=[0,0,0];for(let m=0;m<3;m++)for(let t=0;t<3;t++)Math.abs(i[m])-1===t&&(a[t]=m*Math.sign(i[m]));let s=1;
1const o=[1,1,1],l=[!1,!1,!1];for(let m=0;m<a.length;m++)for(let t=0;t<a.length;t++)Math.abs(a[t])===m&&(o[t]=s,(a[t]<0||Object.is(a[t],-0))&&(l[t]=!0),s*=e[t+1]);let c=ye.range(0,e[1]-1,1);l[0]&&(c=ye.range(e[1]-1,0,-1));for(let m=0;m<e[1];m++)c[m]*=o[0];let h=ye.range(0,e[2]-1,1);l[1]&&(h=ye.range(e[2]-1,0,-1));for(let m=0;m<e[2];m++)h[m]*=o[1];let d=ye.range(0,e[3]-1,1);l[2]&&(d=ye.range(e[3]-1,0,-1));for(let m=0;m<e[3];m++)d[m]*=o[2];let u=0;for(let m=0;m<e[3];m++)for(let i=0;i<e[2];i++)for(let n=0;n<e[1];n++)r[c[n]+h[i]+d[m]]=t.img[u],u++;return r}(this.back);const a=this.r16Tex(null,k,this.back.dims,r);for(let v=1;v<i;v++)r[v]=this.drawBitmap[v];const s=this.r16Tex(null,Y,this.back.dims,r),o=this.r16Tex(null,G,this.back.dims,r);for(let v=1;v<i;v++)r[v]>0&&(r[v]=1e4);const l=this.r16Tex(null,O,this.back.dims,r),c=this.r16Tex(null,z,this.back.dims,r);e.bindVertexArray(this.genericVAO);const h=this.growCutShader;h.use(e);e.uniform1i(h.uniforms.finalPass,0),e.uniform1i(h.uniforms.backTex,11);for(let v=0;v<128;v++){e.uniform1i(h.uniforms.labelTex,14),e.uniform1i(h.uniforms.strengthTex,12);for(let t=0;t<this.back.dims[3];t++){const i=1/this.back.dims[3]*(t+.5);e.uniform1f(h.uniforms.coordZ,i),e.framebufferTextureLayer(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,o,0,t),e.framebufferTextureLayer(e.FRAMEBUFFER,e.COLOR_ATTACHMENT1,c,0,t),e.drawBuffers([e.COLOR_ATTACHMENT0,e.COLOR_ATTACHMENT1]);e.checkFramebufferStatus(e.FRAMEBUFFER)!==e.FRAMEBUFFER_COMPLETE&&Q.error("Incomplete framebuffer"),e.drawArrays(e.TRIANGLE_STRIP,0,4)}127===v&&e.uniform1i(h.uniforms.finalPass,1),e.uniform1i(h.uniforms.labelTex,15),e.uniform1i(h.uniforms.strengthTex,13);for(let t=0;t<this.back.dims[3];t++){const i=1/this.back.dims[3]*(t+.5);e.uniform1f(h.uniforms.coordZ,i),e.framebufferTextureLayer(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,s,0,t),e.framebufferTextureLayer(e.FRAMEBUFFER,e.COLOR_ATTACHMENT1,l,0,t),e.drawBuffers([e.COLOR_ATTACHMENT0,e.COLOR_ATTACHMENT1]);e.checkFramebufferStatus(e.FRAMEBUFFER)!==e.FRAMEBUFFER_COMPLETE&&Q.error("Incomplete framebuffer"),e.drawArrays(e.TRIANGLE_STRIP,0,4)}}e.drawBuffers([e.COLOR_ATTACHMENT0]);const d=e.COLOR_ATTACHMENT1,u=s;e.readBuffer(d);const m=e.getParameter(e.IMPLEMENTATION_COLOR_READ_FORMAT),f=e.getParameter(e.IMPLEMENTATION_COLOR_READ_TYPE);m===e.RED_INTEGER&&f===e.SHORT||Q.debug("readPixels will fail."),r=new Int16Array;const g=this.back.dims[1]*this.back.dims[2],A=new Int16Array(g);for(let v=0;v<this.back.dims[3];v++)e.framebufferTextureLayer(e.FRAMEBUFFER,d,u,0,v),e.readPixels(0,0,this.back.dims[1],this.back.dims[2],m,f,A),r=Int16Array.from([...r,...A]);let p=r[0];for(let v=0;v<r.length;v++)p=Math.max(p,r[v]);for(let v=1;v<i;v++)this.drawBitmap[v]=r[v];e.deleteTexture(a),e.deleteTexture(l),e.deleteTexture(c),e.deleteTexture(s),e.deleteTexture(o),e.bindVertexArray(this.unusedVAO),e.viewport(0,0,e.canvas.width,e.canvas.height),e.bindFramebuffer(e.FRAMEBUFFER,null),e.deleteFramebuffer(n),this.drawAddUndoBitmap(),this.refreshDrawing(!0)}drawPt(t,e,i,n,r){void 0===r&&(r=null);const a=r??this.drawBitmap;if(!a)throw new Error("drawBitmap not set");if(!this.back?.dims)throw new Error("back.dims not set");Oa({x:t,y:e,z:i,penValue:n,drawBitmap:a,dims:this.back.dims,penSize:this.opts.penSize,penAxCorSag:this.drawPenAxCorSag})}drawPenLine(t,e,i){if(!this.drawBitmap)throw new Error("drawBitmap not set");if(!this.back?.dims)throw new Error("back.dims not set");!function(t){const{ptA:e,ptB:i,penValue:n,drawBitmap:r,dims:a,penSize:s,penAxCorSag:o}=t,l=Math.abs(e[0]-i[0]),c=Math.abs(e[1]-i[1]),h=Math.abs(e[2]-i[2]),d=i[0]>e[0]?1:-1,u=i[1]>e[1]?1:-1,m=i[2]>e[2]?1:-1;let f=e[0],g=e[1],A=e[2];const p=i[0],v=i[1],x=i[2],w={x:0,y:0,z:0,penValue:n,drawBitmap:r,dims:a,penSize:s,penAxCorSag:o};if(l>=c&&l>=h){let t=2*c-l,e=2*h-l;for(;f!==p;)f+=d,t>=0&&(g+=u,t-=2*l),e>=0&&(A+=m,e-=2*l),t+=2*c,e+=2*h,w.x=f,w.y=g,w.z=A,Oa(w)}else if(c>=l&&c>=h){let t=2*l-c,e=2*h-c;for(;g!==v;)g+=u,t>=0&&(f+=d,t-=2*c),e>=0&&(A+=m,e-=2*c),t+=2*l,e+=2*h,w.x=f,w.y=g,w.z=A,Oa(w)}else{let t=2*c-h,e=2*l-h;for(;A!==x;)A+=m,t>=0&&(g+=u,t-=2*h),e>=0&&(f+=d,e-=2*h),t+=2*c,e+=2*l,w.x=f,w.y=g,w.z=A,Oa(w)}}({ptA:t,ptB:e,penValue:i,drawBitmap:this.drawBitmap,dims:this.back.dims,penSize:this.opts.penSize,penAxCorSag:this.drawPenAxCorSag})}drawRectangleMask(t,e,i){if(!this.drawBitmap)throw new Error("drawBitmap not set");if(!this.back?.dims)throw new Error("back.dims not set");!function(t){const{ptA:e,ptB:i,penValue:n,drawBitmap:r,dims:a,penSize:s,penAxCorSag:o}=t,l=Wa({ptA:e,ptB:i,dims:a}),{x1:c,y1:h,z1:d,x2:u,y2:m,z2:f}=l,g={x:0,y:0,z:0,penValue:n,drawBitmap:r,dims:a,penSize:s,penAxCorSag:o};for(let A=d;A<=f;A++)for(let t=h;t<=m;t++)for(let e=c;e<=u;e++)g.x=e,g.y=t,g.z=A,Oa(g)}({ptA:t,ptB:e,penValue:i,drawBitmap:this.drawBitmap,dims:this.back.dims,penSize:this.opts.penSize,penAxCorSag:this.drawPenAxCorSag})}drawEllipseMask(t,e,i){if(!this.drawBitmap)throw new Error("drawBitmap not set");if(!this.back?.dims)throw new Error("back.dims not set");Ka({ptA:t,ptB:e,penValue:i,drawBitmap:this.drawBitmap,dims:this.back.dims,penSize:this.opts.penSize,penAxCorSag:this.drawPenAxCorSag})}drawingBinaryDilationWithSeed(t,e){void 0===e&&(e=6);try{let i=function(t){return t[0]+t[1]*o+t[2]*l};const n=this.drawBitmap,r=this.back.dims[1],a=this.back.dims[2],s=this.back.dims[3],o=r,l=r*a,c=l*s,h=i(t);if(h<0||h>=c)throw new Error("Seed index is out of bounds.");const d=n[h];if(0===d)throw new Error("Seed voxel is not part of a filled cluster.");const u=n.slice();for(let t=0;t<c;t++)u[t]=u[t]===d?1:0;this.drawFloodFillCore(u,h,e);const m=n.slice(),f=[],g=[-l,l,-r,r,-1,1];f.push(...g),e>
16&&f.push(-r-1,1-r,r-1,r+1,-l-r,-l+r,-l-1,1-l,l-r,l+r,l-1,l+1),e>18&&f.push(-l-r-1,-l-r+1,-l+r-1,-l+r+1,l-r-1,l-r+1,l+r-1,l+r+1);for(let t=0;t<c;t++)if(2===u[t]){const e=t%r,i=Math.floor(t%l/r),a=Math.floor(t/l);for(const s of f){const o=t+s;if(o<0||o>=c)continue;const h=o%r,u=Math.floor(o%l/r),f=Math.floor(o/l);Math.abs(h-e)>1||Math.abs(u-i)>1||Math.abs(f-a)>1||0===n[o]&&(m[o]=d)}}this.drawBitmap=m,this.drawAddUndoBitmap(),this.refreshDrawing(!0)}catch(i){Q.error("Error in drawingBinaryDilationWithSeed:",i)}}drawFloodFillCore(t,e,i){if(void 0===i&&(i=6),!this.back?.dims)throw new Error("back.dims undefined");!function(t){const{img:e,seedVx:i,dims:n,neighbors:r=6}=t,a=Ha(n),s=[];s.push(i),e[i]=2;const o=[...Qa.face];for(r>=18&&o.push(...Qa.edge),r>=26&&o.push(...Qa.corner);s.length>0;){const t=s.shift(),i=a.vx2xyz(t);for(const r of o){const t=[i[0]+r[0],i[1]+r[1],i[2]+r[2]];if(t[0]<0||t[1]<0||t[2]<0)continue;if(t[0]>=n[0]||t[1]>=n[1]||t[2]>=n[2])continue;const o=a.xyz2vx(t);1===e[o]&&(e[o]=2,s.push(o))}}}({img:t,seedVx:e,dims:[this.back.dims[1],this.back.dims[2],this.back.dims[3]],neighbors:i})}drawFloodFill(t,e,i,n,r,a,s,o,l,c){if(void 0===e&&(e=0),void 0===i&&(i=0),void 0===n&&(n=NaN),void 0===r&&(r=NaN),void 0===a&&(a=6),void 0===s&&(s=Number.POSITIVE_INFINITY),void 0===o&&(o=!1),void 0===l&&(l=null),void 0===c&&(c=!1),!this.drawBitmap&&(Q.warn("drawFloodFill called without an initialized drawBitmap."),this.createEmptyDrawing(),!this.drawBitmap))return void Q.error("Failed to create drawing bitmap.");if(this.clickToSegmentIsGrowing&&!this.clickToSegmentGrowingBitmap){if(Q.warn("drawFloodFill called in preview mode without initialized clickToSegmentGrowingBitmap."),!this.drawBitmap)return void Q.error("Cannot initialize growing bitmap as drawBitmap is null.");if(this.clickToSegmentGrowingBitmap=this.drawBitmap.slice(),!this.clickToSegmentGrowingBitmap)return void Q.error("Failed to create growing bitmap.")}if(null===l&&(l=this.drawBitmap),!l)return void Q.error("drawFloodFill targetBitmap is null.");if(!this.back?.dims)throw new Error("back.dims undefined");e=Math.abs(e);const h=[this.back.dims[1],this.back.dims[2],this.back.dims[3]];if(!function(t,e){return!(t[0]<0||t[1]<0||t[2]<0||t[0]>=e[0]||t[1]>=e[1]||t[2]>=e[2])}(t,h))return;const d=Ha(h),{nxyz:u}=d,m=this.clickToSegmentIsGrowing?this.drawBitmap:l;if(!m)return void Q.error("Could not determine original bitmap state.");const f=new Uint8Array(u).fill(0),g=function(t,e){return t?0===e?2:1===e?1:2===e?0:-1:-1}(o,this.drawPenAxCorSag),A=d.vx2xyz,p=d.xyz2vx,v=t=>this.vox2mm(t,this.back.matRAS),x=v(t),w=s**2;function y(e){const i=A(e);if(g>=0&&i[g]!==t[g])return!1;const n=v(i);return(n[0]-x[0])**2+(n[1]-x[1])**2+(n[2]-x[2])**2<=w}const b=p(t),C=m[b];if(c&&!function(t){return 0!==t}(C))return Q.debug("Grow/Erase Cluster tool requires starting on a masked voxel."),void(this.clickToSegmentIsGrowing&&this.clickToSegmentGrowingBitmap&&this.drawBitmap&&(this.clickToSegmentGrowingBitmap.set(this.drawBitmap),this.refreshDrawing(!0,!0)));if(0===i&&C===e&&!c&&0!==e&&(Q.debug("drawFloodFill selected voxel is already desired color"),!this.clickToSegmentIsGrowing))return;let M=NaN;if(!c||i!==Number.POSITIVE_INFINITY&&i!==Number.NEGATIVE_INFINITY)if(0===i)if(c&&0===e){Q.debug(`Erase Cluster: Identifying cluster with color ${C}`);for(let t=0;t<u;t++)f[t]=m[t]===C&&y(t)?1:0}else for(let D=0;D<u;D++)m[D]===C&&y(D)&&0!==C&&(f[D]=1);else{const t=this.volumes[0].img2RAS();M=t[b];const[a,s]=qa(i,M,n,r);for(let e=0;e<u;e++){const i=t[e];i>=a&&i<=s&&y(e)&&(f[e]=1)}0===(e=m[b])&&((e=this.opts.penValue)<1||!isFinite(e))&&(e=1)}else{const t=m.slice();for(let e=0;e<u;e++)t[e]=t[e]===C&&y(e)?1:0;if(1!==t[b])return void Q.error("Seed voxel could not be marked for cluster ID.");this.drawFloodFillCore(t,b,a);const n=this.volumes[0].img2RAS();M=function(t){const{clusterImg:e,backImg:i,nxyz:n,fallbackIntensity:r}=t;let a=0,s=0;for(let o=0;o<n;o++)2===e[o]&&(a+=i[o],s++);return s>0?a/s:r}({clusterImg:t,backImg:n,nxyz:u,fallbackIntensity:n[b]}),Q.debug(`Grow Cluster using mean intensity: ${M.toFixed(2)} voxels.`);const[r,s]=qa(i,M,NaN,NaN);for(let e=0;e<u;e++)if(2===t[e])f[e]=1;else if(0===m[e]){const t=n[e];t>=r&&t<=s&&y(e)&&(f[e]=1)}e=C}
1if(1!==f[b]){const t=function(t,e,i,n){return i&&0!==n?0!==t:0!==t||0===e}(C,e,c,i);if(!t||!y(b))return Q.debug("Seed voxel not marked as candidate '1' and not valid originally."),void(this.clickToSegmentIsGrowing&&this.clickToSegmentGrowingBitmap&&this.drawBitmap&&this.clickToSegmentGrowingBitmap.set(this.drawBitmap));f[b]=1,Q.debug("Forcing seed voxel to 1 in working buffer.")}this.drawFloodFillCore(f,b,a),function(t){const{img:e,targetBitmap:i,originalBitmap:n,newColor:r,nxyz:a,isPreviewMode:s}=t;let o=0;for(let l=0;l<a;l++)2===e[l]?(i[l]=r,o++):s&&(i[l]=n[l])}({img:f,targetBitmap:l,originalBitmap:m,newColor:e,nxyz:u,isPreviewMode:this.clickToSegmentIsGrowing&&l===this.clickToSegmentGrowingBitmap}),this.clickToSegmentIsGrowing?this.refreshDrawing(!0,!0):(this.drawAddUndoBitmap(),this.refreshDrawing(!0,!1))}floodFillSectionFIFO(t,e,i,n){za({img2D:t,dims2D:e,minPt:i,maxPt:n})}drawPenFilled(){if(this.drawPenFillPts.length<2)return void(this.drawPenFillPts=[]);if(!this.drawBitmap)throw new Error("drawBitmap undefined");if(!this.back?.dims)throw new Error("back.dims undefined");const t=this.drawUndoBitmaps[this.currentDrawUndoBitmap]?.length>0?this.drawUndoBitmaps[this.currentDrawUndoBitmap]:null,e=function(t){const{penFillPts:e,penAxCorSag:i,drawBitmap:n,dims:r,penValue:a,fillOverwrites:s,currentUndoBitmap:o}=t,l=e.length;if(l<2)return{drawBitmap:n,success:!1};const[c,h]=function(t){let e=0,i=1;return 1===t?i=2:2===t&&(e=1,i=2),[e,i]}(i),d=[r[c+1],r[h+1]],u=new Uint8Array(d[0]*d[1]),m=Ga([e[0][c],e[0][h]],d);let f=[...m],g=[...m],A=m;for(let w=1;w<l;w++){let t=[e[w][c],e[w][h]];t=Ga(t,d),f=[Math.min(t[0],f[0]),Math.min(t[1],f[1])],g=[Math.max(t[0],g[0]),Math.max(t[1],g[1])],Ya(u,d,A,t,1),A=t}Ya(u,d,m,A,1),f[0]=Math.max(0,f[0]-1),f[1]=Math.max(0,f[1]-1),g[0]=Math.min(d[0]-1,g[0]+1),g[1]=Math.min(d[1]-1,g[1]+1);for(let w=0;w<d[1];w++)for(let t=0;t<d[0];t++){if(t>=f[0]&&t<g[0]&&w>=f[1]&&w<=g[1])continue;const e=t+w*d[0];0===u[e]&&(u[e]=2)}const p=Date.now();za({img2D:u,dims2D:d,minPt:f,maxPt:g}),Q.debug("FloodFill "+(Date.now()-p));const v=e[0][3-(c+h)],x=new Uint8Array(n);if(0===i){const t=v*d[0]*d[1];for(let e=0;e<d[0]*d[1];e++)2!==u[e]&&(x[e+t]=a)}else{let t=1;const e=r[1]*r[2];let n=v*r[1];2===i&&(t=r[1],n=v);let s=0;for(let i=0;i<d[1];i++)for(let r=0;r<d[0];r++)2!==u[s]&&(x[r*t+i*e+n]=a),s++}if(!s&&o&&o.length>0){const t=x.length,e=Da(o,t);for(let i=0;i<t;i++)0!==e[i]&&(x[i]=e[i])}return{drawBitmap:x,success:!0}}({penFillPts:this.drawPenFillPts,penAxCorSag:this.drawPenAxCorSag,drawBitmap:this.drawBitmap,dims:this.back.dims,penValue:this.opts.penValue,fillOverwrites:this.drawFillOverwrites,currentUndoBitmap:t});e.success&&(this.drawBitmap=e.drawBitmap),this.drawPenFillPts=[],this.drawAddUndoBitmap(),this.refreshDrawing(!1),this._emitEvent("drawingChanged",{action:"draw"}),this.onDrawingChanged("draw")}blurDrawingGL(t){const e=this.gl,i=this.blurShader;if(!i||!this.drawTexture)return;const n=Math.max(1,Math.round(this.opts.smoothDrawing));this.drawSmoothedTexture=function(t,e,i,n){return e&&t.deleteTexture(e),e=t.createTexture(),t.activeTexture(i),t.bindTexture(t.TEXTURE_3D,e),t.texParameteri(t.TEXTURE_3D,t.TEXTURE_MIN_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_3D,t.TEXTURE_MAG_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_3D,t.TEXTURE_WRAP_R,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_3D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_3D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.pixelStorei(t.UNPACK_ALIGNMENT,1),t.texStorage3D(t.TEXTURE_3D,1,t.R8,n[1],n[2],n[3]),e}(e,this.drawSmoothedTexture,N,t);const r=k;e.bindVertexArray(this.genericVAO);const a=e.createFramebuffer();e.bindFramebuffer(e.FRAMEBUFFER,a),e.viewport(0,0,t[1],t[2]),e.disable(e.BLEND),i.use(e),e.activeTexture(r),e.bindTexture(e.TEXTURE_3D,this.drawTexture),e.uniform1i(i.uniforms.intensityVol,11),e.uniform1f(i.uniforms.dX,1/t[1]),e.uniform1f(i.uniforms.dY,1/t[2]),e.uniform1f(i.uniforms.dZ,1/t[3]),e.uniform1i(i.uniforms.kernelRadius,n),e.uniform1i(i.uniforms.binarize,1);for(let s=0;s<t[3];s++)e.uniform1f(i.uniforms.coordZ,(s+.5)/t[3]),e.framebufferTextureLayer(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,this.drawSmoothedTexture,0,s),e.drawArrays(e.TRIANGLE_STRIP,0,4);e.deleteFramebuffer(a),e.bindFramebuffer(e.FRAMEBUFFER,null),e.bindVertexArray(this.unusedVAO)}closeDrawing(){this.drawClearAllUndoBitmaps(),this.drawTexture=this.rgbaTex(this.drawTexture,R,[2,2,2,2],!0),this.drawSmoothedTexture&&(this.gl.deleteTexture(this.drawSmoothedTexture),this.drawSmoothedTexture=null),this.drawBitmap=null,this.clickToSegmentGrowingBitmap=null,this._emitEvent("drawingChanged",{action:"close"}),this.onDrawingChanged("close"),this.drawScene()}refreshDrawing(t,e){void 0===t&&(t=!0),void 0===e&&(e=!1);const i=function(t){let{useClickToSegmentBitmap:e,drawingEnabled:i,clickToSegment:n,drawBitmap:r,clickToSegmentGrowingBitmap:a}=t,s=null;!e||i&&n||(Q.debug("determineBitmapDataSource: Conditions not met for clickToSegment bitmap, using drawBitmap."),e=!1);const o=e?a:r;return o||e||!a?!o&&e&&r?(s="clickToSegmentGrowingBitmap is null, falling back to drawBitmap.",e=!1):o||(s="Both bitmaps are null. Uploading empty data."):s="drawBitmap is null, but clickToSegmentGrowingBitmap exists. Check state.",{bitmapDataSource:e?a:r,useClickToSegmentBitmap:e,warning:s}}({useClickToSegmentBitmap:e,drawingEnabled:this.opts.drawingEnabled,clickToSegment:this.opts.clickToSegment,drawBitmap:this.drawBitmap,clickToSegmentGrowingBitmap:this.clickToSegmentGrowingBitmap});i.warning&&Q.warn(`refreshDrawing: ${i.warning}`);const n=i.bitmapDataSource;if(!this.back?.dims)return void Q.warn("refreshDrawing: back.dims undefined, cannot refresh drawing texture yet.");const r=Pa(this.back.dims);if(!n)return Q.warn(`refreshDrawing: Bitmap data source (${i.useClickToSegmentBitmap?"growing":"main"}) is null. Cannot update texture.`),void(t&&this.drawScene());const a=function(t,e){return 8===t?[e[0],2,2,2,...e.slice(4)]:e}(n.length,this.back.dims.slice());var s,o;if(s=n.length,o=r,8!==s&&s!==o&&Q.warn(`Drawing bitmap length (${n.length}) must match the background image (${r})`),this.gl.activeTexture(R),this.opts.is2DSliceShader){const t=this.frac2vox(this.scene.crosshairPos),e=Math.min(Math.max(t[2],0),a[3]-1),i=a[1]*a[2],r=e*i;Q.debug(`refresh huge 2D drawing x\xd7y\xd7z ${a[1]}\xd7${a[2]}\xd7${a[3]} slice ${r}`);const s=n.subarray(r,r+i);this.gl.bindTexture(this.gl.TEXTURE_2D,this.drawTexture),this.gl.texSubImage2D(this.gl.TEXTURE_2D,0,0,0,a[1],a[2],this.gl.RED,this.gl.UNSIGNED_BYTE,s)}else this.gl.bindTexture(this.gl.TEXTURE_3D,this.drawTexture),this.gl.texSubImage3D(this.gl.TEXTURE_3D,0,0,0,0,a[1],a[2],a[3],this.gl.RED,this.gl.UNSIGNED_BYTE,n);if(!this.drawTexture)return void Q.error("refreshDrawing: drawTexture (GPU texture) is null.");const l=n.some((t=>0!==t));this.opts.smoothDrawing>0&&!this.opts.is2DSliceShader&&l&&this.blurDrawingGL(a),t&&this.drawScene()}closePAQD(){this._gl&&this.paqdTexture&&(this.paqdTexture=this.rgbaTex(this.paqdTexture,P,[2,2,2,2],!0))}
1r8Tex2D(t,e,i,n){if(void 0===n&&(n=!1),t&&this.gl.deleteTexture(t),t=this.gl.createTexture(),this.gl.activeTexture(e),this.gl.bindTexture(this.gl.TEXTURE_2D,t),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_MIN_FILTER,this.gl.NEAREST),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_MAG_FILTER,this.gl.NEAREST),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_WRAP_R,this.gl.CLAMP_TO_EDGE),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_WRAP_S,this.gl.CLAMP_TO_EDGE),this.gl.pixelStorei(this.gl.UNPACK_ALIGNMENT,1),this.gl.texStorage2D(this.gl.TEXTURE_2D,1,this.gl.R8,i[1],i[2]),n){const t=new Uint8Array(i[1]*i[2]);this.gl.texSubImage2D(this.gl.TEXTURE_2D,0,0,0,i[1],i[2],this.gl.RED,this.gl.UNSIGNED_BYTE,t)}return t}initFontMets(){if(!this.fontMetrics)throw new Error("fontMetrics undefined");this.fontMets={distanceRange:this.fontMetrics.atlas.distanceRange,size:this.fontMetrics.atlas.size,mets:{}};const t=this.fontMetrics.atlas.width,e=this.fontMetrics.atlas.height;for(let i=0;i<this.fontMetrics.glyphs.length;i++){const n=this.fontMetrics.glyphs[i],r=n.unicode;if(this.fontMets.mets[r]||(this.fontMets.mets[r]={xadv:0,uv_lbwh:[0,0,0,0],lbwh:[0,0,0,0]}),this.fontMets.mets[r].xadv=n.advance,void 0===n.planeBounds)continue;let a=n.atlasBounds.left/t,s=(e-n.atlasBounds.top)/e,o=(n.atlasBounds.right-n.atlasBounds.left)/t,l=(n.atlasBounds.top-n.atlasBounds.bottom)/e;this.fontMets.mets[r].uv_lbwh=[a,s,o,l],a=n.planeBounds.left,s=n.planeBounds.bottom,o=n.planeBounds.right-n.planeBounds.left,l=n.planeBounds.top-n.planeBounds.bottom,this.fontMets.mets[r].lbwh=[a,s,o,l]}}async loadFont(t,e){if(void 0===t&&(t=Ie),void 0===e&&(e=Se),await this.loadFontTexture(t),"string"==typeof e){const t=await fetch(e);if(!t.ok)throw Error(t.statusText);this.fontMetrics=await t.json()}else this.fontMetrics=e;this.initFontMets(),this.fontShader.use(this.gl),this.drawScene()}async loadDefaultMatCap(){return this.loadMatCapTexture("data:image/jpeg;base64,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AFBnUHNlbnVtAAAAAFBnUHMAAAAAUGdQQwAAAABMZWZ0VW50RiNSbHQAAAAAAAAAAAAAAABUb3AgVW50RiNSbHQAAAAAAAAAAAAAAABTY2wgVW50RiNQcmNAWQAAAAAAAAAAABBjcm9wV2hlblByaW50aW5nYm9vbAAAAAAOY3JvcFJlY3RCb3R0b21sb25nAAAAAAAAAAxjcm9wUmVjdExlZnRsb25nAAAAAAAAAA1jcm9wUmVjdFJpZ2h0bG9uZwAAAAAAAAALY3JvcFJlY3RUb3Bsb25nAAAAAAA4QklNA+0AAAAAABAASAAAAAEAAQBIAAAAAQABOEJJTQQmAAAAAAAOAAAAAAAAAAAAAD+AAAA4QklNBA0AAAAAAAQAAAAeOEJJTQQZAAAAAAAEAAAAHjhCSU0D8wAAAAAACQAAAAAAAAAAAQA4QklNJxAAAAAAAAoAAQAAAAAAAAABOEJJTQP1AAAAAABIAC9mZgABAGxmZgAGAAAAAAABAC9mZgABAKGZmgAGAAAAAAABADIAAAABAFoAAAAGAAAAAAABADUAAAABAC0AAAAGAAAAAAABOEJJTQP4AAAAAABwAAD/////////////////////////////A+gAAAAA/////////////////////////////wPoAAAAAP////////////////////////////8D6AAAAAD/////////////////////////////A+gAADhCSU0EAAAAAAAAAgAAOEJJTQQCAAAAAAACAAA4QklNBDAAAAAAAAEBADhCSU0ELQAAAAAABgABAAAAMjhCSU0ECAAAAAAAEAAAAAEAAAJAAAACQAAAAAA4QklNBB4AAAAAAAQAAAAAOEJJTQQaAAAAAAM9AAAABgAAAAAAAAAAAAACAAAAAgAAAAAEAG0AYwA2ADEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAgAAAAIAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAEAAAAAAABudWxsAAAAAgAAAAZib3VuZHNPYmpjAAAAAQAAAAAAAFJjdDEAAAAEAAAAAFRvcCBsb25nAAAAAAAAAABMZWZ0bG9uZwAAAAAAAAAAQnRvbWxvbmcAAAIAAAAAAFJnaHRsb25nAAACAAAAAAZzbGljZXNWbExzAAAAAU9iamMAAAABAAAAAAAFc2xpY2UAAAASAAAAB3NsaWNlSURsb25nAAAAAAAAAAdncm91cElEbG9uZwAAAAAAAAAGb3JpZ2luZW51bQAAAAxFU2xpY2VPcmlnaW4AAAANYXV0b0dlbmVyYXRlZAAAAABUeXBlZW51bQAAAApFU2xpY2VUeXBlAAAAAEltZyAAAAAGYm91bmRzT2JqYwAAAAEAAAAAAABSY3QxAAAABAAAAABUb3AgbG9uZwAAAAAAAAAATGVmdGxvbmcAAAAAAAAAAEJ0b21sb25nAAACAAAAAABSZ2h0bG9uZwAAAgAAAAADdXJsVEVYVAAAAAEAAAAAAABudWxsVEVYVAAAAAEAAAAAAABNc2dlVEVYVAAAAAEAAAAAAAZhbHRUYWdURVhUAAAAAQAAAAAADmNlbGxUZXh0SXNIVE1MYm9vbAEAAAAIY2VsbFRleHRURVhUAAAAAQAAAAAACWhvcnpBbGlnbmVudW0AAAAPRVNsaWNlSG9yekFsaWduAAAAB2RlZmF1bHQAAAAJdmVydEFsaWduZW51bQAAAA9FU2xpY2VWZXJ0QWxpZ24AAAAHZGVmYXVsdAAAAAtiZ0NvbG9yVHlwZWVudW0AAAARRVNsaWNlQkdDb2xvclR5cGUAAAAATm9uZQAAAAl0b3BPdXRzZXRsb25nAAAAAAAAAApsZWZ0T3V0c2V0bG9uZwAAAAAAAAAMYm90dG9tT3V0c2V0bG9uZwAAAAAAAAALcmlnaHRPdXRzZXRsb25nAAAAAAA4QklNBCgAAAAAAAwAAAACP/AAAAAAAAA4QklNBBQAAAAAAAQAAAAyOEJJTQQMAAAAAAmrAAAAAQAAAKAAAACgAAAB4AABLAAAAAmPABgAAf/Y/+0ADEFkb2JlX0NNAAH/7gAOQWRvYmUAZIAAAAAB/9sAhAAMCAgICQgMCQkMEQsKCxEVDwwMDxUYExMVExMYEQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAQ0LCw0ODRAODhAUDg4OFBQODg4OFBEMDAwMDBERDAwMDAwMEQwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCACgAKADASIAAhEBAxEB/90ABAAK/8QBPwAAAQUBAQEBAQEAAAAAAAAAAwABAgQFBgcICQoLAQABBQEBAQEBAQAAAAAAAAABAAIDBAUGBwgJCgsQAAEEAQMCBAIFBwYIBQMMMwEAAhEDBCESMQVBUWETInGBMgYUkaGxQiMkFVLBYjM0coLRQwclklPw4fFjczUWorKDJkSTVGRFwqN0NhfSVeJl8rOEw9N14/NGJ5SkhbSVxNTk9KW1xdXl9VZmdoaWprbG1ub2N0dXZ3eHl6e3x9fn9xEAAgIBAgQEAwQFBgcHBgU1AQACEQMhMRIEQVFhcSITBTKBkRShsUIjwVLR8DMkYuFygpJDUxVjczTxJQYWorKDByY1wtJEk1SjF2RFVTZ0ZeLys4TD03Xj80aUpIW0lcTU5PSltcXV5fVWZnaGlqa2xtbm9ic3R1dnd4eXp7fH/9oADAMBAAIRAxEAPwDQUSpKJUi1gU0JykAkpdrUQMVnp/TMrOftob7R9J50aPiV0VXSel9MqFuWfWs7buCf5FX539tApedxum5eUYoqc8eIGn+efZ/0lqVfVZ4bvyrmUt79/v8A5tv/AEkfI67e/wBmM0UVjQHQuj/qGrPssfa7da42O8XGfyoJbL+ndBoaf0r8iwdmAR/nbdv/AE1VdVjz7Kw0eB1/gEpTohVMDRUeWN+4KDsPHdzW35CPyI8J4RQ59nTKj9Alv4hVbcC9nA3jy5+5bUJiyUUPPFpBg6HwUYW3fiV2D3DXse6zcjEfVqPc3x7hJDXCcFMkkpkCpShypApKf//Q0VEhSShSLUZC0+i9Ft6i/wBV814rTDn93Ectr/8AJofR+lu6nkO3EtwqD+ns4k8+ix3/AFf7n/batdV66Lh9j6f+iwqxsBZpvA09v7tP/nxAlIDp5XWcTBZ9k6c1p2aFw+gD/wCjHrFtybb7DZa4vce5VNrkVpQXUmBUwoNRAkpcBSATBSCKlwE4CQUgihaEoUoSRQwLUN9QKPCYhJDjZeFEvrHxaqMLonslZediRNrB/WH8UlNFOEyeElP/0dJRc2222rFoE35DgxnlP5xUpAEkwBqT5Kth9U+yZF2a0TkbCzGB4aXe02f2K08rQ7HWs6nBxm9B6e79HUIy7Ry5x9zq5/l/Tv8A+2VjsdKpteXElxLnEyXHkk8uKs1lNteA2q1YYq1asMKSU7URqE0ojUVJApBRCkEUMgpBRCkEULpIlVT7XBrBJPZHt6
1dk1M3uboOY1hFDUTKREJkkMCEGxkhHKg4JKcTJo9KzT6LuELatTKqD2nx5CpBiBU//0rOfb6ePtHNhj5DVyyDZJVrq1v6YM7MaPvPuWe06pSOqYhuVFXKiqNJVuooBc3WFHYVVrKOwpymy0orSq7CjNKSEwUwhNKmCnBBSBOFAFSBRQ63RdhfYSfeAIHl3WsuWrscxwc0lpHBGisHqOUW7TYYQMb6oZdSbU3KeK4jSQOJ/OVRIunlNKcpSi5PKiUkIrBIVF7YcQr71TvEOlAqf/9Ojnv35Vn9Yj7vag7S1Sd+kyyPF5/EqzlUGsDRRzl6qZYR9No6irdblRYYKtVu4Tggt1jkdjlTY5WGOTkNtjkZrlVY5Fa5FDZa5TBQGuUw5OCE4KeUIOThyKEsp9yFuT7kkJJTSoSlKKmcpiVGUiUkMXFVcn6JPgrDiq2QfYfggp//UzqoGeJ7Wwf8AOXQ9aww1jXtGkALncsGrqFwHZ5I+Z3hdhe5uZ09rhqXs3D48qnzJMckD0sgt3lQJ45x60CHkXDa6EVj1PLpg7h31VdpgqeErDBKNFu1uVhjlRY9WGPUgWNxjkZrlUY9Ga5OCG01yIHKs1yI1yKGwHJw5BDlIOTkJdyfchbk+5JCWUpQ9yfckpnKRcoSmLkUKc5Vr3e0ornKta6XBviQgp//Vp9br9PNbZ2tYD82+x3/fVp9HzycUVOP83oELrdHq4fqge6g7v7J9r/8AvqysHINb4nR35VFzOPiH4s3LZTA2PJ2MhjXBzR2OnwOoWZawtcrZyeD8j8EG1wcooWGadSQtdCOx6qnQqbXqcFgIbzHo7Xqix6Ox6eFhbjXojXqq16K16cENkOUg5AD1IORQnDk+5BDlLcipLuT7kLcn3JISbkxch71Fz0lLvegNO67yaCfv0TWWQFHHPsLzy86fAaBJD//W0CGuBa4S1wIcPEHQrl8mh2JkvodrsPtPi0/Qd/mrpZVDq+J9opFtYm2kHQcuZy5v9Zn02J842ERNFzGXEjXlTFnZU2uj+BUw9VuFsCTYLpTA6oYJKkCnAIJbDHI7Hqm1yKx6eFhbjXorXqo16K16eFraD0QPVUPUw5FDaDlIOVcPUg9FSbclvQt6i58JISl6G+xCdaq92QACSUlJLHmxwradXd/AfnFWAQAANANAFXxa3BptePe/geDew/tIySCX/9e1KUnkdkyZSrHI6pgekTkVD9C4zY0fmOP53/FP/wDA1QbIOq6byOoOhB1ELJzemGqbccF1XLqxqWf1f3q/+oTJw6hfGXQtMFTCE3TUahTBTKX2zCm0oYcFIEJKTNeiNsVcKQcnBDba9ED1TD1MWIobgenD1UFqf1UUNr1FCy1VnXwq92UBolaGxZkAd1PDode4X2j9ENWNP5x/e/qNQ8PAfcRdkgivltZ0Lv637rFqgf7AlSCtCUKYCeEUP//QsJJJlMsUpN0MhRUggpq5XS6rybKiKbTz+47+s0fR/rNWXdj247tt7DWTw7lp/qvXQhOQHNLXAOaeWkSD8imkLgXm9vdOAte3pWM6TUTQfBurf8x3/klVf0vLb9HZaP5J2n/Nf/5JN4V3E1AnRHY2Sz6VNg/skj/o7lAtcOWuHxaR/BKlWpLckGvPDSfgCpNxcl30an/5pH/VQiq2JeoOtKts6Xkv+ntYPMyfuarNXSsdmtk2nz0H+aEaK2w5VdeRkO21NLvE9h/WctHE6bVSQ+2LbRqP3QfIfnf2le2taA1oAaOANAmRAQSyCkFAKYRQyCdRlPKSn//ZADhCSU0EIQAAAAAAUwAAAAEBAAAADwBBAGQAbwBiAGUAIABQAGgAbwB0AG8AcwBoAG8AcAAAABIAQQBkAG8AYgBlACAAUABoAG8AdABvAHMAaABvAHAAIABDAEMAAAABADhCSU0EBgAAAAAABwAGAAAAAQEA/+ESK2h0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8APD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDIgNzkuMTYwOTI0LCAyMDE3LzA3LzEzLTAxOjA2OjM5ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChXaW5kb3dzKSIgeG1wOkNyZWF0ZURhdGU9IjIwMTgtMDctMTJUMjA6MDc6NDcrMDE6MDAiIHhtcDpNb2RpZnlEYXRlPSIyMDE4LTA3LTEzVDE3OjU0OjI3KzAxOjAwIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDE4LTA3LTEzVDE3OjU0OjI3KzAxOjAwIiBkYzpmb3JtYXQ9ImltYWdlL2pwZWciIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo3MmVhYjVmZS02NDZkLWVhNDMtODQyNC0xNWQzZTgwOWExNDQiIHhtcE1NOkRvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDo0OGNjMGI3YS1iYTJkLWZmNDAtYmNkNC1jNGQzMzIyZjBiNzQiIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDphYzFjM2NhNS1hYTg4LWI5NGMtOGE4MS05YmU4MjA3ZGZiODciPiA8cGhvdG9zaG9wOkRvY3VtZW50QW5jZXN0b3JzPiA8cmRmOkJhZz4gPHJkZjpsaT5hZG9iZTpkb2NpZDpwaG90b3Nob3A6YThjMGNhZTYtODNjYy1hYzQ4LWI2YzAtN2FiODNlOWJkMGM3PC9yZGY6bGk+IDwvcmRmOkJhZz4gPC9waG90b3Nob3A6RG9jdW1lbnRBbmNlc3RvcnM+IDx4bXBNTTpIaXN0b3J5PiA8cmRmOlNlcT4gPHJkZjpsaSBzdEV2dDphY3Rpb249ImNyZWF0ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6YWMxYzNjYTUtYWE4OC1iOTRjLThhODEtOWJlODIwN2RmYjg3IiBzdEV2dDp3aGVuPSIyMDE4LTA3LTEyVDIwOjA3OjQ3KzAxOjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgKFdpbmRvd3MpIi8+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDpjYmI3MzZlZC0zOTRhLTM2NDgtYThiOC02Mzk1MmY0NDcxMjIiIHN0RXZ0OndoZW49IjIwMTgtMDctMTNUMTY6MTM6NTgrMDE6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAoV2luZG93cykiIHN0RXZ0OmNoYW5nZWQ9Ii8iLz4gPHJkZjpsaSBzdEV2dDphY3Rpb249InNhdmVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjQ2YjNkYTI3LWI4YjEtYmU0Yi1hYTQ4LTExZGM5NmZkNTIyZiIgc3RFdnQ6d2hlbj0iMjAxOC0wNy0xM1QxNzo1NDoyNyswMTowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIENDIChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY29udmVydGVkIiBzdEV2dDpwYXJhbWV0ZXJzPSJmcm9tIGFwcGxpY2F0aW9uL3ZuZC5hZG9iZS5waG90b3Nob3AgdG8gaW1hZ2UvanBlZyIvPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iZGVyaXZlZCIgc3RFdnQ6cGFyYW1ldGVycz0iY29udmVydGVkIGZyb20gYXBwbGljYXRpb24vdm5kLmFkb2JlLnBob3Rvc2hvcCB0byBpbWFnZS9qcGVnIi8+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDo3MmVhYjVmZS02NDZkLWVhNDMtODQyNC0xNWQzZTgwOWExNDQiIHN0RXZ0OndoZW49IjIwMTgtMDctMTNUMTc6NTQ6MjcrMDE6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAoV2luZG93cykiIHN0RXZ0OmNoYW5nZWQ9Ii8iLz4gPC9yZGY6U2VxPiA8L3htcE1NOkhpc3Rvcnk+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjQ2YjNkYTI3LWI4YjEtYmU0Yi1hYTQ4LTExZGM5NmZkNTIyZiIgc3RSZWY6ZG9jdW1lbnRJRD0iYWRvYmU6ZG9jaWQ6cGhvdG9zaG9wOjg3NjM1NDk5LWZiMTItYWU0MC04NWEzLThkMWFiN2NkZGVhOSIgc3RSZWY6b3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOmFjMWMzY2E1LWFhODgtYjk0Yy04YTgxLTliZTgyMDdkZmI4NyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8P3hwYWNrZXQgZW5kPSJ3Ij8+/+IMWElDQ19QUk9GSUxFAAEBAAAMSExpbm8CEAAAbW50clJHQiBYWVogB84AAgAJAAYAMQAAYW
1NzcE1TRlQAAAAASUVDIHNSR0IAAAAAAAAAAAAAAAEAAPbWAAEAAAAA0y1IUCAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARY3BydAAAAVAAAAAzZGVzYwAAAYQAAABsd3RwdAAAAfAAAAAUYmtwdAAAAgQAAAAUclhZWgAAAhgAAAAUZ1hZWgAAAiwAAAAUYlhZWgAAAkAAAAAUZG1uZAAAAlQAAABwZG1kZAAAAsQAAACIdnVlZAAAA0wAAACGdmlldwAAA9QAAAAkbHVtaQAAA/gAAAAUbWVhcwAABAwAAAAkdGVjaAAABDAAAAAMclRSQwAABDwAAAgMZ1RSQwAABDwAAAgMYlRSQwAABDwAAAgMdGV4dAAAAABDb3B5cmlnaHQgKGMpIDE5OTggSGV3bGV0dC1QYWNrYXJkIENvbXBhbnkAAGRlc2MAAAAAAAAAEnNSR0IgSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAASc1JHQiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAADzUQABAAAAARbMWFlaIAAAAAAAAAAAAAAAAAAAAABYWVogAAAAAAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABjaWFlaIAAAAAAAACSgAAAPhAAAts9kZXNjAAAAAAAAABZJRUMgaHR0cDovL3d3dy5pZWMuY2gAAAAAAAAAAAAAABZJRUMgaHR0cDovL3d3dy5pZWMuY2gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZGVzYwAAAAAAAAAuSUVDIDYxOTY2LTIuMSBEZWZhdWx0IFJHQiBjb2xvdXIgc3BhY2UgLSBzUkdCAAAAAAAAAAAAAAAuSUVDIDYxOTY2LTIuMSBEZWZhdWx0IFJHQiBjb2xvdXIgc3BhY2UgLSBzUkdCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGRlc2MAAAAAAAAALFJlZmVyZW5jZSBWaWV3aW5nIENvbmRpdGlvbiBpbiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAACxSZWZlcmVuY2UgVmlld2luZyBDb25kaXRpb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")}async loadDefaultFont(){await this.loadFontTexture(this.DEFAULT_FONT_GLYPH_SHEET),this.fontMetrics=this.DEFAULT_FONT_METRICS,this.initFontMets()}async initText(){this.fontShader=new Cn(this.gl,"#version 300 es\n#line 576\nlayout(location=0) in vec3 pos;\nuniform vec2 canvasWidthHeight;\nuniform vec4 leftTopWidthHeight;\nuniform vec4 uvLeftTopWidthHeight;\nout vec2 vUV;\nvoid main(void) {\n\t//convert pixel x,y space 1..canvasWidth,1..canvasHeight to WebGL 1..-1,-1..1\n\tvec2 frac;\n\tfrac.x = (leftTopWidthHeight.x + (pos.x * leftTopWidthHeight.z)) / canvasWidthHeight.x; //0..1\n\tfrac.y = 1.0 - ((leftTopWidthHeight.y + ((1.0 - pos.y) * leftTopWidthHeight.w)) / canvasWidthHeight.y); //1..0\n\tfrac = (frac * 2.0) - 1.0;\n\tgl_Position = vec4(frac, 0.0, 1.0);\n\tvUV = vec2(uvLeftTopWidthHeight.x + (pos.x * uvLeftTopWidthHeight.z), uvLeftTopWidthHeight.y  + ((1.0 - pos.y) * uvLeftTopWidthHeight.w) );\n}","#version 300 es\n#line 593\nprecision highp int;\nprecision highp float;\nuniform highp sampler2D fontTexture;\nuniform vec4 fontColor;\nuniform float screenPxRange;\nin vec2 vUV;\nout vec4 color;\nfloat median(float r, float g, float b) {\n\treturn max(min(r, g), min(max(r, g), b));\n}\nvoid main() {\n\tvec3 msd = texture(fontTexture, vUV).rgb;\n\tfloat sd = median(msd.r, msd.g, msd.b);\n\tfloat screenPxDistance = screenPxRange*(sd - 0.5);\n\tfloat opacity = clamp(screenPxDistance + 0.5, 0.0, 1.0);\n\tcolor = vec4(fontColor.rgb , fontColor.a * opacity);\n}"),this.fontShader.use(this.gl),await this.loadDefaultFont(),await this.loadDefaultMatCap(),this.drawLoadingText(this.opts.loadingText)}meshShaderNameToNumber(t){return void 0===t&&(t="Phong"),nr(t,this.meshShaders)}setMeshShader(t,e){void 0===e&&(e=2);const i=function(t){const{meshes:e,meshShaders:i,id:n,meshShaderNameOrNumber:r,meshShaderNameToNumber:a}=t;let s=0;if(s="number"==typeof r?r:a(r),void 0===s)throw new Error("shaderIndex undefined");s=Math.min(s,i.length-1),s=Math.max(s,0);const o=cr(e,n);return o>=e.length||o<0?(Q.debug("Unable to change shader until mesh is loaded (maybe you need async)"),null):(e[o].meshShaderIndex=s,{meshIndex:o,shaderIndex:s})}({meshes:this.meshes,meshShaders:this.meshShaders,id:t,meshShaderNameOrNumber:e,meshShaderNameToNumber:this.meshShaderNameToNumber.bind(this)});null!==i&&(this.updateGLVolume(),this._emitEvent("meshShaderChanged",{meshIndex:i.meshIndex,shaderIndex:i.shaderIndex}),this.onMeshShaderChanged(i.meshIndex,i.shaderIndex))}createCustomMeshShader(t,e){return void 0===e&&(e="Custom"),function(t){const{gl:e,fragmentShaderText:i,name:n,meshShaders:r}=t;if(!i)throw new Error("Need fragment shader");const a=nr(n,r);if(void 0!==a&&a>=0){const t=r[a].shader;t&&e.deleteProgram(t.program),r.splice(a,1)}const s=new Cn(e,Zn,i);return s.use(e),{Name:n,Frag:i,shader:s}}({gl:this.gl,fragmentShaderText:t,name:e,meshShaders:this.meshShaders})}setCustomSliceShader(t){void 0===t&&(t=""),this.customSliceShader=function(t){const{gl:e,fragmentShaderText:i,drawOpacity:n,customSliceShader:r}=t;if(r&&e.deleteProgram(r.program),!i)return null;const a=new Cn(e,Pn,i);return a.use(e),e.uniform1i(a.uniforms.volume,0),e.uniform1i(a.uniforms.colormap,1),e.uniform1i(a.uniforms.overlay,2),e.uniform1i(a.uniforms.drawing,7),e.uniform1i(a.uniforms.paqd,8),e.uniform1f(a.uniforms.drawOpacity,n),a}({gl:this.gl,fragmentShaderText:t,drawOpacity:this.drawOpacity,customSliceShader:this.customSliceShader}),this.updateGLVolume()}setCustomMeshShader(t,e){void 0===t&&(t=""),void 0===e&&(e="Custom");const i=this.createCustomMeshShader(t,e);return this.meshShaders.push(i),this._emitEvent("customMeshShaderAdded",{fragmentShaderText:t,name:e}),this.onCustomMeshShaderAdded(t,e),this.meshShaders.length-1}async setCustomMeshShaderFromUrl(t,e){void 0===e&&(e="");try{const i=await fetch(t);if(!i.ok)throw new Error(`Failed to fetch shader from ${t}: ${i.status} ${i.statusText}`);const n=await i.text();if(!e||""===e.trim()){const i=t.split("/").pop()??t;e=i.split("?")[0].split("#")[0].replace(/\.[^/.]+$/,"")}return this.setCustomMeshShader(n,e)}catch(i){throw new Error(`setCustomMeshShaderFromUrl(${t}) failed: ${i.message}`)}}meshShaderNames(t){return void 0===t&&(t=!0),function(t,e){void 0===e&&(e=!0);const i=t.map((t=>t.Name));return e?i.sort():i}(this.meshShaders,t)}initRenderShader(t,e){void 0===e&&(e=0),ir({gl:this.gl,shader:t,gradientAmount:e,renderDrawAmbientOcclusion:this.renderDrawAmbientOcclusion,renderSilhouette:this.opts.renderSilhouette,gradientOpacity:this.opts.gradientOpacity})}
1async init(){const t=this.gl.getExtension("WEBGL_debug_renderer_info");if(t){const e=this.gl.getParameter(t.UNMASKED_VENDOR_WEBGL),i=this.gl.getParameter(t.UNMASKED_RENDERER_WEBGL);Q.info("renderer vendor: ",e),Q.info("renderer: ",i)}else Q.info("debug_renderer_info unavailable");const e=this.gl.getParameter(this.gl.RENDERER);Q.info("firefox renderer: ",e),this.gl.enable(this.gl.CULL_FACE),this.gl.cullFace(this.gl.FRONT),this.gl.enable(this.gl.BLEND),this.gl.blendFunc(this.gl.SRC_ALPHA,this.gl.ONE_MINUS_SRC_ALPHA),this.volumeTexture=this.rgbaTex(this.volumeTexture,S,[2,2,2,2],!0),this.overlayTexture=this.rgbaTex(this.overlayTexture,F,[2,2,2,2],!0),this.drawTexture=this.r8Tex(this.drawTexture,R,[2,2,2,2],!0),this.paqdTexture=this.rgbaTex(this.paqdTexture,P,[2,2,2,2],!0);const i=this.gl;this.cuboidVertexBuffer=i.createBuffer(),i.bindBuffer(i.ARRAY_BUFFER,this.cuboidVertexBuffer),i.bufferData(i.ARRAY_BUFFER,new Float32Array([1,1,0,1,0,0,0,1,0,0,0,0]),i.STATIC_DRAW),this.genericVAO=i.createVertexArray(),i.bindVertexArray(this.genericVAO),i.bindBuffer(i.ARRAY_BUFFER,this.cuboidVertexBuffer),i.enableVertexAttribArray(0),i.vertexAttribPointer(0,3,i.FLOAT,!1,0,0),i.bindVertexArray(this.unusedVAO),this.pickingMeshShader=new Cn(i,Zn,"#version 300 es\nprecision highp int;\nprecision highp float;\nuniform float opacity;\nout vec4 color;\nvec4 packFloatToVec4i(const float value) {\n\tconst vec4 bitSh = vec4(256.0*256.0*256.0, 256.0*256.0, 256.0, 1.0);\n\tconst vec4 bitMsk = vec4(0.0, 1.0/256.0, 1.0/256.0, 1.0/256.0);\n\tvec4 res = fract(value * bitSh);\n\tres -= res.xxyz * bitMsk;\n\treturn res;\n}\nvoid main() {\n\tcolor = packFloatToVec4i(gl_FragCoord.z);\n}"),this.pickingMeshShader.use(i),this.pickingImageShader=function(t){const e=new Cn(t,Mn,Jn);return e.use(t),e.uniforms.clipPlanes=t.getUniformLocation(e.program,"clipPlanes[0]"),t.uniform1i(e.uniforms.volume,0),t.uniform1i(e.uniforms.colormap,1),t.uniform1i(e.uniforms.overlay,2),t.uniform1i(e.uniforms.drawing,7),e}(i);const n=function(t,e){const i=new Cn(t,Pn,Ln);i.use(t),t.uniform1i(i.uniforms.volume,0),t.uniform1i(i.uniforms.colormap,1),t.uniform1i(i.uniforms.overlay,2),t.uniform1i(i.uniforms.drawing,7),t.uniform1f(i.uniforms.drawOpacity,e);const n=new Cn(t,Pn,On);n.use(t),t.uniform1i(n.uniforms.volume,0),t.uniform1i(n.uniforms.colormap,1),t.uniform1i(n.uniforms.overlay,2),t.uniform1i(n.uniforms.drawing,7),t.uniform1f(n.uniforms.drawOpacity,e);const r=new Cn(t,Pn,zn);return r.use(t),t.uniform1i(r.uniforms.volume,0),t.uniform1i(r.uniforms.colormap,1),t.uniform1i(r.uniforms.overlay,2),t.uniform1i(r.uniforms.drawing,7),t.uniform1f(r.uniforms.drawOpacity,e),{slice2DShader:i,sliceMMShader:n,sliceV1Shader:r}}(i,this.drawOpacity);this.slice2DShader=n.slice2DShader,this.sliceMMShader=n.sliceMMShader,this.sliceV1Shader=n.sliceV1Shader;const r=function(t,e,i){const n=new Cn(t,"#version 300 es\n// an attribute is an input (in) to a vertex shader.\n// It will receive data from a buffer\nlayout(location=0)  in vec3 a_position;\nlayout(location=1)  in vec3 a_color;\n// A matrix to transform the positions by\nuniform mat4 u_matrix;\nout vec3 vColor;\n// all shaders have a main function\nvoid main() {\n\t// Multiply the position by the matrix.\n\tvec4 pos = vec4(a_position, 1.0);\n\tgl_Position = u_matrix * vec4(pos);\n\tvColor = a_color;\n}\n","#version 300 es\nprecision highp float;\nuniform vec4 u_color;\nin vec3 vColor;\nout vec4 outColor;\nvoid main() {\n\toutColor = vec4(vColor, 1.0);\n}"),r=t.createVertexArray();t.bindVertexArray(r);const a=t.createBuffer();return t.enableVertexAttribArray(0),t.enableVertexAttribArray(1),t.bindBuffer(t.ARRAY_BUFFER,a),t.bufferData(t.ARRAY_BUFFER,e,t.STATIC_DRAW),t.vertexAttribPointer(0,3,t.FLOAT,!1,24,0),t.enableVertexAttribArray(1),t.vertexAttribPointer(1,3,t.FLOAT,!1,24,12),t.bindVertexArray(i),{shader:n,vao:r}}(i,W,this.unusedVAO);this.orientCubeShader=r.shader,this.orientCubeShaderVAO=r.vao;const a=function(t){const e=new Cn(t,Gn,Yn);e.use(t);const i=new Cn(t,Gn,"#version 300 es\n#line 723\nprecision highp int;\nprecision highp float;\n\nuniform vec4 lineColor;\nuniform vec4 leftTopWidthHeight;\nuniform float thickness; // line thickness in pixels\nuniform vec2 canvasWidthHeight;\n\nout vec4 color;\n\nvoid main() {\n    // fragment position in screen coordinates\n    vec2 fragCoord = gl_FragCoord.xy;\n\n    // canvas height\n    float canvasHeight = canvasWidthHeight.y;\n\n    // 'top' and 'bottom' to match gl_FragCoord.y coordinate system\n    float top = canvasHeight - leftTopWidthHeight.y;\n    float bottom = top - leftTopWidthHeight.w;\n\n    // left and right edges\n    float left = leftTopWidthHeight.x;\n    float right = left + leftTopWidthHeight.z;\n\n    bool withinLeft = fragCoord.x >= left && fragCoord.x <= left + thickness;\n    bool withinRight = fragCoord.x <= right && fragCoord.x >= right - thickness;\n    bool withinTop = fragCoord.y <= top && fragCoord.y >= top - thickness;\n    bool withinBottom = fragCoord.y >= bottom && fragCoord.y <= bottom + thickness;\n\n    bool isOutline = withinLeft || withinRight || withinTop || withinBottom;\n\n    if (isOutline) {\n        color = lineColor;\n    } else {\n        discard; \n    }\n}");i.use(t);const n=new Cn(t,"#version 300 es\n#line 534\nlayout(location=0) in vec3 pos;\nuniform vec2 canvasWidthHeight;\nuniform float thickness;\nuniform vec4 startXYendXY;\nvoid main(void) {\n\tvec2 posXY = mix(startXYendXY.xy, startXYendXY.zw, pos.x);\n\tvec2 dir = normalize(startXYendXY.xy - startXYendXY.zw);\n\tposXY += vec2(-dir.y, dir.x) * thickness * (pos.y - 0.5);
1\n\tposXY.x = (posXY.x) / canvasWidthHeight.x; //0..1\n\tposXY.y = 1.0 - (posXY.y / canvasWidthHeight.y); //1..0\n\tgl_Position = vec4((posXY * 2.0) - 1.0, 0.0, 1.0);\n}",Yn);n.use(t);const r=new Cn(t,"#version 300 es\n#line 534\nlayout(location=0) in vec3 pos;\nuniform vec2 canvasWidthHeight;\nuniform float thickness;\nuniform vec2 startXY;\nuniform vec3 endXYZ; // transformed XYZ point\nvoid main(void) {\t\n\tvec2 posXY = mix(startXY.xy, endXYZ.xy, pos.x);\n\tvec2 startDiff = endXYZ.xy - startXY.xy;\n\tfloat startDistance = length(startDiff);\n\tvec2 diff = endXYZ.xy - posXY;\n\tfloat currentDistance = length(diff);\n\tvec2 dir = normalize(startXY.xy - endXYZ.xy);\n\tposXY += vec2(-dir.y, dir.x) * thickness * (pos.y - 0.5);\n\tposXY.x = (posXY.x) / canvasWidthHeight.x; //0..1\n\tposXY.y = 1.0 - (posXY.y / canvasWidthHeight.y); //1..0\t\n\tfloat z = endXYZ.z * ( 1.0 - abs(currentDistance/startDistance)); \n\tgl_Position = vec4((posXY * 2.0) - 1.0, z, 1.0);\n}",Yn);r.use(t);const a=new Cn(t,"#version 300 es\nlayout(location=0) in vec3 pos;\nuniform vec2 canvasWidthHeight;\nuniform vec4 leftTopWidthHeight;\nuniform vec4 uvLeftTopWidthHeight;\nout vec2 vUV;\nvoid main(void) {\n\t//convert pixel x,y space 1..canvasWidth,1..canvasHeight to WebGL 1..-1,-1..1\n\tvec2 frac;\n\tfrac.x = (leftTopWidthHeight.x + (pos.x * leftTopWidthHeight.z)) / canvasWidthHeight.x; //0..1\n\tfrac.y = 1.0 - ((leftTopWidthHeight.y + ((1.0 - pos.y) * leftTopWidthHeight.w)) / canvasWidthHeight.y); //1..0\n\tfrac = (frac * 2.0) - 1.0;\n\tgl_Position = vec4(frac, 0.0, 1.0);\n\tvUV = pos.xy;\n}","#version 300 es\nprecision highp int;\nprecision highp float;\nuniform vec4 circleColor;\nuniform float fillPercent;\nin vec2 vUV;\nout vec4 color;\nvoid main() {\n\t/* Check if the pixel is inside the circle\n\t\t and color it with a gradient. Otherwise, color it \n\t\t transparent   */\n\tfloat distance = length(vUV-vec2(0.5,0.5));\n\tif ( distance < 0.5 && distance >= (1.0 - fillPercent) / 2.0){\n\t\t\tcolor = vec4(circleColor.r,circleColor.g,circleColor.b,circleColor.a) ;\t\t\t\n\t}else{\n\t\t\tcolor = vec4(0.0,0.0,0.0,0.0);\n\t}\n}\n");return a.use(t),{rectShader:e,rectOutlineShader:i,lineShader:n,line3DShader:r,circleShader:a}}(i);this.rectShader=a.rectShader,this.rectOutlineShader=a.rectOutlineShader,this.lineShader=a.lineShader,this.line3DShader=a.line3DShader,this.circleShader=a.circleShader;const s=function(t){const{gl:e,renderDrawAmbientOcclusion:i,renderSilhouette:n,gradientOpacity:r}=t,a=new Cn(e,Mn,Fn);ir({gl:e,shader:a,renderDrawAmbientOcclusion:i,renderSilhouette:n,gradientOpacity:r});const s=new Cn(e,Mn,En);ir({gl:e,shader:s,renderDrawAmbientOcclusion:i,renderSilhouette:n,gradientOpacity:r});const o=new Cn(e,Mn,Un);ir({gl:e,shader:o,gradientAmount:.3,renderDrawAmbientOcclusion:i,renderSilhouette:n,gradientOpacity:r}),e.uniform1i(o.uniforms.matCap,5),e.uniform1i(o.uniforms.gradient,6);const l=new Cn(e,Mn,Rn);return ir({gl:e,shader:l,renderDrawAmbientOcclusion:i,renderSilhouette:n,gradientOpacity:r}),e.uniform1i(l.uniforms.matCap,5),e.uniform1i(l.uniforms.gradient,6),{renderVolumeShader:a,renderSliceShader:s,renderGradientShader:o,renderGradientValuesShader:l,renderShader:a}}({gl:i,renderDrawAmbientOcclusion:this.renderDrawAmbientOcclusion,renderSilhouette:this.opts.renderSilhouette,gradientOpacity:this.opts.gradientOpacity});this.renderVolumeShader=s.renderVolumeShader,this.renderSliceShader=s.renderSliceShader,this.renderGradientShader=s.renderGradientShader,this.renderGradientValuesShader=s.renderGradientValuesShader,this.renderShader=s.renderShader,this.colorbarShader=function(t){const e=new Cn(t,"#version 300 es\n#line 490\nlayout(location=0) in vec3 pos;\nuniform vec2 canvasWidthHeight;\nuniform vec4 leftTopWidthHeight;\nout vec2 vColor;\nvoid main(void) {\n\t//convert pixel x,y space 1..canvasWidth,1..canvasHeight to WebGL 1..-1,-1..1\n\tvec2 frac;\n\tfrac.x = (leftTopWidthHeight.x + (pos.x * leftTopWidthHeight.z)) / canvasWidthHeight.x; //0..1\n\tfrac.y = 1.0 - ((leftTopWidthHeight.y + ((1.0 - pos.y) * leftTopWidthHeight.w)) / canvasWidthHeight.y); //1..0\n\tfrac = (frac * 2.0) - 1.0;\n\tgl_Position = vec4(frac, 0.0, 1.0);\n\tvColor = pos.xy;\n}","#version 300 es\n#line 506\nprecision highp int;\nprecision highp float;\nuniform highp sampler2D colormap;\nuniform float layer;\nin vec2 vColor;\nout vec4 color;\nvoid main() {\n\tfloat nlayer = float(textureSize(colormap, 0).y);
1\n\tfloat fmap = (0.5 + layer) / nlayer;\n\tcolor = vec4(texture(colormap, vec2(vColor.x, fmap)).rgb, 1.0);\n}");return e.use(t),t.uniform1i(e.uniforms.colormap,1),e}(i);const o=function(t){return{blurShader:new Cn(t,_n,"#version 300 es\n#line 298\nprecision highp int;\nprecision highp float;\nin vec2 TexCoord;\nout vec4 FragColor;\nuniform float coordZ;\nuniform float dX;\nuniform float dY;\nuniform float dZ;\n// Optional uniforms for parameterised (2r+1)^3 box blur. When kernelRadius\n// is 0 (default / gradient pipeline) the legacy 8-corner sample is used.\nuniform int kernelRadius;\nuniform bool binarize;\nuniform highp sampler3D intensityVol;\nvoid main(void) {\n vec3 vx = vec3(TexCoord.xy, coordZ);\n if (kernelRadius > 0) {\n  vec4 sum = vec4(0.0);\n  float count = 0.0;\n  for (int k = -kernelRadius; k <= kernelRadius; k++) {\n   for (int j = -kernelRadius; j <= kernelRadius; j++) {\n    for (int i = -kernelRadius; i <= kernelRadius; i++) {\n     vec3 off = vec3(float(i) * dX, float(j) * dY, float(k) * dZ);\n     vec4 v = texture(intensityVol, vx + off);\n     if (binarize) v = vec4(v.r > 0.0 ? 1.0 : 0.0, 0.0, 0.0, 0.0);\n     sum += v;\n     count += 1.0;\n    }\n   }\n  }\n  FragColor = sum / count;\n  return;\n }\n // Legacy 8-corner box blur (gradient pipeline)\n vec4 samp = texture(intensityVol,vx+vec3(+dX,+dY,+dZ));\n samp += texture(intensityVol,vx+vec3(+dX,+dY,-dZ));\n samp += texture(intensityVol,vx+vec3(+dX,-dY,+dZ));\n samp += texture(intensityVol,vx+vec3(+dX,-dY,-dZ));\n samp += texture(intensityVol,vx+vec3(-dX,+dY,+dZ));\n samp += texture(intensityVol,vx+vec3(-dX,+dY,-dZ));\n samp += texture(intensityVol,vx+vec3(-dX,-dY,+dZ));\n samp += texture(intensityVol,vx+vec3(-dX,-dY,-dZ));\n FragColor = samp*0.125;\n}"),gradientPrePassShader:new Cn(t,_n,"#version 300 es\n#line 298\nprecision highp int;\nprecision highp float;\nin vec2 TexCoord;\nout vec4 FragColor;\nuniform float coordZ;\nuniform float dX;\nuniform float dY;\nuniform float dZ;\nuniform highp sampler3D intensityVol;\nvoid main(void) {\n  vec3 vx = vec3(TexCoord.xy, coordZ);\n  // --- Z+ Plane (+dZ) ---\n  float XYZ = texture(intensityVol, vx + vec3(+dX, +dY, +dZ)).a;\n  float OYZ = texture(intensityVol, vx + vec3(0.0, +dY, +dZ)).a;\n  float xYZ = texture(intensityVol, vx + vec3(-dX, +dY, +dZ)).a;\n  float XOZ = texture(intensityVol, vx + vec3(+dX, 0.0, +dZ)).a;\n  float OOZ = texture(intensityVol, vx + vec3(0.0, 0.0, +dZ)).a;\n  float xOZ = texture(intensityVol, vx + vec3(-dX, 0.0, +dZ)).a;\n  float XyZ = texture(intensityVol, vx + vec3(+dX, -dY, +dZ)).a;\n  float OyZ = texture(intensityVol, vx + vec3(0.0, -dY, +dZ)).a;\n  float xyZ = texture(intensityVol, vx + vec3(-dX, -dY, +dZ)).a;\n  // --- Z0 Plane (0.0) ---\n  float XYO = texture(intensityVol, vx + vec3(+dX, +dY, 0.0)).a;\n  float OYO = texture(intensityVol, vx + vec3(0.0, +dY, 0.0)).a;\n  float xYO = texture(intensityVol, vx + vec3(-dX, +dY, 0.0)).a;\n  float XOO = texture(intensityVol, vx + vec3(+dX, 0.0, 0.0)).a;\n  float OOO = texture(intensityVol, vx + vec3(0.0, 0.0, 0.0)).a;\n  float xOO = texture(intensityVol, vx + vec3(-dX, 0.0, 0.0)).a;\n  float XyO = texture(intensityVol, vx + vec3(+dX, -dY, 0.0)).a;\n  float OyO = texture(intensityVol, vx + vec3(0.0, -dY, 0.0)).a;\n  float xyO = texture(intensityVol, vx + vec3(-dX, -dY, 0.0)).a;\n  // --- Z- Plane (-dZ) ---\n  float XYz = texture(intensityVol, vx + vec3(+dX, +dY, -dZ)).a;\n  float OYz = texture(intensityVol, vx + vec3(0.0, +dY, -dZ)).a;\n  float xYz = texture(intensityVol, vx + vec3(-dX, +dY, -dZ)).a;\n  float XOz = texture(intensityVol, vx + vec3(+dX, 0.0, -dZ)).a;\n  float OOz = texture(intensityVol, vx + vec3(0.0, 0.0, -dZ)).a;\n  float xOz = texture(intensityVol, vx + vec3(-dX, 0.0, -dZ)).a;\n  float Xyz = texture(intensityVol, vx + vec3(+dX, -dY, -dZ)).a;\n  float Oyz = texture(intensityVol, vx + vec3(0.0, -dY, -dZ)).a;\n  float xyz = texture(intensityVol, vx + vec3(-dX, -dY, -dZ)).a;\n  // --- Directional blur sums ---\n  vec3 blurred;\n  blurred.x = 2.0 * (xOz + xOZ + xyO + xYO + xOO + XOz + XOZ + XyO + XYO + XOO)\n              + xyz + xyZ + xYz + xYZ + Xyz + XyZ + XYz + XYZ;\n  blurred.y = 2.0 * (Oyz + OyZ + xyO + XyO + OyO + OYz + OYZ + xYO + XYO + OYO)\n              + xyz + Xyz + xyZ + XyZ + xYz + XYz + xYZ + XYZ;\n  blurred.z = 2.0 * (Oyz + OYz + xOz + XOz + OOz + OyZ + OYZ + xOZ + XOZ + OOZ)\n              + xyz + Xyz + xYz + XYz + xyZ + XyZ + xYZ + XYZ;\n  float finalAlpha = 0.32 * (abs(blurred.x) + abs(blurred.y) + abs(blurred.z));\n  // 0.0357 = 1/28 to account for weights, rescale to 2**16,\n  FragColor = 0.0357 * vec4(blurred, finalAlpha);\n}"),sobelFirstOrderShader:new Cn(t,_n,tr),sobelSecondOrderShader:new Cn(t,_n,er),growCutShader:new Cn(t,"#version 300 es\n#line 808\nprecision highp int;\nprecision highp float;\nin vec3 vPos;\nout vec2 TexCoord;\nvoid main() {\n\tTexCoord = vPos.xy;\n\tgl_Position = vec4((vPos.x - 0.5) * 2.0, (vPos.y - 0.5) * 2.0, 0.0, 1.0);\n}","#version 300 es\n#line 829\n\tprecision highp float;\n\tprecision highp int;\n\tprecision highp isampler3D;\n\tlayout(location = 0) out int label;\n\tlayout(location = 1) out int strength;\n\tin vec2 TexCoord;\n\tuniform int finalPass;\n\tuniform float coordZ;\n\tuniform lowp sampler3D in3D;\n\tuniform highp isampler3D backTex; // background\n\tuniform highp isampler3D labelTex; // label\n\tuniform highp isampler3D strengthTex; // strength\nvoid main(void) {\n\tvec3 interpolatedTextureCoordinate = vec3(TexCoord.xy, coordZ);\n\tivec3 size = textureSize(backTex, 0);
1\n\tivec3 texelIndex = ivec3(floor(interpolatedTextureCoordinate * vec3(size)));\n\tint background = texelFetch(backTex, texelIndex, 0).r;\n\tlabel = texelFetch(labelTex, texelIndex, 0).r;\n\tstrength = texelFetch(strengthTex, texelIndex, 0).r;\n\tfor (int k = -1; k <= 1; k++) {\n\t\tfor (int j = -1; j <= 1; j++) {\n\t\t\tfor (int i = -1; i <= 1; i++) {\n\t\t\t\tif (i != 0 && j != 0 && k != 0) {\n\t\t\t\t\tivec3 neighborIndex = texelIndex + ivec3(i,j,k);\n\t\t\t\t\tint neighborBackground = texelFetch(backTex, neighborIndex, 0).r;\n\t\t\t\t\tint neighborStrength = texelFetch(strengthTex, neighborIndex, 0).r;\n\t\t\t\t\tint strengthCost = abs(neighborBackground - background);\n\t\t\t\t\tint takeoverStrength = neighborStrength - strengthCost;\n\t\t\t\t\tif (takeoverStrength > strength) {\n\t\t\t\t\t\tstrength = takeoverStrength;\n\t\t\t\t\t\tlabel = texelFetch(labelTex, neighborIndex, 0).r;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (finalPass < 1)\n\t\treturn;\n\tint ok = 1;\n\tivec4 labelCount = ivec4(0,0,0,0);
1\n\tfor (int k = -1; k <= 1; k++)\n\t\tfor (int j = -1; j <= 1; j++)\n\t\t\tfor (int i = -1; i <= 1; i++) {\n\t\t\t\tivec3 neighborIndex = texelIndex + ivec3(i,j,k);\n\t\t\t\tint ilabel = texelFetch(labelTex, neighborIndex, 0).r;\n\t\t\t\tif ((ilabel < 0) || (ilabel > 3))\n\t\t\t\t\tok = 0;\n\t\t\t\telse\n\t\t\t\t\tlabelCount[ilabel]++;\n\t\t\t}\n\tif (ok != 1) {\n\t\treturn;\n\t}\n\tint maxIdx = 0;\n\tfor (int i = 1; i < 4; i++) {\n\t\tif (labelCount[i] > labelCount[maxIdx])\n\t\t\tmaxIdx = i;\n\t}\n\tlabel = maxIdx;\n}"),passThroughShader:new Cn(t,"#version 300 es\n#line 1359\nprecision highp int;\nprecision highp float;\nin vec3 vPos;\nout vec2 TexCoord;\nvoid main() {\n\tTexCoord = vPos.xy;\n\tvec2 viewCoord = (vPos.xy - 0.5) * 2.0;\n\tgl_Position = vec4((vPos.xy - 0.5) * 2.0, 0.0, 1.0);\n}","#version 300 es\nprecision highp int;\nprecision highp float;\nin vec2 TexCoord;\nout vec4 FragColor;\nuniform float coordZ;\nuniform lowp sampler3D in3D;\nvoid main(void) {\n FragColor = texture(in3D, vec3(TexCoord.xy, coordZ));\n}")}}(i);this.blurShader=o.blurShader,this.gradientPrePassShader=o.gradientPrePassShader,this.sobelFirstOrderShader=o.sobelFirstOrderShader,this.sobelSecondOrderShader=o.sobelSecondOrderShader,this.growCutShader=o.growCutShader,this.passThroughShader=o.passThroughShader;const l=function(t){return{orientShaderAtlasU:new Cn(t,Wn,Xn.concat(Qn)),orientShaderAtlasI:new Cn(t,Wn,Kn.concat(Qn)),orientShaderU:new Cn(t,Wn,Xn.concat(qn)),orientShaderI:new Cn(t,Wn,Kn.concat(qn)),orientShaderF:new Cn(t,Wn,Hn.concat(qn)),orientShaderRGBU:new Cn(t,Wn,Xn.concat("#line 773\nprecision highp int;\nprecision highp float;\nin vec2 TexCoord;\nout vec4 FragColor;\nuniform float coordZ;\nuniform float layer;\nuniform float scl_slope;\nuniform float scl_inter;\nuniform float cal_max;\nuniform float cal_min;\nuniform highp sampler2D colormap;\nuniform lowp sampler3D blend3D;\nuniform float opacity;\nuniform mat4 mtx;\nuniform bool hasAlpha;\nuniform int modulation;\nuniform highp sampler3D modulationVol;\nvoid main(void) {\n\tvec4 vx = vec4(TexCoord.xy, coordZ, 1.0) * mtx;\n\tuvec4 aColor = texture(intensityVol, vx.xyz);\n\tFragColor = vec4(float(aColor.r) / 255.0, float(aColor.g) / 255.0, float(aColor.b) / 255.0, float(aColor.a) / 25
15.0);\n\tif (modulation == 1)\n\t\tFragColor.rgb *= texture(modulationVol, vx.xyz).r;\n\tif (!hasAlpha) {\n\t\tFragColor.a = (FragColor.r * 0.21 + FragColor.g * 0.72 + FragColor.b * 0.07);\n\t\t//next line: we could binarize alpha, but see rendering of visible human\n\t\t//FragColor.a = step(0.01, FragColor.a);\n\t}\n\tif (modulation == 2)\n\t\tFragColor.a = texture(modulationVol, vx.xyz).r;\n\tFragColor.a *= opacity;\n\tif (layer < 1.0) return;\n\tvec4 prevColor = texture(blend3D, vec3(TexCoord.xy, coordZ));\n\t// https://en.wikipedia.org/wiki/Alpha_compositing\n\tfloat aout = FragColor.a + (1.0 - FragColor.a) * prevColor.a;\n\tif (aout <= 0.0) return;\n\tFragColor.rgb = ((FragColor.rgb * FragColor.a) + (prevColor.rgb * prevColor.a * (1.0 - FragColor.a))) / aout;\n\tFragColor.a = aout;\n}")),orientShaderPAQD:new Cn(t,Wn,Xn.concat("#line 773\nprecision highp int;\nprecision highp float;\nin vec2 TexCoord;\nout vec4 FragColor;\nuniform float coordZ;\nuniform float layer;\nuniform float scl_slope;\nuniform float scl_inter;\nuniform float cal_max;\nuniform float cal_min;\nuniform highp sampler2D colormap;\nuniform lowp sampler3D blend3D;\nuniform float opacity;\nuniform mat4 mtx;\nuniform bool hasAlpha;\nuniform int modulation;\nuniform highp sampler3D modulationVol;\nfloat textureWidth;\nfloat nlayer;\nfloat layerY;\n\nvec4 scalar2color(uint idx) {\n\tfloat fx = (float(idx) + 0.5) / textureWidth;\n\tvec4 clr = texture(colormap, vec2(fx, layerY)).rgba;\n\tif (clr.a > 0.0)\n\t\tclr.a = 1.0;\n\tclr.a *= opacity;\n\treturn clr;\n}\n\nvec4 paqd2color(uvec4 rgba) {\n  // paqd r: max prob index, g: 2nd index, b: max prob a: 2nd prob\n  float prob1 = float(rgba.b)/255.0;\n  float prob2 = float(rgba.a)/255.0;\n  vec4 clr1 = scalar2color(rgba.r);\n  vec4 clr2 = scalar2color(rgba.g);\n  float total = prob1 + prob2;\n  vec4 clr = vec4(clr1.rgb, total);\n  // vec4 clr = vec4(clr1.rgb, prob1);\n  if (total > 0.0) {\n    clr.rgb = mix(clr2.rgb, clr1.rgb, prob1 / total);\n  }\n  return clr;\n}\nvoid main(void) {\n\tvec4 vx = vec4(TexCoord.xy, coordZ, 1.0) * mtx;\n\tivec3 voxelCoord = ivec3(vx.xyz * vec3(textureSize(intensityVol, 0)));\n\tuvec4 rgba = texelFetch(intensityVol, voxelCoord, 0);\n\tFragColor = vec4(0.0, 0.0, 0.0, 0.0);\n\tif (rgba.r > uint(0)) {\n\t\ttextureWidth = float(textureSize(colormap, 0).x);\n\t\tnlayer = float(textureSize(colormap, 0).y);\n\t\tlayerY = ((2.0 * layer) + 1.5) / nlayer;\n\t\tFragColor = paqd2color(rgba);\n\t\treturn;\n\t}\n\t// if (layer > 2.0) return;\n\t// FragColor = texture(blend3D, vec3(TexCoord.xy, coordZ));\n}"))}}(i);this.orientShaderAtlasU=l.orientShaderAtlasU,this.orientShaderAtlasI=l.orientShaderAtlasI,this.orientShaderU=l.orientShaderU,this.orientShaderI=l.orientShaderI,this.orientShaderF=l.orientShaderF,this.orientShaderRGBU=l.orientShaderRGBU,this.orientShaderPAQD=l.orientShaderPAQD;const c=function(t){const e=new Cn(t,"#version 300 es\nlayout(location=0) in vec3 pos;\nuniform mat4 mvpMtx;\nvoid main(void) {\n\tgl_Position = mvpMtx * vec4(pos, 1.0);\n}","#version 300 es\nprecision highp int;\nprecision highp float;\nuniform vec4 surfaceColor;\nout vec4 color;\nvoid main() {\n\tcolor = surfaceColor;\n}");return e.use(t),{surfaceShader:e,fiberShader:new Cn(t,"#version 300 es\nlayout(location=0) in vec3 pos;\nlayout(location=1) in vec4 clr;\nout vec4 vClr;\nuniform mat4 mvpMtx;\nvoid main(void) {\n\tgl_Position = mvpMtx * vec4(pos, 1.0);\n\tvClr = clr;\n}","#version 300 es\nprecision highp int;\nprecision highp float;\nin vec4 vClr;\nout vec4 color;\nuniform float opacity;\nvoid main() {\n\tcolor = vec4(vClr.rgb, opacity);\n}")}}(i);return this.surfaceShader=c.surfaceShader,this.fiberShader=c.fiberShader,this.pickingImageShader.use(i),function(t,e){for(let i=0;i<e.length;i++){const n=e[i];"Flat"===n.Name?n.shader=new Cn(t,"#version 300 es\nlayout(location=0) in vec3 pos;\nlayout(location=1) in vec4 norm;\nlayout(location=2) in vec4 clr;\nuniform mat4 mvpMtx;\n//uniform mat4 modelMtx;\nuniform mat4 normMtx;\nout vec4 vClr;\nflat out vec3 vN;
1\nvoid main(void) {\n\tgl_Position = mvpMtx * vec4(pos, 1.0);\n\tvN = normalize((normMtx * vec4(norm.xyz,1.0)).xyz);\n\t//vV = -vec3(modelMtx*vec4(pos,1.0));\n\tvClr = clr;\n}",jn):n.shader=new Cn(t,Zn,n.Frag),n.shader.use(t),n.shader.isCrosscut="Crosscut"===n.Name,n.shader.isMatcap="Matcap"===n.Name,n.shader.isMatcap&&t.uniform1i(n.shader.uniforms.matCap,5)}}(i,this.meshShaders),this.bmpShader=new Cn(i,"#version 300 es\n#line 549\nlayout(location=0) in vec3 pos;\nuniform vec2 canvasWidthHeight;\nuniform vec4 leftTopWidthHeight;\nout vec2 vUV;\nvoid main(void) {\n\t//convert pixel x,y space 1..canvasWidth,1..canvasHeight to WebGL 1..-1,-1..1\n\tvec2 frac;\n\tfrac.x = (leftTopWidthHeight.x + (pos.x * leftTopWidthHeight.z)) / canvasWidthHeight.x; //0..1\n\tfrac.y = 1.0 - ((leftTopWidthHeight.y + ((1.0 - pos.y) * leftTopWidthHeight.w)) / canvasWidthHeight.y); //1..0\n\tfrac = (frac * 2.0) - 1.0;\n\tgl_Position = vec4(frac, 0.0, 1.0);\n\tvUV = vec2(pos.x, 1.0 - pos.y);\n}","#version 300 es\n#line 565\nprecision highp int;\nprecision highp float;\nuniform highp sampler2D bmpTexture;\nin vec2 vUV;\nout vec4 color;\nvoid main() {\n\tcolor = texture(bmpTexture, vUV);\n}"),await this.initText(),this.opts.thumbnail.length>0&&(await this.loadBmpTexture(this.opts.thumbnail),this.thumbnailVisible=!0),this.updateGLVolume(),this.initialized=!0,this.resizeListener(),this.drawScene(),this}gradientGL(t){this.gradientTexture=Fr({gl:this.gl,hdr:t,genericVAO:this.genericVAO,unusedVAO:this.unusedVAO,volumeTexture:this.volumeTexture,paqdTexture:this.paqdTexture,gradientTexture:this.gradientTexture,gradientOrder:this.opts.gradientOrder,blurShader:this.blurShader,gradientPrePassShader:this.gradientPrePassShader,sobelFirstOrderShader:this.sobelFirstOrderShader,sobelSecondOrderShader:this.sobelSecondOrderShader,rgbaTex:this.rgbaTex.bind(this)})}getGradientTextureData(){return function(t){const{gl:e,gradientTexture:i,dims:n}=t;if(!i||!n)return null;const r=n[1],a=n[2],s=n[3],o=r*a*s,l=e.createFramebuffer();e.bindFramebuffer(e.FRAMEBUFFER,l);const c=new Float32Array(4*o);try{for(let t=0;t<s;t++){e.framebufferTextureLayer(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,i,0,t);const n=e.checkFramebufferStatus(e.FRAMEBUFFER);if(n===e.FRAMEBUFFER_COMPLETE)try{const i=new Uint8Array(r*a*4);e.readPixels(0,0,r,a,e.RGBA,e.UNSIGNED_BYTE,i);const n=new Float32Array(r*a*4);for(let t=0;t<i.length;t++)n[t]=i[t]/127.5-1;const s=t*r*a*4;c.set(n,s)}catch(h){console.warn("Failed to read pixels for slice",t,":",h);const e=t*r*a*4,i=new Float32Array(r*a*4);c.set(i,e)}else console.warn("Framebuffer not complete for gradient texture reading, slice",t,"status:",n.toString(16))}}catch(d){return console.error("Error reading gradient texture:",d),null}finally{e.deleteFramebuffer(l),e.bindFramebuffer(e.FRAMEBUFFER,null)}return c}({gl:this.gl,gradientTexture:this.gradientTexture,dims:this.back?.dims??null})}setCustomGradientTexture(t,e){const i=function(t){const{gl:e,data:i,dims:n,backDims:r,gradientTextureAmount:a,hdr:s,gradientGLFn:o}=t;let{gradientTexture:l}=t;if(null===i)return s&&a>0&&o&&o(s),{gradientTexture:l,useCustomGradientTexture:!1};if(!n&&!r)return console.warn("No dimensions provided and no background volume loaded"),{gradientTexture:l,useCustomGradientTexture:!1};const c=n||r,h=c[1],d=c[2],u=c[3],m=h*d*u*4;if(i.length!==m)return console.warn(`Custom gradient data size mismatch. Expected ${m}, got ${i.length}`),{gradientTexture:l,useCustomGradientTexture:!1};let f;if(null!==l&&e.deleteTexture(l),l=e.createTexture(),e.activeTexture(Tr),e.bindTexture(e.TEXTURE_3D,l),e.texParameteri(e.TEXTURE_3D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_3D,e.TEXTURE_MAG_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_3D,e.TEXTURE_WRAP_R,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_3D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_3D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.pixelStorei(e.UNPACK_ALIGNMENT,1),i instanceof Float32Array){f=new Uint8Array(i.length);for(let t=0;t<i.length;t++){const e=Math.max(-1,Math.min(1,i[t]));f[t]=Math.round(127.5*(e+1))}}else f=i;return e.texStorage3D(e.TEXTURE_3D,1,e.RGBA8,h,d,u),e.texSubImage3D(e.TEXTURE_3D,0,0,0,0,h,d,u,e.RGBA,e.UNSIGNED_BYTE,f),{gradientTexture:l,useCustomGradientTexture:!0}}({gl:this.gl,data:t,dims:e,backDims:this.back?.dims??null,gradientTexture:this.gradientTexture,gradientTextureAmount:this.gradientTextureAmount,hdr:this.back?.hdr??null,gradientGLFn:this.gradientGL.bind(this)});this.gradientTexture=i.gradientTexture,this.useCustomGradientTexture=i.useCustomGradientTexture,null!==t&&i.useCustomGradientTexture&&this.drawScene()}updateGLVolume(){let t=0;const e=this.volumes.length;this.refreshColormaps(),this.closePAQD();for(let i=0;i<e;i++)this.volumes[i].toRAS&&(this.refreshLayers(this.volumes[i],t),t++);if(this.furthestVertexFromOrigin=0,e>0&&(this.furthestVertexFromOrigin=this.volumeObject3D?.furthestVertexFromOrigin??0),this.meshes)for(let i=0;i<this.meshes.length;i++)this.furthestVertexFromOrigin=Math.max(this.furthestVertexFromOrigin,this.meshes[i].furthestVertexFromOrigin);this._emitEvent("volumeUpdated",void 0),this.onVolumeUpdated&&this.onVolumeUpdated(),this.drawScene()}getDescriptives(t){const{layer:e=0,masks:i=[],drawingIsMask:n=!1,roiIsMask:r=!1,startVox:a=[0,0,0],endVox:s=[0,0,0]}=t,o=this.volumes[e].hdr,l=this.volumes[e].pixDimsRAS,c=isNaN(o.scl_slope)?1:o.scl_slope,h=isNaN(o.scl_inter)?1:o.scl_inter,d=this.volumes[e].img,u=d.length,m=function(t,e,
1i){const n=t.length,r=new Float32Array(n);for(let a=0;a<n;a++)r[a]=t[a]*e+i;return r}(d,c,h),f=i.filter((t=>{const e=this.volumes[t].img.length===u;return e||Q.debug("Mask resolution does not match image. Skipping masking layer "+t),e})).map((t=>this.volumes[t].img)),{mask:g,area:A}=is({nv:u,maskImages:f.length>0?f:void 0,drawBitmap:this.drawBitmap,drawingIsMask:i.length<1&&n,roiIsMask:i.length<1&&r,startVox:a,endVox:s,hdr:o,pixDimsRAS:l}),p=function(t,e){const i=t.length;let n=0,r=0,a=0,s=Number.NEGATIVE_INFINITY,o=Number.POSITIVE_INFINITY,l=0,c=0,h=0;for(let g=0;g<i;g++){if(e[g]<1)continue;const i=t[g];n++;let d=r+(i-r)/n;a+=(i-r)*(i-d),r=d,0!==i&&(l++,d=c+(i-c)/l,h+=(i-c)*(i-d),c=d,o=Math.min(i,o),s=Math.max(i,s))}const d=Math.sqrt(a/(n-1)),u=Math.sqrt(h/(l-1)),m=o,f=s;return n!==l&&(o=Math.min(0,o),s=Math.max(0,s)),{mean:r,stdev:d,nvox:n,min:o,max:s,meanNot0:c,stdevNot0:u,nvoxNot0:l,minNot0:m,maxNot0:f}}(m,g);return{...p,volumeMM3:p.nvox*o.pixDims[1]*o.pixDims[2]*o.pixDims[3],volumeML:p.nvox*o.pixDims[1]*o.pixDims[2]*o.pixDims[3]*.001,cal_min:this.volumes[e].cal_min,cal_max:this.volumes[e].cal_max,robust_min:this.volumes[e].robust_min,robust_max:this.volumes[e].robust_max,area:A}}refreshLayers(t,e){if(this.volumes.length<1)return;this.refreshColormaps();const i=t.hdr,n=function(t){let e=t.img;return t.frame4D>0&&t.frame4D<t.nFrame4D&&(e=t.img.slice(t.frame4D*t.nVox3D,(t.frame4D+1)*t.nVox3D)),e}(t),s=t.opacity;if(e>1&&0===s)return;let o=null;if(!this.back)throw new Error("back undefined");this.gl.bindVertexArray(this.unusedVAO),this.crosshairs3D&&(this.crosshairs3D.mm[0]=NaN);let l=a.o8(t.toRAS);if(0===e){this.volumeObject3D=function(t){const{overlayItem:e,VOLUME_ID:i,gl:n}=t;return or(e,i,n)}({overlayItem:t,VOLUME_ID:this.VOLUME_ID,gl:this.gl}),a.B8(l,l),this.back.matRAS=t.matRAS,this.back.dims=t.dimsRAS,this.back.pixDims=t.pixDimsRAS;const{volScale:e,vox:r}=this.sliceScale(!0);this.volScale=e,this.vox=r,this.volumeObject3D.scale=Array.from(e);const{isAboveMax2D:s,isAboveMax3D:c}=function(t){const{hdr:e,max2D:i,max3D:n}=t;return{isAboveMax2D:e.dims[1]>i||e.dims[2]>i,isAboveMax3D:e.dims[1]>n||e.dims[2]>n||e.dims[3]>n}}({hdr:i,max2D:this.uiData.max2D,max3D:this.uiData.max3D});if(s&&Q.error("Image dimensions exceed maximum texture size of hardware."),2304===i.datatypeCode&&i.dims[3]<2)return Q.info(`RGBA 2D image (${i.dims[1]}\xd7${i.dims[2]}) using Texture2D`),this.opts.is2DSliceShader=!0,void(this.volumeTexture=this.rgbaTex2D(this.volumeTexture,S,t.dimsRAS,n,!1));if(c){Q.info(`Large scalar image (>${this.uiData.max3D}) requires Texture2D (${i.dims[1]}\xd7${i.dims[2]}\xd7${i.dims[3]})`);const e=i.dims[1]*i.dims[2],r=this.frac2vox(this.scene.crosshairPos),a=Math.min(Math.max(r[2],0),i.dims[3]-1)*e,s=new Uint8Array(4*e),l=new Uint32Array(s.buffer),c=Math.floor(255*t.opacity),h=255*i.scl_slope/(t.cal_max-t.cal_min),d=255*(i.scl_inter-t.cal_min)/(t.cal_max-t.cal_min),u=new Uint8Array(this.colormap(t.colormap)),m=new Uint32Array(u.buffer);let f=-1;for(let t=0;t<e;t++){const e=n[t+a]*h+d,i=Math.round(Math.min(255,Math.max(0,e)));l[t]=m[i],s[f+=4]=c}return this.opts.is2DSliceShader=!0,void(o=this.rgbaTex2D(this.volumeTexture,S,t.dimsRAS,s,!1))}if(c&&Q.warn(`dimensions exceed 3D limits ${i.dims}`),this.opts.is2DSliceShader=!1,o=this.rgbaTex(this.volumeTexture,S,t.dimsRAS),!this.renderShader)throw new Error("renderShader undefined");this.renderShader.use(this.gl),this.gl.uniform3fv(this.renderShader.uniforms.texVox,this.vox),this.gl.uniform3fv(this.renderShader.uniforms.volScale,this.volScale);const h=this.pickingImageShader;h.use(this.gl),this.gl.uniform1i(h.uniforms.volume,0),this.gl.uniform1i(h.uniforms.colormap,1),this.gl.uniform1i(h.uniforms.overlay,2),this.gl.uniform3fv(h.uniforms.volScale,this.volScale),Q.debug(this.volumeObject3D)}else if(void 0===this.back?.dims&&Q.error("Fatal error: Unable to render overlay: background dimensions not defined!"),l=function(t){const{overlayItem:e,mm2frac:i}=t,n=i(e.mm000,0,!0);let s=i(e.mm100,0,!0),o=i(e.mm010,0,!0),l=i(e.mm001,0,!0);s=r.Re(s,s,n),o=r.Re(o,o,n),l=r.Re(l,l,n);const c=a.fA(s[0],o[0],l[0],n[0],s[1],o[1],l[1],n[1],s[2],o[2],l[2],n[2],0,0,0,1);return a.B8(c,c),c}({overlayItem:t,mm2frac:this.mm2frac.bind(this)}),1===e){const t=function(t){const{layer:e,backDims:i,rgbaTex:n}=t;if(0===e)return{volumeTexture:n(null,33984,i)};if(1===e){const t=n(null,33986,i);return{overlayTexture:t,overlayTextureID:t}}return{}}({gl:this.gl,layer:e,backDims:this.back.dims,rgbaTex:this.rgbaTex.bind(this)});o=t.overlayTexture,this.overlayTexture=o,this.overlayTextureID=o}else o=this.overlayTextureID;const c=function(t){const e=t.createFramebuffer();return t.bindFramebuffer(t.FRAMEBUFFER,e),t.disable(t.CULL_FACE),t.disable(t.BLEND),e}(this.gl);this.gl.viewport(0,0,this.back.dims[1],this.back.dims[2]);const h=function(t){const{gl:e,TEXTURE9_ORIENT:i}=t,n=e.createTexture();return e.activeTexture(i),e.bindTexture(e.TEXTURE_3D,n),e.texParameteri(e.TEXTURE_3D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_3D,e.TEXTURE_MAG_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_3D,e.TEXTURE_WRAP_R,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_3D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_3D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.pixelStorei(e.UNPACK_ALIGNMENT,1),n}({gl:this.gl,TEXTURE9_ORIENT:L});if(!i)throw new Error("hdr undefined");if(!n)throw new Error("img undefined");let d=this.orientShaderU;if(2304===i.datatypeCode){const r=function(t){const{gl:e,hdr:i,img:n,overlayItem:r,layer:a,orientShaderRGBU:s,orientShaderPAQD:o,volumes:l,backDims:c,rgbaTex:h,paqdTexture:d,TEXTURE8_PAQD:u,TEXTURE9_ORIENT:m}=t;let f=s,g=null,A=d;if(r.colormapLabel){f=o;let t=!0;for(let e=0;e<a;e++){const i=2304===l[e].hdr.datatypeCode,n=!!l[e].colormapLabel;i&&n&&(t=!1)}t&&(A=h(d,u,c)),g=A,e.activeTexture(m)}return f.use(e),e.uniform1i(f.uniforms.hasAlpha,1),e.texStorage3D(e.TEXTURE_3D,1,e.RGBA8UI,i.dims[1],i.dims[2],i.dims[3]),e.texSubImage3D(e.TEXTURE_3D,0,0,0,0,i.dims[1],i.dims[2],i.dims[3],e.RGBA_INTEGER,e.UNSIGNED_BYTE,n),{orientShader:f,outTexture:g,paqdTexture:A}}({gl:this.gl,hdr:i,img:n,overlayItem:t,layer:e,orientShaderRGBU:this.orientShaderRGBU,orientShaderPAQD:this.orientShaderPAQD,volumes:this.volumes,backDims:this.back.dims,rgbaTex:this.rgbaTex.bind(this),paqdTexture:this.paqdTexture,TEXTURE8_PAQD:P,TEXTURE9_ORIENT:L});d=r.orientShader,null!==r.outTexture&&(o=r.outTexture),null!==r.paqdTexture&&(this.paqdTexture=r.paqdTexture)}else{const t=function(t){const{gl:e,hdr:i,img:n,orientShaderU:r,orientShaderI:a,orientShaderF:s,orientShaderRGBU:o,orientShaderAtlasU:l,orientShaderAtlasI:c}=t;let h=r;if(2===i.datatypeCode)i.intent_code===lr&&(h=l),e.texStorage3D(e.TEXTURE_3D,1,e.R8UI,i.dims[1],i.dims[2],i.dims[3]),e.texSubImage3D(e.TEXTURE_3D,0,0,0,0,i.dims[1],i.dims[2],i.dims[3],e.RED_INTEGER,e.UNSIGNED_BYTE,n);else if(4===i.datatypeCode)h=a,i.intent_code===lr&&(h=c),e.texStorage3D(e.TEXTURE_3D,1,e.R16I,i.dims[1],i.dims[2],i.dims[3]),e.texSubImage3D(e.TEXTURE_3D,0,0,0,0,i.dims[1],i.dims[2],i.dims[3],e.RED_INTEGER,e.SHORT,n);else if(16===i.datatypeCode)e.texStorage3D(e.TEXTURE_3D,1,e.R32F,i.dims[1],i.dims[2],i.dims[3]),e.texSubImage3D(e.TEXTURE_3D,0,0,0,0,i.dims[1],i.dims[2],i.dims[3],e.RED,e.FLOAT,n),h=s;else if(64===i.datatypeCode){const t=Float32Array.from(n);e.texStorage3D(e.TEXTURE_3D,1,e.R32F,i.dims[1],i.dims[2],i.dims[3]),e.texSubImage3D(e.TEXTURE_3D,0,0,0,0,i.dims[1],i.dims[2],i.dims[3],e.RED,e.FLOAT,t),h=s}else 128===i.datatypeCode?(h=o,h.use(e),e.uniform1i(h.uniforms.hasAlpha,0),e.texStorage3D(e.TEXTURE_3D,1,e.RGB8UI,i.dims[1],i.dims[2],i.dims[3]),e.texSubImage3D(e.TEXTURE_3D,0,0,0,0,i.dims[1],i.dims[2],i.dims[3],e.RGB_INTEGER,e.UNSIGNED_BYTE,n)):512===i.datatypeCode&&(i.intent_code===lr&&(h=l),e.texStorage3D(e.TEXTURE_3D,1,e.R16UI,i.dims[1],i.dims[2],i.dims[3]),e.texSubImage3D(e.TEXTURE_3D,0,0,0,0,i.dims[1],i.dims[2],i.dims[3],e.RED_INTEGER,e.UNSIGNED_SHORT,n));return{orientShader:h}}({gl:this.gl,hdr:i,img:n,orientShaderU:this.orientShaderU,orientShaderI:this.orientShaderI,orientShaderF:this.orientShaderF,orientShaderRGBU:this.orientShaderRGBU,orientShaderAtlasU:this.orientShaderAtlasU,orientShaderAtlasI:this.orientShaderAtlasI});d=t.orientShader}void 0===t.global_min&&t.calMinMax(),this.gl.bindVertexArray(this.genericVAO);const u=function(t){const{gl:e,layer:i,backDims:n,rgbaTex:r,passThroughShader:a}=t;if(i<=1)return r(null,33994,[2,2,2,2]);const s=r(null,33994,n);e.bindTexture(e.TEXTURE_3D,s),a.use(e),e.uniform1i(a.uniforms.in3D,2);for(let o=0;o<n[3];o++){const t=1/n[3]*(o+.5);e.uniform1f(a.uniforms.coordZ,t),e.framebufferTextureLayer(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,s,0,o),e.drawArrays(e.TRIANGLE_STRIP,0,4)}return s}({gl:this.gl,layer:e,backDims:this.back.dims,rgbaTex:this.rgbaTex.bind(this),passThroughShader:this.passThroughShader});d.use(this.gl),this.gl.activeTexture(E);const{colormapLabelTexture:m}=function(t){const{gl:e,overlayItem:i,orientShader:n,createColormapTexture:r}=t;if(null===i.colormapLabel||i.colormapLabel.lut.length<=7)return{colormapLabelTexture:null,shouldCleanup:!1};const a=i.colormapLabel.max-i.colormapLabel.min+1,s=r(null,1,a);return e.texSubImage2D(e.TEXTURE_2D,0,0,0,a,1,e.RGBA,e.UNSIGNED_BYTE,i.colormapLabel.lut),e.uniform1f(n.uniforms.cal_min,i.colormapLabel.min-.5),e.uniform1f(n.uniforms.cal_max,i.colormapLabel.max+.5),e.bindTexture(e.TEXTURE_2D,s),{colormapLabelTexture:s,shouldCleanup:!0}
1}({gl:this.gl,overlayItem:t,orientShader:d,createColormapTexture:this.createColormapTexture.bind(this)});if(null===m&&(this.gl.bindTexture(this.gl.TEXTURE_2D,this.colormapTexture),this.gl.uniform1f(d.uniforms.cal_min,t.cal_min),this.gl.uniform1f(d.uniforms.cal_max,t.cal_max)),"alphaThreshold"in t&&(Q.warn("alphaThreshold is deprecated: use colormapType"),!0===t.alphaThreshold&&(t.colormapType=2),!1===t.alphaThreshold&&(t.colormapType=1),delete t.alphaThreshold),!d)throw new Error("orientShader undefined");!function(t){const{gl:e,overlayItem:i,orientShader:n,layer:r,isAdditiveBlend:a}=t,s=0!==i.colormapType?1:0,o=1===i.colormapType?1:0;e.uniform1i(n.uniforms.isAlphaThreshold,o),e.uniform1i(n.uniforms.isColorbarFromZero,s),e.uniform1i(n.uniforms.isAdditiveBlend,a?1:0);let l=Number.POSITIVE_INFINITY,c=Number.NEGATIVE_INFINITY;i.colormapNegative.length>0&&(l=Math.min(-i.cal_min,-i.cal_max),c=Math.max(-i.cal_min,-i.cal_max),isFinite(i.cal_minNeg)&&isFinite(i.cal_maxNeg)&&(l=Math.min(i.cal_minNeg,i.cal_maxNeg),c=Math.max(i.cal_minNeg,i.cal_maxNeg))),e.uniform1f(n.uniforms.layer??null,r),e.uniform1f(n.uniforms.cal_minNeg??null,l),e.uniform1f(n.uniforms.cal_maxNeg??null,c)}({gl:this.gl,overlayItem:t,orientShader:d,layer:e,isAdditiveBlend:this.opts.isAdditiveBlend});const{modulateTexture:f}=function(t){const{gl:e,overlayItem:i,hdr:n,volumes:r,orientShader:a,r8Tex:s,TEXTURE7:o}=t;if(null===i.modulationImage||i.modulationImage<0||i.modulationImage>=r.length)return e.uniform1i(a.uniforms.modulation,0),{modulateTexture:null};const l=r[i.modulationImage].hdr;if(l.dims[1]!==n.dims[1]||l.dims[2]!==n.dims[2]||l.dims[3]!==n.dims[3])return Q.debug("Modulation image dimensions do not match target"),e.uniform1i(a.uniforms.modulation,0),{modulateTexture:null};Q.debug("modulating",r),i.modulateAlpha?(e.uniform1i(a.uniforms.modulation,2),e.uniform1f(a.uniforms.opacity,1)):e.uniform1i(a.uniforms.modulation,1);const c=s(null,o,n.dims,!0);e.activeTexture(o),e.bindTexture(e.TEXTURE_3D,c);const h=n.dims[1]*n.dims[2]*n.dims[3],d=new Uint8Array(h),u=r[i.modulationImage].cal_min,m=1/(r[i.modulationImage].cal_max-u),f=r[i.modulationImage].img.buffer;let g=new Uint8Array(f);switch(l.datatypeCode){case 4:g=new Int16Array(f);break;case 16:g=new Float32Array(f);break;case 64:g=new Float64Array(f);break;case 128:g=new Uint8Array(f);break;case 512:g=new Uint16Array(f)}Q.debug(r[i.modulationImage]);const A=r[i.modulationImage].colormapNegative.length>0;let p=r[i.modulationImage].cal_min,v=r[i.modulationImage].cal_max;isFinite(r[i.modulationImage].cal_minNeg)&&isFinite(r[i.modulationImage].cal_maxNeg)&&(p=r[i.modulationImage].cal_minNeg,v=r[i.modulationImage].cal_maxNeg),p=Math.abs(p),v=Math.abs(v),p>v&&([p,v]=[v,p]);const x=1/(v-p);let w=Math.abs(i.modulateAlpha);w=Math.max(w,1);const y=r[i.modulationImage].frame4D*h;for(let b=0;b<h;b++){const t=g[b+y]*l.scl_slope+l.scl_inter;let e=(t-u)*m;A&&t<0&&(e=(Math.abs(t)-p)*x),e=Math.min(Math.max(e,0),1),e=255*Math.pow(e,w),d[b]=e}return e.texSubImage3D(e.TEXTURE_3D,0,0,0,0,n.dims[1],n.dims[2],n.dims[3],e.RED,e.UNSIGNED_BYTE,d),{modulateTexture:c}}({gl:this.gl,overlayItem:t,hdr:i,volumes:this.volumes,orientShader:d,r8Tex:this.r8Tex.bind(this),TEXTURE7:this.gl.TEXTURE7});if(this.gl.activeTexture(L),this.gl.bindTexture(this.gl.TEXTURE_3D,h),!this.back.dims)throw new Error("back.dims undefined");if(function(t){const{gl:e,orientShader:i,backDims:n,outTexture:r,mtx:a,hdr:s,intensityVolTextureUnit:o,blendTextureUnit:l,colormapTextureUnit:c,modulationTextureUnit:h,opacity:d,atlasOutline:u,atlasActiveIndex:m}=t;i.use(e),e.uniform1i(i.uniforms.intensityVol??null,o),e.uniform1i(i.uniforms.blend3D??null,l),e.uniform1i(i.uniforms.colormap??null,c),e.uniform1f(i.uniforms.scl_inter??null,s.scl_inter),e.uniform1f(i.uniforms.scl_slope??null,s.scl_slope),e.uniform1f(i.uniforms.opacity??null,d),e.uniform1i(i.uniforms.modulationVol??null,h),e.uniformMatrix4fv(i.uniforms.mtx,!1,a);let f=0;1002===s.intent_code&&(f=u,e.uniform1ui(i.uniforms.activeIndex,0|m)),e.uniform4fv(i.uniforms.xyzaFrac,[1/n[1],1/n[2],1
1/n[3],f]);for(let g=0;g<n[3];g++){const t=1/n[3]*(g+.5);e.uniform1f(i.uniforms.coordZ,t),e.framebufferTextureLayer(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,r,0,g),e.drawArrays(e.TRIANGLE_STRIP,0,4)}}({gl:this.gl,orientShader:d,backDims:this.back.dims,outTexture:o,mtx:l,hdr:i,intensityVolTextureUnit:9,blendTextureUnit:10,colormapTextureUnit:1,modulationTextureUnit:7,opacity:s,atlasOutline:this.opts.atlasOutline,atlasActiveIndex:this.opts.atlasActiveIndex}),Q.debug("back dims: ",this.back.dims),this.gl.bindVertexArray(this.unusedVAO),this.gl.deleteTexture(h),this.gl.deleteTexture(f),this.gl.deleteTexture(u),this.gl.viewport(0,0,this.gl.canvas.width,this.gl.canvas.height),this.gl.bindFramebuffer(this.gl.FRAMEBUFFER,null),this.gl.deleteFramebuffer(c),0===e&&(this.volumeTexture=o,this.gradientTexture=Fr({gl:this.gl,hdr:i,genericVAO:this.genericVAO,unusedVAO:this.unusedVAO,volumeTexture:this.volumeTexture,paqdTexture:this.paqdTexture,gradientTexture:this.gradientTexture,gradientOrder:this.opts.gradientOrder,blurShader:this.blurShader,gradientPrePassShader:this.gradientPrePassShader,sobelFirstOrderShader:this.sobelFirstOrderShader,sobelSecondOrderShader:this.sobelSecondOrderShader,rgbaTex:this.rgbaTex.bind(this)})),!this.renderShader)throw new Error("renderShader undefined");if(!this.pickingImageShader)throw new Error("pickingImageShader undefined");const g=this.sliceScale(!0),A=g.vox,p=g.volScale,v=function(t){const{is2DSliceShader:e,isV1SliceShader:i,sliceMMShader:n,slice2DShader:r,sliceV1Shader:a,customSliceShader:s}=t;let o=n;if(e&&(o=r),i&&(o=a),s&&(o=s),!o)throw new Error("slice shader undefined");return o}({is2DSliceShader:this.opts.is2DSliceShader,isV1SliceShader:this.opts.isV1SliceShader,sliceMMShader:this.sliceMMShader,slice2DShader:this.slice2DShader,sliceV1Shader:this.sliceV1Shader,customSliceShader:this.customSliceShader});!function(t){const{gl:e,renderShader:i,pickingImageShader:n,sliceShader:r,overlaysLength:a,clipPlaneColor:s,backOpacity:o,renderOverlayBlend:l,clipPlane:c,texVox:h,volScale:d,drawOpacity:u,paqdUniforms:m}=t;i.use(e),e.uniform1f(i.uniforms.overlays,a),e.uniform4fv(i.uniforms.clipPlaneColor,s),e.uniform1f(i.uniforms.backOpacity,o),e.uniform1f(i.uniforms.renderOverlayBlend,l),e.uniform4fv(i.uniforms.clipPlane,c),e.uniform3fv(i.uniforms.texVox,h),e.uniform3fv(i.uniforms.volScale,d),n.use(e),e.uniform1f(n.uniforms.overlays,a),e.uniform3fv(n.uniforms.texVox,h),r.use(e),e.uniform1f(r.uniforms.overlays,a),e.uniform1f(r.uniforms.drawOpacity,u),e.uniform4fv(r.uniforms.paqdUniforms,m)}({gl:this.gl,renderShader:this.renderShader,pickingImageShader:this.pickingImageShader,sliceShader:v,overlaysLength:this.overlays.length,clipPlaneColor:this.opts.clipPlaneColor,backOpacity:this.volumes[0].opacity,renderOverlayBlend:this.opts.renderOverlayBlend,clipPlane:this.scene.clipPlane,texVox:A,volScale:p,drawOpacity:this.drawOpacity,paqdUniforms:this.opts.paqdUniforms}),null!==m&&(this.gl.deleteTexture(m),this.gl.activeTexture(E),this.gl.bindTexture(this.gl.TEXTURE_2D,this.colormapTexture)),function(t){const{gl:e,shader:i,is2DSliceShader:n,drawTexture:r,paqdTexture:a,TEXTURE7_DRAW:s,TEXTURE8_PAQD:o}=t;e.uniform1i(i.uniforms.drawing,7),e.activeTexture(s),n?e.bindTexture(e.TEXTURE_2D,r):e.bindTexture(e.TEXTURE_3D,r),e.uniform1i(i.uniforms.paqd,8),e.activeTexture(o),e.bindTexture(e.TEXTURE_3D,a)}({gl:this.gl,shader:v,is2DSliceShader:this.opts.is2DSliceShader,drawTexture:this.drawTexture,paqdTexture:this.paqdTexture,TEXTURE7_DRAW:R,TEXTURE8_PAQD:P}),this.updateInterpolation(e)}colormaps(){return ve.colormaps()}addColormap(t,e){ve.addColormap(t,e)}setColormap(t,e){const i=this.getVolumeIndexByID(t);this.volumes[i].colormap=e,this.updateGLVolume()}idx(t,e,i,n){return Za(t,e,i,n)}check_previous_slice(t,e,i,n,r,a,s,o){return Ja(t,e,i,n,r,a,s,o)}do_initial_labelling(t,e,i){const n=_a(t,e,i);return[n.labelCount,n.translationTable,n.initialLabels]}fill_tratab(t,e,i){ja(t,e,i)}translate_labels(t,e,i,n){const r=$a(t,e,i,n);return[r.clusterCount,r.labels]}largest_original_cluster_labels(t,e,i){const n=ts(t,e,i);return[n.maxValue,n.voxels]}bwlabel(t,e,i,n,r){void 0===i&&(i=26),void 0===n&&(n=!1),void 0===r&&(r=!1);const a=function(t){const{img:e,dim:i,conn:n=26,binarize:r=!1,onlyLargestClusterPerClass:a=!1}=t,s=Date.now(),o=i[0]*i[1]*i[2],l=new Uint32Array(o).fill(0);if(![6,18,26].includes(n))return Q.info("bwlabel: conn must be 6, 18 or 26."),{clusterCount:0,labels:l};if(i[0]<2||i[1]<2||i[2]<1)return Q.info("bwlabel: img must be 2 or 3-dimensional"),{clusterCount:0,labels:l};if(r)for(let f=0;f<o;f++)0!==e[f]&&(l[f]=1);else l.set(e);let{labelCount:c,translationTable:h,initialLabels:d}=_a(l,i,n);void 0===h&&(h=new Uint32Array);const{clusterCount:u,labels:m}=$a(d,i,h,c);if(Q.info(n+" neighbor clustering into "+u+" regions in "+(Date.now()-s)+"ms"),a){const{maxValue:t,voxels:e}=ts(l,u,m);return{clusterCount:t,labels:e}}return{clusterCount:u,labels:m}}({img:t,dim:e,conn:i,binarize:n,onlyLargestClusterPerClass:r});return[a.clusterCount,a.labels]}async createConnectedLabelImage(t,e,i,n){void 0===e&&(e=26),void 0===i&&(i=!1),void 0===n&&(n=!1);const r=this.getVolumeIndexByID(t),a=Uint32Array.from(this.volumes[r].dims?.slice(1,4)??[]),s=Uint32Array.from(this.volumes[r].img?.slice()??[]),[o,l]=this.bwlabel(s,a,e,i,n),c=this.volumes[r].clone();c.opacity=.5,c.colormap="random";for(let h=0;h<c.img.length;h++)c.img[h]=l[h];return c.cal_min=0,c.cal_max=o,c}async createNiftiArray(t,e,i,n,r){return void 0===t&&(t=[256,256,256]),void 0===e&&(e=[
11,1,1]),void 0===i&&(i=[1,0,0,-128,0,1,0,-128,0,0,1,-128,0,0,0,1]),void 0===n&&(n=2),void 0===r&&(r=new Uint8Array),await Gi.createNiftiArray(t,e,i,n,r)}async niftiArray2NVImage(t){return void 0===t&&(t=new Uint8Array),await Gi.loadFromUrl({url:t})}async loadFromUrl(t){return await Gi.loadFromUrl({url:t})}async conform(t,e,i,s,o,l,c,h){void 0===e&&(e=!1),void 0===i&&(i=!0),void 0===s&&(s=!1),void 0===o&&(o=!1),void 0===l&&(l=[256,256,256]),void 0===c&&(c=1),void 0===h&&(h=!1);const[d,u,m]=l,f=c,{outAffine:g,invVox2vox:A}=function(t){const{inDims:e,inAffine:i,outDim:s=256,outDims:o,outMM:l=1,toRAS:c=!1}=t,[h,d,u]=o??[s,s,s],m=i.flat(),f=a.fA(m[0],m[1],m[2],m[3],m[4],m[5],m[6],m[7],m[8],m[9],m[10],m[11],m[12],m[13],m[14],m[15]),g=n.fA(e[1]/2,e[2]/2,e[3]/2,1),A=n.vt(),p=a.vt();a.mg(p,f),n.Z0(A,g,p);const v=r.fA(A[0],A[1],A[2]),x=r.fA(l,l,l);let w=a.fA(-1,0,0,0,0,0,1,0,0,-1,0,0,0,0,0,1);c&&(w=a.fA(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1)),a.mg(w,w);const y=n.fA(h,d,u,1),b=a.vt();a.hs(b,w,x);const C=n.fA(y[0],y[1],y[2],1);n.Z0(C,C,b),n.hs(C,C,.5);const M=r.vt();r.Re(M,v,r.fA(C[0],C[1],C[2]));const D=a.vt();a.mg(D,b),D[3]=M[0],D[7]=M[1],D[11]=M[2];const T=a.vt();a.B8(T,D);const I=a.vt();a.lK(I,f,T);const S=a.vt();return a.B8(S,I),{outAffine:D,vox2vox:I,invVox2vox:S}}({inDims:t.hdr.dims,inAffine:t.hdr.affine.flat(),outDims:[d,u,m],outMM:f,toRAS:e}),p=new Float32Array(t.img),v=t.hdr.dims[1]*t.hdr.dims[2]*t.hdr.dims[3];if(1!==t.hdr.scl_slope||0!==t.hdr.scl_inter)for(let n=0;n<v;n++)p[n]=p[n]*t.hdr.scl_slope+t.hdr.scl_inter;const x=function(t){const{inImg:e,inDims:i,outDim:n,outDims:r,invVox2vox:a,isLinear:s}=t,[o,l,c]=r??[n??256,n??256,n??256],h=new Float32Array(o*l*c),d=i[1],u=i[2],m=i[3],f=d*u;function g(t,e,i){return t+e*d+i*f}const A=a[0],p=a[4],v=a[8];let x=-1;if(s)for(let w=0;w<c;w++)for(let t=0;t<l;t++){const i=t*a[1]+w*a[2]+a[3],n=t*a[5]+w*a[6]+a[7],r=t*a[9]+w*a[10]+a[11];for(let t=0;t<o;t++){const a=t*A+i,s=t*p+n,o=t*v+r,l=Math.floor(a),c=Math.floor(s),w=Math.floor(o);if(x++,l<0||c<0||w<0)continue;const y=Math.ceil(a),b=Math.ceil(s),C=Math.ceil(o);if(y>=d||b>=u||C>=m)continue;const M=a-l,D=s-c,T=o-w,I=1-M,S=1-D,E=1-T,F=g(l,c,w);let B=0;B+=e[F]*I*S*E,B+=e[F+f]*I*S*T,B+=e[F+d]*I*D*E,B+=e[F+d+f]*I*D*T,B+=e[F+1]*M*S*E,B+=e[F+1+f]*M*S*T,B+=e[F+1+d]*M*D*E,B+=e[F+1+d+f]*M*D*T,h[x]=B}}else for(let w=0;w<c;w++)for(let t=0;t<l;t++){const i=t*a[1]+w*a[2]+a[3],n=t*a[5]+w*a[6]+a[7],r=t*a[9]+w*a[10]+a[11];for(let t=0;t<o;t++){const a=Math.round(t*A+i),s=Math.round(t*p+n),o=Math.round(t*v+r);x++,a<0||s<0||o<0||a>=d||s>=u||o>=m||(h[x]=e[g(a,s,o)])}}return h}({inImg:p,inDims:t.hdr.dims,outDims:[d,u,m],invVox2vox:A,isLinear:i});let w;if(h)w=await this.createNiftiArray([d,u,m],[f,f,f],Array.from(g),16,new Uint8Array(x.buffer));else if(s){const e=o?NaN:0,i={img:t.img,dims:t.hdr.dims,global_min:t.global_min,global_max:t.global_max,datatypeCode:t.hdr.datatypeCode,scl_slope:t.hdr.scl_slope,scl_inter:t.hdr.scl_inter,cal_min:t.cal_min,cal_max:t.cal_max,f_low:e,dst_min:0,dst_max:1},[n,r]=es(i),a=function(t,e,i,n,r){void 0===e&&(e=0),void 0===i&&(i=1);const a=t.length,s=new Float32Array(a);for(let o=0;o<a;o++){let a=t[o];a=e+r*(a-n),a=Math.max(a,e),a=Math.min(a,i),s[o]=a}return s}(x,0,1,n,r);w=await this.createNiftiArray([d,u,m],[f,f,f],Array.from(g),16,new Uint8Array(a.buffer))}else{const e=o?NaN:0,i={img:t.img,dims:t.hdr.dims,global_min:t.global_min,global_max:t.global_max,datatypeCode:t.hdr.datatypeCode,scl_slope:t.hdr.scl_slope,scl_inter:t.hdr.scl_inter,cal_min:t.cal_min,cal_max:t.cal_max,f_low:e,dst_min:0,dst_max:255},[n,r]=es(i),a=function(t,e,i,n,r){void 0===e&&(e=0),void 0===i&&(i=255);const a=t.length,s=new Uint8Array(a);for(let o=0;o<a;o++){let a=t[o];a=e+r*(a-n),a=Math.max(a,e),a=Math.min(a,i),s[o]=a}return s}(x,0,255,n,r);w=await this.createNiftiArray([d,u,m],[f,f,f],Array.from(g),2,a)}return this.niftiArray2NVImage(w)}setRenderDrawAmbientOcclusion(t){if(!this.renderShader)throw new Error("renderShader undefined");this.renderDrawAmbientOcclusion=t,this.renderShader.use(this.gl),this.gl.uniform1fv(this.renderShader.uniforms.renderDrawAmbientOcclusion,[this.renderDrawAmbientOcclusion,1]),this.drawScene()}setColorMap(t,e){this.setColormap(t,e)}setColormapNegative(t,e){const i=this.getVolumeIndexByID(t);this.volumes[i].colormapNegative=e,this.updateGLVolume()}setModulationImage(t,e,i){void 0===i&&(i=0);const n=this.getVolumeIndexByID(t);let r=null;e.length>0&&(r=this.getVolumeIndexByID(e)),this.volumes[n].modulationImage=r,this.volumes[n].modulateAlpha=i,this.updateGLVolume()}setGamma(t){void 0===t&&(t=1),this.scene.gamma=t,ve.gamma=t,this.updateGLVolume()}async loadDeferred4DVolumes(t){const e=this.getVolumeIndexByID(t),i=this.volumes[e];if(i.nTotalFrame4D<=i.nFrame4D)return;let n;i.nTotalFrame4D=i.nFrame4D,n=i.fileObject?await Gi.loadFromFile({file:i.fileObject}):await Gi.loadFromUrl({url:i.url}),n&&(i.img=n.img.slice(),i.nTotalFrame4D=n.nTotalFrame4D,i.nFrame4D=n.nFrame4D,this.updateGLVolume())}setFrame4D(t,e){const i=this.getVolumeIndexByID(t);if(i<0)return;const n=this.volumes[i].frame4D;
1!function(t,e,i){const n=rr(t,e);if(n<0)return t;const r=t[n];let a=i;a>r.nFrame4D-1&&(a=r.nFrame4D-1),a<0&&(a=0),a===r.frame4D||(r.frame4D=a)}(this.volumes,t,e),this.volumes[i].frame4D!==n&&(this.updateGLVolume(),this._emitEvent("frameChange",{volume:this.volumes[i],index:this.volumes[i].frame4D}),this.onFrameChange(this.volumes[i],this.volumes[i].frame4D),this.createOnLocationChange())}getFrame4D(t){return function(t,e){const i=rr(t,e);return i<0?0:t[i].frame4D}(this.volumes,t)}colormapFromKey(t){return ve.colormapFromKey(t)}colormap(t,e){return void 0===t&&(t=""),void 0===e&&(e=!1),ve.colormap(t,e)}createColormapTexture(t,e,i){return void 0===t&&(t=null),void 0===e&&(e=0),void 0===i&&(i=256),null!==t&&this.gl.deleteTexture(t),e<1||i<1?null:(t=this.gl.createTexture(),this.gl.activeTexture(E),this.gl.bindTexture(this.gl.TEXTURE_2D,t),this.gl.texStorage2D(this.gl.TEXTURE_2D,1,this.gl.RGBA8,i,e),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_MIN_FILTER,this.gl.LINEAR),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_MAG_FILTER,this.gl.LINEAR),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_WRAP_R,this.gl.CLAMP_TO_EDGE),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_WRAP_S,this.gl.CLAMP_TO_EDGE),this.gl.pixelStorei(this.gl.UNPACK_ALIGNMENT,1),t)}addColormapList(t,e,i,n,r,a,s){void 0===t&&(t=""),void 0===e&&(e=NaN),void 0===i&&(i=NaN),void 0===n&&(n=!1),void 0===r&&(r=!1),void 0===a&&(a=!0),void 0===s&&(s=!1),t.length<1&&(a=!1),this.colormapLists.push({name:t,min:e,max:i,isColorbarFromZero:n,negative:r,visible:a,invert:s})}refreshColormaps(){if(this.colormapLists=[],this.volumes.length<1&&this.meshes.length<1)return;const t=this.volumes.length;if(t>0)for(let a=0;a<t;a++){const t=this.volumes[a],e=An(t.cal_min,t.cal_max,t.cal_minNeg,t.cal_maxNeg),i=0!==t.colormapType;this.addColormapList(t.colormapNegative,e[0],e[1],i,!0,t.colorbarVisible,t.colormapInvert),this.addColormapList(t.colormap,t.cal_min,t.cal_max,i,!1,t.colorbarVisible,t.colormapInvert)}const e=this.meshes.length;if(e>0)for(let a=0;a<e;a++){const t=this.meshes[a];if(!t.colorbarVisible)continue;const e=t.layers.length,i=t.fiberColor.toLowerCase();if(t.offsetPt0&&i.startsWith("dp")){let e=null;const n=parseInt(i.substring(3));i.startsWith("dpg")&&!t.fiberGroupColormap&&(e=n<t.dpg.length?t.dpg[n]:t.dpg[0]),i.startsWith("dps")&&(e=n<t.dps.length?t.dps[n]:t.dps[0]),i.startsWith("dpv")&&(e=n<t.dpv.length?t.dpv[n]:t.dpv[0]),e&&"string"==typeof t.colormap&&this.addColormapList(t.colormap,e.cal_min,e.cal_max,!1,!1,!0,t.colormapInvert)}if("edgeColormap"in t&&"edges"in t&&void 0!==t.edges){const e=An(t.edgeMin,t.edgeMax,NaN,NaN);this.addColormapList(t.edgeColormapNegative,e[0],e[1],!1,!0,!0,t.colormapInvert),this.addColormapList(t.edgeColormap,t.edgeMin,t.edgeMax,!1,!1,!0,t.colormapInvert)}if(!(e<1))for(let n=0;n<e;n++){const t=this.meshes[a].layers[n];if(!t.colorbarVisible)continue;if(t.colormap.length<1)continue;const e=0!==t.colormapType;if(t.useNegativeCmap){const i=An(t.cal_min,t.cal_max,t.cal_minNeg,t.cal_maxNeg);this.addColormapList(t.colormapNegative,i[0],i[1],e,!0,!0,t.colormapInvert)}this.addColormapList(t.colormap,t.cal_min,t.cal_max,e,!1,!0,t.colormapInvert)}}const i=this.colormapLists.length;if(i<1)return;this.colormapTexture=this.createColormapTexture(this.colormapTexture,i+1);let n=new Uint8ClampedArray;function r(t){const e=new Uint8ClampedArray(n.length+t.length);e.set(n),e.set(t,n.length),n=e}for(let a=0;a<i;a++)r(Array.from(this.colormap(this.colormapLists[a].name,this.colormapLists[a].invert)));return r(Array.from(this.drawLut.lut)),this.gl.texSubImage2D(this.gl.TEXTURE_2D,0,0,0,256,i+1,this.gl.RGBA,this.gl.UNSIGNED_BYTE,n),this}sliceScale(t){if(void 0===t&&(t=!1),!this.back?.dims)throw new Error("back.dims undefined");return function(t){const{forceVox:e,getScreenFieldOfViewMM:i,getScreenFieldOfViewVox:n,backDims:r}=t;let a=i(0);e&&(a=n(0));const s=Math.max(a[0],Math.max(a[1],a[2]));return{volScale:[a[0]/s,a[1]/s,a[2]/s],vox:[r[1],r[2],r[3]],longestAxis:s,dimsMM:a}}({forceVox:t,getScreenFieldOfViewMM:t=>this.screenFieldOfViewMM(t),getScreenFieldOfViewVox:t=>this.screenFieldOfViewVox(t),backDims:this.back.dims})}tileIndex(t,e){return va({x:t,y:e,screenSlices:this.screenSlices})}inRenderTile(t,e){return function(t){const{x:e,y:i,screenSlices:n}=t,r=va({x:e,y:i,screenSlices:n});return r>=0&&4===n[r].axCorSag?r:-1}
1({x:t,y:e,screenSlices:this.screenSlices})}sliceScroll3D(t){void 0===t&&(t=0);const e=function(t){const{posChange:e,volumesLength:i,clipPlaneDepthAziElevs:n,activeClipPlaneIndex:r,volScaleMultiplier:a}=t;if(0===e)return{action:"none"};if(i>0&&n[r][0]<1.8){const t=n[r][0];let i=t;return e>0&&(i=Math.min(1.5,t+.025)),e<0&&(i=Math.max(-1.5,t-.025)),i!==t?{action:"clipPlane",newClipPlaneDepth:i}:{action:"none"}}let s=a;return e>0&&(s=Math.min(2,1.1*a)),e<0&&(s=Math.max(.5,.9*a)),{action:"zoom",newVolScaleMultiplier:s}}({posChange:t,volumesLength:this.volumes.length,clipPlaneDepthAziElevs:this.scene.clipPlaneDepthAziElevs,activeClipPlaneIndex:this.uiData.activeClipPlaneIndex,volScaleMultiplier:this.scene.volScaleMultiplier});if("none"!==e.action){if("clipPlane"===e.action&&void 0!==e.newClipPlaneDepth){const t=this.scene.clipPlaneDepthAziElevs[this.uiData.activeClipPlaneIndex].slice();return t[0]=e.newClipPlaneDepth,this.scene.clipPlaneDepthAziElevs[this.uiData.activeClipPlaneIndex]=t,this.setClipPlane(this.scene.clipPlaneDepthAziElevs[this.uiData.activeClipPlaneIndex])}"zoom"===e.action&&void 0!==e.newVolScaleMultiplier&&(this.scene.volScaleMultiplier=e.newVolScaleMultiplier,this.drawScene())}}inGraphTile(t,e){return function(t){const{x:e,y:i,graph:n,volumesLength:r,firstVolumeFrameCount:a}=t;if(n.opacity<=0||r<1||a<1||!n.plotLTWH)return!1;if(n.plotLTWH[2]<1||n.plotLTWH[3]<1)return!1;const s=[(e-n.LTWH[0])/n.LTWH[2],(i-n.LTWH[1])/n.LTWH[3]];return s[0]>0&&s[1]>0&&s[0]<=1&&s[1]<=1}({x:t,y:e,graph:this.graph,volumesLength:this.volumes.length,firstVolumeFrameCount:this.volumes.length>0?this.volumes[0].nFrame4D??0:0})}updateBitmapFromClickToSegment(){null!==this.clickToSegmentGrowingBitmap&&null!==this.drawBitmap&&function(t){const{sourceBitmap:e,targetBitmap:i}=t;if(!e||!i)return!1;if(e.length!==i.length)return!1;const n=i.length;for(let r=0;r<n;r++)i[r]=e[r]}({sourceBitmap:this.clickToSegmentGrowingBitmap,targetBitmap:this.drawBitmap})}sumBitmap(t){return function(t){let e=0;for(let i=0;i<t.length;i++)e+=t[i];return e}(t)}doClickToSegment(t){const{tileIndex:e}=t;if(e<0||e>=this.screenSlices.length)return void Q.warn(`Invalid tileIndex ${e} received in doClickToSegment.`);const i=this.screenSlices[e].axCorSag;if(i>2)return void Q.warn("ClickToSegment attempted on non-2D slice tile.");const n=this.screenXY2TextureFrac(this.clickToSegmentXY[0],this.clickToSegmentXY[1],e,!1);if(n[0]<0)return void Q.debug("Click location outside valid texture fraction for the tile.");const r=this.frac2vox(n),a=function(t){const{voxelIntensity:e,thresholdPercent:i,calMin:n,calMax:r,autoIntensity:a,currentIntensityMin:s,currentIntensityMax:o,currentBright:l}=t;let c=s,h=o,d=l;if(a){if(0!==i){const t=0===e?.01:e;h=t*(1+i),c=t*(1-i)}d=e>.5*(n+r)}return{intensityMin:c,intensityMax:h,isBright:d}}({voxelIntensity:this.back.getValue(r[0],r[1],r[2]),thresholdPercent:this.opts.clickToSegmentPercent,calMin:this.back.cal_min,calMax:this.back.cal_max,autoIntensity:this.opts.clickToSegmentAutoIntensity,currentIntensityMin:this.opts.clickToSegmentIntensityMin,currentIntensityMax:this.opts.clickToSegmentIntensityMax,currentBright:this.opts.clickToSegmentBright});this.opts.clickToSegmentIntensityMin=a.intensityMin,this.opts.clickToSegmentIntensityMax=a.intensityMax,this.opts.clickToSegmentBright=a.isBright;const s=a.isBright?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY;this.drawPenAxCorSag=i;const o=this.clickToSegmentIsGrowing?this.clickToSegmentGrowingBitmap:this.drawBitmap;if(!o){if(Q.error("Target bitmap for flood fill is null."),this.clickToSegmentIsGrowing){if(this.drawBitmap||this.createEmptyDrawing(),!this.drawBitmap)return;this.clickToSegmentGrowingBitmap=this.drawBitmap.slice()}else if(this.createEmptyDrawing(),!this.drawBitmap)return;Q.warn("Initialized missing bitmap in doClickToSegment.")}if(this.drawFloodFill([r[0],r[1],r[2]],this.opts.penValue,s,this.opts.clickToSegmentIntensityMin,this.opts.clickToSegmentIntensityMax,this.opts.floodFillNeighbors,this.opts.clickToSegmentMaxDistanceMM,this.opts.clickToSegmentIs2D,o),!this.clickToSegmentIsGrowing&&(Q.debug("Applying clickToSegment mask to drawBitmap."),this.drawBitmap?(this.refreshDrawing(!1,!1),this.drawScene()):Q.error("Cannot refresh drawing after click-to-segment apply, drawBitmap is null."),this.drawBitmap)){const t=this.getDescriptives({layer:0,masks:[],drawingIsMask:!0}),e={mL:t.volumeML,mm3:t.volumeMM3};this._emitEvent("clickToSegment",e),this.onClickToSegment(e)}this.createOnLocationChange(i)}
1mouseClick(t,e,i,n){if(void 0===i&&(i=0),void 0===n&&(n=!0),t*=this.uiData.dpr,e*=this.uiData.dpr,this.canvas.focus(),this.thumbnailVisible)return this.thumbnailVisible=!1,Promise.all([this.loadVolumes(this.deferredVolumes),this.loadMeshes(this.deferredMeshes)]).catch((t=>{throw t})),!0;if(this.inGraphTile(t,e)){if(!this.graph.plotLTWH)throw new Error("plotLTWH undefined");const i=[(t-this.graph.plotLTWH[0])/this.graph.plotLTWH[2],(e-this.graph.plotLTWH[1])/this.graph.plotLTWH[3]];if(i[0]>0&&i[1]>0&&i[0]<=1&&i[1]<=1){const t=Math.round(i[0]*(this.volumes[0].nFrame4D-1));return this.setFrame4D(this.volumes[0].id,t),!0}return i[0]>.5&&i[1]>1&&this.loadDeferred4DVolumes(this.volumes[0].id).catch((t=>{throw t})),!1}if(this.inRenderTile(t,e)>=0)return 0!==i&&(this.sliceScroll3D(i),this.drawScene(),!0);if(this.screenSlices.length<1||this.gl.canvas.height<1||this.gl.canvas.width<1)return!1;for(let a=0;a<this.screenSlices.length;a++){const s=this.screenSlices[a].axCorSag;if(this.drawPenAxCorSag>=0&&this.drawPenAxCorSag!==s)continue;if(s>2&&!this.opts.clickToSegment&&0===i)continue;const o=this.screenXY2TextureFrac(t,e,a,!0);if(o[0]<0)continue;if(0!==i||!n){if(!n)return s<=2&&(this.scene.crosshairPos[2-s]=i,this.drawScene(),this.createOnLocationChange(s)),!0;const t=i<0?-1:1,e=[0,0,0];return s<=2&&(e[2-s]=t,this.moveCrosshairInVox(e[0],e[1],e[2])),!0}const l=this.opts.isForceMouseClickToVoxelCenters?this.vox2frac(this.frac2vox(o)):o;if(!!r.aI(this.scene.crosshairPos,l)&&!this.opts.drawingEnabled)return!1;if(this.scene.crosshairPos=r.o8(l),this.opts.drawingEnabled){const t=this.frac2vox(this.scene.crosshairPos);if(!isFinite(this.opts.penValue)||this.opts.penValue<0||Object.is(this.opts.penValue,-0)){let e=0,i=Math.abs(this.opts.penValue);const n=!0;return Object.is(this.opts.penValue,-0)?(e=0,i=0,Q.debug("Erase Cluster selected")):(e=this.opts.penValue,Q.debug("Intensity Grow selected",e)),this.drawFloodFill(t,i,e,NaN,NaN,this.opts.floodFillNeighbors,Number.POSITIVE_INFINITY,!1,this.drawBitmap,n),this.drawScene(),this.createOnLocationChange(s),!0}if(this.opts.clickToSegment)return s<=2&&(this.clickToSegmentIsGrowing=!1,this.doClickToSegment({x:this.clickToSegmentXY[0],y:this.clickToSegmentXY[1],tileIndex:a})),this.createOnLocationChange(s),!0;if(0===this.opts.penType){if(isNaN(this.drawPenLocation[0]))this.drawPenAxCorSag=s,this.drawPenFillPts=[],this.drawPt(...t,this.opts.penValue);else{if(t[0]===this.drawPenLocation[0]&&t[1]===this.drawPenLocation[1]&&t[2]===this.drawPenLocation[2])return this.drawScene(),this.createOnLocationChange(s),!0;this.drawPenLine(t,this.drawPenLocation,this.opts.penValue)}this.drawPenLocation=t,this.opts.isFilledPen&&this.drawPenFillPts.push(t),this.refreshDrawing(!1,!1)}else 1!==this.opts.penType&&2!==this.opts.penType||(isNaN(this.drawShapeStartLocation[0])?(this.drawPenAxCorSag=s,this.drawShapeStartLocation=[...t],this.drawBitmap&&(this.drawShapePreviewBitmap=this.drawBitmap.slice())):this.drawShapePreviewBitmap&&this.drawBitmap&&(this.drawBitmap.set(this.drawShapePreviewBitmap),1===this.opts.penType?this.drawRectangleMask(this.drawShapeStartLocation,t,this.opts.penValue):2===this.opts.penType&&this.drawEllipseMask(this.drawShapeStartLocation,t,this.opts.penValue),this.refreshDrawing(!1,!1)))}return this.drawScene(),this.createOnLocationChange(s),!0}return!1}drawRuler(){let t=[],e=[];for(let h=0;h<this.screenSlices.length;h++)if(4!==this.screenSlices[h].axCorSag&&this.screenSlices[h].fovMM.length>1){e=this.screenSlices[h].leftTopWidthHeight,t=this.screenSlices[h].fovMM;break}if(e.length<4)return;const[i,n,r,a]=this.getBoundsRegion(),s=Number(this.opts.rulerWidth),o=function(t){const{fovMM:e,ltwh:i,rulerWidth:n,regionBounds:r}=t;if(i.length<4||e.length<1)return null;const a=100/e[0]*i[2],s=Math.max(Math.round(.1*a),2),o=Math.floor(i[0]+.5*i[2]-.5*a),l=Math.floor(i[1]+i[3]-s)+.5*n,c=Math.max(r.x,o),h=Math.min(r.x+r.w,o+a),d=Math.min(r.y+r.h,l);return h<=c?null:{startXYendXY:[c,d,h,d],pix1cm:s,clipped:c>o||h<o+a}}({fovMM:t,ltwh:e,rulerWidth:s,regionBounds:{x:i,y:n,w:r,h:a}});if(!o)return;const l=(c=this.opts.rulerColor)[0]+c[1]+c[2]<.8?[1,1,1,1]:[0,0,0,1];var c;this.drawRuler10cm(o.startXYendXY,l,s+1),this.drawRuler10cm(o.startXYendXY,this.opts.rulerColor,s)}drawRuler10cm(t,e,i){if(void 0===i&&(i=1),!this.lineShader)throw new Error("lineShader undefined");this.gl.bindVertexArray(this.genericVAO),this.lineShader.use(this.gl),this.gl.uniform4fv(this.lineShader.uniforms.lineColor,e),this.gl.uniform2fv(this.lineShader.uniforms.canvasWidthHeight,[this.gl.canvas.width,this.gl.canvas.height]),this.gl.uniform1f(this.lineShader.uniforms.thickness,i),this.gl.uniform4fv(this.lineShader.uniforms.startXYendXY,t),this.gl.drawArrays(this.gl.TRIANGLE_STRIP,0,4);const n=function(t,e){const i=[],n=-.1*(t[0]-t[2]),r=t[1]-Math.floor(.5*e),a=Math.floor(r-.35*n),s=Math.floor(r-.7*n);for(let o=0;o<11;o++){let l=t[0]+o*n;l=Math.max(l,t[0]+.5*e),l=Math.min(l,t[2]-.5*e);const c=[l,r,l,o%5==0?s:a];i.push(c)}return i}(t,this.opts.rulerWidth);for(const r of n)this.gl.uniform4fv(this.lineShader.uniforms.startXYendXY,r),this.gl.drawArrays(this.gl.TRIANGLE_STRIP,0,4);this.gl.bindVertexArray(this.unusedVAO)}
1screenXY2mm(t,e,i){return void 0===i&&(i=-1),function(t,e,i,r){const{volumes:a,meshes:s,volumeObject3D:o,isSliceMM:l=!1,forceSlice:c=-1}=r;for(let h=0;h<i.length;h++){let r=h;c>=0&&(r=c);const d=i[r];if(d.axCorSag>2)continue;const u=d.leftTopWidthHeight;if(t<u[0]||e<u[1]||t>u[0]+u[2]||e>u[1]+u[3])continue;const m=bn(t,e,i,r,{volumes:a,meshes:s,volumeObject3D:o,isSliceMM:l,restrict0to1:!1});if(m[0]<0)continue;const f=yn(m,{volumes:a,meshes:s,volumeObject3D:o,isSliceMM:l});return n.fA(f[0],f[1],f[2],r)}return n.fA(NaN,NaN,NaN,NaN)}(t,e,this.screenSlices,{volumes:this.volumes,meshes:this.meshes,volumeObject3D:this.volumeObject3D,isSliceMM:this.opts.isSliceMM,forceSlice:i})}dragForPanZoom(t){const e=this.getZarrVolumes().filter((t=>t.zarrHelper?.centerAtDragStart));if(e.length>0){const i=t[2]-t[0],n=t[3]-t[1];if(0===i&&0===n)return;let r,a,s=0;for(const e of this.screenSlices){if(e.axCorSag>2)continue;const i=e.leftTopWidthHeight,n=t[0],r=t[1];if(n>=i[0]&&r>=i[1]&&n<=i[0]+i[2]&&r<=i[1]+i[3]){s=e.axCorSag;break}}0===s?(r=0,a=1):1===s?(r=0,a=2):(r=1,a=2);const o=[];for(const t of e){const e=t.zarrHelper,s=t.hdr.affine,l=[{col:0,sign:-1},{col:1,sign:-1},{col:2,sign:-1}];for(let t=0;t<3;t++){let e=0;for(let i=0;i<3;i++){const n=Math.abs(s[t][i]);n>e&&(e=n,l[t]={col:i,sign:s[t][i]<0?-1:1})}}const c=e.centerAtDragStart,h=[c.x,c.y,c.z];h[l[r].col]+=i*l[r].sign,h[l[a].col]+=-n*l[a].sign;const d=h[0],u=h[1],m=h[2],f=e.getViewportState(),g=Math.abs(d-f.centerX),A=Math.abs(u-f.centerY),p=Math.abs(m-f.centerZ);g<.001&&A<.001&&p<.001||o.push(e.panTo(d,u,m))}return o.length>0&&Promise.all(o).then((()=>{this._skipDragInDraw=!0,this.drawScene(),this._skipDragInDraw=!1})).catch((t=>{Q.error("Failed to pan Zarr:",t)})),void this.canvas.focus()}const i=this.screenXY2mm(t[2],t[3]);if(isNaN(i[0]))return;const r=this.screenXY2mm(t[0],t[1],i[3]);if(isNaN(r[0])||isNaN(i[0])||isNaN(i[3]))return;const a=function(t){const{startMM:e,endMM:i,pan2DxyzmmAtMouseDown:r}=t,a=n.vt();n.jb(a,i,e);const s=r[3];return{pan2Dxyzmm:[r[0]+s*a[0],r[1]+s*a[1],r[2]+s*a[2],s]}}({startMM:r,endMM:i,pan2DxyzmmAtMouseDown:this.uiData.pan2DxyzmmAtMouseDown});this.scene.pan2Dxyzmm[0]=a.pan2Dxyzmm[0],this.scene.pan2Dxyzmm[1]=a.pan2Dxyzmm[1],this.scene.pan2Dxyzmm[2]=a.pan2Dxyzmm[2],this.canvas.focus()}dragForCenterButton(t){this.dragForPanZoom(t)}dragForSlicer3D(t){const e=this.frac2mm(this.scene.crosshairPos),i=function(t){const{startY:e,endY:i,pan2DxyzmmAtMouseDown:n,currentPan2Dxyzmm:r,crosshairMM:a,yoke3Dto2DZoom:s}=t;let o=n[3];o+=.01*(i-e),o=Math.max(o,.1),o=Math.min(o,10);const l=r[3]-o,c={zoom:o,pan2Dxyzmm:[r[0]+l*a[0],r[1]+l*a[1],r[2]+l*a[2],o]};return s&&(c.volScaleMultiplier=o),c}({startY:t[1],endY:t[3],pan2DxyzmmAtMouseDown:this.uiData.pan2DxyzmmAtMouseDown,currentPan2Dxyzmm:this.scene.pan2Dxyzmm,crosshairMM:e,yoke3Dto2DZoom:this.opts.yoke3Dto2DZoom});void 0!==i.volScaleMultiplier&&(this.scene.volScaleMultiplier=i.volScaleMultiplier),this.scene.pan2Dxyzmm[0]=i.pan2Dxyzmm[0],this.scene.pan2Dxyzmm[1]=i.pan2Dxyzmm[1],this.scene.pan2Dxyzmm[2]=i.pan2Dxyzmm[2],this.scene.pan2Dxyzmm[3]=i.pan2Dxyzmm[3]}drawMeasurementTool(t,e){void 0===e&&(e=!0);const i=(t,e,i,n,r)=>function(t){const{startXYendXY:e,distance:i}=t,n=e[0],r=e[1],a=e[2],s=e[3],o=n-a,l=r-s;if(0===o&&0===l)return{origin:[a+i,s],terminus:[a+i,s]};const c=Math.sqrt(o*o+l*l),h=i*o/c,d=i*l/c;return{origin:[n+h,r+d],terminus:[a-h,s-d]}}({startXYendXY:[t,e,i,n],distance:r}),n=this.gl;if(n.viewport(0,0,n.canvas.width,n.canvas.height),n.bindVertexArray(this.genericVAO),n.depthFunc(n.ALWAYS),n.enable(n.BLEND),n.blendFunc(n.SRC_ALPHA,n.ONE_MINUS_SRC_ALPHA),!this.lineShader)throw new Error("lineShader undefined");this.lineShader.use(this.gl),n.uniform4fv(this.lineShader.uniforms.lineColor,this.opts.rulerColor),n.uniform2fv(this.lineShader.uniforms.canvasWidthHeight,[n.canvas.width,n.canvas.height]),n.uniform1f(this.lineShader.uniforms.thickness,this.opts.rulerWidth),n.uniform4fv(this.lineShader.uniforms.startXYendXY,t),n.drawArrays(n.TRIANGLE_STRIP,0,4);const a=this.opts.measureLineColor;a[3]=1,n.uniform4fv(this.lineShader.uniforms.lineColor,a);const s=this.opts.rulerWidth;n.uniform1f(this.lineShader.uniforms.thickness,2*s);let o=[t[0],t[1]-s,t[0],t[1]+s];n.uniform4fv(this.lineShader.uniforms.startXYendXY,o),n.drawArrays(n.TRIANGLE_STRIP,0,4),o=[t[2],t[3]-s,t[2],t[3]+s],n.uniform4fv(this.lineShader.uniforms.startXYendXY,o),n.drawArrays(n.TRIANGLE_STRIP,0,4);let l=this.canvasPos2frac([t[0],t[1]]),c=this.canvasPos2frac([t[2],t[3]]);if(l[0]>=0&&c[0]>=0){const n=this.frac2mm(l);l=r.fA(n[0],n[1],n[2]);const a=this.frac2mm(c);c=r.fA(a[0],a[1],a[2]);const s=r.vt();r.jb(s,l,c);const o=r.Il(s);let h=2;o>9&&(h=1),o>99&&(h=0);let d=o.toFixed(h);this.opts.showMeasureUnits&&(d=`${d} mm`);let u=t;const[m,f,g,A]=t,{origin:p,terminus:v}=i(m,f,g,A,30);switch(this.opts.measureTextJustify){case"start":u=[...p,...p.map((t=>t+1))];break;case"end":u=u=[...v,...v.map((t=>t+1))];break;default:u=t}e&&this.drawTextBetween(u,d,this.opts.measureTextHeight/.06,this.opts.measureTextColor)}n.bindVertexArray(this.unusedVAO)}drawAngleMeasurementTool(){"drawing_first_line"===this.uiData.angleState?this.drawMeasurementTool([this.uiData.dragStart[0],this.uiData.dragStart[1],this.uiData.dragEnd[0],this.uiData.dragEnd[1]],!1):"drawing_second_line"===this.uiData.angleState&&(this.drawMeasurementTool(this.uiData.angleFirstLine,!1),this.drawMeasurementTool([this.uiData.angleFirstLine[2],this.uiData.angleFirstLine[3],this.uiData.dragEnd[0],this.uiData.dragEnd[1]],!1),this.drawAngleText())}drawAngleText(){const t=this.uiData.angleFirstLine,e=[this.uiData.angleFirstLine[2],this.uiData.angleFirstLine[3],this.uiData.dragEnd[0],this.uiData.dragEnd[1]],i=this.calculateAngleBet
1weenLines(t,e),n=this.uiData.angleFirstLine[2],r=this.uiData.angleFirstLine[3],a=`${i.toFixed(1)}\xb0`;this.drawTextBetween([n,r,n+1,r+1],a,this.opts.measureTextHeight/.06,this.opts.measureTextColor)}drawAngleTextForAngle(t){const e=this.calculateAngleBetweenLines(t.firstLine,t.secondLine),i=t.firstLine[2],n=t.firstLine[3],r=`${e.toFixed(1)}\xb0`;this.drawTextBetween([i,n,i+1,n+1],r,this.opts.measureTextHeight/.06,this.opts.measureTextColor)}calculateAngleBetweenLines(t,e){return function(t,e){const i=t[2],n=t[3],r=t[0]-i,a=t[1]-n,s=e[2]-i,o=e[3]-n,l=r*s+a*o,c=Math.sqrt(r*r+a*a),h=Math.sqrt(s*s+o*o);if(0===c||0===h)return 0;const d=Math.max(-1,Math.min(1,l/(c*h)));return Math.acos(d)*(180/Math.PI)}(t,e)}resetAngleMeasurement(){const t={angleState:"none",angleFirstLine:[0,0,0,0]};this.uiData.angleState=t.angleState,this.uiData.angleFirstLine=t.angleFirstLine}getCurrentSliceInfo(){return function(t){const{dragStart:e,screenSlices:i,crosshairPos:n,currentSliceType:r,canvasPos2frac:a}=t,s=va({x:e[0],y:e[1],screenSlices:i});if(s>=0&&s<i.length){const t=i[s].axCorSag;return{sliceIndex:s,sliceType:t,slicePosition:xa({sliceType:t,crosshairPos:n})}}let o=0;0===r?o=n[2]:1===r?o=n[1]:2===r?o=n[0]:3===r&&a([e[0],e[1]])[0]>=0&&(o=n[2]);return{sliceIndex:-1,sliceType:r,slicePosition:o}}({dragStart:this.uiData.dragStart,screenSlices:this.screenSlices,crosshairPos:this.scene.crosshairPos,currentSliceType:this.opts.sliceType,canvasPos2frac:t=>this.canvasPos2frac(t)})}getCurrentSlicePosition(t){return xa({sliceType:t,crosshairPos:this.scene.crosshairPos})}shouldDrawOnCurrentSlice(t,e,i){return function(t){const{sliceType:e,slicePosition:i,currentSliceTypeOpt:n,screenSlices:r,crosshairPos:a}=t;if(3===n){if(e>2)return!1;for(let t=0;t<r.length;t++)if(r[t].axCorSag===e){const t=xa({sliceType:e,crosshairPos:a}),n=.001;if(Math.abs(t-i)<n)return!0}return!1}if(e!==n)return!1;const s=xa({sliceType:e,crosshairPos:a});return Math.abs(s-i)<.001}({sliceIndex:t,sliceType:e,slicePosition:i,currentSliceTypeOpt:this.opts.sliceType,screenSlices:this.screenSlices,crosshairPos:this.scene.crosshairPos})}clearMeasurements(){this.document.completedMeasurements=[],this.drawScene()}clearAngles(){this.document.completedAngles=[],this.drawScene()}clearAllMeasurements(){this.document.completedMeasurements=[],this.document.completedAngles=[],this.drawScene()}setDragMode(t){const e=function(t){if("string"==typeof t){const e=ma[t];return void 0!==e?e:null}return t}(t);null!==e?(this.opts.dragMode=e,7!==this.opts.dragMode&&this.resetAngleMeasurement(),this.clearActiveDragMode()):console.warn(`Unknown drag mode: ${t}`)}setMouseEventConfig(t){this.opts.mouseEventConfig=t,this.clearActiveDragMode()}setTouchEventConfig(t){this.opts.touchEventConfig=t,this.clearActiveDragMode()}getMouseEventConfig(){return this.opts.mouseEventConfig}getTouchEventConfig(){return this.opts.touchEventConfig}drawRect(t,e){if(void 0===e&&(e=[1,0,0,-1]),e[3]<0&&(e=this.opts.crosshairColor),!this.rectShader)throw new Error("rectShader undefined");this.gl.disable(this.gl.CULL_FACE),this.opts.selectionBoxIsOutline?(this.drawCircle(t,e,.1),this.rectOutlineShader.use(this.gl),this.gl.enable(this.gl.BLEND),this.gl.uniform1f(this.rectOutlineShader.uniforms.thickness,this.opts.selectionBoxLineThickness),this.gl.uniform4fv(this.rectOutlineShader.uniforms.lineColor,e),this.gl.uniform2fv(this.rectOutlineShader.uniforms.canvasWidthHeight,[this.gl.canvas.width,this.gl.canvas.height]),this.gl.uniform4f(this.rectOutlineShader.uniforms.leftTopWidthHeight,t[0],t[1],t[2],t[3]),this.gl.bindVertexArray(this.genericVAO),this.gl.drawArrays(this.gl.TRIANGLE_STRIP,0,4),this.gl.bindVertexArray(this.unusedVAO)):(this.rectShader.use(this.gl),this.gl.enable(this.gl.BLEND),this.gl.uniform4fv(this.rectShader.uniforms.lineColor,e),this.gl.uniform2fv(this.rectShader.uniforms.canvasWidthHeight,[this.gl.canvas.width,this.gl.canvas.height]),this.gl.uniform4f(this.rectShader.uniforms.leftTopWidthHeight,t[0],t[1],t[2],t[3]),this.gl.bindVertexArray(this.genericVAO),this.gl.drawArrays(this.gl.TRIANGLE_STRIP,0,4),this.gl.bindVertexArray(this.unusedVAO))}getZarrVolume(){for(const t of this.volumes)if(t.zarrHelper)return t;return null}getZarrVolumes(){return this.volumes.filter((t=>t.zarrHelper))}drawBoundsBox(t,e,i){if(void 0===i&&(i=2),!this.rectOutlineShader)throw new Error("rectOutlineShader undefined");const n=this.gl,[r,a,s,o]=t;n.viewport(0,0,n.canvas.width,n.canvas.height),this.rectOutlineShader.use(n),n.enable(n.BLEND),n.uniform1f(this.rectOutlineShader.uniforms.thickness,i),n.uniform4fv(this.rectOutlineShader.uniforms.lineColor,e),n.uniform2fv(this.rectOutlineShader.uniforms.canvasWidthHeight,[n.canvas.width,n.canvas.height]),n.uniform4f(this.rectOutlineShader.uniforms.leftTopWidthHeight,r,a,s,o),n.bindVertexArray(this.genericVAO),n.drawArrays(n.TRIANGLE_STRIP,0,4),n.bindVertexArray(this.unusedVAO)}drawCircle(t,e,i){if(void 0===e&&(e=this.opts.fontColor),void 0===i&&(i=1),!this.circleShader)throw new Error("circleShader undefined");this.circleShader.use(this.gl),this.gl.enable(this.gl.BLEND),this.gl.uniform4fv(this.circleShader.uniforms.circleColor,e),this.gl.uniform2fv(this.circleShader.uniforms.canvasWidthHeight,[this.gl.canvas.width,this.gl.canvas.height]),this.gl.uniform4f(this.circleShader.uniforms.leftTopWidthHeight,t[0],t[1],t[2],t[3]),this.gl.uniform1f(this.circleShader.uniforms.fillPercent,i),this.gl.uniform4fv(this.circleShader.uniforms.circleColor,e),this.gl.bindVertexArray(this.genericVAO),this.gl.drawArrays(this.gl.TRIANGLE_STRIP,0,4),this.gl.bindVertexArray(this.unusedVAO)}drawSelectionBox(t){this.gl.viewport(0,0,this.gl.canvas.width,this.gl.canvas.height),6!==this.getCurrentDragMode()?this.drawRect(t,this.opts.selectionBoxColor):this.drawCircle(t,this.opts.selectionBoxColor,.1)}effectiveCanvasHeight(){return function(t){const{canvasHeight:e,bounds:i,colorbarHeight:n}=t;let r=e;if(i){const[[,t],[,n]]=i,a=Math.round(t*e);r=Math.round(n*e)-a}return r-n}({canvasHeight:this.gl.canvas.height,bounds:this.opts.bounds,colorbarHeight:this.colorbarHeight})}effectiveCanvasWidth(){return function(t){const{canvasWidth:e,bounds:i,legendPanelWidth:n}=t;let r=e;if(i){const[[t],[n]]=i;r=Math.round((n-t)*e)}return r-n}({canvasWidth:this.gl.canvas.width,bounds:this.opts.bounds,legendPanelWidth:this.getLegendPanelWidth()})}getAllLabels(){return function(t){const{meshes:e,documentLabels:i}=t;return[...i,...e.filter((t=>"connectome"===t.type)).flatMap((t=>t.nodes)).map((t=>t.label)).filter((t=>void 0!==t))]}({meshes:this.meshes,documentLabels:this.document.labels})}getConnectomeLabels(){return function(t){const{meshes:e,documentLabels:i}=t,n=e.filter((t=>
1"connectome"===t.type&&!1!==t.showLegend)).flatMap((t=>t.nodes)).map((t=>t.label)).filter((t=>void 0!==t&&""!==t.text)),r=i.filter((t=>null==t.anchor||0===t.anchor)),a=new Set(n);for(const o of r)a.add(o);const s=e.filter((t=>"mesh"===t.type));for(let o=0;o<s.length;o++)for(let t=0;t<s[o].layers.length;t++)if(s[o].layers[t].labels)for(let e=0;e<s[o].layers[t].labels.length;e++)a.add(s[o].layers[t].labels[e]);return Array.from(a)}({meshes:this.meshes,documentLabels:this.document.labels})}getBulletMarginWidth(){return function(t){const{labels:e,fontPx:i,textHeight:n}=t;if(0===e.length)return 0;const r=1===e.length?e[0].style.bulletScale??1:e.reduce(((t,e)=>(t.style.bulletScale??1)>(e.style.bulletScale??1)?t:e)).style.bulletScale??1,a=1===e.length?e[0]:e.reduce(((t,e)=>{const r=i*t.style.textScale,a=i*e.style.textScale;return n(r,t.text)>n(a,e.text)?t:e})),s=i*a.style.textScale;let o=n(s,a.text)*r;return o+=s,o}({labels:this.getConnectomeLabels(),fontPx:this.fontPx,textHeight:(t,e)=>this.textHeight(t,e)})}getLegendPanelWidth(){return function(t){const{labels:e,showLegend:i,fontPx:n,canvasWidth:r,textWidth:a,getBulletMarginWidth:s}=t;if(!i||0===e.length)return 0;const o=1*n;let l=0;const c=e.reduce(((t,e)=>{const i=n*t.style.textScale,r=n*e.style.textScale;return a(i,t.text)>a(r,e.text)?t:e})),h=n*c.style.textScale,d=a(h,c.text),u=s();return d&&(l=u+d,l+=2*o),l>=r?0:l}({labels:this.getConnectomeLabels(),showLegend:this.opts.showLegend,fontPx:this.fontPx,canvasWidth:this.gl.canvas.width,textWidth:(t,e)=>this.textWidth(t,e),getBulletMarginWidth:()=>this.getBulletMarginWidth()})}getLegendPanelHeight(t){void 0===t&&(t=1);return function(t){const{labels:e,fontPx:i,panelScale:n,textHeight:r}=t;let a=0;const s=i;for(const o of e)a+=r(i*o.style.textScale*n,o.text);return a&&(a+=s/2*(e.length+1)*n),a}({labels:this.getConnectomeLabels(),fontPx:this.fontPx,panelScale:t,textHeight:(t,e)=>this.textHeight(t,e)})}reserveColorbarPanel(){const t=function(t){const{fontPx:e,boundsRegion:i,colorbarWidth:n}=t,r=3*e;if(r<0)return{leftTopWidthHeight:[0,0,0,0],colorbarHeight:0};const[a,s,o,l]=i,c=(n>0&&n<=1?n:1)*o;return{leftTopWidthHeight:[a+(o-c)/2,s+l-r,c,r],colorbarHeight:r+1}}({fontPx:this.fontPx,boundsRegion:this.getBoundsRegion(),colorbarWidth:this.opts.colorbarWidth});return this.colorbarHeight=t.colorbarHeight,t.leftTopWidthHeight}drawColorbarCore(t,e,i,n,r,a){if(void 0===t&&(t=0),void 0===e&&(e=[0,0,0,0]),void 0===i&&(i=!1),void 0===n&&(n=0),void 0===r&&(r=1),e[2]<=0||e[3]<=0)return;const s=this.fontPx;if(s<=0)return;this.gl.viewport(0,0,this.gl.canvas.width,this.gl.canvas.height);let o=s;const l=3*s;let c=s;if(e[3]<l){if(e[3]<3)return;o=1,c=e[3]-2}this.gl.disable(this.gl.DEPTH_TEST),this.colorbarHeight=e[3]+1;const h=[e[0]+o,e[1],e[2]-2*o,c],d=[h[0]-1,h[1]-1,h[2]+2,h[3]+2];if(this.opts.showColorbarBorder&&this.drawRect(d,this.opts.crosshairColor),!this.colorbarShader)throw new Error("colorbarShader undefined");this.colorbarShader.use(this.gl),this.gl.activeTexture(E),this.gl.bindTexture(this.gl.TEXTURE_2D,this.colormapTexture),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_MIN_FILTER,this.gl.NEAREST),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_MAG_FILTER,this.gl.NEAREST);const u=t;if(this.gl.uniform1f(this.colorbarShader.uniforms.layer,u),this.gl.uniform2fv(this.colorbarShader.uniforms.canvasWidthHeight,[this.gl.canvas.width,this.gl.canvas.height]),this.gl.disable(this.gl.CULL_FACE),i){const t=[h[0]+h[2],h[1],-h[2],h[3]];this.gl.uniform4fv(this.colorbarShader.uniforms.leftTopWidthHeight,t)}else this.gl.uniform4fv(this.colorbarShader.uniforms.leftTopWidthHeight,h);this.gl.bindVertexArray(this.genericVAO),this.gl.drawArrays(this.gl.TRIANGLE_STRIP,0,4),this.gl.bindVertexArray(this.unusedVAO),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_MIN_FILTER,this.gl.LINEAR),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_MAG_FILTER,this.gl.LINEAR);let m=0;if(a&&r<0&&i?(m=r,r=0):a&&n>0&&(m=n,n=0),n===r||s<1)return;const f=Math.abs(r-n);let[g,A]=fn(n,r);A<n&&(A+=g);let p=A;const v=[0,h[1]+h[3]-.5*s,2,.75*s],x=v[1]+v[3];for(;p<=r;){v[0]=h[0]+(p-n)/f*h[2],this.drawRect(v);const t=(1*p).toFixed(6).replace(/\.?0*$/,"");this.drawTextBelow([v[0],x],t),p+=g}if(0!==m){const t=[h[0]+(m-n)/f*h[2],h[1]-.25*h[3],2,1.5*h[3]];this.drawRect(t)}}drawColorbar(){const t=this.colormapLists,e=t.length;if(e<1)return;let i=0;for(let s=0;s<e;s++)t[s].visible&&i++;if(i<1)return;let n=this.reserveColorbarPanel();const r=3*this.fontPx;if(r<0)return;let a=n[2]/i;(n[2]<=0||n[3]<=0)&&(a=this.gl.canvas.width/i,n=[0,this.gl.canvas.height-r,a,r]),n[2]=a;for(let s=0;s<e;s++)t[s].visible&&(this.drawColorbarCore(s,n,t[s].negative,t[s].min,t[s].max,t[s].isColorbarFromZero),n[0]+=a)}textWidth(t,e){return function(t){const{fontMets:e,scale:i,str:n}=t;if(!n)return 0;let r=0;for(const a of n){const t=a.codePointAt(0),s=e.mets[t];s?r+=i*s.xadv:console.warn(`calculateTextWidth() : Missing font metric for c
1ode point ${t} in string "${n}"`)}return r}({fontMets:this.fontMets,scale:t,str:e})}textHeight(t,e){return function(t){const{fontMets:e,scale:i,str:n}=t;if(!n)return 0;let r=0;for(const a of n){const t=a.codePointAt(0),i=e.mets[t];i?.lbwh?.[3]>r&&(r=i.lbwh[3])}return i*r}({fontMets:this.fontMets,scale:t,str:e})}drawChar(t,e,i){if(!this.fontShader)throw new Error("fontShader undefined");const n=this.fontMets.mets[i];if(n){const i=t[0]+e*n.lbwh[0],r=-e*n.lbwh[1],a=e*n.lbwh[2],s=e*n.lbwh[3],o=t[1]+(r-s)+e;return this.gl.uniform4f(this.fontShader.uniforms.leftTopWidthHeight,i,o,a,s),this.gl.uniform4fv(this.fontShader.uniforms.uvLeftTopWidthHeight,n.uv_lbwh),this.gl.drawArrays(this.gl.TRIANGLE_STRIP,0,4),e*n.xadv}return console.warn(`drawChar() : Missing font metric for char : "${i}"`),0}drawLoadingText(t){if(!t)return;if(!this.canvas)throw new Error("canvas undefined");const[e,i,n,r]=this.getBoundsRegion();this.gl.viewport(e,i,n,r),this.gl.enable(this.gl.CULL_FACE),this.gl.enable(this.gl.BLEND);const a=e+n/2,s=i+r/2;this.drawTextBelow([a,s],t,3)}drawText(t,e,i,n){if(void 0===i&&(i=1),void 0===n&&(n=null),this.fontPx<=0)return;if(!this.fontShader)throw new Error("fontShader undefined");this.fontShader.use(this.gl);const r=this.fontPx*i;this.gl.enable(this.gl.BLEND),this.gl.uniform2f(this.fontShader.uniforms.canvasWidthHeight,this.gl.canvas.width,this.gl.canvas.height),null===n&&(n=this.opts.fontColor),this.gl.uniform4fv(this.fontShader.uniforms.fontColor,n);let a=r/this.fontMets.size*this.fontMets.distanceRange;a=Math.max(a,1),this.gl.uniform1f(this.fontShader.uniforms.screenPxRange,a),this.gl.bindVertexArray(this.genericVAO);for(const s of e){const e=s.codePointAt(0);t[0]+=this.drawChar(t,r,e)}this.gl.bindVertexArray(this.unusedVAO)}drawTextRight(t,e,i,n){void 0===i&&(i=1),void 0===n&&(n=null),this.fontPx<=0||(t[1]-=.5*this.fontPx,this.drawText(t,e,i,n))}drawTextLeft(t,e,i,n){if(void 0===i&&(i=1),void 0===n&&(n=null),this.fontPx<=0)return;const r=this.fontPx*i;t[0]-=this.textWidth(r,e),t[1]-=.5*r,this.drawText(t,e,i,n)}drawTextRightBelow(t,e,i,n){void 0===i&&(i=1),void 0===n&&(n=null),this.fontPx<=0||this.drawText(t,e,i,n)}drawTextBetween(t,e,i,n){if(void 0===i&&(i=1),void 0===n&&(n=null),this.fontPx<=0)return;const r=function(t,e,i,n,r){const a=i*n,s=r(a,e),o=.5*(t[0]+t[2])-.5*s,l=.5*(t[1]+t[3])-.5*a;return{textX:o,textY:l,rectLTWH:[o-1,l-1,s+2,a+2]}}(t,e,this.fontPx,i,((t,e)=>this.textWidth(t,e))),a=function(t,e){const i=t??e;return i&&i[0]+i[1]+i[2]>.8?[0,0,0,.5]:[1,1,1,.5]}(n,this.opts.crosshairColor);this.drawRect(r.rectLTWH,a),this.drawText([r.textX,r.textY],e,i,n)}drawTextBelow(t,e,i,n){if(void 0===i&&(i=1),void 0===n&&(n=null),this.fontPx<=0)return;if(!this.canvas)throw new Error("canvas undefined");const r=function(t,e){const{xy:i,str:n,fontPx:r,canvasWidth:a}=t;let s=t.scale,o=r*s,l=e(o,n);l>a&&(s*=(a-2)/l,o=r*s,l=e(o,n));let c=i[0]-.5*e(o,n);return c=Math.max(c,1),c=Math.min(c,a-l-1),{x:c,y:i[1],scale:s}}({xy:t,str:e,fontPx:this.fontPx,scale:i,canvasWidth:this.canvas.width},((t,e)=>this.textWidth(t,e)));this.drawText([r.x,r.y],e,r.scale,n)}drawTextAbove(t,e,i,n){if(void 0===i&&(i=1),void 0===n&&(n=null),this.fontPx<=0)return;if(!this.canvas)throw new Error("canvas undefined");const r=function(t,e){const{xy:i,str:n,fontPx:r,canvasWidth:a}=t;let s=t.scale,o=r*s,l=e(o,n);l>a&&(s*=(a-2)/l,o=r*s,l=e(o,n));let c=i[0]-.5*e(o,n);return c=Math.max(c,1),c=Math.min(c,a-l-1),{x:c,y:i[1]-o,scale:s}}({xy:t,str:e,fontPx:this.fontPx,scale:i,canvasWidth:this.canvas.width},((t,e)=>this.textWidth(t,e)));this.drawText([r.x,r.y],e,r.scale,n)}updateInterpolation(t,e){void 0===e&&(e=!1),function(t){const{gl:e,layer:i,isForceLinear:n=!1,isNearestInterpolation:r,is2DSliceShader:a}=t;let s=e.LINEAR;!n&&r&&(s=e.NEAREST),0===i?(e.activeTexture(33984),a?(e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,s),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,s)):(e.texParameteri(e.TEXTURE_3D,e.TEXTURE_MIN_FILTER,s),e.texParameteri(e.TEXTURE_3D,e.TEXTURE_MAG_FILTER,s))):(e.activeTexture(33986),e.texParameteri(e.TEXTURE_3D,e.TEXTURE_MIN_FILTER,s),e.texParameteri(e.TEXTURE_3D,e.TEXTURE_MAG_FILTER,s))}({gl:this.gl,layer:t,isForceLinear:e,isNearestInterpolation:this.opts.isNearestInterpolation,is2DSliceShader:this.opts.is2DSliceShader})}setAtlasOutline(t){this.opts.atlasOutline=t,this.updateGLVolume(),this.drawScene()}setInterpolation(t){this.opts.isNearestInterpolation=t;const e=this.volumes.length;if(!(e<1)){for(let t=0;t<e;t++)this.updateInterpolation(t);this.drawScene()}}getNearestInterpolation(){return this.opts.isNearestInterpolation}calculateMvpMatrix2D(t,e,i,n,s,o,l,c){void 0===n&&(n=1/0),void 0===s&&(s=0),void 0===o&&(o=0),void 0===l&&(l=0),void 0===c&&(c=!1);this.gl.viewport(t[0],this.gl.canvas.height-(t[1]+t[3]),t[2],t[3]);let h=e[0],d=i[0],u=[h,e[1]],m=[d-h,i[1]-e[1]];c&&(u=[i[0],e[1]],m=[e[0]-i[0],i[1]-e[1]],h=-i[0],d=-e[0]);const f=2*Math.max(Math.abs(e[2]),Math.abs(i[2])),g=a.vt();let A=.01,p=8*f;if(n!==1/0){let t=c;0!==l||0!==o&&180!==o||(t=!t);let e=1.8*f-s;t||(e=1.8*f+s),p=e-n,A=e+n}a.v3(g,h,d,e[1],i[1],p,A);const v=a.vt();v[0]=-1;const x=r.fA(0,0,1.8*-f);a.Tl(v,v,x),a.eL(v,v,gn(270-l)),a.Qr(v,v,gn(o-180));const w=a.vt();a.B8(w,v);const y=a.vt();a.mg(y,w);const b=a.vt();return a.lw(b,g,v),{modelViewProjectionMatrix:b,modelMatrix:v,normalMatrix:y,leftTopMM:u,fovMM:m}}swizzleVec3MM(t,e){return function(t,e){return 1===e?pn(t,[0,2,1]):2===e?pn(t,[1,2,0]):t}(t,e)}screenFieldOfViewVox(t){void 0===t&&(t=0);const e=r.o8(this.volumeObject3D.fieldOfViewDeObliqueMM);return this.swizzleVec3MM(e,t)}screenFieldOfViewMM(t,e){if(void 0===t&&(t=0),void 0===e&&(e=!1),this.volumes.length<1){let e=r.fA(this.extentsMin[0],this.extentsMin[1],this.extentsMin[2]),i=r.fA(this.extentsMax[0],this.extentsMax[1],this.extentsMax[2]);e=this.swizzleVec3MM(e,t),i=this.swizzleVec3MM(i,t);const n=r.vt();return r.Re(n,i,e),n}if(!e&&!this.opts.isSliceMM)return this.screenFieldOfViewVox(t);const i=this.volumeObject3D.extentsMin,n=this.volumeObject3D.extentsMax;let a=r.fA(i[0],i[1],i[2]),s=r.fA(n[0],n[1],n[2]);a=this.swizzleVec3MM(a,t),s=this.swizzleVec3MM(s,t);const o=r.vt();return r.Re(o,s,a),o}screenFieldOfViewExtendedVox(t){void 0===t&&(t=0);const e=this.volumes[0].extentsMinOrtho,i=this.volumes[0].extentsMaxOrtho;let n=r.fA(e[0],e[1],e[2]),s=r.fA(i[0],i[1],i[2]);const o=a.vt();n=this.swizzleVec3MM(n,t),s=this.swizzleVec3MM(s,t);const l=r.vt();return r.Re(l,s,n),{mnMM:n,mxMM:s,rotation:o,fovMM:l}}screenFieldOfViewExtendedMM(t){if(void 0===t&&(t=0),this.volumes.length<1){let e=r.fA(this.extentsMin[0],this.extentsMin[1],this.extentsMin[2]),i=r.fA(this.extentsMax[0],this.extentsMax[1],this.extentsMax[2]);const n=a.vt();e=this.swizzleVec3MM(e,t),i=this.swizzleVec3MM(i,t);const s=r.vt();return r.Re(s,i,e),{mnMM:e,mxMM:i,rotation:n,fovMM:s}}if(!this.volumeObject3D)throw new Error("volumeObject3D undefined");const e=this.volumeObject3D.extentsMin,i=this.volumeObject3D.extentsMax;let n=r.fA(e[0],e[1],e[2]),s=r.fA(i[0],i[1],i[2]);const o=a.vt();n=this.swizzleVec3MM(n,t),s=this.swizzleVec3MM(s,t);const l=r.vt();return r.Re(l,s,n),{mnMM:n,mxMM:s,rotation:o,fovMM:l}}drawSliceOrientationText(t,e,i){void 0===i&&(i=[NaN,NaN]),this.gl.viewport(0,0,this.gl.canvas.width,this.gl.canvas.height);let n="S";0===e&&(n="A");let r=this.opts.isRadiologicalConvention?"R":"L";2===e&&(r=this.opts.sagittalNoseLeft?"A":"P");let a="I";0===e&&(a="P");let s=this.opts.isRadiologicalConvention?"L":"R";if(2===e&&(s=this.opts.sagittalNoseLeft?"P":"A"),this.opts.isCornerOrientationText)return void this.drawTextRightBelow([t[0],t[1]],r+n);let o=!0,l=!0;const c=this.opts.showAllOrientationMarkers,h=this.opts.showAllOrientationMarkers;if(!isNaN(i[0])){const e=this.fontPx+2;i[1]>e&&(this.drawTextBelow([t[0]+.5*t[2],t[1]+i[1]-e],n),o=!1);const a=this.textWidth(e,r)+2;i[0]>a&&(this.drawTextRight([t[0]+i[0]-a,t[1]+.5*t[3]],r),l=!1)}o&&this.drawTextBelow([t[0]+.5*t[2],t[1]],n),l&&this.drawTextRight([t[0],t[1]+.5*t[3]],r),c&&this.drawTextAbove([t[0]+.5*t[2],t[1]+t[3]],a),h&&this.drawTextLeft([t[0]+t[2],t[1]+.5*t[3]],s)}xyMM2xyzMM(t,e){return function(t){const{axCorSag:e,sliceFrac:i,frac2mm:n,swizzleVec3MM:a}=t;let s=2;1===e&&(s=1),2===e&&(s=0);const o=[0,0,0],l=[1,1,0],c=[1,0,1];o[s]=i,l[s]=i,c[s]=i;const h=n(o),d=n(l),u=n(c),m=a(r.fA(h[0],h[1],h[2]),e),f=a(r.fA(d[0],d[1],d[2]),e),g=a(r.fA(u[0],u[1],u[2]),e),A=(f[0]-m[0])*(g[1]-m[1])-(g[0]-m[0])*(f[1]-m[1]);let p=(f[0]-m[0])*(g[2]-m[2])-(g[0]-m[0])*(f[2]-m[2]);p/=A;let v=(f[1]-m[1])*(g[2]-m[2])-(g[1]-m[1])*(f[2]-m[2]);v/=A;const x=[0,0,0,0,0];return x[0]=m[0],x[1]=m[1],x[2]=m[2],x[3]=v,x[4]=p,x}({axCorSag:t,sliceFrac:e,frac2mm:t=>this.frac2mm(t),swizzleVec3MM:(t,e)=>this.swizzleVec3MM(t,e)})}draw2DMain(t,e,i){void 0===i&&(i=NaN);let n=new Float32Array([0,0,0]);this.volumes.length>0&&(n=new Float32Array(this.volumes[0].frac2mm.slice()));let s=this.screenFieldOfViewExtendedMM(e),o=a.vt();!this.opts.isSliceMM&&this.volumes.length>0&&(n=new Float32Array(this.volumes[0].frac2mmOrtho.slice()),o=a.o8(this.volumes[0].mm2ortho),s=this.screenFieldOfViewExtendedVox(e));let l=this.opts.isRadiologicalConvention&&e<2;i===1/0||i===-1/0?(l=i!==1/0,1===e&&(l=!l)):this.opts.sagittalNoseLeft&&2===e&&(l=!l);let c=0,h=0;2===e?h=l?90:-90:1===e?h=l?180:0:(h=l?180:0,c=l?-90:90);const d=this.gl;let u=!1;if(0===t[2]||0===t[3]){u=!0;const e=d.canvas.width/s.fovMM[0],i=d.canvas.height/s.fovMM[1],n=Math.min(e,i),r=e/n,a=i/n;s.fovMM[0]*=r,s.fovMM[1]*=a;let o=.5*(s.mnMM[0]+s.mxMM[0]);s.mnMM[0]=o-.5*s.fovMM[0],s.mxMM[0]=o+.5*s.fovMM[0],o=.5*(s.mnMM[1]+s.mxMM[1]),s.mnMM[1]=o-.5*s.fovMM[1],s.mxMM[1]=o+.5*s.fovMM[1],t=[0,0,d.canvas.width,d.canvas.height]}if(isNaN(i)){const t=this.scene.pan2Dxyzmm,i=this.swizzleVec3MM(r.fA(t[0],t[1],t[2]),e),n=this.scene.pan2Dxyzmm[3];s.mnMM[0]-=i[0],s.mxMM[0]-=i[0],s.mnMM[1]-=i[1],s.mxMM[1]-=i[1],s.mnMM[0]/=n,s.mxMM[0]/=n,s.mnMM[1]/=n,s.mxMM[1]/=n}let m=2;1===e&&(m=1),2===e&&(m=0);let f=this.scene.crosshairPos[m],g=this.frac2mm(this.scene.crosshairPos);if(!isNaN(i)&&i!==1/0&&i!==-1/0){g=this.frac2mm([.5,.5,.5]),g[m]=i;f=this.mm2frac(g)[m]}const A=g[m],p=d.canvas.height-t[1]-t[3],v=[t[0],p,t[2],t[3]];this.clearBounds(d.DEPTH_BUFFER_BIT,v),d.viewport(v[0],v[1],v[2],v[3]);let x=this.calculateMvpMatrix2D(t,s.mnMM,s.mxMM,1/0,0,h,c,l);
1if(i===1/0||i===-1/0){const i=t.slice();this.draw3D(t,x.modelViewProjectionMatrix,x.modelMatrix,x.normalMatrix,h,c);const n=this.screenSlices[this.screenSlices.length-1];return n.leftTopWidthHeight=i,n.axCorSag=e,n.sliceFrac=1/0,n.AxyzMxy=this.xyMM2xyzMM(e,f),n.leftTopMM=x.leftTopMM,void(n.fovMM=x.fovMM)}if(d.enable(d.DEPTH_TEST),d.blendFunc(d.SRC_ALPHA,d.ONE_MINUS_SRC_ALPHA),d.disable(d.BLEND),d.depthFunc(d.ALWAYS),d.disable(d.CULL_FACE),this.volumes.length>0){let i=this.sliceMMShader;if(this.opts.is2DSliceShader&&(i=this.slice2DShader),this.opts.isV1SliceShader&&(i=this.sliceV1Shader),this.customSliceShader&&(i=this.customSliceShader),!i)throw new Error("slice Shader undefined");i.use(this.gl),d.uniform1f(i.uniforms.overlayOutlineWidth,this.overlayOutlineWidth),d.uniform1f(i.uniforms.overlayAlphaShader,this.overlayAlphaShader),d.uniform1i(i.uniforms.isAlphaClipDark,this.isAlphaClipDark?1:0),d.uniform1i(i.uniforms.backgroundMasksOverlays,this.backgroundMasksOverlays),d.uniform1f(i.uniforms.drawOpacity,this.drawOpacity),d.uniform1f(i.uniforms.drawRimOpacity,this.drawRimOpacity),d.enable(d.BLEND),d.blendFunc(d.SRC_ALPHA,d.ONE_MINUS_SRC_ALPHA),d.uniform1f(i.uniforms.opacity,this.volumes[0].opacity),d.uniform1i(i.uniforms.axCorSag,e),d.uniform1f(i.uniforms.slice,f),d.uniformMatrix4fv(i.uniforms.frac2mm,!1,n),d.uniformMatrix4fv(i.uniforms.mvpMtx,!1,x.modelViewProjectionMatrix.slice()),d.bindVertexArray(this.genericVAO),d.drawArrays(d.TRIANGLE_STRIP,0,4),d.bindVertexArray(this.unusedVAO),this.screenSlices.push({leftTopWidthHeight:t,axCorSag:e,sliceFrac:f,AxyzMxy:this.xyMM2xyzMM(e,f),leftTopMM:x.leftTopMM,screen2frac:[],fovMM:x.fovMM})}if(d.depthMask(!0),d.depthFunc(d.LEQUAL),isNaN(i)&&this.drawCrosshairs3D(!0,1,x.modelViewProjectionMatrix,!0,this.opts.isSliceMM),this.opts.meshThicknessOn2D>0){this.opts.meshThicknessOn2D!==1/0&&(x=this.calculateMvpMatrix2D(t,s.mnMM,s.mxMM,this.opts.meshThicknessOn2D,A,h,c,l));const e=a.o8(x.modelViewProjectionMatrix);a.lw(e,e,o),this.drawMesh3D(!0,1,e,x.modelMatrix,x.normalMatrix,!0)}isNaN(i)&&this.drawCrosshairs3D(!1,.15,x.modelViewProjectionMatrix,!0,this.opts.isSliceMM),u&&this.opts.isOrientationTextVisible&&this.drawSliceOrientationText(t,e),this.readyForSync=!0}
1draw2D(t,e,i,n){void 0===i&&(i=NaN),void 0===n&&(n=[NaN,NaN]);const[r,a,s,o]=this.getBoundsRegion();let l;l=0===t[2]&&0===t[3]?this.opts.bounds?[r,a,s,o]:[0,0,this.gl.canvas.width,this.gl.canvas.height]:t.slice();const c=[NaN,NaN];if(n[0]===1/0){const t=this.sliceScale().volScale;let i=this.scaleSlice(t[0],t[1],[0,0],[l[2],l[3]]);1===e&&(i=this.scaleSlice(t[0],t[2],[0,0],[l[2],l[3]])),2===e&&(i=this.scaleSlice(t[1],t[2],[0,0],[l[2],l[3]])),n[0]=i[2],n[1]=i[3]}if(isNaN(n[0])){const n=0===t[2]&&0===t[3];this.draw2DMain(n?[0,0,0,0]:l,e,i)}else{const t=[NaN,NaN];t[0]=Math.floor(.5*(l[2]-n[0])),t[1]=Math.floor(.5*(l[3]-n[1])),l[0]+=t[0],l[1]+=t[1],l[2]=n[0],l[3]=n[1],this.draw2DMain(l,e,i)}i!==1/0&&i!==-1/0&&4!==e&&0!==l[2]&&0!==l[3]&&this.opts.isOrientationTextVisible&&this.drawSliceOrientationText(l,e,c)}calculateMvpMatrix(t,e,i,n){void 0===e&&(e=[0,0,0,0]);const s=function(t){const{canvasWidth:e,canvasHeight:i,leftTopWidthHeight:n,azimuth:s,elevation:o,furthestFromPivot:l,pivot3D:c,volScaleMultiplier:h,position:d}=t;let u=n;0!==u[2]&&0!==u[3]||(u=[0,0,e,i]);const m=u[2]/u[3];let f=l;const g=c,A=a.vt();f=.8*f/h,m<1?a.v3(A,-f,f,-f/m,f/m,8*f,.01*f):a.v3(A,-f*m,f*m,-f,f,8*f,.01*f);const p=a.vt();p[0]=-1;const v=r.fA(0,0,1.8*-f);a.Tl(p,p,v),d&&a.Tl(p,p,d),a.eL(p,p,gn(270-o)),a.Qr(p,p,gn(s-180)),a.Tl(p,p,[-g[0],-g[1],-g[2]]);const x=a.vt();a.B8(x,p);const w=a.vt();a.mg(w,x);const y=a.vt();return a.lw(y,A,p),{mvpMatrix:y,modelMatrix:p,normalMatrix:w}}({canvasWidth:this.gl.canvas.width,canvasHeight:this.gl.canvas.height,leftTopWidthHeight:e,azimuth:i,elevation:n,furthestFromPivot:this.furthestFromPivot,pivot3D:this.pivot3D,volScaleMultiplier:this.scene.volScaleMultiplier,position:this.position});return[s.mvpMatrix,s.modelMatrix,s.normalMatrix]}calculateModelMatrix(t,e){if(!this.back)throw new Error("back undefined");return Sr({azimuth:t,elevation:e,obliqueRAS:this.back.obliqueRAS})}calculateRayDirection(t,e){return Er({azimuth:t,elevation:e,obliqueRAS:this.back?.obliqueRAS})}sceneExtentsMinMax(t){return void 0===t&&(t=!0),xn({volumes:this.volumes,meshes:this.meshes,volumeObject3D:this.volumeObject3D},t)}setPivot3D(){const[t,e]=this.sceneExtentsMinMax(),i=function(t){const{sceneMin:e,sceneMax:i}=t,n=r.vt();r.WQ(n,e,i),r.hs(n,n,.5);const a=r.vt();return r.Re(a,i,e),{pivot3D:[n[0],n[1],n[2]],furthestFromPivot:.5*r.Bw(a),extentsMin:e,extentsMax:i}}({sceneMin:t,sceneMax:e});this.pivot3D=i.pivot3D,this.furthestFromPivot=i.furthestFromPivot,this.extentsMin=i.extentsMin,this.extentsMax=i.extentsMax}getMaxVols(){return function(t){const{volumes:e}=t;if(e.length<1)return 0;let i=0;for(let n=0;n<e.length;n++)i=Math.max(i,e[n].nFrame4D??0);return i}({volumes:this.volumes})}detectPartialllyLoaded4D(){if(this.volumes.length<1)return!1;for(let t=0;t<this.volumes.length;t++)if(this.volumes[t].nFrame4D<this.volumes[t].hdr.dims[4])return!0;return!1}drawGraph(){if(this.getMaxVols()<2)return;const t=this.graph,[e,i,n,r]=this.getBoundsRegion();let a=0;if(t.autoSizeMultiplanar&&3===this.opts.sliceType)for(let B=0;B<this.screenSlices.length;B++){const e=this.screenSlices[B].axCorSag;if(0===e&&(a=this.screenSlices[B].leftTopWidthHeight[1]),2!==e)continue;const i=this.screenSlices[B].leftTopWidthHeight.slice();i[1]===a?(t.LTWH[0]=i[0]+i[2],t.LTWH[1]=i[1]):(t.LTWH[0]=i[0],t.LTWH[1]=i[1]+i[3]),t.LTWH[2]=i[2],t.LTWH[3]=i[2]}if(t.LTWH[0]=Math.max(e,t.LTWH[0]),t.LTWH[1]=Math.max(i,t.LTWH[1]),t.LTWH[2]=Math.min(n,t.LTWH[2]),t.LTWH[3]=Math.min(r,t.LTWH[3]),t.opacity<=0||t.LTWH[2]<=5||t.LTWH[3]<=5||Math.floor(t.LTWH[0]+t.LTWH[2])>e+n||Math.floor(t.LTWH[1]+t.LTWH[3])>i+r)return;t.backColor=[.15,.15,.15,t.opacity],t.lineColor=[1,1,1,1],this.opts.backColor[0]+this.opts.backColor[1]+this.opts.backColor[2]>1.5&&(t.backColor=[.95,.95,.95,t.opacity],t.lineColor=[0,0,0,1]);t.lineColor[3]=.2,t.textColor=t.lineColor.slice(),t.textColor[3]=1,t.lineThickness=3,t.gridLineThickness=1,t.lineAlpha=1,t.lines=[];const s=[];if(t.vols.length<1)null!=this.volumes[0]&&s.push(0);else for(let B=0;B<t.vols.length;B++){const e=t.vols[B];if(null==this.volumes[e])continue;this.volumes[e].nFrame4D<2||s.push(e)}if(s.length<1)return;const o=this.volumes[s[0]].nFrame4D;
1if(this.graph.selectedColumn=this.volumes[s[0]].frame4D,o<2)return void Q.debug("Unable to generate a graph: Selected volume is 3D not 4D");for(let B=0;B<s.length;B++){t.lines[B]=[];const e=this.frac2vox(this.scene.crosshairPos),i=this.volumes[s[B]];let n=i.nFrame4D;n=Math.min(n,o);for(let r=0;r<n;r++){const n=i.getValue(e[0],e[1],e[2],r);t.lines[B].push(n)}}t.lineRGB=[[.8,0,0],[0,.7,0],[0,0,.9],[.7,.7,0],[.8,0,.8],[0,.7,.7],[.6,.6,.6],[0,0,0]];let l=t.lines[0][0],c=t.lines[0][0];for(let B=0;B<t.lines.length;B++)for(let e=0;e<t.lines[B].length;e++){const i=t.lines[B][e];l=Math.min(i,l),c=Math.max(i,c)}const h=this.volumes[s[0]].cal_min,d=this.volumes[s[0]].cal_max;if(t.isRangeCalMinMax&&h<d&&isFinite(h)&&isFinite(d)&&(l=h,c=d),t.normalizeValues&&c>l){const e=c-l;for(let i=0;i<t.lines.length;i++)for(let n=0;n<t.lines[i].length;n++){const r=t.lines[i][n];t.lines[i][n]=(r-l)/e}l=0,c=1}l>=c&&(c=l+1),this.drawRect(t.LTWH,t.backColor);const[u,m,f]=fn(l,c),g=Math.max(0,-1*Math.floor(Math.log(u)/Math.log(10)));function A(t){return t.toFixed(6).replace(/\.?0*$/,"")}l=Math.min(m,l),c=Math.max(f,c);let p=.7*this.fontPx;p=n/this.uiData.dpr*(r/this.uiData.dpr)<48e4?0:Math.max(p,this.opts.fontMinPx);const v=p/this.fontPx;let x=0,w=m;if(p>0)for(;w<=c;){const t=w.toFixed(g),e=this.textWidth(p,t);x=Math.max(e,x),w+=u}const y=.05,b=Math.abs(t.LTWH[2]),C=Math.abs(t.LTWH[3]),M=[t.LTWH[0]+y*b+x,t.LTWH[1]+y*C,t.LTWH[2]-x-.1*b,t.LTWH[3]-p-.125*C];this.graph.LTWH=t.LTWH,this.graph.plotLTWH=M,this.drawRect(M,this.opts.backColor);const D=M[3]/(c-l),T=M[2]/(t.lines[0].length-1),I=M[1]+M[3];w=m+.5*u;const S=t.lineColor.slice();for(S[3]=.5*t.lineColor[3];w<=c;){const e=I-(w-l)*D;this.drawLine([M[0],e,M[0]+M[2],e],t.gridLineThickness,S),w+=u}w=m;const E=.5*t.gridLineThickness;for(;w<=c;){const e=I-(w-l)*D;this.drawLine([M[0]-E,e,M[0]+M[2]+t.gridLineThickness,e],t.gridLineThickness,t.lineColor);const i=w.toFixed(g);p>0&&this.drawTextLeft([M[0]-6,e],i,v,t.textColor),w+=u}let F=1;for(;t.lines[0].length/F>20;)F*=5;for(let B=0;B<t.lines[0].length;B+=F){const e=B*T+M[0];let i=t.gridLineThickness;if(B%2==1)i*=.5,this.drawLine([e,M[1],e,M[1]+M[3]],i,S);else{const n=A(B);p>0&&this.drawTextBelow([e,2+M[1]+M[3]],n,v,t.textColor),this.drawLine([e,M[1],e,M[1]+M[3]],i,t.lineColor)}}for(let B=0;B<t.lines.length;B++){let e=[1,0,0,t.lineAlpha];B<t.lineRGB.length&&(e=[t.lineRGB[B][0],t.lineRGB[B][1],t.lineRGB[B][2],t.lineAlpha]);for(let i=1;i<t.lines[B].length;i++){const n=(i-1)*T,r=i*T,a=(t.lines[B][i-1]-l)*D,s=(t.lines[B][i]-l)*D,o=[M[0]+n,M[1]+M[3]-a,M[0]+r,M[1]+M[3]-s];this.drawLine(o,t.lineThickness,e)}}if(t.selectedColumn>=0&&t.selectedColumn<t.lines[0].length){const e=t.selectedColumn*T+M[0];this.drawLine([e,M[1],e,M[1]+M[3]],t.lineThickness,[t.lineRGB[0][0],t.lineRGB[0][1],t.lineRGB[0][2],.3])}p>0&&t.LTWH[1]+t.LTWH[3]>M[1]+M[3]+2.4*p&&this.drawTextBelow([M[0]+.5*M[2],M[1]+M[3]+1.2*p],"Volume",v,t.textColor),this.detectPartialllyLoaded4D()&&this.drawTextBelow([M[0]+M[2],M[1]+M[3]+.5*p],"...",v,t.textColor)}depthPicker(t,e){if(!this.uiData.mouseDepthPicker)return;this.uiData.mouseDepthPicker=!1;const i=this.gl,r=this.mousePos[0]*t[2]/t[2],s=i.canvas.height-this.mousePos[1]*t[3]/t[3]-1,o=new Uint8Array(4);if(i.readPixels(r,s,1,1,i.RGBA,i.UNSIGNED_BYTE,o),this.selectedObjectId=o[3],this.selectedObjectId===this.VOLUME_ID)return void(this.scene.crosshairPos=new Float32Array(o.slice(0,3)).map((t=>t/255)));const l=function(t){const e=[1/16777216,1/65536,1/256,1];return(t[0]*e[0]+t[1]*e[1]+t[2]*e[2]+t[3]*e[3])/255}(o);if(l>1)return;const c=function(t,e,i,r){const s=n.fA(t,e,i,1),o=a.o8(r);a.B8(o,o),s[0]=2*s[0]-1,s[1]=2*s[1]-1,s[2]=2*s[2]-1;const l=n.vt();return n.Z0(l,s,o),0===l[3]||(l[0]/=l[3],l[1]/=l[3],l[2]/=l[3]),l}((this.mousePos[0]-t[0])/t[2],(i.canvas.height-this.mousePos[1]-t[1])/t[3],l,e),h=this.mm2frac(c,0,!0);h[0]<0||h[0]>1||h[1]<0||h[1]>1||h[2]<0||h[2]>1||(this.scene.crosshairPos=this.mm2frac(c,0,!0))}drawImage3D(t,e,i){!function(t){const{gl:e,mvpMatrix:i,azimuth:n,elevation:r,volumesLength:s,volumeObject3D:o,unusedVAO:l,renderShader:c,pickingImageShader:h,mouseDepthPicker:d,backgroundMasksOverlays:u,gradientTextureAmount:m,gradientTexture:f,drawBitmap:g,renderDrawAmbientOcclusion:A,drawOpacity:p,smoothDrawing:v,drawSmoothedTexture:x,paqdUniforms:w,matRAS:y,crosshairPos:b,clipPlaneDepthAziElevs:C,isClipPlanesCutaway:M,isClipAllVolumes:D,obliqueRAS:T}=t;if(0===s)return;const I=Er({azimuth:n,elevation:r,obliqueRAS:T}),S=o;if(S){e.enable(e.BLEND),e.blendFunc(e.SRC_ALPHA,e.ONE_MINUS_SRC_ALPHA),e.enable(e.CULL_FACE),e.cullFace(e.FRONT);let t=c;if(d&&(t=h),t.use(e),e.uniform1i(t.uniforms.backgroundMasksOverlays,u),m>0&&t.uniforms.normMtx&&f){e.activeTexture(Tr),e.bindTexture(e.TEXTURE_3D,f);const i=Sr({azimuth:n,elevation:r,obliqueRAS:T}),s=a.vt();a.B8(s,i);const o=a.vt();a.mg(o,s),e.uniformMatrix4fv(t.uniforms.normMtx,!1,o)}if(g&&g.length>8?(e.uniform2f(t.uniforms.renderDrawAmbientOcclusionXY,A,p),v>0&&x?(e.uniform1f(t.uniforms.smoothDrawing,v),e.activeTexture(e.TEXTURE10),e.bindTexture(e.TEXTURE_3D,x)):e.uniform1f(t.uniforms.smoothDrawing,0)):(e.uniform2f(t.uniforms.renderDrawAmbientOcclusionXY,A,0),e.uniform1f(t.uniforms.smoothDrawing,0)),e.uniform4fv(t.uniforms.paqdUniforms,w),e.uniformMatrix4fv(t.uniforms.mvpMtx,!1,i),e.uniformMatrix4fv(t.uniforms.matRAS,!1,y),e.uniform3fv(t.uniforms.rayDir,I),m<0)e.uniform4fv(t.uniforms.clipPlane,[b[0],b[1],b[2],30]);else{const i=new Float32Array(24).fill(2);for(let t=0;t<C.length;t++){const e=C[t],n=Ir(e[1]+180,e[2]),r=[n[0],n[1],n[2],e[0]];i.set(r,4*t)}e.uniform4fv(t.uniforms.clipPlanes,i)}e.uniform1f(t.uniforms.drawOpacity,1),e.uniform1i(t.uniforms.isCl
1ipCutaway,M?1:0),e.uniform1i(t.uniforms.isClipAllVolumes,D?1:0),e.bindVertexArray(S.vao),e.drawElements(S.mode,S.indexCount,e.UNSIGNED_SHORT,0),e.bindVertexArray(l)}}({gl:this.gl,mvpMatrix:t,azimuth:e,elevation:i,volumesLength:this.volumes.length,volumeObject3D:this.volumeObject3D,unusedVAO:this.unusedVAO,renderShader:this.renderShader,pickingImageShader:this.pickingImageShader,mouseDepthPicker:this.uiData.mouseDepthPicker,backgroundMasksOverlays:this.backgroundMasksOverlays,gradientTextureAmount:this.gradientTextureAmount,gradientTexture:this.gradientTexture,drawBitmap:this.drawBitmap,renderDrawAmbientOcclusion:this.renderDrawAmbientOcclusion,drawOpacity:this.drawOpacity,smoothDrawing:this.opts.smoothDrawing,drawSmoothedTexture:this.drawSmoothedTexture,paqdUniforms:this.opts.paqdUniforms,matRAS:this.back.matRAS,crosshairPos:this.scene.crosshairPos,clipPlaneDepthAziElevs:this.scene.clipPlaneDepthAziElevs,isClipPlanesCutaway:this.opts.isClipPlanesCutaway,isClipAllVolumes:this.opts.isClipAllVolumes,obliqueRAS:this.back?.obliqueRAS})}drawOrientationCube(t,e,i){if(void 0===e&&(e=0),void 0===i&&(i=0),!this.opts.isOrientCube)return;const n=.05*Math.min(t[2],t[3]);if(n<5)return;const r=this.gl;r.enable(r.CULL_FACE),r.cullFace(r.BACK),r.disable(r.DEPTH_TEST),this.orientCubeShader.use(this.gl),r.bindVertexArray(this.orientCubeShaderVAO);const s=a.vt(),o=a.vt();a.v3(o,0,r.canvas.width,0,r.canvas.height,-10*n,10*n);let l=0;0===t[1]&&(l=r.canvas.height-this.effectiveCanvasHeight()),a.Tl(s,s,[1.8*n+t[0],l+1.8*n+t[1],0]),a.hs(s,s,[n,n,n]),a.eL(s,s,gn(270-i)),a.Qr(s,s,gn(-e));const c=a.vt();a.lw(c,o,s),r.uniformMatrix4fv(this.orientCubeShader.uniforms.u_matrix,!1,c),r.drawArrays(r.TRIANGLE_STRIP,0,168),r.bindVertexArray(this.unusedVAO),this.gl.disable(this.gl.CULL_FACE)}createOnLocationChange(t){void 0===t&&(t=NaN);const[e,i,n]=this.sceneExtentsMinMax(!0),r=Math.max(Math.max(n[0],n[1]),n[2]);let a=(s=.001*r,Math.max(0,-Math.ceil(Math.log10(Math.abs(s)))));var s;const o=this.frac2mm(this.scene.crosshairPos,0,!0);function l(t,e){return void 0===e&&(e=0),parseFloat(Number(t).toFixed(e))}let c=l(o[0],a)+"\xd7"+l(o[1],a)+"\xd7"+l(o[2],a);if(this.volumes.length>0&&this.volumes[0].nFrame4D>0&&(c+="\xd7"+l(this.volumes[0].frame4D)),this.volumes.length>0){let t=" = ";for(let n=0;n<this.volumes.length;n++){const e=this.volumes[n].mm2vox(o);let i=this.volumes[n].getValue(e[0],e[1],e[2],this.volumes[n].frame4D);if(a=3,null!==this.volumes[n].colormapLabel){const r=Math.round(i);if(1002===this.volumes[n].hdr.intent_code&&2304===this.volumes[n].hdr.datatypeCode){const i=this.volumes[n].getValues(e[0],e[1],e[2],this.volumes[n].frame4D);if(i[2]>2){const e=Math.round(100*i[2]/255);if(t+=this.volumes[n].colormapLabel.labels[i[0]]+` (${e}%)`,i[3]>2){const e=Math.round(100*i[3]/255);t+=" "+this.volumes[n].colormapLabel.labels[i[1]]+` (${e}%)`}}}else r>=0&&this.volumes[n].colormapLabel.labels&&r<this.volumes[n].colormapLabel.labels.length?t+=this.volumes[n].colormapLabel.labels[r]:t+="undefined("+l(i,a)+")"}else t+=l(i,a);this.volumes[n].imaginary&&(i=this.volumes[n].getValue(e[0],e[1],e[2],this.volumes[n].frame4D,!0),i>=0&&(t+="+"),t+=l(i,a)),t+="   "}c+=t;const e=this.back.dimsRAS,i=e[1]*e[2]*e[3];if(this.drawBitmap&&this.drawBitmap.length===i){const t=this.frac2vox(this.scene.crosshairPos),i=t[0]+t[1]*e[1]+t[2]*e[1]*e[2];c+=" "+this.drawLut.labels[this.drawBitmap[i]]}}const h={mm:this.frac2mm(this.scene.crosshairPos,0,!0),axCorSag:t,vox:this.frac2vox(this.scene.crosshairPos),frac:this.scene.crosshairPos,xy:[this.mousePos[0],this.mousePos[1]],values:this.volumes.map((t=>{const e=this.frac2mm(this.scene.crosshairPos,0,!0),i=t.mm2vox(e),n=t.getValue(i[0],i[1],i[2],t.frame4D);return{name:t.name,value:n,id:t.id,mm:e,vox:i}})),string:c};this._emitEvent("locationChange",h),this.onLocationChange(h)}addLabel(t,e,i,n,r){const a={textColor:this.opts.legendTextColor,textScale:1,textAlignment:"left",lineWidth:0,lineColor:this.opts.legendTextColor,lineTerminator:"none",bulletScale:0,bulletColor:this.opts.legendTextColor},s=e?{...a,...e}:{...a},o=new Me(t,{...s},i,n,r);return this.document.labels.push(o),o}calculateScreenPoint(t,e,i){const r=n.vt();return n.Z0(r,[...t,1],e),0!==r[3]&&(r[0]=.5*(r[0]/r[3]+1)*i[2],r[1]=.5*(1-r[1]/r[3])*i[3],r[2]/=r[3],r[0]+=i[0],r[1]+=i[1]),r}getLabelAtPoint(t){const e=this.legendFontScaling,i=this.fontPx*e,n=this.fontPx*e;for(const c of this.document.labels){if(null==c.anchor||0===c.anch
1or)continue;const i=this.fontPx*c.style.textScale*e,r=this.textHeight(i,c.text),a=this.textWidth(i,c.text);if(!(1&c.anchor&&t[0]>a)){if(2&c.anchor){if(t[0]<(this.gl.canvas.width-a)/2)continue;if(t[0]>(this.gl.canvas.width+a)/2)continue}if(!(4&c.anchor&&t[0]<this.gl.canvas.width-a)){if(8&c.anchor){if(t[1]<n/2)continue;if(t[1]>r+n/2)continue}if(16&c.anchor){if(t[1]<(this.gl.canvas.height-r-n)/2)continue;if(t[1]>(this.gl.canvas.height+r-n/2)/2)continue}if(32&c.anchor){if(t[1]<this.gl.canvas.height-r-n)continue;if(t[1]>this.gl.canvas.height-n/2)continue}return c}}}Q.debug("screenPoint",t);const r=this.getLegendPanelHeight(e),a=this.getLegendPanelWidth(),s=this.gl.canvas.width-a;let o=(this.canvas.height-r)/2;if(Q.debug("panelrect",s,o,s+a,o+r),t[0]<s||t[1]<o||t[0]>s+a||t[1]>o+r)return null;const l=this.getConnectomeLabels();for(const c of l){const n=this.fontPx*c.style.textScale*e,r=this.textHeight(n,c.text);if(t[1]>=o&&t[1]<=o+r+i/2)return Q.debug(`label clicked ${c.text}`),c;o+=r,o+=i/2}return null}drawLabelLine(t,e,i,n,r){void 0===r&&(r=!1);const a=Array.isArray(t.points)&&Array.isArray(t.points[0])?t.points:[t.points];for(const s of a){const a=this.calculateScreenPoint(s,i,n);r?this.drawDottedLine([...e,a[0],a[1]],t.style.lineWidth,t.style.lineColor):this.draw3DLine(e,[a[0],a[1],a[2]],t.style.lineWidth,t.style.lineColor)}}draw3DLabel(t,e,i,n,r,a,s,o){void 0===o&&(o=1);const l=t.text,c=e[0],h=e[1],d=this.fontPx*o,u=this.textHeight(t.style.textScale,l)*d;if(t.style.lineWidth>0&&Array.isArray(t.points)&&this.drawLabelLine(t,[c,h+u],i,n,s),t.style.bulletScale){const e=t.style.bulletScale*u,i=h+(u-e)/2+e/2,n=c+(r-e)/2;this.drawCircle([n,i,e,e],t.style.bulletColor)}let m=c;if(a)if("left"!==t.style.textAlignment){const e=this.textWidth(t.style.textScale,t.text)*d;if("right"===t.style.textAlignment)m=c+a-1.5*d-e;else{m+=(a-(r||d)-e)/2}}else m+=r;const f=t.style.textScale;this.drawText([m,h],l,f,t.style.textColor)}draw3DLabels(t,e,i){void 0===i&&(i=!1);const n=this.getConnectomeLabels();if(!this.opts.showLegend||0===n.length)return;let r=this.getLegendPanelHeight(1);if(!this.canvas||r<1)return;const a=this.gl;if(a.disable(a.CULL_FACE),a.viewport(0,0,this.canvas.width,this.canvas.height),this.legendFontScaling=1,r>this.canvas.height){const t=10*this.uiData.dpr;this.legendFontScaling=Math.max(this.canvas.height-t,1)/r,Q.debug(`Legend too large for screen, font reduction factor x${this.legendFontScaling}`),r=this.getLegendPanelHeight(this.legendFontScaling)}const s=this.fontPx*this.legendFontScaling,o=this.getBulletMarginWidth(),l=this.getLegendPanelWidth(),c=a.canvas.width-l;let h=(this.canvas.height-r)/2;this.drawRect([a.canvas.width-l,h,l-s,r],this.opts.legendBackgroundColor);const d=a.getParameter(a.BLEND),u=a.getParameter(a.DEPTH_FUNC);i||(a.disable(a.BLEND),a.depthFunc(a.LEQUAL));for(const m of n){this.draw3DLabel(m,[c,h],t,e,o,l,i,this.legendFontScaling);const n=this.fontPx*m.style.textScale;h+=this.textHeight(n,m.text)*this.legendFontScaling,h+=s/2}i||(a.depthFunc(u),d&&a.enable(a.BLEND))}drawAnchoredLabels(){const t=this.fontPx,e=this.document.labels.filter((t=>null!=t.anchor&&0!==t.anchor));for(const i of e){const e=i.text,n=this.textHeight(i.style.textScale,e)*t,r=this.textWidth(i.style.textScale,e)*t;let a,s;const o=1,l=this.fontPx*o,c=l;let h=l/4,d=0,u=0;1&i.anchor&&(a=0),4&i.anchor&&(a=this.canvas.width-r,d-=l/4),2&i.anchor&&(a=(this.canvas.width-r)/2,d-=l/4,h+=l/4),8&i.anchor&&(s=0),16&i.anchor&&(s=(this.canvas.height-n-l)/2,u-=l/4),32&i.anchor&&(s=this.canvas.height-n-l,u-=l/4),this.drawRect([a+d,s+u,r+h,n+c],i.style.backgroundColor),this.draw3DLabel(i,[a,s])}}draw3D(t,e,i,n,r,a){void 0===t&&(t=[0,0,0,0]),void 0===e&&(e=null),void 0===i&&(i=null),void 0===n&&(n=null),void 0===r&&(r=null),void 0===a&&(a=0);const s=this.gl,[o,l,c,h]=this.getBoundsRegion();let d=[...t];0!==d[2]&&0!==d[3]||(d=this.opts.bounds?[o,l,c,h]:[0,0,s.canvas.width,s.canvas.height]);const u=null!==r;this.setPivot3D(),u||(r=this.scene.renderAzimuth,a=this.scene.renderElevation),null===e&&([e,i,n]=this.calculateMvpMatrix(null,d,r,a));const m=[...d];this.screenSlices.push({leftTopWidthHeight:d.slice(),axCorSag:4,sliceFrac:0,AxyzMxy:[],leftTopMM:[],fovMM:[vn(i),0]});const f=[d[0],s.canvas.height-d[3]-d[1],d[2],d[3]];if(d[1]=s.canvas.height-d[3]-d[1],s.clear(s.DEPTH_BUFFER_BIT),s.enable(s.DEPTH_TEST),s.depthFunc(s.ALWAYS),s.depthMask(!0),this.draw3DLabels(e,m,!1),this.gl.viewport(f[0],f[1],f[2],f[3]),this.volumes.length>0&&(this.updateInterpolation(0,!0),this.updateInterpolation(1,!0),this.drawImage3D(e,r,a)),this.updateInterpolation(0),this.updateInterpolation(1),u||this.drawCrosshairs3D(!0,1,e),this.drawMesh3D(!0,1,e,i,n),this.uiData.mouseDepthPicker)return this.depthPicker(d,e),this.createOnLocationChange(),void this.draw3D(m,e,i,n,r,a);this.opts.meshXRay>0&&this.drawMesh3D(!1,this.opts.meshXRay,e,i,n),this.gl.disable(this.gl.CULL_FACE),this.draw3DLabels(e,m,!1),s.viewport(d[0],d[1],d[2],d[3]),u||this.drawCrosshairs3D(!1,.15,e),s.viewport(o,l,c,h),this.drawOrientationCube(d,r,a);const g="azimuth: "+this.scene.renderAzimuth.toFixed(0)+" elevation: "+this.scene.renderElevation.toFixed(0);return this.readyForSync=!0,this.sync(),this.draw3DLabels(e,m,!0),g}drawMesh3D(t,e,i,n,r,a){void 0===t&&(t=!0),void 0===e&&(e=1),void 0===a&&(a=!1),this.meshes.length<1||(i||([i,n,r]=this.calculateMvpMatrix(this.volumeObject3D,void 0,this.scene.renderAzimuth,this.scene.renderElevation)),function(t){const{gl:e,meshes:i,isDepthTest:n,alpha:r,mvpMatrix:a,modelMatrix:s,normalMatrix:o,is2D:l,meshShaders:c,pickingMeshShader:h,fiberShader:d,mouseDepthPicker:u,matCapTexture:m,unusedVAO:f,meshXRay:g,meshThicknessOn2D:A,frac2mm:p,crosshairPos:v}=t;if(i.length<1)return;e.enable(e.DEPTH_TEST),n?e.depthFunc(e.LEQUAL):e.depthFunc(e.ALWAYS),e.cullFace(e.BACK),e.blendFunc(e.SRC_ALPHA,e.ONE_MINUS_SRC_ALPHA);let x=!1;for(const w of i){if(!Br({visible:w.visible,opacity:w.opacity,indexCount:w.indexCount}))continue;const t=Ur({meshOpacity:w.opacity,globalAlpha:r}),i=Vr({meshShaderIndex:w.meshShaderIndex,meshShaders:c,pickingMeshShader:h,mouseDepthPicker:u});i&&(i.use(e),i.isCrosscut?Lr({gl:e,shader:i,modelMtx:s,sliceMM:Pr({modelMtx:s,crosshairMM:p([v[0],v[1],v[2]]),is2D:l}),meshThickness:Nr(A)}):(e.enable(e.CULL_FACE),e.enable(e.DEPTH_TEST)),kr({gl:e,shader:i,mvpMtx:a,normMtx:o,opacity:t}),t>=1?(e.disable(e.BLEND),e.depthMask(!0)):(e.enable(e.BLEND),e.depthMask(!1)),Rr({offsetPt0:w.offsetPt0,fiberSides:w.fiberSides,fiberRadius:w.fiberRadius})?x=!0:(i.isMatcap&&Or({gl:e,matCapTexture:m}),zr({gl:e,mesh:w,unusedVAO:f})))}if(e.enable(e.CULL_FACE),g>
10&&!x){!function(t){const{gl:e}=t;e.enable(e.BLEND),e.depthMask(!1),e.depthFunc(e.ALWAYS)}({gl:e});for(const t of i){if(!t.visible||t.indexCount<3)continue;const i=c[t.meshShaderIndex]?.shader;i&&(i.use(e),kr({gl:e,shader:i,mvpMtx:a,normMtx:o,opacity:t.opacity*r*g}),zr({gl:e,mesh:t,unusedVAO:f}))}!function(t){t.depthMask(!0),t.depthFunc(t.LEQUAL),t.disable(t.BLEND)}(e)}if(x&&d){d.use(e),e.uniformMatrix4fv(d.uniforms.mvpMtx,!1,a),e.uniform1f(d.uniforms.opacity,r);for(const t of i)t.offsetPt0&&(t.fiberSides>=3&&t.fiberRadius>0||Yr({gl:e,mesh:t,unusedVAO:f}))}!function(t){t.depthMask(!0),t.disable(t.BLEND)}(e)}({gl:this.gl,meshes:this.meshes,isDepthTest:t,alpha:e,mvpMatrix:i,modelMatrix:n,normalMatrix:r,is2D:a,meshShaders:this.meshShaders,pickingMeshShader:this.pickingMeshShader,fiberShader:this.fiberShader,mouseDepthPicker:this.uiData.mouseDepthPicker,matCapTexture:this.matCapTexture,unusedVAO:this.unusedVAO,meshXRay:this.opts.meshXRay,meshThicknessOn2D:this.opts.meshThicknessOn2D,frac2mm:t=>this.frac2mm(t,0,this.opts.isSliceMM),crosshairPos:this.scene.crosshairPos}),this.readyForSync=!0)}drawCrosshairs3D(t,e,i,n,r){if(void 0===t&&(t=!0),void 0===e&&(e=1),void 0===i&&(i=null),void 0===n&&(n=!1),void 0===r&&(r=!0),!this.opts.show3Dcrosshair&&!n)return;if(this.opts.crosshairWidth<=0&&n)return;const a=this.gl,s=this.frac2mm(this.scene.crosshairPos,0,r);let o=1;const[l,c,h]=this.sceneExtentsMinMax(r);if(this.volumes.length>0){if(!this.back)throw new Error("back undefined");o=.5*Math.min(Math.min(this.back.pixDims[1],this.back.pixDims[2]),this.back.pixDims[3])}else(h[0]<50||h[0]>1e3)&&(o=.02*h[0]);if(o*=this.opts.crosshairWidth,"percent"===this.opts?.crosshairWidthUnit&&(o=h[0]*this.opts.crosshairWidth*.5*.01),"mm"===this.opts?.crosshairWidthUnit&&(o=.5*this.opts.crosshairWidth),null!==this.crosshairs3D&&this.crosshairs3D.mm[0]===s[0]&&this.crosshairs3D.mm[1]===s[1]&&this.crosshairs3D.mm[2]===s[2]||(null!==this.crosshairs3D&&(a.deleteBuffer(this.crosshairs3D.indexBuffer),a.deleteBuffer(this.crosshairs3D.vertexBuffer)),this.crosshairs3D=K.generateCrosshairs(this.gl,1,s,l,c,o,20,this.opts.crosshairGap),this.crosshairs3D.mm=s),!this.surfaceShader)throw new Error("surfaceShader undefined");const d=this.surfaceShader;d.use(this.gl),null==i&&([i]=this.calculateMvpMatrix(this.crosshairs3D,void 0,this.scene.renderAzimuth,this.scene.renderElevation)),a.uniformMatrix4fv(d.uniforms.mvpMtx,!1,i),a.disable(a.CULL_FACE),a.bindBuffer(a.ELEMENT_ARRAY_BUFFER,this.crosshairs3D.indexBuffer),a.enable(a.DEPTH_TEST);const u=[...this.opts.crosshairColor];t?(a.disable(a.BLEND),a.depthFunc(a.LEQUAL)):(a.enable(a.BLEND),a.blendFunc(a.SRC_ALPHA,a.ONE_MINUS_SRC_ALPHA),a.depthFunc(a.ALWAYS)),u[3]=e,a.uniform4fv(d.uniforms.surfaceColor,u),a.bindVertexArray(this.crosshairs3D.vao),a.drawElements(a.TRIANGLES,this.crosshairs3D.indexCount,a.UNSIGNED_INT,0),a.bindVertexArray(this.unusedVAO)}mm2frac(t,e,i){return void 0===e&&(e=0),void 0===i&&(i=!1),wn(t,{volumes:this.volumes,meshes:this.meshes,volumeObject3D:this.volumeObject3D,volIdx:e,isSliceMM:i||this.opts.isSliceMM})}vox2frac(t,e){return void 0===e&&(e=0),function(t,e,i){return void 0===i&&(i=0),e[i].convertVox2Frac(t)}(t,this.volumes,e)}frac2vox(t,e){return void 0===e&&(e=0),function(t,e,i){return void 0===i&&(i=0),e.length<=i?r.fA(0,0,0):e[i].convertFrac2V
1ox(t)}(t,this.volumes,e)}moveCrosshairInVox(t,e,i){const n=function(t){const{x:e,y:i,z:n,currentVox:a,dimsRAS:s}=t,o=r.o8(a),l=o[2];return o[0]+=e,o[1]+=i,o[2]+=n,o[0]=Math.max(0,Math.min(o[0],s[1]-1)),o[1]=Math.max(0,Math.min(o[1],s[2]-1)),o[2]=Math.max(0,Math.min(o[2],s[3]-1)),{newVox:o,zChanged:l!==o[2]}}({x:t,y:e,z:i,currentVox:this.frac2vox(this.scene.crosshairPos),dimsRAS:this.volumes[0].dimsRAS});this.scene.crosshairPos=this.vox2frac(n.newVox),this.createOnLocationChange(),this.opts.is2DSliceShader&&n.zChanged&&(this.updateGLVolume(),this.refreshDrawing(!1)),this.drawScene()}frac2mm(t,e,i){return void 0===e&&(e=0),void 0===i&&(i=!1),yn(t,{volumes:this.volumes,meshes:this.meshes,volumeObject3D:this.volumeObject3D,volIdx:e,isSliceMM:i||this.opts.isSliceMM})}screenXY2TextureFrac(t,e,i,n){return void 0===n&&(n=!0),bn(t,e,this.screenSlices,i,{volumes:this.volumes,meshes:this.meshes,volumeObject3D:this.volumeObject3D,isSliceMM:this.opts.isSliceMM,restrict0to1:n})}canvasPos2frac(t){return function(t,e,i){const{volumes:n,meshes:a,volumeObject3D:s,isSliceMM:o=!1}=i;for(let r=0;r<e.length;r++){const i=bn(t[0],t[1],e,r,{volumes:n,meshes:a,volumeObject3D:s,isSliceMM:o});if(i[0]>=0)return i}return r.fA(-1,-1,-1)}(t,this.screenSlices,{volumes:this.volumes,meshes:this.meshes,volumeObject3D:this.volumeObject3D,isSliceMM:this.opts.isSliceMM})}
1frac2canvasPosWithTile(t,e){return function(t,e,i){const{volumes:n,meshes:a,volumeObject3D:s,isSliceMM:o=!1,preferredSliceType:l}=i,c=yn(t,{volumes:n,meshes:a,volumeObject3D:s,isSliceMM:o});let h={index:-1,distance:1/0};for(let d=0;d<e.length;d++){const t=e[d],i=t.axCorSag;if(i>2)continue;if(t.AxyzMxy.length<4)continue;if(void 0!==l&&i!==l)continue;let n=r.fA(c[0],c[1],c[2]);1===i&&(n=pn(n,[0,2,1])),2===i&&(n=pn(n,[1,2,0]));const a=t.AxyzMxy,s=a[2]+a[4]*(n[1]-a[1])-a[3]*(n[0]-a[0]),o=Math.abs(n[2]-s);if(o<h.distance&&(h={index:d,distance:o}),o<=.1){const e=(n[0]-t.leftTopMM[0])/t.fovMM[0],i=(n[1]-t.leftTopMM[1])/t.fovMM[1];if(e>=0&&e<=1&&i>=0&&i<=1){const n=t.leftTopWidthHeight.slice();let r=!1;n[2]<0&&(r=!0,n[0]+=n[2],n[2]=-n[2]);let a=e;r&&(a=1-e);const s=1-i;return{pos:[n[0]+a*n[2],n[1]+s*n[3]],tileIndex:d}}}}if(h.index>=0&&h.distance<2){const t=h.index,i=e[t],n=i.axCorSag;let a=r.fA(c[0],c[1],c[2]);1===n&&(a=pn(a,[0,2,1])),2===n&&(a=pn(a,[1,2,0]));const s=i.AxyzMxy;a[2]=s[2]+s[4]*(a[1]-s[1])-s[3]*(a[0]-s[0]);const o=(a[0]-i.leftTopMM[0])/i.fovMM[0],l=(a[1]-i.leftTopMM[1])/i.fovMM[1];if(o>=-.1&&o<=1.1&&l>=-.1&&l<=1.1){const e=Math.max(0,Math.min(1,o)),n=Math.max(0,Math.min(1,l)),r=i.leftTopWidthHeight.slice();let a=!1;r[2]<0&&(a=!0,r[0]+=r[2],r[2]=-r[2]);let s=e;a&&(s=1-e);const c=1-n;return{pos:[r[0]+s*r[2],r[1]+c*r[3]],tileIndex:t}}}return null}(t,this.screenSlices,{volumes:this.volumes,meshes:this.meshes,volumeObject3D:this.volumeObject3D,isSliceMM:this.opts.isSliceMM,preferredSliceType:e})}frac2canvasPos(t){return function(t,e,i){const{volumes:n,meshes:a,volumeObject3D:s,isSliceMM:o=!1,sliceType:l}=i,c=yn(t,{volumes:n,meshes:a,volumeObject3D:s,isSliceMM:o});let h={index:-1,distance:1/0};for(let d=0;d<e.length;d++){const t=e[d],i=t.axCorSag;if(i>2)continue;if(t.AxyzMxy.length<4)continue;let n=r.fA(c[0],c[1],c[2]);
11===i&&(n=pn(n,[0,2,1])),2===i&&(n=pn(n,[1,2,0]));const a=t.AxyzMxy,s=a[2]+a[4]*(n[1]-a[1])-a[3]*(n[0]-a[0]),o=Math.abs(n[2]-s),u=3===l?1:.1;if(o<h.distance&&(h={index:d,distance:o}),o<=u){const e=(n[0]-t.leftTopMM[0])/t.fovMM[0],i=(n[1]-t.leftTopMM[1])/t.fovMM[1];if(e>=0&&e<=1&&i>=0&&i<=1){const n=t.leftTopWidthHeight.slice();let r=!1;n[2]<0&&(r=!0,n[0]+=n[2],n[2]=-n[2]);let a=e;r&&(a=1-e);const s=1-i;return[n[0]+a*n[2],n[1]+s*n[3]]}}}if(h.index>=0&&h.distance<2){const t=e[h.index],i=t.axCorSag;let n=r.fA(c[0],c[1],c[2]);1===i&&(n=pn(n,[0,2,1])),2===i&&(n=pn(n,[1,2,0]));const a=t.AxyzMxy;n[2]=a[2]+a[4]*(n[1]-a[1])-a[3]*(n[0]-a[0]);const s=(n[0]-t.leftTopMM[0])/t.fovMM[0],o=(n[1]-t.leftTopMM[1])/t.fovMM[1];if(s>=-.1&&s<=1.1&&o>=-.1&&o<=1.1){const e=Math.max(0,Math.min(1,s)),i=Math.max(0,Math.min(1,o)),n=t.leftTopWidthHeight.slice();let r=!1;n[2]<0&&(r=!0,n[0]+=n[2],n[2]=-n[2]);let a=e;r&&(a=1-e);const l=1-i;return[n[0]+a*n[2],n[1]+l*n[3]]}}return null}(t,this.screenSlices,{volumes:this.volumes,meshes:this.meshes,volumeObject3D:this.volumeObject3D,isSliceMM:this.opts.isSliceMM,sliceType:this.opts.sliceType})}scaleSlice(t,e,i,n){void 0===i&&(i=[0,0]),void 0===n&&(n=[0,0]);const r=0===n[0]?this.effectiveCanvasWidth()-i[0]:n[0]-i[0],a=0===n[1]?this.effectiveCanvasHeight()-i[1]:n[1]-i[1];let s=r/t;e*s>a&&(s=a/e);const o=t*s,l=e*s;return[.5*(r-o),.5*(a-l),o,l,s]}drawThumbnail(){if(!this.bmpShader)throw new Error("bmpShader undefined");this.bmpShader.use(this.gl);const[t,e,i,n]=this.getBoundsRegion();this.gl.uniform2f(this.bmpShader.uniforms.canvasWidthHeight,i,n);const r=function(t,e,i){let n=e,r=e*i;return r>t&&(n=t/i,r=t),{left:(t-r)/2,top:(e-n)/2,width:r,height:n}}(i,n,this.bmpTextureWH),a=t+r.left,s=e+r.top;this.gl.uniform4f(this.bmpShader.uniforms.leftTopWidthHeight,a,s,r.width,r.height),this.gl.bindVertexArray(this.genericVAO),this.gl.drawArrays(this.gl.TRIANGLE_STRIP,0,4),this.gl.bindVertexArray(this.unusedVAO)}drawLine(t,e,i){if(void 0===e&&(e=1),void 0===i&&(i=[1,0,0,-1]),this.gl.bindVertexArray(this.genericVAO),!this.lineShader)throw new Error("lineShader undefined");this.lineShader.use(this.gl),i[3]<0&&(i=this.opts.crosshairColor),this.gl.uniform4fv(this.lineShader.uniforms.lineColor,i),this.gl.uniform2fv(this.lineShader.uniforms.canvasWidthHeight,[this.gl.canvas.width,this.gl.canvas.height]),this.gl.uniform1f(this.lineShader.uniforms.thickness,e),this.gl.uniform4fv(this.lineShader.uniforms.startXYendXY,t),this.gl.drawArrays(this.gl.TRIANGLE_STRIP,0,4),this.gl.bindVertexArray(this.unusedVAO)}draw3DLine(t,e,i,n){if(void 0===i&&(i=1),void 0===n&&(n=[1,0,0,-1]),this.gl.bindVertexArray(this.genericVAO),!this.line3DShader)throw new Error("line3DShader undefined");this.line3DShader.use(this.gl),n[3]<0&&(n=this.opts.crosshairColor),this.gl.uniform4fv(this.line3DShader.uniforms.lineColor,n),this.gl.uniform2fv(this.line3DShader.uniforms.canvasWidthHeight,[this.gl.canvas.width,this.gl.canvas.height]),this.gl.uniform1f(this.line3DShader.uniforms.thickness,i),this.gl.uniform2fv(this.line3DShader.uniforms.startXY,t),this.gl.uniform3fv(this.line3DShader.uniforms.endXYZ,e),this.gl.drawArrays(this.gl.TRIANGLE_STRIP,0,4),this.gl.bindVertexArray(this.unusedVAO)}drawDottedLine(t,e,i){if(void 0===e&&(e=1),void 0===i&&(i=[1,0,0,-1]),this.gl.bindVertexArray(this.genericVAO),!this.lineShader)throw new Error("lineShader undefined");this.lineShader.use(this.gl);const n=i[3]<0?[...this.opts.crosshairColor]:[...i];n[3]=.3,this.gl.uniform4fv(this.lineShader.uniforms.lineColor,n),this.gl.uniform2fv(this.lineShader.uniforms.canvasWidthHeight,[this.gl.canvas.width,this.gl.canvas.height]),this.gl.uniform1f(this.lineShader.uniforms.thickness,e);const r=function(t,e,i){const n=[],r=t[2]-t[0],a=t[3]-t[1],s=Math.sqrt(r*r+a*a);if(0===s)return n;const o=e*i/2,l=r/s*o,c=a/s*o;let h=Math.floor(s/o);s%o&&h++;let d=t[0],u=t[1];for(let m=0;m<h-1;m++)m%2==0&&n.push({startX:d,startY:u,endX:d+l,endY:u+c}),d+=l,u+=c;return n}(t,this.fontPx,1);for(const a of r)this.gl.uniform4fv(this.lineShader.uniforms.startXYendXY,[a.startX,a.startY,a.endX,a.endY]),this.gl.drawArrays(this.gl.TRIANGLE_STRIP,0,4);this.gl.bindVertexArray(this.unusedVAO)}
1drawGraphLine(t,e,i){void 0===e&&(e=[1,0,0,.5]),void 0===i&&(i=2),this.drawLine(t,i,e)}drawCrossLinesMM(t,e,i,n,r){if(t<0||this.screenSlices.length<=t)return;const a=this.screenSlices[t];let o=a.sliceFrac;o===1/0&&Q.debug("Rendering approximate cross lines in world view mode"),o===1/0&&(o=.5);const{linesH:l,linesV:c}=Dr(e,i,n,r),h=Math.max(1,this.opts.crosshairWidth),d=t=>{const e=s.fA(0,0);return e[0]=a.leftTopWidthHeight[0]+(t[0]-a.leftTopMM[0])/a.fovMM[0]*a.leftTopWidthHeight[2],e[1]=a.leftTopWidthHeight[1]+a.leftTopWidthHeight[3]-(t[1]-a.leftTopMM[1])/a.fovMM[1]*a.leftTopWidthHeight[3],e};if(l.length>0&&0===e){const t=o,e=1;for(let i=0;i<l.length;i++){const n=this.frac2mm([.5,.5,.5]);n[e]=l[i];let r=this.mm2frac(n);r=r[e];let a=this.frac2mm([0,r,t]);a=pn(a,[0,1,2]);let s=this.frac2mm([1,r,t]);s=pn(s,[0,1,2]),a=d(a),s=d(s),this.drawLine([a[0],a[1],s[0],s[1]],h)}}if(l.length>0&&1===e){const t=o,e=2;for(let i=0;i<l.length;i++){const n=this.frac2mm([.5,.5,.5]);n[e]=l[i];let r=this.mm2frac(n);r=r[e];let a=this.frac2mm([0,t,r]);a=pn(a,[0,2,1]);let s=this.frac2mm([1,t,r]);s=pn(s,[0,2,1]),a=d(a),s=d(s),this.drawLine([a[0],a[1],s[0],s[1]],h)}}if(l.length>0&&2===e){const t=o,e=2;for(let i=0;i<l.length;i++){const n=this.frac2mm([.5,.5,.5]);n[e]=l[i];let r=this.mm2frac(n);r=r[e];let a=this.frac2mm([t,0,r]);a=pn(a,[1,2,0]);let s=this.frac2mm([t,1,r]);s=pn(s,[1,2,0]),a=d(a),s=d(s),this.drawLine([a[0],a[1],s[0],s[1]],h)}}if(c.length>0&&0===e){const t=o,e=0;for(let i=0;i<c.length;i++){const n=this.frac2mm([.5,.5,.5]);n[e]=c[i];let r=this.mm2frac(n);r=r[e];let a=this.frac2mm([r,0,t]);a=pn(a,[0,1,2]);let s=this.frac2mm([r,1,t]);s=pn(s,[0,1,2]),a=d(a),s=d(s),this.drawLine([a[0],a[1],s[0],s[1]],h)}}if(c.length>0&&1===e){const t=o,e=0;for(let i=0;i<c.length;i++){const n=this.frac2mm([.5,.5,.5]);n[e]=c[i];let r=this.mm2frac(n);r=r[e];let a=this.frac2mm([r,t,0]);a=pn(a,[0,2,1]);let s=this.frac2mm([r,t,1]);s=pn(s,[0,2,1]),a=d(a),s=d(s),this.drawLine([a[0],a[1],s[0],s[1]],h)}}if(c.length>0&&2===e){const t=o,e=1;for(let i=0;i<c.length;i++){const n=this.frac2mm([.5,.5,.5]);n[e]=c[i];let r=this.mm2frac(n);r=r[e];let a=this.frac2mm([t,r,0]);a=pn(a,[1,2,0]);let s=this.frac2mm([t,r,1]);s=pn(s,[1,2,0]),a=d(a),s=d(s),this.drawLine([a[0],a[1],s[0],s[1]],h)}}}drawCrossLines(t,e,i,n,r){if(t<0||this.screenSlices.length<=t)return;if(this.opts.isSliceMM)return this.drawCrossLinesMM(t,e,i,n,r);if(this.screenSlices[t].sliceFrac===1/0)return this.drawCrossLinesMM(t,e,i,n,r);const a=this.screenSlices[t],{linesH:s,linesV:o}=Dr(e,i,n,r);if(s.length>0){const t=a.leftTopWidthHeight.slice();let i=2;0===e&&(i=1);const n=this.frac2mm([.5,.5,.5]);for(let e=0;e<s.length;e++){n[i]=s[e];const r=this.mm2frac(n);this.drawRect([t[0],t[1]+t[3]-r[i]*t[3],t[2],1])}}if(o.length>0){const t=a.leftTopWidthHeight.slice(),i=a.fovMM[0]<0;let n=0;2===e&&(n=1);const r=this.frac2mm([.5,.5,.5]);for(let e=0;e<o.length;e++){r[n]=o[e];const a=this.mm2frac(r);i?this.drawRect([t[0]+(t[2]-a[n]*t[2]),t[1],1,t[3]]):this.drawRect([t[0]+a[n]*t[2],t[1],1,t[3]])}}}drawMosaic(t){this.screenSlices=[];const[e,i,n,r]=this.getBoundsRegion(),a=this.screenFieldOfViewMM(0,!0),s=this.screenFieldOfViewMM(0),o=[],l=[],c=[],h=(t=t.replaceAll(";"," ;").trim()).split(/\s+/);let d=1;const u=this.fontPx;let m=0,f=0,g=0;this.volumes[0]?.dims||(g=Math.ceil(.3*this.opts.tileMargin));for(let A=0;A<2;A++){let t=!1,p=!1,v=0,x=0,w=0,y=0,b=!1,C=0,M=0,D=0,T=0;for(let n=0;n<h.length;n++){const r=h[n];if(r.includes("X")){p=!0;continue}if(r.includes("L")){b=!r.includes("-");continue}if(r.includes("H")){n++,M=Math.abs(Math.max(0,Math.min(1,parseFloat(h[n]))));continue}if(r.includes("V")){n++;continue}if(r.includes("A")){C=0;continue}if(r.includes("C")){C=1;continue}if(r.includes("S")){C=2;continue}if(r.includes("R")){t=!0;continue}if(r.includes(";")){w+=v,y=Math.max(y,x+D),v=0,x=0,D=0;continue}T=D,M>0&&!t&&(T=Math.round(T*(1-M))),x+=T,T=0;const I=parseFloat(r);if(isNaN(I))continue;let S=0,E=s;if(t&&(E=a),T=2===C?E[1]:E[0],S=0===C?E[1]:E[2],0===A)t||(0===C&&o.push(I),1===C&&l.push(I),2===C&&c.push(I));else{const n=[e+m+d*x,i+f+d*w,d*T,d*S];if(this.fontPx=b?u:0,t){let t=I<0?-1/0:1/0;Object.is(I,-0)&&(t=-1/0),this.draw2D(n,C,t)}else this.draw2D(n,C,I);p&&this.drawCrossLines(this.screenSlices.length-1,C,o,l,c),t=!1,p=!1}D=T,x+=g,v=Math.max(v,S)}if(w+=v,y=Math.max(y,x+D),y<=0||w<=0)break;const I=(n-2*this.opts.tileMargin-g)/y,S=(r-2*this.opts.tileMargin)/w;d=Math.min(I,S),this.opts.centerMosaic?(m=Math.floor(.5*(n-y*d)),f=Math.floor(.5*(r-w*d))):(m=this.opts.tileMargin,f=this.opts.tileMargin)}this.fontPx=u}
1calculateWidthHeight(t,e,i,n){return function(t,e,i,n){let r,a;switch(t){case 0:r=e[0],a=e[1];break;case 1:r=e[0],a=e[2];break;case 2:r=e[1],a=e[2];break;default:return[i,n]}const s=r/a;let o,l;return s>i/n?(o=i,l=i/s):(l=n,o=n*s),[o,l]}(t,e,i,n)}getBoundsRegionCSS(){const t=this.gl.canvas.getBoundingClientRect();return function(t){const{bounds:e,rectWidth:i,rectHeight:n}=t;if(!e)return[0,0,i,n];const[[r,a],[s,o]]=e,l=Math.round(r*i),c=Math.round((s-r)*i),h=Math.round(a*n),d=Math.round(o*n);return[l,n-d,c,d-h]}({bounds:this.opts.bounds,rectWidth:t.width,rectHeight:t.height})}eventInBounds(t){const e=this.gl.canvas.getBoundingClientRect();let i,n;if(t instanceof MouseEvent)i=t.clientX,n=t.clientY;else if(t instanceof TouchEvent){const e=t.touches[0]??t.changedTouches[0];if(!e)return!1;i=e.clientX,n=e.clientY}else i=t.clientX,n=t.clientY;return function(t){const{x:e,y:i,boundsRegion:n}=t,[r,a,s,o]=n;return e>=r&&e<=r+s&&i>=a&&i<=a+o}({x:i-e.left,y:n-e.top,boundsRegion:this.getBoundsRegionCSS()})}cursorInBounds(){return function(t){const{mouseX:e,mouseY:i,boundsRegion:n}=t;if(e<0||i<0)return!1;const[r,a,s,o]=n;return e>=r&&e<=r+s&&i>=a&&i<=a+o}({mouseX:this.mousePos[0],mouseY:this.mousePos[1],boundsRegion:this.getBoundsRegion()})}getBoundsRegion(){const t=this.gl,e=this.uiData?.dpr||window.devicePixelRatio||1,i=t.canvas;return function(t){const{bounds:e,canvasWidth:i,canvasHeight:n,cssWidth:r,cssHeight:a,dpr:s}=t;if(!e)return[0,0,i,n];const[[o,l],[c,h]]=e,d=Math.floor(o*r*s),u=Math.ceil((c-o)*r*s);let m=Math.floor((1-h)*a*s),f=Math.ceil((h-l)*a*s);return m<0&&(f+=m,m=0),m+f>n&&(f=n-m),[d,m,u,f]}({bounds:this.opts.bounds,canvasWidth:t.canvas.width,canvasHeight:t.canvas.height,cssWidth:i.clientWidth,cssHeight:i.clientHeight,dpr:e})}inBounds(t,e){return function(t){const{x:e,y:i,dpr:n,canvasHeight:r,boundsRegion:a}=t,[s,o,l,c]=a,h=e*n,d=r-i*n;return h>=s&&h<=s+l&&d>=o&&d<=o+c}({x:t,y:e,dpr:this.uiData.dpr,canvasHeight:this.gl.canvas.height,boundsRegion:this.getBoundsRegion()})}bindTextures(){this.gl.activeTexture(S),this.opts.is2DSliceShader?this.gl.bindTexture(this.gl.TEXTURE_2D,this.volumeTexture):this.gl.bindTexture(this.gl.TEXTURE_3D,this.volumeTexture),this.gl.activeTexture(F),this.gl.bindTexture(this.gl.TEXTURE_3D,this.overlayTexture),this.gl.activeTexture(P),this.gl.bindTexture(this.gl.TEXTURE_3D,this.paqdTexture),this.gl.activeTexture(B),this.gl.bindTexture(this.gl.TEXTURE_2D,this.fontTexture),this.gl.activeTexture(E),this.gl.bindTexture(this.gl.TEXTURE_2D,this.colormapTexture),this.gl.activeTexture(V),this.gl.bindTexture(this.gl.TEXTURE_2D,this.matCapTexture),this.gl.activeTexture(U),this.gl.bindTexture(this.gl.TEXTURE_3D,this.gradientTexture)}clearBounds(t,e){void 0===t&&(t=this.gl.COLOR_BUFFER_BIT|this.gl.DEPTH_BUFFER_BIT);const i=this.gl,[n,r,a,s]=e??this.getBoundsRegion(),o=i.canvas.height-r-s;t&i.DEPTH_BUFFER_BIT&&i.clearDepth(1),i.enable(i.SCISSOR_TEST),i.scissor(n,o,a,s),t&i.COLOR_BUFFER_BIT&&i.clearColor(this.opts.backColor[0],this.opts.backColor[1],this.opts.backColor[2],this.opts.backColor[3]),i.clear(t),i.disable(i.SCISSOR_TEST)}drawBoundsBorder(){if(!this.opts.showBoundsBorder)return;const[t,e,i,n]=this.getBoundsRegion();this.drawBoundsBox([t,e,i,n],this.opts.boundsBorderColor,this.opts.selectionBoxLineThickness)}drawSceneCore(){if(!this.initialized)return;this.colorbarHeight=0;const[t,e,i,n]=this.getBoundsRegion();if(this.gl.viewport(t,e,i,n),this.clearBounds(this.gl.COLOR_BUFFER_BIT|this.gl.DEPTH_BUFFER_BIT),this.bindTextures(),this.bmpTexture&&this.thumbnailVisible)return void this.drawThumbnail();let r="";if(0===this.volumes.length||void 0===this.volumes[0].dims)return this.meshes.length>0?this.sliceMosaicString.length>0?(this.opts.isColorbar&&this.reserveColorbarPanel(),this.drawMosaic(this.sliceMosaicString),void(this.opts.isColorbar&&this.drawColorbar())):(this.screenSlices=[],this.draw3D([t,e,i,n]),this.opts.isColorbar&&this.drawColorbar(),void this.drawAnchoredLabels()):void this.drawLoadingText(this.opts.loadingText);const s=this.scene.clipPlaneDepthAziElevs?.[this.uiData.activeClipPlaneIndex]?.[0]??2;if(function(t){const{isDragging:e,activeClipPlaneDepth:i,dragStartTileIndex:n}=t;return e&&(void 0===r&&(r=1.8),i<r)&&n>=0;var r}({isDragging:this.uiData.isDragging,activeClipPlaneDepth:s,dragStartTileIndex:this.inRenderTile(this.uiData.dragStart[0],this.uiData.dragStart[1])})){const t=this.uiData.dragStart[0]-this.uiData.dragEnd[0],e=this.uiData.dragStart[1]-this.uiData.dragEnd[1],i=function(t){const{startDepthAziElev:e,dragDeltaX:i,dragDeltaY:n}=t,r=[e[0],(e[1]-i)%360,e[2]+n];return{depthAziElev:r,changed:r[1]!==e[1]||r[2]!==e[2]}}({startDepthAziElev:this.uiData.dragClipPlaneStartDepthAziElev,dragDeltaX:t,dragDeltaY:e});if(i.changed){const t=this.uiData.activeClipPlaneIndex;this.scene.clipPlaneDepthAziElevs[t]=i.depthAziElev;const e=ba({depth:i.depthAziElev[0],azimuth:i.depthAziElev[1],elevation:i.depthAziElev[2]});this.scene.clipPlanes[t]=e,this._emitEvent("clipPlaneChange",{clipPlane:e}),this.onClipPlaneChange(e)}}if(this.sliceMosaicString.length<1&&4===this.opts.sliceType)return this.opts.isColorbar&&this.reserveColorbarPanel(),this.screenSlices=[],this.draw3D(),this.opts.isColorbar&&this.drawColorbar(),void this.drawAnchoredLabels();this.opts.isColorbar&&this.reserveColorbarPanel();const o=this.getMaxVols(),l=3===this.opts.sliceType&&o>1&&this.graph.autoSizeMultiplanar&&this.graph.opacity>0;if(this.sliceMosaicString.length>0)this.drawMosaic(this.sliceMosaicString);else{const r=[0,0];let a=!1;if(this.screenSlices=[],this.customLayout&&this.customLayout.length>0){this.screenSlices=[];const{volScale:r}=this.sliceScale();for(const a of this.customLayout){const{sliceType:s,position:o,sliceMM:l}=a,c=[t+o[0]*i,e+o[1]*n,o[2]*i,o[3]*n];if(c[0]+c[2]>t+i&&(Q.warn("adjusting slice width because it would have been clipped"),c[2]=t+i-c[0]),c[1]+c[3]>e+n&&(Q.warn("adjusting slice height because it would have been clipped"),c[3]=e+n-c[1]),4===s)this.draw3D(c);else{const t=this.calculateWidthHeight(s,r,c[2],c[3]);this.draw2D(c,s,l??NaN,t)}}}else if(0===this.opts.sliceType||1===this.opts.sliceType||2===this.opts.sliceType)this.draw2D([0,0,0,0],this.opts.sliceType,NaN);
1else{let t=function(t,e){return[(t-1)*c+t*h,(e-1)*c+e*h]},e=!1;this.opts.multiplanarForceRender?(e=!0,this.opts.multiplanarForceRender?this.opts.multiplanarShowRender=1:this.opts.multiplanarShowRender=2,delete this.opts.multiplanarForceRender):1===this.opts.multiplanarShowRender&&(e=!0);const i=isFinite(this.drawPenLocation[0])&&this.opts.drawingEnabled,{volScale:n}=this.sliceScale(),s=n.slice();this.opts.multiplanarEqualSize&&(n[0]=1,n[1]=1,n[2]=1),"number"!=typeof this.opts.multiplanarPadPixels&&Q.debug("multiplanarPadPixels must be numeric");const c=parseFloat(`${this.opts.multiplanarPadPixels}`)*this.uiData.dpr;let h=this.opts.tileMargin*this.uiData.dpr;h<0&&(h=2*(2+Math.ceil(this.fontPx)));const[d,u,m,f]=this.getBoundsRegion();let g=[this.effectiveCanvasWidth(),this.effectiveCanvasHeight()];this.opts.heroImageFraction>0&&this.opts.heroImageFraction<1&&(e=!1,a=!0,g[0]>g[1]&&3!==this.opts.multiplanarLayout?r[0]=g[0]*this.opts.heroImageFraction:r[1]=g[1]*this.opts.heroImageFraction,g=[g[0]-r[0],g[1]-r[1]]);const A=this.scaleSlice(n[0]+n[1],n[1]+n[2],t(2,2),g),p=Math.max(Math.max(n[1],n[2]),n[0]),v=this.scaleSlice(n[0]+n[0]+n[1],Math.max(n[1],n[2]),t(3,1),g),x=this.scaleSlice(n[0]+n[0]+n[1]+p,Math.max(n[1],n[2]),t(4,1),g),w=this.scaleSlice(p,n[1]+n[2]+n[2],t(1,3),g),y=this.scaleSlice(p,n[1]+n[2]+n[2]+p,t(1,4),g);let b=!i&&(o<2||!l),C=!1,M=!1,D=!1;1===this.opts.multiplanarLayout?C=!0:2===this.opts.multiplanarLayout?M=!0:3===this.opts.multiplanarLayout?D=!0:w[4]>v[4]&&w[4]>A[4]?C=!0:v[4]>A[4]?D=!0:M=!0;let T=A;if(C?(T=w,!a&&(e||2===this.opts.multiplanarShowRender&&y[4]>=w[4])?T=y:b=!1):D&&(T=v,!a&&(e||2===this.opts.multiplanarShowRender&&x[4]>=v[4])?T=x:b=!1),a){const t=0===r[0]?m:r[0],e=0===r[1]?f:r[1];if(0===this.opts?.heroSliceType||1===this.opts?.heroSliceType||2===this.opts?.heroSliceType)this.draw2D([d,u,t,e],this.opts.heroSliceType,NaN,[1/0,1/0]);else{const i=T.slice();t===m&&(i[0]=0),this.draw3D([d+i[0],u,t,e])}T[0]+=r[0],T[1]+=r[1],b=!1}const I=n[0]*T[4]+h,S=n[1]*T[4]+h,E=n[2]*T[4]+h,F=s[0]*T[4],B=s[1]*T[4],V=s[2]*T[4];if(C){if(this.draw2D([d+T[0],u+T[1],I,S],0,NaN,[F,B]),this.draw2D([d+T[0],u+T[1]+S+c,I,E],1,NaN,[F,V]),this.draw2D([d+T[0],u+T[1]+S+c+E+c,S,E],2,NaN,[B,V]),b){const t=p*T[4];this.draw3D([d+T[0],u+T[1]+S+E+E+3*c,t,t])}}else if(D){if(this.draw2D([d+T[0],u+T[1],I,S],0,NaN,[F,B]),this.draw2D([d+T[0]+I+c,u+T[1],I,E],1,NaN,[F,V]),this.draw2D([d+T[0]+I+I+2*c,u+T[1],S,E],2,NaN,[B,V]),b){const t=p*T[4];this.draw3D([d+T[0]+I+I+S+3*c,u+T[1],t,t])}}else M&&(e||(b=!1),2===this.opts.multiplanarShowRender&&(b=!0),a&&(b=!1),this.draw2D([d+T[0],u+T[1]+E+c,I,S],0,NaN,[F,B]),this.draw2D([d+T[0],u+T[1],I,E],1,NaN,[F,V]),this.draw2D([d+T[0]+I+c,u+T[1],S,E],2,NaN,[B,V]),b&&this.draw3D([d+T[0]+I+c,u+T[1]+E+c,S,S]))}}if(this.opts.isRuler&&this.drawRuler(),this.opts.isColorbar&&this.drawColorbar(),l&&this.drawGraph(),this.uiData.isDragging){if(this.uiData.mouseButtonCenterDown)return void this.dragForCenterButton([this.uiData.dragStart[0],this.uiData.dragStart[1],this.uiData.dragEnd[0],this.uiData.dragEnd[1]]);if(4===this.getCurrentDragMode())return void this.dragForSlicer3D([this.uiData.dragStart[0],this.uiData.dragStart[1],this.uiData.dragEnd[0],this.uiData.dragEnd[1]]);if(3===this.getCurrentDragMode()&&!this._skipDragInDraw)return void this.dragForPanZoom([this.uiData.dragStart[0],this.uiData.dragStart[1],this.uiData.dragEnd[0],this.uiData.dragEnd[1]]);if(this.inRenderTile(this.uiData.dragStart[0],this.uiData.dragStart[1])>=0)return;2===this.getCurrentDragMode()&&this.drawMeasurementTool([this.uiData.dragStart[0],this.uiData.dragStart[1],this.uiData.dragEnd[0],this.uiData.dragEnd[1]]),7===this.getCurrentDragMode()&&this.drawAngleMeasurementTool();const t=this.getCurrentDragMode();if(1===t||6===t){const t=Math.abs(this.uiData.dragStart[0]-this.uiData.dragEnd[0]),e=Math.abs(this.uiData.dragStart[1]-this.uiData.dragEnd[1]);this.drawSelectionBox([Math.min(this.uiData.dragStart[0],this.uiData.dragEnd[0]),Math.min(this.uiData.dragStart[1],this.uiData.dragEnd[1]),t,e])}}for(const a of this.document.completedMeasurements)if(this.shouldDrawOnCurrentSlice(a.sliceIndex,a.sliceType,a.slicePosition)){const t=this.mm2frac(a.startMM),e=this.mm2frac(a.endMM),i=this.frac2canvasPosWithT
1ile(t,a.sliceType),n=this.frac2canvasPosWithTile(e,a.sliceType);i&&n&&i.tileIndex===n.tileIndex&&this.drawMeasurementTool([i.pos[0],i.pos[1],n.pos[0],n.pos[1]])}for(let a=0;a<this.document.completedAngles.length;a++){const t=this.document.completedAngles[a];if(this.shouldDrawOnCurrentSlice(t.sliceIndex,t.sliceType,t.slicePosition)){const e=this.mm2frac(t.firstLineMM.start),i=this.mm2frac(t.firstLineMM.end),n=this.mm2frac(t.secondLineMM.start),r=this.mm2frac(t.secondLineMM.end),a=this.frac2canvasPosWithTile(e,t.sliceType),s=this.frac2canvasPosWithTile(i,t.sliceType),o=this.frac2canvasPosWithTile(n,t.sliceType),l=this.frac2canvasPosWithTile(r,t.sliceType);if(a&&s&&o&&l&&a.tileIndex===s.tileIndex&&a.tileIndex===o.tileIndex&&a.tileIndex===l.tileIndex){this.drawMeasurementTool([a.pos[0],a.pos[1],s.pos[0],s.pos[1]],!1),this.drawMeasurementTool([o.pos[0],o.pos[1],l.pos[0],l.pos[1]],!1);const e={firstLine:[a.pos[0],a.pos[1],s.pos[0],s.pos[1]],secondLine:[o.pos[0],o.pos[1],l.pos[0],l.pos[1]],sliceIndex:t.sliceIndex,sliceType:t.sliceType,slicePosition:t.slicePosition};this.drawAngleTextForAngle(e)}}}const c=this.frac2mm([this.scene.crosshairPos[0],this.scene.crosshairPos[1],this.scene.crosshairPos[2]]);r=c[0].toFixed(2)+"\xd7"+c[1].toFixed(2)+"\xd7"+c[2].toFixed(2),this.readyForSync=!0,this.sync();return this.screenSlices.some((t=>4===t.axCorSag))||this.draw3DLabels(a.vt(),[0,0,0,0],!0),this.drawAnchoredLabels(),this.drawBoundsBorder(),r}drawScene(){if(this.isBusy)return void(this.needsRefresh=!0);this.isBusy=!1,this.needsRefresh=!1;let t=this.drawSceneCore();return null!==this._gl&&this.gl.finish(),this.needsRefresh&&(t=this.drawScene()),t}
1r8Tex(t,e,i,n){return void 0===n&&(n=!1),function(t,e,i,n,r){if(void 0===r&&(r=!1),e&&t.deleteTexture(e),e=t.createTexture(),t.activeTexture(i),t.bindTexture(t.TEXTURE_3D,e),t.texParameteri(t.TEXTURE_3D,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_3D,t.TEXTURE_MAG_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_3D,t.TEXTURE_WRAP_R,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_3D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_3D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.pixelStorei(t.UNPACK_ALIGNMENT,1),t.texStorage3D(t.TEXTURE_3D,1,t.R8,n[1],n[2],n[3]),r){const e=new Uint8Array(n[1]*n[2]*n[3]);t.texSubImage3D(t.TEXTURE_3D,0,0,0,0,n[1],n[2],n[3],t.RED,t.UNSIGNED_BYTE,e)}return e}(this.gl,t,e,i,n)}r16Tex(t,e,i,n){return function(t,e,i,n,r){e&&t.deleteTexture(e),e=t.createTexture(),t.activeTexture(i),t.bindTexture(t.TEXTURE_3D,e),t.texParameteri(t.TEXTURE_3D,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_3D,t.TEXTURE_MAG_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_3D,t.TEXTURE_WRAP_R,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_3D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_3D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.pixelStorei(t.UNPACK_ALIGNMENT,1),t.texStorage3D(t.TEXTURE_3D,1,t.R16I,n[1],n[2],n[3]);const a=n[1]*n[2]*n[3];return r.length!==a&&(r=new Int16Array(a)),t.texSubImage3D(t.TEXTURE_3D,0,0,0,0,n[1],n[2],n[3],t.RED_INTEGER,t.SHORT,r),e}(this.gl,t,e,i,n)}r16fTex(t,e,i,n){return function(t,e,i,n,r){return e&&t.deleteTexture(e),e=t.createTexture(),t.activeTexture(i),t.bindTexture(t.TEXTURE_3D,e),t.texParameteri(t.TEXTURE_3D,t.TEXTURE_MIN_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_3D,t.TEXTURE_MAG_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_3D,t.TEXTURE_WRAP_R,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_3D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_3D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.pixelStorei(t.UNPACK_ALIGNMENT,1),t.texStorage3D(t.TEXTURE_3D,1,t.R16F,n[1],n[2],n[3]),t.texSubImage3D(t.TEXTURE_3D,0,0,0,0,n[1],n[2],n[3],t.RED,t.FLOAT,r),e}(this.gl,t,e,i,n)}rgbaTex2D(t,e,i,n,r){return void 0===n&&(n=null),void 0===r&&(r=!0),function(t,e,i,n,r,a){if(void 0===r&&(r=null),void 0===a&&(a=!0),e&&t.deleteTexture(e),e=t.createTexture(),t.activeTexture(i),t.bindTexture(t.TEXTURE_2D,e),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.pixelStorei(t.UNPACK_ALIGNMENT,1),t.texStorage2D(t.TEXTURE_2D,1,t.RGBA8,n[1],n[2]),r){let e=r;const i=n[1],s=n[2];if(a){e=new Uint8Array(r.length);const t=4*i;for(let i=0;i<s;i++){const n=i*t,a=(s-1-i)*t;e.set(r.subarray(n,n+t),a)}}t.texSubImage2D(t.TEXTURE_2D,0,0,0,i,s,t.RGBA,t.UNSIGNED_BYTE,e)}return e}(this.gl,t,e,i,n,r)}rgbaTex(t,e,i,n){return void 0===n&&(n=!1),function(t,e,i,n,r){if(void 0===r&&(r=!1),e&&t.deleteTexture(e),e=t.createTexture(),t.activeTexture(i),t.bindTexture(t.TEXTURE_3D,e),t.texParameteri(t.TEXTURE_3D,t.TEXTURE_MIN_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_3D,t.TEXTURE_MAG_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_3D,t.TEXTURE_WRAP_R,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_3D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_3D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.pixelStorei(t.UNPACK_ALIGNMENT,1),t.texStorage3D(t.TEXTURE_3D,1,t.RGBA8,n[1],n[2],n[3]),r){const e=new Uint8Array(n[1]*n[2]*n[3]*4);t.texSubImage3D(t.TEXTURE_3D,0,0,0,0,n[1],n[2],n[3],t.RGBA,t.UNSIGNED_BYTE,e)}return e}(this.gl,t,e,i,n)}rgba16Tex(t,e,i,n){return void 0===n&&(n=!1),function(t,e,i,n,r){if(void 0===r&&(r=!1),e&&t.deleteTexture(e),e=t.createTexture(),t.activeTexture(i),t.bindTexture(t.TEXTURE_3D,e),t.texParameteri(t.TEXTURE_3D,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_3D,t.TEXTURE_MAG_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_3D,t.TEXTURE_WRAP_R,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_3D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_3D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.pixelStorei(t.UNPACK_ALIGNMENT,2),t.pixelStorei(t.PACK_ALIGNMENT,2),t.texStorage3D(t.TEXTURE_3D,1,t.RGBA16UI,n[1],n[2],n[3]),r){const e=new Uint16Array(n[1]*n[2]*n[3]*4);t.texSubImage3D(t.TEXTURE_3D,0,0,0,0,n[1],n[2],n[3],t.RGBA_INTEGER,t.UNSIGNED_SHORT,e)}return e}(this.gl,t,e,i,n)}requestCORSIfNotSameOrigin(t,e){Ee(t,e)}
1async loadPngAsTexture(t,e){const i=await async function(t,e,i,n,r,a,s,o,l){return new Promise(((c,h)=>{const d=new Image;d.onload=()=>{if(!r)return;let e;if(4===i){null!==s&&t.deleteTexture(s),e=t.createTexture();const i=d.width/d.height;t.activeTexture(33988),r.use(t),t.uniform1i(r.uniforms.bmpTexture,4),l&&l(i)}else if(5===i)null!==o&&t.deleteTexture(o),e=t.createTexture(),t.activeTexture(33989);else{if(!n)return void h(new Error("Font shader required for texture unit 3"));null!==a&&t.deleteTexture(a),e=t.createTexture(),n.use(t),t.activeTexture(33987),t.uniform1i(n.uniforms.fontTexture,3)}t.bindTexture(t.TEXTURE_2D,e),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.LINEAR),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,d),c(e)},d.onerror=h,Ee(d,e),d.src=e}))}(this.gl,t,e,this.fontShader,this.bmpShader,this.fontTexture,this.bmpTexture,this.matCapTexture,(t=>{this.bmpTextureWH=t}));return 3===e?this.fontTexture=i:4===e?this.bmpTexture=i:5===e&&(this.matCapTexture=i),this.drawScene(),i}async loadFontTexture(t){return this.loadPngAsTexture(t,3)}async loadBmpTexture(t){return this.loadPngAsTexture(t,4)}async loadMatCapTexture(t){return this.loadPngAsTexture(t,5)}get gl(){if(!this._gl)throw new Error("unable to get WebGL context. Maybe the browser doesn't support WebGL2.");return this._gl}set gl(t){this._gl=t}findDrawingBoundarySlices(t){if(!this.back||!this.back.dims||!this.drawBitmap)return null;const e={dimX:this.back.dims[1],dimY:this.back.dims[2],dimZ:this.back.dims[3]};return function(t,e,i){const{dimX:n,dimY:r,dimZ:a}=i;let s;if(0===t)s=a;else if(1===t)s=r;else{if(2!==t)return null;s=n}let o=-1,l=-1;for(let c=0;c<s;c++){let i=!1;if(0===t){const t=c*n*r;for(let a=0;a<n*r;a++)if(e[t+a]>0){i=!0;break}}else if(1===t)for(let t=0;t<a;t++){for(let a=0;a<n;a++)if(e[a+c*n+t*n*r]>0){i=!0;break}if(i)break}else if(2===t)for(let t=0;t<a;t++){for(let a=0;a<r;a++)if(e[c+a*n+t*n*r]>0){i=!0;break}if(i)break}i&&(-1===o&&(o=c),l=c)}return-1===o||-1===l?null:{first:o,last:l}}(t,this.drawBitmap,e)}interpolateMaskSlices(t,e,i){if(void 0===i&&(i={}),!this.back||!this.back.dims||!this.drawBitmap)throw new Error("Background image and drawing bitmap must be loaded");const n={dimX:this.back.dims[1],dimY:this.back.dims[2],dimZ:this.back.dims[3]},r=this.back.img,a=this.back.global_max;!function(t,e,i,n,r,a,s,o){const{dimX:l,dimY:c,dimZ:h}=e,d=s.sliceType??0;let u,m,f;if(0===d)u=l,m=c,f=h-1;else if(1===d)u=l,m=h,f=c-1;else{if(2!==d)throw new Error("Invalid slice type. Must be AXIAL, CORONAL, or SAGITTAL");u=c,m=h,f=l-1}const g={intensityWeight:s.intensityWeight??.7,binaryThreshold:s.binaryThreshold??.375,intensitySigma:s.intensitySigma??.1,applySmoothingToSlices:s.applySmoothingToSlices??!0,useIntensityGuided:s.useIntensityGuided??!0};if(void 0!==r&&void 0!==a){if(r>=a)throw new Error("Low slice index must be less than high slice index");if(r<0||a>f)throw new Error(`Slice indices out of bounds [0, ${f}]`)}const A=new Map;for(let p=0;p<=f;p++){const i=Ta(p,d,t,e);for(let t=0;t<i.length;t++){const e=i[t];if(e>0)if(A.has(e)){const t=A.get(e);t.min=Math.min(t.min,p),t.max=Math.max(t.max,p)}else A.set(e,{min:p,max:p})}}for(const[p,v]of A){const s=void 0!==r?Math.max(r,v.min):v.min,o=void 0!==a?Math.min(a,v.max):v.max;if(s>=o||o-s<2)continue;const l=Ta(s,d,t,e),c=Ta(o,d,t,e),h=new Float32Array(l.length),f=new Float32Array(c.length);for(let t=0;t<l.length;t++)h[t]=l[t]===p?1:0,f[t]=c[t]===p?1:0;g.applySmoothingToSlices&&(Ea(h,u,m),Ea(f,u,m));for(let r=s+1;r<o;r++){const a=new Float32Array(u*m);g.useIntensityGuided&&i?Va(h,f,r,s,o,a,g,Ia(s,d,i,e,n),Ia(o,d,i,e,n),Ia(r,d,i,e,n)):Ba(h,f,r,s,o,a),Sa(a,r,d,t,e,g.binaryThreshold,p)}}o()}(this.drawBitmap,n,r,a,t,e,i,(()=>this.refreshDrawing(!0)))}};ns=new WeakMap}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.