iflow-engine-base 3.8.3 → 3.8.4

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.
@@ -5550,7 +5550,7 @@ ${JSON.stringify(l,null,2)}
5550
5550
  <path d="M2 2L14 14" stroke="currentColor" stroke-width="1.2"/>
5551
5551
  <path d="M8 3C4.5 3 1.5 8 1.5 8C2.2 9.3 3.3 10.5 4.5 11.5" stroke="currentColor" stroke-width="1.2"/>
5552
5552
  <path d="M11.5 11.5C12.7 10.5 13.8 9.3 14.5 8C14.5 8 11.5 3 8 3" stroke="currentColor" stroke-width="1.2"/>
5553
- </svg>`}_colorToHex(e){return"#"+e.toString(16).padStart(6,"0")}_makeDraggable(e,t){t.onmousedown=n=>{n.preventDefault();const i=e.getBoundingClientRect(),r=e.offsetParent?.getBoundingClientRect()??{left:0,top:0};e.style.left=i.left-r.left+"px",e.style.top=i.top-r.top+"px",e.style.right="auto",e.style.bottom="auto";const o=n.clientX-i.left,a=n.clientY-i.top,l=h=>{e.style.left=h.clientX-o-r.left+"px",e.style.top=h.clientY-a-r.top+"px"},c=()=>{document.removeEventListener("mousemove",l),document.removeEventListener("mouseup",c)};document.addEventListener("mousemove",l),document.addEventListener("mouseup",c)}}dispose(){this.panel?.remove(),this.panel=null,this.listEl=null}}class Ly{engine;layerMap=new Map;panelUI=null;constructor(e){this.engine=e;const t=document.getElementById(e?.options?.containerId??"")??e?.container??null;t&&(this.panelUI=new WP(t,this))}_loadLayers(e=this.engine.dwgData?.layers??[]){this.layerMap.clear();for(const t of e)this.layerMap.set(t.name,{...t});this.panelUI?.refresh()}syncFromModel(e){e?.length>0&&(this._loadLayers(e),this.panelUI?.refresh())}getLayers(){return Array.from(this.layerMap.values())}getDisplayColor(e){return this.engine.modelToolModule2d?.getDisplayColor(e)??e}refresh(){this.panelUI?.refresh()}setLayerVisible(e,t){const n=this.layerMap.get(e);n&&(n.visible=t),this._applyVisibility(e,t),t||this.clearInteractiveStateForLayer(e)}toggleLayer(e){const t=this.layerMap.get(e);if(!t)return!0;const n=!t.visible;return this.setLayerVisible(e,n),n}setAllLayersVisible(e){for(const t of this.layerMap.keys()){const n=this.layerMap.get(t);n.visible=e,this._applyVisibility(t,e)}}isAllVisible(){return Array.from(this.layerMap.values()).every(e=>e.visible)}isLayerVisible(e){return e?this.layerMap.get(e)?.visible!==!1:!0}isModelVisibleByLayer(e){const t=this.engine.loaderModule2d?.model?.nodeMap?.get(String(e))??this.engine.loaderModule2d?.model?.nodeMap?.get(e);return!t||t.length===0?!0:t.some(n=>{const i=this.getNodeObject(n);return this.isLayerVisible(n?.layer)&&i?.visible!==!1})}_applyVisibility(e,t){const n=this.engine?.modelGroup??this.engine?.scene;if(!n)return;const i=e+"||";n.traverse(r=>{r.name?.startsWith(i)&&(r.visible=t)})}getNodeObject(e){return e?.object??e?.group?.children?.[e.indexes?.[0]]??this.engine.modelGroup?.children?.[e.indexes?.[0]]}clearInteractiveStateForLayer(e){const t=[...this.engine.engineStatus2d?.highlightModels??[],...this.engine.engineStatus2d?.highlightHoverModels??[]];t.length===0||!t.some(i=>(this.engine.loaderModule2d?.model?.nodeMap?.get(String(i))??this.engine.loaderModule2d?.model?.nodeMap?.get(i))?.some(o=>o?.layer===e))||(this.engine.modelToolModule2d?.unHighlightModelHover?.(),this.engine.modelToolModule2d?.unhighlightAllModels?.())}show(){this.panelUI?.show()}hide(){this.panelUI?.hide()}toggle(){this.panelUI?.toggle()}dispose(){this.panelUI?.dispose(),this.panelUI=null,this.layerMap.clear()}}var li=(s=>(s.ModelLoadStart="model-load-start",s.ModelLoadProgress="model-load-progress",s.ModelLoaded="model-loaded",s.ModelLoadError="model-load-error",s.RenderStart="render-start",s.RenderEnd="render-end",s.CameraChanged="camera-changed",s.CameraReset="camera-reset",s.SelectionChanged="selection-changed",s.HoverChanged="hover-changed",s.EntityClick="entity-click",s.LayerVisibilityChanged="layer-visibility-changed",s.LayerColorChanged="layer-color-changed",s.ViewZoomChanged="view-zoom-changed",s.ViewPanChanged="view-pan-changed",s.ToolActivated="tool-activated",s.ToolDeactivated="tool-deactivated",s.Error="error",s.Warning="warning",s))(li||{});class HP{listeners=new Map;onceListeners=new Map;debugMode=!1;constructor(e=!1){this.debugMode=e,this.initializeEvents()}initializeEvents(){Object.values(li).forEach(t=>{this.listeners.set(t,new Set),this.onceListeners.set(t,new Set)})}on(e,t){return this.listeners.has(e)?(this.listeners.get(e).add(t),this.debugMode&&console.log(`[EventModule2d] Listener added for ${e}`),()=>this.off(e,t)):(console.warn(`Event type ${e} is not registered`),()=>{})}once(e,t){if(!this.onceListeners.has(e)){console.warn(`Event type ${e} is not registered`);return}this.onceListeners.get(e).add(t),this.debugMode&&console.log(`[EventModule2d] Once listener added for ${e}`)}off(e,t){const n=this.listeners.get(e);n&&(n.delete(t),this.debugMode&&console.log(`[EventModule2d] Listener removed for ${e}`))}trigger(e,t){this.debugMode&&console.log(`[EventModule2d] Triggering ${e}`,t);const n=this.listeners.get(e);n&&n.size>0&&n.forEach(r=>{try{r(t)}catch(o){console.error(`[EventModule2d] Error in listener for ${e}:`,o)}});const i=this.onceListeners.get(e);i&&i.size>0&&(i.forEach(r=>{try{r(t)}catch(o){console.error(`[EventModule2d] Error in once listener for ${e}:`,o)}}),i.clear())}removeAllListeners(){this.listeners.forEach(e=>e.clear()),this.onceListeners.forEach(e=>e.clear()),this.debugMode&&console.log("[EventModule2d] All listeners removed")}removeListenersOfType(e){const t=this.listeners.get(e),n=this.onceListeners.get(e);t&&t.clear(),n&&n.clear(),this.debugMode&&console.log(`[EventModule2d] All listeners removed for ${e}`)}getListenerCount(e){const t=this.listeners.get(e),n=this.onceListeners.get(e);return(t?.size||0)+(n?.size||0)}setDebugMode(e){this.debugMode=e}getAllEventTypes(){return Object.values(li)}dispose(){this.removeAllListeners(),this.listeners.clear(),this.onceListeners.clear(),this.debugMode&&console.log("[EventModule2d] Disposed")}}function ks(s){return Array.isArray(s)?new b.Vector3(s[0]??0,s[1]??0,s[2]??0):new b.Vector3(s?.x??0,s?.y??0,s?.z??0)}function Mr(s){return s?(s.computeBoundingBox(),{min:s.boundingBox?.min.clone()??new b.Vector3,max:s.boundingBox?.max.clone()??new b.Vector3}):{min:new b.Vector3,max:new b.Vector3}}function cp(s,e,t){const n=new b.Vector3(s[0]??0,s[1]??0,s[2]??0),i=new b.Euler(0,0,t??0),r=new b.Vector3(e[0]??1,e[1]??1,e[2]??1),o=new b.Quaternion().setFromEuler(i);return new b.Matrix4().compose(n,o,r)}function qP(s){return Array.isArray(s?.transformMatrix)&&s.transformMatrix.length===16?new b.Matrix4().fromArray(s.transformMatrix):cp(s.position??[0,0,0],s.scale??[1,1,1],s.rotation??0)}function Ry(s){if(s.length===0)return{min:new b.Vector3,max:new b.Vector3};const e=new b.Vector3(Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY),t=new b.Vector3(Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY);return s.forEach(n=>{e.x=Math.min(e.x,n.x),e.y=Math.min(e.y,n.y),e.z=Math.min(e.z,n.z),t.x=Math.max(t.x,n.x),t.y=Math.max(t.y,n.y),t.z=Math.max(t.z,n.z)}),{min:e,max:t}}class XP{constructor(e){this.geometryFactory=e}cache=new Map;blockIndex=new Map;setBlocks(e){this.cache.clear(),this.blockIndex.clear(),(e??[]).forEach(t=>{t?.name&&this.blockIndex.set(t.name,t),t?.id&&this.blockIndex.set(t.id,t)})}clearCache(){this.cache.clear()}flattenRootEntities(e){return Array.from(this.iterateRootEntities(e))}*iterateRootEntities(e){yield*this.iterateEntities(e??[],new b.Matrix4,0)}flattenBlock(e,t,n){const i=this.cache.get(t);if(i)return i;const r=e.origin??[0,0,0],o=new b.Matrix4().makeTranslation(-r[0],-r[1],-(r[2]??0)),a=this.flattenEntities(e.entities??[],o,n);return this.cache.set(t,a),e.name&&this.cache.set(e.name,a),e.id&&this.cache.set(e.id,a),a}flattenEntities(e,t,n){return Array.from(this.iterateEntities(e,t,n))}*iterateEntities(e,t,n){if(n>20){console.warn("[LoaderModule2d] Block nesting is too deep, skip nested INSERT.");return}for(const i of e)if(i?.visible!==!1){if(i.type==="INSERT"){const r=this.getBlockItems(i.blockId,n+1),o=t.clone().multiply(qP(i)),a=this.getClipPolygon(i,t);for(const l of r){const c=this.cloneRenderItem(l,o,i),h=a?this.clipRenderItem(c,a):c;h&&(yield h)}a&&i.displayClipBoundary===!0&&(yield this.createClipBoundaryItem(i,a));continue}for(const r of this.geometryFactory.create(i,t))yield r}}getBlockItems(e,t){const n=this.cache.get(e);if(n)return n;const i=this.blockIndex.get(e);return i?this.flattenBlock(i,i.name??i.id??e,t):(console.warn(`[LoaderModule2d] Missing block: ${e}`),[])}cloneRenderItem(e,t,n){const i=e.layer==="0"&&n?.layer?n.layer:e.layer??n?.layer,r=e.color==null||e.color===0?n?.color??e.color??0:e.color,o=n?.linkId??n?.id??e.linkId;if(e.kind==="line")return{...e,layer:i,color:r,linkId:o,points:(e.points??[]).map(h=>h.clone().applyMatrix4(t))};const a=e.geometry?.clone();a?.applyMatrix4(t);const l=e.textAnchor?.clone().applyMatrix4(t),c=Mr(a);return{...e,layer:i,color:r,linkId:o,geometry:a,min:c.min,max:c.max,textAnchor:l}}getClipPolygon(e,t){if(e?.clipping!==!0||!Array.isArray(e?.clipBoundary))return null;const n=e.clipBoundary.map(r=>new b.Vector3(r?.[0]??r?.x??0,r?.[1]??r?.y??0,r?.[2]??r?.z??0)).filter(r=>Number.isFinite(r.x)&&Number.isFinite(r.y));if(n.length<3)return null;const i=this.getClipBoundaryMatrix(e,t);return i?n.map(r=>r.clone().applyMatrix4(i)):n}getClipBoundaryMatrix(e,t){return!Array.isArray(e?.clipInsertTransform)||e.clipInsertTransform.length!==16?null:t.clone().multiply(new b.Matrix4().fromArray(e.clipInsertTransform))}clipRenderItem(e,t){if(e.kind==="line"){const r=this.clipLinePoints(e.points??[],t);if(r.length===0)return null;const o=this.getPointsBounds(r);return{...e,points:r,min:o.min,max:o.max}}const n=this.clipGeometry(e.geometry,t);if(!n)return null;const i=Mr(n);return{...e,geometry:n,min:i.min,max:i.max}}clipLinePoints(e,t){const n=[];for(let i=0;i<e.length-1;i+=2)this.clipSegmentByPolygon(e[i],e[i+1],t).forEach(r=>{n.push(r[0],r[1])});return n}clipSegmentByPolygon(e,t,n){const i=t.clone().sub(e),r=[0,1];for(let l=0;l<n.length;l+=1){const c=this.getSegmentIntersectionParameter(e,t,n[l],n[(l+1)%n.length]);c!=null&&c>1e-9&&c<1-1e-9&&r.push(c)}const o=Array.from(new Set(r.map(l=>Number(l.toFixed(12))))).sort((l,c)=>l-c),a=[];for(let l=0;l<o.length-1;l+=1){const c=o[l],h=o[l+1];if(h-c<1e-10)continue;const u=(c+h)*.5,d=e.clone().add(i.clone().multiplyScalar(u));this.isPointInPolygon(d,n)&&a.push([e.clone().add(i.clone().multiplyScalar(c)),e.clone().add(i.clone().multiplyScalar(h))])}return a}getSegmentIntersectionParameter(e,t,n,i){const r=t.x-e.x,o=t.y-e.y,a=i.x-n.x,l=i.y-n.y,c=r*l-o*a;if(Math.abs(c)<1e-12)return null;const h=n.x-e.x,u=n.y-e.y,d=(h*l-u*a)/c,f=(h*o-u*r)/c;return d>=-1e-9&&d<=1+1e-9&&f>=-1e-9&&f<=1+1e-9?b.MathUtils.clamp(d,0,1):null}isPointInPolygon(e,t){let n=!1;for(let i=0,r=t.length-1;i<t.length;r=i,i+=1){const o=t[i],a=t[r];if(this.isPointOnSegment(e,o,a))return!0;o.y>e.y!=a.y>e.y&&e.x<(a.x-o.x)*(e.y-o.y)/(a.y-o.y)+o.x&&(n=!n)}return n}isPointOnSegment(e,t,n){const i=(n.x-t.x)*(e.y-t.y)-(n.y-t.y)*(e.x-t.x);if(Math.abs(i)>1e-8)return!1;const r=(e.x-t.x)*(n.x-t.x)+(e.y-t.y)*(n.y-t.y),o=(n.x-t.x)**2+(n.y-t.y)**2;return r>=-1e-8&&r<=o+1e-8}clipGeometry(e,t){if(!e?.attributes?.position)return null;const n=e.attributes.position,i=e.attributes.uv,r=e.index,o=[],a=[],l=!!i,c=this.triangulateClipPolygon(t),h=f=>({position:new b.Vector3(n.getX(f),n.getY(f),n.getZ(f)),uv:l?new b.Vector2(i.getX(f),i.getY(f)):void 0}),u=r?r.count:n.count;for(let f=0;f<u;f+=3){const m=r?r.getX(f):f,g=r?r.getX(f+1):f+1,A=r?r.getX(f+2):f+2,p=[h(m),h(g),h(A)];c.forEach(x=>{const y=this.clipTriangle(p,x);if(!(y.length<3))for(let v=1;v<y.length-1;v+=1)[y[0],y[v],y[v+1]].forEach(_=>{o.push(_.position.x,_.position.y,_.position.z),l&&_.uv&&a.push(_.uv.x,_.uv.y)})})}if(o.length===0)return null;const d=new b.BufferGeometry;return d.setAttribute("position",new b.Float32BufferAttribute(o,3)),l&&d.setAttribute("uv",new b.Float32BufferAttribute(a,2)),d.computeVertexNormals(),d}triangulateClipPolygon(e){const t=e.map(i=>new b.Vector2(i.x,i.y)),n=b.ShapeUtils.triangulateShape(t,[]);if(n.length===0){const i=[];for(let r=1;r<e.length-1;r+=1)i.push([e[0],e[r],e[r+1]]);return i}return n.map(i=>i.map(r=>e[r]))}clipTriangle(e,t){const n=this.getPolygonOrientation(t);let i=e;for(let r=0;r<t.length;r+=1){const o=t[r],a=t[(r+1)%t.length],l=i;if(i=[],l.length===0)break;let c=l[l.length-1],h=this.isInsideClipEdge(c.position,o,a,n);l.forEach(u=>{const d=this.isInsideClipEdge(u.position,o,a,n);d!==h&&i.push(this.intersectClipEdge(c,u,o,a,n)),d&&i.push(u),c=u,h=d})}return i}isInsideClipEdge(e,t,n,i){const r=n.x-t.x,o=n.y-t.y;return i*(r*(e.y-t.y)-o*(e.x-t.x))>=-1e-9}intersectClipEdge(e,t,n,i,r){const o=i.x-n.x,a=i.y-n.y,l=r*(o*(e.position.y-n.y)-a*(e.position.x-n.x)),c=r*(o*(t.position.y-n.y)-a*(t.position.x-n.x)),h=Math.abs(l-c)<1e-12?0:l/(l-c);return{position:e.position.clone().lerp(t.position,h),uv:e.uv&&t.uv?e.uv.clone().lerp(t.uv,h):void 0}}getPolygonOrientation(e){let t=0;for(let n=0;n<e.length;n+=1){const i=e[n],r=e[(n+1)%e.length];t+=i.x*r.y-r.x*i.y}return t>=0?1:-1}getPointsBounds(e){const t=new b.Vector3(Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY),n=new b.Vector3(Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY);return e.forEach(i=>{t.min(i),n.max(i)}),{min:t,max:n}}createClipBoundaryItem(e,t){const n=[];for(let r=0;r<t.length;r+=1)n.push(t[r].clone(),t[(r+1)%t.length].clone());const i=this.getPointsBounds(n);return{kind:"line",layer:e.layer??"0",color:e.clipBoundaryColor??16711935,lineType:"Continuous",linkId:e.linkId??e.id,points:n,min:i.min,max:i.max,info:e}}}class YP{zipObjectUrls=[];async load(e){if(this.clearZipObjectUrls(),this.is2dZipUrl(e))return this.loadZipData(e);const t=this.isManifestUrl(e)?e:this.joinUrl(this.normalizeDirectoryUrl(e),"manifest.json"),n=await this.fetchJson(t);if(!this.isSplitManifest(n))throw new Error("[LoaderModule2d] Expected split CAD manifest data.");return this.loadSplitData(this.getBaseUrl(t),n)}async fetchJson(e){const t=await fetch(e);if(!t.ok)throw new Error(`HTTP error! status: ${t.status}`);return t.json()}async loadSplitData(e,t,n=r=>this.fetchJson(r),i=(r,o)=>Promise.resolve(this.resolveImageUrl(r,o))){const[r,o,a,l]=await Promise.all([n(this.joinUrl(e,t.metadataUrl??"metadata.json")),n(this.joinUrl(e,t.layersUrl??"layers.json")),this.loadBlocks(e,t.blocksUrl??"blocks/index.json",n),this.loadTiles(e,t.root,n)]);await this.resolveBlockAssets(a,e,i);const c=[];return l.forEach(h=>{h.inserts.forEach(u=>c.push(u))}),{version:t.version??"1.0",metadata:r,layers:o,blocks:a,entities:c,octree:t.root,tiles:l}}async loadBlocks(e,t,n){const r=(await n(this.joinUrl(e,t))).parts??[],o=await Promise.all(r.map(l=>this.loadBlockPart(this.joinUrl(e,l),n))),a=[];return o.forEach(l=>{(Array.isArray(l?.blocks)?l.blocks:[]).forEach(h=>a.push(h))}),a}async loadBlockPart(e,t){try{return await t(e)}catch(n){const i=n instanceof Error?n.message:String(n);return console.warn(`[LoaderModule2d] Skip missing block json: ${e}`,i),{blocks:[]}}}async resolveBlockAssets(e,t,n){await Promise.all(e.map(async i=>{const r=Array.isArray(i?.entities)?i.entities:[];await Promise.all(r.map(async o=>{String(o?.type).toUpperCase()==="IMAGE"&&(o.imageUrl=await n(o,t))}))}))}resolveImageUrl(e,t){const n=e.localPath||e.sourcePath||e.path||e.url||"";if(/^(https?:)?\/\//i.test(n)||n.startsWith("/"))return n;const r=String(n).replace(/\\/g,"/").split("/").filter(Boolean).pop();return r?this.joinUrl(t,r):""}async loadTiles(e,t,n){const i=this.collectTileNodes(t);return await Promise.all(i.map(async o=>{const a=o.tileUrl??"",l=await n(this.joinUrl(e,a)),c=this.normalizeTileInserts(l.inserts??[]);return o.elements=c.map(h=>h.linkId??h.id).filter(h=>h!=null),{id:o.id??l.id??a,url:a,node:o,inserts:c}}))}normalizeTileInserts(e){return e.map(t=>({...t,linkId:t.linkId??t.id,type:"INSERT",color:t.color??0,visible:t.visible??!0}))}collectTileNodes(e){if(!e)return[];const t=[],n=[e];for(;n.length>0;){const i=n.pop();if(!i)continue;i.tileUrl&&t.push(i);const r=i.children??[];for(let o=r.length-1;o>=0;o-=1)n.push(r[o])}return t}async loadZipData(e){const t=await fetch(e);if(!t.ok)throw new Error(`HTTP error! status: ${t.status}`);const n=await zd.loadAsync(await t.arrayBuffer()),i=this.findZipManifestPath(n),r=await this.fetchZipJson(n,i);if(!this.isSplitManifest(r))throw new Error("[LoaderModule2d] Expected split CAD manifest data in .2d package.");const o=this.getZipBasePath(i);return this.loadSplitData(o,r,a=>this.fetchZipJson(n,a),(a,l)=>this.resolveZipImageUrl(n,a,l))}findZipManifestPath(e){const t=Object.keys(e.files).filter(r=>!e.files[r].dir),i=t.find(r=>this.normalizeZipPath(r).toLowerCase()==="manifest.json")??t.find(r=>this.normalizeZipPath(r).toLowerCase().endsWith("/manifest.json"));if(!i)throw new Error("[LoaderModule2d] Missing manifest.json in .2d package.");return this.normalizeZipPath(i)}async fetchZipJson(e,t){if(/^(https?:)?\/\//i.test(t))return this.fetchJson(t);const n=this.getZipFile(e,t);if(!n)throw new Error(`[LoaderModule2d] Missing file in .2d package: ${t}`);return JSON.parse(await n.async("string"))}async resolveZipImageUrl(e,t,n){const i=t.localPath||t.sourcePath||t.path||t.url||"";if(/^(https?:)?\/\//i.test(i)||String(i).startsWith("blob:"))return i;const r=this.normalizeZipPath(String(i)),o=r.split("/").filter(Boolean).pop(),l=[this.joinUrl(n,r),o?this.joinUrl(n,o):"",r,o??""].filter(Boolean).map(h=>this.getZipFile(e,h)).find(h=>!!h);if(!l)return"";const c=URL.createObjectURL(new Blob([await l.async("arraybuffer")]));return this.zipObjectUrls.push(c),c}isSplitManifest(e){return!!e&&typeof e=="object"&&(e.splitType==="octree-2d"||!!e.blocksUrl)}is2dZipUrl(e){return/\.2d($|[?#])/i.test(e)}isManifestUrl(e){return/manifest\.json($|\?)/i.test(e)}getBaseUrl(e){const t=e.split("?")[0];return t.slice(0,t.lastIndexOf("/")+1)}getZipBasePath(e){const t=this.normalizeZipPath(e),n=t.lastIndexOf("/");return n>=0?t.slice(0,n+1):""}normalizeDirectoryUrl(e){return e.endsWith("/")?e:`${e}/`}joinUrl(e,t){return/^(https?:)?\/\//i.test(t)||t.startsWith("/")?t:`${e}${t}`.replace(/([^:]\/)\/+/g,"$1")}normalizeZipPath(e){return String(e).split("?")[0].split("#")[0].replace(/\\/g,"/").replace(/^\/+/,"")}getZipFile(e,t){const n=this.normalizeZipPath(t),i=e.file(n);if(i)return i;const r=n.toLowerCase(),o=Object.keys(e.files).find(a=>this.normalizeZipPath(a).toLowerCase()===r);return o?e.file(o):null}clearZipObjectUrls(){this.zipObjectUrls.forEach(e=>URL.revokeObjectURL(e)),this.zipObjectUrls=[]}}function ky(s,e,t){const n=t.length-s-1;if(e>=t[n])return n-1;if(e<=t[s])return s;let i=s,r=n,o=Math.floor((i+r)/2);for(;e<t[o]||e>=t[o+1];)e<t[o]?r=o:i=o,o=Math.floor((i+r)/2);return o}function KP(s,e,t,n){const i=[],r=[],o=[];i[0]=1;for(let a=1;a<=t;++a){r[a]=e-n[s+1-a],o[a]=n[s+a]-e;let l=0;for(let c=0;c<a;++c){const h=o[c+1],u=r[a-c],d=i[c]/(h+u);i[c]=l+h*d,l=u*d}i[a]=l}return i}function $P(s,e,t,n){const i=ky(s,n,e),r=KP(i,n,s,e),o=new w.Vector4(0,0,0,0);for(let a=0;a<=s;++a){const l=t[i-s+a],c=r[a],h=l.w*c;o.x+=l.x*h,o.y+=l.y*h,o.z+=l.z*h,o.w+=l.w*c}return o}function JP(s,e,t,n,i){const r=[];for(let u=0;u<=t;++u)r[u]=0;const o=[];for(let u=0;u<=n;++u)o[u]=r.slice(0);const a=[];for(let u=0;u<=t;++u)a[u]=r.slice(0);a[0][0]=1;const l=r.slice(0),c=r.slice(0);for(let u=1;u<=t;++u){l[u]=e-i[s+1-u],c[u]=i[s+u]-e;let d=0;for(let f=0;f<u;++f){const m=c[f+1],g=l[u-f];a[u][f]=m+g;const A=a[f][u-1]/a[u][f];a[f][u]=d+m*A,d=g*A}a[u][u]=d}for(let u=0;u<=t;++u)o[0][u]=a[u][t];for(let u=0;u<=t;++u){let d=0,f=1;const m=[];for(let g=0;g<=t;++g)m[g]=r.slice(0);m[0][0]=1;for(let g=1;g<=n;++g){let A=0;const p=u-g,x=t-g;u>=g&&(m[f][0]=m[d][0]/a[x+1][p],A=m[f][0]*a[p][x]);const y=p>=-1?1:-p,v=u-1<=x?g-1:t-u;for(let E=y;E<=v;++E)m[f][E]=(m[d][E]-m[d][E-1])/a[x+1][p+E],A+=m[f][E]*a[p+E][x];u<=x&&(m[f][g]=-m[d][g-1]/a[x+1][u],A+=m[f][g]*a[u][x]),o[g][u]=A;const _=d;d=f,f=_}}let h=t;for(let u=1;u<=n;++u){for(let d=0;d<=t;++d)o[u][d]*=h;h*=t-u}return o}function ZP(s,e,t,n,i){const r=i<s?i:s,o=[],a=ky(s,n,e),l=JP(a,n,s,r,e),c=[];for(let h=0;h<t.length;++h){const u=t[h].clone(),d=u.w;u.x*=d,u.y*=d,u.z*=d,c[h]=u}for(let h=0;h<=r;++h){const u=c[a-s].clone().multiplyScalar(l[h][0]);for(let d=1;d<=s;++d)u.add(c[a-s+d].clone().multiplyScalar(l[h][d]));o[h]=u}for(let h=r+1;h<=i+1;++h)o[h]=new w.Vector4(0,0,0);return o}function e3(s,e){let t=1;for(let i=2;i<=s;++i)t*=i;let n=1;for(let i=2;i<=e;++i)n*=i;for(let i=2;i<=s-e;++i)n*=i;return t/n}function t3(s){const e=s.length,t=[],n=[];for(let r=0;r<e;++r){const o=s[r];t[r]=new w.Vector3(o.x,o.y,o.z),n[r]=o.w}const i=[];for(let r=0;r<e;++r){const o=t[r].clone();for(let a=1;a<=r;++a)o.sub(i[r-a].clone().multiplyScalar(e3(r,a)*n[a]));i[r]=o.divideScalar(n[0])}return i}function n3(s,e,t,n,i){const r=ZP(s,e,t,n,i);return t3(r)}class i3 extends w.Curve{constructor(e,t,n,i,r){super();const o=t?t.length-1:0,a=n?n.length:0;this.degree=e,this.knots=t,this.controlPoints=[],this.startKnot=i||0,this.endKnot=r||o;for(let l=0;l<a;++l){const c=n[l];this.controlPoints[l]=new w.Vector4(c.x,c.y,c.z,c.w)}}getPoint(e,t=new w.Vector3){const n=t,i=this.knots[this.startKnot]+e*(this.knots[this.endKnot]-this.knots[this.startKnot]),r=$P(this.degree,this.knots,this.controlPoints,i);return r.w!==1&&r.divideScalar(r.w),n.set(r.x,r.y,r.z)}getTangent(e,t=new w.Vector3){const n=t,i=this.knots[0]+e*(this.knots[this.knots.length-1]-this.knots[0]),r=n3(this.degree,this.knots,this.controlPoints,i,1);return n.copy(r[1]).normalize(),n}toJSON(){const e=super.toJSON();return e.degree=this.degree,e.knots=[...this.knots],e.controlPoints=this.controlPoints.map(t=>t.toArray()),e.startKnot=this.startKnot,e.endKnot=this.endKnot,e}fromJSON(e){return super.fromJSON(e),this.degree=e.degree,this.knots=[...e.knots],this.controlPoints=e.controlPoints.map(t=>new w.Vector4(t[0],t[1],t[2],t[3])),this.startKnot=e.startKnot,this.endKnot=e.endKnot,this}}const Tt=1e-8,Fy=.001,s3=8421504;class r3{constructor(e){this.engine=e}create(e,t){const n=this.getLoopSet(e);if(n.outers.length===0)return[];if(this.isGradientFill(e))return this.createGradientItems(e,t,n);if(this.isSolidFill(e))return this.createSolidItems(e,t,n);const r=this.createPatternLineItem(e,t,n);return r?[r]:(this.warnUnknownPatternFallback(e),this.createSolidItems(e,t,n,s3))}isSolidFill(e){const t=String(e.pattern??e.patternName??"").toUpperCase();return e.solid===!0||t==="SOLID"}warnUnknownPatternFallback(e){const t=e.pattern??e.patternName??"UNKNOWN";this.engine.options?.debugHatch===!0&&console.warn(`[LoaderModule2d] HATCH pattern "${t}" cannot be rendered, use gray solid fallback.`)}isGradientFill(e){return e.gradient?.enabled===!0||String(e.patternType??"").toUpperCase()==="GRADIENTFILL"}getLoopSet(e){const t=(e.loops??[]).map(o=>this.normalizeLoop(o.points)).filter(o=>o.length>=3);if(t.length===0)return{outers:[],holes:[]};const n=(e.loops??[]).filter(o=>this.normalizeLoop(o.points).length>=3);if(!n.some(o=>o.type===!1))return this.classifyLoopsByContainment(t);const i=n.filter(o=>o.type!==!1).map(o=>this.normalizeLoop(o.points)),r=n.filter(o=>o.type===!1).map(o=>this.normalizeLoop(o.points));return i.length>0?{outers:i,holes:r}:{outers:[t[0]],holes:t.slice(1)}}classifyLoopsByContainment(e){const t=[...e].sort((r,o)=>Math.abs(this.signedArea(o))-Math.abs(this.signedArea(r))),n=[],i=[];return t.forEach((r,o)=>{const a=new b.Vector2(r[0][0],r[0][1]);t.slice(0,o).filter(c=>this.pointInPolygon(a,c)).length%2===0?n.push(r):i.push(r)}),{outers:n,holes:i}}signedArea(e){let t=0;for(let n=0;n<e.length;n+=1){const i=e[n],r=e[(n+1)%e.length];t+=i[0]*r[1]-r[0]*i[1]}return t/2}normalizeLoop(e){const t=[];(e??[]).forEach(r=>{if(!Array.isArray(r)||r.length<2)return;const o=[Number(r[0]),Number(r[1])];if(!Number.isFinite(o[0])||!Number.isFinite(o[1]))return;const a=t[t.length-1];(!a||Math.hypot(o[0]-a[0],o[1]-a[1])>Tt)&&t.push(o)});const n=t[0],i=t[t.length-1];return n&&i&&Math.hypot(n[0]-i[0],n[1]-i[1])<=Tt&&t.pop(),t}createSolidItems(e,t,n,i){const r=[];if(n.outers.forEach(l=>{const c=this.createShape(l);n.holes.filter(h=>this.pointInPolygon(new b.Vector2(h[0][0],h[0][1]),l)).forEach(h=>{c.holes.push(this.createPath(h))}),r.push(new b.ShapeGeometry(c))}),r.length===0)return[];const o=r.length===1?r[0]:_i(r,!1);o.applyMatrix4(t);const a=Mr(o);return[{kind:"hatch",layer:e.layer??"0",color:i??this.resolveEntityColor(e),linkId:e.linkId??e.id,geometry:o,min:a.min,max:a.max,info:e}]}createShape(e){const t=new b.Shape;t.moveTo(e[0][0],e[0][1]);for(let n=1;n<e.length;n+=1)t.lineTo(e[n][0],e[n][1]);return t.closePath(),t}createPath(e){const t=new b.Path;t.moveTo(e[0][0],e[0][1]);for(let n=1;n<e.length;n+=1)t.lineTo(e[n][0],e[n][1]);return t.closePath(),t}createGradientItems(e,t,n){const i=[];if(n.outers.forEach(a=>{const l=this.createShape(a);n.holes.filter(h=>this.pointInPolygon(new b.Vector2(h[0][0],h[0][1]),a)).forEach(h=>{l.holes.push(this.createPath(h))});const c=this.subdivideTriangles(new b.ShapeGeometry(l),this.engine.options?.hatchGradientSubdivisions??3);this.applyGradientVertexColors(c,a,e.gradient),i.push(c)}),i.length===0)return[];const r=i.length===1?i[0]:_i(i,!1);r.applyMatrix4(t);const o=Mr(r);return[{kind:"hatch",layer:e.layer??"0",color:this.resolveEntityColor(e),linkId:e.linkId??e.id,geometry:r,useVertexColors:!0,min:o.min,max:o.max,info:e}]}applyGradientVertexColors(e,t,n){const i=e.getAttribute("position"),r=[],o=this.resolveGradientStops(n),a=this.getBounds(t),l=new b.Vector2((a.minX+a.maxX)/2,(a.minY+a.maxY)/2),c=Math.max(a.maxX-a.minX,Tt),h=Math.max(a.maxY-a.minY,Tt),u=Math.max(Math.hypot(c/2,h/2),Tt),d=Number(n?.angle??0),f=new b.Vector2(Math.cos(d),Math.sin(d)).normalize(),m=new b.Vector2(-f.y,f.x);for(let g=0;g<i.count;g+=1){const A=new b.Vector2(i.getX(g),i.getY(g)),p=this.resolveGradientFactor(A,l,f,m,c,h,u,n),x=this.sampleGradientColor(o,p);r.push(x.r,x.g,x.b)}e.setAttribute("color",new b.Float32BufferAttribute(r,3))}subdivideTriangles(e,t){let n=e.index?e.toNonIndexed():e.clone();const i=Math.max(0,Math.min(Math.floor(Number(t)||0),5));for(let r=0;r<i;r+=1){const o=n.getAttribute("position"),a=[];for(let l=0;l<o.count;l+=3){const c=new b.Vector3(o.getX(l),o.getY(l),o.getZ(l)),h=new b.Vector3(o.getX(l+1),o.getY(l+1),o.getZ(l+1)),u=new b.Vector3(o.getX(l+2),o.getY(l+2),o.getZ(l+2)),d=c.clone().lerp(h,.5),f=h.clone().lerp(u,.5),m=u.clone().lerp(c,.5);this.pushTriangle(a,c,d,m),this.pushTriangle(a,d,h,f),this.pushTriangle(a,m,f,u),this.pushTriangle(a,d,f,m)}n=new b.BufferGeometry().setAttribute("position",new b.Float32BufferAttribute(a,3))}return n}pushTriangle(e,t,n,i){e.push(t.x,t.y,t.z,n.x,n.y,n.z,i.x,i.y,i.z)}resolveGradientFactor(e,t,n,i,r,o,a,l){const c=e.clone().sub(t),h=String(l?.name??"LINEAR").toUpperCase(),u=Number(l?.shift??0),d=Math.max(Math.abs(n.x)*r+Math.abs(n.y)*o,Tt),f=Math.max(Math.abs(i.x)*r+Math.abs(i.y)*o,Tt);let m=.5+c.dot(n)/d+u;return h.includes("CYLINDER")?m=Math.abs(c.dot(i))/(f/2):h.includes("SPHERICAL")?(m=c.length()/a,h.includes("HEMI")&&(m=Math.sqrt(m))):h.includes("CURVED")&&(m=Math.pow(Math.abs(c.dot(n))/(d/2),.65)),h.startsWith("INV")&&(m=1-m),b.MathUtils.clamp(m,0,1)}resolveGradientStops(e){const t=(e?.colors??[]).map(n=>({value:b.MathUtils.clamp(Number(n.value??0),0,1),color:this.resolveGradientStopColor(n)})).sort((n,i)=>n.value-i.value);if(t.length>=2)return t;if(t.length===1){const n=b.MathUtils.clamp(Number(e?.colorTint??0),0,1);return[{value:0,color:t[0].color.clone().lerp(new b.Color(16777215),n)},{value:1,color:t[0].color}]}return[{value:0,color:new b.Color(16777215)},{value:1,color:new b.Color(0)}]}resolveGradientStopColor(e){if(Array.isArray(e.rgb)&&e.rgb.length>=3){const[t,n,i]=e.rgb.map(r=>b.MathUtils.clamp(Number(r??0),0,255)/255);return new b.Color(t,n,i)}return new b.Color(e.color??16777215)}resolveEntityColor(e){if(Array.isArray(e.rgb)&&e.rgb.length>=3){const[t,n,i]=e.rgb.map(r=>Math.round(b.MathUtils.clamp(Number(r??0),0,255)));return t<<16|n<<8|i}return e.color??16777215}sampleGradientColor(e,t){if(t<=e[0].value)return e[0].color.clone();for(let n=0;n<e.length-1;n+=1){const i=e[n],r=e[n+1];if(t<=r.value+Tt){const o=Math.max(r.value-i.value,Tt);return i.color.clone().lerp(r.color,(t-i.value)/o)}}return e[e.length-1].color.clone()}createPatternLineItem(e,t,n){const i=[],r=this.engine.options?.hatchPatternMaxSegments??2e4;let o=0;for(const l of n.outers){const c=this.getBounds(l),h=Math.hypot(c.maxX-c.minX,c.maxY-c.minY);if(!(h<Tt))for(const u of e.patternLines??[]){if(o>=r)break;const d=this.createPatternFamilySegments(e,u,l,n.holes,c,h,r-o);d.forEach(([f,m])=>{i.push(new b.Vector3(f.x,f.y,Fy),new b.Vector3(m.x,m.y,Fy))}),o+=d.length}}if(i.length===0)return null;i.forEach(l=>l.applyMatrix4(t));const a=Ry(i);return{kind:"line",layer:e.layer??"0",color:this.resolveEntityColor(e),linkId:e.linkId??e.id,points:i,min:a.min,max:a.max,info:e}}createPatternFamilySegments(e,t,n,i,r,o,a){const l=this.resolvePatternLineTransform(e,t),c=l.dir,h=new b.Vector2(-c.y,c.x),u=l.base,d=l.offset;let f=d.dot(h);if(Math.abs(f)<Tt&&(f=Number(t.lineOffset??0)),Math.abs(f)<Tt)return[];const m=[new b.Vector2(r.minX,r.minY),new b.Vector2(r.maxX,r.minY),new b.Vector2(r.maxX,r.maxY),new b.Vector2(r.minX,r.maxY)],g=u.dot(h),A=m.map(I=>I.dot(h)-g),p=Math.min(...A)-o,x=Math.max(...A)+o,y=Math.floor(Math.min(p/f,x/f))-2,v=Math.ceil(Math.max(p/f,x/f))+2,_=[],E=new b.Vector2((r.minX+r.maxX)/2,(r.minY+r.maxY)/2);for(let I=y;I<=v&&_.length<a;I+=1){const B=u.clone().add(d.clone().multiplyScalar(I)),M=B.clone().add(c.clone().multiplyScalar(E.clone().sub(B).dot(c))),C=M.clone().add(c.clone().multiplyScalar(-o*2)),P=M.clone().add(c.clone().multiplyScalar(o*2));this.clipLineByPolygon(C,P,n).forEach(([R,S])=>{this.subtractHoles(R,S,i).forEach(([F,N])=>{this.appendDashedSegment(_,F,N,t.dashLengths,B,c)})})}return _.slice(0,a)}resolvePatternLineTransform(e,t){const n=Number(t.angle??e.patternAngle??0);return{dir:new b.Vector2(Math.cos(n),Math.sin(n)).normalize(),base:this.toVector2(t.basePoint),offset:this.toVector2(t.offset)}}toVector2(e){return new b.Vector2(e?.[0]??0,e?.[1]??0)}getBounds(e){return{minX:Math.min(...e.map(t=>t[0])),minY:Math.min(...e.map(t=>t[1])),maxX:Math.max(...e.map(t=>t[0])),maxY:Math.max(...e.map(t=>t[1]))}}clipLineByPolygon(e,t,n){const i=[0,1];for(let a=0;a<n.length;a+=1){const l=new b.Vector2(n[a][0],n[a][1]),c=new b.Vector2(n[(a+1)%n.length][0],n[(a+1)%n.length][1]),h=this.segmentIntersectionT(e,t,l,c);h!==null&&h>Tt&&h<1-Tt&&i.push(h)}const r=this.dedupeSorted(i.sort((a,l)=>a-l),1e-7),o=[];for(let a=0;a<r.length-1;a+=1){const l=r[a],c=r[a+1];if(c-l<1e-7)continue;const h=this.interpolate2(e,t,(l+c)/2);this.pointInPolygon(h,n)&&o.push([this.interpolate2(e,t,l),this.interpolate2(e,t,c)])}return o}subtractHoles(e,t,n){let i=[[e,t]];return n.forEach(r=>{const o=[];i.forEach(([a,l])=>{const c=this.clipLineByPolygon(a,l,r);o.push(...this.subtractSegments(a,l,c))}),i=o}),i}appendDashedSegment(e,t,n,i,r,o){const a=t.distanceTo(n);if(a<Tt)return;if(!i?.length){e.push([t,n]);return}const l=this.normalizeDashPattern(i),c=l.reduce((y,v)=>y+v.length,0);if(c<Tt){e.push([t,n]);return}const h=o?.clone().normalize()??n.clone().sub(t).normalize(),u=r??t,f=n.clone().sub(t).normalize().dot(h)>=0?1:-1,m=t.clone().sub(u).dot(h)*f,g=this.positiveModulo(m,c);let A=0,p=this.findDashIndex(l,g),x=g-l[p].start;for(;A<a-Tt;){const y=l[p],v=Math.max(y.length-x,Tt),_=Math.min(a,A+v);y.draw&&e.push([this.pointAtLength(t,n,A),this.pointAtLength(t,n,_)]),A=_,p=(p+1)%l.length,x=0}}normalizeDashPattern(e){let t=0;return e.map(n=>{const i=Number(n??0),r={length:Math.max(Math.abs(i),5e-4),draw:i>=0,start:t};return t+=r.length,r}).filter(n=>n.length>Tt)}findDashIndex(e,t){for(let n=e.length-1;n>=0;n-=1)if(t>=e[n].start-Tt)return n;return 0}positiveModulo(e,t){return(e%t+t)%t}subtractSegments(e,t,n){const i=n.map(([a,l])=>[this.projectT(e,t,a),this.projectT(e,t,l)]).map(([a,l])=>[Math.max(0,Math.min(a,l)),Math.min(1,Math.max(a,l))]).sort((a,l)=>a[0]-l[0]),r=[];let o=0;return i.forEach(([a,l])=>{a>o+Tt&&r.push([this.interpolate2(e,t,o),this.interpolate2(e,t,a)]),o=Math.max(o,l)}),o<1-Tt&&r.push([this.interpolate2(e,t,o),this.interpolate2(e,t,1)]),r}segmentIntersectionT(e,t,n,i){const r=t.clone().sub(e),o=i.clone().sub(n),a=this.cross2(r,o);if(Math.abs(a)<1e-10)return null;const l=n.clone().sub(e),c=this.cross2(l,o)/a,h=this.cross2(l,r)/a;return c>=-1e-8&&c<=1+1e-8&&h>=-1e-8&&h<=1+1e-8?c:null}pointInPolygon(e,t){let n=!1;for(let i=0,r=t.length-1;i<t.length;r=i,i+=1){const o=t[i][0],a=t[i][1],l=t[r][0],c=t[r][1];a>e.y!=c>e.y&&e.x<(l-o)*(e.y-a)/(c-a+1e-20)+o&&(n=!n)}return n}cross2(e,t){return e.x*t.y-e.y*t.x}interpolate2(e,t,n){return e.clone().lerp(t,n)}projectT(e,t,n){const i=t.clone().sub(e),r=i.lengthSq();return r<1e-12?0:n.clone().sub(e).dot(i)/r}pointAtLength(e,t,n){const i=e.distanceTo(t);return this.interpolate2(e,t,i<1e-12?0:n/i)}dedupeSorted(e,t){const n=[];return e.forEach(i=>{(!n.length||Math.abs(i-n[n.length-1])>t)&&n.push(i)}),n}}class o3{constructor(e,t){this.engine=e,this.textFactory=t,this.hatchRenderer=new r3(e)}hatchRenderer;create(e,t){switch(e.type){case"LINE_GROUP":case"LINE":case"CIRCLE":case"POLYLINE":case"SPLINE":return this.createLineItem(e,t);case"MTEXT":case"TEXT":return this.textFactory.create(e,t);case"HATCH":return this.createHatch(e,t);case"IMAGE":return this.createImage(e,t);default:return[]}}createLineItem(e,t){const n=this.getEntityPoints(e).map(i=>i.clone().applyMatrix4(t));return n.length===0?[]:[{kind:"line",layer:e.layer,color:e.color,lineType:e.lineType,lineTypeScale:e.lineTypeScale,lineTypePattern:Array.isArray(e.lineTypePattern)?e.lineTypePattern:void 0,linkId:e.linkId??e.id,points:n,info:e}]}getEntityPoints(e){switch(e.type){case"LINE_GROUP":return this.getLineGroupPoints(e);case"LINE":return[ks(e.startPoint),ks(e.endPoint)];case"CIRCLE":return this.getCirclePoints(e);case"POLYLINE":return this.getPolylinePoints(e);case"SPLINE":return this.getSplinePoints(e);default:return[]}}getLineGroupPoints(e){const t=[];return(e.segments??[]).forEach(n=>{t.push(new b.Vector3(n[0]??0,n[1]??0,n[2]??0)),t.push(new b.Vector3(n[3]??0,n[4]??0,n[5]??0))}),t}getCirclePoints(e){const t=new b.EllipseCurve(e.center?.[0]??0,e.center?.[1]??0,e.radius??0,e.radius??0,e.startAngle??0,(e.endAngle??Math.PI*2)-1e-5,!1,0);return this.pointsToSegments(t.getPoints(this.engine.options?.circleSegments??48).map(n=>new b.Vector3(n.x,n.y,e.center?.[2]??0)))}getPolylinePoints(e){const t=[],n=e.points??[];for(let i=0;i<n.length-1;i+=1)this.getPolylineSegmentPoints(n[i],n[i+1]).forEach(r=>{t.push(r)});return e.closed&&n.length>1&&this.getPolylineSegmentPoints(n[n.length-1],n[0]).forEach(i=>{t.push(i)}),t}getPolylineSegmentPoints(e,t){const n=ks(e),i=ks(t),r=Number(e?.bulge??0);if(!Number.isFinite(r)||Math.abs(r)<1e-10)return[n,i];const o=i.clone().sub(n),a=o.length();if(a<1e-12)return[n,i];const l=4*Math.atan(r),c=a*(1+r*r)/(4*Math.abs(r)),h=n.clone().add(i).multiplyScalar(.5),u=new b.Vector3(-o.y/a,o.x/a,0),d=h.clone().add(u.multiplyScalar(a*(1-r*r)/(4*r))),f=Math.atan2(n.y-d.y,n.x-d.x),m=Math.max(4,Math.ceil(Math.abs(l)/(this.engine.options?.polylineArcAngleStep??Math.PI/18))),g=[];for(let A=0;A<=m;A+=1){const p=A/m,x=f+l*p;g.push(new b.Vector3(d.x+Math.cos(x)*c,d.y+Math.sin(x)*c,n.z+(i.z-n.z)*p))}return this.pointsToSegments(g)}getSplinePoints(e){const t=(e.points??[]).map(i=>ks(i));if(t.length<2)return[];const n=t.length===2?t:this.sampleSplineCurve(t,e);return this.pointsToSegments(n)}sampleSplineCurve(e,t){const n=Math.min(Math.max(Number(t.degree??this.engine.options?.splineDegree??6),1),e.length-1),i=Array.isArray(t.knots)&&t.knots.length===e.length+n+1?t.knots:this.createClampedUniformKnots(e.length,n),r=e.map((l,c)=>{const h=Array.isArray(t.weights)?Number(t.weights[c]??1):1;return new b.Vector4(l.x,l.y,l.z,Number.isFinite(h)?h:1)});let o=(e.length-1)*2;const a=new i3(n,i,r).getPoints(o);return t.closed===!0&&a.length>1&&a.push(a[0].clone()),a}createClampedUniformKnots(e,t){const n=[];for(let i=0;i<e+t+1;i+=1)i<=t?n.push(0):i>=e?n.push(1):n.push((i-t)/(e-t));return n}pointsToSegments(e){const t=[];for(let n=0;n<e.length-1;n+=1)t.push(e[n].clone(),e[n+1].clone());return t}createHatch(e,t){return this.hatchRenderer.create(e,t)}createImage(e,t){const n=e.imageUrl||e.url;if(!n)return[];const i=ks(e.position),r=ks(e.uVector),o=ks(e.vVector),a=Number(e.pixelWidth??e.width??1),l=Number(e.pixelHeight??e.height??1);if(!Number.isFinite(a)||!Number.isFinite(l)||a===0||l===0)return[];const c=r.multiplyScalar(a),h=o.multiplyScalar(l),u=i.clone(),d=i.clone().add(c),f=i.clone().add(c).add(h),m=i.clone().add(h);[u,d,f,m].forEach(x=>x.applyMatrix4(t));const g=new b.BufferGeometry;g.setAttribute("position",new b.Float32BufferAttribute([u.x,u.y,u.z,d.x,d.y,d.z,f.x,f.y,f.z,u.x,u.y,u.z,f.x,f.y,f.z,m.x,m.y,m.z],3)),g.setAttribute("uv",new b.Float32BufferAttribute([0,0,1,0,1,1,0,0,1,1,0,1],2)),g.computeVertexNormals();const A=Mr(g),p=Number(e.fade??0);return[{kind:"image",layer:e.layer??"0",color:e.color??16777215,linkId:e.linkId??e.id,geometry:g,imageUrl:n,opacity:Number.isFinite(p)?b.MathUtils.clamp(1-p/100,0,1):1,min:A.min,max:A.max,info:e}]}}class a3{constructor(e,t,n=e.modelGroup){this.model=t,this.targetGroup=n}modelMap=new Map;hatchMap=new Map;textMap=new Map;imageMap=new Map;textureLoader=new b.TextureLoader;addRenderItems(e){e.forEach(t=>this.addRenderItem(t))}buildSceneObjects(){this.buildImageObjects(),this.buildHatchObjects(),this.buildLineObjects(),this.buildTextObjects()}addRenderItem(e){const t=`${e.layer}||${e.color}`;if(e.kind==="line"){let o=this.modelMap.get(t);o||(o=new Map,this.modelMap.set(t,o));const a=this.resolveLinePoints(e),l=o.get(e.linkId);l?a.forEach(c=>l.push(c)):o.set(e.linkId,[...a]);return}const n=this.getItemMap(e),i=e.kind==="image"?`${t}||${e.imageUrl??""}`:t,r=n.get(i);r?r.push(e):n.set(i,[e])}getItemMap(e){return e.kind==="text"?this.textMap:e.kind==="image"?this.imageMap:this.hatchMap}resolveLinePoints(e){const t=e.points??[],n=this.resolveLineTypePattern(e);if(!n)return t;const i=[];for(let r=0;r<t.length-1;r+=2)this.applyDashPattern(t[r],t[r+1],n).forEach(o=>i.push(o));return i}resolveLineTypePattern(e){const t=this.model.layers.find(l=>l.name===e.layer),n=String(e.lineType??"").toLowerCase(),i=n==="bylayer"||n===""?String(t?.lineType??"").toLowerCase():n;if(!i||i==="continuous"||i==="byblock")return null;const r=Array.isArray(e.lineTypePattern)&&e.lineTypePattern.length>0?e.lineTypePattern:Array.isArray(t?.lineTypePattern)?t.lineTypePattern:this.getFallbackLineTypePattern(i);if(!r||r.length===0)return null;const o=this.resolveLineTypeScale(e,t),a=r.map(l=>Number(l)).filter(l=>Number.isFinite(l)).map(l=>l*o);return a.some(l=>Math.abs(l)>1e-12)?a:null}getFallbackLineTypePattern(e){return e.includes("dash")?[.25,-.1]:e.includes("dot")?[0,-.1]:null}resolveLineTypeScale(e,t){const n=Number(e.lineTypeScale??t?.lineTypeScale??1);return!Number.isFinite(n)||Math.abs(n)<1e-12?1:Math.abs(n)}applyDashPattern(e,t,n){const i=t.clone().sub(e),r=i.length();if(r<1e-12)return[];const o=i.multiplyScalar(1/r),a=n.reduce((d,f)=>d+Math.abs(f),0),l=Math.max(a*.05,r*.002,1e-6),c=[];let h=0,u=0;for(;h<r-1e-12;){const d=n[u%n.length],f=d>=0,m=Math.max(Math.abs(d),l),g=Math.min(h+m,r);if(f&&g>h&&c.push(e.clone().add(o.clone().multiplyScalar(h)),e.clone().add(o.clone().multiplyScalar(g))),h=g,u+=1,u>1e5)break}return c}buildLineObjects(){this.modelMap.forEach((e,t)=>{const[n]=t.split("||"),i=[];if(e.forEach(u=>{u.forEach(d=>i.push(d))}),i.length===0)return;const r=new b.BufferGeometry().setFromPoints(i),o=new b.LineBasicMaterial({color:this.resolveColor(t)}),a=new b.LineSegments(r,o);a.name=t;const l=r.getAttribute("position");a.clonePoints=l.array.slice(),a.materialClone=o.clone(),this.targetGroup.add(a);const c=this.targetGroup.children.length-1;let h=0;e.forEach((u,d)=>{const f=Ry(u);this.pushNodeMap(d,{indexes:[c,h,h+u.length*3],object:a,group:this.targetGroup,kind:"line",layer:n,min:f.min,max:f.max}),h+=u.length*3})})}buildTextObjects(){this.textMap.forEach((e,t)=>{const n=e.filter(a=>!!a.geometry),i=this.normalizeMeshGeometries(n,!1,!1);if(i.length===0)return;const r=this.mergeMeshGeometries(i),o=new b.MeshBasicMaterial({color:this.resolveColor(t),side:b.DoubleSide});t.includes("_hitbox")&&(o.visible=!1),this.addMeshObject(n,t,r,i,o)})}buildHatchObjects(){this.hatchMap.forEach((e,t)=>{const n=e.filter(l=>!!l.geometry),i=n.some(l=>l.useVertexColors===!0),r=this.normalizeMeshGeometries(n,!1,i);if(r.length===0)return;const o=this.mergeMeshGeometries(r),a=new b.MeshBasicMaterial({color:i?16777215:this.resolveColor(t),side:b.DoubleSide,transparent:!0,opacity:i?1:.5,vertexColors:i});this.addMeshObject(n,t,o,r,a)})}buildImageObjects(){this.imageMap.forEach((e,t)=>{const n=e.filter(h=>!!h.geometry),i=this.normalizeMeshGeometries(n,!0,!1);if(i.length===0)return;const r=n[0]?.imageUrl;if(!r)return;const o=this.mergeMeshGeometries(i),a=this.textureLoader.load(r);a.colorSpace=b.SRGBColorSpace,a.needsUpdate=!0;const l=n.reduce((h,u)=>Math.min(h,u.opacity??1),1),c=new b.MeshBasicMaterial({map:a,side:b.DoubleSide,transparent:!0,opacity:l,depthWrite:!1});this.addMeshObject(n,t,o,i,c)})}mergeMeshGeometries(e){const t=e.length===1?e[0]:_i(e,!0);if(t.groups.length===0){const n=t.getAttribute("position");t.addGroup(0,n?.count??0,0)}return t.groups.forEach(n=>{n.materialIndex=0}),t}normalizeMeshGeometries(e,t,n){return e.map(i=>{const r=i.geometry,o=r.index?r.toNonIndexed():r.clone(),a=o.getAttribute("position"),l=o.getAttribute("uv"),c=o.getAttribute("color"),h=new b.BufferGeometry;return h.setAttribute("position",a.clone()),t&&h.setAttribute("uv",l?l.clone():this.createEmptyUv(a.count)),n&&h.setAttribute("color",c?c.clone():this.createSolidColorAttribute(a.count,i.color)),h})}createEmptyUv(e){return new b.Float32BufferAttribute(new Array(e*2).fill(0),2)}createSolidColorAttribute(e,t){const n=new b.Color(t??16777215),i=[];for(let r=0;r<e;r+=1)i.push(n.r,n.g,n.b);return new b.Float32BufferAttribute(i,3)}addMeshObject(e,t,n,i,r){const o=new b.Mesh(n,r);o.name=t,o.materialClone=r.clone(),o.isSplit=!1,o.geometrys=void 0,i.forEach(l=>{l!==n&&l.dispose()}),this.targetGroup.add(o);const a=this.targetGroup.children.length-1;e.forEach((l,c)=>{const h=l.linkId??l.info?.id;this.pushNodeMap(h,{indexes:[a,c],object:o,group:this.targetGroup,kind:l.kind,layer:l.layer,info:l.info,min:l.min??new b.Vector3,max:l.max??new b.Vector3}),this.pushTextSearchItem(l,t)})}pushTextSearchItem(e,t){if(e.kind!=="text"||t.includes("_hitbox"))return;const n=e.info?.text,i=String(n??"").replace(/\r\n/g,`
5553
+ </svg>`}_colorToHex(e){return"#"+e.toString(16).padStart(6,"0")}_makeDraggable(e,t){t.onmousedown=n=>{n.preventDefault();const i=e.getBoundingClientRect(),r=e.offsetParent?.getBoundingClientRect()??{left:0,top:0};e.style.left=i.left-r.left+"px",e.style.top=i.top-r.top+"px",e.style.right="auto",e.style.bottom="auto";const o=n.clientX-i.left,a=n.clientY-i.top,l=h=>{e.style.left=h.clientX-o-r.left+"px",e.style.top=h.clientY-a-r.top+"px"},c=()=>{document.removeEventListener("mousemove",l),document.removeEventListener("mouseup",c)};document.addEventListener("mousemove",l),document.addEventListener("mouseup",c)}}dispose(){this.panel?.remove(),this.panel=null,this.listEl=null}}class Ly{engine;layerMap=new Map;panelUI=null;constructor(e){this.engine=e;const t=document.getElementById(e?.options?.containerId??"")??e?.container??null;t&&(this.panelUI=new WP(t,this))}_loadLayers(e=this.engine.dwgData?.layers??[]){this.layerMap.clear();for(const t of e)this.layerMap.set(t.name,{...t});this.panelUI?.refresh()}syncFromModel(e){e?.length>0&&(this._loadLayers(e),this.panelUI?.refresh())}getLayers(){return Array.from(this.layerMap.values())}getDisplayColor(e){return this.engine.modelToolModule2d?.getDisplayColor(e)??e}refresh(){this.panelUI?.refresh()}setLayerVisible(e,t){const n=this.layerMap.get(e);n&&(n.visible=t),this._applyVisibility(e,t),t||this.clearInteractiveStateForLayer(e)}toggleLayer(e){const t=this.layerMap.get(e);if(!t)return!0;const n=!t.visible;return this.setLayerVisible(e,n),n}setAllLayersVisible(e){for(const t of this.layerMap.keys()){const n=this.layerMap.get(t);n.visible=e,this._applyVisibility(t,e)}}isAllVisible(){return Array.from(this.layerMap.values()).every(e=>e.visible)}isLayerVisible(e){return e?this.layerMap.get(e)?.visible!==!1:!0}isModelVisibleByLayer(e){const t=this.engine.loaderModule2d?.model?.nodeMap?.get(String(e))??this.engine.loaderModule2d?.model?.nodeMap?.get(e);return!t||t.length===0?!0:t.some(n=>{const i=this.getNodeObject(n);return this.isLayerVisible(n?.layer)&&i?.visible!==!1})}_applyVisibility(e,t){const n=this.engine?.modelGroup??this.engine?.scene;if(!n)return;const i=e+"||";n.traverse(r=>{r.name?.startsWith(i)&&(r.visible=t)})}getNodeObject(e){return e?.object??e?.group?.children?.[e.indexes?.[0]]??this.engine.modelGroup?.children?.[e.indexes?.[0]]}clearInteractiveStateForLayer(e){const t=[...this.engine.engineStatus2d?.highlightModels??[],...this.engine.engineStatus2d?.highlightHoverModels??[]];t.length===0||!t.some(i=>(this.engine.loaderModule2d?.model?.nodeMap?.get(String(i))??this.engine.loaderModule2d?.model?.nodeMap?.get(i))?.some(o=>o?.layer===e))||(this.engine.modelToolModule2d?.unHighlightModelHover?.(),this.engine.modelToolModule2d?.unhighlightAllModels?.())}show(){this.panelUI?.show()}hide(){this.panelUI?.hide()}toggle(){this.panelUI?.toggle()}dispose(){this.panelUI?.dispose(),this.panelUI=null,this.layerMap.clear()}}var li=(s=>(s.ModelLoadStart="model-load-start",s.ModelLoadProgress="model-load-progress",s.ModelLoaded="model-loaded",s.ModelLoadError="model-load-error",s.RenderStart="render-start",s.RenderEnd="render-end",s.CameraChanged="camera-changed",s.CameraReset="camera-reset",s.SelectionChanged="selection-changed",s.HoverChanged="hover-changed",s.EntityClick="entity-click",s.LayerVisibilityChanged="layer-visibility-changed",s.LayerColorChanged="layer-color-changed",s.ViewZoomChanged="view-zoom-changed",s.ViewPanChanged="view-pan-changed",s.ToolActivated="tool-activated",s.ToolDeactivated="tool-deactivated",s.Error="error",s.Warning="warning",s))(li||{});class HP{listeners=new Map;onceListeners=new Map;debugMode=!1;constructor(e=!1){this.debugMode=e,this.initializeEvents()}initializeEvents(){Object.values(li).forEach(t=>{this.listeners.set(t,new Set),this.onceListeners.set(t,new Set)})}on(e,t){return this.listeners.has(e)?(this.listeners.get(e).add(t),this.debugMode&&console.log(`[EventModule2d] Listener added for ${e}`),()=>this.off(e,t)):(console.warn(`Event type ${e} is not registered`),()=>{})}once(e,t){if(!this.onceListeners.has(e)){console.warn(`Event type ${e} is not registered`);return}this.onceListeners.get(e).add(t),this.debugMode&&console.log(`[EventModule2d] Once listener added for ${e}`)}off(e,t){const n=this.listeners.get(e);n&&(n.delete(t),this.debugMode&&console.log(`[EventModule2d] Listener removed for ${e}`))}trigger(e,t){this.debugMode&&console.log(`[EventModule2d] Triggering ${e}`,t);const n=this.listeners.get(e);n&&n.size>0&&n.forEach(r=>{try{r(t)}catch(o){console.error(`[EventModule2d] Error in listener for ${e}:`,o)}});const i=this.onceListeners.get(e);i&&i.size>0&&(i.forEach(r=>{try{r(t)}catch(o){console.error(`[EventModule2d] Error in once listener for ${e}:`,o)}}),i.clear())}removeAllListeners(){this.listeners.forEach(e=>e.clear()),this.onceListeners.forEach(e=>e.clear()),this.debugMode&&console.log("[EventModule2d] All listeners removed")}removeListenersOfType(e){const t=this.listeners.get(e),n=this.onceListeners.get(e);t&&t.clear(),n&&n.clear(),this.debugMode&&console.log(`[EventModule2d] All listeners removed for ${e}`)}getListenerCount(e){const t=this.listeners.get(e),n=this.onceListeners.get(e);return(t?.size||0)+(n?.size||0)}setDebugMode(e){this.debugMode=e}getAllEventTypes(){return Object.values(li)}dispose(){this.removeAllListeners(),this.listeners.clear(),this.onceListeners.clear(),this.debugMode&&console.log("[EventModule2d] Disposed")}}function ks(s){return Array.isArray(s)?new b.Vector3(s[0]??0,s[1]??0,s[2]??0):new b.Vector3(s?.x??0,s?.y??0,s?.z??0)}function Mr(s){return s?(s.computeBoundingBox(),{min:s.boundingBox?.min.clone()??new b.Vector3,max:s.boundingBox?.max.clone()??new b.Vector3}):{min:new b.Vector3,max:new b.Vector3}}function cp(s,e,t){const n=new b.Vector3(s[0]??0,s[1]??0,s[2]??0),i=new b.Euler(0,0,t??0),r=new b.Vector3(e[0]??1,e[1]??1,e[2]??1),o=new b.Quaternion().setFromEuler(i);return new b.Matrix4().compose(n,o,r)}function qP(s){return Array.isArray(s?.transformMatrix)&&s.transformMatrix.length===16?new b.Matrix4().fromArray(s.transformMatrix):cp(s.position??[0,0,0],s.scale??[1,1,1],s.rotation??0)}function Ry(s){if(s.length===0)return{min:new b.Vector3,max:new b.Vector3};const e=new b.Vector3(Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY),t=new b.Vector3(Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY);return s.forEach(n=>{e.x=Math.min(e.x,n.x),e.y=Math.min(e.y,n.y),e.z=Math.min(e.z,n.z),t.x=Math.max(t.x,n.x),t.y=Math.max(t.y,n.y),t.z=Math.max(t.z,n.z)}),{min:e,max:t}}class XP{constructor(e){this.geometryFactory=e}cache=new Map;blockIndex=new Map;setBlocks(e){this.cache.clear(),this.blockIndex.clear(),(e??[]).forEach(t=>{t?.name&&this.blockIndex.set(t.name,t),t?.id&&this.blockIndex.set(t.id,t)})}clearCache(){this.cache.clear()}flattenRootEntities(e){return Array.from(this.iterateRootEntities(e))}*iterateRootEntities(e){yield*this.iterateEntities(e??[],new b.Matrix4,0)}flattenBlock(e,t,n){const i=this.cache.get(t);if(i)return i;const r=e.origin??[0,0,0],o=new b.Matrix4().makeTranslation(-r[0],-r[1],-(r[2]??0)),a=this.flattenEntities(e.entities??[],o,n);return this.cache.set(t,a),e.name&&this.cache.set(e.name,a),e.id&&this.cache.set(e.id,a),a}flattenEntities(e,t,n){return Array.from(this.iterateEntities(e,t,n))}*iterateEntities(e,t,n){if(n>20){console.warn("[LoaderModule2d] Block nesting is too deep, skip nested INSERT.");return}for(const i of e)if(i?.visible!==!1){if(i.type==="INSERT"){const r=this.getBlockItems(i.blockId,n+1),o=t.clone().multiply(qP(i)),a=this.getClipPolygon(i,t);for(const l of r){const c=this.cloneRenderItem(l,o,i),h=a?this.clipRenderItem(c,a):c;h&&(yield h)}a&&i.displayClipBoundary===!0&&(yield this.createClipBoundaryItem(i,a));continue}for(const r of this.geometryFactory.create(i,t))yield r}}getBlockItems(e,t){const n=this.cache.get(e);if(n)return n;const i=this.blockIndex.get(e);return i?this.flattenBlock(i,i.name??i.id??e,t):(console.warn(`[LoaderModule2d] Missing block: ${e}`),[])}cloneRenderItem(e,t,n){const i=e.layer==="0"&&n?.layer?n.layer:e.layer??n?.layer,r=e.color==null||e.color===0?n?.color??e.color??0:e.color,o=n?.linkId??n?.id??e.linkId;if(e.kind==="line")return{...e,layer:i,color:r,linkId:o,points:(e.points??[]).map(h=>h.clone().applyMatrix4(t))};const a=e.geometry?.clone();a?.applyMatrix4(t);const l=e.textAnchor?.clone().applyMatrix4(t),c=Mr(a);return{...e,layer:i,color:r,linkId:o,geometry:a,min:c.min,max:c.max,textAnchor:l}}getClipPolygon(e,t){if(e?.clipping!==!0||!Array.isArray(e?.clipBoundary))return null;const n=e.clipBoundary.map(r=>new b.Vector3(r?.[0]??r?.x??0,r?.[1]??r?.y??0,r?.[2]??r?.z??0)).filter(r=>Number.isFinite(r.x)&&Number.isFinite(r.y));if(n.length<3)return null;const i=this.getClipBoundaryMatrix(e,t);return i?n.map(r=>r.clone().applyMatrix4(i)):n}getClipBoundaryMatrix(e,t){return!Array.isArray(e?.clipInsertTransform)||e.clipInsertTransform.length!==16?null:t.clone().multiply(new b.Matrix4().fromArray(e.clipInsertTransform))}clipRenderItem(e,t){if(e.kind==="line"){const r=this.clipLinePoints(e.points??[],t);if(r.length===0)return null;const o=this.getPointsBounds(r);return{...e,points:r,min:o.min,max:o.max}}const n=this.clipGeometry(e.geometry,t);if(!n)return null;const i=Mr(n);return{...e,geometry:n,min:i.min,max:i.max}}clipLinePoints(e,t){const n=[];for(let i=0;i<e.length-1;i+=2)this.clipSegmentByPolygon(e[i],e[i+1],t).forEach(r=>{n.push(r[0],r[1])});return n}clipSegmentByPolygon(e,t,n){const i=t.clone().sub(e),r=[0,1];for(let l=0;l<n.length;l+=1){const c=this.getSegmentIntersectionParameter(e,t,n[l],n[(l+1)%n.length]);c!=null&&c>1e-9&&c<1-1e-9&&r.push(c)}const o=Array.from(new Set(r.map(l=>Number(l.toFixed(12))))).sort((l,c)=>l-c),a=[];for(let l=0;l<o.length-1;l+=1){const c=o[l],h=o[l+1];if(h-c<1e-10)continue;const u=(c+h)*.5,d=e.clone().add(i.clone().multiplyScalar(u));this.isPointInPolygon(d,n)&&a.push([e.clone().add(i.clone().multiplyScalar(c)),e.clone().add(i.clone().multiplyScalar(h))])}return a}getSegmentIntersectionParameter(e,t,n,i){const r=t.x-e.x,o=t.y-e.y,a=i.x-n.x,l=i.y-n.y,c=r*l-o*a;if(Math.abs(c)<1e-12)return null;const h=n.x-e.x,u=n.y-e.y,d=(h*l-u*a)/c,f=(h*o-u*r)/c;return d>=-1e-9&&d<=1+1e-9&&f>=-1e-9&&f<=1+1e-9?b.MathUtils.clamp(d,0,1):null}isPointInPolygon(e,t){let n=!1;for(let i=0,r=t.length-1;i<t.length;r=i,i+=1){const o=t[i],a=t[r];if(this.isPointOnSegment(e,o,a))return!0;o.y>e.y!=a.y>e.y&&e.x<(a.x-o.x)*(e.y-o.y)/(a.y-o.y)+o.x&&(n=!n)}return n}isPointOnSegment(e,t,n){const i=(n.x-t.x)*(e.y-t.y)-(n.y-t.y)*(e.x-t.x);if(Math.abs(i)>1e-8)return!1;const r=(e.x-t.x)*(n.x-t.x)+(e.y-t.y)*(n.y-t.y),o=(n.x-t.x)**2+(n.y-t.y)**2;return r>=-1e-8&&r<=o+1e-8}clipGeometry(e,t){if(!e?.attributes?.position)return null;const n=e.attributes.position,i=e.attributes.uv,r=e.index,o=[],a=[],l=!!i,c=this.triangulateClipPolygon(t),h=f=>({position:new b.Vector3(n.getX(f),n.getY(f),n.getZ(f)),uv:l?new b.Vector2(i.getX(f),i.getY(f)):void 0}),u=r?r.count:n.count;for(let f=0;f<u;f+=3){const m=r?r.getX(f):f,g=r?r.getX(f+1):f+1,A=r?r.getX(f+2):f+2,p=[h(m),h(g),h(A)];c.forEach(x=>{const y=this.clipTriangle(p,x);if(!(y.length<3))for(let v=1;v<y.length-1;v+=1)[y[0],y[v],y[v+1]].forEach(_=>{o.push(_.position.x,_.position.y,_.position.z),l&&_.uv&&a.push(_.uv.x,_.uv.y)})})}if(o.length===0)return null;const d=new b.BufferGeometry;return d.setAttribute("position",new b.Float32BufferAttribute(o,3)),l&&d.setAttribute("uv",new b.Float32BufferAttribute(a,2)),d.computeVertexNormals(),d}triangulateClipPolygon(e){const t=e.map(i=>new b.Vector2(i.x,i.y)),n=b.ShapeUtils.triangulateShape(t,[]);if(n.length===0){const i=[];for(let r=1;r<e.length-1;r+=1)i.push([e[0],e[r],e[r+1]]);return i}return n.map(i=>i.map(r=>e[r]))}clipTriangle(e,t){const n=this.getPolygonOrientation(t);let i=e;for(let r=0;r<t.length;r+=1){const o=t[r],a=t[(r+1)%t.length],l=i;if(i=[],l.length===0)break;let c=l[l.length-1],h=this.isInsideClipEdge(c.position,o,a,n);l.forEach(u=>{const d=this.isInsideClipEdge(u.position,o,a,n);d!==h&&i.push(this.intersectClipEdge(c,u,o,a,n)),d&&i.push(u),c=u,h=d})}return i}isInsideClipEdge(e,t,n,i){const r=n.x-t.x,o=n.y-t.y;return i*(r*(e.y-t.y)-o*(e.x-t.x))>=-1e-9}intersectClipEdge(e,t,n,i,r){const o=i.x-n.x,a=i.y-n.y,l=r*(o*(e.position.y-n.y)-a*(e.position.x-n.x)),c=r*(o*(t.position.y-n.y)-a*(t.position.x-n.x)),h=Math.abs(l-c)<1e-12?0:l/(l-c);return{position:e.position.clone().lerp(t.position,h),uv:e.uv&&t.uv?e.uv.clone().lerp(t.uv,h):void 0}}getPolygonOrientation(e){let t=0;for(let n=0;n<e.length;n+=1){const i=e[n],r=e[(n+1)%e.length];t+=i.x*r.y-r.x*i.y}return t>=0?1:-1}getPointsBounds(e){const t=new b.Vector3(Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY),n=new b.Vector3(Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY);return e.forEach(i=>{t.min(i),n.max(i)}),{min:t,max:n}}createClipBoundaryItem(e,t){const n=[];for(let r=0;r<t.length;r+=1)n.push(t[r].clone(),t[(r+1)%t.length].clone());const i=this.getPointsBounds(n);return{kind:"line",layer:e.layer??"0",color:e.clipBoundaryColor??16711935,lineType:"Continuous",linkId:e.linkId??e.id,points:n,min:i.min,max:i.max,info:e}}}class YP{zipObjectUrls=[];async load(e){return this.clearZipObjectUrls(),this.loadZipData(e)}async fetchJson(e){const t=await fetch(e);if(!t.ok)throw new Error(`HTTP error! status: ${t.status}`);return t.json()}async loadSplitData(e,t,n=r=>this.fetchJson(r),i=(r,o)=>Promise.resolve(this.resolveImageUrl(r,o))){const[r,o,a,l]=await Promise.all([n(this.joinUrl(e,t.metadataUrl??"metadata.json")),n(this.joinUrl(e,t.layersUrl??"layers.json")),this.loadBlocks(e,t.blocksUrl??"blocks/index.json",n),this.loadTiles(e,t.root,n)]);await this.resolveBlockAssets(a,e,i);const c=[];return l.forEach(h=>{h.inserts.forEach(u=>c.push(u))}),{version:t.version??"1.0",metadata:r,layers:o,blocks:a,entities:c,octree:t.root,tiles:l}}async loadBlocks(e,t,n){const r=(await n(this.joinUrl(e,t))).parts??[],o=await Promise.all(r.map(l=>this.loadBlockPart(this.joinUrl(e,l),n))),a=[];return o.forEach(l=>{(Array.isArray(l?.blocks)?l.blocks:[]).forEach(h=>a.push(h))}),a}async loadBlockPart(e,t){try{return await t(e)}catch(n){const i=n instanceof Error?n.message:String(n);return console.warn(`[LoaderModule2d] Skip missing block json: ${e}`,i),{blocks:[]}}}async resolveBlockAssets(e,t,n){await Promise.all(e.map(async i=>{const r=Array.isArray(i?.entities)?i.entities:[];await Promise.all(r.map(async o=>{String(o?.type).toUpperCase()==="IMAGE"&&(o.imageUrl=await n(o,t))}))}))}resolveImageUrl(e,t){const n=e.localPath||e.sourcePath||e.path||e.url||"";if(/^(https?:)?\/\//i.test(n)||n.startsWith("/"))return n;const r=String(n).replace(/\\/g,"/").split("/").filter(Boolean).pop();return r?this.joinUrl(t,r):""}async loadTiles(e,t,n){const i=this.collectTileNodes(t);return await Promise.all(i.map(async o=>{const a=o.tileUrl??"",l=await n(this.joinUrl(e,a)),c=this.normalizeTileInserts(l.inserts??[]);return o.elements=c.map(h=>h.linkId??h.id).filter(h=>h!=null),{id:o.id??l.id??a,url:a,node:o,inserts:c}}))}normalizeTileInserts(e){return e.map(t=>({...t,linkId:t.linkId??t.id,type:"INSERT",color:t.color??0,visible:t.visible??!0}))}collectTileNodes(e){if(!e)return[];const t=[],n=[e];for(;n.length>0;){const i=n.pop();if(!i)continue;i.tileUrl&&t.push(i);const r=i.children??[];for(let o=r.length-1;o>=0;o-=1)n.push(r[o])}return t}async loadZipData(e){const t=await fetch(e);if(!t.ok)throw new Error(`HTTP error! status: ${t.status}`);const n=await zd.loadAsync(await t.arrayBuffer()),i=this.findZipManifestPath(n),r=await this.fetchZipJson(n,i);if(!this.isSplitManifest(r))throw new Error("[LoaderModule2d] Expected split CAD manifest data in .2d package.");const o=this.getZipBasePath(i);return this.loadSplitData(o,r,a=>this.fetchZipJson(n,a),(a,l)=>this.resolveZipImageUrl(n,a,l))}findZipManifestPath(e){const t=Object.keys(e.files).filter(r=>!e.files[r].dir),i=t.find(r=>this.normalizeZipPath(r).toLowerCase()==="manifest.json")??t.find(r=>this.normalizeZipPath(r).toLowerCase().endsWith("/manifest.json"));if(!i)throw new Error("[LoaderModule2d] Missing manifest.json in .2d package.");return this.normalizeZipPath(i)}async fetchZipJson(e,t){if(/^(https?:)?\/\//i.test(t))return this.fetchJson(t);const n=this.getZipFile(e,t);if(!n)throw new Error(`[LoaderModule2d] Missing file in .2d package: ${t}`);return JSON.parse(await n.async("string"))}async resolveZipImageUrl(e,t,n){const i=t.localPath||t.sourcePath||t.path||t.url||"";if(/^(https?:)?\/\//i.test(i)||String(i).startsWith("blob:"))return i;const r=this.normalizeZipPath(String(i)),o=r.split("/").filter(Boolean).pop(),l=[this.joinUrl(n,r),o?this.joinUrl(n,o):"",r,o??""].filter(Boolean).map(h=>this.getZipFile(e,h)).find(h=>!!h);if(!l)return"";const c=URL.createObjectURL(new Blob([await l.async("arraybuffer")]));return this.zipObjectUrls.push(c),c}isSplitManifest(e){return!!e&&typeof e=="object"&&(e.splitType==="octree-2d"||!!e.blocksUrl)}is2dZipUrl(e){return/\.2d($|[?#])/i.test(e)}isManifestUrl(e){return/manifest\.json($|\?)/i.test(e)}getBaseUrl(e){const t=e.split("?")[0];return t.slice(0,t.lastIndexOf("/")+1)}getZipBasePath(e){const t=this.normalizeZipPath(e),n=t.lastIndexOf("/");return n>=0?t.slice(0,n+1):""}normalizeDirectoryUrl(e){return e.endsWith("/")?e:`${e}/`}joinUrl(e,t){return/^(https?:)?\/\//i.test(t)||t.startsWith("/")?t:`${e}${t}`.replace(/([^:]\/)\/+/g,"$1")}normalizeZipPath(e){return String(e).split("?")[0].split("#")[0].replace(/\\/g,"/").replace(/^\/+/,"")}getZipFile(e,t){const n=this.normalizeZipPath(t),i=e.file(n);if(i)return i;const r=n.toLowerCase(),o=Object.keys(e.files).find(a=>this.normalizeZipPath(a).toLowerCase()===r);return o?e.file(o):null}clearZipObjectUrls(){this.zipObjectUrls.forEach(e=>URL.revokeObjectURL(e)),this.zipObjectUrls=[]}}function ky(s,e,t){const n=t.length-s-1;if(e>=t[n])return n-1;if(e<=t[s])return s;let i=s,r=n,o=Math.floor((i+r)/2);for(;e<t[o]||e>=t[o+1];)e<t[o]?r=o:i=o,o=Math.floor((i+r)/2);return o}function KP(s,e,t,n){const i=[],r=[],o=[];i[0]=1;for(let a=1;a<=t;++a){r[a]=e-n[s+1-a],o[a]=n[s+a]-e;let l=0;for(let c=0;c<a;++c){const h=o[c+1],u=r[a-c],d=i[c]/(h+u);i[c]=l+h*d,l=u*d}i[a]=l}return i}function $P(s,e,t,n){const i=ky(s,n,e),r=KP(i,n,s,e),o=new w.Vector4(0,0,0,0);for(let a=0;a<=s;++a){const l=t[i-s+a],c=r[a],h=l.w*c;o.x+=l.x*h,o.y+=l.y*h,o.z+=l.z*h,o.w+=l.w*c}return o}function JP(s,e,t,n,i){const r=[];for(let u=0;u<=t;++u)r[u]=0;const o=[];for(let u=0;u<=n;++u)o[u]=r.slice(0);const a=[];for(let u=0;u<=t;++u)a[u]=r.slice(0);a[0][0]=1;const l=r.slice(0),c=r.slice(0);for(let u=1;u<=t;++u){l[u]=e-i[s+1-u],c[u]=i[s+u]-e;let d=0;for(let f=0;f<u;++f){const m=c[f+1],g=l[u-f];a[u][f]=m+g;const A=a[f][u-1]/a[u][f];a[f][u]=d+m*A,d=g*A}a[u][u]=d}for(let u=0;u<=t;++u)o[0][u]=a[u][t];for(let u=0;u<=t;++u){let d=0,f=1;const m=[];for(let g=0;g<=t;++g)m[g]=r.slice(0);m[0][0]=1;for(let g=1;g<=n;++g){let A=0;const p=u-g,x=t-g;u>=g&&(m[f][0]=m[d][0]/a[x+1][p],A=m[f][0]*a[p][x]);const y=p>=-1?1:-p,v=u-1<=x?g-1:t-u;for(let E=y;E<=v;++E)m[f][E]=(m[d][E]-m[d][E-1])/a[x+1][p+E],A+=m[f][E]*a[p+E][x];u<=x&&(m[f][g]=-m[d][g-1]/a[x+1][u],A+=m[f][g]*a[u][x]),o[g][u]=A;const _=d;d=f,f=_}}let h=t;for(let u=1;u<=n;++u){for(let d=0;d<=t;++d)o[u][d]*=h;h*=t-u}return o}function ZP(s,e,t,n,i){const r=i<s?i:s,o=[],a=ky(s,n,e),l=JP(a,n,s,r,e),c=[];for(let h=0;h<t.length;++h){const u=t[h].clone(),d=u.w;u.x*=d,u.y*=d,u.z*=d,c[h]=u}for(let h=0;h<=r;++h){const u=c[a-s].clone().multiplyScalar(l[h][0]);for(let d=1;d<=s;++d)u.add(c[a-s+d].clone().multiplyScalar(l[h][d]));o[h]=u}for(let h=r+1;h<=i+1;++h)o[h]=new w.Vector4(0,0,0);return o}function e3(s,e){let t=1;for(let i=2;i<=s;++i)t*=i;let n=1;for(let i=2;i<=e;++i)n*=i;for(let i=2;i<=s-e;++i)n*=i;return t/n}function t3(s){const e=s.length,t=[],n=[];for(let r=0;r<e;++r){const o=s[r];t[r]=new w.Vector3(o.x,o.y,o.z),n[r]=o.w}const i=[];for(let r=0;r<e;++r){const o=t[r].clone();for(let a=1;a<=r;++a)o.sub(i[r-a].clone().multiplyScalar(e3(r,a)*n[a]));i[r]=o.divideScalar(n[0])}return i}function n3(s,e,t,n,i){const r=ZP(s,e,t,n,i);return t3(r)}class i3 extends w.Curve{constructor(e,t,n,i,r){super();const o=t?t.length-1:0,a=n?n.length:0;this.degree=e,this.knots=t,this.controlPoints=[],this.startKnot=i||0,this.endKnot=r||o;for(let l=0;l<a;++l){const c=n[l];this.controlPoints[l]=new w.Vector4(c.x,c.y,c.z,c.w)}}getPoint(e,t=new w.Vector3){const n=t,i=this.knots[this.startKnot]+e*(this.knots[this.endKnot]-this.knots[this.startKnot]),r=$P(this.degree,this.knots,this.controlPoints,i);return r.w!==1&&r.divideScalar(r.w),n.set(r.x,r.y,r.z)}getTangent(e,t=new w.Vector3){const n=t,i=this.knots[0]+e*(this.knots[this.knots.length-1]-this.knots[0]),r=n3(this.degree,this.knots,this.controlPoints,i,1);return n.copy(r[1]).normalize(),n}toJSON(){const e=super.toJSON();return e.degree=this.degree,e.knots=[...this.knots],e.controlPoints=this.controlPoints.map(t=>t.toArray()),e.startKnot=this.startKnot,e.endKnot=this.endKnot,e}fromJSON(e){return super.fromJSON(e),this.degree=e.degree,this.knots=[...e.knots],this.controlPoints=e.controlPoints.map(t=>new w.Vector4(t[0],t[1],t[2],t[3])),this.startKnot=e.startKnot,this.endKnot=e.endKnot,this}}const Tt=1e-8,Fy=.001,s3=8421504;class r3{constructor(e){this.engine=e}create(e,t){const n=this.getLoopSet(e);if(n.outers.length===0)return[];if(this.isGradientFill(e))return this.createGradientItems(e,t,n);if(this.isSolidFill(e))return this.createSolidItems(e,t,n);const r=this.createPatternLineItem(e,t,n);return r?[r]:(this.warnUnknownPatternFallback(e),this.createSolidItems(e,t,n,s3))}isSolidFill(e){const t=String(e.pattern??e.patternName??"").toUpperCase();return e.solid===!0||t==="SOLID"}warnUnknownPatternFallback(e){const t=e.pattern??e.patternName??"UNKNOWN";this.engine.options?.debugHatch===!0&&console.warn(`[LoaderModule2d] HATCH pattern "${t}" cannot be rendered, use gray solid fallback.`)}isGradientFill(e){return e.gradient?.enabled===!0||String(e.patternType??"").toUpperCase()==="GRADIENTFILL"}getLoopSet(e){const t=(e.loops??[]).map(o=>this.normalizeLoop(o.points)).filter(o=>o.length>=3);if(t.length===0)return{outers:[],holes:[]};const n=(e.loops??[]).filter(o=>this.normalizeLoop(o.points).length>=3);if(!n.some(o=>o.type===!1))return this.classifyLoopsByContainment(t);const i=n.filter(o=>o.type!==!1).map(o=>this.normalizeLoop(o.points)),r=n.filter(o=>o.type===!1).map(o=>this.normalizeLoop(o.points));return i.length>0?{outers:i,holes:r}:{outers:[t[0]],holes:t.slice(1)}}classifyLoopsByContainment(e){const t=[...e].sort((r,o)=>Math.abs(this.signedArea(o))-Math.abs(this.signedArea(r))),n=[],i=[];return t.forEach((r,o)=>{const a=new b.Vector2(r[0][0],r[0][1]);t.slice(0,o).filter(c=>this.pointInPolygon(a,c)).length%2===0?n.push(r):i.push(r)}),{outers:n,holes:i}}signedArea(e){let t=0;for(let n=0;n<e.length;n+=1){const i=e[n],r=e[(n+1)%e.length];t+=i[0]*r[1]-r[0]*i[1]}return t/2}normalizeLoop(e){const t=[];(e??[]).forEach(r=>{if(!Array.isArray(r)||r.length<2)return;const o=[Number(r[0]),Number(r[1])];if(!Number.isFinite(o[0])||!Number.isFinite(o[1]))return;const a=t[t.length-1];(!a||Math.hypot(o[0]-a[0],o[1]-a[1])>Tt)&&t.push(o)});const n=t[0],i=t[t.length-1];return n&&i&&Math.hypot(n[0]-i[0],n[1]-i[1])<=Tt&&t.pop(),t}createSolidItems(e,t,n,i){const r=[];if(n.outers.forEach(l=>{const c=this.createShape(l);n.holes.filter(h=>this.pointInPolygon(new b.Vector2(h[0][0],h[0][1]),l)).forEach(h=>{c.holes.push(this.createPath(h))}),r.push(new b.ShapeGeometry(c))}),r.length===0)return[];const o=r.length===1?r[0]:_i(r,!1);o.applyMatrix4(t);const a=Mr(o);return[{kind:"hatch",layer:e.layer??"0",color:i??this.resolveEntityColor(e),linkId:e.linkId??e.id,geometry:o,min:a.min,max:a.max,info:e}]}createShape(e){const t=new b.Shape;t.moveTo(e[0][0],e[0][1]);for(let n=1;n<e.length;n+=1)t.lineTo(e[n][0],e[n][1]);return t.closePath(),t}createPath(e){const t=new b.Path;t.moveTo(e[0][0],e[0][1]);for(let n=1;n<e.length;n+=1)t.lineTo(e[n][0],e[n][1]);return t.closePath(),t}createGradientItems(e,t,n){const i=[];if(n.outers.forEach(a=>{const l=this.createShape(a);n.holes.filter(h=>this.pointInPolygon(new b.Vector2(h[0][0],h[0][1]),a)).forEach(h=>{l.holes.push(this.createPath(h))});const c=this.subdivideTriangles(new b.ShapeGeometry(l),this.engine.options?.hatchGradientSubdivisions??3);this.applyGradientVertexColors(c,a,e.gradient),i.push(c)}),i.length===0)return[];const r=i.length===1?i[0]:_i(i,!1);r.applyMatrix4(t);const o=Mr(r);return[{kind:"hatch",layer:e.layer??"0",color:this.resolveEntityColor(e),linkId:e.linkId??e.id,geometry:r,useVertexColors:!0,min:o.min,max:o.max,info:e}]}applyGradientVertexColors(e,t,n){const i=e.getAttribute("position"),r=[],o=this.resolveGradientStops(n),a=this.getBounds(t),l=new b.Vector2((a.minX+a.maxX)/2,(a.minY+a.maxY)/2),c=Math.max(a.maxX-a.minX,Tt),h=Math.max(a.maxY-a.minY,Tt),u=Math.max(Math.hypot(c/2,h/2),Tt),d=Number(n?.angle??0),f=new b.Vector2(Math.cos(d),Math.sin(d)).normalize(),m=new b.Vector2(-f.y,f.x);for(let g=0;g<i.count;g+=1){const A=new b.Vector2(i.getX(g),i.getY(g)),p=this.resolveGradientFactor(A,l,f,m,c,h,u,n),x=this.sampleGradientColor(o,p);r.push(x.r,x.g,x.b)}e.setAttribute("color",new b.Float32BufferAttribute(r,3))}subdivideTriangles(e,t){let n=e.index?e.toNonIndexed():e.clone();const i=Math.max(0,Math.min(Math.floor(Number(t)||0),5));for(let r=0;r<i;r+=1){const o=n.getAttribute("position"),a=[];for(let l=0;l<o.count;l+=3){const c=new b.Vector3(o.getX(l),o.getY(l),o.getZ(l)),h=new b.Vector3(o.getX(l+1),o.getY(l+1),o.getZ(l+1)),u=new b.Vector3(o.getX(l+2),o.getY(l+2),o.getZ(l+2)),d=c.clone().lerp(h,.5),f=h.clone().lerp(u,.5),m=u.clone().lerp(c,.5);this.pushTriangle(a,c,d,m),this.pushTriangle(a,d,h,f),this.pushTriangle(a,m,f,u),this.pushTriangle(a,d,f,m)}n=new b.BufferGeometry().setAttribute("position",new b.Float32BufferAttribute(a,3))}return n}pushTriangle(e,t,n,i){e.push(t.x,t.y,t.z,n.x,n.y,n.z,i.x,i.y,i.z)}resolveGradientFactor(e,t,n,i,r,o,a,l){const c=e.clone().sub(t),h=String(l?.name??"LINEAR").toUpperCase(),u=Number(l?.shift??0),d=Math.max(Math.abs(n.x)*r+Math.abs(n.y)*o,Tt),f=Math.max(Math.abs(i.x)*r+Math.abs(i.y)*o,Tt);let m=.5+c.dot(n)/d+u;return h.includes("CYLINDER")?m=Math.abs(c.dot(i))/(f/2):h.includes("SPHERICAL")?(m=c.length()/a,h.includes("HEMI")&&(m=Math.sqrt(m))):h.includes("CURVED")&&(m=Math.pow(Math.abs(c.dot(n))/(d/2),.65)),h.startsWith("INV")&&(m=1-m),b.MathUtils.clamp(m,0,1)}resolveGradientStops(e){const t=(e?.colors??[]).map(n=>({value:b.MathUtils.clamp(Number(n.value??0),0,1),color:this.resolveGradientStopColor(n)})).sort((n,i)=>n.value-i.value);if(t.length>=2)return t;if(t.length===1){const n=b.MathUtils.clamp(Number(e?.colorTint??0),0,1);return[{value:0,color:t[0].color.clone().lerp(new b.Color(16777215),n)},{value:1,color:t[0].color}]}return[{value:0,color:new b.Color(16777215)},{value:1,color:new b.Color(0)}]}resolveGradientStopColor(e){if(Array.isArray(e.rgb)&&e.rgb.length>=3){const[t,n,i]=e.rgb.map(r=>b.MathUtils.clamp(Number(r??0),0,255)/255);return new b.Color(t,n,i)}return new b.Color(e.color??16777215)}resolveEntityColor(e){if(Array.isArray(e.rgb)&&e.rgb.length>=3){const[t,n,i]=e.rgb.map(r=>Math.round(b.MathUtils.clamp(Number(r??0),0,255)));return t<<16|n<<8|i}return e.color??16777215}sampleGradientColor(e,t){if(t<=e[0].value)return e[0].color.clone();for(let n=0;n<e.length-1;n+=1){const i=e[n],r=e[n+1];if(t<=r.value+Tt){const o=Math.max(r.value-i.value,Tt);return i.color.clone().lerp(r.color,(t-i.value)/o)}}return e[e.length-1].color.clone()}createPatternLineItem(e,t,n){const i=[],r=this.engine.options?.hatchPatternMaxSegments??2e4;let o=0;for(const l of n.outers){const c=this.getBounds(l),h=Math.hypot(c.maxX-c.minX,c.maxY-c.minY);if(!(h<Tt))for(const u of e.patternLines??[]){if(o>=r)break;const d=this.createPatternFamilySegments(e,u,l,n.holes,c,h,r-o);d.forEach(([f,m])=>{i.push(new b.Vector3(f.x,f.y,Fy),new b.Vector3(m.x,m.y,Fy))}),o+=d.length}}if(i.length===0)return null;i.forEach(l=>l.applyMatrix4(t));const a=Ry(i);return{kind:"line",layer:e.layer??"0",color:this.resolveEntityColor(e),linkId:e.linkId??e.id,points:i,min:a.min,max:a.max,info:e}}createPatternFamilySegments(e,t,n,i,r,o,a){const l=this.resolvePatternLineTransform(e,t),c=l.dir,h=new b.Vector2(-c.y,c.x),u=l.base,d=l.offset;let f=d.dot(h);if(Math.abs(f)<Tt&&(f=Number(t.lineOffset??0)),Math.abs(f)<Tt)return[];const m=[new b.Vector2(r.minX,r.minY),new b.Vector2(r.maxX,r.minY),new b.Vector2(r.maxX,r.maxY),new b.Vector2(r.minX,r.maxY)],g=u.dot(h),A=m.map(I=>I.dot(h)-g),p=Math.min(...A)-o,x=Math.max(...A)+o,y=Math.floor(Math.min(p/f,x/f))-2,v=Math.ceil(Math.max(p/f,x/f))+2,_=[],E=new b.Vector2((r.minX+r.maxX)/2,(r.minY+r.maxY)/2);for(let I=y;I<=v&&_.length<a;I+=1){const B=u.clone().add(d.clone().multiplyScalar(I)),M=B.clone().add(c.clone().multiplyScalar(E.clone().sub(B).dot(c))),C=M.clone().add(c.clone().multiplyScalar(-o*2)),P=M.clone().add(c.clone().multiplyScalar(o*2));this.clipLineByPolygon(C,P,n).forEach(([R,S])=>{this.subtractHoles(R,S,i).forEach(([F,N])=>{this.appendDashedSegment(_,F,N,t.dashLengths,B,c)})})}return _.slice(0,a)}resolvePatternLineTransform(e,t){const n=Number(t.angle??e.patternAngle??0);return{dir:new b.Vector2(Math.cos(n),Math.sin(n)).normalize(),base:this.toVector2(t.basePoint),offset:this.toVector2(t.offset)}}toVector2(e){return new b.Vector2(e?.[0]??0,e?.[1]??0)}getBounds(e){return{minX:Math.min(...e.map(t=>t[0])),minY:Math.min(...e.map(t=>t[1])),maxX:Math.max(...e.map(t=>t[0])),maxY:Math.max(...e.map(t=>t[1]))}}clipLineByPolygon(e,t,n){const i=[0,1];for(let a=0;a<n.length;a+=1){const l=new b.Vector2(n[a][0],n[a][1]),c=new b.Vector2(n[(a+1)%n.length][0],n[(a+1)%n.length][1]),h=this.segmentIntersectionT(e,t,l,c);h!==null&&h>Tt&&h<1-Tt&&i.push(h)}const r=this.dedupeSorted(i.sort((a,l)=>a-l),1e-7),o=[];for(let a=0;a<r.length-1;a+=1){const l=r[a],c=r[a+1];if(c-l<1e-7)continue;const h=this.interpolate2(e,t,(l+c)/2);this.pointInPolygon(h,n)&&o.push([this.interpolate2(e,t,l),this.interpolate2(e,t,c)])}return o}subtractHoles(e,t,n){let i=[[e,t]];return n.forEach(r=>{const o=[];i.forEach(([a,l])=>{const c=this.clipLineByPolygon(a,l,r);o.push(...this.subtractSegments(a,l,c))}),i=o}),i}appendDashedSegment(e,t,n,i,r,o){const a=t.distanceTo(n);if(a<Tt)return;if(!i?.length){e.push([t,n]);return}const l=this.normalizeDashPattern(i),c=l.reduce((y,v)=>y+v.length,0);if(c<Tt){e.push([t,n]);return}const h=o?.clone().normalize()??n.clone().sub(t).normalize(),u=r??t,f=n.clone().sub(t).normalize().dot(h)>=0?1:-1,m=t.clone().sub(u).dot(h)*f,g=this.positiveModulo(m,c);let A=0,p=this.findDashIndex(l,g),x=g-l[p].start;for(;A<a-Tt;){const y=l[p],v=Math.max(y.length-x,Tt),_=Math.min(a,A+v);y.draw&&e.push([this.pointAtLength(t,n,A),this.pointAtLength(t,n,_)]),A=_,p=(p+1)%l.length,x=0}}normalizeDashPattern(e){let t=0;return e.map(n=>{const i=Number(n??0),r={length:Math.max(Math.abs(i),5e-4),draw:i>=0,start:t};return t+=r.length,r}).filter(n=>n.length>Tt)}findDashIndex(e,t){for(let n=e.length-1;n>=0;n-=1)if(t>=e[n].start-Tt)return n;return 0}positiveModulo(e,t){return(e%t+t)%t}subtractSegments(e,t,n){const i=n.map(([a,l])=>[this.projectT(e,t,a),this.projectT(e,t,l)]).map(([a,l])=>[Math.max(0,Math.min(a,l)),Math.min(1,Math.max(a,l))]).sort((a,l)=>a[0]-l[0]),r=[];let o=0;return i.forEach(([a,l])=>{a>o+Tt&&r.push([this.interpolate2(e,t,o),this.interpolate2(e,t,a)]),o=Math.max(o,l)}),o<1-Tt&&r.push([this.interpolate2(e,t,o),this.interpolate2(e,t,1)]),r}segmentIntersectionT(e,t,n,i){const r=t.clone().sub(e),o=i.clone().sub(n),a=this.cross2(r,o);if(Math.abs(a)<1e-10)return null;const l=n.clone().sub(e),c=this.cross2(l,o)/a,h=this.cross2(l,r)/a;return c>=-1e-8&&c<=1+1e-8&&h>=-1e-8&&h<=1+1e-8?c:null}pointInPolygon(e,t){let n=!1;for(let i=0,r=t.length-1;i<t.length;r=i,i+=1){const o=t[i][0],a=t[i][1],l=t[r][0],c=t[r][1];a>e.y!=c>e.y&&e.x<(l-o)*(e.y-a)/(c-a+1e-20)+o&&(n=!n)}return n}cross2(e,t){return e.x*t.y-e.y*t.x}interpolate2(e,t,n){return e.clone().lerp(t,n)}projectT(e,t,n){const i=t.clone().sub(e),r=i.lengthSq();return r<1e-12?0:n.clone().sub(e).dot(i)/r}pointAtLength(e,t,n){const i=e.distanceTo(t);return this.interpolate2(e,t,i<1e-12?0:n/i)}dedupeSorted(e,t){const n=[];return e.forEach(i=>{(!n.length||Math.abs(i-n[n.length-1])>t)&&n.push(i)}),n}}class o3{constructor(e,t){this.engine=e,this.textFactory=t,this.hatchRenderer=new r3(e)}hatchRenderer;create(e,t){switch(e.type){case"LINE_GROUP":case"LINE":case"CIRCLE":case"POLYLINE":case"SPLINE":return this.createLineItem(e,t);case"MTEXT":case"TEXT":return this.textFactory.create(e,t);case"HATCH":return this.createHatch(e,t);case"IMAGE":return this.createImage(e,t);default:return[]}}createLineItem(e,t){const n=this.getEntityPoints(e).map(i=>i.clone().applyMatrix4(t));return n.length===0?[]:[{kind:"line",layer:e.layer,color:e.color,lineType:e.lineType,lineTypeScale:e.lineTypeScale,lineTypePattern:Array.isArray(e.lineTypePattern)?e.lineTypePattern:void 0,linkId:e.linkId??e.id,points:n,info:e}]}getEntityPoints(e){switch(e.type){case"LINE_GROUP":return this.getLineGroupPoints(e);case"LINE":return[ks(e.startPoint),ks(e.endPoint)];case"CIRCLE":return this.getCirclePoints(e);case"POLYLINE":return this.getPolylinePoints(e);case"SPLINE":return this.getSplinePoints(e);default:return[]}}getLineGroupPoints(e){const t=[];return(e.segments??[]).forEach(n=>{t.push(new b.Vector3(n[0]??0,n[1]??0,n[2]??0)),t.push(new b.Vector3(n[3]??0,n[4]??0,n[5]??0))}),t}getCirclePoints(e){const t=new b.EllipseCurve(e.center?.[0]??0,e.center?.[1]??0,e.radius??0,e.radius??0,e.startAngle??0,(e.endAngle??Math.PI*2)-1e-5,!1,0);return this.pointsToSegments(t.getPoints(this.engine.options?.circleSegments??48).map(n=>new b.Vector3(n.x,n.y,e.center?.[2]??0)))}getPolylinePoints(e){const t=[],n=e.points??[];for(let i=0;i<n.length-1;i+=1)this.getPolylineSegmentPoints(n[i],n[i+1]).forEach(r=>{t.push(r)});return e.closed&&n.length>1&&this.getPolylineSegmentPoints(n[n.length-1],n[0]).forEach(i=>{t.push(i)}),t}getPolylineSegmentPoints(e,t){const n=ks(e),i=ks(t),r=Number(e?.bulge??0);if(!Number.isFinite(r)||Math.abs(r)<1e-10)return[n,i];const o=i.clone().sub(n),a=o.length();if(a<1e-12)return[n,i];const l=4*Math.atan(r),c=a*(1+r*r)/(4*Math.abs(r)),h=n.clone().add(i).multiplyScalar(.5),u=new b.Vector3(-o.y/a,o.x/a,0),d=h.clone().add(u.multiplyScalar(a*(1-r*r)/(4*r))),f=Math.atan2(n.y-d.y,n.x-d.x),m=Math.max(4,Math.ceil(Math.abs(l)/(this.engine.options?.polylineArcAngleStep??Math.PI/18))),g=[];for(let A=0;A<=m;A+=1){const p=A/m,x=f+l*p;g.push(new b.Vector3(d.x+Math.cos(x)*c,d.y+Math.sin(x)*c,n.z+(i.z-n.z)*p))}return this.pointsToSegments(g)}getSplinePoints(e){const t=(e.points??[]).map(i=>ks(i));if(t.length<2)return[];const n=t.length===2?t:this.sampleSplineCurve(t,e);return this.pointsToSegments(n)}sampleSplineCurve(e,t){const n=Math.min(Math.max(Number(t.degree??this.engine.options?.splineDegree??6),1),e.length-1),i=Array.isArray(t.knots)&&t.knots.length===e.length+n+1?t.knots:this.createClampedUniformKnots(e.length,n),r=e.map((l,c)=>{const h=Array.isArray(t.weights)?Number(t.weights[c]??1):1;return new b.Vector4(l.x,l.y,l.z,Number.isFinite(h)?h:1)});let o=(e.length-1)*2;const a=new i3(n,i,r).getPoints(o);return t.closed===!0&&a.length>1&&a.push(a[0].clone()),a}createClampedUniformKnots(e,t){const n=[];for(let i=0;i<e+t+1;i+=1)i<=t?n.push(0):i>=e?n.push(1):n.push((i-t)/(e-t));return n}pointsToSegments(e){const t=[];for(let n=0;n<e.length-1;n+=1)t.push(e[n].clone(),e[n+1].clone());return t}createHatch(e,t){return this.hatchRenderer.create(e,t)}createImage(e,t){const n=e.imageUrl||e.url;if(!n)return[];const i=ks(e.position),r=ks(e.uVector),o=ks(e.vVector),a=Number(e.pixelWidth??e.width??1),l=Number(e.pixelHeight??e.height??1);if(!Number.isFinite(a)||!Number.isFinite(l)||a===0||l===0)return[];const c=r.multiplyScalar(a),h=o.multiplyScalar(l),u=i.clone(),d=i.clone().add(c),f=i.clone().add(c).add(h),m=i.clone().add(h);[u,d,f,m].forEach(x=>x.applyMatrix4(t));const g=new b.BufferGeometry;g.setAttribute("position",new b.Float32BufferAttribute([u.x,u.y,u.z,d.x,d.y,d.z,f.x,f.y,f.z,u.x,u.y,u.z,f.x,f.y,f.z,m.x,m.y,m.z],3)),g.setAttribute("uv",new b.Float32BufferAttribute([0,0,1,0,1,1,0,0,1,1,0,1],2)),g.computeVertexNormals();const A=Mr(g),p=Number(e.fade??0);return[{kind:"image",layer:e.layer??"0",color:e.color??16777215,linkId:e.linkId??e.id,geometry:g,imageUrl:n,opacity:Number.isFinite(p)?b.MathUtils.clamp(1-p/100,0,1):1,min:A.min,max:A.max,info:e}]}}class a3{constructor(e,t,n=e.modelGroup){this.model=t,this.targetGroup=n}modelMap=new Map;hatchMap=new Map;textMap=new Map;imageMap=new Map;textureLoader=new b.TextureLoader;addRenderItems(e){e.forEach(t=>this.addRenderItem(t))}buildSceneObjects(){this.buildImageObjects(),this.buildHatchObjects(),this.buildLineObjects(),this.buildTextObjects()}addRenderItem(e){const t=`${e.layer}||${e.color}`;if(e.kind==="line"){let o=this.modelMap.get(t);o||(o=new Map,this.modelMap.set(t,o));const a=this.resolveLinePoints(e),l=o.get(e.linkId);l?a.forEach(c=>l.push(c)):o.set(e.linkId,[...a]);return}const n=this.getItemMap(e),i=e.kind==="image"?`${t}||${e.imageUrl??""}`:t,r=n.get(i);r?r.push(e):n.set(i,[e])}getItemMap(e){return e.kind==="text"?this.textMap:e.kind==="image"?this.imageMap:this.hatchMap}resolveLinePoints(e){const t=e.points??[],n=this.resolveLineTypePattern(e);if(!n)return t;const i=[];for(let r=0;r<t.length-1;r+=2)this.applyDashPattern(t[r],t[r+1],n).forEach(o=>i.push(o));return i}resolveLineTypePattern(e){const t=this.model.layers.find(l=>l.name===e.layer),n=String(e.lineType??"").toLowerCase(),i=n==="bylayer"||n===""?String(t?.lineType??"").toLowerCase():n;if(!i||i==="continuous"||i==="byblock")return null;const r=Array.isArray(e.lineTypePattern)&&e.lineTypePattern.length>0?e.lineTypePattern:Array.isArray(t?.lineTypePattern)?t.lineTypePattern:this.getFallbackLineTypePattern(i);if(!r||r.length===0)return null;const o=this.resolveLineTypeScale(e,t),a=r.map(l=>Number(l)).filter(l=>Number.isFinite(l)).map(l=>l*o);return a.some(l=>Math.abs(l)>1e-12)?a:null}getFallbackLineTypePattern(e){return e.includes("dash")?[.25,-.1]:e.includes("dot")?[0,-.1]:null}resolveLineTypeScale(e,t){const n=Number(e.lineTypeScale??t?.lineTypeScale??1);return!Number.isFinite(n)||Math.abs(n)<1e-12?1:Math.abs(n)}applyDashPattern(e,t,n){const i=t.clone().sub(e),r=i.length();if(r<1e-12)return[];const o=i.multiplyScalar(1/r),a=n.reduce((d,f)=>d+Math.abs(f),0),l=Math.max(a*.05,r*.002,1e-6),c=[];let h=0,u=0;for(;h<r-1e-12;){const d=n[u%n.length],f=d>=0,m=Math.max(Math.abs(d),l),g=Math.min(h+m,r);if(f&&g>h&&c.push(e.clone().add(o.clone().multiplyScalar(h)),e.clone().add(o.clone().multiplyScalar(g))),h=g,u+=1,u>1e5)break}return c}buildLineObjects(){this.modelMap.forEach((e,t)=>{const[n]=t.split("||"),i=[];if(e.forEach(u=>{u.forEach(d=>i.push(d))}),i.length===0)return;const r=new b.BufferGeometry().setFromPoints(i),o=new b.LineBasicMaterial({color:this.resolveColor(t)}),a=new b.LineSegments(r,o);a.name=t;const l=r.getAttribute("position");a.clonePoints=l.array.slice(),a.materialClone=o.clone(),this.targetGroup.add(a);const c=this.targetGroup.children.length-1;let h=0;e.forEach((u,d)=>{const f=Ry(u);this.pushNodeMap(d,{indexes:[c,h,h+u.length*3],object:a,group:this.targetGroup,kind:"line",layer:n,min:f.min,max:f.max}),h+=u.length*3})})}buildTextObjects(){this.textMap.forEach((e,t)=>{const n=e.filter(a=>!!a.geometry),i=this.normalizeMeshGeometries(n,!1,!1);if(i.length===0)return;const r=this.mergeMeshGeometries(i),o=new b.MeshBasicMaterial({color:this.resolveColor(t),side:b.DoubleSide});t.includes("_hitbox")&&(o.visible=!1),this.addMeshObject(n,t,r,i,o)})}buildHatchObjects(){this.hatchMap.forEach((e,t)=>{const n=e.filter(l=>!!l.geometry),i=n.some(l=>l.useVertexColors===!0),r=this.normalizeMeshGeometries(n,!1,i);if(r.length===0)return;const o=this.mergeMeshGeometries(r),a=new b.MeshBasicMaterial({color:i?16777215:this.resolveColor(t),side:b.DoubleSide,transparent:!0,opacity:i?1:.5,vertexColors:i});this.addMeshObject(n,t,o,r,a)})}buildImageObjects(){this.imageMap.forEach((e,t)=>{const n=e.filter(h=>!!h.geometry),i=this.normalizeMeshGeometries(n,!0,!1);if(i.length===0)return;const r=n[0]?.imageUrl;if(!r)return;const o=this.mergeMeshGeometries(i),a=this.textureLoader.load(r);a.colorSpace=b.SRGBColorSpace,a.needsUpdate=!0;const l=n.reduce((h,u)=>Math.min(h,u.opacity??1),1),c=new b.MeshBasicMaterial({map:a,side:b.DoubleSide,transparent:!0,opacity:l,depthWrite:!1});this.addMeshObject(n,t,o,i,c)})}mergeMeshGeometries(e){const t=e.length===1?e[0]:_i(e,!0);if(t.groups.length===0){const n=t.getAttribute("position");t.addGroup(0,n?.count??0,0)}return t.groups.forEach(n=>{n.materialIndex=0}),t}normalizeMeshGeometries(e,t,n){return e.map(i=>{const r=i.geometry,o=r.index?r.toNonIndexed():r.clone(),a=o.getAttribute("position"),l=o.getAttribute("uv"),c=o.getAttribute("color"),h=new b.BufferGeometry;return h.setAttribute("position",a.clone()),t&&h.setAttribute("uv",l?l.clone():this.createEmptyUv(a.count)),n&&h.setAttribute("color",c?c.clone():this.createSolidColorAttribute(a.count,i.color)),h})}createEmptyUv(e){return new b.Float32BufferAttribute(new Array(e*2).fill(0),2)}createSolidColorAttribute(e,t){const n=new b.Color(t??16777215),i=[];for(let r=0;r<e;r+=1)i.push(n.r,n.g,n.b);return new b.Float32BufferAttribute(i,3)}addMeshObject(e,t,n,i,r){const o=new b.Mesh(n,r);o.name=t,o.materialClone=r.clone(),o.isSplit=!1,o.geometrys=void 0,i.forEach(l=>{l!==n&&l.dispose()}),this.targetGroup.add(o);const a=this.targetGroup.children.length-1;e.forEach((l,c)=>{const h=l.linkId??l.info?.id;this.pushNodeMap(h,{indexes:[a,c],object:o,group:this.targetGroup,kind:l.kind,layer:l.layer,info:l.info,min:l.min??new b.Vector3,max:l.max??new b.Vector3}),this.pushTextSearchItem(l,t)})}pushTextSearchItem(e,t){if(e.kind!=="text"||t.includes("_hitbox"))return;const n=e.info?.text,i=String(n??"").replace(/\r\n/g,`
5554
5554
  `).replace(/\r/g,`
