Skip to content

Capabilities and status ​

This page is deliberately conservative. It exists so that an engineer — or a coding agent — can scope work against what the code does, not against what the IFC schema contains or a crate name suggests.

Status vocabulary ​

TermMeaning
ImplementedExecutable behaviour with tests. Safe to build on.
PartialA real vertical slice exists; the issues in its row name what it lacks, and unsupported input returns a typed error.
ScaffoldThe crate exists and its ownership is settled. No behaviour.
AbsentNot present in the workspace at all.

No source file reserves a name for later work: a module that holds only comments fails the gate, and planned work is an issue (ADR 0019). A module path in the tree is therefore always backed by code.

Workspace census ​

Generated by cargo run -p xtask -- docs from each crate's [package.metadata.openbim]: status is a declared judgement, and gaps lists the open issues behind it. A Partial crate must name at least one. scripts/gate.sh fails if the table drifts from the manifests. Crate size is deliberately not published here: it changes with nearly every commit, and a committed figure that moves that often only produces merge conflicts. Coverage measures what each crate does instead.

CrateStatusOpen gaps
ifc-alignmentImplemented
ifc-approvalImplemented
ifc-authorImplemented
ifc-classificationImplemented
ifc-constraintImplemented
ifc-controlImplemented
ifc-costImplemented
ifc-element-typeImplemented
ifc-geometryPartial#311
ifc-georefImplemented
ifc-materialImplemented
ifc-modelImplemented#105
ifc-occurrenceImplemented
ifc-propertiesImplemented
ifc-resourceImplemented
ifc-scheduleImplemented
ifc-schemaImplemented
ifc-spatialImplemented
ifc-stepImplemented
ifc-structuralImplemented
ifc-styleImplemented
ifc-systemsImplemented
ifc-tabularImplemented
ifc-template-catalogImplemented
ifc-validateImplemented
ifc-xmlImplemented
openbim-ifcImplemented
openbim-ifc-binding-coreImplemented
openbim-ifc-capiImplemented
openbim-ifc-cliPartial#329
openbim-ifc-dotnetImplemented
openbim-ifc-pyImplemented
openbim-ifc-wasmImplemented

Geometry items this repository does not address ​

Every concrete IfcRepresentationItem subtype in IFC4 ADD2 TC1 and IFC4X3 ADD2 is named somewhere in this repository -- implemented, refused, or explicitly classified as carrying no shape. This section is generated by walking down from the schema, so it reports zero only when the walk actually finds nothing unaddressed. Being named is not the same as being implemented: see the tables above for the status of each one.

0 of 33 crates are scaffolds.

Core: model, codecs, schema ​

