ifcurl/SPECIFICATION.md
Bruno Postle ed03c13d36 service: add GET /foundation/versions OpenCDE discovery endpoint
Returns the Foundation API 1.1 version document listing BCF 3.0 and
Documents 1.0 API base URLs. Public, no auth required. Derives the
public base URL from X-Forwarded-Host/X-Forwarded-Proto headers so it
works correctly behind an nginx/Caddy reverse proxy with no extra config.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 19:20:54 +01:00

12 KiB

IFC URL — Specification

1. Overview

IFC URL is a URL scheme for addressing a specific view of an IFC model. A single URL encodes the model source — a Git repository or an OpenCDE Common Data Environment — an optional element selection, and an optional camera viewpoint.

The scheme identifier is ifc://.


2. Git source encoding

Transport inference

The transport is inferred from the URL structure. No transport prefix is required.

URL form Inferred transport
ifc://user@host/org/repo SSH (git)
ifc://host/org/repo HTTPS (git)
ifc:///path/to/repo Local file
ifc://host/...?document_id=... OpenCDE HTTPS (see §9)

The presence of user@ userinfo signals SSH. A bare hostname signals HTTPS git. An empty authority (triple slash) signals a local file path. The presence of a document_id query parameter signals OpenCDE transport regardless of the host form; in this case no @ref component is used.

Credentials are never embedded in the URL. Authentication is handled by the platform's git credential store (desktop apps) or by sideloaded tokens (preview service).

SCP-style SSH addresses (git@host:org/repo) are normalised to ifc://git@host/org/repo when generating URLs.

Ref format

Refs follow git's namespace structure to prevent ambiguity between branches and tags that share a name.

Ref type Form Example
Branch @heads/<name> @heads/main
Tag @tags/<name> @tags/v1.2
Commit hash @<hash> @abc123def
Default branch @HEAD @HEAD

The @ character delimits the repository path from the ref. It is always present in git URLs. It is omitted in OpenCDE URLs (see §9).

Full structure

ifc://[user@]host/org/repo@<ref>?<parameters>

3. Parameters

All parameters are optional. A URL with no parameters opens the model at its default view with no selection.

path

Path to the IFC file within the repository, relative to the repository root.

path=models/architectural/building.ifc

May be omitted when the target is a federated root file whose linked model references are defined within the IFC itself (see section 5).

selector

An IfcOpenShell selector expression, percent-encoded. The selector syntax is specified at:

https://docs.ifcopenshell.org/ifcopenshell-python/selector_syntax.html

Selectors are single-line expressions. Filters within a group are comma-separated; groups are joined with + for union.

selector=IfcWall
selector=IfcWall,+Name="Core+Wall"
selector=IfcWall+IfcSlab
selector=IfcWall,+Pset_WallCommon.FireRating=2HR
selector=325Q7Fhnf67OZC$$r43uzK

When omitted, no selection is applied.

camera

Nine comma-separated decimal values defining the camera in IFC world coordinates (see section 4):

camera=px,py,pz,dx,dy,dz,ux,uy,uz
Values Meaning
px,py,pz Camera position
dx,dy,dz View direction vector (unit vector)
ux,uy,uz Up vector (unit vector)

camera must be accompanied by either fov (perspective) or scale (orthographic). Their presence signals the projection type. Exactly one must be present if camera is present.

When camera is omitted entirely, the viewer fits the view to the selection if a selector is present, or shows the model's default view otherwise.

fov

Field of view in degrees. Signals perspective projection.

fov=60

scale

View-to-world scale. Signals orthographic projection. The value represents how many model units correspond to one unit in the normalised view, equivalent to BCF's ViewToWorldScale.

scale=50

clip

A clipping plane, defined by a point on the plane and a normal vector pointing toward the visible side. All values are in IFC world coordinates.

clip=px,py,pz,nx,ny,nz

Repeatable. Multiple clip parameters define the intersection of their half-spaces.

clip=0,0,3,0,0,-1&clip=0,0,0,0,0,1

document_id

OpenCDE Documents API identifier for the document to fetch. Its presence signals OpenCDE transport (see §9). Mutually exclusive with path.

document_id=bf546064-6b97-4730-a094-c21ab929c91a

The value is an opaque string assigned by the CDE; no particular format is required by the OpenCDE specification.

version_index

OpenCDE version index of the specific document version to fetch. Must be a positive integer matching the version_index field returned by the OpenCDE Documents API, where higher values indicate newer versions. Only meaningful when document_id is also present.

version_index=3

When omitted, the resolver fetches the version with the highest version_index (the current version). A URL with version_index present is immutable; one with version_index absent is mutable.

visibility

Controls how selected and unselected elements are displayed.

Value Behaviour
highlight Show all elements, highlight selection (default)
ghost Show selection normally, dim all other elements
isolate Show only selected elements, hide all others

When omitted, highlight is assumed.


4. Coordinate system

All spatial values (camera, clip) are expressed in the IFC project's world coordinate system, consistent with BCF viewpoint conventions. Local coordinate systems, object placements, and georeferenced survey coordinates are not used.

Where an IFC file uses IfcMapConversion (IFC 4.1+) to define a georeferenced coordinate system, camera and clipping plane values remain in IFC world coordinates, not in the mapped survey coordinate system.


5. Federation

Federated models are referenced within the IFC file itself using IFCDOCUMENTINFORMATION with a LINKED_MODEL purpose, associated with the root IFCPROJECT entity via IFCRELASSOCIATESDOCUMENT. The location is carried in IFCDOCUMENTREFERENCE:

