react-native-mask-segment-c.../dist/utils/magneticLasso.js
a1518 3a3f07628d
Some checks failed
Deploy Docs to GitHub Pages / deploy (push) Has been cancelled
Publish to npm / publish (push) Has been cancelled
feat: add manual lasso wall splitting with magnetic edge-snapping and active contour refinement
- New magneticLasso module: Sobel energy map + Dijkstra shortest-path + Douglas-Peucker
- New activeContour module: greedy snake + balloon force for polygon-to-edge refinement
- wallTextureSplit: edge barrier mask, morphological mask hole closing, Moore boundary tracing, simplified polygon contours, manual pick map patching, gap absorption
- MaskSegmentCanvas: full lasso gesture pipeline (tap vertices, drag, magnetic paths, close polygon, endLasso/cancelLasso/deleteLasso)
- New maskConfig options: splitWallsEdgeBarrierThreshold, splitWallsCloseMaskRadius, manualSplitWalls, manualSplitWallsMaxCount, manualSplitWallsGapAbsorbDilatePx, magneticLasso, activeContourRefine
- New ref methods: startLasso, endLasso, cancelLasso, getManualRegions, deleteLasso
- New exported types: LassoPolygon, ManualWallPartition
- RegionMaskData carries indexToName and wallSemanticIdx through downsample
- Simplify README to point to documentation site
- Update documentation site (EN + ZH-CN) with all new APIs and interaction guide
- Example app: lasso mode toggles and operation buttons

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-06 20:23:57 -07:00

2 lines
6.0 KiB
JavaScript

