open-plant 1.2.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +7 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var Ht=Object.defineProperty;var Zt=(t,e,
|
|
1
|
+
"use strict";var Ht=Object.defineProperty;var Zt=(t,e,r)=>e in t?Ht(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r;var d=(t,e,r)=>Zt(t,typeof e!="symbol"?e+"":e,r);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const de=require("react/jsx-runtime"),f=require("react");var He=typeof document<"u"?document.currentScript:null;function gt(t,e,r){const n=t.createShader(e);if(!n)throw new Error("Failed to create shader.");if(t.shaderSource(n,r),t.compileShader(n),!t.getShaderParameter(n,t.COMPILE_STATUS)){const o=t.getShaderInfoLog(n)??"unknown shader error";throw t.deleteShader(n),new Error(o)}return n}function jt(t,e,r){const n=gt(t,t.VERTEX_SHADER,e),i=gt(t,t.FRAGMENT_SHADER,r),o=t.createProgram();if(!o)throw t.deleteShader(n),t.deleteShader(i),new Error("Failed to create program.");if(t.attachShader(o,n),t.attachShader(o,i),t.linkProgram(o),t.deleteShader(n),t.deleteShader(i),!t.getProgramParameter(o,t.LINK_STATUS)){const a=t.getProgramInfoLog(o)??"unknown link error";throw t.deleteProgram(o),new Error(a)}return o}function Ze(t,e,r){const n=t.getUniformLocation(e,r);if(!n)throw new Error(`Failed to get uniform location: ${r}`);return n}function Kt(t){const e=t.getContext("webgl2",{alpha:!1,antialias:!1,depth:!1,stencil:!1,preserveDrawingBuffer:!1,powerPreference:"high-performance"});if(!e)throw new Error("WebGL2 is not available.");return e}let Jt=class{constructor(){d(this,"viewportWidth",1);d(this,"viewportHeight",1);d(this,"viewState",{offsetX:0,offsetY:0,zoom:1})}setViewport(e,r){this.viewportWidth=Math.max(1,e),this.viewportHeight=Math.max(1,r)}getViewportSize(){return{width:this.viewportWidth,height:this.viewportHeight}}setViewState(e){e.offsetX!==void 0&&(this.viewState.offsetX=e.offsetX),e.offsetY!==void 0&&(this.viewState.offsetY=e.offsetY),e.zoom!==void 0&&(this.viewState.zoom=Math.max(1e-4,e.zoom))}getViewState(){return{...this.viewState}}getMatrix(){const e=this.viewportWidth/this.viewState.zoom,r=this.viewportHeight/this.viewState.zoom,n=2/e,i=-2/r,o=-1-this.viewState.offsetX*n,s=1-this.viewState.offsetY*i;return new Float32Array([n,0,0,0,i,0,o,s,1])}};const Qt=`#version 300 es
|
|
2
2
|
precision highp float;
|
|
3
3
|
|
|
4
4
|
in vec2 aUnit;
|
|
@@ -18,7 +18,7 @@ void main() {
|
|
|
18
18
|
gl_Position = vec4(clip.xy, 0.0, 1.0);
|
|
19
19
|
vUv = aUv;
|
|
20
20
|
}
|
|
21
|
-
`,
|
|
21
|
+
`,er=`#version 300 es
|
|
22
22
|
precision highp float;
|
|
23
23
|
|
|
24
24
|
in vec2 vUv;
|
|
@@ -29,7 +29,7 @@ out vec4 outColor;
|
|
|
29
29
|
void main() {
|
|
30
30
|
outColor = texture(uTexture, vUv);
|
|
31
31
|
}
|
|
32
|
-
`;class St{constructor(e){d(this,"canvas");d(this,"gl");d(this,"camera",new Jt);d(this,"imageWidth");d(this,"imageHeight");d(this,"clearColor");d(this,"program");d(this,"vao");d(this,"quadBuffer");d(this,"uCameraLocation");d(this,"uBoundsLocation");d(this,"uTextureLocation");d(this,"resizeObserver");d(this,"tiles",[]);d(this,"frameId",null);d(this,"loadVersion",0);d(this,"destroyed",!1);d(this,"fitted",!1);d(this,"controlledViewState",!1);this.canvas=e.canvas,this.imageWidth=Math.max(1,e.imageWidth),this.imageHeight=Math.max(1,e.imageHeight),this.clearColor=e.clearColor??[.03,.05,.08,1],this.gl=Kt(this.canvas),this.program=jt(this.gl,Qt,en);const n=this.gl.createVertexArray(),r=this.gl.createBuffer();if(!n||!r)throw new Error("Failed to create WebGL buffers.");this.vao=n,this.quadBuffer=r,this.gl.bindVertexArray(this.vao),this.gl.bindBuffer(this.gl.ARRAY_BUFFER,this.quadBuffer);const i=new Float32Array([0,0,0,0,1,0,1,0,0,1,0,1,1,1,1,1]);this.gl.bufferData(this.gl.ARRAY_BUFFER,i,this.gl.STATIC_DRAW);const o=this.gl.getAttribLocation(this.program,"aUnit"),s=this.gl.getAttribLocation(this.program,"aUv");if(o<0||s<0)throw new Error("Failed to get attribute locations.");const a=4*Float32Array.BYTES_PER_ELEMENT;this.gl.enableVertexAttribArray(o),this.gl.vertexAttribPointer(o,2,this.gl.FLOAT,!1,a,0),this.gl.enableVertexAttribArray(s),this.gl.vertexAttribPointer(s,2,this.gl.FLOAT,!1,a,2*Float32Array.BYTES_PER_ELEMENT),this.gl.bindVertexArray(null),this.gl.bindBuffer(this.gl.ARRAY_BUFFER,null),this.uCameraLocation=Ze(this.gl,this.program,"uCamera"),this.uBoundsLocation=Ze(this.gl,this.program,"uBounds"),this.uTextureLocation=Ze(this.gl,this.program,"uTexture"),e.initialViewState&&(this.controlledViewState=!0,this.camera.setViewState(e.initialViewState)),this.resizeObserver=new ResizeObserver(()=>{this.resize()}),this.resizeObserver.observe(this.canvas),this.resize()}async setTiles(e){if(this.destroyed)return;const n=++this.loadVersion,r=await Promise.all(e.map(async i=>await this.loadTile(i,n)));if(this.destroyed||n!==this.loadVersion){for(const i of r)i&&this.gl.deleteTexture(i.texture);return}this.disposeTiles(this.tiles),this.tiles=r.filter(i=>i!==null),this.requestRender()}setViewState(e){this.controlledViewState=!0,this.camera.setViewState(e),this.requestRender()}getViewState(){return this.camera.getViewState()}destroy(){this.destroyed||(this.destroyed=!0,this.loadVersion+=1,this.frameId!==null&&(cancelAnimationFrame(this.frameId),this.frameId=null),this.resizeObserver.disconnect(),this.disposeTiles(this.tiles),this.tiles=[],this.gl.deleteBuffer(this.quadBuffer),this.gl.deleteVertexArray(this.vao),this.gl.deleteProgram(this.program))}async loadTile(e,n){try{const r=await fetch(e.url);if(!r.ok)throw new Error(`Tile fetch failed: ${r.status} ${r.statusText}`);const i=await r.blob(),o=await createImageBitmap(i);if(this.destroyed||n!==this.loadVersion)return o.close(),null;const s=this.gl.createTexture();if(!s)throw o.close(),new Error("Failed to create tile texture.");return this.gl.bindTexture(this.gl.TEXTURE_2D,s),this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,1),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_WRAP_S,this.gl.CLAMP_TO_EDGE),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_WRAP_T,this.gl.CLAMP_TO_EDGE),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.texImage2D(this.gl.TEXTURE_2D,0,this.gl.RGBA,this.gl.RGBA,this.gl.UNSIGNED_BYTE,o),this.gl.bindTexture(this.gl.TEXTURE_2D,null),o.close(),{id:e.id,bounds:e.bounds,texture:s}}catch(r){return console.error(`[M1TileRenderer] tile load failed: ${e.id}`,r),null}}resize(){if(this.destroyed)return;const e=this.canvas.getBoundingClientRect(),n=Math.max(1,e.width||this.canvas.clientWidth||1),r=Math.max(1,e.height||this.canvas.clientHeight||1),i=Math.max(1,window.devicePixelRatio||1),o=Math.max(1,Math.round(n*i)),s=Math.max(1,Math.round(r*i));(this.canvas.width!==o||this.canvas.height!==s)&&(this.canvas.width=o,this.canvas.height=s),this.camera.setViewport(n,r),this.gl.viewport(0,0,this.canvas.width,this.canvas.height),!this.fitted&&!this.controlledViewState&&(this.fitToImage(),this.fitted=!0),this.requestRender()}fitToImage(){const e=this.camera.getViewportSize(),n=Math.min(e.width/this.imageWidth,e.height/this.imageHeight),r=Number.isFinite(n)&&n>0?n:1,i=e.width/r,o=e.height/r,s=(this.imageWidth-i)*.5,a=(this.imageHeight-o)*.5;this.camera.setViewState({zoom:r,offsetX:s,offsetY:a})}requestRender(){this.frameId!==null||this.destroyed||(this.frameId=requestAnimationFrame(()=>{this.frameId=null,this.render()}))}render(){if(!this.destroyed){this.gl.clearColor(this.clearColor[0],this.clearColor[1],this.clearColor[2],this.clearColor[3]),this.gl.clear(this.gl.COLOR_BUFFER_BIT),this.gl.useProgram(this.program),this.gl.bindVertexArray(this.vao),this.gl.uniformMatrix3fv(this.uCameraLocation,!1,this.camera.getMatrix()),this.gl.uniform1i(this.uTextureLocation,0);for(const e of this.tiles)this.gl.activeTexture(this.gl.TEXTURE0),this.gl.bindTexture(this.gl.TEXTURE_2D,e.texture),this.gl.uniform4f(this.uBoundsLocation,e.bounds[0],e.bounds[1],e.bounds[2],e.bounds[3]),this.gl.drawArrays(this.gl.TRIANGLE_STRIP,0,4);this.gl.bindTexture(this.gl.TEXTURE_2D,null),this.gl.bindVertexArray(null)}}disposeTiles(e){for(const n of e)this.gl.deleteTexture(n.texture)}}const at=[160,160,160,255];function q(t,e,n){return Math.max(e,Math.min(n,t))}function ut(t,e,n){const r=Number(t),i=Number(e),o=Number(n);return!Number.isFinite(r)||r<=0?1:!Number.isFinite(i)||!Number.isFinite(o)?r:Math.pow(2,i-o)*r}function tn(t,e,n){let i=100*ut(t,e,n);if(Number(t)){let o="μm";return i>1e3&&(i/=1e3,o="mm"),`${i.toPrecision(3)} ${o}`}return`${Math.round(i*1e3)/1e3} pixels`}function nn(t,e){return!t&&!e?!0:!t||!e?!1:Math.abs((t.zoom??0)-(e.zoom??0))<1e-6&&Math.abs((t.offsetX??0)-(e.offsetX??0))<1e-6&&Math.abs((t.offsetY??0)-(e.offsetY??0))<1e-6&&Math.abs((t.rotationDeg??0)-(e.rotationDeg??0))<1e-6}function rn(t){const e=String(t??"").trim();if(!e)return"";if(/^bearer\s+/i.test(e)){const n=e.replace(/^bearer\s+/i,"").trim();return n?`Bearer ${n}`:""}return`Bearer ${e}`}function At(t){const n=String(t??"").trim().match(/^#?([0-9a-fA-F]{6})$/);if(!n)return[...at];const r=Number.parseInt(n[1],16);return[r>>16&255,r>>8&255,r&255,255]}function on(t){const e=[[...at]],n=new Map;for(const i of t??[]){const o=String(i?.termId??"");!o||n.has(o)||(n.set(o,e.length),e.push(At(i?.termColor)))}const r=new Uint8Array(e.length*4);for(let i=0;i<e.length;i+=1)r[i*4]=e[i][0],r[i*4+1]=e[i][1],r[i*4+2]=e[i][2],r[i*4+3]=e[i][3];return{colors:r,termToPaletteIndex:n}}function pt(t,e,n){const r=t.createShader(t.VERTEX_SHADER),i=t.createShader(t.FRAGMENT_SHADER);if(!r||!i)throw new Error("Shader allocation failed");if(t.shaderSource(r,e),t.compileShader(r),!t.getShaderParameter(r,t.COMPILE_STATUS))throw new Error(t.getShaderInfoLog(r)||"vertex compile failed");if(t.shaderSource(i,n),t.compileShader(i),!t.getShaderParameter(i,t.COMPILE_STATUS))throw new Error(t.getShaderInfoLog(i)||"fragment compile failed");const o=t.createProgram();if(!o)throw new Error("Program allocation failed");if(t.attachShader(o,r),t.attachShader(o,i),t.linkProgram(o),t.deleteShader(r),t.deleteShader(i),!t.getProgramParameter(o,t.LINK_STATUS))throw new Error(t.getProgramInfoLog(o)||"program link failed");return o}const sn="rgba(255, 77, 79, 0.16)",an=3,un=2,It=96,cn=1,ln=[],tt=[],bt=1e3,_t=2,Bt=2,hn=4096,fn=.2,Pe={color:"#ff4d4f",width:2,lineJoin:"round",lineCap:"round",shadowColor:"rgba(0, 0, 0, 0)",shadowBlur:0,shadowOffsetX:0,shadowOffsetY:0},ge={fontFamily:"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace",fontSize:12,fontWeight:500,textColor:"#ffffff",backgroundColor:"rgba(8, 14, 22, 0.88)",borderColor:"rgba(255, 77, 79, 0.85)",borderWidth:1,paddingX:6,paddingY:4,offsetY:10,borderRadius:3};function qe(t,e,n){return Math.max(e,Math.min(n,t))}function ke(t){return t==="stamp-rectangle"||t==="stamp-circle"||t==="stamp-rectangle-4096px"||t==="stamp-rectangle-2mm2"||t==="stamp-circle-2mm2"||t==="stamp-circle-hpf-0.2mm2"}function je(t,e){return typeof t!="number"||!Number.isFinite(t)||t<=0?e:t}function dn(t){return{rectangleAreaMm2:je(t?.rectangleAreaMm2,_t),circleAreaMm2:je(t?.circleAreaMm2,Bt),rectanglePixelSize:je(t?.rectanglePixelSize,hn)}}function mn(t){return t*bt*bt}function wt(t,e){return!t||!Number.isFinite(e)||e<=0?[]:xe([[t[0]-e,t[1]-e],[t[0]+e,t[1]-e],[t[0]+e,t[1]+e],[t[0]-e,t[1]+e]])}function gn(t,e,n=It){if(!t||!Number.isFinite(e)||e<=0)return[];const r=[];for(let i=0;i<=n;i+=1){const o=i/n*Math.PI*2;r.push([t[0]+Math.cos(o)*e,t[1]+Math.sin(o)*e])}return xe(r)}function xe(t){if(!Array.isArray(t)||t.length<3)return[];const e=t.map(([i,o])=>[i,o]),n=e[0],r=e[e.length-1];return!n||!r?[]:((n[0]!==r[0]||n[1]!==r[1])&&e.push([n[0],n[1]]),e)}function nt(t,e){return!t||!e?[]:xe([[t[0],t[1]],[e[0],t[1]],[e[0],e[1]],[t[0],e[1]]])}function rt(t,e,n=It){if(!t||!e)return[];const r=(t[0]+e[0])*.5,i=(t[1]+e[1])*.5,o=Math.hypot(e[0]-t[0],e[1]-t[1])*.5;if(o<1)return[];const s=[];for(let a=0;a<=n;a+=1){const l=a/n*Math.PI*2;s.push([r+Math.cos(l)*o,i+Math.sin(l)*o])}return xe(s)}function it(t){if(!Array.isArray(t)||t.length<4)return 0;let e=0;for(let n=0;n<t.length-1;n+=1){const r=t[n],i=t[n+1];e+=r[0]*i[1]-i[0]*r[1]}return Math.abs(e*.5)}function yt(t){if(!Array.isArray(t)||t.length===0)return[0,0,0,0];let e=1/0,n=1/0,r=-1/0,i=-1/0;for(const[o,s]of t)o<e&&(e=o),o>r&&(r=o),s<n&&(n=s),s>i&&(i=s);return[e,n,r,i]}function xt(t){return Array.isArray(t)&&t.length>=4&&it(t)>cn}function _e(t,e,n,r=!1,i=!1){if(e.length!==0){t.beginPath(),t.moveTo(e[0][0],e[0][1]);for(let o=1;o<e.length;o+=1)t.lineTo(e[o][0],e[o][1]);r&&t.closePath(),i&&r&&(t.fillStyle=sn,t.fill()),t.strokeStyle=n.color,t.lineWidth=n.width,t.lineJoin=n.lineJoin,t.lineCap=n.lineCap,t.shadowColor=n.shadowColor,t.shadowBlur=n.shadowBlur,t.shadowOffsetX=n.shadowOffsetX,t.shadowOffsetY=n.shadowOffsetY,t.setLineDash(n.lineDash),t.stroke(),t.setLineDash(tt),t.shadowColor="rgba(0, 0, 0, 0)",t.shadowBlur=0,t.shadowOffsetX=0,t.shadowOffsetY=0}}function Ut(t){const e=Array.isArray(t?.lineDash)?t.lineDash.filter(s=>Number.isFinite(s)&&s>=0):tt,n=typeof t?.width=="number"&&Number.isFinite(t.width)?Math.max(0,t.width):Pe.width,r=typeof t?.shadowBlur=="number"&&Number.isFinite(t.shadowBlur)?Math.max(0,t.shadowBlur):Pe.shadowBlur,i=typeof t?.shadowOffsetX=="number"&&Number.isFinite(t.shadowOffsetX)?t.shadowOffsetX:Pe.shadowOffsetX,o=typeof t?.shadowOffsetY=="number"&&Number.isFinite(t.shadowOffsetY)?t.shadowOffsetY:Pe.shadowOffsetY;return{color:t?.color||Pe.color,width:n,lineDash:e.length?e:tt,lineJoin:t?.lineJoin||Pe.lineJoin,lineCap:t?.lineCap||Pe.lineCap,shadowColor:t?.shadowColor||Pe.shadowColor,shadowBlur:r,shadowOffsetX:i,shadowOffsetY:o}}function Ne(t,e){return e?Ut({color:e.color??t.color,width:e.width??t.width,lineDash:e.lineDash??t.lineDash,lineJoin:e.lineJoin??t.lineJoin,lineCap:e.lineCap??t.lineCap,shadowColor:e.shadowColor??t.shadowColor,shadowBlur:e.shadowBlur??t.shadowBlur,shadowOffsetX:e.shadowOffsetX??t.shadowOffsetX,shadowOffsetY:e.shadowOffsetY??t.shadowOffsetY}):t}function Tt(t,e){return t==null||e===null||e===void 0?!1:String(t)===String(e)}function pn(t){const e=typeof t?.paddingX=="number"&&Number.isFinite(t.paddingX)?Math.max(0,t.paddingX):ge.paddingX,n=typeof t?.paddingY=="number"&&Number.isFinite(t.paddingY)?Math.max(0,t.paddingY):ge.paddingY,r=typeof t?.fontSize=="number"&&Number.isFinite(t.fontSize)?Math.max(8,t.fontSize):ge.fontSize,i=typeof t?.borderWidth=="number"&&Number.isFinite(t.borderWidth)?Math.max(0,t.borderWidth):ge.borderWidth,o=typeof t?.offsetY=="number"&&Number.isFinite(t.offsetY)?t.offsetY:ge.offsetY,s=typeof t?.borderRadius=="number"&&Number.isFinite(t.borderRadius)?Math.max(0,t.borderRadius):ge.borderRadius;return{fontFamily:t?.fontFamily||ge.fontFamily,fontSize:r,fontWeight:t?.fontWeight||ge.fontWeight,textColor:t?.textColor||ge.textColor,backgroundColor:t?.backgroundColor||ge.backgroundColor,borderColor:t?.borderColor||ge.borderColor,borderWidth:i,paddingX:e,paddingY:n,offsetY:o,borderRadius:s}}function bn(t,e,n,r,i,o){const s=Math.max(0,Math.min(o,r*.5,i*.5));t.beginPath(),t.moveTo(e+s,n),t.lineTo(e+r-s,n),t.quadraticCurveTo(e+r,n,e+r,n+s),t.lineTo(e+r,n+i-s),t.quadraticCurveTo(e+r,n+i,e+r-s,n+i),t.lineTo(e+s,n+i),t.quadraticCurveTo(e,n+i,e,n+i-s),t.lineTo(e,n+s),t.quadraticCurveTo(e,n,e+s,n),t.closePath()}function wn(t){if(!t.length)return null;let e=1/0;for(const i of t)i[1]<e&&(e=i[1]);if(!Number.isFinite(e))return null;let n=1/0,r=-1/0;for(const i of t)Math.abs(i[1]-e)>.5||(i[0]<n&&(n=i[0]),i[0]>r&&(r=i[0]));return!Number.isFinite(n)||!Number.isFinite(r)?null:[(n+r)*.5,e]}function yn(t,e,n,r,i,o){const s=e.trim();if(!s)return;t.save(),t.font=`${o.fontWeight} ${o.fontSize}px ${o.fontFamily}`,t.textAlign="center",t.textBaseline="middle";const l=t.measureText(s).width+o.paddingX*2,u=o.fontSize+o.paddingY*2,h=qe(n[0],l*.5+1,r-l*.5-1),b=qe(n[1]-o.offsetY,u*.5+1,i-u*.5-1),m=h-l*.5,p=b-u*.5;t.fillStyle=o.backgroundColor,t.strokeStyle=o.borderColor,t.lineWidth=o.borderWidth,bn(t,m,p,l,u,o.borderRadius),t.fill(),o.borderWidth>0&&t.stroke(),t.fillStyle=o.textColor,t.fillText(s,h,b+.5),t.restore()}function Ke(t,e,n){return[qe(t[0],0,e),qe(t[1],0,n)]}function Je(t){if(!Array.isArray(t)||t.length<2)return null;const e=Number(t[0]),n=Number(t[1]);return!Number.isFinite(e)||!Number.isFinite(n)?null:[e,n]}function Dt({tool:t,imageWidth:e,imageHeight:n,imageMpp:r,imageZoom:i,stampOptions:o,projectorRef:s,onDrawComplete:a,enabled:l,viewStateSignal:u,persistedRegions:h,persistedPolygons:b,regionStrokeStyle:m,regionStrokeHoverStyle:p,regionStrokeActiveStyle:x,resolveRegionStrokeStyle:w,overlayShapes:T,hoveredRegionId:S=null,activeRegionId:F=null,regionLabelStyle:I,invalidateRef:L,className:pe,style:ae}){const z=f.useRef(null),be=f.useRef(!1),ue=f.useRef(t),Q=f.useRef({isDrawing:!1,pointerId:null,start:null,current:null,points:[],stampCenter:null}),$=l??t!=="cursor",X=f.useMemo(()=>h&&h.length>0?h:!b||b.length===0?ln:b.map((c,g)=>({id:g,coordinates:c})),[h,b]),j=f.useMemo(()=>Ut(m),[m]),Te=f.useMemo(()=>Ne(j,p),[j,p]),we=f.useMemo(()=>Ne(j,x),[j,x]),oe=f.useMemo(()=>pn(I),[I]),ye=f.useMemo(()=>dn(o),[o]),P=f.useMemo(()=>({position:"absolute",inset:0,zIndex:2,width:"100%",height:"100%",display:"block",touchAction:"none",pointerEvents:$?"auto":"none",cursor:$?"crosshair":"default",...ae}),[$,ae]),R=f.useCallback(()=>{const c=z.current;if(!c)return;const g=c.getBoundingClientRect(),M=Math.max(1,window.devicePixelRatio||1),E=Math.max(1,Math.round(g.width*M)),k=Math.max(1,Math.round(g.height*M));(c.width!==E||c.height!==k)&&(c.width=E,c.height=k)},[]),C=f.useCallback(c=>{const g=s.current;if(!g||c.length===0)return[];const M=new Array(c.length);for(let E=0;E<c.length;E+=1){const k=Je(g.worldToScreen(c[E][0],c[E][1]));if(!k)return[];M[E]=k}return M},[s]),_=f.useCallback(c=>{if(!Number.isFinite(c)||c<=0)return 0;const g=typeof r=="number"&&Number.isFinite(r)&&r>0?r:1,M=typeof i=="number"&&Number.isFinite(i)?i:0,E=s.current?.getViewState?.().zoom,k=typeof E=="number"&&Number.isFinite(E)&&E>0?E:1,v=M+Math.log2(k),B=Math.max(1e-9,ut(g,M,v));return c/B/k},[r,i,s]),V=f.useCallback((c,g)=>{if(!g)return[];let M=0;if(c==="stamp-rectangle-4096px"){const v=ye.rectanglePixelSize*.5;return wt(g,v).map(O=>Ke(O,e,n))}if(c==="stamp-rectangle"||c==="stamp-rectangle-2mm2"?M=c==="stamp-rectangle-2mm2"?_t:ye.rectangleAreaMm2:(c==="stamp-circle"||c==="stamp-circle-2mm2"||c==="stamp-circle-hpf-0.2mm2")&&(M=c==="stamp-circle-hpf-0.2mm2"?fn:c==="stamp-circle-2mm2"?Bt:ye.circleAreaMm2),!Number.isFinite(M)||M<=0)return[];const E=mn(M);let k=[];if(c==="stamp-rectangle"||c==="stamp-rectangle-2mm2"){const v=_(Math.sqrt(E)*.5);k=wt(g,v)}else if(c==="stamp-circle"||c==="stamp-circle-2mm2"||c==="stamp-circle-hpf-0.2mm2"){const v=_(Math.sqrt(E/Math.PI));k=gn(g,v)}return k.length?k.map(v=>Ke(v,e,n)):[]},[_,e,n,ye]),te=f.useCallback(()=>{const c=Q.current;return ke(t)?V(t,c.stampCenter):c.isDrawing?t==="freehand"?c.points:t==="rectangle"?nt(c.start,c.current):t==="circular"?rt(c.start,c.current):[]:[]},[t,V]),ne=f.useCallback(()=>{R();const c=z.current;if(!c)return;const g=c.getContext("2d");if(!g)return;const M=Math.max(1,window.devicePixelRatio||1),E=c.width/M,k=c.height/M;if(g.setTransform(1,0,0,1,0,0),g.clearRect(0,0,c.width,c.height),g.setTransform(M,0,0,M,0,0),X.length>0)for(let v=0;v<X.length;v+=1){const B=X[v],O=B?.coordinates;if(!O||O.length<3)continue;const J=xe(O),le=C(J);if(le.length>=4){const Re=B.id??v,Z=Tt(F,Re)?"active":Tt(S,Re)?"hover":"default";let me=Z==="active"?we:Z==="hover"?Te:j;if(w){const Se=w({region:B,regionId:Re,regionIndex:v,state:Z});me=Ne(me,Se||void 0)}_e(g,le,me,!0,!1)}}if(Array.isArray(T)&&T.length>0)for(let v=0;v<T.length;v+=1){const B=T[v];if(!B?.coordinates?.length)continue;const O=B.closed??!1,J=O?xe(B.coordinates):B.coordinates,le=C(J);if(le.length<2)continue;const Re=Ne(j,B.strokeStyle);_e(g,le,Re,O,B.fill??!1)}if($){const v=te();if(v.length>0)if(t==="freehand"){const B=C(v);B.length>=2&&_e(g,B,j,!1,!1),B.length>=3&&_e(g,C(xe(v)),j,!0,!0)}else{const B=C(v);B.length>=4&&_e(g,B,j,!0,!0)}}if(X.length>0)for(const v of X){if(!v.label)continue;const B=v?.coordinates;if(!B||B.length<3)continue;const O=xe(B),J=wn(O);if(!J)continue;const le=Je(s.current?.worldToScreen(J[0],J[1])??[]);le&&yn(g,v.label,le,E,k,oe)}},[$,t,te,R,C,s,X,T,S,F,j,Te,we,w,oe]),A=f.useCallback(()=>{be.current||(be.current=!0,requestAnimationFrame(()=>{be.current=!1,ne()}))},[ne]),W=f.useCallback(()=>{const c=Q.current,g=z.current;if(g&&c.pointerId!==null&&g.hasPointerCapture(c.pointerId))try{g.releasePointerCapture(c.pointerId)}catch{}c.isDrawing=!1,c.pointerId=null,c.start=null,c.current=null,c.points=[],c.stampCenter=null},[]),re=f.useCallback(c=>{const g=s.current;if(!g||e<=0||n<=0)return null;const M=Je(g.screenToWorld(c.clientX,c.clientY));return M?Ke(M,e,n):null},[s,e,n]),ce=f.useCallback(()=>{const c=Q.current;if(!c.isDrawing){W(),A();return}let g=[];t==="freehand"?c.points.length>=an&&(g=xe(c.points)):t==="rectangle"?g=nt(c.start,c.current):t==="circular"&&(g=rt(c.start,c.current)),(t==="freehand"||t==="rectangle"||t==="circular")&&xt(g)&&a&&a({tool:t,coordinates:g,bbox:yt(g),areaPx:it(g)}),W(),A()},[t,a,W,A]),Y=f.useCallback((c,g)=>{const M=V(c,g);!xt(M)||!a||a({tool:c,coordinates:M,bbox:yt(M),areaPx:it(M)})},[V,a]),H=f.useCallback(c=>{if(!$||t==="cursor"||c.button!==0)return;const g=re(c);if(!g)return;if(c.preventDefault(),c.stopPropagation(),ke(t)){const k=Q.current;k.stampCenter=g,Y(t,g),A();return}const M=z.current;M&&M.setPointerCapture(c.pointerId);const E=Q.current;E.isDrawing=!0,E.pointerId=c.pointerId,E.start=g,E.current=g,E.points=t==="freehand"?[g]:[],A()},[$,t,re,Y,A]),ee=f.useCallback(c=>{if(!$||t==="cursor")return;const g=re(c);if(!g)return;if(ke(t)){const E=Q.current;E.stampCenter=g,c.preventDefault(),c.stopPropagation(),A();return}const M=Q.current;if(!(!M.isDrawing||M.pointerId!==c.pointerId)){if(c.preventDefault(),c.stopPropagation(),t==="freehand"){const E=s.current,k=Math.max(1e-6,E?.getViewState?.().zoom??1),v=un/k,B=v*v,O=M.points[M.points.length-1];if(!O)M.points.push(g);else{const J=g[0]-O[0],le=g[1]-O[1];J*J+le*le>=B&&M.points.push(g)}}else M.current=g;A()}},[$,t,re,A,s]),G=f.useCallback(c=>{const g=Q.current;if(!g.isDrawing||g.pointerId!==c.pointerId)return;c.preventDefault(),c.stopPropagation();const M=z.current;if(M&&M.hasPointerCapture(c.pointerId))try{M.releasePointerCapture(c.pointerId)}catch{}ce()},[ce]),K=f.useCallback(()=>{if(!ke(t))return;const c=Q.current;c.stampCenter&&(c.stampCenter=null,A())},[t,A]);return f.useEffect(()=>{R(),A();const c=z.current;if(!c)return;const g=new ResizeObserver(()=>{R(),A()});return g.observe(c),()=>{g.disconnect()}},[R,A]),f.useEffect(()=>{$||W(),A()},[$,A,W]),f.useEffect(()=>{ue.current!==t&&(ue.current=t,W(),A())},[t,W,A]),f.useEffect(()=>{A()},[u,X,T,A]),f.useEffect(()=>{if(L)return L.current=A,()=>{L.current===A&&(L.current=null)}},[L,A]),f.useEffect(()=>{if(!$)return;const c=g=>{g.key==="Escape"&&(W(),A())};return window.addEventListener("keydown",c),()=>{window.removeEventListener("keydown",c)}},[$,W,A]),de.jsx("canvas",{ref:z,className:pe,style:P,onPointerDown:H,onPointerMove:ee,onPointerUp:G,onPointerCancel:G,onPointerLeave:K,onContextMenu:c=>{$&&c.preventDefault()},onWheel:c=>{$&&c.preventDefault()}})}function vt(t){return String(t??"").replace(/\/+$/,"")}function Ft(t){const e=String(t??"");return e.startsWith("/")?e:`/${e}`}function xn(t){const e=vt(t);if(!e)return"";if(/\/TileGroup\d+$/i.test(e))return e;let n=null;try{n=new URL(e)}catch{n=null}if(n){const r=`${n.protocol}//${n.host}`,i=vt(n.pathname||"");return/\/ims$/i.test(i)?`${r}${i}`:/\/tiles$/i.test(i)?`${r}${i}`:`${r}${i}/tiles`}return/\/ims$/i.test(e)?"/ims":/\/tiles$/i.test(e)?`${e}`:`${e}/tiles`}function Tn(t,e){const n=t?.imsInfo||{},r=!!t?.imsInfo,i=Number(n.width??t?.width??0),o=Number(n.height??t?.height??0),s=Number(n.tileSize??t?.tileSize??0),a=Number(n.zoom??t?.zoom??0),l=String(n.path??t?.path??""),u=Number(n.mpp??t?.mpp??0);if(!i||!o||!s||!l)throw new Error("이미지 메타데이터가 불완전합니다. width/height/tileSize/path 확인 필요");const h=Array.isArray(t?.terms)?t.terms.map(x=>({termId:String(x?.termId??""),termName:String(x?.termName??""),termColor:String(x?.termColor??"")})):[],b=Ft(l),m=xn(e),p=r?(x,w,T)=>`${m}${b}/${x}/${T}_${w}.webp`:void 0;return{id:t?._id||"unknown",name:t?.name||"unknown",width:i,height:o,mpp:Number.isFinite(u)&&u>0?u:void 0,tileSize:s,maxTierZoom:Number.isFinite(a)?Math.max(0,Math.floor(a)):0,tilePath:l,tileBaseUrl:e,terms:h,tileUrlBuilder:p}}function ct(t,e,n,r){if(t.tileUrlBuilder)return t.tileUrlBuilder(e,n,r);const i=Ft(t.tilePath);return`${t.tileBaseUrl}${i}/${e}/${r}_${n}.webp`}const he={width:220,height:140,margin:16,position:"bottom-right",borderRadius:10,borderWidth:1.5,backgroundColor:"rgba(4, 10, 18, 0.88)",borderColor:"rgba(230, 244, 255, 0.35)",viewportStrokeColor:"rgba(255, 106, 61, 0.95)",viewportFillColor:"rgba(255, 106, 61, 0.2)",interactive:!0,showThumbnail:!0,maxThumbnailTiles:16};function Ie(t,e,n=1){return typeof t!="number"||!Number.isFinite(t)?e:Math.max(n,t)}function ze(t){return Array.isArray(t)&&t.length===4&&Number.isFinite(t[0])&&Number.isFinite(t[1])&&Number.isFinite(t[2])&&Number.isFinite(t[3])}function Lt({source:t,projectorRef:e,authToken:n="",options:r,invalidateRef:i,className:o,style:s}){const a=f.useRef(null),l=f.useRef(null),u=f.useRef(null),h=f.useRef({active:!1,pointerId:null}),b=f.useRef(null),m=f.useRef(!1),p=Ie(r?.width,he.width,64),x=Ie(r?.height,he.height,48),w=Ie(r?.margin,he.margin,0),T=Ie(r?.borderRadius,he.borderRadius,0),S=Ie(r?.borderWidth,he.borderWidth,0),F=Math.max(1,Math.round(Ie(r?.maxThumbnailTiles,he.maxThumbnailTiles,1))),I=r?.backgroundColor||he.backgroundColor,L=r?.borderColor||he.borderColor,pe=r?.viewportStrokeColor||he.viewportStrokeColor,ae=r?.viewportFillColor||he.viewportFillColor,z=r?.interactive??he.interactive,be=r?.showThumbnail??he.showThumbnail,ue=r?.position||he.position,Q=f.useMemo(()=>{const P={};return ue==="top-left"||ue==="bottom-left"?P.left=w:P.right=w,ue==="top-left"||ue==="top-right"?P.top=w:P.bottom=w,{position:"absolute",...P,width:p,height:x,borderRadius:T,overflow:"hidden",zIndex:4,pointerEvents:z?"auto":"none",touchAction:"none",boxShadow:"0 10px 22px rgba(0, 0, 0, 0.3)",...s}},[w,ue,p,x,T,z,s]),$=f.useCallback(()=>{const P=a.current;if(!P)return;const R=P.getContext("2d");if(!R)return;const C=p,_=x,V=Math.max(1,window.devicePixelRatio||1),te=Math.max(1,Math.round(C*V)),ne=Math.max(1,Math.round(_*V));(P.width!==te||P.height!==ne)&&(P.width=te,P.height=ne),R.setTransform(1,0,0,1,0,0),R.clearRect(0,0,P.width,P.height),R.setTransform(V,0,0,V,0,0),R.fillStyle=I,R.fillRect(0,0,C,_);const A=l.current;A&&R.drawImage(A,0,0,C,_),R.strokeStyle=L,R.lineWidth=S,R.strokeRect(S*.5,S*.5,C-S,_-S);const W=e.current,re=W?.getViewBounds?.(),ce=W?.getViewCorners?.(),Y=ze(re)?re:ze(u.current)?u.current:null;if(!Y)return;u.current=Y;const H=C/Math.max(1,t.width),ee=_/Math.max(1,t.height),G=Array.isArray(ce)&&ce.length>=4&&ce.every(v=>Array.isArray(v)&&v.length>=2&&Number.isFinite(v[0])&&Number.isFinite(v[1]))?ce:null;if(G){R.beginPath();for(let v=0;v<G.length;v+=1){const B=G[v],O=q(B[0]*H,0,C),J=q(B[1]*ee,0,_);v===0?R.moveTo(O,J):R.lineTo(O,J)}R.closePath(),R.fillStyle=ae,R.fill(),R.strokeStyle=pe,R.lineWidth=1.5,R.stroke();return}const K=q(Y[0]*H,0,C),c=q(Y[1]*ee,0,_),g=q(Y[2]*H,0,C),M=q(Y[3]*ee,0,_),E=Math.max(1,g-K),k=Math.max(1,M-c);R.fillStyle=ae,R.fillRect(K,c,E,k),R.strokeStyle=pe,R.lineWidth=1.5,R.strokeRect(K+.5,c+.5,Math.max(1,E-1),Math.max(1,k-1))},[p,x,I,L,S,e,t.width,t.height,ae,pe]),X=f.useCallback(()=>{m.current||(m.current=!0,b.current=requestAnimationFrame(()=>{m.current=!1,b.current=null,$()}))},[$]),j=f.useCallback((P,R)=>{const C=a.current;if(!C)return null;const _=C.getBoundingClientRect();if(!_.width||!_.height)return null;const V=q((P-_.left)/_.width,0,1),te=q((R-_.top)/_.height,0,1);return[V*t.width,te*t.height]},[t.width,t.height]),Te=f.useCallback((P,R)=>{const C=e.current;if(!C)return;if(C.setViewCenter){C.setViewCenter(P,R),X();return}const _=C.getViewBounds?.(),V=ze(_)?_:ze(u.current)?u.current:null;if(!V)return;const te=Math.max(1e-6,V[2]-V[0]),ne=Math.max(1e-6,V[3]-V[1]);C.setViewState({offsetX:P-te*.5,offsetY:R-ne*.5}),X()},[e,X]),we=f.useCallback(P=>{if(!z||P.button!==0)return;const R=a.current;if(!R)return;const C=j(P.clientX,P.clientY);C&&(P.preventDefault(),P.stopPropagation(),R.setPointerCapture(P.pointerId),h.current={active:!0,pointerId:P.pointerId},Te(C[0],C[1]))},[z,j,Te]),oe=f.useCallback(P=>{const R=h.current;if(!R.active||R.pointerId!==P.pointerId)return;const C=j(P.clientX,P.clientY);C&&(P.preventDefault(),P.stopPropagation(),Te(C[0],C[1]))},[j,Te]),ye=f.useCallback(P=>{const R=h.current;if(!R.active||R.pointerId!==P.pointerId)return;const C=a.current;if(C&&C.hasPointerCapture(P.pointerId))try{C.releasePointerCapture(P.pointerId)}catch{}h.current={active:!1,pointerId:null},X()},[X]);return f.useEffect(()=>{let P=!1;l.current=null,X();const R=0,C=2**(t.maxTierZoom-R),_=Math.ceil(t.width/C),V=Math.ceil(t.height/C),te=Math.max(1,Math.ceil(_/t.tileSize)),ne=Math.max(1,Math.ceil(V/t.tileSize)),A=te*ne;if(!be||A>F)return;const W=document.createElement("canvas");W.width=Math.max(1,Math.round(p)),W.height=Math.max(1,Math.round(x));const re=W.getContext("2d");if(!re)return;re.fillStyle=I,re.fillRect(0,0,W.width,W.height);const ce=[];for(let Y=0;Y<ne;Y+=1)for(let H=0;H<te;H+=1){const ee=H*t.tileSize*C,G=Y*t.tileSize*C,K=Math.min((H+1)*t.tileSize,_)*C,c=Math.min((Y+1)*t.tileSize,V)*C;ce.push({url:ct(t,R,H,Y),bounds:[ee,G,K,c]})}return Promise.allSettled(ce.map(async Y=>{const H=!!n,ee=await fetch(Y.url,{headers:H?{Authorization:n}:void 0});if(!ee.ok)throw new Error(`HTTP ${ee.status}`);const G=await createImageBitmap(await ee.blob());return{tile:Y,bitmap:G}})).then(Y=>{if(P){for(const G of Y)G.status==="fulfilled"&&G.value.bitmap.close();return}const H=W.width/Math.max(1,t.width),ee=W.height/Math.max(1,t.height);for(const G of Y){if(G.status!=="fulfilled")continue;const{tile:{bounds:K},bitmap:c}=G.value,g=K[0]*H,M=K[1]*ee,E=Math.max(1,(K[2]-K[0])*H),k=Math.max(1,(K[3]-K[1])*ee);re.drawImage(c,g,M,E,k),c.close()}l.current=W,X()}),()=>{P=!0}},[t,n,p,x,I,be,F,X]),f.useEffect(()=>{X()},[X]),f.useEffect(()=>{if(i)return i.current=X,()=>{i.current===X&&(i.current=null)}},[i,X]),f.useEffect(()=>()=>{h.current={active:!1,pointerId:null},b.current!==null&&(cancelAnimationFrame(b.current),b.current=null),m.current=!1},[]),de.jsx("canvas",{ref:a,className:o,style:Q,onPointerDown:we,onPointerMove:oe,onPointerUp:ye,onPointerCancel:ye,onContextMenu:P=>{P.preventDefault()},onWheel:P=>{P.preventDefault(),P.stopPropagation()}})}function vn({imageWidth:t,imageHeight:e,tiles:n,viewState:r,className:i,style:o}){const s=f.useRef(null),a=f.useRef(null),l=f.useMemo(()=>({width:"100%",height:"100%",display:"block",...o}),[o]);return f.useEffect(()=>{const u=s.current;if(!u)return;const h=new St({canvas:u,imageWidth:t,imageHeight:e,initialViewState:r});return a.current=h,h.setTiles(n),()=>{h.destroy(),a.current=null}},[t,e]),f.useEffect(()=>{const u=a.current;u&&u.setTiles(n)},[n]),f.useEffect(()=>{const u=a.current;!u||!r||u.setViewState(r)},[r]),de.jsx("canvas",{ref:s,className:i,style:l})}function En(t){if(!Array.isArray(t)||t.length<3)return[];const e=t.map(([i,o])=>[i,o]),n=e[0],r=e[e.length-1];return!n||!r?[]:((n[0]!==r[0]||n[1]!==r[1])&&e.push([n[0],n[1]]),e)}function Pn(t){const e=[];for(const n of t??[]){const r=En(n);if(r.length<4)continue;let i=1/0,o=1/0,s=-1/0,a=-1/0;for(const[l,u]of r)l<i&&(i=l),l>s&&(s=l),u<o&&(o=u),u>a&&(a=u);!Number.isFinite(i)||!Number.isFinite(o)||e.push({ring:r,minX:i,minY:o,maxX:s,maxY:a})}return e}function Rn(t,e,n){let r=!1;for(let i=0,o=n.length-1;i<n.length;o=i,i+=1){const s=n[i][0],a=n[i][1],l=n[o][0],u=n[o][1];a>e!=u>e&&t<(l-s)*(e-a)/(u-a||Number.EPSILON)+s&&(r=!r)}return r}function Mn(t,e,n){for(const r of n)if(!(t<r.minX||t>r.maxX||e<r.minY||e>r.maxY)&&Rn(t,e,r.ring))return!0;return!1}function Ue(t,e){if(!t||!t.count||!t.positions||!t.paletteIndices)return null;const n=Pn(e??[]);if(n.length===0)return{count:0,positions:new Float32Array(0),paletteIndices:new Uint16Array(0)};const r=t.count,i=t.positions,o=t.paletteIndices,s=new Float32Array(r*2),a=new Uint16Array(r);let l=0;for(let u=0;u<r;u+=1){const h=i[u*2],b=i[u*2+1];Mn(h,b,n)&&(s[l*2]=h,s[l*2+1]=b,a[l]=o[u],l+=1)}return{count:l,positions:s.subarray(0,l*2),paletteIndices:a.subarray(0,l)}}let We=null;const Cn=`
|
|
32
|
+
`;class Ct{constructor(e){d(this,"canvas");d(this,"gl");d(this,"camera",new Jt);d(this,"imageWidth");d(this,"imageHeight");d(this,"clearColor");d(this,"program");d(this,"vao");d(this,"quadBuffer");d(this,"uCameraLocation");d(this,"uBoundsLocation");d(this,"uTextureLocation");d(this,"resizeObserver");d(this,"tiles",[]);d(this,"frameId",null);d(this,"loadVersion",0);d(this,"destroyed",!1);d(this,"fitted",!1);d(this,"controlledViewState",!1);this.canvas=e.canvas,this.imageWidth=Math.max(1,e.imageWidth),this.imageHeight=Math.max(1,e.imageHeight),this.clearColor=e.clearColor??[.03,.05,.08,1],this.gl=Kt(this.canvas),this.program=jt(this.gl,Qt,er);const r=this.gl.createVertexArray(),n=this.gl.createBuffer();if(!r||!n)throw new Error("Failed to create WebGL buffers.");this.vao=r,this.quadBuffer=n,this.gl.bindVertexArray(this.vao),this.gl.bindBuffer(this.gl.ARRAY_BUFFER,this.quadBuffer);const i=new Float32Array([0,0,0,0,1,0,1,0,0,1,0,1,1,1,1,1]);this.gl.bufferData(this.gl.ARRAY_BUFFER,i,this.gl.STATIC_DRAW);const o=this.gl.getAttribLocation(this.program,"aUnit"),s=this.gl.getAttribLocation(this.program,"aUv");if(o<0||s<0)throw new Error("Failed to get attribute locations.");const a=4*Float32Array.BYTES_PER_ELEMENT;this.gl.enableVertexAttribArray(o),this.gl.vertexAttribPointer(o,2,this.gl.FLOAT,!1,a,0),this.gl.enableVertexAttribArray(s),this.gl.vertexAttribPointer(s,2,this.gl.FLOAT,!1,a,2*Float32Array.BYTES_PER_ELEMENT),this.gl.bindVertexArray(null),this.gl.bindBuffer(this.gl.ARRAY_BUFFER,null),this.uCameraLocation=Ze(this.gl,this.program,"uCamera"),this.uBoundsLocation=Ze(this.gl,this.program,"uBounds"),this.uTextureLocation=Ze(this.gl,this.program,"uTexture"),e.initialViewState&&(this.controlledViewState=!0,this.camera.setViewState(e.initialViewState)),this.resizeObserver=new ResizeObserver(()=>{this.resize()}),this.resizeObserver.observe(this.canvas),this.resize()}async setTiles(e){if(this.destroyed)return;const r=++this.loadVersion,n=await Promise.all(e.map(async i=>await this.loadTile(i,r)));if(this.destroyed||r!==this.loadVersion){for(const i of n)i&&this.gl.deleteTexture(i.texture);return}this.disposeTiles(this.tiles),this.tiles=n.filter(i=>i!==null),this.requestRender()}setViewState(e){this.controlledViewState=!0,this.camera.setViewState(e),this.requestRender()}getViewState(){return this.camera.getViewState()}destroy(){this.destroyed||(this.destroyed=!0,this.loadVersion+=1,this.frameId!==null&&(cancelAnimationFrame(this.frameId),this.frameId=null),this.resizeObserver.disconnect(),this.disposeTiles(this.tiles),this.tiles=[],this.gl.deleteBuffer(this.quadBuffer),this.gl.deleteVertexArray(this.vao),this.gl.deleteProgram(this.program))}async loadTile(e,r){try{const n=await fetch(e.url);if(!n.ok)throw new Error(`Tile fetch failed: ${n.status} ${n.statusText}`);const i=await n.blob(),o=await createImageBitmap(i);if(this.destroyed||r!==this.loadVersion)return o.close(),null;const s=this.gl.createTexture();if(!s)throw o.close(),new Error("Failed to create tile texture.");return this.gl.bindTexture(this.gl.TEXTURE_2D,s),this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,1),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_WRAP_S,this.gl.CLAMP_TO_EDGE),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_WRAP_T,this.gl.CLAMP_TO_EDGE),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.texImage2D(this.gl.TEXTURE_2D,0,this.gl.RGBA,this.gl.RGBA,this.gl.UNSIGNED_BYTE,o),this.gl.bindTexture(this.gl.TEXTURE_2D,null),o.close(),{id:e.id,bounds:e.bounds,texture:s}}catch(n){return console.error(`[M1TileRenderer] tile load failed: ${e.id}`,n),null}}resize(){if(this.destroyed)return;const e=this.canvas.getBoundingClientRect(),r=Math.max(1,e.width||this.canvas.clientWidth||1),n=Math.max(1,e.height||this.canvas.clientHeight||1),i=Math.max(1,window.devicePixelRatio||1),o=Math.max(1,Math.round(r*i)),s=Math.max(1,Math.round(n*i));(this.canvas.width!==o||this.canvas.height!==s)&&(this.canvas.width=o,this.canvas.height=s),this.camera.setViewport(r,n),this.gl.viewport(0,0,this.canvas.width,this.canvas.height),!this.fitted&&!this.controlledViewState&&(this.fitToImage(),this.fitted=!0),this.requestRender()}fitToImage(){const e=this.camera.getViewportSize(),r=Math.min(e.width/this.imageWidth,e.height/this.imageHeight),n=Number.isFinite(r)&&r>0?r:1,i=e.width/n,o=e.height/n,s=(this.imageWidth-i)*.5,a=(this.imageHeight-o)*.5;this.camera.setViewState({zoom:n,offsetX:s,offsetY:a})}requestRender(){this.frameId!==null||this.destroyed||(this.frameId=requestAnimationFrame(()=>{this.frameId=null,this.render()}))}render(){if(!this.destroyed){this.gl.clearColor(this.clearColor[0],this.clearColor[1],this.clearColor[2],this.clearColor[3]),this.gl.clear(this.gl.COLOR_BUFFER_BIT),this.gl.useProgram(this.program),this.gl.bindVertexArray(this.vao),this.gl.uniformMatrix3fv(this.uCameraLocation,!1,this.camera.getMatrix()),this.gl.uniform1i(this.uTextureLocation,0);for(const e of this.tiles)this.gl.activeTexture(this.gl.TEXTURE0),this.gl.bindTexture(this.gl.TEXTURE_2D,e.texture),this.gl.uniform4f(this.uBoundsLocation,e.bounds[0],e.bounds[1],e.bounds[2],e.bounds[3]),this.gl.drawArrays(this.gl.TRIANGLE_STRIP,0,4);this.gl.bindTexture(this.gl.TEXTURE_2D,null),this.gl.bindVertexArray(null)}}disposeTiles(e){for(const r of e)this.gl.deleteTexture(r.texture)}}const at=[160,160,160,255];function q(t,e,r){return Math.max(e,Math.min(r,t))}function ut(t,e,r){const n=Number(t),i=Number(e),o=Number(r);return!Number.isFinite(n)||n<=0?1:!Number.isFinite(i)||!Number.isFinite(o)?n:Math.pow(2,i-o)*n}function tr(t,e,r){let i=100*ut(t,e,r);if(Number(t)){let o="μm";return i>1e3&&(i/=1e3,o="mm"),`${i.toPrecision(3)} ${o}`}return`${Math.round(i*1e3)/1e3} pixels`}function rr(t,e){return!t&&!e?!0:!t||!e?!1:Math.abs((t.zoom??0)-(e.zoom??0))<1e-6&&Math.abs((t.offsetX??0)-(e.offsetX??0))<1e-6&&Math.abs((t.offsetY??0)-(e.offsetY??0))<1e-6&&Math.abs((t.rotationDeg??0)-(e.rotationDeg??0))<1e-6}function nr(t){const e=String(t??"").trim();if(!e)return"";if(/^bearer\s+/i.test(e)){const r=e.replace(/^bearer\s+/i,"").trim();return r?`Bearer ${r}`:""}return`Bearer ${e}`}function At(t){const r=String(t??"").trim().match(/^#?([0-9a-fA-F]{6})$/);if(!r)return[...at];const n=Number.parseInt(r[1],16);return[n>>16&255,n>>8&255,n&255,255]}function ir(t){const e=[[...at]],r=new Map;for(const i of t??[]){const o=String(i?.termId??"");!o||r.has(o)||(r.set(o,e.length),e.push(At(i?.termColor)))}const n=new Uint8Array(e.length*4);for(let i=0;i<e.length;i+=1)n[i*4]=e[i][0],n[i*4+1]=e[i][1],n[i*4+2]=e[i][2],n[i*4+3]=e[i][3];return{colors:n,termToPaletteIndex:r}}function pt(t,e,r){const n=t.createShader(t.VERTEX_SHADER),i=t.createShader(t.FRAGMENT_SHADER);if(!n||!i)throw new Error("Shader allocation failed");if(t.shaderSource(n,e),t.compileShader(n),!t.getShaderParameter(n,t.COMPILE_STATUS))throw new Error(t.getShaderInfoLog(n)||"vertex compile failed");if(t.shaderSource(i,r),t.compileShader(i),!t.getShaderParameter(i,t.COMPILE_STATUS))throw new Error(t.getShaderInfoLog(i)||"fragment compile failed");const o=t.createProgram();if(!o)throw new Error("Program allocation failed");if(t.attachShader(o,n),t.attachShader(o,i),t.linkProgram(o),t.deleteShader(n),t.deleteShader(i),!t.getProgramParameter(o,t.LINK_STATUS))throw new Error(t.getProgramInfoLog(o)||"program link failed");return o}const or="rgba(255, 77, 79, 0.16)",sr=3,ar=2,It=96,ur=1,cr=[],tt=[],bt=1e3,_t=2,Bt=2,lr=4096,hr=.2,Re={color:"#ff4d4f",width:2,lineJoin:"round",lineCap:"round",shadowColor:"rgba(0, 0, 0, 0)",shadowBlur:0,shadowOffsetX:0,shadowOffsetY:0},ge={fontFamily:"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace",fontSize:12,fontWeight:500,textColor:"#ffffff",backgroundColor:"rgba(8, 14, 22, 0.88)",borderColor:"rgba(255, 77, 79, 0.85)",borderWidth:1,paddingX:6,paddingY:4,offsetY:10,borderRadius:3};function qe(t,e,r){return Math.max(e,Math.min(r,t))}function ke(t){return t==="stamp-rectangle"||t==="stamp-circle"||t==="stamp-rectangle-4096px"||t==="stamp-rectangle-2mm2"||t==="stamp-circle-2mm2"||t==="stamp-circle-hpf-0.2mm2"}function je(t,e){return typeof t!="number"||!Number.isFinite(t)||t<=0?e:t}function fr(t){return{rectangleAreaMm2:je(t?.rectangleAreaMm2,_t),circleAreaMm2:je(t?.circleAreaMm2,Bt),rectanglePixelSize:je(t?.rectanglePixelSize,lr)}}function dr(t){return t*bt*bt}function wt(t,e){return!t||!Number.isFinite(e)||e<=0?[]:xe([[t[0]-e,t[1]-e],[t[0]+e,t[1]-e],[t[0]+e,t[1]+e],[t[0]-e,t[1]+e]])}function mr(t,e,r=It){if(!t||!Number.isFinite(e)||e<=0)return[];const n=[];for(let i=0;i<=r;i+=1){const o=i/r*Math.PI*2;n.push([t[0]+Math.cos(o)*e,t[1]+Math.sin(o)*e])}return xe(n)}function xe(t){if(!Array.isArray(t)||t.length<3)return[];const e=t.map(([i,o])=>[i,o]),r=e[0],n=e[e.length-1];return!r||!n?[]:((r[0]!==n[0]||r[1]!==n[1])&&e.push([r[0],r[1]]),e)}function rt(t,e){return!t||!e?[]:xe([[t[0],t[1]],[e[0],t[1]],[e[0],e[1]],[t[0],e[1]]])}function nt(t,e,r=It){if(!t||!e)return[];const n=(t[0]+e[0])*.5,i=(t[1]+e[1])*.5,o=Math.hypot(e[0]-t[0],e[1]-t[1])*.5;if(o<1)return[];const s=[];for(let a=0;a<=r;a+=1){const l=a/r*Math.PI*2;s.push([n+Math.cos(l)*o,i+Math.sin(l)*o])}return xe(s)}function it(t){if(!Array.isArray(t)||t.length<4)return 0;let e=0;for(let r=0;r<t.length-1;r+=1){const n=t[r],i=t[r+1];e+=n[0]*i[1]-i[0]*n[1]}return Math.abs(e*.5)}function yt(t){if(!Array.isArray(t)||t.length===0)return[0,0,0,0];let e=1/0,r=1/0,n=-1/0,i=-1/0;for(const[o,s]of t)o<e&&(e=o),o>n&&(n=o),s<r&&(r=s),s>i&&(i=s);return[e,r,n,i]}function xt(t){return Array.isArray(t)&&t.length>=4&&it(t)>ur}function _e(t,e,r,n=!1,i=!1){if(e.length!==0){t.beginPath(),t.moveTo(e[0][0],e[0][1]);for(let o=1;o<e.length;o+=1)t.lineTo(e[o][0],e[o][1]);n&&t.closePath(),i&&n&&(t.fillStyle=or,t.fill()),t.strokeStyle=r.color,t.lineWidth=r.width,t.lineJoin=r.lineJoin,t.lineCap=r.lineCap,t.shadowColor=r.shadowColor,t.shadowBlur=r.shadowBlur,t.shadowOffsetX=r.shadowOffsetX,t.shadowOffsetY=r.shadowOffsetY,t.setLineDash(r.lineDash),t.stroke(),t.setLineDash(tt),t.shadowColor="rgba(0, 0, 0, 0)",t.shadowBlur=0,t.shadowOffsetX=0,t.shadowOffsetY=0}}function Ut(t){const e=Array.isArray(t?.lineDash)?t.lineDash.filter(s=>Number.isFinite(s)&&s>=0):tt,r=typeof t?.width=="number"&&Number.isFinite(t.width)?Math.max(0,t.width):Re.width,n=typeof t?.shadowBlur=="number"&&Number.isFinite(t.shadowBlur)?Math.max(0,t.shadowBlur):Re.shadowBlur,i=typeof t?.shadowOffsetX=="number"&&Number.isFinite(t.shadowOffsetX)?t.shadowOffsetX:Re.shadowOffsetX,o=typeof t?.shadowOffsetY=="number"&&Number.isFinite(t.shadowOffsetY)?t.shadowOffsetY:Re.shadowOffsetY;return{color:t?.color||Re.color,width:r,lineDash:e.length?e:tt,lineJoin:t?.lineJoin||Re.lineJoin,lineCap:t?.lineCap||Re.lineCap,shadowColor:t?.shadowColor||Re.shadowColor,shadowBlur:n,shadowOffsetX:i,shadowOffsetY:o}}function Ne(t,e){return e?Ut({color:e.color??t.color,width:e.width??t.width,lineDash:e.lineDash??t.lineDash,lineJoin:e.lineJoin??t.lineJoin,lineCap:e.lineCap??t.lineCap,shadowColor:e.shadowColor??t.shadowColor,shadowBlur:e.shadowBlur??t.shadowBlur,shadowOffsetX:e.shadowOffsetX??t.shadowOffsetX,shadowOffsetY:e.shadowOffsetY??t.shadowOffsetY}):t}function Tt(t,e){return t==null||e===null||e===void 0?!1:String(t)===String(e)}function gr(t){const e=typeof t?.paddingX=="number"&&Number.isFinite(t.paddingX)?Math.max(0,t.paddingX):ge.paddingX,r=typeof t?.paddingY=="number"&&Number.isFinite(t.paddingY)?Math.max(0,t.paddingY):ge.paddingY,n=typeof t?.fontSize=="number"&&Number.isFinite(t.fontSize)?Math.max(8,t.fontSize):ge.fontSize,i=typeof t?.borderWidth=="number"&&Number.isFinite(t.borderWidth)?Math.max(0,t.borderWidth):ge.borderWidth,o=typeof t?.offsetY=="number"&&Number.isFinite(t.offsetY)?t.offsetY:ge.offsetY,s=typeof t?.borderRadius=="number"&&Number.isFinite(t.borderRadius)?Math.max(0,t.borderRadius):ge.borderRadius;return{fontFamily:t?.fontFamily||ge.fontFamily,fontSize:n,fontWeight:t?.fontWeight||ge.fontWeight,textColor:t?.textColor||ge.textColor,backgroundColor:t?.backgroundColor||ge.backgroundColor,borderColor:t?.borderColor||ge.borderColor,borderWidth:i,paddingX:e,paddingY:r,offsetY:o,borderRadius:s}}function pr(t,e,r,n,i,o){const s=Math.max(0,Math.min(o,n*.5,i*.5));t.beginPath(),t.moveTo(e+s,r),t.lineTo(e+n-s,r),t.quadraticCurveTo(e+n,r,e+n,r+s),t.lineTo(e+n,r+i-s),t.quadraticCurveTo(e+n,r+i,e+n-s,r+i),t.lineTo(e+s,r+i),t.quadraticCurveTo(e,r+i,e,r+i-s),t.lineTo(e,r+s),t.quadraticCurveTo(e,r,e+s,r),t.closePath()}function br(t){if(!t.length)return null;let e=1/0;for(const i of t)i[1]<e&&(e=i[1]);if(!Number.isFinite(e))return null;let r=1/0,n=-1/0;for(const i of t)Math.abs(i[1]-e)>.5||(i[0]<r&&(r=i[0]),i[0]>n&&(n=i[0]));return!Number.isFinite(r)||!Number.isFinite(n)?null:[(r+n)*.5,e]}function wr(t,e,r,n,i,o){const s=e.trim();if(!s)return;t.save(),t.font=`${o.fontWeight} ${o.fontSize}px ${o.fontFamily}`,t.textAlign="center",t.textBaseline="middle";const l=t.measureText(s).width+o.paddingX*2,u=o.fontSize+o.paddingY*2,h=qe(r[0],l*.5+1,n-l*.5-1),b=qe(r[1]-o.offsetY,u*.5+1,i-u*.5-1),m=h-l*.5,p=b-u*.5;t.fillStyle=o.backgroundColor,t.strokeStyle=o.borderColor,t.lineWidth=o.borderWidth,pr(t,m,p,l,u,o.borderRadius),t.fill(),o.borderWidth>0&&t.stroke(),t.fillStyle=o.textColor,t.fillText(s,h,b+.5),t.restore()}function Ke(t,e,r){return[qe(t[0],0,e),qe(t[1],0,r)]}function Je(t){if(!Array.isArray(t)||t.length<2)return null;const e=Number(t[0]),r=Number(t[1]);return!Number.isFinite(e)||!Number.isFinite(r)?null:[e,r]}function Dt({tool:t,imageWidth:e,imageHeight:r,imageMpp:n,imageZoom:i,stampOptions:o,projectorRef:s,onDrawComplete:a,enabled:l,viewStateSignal:u,persistedRegions:h,persistedPolygons:b,regionStrokeStyle:m,regionStrokeHoverStyle:p,regionStrokeActiveStyle:x,resolveRegionStrokeStyle:w,overlayShapes:T,hoveredRegionId:C=null,activeRegionId:F=null,regionLabelStyle:I,invalidateRef:L,className:pe,style:ae}){const z=f.useRef(null),be=f.useRef(!1),ue=f.useRef(t),Q=f.useRef({isDrawing:!1,pointerId:null,start:null,current:null,points:[],stampCenter:null}),$=l??t!=="cursor",X=f.useMemo(()=>h&&h.length>0?h:!b||b.length===0?cr:b.map((c,g)=>({id:g,coordinates:c})),[h,b]),j=f.useMemo(()=>Ut(m),[m]),Te=f.useMemo(()=>Ne(j,p),[j,p]),we=f.useMemo(()=>Ne(j,x),[j,x]),oe=f.useMemo(()=>gr(I),[I]),ye=f.useMemo(()=>fr(o),[o]),R=f.useMemo(()=>({position:"absolute",inset:0,zIndex:2,width:"100%",height:"100%",display:"block",touchAction:"none",pointerEvents:$?"auto":"none",cursor:$?"crosshair":"default",...ae}),[$,ae]),P=f.useCallback(()=>{const c=z.current;if(!c)return;const g=c.getBoundingClientRect(),S=Math.max(1,window.devicePixelRatio||1),E=Math.max(1,Math.round(g.width*S)),k=Math.max(1,Math.round(g.height*S));(c.width!==E||c.height!==k)&&(c.width=E,c.height=k)},[]),M=f.useCallback(c=>{const g=s.current;if(!g||c.length===0)return[];const S=new Array(c.length);for(let E=0;E<c.length;E+=1){const k=Je(g.worldToScreen(c[E][0],c[E][1]));if(!k)return[];S[E]=k}return S},[s]),_=f.useCallback(c=>{if(!Number.isFinite(c)||c<=0)return 0;const g=typeof n=="number"&&Number.isFinite(n)&&n>0?n:1,S=typeof i=="number"&&Number.isFinite(i)?i:0,E=s.current?.getViewState?.().zoom,k=typeof E=="number"&&Number.isFinite(E)&&E>0?E:1,v=S+Math.log2(k),B=Math.max(1e-9,ut(g,S,v));return c/B/k},[n,i,s]),V=f.useCallback((c,g)=>{if(!g)return[];let S=0;if(c==="stamp-rectangle-4096px"){const v=ye.rectanglePixelSize*.5;return wt(g,v).map(O=>Ke(O,e,r))}if(c==="stamp-rectangle"||c==="stamp-rectangle-2mm2"?S=c==="stamp-rectangle-2mm2"?_t:ye.rectangleAreaMm2:(c==="stamp-circle"||c==="stamp-circle-2mm2"||c==="stamp-circle-hpf-0.2mm2")&&(S=c==="stamp-circle-hpf-0.2mm2"?hr:c==="stamp-circle-2mm2"?Bt:ye.circleAreaMm2),!Number.isFinite(S)||S<=0)return[];const E=dr(S);let k=[];if(c==="stamp-rectangle"||c==="stamp-rectangle-2mm2"){const v=_(Math.sqrt(E)*.5);k=wt(g,v)}else if(c==="stamp-circle"||c==="stamp-circle-2mm2"||c==="stamp-circle-hpf-0.2mm2"){const v=_(Math.sqrt(E/Math.PI));k=mr(g,v)}return k.length?k.map(v=>Ke(v,e,r)):[]},[_,e,r,ye]),te=f.useCallback(()=>{const c=Q.current;return ke(t)?V(t,c.stampCenter):c.isDrawing?t==="freehand"?c.points:t==="rectangle"?rt(c.start,c.current):t==="circular"?nt(c.start,c.current):[]:[]},[t,V]),re=f.useCallback(()=>{P();const c=z.current;if(!c)return;const g=c.getContext("2d");if(!g)return;const S=Math.max(1,window.devicePixelRatio||1),E=c.width/S,k=c.height/S;if(g.setTransform(1,0,0,1,0,0),g.clearRect(0,0,c.width,c.height),g.setTransform(S,0,0,S,0,0),X.length>0)for(let v=0;v<X.length;v+=1){const B=X[v],O=B?.coordinates;if(!O||O.length<3)continue;const J=xe(O),le=M(J);if(le.length>=4){const Pe=B.id??v,Z=Tt(F,Pe)?"active":Tt(C,Pe)?"hover":"default";let me=Z==="active"?we:Z==="hover"?Te:j;if(w){const Ce=w({region:B,regionId:Pe,regionIndex:v,state:Z});me=Ne(me,Ce||void 0)}_e(g,le,me,!0,!1)}}if(Array.isArray(T)&&T.length>0)for(let v=0;v<T.length;v+=1){const B=T[v];if(!B?.coordinates?.length)continue;const O=B.closed??!1,J=O?xe(B.coordinates):B.coordinates,le=M(J);if(le.length<2)continue;const Pe=Ne(j,B.strokeStyle);_e(g,le,Pe,O,B.fill??!1)}if($){const v=te();if(v.length>0)if(t==="freehand"){const B=M(v);B.length>=2&&_e(g,B,j,!1,!1),B.length>=3&&_e(g,M(xe(v)),j,!0,!0)}else{const B=M(v);B.length>=4&&_e(g,B,j,!0,!0)}}if(X.length>0)for(const v of X){if(!v.label)continue;const B=v?.coordinates;if(!B||B.length<3)continue;const O=xe(B),J=br(O);if(!J)continue;const le=Je(s.current?.worldToScreen(J[0],J[1])??[]);le&&wr(g,v.label,le,E,k,oe)}},[$,t,te,P,M,s,X,T,C,F,j,Te,we,w,oe]),A=f.useCallback(()=>{be.current||(be.current=!0,requestAnimationFrame(()=>{be.current=!1,re()}))},[re]),W=f.useCallback(()=>{const c=Q.current,g=z.current;if(g&&c.pointerId!==null&&g.hasPointerCapture(c.pointerId))try{g.releasePointerCapture(c.pointerId)}catch{}c.isDrawing=!1,c.pointerId=null,c.start=null,c.current=null,c.points=[],c.stampCenter=null},[]),ne=f.useCallback(c=>{const g=s.current;if(!g||e<=0||r<=0)return null;const S=Je(g.screenToWorld(c.clientX,c.clientY));return S?Ke(S,e,r):null},[s,e,r]),ce=f.useCallback(()=>{const c=Q.current;if(!c.isDrawing){W(),A();return}let g=[];t==="freehand"?c.points.length>=sr&&(g=xe(c.points)):t==="rectangle"?g=rt(c.start,c.current):t==="circular"&&(g=nt(c.start,c.current)),(t==="freehand"||t==="rectangle"||t==="circular")&&xt(g)&&a&&a({tool:t,coordinates:g,bbox:yt(g),areaPx:it(g)}),W(),A()},[t,a,W,A]),Y=f.useCallback((c,g)=>{const S=V(c,g);!xt(S)||!a||a({tool:c,coordinates:S,bbox:yt(S),areaPx:it(S)})},[V,a]),H=f.useCallback(c=>{if(!$||t==="cursor"||c.button!==0)return;const g=ne(c);if(!g)return;if(c.preventDefault(),c.stopPropagation(),ke(t)){const k=Q.current;k.stampCenter=g,Y(t,g),A();return}const S=z.current;S&&S.setPointerCapture(c.pointerId);const E=Q.current;E.isDrawing=!0,E.pointerId=c.pointerId,E.start=g,E.current=g,E.points=t==="freehand"?[g]:[],A()},[$,t,ne,Y,A]),ee=f.useCallback(c=>{if(!$||t==="cursor")return;const g=ne(c);if(!g)return;if(ke(t)){const E=Q.current;E.stampCenter=g,c.preventDefault(),c.stopPropagation(),A();return}const S=Q.current;if(!(!S.isDrawing||S.pointerId!==c.pointerId)){if(c.preventDefault(),c.stopPropagation(),t==="freehand"){const E=s.current,k=Math.max(1e-6,E?.getViewState?.().zoom??1),v=ar/k,B=v*v,O=S.points[S.points.length-1];if(!O)S.points.push(g);else{const J=g[0]-O[0],le=g[1]-O[1];J*J+le*le>=B&&S.points.push(g)}}else S.current=g;A()}},[$,t,ne,A,s]),G=f.useCallback(c=>{const g=Q.current;if(!g.isDrawing||g.pointerId!==c.pointerId)return;c.preventDefault(),c.stopPropagation();const S=z.current;if(S&&S.hasPointerCapture(c.pointerId))try{S.releasePointerCapture(c.pointerId)}catch{}ce()},[ce]),K=f.useCallback(()=>{if(!ke(t))return;const c=Q.current;c.stampCenter&&(c.stampCenter=null,A())},[t,A]);return f.useEffect(()=>{P(),A();const c=z.current;if(!c)return;const g=new ResizeObserver(()=>{P(),A()});return g.observe(c),()=>{g.disconnect()}},[P,A]),f.useEffect(()=>{$||W(),A()},[$,A,W]),f.useEffect(()=>{ue.current!==t&&(ue.current=t,W(),A())},[t,W,A]),f.useEffect(()=>{A()},[u,X,T,A]),f.useEffect(()=>{if(L)return L.current=A,()=>{L.current===A&&(L.current=null)}},[L,A]),f.useEffect(()=>{if(!$)return;const c=g=>{g.key==="Escape"&&(W(),A())};return window.addEventListener("keydown",c),()=>{window.removeEventListener("keydown",c)}},[$,W,A]),de.jsx("canvas",{ref:z,className:pe,style:R,onPointerDown:H,onPointerMove:ee,onPointerUp:G,onPointerCancel:G,onPointerLeave:K,onContextMenu:c=>{$&&c.preventDefault()},onWheel:c=>{$&&c.preventDefault()}})}function vt(t){return String(t??"").replace(/\/+$/,"")}function Ft(t){const e=String(t??"");return e.startsWith("/")?e:`/${e}`}function yr(t){const e=vt(t);if(!e)return"";if(/\/TileGroup\d+$/i.test(e))return e;let r=null;try{r=new URL(e)}catch{r=null}if(r){const n=`${r.protocol}//${r.host}`,i=vt(r.pathname||"");return/\/ims$/i.test(i)?`${n}${i}`:/\/tiles$/i.test(i)?`${n}${i}`:`${n}${i}/tiles`}return/\/ims$/i.test(e)?"/ims":/\/tiles$/i.test(e)?`${e}`:`${e}/tiles`}function xr(t,e){const r=t?.imsInfo||{},n=!!t?.imsInfo,i=Number(r.width??t?.width??0),o=Number(r.height??t?.height??0),s=Number(r.tileSize??t?.tileSize??0),a=Number(r.zoom??t?.zoom??0),l=String(r.path??t?.path??""),u=Number(r.mpp??t?.mpp??0);if(!i||!o||!s||!l)throw new Error("이미지 메타데이터가 불완전합니다. width/height/tileSize/path 확인 필요");const h=Array.isArray(t?.terms)?t.terms.map(x=>({termId:String(x?.termId??""),termName:String(x?.termName??""),termColor:String(x?.termColor??"")})):[],b=Ft(l),m=yr(e),p=n?(x,w,T)=>`${m}${b}/${x}/${T}_${w}.webp`:void 0;return{id:t?._id||"unknown",name:t?.name||"unknown",width:i,height:o,mpp:Number.isFinite(u)&&u>0?u:void 0,tileSize:s,maxTierZoom:Number.isFinite(a)?Math.max(0,Math.floor(a)):0,tilePath:l,tileBaseUrl:e,terms:h,tileUrlBuilder:p}}function ct(t,e,r,n){if(t.tileUrlBuilder)return t.tileUrlBuilder(e,r,n);const i=Ft(t.tilePath);return`${t.tileBaseUrl}${i}/${e}/${n}_${r}.webp`}const he={width:220,height:140,margin:16,position:"bottom-right",borderRadius:10,borderWidth:1.5,backgroundColor:"rgba(4, 10, 18, 0.88)",borderColor:"rgba(230, 244, 255, 0.35)",viewportStrokeColor:"rgba(255, 106, 61, 0.95)",viewportFillColor:"rgba(255, 106, 61, 0.2)",interactive:!0,showThumbnail:!0,maxThumbnailTiles:16};function Ie(t,e,r=1){return typeof t!="number"||!Number.isFinite(t)?e:Math.max(r,t)}function ze(t){return Array.isArray(t)&&t.length===4&&Number.isFinite(t[0])&&Number.isFinite(t[1])&&Number.isFinite(t[2])&&Number.isFinite(t[3])}function Lt({source:t,projectorRef:e,authToken:r="",options:n,invalidateRef:i,className:o,style:s}){const a=f.useRef(null),l=f.useRef(null),u=f.useRef(null),h=f.useRef({active:!1,pointerId:null}),b=f.useRef(null),m=f.useRef(!1),p=Ie(n?.width,he.width,64),x=Ie(n?.height,he.height,48),w=Ie(n?.margin,he.margin,0),T=Ie(n?.borderRadius,he.borderRadius,0),C=Ie(n?.borderWidth,he.borderWidth,0),F=Math.max(1,Math.round(Ie(n?.maxThumbnailTiles,he.maxThumbnailTiles,1))),I=n?.backgroundColor||he.backgroundColor,L=n?.borderColor||he.borderColor,pe=n?.viewportStrokeColor||he.viewportStrokeColor,ae=n?.viewportFillColor||he.viewportFillColor,z=n?.interactive??he.interactive,be=n?.showThumbnail??he.showThumbnail,ue=n?.position||he.position,Q=f.useMemo(()=>{const R={};return ue==="top-left"||ue==="bottom-left"?R.left=w:R.right=w,ue==="top-left"||ue==="top-right"?R.top=w:R.bottom=w,{position:"absolute",...R,width:p,height:x,borderRadius:T,overflow:"hidden",zIndex:4,pointerEvents:z?"auto":"none",touchAction:"none",boxShadow:"0 10px 22px rgba(0, 0, 0, 0.3)",...s}},[w,ue,p,x,T,z,s]),$=f.useCallback(()=>{const R=a.current;if(!R)return;const P=R.getContext("2d");if(!P)return;const M=p,_=x,V=Math.max(1,window.devicePixelRatio||1),te=Math.max(1,Math.round(M*V)),re=Math.max(1,Math.round(_*V));(R.width!==te||R.height!==re)&&(R.width=te,R.height=re),P.setTransform(1,0,0,1,0,0),P.clearRect(0,0,R.width,R.height),P.setTransform(V,0,0,V,0,0),P.fillStyle=I,P.fillRect(0,0,M,_);const A=l.current;A&&P.drawImage(A,0,0,M,_),P.strokeStyle=L,P.lineWidth=C,P.strokeRect(C*.5,C*.5,M-C,_-C);const W=e.current,ne=W?.getViewBounds?.(),ce=W?.getViewCorners?.(),Y=ze(ne)?ne:ze(u.current)?u.current:null;if(!Y)return;u.current=Y;const H=M/Math.max(1,t.width),ee=_/Math.max(1,t.height),G=Array.isArray(ce)&&ce.length>=4&&ce.every(v=>Array.isArray(v)&&v.length>=2&&Number.isFinite(v[0])&&Number.isFinite(v[1]))?ce:null;if(G){P.beginPath();for(let v=0;v<G.length;v+=1){const B=G[v],O=q(B[0]*H,0,M),J=q(B[1]*ee,0,_);v===0?P.moveTo(O,J):P.lineTo(O,J)}P.closePath(),P.fillStyle=ae,P.fill(),P.strokeStyle=pe,P.lineWidth=1.5,P.stroke();return}const K=q(Y[0]*H,0,M),c=q(Y[1]*ee,0,_),g=q(Y[2]*H,0,M),S=q(Y[3]*ee,0,_),E=Math.max(1,g-K),k=Math.max(1,S-c);P.fillStyle=ae,P.fillRect(K,c,E,k),P.strokeStyle=pe,P.lineWidth=1.5,P.strokeRect(K+.5,c+.5,Math.max(1,E-1),Math.max(1,k-1))},[p,x,I,L,C,e,t.width,t.height,ae,pe]),X=f.useCallback(()=>{m.current||(m.current=!0,b.current=requestAnimationFrame(()=>{m.current=!1,b.current=null,$()}))},[$]),j=f.useCallback((R,P)=>{const M=a.current;if(!M)return null;const _=M.getBoundingClientRect();if(!_.width||!_.height)return null;const V=q((R-_.left)/_.width,0,1),te=q((P-_.top)/_.height,0,1);return[V*t.width,te*t.height]},[t.width,t.height]),Te=f.useCallback((R,P)=>{const M=e.current;if(!M)return;if(M.setViewCenter){M.setViewCenter(R,P),X();return}const _=M.getViewBounds?.(),V=ze(_)?_:ze(u.current)?u.current:null;if(!V)return;const te=Math.max(1e-6,V[2]-V[0]),re=Math.max(1e-6,V[3]-V[1]);M.setViewState({offsetX:R-te*.5,offsetY:P-re*.5}),X()},[e,X]),we=f.useCallback(R=>{if(!z||R.button!==0)return;const P=a.current;if(!P)return;const M=j(R.clientX,R.clientY);M&&(R.preventDefault(),R.stopPropagation(),P.setPointerCapture(R.pointerId),h.current={active:!0,pointerId:R.pointerId},Te(M[0],M[1]))},[z,j,Te]),oe=f.useCallback(R=>{const P=h.current;if(!P.active||P.pointerId!==R.pointerId)return;const M=j(R.clientX,R.clientY);M&&(R.preventDefault(),R.stopPropagation(),Te(M[0],M[1]))},[j,Te]),ye=f.useCallback(R=>{const P=h.current;if(!P.active||P.pointerId!==R.pointerId)return;const M=a.current;if(M&&M.hasPointerCapture(R.pointerId))try{M.releasePointerCapture(R.pointerId)}catch{}h.current={active:!1,pointerId:null},X()},[X]);return f.useEffect(()=>{let R=!1;l.current=null,X();const P=0,M=2**(t.maxTierZoom-P),_=Math.ceil(t.width/M),V=Math.ceil(t.height/M),te=Math.max(1,Math.ceil(_/t.tileSize)),re=Math.max(1,Math.ceil(V/t.tileSize)),A=te*re;if(!be||A>F)return;const W=document.createElement("canvas");W.width=Math.max(1,Math.round(p)),W.height=Math.max(1,Math.round(x));const ne=W.getContext("2d");if(!ne)return;ne.fillStyle=I,ne.fillRect(0,0,W.width,W.height);const ce=[];for(let Y=0;Y<re;Y+=1)for(let H=0;H<te;H+=1){const ee=H*t.tileSize*M,G=Y*t.tileSize*M,K=Math.min((H+1)*t.tileSize,_)*M,c=Math.min((Y+1)*t.tileSize,V)*M;ce.push({url:ct(t,P,H,Y),bounds:[ee,G,K,c]})}return Promise.allSettled(ce.map(async Y=>{const H=!!r,ee=await fetch(Y.url,{headers:H?{Authorization:r}:void 0});if(!ee.ok)throw new Error(`HTTP ${ee.status}`);const G=await createImageBitmap(await ee.blob());return{tile:Y,bitmap:G}})).then(Y=>{if(R){for(const G of Y)G.status==="fulfilled"&&G.value.bitmap.close();return}const H=W.width/Math.max(1,t.width),ee=W.height/Math.max(1,t.height);for(const G of Y){if(G.status!=="fulfilled")continue;const{tile:{bounds:K},bitmap:c}=G.value,g=K[0]*H,S=K[1]*ee,E=Math.max(1,(K[2]-K[0])*H),k=Math.max(1,(K[3]-K[1])*ee);ne.drawImage(c,g,S,E,k),c.close()}l.current=W,X()}),()=>{R=!0}},[t,r,p,x,I,be,F,X]),f.useEffect(()=>{X()},[X]),f.useEffect(()=>{if(i)return i.current=X,()=>{i.current===X&&(i.current=null)}},[i,X]),f.useEffect(()=>()=>{h.current={active:!1,pointerId:null},b.current!==null&&(cancelAnimationFrame(b.current),b.current=null),m.current=!1},[]),de.jsx("canvas",{ref:a,className:o,style:Q,onPointerDown:we,onPointerMove:oe,onPointerUp:ye,onPointerCancel:ye,onContextMenu:R=>{R.preventDefault()},onWheel:R=>{R.preventDefault(),R.stopPropagation()}})}function Tr({imageWidth:t,imageHeight:e,tiles:r,viewState:n,className:i,style:o}){const s=f.useRef(null),a=f.useRef(null),l=f.useMemo(()=>({width:"100%",height:"100%",display:"block",...o}),[o]);return f.useEffect(()=>{const u=s.current;if(!u)return;const h=new Ct({canvas:u,imageWidth:t,imageHeight:e,initialViewState:n});return a.current=h,h.setTiles(r),()=>{h.destroy(),a.current=null}},[t,e]),f.useEffect(()=>{const u=a.current;u&&u.setTiles(r)},[r]),f.useEffect(()=>{const u=a.current;!u||!n||u.setViewState(n)},[n]),de.jsx("canvas",{ref:s,className:i,style:l})}function vr(t){if(!Array.isArray(t)||t.length<3)return[];const e=t.map(([i,o])=>[i,o]),r=e[0],n=e[e.length-1];return!r||!n?[]:((r[0]!==n[0]||r[1]!==n[1])&&e.push([r[0],r[1]]),e)}function Er(t){const e=[];for(const r of t??[]){const n=vr(r);if(n.length<4)continue;let i=1/0,o=1/0,s=-1/0,a=-1/0;for(const[l,u]of n)l<i&&(i=l),l>s&&(s=l),u<o&&(o=u),u>a&&(a=u);!Number.isFinite(i)||!Number.isFinite(o)||e.push({ring:n,minX:i,minY:o,maxX:s,maxY:a})}return e}function Rr(t,e,r){let n=!1;for(let i=0,o=r.length-1;i<r.length;o=i,i+=1){const s=r[i][0],a=r[i][1],l=r[o][0],u=r[o][1];a>e!=u>e&&t<(l-s)*(e-a)/(u-a||Number.EPSILON)+s&&(n=!n)}return n}function Pr(t,e,r){for(const n of r)if(!(t<n.minX||t>n.maxX||e<n.minY||e>n.maxY)&&Rr(t,e,n.ring))return!0;return!1}function Ue(t,e){if(!t||!t.count||!t.positions||!t.paletteIndices)return null;const r=Er(e??[]);if(r.length===0)return{count:0,positions:new Float32Array(0),paletteIndices:new Uint16Array(0)};const n=t.count,i=t.positions,o=t.paletteIndices,s=new Float32Array(n*2),a=new Uint16Array(n);let l=0;for(let u=0;u<n;u+=1){const h=i[u*2],b=i[u*2+1];Pr(h,b,r)&&(s[l*2]=h,s[l*2+1]=b,a[l]=o[u],l+=1)}return{count:l,positions:s.subarray(0,l*2),paletteIndices:a.subarray(0,l)}}let We=null;const Sr=`
|
|
33
33
|
struct Params {
|
|
34
34
|
pointCount: u32,
|
|
35
35
|
boundsCount: u32,
|
|
@@ -60,7 +60,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
|
|
|
60
60
|
}
|
|
61
61
|
outputMask[i] = inside;
|
|
62
62
|
}
|
|
63
|
-
`;function Sn(){if(typeof navigator>"u")return!1;const t=navigator;return typeof t.gpu=="object"&&t.gpu!==null}function kt(){if(!Sn())return null;const e=navigator.gpu;if(!e||typeof e!="object")return null;const n=e;return typeof n.requestAdapter!="function"?null:n}const Ye=globalThis.GPUShaderStage?.COMPUTE??4,Qe=globalThis.GPUBufferUsage?.STORAGE??128,Xe=globalThis.GPUBufferUsage?.COPY_DST??8,An=globalThis.GPUBufferUsage?.COPY_SRC??4,In=globalThis.GPUBufferUsage?.UNIFORM??64,_n=globalThis.GPUBufferUsage?.MAP_READ??1,Bn=globalThis.GPUMapMode?.READ??1;async function Un(){const t=kt();if(!t)return{supported:!1,features:[]};const e=await t.requestAdapter();return e?{supported:!0,adapterName:e.info?.description??e.info?.vendor??"unknown",features:Array.from(e.features),limits:{maxStorageBufferBindingSize:Number(e.limits.maxStorageBufferBindingSize),maxComputeInvocationsPerWorkgroup:Number(e.limits.maxComputeInvocationsPerWorkgroup),maxComputeWorkgroupSizeX:Number(e.limits.maxComputeWorkgroupSizeX)}}:{supported:!1,features:[]}}async function Dn(){return We||(We=(async()=>{const t=kt();if(!t)return null;const e=await t.requestAdapter();if(!e)return null;const n=await e.requestDevice(),r=n.createBindGroupLayout({entries:[{binding:0,visibility:Ye,buffer:{type:"read-only-storage"}},{binding:1,visibility:Ye,buffer:{type:"read-only-storage"}},{binding:2,visibility:Ye,buffer:{type:"storage"}},{binding:3,visibility:Ye,buffer:{type:"uniform"}}]}),i=n.createComputePipeline({layout:n.createPipelineLayout({bindGroupLayouts:[r]}),compute:{module:n.createShaderModule({code:Cn}),entryPoint:"main"}});return{device:n,pipeline:i,bindGroupLayout:r}})(),We)}function Ve(t,e){return Math.ceil(t/e)*e}async function Nt(t,e,n){const r=await Dn();if(!r)return null;const i=Math.max(0,Math.floor(e)),o=Math.max(0,Math.floor(n.length/4));if(i===0||o===0)return new Uint32Array(0);const s=Math.min(i,Math.floor(t.length/2));if(s===0)return new Uint32Array(0);const a=s*2*Float32Array.BYTES_PER_ELEMENT,l=o*4*Float32Array.BYTES_PER_ELEMENT,u=s*Uint32Array.BYTES_PER_ELEMENT,h=Number(r.device.limits.maxStorageBufferBindingSize);if(a>h||l>h||u>h)return null;const b=r.device.createBuffer({size:Ve(a,4),usage:Qe|Xe}),m=r.device.createBuffer({size:Ve(l,4),usage:Qe|Xe}),p=r.device.createBuffer({size:Ve(u,4),usage:Qe|An}),x=r.device.createBuffer({size:16,usage:In|Xe}),w=r.device.createBuffer({size:Ve(u,4),usage:Xe|_n});r.device.queue.writeBuffer(b,0,t.buffer,t.byteOffset,a),r.device.queue.writeBuffer(m,0,n.buffer,n.byteOffset,l),r.device.queue.writeBuffer(x,0,new Uint32Array([s,o,0,0]));const T=r.device.createBindGroup({layout:r.bindGroupLayout,entries:[{binding:0,resource:{buffer:b}},{binding:1,resource:{buffer:m}},{binding:2,resource:{buffer:p}},{binding:3,resource:{buffer:x}}]}),S=r.device.createCommandEncoder(),F=S.beginComputePass();F.setPipeline(r.pipeline),F.setBindGroup(0,T),F.dispatchWorkgroups(Math.ceil(s/256)),F.end(),S.copyBufferToBuffer(p,0,w,0,u),r.device.queue.submit([S.finish()]),await w.mapAsync(Bn);const I=w.getMappedRange(),L=new Uint32Array(I.slice(0));return w.unmap(),b.destroy(),m.destroy(),p.destroy(),x.destroy(),w.destroy(),L}function ve(){return typeof performance<"u"&&typeof performance.now=="function"?performance.now():Date.now()}function Fn(t){if(!Array.isArray(t)||t.length<3)return[];const e=t.map(([i,o])=>[i,o]),n=e[0],r=e[e.length-1];return!n||!r?[]:((n[0]!==r[0]||n[1]!==r[1])&&e.push([n[0],n[1]]),e)}function Ln(t){const e=[];for(const n of t??[]){const r=Fn(n);if(r.length<4)continue;let i=1/0,o=1/0,s=-1/0,a=-1/0;for(const[l,u]of r)l<i&&(i=l),l>s&&(s=l),u<o&&(o=u),u>a&&(a=u);!Number.isFinite(i)||!Number.isFinite(o)||e.push({ring:r,minX:i,minY:o,maxX:s,maxY:a})}return e}function kn(t,e,n){let r=!1;for(let i=0,o=n.length-1;i<n.length;o=i,i+=1){const s=n[i][0],a=n[i][1],l=n[o][0],u=n[o][1];a>e!=u>e&&t<(l-s)*(e-a)/(u-a||Number.EPSILON)+s&&(r=!r)}return r}function Et(t,e,n){for(const r of n)if(!(t<r.minX||t>r.maxX||e<r.minY||e>r.maxY)&&kn(t,e,r.ring))return!0;return!1}async function zt(t,e,n={}){const r=ve(),i=n.bridgeToDraw===!0;if(!t||!t.count||!t.positions||!t.paletteIndices)return{data:null,meta:{mode:"hybrid-webgpu",durationMs:ve()-r,usedWebGpu:!1,candidateCount:0,bridgedToDraw:!1}};const o=Ln(e??[]);if(o.length===0)return{data:{count:0,positions:new Float32Array(0),paletteIndices:new Uint16Array(0)},meta:{mode:"hybrid-webgpu",durationMs:ve()-r,usedWebGpu:!1,candidateCount:0,bridgedToDraw:!1}};const s=Math.max(0,Math.min(t.count,Math.floor(t.positions.length/2),t.paletteIndices.length));if(s===0)return{data:{count:0,positions:new Float32Array(0),paletteIndices:new Uint16Array(0)},meta:{mode:"hybrid-webgpu",durationMs:ve()-r,usedWebGpu:!1,candidateCount:0,bridgedToDraw:!1}};const a=new Float32Array(o.length*4);for(let w=0;w<o.length;w+=1){const T=w*4,S=o[w];a[T]=S.minX,a[T+1]=S.minY,a[T+2]=S.maxX,a[T+3]=S.maxY}let l=null,u=!1;try{l=await Nt(t.positions,s,a),u=!!l}catch{l=null,u=!1}if(!l)return{data:Ue(t,e),meta:{mode:"hybrid-webgpu",durationMs:ve()-r,usedWebGpu:!1,candidateCount:s,bridgedToDraw:!1}};let h=0;for(let w=0;w<s;w+=1)l[w]===1&&(h+=1);const b=new Uint32Array(h);if(h>0){let w=0;for(let T=0;T<s;T+=1)l[T]===1&&(b[w]=T,w+=1)}if(h===0)return i?{data:{count:s,positions:t.positions.subarray(0,s*2),paletteIndices:t.paletteIndices.subarray(0,s),drawIndices:new Uint32Array(0)},meta:{mode:"hybrid-webgpu",durationMs:ve()-r,usedWebGpu:!0,candidateCount:0,bridgedToDraw:!0}}:{data:{count:0,positions:new Float32Array(0),paletteIndices:new Uint16Array(0)},meta:{mode:"hybrid-webgpu",durationMs:ve()-r,usedWebGpu:!0,candidateCount:0,bridgedToDraw:!1}};if(i){const w=new Uint32Array(h);let T=0;for(let S=0;S<h;S+=1){const F=b[S]??0,I=t.positions[F*2],L=t.positions[F*2+1];Et(I,L,o)&&(w[T]=F,T+=1)}return{data:{count:s,positions:t.positions.subarray(0,s*2),paletteIndices:t.paletteIndices.subarray(0,s),drawIndices:w.subarray(0,T)},meta:{mode:"hybrid-webgpu",durationMs:ve()-r,usedWebGpu:!0,candidateCount:h,bridgedToDraw:!0}}}const m=new Float32Array(h*2),p=new Uint16Array(h);let x=0;for(let w=0;w<h;w+=1){const T=b[w]??0,S=t.positions[T*2],F=t.positions[T*2+1];Et(S,F,o)&&(m[x*2]=S,m[x*2+1]=F,p[x]=t.paletteIndices[T],x+=1)}return{data:{count:x,positions:m.subarray(0,x*2),paletteIndices:p.subarray(0,x)},meta:{mode:"hybrid-webgpu",durationMs:ve()-r,usedWebGpu:!0,candidateCount:h,bridgedToDraw:!1}}}let fe=null,ot=!0,Nn=1;const Ce=new Map;function Ge(){return typeof performance<"u"&&typeof performance.now=="function"?performance.now():Date.now()}function zn(){if(!ot)return null;if(fe)return fe;try{const t=new Worker(new URL("/assets/roi-clip-worker-i1SE1Dpa.js",typeof document>"u"?require("url").pathToFileURL(__filename).href:He&&He.tagName.toUpperCase()==="SCRIPT"&&He.src||new URL("index.cjs",document.baseURI).href),{type:"module"});return t.addEventListener("message",lt),t.addEventListener("error",ht),fe=t,t}catch{return ot=!1,null}}function lt(t){const e=t.data;if(!e)return;const n=Ce.get(e.id);if(!n)return;if(Ce.delete(e.id),e.type==="roi-clip-failure"){n.reject(new Error(e.error||"worker clip failed"));return}const r=Math.max(0,Math.floor(e.count)),i=new Float32Array(e.positions),o=new Uint16Array(e.paletteIndices),s={count:r,positions:i.subarray(0,r*2),paletteIndices:o.subarray(0,r)};n.resolve({data:s,meta:{mode:"worker",durationMs:Number.isFinite(e.durationMs)?e.durationMs:Ge()-n.startMs}})}function ht(){ot=!1,fe&&(fe.removeEventListener("message",lt),fe.removeEventListener("error",ht),fe.terminate(),fe=null);for(const[,t]of Ce)t.reject(new Error("worker crashed"));Ce.clear()}function Wn(){if(fe){fe.removeEventListener("message",lt),fe.removeEventListener("error",ht),fe.terminate(),fe=null;for(const[,t]of Ce)t.reject(new Error("worker terminated"));Ce.clear()}}async function Wt(t,e){if(!t||!t.count||!t.positions||!t.paletteIndices)return{data:null,meta:{mode:"worker",durationMs:0}};const n=zn();if(!n){const l=Ge();return{data:Ue(t,e),meta:{mode:"sync",durationMs:Ge()-l}}}const r=Math.max(0,Math.min(t.count,Math.floor(t.positions.length/2),t.paletteIndices.length)),i=t.positions.slice(0,r*2),o=t.paletteIndices.slice(0,r),s=Nn++,a=Ge();return new Promise((l,u)=>{Ce.set(s,{resolve:l,reject:u,startMs:a});const h={type:"roi-clip-request",id:s,count:r,positions:i.buffer,paletteIndices:o.buffer,polygons:e??[]};n.postMessage(h,[i.buffer,o.buffer])})}function Yn(t){if(!Array.isArray(t)||t.length<3)return[];const e=t.map(i=>[Number(i[0]),Number(i[1])]),n=e[0],r=e[e.length-1];return!n||!r?[]:((n[0]!==r[0]||n[1]!==r[1])&&e.push([n[0],n[1]]),e)}function Xn(t){let e=0;for(let n=0;n<t.length-1;n+=1){const[r,i]=t[n],[o,s]=t[n+1];e+=r*s-o*i}return Math.abs(e*.5)}function Vn(t){const e=[];for(let n=0;n<t.length;n+=1){const r=t[n];if(!r?.coordinates?.length)continue;const i=Yn(r.coordinates);if(i.length<4)continue;let o=1/0,s=1/0,a=-1/0,l=-1/0;for(const[u,h]of i)u<o&&(o=u),u>a&&(a=u),h<s&&(s=h),h>l&&(l=h);!Number.isFinite(o)||!Number.isFinite(s)||!Number.isFinite(a)||!Number.isFinite(l)||e.push({regionId:r.id??n,regionIndex:n,ring:i,minX:o,minY:s,maxX:a,maxY:l,area:Math.max(1e-6,Xn(i))})}return e}function On(t,e,n){let r=!1;for(let i=0,o=n.length-1;i<n.length;o=i,i+=1){const s=n[i][0],a=n[i][1],l=n[o][0],u=n[o][1];a>e!=u>e&&t<(l-s)*(e-a)/(u-a||Number.EPSILON)+s&&(r=!r)}return r}function Gn(t,e){if(Array.isArray(e)){const n=e[t];if(typeof n=="string"&&n.length>0)return n}if(e instanceof Map){const n=e.get(t);if(typeof n=="string"&&n.length>0)return n}return String(t)}function Yt(t,e,n={}){const r=Math.max(0,Math.min(Math.floor(t?.count??0),Math.floor((t?.positions?.length??0)/2),t?.paletteIndices?.length??0));let i=null;if(t?.drawIndices instanceof Uint32Array){const m=t.drawIndices;let p=m.length;for(let x=0;x<m.length;x+=1)m[x]<r||(p-=1);if(p===m.length)i=m;else if(p>0){const x=new Uint32Array(p);let w=0;for(let T=0;T<m.length;T+=1){const S=m[T];S>=r||(x[w]=S,w+=1)}i=x}else i=new Uint32Array(0)}const o=i?i.length:r,s=Vn(e??[]);if(!t||o===0||s.length===0)return{groups:[],inputPointCount:o,pointsInsideAnyRegion:0,unmatchedPointCount:o};const a=new Map,l=new Map;let u=0;for(let m=0;m<o;m+=1){const p=i?i[m]:m,x=t.positions[p*2],w=t.positions[p*2+1];let T=null;for(const I of s)x<I.minX||x>I.maxX||w<I.minY||w>I.maxY||On(x,w,I.ring)&&(!T||I.area<T.area)&&(T=I);if(!T)continue;u+=1;const S=t.paletteIndices[p]??0,F=a.get(T.regionIndex)??new Map;F.set(S,(F.get(S)??0)+1),a.set(T.regionIndex,F),l.set(T.regionIndex,(l.get(T.regionIndex)??0)+1)}const h=n.includeEmptyRegions??!1,b=[];for(const m of s){const p=l.get(m.regionIndex)??0;if(!h&&p<=0)continue;const x=a.get(m.regionIndex)??new Map,w=Array.from(x.entries()).map(([T,S])=>({termId:Gn(T,n.paletteIndexToTermId),paletteIndex:T,count:S})).sort((T,S)=>S.count-T.count||T.paletteIndex-S.paletteIndex);b.push({regionId:m.regionId,regionIndex:m.regionIndex,totalCount:p,termCounts:w})}return{groups:b,inputPointCount:o,pointsInsideAnyRegion:u,unmatchedPointCount:Math.max(0,o-u)}}function Oe(){return typeof performance<"u"&&typeof performance.now=="function"?performance.now():Date.now()}function qn(t,e){if(!e)return!1;try{const r=new URL(t,typeof window<"u"?window.location.href:void 0).hostname.toLowerCase();if(r.includes("amazonaws.com")||r.startsWith("s3.")||r.includes(".s3."))return!1}catch{}return!0}class Xt{constructor(e){d(this,"maxConcurrency");d(this,"maxRetries");d(this,"retryBaseDelayMs");d(this,"retryMaxDelayMs");d(this,"onTileLoad");d(this,"onTileError");d(this,"onStateChange");d(this,"authToken");d(this,"destroyed",!1);d(this,"queue",[]);d(this,"queuedByKey",new Map);d(this,"inflight",new Map);d(this,"visibleKeys",new Set);d(this,"timerId",null);d(this,"abortedCount",0);d(this,"retryCount",0);d(this,"failedCount",0);this.maxConcurrency=Math.max(1,Math.floor(e.maxConcurrency??12)),this.maxRetries=Math.max(0,Math.floor(e.maxRetries??2)),this.retryBaseDelayMs=Math.max(10,Math.floor(e.retryBaseDelayMs??120)),this.retryMaxDelayMs=Math.max(this.retryBaseDelayMs,Math.floor(e.retryMaxDelayMs??1200)),this.authToken=e.authToken??"",this.onTileLoad=e.onTileLoad,this.onTileError=e.onTileError,this.onStateChange=e.onStateChange}setAuthToken(e){this.authToken=String(e??"")}schedule(e){if(this.destroyed)return;const n=new Set;for(const r of e)n.add(r.key);this.visibleKeys=n,this.dropInvisibleQueued(n),this.abortInvisibleInflight(n);for(const r of e){if(this.inflight.has(r.key)){const s=this.inflight.get(r.key);s&&(s.tile=r);continue}const i=this.queuedByKey.get(r.key);if(i){i.tile=r;continue}const o={tile:r,attempt:0,readyAt:Oe()};this.queue.push(o),this.queuedByKey.set(r.key,o)}this.sortQueue(),this.pump(),this.emitStateChange()}clear(){this.clearPumpTimer(),this.visibleKeys.clear(),this.queue=[],this.queuedByKey.clear();for(const[,e]of this.inflight)e.controller.abort();this.inflight.clear(),this.emitStateChange()}destroy(){this.destroyed||(this.destroyed=!0,this.clear())}getInflightCount(){return this.inflight.size}getSnapshot(){return{inflight:this.inflight.size,queued:this.queue.length,aborted:this.abortedCount,retries:this.retryCount,failed:this.failedCount}}dropInvisibleQueued(e){if(this.queue.length===0)return;const n=[];for(const r of this.queue){if(!e.has(r.tile.key)){this.queuedByKey.delete(r.tile.key);continue}n.push(r)}this.queue=n}abortInvisibleInflight(e){for(const[n,r]of this.inflight)e.has(n)||(this.inflight.delete(n),this.abortedCount+=1,r.controller.abort())}sortQueue(){this.queue.sort((e,n)=>e.readyAt!==n.readyAt?e.readyAt-n.readyAt:e.tile.distance2!==n.tile.distance2?e.tile.distance2-n.tile.distance2:e.tile.tier!==n.tile.tier?n.tile.tier-e.tile.tier:e.tile.key.localeCompare(n.tile.key))}pump(){if(this.destroyed)return;for(this.clearPumpTimer();this.inflight.size<this.maxConcurrency;){const r=this.takeNextReadyQueueItem();if(!r)break;this.startFetch(r)}if(this.inflight.size>=this.maxConcurrency||this.queue.length===0)return;const e=this.queue[0]?.readyAt;if(typeof e!="number")return;const n=Math.max(0,e-Oe());this.timerId=window.setTimeout(()=>{this.timerId=null,this.pump()},n)}takeNextReadyQueueItem(){if(this.queue.length===0)return null;const e=Oe(),n=this.queue[0];return!n||n.readyAt>e?null:(this.queue.shift(),this.queuedByKey.delete(n.tile.key),n)}startFetch(e){const n=new AbortController,r={tile:e.tile,attempt:e.attempt,controller:n};this.inflight.set(e.tile.key,r),this.emitStateChange();const i=qn(e.tile.url,this.authToken);fetch(e.tile.url,{signal:n.signal,headers:i?{Authorization:this.authToken}:void 0}).then(o=>{if(!o.ok)throw new Error(`HTTP ${o.status}`);return o.blob()}).then(o=>createImageBitmap(o)).then(o=>{if(this.destroyed||n.signal.aborted){o.close();return}if(!this.visibleKeys.has(e.tile.key)){o.close();return}this.onTileLoad(e.tile,o)}).catch(o=>{if(n.signal.aborted||this.destroyed)return;if(e.attempt<this.maxRetries&&this.visibleKeys.has(e.tile.key)){this.retryCount+=1;const a=e.attempt+1,l=this.getRetryDelay(a),u={tile:e.tile,attempt:a,readyAt:Oe()+l},h=this.queuedByKey.get(e.tile.key);h?(h.tile=u.tile,h.readyAt=Math.min(h.readyAt,u.readyAt),h.attempt=Math.max(h.attempt,u.attempt)):(this.queue.push(u),this.queuedByKey.set(u.tile.key,u)),this.sortQueue();return}this.failedCount+=1,this.onTileError?.(e.tile,o,e.attempt+1)}).finally(()=>{this.inflight.delete(e.tile.key),this.pump(),this.emitStateChange()})}getRetryDelay(e){const n=Math.max(0,e-1),r=Math.min(this.retryMaxDelayMs,this.retryBaseDelayMs*2**n),i=.85+Math.random()*.3;return Math.round(r*i)}clearPumpTimer(){this.timerId!==null&&(window.clearTimeout(this.timerId),this.timerId=null)}emitStateChange(){this.onStateChange?.(this.getSnapshot())}}const Pt=.35;class $n{constructor(){d(this,"viewportWidth",1);d(this,"viewportHeight",1);d(this,"viewState",{zoom:1,offsetX:0,offsetY:0,rotationDeg:0})}setViewport(e,n){this.viewportWidth=Math.max(1,e),this.viewportHeight=Math.max(1,n)}getViewport(){return{width:this.viewportWidth,height:this.viewportHeight}}setViewState(e){typeof e.zoom=="number"&&(this.viewState.zoom=Math.max(1e-4,e.zoom)),typeof e.offsetX=="number"&&(this.viewState.offsetX=e.offsetX),typeof e.offsetY=="number"&&(this.viewState.offsetY=e.offsetY),typeof e.rotationDeg=="number"&&Number.isFinite(e.rotationDeg)&&(this.viewState.rotationDeg=e.rotationDeg)}getViewState(){return{...this.viewState}}getCenter(){const e=Math.max(1e-6,this.viewState.zoom);return[this.viewState.offsetX+this.viewportWidth/(2*e),this.viewState.offsetY+this.viewportHeight/(2*e)]}setCenter(e,n){const r=Math.max(1e-6,this.viewState.zoom);this.viewState.offsetX=e-this.viewportWidth/(2*r),this.viewState.offsetY=n-this.viewportHeight/(2*r)}screenToWorld(e,n){const r=this.viewState,i=Math.max(1e-6,r.zoom),[o,s]=this.getCenter(),a=(e-this.viewportWidth*.5)/i,l=(n-this.viewportHeight*.5)/i,u=Be(r.rotationDeg),h=Math.cos(u),b=Math.sin(u);return[o+a*h-l*b,s+a*b+l*h]}worldToScreen(e,n){const r=this.viewState,i=Math.max(1e-6,r.zoom),[o,s]=this.getCenter(),a=e-o,l=n-s,u=Be(r.rotationDeg),h=Math.cos(u),b=Math.sin(u),m=a*h+l*b,p=-a*b+l*h;return[this.viewportWidth*.5+m*i,this.viewportHeight*.5+p*i]}getViewCorners(){const e=this.viewportWidth,n=this.viewportHeight;return[this.screenToWorld(0,0),this.screenToWorld(e,0),this.screenToWorld(e,n),this.screenToWorld(0,n)]}getMatrix(){const e=Math.max(1e-6,this.viewState.zoom),[n,r]=this.getCenter(),i=Be(this.viewState.rotationDeg),o=Math.cos(i),s=Math.sin(i),a=2*e*o/this.viewportWidth,l=2*e*s/this.viewportWidth,u=2*e*s/this.viewportHeight,h=-2*e*o/this.viewportHeight,b=-(a*n+l*r),m=-(u*n+h*r);return new Float32Array([a,u,0,l,h,0,b,m,1])}}function Be(t){return t*Math.PI/180}function Rt(){return typeof performance<"u"&&typeof performance.now=="function"?performance.now():Date.now()}function Me(t,e,n){const r=t.getUniformLocation(e,n);if(!r)throw new Error(`uniform location lookup failed: ${n}`);return r}function et(t,e){return!t||!e?t===e:t.buffer===e.buffer&&t.byteOffset===e.byteOffset&&t.byteLength===e.byteLength}class Vt{constructor(e,n,r={}){d(this,"canvas");d(this,"source");d(this,"gl");d(this,"camera",new $n);d(this,"onViewStateChange");d(this,"onStats");d(this,"onTileError");d(this,"onContextLost");d(this,"onContextRestored");d(this,"resizeObserver");d(this,"tileProgram");d(this,"pointProgram");d(this,"tileScheduler");d(this,"authToken");d(this,"destroyed",!1);d(this,"contextLost",!1);d(this,"frame",null);d(this,"frameSerial",0);d(this,"dragging",!1);d(this,"interactionMode","none");d(this,"rotateLastAngleRad",null);d(this,"pointerId",null);d(this,"lastPointerX",0);d(this,"lastPointerY",0);d(this,"interactionLocked",!1);d(this,"ctrlDragRotate",!0);d(this,"rotationDragSensitivityDegPerPixel",.35);d(this,"maxCacheTiles");d(this,"fitZoom",1);d(this,"minZoom",1e-6);d(this,"maxZoom",1);d(this,"currentTier",0);d(this,"pointCount",0);d(this,"usePointIndices",!1);d(this,"pointBuffersDirty",!0);d(this,"pointPaletteSize",1);d(this,"lastPointData",null);d(this,"lastPointPalette",null);d(this,"cache",new Map);d(this,"boundPointerDown");d(this,"boundPointerMove");d(this,"boundPointerUp");d(this,"boundWheel");d(this,"boundDoubleClick");d(this,"boundContextMenu");d(this,"boundContextLost");d(this,"boundContextRestored");this.canvas=e,this.source=n,this.onViewStateChange=r.onViewStateChange,this.onStats=r.onStats,this.onTileError=r.onTileError,this.onContextLost=r.onContextLost,this.onContextRestored=r.onContextRestored,this.authToken=r.authToken??"",this.maxCacheTiles=Math.max(32,Math.floor(r.maxCacheTiles??320)),this.ctrlDragRotate=r.ctrlDragRotate??!0,this.rotationDragSensitivityDegPerPixel=typeof r.rotationDragSensitivityDegPerPixel=="number"&&Number.isFinite(r.rotationDragSensitivityDegPerPixel)?Math.max(0,r.rotationDragSensitivityDegPerPixel):Pt;const i=e.getContext("webgl2",{alpha:!1,antialias:!1,depth:!1,stencil:!1,powerPreference:"high-performance"});if(!i)throw new Error("WebGL2 not supported");this.gl=i,this.tileProgram=this.initTileProgram(),this.pointProgram=this.initPointProgram(),this.tileScheduler=new Xt({authToken:this.authToken,maxConcurrency:r.tileScheduler?.maxConcurrency??12,maxRetries:r.tileScheduler?.maxRetries??2,retryBaseDelayMs:r.tileScheduler?.retryBaseDelayMs??120,retryMaxDelayMs:r.tileScheduler?.retryMaxDelayMs??1200,onTileLoad:(o,s)=>this.handleTileLoaded(o,s),onTileError:(o,s,a)=>{this.onTileError?.({tile:o,error:s,attemptCount:a}),console.warn("tile load failed",o.url,s)}}),this.resizeObserver=new ResizeObserver(()=>this.resize()),this.resizeObserver.observe(e),this.boundPointerDown=o=>this.onPointerDown(o),this.boundPointerMove=o=>this.onPointerMove(o),this.boundPointerUp=o=>this.onPointerUp(o),this.boundWheel=o=>this.onWheel(o),this.boundDoubleClick=o=>this.onDoubleClick(o),this.boundContextMenu=o=>this.onContextMenu(o),this.boundContextLost=o=>this.onWebGlContextLost(o),this.boundContextRestored=o=>this.onWebGlContextRestored(o),e.addEventListener("pointerdown",this.boundPointerDown),e.addEventListener("pointermove",this.boundPointerMove),e.addEventListener("pointerup",this.boundPointerUp),e.addEventListener("pointercancel",this.boundPointerUp),e.addEventListener("wheel",this.boundWheel,{passive:!1}),e.addEventListener("dblclick",this.boundDoubleClick),e.addEventListener("contextmenu",this.boundContextMenu),e.addEventListener("webglcontextlost",this.boundContextLost),e.addEventListener("webglcontextrestored",this.boundContextRestored),this.fitToImage(),this.resize()}setAuthToken(e){this.authToken=String(e??""),this.tileScheduler.setAuthToken(this.authToken)}setViewState(e){const n={...e};typeof n.zoom=="number"&&(n.zoom=q(n.zoom,this.minZoom,this.maxZoom)),this.camera.setViewState(n),this.clampViewState(),this.emitViewState(),this.requestRender()}getViewState(){return this.camera.getViewState()}setPointPalette(e){if(!e||e.length===0){this.lastPointPalette=null;return}if(this.lastPointPalette=new Uint8Array(e),this.contextLost||this.gl.isContextLost())return;const n=this.gl,r=Math.max(1,Math.floor(this.lastPointPalette.length/4));this.pointPaletteSize=r,n.bindTexture(n.TEXTURE_2D,this.pointProgram.paletteTexture),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,r,1,0,n.RGBA,n.UNSIGNED_BYTE,this.lastPointPalette),n.bindTexture(n.TEXTURE_2D,null),this.requestRender()}setPointData(e){if(!e||!e.count||!e.positions||!e.paletteIndices){this.lastPointData=null,this.pointCount=0,this.usePointIndices=!1,this.requestRender();return}const n=Math.max(0,Math.min(e.count,Math.floor(e.positions.length/2),e.paletteIndices.length)),r=e.positions.subarray(0,n*2),i=e.paletteIndices.subarray(0,n),o=e.drawIndices instanceof Uint32Array,s=o?this.sanitizeDrawIndices(e.drawIndices,n):null,a=this.lastPointData;let l=this.pointBuffersDirty||!a||a.count!==n||!et(a.positions,r)||!et(a.paletteIndices,i),u=this.pointBuffersDirty||o&&(!a?.drawIndices||!et(a.drawIndices,s))||!o&&!!a?.drawIndices;if(this.lastPointData={count:n,positions:r,paletteIndices:i,drawIndices:o?s??void 0:void 0},this.contextLost||this.gl.isContextLost())return;const h=this.gl;l&&(h.bindBuffer(h.ARRAY_BUFFER,this.pointProgram.posBuffer),h.bufferData(h.ARRAY_BUFFER,this.lastPointData.positions,h.STATIC_DRAW),h.bindBuffer(h.ARRAY_BUFFER,this.pointProgram.termBuffer),h.bufferData(h.ARRAY_BUFFER,this.lastPointData.paletteIndices,h.STATIC_DRAW),h.bindBuffer(h.ARRAY_BUFFER,null)),o&&u&&(h.bindBuffer(h.ELEMENT_ARRAY_BUFFER,this.pointProgram.indexBuffer),h.bufferData(h.ELEMENT_ARRAY_BUFFER,s??new Uint32Array(0),h.DYNAMIC_DRAW),h.bindBuffer(h.ELEMENT_ARRAY_BUFFER,null)),this.usePointIndices=o,this.pointCount=o?s?.length??0:this.lastPointData.count,(l||u)&&(this.pointBuffersDirty=!1),this.requestRender()}sanitizeDrawIndices(e,n){if(n<=0||e.length===0)return new Uint32Array(0);let r=e.length;for(let s=0;s<e.length;s+=1)e[s]<n||(r-=1);if(r===e.length)return e;if(r<=0)return new Uint32Array(0);const i=new Uint32Array(r);let o=0;for(let s=0;s<e.length;s+=1){const a=e[s];a>=n||(i[o]=a,o+=1)}return i}setInteractionLock(e){const n=!!e;this.interactionLocked!==n&&(this.interactionLocked=n,n&&this.cancelDrag())}cancelDrag(){if(this.pointerId!==null&&this.canvas.hasPointerCapture(this.pointerId))try{this.canvas.releasePointerCapture(this.pointerId)}catch{}this.dragging=!1,this.interactionMode="none",this.rotateLastAngleRad=null,this.pointerId=null,this.canvas.classList.remove("dragging")}getPointerAngleRad(e,n){const r=this.canvas.getBoundingClientRect(),i=e-r.left-r.width*.5,o=n-r.top-r.height*.5;return Math.atan2(o,i)}screenToWorld(e,n){const r=this.canvas.getBoundingClientRect(),i=e-r.left,o=n-r.top;return this.camera.screenToWorld(i,o)}worldToScreen(e,n){return this.camera.worldToScreen(e,n)}setViewCenter(e,n){!Number.isFinite(e)||!Number.isFinite(n)||(this.camera.setCenter(e,n),this.clampViewState(),this.emitViewState(),this.requestRender())}getViewCorners(){return this.camera.getViewCorners()}resetRotation(){const e=this.camera.getViewState();Math.abs(e.rotationDeg)<1e-6||(this.camera.setViewState({rotationDeg:0}),this.clampViewState(),this.emitViewState(),this.requestRender())}getPointSizeByZoom(){const e=Math.max(1e-6,this.camera.getViewState().zoom),n=this.source.maxTierZoom+Math.log2(e),r=[[1,2.6],[2,3.1],[3,3.8],[4,4.8],[5,6.1],[6,7.4],[7,8.4],[8,9],[9,11.5],[10,14.5],[11,18],[12,22]];let i=r[0][1];for(let s=1;s<r.length;s+=1){const[a,l]=r[s-1],[u,h]=r[s];if(n<=a)break;const b=q((n-a)/Math.max(1e-6,u-a),0,1);i=l+(h-l)*b}const o=r[r.length-1];return n>o[0]&&(i+=(n-o[0])*4),q(i,2.2,36)}fitToImage(){const e=this.canvas.getBoundingClientRect(),n=Math.max(1,e.width||1),r=Math.max(1,e.height||1),i=Math.min(n/this.source.width,r/this.source.height),o=Number.isFinite(i)&&i>0?i:1;this.fitZoom=o,this.minZoom=Math.max(this.fitZoom*.5,1e-6),this.maxZoom=Math.max(1,this.fitZoom*8),this.minZoom>this.maxZoom&&(this.minZoom=this.maxZoom);const s=n/o,a=r/o;this.camera.setViewState({zoom:q(o,this.minZoom,this.maxZoom),offsetX:(this.source.width-s)*.5,offsetY:(this.source.height-a)*.5,rotationDeg:0}),this.clampViewState(),this.emitViewState(),this.requestRender()}zoomBy(e,n,r){const i=this.camera.getViewState(),o=q(i.zoom*e,this.minZoom,this.maxZoom);if(o===i.zoom)return;const[s,a]=this.camera.screenToWorld(n,r);this.camera.setViewState({zoom:o});const l=this.camera.getViewport(),u=n-l.width*.5,h=r-l.height*.5,b=Be(this.camera.getViewState().rotationDeg),m=Math.cos(b),p=Math.sin(b),x=u/o*m-h/o*p,w=u/o*p+h/o*m;this.camera.setCenter(s-x,a-w),this.clampViewState(),this.emitViewState(),this.requestRender()}clampViewState(){const e=this.getViewBounds(),n=Math.max(1e-6,e[2]-e[0]),r=Math.max(1e-6,e[3]-e[1]),i=n*.2,o=r*.2,[s,a]=this.camera.getCenter(),l=n*.5,u=r*.5,h=l-i,b=this.source.width-l+i,m=u-o,p=this.source.height-u+o,x=h<=b?q(s,h,b):this.source.width*.5,w=m<=p?q(a,m,p):this.source.height*.5;this.camera.setCenter(x,w)}emitViewState(){this.onViewStateChange?.(this.camera.getViewState())}selectTier(){const e=Math.max(1e-6,this.camera.getViewState().zoom),n=this.source.maxTierZoom+Math.log2(e);return q(Math.floor(n),0,this.source.maxTierZoom)}getViewBounds(){const e=this.camera.getViewCorners();let n=1/0,r=1/0,i=-1/0,o=-1/0;for(const[s,a]of e)s<n&&(n=s),s>i&&(i=s),a<r&&(r=a),a>o&&(o=a);return[n,r,i,o]}intersectsBounds(e,n){return!(e[2]<=n[0]||e[0]>=n[2]||e[3]<=n[1]||e[1]>=n[3])}getVisibleTiles(){const e=this.selectTier();this.currentTier=e;const n=this.getViewBounds(),r=Math.pow(2,this.source.maxTierZoom-e),i=Math.ceil(this.source.width/r),o=Math.ceil(this.source.height/r),s=Math.max(1,Math.ceil(i/this.source.tileSize)),a=Math.max(1,Math.ceil(o/this.source.tileSize)),l=n[0],u=n[1],h=n[2],b=n[3],m=q(Math.floor(l/r/this.source.tileSize),0,s-1),p=q(Math.floor((h-1)/r/this.source.tileSize),0,s-1),x=q(Math.floor(u/r/this.source.tileSize),0,a-1),w=q(Math.floor((b-1)/r/this.source.tileSize),0,a-1);if(m>p||x>w)return[];const T=(l+h)*.5/r/this.source.tileSize,S=(u+b)*.5/r/this.source.tileSize,F=[];for(let I=x;I<=w;I+=1)for(let L=m;L<=p;L+=1){const pe=L*this.source.tileSize*r,ae=I*this.source.tileSize*r,z=Math.min((L+1)*this.source.tileSize,i)*r,be=Math.min((I+1)*this.source.tileSize,o)*r,ue=L-T,Q=I-S;F.push({key:`${e}/${L}/${I}`,tier:e,x:L,y:I,bounds:[pe,ae,z,be],distance2:ue*ue+Q*Q,url:ct(this.source,e,L,I)})}return F.sort((I,L)=>I.distance2-L.distance2),F}trimCache(){if(this.cache.size<=this.maxCacheTiles)return;const e=Array.from(this.cache.entries());e.sort((r,i)=>r[1].lastUsed-i[1].lastUsed);const n=this.cache.size-this.maxCacheTiles;for(let r=0;r<n;r+=1){const[i,o]=e[r];this.gl.deleteTexture(o.texture),this.cache.delete(i)}}render(){if(this.destroyed||this.contextLost||this.gl.isContextLost())return;const e=Rt();this.frameSerial+=1;const n=this.gl,r=this.tileProgram,i=this.pointProgram;n.clearColor(.03,.06,.1,1),n.clear(n.COLOR_BUFFER_BIT);const o=this.getVisibleTiles(),s=this.getViewBounds(),a=new Set(o.map(m=>m.key));n.useProgram(r.program),n.bindVertexArray(r.vao),n.uniformMatrix3fv(r.uCamera,!1,this.camera.getMatrix()),n.uniform1i(r.uTexture,0);const l=[];for(const[,m]of this.cache)a.has(m.key)||this.intersectsBounds(m.bounds,s)&&l.push(m);l.sort((m,p)=>m.tier-p.tier);for(const m of l)m.lastUsed=this.frameSerial,n.activeTexture(n.TEXTURE0),n.bindTexture(n.TEXTURE_2D,m.texture),n.uniform4f(r.uBounds,m.bounds[0],m.bounds[1],m.bounds[2],m.bounds[3]),n.drawArrays(n.TRIANGLE_STRIP,0,4);let u=0;const h=[];for(const m of o){const p=this.cache.get(m.key);if(!p){h.push(m);continue}p.lastUsed=this.frameSerial,n.activeTexture(n.TEXTURE0),n.bindTexture(n.TEXTURE_2D,p.texture),n.uniform4f(r.uBounds,p.bounds[0],p.bounds[1],p.bounds[2],p.bounds[3]),n.drawArrays(n.TRIANGLE_STRIP,0,4),u+=1}this.tileScheduler.schedule(h),n.bindTexture(n.TEXTURE_2D,null),n.bindVertexArray(null);let b=0;if(this.pointCount>0&&(n.enable(n.BLEND),n.blendFunc(n.ONE,n.ONE_MINUS_SRC_ALPHA),n.useProgram(i.program),n.bindVertexArray(i.vao),n.uniformMatrix3fv(i.uCamera,!1,this.camera.getMatrix()),n.uniform1f(i.uPointSize,this.getPointSizeByZoom()),n.uniform1f(i.uPaletteSize,this.pointPaletteSize),n.uniform1i(i.uPalette,1),n.activeTexture(n.TEXTURE1),n.bindTexture(n.TEXTURE_2D,i.paletteTexture),this.usePointIndices?n.drawElements(n.POINTS,this.pointCount,n.UNSIGNED_INT,0):n.drawArrays(n.POINTS,0,this.pointCount),n.bindTexture(n.TEXTURE_2D,null),n.bindVertexArray(null),b=this.pointCount),this.onStats){const m=this.tileScheduler.getSnapshot(),p=u,x=h.length,w=l.length+u+(b>0?1:0);this.onStats({tier:this.currentTier,visible:o.length,rendered:u,points:b,fallback:l.length,cache:this.cache.size,inflight:m.inflight,queued:m.queued,retries:m.retries,failed:m.failed,aborted:m.aborted,cacheHits:p,cacheMisses:x,drawCalls:w,frameMs:Rt()-e})}}requestRender(){this.frame!==null||this.destroyed||this.contextLost||this.gl.isContextLost()||(this.frame=requestAnimationFrame(()=>{this.frame=null,this.render()}))}resize(){const e=this.canvas.getBoundingClientRect(),n=Math.max(1,e.width||this.canvas.clientWidth||1),r=Math.max(1,e.height||this.canvas.clientHeight||1),i=Math.max(1,window.devicePixelRatio||1),o=Math.max(1,Math.round(n*i)),s=Math.max(1,Math.round(r*i));(this.canvas.width!==o||this.canvas.height!==s)&&(this.canvas.width=o,this.canvas.height=s),this.camera.setViewport(n,r),this.gl.viewport(0,0,o,s),this.requestRender()}onPointerDown(e){if(this.interactionLocked)return;const n=this.ctrlDragRotate&&(e.ctrlKey||e.metaKey);(e.button===0||n&&e.button===2)&&(n&&e.preventDefault(),this.dragging=!0,this.interactionMode=n?"rotate":"pan",this.pointerId=e.pointerId,this.lastPointerX=e.clientX,this.lastPointerY=e.clientY,this.rotateLastAngleRad=this.interactionMode==="rotate"?this.getPointerAngleRad(e.clientX,e.clientY):null,this.canvas.classList.add("dragging"),this.canvas.setPointerCapture(e.pointerId))}onPointerMove(e){if(this.interactionLocked||!this.dragging||e.pointerId!==this.pointerId)return;const n=e.clientX-this.lastPointerX,r=e.clientY-this.lastPointerY;if(this.lastPointerX=e.clientX,this.lastPointerY=e.clientY,this.interactionMode==="rotate"){const i=this.getPointerAngleRad(e.clientX,e.clientY),o=this.rotateLastAngleRad;if(this.rotateLastAngleRad=i,o!==null){const s=i-o,a=Math.atan2(Math.sin(s),Math.cos(s)),l=this.rotationDragSensitivityDegPerPixel/Pt,u=this.camera.getViewState();this.camera.setViewState({rotationDeg:u.rotationDeg-a*180/Math.PI*l})}}else{const i=this.camera.getViewState(),o=Math.max(1e-6,i.zoom),s=Be(i.rotationDeg),a=Math.cos(s),l=Math.sin(s),u=(n*a-r*l)/o,h=(n*l+r*a)/o;this.camera.setViewState({offsetX:i.offsetX-u,offsetY:i.offsetY-h})}this.clampViewState(),this.emitViewState(),this.requestRender()}onPointerUp(e){this.interactionLocked||e.pointerId===this.pointerId&&this.cancelDrag()}onWheel(e){if(this.interactionLocked){e.preventDefault();return}e.preventDefault();const n=this.canvas.getBoundingClientRect(),r=e.clientX-n.left,i=e.clientY-n.top,o=e.deltaY<0?1.12:.89;this.zoomBy(o,r,i)}onDoubleClick(e){if(this.interactionLocked)return;const n=this.canvas.getBoundingClientRect(),r=e.clientX-n.left,i=e.clientY-n.top;this.zoomBy(e.shiftKey?.8:1.25,r,i)}onContextMenu(e){(this.dragging||e.ctrlKey||e.metaKey)&&e.preventDefault()}onWebGlContextLost(e){e.preventDefault(),!(this.destroyed||this.contextLost)&&(this.contextLost=!0,this.pointBuffersDirty=!0,this.frame!==null&&(cancelAnimationFrame(this.frame),this.frame=null),this.cancelDrag(),this.tileScheduler.clear(),this.cache.clear(),this.onContextLost?.())}onWebGlContextRestored(e){this.destroyed||(this.contextLost=!1,this.cache.clear(),this.tileProgram=this.initTileProgram(),this.pointProgram=this.initPointProgram(),this.pointBuffersDirty=!0,this.lastPointPalette&&this.lastPointPalette.length>0&&this.setPointPalette(this.lastPointPalette),this.lastPointData?this.setPointData(this.lastPointData):this.pointCount=0,this.resize(),this.requestRender(),this.onContextRestored?.())}destroy(){if(!this.destroyed){if(this.destroyed=!0,this.frame!==null&&(cancelAnimationFrame(this.frame),this.frame=null),this.resizeObserver.disconnect(),this.canvas.removeEventListener("pointerdown",this.boundPointerDown),this.canvas.removeEventListener("pointermove",this.boundPointerMove),this.canvas.removeEventListener("pointerup",this.boundPointerUp),this.canvas.removeEventListener("pointercancel",this.boundPointerUp),this.canvas.removeEventListener("wheel",this.boundWheel),this.canvas.removeEventListener("dblclick",this.boundDoubleClick),this.canvas.removeEventListener("contextmenu",this.boundContextMenu),this.canvas.removeEventListener("webglcontextlost",this.boundContextLost),this.canvas.removeEventListener("webglcontextrestored",this.boundContextRestored),this.cancelDrag(),this.tileScheduler.destroy(),!this.contextLost&&!this.gl.isContextLost()){for(const[,e]of this.cache)this.gl.deleteTexture(e.texture);this.gl.deleteBuffer(this.tileProgram.vbo),this.gl.deleteVertexArray(this.tileProgram.vao),this.gl.deleteProgram(this.tileProgram.program),this.gl.deleteBuffer(this.pointProgram.posBuffer),this.gl.deleteBuffer(this.pointProgram.termBuffer),this.gl.deleteBuffer(this.pointProgram.indexBuffer),this.gl.deleteTexture(this.pointProgram.paletteTexture),this.gl.deleteVertexArray(this.pointProgram.vao),this.gl.deleteProgram(this.pointProgram.program)}this.cache.clear()}}initTileProgram(){const e=this.gl,i=pt(e,`#version 300 es
|
|
63
|
+
`;function Mr(){if(typeof navigator>"u")return!1;const t=navigator;return typeof t.gpu=="object"&&t.gpu!==null}function kt(){if(!Mr())return null;const e=navigator.gpu;if(!e||typeof e!="object")return null;const r=e;return typeof r.requestAdapter!="function"?null:r}const Ye=globalThis.GPUShaderStage?.COMPUTE??4,Qe=globalThis.GPUBufferUsage?.STORAGE??128,Xe=globalThis.GPUBufferUsage?.COPY_DST??8,Cr=globalThis.GPUBufferUsage?.COPY_SRC??4,Ar=globalThis.GPUBufferUsage?.UNIFORM??64,Ir=globalThis.GPUBufferUsage?.MAP_READ??1,_r=globalThis.GPUMapMode?.READ??1;async function Br(){const t=kt();if(!t)return{supported:!1,features:[]};const e=await t.requestAdapter();return e?{supported:!0,adapterName:e.info?.description??e.info?.vendor??"unknown",features:Array.from(e.features),limits:{maxStorageBufferBindingSize:Number(e.limits.maxStorageBufferBindingSize),maxComputeInvocationsPerWorkgroup:Number(e.limits.maxComputeInvocationsPerWorkgroup),maxComputeWorkgroupSizeX:Number(e.limits.maxComputeWorkgroupSizeX)}}:{supported:!1,features:[]}}async function Ur(){return We||(We=(async()=>{const t=kt();if(!t)return null;const e=await t.requestAdapter();if(!e)return null;const r=await e.requestDevice(),n=r.createBindGroupLayout({entries:[{binding:0,visibility:Ye,buffer:{type:"read-only-storage"}},{binding:1,visibility:Ye,buffer:{type:"read-only-storage"}},{binding:2,visibility:Ye,buffer:{type:"storage"}},{binding:3,visibility:Ye,buffer:{type:"uniform"}}]}),i=r.createComputePipeline({layout:r.createPipelineLayout({bindGroupLayouts:[n]}),compute:{module:r.createShaderModule({code:Sr}),entryPoint:"main"}});return{device:r,pipeline:i,bindGroupLayout:n}})(),We)}function Ve(t,e){return Math.ceil(t/e)*e}async function Nt(t,e,r){const n=await Ur();if(!n)return null;const i=Math.max(0,Math.floor(e)),o=Math.max(0,Math.floor(r.length/4));if(i===0||o===0)return new Uint32Array(0);const s=Math.min(i,Math.floor(t.length/2));if(s===0)return new Uint32Array(0);const a=s*2*Float32Array.BYTES_PER_ELEMENT,l=o*4*Float32Array.BYTES_PER_ELEMENT,u=s*Uint32Array.BYTES_PER_ELEMENT,h=Number(n.device.limits.maxStorageBufferBindingSize);if(a>h||l>h||u>h)return null;const b=n.device.createBuffer({size:Ve(a,4),usage:Qe|Xe}),m=n.device.createBuffer({size:Ve(l,4),usage:Qe|Xe}),p=n.device.createBuffer({size:Ve(u,4),usage:Qe|Cr}),x=n.device.createBuffer({size:16,usage:Ar|Xe}),w=n.device.createBuffer({size:Ve(u,4),usage:Xe|Ir});n.device.queue.writeBuffer(b,0,t.buffer,t.byteOffset,a),n.device.queue.writeBuffer(m,0,r.buffer,r.byteOffset,l),n.device.queue.writeBuffer(x,0,new Uint32Array([s,o,0,0]));const T=n.device.createBindGroup({layout:n.bindGroupLayout,entries:[{binding:0,resource:{buffer:b}},{binding:1,resource:{buffer:m}},{binding:2,resource:{buffer:p}},{binding:3,resource:{buffer:x}}]}),C=n.device.createCommandEncoder(),F=C.beginComputePass();F.setPipeline(n.pipeline),F.setBindGroup(0,T),F.dispatchWorkgroups(Math.ceil(s/256)),F.end(),C.copyBufferToBuffer(p,0,w,0,u),n.device.queue.submit([C.finish()]),await w.mapAsync(_r);const I=w.getMappedRange(),L=new Uint32Array(I.slice(0));return w.unmap(),b.destroy(),m.destroy(),p.destroy(),x.destroy(),w.destroy(),L}function ve(){return typeof performance<"u"&&typeof performance.now=="function"?performance.now():Date.now()}function Dr(t){if(!Array.isArray(t)||t.length<3)return[];const e=t.map(([i,o])=>[i,o]),r=e[0],n=e[e.length-1];return!r||!n?[]:((r[0]!==n[0]||r[1]!==n[1])&&e.push([r[0],r[1]]),e)}function Fr(t){const e=[];for(const r of t??[]){const n=Dr(r);if(n.length<4)continue;let i=1/0,o=1/0,s=-1/0,a=-1/0;for(const[l,u]of n)l<i&&(i=l),l>s&&(s=l),u<o&&(o=u),u>a&&(a=u);!Number.isFinite(i)||!Number.isFinite(o)||e.push({ring:n,minX:i,minY:o,maxX:s,maxY:a})}return e}function Lr(t,e,r){let n=!1;for(let i=0,o=r.length-1;i<r.length;o=i,i+=1){const s=r[i][0],a=r[i][1],l=r[o][0],u=r[o][1];a>e!=u>e&&t<(l-s)*(e-a)/(u-a||Number.EPSILON)+s&&(n=!n)}return n}function Et(t,e,r){for(const n of r)if(!(t<n.minX||t>n.maxX||e<n.minY||e>n.maxY)&&Lr(t,e,n.ring))return!0;return!1}async function zt(t,e,r={}){const n=ve(),i=r.bridgeToDraw===!0;if(!t||!t.count||!t.positions||!t.paletteIndices)return{data:null,meta:{mode:"hybrid-webgpu",durationMs:ve()-n,usedWebGpu:!1,candidateCount:0,bridgedToDraw:!1}};const o=Fr(e??[]);if(o.length===0)return{data:{count:0,positions:new Float32Array(0),paletteIndices:new Uint16Array(0)},meta:{mode:"hybrid-webgpu",durationMs:ve()-n,usedWebGpu:!1,candidateCount:0,bridgedToDraw:!1}};const s=Math.max(0,Math.min(t.count,Math.floor(t.positions.length/2),t.paletteIndices.length));if(s===0)return{data:{count:0,positions:new Float32Array(0),paletteIndices:new Uint16Array(0)},meta:{mode:"hybrid-webgpu",durationMs:ve()-n,usedWebGpu:!1,candidateCount:0,bridgedToDraw:!1}};const a=new Float32Array(o.length*4);for(let w=0;w<o.length;w+=1){const T=w*4,C=o[w];a[T]=C.minX,a[T+1]=C.minY,a[T+2]=C.maxX,a[T+3]=C.maxY}let l=null,u=!1;try{l=await Nt(t.positions,s,a),u=!!l}catch{l=null,u=!1}if(!l)return{data:Ue(t,e),meta:{mode:"hybrid-webgpu",durationMs:ve()-n,usedWebGpu:!1,candidateCount:s,bridgedToDraw:!1}};let h=0;for(let w=0;w<s;w+=1)l[w]===1&&(h+=1);const b=new Uint32Array(h);if(h>0){let w=0;for(let T=0;T<s;T+=1)l[T]===1&&(b[w]=T,w+=1)}if(h===0)return i?{data:{count:s,positions:t.positions.subarray(0,s*2),paletteIndices:t.paletteIndices.subarray(0,s),drawIndices:new Uint32Array(0)},meta:{mode:"hybrid-webgpu",durationMs:ve()-n,usedWebGpu:!0,candidateCount:0,bridgedToDraw:!0}}:{data:{count:0,positions:new Float32Array(0),paletteIndices:new Uint16Array(0)},meta:{mode:"hybrid-webgpu",durationMs:ve()-n,usedWebGpu:!0,candidateCount:0,bridgedToDraw:!1}};if(i){const w=new Uint32Array(h);let T=0;for(let C=0;C<h;C+=1){const F=b[C]??0,I=t.positions[F*2],L=t.positions[F*2+1];Et(I,L,o)&&(w[T]=F,T+=1)}return{data:{count:s,positions:t.positions.subarray(0,s*2),paletteIndices:t.paletteIndices.subarray(0,s),drawIndices:w.subarray(0,T)},meta:{mode:"hybrid-webgpu",durationMs:ve()-n,usedWebGpu:!0,candidateCount:h,bridgedToDraw:!0}}}const m=new Float32Array(h*2),p=new Uint16Array(h);let x=0;for(let w=0;w<h;w+=1){const T=b[w]??0,C=t.positions[T*2],F=t.positions[T*2+1];Et(C,F,o)&&(m[x*2]=C,m[x*2+1]=F,p[x]=t.paletteIndices[T],x+=1)}return{data:{count:x,positions:m.subarray(0,x*2),paletteIndices:p.subarray(0,x)},meta:{mode:"hybrid-webgpu",durationMs:ve()-n,usedWebGpu:!0,candidateCount:h,bridgedToDraw:!1}}}let fe=null,ot=!0,kr=1;const Me=new Map;function Ge(){return typeof performance<"u"&&typeof performance.now=="function"?performance.now():Date.now()}function Nr(){if(!ot)return null;if(fe)return fe;try{const t=new Worker(new URL(""+(typeof document>"u"?require("url").pathToFileURL(__dirname+"/assets/roi-clip-worker-i1SE1Dpa.js").href:new URL("assets/roi-clip-worker-i1SE1Dpa.js",document.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"&&document.currentScript.src||document.baseURI).href),typeof document>"u"?require("url").pathToFileURL(__filename).href:He&&He.tagName.toUpperCase()==="SCRIPT"&&He.src||new URL("index.cjs",document.baseURI).href),{type:"module"});return t.addEventListener("message",lt),t.addEventListener("error",ht),fe=t,t}catch{return ot=!1,null}}function lt(t){const e=t.data;if(!e)return;const r=Me.get(e.id);if(!r)return;if(Me.delete(e.id),e.type==="roi-clip-failure"){r.reject(new Error(e.error||"worker clip failed"));return}const n=Math.max(0,Math.floor(e.count)),i=new Float32Array(e.positions),o=new Uint16Array(e.paletteIndices),s={count:n,positions:i.subarray(0,n*2),paletteIndices:o.subarray(0,n)};r.resolve({data:s,meta:{mode:"worker",durationMs:Number.isFinite(e.durationMs)?e.durationMs:Ge()-r.startMs}})}function ht(){ot=!1,fe&&(fe.removeEventListener("message",lt),fe.removeEventListener("error",ht),fe.terminate(),fe=null);for(const[,t]of Me)t.reject(new Error("worker crashed"));Me.clear()}function zr(){if(fe){fe.removeEventListener("message",lt),fe.removeEventListener("error",ht),fe.terminate(),fe=null;for(const[,t]of Me)t.reject(new Error("worker terminated"));Me.clear()}}async function Wt(t,e){if(!t||!t.count||!t.positions||!t.paletteIndices)return{data:null,meta:{mode:"worker",durationMs:0}};const r=Nr();if(!r){const l=Ge();return{data:Ue(t,e),meta:{mode:"sync",durationMs:Ge()-l}}}const n=Math.max(0,Math.min(t.count,Math.floor(t.positions.length/2),t.paletteIndices.length)),i=t.positions.slice(0,n*2),o=t.paletteIndices.slice(0,n),s=kr++,a=Ge();return new Promise((l,u)=>{Me.set(s,{resolve:l,reject:u,startMs:a});const h={type:"roi-clip-request",id:s,count:n,positions:i.buffer,paletteIndices:o.buffer,polygons:e??[]};r.postMessage(h,[i.buffer,o.buffer])})}function Wr(t){if(!Array.isArray(t)||t.length<3)return[];const e=t.map(i=>[Number(i[0]),Number(i[1])]),r=e[0],n=e[e.length-1];return!r||!n?[]:((r[0]!==n[0]||r[1]!==n[1])&&e.push([r[0],r[1]]),e)}function Yr(t){let e=0;for(let r=0;r<t.length-1;r+=1){const[n,i]=t[r],[o,s]=t[r+1];e+=n*s-o*i}return Math.abs(e*.5)}function Xr(t){const e=[];for(let r=0;r<t.length;r+=1){const n=t[r];if(!n?.coordinates?.length)continue;const i=Wr(n.coordinates);if(i.length<4)continue;let o=1/0,s=1/0,a=-1/0,l=-1/0;for(const[u,h]of i)u<o&&(o=u),u>a&&(a=u),h<s&&(s=h),h>l&&(l=h);!Number.isFinite(o)||!Number.isFinite(s)||!Number.isFinite(a)||!Number.isFinite(l)||e.push({regionId:n.id??r,regionIndex:r,ring:i,minX:o,minY:s,maxX:a,maxY:l,area:Math.max(1e-6,Yr(i))})}return e}function Vr(t,e,r){let n=!1;for(let i=0,o=r.length-1;i<r.length;o=i,i+=1){const s=r[i][0],a=r[i][1],l=r[o][0],u=r[o][1];a>e!=u>e&&t<(l-s)*(e-a)/(u-a||Number.EPSILON)+s&&(n=!n)}return n}function Or(t,e){if(Array.isArray(e)){const r=e[t];if(typeof r=="string"&&r.length>0)return r}if(e instanceof Map){const r=e.get(t);if(typeof r=="string"&&r.length>0)return r}return String(t)}function Yt(t,e,r={}){const n=Math.max(0,Math.min(Math.floor(t?.count??0),Math.floor((t?.positions?.length??0)/2),t?.paletteIndices?.length??0));let i=null;if(t?.drawIndices instanceof Uint32Array){const m=t.drawIndices;let p=m.length;for(let x=0;x<m.length;x+=1)m[x]<n||(p-=1);if(p===m.length)i=m;else if(p>0){const x=new Uint32Array(p);let w=0;for(let T=0;T<m.length;T+=1){const C=m[T];C>=n||(x[w]=C,w+=1)}i=x}else i=new Uint32Array(0)}const o=i?i.length:n,s=Xr(e??[]);if(!t||o===0||s.length===0)return{groups:[],inputPointCount:o,pointsInsideAnyRegion:0,unmatchedPointCount:o};const a=new Map,l=new Map;let u=0;for(let m=0;m<o;m+=1){const p=i?i[m]:m,x=t.positions[p*2],w=t.positions[p*2+1];let T=null;for(const I of s)x<I.minX||x>I.maxX||w<I.minY||w>I.maxY||Vr(x,w,I.ring)&&(!T||I.area<T.area)&&(T=I);if(!T)continue;u+=1;const C=t.paletteIndices[p]??0,F=a.get(T.regionIndex)??new Map;F.set(C,(F.get(C)??0)+1),a.set(T.regionIndex,F),l.set(T.regionIndex,(l.get(T.regionIndex)??0)+1)}const h=r.includeEmptyRegions??!1,b=[];for(const m of s){const p=l.get(m.regionIndex)??0;if(!h&&p<=0)continue;const x=a.get(m.regionIndex)??new Map,w=Array.from(x.entries()).map(([T,C])=>({termId:Or(T,r.paletteIndexToTermId),paletteIndex:T,count:C})).sort((T,C)=>C.count-T.count||T.paletteIndex-C.paletteIndex);b.push({regionId:m.regionId,regionIndex:m.regionIndex,totalCount:p,termCounts:w})}return{groups:b,inputPointCount:o,pointsInsideAnyRegion:u,unmatchedPointCount:Math.max(0,o-u)}}function Oe(){return typeof performance<"u"&&typeof performance.now=="function"?performance.now():Date.now()}function Gr(t,e){if(!e)return!1;try{const n=new URL(t,typeof window<"u"?window.location.href:void 0).hostname.toLowerCase();if(n.includes("amazonaws.com")||n.startsWith("s3.")||n.includes(".s3."))return!1}catch{}return!0}class Xt{constructor(e){d(this,"maxConcurrency");d(this,"maxRetries");d(this,"retryBaseDelayMs");d(this,"retryMaxDelayMs");d(this,"onTileLoad");d(this,"onTileError");d(this,"onStateChange");d(this,"authToken");d(this,"destroyed",!1);d(this,"queue",[]);d(this,"queuedByKey",new Map);d(this,"inflight",new Map);d(this,"visibleKeys",new Set);d(this,"timerId",null);d(this,"abortedCount",0);d(this,"retryCount",0);d(this,"failedCount",0);this.maxConcurrency=Math.max(1,Math.floor(e.maxConcurrency??12)),this.maxRetries=Math.max(0,Math.floor(e.maxRetries??2)),this.retryBaseDelayMs=Math.max(10,Math.floor(e.retryBaseDelayMs??120)),this.retryMaxDelayMs=Math.max(this.retryBaseDelayMs,Math.floor(e.retryMaxDelayMs??1200)),this.authToken=e.authToken??"",this.onTileLoad=e.onTileLoad,this.onTileError=e.onTileError,this.onStateChange=e.onStateChange}setAuthToken(e){this.authToken=String(e??"")}schedule(e){if(this.destroyed)return;const r=new Set;for(const n of e)r.add(n.key);this.visibleKeys=r,this.dropInvisibleQueued(r),this.abortInvisibleInflight(r);for(const n of e){if(this.inflight.has(n.key)){const s=this.inflight.get(n.key);s&&(s.tile=n);continue}const i=this.queuedByKey.get(n.key);if(i){i.tile=n;continue}const o={tile:n,attempt:0,readyAt:Oe()};this.queue.push(o),this.queuedByKey.set(n.key,o)}this.sortQueue(),this.pump(),this.emitStateChange()}clear(){this.clearPumpTimer(),this.visibleKeys.clear(),this.queue=[],this.queuedByKey.clear();for(const[,e]of this.inflight)e.controller.abort();this.inflight.clear(),this.emitStateChange()}destroy(){this.destroyed||(this.destroyed=!0,this.clear())}getInflightCount(){return this.inflight.size}getSnapshot(){return{inflight:this.inflight.size,queued:this.queue.length,aborted:this.abortedCount,retries:this.retryCount,failed:this.failedCount}}dropInvisibleQueued(e){if(this.queue.length===0)return;const r=[];for(const n of this.queue){if(!e.has(n.tile.key)){this.queuedByKey.delete(n.tile.key);continue}r.push(n)}this.queue=r}abortInvisibleInflight(e){for(const[r,n]of this.inflight)e.has(r)||(this.inflight.delete(r),this.abortedCount+=1,n.controller.abort())}sortQueue(){this.queue.sort((e,r)=>e.readyAt!==r.readyAt?e.readyAt-r.readyAt:e.tile.distance2!==r.tile.distance2?e.tile.distance2-r.tile.distance2:e.tile.tier!==r.tile.tier?r.tile.tier-e.tile.tier:e.tile.key.localeCompare(r.tile.key))}pump(){if(this.destroyed)return;for(this.clearPumpTimer();this.inflight.size<this.maxConcurrency;){const n=this.takeNextReadyQueueItem();if(!n)break;this.startFetch(n)}if(this.inflight.size>=this.maxConcurrency||this.queue.length===0)return;const e=this.queue[0]?.readyAt;if(typeof e!="number")return;const r=Math.max(0,e-Oe());this.timerId=window.setTimeout(()=>{this.timerId=null,this.pump()},r)}takeNextReadyQueueItem(){if(this.queue.length===0)return null;const e=Oe(),r=this.queue[0];return!r||r.readyAt>e?null:(this.queue.shift(),this.queuedByKey.delete(r.tile.key),r)}startFetch(e){const r=new AbortController,n={tile:e.tile,attempt:e.attempt,controller:r};this.inflight.set(e.tile.key,n),this.emitStateChange();const i=Gr(e.tile.url,this.authToken);fetch(e.tile.url,{signal:r.signal,headers:i?{Authorization:this.authToken}:void 0}).then(o=>{if(!o.ok)throw new Error(`HTTP ${o.status}`);return o.blob()}).then(o=>createImageBitmap(o)).then(o=>{if(this.destroyed||r.signal.aborted){o.close();return}if(!this.visibleKeys.has(e.tile.key)){o.close();return}this.onTileLoad(e.tile,o)}).catch(o=>{if(r.signal.aborted||this.destroyed)return;if(e.attempt<this.maxRetries&&this.visibleKeys.has(e.tile.key)){this.retryCount+=1;const a=e.attempt+1,l=this.getRetryDelay(a),u={tile:e.tile,attempt:a,readyAt:Oe()+l},h=this.queuedByKey.get(e.tile.key);h?(h.tile=u.tile,h.readyAt=Math.min(h.readyAt,u.readyAt),h.attempt=Math.max(h.attempt,u.attempt)):(this.queue.push(u),this.queuedByKey.set(u.tile.key,u)),this.sortQueue();return}this.failedCount+=1,this.onTileError?.(e.tile,o,e.attempt+1)}).finally(()=>{this.inflight.delete(e.tile.key),this.pump(),this.emitStateChange()})}getRetryDelay(e){const r=Math.max(0,e-1),n=Math.min(this.retryMaxDelayMs,this.retryBaseDelayMs*2**r),i=.85+Math.random()*.3;return Math.round(n*i)}clearPumpTimer(){this.timerId!==null&&(window.clearTimeout(this.timerId),this.timerId=null)}emitStateChange(){this.onStateChange?.(this.getSnapshot())}}const Rt=.35;class qr{constructor(){d(this,"viewportWidth",1);d(this,"viewportHeight",1);d(this,"viewState",{zoom:1,offsetX:0,offsetY:0,rotationDeg:0})}setViewport(e,r){this.viewportWidth=Math.max(1,e),this.viewportHeight=Math.max(1,r)}getViewport(){return{width:this.viewportWidth,height:this.viewportHeight}}setViewState(e){typeof e.zoom=="number"&&(this.viewState.zoom=Math.max(1e-4,e.zoom)),typeof e.offsetX=="number"&&(this.viewState.offsetX=e.offsetX),typeof e.offsetY=="number"&&(this.viewState.offsetY=e.offsetY),typeof e.rotationDeg=="number"&&Number.isFinite(e.rotationDeg)&&(this.viewState.rotationDeg=e.rotationDeg)}getViewState(){return{...this.viewState}}getCenter(){const e=Math.max(1e-6,this.viewState.zoom);return[this.viewState.offsetX+this.viewportWidth/(2*e),this.viewState.offsetY+this.viewportHeight/(2*e)]}setCenter(e,r){const n=Math.max(1e-6,this.viewState.zoom);this.viewState.offsetX=e-this.viewportWidth/(2*n),this.viewState.offsetY=r-this.viewportHeight/(2*n)}screenToWorld(e,r){const n=this.viewState,i=Math.max(1e-6,n.zoom),[o,s]=this.getCenter(),a=(e-this.viewportWidth*.5)/i,l=(r-this.viewportHeight*.5)/i,u=Be(n.rotationDeg),h=Math.cos(u),b=Math.sin(u);return[o+a*h-l*b,s+a*b+l*h]}worldToScreen(e,r){const n=this.viewState,i=Math.max(1e-6,n.zoom),[o,s]=this.getCenter(),a=e-o,l=r-s,u=Be(n.rotationDeg),h=Math.cos(u),b=Math.sin(u),m=a*h+l*b,p=-a*b+l*h;return[this.viewportWidth*.5+m*i,this.viewportHeight*.5+p*i]}getViewCorners(){const e=this.viewportWidth,r=this.viewportHeight;return[this.screenToWorld(0,0),this.screenToWorld(e,0),this.screenToWorld(e,r),this.screenToWorld(0,r)]}getMatrix(){const e=Math.max(1e-6,this.viewState.zoom),[r,n]=this.getCenter(),i=Be(this.viewState.rotationDeg),o=Math.cos(i),s=Math.sin(i),a=2*e*o/this.viewportWidth,l=2*e*s/this.viewportWidth,u=2*e*s/this.viewportHeight,h=-2*e*o/this.viewportHeight,b=-(a*r+l*n),m=-(u*r+h*n);return new Float32Array([a,u,0,l,h,0,b,m,1])}}function Be(t){return t*Math.PI/180}function Pt(){return typeof performance<"u"&&typeof performance.now=="function"?performance.now():Date.now()}function Se(t,e,r){const n=t.getUniformLocation(e,r);if(!n)throw new Error(`uniform location lookup failed: ${r}`);return n}function et(t,e){return!t||!e?t===e:t.buffer===e.buffer&&t.byteOffset===e.byteOffset&&t.byteLength===e.byteLength}class Vt{constructor(e,r,n={}){d(this,"canvas");d(this,"source");d(this,"gl");d(this,"camera",new qr);d(this,"onViewStateChange");d(this,"onStats");d(this,"onTileError");d(this,"onContextLost");d(this,"onContextRestored");d(this,"resizeObserver");d(this,"tileProgram");d(this,"pointProgram");d(this,"tileScheduler");d(this,"authToken");d(this,"destroyed",!1);d(this,"contextLost",!1);d(this,"frame",null);d(this,"frameSerial",0);d(this,"dragging",!1);d(this,"interactionMode","none");d(this,"rotateLastAngleRad",null);d(this,"pointerId",null);d(this,"lastPointerX",0);d(this,"lastPointerY",0);d(this,"interactionLocked",!1);d(this,"ctrlDragRotate",!0);d(this,"rotationDragSensitivityDegPerPixel",.35);d(this,"maxCacheTiles");d(this,"fitZoom",1);d(this,"minZoom",1e-6);d(this,"maxZoom",1);d(this,"currentTier",0);d(this,"pointCount",0);d(this,"usePointIndices",!1);d(this,"pointBuffersDirty",!0);d(this,"pointPaletteSize",1);d(this,"lastPointData",null);d(this,"lastPointPalette",null);d(this,"cache",new Map);d(this,"boundPointerDown");d(this,"boundPointerMove");d(this,"boundPointerUp");d(this,"boundWheel");d(this,"boundDoubleClick");d(this,"boundContextMenu");d(this,"boundContextLost");d(this,"boundContextRestored");this.canvas=e,this.source=r,this.onViewStateChange=n.onViewStateChange,this.onStats=n.onStats,this.onTileError=n.onTileError,this.onContextLost=n.onContextLost,this.onContextRestored=n.onContextRestored,this.authToken=n.authToken??"",this.maxCacheTiles=Math.max(32,Math.floor(n.maxCacheTiles??320)),this.ctrlDragRotate=n.ctrlDragRotate??!0,this.rotationDragSensitivityDegPerPixel=typeof n.rotationDragSensitivityDegPerPixel=="number"&&Number.isFinite(n.rotationDragSensitivityDegPerPixel)?Math.max(0,n.rotationDragSensitivityDegPerPixel):Rt;const i=e.getContext("webgl2",{alpha:!1,antialias:!1,depth:!1,stencil:!1,powerPreference:"high-performance"});if(!i)throw new Error("WebGL2 not supported");this.gl=i,this.tileProgram=this.initTileProgram(),this.pointProgram=this.initPointProgram(),this.tileScheduler=new Xt({authToken:this.authToken,maxConcurrency:n.tileScheduler?.maxConcurrency??12,maxRetries:n.tileScheduler?.maxRetries??2,retryBaseDelayMs:n.tileScheduler?.retryBaseDelayMs??120,retryMaxDelayMs:n.tileScheduler?.retryMaxDelayMs??1200,onTileLoad:(o,s)=>this.handleTileLoaded(o,s),onTileError:(o,s,a)=>{this.onTileError?.({tile:o,error:s,attemptCount:a}),console.warn("tile load failed",o.url,s)}}),this.resizeObserver=new ResizeObserver(()=>this.resize()),this.resizeObserver.observe(e),this.boundPointerDown=o=>this.onPointerDown(o),this.boundPointerMove=o=>this.onPointerMove(o),this.boundPointerUp=o=>this.onPointerUp(o),this.boundWheel=o=>this.onWheel(o),this.boundDoubleClick=o=>this.onDoubleClick(o),this.boundContextMenu=o=>this.onContextMenu(o),this.boundContextLost=o=>this.onWebGlContextLost(o),this.boundContextRestored=o=>this.onWebGlContextRestored(o),e.addEventListener("pointerdown",this.boundPointerDown),e.addEventListener("pointermove",this.boundPointerMove),e.addEventListener("pointerup",this.boundPointerUp),e.addEventListener("pointercancel",this.boundPointerUp),e.addEventListener("wheel",this.boundWheel,{passive:!1}),e.addEventListener("dblclick",this.boundDoubleClick),e.addEventListener("contextmenu",this.boundContextMenu),e.addEventListener("webglcontextlost",this.boundContextLost),e.addEventListener("webglcontextrestored",this.boundContextRestored),this.fitToImage(),this.resize()}setAuthToken(e){this.authToken=String(e??""),this.tileScheduler.setAuthToken(this.authToken)}setViewState(e){const r={...e};typeof r.zoom=="number"&&(r.zoom=q(r.zoom,this.minZoom,this.maxZoom)),this.camera.setViewState(r),this.clampViewState(),this.emitViewState(),this.requestRender()}getViewState(){return this.camera.getViewState()}setPointPalette(e){if(!e||e.length===0){this.lastPointPalette=null;return}if(this.lastPointPalette=new Uint8Array(e),this.contextLost||this.gl.isContextLost())return;const r=this.gl,n=Math.max(1,Math.floor(this.lastPointPalette.length/4));this.pointPaletteSize=n,r.bindTexture(r.TEXTURE_2D,this.pointProgram.paletteTexture),r.texImage2D(r.TEXTURE_2D,0,r.RGBA,n,1,0,r.RGBA,r.UNSIGNED_BYTE,this.lastPointPalette),r.bindTexture(r.TEXTURE_2D,null),this.requestRender()}setPointData(e){if(!e||!e.count||!e.positions||!e.paletteIndices){this.lastPointData=null,this.pointCount=0,this.usePointIndices=!1,this.requestRender();return}const r=Math.max(0,Math.min(e.count,Math.floor(e.positions.length/2),e.paletteIndices.length)),n=e.positions.subarray(0,r*2),i=e.paletteIndices.subarray(0,r),o=e.drawIndices instanceof Uint32Array,s=o?this.sanitizeDrawIndices(e.drawIndices,r):null,a=this.lastPointData;let l=this.pointBuffersDirty||!a||a.count!==r||!et(a.positions,n)||!et(a.paletteIndices,i),u=this.pointBuffersDirty||o&&(!a?.drawIndices||!et(a.drawIndices,s))||!o&&!!a?.drawIndices;if(this.lastPointData={count:r,positions:n,paletteIndices:i,drawIndices:o?s??void 0:void 0},this.contextLost||this.gl.isContextLost())return;const h=this.gl;l&&(h.bindBuffer(h.ARRAY_BUFFER,this.pointProgram.posBuffer),h.bufferData(h.ARRAY_BUFFER,this.lastPointData.positions,h.STATIC_DRAW),h.bindBuffer(h.ARRAY_BUFFER,this.pointProgram.termBuffer),h.bufferData(h.ARRAY_BUFFER,this.lastPointData.paletteIndices,h.STATIC_DRAW),h.bindBuffer(h.ARRAY_BUFFER,null)),o&&u&&(h.bindBuffer(h.ELEMENT_ARRAY_BUFFER,this.pointProgram.indexBuffer),h.bufferData(h.ELEMENT_ARRAY_BUFFER,s??new Uint32Array(0),h.DYNAMIC_DRAW),h.bindBuffer(h.ELEMENT_ARRAY_BUFFER,null)),this.usePointIndices=o,this.pointCount=o?s?.length??0:this.lastPointData.count,(l||u)&&(this.pointBuffersDirty=!1),this.requestRender()}sanitizeDrawIndices(e,r){if(r<=0||e.length===0)return new Uint32Array(0);let n=e.length;for(let s=0;s<e.length;s+=1)e[s]<r||(n-=1);if(n===e.length)return e;if(n<=0)return new Uint32Array(0);const i=new Uint32Array(n);let o=0;for(let s=0;s<e.length;s+=1){const a=e[s];a>=r||(i[o]=a,o+=1)}return i}setInteractionLock(e){const r=!!e;this.interactionLocked!==r&&(this.interactionLocked=r,r&&this.cancelDrag())}cancelDrag(){if(this.pointerId!==null&&this.canvas.hasPointerCapture(this.pointerId))try{this.canvas.releasePointerCapture(this.pointerId)}catch{}this.dragging=!1,this.interactionMode="none",this.rotateLastAngleRad=null,this.pointerId=null,this.canvas.classList.remove("dragging")}getPointerAngleRad(e,r){const n=this.canvas.getBoundingClientRect(),i=e-n.left-n.width*.5,o=r-n.top-n.height*.5;return Math.atan2(o,i)}screenToWorld(e,r){const n=this.canvas.getBoundingClientRect(),i=e-n.left,o=r-n.top;return this.camera.screenToWorld(i,o)}worldToScreen(e,r){return this.camera.worldToScreen(e,r)}setViewCenter(e,r){!Number.isFinite(e)||!Number.isFinite(r)||(this.camera.setCenter(e,r),this.clampViewState(),this.emitViewState(),this.requestRender())}getViewCorners(){return this.camera.getViewCorners()}resetRotation(){const e=this.camera.getViewState();Math.abs(e.rotationDeg)<1e-6||(this.camera.setViewState({rotationDeg:0}),this.clampViewState(),this.emitViewState(),this.requestRender())}getPointSizeByZoom(){const e=Math.max(1e-6,this.camera.getViewState().zoom),r=this.source.maxTierZoom+Math.log2(e),n=[[1,2.6],[2,3.1],[3,3.8],[4,4.8],[5,6.1],[6,7.4],[7,8.4],[8,9],[9,11.5],[10,14.5],[11,18],[12,22]];let i=n[0][1];for(let s=1;s<n.length;s+=1){const[a,l]=n[s-1],[u,h]=n[s];if(r<=a)break;const b=q((r-a)/Math.max(1e-6,u-a),0,1);i=l+(h-l)*b}const o=n[n.length-1];return r>o[0]&&(i+=(r-o[0])*4),q(i,2.2,36)}fitToImage(){const e=this.canvas.getBoundingClientRect(),r=Math.max(1,e.width||1),n=Math.max(1,e.height||1),i=Math.min(r/this.source.width,n/this.source.height),o=Number.isFinite(i)&&i>0?i:1;this.fitZoom=o,this.minZoom=Math.max(this.fitZoom*.5,1e-6),this.maxZoom=Math.max(1,this.fitZoom*8),this.minZoom>this.maxZoom&&(this.minZoom=this.maxZoom);const s=r/o,a=n/o;this.camera.setViewState({zoom:q(o,this.minZoom,this.maxZoom),offsetX:(this.source.width-s)*.5,offsetY:(this.source.height-a)*.5,rotationDeg:0}),this.clampViewState(),this.emitViewState(),this.requestRender()}zoomBy(e,r,n){const i=this.camera.getViewState(),o=q(i.zoom*e,this.minZoom,this.maxZoom);if(o===i.zoom)return;const[s,a]=this.camera.screenToWorld(r,n);this.camera.setViewState({zoom:o});const l=this.camera.getViewport(),u=r-l.width*.5,h=n-l.height*.5,b=Be(this.camera.getViewState().rotationDeg),m=Math.cos(b),p=Math.sin(b),x=u/o*m-h/o*p,w=u/o*p+h/o*m;this.camera.setCenter(s-x,a-w),this.clampViewState(),this.emitViewState(),this.requestRender()}clampViewState(){const e=this.getViewBounds(),r=Math.max(1e-6,e[2]-e[0]),n=Math.max(1e-6,e[3]-e[1]),i=r*.2,o=n*.2,[s,a]=this.camera.getCenter(),l=r*.5,u=n*.5,h=l-i,b=this.source.width-l+i,m=u-o,p=this.source.height-u+o,x=h<=b?q(s,h,b):this.source.width*.5,w=m<=p?q(a,m,p):this.source.height*.5;this.camera.setCenter(x,w)}emitViewState(){this.onViewStateChange?.(this.camera.getViewState())}selectTier(){const e=Math.max(1e-6,this.camera.getViewState().zoom),r=this.source.maxTierZoom+Math.log2(e);return q(Math.floor(r),0,this.source.maxTierZoom)}getViewBounds(){const e=this.camera.getViewCorners();let r=1/0,n=1/0,i=-1/0,o=-1/0;for(const[s,a]of e)s<r&&(r=s),s>i&&(i=s),a<n&&(n=a),a>o&&(o=a);return[r,n,i,o]}intersectsBounds(e,r){return!(e[2]<=r[0]||e[0]>=r[2]||e[3]<=r[1]||e[1]>=r[3])}getVisibleTiles(){const e=this.selectTier();this.currentTier=e;const r=this.getViewBounds(),n=Math.pow(2,this.source.maxTierZoom-e),i=Math.ceil(this.source.width/n),o=Math.ceil(this.source.height/n),s=Math.max(1,Math.ceil(i/this.source.tileSize)),a=Math.max(1,Math.ceil(o/this.source.tileSize)),l=r[0],u=r[1],h=r[2],b=r[3],m=q(Math.floor(l/n/this.source.tileSize),0,s-1),p=q(Math.floor((h-1)/n/this.source.tileSize),0,s-1),x=q(Math.floor(u/n/this.source.tileSize),0,a-1),w=q(Math.floor((b-1)/n/this.source.tileSize),0,a-1);if(m>p||x>w)return[];const T=(l+h)*.5/n/this.source.tileSize,C=(u+b)*.5/n/this.source.tileSize,F=[];for(let I=x;I<=w;I+=1)for(let L=m;L<=p;L+=1){const pe=L*this.source.tileSize*n,ae=I*this.source.tileSize*n,z=Math.min((L+1)*this.source.tileSize,i)*n,be=Math.min((I+1)*this.source.tileSize,o)*n,ue=L-T,Q=I-C;F.push({key:`${e}/${L}/${I}`,tier:e,x:L,y:I,bounds:[pe,ae,z,be],distance2:ue*ue+Q*Q,url:ct(this.source,e,L,I)})}return F.sort((I,L)=>I.distance2-L.distance2),F}trimCache(){if(this.cache.size<=this.maxCacheTiles)return;const e=Array.from(this.cache.entries());e.sort((n,i)=>n[1].lastUsed-i[1].lastUsed);const r=this.cache.size-this.maxCacheTiles;for(let n=0;n<r;n+=1){const[i,o]=e[n];this.gl.deleteTexture(o.texture),this.cache.delete(i)}}render(){if(this.destroyed||this.contextLost||this.gl.isContextLost())return;const e=Pt();this.frameSerial+=1;const r=this.gl,n=this.tileProgram,i=this.pointProgram;r.clearColor(.03,.06,.1,1),r.clear(r.COLOR_BUFFER_BIT);const o=this.getVisibleTiles(),s=this.getViewBounds(),a=new Set(o.map(m=>m.key));r.useProgram(n.program),r.bindVertexArray(n.vao),r.uniformMatrix3fv(n.uCamera,!1,this.camera.getMatrix()),r.uniform1i(n.uTexture,0);const l=[];for(const[,m]of this.cache)a.has(m.key)||this.intersectsBounds(m.bounds,s)&&l.push(m);l.sort((m,p)=>m.tier-p.tier);for(const m of l)m.lastUsed=this.frameSerial,r.activeTexture(r.TEXTURE0),r.bindTexture(r.TEXTURE_2D,m.texture),r.uniform4f(n.uBounds,m.bounds[0],m.bounds[1],m.bounds[2],m.bounds[3]),r.drawArrays(r.TRIANGLE_STRIP,0,4);let u=0;const h=[];for(const m of o){const p=this.cache.get(m.key);if(!p){h.push(m);continue}p.lastUsed=this.frameSerial,r.activeTexture(r.TEXTURE0),r.bindTexture(r.TEXTURE_2D,p.texture),r.uniform4f(n.uBounds,p.bounds[0],p.bounds[1],p.bounds[2],p.bounds[3]),r.drawArrays(r.TRIANGLE_STRIP,0,4),u+=1}this.tileScheduler.schedule(h),r.bindTexture(r.TEXTURE_2D,null),r.bindVertexArray(null);let b=0;if(this.pointCount>0&&(r.enable(r.BLEND),r.blendFunc(r.ONE,r.ONE_MINUS_SRC_ALPHA),r.useProgram(i.program),r.bindVertexArray(i.vao),r.uniformMatrix3fv(i.uCamera,!1,this.camera.getMatrix()),r.uniform1f(i.uPointSize,this.getPointSizeByZoom()),r.uniform1f(i.uPaletteSize,this.pointPaletteSize),r.uniform1i(i.uPalette,1),r.activeTexture(r.TEXTURE1),r.bindTexture(r.TEXTURE_2D,i.paletteTexture),this.usePointIndices?r.drawElements(r.POINTS,this.pointCount,r.UNSIGNED_INT,0):r.drawArrays(r.POINTS,0,this.pointCount),r.bindTexture(r.TEXTURE_2D,null),r.bindVertexArray(null),b=this.pointCount),this.onStats){const m=this.tileScheduler.getSnapshot(),p=u,x=h.length,w=l.length+u+(b>0?1:0);this.onStats({tier:this.currentTier,visible:o.length,rendered:u,points:b,fallback:l.length,cache:this.cache.size,inflight:m.inflight,queued:m.queued,retries:m.retries,failed:m.failed,aborted:m.aborted,cacheHits:p,cacheMisses:x,drawCalls:w,frameMs:Pt()-e})}}requestRender(){this.frame!==null||this.destroyed||this.contextLost||this.gl.isContextLost()||(this.frame=requestAnimationFrame(()=>{this.frame=null,this.render()}))}resize(){const e=this.canvas.getBoundingClientRect(),r=Math.max(1,e.width||this.canvas.clientWidth||1),n=Math.max(1,e.height||this.canvas.clientHeight||1),i=Math.max(1,window.devicePixelRatio||1),o=Math.max(1,Math.round(r*i)),s=Math.max(1,Math.round(n*i));(this.canvas.width!==o||this.canvas.height!==s)&&(this.canvas.width=o,this.canvas.height=s),this.camera.setViewport(r,n),this.gl.viewport(0,0,o,s),this.requestRender()}onPointerDown(e){if(this.interactionLocked)return;const r=this.ctrlDragRotate&&(e.ctrlKey||e.metaKey);(e.button===0||r&&e.button===2)&&(r&&e.preventDefault(),this.dragging=!0,this.interactionMode=r?"rotate":"pan",this.pointerId=e.pointerId,this.lastPointerX=e.clientX,this.lastPointerY=e.clientY,this.rotateLastAngleRad=this.interactionMode==="rotate"?this.getPointerAngleRad(e.clientX,e.clientY):null,this.canvas.classList.add("dragging"),this.canvas.setPointerCapture(e.pointerId))}onPointerMove(e){if(this.interactionLocked||!this.dragging||e.pointerId!==this.pointerId)return;const r=e.clientX-this.lastPointerX,n=e.clientY-this.lastPointerY;if(this.lastPointerX=e.clientX,this.lastPointerY=e.clientY,this.interactionMode==="rotate"){const i=this.getPointerAngleRad(e.clientX,e.clientY),o=this.rotateLastAngleRad;if(this.rotateLastAngleRad=i,o!==null){const s=i-o,a=Math.atan2(Math.sin(s),Math.cos(s)),l=this.rotationDragSensitivityDegPerPixel/Rt,u=this.camera.getViewState();this.camera.setViewState({rotationDeg:u.rotationDeg-a*180/Math.PI*l})}}else{const i=this.camera.getViewState(),o=Math.max(1e-6,i.zoom),s=Be(i.rotationDeg),a=Math.cos(s),l=Math.sin(s),u=(r*a-n*l)/o,h=(r*l+n*a)/o;this.camera.setViewState({offsetX:i.offsetX-u,offsetY:i.offsetY-h})}this.clampViewState(),this.emitViewState(),this.requestRender()}onPointerUp(e){this.interactionLocked||e.pointerId===this.pointerId&&this.cancelDrag()}onWheel(e){if(this.interactionLocked){e.preventDefault();return}e.preventDefault();const r=this.canvas.getBoundingClientRect(),n=e.clientX-r.left,i=e.clientY-r.top,o=e.deltaY<0?1.12:.89;this.zoomBy(o,n,i)}onDoubleClick(e){if(this.interactionLocked)return;const r=this.canvas.getBoundingClientRect(),n=e.clientX-r.left,i=e.clientY-r.top;this.zoomBy(e.shiftKey?.8:1.25,n,i)}onContextMenu(e){(this.dragging||e.ctrlKey||e.metaKey)&&e.preventDefault()}onWebGlContextLost(e){e.preventDefault(),!(this.destroyed||this.contextLost)&&(this.contextLost=!0,this.pointBuffersDirty=!0,this.frame!==null&&(cancelAnimationFrame(this.frame),this.frame=null),this.cancelDrag(),this.tileScheduler.clear(),this.cache.clear(),this.onContextLost?.())}onWebGlContextRestored(e){this.destroyed||(this.contextLost=!1,this.cache.clear(),this.tileProgram=this.initTileProgram(),this.pointProgram=this.initPointProgram(),this.pointBuffersDirty=!0,this.lastPointPalette&&this.lastPointPalette.length>0&&this.setPointPalette(this.lastPointPalette),this.lastPointData?this.setPointData(this.lastPointData):this.pointCount=0,this.resize(),this.requestRender(),this.onContextRestored?.())}destroy(){if(!this.destroyed){if(this.destroyed=!0,this.frame!==null&&(cancelAnimationFrame(this.frame),this.frame=null),this.resizeObserver.disconnect(),this.canvas.removeEventListener("pointerdown",this.boundPointerDown),this.canvas.removeEventListener("pointermove",this.boundPointerMove),this.canvas.removeEventListener("pointerup",this.boundPointerUp),this.canvas.removeEventListener("pointercancel",this.boundPointerUp),this.canvas.removeEventListener("wheel",this.boundWheel),this.canvas.removeEventListener("dblclick",this.boundDoubleClick),this.canvas.removeEventListener("contextmenu",this.boundContextMenu),this.canvas.removeEventListener("webglcontextlost",this.boundContextLost),this.canvas.removeEventListener("webglcontextrestored",this.boundContextRestored),this.cancelDrag(),this.tileScheduler.destroy(),!this.contextLost&&!this.gl.isContextLost()){for(const[,e]of this.cache)this.gl.deleteTexture(e.texture);this.gl.deleteBuffer(this.tileProgram.vbo),this.gl.deleteVertexArray(this.tileProgram.vao),this.gl.deleteProgram(this.tileProgram.program),this.gl.deleteBuffer(this.pointProgram.posBuffer),this.gl.deleteBuffer(this.pointProgram.termBuffer),this.gl.deleteBuffer(this.pointProgram.indexBuffer),this.gl.deleteTexture(this.pointProgram.paletteTexture),this.gl.deleteVertexArray(this.pointProgram.vao),this.gl.deleteProgram(this.pointProgram.program)}this.cache.clear()}}initTileProgram(){const e=this.gl,i=pt(e,`#version 300 es
|
|
64
64
|
precision highp float;
|
|
65
65
|
in vec2 aUnit;
|
|
66
66
|
in vec2 aUv;
|
|
@@ -82,7 +82,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
|
|
|
82
82
|
out vec4 outColor;
|
|
83
83
|
void main() {
|
|
84
84
|
outColor = texture(uTexture, vUv);
|
|
85
|
-
}`),o=
|
|
85
|
+
}`),o=Se(e,i,"uCamera"),s=Se(e,i,"uBounds"),a=Se(e,i,"uTexture"),l=e.createVertexArray(),u=e.createBuffer();if(!l||!u)throw new Error("buffer allocation failed");e.bindVertexArray(l),e.bindBuffer(e.ARRAY_BUFFER,u),e.bufferData(e.ARRAY_BUFFER,new Float32Array([0,0,0,0,1,0,1,0,0,1,0,1,1,1,1,1]),e.STATIC_DRAW);const h=e.getAttribLocation(i,"aUnit"),b=e.getAttribLocation(i,"aUv");if(h<0||b<0)throw new Error("tile attribute lookup failed");return e.enableVertexAttribArray(h),e.enableVertexAttribArray(b),e.vertexAttribPointer(h,2,e.FLOAT,!1,16,0),e.vertexAttribPointer(b,2,e.FLOAT,!1,16,8),e.bindVertexArray(null),e.bindBuffer(e.ARRAY_BUFFER,null),{program:i,vao:l,vbo:u,uCamera:o,uBounds:s,uTexture:a}}initPointProgram(){const e=this.gl,i=pt(e,`#version 300 es
|
|
86
86
|
precision highp float;
|
|
87
87
|
in vec2 aPosition;
|
|
88
88
|
in uint aTerm;
|
|
@@ -121,6 +121,6 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
|
|
|
121
121
|
if (alpha <= 0.001) discard;
|
|
122
122
|
|
|
123
123
|
outColor = vec4(color.rgb * alpha, alpha);
|
|
124
|
-
}`),o=
|
|
125
|
-
`):"stats: waiting for first frame...",[E]);f.useEffect(()=>{!(g===null?!0:Z.some((ie,D)=>String(st(ie,D))===String(g)))&&g!==null&&Ae(null);const U=v.current;!(U===null?!0:Z.some((ie,D)=>String(st(ie,D))===String(U)))&&U!==null&&(v.current=null,c(null),oe?.({region:null,regionId:null,regionIndex:-1,coordinate:null}))},[Z,g,oe,Ae]);const mt=f.useCallback(y=>{const U=ce.current;U&&U(y),W.current?.(),
|
|
124
|
+
}`),o=Se(e,i,"uCamera"),s=Se(e,i,"uPointSize"),a=Se(e,i,"uPalette"),l=Se(e,i,"uPaletteSize"),u=e.createVertexArray(),h=e.createBuffer(),b=e.createBuffer(),m=e.createBuffer(),p=e.createTexture();if(!u||!h||!b||!m||!p)throw new Error("point buffer allocation failed");e.bindVertexArray(u),e.bindBuffer(e.ARRAY_BUFFER,h),e.bufferData(e.ARRAY_BUFFER,0,e.DYNAMIC_DRAW);const x=e.getAttribLocation(i,"aPosition");if(x<0)throw new Error("point position attribute not found");e.enableVertexAttribArray(x),e.vertexAttribPointer(x,2,e.FLOAT,!1,0,0),e.bindBuffer(e.ARRAY_BUFFER,b),e.bufferData(e.ARRAY_BUFFER,0,e.DYNAMIC_DRAW);const w=e.getAttribLocation(i,"aTerm");if(w<0)throw new Error("point term attribute not found");return e.enableVertexAttribArray(w),e.vertexAttribIPointer(w,1,e.UNSIGNED_SHORT,0,0),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,m),e.bufferData(e.ELEMENT_ARRAY_BUFFER,0,e.DYNAMIC_DRAW),e.bindVertexArray(null),e.bindBuffer(e.ARRAY_BUFFER,null),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,null),e.bindTexture(e.TEXTURE_2D,p),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,1,1,0,e.RGBA,e.UNSIGNED_BYTE,new Uint8Array([160,160,160,255])),e.bindTexture(e.TEXTURE_2D,null),{program:i,vao:u,posBuffer:h,termBuffer:b,indexBuffer:m,paletteTexture:p,uCamera:o,uPointSize:s,uPalette:a,uPaletteSize:l}}handleTileLoaded(e,r){if(this.destroyed||this.contextLost||this.gl.isContextLost()){r.close();return}if(this.cache.has(e.key)){r.close();return}const n=this.createTextureFromBitmap(r);r.close(),n&&(this.cache.set(e.key,{key:e.key,texture:n,bounds:e.bounds,tier:e.tier,lastUsed:this.frameSerial}),this.trimCache(),this.requestRender())}createTextureFromBitmap(e){if(this.contextLost||this.gl.isContextLost())return null;const r=this.gl,n=r.createTexture();return n?(r.bindTexture(r.TEXTURE_2D,n),r.pixelStorei(r.UNPACK_FLIP_Y_WEBGL,1),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_WRAP_S,r.CLAMP_TO_EDGE),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_WRAP_T,r.CLAMP_TO_EDGE),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_MIN_FILTER,r.LINEAR),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_MAG_FILTER,r.LINEAR),r.texImage2D(r.TEXTURE_2D,0,r.RGBA,r.RGBA,r.UNSIGNED_BYTE,e),r.bindTexture(r.TEXTURE_2D,null),n):null}}const St=[],$r=[],Hr={count:0,positions:new Float32Array(0),paletteIndices:new Uint16Array(0)};function st(t,e){return t.id??e}function Zr(t,e){if(!Array.isArray(e)||e.length<3)return!1;const[r,n]=t;let i=!1;for(let o=0,s=e.length-1;o<e.length;s=o++){const[a,l]=e[o],[u,h]=e[s];l>n!=h>n&&r<(u-a)*(n-l)/Math.max(1e-12,h-l)+a&&(i=!i)}return i}function Mt(t,e){for(let r=e.length-1;r>=0;r-=1){const n=e[r];if(n?.coordinates?.length&&Zr(t,n.coordinates))return{region:n,regionIndex:r,regionId:st(n,r)}}return null}function jr({source:t,viewState:e,onViewStateChange:r,onStats:n,onTileError:i,onContextLost:o,onContextRestored:s,debugOverlay:a=!1,debugOverlayStyle:l,fitNonce:u=0,rotationResetNonce:h=0,authToken:b="",ctrlDragRotate:m=!0,pointData:p=null,pointPalette:x=null,roiRegions:w,roiPolygons:T,clipPointsToRois:C=!1,clipMode:F="worker",onClipStats:I,onRoiPointGroups:L,roiPaletteIndexToTermId:pe,interactionLock:ae=!1,drawTool:z="cursor",stampOptions:be,regionStrokeStyle:ue,regionStrokeHoverStyle:Q,regionStrokeActiveStyle:$,resolveRegionStrokeStyle:X,overlayShapes:j,regionLabelStyle:Te,onPointerWorldMove:we,onRegionHover:oe,onRegionClick:ye,onActiveRegionChange:R,onDrawComplete:P,showOverviewMap:M=!1,overviewMapOptions:_,className:V,style:te}){const re=f.useRef(null),A=f.useRef(null),W=f.useRef(null),ne=f.useRef(null),ce=f.useRef(r),Y=f.useRef(n),H=f.useRef(a),[ee,G]=f.useState(!0),[K,c]=f.useState(null),[g,S]=f.useState(null),[E,k]=f.useState(null),v=f.useRef(null),B=f.useRef(0),O=w??St,J=T??$r,le=f.useMemo(()=>({position:"relative",width:"100%",height:"100%",...te}),[te]),Pe=f.useMemo(()=>({position:"absolute",top:8,left:8,zIndex:7,margin:0,padding:"8px 10px",maxWidth:"min(420px, 80%)",pointerEvents:"none",whiteSpace:"pre-wrap",lineHeight:1.35,fontFamily:"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace",fontSize:11,color:"#cde6ff",background:"rgba(6, 12, 20, 0.82)",border:"1px solid rgba(173, 216, 255, 0.28)",borderRadius:8,boxShadow:"0 8px 22px rgba(0,0,0,0.35)",...l}),[l]),Z=f.useMemo(()=>O.length>0?O:J.length===0?St:J.map((y,U)=>({id:U,coordinates:y})),[O,J]),me=f.useMemo(()=>Z.map(y=>y.coordinates),[Z]),[Ce,De]=f.useState(p);f.useEffect(()=>{const y=++B.current;let U=!1;if(!C)return De(p),()=>{U=!0};if(!p||!p.count||!p.positions||!p.paletteIndices)return De(null),()=>{U=!0};if(me.length===0)return De(Hr),I?.({mode:F,durationMs:0,inputCount:p.count,outputCount:0,polygonCount:0}),()=>{U=!0};const N=(D,se)=>{if(U||y!==B.current)return;const $e=D?.drawIndices?D.drawIndices.length:D?.count??0;De(D),I?.({mode:se.mode,durationMs:se.durationMs,inputCount:p.count,outputCount:$e,polygonCount:me.length,usedWebGpu:se.usedWebGpu,candidateCount:se.candidateCount,bridgedToDraw:se.bridgedToDraw})};return(async()=>{if(F==="sync"){const D=performance.now(),se=Ue(p,me);N(se,{mode:"sync",durationMs:performance.now()-D});return}if(F==="hybrid-webgpu"){const D=await zt(p,me,{bridgeToDraw:!0});N(D.data,{mode:D.meta.mode,durationMs:D.meta.durationMs,usedWebGpu:D.meta.usedWebGpu,candidateCount:D.meta.candidateCount,bridgedToDraw:D.meta.bridgedToDraw});return}try{const D=await Wt(p,me);N(D.data,{mode:D.meta.mode,durationMs:D.meta.durationMs})}catch{const D=performance.now(),se=Ue(p,me);N(se,{mode:"sync",durationMs:performance.now()-D})}})(),()=>{U=!0}},[C,F,p,me,I]),f.useMemo(()=>{const y=Number(_?.width??220);return Number.isFinite(y)?Math.max(64,y):220},[_?.width]);const ft=f.useMemo(()=>{const y=Number(_?.height??140);return Number.isFinite(y)?Math.max(48,y):140},[_?.height]),Ee=f.useMemo(()=>{const y=Number(_?.margin??16);return Number.isFinite(y)?Math.max(0,y):16},[_?.margin]),Fe=_?.position||"bottom-right",Ae=f.useCallback(y=>{S(U=>String(U)===String(y)?U:(R?.(y),y))},[R]);f.useEffect(()=>{ce.current=r},[r]),f.useEffect(()=>{Y.current=n},[n]),f.useEffect(()=>{H.current=a,a||k(null)},[a]);const dt=f.useCallback(y=>{Y.current?.(y),H.current&&k(y)},[]),Ot=f.useMemo(()=>E?[`tier ${E.tier} | frame ${E.frameMs?.toFixed(2)??"-"} ms | drawCalls ${E.drawCalls??"-"}`,`tiles visible ${E.visible} | rendered ${E.rendered} | fallback ${E.fallback}`,`cache size ${E.cache} | hit ${E.cacheHits??"-"} | miss ${E.cacheMisses??"-"}`,`queue inflight ${E.inflight} | queued ${E.queued??"-"} | retries ${E.retries??"-"} | failed ${E.failed??"-"} | aborted ${E.aborted??"-"}`,`points ${E.points}`].join(`
|
|
125
|
+
`):"stats: waiting for first frame...",[E]);f.useEffect(()=>{!(g===null?!0:Z.some((ie,D)=>String(st(ie,D))===String(g)))&&g!==null&&Ae(null);const U=v.current;!(U===null?!0:Z.some((ie,D)=>String(st(ie,D))===String(U)))&&U!==null&&(v.current=null,c(null),oe?.({region:null,regionId:null,regionIndex:-1,coordinate:null}))},[Z,g,oe,Ae]);const mt=f.useCallback(y=>{const U=ce.current;U&&U(y),W.current?.(),ne.current?.()},[]);f.useEffect(()=>{if(!M){G(!1);return}G(!0)},[M,t?.id]),f.useEffect(()=>{z!=="cursor"&&v.current!==null&&(v.current=null,c(null),oe?.({region:null,regionId:null,regionIndex:-1,coordinate:null}))},[z,oe]);const Le=f.useCallback((y,U)=>{const N=A.current;if(!N)return null;const ie=N.screenToWorld(y,U);if(!Array.isArray(ie)||ie.length<2)return null;const D=Number(ie[0]),se=Number(ie[1]);return!Number.isFinite(D)||!Number.isFinite(se)?null:[D,se]},[]),Gt=f.useCallback(y=>{const U=y.target===re.current,N=Le(y.clientX,y.clientY);if(we){const $e=!!N&&N[0]>=0&&N[1]>=0&&!!t&&N[0]<=t.width&&N[1]<=t.height;we({coordinate:N,clientX:y.clientX,clientY:y.clientY,insideImage:$e})}if(z!=="cursor")return;if(!U){v.current!==null&&(v.current=null,c(null),oe?.({region:null,regionId:null,regionIndex:-1,coordinate:null}));return}if(!N||!Z.length)return;const ie=Mt(N,Z),D=ie?.regionId??null,se=v.current;String(se)!==String(D)&&(v.current=D,c(D),oe?.({region:ie?.region??null,regionId:D,regionIndex:ie?.regionIndex??-1,coordinate:N}))},[z,Z,Le,oe,we,t]),qt=f.useCallback(()=>{we?.({coordinate:null,clientX:-1,clientY:-1,insideImage:!1}),v.current!==null&&(v.current=null,c(null),oe?.({region:null,regionId:null,regionIndex:-1,coordinate:null}))},[oe,we]),$t=f.useCallback(y=>{if(z!=="cursor"||y.target!==re.current)return;if(!Z.length){Ae(null);return}const U=Le(y.clientX,y.clientY);if(!U)return;const N=Mt(U,Z);if(!N){Ae(null);return}const ie=g!==null&&String(g)===String(N.regionId)?null:N.regionId;Ae(ie),ye?.({region:N.region,regionId:N.regionId,regionIndex:N.regionIndex,coordinate:U})},[z,Z,Le,ye,g,Ae]);return f.useEffect(()=>{const y=re.current;if(!y||!t)return;const U=new Vt(y,t,{onViewStateChange:mt,onStats:dt,onTileError:i,onContextLost:o,onContextRestored:s,authToken:b,ctrlDragRotate:m});return A.current=U,e&&U.setViewState(e),U.setInteractionLock(ae),()=>{U.destroy(),A.current=null}},[t,dt,i,o,s,b,m,mt]),f.useEffect(()=>{const y=A.current;!y||!e||y.setViewState(e)},[e]),f.useEffect(()=>{const y=A.current;y&&y.fitToImage()},[u]),f.useEffect(()=>{const y=A.current;y&&y.resetRotation()},[h]),f.useEffect(()=>{const y=A.current;!y||!x||y.setPointPalette(x)},[x]),f.useEffect(()=>{const y=A.current;y&&y.setPointData(Ce)},[Ce]),f.useEffect(()=>{if(!L)return;const U=Yt(C?Ce:p,Z,{paletteIndexToTermId:pe,includeEmptyRegions:!0});L(U)},[L,C,p,Ce,Z,pe]),f.useEffect(()=>{const y=A.current;y&&y.setInteractionLock(ae)},[ae]),de.jsxs("div",{className:V,style:le,onPointerMove:Gt,onPointerLeave:qt,onClick:$t,children:[de.jsx("canvas",{ref:re,className:"wsi-render-canvas",style:{position:"absolute",inset:0,zIndex:1,width:"100%",height:"100%",display:"block",touchAction:"none",cursor:z==="cursor"&&K!==null?"pointer":ae?"crosshair":"grab"}}),t?de.jsx(Dt,{tool:z,enabled:z!=="cursor",imageWidth:t.width,imageHeight:t.height,imageMpp:t.mpp,imageZoom:t.maxTierZoom,stampOptions:be,projectorRef:A,viewStateSignal:e,persistedRegions:Z,regionStrokeStyle:ue,regionStrokeHoverStyle:Q,regionStrokeActiveStyle:$,resolveRegionStrokeStyle:X,overlayShapes:j,hoveredRegionId:K,activeRegionId:g,regionLabelStyle:Te,invalidateRef:W,onDrawComplete:P}):null,a?de.jsx("pre",{"data-open-plant-debug-overlay":!0,style:Pe,children:Ot}):null,t&&M?ee?de.jsxs(de.Fragment,{children:[de.jsx(Lt,{source:t,projectorRef:A,authToken:b,options:_,invalidateRef:ne}),de.jsx("button",{type:"button","aria-label":"Hide overview map",onClick:()=>G(!1),style:{position:"absolute",zIndex:6,...Fe.includes("left")?{left:Ee}:{right:Ee},...Fe.includes("top")?{top:Ee+ft+8}:{bottom:Ee+ft+8},width:20,height:20,borderRadius:999,border:"1px solid rgba(255,255,255,0.4)",background:"rgba(8, 14, 22, 0.9)",color:"#fff",fontSize:13,lineHeight:1,cursor:"pointer",padding:0},children:"×"})]}):de.jsx("button",{type:"button","aria-label":"Show overview map",onClick:()=>G(!0),style:{position:"absolute",zIndex:6,...Fe.includes("left")?{left:Ee}:{right:Ee},...Fe.includes("top")?{top:Ee}:{bottom:Ee},height:24,minWidth:40,borderRadius:999,border:"1px solid rgba(255,255,255,0.45)",background:"rgba(8, 14, 22, 0.9)",color:"#dff8ff",fontSize:11,fontWeight:700,cursor:"pointer",padding:"0 8px"},children:"Map"}):null]})}exports.DEFAULT_POINT_COLOR=at;exports.DrawLayer=Dt;exports.M1TileRenderer=Ct;exports.OverviewMap=Lt;exports.TileScheduler=Xt;exports.TileViewerCanvas=Tr;exports.WsiTileRenderer=Vt;exports.WsiViewerCanvas=jr;exports.buildTermPalette=ir;exports.calcScaleLength=tr;exports.calcScaleResolution=ut;exports.clamp=q;exports.closeRing=xe;exports.computeRoiPointGroups=Yt;exports.createCircle=nt;exports.createRectangle=rt;exports.filterPointDataByPolygons=Ue;exports.filterPointDataByPolygonsHybrid=zt;exports.filterPointDataByPolygonsInWorker=Wt;exports.getWebGpuCapabilities=Br;exports.hexToRgba=At;exports.isSameViewState=rr;exports.normalizeImageInfo=xr;exports.prefilterPointsByBoundsWebGpu=Nt;exports.terminateRoiClipWorker=zr;exports.toBearerToken=nr;exports.toTileUrl=ct;
|
|
126
126
|
//# sourceMappingURL=index.cjs.map
|