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:
Wassim SAMAD
2026-05-21 10:45:12 -04:00
co-authored by Claude Opus 4.7
parent 8505d6cdfa
commit 0df51219d0
27 changed files with 150847 additions and 0 deletions
+51
View File
@@ -0,0 +1,51 @@
# IFC → Pascal Converter
A web app that converts IFC building models into Pascal scene-graph JSON and
previews the result in the real `@pascal-app/viewer`. Drop in an `.ifc` file
(or pick a bundled example), inspect what was extracted, and download the
JSON to load into the Pascal editor.
> ## ⚠️ Early alpha
>
> This converter is in **early alpha**. IFC is a sprawling, loosely-followed
> standard and real-world exports vary wildly — so expect rough edges:
> misplaced or missing elements, walls that default to a fixed height when
> their geometry can't be read, items skipped entirely, and element types
> that aren't mapped yet. The output is meant for previewing and iterating,
> not production.
>
> **Contributions very welcome** — if you hit a file that converts badly,
> a sample IFC + a note on what's wrong is hugely helpful, and PRs improving
> the conversion (better geometry extraction, more element types, edge-case
> handling) are exactly what this needs. Jump in. 🙏
## How it works
- **`@pascal-app/ifc-converter`** (`packages/ifc-converter`) — the pure
conversion logic. Parses IFC via [web-ifc](https://github.com/ThatOpen/engine_web-ifc),
maps elements onto Pascal node schemas from `@pascal-app/core`. No DOM, no
React.
- **This app** — the UI: drop zone, example picker, element search/filters,
the 3D preview, and JSON download.
## Develop
```bash
bun dev # from this directory, or `turbo run dev` at the repo root
```
The `web-ifc.wasm` binary is copied into `public/` automatically on
install/dev/build (`scripts/copy-web-ifc-wasm.mjs`). Large example IFCs are
fetched from a public bucket at runtime; the small ones are committed under
`public/test-ifc-files/`. Override the bucket with
`NEXT_PUBLIC_IFC_EXAMPLES_BASE_URL`.
## Known limitations (help wanted)
- Plain `IFCWALL` (Brep/mapped geometry) falls back to a default height — exact
per-wall heights need geometry-AABB extraction.
- Items (furniture, etc.) are skipped — Pascal items require a catalog asset.
- Beams have no Pascal node type yet and are skipped.
- Doors/windows are matched to walls by proximity when the IFC omits fill
relationships; matching isn't perfect.
- Stairs/roofs are placeholders (bounding box / flat polygon in metadata).