"use strict";var P=Object.defineProperty;var O=Object.getOwnPropertyDescriptor;var L=Object.getOwnPropertyNames;var V=Object.prototype.hasOwnProperty;var R=(e,t,n)=>t in e?P(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var Y=(e,t)=>{for(var n in t)P(e,n,{get:t[n],enumerable:!0})},j=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of L(t))!V.call(e,r)&&r!==n&&P(e,r,{get:()=>t[r],enumerable:!(o=O(t,r))||o.enumerable});return e};var z=e=>j(P({},"__esModule",{value:!0}),e);var F=(e,t,n)=>R(e,typeof t!="symbol"?t+"":t,n);var lt={};Y(lt,{buildEnergyMap:()=>tt,buildWallAllowedMask:()=>Z,energyPointsToNorm:()=>st,extractCornerPoints:()=>at,filterVerticesToWallMask:()=>H,findShortestPath:()=>ot,isNormPointOnWallMask:()=>C,normToEnergyPoint:()=>it,resolveLassoWallDragPoint:()=>Q,snapNormPointToWallCornerOrEdge:()=>q,snapNormPointToWallEdge:()=>K,upscalePath:()=>ut});module.exports=z(lt);function C(e,t,n){const{labels:o,baseboardBinary:r,cols:c,rows:l,wallSemanticIdx:a}=n;if(a<0||c<=0||l<=0)return!1;const f=Math.min(c-1,Math.max(0,Math.floor(e*c))),h=Math.min(l-1,Math.max(0,Math.floor(t*l)))*c+f;return r[h]?!1:o[h]===a}function H(e,t){return e.filter(n=>C(n.x,n.y,t))}function v(e,t,n){const{labels:o,baseboardBinary:r,cols:c,rows:l,wallSemanticIdx:a}=e;if(t<0||n<0||t>=c||n>=l||a<0)return!1;const f=n*c+t;return r[f]?!1:o[f]===a}function G(e,t,n){if(!v(e,t,n))return!1;const{cols:o,rows:r}=e;return t===0||n===0||t===o-1||n===r-1?!0:!v(e,t-1,n)||!v(e,t+1,n)||!v(e,t,n-1)||!v(e,t,n+1)}function J(e,t,n){if(!G(e,t,n))return!1;const o=!v(e,t-1,n),r=!v(e,t+1,n),c=!v(e,t,n-1),l=!v(e,t,n+1);return(o||r)&&(c||l)}function K(e,t,n,o=12){return B(e,t,n,o,"edge")??{x:e,y:t}}function q(e,t,n,o=16){const r=B(e,t,n,o,"corner");return r||(B(e,t,n,o,"edge")??{x:e,y:t})}function Q(e,t,n,o=12){const r=q(e,t,n,o);return C(r.x,r.y,n)?r:C(e,t,n)?{x:e,y:t}:null}function B(e,t,n,o,r){const{cols:c,rows:l}=n;if(c<=0||l<=0)return null;const a=e*c,f=t*l,y=Math.floor(a),h=Math.floor(f),p=Math.max(1,Math.ceil(o)),M=o*o;let g=1/0,A=-1,s=-1;for(let i=-p;i<=p;i++)for(let b=-p;b<=p;b++){const u=y+b,m=h+i;if(u<0||m<0||u>=c||m>=l||!G(n,u,m)||r==="corner"&&!J(n,u,m))continue;const d=(a-(u+.5))**2+(f-(m+.5))**2;d<=M&&d<g&&(g=d,A=u,s=m)}return A<0?null:{x:(A+.5)/c,y:(s+.5)/l}}function Z(e,t,n){if(n<0)return null;const o=new Uint8Array(e.length);for(let r=0;r<e.length;r++)o[r]=e[r]===n&&!t[r]?1:0;return o}const $=.299,X=.587,k=.114;function tt(e,t,n,o=256,r){const c=Math.max(t,n),l=c>o?o/c:1,a=Math.max(1,Math.floor(t*l)),f=Math.max(1,Math.floor(n*l)),y=a*f,h=new Float32Array(y);for(let s=0;s<f;s++){const b=Math.min(n-1,Math.floor(s*n/f))*t;for(let u=0;u<a;u++){const m=Math.min(t-1,Math.floor(u*t/a)),d=(b+m)*3,E=$*e[d+2]+X*e[d+1]+k*e[d];h[s*a+u]=E}}const p=new Float32Array(y);let M=1;for(let s=1;s<f-1;s++)for(let i=1;i<a-1;i++){const b=s*a+i,u=h[(s-1)*a+(i-1)],m=h[(s-1)*a+i],x=h[(s-1)*a+(i+1)],d=h[s*a+(i-1)],E=h[s*a+i+1],W=h[(s+1)*a+(i-1)],w=h[(s+1)*a+i],S=h[(s+1)*a+(i+1)],T=-u+x-2*d+2*E-W+S,I=-u-2*m-x+W+2*w+S,U=Math.sqrt(T*T+I*I);p[b]=U,U>M&&(M=U)}if(r&&r.length===t*n)for(let s=0;s<f;s++)for(let i=0;i<a;i++){const b=s*a+i,u=Math.min(t-1,Math.floor(i*t/a)),m=Math.min(n-1,Math.floor(s*n/f));if(!r[m*t+u])continue;let x=u===0||m===0||u===t-1||m===n-1;if(!x){const d=r[m*t+(u-1)],E=r[m*t+(u+1)],W=r[(m-1)*t+u],w=r[(m+1)*t+u];x=d===0||E===0||W===0||w===0}x&&(p[b]=M)}const g=new Float32Array(y),A=r&&r.length===t*n?new Uint8Array(y):void 0;for(let s=0;s<f;s++)for(let i=0;i<a;i++){const b=s*a+i,u=Math.min(t-1,Math.floor(i*t/a)),m=Math.min(n-1,Math.floor(s*n/f)),x=!r||r[m*t+u]>0;A&&(A[b]=x?1:0),g[b]=x?1/(1+4*(p[b]/M)):1}return{map:g,w:a,h:f,scale:l,traversable:A}}const nt=[[-1,-1],[0,-1],[1,-1],[-1,0],[1,0],[-1,1],[0,1],[1,1]],N=1e4;class et{constructor(){F(this,"data",[])}push(t,n){this.data.push({idx:t,dist:n}),this.bubbleUp(this.data.length-1)}pop(){if(this.data.length===0)return;const t=this.data[0],n=this.data.pop();return this.data.length>0&&(this.data[0]=n,this.bubbleDown(0)),t}get length(){return this.data.length}bubbleUp(t){for(;t>0;){const n=t-1>>1;if(this.data[n].dist<=this.data[t].dist)break;[this.data[n],this.data[t]]=[this.data[t],this.data[n]],t=n}}bubbleDown(t){const n=this.data.length;for(;;){let o=t;const r=2*t+1,c=2*t+2;if(r<n&&this.data[r].dist<this.data[o].dist&&(o=r),c<n&&this.data[c].dist<this.data[o].dist&&(o=c),o===t)break;[this.data[o],this.data[t]]=[this.data[t],this.data[o]],t=o}}}const rt=4294967295;function ot(e,t,n,o,r,c,l,a){const f=m=>Math.max(1,Math.min(t-2,Math.round(m))),y=m=>Math.max(1,Math.min(n-2,Math.round(m))),h=f(o),p=y(r),M=f(c),g=y(l),A=t*n,s=p*t+h,i=new Uint32Array(A);i.fill(rt),i[s]=0;const b=new Int32Array(A);b.fill(-1);const u=new et;for(u.push(s,0);u.length>0;){const m=u.pop(),x=m.idx,d=m.dist;if(d>i[x])continue;const E=x%t,W=Math.floor(x/t);if(E===M&&W===g){const w=[];let S=x;for(;S>=0;)w.push({x:S%t,y:Math.floor(S/t)}),S=b[S];return w.reverse(),w}for(const[w,S]of nt){const T=E+w,I=W+S;if(T<0||T>=t||I<0||I>=n)continue;const U=I*t+T;if(a&&a[U]===0)continue;const _=Math.round(w!==0&&S!==0?e[U]*N*1.4142:e[U]*N),D=d+_;D<i[U]&&(i[U]=D,b[U]=x,u.push(U,D))}}return[{x:h,y:p},{x:M,y:g}]}function at(e,t=8,n=2){if(e.length<=2)return[...e];const o=new Uint8Array(e.length);o[0]=1,o[e.length-1]=1;function r(l,a){if(a-l<=1)return;const f=e[l].x,y=e[l].y,h=e[a].x,p=e[a].y,M=h-f,g=p-y,A=M*M+g*g;let s=0,i=l;for(let b=l+1;b<a;b++){let u;if(A===0)u=Math.hypot(e[b].x-f,e[b].y-y);else{const m=Math.max(0,Math.min(1,((e[b].x-f)*M+(e[b].y-y)*g)/A)),x=f+m*M,d=y+m*g;u=Math.hypot(e[b].x-x,e[b].y-d)}u>s&&(s=u,i=b)}s>n&&(o[i]=1,r(l,i),r(i,a))}r(0,e.length-1);const c=[];for(let l=0;l<e.length;l++)if(o[l]){if(c.length>0){const a=c[c.length-1];if(Math.hypot(e[l].x-a.x,e[l].y-a.y)<t)continue}c.push({x:e[l].x,y:e[l].y})}return c}function it(e,t,n){return{x:Math.min(n.w-1,Math.max(0,e*n.w)),y:Math.min(n.h-1,Math.max(0,t*n.h))}}function st(e,t){return e.map(n=>({x:Math.min(1,Math.max(0,n.x/t.w)),y:Math.min(1,Math.max(0,n.y/t.h))}))}function ut(e,t,n,o){return e.map(r=>({x:Math.min(n-1,Math.max(0,Math.round(r.x/t))),y:Math.min(o-1,Math.max(0,Math.round(r.y/t)))}))}