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 <noreply@anthropic.com>
(cherry picked from commit 6085894433)
This commit is contained in:
Petru Conduraru
2026-07-13 06:27:17 +03:00
committed by Dion Moult
parent 87dd026f94
commit 3f42e02cb4
2 changed files with 16 additions and 16 deletions
+8 -8
View File
@@ -529,16 +529,16 @@
"Qto_SpaceBaseQuantities": { "Qto_SpaceBaseQuantities": {
"FinishCeilingHeight": null, "FinishCeilingHeight": null,
"FinishFloorHeight": null, "FinishFloorHeight": null,
"GrossCeilingArea": null, "GrossCeilingArea": "gross_get_top_area",
"GrossFloorArea": null, "GrossFloorArea": "gross_get_footprint_area",
"GrossPerimeter": null, "GrossPerimeter": "gross_get_footprint_perimeter",
"GrossVolume": null, "GrossVolume": "gross_get_volume",
"GrossWallArea": null, "GrossWallArea": null,
"Height": null, "Height": "net_get_z",
"NetCeilingArea": null, "NetCeilingArea": "net_get_top_area",
"NetFloorArea": null, "NetFloorArea": "net_get_footprint_area",
"NetPerimeter": null, "NetPerimeter": null,
"NetVolume": null, "NetVolume": "net_get_volume",
"NetWallArea": null "NetWallArea": null
} }
}, },
+8 -8
View File
@@ -665,16 +665,16 @@
"Qto_SpaceBaseQuantities": { "Qto_SpaceBaseQuantities": {
"FinishCeilingHeight": null, "FinishCeilingHeight": null,
"FinishFloorHeight": null, "FinishFloorHeight": null,
"GrossCeilingArea": null, "GrossCeilingArea": "gross_get_top_area",
"GrossFloorArea": null, "GrossFloorArea": "gross_get_footprint_area",
"GrossPerimeter": null, "GrossPerimeter": "gross_get_footprint_perimeter",
"GrossVolume": null, "GrossVolume": "gross_get_volume",
"GrossWallArea": null, "GrossWallArea": null,
"Height": null, "Height": "net_get_z",
"NetCeilingArea": null, "NetCeilingArea": "net_get_top_area",
"NetFloorArea": null, "NetFloorArea": "net_get_footprint_area",
"NetPerimeter": null, "NetPerimeter": null,
"NetVolume": null, "NetVolume": "net_get_volume",
"NetWallArea": null "NetWallArea": null
} }
}, },