From b78e7104790d567b7871f1509f61b826ba862022 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Tue, 12 Jan 2021 16:39:01 +1100 Subject: [PATCH] WIP implement add / remove fills. See #1222. --- .../blenderbim/bim/import_ifc.py | 2 +- .../blenderbim/bim/module/void/__init__.py | 9 ++-- .../blenderbim/bim/module/void/add_filling.py | 16 ++++++ .../blenderbim/bim/module/void/data.py | 12 +++-- .../blenderbim/bim/module/void/operator.py | 50 +++++++++++++++++-- .../blenderbim/bim/module/void/prop.py | 7 +++ .../bim/module/void/remove_filling.py | 12 +++++ .../blenderbim/bim/module/void/ui.py | 26 +++++++--- 8 files changed, 117 insertions(+), 17 deletions(-) create mode 100644 src/ifcblenderexport/blenderbim/bim/module/void/add_filling.py create mode 100644 src/ifcblenderexport/blenderbim/bim/module/void/prop.py create mode 100644 src/ifcblenderexport/blenderbim/bim/module/void/remove_filling.py diff --git a/src/ifcblenderexport/blenderbim/bim/import_ifc.py b/src/ifcblenderexport/blenderbim/bim/import_ifc.py index e099e3c41c..5c202bc7da 100644 --- a/src/ifcblenderexport/blenderbim/bim/import_ifc.py +++ b/src/ifcblenderexport/blenderbim/bim/import_ifc.py @@ -471,7 +471,7 @@ class IfcImporter: self.profile_code("Create presentation layers") self.add_project_to_scene() self.profile_code("Add project to scene") - if self.ifc_import_settings.should_clean_mesh and len(self.file.by_type("IfcElement")) < 10000: + if self.ifc_import_settings.should_clean_mesh and len(self.file.by_type("IfcElement")) < 1000: self.clean_mesh() self.profile_code("Mesh cleaning") diff --git a/src/ifcblenderexport/blenderbim/bim/module/void/__init__.py b/src/ifcblenderexport/blenderbim/bim/module/void/__init__.py index a5f2fe7f70..3727f40508 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/void/__init__.py +++ b/src/ifcblenderexport/blenderbim/bim/module/void/__init__.py @@ -1,16 +1,19 @@ import bpy -from . import ui, operator +from . import ui, prop, operator classes = ( operator.AddOpening, operator.RemoveOpening, + operator.AddFilling, + operator.RemoveFilling, + prop.VoidProperties, ui.BIM_PT_voids, ) def register(): - pass + bpy.types.Scene.VoidProperties = bpy.props.PointerProperty(type=prop.VoidProperties) def unregister(): - pass + del bpy.types.Scene.VoidProperties diff --git a/src/ifcblenderexport/blenderbim/bim/module/void/add_filling.py b/src/ifcblenderexport/blenderbim/bim/module/void/add_filling.py new file mode 100644 index 0000000000..0acb8b6c48 --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/void/add_filling.py @@ -0,0 +1,16 @@ +import ifcopenshell + + +class Usecase: + def __init__(self, file, settings=None): + self.file = file + self.settings = {"opening": None, "element": None} + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + self.file.create_entity("IfcRelFillsElement", **{ + "GlobalId": ifcopenshell.guid.new(), + "RelatingOpeningElement": self.settings["opening"], + "RelatedBuildingElement": self.settings["element"] + }) diff --git a/src/ifcblenderexport/blenderbim/bim/module/void/data.py b/src/ifcblenderexport/blenderbim/bim/module/void/data.py index 13d018f72c..363405b4ca 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/void/data.py +++ b/src/ifcblenderexport/blenderbim/bim/module/void/data.py @@ -8,11 +8,12 @@ class Data: @classmethod def load(cls, product_id): - print('loading', product_id) file = IfcStore.get_file() if not file: return cls.products[product_id] = set() + if product_id in cls.fillings: + del cls.fillings[product_id] product = file.by_id(product_id) for rel in file.by_type("IfcRelVoidsElement"): building_element = rel.RelatingBuildingElement @@ -25,10 +26,15 @@ class Data: for rel in file.by_type("IfcRelFillsElement"): opening = rel.RelatingOpeningElement opening_id = int(opening.id()) - if opening_id not in cls.openings: - continue filling = rel.RelatedBuildingElement filling_id = int(filling.id()) + + if filling_id == product_id and opening_id not in cls.openings: + cls.openings[opening_id] = {"Name": opening.Name, "HasFillings": set()} + + if opening_id not in cls.openings: + continue + cls.fillings[filling_id] = {"Name": filling.Name, "FillsVoid": opening_id} cls.openings[opening_id]["HasFillings"].add(filling_id) return # See bug #1224 diff --git a/src/ifcblenderexport/blenderbim/bim/module/void/operator.py b/src/ifcblenderexport/blenderbim/bim/module/void/operator.py index 970bfdc8ef..5e3b998c48 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/void/operator.py +++ b/src/ifcblenderexport/blenderbim/bim/module/void/operator.py @@ -1,6 +1,8 @@ import bpy import blenderbim.bim.module.void.add_opening as add_opening import blenderbim.bim.module.void.remove_opening as remove_opening +import blenderbim.bim.module.void.add_filling as add_filling +import blenderbim.bim.module.void.remove_filling as remove_filling from blenderbim.bim.ifc import IfcStore from blenderbim.bim.module.void.data import Data from blenderbim.bim.module.context.data import Data as ContextData @@ -30,10 +32,13 @@ class AddOpening(bpy.types.Operator): self.file = IfcStore.get_file() element_id = obj.BIMObjectProperties.ifc_definition_id - add_opening.Usecase(self.file, { - "opening": self.file.by_id(opening.BIMObjectProperties.ifc_definition_id), - "element": self.file.by_id(element_id) - }).execute() + add_opening.Usecase( + self.file, + { + "opening": self.file.by_id(opening.BIMObjectProperties.ifc_definition_id), + "element": self.file.by_id(element_id), + }, + ).execute() Data.load(element_id) has_modifier = False @@ -72,3 +77,40 @@ class RemoveOpening(bpy.types.Operator): remove_opening.Usecase(self.file, {"opening": self.file.by_id(self.opening_id)}).execute() Data.load(obj.BIMObjectProperties.ifc_definition_id) return {"FINISHED"} + + +class AddFilling(bpy.types.Operator): + bl_idname = "bim.add_filling" + bl_label = "Add Filling" + opening: bpy.props.StringProperty() + obj: bpy.props.StringProperty() + + def execute(self, context): + obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object + opening = bpy.data.objects.get(self.opening) if self.opening else context.scene.VoidProperties.desired_opening + self.file = IfcStore.get_file() + element_id = obj.BIMObjectProperties.ifc_definition_id + add_filling.Usecase( + self.file, + { + "opening": self.file.by_id(opening.BIMObjectProperties.ifc_definition_id), + "element": self.file.by_id(element_id), + }, + ).execute() + Data.load(element_id) + return {"FINISHED"} + + +class RemoveFilling(bpy.types.Operator): + bl_idname = "bim.remove_filling" + bl_label = "Remove Filling" + obj: bpy.props.StringProperty() + + def execute(self, context): + obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object + self.file = IfcStore.get_file() + remove_filling.Usecase( + self.file, {"element": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)} + ).execute() + Data.load(obj.BIMObjectProperties.ifc_definition_id) + return {"FINISHED"} diff --git a/src/ifcblenderexport/blenderbim/bim/module/void/prop.py b/src/ifcblenderexport/blenderbim/bim/module/void/prop.py new file mode 100644 index 0000000000..4dd1185fe6 --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/void/prop.py @@ -0,0 +1,7 @@ +import bpy +from bpy.types import PropertyGroup +from bpy.props import PointerProperty + + +class VoidProperties(PropertyGroup): + desired_opening: PointerProperty(name="Desired Opening To Fill", type=bpy.types.Object) diff --git a/src/ifcblenderexport/blenderbim/bim/module/void/remove_filling.py b/src/ifcblenderexport/blenderbim/bim/module/void/remove_filling.py new file mode 100644 index 0000000000..105acb9160 --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/void/remove_filling.py @@ -0,0 +1,12 @@ +class Usecase: + def __init__(self, file, settings=None): + self.file = file + self.settings = {"element": None} + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + for rel in self.file.by_type("IfcRelFillsElement"): + if rel.RelatedBuildingElement == self.settings["element"]: + self.file.remove(rel) + break diff --git a/src/ifcblenderexport/blenderbim/bim/module/void/ui.py b/src/ifcblenderexport/blenderbim/bim/module/void/ui.py index cc5144b7ee..be4a49f194 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/void/ui.py +++ b/src/ifcblenderexport/blenderbim/bim/module/void/ui.py @@ -18,7 +18,7 @@ class BIM_PT_voids(Panel): row = self.layout.row(align=True) if len(context.selected_objects) == 2: - op = row.operator("bim.add_opening", icon="ADD", text="Add Selected") + op = row.operator("bim.add_opening", icon="ADD", text="Add Opening") for obj in context.selected_objects: if "IfcOpeningElement" in obj.name or not obj.BIMObjectProperties.ifc_definition_id: op.opening = obj.name @@ -35,22 +35,36 @@ class BIM_PT_voids(Panel): else: obj_name = obj.name if opening_id and obj_name: - op = row.operator("bim.remove_opening", icon="X", text="Remove Selected") + op = row.operator("bim.remove_opening", icon="X", text="Remove Opening") op.opening_id = opening_id op.obj = obj_name else: row.label(text="Select an opening and an element to modify", icon="HELP") - for opening_id in Data.products[props.ifc_definition_id]: + opening_ids = Data.products[props.ifc_definition_id] + if not opening_ids: + row = self.layout.row(align=True) + row.label(text="No Openings", icon="SELECT_SUBTRACT") + for opening_id in opening_ids: opening = Data.openings[opening_id] if opening["HasFillings"]: for filling_id in opening["HasFillings"]: filling = Data.fillings[filling_id] row = self.layout.row(align=True) - row.label(text=opening["Name"]) - row.label(text=filling["Name"]) + row.label(text=opening["Name"], icon="SELECT_SUBTRACT") + row.label(text=filling["Name"], icon="SELECT_INTERSECT") else: row = self.layout.row(align=True) - row.label(text=opening["Name"]) + row.label(text=opening["Name"], icon="SELECT_SUBTRACT") op = row.operator("bim.remove_opening", icon="X", text="") op.opening_id = opening_id + + if props.ifc_definition_id not in Data.fillings: + row = self.layout.row(align=True) + row.prop(context.scene.VoidProperties, "desired_opening", text="", icon="SELECT_INTERSECT") + row.operator("bim.add_filling", icon="ADD", text="") + else: + opening = Data.openings[Data.fillings[props.ifc_definition_id]["FillsVoid"]] + row = self.layout.row(align=True) + row.label(text=opening["Name"], icon="SELECT_INTERSECT") + row.operator("bim.remove_filling", icon="X", text="")