From 1408beeac517e06b09f6bf457533b9165f68018d Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Fri, 14 Mar 2025 11:43:19 +0500 Subject: [PATCH] ifc5d.qto.Blender - functions descriptions --- .../bonsai/bim/module/qto/calculator.py | 11 +++++++++++ src/bonsai/bonsai/bim/module/qto/prop.py | 4 ++++ src/ifc5d/ifc5d/qto.py | 19 +++++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/src/bonsai/bonsai/bim/module/qto/calculator.py b/src/bonsai/bonsai/bim/module/qto/calculator.py index 1cfd731bb3..dbb8fe225d 100644 --- a/src/bonsai/bonsai/bim/module/qto/calculator.py +++ b/src/bonsai/bonsai/bim/module/qto/calculator.py @@ -36,14 +36,17 @@ VectorTuple = tuple[float, float, float] def get_x(o: bpy.types.Object) -> float: + """Calculate the length along the local X axis.""" return o.bound_box[6][0] - o.bound_box[0][0] def get_y(o: bpy.types.Object) -> float: + """Calculate the length along the local Y axis.""" return o.bound_box[6][1] - o.bound_box[0][1] def get_z(o: bpy.types.Object) -> float: + """Calculate the length along the local Z axis.""" return o.bound_box[6][2] - o.bound_box[0][2] @@ -64,6 +67,7 @@ def get_linear_length(o: bpy.types.Object) -> float: def get_length(o: bpy.types.Object, vg_index: Optional[int] = None) -> float: + """Calculate the object length trying to guess the main axis.""" if vg_index is None: x = get_x(o) y = get_y(o) @@ -158,6 +162,8 @@ def get_covering_width(obj: bpy.types.Object) -> float: def get_width(o: bpy.types.Object) -> float: """_summary_: Returns the width of the object bounding box + Min value between X and Y axes lengths. + :param blender-object o: blender object :return float: width """ @@ -169,6 +175,8 @@ def get_width(o: bpy.types.Object) -> float: def get_height(o: bpy.types.Object) -> float: """_summary_: Returns the height of the object bounding box + Based on the the length along the local Z axis. + :param blender-object o: blender object :return float: height """ @@ -549,6 +557,7 @@ def get_obj_decompositions(obj: bpy.types.Object) -> set[ifcopenshell.entity_ins def get_gross_weight(obj: bpy.types.Object) -> Union[float, None]: + """Get gross weight of the object (based on gross volume and Pset_MaterialCommon.MassDensity)""" obj_mass_density = get_obj_mass_density(obj) if not obj_mass_density: return @@ -558,6 +567,7 @@ def get_gross_weight(obj: bpy.types.Object) -> Union[float, None]: def get_net_weight(obj: bpy.types.Object) -> Union[float, None]: + """Get net weight of the object (based on net volume and Pset_MaterialCommon.MassDensity)""" obj_mass_density = get_obj_mass_density(obj) if not obj_mass_density: return @@ -567,6 +577,7 @@ def get_net_weight(obj: bpy.types.Object) -> Union[float, None]: def get_obj_mass_density(obj: bpy.types.Object) -> Union[float, None]: + """Calculate object mass density based on Pset_MaterialCommon.MassDensity.""" entity = tool.Ifc.get_entity(obj) assert entity material = ifcopenshell.util.element.get_material(entity) diff --git a/src/bonsai/bonsai/bim/module/qto/prop.py b/src/bonsai/bonsai/bim/module/qto/prop.py index b4d01ff29b..4f54fa3893 100644 --- a/src/bonsai/bonsai/bim/module/qto/prop.py +++ b/src/bonsai/bonsai/bim/module/qto/prop.py @@ -58,6 +58,10 @@ def get_calculator_function( ) -> list[Union[tuple[str, str, str], None]]: global CALCULATOR_FUNCTION_ENUM_ITEMS calculator = ifc5d.qto.calculators[self.calculator] + + if calculator is ifc5d.qto.Blender: + calculator.populate_descriptions() + CALCULATOR_FUNCTION_ENUM_ITEMS = [] previous_measure = None for function_id, function in calculator.functions.items(): diff --git a/src/ifc5d/ifc5d/qto.py b/src/ifc5d/ifc5d/qto.py index 8827bef51e..1ed520193a 100644 --- a/src/ifc5d/ifc5d/qto.py +++ b/src/ifc5d/ifc5d/qto.py @@ -388,6 +388,25 @@ class Blender(QtoCalculator): "get_net_weight": Function("IfcMassMeasure", "Net Weight", ""), } + description_populated = False + + @classmethod + def populate_descriptions(cls) -> None: + """Populate the descriptions based on the function docstrings. + + The action is postponed to ensure ifc5d package works without Blender. + """ + if cls.description_populated: + return + + import bonsai.bim.module.qto.calculator as calculator + + for function in cls.functions: + doc = getattr(calculator, function).__doc__ or "" + doc = doc[: doc.find(":param")].strip() + old_function = cls.functions[function] + cls.functions[function] = Function(old_function.measure, old_function.name, doc) + @classmethod def calculate(cls, ifc_file, elements, qtos, results): import bonsai.tool as tool