From aef141505bfc0b18b1c26cf0f171e32473b2805b Mon Sep 17 00:00:00 2001 From: Bruno Postle Date: Sun, 12 Jul 2026 23:16:12 +0100 Subject: [PATCH] ifcedit: include IfcSpace in default QTO element scope IfcSpace is not a subtype of IfcElement, so quantify.run_quantify()'s default selector silently skipped all spaces, reporting elements_quantified: 0 with no error or warning. Generated with the assistance of an AI coding tool. (cherry picked from commit ab157507474a82d32d4fe3c8cac69be7a6b7b2dc) --- src/ifcedit/README.md | 2 +- src/ifcedit/ifcedit/__main__.py | 4 +++- src/ifcedit/ifcedit/quantify.py | 2 +- src/ifcedit/tests/test_quantify.py | 17 +++++++++++++++++ src/ifcmcp/README.md | 2 +- src/ifcmcp/ifcmcp/core.py | 2 +- 6 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/ifcedit/README.md b/src/ifcedit/README.md index 1b8858fe5a..a99bac715f 100644 --- a/src/ifcedit/README.md +++ b/src/ifcedit/README.md @@ -258,7 +258,7 @@ ifcedit quantify run model.ifc IFC4QtoBaseQuantities -o model_qto.ifc Options: -- `--selector ` -- ifcopenshell selector to restrict elements (default: all `IfcElement`) +- `--selector ` -- ifcopenshell selector to restrict elements (default: all `IfcElement` and `IfcSpace`) - `-o, --output ` -- write to a different file instead of overwriting the input Note: `quantify run` writes geometry-based measurements and requires the diff --git a/src/ifcedit/ifcedit/__main__.py b/src/ifcedit/ifcedit/__main__.py index 28292f378e..2d7786fbf9 100644 --- a/src/ifcedit/ifcedit/__main__.py +++ b/src/ifcedit/ifcedit/__main__.py @@ -244,7 +244,9 @@ def main(): qrun_parser = quantify_sub.add_parser("run", help="Run QTO on an IFC file") qrun_parser.add_argument("ifc_file", help="Path to the IFC file") qrun_parser.add_argument("rule_name", help="QTO rule name (e.g. IFC4QtoBaseQuantities)") - qrun_parser.add_argument("--selector", help="ifcopenshell selector to restrict elements (default: all IfcElement)") + qrun_parser.add_argument( + "--selector", help="ifcopenshell selector to restrict elements (default: all IfcElement and IfcSpace)" + ) qrun_parser.add_argument("-o", "--output", help="Output file path (default: overwrite input)") args, extra = parser.parse_known_args() diff --git a/src/ifcedit/ifcedit/quantify.py b/src/ifcedit/ifcedit/quantify.py index f85475e22c..adc024ca2f 100644 --- a/src/ifcedit/ifcedit/quantify.py +++ b/src/ifcedit/ifcedit/quantify.py @@ -30,7 +30,7 @@ def run_quantify(model: ifcopenshell.file, rule: str, selector: str | None = Non if selector: elements = set(ifcopenshell.util.selector.filter_elements(model, selector)) else: - elements = set(model.by_type("IfcElement")) + elements = set(model.by_type("IfcElement")) | set(model.by_type("IfcSpace")) results = quantify(model, elements, rule_sets[rule]) edit_qtos(model, results) diff --git a/src/ifcedit/tests/test_quantify.py b/src/ifcedit/tests/test_quantify.py index f4335fb2a7..a2236651b1 100644 --- a/src/ifcedit/tests/test_quantify.py +++ b/src/ifcedit/tests/test_quantify.py @@ -85,3 +85,20 @@ class TestRunQuantify: def test_empty_selector_runs_on_all(self, quantify_model): result = run_quantify(quantify_model, "IFC4QtoBaseQuantities", selector=None) assert result["ok"] is True + + def test_default_selector_includes_spaces(self, quantify_model, monkeypatch): + """IfcSpace is not a subtype of IfcElement, so the default scope must add it explicitly.""" + import ifc5d.qto + + seen_elements = {} + + def fake_quantify(ifc_file, elements, rules): + seen_elements["elements"] = elements + return {} + + monkeypatch.setattr(ifc5d.qto, "quantify", fake_quantify) + + space = ifcopenshell.api.root.create_entity(quantify_model, ifc_class="IfcSpace", name="TestSpace") + run_quantify(quantify_model, "IFC4QtoBaseQuantities") + + assert space in seen_elements["elements"] diff --git a/src/ifcmcp/README.md b/src/ifcmcp/README.md index 6d513bfd07..7675f2d5c7 100644 --- a/src/ifcmcp/README.md +++ b/src/ifcmcp/README.md @@ -255,7 +255,7 @@ ifc_quantify(rule="IFC4QtoBaseQuantities", selector="IfcWall") Available rules: `IFC4QtoBaseQuantities`, `IFC4X3QtoBaseQuantities`. `selector` is an optional ifcopenshell selector to restrict which elements -are quantified (default: all `IfcElement`). +are quantified (default: all `IfcElement` and `IfcSpace`). Returns `{"ok": true, "rule": "...", "elements_quantified": 42}`. diff --git a/src/ifcmcp/ifcmcp/core.py b/src/ifcmcp/ifcmcp/core.py index 137cdbdce0..3f249a57bb 100644 --- a/src/ifcmcp/ifcmcp/core.py +++ b/src/ifcmcp/ifcmcp/core.py @@ -703,7 +703,7 @@ class IfcSession: "rule": {"type": "string", "description": "QTO rule name, e.g. IFC4QtoBaseQuantities"}, "selector": { "type": "string", - "description": "ifcopenshell selector to restrict elements (default: all IfcElement)", + "description": "ifcopenshell selector to restrict elements (default: all IfcElement and IfcSpace)", }, }, "required": ["rule"],