From da70c46c4829b79b8eaffd04ad6064bddcf84af6 Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Fri, 15 Nov 2024 11:33:39 +0500 Subject: [PATCH] editing quantity set to guess type based on name if template is not found E.g. all props with "Area" in it's name will automatically get IfcQuantityArea type, "Volume" - IfcQuantityVolume, see edit_qto documentation. --- .../ifcopenshell/api/pset/edit_qto.py | 40 ++++++++++++++++--- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/src/ifcopenshell-python/ifcopenshell/api/pset/edit_qto.py b/src/ifcopenshell-python/ifcopenshell/api/pset/edit_qto.py index 47c21d6b5e..f1aea4f999 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/pset/edit_qto.py +++ b/src/ifcopenshell-python/ifcopenshell/api/pset/edit_qto.py @@ -20,6 +20,15 @@ import ifcopenshell import ifcopenshell.api.pset import ifcopenshell.util.pset from typing import Optional, Any, Union +from typing_extensions import assert_never + +FLOAT_TYPE_KEYWORDS = ( + ("Area", ("area",)), + ("Volume", ("volume",)), + ("Weight", ("weight", "mass")), + ("Length", ("length", "width", "height", "depth", "distance")), + ("Time", ("time", "duration")), +) def edit_qto( @@ -46,12 +55,16 @@ def edit_qto( :param properties: A dictionary of properties. The keys must be a string of the name of the quantity. The data type of the value will be determined by the quantity set template. If no quantity set - template is found, the data types of the Python values will - influence the IFC data type of the quantity. String values will - become IfcLabel, float values will become IfcReal, booleans will - become IfcBoolean, and integers will become IfcInteger. If more - control is desired, you may explicitly specify IFC data objects - directly. + template is found, the data types of the Python values and + properties names will influence the IFC data type of the quantity. + + - For `float` values - see `FLOAT_TYPE_KEYWORDS` for the keywords in property name + used to detect the quantity type. If no keyword matches, + the default quantity type will be IfcQuantityLength. + + - `int` values will map to IfcQuantityCount. + + If more control is desired, you may explicitly specify IFC data objects directly. :param pset_template: If a quantity set template is provided, this will be used to determine data types. If no user-defined template is provided, the built-in buildingSMART templates will be loaded. @@ -203,4 +216,19 @@ class Usecase: if prop_template.Name != name: continue return prop_template.TemplateType[2:].lower().capitalize() + return infer_property_type(name, value) + + +def infer_property_type(name: str, value: Union[float, int]) -> str: + name_lower = name.lower() + # Only undetected type is IfcQuantityNumber (IFC4X3), + # not sure when it's appropriate. + if isinstance(value, float): + for category, keywords in FLOAT_TYPE_KEYWORDS: + if any(keyword in name_lower for keyword in keywords): + return category return "Length" + elif isinstance(value, int): + return "Count" + else: + assert_never(value)