162 lines
5.2 KiB
Markdown
162 lines
5.2 KiB
Markdown
# IFC in the Browser: WASM Options
|
||
|
||
## Goal
|
||
|
||
Run `ifc-commit` logic (IFC extraction, modification, merge) client-side in a browser — no server, no Python install.
|
||
|
||
---
|
||
|
||
## Option 1 — IfcOpenShell via Pyodide (closest drop-in)
|
||
|
||
**Repo:** https://github.com/IfcOpenShell/wasm-wheels
|
||
**Wheel index:** https://ifcopenshell.github.io/wasm-wheels/
|
||
|
||
IfcOpenShell ships WASM as Pyodide wheels — Python packages compiled to `wasm32` via Emscripten. The full Python API runs inside a browser through the Pyodide runtime.
|
||
|
||
### Setup
|
||
|
||
```html
|
||
<script src="https://cdn.jsdelivr.net/pyodide/v0.27/full/pyodide.js"></script>
|
||
```
|
||
|
||
```javascript
|
||
const pyodide = await loadPyodide();
|
||
await pyodide.loadPackage("micropip");
|
||
await pyodide.runPythonAsync(`
|
||
import micropip
|
||
await micropip.install(
|
||
"https://ifcopenshell.github.io/wasm-wheels/"
|
||
"ifcopenshell-0.8.3+34a1bc6-cp313-cp313-emscripten_4_0_9_wasm32.whl"
|
||
)
|
||
`);
|
||
```
|
||
|
||
### Usage
|
||
|
||
```python
|
||
# Identical to desktop ifccommit.py
|
||
import ifcopenshell
|
||
import ifcpatch
|
||
|
||
model = ifcopenshell.open("input.ifc")
|
||
result = ifcpatch.execute({
|
||
"input": "input.ifc",
|
||
"file": model,
|
||
"recipe": "ExtractElements",
|
||
"arguments": [["IfcWall", "IfcSlab"]],
|
||
})
|
||
ifcpatch.write(result, "output.ifc")
|
||
```
|
||
|
||
### Available wheels (early 2026)
|
||
|
||
| Wheel | Python | Emscripten |
|
||
|-------|--------|------------|
|
||
| `ifcopenshell-0.8.3+34a1bc6-cp313-cp313-emscripten_4_0_9_wasm32.whl` | 3.13 | 4.0.9 |
|
||
| `ifcopenshell-0.8.2+d50e806-cp312-cp312-emscripten_3_1_58_wasm32.whl` | 3.12 | 3.1.58 |
|
||
|
||
### Pros / Cons
|
||
|
||
| + | - |
|
||
|---|---|
|
||
| Identical API to desktop — `ifcpatch` recipes work as-is | Requires loading Pyodide (~10 MB) + Python interpreter overhead |
|
||
| `ifcpatch`, `ifcclash`, `ifctester` all available | Not on PyPI; must install from CDN wheel URL |
|
||
| Zero code changes to `ifccommit.py` | Slower than native due to WASM + Python layers |
|
||
| Models stay in browser (no server upload) | Large initial download |
|
||
|
||
**Best fit:** A browser version that mirrors the CLI exactly — same `ExtractElements`, `PatchIfc` recipes, same Python logic.
|
||
|
||
---
|
||
|
||
## Option 2 — web-ifc (C++/JS, no Python)
|
||
|
||
**npm:** `web-ifc`
|
||
**Repo:** https://github.com/ThatOpen/engine_web-ifc (by That Open Company, formerly IFCjs)
|
||
|
||
C++ IFC parser compiled to WASM via Emscripten, with a TypeScript API. The dominant ecosystem for browser IFC tools.
|
||
|
||
```bash
|
||
npm install web-ifc
|
||
```
|
||
|
||
```javascript
|
||
import { IfcAPI } from "web-ifc";
|
||
|
||
const api = new IfcAPI();
|
||
await api.Init();
|
||
const bytes = new Uint8Array(await file.arrayBuffer());
|
||
const modelID = api.OpenModel(bytes);
|
||
const walls = api.GetLineIDsWithType(modelID, api.IFCWALL);
|
||
api.CloseModel(modelID);
|
||
```
|
||
|
||
### Pros / Cons
|
||
|
||
| + | - |
|
||
|---|---|
|
||
| Native JS/TS — no Python runtime | No `ifcpatch` recipe system |
|
||
| Smaller footprint than Pyodide | Lower-level API — more code to replicate `ifccommit` logic |
|
||
| Actively maintained, large ecosystem | No `ifcclash`, `ifctester`, `ifcdiff` equivalents |
|
||
| Runs in Web Workers (multi-threaded) | Write support is lower-level |
|
||
|
||
**Best fit:** A rewrite of `ifc-commit` as a TypeScript/JS app, or integration into a larger BIM web app (Three.js, React, etc.).
|
||
|
||
---
|
||
|
||
## Option 3 — ifc-lite (Rust/WASM + WebGPU)
|
||
|
||
**Repo:** https://github.com/louistrue/ifc-lite
|
||
**npm scope:** `@ifc-lite/*` (e.g. `@ifc-lite/parser`, `@ifc-lite/geometry`, `@ifc-lite/query`)
|
||
|
||
Rust-based IFC parser compiled to WASM via `wasm-bindgen`, with WebGPU rendering. Claims 5× faster geometry processing than alternatives. Supports IFC4, IFC4X3, and IFC5 (IFCX alpha).
|
||
|
||
```bash
|
||
npm install @ifc-lite/parser @ifc-lite/query
|
||
```
|
||
|
||
### Pros / Cons
|
||
|
||
| + | - |
|
||
|---|---|
|
||
| Fastest option (Rust + WebGPU) | Very new — alpha-stage API stability |
|
||
| Supports IFC5/IFCX | No `ifcpatch` equivalent |
|
||
| No Rust toolchain needed (pre-built WASM) | Requires rewriting all `ifc-commit` logic in TS |
|
||
|
||
**Best fit:** Performance-critical geometry/visualization use cases.
|
||
|
||
---
|
||
|
||
## Option 4 — IFCflow (inspiration, not a library)
|
||
|
||
**URL:** https://ifcflow.com
|
||
**Docs repo:** https://github.com/louistrue/IfcFlow-Docs
|
||
|
||
A browser-based visual node editor for IFC pipelines. Uses the IfcOpenShell WASM wheels (Pyodide) for on-device processing. Not a reusable library — a hosted web app — but demonstrates that the Pyodide approach works end-to-end for extract/filter/export workflows similar to `ifc-commit`.
|
||
|
||
---
|
||
|
||
## Recommended Path for ifc-commit
|
||
|
||
### Phase 1 — Pyodide prototype (zero code changes)
|
||
|
||
1. Create `web/index.html` with Pyodide bootstrapped.
|
||
2. On file drop/upload, pass the `ArrayBuffer` into Python as bytes.
|
||
3. Call `ifccommit.py` functions directly via `pyodide.runPythonAsync()`.
|
||
4. Offer the output `.ifc` as a download via a `Blob` URL.
|
||
|
||
This requires no changes to `ifccommit.py`.
|
||
|
||
### Phase 2 — web-ifc rewrite (optional, for performance)
|
||
|
||
If Pyodide startup time (~3–5 s) or bundle size is a problem, rewrite the core operations using `web-ifc` TypeScript API. This is a significant effort — `ifcpatch` recipes must be re-implemented.
|
||
|
||
---
|
||
|
||
## References
|
||
|
||
- IfcOpenShell WASM wheels: https://github.com/IfcOpenShell/wasm-wheels
|
||
- Wheel CDN: https://ifcopenshell.github.io/wasm-wheels/
|
||
- Pyodide: https://pyodide.org
|
||
- web-ifc: https://github.com/ThatOpen/engine_web-ifc
|
||
- ifc-lite: https://github.com/louistrue/ifc-lite
|
||
- IFCflow: https://ifcflow.com
|