#46471=IFCDOCUMENTINFORMATION('X','model.ifc',$,$,$,$,'LINKED_MODEL',$,$,$,$,$,$,$,$,$,$);
#46472=IFCRELASSOCIATESDOCUMENT('0mypTfsjT...',$,$,$,(#10510),#46471);
#46473=IFCDOCUMENTREFERENCE('../conservatory-ifc/model.ifc','<4x4 matrix>',$,$,#46471);

The second field of IFCDOCUMENTREFERENCE is a 4x4 transformation matrix (sixteen comma-separated values) that positions the linked model in the shared coordinate system. This is resolved entirely by the viewer.

Location field values

The location field (first field of IFCDOCUMENTREFERENCE) supports:

  • Relative path — resolved relative to the root IFC file's directory within the repository, using the same repo and ref context
  • Absolute local path — resolved on the local filesystem (desktop use only)
  • ifc:// URL — resolved as a full IFC URL, enabling cross-repo and cross-server federation

When a relative path would traverse above the repository root, an ifc:// URL must be used instead. This is the primary motivation for supporting ifc:// in the location field.


6. BCF interoperability

The camera and selection in an IFC URL map directly to BCF viewpoint concepts.

IFC URL to BCF viewpoint:

  1. Resolve the selector against the model to obtain a set of GUIDs
  2. Construct a BCF PerspectiveCamera or OrthogonalCamera from the camera parameters
  3. Add clipping planes if present
  4. Populate Components/Selection with the resolved GUIDs

BCF viewpoint to IFC URL:

  1. Extract the GUID list from Components/Selection; if DefaultVisibility is false, use the GUIDs from Visibility/Exceptions instead and set visibility=isolate
  2. Construct an IfcOpenShell GUID selector (bare GUIDs joined with +)
  3. Convert the BCF camera to camera, fov or scale parameters
  4. Convert clipping planes to clip parameters

7. Viewer compliance

A compliant viewer must:

  • Register ifc:// as an OS-level protocol handler
  • Resolve the git source (repo, ref, path) and fetch the IFC file
  • Resolve an OpenCDE document source via Foundation API discovery and the Documents API (see §9)
  • Resolve an IfcOpenShell selector against the loaded model
  • Apply perspective camera (camera + fov)
  • Apply orthographic camera (camera + scale)
  • Apply clipping planes (clip)
  • Apply visibility mode (highlight, ghost, isolate)
  • Resolve relative IFCDOCUMENTREFERENCE paths using the root file's repo and ref context
  • Resolve ifc:// IFCDOCUMENTREFERENCE locations

Optional extensions:

  • Semantic colouring
  • Advanced visual styles beyond the three visibility modes

8. Complete examples

Open a model at the default view:

ifc://example.com/org/project@heads/main?path=models/building.ifc

Perspective view of selected walls:

ifc://git@example.com/org/project@abc123def?path=models/building.ifc&selector=IfcWall,+Name="Core+Wall"&camera=10,20,5,0,-1,0,0,0,1&fov=60&visibility=ghost

Orthographic plan view at level 2 with a clipping plane:

ifc://example.com/org/project@tags/v2.0?path=models/building.ifc&camera=0,0,8,0,0,-1,0,1,0&scale=50&clip=0,0,5,0,0,-1

Local file, default branch:

ifc:///home/alice/projects/office@HEAD?path=model.ifc

OpenCDE document, specific version, perspective view of all walls:

ifc://cde.example.com/project-123?document_id=bf546064-6b97-4730-a094-c21ab929c91a&version_index=3&selector=IfcWall&camera=10,20,5,0,-1,0,0,0,1&fov=60&visibility=ghost

OpenCDE document, current version, no view parameters (opens at default view):

ifc://cde.example.com/project-123?document_id=bf546064-6b97-4730-a094-c21ab929c91a

9. OpenCDE transport

When a document_id parameter is present, the URL addresses a document on an OpenCDE-compliant Common Data Environment rather than a Git repository. The path parameter and the @ref component are both absent.

URL structure

ifc://host[/project-path]?document_id=<id>[&version_index=<N>]&<view-parameters>

The authority and optional path locate the CDE server and project. The path structure is implementation-defined and is passed through to the resolver without interpretation; it may be empty, a single project identifier, or a deeper hierarchy depending on the CDE.

Version reference

version_index Meaning Tier 4 caching
version_index=N Specific immutable version Safe
absent Current version (highest index) Never

The version_index value corresponds directly to the field of the same name in the OpenCDE Documents API: a machine-readable integer sequence where higher values represent newer versions. It is distinct from version_number, which is a free-form human-readable label that varies across CDE implementations and is not used in ifc:// URLs.

Resolver workflow

  1. Discover APIsGET https://host/foundation/versions. This endpoint is public and requires no authentication. It returns the base URLs for all OpenCDE APIs on this server (Foundation API 1.1 format: versions array with api_id, version_id, detailed_version, api_base_url per entry).

  2. Authenticate — OAuth2 authorization code or implicit flow, using the configuration obtained from step 1. Credentials are never embedded in the ifc:// URL. Viewer implementations served from the same browser session as the CDE web interface may share the existing session cookie, avoiding an explicit OAuth2 flow for authenticated users.

  3. Resolve document versionPOST <documents_api_base>/document-versions with body {"document_ids": ["<document_id>"]}. If version_index is present, select the returned version whose version_index matches; if absent, select the version with the highest version_index.

  4. Download — Fetch the IFC file from the document_version_download URL returned in the Documents API response.

Federation

ifc:// URLs addressing OpenCDE documents may appear in IFCDOCUMENTREFERENCE location fields (see §5) alongside relative paths and git-hosted ifc:// URLs. No changes to the federation model are required.