5555
5555
  `).trim(),r=e.linkId??e.info?.id;!i||r==null||this.model.textItems.push({id:String(r),text:i,layer:e.layer,min:e.min,max:e.max,anchor:e.textAnchor,info:e.info})}resolveColor(e){const[t,n]=e.split("||");let i=Number.parseInt(n);return(i===0||Number.isNaN(i))&&(i=this.model.layers.find(o=>o.name===t)?.color??16777215),i}pushNodeMap(e,t){if(e==null)return;const n=String(e),i=this.model.nodeMap.get(n);i?i.push(t):this.model.nodeMap.set(n,[t])}}class l3{constructor(e,t){this.engine=e,this.font=t}create(e,t=new b.Matrix4){if(!e.text)return[];const n=this.normalizeText(e.text);if(!n.trim())return[];const i=this.engine.options?.textCurveSegments??1,r=this.createTextGeometry(n,e.height??100,i);if(!r)return[];const o=[...e.position??[0,0,0]];o[1]=o[1]-(e.height??0);const a=this.resolveWidthScale(e),l=new b.Vector3(o[0]??0,o[1]??0,o[2]??0).applyMatrix4(t),c=1.4*e.scale;r.applyMatrix4(t.clone().multiply(cp(o,[a*1.4,1*c,1*c],e.rotation??0)));const h=Mr(r),u=[{kind:"text",layer:e.layer,color:e.color,linkId:e.linkId??e.id,geometry:r,min:h.min,max:h.max,textAnchor:l,info:e}],d=this.createHitbox(r);if(d){const f=Mr(d);u.push({kind:"text",layer:e.layer,color:`${e.color}_hitbox`,linkId:e.linkId??e.id,geometry:d,min:f.min,max:f.max,textAnchor:l,info:e})}return u}resolveWidthScale(e){const t=Number(e.widthScale??e.widthFactor??1);return!Number.isFinite(t)||Math.abs(t)<1e-12?1:t}normalizeText(e){return String(e??"").replace(/\r\n/g,`
