ifcurl/PLAN.md
2026-04-22 08:31:24 +01:00

9.1 KiB

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

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 3b — Web IFC viewer

Add a 3D viewer that opens in a separate browser window when viewing an .ifc file in Forgejo.

Architecture

  • Forgejo Go patch: when rendering the file view for a .ifc file, inject a "View in 3D" button that opens http://localhost:8000/viewer?url=ifc://... in a new tab. The ifc:// URL encodes the current host, repo, ref, and file path.

  • /viewer endpoint in the ifcurl preview service: returns a self-contained HTML page. No server-side IFC processing — the browser does all rendering.

  • Browser rendering: the viewer page loads @thatopen/components (and its web-ifc + Three.js peer dependencies) from a CDN via an ES module importmap. It constructs the Forgejo raw file URL from the ifc:// URL parameters and fetches the IFC bytes directly from Forgejo.

Current scope (Phase 3b)

  • Display the full model for whatever ref is shown in Forgejo.
  • Basic orbit/pan/zoom camera controls.
  • No filtering or selection UI yet.

Future scope

  • Element filtering and selection using @thatopen/components classifier and highlighter APIs.
  • Camera state serialised to an ifc:// URL so the user can copy a view link (feeds into Phase 4 Bonsai "Copy view URL").
  • Diff highlighting driven by ifcmerge output (see Phase 3c).

Phase 3c — ifcmerge integration

ifcmerge is a git custom merge driver that resolves conflicts in .ifc files that git's built-in 3-way merge cannot handle. Where two branches have both modified an IFC file (a fork), git would report an unresolvable conflict; ifcmerge performs a semantics-aware merge and produces a valid merged IFC file.

Git merge driver configuration

Register ifcmerge as the git merge driver for .ifc files on the Forgejo server:

# /etc/gitconfig or ~forgejo/.gitconfig
[merge "ifcmerge"]
    name = IFC merge driver
    driver = ifcmerge %O %A %B %L
# .gitattributes in each repo, or server-side gitattributes
*.ifc merge=ifcmerge

With this in place, Forgejo's existing "merge automatically" path will invoke ifcmerge via git when merging .ifc files, and the PR merge button will work without any Go-side changes for the common case.

Forgejo integration

  • Verify that Forgejo's merge-ability check (the "these branches can be merged automatically" indicator) correctly reflects ifcmerge's ability to merge .ifc files — investigate whether the check runs a trial merge via git or uses a heuristic.
  • If needed, patch Forgejo to run a trial git merge --no-commit to get an accurate result for IFC files.

3D diff view (future)

  • After a merge completes, surface a "View merge in 3D" button in the PR using the Phase 3b viewer.
  • Use @thatopen/components highlighter to colour added, removed, and modified elements differently, driven by comparing the merged IFC against either parent.

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.