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.
This commit is contained in:
Andrej730
2024-11-15 11:33:39 +05:00
parent b860a8eaad
commit da70c46c48
@@ -20,6 +20,15 @@ import ifcopenshell
import ifcopenshell.api.pset import ifcopenshell.api.pset
import ifcopenshell.util.pset import ifcopenshell.util.pset
from typing import Optional, Any, Union 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( def edit_qto(
@@ -46,12 +55,16 @@ def edit_qto(
:param properties: A dictionary of properties. The keys must be a string :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 of the name of the quantity. The data type of the value will be
determined by the quantity set template. If no quantity set determined by the quantity set template. If no quantity set
template is found, the data types of the Python values will template is found, the data types of the Python values and
influence the IFC data type of the quantity. String values will properties names will influence the IFC data type of the quantity.
become IfcLabel, float values will become IfcReal, booleans will
become IfcBoolean, and integers will become IfcInteger. If more - For `float` values - see `FLOAT_TYPE_KEYWORDS` for the keywords in property name
control is desired, you may explicitly specify IFC data objects used to detect the quantity type. If no keyword matches,
directly. 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 :param pset_template: If a quantity set template is provided, this will
be used to determine data types. If no user-defined template is be used to determine data types. If no user-defined template is
provided, the built-in buildingSMART templates will be loaded. provided, the built-in buildingSMART templates will be loaded.
@@ -203,4 +216,19 @@ class Usecase:
if prop_template.Name != name: if prop_template.Name != name:
continue continue
return prop_template.TemplateType[2:].lower().capitalize() 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" return "Length"
elif isinstance(value, int):
return "Count"
else:
assert_never(value)