From bf134eb0f4f9a80eace8422bd6fb9492255601f5 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Mon, 8 Nov 2021 21:00:10 +1100 Subject: [PATCH] Implement cache updating for drawings. See #1153. --- src/blenderbim/blenderbim/bim/export_ifc.py | 16 ++++++++++++- .../blenderbim/bim/module/drawing/operator.py | 23 +++++++++++++++---- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/export_ifc.py b/src/blenderbim/blenderbim/bim/export_ifc.py index 75051f7564..3d0500bd8f 100644 --- a/src/blenderbim/blenderbim/bim/export_ifc.py +++ b/src/blenderbim/blenderbim/bim/export_ifc.py @@ -85,25 +85,34 @@ class IfcExporter: ) def sync_deletions(self): + results = [] for ifc_definition_id in IfcStore.deleted_ids: try: product = self.file.by_id(ifc_definition_id) + if hasattr(product, "GlobalId"): + results.append(product.GlobalId) except: continue ifcopenshell.api.run("root.remove_product", self.file, **{"product": product}) + return results def sync_object_placements(self): + results = [] self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(self.file) for ifc_definition_id, obj in IfcStore.id_map.items(): try: if isinstance(obj, bpy.types.Material): continue tool.Collector.sync(obj) - self.sync_object_placement(obj) + result = self.sync_object_placement(obj) + if result: + results.append(result) except ReferenceError: pass # The object is likely deleted + return results def sync_edited_objects(self): + results = [] for obj in IfcStore.edited_objs.copy(): if not obj: continue @@ -111,10 +120,14 @@ class IfcExporter: if isinstance(obj, bpy.types.Material): blenderbim.core.style.update_style_colours(tool.Ifc, tool.Style, obj=obj) else: + element = tool.Ifc.get_entity(obj) + if element: + results.append(element) bpy.ops.bim.update_representation(obj=obj.name) except ReferenceError: pass # The object is likely deleted IfcStore.edited_objs.clear() + return results def sync_object_placement(self, obj): blender_matrix = np.array(obj.matrix_world) @@ -140,6 +153,7 @@ class IfcExporter: ) if not np.allclose(ifc_matrix, blender_matrix, atol=0.0001): blenderbim.core.geometry.edit_object_placement(tool.Ifc, tool.Surveyor, obj=obj) + return element def sync_grid_axis_object_placement(self, obj, element): grid = (element.PartOfU or element.PartOfV or element.PartOfW)[0] diff --git a/src/blenderbim/blenderbim/bim/module/drawing/operator.py b/src/blenderbim/blenderbim/bim/module/drawing/operator.py index 7e62b6a31f..5884ef54ba 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/operator.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/operator.py @@ -37,6 +37,7 @@ import blenderbim.bim.module.drawing.annotation as annotation import blenderbim.bim.module.drawing.sheeter as sheeter import blenderbim.bim.module.drawing.scheduler as scheduler import blenderbim.bim.module.drawing.helper as helper +import blenderbim.bim.export_ifc from lxml import etree from mathutils import Vector, Matrix, Euler, geometry from blenderbim.bim.module.drawing.prop import RasterStyleProperty @@ -281,6 +282,14 @@ class CreateDrawing(bpy.types.Operator): if os.path.isfile(svg_path) and self.props.should_use_linework_cache: return svg_path + # All very hackish whilst prototyping + exporter = blenderbim.bim.export_ifc.IfcExporter(None) + exporter.file = tool.Ifc.get() + invalidated_guids = exporter.sync_deletions() + invalidated_elements = exporter.sync_object_placements() + invalidated_elements += exporter.sync_edited_objects() + [invalidated_guids.append(e.GlobalId) for e in invalidated_elements if hasattr(e, "GlobalId")] + # If we have already calculated it in the SVG in the past, don't recalculate edited_guids = set() for obj in IfcStore.edited_objs: @@ -324,15 +333,15 @@ class CreateDrawing(bpy.types.Operator): continue elements = set(ifc.by_type("IfcElement")) - set(ifc.by_type("IfcOpeningElement")) - # elements = set([tool.Ifc.get_entity(o) for o in bpy.context.visible_objects if tool.Ifc.get_entity(o).is_a("IfcProduct")]) 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.remove(guid) for guid in invalidated_guids] - if target_view_contexts: + if target_view_contexts and elements: geom_settings = ifcopenshell.geom.settings( APPLY_DEFAULT_MATERIALS=True, DISABLE_TRIANGULATION=True, SEW_SHELLS=True, INCLUDE_CURVES=True ) @@ -341,11 +350,11 @@ class CreateDrawing(bpy.types.Operator): it.set_cache(cache) processed = set() for elem in self.yield_from_iterator(it): - processed.add(ifc.by_guid(elem.guid)) + processed.add(ifc.by_id(elem.id)) self.serialiser.write(elem) elements -= processed - if body_contexts: + if body_contexts and elements: geom_settings = ifcopenshell.geom.settings( APPLY_DEFAULT_MATERIALS=True, DISABLE_TRIANGULATION=True, SEW_SHELLS=True ) @@ -409,7 +418,11 @@ class CreateDrawing(bpy.types.Operator): ifc = tool.Ifc.get() for el in root.findall(".//{http://www.w3.org/2000/svg}g[@{http://www.ifcopenshell.org/ns}guid]"): classes = ["cut"] - element = ifc.by_guid(el.get("{http://www.ifcopenshell.org/ns}guid")) + try: + element = ifc.by_guid(el.get("{http://www.ifcopenshell.org/ns}guid")) + except: + # See #1861 - freshly created guids cannot be extracted unfortunately + continue material = ifcopenshell.util.element.get_material(element, should_skip_usage=True) if material: if material.is_a("IfcMaterialLayerSet"):