From c5164395b8b6d12e55113c3cf6d747b88e59ab55 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Wed, 29 Nov 2023 15:57:59 +1100 Subject: [PATCH] See #4054. Diffing now allows partial loading of changed elements to make it easier to visualise without loading and linking two models. --- .../blenderbim/bim/module/diff/operator.py | 92 +++++++++++++++++-- .../blenderbim/bim/module/diff/prop.py | 10 ++ .../blenderbim/bim/module/diff/ui.py | 37 ++++++-- .../bim/module/geometry/operator.py | 1 - 4 files changed, 127 insertions(+), 13 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/diff/operator.py b/src/blenderbim/blenderbim/bim/module/diff/operator.py index b11aa9c288..6ddc336812 100644 --- a/src/blenderbim/blenderbim/bim/module/diff/operator.py +++ b/src/blenderbim/blenderbim/bim/module/diff/operator.py @@ -18,7 +18,7 @@ import bpy import json -import ifccsv +import logging import ifcopenshell import blenderbim.bim.handler import blenderbim.tool as tool @@ -53,6 +53,16 @@ class VisualiseDiff(bpy.types.Operator): for obj in context.visible_objects: obj.color = (1.0, 1.0, 1.0, 1.0) + if "IfcDiff Deleted Elements" in obj.users_collection[0].name: + obj.color = (1.0, 0.0, 0.0, 1.0) + continue + elif "IfcDiff Added Elements" in obj.users_collection[0].name: + obj.color = (0.0, 1.0, 0.0, 1.0) + continue + elif "IfcDiff Changed Elements" in obj.users_collection[0].name: + obj.color = (0.0, 0.0, 0.7, 1.0) + continue + if not obj.BIMObjectProperties.ifc_definition_id: continue @@ -135,14 +145,84 @@ class ExecuteIfcDiff(bpy.types.Operator): def execute(self, context): import ifcdiff - old = ifcopenshell.open(context.scene.DiffProperties.old_file) - new = ifcopenshell.open(context.scene.DiffProperties.new_file) - relationships = [r.relationship for r in context.scene.DiffProperties.diff_relationships] - query = context.scene.DiffProperties.diff_filter_elements + self.props = context.scene.DiffProperties + + if tool.Ifc.get(): + if self.props.active_file == "NONE": + old = ifcopenshell.open(self.props.old_file) + new = ifcopenshell.open(self.props.new_file) + elif self.props.active_file == "NEW": + old = ifcopenshell.open(self.props.old_file) + new = tool.Ifc.get() + elif self.props.active_file == "OLD": + old = tool.Ifc.get() + new = ifcopenshell.open(self.props.new_file) + else: + old = ifcopenshell.open(self.props.old_file) + new = ifcopenshell.open(self.props.new_file) + + relationships = [r.relationship for r in self.props.diff_relationships] + query = self.props.diff_filter_elements ifc_diff = ifcdiff.IfcDiff(old, new, relationships=relationships, filter_elements=query) ifc_diff.diff() ifc_diff.export(self.filepath) - context.scene.DiffProperties.diff_json_file = self.filepath + self.props.diff_json_file = self.filepath + + self.load_changed_elements(ifc_diff) + blenderbim.bim.handler.refresh_ui_data() return {"FINISHED"} + + def load_changed_elements(self, ifc_diff): + if not tool.Ifc.get() or self.props.active_file == "NONE" or not self.props.should_load_changed_elements: + return + + active_ifc = tool.Ifc.get() + logger = logging.getLogger("ImportIFC") + ifc_import_settings = blenderbim.bim.import_ifc.IfcImportSettings.factory(bpy.context, None, logger) + ifc_importer = blenderbim.bim.import_ifc.IfcImporter(ifc_import_settings) + + if self.props.active_file == "NEW": + tool.Ifc.set(ifc_diff.old) + ifc_importer.file = ifc_diff.old + ifc_importer.process_context_filter() + ifc_importer.create_materials() + ifc_importer.create_styles() + + elements = {ifc_diff.old.by_guid(guid) for guid in ifc_diff.deleted_elements} + ifc_importer.create_generic_elements(elements) + self.place_objs_in_collection(ifc_importer.added_data.values(), "IfcDiff Deleted Elements") + + ifc_importer.added_data = {} + + elements = {ifc_diff.old.by_guid(guid) for guid in ifc_diff.change_register.keys()} + ifc_importer.create_generic_elements(elements) + self.place_objs_in_collection(ifc_importer.added_data.values(), "IfcDiff Changed Elements") + elif self.props.active_file == "OLD": + tool.Ifc.set(ifc_diff.new) + ifc_importer.file = ifc_diff.new + ifc_importer.process_context_filter() + ifc_importer.create_materials() + ifc_importer.create_styles() + + elements = {ifc_diff.new.by_guid(guid) for guid in ifc_diff.added_elements} + ifc_importer.create_generic_elements(elements) + self.place_objs_in_collection(ifc_importer.added_data.values(), "IfcDiff Added Elements") + + ifc_importer.added_data = {} + + elements = {ifc_diff.new.by_guid(guid) for guid in ifc_diff.change_register.keys()} + ifc_importer.create_generic_elements(elements) + self.place_objs_in_collection(ifc_importer.added_data.values(), "IfcDiff Changed Elements") + tool.Ifc.set(active_ifc) + + def place_objs_in_collection(self, objs, name): + collection = bpy.data.collections.get(name) + if not collection: + collection = bpy.data.collections.new(name) + bpy.context.scene.collection.children.link(collection) + + for obj in objs: + if isinstance(obj, bpy.types.Object): + collection.objects.link(obj) diff --git a/src/blenderbim/blenderbim/bim/module/diff/prop.py b/src/blenderbim/blenderbim/bim/module/diff/prop.py index fb1426416a..8a1522e771 100644 --- a/src/blenderbim/blenderbim/bim/module/diff/prop.py +++ b/src/blenderbim/blenderbim/bim/module/diff/prop.py @@ -49,3 +49,13 @@ class DiffProperties(PropertyGroup): new_file: StringProperty(default="", name="New IFC File") diff_relationships: CollectionProperty(type=Relationships, name="Relationships") diff_filter_elements: StringProperty(default="", name="Filter") + should_load_changed_elements: BoolProperty(name="Load Changed Elements", default=True) + active_file: EnumProperty( + items=[ + ("NONE", "N/A", ""), + ("OLD", "Old", ""), + ("NEW", "New", ""), + ], + name="Active File", + default="NEW", + ) diff --git a/src/blenderbim/blenderbim/bim/module/diff/ui.py b/src/blenderbim/blenderbim/bim/module/diff/ui.py index a0343e2042..335d6ffc6d 100644 --- a/src/blenderbim/blenderbim/bim/module/diff/ui.py +++ b/src/blenderbim/blenderbim/bim/module/diff/ui.py @@ -44,13 +44,38 @@ class BIM_PT_diff(Panel): layout.label(text="IFC Diff Setup:") - row = layout.row(align=True) - row.prop(props, "old_file") - row.operator("bim.select_diff_old_file", icon="FILE_FOLDER", text="") + if tool.Ifc.get(): + row = layout.row() + row.prop(props, "active_file") - row = layout.row(align=True) - row.prop(props, "new_file") - row.operator("bim.select_diff_new_file", icon="FILE_FOLDER", text="") + if props.active_file == "NONE": + row = layout.row(align=True) + row.prop(props, "old_file") + row.operator("bim.select_diff_old_file", icon="FILE_FOLDER", text="") + + row = layout.row(align=True) + row.prop(props, "new_file") + row.operator("bim.select_diff_new_file", icon="FILE_FOLDER", text="") + elif props.active_file == "NEW": + row = layout.row(align=True) + row.prop(props, "old_file") + row.operator("bim.select_diff_old_file", icon="FILE_FOLDER", text="") + elif props.active_file == "OLD": + row = layout.row(align=True) + row.prop(props, "new_file") + row.operator("bim.select_diff_new_file", icon="FILE_FOLDER", text="") + + if props.active_file != "NONE": + row = layout.row() + row.prop(props, "should_load_changed_elements") + else: + row = layout.row(align=True) + row.prop(props, "old_file") + row.operator("bim.select_diff_old_file", icon="FILE_FOLDER", text="") + + row = layout.row(align=True) + row.prop(props, "new_file") + row.operator("bim.select_diff_new_file", icon="FILE_FOLDER", text="") row = layout.row(align=True) row.prop(props, "diff_relationships") diff --git a/src/blenderbim/blenderbim/bim/module/geometry/operator.py b/src/blenderbim/blenderbim/bim/module/geometry/operator.py index 779dfe3044..e9925eafca 100644 --- a/src/blenderbim/blenderbim/bim/module/geometry/operator.py +++ b/src/blenderbim/blenderbim/bim/module/geometry/operator.py @@ -35,7 +35,6 @@ import blenderbim.tool as tool import blenderbim.bim.handler from mathutils import Vector, Matrix from time import time -from blenderbim.bim import import_ifc from blenderbim.bim.ifc import IfcStore