open-plant 1.2.9 → 1.2.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -190,6 +190,7 @@ import { WsiViewerCanvas } from "open-plant";
190
190
 
191
191
  `brushOptions.clickSelectRoi`를 `true`로 두면 브러시 모드에서 클릭(드래그 없음) 시 ROI hit-test로 선택을 시도하고, ROI 밖 클릭은 기존 브러시 점찍기 동작을 유지합니다.
192
192
  `brushOptions.edgeDetail`/`edgeSmoothing`으로 브러시 경계의 해상도와 스무딩 정도를 조절할 수 있습니다.
193
+ `pointData.fillModes`(선택, `Uint8Array`)를 주면 포인트별 렌더 모드를 제어할 수 있습니다. `0`은 ring(stroked), `1`은 solid(fill)이며 `0`이 아닌 값은 solid로 처리됩니다.
193
194
  `roiRegions[].coordinates`는 단일 링뿐 아니라 hole이 포함된 Polygon(`[[outer],[hole1], ...]`)과 MultiPolygon(`[[[...]], [[...]], ...]`)도 지원합니다.
194
195
 
195
196
  ### `<DrawLayer>`
@@ -0,0 +1,2 @@
1
+ (function(){"use strict";function w(n){return typeof n=="number"&&Number.isFinite(n)}function X(n){return Array.isArray(n)&&n.length>=2&&w(n[0])&&w(n[1])}function I(n){return Array.isArray(n)&&n.length>0&&n.every(t=>X(t))}function F(n){return Array.isArray(n)&&n.length>0&&n.every(t=>I(t))}function z(n){return Array.isArray(n)&&n.length>0&&n.every(t=>F(t))}function Y(n){if(!Array.isArray(n)||n.length<3)return[];const t=[];for(const r of n){if(!Array.isArray(r)||r.length<2)continue;const i=Number(r[0]),s=Number(r[1]);if(!Number.isFinite(i)||!Number.isFinite(s))continue;const f=t[t.length-1];f&&f[0]===i&&f[1]===s||t.push([i,s])}if(t.length<3)return[];const e=t[0],o=t[t.length-1];return(e[0]!==o[0]||e[1]!==o[1])&&t.push([e[0],e[1]]),t.length>=4?t:[]}function m(n){if(!Array.isArray(n)||n.length<4)return 0;let t=0;for(let e=0;e<n.length-1;e+=1){const o=n[e],r=n[e+1];t+=o[0]*r[1]-r[0]*o[1]}return t*.5}function b(n){if(!Array.isArray(n)||n.length===0)return[];const t=[];for(const i of n){const s=Y(i);s.length>=4&&t.push(s)}if(t.length===0)return[];if(t.length===1)return[t[0]];let e=0,o=0;for(let i=0;i<t.length;i+=1){const s=Math.abs(m(t[i]));s<=o||(o=s,e=i)}const r=[t[e]];for(let i=0;i<t.length;i+=1)i!==e&&r.push(t[i]);return r}function j(n){if(!n)return[];if(I(n)){const t=b([n]);return t.length>0?[t]:[]}if(F(n)){const t=b(n);return t.length>0?[t]:[]}if(z(n)){const t=[];for(const e of n){const o=b(e);o.length>0&&t.push(o)}return t}return[]}function N(n,t,e){let o=!1;for(let r=0,i=e.length-1;r<e.length;i=r,r+=1){const s=e[r][0],f=e[r][1],c=e[i][0],l=e[i][1];f>t!=l>t&&n<(c-s)*(t-f)/(l-f||Number.EPSILON)+s&&(o=!o)}return o}function P(n){const t=[];for(const e of n??[]){const o=j(e);for(const r of o){const i=r[0];if(!i||i.length<4)continue;let s=1/0,f=1/0,c=-1/0,l=-1/0;for(const[u,h]of i)u<s&&(s=u),u>c&&(c=u),h<f&&(f=h),h>l&&(l=h);if(!Number.isFinite(s)||!Number.isFinite(f)||!Number.isFinite(c)||!Number.isFinite(l))continue;let a=Math.abs(m(i));for(let u=1;u<r.length;u+=1)a-=Math.abs(m(r[u]));t.push({outer:i,holes:r.slice(1),minX:s,minY:f,maxX:c,maxY:l,area:Math.max(1e-6,a)})}}return t}function k(n,t,e){if(n<e.minX||n>e.maxX||t<e.minY||t>e.maxY||!N(n,t,e.outer))return!1;for(const o of e.holes)if(N(n,t,o))return!1;return!0}function U(n,t,e){for(const o of e)if(k(n,t,o))return!0;return!1}function y(){return typeof performance<"u"&&typeof performance.now=="function"?performance.now():Date.now()}function L(n){if(n instanceof Error)return n.message;try{return String(n)}catch{return"unknown worker error"}}const A=self;function T(n){const t=y(),e=Math.max(0,Math.floor(n.count)),o=new Float32Array(n.positions),r=new Uint16Array(n.paletteIndices),i=n.fillModes?new Uint8Array(n.fillModes):null,s=n.ids?new Uint32Array(n.ids):null,f=Math.floor(o.length/2),c=Math.max(0,Math.min(e,f,r.length,i?i.length:Number.MAX_SAFE_INTEGER)),l=i instanceof Uint8Array&&i.length>=c,a=s instanceof Uint32Array&&s.length>=c,u=P(n.polygons??[]);if(c===0||u.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 l&&(d.fillModes=new Uint8Array(0).buffer),a&&(d.ids=new Uint32Array(0).buffer),d}const h=new Float32Array(c*2),R=new Uint16Array(c),M=l?new Uint8Array(c):null,g=a?new Uint32Array(c):null;let p=0;for(let d=0;d<c;d+=1){const C=o[d*2],S=o[d*2+1];U(C,S,u)&&(h[p*2]=C,h[p*2+1]=S,R[p]=r[d],M&&(M[p]=i[d]),g&&(g[p]=s[d]),p+=1)}const D=h.slice(0,p*2),G=R.slice(0,p),E=M?M.slice(0,p):null,q=g?g.slice(0,p):null,x={type:"roi-clip-success",id:n.id,count:p,positions:D.buffer,paletteIndices:G.buffer,durationMs:y()-t};return E&&(x.fillModes=E.buffer),q&&(x.ids=q.buffer),x}function B(n){const t=y(),e=Math.max(0,Math.floor(n.count)),o=new Float32Array(n.positions),r=Math.floor(o.length/2),i=Math.max(0,Math.min(e,r)),s=P(n.polygons??[]);if(i===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(i);let c=0;for(let a=0;a<i;a+=1){const u=o[a*2],h=o[a*2+1];U(u,h,s)&&(f[c]=a,c+=1)}const l=f.slice(0,c);return{type:"roi-clip-index-success",id:n.id,count:c,indices:l.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 r=B(t);A.postMessage(r,[r.indices]);return}const e=T(t),o=[e.positions,e.paletteIndices];e.fillModes&&o.push(e.fillModes),e.ids&&o.push(e.ids),A.postMessage(e,o)}catch(e){const o={type:"roi-clip-failure",id:t.id,error:L(e)};A.postMessage(o)}})})();
2
+ //# sourceMappingURL=roi-clip-worker-BDVQwN2T.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roi-clip-worker-BDVQwN2T.js","sources":["../src/wsi/roi-geometry.ts","../src/workers/roi-clip-worker.ts"],"sourcesContent":["export type RoiCoordinate = [number, number];\nexport type RoiLinearRing = RoiCoordinate[];\nexport type RoiPolygonRings = RoiLinearRing[];\nexport type RoiMultiPolygon = RoiPolygonRings[];\nexport type RoiGeometry = RoiLinearRing | RoiPolygonRings | RoiMultiPolygon;\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 (!geometry) return [];\n\n\tif (isLinearRing(geometry)) {\n\t\tconst polygon = normalizePolygonRings([geometry]);\n\t\treturn polygon.length > 0 ? [polygon] : [];\n\t}\n\n\tif (isPolygonRings(geometry)) {\n\t\tconst polygon = normalizePolygonRings(geometry);\n\t\treturn polygon.length > 0 ? [polygon] : [];\n\t}\n\n\tif (isMultiPolygon(geometry)) {\n\t\tconst out: RoiMultiPolygon = [];\n\t\tfor (const polygon of geometry) {\n\t\t\tconst normalized = normalizePolygonRings(polygon);\n\t\t\tif (normalized.length > 0) out.push(normalized);\n\t\t}\n\t\treturn out;\n\t}\n\n\treturn [];\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\tconst intersect =\n\t\t\tyi > y !== yj > y &&\n\t\t\tx < ((xj - xi) * (y - yi)) / ((yj - yi) || Number.EPSILON) + 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 {\n pointInAnyPreparedPolygon,\n prepareRoiPolygons,\n} from \"../wsi/roi-geometry\";\nimport type {\n RoiClipWorkerDataRequest,\n RoiClipWorkerIndexRequest,\n RoiClipWorkerIndexSuccess,\n RoiClipWorkerRequest,\n RoiClipWorkerResponse,\n RoiClipWorkerSuccess,\n} from \"../wsi/point-clip-worker-protocol\";\n\nfunction nowMs(): number {\n if (typeof performance !== \"undefined\" && typeof performance.now === \"function\") {\n return performance.now();\n }\n return Date.now();\n}\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","isLinearRing","point","isPolygonRings","ring","isMultiPolygon","polygon","closeRoiRing","coordinates","out","x","y","prev","first","last","polygonSignedArea","sum","i","a","b","normalizePolygonRings","rings","normalized","closed","outerIndex","outerArea","area","normalizeRoiGeometry","geometry","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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"}