From bfb2f06e4469cf0ab68294d10226be7651c58da0 Mon Sep 17 00:00:00 2001 From: Massimo Fabbro Date: Mon, 7 Nov 2022 22:07:55 +0100 Subject: [PATCH] Finish mapping Qto_BeamBaseQuantities --- .../pset/calc_quantity_function_mapper.py | 14 +-- ...tes_about_mapped_calculated_quantities.txt | 19 +++++ .../bim/module/pset/qto_calculator.py | 85 +++++++++++++++++-- 3 files changed, 106 insertions(+), 12 deletions(-) create mode 100644 src/blenderbim/blenderbim/bim/module/pset/notes_about_mapped_calculated_quantities.txt diff --git a/src/blenderbim/blenderbim/bim/module/pset/calc_quantity_function_mapper.py b/src/blenderbim/blenderbim/bim/module/pset/calc_quantity_function_mapper.py index 7d113e4e6c..b0ab783e70 100644 --- a/src/blenderbim/blenderbim/bim/module/pset/calc_quantity_function_mapper.py +++ b/src/blenderbim/blenderbim/bim/module/pset/calc_quantity_function_mapper.py @@ -470,13 +470,13 @@ mapper = { 'NetWeight' : None, }, 'Qto_BeamBaseQuantities' : { - 'Length' : None, - 'CrossSectionArea' : None, - 'OuterSurfaceArea' : None, - 'GrossSurfaceArea' : None, - 'NetSurfaceArea' : None, - 'GrossVolume' : None, - 'NetVolume' : None, + 'Length' : "get_length", + 'CrossSectionArea' : { "function_name" : "get_end_area", "args" : ", exclude_side_areas = True" }, + 'GrossSurfaceArea' : { "function_name" : "get_gross_lateral_area", "args" : ", exclude_end_areas = False, angle_z1 = 0, angle_z2 = 360" }, + 'OuterSurfaceArea' : { "function_name" : "get_lateral_area", "args" : ", exclude_end_areas = True, angle_z1 = 0, angle_z2 = 360" }, + 'NetSurfaceArea' : { "function_name" : "get_lateral_area", "args" : ", exclude_end_areas = False, angle_z1 = 0, angle_z2 = 360" }, + 'GrossVolume' : "get_gross_volume", + 'NetVolume' : "get_net_volume", 'GrossWeight' : None, 'NetWeight' : None, }, diff --git a/src/blenderbim/blenderbim/bim/module/pset/notes_about_mapped_calculated_quantities.txt b/src/blenderbim/blenderbim/bim/module/pset/notes_about_mapped_calculated_quantities.txt new file mode 100644 index 0000000000..ce82fd3e01 --- /dev/null +++ b/src/blenderbim/blenderbim/bim/module/pset/notes_about_mapped_calculated_quantities.txt @@ -0,0 +1,19 @@ +So, here are some note needed to know about how quantities are calculated. + +NET VOLUME AND GROSS VOLUME +The difference between gross volume and net volume is that the gross volume is calculated +without the related IFC opening. +So, if an object is created lets say with a hole but without defining the opening, the hole is counted into net volume (so get volume and net volume are the same). +This is in order to follow the native IFC approach. + +WALLS AND BEAM LENGTH, HEIGHT, WIDTH AND LATERAL AREA +These dimensions are calculated with the convention that the object can have main axis along x or z. +The same with lateral area. + +SLAB THICKNESS +The slab thickness is defined as Width, following the IFC definition +Also, note that these dimensions are calculated only if the slab is prismatic. + + + + diff --git a/src/blenderbim/blenderbim/bim/module/pset/qto_calculator.py b/src/blenderbim/blenderbim/bim/module/pset/qto_calculator.py index 422d17b956..af07d66e7b 100644 --- a/src/blenderbim/blenderbim/bim/module/pset/qto_calculator.py +++ b/src/blenderbim/blenderbim/bim/module/pset/qto_calculator.py @@ -96,10 +96,13 @@ class QtoCalculator: return max(x, y, z) def get_length(self, o, vg_index=None): - if vg_index is None: + if vg_index is None and not self.has_local_axes_rotated(o): x = (Vector(o.bound_box[4]) - Vector(o.bound_box[0])).length y = (Vector(o.bound_box[3]) - Vector(o.bound_box[0])).length return max(x, y) + if vg_index is None and self.has_local_axes_rotated(o): + return ((Vector(o.bound_box[1]) - Vector(o.bound_box[0])).length) + length = 0 edges = [ e @@ -425,9 +428,16 @@ class QtoCalculator: :param int angle_z2: Angle measured from the positive z-axis to the normal-vector of the area. Openings with a normal_vector greater than this value will be ignored, defaults to 135 :return float: Lateral Area """ - x_axis = [1, 0, 0] - y_axis = [0, 1, 0] - z_axis = [0, 0, 1] + + if not self.has_local_axes_rotated(obj): + x_axis = [1, 0, 0] + y_axis = [0, 1, 0] + z_axis = [0, 0, 1] + if self.has_local_axes_rotated(obj): + x_axis = [0, 0, 1] + y_axis = [1, 0, 0] + z_axis = [0, 1, 0] + area = 0 total_opening_area = ( 0 if subtract_openings else self.get_opening_area(obj, angle_z1=angle_z1, angle_z2=angle_z2) @@ -447,10 +457,45 @@ class QtoCalculator: if angle_to_y_axis < 45 or angle_to_y_axis > 135: continue area += polygon.area + return area + total_opening_area + def get_gross_lateral_area( + self, + obj, + subtract_openings: bool = True, + exclude_end_areas: bool = False, + exclude_side_areas: bool = False, + angle_z1: int = 45, + angle_z2: int = 135, + ): + """_summary_ + + :param blender-object obj: blender object, bpy.types.Object + :param bool subtract_openings: Toggle whether opening-areas should be subtracted, defaults to True + :param bool exclude_end_areas: , defaults to False + :param bool exclude_side_areas: , defaults to False + :param int angle_z1: Angle measured from the positive z-axis to the normal-vector of the area. Openings with a normal_vector lower than this value will be ignored, defaults to 45 + :param int angle_z2: Angle measured from the positive z-axis to the normal-vector of the area. Openings with a normal_vector greater than this value will be ignored, defaults to 135 + :return float: Lateral gross Area + """ + + element = tool.Ifc.get_entity(obj) + + gross_mesh = self.get_gross_element_mesh(element) + + gross_obj = bpy.data.objects.new("MyObject", gross_mesh) + + gross_lateral_area = self.get_lateral_area(gross_obj, subtract_openings, exclude_end_areas, exclude_side_areas, angle_z1, angle_z2 ) + + self.delete_obj(gross_obj) + self.delete_mesh(gross_mesh) + + return gross_lateral_area + + def get_half_lateral_area( - self, + self, obj, subtract_openings: bool = True, exclude_end_areas: bool = False, @@ -469,6 +514,29 @@ class QtoCalculator: """ return self.get_lateral_area(obj, subtract_openings, exclude_end_areas, exclude_side_areas, angle_z1, angle_z2)/2 + def get_end_area( + self, + obj, + subtract_openings: bool = True, + exclude_end_areas: bool = False, + exclude_side_areas: bool = False, + angle_z1: int = 45, + angle_z2: int = 135, + ): + + element = tool.Ifc.get_entity(obj) + gross_mesh = self.get_gross_element_mesh(element) + + gross_obj = bpy.data.objects.new("MyObject", gross_mesh) + gross_obj.matrix_world = obj.matrix_world + + end_area = self.get_lateral_area(gross_obj, subtract_openings, exclude_end_areas, exclude_side_areas, angle_z1, angle_z2)/2 + + self.delete_obj(gross_obj) + self.delete_mesh(gross_mesh) + + return end_area + def get_gross_top_area(self, obj, angle: int = 45): """_summary_: Returns the gross top area of the object. @@ -888,6 +956,13 @@ class QtoCalculator: bm.from_mesh(mesh) return bm + def has_local_axes_rotated(self, o): + matrix = o.matrix_world + if matrix[0][0] == 1: + return False + if matrix[0][2] == 1: + return True + def delete_mesh(self, mesh): mesh.user_clear() bpy.data.meshes.remove(mesh)