@Moult wrote the following to help me resync a blender/ifc file.
He mentioned making this integral to BB, but in the meantime wanted to paste it here for others, and save for the future, if necessary.
import bpy
import logging
import ifcopenshell
import blenderbim.tool as tool
import blenderbim.bim.handler
import blenderbim.bim.import_ifc as import_ifc
from blenderbim.bim.ifc import IfcStore
def execute():
f = tool.Ifc.get()
project_collections = set()
queue = []
project_collection = bpy.data.collections.get('IfcProject/My Project')
if project_collection:
queue.append(project_collection)
while queue:
collection = queue.pop()
project_collections.add(collection)
queue.extend(collection.children)
print(project_collections)
for obj in bpy.data.objects:
ifc_id = obj.BIMObjectProperties.ifc_definition_id
if ifc_id:
try:
element = f.by_id(ifc_id)
except:
print("Object not validly linked to anything", obj)
bpy.data.objects.remove(obj)
continue
ifc_class = obj.name.split("/")[0]
if not element.is_a(ifc_class):
print("Object linked to different class", obj, element)
bpy.data.objects.remove(obj)
elif element.is_a("IfcAnnotation"):
bpy.data.objects.remove(obj) # Annotations are lazy loaded
elif not element.is_a("IfcContext") and not element.is_a("IfcProduct") and not element.is_a("IfcTypeProduct"):
print("Object linked to strange element", obj, element)
bpy.data.objects.remove(obj)
else:
for collection in obj.users_collection:
if collection in project_collections:
print('uhoh', obj, collection) # Deal with this situation if it turns up
# return
for collection in bpy.data.collections:
if "Ifc" in collection.name or collection in project_collections:
bpy.data.collections.remove(collection)
project = tool.Ifc.get().by_type("IfcProject")[0]
project_obj = tool.Ifc.get_object(project)
bpy.data.objects.remove(project_obj)
logger = logging.getLogger("ImportIFC")
ifc_import_settings = import_ifc.IfcImportSettings.factory(bpy.context, tool.Ifc.get_path(), logger)
ifc_importer = import_ifc.IfcImporter(ifc_import_settings)
ifc_importer.file = tool.Ifc.get()
ifc_importer.spatial_elements = set(tool.Ifc.get().by_type("IfcSpatialElement"))
ifc_importer.create_project()
ifc_importer.process_context_filter()
ifc_importer.create_collections()
materials = {}
existing_styles = {}
for material in bpy.data.materials:
ifc_id = material.BIMObjectProperties.ifc_definition_id
if ifc_id:
materials[ifc_id] = material
ifc_id = material.BIMMaterialProperties.ifc_style_id
if ifc_id:
existing_styles[ifc_id] = material
ifc_importer.material_creator.materials = materials
ifc_importer.material_creator.styles = existing_styles
for material in tool.Ifc.get().by_type("IfcMaterial"):
if material.id() not in materials:
print("Material not in blend", material)
ifc_importer.create_material(material)
# create styles
parsed_styles = set()
for material_definition_representation in tool.Ifc.get().by_type("IfcMaterialDefinitionRepresentation"):
material = material_definition_representation.RepresentedMaterial
blender_material = ifc_importer.material_creator.materials[material.id()]
for representation in material_definition_representation.Representations:
styles = []
for styled_item in representation.Items:
styles.extend(styled_item.Styles)
while styles:
style = styles.pop()
if style.is_a("IfcSurfaceStyle"):
if style.id() not in existing_styles:
print("Material style not in blend", style, blender_material)
ifc_importer.create_style(style, blender_material)
parsed_styles.add(style.id())
elif style.is_a("IfcPresentationStyleAssignment"):
styles.extend(style.Styles)
for style in tool.Ifc.get().by_type("IfcSurfaceStyle"):
if style.id() in parsed_styles:
continue
if style.id() not in existing_styles:
print("Style not in blend", style)
ifc_importer.create_style(style)
# Done
elements = tool.Ifc.get().by_type("IfcElement")
missing_elements = set()
missing_elements2 = set()
for element in elements:
if element.is_a("IfcOpeningElement"):
continue
obj = tool.Ifc.get_object(element)
if not obj:
print("Object does not exist", element)
missing_elements.add(element)
missing_elements2.add(element)
ifc_importer.create_generic_elements(missing_elements)
for missing_element in missing_elements2:
print("Created missing element", tool.Ifc.get_object(missing_element))
element_types = tool.Ifc.get().by_type("IfcTypeProduct")
for element in element_types:
obj = tool.Ifc.get_object(element)
if not obj:
print("Object does not exist", element)
blenderbim.bim.handler.loadIfcStore(bpy.context.scene)
ifc_importer.added_data = IfcStore.id_map
ifc_importer.place_objects_in_collections()
project_obj = tool.Ifc.get_object(project)
bpy.context.scene.collection.children.link(project_obj.BIMObjectProperties.collection)
for mat in bpy.data.materials:
if mat.BIMObjectProperties.ifc_definition_id or mat.BIMMaterialProperties.ifc_style_id:
mat.use_fake_user = True
execute()