diff --git a/src/ifcblenderexport/blenderbim/bim/__init__.py b/src/ifcblenderexport/blenderbim/bim/__init__.py index e055545c12..efe716e7f0 100644 --- a/src/ifcblenderexport/blenderbim/bim/__init__.py +++ b/src/ifcblenderexport/blenderbim/bim/__init__.py @@ -11,6 +11,7 @@ if bpy is not None: import blenderbim.bim.module.covetool as module_covetool import blenderbim.bim.module.geometry as module_geometry import blenderbim.bim.module.model as module_model + import blenderbim.bim.module.spatial as module_spatial from . import ui, prop, operator classes = [ @@ -316,6 +317,7 @@ if bpy is not None: classes.extend(module_covetool.classes) classes.extend(module_geometry.classes) classes.extend(module_model.classes) + classes.extend(module_spatial.classes) def menu_func_export(self, context): self.layout.operator(operator.ExportIFC.bl_idname, text="Industry Foundation Classes (.ifc/.ifczip/.ifcjson)") @@ -353,6 +355,7 @@ if bpy is not None: module_covetool.register() module_geometry.register() module_model.register() + module_spatial.register() bpy.app.handlers.depsgraph_update_pre.append(operator.depsgraph_update_pre_handler) def unregister(): @@ -373,6 +376,7 @@ if bpy is not None: del bpy.types.Camera.BIMCameraProperties del bpy.types.TextCurve.BIMTextProperties bpy.types.SCENE_PT_unit.remove(ui.ifc_units) + module_spatial.unregister() module_model.unregister() module_geometry.unregister() module_covetool.unregister() diff --git a/src/ifcblenderexport/blenderbim/bim/module/root/operator.py b/src/ifcblenderexport/blenderbim/bim/module/root/operator.py index f4450f06a4..e1f7a3b41f 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/root/operator.py +++ b/src/ifcblenderexport/blenderbim/bim/module/root/operator.py @@ -10,8 +10,6 @@ import blenderbim.bim.module.geometry.assign_representation as assign_representa import blenderbim.bim.module.geometry.add_object_placement as add_object_placement from blenderbim.bim.ifc import IfcStore -# from blenderbim.bim.module.geometry.data import Data - class EnableReassignClass(bpy.types.Operator): bl_idname = "bim.enable_reassign_class" diff --git a/src/ifcblenderexport/blenderbim/bim/module/spatial/__init__.py b/src/ifcblenderexport/blenderbim/bim/module/spatial/__init__.py new file mode 100644 index 0000000000..b3fa7d3542 --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/spatial/__init__.py @@ -0,0 +1,15 @@ +import bpy +from . import ui, operator + +classes = ( + operator.AssignContainer, + ui.BIM_PT_spatial, +) + + +def register(): + pass + + +def unregister(): + pass diff --git a/src/ifcblenderexport/blenderbim/bim/module/spatial/assign_container.py b/src/ifcblenderexport/blenderbim/bim/module/spatial/assign_container.py new file mode 100644 index 0000000000..7e0da2739f --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/spatial/assign_container.py @@ -0,0 +1,42 @@ +import ifcopenshell + + +class Usecase: + def __init__(self, file, settings=None): + self.file = file + self.settings = { + "product": None, + "relating_structure": None, + } + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + contained_in_structure = self.settings["product"].ContainedInStructure + contains_elements = self.settings["relating_structure"].ContainsElements + + if contained_in_structure == contains_elements: + return + + if contained_in_structure: + related_elements = list(contained_in_structure[0].RelatedElements) + related_elements.remove(self.settings["product"]) + if related_elements: + contained_in_structure[0].RelatedElements = related_elements + else: + self.file.remove(contained_in_structure) + + if contains_elements: + related_elements = list(contains_elements[0].RelatedElements) + related_elements.append(self.settings["product"]) + contains_elements.RelatedElements = related_elements + else: + contains_elements = self.file.create_entity( + "IfcRelContainedInSpatialStructure", + **{ + "GlobalId": ifcopenshell.guid.new(), + # TODO "OwnerHistory": None + "RelatedElements": [self.settings["product"]], + "RelatingStructure": self.settings["relating_structure"], + } + ) diff --git a/src/ifcblenderexport/blenderbim/bim/module/spatial/data.py b/src/ifcblenderexport/blenderbim/bim/module/spatial/data.py new file mode 100644 index 0000000000..58007f0ae7 --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/spatial/data.py @@ -0,0 +1,18 @@ +from blenderbim.bim.ifc import IfcStore + + +class Data: + products = {} + + @classmethod + def load(cls, product_id): + file = IfcStore.get_file() + if not file: + return + product = file.by_id(product_id) + element = product.ContainedInStructure[0].RelatingStructure if product.ContainedInStructure else None + cls.products[product_id] = { + "type": element.is_a() if element else None, + "Name": element.Name if element else None, + "id": int(element.id()) if element else None + } diff --git a/src/ifcblenderexport/blenderbim/bim/module/spatial/operator.py b/src/ifcblenderexport/blenderbim/bim/module/spatial/operator.py new file mode 100644 index 0000000000..c78b24de0b --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/spatial/operator.py @@ -0,0 +1,32 @@ +import bpy +import blenderbim.bim.module.spatial.assign_container as assign_container +from blenderbim.bim.ifc import IfcStore +from blenderbim.bim.module.spatial.data import Data + + +class AssignContainer(bpy.types.Operator): + bl_idname = "bim.assign_container" + bl_label = "Assign Container" + + def execute(self, context): + self.file = IfcStore.get_file() + obj = bpy.context.active_object + props = obj.BIMObjectProperties + relating_structure = None + for collection in obj.users_collection: + if "Ifc" in collection.name: + relating_structure = self.file.by_id( + bpy.data.objects.get(collection.name).BIMObjectProperties.ifc_definition_id + ) + if not relating_structure: + return {"FINISHED"} + usecase = assign_container.Usecase( + self.file, + { + "product": self.file.by_id(props.ifc_definition_id), + "relating_structure": relating_structure, + }, + ) + usecase.execute() + Data.load(props.ifc_definition_id) + return {"FINISHED"} diff --git a/src/ifcblenderexport/blenderbim/bim/module/spatial/ui.py b/src/ifcblenderexport/blenderbim/bim/module/spatial/ui.py new file mode 100644 index 0000000000..e958ef168c --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/spatial/ui.py @@ -0,0 +1,31 @@ +from bpy.types import Panel +from blenderbim.bim.module.spatial.data import Data + + +class BIM_PT_spatial(Panel): + bl_label = "IFC Spatial Container" + bl_idname = "BIM_PT_spatial" + bl_space_type = "PROPERTIES" + bl_region_type = "WINDOW" + bl_context = "object" + + @classmethod + def poll(cls, context): + return bool(context.active_object.BIMObjectProperties.ifc_definition_id) + + def draw(self, context): + props = context.active_object.BIMObjectProperties + if not props.ifc_definition_id: + return + if props.ifc_definition_id not in Data.products: + Data.load(props.ifc_definition_id) + + if "Ifc" not in context.active_object.name: + return + + row = self.layout.row(align=True) + name = "{}/{}".format( + Data.products[props.ifc_definition_id]["type"], Data.products[props.ifc_definition_id]["Name"] + ) + row.label(text=name) + row.operator("bim.assign_container", icon="FILE_REFRESH", text="") diff --git a/src/ifcblenderexport/blenderbim/bim/ui.py b/src/ifcblenderexport/blenderbim/bim/ui.py index d29ec12bd1..e7b73b0602 100644 --- a/src/ifcblenderexport/blenderbim/bim/ui.py +++ b/src/ifcblenderexport/blenderbim/bim/ui.py @@ -51,8 +51,6 @@ class BIM_PT_object(Panel): row = layout.row(align=True) row.prop(props, "relating_type") row.operator("bim.select_similar_type", icon="RESTRICT_SELECT_OFF", text="") - row = layout.row() - row.prop(props, "relating_structure") def draw_addresses_ui(self): layout = self.layout