open-plant 1.3.3 → 1.3.5
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/assets/roi-clip-worker-BuNuUQQg.js +2 -0
- package/dist/assets/roi-clip-worker-BuNuUQQg.js.map +1 -0
- package/dist/index.cjs +7 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +3073 -2741
- package/dist/index.js.map +1 -1
- package/dist/types/index.d.ts +5 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/react/draw-layer-label.d.ts +3 -3
- package/dist/types/react/draw-layer-label.d.ts.map +1 -1
- package/dist/types/react/draw-layer-types.d.ts +2 -0
- package/dist/types/react/draw-layer-types.d.ts.map +1 -1
- package/dist/types/react/draw-layer.d.ts +2 -2
- package/dist/types/react/draw-layer.d.ts.map +1 -1
- package/dist/types/react/wsi-region-hit-utils.d.ts +2 -2
- package/dist/types/react/wsi-region-hit-utils.d.ts.map +1 -1
- package/dist/types/react/wsi-viewer-canvas.d.ts +3 -2
- package/dist/types/react/wsi-viewer-canvas.d.ts.map +1 -1
- package/dist/types/wsi/brush-stroke.d.ts.map +1 -1
- package/dist/types/wsi/roi-geometry.d.ts.map +1 -1
- package/dist/types/wsi/roi-term-stats.d.ts.map +1 -1
- package/dist/types/wsi/spatial-index.d.ts +14 -0
- package/dist/types/wsi/spatial-index.d.ts.map +1 -0
- package/dist/types/wsi/webgpu.d.ts.map +1 -1
- package/dist/types/wsi/wkt.d.ts +12 -0
- package/dist/types/wsi/wkt.d.ts.map +1 -0
- package/dist/types/wsi/wsi-tile-cache.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/assets/roi-clip-worker-BDVQwN2T.js +0 -2
- package/dist/assets/roi-clip-worker-BDVQwN2T.js.map +0 -1
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
(function(){"use strict";function I(n){return typeof n=="number"&&Number.isFinite(n)}function b(n){return Array.isArray(n)&&n.length>=2&&I(n[0])&&I(n[1])}function X(n){if(!Array.isArray(n)||n.length<3)return[];const t=[];for(const i of n){if(!Array.isArray(i)||i.length<2)continue;const o=Number(i[0]),s=Number(i[1]);if(!Number.isFinite(o)||!Number.isFinite(s))continue;const f=t[t.length-1];f&&f[0]===o&&f[1]===s||t.push([o,s])}if(t.length<3)return[];const e=t[0],r=t[t.length-1];return(e[0]!==r[0]||e[1]!==r[1])&&t.push([e[0],e[1]]),t.length>=4?t:[]}function g(n){if(!Array.isArray(n)||n.length<4)return 0;let t=0;for(let e=0;e<n.length-1;e+=1){const r=n[e],i=n[e+1];t+=r[0]*i[1]-i[0]*r[1]}return t*.5}function x(n){if(!Array.isArray(n)||n.length===0)return[];const t=[];for(const o of n){const s=X(o);s.length>=4&&t.push(s)}if(t.length===0)return[];if(t.length===1)return[t[0]];let e=0,r=0;for(let o=0;o<t.length;o+=1){const s=Math.abs(g(t[o]));s<=r||(r=s,e=o)}const i=[t[e]];for(let o=0;o<t.length;o+=1)o!==e&&i.push(t[o]);return i}function z(n){if(!Array.isArray(n)||n.length===0)return[];const t=n[0];if(b(t)){const i=x([n]);return i.length>0?[i]:[]}if(!Array.isArray(t)||t.length===0)return[];const e=t[0];if(b(e)){const i=x(n);return i.length>0?[i]:[]}if(!Array.isArray(e)||e.length===0||!b(e[0]))return[];const r=[];for(const i of n){const o=x(i);o.length>0&&r.push(o)}return r}function F(n,t,e){let r=!1;for(let i=0,o=e.length-1;i<e.length;o=i,i+=1){const s=e[i][0],f=e[i][1],c=e[o][0],u=e[o][1];if(f===u||f>t==u>t)continue;n<(c-s)*(t-f)/(u-f)+s&&(r=!r)}return r}function U(n){const t=[];for(const e of n??[]){const r=z(e);for(const i of r){const o=i[0];if(!o||o.length<4)continue;let s=1/0,f=1/0,c=-1/0,u=-1/0;for(const[l,h]of o)l<s&&(s=l),l>c&&(c=l),h<f&&(f=h),h>u&&(u=h);if(!Number.isFinite(s)||!Number.isFinite(f)||!Number.isFinite(c)||!Number.isFinite(u))continue;let a=Math.abs(g(o));for(let l=1;l<i.length;l+=1)a-=Math.abs(g(i[l]));t.push({outer:o,holes:i.slice(1),minX:s,minY:f,maxX:c,maxY:u,area:Math.max(1e-6,a)})}}return t}function S(n,t,e){if(n<e.minX||n>e.maxX||t<e.minY||t>e.maxY||!F(n,t,e.outer))return!1;for(const r of e.holes)if(F(n,t,r))return!1;return!0}function N(n,t,e){for(const r of e)if(S(n,t,r))return!0;return!1}function y(){return typeof performance<"u"&&typeof performance.now=="function"?performance.now():Date.now()}function Y(n){if(n instanceof Error)return n.message;try{return String(n)}catch{return"unknown worker error"}}const A=self;function j(n){const t=y(),e=Math.max(0,Math.floor(n.count)),r=new Float32Array(n.positions),i=new Uint16Array(n.paletteIndices),o=n.fillModes?new Uint8Array(n.fillModes):null,s=n.ids?new Uint32Array(n.ids):null,f=Math.floor(r.length/2),c=Math.max(0,Math.min(e,f,i.length,o?o.length:Number.MAX_SAFE_INTEGER)),u=o instanceof Uint8Array&&o.length>=c,a=s instanceof Uint32Array&&s.length>=c,l=U(n.polygons??[]);if(c===0||l.length===0){const d={type:"roi-clip-success",id:n.id,count:0,positions:new Float32Array(0).buffer,paletteIndices:new Uint16Array(0).buffer,durationMs:y()-t};return u&&(d.fillModes=new Uint8Array(0).buffer),a&&(d.ids=new Uint32Array(0).buffer),d}const h=new Float32Array(c*2),P=new Uint16Array(c),M=u?new Uint8Array(c):null,m=a?new Uint32Array(c):null;let p=0;for(let d=0;d<c;d+=1){const q=r[d*2],C=r[d*2+1];N(q,C,l)&&(h[p*2]=q,h[p*2+1]=C,P[p]=i[d],M&&(M[p]=o[d]),m&&(m[p]=s[d]),p+=1)}const T=h.slice(0,p*2),B=P.slice(0,p),R=M?M.slice(0,p):null,E=m?m.slice(0,p):null,w={type:"roi-clip-success",id:n.id,count:p,positions:T.buffer,paletteIndices:B.buffer,durationMs:y()-t};return R&&(w.fillModes=R.buffer),E&&(w.ids=E.buffer),w}function k(n){const t=y(),e=Math.max(0,Math.floor(n.count)),r=new Float32Array(n.positions),i=Math.floor(r.length/2),o=Math.max(0,Math.min(e,i)),s=U(n.polygons??[]);if(o===0||s.length===0)return{type:"roi-clip-index-success",id:n.id,count:0,indices:new Uint32Array(0).buffer,durationMs:y()-t};const f=new Uint32Array(o);let c=0;for(let a=0;a<o;a+=1){const l=r[a*2],h=r[a*2+1];N(l,h,s)&&(f[c]=a,c+=1)}const u=f.slice(0,c);return{type:"roi-clip-index-success",id:n.id,count:c,indices:u.buffer,durationMs:y()-t}}A.addEventListener("message",n=>{const t=n.data;if(!(!t||t.type!=="roi-clip-request"&&t.type!=="roi-clip-index-request"))try{if(t.type==="roi-clip-index-request"){const i=k(t);A.postMessage(i,[i.indices]);return}const e=j(t),r=[e.positions,e.paletteIndices];e.fillModes&&r.push(e.fillModes),e.ids&&r.push(e.ids),A.postMessage(e,r)}catch(e){const r={type:"roi-clip-failure",id:t.id,error:Y(e)};A.postMessage(r)}})})();
|
|
2
|
+
//# sourceMappingURL=roi-clip-worker-BuNuUQQg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"roi-clip-worker-BuNuUQQg.js","sources":["../src/wsi/roi-geometry.ts","../src/wsi/utils.ts","../src/workers/roi-clip-worker.ts"],"sourcesContent":["import type { WsiRegionCoordinates } from \"./types\";\n\nexport type RoiCoordinate = [number, number];\nexport type RoiLinearRing = RoiCoordinate[];\nexport type RoiPolygonRings = RoiLinearRing[];\nexport type RoiMultiPolygon = RoiPolygonRings[];\nexport type RoiGeometry = RoiLinearRing | RoiPolygonRings | RoiMultiPolygon;\n\nexport function toRoiGeometry(coords: WsiRegionCoordinates | null | undefined): RoiGeometry | null | undefined;\nexport function toRoiGeometry(coords: unknown): RoiGeometry | null | undefined;\nexport function toRoiGeometry(coords: unknown): RoiGeometry | null | undefined {\n\tif (coords == null) return null;\n\tif (isLinearRing(coords) || isPolygonRings(coords) || isMultiPolygon(coords)) {\n\t\treturn coords;\n\t}\n\treturn null;\n}\n\nexport interface PreparedRoiPolygon {\n\touter: RoiLinearRing;\n\tholes: RoiLinearRing[];\n\tminX: number;\n\tminY: number;\n\tmaxX: number;\n\tmaxY: number;\n\tarea: number;\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n\treturn typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction isCoordinatePair(value: unknown): value is RoiCoordinate {\n\treturn (\n\t\tArray.isArray(value) &&\n\t\tvalue.length >= 2 &&\n\t\tisFiniteNumber(value[0]) &&\n\t\tisFiniteNumber(value[1])\n\t);\n}\n\nfunction isLinearRing(value: unknown): value is RoiLinearRing {\n\treturn Array.isArray(value) && value.length > 0 && value.every(point => isCoordinatePair(point));\n}\n\nfunction isPolygonRings(value: unknown): value is RoiPolygonRings {\n\treturn Array.isArray(value) && value.length > 0 && value.every(ring => isLinearRing(ring));\n}\n\nfunction isMultiPolygon(value: unknown): value is RoiMultiPolygon {\n\treturn Array.isArray(value) && value.length > 0 && value.every(polygon => isPolygonRings(polygon));\n}\n\nexport function closeRoiRing(coordinates: readonly RoiCoordinate[]): RoiLinearRing {\n\tif (!Array.isArray(coordinates) || coordinates.length < 3) return [];\n\tconst out: RoiLinearRing = [];\n\tfor (const point of coordinates) {\n\t\tif (!Array.isArray(point) || point.length < 2) continue;\n\t\tconst x = Number(point[0]);\n\t\tconst y = Number(point[1]);\n\t\tif (!Number.isFinite(x) || !Number.isFinite(y)) continue;\n\t\tconst prev = out[out.length - 1];\n\t\tif (prev && prev[0] === x && prev[1] === y) continue;\n\t\tout.push([x, y]);\n\t}\n\tif (out.length < 3) return [];\n\tconst first = out[0];\n\tconst last = out[out.length - 1];\n\tif (first[0] !== last[0] || first[1] !== last[1]) {\n\t\tout.push([first[0], first[1]]);\n\t}\n\treturn out.length >= 4 ? out : [];\n}\n\nexport function polygonSignedArea(ring: RoiLinearRing): number {\n\tif (!Array.isArray(ring) || ring.length < 4) return 0;\n\tlet sum = 0;\n\tfor (let i = 0; i < ring.length - 1; i += 1) {\n\t\tconst a = ring[i];\n\t\tconst b = ring[i + 1];\n\t\tsum += a[0] * b[1] - b[0] * a[1];\n\t}\n\treturn sum * 0.5;\n}\n\nfunction normalizePolygonRings(rings: RoiPolygonRings): RoiPolygonRings {\n\tif (!Array.isArray(rings) || rings.length === 0) return [];\n\tconst normalized: RoiLinearRing[] = [];\n\tfor (const ring of rings) {\n\t\tconst closed = closeRoiRing(ring);\n\t\tif (closed.length >= 4) normalized.push(closed);\n\t}\n\tif (normalized.length === 0) return [];\n\tif (normalized.length === 1) return [normalized[0]];\n\n\tlet outerIndex = 0;\n\tlet outerArea = 0;\n\tfor (let i = 0; i < normalized.length; i += 1) {\n\t\tconst area = Math.abs(polygonSignedArea(normalized[i]));\n\t\tif (area <= outerArea) continue;\n\t\touterArea = area;\n\t\touterIndex = i;\n\t}\n\n\tconst out: RoiPolygonRings = [normalized[outerIndex]];\n\tfor (let i = 0; i < normalized.length; i += 1) {\n\t\tif (i === outerIndex) continue;\n\t\tout.push(normalized[i]);\n\t}\n\treturn out;\n}\n\nexport function normalizeRoiGeometry(geometry: RoiGeometry | null | undefined): RoiMultiPolygon {\n\tif (!Array.isArray(geometry) || geometry.length === 0) return [];\n\n\tconst first = geometry[0];\n\tif (isCoordinatePair(first)) {\n\t\tconst polygon = normalizePolygonRings([geometry as RoiLinearRing]);\n\t\treturn polygon.length > 0 ? [polygon] : [];\n\t}\n\n\tif (!Array.isArray(first) || first.length === 0) return [];\n\tconst second = first[0];\n\tif (isCoordinatePair(second)) {\n\t\tconst polygon = normalizePolygonRings(geometry as RoiPolygonRings);\n\t\treturn polygon.length > 0 ? [polygon] : [];\n\t}\n\n\tif (!Array.isArray(second) || second.length === 0 || !isCoordinatePair(second[0])) {\n\t\treturn [];\n\t}\n\n\tconst out: RoiMultiPolygon = [];\n\tfor (const polygon of geometry as RoiMultiPolygon) {\n\t\tconst normalized = normalizePolygonRings(polygon);\n\t\tif (normalized.length > 0) out.push(normalized);\n\t}\n\treturn out;\n}\n\nexport function pointInRing(x: number, y: number, ring: RoiLinearRing): boolean {\n\tlet inside = false;\n\tfor (let i = 0, j = ring.length - 1; i < ring.length; j = i, i += 1) {\n\t\tconst xi = ring[i][0];\n\t\tconst yi = ring[i][1];\n\t\tconst xj = ring[j][0];\n\t\tconst yj = ring[j][1];\n\t\tif (yi === yj) continue;\n\t\tif ((yi > y) === (yj > y)) continue;\n\t\tconst intersect = x < ((xj - xi) * (y - yi)) / (yj - yi) + xi;\n\t\tif (intersect) inside = !inside;\n\t}\n\treturn inside;\n}\n\nexport function pointInPolygonWithHoles(\n\tx: number,\n\ty: number,\n\tpolygon: RoiPolygonRings,\n): boolean {\n\tif (!Array.isArray(polygon) || polygon.length === 0) return false;\n\tconst outer = polygon[0];\n\tif (!outer || outer.length < 4) return false;\n\tif (!pointInRing(x, y, outer)) return false;\n\tfor (let i = 1; i < polygon.length; i += 1) {\n\t\tconst hole = polygon[i];\n\t\tif (!hole || hole.length < 4) continue;\n\t\tif (pointInRing(x, y, hole)) return false;\n\t}\n\treturn true;\n}\n\nexport function prepareRoiPolygons(\n\tgeometries: readonly (RoiGeometry | null | undefined)[] | null | undefined,\n): PreparedRoiPolygon[] {\n\tconst prepared: PreparedRoiPolygon[] = [];\n\tfor (const geometry of geometries ?? []) {\n\t\tconst multipolygon = normalizeRoiGeometry(geometry);\n\t\tfor (const polygon of multipolygon) {\n\t\t\tconst outer = polygon[0];\n\t\t\tif (!outer || outer.length < 4) continue;\n\t\t\tlet minX = Infinity;\n\t\t\tlet minY = Infinity;\n\t\t\tlet maxX = -Infinity;\n\t\t\tlet maxY = -Infinity;\n\t\t\tfor (const [x, y] of outer) {\n\t\t\t\tif (x < minX) minX = x;\n\t\t\t\tif (x > maxX) maxX = x;\n\t\t\t\tif (y < minY) minY = y;\n\t\t\t\tif (y > maxY) maxY = y;\n\t\t\t}\n\t\t\tif (\n\t\t\t\t!Number.isFinite(minX) ||\n\t\t\t\t!Number.isFinite(minY) ||\n\t\t\t\t!Number.isFinite(maxX) ||\n\t\t\t\t!Number.isFinite(maxY)\n\t\t\t) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tlet area = Math.abs(polygonSignedArea(outer));\n\t\t\tfor (let i = 1; i < polygon.length; i += 1) {\n\t\t\t\tarea -= Math.abs(polygonSignedArea(polygon[i]));\n\t\t\t}\n\t\t\tprepared.push({\n\t\t\t\touter,\n\t\t\t\tholes: polygon.slice(1),\n\t\t\t\tminX,\n\t\t\t\tminY,\n\t\t\t\tmaxX,\n\t\t\t\tmaxY,\n\t\t\t\tarea: Math.max(1e-6, area),\n\t\t\t});\n\t\t}\n\t}\n\treturn prepared;\n}\n\nexport function pointInPreparedPolygon(\n\tx: number,\n\ty: number,\n\tpolygon: PreparedRoiPolygon,\n): boolean {\n\tif (x < polygon.minX || x > polygon.maxX || y < polygon.minY || y > polygon.maxY) {\n\t\treturn false;\n\t}\n\tif (!pointInRing(x, y, polygon.outer)) return false;\n\tfor (const hole of polygon.holes) {\n\t\tif (pointInRing(x, y, hole)) return false;\n\t}\n\treturn true;\n}\n\nexport function pointInAnyPreparedPolygon(\n\tx: number,\n\ty: number,\n\tpolygons: readonly PreparedRoiPolygon[],\n): boolean {\n\tfor (const polygon of polygons) {\n\t\tif (!pointInPreparedPolygon(x, y, polygon)) continue;\n\t\treturn true;\n\t}\n\treturn false;\n}\n","import { DEFAULT_POINT_COLOR } from \"./constants\";\nimport type { TermPalette, WsiPointData, WsiViewState } from \"./types\";\n\nexport function clamp(value: number, min: number, max: number): number {\n\treturn Math.max(min, Math.min(max, value));\n}\n\nexport function calcScaleResolution(\n\timageMpp: number,\n\timageZoom: number,\n\tcurrentZoom: number,\n): number {\n\tconst mpp = Number(imageMpp);\n\tconst z0 = Number(imageZoom);\n\tconst z1 = Number(currentZoom);\n\tif (!Number.isFinite(mpp) || mpp <= 0) return 1;\n\tif (!Number.isFinite(z0) || !Number.isFinite(z1)) return mpp;\n\treturn Math.pow(2, z0 - z1) * mpp;\n}\n\nexport function calcScaleLength(\n\timageMpp: number,\n\timageZoom: number,\n\tcurrentZoom: number,\n): string {\n\tconst resolution = calcScaleResolution(imageMpp, imageZoom, currentZoom);\n\tlet length = 100 * resolution;\n\tif (Number(imageMpp)) {\n\t\tlet unit = \"μm\";\n\t\tif (length > 1000) {\n\t\t\tlength /= 1000;\n\t\t\tunit = \"mm\";\n\t\t}\n\t\treturn `${length.toPrecision(3)} ${unit}`;\n\t}\n\treturn `${Math.round(length * 1000) / 1000} pixels`;\n}\n\nexport function nowMs(): number {\n\tif (typeof performance !== \"undefined\" && typeof performance.now === \"function\") {\n\t\treturn performance.now();\n\t}\n\treturn Date.now();\n}\n\nexport function sanitizePointCount(pointData: WsiPointData): number {\n\tconst fillModesLength =\n\t\tpointData.fillModes instanceof Uint8Array\n\t\t\t? pointData.fillModes.length\n\t\t\t: Number.MAX_SAFE_INTEGER;\n\treturn Math.max(\n\t\t0,\n\t\tMath.min(\n\t\t\tMath.floor(pointData.count ?? 0),\n\t\t\tMath.floor((pointData.positions?.length ?? 0) / 2),\n\t\t\tpointData.paletteIndices?.length ?? 0,\n\t\t\tfillModesLength,\n\t\t),\n\t);\n}\n\nexport function isSameViewState(\n\ta: Partial<WsiViewState> | null | undefined,\n\tb: Partial<WsiViewState> | null | undefined,\n): boolean {\n\tif (!a && !b) return true;\n\tif (!a || !b) return false;\n\treturn (\n\t\tMath.abs((a.zoom ?? 0) - (b.zoom ?? 0)) < 1e-6 &&\n\t\tMath.abs((a.offsetX ?? 0) - (b.offsetX ?? 0)) < 1e-6 &&\n\t\tMath.abs((a.offsetY ?? 0) - (b.offsetY ?? 0)) < 1e-6 &&\n\t\tMath.abs((a.rotationDeg ?? 0) - (b.rotationDeg ?? 0)) < 1e-6\n\t);\n}\n\nexport function toBearerToken(value: string | null | undefined): string {\n\tconst trimmed = String(value ?? \"\").trim();\n\tif (!trimmed) return \"\";\n\tif (/^bearer\\s+/i.test(trimmed)) {\n\t\tconst token = trimmed.replace(/^bearer\\s+/i, \"\").trim();\n\t\treturn token ? `Bearer ${token}` : \"\";\n\t}\n\treturn `Bearer ${trimmed}`;\n}\n\nexport function hexToRgba(\n\thex: string | null | undefined,\n): [number, number, number, number] {\n\tconst value = String(hex ?? \"\").trim();\n\tconst match = value.match(/^#?([0-9a-fA-F]{6})$/);\n\tif (!match) return [...DEFAULT_POINT_COLOR];\n\n\tconst n = Number.parseInt(match[1], 16);\n\treturn [(n >> 16) & 255, (n >> 8) & 255, n & 255, 255];\n}\n\nexport function buildTermPalette(\n\tterms:\n\t\t| Array<{ termId?: string | null; termColor?: string | null }>\n\t\t| null\n\t\t| undefined,\n): TermPalette {\n\tconst palette: Array<[number, number, number, number]> = [\n\t\t[...DEFAULT_POINT_COLOR],\n\t];\n\tconst termToPaletteIndex = new Map<string, number>();\n\n\tfor (const term of terms ?? []) {\n\t\tconst termId = String(term?.termId ?? \"\");\n\t\tif (!termId || termToPaletteIndex.has(termId)) continue;\n\n\t\ttermToPaletteIndex.set(termId, palette.length);\n\t\tpalette.push(hexToRgba(term?.termColor));\n\t}\n\n\tconst colors = new Uint8Array(palette.length * 4);\n\tfor (let i = 0; i < palette.length; i += 1) {\n\t\tcolors[i * 4] = palette[i][0];\n\t\tcolors[i * 4 + 1] = palette[i][1];\n\t\tcolors[i * 4 + 2] = palette[i][2];\n\t\tcolors[i * 4 + 3] = palette[i][3];\n\t}\n\n\treturn { colors, termToPaletteIndex };\n}\n","import type {\n RoiClipWorkerDataRequest,\n RoiClipWorkerIndexRequest,\n RoiClipWorkerIndexSuccess,\n RoiClipWorkerRequest,\n RoiClipWorkerResponse,\n RoiClipWorkerSuccess,\n} from \"../wsi/point-clip-worker-protocol\";\nimport { pointInAnyPreparedPolygon, prepareRoiPolygons } from \"../wsi/roi-geometry\";\nimport { nowMs } from \"../wsi/utils\";\n\nfunction toErrorMessage(error: unknown): string {\n if (error instanceof Error) return error.message;\n try {\n return String(error);\n } catch {\n return \"unknown worker error\";\n }\n}\n\ninterface WorkerScope {\n postMessage(message: unknown, transfer?: Transferable[]): void;\n addEventListener(type: \"message\", listener: (event: MessageEvent<RoiClipWorkerRequest>) => void): void;\n}\n\nconst workerScope = self as unknown as WorkerScope;\n\nfunction handleDataRequest(msg: RoiClipWorkerDataRequest): RoiClipWorkerSuccess {\n const start = nowMs();\n const count = Math.max(0, Math.floor(msg.count));\n const positions = new Float32Array(msg.positions);\n const terms = new Uint16Array(msg.paletteIndices);\n const fillModes = msg.fillModes ? new Uint8Array(msg.fillModes) : null;\n const ids = msg.ids ? new Uint32Array(msg.ids) : null;\n\n const maxCountByPositions = Math.floor(positions.length / 2);\n const safeCount = Math.max(0, Math.min(count, maxCountByPositions, terms.length, fillModes ? fillModes.length : Number.MAX_SAFE_INTEGER));\n const hasFillModes = fillModes instanceof Uint8Array && fillModes.length >= safeCount;\n const hasIds = ids instanceof Uint32Array && ids.length >= safeCount;\n const prepared = prepareRoiPolygons(msg.polygons ?? []);\n\n if (safeCount === 0 || prepared.length === 0) {\n const empty: RoiClipWorkerSuccess = {\n type: \"roi-clip-success\",\n id: msg.id,\n count: 0,\n positions: new Float32Array(0).buffer,\n paletteIndices: new Uint16Array(0).buffer,\n durationMs: nowMs() - start,\n };\n if (hasFillModes) {\n empty.fillModes = new Uint8Array(0).buffer;\n }\n if (hasIds) {\n empty.ids = new Uint32Array(0).buffer;\n }\n return empty;\n }\n\n const nextPositions = new Float32Array(safeCount * 2);\n const nextTerms = new Uint16Array(safeCount);\n const nextFillModes = hasFillModes ? new Uint8Array(safeCount) : null;\n const nextIds = hasIds ? new Uint32Array(safeCount) : null;\n let cursor = 0;\n\n for (let i = 0; i < safeCount; i += 1) {\n const x = positions[i * 2];\n const y = positions[i * 2 + 1];\n if (!pointInAnyPreparedPolygon(x, y, prepared)) continue;\n nextPositions[cursor * 2] = x;\n nextPositions[cursor * 2 + 1] = y;\n nextTerms[cursor] = terms[i];\n if (nextFillModes) {\n nextFillModes[cursor] = fillModes![i];\n }\n if (nextIds) {\n nextIds[cursor] = ids![i];\n }\n cursor += 1;\n }\n\n const outPositions = nextPositions.slice(0, cursor * 2);\n const outTerms = nextTerms.slice(0, cursor);\n const outFillModes = nextFillModes ? nextFillModes.slice(0, cursor) : null;\n const outIds = nextIds ? nextIds.slice(0, cursor) : null;\n\n const success: RoiClipWorkerSuccess = {\n type: \"roi-clip-success\",\n id: msg.id,\n count: cursor,\n positions: outPositions.buffer,\n paletteIndices: outTerms.buffer,\n durationMs: nowMs() - start,\n };\n if (outFillModes) {\n success.fillModes = outFillModes.buffer;\n }\n if (outIds) {\n success.ids = outIds.buffer;\n }\n return success;\n}\n\nfunction handleIndexRequest(msg: RoiClipWorkerIndexRequest): RoiClipWorkerIndexSuccess {\n const start = nowMs();\n const count = Math.max(0, Math.floor(msg.count));\n const positions = new Float32Array(msg.positions);\n const maxCountByPositions = Math.floor(positions.length / 2);\n const safeCount = Math.max(0, Math.min(count, maxCountByPositions));\n const prepared = prepareRoiPolygons(msg.polygons ?? []);\n\n if (safeCount === 0 || prepared.length === 0) {\n return {\n type: \"roi-clip-index-success\",\n id: msg.id,\n count: 0,\n indices: new Uint32Array(0).buffer,\n durationMs: nowMs() - start,\n };\n }\n\n const out = new Uint32Array(safeCount);\n let cursor = 0;\n for (let i = 0; i < safeCount; i += 1) {\n const x = positions[i * 2];\n const y = positions[i * 2 + 1];\n if (!pointInAnyPreparedPolygon(x, y, prepared)) continue;\n out[cursor] = i;\n cursor += 1;\n }\n\n const outIndices = out.slice(0, cursor);\n return {\n type: \"roi-clip-index-success\",\n id: msg.id,\n count: cursor,\n indices: outIndices.buffer,\n durationMs: nowMs() - start,\n };\n}\n\nworkerScope.addEventListener(\"message\", (event: MessageEvent<RoiClipWorkerRequest>) => {\n const data = event.data;\n if (!data || (data.type !== \"roi-clip-request\" && data.type !== \"roi-clip-index-request\")) return;\n\n try {\n if (data.type === \"roi-clip-index-request\") {\n const response = handleIndexRequest(data);\n workerScope.postMessage(response, [response.indices]);\n return;\n }\n const response = handleDataRequest(data);\n const transfer: Transferable[] = [response.positions, response.paletteIndices];\n if (response.fillModes) {\n transfer.push(response.fillModes);\n }\n if (response.ids) {\n transfer.push(response.ids);\n }\n workerScope.postMessage(response, transfer);\n } catch (error) {\n const fail: RoiClipWorkerResponse = {\n type: \"roi-clip-failure\",\n id: data.id,\n error: toErrorMessage(error),\n };\n workerScope.postMessage(fail);\n }\n});\n"],"names":["isFiniteNumber","value","isCoordinatePair","closeRoiRing","coordinates","out","point","x","y","prev","first","last","polygonSignedArea","ring","sum","i","a","b","normalizePolygonRings","rings","normalized","closed","outerIndex","outerArea","area","normalizeRoiGeometry","geometry","polygon","second","pointInRing","inside","j","xi","yi","xj","yj","prepareRoiPolygons","geometries","prepared","multipolygon","outer","minX","minY","maxX","maxY","pointInPreparedPolygon","hole","pointInAnyPreparedPolygon","polygons","nowMs","toErrorMessage","error","workerScope","handleDataRequest","msg","start","count","positions","terms","fillModes","ids","maxCountByPositions","safeCount","hasFillModes","hasIds","empty","nextPositions","nextTerms","nextFillModes","nextIds","cursor","outPositions","outTerms","outFillModes","outIds","success","handleIndexRequest","outIndices","event","data","response","transfer","fail"],"mappings":"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"}
|