@ifc-lite/viewer 1.27.0 → 1.28.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +35 -42
- package/CHANGELOG.md +74 -0
- package/dist/assets/{basketViewActivator-B3CdrLsb.js → basketViewActivator-Ce38DhXd.js} +8 -8
- package/dist/assets/{bcf-QeHK_Aud.js → bcf-Cv_O3JfD.js} +56 -56
- package/dist/assets/{decode-worker-CgM1iNSK.js → decode-worker-Cjign7Zh.js} +1 -1
- package/dist/assets/{deflate-B-d0SYQM.js → deflate-HbyMq59o.js} +1 -1
- package/dist/assets/drawing-2d-DW98umlt.js +257 -0
- package/dist/assets/e57-source-2wI9jkCA.js +1 -0
- package/dist/assets/{exporters-B4LbZFeT.js → exporters-BuD3XRzB.js} +1309 -1153
- package/dist/assets/geometry.worker-TH3fCCoY.js +1 -0
- package/dist/assets/{geotiff-CrVtDRFq.js → geotiff-B2HA8Bwm.js} +10 -10
- package/dist/assets/{ids-DjsGFN10.js → ids-DYUFMd5f.js} +952 -945
- package/dist/assets/{ifc-lite_bg-DsYUIHm3.wasm → ifc-lite_bg-BEA5DLmg.wasm} +0 -0
- package/dist/assets/index-E9wB0zWt.css +1 -0
- package/dist/assets/{index-COYokSKc.js → index-n5O1QJMM.js} +37877 -38126
- package/dist/assets/{index.es-CY202jA3.js → index.es-BKVIpZgL.js} +9 -9
- package/dist/assets/{jpeg-D4wOkf5h.js → jpeg-C7hjKjPX.js} +1 -1
- package/dist/assets/{jspdf.es.min-DIGb9BHN.js → jspdf.es.min-oWlFc42Y.js} +4 -4
- package/dist/assets/lens-C4p1kQ0p.js +1 -0
- package/dist/assets/{lerc-DmW0_tgf.js → lerc-BfIOGhQz.js} +1 -1
- package/dist/assets/{lzw-oWetY-d6.js → lzw-B0jRuuW5.js} +1 -1
- package/dist/assets/{native-bridge-BX8_tHXE.js → native-bridge-DpB-dtEn.js} +6 -3
- package/dist/assets/{packbits-F8Nkp4NY.js → packbits-DVvBTC39.js} +1 -1
- package/dist/assets/parser.worker-BDsWQ6rc.js +182 -0
- package/dist/assets/{pdf-Dsh3HPZB.js → pdf-dVIqI5ac.js} +10 -10
- package/dist/assets/raw-C0ZJYGmN.js +1 -0
- package/dist/assets/{sandbox-BAC3a-eN.js → sandbox-qpJlrNN0.js} +2962 -2554
- package/dist/assets/server-client-DVZ2huNS.js +719 -0
- package/dist/assets/{webimage-BLV1dgmd.js → webimage-B394g0Tw.js} +1 -1
- package/dist/assets/{xlsx-Bc2HTrjC.js → xlsx-D-oHO76J.js} +8 -8
- package/dist/assets/{zstd-C_1HxVrA.js → zstd-Bf38MwV2.js} +1 -1
- package/dist/index.html +9 -9
- package/package.json +24 -23
- package/src/App.tsx +1 -3
- package/src/components/mcp/playground-dispatcher.ts +3 -0
- package/src/components/mcp/playground-files.ts +33 -1
- package/src/components/viewer/BCFPanel.tsx +1 -16
- package/src/components/viewer/ChatPanel.tsx +11 -46
- package/src/components/viewer/CommandPalette.tsx +6 -1
- package/src/components/viewer/ComparePanel.tsx +420 -0
- package/src/components/viewer/HierarchyPanel.tsx +48 -183
- package/src/components/viewer/IDSPanel.tsx +1 -26
- package/src/components/viewer/MainToolbar.tsx +94 -187
- package/src/components/viewer/MobileToolbar.tsx +1 -9
- package/src/components/viewer/PropertiesPanel.tsx +98 -127
- package/src/components/viewer/ScriptPanel.tsx +8 -34
- package/src/components/viewer/Section2DPanel.tsx +32 -1
- package/src/components/viewer/ViewerLayout.tsx +5 -2
- package/src/components/viewer/Viewport.tsx +3 -0
- package/src/components/viewer/ViewportContainer.tsx +24 -42
- package/src/components/viewer/ViewportOverlays.tsx +1 -4
- package/src/components/viewer/hierarchy/HierarchyNode.tsx +3 -3
- package/src/components/viewer/hierarchy/ifc-icons.ts +9 -0
- package/src/components/viewer/hierarchy/treeDataBuilder.ts +87 -0
- package/src/components/viewer/hierarchy/types.ts +1 -0
- package/src/components/viewer/hierarchy/useHierarchyTree.ts +6 -2
- package/src/components/viewer/properties/MaterialTotalsPanel.tsx +283 -0
- package/src/components/viewer/useGeometryStreaming.ts +0 -2
- package/src/hooks/federationLoadGate.test.ts +12 -2
- package/src/hooks/federationLoadGate.ts +9 -2
- package/src/hooks/ingest/federationAlign.ts +488 -0
- package/src/hooks/ingest/viewerModelIngest.ts +3 -212
- package/src/hooks/useCompare.ts +0 -0
- package/src/hooks/useCompareOverlay.ts +119 -0
- package/src/hooks/useDrawingGeneration.ts +234 -14
- package/src/hooks/useIfc.ts +1 -1
- package/src/hooks/useIfcCache.ts +100 -24
- package/src/hooks/useIfcFederation.ts +42 -811
- package/src/hooks/useIfcLoader.ts +349 -1517
- package/src/hooks/useIfcServer.ts +3 -0
- package/src/hooks/useLens.ts +5 -1
- package/src/hooks/useSymbolicAnnotations.ts +70 -38
- package/src/lib/compare/buildFingerprints.ts +173 -0
- package/src/lib/compare/describeChange.ts +0 -0
- package/src/lib/compare/geometricData.test.ts +54 -0
- package/src/lib/compare/geometricData.ts +37 -0
- package/src/lib/compare/overlay.test.ts +99 -0
- package/src/lib/compare/overlay.ts +91 -0
- package/src/lib/geo/cesium-placement.ts +1 -1
- package/src/lib/geo/reproject.ts +4 -1
- package/src/lib/llm/script-edit-ops.ts +23 -0
- package/src/lib/llm/stream-client.ts +8 -1
- package/src/lib/search/result-export.ts +7 -1
- package/src/sdk/adapters/export-adapter.ts +6 -1
- package/src/services/cacheService.ts +9 -25
- package/src/services/desktop-export.ts +2 -59
- package/src/services/file-dialog.ts +8 -142
- package/src/store/constants.ts +23 -0
- package/src/store/globalId.ts +15 -13
- package/src/store/index.ts +19 -6
- package/src/store/slices/cesiumSlice.ts +8 -1
- package/src/store/slices/compareSlice.ts +96 -0
- package/src/store/slices/drawing2DSlice.ts +8 -0
- package/src/store/slices/lensSlice.ts +8 -0
- package/src/store/slices/visibilitySlice.ts +22 -1
- package/src/store/types.ts +1 -71
- package/src/utils/acquireFileBuffer.test.ts +12 -4
- package/src/utils/ifcConfig.ts +0 -12
- package/src/utils/loadingUtils.ts +32 -0
- package/src/utils/spatialHierarchy.test.ts +53 -1
- package/src/utils/spatialHierarchy.ts +42 -2
- package/src/vite-env.d.ts +2 -0
- package/vite.config.ts +6 -3
- package/DESKTOP_CONTRACT_VERSION +0 -1
- package/dist/assets/drawing-2d-C71b8Ugx.js +0 -257
- package/dist/assets/e57-source-CQHxE8n3.js +0 -1
- package/dist/assets/event-B0kAzHa-.js +0 -1
- package/dist/assets/geometry.worker-BdH-E6NB.js +0 -1
- package/dist/assets/index-ajK6D32J.css +0 -1
- package/dist/assets/lens-PYsLu_MA.js +0 -1
- package/dist/assets/parser.worker-D591Zu_-.js +0 -182
- package/dist/assets/raw-D9iw0tmc.js +0 -1
- package/dist/assets/server-client-Cjwnm7il.js +0 -706
- package/dist/assets/tauri-core-stub-D8Fa-u43.js +0 -1
- package/dist/assets/tauri-dialog-stub-r7Wksg7o.js +0 -1
- package/dist/assets/tauri-fs-stub-BdeRC7aK.js +0 -1
- package/src/components/viewer/DesktopEntitlementBanner.tsx +0 -74
- package/src/components/viewer/SettingsPage.tsx +0 -581
- package/src/hooks/ingest/resolveDataStoreOrAbort.test.ts +0 -61
- package/src/hooks/ingest/resolveDataStoreOrAbort.ts +0 -28
- package/src/hooks/ingest/watchedGeometryStream.test.ts +0 -78
- package/src/hooks/ingest/watchedGeometryStream.ts +0 -76
- package/src/lib/desktop/desktopEntitlementEvents.ts +0 -39
- package/src/lib/desktop-entitlement.ts +0 -43
- package/src/lib/desktop-product.ts +0 -130
- package/src/lib/platform.ts +0 -23
- package/src/services/desktop-cache.ts +0 -186
- package/src/services/desktop-harness.ts +0 -196
- package/src/services/desktop-logger.ts +0 -20
- package/src/services/desktop-native-metadata.ts +0 -230
- package/src/services/desktop-panel-actions.ts +0 -43
- package/src/services/desktop-preferences.ts +0 -44
- package/src/services/fs-cache.ts +0 -212
- package/src/services/tauri-core-stub.ts +0 -7
- package/src/services/tauri-dialog-stub.ts +0 -7
- package/src/services/tauri-fs-stub.ts +0 -7
- package/src/services/tauri-modules.d.ts +0 -50
- package/src/store/slices/desktopEntitlementSlice.ts +0 -86
- package/src/utils/desktopModelSnapshot.ts +0 -358
- package/src/utils/nativeSpatialDataStore.ts +0 -277
- package/src-tauri/Cargo.toml +0 -29
- package/src-tauri/build.rs +0 -7
- package/src-tauri/capabilities/default.json +0 -18
- package/src-tauri/icons/128x128.png +0 -0
- package/src-tauri/icons/128x128@2x.png +0 -0
- package/src-tauri/icons/32x32.png +0 -0
- package/src-tauri/icons/Square107x107Logo.png +0 -0
- package/src-tauri/icons/Square142x142Logo.png +0 -0
- package/src-tauri/icons/Square150x150Logo.png +0 -0
- package/src-tauri/icons/Square284x284Logo.png +0 -0
- package/src-tauri/icons/Square30x30Logo.png +0 -0
- package/src-tauri/icons/Square310x310Logo.png +0 -0
- package/src-tauri/icons/Square44x44Logo.png +0 -0
- package/src-tauri/icons/Square71x71Logo.png +0 -0
- package/src-tauri/icons/Square89x89Logo.png +0 -0
- package/src-tauri/icons/StoreLogo.png +0 -0
- package/src-tauri/icons/icon.icns +0 -0
- package/src-tauri/icons/icon.ico +0 -0
- package/src-tauri/icons/icon.png +0 -0
- package/src-tauri/src/lib.rs +0 -21
- package/src-tauri/src/main.rs +0 -10
- package/src-tauri/tauri.conf.json +0 -39
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
const Lt={projectionDepth:10,includeHiddenLines:!0,creaseAngle:30,scale:100};function U(n,t){return`${n}:${t}`}const S=1e-7;function Z(n,t,e){return{x:n,y:t,z:e}}function it(n,t){return{x:n.x-t.x,y:n.y-t.y,z:n.z-t.z}}function W(n,t){return n.x*t.x+n.y*t.y+n.z*t.z}function vt(n,t){return{x:n.y*t.z-n.z*t.y,y:n.z*t.x-n.x*t.z,z:n.x*t.y-n.y*t.x}}function kt(n){return Math.sqrt(n.x*n.x+n.y*n.y+n.z*n.z)}function ot(n){const t=kt(n);return t<S?{x:0,y:0,z:0}:{x:n.x/t,y:n.y/t,z:n.z/t}}function j(n,t,e){return{x:n.x+e*(t.x-n.x),y:n.y+e*(t.y-n.y),z:n.z+e*(t.z-n.z)}}function z(n,t){return{x:n.x-t.x,y:n.y-t.y}}function Et(n,t){return n.x*t.x+n.y*t.y}function Tt(n){return Math.sqrt(n.x*n.x+n.y*n.y)}function D(n,t){const e=t.x-n.x,i=t.y-n.y;return Math.sqrt(e*e+i*i)}function st(n,t,e){return{x:n.x+e*(t.x-n.x),y:n.y+e*(t.y-n.y)}}function Dt(n){const t=Tt(n);return t<S?{x:0,y:0}:{x:n.x/t,y:n.y/t}}function rt(n,t){return n.x*t.y-n.y*t.x}function Rt(n){return D(n.start,n.end)}function J(n){return Dt(z(n.end,n.start))}function yt(){return{min:{x:1/0,y:1/0},max:{x:-1/0,y:-1/0}}}function G(n,t){return{min:{x:Math.min(n.min.x,t.x),y:Math.min(n.min.y,t.y)},max:{x:Math.max(n.max.x,t.x),y:Math.max(n.max.y,t.y)}}}function Wt(n,t){let e=G(n,t.start);return e=G(e,t.end),e}function zt(n){return{x:(n.min.x+n.max.x)/2,y:(n.min.y+n.max.y)/2}}function _t(n){return{x:n.max.x-n.min.x,y:n.max.y-n.min.y}}function N(n,t,e){return W(n,t)-e}function pt(n,t){switch(n){case"x":return{x:1,y:0,z:0};case"y":return{x:0,y:1,z:0};case"z":return{x:0,y:0,z:1}}}function mt(n){switch(n){case"x":return{u:"z",v:"y"};case"y":return{u:"x",v:"z"};case"z":return{u:"x",v:"y"}}}function V(n,t,e){const i=mt(t),s=n[i.u],o=n[i.v];return{x:e?-s:s,y:o}}function Y(n,t,e,i){const s=n.x-t.x,o=n.y-t.y,r=n.z-t.z;return{x:s*e.x+o*e.y+r*e.z,y:s*i.x+o*i.y+r*i.z}}function xt(n){if(n.length<3)return 0;let t=0;for(let e=0;e<n.length;e++){const i=(e+1)%n.length;t+=n[e].x*n[i].y,t-=n[i].x*n[e].y}return t/2}function bt(n){return xt(n)>0}function Ct(n){return[...n].reverse()}function Bt(n){return bt(n)?n:Ct(n)}function Nt(n){return bt(n)?Ct(n):n}class It{tolerance;constructor(t=1e-4){this.tolerance=t}buildPolygons(t){const e=new Map;for(const s of t){const o=U(s.modelIndex,s.entityId);e.has(o)||e.set(o,[]),e.get(o).push(s)}const i=[];for(const[s,o]of e){const r=this.buildEntityPolygons(o);i.push(r)}return i.flat()}buildEntityPolygons(t){if(t.length===0)return[];const e=t[0],{entityId:i,ifcType:s,modelIndex:o}=e,r=t.map(c=>({start:c.p0_2d,end:c.p1_2d,used:!1})),a=this.buildLoops(r);return a.length===0?[]:this.classifyLoops(a).map(c=>({polygon:{outer:c.outer,holes:c.holes},entityId:i,ifcType:s,modelIndex:o,isCut:!0}))}buildLoops(t){const e=[];for(;;){const i=t.findIndex(o=>!o.used);if(i===-1)break;const s=this.buildSingleLoop(t,i);if(s&&s.length>=3){const o=xt(s);e.push({points:s,area:o})}}return e}buildSingleLoop(t,e){const i=[],s=t[e];s.used=!0,i.push(s.start);let o=s.end;const r=s.start,a=t.length;let l=0;for(;l<a;){if(l++,D(o,r)<this.tolerance)return i;const c=this.findConnectingSegment(t,o);if(c===-1)break;const u=t[c];u.used=!0,D(u.start,o)<this.tolerance?(i.push(u.start),o=u.end):(i.push(u.end),o=u.start)}return i.length>=3?i:null}findConnectingSegment(t,e){let i=-1,s=this.tolerance;for(let o=0;o<t.length;o++){if(t[o].used)continue;const r=t[o],a=D(r.start,e);a<s&&(s=a,i=o);const l=D(r.end,e);l<s&&(s=l,i=o)}return i}classifyLoops(t){if(t.length===0)return[];const e=[...t].sort((o,r)=>Math.abs(r.area)-Math.abs(o.area)),i=[],s=new Set;for(let o=0;o<e.length;o++){if(s.has(o))continue;const r=e[o],a=Bt(r.points),l=[];for(let c=o+1;c<e.length;c++){if(s.has(c))continue;const u=e[c];this.isLoopContainedIn(u.points,a)&&(l.push(Nt(u.points)),s.add(c))}s.add(o),i.push({outer:a,holes:l})}return i}isLoopContainedIn(t,e){const i=t[0];return this.pointInPolygon(i,e)}pointInPolygon(t,e){let i=!1;const s=e.length;for(let o=0,r=s-1;o<s;r=o++){const a=e[o],l=e[r];a.y>t.y!=l.y>t.y&&t.x<(l.x-a.x)*(t.y-a.y)/(l.y-a.y)+a.x&&(i=!i)}return i}}class Ot{planeNormal;planeDistance;axis;flipped;customPlane;constructor(t){this.axis=t.axis,this.flipped=t.flipped,this.customPlane=t.customPlane,this.customPlane?(this.planeNormal=this.customPlane.normal,this.planeDistance=this.customPlane.distance):(this.planeNormal=pt(t.axis),this.planeDistance=t.position)}cutMeshes(t){const e=performance.now(),i=[];let s=0,o=0;for(const u of t){const h=this.cutSingleMesh(u);i.push(h.segments),s+=h.trianglesProcessed,o+=h.trianglesIntersected}const r=i.flat(),l=new It().buildPolygons(r),c=performance.now()-e;return{segments:r,polygons:l,stats:{totalTriangles:s,intersectedTriangles:o,segmentCount:r.length,polygonCount:l.length,processingTimeMs:c}}}cutSingleMesh(t){const e=[],{positions:i,indices:s,expressId:o,ifcType:r,modelIndex:a}=t,l=s.length/3;let c=0;for(let u=0;u<l;u++){const h=s[u*3],d=s[u*3+1],f=s[u*3+2],g=this.getVertex(i,h),p=this.getVertex(i,d),y=this.getVertex(i,f),m=N(g,this.planeNormal,this.planeDistance),C=N(p,this.planeNormal,this.planeDistance),x=N(y,this.planeNormal,this.planeDistance),w=this.intersectTrianglePlane(g,p,y,m,C,x);if(w){c++;const b=this.customPlane?Y(w.p0,this.customPlane.origin,this.customPlane.tangent,this.customPlane.bitangent):V(w.p0,this.axis,this.flipped),M=this.customPlane?Y(w.p1,this.customPlane.origin,this.customPlane.tangent,this.customPlane.bitangent):V(w.p1,this.axis,this.flipped),$=M.x-b.x,I=M.y-b.y;if($*$+I*I<S*S)continue;e.push({p0:w.p0,p1:w.p1,p0_2d:b,p1_2d:M,entityId:o,ifcType:r||"Unknown",modelIndex:a||0})}}return{segments:e,trianglesProcessed:l,trianglesIntersected:c}}getVertex(t,e){const i=e*3;return Z(t[i],t[i+1],t[i+2])}intersectTrianglePlane(t,e,i,s,o,r){const a=(s>S?1:0)+(o>S?1:0)+(r>S?1:0),l=(s<-S?1:0)+(o<-S?1:0)+(r<-S?1:0);if(a===3||l===3||a===0&&l===0)return null;const c=[],u=this.edgePlaneIntersection(t,e,s,o);u&&c.push(u);const h=this.edgePlaneIntersection(e,i,o,r);if(h&&c.push(h),c.length<2){const d=this.edgePlaneIntersection(i,t,r,s);d&&c.push(d)}return c.length>=2?{p0:c[0],p1:c[1]}:null}edgePlaneIntersection(t,e,i,s){if(Math.abs(i)<S&&Math.abs(s)<S)return null;if(Math.abs(i)<S)return t;if(Math.abs(s)<S)return e;if(i>0==s>0)return null;const o=i/(i-s);return j(t,e,o)}}const wt={angleTolerance:.01,distanceTolerance:.001,gapTolerance:.01};function Ht(n,t={}){const e={...wt,...t},i=new Map;for(const o of n){const r=`${o.modelIndex}:${o.entityId}:${o.category}:${o.visibility}`;i.has(r)||i.set(r,[]),i.get(r).push(o)}const s=[];for(const o of i.values()){const r=Ut(o,e);s.push(...r)}return s}function Ut(n,t){if(n.length<=1)return n;const e=n.map(o=>o.line),i=jt(e,t),s=n[0];return i.map(o=>({...s,line:o}))}function jt(n,t={}){const e={...wt,...t};if(n.length<=1)return n;const i=Gt(n,e.angleTolerance),s=[];for(const o of i.values()){const r=Vt(o,e.distanceTolerance);for(const a of r){const l=Xt(a,e.gapTolerance);s.push(...l)}}return s}function Gt(n,t){const e=new Map,i=t*2;for(const s of n){const o=J(s);let r=Math.atan2(o.y,o.x);r<0&&(r+=Math.PI),r>=Math.PI&&(r-=Math.PI);const a=Math.floor(r/i);e.has(a)||e.set(a,[]),e.get(a).push(s)}return e}function Vt(n,t){const e=[],i=new Set;for(let s=0;s<n.length;s++){if(i.has(s))continue;const o=[n[s]];i.add(s);for(let r=s+1;r<n.length;r++)i.has(r)||Yt(n[s],n[r],t)&&(o.push(n[r]),i.add(r));e.push(o)}return e}function Yt(n,t,e){const i=J(n),s=z(t.start,n.start);if(Math.abs(rt(i,s))>e)return!1;const r=z(t.end,n.start);return Math.abs(rt(i,r))<=e}function Xt(n,t){if(n.length<=1)return n;const e=n[0],i=J(e),s=e.start,o=n.map(l=>{const c=at(l.start,s,i),u=at(l.end,s,i);return{t0:Math.min(c,u),t1:Math.max(c,u)}});o.sort((l,c)=>l.t0-c.t0);const r=[];let a=o[0];for(let l=1;l<o.length;l++){const c=o[l];c.t0<=a.t1+t?a={t0:a.t0,t1:Math.max(a.t1,c.t1)}:(r.push(a),a=c)}return r.push(a),r.map(l=>({start:{x:s.x+i.x*l.t0,y:s.y+i.y*l.t0},end:{x:s.x+i.x*l.t1,y:s.y+i.y*l.t1}}))}function at(n,t,e){const i=z(n,t);return Et(i,e)}function qt(n){switch(n){case"x":return{x:1,y:0,z:0};case"y":return{x:0,y:1,z:0};case"z":return{x:0,y:0,z:1}}}function Zt(n){return n.customPlane?{normal:n.customPlane.normal,offset:n.customPlane.distance}:{normal:qt(n.axis),offset:n.position}}function lt(n,t,e){const i=n-t;return e?-i:i}function v(n,t){const{normal:e,offset:i}=Zt(t),s=n.x*e.x+n.y*e.y+n.z*e.z-i;return t.flipped?-s:s}function Jt(n){const t=n.flipped?1:-1;if(n.customPlane){const e=n.customPlane.normal;return{x:e.x*t,y:e.y*t,z:e.z*t}}switch(n.axis){case"x":return{x:t,y:0,z:0};case"y":return{x:0,y:t,z:0};case"z":return{x:0,y:0,z:t}}}function _(n,t){if(t.customPlane){const e=t.customPlane;return Y(n,e.origin,e.tangent,e.bitangent)}return V(n,t.axis,t.flipped)}function K(n,t,e){const i=Math.min(n,t),s=Math.max(n,t),o=i<0&&s>=-e.below,r=s>0&&i<=e.above;return o&&r?"spanning":o?"visible":r?"overhead":"cull"}function Kt(n,t,e,i){const s=v(n,e),o=v(t,e);return K(s,o,i)}function Q(n){switch(n){case"overhead":return"hidden";case"visible":case"spanning":return"visible";case"cull":return null}}function Qt(n,t,e,i){const s=e.customPlane?e.customPlane.distance:e.position,o=lt(n.axisMin,s,e.flipped),r=lt(n.axisMax,s,e.flipped),a=Q(K(o,r,i));if(a===null)return[];const l=[];for(const c of n.contours){const u=Math.floor(c.length/2);if(!(u<3))for(let h=0;h<u;h++){const d=(h+1)%u,f=c[h*2],g=c[h*2+1],p=c[d*2],y=c[d*2+1];Math.abs(f-p)<1e-7&&Math.abs(g-y)<1e-7||l.push({line:{start:{x:f,y:g},end:{x:p,y}},category:"projection",visibility:a,entityId:t.entityId,ifcType:t.ifcType,modelIndex:t.modelIndex,depth:0})}}return l}function te(n,t,e,i){const s=t-n;if(Math.abs(s)<1e-12)return n>=e&&n<=i?[0,1]:null;const o=(e-n)/s,r=(i-n)/s,a=Math.max(0,Math.min(o,r)),l=Math.min(1,Math.max(o,r));return a<=l?[a,l]:null}class ee{creaseAngle;constructor(t=30){this.creaseAngle=t*Math.PI/180}extractEdges(t){const{positions:e,indices:i,expressId:s,ifcType:o,modelIndex:r}=t,a=new Map,l=[],c=i.length/3;for(let h=0;h<c;h++){const d=i[h*3],f=i[h*3+1],g=i[h*3+2],p=this.getVertex(e,d),y=this.getVertex(e,f),m=this.getVertex(e,g),C=this.computeFaceNormal(p,y,m);l.push(C),this.registerEdge(a,d,f,h),this.registerEdge(a,f,g,h),this.registerEdge(a,g,d,h)}const u=[];for(const[,h]of a){const d=this.getVertex(e,h.v0Idx),f=this.getVertex(e,h.v1Idx);let g=null,p=null,y=0,m="smooth";if(h.faceIndices.length===1)m="boundary",g=l[h.faceIndices[0]];else if(h.faceIndices.length>=2){g=l[h.faceIndices[0]],p=l[h.faceIndices[1]];const C=Math.max(-1,Math.min(1,W(g,p)));y=Math.acos(C),y>this.creaseAngle&&(m="crease")}m!=="smooth"&&u.push({v0:d,v1:f,face0Normal:g,face1Normal:p,dihedralAngle:y,type:m,entityId:s,ifcType:o||"Unknown",modelIndex:r||0})}return u}extractSilhouettes(t,e){const i=ot(e);return t.filter(s=>{if(s.type==="boundary")return!0;if(!s.face0Normal||!s.face1Normal)return!1;const o=W(s.face0Normal,i),r=W(s.face1Normal,i),a=o<-1e-4,l=r<-1e-4;return a!==l})}edgesToProjectionLines(t,e,i){const s=[],o=-i.below,r=i.above;for(const a of t){const l=v(a.v0,e),c=v(a.v1,e),u=te(l,c,o,r);if(!u)continue;const h=j(a.v0,a.v1,u[0]),d=j(a.v0,a.v1,u[1]),f=Q(Kt(h,d,e,i));if(f===null)continue;const g=_(h,e),p=_(d,e);Math.abs(g.x-p.x)<S&&Math.abs(g.y-p.y)<S||s.push({line:{start:g,end:p},category:"projection",visibility:f,entityId:a.entityId,ifcType:a.ifcType,modelIndex:a.modelIndex,depth:0})}return s}getVertex(t,e){const i=e*3;return Z(t[i],t[i+1],t[i+2])}computeFaceNormal(t,e,i){const s=it(e,t),o=it(i,t),r=vt(s,o);return ot(r)}registerEdge(t,e,i,s){const o=Math.min(e,i),r=Math.max(e,i),a=`${o}:${r}`;t.has(a)||t.set(a,{v0Idx:o,v1Idx:r,faceIndices:[]}),t.get(a).faceIndices.push(s)}}function ne(n,t,e){const i=[];for(const s of n){const o=ie(s,t,e),r=Q(o);if(r===null)continue;ct(i,s,s.outerPoints,"projection",t,r);let a=0;for(let l=0;l<s.holeCounts.length;l++){const c=s.holeCounts[l];if(c<2||a+c*2>s.holePoints.length){a+=c*2;continue}const u=s.holePoints.subarray(a,a+c*2);ct(i,s,u,"projection",t,r),a+=c*2}}return i}function ie(n,t,e){const{min:i,max:s}=oe(n,t);return K(i,s,e)}function ct(n,t,e,i,s,o){const r=Math.floor(e.length/2);if(r<2)return;const a=t.transform;for(let l=0;l<r;l++){const c=(l+1)%r,u=e[l*2],h=e[l*2+1],d=e[c*2],f=e[c*2+1],g=X(u,h,a),p=X(d,f,a),y=_(g,s),m=_(p,s);Math.abs(y.x-m.x)<1e-7&&Math.abs(y.y-m.y)<1e-7||n.push({line:{start:y,end:m},category:i,visibility:o,entityId:t.expressId,ifcType:t.ifcType,modelIndex:t.modelIndex,depth:re(g,p,s)})}}function X(n,t,e){return{x:e[0]*n+e[4]*t+e[12],y:e[1]*n+e[5]*t+e[13],z:e[2]*n+e[6]*t+e[14]}}function O(n,t){return n[12+se(t)]}function oe(n,t){let e=Number.POSITIVE_INFINITY,i=Number.NEGATIVE_INFINITY;const s=a=>{const l=v(a,t);l<e&&(e=l),l>i&&(i=l)},o={x:n.extrusionDir[0]*n.extrusionDepth,y:n.extrusionDir[1]*n.extrusionDepth,z:n.extrusionDir[2]*n.extrusionDepth},r=a=>{const l=Math.floor(a.length/2);for(let c=0;c<l;c++){const u=X(a[c*2],a[c*2+1],n.transform);s(u),s({x:u.x+o.x,y:u.y+o.y,z:u.z+o.z})}};if(r(n.outerPoints),r(n.holePoints),!Number.isFinite(e)||!Number.isFinite(i)){const a={x:O(n.transform,"x"),y:O(n.transform,"y"),z:O(n.transform,"z")},l=v(a,t),c=v({x:a.x+o.x,y:a.y+o.y,z:a.z+o.z},t);return{min:Math.min(l,c),max:Math.max(l,c)}}return{min:e,max:i}}function se(n){return n==="x"?0:n==="y"?1:2}function re(n,t,e){return(v(n,e)+v(t,e))/2}const ae={resolution:1024,samplesPerLine:10,depthBias:.001};class le{options;depthBuffer=null;width=0;height=0;bounds=null;constructor(t={}){this.options={...ae,...t}}buildDepthBuffer(t,e,i,s,o,r){r||(r=this.computeBounds(t,e,i,s,o)),this.bounds=r;const a=r.max.x-r.min.x,l=r.max.y-r.min.y;if(a<S||l<S){this.width=1,this.height=1,this.depthBuffer=new Float32Array([1/0]);return}const c=a/l;c>1?(this.width=this.options.resolution,this.height=Math.max(1,Math.floor(this.options.resolution/c))):(this.height=this.options.resolution,this.width=Math.max(1,Math.floor(this.options.resolution*c))),this.depthBuffer=new Float32Array(this.width*this.height),this.depthBuffer.fill(1/0);for(const u of t)this.rasterizeMesh(u,e,i,s,o)}classifyLines(t){if(!this.depthBuffer||!this.bounds)throw new Error("Depth buffer not built. Call buildDepthBuffer first.");const e=[];for(const i of t){const s=this.classifySingleLine(i);e.push(s)}return e}applyVisibility(t){const e=this.classifyLines(t),i=[];for(const s of e)if(s.overallVisibility==="visible")i.push({...s.line,visibility:"visible"});else if(s.overallVisibility==="hidden")i.push({...s.line,visibility:"hidden"});else for(const o of s.segments)i.push({...s.line,line:{start:o.start,end:o.end},visibility:o.visible?"visible":"hidden"});return i}computeBounds(t,e,i,s,o){let r=yt();const a=this.getProjectionAxes(e);for(const c of t){const{positions:u}=c,h=u.length/3;for(let d=0;d<h;d++){const f=u[d*3],g=u[d*3+1],p=u[d*3+2],y={x:f,y:g,z:p},m=y[e]-i;if(o?m<=0&&m>=-s:m>=0&&m<=s){const x=y[a.u],w=y[a.v],b={x:o?-x:x,y:w};r=G(r,b)}}}const l=Math.max(r.max.x-r.min.x,r.max.y-r.min.y)*.01;return r.min.x-=l,r.min.y-=l,r.max.x+=l,r.max.y+=l,r}getProjectionAxes(t){switch(t){case"x":return{u:"z",v:"y"};case"y":return{u:"x",v:"z"};case"z":return{u:"x",v:"y"}}}rasterizeMesh(t,e,i,s,o){const{positions:r,indices:a}=t,l=this.getProjectionAxes(e),c=a.length/3;for(let u=0;u<c;u++){const h=a[u*3],d=a[u*3+1],f=a[u*3+2],g=this.getVertex(r,h),p=this.getVertex(r,d),y=this.getVertex(r,f),m=g[e]-i,C=p[e]-i,x=y[e]-i,w=I=>o?I<=0&&I>=-s:I>=0&&I<=s;if(!w(m)&&!w(C)&&!w(x))continue;const b=this.projectVertex(g,l,o,i),M=this.projectVertex(p,l,o,i),$=this.projectVertex(y,l,o,i);this.rasterizeTriangle(b,M,$)}}getVertex(t,e){const i=e*3;return Z(t[i],t[i+1],t[i+2])}projectVertex(t,e,i,s){const o=t[e.u],r=t[e.v],l=["x","y","z"].find(u=>u!==e.u&&u!==e.v)??"z",c=t[l]-s;return{x:i?-o:o,y:r,depth:i?-c:c}}rasterizeTriangle(t,e,i){if(!this.bounds||!this.depthBuffer)return;const s=f=>(f-this.bounds.min.x)/(this.bounds.max.x-this.bounds.min.x)*(this.width-1),o=f=>(f-this.bounds.min.y)/(this.bounds.max.y-this.bounds.min.y)*(this.height-1),r={x:s(t.x),y:o(t.y),depth:t.depth},a={x:s(e.x),y:o(e.y),depth:e.depth},l={x:s(i.x),y:o(i.y),depth:i.depth},c=Math.max(0,Math.floor(Math.min(r.x,a.x,l.x))),u=Math.min(this.width-1,Math.ceil(Math.max(r.x,a.x,l.x))),h=Math.max(0,Math.floor(Math.min(r.y,a.y,l.y))),d=Math.min(this.height-1,Math.ceil(Math.max(r.y,a.y,l.y)));for(let f=h;f<=d;f++)for(let g=c;g<=u;g++){const p=this.barycentricCoords(g+.5,f+.5,r,a,l);if(p.u>=0&&p.v>=0&&p.w>=0){const y=p.u*r.depth+p.v*a.depth+p.w*l.depth,m=f*this.width+g;y<this.depthBuffer[m]&&(this.depthBuffer[m]=y)}}}barycentricCoords(t,e,i,s,o){const r=s.x-i.x,a=s.y-i.y,l=o.x-i.x,c=o.y-i.y,u=t-i.x,h=e-i.y,d=r*r+a*a,f=r*l+a*c,g=r*u+a*h,p=l*l+c*c,y=l*u+c*h,m=d*p-f*f;if(Math.abs(m)<1e-10)return{u:-1,v:-1,w:-1};const C=1/m,x=(p*g-f*y)*C,w=(d*y-f*g)*C;return{u:1-x-w,v:x,w}}classifySingleLine(t){if(!this.bounds||!this.depthBuffer)return{line:t,segments:[{start:t.line.start,end:t.line.end,visible:!0}],overallVisibility:"visible"};const{samplesPerLine:e,depthBias:i}=this.options,o=D(t.line.start,t.line.end)<S?1:Math.max(2,e),r=[];let a=t.line.start,l=this.sampleVisibility(t.line.start,t.depth,i),c=l?1:0;for(let h=1;h<=o;h++){const d=h/o,f=st(t.line.start,t.line.end,d),g=this.sampleVisibility(f,t.depth,i);if(g&&c++,g!==l&&h<o){const p=(h-.5)/o,y=st(t.line.start,t.line.end,p);r.push({start:a,end:y,visible:l}),a=y,l=g}}r.push({start:a,end:t.line.end,visible:l});let u;return c===o+1?u="visible":c===0?u="hidden":u="partial",{line:t,segments:r,overallVisibility:u}}sampleVisibility(t,e,i){if(!this.bounds||!this.depthBuffer)return!0;const s=(t.x-this.bounds.min.x)/(this.bounds.max.x-this.bounds.min.x)*(this.width-1),o=(t.y-this.bounds.min.y)/(this.bounds.max.y-this.bounds.min.y)*(this.height-1),r=Math.max(0,Math.min(this.width-1,Math.floor(s))),a=Math.max(0,Math.min(this.height-1,Math.floor(o))),l=this.depthBuffer[a*this.width+r];return e<=l+i}}const ht={IfcWall:{type:"diagonal",spacing:3,angle:45,lineWeight:.18,strokeColor:"#000000"},IfcWallStandardCase:{type:"diagonal",spacing:3,angle:45,lineWeight:.18,strokeColor:"#000000"},IfcCurtainWall:{type:"none",spacing:0,angle:0,lineWeight:.13,strokeColor:"#0066CC"},IfcSlab:{type:"concrete",spacing:2.5,angle:0,lineWeight:.13,strokeColor:"#666666"},IfcRoof:{type:"cross-hatch",spacing:4,angle:45,secondaryAngle:-45,lineWeight:.13,strokeColor:"#8B4513"},IfcCovering:{type:"horizontal",spacing:8,angle:0,lineWeight:.09,strokeColor:"#999999"},IfcColumn:{type:"steel",spacing:2,angle:45,lineWeight:.25,strokeColor:"#333333"},IfcBeam:{type:"steel",spacing:2,angle:45,lineWeight:.25,strokeColor:"#333333"},IfcMember:{type:"diagonal",spacing:2.5,angle:45,lineWeight:.18,strokeColor:"#444444"},IfcPlate:{type:"steel",spacing:1.5,angle:45,lineWeight:.18,strokeColor:"#555555"},IfcFooting:{type:"concrete",spacing:3,angle:0,lineWeight:.18,strokeColor:"#777777"},IfcPile:{type:"concrete",spacing:2.5,angle:0,lineWeight:.18,strokeColor:"#666666"},IfcWindow:{type:"glass",spacing:0,angle:0,lineWeight:.13,strokeColor:"#0099CC",fillColor:"rgba(200, 230, 255, 0.3)"},IfcDoor:{type:"none",spacing:0,angle:0,lineWeight:.25,strokeColor:"#000000"},IfcOpeningElement:{type:"none",spacing:0,angle:0,lineWeight:.13,strokeColor:"#CCCCCC"},IfcStair:{type:"horizontal",spacing:5,angle:0,lineWeight:.18,strokeColor:"#444444"},IfcStairFlight:{type:"horizontal",spacing:5,angle:0,lineWeight:.18,strokeColor:"#444444"},IfcRamp:{type:"diagonal",spacing:6,angle:30,lineWeight:.13,strokeColor:"#555555"},IfcRailing:{type:"none",spacing:0,angle:0,lineWeight:.13,strokeColor:"#666666"},IfcFlowTerminal:{type:"none",spacing:0,angle:0,lineWeight:.13,strokeColor:"#0066AA"},IfcFlowSegment:{type:"none",spacing:0,angle:0,lineWeight:.18,strokeColor:"#0066AA"},IfcDistributionElement:{type:"none",spacing:0,angle:0,lineWeight:.13,strokeColor:"#006688"},IfcSpace:{type:"none",spacing:0,angle:0,lineWeight:.09,strokeColor:"#CCCCCC"},IfcFurnishingElement:{type:"none",spacing:0,angle:0,lineWeight:.13,strokeColor:"#888888"},IfcFurniture:{type:"none",spacing:0,angle:0,lineWeight:.13,strokeColor:"#888888"},default:{type:"diagonal",spacing:4,angle:45,lineWeight:.13,strokeColor:"#666666"}};function Mt(n){return ht[n]||ht.default}const ce={cut:{weight:.5,color:"#000000",dashPattern:[],lineCap:"round",lineJoin:"round"},projection:{weight:.25,color:"#000000",dashPattern:[],lineCap:"round",lineJoin:"round"},hidden:{weight:.18,color:"#666666",dashPattern:[2,1],lineCap:"butt",lineJoin:"round"},silhouette:{weight:.35,color:"#000000",dashPattern:[],lineCap:"round",lineJoin:"round"},crease:{weight:.18,color:"#000000",dashPattern:[],lineCap:"round",lineJoin:"round"},boundary:{weight:.25,color:"#000000",dashPattern:[],lineCap:"round",lineJoin:"round"},annotation:{weight:.13,color:"#000000",dashPattern:[],lineCap:"butt",lineJoin:"miter"}},dt={IfcWall:{cut:.7,projection:.35},IfcWallStandardCase:{cut:.7,projection:.35},IfcSlab:{cut:.5,projection:.25},IfcColumn:{cut:.5,projection:.35},IfcBeam:{cut:.5,projection:.35},IfcWindow:{cut:.35,projection:.18},IfcDoor:{cut:.35,projection:.25},IfcStair:{cut:.35,projection:.25},IfcFurnishingElement:{cut:.18,projection:.13},IfcFurniture:{cut:.18,projection:.13},IfcSpace:{cut:.09,projection:.09}};function he(n,t){const e=ce[n];if(t&&dt[t]){const i=dt[t][n];if(i!==void 0)return{...e,weight:i}}return e}const H=[{name:"1:1",factor:1,useCase:"Full size details"},{name:"1:2",factor:2,useCase:"Large details"},{name:"1:5",factor:5,useCase:"Construction details"},{name:"1:10",factor:10,useCase:"Details"},{name:"1:20",factor:20,useCase:"Room plans, sections"},{name:"1:50",factor:50,useCase:"Floor plans, elevations"},{name:"1:100",factor:100,useCase:"Building plans"},{name:"1:200",factor:200,useCase:"Site plans"},{name:"1:500",factor:500,useCase:"Site context"},{name:"1:1000",factor:1e3,useCase:"Urban context"}],ut={A3_LANDSCAPE:{name:"A3 Landscape",width:420,height:297}};class Ft{generateHatch(t,e=100,i){const s=Mt(t.ifcType),o=i?{...s,type:i.type,spacing:i.spacing??s.spacing,angle:i.angle??s.angle,secondaryAngle:i.secondaryAngle??s.secondaryAngle}:s;if(o.type==="none"||o.type==="solid"||o.type==="glass")return{lines:[],pattern:o,polygon:t};const r=o.spacing*(e/100);let a=[];const l=this.generateParallelLines(t.polygon,r,o.angle,t.entityId,t.ifcType,t.modelIndex);if(a.push(...l),o.type==="cross-hatch"&&o.secondaryAngle!==void 0){const c=this.generateParallelLines(t.polygon,r,o.secondaryAngle,t.entityId,t.ifcType,t.modelIndex);a.push(...c)}if(o.type==="concrete"){const c=this.generateParallelLines(t.polygon,r*1.5,o.angle+90,t.entityId,t.ifcType,t.modelIndex);a.push(...c)}return{lines:a,pattern:o,polygon:t}}generateHatches(t,e=100,i){return t.map(s=>{const o=i?.(s);return this.generateHatch(s,e,o)})}generateParallelLines(t,e,i,s,o,r){if(e<S)return[];const a=i*Math.PI/180,l=Math.cos(a),c=Math.sin(a),u=-c,h=l,d=this.computePolygonBounds(t);if(!d)return[];const f=[{x:d.min.x,y:d.min.y},{x:d.max.x,y:d.min.y},{x:d.max.x,y:d.max.y},{x:d.min.x,y:d.max.y}];let g=1/0,p=-1/0;for(const C of f){const x=C.x*l+C.y*c;g=Math.min(g,x),p=Math.max(p,x)}const y=Math.sqrt(Math.pow(d.max.x-d.min.x,2)+Math.pow(d.max.y-d.min.y,2))*1.5,m=[];for(let C=g;C<=p;C+=e){const x=C*l,w=C*c,b={x:x-u*y,y:w-h*y},M={x:x+u*y,y:w+h*y},$=this.clipLineToPolygon({start:b,end:M},t);for(const I of $)m.push({line:I,entityId:s,ifcType:o,modelIndex:r})}return m}clipLineToPolygon(t,e){let i=this.clipLineToRing(t,e.outer,!0);for(const s of e.holes){const o=[];for(const r of i){const a=this.clipLineToRing(r,s,!1);o.push(...a)}i=o}return i}clipLineToRing(t,e,i){const s=[],o=t.end.x-t.start.x,r=t.end.y-t.start.y;for(let h=0;h<e.length;h++){const d=(h+1)%e.length,f=e[h],g=e[d],p=this.lineLineIntersection(t.start,t.end,f,g);if(p!==null&&p.t>=0&&p.t<=1){const y=-(g.y-f.y),m=g.x-f.x,C=o*y+r*m>0;s.push({t:p.t,entering:C})}}s.sort((h,d)=>h.t-d.t);const a=[];for(const h of s)(a.length===0||Math.abs(h.t-a[a.length-1].t)>S)&&a.push(h);if(a.length===0){const h={x:(t.start.x+t.end.x)/2,y:(t.start.y+t.end.y)/2};return this.pointInRing(h,e)===i?[t]:[]}const l=[];let c=this.pointInRing(t.start,e),u=0;for(const h of a)c===i&&l.push({start:{x:t.start.x+u*o,y:t.start.y+u*r},end:{x:t.start.x+h.t*o,y:t.start.y+h.t*r}}),u=h.t,c=!c;return c===i&&l.push({start:{x:t.start.x+u*o,y:t.start.y+u*r},end:t.end}),l.filter(h=>Math.abs(h.end.x-h.start.x)+Math.abs(h.end.y-h.start.y)>S)}lineLineIntersection(t,e,i,s){const o=e.x-t.x,r=e.y-t.y,a=s.x-i.x,l=s.y-i.y,c=o*l-r*a;if(Math.abs(c)<S)return null;const u=i.x-t.x,h=i.y-t.y,d=(u*l-h*a)/c,f=(u*r-h*o)/c;return f<0||f>1?null:{t:d,u:f}}pointInRing(t,e){let i=!1;const s=e.length;for(let o=0,r=s-1;o<s;r=o++){const a=e[o],l=e[r];a.y>t.y!=l.y>t.y&&t.x<(l.x-a.x)*(t.y-a.y)/(l.y-a.y)+a.x&&(i=!i)}return i}computePolygonBounds(t){if(t.outer.length===0)return null;let e=1/0,i=1/0,s=-1/0,o=-1/0;for(const r of t.outer)e=Math.min(e,r.x),i=Math.min(i,r.y),s=Math.max(s,r.x),o=Math.max(o,r.y);return{min:{x:e,y:i},max:{x:s,y:o}}}}class de{hatchGenerator=new Ft;export(t,e={}){const{paperSize:i=ut.A3_LANDSCAPE,scale:s=H.find(m=>m.factor===t.config.scale)||H[5],padding:o=20,showHiddenLines:r=!0,showHatching:a=!0,showTitleBlock:l=!1,title:c="Section",projectName:u="",backgroundColor:h="#FFFFFF"}=e,d=this.computeTransform(t.bounds,i,s,o);let f=this.createHeader(i,h);if(f+=this.createDefs(t,s.factor),a&&t.cutPolygons.length>0&&(f+=this.createHatchingLayer(t.cutPolygons,d,s.factor)),r){const m=t.lines.filter(C=>C.visibility==="hidden");m.length>0&&(f+=this.createLineLayer("hidden-lines",m,d,"Hidden Lines"))}const g=t.lines.filter(m=>m.category==="projection"&&m.visibility!=="hidden");g.length>0&&(f+=this.createLineLayer("projection-lines",g,d,"Projection"));const p=t.lines.filter(m=>(m.category==="silhouette"||m.category==="crease"||m.category==="boundary")&&m.visibility!=="hidden");p.length>0&&(f+=this.createLineLayer("feature-lines",p,d,"Feature Edges"));const y=t.lines.filter(m=>m.category==="cut");return y.length>0&&(f+=this.createLineLayer("cut-lines",y,d,"Cut Lines")),l&&(f+=this.createTitleBlock(i,c,u,s)),f+="</svg>",f}exportPolygons(t,e,i={}){const{paperSize:s=ut.A3_LANDSCAPE,scale:o=H[5],padding:r=20,backgroundColor:a="#FFFFFF"}=i,l=this.computeTransform(e,s,o,r);let c=this.createHeader(s,a);return c+=this.createPolygonDefs(o.factor),c+=this.createHatchingLayer(t,l,o.factor),c+="</svg>",c}computeTransform(t,e,i,s){_t(t);const o=zt(t);e.width-s*2,e.height-s*2;const r=1e3/i.factor,a=e.width/2-o.x*r,l=e.height/2+o.y*r;return{scale:r,offsetX:a,offsetY:l,flipY:!0}}transformPoint(t,e){return{x:t.x*e.scale+e.offsetX,y:e.flipY?-t.y*e.scale+e.offsetY:t.y*e.scale+e.offsetY}}createHeader(t,e){return`<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<svg xmlns="http://www.w3.org/2000/svg"
|
|
3
|
+
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
4
|
+
width="${t.width}mm"
|
|
5
|
+
height="${t.height}mm"
|
|
6
|
+
viewBox="0 0 ${t.width} ${t.height}">
|
|
7
|
+
<rect width="100%" height="100%" fill="${this.escapeXml(e)}"/>
|
|
8
|
+
`}createDefs(t,e){let i=` <defs>
|
|
9
|
+
`;return i+=this.createHatchPatternDefs(e),i+=` </defs>
|
|
10
|
+
`,i}createPolygonDefs(t){let e=` <defs>
|
|
11
|
+
`;return e+=this.createHatchPatternDefs(t),e+=` </defs>
|
|
12
|
+
`,e}createHatchPatternDefs(t){const e=3*(t/100);let i="";return i+=` <pattern id="hatch-diagonal" patternUnits="userSpaceOnUse"
|
|
13
|
+
width="${e}" height="${e}" patternTransform="rotate(45)">
|
|
14
|
+
<line x1="0" y1="0" x2="0" y2="${e}" stroke="#000" stroke-width="0.15"/>
|
|
15
|
+
</pattern>
|
|
16
|
+
`,i+=` <pattern id="hatch-cross" patternUnits="userSpaceOnUse"
|
|
17
|
+
width="${e}" height="${e}">
|
|
18
|
+
<line x1="0" y1="0" x2="${e}" y2="${e}" stroke="#000" stroke-width="0.1"/>
|
|
19
|
+
<line x1="${e}" y1="0" x2="0" y2="${e}" stroke="#000" stroke-width="0.1"/>
|
|
20
|
+
</pattern>
|
|
21
|
+
`,i+=` <pattern id="hatch-horizontal" patternUnits="userSpaceOnUse"
|
|
22
|
+
width="${e}" height="${e}">
|
|
23
|
+
<line x1="0" y1="${e/2}" x2="${e}" y2="${e/2}" stroke="#000" stroke-width="0.1"/>
|
|
24
|
+
</pattern>
|
|
25
|
+
`,i+=` <pattern id="hatch-concrete" patternUnits="userSpaceOnUse"
|
|
26
|
+
width="${e*2}" height="${e*2}">
|
|
27
|
+
<circle cx="${e*.3}" cy="${e*.3}" r="0.3" fill="#666"/>
|
|
28
|
+
<circle cx="${e*1.3}" cy="${e*1.3}" r="0.3" fill="#666"/>
|
|
29
|
+
<circle cx="${e*.8}" cy="${e*1.6}" r="0.2" fill="#888"/>
|
|
30
|
+
</pattern>
|
|
31
|
+
`,i+=` <pattern id="hatch-steel" patternUnits="userSpaceOnUse"
|
|
32
|
+
width="${e*.7}" height="${e*.7}" patternTransform="rotate(45)">
|
|
33
|
+
<line x1="0" y1="0" x2="0" y2="${e*.7}" stroke="#333" stroke-width="0.2"/>
|
|
34
|
+
</pattern>
|
|
35
|
+
`,i}createLineLayer(t,e,i,s){let o=` <g id="${t}" inkscape:label="${s}" inkscape:groupmode="layer">
|
|
36
|
+
`;for(const r of e)o+=this.renderLine(r,i);return o+=` </g>
|
|
37
|
+
`,o}renderLine(t,e){const i=he(t.category,t.ifcType),s=this.transformPoint(t.line.start,e),o=this.transformPoint(t.line.end,e),r=i.dashPattern.length>0?` stroke-dasharray="${i.dashPattern.join(" ")}"`:"";return` <line x1="${s.x.toFixed(3)}" y1="${s.y.toFixed(3)}" x2="${o.x.toFixed(3)}" y2="${o.y.toFixed(3)}"
|
|
38
|
+
stroke="${i.color}" stroke-width="${i.weight}"
|
|
39
|
+
stroke-linecap="${i.lineCap}"${r}
|
|
40
|
+
data-entity-id="${t.entityId}" data-ifc-type="${this.escapeXml(t.ifcType)}"/>
|
|
41
|
+
`}createHatchingLayer(t,e,i){let s=` <g id="hatching" inkscape:label="Hatching" inkscape:groupmode="layer">
|
|
42
|
+
`;for(const o of t){const r=Mt(o.ifcType);if(r.type!=="none"&&(s+=this.renderPolygon(o,e,r),r.type!=="solid"&&r.type!=="glass")){const a=this.hatchGenerator.generateHatch(o,i);for(const l of a.lines)s+=this.renderHatchLine(l,e,r)}}return s+=` </g>
|
|
43
|
+
`,s}renderPolygon(t,e,i){const s=this.polygonToPath(t.polygon,e);let o;return i.type==="solid"?o=i.fillColor||"#CCCCCC":i.type==="glass"?o=i.fillColor||"rgba(200, 230, 255, 0.3)":i.type==="none"?o="none":o=`url(#hatch-${i.type})`,` <path d="${s}" fill="${o}"
|
|
44
|
+
stroke="${i.strokeColor}" stroke-width="${i.lineWeight}"
|
|
45
|
+
data-entity-id="${t.entityId}" data-ifc-type="${this.escapeXml(t.ifcType)}"/>
|
|
46
|
+
`}polygonToPath(t,e){let i="";if(t.outer.length>0){const s=this.transformPoint(t.outer[0],e);i+=`M ${s.x.toFixed(3)} ${s.y.toFixed(3)}`;for(let o=1;o<t.outer.length;o++){const r=this.transformPoint(t.outer[o],e);i+=` L ${r.x.toFixed(3)} ${r.y.toFixed(3)}`}i+=" Z"}for(const s of t.holes)if(s.length>0){const o=this.transformPoint(s[0],e);i+=` M ${o.x.toFixed(3)} ${o.y.toFixed(3)}`;for(let r=1;r<s.length;r++){const a=this.transformPoint(s[r],e);i+=` L ${a.x.toFixed(3)} ${a.y.toFixed(3)}`}i+=" Z"}return i}renderHatchLine(t,e,i){const s=this.transformPoint(t.line.start,e),o=this.transformPoint(t.line.end,e);return` <line x1="${s.x.toFixed(3)}" y1="${s.y.toFixed(3)}" x2="${o.x.toFixed(3)}" y2="${o.y.toFixed(3)}"
|
|
47
|
+
stroke="${i.strokeColor}" stroke-width="${i.lineWeight}" stroke-linecap="butt"/>
|
|
48
|
+
`}createTitleBlock(t,e,i,s){const a=t.width-180-10,l=t.height-50-10;return` <g id="title-block">
|
|
49
|
+
<rect x="${a}" y="${l}" width="180" height="50"
|
|
50
|
+
fill="white" stroke="black" stroke-width="0.5"/>
|
|
51
|
+
<line x1="${a}" y1="${l+20}" x2="${a+180}" y2="${l+20}" stroke="black" stroke-width="0.3"/>
|
|
52
|
+
<line x1="${a}" y1="${l+35}" x2="${a+180}" y2="${l+35}" stroke="black" stroke-width="0.3"/>
|
|
53
|
+
<line x1="${a+100}" y1="${l+20}" x2="${a+100}" y2="${l+50}" stroke="black" stroke-width="0.3"/>
|
|
54
|
+
<text x="${a+5}" y="${l+14}" font-family="Arial" font-size="10" font-weight="bold">${this.escapeXml(e)}</text>
|
|
55
|
+
<text x="${a+5}" y="${l+30}" font-family="Arial" font-size="8">${this.escapeXml(i)}</text>
|
|
56
|
+
<text x="${a+5}" y="${l+45}" font-family="Arial" font-size="8">Scale: ${s.name}</text>
|
|
57
|
+
<text x="${a+105}" y="${l+30}" font-family="Arial" font-size="7">Date:</text>
|
|
58
|
+
<text x="${a+105}" y="${l+45}" font-family="Arial" font-size="7">${new Date().toLocaleDateString()}</text>
|
|
59
|
+
</g>
|
|
60
|
+
`}escapeXml(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}}const ue=`
|
|
61
|
+
struct Triangle {
|
|
62
|
+
v0: vec3<f32>,
|
|
63
|
+
v1: vec3<f32>,
|
|
64
|
+
v2: vec3<f32>,
|
|
65
|
+
entityId: u32,
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
struct Plane {
|
|
69
|
+
normal: vec3<f32>,
|
|
70
|
+
distance: f32,
|
|
71
|
+
// Projection axes for 2D output
|
|
72
|
+
axisU: u32, // 0=x, 1=y, 2=z
|
|
73
|
+
axisV: u32,
|
|
74
|
+
flipU: f32, // 1.0 or -1.0
|
|
75
|
+
_padding: f32,
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
struct Segment {
|
|
79
|
+
p0_3d: vec3<f32>,
|
|
80
|
+
_pad0: f32,
|
|
81
|
+
p1_3d: vec3<f32>,
|
|
82
|
+
_pad1: f32,
|
|
83
|
+
p0_2d: vec2<f32>,
|
|
84
|
+
p1_2d: vec2<f32>,
|
|
85
|
+
entityId: u32,
|
|
86
|
+
valid: u32,
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@group(0) @binding(0) var<storage, read> triangles: array<Triangle>;
|
|
90
|
+
@group(0) @binding(1) var<uniform> plane: Plane;
|
|
91
|
+
@group(0) @binding(2) var<storage, read_write> segments: array<Segment>;
|
|
92
|
+
@group(0) @binding(3) var<storage, read_write> segmentCount: atomic<u32>;
|
|
93
|
+
|
|
94
|
+
const EPSILON: f32 = 1e-7;
|
|
95
|
+
|
|
96
|
+
fn signedDistance(point: vec3<f32>) -> f32 {
|
|
97
|
+
return dot(point, plane.normal) - plane.distance;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
fn edgeIntersection(v0: vec3<f32>, v1: vec3<f32>, d0: f32, d1: f32) -> vec3<f32> {
|
|
101
|
+
let t = d0 / (d0 - d1);
|
|
102
|
+
return mix(v0, v1, t);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
fn projectTo2D(p: vec3<f32>) -> vec2<f32> {
|
|
106
|
+
var coords: array<f32, 3>;
|
|
107
|
+
coords[0] = p.x;
|
|
108
|
+
coords[1] = p.y;
|
|
109
|
+
coords[2] = p.z;
|
|
110
|
+
|
|
111
|
+
let u = coords[plane.axisU] * plane.flipU;
|
|
112
|
+
let v = coords[plane.axisV];
|
|
113
|
+
return vec2<f32>(u, v);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
@compute @workgroup_size(64)
|
|
117
|
+
fn main(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
118
|
+
let triIdx = id.x;
|
|
119
|
+
if (triIdx >= arrayLength(&triangles)) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
let tri = triangles[triIdx];
|
|
124
|
+
|
|
125
|
+
// Signed distances from plane
|
|
126
|
+
let d0 = signedDistance(tri.v0);
|
|
127
|
+
let d1 = signedDistance(tri.v1);
|
|
128
|
+
let d2 = signedDistance(tri.v2);
|
|
129
|
+
|
|
130
|
+
// Check for intersection
|
|
131
|
+
let pos = u32(d0 > EPSILON) + u32(d1 > EPSILON) + u32(d2 > EPSILON);
|
|
132
|
+
let neg = u32(d0 < -EPSILON) + u32(d1 < -EPSILON) + u32(d2 < -EPSILON);
|
|
133
|
+
|
|
134
|
+
// No intersection if all on same side
|
|
135
|
+
if (pos == 3u || neg == 3u || (pos == 0u && neg == 0u)) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Find intersection points
|
|
140
|
+
var points: array<vec3<f32>, 2>;
|
|
141
|
+
var count: u32 = 0u;
|
|
142
|
+
|
|
143
|
+
// Edge v0-v1
|
|
144
|
+
if ((d0 > EPSILON) != (d1 > EPSILON)) {
|
|
145
|
+
points[count] = edgeIntersection(tri.v0, tri.v1, d0, d1);
|
|
146
|
+
count = count + 1u;
|
|
147
|
+
} else if (abs(d0) < EPSILON) {
|
|
148
|
+
points[count] = tri.v0;
|
|
149
|
+
count = count + 1u;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Edge v1-v2
|
|
153
|
+
if ((d1 > EPSILON) != (d2 > EPSILON)) {
|
|
154
|
+
points[count] = edgeIntersection(tri.v1, tri.v2, d1, d2);
|
|
155
|
+
count = count + 1u;
|
|
156
|
+
} else if (abs(d1) < EPSILON && count < 2u) {
|
|
157
|
+
points[count] = tri.v1;
|
|
158
|
+
count = count + 1u;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Edge v2-v0
|
|
162
|
+
if (count < 2u) {
|
|
163
|
+
if ((d2 > EPSILON) != (d0 > EPSILON)) {
|
|
164
|
+
points[count] = edgeIntersection(tri.v2, tri.v0, d2, d0);
|
|
165
|
+
count = count + 1u;
|
|
166
|
+
} else if (abs(d2) < EPSILON && count < 2u) {
|
|
167
|
+
points[count] = tri.v2;
|
|
168
|
+
count = count + 1u;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (count >= 2u) {
|
|
173
|
+
// Project to 2D
|
|
174
|
+
let p0_2d = projectTo2D(points[0]);
|
|
175
|
+
let p1_2d = projectTo2D(points[1]);
|
|
176
|
+
|
|
177
|
+
// Skip degenerate segments
|
|
178
|
+
let diff = p1_2d - p0_2d;
|
|
179
|
+
if (dot(diff, diff) < EPSILON * EPSILON) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Atomically allocate output slot
|
|
184
|
+
let outIdx = atomicAdd(&segmentCount, 1u);
|
|
185
|
+
|
|
186
|
+
segments[outIdx].p0_3d = points[0];
|
|
187
|
+
segments[outIdx].p1_3d = points[1];
|
|
188
|
+
segments[outIdx].p0_2d = p0_2d;
|
|
189
|
+
segments[outIdx].p1_2d = p1_2d;
|
|
190
|
+
segments[outIdx].entityId = tri.entityId;
|
|
191
|
+
segments[outIdx].valid = 1u;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
`;class fe{device;resources=null;constructor(t){this.device=t}async initialize(t){this.resources&&(this.resources.triangleBuffer.destroy(),this.resources.planeBuffer.destroy(),this.resources.segmentBuffer.destroy(),this.resources.countBuffer.destroy(),this.resources.readbackBuffer.destroy(),this.resources.countReadbackBuffer.destroy(),this.resources=null);const e=t,i=this.device.createShaderModule({code:ue}),s=this.device.createComputePipeline({layout:"auto",compute:{module:i,entryPoint:"main"}}),o=t*48,r=this.device.createBuffer({size:o,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),a=this.device.createBuffer({size:32,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),l=e*64,c=this.device.createBuffer({size:l,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC}),u=this.device.createBuffer({size:4,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST|GPUBufferUsage.COPY_SRC}),h=this.device.createBuffer({size:l,usage:GPUBufferUsage.MAP_READ|GPUBufferUsage.COPY_DST}),d=this.device.createBuffer({size:4,usage:GPUBufferUsage.MAP_READ|GPUBufferUsage.COPY_DST}),f=this.device.createBindGroup({layout:s.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:r}},{binding:1,resource:{buffer:a}},{binding:2,resource:{buffer:c}},{binding:3,resource:{buffer:u}}]});this.resources={pipeline:s,triangleBuffer:r,planeBuffer:a,segmentBuffer:c,countBuffer:u,readbackBuffer:h,countReadbackBuffer:d,bindGroup:f,maxTriangles:t,maxSegments:e}}async cutMeshes(t,e){if(!this.resources)throw new Error("GPU resources not initialized. Call initialize() first.");const i=this.collectTriangles(t),s=i.count;if(s===0)return[];s>this.resources.maxTriangles&&await this.initialize(s*2);const o=this.resources;if(!o)throw new Error("GPU resources became unavailable after initialization");this.device.queue.writeBuffer(o.triangleBuffer,0,i.buffer.buffer,i.buffer.byteOffset,i.buffer.byteLength);const r=this.createPlaneData(e);this.device.queue.writeBuffer(o.planeBuffer,0,r.buffer,r.byteOffset,r.byteLength),this.device.queue.writeBuffer(o.countBuffer,0,new Uint32Array([0]));const a=this.device.createCommandEncoder(),l=a.beginComputePass();l.setPipeline(o.pipeline),l.setBindGroup(0,o.bindGroup);const c=Math.ceil(s/64);l.dispatchWorkgroups(c),l.end(),a.copyBufferToBuffer(o.countBuffer,0,o.countReadbackBuffer,0,4),this.device.queue.submit([a.finish()]),await o.countReadbackBuffer.mapAsync(GPUMapMode.READ);const h=new Uint32Array(o.countReadbackBuffer.getMappedRange())[0];if(o.countReadbackBuffer.unmap(),h===0)return[];const d=this.device.createCommandEncoder();d.copyBufferToBuffer(o.segmentBuffer,0,o.readbackBuffer,0,h*64),this.device.queue.submit([d.finish()]),await o.readbackBuffer.mapAsync(GPUMapMode.READ);const f=new Float32Array(o.readbackBuffer.getMappedRange(0,h*64)),g=this.parseSegments(f,h,i.entityMap);return o.readbackBuffer.unmap(),g}collectTriangles(t){let e=0;for(const a of t)e+=a.indices.length/3;const i=new Float32Array(e*12),s=new Map;let o=0,r=0;for(const a of t){const{positions:l,indices:c,expressId:u,ifcType:h,modelIndex:d}=a,f=c.length/3;s.set(r,{entityId:u,ifcType:h||"Unknown",modelIndex:d||0});for(let g=0;g<f;g++){const p=c[g*3],y=c[g*3+1],m=c[g*3+2],C=o*12;i[C+0]=l[p*3],i[C+1]=l[p*3+1],i[C+2]=l[p*3+2],i[C+4]=l[y*3],i[C+5]=l[y*3+1],i[C+6]=l[y*3+2],i[C+8]=l[m*3],i[C+9]=l[m*3+1],i[C+10]=l[m*3+2],new DataView(i.buffer,(C+11)*4,4).setUint32(0,r,!0),o++}r++}return{buffer:i,count:e,entityMap:s}}createPlaneData(t){const e=pt(t.axis),i=mt(t.axis),s={x:0,y:1,z:2},o=new Float32Array(8);o[0]=e.x,o[1]=e.y,o[2]=e.z,o[3]=t.position;const r=new DataView(o.buffer);return r.setUint32(16,s[i.u],!0),r.setUint32(20,s[i.v],!0),o[6]=t.flipped?-1:1,o[7]=0,o}parseSegments(t,e,i){const s=[];for(let o=0;o<e;o++){const r=o*16;if(new DataView(t.buffer,(r+13)*4,4).getUint32(0,!0)!==1)continue;const l=new DataView(t.buffer,(r+12)*4,4).getUint32(0,!0),c=i.get(l)||{entityId:0,ifcType:"Unknown",modelIndex:0};s.push({p0:{x:t[r+0],y:t[r+1],z:t[r+2]},p1:{x:t[r+4],y:t[r+5],z:t[r+6]},p0_2d:{x:t[r+8],y:t[r+9]},p1_2d:{x:t[r+10],y:t[r+11]},entityId:c.entityId,ifcType:c.ifcType,modelIndex:c.modelIndex})}return s}destroy(){this.resources&&(this.resources.triangleBuffer.destroy(),this.resources.planeBuffer.destroy(),this.resources.segmentBuffer.destroy(),this.resources.countBuffer.destroy(),this.resources.readbackBuffer.destroy(),this.resources.countReadbackBuffer.destroy(),this.resources=null)}}const ge={useGPU:!0,includeHiddenLines:!0,includeProjection:!0,includeEdges:!0,mergeLines:!0};class He{gpuCutter=null;cpuCutter=null;polygonBuilder=new It;edgeExtractor=new ee(30);hiddenLineClassifier=new le({resolution:1024});hatchGenerator=new Ft;svgExporter=new de;gpuDevice=null;initialized=!1;async initialize(t){t&&(this.gpuDevice=t,this.gpuCutter=new fe(t),await this.gpuCutter.initialize(1e5)),this.initialized=!0}async generate(t,e,i={},s){const o={...ge,...i},r=performance.now(),a=(x,w)=>{o.onProgress?.(x,w)};a("cutting",0);let l;o.useGPU&&this.gpuCutter&&this.gpuDevice&&!e.plane.customPlane?l=await this.gpuCutter.cutMeshes(t,e.plane):(this.cpuCutter=new Ot(e.plane),l=this.cpuCutter.cutMeshes(t).segments),a("cutting",1),a("polygons",0);const c=this.polygonBuilder.buildPolygons(l);a("polygons",1);const u=l.map(x=>({line:{start:x.p0_2d,end:x.p1_2d},category:"cut",visibility:"visible",entityId:x.entityId,ifcType:x.ifcType,modelIndex:x.modelIndex,depth:0}));let h=[];if(o.includeProjection){a("edges",0);const x={below:e.projectionBelowDepth??e.projectionDepth,above:e.projectionAboveDepth??e.projectionDepth},w=new Set;if(s&&s.length>0){for(const M of s)w.add(U(M.modelIndex,M.expressId));h.push(...ne(s,e.plane,x))}if(o.includeEdges){const M=w.size>0?t.filter(I=>!w.has(U(I.modelIndex??0,I.expressId))):t,$=Jt(e.plane);for(const I of M){const A=o.outlineProvider?o.outlineProvider(I,e.plane.axis,e.plane.flipped):null;if(A&&A.contours.length>0)h.push(...Qt(A,{entityId:I.expressId,ifcType:I.ifcType??"Unknown",modelIndex:I.modelIndex??0},e.plane,x));else{const L=this.edgeExtractor.extractEdges(I),R=this.edgeExtractor.extractSilhouettes(L,$);h.push(...this.edgeExtractor.edgesToProjectionLines(R,e.plane,x))}}}const b=this.computeBounds(u);if(b.min.x<b.max.x&&b.min.y<b.max.y){const M=b.max.x-b.min.x,$=b.max.y-b.min.y,A=Math.sqrt(M*M+$*$)*1.5;h=h.filter(L=>Rt(L.line)<=A)}a("edges",1)}let d=[...u,...h];if(o.includeHiddenLines&&h.length>0){a("hidden",0);const x=this.computeBounds(d),w=Math.max(e.projectionDepth,e.projectionBelowDepth??e.projectionDepth,e.projectionAboveDepth??e.projectionDepth);this.hiddenLineClassifier.buildDepthBuffer(t,e.plane.axis,e.plane.position,w,e.plane.flipped,x);const b=d.filter(I=>I.category!=="cut"&&I.visibility==="visible"),M=d.filter(I=>I.category!=="cut"&&I.visibility!=="visible"),$=this.hiddenLineClassifier.applyVisibility(b);d=[...u,...$,...M],a("hidden",1)}o.mergeLines&&(a("merging",0),d=Ht(d),a("merging",1));const f=this.computeBounds(d),g=performance.now()-r,p=d.filter(x=>x.category==="cut").length,y=d.filter(x=>x.category==="projection").length,m=d.filter(x=>x.visibility==="hidden").length,C=d.filter(x=>x.category==="silhouette").length;return a("complete",1),{config:e,lines:d,cutPolygons:c,projectionPolygons:[],bounds:f,stats:{cutLineCount:p,projectionLineCount:y,hiddenLineCount:m,silhouetteLineCount:C,polygonCount:c.length,totalTriangles:t.reduce((x,w)=>x+w.indices.length/3,0),processingTimeMs:g}}}exportSVG(t,e){return this.svgExporter.export(t,e)}generateHatching(t){const e=this.hatchGenerator.generateHatches(t.cutPolygons,t.config.scale),i=[];for(const s of e)for(const o of s.lines)i.push({line:o.line,category:"annotation",visibility:"visible",entityId:o.entityId,ifcType:o.ifcType,modelIndex:o.modelIndex,depth:0});return i}computeBounds(t){let e=yt();for(const i of t)e=Wt(e,i.line);return e}dispose(){this.gpuCutter&&(this.gpuCutter.destroy(),this.gpuCutter=null),this.gpuDevice=null,this.initialized=!1}}function Ue(n,t,e={}){return{plane:{axis:n,position:t,flipped:!1},...Lt,...e}}const ye={heavy:.5,medium:.35,light:.25,hairline:.18},ft={solid:[],dashed:[2,1],dotted:[.5,.5],dashdot:[3,1,.5,1],center:[6,1,1,1]},k={fillColor:"#CCCCCC",strokeColor:"#000000",backgroundColor:"#FFFFFF",lineWeight:.25,lineCap:"round",lineJoin:"round",dashPattern:[],hatchPattern:"none",hatchSpacing:3,hatchAngle:45,hatchSecondaryAngle:-45,hatchColor:"#000000",hatchLineWeight:.13,visible:!0,opacity:1,drawOrder:0},pe={IfcWall:["IfcWallStandardCase","IfcWallElementedCase"],IfcSlab:["IfcSlabStandardCase","IfcSlabElementedCase"],IfcBeam:["IfcBeamStandardCase"],IfcColumn:["IfcColumnStandardCase"],IfcDoor:["IfcDoorStandardCase"],IfcWindow:["IfcWindowStandardCase"],IfcMember:["IfcMemberStandardCase"],IfcPlate:["IfcPlateStandardCase"],IfcStair:["IfcStairFlight"],IfcRamp:["IfcRampFlight"],IfcBuildingElement:["IfcWall","IfcSlab","IfcBeam","IfcColumn","IfcDoor","IfcWindow","IfcStair","IfcRamp","IfcRoof","IfcRailing","IfcCovering"],IfcDistributionElement:["IfcDistributionFlowElement","IfcDistributionControlElement"],IfcFlowElement:["IfcFlowTerminal","IfcFlowSegment","IfcFlowFitting","IfcFlowController"]};function Pt(n){const t=pe[n]||[],e=[...t];for(const i of t)e.push(...Pt(i));return e}function me(n,t,e){switch(t){case"equals":return n===e;case"notEquals":return n!==e;case"contains":return typeof n=="string"&&typeof e=="string"?n.toLowerCase().includes(e.toLowerCase()):!1;case"notContains":return typeof n=="string"&&typeof e=="string"?!n.toLowerCase().includes(e.toLowerCase()):!0;case"startsWith":return typeof n=="string"&&typeof e=="string"?n.toLowerCase().startsWith(e.toLowerCase()):!1;case"endsWith":return typeof n=="string"&&typeof e=="string"?n.toLowerCase().endsWith(e.toLowerCase()):!1;case"greaterThan":return typeof n=="number"&&typeof e=="number"?n>e:!1;case"lessThan":return typeof n=="number"&&typeof e=="number"?n<e:!1;case"greaterOrEqual":return typeof n=="number"&&typeof e=="number"?n>=e:!1;case"lessOrEqual":return typeof n=="number"&&typeof e=="number"?n<=e:!1;case"exists":return n!=null;case"notExists":return n==null;case"in":return Array.isArray(e)?e.includes(n):!1;case"notIn":return Array.isArray(e)?!e.includes(n):!0;default:return!1}}function xe(n,t){switch(n.type){case"all":return!0;case"ifcType":return!n.ifcTypes||n.ifcTypes.length===0?!0:(n.includeSubtypes?n.ifcTypes.flatMap(i=>[i,...Pt(i)]):n.ifcTypes).some(i=>i.toLowerCase()===t.ifcType.toLowerCase());case"property":{if(!n.propertyName)return!1;const e=n.operator||"equals";let i;if(n.propertySet&&t.properties)i=t.properties[n.propertySet]?.[n.propertyName];else if(t.properties){for(const s of Object.values(t.properties))if(n.propertyName in s){i=s[n.propertyName];break}}return me(i,e,n.value)}case"propertySet":{if(!n.propertySet||!t.properties)return n.operator==="notExists";const e=n.propertySet in t.properties,i=n.operator||"exists";return i==="exists"?e:i==="notExists"?!e:e}case"material":return!n.materialNames||!t.materials?!1:n.materialNames.some(e=>t.materials.some(i=>i.toLowerCase().includes(e.toLowerCase())));case"layer":return!n.layerNames||!t.layers?!1:n.layerNames.some(e=>t.layers.some(i=>i.toLowerCase().includes(e.toLowerCase())));case"expressId":return n.expressIds?n.expressIds.includes(t.expressId):!1;case"modelId":return!n.modelIds||!t.modelId?!1:n.modelIds.includes(t.modelId);default:return!1}}function St(n){return"logic"in n&&"conditions"in n}function q(n,t){if(St(n)){const e=n.conditions.map(i=>q(i,t));return n.logic==="and"?e.every(Boolean):e.some(Boolean)}return xe(n,t)}function be(n){if(n===void 0)return k.lineWeight;if(typeof n=="number")return n;const t=ye[n];return t!==void 0?t:k.lineWeight}function Ce(n){return n===void 0?k.dashPattern:typeof n=="string"?ft[n]??k.dashPattern:n.custom?n.custom:n.preset?ft[n.preset]??k.dashPattern:k.dashPattern}function gt(n,t){return{fillColor:t.fillColor??n.fillColor,strokeColor:t.strokeColor??n.strokeColor,backgroundColor:t.backgroundColor??n.backgroundColor,lineWeight:t.lineWeight!==void 0?be(t.lineWeight):n.lineWeight,lineCap:t.lineCap??n.lineCap,lineJoin:t.lineJoin??n.lineJoin,dashPattern:t.lineStyle?Ce(t.lineStyle):n.dashPattern,hatchPattern:t.hatchPattern??n.hatchPattern,hatchSpacing:t.hatchSpacing??n.hatchSpacing,hatchAngle:t.hatchAngle??n.hatchAngle,hatchSecondaryAngle:t.hatchSecondaryAngle??n.hatchSecondaryAngle,hatchColor:t.hatchColor??n.hatchColor,hatchLineWeight:t.hatchLineWeight??n.hatchLineWeight,visible:t.visible??n.visible,opacity:t.opacity??n.opacity,drawOrder:t.drawOrder??n.drawOrder}}class $t{rules=[];constructor(t){t&&this.setRules(t)}setRules(t){this.rules=[...t].sort((e,i)=>e.priority-i.priority)}addRule(t){this.rules.push(t),this.rules.sort((e,i)=>e.priority-i.priority)}removeRule(t){this.rules=this.rules.filter(e=>e.id!==t)}getRules(){return[...this.rules]}applyOverrides(t,e){let i=e?gt(k,e):{...k};const s=[];for(const o of this.rules)o.enabled&&q(o.criteria,t)&&(i=gt(i,o.style),s.push(o));return{element:t,style:i,matchedRules:s}}applyOverridesToMany(t,e){const i=new Map;for(const s of t){const o=e?.get(s.expressId);i.set(s.expressId,this.applyOverrides(s,o))}return i}getMatchingRules(t){return this.rules.filter(e=>e.enabled&&q(e.criteria,t))}static validateCriteria(t){const e=[];if(St(t)){(!t.conditions||t.conditions.length===0)&&e.push("Compound criteria must have at least one condition");for(const i of t.conditions)e.push(...$t.validateCriteria(i))}else t.type||e.push("Criterion must have a type"),t.type==="property"&&!t.propertyName&&e.push("Property criterion requires propertyName"),t.type==="ifcType"&&(!t.ifcTypes||t.ifcTypes.length===0)&&e.push("IFC type criterion requires at least one type");return e}}function P(n,t=!0){return{type:"ifcType",ifcTypes:n,includeSubtypes:t}}function E(n,t,e,i){return{type:"property",propertyName:n,propertySet:i,operator:t,value:e}}function T(...n){return{logic:"and",conditions:n}}let Ie=0;function we(){return`builtin-rule-${++Ie}`}function F(n,t,e,i=100,s){return{id:we(),name:n,description:s,enabled:!0,priority:i,criteria:t,style:e}}const Me=[F("Walls - Heavy cut lines",P(["IfcWall"]),{lineWeight:"heavy",strokeColor:"#000000",hatchPattern:"diagonal",hatchSpacing:3,hatchAngle:45},100,"Standard wall representation"),F("Columns - Heavy cut lines",P(["IfcColumn"]),{lineWeight:"heavy",strokeColor:"#000000",hatchPattern:"cross-hatch",hatchSpacing:2},100),F("Slabs - Medium lines",P(["IfcSlab"]),{lineWeight:"medium",fillColor:"#E0E0E0",hatchPattern:"concrete"},90),F("Windows - Light blue tint",P(["IfcWindow"]),{lineWeight:"light",fillColor:"#E3F2FD",strokeColor:"#1976D2",hatchPattern:"none"},80),F("Doors - No fill",P(["IfcDoor"]),{lineWeight:"medium",fillColor:"#FFFFFF",strokeColor:"#000000",hatchPattern:"none"},80),F("Furniture - Hairline",P(["IfcFurnishingElement","IfcFurniture"]),{lineWeight:"hairline",strokeColor:"#666666",fillColor:"#F5F5F5",hatchPattern:"none"},60)],Fe={id:"preset-architectural",name:"Architectural Standards",description:"ISO 128 compliant architectural drawing standards",icon:"PenTool",rules:Me,builtIn:!0,category:"Standards"},Pe=[F("Fire Rated 2hr+ - Red",T(P(["IfcWall"]),E("FireRating","greaterOrEqual",120)),{fillColor:"#FFCDD2",strokeColor:"#C62828",lineWeight:"heavy",hatchPattern:"diagonal",hatchColor:"#C62828"},200,"2-hour or higher fire rating"),F("Fire Rated 1hr - Orange",T(P(["IfcWall"]),E("FireRating","greaterOrEqual",60)),{fillColor:"#FFE0B2",strokeColor:"#E65100",lineWeight:"heavy",hatchPattern:"diagonal",hatchColor:"#E65100"},190),F("Fire Rated 30min - Yellow",T(P(["IfcWall"]),E("FireRating","greaterOrEqual",30)),{fillColor:"#FFF9C4",strokeColor:"#F9A825",lineWeight:"medium",hatchPattern:"diagonal",hatchColor:"#F9A825"},180),F("Fire Doors - Red outline",T(P(["IfcDoor"]),E("FireRating","exists")),{strokeColor:"#C62828",lineWeight:"heavy"},200),F("Escape Routes - Green",T(P(["IfcSpace"]),E("OccupancyType","contains","CIRCULATION")),{fillColor:"#C8E6C9",strokeColor:"#2E7D32",lineWeight:"light"},150)],Se={id:"preset-fire-safety",name:"Fire Safety",description:"Highlight fire-rated elements and escape routes",icon:"Flame",rules:Pe,builtIn:!0,category:"Safety"},$e=[F("Load-bearing Walls - Blue",T(P(["IfcWall"]),E("LoadBearing","equals",!0)),{fillColor:"#BBDEFB",strokeColor:"#1565C0",lineWeight:"heavy",hatchPattern:"diagonal",hatchColor:"#1565C0"},200),F("Columns - Blue heavy",P(["IfcColumn"]),{fillColor:"#90CAF9",strokeColor:"#0D47A1",lineWeight:"heavy",hatchPattern:"cross-hatch",hatchColor:"#0D47A1"},190),F("Beams - Blue medium",P(["IfcBeam"]),{fillColor:"#64B5F6",strokeColor:"#1976D2",lineWeight:"medium",hatchPattern:"diagonal"},180),F("Slabs - Light blue",P(["IfcSlab"]),{fillColor:"#E3F2FD",strokeColor:"#42A5F5",lineWeight:"medium"},170),F("Footings - Dark blue",P(["IfcFooting","IfcPile"]),{fillColor:"#1976D2",strokeColor:"#0D47A1",lineWeight:"heavy",hatchPattern:"concrete"},200),F("Non-structural - Faded",P(["IfcFurnishingElement","IfcFurniture","IfcCovering"]),{opacity:.3,lineWeight:"hairline"},50)],Ae={id:"preset-structural",name:"Structural Highlight",description:"Emphasize structural elements, fade non-structural",icon:"Building2",rules:$e,builtIn:!0,category:"Discipline"},Le=[F("HVAC Ducts - Blue",P(["IfcDuctSegment","IfcDuctFitting"]),{fillColor:"#E3F2FD",strokeColor:"#1976D2",lineWeight:"medium"},150),F("Air Terminals - Blue",P(["IfcAirTerminal","IfcAirTerminalBox"]),{fillColor:"#BBDEFB",strokeColor:"#1565C0",lineWeight:"light"},140),F("Pipes - Green",P(["IfcPipeSegment","IfcPipeFitting"]),{fillColor:"#E8F5E9",strokeColor:"#388E3C",lineWeight:"medium"},150),F("Plumbing Fixtures - Green",P(["IfcSanitaryTerminal","IfcWasteTerminal"]),{fillColor:"#C8E6C9",strokeColor:"#2E7D32",lineWeight:"light"},140),F("Cable Trays - Orange",P(["IfcCableCarrierSegment","IfcCableCarrierFitting"]),{fillColor:"#FFF3E0",strokeColor:"#E65100",lineWeight:"light"},150),F("Electrical Equipment - Yellow",P(["IfcElectricDistributionBoard","IfcSwitchingDevice","IfcOutlet"]),{fillColor:"#FFFDE7",strokeColor:"#F9A825",lineWeight:"light"},140),F("Architectural - Faded",P(["IfcWall","IfcSlab","IfcDoor","IfcWindow"]),{opacity:.4,strokeColor:"#9E9E9E"},50)],ve={id:"preset-mep",name:"MEP Highlight",description:"Color-code mechanical, electrical, and plumbing systems",icon:"Wrench",rules:Le,builtIn:!0,category:"Discipline"},ke={id:"preset-3d-colors",name:"Default",description:"By material color",icon:"Palette",rules:[],builtIn:!0,category:"Standards"},Ee=[F("All elements - Black and white",{type:"all"},{strokeColor:"#000000",fillColor:"#FFFFFF",hatchColor:"#000000"},1),F("Cut elements - Gray fill",P(["IfcWall","IfcColumn","IfcSlab","IfcBeam"]),{fillColor:"#E0E0E0"},10)],Te={id:"preset-monochrome",name:"Monochrome",description:"Black and white print-ready output",icon:"Printer",rules:Ee,builtIn:!0,category:"Output"},je=[ke,Fe,Se,Ae,ve,Te],Ge={A0_LANDSCAPE:{id:"A0_LANDSCAPE",name:"A0 Landscape",category:"ISO",widthMm:1189,heightMm:841,orientation:"landscape",defaultMarginMm:20},A0_PORTRAIT:{id:"A0_PORTRAIT",name:"A0 Portrait",category:"ISO",widthMm:841,heightMm:1189,orientation:"portrait",defaultMarginMm:20},A1_LANDSCAPE:{id:"A1_LANDSCAPE",name:"A1 Landscape",category:"ISO",widthMm:841,heightMm:594,orientation:"landscape",defaultMarginMm:20},A1_PORTRAIT:{id:"A1_PORTRAIT",name:"A1 Portrait",category:"ISO",widthMm:594,heightMm:841,orientation:"portrait",defaultMarginMm:20},A2_LANDSCAPE:{id:"A2_LANDSCAPE",name:"A2 Landscape",category:"ISO",widthMm:594,heightMm:420,orientation:"landscape",defaultMarginMm:15},A2_PORTRAIT:{id:"A2_PORTRAIT",name:"A2 Portrait",category:"ISO",widthMm:420,heightMm:594,orientation:"portrait",defaultMarginMm:15},A3_LANDSCAPE:{id:"A3_LANDSCAPE",name:"A3 Landscape",category:"ISO",widthMm:420,heightMm:297,orientation:"landscape",defaultMarginMm:10},A3_PORTRAIT:{id:"A3_PORTRAIT",name:"A3 Portrait",category:"ISO",widthMm:297,heightMm:420,orientation:"portrait",defaultMarginMm:10},A4_LANDSCAPE:{id:"A4_LANDSCAPE",name:"A4 Landscape",category:"ISO",widthMm:297,heightMm:210,orientation:"landscape",defaultMarginMm:10},A4_PORTRAIT:{id:"A4_PORTRAIT",name:"A4 Portrait",category:"ISO",widthMm:210,heightMm:297,orientation:"portrait",defaultMarginMm:10},LETTER_LANDSCAPE:{id:"LETTER_LANDSCAPE",name:"US Letter Landscape",category:"ANSI",widthMm:279.4,heightMm:215.9,orientation:"landscape",defaultMarginMm:10},LETTER_PORTRAIT:{id:"LETTER_PORTRAIT",name:"US Letter Portrait",category:"ANSI",widthMm:215.9,heightMm:279.4,orientation:"portrait",defaultMarginMm:10},LEGAL_LANDSCAPE:{id:"LEGAL_LANDSCAPE",name:"US Legal Landscape",category:"ANSI",widthMm:355.6,heightMm:215.9,orientation:"landscape",defaultMarginMm:10},LEGAL_PORTRAIT:{id:"LEGAL_PORTRAIT",name:"US Legal Portrait",category:"ANSI",widthMm:215.9,heightMm:355.6,orientation:"portrait",defaultMarginMm:10},TABLOID_LANDSCAPE:{id:"TABLOID_LANDSCAPE",name:"US Tabloid Landscape",category:"ANSI",widthMm:431.8,heightMm:279.4,orientation:"landscape",defaultMarginMm:15},TABLOID_PORTRAIT:{id:"TABLOID_PORTRAIT",name:"US Tabloid Portrait",category:"ANSI",widthMm:279.4,heightMm:431.8,orientation:"portrait",defaultMarginMm:15},ANSI_C:{id:"ANSI_C",name:"ANSI C (17x22)",category:"ANSI",widthMm:558.8,heightMm:431.8,orientation:"landscape",defaultMarginMm:15},ANSI_D:{id:"ANSI_D",name:"ANSI D (22x34)",category:"ANSI",widthMm:863.6,heightMm:558.8,orientation:"landscape",defaultMarginMm:20},ANSI_E:{id:"ANSI_E",name:"ANSI E (34x44)",category:"ANSI",widthMm:1117.6,heightMm:863.6,orientation:"landscape",defaultMarginMm:20},ARCH_A:{id:"ARCH_A",name:"ARCH A (9x12)",category:"ARCH",widthMm:304.8,heightMm:228.6,orientation:"landscape",defaultMarginMm:10},ARCH_B:{id:"ARCH_B",name:"ARCH B (12x18)",category:"ARCH",widthMm:457.2,heightMm:304.8,orientation:"landscape",defaultMarginMm:15},ARCH_C:{id:"ARCH_C",name:"ARCH C (18x24)",category:"ARCH",widthMm:609.6,heightMm:457.2,orientation:"landscape",defaultMarginMm:15},ARCH_D:{id:"ARCH_D",name:"ARCH D (24x36)",category:"ARCH",widthMm:914.4,heightMm:609.6,orientation:"landscape",defaultMarginMm:20},ARCH_E:{id:"ARCH_E",name:"ARCH E (36x48)",category:"ARCH",widthMm:1219.2,heightMm:914.4,orientation:"landscape",defaultMarginMm:20},ARCH_E1:{id:"ARCH_E1",name:"ARCH E1 (30x42)",category:"ARCH",widthMm:1066.8,heightMm:762,orientation:"landscape",defaultMarginMm:20}},Ve={simple:{margins:{top:10,right:10,bottom:10,left:10,bindingMargin:0},border:{outerLineWeight:.7,innerLineWeight:.35,borderGap:0,showFoldMarks:!1,showTrimMarks:!1},showZoneReferences:!1,horizontalZones:0,verticalZones:0,zoneFontSize:3},professional:{margins:{top:10,right:10,bottom:10,left:20,bindingMargin:10},border:{outerLineWeight:.7,innerLineWeight:.35,borderGap:5,showFoldMarks:!0,showTrimMarks:!0},showZoneReferences:!0,horizontalZones:8,verticalZones:6,zoneFontSize:3.5},minimal:{margins:{top:5,right:5,bottom:5,left:5,bindingMargin:0},border:{outerLineWeight:.35,innerLineWeight:0,borderGap:0,showFoldMarks:!1,showTrimMarks:!1},showZoneReferences:!1,horizontalZones:0,verticalZones:0,zoneFontSize:3},iso:{margins:{top:10,right:10,bottom:10,left:20,bindingMargin:10},border:{outerLineWeight:.7,innerLineWeight:.35,borderGap:5,showFoldMarks:!0,showTrimMarks:!0},showZoneReferences:!0,horizontalZones:8,verticalZones:4,zoneFontSize:3.5},custom:{margins:{top:10,right:10,bottom:10,left:10,bindingMargin:0},border:{outerLineWeight:.5,innerLineWeight:.25,borderGap:3,showFoldMarks:!1,showTrimMarks:!1},showZoneReferences:!1,horizontalZones:0,verticalZones:0,zoneFontSize:3}},Ye=[{id:"project-name",label:"Project",value:"",editable:!0,autoPopulate:!0,autoPopulateSource:"project.name",fontSize:4.5,fontWeight:"bold",row:0,col:0,colSpan:2},{id:"drawing-title",label:"Drawing Title",value:"Section",editable:!0,autoPopulate:!1,fontSize:5,fontWeight:"bold",row:1,col:0,colSpan:2},{id:"drawing-number",label:"Drawing No.",value:"A-001",editable:!0,autoPopulate:!1,fontSize:4,fontWeight:"bold",row:2,col:0},{id:"revision",label:"Rev",value:"-",editable:!0,autoPopulate:!1,fontSize:3.5,fontWeight:"bold",row:2,col:1},{id:"scale",label:"Scale",value:"1:100",editable:!1,autoPopulate:!0,autoPopulateSource:"drawing.scale",fontSize:3.5,fontWeight:"normal",row:3,col:0},{id:"date",label:"Date",value:"",editable:!0,autoPopulate:!0,autoPopulateSource:"date.today",fontSize:3,fontWeight:"normal",row:3,col:1},{id:"drawn-by",label:"Drawn",value:"",editable:!0,autoPopulate:!1,fontSize:3,fontWeight:"normal",row:4,col:0},{id:"checked-by",label:"Checked",value:"",editable:!0,autoPopulate:!1,fontSize:3,fontWeight:"normal",row:4,col:1},{id:"sheet-number",label:"Sheet",value:"1 of 1",editable:!0,autoPopulate:!1,fontSize:3,fontWeight:"normal",row:5,col:0,colSpan:2}],Xe={compact:{layout:"compact",position:"bottom-right",widthMm:120,heightMm:35,borderWeight:.5,gridWeight:.25,showRevisionHistory:!1,maxRevisionEntries:0},standard:{layout:"standard",position:"bottom-right",widthMm:180,heightMm:55,borderWeight:.5,gridWeight:.25,showRevisionHistory:!0,maxRevisionEntries:3},extended:{layout:"extended",position:"bottom-full",widthMm:0,heightMm:70,borderWeight:.5,gridWeight:.25,showRevisionHistory:!0,maxRevisionEntries:5},custom:{layout:"custom",position:"bottom-right",widthMm:180,heightMm:55,borderWeight:.5,gridWeight:.25,showRevisionHistory:!1,maxRevisionEntries:0}},qe={visible:!0,style:"alternating",position:"below-viewport",units:"metric",totalLengthM:5,primaryDivisions:5,subdivisions:2,heightMm:3,labelFontSize:2.5,showUnitLabel:!0,fillColor:"#000000",strokeColor:"#000000",lineWeight:.25};function Ze(n,t){const i=Math.min(80,t*.8)*n/1e3,s=[.1,.2,.5,1,2,5,10,20,50,100,200,500,1e3];for(const o of s)if(o>=i*.5&&o<=i*1.5)return o;return Math.round(i)}const Je={style:"simple",rotation:0,positionMm:{x:30,y:30},sizeMm:15};function Ke(n,t,e){const i=t.margins.left+t.margins.bindingMargin+t.border.borderGap,s=n.widthMm-t.margins.right-t.border.borderGap,o=t.margins.top+t.border.borderGap,r=n.heightMm-t.margins.bottom-t.border.borderGap;let a=i,l=o,c=s-i,u=r-o;const h=5;switch(e.position){case"bottom-right":u=r-o-e.heightMm-h;break;case"bottom-full":u=r-o-e.heightMm-h;break;case"right-strip":c=s-i-e.widthMm-h;break}return{x:a,y:l,width:c,height:u}}function Qe(n,t,e){const i=n.maxX-n.minX,s=n.maxY-n.minY,o=1e3/e.factor,r=i*o,a=s*o,l=.95,c=t.width*l/r,u=t.height*l/a,h=Math.min(c,u,1),d=o*h,f=i*d,g=s*d,p=t.x+(t.width-f)/2-n.minX*d,y=t.y+(t.height-g)/2+n.maxY*d;return{translateX:p,translateY:y,scaleFactor:d}}function tn(n,t){let e=` <g id="drawing-frame">
|
|
195
|
+
`;const i=t.margins.left+t.margins.bindingMargin,s=t.margins.top,o=n.widthMm-t.margins.left-t.margins.right-t.margins.bindingMargin,r=n.heightMm-t.margins.top-t.margins.bottom;e+=` <rect x="${i.toFixed(2)}" y="${s.toFixed(2)}" `,e+=`width="${o.toFixed(2)}" height="${r.toFixed(2)}" `,e+=`fill="none" stroke="#000000" stroke-width="${t.border.outerLineWeight}"/>
|
|
196
|
+
`;let a=i,l=s,c=o,u=r;return t.border.borderGap>0&&t.border.innerLineWeight>0&&(a=i+t.border.borderGap,l=s+t.border.borderGap,c=o-2*t.border.borderGap,u=r-2*t.border.borderGap,e+=` <rect x="${a.toFixed(2)}" y="${l.toFixed(2)}" `,e+=`width="${c.toFixed(2)}" height="${u.toFixed(2)}" `,e+=`fill="none" stroke="#000000" stroke-width="${t.border.innerLineWeight}"/>
|
|
197
|
+
`),t.showZoneReferences&&t.horizontalZones>0&&(e+=De(i,s,o,r,t.border.borderGap,t.horizontalZones,t.verticalZones,t.zoneFontSize,t.border.innerLineWeight)),t.border.showFoldMarks&&(e+=Re(n)),t.border.showTrimMarks&&(e+=We(n)),e+=` </g>
|
|
198
|
+
`,{svgElements:e,innerBounds:{x:a,y:l,width:c,height:u}}}function De(n,t,e,i,s,o,r,a,l){let c=` <g id="zone-references">
|
|
199
|
+
`;const u=e/o,h=i/r,d="ABCDEFGHIJKLMNOPQRSTUVWXYZ";for(let f=0;f<o;f++){const g=n+u*(f+.5),p=d[f%26];if(c+=` <text x="${g.toFixed(2)}" y="${(t-s/2).toFixed(2)}" `,c+=`font-family="Arial, sans-serif" font-size="${a}" `,c+=`text-anchor="middle" dominant-baseline="middle">${p}</text>
|
|
200
|
+
`,c+=` <text x="${g.toFixed(2)}" y="${(t+i+s/2).toFixed(2)}" `,c+=`font-family="Arial, sans-serif" font-size="${a}" `,c+=`text-anchor="middle" dominant-baseline="middle">${p}</text>
|
|
201
|
+
`,f>0){const y=n+u*f;c+=` <line x1="${y.toFixed(2)}" y1="${t.toFixed(2)}" `,c+=`x2="${y.toFixed(2)}" y2="${(t-s+2).toFixed(2)}" `,c+=`stroke="#000000" stroke-width="${l}"/>
|
|
202
|
+
`,c+=` <line x1="${y.toFixed(2)}" y1="${(t+i).toFixed(2)}" `,c+=`x2="${y.toFixed(2)}" y2="${(t+i+s-2).toFixed(2)}" `,c+=`stroke="#000000" stroke-width="${l}"/>
|
|
203
|
+
`}}for(let f=0;f<r;f++){const g=t+h*(f+.5),p=(f+1).toString();if(c+=` <text x="${(n-s/2).toFixed(2)}" y="${g.toFixed(2)}" `,c+=`font-family="Arial, sans-serif" font-size="${a}" `,c+=`text-anchor="middle" dominant-baseline="middle">${p}</text>
|
|
204
|
+
`,c+=` <text x="${(n+e+s/2).toFixed(2)}" y="${g.toFixed(2)}" `,c+=`font-family="Arial, sans-serif" font-size="${a}" `,c+=`text-anchor="middle" dominant-baseline="middle">${p}</text>
|
|
205
|
+
`,f>0){const y=t+h*f;c+=` <line x1="${n.toFixed(2)}" y1="${y.toFixed(2)}" `,c+=`x2="${(n-s+2).toFixed(2)}" y2="${y.toFixed(2)}" `,c+=`stroke="#000000" stroke-width="${l}"/>
|
|
206
|
+
`,c+=` <line x1="${(n+e).toFixed(2)}" y1="${y.toFixed(2)}" `,c+=`x2="${(n+e+s-2).toFixed(2)}" y2="${y.toFixed(2)}" `,c+=`stroke="#000000" stroke-width="${l}"/>
|
|
207
|
+
`}}return c+=` </g>
|
|
208
|
+
`,c}function Re(n,t,e,i,s){let o=` <g id="fold-marks">
|
|
209
|
+
`;if(n.heightMm>297){const u=Math.ceil(n.heightMm/297);for(let h=1;h<u;h++){const d=h*297;d<n.heightMm-20&&(o+=` <line x1="0" y1="${d.toFixed(2)}" x2="${5 .toFixed(2)}" y2="${d.toFixed(2)}" `,o+=`stroke="#000000" stroke-width="${.25}"/>
|
|
210
|
+
`,o+=` <line x1="${(n.widthMm-5).toFixed(2)}" y1="${d.toFixed(2)}" `,o+=`x2="${n.widthMm.toFixed(2)}" y2="${d.toFixed(2)}" `,o+=`stroke="#000000" stroke-width="${.25}"/>
|
|
211
|
+
`)}}if(n.widthMm>210){const u=Math.ceil(n.widthMm/210);for(let h=1;h<u;h++){const d=n.widthMm-h*210;d>20&&(o+=` <line x1="${d.toFixed(2)}" y1="0" x2="${d.toFixed(2)}" y2="${5 .toFixed(2)}" `,o+=`stroke="#000000" stroke-width="${.25}"/>
|
|
212
|
+
`,o+=` <line x1="${d.toFixed(2)}" y1="${(n.heightMm-5).toFixed(2)}" `,o+=`x2="${d.toFixed(2)}" y2="${n.heightMm.toFixed(2)}" `,o+=`stroke="#000000" stroke-width="${.25}"/>
|
|
213
|
+
`)}}return o+=` </g>
|
|
214
|
+
`,o}function We(n){let t=` <g id="trim-marks">
|
|
215
|
+
`;return t+=` <line x1="${3 .toFixed(2)}" y1="0" x2="${3 .toFixed(2)}" y2="${8 .toFixed(2)}" `,t+=`stroke="#000000" stroke-width="${.15}"/>
|
|
216
|
+
`,t+=` <line x1="0" y1="${3 .toFixed(2)}" x2="${8 .toFixed(2)}" y2="${3 .toFixed(2)}" `,t+=`stroke="#000000" stroke-width="${.15}"/>
|
|
217
|
+
`,t+=` <line x1="${(n.widthMm-3).toFixed(2)}" y1="0" `,t+=`x2="${(n.widthMm-3).toFixed(2)}" y2="${8 .toFixed(2)}" `,t+=`stroke="#000000" stroke-width="${.15}"/>
|
|
218
|
+
`,t+=` <line x1="${(n.widthMm-8).toFixed(2)}" y1="${3 .toFixed(2)}" `,t+=`x2="${n.widthMm.toFixed(2)}" y2="${3 .toFixed(2)}" `,t+=`stroke="#000000" stroke-width="${.15}"/>
|
|
219
|
+
`,t+=` <line x1="${3 .toFixed(2)}" y1="${(n.heightMm-8).toFixed(2)}" `,t+=`x2="${3 .toFixed(2)}" y2="${n.heightMm.toFixed(2)}" `,t+=`stroke="#000000" stroke-width="${.15}"/>
|
|
220
|
+
`,t+=` <line x1="0" y1="${(n.heightMm-3).toFixed(2)}" `,t+=`x2="${8 .toFixed(2)}" y2="${(n.heightMm-3).toFixed(2)}" `,t+=`stroke="#000000" stroke-width="${.15}"/>
|
|
221
|
+
`,t+=` <line x1="${(n.widthMm-3).toFixed(2)}" y1="${(n.heightMm-8).toFixed(2)}" `,t+=`x2="${(n.widthMm-3).toFixed(2)}" y2="${n.heightMm.toFixed(2)}" `,t+=`stroke="#000000" stroke-width="${.15}"/>
|
|
222
|
+
`,t+=` <line x1="${(n.widthMm-8).toFixed(2)}" y1="${(n.heightMm-3).toFixed(2)}" `,t+=`x2="${n.widthMm.toFixed(2)}" y2="${(n.heightMm-3).toFixed(2)}" `,t+=`stroke="#000000" stroke-width="${.15}"/>
|
|
223
|
+
`,t+=` </g>
|
|
224
|
+
`,t}function en(n,t,e=[],i){let s,o,r,a;switch(n.position){case"bottom-right":r=n.widthMm,a=n.heightMm,s=t.x+t.width-r,o=t.y+t.height-a;break;case"bottom-full":r=t.width,a=n.heightMm,s=t.x,o=t.y+t.height-a;break;case"right-strip":r=n.widthMm,a=t.height,s=t.x+t.width-r,o=t.y;break;default:r=n.widthMm,a=n.heightMm,s=t.x+t.width-r,o=t.y+t.height-a}let l=` <g id="title-block">
|
|
225
|
+
`;return n.backgroundColor&&(l+=` <rect x="${s.toFixed(2)}" y="${o.toFixed(2)}" `,l+=`width="${r.toFixed(2)}" height="${a.toFixed(2)}" `,l+=`fill="${n.backgroundColor}"/>
|
|
226
|
+
`),l+=` <rect x="${s.toFixed(2)}" y="${o.toFixed(2)}" `,l+=`width="${r.toFixed(2)}" height="${a.toFixed(2)}" `,l+=`fill="none" stroke="#000000" stroke-width="${n.borderWeight}"/>
|
|
227
|
+
`,l+=ze(n,s,o,r,a),n.logo?.source&&(l+=_e(n.logo,s,o,r,a)),i?.scaleBar?.visible&&i?.scale&&a>10&&(l+=Ne(i.scaleBar,i.scale,s,o,r,a,n.logo!=null,i.effectiveScaleFactor)),i?.northArrow&&i.northArrow.style!=="none"&&a>15&&(l+=Oe(i.northArrow,s,o,r,a,n.logo!=null,n.position)),n.showRevisionHistory&&e.length>0&&(l+=Be(e.slice(0,n.maxRevisionEntries),s,o,r,a,n)),l+=` </g>
|
|
228
|
+
`,{svgElements:l,bounds:{x:s,y:o,width:r,height:a}}}function ze(n,t,e,i,s){let o=` <g id="title-block-fields">
|
|
229
|
+
`;const a=n.logo?50:0,l=n.showRevisionHistory?20:0,c=i-a-5,u=s-l-4,h=new Map;for(const b of n.fields){const M=b.row??0;h.has(M)||h.set(M,[]),h.get(M).push(b)}const d=Math.max(...Array.from(h.keys()))+1,f=[];let g=0;for(let b=0;b<d;b++){const M=h.get(b)||[],$=M.length>0?Math.max(...M.map(L=>L.fontSize)):3,A=Math.min($*.5,2.2)+1+$+2;f.push(A),g+=A}const p=g>u?u/g:1,y=f.map(b=>b*p),m=t+a+2,C=e+2,x=c/2,w=[C];for(let b=0;b<y.length-1;b++)w.push(w[b]+y[b]);for(let b=1;b<d;b++){const M=w[b];o+=` <line x1="${m.toFixed(2)}" y1="${M.toFixed(2)}" `,o+=`x2="${(m+c-4).toFixed(2)}" y2="${M.toFixed(2)}" `,o+=`stroke="#000000" stroke-width="${n.gridWeight}"/>
|
|
230
|
+
`}for(const[b,M]of h)if(M.some(I=>(I.colSpan??1)<2)){const I=m+x,A=w[b],L=w[b]+y[b];o+=` <line x1="${I.toFixed(2)}" y1="${A.toFixed(2)}" `,o+=`x2="${I.toFixed(2)}" y2="${L.toFixed(2)}" `,o+=`stroke="#000000" stroke-width="${n.gridWeight}"/>
|
|
231
|
+
`}for(const[b,M]of h){const $=w[b];y[b];for(const I of M){const A=I.col??0;I.colSpan;const L=m+A*x+1.5,R=p<1?p:1,tt=Math.min(I.fontSize*.45,2.2)*Math.max(R,.7),et=I.fontSize*Math.max(R,.7),nt=$+.5+tt;o+=` <text x="${L.toFixed(2)}" y="${nt.toFixed(2)}" `,o+=`font-family="Arial, sans-serif" font-size="${tt.toFixed(2)}" `,o+=`fill="#666666">${B(I.label)}</text>
|
|
232
|
+
`;const At=nt+.8+et*.8;o+=` <text x="${L.toFixed(2)}" y="${At.toFixed(2)}" `,o+=`font-family="Arial, sans-serif" font-size="${et.toFixed(2)}" `,o+=`font-weight="${I.fontWeight}" fill="#000000">${B(I.value)}</text>
|
|
233
|
+
`}}return o+=` </g>
|
|
234
|
+
`,o}function _e(n,t,e,i,s){let o=` <g id="title-block-logo">
|
|
235
|
+
`,r,a;switch(n.position){case"top-left":r=t+3,a=e+3;break;case"top-right":r=t+i-n.widthMm-3,a=e+3;break;case"bottom-left":default:r=t+3,a=e+s-n.heightMm-3;break}return o+=` <image x="${r.toFixed(2)}" y="${a.toFixed(2)}" `,o+=`width="${n.widthMm.toFixed(2)}" height="${n.heightMm.toFixed(2)}" `,o+=`href="${B(n.source)}" preserveAspectRatio="xMidYMid meet"/>
|
|
236
|
+
`,o+=` </g>
|
|
237
|
+
`,o}function Be(n,t,e,i,s,o){let r=` <g id="revision-history">
|
|
238
|
+
`;const l=e-18-2,c=4,u=2.2;r+=` <rect x="${t.toFixed(2)}" y="${l.toFixed(2)}" `,r+=`width="${i.toFixed(2)}" height="${18 .toFixed(2)}" `,r+=`fill="none" stroke="#000000" stroke-width="${o.gridWeight}"/>
|
|
239
|
+
`;const h=[{label:"REV",width:i*.1},{label:"DESCRIPTION",width:i*.5},{label:"DATE",width:i*.2},{label:"BY",width:i*.2}];let d=t;for(const f of h)r+=` <text x="${(d+1).toFixed(2)}" y="${(l+3).toFixed(2)}" `,r+=`font-family="Arial, sans-serif" font-size="${u}" `,r+=`font-weight="bold" fill="#000000">${f.label}</text>
|
|
240
|
+
`,d>t&&(r+=` <line x1="${d.toFixed(2)}" y1="${l.toFixed(2)}" `,r+=`x2="${d.toFixed(2)}" y2="${(l+18).toFixed(2)}" `,r+=`stroke="#000000" stroke-width="${o.gridWeight}"/>
|
|
241
|
+
`),d+=f.width;r+=` <line x1="${t.toFixed(2)}" y1="${(l+c).toFixed(2)}" `,r+=`x2="${(t+i).toFixed(2)}" y2="${(l+c).toFixed(2)}" `,r+=`stroke="#000000" stroke-width="${o.gridWeight}"/>
|
|
242
|
+
`;for(let f=0;f<n.length&&f<o.maxRevisionEntries;f++){const g=n[f],p=l+c*(f+1.5);d=t;const y=[g.revision,g.description,g.date,g.author];for(let m=0;m<h.length;m++){const C=Math.floor(h[m].width/2),x=y[m].length>C?y[m].substring(0,C-2)+"..":y[m];r+=` <text x="${(d+1).toFixed(2)}" y="${p.toFixed(2)}" `,r+=`font-family="Arial, sans-serif" font-size="${u}" `,r+=`fill="#000000">${B(x)}</text>
|
|
243
|
+
`,d+=h[m].width}f<n.length-1&&(r+=` <line x1="${t.toFixed(2)}" y1="${(l+c*(f+2)).toFixed(2)}" `,r+=`x2="${(t+i).toFixed(2)}" y2="${(l+c*(f+2)).toFixed(2)}" `,r+=`stroke="#000000" stroke-width="${o.gridWeight*.5}"/>
|
|
244
|
+
`)}return r+=` </g>
|
|
245
|
+
`,r}function Ne(n,t,e,i,s,o,r,a){let l=` <g id="title-block-scale-bar">
|
|
246
|
+
`;const c=a??t.factor,u=e+3,h=i+o-8,d=Math.min(s*.3,50),f=n.totalLengthM*1e3/c,g=Math.min(f,d),p=Math.min(n.heightMm,3),y=g*c/1e3,m=n.primaryDivisions,C=g/m;for(let M=0;M<m;M++){const $=u+M*C,I=M%2===0?n.fillColor:"#ffffff";l+=` <rect x="${$.toFixed(2)}" y="${h.toFixed(2)}" `,l+=`width="${C.toFixed(2)}" height="${p.toFixed(2)}" `,l+=`fill="${I}" stroke="${n.strokeColor}" stroke-width="${n.lineWeight}"/>
|
|
247
|
+
`}const x=1.8,w=h+p+x+.3;l+=` <text x="${u.toFixed(2)}" y="${w.toFixed(2)}" `,l+=`font-family="Arial, sans-serif" font-size="${x}" `,l+=`text-anchor="start" fill="#000000">0</text>
|
|
248
|
+
`;const b=y<1?`${(y*100).toFixed(0)}cm`:`${y.toFixed(0)}m`;return l+=` <text x="${(u+g).toFixed(2)}" y="${w.toFixed(2)}" `,l+=`font-family="Arial, sans-serif" font-size="${x}" `,l+=`text-anchor="end" fill="#000000">${b}</text>
|
|
249
|
+
`,l+=` </g>
|
|
250
|
+
`,l}function Oe(n,t,e,i,s,o,r){let a=` <g id="title-block-north-arrow">
|
|
251
|
+
`;const l=Math.min(n.sizeMm,8,s*.6),c=t+i-l-5,u=e+s-l/2-3,h=n.rotation;a+=` <g transform="translate(${c.toFixed(2)}, ${u.toFixed(2)}) rotate(${h})">
|
|
252
|
+
`;const d=l/2;a+=` <polygon points="0,${(-d).toFixed(2)} ${(-d/3).toFixed(2)},${(d/2).toFixed(2)} ${(d/3).toFixed(2)},${(d/2).toFixed(2)}" `,a+=`fill="#000000" stroke="none"/>
|
|
253
|
+
`,a+=` <polygon points="0,${(d/3).toFixed(2)} ${(-d/3).toFixed(2)},${(d/2).toFixed(2)} ${(d/3).toFixed(2)},${(d/2).toFixed(2)}" `,a+=`fill="#ffffff" stroke="#000000" stroke-width="0.25"/>
|
|
254
|
+
`;const f=l*.4;return a+=` <text x="0" y="${(-d-1).toFixed(2)}" `,a+=`font-family="Arial, sans-serif" font-size="${f.toFixed(2)}" font-weight="bold" `,a+=`text-anchor="middle" fill="#000000">N</text>
|
|
255
|
+
`,a+=` </g>
|
|
256
|
+
`,a+=` </g>
|
|
257
|
+
`,a}function B(n){return n.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}export{je as B,H as C,Je as D,Ve as F,$t as G,Ge as P,Xe as T,qe as a,Ye as b,He as c,Qe as d,Ze as e,Ke as f,Ue as g,en as h,tn as r};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const q="ASTM-E57";function Q(t){if(t.length<48)throw new Error("E57: header truncated (need 48 bytes)");const e=String.fromCharCode(...t.subarray(0,8));if(e!==q)throw new Error(`E57: bad magic "${e}" (expected "${q}")`);const n=new DataView(t.buffer,t.byteOffset,t.byteLength);return{majorVersion:n.getUint32(8,!0),minorVersion:n.getUint32(12,!0),fileLogicalSize:P(n,16),xmlLogicalOffset:R(P(n,24),P(n,40)),xmlLogicalLength:P(n,32),pageSize:P(n,40)}}function tt(t,e){if(e<=4)throw new Error("E57: pageSize too small");const n=e-4,o=Math.floor(t.length/e),r=t.length-o*e,s=new Uint8Array(o*n+Math.max(0,r-4));let i=0;for(let l=0;l<o;l++){const c=l*e;s.set(t.subarray(c,c+n),i),i+=n}if(r>4){const l=o*e;s.set(t.subarray(l,l+r-4),i)}return s}function R(t,e){const n=e-4,o=Math.floor(t/e),r=t-o*e;return o*n+r}function nt(t,e,n){const o=R(e,n);if(o+32>t.length)throw new Error(`E57: CompressedVector section header at logical ${o} runs past end of file (length ${t.length})`);const r=new DataView(t.buffer,t.byteOffset+o,32),s=r.getUint8(0);if(s!==1)throw new Error(`E57: expected CompressedVector section (id=1) at physical ${e}, got id=${s}`);const i=P(r,16);return R(i,n)}function P(t,e){const n=t.getUint32(e,!0);return t.getUint32(e+4,!0)*4294967296+n}function et(t){const e={name:"",attrs:new Map,children:[],text:""},n=[e];let o=0;const r=t.length;let s=-1;const i=l=>{if(s<0||s>=l){s=-1;return}const c=t.slice(s,l).trim();if(c.length>0){const u=n[n.length-1];u.children.length===0&&(u.text=u.text+G(c))}s=-1};for(;o<r;){if(t.charCodeAt(o)!==60){s<0&&(s=o),o++;continue}if(i(o),t.startsWith("<?",o)){const a=t.indexOf("?>",o+2);o=a<0?r:a+2;continue}if(t.startsWith("<!--",o)){const a=t.indexOf("-->",o+4);o=a<0?r:a+3;continue}if(t.startsWith("<![CDATA[",o)){const a=t.indexOf("]]>",o+9),b=t.slice(o+9,a<0?r:a),w=n[n.length-1];w.children.length===0&&(w.text=w.text+b),o=a<0?r:a+3;continue}if(t.startsWith("<!",o)){const a=t.indexOf(">",o+2);o=a<0?r:a+1;continue}if(t.charCodeAt(o+1)===47){const a=t.indexOf(">",o+2);if(a<0)throw new Error("XML: unterminated closing tag");const b=t.slice(o+2,a).trim(),w=n[n.length-1];if(w.name!==b)throw new Error(`XML: mismatched closing tag </${b}> (expected </${w.name}>)`);n.pop(),o=a+1;continue}const c=ot(t,o+1);if(c<0)throw new Error("XML: unterminated tag");let u=t.slice(o+1,c).trim(),d=!1;u.endsWith("/")&&(d=!0,u=u.slice(0,-1).trim());const p=u.match(/^([A-Za-z_][\w:.\-]*)/);if(!p){o=c+1;continue}const g=p[1],f=u.slice(g.length).trim(),m=rt(f),h={name:g,attrs:m,children:[],text:""};n.length===1&&e.name===""?(e.name=g,e.attrs=m,d||n.push(e)):(n[n.length-1].children.push(h),d||n.push(h)),o=c+1}if(i(r),n.length!==1)throw new Error(`XML: unclosed tag <${n[n.length-1].name}>`);if(e.name==="")throw new Error("XML: missing root element");return e}function ot(t,e){let n=!1;for(let o=e;o<t.length;o++){const r=t.charCodeAt(o);if(r===34)n=!n;else if(r===62&&!n)return o}return-1}const W=/([A-Za-z_][\w:.\-]*)\s*=\s*"([^"]*)"/g;function rt(t){const e=new Map;if(!t)return e;let n;for(W.lastIndex=0;(n=W.exec(t))!==null;)e.set(n[1],G(n[2]));return e}function G(t){return t.indexOf("&")<0?t:t.replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'").replace(/&#(\d+);/g,(e,n)=>String.fromCharCode(parseInt(n,10))).replace(/&#x([0-9a-fA-F]+);/g,(e,n)=>String.fromCharCode(parseInt(n,16))).replace(/&/g,"&")}function N(t,e){for(const n of t.children)if(n.name===e)return n;return null}function st(t,e){return t.children.filter(n=>n.name===e)}function A(t,e){const n=N(t,e);if(!n)return null;const o=n.text.trim();return o.length>0?o:null}function it(t){const e=et(t);if(e.name!=="e57Root")throw new Error(`E57: XML root is not <e57Root> (saw <${e.name||"?"}>)`);const n=N(e,"data3D");if(!n)return[];const o=[];for(const r of st(n,"vectorChild")){const s=N(r,"points");if(!s||s.attrs.get("type")!=="CompressedVector")continue;const i=s.attrs.get("fileOffset"),l=s.attrs.get("recordCount");if(!i||!l)continue;const c=Number(i),u=Number(l);if(!Number.isFinite(c)||c<0||!Number.isFinite(u)||u<0)continue;const d=N(s,"prototype");if(!d)continue;const p=[];for(const g of d.children){const f=g.attrs.get("type")??"";f==="Float"?p.push({name:g.name,kind:"Float",precision:g.attrs.get("precision")==="single"?"single":"double"}):f==="ScaledInteger"?p.push({name:g.name,kind:"ScaledInteger",scale:Number(g.attrs.get("scale")??"1"),offset:Number(g.attrs.get("offset")??"0"),minimum:Number(g.attrs.get("minimum")??"0"),maximum:Number(g.attrs.get("maximum")??"0")}):f==="Integer"&&p.push({name:g.name,kind:"Integer",minimum:Number(g.attrs.get("minimum")??"0"),maximum:Number(g.attrs.get("maximum")??"0")})}o.push({guid:A(r,"guid")??"",name:A(r,"name")??void 0,recordCount:u,binaryFileOffset:c,prototype:p,pose:at(N(r,"pose"))??void 0})}return o}function at(t){if(!t)return null;const e=N(t,"rotation"),n=N(t,"translation");if(!e||!n)return null;const o=Number(A(e,"w")??"1"),r=Number(A(e,"x")??"0"),s=Number(A(e,"y")??"0"),i=Number(A(e,"z")??"0"),l=Number(A(n,"x")??"0"),c=Number(A(n,"y")??"0"),u=Number(A(n,"z")??"0");return[o,r,s,i,l,c,u].every(Number.isFinite)?{rotation:{w:o,x:r,y:s,z:i},translation:{x:l,y:c,z:u}}:null}function U(t,e){return t.find(n=>n.name===e)}function ct(t,e){const n=U(e.prototype,"cartesianX"),o=U(e.prototype,"cartesianY"),r=U(e.prototype,"cartesianZ");if(!n||!o||!r)throw new Error("E57: prototype missing cartesianX/Y/Z");for(const w of[n,o,r])if(w.kind==="Integer")throw new Error(`E57: cartesian${w.name.slice(-1)} encoded as plain Integer (only Float / ScaledInteger supported)`);const s=U(e.prototype,"colorRed"),i=U(e.prototype,"colorGreen"),l=U(e.prototype,"colorBlue"),c=!!(s&&i&&l),u=U(e.prototype,"intensity"),d=U(e.prototype,"classification"),p=new Float32Array(e.recordCount*3),g=c?new Float32Array(e.recordCount*3):void 0,f=u&&(u.kind==="Float"||u.kind==="Integer"||u.kind==="ScaledInteger")?new Uint16Array(e.recordCount):void 0,m=d&&(d.kind==="Integer"||d.kind==="ScaledInteger")?new Uint8Array(e.recordCount):void 0;let h=e.binaryFileOffset;const a=new DataView(t.buffer,t.byteOffset,t.byteLength);let b=0;for(;b<e.recordCount&&h<t.length;){if(h+4>t.length)throw new Error("E57: truncated DataPacket header");const w=a.getUint8(h),x=a.getUint16(h+2,!0)+1;if(w!==1){h+=x;continue}const y=h+x;if(y>t.length)throw new Error("E57: DataPacket runs past end of logical bytes");const C=y;if(h+6>C)throw new Error("E57: truncated DataPacket header");const M=a.getUint16(h+4,!0);if(M!==e.prototype.length)throw new Error(`E57: packet bytestreamCount (${M}) ≠ prototype length (${e.prototype.length})`);const L=[];let S=h+6;for(let E=0;E<M;E++){if(S+2>C)throw new Error("E57: truncated bytestream length table");L.push(a.getUint16(S,!0)),S+=2}const F=new Map;let k=S;for(let E=0;E<M;E++){if(k+L[E]>C)throw new Error(`E57: bytestream ${e.prototype[E].name} (${L[E]} bytes) runs past packet payload at offset ${k}`);F.set(e.prototype[E].name,{start:k,length:L[E]}),k+=L[E]}const V=F.get("cartesianX"),Z=F.get("cartesianY"),_=F.get("cartesianZ"),j=v(n,V.length),H=v(o,Z.length),J=v(r,_.length),K=Math.min(j,H,J),I=Math.min(K,e.recordCount-b);D(t,a,n,V.start,p,b,I,0),D(t,a,o,Z.start,p,b,I,1),D(t,a,r,_.start,p,b,I,2),g&&s&&i&&l&&(z(a,F.get("colorRed").start,s,g,b,I,0,t),z(a,F.get("colorGreen").start,i,g,b,I,1,t),z(a,F.get("colorBlue").start,l,g,b,I,2,t)),f&&u&&ut(t,a,u,F.get("intensity").start,f,b,I),m&&d&<(t,a,d,F.get("classification").start,m,b,I),b+=I,h=y}return b<e.recordCount?Y(p.subarray(0,b*3),g?.subarray(0,b*3),f?.subarray(0,b),m?.subarray(0,b),b):Y(p,g,f,m,e.recordCount)}function z(t,e,n,o,r,s,i,l){if(n.kind==="Float"){const c=n.precision==="single"?4:8;for(let u=0;u<s;u++){const d=c===4?t.getFloat32(e+u*c,!0):t.getFloat64(e+u*c,!0);o[(r+u)*3+i]=X(d)}}else if(n.kind==="Integer"){const c=n.minimum??0,u=n.maximum??255,d=u-c,p=d>0?1/d:1,f=Math.max(Math.abs(c),Math.abs(u))>255?2:1,m=c<0;for(let h=0;h<s;h++){const a=e+h*f,b=f===2?m?t.getInt16(a,!0):t.getUint16(a,!0):m?t.getInt8(a):t.getUint8(a);o[(r+h)*3+i]=X((b-c)*p)}}else{const c=n.minimum??0,d=(n.maximum??1)-c,p=d>0?1/d:1,g=O(n),f=e*8;for(let m=0;m<s;m++){const h=$(l,f+m*g,g);o[(r+m)*3+i]=X(h*p)}}}function D(t,e,n,o,r,s,i,l){if(n.kind==="Float"){const f=n.precision==="single"?4:8;if(f===4)for(let m=0;m<i;m++)r[(s+m)*3+l]=e.getFloat32(o+m*f,!0);else for(let m=0;m<i;m++)r[(s+m)*3+l]=e.getFloat64(o+m*f,!0);return}const c=O(n),u=n.minimum??0,d=n.scale??1,p=n.offset??0,g=o*8;for(let f=0;f<i;f++){const m=$(t,g+f*c,c);r[(s+f)*3+l]=(m+u)*d+p}}function ut(t,e,n,o,r,s,i){if(n.kind==="Float"){const f=n.precision==="single"?4:8;for(let m=0;m<i;m++){const h=f===4?e.getFloat32(o+m*f,!0):e.getFloat64(o+m*f,!0);r[s+m]=Math.min(65535,Math.max(0,Math.round(h*65535)))}return}if(n.kind==="Integer"){const f=n.minimum??0,m=n.maximum??65535,h=m-f,a=h>0?1/h:1,w=Math.max(Math.abs(f),Math.abs(m))>255?2:1,x=f<0;for(let y=0;y<i;y++){const C=o+y*w,L=((w===2?x?e.getInt16(C,!0):e.getUint16(C,!0):x?e.getInt8(C):e.getUint8(C))-f)*a;r[s+y]=Math.min(65535,Math.max(0,Math.round(L*65535)))}return}const l=O(n),c=n.minimum??0,d=(n.maximum??c)-c,p=d>0?1/d:1,g=o*8;for(let f=0;f<i;f++){const m=$(t,g+f*l,l);r[s+f]=Math.min(65535,Math.max(0,Math.round(m*p*65535)))}}function O(t){const e=t.minimum??0,n=t.maximum??e,o=Math.max(0,n-e);if(o===0)return 1;const r=Math.ceil(Math.log2(o+1));if(r>53)throw new Error(`E57: ScaledInteger field "${t.name}" needs ${r} bits — exceeds the 53-bit Number-precision limit`);return Math.max(1,r)}function v(t,e){if(t.kind==="Float"){const i=t.precision==="single"?4:8;return Math.floor(e/i)}if(t.kind==="ScaledInteger"){const i=O(t);return Math.floor(e*8/i)}const n=t.minimum??0,o=t.maximum??255,s=Math.max(Math.abs(n),Math.abs(o))>255?2:1;return Math.floor(e/s)}function $(t,e,n){let o=0,r=0,s=e>>>3,i=e&7;for(;r<n;){const l=8-i,c=Math.min(l,n-r),u=(1<<c)-1,d=t[s]>>>i&u;o+=d*Math.pow(2,r),r+=c,i=0,s++}return o}function Y(t,e,n,o,r){return{positions:new Float32Array(t),colors:e?new Float32Array(e):void 0,intensities:n?new Uint16Array(n):void 0,classifications:o?new Uint8Array(o):void 0,pointCount:r,bbox:T(t)}}function lt(t,e,n,o,r,s,i){if(n.kind==="Integer"){const d=n.minimum??0,p=n.maximum??255,f=Math.max(Math.abs(d),Math.abs(p))>255?2:1,m=d<0;for(let h=0;h<i;h++){const a=o+h*f,b=f===2?m?e.getInt16(a,!0):e.getUint16(a,!0):m?e.getInt8(a):e.getUint8(a);r[s+h]=Math.max(0,Math.min(255,b))}return}const l=O(n),c=n.minimum??0,u=o*8;for(let d=0;d<i;d++){const p=$(t,u+d*l,l);r[s+d]=Math.max(0,Math.min(255,p+c))}}function X(t){return t<0?0:t>1?1:t}function T(t){if(t.length<3)return{min:[0,0,0],max:[0,0,0]};let e=1/0,n=1/0,o=1/0,r=-1/0,s=-1/0,i=-1/0,l=!1;for(let c=0;c+2<t.length;c+=3){const u=t[c],d=t[c+1],p=t[c+2];!Number.isFinite(u)||!Number.isFinite(d)||!Number.isFinite(p)||(l=!0,u<e&&(e=u),u>r&&(r=u),d<n&&(n=d),d>s&&(s=d),p<o&&(o=p),p>i&&(i=p))}return l?{min:[e,n,o],max:[r,s,i]}:{min:[0,0,0],max:[0,0,0]}}const ft=new TextDecoder;function mt(t){const e=Q(t),n=tt(t,e.pageSize),o=n.subarray(e.xmlLogicalOffset,e.xmlLogicalOffset+e.xmlLogicalLength),r=ft.decode(o),s=it(r);if(s.length===0)return null;const i=s.map(a=>{const b=nt(n,a.binaryFileOffset,e.pageSize),w=ct(n,{...a,binaryFileOffset:b});return a.pose&&(dt(w.positions,w.pointCount,a.pose),w.bbox=T(w.positions)),w});if(i.length===1)return i[0];let l=0;for(const a of i)l+=a.pointCount;const c=new Float32Array(l*3),u=i.some(a=>a.colors),d=i.some(a=>a.intensities),p=i.some(a=>a.classifications),g=u?new Float32Array(l*3):void 0,f=d?new Uint16Array(l):void 0,m=p?new Uint8Array(l):void 0;let h=0;for(const a of i)c.set(a.positions,h*3),g&&a.colors&&g.set(a.colors,h*3),f&&a.intensities&&f.set(a.intensities,h),m&&a.classifications&&m.set(a.classifications,h),h+=a.pointCount;return{positions:c,colors:g,intensities:f,classifications:m,pointCount:l,bbox:T(c)}}function dt(t,e,n){const{w:o,x:r,y:s,z:i}=n.rotation,l=n.translation.x,c=n.translation.y,u=n.translation.z,d=1-2*(s*s+i*i),p=2*(r*s-o*i),g=2*(r*i+o*s),f=2*(r*s+o*i),m=1-2*(r*r+i*i),h=2*(s*i-o*r),a=2*(r*i-o*s),b=2*(s*i+o*r),w=1-2*(r*r+s*s);for(let x=0;x<e;x++){const y=t[x*3],C=t[x*3+1],M=t[x*3+2];t[x*3]=d*y+p*C+g*M+l,t[x*3+1]=f*y+m*C+h*M+c,t[x*3+2]=a*y+b*C+w*M+u}}class gt{blob;downsample;label;chunk=null;served=!1;constructor(e,n={}){this.blob=e,this.downsample=n.downsample??{stride:1},this.label=n.label}async open(e){B(e);const n=await this.blob.arrayBuffer();B(e);const o=mt(new Uint8Array(n));if(!o)throw new Error("E57: file contains no Data3D scans");return this.chunk=ht(o,this.downsample.stride),{totalPointCount:this.chunk.pointCount,bbox:this.chunk.bbox,hasColor:!!this.chunk.colors,hasClassification:!!this.chunk.classifications,hasIntensity:!!this.chunk.intensities,label:this.label}}async next(e,n){return B(n),!this.chunk||this.served?null:(this.served=!0,this.chunk)}close(){this.chunk=null,this.served=!1}}function ht(t,e){const n=Math.max(1,e|0);if(n===1)return t;const o=Math.ceil(t.pointCount/n),r=new Float32Array(o*3),s=t.colors?new Float32Array(o*3):void 0,i=t.intensities?new Uint16Array(o):void 0,l=t.classifications?new Uint8Array(o):void 0;let c=0;for(let u=0;u<t.pointCount;u+=n)r[c*3]=t.positions[u*3],r[c*3+1]=t.positions[u*3+1],r[c*3+2]=t.positions[u*3+2],s&&t.colors&&(s[c*3]=t.colors[u*3],s[c*3+1]=t.colors[u*3+1],s[c*3+2]=t.colors[u*3+2]),i&&t.intensities&&(i[c]=t.intensities[u]),l&&t.classifications&&(l[c]=t.classifications[u]),c++;return{positions:r,colors:s,intensities:i,classifications:l,pointCount:o,bbox:t.bbox}}function B(t){if(t?.aborted)throw new DOMException("Aborted","AbortError")}export{gt as E57StreamingSource};
|