mirror of
https://github.com/brunopostle/ifcurl.git
synced 2026-07-12 02:08:13 +00:00
204 lines
6.2 KiB
Markdown
204 lines
6.2 KiB
Markdown
|
|
# IFC URL — Development Plan
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
IFC URL requires work across four distinct areas:
|
||
|
|
|
||
|
|
1. A Python core library and CLI tool
|
||
|
|
2. A preview service with Gitea integration
|
||
|
|
3. Desktop app integration (Bonsai, IFC Viewer)
|
||
|
|
4. The federation extension to `IFCDOCUMENTREFERENCE`
|
||
|
|
|
||
|
|
The Python core is the foundation for all other work. The Gitea integration
|
||
|
|
and desktop app work can proceed in parallel once the core exists.
|
||
|
|
|
||
|
|
### Language ownership
|
||
|
|
|
||
|
|
| Component | Language | Rationale |
|
||
|
|
|---|---|---|
|
||
|
|
| URL parsing, git fetch, selector execution, rendering | Python | Built on IfcOpenShell |
|
||
|
|
| Bonsai plugin | Python | Bonsai is a Blender/Python addon |
|
||
|
|
| CLI tool | Python | Wraps the core library |
|
||
|
|
| Preview service | Python | Wraps the core library |
|
||
|
|
| Gitea plugin | Go | Gitea is written in Go; the plugin only calls an HTTP endpoint |
|
||
|
|
| Web viewer integration | JavaScript | Future, not in current scope |
|
||
|
|
|
||
|
|
The Python core is a strong candidate for eventual contribution to
|
||
|
|
IfcOpenShell, but this is not a prerequisite for any phase.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Phase 1 — Python core and CLI tool
|
||
|
|
|
||
|
|
Build a Python library that resolves an `ifc://` URL and produces a rendered
|
||
|
|
PNG. This validates the spec against real IFC files and is the foundation for
|
||
|
|
all subsequent work.
|
||
|
|
|
||
|
|
### Library responsibilities
|
||
|
|
|
||
|
|
- Parse an `ifc://` URL into its components
|
||
|
|
- Infer git transport from URL structure (SSH, HTTPS, local)
|
||
|
|
- Fetch the IFC file from the repository at the specified ref
|
||
|
|
- Execute the IfcOpenShell selector against the loaded model
|
||
|
|
- Apply camera (perspective and orthographic), clipping planes, and
|
||
|
|
visibility mode
|
||
|
|
- Render a static PNG
|
||
|
|
|
||
|
|
### CLI interface
|
||
|
|
|
||
|
|
```bash
|
||
|
|
ifc-url render "ifc://example.com/org/repo@abc123?path=model.ifc&selector=IfcWall&fov=60"
|
||
|
|
ifc-url render "ifc://example.com/org/repo@heads/main?path=model.ifc&camera=0,0,8,0,0,-1,0,1,0&scale=50"
|
||
|
|
```
|
||
|
|
|
||
|
|
### Notes
|
||
|
|
|
||
|
|
- IfcOpenShell handles selector execution, model parsing, and geometry
|
||
|
|
- Rendering requires a headless approach; options include IfcOpenShell's own
|
||
|
|
geometry processing with a software or headless OpenGL renderer
|
||
|
|
- Git access uses the platform credential store for HTTPS and ssh-agent or
|
||
|
|
key files for SSH
|
||
|
|
- The CLI accepts the URL as a plain string so it can be called from
|
||
|
|
non-Python contexts
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Phase 2 — Preview service
|
||
|
|
|
||
|
|
Wrap the Phase 1 library in an HTTP service for use by Gitea and other
|
||
|
|
consumers.
|
||
|
|
|
||
|
|
### Endpoint
|
||
|
|
|
||
|
|
```
|
||
|
|
POST /preview
|
||
|
|
body: { url: "ifc://..." }
|
||
|
|
response: image/png
|
||
|
|
```
|
||
|
|
|
||
|
|
### Caching
|
||
|
|
|
||
|
|
| Tier | Cache key | Contents | Notes |
|
||
|
|
|---|---|---|---|
|
||
|
|
| 2 | commit hash | Parsed model structure | Shared across requests |
|
||
|
|
| 3 | commit hash + selector | Resolved GUID set | |
|
||
|
|
| 4 | full URL hash | Rendered PNG | Not applied to mutable refs |
|
||
|
|
|
||
|
|
Mutable refs (`@heads/`, `@HEAD`) must not be cached at tier 4 since the
|
||
|
|
underlying commit may change. Commit hash refs are immutable and can be
|
||
|
|
cached indefinitely at all tiers.
|
||
|
|
|
||
|
|
### Authentication
|
||
|
|
|
||
|
|
- **Co-located with Gitea** — uses the requesting user's Gitea session token,
|
||
|
|
passed from the Gitea plugin
|
||
|
|
- **Standalone** — sideloaded token configuration per git host
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Phase 3 — Gitea integration
|
||
|
|
|
||
|
|
Add `ifc://` link detection and preview embedding to Gitea.
|
||
|
|
|
||
|
|
### Go plugin responsibilities
|
||
|
|
|
||
|
|
- Detect `ifc://` links in post and comment content
|
||
|
|
- Call the preview service with the URL and the current user's session token
|
||
|
|
- Embed the returned PNG inline with a link that opens the URL
|
||
|
|
- Degrade gracefully when the preview service is unavailable (show the raw
|
||
|
|
URL rather than failing)
|
||
|
|
|
||
|
|
### Notes
|
||
|
|
|
||
|
|
- The plugin has no IFC awareness; all IFC logic lives in the preview service
|
||
|
|
- Repeated embeds of the same URL across different posts do not trigger
|
||
|
|
re-renders — the preview service cache handles deduplication
|
||
|
|
- The preview service may run as a companion process on the same host or
|
||
|
|
as a separately configured external service
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Phase 4 — Bonsai integration
|
||
|
|
|
||
|
|
Add `ifc://` handling to Bonsai.
|
||
|
|
|
||
|
|
### Protocol handler
|
||
|
|
|
||
|
|
Register `ifc://` as an OS protocol handler on installation (Windows,
|
||
|
|
macOS, Linux). On receiving a URL, resolve the git source, load the model,
|
||
|
|
and apply the view state from the URL parameters.
|
||
|
|
|
||
|
|
### "Copy view URL"
|
||
|
|
|
||
|
|
A button that generates an `ifc://` URL from the current Bonsai state:
|
||
|
|
|
||
|
|
- Git remote, ref, and file path of the open model
|
||
|
|
- Active selection converted to an IfcOpenShell selector
|
||
|
|
- Current camera converted to the `camera` + `fov` or `scale` format,
|
||
|
|
in IFC world coordinates
|
||
|
|
- Active clipping planes as `clip` parameters
|
||
|
|
- Current visibility mode
|
||
|
|
|
||
|
|
The button always generates a commit hash ref by default. Generating a
|
||
|
|
`@heads/` ref is a secondary option for authoring links intended to track
|
||
|
|
a branch.
|
||
|
|
|
||
|
|
### Federation
|
||
|
|
|
||
|
|
When opening a model via `ifc://`, Bonsai resolves `IFCDOCUMENTREFERENCE`
|
||
|
|
locations using the repo and ref from the root file's URL as context.
|
||
|
|
`ifc://` locations in linked model references are resolved recursively.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Phase 5 — IFC Viewer integration
|
||
|
|
|
||
|
|
Equivalent to Phase 4 for the IFC Viewer desktop application.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Phase 6 — Federation extension
|
||
|
|
|
||
|
|
Extend the `IFCDOCUMENTREFERENCE` location field in Bonsai to accept
|
||
|
|
`ifc://` URLs, enabling cross-repo and cross-server federation.
|
||
|
|
|
||
|
|
### Tasks
|
||
|
|
|
||
|
|
- When saving a linked model reference, offer the option to write the
|
||
|
|
location as an `ifc://` URL rather than a relative path
|
||
|
|
- When a relative path would traverse above the repository root, prompt
|
||
|
|
the user to convert it to an `ifc://` URL
|
||
|
|
- Resolve `ifc://` location fields through the Phase 4 URL resolver
|
||
|
|
|
||
|
|
The transformation matrix in `IFCDOCUMENTREFERENCE` is unaffected by this
|
||
|
|
change. Phase 4 must be complete before this phase begins.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Future work
|
||
|
|
|
||
|
|
### BCF export
|
||
|
|
|
||
|
|
An additional preview service endpoint returning a BCF file:
|
||
|
|
|
||
|
|
```
|
||
|
|
POST /bcf
|
||
|
|
body: { url: "ifc://..." }
|
||
|
|
response: application/zip
|
||
|
|
```
|
||
|
|
|
||
|
|
Resolves the selector to a GUID set and constructs a BCF viewpoint from the
|
||
|
|
camera, clipping planes, and visibility state. No implementation is planned
|
||
|
|
before Phase 2 is complete.
|
||
|
|
|
||
|
|
### Web viewer integration
|
||
|
|
|
||
|
|
JavaScript integration with web-based IFC viewers (IFC.js, xeokit) and
|
||
|
|
browser-side forum embedding. Not in current scope.
|
||
|
|
|
||
|
|
### IfcOpenShell contribution
|
||
|
|
|
||
|
|
Once the Python core is stable, the URL parsing and resolution logic is a
|
||
|
|
candidate for contribution to IfcOpenShell as a shared utility. This is not
|
||
|
|
a prerequisite for any phase.
|