diff --git a/src/blenderbim/blenderbim/bim/export_ifc.py b/src/blenderbim/blenderbim/bim/export_ifc.py index d3cbdbda11..030ad57329 100644 --- a/src/blenderbim/blenderbim/bim/export_ifc.py +++ b/src/blenderbim/blenderbim/bim/export_ifc.py @@ -80,9 +80,9 @@ class IfcExporter: for guid, obj in IfcStore.guid_map.items(): try: self.sync_object_placement(obj) - except: - pass - self.sync_object_container(guid, obj) + self.sync_object_container(guid, obj) + except ReferenceError: + pass # The object is likely deleted if self.should_delete(obj): to_delete.append(guid) @@ -105,9 +105,10 @@ class IfcExporter: def sync_object_placement(self, obj): blender_matrix = np.matrix(obj.matrix_world) - ifc_matrix = ifcopenshell.util.placement.get_local_placement( - self.file.by_id(obj.BIMObjectProperties.ifc_definition_id).ObjectPlacement - ) + element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id) + if not hasattr(element, "ObjectPlacement"): + return + ifc_matrix = ifcopenshell.util.placement.get_local_placement(element.ObjectPlacement) ifc_matrix[0][3] *= self.unit_scale ifc_matrix[1][3] *= self.unit_scale ifc_matrix[2][3] *= self.unit_scale diff --git a/src/ifcopenshell-python/ifcopenshell/api/project/append_asset.py b/src/ifcopenshell-python/ifcopenshell/api/project/append_asset.py new file mode 100644 index 0000000000..a3409a0bf6 --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/project/append_asset.py @@ -0,0 +1,54 @@ +import ifcopenshell +import ifcopenshell.api + + +class Usecase: + def __init__(self, file, **settings): + self.file = file + self.settings = {"element": None} + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + element = self.file.add(self.settings["element"]) + self.existing_contexts = self.file.by_type("IfcGeometricRepresentationContext") + added_contexts = [e for e in self.file.traverse(element) if e.is_a("IfcGeometricRepresentationContext")] + for added_context in added_contexts: + equivalent_existing_context = self.get_equivalent_existing_context(added_context) + if not equivalent_existing_context: + equivalent_existing_context = self.create_equivalent_context(added_context) + for inverse in self.file.get_inverse(added_context): + ifcopenshell.util.element.replace_attribute(inverse, added_context, equivalent_existing_context) + for added_context in added_contexts: + if added_context.is_a() == "IfcGeometricRepresentationContext": + ifcopenshell.util.element.remove_deep(self.file, added_context) + return element + + def get_equivalent_existing_context(self, added_context): + for context in self.existing_contexts: + if context.is_a() != added_context.is_a(): + continue + if context.is_a("IfcGeometricRepresentationSubContext"): + if ( + context.ContextType == added_context.ContextType + and context.ContextIdentifier == added_context.ContextIdentifier + and context.TargetView == added_context.TargetView + ): + return context + elif ( + context.ContextType == added_context.ContextType + and context.ContextIdentifier == added_context.ContextIdentifier + ): + return context + + def create_equivalent_context(self, added_context): + if added_context.is_a("IfcGeometricRepresentationSubContext"): + return ifcopenshell.api.run( + "context.add_context", + context=added_context.ContextType, + subcontext=added_context.ContextIdentifier, + target_view=added_context.TargetView, + ) + return ifcopenshell.api.run( + "context.add_context", context=added_context.ContextType, subcontext=added_context.ContextIdentifier + )