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):
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()
+26
View File
@@ -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]
@@ -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
@@ -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)
@@ -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]))
@@ -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))
+1
View File
@@ -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
@@ -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:
@@ -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()
@@ -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"))