feat: IFC → Pascal converter (package + app)
Brings the IFC-to-Pascal converter into the monorepo as a pure-logic package plus a Next.js app, replacing the standalone repo that consumed published @pascal-app/* packages (and drifted from their schemas). packages/ifc-converter — pure conversion. Parses IFC via web-ifc and maps elements onto @pascal-app/core node schemas (workspace-linked, so no more version drift). Builds doors/windows, walls, slabs, columns, roofs, stairs, sites/buildings/levels. Validates each node via the real Zod schemas at build time (tryParse) and strips undefined metadata. apps/ifc-converter — the UI: drop zone, example picker, element search, JSON download, and a 3D preview rendered through the real @pascal-app/viewer (registry bootstrap + read-only scene) with a custom toolbar (camera/level/wall/grid/theme), level selector with camera-focus, auto-fit, and selection bridged to an inspector. Conversion specifics worth noting: - Door/window vertical centering (height/2; windows + sill). - Nearest-wall hosting fallback for files lacking IFCRELFILLSELEMENT, preferring walls long enough to contain the opening and clamping the along-wall position so cutouts can't overflow and break wall CSG. - Plain IFCWALL (Brep/mapped geometry) falls back to default height/thickness instead of collapsing to zero-height slivers. - Columns convert as plain structural shafts (no decorative base/capital) sized from the IFC profile. - Beams + items are skipped for now (no Pascal beam type; items need a catalog asset) — counted in the conversion summary. Large example IFCs are fetched from a public bucket at runtime; the four small ones are committed. web-ifc.wasm is copied into public/ on install/dev/build. README flags early-alpha + invites contributions. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
8505d6cdfa
commit
0df51219d0
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env node
|
||||
// web-ifc ships its WASM binaries inside node_modules. Next.js needs to
|
||||
// serve them at the app root URL (the library hardcodes `/web-ifc.wasm`
|
||||
// when no `wasmPath` override is set), so copy the three blobs into
|
||||
// `public/` so they're served from /web-ifc*.wasm.
|
||||
//
|
||||
// Run on `postinstall` and again on `predev` / `prebuild` so a forgotten
|
||||
// install step doesn't leave the dev server with a stale or missing
|
||||
// copy. Idempotent: skips files that already match by size.
|
||||
|
||||
import { copyFileSync, existsSync, mkdirSync, statSync } from 'node:fs'
|
||||
import { join, resolve } from 'node:path'
|
||||
|
||||
// web-ifc's package.json doesn't expose subpath exports, so we can't use
|
||||
// require.resolve('web-ifc/package.json'). Walk up the script directory
|
||||
// looking for the package folder inside any node_modules along the way.
|
||||
function findWebIfcDir(startDir) {
|
||||
let dir = startDir
|
||||
while (dir && dir !== '/') {
|
||||
const candidate = join(dir, 'node_modules', 'web-ifc')
|
||||
if (existsSync(join(candidate, 'web-ifc.wasm'))) return candidate
|
||||
dir = resolve(dir, '..')
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
const webIfcDir = findWebIfcDir(import.meta.dirname)
|
||||
if (!webIfcDir) {
|
||||
console.warn('[ifc-converter] web-ifc package not found — wasm copy skipped.')
|
||||
process.exit(0)
|
||||
}
|
||||
const publicDir = join(import.meta.dirname, '..', 'public')
|
||||
|
||||
mkdirSync(publicDir, { recursive: true })
|
||||
|
||||
const files = ['web-ifc.wasm', 'web-ifc-mt.wasm', 'web-ifc-node.wasm']
|
||||
for (const name of files) {
|
||||
const src = join(webIfcDir, name)
|
||||
const dst = join(publicDir, name)
|
||||
try {
|
||||
const srcSize = statSync(src).size
|
||||
let dstSize = 0
|
||||
try {
|
||||
dstSize = statSync(dst).size
|
||||
} catch {
|
||||
/* not present yet */
|
||||
}
|
||||
if (srcSize === dstSize) {
|
||||
continue
|
||||
}
|
||||
copyFileSync(src, dst)
|
||||
console.log(`[ifc-converter] copied ${name} (${(srcSize / 1024).toFixed(0)} KB)`)
|
||||
} catch (err) {
|
||||
console.warn(`[ifc-converter] could not copy ${name}:`, err.message)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user