diff --git a/src/blenderbim/blenderbim/bim/export_ifc.py b/src/blenderbim/blenderbim/bim/export_ifc.py index 094b77dcaa..815c815b80 100644 --- a/src/blenderbim/blenderbim/bim/export_ifc.py +++ b/src/blenderbim/blenderbim/bim/export_ifc.py @@ -41,6 +41,7 @@ class IfcExporter: def export(self): self.file = IfcStore.get_file() self.set_header() + IfcStore.update_cache() if bpy.context.scene.BIMProjectProperties.is_authoring: self.sync_deletions() self.sync_object_placements() diff --git a/src/blenderbim/blenderbim/bim/ifc.py b/src/blenderbim/blenderbim/bim/ifc.py index 9942c7059c..bb4c20855f 100644 --- a/src/blenderbim/blenderbim/bim/ifc.py +++ b/src/blenderbim/blenderbim/bim/ifc.py @@ -19,6 +19,7 @@ import os import bpy import uuid +import hashlib import zipfile import tempfile import ifcopenshell @@ -30,6 +31,8 @@ class IfcStore: path = "" file = None schema = None + cache = None + cache_path = None id_map = {} guid_map = {} deleted_ids = set() @@ -50,6 +53,8 @@ class IfcStore: IfcStore.path = "" IfcStore.file = None IfcStore.schema = None + IfcStore.cache = None + IfcStore.cache_path = None IfcStore.id_map = {} IfcStore.guid_map = {} IfcStore.deleted_ids = set() @@ -72,6 +77,27 @@ class IfcStore: pass return IfcStore.file + @staticmethod + def get_cache(): + if IfcStore.cache is None and IfcStore.path: + ifc_key = IfcStore.path + IfcStore.file.wrapped_data.header.file_name.time_stamp + ifc_hash = hashlib.md5(ifc_key.encode("utf-8")).hexdigest() + IfcStore.cache_path = os.path.join(bpy.context.scene.BIMProperties.data_dir, "cache", f"{ifc_hash}.h5") + cache_settings = ifcopenshell.geom.settings() + IfcStore.cache = ifcopenshell.geom.serializers.hdf5(IfcStore.cache_path, cache_settings) + return IfcStore.cache + + @staticmethod + def update_cache(): + if not IfcStore.cache: + return + ifc_key = IfcStore.path + IfcStore.file.wrapped_data.header.file_name.time_stamp + ifc_hash = hashlib.md5(ifc_key.encode("utf-8")).hexdigest() + new_cache_path = os.path.join(bpy.context.scene.BIMProperties.data_dir, "cache", f"{ifc_hash}.h5") + os.replace(IfcStore.cache_path, new_cache_path) + IfcStore.cache = None + IfcStore.get_cache() + @staticmethod def load_file(path): extension = path.split(".")[-1] diff --git a/src/blenderbim/blenderbim/bim/import_ifc.py b/src/blenderbim/blenderbim/bim/import_ifc.py index fef1d45e5f..331d43a782 100644 --- a/src/blenderbim/blenderbim/bim/import_ifc.py +++ b/src/blenderbim/blenderbim/bim/import_ifc.py @@ -625,6 +625,7 @@ class IfcImporter: ) else: iterator = ifcopenshell.geom.iterator(self.settings, self.file, include=products) + iterator.set_cache(IfcStore.get_cache()) valid_file = iterator.initialize() if not valid_file: return results @@ -770,6 +771,7 @@ class IfcImporter: ) else: iterator = ifcopenshell.geom.iterator(self.settings_2d, self.file, include=products) + iterator.set_cache(IfcStore.get_cache()) valid_file = iterator.initialize() if not valid_file: return results diff --git a/src/blenderbim/blenderbim/bim/module/drawing/operator.py b/src/blenderbim/blenderbim/bim/module/drawing/operator.py index 5884ef54ba..95cc499211 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/operator.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/operator.py @@ -335,16 +335,12 @@ class CreateDrawing(bpy.types.Operator): elements = set(ifc.by_type("IfcElement")) - set(ifc.by_type("IfcOpeningElement")) self.setup_serialiser(ifc) - cache_settings = ifcopenshell.geom.settings( - APPLY_DEFAULT_MATERIALS=True, DISABLE_TRIANGULATION=True, SEW_SHELLS=True - ) - cache = ifcopenshell.geom.serializers.hdf5(ifc_cache_path, cache_settings) + cache_settings = ifcopenshell.geom.settings(DISABLE_TRIANGULATION=True) + cache = IfcStore.get_cache() [cache.remove(guid) for guid in invalidated_guids] if target_view_contexts and elements: - geom_settings = ifcopenshell.geom.settings( - APPLY_DEFAULT_MATERIALS=True, DISABLE_TRIANGULATION=True, SEW_SHELLS=True, INCLUDE_CURVES=True - ) + geom_settings = ifcopenshell.geom.settings(DISABLE_TRIANGULATION=True, INCLUDE_CURVES=True) geom_settings.set_context_ids(target_view_contexts) it = ifcopenshell.geom.iterator(geom_settings, ifc, multiprocessing.cpu_count(), include=elements) it.set_cache(cache) @@ -356,7 +352,7 @@ class CreateDrawing(bpy.types.Operator): if body_contexts and elements: geom_settings = ifcopenshell.geom.settings( - APPLY_DEFAULT_MATERIALS=True, DISABLE_TRIANGULATION=True, SEW_SHELLS=True + DISABLE_TRIANGULATION=True, ) geom_settings.set_context_ids(body_contexts) it = ifcopenshell.geom.iterator(geom_settings, ifc, multiprocessing.cpu_count(), include=elements) @@ -365,7 +361,7 @@ class CreateDrawing(bpy.types.Operator): self.serialiser.write(elem) geom_settings = ifcopenshell.geom.settings( - APPLY_DEFAULT_MATERIALS=True, DISABLE_TRIANGULATION=True, SEW_SHELLS=True + DISABLE_TRIANGULATION=True, ) it = ifcopenshell.geom.iterator(geom_settings, ifc, include=[self.camera_element]) for elem in self.yield_from_iterator(it): @@ -383,9 +379,7 @@ class CreateDrawing(bpy.types.Operator): return svg_path def setup_serialiser(self, ifc): - self.svg_settings = ifcopenshell.geom.settings( - APPLY_DEFAULT_MATERIALS=True, DISABLE_TRIANGULATION=True, INCLUDE_CURVES=True - ) + self.svg_settings = ifcopenshell.geom.settings(DISABLE_TRIANGULATION=True, INCLUDE_CURVES=True) self.svg_buffer = ifcopenshell.geom.serializers.buffer() self.serialiser = ifcopenshell.geom.serializers.svg(self.svg_buffer, self.svg_settings) self.serialiser.setFile(ifc) diff --git a/src/blenderbim/blenderbim/bim/module/model/data.py b/src/blenderbim/blenderbim/bim/module/model/data.py index 3bd199dd5a..704b4f5228 100644 --- a/src/blenderbim/blenderbim/bim/module/model/data.py +++ b/src/blenderbim/blenderbim/bim/module/model/data.py @@ -45,10 +45,13 @@ class AuthoringData: @classmethod def relating_types(cls): - if not cls.ifc_classes(): + ifc_classes = cls.ifc_classes() + if not ifc_classes: return [] results = [] ifc_class = bpy.context.scene.BIMModelProperties.ifc_class + if not ifc_class and ifc_classes: + ifc_class = ifc_classes[0][0] if ifc_class: elements = [(str(e.id()), e.Name, "") for e in tool.Ifc.get().by_type(ifc_class)] results.extend(sorted(elements, key=lambda s: s[1])) diff --git a/src/blenderbim/blenderbim/core/geometry.py b/src/blenderbim/blenderbim/core/geometry.py index dbc70cea58..fa34dd865c 100644 --- a/src/blenderbim/blenderbim/core/geometry.py +++ b/src/blenderbim/blenderbim/core/geometry.py @@ -22,6 +22,7 @@ import blenderbim.core.style def edit_object_placement(ifc, geometry, surveyor, obj=None): element = ifc.get_entity(obj) if element: + geometry.clear_cache(element) geometry.clear_scale(obj) ifc.run("geometry.edit_object_placement", product=element, matrix=surveyor.get_absolute_matrix(obj)) diff --git a/src/blenderbim/blenderbim/core/tool.py b/src/blenderbim/blenderbim/core/tool.py index b50fb96788..13340b419e 100644 --- a/src/blenderbim/blenderbim/core/tool.py +++ b/src/blenderbim/blenderbim/core/tool.py @@ -73,6 +73,7 @@ class Context: @interface class Geometry: def change_object_data(cls, obj, data, is_global=False): pass + def clear_cache(cls, element): pass def clear_modifiers(cls, obj): pass def clear_scale(cls, obj): pass def create_dynamic_voids(cls, obj): pass diff --git a/src/blenderbim/blenderbim/tool/geometry.py b/src/blenderbim/blenderbim/tool/geometry.py index 7544cbfc0c..ce0ef6d7e1 100644 --- a/src/blenderbim/blenderbim/tool/geometry.py +++ b/src/blenderbim/blenderbim/tool/geometry.py @@ -34,6 +34,10 @@ class Geometry(blenderbim.core.tool.Geometry): else: obj.data = data + @classmethod + def clear_cache(cls, element): + IfcStore.get_cache().remove(element.GlobalId) + @classmethod def clear_modifiers(cls, obj): for modifier in obj.modifiers: diff --git a/src/blenderbim/test/core/test_geometry.py b/src/blenderbim/test/core/test_geometry.py index a80991906e..7a5d122c64 100644 --- a/src/blenderbim/test/core/test_geometry.py +++ b/src/blenderbim/test/core/test_geometry.py @@ -24,6 +24,7 @@ from test.core.bootstrap import ifc, surveyor, geometry, style class TestEditObjectPlacement: def predict(self, ifc, geometry, surveyor): ifc.get_entity("obj").should_be_called().will_return("element") + geometry.clear_cache("element").should_be_called() geometry.clear_scale("obj").should_be_called() surveyor.get_absolute_matrix("obj").should_be_called().will_return("matrix") ifc.run("geometry.edit_object_placement", product="element", matrix="matrix").should_be_called() diff --git a/src/blenderbim/test/tool/test_geometry.py b/src/blenderbim/test/tool/test_geometry.py index d1caf5b85a..1328bdab01 100644 --- a/src/blenderbim/test/tool/test_geometry.py +++ b/src/blenderbim/test/tool/test_geometry.py @@ -53,6 +53,11 @@ class TestChangeObjectData(NewFile): assert obj2.data == data2 +class TestClearCache(NewFile): + def test_nothing(self): + pass # TODO I don't know how to test this + + class TestClearModifiers(NewFile): def test_run(self): obj = bpy.data.objects.new("Object", bpy.data.meshes.new("Mesh"))