From b09068e1f415deaf56a0801e4dffd8f3dc1436ae Mon Sep 17 00:00:00 2001 From: martinaCodes Date: Mon, 7 Nov 2022 17:40:18 +0100 Subject: [PATCH] write_file added logic that ensures proper model hierarchy --- src/ifcsverchok/__init__.py | 15 ++------ src/ifcsverchok/nodes/ifc/bmesh_to_ifc.py | 3 +- src/ifcsverchok/nodes/ifc/write_file.py | 44 ++++++++++++++++++++++- 3 files changed, 48 insertions(+), 14 deletions(-) diff --git a/src/ifcsverchok/__init__.py b/src/ifcsverchok/__init__.py index d01676e15c..a747a7aa34 100644 --- a/src/ifcsverchok/__init__.py +++ b/src/ifcsverchok/__init__.py @@ -118,16 +118,13 @@ class IFC_Sv_UpdateCurrent(bpy.types.Operator): self.file.write("/Users/martina/Documents/GSoC/CodeTests/IfcFileTest_7_11_purged.ifc") node_tree = context.space_data.node_tree if node_tree: - print("### \tupdate tree", node_tree) if self.force_mode or node_tree.sv_process: - print("### \tforce update") try: bpy.context.window.cursor_set("WAIT") node_tree.force_update() finally: bpy.context.window.cursor_set("DEFAULT") - print("### \tupdate tree done") - self.report({"INFO"}, "Node tree updated") + self.report({"INFO"}, "Node tree updated.") return {'FINISHED'} class IFC_Sv_write_file(bpy.types.Operator): @@ -193,13 +190,6 @@ class IFC_Sv_write_file(bpy.types.Operator): raise Exception("Bad path. Provide a path to a file.") else: self.ensure_hirarchy(self.file) - print("### \thirarchy ensured") - # if not (self.file.by_type("IfcSpatialElement") or self.file.by_type("IfcSpatialStructureElement")): - # self.report({"INFO"},"No Ifc Spatial Element found. Adding all elements to IfcBuilding.") - # elements = self.file.by_type("IfcElement") - # building = ifcopenshell.api.run("root.create_entity", self.file, name="DefaultBuilding", ifc_class="IfcBuilding") - # for element in elements: - # ifcopenshell.api.run("spatial.assign_container", self.file, product=element, relating_structure=building) self.file.write(self.filepath) self.report({"INFO"}, f"File written to: {self.filepath}") return {"FINISHED"} @@ -226,8 +216,9 @@ class IFC_PT_write_file_panel(bpy.types.Panel): layout = self.layout row = layout.split(factor=0.2, align=True) row = layout.row() + row2 = layout.row() row.operator('ifc.sverchok_update_current', text='IFC Re-run all nodes') - row.operator("ifc.write_file_panel") + row2.operator("ifc.write_file_panel") CLASSES = [IFC_Sv_UpdateCurrent,IFC_Sv_write_file, IFC_PT_write_file_panel] diff --git a/src/ifcsverchok/nodes/ifc/bmesh_to_ifc.py b/src/ifcsverchok/nodes/ifc/bmesh_to_ifc.py index 31a402beb5..5fe56b0ba5 100644 --- a/src/ifcsverchok/nodes/ifc/bmesh_to_ifc.py +++ b/src/ifcsverchok/nodes/ifc/bmesh_to_ifc.py @@ -135,6 +135,7 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help locations = [] for blender_object in blender_objects: if blender_object.type == 'MESH': + bpy.ops.object.mode_set(mode='OBJECT') bpy.ops.object.select_all(action='DESELECT') blender_object.select_set(True) bpy.ops.object.mode_set(mode='EDIT') @@ -147,7 +148,7 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help representations_ids.append(representation.id()) SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Representations", []).append(representation.id()) locations.append(blender_object.matrix_world) - SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Locations", []).append(location) + SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Locations", []).append(blender_object.matrix_world) bpy.ops.object.mode_set(mode='OBJECT') bpy.ops.object.select_all(action='DESELECT') return representations_ids, locations diff --git a/src/ifcsverchok/nodes/ifc/write_file.py b/src/ifcsverchok/nodes/ifc/write_file.py index e2f7c51819..554ae811be 100644 --- a/src/ifcsverchok/nodes/ifc/write_file.py +++ b/src/ifcsverchok/nodes/ifc/write_file.py @@ -50,7 +50,7 @@ class SvIfcWriteFile(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.Sv def draw_buttons(self, context, layout): row = layout.row(align=True) - row.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = "Writes active Ifc file to path.\n It will overwrite an existing file." + row.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = "Writes active Ifc file to path.\n It will overwrite an existing file.\n N.B.! It's recommended to create a fresh IFC File using the 're-run all nodes' button in IfcSverchok panel before saving." row.prop(self, 'refresh_local', icon='FILE_REFRESH') def process(self): @@ -63,8 +63,50 @@ class SvIfcWriteFile(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.Sv if not ext: raise Exception("Bad path. Provide a path to a file.") if self.refresh_local and ext: + self.ensure_hirarchy(file) file.write(path) self.outputs["output"].sv_set(f"File written successfully to: {path}.") + + def ensure_hirarchy(self, file): + elements_in_buildings = [] + if not 0 <= 0 < len(file.by_type("IfcBuilding")): + my_building = ifcopenshell.api.run("root.create_entity", file, ifc_class="IfcBuilding", name="My Building") + elements = ifcopenshell.util.element.get_decomposition(my_building) + else: + for building in file.by_type("IfcBuilding"): + elements = ifcopenshell.util.element.get_decomposition(building) + elements_in_buildings.extend(elements) + + for spatial in (file.by_type("IfcSpatialElement") or file.by_type("IfcSpatialStructureElement")): + if (not (spatial.is_a("IfcSite") or spatial.is_a("IfcBuilding")) and (spatial not in elements_in_buildings)): + elements = ifcopenshell.util.element.get_decomposition(spatial) + ifcopenshell.api.run("aggregate.assign_object", file, product=spatial, relating_object=file.by_type("IfcBuilding")[0]) + + elements_in_buildings_after = [] + for building in file.by_type("IfcBuilding"): + elements = ifcopenshell.util.element.get_decomposition(building) + elements_in_buildings_after.extend(elements) + + elements = file.by_type("IfcElement") + for element in elements: + if element not in elements_in_buildings: + ifcopenshell.api.run("spatial.assign_container", file, product=element, relating_structure=file.by_type("IfcBuilding")[0]) + + + for building in file.by_type("IfcBuilding"): + elements = ifcopenshell.util.element.get_decomposition(building) + if not building.Decomposes: + if not 0 <= 0 < len(file.by_type("IfcSite")): + ifcopenshell.api.run("root.create_entity", file, ifc_class="IfcSite", name="My Site") + ifcopenshell.api.run("aggregate.assign_object", file, product=building, relating_object=file.by_type("IfcSite")[0]) + try: + if file.by_type("IfcSite")[0].Decomposes[0].RelatingObject.is_a("IfcProject"): + continue + except IndexError: + pass + ifcopenshell.api.run("aggregate.assign_object", file, product=file.by_type("IfcSite")[0], relating_object=file.by_type("IfcProject")[0]) + self.file = file + return