Skip to content

Commit

Permalink
Experimental reimplementation of reloading an updated IFC
Browse files Browse the repository at this point in the history
  • Loading branch information
Moult committed Oct 24, 2022
1 parent a908fa6 commit 248dab9
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 6 deletions.
10 changes: 8 additions & 2 deletions src/blenderbim/blenderbim/bim/ifc.py
Expand Up @@ -252,13 +252,19 @@ def relink_object(obj):
if not obj:
return
if obj.BIMObjectProperties.ifc_definition_id:
element = IfcStore.get_file().by_id(obj.BIMObjectProperties.ifc_definition_id)
try:
element = IfcStore.get_file().by_id(obj.BIMObjectProperties.ifc_definition_id)
except:
return
data = {"id": element.id(), "obj": obj.name}
if hasattr(element, "GlobalId"):
data["guid"] = element.GlobalId
IfcStore.commit_link_element(data)
if hasattr(obj, "BIMMaterialProperties") and obj.BIMMaterialProperties.ifc_style_id:
element = IfcStore.get_file().by_id(obj.BIMMaterialProperties.ifc_style_id)
try:
element = IfcStore.get_file().by_id(obj.BIMMaterialProperties.ifc_style_id)
except:
return
data = {"id": element.id(), "obj": obj.name}
IfcStore.commit_link_element(data)

Expand Down
72 changes: 68 additions & 4 deletions src/blenderbim/blenderbim/bim/operator.py
Expand Up @@ -19,11 +19,14 @@
import os
import bpy
import json
import time
import logging
import webbrowser
import ifcopenshell
import blenderbim.bim.handler
import blenderbim.tool as tool
from . import schema
from blenderbim.bim import import_ifc
from blenderbim.bim.ifc import IfcStore
from blenderbim.bim.prop import StrProperty
from blenderbim.bim.ui import IFCFileSelector
Expand Down Expand Up @@ -397,16 +400,77 @@ def purge_all_section_data(self, context):
bpy.ops.object.delete({"selected_objects": [context.active_object]})


class ReloadIfcFile(bpy.types.Operator):
class ReloadIfcFile(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.reload_ifc_file"
bl_label = "Reload IFC File"
bl_options = {"REGISTER", "UNDO"}
bl_description = "Reload the same IFC file"
bl_description = "Reload an updated IFC file"
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
filter_glob: bpy.props.StringProperty(default="*.ifc", options={"HIDDEN"})

def execute(self, context):
# TODO: reimplement. See #1222.
def _execute(self, context):
import ifcdiff

old = tool.Ifc.get()
new = ifcopenshell.open(self.filepath)

ifc_diff = ifcdiff.IfcDiff(old, new, relationships=[])
ifc_diff.diff()

changed_elements = set([k for k, v in ifc_diff.change_register.items() if "geometry_changed" in v])

for global_id in ifc_diff.deleted_elements | changed_elements:
element = tool.Ifc.get().by_guid(global_id)
obj = tool.Ifc.get_object(element)
if obj:
bpy.data.objects.remove(obj)

# STEP IDs may change, but we assume the GlobalID to be constant
obj_map = {}
for obj in bpy.data.objects:
element = tool.Ifc.get_entity(obj)
if element and hasattr(element, "GlobalId"):
obj_map[obj.name] = element.GlobalId

delta_elements = [new.by_guid(global_id) for global_id in ifc_diff.added_elements | changed_elements]
tool.Ifc.set(new)

for obj in bpy.data.objects:
global_id = obj_map.get(obj.name)
if global_id:
try:
tool.Ifc.link(new.by_guid(global_id), obj)
except:
# Still prototyping, so things like types definitely won't work
print("Could not relink", obj)

start = time.time()
logger = logging.getLogger("ImportIFC")
path_log = os.path.join(context.scene.BIMProperties.data_dir, "process.log")
if not os.access(context.scene.BIMProperties.data_dir, os.W_OK):
path_log = os.path.join(tempfile.mkdtemp(), "process.log")
logging.basicConfig(
filename=path_log,
filemode="a",
level=logging.DEBUG,
)
settings = import_ifc.IfcImportSettings.factory(context, self.filepath, logger)
settings.has_filter = True
settings.should_filter_spatial_elements = False
settings.elements = delta_elements
settings.logger.info("Starting import")
ifc_importer = import_ifc.IfcImporter(settings)
ifc_importer.execute()
settings.logger.info("Import finished in {:.2f} seconds".format(time.time() - start))
print("Import finished in {:.2f} seconds".format(time.time() - start))

context.scene.BIMProperties.ifc_file = self.filepath
return {"FINISHED"}

def invoke(self, context, event):
context.window_manager.fileselect_add(self)
return {"RUNNING_MODAL"}


class AddIfcFile(bpy.types.Operator):
bl_idname = "bim.add_ifc_file"
Expand Down

0 comments on commit 248dab9

Please sign in to comment.