diff --git a/src/ifcblenderexport/blenderbim/bim/__init__.py b/src/ifcblenderexport/blenderbim/bim/__init__.py index ede7d1d841..86c83ad22a 100644 --- a/src/ifcblenderexport/blenderbim/bim/__init__.py +++ b/src/ifcblenderexport/blenderbim/bim/__init__.py @@ -221,6 +221,9 @@ if bpy is not None: operator.RefreshDrawingList, operator.GetRepresentationIfcParameters, operator.UpdateIfcRepresentation, + operator.SetBlenderClashSetA, + operator.SetBlenderClashSetB, + operator.ExecuteBlenderClash, prop.StrProperty, prop.Attribute, prop.MaterialLayer, diff --git a/src/ifcblenderexport/blenderbim/bim/operator.py b/src/ifcblenderexport/blenderbim/bim/operator.py index dce8c7e224..0eaa53b7cb 100644 --- a/src/ifcblenderexport/blenderbim/bim/operator.py +++ b/src/ifcblenderexport/blenderbim/bim/operator.py @@ -4551,3 +4551,83 @@ class UpdateIfcRepresentation(bpy.types.Operator): ifc_importer.material_creator.mesh = mesh if ifc_importer.material_creator.parse_representation(element): ifc_importer.material_creator.assign_material_slots_to_faces(bpy.context.active_object) + + +class BlenderClasher(): + def process_clash_set(self): + import collision + a_cm = collision.CollisionManager() + b_cm = collision.CollisionManager() + self.add_to_cm(a_cm, bpy.context.scene.BIMProperties.blender_clash_set_a) + self.add_to_cm(b_cm, bpy.context.scene.BIMProperties.blender_clash_set_b) + results = a_cm.in_collision_other(b_cm, return_data=True) + if not results[0]: + print("No clashes") + return + for contact in results[1]: + if contact.raw.penetration_depth < 0.01: + continue + print("-----") + print(contact.names) + print(contact.raw.normal) + print(contact.raw.pos) + + def add_to_cm(self, cm, object_names): + import numpy as np + import ifcclash + for object_name in object_names: + name = object_name.name + obj = bpy.data.objects[name] + triangulated_mesh = self.triangulate_mesh(obj) + mat = np.array(obj.matrix_world) + mesh = ifcclash.Mesh() + mesh.vertices = np.array([tuple(v.co) for v in triangulated_mesh.vertices]) + mesh.faces = np.array([tuple(p.vertices) for p in triangulated_mesh.polygons]) + cm.add_object(name, mesh, mat) + + def triangulate_mesh(self, obj): + import bmesh + mesh = obj.evaluated_get(bpy.context.evaluated_depsgraph_get()).to_mesh() + bm = bmesh.new() + bm.from_mesh(mesh) + bmesh.ops.triangulate(bm, faces=bm.faces) + bm.to_mesh(mesh) + bm.free() + del bm + return mesh + + +class SetBlenderClashSetA(bpy.types.Operator): + bl_idname = "bim.set_blender_clash_set_a" + bl_label = "Set Blender Clash Set A" + + def execute(self, context): + while len(bpy.context.scene.BIMProperties.blender_clash_set_a) > 0: + bpy.context.scene.BIMProperties.blender_clash_set_a.remove(0) + for obj in bpy.context.selected_objects: + new = bpy.context.scene.BIMProperties.blender_clash_set_a.add() + new.name = obj.name + return {"FINISHED"} + + +class SetBlenderClashSetB(bpy.types.Operator): + bl_idname = "bim.set_blender_clash_set_b" + bl_label = "Set Blender Clash Set B" + + def execute(self, context): + while len(bpy.context.scene.BIMProperties.blender_clash_set_b) > 0: + bpy.context.scene.BIMProperties.blender_clash_set_b.remove(0) + for obj in bpy.context.selected_objects: + new = bpy.context.scene.BIMProperties.blender_clash_set_b.add() + new.name = obj.name + return {"FINISHED"} + + +class ExecuteBlenderClash(bpy.types.Operator): + bl_idname = "bim.execute_blender_clash" + bl_label = "Execute Blender Clash" + + def execute(self, context): + blender_clasher = BlenderClasher() + blender_clasher.process_clash_set() + return {"FINISHED"} diff --git a/src/ifcblenderexport/blenderbim/bim/prop.py b/src/ifcblenderexport/blenderbim/bim/prop.py index 577c4b9870..d9b0371e16 100644 --- a/src/ifcblenderexport/blenderbim/bim/prop.py +++ b/src/ifcblenderexport/blenderbim/bim/prop.py @@ -1514,6 +1514,8 @@ class BIMProperties(PropertyGroup): active_document_information_index: IntProperty(name="Active Document Information Index") document_references: CollectionProperty(name="Document References", type=DocumentReference) active_document_reference_index: IntProperty(name="Active Document Reference Index") + blender_clash_set_a: CollectionProperty(name="Blender Clash Set A", type=StrProperty) + blender_clash_set_b: CollectionProperty(name="Blender Clash Set B", type=StrProperty) clash_sets: CollectionProperty(name="Clash Sets", type=ClashSet) active_clash_set_index: IntProperty(name="Active Clash Set Index") constraints: CollectionProperty(name="Constraints", type=Constraint) diff --git a/src/ifcblenderexport/blenderbim/bim/ui.py b/src/ifcblenderexport/blenderbim/bim/ui.py index 53462c1546..e2dc5830c2 100644 --- a/src/ifcblenderexport/blenderbim/bim/ui.py +++ b/src/ifcblenderexport/blenderbim/bim/ui.py @@ -2130,6 +2130,17 @@ class BIM_PT_ifcclash(Panel): scene = context.scene props = scene.BIMProperties + layout.label(text="Blender Clash:") + + row = layout.row(align=True) + row.operator("bim.set_blender_clash_set_a") + row.operator("bim.set_blender_clash_set_b") + + row = layout.row(align=True) + row.operator("bim.execute_blender_clash") + + layout.label(text="IFC Clash:") + row = layout.row(align=True) row.operator("bim.add_clash_set") row.operator("bim.import_clash_sets", text="", icon="IMPORT")