From 3f42e02cb4c390bdb1844b8bdc44129c49e34be7 Mon Sep 17 00:00:00 2001 From: Petru Conduraru Date: Mon, 13 Jul 2026 06:27:17 +0300 Subject: [PATCH] Fix #8570: populate ifc5d IfcOpenShell QTO formulas for IfcSpace The headless "IfcOpenShell" calculator had all Qto_SpaceBaseQuantities formulas set to null for IfcSpace in both IFC4QtoBaseQuantities.json and IFC4X3QtoBaseQuantities.json, so qto.py's `if not formula: continue` skipped every quantity, no geometry task was queued, and spaces never appeared in results (elements_quantified: 0). The Blender calculator already computes these; they were just never ported to the ifcopenshell.util.shape-backed calculator. Map the eight computable quantities to existing util.shape functions, mirroring the Blender calculator semantics (no new shape.py code): GrossFloorArea=gross_get_footprint_area, NetFloorArea=net_get_footprint_area, GrossCeilingArea=gross_get_top_area, NetCeilingArea=net_get_top_area, GrossPerimeter=gross_get_footprint_perimeter, GrossVolume=gross_get_volume, NetVolume=net_get_volume, Height=net_get_z. Left null (matching the Blender ruleset, not guessed): GrossWallArea, NetWallArea, NetPerimeter (Blender stub), and FinishFloor/CeilingHeight (Blender derives these from sibling IfcCovering decomposition geometry, which this per-element calculator architecture can't reach). Verified on IFC4 (4x3 space extruded 2.5m): before -> {} / elements_quantified 0; after -> GrossFloorArea 12, GrossPerimeter 14, Height 2.5, GrossVolume 30, etc. - all exact matches to the extrusion. IFC4X3 formulas are identical and the formula->function resolution is schema-agnostic. Scope: fixes the IfcSpace case (the issue title). The 12 other all-null classes noted in the issue (IfcDoor, IfcSite, IfcRailing, ...) are left as follow-up. This change was made with the assistance of an AI tool. Co-Authored-By: Claude Fable 5 (cherry picked from commit 60858944331a723118f822edd2bf821709c94496) --- src/ifc5d/ifc5d/IFC4QtoBaseQuantities.json | 16 ++++++++-------- src/ifc5d/ifc5d/IFC4X3QtoBaseQuantities.json | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/ifc5d/ifc5d/IFC4QtoBaseQuantities.json b/src/ifc5d/ifc5d/IFC4QtoBaseQuantities.json index aa3a80b632..c002cfaa4c 100644 --- a/src/ifc5d/ifc5d/IFC4QtoBaseQuantities.json +++ b/src/ifc5d/ifc5d/IFC4QtoBaseQuantities.json @@ -529,16 +529,16 @@ "Qto_SpaceBaseQuantities": { "FinishCeilingHeight": null, "FinishFloorHeight": null, - "GrossCeilingArea": null, - "GrossFloorArea": null, - "GrossPerimeter": null, - "GrossVolume": null, + "GrossCeilingArea": "gross_get_top_area", + "GrossFloorArea": "gross_get_footprint_area", + "GrossPerimeter": "gross_get_footprint_perimeter", + "GrossVolume": "gross_get_volume", "GrossWallArea": null, - "Height": null, - "NetCeilingArea": null, - "NetFloorArea": null, + "Height": "net_get_z", + "NetCeilingArea": "net_get_top_area", + "NetFloorArea": "net_get_footprint_area", "NetPerimeter": null, - "NetVolume": null, + "NetVolume": "net_get_volume", "NetWallArea": null } }, diff --git a/src/ifc5d/ifc5d/IFC4X3QtoBaseQuantities.json b/src/ifc5d/ifc5d/IFC4X3QtoBaseQuantities.json index 2f1a56ffac..017e164119 100644 --- a/src/ifc5d/ifc5d/IFC4X3QtoBaseQuantities.json +++ b/src/ifc5d/ifc5d/IFC4X3QtoBaseQuantities.json @@ -665,16 +665,16 @@ "Qto_SpaceBaseQuantities": { "FinishCeilingHeight": null, "FinishFloorHeight": null, - "GrossCeilingArea": null, - "GrossFloorArea": null, - "GrossPerimeter": null, - "GrossVolume": null, + "GrossCeilingArea": "gross_get_top_area", + "GrossFloorArea": "gross_get_footprint_area", + "GrossPerimeter": "gross_get_footprint_perimeter", + "GrossVolume": "gross_get_volume", "GrossWallArea": null, - "Height": null, - "NetCeilingArea": null, - "NetFloorArea": null, + "Height": "net_get_z", + "NetCeilingArea": "net_get_top_area", + "NetFloorArea": "net_get_footprint_area", "NetPerimeter": null, - "NetVolume": null, + "NetVolume": "net_get_volume", "NetWallArea": null } },