Geometry caching is now enabled for model importing

This commit is contained in:
Dion Moult
2021-11-10 13:52:14 +11:00
parent c1c50f8868
commit 0992f43f11
10 changed files with 51 additions and 13 deletions
@@ -41,6 +41,7 @@ class IfcExporter:
def export(self): def export(self):
self.file = IfcStore.get_file() self.file = IfcStore.get_file()
self.set_header() self.set_header()
IfcStore.update_cache()
if bpy.context.scene.BIMProjectProperties.is_authoring: if bpy.context.scene.BIMProjectProperties.is_authoring:
self.sync_deletions() self.sync_deletions()
self.sync_object_placements() self.sync_object_placements()
+26
View File
@@ -19,6 +19,7 @@
import os import os
import bpy import bpy
import uuid import uuid
import hashlib
import zipfile import zipfile
import tempfile import tempfile
import ifcopenshell import ifcopenshell
@@ -30,6 +31,8 @@ class IfcStore:
path = "" path = ""
file = None file = None
schema = None schema = None
cache = None
cache_path = None
id_map = {} id_map = {}
guid_map = {} guid_map = {}
deleted_ids = set() deleted_ids = set()
@@ -50,6 +53,8 @@ class IfcStore:
IfcStore.path = "" IfcStore.path = ""
IfcStore.file = None IfcStore.file = None
IfcStore.schema = None IfcStore.schema = None
IfcStore.cache = None
IfcStore.cache_path = None
IfcStore.id_map = {} IfcStore.id_map = {}
IfcStore.guid_map = {} IfcStore.guid_map = {}
IfcStore.deleted_ids = set() IfcStore.deleted_ids = set()
@@ -72,6 +77,27 @@ class IfcStore:
pass pass
return IfcStore.file 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 @staticmethod
def load_file(path): def load_file(path):
extension = path.split(".")[-1] extension = path.split(".")[-1]
@@ -625,6 +625,7 @@ class IfcImporter:
) )
else: else:
iterator = ifcopenshell.geom.iterator(self.settings, self.file, include=products) iterator = ifcopenshell.geom.iterator(self.settings, self.file, include=products)
iterator.set_cache(IfcStore.get_cache())
valid_file = iterator.initialize() valid_file = iterator.initialize()
if not valid_file: if not valid_file:
return results return results
@@ -770,6 +771,7 @@ class IfcImporter:
) )
else: else:
iterator = ifcopenshell.geom.iterator(self.settings_2d, self.file, include=products) iterator = ifcopenshell.geom.iterator(self.settings_2d, self.file, include=products)
iterator.set_cache(IfcStore.get_cache())
valid_file = iterator.initialize() valid_file = iterator.initialize()
if not valid_file: if not valid_file:
return results return results
@@ -335,16 +335,12 @@ class CreateDrawing(bpy.types.Operator):
elements = set(ifc.by_type("IfcElement")) - set(ifc.by_type("IfcOpeningElement")) elements = set(ifc.by_type("IfcElement")) - set(ifc.by_type("IfcOpeningElement"))
self.setup_serialiser(ifc) self.setup_serialiser(ifc)
cache_settings = ifcopenshell.geom.settings( cache_settings = ifcopenshell.geom.settings(DISABLE_TRIANGULATION=True)
APPLY_DEFAULT_MATERIALS=True, DISABLE_TRIANGULATION=True, SEW_SHELLS=True cache = IfcStore.get_cache()
)
cache = ifcopenshell.geom.serializers.hdf5(ifc_cache_path, cache_settings)
[cache.remove(guid) for guid in invalidated_guids] [cache.remove(guid) for guid in invalidated_guids]
if target_view_contexts and elements: if target_view_contexts and elements:
geom_settings = ifcopenshell.geom.settings( geom_settings = ifcopenshell.geom.settings(DISABLE_TRIANGULATION=True, INCLUDE_CURVES=True)
APPLY_DEFAULT_MATERIALS=True, DISABLE_TRIANGULATION=True, SEW_SHELLS=True, INCLUDE_CURVES=True
)
geom_settings.set_context_ids(target_view_contexts) geom_settings.set_context_ids(target_view_contexts)
it = ifcopenshell.geom.iterator(geom_settings, ifc, multiprocessing.cpu_count(), include=elements) it = ifcopenshell.geom.iterator(geom_settings, ifc, multiprocessing.cpu_count(), include=elements)
it.set_cache(cache) it.set_cache(cache)
@@ -356,7 +352,7 @@ class CreateDrawing(bpy.types.Operator):
if body_contexts and elements: if body_contexts and elements:
geom_settings = ifcopenshell.geom.settings( 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) geom_settings.set_context_ids(body_contexts)
it = ifcopenshell.geom.iterator(geom_settings, ifc, multiprocessing.cpu_count(), include=elements) 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) self.serialiser.write(elem)
geom_settings = ifcopenshell.geom.settings( 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]) it = ifcopenshell.geom.iterator(geom_settings, ifc, include=[self.camera_element])
for elem in self.yield_from_iterator(it): for elem in self.yield_from_iterator(it):
@@ -383,9 +379,7 @@ class CreateDrawing(bpy.types.Operator):
return svg_path return svg_path
def setup_serialiser(self, ifc): def setup_serialiser(self, ifc):
self.svg_settings = ifcopenshell.geom.settings( self.svg_settings = ifcopenshell.geom.settings(DISABLE_TRIANGULATION=True, INCLUDE_CURVES=True)
APPLY_DEFAULT_MATERIALS=True, DISABLE_TRIANGULATION=True, INCLUDE_CURVES=True
)
self.svg_buffer = ifcopenshell.geom.serializers.buffer() self.svg_buffer = ifcopenshell.geom.serializers.buffer()
self.serialiser = ifcopenshell.geom.serializers.svg(self.svg_buffer, self.svg_settings) self.serialiser = ifcopenshell.geom.serializers.svg(self.svg_buffer, self.svg_settings)
self.serialiser.setFile(ifc) self.serialiser.setFile(ifc)
@@ -45,10 +45,13 @@ class AuthoringData:
@classmethod @classmethod
def relating_types(cls): def relating_types(cls):
if not cls.ifc_classes(): ifc_classes = cls.ifc_classes()
if not ifc_classes:
return [] return []
results = [] results = []
ifc_class = bpy.context.scene.BIMModelProperties.ifc_class ifc_class = bpy.context.scene.BIMModelProperties.ifc_class
if not ifc_class and ifc_classes:
ifc_class = ifc_classes[0][0]
if ifc_class: if ifc_class:
elements = [(str(e.id()), e.Name, "") for e in tool.Ifc.get().by_type(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])) results.extend(sorted(elements, key=lambda s: s[1]))
@@ -22,6 +22,7 @@ import blenderbim.core.style
def edit_object_placement(ifc, geometry, surveyor, obj=None): def edit_object_placement(ifc, geometry, surveyor, obj=None):
element = ifc.get_entity(obj) element = ifc.get_entity(obj)
if element: if element:
geometry.clear_cache(element)
geometry.clear_scale(obj) geometry.clear_scale(obj)
ifc.run("geometry.edit_object_placement", product=element, matrix=surveyor.get_absolute_matrix(obj)) ifc.run("geometry.edit_object_placement", product=element, matrix=surveyor.get_absolute_matrix(obj))
+1
View File
@@ -73,6 +73,7 @@ class Context:
@interface @interface
class Geometry: class Geometry:
def change_object_data(cls, obj, data, is_global=False): pass 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_modifiers(cls, obj): pass
def clear_scale(cls, obj): pass def clear_scale(cls, obj): pass
def create_dynamic_voids(cls, obj): pass def create_dynamic_voids(cls, obj): pass
@@ -34,6 +34,10 @@ class Geometry(blenderbim.core.tool.Geometry):
else: else:
obj.data = data obj.data = data
@classmethod
def clear_cache(cls, element):
IfcStore.get_cache().remove(element.GlobalId)
@classmethod @classmethod
def clear_modifiers(cls, obj): def clear_modifiers(cls, obj):
for modifier in obj.modifiers: for modifier in obj.modifiers:
@@ -24,6 +24,7 @@ from test.core.bootstrap import ifc, surveyor, geometry, style
class TestEditObjectPlacement: class TestEditObjectPlacement:
def predict(self, ifc, geometry, surveyor): def predict(self, ifc, geometry, surveyor):
ifc.get_entity("obj").should_be_called().will_return("element") ifc.get_entity("obj").should_be_called().will_return("element")
geometry.clear_cache("element").should_be_called()
geometry.clear_scale("obj").should_be_called() geometry.clear_scale("obj").should_be_called()
surveyor.get_absolute_matrix("obj").should_be_called().will_return("matrix") surveyor.get_absolute_matrix("obj").should_be_called().will_return("matrix")
ifc.run("geometry.edit_object_placement", product="element", matrix="matrix").should_be_called() ifc.run("geometry.edit_object_placement", product="element", matrix="matrix").should_be_called()
@@ -53,6 +53,11 @@ class TestChangeObjectData(NewFile):
assert obj2.data == data2 assert obj2.data == data2
class TestClearCache(NewFile):
def test_nothing(self):
pass # TODO I don't know how to test this
class TestClearModifiers(NewFile): class TestClearModifiers(NewFile):
def test_run(self): def test_run(self):
obj = bpy.data.objects.new("Object", bpy.data.meshes.new("Mesh")) obj = bpy.data.objects.new("Object", bpy.data.meshes.new("Mesh"))