5556
5556
  `).replace(/\r/g,`
@@ -6060,7 +6060,7 @@ void main() {
6060
6060
  color.b += max != color.b ? (max - color.b) * amt : 0.00;
6061
6061
  gl_FragColor = color;
6062
6062
  }
6063
- `}applyTo2d({imageData:{data:s}}){let e=-this.vibrance;for(let t=0;t<s.length;t+=4){let n=s[t],i=s[t+1],r=s[t+2],o=Math.max(n,i,r),a=(n+i+r)/3,l=2*Math.abs(o-a)/255*e;s[t]+=o===n?0:(o-n)*l,s[t+1]+=o===i?0:(o-i)*l,s[t+2]+=o===r?0:(o-r)*l}}sendUniformData(s,e){s.uniform1f(e.uVibrance,-this.vibrance)}isNeutralState(){return this.vibrance===0}};K(ml,"type","Vibrance"),K(ml,"defaults",{vibrance:0}),K(ml,"uniformLocations",["uVibrance"]),ke.setClass(ml),Ua({BaseFilter:()=>zt,BlackWhite:()=>OR,BlendColor:()=>nl,BlendImage:()=>il,Blur:()=>sl,Brightness:()=>rl,Brownie:()=>DR,ColorMatrix:()=>Ur,Composed:()=>ag,Contrast:()=>ol,Convolute:()=>al,Gamma:()=>ll,Grayscale:()=>cl,HueRotation:()=>qh,Invert:()=>hl,Kodachrome:()=>LR,Noise:()=>ul,Pixelate:()=>dl,Polaroid:()=>kR,RemoveColor:()=>fl,Resize:()=>pl,Saturation:()=>gl,Sepia:()=>FR,Technicolor:()=>RR,Vibrance:()=>ml,Vintage:()=>PR});function GR(s,e,t="bim-snapshot.png"){const n=s?.renderer,i=n?.domElement;if(!n||!i||!e)return null;const r=i.width||i.clientWidth,o=i.height||i.clientHeight;if(r<=0||o<=0)return null;let a=VR(i,r,o);if(!QR(a)){const d=jR(s,r,o);d&&(a=d)}const l=document.createElement("canvas");l.width=r,l.height=o;const c=l.getContext("2d");if(!c)return null;c.drawImage(a,0,0,r,o),c.drawImage(e,0,0,r,o);const h=l.toDataURL("image/png"),u=document.createElement("a");return u.href=h,u.download=t.toLowerCase().endsWith(".png")?t:`${t}.png`,u.click(),h}function VR(s,e,t){const n=document.createElement("canvas");n.width=e,n.height=t;const i=n.getContext("2d");return i&&i.drawImage(s,0,0,e,t),n}function QR(s){const e=s.getContext("2d");if(!e||s.width<=0||s.height<=0)return!1;const t=Math.min(32,s.width),n=Math.min(32,s.height),i=Math.max(1,Math.floor(s.width/t)),r=Math.max(1,Math.floor(s.height/n));for(let o=0;o<s.height;o+=r)for(let a=0;a<s.width;a+=i){const l=e.getImageData(a,o,1,1).data;if(l[0]!==0||l[1]!==0||l[2]!==0||l[3]!==0)return!0}return!1}function jR(s,e,t){const n=s?.renderer,i=s?.scene,r=s?.camera;if(!n||!i||!r)return null;const o=new b.WebGLRenderTarget(e,t,{minFilter:b.LinearFilter,magFilter:b.LinearFilter,format:b.RGBAFormat,depthBuffer:!0,stencilBuffer:!0}),a=n.getRenderTarget(),l=n.autoClear,c=n.xr?.enabled??!1;try{n.xr&&(n.xr.enabled=!1),n.autoClear=!0,n.setRenderTarget(o),n.clear(!0,!0,!0),n.render(i,r);const h=new Uint8Array(e*t*4);return n.readRenderTargetPixels(o,0,0,e,t,h),WR(h,e,t)}catch{return null}finally{n.setRenderTarget(a),n.autoClear=l,n.xr&&(n.xr.enabled=c),o.dispose()}}function WR(s,e,t){const n=document.createElement("canvas");n.width=e,n.height=t;const i=n.getContext("2d");if(!i)return n;const r=i.createImageData(e,t),o=e*4;for(let a=0;a<t;a++){const l=(t-1-a)*o,c=a*o;for(let h=0;h<o;h++)r.data[c+h]=s[l+h]}return i.putImageData(r,0,0),n}const HR=["#ffffff","#000000","#ff4d4f","#fa8c16","#fadb14","#52c41a","#13c2c2","#1677ff","#722ed1","#eb2f96"],qR={none:new URL("/assets/icon/%E9%80%89%E6%8B%A9.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,line:new URL("/assets/icon/%E7%BA%BF.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,arrow:new URL("/assets/icon/%E7%AE%AD%E5%A4%B4.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,rect:new URL("/assets/icon/%E7%9F%A9%E5%BD%A2.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,circle:new URL("/assets/icon/%E5%9C%86%E5%BD%A2.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,text:new URL("/assets/icon/%E6%96%87%E5%AD%97.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,cloudline:new URL("/assets/icon/%E4%BA%91%E7%BA%BF.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href},XR=new URL("/assets/icon/%E6%B5%8B%E8%B7%9D.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,YR=new URL("/assets/icon/%E6%88%AA%E5%9B%BE.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,KR=new URL("/assets/icon/%E7%BA%BF%E5%AE%BD.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,$R=new URL("/assets/icon/%E5%AD%97%E5%8F%B7.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,JR=[{type:"distance",label:"距离"},{type:"clearDistance",label:"净距"},{type:"clearHeight",label:"净高"},{type:"elevation",label:"标高"},{type:"point",label:"坐标"},{type:"angle",label:"角度"},{type:"area",label:"面积"},{type:"slope",label:"坡度"}],ZR={distance:new URL("/assets/icon/%E8%B7%9D%E7%A6%BB.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,clearDistance:new URL("/assets/icon/%E5%87%80%E8%B7%9D.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,clearHeight:new URL("/assets/icon/%E5%87%80%E9%AB%98.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,elevation:new URL("/assets/icon/%E6%A0%87%E9%AB%98.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,point:new URL("/assets/icon/%E5%9D%90%E6%A0%87.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,angle:new URL("/assets/icon/%E8%A7%92%E5%BA%A6.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,area:new URL("/assets/icon/%E9%9D%A2%E7%A7%AF.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,slope:new URL("/assets/icon/%E5%9D%A1%E5%BA%A6.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href};class ek{constructor(e,t){this.handlers=e,this.root=document.createElement("div"),this.root.style.position="absolute",this.root.style.top="8px",this.root.style.left="50%",this.root.style.transform="translateX(-50%)",this.root.style.display="none",this.root.style.padding="6px",this.root.style.background="#ffffff",this.root.style.border="1px solid #d9d9d9",this.root.style.borderRadius="8px",this.root.style.pointerEvents="auto",this.root.style.userSelect="none",this.root.style.boxShadow="0 4px 14px rgba(0, 0, 0, 0.12)",this.root.style.zIndex="1300",this.root.style.overflow="visible",this.editPanel=document.createElement("div"),this.editPanel.style.display="flex",this.editPanel.style.flexDirection="column",this.editPanel.style.gap="6px",this.viewPanel=document.createElement("div"),this.viewPanel.style.display="none",this.viewPanel.style.alignItems="center",this.viewPanel.style.gap="6px";const n=document.createElement("div");n.style.display="flex",n.style.alignItems="center",n.style.gap="6px",n.style.flexWrap="wrap",[{type:"none",label:"选择"},{type:"line",label:"线"},{type:"arrow",label:"箭头"},{type:"rect",label:"矩形"},{type:"circle",label:"圆形"},{type:"text",label:"文字"},{type:"cloudline",label:"云线"}].forEach(f=>{const m=this.createIconButton(f.label,qR[f.type]);m.onclick=()=>this.handlers.onDrawTypeChange(f.type),this.drawButtons[f.type]=m,n.appendChild(m)});const r=document.createElement("div");r.style.position="relative",r.style.display="flex",r.style.alignItems="center",this.colorTrigger=document.createElement("button"),this.colorTrigger.type="button",this.colorTrigger.title="颜色",this.colorTrigger.style.width="32px",this.colorTrigger.style.height="24px",this.colorTrigger.style.padding="2px",this.colorTrigger.style.border="1px solid #d9d9d9",this.colorTrigger.style.borderRadius="4px",this.colorTrigger.style.background="#ffffff",this.colorTrigger.style.cursor="pointer",this.colorTrigger.style.display="flex",this.colorTrigger.style.alignItems="center",this.colorTrigger.style.justifyContent="center",this.colorTrigger.onclick=()=>this.setColorPresetVisible(!this.isColorPresetOpen);const o=document.createElement("span");o.style.display="block",o.style.width="100%",o.style.height="100%",o.style.borderRadius="2px",o.style.border="1px solid rgba(0, 0, 0, 0.12)",this.colorTrigger.appendChild(o),r.appendChild(this.colorTrigger),this.colorInput=document.createElement("input"),this.colorInput.type="color",this.colorInput.value=t.stroke,this.colorInput.style.position="absolute",this.colorInput.style.width="1px",this.colorInput.style.height="1px",this.colorInput.style.opacity="0",this.colorInput.style.pointerEvents="none",this.colorInput.style.left="0",this.colorInput.style.top="0",this.colorInput.tabIndex=-1,this.colorInput.oninput=()=>{this.updateColorControl(this.colorInput.value),this.handlers.onColorChange(this.colorInput.value),this.setColorPresetVisible(!1)},r.appendChild(this.colorInput),this.colorPresetPanel=document.createElement("div"),this.colorPresetPanel.style.position="absolute",this.colorPresetPanel.style.top="30px",this.colorPresetPanel.style.left="0",this.colorPresetPanel.style.display="none",this.colorPresetPanel.style.padding="8px",this.colorPresetPanel.style.background="#ffffff",this.colorPresetPanel.style.border="1px solid #d9d9d9",this.colorPresetPanel.style.borderRadius="6px",this.colorPresetPanel.style.boxShadow="0 6px 18px rgba(0, 0, 0, 0.14)",this.colorPresetPanel.style.zIndex="20",this.colorPresetPanel.style.width="152px";const a=document.createElement("div");a.style.display="grid",a.style.gridTemplateColumns="repeat(5, 1fr)",a.style.gap="6px",HR.forEach(f=>{const m=document.createElement("button");m.type="button",m.title=f,m.style.width="22px",m.style.height="22px",m.style.padding="0",m.style.border="1px solid #d9d9d9",m.style.borderRadius="4px",m.style.background=f,m.style.cursor="pointer",m.onclick=()=>{this.updateColorControl(f),this.handlers.onColorChange(f),this.setColorPresetVisible(!1)},a.appendChild(m)}),this.colorPresetPanel.appendChild(a);const l=document.createElement("button");l.type="button",l.textContent="自定义",l.style.marginTop="8px",l.style.width="100%",l.style.height="26px",l.style.border="1px solid #d9d9d9",l.style.borderRadius="4px",l.style.background="#ffffff",l.style.color="#333333",l.style.cursor="pointer",l.onclick=()=>this.openNativeColorPicker(),this.colorPresetPanel.appendChild(l),r.appendChild(this.colorPresetPanel),this.updateColorControl(t.stroke),n.appendChild(this.createField("",r)),this.strokeWidthInput=document.createElement("input"),this.strokeWidthInput.type="number",this.strokeWidthInput.min="1",this.strokeWidthInput.max="20",this.strokeWidthInput.step="1",this.strokeWidthInput.value=String(t.strokeWidth),this.strokeWidthInput.style.width="46px",this.strokeWidthInput.oninput=()=>this.handlers.onStrokeWidthChange(this.strokeWidthInput.value),n.appendChild(this.createField("",this.strokeWidthInput,KR,"线宽")),this.fontSizeInput=document.createElement("input"),this.fontSizeInput.type="number",this.fontSizeInput.min="10",this.fontSizeInput.max="96",this.fontSizeInput.step="1",this.fontSizeInput.value=String(t.fontSize),this.fontSizeInput.style.width="46px",this.fontSizeInput.oninput=()=>this.handlers.onFontSizeChange(this.fontSizeInput.value),n.appendChild(this.createField("",this.fontSizeInput,$R,"字号")),this.distanceButton=this.createIconButton("测量",XR),this.distanceButton.onclick=()=>this.handlers.onMeasureToggle(),n.appendChild(this.distanceButton);const c=this.createIconButton("截图",YR);c.onclick=()=>this.handlers.onScreenshot(),n.appendChild(c);const h=this.createTextButton("×","取消");h.onclick=()=>this.handlers.onCancel(),h.style.background="#ff4d4f",h.style.borderColor="#ff4d4f",h.style.color="#ffffff",n.appendChild(h);const u=this.createTextButton("✔","确定");u.onclick=()=>this.handlers.onConfirm(),u.style.background="#52c41a",u.style.borderColor="#52c41a",u.style.color="#ffffff",n.appendChild(u),this.measureSubPanel=document.createElement("div"),this.measureSubPanel.style.display="none",this.measureSubPanel.style.alignItems="center",this.measureSubPanel.style.gap="6px",this.measureSubPanel.style.flexWrap="wrap",this.measureSubPanel.style.paddingTop="2px",JR.forEach(f=>{const m=this.createSmallIconButton(f.label,ZR[f.type]);m.onclick=()=>this.handlers.onMeasureTypeChange(f.type),this.measureTypeButtons[f.type]=m,this.measureSubPanel.appendChild(m)}),this.editPanel.appendChild(n),this.editPanel.appendChild(this.measureSubPanel);const d=this.createTextButton("关闭","关闭");d.onclick=()=>this.handlers.onClose(),this.viewPanel.appendChild(d),this.root.appendChild(this.editPanel),this.root.appendChild(this.viewPanel),this.disabledMask=document.createElement("div"),this.disabledMask.style.position="absolute",this.disabledMask.style.inset="0",this.disabledMask.style.display="none",this.disabledMask.style.background="rgba(255, 255, 255, 0.55)",this.disabledMask.style.backdropFilter="blur(1px)",this.disabledMask.style.cursor="not-allowed",this.disabledMask.style.pointerEvents="auto",this.disabledMask.style.zIndex="10",this.root.appendChild(this.disabledMask),document.addEventListener("pointerdown",this.onDocumentPointerDown),this.setMode("edit")}root;disabledMask;drawButtons={};measureTypeButtons={};distanceButton;colorTrigger;colorInput;colorPresetPanel;strokeWidthInput;fontSizeInput;editPanel;viewPanel;measureSubPanel;mode="edit";isEditPanelMasked=!1;isColorPresetOpen=!1;onDocumentPointerDown=e=>{const t=e.target;t&&this.root.contains(t)||this.setColorPresetVisible(!1)};mount(e){e.appendChild(this.root)}show(){this.root.style.display="block"}hide(){this.root.style.display="none"}setMode(e){this.mode=e,this.editPanel.style.display=e==="edit"?"flex":"none",this.viewPanel.style.display=e==="view"?"flex":"none",e==="view"&&(this.setMeasurePanelVisible(!1),this.setColorPresetVisible(!1)),this.applyEditPanelMaskState()}setEditPanelMasked(e){this.isEditPanelMasked=e,this.applyEditPanelMaskState()}setDrawType(e){for(const t in this.drawButtons){const n=this.drawButtons[t];if(!n)continue;const i=t===e;n.style.background=i?"#eaf2ff":"#ffffff",n.style.borderColor=i?"#2f80ed":"#d9d9d9"}}setMeasurePanelVisible(e){if(this.mode!=="edit"){this.measureSubPanel.style.display="none";return}this.measureSubPanel.style.display=e?"flex":"none"}setMeasureState(e,t){this.distanceButton.style.background=e?"#eaf2ff":"#ffffff",this.distanceButton.style.borderColor=e?"#2f80ed":"#d9d9d9";for(const n in this.measureTypeButtons){const i=this.measureTypeButtons[n];if(!i)continue;const r=e&&t===n;i.style.background=r?"#eaf2ff":"#ffffff",i.style.borderColor=r?"#2f80ed":"#d9d9d9"}}setStyleValues(e){e.stroke&&this.updateColorControl(e.stroke),typeof e.strokeWidth=="number"&&(this.strokeWidthInput.value=String(e.strokeWidth)),typeof e.fontSize=="number"&&(this.fontSizeInput.value=String(e.fontSize))}dispose(){this.colorInput.oninput=null,this.strokeWidthInput.oninput=null,this.fontSizeInput.oninput=null,document.removeEventListener("pointerdown",this.onDocumentPointerDown),this.root.remove()}applyEditPanelMaskState(){const e=this.mode==="edit"&&this.isEditPanelMasked;this.disabledMask.style.display=e?"block":"none",e&&this.setColorPresetVisible(!1),this.editPanel.querySelectorAll("button, input").forEach(n=>{const i=n;i.disabled=e})}createField(e,t,n,i=""){const r=document.createElement("div");if(r.style.display="flex",r.style.alignItems="center",r.style.gap="4px",r.style.padding="0 2px",r.style.color="#333333",r.style.fontSize="12px",e){const o=document.createElement("span");o.textContent=e,r.appendChild(o)}if(n){const o=document.createElement("img");o.src=n,o.alt=i,o.style.width="14px",o.style.height="14px",o.style.display="block",r.appendChild(o)}return t instanceof HTMLInputElement&&(t.style.height="24px",t.style.border="1px solid #d9d9d9",t.style.borderRadius="4px",t.style.background="#ffffff",t.style.color="#333333",t.style.outline="none",t.style.padding="0 4px"),r.appendChild(t),r}updateColorControl(e){this.colorInput.value=e;const t=this.colorTrigger.firstElementChild;t&&(t.style.background=e)}setColorPresetVisible(e){this.isColorPresetOpen=e,this.colorPresetPanel.style.display=e?"block":"none",this.colorTrigger.style.borderColor=e?"#2f80ed":"#d9d9d9"}openNativeColorPicker(){const e=this.colorInput;if(typeof e.showPicker=="function"){e.showPicker();return}e.click()}createIconButton(e,t){const n=document.createElement("button");n.type="button",n.style.width="28px",n.style.height="28px",n.style.padding="0",n.style.display="flex",n.style.alignItems="center",n.style.justifyContent="center",n.style.border="1px solid #d9d9d9",n.style.borderRadius="4px",n.style.background="#ffffff",n.style.cursor="pointer";const i=document.createElement("img");return i.src=t,i.alt=e,i.style.width="16px",i.style.height="16px",i.style.display="block",n.appendChild(i),n}createSmallIconButton(e,t){const n=document.createElement("button");n.type="button",n.style.width="26px",n.style.height="26px",n.style.padding="0",n.style.display="flex",n.style.alignItems="center",n.style.justifyContent="center",n.style.border="1px solid #d9d9d9",n.style.borderRadius="4px",n.style.background="#ffffff",n.style.cursor="pointer";const i=document.createElement("img");return i.src=t,i.alt=e,i.style.width="14px",i.style.height="14px",i.style.display="block",n.appendChild(i),n}createTextButton(e,t){const n=document.createElement("button");return n.type="button",n.title=t,n.textContent=e,n.style.width="28px",n.style.height="28px",n.style.padding="0 10px",n.style.border="1px solid #d9d9d9",n.style.borderRadius="4px",n.style.background="#ffffff",n.style.color="#333333",n.style.fontSize="13px",n.style.lineHeight="1",n.style.cursor="pointer",n}}class tk{engine;wrapper;canvasEl;canvas;toolbar;isActive=!1;isVisible=!0;isViewLocked=!0;isDistanceMeasureMode=!1;isMeasurePanelExpanded=!1;drawType="none";mode="edit";currentMeasureType=null;sessionSnapshot=null;actionHandlers={};drawStyle={stroke:"#ff4d4f",strokeWidth:2,fill:"rgba(255, 77, 79, 0.08)",fontSize:16,text:"T",cloudRadius:10};startPoint=null;tempObject=null;cloudPoints=[];onMouseDown=e=>this.handleMouseDown(e);onMouseMove=e=>this.handleMouseMove(e);onMouseUp=e=>this.handleMouseUp(e);onMouseDblClick=e=>this.handleMouseDblClick(e);onSelectionChanged=()=>this.syncStyleFromSelection();onKeyDown=e=>this.handleKeyDown(e);constructor(e){this.engine=e;const t=this.engine.container;if(!t)throw new Error("FabricDraw: engine container not found.");this.wrapper=document.createElement("div"),this.wrapper.className="fabric-draw-layer",this.wrapper.style.position="absolute",this.wrapper.style.left="0",this.wrapper.style.top="0",this.wrapper.style.right="0",this.wrapper.style.bottom="0",this.wrapper.style.pointerEvents="none",this.canvasEl=document.createElement("canvas"),this.canvasEl.style.width="100%",this.canvasEl.style.height="100%",this.wrapper.appendChild(this.canvasEl),this.toolbar=new ek({onDrawTypeChange:i=>this.setDrawType(i),onMeasureToggle:()=>this.toggleMeasurePanel(),onMeasureTypeChange:i=>this.activateDistanceMeasure(i),onScreenshot:()=>{this.saveScreenshot(this.createScreenshotFileName())},onColorChange:i=>this.handleColorInputChange(i),onStrokeWidthChange:i=>this.handleStrokeWidthInputChange(i),onFontSizeChange:i=>this.handleFontSizeInputChange(i),onCancel:()=>{this.handleCancelClick()},onConfirm:()=>this.handleConfirmClick(),onClose:()=>{this.handleCloseClick()}},{stroke:this.drawStyle.stroke,strokeWidth:this.drawStyle.strokeWidth,fontSize:this.drawStyle.fontSize}),this.toolbar.mount(this.wrapper);const n=this.engine.renderer?.domElement;n?.nextSibling?t.insertBefore(this.wrapper,n.nextSibling):t.appendChild(this.wrapper),this.canvas=new Zp(this.canvasEl,{selection:!0,preserveObjectStacking:!0}),this.resize(),this.canvas.on("mouse:down",this.onMouseDown),this.canvas.on("mouse:move",this.onMouseMove),this.canvas.on("mouse:up",this.onMouseUp),this.canvas.on("mouse:dblclick",this.onMouseDblClick),this.canvas.on("selection:created",this.onSelectionChanged),this.canvas.on("selection:updated",this.onSelectionChanged),this.canvas.on("selection:cleared",this.onSelectionChanged),window.addEventListener("keydown",this.onKeyDown),this.refreshToolbarState()}active(e="edit"){this.isActive=!0,this.mode=e,this.isViewLocked=!0,this.drawType="none",this.isMeasurePanelExpanded=!1,this.currentMeasureType=null,this.canvas.defaultCursor="default",this.sessionSnapshot=e==="edit"?this.cloneJson(this.getAllShapes()):null,this.toolbar.setMode(e),this.applyCanvasInteractive(e==="edit"),this.isVisible&&this.toolbar.show(),this.updateOverlayPointerEvents(),this.refreshToolbarState()}disActive(){this.isActive=!1,this.isViewLocked=!0,this.startPoint=null,this.cloudPoints=[],this.tempObject=null,this.drawType="none",this.mode="edit",this.isMeasurePanelExpanded=!1,this.currentMeasureType=null,this.sessionSnapshot=null,this.stopDistanceMeasureMode(),this.canvas.defaultCursor="default",this.canvas.discardActiveObject(),this.applyCanvasInteractive(!0),this.canvas.requestRenderAll(),this.toolbar.setMode("edit"),this.toolbar.hide(),this.updateOverlayPointerEvents(),this.refreshToolbarState()}close(){this.disActive()}hide(){this.isVisible=!1,this.wrapper.style.display="none",this.toolbar.hide()}show(){this.isVisible=!0,this.wrapper.style.display="block",this.isActive&&this.toolbar.show(),this.resize()}isShown(){return this.isVisible}setDrawType(e,t){this.mode!=="view"&&(this.stopDistanceMeasureMode(),this.isMeasurePanelExpanded=!1,this.currentMeasureType=null,this.drawType=e,t&&(this.drawStyle={...this.drawStyle,...t}),this.canvas.defaultCursor=e==="none"?"default":"crosshair",this.updateOverlayPointerEvents(),this.refreshToolbarState())}getDrawType(){return this.drawType}setActionHandlers(e){this.actionHandlers={...e}}drawLine(e,t,n){const i=this.mergeStyle(n),r=this.createLineObject(e,t,i,!0);return this.canvas.add(r),this.canvas.requestRenderAll(),r}drawArrow(e,t,n){const i=this.mergeStyle(n),r=this.createArrowObject(e,t,i,!0);return this.canvas.add(r),this.canvas.requestRenderAll(),r}drawRect(e,t,n){const i=this.mergeStyle(n),r=this.createRectObject(e,t,i,!0);return this.canvas.add(r),this.canvas.requestRenderAll(),r}drawCircle(e,t,n){const i=this.mergeStyle(n),r=this.createCircleObject(e,t,i,!0);return this.canvas.add(r),this.canvas.requestRenderAll(),r}drawText(e,t,n){const i=this.mergeStyle(n),r=new Fr(t??i.text,{left:e.x,top:e.y,...this.createTextStyle(i),selectable:!0,evented:!0,objectCaching:!1});return r.annotationType="text",this.canvas.add(r),this.canvas.requestRenderAll(),r}drawCloudLine(e,t){if(e.length<2)return null;const n=this.mergeStyle(t),i=this.createCloudObject(e,n,!0);return i?(this.canvas.add(i),this.canvas.requestRenderAll(),i):null}getAllShapes(){return this.canvas.toObject(["annotationType"])}clearAllShapes(){this.canvas.clear(),this.canvas.requestRenderAll()}async restoreAllShapes(e){await this.canvas.loadFromJSON(e),this.canvas.requestRenderAll()}saveScreenshot(e="bim-snapshot.png"){const t=this.canvas.lowerCanvasEl;return t?GR(this.engine,t,e):null}resize(e,t){const n=this.engine.container;if(!n)return;const i=e??n.clientWidth??1,r=t??n.clientHeight??1;this.canvas.setDimensions({width:i,height:r}),this.canvas.requestRenderAll()}dispose(){this.stopDistanceMeasureMode(),window.removeEventListener("keydown",this.onKeyDown),this.canvas.off("mouse:down",this.onMouseDown),this.canvas.off("mouse:move",this.onMouseMove),this.canvas.off("mouse:up",this.onMouseUp),this.canvas.off("mouse:dblclick",this.onMouseDblClick),this.canvas.off("selection:created",this.onSelectionChanged),this.canvas.off("selection:updated",this.onSelectionChanged),this.canvas.off("selection:cleared",this.onSelectionChanged),this.toolbar.dispose(),this.canvas.dispose(),this.wrapper.remove()}handleMouseDown(e){if(!this.isActive||this.mode==="view"||!this.isViewLocked||this.drawType==="none"||e?.target)return;const t=this.getPointFromEvent(e);if(this.drawType==="text"){const i=this.drawText(t);this.canvas.setActiveObject(i),this.canvas.requestRenderAll(),setTimeout(()=>{i.enterEditing(),i.hiddenTextarea?.focus(),i.selectAll()},0);return}this.startPoint=t,this.cloudPoints=[t],this.canvas.selection=!1,this.canvas.discardActiveObject();const n=this.createDraftObject(t,t);n&&(this.tempObject=n,this.canvas.add(n),this.canvas.requestRenderAll())}handleMouseMove(e){if(!this.isActive||this.mode==="view"||!this.isViewLocked||!this.startPoint||!this.tempObject)return;const t=this.getPointFromEvent(e),n=this.drawStyle;if(this.drawType==="cloudline"){if(this.shouldAppendCloudPoint(t)){this.cloudPoints.push(t),this.canvas.remove(this.tempObject);const i=this.createCloudObject(this.cloudPoints,n,!1);if(!i)return;this.tempObject=i,this.canvas.add(i),this.canvas.requestRenderAll()}return}if(this.drawType==="arrow"){this.canvas.remove(this.tempObject),this.tempObject=this.createArrowObject(this.startPoint,t,n,!1),this.canvas.add(this.tempObject),this.canvas.requestRenderAll();return}this.updateDraftObject(this.startPoint,t),this.canvas.requestRenderAll()}handleMouseUp(e){if(!this.isActive||this.mode==="view"||!this.isViewLocked||!this.startPoint)return;const t=this.getPointFromEvent(e);this.drawType==="cloudline"&&this.cloudPoints.length===1&&(this.cloudPoints.push(t),this.canvas.remove(this.tempObject),this.tempObject=this.createCloudObject(this.cloudPoints,this.drawStyle,!0),this.tempObject&&this.canvas.add(this.tempObject)),this.tempObject&&(this.tempObject.set({selectable:!0,evented:!0}),this.tempObject.setCoords?.(),this.canvas.requestRenderAll()),this.startPoint=null,this.tempObject=null,this.cloudPoints=[],this.canvas.selection=!0}handleMouseDblClick(e){const t=e?.target;this.isTextObject(t)&&(t.enterEditing(),t.hiddenTextarea?.focus(),t.selectAll?.())}handleKeyDown(e){if(!this.isActive)return;const t=this.canvas.getActiveObject();if(this.isTextObject(t)&&t?.isEditing||this.isInputElement(e.target))return;if(e.key==="Control"&&!e.repeat){this.toggleViewLock();return}if(e.key==="Escape"){e.preventDefault(),this.mode==="view"?this.handleCloseClick():this.handleCancelClick();return}if(e.key==="Enter"){this.mode==="edit"&&(e.preventDefault(),this.handleConfirmClick());return}if(e.key!=="Delete"&&e.key!=="Backspace"||!t)return;e.preventDefault(),this.canvas.getActiveObjects().forEach(r=>this.canvas.remove(r)),this.canvas.discardActiveObject(),this.canvas.requestRenderAll()}getPointFromEvent(e){if(e?.e){const n=this.canvas.getScenePoint(e.e);return{x:n.x,y:n.y}}const t=e?.scenePoint??e?.pointer??e?.absolutePointer;return t?{x:t.x,y:t.y}:{x:0,y:0}}shouldAppendCloudPoint(e){if(this.cloudPoints.length===0)return!0;const t=this.cloudPoints[this.cloudPoints.length-1],n=e.x-t.x,i=e.y-t.y;return Math.sqrt(n*n+i*i)>=6}createDraftObject(e,t){const n=this.drawStyle;switch(this.drawType){case"line":return this.createLineObject(e,t,n,!1);case"arrow":return this.createArrowObject(e,t,n,!1);case"rect":return this.createRectObject(e,t,n,!1);case"circle":return this.createCircleObject(e,t,n,!1);case"cloudline":return this.createCloudObject([e,t],n,!1);default:return null}}updateDraftObject(e,t){if(this.tempObject){if(this.drawType==="line"){this.tempObject.set({x2:t.x,y2:t.y});return}if(this.drawType==="rect"){const n=this.getBoxFromPoints(e,t);this.tempObject.set({left:n.left,top:n.top,width:n.width,height:n.height});return}if(this.drawType==="circle"){const n=this.getCircleFromPoints(e,t);this.tempObject.set({left:n.left,top:n.top,radius:n.radius})}}}mergeStyle(e){return{...this.drawStyle,...e??{}}}createObjectBase(e,t){return{stroke:e.stroke,strokeWidth:e.strokeWidth,fill:e.fill,selectable:t,evented:t,objectCaching:!1}}createLineObject(e,t,n,i){const r=new Hs([e.x,e.y,t.x,t.y],{...this.createObjectBase(n,i),fill:"",strokeLineCap:"round"});return r.annotationType="line",r}createRectObject(e,t,n,i){const r=this.getBoxFromPoints(e,t),o=new Qs({...this.createObjectBase(n,i),left:r.left,top:r.top,width:r.width,height:r.height,originX:"left",originY:"top"});return o.annotationType="rect",o}createCircleObject(e,t,n,i){const r=this.getCircleFromPoints(e,t),o=new kr({...this.createObjectBase(n,i),left:r.left,top:r.top,radius:r.radius,originX:"left",originY:"top"});return o.annotationType="circle",o}createArrowObject(e,t,n,i){const r=t.x-e.x,o=t.y-e.y,a=Math.sqrt(r*r+o*o);if(a<1e-6){const B=new Hs([e.x,e.y,t.x,t.y],{stroke:n.stroke,strokeWidth:n.strokeWidth,fill:"",selectable:i,evented:i}),M=new js([B],{selectable:i,evented:i,objectCaching:!1});return M.annotationType="arrow",M}const l=r/a,c=o/a,h=-c,u=l,d=Math.max(10,n.strokeWidth*6),f=d*.72,m=t.x-l*d,g=t.y-c*d,A=m+h*(f*.5),p=g+u*(f*.5),x=m-h*(f*.5),y=g-u*(f*.5),v=new Hs([e.x,e.y,t.x,t.y],{stroke:n.stroke,strokeWidth:n.strokeWidth,fill:"",strokeLineCap:"round",selectable:!1,evented:!1}),_=`M ${t.x} ${t.y} L ${A} ${p} L ${x} ${y} Z`,E=new Rr(_,{fill:n.stroke,stroke:n.stroke,strokeWidth:1,selectable:!1,evented:!1,objectCaching:!1}),I=new js([v,E],{selectable:i,evented:i,objectCaching:!1});return I.annotationType="arrow",I}createCloudObject(e,t,n){const i=this.buildCloudPath(e,t.cloudRadius);if(!i)return null;const r=new Rr(i,{stroke:t.stroke,strokeWidth:t.strokeWidth,fill:"",strokeLineCap:"round",strokeLineJoin:"round",selectable:n,evented:n});return r.annotationType="cloudline",r}getBoxFromPoints(e,t){return{left:Math.min(e.x,t.x),top:Math.min(e.y,t.y),width:Math.abs(t.x-e.x),height:Math.abs(t.y-e.y)}}getCircleFromPoints(e,t){const n=t.x-e.x,i=t.y-e.y,r=Math.max(Math.abs(n),Math.abs(i)),o=n>=0?e.x:e.x-r,a=i>=0?e.y:e.y-r;return{left:o,top:a,radius:Math.max(r/2,1)}}buildCloudPath(e,t){if(e.length<2)return"";const n=Math.max(2,t),i=n*1.4;let r=`M ${e[0].x} ${e[0].y}`,o=1;for(let a=1;a<e.length;a++){const l=e[a-1],c=e[a],h=c.x-l.x,u=c.y-l.y,d=Math.sqrt(h*h+u*u);if(d<.1)continue;const f=-u/d,m=h/d,g=Math.max(1,Math.round(d/i));for(let A=1;A<=g;A++){const p=A/g,x=l.x+h*p,y=l.y+u*p,v=o%2===0?-1:1,_=x+f*n*v,E=y+m*n*v;r+=` Q ${_} ${E} ${x} ${y}`,o++}}return r}handleColorInputChange(e){this.drawStyle.stroke=e||this.drawStyle.stroke,this.drawStyle.fill=this.colorToAlpha(this.drawStyle.stroke,.08),this.applyCurrentStyleToSelection(),this.refreshToolbarStyleValues()}handleStrokeWidthInputChange(e){const t=this.parseNumber(e,this.drawStyle.strokeWidth,1,20);this.drawStyle.strokeWidth=t,this.applyCurrentStyleToSelection(),this.refreshToolbarStyleValues()}handleFontSizeInputChange(e){const t=this.parseNumber(e,this.drawStyle.fontSize,1,200);this.drawStyle.fontSize=t,this.applyCurrentStyleToSelection(),this.refreshToolbarStyleValues()}applyCurrentStyleToSelection(){const e=this.canvas.getActiveObjects();e.length!==0&&(e.forEach(t=>this.applyStyleToObject(t)),this.canvas.requestRenderAll())}applyStyleToObject(e){if(!e)return;if(e.annotationType==="arrow"&&Array.isArray(e._objects)){e._objects.forEach(n=>{if(n?.type==="triangle"||n?.type==="path"){n.set({fill:this.drawStyle.stroke,stroke:this.drawStyle.stroke,strokeWidth:1});return}n?.set({stroke:this.drawStyle.stroke,strokeWidth:this.drawStyle.strokeWidth,strokeLineCap:"round"})}),e.set({dirty:!0}),e.setCoords?.();return}if(this.isTextObject(e)){e.set({...this.createTextStyle(this.drawStyle),fontSize:this.drawStyle.fontSize}),e.setCoords?.();return}const t={stroke:this.drawStyle.stroke,strokeWidth:this.drawStyle.strokeWidth};e?.type==="line"||e?.type==="path"?t.fill="":t.fill=this.drawStyle.fill,e.set(t),e.setCoords?.()}syncStyleFromSelection(){const e=this.canvas.getActiveObject();if(!e)return;const t=this.readStyleFromObject(e);t.stroke&&(this.drawStyle.stroke=t.stroke,this.drawStyle.fill=this.colorToAlpha(t.stroke,.08)),typeof t.strokeWidth=="number"&&(this.drawStyle.strokeWidth=t.strokeWidth),typeof t.fontSize=="number"&&(this.drawStyle.fontSize=t.fontSize),this.refreshToolbarStyleValues()}readStyleFromObject(e){if(!e)return{};if(e.annotationType==="arrow"&&Array.isArray(e._objects)){const t=e._objects.find(n=>n?.type==="line")??e._objects[0];return{stroke:t?.stroke,strokeWidth:t?.strokeWidth}}return this.isTextObject(e)?{stroke:e.fill??this.drawStyle.stroke,fontSize:e.fontSize??this.drawStyle.fontSize}:{stroke:e.stroke??this.drawStyle.stroke,strokeWidth:e.strokeWidth??this.drawStyle.strokeWidth}}isTextObject(e){return e?e.type==="i-text"||e.type==="textbox"||e.annotationType==="text":!1}createTextStyle(e){return{fontSize:e.fontSize,fill:e.stroke,stroke:this.getTextOutlineColor(e.stroke),strokeWidth:3,strokeLineJoin:"round",paintFirst:"stroke"}}getTextOutlineColor(e){return this.isWhiteTextColor(e)?"#000000":"#ffffff"}isWhiteTextColor(e){const t=e.trim().toLowerCase();if(t==="#fff"||t==="#ffffff"||t==="white")return!0;const n=t.match(/^rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})/);if(n){const[,i,r,o]=n;return Number(i)>=245&&Number(r)>=245&&Number(o)>=245}return!1}isInputElement(e){const t=e;if(!t||!t.tagName)return!1;const n=t.tagName.toLowerCase();return n==="input"||n==="textarea"||!!t.isContentEditable}applyCanvasInteractive(e){this.canvas.selection=e,this.canvas.getObjects().forEach(t=>{t.set({selectable:e,evented:e}),t.setCoords?.()}),this.canvas.discardActiveObject(),this.canvas.requestRenderAll()}parseNumber(e,t,n,i){const r=Number(e);return Number.isFinite(r)?Math.min(i,Math.max(n,r)):t}colorToAlpha(e,t){const n=e.trim(),i=/^#([0-9a-fA-F]{3})$/.exec(n);if(i){const o=i[1],a=parseInt(o[0]+o[0],16),l=parseInt(o[1]+o[1],16),c=parseInt(o[2]+o[2],16);return`rgba(${a}, ${l}, ${c}, ${t})`}const r=/^#([0-9a-fA-F]{6})$/.exec(n);if(r){const o=r[1],a=parseInt(o.slice(0,2),16),l=parseInt(o.slice(2,4),16),c=parseInt(o.slice(4,6),16);return`rgba(${a}, ${l}, ${c}, ${t})`}return this.drawStyle.fill}toggleMeasurePanel(){!this.isActive||this.mode!=="edit"||(this.isMeasurePanelExpanded=!this.isMeasurePanelExpanded,this.refreshToolbarState())}activateDistanceMeasure(e){if(!this.isActive||this.mode!=="edit")return;this.drawType="none",this.canvas.defaultCursor="default",this.isDistanceMeasureMode=!0,this.isMeasurePanelExpanded=!0,this.currentMeasureType=e,this.canvas.discardActiveObject(),this.canvas.requestRenderAll();const t=this.engine.measure;t?.active?.(),this.disActiveMeasureTools(t),this.activeMeasureTool(t,e),this.updateOverlayPointerEvents(),this.refreshToolbarState()}stopDistanceMeasureMode(){if(!this.isDistanceMeasureMode)return;const e=this.engine.measure;this.disActiveMeasureTools(e),this.isDistanceMeasureMode=!1,this.currentMeasureType=null,this.updateOverlayPointerEvents(),this.refreshToolbarState()}disActiveMeasureTools(e){e?.distanceMeasure?.disActive?.(),e?.faceDistanceMeasure?.disActive?.(),e?.clearHeightMeasure?.disActive?.(),e?.elevationMeasure?.disActive?.(),e?.pointMeasure?.disActive?.(),e?.angleMeasure?.disActive?.(),e?.areaMeasure?.disActive?.(),e?.slopeMeasure?.disActive?.()}activeMeasureTool(e,t){const i={distance:"distanceMeasure",clearDistance:"faceDistanceMeasure",clearHeight:"clearHeightMeasure",elevation:"elevationMeasure",point:"pointMeasure",angle:"angleMeasure",area:"areaMeasure",slope:"slopeMeasure"}[t];i&&e?.[i]?.active?.()}updateOverlayPointerEvents(){if(!this.isActive){this.wrapper.style.pointerEvents="none",this.canvasEl.style.pointerEvents="none";return}if(this.mode==="view"||this.isDistanceMeasureMode||!this.isViewLocked){this.wrapper.style.pointerEvents="none",this.canvasEl.style.pointerEvents="none",this.toolbar.root.style.pointerEvents="auto";return}this.wrapper.style.pointerEvents="auto",this.canvasEl.style.pointerEvents="auto",this.toolbar.root.style.pointerEvents="auto"}toggleViewLock(){!this.isActive||this.mode!=="edit"||this.isDistanceMeasureMode||(this.isViewLocked=!this.isViewLocked,this.isViewLocked?this.canvas.selection=!0:(this.startPoint=null,this.tempObject=null,this.cloudPoints=[],this.canvas.discardActiveObject(),this.canvas.selection=!1),this.canvas.requestRenderAll(),this.updateOverlayPointerEvents(),this.refreshToolbarState())}async handleCancelClick(){this.sessionSnapshot&&await this.restoreAllShapes(this.cloneJson(this.sessionSnapshot)),this.actionHandlers.onCancel?.(),this.disActive()}async handleCloseClick(){this.disActive()}handleConfirmClick(){const e=this.cloneJson(this.getAllShapes());this.actionHandlers.onConfirm?.(e),this.disActive()}refreshToolbarStyleValues(){this.toolbar.setStyleValues({stroke:this.drawStyle.stroke,strokeWidth:this.drawStyle.strokeWidth,fontSize:this.drawStyle.fontSize})}refreshToolbarState(){this.toolbar.setDrawType(this.drawType),this.toolbar.setMode(this.mode),this.toolbar.setMeasurePanelVisible(this.isMeasurePanelExpanded),this.toolbar.setMeasureState(this.isDistanceMeasureMode,this.currentMeasureType),this.toolbar.setEditPanelMasked(!this.isViewLocked),this.refreshToolbarStyleValues()}createScreenshotFileName(){const e=new Date,t=e.getFullYear(),n=String(e.getMonth()+1).padStart(2,"0"),i=String(e.getDate()).padStart(2,"0"),r=String(e.getHours()).padStart(2,"0"),o=String(e.getMinutes()).padStart(2,"0"),a=String(e.getSeconds()).padStart(2,"0");return`bim-snapshot-${t}${n}${i}-${r}${o}${a}.png`}cloneJson(e){return JSON.parse(JSON.stringify(e))}}class nk{engine;constructor(e){this.engine=e}get(){return{cameraPose:this.engine.cameraModule?.getCameraPose?.()??null,clipping:this.captureClippingState(),measureData:this.captureMeasureData(),annotationData:this.captureAnnotationData()}}async restore(e,t="view",n){if(!e){n?.(null);return}e.cameraPose&&this.engine.cameraModule?.restoreCameraPose?.(e.cameraPose),this.restoreClippingState(e.clipping),this.restoreMeasureData(e.measureData),await this.restoreAnnotationData(e.annotationData),this.applyAnnotationMode(t);const i=this.engine.fabricDraw;i&&i.setActionHandlers({onConfirm:r=>{const o=this.get();o.annotationData=this.serializeSnapshotValue(r),n&&n(o),this.clearAnnotation()},onCancel:()=>{this.clearAnnotation()}})}create(e){const t=this.engine.fabricDraw;if(!t){e?.(this.get());return}t.setActionHandlers({onConfirm:n=>{const i=this.get();i.annotationData=this.serializeSnapshotValue(n),e?.(i),this.clearAnnotation()},onCancel:()=>{this.clearAnnotation()}}),t.show?.(),t.active?.("edit"),t.setDrawType?.("none")}clearAnnotation(){this.engine.fabricDraw?.clearAllShapes?.(),this.engine.measure.disActive?.()}captureClippingState(){const e=this.engine.clipping,t=e?.sectionFace,n=e?.currentClippingMode??"",i={mode:n,fillCutFace:e?.getFillCutFace?.()??!0};if(n==="box"&&e?.sectionBox?.getboxXyz&&(i.box=e.sectionBox.getboxXyz()),n==="x"||n==="y"||n==="z"||n==="face"){const r=t?.normal;r&&(i.face={normal:{x:Number(r.x)||0,y:Number(r.y)||0,z:Number(r.z)||1},distance:Number(t?.distance)||0,direction:Number(t?.direction)===-1?-1:1})}return i}restoreClippingState(e){const t=this.engine.clipping;if(!t)return;typeof e?.fillCutFace=="boolean"&&t.setFillCutFace?.(e.fillCutFace);const n=e?.mode??"";if(!n){t.disActive?.();return}if(n==="box"){t.active?.("box"),e.box&&t.sectionBox?.setboxXyz?.(e.box);return}if(n==="x"||n==="y"||n==="z"){t.active?.(n),this.applyFaceState(e.face);return}if(n==="face"){this.restoreFaceMode(e.face);return}t.active?.(n)}restoreFaceMode(e){const t=this.engine.clipping,n=t?.sectionFace;!t||!n||(t.sectionBox?.disActive?.(),n.disActive?.(),n.active?.(),t.currentClippingMode="face",this.applyFaceState(e))}applyFaceState(e){if(!e)return;const t=this.engine.clipping?.sectionFace;if(!t)return;const n=new b.Vector3(e.normal.x,e.normal.y,e.normal.z).normalize();t.direction=e.direction===-1?-1:1,t.setFaceNormal?.(n,e.distance??0)}captureMeasureData(){const e=this.engine.measure?.annotationData;return e?this.serializeSnapshotValue(e):null}restoreMeasureData(e){const t=this.engine.measure;if(!t)return;try{t.clearAll?.()}catch{}if(!e)return;const n=this.deserializeSnapshotValue(e);(!t.annotationData||typeof t.annotationData!="object")&&(t.annotationData={}),Object.keys(t.annotationData).forEach(i=>{t.annotationData[i]=[]}),Object.keys(n).forEach(i=>{t.annotationData[i]=Array.isArray(n[i])?n[i]:[]}),t.tools?.drawNormalAnnotation?.()}captureAnnotationData(){const e=this.engine.fabricDraw;return e?.getAllShapes?this.serializeSnapshotValue(e.getAllShapes()):null}async restoreAnnotationData(e){const t=this.engine.fabricDraw;if(!t)return;if(!e){t.clearAllShapes?.();return}const n=this.deserializeSnapshotValue(e);await t.restoreAllShapes?.(n)}applyAnnotationMode(e){const t=this.engine.fabricDraw;t&&(t.setActionHandlers?.({}),t.show?.(),t.active?.(e),t.setDrawType?.("none"))}serializeSnapshotValue(e){if(e==null)return e;if(e instanceof b.Vector3)return{__type:"Vector3",x:e.x,y:e.y,z:e.z};if(Array.isArray(e))return e.map(t=>this.serializeSnapshotValue(t));if(typeof e=="object"){if(e instanceof HTMLElement||e instanceof SVGElement)return;const t={};return Object.keys(e).forEach(n=>{if(n==="container")return;const i=this.serializeSnapshotValue(e[n]);i!==void 0&&(t[n]=i)}),t}if(typeof e!="function")return e}deserializeSnapshotValue(e){if(e==null)return e;if(Array.isArray(e))return e.map(t=>this.deserializeSnapshotValue(t));if(typeof e=="object"){if(e.__type==="Vector3")return new b.Vector3(e.x,e.y,e.z);const t={};return Object.keys(e).forEach(n=>{t[n]=this.deserializeSnapshotValue(e[n])}),t}return e}}class ik{options;deviceType;animationId=null;isDisposed=!1;isRenderingPaused=!1;controlsEnabledBeforePause=!0;animate;onWindowResize;_fpsFrameCount=0;_fpsLastCheck=0;_fpsLastSwitch=0;_lowFpsCount=0;_highFpsCount=0;_fpsCheckInterval=100;_fpsSwitchCooldown=100;_fpsThreshold=30;_fpsUpgradeThreshold=60;_lowFpsRequired=5;_highFpsRequired=.1;isMouseDown=!1;isWheeling=!1;scene;camera;renderer;sceneModule;cameraModule;deviceModule;renderModule;controlModule;composerModule;loaderModule;engineStatus;events;lightModule;interactionModule;modelToolModule;worldToScreen;handelBehaved;octreeBox;controls;stats;catchSvg;engineModelModule;viewTree;merge2d;viewCube;rangeScale;setting;measure;clipping;modelTree;engineInfo;modelProperties;modelMapperBatch;modelEdge;ai;pathRoaming;hoverHighLight;minMap;grid;level;issueReport;text;hdr;ground;skyManager;linkElement2d3d;linkView2d3d;oneClickEncoding;fabricDraw;drawingPin;models=[];reactBoundingClientRect={left:0,top:0};version="3.8.3";versionEl=null;container;constructor(e){if(window.THREE=b,this.options=e,this.container=document.getElementById(e.containerId),!this.container)throw new Error(`Container ${e.containerId} not found`);if(this.engineModelModule=new Q2(this),this.engineModelModule.init(),this.ai=new DP(this),this.deviceModule=new E_(this),this.deviceType=this.deviceModule.getDeviceType(),this.cameraModule=new Sn(this),this.sceneModule=new S_(this),this.scene=this.sceneModule.scene,this.renderModule=new sE(this),this.renderer=this.renderModule.createRenderer(),this.camera=this.cameraModule.orthographicCamera,this.scene.camera=this.camera,this.renderer){const r=this.renderer;r.interactionCullingEnabled=!0,r.interactionActive=!1,r.interactionRenderScene=this.scene,r.interactionFrameBudgetMs=this.options.interactionFrameBudgetMs??6,r.interactionSkipShadows=this.options.interactionSkipShadows??!0}this.controlModule=new dE(this),this.controlModule.switchDefaultMode(),this.controls=this.controlModule.orbitControls,this.clipping=new MP(this),this.clipping.init(),this.composerModule=new ME(this),this.composerModule.init(),this.events=new L2,this.engineStatus=new P2(this),this.engineStatus.init(),this.loaderModule=new D2(this),this.lightModule=new O2(this),this.lightModule.init(),this.viewCube=new aB(this),this.viewCube.init(),this.options.showViewCube==!1&&this.viewCube.hide(),this.octreeBox=lB(this),this.rangeScale=new cB(this),this.rangeScale.init(),this.setting=new vB(this),this.engineModelModule.init(),this.handelBehaved=Od(this),this.modelMapperBatch=new TP(this),this.measure=new DB(this),this.modelToolModule=new N2(this),this.modelProperties=new IP(this),this.interactionModule=new U2(this),this.interactionModule.init(),this.interactionModule.active(),this.hoverHighLight=new Dc(this),this.modelEdge=new yB(this),this.modelTree=new SP(this),this.viewTree=new zP(this),this.merge2d=new c3(this),this.engineInfo=new EP(this),this.pathRoaming=new PP(this),this.pathRoaming.init(),this.oneClickEncoding=new NP(this),this.minMap=new LP(this),this.linkElement2d3d=new FP(this),this.linkView2d3d=new OP(this),this.grid=new dB(this),this.level=new xB(this),this.issueReport=new RP(this),this.fabricDraw=new tk(this),this.drawingPin=new nk(this),this.text=new kP(this),this.hdr=new gB(this),this.ground=new bf(this),this.ground.init(),this.skyManager=new bB(this),this.setting.init(),this.worldToScreen=new vt(this.camera,this.renderer,this.scene),this.options.showStats&&(this.stats=new Ax,this.stats.showPanel(0),this.stats.dom.style.position="absolute",this.stats.dom.style.top="0px",this.stats.dom.style.left="0px",this.stats.dom.style.zIndex="1000",this.container.appendChild(this.stats.dom));let t=document.createElement("div");t.className="versionText",this.versionEl=t,this.updateVersionDisplay(),this.container.appendChild(t);let n=document.createElementNS("http://www.w3.org/2000/svg","svg");n.style.position="absolute",n.style.zIndex="1000",n.style.left="0px",n.style.top="0px",n.style.pointerEvents="none",this.container.appendChild(n),this.catchSvg=n,this.onWindowResize=()=>{this.handleWindowResize()},window.addEventListener("resize",this.onWindowResize);let i=this;this.controls.addEventListener("start",()=>{i.renderer&&(i.renderer.interactionActive=!0),i.events.trigger(Ss.EngineBusy),i.container&&(i.container.style.cursor="none")}),this.controls.addEventListener("end",()=>{i.renderer&&(i.renderer.interactionActive=!1),i.events.trigger(Ss.EngineFree),i.container&&(i.container.style.cursor="default")}),this.controls.addEventListener("change",()=>{const r=new b.Vector3;i.camera.getWorldDirection(r);const o=Math.atan2(r.x,-r.z);let a=new CustomEvent("D3ViewUpdate",{detail:{position:i.camera.position,rotation:o,type:i.camera.type}});window.dispatchEvent(a)}),this.events.on(Ss.LoadingCompleted,r=>{i.modelEdge.active()}),this.animate=()=>{if(!this.isRenderingPaused)this.animationId=requestAnimationFrame(this.animate);else{this.animationId=null;return}this.stats&&this.stats.begin(),this.composerModule&&this.composerModule.composer.render(),this.viewCube&&this.viewCube.cubeTool.RenderScene(),this.measure.update(),this.ground.update(),this.skyManager.update(),this.hoverHighLight.update(),this.controlModule.update(),this.minMap.update(),this.grid.update(),this.level.update(),this.text&&this.text.update(),this.stats&&this.stats.end(),this._fpsFrameCount++;const r=performance.now();if(r-this._fpsLastCheck>=this._fpsCheckInterval){const o=r-this._fpsLastCheck,a=this._fpsFrameCount/o*1e3;this._fpsFrameCount=0,this._fpsLastCheck=r,a<this._fpsThreshold?(this._lowFpsCount++,this._highFpsCount=0,this._lowFpsCount>=this._lowFpsRequired&&r-this._fpsLastSwitch>this._fpsSwitchCooldown&&(this._adaptiveRenderingDowngrade(),this._fpsLastSwitch=r,this._lowFpsCount=0)):(this._lowFpsCount=0,this._highFpsCount=0)}if(this.scene){let o=this.scene?.dirLight;o&&this.camera&&this.updateLightPosition(this.camera,o)}},this.animate()}updateVersionDisplay(){if(!this.versionEl)return;const e={simple:"simple",balance:"balance",advanced:"advanced"},t=this.engineModelModule?.getCurrentMode()??"",n=e[t]??t;this.versionEl.innerHTML=`v${this.version} | ${n}`}updateLightPosition(e,t,n=!0){const i=new b.Vector3;e.getWorldDirection(i);const r=100,o=new b.Vector3().copy(i).multiplyScalar(-r),a=new b.Vector3(0,1,0),l=new b.Vector3().crossVectors(i,a).normalize();o.addScaledVector(a,r*.5),o.addScaledVector(l,r*.3),t.position.copy(e.position).add(o);const c=new b.Vector3().copy(e.position).add(i.multiplyScalar(20));t.target.position.copy(c),t.target.updateMatrixWorld()}_adaptiveRenderingDowngrade(){const e=["simple","balance","advanced"],t=this.engineModelModule.getCurrentMode(),n=e.indexOf(t);if(n>0){const i=e[n-1];console.log(`[AdaptiveRendering] FPS低于${this._fpsThreshold},自动降级: ${t} → ${i}`),this.engineModelModule.autoSwitch(i)}}_adaptiveRenderingUpgrade(){const e=["simple","balance","advanced"],t=this.engineModelModule.getCurrentMode(),n=e.indexOf(t);if(n<e.length-1){const i=e[n+1];console.log(`[AdaptiveRendering] FPS高于${this._fpsUpgradeThreshold},自动升级: ${t} → ${i}`),this.engineModelModule.autoSwitch(i)}}pauseRendering(){if(this.isRenderingPaused){console.warn("[BimEngine] Rendering is already paused");return}this.isRenderingPaused=!0,this.controls&&(this.controlsEnabledBeforePause=this.controls.enabled,this.controls.enabled=!1)}resumeRendering(){if(!this.isRenderingPaused){console.warn("[BimEngine] Rendering is not paused");return}this.isRenderingPaused=!1,this.controls&&(this.controls.enabled=this.controlsEnabledBeforePause),this.animationId===null&&this.animate()}isRenderingPausedState(){return this.isRenderingPaused}handleWindowResize(e,t){if(!this.container||!this.renderer||!this.camera)return;if(e===void 0||t===void 0){const c=this.deviceModule.getContainerSize();e=e??c.width,t=t??c.height}if(!e||!t)return;const n=this.camera.position.clone(),i=this.camera.quaternion.clone(),r=this.camera.up.clone(),o=this.controls?.target?.clone?.(),a=this.controlModule?.orbitControls?.origin?.clone?.();this.renderer.setPixelRatio(window.devicePixelRatio),this.renderer.setSize(e,t);const l=e/t;if(this.camera===this.cameraModule.perspectiveCamera)this.cameraModule.perspectiveCamera.aspect=l,this.cameraModule.perspectiveCamera.updateProjectionMatrix(),this.camera=this.cameraModule.perspectiveCamera;else if(this.camera===this.cameraModule.orthographicCamera){const c=this.cameraModule.orthographicCamera,h=this.cameraModule.getOrthographicVisibleHeight(c);this.cameraModule.setOrthographicVisibleHeight(h,c,l),c.updateProjectionMatrix()}if(this.composerModule&&(typeof this.composerModule.resize=="function"?this.composerModule.resize(e,t):this.composerModule.composer&&this.composerModule.composer.setSize(e,t)),this.catchSvg&&this.catchSvg.setAttribute("viewBox",`0 0 ${e} ${t}`),this.fabricDraw&&this.fabricDraw.resize(e,t),this.camera.position.copy(n),this.camera.quaternion.copy(i),this.camera.up.copy(r),this.camera.updateMatrix(),this.camera.updateMatrixWorld(!0),o&&this.controls?.target&&this.controls.target.copy(o),a&&this.controlModule?.orbitControls?.origin&&this.controlModule.orbitControls.origin.copy(a),this.controlModule?.orbitControls){const c=this.controlModule.orbitControls;c._lastPosition?.copy?.(this.camera.position),c._lastTarget?.copy?.(c.target),c._lastUp?.copy?.(this.camera.up),c._lastQuaternion?.copy?.(this.camera.quaternion),c._lastZoom=this.camera.zoom}this.controlModule?.firstPersonControls?.syncRotationStateFromCamera?.(),this.controlModule?.firstPersonControls?.syncSharedTargetFromCamera?.(),this.events&&this.events.trigger(Ss.ViewportResize,{width:e,height:t})}dispose(){if(this.isDisposed)return;this.isDisposed=!0,console.log("[BimEngine] Starting engine disposal..."),this.animationId!==null&&(cancelAnimationFrame(this.animationId),this.animationId=null),this.isRenderingPaused=!0,this.onWindowResize&&window.removeEventListener("resize",this.onWindowResize);try{this.invokeIfExists(this.rangeScale,"dispose"),this.invokeIfExists(this.measure,"dispose"),this.invokeIfExists(this.clipping,"disActive"),this.invokeIfExists(this.interactionModule,"dispose"),this.invokeIfExists(this.controlModule,"dispose"),this.invokeIfExists(this.pathRoaming,"dispose"),this.invokeIfExists(this.hoverHighLight,"dispose"),this.invokeIfExists(this.linkElement2d3d,"dispose"),this.invokeIfExists(this.linkView2d3d,"dispose"),this.invokeIfExists(this.skyManager,"close",!0),this.invokeIfExists(this.hdr,"dispose"),this.invokeIfExists(this.minMap,"dispose"),this.invokeIfExists(this.grid,"dispose"),this.invokeIfExists(this.level,"dispose"),this.invokeIfExists(this.ground,"dispose"),this.invokeIfExists(this.text,"dispose"),this.invokeIfExists(this.issueReport,"dispose"),this.invokeIfExists(this.fabricDraw,"dispose"),this.invokeIfExists(this.viewCube?.cubeTool,"dispose"),this.invokeIfExists(this.handelBehaved,"disActive")}catch(t){console.warn("[BimEngine] Error disposing managers:",t)}try{this.controlModule&&(this.controlModule.originDiv&&this.controlModule.originDiv.remove(),this.controlModule.orbitControls&&typeof this.controlModule.orbitControls.dispose=="function"&&this.controlModule.orbitControls.dispose(),this.controlModule.firstPersonControls&&typeof this.controlModule.firstPersonControls.dispose=="function"&&this.controlModule.firstPersonControls.dispose())}catch(t){console.warn("[BimEngine] Error disposing controls:",t)}this.scene&&(this.disposeSceneAttachments(this.scene),this.clearScene(this.scene));try{this.composerModule&&this.composerModule.composer&&(this.composerModule.composer.passes&&this.composerModule.composer.passes.forEach(t=>{t?.dispose?.()}),this.composerModule.composer.renderTarget1&&this.composerModule.composer.renderTarget1.dispose(),this.composerModule.composer.renderTarget2&&this.composerModule.composer.renderTarget2.dispose(),this.composerModule.composer.dispose?.(),this.composerModule.composer.passes=[])}catch(t){console.warn("[BimEngine] Error disposing composer:",t)}try{this.renderModule?.disposeRenderer?.(),this.renderer&&(this.renderer.renderLists?.dispose?.(),this.renderer.domElement&&this.renderer.domElement.parentElement&&this.renderer.domElement.parentElement.removeChild(this.renderer.domElement),this.renderer.dispose(),this.renderer.forceContextLoss())}catch(t){console.warn("[BimEngine] Error disposing renderer:",t)}try{this.stats?.dom?.parentElement&&this.stats.dom.parentElement.removeChild(this.stats.dom),this.catchSvg?.parentElement&&this.catchSvg.parentElement.removeChild(this.catchSvg),this.versionEl?.parentElement&&this.versionEl.parentElement.removeChild(this.versionEl)}catch(t){console.warn("[BimEngine] Error disposing DOM elements:",t)}try{this.events&&this.events.listeners&&this.events.listeners.clear()}catch(t){console.warn("[BimEngine] Error clearing event listeners:",t)}const e=this;e.scene=null,e.camera=null,e.renderer=null,e.controls=null,e.models=[],e.container=null,e.catchSvg=null,e.stats=null,e.versionEl=null,e.worldToScreen=null,e.measure=null,e.clipping=null,e.interactionModule=null,e.controlModule=null,e.sceneModule=null,e.cameraModule=null,e.deviceModule=null,e.renderModule=null,e.composerModule=null,e.loaderModule=null,e.lightModule=null,e.engineStatus=null,e.hoverHighLight=null,e.pathRoaming=null,e.hdr=null,e.skyManager=null,e.viewCube=null,e.grid=null,e.level=null,e.ground=null,e.minMap=null,e.fabricDraw=null,e.linkElement2d3d=null,e.linkView2d3d=null,e.rangeScale=null,e.text=null,e.issueReport=null,e.modelEdge=null,e.modelTree=null,e.modelProperties=null,e.modelMapperBatch=null,e.engineInfo=null,e.ai=null,e.oneClickEncoding=null,e.drawingPin=null,e.events=null,console.log("[BimEngine] Engine disposal completed")}clearScene(e){if(!e)return;[...e.children].forEach(n=>{this.clearScene(n)}),e.parent&&e.parent.remove(e),e instanceof b.Mesh&&!(e instanceof b.InstancedMesh)&&(e.geometry&&e.geometry.dispose(),e.material&&(Array.isArray(e.material)?e.material.forEach(n=>this.disposeMaterial(n)):this.disposeMaterial(e.material))),e instanceof b.Line&&(e.geometry&&e.geometry.dispose(),e.material&&this.disposeMaterial(e.material)),e instanceof b.Points&&(e.geometry&&e.geometry.dispose(),e.material&&this.disposeMaterial(e.material)),e instanceof b.InstancedMesh&&(e.geometry&&e.geometry.dispose(),e.material&&(Array.isArray(e.material)?e.material.forEach(n=>this.disposeMaterial(n)):this.disposeMaterial(e.material)),e.instanceMatrix&&(e.instanceMatrix=null),e.instanceColor&&(e.instanceColor=null)),e instanceof b.Sprite&&e.material&&this.disposeMaterial(e.material),e instanceof b.Light&&e.shadow?.dispose?.()}invokeIfExists(e,t,...n){const i=e?.[t];typeof i=="function"&&i.apply(e,n)}disposeSceneAttachments(e){new Set([e.background,e.environment,e.overrideMaterial]).forEach(n=>{this.disposeSceneAttachment(n)}),e.background=null,e.environment=null,e.overrideMaterial=null,e.dirLight=null,e.camera=null}disposeSceneAttachment(e){e&&(e instanceof b.Material||e instanceof b.Texture)&&e.dispose?.()}disposeMaterial(e){if(!e)return;["map","lightMap","bumpMap","normalMap","specularMap","envMap","alphaMap","aoMap","displacementMap","emissiveMap","gradientMap","metalnessMap","roughnessMap","clearcoatMap","clearcoatNormalMap","clearcoatRoughnessMap","transmissionMap","thicknessMap","sheenColorMap","sheenRoughnessMap","specularIntensityMap","specularColorMap","iridescenceMap","iridescenceThicknessMap"].forEach(n=>{const i=e[n];i&&i instanceof b.Texture&&i.dispose()}),e.dispose()}}const sk=`
6063
+ `}applyTo2d({imageData:{data:s}}){let e=-this.vibrance;for(let t=0;t<s.length;t+=4){let n=s[t],i=s[t+1],r=s[t+2],o=Math.max(n,i,r),a=(n+i+r)/3,l=2*Math.abs(o-a)/255*e;s[t]+=o===n?0:(o-n)*l,s[t+1]+=o===i?0:(o-i)*l,s[t+2]+=o===r?0:(o-r)*l}}sendUniformData(s,e){s.uniform1f(e.uVibrance,-this.vibrance)}isNeutralState(){return this.vibrance===0}};K(ml,"type","Vibrance"),K(ml,"defaults",{vibrance:0}),K(ml,"uniformLocations",["uVibrance"]),ke.setClass(ml),Ua({BaseFilter:()=>zt,BlackWhite:()=>OR,BlendColor:()=>nl,BlendImage:()=>il,Blur:()=>sl,Brightness:()=>rl,Brownie:()=>DR,ColorMatrix:()=>Ur,Composed:()=>ag,Contrast:()=>ol,Convolute:()=>al,Gamma:()=>ll,Grayscale:()=>cl,HueRotation:()=>qh,Invert:()=>hl,Kodachrome:()=>LR,Noise:()=>ul,Pixelate:()=>dl,Polaroid:()=>kR,RemoveColor:()=>fl,Resize:()=>pl,Saturation:()=>gl,Sepia:()=>FR,Technicolor:()=>RR,Vibrance:()=>ml,Vintage:()=>PR});function GR(s,e,t="bim-snapshot.png"){const n=s?.renderer,i=n?.domElement;if(!n||!i||!e)return null;const r=i.width||i.clientWidth,o=i.height||i.clientHeight;if(r<=0||o<=0)return null;let a=VR(i,r,o);if(!QR(a)){const d=jR(s,r,o);d&&(a=d)}const l=document.createElement("canvas");l.width=r,l.height=o;const c=l.getContext("2d");if(!c)return null;c.drawImage(a,0,0,r,o),c.drawImage(e,0,0,r,o);const h=l.toDataURL("image/png"),u=document.createElement("a");return u.href=h,u.download=t.toLowerCase().endsWith(".png")?t:`${t}.png`,u.click(),h}function VR(s,e,t){const n=document.createElement("canvas");n.width=e,n.height=t;const i=n.getContext("2d");return i&&i.drawImage(s,0,0,e,t),n}function QR(s){const e=s.getContext("2d");if(!e||s.width<=0||s.height<=0)return!1;const t=Math.min(32,s.width),n=Math.min(32,s.height),i=Math.max(1,Math.floor(s.width/t)),r=Math.max(1,Math.floor(s.height/n));for(let o=0;o<s.height;o+=r)for(let a=0;a<s.width;a+=i){const l=e.getImageData(a,o,1,1).data;if(l[0]!==0||l[1]!==0||l[2]!==0||l[3]!==0)return!0}return!1}function jR(s,e,t){const n=s?.renderer,i=s?.scene,r=s?.camera;if(!n||!i||!r)return null;const o=new b.WebGLRenderTarget(e,t,{minFilter:b.LinearFilter,magFilter:b.LinearFilter,format:b.RGBAFormat,depthBuffer:!0,stencilBuffer:!0}),a=n.getRenderTarget(),l=n.autoClear,c=n.xr?.enabled??!1;try{n.xr&&(n.xr.enabled=!1),n.autoClear=!0,n.setRenderTarget(o),n.clear(!0,!0,!0),n.render(i,r);const h=new Uint8Array(e*t*4);return n.readRenderTargetPixels(o,0,0,e,t,h),WR(h,e,t)}catch{return null}finally{n.setRenderTarget(a),n.autoClear=l,n.xr&&(n.xr.enabled=c),o.dispose()}}function WR(s,e,t){const n=document.createElement("canvas");n.width=e,n.height=t;const i=n.getContext("2d");if(!i)return n;const r=i.createImageData(e,t),o=e*4;for(let a=0;a<t;a++){const l=(t-1-a)*o,c=a*o;for(let h=0;h<o;h++)r.data[c+h]=s[l+h]}return i.putImageData(r,0,0),n}const HR=["#ffffff","#000000","#ff4d4f","#fa8c16","#fadb14","#52c41a","#13c2c2","#1677ff","#722ed1","#eb2f96"],qR={none:new URL("/assets/icon/%E9%80%89%E6%8B%A9.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,line:new URL("/assets/icon/%E7%BA%BF.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,arrow:new URL("/assets/icon/%E7%AE%AD%E5%A4%B4.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,rect:new URL("/assets/icon/%E7%9F%A9%E5%BD%A2.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,circle:new URL("/assets/icon/%E5%9C%86%E5%BD%A2.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,text:new URL("/assets/icon/%E6%96%87%E5%AD%97.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,cloudline:new URL("/assets/icon/%E4%BA%91%E7%BA%BF.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href},XR=new URL("/assets/icon/%E6%B5%8B%E8%B7%9D.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,YR=new URL("/assets/icon/%E6%88%AA%E5%9B%BE.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,KR=new URL("/assets/icon/%E7%BA%BF%E5%AE%BD.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,$R=new URL("/assets/icon/%E5%AD%97%E5%8F%B7.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,JR=[{type:"distance",label:"距离"},{type:"clearDistance",label:"净距"},{type:"clearHeight",label:"净高"},{type:"elevation",label:"标高"},{type:"point",label:"坐标"},{type:"angle",label:"角度"},{type:"area",label:"面积"},{type:"slope",label:"坡度"}],ZR={distance:new URL("/assets/icon/%E8%B7%9D%E7%A6%BB.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,clearDistance:new URL("/assets/icon/%E5%87%80%E8%B7%9D.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,clearHeight:new URL("/assets/icon/%E5%87%80%E9%AB%98.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,elevation:new URL("/assets/icon/%E6%A0%87%E9%AB%98.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,point:new URL("/assets/icon/%E5%9D%90%E6%A0%87.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,angle:new URL("/assets/icon/%E8%A7%92%E5%BA%A6.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,area:new URL("/assets/icon/%E9%9D%A2%E7%A7%AF.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href,slope:new URL("/assets/icon/%E5%9D%A1%E5%BA%A6.svg",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:ze&&ze.tagName.toUpperCase()==="SCRIPT"&&ze.src||new URL("bim-engine-sdk.umd.js",document.baseURI).href).href};class ek{constructor(e,t){this.handlers=e,this.root=document.createElement("div"),this.root.style.position="absolute",this.root.style.top="8px",this.root.style.left="50%",this.root.style.transform="translateX(-50%)",this.root.style.display="none",this.root.style.padding="6px",this.root.style.background="#ffffff",this.root.style.border="1px solid #d9d9d9",this.root.style.borderRadius="8px",this.root.style.pointerEvents="auto",this.root.style.userSelect="none",this.root.style.boxShadow="0 4px 14px rgba(0, 0, 0, 0.12)",this.root.style.zIndex="1300",this.root.style.overflow="visible",this.editPanel=document.createElement("div"),this.editPanel.style.display="flex",this.editPanel.style.flexDirection="column",this.editPanel.style.gap="6px",this.viewPanel=document.createElement("div"),this.viewPanel.style.display="none",this.viewPanel.style.alignItems="center",this.viewPanel.style.gap="6px";const n=document.createElement("div");n.style.display="flex",n.style.alignItems="center",n.style.gap="6px",n.style.flexWrap="wrap",[{type:"none",label:"选择"},{type:"line",label:"线"},{type:"arrow",label:"箭头"},{type:"rect",label:"矩形"},{type:"circle",label:"圆形"},{type:"text",label:"文字"},{type:"cloudline",label:"云线"}].forEach(f=>{const m=this.createIconButton(f.label,qR[f.type]);m.onclick=()=>this.handlers.onDrawTypeChange(f.type),this.drawButtons[f.type]=m,n.appendChild(m)});const r=document.createElement("div");r.style.position="relative",r.style.display="flex",r.style.alignItems="center",this.colorTrigger=document.createElement("button"),this.colorTrigger.type="button",this.colorTrigger.title="颜色",this.colorTrigger.style.width="32px",this.colorTrigger.style.height="24px",this.colorTrigger.style.padding="2px",this.colorTrigger.style.border="1px solid #d9d9d9",this.colorTrigger.style.borderRadius="4px",this.colorTrigger.style.background="#ffffff",this.colorTrigger.style.cursor="pointer",this.colorTrigger.style.display="flex",this.colorTrigger.style.alignItems="center",this.colorTrigger.style.justifyContent="center",this.colorTrigger.onclick=()=>this.setColorPresetVisible(!this.isColorPresetOpen);const o=document.createElement("span");o.style.display="block",o.style.width="100%",o.style.height="100%",o.style.borderRadius="2px",o.style.border="1px solid rgba(0, 0, 0, 0.12)",this.colorTrigger.appendChild(o),r.appendChild(this.colorTrigger),this.colorInput=document.createElement("input"),this.colorInput.type="color",this.colorInput.value=t.stroke,this.colorInput.style.position="absolute",this.colorInput.style.width="1px",this.colorInput.style.height="1px",this.colorInput.style.opacity="0",this.colorInput.style.pointerEvents="none",this.colorInput.style.left="0",this.colorInput.style.top="0",this.colorInput.tabIndex=-1,this.colorInput.oninput=()=>{this.updateColorControl(this.colorInput.value),this.handlers.onColorChange(this.colorInput.value),this.setColorPresetVisible(!1)},r.appendChild(this.colorInput),this.colorPresetPanel=document.createElement("div"),this.colorPresetPanel.style.position="absolute",this.colorPresetPanel.style.top="30px",this.colorPresetPanel.style.left="0",this.colorPresetPanel.style.display="none",this.colorPresetPanel.style.padding="8px",this.colorPresetPanel.style.background="#ffffff",this.colorPresetPanel.style.border="1px solid #d9d9d9",this.colorPresetPanel.style.borderRadius="6px",this.colorPresetPanel.style.boxShadow="0 6px 18px rgba(0, 0, 0, 0.14)",this.colorPresetPanel.style.zIndex="20",this.colorPresetPanel.style.width="152px";const a=document.createElement("div");a.style.display="grid",a.style.gridTemplateColumns="repeat(5, 1fr)",a.style.gap="6px",HR.forEach(f=>{const m=document.createElement("button");m.type="button",m.title=f,m.style.width="22px",m.style.height="22px",m.style.padding="0",m.style.border="1px solid #d9d9d9",m.style.borderRadius="4px",m.style.background=f,m.style.cursor="pointer",m.onclick=()=>{this.updateColorControl(f),this.handlers.onColorChange(f),this.setColorPresetVisible(!1)},a.appendChild(m)}),this.colorPresetPanel.appendChild(a);const l=document.createElement("button");l.type="button",l.textContent="自定义",l.style.marginTop="8px",l.style.width="100%",l.style.height="26px",l.style.border="1px solid #d9d9d9",l.style.borderRadius="4px",l.style.background="#ffffff",l.style.color="#333333",l.style.cursor="pointer",l.onclick=()=>this.openNativeColorPicker(),this.colorPresetPanel.appendChild(l),r.appendChild(this.colorPresetPanel),this.updateColorControl(t.stroke),n.appendChild(this.createField("",r)),this.strokeWidthInput=document.createElement("input"),this.strokeWidthInput.type="number",this.strokeWidthInput.min="1",this.strokeWidthInput.max="20",this.strokeWidthInput.step="1",this.strokeWidthInput.value=String(t.strokeWidth),this.strokeWidthInput.style.width="46px",this.strokeWidthInput.oninput=()=>this.handlers.onStrokeWidthChange(this.strokeWidthInput.value),n.appendChild(this.createField("",this.strokeWidthInput,KR,"线宽")),this.fontSizeInput=document.createElement("input"),this.fontSizeInput.type="number",this.fontSizeInput.min="10",this.fontSizeInput.max="96",this.fontSizeInput.step="1",this.fontSizeInput.value=String(t.fontSize),this.fontSizeInput.style.width="46px",this.fontSizeInput.oninput=()=>this.handlers.onFontSizeChange(this.fontSizeInput.value),n.appendChild(this.createField("",this.fontSizeInput,$R,"字号")),this.distanceButton=this.createIconButton("测量",XR),this.distanceButton.onclick=()=>this.handlers.onMeasureToggle(),n.appendChild(this.distanceButton);const c=this.createIconButton("截图",YR);c.onclick=()=>this.handlers.onScreenshot(),n.appendChild(c);const h=this.createTextButton("×","取消");h.onclick=()=>this.handlers.onCancel(),h.style.background="#ff4d4f",h.style.borderColor="#ff4d4f",h.style.color="#ffffff",n.appendChild(h);const u=this.createTextButton("✔","确定");u.onclick=()=>this.handlers.onConfirm(),u.style.background="#52c41a",u.style.borderColor="#52c41a",u.style.color="#ffffff",n.appendChild(u),this.measureSubPanel=document.createElement("div"),this.measureSubPanel.style.display="none",this.measureSubPanel.style.alignItems="center",this.measureSubPanel.style.gap="6px",this.measureSubPanel.style.flexWrap="wrap",this.measureSubPanel.style.paddingTop="2px",JR.forEach(f=>{const m=this.createSmallIconButton(f.label,ZR[f.type]);m.onclick=()=>this.handlers.onMeasureTypeChange(f.type),this.measureTypeButtons[f.type]=m,this.measureSubPanel.appendChild(m)}),this.editPanel.appendChild(n),this.editPanel.appendChild(this.measureSubPanel);const d=this.createTextButton("关闭","关闭");d.onclick=()=>this.handlers.onClose(),this.viewPanel.appendChild(d),this.root.appendChild(this.editPanel),this.root.appendChild(this.viewPanel),this.disabledMask=document.createElement("div"),this.disabledMask.style.position="absolute",this.disabledMask.style.inset="0",this.disabledMask.style.display="none",this.disabledMask.style.background="rgba(255, 255, 255, 0.55)",this.disabledMask.style.backdropFilter="blur(1px)",this.disabledMask.style.cursor="not-allowed",this.disabledMask.style.pointerEvents="auto",this.disabledMask.style.zIndex="10",this.root.appendChild(this.disabledMask),document.addEventListener("pointerdown",this.onDocumentPointerDown),this.setMode("edit")}root;disabledMask;drawButtons={};measureTypeButtons={};distanceButton;colorTrigger;colorInput;colorPresetPanel;strokeWidthInput;fontSizeInput;editPanel;viewPanel;measureSubPanel;mode="edit";isEditPanelMasked=!1;isColorPresetOpen=!1;onDocumentPointerDown=e=>{const t=e.target;t&&this.root.contains(t)||this.setColorPresetVisible(!1)};mount(e){e.appendChild(this.root)}show(){this.root.style.display="block"}hide(){this.root.style.display="none"}setMode(e){this.mode=e,this.editPanel.style.display=e==="edit"?"flex":"none",this.viewPanel.style.display=e==="view"?"flex":"none",e==="view"&&(this.setMeasurePanelVisible(!1),this.setColorPresetVisible(!1)),this.applyEditPanelMaskState()}setEditPanelMasked(e){this.isEditPanelMasked=e,this.applyEditPanelMaskState()}setDrawType(e){for(const t in this.drawButtons){const n=this.drawButtons[t];if(!n)continue;const i=t===e;n.style.background=i?"#eaf2ff":"#ffffff",n.style.borderColor=i?"#2f80ed":"#d9d9d9"}}setMeasurePanelVisible(e){if(this.mode!=="edit"){this.measureSubPanel.style.display="none";return}this.measureSubPanel.style.display=e?"flex":"none"}setMeasureState(e,t){this.distanceButton.style.background=e?"#eaf2ff":"#ffffff",this.distanceButton.style.borderColor=e?"#2f80ed":"#d9d9d9";for(const n in this.measureTypeButtons){const i=this.measureTypeButtons[n];if(!i)continue;const r=e&&t===n;i.style.background=r?"#eaf2ff":"#ffffff",i.style.borderColor=r?"#2f80ed":"#d9d9d9"}}setStyleValues(e){e.stroke&&this.updateColorControl(e.stroke),typeof e.strokeWidth=="number"&&(this.strokeWidthInput.value=String(e.strokeWidth)),typeof e.fontSize=="number"&&(this.fontSizeInput.value=String(e.fontSize))}dispose(){this.colorInput.oninput=null,this.strokeWidthInput.oninput=null,this.fontSizeInput.oninput=null,document.removeEventListener("pointerdown",this.onDocumentPointerDown),this.root.remove()}applyEditPanelMaskState(){const e=this.mode==="edit"&&this.isEditPanelMasked;this.disabledMask.style.display=e?"block":"none",e&&this.setColorPresetVisible(!1),this.editPanel.querySelectorAll("button, input").forEach(n=>{const i=n;i.disabled=e})}createField(e,t,n,i=""){const r=document.createElement("div");if(r.style.display="flex",r.style.alignItems="center",r.style.gap="4px",r.style.padding="0 2px",r.style.color="#333333",r.style.fontSize="12px",e){const o=document.createElement("span");o.textContent=e,r.appendChild(o)}if(n){const o=document.createElement("img");o.src=n,o.alt=i,o.style.width="14px",o.style.height="14px",o.style.display="block",r.appendChild(o)}return t instanceof HTMLInputElement&&(t.style.height="24px",t.style.border="1px solid #d9d9d9",t.style.borderRadius="4px",t.style.background="#ffffff",t.style.color="#333333",t.style.outline="none",t.style.padding="0 4px"),r.appendChild(t),r}updateColorControl(e){this.colorInput.value=e;const t=this.colorTrigger.firstElementChild;t&&(t.style.background=e)}setColorPresetVisible(e){this.isColorPresetOpen=e,this.colorPresetPanel.style.display=e?"block":"none",this.colorTrigger.style.borderColor=e?"#2f80ed":"#d9d9d9"}openNativeColorPicker(){const e=this.colorInput;if(typeof e.showPicker=="function"){e.showPicker();return}e.click()}createIconButton(e,t){const n=document.createElement("button");n.type="button",n.style.width="28px",n.style.height="28px",n.style.padding="0",n.style.display="flex",n.style.alignItems="center",n.style.justifyContent="center",n.style.border="1px solid #d9d9d9",n.style.borderRadius="4px",n.style.background="#ffffff",n.style.cursor="pointer";const i=document.createElement("img");return i.src=t,i.alt=e,i.style.width="16px",i.style.height="16px",i.style.display="block",n.appendChild(i),n}createSmallIconButton(e,t){const n=document.createElement("button");n.type="button",n.style.width="26px",n.style.height="26px",n.style.padding="0",n.style.display="flex",n.style.alignItems="center",n.style.justifyContent="center",n.style.border="1px solid #d9d9d9",n.style.borderRadius="4px",n.style.background="#ffffff",n.style.cursor="pointer";const i=document.createElement("img");return i.src=t,i.alt=e,i.style.width="14px",i.style.height="14px",i.style.display="block",n.appendChild(i),n}createTextButton(e,t){const n=document.createElement("button");return n.type="button",n.title=t,n.textContent=e,n.style.width="28px",n.style.height="28px",n.style.padding="0 10px",n.style.border="1px solid #d9d9d9",n.style.borderRadius="4px",n.style.background="#ffffff",n.style.color="#333333",n.style.fontSize="13px",n.style.lineHeight="1",n.style.cursor="pointer",n}}class tk{engine;wrapper;canvasEl;canvas;toolbar;isActive=!1;isVisible=!0;isViewLocked=!0;isDistanceMeasureMode=!1;isMeasurePanelExpanded=!1;drawType="none";mode="edit";currentMeasureType=null;sessionSnapshot=null;actionHandlers={};drawStyle={stroke:"#ff4d4f",strokeWidth:2,fill:"rgba(255, 77, 79, 0.08)",fontSize:16,text:"T",cloudRadius:10};startPoint=null;tempObject=null;cloudPoints=[];onMouseDown=e=>this.handleMouseDown(e);onMouseMove=e=>this.handleMouseMove(e);onMouseUp=e=>this.handleMouseUp(e);onMouseDblClick=e=>this.handleMouseDblClick(e);onSelectionChanged=()=>this.syncStyleFromSelection();onKeyDown=e=>this.handleKeyDown(e);constructor(e){this.engine=e;const t=this.engine.container;if(!t)throw new Error("FabricDraw: engine container not found.");this.wrapper=document.createElement("div"),this.wrapper.className="fabric-draw-layer",this.wrapper.style.position="absolute",this.wrapper.style.left="0",this.wrapper.style.top="0",this.wrapper.style.right="0",this.wrapper.style.bottom="0",this.wrapper.style.pointerEvents="none",this.canvasEl=document.createElement("canvas"),this.canvasEl.style.width="100%",this.canvasEl.style.height="100%",this.wrapper.appendChild(this.canvasEl),this.toolbar=new ek({onDrawTypeChange:i=>this.setDrawType(i),onMeasureToggle:()=>this.toggleMeasurePanel(),onMeasureTypeChange:i=>this.activateDistanceMeasure(i),onScreenshot:()=>{this.saveScreenshot(this.createScreenshotFileName())},onColorChange:i=>this.handleColorInputChange(i),onStrokeWidthChange:i=>this.handleStrokeWidthInputChange(i),onFontSizeChange:i=>this.handleFontSizeInputChange(i),onCancel:()=>{this.handleCancelClick()},onConfirm:()=>this.handleConfirmClick(),onClose:()=>{this.handleCloseClick()}},{stroke:this.drawStyle.stroke,strokeWidth:this.drawStyle.strokeWidth,fontSize:this.drawStyle.fontSize}),this.toolbar.mount(this.wrapper);const n=this.engine.renderer?.domElement;n?.nextSibling?t.insertBefore(this.wrapper,n.nextSibling):t.appendChild(this.wrapper),this.canvas=new Zp(this.canvasEl,{selection:!0,preserveObjectStacking:!0}),this.resize(),this.canvas.on("mouse:down",this.onMouseDown),this.canvas.on("mouse:move",this.onMouseMove),this.canvas.on("mouse:up",this.onMouseUp),this.canvas.on("mouse:dblclick",this.onMouseDblClick),this.canvas.on("selection:created",this.onSelectionChanged),this.canvas.on("selection:updated",this.onSelectionChanged),this.canvas.on("selection:cleared",this.onSelectionChanged),window.addEventListener("keydown",this.onKeyDown),this.refreshToolbarState()}active(e="edit"){this.isActive=!0,this.mode=e,this.isViewLocked=!0,this.drawType="none",this.isMeasurePanelExpanded=!1,this.currentMeasureType=null,this.canvas.defaultCursor="default",this.sessionSnapshot=e==="edit"?this.cloneJson(this.getAllShapes()):null,this.toolbar.setMode(e),this.applyCanvasInteractive(e==="edit"),this.isVisible&&this.toolbar.show(),this.updateOverlayPointerEvents(),this.refreshToolbarState()}disActive(){this.isActive=!1,this.isViewLocked=!0,this.startPoint=null,this.cloudPoints=[],this.tempObject=null,this.drawType="none",this.mode="edit",this.isMeasurePanelExpanded=!1,this.currentMeasureType=null,this.sessionSnapshot=null,this.stopDistanceMeasureMode(),this.canvas.defaultCursor="default",this.canvas.discardActiveObject(),this.applyCanvasInteractive(!0),this.canvas.requestRenderAll(),this.toolbar.setMode("edit"),this.toolbar.hide(),this.updateOverlayPointerEvents(),this.refreshToolbarState()}close(){this.disActive()}hide(){this.isVisible=!1,this.wrapper.style.display="none",this.toolbar.hide()}show(){this.isVisible=!0,this.wrapper.style.display="block",this.isActive&&this.toolbar.show(),this.resize()}isShown(){return this.isVisible}setDrawType(e,t){this.mode!=="view"&&(this.stopDistanceMeasureMode(),this.isMeasurePanelExpanded=!1,this.currentMeasureType=null,this.drawType=e,t&&(this.drawStyle={...this.drawStyle,...t}),this.canvas.defaultCursor=e==="none"?"default":"crosshair",this.updateOverlayPointerEvents(),this.refreshToolbarState())}getDrawType(){return this.drawType}setActionHandlers(e){this.actionHandlers={...e}}drawLine(e,t,n){const i=this.mergeStyle(n),r=this.createLineObject(e,t,i,!0);return this.canvas.add(r),this.canvas.requestRenderAll(),r}drawArrow(e,t,n){const i=this.mergeStyle(n),r=this.createArrowObject(e,t,i,!0);return this.canvas.add(r),this.canvas.requestRenderAll(),r}drawRect(e,t,n){const i=this.mergeStyle(n),r=this.createRectObject(e,t,i,!0);return this.canvas.add(r),this.canvas.requestRenderAll(),r}drawCircle(e,t,n){const i=this.mergeStyle(n),r=this.createCircleObject(e,t,i,!0);return this.canvas.add(r),this.canvas.requestRenderAll(),r}drawText(e,t,n){const i=this.mergeStyle(n),r=new Fr(t??i.text,{left:e.x,top:e.y,...this.createTextStyle(i),selectable:!0,evented:!0,objectCaching:!1});return r.annotationType="text",this.canvas.add(r),this.canvas.requestRenderAll(),r}drawCloudLine(e,t){if(e.length<2)return null;const n=this.mergeStyle(t),i=this.createCloudObject(e,n,!0);return i?(this.canvas.add(i),this.canvas.requestRenderAll(),i):null}getAllShapes(){return this.canvas.toObject(["annotationType"])}clearAllShapes(){this.canvas.clear(),this.canvas.requestRenderAll()}async restoreAllShapes(e){await this.canvas.loadFromJSON(e),this.canvas.requestRenderAll()}saveScreenshot(e="bim-snapshot.png"){const t=this.canvas.lowerCanvasEl;return t?GR(this.engine,t,e):null}resize(e,t){const n=this.engine.container;if(!n)return;const i=e??n.clientWidth??1,r=t??n.clientHeight??1;this.canvas.setDimensions({width:i,height:r}),this.canvas.requestRenderAll()}dispose(){this.stopDistanceMeasureMode(),window.removeEventListener("keydown",this.onKeyDown),this.canvas.off("mouse:down",this.onMouseDown),this.canvas.off("mouse:move",this.onMouseMove),this.canvas.off("mouse:up",this.onMouseUp),this.canvas.off("mouse:dblclick",this.onMouseDblClick),this.canvas.off("selection:created",this.onSelectionChanged),this.canvas.off("selection:updated",this.onSelectionChanged),this.canvas.off("selection:cleared",this.onSelectionChanged),this.toolbar.dispose(),this.canvas.dispose(),this.wrapper.remove()}handleMouseDown(e){if(!this.isActive||this.mode==="view"||!this.isViewLocked||this.drawType==="none"||e?.target)return;const t=this.getPointFromEvent(e);if(this.drawType==="text"){const i=this.drawText(t);this.canvas.setActiveObject(i),this.canvas.requestRenderAll(),setTimeout(()=>{i.enterEditing(),i.hiddenTextarea?.focus(),i.selectAll()},0);return}this.startPoint=t,this.cloudPoints=[t],this.canvas.selection=!1,this.canvas.discardActiveObject();const n=this.createDraftObject(t,t);n&&(this.tempObject=n,this.canvas.add(n),this.canvas.requestRenderAll())}handleMouseMove(e){if(!this.isActive||this.mode==="view"||!this.isViewLocked||!this.startPoint||!this.tempObject)return;const t=this.getPointFromEvent(e),n=this.drawStyle;if(this.drawType==="cloudline"){if(this.shouldAppendCloudPoint(t)){this.cloudPoints.push(t),this.canvas.remove(this.tempObject);const i=this.createCloudObject(this.cloudPoints,n,!1);if(!i)return;this.tempObject=i,this.canvas.add(i),this.canvas.requestRenderAll()}return}if(this.drawType==="arrow"){this.canvas.remove(this.tempObject),this.tempObject=this.createArrowObject(this.startPoint,t,n,!1),this.canvas.add(this.tempObject),this.canvas.requestRenderAll();return}this.updateDraftObject(this.startPoint,t),this.canvas.requestRenderAll()}handleMouseUp(e){if(!this.isActive||this.mode==="view"||!this.isViewLocked||!this.startPoint)return;const t=this.getPointFromEvent(e);this.drawType==="cloudline"&&this.cloudPoints.length===1&&(this.cloudPoints.push(t),this.canvas.remove(this.tempObject),this.tempObject=this.createCloudObject(this.cloudPoints,this.drawStyle,!0),this.tempObject&&this.canvas.add(this.tempObject)),this.tempObject&&(this.tempObject.set({selectable:!0,evented:!0}),this.tempObject.setCoords?.(),this.canvas.requestRenderAll()),this.startPoint=null,this.tempObject=null,this.cloudPoints=[],this.canvas.selection=!0}handleMouseDblClick(e){const t=e?.target;this.isTextObject(t)&&(t.enterEditing(),t.hiddenTextarea?.focus(),t.selectAll?.())}handleKeyDown(e){if(!this.isActive)return;const t=this.canvas.getActiveObject();if(this.isTextObject(t)&&t?.isEditing||this.isInputElement(e.target))return;if(e.key==="Control"&&!e.repeat){this.toggleViewLock();return}if(e.key==="Escape"){e.preventDefault(),this.mode==="view"?this.handleCloseClick():this.handleCancelClick();return}if(e.key==="Enter"){this.mode==="edit"&&(e.preventDefault(),this.handleConfirmClick());return}if(e.key!=="Delete"&&e.key!=="Backspace"||!t)return;e.preventDefault(),this.canvas.getActiveObjects().forEach(r=>this.canvas.remove(r)),this.canvas.discardActiveObject(),this.canvas.requestRenderAll()}getPointFromEvent(e){if(e?.e){const n=this.canvas.getScenePoint(e.e);return{x:n.x,y:n.y}}const t=e?.scenePoint??e?.pointer??e?.absolutePointer;return t?{x:t.x,y:t.y}:{x:0,y:0}}shouldAppendCloudPoint(e){if(this.cloudPoints.length===0)return!0;const t=this.cloudPoints[this.cloudPoints.length-1],n=e.x-t.x,i=e.y-t.y;return Math.sqrt(n*n+i*i)>=6}createDraftObject(e,t){const n=this.drawStyle;switch(this.drawType){case"line":return this.createLineObject(e,t,n,!1);case"arrow":return this.createArrowObject(e,t,n,!1);case"rect":return this.createRectObject(e,t,n,!1);case"circle":return this.createCircleObject(e,t,n,!1);case"cloudline":return this.createCloudObject([e,t],n,!1);default:return null}}updateDraftObject(e,t){if(this.tempObject){if(this.drawType==="line"){this.tempObject.set({x2:t.x,y2:t.y});return}if(this.drawType==="rect"){const n=this.getBoxFromPoints(e,t);this.tempObject.set({left:n.left,top:n.top,width:n.width,height:n.height});return}if(this.drawType==="circle"){const n=this.getCircleFromPoints(e,t);this.tempObject.set({left:n.left,top:n.top,radius:n.radius})}}}mergeStyle(e){return{...this.drawStyle,...e??{}}}createObjectBase(e,t){return{stroke:e.stroke,strokeWidth:e.strokeWidth,fill:e.fill,selectable:t,evented:t,objectCaching:!1}}createLineObject(e,t,n,i){const r=new Hs([e.x,e.y,t.x,t.y],{...this.createObjectBase(n,i),fill:"",strokeLineCap:"round"});return r.annotationType="line",r}createRectObject(e,t,n,i){const r=this.getBoxFromPoints(e,t),o=new Qs({...this.createObjectBase(n,i),left:r.left,top:r.top,width:r.width,height:r.height,originX:"left",originY:"top"});return o.annotationType="rect",o}createCircleObject(e,t,n,i){const r=this.getCircleFromPoints(e,t),o=new kr({...this.createObjectBase(n,i),left:r.left,top:r.top,radius:r.radius,originX:"left",originY:"top"});return o.annotationType="circle",o}createArrowObject(e,t,n,i){const r=t.x-e.x,o=t.y-e.y,a=Math.sqrt(r*r+o*o);if(a<1e-6){const B=new Hs([e.x,e.y,t.x,t.y],{stroke:n.stroke,strokeWidth:n.strokeWidth,fill:"",selectable:i,evented:i}),M=new js([B],{selectable:i,evented:i,objectCaching:!1});return M.annotationType="arrow",M}const l=r/a,c=o/a,h=-c,u=l,d=Math.max(10,n.strokeWidth*6),f=d*.72,m=t.x-l*d,g=t.y-c*d,A=m+h*(f*.5),p=g+u*(f*.5),x=m-h*(f*.5),y=g-u*(f*.5),v=new Hs([e.x,e.y,t.x,t.y],{stroke:n.stroke,strokeWidth:n.strokeWidth,fill:"",strokeLineCap:"round",selectable:!1,evented:!1}),_=`M ${t.x} ${t.y} L ${A} ${p} L ${x} ${y} Z`,E=new Rr(_,{fill:n.stroke,stroke:n.stroke,strokeWidth:1,selectable:!1,evented:!1,objectCaching:!1}),I=new js([v,E],{selectable:i,evented:i,objectCaching:!1});return I.annotationType="arrow",I}createCloudObject(e,t,n){const i=this.buildCloudPath(e,t.cloudRadius);if(!i)return null;const r=new Rr(i,{stroke:t.stroke,strokeWidth:t.strokeWidth,fill:"",strokeLineCap:"round",strokeLineJoin:"round",selectable:n,evented:n});return r.annotationType="cloudline",r}getBoxFromPoints(e,t){return{left:Math.min(e.x,t.x),top:Math.min(e.y,t.y),width:Math.abs(t.x-e.x),height:Math.abs(t.y-e.y)}}getCircleFromPoints(e,t){const n=t.x-e.x,i=t.y-e.y,r=Math.max(Math.abs(n),Math.abs(i)),o=n>=0?e.x:e.x-r,a=i>=0?e.y:e.y-r;return{left:o,top:a,radius:Math.max(r/2,1)}}buildCloudPath(e,t){if(e.length<2)return"";const n=Math.max(2,t),i=n*1.4;let r=`M ${e[0].x} ${e[0].y}`,o=1;for(let a=1;a<e.length;a++){const l=e[a-1],c=e[a],h=c.x-l.x,u=c.y-l.y,d=Math.sqrt(h*h+u*u);if(d<.1)continue;const f=-u/d,m=h/d,g=Math.max(1,Math.round(d/i));for(let A=1;A<=g;A++){const p=A/g,x=l.x+h*p,y=l.y+u*p,v=o%2===0?-1:1,_=x+f*n*v,E=y+m*n*v;r+=` Q ${_} ${E} ${x} ${y}`,o++}}return r}handleColorInputChange(e){this.drawStyle.stroke=e||this.drawStyle.stroke,this.drawStyle.fill=this.colorToAlpha(this.drawStyle.stroke,.08),this.applyCurrentStyleToSelection(),this.refreshToolbarStyleValues()}handleStrokeWidthInputChange(e){const t=this.parseNumber(e,this.drawStyle.strokeWidth,1,20);this.drawStyle.strokeWidth=t,this.applyCurrentStyleToSelection(),this.refreshToolbarStyleValues()}handleFontSizeInputChange(e){const t=this.parseNumber(e,this.drawStyle.fontSize,1,200);this.drawStyle.fontSize=t,this.applyCurrentStyleToSelection(),this.refreshToolbarStyleValues()}applyCurrentStyleToSelection(){const e=this.canvas.getActiveObjects();e.length!==0&&(e.forEach(t=>this.applyStyleToObject(t)),this.canvas.requestRenderAll())}applyStyleToObject(e){if(!e)return;if(e.annotationType==="arrow"&&Array.isArray(e._objects)){e._objects.forEach(n=>{if(n?.type==="triangle"||n?.type==="path"){n.set({fill:this.drawStyle.stroke,stroke:this.drawStyle.stroke,strokeWidth:1});return}n?.set({stroke:this.drawStyle.stroke,strokeWidth:this.drawStyle.strokeWidth,strokeLineCap:"round"})}),e.set({dirty:!0}),e.setCoords?.();return}if(this.isTextObject(e)){e.set({...this.createTextStyle(this.drawStyle),fontSize:this.drawStyle.fontSize}),e.setCoords?.();return}const t={stroke:this.drawStyle.stroke,strokeWidth:this.drawStyle.strokeWidth};e?.type==="line"||e?.type==="path"?t.fill="":t.fill=this.drawStyle.fill,e.set(t),e.setCoords?.()}syncStyleFromSelection(){const e=this.canvas.getActiveObject();if(!e)return;const t=this.readStyleFromObject(e);t.stroke&&(this.drawStyle.stroke=t.stroke,this.drawStyle.fill=this.colorToAlpha(t.stroke,.08)),typeof t.strokeWidth=="number"&&(this.drawStyle.strokeWidth=t.strokeWidth),typeof t.fontSize=="number"&&(this.drawStyle.fontSize=t.fontSize),this.refreshToolbarStyleValues()}readStyleFromObject(e){if(!e)return{};if(e.annotationType==="arrow"&&Array.isArray(e._objects)){const t=e._objects.find(n=>n?.type==="line")??e._objects[0];return{stroke:t?.stroke,strokeWidth:t?.strokeWidth}}return this.isTextObject(e)?{stroke:e.fill??this.drawStyle.stroke,fontSize:e.fontSize??this.drawStyle.fontSize}:{stroke:e.stroke??this.drawStyle.stroke,strokeWidth:e.strokeWidth??this.drawStyle.strokeWidth}}isTextObject(e){return e?e.type==="i-text"||e.type==="textbox"||e.annotationType==="text":!1}createTextStyle(e){return{fontSize:e.fontSize,fill:e.stroke,stroke:this.getTextOutlineColor(e.stroke),strokeWidth:3,strokeLineJoin:"round",paintFirst:"stroke"}}getTextOutlineColor(e){return this.isWhiteTextColor(e)?"#000000":"#ffffff"}isWhiteTextColor(e){const t=e.trim().toLowerCase();if(t==="#fff"||t==="#ffffff"||t==="white")return!0;const n=t.match(/^rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})/);if(n){const[,i,r,o]=n;return Number(i)>=245&&Number(r)>=245&&Number(o)>=245}return!1}isInputElement(e){const t=e;if(!t||!t.tagName)return!1;const n=t.tagName.toLowerCase();return n==="input"||n==="textarea"||!!t.isContentEditable}applyCanvasInteractive(e){this.canvas.selection=e,this.canvas.getObjects().forEach(t=>{t.set({selectable:e,evented:e}),t.setCoords?.()}),this.canvas.discardActiveObject(),this.canvas.requestRenderAll()}parseNumber(e,t,n,i){const r=Number(e);return Number.isFinite(r)?Math.min(i,Math.max(n,r)):t}colorToAlpha(e,t){const n=e.trim(),i=/^#([0-9a-fA-F]{3})$/.exec(n);if(i){const o=i[1],a=parseInt(o[0]+o[0],16),l=parseInt(o[1]+o[1],16),c=parseInt(o[2]+o[2],16);return`rgba(${a}, ${l}, ${c}, ${t})`}const r=/^#([0-9a-fA-F]{6})$/.exec(n);if(r){const o=r[1],a=parseInt(o.slice(0,2),16),l=parseInt(o.slice(2,4),16),c=parseInt(o.slice(4,6),16);return`rgba(${a}, ${l}, ${c}, ${t})`}return this.drawStyle.fill}toggleMeasurePanel(){!this.isActive||this.mode!=="edit"||(this.isMeasurePanelExpanded=!this.isMeasurePanelExpanded,this.refreshToolbarState())}activateDistanceMeasure(e){if(!this.isActive||this.mode!=="edit")return;this.drawType="none",this.canvas.defaultCursor="default",this.isDistanceMeasureMode=!0,this.isMeasurePanelExpanded=!0,this.currentMeasureType=e,this.canvas.discardActiveObject(),this.canvas.requestRenderAll();const t=this.engine.measure;t?.active?.(),this.disActiveMeasureTools(t),this.activeMeasureTool(t,e),this.updateOverlayPointerEvents(),this.refreshToolbarState()}stopDistanceMeasureMode(){if(!this.isDistanceMeasureMode)return;const e=this.engine.measure;this.disActiveMeasureTools(e),this.isDistanceMeasureMode=!1,this.currentMeasureType=null,this.updateOverlayPointerEvents(),this.refreshToolbarState()}disActiveMeasureTools(e){e?.distanceMeasure?.disActive?.(),e?.faceDistanceMeasure?.disActive?.(),e?.clearHeightMeasure?.disActive?.(),e?.elevationMeasure?.disActive?.(),e?.pointMeasure?.disActive?.(),e?.angleMeasure?.disActive?.(),e?.areaMeasure?.disActive?.(),e?.slopeMeasure?.disActive?.()}activeMeasureTool(e,t){const i={distance:"distanceMeasure",clearDistance:"faceDistanceMeasure",clearHeight:"clearHeightMeasure",elevation:"elevationMeasure",point:"pointMeasure",angle:"angleMeasure",area:"areaMeasure",slope:"slopeMeasure"}[t];i&&e?.[i]?.active?.()}updateOverlayPointerEvents(){if(!this.isActive){this.wrapper.style.pointerEvents="none",this.canvasEl.style.pointerEvents="none";return}if(this.mode==="view"||this.isDistanceMeasureMode||!this.isViewLocked){this.wrapper.style.pointerEvents="none",this.canvasEl.style.pointerEvents="none",this.toolbar.root.style.pointerEvents="auto";return}this.wrapper.style.pointerEvents="auto",this.canvasEl.style.pointerEvents="auto",this.toolbar.root.style.pointerEvents="auto"}toggleViewLock(){!this.isActive||this.mode!=="edit"||this.isDistanceMeasureMode||(this.isViewLocked=!this.isViewLocked,this.isViewLocked?this.canvas.selection=!0:(this.startPoint=null,this.tempObject=null,this.cloudPoints=[],this.canvas.discardActiveObject(),this.canvas.selection=!1),this.canvas.requestRenderAll(),this.updateOverlayPointerEvents(),this.refreshToolbarState())}async handleCancelClick(){this.sessionSnapshot&&await this.restoreAllShapes(this.cloneJson(this.sessionSnapshot)),this.actionHandlers.onCancel?.(),this.disActive()}async handleCloseClick(){this.disActive()}handleConfirmClick(){const e=this.cloneJson(this.getAllShapes());this.actionHandlers.onConfirm?.(e),this.disActive()}refreshToolbarStyleValues(){this.toolbar.setStyleValues({stroke:this.drawStyle.stroke,strokeWidth:this.drawStyle.strokeWidth,fontSize:this.drawStyle.fontSize})}refreshToolbarState(){this.toolbar.setDrawType(this.drawType),this.toolbar.setMode(this.mode),this.toolbar.setMeasurePanelVisible(this.isMeasurePanelExpanded),this.toolbar.setMeasureState(this.isDistanceMeasureMode,this.currentMeasureType),this.toolbar.setEditPanelMasked(!this.isViewLocked),this.refreshToolbarStyleValues()}createScreenshotFileName(){const e=new Date,t=e.getFullYear(),n=String(e.getMonth()+1).padStart(2,"0"),i=String(e.getDate()).padStart(2,"0"),r=String(e.getHours()).padStart(2,"0"),o=String(e.getMinutes()).padStart(2,"0"),a=String(e.getSeconds()).padStart(2,"0");return`bim-snapshot-${t}${n}${i}-${r}${o}${a}.png`}cloneJson(e){return JSON.parse(JSON.stringify(e))}}class nk{engine;constructor(e){this.engine=e}get(){return{cameraPose:this.engine.cameraModule?.getCameraPose?.()??null,clipping:this.captureClippingState(),measureData:this.captureMeasureData(),annotationData:this.captureAnnotationData()}}async restore(e,t="view",n){if(!e){n?.(null);return}e.cameraPose&&this.engine.cameraModule?.restoreCameraPose?.(e.cameraPose),this.restoreClippingState(e.clipping),this.restoreMeasureData(e.measureData),await this.restoreAnnotationData(e.annotationData),this.applyAnnotationMode(t);const i=this.engine.fabricDraw;i&&i.setActionHandlers({onConfirm:r=>{const o=this.get();o.annotationData=this.serializeSnapshotValue(r),n&&n(o),this.clearAnnotation()},onCancel:()=>{this.clearAnnotation()}})}create(e){const t=this.engine.fabricDraw;if(!t){e?.(this.get());return}t.setActionHandlers({onConfirm:n=>{const i=this.get();i.annotationData=this.serializeSnapshotValue(n),e?.(i),this.clearAnnotation()},onCancel:()=>{this.clearAnnotation()}}),t.show?.(),t.active?.("edit"),t.setDrawType?.("none")}clearAnnotation(){this.engine.fabricDraw?.clearAllShapes?.(),this.engine.measure.disActive?.()}captureClippingState(){const e=this.engine.clipping,t=e?.sectionFace,n=e?.currentClippingMode??"",i={mode:n,fillCutFace:e?.getFillCutFace?.()??!0};if(n==="box"&&e?.sectionBox?.getboxXyz&&(i.box=e.sectionBox.getboxXyz()),n==="x"||n==="y"||n==="z"||n==="face"){const r=t?.normal;r&&(i.face={normal:{x:Number(r.x)||0,y:Number(r.y)||0,z:Number(r.z)||1},distance:Number(t?.distance)||0,direction:Number(t?.direction)===-1?-1:1})}return i}restoreClippingState(e){const t=this.engine.clipping;if(!t)return;typeof e?.fillCutFace=="boolean"&&t.setFillCutFace?.(e.fillCutFace);const n=e?.mode??"";if(!n){t.disActive?.();return}if(n==="box"){t.active?.("box"),e.box&&t.sectionBox?.setboxXyz?.(e.box);return}if(n==="x"||n==="y"||n==="z"){t.active?.(n),this.applyFaceState(e.face);return}if(n==="face"){this.restoreFaceMode(e.face);return}t.active?.(n)}restoreFaceMode(e){const t=this.engine.clipping,n=t?.sectionFace;!t||!n||(t.sectionBox?.disActive?.(),n.disActive?.(),n.active?.(),t.currentClippingMode="face",this.applyFaceState(e))}applyFaceState(e){if(!e)return;const t=this.engine.clipping?.sectionFace;if(!t)return;const n=new b.Vector3(e.normal.x,e.normal.y,e.normal.z).normalize();t.direction=e.direction===-1?-1:1,t.setFaceNormal?.(n,e.distance??0)}captureMeasureData(){const e=this.engine.measure?.annotationData;return e?this.serializeSnapshotValue(e):null}restoreMeasureData(e){const t=this.engine.measure;if(!t)return;try{t.clearAll?.()}catch{}if(!e)return;const n=this.deserializeSnapshotValue(e);(!t.annotationData||typeof t.annotationData!="object")&&(t.annotationData={}),Object.keys(t.annotationData).forEach(i=>{t.annotationData[i]=[]}),Object.keys(n).forEach(i=>{t.annotationData[i]=Array.isArray(n[i])?n[i]:[]}),t.tools?.drawNormalAnnotation?.()}captureAnnotationData(){const e=this.engine.fabricDraw;return e?.getAllShapes?this.serializeSnapshotValue(e.getAllShapes()):null}async restoreAnnotationData(e){const t=this.engine.fabricDraw;if(!t)return;if(!e){t.clearAllShapes?.();return}const n=this.deserializeSnapshotValue(e);await t.restoreAllShapes?.(n)}applyAnnotationMode(e){const t=this.engine.fabricDraw;t&&(t.setActionHandlers?.({}),t.show?.(),t.active?.(e),t.setDrawType?.("none"))}serializeSnapshotValue(e){if(e==null)return e;if(e instanceof b.Vector3)return{__type:"Vector3",x:e.x,y:e.y,z:e.z};if(Array.isArray(e))return e.map(t=>this.serializeSnapshotValue(t));if(typeof e=="object"){if(e instanceof HTMLElement||e instanceof SVGElement)return;const t={};return Object.keys(e).forEach(n=>{if(n==="container")return;const i=this.serializeSnapshotValue(e[n]);i!==void 0&&(t[n]=i)}),t}if(typeof e!="function")return e}deserializeSnapshotValue(e){if(e==null)return e;if(Array.isArray(e))return e.map(t=>this.deserializeSnapshotValue(t));if(typeof e=="object"){if(e.__type==="Vector3")return new b.Vector3(e.x,e.y,e.z);const t={};return Object.keys(e).forEach(n=>{t[n]=this.deserializeSnapshotValue(e[n])}),t}return e}}class ik{options;deviceType;animationId=null;isDisposed=!1;isRenderingPaused=!1;controlsEnabledBeforePause=!0;animate;onWindowResize;_fpsFrameCount=0;_fpsLastCheck=0;_fpsLastSwitch=0;_lowFpsCount=0;_highFpsCount=0;_fpsCheckInterval=100;_fpsSwitchCooldown=100;_fpsThreshold=30;_fpsUpgradeThreshold=60;_lowFpsRequired=5;_highFpsRequired=.1;isMouseDown=!1;isWheeling=!1;scene;camera;renderer;sceneModule;cameraModule;deviceModule;renderModule;controlModule;composerModule;loaderModule;engineStatus;events;lightModule;interactionModule;modelToolModule;worldToScreen;handelBehaved;octreeBox;controls;stats;catchSvg;engineModelModule;viewTree;merge2d;viewCube;rangeScale;setting;measure;clipping;modelTree;engineInfo;modelProperties;modelMapperBatch;modelEdge;ai;pathRoaming;hoverHighLight;minMap;grid;level;issueReport;text;hdr;ground;skyManager;linkElement2d3d;linkView2d3d;oneClickEncoding;fabricDraw;drawingPin;models=[];reactBoundingClientRect={left:0,top:0};version="3.8.4";versionEl=null;container;constructor(e){if(window.THREE=b,this.options=e,this.container=document.getElementById(e.containerId),!this.container)throw new Error(`Container ${e.containerId} not found`);if(this.engineModelModule=new Q2(this),this.engineModelModule.init(),this.ai=new DP(this),this.deviceModule=new E_(this),this.deviceType=this.deviceModule.getDeviceType(),this.cameraModule=new Sn(this),this.sceneModule=new S_(this),this.scene=this.sceneModule.scene,this.renderModule=new sE(this),this.renderer=this.renderModule.createRenderer(),this.camera=this.cameraModule.orthographicCamera,this.scene.camera=this.camera,this.renderer){const r=this.renderer;r.interactionCullingEnabled=!0,r.interactionActive=!1,r.interactionRenderScene=this.scene,r.interactionFrameBudgetMs=this.options.interactionFrameBudgetMs??6,r.interactionSkipShadows=this.options.interactionSkipShadows??!0}this.controlModule=new dE(this),this.controlModule.switchDefaultMode(),this.controls=this.controlModule.orbitControls,this.clipping=new MP(this),this.clipping.init(),this.composerModule=new ME(this),this.composerModule.init(),this.events=new L2,this.engineStatus=new P2(this),this.engineStatus.init(),this.loaderModule=new D2(this),this.lightModule=new O2(this),this.lightModule.init(),this.viewCube=new aB(this),this.viewCube.init(),this.options.showViewCube==!1&&this.viewCube.hide(),this.octreeBox=lB(this),this.rangeScale=new cB(this),this.rangeScale.init(),this.setting=new vB(this),this.engineModelModule.init(),this.handelBehaved=Od(this),this.modelMapperBatch=new TP(this),this.measure=new DB(this),this.modelToolModule=new N2(this),this.modelProperties=new IP(this),this.interactionModule=new U2(this),this.interactionModule.init(),this.interactionModule.active(),this.hoverHighLight=new Dc(this),this.modelEdge=new yB(this),this.modelTree=new SP(this),this.viewTree=new zP(this),this.merge2d=new c3(this),this.engineInfo=new EP(this),this.pathRoaming=new PP(this),this.pathRoaming.init(),this.oneClickEncoding=new NP(this),this.minMap=new LP(this),this.linkElement2d3d=new FP(this),this.linkView2d3d=new OP(this),this.grid=new dB(this),this.level=new xB(this),this.issueReport=new RP(this),this.fabricDraw=new tk(this),this.drawingPin=new nk(this),this.text=new kP(this),this.hdr=new gB(this),this.ground=new bf(this),this.ground.init(),this.skyManager=new bB(this),this.setting.init(),this.worldToScreen=new vt(this.camera,this.renderer,this.scene),this.options.showStats&&(this.stats=new Ax,this.stats.showPanel(0),this.stats.dom.style.position="absolute",this.stats.dom.style.top="0px",this.stats.dom.style.left="0px",this.stats.dom.style.zIndex="1000",this.container.appendChild(this.stats.dom));let t=document.createElement("div");t.className="versionText",this.versionEl=t,this.updateVersionDisplay(),this.container.appendChild(t);let n=document.createElementNS("http://www.w3.org/2000/svg","svg");n.style.position="absolute",n.style.zIndex="1000",n.style.left="0px",n.style.top="0px",n.style.pointerEvents="none",this.container.appendChild(n),this.catchSvg=n,this.onWindowResize=()=>{this.handleWindowResize()},window.addEventListener("resize",this.onWindowResize);let i=this;this.controls.addEventListener("start",()=>{i.renderer&&(i.renderer.interactionActive=!0),i.events.trigger(Ss.EngineBusy),i.container&&(i.container.style.cursor="none")}),this.controls.addEventListener("end",()=>{i.renderer&&(i.renderer.interactionActive=!1),i.events.trigger(Ss.EngineFree),i.container&&(i.container.style.cursor="default")}),this.controls.addEventListener("change",()=>{const r=new b.Vector3;i.camera.getWorldDirection(r);const o=Math.atan2(r.x,-r.z);let a=new CustomEvent("D3ViewUpdate",{detail:{position:i.camera.position,rotation:o,type:i.camera.type}});window.dispatchEvent(a)}),this.events.on(Ss.LoadingCompleted,r=>{i.modelEdge.active()}),this.animate=()=>{if(!this.isRenderingPaused)this.animationId=requestAnimationFrame(this.animate);else{this.animationId=null;return}this.stats&&this.stats.begin(),this.composerModule&&this.composerModule.composer.render(),this.viewCube&&this.viewCube.cubeTool.RenderScene(),this.measure.update(),this.ground.update(),this.skyManager.update(),this.hoverHighLight.update(),this.controlModule.update(),this.minMap.update(),this.grid.update(),this.level.update(),this.text&&this.text.update(),this.stats&&this.stats.end(),this._fpsFrameCount++;const r=performance.now();if(r-this._fpsLastCheck>=this._fpsCheckInterval){const o=r-this._fpsLastCheck,a=this._fpsFrameCount/o*1e3;this._fpsFrameCount=0,this._fpsLastCheck=r,a<this._fpsThreshold?(this._lowFpsCount++,this._highFpsCount=0,this._lowFpsCount>=this._lowFpsRequired&&r-this._fpsLastSwitch>this._fpsSwitchCooldown&&(this._adaptiveRenderingDowngrade(),this._fpsLastSwitch=r,this._lowFpsCount=0)):(this._lowFpsCount=0,this._highFpsCount=0)}if(this.scene){let o=this.scene?.dirLight;o&&this.camera&&this.updateLightPosition(this.camera,o)}},this.animate()}updateVersionDisplay(){if(!this.versionEl)return;const e={simple:"simple",balance:"balance",advanced:"advanced"},t=this.engineModelModule?.getCurrentMode()??"",n=e[t]??t;this.versionEl.innerHTML=`v${this.version} | ${n}`}updateLightPosition(e,t,n=!0){const i=new b.Vector3;e.getWorldDirection(i);const r=100,o=new b.Vector3().copy(i).multiplyScalar(-r),a=new b.Vector3(0,1,0),l=new b.Vector3().crossVectors(i,a).normalize();o.addScaledVector(a,r*.5),o.addScaledVector(l,r*.3),t.position.copy(e.position).add(o);const c=new b.Vector3().copy(e.position).add(i.multiplyScalar(20));t.target.position.copy(c),t.target.updateMatrixWorld()}_adaptiveRenderingDowngrade(){const e=["simple","balance","advanced"],t=this.engineModelModule.getCurrentMode(),n=e.indexOf(t);if(n>0){const i=e[n-1];console.log(`[AdaptiveRendering] FPS低于${this._fpsThreshold},自动降级: ${t} → ${i}`),this.engineModelModule.autoSwitch(i)}}_adaptiveRenderingUpgrade(){const e=["simple","balance","advanced"],t=this.engineModelModule.getCurrentMode(),n=e.indexOf(t);if(n<e.length-1){const i=e[n+1];console.log(`[AdaptiveRendering] FPS高于${this._fpsUpgradeThreshold},自动升级: ${t} → ${i}`),this.engineModelModule.autoSwitch(i)}}pauseRendering(){if(this.isRenderingPaused){console.warn("[BimEngine] Rendering is already paused");return}this.isRenderingPaused=!0,this.controls&&(this.controlsEnabledBeforePause=this.controls.enabled,this.controls.enabled=!1)}resumeRendering(){if(!this.isRenderingPaused){console.warn("[BimEngine] Rendering is not paused");return}this.isRenderingPaused=!1,this.controls&&(this.controls.enabled=this.controlsEnabledBeforePause),this.animationId===null&&this.animate()}isRenderingPausedState(){return this.isRenderingPaused}handleWindowResize(e,t){if(!this.container||!this.renderer||!this.camera)return;if(e===void 0||t===void 0){const c=this.deviceModule.getContainerSize();e=e??c.width,t=t??c.height}if(!e||!t)return;const n=this.camera.position.clone(),i=this.camera.quaternion.clone(),r=this.camera.up.clone(),o=this.controls?.target?.clone?.(),a=this.controlModule?.orbitControls?.origin?.clone?.();this.renderer.setPixelRatio(window.devicePixelRatio),this.renderer.setSize(e,t);const l=e/t;if(this.camera===this.cameraModule.perspectiveCamera)this.cameraModule.perspectiveCamera.aspect=l,this.cameraModule.perspectiveCamera.updateProjectionMatrix(),this.camera=this.cameraModule.perspectiveCamera;else if(this.camera===this.cameraModule.orthographicCamera){const c=this.cameraModule.orthographicCamera,h=this.cameraModule.getOrthographicVisibleHeight(c);this.cameraModule.setOrthographicVisibleHeight(h,c,l),c.updateProjectionMatrix()}if(this.composerModule&&(typeof this.composerModule.resize=="function"?this.composerModule.resize(e,t):this.composerModule.composer&&this.composerModule.composer.setSize(e,t)),this.catchSvg&&this.catchSvg.setAttribute("viewBox",`0 0 ${e} ${t}`),this.fabricDraw&&this.fabricDraw.resize(e,t),this.camera.position.copy(n),this.camera.quaternion.copy(i),this.camera.up.copy(r),this.camera.updateMatrix(),this.camera.updateMatrixWorld(!0),o&&this.controls?.target&&this.controls.target.copy(o),a&&this.controlModule?.orbitControls?.origin&&this.controlModule.orbitControls.origin.copy(a),this.controlModule?.orbitControls){const c=this.controlModule.orbitControls;c._lastPosition?.copy?.(this.camera.position),c._lastTarget?.copy?.(c.target),c._lastUp?.copy?.(this.camera.up),c._lastQuaternion?.copy?.(this.camera.quaternion),c._lastZoom=this.camera.zoom}this.controlModule?.firstPersonControls?.syncRotationStateFromCamera?.(),this.controlModule?.firstPersonControls?.syncSharedTargetFromCamera?.(),this.events&&this.events.trigger(Ss.ViewportResize,{width:e,height:t})}dispose(){if(this.isDisposed)return;this.isDisposed=!0,console.log("[BimEngine] Starting engine disposal..."),this.animationId!==null&&(cancelAnimationFrame(this.animationId),this.animationId=null),this.isRenderingPaused=!0,this.onWindowResize&&window.removeEventListener("resize",this.onWindowResize);try{this.invokeIfExists(this.rangeScale,"dispose"),this.invokeIfExists(this.measure,"dispose"),this.invokeIfExists(this.clipping,"disActive"),this.invokeIfExists(this.interactionModule,"dispose"),this.invokeIfExists(this.controlModule,"dispose"),this.invokeIfExists(this.pathRoaming,"dispose"),this.invokeIfExists(this.hoverHighLight,"dispose"),this.invokeIfExists(this.linkElement2d3d,"dispose"),this.invokeIfExists(this.linkView2d3d,"dispose"),this.invokeIfExists(this.skyManager,"close",!0),this.invokeIfExists(this.hdr,"dispose"),this.invokeIfExists(this.minMap,"dispose"),this.invokeIfExists(this.grid,"dispose"),this.invokeIfExists(this.level,"dispose"),this.invokeIfExists(this.ground,"dispose"),this.invokeIfExists(this.text,"dispose"),this.invokeIfExists(this.issueReport,"dispose"),this.invokeIfExists(this.fabricDraw,"dispose"),this.invokeIfExists(this.viewCube?.cubeTool,"dispose"),this.invokeIfExists(this.handelBehaved,"disActive")}catch(t){console.warn("[BimEngine] Error disposing managers:",t)}try{this.controlModule&&(this.controlModule.originDiv&&this.controlModule.originDiv.remove(),this.controlModule.orbitControls&&typeof this.controlModule.orbitControls.dispose=="function"&&this.controlModule.orbitControls.dispose(),this.controlModule.firstPersonControls&&typeof this.controlModule.firstPersonControls.dispose=="function"&&this.controlModule.firstPersonControls.dispose())}catch(t){console.warn("[BimEngine] Error disposing controls:",t)}this.scene&&(this.disposeSceneAttachments(this.scene),this.clearScene(this.scene));try{this.composerModule&&this.composerModule.composer&&(this.composerModule.composer.passes&&this.composerModule.composer.passes.forEach(t=>{t?.dispose?.()}),this.composerModule.composer.renderTarget1&&this.composerModule.composer.renderTarget1.dispose(),this.composerModule.composer.renderTarget2&&this.composerModule.composer.renderTarget2.dispose(),this.composerModule.composer.dispose?.(),this.composerModule.composer.passes=[])}catch(t){console.warn("[BimEngine] Error disposing composer:",t)}try{this.renderModule?.disposeRenderer?.(),this.renderer&&(this.renderer.renderLists?.dispose?.(),this.renderer.domElement&&this.renderer.domElement.parentElement&&this.renderer.domElement.parentElement.removeChild(this.renderer.domElement),this.renderer.dispose(),this.renderer.forceContextLoss())}catch(t){console.warn("[BimEngine] Error disposing renderer:",t)}try{this.stats?.dom?.parentElement&&this.stats.dom.parentElement.removeChild(this.stats.dom),this.catchSvg?.parentElement&&this.catchSvg.parentElement.removeChild(this.catchSvg),this.versionEl?.parentElement&&this.versionEl.parentElement.removeChild(this.versionEl)}catch(t){console.warn("[BimEngine] Error disposing DOM elements:",t)}try{this.events&&this.events.listeners&&this.events.listeners.clear()}catch(t){console.warn("[BimEngine] Error clearing event listeners:",t)}const e=this;e.scene=null,e.camera=null,e.renderer=null,e.controls=null,e.models=[],e.container=null,e.catchSvg=null,e.stats=null,e.versionEl=null,e.worldToScreen=null,e.measure=null,e.clipping=null,e.interactionModule=null,e.controlModule=null,e.sceneModule=null,e.cameraModule=null,e.deviceModule=null,e.renderModule=null,e.composerModule=null,e.loaderModule=null,e.lightModule=null,e.engineStatus=null,e.hoverHighLight=null,e.pathRoaming=null,e.hdr=null,e.skyManager=null,e.viewCube=null,e.grid=null,e.level=null,e.ground=null,e.minMap=null,e.fabricDraw=null,e.linkElement2d3d=null,e.linkView2d3d=null,e.rangeScale=null,e.text=null,e.issueReport=null,e.modelEdge=null,e.modelTree=null,e.modelProperties=null,e.modelMapperBatch=null,e.engineInfo=null,e.ai=null,e.oneClickEncoding=null,e.drawingPin=null,e.events=null,console.log("[BimEngine] Engine disposal completed")}clearScene(e){if(!e)return;[...e.children].forEach(n=>{this.clearScene(n)}),e.parent&&e.parent.remove(e),e instanceof b.Mesh&&!(e instanceof b.InstancedMesh)&&(e.geometry&&e.geometry.dispose(),e.material&&(Array.isArray(e.material)?e.material.forEach(n=>this.disposeMaterial(n)):this.disposeMaterial(e.material))),e instanceof b.Line&&(e.geometry&&e.geometry.dispose(),e.material&&this.disposeMaterial(e.material)),e instanceof b.Points&&(e.geometry&&e.geometry.dispose(),e.material&&this.disposeMaterial(e.material)),e instanceof b.InstancedMesh&&(e.geometry&&e.geometry.dispose(),e.material&&(Array.isArray(e.material)?e.material.forEach(n=>this.disposeMaterial(n)):this.disposeMaterial(e.material)),e.instanceMatrix&&(e.instanceMatrix=null),e.instanceColor&&(e.instanceColor=null)),e instanceof b.Sprite&&e.material&&this.disposeMaterial(e.material),e instanceof b.Light&&e.shadow?.dispose?.()}invokeIfExists(e,t,...n){const i=e?.[t];typeof i=="function"&&i.apply(e,n)}disposeSceneAttachments(e){new Set([e.background,e.environment,e.overrideMaterial]).forEach(n=>{this.disposeSceneAttachment(n)}),e.background=null,e.environment=null,e.overrideMaterial=null,e.dirLight=null,e.camera=null}disposeSceneAttachment(e){e&&(e instanceof b.Material||e instanceof b.Texture)&&e.dispose?.()}disposeMaterial(e){if(!e)return;["map","lightMap","bumpMap","normalMap","specularMap","envMap","alphaMap","aoMap","displacementMap","emissiveMap","gradientMap","metalnessMap","roughnessMap","clearcoatMap","clearcoatNormalMap","clearcoatRoughnessMap","transmissionMap","thicknessMap","sheenColorMap","sheenRoughnessMap","specularIntensityMap","specularColorMap","iridescenceMap","iridescenceThicknessMap"].forEach(n=>{const i=e[n];i&&i instanceof b.Texture&&i.dispose()}),e.dispose()}}const sk=`
6064
6064
  varying vec2 vWorldPos;
6065
6065
 
6066
6066
  void main() {