diff --git a/src/blenderbim/blenderbim/bim/module/model/array.py b/src/blenderbim/blenderbim/bim/module/model/array.py index 0c3e3cb819..d6a674e5f3 100644 --- a/src/blenderbim/blenderbim/bim/module/model/array.py +++ b/src/blenderbim/blenderbim/bim/module/model/array.py @@ -120,7 +120,7 @@ class EnableEditingArray(bpy.types.Operator, tool.Ifc.Operator): props.y = data["y"] props.z = data["z"] props.is_editing = self.item - return {'FINISHED'} + return {"FINISHED"} class RemoveArray(bpy.types.Operator, tool.Ifc.Operator): diff --git a/src/blenderbim/blenderbim/bim/module/model/data.py b/src/blenderbim/blenderbim/bim/module/model/data.py index 3982a9d7ad..44aefdef0b 100644 --- a/src/blenderbim/blenderbim/bim/module/model/data.py +++ b/src/blenderbim/blenderbim/bim/module/model/data.py @@ -425,4 +425,4 @@ class WindowData: parameters = psets.get("BBIM_Window", None) if parameters: parameters["data"] = json.loads(parameters.get("Data", "[]") or "[]") - return parameters \ No newline at end of file + return parameters diff --git a/src/blenderbim/blenderbim/bim/module/model/prop.py b/src/blenderbim/blenderbim/bim/module/model/prop.py index 51d6aef2c1..0becdda5a2 100644 --- a/src/blenderbim/blenderbim/bim/module/model/prop.py +++ b/src/blenderbim/blenderbim/bim/module/model/prop.py @@ -303,7 +303,7 @@ class BIMSverchokProperties(PropertyGroup): def window_type_prop_update(self, context): panels_data = self.window_types_panels[self.window_type] for i in range(3): - try: + try: width, height = panels_data[i] except IndexError: width, height = (0.0, 0.0) @@ -311,51 +311,54 @@ def window_type_prop_update(self, context): self.relative_width[i] = width self.relative_height[i] = height + class BIMWindowProperties(PropertyGroup): window_types = ( - ('SINGLE_PANEL', 'SINGLE_PANEL', ''), - ('DOUBLE_PANEL_HORIZONTAL', 'DOUBLE_PANEL_HORIZONTAL', ''), - ('DOUBLE_PANEL_VERTICAL', 'DOUBLE_PANEL_VERTICAL', ''), - ('TRIPLE_PANEL_BOTTOM', 'TRIPLE_PANEL_BOTTOM', ''), - ('TRIPLE_PANEL_TOP', 'TRIPLE_PANEL_TOP', ''), - ('TRIPLE_PANEL_LEFT', 'TRIPLE_PANEL_LEFT', ''), - ('TRIPLE_PANEL_RIGHT', 'TRIPLE_PANEL_RIGHT', ''), - ('TRIPLE_PANEL_HORIZONTAL', 'TRIPLE_PANEL_HORIZONTAL', ''), - ('TRIPLE_PANEL_VERTICAL', 'TRIPLE_PANEL_VERTICAL', ''), + ("SINGLE_PANEL", "SINGLE_PANEL", ""), + ("DOUBLE_PANEL_HORIZONTAL", "DOUBLE_PANEL_HORIZONTAL", ""), + ("DOUBLE_PANEL_VERTICAL", "DOUBLE_PANEL_VERTICAL", ""), + ("TRIPLE_PANEL_BOTTOM", "TRIPLE_PANEL_BOTTOM", ""), + ("TRIPLE_PANEL_TOP", "TRIPLE_PANEL_TOP", ""), + ("TRIPLE_PANEL_LEFT", "TRIPLE_PANEL_LEFT", ""), + ("TRIPLE_PANEL_RIGHT", "TRIPLE_PANEL_RIGHT", ""), + ("TRIPLE_PANEL_HORIZONTAL", "TRIPLE_PANEL_HORIZONTAL", ""), + ("TRIPLE_PANEL_VERTICAL", "TRIPLE_PANEL_VERTICAL", ""), ) # default panel relative dimensions window_types_panels = { - 'SINGLE_PANEL': ((1.0, 1.0), ), - 'DOUBLE_PANEL_HORIZONTAL': ((1.0, 0.5), (1.0, 0.5), ), - 'DOUBLE_PANEL_VERTICAL': ((0.5, 1.0), (0.5, 1.0), ), - 'TRIPLE_PANEL_BOTTOM': ((0.5, 0.5), (0.5, 0.5), (1.0, 0.5), ), - 'TRIPLE_PANEL_TOP': ((1.0, 0.5), (0.5, 0.5), (0.5, 0.5), ), - 'TRIPLE_PANEL_LEFT': ((0.5, 1.0), (0.5, 0.5), (0.5, 0.5), ), - 'TRIPLE_PANEL_RIGHT': ((0.5, 0.5), (0.5, 1.0), (0.5, 0.5), ), - 'TRIPLE_PANEL_HORIZONTAL': ((1.0, 1/3), (1.0, 1/3), (1.0, 1/3),), - 'TRIPLE_PANEL_VERTICAL': ((1/3, 1.0), (1/3, 1.0), (1/3, 1.0),), + "SINGLE_PANEL": ((1.0, 1.0), ), + "DOUBLE_PANEL_HORIZONTAL": ((1.0, 0.5), (1.0, 0.5), ), + "DOUBLE_PANEL_VERTICAL": ((0.5, 1.0), (0.5, 1.0), ), + "TRIPLE_PANEL_BOTTOM": ((0.5, 0.5), (0.5, 0.5), (1.0, 0.5), ), + "TRIPLE_PANEL_TOP": ((1.0, 0.5), (0.5, 0.5), (0.5, 0.5), ), + "TRIPLE_PANEL_LEFT": ((0.5, 1.0), (0.5, 0.5), (0.5, 0.5), ), + "TRIPLE_PANEL_RIGHT": ((0.5, 0.5), (0.5, 1.0), (0.5, 0.5), ), + "TRIPLE_PANEL_HORIZONTAL": ((1.0, 1/3), (1.0, 1/3), (1.0, 1/3),), + "TRIPLE_PANEL_VERTICAL": ((1/3, 1.0), (1/3, 1.0), (1/3, 1.0),), } is_editing: bpy.props.IntProperty(default=-1) - window_type: bpy.props.EnumProperty(name="Window Type", items=window_types, default="SINGLE_PANEL", update=window_type_prop_update) - overall_height: bpy.props.FloatProperty(name='Overall Height', default=900) - overall_width: bpy.props.FloatProperty(name='Overall Width', default=600) + window_type: bpy.props.EnumProperty( + name="Window Type", items=window_types, default="SINGLE_PANEL", update=window_type_prop_update + ) + overall_height: bpy.props.FloatProperty(name="Overall Height", default=900) + overall_width: bpy.props.FloatProperty(name="Overall Width", default=600) # lining properties - lining_depth: bpy.props.FloatProperty(name='Lining Depth', default=50) - lining_thickness: bpy.props.FloatProperty(name='Lining Thickness', default=50) - lining_offset: bpy.props.FloatProperty(name='Lining Offset', default=50) - lining_to_panel_offset_x: bpy.props.FloatProperty(name='Lining to Panel Offset X', default=25) - lining_to_panel_offset_y: bpy.props.FloatProperty(name='Lining to Panel Offset Y', default=25) - mullion_thickness: bpy.props.FloatProperty(name='(not used) Mullion Thickness') - transom_thickness: bpy.props.FloatProperty(name='(not used) Transom Thickness') + lining_depth: bpy.props.FloatProperty(name="Lining Depth", default=50) + lining_thickness: bpy.props.FloatProperty(name="Lining Thickness", default=50) + lining_offset: bpy.props.FloatProperty(name="Lining Offset", default=50) + lining_to_panel_offset_x: bpy.props.FloatProperty(name="Lining to Panel Offset X", default=25) + lining_to_panel_offset_y: bpy.props.FloatProperty(name="Lining to Panel Offset Y", default=25) + mullion_thickness: bpy.props.FloatProperty(name="(not used) Mullion Thickness") + transom_thickness: bpy.props.FloatProperty(name="(not used) Transom Thickness") # panel_properties - frame_depth: bpy.props.FloatVectorProperty(name='Frame Depth', size=3, default=[35]*3) - frame_thickness: bpy.props.FloatVectorProperty(name='Frame Thickness', size=3, default=[35]*3) - relative_width: bpy.props.FloatVectorProperty(name='Relative Width', size=3, default=[1,0,0]) - relative_height: bpy.props.FloatVectorProperty(name='Relative Height', size=3, default=[1,0,0]) + frame_depth: bpy.props.FloatVectorProperty(name="Frame Depth", size=3, default=[35] * 3) + frame_thickness: bpy.props.FloatVectorProperty(name="Frame Thickness", size=3, default=[35] * 3) + relative_width: bpy.props.FloatVectorProperty(name="Relative Width", size=3, default=[1, 0, 0]) + relative_height: bpy.props.FloatVectorProperty(name="Relative Height", size=3, default=[1, 0, 0]) def get_general_kwargs(self): return { @@ -381,4 +384,4 @@ class BIMWindowProperties(PropertyGroup): "frame_thickness": self.frame_thickness, "relative_width": self.relative_width, "relative_height": self.relative_height, - } \ No newline at end of file + } diff --git a/src/blenderbim/blenderbim/bim/module/model/stair.py b/src/blenderbim/blenderbim/bim/module/model/stair.py index c47cdb89d3..2061bbe786 100644 --- a/src/blenderbim/blenderbim/bim/module/model/stair.py +++ b/src/blenderbim/blenderbim/bim/module/model/stair.py @@ -361,7 +361,7 @@ class EnableEditingStair(bpy.types.Operator, tool.Ifc.Operator): setattr(props, prop_name, data[prop_name]) props.is_editing = 1 - return {'FINISHED'} + return {"FINISHED"} class RemoveStair(bpy.types.Operator, tool.Ifc.Operator): diff --git a/src/blenderbim/blenderbim/bim/module/model/ui.py b/src/blenderbim/blenderbim/bim/module/model/ui.py index ae7f923c7e..cb3783f609 100644 --- a/src/blenderbim/blenderbim/bim/module/model/ui.py +++ b/src/blenderbim/blenderbim/bim/module/model/ui.py @@ -424,13 +424,13 @@ class BIM_PT_window(bpy.types.Panel): props = context.active_object.BIMWindowProperties - if WindowData.data['parameters']: + if WindowData.data["parameters"]: row = self.layout.row(align=True) row.label(text="Window parameters", icon="OUTLINER_OB_LATTICE") - window_data = WindowData.data['parameters']['data'] + window_data = WindowData.data["parameters"]["data"] - if props.is_editing != - 1: + if props.is_editing != -1: row = self.layout.row(align=True) row.operator("bim.finish_editing_window", icon="CHECKMARK", text="Finish editing") row.operator("bim.cancel_editing_window", icon="CANCEL", text="") @@ -440,30 +440,30 @@ class BIM_PT_window(bpy.types.Panel): self.layout.prop(props, prop) lining_props = props.get_lining_kwargs() - self.layout.label(text='Lining properties') + self.layout.label(text="Lining properties") for prop in lining_props: self.layout.prop(props, prop) panel_props = props.get_panel_kwargs() - self.layout.label(text='Panel properties') + self.layout.label(text="Panel properties") number_of_panels = len(props.window_types_panels[props.window_type]) panel_box = self.layout.box() row = panel_box.row() - cols = [row.column(align=True) for i in range(number_of_panels+1)] + cols = [row.column(align=True) for i in range(number_of_panels + 1)] + + cols[0].label(text="") - cols[0].label(text='') - for panel_i in range(number_of_panels): - r = cols[panel_i+1].row() - r.alignment = 'CENTER' - r.label(text=f'#{panel_i}') - r = cols[panel_i+1].row() + r = cols[panel_i + 1].row() + r.alignment = "CENTER" + r.label(text=f"#{panel_i}") + r = cols[panel_i + 1].row() for prop in panel_props: cols[0].label(text=f"{props.bl_rna.properties[prop].name}") for panel_i in range(number_of_panels): - cols[panel_i+1].prop(props, prop, index=panel_i, text='') + cols[panel_i + 1].prop(props, prop, index=panel_i, text="") update_window_modifier_bmesh(context) @@ -481,46 +481,47 @@ class BIM_PT_window(bpy.types.Panel): row.label(text=str(prop_value)) lining_props = props.get_lining_kwargs() - self.layout.label(text='Lining properties') + self.layout.label(text="Lining properties") lining_box = self.layout.box() for prop in lining_props: - prop_value = window_data['lining_properties'][prop] + prop_value = window_data["lining_properties"][prop] prop_value = round(prop_value, 5) if type(prop_value) is float else prop_value row = lining_box.row(align=True) row.label(text=f"{props.bl_rna.properties[prop].name}") row.label(text=str(prop_value)) panel_props = props.get_panel_kwargs() - self.layout.label(text='Panel properties') + self.layout.label(text="Panel properties") number_of_panels = len(props.window_types_panels[props.window_type]) panel_box = self.layout.box() row = panel_box.row() - cols = [row.column(align=True) for i in range(number_of_panels+1)] - cols[0].label(text='') - + cols = [row.column(align=True) for i in range(number_of_panels + 1)] + cols[0].label(text="") + for panel_i in range(number_of_panels): - r = cols[panel_i+1].row() - r.alignment = 'CENTER' - r.label(text=f'#{panel_i}') - r = cols[panel_i+1].row() + r = cols[panel_i + 1].row() + r.alignment = "CENTER" + r.label(text=f"#{panel_i}") + r = cols[panel_i + 1].row() # TODO: align property values more evenly for prop in panel_props: cols[0].row().label(text=f"{props.bl_rna.properties[prop].name}") for panel_i in range(number_of_panels): - r = cols[panel_i+1].row() - r.alignment = 'CENTER' - prop_value = window_data['panel_properties'][prop][panel_i] + r = cols[panel_i + 1].row() + r.alignment = "CENTER" + prop_value = window_data["panel_properties"][prop][panel_i] prop_value = round(prop_value, 5) if type(prop_value) is float else prop_value r.label(text=str(prop_value)) - r = cols[panel_i+1].row() + r = cols[panel_i + 1].row() else: row = self.layout.row() row.label(text="No Window Found") row.operator("bim.add_window", icon="ADD", text="") + class BIM_MT_model(Menu): bl_idname = "BIM_MT_model" bl_label = "IFC Objects" diff --git a/src/blenderbim/blenderbim/bim/module/model/window.py b/src/blenderbim/blenderbim/bim/module/model/window.py index a71920869a..9358c40460 100644 --- a/src/blenderbim/blenderbim/bim/module/model/window.py +++ b/src/blenderbim/blenderbim/bim/module/model/window.py @@ -40,54 +40,59 @@ import json V = lambda *x: Vector([float(i) for i in x]) + def update_window_modifier_representation(context): obj = context.active_object props = obj.BIMWindowProperties ifc_file = tool.Ifc.get() representation_data = { - 'partition_type': props.window_type, - 'overall_height': props.overall_height, - 'overall_width': props.overall_width, - 'lining_properties': { - 'LiningDepth': props.lining_depth, - 'LiningThickness': props.lining_thickness, - 'LiningOffset': props.lining_offset, - 'LiningToPanelOffsetX': props.lining_to_panel_offset_x, - 'LiningToPanelOffsetY': props.lining_to_panel_offset_y, + "partition_type": props.window_type, + "overall_height": props.overall_height, + "overall_width": props.overall_width, + "lining_properties": { + "LiningDepth": props.lining_depth, + "LiningThickness": props.lining_thickness, + "LiningOffset": props.lining_offset, + "LiningToPanelOffsetX": props.lining_to_panel_offset_x, + "LiningToPanelOffsetY": props.lining_to_panel_offset_y, }, - 'panel_properties': [] + "panel_properties": [], } number_of_panels = len(props.window_types_panels[props.window_type]) for panel_i in range(number_of_panels): panel_data = { - 'FrameDepth': props.frame_depth[panel_i], - 'FrameThickness': props.frame_thickness[panel_i], - 'RelativeWidth': props.relative_width[panel_i], - 'RelativeHeight': props.relative_height[panel_i], + "FrameDepth": props.frame_depth[panel_i], + "FrameThickness": props.frame_thickness[panel_i], + "RelativeWidth": props.relative_width[panel_i], + "RelativeHeight": props.relative_height[panel_i], } - representation_data['panel_properties'].append(panel_data) + representation_data["panel_properties"].append(panel_data) # ELEVATION_VIEW representation ifc_context = ifcopenshell.util.representation.get_context(ifc_file, "Model", "Profile", "ELEVATION_VIEW") if not ifc_context: - model_context = ifcopenshell.util.representation.get_context(ifc_file, 'Model') + model_context = ifcopenshell.util.representation.get_context(ifc_file, "Model") ifc_context = ifcopenshell.api.run( - 'context.add_context', - ifc_file, - context_type='Model', - context_identifier='Profile', - target_view='ELEVATION_VIEW', - parent=model_context) + "context.add_context", + ifc_file, + context_type="Model", + context_identifier="Profile", + target_view="ELEVATION_VIEW", + parent=model_context, + ) - representation_data['context'] = ifc_context - elevation_representation = ifcopenshell.api.run("geometry.add_window_representation", ifc_file, **representation_data) + representation_data["context"] = ifc_context + elevation_representation = ifcopenshell.api.run( + "geometry.add_window_representation", ifc_file, **representation_data + ) replace_representation_for_object(ifc_file, ifc_context, obj, elevation_representation) # MODEL_VIEW representation ifc_context = ifcopenshell.util.representation.get_context(ifc_file, "Model", "Body", "MODEL_VIEW") - representation_data['context'] = ifc_context + representation_data["context"] = ifc_context model_representation = ifcopenshell.api.run("geometry.add_window_representation", ifc_file, **representation_data) - replace_representation_for_object(ifc_file, ifc_context, obj, model_representation) + replace_representation_for_object(ifc_file, ifc_context, obj, model_representation) + def replace_representation_for_object(ifc_file, ifc_context, obj, new_representation): ifc_element = tool.Ifc.get_entity(obj) @@ -106,24 +111,27 @@ def replace_representation_for_object(ifc_file, ifc_context, obj, new_representa representation=new_representation, should_reload=True, is_global=False, - should_sync_changes_first=True + should_sync_changes_first=True, ) core.remove_representation(tool.Ifc, tool.Geometry, obj=obj, representation=old_representation) else: - ifcopenshell.api.run("geometry.assign_representation", ifc_file, product=ifc_element, representation=new_representation) + ifcopenshell.api.run( + "geometry.assign_representation", ifc_file, product=ifc_element, representation=new_representation + ) -def create_bm_window_closed_profile(bm, size: Vector, thickness:float, position:Vector): + +def create_bm_window_closed_profile(bm, size: Vector, thickness: float, position: Vector): width, depth, height = size verts = [ - (0, [thickness, 0.0, thickness]), - (1, [width-thickness, 0.0, thickness]), - (2, [thickness, 0.0, height-thickness]), - (3, [width-thickness, 0.0, height-thickness]), - (4, [0.0, 0.0, 0.0]), - (5, [0.0, 0.0, height]), - (6, [width, 0.0, 0.0]), - (7, [width, 0.0, height]), + (0, [thickness, 0.0, thickness]), + (1, [width - thickness, 0.0, thickness]), + (2, [thickness, 0.0, height - thickness]), + (3, [width - thickness, 0.0, height - thickness]), + (4, [0.0, 0.0, 0.0]), + (5, [0.0, 0.0, height]), + (6, [width, 0.0, 0.0]), + (7, [width, 0.0, height]), ] edges = [ @@ -142,10 +150,10 @@ def create_bm_window_closed_profile(bm, size: Vector, thickness:float, position: ] faces = [ - (0, (2, 3, 7, 5)), - (1, (5, 4, 0, 2)), - (2, (1, 0, 4, 6)), - (3, (7, 3, 1, 6)), + (0, (2, 3, 7, 5)), + (1, (5, 4, 0, 2)), + (2, (1, 0, 4, 6)), + (3, (7, 3, 1, 6)), ] bm.verts.index_update() @@ -161,7 +169,7 @@ def create_bm_window_closed_profile(bm, size: Vector, thickness:float, position: translate_verts = [v for v in extruded["geom"] if isinstance(v, BMVert)] bmesh.ops.translate(bm, vec=extrusion_vector, verts=translate_verts) - bmesh.ops.translate(bm, vec=position, verts=new_verts+translate_verts) + bmesh.ops.translate(bm, vec=position, verts=new_verts + translate_verts) return new_verts @@ -195,53 +203,52 @@ def update_window_modifier_bmesh(context): # create lining lining_size = V( - overall_width * props.relative_width[panel_i], - lining_depth, - overall_height* props.relative_height[panel_i]) + overall_width * props.relative_width[panel_i], + lining_depth, + overall_height * props.relative_height[panel_i], + ) thickness = props.lining_thickness * si_conversion lining_verts = create_bm_window_closed_profile(bm, lining_size, thickness, V(0, 0, 0)) # add panel panel_size = lining_size.copy() panel_size.y = frame_depth - panel_size = panel_size - V(lining_to_panel_offset_x*2, 0, lining_to_panel_offset_x*2) + panel_size = panel_size - V(lining_to_panel_offset_x * 2, 0, lining_to_panel_offset_x * 2) panel_position = V( props.lining_to_panel_offset_x * si_conversion, - ((props.lining_depth-props.frame_depth[panel_i]) + props.lining_to_panel_offset_y) * si_conversion, + ((props.lining_depth - props.frame_depth[panel_i]) + props.lining_to_panel_offset_y) * si_conversion, props.lining_to_panel_offset_x * si_conversion, ) thickness = props.frame_thickness[panel_i] * si_conversion panel_verts = create_bm_window_closed_profile(bm, panel_size, thickness, panel_position) # add glass - glass_verts = bmesh.ops.create_cube(bm, size=1)['verts'] + glass_verts = bmesh.ops.create_cube(bm, size=1)["verts"] bmesh.ops.translate(bm, vec=-glass_verts[0].co, verts=glass_verts) glass_size = panel_size glass_size.y = glass_thickness - glass_size = glass_size - V(frame_thickness*2, 0, frame_thickness) + glass_size = glass_size - V(frame_thickness * 2, 0, frame_thickness) glass_position = panel_position + V( frame_thickness, - frame_depth/2-glass_thickness/2, + frame_depth / 2 - glass_thickness / 2, frame_thickness, ) bmesh.ops.scale(bm, vec=glass_size, verts=glass_verts) bmesh.ops.translate(bm, vec=glass_position, verts=glass_verts) # translate panel - accumulated_offset = V(accumulated_width, 0, accumulated_height[column_i]) * V(overall_width, 0, overall_height) - bmesh.ops.translate(bm, - vec=accumulated_offset, - verts=lining_verts + panel_verts + glass_verts) + accumulated_offset = V(accumulated_width, 0, accumulated_height[column_i]) * V( + overall_width, 0, overall_height + ) + bmesh.ops.translate(bm, vec=accumulated_offset, verts=lining_verts + panel_verts + glass_verts) built_panels.append(panel_i) accumulated_height[column_i] += props.relative_height[panel_i] accumulated_width += props.relative_width[panel_i] - - bmesh.ops.translate(bm, - vec=V(0, props.lining_offset * si_conversion, 0), - verts=bm.verts) + + bmesh.ops.translate(bm, vec=V(0, props.lining_offset * si_conversion, 0), verts=bm.verts) bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.0001) if bpy.context.object.mode == "EDIT": @@ -267,8 +274,8 @@ class AddWindow(bpy.types.Operator, tool.Ifc.Operator): lining_props = props.get_lining_kwargs() panel_props = props.get_panel_kwargs() - window_data['lining_properties'] = lining_props - window_data['panel_properties'] = panel_props + window_data["lining_properties"] = lining_props + window_data["panel_properties"] = panel_props psets = ifcopenshell.util.element.get_psets(element) pset = psets.get("BBIM_Window", None) @@ -286,7 +293,7 @@ class AddWindow(bpy.types.Operator, tool.Ifc.Operator): update_window_modifier_representation(context) return {"FINISHED"} - + class CancelEditingWindow(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.cancel_editing_window" bl_label = "Cancel editing Window" @@ -324,8 +331,8 @@ class FinishEditingWindow(bpy.types.Operator, tool.Ifc.Operator): lining_props = props.get_lining_kwargs() panel_props = props.get_panel_kwargs() - window_data['lining_properties'] = lining_props - window_data['panel_properties'] = panel_props + window_data["lining_properties"] = lining_props + window_data["panel_properties"] = panel_props props.is_editing = -1 @@ -357,7 +364,7 @@ class EnableEditingWindow(bpy.types.Operator, tool.Ifc.Operator): setattr(props, prop_name, data[prop_name]) props.is_editing = 1 - return {'FINISHED'} + return {"FINISHED"} class RemoveWindow(bpy.types.Operator, tool.Ifc.Operator): diff --git a/src/blenderbim/scripts/shape_builder_examples.py b/src/blenderbim/scripts/shape_builder_examples.py index d68fc19699..fd4ad612c6 100644 --- a/src/blenderbim/scripts/shape_builder_examples.py +++ b/src/blenderbim/scripts/shape_builder_examples.py @@ -66,6 +66,7 @@ def simple_uses(): ifc_file.write("tmp.ifc") + def generate_desk_test(): ifc_file = ifcopenshell.file() desks = [ @@ -80,6 +81,7 @@ def generate_desk_test(): ifc_file.write("tmp.ifc") + def mirror_placement_test(): ifc_file = ifcopenshell.api.run("project.create_file") project = ifcopenshell.api.run( @@ -153,6 +155,7 @@ def mirror_placement_test(): ifc_file.write("tmp.ifc") + def curve_between_two_points_test(): ifc_file = ifcopenshell.api.run("project.create_file") project = ifcopenshell.api.run( @@ -217,6 +220,7 @@ def curve_between_two_points_test(): ifc_file.write("tmp.ifc") + def generate_simple_desk(ifc_file, width, depth, height): # > width, depth, height in mm width, depth, height = [i / 1000 for i in (width, depth, height)] @@ -226,6 +230,7 @@ def generate_simple_desk(ifc_file, width, depth, height): extruded_area = builder.extrude(profile, height) return extruded_area + def generate_table(ifc_file, width, depth, height, countertop_thickness=20, leg_size=40, leg_offset=50): # > width, depth, height in mm width, depth, height, countertop_thickness, leg_size, leg_offset = [ diff --git a/src/ifcopenshell-python/ifcopenshell/api/geometry/add_window_representation.py b/src/ifcopenshell-python/ifcopenshell/api/geometry/add_window_representation.py index d159f64453..f71cded829 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/geometry/add_window_representation.py +++ b/src/ifcopenshell-python/ifcopenshell/api/geometry/add_window_representation.py @@ -29,81 +29,81 @@ from mathutils import Vector # - order of rows is from top of the window to bottom DEFAULT_PANEL_SCHEMAS = { - 'SINGLE_PANEL': [[0]], - 'DOUBLE_PANEL_HORIZONTAL': [[0],[1]], - 'DOUBLE_PANEL_VERTICAL': [[0,1]], - 'TRIPLE_PANEL_BOTTOM': [[0,1],[2,2]], - 'TRIPLE_PANEL_TOP': [[0,0], [1,2]], - 'TRIPLE_PANEL_LEFT': [[0,1],[0,2]], - 'TRIPLE_PANEL_RIGHT': [[0,1],[2,1]], - 'TRIPLE_PANEL_HORIZONTAL': [[0],[1],[2]], - 'TRIPLE_PANEL_VERTICAL': [[0,1,2]], + "SINGLE_PANEL": [[0]], + "DOUBLE_PANEL_HORIZONTAL": [[0], [1]], + "DOUBLE_PANEL_VERTICAL": [[0, 1]], + "TRIPLE_PANEL_BOTTOM": [[0, 1], [2, 2]], + "TRIPLE_PANEL_TOP": [[0, 0], [1, 2]], + "TRIPLE_PANEL_LEFT": [[0, 1], [0, 2]], + "TRIPLE_PANEL_RIGHT": [[0, 1], [2, 1]], + "TRIPLE_PANEL_HORIZONTAL": [[0], [1], [2]], + "TRIPLE_PANEL_VERTICAL": [[0, 1, 2]], } + class Usecase: def __init__(self, file, **settings): self.file = file # http://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcWindow.htm # http://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcWindowTypePartitioningEnum.htm - # http://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcWindowLiningProperties.htm + # http://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcWindowLiningProperties.htm # http://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcWindowPanelProperties.htm self.settings = { "context": None, # IfcGeometricRepresentationContext - # SINGLE_PANEL, DOUBLE_PANEL_HORIZONTAL, DOUBLE_PANEL_VERTICAL, + # SINGLE_PANEL, DOUBLE_PANEL_HORIZONTAL, DOUBLE_PANEL_VERTICAL, # TRIPLE_PANEL_BOTTOM, TRIPLE_PANEL_HORIZONTAL, TRIPLE_PANEL_LEFT, TRIPLE_PANEL_RIGHT, TRIPLE_PANEL_TOP, TRIPLE_PANEL_VERTICAL - "partition_type": 'SINGLE_PANEL', + "partition_type": "SINGLE_PANEL", "overall_height": 900, - "overall_width": 600, + "overall_width": 600, "lining_properties": { - 'LiningDepth': 50, - 'LiningThickness': 50, - 'LiningOffset': 50, # offset to the wall - 'LiningToPanelOffsetX': 25, - 'LiningToPanelOffsetY': 25, + "LiningDepth": 50, + "LiningThickness": 50, + "LiningOffset": 50, # offset to the wall + "LiningToPanelOffsetX": 25, + "LiningToPanelOffsetY": 25, # applies to DoublePanelVertical, TriplePanelBottom, TriplePanelTop, TriplePanelLeft, TriplePanelRight # mullion - distance between panels - 'FirstMullionOffset': ..., # distance from the first lining to the mullion + "FirstMullionOffset": ..., # distance from the first lining to the mullion # TODO: take mullion thickness into account - 'MullionThickness': ..., + "MullionThickness": ..., # applies to DoublePanelHorizontal, TriplePanelBottom, TriplePanelTop, TriplePanelLeft, TriplePanelRight # works similar way to mullion - 'FirstTransomOffset': ..., - 'TransomThickness': ..., + "FirstTransomOffset": ..., + "TransomThickness": ..., # applies to TriplePanelVertical - 'SecondMullionOffset': ..., # distance from the first lining to the second mullion + "SecondMullionOffset": ..., # distance from the first lining to the second mullion # applies to TriplePanelHorizontal - 'SecondTransomOffset': ..., - 'ShapeAspectStyle': None, # DEPRECATED - }, + "SecondTransomOffset": ..., + "ShapeAspectStyle": None, # DEPRECATED + }, "panel_properties": [ { - 'FrameDepth': 35, # by Y - 'FrameThickness': 35, # by X + "FrameDepth": 35, # by Y + "FrameThickness": 35, # by X # BOTTOM, LEFT, MIDDLE, RIGHT, TOP - 'PanelPosition': ..., + "PanelPosition": ..., # defines the basic ways to describe how window panels operate # how it's hanged, how it opens - 'OperationType': None, - 'ShapeAspectStyle': None, # DEPRECATED - + "OperationType": None, + "ShapeAspectStyle": None, # DEPRECATED # Custom Parameter not available in IFC # dimensions of the panel relative to overall window dimensions - 'RelativeWidth': 1.0, - 'RelativeHeight': 1.0, + "RelativeWidth": 1.0, + "RelativeHeight": 1.0, }, - ] + ], } for key, value in settings.items(): self.settings[key] = value - self.settings["panel_schema"] = DEFAULT_PANEL_SCHEMAS[self.settings['partition_type']] + self.settings["panel_schema"] = DEFAULT_PANEL_SCHEMAS[self.settings["partition_type"]] # recalculate relative width and height to avoid errors # TODO: rework or remove # panels_data = self.settings['panel_properties'] # current_height = sum(p['RelativeHeight'] for p in panels_data) # current_width = sum(p['RelativeWidth'] for p in panels_data) - + # for p in panels_data: # if current_height != 1.0: # p['RelativeHeight'] = p['RelativeHeight'] / current_height @@ -111,74 +111,70 @@ class Usecase: # if current_width != 1.0: # p['RelativeWidth'] = p['RelativeWidth'] / current_width - - def execute(self): self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file) builder = ShapeBuilder(self.file) - overall_height = self.convert_si_to_unit(self.settings['overall_height']) - overall_width = self.convert_si_to_unit(self.settings['overall_width']) + overall_height = self.convert_si_to_unit(self.settings["overall_height"]) + overall_width = self.convert_si_to_unit(self.settings["overall_width"]) - if self.settings['context'].TargetView == 'ELEVATION_VIEW': + if self.settings["context"].TargetView == "ELEVATION_VIEW": rect = builder.rectangle(V(overall_width, 0, overall_height)) - representation_evelevation = builder.get_representation(self.settings['context'], rect) + representation_evelevation = builder.get_representation(self.settings["context"], rect) return representation_evelevation - - panel_schema = self.settings['panel_schema'] - panels = self.settings['panel_properties'] + panel_schema = self.settings["panel_schema"] + panels = self.settings["panel_properties"] accumulated_height = [0] * len(panel_schema[0]) built_panels = [] window_items = [] - lining_thickness = self.convert_si_to_unit(self.settings['lining_properties']['LiningThickness']) - lining_depth = self.convert_si_to_unit(self.settings['lining_properties']['LiningDepth']) - lining_offset = self.convert_si_to_unit(self.settings['lining_properties']['LiningOffset']) - lining_panel_offset_x = self.convert_si_to_unit(self.settings['lining_properties']['LiningToPanelOffsetX']) - lining_panel_offset_y = self.convert_si_to_unit(self.settings['lining_properties']['LiningToPanelOffsetY']) + lining_thickness = self.convert_si_to_unit(self.settings["lining_properties"]["LiningThickness"]) + lining_depth = self.convert_si_to_unit(self.settings["lining_properties"]["LiningDepth"]) + lining_offset = self.convert_si_to_unit(self.settings["lining_properties"]["LiningOffset"]) + lining_panel_offset_x = self.convert_si_to_unit(self.settings["lining_properties"]["LiningToPanelOffsetX"]) + lining_panel_offset_y = self.convert_si_to_unit(self.settings["lining_properties"]["LiningToPanelOffsetY"]) glass_thickness = self.convert_si_to_unit(10) for row_i, panel_row in enumerate(reversed(panel_schema)): accumulated_width = 0 for column_i, panel_i in enumerate(panel_row): if panel_i in built_panels: - accumulated_height[column_i] += cur_panel['RelativeHeight'] - accumulated_width += cur_panel['RelativeWidth'] + accumulated_height[column_i] += cur_panel["RelativeHeight"] + accumulated_width += cur_panel["RelativeWidth"] continue cur_panel = panels[panel_i] current_items = [] - panel_depth = self.convert_si_to_unit(cur_panel['FrameDepth']) - panel_thickness = self.convert_si_to_unit(cur_panel['FrameThickness']) - panel_height = cur_panel['RelativeHeight'] * overall_height - panel_width = cur_panel['RelativeWidth'] * overall_width + panel_depth = self.convert_si_to_unit(cur_panel["FrameDepth"]) + panel_thickness = self.convert_si_to_unit(cur_panel["FrameThickness"]) + panel_height = cur_panel["RelativeHeight"] * overall_height + panel_width = cur_panel["RelativeWidth"] * overall_width - panel_actual_width = panel_width-lining_panel_offset_x*2 - panel_actual_height = panel_height-lining_panel_offset_x*2 + panel_actual_width = panel_width - lining_panel_offset_x * 2 + panel_actual_height = panel_height - lining_panel_offset_x * 2 - glass_width = panel_actual_width - panel_thickness*2 - glass_height = panel_actual_height - panel_thickness*2 + glass_width = panel_actual_width - panel_thickness * 2 + glass_height = panel_actual_height - panel_thickness * 2 # build lining lining_items_vertical = [] lining_items = [] # lining is calculated on panel level because # panel depth is used - lining_rectangle = builder.rectangle( size=V(lining_thickness, lining_depth) ) + lining_rectangle = builder.rectangle(size=V(lining_thickness, lining_depth)) # need to check offsets to decide whether lining should be rectangle # or L shaped - if lining_panel_offset_x >= lining_thickness \ - or lining_panel_offset_y >= lining_depth: + if lining_panel_offset_x >= lining_thickness or lining_panel_offset_y >= lining_depth: lining_vertical_polyline = ifcopenshell.util.element.copy_deep(self.file, lining_rectangle) lining_vertical_height = panel_height else: lining_points = [ - V(0, 0), + V(0, 0), V(0, lining_depth), V(lining_panel_offset_x, lining_depth), - V(lining_panel_offset_x, lining_depth-(panel_depth-lining_panel_offset_y)), - V(lining_thickness, lining_depth-(panel_depth-lining_panel_offset_y)), + V(lining_panel_offset_x, lining_depth - (panel_depth - lining_panel_offset_y)), + V(lining_thickness, lining_depth - (panel_depth - lining_panel_offset_y)), V(lining_thickness, 0), ] @@ -186,61 +182,70 @@ class Usecase: lining_vertical_polyline = builder.polyline(lining_points, closed=True) lining_vertical_height = panel_height - lining_panel_offset_x * 2 - # if lining panel X offset is present + # if lining panel X offset is present # then we also need to add two more box shapes - # to finish the lining after the panel ends + # to finish the lining after the panel ends if lining_panel_offset_x > 0: - lining_vertical_addition = builder.extrude(builder.deep_copy(lining_rectangle), lining_panel_offset_x) + lining_vertical_addition = builder.extrude( + builder.deep_copy(lining_rectangle), lining_panel_offset_x + ) - lining_items_vertical.extend([ - lining_vertical_addition, - builder.translate(lining_vertical_addition, V(0,0,panel_height - lining_panel_offset_x), create_copy=True) - ]) + lining_items_vertical.extend( + [ + lining_vertical_addition, + builder.translate( + lining_vertical_addition, + V(0, 0, panel_height - lining_panel_offset_x), + create_copy=True, + ), + ] + ) # horizontal lining lining_horizontal_polyline = builder.deep_copy(lining_vertical_polyline) lining_horizontal_extruded = builder.extrude( lining_horizontal_polyline, - magnitude=panel_width-2*lining_thickness, - extrusion_vector=V(0,0,-1), - position_z_axis=V(-1,0,0), - position_x_axis=V(0,0,1), - position=V(lining_thickness, 0, 0) + magnitude=panel_width - 2 * lining_thickness, + extrusion_vector=V(0, 0, -1), + position_z_axis=V(-1, 0, 0), + position_x_axis=V(0, 0, 1), + position=V(lining_thickness, 0, 0), ) # TODO: should implement mirror by Z for more readability # TODO: investigate meaning of mirror axes in case of custom x/y/z space # lining_horizontal_mirrored = builder.mirror( - # lining_horizontal_extruded, + # lining_horizontal_extruded, # mirror_point=V(0, panel_height/2), # mirror_axes=V(0,1), # create_copy=True # ) - + lining_horizontal_polyline_mirrored = builder.mirror( lining_horizontal_polyline, - mirror_axes=V(1,0), - mirror_point=V(lining_thickness,0), - create_copy=True + mirror_axes=V(1, 0), + mirror_point=V(lining_thickness, 0), + create_copy=True, ) lining_horizontal_mirrored = builder.extrude( lining_horizontal_polyline_mirrored, - magnitude=panel_width-2*lining_thickness, - extrusion_vector=V(0,0,-1), - position_z_axis=V(-1,0,0), - position_x_axis=V(0,0,1), - position=V(lining_thickness, 0, panel_height - lining_thickness*2) + magnitude=panel_width - 2 * lining_thickness, + extrusion_vector=V(0, 0, -1), + position_z_axis=V(-1, 0, 0), + position_x_axis=V(0, 0, 1), + position=V(lining_thickness, 0, panel_height - lining_thickness * 2), ) lining_items.extend([lining_horizontal_extruded, lining_horizontal_mirrored]) - extrusion_position = V(0,0,lining_panel_offset_x) - lining_vertical_extruded = builder.extrude(lining_vertical_polyline, lining_vertical_height, position=extrusion_position) + extrusion_position = V(0, 0, lining_panel_offset_x) + lining_vertical_extruded = builder.extrude( + lining_vertical_polyline, lining_vertical_height, position=extrusion_position + ) lining_items_vertical.append(lining_vertical_extruded) lining_items_vertical_mirrored = builder.mirror( - lining_items_vertical, mirror_point=V(panel_width/2, 0), - mirror_axes=V(1,0), - create_copy=True) + lining_items_vertical, mirror_point=V(panel_width / 2, 0), mirror_axes=V(1, 0), create_copy=True + ) lining_items.extend(lining_items_vertical) lining_items.extend(lining_items_vertical_mirrored) @@ -250,51 +255,48 @@ class Usecase: panel_items = [] panel_position = V( - lining_panel_offset_x, - (lining_depth-panel_depth) + lining_panel_offset_y, - lining_panel_offset_x) + lining_panel_offset_x, (lining_depth - panel_depth) + lining_panel_offset_y, lining_panel_offset_x + ) panel_rect = builder.rectangle(size=V(panel_actual_width, 0, panel_actual_height)) glass_rect = builder.rectangle( - size=V(glass_width, 0, glass_height), - position=V(panel_thickness, 0, panel_thickness)) + size=V(glass_width, 0, glass_height), position=V(panel_thickness, 0, panel_thickness) + ) panel_profile = builder.profile(panel_rect, inner_curves=glass_rect) panel_extruded = builder.extrude( - panel_profile, - panel_depth, - extrusion_vector=V(0,1,0), - position=panel_position) + panel_profile, panel_depth, extrusion_vector=V(0, 1, 0), position=panel_position + ) panel_items.append(panel_extruded) current_items.extend(panel_items) # add glass - glass_position = panel_position + V(0, panel_depth/2-glass_thickness/2, 0) + glass_position = panel_position + V(0, panel_depth / 2 - glass_thickness / 2, 0) glass_rect = builder.deep_copy(glass_rect) glass = builder.extrude( - glass_rect, - glass_thickness, - extrusion_vector=V(0,1,0), - position=glass_position + glass_rect, glass_thickness, extrusion_vector=V(0, 1, 0), position=glass_position ) current_items.append(glass) # translate panel - accumulated_offset = V(accumulated_width, 0, accumulated_height[column_i]) * V(overall_width, 0, overall_height) + accumulated_offset = V(accumulated_width, 0, accumulated_height[column_i]) * V( + overall_width, 0, overall_height + ) builder.translate(current_items, accumulated_offset) built_panels.append(panel_i) window_items.extend(current_items) - - accumulated_height[column_i] += cur_panel['RelativeHeight'] - accumulated_width += cur_panel['RelativeWidth'] - builder.translate(window_items, V(0, lining_offset, 0)) # wall offset - representation = builder.get_representation(self.settings['context'], window_items) + accumulated_height[column_i] += cur_panel["RelativeHeight"] + accumulated_width += cur_panel["RelativeWidth"] + + builder.translate(window_items, V(0, lining_offset, 0)) # wall offset + representation = builder.get_representation(self.settings["context"], window_items) return representation def convert_si_to_unit(self, value): return value * 0.001 / self.settings["unit_scale"] + # TODO: remove test at the end if __name__ == "__main__": ifc_file = ifcopenshell.file() @@ -337,14 +339,13 @@ if __name__ == "__main__": ), } - settings = { - 'context': representations['body'], - # SINGLE_PANEL, DOUBLE_PANEL_HORIZONTAL, DOUBLE_PANEL_VERTICAL, + "context": representations["body"], + # SINGLE_PANEL, DOUBLE_PANEL_HORIZONTAL, DOUBLE_PANEL_VERTICAL, # TRIPLE_PANEL_BOTTOM, TRIPLE_PANEL_HORIZONTAL, TRIPLE_PANEL_LEFT, TRIPLE_PANEL_RIGHT, TRIPLE_PANEL_TOP, TRIPLE_PANEL_VERTICAL - "partition_type": 'TRIPLE_PANEL_RIGHT', + "partition_type": "TRIPLE_PANEL_RIGHT", "overall_height": 900, - "overall_width": 600*3, + "overall_width": 600 * 3, # "lining_properties": { # 'LiningDepth': 50, # 'LiningThickness': 50, @@ -358,34 +359,34 @@ if __name__ == "__main__": # 'MullionThickness': ..., # # applies to DoublePanelHorizontal, TriplePanelBottom, TriplePanelTop, TriplePanelLeft, TriplePanelRight # # works similar way to mullion - # 'FirstTransomOffset': ..., + # 'FirstTransomOffset': ..., # 'TransomThickness': ..., # # applies to TriplePanelVertical # 'SecondMullionOffset': ..., # distance from the first lining to the second mullion # # applies to TriplePanelHorizontal # 'SecondTransomOffset': ..., # 'ShapeAspectStyle': None, # DEPRECATED - # }, + # }, "panel_properties": [ { - 'FrameDepth': 35, # by Y - 'FrameThickness': 35, # by X - 'RelativeWidth': 1.0/2, - 'RelativeHeight': 1.0/2, + "FrameDepth": 35, # by Y + "FrameThickness": 35, # by X + "RelativeWidth": 1.0 / 2, + "RelativeHeight": 1.0 / 2, }, { - 'FrameDepth': 35, # by Y - 'FrameThickness': 35, # by X - 'RelativeWidth': 1.0/2, - 'RelativeHeight': 1.0, + "FrameDepth": 35, # by Y + "FrameThickness": 35, # by X + "RelativeWidth": 1.0 / 2, + "RelativeHeight": 1.0, }, { - 'FrameDepth': 35, # by Y - 'FrameThickness': 35, # by X - 'RelativeWidth': 1.0/2, - 'RelativeHeight': 1.0/2, + "FrameDepth": 35, # by Y + "FrameThickness": 35, # by X + "RelativeWidth": 1.0 / 2, + "RelativeHeight": 1.0 / 2, }, - ] + ], } # builder = ShapeBuilder(ifc_file) # points = [V(0,0), V(5,1)] @@ -405,9 +406,9 @@ if __name__ == "__main__": representation = use_case.execute() print(representation) - settings['context'] = representations['elevation'] + settings["context"] = representations["elevation"] use_case = Usecase(ifc_file, **settings) representation_2d = use_case.execute() print(representation_2d) - ifc_file.write("tmp.ifc") \ No newline at end of file + ifc_file.write("tmp.ifc") diff --git a/src/ifcopenshell-python/ifcopenshell/util/shape_builder.py b/src/ifcopenshell-python/ifcopenshell/util/shape_builder.py index 7971afb0cf..cad8a3437a 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/shape_builder.py +++ b/src/ifcopenshell-python/ifcopenshell/util/shape_builder.py @@ -30,6 +30,7 @@ sign = lambda x: x and (1, -1)[x < 0] # is applied twice during one run to the same element # which might produce undesirable results + class ShapeBuilder: def __init__(self, ifc_file): self.ifc = ifc_file @@ -60,7 +61,7 @@ class ShapeBuilder: dimensions = len(size) if not position: - position = Vector([0]*dimensions) + position = Vector([0] * dimensions) # adds support both 2d and 3d sizes non_empty_coords = [i for i, v in enumerate(size) if v] @@ -70,7 +71,7 @@ class ShapeBuilder: position, position + size * id_matrix[non_empty_coords[0]], position + size, - position + size * id_matrix[non_empty_coords[1]] + position + size * id_matrix[non_empty_coords[1]], ] return points @@ -132,7 +133,7 @@ class ShapeBuilder: V(0, -y_axis_radius), ) if position_offset: - trim_points = [points[i]+position_offset for i in trim_points_mask] + trim_points = [points[i] + position_offset for i in trim_points_mask] else: trim_points = [points[i] for i in trim_points_mask] return trim_points @@ -148,7 +149,7 @@ class ShapeBuilder: ): """ Ellipse trimming points should be specified in counter clockwise order. - + For example, if you need to get the part of the ellipse ABOVE y-axis, you need to use mask (0,2). Below y-axis - (2,0) For more information about trim_points_mask check builder.get_trim_points_from_mask @@ -157,7 +158,9 @@ class ShapeBuilder: for further extrusion. """ direction = self.ifc.createIfcDirection(ref_x_direction) - ifc_position = self.ifc.createIfcAxis2Placement2D(self.ifc.createIfcCartesianPoint(position), RefDirection=direction) + ifc_position = self.ifc.createIfcAxis2Placement2D( + self.ifc.createIfcCartesianPoint(position), RefDirection=direction + ) ifc_ellipse = self.ifc.createIfcEllipse(Position=ifc_position, SemiAxis1=x_axis_radius, SemiAxis2=y_axis_radius) if not trim_points: @@ -239,11 +242,10 @@ class ShapeBuilder: return processed_objects if multiple_objects else processed_objects[0] - def rotate_2d_point(self, point_2d:Vector, angle=90, - pivot_point:Vector = Vector( (0., 0.)).freeze(), - counter_clockwise=False + def rotate_2d_point( + self, point_2d: Vector, angle=90, pivot_point: Vector = Vector((0.0, 0.0)).freeze(), counter_clockwise=False ): - + # > angle - in degrees # < rotated Vector @@ -345,7 +347,7 @@ class ShapeBuilder: placement_matrix=None, ): """mirror_axes - along which axes mirror will be applied - + For example, mirroring A(1,0) by axis (1,0) will result in A'(-1,0) """ # > curve_or_item - could be a list of curves or items @@ -415,7 +417,7 @@ class ShapeBuilder: # TODO: add support for Z-axis too # mirror point is ignored for extrusion direction - new_direction = self.mirror_2d_point(extruded_direction.to_2d(), mirror_axes, mirror_point=V(0,0)) + new_direction = self.mirror_2d_point(extruded_direction.to_2d(), mirror_axes, mirror_point=V(0, 0)) new_direction = new_direction.to_3d() new_direction.z = extruded_direction.z @@ -500,4 +502,4 @@ class ShapeBuilder: return representation def deep_copy(self, element): - return ifcopenshell.util.element.copy_deep(self.ifc, element) \ No newline at end of file + return ifcopenshell.util.element.copy_deep(self.ifc, element)