CapabilityStatusEvidence
Entity graph with positional attributesImplementedifc-model::Model
Round-trip of entities the build does not understandImplementedcrates/openbim-ifc/tests/costing_roundtrip.rs (runs with no domain crate compiled)
STEP (.ifc) read and writeImplementedifc-step; deterministic model order, finite scalar safeguards, generic syntax delegated to openbim-step
ifcXML read and writeImplementedifc-xml: its own lossless layout, read and written, typed from the schema when one is given (SchemaReading::Strict), under an exact release namespace with a strict profile (not valid against the XSD; an opt-in xmllint check pins the departures); the buildingSMART XSD configuration of IFC4 ADD2 TC1 and IFC4X3 ADD2, read and written (XmlCodec::xsd), its rules checked against both release XSDs and its IFC4 output validated against IFC4.xsd (opt-in xmllint check); content either layout cannot carry exactly is a typed error
ifcZIP (.ifczip) read and writeImplementedopenbim-ifc feature zip (ifc::ifczip, IfcZipCodec; #450): one STEP or ifcXML model (either layout, detected from its content) at the archive root, per buildingSMART implementation agreement CV-2x3-154; Stored and Deflate only. No model, several, an unknown inner format, an encrypted entry and another compression method are typed refusals; decompression is bounded by an absolute and a ratio budget, checked while inflating. Writes one Deflate entry, reproducibly. Pure Rust (zip with flate2/miniz_oxide). crates/openbim-ifc/tests/ifczip.rs
IFC-JSONAbsentNot planned (#122): buildingSMART's ifcJSON never became a standard; see ADR 0020
IFC5 / IFCXAbsentOut of scope here: a different data model, developed as its own family in openbimrs/ifcx (ADR 0020); the IFC5 schema token is refused with a typed error
EXPRESS schema metadata, subtype queriesImplementedifc-schema
GlobalId base-64 encode/decodeImplementedifc-model::guid
Entities by GlobalId; new GlobalIdsImplementedopenbim-ifc::GlobalIdIndex (built once; a duplicated GlobalId is refused with every holder, never answered with one) and by_guid; new_guid (random, RFC 9562 version 4, through getrandom; in the browser with js-random) and name_based_guid (reproducible, version 8). In every binding. crates/openbim-ifc/tests/object_relations.rs.
An object's type, a type's occurrences, openings and fillingsImplementedopenbim-ifc::{type_of, occurrences_of, openings_of, fillings_of, voided_element_of} read IfcRelDefinesByType, IfcRelVoidsElement and IfcRelFillsElement in IFC2X3, IFC4 and IFC4X3, refusing two answers where the schema allows one. In every binding.
Selector queries; values by pathImplementedopenbim-ifc::selector (feature selector, #464): a versioned grammar close to IfcOpenShell's selector (class, GlobalId, attribute, property, type, material, classification, location and group facets, patterns, , lists and + unions) parsed into a typed query with spanned errors, evaluated over the type, GlobalId, property and relationship indexes; values read and written by path through one checked transaction. In every binding and the select command. Guide; crates/openbim-ifc/tests/selector.rs.
Tables of values by pathImplementedopenbim-ifc::sheet (feature sheet, XLSX with sheet-xlsx, #474): selected entities exported by value paths (attributes, properties, quantities, relations) as CSV, TSV or XLSX keyed by GlobalId or id, and a table imported back as one checked transaction typed by each target's declared or stated type, with a planned diff, every refusal by row and column, and an unchanged table a no-op. In every binding and the export-table, import-table and edit commands. Guide; crates/openbim-ifc/tests/sheet.rs.
Spatial containment tree traversalImplementedifc-spatial::SpatialTree; facade feature spatial. See below.
Element properties by spatial containerImplementedopenbim-ifc::spatial_properties (features spatial and properties): each container in tree order with its contained, aggregated-part and referenced elements, each with its exact property list or its own ExactPropertyError, in IFC2X3, IFC4 and IFC4X3. crates/openbim-ifc/tests/spatial_properties.rs.
Objectified relationship traversalImplementedAll 45 concrete IfcRel* families are read, and IFC2X3's IfcRelAssignsTasks. Spatial composition, containment, coverings, space boundaries, element connection and interference, assignment, declaration and system service in ifc-spatial; association and definition in ifc-classification, ifc-material, ifc-properties, ifc-resource, ifc-approval and ifc-constraint; connectivity in ifc-systems and ifc-structural; sequencing and IFC2X3 task time assignment in ifc-schedule, sequencing in ifc-cost; feature attachment in the openbim-ifc reachability check. Slot positions are asserted against the shipped IFC2x3/IFC4/IFC4x3 schemas in crates/ifc-spatial/tests/slot_layout.rs, and crates/openbim-ifc/tests/relationship_census.rs fails if a family loses its reader.
Distribution systems, ports and connectivityImplementedifc-systems reads systems and membership, ports through both IfcRelNests and the legacy IfcRelConnectsPortToElement, the connection network, flow roles and direction, zones with their WR1 membership rule, spatial containment vs referencing, and direction-aware upstream/downstream queries. Relationship-only: no geometry is read, so a geometry-free file still yields a full network.
Cost items, rates and rollupsImplementedifc-cost reads IfcCostItem nesting, IfcCostValue component trees with arithmetic operators, and totals a cost tree. Currencies are compared, never converted: a rollup mixing EUR and USD is refused. Typed drafts stage selected IFC4 values, items, schedules, nesting, and schedule assignments atomically.
Work schedules, tasks and sequencingImplementedifc-schedule reads IfcWorkPlan/IfcWorkSchedule, IfcTask with IfcTaskTime, IfcRelSequence with signed lag, work calendars and events, and produces a deterministic execution order. Cycles report the offending path.
Transactional authoringImplementedifc-model::Transaction stages structural edits, validates them against the projected end state, and applies them as a unit. A removal that would orphan a surviving reference is refused, as is a commit against a model whose revision moved since the transaction opened. ifc-model remains schema-agnostic; typed staging helpers live in domain crates, including classification, documents, libraries, materials, quantities, cost, style, structural, and resources.
Undo and redoPartialifc-model::Inverse records the exact inverse of a change (attributes, created and removed entities, file and type-index order, header, next free id), and History keeps a bounded undo and redo stack; History::track wraps an authoring batch or any other change as one entry. Applying an inverse writes the same STEP bytes. The language bindings do not expose it yet.
Quantity authoringImplementedifc-properties stages quantity writes onto a caller-owned transaction, so a takeoff spanning many elements lands atomically. The declared measure type is preserved on every write.
Schema validationImplementedifc-validate checks references, required slots, aggregate shape, bounds and element uniqueness, UNIQUE clauses, entity types, abstract instantiation, scalar forms and STRING(n) FIXED widths against the exact schema the file declares (IFC2x3 TC1, IFC4 ADD2 TC1, or IFC4X3 ADD2). Registered rules run under a hard findings-storage cap; the coverage page lists each one and whether it is evaluated. They include external-reference identity, sequence endpoints, decomposition and assignment self-reference, material and path-connection priority bounds, and space-boundary physicality across all three concrete IfcRelSpaceBoundary subtypes. A registered rule that applies to an instance but cannot be decided for it (an operand of a shape it cannot read, a missing target, or an attribute the tables lack) is reported as an evaluation error and makes the report non-conformant, never skipped. Given the release's own .exp text (CC BY-ND 4.0, so supplied at run time, never bundled), ifc_validate::express evaluates every entity WHERE rule, type WHERE rule, global rule and function of IFC2X3, IFC4, IFC4X1, IFC4X2 and IFC4X3 under three-valued logic and step and depth budgets, and checks INVERSE cardinality; UNKNOWN results are reported as indeterminate. On the fixture corpus and IfcOpenShell's own rule fixtures its verdicts match IfcOpenShell's express_rules except where the coverage page lists why. With the PSD/QTO catalog, a Pset_/Qto_ set the release's catalog does not define is a warning, and so are a property or quantity inside a defined set that its template does not declare and a set kind, entity form or value type that differs from it (bSI PSE001). Without the rule text, rules not hand-written are reported as unsupported; a clean report never implies full EXPRESS conformance. The CLI (validate --express FILE.exp) and the JavaScript, Python, C and .NET bindings evaluate the same rules from .exp text the caller supplies.
Property sets and every property value familyImplementedifc-properties reads single, enumerated, bounded, list, table, reference and complex properties. The declared measure type (IfcLengthMeasure and friends) is retained, because it is the only statement of what a bare number means.
Occurrence/type property precedenceImplementedAn occurrence property set overrides a same-named set inherited from the object's type. The shadowed type set is kept, so a checker can explain why an effective value differs from the type default.
Quantities and unit resolutionImplementedSimple and complex quantities, SI prefixes carried as exact decimal exponents, conversion-based and derived units. WR21 (unit matches quantity kind) and WR22 (non-negative value) breaches are reported. ifcopenshell.validate checks both only when its EXPRESS rules are enabled (express_rules=True, --rules), not in its default run. Quantities are read as authored assertions and never computed from geometry.
Unit conversion and a model's length unitImplementedifc-properties::unit_conversion converts between any two units of the same dimensions (SI with prefixes by exact powers of ten, conversion-based units through their factors, derived units by their exponents, IFC4 Table 673 named units with exact factors) and refuses others, monetary and context-dependent units, and offset units pending #110; format_length writes decimal or feet-and-inches text. openbim-ifc::convert_length_unit rescales every length, area and volume value of a model to a new length unit as one transaction, the lengths identified by the release's measure types, parameter values by their curve's or surface's parameter space, map coordinates by their MapUnit, and refuses by name what it cannot carry. In every binding and the CLI (convert-units). IFC2X3, IFC4, IFC4X3: crates/openbim-ifc/tests/length_unit_corpus.rs, length_unit_cases.rs.
Type index (ids_of_type, of_type)ImplementedModel::ids_of_type, Model::of_type, Model::type_histogram
Reverse-reference index ("who references me")Implementedifc-model::ReverseIndex, built on demand; records the attribute slot
Bounded graph traversal with cycle reportsImplementedifc-model::{depth_first, breadth_first, find_cycle} with Budget/Stop
Dangling-reference detectionImplementedModel::dangling_references
Schema-checked entity construction (authoring)Implementedifc-author::EntityBuilder; facade feature author. See below.
Delete a product with its owned data; purge orphansImplementedopenbim-ifc::AuthorOp::RemoveProduct removes a product or type object with what it solely owns (placement, representation, own property sets, material usage, openings, ports, relationships left without an end), decided by reference counts within the batch's one transaction, and reports what it kept as shared and why; dependent placements are refused or re-based with the composed transform, a type with occurrences refused or untyped. AuthorOp::Purge removes resource entities no IfcRoot reaches, or unreferenced entities of named classes; staging the batch is the dry run. In every binding (remove_product, purge); the raw binding remove is deprecated. IFC2X3, IFC4, IFC4X3: crates/openbim-ifc/tests/cascade_delete.rs.
Propagate a type on assignment; replace a type, container or parentImplementedopenbim-ifc::AuthorOp::AssignType with AssignTypeOptions maps the type's RepresentationMaps onto each object as IfcMappedItem representations, derives an IfcMaterialLayerSetUsage or IfcMaterialProfileSetUsage from the type's set with documented defaults, and validates or synchronises PredefinedType; replace unassigns a previous type with what it propagated, and RelateOptions::replace moves an element to another container or aggregate parent. Refusing remains the default; one transaction. In every binding. IFC2X3, IFC4, IFC4X3 door and wall types: crates/openbim-ifc/tests/type_propagation/.
Assemble, assign, copy and remove shape representationsImplementedopenbim-ifc::AuthorOp::ShapeRepresentation assembles an IfcShapeRepresentation from items in a geometric context, its RepresentationType checked against the items by the release's IfcShapeRepresentationTypes (CorrectItemsForType) or inferred as the most specific listed type, its identifier from the sub-context; AssignRepresentation adds it to a product's IfcProductDefinitionShape or wraps it in a type's new IfcRepresentationMap, refusing a second use (IfcShapeModel.WR11); UnassignRepresentation, CopyRepresentation (items copied, context, styles and type maps shared) and RemoveRepresentation (the #478 cascade, shared items kept). In every binding (batch operations; remove_representation). IFC2X3, IFC4, IFC4X3: crates/openbim-ifc/tests/shape_representation.rs.
Copy products and entities; append from another modelImplementedopenbim-ifc::AuthorOp::CopyProduct copies a product or type object with what RemoveProduct would remove with it (placement, moved or replaced by option; representation by CopyRepresentation's rules; own property sets, material usage, ports; openings and fillings by option) and shares what it would keep, the copy joining the type assignment, shared property sets, classification and, by option, container and whole; a CopyReport maps every original to its copy. AuthorOp::CopyEntity deep-copies by an explicit share/copy policy. apply_append copies entities with their closure from another model, reusing equal units, contexts, owner history, materials and styles, moving attributes by name between releases (refused with IncompatibleRelease where the target lacks one), refusing differing length or angle units (UnitMismatch), and keeping, merging or regenerating GlobalIds. In every binding (copy_product, append, batch operations). IFC2X3, IFC4, IFC4X3: crates/openbim-ifc/tests/copy_product.rs, append_model.rs.

Authoring ​

Applications that generate IFC name attributes; the schema decides positions.

rust
use ifc::EntityBuilder; // feature = "author"

let id = EntityBuilder::new(&schema, "IfcAnnotation")
    .text("GlobalId", "3vB2YO$MX4xv5uCqZZG05x")
    .text("Name", "Brandwand")
    .insert(&mut model)?;

Slot order comes from Schema::attributes, which returns inherited attributes first — the ordering positional STEP records depend on. IfcAnnotation gets seven slots because IFC4 declares seven, not because the caller counted.

Construction is refused, rather than silently accepted, for:

FailureExample
Unknown entityIfcAnnotaton (typo)
Unknown attributeIfcAnnotation.RefLatitude (belongs to IfcSite)
Attribute set twicetwo Name calls, instead of a silent overwrite
Required attribute unsetIfcAnnotation with no GlobalId
Declared-type mismatcha string where IfcLengthMeasure is declared
Scalar/aggregate confusiona scalar where LIST OF is declared
Malformed GlobalIdnot 22 characters in IFC's base-64 alphabet

A refused build leaves the model untouched.

What this is not. WHERE rules, inverse attributes, uniqueness, and cross-entity consistency need a whole model rather than one entity; ifc-validate owns those. Value checking is deliberately permissive where a declared type cannot be resolved — see ADR 0007 for why authoring is a schema-layer concern and not a model-layer one.

Model::push remains public and unchecked, for the case where an application must write an entity the schema does not declare.

Spatial traversal ​

IFC stores no parent pointers: a wall does not name its storey, a relationship entity names both ends. ifc-spatial reads those relationships into a tree.

rust
use ifc::{SpatialKind, SpatialTree}; // feature = "spatial"

let tree = SpatialTree::build(&model);

for level in tree.of_kind(SpatialKind::Storey) {
    for element in tree.elements_of(level.id) {
        println!("{element} is placed directly on {}", level.id);
    }
}

let home = tree.container_of(wall); // which storey is this wall on?
let above = tree.ancestors(storey); // storey -> building -> site -> project
let beneath = tree.elements_recursive(building); // everything beneath a container

The trap this closes. The two relationships that build the tree disagree about slot order — IfcRelAggregates puts the parent in slot 4, IfcRelContainedInSpatialStructure puts it in slot 5. Reading one like the other inverts containment silently. The constants are asserted against IFC2x3, IFC4 and IFC4x3 in crates/ifc-spatial/tests/slot_layout.rs; see ADR 0008.

Real files, not the ideal shape. Omitted sites, elements hung directly off a building, duplicate storeys, relationships naming absent entities, and containment cycles are all handled and, where they are defects, reported through orphans() and dangling() rather than dropped. One corpus fixture turned out to use IfcRelAggregates exclusively with no containment relationship at all; that case is pinned in tests/real_files.rs.

Containers come from the declared release. An entity is a spatial container when the release in FILE_SCHEMA declares it an IfcSpatialElement (IFC2X3: IfcSpatialStructureElement), so the IFC4X3 facilities (IfcRoad, IfcBridge, IfcRailway, IfcMarineFacility) and their parts hold elements like a storey does. Containment or reference into something that is not a container is reported through anomalies().

Contained is not referenced. IfcRelReferencedInSpatialStructure adds an element to structures it spans without being contained there (a curtain wall contained by the ground floor and referenced by the storeys above). referenced_elements() and referencing_structures() answer it apart from elements_of() and container_of(), so a multi-storey element never looks contained twice.

What this is not. It reports what the file says and never rejects it — cardinality and WHERE rules belong to ifc-validate. It groups elements; it does not interpret their geometry or properties. The facade's spatial_properties (features spatial and properties) joins the two: each container's contained, part and referenced elements with their exact properties, an error reported on the element it concerns.

Construction resources ​

With facade feature resource, ifc-resource selects IFC4 ADD2 TC1 or IFC4X3 ADD2 from the model header and exposes borrowed views for labor, equipment, crew, construction material, construction product, and subcontract occurrences. It resolves authored IfcResourceTime, validates and queries IfcRelAssignsToResource including its authored RelatedObjectsType category constraint, and walks resource composition through IfcRelNests with authored order plus explicit cycle, multiple-parent, depth, and node failures. Selected records and relationships can be created through schema-checked transaction-staged drafts; they reject duplicate GlobalId values and cycle/second-parent creation before staging. See the construction-resource guide.

This is a partial, deliberately bounded profile covering IFC4 and IFC4X3. It does not level or schedule resources, calculate costs/durations/quantities, interpret calendars, or claim IFC2X3 support (the schema does not declare the entities this crate projects).

Geometry ​

ifc-geometry is the largest crate in the workspace. It resolves IFC units, placements, profiles, and representation relationships, then lowers implemented families into the neutral axiolid-model DAG.

Representation-item lowering ​

The dispatcher keeps coverage as data so it is auditable from one table (crates/ifc-geometry/src/lower/dispatch.rs). The table covers IFC4 ADD2 TC1 and IFC4X3 ADD2: crates/ifc-geometry/tests/schema_coverage.rs lists the representation items IFC4X3 adds from IFC4X3_ADD2.exp, and fails when one is neither implemented nor planned with a reason.

FamilyStatus
IfcExtrudedAreaSolidImplemented
IfcRevolvedAreaSolidImplemented
IfcBooleanResultImplemented
IfcBooleanClippingResultImplemented
IfcMappedItemImplemented
IfcFacetedBrepImplemented
IfcFacetedBrepWithVoidsImplemented
IfcAdvancedBrepImplemented
IfcAdvancedBrepWithVoidsImplemented
IfcHalfSpaceSolidImplemented
IfcBoxedHalfSpaceImplemented
IfcPolygonalBoundedHalfSpaceImplemented
IfcTriangulatedFaceSetImplemented
IfcTriangulatedIrregularNetworkPartial — 2 authored form(s) refused; see variants
IfcPolygonalFaceSetImplemented
IfcCsgSolidImplemented
IfcSweptDiskSolidImplemented
IfcSweptDiskSolidPolygonalImplemented
IfcSurfaceCurveSweptAreaSolidImplemented
IfcBlockImplemented
IfcSphereImplemented
IfcRightCircularCylinderImplemented
IfcRightCircularConeImplemented
IfcRectangularPyramidImplemented
IfcBoundingBoxImplemented
IfcExtrudedAreaSolidTaperedImplemented
IfcRevolvedAreaSolidTaperedImplemented
IfcFixedReferenceSweptAreaSolidImplemented
IfcDirectrixDerivedReferenceSweptAreaSolidPartial — 1 authored form(s) refused; see variants
IfcSectionedSpineImplemented
IfcShellBasedSurfaceModelImplemented
IfcFaceBasedSurfaceModelImplemented
IfcFaceSurfaceImplemented
IfcAdvancedFaceImplemented
IfcGeometricSetImplemented
IfcGeometricCurveSetImplemented
IfcLineImplemented
IfcCircleImplemented
IfcEllipseImplemented
IfcPolylineImplemented
IfcIndexedPolyCurveImplemented
IfcCompositeCurveImplemented
IfcCompositeCurveOnSurfaceImplemented
IfcBoundaryCurveImplemented
IfcOuterBoundaryCurveImplemented
IfcTrimmedCurveImplemented
IfcOffsetCurve2DImplemented
IfcOffsetCurve3DImplemented
IfcPcurvePartial — 2 authored form(s) refused; see variants
IfcSurfaceCurvePartial — 1 authored form(s) refused; see variants
IfcIntersectionCurveImplemented
IfcSeamCurveImplemented
IfcBSplineCurveWithKnotsImplemented
IfcRationalBSplineCurveWithKnotsImplemented
IfcPlaneImplemented
IfcCylindricalSurfaceImplemented
IfcSphericalSurfaceImplemented
IfcToroidalSurfaceImplemented
IfcSurfaceOfLinearExtrusionImplemented
IfcSurfaceOfRevolutionImplemented
IfcRectangularTrimmedSurfaceImplemented
IfcCurveBoundedPlaneImplemented
IfcCurveBoundedSurfaceImplemented
IfcBSplineSurfaceWithKnotsImplemented
IfcRationalBSplineSurfaceWithKnotsImplemented
IfcPointOnCurveImplemented
IfcPointOnSurfaceImplemented
IfcCurveSegmentPartial — 3 authored form(s) refused; see variants
IfcGradientCurvePartial — 3 authored form(s) refused; see variants
IfcPointByDistanceExpressionPartial — 3 authored form(s) refused; see variants
IfcAxis2PlacementLinearPartial — 1 authored form(s) refused; see variants
IfcOffsetCurveByDistancesPartial — 1 authored form(s) refused; see variants
IfcSectionedSolidHorizontalPartial — 1 authored form(s) refused; see variants
IfcSectionedSurfacePartial — 1 authored form(s) refused; see variants
IfcClothoidPlanned — an IfcSpiral is unbounded (-inf < u < inf) and the neutral intrinsic curve needs a finite arc length; it lowers exactly as the ParentCurve of an IfcCurveSegment
IfcSecondOrderPolynomialSpiralPlanned — an IfcSpiral is unbounded (-inf < u < inf) and the neutral intrinsic curve needs a finite arc length; it lowers exactly as the ParentCurve of an IfcCurveSegment
IfcThirdOrderPolynomialSpiralPlanned — an IfcSpiral is unbounded (-inf < u < inf) and the neutral intrinsic curve needs a finite arc length; it lowers exactly as the ParentCurve of an IfcCurveSegment
IfcSeventhOrderPolynomialSpiralPlanned — an IfcSpiral is unbounded (-inf < u < inf) and the neutral intrinsic curve needs a finite arc length; it lowers exactly as the ParentCurve of an IfcCurveSegment
IfcCosineSpiralPlanned — an IfcCosineSpiral or IfcSineSpiral law depends on the length L of the IfcCurveSegment using it; it lowers exactly only as the ParentCurve of an IfcCurveSegment
IfcSineSpiralPlanned — an IfcCosineSpiral or IfcSineSpiral law depends on the length L of the IfcCurveSegment using it; it lowers exactly only as the ParentCurve of an IfcCurveSegment
IfcPolynomialCurvePlanned — an IfcPolynomialCurve is unbounded (-inf < u < inf) and the neutral vocabulary has no unbounded polynomial curve; it lowers exactly as the ParentCurve of an IfcCurveSegment
IfcSegmentedReferenceCurvePlanned — IfcSegmentedReferenceCurve segments are curves in the (distance along, deviating elevation) space of its base curve, and no normative rule maps a segment's ParentCurve and placement Axis to a cant law and pivot: implementations differ in the coefficient scaling (cant kappaL or kappaL^2) and the cross slope (sine or tangent of cant over rail head distance); the business cant layout lowers to a banked curve through ifc-alignment (#311)

Partially supported variants ​

Families marked Partial above lower some authored forms exactly and refuse others by name. This table is generated from the PARTIAL catalog in crates/ifc-geometry/src/lower/dispatch.rs, and tests/lower_dispatch_corpus.rs drives the real lowering path for every row -- so a wrong disposition here fails CI rather than merely misinforming a reader.

Some of these refusals exist because the schema permits a combination the geometry cannot honour, rather than because the feature is unimplemented. Those are listed with their reasoning in Schema looseness.

FamilyVariantStatusRationale
IfcAxis2PlacementLinearAxis and RefDirection absent, or 3D and not parallelAdmittedan OrientedCurveStation: the ratios are components in the curve's (tangent, left, up) frame, Axis exact and RefDirection orthogonalised against it, as 8.9.3.4 states
IfcAxis2PlacementLinearLocation is refused as an IfcPointByDistanceExpressionRefusedthe placement is its station; see IFCPOINTBYDISTANCEEXPRESSION
IfcCurveSegmentParentCurve is an IfcLine, IfcCircle or 2D IfcPolyline, measured by IfcLengthMeasureAdmitteda line, arc or polyline cut by arc length and placed rigidly is elementary: a polyline or an angle-trimmed circle
IfcCurveSegmentParentCurve is an IfcSpiral subtype, measured by IfcLengthMeasureAdmittedthe spiral's curvature law, rebased to the segment in closed form, on a planar intrinsic curve; nothing is integrated
IfcCurveSegmentSegmentLength is zero (the closing segment of a layout)Admittedits placement exactly: a planar intrinsic curve of length zero
IfcCurveSegmentParentCurve is a 2D IfcPolynomialCurve with a degree-one coordinate, cut forwards from SegmentStart 0Admittedits Bezier over a closed-form parameter bound, placed rigidly and trimmed at TrimSelector::ArcLength: the kernel inverts the arc length, nothing is integrated here
IfcCurveSegmentParentCurve is an IfcPolynomialCurve cut from a non-zero SegmentStart, walked backwards, 3D, or with no degree-one coordinateRefusedthe placed start point inverts a non-elementary arc-length integral, a 3D polynomial has no plane for the placement, and without a degree-one coordinate the trim has no closed-form parameter bound
IfcCurveSegmentSegmentStart or SegmentLength is an IfcParameterValueRefusedSegmentStart/SegmentLength given as IfcParameterValue: IFC4.3 ADD2 defines no parametric space for IfcCurveSegment parents yet (informal proposition 1 requires IfcLengthMeasure)
IfcCurveSegmentPlacement is an IfcAxis2PlacementLinear, the segment met on its own or in a plain IfcCompositeCurveAdmittedan InstanceAtStation: the parent's piece in local coordinates placed in the frame of the OrientedCurveStation the placement lowers to, local X, Y, Z on the station's tangent, left and up as 8.9.3.4 reads them; the kernel resolves the station
IfcCurveSegmentPlacement is an IfcAxis2PlacementLinear in an IfcGradientCurveRefusedan IfcAxis2PlacementLinear placement stands at a station along a basis curve, which only a kernel resolves; a segment of an IfcGradientCurve is read as a plan or profile piece and needs a resolved placement
IfcDirectrixDerivedReferenceSweptAreaSoliddirectrix defines only a tangent (no IfcCurveSegment, segment-built or surface curve reachable)AdmittedIFC4.3 gives it exactly the behaviour of IfcFixedReferenceSweptAreaSolid in this case, so it lowers to the same FixedReferenceSweep
IfcDirectrixDerivedReferenceSweptAreaSoliddirectrix defines a tangent planeRefusedkernel: the directrix defines a tangent plane (it is built from IfcCurveSegment placements or lies on a surface), so the derived reference adds that plane's rotation to FixedReference; the neutral FixedReferenceSweep carries only a constant reference direction
IfcGradientCurvehorizontal IfcCurveSegments over lines, arcs, spirals and 2D IfcPolynomialCurves; vertical IfcCurveSegments over IfcLine, IfcCircle, an IfcSpiral subtype, or a degree-2 IfcPolynomialCurve that keeps its start tangentAdmittedone plan parameterised by arc length (an intrinsic curve, or an arc-length chain with a polynomial piece) plus a piecewise elevation law of polynomial, circular and intrinsic pieces: Curve3::Elevated, exact
IfcGradientCurvea vertical parabola or spiral with no following segment, closing segment or EndPointRefusedits plan extent inverts a non-elementary arc-length integral, and nothing states it
IfcGradientCurvea heading kink, a closed-form position gap, or a profile that does not span the base curveRefusedone plan curve and one elevation law cannot carry a kink or a gap, and an elevation law must cover the whole plan
IfcGradientCurveplaced by a frame that tilts, scales or mirrors the verticalRefuseda plan plus a height is carried only by frames that keep the vertical axis
IfcOffsetCurveByDistancesOffsetValues along its own BasisCurve, spanning it or on a basis with a stated length, across its tangent discontinuities tooAdmittedOffsetByStations, linear between the offsets; a span short of the ends is carried on unchanged to them by added stations, as 8.9.3.42.3 states; mitred at a seam like the sweeps on the same stations (8.8.3.35.1)
IfcOffsetCurveByDistancesOffsetValues short of the ends of a bounded basis whose length lies at an arc-length integral (an offset beside a gradient curve, a spiral, a B-spline or an ellipse, a relation with an ellipse or a B-spline piece, a B-spline or an ellipse)AdmittedOffsetsAtStations continued by stations at the basis's start and end, whose distances the kernel measures (RunStation::at_basis_start / at_basis_end, axiolid/kernel#303, #433), as 8.9.3.42.3 states; stations carry the kernel's seam-snapping window where the seams are quadratures (#429); a stated station at or past the end the kernel measures is refused by it by name
IfcOffsetCurveByDistancesoffsets short of an unbounded end, a non-zero OffsetLongitudinal, a member on another basis, or a run across a seam where the basis turns back on itselfRefusedan unbounded line has no end to continue the offsets to and the neutral offset curve stops at its last station, IFC states no law for a longitudinal offset along a curve, and a mitre has no plane at a reversal
IfcPcurvereference curve is an IfcPolylineAdmittedan ordered 2D point sequence needs no evaluation
IfcPcurvereference curve is an IfcIndexedPolyCurve with no explicit Segments, or only IfcLineIndex segmentsAdmittedreads identically to a plain ordered point sequence
IfcPcurvereference curve is an IfcLine, IfcCircle or IfcEllipse positioned by an IfcAxis2Placement2DAdmitteddefining values are read verbatim in the surface's own (u, v) domain with no unit conversion
IfcPcurvereference conic positioned by an IfcAxis2Placement3DRefuseda 3D placement's axis has no meaning in a 2D parameter domain; admitting it would require inventing a projection
IfcPcurvereference curve is an IfcIndexedPolyCurve with an explicit IfcArcIndex segmentAdmitteda three-point arc composes exactly from a parameter-space circumcentre into Circle2 plus a Cartesian trim, mirroring the 3D path with no approximation
IfcPcurvereference curve is an explicit-knot IfcBSplineCurveWithKnots or IfcRationalBSplineCurveWithKnotsAdmittedevery field is dimensionless or a curve parameter; knots already pass through the 3D path unscaled, and control points are read as raw (u, v) pairs
IfcPcurvereference curve is a trimmed or composite curveAdmittedtrim parameters and segments stay in the surface (u, v) domain, unscaled, so no dimensional contract is needed
IfcPcurvereference curve is a convention-only IfcBSplineCurveRefuseda base spline carries no authored knot vector to preserve
IfcPointByDistanceExpressionDistanceAlong is an IfcLengthMeasure on the basis curve, on or off its tangent discontinuitiesAdmitteda CurveStation: distance (plan distance on a gradient curve, arc length otherwise) and the lateral (left), vertical and longitudinal offsets, in the same frame IFC4.3 ADD2 8.9.3.48 states; within precision of a seam, at the seam reading SeamSide::Incoming, since the previous segment's tangent governs (8.9.3.48.3)
IfcPointByDistanceExpressionDistanceAlong is an IfcParameterValueRefusedIFC4.3 ADD2 gives most basis curves no parameterisation a distance can be read from, and a neutral station is a distance
IfcPointByDistanceExpressionDistanceAlong on a composite, trimmed or surface curve, or on segments placed at stations, whose pieces' lengths are stated by their dataAdmitteda station along the curve relation, measured end to end through its pieces (axiolid/kernel#285); every joint is a seam, and within precision of one the station stands on it reading SeamSide::Incoming, the previous segment (8.9.3.48.3)
IfcPointByDistanceExpressionDistanceAlong on a basis whose tangent discontinuities lie at arc-length integrals: an offset whose length is a quadrature (beside a gradient curve, a spiral, a B-spline or an ellipse, or a variable offset of a circle), a relation with an ellipse or a B-spline piece, a B-spline with a corner knotAdmittedan OrientedCurveStation at its own distance reading SeamSide::Incoming, with the model's precision as its seam-snapping window (axiolid/kernel#294, #423): the kernel reads it on a seam within the window, from the previous segment (8.9.3.48.3), at its own certified distance, and refuses two seams in the window, a seam on its edge and a length it cannot certify by name
IfcPointByDistanceExpressionDistanceAlong on an IfcOffsetCurve2D/3D or an IfcOffsetCurveByDistances of lines, polylines or circles (a constant offset of a circle in its plane)Admitteda station along the offset relation, in the offset's own length (axiolid/kernel#289); every seam of the basis and every OffsetValues station is a joint, and within precision of one the station stands on it reading SeamSide::Incoming, the previous segment (8.9.3.48.3); IFC's positive Distance (anticlockwise normal) is Axiolid's left
IfcPointByDistanceExpressionDistanceAlong on an offset of an offset, a trim of an offset, an offset through a circle's centre, or an offset across a corner of its basisRefusedkernel: Axiolid measures a station along an offset of atomic pieces whose sides meet, in its own length
IfcPointByDistanceExpressionDistanceAlong on a relation joining gradient curves with other piecesRefusedkernel: no one distance runs through pieces measured in plan distance and in arc length
IfcSectionedSolidHorizontalarea sections at positions along the Directrix, across its tangent discontinuities tooAdmittedSectionsAtStations in the curve's frame, matched by ring and index; RefDirection is the profile normal and Axis profile Y (IFC4.x-IF#147, IFC4.x-development#1010); a seam is mitred at half angle (8.8.3.35.1)
IfcSectionedSolidHorizontalarea sections along a Directrix whose seams lie at arc-length integrals (an offset beside a gradient curve, a spiral, a B-spline or an ellipse, or a B-spline corner knot)Admittedeach section carries the model's precision as the kernel's seam-snapping window, reading SeamSide::Incoming (axiolid/kernel#301, #429): the kernel snaps it onto a seam within the window and mitres there at half angle (8.8.3.35.1), and refuses two seams in a window, a seam on its edge, a length it cannot certify and positions no longer increasing once snapped by name
IfcSectionedSolidHorizontalpositions off the Directrix, or spanning a seam where it turns back on itselfRefuseda station measures along its own basis, and "very sharp edges may result in nearly impossible miter" (8.8.3.35.1)
IfcSectionedSurfaceopen sections tagged throughout or not at all, with one tag setAdmittedOpenSectionsAtStations joined by tag, forwards or reversed; profile X to the left as IfcOpenCrossProfileDef states (8.15.3.15.1, #344)
IfcSectionedSurfaceopen sections along a Directrix whose seams lie at arc-length integralsAdmittedas IFCSECTIONEDSOLIDHORIZONTAL: each section carries the kernel's seam-snapping window and the incoming side (axiolid/kernel#301, #429), mitred at half angle where it snaps (8.8.3.37.1)
IfcSectionedSurfacemixed tagging or branching breaklines (sections with different Tags)Refusedthe neutral surface joins one tag set through every section
IfcSurfaceCurveMasterRepresentation is Curve3D, PCurveS1, or PCurveS2 with the named side presentAdmittedeach side pairs a surface with its own p-curve, so the neutral MasterRepresentation names S1 and S2 exactly
IfcSurfaceCurveMasterRepresentation is PCurveS2 with only one associated p-curveRefusedthe master names a parametric side the curve does not have; the schema calls this inconsistent, so it is refused rather than resolved to the remaining p-curve
IfcTriangulatedIrregularNetworkevery Flags value is a breakline code, 0 to 7Admitteda breakline marks an edge the triangulation already has, so the triangle surface is the supertype's; the flags are not carried into the mesh
IfcTriangulatedIrregularNetworka Flags value is -1 (hole) or -2 (void)Refusedthe triangle is excluded from the surface, and a hole may fall back on another surface; the neutral mesh has no face-exclusion or fall-back channel
IfcTriangulatedIrregularNetworka Flags value is outside -2 to 7Refusedthe documentation defines no meaning for it

Coverage below is generated

The table above is derived from crates/ifc-geometry/src/lower/dispatch.rs by cargo run -p xtask -- docs, and scripts/gate.sh fails when this page and that source disagree. It cannot drift from the code without breaking the build.

Unimplemented families return a typed GeometryError::Unsupported naming the source entity and the specific missing capability — never a panic, and never a silently substituted approximate shape.

Profile lowering ​

Swept solids reference a profile, so profile coverage bounds how much of a real model lowers. Steel sections carry their fillet radii, edge radii and flange slopes into the neutral model rather than being reduced to an outline, because a section without them has the wrong area and the wrong section modulus.

An arbitrary profile's boundary is either an IfcPolyline or an IfcCompositeCurve of polylines, trimmed circles and lines, and nested composites. Arcs stay exact. A composite whose segments do not meet within 1e-5 m is refused rather than closed with an edge the file never authored, and any other boundary curve family is refused by name.

Profile familyStatus
IfcArbitraryClosedProfileDefImplemented
IfcArbitraryOpenProfileDefImplemented
IfcArbitraryProfileDefWithVoidsImplemented
IfcAsymmetricIShapeProfileDefImplemented
IfcCenterLineProfileDefImplemented
IfcCircleHollowProfileDefImplemented
IfcCircleProfileDefImplemented
IfcCompositeProfileDefImplemented
IfcCShapeProfileDefImplemented
IfcDerivedProfileDefImplemented
IfcEllipseProfileDefImplemented
IfcIShapeProfileDefImplemented
IfcLShapeProfileDefImplemented
IfcMirroredProfileDefImplemented
IfcOpenCrossProfileDefImplemented
IfcRectangleHollowProfileDefImplemented
IfcRectangleProfileDefImplemented
IfcRoundedRectangleProfileDefImplemented
IfcTShapeProfileDefImplemented
IfcTrapeziumProfileDefImplemented
IfcUShapeProfileDefImplemented
IfcZShapeProfileDefImplemented
IfcProfileDefRefused — generic profile declaration carries no concrete geometry to lower

IfcArbitraryOpenProfileDef is implemented through the explicit lower_open_profile_node authored-path API. It is not an area profile and is therefore still refused when an extrusion or other area-based solid requests lower_profile.

The boundary curves of IfcArbitraryClosedProfileDef and IfcArbitraryProfileDefWithVoids lower from IfcPolyline, IfcCompositeCurve (polylines, trimmed circles and lines, nested composites) and IfcIndexedPolyCurve (line and exact three-point arc segments, or one polyline without Segments). An arc whose three points are collinear within the model's Precision is the polyline through them, as IFC prescribes. An open boundary, an arc with coincident points and SelfIntersect TRUE are refused as degenerate, never closed or chorded; other curve families are refused as unsupported.

Curves and placement ​

CapabilityStatusModule
IfcPolyline, IfcIndexedPolyCurveImplementedexact line and three-point arc segments; an arc collinear within the model's Precision is its polyline segment, as IFC prescribes (#396)
IfcCircle, IfcEllipseImplementedcurve/conic.rs
IfcLineImplementedcurve/line.rs
IfcTrimmedCurveImplementedcurve/trimmed.rs
IfcCompositeCurveImplementedcurve/composite.rs
Convention-only IfcBSplineCurvePartialtyped view only; lowering does not invent absent knots
IfcBSplineCurveWithKnots, IfcRationalBSplineCurveWithKnotsImplementedcurve/bspline.rs representation + exact neutral lowering
IfcOffsetCurve2D/3DImplementedcurve/offset.rs
IfcPcurve, IfcSurfaceCurve, IfcIntersectionCurvePartialexact supported forms; typed refusal otherwise
IfcAxis2Placement2D/3DImplementedresource/placement.rs
IfcCartesianTransformationOperator*Implementedresource/operator.rs
Unit resolution (SI, conversion-based)Implementedunits.rs

Curves lower in nested and curve-representation paths

lower/curve.rs lowers polylines/indexed poly-curves, conics, lines, trims, composites, offsets and surface-associated curves, plus explicit-knot polynomial/rational B-splines into the neutral graph. Convention-only base splines remain unsupported. Curves reach this lowerer through a sweep directrix, a surface boundary, a B-rep edge, or an IfcGeometricCurveSet member.

Bare curves are dispatch targets for Curve2D, Curve3D, and plan representations. Selection remains explicit: callers choose Body or Plan; a plan curve never silently replaces a body.

Explicit-knot surfaces ​

CapabilityStatusModule
Convention-only IfcBSplineSurfacePartialtyped view only. Lowering requires an explicit knot vector, so IfcBSplineSurfaceWithKnots lowers and the convention-only parent form does not: deriving the implied knots would be inventing geometry the file did not state.

Representation selection ​

Two selectors, deliberately disagreeing:

rust
use ifc::{select_plan_representation, select_shape_representation};

let body = select_shape_representation(&model, wall)?; // what a 3D viewer draws
let outline = select_plan_representation(&model, wall)?; // what a drawing draws

select_shape_representation prefers Body, then Facetation, then an unnamed representation, and refuses Axis/FootPrint so a 2D curve never silently replaces a solid.

select_plan_representation is its inverse. It prefers, in order:

  1. a PLAN_IDENTIFIERS match inside a PLAN_VIEW sub-context — drawable geometry the author explicitly targeted at a plan;
  2. otherwise the best PLAN_IDENTIFIERS match in any context: Plan, Annotation, FootPrint, Axis.

The two rules are intersected, not ordered. Authorial intent selects between drawable candidates; it does not make a bounding box drawable. ArchiCAD writes Box/BoundingBox representations inside PLAN_VIEW sub-contexts, so a context-first rule returns those boxes and never reaches the identifier list.

It returns None for a solid-only or box-only product. That is the honest answer, not a failure: deriving a plan from a solid requires sectioning, which this library does not do — see R9b/R10 on the roadmap.

Representation context ​

CapabilityStatusEvidence
IfcGeometricRepresentationContextImplementedRepresentationContext; identifier, type, precision, placement
IfcGeometricRepresentationSubContextImplementedparent, target scale, target view
TargetView (PLAN_VIEW, MODEL_VIEW, ...)Implementedtyped enum; unknown constants preserved, not flattened
Authoring a plan sub-contextImplementedifc_georef::create_representation_subcontext (parent context, identifier, target view, with the ParentNoSub and UserTargetProvided rules); also constructible via EntityBuilder
rust
use ifc::plan_contexts; // feature = "geometry-select"

for context in plan_contexts(&model) {
    let scale = context.target_scale(); // Some(0.01) for 1:100
    let precision = context.precision(&model); // inherited from the parent context
    println!("plan view at {scale:?}, precision {precision:?}");
}

The * trap this closes. A sub-context redeclares six inherited attributes as DERIVED, and real files write them as *:

text
IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Body','Model',*,*,*,*,#1,$,.MODEL_VIEW.,$)

* is not $ — it means "read this from my parent". Accessors that take &model (precision, world_coordinate_system, coordinate_space_dimension, true_north) walk ParentContext to resolve it. A consumer reading the slot directly gets the marker and loses the project's precision and placement. See ADR 0009.

Slot positions are asserted against IFC2x3, IFC4 and IFC4x3 in crates/ifc-geometry/tests/context_slots.rs, including that the sub-context still inherits exactly six attributes — the off-by-six that would read TargetScale as the target view.

Presentation, annotation, and external references ​

These are the areas most relevant to drawing production and document/approval workflows. Presentation and annotation have schema-resolved typed views and bounded transaction-staged authoring; rendering and drawing layout remain outside the domain contracts. Approvals and constraints have bounded typed views and authoring (the whole approval resource schema is not claimed). External classification/document/library references have typed read/query/authoring coverage.

Entity / conceptStatusNote
IfcAnnotationImplementedStrict borrowed view and transaction-staged authoring; IFC4X3 PredefinedType remains version-conditional
IfcTextLiteral, IfcTextLiteralWithExtentImplementedStrict literal/placement/path/extent views and transaction-staged authoring
IfcAnnotationFillAreaImplementedType-checked outer/inner boundary views and transaction-staged authoring
IfcCurveStyle, IfcFillAreaStyleImplementedSchema-resolved curve/font/fill/hatch/tile views; no rendering claim
IfcSurfaceStyle and childrenImplementedRGB/factor, shading, rendering, lighting, refraction, and texture views; core surface graph authoring
IfcPresentationLayerAssignmentImplementedLayer membership/style/visibility view and styled-layer authoring
IfcStyledItemImplementedStrict direct assignment view/writer and deterministic direct-over-layer resolution; IFC2x3 wrappers are explicit
IfcShapeRepresentationAbsentGeneric Representation view exists; the subtype does not
IfcGeometricRepresentationSubContextPartialStrict inherited view and plan-context query exist; authoring uses generic EntityBuilder, not a dedicated helper
IfcLibraryReferenceImplementedStrict borrowed view and transaction-staged authoring
IfcLibraryInformationImplementedStrict borrowed view and transaction-staged authoring
IfcRelAssociatesLibraryImplementedDeterministic object lookup and transaction-staged authoring
IfcExternalReference and IfcLibrarySelectImplementedInherited fields are exposed by concrete views; select targets are type-checked
IfcExternalReferenceRelationshipImplementedifc-classification owns strict selected projections, deterministic lookup, and transaction-staged authoring
IfcApproval and selected approval relationshipsImplementedifc-approval owns bounded IFC4 projections, queries, and transaction-staged authoring; the whole IfcApprovalResource schema is not claimed
IfcMetric, IfcObjective, and selected constraint relationshipsImplementedifc-constraint preserves typed metric values and stages bounded IFC4 authoring without evaluating constraints
IfcClassificationReferenceImplementedBounded hierarchy, explicit occurrence/type sources, and authoring

Because ifc-model round-trips entities structurally, every row above reads and re-exports without loss. The status distinguishes that baseline from typed interpretation and authoring; only rows marked implemented expose those domain contracts.

Explicit non-goals ​

  • A CAD modelling kernel. Booleans, tessellation, and NURBS evaluation live in Axiolid or its providers.
  • Rendering, drawing layout, or paper-space composition.
  • Vendored ISO or buildingSMART schema payloads (the contributing guide).
  • Any C++ in the dependency graph.
  • IFC5 / IFCX and a JSON serialisation of the EXPRESS releases (ADR 0020).

How to verify a claim on this page ​

  1. Read the crate's public API and its tests/ directory.
  2. Read the crate's README.md and module docs for its design notes, and its reference page for its latest release notes.
  3. Run the gate: scripts/gate.sh. It regenerates every table on this page and on the coverage page and fails if the committed copy differs.
  4. For geometry coverage, read crates/ifc-geometry/src/lower/dispatch.rs; the tables above are generated from its IMPLEMENTED, PLANNED and PARTIAL constants, which tests assert against the schema.

Released under the AGPL-3.0-or-later licence. ISO and CEN standards material is not redistributed.